feat(surgery): 完善手术管理功能模块

- 添加手术申请相关API接口,包括根据患者ID查询就诊列表功能
- 在医生工作站界面集成手术申请功能选项卡
- 实现手术管理页面的完整功能,包括手术申请的增删改查
- 添加手术排期、开始、完成等状态流转功能
- 优化手术管理页面表格展示,增加手术类型、等级、计划时间等字段
- 实现手术申请表单的完整编辑和查看模式
- 集成患者信息和就诊记录关联功能
- 添加手术室、医生、护士等资源选择功能
- 更新系统依赖配置,添加core-common模块
- 优化图标资源和manifest配置文件
- 调整患者档案和门诊记录相关状态枚举
This commit is contained in:
2026-01-06 16:23:15 +08:00
parent fa2884b320
commit b0850257c8
66 changed files with 7683 additions and 313 deletions

View File

@@ -0,0 +1,372 @@
<template>
<div :class="['today-outpatient-page', { 'fullscreen-mode': isFullscreen }]">
<!-- 页面头部工具栏 -->
<div class="page-header-toolbar">
<el-row :gutter="10">
<el-col :span="18">
<div class="toolbar-left">
<h2 style="margin: 0; line-height: 32px;">
<i class="el-icon-calendar" style="margin-right: 8px;"></i>
今日门诊
<span v-if="isFullscreen" style="margin-left: 12px; font-size: 14px; color: #666;">
(全屏模式)
</span>
</h2>
</div>
</el-col>
<el-col :span="6">
<div class="toolbar-right">
<el-button-group>
<el-tooltip :content="isFullscreen ? '退出全屏模式' : '进入全屏模式'" placement="top">
<el-button
:type="isFullscreen ? 'warning' : 'primary'"
:icon="isFullscreen ? 'CloseBold' : 'FullScreen'"
@click="toggleFullscreen"
:loading="refreshing"
>
{{ isFullscreen ? '退出全屏' : '全屏' }}
</el-button>
</el-tooltip>
<el-tooltip content="刷新数据" placement="top">
<el-button
type="primary"
icon="Refresh"
@click="refreshData"
:loading="refreshing"
>
刷新
</el-button>
</el-tooltip>
<el-tooltip content="页面设置" placement="top">
<el-button
type="info"
icon="Setting"
@click="showSettings = true"
>
设置
</el-button>
</el-tooltip>
</el-button-group>
</div>
</el-col>
</el-row>
</div>
<!-- 内容区域 -->
<div class="content-area">
<!-- 统计卡片 -->
<div class="stats-section">
<today-outpatient-stats />
</div>
<!-- 患者列表 -->
<div class="patient-list-section">
<today-outpatient-patient-list />
</div>
</div>
<!-- 设置对话框 -->
<el-dialog
v-model="showSettings"
title="今日门诊设置"
width="500px"
>
<el-form :model="settingsForm" label-width="100px">
<el-form-item label="默认显示">
<el-select v-model="settingsForm.defaultView" placeholder="请选择默认视图">
<el-option label="待就诊" value="waiting" />
<el-option label="就诊中" value="inProgress" />
<el-option label="已完成" value="completed" />
<el-option label="全部" value="all" />
</el-select>
</el-form-item>
<el-form-item label="每页显示">
<el-input-number
v-model="settingsForm.pageSize"
:min="5"
:max="100"
:step="5"
/>
</el-form-item>
<el-form-item label="自动刷新">
<el-switch v-model="settingsForm.autoRefresh" />
<div style="margin-top: 8px; font-size: 12px; color: #999;">
启用后每30秒自动刷新数据
</div>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="showSettings = false">取消</el-button>
<el-button type="primary" @click="saveSettings">保存</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted, computed } from 'vue'
import { ElMessage } from 'element-plus'
import TodayOutpatientStats from './components/todayOutpatient/TodayOutpatientStats.vue'
import TodayOutpatientPatientList from './components/todayOutpatient/TodayOutpatientPatientList.vue'
// 数据
const showSettings = ref(false)
const refreshTimer = ref(null)
const refreshing = ref(false)
const isFullscreen = ref(false)
const settingsForm = ref({
defaultView: 'waiting',
pageSize: 10,
autoRefresh: false
})
// 页面加载
onMounted(() => {
loadSettings()
})
// 页面卸载
onUnmounted(() => {
if (refreshTimer.value) {
clearInterval(refreshTimer.value)
}
})
// 加载设置
const loadSettings = () => {
const savedSettings = localStorage.getItem('todayOutpatientSettings')
if (savedSettings) {
settingsForm.value = JSON.parse(savedSettings)
}
// 启动自动刷新
if (settingsForm.value.autoRefresh) {
startAutoRefresh()
}
}
// 保存设置
const saveSettings = () => {
localStorage.setItem('todayOutpatientSettings', JSON.stringify(settingsForm.value))
// 更新自动刷新
if (settingsForm.value.autoRefresh) {
startAutoRefresh()
} else {
stopAutoRefresh()
}
ElMessage.success('设置保存成功')
showSettings.value = false
}
// 开始自动刷新
const startAutoRefresh = () => {
stopAutoRefresh() // 先停止现有的定时器
refreshTimer.value = setInterval(() => {
refreshData()
}, 30000) // 30秒刷新一次
}
// 停止自动刷新
const stopAutoRefresh = () => {
if (refreshTimer.value) {
clearInterval(refreshTimer.value)
refreshTimer.value = null
}
}
// 刷新数据
const refreshData = () => {
refreshing.value = true
// 触发子组件的刷新方法
// 在实际应用中可以通过事件总线或provide/inject传递刷新方法
setTimeout(() => {
refreshing.value = false
ElMessage.success('数据已刷新')
}, 500)
}
// 全屏切换功能
const toggleFullscreen = () => {
if (!isFullscreen.value) {
// 进入全屏模式
const elem = document.documentElement
if (elem.requestFullscreen) {
elem.requestFullscreen()
} else if (elem.webkitRequestFullscreen) { /* Safari */
elem.webkitRequestFullscreen()
} else if (elem.msRequestFullscreen) { /* IE11 */
elem.msRequestFullscreen()
}
isFullscreen.value = true
ElMessage.success('已进入全屏模式')
} else {
// 退出全屏模式
if (document.exitFullscreen) {
document.exitFullscreen()
} else if (document.webkitExitFullscreen) { /* Safari */
document.webkitExitFullscreen()
} else if (document.msExitFullscreen) { /* IE11 */
document.msExitFullscreen()
}
isFullscreen.value = false
ElMessage.success('已退出全屏模式')
}
}
// 监听全屏状态变化
const handleFullscreenChange = () => {
isFullscreen.value = !!(
document.fullscreenElement ||
document.webkitFullscreenElement ||
document.msFullscreenElement
)
}
// 监听键盘事件ESC退出全屏
const handleKeyDown = (e) => {
if (e.key === 'Escape' && isFullscreen.value) {
toggleFullscreen()
}
}
// 页面加载时添加监听器
onMounted(() => {
loadSettings()
document.addEventListener('fullscreenchange', handleFullscreenChange)
document.addEventListener('webkitfullscreenchange', handleFullscreenChange)
document.addEventListener('msfullscreenchange', handleFullscreenChange)
document.addEventListener('keydown', handleKeyDown)
})
// 页面卸载时移除监听器
onUnmounted(() => {
if (refreshTimer.value) {
clearInterval(refreshTimer.value)
}
document.removeEventListener('fullscreenchange', handleFullscreenChange)
document.removeEventListener('webkitfullscreenchange', handleFullscreenChange)
document.removeEventListener('msfullscreenchange', handleFullscreenChange)
document.removeEventListener('keydown', handleKeyDown)
})
</script>
<style lang="scss" scoped>
.today-outpatient-page {
height: 100%;
display: flex;
flex-direction: column;
background-color: #f5f7fa;
// 全屏模式样式
&.fullscreen-mode {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 9999;
background: white;
padding: 0 !important;
.page-header-toolbar {
background: #fff !important;
border-bottom: 1px solid #dcdfe6 !important;
}
}
.page-header-toolbar {
background: #f5f7fa;
padding: 16px 20px;
border-bottom: 1px solid #ebeef5;
margin-bottom: 20px;
flex-shrink: 0;
.toolbar-left {
display: flex;
align-items: center;
h2 {
margin: 0;
font-size: 18px;
font-weight: 600;
color: #333;
.el-icon-calendar {
color: #409eff;
}
}
}
.toolbar-right {
display: flex;
justify-content: flex-end;
align-items: center;
.el-button-group {
display: flex;
gap: 8px;
}
}
}
.content-area {
flex: 1;
overflow: hidden;
padding: 0 20px 20px 20px;
display: flex;
flex-direction: column;
}
.stats-section {
margin-bottom: 20px;
flex-shrink: 0;
}
.patient-list-section {
flex: 1;
min-height: 0;
background: white;
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
overflow: auto;
}
}
// 全屏模式下的特定样式
:fullscreen .today-outpatient-page,
:-webkit-full-screen .today-outpatient-page,
:-moz-full-screen .today-outpatient-page,
:-ms-fullscreen .today-outpatient-page {
&.fullscreen-mode {
.content-area {
padding: 0 20px;
}
}
}
// 响应式设计
@media (max-width: 768px) {
.today-outpatient-page {
.page-header-toolbar {
padding: 12px;
.toolbar-left h2 {
font-size: 16px;
}
}
.content-area {
padding: 0 12px 12px 12px;
}
.patient-list-section {
padding: 12px;
}
}
}
</style>