From c65b90aaa3477a90ebc325024927d80227c0c841 Mon Sep 17 00:00:00 2001
From: WXL (wul) <wl_5969728@163.com>
Date: 星期四, 09 四月 2026 14:09:25 +0800
Subject: [PATCH] 测试完成
---
src/views/Satisfaction/configurationmyd/batch.vue | 1081 +++++++++++++++++++++++++++++++++++++-------------------
1 files changed, 717 insertions(+), 364 deletions(-)
diff --git a/src/views/Satisfaction/configurationmyd/batch.vue b/src/views/Satisfaction/configurationmyd/batch.vue
index 41c2d0d..bd73abe 100644
--- a/src/views/Satisfaction/configurationmyd/batch.vue
+++ b/src/views/Satisfaction/configurationmyd/batch.vue
@@ -11,14 +11,11 @@
icon="el-icon-check"
@click="handleBatchSubmit"
:loading="batchProcessing"
+ :disabled="selectedExceptionIds.length === 0"
>
- 鎵归噺鎻愪氦澶勭悊
+ 鎵归噺鎻愪氦澶勭悊 ({{ selectedExceptionIds.length }})
</el-button>
- <el-button
- type="warning"
- icon="el-icon-back"
- @click="handleGoBack"
- >
+ <el-button type="warning" icon="el-icon-back" @click="handleGoBack">
杩斿洖寮傚父鍒楄〃
</el-button>
</div>
@@ -37,29 +34,40 @@
>
<el-form-item label="璐熻矗绉戝">
<el-select
- v-model="filterParams.deptId"
+ v-model="filterParams.todeptcode"
placeholder="璇烽�夋嫨绉戝"
clearable
+ filterable
style="width: 200px"
>
<el-option
v-for="dept in deptList"
- :key="dept.id"
- :label="dept.name"
- :value="dept.id"
+ :key="dept.deptCode"
+ :label="dept.label"
+ :value="dept.deptCode"
/>
</el-select>
</el-form-item>
<el-form-item label="澶勭悊鐘舵��">
<el-select
- v-model="filterParams.status"
+ v-model="filterParams.handleFlag"
placeholder="璇烽�夋嫨鐘舵��"
clearable
style="width: 200px"
>
- <el-option label="寰呭鐞�" :value="0" />
- <el-option label="澶勭悊涓�" :value="1" />
- <el-option label="宸插鐞�" :value="2" />
+ <el-option label="鏈鐞�" :value="'0'" />
+ <el-option label="宸插鐞�" :value="'1'" />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="婊℃剰搴︾被鍨�">
+ <el-select
+ v-model="filterParams.templateType"
+ placeholder="璇烽�夋嫨妯℃澘绫诲瀷"
+ clearable
+ style="width: 200px"
+ >
+ <el-option label="璇煶妯℃澘" :value="1" />
+ <el-option label="闂嵎妯℃澘" :value="2" />
</el-select>
</el-form-item>
<el-form-item>
@@ -70,10 +78,7 @@
>
绛涢��
</el-button>
- <el-button
- icon="el-icon-refresh"
- @click="handleResetFilter"
- >
+ <el-button icon="el-icon-refresh" @click="handleResetFilter">
閲嶇疆
</el-button>
</el-form-item>
@@ -86,13 +91,10 @@
:border="true"
style="width: 100%"
@selection-change="handleSelectionChange"
+ row-key="id"
class="exception-table"
>
- <el-table-column
- type="selection"
- width="55"
- align="center"
- />
+ <el-table-column type="selection" width="55" align="center" />
<el-table-column
label="搴忓彿"
@@ -103,73 +105,81 @@
<el-table-column
label="璐熻矗绉戝"
- prop="responsibilityDept"
- width="120"
+ prop="todeptname"
+ width="200"
align="center"
>
<template slot-scope="{ row }">
- <el-tag type="primary">{{ row.responsibilityDept }}</el-tag>
+ <el-tag type="primary" v-if="row.todeptname">{{
+ row.todeptname
+ }}</el-tag>
+ <span v-else class="no-data">鏈垎閰�</span>
</template>
</el-table-column>
- <el-table-column
- label="涓嶆弧鎰忚鎯�"
- prop="unsatisfactoryDetail"
- min-width="200"
- align="center"
- >
+ <el-table-column label="涓嶆弧鎰忚鎯�" min-width="250" align="center">
<template slot-scope="{ row }">
<div class="detail-content">
- {{ row.unsatisfactoryDetail }}
+ <div class="question-text">
+ <strong>闂锛�</strong>{{ row.questiontext }}
+ </div>
+ <div class="answer-text">
+ <strong>鍥炵瓟锛�</strong>{{ row.asrtext || "鏃犲洖绛�" }}
+ </div>
+ <div class="matched-text" v-if="row.matchedtext">
+ <strong>瑙f瀽鍊硷細</strong>{{ row.matchedtext }}
+ </div>
</div>
</template>
</el-table-column>
- <el-table-column
- label="鎮h�呬俊鎭�"
- width="300"
- align="center"
- >
+ <el-table-column label="鎮h�呬俊鎭�" width="300" align="center">
<template slot-scope="{ row }">
<div class="patient-info">
- <div class="patient-item">
- <span class="label">濮撳悕锛�</span>
- <span class="value">{{ row.patientName }}</span>
+ <div class="patient-row">
+ <div class="patient-item">
+ <span class="label">濮撳悕锛�</span>
+ <span class="value">{{ row.patdescJson.sendname }}</span>
+ </div>
+ <div class="patient-item">
+ <span class="label">鎬у埆锛�</span>
+ <span class="value">{{
+ row.patdescJson.sex
+ }}</span>
+ </div>
+ <div class="patient-item">
+ <span class="label">骞撮緞锛�</span>
+ <span class="value">{{ row.patdescJson.age }}宀�</span>
+ </div>
</div>
- <div class="patient-item">
- <span class="label">鎬у埆锛�</span>
- <span class="value">{{ row.gender === 1 ? '鐢�' : '濂�' }}</span>
- </div>
- <div class="patient-item">
- <span class="label">骞撮緞锛�</span>
- <span class="value">{{ row.age }}宀�</span>
- </div>
- <div class="patient-item">
- <span class="label">鐢佃瘽锛�</span>
- <span class="value">{{ row.phone }}</span>
+ <div class="patient-row">
+ <div class="patient-item full-width">
+ <span class="label">鐢佃瘽锛�</span>
+ <span class="value">{{ row.patdescJson.phone }}</span>
+ </div>
</div>
</div>
</template>
</el-table-column>
- <el-table-column
- label="鍑洪櫌淇℃伅"
- width="250"
- align="center"
- >
+ <el-table-column label="濉啓淇℃伅" width="180" align="center">
<template slot-scope="{ row }">
- <div class="discharge-info">
+ <div class="fill-info">
<div class="info-item">
- <span class="label">绉戝锛�</span>
- <span class="value">{{ row.dischargeDept }}</span>
+ <span class="label">濉姤鏃堕棿锛�</span>
+ <span class="value time">{{
+ formatDateTime(row.createTime)
+ }}</span>
</div>
- <div class="info-item">
- <span class="label">鐥呭尯锛�</span>
- <span class="value">{{ row.dischargeWard }}</span>
- </div>
- <div class="info-item">
- <span class="label">濉啓鏃堕棿锛�</span>
- <span class="value time">{{ row.fillTime }}</span>
+ <div v-if="row.recordurl" class="info-item">
+ <el-button
+ type="text"
+ size="small"
+ @click="handlePlayAudio(row.recordurl)"
+ icon="el-icon-headset"
+ >
+ 鎾斁褰曢煶
+ </el-button>
</div>
</div>
</template>
@@ -177,23 +187,42 @@
<el-table-column
label="澶勭悊鐘舵��"
- prop="processStatus"
+ prop="handleFlag"
width="100"
align="center"
>
<template slot-scope="{ row }">
- <el-tag
- :type="getStatusTagType(row.processStatus)"
- effect="dark"
- >
- {{ getStatusText(row.processStatus) }}
+ <el-tag :type="getStatusTagType(row.handleFlag)" effect="dark">
+ {{ getStatusText(row.handleFlag) }}
</el-tag>
+ </template>
+ </el-table-column>
+
+ <el-table-column label="鏈�鏂板鐞嗕俊鎭�" width="180" align="center">
+ <template slot-scope="{ row }">
+ <div v-if="row.handleTime" class="handle-info">
+ <div class="info-item">
+ <span class="label">澶勭悊浜猴細</span>
+ <span class="value">{{ row.handleBy || "绯荤粺" }}</span>
+ </div>
+ <div class="info-item">
+ <span class="label">澶勭悊鏃堕棿锛�</span>
+ <span class="value time">{{
+ formatDateTime(row.handleTime)
+ }}</span>
+ </div>
+ <div class="info-item">
+ <span class="label">澶勭悊璇存槑锛�</span>
+ <span class="value">{{ row.handledesc }}</span>
+ </div>
+ </div>
+ <span v-else class="no-data">鏈鐞�</span>
</template>
</el-table-column>
<el-table-column
label="鎿嶄綔"
- width="180"
+ width="210"
align="center"
fixed="right"
>
@@ -211,7 +240,7 @@
size="small"
icon="el-icon-edit"
@click="handleProcess(row)"
- :disabled="row.processStatus === 2"
+ :disabled="row.handleFlag === '1'"
>
澶勭悊
</el-button>
@@ -249,70 +278,81 @@
label-width="100px"
size="medium"
>
- <el-form-item label="澶勭悊鐘舵��" prop="status">
+ <el-form-item label="澶勭悊鐘舵��" prop="handleFlag">
<el-select
- v-model="processForm.status"
+ v-model="processForm.handleFlag"
placeholder="璇烽�夋嫨澶勭悊鐘舵��"
style="width: 100%"
>
- <el-option label="澶勭悊涓�" :value="1" />
- <el-option label="宸插鐞�" :value="2" />
- <el-option label="宸查┏鍥�" :value="3" />
+ <el-option label="宸插鐞�" :value="'1'" />
+ <el-option label="鍙栨秷澶勭悊" :value="'0'" />
</el-select>
</el-form-item>
- <el-form-item label="鎶ュ绉戝" prop="reportDepts">
+ <el-form-item label="鎶ュ绉戝" prop="ccdepts">
<el-select
- v-model="processForm.reportDepts"
+ v-model="processForm.ccdepts"
placeholder="璇烽�夋嫨鎶ュ绉戝"
multiple
filterable
collapse-tags
style="width: 100%"
+ :disabled="processForm.handleFlag !== '1'"
>
<el-option
v-for="dept in deptList"
- :key="dept.id"
- :label="dept.name"
- :value="dept.id"
+ :key="dept.deptCode"
+ :label="dept.label"
+ :value="dept.deptCode"
/>
</el-select>
</el-form-item>
- <el-form-item label="澶勭悊澶囨敞" prop="remark">
+ <el-form-item label="澶勭悊缁撴灉" prop="handleresult">
+ <el-select
+ v-model="processForm.handleresult"
+ placeholder="璇烽�夋嫨澶勭悊缁撴灉"
+ style="width: 100%"
+ :disabled="processForm.handleFlag !== '1'"
+ >
+ <el-option label="宸茶В鍐�" value="resolved" />
+ <el-option label="宸茶В閲�" value="explained" />
+ <el-option label="宸茶浆浜�" value="transferred" />
+ <el-option label="闇�鏀硅繘" value="improvement" />
+ <el-option label="宸查┏鍥�" value="rejected" />
+ </el-select>
+ </el-form-item>
+
+ <el-form-item label="澶勭悊璇存槑" prop="handledesc">
<el-input
- v-model="processForm.remark"
+ v-model="processForm.handledesc"
type="textarea"
:rows="4"
- placeholder="璇疯緭鍏ュ鐞嗗娉紙鏈�澶�500瀛楋級"
+ placeholder="璇疯緭鍏ュ鐞嗚鏄庯紙鏈�澶�500瀛楋級"
maxlength="500"
show-word-limit
+ :disabled="processForm.handleFlag !== '1'"
/>
</el-form-item>
- <el-form-item label="闄勪欢涓婁紶">
- <el-upload
- class="upload-demo"
- action="#"
- :on-preview="handlePreview"
- :on-remove="handleRemove"
- :before-remove="beforeRemove"
- :limit="3"
- :on-exceed="handleExceed"
- :file-list="fileList"
- >
- <el-button size="small" type="primary">鐐瑰嚮涓婁紶</el-button>
- <div slot="tip" class="el-upload__tip">鏀寔涓婁紶鍥剧墖銆佹枃妗g瓑闄勪欢锛屽崟涓枃浠朵笉瓒呰繃10MB</div>
- </el-upload>
+ <el-form-item
+ label="鏈�缁堟剰瑙�"
+ prop="finaloption"
+ v-if="hasQualityPermission"
+ >
+ <el-input
+ v-model="processForm.finaloption"
+ type="textarea"
+ :rows="3"
+ placeholder="璇疯緭鍏ユ渶缁堝鐞嗘剰瑙侊紙鏈�澶�300瀛楋級"
+ maxlength="300"
+ show-word-limit
+ />
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="processDialogVisible = false">鍙栨秷</el-button>
- <el-button
- type="primary"
- @click="submitProcess"
- :loading="processing"
- >
+ <el-button type="primary" @click="submitProcess" :loading="processing">
鎻愪氦澶勭悊
</el-button>
</span>
@@ -332,44 +372,60 @@
label-width="100px"
size="medium"
>
- <el-form-item label="澶勭悊鐘舵��" prop="status">
+ <el-form-item label="澶勭悊鐘舵��" prop="handleFlag">
<el-select
- v-model="batchProcessForm.status"
+ v-model="batchProcessForm.handleFlag"
placeholder="璇烽�夋嫨澶勭悊鐘舵��"
style="width: 100%"
>
- <el-option label="澶勭悊涓�" :value="1" />
- <el-option label="宸插鐞�" :value="2" />
- <el-option label="宸查┏鍥�" :value="3" />
+ <el-option label="宸插鐞�" :value="'1'" />
+ <el-option label="鍙栨秷澶勭悊" :value="'0'" />
</el-select>
</el-form-item>
- <el-form-item label="鎶ュ绉戝" prop="reportDepts">
+ <el-form-item label="鎶ュ绉戝" prop="ccdepts">
<el-select
- v-model="batchProcessForm.reportDepts"
+ v-model="batchProcessForm.ccdepts"
placeholder="璇烽�夋嫨鎶ュ绉戝"
multiple
filterable
collapse-tags
style="width: 100%"
+ :disabled="batchProcessForm.handleFlag !== '1'"
>
<el-option
v-for="dept in deptList"
- :key="dept.id"
- :label="dept.name"
- :value="dept.id"
+ :key="dept.deptCode"
+ :label="dept.label"
+ :value="dept.deptCode"
/>
</el-select>
</el-form-item>
- <el-form-item label="澶勭悊澶囨敞" prop="remark">
+ <el-form-item label="澶勭悊缁撴灉" prop="handleresult">
+ <el-select
+ v-model="batchProcessForm.handleresult"
+ placeholder="璇烽�夋嫨澶勭悊缁撴灉"
+ style="width: 100%"
+ :disabled="batchProcessForm.handleFlag !== '1'"
+ >
+ <el-option label="宸茶В鍐�" value="resolved" />
+ <el-option label="宸茶В閲�" value="explained" />
+ <el-option label="宸茶浆浜�" value="transferred" />
+ <el-option label="闇�鏀硅繘" value="improvement" />
+ <el-option label="宸查┏鍥�" value="rejected" />
+ </el-select>
+ </el-form-item>
+
+ <el-form-item label="澶勭悊璇存槑" prop="handledesc">
<el-input
- v-model="batchProcessForm.remark"
+ v-model="batchProcessForm.handledesc"
type="textarea"
:rows="4"
- placeholder="璇疯緭鍏ュ鐞嗗娉紙鏈�澶�500瀛楋級"
+ placeholder="璇疯緭鍏ュ鐞嗚鏄庯紙鏈�澶�500瀛楋級"
maxlength="500"
show-word-limit
+ :disabled="batchProcessForm.handleFlag !== '1'"
/>
</el-form-item>
</el-form>
@@ -380,18 +436,73 @@
@click="submitBatchProcess"
:loading="batchProcessing"
>
- 鎵归噺鎻愪氦
+ 鎵归噺鎻愪氦 ({{ selectedExceptionIds.length }})
</el-button>
</span>
</el-dialog>
+ <!-- 杩涘害瀵硅瘽妗� -->
+ <el-dialog
+ title="鎵归噺澶勭悊杩涘害"
+ :visible.sync="batchProgress.visible"
+ width="400px"
+ :close-on-click-modal="false"
+ :show-close="false"
+ :close-on-press-escape="false"
+ >
+ <div class="progress-content">
+ <el-progress
+ :percentage="batchProgress.percentage"
+ :status="batchProgress.percentage === 100 ? 'success' : ''"
+ />
+ <div class="progress-info">
+ 宸插鐞� {{ batchProgress.processed }}/{{ batchProgress.total }} 鏉¤褰�
+ </div>
+ </div>
+ </el-dialog>
+ <!-- 寮傚父璇︽儏寮规 -->
+ <Details-anomaly
+ :visible="detailDialogVisible"
+ :record-id="selectedRecordId"
+ :title="detailDialogTitle"
+ :record-data="selectedRecordData"
+ @update:visible="handleDetailDialogClose"
+ @processed="handleProcessed"
+ @close="handleDetailDialogClose"
+ />
+
+ <!-- 褰曢煶鎾斁鍣� -->
+ <audio
+ v-if="audioUrl"
+ :src="audioUrl"
+ ref="audioPlayer"
+ controls
+ style="display: none"
+ />
</div>
</template>
<script>
+import DetailsAnomaly from "./components/DetailsAnomaly.vue";
+import { tracelist, traceedit } from "@/api/AiCentre/index";
+import dayjs from "dayjs";
+import { deptTreeSelect } from "@/api/system/user";
+
export default {
- name: 'BatchProcess',
+ name: "BatchProcess",
+ components: {
+ DetailsAnomaly,
+ },
data() {
return {
+ // 璇︽儏寮规鐩稿叧
+ detailDialogVisible: false,
+ selectedRecordId: null,
+ selectedRecordData: null,
+ detailDialogTitle: "寮傚父鍙嶉璇︽儏",
+
+ // 闊抽鎾斁
+ audioUrl: "",
+
// 褰撳墠澶勭悊鐨勫紓甯窱D
currentExceptionId: null,
@@ -400,10 +511,12 @@
// 杩囨护鍙傛暟
filterParams: {
- deptId: '',
- status: '',
+ todeptcode: "",
+ handleFlag: "",
+ templateType: null,
+ scriptids: null,
pageNum: 1,
- pageSize: 10
+ pageSize: 10,
},
// 鍔犺浇鐘舵��
@@ -411,19 +524,11 @@
processing: false,
batchProcessing: false,
+ // 鏉冮檺鎺у埗
+ hasQualityPermission: false, // 鏄惁鍏锋湁璐ㄧ鏉冮檺
+
// 绉戝鍒楄〃
- deptList: [
- { id: 1, name: '蹇冭绠″唴绉�' },
- { id: 2, name: '绁炵粡鍐呯' },
- { id: 3, name: '鏅绉�' },
- { id: 4, name: '楠ㄧ' },
- { id: 5, name: '濡囦骇绉�' },
- { id: 6, name: '鍎跨' },
- { id: 7, name: '鎬ヨ瘖绉�' },
- { id: 8, name: '鍛煎惛鍐呯' },
- { id: 9, name: '娑堝寲鍐呯' },
- { id: 10, name: '鍐呭垎娉岀' }
- ],
+ deptList: [],
// 寮傚父鍒楄〃鏁版嵁
exceptionList: [],
@@ -432,183 +537,252 @@
// 澶勭悊瀵硅瘽妗�
processDialogVisible: false,
processForm: {
- status: '',
- reportDepts: [],
- remark: ''
+ handleFlag: "",
+ ccdepts: [],
+ handleresult: "",
+ handledesc: "",
+ finaloption: "",
+ },
+ batchProgress: {
+ visible: false,
+ percentage: 0,
+ processed: 0,
+ total: 0,
},
processRules: {
- status: [
- { required: true, message: '璇烽�夋嫨澶勭悊鐘舵��', trigger: 'change' }
+ handleFlag: [
+ { required: true, message: "璇烽�夋嫨澶勭悊鐘舵��", trigger: "change" },
],
- remark: [
- { required: true, message: '璇疯緭鍏ュ鐞嗗娉�', trigger: 'blur' },
- { min: 5, max: 500, message: '澶囨敞闀垮害鍦� 5 鍒� 500 涓瓧绗�', trigger: 'blur' }
- ]
+ handleresult: [
+ {
+ required: true,
+ message: "璇烽�夋嫨澶勭悊缁撴灉",
+ trigger: "change",
+ validator: (rule, value, callback) => {
+ if (this.processForm.handleFlag === "1" && !value) {
+ callback(new Error("璇烽�夋嫨澶勭悊缁撴灉"));
+ } else {
+ callback();
+ }
+ },
+ },
+ ],
+ handledesc: [
+ {
+ required: true,
+ message: "璇疯緭鍏ュ鐞嗚鏄�",
+ trigger: "blur",
+ validator: (rule, value, callback) => {
+ if (
+ this.processForm.handleFlag === "1" &&
+ (!value || value.trim().length < 3)
+ ) {
+ callback(new Error("澶勭悊璇存槑鑷冲皯3涓瓧绗�"));
+ } else {
+ callback();
+ }
+ },
+ },
+ ],
},
- fileList: [],
// 鎵归噺澶勭悊瀵硅瘽妗�
batchDialogVisible: false,
batchProcessForm: {
- status: '',
- reportDepts: [],
- remark: ''
- }
+ handleFlag: "",
+ ccdepts: [],
+ handleresult: "",
+ handledesc: "",
+ },
};
+ },
+
+ created() {
+ // 浠庤矾鐢卞弬鏁拌幏鍙栭棶棰業D
+ this.filterParams.scriptids = this.$route.query.questionId || this.$route.query.questionIds||null;
+ // if (this.$route.query.questionId) {
+ // } else if (this.$route.query.questionIds) {
+ // console.log(
+ // this.$route.query.questionIds,
+ // "this.$route.query.questionIds"
+ // );
+
+ this.filterParams.templateType = Number(this.$route.query.type)||null;
+
+ // this.filterParams.scriptid = null;
+ // }
+ this.hasQualityPermission = this.checkQualityPermission();
},
mounted() {
this.loadExceptionList();
+ this.getDeptOptions();
},
methods: {
- // 鍔犺浇寮傚父鍒楄〃
- async loadExceptionList() {
- this.loading = true;
+ // 鏍煎紡鍖栨棩鏈熸椂闂�
+ formatDateTime(dateTime) {
+ if (!dateTime) return "";
try {
- // Mock 鏁版嵁
- await new Promise(resolve => {
- setTimeout(() => {
- this.exceptionList = [
- {
- id: 1,
- responsibilityDept: '蹇冭绠″唴绉�',
- unsatisfactoryDetail: '鍖荤敓鏌ユ埧鏃堕棿澶煭锛屾矡閫氫笉澶熷厖鍒嗭紝瀵圭梾鎯呰В閲婁笉澶熻缁�',
- patientName: '寮犲厛鐢�',
- gender: 1,
- age: 45,
- phone: '138****1234',
- dischargeDept: '蹇冭绠″唴绉�',
- dischargeWard: '鍐呯涓�鐥呭尯',
- fillTime: '2024-01-15 10:30:25',
- processStatus: 0,
- questionnaireId: 1001
- },
- {
- id: 2,
- responsibilityDept: '绁炵粡鍐呯',
- unsatisfactoryDetail: '鎶ゅ+鎵撻拡鎶�鏈笉浣筹紝鎵庝簡涓夋鎵嶆垚鍔燂紝涓旀�佸害涓嶅鑰愬績',
- patientName: '鏉庡コ澹�',
- gender: 0,
- age: 38,
- phone: '139****5678',
- dischargeDept: '绁炵粡鍐呯',
- dischargeWard: '鍐呯浜岀梾鍖�',
- fillTime: '2024-01-14 16:20:10',
- processStatus: 0,
- questionnaireId: 1002
- },
- {
- id: 3,
- responsibilityDept: '鏅绉�',
- unsatisfactoryDetail: '鏈悗鎹㈣嵂涓嶅強鏃讹紝浼ゅ彛鐤肩棝鏃舵病鏈夊強鏃跺鐞�',
- patientName: '鐜嬪厛鐢�',
- gender: 1,
- age: 52,
- phone: '137****9012',
- dischargeDept: '鏅绉�',
- dischargeWard: '澶栫涓�鐥呭尯',
- fillTime: '2024-01-13 09:15:45',
- processStatus: 1,
- questionnaireId: 1003
- },
- {
- id: 4,
- responsibilityDept: '楠ㄧ',
- unsatisfactoryDetail: '搴峰鎸囧涓嶅涓撲笟锛屽鎭㈠杩囩▼鎻忚堪涓嶆竻妤�',
- patientName: '鍒樺コ澹�',
- gender: 0,
- age: 65,
- phone: '136****3456',
- dischargeDept: '楠ㄧ',
- dischargeWard: '澶栫浜岀梾鍖�',
- fillTime: '2024-01-12 14:40:30',
- processStatus: 0,
- questionnaireId: 1004
- },
- {
- id: 5,
- responsibilityDept: '濡囦骇绉�',
- unsatisfactoryDetail: '浜у墠妫�鏌ユ帓闃熸椂闂磋繃闀匡紝绛夊緟鏈熼棿娌℃湁浼戞伅搴т綅',
- patientName: '闄堝コ澹�',
- gender: 0,
- age: 28,
- phone: '135****7890',
- dischargeDept: '濡囦骇绉�',
- dischargeWard: '濡囦骇绉戠梾鍖�',
- fillTime: '2024-01-11 11:25:15',
- processStatus: 2,
- questionnaireId: 1005
- },
- {
- id: 6,
- responsibilityDept: '鍎跨',
- unsatisfactoryDetail: '鍎跨鐢ㄨ嵂鍓傞噺浜や唬涓嶆竻鏅帮紝鐢ㄨ嵂娉ㄦ剰浜嬮」娌℃湁璇存槑',
- patientName: '璧靛疂瀹�',
- gender: 1,
- age: 5,
- phone: '134****1234',
- dischargeDept: '鍎跨',
- dischargeWard: '鍎跨鐥呭尯',
- fillTime: '2024-01-10 15:50:20',
- processStatus: 0,
- questionnaireId: 1006
- },
- {
- id: 7,
- responsibilityDept: '鎬ヨ瘖绉�',
- unsatisfactoryDetail: '鎬ヨ瘖绛夊緟鏃堕棿杩囬暱锛岀梾鎯呮病鏈夊緱鍒板強鏃惰瘎浼�',
- patientName: '瀛欏厛鐢�',
- gender: 1,
- age: 40,
- phone: '133****5678',
- dischargeDept: '鎬ヨ瘖绉�',
- dischargeWard: '鎬ヨ瘖鐥呭尯',
- fillTime: '2024-01-09 10:15:40',
- processStatus: 0,
- questionnaireId: 1007
- },
- {
- id: 8,
- responsibilityDept: '鍛煎惛鍐呯',
- unsatisfactoryDetail: '鍖荤敓寮�鑽緝澶氾紝璐圭敤杈冮珮锛屾病鏈夎鏄庡繀瑕佹��',
- patientName: '鍛ㄥコ澹�',
- gender: 0,
- age: 55,
- phone: '132****9012',
- dischargeDept: '鍛煎惛鍐呯',
- dischargeWard: '鍐呯涓�鐥呭尯',
- fillTime: '2024-01-08 13:30:55',
- processStatus: 1,
- questionnaireId: 1008
- }
- ];
- this.total = this.exceptionList.length;
- resolve();
- }, 500);
+ const date = new Date(dateTime);
+ if (isNaN(date.getTime())) {
+ return dateTime;
+ }
+ return (
+ date.toLocaleDateString().replace(/\//g, "-") +
+ " " +
+ date.toTimeString().split(" ")[0]
+ );
+ } catch (error) {
+ console.error("鏃ユ湡鏍煎紡鍖栭敊璇�:", error);
+ return dateTime;
+ }
+ },
+ /** 鏌ヨ绉戝鍒楄〃 */
+ getDeptOptions() {
+ deptTreeSelect()
+ .then((res) => {
+ if (res.code == 200) {
+ this.deptList = this.flattenArray(res.data) || [];
+ }
+ })
+ .catch((error) => {
+ console.error("鑾峰彇绉戝鍒楄〃澶辫触:", error);
+ this.$message.error("鑾峰彇绉戝鍒楄〃澶辫触");
});
- } finally {
- this.loading = false;
+ },
+ flattenArray(multiArray) {
+ let result = [];
+
+ function flatten(element) {
+ if (element.children && element.children.length > 0) {
+ element.children.forEach((child) => flatten(child));
+ } else {
+ let item = JSON.parse(JSON.stringify(element));
+ result.push(item);
+ }
+ }
+
+ multiArray.forEach((element) => flatten(element));
+ return result;
+ },
+ // 瑙f瀽鎮h�呮弿杩颁俊鎭�
+ parsePatDesc(patdesc) {
+ if (!patdesc) return [];
+
+ try {
+ const parts = patdesc.split("|");
+ const items = [];
+
+ if (parts[0]) items.push({ label: "濮撳悕", value: parts[0] });
+ if (parts[1]) items.push({ label: "鐢佃瘽", value: parts[1] });
+ if (parts[2]) items.push({ label: "绉戝", value: parts[2] });
+
+ return items;
+ } catch (error) {
+ console.error("瑙f瀽鎮h�呬俊鎭け璐�:", error);
+ return [];
}
},
+ // 妫�鏌ヨ川绠℃潈闄�
+ checkQualityPermission() {
+ // 杩欓噷鍙互鏍规嵁瀹為檯鏉冮檺绯荤粺瀹炵幇
+ const userRoles = this.$store.getters.roles || [];
+ return (
+ userRoles.includes("quality_manager") || userRoles.includes("admin")
+ );
+ },
+
// 鑾峰彇鐘舵�佹爣绛剧被鍨�
- getStatusTagType(status) {
- switch (status) {
- case 0: return 'warning'; // 寰呭鐞�
- case 1: return 'primary'; // 澶勭悊涓�
- case 2: return 'success'; // 宸插鐞�
- default: return 'info';
+ getStatusTagType(handleFlag) {
+ switch (handleFlag) {
+ case "0":
+ return "warning"; // 鏈鐞�
+ case "1":
+ return "success"; // 宸插鐞�
+ default:
+ return "info";
}
},
// 鑾峰彇鐘舵�佹枃鏈�
- getStatusText(status) {
- switch (status) {
- case 0: return '寰呭鐞�';
- case 1: return '澶勭悊涓�';
- case 2: return '宸插鐞�';
- default: return '鏈煡';
+ getStatusText(handleFlag) {
+ switch (handleFlag) {
+ case "0":
+ return "鏈鐞�";
+ case "1":
+ return "宸插鐞�";
+ default:
+ return "鏈煡";
+ }
+ },
+
+ // 鎾斁褰曢煶
+ handlePlayAudio(url) {
+ this.audioUrl = url;
+ this.$nextTick(() => {
+ const audioPlayer = this.$refs.audioPlayer;
+ if (audioPlayer) {
+ audioPlayer.play().catch((error) => {
+ console.error("鎾斁澶辫触:", error);
+ this.$message.error("闊抽鎾斁澶辫触");
+ });
+ }
+ });
+ },
+
+ // 鏋勫缓鏌ヨ鍙傛暟
+ buildQueryParams() {
+ const params = {
+ pageNum: this.filterParams.pageNum,
+ pageSize: this.filterParams.pageSize,
+ };
+
+ if (this.filterParams.todeptcode) {
+ params.todeptcode = this.filterParams.todeptcode;
+ }
+
+ if (this.filterParams.handleFlag !== "") {
+ params.handleFlag = this.filterParams.handleFlag;
+ }
+
+ if (this.filterParams.templateType) {
+ params.templateType = this.filterParams.templateType;
+ }
+
+ // if (this.filterParams.scriptid) {
+ // params.scriptid = this.filterParams.scriptid;
+ // }
+ if (this.filterParams.scriptids) {
+ params.scriptids = this.filterParams.scriptids.split(",");
+ }
+
+ return params;
+ },
+
+ // 鍔犺浇寮傚父鍒楄〃
+ async loadExceptionList() {
+ this.loading = true;
+ try {
+ const params = this.buildQueryParams();
+ const response = await tracelist(params);
+
+ if (response && response.code === 200) {
+ this.exceptionList = response.rows || [];
+ this.total = response.total || 0;
+ } else {
+ this.exceptionList = [];
+ this.total = 0;
+ this.$message.error(response?.msg || "鍔犺浇寮傚父鍒楄〃澶辫触");
+ }
+ } catch (error) {
+ console.error("鍔犺浇寮傚父鍒楄〃澶辫触:", error);
+ this.$message.error("鍔犺浇寮傚父鍒楄〃澶辫触锛岃绋嶅悗閲嶈瘯");
+ this.exceptionList = [];
+ this.total = 0;
+ } finally {
+ this.loading = false;
}
},
@@ -621,69 +795,128 @@
// 閲嶇疆绛涢��
handleResetFilter() {
this.filterParams = {
- deptId: '',
- status: '',
+ todeptcode: "",
+ handleFlag: "",
+ templateType: "",
+ scriptids: null, // 淇濈暀闂ID
pageNum: 1,
- pageSize: 10
+ pageSize: 10,
};
+ this.selectedExceptionIds = [];
this.loadExceptionList();
},
// 澶勭悊閫夋嫨鍙樺寲
handleSelectionChange(selection) {
- this.selectedExceptionIds = selection.map(item => item.id);
+ this.selectedExceptionIds = selection.map((item) => item.id);
},
// 澶勭悊鎵归噺鎻愪氦
handleBatchSubmit() {
if (this.selectedExceptionIds.length === 0) {
- this.$message.warning('璇峰厛閫夋嫨瑕佸鐞嗙殑寮傚父鍙嶉');
+ this.$message.warning("璇峰厛閫夋嫨瑕佸鐞嗙殑寮傚父鍙嶉");
return;
}
+
+ // 閲嶇疆鎵归噺澶勭悊琛ㄥ崟
+ this.batchProcessForm = {
+ handleFlag: "",
+ ccdepts: [],
+ handleresult: "",
+ handledesc: "",
+ };
+
this.batchDialogVisible = true;
},
// 杩斿洖寮傚父鍒楄〃
handleGoBack() {
- this.$router.push('/satisfaction/exception/list');
+ this.$router.push("/satisfaction/exception/list");
},
// 鏌ョ湅璇︽儏
handleViewDetail(row) {
- this.$router.push({
- path: '/satisfaction/exception/detail',
- query: {
- id: row.questionnaireId
+ this.selectedRecordId = row.id;
+ this.selectedRecordData = row;
+
+ // 鐢熸垚寮规鏍囬
+ let title = "寮傚父鍙嶉璇︽儏";
+ if (row.patdesc) {
+ const patientName = row.patdescJson.sendname;
+ if (patientName) {
+ title = `${patientName} - ${title}`;
}
- });
+ }
+ this.detailDialogTitle = title;
+
+ this.detailDialogVisible = true;
+ },
+
+ // 澶勭悊璇︽儏寮规鍏抽棴
+ handleDetailDialogClose() {
+ this.detailDialogVisible = false;
+ this.selectedRecordId = null;
+ this.selectedRecordData = null;
+ },
+
+ // 澶勭悊瀹屾垚鍚庣殑鍥炶皟
+ handleProcessed() {
+ this.loadExceptionList();
},
// 澶勭悊鍗曚釜寮傚父
handleProcess(row) {
this.currentExceptionId = row.id;
+
+ // 鍒濆鍖栬〃鍗曟暟鎹�
this.processForm = {
- status: row.processStatus === 0 ? 1 : row.processStatus,
- reportDepts: [],
- remark: ''
+ handleFlag: row.handleFlag === "0" ? "1" : "0",
+ ccdepts: row.ccdepts ? row.ccdepts.split(",") : [],
+ handleresult: row.handleresult || "",
+ handledesc: row.handledesc || "",
+ finaloption: row.finaloption || "",
};
+
this.processDialogVisible = true;
},
// 鎻愪氦澶勭悊
async submitProcess() {
this.$refs.processForm.validate(async (valid) => {
- if (valid) {
- this.processing = true;
- try {
- // Mock API璋冪敤
- await new Promise(resolve => setTimeout(resolve, 1000));
+ if (!valid) {
+ return;
+ }
- this.$message.success('澶勭悊鎻愪氦鎴愬姛');
- this.processDialogVisible = false;
- this.loadExceptionList();
- } finally {
- this.processing = false;
- }
+ this.processing = true;
+
+ try {
+ // 鍑嗗鎻愪氦鏁版嵁
+ const submitData = {
+ id: this.currentExceptionId,
+ handleFlag: this.processForm.handleFlag,
+ handleresult: this.processForm.handleresult,
+ handledesc: this.processForm.handledesc,
+ finaloption: this.processForm.finaloption,
+ handleBy: this.$store.state.user.nickName,
+ handleTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
+ // 灏嗘暟缁勮浆鎹负閫楀彿鍒嗛殧鐨勫瓧绗︿覆
+ ccdepts: Array.isArray(this.processForm.ccdepts)
+ ? this.processForm.ccdepts.join(",")
+ : this.processForm.ccdepts,
+ };
+ // TODO: 杩欓噷闇�瑕佽皟鐢ㄥ疄闄呯殑澶勭悊鎺ュ彛
+ await traceedit(submitData);
+
+ // await new Promise((resolve) => setTimeout(resolve, 1000));
+
+ this.$message.success("澶勭悊鎻愪氦鎴愬姛");
+ this.processDialogVisible = false;
+ this.loadExceptionList();
+ } catch (error) {
+ console.error("澶勭悊鎻愪氦澶辫触:", error);
+ this.$message.error("澶勭悊鎻愪氦澶辫触锛岃绋嶅悗閲嶈瘯");
+ } finally {
+ this.processing = false;
}
});
},
@@ -691,19 +924,111 @@
// 鎻愪氦鎵归噺澶勭悊
async submitBatchProcess() {
this.$refs.batchProcessForm.validate(async (valid) => {
- if (valid) {
- this.batchProcessing = true;
- try {
- // Mock API璋冪敤
- await new Promise(resolve => setTimeout(resolve, 1500));
+ if (!valid) {
+ return;
+ }
- this.$message.success(`宸叉壒閲忓鐞� ${this.selectedExceptionIds.length} 鏉″紓甯稿弽棣坄);
- this.batchDialogVisible = false;
- this.selectedExceptionIds = [];
- this.loadExceptionList();
- } finally {
- this.batchProcessing = false;
+ this.batchProcessing = true;
+ // 鏄剧ず杩涘害鏉�
+ this.batchProgress = {
+ visible: true,
+ percentage: 0,
+ processed: 0,
+ total: this.selectedExceptionIds.length,
+ };
+ try {
+ // 鍑嗗鎵归噺鎻愪氦鏁版嵁
+ const processData = {
+ handleFlag: this.batchProcessForm.handleFlag,
+ handleresult: this.batchProcessForm.handleresult,
+ handledesc: this.batchProcessForm.handledesc,
+ ccdepts: Array.isArray(this.batchProcessForm.ccdepts)
+ ? this.batchProcessForm.ccdepts.join(",")
+ : this.batchProcessForm.ccdepts,
+ };
+
+ // 鎺у埗骞跺彂鏁�
+ const CONCURRENT_LIMIT = 10; // 鍚屾椂鏈�澶�3涓姹�
+ const totalCount = this.selectedExceptionIds.length;
+ const results = [];
+ let successCount = 0;
+ let failCount = 0;
+
+ this.$message.info(`寮�濮嬫壒閲忓鐞� ${totalCount} 鏉¤褰�...`);
+
+ // 鍒嗙粍澶勭悊
+ for (
+ let i = 0;
+ i < this.selectedExceptionIds.length;
+ i += CONCURRENT_LIMIT
+ ) {
+ const batchIds = this.selectedExceptionIds.slice(
+ i,
+ i + CONCURRENT_LIMIT
+ );
+
+ // 骞跺彂澶勭悊褰撳墠鎵规
+ const batchPromises = batchIds.map((id) =>
+ traceedit({
+ id: id,
+ ...processData,
+ })
+ .then((result) => ({
+ id,
+ success: result && result.code === 200,
+ error: result?.msg,
+ }))
+ .catch((error) => ({
+ id,
+ success: false,
+ error: error.message,
+ }))
+ );
+
+ const batchResults = await Promise.all(batchPromises);
+ results.push(...batchResults);
+
+ // 鏇存柊缁熻
+ batchResults.forEach((result) => {
+ if (result.success) {
+ successCount++;
+ } else {
+ failCount++;
+ console.error(`澶勭悊璁板綍 ${result.id} 澶辫触:`, result.error);
+ }
+ });
+ // 鏇存柊杩涘害
+ this.batchProgress.processed = i + 1;
+ this.batchProgress.percentage = Math.round(
+ ((i + 1) / totalCount) * 100
+ );
+ // 鏄剧ず杩涘害
+ console.log(
+ `杩涘害: ${Math.min(
+ i + CONCURRENT_LIMIT,
+ totalCount
+ )}/${totalCount}`
+ );
}
+
+ // 澶勭悊缁撴灉鎻愮ず
+ if (successCount === totalCount) {
+ this.$message.success(`宸叉垚鍔熷鐞嗗叏閮� ${totalCount} 鏉″紓甯稿弽棣坄);
+ } else {
+ this.$message.warning(
+ `宸插鐞� ${successCount} 鏉★紝澶辫触 ${failCount} 鏉″紓甯稿弽棣坄
+ );
+ }
+
+ this.batchDialogVisible = false;
+ this.selectedExceptionIds = [];
+ this.loadExceptionList();
+ } catch (error) {
+ console.error("鎵归噺澶勭悊澶辫触:", error);
+ this.$message.error("鎵归噺澶勭悊澶辫触锛岃绋嶅悗閲嶈瘯");
+ } finally {
+ this.batchProcessing = false;
+ this.batchProgress.visible = false;
}
});
},
@@ -720,24 +1045,7 @@
this.filterParams.pageNum = page;
this.loadExceptionList();
},
-
- // 鏂囦欢涓婁紶鐩稿叧鏂规硶
- handlePreview(file) {
- console.log('棰勮鏂囦欢:', file);
- },
-
- handleRemove(file, fileList) {
- console.log('绉婚櫎鏂囦欢:', file, fileList);
- },
-
- beforeRemove(file) {
- return this.$confirm(`纭畾绉婚櫎 ${file.name}锛焋);
- },
-
- handleExceed(files, fileList) {
- this.$message.warning(`褰撳墠闄愬埗閫夋嫨 3 涓枃浠讹紝鏈閫夋嫨浜� ${files.length} 涓枃浠讹紝鍏遍�夋嫨浜� ${files.length + fileList.length} 涓枃浠禶);
- }
- }
+ },
};
</script>
@@ -750,7 +1058,7 @@
.page-header {
margin-bottom: 20px;
padding: 20px;
- background: linear-gradient(135deg, #5788FE 0%, #66b1ff 100%);
+ background: linear-gradient(135deg, #5788fe 0%, #66b1ff 100%);
border-radius: 8px;
color: white;
@@ -804,64 +1112,109 @@
}
.detail-content {
- font-size: 13px;
- color: #606266;
- line-height: 1.5;
text-align: left;
+ font-size: 12px;
+ line-height: 1.5;
+
+ .question-text {
+ color: #303133;
+ margin-bottom: 5px;
+ font-weight: 500;
+ }
+
+ .answer-text {
+ color: #f56c6c;
+ margin-bottom: 5px;
+ }
+
+ .matched-text {
+ color: #e6a23c;
+ font-style: italic;
+ }
+
+ strong {
+ color: #606266;
+ font-weight: 600;
+ }
}
.patient-info {
- .patient-item {
+ .patient-row {
display: flex;
justify-content: space-between;
align-items: center;
- margin-bottom: 5px;
- padding: 2px 0;
+ margin-bottom: 8px;
- .label {
- font-size: 12px;
- color: #606266;
- min-width: 40px;
+ &:last-child {
+ margin-bottom: 0;
}
- .value {
- font-size: 13px;
- color: #333;
- font-weight: 500;
- text-align: right;
+ .patient-item {
flex: 1;
+ display: flex;
+ justify-content: flex-start;
+ align-items: center;
+ padding: 0 5px;
+
+ &.full-width {
+ flex: 1 0 100%;
+ margin-left: 0;
+ margin-right: 0;
+ }
+
+ .label {
+ font-size: 12px;
+ color: #606266;
+ margin-right: 5px;
+ white-space: nowrap;
+ }
+
+ .value {
+ font-size: 12px;
+ color: #333;
+ font-weight: 500;
+ text-align: right;
+ word-break: break-all;
+ }
}
}
}
- .discharge-info {
+ .fill-info,
+ .handle-info {
+ font-size: 12px;
+
.info-item {
display: flex;
- justify-content: space-between;
+ justify-content: flex-start;
align-items: center;
margin-bottom: 5px;
padding: 2px 0;
.label {
- font-size: 12px;
color: #606266;
min-width: 50px;
}
.value {
- font-size: 13px;
color: #333;
font-weight: 500;
- text-align: right;
+ // text-align: right;
flex: 1;
&.time {
- font-size: 12px;
color: #909399;
+ font-size: 11px;
}
}
}
}
+
+ .no-data {
+ color: #909399;
+ font-style: italic;
+ font-size: 12px;
+ }
}
.pagination-section {
--
Gitblit v1.9.3