885 lines
33 KiB
Vue
885 lines
33 KiB
Vue
<template>
|
||
<div class="tcm-diagnosis">
|
||
<el-card class="!border-none" shadow="never">
|
||
<el-form class="ls-form" :model="formData" inline>
|
||
<el-form-item class="w-[280px]" label="患者姓名">
|
||
<el-input
|
||
placeholder="请输入患者姓名"
|
||
v-model="formData.patient_name"
|
||
clearable
|
||
@keyup.enter="resetPage"
|
||
/>
|
||
</el-form-item>
|
||
|
||
<el-form-item class="w-[280px]" label="诊断类型">
|
||
<el-select v-model="formData.diagnosis_type" placeholder="请选择" clearable>
|
||
<el-option
|
||
v-for="item in diagnosisTypeOptions"
|
||
:key="item.value"
|
||
:label="item.name"
|
||
:value="item.value"
|
||
/>
|
||
</el-select>
|
||
</el-form-item>
|
||
|
||
<el-form-item class="w-[280px]" label="证型">
|
||
<el-select v-model="formData.syndrome_type" placeholder="请选择" clearable>
|
||
<el-option
|
||
v-for="item in syndromeTypeOptions"
|
||
:key="item.value"
|
||
:label="item.name"
|
||
:value="item.value"
|
||
/>
|
||
</el-select>
|
||
</el-form-item>
|
||
|
||
<el-form-item class="w-[280px]" label="医助">
|
||
<el-select v-model="formData.assistant_id" placeholder="请选择" clearable filterable>
|
||
<el-option
|
||
v-for="item in assistantOptions"
|
||
:key="item.id"
|
||
:label="item.name"
|
||
:value="Number(item.id)"
|
||
/>
|
||
</el-select>
|
||
</el-form-item>
|
||
|
||
|
||
<el-form-item>
|
||
<el-button type="primary" @click="resetPage">查询</el-button>
|
||
<el-button @click="resetParams">重置</el-button>
|
||
</el-form-item>
|
||
</el-form>
|
||
</el-card>
|
||
|
||
<el-card class="!border-none mt-4" shadow="never">
|
||
<div class="mb-4 flex justify-between items-center">
|
||
<div>
|
||
<el-button type="primary" @click="handleAdd" v-perms="['tcm.diagnosis/add']">新增诊单</el-button>
|
||
<el-button
|
||
v-perms="['tcm.diagnosis/assign']"
|
||
type="success"
|
||
@click="handleBatchAssign"
|
||
:disabled="selectedIds.length === 0"
|
||
>
|
||
批量指派医助
|
||
</el-button>
|
||
</div>
|
||
<div v-if="selectedIds.length > 0" class="text-gray-500">
|
||
已选择 {{ selectedIds.length }} 条记录
|
||
</div>
|
||
</div>
|
||
<el-table
|
||
:data="pager.lists"
|
||
size="large"
|
||
v-loading="pager.loading"
|
||
@selection-change="handleSelectionChange"
|
||
>
|
||
<el-table-column type="selection" width="55" />
|
||
<el-table-column label="账户编号" prop="id" width="90" />
|
||
<el-table-column label="账户姓名" prop="patient_name" min-width="100" />
|
||
|
||
<el-table-column label="性别" prop="gender_desc" width="80" />
|
||
<el-table-column label="年龄" prop="age" width="80" />
|
||
<el-table-column label="诊断日期" prop="diagnosis_date_text" min-width="120" />
|
||
<el-table-column label="诊断类型" prop="diagnosis_type" min-width="100">
|
||
<template #default="{ row }">
|
||
<span>{{ getDictLabel(diagnosisTypeOptions, row.diagnosis_type) }}</span>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="确认诊单" min-width="100">
|
||
<template #default="{ row }">
|
||
<el-tag v-if="row.DiagnosisViewRecord && row.DiagnosisViewRecord.length > 0" type="success" size="small">已确认</el-tag>
|
||
<el-tag v-else type="info" size="small">未确认</el-tag>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="证型" prop="syndrome_type" min-width="100">
|
||
<template #default="{ row }">
|
||
<span>{{ getDictLabel(syndromeTypeOptions, row.syndrome_type) }}</span>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="归属助理" prop="assistant_name" min-width="100">
|
||
<template #default="{ row }">
|
||
<span>{{ getAssistantName(row.assistant_id || row.assistant) }}</span>
|
||
</template>
|
||
</el-table-column>
|
||
<!-- <el-table-column label="状态" width="80">
|
||
<template #default="{ row }">
|
||
<el-tag v-if="row.status == 1" type="success">启用</el-tag>
|
||
<el-tag v-else type="danger">禁用</el-tag>
|
||
</template>
|
||
</el-table-column> -->
|
||
<el-table-column label="创建时间" prop="create_time" min-width="160">
|
||
<template #default="{ row }">
|
||
<span>{{ formatDateTime(row.create_time) }}</span>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="操作" width="300" fixed="right">
|
||
<template #default="{ row }">
|
||
<!-- <el-button type="primary" link @click="handleDetail(row.id)">
|
||
查看
|
||
</el-button> -->
|
||
<el-button
|
||
v-perms="['tcm.diagnosis/assign']"
|
||
type="success"
|
||
link
|
||
@click="handleSingleAssign(row)"
|
||
>
|
||
指派
|
||
</el-button>
|
||
<!-- <el-button
|
||
v-perms="['tcm.diagnosis/video-call']"
|
||
type="success"
|
||
link
|
||
@click="handleVideoCall(row)"
|
||
>
|
||
1V1通话
|
||
</el-button>
|
||
<el-button
|
||
v-perms="['tcm.diagnosis/video-group']"
|
||
type="success"
|
||
link
|
||
@click="handleGroupVideoCall(row)"
|
||
>
|
||
群通话
|
||
</el-button>-->
|
||
<el-button
|
||
v-perms="['tcm.diagnosis/guahao']"
|
||
type="success"
|
||
link
|
||
@click="handleAppointment(row)"
|
||
>
|
||
预约医生
|
||
</el-button>
|
||
<el-button
|
||
v-perms="['tcm.diagnosis/guahao']"
|
||
type="success"
|
||
link
|
||
@click="handleMiniProgramQRCode(row)"
|
||
>
|
||
确认诊单二维码
|
||
</el-button>
|
||
<el-button type="primary" link @click="handleEdit(row.id)" v-perms="['tcm.diagnosis/edit']">
|
||
诊单
|
||
</el-button>
|
||
<!-- <el-button type="primary" link @click="handleWechatRecords(row)">
|
||
企微记录
|
||
</el-button> -->
|
||
<el-button type="primary" link @click="handleCreateOrder(row)">
|
||
创建订单
|
||
</el-button>
|
||
<el-button type="danger" link @click="handleDelete(row.id)" v-perms="['tcm.diagnosis/delete']">
|
||
删除
|
||
</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
<div class="flex mt-4 justify-end">
|
||
<pagination v-model="pager" @change="getLists" />
|
||
</div>
|
||
</el-card>
|
||
|
||
<edit-popup ref="editRef" @success="getLists" />
|
||
<detail-popup ref="detailRef" />
|
||
<appointment-popup ref="appointmentRef" @success="getLists" />
|
||
|
||
<!-- 小程序二维码弹窗 -->
|
||
<el-dialog
|
||
v-model="qrcodeDialogVisible"
|
||
title="小程序二维码"
|
||
width="400px"
|
||
:close-on-click-modal="false"
|
||
>
|
||
<div class="flex flex-col items-center justify-center py-4">
|
||
<div v-if="qrcodeLoading" class="text-center">
|
||
<el-icon class="is-loading" :size="40">
|
||
<Loading />
|
||
</el-icon>
|
||
<div class="mt-4 text-gray-500">生成中...</div>
|
||
</div>
|
||
<div v-else-if="qrcodeUrl" class="text-center">
|
||
<img :src="qrcodeUrl" alt="小程序二维码" class="w-64 h-64 border border-gray-200 rounded" />
|
||
<div class="mt-4 text-sm text-gray-600">
|
||
<div>患者:{{ currentQRCodePatient?.patient_name }}</div>
|
||
<div class="mt-2">请使用微信扫描二维码</div>
|
||
</div>
|
||
</div>
|
||
<div v-else class="text-center text-gray-500">
|
||
生成失败,请重试
|
||
</div>
|
||
</div>
|
||
<template #footer>
|
||
<el-button @click="qrcodeDialogVisible = false">关闭</el-button>
|
||
<el-button v-if="!qrcodeLoading" type="primary" @click="handleRegenerateQRCode">
|
||
重新生成
|
||
</el-button>
|
||
</template>
|
||
</el-dialog>
|
||
|
||
<!-- 批量指派医助弹窗 -->
|
||
<el-dialog
|
||
v-model="assignDialogVisible"
|
||
:title="assignMode === 'batch' ? '批量指派医助' : '指派医助'"
|
||
width="500px"
|
||
>
|
||
<el-form :model="assignForm" label-width="100px">
|
||
<el-form-item label="选择医助" required>
|
||
<el-select
|
||
v-model="assignForm.assistant_id"
|
||
placeholder="请选择医助"
|
||
class="w-full"
|
||
filterable
|
||
clearable
|
||
value-key="id"
|
||
>
|
||
<el-option
|
||
v-for="item in assistantOptions"
|
||
:key="item.id"
|
||
:label="item.name"
|
||
:value="Number(item.id)"
|
||
/>
|
||
</el-select>
|
||
</el-form-item>
|
||
<el-form-item v-if="assignMode === 'batch'" label="已选择">
|
||
<div class="text-gray-500">{{ selectedIds.length }} 条诊单记录</div>
|
||
</el-form-item>
|
||
<el-form-item v-else label="诊单信息">
|
||
<div class="text-gray-500">
|
||
<div>患者:{{ currentRow?.patient_name }}</div>
|
||
<div>诊断日期:{{ currentRow?.diagnosis_date_text }}</div>
|
||
</div>
|
||
</el-form-item>
|
||
</el-form>
|
||
<template #footer>
|
||
<el-button @click="assignDialogVisible = false">取消</el-button>
|
||
<el-button
|
||
type="primary"
|
||
@click="handleConfirmAssign"
|
||
:loading="assignLoading"
|
||
>
|
||
确定指派
|
||
</el-button>
|
||
</template>
|
||
</el-dialog>
|
||
|
||
<!-- 创建订单弹窗 -->
|
||
<el-dialog
|
||
v-model="createOrderVisible"
|
||
title="创建订单"
|
||
width="600px"
|
||
@close="resetOrderForm"
|
||
>
|
||
<el-form
|
||
ref="orderFormRef"
|
||
:model="orderForm"
|
||
:rules="orderRules"
|
||
label-width="100px"
|
||
>
|
||
<el-form-item label="患者">
|
||
<span class="font-medium">{{ orderForm.patient_name }} ({{ orderForm.phone }})</span>
|
||
</el-form-item>
|
||
|
||
<el-form-item label="订单类型" prop="order_type">
|
||
<el-select v-model="orderForm.order_type" placeholder="请选择" class="w-full">
|
||
<el-option label="挂号费" :value="1" />
|
||
<el-option label="问诊费" :value="2" />
|
||
<el-option label="药品费用" :value="3" />
|
||
</el-select>
|
||
</el-form-item>
|
||
|
||
<el-form-item label="订单金额" prop="amount">
|
||
<el-input-number
|
||
v-model="orderForm.amount"
|
||
:min="0"
|
||
:step="0.01"
|
||
:precision="2"
|
||
placeholder="请输入金额"
|
||
class="w-full"
|
||
/>
|
||
</el-form-item>
|
||
|
||
<el-form-item label="备注" prop="remark">
|
||
<el-input
|
||
v-model="orderForm.remark"
|
||
type="textarea"
|
||
:rows="3"
|
||
placeholder="请输入备注(可选)"
|
||
/>
|
||
</el-form-item>
|
||
</el-form>
|
||
<template #footer>
|
||
<el-button @click="createOrderVisible = false">取消</el-button>
|
||
<el-button type="primary" @click="submitOrder" :loading="orderLoading">创建订单</el-button>
|
||
</template>
|
||
</el-dialog>
|
||
|
||
<!-- 企业微信聊天记录抽屉 -->
|
||
<el-drawer
|
||
v-model="wechatDrawerVisible"
|
||
:title="`企业微信记录 - ${wechatCurrentPatient?.patient_name || ''}`"
|
||
size="600px"
|
||
:destroy-on-close="true"
|
||
>
|
||
<!-- 患者与企微信息 -->
|
||
<div v-if="wechatContactInfo" class="mb-4">
|
||
<el-descriptions :column="2" border size="small">
|
||
<el-descriptions-item label="患者姓名">{{ wechatCurrentPatient?.patient_name }}</el-descriptions-item>
|
||
<el-descriptions-item label="手机号">{{ wechatContactInfo.phone || '-' }}</el-descriptions-item>
|
||
<el-descriptions-item label="企微联系人ID">
|
||
<span v-if="wechatContactInfo.external_userid">{{ wechatContactInfo.external_userid }}</span>
|
||
<el-tag v-else type="info" size="small">未关联</el-tag>
|
||
</el-descriptions-item>
|
||
<el-descriptions-item label="会话存档">
|
||
<el-tag v-if="wechatContactInfo.msgaudit_enabled" type="success" size="small">已开通</el-tag>
|
||
<el-tag v-else type="info" size="small">未配置</el-tag>
|
||
</el-descriptions-item>
|
||
</el-descriptions>
|
||
<!-- 存档成员列表 -->
|
||
<div v-if="wechatContactInfo.permit_users?.length" class="mt-2">
|
||
<span class="text-sm text-gray-500 mr-2">存档成员:</span>
|
||
<el-tag
|
||
v-for="uid in wechatContactInfo.permit_users"
|
||
:key="uid"
|
||
size="small"
|
||
class="mr-1"
|
||
>
|
||
{{ uid }}
|
||
</el-tag>
|
||
</div>
|
||
<!-- 同意存档情况 -->
|
||
<div v-if="wechatContactInfo.msgaudit_agree?.length" class="mt-2">
|
||
<span class="text-sm text-gray-500 mr-2">存档同意:</span>
|
||
<el-tag
|
||
v-for="(info, idx) in wechatContactInfo.msgaudit_agree"
|
||
:key="idx"
|
||
:type="info.agree_status === 'Agree' ? 'success' : 'warning'"
|
||
size="small"
|
||
class="mr-1"
|
||
>
|
||
{{ info.userid }}: {{ info.agree_status === 'Agree' ? '已同意' : info.agree_status }}
|
||
</el-tag>
|
||
</div>
|
||
</div>
|
||
|
||
<el-divider />
|
||
|
||
<!-- 添加记录 -->
|
||
<div class="mb-4">
|
||
<div class="flex gap-2">
|
||
<el-input
|
||
v-model="wechatNewNote"
|
||
type="textarea"
|
||
:rows="2"
|
||
placeholder="添加沟通记录..."
|
||
class="flex-1"
|
||
/>
|
||
<el-button type="primary" @click="handleAddRecord" :loading="wechatAddLoading" class="self-end">
|
||
添加
|
||
</el-button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 记录列表 -->
|
||
<div v-loading="wechatRecordsLoading">
|
||
<div v-if="wechatRecords.length === 0" class="text-center text-gray-400 py-10">
|
||
暂无聊天记录
|
||
</div>
|
||
<div v-else class="record-list">
|
||
<div
|
||
v-for="record in wechatRecords"
|
||
:key="record.id"
|
||
class="record-item"
|
||
>
|
||
<div class="record-header">
|
||
<div class="flex items-center gap-2">
|
||
<el-tag :type="record.direction === 0 ? 'primary' : 'success'" size="small">
|
||
{{ record.direction === 0 ? '员工' : '客户' }}
|
||
</el-tag>
|
||
<span class="font-medium text-sm">
|
||
{{ record.direction === 0 ? record.staff_name : record.external_name || wechatCurrentPatient?.patient_name }}
|
||
</span>
|
||
<el-tag v-if="record.msg_type === 'note'" type="warning" size="small">备注</el-tag>
|
||
</div>
|
||
<div class="flex items-center gap-2">
|
||
<span class="text-xs text-gray-400">{{ formatTimestamp(record.chat_time) }}</span>
|
||
<el-button type="danger" link size="small" @click="handleDeleteRecord(record.id)">
|
||
删除
|
||
</el-button>
|
||
</div>
|
||
</div>
|
||
<div class="record-content">{{ record.content }}</div>
|
||
<div v-if="record.media_url" class="mt-1">
|
||
<el-image :src="record.media_url" style="max-width: 200px" fit="contain" :preview-src-list="[record.media_url]" />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div v-if="wechatRecordTotal > wechatRecords.length" class="text-center mt-4">
|
||
<el-button link type="primary" @click="loadMoreRecords">加载更多</el-button>
|
||
</div>
|
||
</div>
|
||
</el-drawer>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts" name="tcmDiagnosis">
|
||
import { tcmDiagnosisLists, tcmDiagnosisDelete, tcmDiagnosisAssign, getAssistants, generateMiniProgramQrcode, generateOrderQrcode, getWechatChatRecords, addWechatChatRecord, deleteWechatChatRecord, getWechatExternalContact } from '@/api/tcm'
|
||
import { orderCreate } from '@/api/order'
|
||
import { usePaging } from '@/hooks/usePaging'
|
||
import { getDictData } from '@/api/app'
|
||
import { getWeappConfig } from '@/api/channel/weapp'
|
||
import feedback from '@/utils/feedback'
|
||
import { Loading } from '@element-plus/icons-vue'
|
||
import EditPopup from './edit.vue'
|
||
import DetailPopup from './detail.vue'
|
||
import AppointmentPopup from './appointment.vue'
|
||
import useUserStore from '@/stores/modules/user'
|
||
import dayjs from 'dayjs'
|
||
|
||
// 格式化时间戳为日期时间
|
||
const formatDateTime = (timestamp: number | string) => {
|
||
if (!timestamp) return '-'
|
||
// 如果是秒级时间戳(10位),转换为毫秒级
|
||
const ts = String(timestamp).length === 10 ? Number(timestamp) * 1000 : Number(timestamp)
|
||
return dayjs(ts).format('YYYY-MM-DD HH:mm:ss')
|
||
}
|
||
|
||
const formData = ref({
|
||
patient_name: '',
|
||
diagnosis_type: '',
|
||
syndrome_type: '',
|
||
assistant_id: '',
|
||
start_time: '',
|
||
end_time: ''
|
||
})
|
||
|
||
// 获取字典选项
|
||
const diagnosisTypeOptions = ref<any[]>([])
|
||
const syndromeTypeOptions = ref<any[]>([])
|
||
const assistantOptions = ref<any[]>([])
|
||
|
||
const getDictOptions = async () => {
|
||
try {
|
||
const [diagnosisType, syndromeType, assistants] = await Promise.all([
|
||
getDictData({ type: 'diagnosis_type' }),
|
||
getDictData({ type: 'syndrome_type' }),
|
||
getAssistants()
|
||
])
|
||
diagnosisTypeOptions.value = diagnosisType?.diagnosis_type || []
|
||
syndromeTypeOptions.value = syndromeType?.syndrome_type || []
|
||
assistantOptions.value = assistants || []
|
||
|
||
// 调试:打印医助列表
|
||
console.log('医助列表数据:', assistants)
|
||
console.log('assistantOptions:', assistantOptions.value)
|
||
} catch (error) {
|
||
console.error('获取字典数据失败:', error)
|
||
}
|
||
}
|
||
|
||
// 获取字典标签
|
||
const getDictLabel = (options: any[], value: string) => {
|
||
const item = options.find(opt => opt.value === value)
|
||
return item ? item.name : value || '-'
|
||
}
|
||
|
||
// 获取医助名称
|
||
const getAssistantName = (assistantId: number | string) => {
|
||
// 如果没有assistant_id,返回"-"
|
||
if (!assistantId && assistantId !== 0) return '-'
|
||
|
||
// 确保类型匹配,转换为数字进行比较
|
||
const id = typeof assistantId === 'string' ? parseInt(assistantId) : assistantId
|
||
|
||
// 如果医助列表还没加载,返回"加载中..."
|
||
if (assistantOptions.value.length === 0) return '...'
|
||
|
||
const assistant = assistantOptions.value.find(item => {
|
||
const itemId = typeof item.id === 'string' ? parseInt(item.id) : item.id
|
||
return itemId === id
|
||
})
|
||
|
||
return assistant ? assistant.name : '-'
|
||
}
|
||
|
||
const { pager, getLists, resetParams, resetPage } = usePaging({
|
||
fetchFun: tcmDiagnosisLists,
|
||
params: formData.value
|
||
})
|
||
|
||
const editRef = ref()
|
||
const detailRef = ref()
|
||
const appointmentRef = ref()
|
||
const userStore = useUserStore()
|
||
|
||
// 创建订单相关
|
||
const createOrderVisible = ref(false)
|
||
const orderFormRef = ref()
|
||
const orderLoading = ref(false)
|
||
const orderForm = reactive({
|
||
patient_id: '' as string | number,
|
||
patient_name: '',
|
||
phone: '',
|
||
order_type: '' as string | number,
|
||
amount: 0,
|
||
remark: ''
|
||
})
|
||
const orderRules = {
|
||
order_type: [{ required: true, message: '请选择订单类型', trigger: 'change' }],
|
||
amount: [{ required: true, message: '请输入订单金额', trigger: 'blur' }]
|
||
}
|
||
|
||
const handleCreateOrder = (row: any) => {
|
||
orderForm.patient_id = row.patient_id || row.id
|
||
orderForm.patient_name = row.patient_name
|
||
orderForm.phone = row.phone || ''
|
||
orderForm.order_type = ''
|
||
orderForm.amount = 0
|
||
orderForm.remark = ''
|
||
orderFormRef.value?.clearValidate()
|
||
createOrderVisible.value = true
|
||
}
|
||
|
||
const resetOrderForm = () => {
|
||
orderForm.patient_id = ''
|
||
orderForm.patient_name = ''
|
||
orderForm.phone = ''
|
||
orderForm.order_type = ''
|
||
orderForm.amount = 0
|
||
orderForm.remark = ''
|
||
orderFormRef.value?.clearValidate()
|
||
}
|
||
|
||
const submitOrder = async () => {
|
||
try {
|
||
await orderFormRef.value?.validate()
|
||
orderLoading.value = true
|
||
const res = await orderCreate({
|
||
patient_id: orderForm.patient_id,
|
||
order_type: orderForm.order_type,
|
||
amount: orderForm.amount,
|
||
remark: orderForm.remark
|
||
})
|
||
createOrderVisible.value = false
|
||
getLists()
|
||
|
||
const orderNo = res?.order_no
|
||
if (orderNo) {
|
||
qrcodeDialogVisible.value = true
|
||
qrcodeLoading.value = true
|
||
qrcodeUrl.value = ''
|
||
currentQRCodePatient.value = { patient_name: orderForm.patient_name }
|
||
try {
|
||
const qrRes = await generateOrderQrcode({ order_no: orderNo })
|
||
if (qrRes?.qrcode_url) {
|
||
qrcodeUrl.value = qrRes.qrcode_url
|
||
} else {
|
||
feedback.msgError('二维码生成失败')
|
||
}
|
||
} catch (e: any) {
|
||
feedback.msgError(e?.msg || '生成二维码失败')
|
||
} finally {
|
||
qrcodeLoading.value = false
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.error('创建订单失败:', error)
|
||
} finally {
|
||
orderLoading.value = false
|
||
}
|
||
}
|
||
|
||
// 小程序二维码相关
|
||
const qrcodeDialogVisible = ref(false)
|
||
const qrcodeLoading = ref(false)
|
||
const qrcodeUrl = ref('')
|
||
const currentQRCodePatient = ref<any>(null)
|
||
|
||
// 批量指派相关
|
||
const selectedIds = ref<number[]>([])
|
||
const assignDialogVisible = ref(false)
|
||
const assignLoading = ref(false)
|
||
const assignMode = ref<'batch' | 'single'>('batch')
|
||
const currentRow = ref<any>(null)
|
||
const assignForm = ref({
|
||
assistant_id: null as number | null
|
||
})
|
||
|
||
const handleSelectionChange = (selection: any[]) => {
|
||
selectedIds.value = selection.map(item => item.id)
|
||
}
|
||
|
||
// 单独指派
|
||
const handleSingleAssign = (row: any) => {
|
||
assignMode.value = 'single'
|
||
currentRow.value = row
|
||
// 确保类型一致,转换为数字
|
||
assignForm.value.assistant_id = row.assistant_id ? Number(row.assistant_id) : null
|
||
assignDialogVisible.value = true
|
||
|
||
// 调试
|
||
console.log('当前行数据:', row)
|
||
console.log('assistant_id:', row.assistant_id, '类型:', typeof row.assistant_id)
|
||
console.log('转换后:', assignForm.value.assistant_id, '类型:', typeof assignForm.value.assistant_id)
|
||
console.log('医助选项:', assistantOptions.value)
|
||
}
|
||
|
||
// 批量指派
|
||
const handleBatchAssign = () => {
|
||
if (selectedIds.value.length === 0) {
|
||
feedback.msgWarning('请先选择要指派的诊单')
|
||
return
|
||
}
|
||
assignMode.value = 'batch'
|
||
currentRow.value = null
|
||
assignForm.value.assistant_id = null
|
||
assignDialogVisible.value = true
|
||
}
|
||
|
||
const handleConfirmAssign = async () => {
|
||
if (!assignForm.value.assistant_id) {
|
||
feedback.msgWarning('请选择医助')
|
||
return
|
||
}
|
||
|
||
assignLoading.value = true
|
||
try {
|
||
if (assignMode.value === 'single') {
|
||
// 单独指派
|
||
await tcmDiagnosisAssign({
|
||
id: currentRow.value.id,
|
||
assistant_id: assignForm.value.assistant_id
|
||
})
|
||
} else {
|
||
// 批量指派
|
||
const promises = selectedIds.value.map(id =>
|
||
tcmDiagnosisAssign({
|
||
id,
|
||
assistant_id: assignForm.value.assistant_id
|
||
})
|
||
)
|
||
await Promise.all(promises)
|
||
selectedIds.value = []
|
||
}
|
||
|
||
assignDialogVisible.value = false
|
||
getLists()
|
||
} catch (error) {
|
||
console.error('指派失败:', error)
|
||
} finally {
|
||
assignLoading.value = false
|
||
}
|
||
}
|
||
|
||
const handleAdd = () => {
|
||
editRef.value.open('add')
|
||
}
|
||
|
||
const handleEdit = (id: number) => {
|
||
editRef.value.open('edit', id)
|
||
}
|
||
|
||
const handleDetail = (id: number) => {
|
||
detailRef.value.open(id)
|
||
}
|
||
|
||
const handleDelete = async (id: number) => {
|
||
await feedback.confirm('确定要删除该诊单吗?')
|
||
await tcmDiagnosisDelete({ id })
|
||
getLists()
|
||
}
|
||
|
||
// 患者挂号
|
||
const handleAppointment = (row: any) => {
|
||
if (!row.patient_id) {
|
||
feedback.msgWarning('患者信息不完整')
|
||
return
|
||
}
|
||
|
||
appointmentRef.value?.open(row)
|
||
}
|
||
|
||
// 生成小程序二维码
|
||
const handleMiniProgramQRCode = async (row: any) => {
|
||
if (!row.patient_id) {
|
||
feedback.msgWarning('患者信息不完整')
|
||
return
|
||
}
|
||
|
||
currentQRCodePatient.value = row
|
||
qrcodeDialogVisible.value = true
|
||
qrcodeLoading.value = true
|
||
qrcodeUrl.value = ''
|
||
|
||
try {
|
||
// 获取小程序配置
|
||
const config = await getWeappConfig()
|
||
|
||
if (!config?.app_id) {
|
||
feedback.msgError('小程序未配置,请先配置小程序信息')
|
||
qrcodeDialogVisible.value = false
|
||
return
|
||
}
|
||
|
||
// 获取当前登录用户信息
|
||
const currentUser = userStore.userInfo
|
||
|
||
// 调用生成二维码接口
|
||
const result = await generateMiniProgramQrcode({
|
||
diagnosis_id: row.id,
|
||
patient_id: row.patient_id,
|
||
share_user_id: currentUser?.id || ''
|
||
})
|
||
|
||
if (result?.qrcode_url) {
|
||
qrcodeUrl.value = result.qrcode_url
|
||
} else {
|
||
feedback.msgError('二维码生成失败')
|
||
}
|
||
} catch (error: any) {
|
||
console.error('生成小程序二维码失败:', error)
|
||
feedback.msgError(error?.msg || '生成二维码失败,请重试')
|
||
} finally {
|
||
qrcodeLoading.value = false
|
||
}
|
||
}
|
||
|
||
// 重新生成二维码
|
||
const handleRegenerateQRCode = () => {
|
||
if (currentQRCodePatient.value) {
|
||
handleMiniProgramQRCode(currentQRCodePatient.value)
|
||
}
|
||
}
|
||
|
||
// ========== 企业微信聊天记录 ==========
|
||
const wechatDrawerVisible = ref(false)
|
||
const wechatCurrentPatient = ref<any>(null)
|
||
const wechatRecords = ref<any[]>([])
|
||
const wechatRecordTotal = ref(0)
|
||
const wechatRecordsLoading = ref(false)
|
||
const wechatContactInfo = ref<any>(null)
|
||
const wechatNewNote = ref('')
|
||
const wechatAddLoading = ref(false)
|
||
const wechatPage = ref(1)
|
||
|
||
const formatTimestamp = (ts: number) => {
|
||
if (!ts) return '-'
|
||
const t = String(ts).length === 10 ? ts * 1000 : ts
|
||
return dayjs(t).format('YYYY-MM-DD HH:mm')
|
||
}
|
||
|
||
const handleWechatRecords = async (row: any) => {
|
||
wechatCurrentPatient.value = row
|
||
wechatDrawerVisible.value = true
|
||
wechatRecords.value = []
|
||
wechatRecordTotal.value = 0
|
||
wechatContactInfo.value = null
|
||
wechatNewNote.value = ''
|
||
wechatPage.value = 1
|
||
|
||
// 并行加载聊天记录和外部联系人信息
|
||
wechatRecordsLoading.value = true
|
||
try {
|
||
const [recordsRes, contactRes] = await Promise.all([
|
||
getWechatChatRecords({ diagnosis_id: row.id, patient_id: row.patient_id, page_no: 1, page_size: 20 }),
|
||
getWechatExternalContact({ patient_id: row.patient_id || row.id }).catch(() => null)
|
||
])
|
||
|
||
wechatRecords.value = recordsRes?.lists || []
|
||
wechatRecordTotal.value = recordsRes?.count || 0
|
||
wechatContactInfo.value = contactRes
|
||
} catch (e) {
|
||
console.error('加载企业微信记录失败:', e)
|
||
} finally {
|
||
wechatRecordsLoading.value = false
|
||
}
|
||
}
|
||
|
||
const loadMoreRecords = async () => {
|
||
if (!wechatCurrentPatient.value) return
|
||
wechatPage.value++
|
||
try {
|
||
const res = await getWechatChatRecords({
|
||
diagnosis_id: wechatCurrentPatient.value.id,
|
||
patient_id: wechatCurrentPatient.value.patient_id,
|
||
page_no: wechatPage.value,
|
||
page_size: 20
|
||
})
|
||
wechatRecords.value.push(...(res?.lists || []))
|
||
} catch (e) {
|
||
console.error('加载更多记录失败:', e)
|
||
}
|
||
}
|
||
|
||
const handleAddRecord = async () => {
|
||
if (!wechatNewNote.value.trim()) {
|
||
feedback.msgWarning('请输入内容')
|
||
return
|
||
}
|
||
wechatAddLoading.value = true
|
||
try {
|
||
await addWechatChatRecord({
|
||
diagnosis_id: wechatCurrentPatient.value.id,
|
||
patient_id: wechatCurrentPatient.value.patient_id,
|
||
content: wechatNewNote.value.trim(),
|
||
msg_type: 'note',
|
||
staff_name: userStore.userInfo?.name || '',
|
||
external_name: wechatCurrentPatient.value.patient_name || '',
|
||
})
|
||
wechatNewNote.value = ''
|
||
// 重新加载记录
|
||
handleWechatRecords(wechatCurrentPatient.value)
|
||
} catch (e: any) {
|
||
feedback.msgError(e?.msg || '添加失败')
|
||
} finally {
|
||
wechatAddLoading.value = false
|
||
}
|
||
}
|
||
|
||
const handleDeleteRecord = async (id: number) => {
|
||
await feedback.confirm('确定删除该记录吗?')
|
||
try {
|
||
await deleteWechatChatRecord({ id })
|
||
wechatRecords.value = wechatRecords.value.filter(r => r.id !== id)
|
||
wechatRecordTotal.value--
|
||
} catch (e: any) {
|
||
feedback.msgError(e?.msg || '删除失败')
|
||
}
|
||
}
|
||
|
||
onMounted(async () => {
|
||
await getDictOptions()
|
||
getLists()
|
||
})
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.record-list {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 12px;
|
||
}
|
||
|
||
.record-item {
|
||
background: #f9fafb;
|
||
border-radius: 8px;
|
||
padding: 12px;
|
||
border: 1px solid #f0f0f0;
|
||
}
|
||
|
||
.record-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 8px;
|
||
}
|
||
|
||
.record-content {
|
||
font-size: 14px;
|
||
line-height: 1.6;
|
||
color: #333;
|
||
white-space: pre-wrap;
|
||
word-break: break-all;
|
||
}
|
||
</style>
|