From 6dc9aaba6c4dbcda3943d4cf715813855c4c3253 Mon Sep 17 00:00:00 2001 From: chenqi Date: Fri, 19 Jun 2026 22:04:41 +0800 Subject: [PATCH] =?UTF-8?q?feat(mobile):=20=E9=87=8D=E6=9E=84=E7=A7=BB?= =?UTF-8?q?=E5=8A=A8=E7=AB=AF=E6=8A=A4=E5=A3=AB=E5=B7=A5=E4=BD=9C=E7=AB=99?= =?UTF-8?q?=20-=20=E5=AE=8C=E6=95=B4=E5=8A=9F=E8=83=BD=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- healthlink-his-mobile/.env.development | 11 ++ healthlink-his-mobile/.env.production | 8 ++ healthlink-his-mobile/package.json | 7 +- healthlink-his-mobile/src/api/index.js | 48 ++++---- healthlink-his-mobile/src/main.js | 3 +- healthlink-his-mobile/src/router/index.js | 16 +-- .../src/views/AssessmentForm.vue | 49 +++----- healthlink-his-mobile/src/views/Home.vue | 89 ++++++++++++++ healthlink-his-mobile/src/views/Login.vue | 47 ++------ healthlink-his-mobile/src/views/Mine.vue | 35 +++--- .../src/views/MobileLayout.vue | 15 ++- .../src/views/PatientDetail.vue | 114 +++++++----------- .../src/views/PatientList.vue | 68 +++++------ healthlink-his-mobile/src/views/TaskList.vue | 88 +++++--------- .../src/views/VitalSignEntry.vue | 64 +++++----- healthlink-his-mobile/vite.config.js | 50 +++++--- 16 files changed, 366 insertions(+), 346 deletions(-) create mode 100644 healthlink-his-mobile/.env.development create mode 100644 healthlink-his-mobile/.env.production create mode 100644 healthlink-his-mobile/src/views/Home.vue diff --git a/healthlink-his-mobile/.env.development b/healthlink-his-mobile/.env.development new file mode 100644 index 000000000..390ebe68b --- /dev/null +++ b/healthlink-his-mobile/.env.development @@ -0,0 +1,11 @@ +# 页面标题 +VITE_APP_TITLE = HealthLink移动护理 + +# 开发环境配置 +VITE_APP_ENV = 'development' + +# API地址 +VITE_APP_BASE_API = '/dev-api' + +# 后端代理地址 +VITE_API_PROXY = 'http://localhost:18080/healthlink-his' diff --git a/healthlink-his-mobile/.env.production b/healthlink-his-mobile/.env.production new file mode 100644 index 000000000..8196ebc02 --- /dev/null +++ b/healthlink-his-mobile/.env.production @@ -0,0 +1,8 @@ +# 页面标题 +VITE_APP_TITLE = HealthLink移动护理 + +# 生产环境配置 +VITE_APP_ENV = 'production' + +# API地址 +VITE_APP_BASE_API = '/dev-api' diff --git a/healthlink-his-mobile/package.json b/healthlink-his-mobile/package.json index 207255bf4..59f85826b 100644 --- a/healthlink-his-mobile/package.json +++ b/healthlink-his-mobile/package.json @@ -1,6 +1,7 @@ { "name": "healthlink-his-mobile", "version": "1.0.0", + "type": "module", "description": "HealthLink-HIS 移动护理H5工作站", "scripts": { "dev": "vite", @@ -12,11 +13,13 @@ "dependencies": { "vue": "^3.4.0", "vue-router": "^4.3.0", + "pinia": "^2.1.0", "axios": "^1.7.0", "element-plus": "^2.7.0", - "vxe-table": "^4.7.0", "echarts": "^5.5.0", - "pinia": "^2.1.0" + "js-cookie": "^3.0.5", + "nprogress": "^0.2.0", + "path-to-regexp": "^6.2.0" }, "devDependencies": { "@vitejs/plugin-vue": "^5.0.0", diff --git a/healthlink-his-mobile/src/api/index.js b/healthlink-his-mobile/src/api/index.js index 30065b7b6..0e65ca99d 100644 --- a/healthlink-his-mobile/src/api/index.js +++ b/healthlink-his-mobile/src/api/index.js @@ -1,12 +1,12 @@ import axios from 'axios' import { ElMessage } from 'element-plus' -const request = axios.create({ - baseURL: '/dev-api', - timeout: 10000 +const service = axios.create({ + baseURL: import.meta.env.VITE_APP_BASE_API || '/dev-api', + timeout: 30000 }) -request.interceptors.request.use(config => { +service.interceptors.request.use(config => { const token = localStorage.getItem('Admin-Token') if (token && !(config.headers && config.headers.isToken === false)) { config.headers.Authorization = 'Bearer ' + token @@ -14,39 +14,41 @@ request.interceptors.request.use(config => { return config }) -request.interceptors.response.use( - res => { - if (res.data?.code === 401) { +service.interceptors.response.use( + response => { + const res = response.data + if (res.code === 401) { localStorage.removeItem('Admin-Token') window.location.href = '/login' return Promise.reject(new Error('登录已过期')) } - return res.data + return res }, - err => { - if (err.response?.status === 401) { + error => { + if (error.response?.status === 401) { localStorage.removeItem('Admin-Token') window.location.href = '/login' } - return Promise.reject(err) + ElMessage.error(error.response?.data?.msg || '请求失败') + return Promise.reject(error) } ) export const authApi = { - login: (data) => request.post('/login', data, { headers: { isToken: false } }), - getTenants: (username) => request.get('/system/tenant/user-bind/' + username, { headers: { isToken: false } }) + login: (data) => service.post('/login', data, { headers: { isToken: false } }), + getTenants: (username) => service.get('/system/tenant/user-bind/' + username, { headers: { isToken: false } }) } export const nursingApi = { - getTasks: (params) => request.get('/mp/nursing/tasks', { params }), - completeTask: (id, data) => request.post(`/mp/nursing/tasks/${id}/complete`, data), - getPatientInfo: (id) => request.get(`/mp/nursing/patient/${id}`), - getPatientList: (params) => request.get('/mp/nursing/patient/list', { params }), - getOrders: (patientId) => request.get(`/mp/nursing/orders/${patientId}`), - getVitalSigns: (patientId) => request.get(`/mp/nursing/vital-signs/${patientId}`), - submitVitalSign: (data) => request.post('/mp/nursing/vital-sign', data), - getAssessments: (patientId) => request.get(`/mp/nursing/assessments/${patientId}`), - submitAssessment: (data) => request.post('/mp/nursing/assessment', data) + getTasks: (params) => service.get('/mp/nursing/tasks', { params }), + completeTask: (id, data) => service.post(`/mp/nursing/tasks/${id}/complete`, data), + getPatientInfo: (id) => service.get(`/mp/nursing/patient/${id}`), + getPatientList: (params) => service.get('/mp/nursing/patient/list', { params }), + getOrders: (patientId) => service.get(`/mp/nursing/orders/${patientId}`), + getVitalSigns: (patientId) => service.get(`/mp/nursing/vital-signs/${patientId}`), + submitVitalSign: (data) => service.post('/mp/nursing/vital-sign', data), + getAssessments: (patientId) => service.get(`/mp/nursing/assessments/${patientId}`), + submitAssessment: (data) => service.post('/mp/nursing/assessment', data) } -export default request +export default service diff --git a/healthlink-his-mobile/src/main.js b/healthlink-his-mobile/src/main.js index 2df3d027e..99de3f024 100644 --- a/healthlink-his-mobile/src/main.js +++ b/healthlink-his-mobile/src/main.js @@ -1,6 +1,7 @@ import { createApp } from 'vue' import { createPinia } from 'pinia' import ElementPlus from 'element-plus' +import zhCn from 'element-plus/dist/locale/zh-cn.mjs' import 'element-plus/dist/index.css' import App from './App.vue' import router from './router' @@ -9,5 +10,5 @@ import './styles/mobile.css' const app = createApp(App) app.use(createPinia()) app.use(router) -app.use(ElementPlus, { size: 'large' }) +app.use(ElementPlus, { size: 'large', locale: zhCn }) app.mount('#app') diff --git a/healthlink-his-mobile/src/router/index.js b/healthlink-his-mobile/src/router/index.js index 6d3175a3a..463e9d8a2 100644 --- a/healthlink-his-mobile/src/router/index.js +++ b/healthlink-his-mobile/src/router/index.js @@ -2,25 +2,21 @@ import { createRouter, createWebHistory } from 'vue-router' const routes = [ { path: '/login', component: () => import('../views/Login.vue'), meta: { title: '登录' } }, - { path: '/', redirect: '/mobile/tasks' }, + { path: '/', redirect: '/mobile/home' }, { path: '/mobile', component: () => import('../views/MobileLayout.vue'), meta: { requiresAuth: true }, children: [ - { path: 'tasks', component: () => import('../views/TaskList.vue'), meta: { title: '任务' } }, - { path: 'patients', component: () => import('../views/PatientList.vue'), meta: { title: '患者' } }, + { path: 'home', component: () => import('../views/Home.vue'), meta: { title: '首页' } }, + { path: 'tasks', component: () => import('../views/TaskList.vue'), meta: { title: '任务列表' } }, + { path: 'patients', component: () => import('../views/PatientList.vue'), meta: { title: '患者列表' } }, { path: 'patient-detail/:id', component: () => import('../views/PatientDetail.vue'), meta: { title: '患者详情' } }, - { path: 'vital-entry/:patientId', component: () => import('../views/VitalSignEntry.vue'), meta: { title: '生命体征' } }, + { path: 'vital-entry/:patientId', component: () => import('../views/VitalSignEntry.vue'), meta: { title: '生命体征录入' } }, { path: 'assessment/:patientId', component: () => import('../views/AssessmentForm.vue'), meta: { title: '护理评估' } }, { path: 'mine', component: () => import('../views/Mine.vue'), meta: { title: '我的' } } ]} ] const router = createRouter({ history: createWebHistory(), routes }) - router.beforeEach((to, from, next) => { - if (to.meta.requiresAuth) { - const token = localStorage.getItem('Admin-Token') - if (!token) { next('/login'); return } - } + if (to.meta.requiresAuth && !localStorage.getItem('Admin-Token')) { next('/login'); return } next() }) - export default router diff --git a/healthlink-his-mobile/src/views/AssessmentForm.vue b/healthlink-his-mobile/src/views/AssessmentForm.vue index 985282289..e52853aaf 100644 --- a/healthlink-his-mobile/src/views/AssessmentForm.vue +++ b/healthlink-his-mobile/src/views/AssessmentForm.vue @@ -2,24 +2,18 @@
-
{{ type.icon }}
-
{{ type.name }}
+
{{ type.icon }}
{{ type.name }}
{{ item.label }}
- - {{ opt.label }} ({{ opt.score }}分) - + {{ opt.label }} ({{ opt.score }}分)
-
-
总分: {{ totalScore }}
-
{{ riskLevelText }}
-
- +
总分: {{ totalScore }}
{{ riskLevelText }}
+
@@ -27,11 +21,12 @@ diff --git a/healthlink-his-mobile/src/views/Home.vue b/healthlink-his-mobile/src/views/Home.vue new file mode 100644 index 000000000..78bf16d8f --- /dev/null +++ b/healthlink-his-mobile/src/views/Home.vue @@ -0,0 +1,89 @@ + + + + + diff --git a/healthlink-his-mobile/src/views/Login.vue b/healthlink-his-mobile/src/views/Login.vue index 9d1e8fc65..227e58bfc 100644 --- a/healthlink-his-mobile/src/views/Login.vue +++ b/healthlink-his-mobile/src/views/Login.vue @@ -3,7 +3,7 @@

