会诊管理中 门诊会诊申请确认和门诊会诊申请管理模块全部功能的实现。包括数据库设计,前端UI设计,后端接口开发。

This commit is contained in:
weixin_45799331
2026-02-11 13:40:32 +08:00
parent b826afb17c
commit c5d75f053b
25 changed files with 3249 additions and 365 deletions

View File

@@ -86,6 +86,19 @@ function resolvePath(routePath, routeQuery) {
return props.basePath
}
if (routeQuery) {
try {
// 检查 routeQuery 是否已经是对象
if (typeof routeQuery === 'object') {
return { path: getNormalPath(props.basePath + '/' + routePath), query: routeQuery }
}
// 尝试解析 JSON 字符串
let query = JSON.parse(routeQuery);
return { path: getNormalPath(props.basePath + '/' + routePath), query: query }
} catch (e) {
// 如果解析失败,将其作为普通字符串处理
console.warn('Failed to parse routeQuery as JSON:', routeQuery, e);
return getNormalPath(props.basePath + '/' + routePath)
}
try {
let query = JSON.parse(routeQuery);
return { path: getNormalPath(props.basePath + '/' + routePath), query: query }
@@ -93,6 +106,19 @@ function resolvePath(routePath, routeQuery) {
console.error('Failed to parse routeQuery:', routeQuery, e);
return getNormalPath(props.basePath + '/' + routePath)
}
try {
// 检查 routeQuery 是否已经是对象
if (typeof routeQuery === 'object') {
return { path: getNormalPath(props.basePath + '/' + routePath), query: routeQuery }
}
// 尝试解析 JSON 字符串
let query = JSON.parse(routeQuery);
return { path: getNormalPath(props.basePath + '/' + routePath), query: query }
} catch (e) {
// 如果解析失败,将其作为普通字符串处理
console.warn('Failed to parse routeQuery as JSON:', routeQuery, e);
return getNormalPath(props.basePath + '/' + routePath)
}
}
return getNormalPath(props.basePath + '/' + routePath)
}

View File

@@ -237,6 +237,21 @@ export const dynamicRoutes = [
},
],
},
{
path: '/doctorstation',
component: Layout,
redirect: '/doctorstation/index',
name: 'DoctorStation',
meta: { title: '医生工作站', icon: 'operation' },
children: [
{
path: 'pending-emr',
component: () => import('@/views/doctorstation/pendingEmr.vue'),
name: 'PendingEmr',
meta: { title: '待写病历', icon: 'document', permissions: ['doctorstation:pending-emr:view'] }
}
]
},
{
path: '/features',
component: Layout,
@@ -298,6 +313,40 @@ export const dynamicRoutes = [
meta: { title: '门诊日结', icon: 'document' }
}
]
},
{
path: '/consultationmanagement',
component: Layout,
name: 'ConsultationManagement',
meta: { title: '会诊管理', icon: 'operation' },
children: [
{
path: 'consultationapplication',
component: () => import('@/views/consultationmanagement/consultationapplication/index.vue'),
name: 'ConsultationApplication',
meta: { title: '门诊会诊申请管理', icon: 'document' }
},
{
path: 'consultationconfirmation',
component: () => import('@/views/consultationmanagement/consultationconfirmation/index.vue'),
name: 'ConsultationConfirmation',
meta: { title: '门诊会诊申请确认', icon: 'document' }
}
]
},
{
path: '/medicationmanagement',
component: Layout,
name: 'MedicationManagement',
meta: { title: '药房管理', icon: 'medication' },
children: [
{
path: 'dayEndSettlement',
component: () => import('@/views/medicationmanagement/dayEndSettlement/index.vue'),
name: 'DayEndSettlement',
meta: { title: '日结结算单管理', icon: 'document' }
}
]
}
];

View File

@@ -0,0 +1,125 @@
import request from '@/utils/request'
/**
* 获取会诊申请列表(简单查询)
* @param {Object} params 查询参数
*/
export function getConsultationList(params) {
return request({
url: '/consultation/list',
method: 'get',
params
})
}
/**
* 查询会诊申请列表(支持多条件查询)
* @param {Object} data 查询条件
*/
export function queryConsultationList(data) {
return request({
url: '/consultation/query',
method: 'post',
data
})
}
/**
* 分页查询会诊申请列表(支持多条件查询)
* @param {Object} data 查询条件
* @param {Number} pageNum 页码
* @param {Number} pageSize 每页大小
*/
export function queryConsultationListPage(data, pageNum, pageSize) {
return request({
url: '/consultation/queryPage',
method: 'post',
data,
params: { pageNum, pageSize },
headers: {
repeatSubmit: false // 关键:告诉后端不要进行防重复提交检查
}
})
}
/**
* 保存会诊申请(新增或修改)
* @param {Object} data 会诊申请数据
*/
export function saveConsultation(data) {
return request({
url: '/consultation/save',
method: 'post',
data
})
}
/**
* 提交会诊申请
* @param {String} consultationId 会诊申请单号
*/
export function submitConsultation(consultationId) {
return request({
url: '/consultation/submit',
method: 'post',
params: { consultationId }
})
}
/**
* 作废会诊申请
* @param {String} consultationId 会诊申请单号
* @param {String} cancelReason 作废原因
*/
export function cancelConsultation(consultationId, cancelReason) {
return request({
url: '/consultation/cancel',
method: 'post',
params: { consultationId, cancelReason }
})
}
/**
* 结束会诊申请
* @param {String} consultationId 会诊申请单号
*/
export function completeConsultation(consultationId) {
return request({
url: '/consultation/complete',
method: 'post',
params: { consultationId }
})
}
/**
* 获取科室医生树
*/
export function getDepartmentTree() {
return request({
url: '/consultation/departmentTree',
method: 'get'
})
}
/**
* 获取主诊断
* @param {Number} encounterId 就诊ID
*/
export function getMainDiagnosis(encounterId) {
return request({
url: '/consultation/mainDiagnosis',
method: 'get',
params: { encounterId }
})
}
/**
* 获取会诊项目列表
*/
export function getConsultationActivities() {
return request({
url: '/consultation/activities',
method: 'get'
})
}

View File

