#431 会诊申请单:标签文案修改「需要病员及会诊目的」为「简要病史及会诊目的」 #433 手术安排编辑:麻醉方法回显为代码 - 添加Number类型转换 #434 手术安排编辑:切口类型未回显 - 添加Number类型转换 #435 手术安排编辑:费用类别未回显 - 确保字段正确赋值
1494 lines
46 KiB
Vue
1494 lines
46 KiB
Vue
<template>
|
||
<div class="consultation-container">
|
||
<!-- 顶部操作按钮 -->
|
||
<div class="top-actions">
|
||
<div class="left-actions">
|
||
<el-button type="info" @click="handlePrint">打印</el-button>
|
||
<el-button type="primary" @click="handleNew">新增</el-button>
|
||
</div>
|
||
<div class="right-actions">
|
||
<el-button type="danger" @click="handleComplete" :disabled="!selectedRow || selectedRow.consultationStatus !== 30">结束</el-button>
|
||
<el-button type="success" @click="handleSave" :disabled="selectedRow && selectedRow.consultationStatus > 0">保存</el-button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 会诊申请列表 -->
|
||
<div class="consultation-list">
|
||
<el-table
|
||
ref="consultationTableRef"
|
||
:data="consultationList"
|
||
border
|
||
stripe
|
||
highlight-current-row
|
||
@current-change="handleRowClick"
|
||
style="width: 100%"
|
||
max-height="250"
|
||
>
|
||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||
<el-table-column label="急" width="60" align="center">
|
||
<template #default="{ row }">
|
||
<span v-if="row.consultationUrgency === '2'">✓</span>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column prop="consultationId" label="申请单号" width="160" align="center" />
|
||
<el-table-column prop="consultationDate" label="会诊时间" width="160" align="center" />
|
||
<el-table-column prop="invitedObjectText" label="邀请对象" min-width="120" show-overflow-tooltip />
|
||
<el-table-column prop="department" label="申请科室" width="100" align="center" />
|
||
<el-table-column prop="requestingPhysician" label="申请医师" width="100" align="center" />
|
||
<el-table-column prop="consultationRequestDate" label="申请时间" width="160" align="center" />
|
||
<el-table-column label="提交" width="60" align="center">
|
||
<template #default="{ row }">
|
||
<el-checkbox v-model="row.submitted" disabled />
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="结束" width="60" align="center">
|
||
<template #default="{ row }">
|
||
<el-checkbox v-model="row.completed" disabled />
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="操作" width="180" align="center" fixed="right">
|
||
<template #default="{ row }">
|
||
<!-- 新开状态:显示提交和作废按钮 -->
|
||
<template v-if="row.consultationStatus === 0">
|
||
<el-button type="primary" size="small" @click="handleSubmitRow(row)">
|
||
提交
|
||
</el-button>
|
||
<el-button type="danger" size="small" @click="handleDeleteRow(row)">
|
||
作废
|
||
</el-button>
|
||
</template>
|
||
<!-- 已提交状态:显示取消提交按钮 -->
|
||
<!-- 🎯 修复:如果有医生已确认或签名,则隐藏取消提交按钮 -->
|
||
<template v-else-if="row.consultationStatus === 10 && !hasConfirmedOrSignedDoctor(row)">
|
||
<el-button type="warning" size="small" @click="handleCancelSubmit(row)">
|
||
取消提交
|
||
</el-button>
|
||
</template>
|
||
<!-- 已提交但有医生确认/签名:显示查看按钮 -->
|
||
<template v-else-if="row.consultationStatus === 10 && hasConfirmedOrSignedDoctor(row)">
|
||
<el-button type="info" size="small" @click="handleView(row)">
|
||
查看
|
||
</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)"
|
||
style="background-color: #f56c6c; border-color: #f56c6c;"
|
||
>
|
||
结束
|
||
</el-button>
|
||
</template>
|
||
<!-- 已完成或已取消:显示查看按钮 -->
|
||
<template v-else>
|
||
<el-button type="info" size="small" @click="handleView(row)">
|
||
查看
|
||
</el-button>
|
||
</template>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</div>
|
||
|
||
<!-- 下方内容区域 -->
|
||
<div class="content-area">
|
||
<!-- 左侧:会诊申请单 -->
|
||
<div class="left-panel">
|
||
<div class="panel-title">会诊申请单</div>
|
||
<el-form ref="formRef" :model="formData" :rules="rules" label-width="100px" class="consultation-form">
|
||
<el-row :gutter="20">
|
||
<el-col :span="8">
|
||
<el-form-item label="申请单号:">
|
||
<el-input v-model="formData.consultationId" disabled />
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="8">
|
||
<el-form-item label="病人姓名:">
|
||
<el-input v-model="formData.patientName" disabled />
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="8">
|
||
<el-form-item label="性别:">
|
||
<el-input v-model="formData.genderText" disabled />
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
|
||
<el-row :gutter="20">
|
||
<el-col :span="8">
|
||
<el-form-item label="申请时间:">
|
||
<el-input v-model="displayApplicationTime" disabled />
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="8">
|
||
<el-form-item label="就诊卡号:">
|
||
<el-input v-model="formData.patientBusNo" disabled />
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="8">
|
||
<el-form-item label="年龄:">
|
||
<el-input v-model="formData.age" disabled />
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
|
||
<el-row :gutter="20">
|
||
<el-col :span="8">
|
||
<el-form-item label="申请医师:">
|
||
<el-input v-model="formData.requestingPhysician" disabled />
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="8">
|
||
<el-form-item label="申请科室:">
|
||
<el-input v-model="formData.department" disabled />
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="8">
|
||
<el-form-item label="门诊诊断:">
|
||
<el-input v-model="formData.provisionalDiagnosis" disabled />
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
|
||
<el-row :gutter="20">
|
||
<el-col :span="8">
|
||
<el-form-item label="会诊项目:" prop="consultationActivityId">
|
||
<el-select
|
||
v-model="formData.consultationActivityId"
|
||
placeholder="请选择会诊项目"
|
||
style="width: 100%"
|
||
@change="handleActivityChange"
|
||
>
|
||
<el-option
|
||
v-for="item in activityList"
|
||
:key="item.id"
|
||
:label="`${item.name} (¥${item.price})`"
|
||
:value="item.id"
|
||
/>
|
||
</el-select>
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="8">
|
||
<el-form-item label="会诊时间:" prop="consultationDate">
|
||
<el-date-picker
|
||
v-model="formData.consultationDate"
|
||
type="datetime"
|
||
placeholder="请选择"
|
||
style="width: 100%"
|
||
format="YYYY/MM/DD HH:mm"
|
||
value-format="YYYY-MM-DD HH:mm:ss"
|
||
:disabled-date="disabledDate"
|
||
/>
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="8">
|
||
<el-form-item label="急诊:">
|
||
<el-checkbox v-model="formData.isUrgent" />
|
||
</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-form-item label="会诊邀请对象:">
|
||
<div class="invited-display">
|
||
<div v-if="selectedPhysiciansList.length > 0" class="invited-list">
|
||
<el-tag
|
||
v-for="physician in selectedPhysiciansList"
|
||
:key="physician.id"
|
||
type="success"
|
||
style="margin: 5px"
|
||
>
|
||
{{ physician.deptName }} - {{ physician.name }}
|
||
</el-tag>
|
||
</div>
|
||
<div v-else class="empty-invited">
|
||
请在右侧选择会诊医生
|
||
</div>
|
||
</div>
|
||
</el-form-item>
|
||
|
||
<div class="section-title">会诊记录</div>
|
||
|
||
<el-form-item label="会诊确认参加医师:">
|
||
<el-input
|
||
v-model="formData.invitedPhysiciansText"
|
||
type="textarea"
|
||
:rows="2"
|
||
placeholder="会诊后自动填充"
|
||
disabled
|
||
/>
|
||
</el-form-item>
|
||
|
||
<el-form-item label="会诊意见:">
|
||
<el-input
|
||
v-model="formData.consultationOpinion"
|
||
type="textarea"
|
||
:rows="4"
|
||
placeholder="会诊后填写"
|
||
disabled
|
||
/>
|
||
</el-form-item>
|
||
|
||
<!-- 🎯 新增:参与医生列表(表格形式) -->
|
||
<el-form-item label="参与医生签名:">
|
||
<el-table
|
||
:data="participatingPhysicians"
|
||
border
|
||
stripe
|
||
style="width: 100%"
|
||
max-height="300"
|
||
>
|
||
<el-table-column type="index" label="序号" min-width="60" align="center" />
|
||
<el-table-column prop="confirmingDeptName" label="代表科室" min-width="120" align="center" />
|
||
<el-table-column prop="confirmingPhysicianName" label="所属医生" min-width="100" align="center" />
|
||
<el-table-column prop="signature" label="签名医生" min-width="100" align="center" />
|
||
<el-table-column prop="signatureDate" label="签名时间" min-width="160" align="center">
|
||
<template #default="{ row }">
|
||
{{ formatDateTime(row.signatureDate) }}
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</el-form-item>
|
||
</el-form>
|
||
</div>
|
||
|
||
<!-- 右侧:会诊邀请对象 -->
|
||
<div class="right-panel">
|
||
<div class="panel-title">会诊邀请对象</div>
|
||
|
||
<!-- 已选择医生统计 -->
|
||
<div class="selected-summary">
|
||
<span class="summary-text">已选择:</span>
|
||
<span class="summary-count">{{ selectedPhysiciansList.length }}</span>
|
||
<span class="summary-text">位医生</span>
|
||
<el-button
|
||
v-if="selectedPhysiciansList.length > 0"
|
||
type="text"
|
||
size="small"
|
||
@click="clearAllSelections"
|
||
style="margin-left: auto; color: #f56c6c;"
|
||
>
|
||
清空
|
||
</el-button>
|
||
</div>
|
||
|
||
<!-- 科室医生树(带复选框) -->
|
||
<div class="invite-section">
|
||
<div class="section-label">选择会诊科室和医生</div>
|
||
<el-scrollbar height="600px">
|
||
<div class="department-list">
|
||
<div
|
||
v-for="dept in departmentTree"
|
||
:key="dept.id"
|
||
class="department-item"
|
||
>
|
||
<!-- 科室标题 -->
|
||
<div
|
||
class="dept-header"
|
||
:class="{ 'expanded': expandedDepts.includes(dept.id) }"
|
||
@click="toggleDept(dept.id)"
|
||
>
|
||
<i
|
||
class="el-icon"
|
||
:class="expandedDepts.includes(dept.id) ? 'el-icon-arrow-down' : 'el-icon-arrow-right'"
|
||
></i>
|
||
<span class="dept-name">{{ dept.label }}</span>
|
||
<span
|
||
v-if="getDeptSelectedCount(dept.id) > 0"
|
||
class="selected-badge"
|
||
>
|
||
{{ getDeptSelectedCount(dept.id) }}
|
||
</span>
|
||
</div>
|
||
|
||
<!-- 医生列表 -->
|
||
<div v-show="expandedDepts.includes(dept.id)" class="physicians-list">
|
||
<div
|
||
v-for="physician in dept.children"
|
||
:key="physician.id"
|
||
class="physician-item"
|
||
>
|
||
<el-checkbox
|
||
:model-value="isPhysicianSelected(physician.id)"
|
||
@change="(checked) => handlePhysicianCheck(checked, physician, dept)"
|
||
>
|
||
{{ physician.label }}
|
||
</el-checkbox>
|
||
</div>
|
||
<div v-if="!dept.children || dept.children.length === 0" class="no-physicians">
|
||
该科室暂无医生
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</el-scrollbar>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, reactive, computed, onMounted, onUnmounted, watch, defineProps } from 'vue';
|
||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||
import { Delete } from '@element-plus/icons-vue';
|
||
import useUserStore from '@/store/modules/user';
|
||
import {
|
||
getConsultationList,
|
||
saveConsultation,
|
||
submitConsultation,
|
||
cancelConsultation,
|
||
completeConsultation,
|
||
getDepartmentTree,
|
||
getMainDiagnosis,
|
||
getConsultationActivities,
|
||
} from './api';
|
||
|
||
// 接收父组件传递的患者信息和激活状态
|
||
const props = defineProps({
|
||
patientInfo: {
|
||
type: Object,
|
||
default: () => ({}),
|
||
},
|
||
activeTab: {
|
||
type: String,
|
||
default: '',
|
||
},
|
||
});
|
||
|
||
// 表单引用
|
||
const formRef = ref(null);
|
||
|
||
// 树形引用
|
||
const treeRef = ref(null);
|
||
|
||
// 会诊项目列表
|
||
const activityList = ref([]);
|
||
|
||
// 当前选中的行
|
||
const selectedRow = ref(null);
|
||
|
||
// 实时显示的当前时间
|
||
const currentTime = ref('');
|
||
let timeTimer = null; // 定时器引用
|
||
|
||
// 计算显示的申请时间 - 如果有选中行则显示其申请时间,否则显示当前时间
|
||
const displayApplicationTime = computed(() => {
|
||
if (selectedRow.value && selectedRow.value.consultationRequestDate) {
|
||
// 如果是编辑已有记录,则显示其申请时间(不是动态时间)
|
||
return selectedRow.value.consultationRequestDate;
|
||
} else {
|
||
// 如果是新增记录,则显示当前时间(动态时间)
|
||
return currentTime.value;
|
||
}
|
||
});
|
||
|
||
// 表单数据
|
||
const formData = reactive({
|
||
consultationId: '',
|
||
consultationActivityId: null,
|
||
consultationActivityName: '',
|
||
patientName: '',
|
||
genderText: '',
|
||
age: '',
|
||
patientBusNo: '',
|
||
requestingPhysician: '',
|
||
department: '',
|
||
provisionalDiagnosis: '',
|
||
consultationDate: null,
|
||
isUrgent: false,
|
||
consultationPurpose: '',
|
||
invitedPhysiciansText: '',
|
||
consultationOpinion: '',
|
||
attendingPhysician: '',
|
||
representDepartment: '',
|
||
signPhysician: '',
|
||
signTime: null,
|
||
createTime: '',
|
||
});
|
||
|
||
// 表单验证规则
|
||
const rules = {
|
||
consultationActivityId: [
|
||
{ required: true, message: '请选择会诊项目', trigger: 'change' },
|
||
],
|
||
consultationDate: [
|
||
{ required: true, message: '请选择会诊时间', trigger: 'change' },
|
||
],
|
||
consultationPurpose: [
|
||
{ required: true, message: '请输入会诊目的', trigger: 'blur' },
|
||
],
|
||
};
|
||
|
||
// 科室医生树
|
||
const departmentTree = ref([]);
|
||
|
||
// 展开的科室列表
|
||
const expandedDepts = ref([]);
|
||
|
||
// 选中的医生列表(用于显示和提交)
|
||
const selectedPhysiciansList = ref([]);
|
||
|
||
// 🎯 新增:参与医生列表(用于显示已确认/已签名的医生)
|
||
const participatingPhysicians = ref([]);
|
||
|
||
// 会诊列表
|
||
const consultationList = ref([]);
|
||
|
||
// 禁用过去的日期
|
||
const disabledDate = (time) => {
|
||
return time.getTime() < Date.now() - 8.64e7;
|
||
};
|
||
|
||
// 加载会诊项目列表
|
||
const loadActivityList = async () => {
|
||
try {
|
||
console.log('开始调用 getConsultationActivities 接口...');
|
||
const res = await getConsultationActivities();
|
||
console.log('getConsultationActivities 接口返回:', res);
|
||
|
||
// 检查响应是否存在
|
||
if (!res) {
|
||
console.error('接口返回空响应');
|
||
ElMessage.warning('会诊项目列表加载失败:未获取到响应数据');
|
||
activityList.value = [];
|
||
return;
|
||
}
|
||
|
||
// 检查响应代码
|
||
if (res.code === 200) {
|
||
activityList.value = res.data || [];
|
||
console.log('会诊项目列表加载成功,数量:', activityList.value.length);
|
||
|
||
// 如果列表为空,给出提示
|
||
if (activityList.value.length === 0) {
|
||
console.warn('会诊项目列表为空,请检查数据库配置');
|
||
ElMessage.warning('暂无可用会诊项目,请联系系统管理员配置');
|
||
}
|
||
} else {
|
||
console.error('接口返回错误:', res.msg || res.message);
|
||
ElMessage.error(res.msg || '加载会诊项目失败');
|
||
activityList.value = [];
|
||
}
|
||
} catch (error) {
|
||
console.error('加载会诊项目失败,错误详情:', error);
|
||
// 网络错误或其他异常
|
||
const errorMsg = error.response?.data?.msg || error.message || '未知错误';
|
||
ElMessage.error('加载会诊项目失败: ' + errorMsg);
|
||
activityList.value = [];
|
||
}
|
||
};
|
||
|
||
// 会诊项目选择变化
|
||
const handleActivityChange = (activityId) => {
|
||
const activity = activityList.value.find((item) => item.id === activityId);
|
||
if (activity) {
|
||
formData.consultationActivityName = activity.name;
|
||
console.log('选择的会诊项目:', activity.name, '价格:', activity.price);
|
||
}
|
||
};
|
||
|
||
// 加载科室医生树
|
||
const loadDepartmentTree = async () => {
|
||
try {
|
||
const res = await getDepartmentTree();
|
||
|
||
// 检查响应是否存在
|
||
if (!res) {
|
||
console.error('接口返回空响应');
|
||
ElMessage.warning('科室医生树加载失败:未获取到响应数据');
|
||
departmentTree.value = [];
|
||
return;
|
||
}
|
||
|
||
if (res.code === 200) {
|
||
departmentTree.value = res.data || [];
|
||
console.log('科室医生树加载成功:', departmentTree.value);
|
||
|
||
// 如果树为空,给出提示
|
||
if (departmentTree.value.length === 0) {
|
||
console.warn('科室医生树为空,请检查数据库配置');
|
||
ElMessage.warning('暂无可用科室医生数据,请联系系统管理员配置');
|
||
}
|
||
} else {
|
||
console.error('接口返回错误:', res.msg || res.message);
|
||
ElMessage.warning(res.msg || '加载科室医生树失败');
|
||
departmentTree.value = [];
|
||
}
|
||
} catch (error) {
|
||
console.error('加载科室医生树失败:', error);
|
||
// 网络错误或其他异常
|
||
const errorMsg = error.response?.data?.msg || error.message || '未知错误';
|
||
ElMessage.warning('加载科室医生树失败: ' + errorMsg);
|
||
departmentTree.value = [];
|
||
}
|
||
};
|
||
|
||
// 处理树节点点击
|
||
const handleNodeClick = (data, node) => {
|
||
console.log('点击节点:', data, node);
|
||
|
||
// 如果点击的是科室节点(有children)
|
||
if (data.children && data.children.length > 0) {
|
||
currentDepartmentId.value = data.id;
|
||
currentDepartmentName.value = data.label;
|
||
|
||
// 显示该科室下的所有医生
|
||
currentDepartmentPhysicians.value = data.children.map(physician => ({
|
||
id: physician.id,
|
||
name: physician.label,
|
||
deptId: data.id,
|
||
deptName: data.label,
|
||
}));
|
||
|
||
console.log('当前科室医生:', currentDepartmentPhysicians.value);
|
||
}
|
||
};
|
||
|
||
// 处理医生选择变化
|
||
// const handlePhysicianSelectionChange = (selectedIds) => {
|
||
// console.log('选中的医生ID:', selectedIds);
|
||
|
||
// // 更新选中的医生列表
|
||
// selectedPhysiciansList.value = currentDepartmentPhysicians.value.filter(physician =>
|
||
// selectedIds.includes(physician.id)
|
||
// );
|
||
|
||
// console.log('选中的医生列表:', selectedPhysiciansList.value);
|
||
// };
|
||
|
||
const handlePhysicianSelectionChange = (selectedIds) => {
|
||
console.log('选中的医生ID:', selectedIds);
|
||
|
||
const deptId = currentDepartmentId.value;
|
||
|
||
// 1) 先保留“非当前科室”的已选医生
|
||
const preserved = selectedPhysiciansList.value.filter(p => p.deptId !== deptId);
|
||
|
||
// 2) 再计算“当前科室”被选中的医生
|
||
const selectedInCurrentDept = currentDepartmentPhysicians.value.filter(p =>
|
||
selectedIds.includes(p.id)
|
||
);
|
||
|
||
// 3) 合并:跨科室累积
|
||
selectedPhysiciansList.value = [...preserved, ...selectedInCurrentDept];
|
||
|
||
console.log('更新后的选中医生列表:', selectedPhysiciansList.value);
|
||
};
|
||
|
||
// 切换科室展开/收起
|
||
const toggleDept = (deptId) => {
|
||
const index = expandedDepts.value.indexOf(deptId);
|
||
if (index > -1) {
|
||
expandedDepts.value.splice(index, 1);
|
||
} else {
|
||
expandedDepts.value.push(deptId);
|
||
}
|
||
};
|
||
|
||
// 判断医生是否被选中
|
||
const isPhysicianSelected = (physicianId) => {
|
||
return selectedPhysiciansList.value.some(p => p.id === physicianId);
|
||
};
|
||
|
||
// 处理医生复选框变化
|
||
const handlePhysicianCheck = (checked, physician, dept) => {
|
||
if (checked) {
|
||
// 添加医生到选中列表
|
||
selectedPhysiciansList.value.push({
|
||
id: physician.id,
|
||
name: physician.label,
|
||
deptId: dept.id,
|
||
deptName: dept.label,
|
||
});
|
||
} else {
|
||
// 从选中列表中移除
|
||
selectedPhysiciansList.value = selectedPhysiciansList.value.filter(
|
||
p => p.id !== physician.id
|
||
);
|
||
}
|
||
console.log('当前选中的医生:', selectedPhysiciansList.value);
|
||
};
|
||
|
||
// 获取某个科室已选中的医生数量
|
||
const getDeptSelectedCount = (deptId) => {
|
||
return selectedPhysiciansList.value.filter(p => p.deptId === deptId).length;
|
||
};
|
||
|
||
// 清空所有选择
|
||
const clearAllSelections = () => {
|
||
selectedPhysiciansList.value = [];
|
||
};
|
||
|
||
// 🎯 检查是否有医生已确认或签名
|
||
const hasConfirmedOrSignedDoctor = (row) => {
|
||
if (!row.invitedList || row.invitedList.length === 0) {
|
||
return false;
|
||
}
|
||
return row.invitedList.some(inv => inv.invitedStatus >= 20);
|
||
};
|
||
|
||
// 加载会诊列表
|
||
const loadConsultationList = async () => {
|
||
if (!props.patientInfo?.encounterId) {
|
||
console.log('没有就诊ID,无法加载会诊列表');
|
||
consultationList.value = [];
|
||
return;
|
||
}
|
||
try {
|
||
const res = await getConsultationList({ encounterId: props.patientInfo.encounterId });
|
||
|
||
// 检查响应是否存在
|
||
if (!res) {
|
||
console.error('接口返回空响应');
|
||
ElMessage.warning('会诊列表加载失败:未获取到响应数据');
|
||
consultationList.value = [];
|
||
return;
|
||
}
|
||
|
||
if (res.code === 200) {
|
||
consultationList.value = (res.data || []).map(item => {
|
||
console.log('列表项数据:', item);
|
||
return {
|
||
...item,
|
||
submitted: item.consultationStatus >= 10,
|
||
completed: item.consultationStatus === 40,
|
||
invitedObjectText: item.invitedObject || (item.invitedList?.map(inv => inv.physicianName).join('、') || ''),
|
||
};
|
||
});
|
||
console.log('会诊列表:', consultationList.value);
|
||
} else {
|
||
console.error('接口返回错误:', res.msg || res.message);
|
||
ElMessage.warning(res.msg || '加载会诊列表失败');
|
||
consultationList.value = [];
|
||
}
|
||
} catch (error) {
|
||
console.error('加载会诊列表失败:', error);
|
||
// 网络错误或其他异常
|
||
const errorMsg = error.response?.data?.msg || error.message || '未知错误';
|
||
ElMessage.warning('加载会诊列表失败: ' + errorMsg);
|
||
consultationList.value = [];
|
||
}
|
||
};
|
||
|
||
// 加载主诊断
|
||
const loadMainDiagnosis = async () => {
|
||
if (!props.patientInfo?.encounterId) {
|
||
return;
|
||
}
|
||
try {
|
||
const res = await getMainDiagnosis({ encounterId: props.patientInfo.encounterId });
|
||
|
||
// 检查响应是否存在
|
||
if (!res) {
|
||
console.error('获取主诊断接口返回空响应');
|
||
return;
|
||
}
|
||
|
||
if (res.code === 200 && res.data) {
|
||
formData.provisionalDiagnosis = res.data.diagnosis || '';
|
||
console.log('主诊断加载成功:', formData.provisionalDiagnosis);
|
||
} else {
|
||
console.warn('获取主诊断失败:', res.msg || res.message);
|
||
formData.provisionalDiagnosis = '';
|
||
}
|
||
} catch (error) {
|
||
console.error('加载主诊断失败:', error);
|
||
// 主诊断加载失败不应该阻塞整个会诊功能,只是不显示诊断信息
|
||
formData.provisionalDiagnosis = '';
|
||
}
|
||
};
|
||
|
||
// 点击表格行
|
||
const handleRowClick = async (row) => {
|
||
console.log('点击行,当前 selectedRow:', selectedRow.value, '新 row:', row);
|
||
|
||
// 先清空表单验证状态
|
||
if (formRef.value) {
|
||
formRef.value.clearValidate();
|
||
}
|
||
|
||
selectedRow.value = row;
|
||
if (row) {
|
||
console.log('点击的行数据:', row);
|
||
|
||
// 🎯 处理会诊确认参加医师字段(可能是JSON格式)
|
||
let physiciansText = row.invitedPhysiciansText || '';
|
||
if (physiciansText) {
|
||
try {
|
||
// 尝试解析JSON格式
|
||
const physicians = JSON.parse(physiciansText);
|
||
if (Array.isArray(physicians)) {
|
||
// 格式化为:科室-姓名、科室-姓名
|
||
physiciansText = physicians
|
||
.map(p => `${p.deptName || ''}-${p.physicianName || ''}`)
|
||
.filter(text => text !== '-')
|
||
.join('、');
|
||
}
|
||
} catch (e) {
|
||
// 如果不是JSON,保持原值
|
||
console.log('invitedPhysiciansText不是JSON格式,使用原值:', physiciansText);
|
||
}
|
||
}
|
||
|
||
// 填充表单数据
|
||
Object.assign(formData, {
|
||
consultationId: row.consultationId,
|
||
consultationActivityId: row.consultationActivityId,
|
||
consultationActivityName: row.consultationActivityName,
|
||
patientName: row.patientName,
|
||
genderText: row.genderEnum === 1 ? '男' : '女',
|
||
age: row.age,
|
||
patientBusNo: row.patientBusNo,
|
||
requestingPhysician: row.requestingPhysician,
|
||
department: row.department,
|
||
provisionalDiagnosis: row.provisionalDiagnosis,
|
||
consultationDate: row.consultationDate,
|
||
isUrgent: row.consultationUrgency === '2', // 2=紧急
|
||
consultationPurpose: row.consultationPurpose,
|
||
createTime: row.consultationRequestDate || row.createTime, // 申请时间
|
||
|
||
// 🎯 填充会诊记录字段(如果会诊已完成或已签名)
|
||
invitedPhysiciansText: physiciansText,
|
||
consultationOpinion: row.consultationOpinion || '',
|
||
attendingPhysician: row.attendingPhysician || '',
|
||
representDepartment: row.representDepartment || '',
|
||
signPhysician: row.signPhysician || '',
|
||
signTime: row.signTime || null,
|
||
});
|
||
|
||
console.log('填充后的表单数据:', formData);
|
||
|
||
// 填充选中的医生
|
||
if (row.invitedList && row.invitedList.length > 0) {
|
||
selectedPhysiciansList.value = row.invitedList.map(inv => ({
|
||
id: inv.physicianId,
|
||
name: inv.physicianName,
|
||
deptId: inv.deptId,
|
||
deptName: inv.deptName,
|
||
}));
|
||
|
||
console.log('填充的医生列表:', selectedPhysiciansList.value);
|
||
|
||
// 🎯 填充参与医生列表(显示确认和签名状态)
|
||
participatingPhysicians.value = row.invitedList
|
||
.filter(inv => inv.invitedStatus >= 20) // 只显示已确认或已签名的医生
|
||
.map(inv => ({
|
||
physicianId: inv.physicianId,
|
||
confirmingPhysicianName: inv.physicianName || '',
|
||
confirmingDeptName: inv.deptName || '',
|
||
signature: inv.invitedStatus >= 30 ? inv.physicianName : '', // 已签名才显示签名医生
|
||
signatureDate: inv.signatureTime || null,
|
||
}));
|
||
|
||
console.log('参与医生列表:', participatingPhysicians.value);
|
||
} else {
|
||
selectedPhysiciansList.value = [];
|
||
participatingPhysicians.value = [];
|
||
}
|
||
}
|
||
|
||
console.log('行点击处理完成,selectedRow:', selectedRow.value);
|
||
};
|
||
|
||
// 表格引用
|
||
const consultationTableRef = ref(null);
|
||
|
||
// 新增
|
||
const handleNew = () => {
|
||
console.log('点击新增按钮');
|
||
|
||
// 先清空表单验证状态
|
||
if (formRef.value) {
|
||
formRef.value.clearValidate();
|
||
}
|
||
|
||
// 🔧 Bug #262 修复:清除表格的当前行选中状态,确保后续点击行能正常触发 current-change 事件
|
||
if (consultationTableRef.value) {
|
||
consultationTableRef.value.setCurrentRow(null);
|
||
}
|
||
|
||
selectedRow.value = null;
|
||
|
||
// 获取当前登录用户信息
|
||
const userStore = useUserStore();
|
||
|
||
// 获取当前时间
|
||
const now = new Date();
|
||
const formatDateTime = (date) => {
|
||
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}`;
|
||
};
|
||
|
||
// 重置表单,填充患者信息和当前医生信息
|
||
Object.assign(formData, {
|
||
consultationId: '保存后自动生成',
|
||
consultationActivityId: null,
|
||
consultationActivityName: '',
|
||
patientName: props.patientInfo.patientName || '',
|
||
genderText: props.patientInfo.genderEnum === 1 ? '男' : '女',
|
||
age: props.patientInfo.age || '',
|
||
// 🔧 Bug #263 修复:就诊卡号应取值于 identifierNo,而非 busNo
|
||
patientBusNo: props.patientInfo.identifierNo || '',
|
||
requestingPhysician: userStore.nickName || '',
|
||
department: userStore.orgName || '',
|
||
provisionalDiagnosis: '',
|
||
consultationDate: null,
|
||
isUrgent: false,
|
||
consultationPurpose: '',
|
||
invitedPhysiciansText: '',
|
||
consultationOpinion: '',
|
||
attendingPhysician: '',
|
||
representDepartment: '',
|
||
signPhysician: '',
|
||
signTime: null,
|
||
createTime: formatDateTime(now),
|
||
});
|
||
|
||
// 清空选中状态
|
||
selectedPhysiciansList.value = [];
|
||
participatingPhysicians.value = [];
|
||
|
||
console.log('新增模式初始化完成,selectedRow:', selectedRow.value);
|
||
|
||
// 加载主诊断
|
||
loadMainDiagnosis();
|
||
};
|
||
|
||
// 保存
|
||
const handleSave = async () => {
|
||
if (!props.patientInfo?.encounterId) {
|
||
ElMessage.warning('请先选择患者');
|
||
return;
|
||
}
|
||
|
||
try {
|
||
await formRef.value.validate();
|
||
|
||
// 检查是否选择了会诊医生
|
||
if (selectedPhysiciansList.value.length === 0) {
|
||
ElMessage.warning('请至少选择1位会诊专家');
|
||
return;
|
||
}
|
||
|
||
// 校验会诊时间不能早于当前时间
|
||
if (formData.consultationDate) {
|
||
const scheduledDate = new Date(formData.consultationDate);
|
||
const now = new Date();
|
||
if (scheduledDate < now) {
|
||
ElMessage.warning('会诊时间不能早于当前时间');
|
||
return;
|
||
}
|
||
}
|
||
|
||
// 构建邀请对象列表
|
||
const invitedList = selectedPhysiciansList.value.map(physician => ({
|
||
physicianId: physician.id,
|
||
physicianName: physician.name,
|
||
deptId: physician.deptId,
|
||
deptName: physician.deptName,
|
||
}));
|
||
|
||
// 处理年龄:去掉"岁"字,转换为纯数字
|
||
let ageValue = props.patientInfo.age;
|
||
if (typeof ageValue === 'string') {
|
||
ageValue = parseInt(ageValue.replace(/[^\d]/g, '')) || 0;
|
||
}
|
||
|
||
// 获取当前登录用户信息
|
||
const userStore = useUserStore();
|
||
|
||
const data = {
|
||
id: selectedRow.value?.id || null,
|
||
consultationId: selectedRow.value?.consultationId || null,
|
||
consultationActivityId: formData.consultationActivityId,
|
||
consultationActivityName: formData.consultationActivityName,
|
||
consultationUrgency: formData.isUrgent ? '2' : '1',
|
||
consultationPurpose: formData.consultationPurpose,
|
||
consultationDate: formData.consultationDate,
|
||
consultationRequestDate: currentTime.value, // 使用动态申请时间
|
||
patientId: props.patientInfo.patientId,
|
||
encounterId: props.patientInfo.encounterId,
|
||
patientName: props.patientInfo.patientName,
|
||
// 🔧 Bug #263 修复:就诊卡号应取值于 identifierNo
|
||
patientBusNo: props.patientInfo.identifierNo || '',
|
||
patientIdentifierNo: props.patientInfo.identifierNo,
|
||
genderEnum: props.patientInfo.genderEnum,
|
||
age: ageValue,
|
||
provisionalDiagnosis: formData.provisionalDiagnosis,
|
||
// 申请医生和科室信息
|
||
requestingPhysician: formData.requestingPhysician || userStore.nickName,
|
||
requestingPhysicianId: userStore.practitionerId,
|
||
department: formData.department || userStore.orgName,
|
||
departmentId: userStore.orgId,
|
||
invitedList: invitedList,
|
||
};
|
||
|
||
console.log('保存会诊申请数据:', data);
|
||
|
||
const res = await saveConsultation(data);
|
||
if (res.code === 200) {
|
||
ElMessage.success('保存成功');
|
||
|
||
// 刷新列表
|
||
await loadConsultationList();
|
||
|
||
// 如果是新增,自动选中新创建的记录
|
||
if (!selectedRow.value && res.data) {
|
||
const newRow = consultationList.value.find(item => item.consultationId === res.data);
|
||
if (newRow) {
|
||
handleRowClick(newRow);
|
||
}
|
||
}
|
||
} else {
|
||
ElMessage.error(res.msg || '保存失败');
|
||
}
|
||
} catch (error) {
|
||
console.error('保存失败:', error);
|
||
if (error !== 'cancel') {
|
||
ElMessage.error('保存失败: ' + (error.message || error));
|
||
}
|
||
}
|
||
};
|
||
|
||
// 提交单行
|
||
const handleSubmitRow = async (row) => {
|
||
// 校验必填字段
|
||
if (!row.consultationDate) {
|
||
ElMessage.warning('请先设置会诊时间');
|
||
return;
|
||
}
|
||
|
||
if (!row.invitedList || row.invitedList.length === 0) {
|
||
ElMessage.warning('请至少选择1位会诊专家');
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const res = await submitConsultation({ consultationId: row.consultationId });
|
||
if (res.code === 200) {
|
||
ElMessage.success('提交成功');
|
||
loadConsultationList();
|
||
} else {
|
||
ElMessage.error(res.msg || '提交失败');
|
||
}
|
||
} catch (error) {
|
||
console.error('提交失败:', error);
|
||
ElMessage.error('提交失败');
|
||
}
|
||
};
|
||
|
||
// 取消提交
|
||
const handleCancelSubmit = async (row) => {
|
||
try {
|
||
await ElMessageBox.confirm('确定要取消提交吗?', '提示', {
|
||
confirmButtonText: '确定',
|
||
cancelButtonText: '取消',
|
||
type: 'warning',
|
||
});
|
||
|
||
// 调用后端接口取消提交(将状态从10改为0)
|
||
const res = await cancelConsultation({
|
||
consultationId: row.consultationId,
|
||
cancelReason: '取消提交',
|
||
});
|
||
|
||
if (res.code === 200) {
|
||
ElMessage.success('取消提交成功');
|
||
loadConsultationList();
|
||
} else {
|
||
ElMessage.error(res.msg || '取消提交失败');
|
||
}
|
||
} catch (error) {
|
||
if (error !== 'cancel') {
|
||
console.error('取消提交失败:', error);
|
||
ElMessage.error('取消提交失败');
|
||
}
|
||
}
|
||
};
|
||
|
||
// 结束会诊(顶部按钮)
|
||
const handleComplete = async () => {
|
||
if (!selectedRow.value) {
|
||
ElMessage.warning('请先选择要结束的会诊申请');
|
||
return;
|
||
}
|
||
|
||
// 校验状态:只有已签名状态(30)才能结束
|
||
if (selectedRow.value.consultationStatus !== 30) {
|
||
ElMessage.warning('只有已签名状态的会诊申请才能结束');
|
||
return;
|
||
}
|
||
|
||
try {
|
||
await ElMessageBox.confirm('确定要结束该会诊吗?', '提示', {
|
||
confirmButtonText: '确定',
|
||
cancelButtonText: '取消',
|
||
type: 'warning',
|
||
});
|
||
|
||
// 调用后端接口结束会诊
|
||
const res = await completeConsultation(selectedRow.value.consultationId);
|
||
|
||
if (res.code === 200) {
|
||
ElMessage.success('会诊已结束');
|
||
loadConsultationList();
|
||
} else {
|
||
ElMessage.error(res.msg || '结束失败');
|
||
}
|
||
} catch (error) {
|
||
if (error !== 'cancel') {
|
||
console.error('结束失败:', error);
|
||
ElMessage.error('结束失败');
|
||
}
|
||
}
|
||
};
|
||
|
||
// 结束会诊(表格行按钮)
|
||
const handleCompleteRow = async (row) => {
|
||
// 校验状态:只有已签名状态(30)才能结束
|
||
if (row.consultationStatus !== 30) {
|
||
ElMessage.warning('只有已签名状态的会诊申请才能结束');
|
||
return;
|
||
}
|
||
|
||
try {
|
||
await ElMessageBox.confirm('确定要结束该会诊吗?', '提示', {
|
||
confirmButtonText: '确定',
|
||
cancelButtonText: '取消',
|
||
type: 'warning',
|
||
});
|
||
|
||
// 调用后端接口结束会诊
|
||
const res = await completeConsultation(row.consultationId);
|
||
|
||
if (res.code === 200) {
|
||
ElMessage.success('会诊已结束');
|
||
loadConsultationList();
|
||
} else {
|
||
ElMessage.error(res.msg || '结束失败');
|
||
}
|
||
} catch (error) {
|
||
if (error !== 'cancel') {
|
||
console.error('结束失败:', error);
|
||
ElMessage.error('结束失败');
|
||
}
|
||
}
|
||
};
|
||
|
||
// 查看详情
|
||
const handleView = (row) => {
|
||
handleRowClick(row);
|
||
// 根据状态显示不同的提示消息
|
||
if (row.consultationStatus === 10 && hasConfirmedOrSignedDoctor(row)) {
|
||
ElMessage.info('已有医生确认或签名,无法取消提交,仅可查看');
|
||
} else if (row.consultationStatus === 20) {
|
||
ElMessage.info('该申请已确认,等待签名');
|
||
} else if (row.consultationStatus === 40) {
|
||
ElMessage.info('该申请已完成,仅可查看');
|
||
} else if (row.consultationStatus === 50) {
|
||
ElMessage.info('该申请已取消,仅可查看');
|
||
}
|
||
};
|
||
|
||
// 作废
|
||
const handleCancel = async () => {
|
||
if (!selectedRow.value) {
|
||
ElMessage.warning('请先选择一条记录');
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const { value } = await ElMessageBox.prompt('请输入作废原因', '作废会诊申请', {
|
||
confirmButtonText: '确定',
|
||
cancelButtonText: '取消',
|
||
inputPattern: /.+/,
|
||
inputErrorMessage: '请输入作废原因',
|
||
});
|
||
|
||
const res = await cancelConsultation({
|
||
consultationId: selectedRow.value.consultationId,
|
||
cancelReason: value,
|
||
});
|
||
|
||
if (res.code === 200) {
|
||
ElMessage.success('作废成功');
|
||
loadConsultationList();
|
||
handleNew();
|
||
} else {
|
||
ElMessage.error(res.msg || '作废失败');
|
||
}
|
||
} catch (error) {
|
||
if (error !== 'cancel') {
|
||
console.error('作废失败:', error);
|
||
}
|
||
}
|
||
};
|
||
|
||
// 作废行
|
||
const handleDeleteRow = async (row) => {
|
||
try {
|
||
await ElMessageBox.confirm('确定要作废这条会诊申请吗?', '提示', {
|
||
confirmButtonText: '确定',
|
||
cancelButtonText: '取消',
|
||
type: 'warning',
|
||
});
|
||
|
||
const res = await cancelConsultation({
|
||
consultationId: row.consultationId,
|
||
cancelReason: '作废',
|
||
});
|
||
|
||
if (res.code === 200) {
|
||
ElMessage.success('作废成功');
|
||
loadConsultationList();
|
||
if (selectedRow.value?.consultationId === row.consultationId) {
|
||
handleNew();
|
||
}
|
||
} else {
|
||
ElMessage.error(res.msg || '作废失败');
|
||
}
|
||
} catch (error) {
|
||
if (error !== 'cancel') {
|
||
console.error('作废失败:', error);
|
||
}
|
||
}
|
||
};
|
||
|
||
// 打印
|
||
const handlePrint = () => {
|
||
ElMessage.info('打印功能开发中...');
|
||
};
|
||
|
||
// 暴露给父组件的方法
|
||
const fetchConsultationList = () => {
|
||
loadConsultationList();
|
||
};
|
||
|
||
// 暴露方法给父组件
|
||
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,
|
||
(newVal) => {
|
||
if (newVal === 'consultation' && props.patientInfo?.encounterId) {
|
||
console.log('切换到会诊tab,加载数据');
|
||
// 并行加载数据,提升性能
|
||
loadConsultationList();
|
||
handleNew();
|
||
} else if (newVal === 'consultation') {
|
||
console.log('切换到会诊tab,但没有患者信息');
|
||
// 即使没有患者信息,也要加载基础数据(会诊项目和科室树)
|
||
handleNew();
|
||
}
|
||
}
|
||
);
|
||
|
||
// 监听患者信息变化
|
||
watch(
|
||
() => props.patientInfo?.encounterId,
|
||
(newVal) => {
|
||
if (newVal && props.activeTab === 'consultation') {
|
||
console.log('患者信息变化,重新加载数据');
|
||
loadConsultationList();
|
||
handleNew();
|
||
}
|
||
}
|
||
);
|
||
|
||
// 初始化
|
||
onMounted(() => {
|
||
console.log('会诊组件已挂载');
|
||
loadActivityList();
|
||
loadDepartmentTree();
|
||
|
||
// 初始化当前时间并启动实时更新(每秒更新一次)
|
||
currentTime.value = formatDateTime(new Date());
|
||
timeTimer = setInterval(() => {
|
||
currentTime.value = formatDateTime(new Date());
|
||
}, 1000);
|
||
|
||
if (props.activeTab === 'consultation' && props.patientInfo?.encounterId) {
|
||
loadConsultationList();
|
||
handleNew();
|
||
}
|
||
});
|
||
|
||
// 组件卸载时清除定时器
|
||
onUnmounted(() => {
|
||
if (timeTimer) {
|
||
clearInterval(timeTimer);
|
||
}
|
||
});
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
.consultation-container {
|
||
padding: 10px;
|
||
background: #f5f7fa;
|
||
height: calc(100vh - 200px);
|
||
display: flex;
|
||
flex-direction: column;
|
||
|
||
.top-actions {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
margin-bottom: 10px;
|
||
|
||
.left-actions {
|
||
display: flex;
|
||
gap: 10px;
|
||
}
|
||
|
||
.right-actions {
|
||
display: flex;
|
||
gap: 10px;
|
||
}
|
||
}
|
||
|
||
.consultation-list {
|
||
background: #fff;
|
||
padding: 10px;
|
||
border-radius: 4px;
|
||
margin-bottom: 10px;
|
||
}
|
||
|
||
.content-area {
|
||
display: flex;
|
||
gap: 10px;
|
||
flex: 1;
|
||
overflow: hidden;
|
||
|
||
.left-panel {
|
||
flex: 1;
|
||
background: #fff;
|
||
padding: 15px;
|
||
border-radius: 4px;
|
||
overflow-y: auto;
|
||
|
||
.panel-title {
|
||
font-size: 16px;
|
||
font-weight: bold;
|
||
color: #303133;
|
||
margin-bottom: 15px;
|
||
padding-bottom: 10px;
|
||
border-bottom: 2px solid #409eff;
|
||
}
|
||
|
||
.section-title {
|
||
font-size: 14px;
|
||
font-weight: bold;
|
||
color: #303133;
|
||
margin: 20px 0 10px 0;
|
||
}
|
||
|
||
.consultation-form {
|
||
:deep(.el-form-item) {
|
||
margin-bottom: 12px;
|
||
}
|
||
|
||
:deep(.el-form-item__label) {
|
||
font-size: 13px;
|
||
}
|
||
|
||
.invited-display {
|
||
min-height: 60px;
|
||
padding: 10px;
|
||
background: #f0f9ff;
|
||
border: 1px dashed #409eff;
|
||
border-radius: 4px;
|
||
|
||
.invited-list {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 5px;
|
||
}
|
||
|
||
.empty-invited {
|
||
color: #909399;
|
||
font-size: 13px;
|
||
text-align: center;
|
||
padding: 10px 0;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.right-panel {
|
||
width: 280px;
|
||
background: #fff;
|
||
padding: 15px;
|
||
border-radius: 4px;
|
||
overflow-y: auto;
|
||
|
||
.panel-title {
|
||
font-size: 16px;
|
||
font-weight: bold;
|
||
color: #303133;
|
||
margin-bottom: 15px;
|
||
padding-bottom: 10px;
|
||
border-bottom: 2px solid #409eff;
|
||
}
|
||
|
||
.selected-summary {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 10px;
|
||
background: #f0f9ff;
|
||
border: 1px solid #b3d8ff;
|
||
border-radius: 4px;
|
||
margin-bottom: 15px;
|
||
|
||
.summary-text {
|
||
font-size: 13px;
|
||
color: #606266;
|
||
}
|
||
|
||
.summary-count {
|
||
font-size: 18px;
|
||
font-weight: bold;
|
||
color: #409eff;
|
||
margin: 0 4px;
|
||
}
|
||
}
|
||
|
||
.invite-section {
|
||
margin-bottom: 15px;
|
||
|
||
.section-label {
|
||
font-size: 14px;
|
||
font-weight: 500;
|
||
color: #606266;
|
||
margin-bottom: 10px;
|
||
}
|
||
|
||
.department-list {
|
||
.department-item {
|
||
margin-bottom: 8px;
|
||
|
||
.dept-header {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 10px;
|
||
background: #f5f7fa;
|
||
border-radius: 4px;
|
||
cursor: pointer;
|
||
transition: all 0.3s;
|
||
|
||
&:hover {
|
||
background: #e6f7ff;
|
||
}
|
||
|
||
&.expanded {
|
||
background: #e6f7ff;
|
||
border-bottom-left-radius: 0;
|
||
border-bottom-right-radius: 0;
|
||
}
|
||
|
||
.el-icon {
|
||
font-size: 14px;
|
||
color: #606266;
|
||
margin-right: 8px;
|
||
transition: transform 0.3s;
|
||
}
|
||
|
||
.dept-name {
|
||
flex: 1;
|
||
font-size: 14px;
|
||
font-weight: 500;
|
||
color: #303133;
|
||
}
|
||
|
||
.selected-badge {
|
||
display: inline-block;
|
||
min-width: 20px;
|
||
height: 20px;
|
||
line-height: 20px;
|
||
text-align: center;
|
||
background: #67c23a;
|
||
color: #fff;
|
||
border-radius: 10px;
|
||
font-size: 12px;
|
||
padding: 0 6px;
|
||
}
|
||
}
|
||
|
||
.physicians-list {
|
||
background: #fafafa;
|
||
border: 1px solid #e6f7ff;
|
||
border-top: none;
|
||
border-bottom-left-radius: 4px;
|
||
border-bottom-right-radius: 4px;
|
||
padding: 10px;
|
||
|
||
.physician-item {
|
||
padding: 6px 10px;
|
||
|
||
:deep(.el-checkbox) {
|
||
width: 100%;
|
||
|
||
.el-checkbox__label {
|
||
font-size: 13px;
|
||
color: #606266;
|
||
}
|
||
|
||
&.is-checked .el-checkbox__label {
|
||
color: #409eff;
|
||
font-weight: 500;
|
||
}
|
||
}
|
||
}
|
||
|
||
.no-physicians {
|
||
color: #909399;
|
||
font-size: 12px;
|
||
text-align: center;
|
||
padding: 10px 0;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</style>
|