Files
his/sql/迁移记录-DB变更记录/手术管理页面代码修正方案.md

612 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 手术管理页面代码修正方案
根据详细设计文档,以下是手术管理页面的完整修正方案。
## 一、表格列定义修正
### 修改前:
```vue
<el-table v-loading="loading" :data="surgeryList" row-key="id">
<el-table-column label="手术编号" align="center" prop="surgeryNo" width="150" />
<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" />
<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" />
<el-table-column label="手术等级" align="center" prop="surgeryLevel_dictText" width="100" />
<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 />
<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="danger" @click="handleDelete(scope.row)" v-if="scope.row.statusEnum === 0 || scope.row.statusEnum === 1">删除</el-button>
</template>
</el-table-column>
</el-table>
```
### 修改后:
```vue
<!-- 添加 row-class-name 属性 -->
<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" />
<!-- 申请医生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 />
<!-- 手术等级string - 三级手术 - 不可操作 -->
<el-table-column label="手术等级" align="center" prop="surgeryLevel_dictText" width="100" />
<!-- 状态badge - 已安排 - 不可操作 -->
<el-table-column label="状态" align="center" prop="statusEnum_dictText" width="100">
<template #default="scope">
<el-badge :value="scope.row.statusEnum_dictText" :type="getStatusBadgeType(scope.row.statusEnum)" />
</template>
</el-table-column>
<!-- 操作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">编辑</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>
</el-table>
```
## 二、操作按钮逻辑修正
### 修改 handleEdit 函数:
```javascript
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)
}
}).catch(error => {
console.error('获取手术信息失败:', error)
proxy.$modal.msgError('获取手术信息失败')
})
}
```
### 修改 handleDelete 函数:
```javascript
function handleDelete(row) {
// 检查状态
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('当前状态不允许取消手术')
}
}
```
### 添加 getRowClassName 函数:
```javascript
// 获取表格行样式
function getRowClassName({ row }) {
return row.statusEnum === 4 ? 'cancelled-row' : ''
}
```
### 修改 submitForm 函数:
```javascript
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)
// 显示红色 toast 提示
proxy.$message.error('新增手术失败,请检查表单信息')
})
} else {
// 修改手术
updateSurgery(form.value).then((res) => {
proxy.$modal.msgSuccess('修改成功')
open.value = false
getPageList()
}).catch(error => {
console.error('更新手术失败:', error)
// 显示红色 toast 提示
proxy.$message.error('更新手术失败,请检查表单信息')
})
}
} else {
// 表单校验失败 - 显示红色 toast 提示
proxy.$message.error('请检查表单信息,标红字段为必填项')
}
})
}
```
### 修改 handleRefresh 函数:
```javascript
function handleRefresh() {
getPageList()
proxy.$modal.msgSuccess('刷新成功')
}
```
### 移除不需要的函数:
```javascript
// 删除这些函数(在新设计中不需要):
// - handleStart()
// - handleComplete()
```
## 三、表单字段调整(根据设计文档)
### 根据设计文档,表单应该包含:
#### 1. 患者基本信息区:
```vue
<el-divider content-position="left">患者基本信息</el-divider>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="手术单号" prop="surgeryNo">
<el-input v-model="form.surgeryNo" disabled placeholder="系统自动生成" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="患者姓名" prop="patientName">
<el-input v-model="form.patientName" disabled placeholder="系统自动获取" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="就诊卡号" prop="encounterNo">
<el-input v-model="form.encounterNo" disabled placeholder="系统自动获取" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="性别" prop="patientGender">
<el-select v-model="form.patientGender" disabled placeholder="系统自动获取">
<el-option label="男" value="1" />
<el-option label="女" value="2" />
<el-option label="其他" value="9" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="年龄" prop="patientAge">
<el-input-number v-model="form.patientAge" disabled placeholder="系统自动获取" />
</el-form-item>
</el-col>
</el-row>
```
#### 2. 手术信息区:
```vue
<el-divider content-position="left">手术信息</el-divider>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="手术类型" prop="surgeryTypeEnum">
<el-select v-model="form.surgeryTypeEnum" placeholder="请选择手术类型" style="width: 100%">
<el-option label="门诊手术" :value="1" />
<el-option label="日间手术" :value="2" />
<el-option label="急诊手术" :value="3" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="手术名称" prop="surgeryName">
<!-- 带搜索的手术字典库 -->
<el-input v-model="form.surgeryName" placeholder="请选择手术名称">
<template #append>
<el-button icon="Search" />
</template>
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="拟实施手术日期" prop="plannedTime">
<el-date-picker
v-model="form.plannedTime"
type="datetime"
placeholder="选择日期时间"
value-format="YYYY-MM-DD HH:mm:ss"
style="width: 100%"
/>
</el-form-item>
</el-col>
</el-row>
```
#### 3. 医疗信息区:
```vue
<el-divider content-position="left">医疗信息</el-divider>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="手术等级" prop="surgeryLevel">
<el-select v-model="form.surgeryLevel" placeholder="请选择手术等级" style="width: 100%">
<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-col>
<el-col :span="12">
<el-form-item label="切口类型" prop="incisionLevel">
<el-select v-model="form.incisionLevel" placeholder="请选择切口类型" style="width: 100%">
<el-option label="I类切口" :value="1" />
<el-option label="II类切口" :value="2" />
<el-option label="III类切口" :value="3" />
<el-option label="IV类切口" :value="4" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="麻醉方式" prop="anesthesiaTypeEnum">
<el-select v-model="form.anesthesiaTypeEnum" placeholder="请选择麻醉方式" style="width: 100%">
<el-option label="局麻" :value="1" />
<el-option label="全麻" :value="3" />
</el-select>
</el-form-item>
</el-col>
</el-row>
```
#### 4. 人员信息区:
```vue
<el-divider content-position="left">人员信息</el-divider>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="申请医生" prop="applyDoctorName">
<el-input v-model="form.applyDoctorName" disabled placeholder="系统自动获取" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="主刀医生" prop="mainSurgeonId">
<!-- 带搜索的医生字典库 -->
<el-select v-model="form.mainSurgeonId" filterable placeholder="请选择主刀医生" style="width: 100%">
<el-option
v-for="item in doctorList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="手术助手" prop="assistantId">
<!-- 带搜索的医生字典库 -->
<el-select v-model="form.assistantId" filterable clearable placeholder="请选择手术助手" style="width: 100%">
<el-option
v-for="item in doctorList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="申请科室" prop="applyDeptName">
<el-input v-model="form.applyDeptName" disabled placeholder="系统自动获取" />
</el-form-item>
</el-col>
</el-row>
```
#### 5. 其他信息区:
```vue
<el-divider content-position="left">其他信息</el-divider>
<el-form-item label="术前诊断" prop="preoperativeDiagnosis">
<el-input
v-model="form.preoperativeDiagnosis"
disabled
placeholder="自动获取门诊诊断的主要诊断名称"
type="textarea"
:rows="3"
/>
</el-form-item>
<el-form-item label="手术指征" prop="surgeryIndication">
<el-input
v-model="form.surgeryIndication"
placeholder="请输入手术指征"
type="textarea"
:rows="3"
/>
</el-form-item>
```
#### 6. 操作按钮区:
```vue
<el-row :gutter="20" justify="center">
<el-col :span="24">
<el-button type="default" @click="cancel" style="width: 120px">取消</el-button>
<el-button type="primary" @click="submitForm" style="width: 120px">提交申请</el-button>
<el-button type="success" icon="Plus" @click="addAppendSurgery">添加次要手术</el-button>
</el-col>
</el-row>
```
## 四、样式添加
```vue
<style scoped lang="scss">
/* 顶部操作栏样式 */
.top-operation-bar {
height: 60px;
display: flex;
align-items: center;
margin-bottom: 16px;
}
.add-button {
background-color: #5b8fb9;
color: white;
border-radius: 8px;
padding: 0 20px;
&:hover {
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(91, 143, 185, 0.3);
}
}
.refresh-button {
background-color: transparent;
border: 1px solid #dcdfe6;
color: #606266;
border-radius: 8px;
padding: 0 20px;
&:hover {
background-color: #f5f7fa;
}
}
/* 表格样式 */
.surgery-table {
width: 100%;
::v-deep(.el-badge__content) {
background-color: #f0f2f5;
border: 1px solid #e4e7ed;
color: #606266;
padding: 4px 12px;
border-radius: 4px;
}
}
/* 已取消状态的行样式 */
.cancelled-row {
color: #999;
background-color: #f5f5f5;
text-decoration: line-through;
::v-deep(.cell) {
opacity: 0.6;
}
}
/* 对话框样式 */
.el-dialog {
border-radius: 12px;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
}
.dialog-footer {
text-align: center;
padding: 20px 0;
}
</style>
```
## 五、添加辅助函数
```javascript
// 获取状态 badge 类型
function getStatusBadgeType(status) {
const typeMap = {
0: 'info', // 新开
1: 'warning', // 已安排
2: 'primary', // 手术中
3: 'success', // 已完成
4: 'danger', // 已取消
5: 'info' // 暂停
}
return typeMap[status] || 'info'
}
// 添加次要手术
function addAppendSurgery() {
// 打开次要手术选择弹窗
proxy.$modal.msgInfo('请选择次要手术')
// TODO: 实现次要手术选择逻辑
}
// 生成手术单号
function generateSurgeryNo() {
const now = new Date()
const year = now.getFullYear()
const month = String(now.getMonth() + 1).padStart(2, '0')
const day = String(now.getDate()).padStart(2, '0')
const random = String(Math.floor(Math.random() * 10000)).padStart(4, '0')
return `OP${year}${month}${day}${random}`
}
```
## 六、完整修正步骤总结
### 步骤1修改表格结构
1. 调整表格列顺序和内容
2. 添加 `row-class-name` 属性
3. 修改操作列的条件判断
### 步骤2修改 JavaScript 函数
1. 修改 `handleEdit()` - 添加状态检查
2. 修改 `handleDelete()` - 区分删除和取消
3. 修改 `submitForm()` - 改进错误提示
4. 添加 `getRowClassName()` - 行样式判断
5. 修改 `handleRefresh()` - 添加成功提示
6. 移除 `handleStart()``handleComplete()` - 新设计不需要
### 步骤3修改表单结构
1. 调整表单分组(添加 divider
2. 添加患者基本信息区(大部分字段禁用)
3. 添加手术信息区
4. 添加医疗信息区
5. 添加人员信息区
6. 添加其他信息区
7. 修改操作按钮(添加次要手术按钮)
### 步骤4添加样式
1. 顶部操作栏样式
2. 表格样式
3. 已取消状态行样式
4. 对话框样式
### 步骤5添加辅助函数
1. `getStatusBadgeType()` - 状态 badge 类型
2. `addAppendSurgery()` - 添加次要手术
3. `generateSurgeryNo()` - 生成手术单号
## 七、后端接口需求
根据设计文档,提交手术申请时需要:
1. **插入 outp_surgery_apply门诊手术申请主表**
2. **通过系统自动插入一条手术申请医嘱**
3. **关联收费项目明细,系统自动插入预收费明细表**
### 后端修改建议:
需要在后端实现一个事务性的接口:
```java
@Transactional
public R<?> submitSurgeryApply(SurgeryApplyDto dto) {
// 1. 插入门诊手术申请主表
// 2. 自动生成手术单号OP+年月日+4位随机数
// 3. 自动插入手术申请医嘱
// 4. 关联收费项目明细
// 5. 插入预收费明细表
return R.ok();
}
```
## 八、测试要点
1. **新增手术申请**
- 检查手术单号是否自动生成
- 检查患者信息是否自动填充
- 检查医生信息是否自动获取
2. **编辑手术申请**
- 只允许新开状态编辑
- 其他状态应提示不可编辑
3. **删除/取消手术申请**
- 新开状态应直接删除
- 已安排状态应更新为已取消
- 取消后行样式应变灰
4. **查看手术详情**
- 显示所有字段
- 提交按钮变为关闭
5. **错误处理**
- 表单校验失败显示红色 toast
- 数据加载失败显示"数据加载失败"