@@ -0,0 +1,743 @@
<template>
<div class="consultation-application-container">
<!-- 页面标题 -->
<div class="page-header">
<span class="tab-title">门诊会诊申请管理</span>
</div>
<!-- 查询条件 -->
<div class="search-section">
<el-form :model="queryParams" inline>
<el-form-item label="时间类型">
<el-select v-model="queryParams.timeType" placeholder="请选择" style="width: 120px">
<el-option label="会诊时间" value="consultation" />
<el-option label="开始时间" value="start" />
<el-option label="结束时间" value="end" />
</el-select>
</el-form-item>
<el-form-item label="开始时间">
<el-date-picker
v-model="queryParams.startTime"
type="datetime"
placeholder="年/月/日 --:--"
format="YYYY/MM/DD HH:mm"
value-format="YYYY-MM-DD HH:mm:ss"
style="width: 180px"
/>
</el-form-item>
<el-form-item label="结束时间">
<el-date-picker
v-model="queryParams.endTime"
type="datetime"
placeholder="年/月/日 --:--"
format="YYYY/MM/DD HH:mm"
value-format="YYYY-MM-DD HH:mm:ss"
style="width: 180px"
/>
</el-form-item>
<el-form-item label="申请科室">
<el-input
v-model="queryParams.applyDept"
placeholder="请输入或输入科室"
clearable
style="width: 150px"
/>
</el-form-item>
<el-form-item label="申请医生">
<el-input
v-model="queryParams.applyDoctor"
placeholder="请输入或输入医生"
clearable
style="width: 150px"
/>
</el-form-item>
<el-form-item label="紧急程度">
<el-select v-model="queryParams.urgency" placeholder="全部" style="width: 120px">
<el-option label="全部" value="" />
<el-option label="一般" value="1" />
<el-option label="紧急" value="2" />
</el-select>
</el-form-item>
<el-form-item label="会诊状态">
<el-select v-model="queryParams.consultationStatus" placeholder="全部" style="width: 120px">
<el-option label="全部" value="" />
<el-option label="未提交" value="0" />
<el-option label="提交" value="10" />
<el-option label="结束" value="40" />
</el-select>
</el-form-item>
<el-form-item label="病人姓名">
<el-input
v-model="queryParams.patientName"
placeholder="请输入病人姓名"
clearable
style="width: 150px"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleQuery">
<el-icon><Search /></el-icon> 查询
</el-button>
<el-button @click="handleReset">
<el-icon><Refresh /></el-icon> 重置
</el-button>
<el-button type="success" @click="handlePrint">
<el-icon><Printer /></el-icon> 打印
</el-button>
</el-form-item>
</el-form>
</div>
<!-- 数据表格 -->
<div class="table-section">
<el-table
:data="tableData"
border
stripe
highlight-current-row
@current-change="handleRowChange"
v-loading="loading"
height="400"
>
<el-table-column type="index" label="ID" width="60" align="center" />
<el-table-column label="急" width="60" align="center">
<template #default="scope">
<el-checkbox :model-value="scope.row.consultationUrgency === '2'" disabled />
</template>
</el-table-column>
<el-table-column prop="patientName" label="病人姓名" min-width="100" />
<el-table-column prop="consultationDate" label="会诊时间" min-width="160">
<template #default="scope">
{{ formatDateTime(scope.row.consultationDate) }}
</template>
</el-table-column>
<el-table-column prop="department" label="申请科室" min-width="120" />
<el-table-column prop="invitedObject" label="邀请对象" min-width="150" show-overflow-tooltip />
<el-table-column prop="consultationRequestDate" label="申请时间" min-width="160">
<template #default="scope">
{{ formatDateTime(scope.row.consultationRequestDate) }}
</template>
</el-table-column>
<el-table-column prop="requestingPhysician" label="申请医师" min-width="100" />
<el-table-column label="提交" width="70" align="center">
<template #default="scope">
<el-checkbox :model-value="scope.row.consultationStatus >= 10" disabled />
</template>
</el-table-column>
<el-table-column label="结束" width="70" align="center">
<template #default="scope">
<el-checkbox :model-value="scope.row.consultationStatus >= 40" disabled />
</template>
</el-table-column>
<el-table-column label="操作" width="200" fixed="right" align="center">
<template #default="scope">
<el-button
type="primary"
size="small"
:icon="Edit"
@click="handleEdit(scope.row)"
:disabled="scope.row.consultationStatus >= 40"
title="编辑"
/>
<el-button
type="info"
size="small"
:icon="View"
@click="handleView(scope.row)"
title="查看"
/>
<el-button
type="danger"
size="small"
:icon="Delete"
@click="handleDelete(scope.row)"
:disabled="scope.row.consultationStatus >= 40"
title="作废"
/>
</template>
</el-table-column>
</el-table>
<!-- 分页组件 -->
<div class="pagination-container">
<el-pagination
v-model:current-page="pagination.currentPage"
v-model:page-size="pagination.pageSize"
:page-sizes="[10, 20, 30, 50, 100]"
:total="pagination.total"
:disabled="loading"
layout="total, sizes, prev, pager, next, jumper"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</div>
<!-- 编辑/查看弹窗 -->
<el-dialog
v-model="dialogVisible"
:title="dialogTitle"
width="800px"
:close-on-click-modal="false"
@close="handleDialogClose"
>
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="120px"
:disabled="isViewMode"
>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="申请单号">
<el-input v-model="formData.consultationId" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="申请时间">
<el-input :model-value="formatDateTime(formData.consultationRequestDate)" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="病人姓名">
<el-input v-model="formData.patientName" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="性别">
<el-input :model-value="formData.genderEnum === 1 ? '男' : '女'" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="年龄">
<el-input v-model="formData.age" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="就诊卡号">
<el-input v-model="formData.patientIdentifierNo" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="申请医师" prop="requestingPhysician">
<el-input v-model="formData.requestingPhysician" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="会诊时间" prop="consultationDate">
<el-date-picker
v-model="formData.consultationDate"
type="datetime"
placeholder="// --:--"
format="YYYY/MM/DD HH:mm"
value-format="YYYY-MM-DD HH:mm:ss"
style="width: 100%"
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="申请科室">
<el-input v-model="formData.department" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="门诊诊断">
<el-input v-model="formData.provisionalDiagnosis" />
</el-form-item>
</el-col>
</el-row>
<el-form-item label="患者病史及会诊目的" prop="consultationPurpose">
<el-input
v-model="formData.consultationPurpose"
type="textarea"
:rows="4"
placeholder="请输入患者病史及会诊目的"
/>
</el-form-item>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="会诊邀请对象">
<el-input v-model="formData.invitedObject" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="会诊邀请参加医师">
<el-input placeholder="请输入参加医师姓名" disabled />
</el-form-item>
</el-col>
</el-row>
<div class="section-title">会诊记录</div>
<el-form-item label="会诊意见">
<el-input
v-model="formData.consultationOpinion"
type="textarea"
:rows="4"
placeholder="会诊意见"
disabled
/>
</el-form-item>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="所属医生">
<el-input v-model="formData.attendingPhysician" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="代表科室">
<el-input v-model="formData.representDepartment" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="签名医生">
<el-input v-model="formData.signPhysician" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="签名时间">
<el-date-picker
v-model="formData.signTime"
type="datetime"
placeholder="// --:--"
format="YYYY/MM/DD HH:mm"
disabled
style="width: 100%"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">{{ isViewMode ? '关闭' : '取消' }}</el-button>
<el-button v-if="!isViewMode" type="primary" @click="handleSave" :loading="saving">
保存
</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup name="ConsultationApplication">
import { ref, reactive, onMounted, computed } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Search, Refresh, Printer, Edit, View, Delete } from '@element-plus/icons-vue'
import { queryConsultationListPage, cancelConsultation, saveConsultation } from './api'
const loading = ref(false)
const saving = ref(false)
const tableData = ref([])
const currentRow = ref(null)
const dialogVisible = ref(false)
const isViewMode = ref(false)
const formRef = ref(null)
// 用于取消请求的控制器
let abortController = null
// 分页参数
const pagination = reactive({
currentPage: 1,
pageSize: 10,
total: 0
})
const queryParams = reactive({
timeType: 'consultation',
startTime: '',
endTime: '',
applyDept: '',
applyDoctor: '',
urgency: '',
consultationStatus: '',
patientName: ''
})
const formData = ref({
id: null,
consultationId: '',
patientName: '',
genderEnum: null,
age: null,
patientIdentifierNo: '',
requestingPhysician: '',
consultationDate: '',
department: '',
provisionalDiagnosis: '',
consultationPurpose: '',
invitedObject: '',
consultationOpinion: '',
attendingPhysician: '',
representDepartment: '',
signPhysician: '',
signTime: null,
consultationRequestDate: null
})
const formRules = {
requestingPhysician: [
{ required: true, message: '请输入申请医师', trigger: 'blur' }
],
consultationDate: [
{ required: true, message: '请选择会诊时间', trigger: 'change' }
],
consultationPurpose: [
{ required: true, message: '请输入患者病史及会诊目的', trigger: 'blur' }
]
}
const dialogTitle = computed(() => {
return isViewMode.value ? '会诊申请查看' : '会诊申请编辑'
})
const formatDateTime = (date) => {
if (!date) return ''
const d = new Date(date)
if (isNaN(d.getTime())) return ''
const pad = (value) => String(value).padStart(2, '0')
const yyyy = d.getFullYear()
const mm = pad(d.getMonth() + 1)
const dd = pad(d.getDate())
const hh = pad(d.getHours())
const mi = pad(d.getMinutes())
const ss = pad(d.getSeconds())
return `${yyyy}-${mm}-${dd} ${hh}:${mi}:${ss}`
}
const handleQuery = async () => {
// 验证时间范围
if (queryParams.startTime && queryParams.endTime) {
const start = new Date(queryParams.startTime)
const end = new Date(queryParams.endTime)
if (end < start) {
ElMessage.warning('结束时间不能早于开始时间')
return
}
}
// 重置到第一页
pagination.currentPage = 1
await loadData()
}
const handleReset = () => {
Object.keys(queryParams).forEach(key => {
if (key === 'timeType') {
queryParams[key] = 'consultation'
} else {
queryParams[key] = ''
}
})
pagination.currentPage = 1
loadData()
}
const handleSizeChange = (val) => {
pagination.pageSize = val
pagination.currentPage = 1
loadData()
}
const handleCurrentChange = (val) => {
// 如果正在加载,忽略此次操作
if (loading.value) {
return
}
pagination.currentPage = val
loadData()
}
const handlePrint = () => {
if (!currentRow.value) {
ElMessage.warning('请先选择一条记录')
return
}
window.print()
}
const handleRowChange = (row) => {
currentRow.value = row
}
const handleEdit = (row) => {
// 检查是否已结束
if (row.consultationStatus >= 40) {
ElMessage.warning('已结束的会诊申请不可编辑')
return
}
isViewMode.value = false
formData.value = { ...row }
dialogVisible.value = true
}
const handleView = (row) => {
isViewMode.value = true
formData.value = { ...row }
dialogVisible.value = true
}
const handleDialogClose = () => {
formRef.value?.clearValidate()
formData.value = {
id: null,
consultationId: '',
patientName: '',
genderEnum: null,
age: null,
patientIdentifierNo: '',
requestingPhysician: '',
consultationDate: '',
department: '',
provisionalDiagnosis: '',
consultationPurpose: '',
invitedObject: '',
consultationOpinion: '',
attendingPhysician: '',
representDepartment: '',
signPhysician: '',
signTime: null,
consultationRequestDate: null
}
}
const handleSave = async () => {
try {
// 表单验证
await formRef.value.validate()
saving.value = true
const res = await saveConsultation(formData.value)
if (res.code === 200) {
ElMessage.success('保存成功')
dialogVisible.value = false
await loadData()
} else {
ElMessage.error(res.msg || '保存失败,请重试')
}
} catch (error) {
if (error !== 'cancel') {
console.error('保存失败:', error)
ElMessage.error('保存失败,请重试')
}
} finally {
saving.value = false
}
}
const handleDelete = async (row) => {
// 检查是否已结束
if (row.consultationStatus >= 40) {
ElMessage.warning('已结束的会诊申请不可作废')
return
}
try {
await ElMessageBox.confirm('确定要作废该会诊申请吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
loading.value = true
const res = await cancelConsultation(row.consultationId, '用户作废')
if (res.code === 200) {
ElMessage.success('作废成功')
await loadData()
} else {
ElMessage.error(res.msg || '作废失败')
}
} catch (error) {
if (error !== 'cancel') {
console.error('作废失败:', error)
ElMessage.error('作废失败')
}
} finally {
loading.value = false
}
}
const loadData = async () => {
// 如果正在加载,取消上一个请求
if (loading.value && abortController) {
abortController.abort()
}
try {
loading.value = true
// 创建新的 AbortController
abortController = new AbortController()
// 构建查询参数
const queryData = {
department: queryParams.applyDept,
requestingPhysician: queryParams.applyDoctor,
consultationStatus: queryParams.consultationStatus,
patientName: queryParams.patientName,
consultationRequestDate: queryParams.startTime,
consultationUrgency: queryParams.urgency
}
console.log('查询参数:', queryData, '页码:', pagination.currentPage, '每页:', pagination.pageSize)
const res = await queryConsultationListPage(queryData, pagination.currentPage, pagination.pageSize)
console.log('查询结果:', res)
if (res.code === 200) {
tableData.value = res.data.records || []
pagination.total = res.data.total || 0
// 如果没有查询结果,显示提示
if (tableData.value.length === 0 && pagination.currentPage === 1) {
ElMessage.info('暂无查询结果')
}
} else {
// 忽略"数据正在处理"的错误提示
if (!res.msg || !res.msg.includes('数据正在处理')) {
ElMessage.error(res.msg || '加载数据失败')
}
tableData.value = []
pagination.total = 0
}
} catch (error) {
// 忽略取消请求的错误
if (error.name === 'AbortError' || error.name === 'CanceledError') {
console.log('请求已取消')
return
}
console.error('加载数据失败:', error)
// 忽略"数据正在处理"的错误提示
const errorMsg = error.message || error.msg || '网络错误'
if (!errorMsg.includes('数据正在处理')) {
ElMessage.error('加载数据失败: ' + errorMsg)
}
tableData.value = []
pagination.total = 0
} finally {
loading.value = false
abortController = null
}
}
onMounted(() => {
loadData()
})
</script>
<style scoped>
.consultation-application-container {
padding: 20px;
background: #fff;
min-height: calc(100vh - 84px);
}
.page-header {
padding-bottom: 12px;
border-bottom: 2px solid #e5e7eb;
margin-bottom: 20px;
}
.tab-title {
display: inline-block;
font-size: 18px;
font-weight: 700;
color: #2563eb;
border-bottom: 3px solid #2563eb;
padding-bottom: 8px;
}
.search-section {
margin-bottom: 20px;
padding: 16px;
background: #f9fafb;
border-radius: 8px;
}
.table-section {
margin-top: 20px;
}
.pagination-container {
margin-top: 16px;
display: flex;
justify-content: flex-end;
}
.section-title {
font-size: 16px;
font-weight: 600;
color: #333;
margin: 20px 0 16px 0;
padding-bottom: 8px;
border-bottom: 2px solid #e5e7eb;
}
.dialog-footer {
display: flex;
justify-content: flex-end;
gap: 12px;
}
@media print {
.search-section,
.pagination-container,
.el-table__column--selection,
.el-table-column--action {
display: none !important;
}
}
/* 表单样式优化 */
:deep(.el-form-item__label) {
font-weight: 500;
color: #606266;
}
:deep(.el-input.is-disabled .el-input__inner) {
background-color: #f5f7fa;
color: #909399;
}
:deep(.el-textarea.is-disabled .el-textarea__inner) {
background-color: #f5f7fa;
color: #909399;
}
</style>

View File

@@ -0,0 +1,74 @@
import request from '@/utils/request'
/**
* 获取待确认的会诊列表(当前医生被邀请的会诊)
*/
export function getPendingConfirmationList() {
return request({
url: '/consultation/confirmation/pending',
method: 'get'
})
}
/**
* 确认会诊
* @param {Object} data 会诊确认数据
*/
export function confirmConsultation(data) {
return request({
url: '/consultation/confirmation/confirm',
method: 'post',
data
})
}
/**
* 取消确认会诊
* @param {String} consultationId 会诊申请单号
*/
export function cancelConfirmation(consultationId) {
return request({
url: '/consultation/confirmation/cancelConfirm',
method: 'post',
params: { consultationId }
})
}
/**
* 签名会诊
* @param {String} consultationId 会诊申请单号
*/
export function signConsultation(consultationId) {
return request({
url: '/consultation/confirmation/sign',
method: 'post',
params: { consultationId }
})
}
/**
* 获取会诊确认详情
* @param {String} consultationId 会诊申请单号
*/
export function getConfirmationDetail(consultationId) {
return request({
url: '/consultation/confirmation/detail',
method: 'get',
params: { consultationId }
})
}
/**
* 获取会诊意见列表
* @param {String} consultationId 会诊申请单号
*/
export function getConsultationOpinions(consultationId) {
return request({
url: '/consultation/confirmation/opinions',
method: 'get',
params: { consultationId }
})
}

View File

@@ -30,28 +30,37 @@
stripe
highlight-current-row
@current-change="handleRowChange"
v-loading="loading"
>
<el-table-column type="index" width="60" label="序号" align="center" />
<el-table-column label="紧急" width="70" align="center">
<template #default="scope">
<el-checkbox v-model="scope.row.urgent" />
<el-checkbox v-model="scope.row.urgent" disabled />
</template>
</el-table-column>
<el-table-column prop="consultationId" label="申请单号" min-width="160" />
<el-table-column prop="patientName" label="病人姓名" min-width="100" />
<el-table-column prop="consultationTime" label="会诊时间" min-width="160" />
<el-table-column prop="invitee" label="邀请对象" min-width="120" />
<el-table-column prop="consultationDate" label="会诊时间" min-width="160">
<template #default="scope">
{{ formatDateTime(scope.row.consultationDate) }}
</template>
</el-table-column>
<el-table-column prop="invitedObject" label="邀请对象" min-width="120" />
<el-table-column prop="applyDept" label="申请科室" min-width="120" />
<el-table-column prop="applyDoctor" label="申请医师" min-width="120" />
<el-table-column prop="applyTime" label="申请时间" min-width="160" />
<el-table-column prop="applyTime" label="申请时间" min-width="160">
<template #default="scope">
{{ formatDateTime(scope.row.applyTime) }}
</template>
</el-table-column>
<el-table-column label="确认" width="70" align="center">
<template #default="scope">
<el-checkbox v-model="scope.row.confirmed" disabled />
<el-checkbox :model-value="scope.row.myInvitedStatus >= 20" disabled />
</template>
</el-table-column>
<el-table-column label="签名" width="70" align="center">
<template #default="scope">
<el-checkbox v-model="scope.row.signed" disabled />
<el-checkbox :model-value="scope.row.myInvitedStatus >= 30" disabled />
</template>
</el-table-column>
</el-table>
@@ -68,7 +77,7 @@
</el-col>
<el-col :span="6">
<el-form-item label="性别">
<el-input v-model="formData.gender" disabled />
<el-input v-model="formData.genderText" disabled />
</el-form-item>
</el-col>
<el-col :span="6">
@@ -78,7 +87,7 @@
</el-col>
<el-col :span="6">
<el-form-item label="就诊卡号">
<el-input v-model="formData.cardNo" disabled />
<el-input v-model="formData.patientIdentifierNo" disabled />
</el-form-item>
</el-col>
<el-col :span="6">
@@ -93,7 +102,7 @@
</el-col>
<el-col :span="6">
<el-form-item label="会诊时间">
<el-input v-model="formData.consultationTime" disabled />
<el-input :model-value="formatDateTime(formData.consultationDate)" disabled />
</el-form-item>
</el-col>
<el-col :span="6">
@@ -103,52 +112,92 @@
</el-col>
<el-col :span="6">
<el-form-item label="会诊邀请对象">
<el-input v-model="formData.invitee" disabled />
<el-input v-model="formData.invitedObject" disabled />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="提交医生">
<el-input v-model="formData.applyDoctor" disabled />
<el-input v-model="formData.submittingPhysician" disabled />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="提交时间">
<el-input v-model="formData.applyTime" disabled />
<el-input :model-value="formatDateTime(formData.submittingTime)" disabled />
</el-form-item>
</el-col>
</el-row>
<el-form-item label="病史及目的">
<el-input v-model="formData.history" type="textarea" :rows="3" disabled />
<el-input v-model="formData.consultationPurpose" type="textarea" :rows="3" disabled />
</el-form-item>
<el-form-item label="会诊确认参加医师" required>
<el-input v-model="formData.confirmingPhysician" placeholder="请输入会诊确认参加医师" />
<el-form-item label="门诊诊断">
<el-input v-model="formData.provisionalDiagnosis" type="textarea" :rows="2" disabled />
</el-form-item>
<el-form-item label="会诊意见" required>
<el-input v-model="formData.opinion" type="textarea" :rows="4" placeholder="请输入会诊意见" />
<el-input
v-model="formData.consultationOpinion"
type="textarea"
:rows="4"
placeholder="请输入会诊意见"
:disabled="!canEdit"
/>
</el-form-item>
<!-- 会诊意见列表 -->
<el-form-item label="所有会诊意见">
<div class="opinions-container">
<el-timeline v-if="opinionList.length > 0">
<el-timeline-item
v-for="opinion in opinionList"
:key="opinion.physicianId"
:timestamp="formatDateTime(opinion.confirmTime)"
placement="top"
>
<el-card shadow="hover">
<div class="opinion-header">
<span class="physician-info">
<el-tag type="info" size="small">{{ opinion.deptName }}</el-tag>
<span style="margin-left: 8px; font-weight: bold;">{{ opinion.physicianName }}</span>
</span>
<el-tag v-if="opinion.isSigned" type="success" size="small">
<el-icon><Check /></el-icon> 已签名
</el-tag>
<el-tag v-else type="warning" size="small">已确认</el-tag>
</div>
<div class="opinion-content">
{{ opinion.opinion }}
</div>
<div v-if="opinion.signatureTime" class="opinion-footer">
签名时间:{{ formatDateTime(opinion.signatureTime) }}
</div>
</el-card>
</el-timeline-item>
</el-timeline>
<el-empty v-else description="暂无会诊意见" :image-size="80" />
</div>
</el-form-item>
<el-row :gutter="16">
<el-col :span="6">
<el-form-item label="所属医生">
<el-input v-model="formData.confirmDoctor" disabled />
<el-input v-model="formData.confirmingPhysicianName" disabled />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="代表科室">
<el-input v-model="formData.confirmDept" disabled />
<el-input v-model="formData.confirmingDeptName" disabled />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="签名医生">
<el-input v-model="formData.signDoctor" disabled />
<el-input v-model="formData.signature" disabled />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="签名时间">
<el-input v-model="formData.signTime" disabled />
<el-input :model-value="formatDateTime(formData.signatureDate)" disabled />
</el-form-item>
</el-col>
</el-row>
@@ -158,94 +207,85 @@
</template>
<script setup name="consultationConfirmation">
import { computed, ref } from 'vue'
import { ElMessage } from 'element-plus'
import { computed, ref, onMounted, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Check } from '@element-plus/icons-vue'
import useUserStore from '@/store/modules/user'
import {
getPendingConfirmationList,
confirmConsultation,
cancelConfirmation,
signConsultation,
getConsultationOpinions
} from './api'
const userStore = useUserStore()
const buildMockRows = () => ([
{
consultationId: 'CS20250812001',
urgent: false,
patientName: '陈明',
gender: '男',
age: '45',
cardNo: 'CARD20250812001',
consultationTime: '2025-08-12 17:48',
invitee: '演示测试',
applyDept: '内科',
applyDoctor: '徐斌',
applyTime: '2025-08-12 16:30',
history: '胸闷、气短一周,既往有高血压史。',
confirmingPhysician: '',
opinion: '',
confirmed: false,
signed: false
},
{
consultationId: 'CS20250812002',
urgent: true,
patientName: '赵敏',
gender: '女',
age: '32',
cardNo: 'CARD20250812002',
consultationTime: '2025-08-12 18:10',
invitee: '李医生',
applyDept: '神经内科',
applyDoctor: '王婷',
applyTime: '2025-08-12 16:50',
history: '头晕伴视物模糊3天。',
confirmingPhysician: '',
opinion: '',
confirmed: false,
signed: false
}
])
const tableData = ref(buildMockRows())
const loading = ref(false)
const tableData = ref([])
const currentRow = ref(null)
const opinionList = ref([]) // 会诊意见列表
const formData = ref({
id: null,
consultationRequestId: null,
consultationId: '',
urgent: false,
patientName: '',
gender: '',
genderText: '',
age: '',
cardNo: '',
consultationTime: '',
invitee: '',
patientIdentifierNo: '',
applyDept: '',
applyDoctor: '',
applyTime: '',
history: '',
applyTime: null,
consultationDate: null,
urgent: false,
invitedObject: '',
consultationPurpose: '',
provisionalDiagnosis: '',
confirmingPhysician: '',
opinion: '',
confirmDoctor: '',
confirmDept: '',
signDoctor: '',
signTime: ''
consultationOpinion: '',
confirmingPhysicianName: '',
confirmingDeptName: '',
signature: '',
signatureDate: null,
submittingPhysician: '',
submittingTime: null,
consultationStatus: 0
})
const confirmButtonText = computed(() => {
if (!currentRow.value) {
return '确认'
}
return currentRow.value.confirmed ? '取消确认' : '确认'
// 基于当前医生的个人状态判断使用ConsultationStatusEnum20=已确认)
return currentRow.value.myInvitedStatus >= 20 ? '取消确认' : '确认'
})
const canSign = computed(() => {
return !!currentRow.value && currentRow.value.confirmed && !currentRow.value.signed
// 只要当前医生已确认但未签名,就可以签名(不需要等待所有医生都确认)
// 使用ConsultationStatusEnum20=已确认30=已签名
return !!currentRow.value &&
currentRow.value.myInvitedStatus >= 20 && // 已确认
currentRow.value.myInvitedStatus < 30 // 但还未签名
})
const formatDateTime = (date = new Date()) => {
const canEdit = computed(() => {
// 当前医生未确认时可以编辑使用ConsultationStatusEnum10=已提交/待确认20=已确认)
return !!currentRow.value && (!currentRow.value.myInvitedStatus || currentRow.value.myInvitedStatus < 20)
})
const formatDateTime = (date) => {
if (!date) return ''
const d = new Date(date)
if (isNaN(d.getTime())) return ''
const pad = (value) => String(value).padStart(2, '0')
const yyyy = date.getFullYear()
const mm = pad(date.getMonth() + 1)
const dd = pad(date.getDate())
const hh = pad(date.getHours())
const mi = pad(date.getMinutes())
const ss = pad(date.getSeconds())
const yyyy = d.getFullYear()
const mm = pad(d.getMonth() + 1)
const dd = pad(d.getDate())
const hh = pad(d.getHours())
const mi = pad(d.getMinutes())
const ss = pad(d.getSeconds())
return `${yyyy}-${mm}-${dd} ${hh}:${mi}:${ss}`
}
@@ -255,84 +295,207 @@ const getDoctorDept = () => userStore.orgName || '当前科室'
const applyRowToForm = (row) => {
if (!row) {
Object.keys(formData.value).forEach((key) => {
formData.value[key] = key === 'urgent' ? false : ''
if (key === 'urgent') {
formData.value[key] = false
} else if (key === 'consultationStatus') {
formData.value[key] = 0
} else {
formData.value[key] = key === 'id' || key === 'consultationRequestId' ? null : ''
}
})
return
}
formData.value.consultationId = row.consultationId
formData.value.urgent = row.urgent
formData.value.patientName = row.patientName
formData.value.gender = row.gender
formData.value.age = row.age
formData.value.cardNo = row.cardNo
formData.value.consultationTime = row.consultationTime
formData.value.invitee = row.invitee
formData.value.applyDept = row.applyDept
formData.value.applyDoctor = row.applyDoctor
formData.value.applyTime = row.applyTime
formData.value.history = row.history
formData.value.confirmingPhysician = row.confirmingPhysician
formData.value.opinion = row.opinion
formData.value.confirmDoctor = row.confirmDoctor || ''
formData.value.confirmDept = row.confirmDept || ''
formData.value.signDoctor = row.signDoctor || ''
formData.value.signTime = row.signTime || ''
formData.value = {
id: row.id,
consultationRequestId: row.consultationRequestId,
consultationId: row.consultationId,
patientName: row.patientName,
genderText: row.genderText,
age: row.age,
patientIdentifierNo: row.patientIdentifierNo,
applyDept: row.applyDept,
applyDoctor: row.applyDoctor,
applyTime: row.applyTime,
consultationDate: row.consultationDate,
urgent: row.urgent,
invitedObject: row.invitedObject,
consultationPurpose: row.consultationPurpose,
provisionalDiagnosis: row.provisionalDiagnosis,
confirmingPhysician: row.confirmingPhysician || '',
consultationOpinion: '', // 先清空,后面从 opinionList 中获取
confirmingPhysicianName: row.confirmingPhysicianName || '',
confirmingDeptName: row.confirmingDeptName || '',
signature: row.signature || '',
signatureDate: row.signatureDate,
submittingPhysician: row.submittingPhysician,
submittingTime: row.submittingTime,
consultationStatus: row.consultationStatus
}
// 从会诊意见列表中获取当前医生的信息
if (opinionList.value.length > 0) {
const currentPhysicianId = userStore.practitionerId || userStore.user?.practitionerId
const myOpinion = opinionList.value.find(op => op.physicianId === currentPhysicianId)
if (myOpinion) {
// 如果当前医生已确认,回显其信息
formData.value.confirmingPhysicianName = myOpinion.physicianName
formData.value.confirmingDeptName = myOpinion.deptName
// 回显会诊意见(去掉前缀"科室-医生"
if (myOpinion.opinion) {
// 格式:科室-医生:意见内容
const opinionText = myOpinion.opinion
const colonIndex = opinionText.indexOf('')
if (colonIndex > 0) {
// 提取冒号后面的内容
formData.value.consultationOpinion = opinionText.substring(colonIndex + 1)
} else {
formData.value.consultationOpinion = opinionText
}
}
if (myOpinion.isSigned) {
formData.value.signature = myOpinion.physicianName
formData.value.signatureDate = myOpinion.signatureTime
}
}
}
}
const handleRowChange = (row) => {
const handleRowChange = async (row) => {
currentRow.value = row
// 先加载会诊意见列表
if (row) {
await loadConsultationOpinions(row.consultationId)
} else {
opinionList.value = []
}
// 然后应用数据到表单(这样可以使用 opinionList 中的数据)
applyRowToForm(row)
}
const handleConfirm = () => {
// 加载会诊意见列表
const loadConsultationOpinions = async (consultationId) => {
try {
const res = await getConsultationOpinions(consultationId)
if (res.code === 200) {
opinionList.value = res.data || []
}
} catch (error) {
console.error('加载会诊意见失败', error)
}
}
const handleConfirm = async () => {
if (!currentRow.value) {
return
}
if (!currentRow.value.confirmed) {
if (!formData.value.opinion.trim()) {
try {
// 如果已确认则取消确认使用ConsultationStatusEnum20=已确认30=已签名)
if (currentRow.value.myInvitedStatus >= 20) {
// 已签名不能取消确认
if (currentRow.value.myInvitedStatus >= 30) {
ElMessage.warning('已签名的会诊无法取消确认')
return
}
await ElMessageBox.confirm('确定要取消确认吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
loading.value = true
const res = await cancelConfirmation(currentRow.value.consultationId)
if (res.code === 200) {
ElMessage.success('取消确认成功')
await loadData()
} else {
ElMessage.error(res.msg || '取消确认失败')
}
} else {
// 确认会诊
if (!formData.value.consultationOpinion.trim()) {
ElMessage.warning('请先填写会诊意见')
return
}
if (!formData.value.confirmingPhysician.trim()) {
ElMessage.warning('请先填写会诊确认参加医师')
return
loading.value = true
const data = {
consultationId: formData.value.consultationId,
consultationOpinion: formData.value.consultationOpinion,
confirmingPhysician: getDoctorName(), // 自动使用当前医生姓名
confirmingDeptName: getDoctorDept() // 自动使用当前科室
}
const res = await confirmConsultation(data)
if (res.code === 200) {
ElMessage.success('会诊确认成功')
await loadData()
} else {
ElMessage.error(res.msg || '会诊确认失败')
}
}
currentRow.value.confirmed = true
currentRow.value.confirmingPhysician = formData.value.confirmingPhysician
currentRow.value.opinion = formData.value.opinion
currentRow.value.confirmDoctor = getDoctorName()
currentRow.value.confirmDept = getDoctorDept()
formData.value.confirmDoctor = currentRow.value.confirmDoctor
formData.value.confirmDept = currentRow.value.confirmDept
ElMessage.success('会诊已确认')
return
} catch (error) {
if (error !== 'cancel') {
console.error('操作失败:', error)
ElMessage.error('操作失败')
}
} finally {
loading.value = false
}
if (currentRow.value.signed) {
ElMessage.warning('已签名的会诊无法取消确认')
return
}
currentRow.value.confirmed = false
currentRow.value.confirmDoctor = ''
currentRow.value.confirmDept = ''
formData.value.confirmDoctor = ''
formData.value.confirmDept = ''
ElMessage.success('已取消确认')
}
const handleSign = () => {
const handleSign = async () => {
if (!currentRow.value) {
return
}
if (!currentRow.value.confirmed) {
ElMessage.warning('请先确认会诊申请')
// 检查当前医生是否已确认使用ConsultationStatusEnum20=已确认30=已签名)
if (!currentRow.value.myInvitedStatus || currentRow.value.myInvitedStatus < 20) {
ElMessage.warning('请先确认会诊后再签名')
return
}
currentRow.value.signed = true
currentRow.value.signDoctor = getDoctorName()
currentRow.value.signTime = formatDateTime()
formData.value.signDoctor = currentRow.value.signDoctor
formData.value.signTime = currentRow.value.signTime
ElMessage.success('签名完成')
// 检查是否已签名
if (currentRow.value.myInvitedStatus >= 30) {
ElMessage.warning('您已经签名过了')
return
}
// 🎯 移除整体状态检查:只要当前医生已确认就可以签名,不需要等待所有医生都确认
try {
await ElMessageBox.confirm('确定要签名吗?签名后将无法修改会诊意见。', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
loading.value = true
const res = await signConsultation(currentRow.value.consultationId)
if (res.code === 200) {
ElMessage.success('签名成功')
await loadData()
} else {
ElMessage.error(res.msg || '签名失败')
}
} catch (error) {
if (error !== 'cancel') {
console.error('签名失败:', error)
ElMessage.error('签名失败')
}
} finally {
loading.value = false
}
}
const handlePrint = () => {
@@ -343,12 +506,50 @@ const handlePrint = () => {
window.print()
}
const handleRefresh = () => {
tableData.value = buildMockRows()
currentRow.value = null
applyRowToForm(null)
const handleRefresh = async () => {
await loadData()
ElMessage.success('已刷新')
}
const loadData = async () => {
try {
loading.value = true
const res = await getPendingConfirmationList()
if (res.code === 200) {
tableData.value = res.data || []
// 如果当前选中的行还在列表中,重新选中
if (currentRow.value) {
const updatedRow = tableData.value.find(
item => item.consultationId === currentRow.value.consultationId
)
if (updatedRow) {
currentRow.value = updatedRow
// 重新加载会诊意见
await loadConsultationOpinions(updatedRow.consultationId)
// 然后应用数据到表单
applyRowToForm(updatedRow)
} else {
currentRow.value = null
applyRowToForm(null)
opinionList.value = []
}
}
} else {
ElMessage.error(res.msg || '加载数据失败')
}
} catch (error) {
console.error('加载数据失败:', error)
ElMessage.error('加载数据失败')
} finally {
loading.value = false
}
}
onMounted(() => {
loadData()
})
</script>
<style scoped>
@@ -390,13 +591,46 @@ const handleRefresh = () => {
padding: 0;
}
}
.opinions-container {
width: 100%;
max-height: 500px;
overflow-y: auto;
padding: 10px;
background-color: #f9fafb;
border-radius: 4px;
}
.opinion-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12px;
}
.physician-info {
display: flex;
align-items: center;
}
.opinion-content {
padding: 12px;
background-color: #f5f7fa;
border-radius: 4px;
line-height: 1.6;
color: #333;
white-space: pre-wrap;
word-break: break-word;
}
.opinion-footer {
margin-top: 8px;
font-size: 12px;
color: #909399;
text-align: right;
}
.el-timeline {
padding-left: 0;
}
</style>

View File

@@ -8,7 +8,7 @@
</div>
<div class="right-actions">
<el-button type="danger" @click="handleComplete" :disabled="!selectedRow || selectedRow.consultationStatus !== 30">结束</el-button>
<el-button type="success" @click="handleSave">保存</el-button>
<el-button type="success" @click="handleSave" :disabled="selectedRow && selectedRow.consultationStatus > 0">保存</el-button>
</div>
</div>
@@ -62,15 +62,19 @@
取消提交
</el-button>
</template>
<!-- 已确认状态显示待签名按钮 -->
<template v-else-if="row.consultationStatus === 20">
<el-button type="success" size="small" @click="handleView(row)">
待签名
</el-button>
</template>
<!-- 已签名状态显示结束按钮 -->
<template v-else-if="row.consultationStatus === 30">
<!-- <el-button type="danger" size="small" @click="handleCompleteRow(row)">-->
<!-- 结束-->
<!-- </el-button>-->
<el-button
type="danger"
size="small"
@click="handleCompleteRow(row)" style="background-color: #f56c6c; border-color: #f56c6c;"
@click="handleCompleteRow(row)"
style="background-color: #f56c6c; border-color: #f56c6c;"
>
结束
</el-button>
@@ -234,39 +238,37 @@
/>
</el-form-item>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="所属医生:">
<el-input v-model="formData.attendingPhysician" placeholder="会诊后填写" disabled />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="代表科室:">
<el-input v-model="formData.representDepartment" placeholder="会诊后填写" disabled />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="签名医生:">
<el-input v-model="formData.signPhysician" placeholder="会诊后填写" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="签名时间:">
<el-date-picker
v-model="formData.signTime"
type="datetime"
placeholder="年/月/日 --:--"
<!-- 🎯 新增参与医生列表表格形式 -->
<el-form-item label="参与医生签名:" v-if="participatingPhysicians.length > 0">
<el-table
:data="participatingPhysicians"
border
stripe
style="width: 100%"
format="YYYY/MM/DD HH:mm"
value-format="YYYY-MM-DD HH:mm:ss"
disabled
/>
max-height="300"
>
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="deptName" label="科室" width="120" align="center" />
<el-table-column prop="physicianName" label="医生" width="100" align="center" />
<el-table-column prop="confirmTime" label="确认时间" width="160" align="center">
<template #default="{ row }">
{{ formatDateTime(row.confirmTime) }}
</template>
</el-table-column>
<el-table-column prop="signatureTime" label="签名时间" width="160" align="center">
<template #default="{ row }">
{{ formatDateTime(row.signatureTime) }}
</template>
</el-table-column>
<el-table-column label="状态" width="80" align="center">
<template #default="{ row }">
<el-tag v-if="row.invitedStatus >= 3" type="success">已签名</el-tag>
<el-tag v-else-if="row.invitedStatus >= 1" type="warning">已确认</el-tag>
<el-tag v-else type="info">待确认</el-tag>
</template>
</el-table-column>
</el-table>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
@@ -289,7 +291,7 @@
清空
</el-button>
</div>
<!-- 科室医生树带复选框 -->
<div class="invite-section">
<div class="section-label">选择会诊科室和医生</div>
@@ -323,7 +325,7 @@
<div v-show="expandedDepts.includes(dept.id)" class="physicians-list">
<div
v-for="physician in dept.children"
:key="physician.id"
:key="physician.id"
class="physician-item"
>
<el-checkbox
@@ -332,11 +334,11 @@
>
{{ physician.label }}
</el-checkbox>
</div>
</div>
<div v-if="!dept.children || dept.children.length === 0" class="no-physicians">
该科室暂无医生
</div>
</div>
</div>
</div>
</div>
</div>
</el-scrollbar>
@@ -432,6 +434,9 @@ const expandedDepts = ref([]);
// 选中的医生列表(用于显示和提交)
const selectedPhysiciansList = ref([]);
// 🎯 新增:参与医生列表(用于显示已确认/已签名的医生)
const participatingPhysicians = ref([]);
// 会诊列表
const consultationList = ref([]);
@@ -716,6 +721,14 @@ const handleRowClick = (row) => {
isUrgent: row.consultationUrgency === '2', // 2=紧急
consultationPurpose: row.consultationPurpose,
createTime: row.consultationRequestDate || row.createTime, // 申请时间
// 🎯 填充会诊记录字段(如果会诊已完成或已签名)
invitedPhysiciansText: row.invitedPhysiciansText || '',
consultationOpinion: row.consultationOpinion || '',
attendingPhysician: row.attendingPhysician || '',
representDepartment: row.representDepartment || '',
signPhysician: row.signPhysician || '',
signTime: row.signTime || null,
});
console.log('填充后的表单数据:', formData);
@@ -730,8 +743,22 @@ const handleRowClick = (row) => {
}));
console.log('填充的医生列表:', selectedPhysiciansList.value);
// 🎯 填充参与医生列表(显示确认和签名状态)
participatingPhysicians.value = row.invitedList.map(inv => ({
physicianId: inv.physicianId,
physicianName: inv.physicianName,
deptId: inv.deptId,
deptName: inv.deptName,
invitedStatus: inv.invitedStatus || 0,
confirmTime: inv.confirmTime || null,
signatureTime: inv.signatureTime || null,
}));
console.log('参与医生列表:', participatingPhysicians.value);
} else {
selectedPhysiciansList.value = [];
participatingPhysicians.value = [];
}
}
};
@@ -781,6 +808,7 @@ const handleNew = () => {
// 清空选中状态
selectedPhysiciansList.value = [];
participatingPhysicians.value = [];
// 加载主诊断
loadMainDiagnosis();
@@ -1090,6 +1118,19 @@ defineExpose({
fetchConsultationList,
});
// 🎯 格式化日期时间
const formatDateTime = (dateTime) => {
if (!dateTime) return '-';
const date = new Date(dateTime);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
const seconds = String(date.getSeconds()).padStart(2, '0');
return `${year}/${month}/${day} ${hours}:${minutes}:${seconds}`;
};
// 监听 activeTab 变化
watch(
() => props.activeTab,
@@ -1302,11 +1343,11 @@ onMounted(() => {
transition: transform 0.3s;
}
.dept-name {
.dept-name {
flex: 1;
font-size: 14px;
font-size: 14px;
font-weight: 500;
color: #303133;
color: #303133;
}
.selected-badge {
@@ -1333,26 +1374,26 @@ onMounted(() => {
.physician-item {
padding: 6px 10px;
:deep(.el-checkbox) {
width: 100%;
:deep(.el-checkbox) {
width: 100%;
.el-checkbox__label {
font-size: 13px;
.el-checkbox__label {
font-size: 13px;
color: #606266;
}
}
&.is-checked .el-checkbox__label {
color: #409eff;
font-weight: 500;
}
}
}
}
}
.no-physicians {
color: #909399;
color: #909399;
font-size: 12px;
text-align: center;
text-align: center;
padding: 10px 0;
}
}