新增功能

This commit is contained in:
Your Name
2026-03-24 16:32:56 +08:00
parent 250d173c2f
commit 9160c36735
248 changed files with 3063 additions and 250 deletions
+117
View File
@@ -136,6 +136,30 @@
<span v-else class="status-unprescribed">未开方</span>
</template>
</el-table-column>
<el-table-column label="视频旁观" width="120" fixed="right" align="center">
<template #default="{ row }">
<div class="video-watch-col">
<template v-if="canWatchCallEntry(row)">
<template v-if="watchCallShowEnterButton(row)">
<el-tooltip :content="watchCallEnterTooltip(row)" placement="top">
<span class="video-watch-trigger">
<el-button
type="primary"
link
size="small"
@click="onWatchCallEntryClick(row)"
>
进入旁观
</el-button>
</span>
</el-tooltip>
</template>
<span v-else class="video-watch-muted">{{ watchCallAssistantIdleText(row) }}</span>
</template>
<span v-else class="video-watch-muted">{{ watchCallPublicStatus(row) }}</span>
</div>
</template>
</el-table-column>
<el-table-column label="操作" width="260" fixed="right" align="left">
<template #default="{ row }">
<div class="action-cell">
@@ -180,6 +204,11 @@
<edit-popup ref="editRef" @success="getLists" />
<detail-popup ref="detailRef" />
<appointment-popup ref="appointmentRef" @success="getLists" />
<assistant-watch-call-dialog
v-model="watchCallVisible"
:diagnosis-id="watchCallDiagnosisId"
@closed="getLists"
/>
<!-- 小程序二维码弹窗 -->
<el-dialog
@@ -465,6 +494,7 @@ import { Loading, Warning, List, CircleCheck, Clock, ArrowDown, RefreshRight, Pi
import EditPopup from './edit.vue'
import DetailPopup from './detail.vue'
import AppointmentPopup from './appointment.vue'
import AssistantWatchCallDialog from './components/AssistantWatchCallDialog.vue'
import useUserStore from '@/stores/modules/user'
import { useRoute } from 'vue-router'
import { nextTick } from 'vue'
@@ -681,6 +711,77 @@ const detailRef = ref()
const appointmentRef = ref()
const userStore = useUserStore()
const watchCallVisible = ref(false)
const watchCallDiagnosisId = ref(0)
const isAssignedAssistant = (row: any) => {
const aid = row.assistant_id ?? row.assistant
if (aid === null || aid === undefined || aid === '') return false
return Number(aid) === Number(userStore.userInfo?.id)
}
const openWatchCall = (row: any) => {
watchCallDiagnosisId.value = Number(row.id) || 0
watchCallVisible.value = true
}
type VideoCallHint = {
state: string
label: string
start_time?: number
end_time?: number
}
const canWatchCallEntry = (row: any) =>
isAssignedAssistant(row) && hasPermission(['tcm.diagnosis/watchCall'])
const watchCallState = (row: any) => (row.video_call_hint?.state as string) || 'none'
const watchCallLiveTooltip = (row: any) => {
const h = row.video_call_hint as VideoCallHint | undefined
const base = '点击进入实时房间(仅观看,不推流、不上麦)'
if (h?.start_time) {
return `${base}。开始时间:${formatDateTime(h.start_time)}`
}
return base
}
/** 通话进行中或已发起待同步房间时,都显示「进入旁观」入口(避免仅 live 才有按钮导致看不见) */
const watchCallShowEnterButton = (row: any) => {
const st = watchCallState(row)
return st === 'live' || st === 'pending_room'
}
const watchCallEnterTooltip = (row: any) => {
if (watchCallState(row) === 'pending_room') {
return '医生尚未接通或未同步房间号,接通后再点此进入'
}
return watchCallLiveTooltip(row)
}
const onWatchCallEntryClick = (row: any) => {
if (watchCallState(row) !== 'live') {
feedback.msgWarning('医生尚未接通或未同步房间号,请稍后再试')
return
}
openWatchCall(row)
}
const watchCallAssistantIdleText = (row: any) => {
const h = row.video_call_hint as VideoCallHint | undefined
if (h?.label) return h.label
return '暂无可旁观通话'
}
const watchCallPublicStatus = (row: any) => {
const st = watchCallState(row)
if (st === 'none') return '—'
if (st === 'live') return '通话中'
if (st === 'pending_room') return '接通中'
const h = row.video_call_hint as VideoCallHint | undefined
return h?.label || '—'
}
// 创建订单相关
const createOrderVisible = ref(false)
const orderFormRef = ref()
@@ -1443,6 +1544,22 @@ onMounted(async () => {
flex-wrap: wrap;
}
.video-watch-col {
font-size: 12px;
line-height: 1.4;
padding: 0 2px;
}
/* el-tooltip 单个子节点为行内按钮时,包一层避免触发区域为 0 或错位 */
.video-watch-trigger {
display: inline-block;
vertical-align: middle;
}
.video-watch-muted {
color: var(--el-text-color-secondary);
}
.text-danger {
color: var(--el-color-danger);
}