feat(menu): 优化菜单路径唯一性校验并更新前端界面
- 在SysLoginController中添加optionMap数据返回 - 添加JSQLParser依赖支持MyBatis Plus功能 - 实现selectMenuByPathExcludeId方法用于排除当前菜单的路径唯一性校验 - 在SysMenuServiceImpl中添加日志记录并优化路径唯一性判断逻辑 - 在SysMenuMapper.xml中添加LIMIT 1限制并实现排除ID查询 - 在前端路由中注释患者管理相关路由配置 - 在用户store中添加optionMap配置项并优先从optionMap获取医院名称 - 重构检查项目设置页面的操作按钮样式为统一的圆形按钮设计 - 更新检查项目设置页面的导航栏样式和交互体验 - 优化门诊记录页面的搜索条件和表格展示功能 - 添加性别和状态筛选条件并改进数据加载逻辑
This commit is contained in:
105
openhis-ui-vue3/src/api/administration/practitionerPatient.js
Normal file
105
openhis-ui-vue3/src/api/administration/practitionerPatient.js
Normal file
@@ -0,0 +1,105 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
/**
|
||||
* 查询医生患者关系列表
|
||||
*/
|
||||
export function listPractitionerPatient(query) {
|
||||
return request({
|
||||
url: '/administration/practitioner-patient/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询医生患者关系详细
|
||||
*/
|
||||
export function getPractitionerPatient(id) {
|
||||
return request({
|
||||
url: '/administration/practitioner-patient/' + id,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取医生的所有有效患者
|
||||
*/
|
||||
export function getPatientsByPractitioner(practitionerId) {
|
||||
return request({
|
||||
url: '/administration/practitioner-patient/practitioner/' + practitionerId + '/patients',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取患者的所有有效医生
|
||||
*/
|
||||
export function getPractitionersByPatient(patientId) {
|
||||
return request({
|
||||
url: '/administration/practitioner-patient/patient/' + patientId + '/practitioners',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增医生患者关系
|
||||
*/
|
||||
export function addPractitionerPatient(data) {
|
||||
return request({
|
||||
url: '/administration/practitioner-patient',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改医生患者关系
|
||||
*/
|
||||
export function updatePractitionerPatient(data) {
|
||||
return request({
|
||||
url: '/administration/practitioner-patient',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 终止医生患者关系
|
||||
*/
|
||||
export function terminatePractitionerPatient(id) {
|
||||
return request({
|
||||
url: '/administration/practitioner-patient/terminate/' + id,
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除医生患者关系
|
||||
*/
|
||||
export function delPractitionerPatient(id) {
|
||||
return request({
|
||||
url: '/administration/practitioner-patient/' + id,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除医生患者关系
|
||||
*/
|
||||
export function delPractitionerPatientBatch(ids) {
|
||||
return request({
|
||||
url: '/administration/practitioner-patient/' + ids,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量创建医生患者关系
|
||||
*/
|
||||
export function batchAddPractitionerPatient(data) {
|
||||
return request({
|
||||
url: '/administration/practitioner-patient/batch',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
9
openhis-ui-vue3/src/api/home.js
Normal file
9
openhis-ui-vue3/src/api/home.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 获取首页统计数据
|
||||
export function getHomeStatistics() {
|
||||
return request({
|
||||
url: '/home/statistics',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
@@ -92,6 +92,27 @@ export const constantRoutes = [
|
||||
path: '/tpr',
|
||||
component: () => import('@/views/inpatientNurse/tprsheet/index.vue'),
|
||||
},
|
||||
// {
|
||||
// path: '/patientmanagement',
|
||||
// component: Layout,
|
||||
// redirect: '/patientmanagement/patientmanagement',
|
||||
// name: 'PatientManagement',
|
||||
// meta: { title: '患者管理', icon: 'patient' },
|
||||
// children: [
|
||||
// {
|
||||
// path: 'patientmanagement',
|
||||
// component: () => import('@/views/patientmanagement/patientmanagement/index.vue'),
|
||||
// name: 'PatientManagementList',
|
||||
// meta: { title: '患者档案管理', icon: 'patient' },
|
||||
// },
|
||||
// {
|
||||
// path: 'outpatienrecords',
|
||||
// component: () => import('@/views/patientmanagement/outpatienrecords/index.vue'),
|
||||
// name: 'OutpatientRecords',
|
||||
// meta: { title: '门诊就诊记录', icon: 'record' },
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
];
|
||||
|
||||
// 动态路由 - 基于用户权限动态加载的路由
|
||||
|
||||
@@ -20,7 +20,8 @@ const useUserStore = defineStore(
|
||||
permissions: [],
|
||||
tenantId: '',
|
||||
tenantName: '', // 租户名称
|
||||
hospitalName:''
|
||||
hospitalName:'',
|
||||
optionMap: {} // 租户配置项Map(从sys_tenant_option表读取)
|
||||
}),
|
||||
actions: {
|
||||
// 登录
|
||||
@@ -63,7 +64,9 @@ const useUserStore = defineStore(
|
||||
this.practitionerId = res.practitionerId
|
||||
this.fixmedinsCode = res.optionJson.fixmedinsCode
|
||||
this.avatar = avatar
|
||||
this.hospitalName = res.optionJson.hospitalName
|
||||
this.optionMap = res.optionMap || {}
|
||||
// 优先从optionMap获取配置,如果没有则从optionJson获取
|
||||
this.hospitalName = this.optionMap.hospitalName || res.optionJson.hospitalName || ''
|
||||
this.tenantName = res.tenantName || ''
|
||||
|
||||
resolve(res)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -111,17 +111,6 @@
|
||||
<!-- 底部 -->
|
||||
|
||||
<div class="el-login-footer">
|
||||
<div class="el-login-footer-link">
|
||||
<span><el-link :underline="false">账号用户协议</el-link></span>
|
||||
<span>|</span>
|
||||
<span>
|
||||
<el-link :underline="false">关于账号与隐私的声明</el-link>
|
||||
</span>
|
||||
<span>|</span>
|
||||
<span><el-link :underline="false">常见问题</el-link></span>
|
||||
<span>|</span>
|
||||
<span><el-link :underline="false">Cookies</el-link></span>
|
||||
</div>
|
||||
<span>
|
||||
<el-link
|
||||
:underline="false"
|
||||
@@ -595,7 +584,7 @@ html, body {
|
||||
}
|
||||
}
|
||||
.el-login-footer {
|
||||
height: 80px;
|
||||
height: 40px;
|
||||
line-height: 30px;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
|
||||
@@ -143,30 +143,35 @@
|
||||
<el-table-column prop="creator" label="操作人" width="100" align="center" />
|
||||
<el-table-column label="操作" width="180" align="center" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
icon="Edit"
|
||||
circle
|
||||
@click="handleEdit(row)"
|
||||
title="编辑"
|
||||
/>
|
||||
<el-button
|
||||
type="info"
|
||||
size="small"
|
||||
icon="View"
|
||||
circle
|
||||
@click="handleView(row)"
|
||||
title="查看"
|
||||
/>
|
||||
<el-button
|
||||
type="danger"
|
||||
size="small"
|
||||
icon="Delete"
|
||||
circle
|
||||
@click="handleDelete(row)"
|
||||
title="删除"
|
||||
/>
|
||||
<div class="actions">
|
||||
<el-button
|
||||
class="btn btn-edit"
|
||||
size="small"
|
||||
circle
|
||||
@click="handleEdit(row)"
|
||||
title="编辑"
|
||||
>
|
||||
✏️
|
||||
</el-button>
|
||||
<el-button
|
||||
class="btn btn-view"
|
||||
size="small"
|
||||
circle
|
||||
@click="handleView(row)"
|
||||
title="查看"
|
||||
>
|
||||
👁️
|
||||
</el-button>
|
||||
<el-button
|
||||
class="btn btn-delete"
|
||||
size="small"
|
||||
circle
|
||||
@click="handleDelete(row)"
|
||||
title="删除"
|
||||
>
|
||||
✕
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -612,10 +617,84 @@ function handleDelete(row) {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding: 16px 20px;
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
margin-top: 16px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.03);
|
||||
}
|
||||
|
||||
/* 统一的操作按钮样式 */
|
||||
.actions {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 6px;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.btn {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
color: white;
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
transform: translateY(-2px) scale(1.1);
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18);
|
||||
}
|
||||
|
||||
.btn:active {
|
||||
transform: translateY(0) scale(0.95);
|
||||
}
|
||||
|
||||
.btn-confirm {
|
||||
background: linear-gradient(135deg, #52C41A 0%, #73d13d 100%);
|
||||
}
|
||||
|
||||
.btn-confirm:hover {
|
||||
background: linear-gradient(135deg, #389E0D 0%, #52C41A 100%);
|
||||
}
|
||||
|
||||
.btn-edit {
|
||||
background: linear-gradient(135deg, #1890FF 0%, #40a9ff 100%);
|
||||
}
|
||||
|
||||
.btn-edit:hover {
|
||||
background: linear-gradient(135deg, #096DD9 0%, #1890FF 100%);
|
||||
}
|
||||
|
||||
.btn-add {
|
||||
background: linear-gradient(135deg, #1890FF 0%, #40a9ff 100%);
|
||||
}
|
||||
|
||||
.btn-add:hover {
|
||||
background: linear-gradient(135deg, #096DD9 0%, #1890FF 100%);
|
||||
}
|
||||
|
||||
.btn-view {
|
||||
background: linear-gradient(135deg, #722ED1 0%, #9254DE 100%);
|
||||
}
|
||||
|
||||
.btn-view:hover {
|
||||
background: linear-gradient(135deg, #531DAE 0%, #722ED1 100%);
|
||||
}
|
||||
|
||||
.btn-delete {
|
||||
background: linear-gradient(135deg, #FF4D4F 0%, #ff7875 100%);
|
||||
z-index: 20;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.btn-delete:hover {
|
||||
background: linear-gradient(135deg, #CF1322 0%, #FF4D4F 100%);
|
||||
}
|
||||
|
||||
/* 优化滚动条样式 - 支持水平和垂直滚动 */
|
||||
|
||||
@@ -337,36 +337,46 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="150" align="center" fixed="right">
|
||||
<template #default="{ row, $index }">
|
||||
<el-button
|
||||
v-if="!row.editing"
|
||||
type="primary"
|
||||
size="small"
|
||||
icon="Edit"
|
||||
circle
|
||||
@click="handleEditRow(row)"
|
||||
/>
|
||||
<el-button
|
||||
v-if="row.editing"
|
||||
type="success"
|
||||
size="small"
|
||||
icon="Check"
|
||||
circle
|
||||
@click="handleConfirmRow(row)"
|
||||
/>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
icon="Plus"
|
||||
circle
|
||||
@click="handleAddRow"
|
||||
/>
|
||||
<el-button
|
||||
type="danger"
|
||||
size="small"
|
||||
icon="Delete"
|
||||
circle
|
||||
@click="handleDeleteRow($index)"
|
||||
/>
|
||||
<div class="actions">
|
||||
<el-button
|
||||
v-if="!row.editing"
|
||||
class="btn btn-edit"
|
||||
size="small"
|
||||
circle
|
||||
@click="handleEditRow(row)"
|
||||
title="编辑"
|
||||
>
|
||||
✏️
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="row.editing"
|
||||
class="btn btn-confirm"
|
||||
size="small"
|
||||
circle
|
||||
@click="handleConfirmRow(row)"
|
||||
title="保存"
|
||||
>
|
||||
✓
|
||||
</el-button>
|
||||
<el-button
|
||||
class="btn btn-add"
|
||||
size="small"
|
||||
circle
|
||||
@click="handleAddRow"
|
||||
title="添加"
|
||||
>
|
||||
+
|
||||
</el-button>
|
||||
<el-button
|
||||
class="btn btn-delete"
|
||||
size="small"
|
||||
circle
|
||||
@click="handleDeleteRow($index)"
|
||||
title="删除"
|
||||
>
|
||||
✕
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -1229,6 +1239,76 @@ async function handleSave() {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
/* 统一的操作按钮样式 */
|
||||
.actions {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 6px;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.btn {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
color: white;
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
transform: translateY(-2px) scale(1.1);
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18);
|
||||
}
|
||||
|
||||
.btn:active {
|
||||
transform: translateY(0) scale(0.95);
|
||||
}
|
||||
|
||||
.btn-confirm {
|
||||
background: linear-gradient(135deg, #52C41A 0%, #73d13d 100%);
|
||||
}
|
||||
|
||||
.btn-confirm:hover {
|
||||
background: linear-gradient(135deg, #389E0D 0%, #52C41A 100%);
|
||||
}
|
||||
|
||||
.btn-edit {
|
||||
background: linear-gradient(135deg, #1890FF 0%, #40a9ff 100%);
|
||||
}
|
||||
|
||||
.btn-edit:hover {
|
||||
background: linear-gradient(135deg, #096DD9 0%, #1890FF 100%);
|
||||
}
|
||||
|
||||
.btn-add {
|
||||
background: linear-gradient(135deg, #1890FF 0%, #40a9ff 100%);
|
||||
}
|
||||
|
||||
.btn-add:hover {
|
||||
background: linear-gradient(135deg, #096DD9 0%, #1890FF 100%);
|
||||
}
|
||||
|
||||
.btn-delete {
|
||||
background: linear-gradient(135deg, #FF4D4F 0%, #ff7875 100%);
|
||||
z-index: 20;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.btn-delete:hover {
|
||||
background: linear-gradient(135deg, #CF1322 0%, #FF4D4F 100%);
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 768px) {
|
||||
.package-settings {
|
||||
@@ -1249,4 +1329,3 @@ async function handleSave() {
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -1,36 +1,41 @@
|
||||
<template>
|
||||
<div class="check-project-settings">
|
||||
<!-- 左侧导航栏 -->
|
||||
<div class="sidebar" style="margin-top: 100px;">
|
||||
<!-- 明确列出所有导航项 -->
|
||||
<button
|
||||
class="menu-item active"
|
||||
@click="handleMenuClick('检查类型')"
|
||||
style="display: block; width: 100%; height: 40px; padding: 8px; text-align: center;"
|
||||
>
|
||||
检查类型
|
||||
</button>
|
||||
<button
|
||||
class="menu-item"
|
||||
@click="handleMenuClick('检查方法')"
|
||||
style="display: block; width: 100%; height: 40px; padding: 8px; text-align: center;"
|
||||
>
|
||||
检查方法
|
||||
</button>
|
||||
<button
|
||||
class="menu-item"
|
||||
@click="handleMenuClick('检查部位')"
|
||||
style="display: block; width: 100%; height: 40px; padding: 8px; text-align: center;"
|
||||
>
|
||||
检查部位
|
||||
</button>
|
||||
<button
|
||||
class="menu-item"
|
||||
@click="handleMenuClick('套餐设置')"
|
||||
style="display: block; width: 100%; height: 40px; padding: 8px; text-align: center;"
|
||||
>
|
||||
套餐设置
|
||||
</button>
|
||||
<div class="sidebar">
|
||||
<div class="sidebar-header">
|
||||
<h3>检查项目管理</h3>
|
||||
</div>
|
||||
<div class="sidebar-menu">
|
||||
<!-- 明确列出所有导航项 -->
|
||||
<button
|
||||
class="menu-item active"
|
||||
@click="handleMenuClick('检查类型')"
|
||||
>
|
||||
<span class="menu-icon">📋</span>
|
||||
<span class="menu-text">检查类型</span>
|
||||
</button>
|
||||
<button
|
||||
class="menu-item"
|
||||
@click="handleMenuClick('检查方法')"
|
||||
>
|
||||
<span class="menu-icon">🔬</span>
|
||||
<span class="menu-text">检查方法</span>
|
||||
</button>
|
||||
<button
|
||||
class="menu-item"
|
||||
@click="handleMenuClick('检查部位')"
|
||||
>
|
||||
<span class="menu-icon">🎯</span>
|
||||
<span class="menu-text">检查部位</span>
|
||||
</button>
|
||||
<button
|
||||
class="menu-item"
|
||||
@click="handleMenuClick('套餐设置')"
|
||||
>
|
||||
<span class="menu-icon">📦</span>
|
||||
<span class="menu-text">套餐设置</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 主内容区域 -->
|
||||
@@ -165,26 +170,27 @@
|
||||
</td>
|
||||
<td class="actions">
|
||||
<template v-if="item.actions">
|
||||
<button class="btn btn-confirm" @click.stop="handleConfirm(index)">
|
||||
<button class="btn btn-confirm" @click.stop="handleConfirm(index)" title="保存">
|
||||
✓
|
||||
</button>
|
||||
<button
|
||||
v-if="!item.row.includes('.')"
|
||||
class="btn btn-add"
|
||||
<button
|
||||
v-if="!item.row.includes('.')"
|
||||
class="btn btn-add"
|
||||
@click.stop="handleAdd(index)"
|
||||
title="添加子项"
|
||||
>
|
||||
+
|
||||
</button>
|
||||
<button class="btn btn-delete" @click.stop="handleDelete(index)">
|
||||
🗑
|
||||
<button class="btn btn-delete" @click.stop="handleDelete(index)" title="删除">
|
||||
✕
|
||||
</button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<button class="btn btn-confirm" @click.stop="handleConfirm(index)">
|
||||
<button class="btn btn-confirm" @click.stop="handleConfirm(index)" title="保存">
|
||||
✓
|
||||
</button>
|
||||
<button class="btn btn-delete" @click.stop="handleDelete(index)">
|
||||
🗑
|
||||
<button class="btn btn-delete" @click.stop="handleDelete(index)" title="删除">
|
||||
✕
|
||||
</button>
|
||||
</template>
|
||||
</td>
|
||||
@@ -329,22 +335,22 @@
|
||||
</td>
|
||||
<td class="actions">
|
||||
<template v-if="item.editing">
|
||||
<button class="btn btn-confirm" @click.stop="handleConfirm(index)">
|
||||
<button class="btn btn-confirm" @click.stop="handleConfirm(index)" title="保存">
|
||||
✓
|
||||
</button>
|
||||
<button class="btn btn-cancel" @click.stop="handleCancelEdit(index)">
|
||||
<button class="btn btn-cancel" @click.stop="handleCancelEdit(index)" title="取消">
|
||||
✕
|
||||
</button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<button class="btn btn-edit" @click.stop="handleEdit(index)">
|
||||
<button class="btn btn-edit" @click.stop="handleEdit(index)" title="编辑">
|
||||
✏️
|
||||
</button>
|
||||
<button class="btn btn-confirm" @click.stop="handleConfirm(index)">
|
||||
<button class="btn btn-confirm" @click.stop="handleConfirm(index)" title="保存">
|
||||
✓
|
||||
</button>
|
||||
<button class="btn btn-delete" @click.stop="handleDelete(index)">
|
||||
🗑
|
||||
<button class="btn btn-delete" @click.stop="handleDelete(index)" title="删除">
|
||||
✕
|
||||
</button>
|
||||
</template>
|
||||
</td>
|
||||
@@ -515,22 +521,22 @@
|
||||
</td>
|
||||
<td class="actions">
|
||||
<template v-if="item.editing">
|
||||
<button class="btn btn-confirm" @click.stop="handleConfirm(index)">
|
||||
<button class="btn btn-confirm" @click.stop="handleConfirm(index)" title="保存">
|
||||
✓
|
||||
</button>
|
||||
<button class="btn btn-cancel" @click.stop="handleCancelEdit(index)">
|
||||
<button class="btn btn-cancel" @click.stop="handleCancelEdit(index)" title="取消">
|
||||
✕
|
||||
</button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<button class="btn btn-edit" @click.stop="handleEdit(index)">
|
||||
<button class="btn btn-edit" @click.stop="handleEdit(index)" title="编辑">
|
||||
✏️
|
||||
</button>
|
||||
<button class="btn btn-confirm" @click.stop="handleConfirm(index)">
|
||||
<button class="btn btn-confirm" @click.stop="handleConfirm(index)" title="保存">
|
||||
✓
|
||||
</button>
|
||||
<button class="btn btn-delete" @click.stop="handleDelete(index)">
|
||||
🗑
|
||||
<button class="btn btn-delete" @click.stop="handleDelete(index)" title="删除">
|
||||
✕
|
||||
</button>
|
||||
</template>
|
||||
</td>
|
||||
@@ -1441,79 +1447,150 @@ select {
|
||||
|
||||
/* 左侧导航栏样式 */
|
||||
.sidebar {
|
||||
width: 160px;
|
||||
background-color: #FFFFFF;
|
||||
height: 100vh;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
padding: 16px 8px;
|
||||
box-shadow: 1px 0 3px rgba(0, 0, 0, 0.05);
|
||||
z-index: 10;
|
||||
width: 200px;
|
||||
background: linear-gradient(180deg, #f8f9fa 0%, #ffffff 100%);
|
||||
height: 100%;
|
||||
position: relative;
|
||||
padding: 24px 0;
|
||||
box-shadow: 2px 0 8px rgba(0, 0, 0, 0.08);
|
||||
overflow-y: auto;
|
||||
flex-shrink: 0;
|
||||
border-right: 1px solid #e8e8e8;
|
||||
}
|
||||
|
||||
.sidebar-header {
|
||||
padding: 0 20px 20px 20px;
|
||||
margin-bottom: 12px;
|
||||
border-bottom: 2px solid #1890FF;
|
||||
}
|
||||
|
||||
.sidebar-header h3 {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #1890FF;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.sidebar-menu {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.menu-item {
|
||||
display: block;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
padding: 8px 12px;
|
||||
margin-bottom: 8px;
|
||||
background-color: #FFFFFF;
|
||||
color: #000000;
|
||||
border-radius: 4px;
|
||||
padding: 14px 16px;
|
||||
margin-bottom: 0;
|
||||
background-color: transparent;
|
||||
color: #333333;
|
||||
border-radius: 8px;
|
||||
text-decoration: none;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
border: none;
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
border: 1px solid transparent;
|
||||
cursor: pointer;
|
||||
text-align: left;
|
||||
transition: all 0.2s ease;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.menu-item::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 4px;
|
||||
height: 0;
|
||||
background: linear-gradient(180deg, #1890FF 0%, #40a9ff 100%);
|
||||
border-radius: 0 4px 4px 0;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
.menu-item:hover {
|
||||
background-color: rgba(24, 144, 255, 0.1);
|
||||
background-color: rgba(24, 144, 255, 0.08);
|
||||
border-color: rgba(24, 144, 255, 0.2);
|
||||
transform: translateX(4px);
|
||||
}
|
||||
|
||||
.menu-item:hover::before {
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.menu-item.active {
|
||||
background-color: #1890FF;
|
||||
background: linear-gradient(135deg, #1890FF 0%, #40a9ff 100%);
|
||||
color: #FFFFFF;
|
||||
border-color: #1890FF;
|
||||
box-shadow: 0 4px 12px rgba(24, 144, 255, 0.3);
|
||||
}
|
||||
|
||||
.menu-item.active::before {
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.menu-icon {
|
||||
font-size: 18px;
|
||||
margin-right: 12px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.menu-item:hover .menu-icon {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.menu-text {
|
||||
flex: 1;
|
||||
letter-spacing: 0.3px;
|
||||
}
|
||||
|
||||
/* 主内容区样式 */
|
||||
.content {
|
||||
flex: 1;
|
||||
margin-left: 160px;
|
||||
padding: 24px;
|
||||
width: calc(100% - 160px);
|
||||
height: 100vh;
|
||||
padding: 32px 32px 32px 32px;
|
||||
min-width: 0;
|
||||
overflow-x: auto;
|
||||
overflow-y: auto;
|
||||
box-sizing: border-box;
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
margin-bottom: 24px;
|
||||
padding: 20px 24px;
|
||||
background: #ffffff;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
|
||||
border: 1px solid #e8e8e8;
|
||||
}
|
||||
|
||||
.header h1 {
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
color: #000000;
|
||||
font-size: 22px;
|
||||
font-weight: 600;
|
||||
color: #1890FF;
|
||||
margin: 0;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
/* 搜索栏样式 */
|
||||
.search-bar {
|
||||
background-color: #FFFFFF;
|
||||
padding: 16px;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 16px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.03);
|
||||
border: 1px solid #D9D9D9;
|
||||
padding: 20px 24px;
|
||||
border-radius: 12px;
|
||||
margin-bottom: 20px;
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
|
||||
border: 1px solid #e8e8e8;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
@@ -1628,9 +1705,9 @@ select {
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
background: #FFFFFF;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.03);
|
||||
border: 1px solid #D9D9D9;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
|
||||
border: 1px solid #e8e8e8;
|
||||
}
|
||||
|
||||
table {
|
||||
@@ -1642,14 +1719,16 @@ table {
|
||||
}
|
||||
|
||||
th {
|
||||
background-color: #fafafa;
|
||||
height: 40px;
|
||||
padding: 8px 16px;
|
||||
background: linear-gradient(180deg, #f8f9fa 0%, #fafbfc 100%);
|
||||
height: 48px;
|
||||
padding: 12px 16px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
font-weight: 600;
|
||||
line-height: 24px;
|
||||
text-align: center;
|
||||
border-bottom: 1px solid #D9D9D9;
|
||||
border-bottom: 2px solid #e8e8e8;
|
||||
color: #1890FF;
|
||||
letter-spacing: 0.3px;
|
||||
}
|
||||
|
||||
td {
|
||||
@@ -1666,57 +1745,78 @@ td {
|
||||
.actions {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
gap: 6px;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.btn {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
transition: all 0.2s ease;
|
||||
font-size: 16px;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
background-color: #66b1ff;
|
||||
color: white;
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
transform: translateY(-2px) scale(1.1);
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18);
|
||||
}
|
||||
|
||||
.btn:active {
|
||||
transform: translateY(0) scale(0.95);
|
||||
}
|
||||
|
||||
.btn-confirm {
|
||||
background: linear-gradient(135deg, #52C41A 0%, #73d13d 100%);
|
||||
}
|
||||
|
||||
.btn-confirm:hover {
|
||||
background: linear-gradient(135deg, #389E0D 0%, #52C41A 100%);
|
||||
}
|
||||
|
||||
.btn-edit {
|
||||
background: linear-gradient(135deg, #1890FF 0%, #40a9ff 100%);
|
||||
}
|
||||
|
||||
.btn-edit:hover {
|
||||
background: linear-gradient(135deg, #096DD9 0%, #1890FF 100%);
|
||||
}
|
||||
|
||||
.btn-add {
|
||||
background: linear-gradient(135deg, #1890FF 0%, #40a9ff 100%);
|
||||
}
|
||||
|
||||
.btn-add:hover {
|
||||
background: linear-gradient(135deg, #096DD9 0%, #1890FF 100%);
|
||||
}
|
||||
|
||||
.btn-cancel {
|
||||
background: linear-gradient(135deg, #FA8C16 0%, #ffa940 100%);
|
||||
}
|
||||
|
||||
.btn-cancel:hover {
|
||||
background: linear-gradient(135deg, #D46B08 0%, #FA8C16 100%);
|
||||
}
|
||||
|
||||
.btn-delete {
|
||||
background-color: #FF4D4F;
|
||||
color: white;
|
||||
font-size: 14px;
|
||||
background: linear-gradient(135deg, #FF4D4F 0%, #ff7875 100%);
|
||||
z-index: 20;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.btn-confirm {
|
||||
background-color: #1890FF;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-edit {
|
||||
background-color: #FFC107;
|
||||
color: white;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.btn-add {
|
||||
background-color: #1890FF;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-delete {
|
||||
background-color: #FF4D4F;
|
||||
color: white;
|
||||
font-size: 14px;
|
||||
.btn-delete:hover {
|
||||
background: linear-gradient(135deg, #CF1322 0%, #FF4D4F 100%);
|
||||
}
|
||||
|
||||
/* 特殊状态样式 */
|
||||
@@ -1803,16 +1903,45 @@ input[type="text"]::placeholder {
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 768px) {
|
||||
.sidebar {
|
||||
width: 60px;
|
||||
width: 70px;
|
||||
padding: 16px 8px;
|
||||
}
|
||||
|
||||
.menu-item span {
|
||||
|
||||
.sidebar-header {
|
||||
padding: 0 8px 16px 8px;
|
||||
}
|
||||
|
||||
.sidebar-header h3 {
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.menu-text {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
.menu-icon {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.menu-item {
|
||||
justify-content: center;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-left: 60px;
|
||||
padding: 16px;
|
||||
padding: 20px 16px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 平板适配 */
|
||||
@media (min-width: 769px) and (max-width: 1024px) {
|
||||
.sidebar {
|
||||
width: 160px;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 24px 20px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -8,11 +8,9 @@ export function listOutpatienRecords(query) {
|
||||
})
|
||||
}
|
||||
|
||||
export function listDoctorNames() {
|
||||
export function listDoctorNames() {
|
||||
return request({
|
||||
url: '/patient-manage/records/init',
|
||||
url: '/patient-manage/records/doctor-names',
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
<el-form-item label="查询内容" prop="searchKey">
|
||||
<el-input
|
||||
v-model="queryParams.searchKey"
|
||||
placeholder="身份证号/病人ID/门诊号/姓名"
|
||||
placeholder="姓名/身份证号/病人ID/门诊号"
|
||||
clearable
|
||||
style="width: 210px"
|
||||
style="width: 240px"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
@@ -15,7 +15,7 @@
|
||||
v-model="queryParams.phone"
|
||||
placeholder="请输入联系方式"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
style="width: 150px"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
@@ -27,14 +27,39 @@
|
||||
range-separator="-"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
style="width: 240px"
|
||||
></el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="性别" prop="genderEnum">
|
||||
<el-select
|
||||
v-model="queryParams.genderEnum"
|
||||
placeholder="请选择性别"
|
||||
clearable
|
||||
style="width: 100px"
|
||||
>
|
||||
<el-option label="男" :value="1" />
|
||||
<el-option label="女" :value="2" />
|
||||
<el-option label="未知" :value="3" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="subjectStatusEnum">
|
||||
<el-select
|
||||
v-model="queryParams.subjectStatusEnum"
|
||||
placeholder="请选择状态"
|
||||
clearable
|
||||
style="width: 120px"
|
||||
>
|
||||
<el-option label="待就诊" :value="1" />
|
||||
<el-option label="就诊中" :value="2" />
|
||||
<el-option label="已完成" :value="3" />
|
||||
<el-option label="已取消" :value="4" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="医生" prop="doctorName">
|
||||
<el-select
|
||||
v-model="queryParams.doctorName"
|
||||
placeholder="请选择医生"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
style="width: 160px"
|
||||
>
|
||||
<el-option
|
||||
@@ -51,18 +76,34 @@
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-table :data="outpatienRecordsList" border style="width: 100%">
|
||||
<el-table-column prop="name" label="患者" width="180" />
|
||||
<el-table-column prop="idCard" label="身份证" width="180" />
|
||||
<el-table-column prop="description" label="疾病" width="180" />
|
||||
<el-table-column prop="patientBusNo" label="病人ID" width="180" />
|
||||
<el-table-column prop="encounterBusNo" label="门诊号" width="180" />
|
||||
<el-table-column prop="genderEnum_enumText" label="性别" width="80" />
|
||||
<el-table
|
||||
:data="outpatienRecordsList"
|
||||
border
|
||||
style="width: 100%"
|
||||
:default-sort="{ prop: 'encounterTime', order: 'descending' }"
|
||||
v-loading="loading"
|
||||
:header-cell-style="{ background: '#f5f7fa', fontWeight: 'bold' }"
|
||||
>
|
||||
<el-table-column prop="name" label="患者" min-width="100" />
|
||||
<el-table-column prop="genderEnum_enumText" label="性别" width="80" align="center" />
|
||||
<el-table-column prop="idCard" label="身份证" min-width="160" :show-overflow-tooltip="true" />
|
||||
<el-table-column prop="phone" label="电话" width="120" />
|
||||
<el-table-column prop="encounterTime" label="就诊时间" width="180" />
|
||||
<el-table-column prop="subjectStatusEnum_enumText" label="状态" width="120" />
|
||||
<el-table-column prop="organizationName" label="接诊医院" width="180" />
|
||||
<el-table-column prop="doctorName" label="接诊医生" width="180" />
|
||||
<el-table-column prop="patientBusNo" label="病人ID" width="100" align="center" />
|
||||
<el-table-column prop="encounterBusNo" label="门诊号" width="120" align="center" />
|
||||
<el-table-column prop="encounterTime" label="就诊时间" width="160" sortable />
|
||||
<el-table-column prop="doctorName" label="接诊医生" width="120" />
|
||||
<el-table-column prop="organizationName" label="医疗机构" min-width="120" :show-overflow-tooltip="true" />
|
||||
<el-table-column prop="subjectStatusEnum_enumText" label="状态" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag
|
||||
:type="getStatusTagType(scope.row.subjectStatusEnum)"
|
||||
size="small"
|
||||
>
|
||||
{{ scope.row.subjectStatusEnum_enumText }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 移除疾病描述列,因为当前数据中没有这个字段 -->
|
||||
</el-table>
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
@@ -75,16 +116,19 @@
|
||||
</template>
|
||||
|
||||
<script setup name="outpatienRecords">
|
||||
import {computed, ref} from 'vue';
|
||||
import {computed, ref, reactive, toRefs, getCurrentInstance} from 'vue';
|
||||
import {listDoctorNames, listOutpatienRecords} from './component/api';
|
||||
import { useRoute } from 'vue-router';
|
||||
|
||||
const showSearch = ref(true);
|
||||
const total = ref(0);
|
||||
const dateRange = ref([]);
|
||||
const outpatienRecordsList = ref([]);
|
||||
const doctorList = ref([]);
|
||||
const loading = ref(false);
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
const route = useRoute();
|
||||
|
||||
const data = reactive({
|
||||
form: {},
|
||||
@@ -94,7 +138,8 @@ const data = reactive({
|
||||
doctorName: undefined,
|
||||
searchKey: undefined,
|
||||
phone: undefined,
|
||||
patientid: undefined,
|
||||
genderEnum: undefined,
|
||||
subjectStatusEnum: undefined,
|
||||
},
|
||||
});
|
||||
const { queryParams } = toRefs(data);
|
||||
@@ -108,23 +153,60 @@ const doctorOptions = computed(() => {
|
||||
|
||||
/** 查询门诊记录列表 */
|
||||
function getList() {
|
||||
loading.value = true;
|
||||
// 如果路由中有患者ID参数,则自动填充到查询条件中
|
||||
if (route.query.patientId) {
|
||||
queryParams.value.searchKey = route.query.patientId;
|
||||
}
|
||||
if (route.query.patientName) {
|
||||
// 可以在页面标题或其他地方显示患者姓名
|
||||
console.log('当前查看患者:', route.query.patientName);
|
||||
}
|
||||
|
||||
listOutpatienRecords(queryParams.value).then((response) => {
|
||||
outpatienRecordsList.value = response.data.records;
|
||||
total.value = response.data.total;
|
||||
loading.value = false;
|
||||
}).catch(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
listDoctorNames().then((response) => {
|
||||
console.log(response);
|
||||
doctorList.value = response.data;
|
||||
console.log(doctorList.value, 'doctorList.value');
|
||||
});
|
||||
|
||||
// 只在医生列表为空时加载医生列表
|
||||
if (doctorList.value.length === 0) {
|
||||
listDoctorNames().then((response) => {
|
||||
doctorList.value = response.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/** 根据状态获取标签类型 */
|
||||
function getStatusTagType(status) {
|
||||
// 假设状态值:1-待就诊,2-就诊中,3-已完成,4-已取消
|
||||
switch (status) {
|
||||
case 1:
|
||||
return 'warning'; // 待就诊 - 黄色
|
||||
case 2:
|
||||
return 'primary'; // 就诊中 - 蓝色
|
||||
case 3:
|
||||
return 'success'; // 已完成 - 绿色
|
||||
case 4:
|
||||
return 'info'; // 已取消 - 灰色
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
function handleQuery() {
|
||||
queryParams.value.startTimeSTime =
|
||||
dateRange.value && dateRange.value.length == 2 ? dateRange.value[0] : '';
|
||||
queryParams.value.startTimeETime =
|
||||
dateRange.value && dateRange.value.length == 2 ? dateRange.value[1] : '';
|
||||
// 处理时间范围参数
|
||||
if (dateRange.value && dateRange.value.length === 2) {
|
||||
queryParams.value.startTimeSTime = dateRange.value[0];
|
||||
queryParams.value.startTimeETime = dateRange.value[1];
|
||||
} else {
|
||||
queryParams.value.startTimeSTime = '';
|
||||
queryParams.value.startTimeETime = '';
|
||||
}
|
||||
|
||||
queryParams.value.pageNo = 1;
|
||||
getList();
|
||||
}
|
||||
|
||||
@@ -35,11 +35,11 @@
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table :data="patientList" border>
|
||||
<el-table-column prop="idCard" label="身份证号" width="180" />
|
||||
<el-table-column prop="busNo" label="病人ID" width="180" />
|
||||
<el-table-column prop="name" label="病人名称" width="180" />
|
||||
<el-table-column prop="genderEnum_enumText" label="性别" width="180">
|
||||
<el-table :data="patientList" border size="small" :header-cell-style="{padding: '8px 0'}" :cell-style="{padding: '6px 0'}">
|
||||
<el-table-column prop="idCard" label="身份证号" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="busNo" label="病人ID" width="100" show-overflow-tooltip />
|
||||
<el-table-column prop="name" label="病人名称" width="80" />
|
||||
<el-table-column prop="genderEnum_enumText" label="性别" width="60" align="center">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="patient_gender_enum" :value="scope.row.genderEnum" class="dict-tag" />
|
||||
</template>
|
||||
@@ -47,55 +47,57 @@
|
||||
<el-table-column
|
||||
prop="maritalStatusEnum_enumText"
|
||||
label="婚姻状况"
|
||||
width="180"
|
||||
width="80"
|
||||
align="center"
|
||||
>
|
||||
<template #default="scope">
|
||||
<dict-tag :options="marital_status_enum" :value="scope.row.maritalStatusEnum" class="dict-tag" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="nationalityCode" label="民族" width="180">
|
||||
<el-table-column prop="nationalityCode" label="民族" width="60" align="center">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="nationality_code" :value="scope.row.nationalityCode" class="dict-tag" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="birthDate" label="生日" width="160" />
|
||||
<el-table-column prop="phone" label="电话" width="140" />
|
||||
<el-table-column prop="bloodAbo_enumText" label="血型ABO" width="140">
|
||||
<el-table-column prop="birthDate" label="生日" width="100" />
|
||||
<el-table-column prop="phone" label="电话" width="110" />
|
||||
<el-table-column prop="bloodAbo_enumText" label="血型ABO" width="70" align="center">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="blood_abo" :value="scope.row.bloodAbo" class="dict-tag" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="bloodRh_enumText" label="血型RH" width="140">
|
||||
<el-table-column prop="bloodRh_enumText" label="血型RH" width="70" align="center">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="blood_rh" :value="scope.row.bloodRh" class="dict-tag" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="linkName" label="联系人" width="180" />
|
||||
<el-table-column prop="linkTelcom" label="联系人电话" width="180" />
|
||||
<el-table-column prop="linkRelationCode_enumText" label="联系人关系" width="180">
|
||||
<el-table-column prop="linkName" label="联系人" width="80" />
|
||||
<el-table-column prop="linkTelcom" label="联系人电话" width="110" />
|
||||
<el-table-column prop="linkRelationCode_enumText" label="联系人关系" width="80" align="center">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="link_relation_code" :value="scope.row.linkRelationCode" class="dict-tag" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="address" label="家庭地址" width="180" />
|
||||
<el-table-column prop="prfsEnum_enumText" label="职业" width="180">
|
||||
<el-table-column prop="address" label="家庭地址" min-width="150" show-overflow-tooltip />
|
||||
<el-table-column prop="prfsEnum_enumText" label="职业" width="80" align="center">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="prfs_enum" :value="scope.row.prfsEnum" class="dict-tag" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="workCompany" label="工作单位" width="180" />
|
||||
<el-table-column prop="organizationName" label="登记医院" width="180" />
|
||||
<el-table-column prop="deceasedDate" label="死亡时间" width="180" />
|
||||
<el-table-column prop="createTime" label="登记时间" width="180" />
|
||||
<el-table-column prop="workCompany" label="工作单位" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="organizationName" label="登记医院" width="100" show-overflow-tooltip />
|
||||
<el-table-column prop="deceasedDate" label="死亡时间" width="100" />
|
||||
<el-table-column prop="createTime" label="登记时间" width="140" />
|
||||
<el-table-column
|
||||
label="操作"
|
||||
align="center"
|
||||
width="210"
|
||||
class-name="small-padding fixed-width"
|
||||
>
|
||||
width="220"
|
||||
fixed="right"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" class="action-button">修改</el-button>
|
||||
<el-button link type="primary" icon="View" @click="handleSee(scope.row)" class="action-button">查看</el-button>
|
||||
<el-button link type="success" icon="Clock" @click="handleVisitHistory(scope.row)" class="action-button">就诊历史</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -174,7 +176,15 @@
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="证件号码" prop="idCard">
|
||||
<el-input v-model="form.idCard" clearable :disabled="isViewMode" />
|
||||
<el-input
|
||||
v-model="form.idCard"
|
||||
clearable
|
||||
:disabled="isViewMode"
|
||||
placeholder="请输入18位身份证号"
|
||||
maxlength="18"
|
||||
show-word-limit
|
||||
@blur="handleIdCardBlur"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="生日" prop="birthDate" v-show="false">
|
||||
<el-input v-model="form.birthDate" v-show="false" />
|
||||
@@ -424,6 +434,10 @@ const data = reactive({
|
||||
name: [{ required: true, message: '姓名不能为空', trigger: 'blur' }],
|
||||
age: [{ required: true, message: '年龄不能为空', trigger: 'change' }],
|
||||
phone: [{ required: true, message: '联系方式不能为空', trigger: 'blur' }],
|
||||
idCard: [
|
||||
{ required: true, message: '身份证号不能为空', trigger: 'blur' },
|
||||
{ validator: validateIdCard, trigger: 'blur' }
|
||||
],
|
||||
},
|
||||
});
|
||||
const { queryParams, form, rules, isViewMode } = toRefs(data);
|
||||
@@ -572,6 +586,18 @@ function handleSee(row) {
|
||||
title.value = '查看患者';
|
||||
});
|
||||
}
|
||||
|
||||
// 查看就诊历史
|
||||
function handleVisitHistory(row) {
|
||||
// 跳转到门诊记录页面,并传递患者ID参数
|
||||
proxy.$router.push({
|
||||
path: '/patient/patienrecords',
|
||||
query: {
|
||||
patientId: row.busNo,
|
||||
patientName: row.name
|
||||
}
|
||||
});
|
||||
}
|
||||
// 映射
|
||||
const nationalityDict = (code) => {
|
||||
const findObj = nationality_code.value.find((item) => item.value === code);
|
||||
@@ -638,6 +664,199 @@ function getAddress(form) {
|
||||
return part ? acc + part : acc;
|
||||
}, '');
|
||||
}
|
||||
/** 身份证号校验函数 */
|
||||
function validateIdCard(rule, value, callback) {
|
||||
if (!value) {
|
||||
return callback(new Error('身份证号不能为空'));
|
||||
}
|
||||
|
||||
// 基本格式校验
|
||||
const idCardReg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/;
|
||||
if (!idCardReg.test(value)) {
|
||||
return callback(new Error('身份证号格式不正确'));
|
||||
}
|
||||
|
||||
// 校验码验证
|
||||
const isValid = checkIdCardCode(value);
|
||||
if (!isValid) {
|
||||
return callback(new Error('身份证号校验码不正确,请检查'));
|
||||
}
|
||||
|
||||
// 日期验证
|
||||
const isValidDate = checkIdCardDate(value);
|
||||
if (!isValidDate) {
|
||||
return callback(new Error('身份证号中的日期不合法'));
|
||||
}
|
||||
|
||||
// 地区码验证(可选)
|
||||
const isValidArea = checkIdCardArea(value);
|
||||
if (!isValidArea) {
|
||||
return callback(new Error('身份证号中的地区码不合法'));
|
||||
}
|
||||
|
||||
callback();
|
||||
}
|
||||
|
||||
/** 身份证号校验码验证 */
|
||||
function checkIdCardCode(idCard) {
|
||||
const city = [11, 12, 13, 14, 15, 21, 22, 23, 31, 32, 33, 34, 35, 36, 37, 41, 42, 43, 44, 45, 46, 50, 51, 52, 53, 54, 61, 62, 63, 64, 65, 71, 81, 82, 91];
|
||||
|
||||
if (idCard.length === 15) {
|
||||
// 15位身份证号不校验码
|
||||
return true;
|
||||
}
|
||||
|
||||
if (idCard.length === 18) {
|
||||
// 18位身份证号校验码验证
|
||||
const coefficient = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
|
||||
const remainder = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
|
||||
let sum = 0;
|
||||
for (let i = 0; i < 17; i++) {
|
||||
sum += parseInt(idCard.charAt(i)) * coefficient[i];
|
||||
}
|
||||
const code = sum % 11;
|
||||
const lastChar = idCard.charAt(17).toUpperCase();
|
||||
return lastChar === remainder[code];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** 身份证号日期验证 */
|
||||
function checkIdCardDate(idCard) {
|
||||
let year, month, day;
|
||||
|
||||
if (idCard.length === 15) {
|
||||
// 15位身份证号:6位年份
|
||||
year = '19' + idCard.substring(6, 8);
|
||||
month = idCard.substring(8, 10);
|
||||
day = idCard.substring(10, 12);
|
||||
} else if (idCard.length === 18) {
|
||||
// 18位身份证号:4位年份
|
||||
year = idCard.substring(6, 10);
|
||||
month = idCard.substring(10, 12);
|
||||
day = idCard.substring(12, 14);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查日期是否合法
|
||||
const date = new Date(year, parseInt(month) - 1, parseInt(day));
|
||||
const now = new Date();
|
||||
|
||||
// 检查年月日是否有效
|
||||
if (date.getFullYear() !== parseInt(year) ||
|
||||
date.getMonth() + 1 !== parseInt(month) ||
|
||||
date.getDate() !== parseInt(day)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查是否是未来日期
|
||||
if (date > now) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查是否是合理的年份(100岁以上或刚出生)
|
||||
const age = now.getFullYear() - date.getFullYear();
|
||||
if (age < 0 || age > 150) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** 身份证号地区码验证 */
|
||||
function checkIdCardArea(idCard) {
|
||||
const areaCode = idCard.substring(0, 6);
|
||||
const validAreas = [
|
||||
'110000', '110101', '110102', '110105', '110106', '110107', '110108', '110109', '110111', '110112', '110113', '110114', '110115', '110116', '110117', '110118', '110119', // 北京
|
||||
'120000', '120101', '120102', '120103', '120104', '120105', '120106', '120110', '120111', '120112', '120113', '120114', '120115', '120116', '120117', '120118', '120119', // 天津
|
||||
'130000', // 河北
|
||||
'140000', // 山西
|
||||
'150000', // 内蒙古
|
||||
'210000', // 辽宁
|
||||
'220000', // 吉林
|
||||
'230000', // 黑龙江
|
||||
'310000', '310101', '310104', '310105', '310106', '310110', '310112', '310113', '310114', '310115', '310116', '310117', '310118', '310120', '310151', // 上海
|
||||
'320000', // 江苏
|
||||
'330000', // 浙江
|
||||
'340000', // 安徽
|
||||
'350000', // 福建
|
||||
'360000', // 江西
|
||||
'370000', // 山东
|
||||
'410000', // 河南
|
||||
'420000', // 湖北
|
||||
'430000', // 湖南
|
||||
'440000', // 广东
|
||||
'450000', // 广西
|
||||
'460000', // 海南
|
||||
'500000', '500101', '500102', '500103', '500104', '500105', '500106', '500107', '500108', '500109', '500110', '500111', '500112', '500113', '500114', '500115', '500116', '500117', '500118', '500119', '500120', '500151', // 重庆
|
||||
'510000', // 四川
|
||||
'520000', // 贵州
|
||||
'530000', // 云南
|
||||
'540000', // 西藏
|
||||
'610000', // 陕西
|
||||
'620000', // 甘肃
|
||||
'630000', // 青海
|
||||
'640000', // 宁夏
|
||||
'650000', // 新疆
|
||||
'710000', // 台湾
|
||||
'810000', // 香港
|
||||
'820000' // 澳门
|
||||
];
|
||||
|
||||
// 检查前6位是否在有效的地区码列表中
|
||||
// 简化验证:只检查省级代码
|
||||
const provinceCode = areaCode.substring(0, 2);
|
||||
const validProvinceCodes = ['11', '12', '13', '14', '15', '21', '22', '23', '31', '32', '33', '34', '35', '36', '37', '41', '42', '43', '44', '45', '46', '50', '51', '52', '53', '54', '61', '62', '63', '64', '65', '71', '81', '82'];
|
||||
|
||||
return validProvinceCodes.includes(provinceCode);
|
||||
}
|
||||
|
||||
/** 身份证号失焦处理 */
|
||||
function handleIdCardBlur() {
|
||||
const idCard = form.value.idCard;
|
||||
if (!idCard) return;
|
||||
|
||||
// 基本格式校验
|
||||
const idCardReg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/;
|
||||
if (!idCardReg.test(idCard)) {
|
||||
proxy.$message.warning('身份证号格式不正确,请输入15位或18位身份证号');
|
||||
return;
|
||||
}
|
||||
|
||||
// 校验码验证
|
||||
const isValidCode = checkIdCardCode(idCard);
|
||||
if (!isValidCode) {
|
||||
proxy.$message.warning('身份证号校验码不正确,请检查输入是否正确');
|
||||
return;
|
||||
}
|
||||
|
||||
// 日期验证
|
||||
const isValidDate = checkIdCardDate(idCard);
|
||||
if (!isValidDate) {
|
||||
proxy.$message.warning('身份证号中的日期不合法,请检查');
|
||||
return;
|
||||
}
|
||||
|
||||
// 地区码验证
|
||||
const isValidArea = checkIdCardArea(idCard);
|
||||
if (!isValidArea) {
|
||||
proxy.$message.warning('身份证号中的地区码不合法,请检查');
|
||||
return;
|
||||
}
|
||||
|
||||
// 所有验证通过,自动填充性别
|
||||
if (idCard.length === 18) {
|
||||
const genderCode = parseInt(idCard.charAt(16));
|
||||
// 男性:奇数,女性:偶数
|
||||
if (!form.value.genderEnum && genderCode) {
|
||||
form.value.genderEnum = genderCode % 2 === 1 ? 1 : 2;
|
||||
proxy.$message.success('身份证号验证通过,已自动填充性别信息');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 提交按钮 */
|
||||
function submitForm() {
|
||||
console.log('selectedOptions=====>', JSON.stringify(selectedOptions.value));
|
||||
@@ -694,21 +913,90 @@ onMounted(() => {
|
||||
|
||||
// 优化按钮组间距
|
||||
.button-group {
|
||||
margin-bottom: 16px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
// 优化表格样式
|
||||
// 优化表格样式 - 紧凑模式
|
||||
.el-table {
|
||||
// 移除固定宽度,让列自适应
|
||||
// 表头样式
|
||||
:deep(th) {
|
||||
background-color: #f8f9fa;
|
||||
color: #606266;
|
||||
font-weight: 600;
|
||||
padding: 12px 0;
|
||||
padding: 6px 8px !important;
|
||||
font-size: 13px;
|
||||
height: 36px !important;
|
||||
line-height: 36px !important;
|
||||
}
|
||||
|
||||
// 单元格样式
|
||||
:deep(td) {
|
||||
padding: 12px 0;
|
||||
padding: 4px 8px !important;
|
||||
font-size: 13px;
|
||||
height: 36px !important;
|
||||
line-height: 36px !important;
|
||||
}
|
||||
|
||||
// 表格整体字体
|
||||
:deep(.cell) {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
// 字典标签样式优化
|
||||
:deep(.dict-tag) {
|
||||
font-size: 12px;
|
||||
padding: 2px 6px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
// 操作按钮样式优化
|
||||
:deep(.action-button) {
|
||||
padding: 2px 4px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
// 小屏幕优化
|
||||
@media (max-height: 800px) {
|
||||
:deep(th) {
|
||||
font-size: 12px;
|
||||
padding: 4px 6px !important;
|
||||
height: 32px !important;
|
||||
line-height: 32px !important;
|
||||
}
|
||||
|
||||
:deep(td) {
|
||||
font-size: 12px;
|
||||
padding: 3px 6px !important;
|
||||
height: 32px !important;
|
||||
line-height: 32px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 优化查询表单样式
|
||||
.query-form {
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
:deep(.el-input) {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
:deep(.el-button) {
|
||||
padding: 8px 16px;
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
|
||||
// 优化分页样式
|
||||
.pagination-container {
|
||||
margin-top: 12px;
|
||||
padding: 12px 0;
|
||||
}
|
||||
|
||||
// 操作按钮间距
|
||||
.el-table :deep(.el-button + .el-button) {
|
||||
margin-left: 4px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -76,32 +76,51 @@
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="surgeryList" row-key="id">
|
||||
<el-table-column label="手术编号" align="center" prop="surgeryNo" width="150" />
|
||||
<el-table v-loading="loading" :data="surgeryList" row-key="id" :row-class-name="getRowClassName">
|
||||
<!-- 申请日期:datetime - 2025-09-19 14:15:00 - 不可操作 -->
|
||||
<el-table-column label="申请日期" align="center" prop="createTime" width="180">
|
||||
<template #default="scope">
|
||||
{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}:{s}') }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 手术单号:string - OP2025092003 - 可查看详情 -->
|
||||
<el-table-column label="手术单号" align="center" prop="surgeryNo" width="150" show-overflow-tooltip />
|
||||
|
||||
<!-- 患者姓名:string - 张小明 - 不可操作 -->
|
||||
<el-table-column label="患者姓名" align="center" prop="patientName" width="100" />
|
||||
<el-table-column label="性别" align="center" prop="patientGender" width="60" />
|
||||
<el-table-column label="年龄" align="center" prop="patientAge" width="60" />
|
||||
|
||||
<!-- 申请医生:string - 张医生 - 不可操作 -->
|
||||
<el-table-column label="申请医生" align="center" prop="applyDoctorName" width="100" />
|
||||
|
||||
<!-- 申请科室:string - 普外科 - 不可操作 -->
|
||||
<el-table-column label="申请科室" align="center" prop="applyDeptName" width="120" show-overflow-tooltip />
|
||||
|
||||
<!-- 手术名称:string - 腹腔镜胆囊切除术 - 不可操作 -->
|
||||
<el-table-column label="手术名称" align="center" prop="surgeryName" min-width="150" show-overflow-tooltip />
|
||||
<el-table-column label="手术类型" align="center" prop="surgeryTypeEnum_dictText" width="100" />
|
||||
|
||||
<!-- 手术等级:string - 三级手术 - 不可操作 -->
|
||||
<el-table-column label="手术等级" align="center" prop="surgeryLevel_dictText" width="100" />
|
||||
<el-table-column label="手术状态" align="center" prop="statusEnum_dictText" width="100">
|
||||
|
||||
<!-- 状态:badge - 已安排 - 不可操作 -->
|
||||
<el-table-column label="状态" align="center" prop="statusEnum_dictText" width="100">
|
||||
<template #default="scope">
|
||||
<el-tag :type="getStatusType(scope.row.statusEnum)">
|
||||
{{ scope.row.statusEnum_dictText }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="计划时间" align="center" prop="plannedTime" width="160" />
|
||||
<el-table-column label="主刀医生" align="center" prop="mainSurgeonName" width="100" />
|
||||
<el-table-column label="麻醉医生" align="center" prop="anesthetistName" width="100" />
|
||||
<el-table-column label="手术室" align="center" prop="operatingRoomName" width="120" />
|
||||
<el-table-column label="执行科室" align="center" prop="orgName" width="120" show-overflow-tooltip />
|
||||
|
||||
<!-- 操作:action - 查看/编辑/删除 - 可操作 -->
|
||||
<el-table-column label="操作" align="center" width="200" fixed="right">
|
||||
<template #default="scope">
|
||||
<!-- 查看:显示手术申请详情(只读模式) -->
|
||||
<el-button link type="primary" @click="handleView(scope.row)">查看</el-button>
|
||||
<el-button link type="primary" @click="handleEdit(scope.row)" v-if="scope.row.statusEnum === 0 || scope.row.statusEnum === 1">编辑</el-button>
|
||||
<el-button link type="primary" @click="handleStart(scope.row)" v-if="scope.row.statusEnum === 1">开始</el-button>
|
||||
<el-button link type="primary" @click="handleComplete(scope.row)" v-if="scope.row.statusEnum === 2">完成</el-button>
|
||||
|
||||
<!-- 编辑:修改手术申请信息(只有状态为新开的能修改) -->
|
||||
<el-button link type="primary" @click="handleEdit(scope.row)" v-if="scope.row.statusEnum === 0">编辑</el-button>
|
||||
|
||||
<!-- 删除:取消手术申请(作废) -->
|
||||
<el-button link type="danger" @click="handleDelete(scope.row)" v-if="scope.row.statusEnum === 0 || scope.row.statusEnum === 1">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -449,6 +468,7 @@ const queryParams = ref({
|
||||
})
|
||||
const open = ref(false)
|
||||
const viewOpen = ref(false)
|
||||
const isEditMode = ref(false)
|
||||
const form = ref({
|
||||
id: undefined,
|
||||
patientId: undefined,
|
||||
@@ -614,8 +634,17 @@ function handleAdd() {
|
||||
}
|
||||
|
||||
function handleEdit(row) {
|
||||
// 检查状态:只有状态为新开(0)时才允许编辑
|
||||
if (row.statusEnum !== 0) {
|
||||
proxy.$modal.msgWarning('当前状态不允许编辑手术,仅新开状态可编辑')
|
||||
return
|
||||
}
|
||||
|
||||
title.value = '编辑手术'
|
||||
open.value = true
|
||||
// 设置为编辑模式
|
||||
isEditMode.value = true
|
||||
|
||||
getSurgeryDetail(row.id).then(res => {
|
||||
if (res.code === 200) {
|
||||
Object.assign(form.value, res.data)
|
||||
@@ -685,37 +714,63 @@ function submitForm() {
|
||||
proxy.$refs['surgeryRef'].validate((valid) => {
|
||||
if (valid) {
|
||||
if (form.value.id == undefined) {
|
||||
// 新增手术
|
||||
addSurgery(form.value).then((res) => {
|
||||
proxy.$modal.msgSuccess('新增成功')
|
||||
open.value = false
|
||||
getPageList()
|
||||
}).catch(error => {
|
||||
console.error('新增手术失败:', error)
|
||||
proxy.$modal.msgError('新增手术失败,请稍后重试')
|
||||
// 显示红色 toast 提示
|
||||
proxy.$message.error('新增手术失败,请检查表单信息')
|
||||
})
|
||||
} else {
|
||||
// 修改手术
|
||||
updateSurgery(form.value).then((res) => {
|
||||
proxy.$modal.msgSuccess('修改成功')
|
||||
open.value = false
|
||||
getPageList()
|
||||
}).catch(error => {
|
||||
console.error('更新手术失败:', error)
|
||||
proxy.$modal.msgError('更新手术失败,请稍后重试')
|
||||
// 显示红色 toast 提示
|
||||
proxy.$message.error('更新手术失败,请检查表单信息')
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// 表单校验失败 - 显示红色 toast 提示
|
||||
proxy.$message.error('请检查表单信息,标红字段为必填项')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function handleDelete(row) {
|
||||
proxy.$modal.confirm('是否确认删除手术"' + row.surgeryName + '"?').then(() => {
|
||||
return deleteSurgery(row.id)
|
||||
}).then(() => {
|
||||
getPageList()
|
||||
proxy.$modal.msgSuccess('删除成功')
|
||||
}).catch(error => {
|
||||
console.error('删除手术失败:', error)
|
||||
})
|
||||
// 检查状态
|
||||
if (row.statusEnum === 0) {
|
||||
// 新开状态 - 直接删除
|
||||
proxy.$modal.confirm('是否确认删除手术"' + row.surgeryName + '"?').then(() => {
|
||||
return deleteSurgery(row.id)
|
||||
}).then(() => {
|
||||
getPageList()
|
||||
proxy.$modal.msgSuccess('删除成功')
|
||||
}).catch(error => {
|
||||
console.error('删除手术失败:', error)
|
||||
proxy.$modal.msgError('删除失败')
|
||||
})
|
||||
} else if (row.statusEnum === 1) {
|
||||
// 已排期状态 - 更新为已取消
|
||||
proxy.$modal.confirm('是否确认取消手术"' + row.surgeryName + '"?').then(() => {
|
||||
return updateSurgeryStatus(row.id, 4) // 4 = 已取消
|
||||
}).then(() => {
|
||||
getPageList()
|
||||
proxy.$modal.msgSuccess('手术已取消')
|
||||
}).catch(error => {
|
||||
console.error('取消手术失败:', error)
|
||||
proxy.$modal.msgError('取消失败')
|
||||
})
|
||||
} else {
|
||||
// 其他状态 - 不允许操作
|
||||
proxy.$modal.msgWarning('当前状态不允许取消手术')
|
||||
}
|
||||
}
|
||||
|
||||
function handleStart(row) {
|
||||
@@ -756,4 +811,57 @@ function getStatusType(status) {
|
||||
}
|
||||
return typeMap[status] || 'info'
|
||||
}
|
||||
|
||||
// 获取表格行样式
|
||||
function getRowClassName({ row }) {
|
||||
return row.statusEnum === 4 ? 'cancelled-row' : ''
|
||||
}
|
||||
|
||||
// 时间格式化函数
|
||||
function parseTime(time, pattern) {
|
||||
if (!time) return ''
|
||||
const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}'
|
||||
let date
|
||||
if (typeof time === 'object') {
|
||||
date = time
|
||||
} else {
|
||||
if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
|
||||
time = parseInt(time)
|
||||
} else if (typeof time === 'string') {
|
||||
time = time.replace(new RegExp(/-/gm), '/').replace('T', ' ').replace(new RegExp(/\.[\d]{3}/gm), '')
|
||||
}
|
||||
if ((typeof time === 'number') && (time.toString().length === 10)) {
|
||||
time = time * 1000
|
||||
}
|
||||
date = new Date(time)
|
||||
}
|
||||
const formatObj = {
|
||||
y: date.getFullYear(),
|
||||
m: date.getMonth() + 1,
|
||||
d: date.getDate(),
|
||||
h: date.getHours(),
|
||||
i: date.getMinutes(),
|
||||
s: date.getSeconds(),
|
||||
a: date.getDay()
|
||||
}
|
||||
const time_str = format.replace(/{([ymdhisa])+}/g, (result, key) => {
|
||||
const value = formatObj[key]
|
||||
if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] }
|
||||
return value.toString().padStart(2, '0')
|
||||
})
|
||||
return time_str
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 已取消行的样式 */
|
||||
:deep(.cancelled-row) {
|
||||
background-color: #f5f5f5;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
:deep(.cancelled-row .el-button--danger) {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -112,72 +112,73 @@
|
||||
</el-col>
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="typeList"
|
||||
height="calc(100vh - 300px)"
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="字典编号" align="center" prop="dictId" />
|
||||
<el-table-column
|
||||
label="字典名称"
|
||||
align="center"
|
||||
prop="dictName"
|
||||
:show-overflow-tooltip="true"
|
||||
/>
|
||||
<el-table-column label="字典类型" align="center" :show-overflow-tooltip="true">
|
||||
<template #default="scope">
|
||||
<router-link :to="'/system/dict-data/index/' + scope.row.dictId" class="link-type">
|
||||
<span>{{ scope.row.dictType }}</span>
|
||||
</router-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" align="center" prop="status">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="sys_normal_disable" :value="scope.row.status" class="dict-tag" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" prop="remark" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="操作"
|
||||
align="center"
|
||||
width="160"
|
||||
class-name="small-padding fixed-width"
|
||||
<div class="table-wrapper">
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="typeList"
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
icon="Edit"
|
||||
@click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['system:dict:edit']"
|
||||
class="action-button">修改</el-button
|
||||
>
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
icon="Delete"
|
||||
@click="handleDelete(scope.row)"
|
||||
v-hasPermi="['system:dict:remove']"
|
||||
class="action-button">删除</el-button
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="pagination-container">
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="字典编号" align="center" prop="dictId" />
|
||||
<el-table-column
|
||||
label="字典名称"
|
||||
align="center"
|
||||
prop="dictName"
|
||||
:show-overflow-tooltip="true"
|
||||
/>
|
||||
<el-table-column label="字典类型" align="center" :show-overflow-tooltip="true">
|
||||
<template #default="scope">
|
||||
<router-link :to="'/system/dict-data/index/' + scope.row.dictId" class="link-type">
|
||||
<span>{{ scope.row.dictType }}</span>
|
||||
</router-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" align="center" prop="status">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="sys_normal_disable" :value="scope.row.status" class="dict-tag" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" prop="remark" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="操作"
|
||||
align="center"
|
||||
width="160"
|
||||
class-name="small-padding fixed-width"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
icon="Edit"
|
||||
@click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['system:dict:edit']"
|
||||
class="action-button">修改</el-button
|
||||
>
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
icon="Delete"
|
||||
@click="handleDelete(scope.row)"
|
||||
v-hasPermi="['system:dict:remove']"
|
||||
class="action-button">删除</el-button
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="pagination-container">
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 添加或修改参数配置对话框 -->
|
||||
@@ -357,3 +358,68 @@ function handleRefreshCache() {
|
||||
|
||||
getList();
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.app-container {
|
||||
padding: 16px;
|
||||
background-color: #f5f7fa;
|
||||
min-height: 100vh;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.query-form {
|
||||
background: white;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 16px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.03);
|
||||
}
|
||||
|
||||
.button-group {
|
||||
background: white;
|
||||
padding: 16px;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 16px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.03);
|
||||
}
|
||||
|
||||
.search-buttons {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.table-wrapper {
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.03);
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
:deep(.el-table) {
|
||||
background: transparent;
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
:deep(.el-table__inner-wrapper) {
|
||||
border-radius: 8px 8px 0 0;
|
||||
}
|
||||
|
||||
.pagination-container {
|
||||
padding: 20px 16px 20px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
border-top: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
:deep(.el-dialog__body) {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.action-button {
|
||||
margin-right: 8px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="orderNum" label="排序" width="60"></el-table-column>
|
||||
<el-table-column prop="perms" label="权限标识" :show-overflow-tooltip="true"></el-table-column>
|
||||
<el-table-column prop="path" label="路由地址" :show-overflow-tooltip="true"></el-table-column>
|
||||
<el-table-column prop="component" label="组件路径" :show-overflow-tooltip="true"></el-table-column>
|
||||
<el-table-column prop="status" label="状态" width="80">
|
||||
<template #default="scope">
|
||||
|
||||
@@ -144,10 +144,12 @@ import {
|
||||
getTenantPage,
|
||||
saveTenantOptionDetailList
|
||||
} from "@/api/system/tenant";
|
||||
import useUserStore from '@/store/modules/user';
|
||||
|
||||
const router = useRouter();
|
||||
const { proxy } = getCurrentInstance();
|
||||
const { sys_normal_disable } = proxy.useDict("sys_normal_disable");
|
||||
const userStore = useUserStore();
|
||||
|
||||
const dynamicFormList = ref([]);
|
||||
// 当前租户信息
|
||||
@@ -345,25 +347,42 @@ async function handleSetOption(row) {
|
||||
currentTenantId.value = row.id;
|
||||
currentTenantName.value = row.tenantName;
|
||||
optionTitle.value = `基本配置`;
|
||||
// 重置表单
|
||||
resetOption();
|
||||
optionForm.tenantId = row.id;
|
||||
// 获取动态表单配置
|
||||
const formListRes = await getTenantOptionFormList();
|
||||
console.log('动态表单配置:', formListRes);
|
||||
dynamicFormList.value = formListRes.data || [];
|
||||
// 获取租户已有配置
|
||||
const detailRes = await getTenantOptionDetailList(row.id);
|
||||
if (detailRes.data) {
|
||||
dynamicFormList.value.forEach(item => {
|
||||
const existingConfig = detailRes.data.find(c => c.code === item.code);
|
||||
item.content = existingConfig ? existingConfig.content : '';
|
||||
console.log('租户已有配置:', detailRes);
|
||||
console.log('租户已有配置数据:', detailRes.data);
|
||||
|
||||
// 填充已有配置值
|
||||
if (detailRes.data && Array.isArray(detailRes.data)) {
|
||||
console.log('开始填充配置值,detailRes.data.length:', detailRes.data.length);
|
||||
console.log('dynamicFormList.value.length:', dynamicFormList.value.length);
|
||||
|
||||
// 将已有配置数据转为 Map 方便查找
|
||||
const configMap = {};
|
||||
detailRes.data.forEach(config => {
|
||||
configMap[config.code] = config.content || '';
|
||||
});
|
||||
|
||||
dynamicFormList.value.forEach(item => {
|
||||
const existingContent = configMap[item.code];
|
||||
console.log(`配置项 ${item.code}, 找到配置值:`, existingContent);
|
||||
item.content = existingContent || '';
|
||||
});
|
||||
console.log('填充后的dynamicFormList:', dynamicFormList.value);
|
||||
} else {
|
||||
console.log('detailRes.data 不是数组或为空,初始化空内容');
|
||||
// 初始化空内容
|
||||
dynamicFormList.value.forEach(item => {
|
||||
item.content = '';
|
||||
});
|
||||
}
|
||||
|
||||
// 设置表单数据
|
||||
optionForm.tenantId = row.id;
|
||||
optionOpen.value = true;
|
||||
} catch (error) {
|
||||
console.error('获取配置项失败:', error);
|
||||
@@ -384,8 +403,14 @@ async function submitOptionForm() {
|
||||
loading.value = true;
|
||||
const res = await saveTenantOptionDetailList(submitData);
|
||||
if (res.code === 200) {
|
||||
proxy.$modal.msgSuccess("配置保存成功");
|
||||
optionOpen.value = false;
|
||||
// 如果修改的是当前登录用户的租户配置,需要刷新用户信息
|
||||
if (userStore.tenantId === optionForm.tenantId) {
|
||||
await userStore.getInfo();
|
||||
proxy.$modal.msgSuccess("配置保存成功,用户信息已刷新");
|
||||
} else {
|
||||
proxy.$modal.msgSuccess("配置保存成功");
|
||||
}
|
||||
} else {
|
||||
proxy.$modal.msgError(res.msg || "配置保存失败");
|
||||
}
|
||||
@@ -397,9 +422,6 @@ async function submitOptionForm() {
|
||||
}
|
||||
/** 重置配置项表单 */
|
||||
function resetOption() {
|
||||
dynamicFormList.value.forEach(item => {
|
||||
item.content = '';
|
||||
});
|
||||
if (proxy.$refs["optionRef"]) {
|
||||
proxy.$refs["optionRef"].resetFields();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user