diff --git a/src/api/health/activity.js b/src/api/health/activity.js
index 00ea5cf..1839f10 100644
--- a/src/api/health/activity.js
+++ b/src/api/health/activity.js
@@ -1,4 +1,14 @@
import request from '@/utils/request'
+import upload from '@/utils/upload'
+
+// 通用文件上传(RuoYi-Cloud 文件接口)
+export function uploadFile(data) {
+ return upload({
+ url: '/file/upload',
+ name: data.name || 'file',
+ filePath: data.filePath
+ })
+}
// 查询活动记录列表
export function listActivity(query) {
diff --git a/src/api/health/doctorRecord.js b/src/api/health/doctorRecord.js
index 055d389..618da5a 100644
--- a/src/api/health/doctorRecord.js
+++ b/src/api/health/doctorRecord.js
@@ -1,4 +1,14 @@
import request from '@/utils/request'
+import upload from '@/utils/upload'
+
+// 通用文件上传(RuoYi-Cloud 文件接口)
+export function uploadFile(data) {
+ return upload({
+ url: '/file/upload',
+ name: data.name || 'file',
+ filePath: data.filePath
+ })
+}
// 查询就医记录列表
export function listDoctorRecord(query) {
diff --git a/src/api/health/medicineBasic.js b/src/api/health/medicineBasic.js
index 0e13201..b8a9da2 100644
--- a/src/api/health/medicineBasic.js
+++ b/src/api/health/medicineBasic.js
@@ -1,4 +1,14 @@
import request from '@/utils/request'
+import upload from '@/utils/upload'
+
+// 通用文件上传(RuoYi-Cloud 文件接口)
+export function uploadFile(data) {
+ return upload({
+ url: '/file/upload',
+ name: data.name || 'file',
+ filePath: data.filePath
+ })
+}
// 查询药品基础信息列表
export function listMedicineBasic(query) {
diff --git a/src/pages.json b/src/pages.json
index 62209f1..f8af2d7 100644
--- a/src/pages.json
+++ b/src/pages.json
@@ -36,6 +36,18 @@
"navigationBarTitleText": "浏览文本"
}
},
+ {
+ "path": "pages/common/agreement/index",
+ "style": {
+ "navigationBarTitleText": "用户服务协议"
+ }
+ },
+ {
+ "path": "pages/common/privacy/index",
+ "style": {
+ "navigationBarTitleText": "隐私协议"
+ }
+ },
{
"path": "pages/health/homepage/index",
"style": {
diff --git a/src/pages/health/activity/addEdit.vue b/src/pages/health/activity/addEdit.vue
index 60232fb..36f4f8a 100644
--- a/src/pages/health/activity/addEdit.vue
+++ b/src/pages/health/activity/addEdit.vue
@@ -74,6 +74,23 @@
+
+
+
+
+
+
+
+
+
+
+
+ 上传图片
+
+
+ 最多上传9张图片,支持 jpg/png/jpeg 等格式
+
+
@@ -105,8 +122,9 @@
-
diff --git a/src/pages/health/activity/list.vue b/src/pages/health/activity/list.vue
index cfe1b84..a59d52a 100644
--- a/src/pages/health/activity/list.vue
+++ b/src/pages/health/activity/list.vue
@@ -84,6 +84,19 @@
备注
{{ item.remark }}
+
+ 附件
+
+
+
+
@@ -180,6 +193,7 @@ import { getDicts } from '@/api/system/dict/data.js'
import { timeHandler } from '@/utils/common.ts'
import {onLoad,onShow} from "@dcloudio/uni-app";
import dayjs from 'dayjs'
+import config from '@/config'
// 计算属性与监听属性是在vue中而非uniap中 需要注意!!!
import {reactive ,toRefs,ref,computed }from "vue";
const pageNum = ref(1)
@@ -409,6 +423,23 @@ function getList() {
}
});
}
+
+function parseAttachment(attachment) {
+ if (!attachment) return []
+ // 附件是后端静态资源直链,需要用域名拼接,不能带网关前缀 prod-api
+ const origin = config.baseUrl.replace(/^(https?:\/\/[^/]+).*$/, '$1')
+ return attachment.split(',').filter(url => url).map(url => {
+ if (url.startsWith('http')) return url
+ return origin + url
+ })
+}
+
+function previewAttachment(urls, index) {
+ uni.previewImage({
+ urls: urls,
+ current: urls[index]
+ })
+}
@@ -489,6 +520,27 @@ function getList() {
border: 1rpx solid rgba(19, 194, 194, 0.3);
}
+.attachment-list {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 12rpx;
+ margin-top: 4rpx;
+ width: 100%;
+
+ .attachment-thumb {
+ width: 120rpx;
+ height: 120rpx;
+ border-radius: 8rpx;
+ background: #f5f7fa;
+ box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.08);
+ transition: transform 0.2s ease;
+
+ &:active {
+ transform: scale(0.95);
+ }
+ }
+}
+
// ==================== 费用汇总面板 ====================
.summary-mask {
position: fixed;
diff --git a/src/pages/health/doctorRecord/addEdit.vue b/src/pages/health/doctorRecord/addEdit.vue
index ff24b0c..66b80b6 100644
--- a/src/pages/health/doctorRecord/addEdit.vue
+++ b/src/pages/health/doctorRecord/addEdit.vue
@@ -70,6 +70,23 @@
+
+
+
+
+
+
+
+
+
+
+
+ 上传图片
+
+
+ 最多上传9张图片,支持 jpg/png/jpeg 等格式
+
+
@@ -95,7 +112,8 @@
@@ -479,4 +655,4 @@ page {
border: 2rpx solid #f56c6c !important;
background: #fef0f0 !important;
}
-
\ No newline at end of file
+
diff --git a/src/pages/health/doctorRecord/costAddEdit.vue b/src/pages/health/doctorRecord/costAddEdit.vue
index 1070989..34679fe 100644
--- a/src/pages/health/doctorRecord/costAddEdit.vue
+++ b/src/pages/health/doctorRecord/costAddEdit.vue
@@ -287,6 +287,10 @@ function getData() {
form.value.typeName = dictStr(form.value.type, costTypeList.value)
form.value.unitName = dictStr(form.value.unit, packageUnitList.value)
form.value.checkTypeName = dictStr(form.value.checkType, checkTypeList.value) || dictStr(form.value.checkType, nursingTypeList.value)
+ // 后端返回的单价/数量/总价为数字类型,校验器按 string 校验会误判为空,这里统一转为字符串
+ form.value.price = form.value.price != null ? String(form.value.price) : form.value.price
+ form.value.count = form.value.count != null ? String(form.value.count) : form.value.count
+ form.value.totalCost = form.value.totalCost != null ? String(form.value.totalCost) : form.value.totalCost
applyTypeState(form.value.type)
if (flag.value != null) {
form.value.id = null
diff --git a/src/pages/health/doctorRecord/list.vue b/src/pages/health/doctorRecord/list.vue
index c9e6ded..2fbf840 100644
--- a/src/pages/health/doctorRecord/list.vue
+++ b/src/pages/health/doctorRecord/list.vue
@@ -168,6 +168,19 @@
备注
{{ item.remark }}
+
+ 附件
+
+
+
+
@@ -213,6 +226,7 @@ import { getDicts } from '@/api/system/dict/data.js'
import { timeHandler } from '@/utils/common.ts'
import {onLoad,onShow} from "@dcloudio/uni-app";
import dayjs from 'dayjs'
+import config from '@/config'
// 计算属性与监听属性是在vue中而非uniap中 需要注意!!!
import {reactive ,toRefs,ref,computed }from "vue";
const pageNum = ref(1)
@@ -467,6 +481,25 @@ function settingCancel() {
}
});
}
+
+// 解析附件字段为URL数组
+function parseAttachment(attachment) {
+ if (!attachment) return []
+ // 附件是后端静态资源直链,需要用域名拼接,不能带网关前缀 prod-api
+ const origin = config.baseUrl.replace(/^(https?:\/\/[^/]+).*$/, '$1')
+ return attachment.split(',').filter(url => url).map(url => {
+ if (url.startsWith('http')) return url
+ return origin + url
+ })
+}
+
+// 预览附件图片
+function previewAttachment(urls, index) {
+ uni.previewImage({
+ urls: urls,
+ current: urls[index]
+ })
+}
diff --git a/src/pages/health/medicineBasic/addEdit.vue b/src/pages/health/medicineBasic/addEdit.vue
index b80152d..7f81b5a 100644
--- a/src/pages/health/medicineBasic/addEdit.vue
+++ b/src/pages/health/medicineBasic/addEdit.vue
@@ -129,6 +129,23 @@
+
+
+
+
+
+
+
+
+
+
+
+ 上传图片
+
+
+ 最多上传9张图片,支持 jpg/png/jpeg 等格式
+
+
@@ -158,7 +175,8 @@
diff --git a/src/pages/health/medicineBasic/list.vue b/src/pages/health/medicineBasic/list.vue
index 8fa3e37..cee1521 100644
--- a/src/pages/health/medicineBasic/list.vue
+++ b/src/pages/health/medicineBasic/list.vue
@@ -130,6 +130,19 @@
录入时间
{{ item.createTime || '--' }}
+
+ 附件
+
+
+
+
@@ -166,6 +179,7 @@ import { getDicts } from '@/api/system/dict/data.js'
import { timeHandler } from '@/utils/common.ts'
import {onLoad,onShow} from "@dcloudio/uni-app";
import auth from "@/plugins/auth"; // 建议使用auth进行鉴权操作
+import config from '@/config'
import dayjs from 'dayjs'
// 计算属性与监听属性是在vue中而非uniap中 需要注意!!!
import {reactive ,toRefs,ref,computed }from "vue";
@@ -358,7 +372,25 @@ function settingCancel() {
}
});
}
-
+
+// 解析附件字段为URL数组
+function parseAttachment(attachment) {
+ if (!attachment) return []
+ // 附件是后端静态资源直链,需要用域名拼接,不能带网关前缀 prod-api
+ const origin = config.baseUrl.replace(/^(https?:\/\/[^/]+).*$/, '$1')
+ return attachment.split(',').filter(url => url).map(url => {
+ if (url.startsWith('http')) return url
+ return origin + url
+ })
+}
+
+// 预览附件图片
+function previewAttachment(urls, index) {
+ uni.previewImage({
+ urls: urls,
+ current: urls[index]
+ })
+}
\ No newline at end of file
diff --git a/src/pages/login.vue b/src/pages/login.vue
index 3828f3c..a1bf15c 100644
--- a/src/pages/login.vue
+++ b/src/pages/login.vue
@@ -38,16 +38,26 @@
/>
-
+
-
-
-
+
+
+
+
+
+
+ 记住密码
+
+
+
+
+
+
+ 已阅读并同意
+ 《用户协议》
+ 和
+ 《隐私协议》
- 已阅读并同意
- 《用户协议》
- 和
- 《隐私协议》
@@ -77,12 +87,23 @@ import { getWxCode } from '@/utils/geek';
import { wxLogin } from '@/api/oauth';
import { setToken } from '@/utils/auth';
import { encrypt, decrypt } from '@/utils/jsencrypt'
+
+// ========== 平台判断(条件编译)==========
+// H5 端为 true,其他端为 false。条件编译保证仅 H5 打包对应逻辑
+let isH5 = false
+// #ifdef H5
+isH5 = true
+// #endif
+
+const REMEMBER_KEY = 'remember_login_info'
+
const userStore = useUserStore()
const codeUrl = ref("");
const captchaEnabled = ref(true); // 是否开启验证码
const useWxLogin = ref(false); // 是否使用微信登录
const globalConfig = ref(config);
-const agree = ref(false); // 同意协议
+const agree = ref(isH5 ? true : false); // H5 端默认勾选同意协议
+const rememberPwd = ref(false); // 记住密码
const loginForm = ref({
username: "",
password: "",
@@ -103,8 +124,49 @@ if (useWxLogin.value) {
}
// 页面加载时检查是否记住了密码
onMounted(() => {
+ loadRememberedLogin()
});
+// 读取本地记住的登录信息(仅 H5)
+function loadRememberedLogin() {
+ if (!isH5) return
+ try {
+ const raw = uni.getStorageSync(REMEMBER_KEY)
+ if (!raw) return
+ const info = JSON.parse(raw)
+ if (info && info.username) {
+ loginForm.value.username = info.username
+ // 密码以 base64 存储,解码后回填
+ if (info.password) {
+ try {
+ loginForm.value.password = decodeURIComponent(escape(atob(info.password)))
+ } catch (e) {
+ loginForm.value.password = ''
+ }
+ }
+ rememberPwd.value = true
+ }
+ } catch (e) {
+ console.error('读取记住的登录信息失败', e)
+ uni.removeStorageSync(REMEMBER_KEY)
+ }
+}
+
+// 保存或清除记住的登录信息(仅 H5)
+function saveRememberedLogin() {
+ if (!isH5) return
+ if (rememberPwd.value && loginForm.value.username) {
+ const info = {
+ username: loginForm.value.username,
+ // 密码使用 base64 简单编码,避免明文存储
+ password: btoa(unescape(encodeURIComponent(loginForm.value.password || '')))
+ }
+ uni.setStorageSync(REMEMBER_KEY, JSON.stringify(info))
+ } else {
+ uni.removeStorageSync(REMEMBER_KEY)
+ }
+}
+
// 获取图形验证码
function getCode() {
getCodeImg().then(res => {
@@ -137,6 +199,8 @@ async function handleLogin() {
async function pwdLogin() {
userStore.login(loginForm.value).then(() => {
modal.closeLoading()
+ // 登录成功后保存或清除记住的密码
+ saveRememberedLogin()
loginSuccess()
}).catch(() => {
if (captchaEnabled.value) {
@@ -158,6 +222,11 @@ function agreeChange(){
agree.value = !agree.value;
}
+// 切换记住密码状态
+function rememberChange(){
+ rememberPwd.value = !rememberPwd.value;
+}
+
// 隐私协议
function handlePrivacy() {
uni.navigateTo({
@@ -266,12 +335,29 @@ page {
margin-top: 24rpx;
padding: 0 4rpx;
+ .agreement-line {
+ display: flex;
+ align-items: flex-start;
+ flex-wrap: wrap;
+ line-height: 1.6;
+ }
+
.agreement-row {
display: flex;
align-items: center;
flex-wrap: wrap;
line-height: 1.6;
+ &.remember-part {
+ margin-right: 32rpx;
+ flex-shrink: 0;
+ }
+
+ &.agree-part {
+ flex: 1;
+ min-width: 0;
+ }
+
.checkbox-small {
width: 28rpx;
height: 28rpx;