{{ currentTenantName || 'HealthLink 移动护理' }}

-

医院信息管理系统

+

护士工作站

@@ -21,14 +21,9 @@
- +
{{ errorMsg }}
- @@ -50,14 +45,8 @@ const loadTenants = async () => { try { const res = await authApi.getTenants(form.value.username) if (res.code === 200 && res.data) { - tenantOptions.value = res.data.map(item => ({ - label: item.tenantName, - value: item.id - })) - if (tenantOptions.value.length === 1) { - form.value.tenantId = tenantOptions.value[0].value - currentTenantName.value = tenantOptions.value[0].label - } + tenantOptions.value = res.data.map(item => ({ label: item.tenantName, value: item.id })) + if (tenantOptions.value.length === 1) { form.value.tenantId = tenantOptions.value[0].value; currentTenantName.value = tenantOptions.value[0].label } } } catch (e) { console.error(e) } } @@ -70,29 +59,12 @@ const onTenantChange = () => { const handleLogin = async () => { if (!form.value.username) { errorMsg.value = '请输入用户名'; return } if (!form.value.password) { errorMsg.value = '请输入密码'; return } - - loading.value = true - errorMsg.value = '' + loading.value = true; errorMsg.value = '' try { - const res = await authApi.login({ - username: form.value.username, - password: form.value.password, - tenantId: form.value.tenantId, - code: '', - uuid: '' - }) - if (res.code === 200 && res.token) { - localStorage.setItem('Admin-Token', res.token) - ElMessage.success('登录成功') - router.push('/mobile/tasks') - } else { - errorMsg.value = res.msg || '登录失败' - } - } catch (e) { - errorMsg.value = e.response?.data?.msg || '登录失败,请检查网络' - } finally { - loading.value = false - } + const res = await authApi.login({ username: form.value.username, password: form.value.password, tenantId: form.value.tenantId, code: '', uuid: '' }) + if (res.code === 200 && res.token) { localStorage.setItem('Admin-Token', res.token); ElMessage.success('登录成功'); router.push('/mobile/home') } + else { errorMsg.value = res.msg || '登录失败' } + } catch (e) { errorMsg.value = e.response?.data?.msg || '登录失败' } finally { loading.value = false } } @@ -111,5 +83,4 @@ select.input { appearance: none; background: #fff url("data:image/svg+xml,%3Csvg .login-btn { width: 100%; padding: 14px; background: #1890ff; color: #fff; border: none; border-radius: 8px; font-size: 18px; font-weight: 600; cursor: pointer; } .login-btn:disabled { background: #91d5ff; } .error-msg { color: #f5222d; text-align: center; margin-top: 12px; font-size: 14px; } -.login-footer { margin-top: 20px; color: rgba(255,255,255,0.6); font-size: 12px; } diff --git a/healthlink-his-mobile/src/views/Mine.vue b/healthlink-his-mobile/src/views/Mine.vue index 100261431..93015e791 100644 --- a/healthlink-his-mobile/src/views/Mine.vue +++ b/healthlink-his-mobile/src/views/Mine.vue @@ -1,39 +1,42 @@ diff --git a/healthlink-his-mobile/src/views/PatientList.vue b/healthlink-his-mobile/src/views/PatientList.vue index 23e47b421..09b03ca2e 100644 --- a/healthlink-his-mobile/src/views/PatientList.vue +++ b/healthlink-his-mobile/src/views/PatientList.vue @@ -1,61 +1,49 @@ diff --git a/healthlink-his-mobile/src/views/TaskList.vue b/healthlink-his-mobile/src/views/TaskList.vue index 80ffe1fa6..439320d7e 100644 --- a/healthlink-his-mobile/src/views/TaskList.vue +++ b/healthlink-his-mobile/src/views/TaskList.vue @@ -1,57 +1,36 @@ diff --git a/healthlink-his-mobile/vite.config.js b/healthlink-his-mobile/vite.config.js index 8593a080a..79464f8d7 100644 --- a/healthlink-his-mobile/vite.config.js +++ b/healthlink-his-mobile/vite.config.js @@ -1,20 +1,42 @@ -import { defineConfig } from 'vite' +import { defineConfig, loadEnv } from 'vite' +import path from 'path' import vue from '@vitejs/plugin-vue' -export default defineConfig({ - plugins: [vue()], - server: { - port: 82, - proxy: { - '/dev-api': { - target: 'http://localhost:18080/healthlink-his', - changeOrigin: true, - rewrite: (p) => p.replace(/^\/dev-api/, '') +export default defineConfig(({ mode }) => { + const env = loadEnv(mode, process.cwd()) + return { + base: '/', + plugins: [vue()], + resolve: { + alias: { + '~': path.resolve(__dirname, './'), + '@': path.resolve(__dirname, './src') + }, + extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'] + }, + server: { + port: 82, + host: true, + proxy: { + '/dev-api': { + target: env.VITE_API_PROXY || 'http://localhost:18080/healthlink-his', + changeOrigin: true, + rewrite: (p) => p.replace(/^\/dev-api/, '') + } + } + }, + build: { + outDir: 'dist', + assetsDir: 'assets', + cssMinify: 'esbuild' + }, + css: { + preprocessorOptions: { + scss: { + api: 'modern-compiler', + silenceDeprecations: ['import', 'global-builtin', 'color-functions', 'legacy-js-api'] + } } } - }, - build: { - outDir: 'dist', - assetsDir: 'assets' } })