From 61f0c5d3a9308d1eaefd8890a46b3c569707e050 Mon Sep 17 00:00:00 2001
From: WXL (wul) <wl_5969728@163.com>
Date: 星期四, 09 四月 2026 09:24:47 +0800
Subject: [PATCH] 测试完成
---
/dev/null | 0
dist.zip | 0
src/api/AiCentre/satisfactionse.js | 25
src/views/Satisfaction/sfstatistics/components/SatisfactionStatistics.vue | 70
vue.config.js | 4
src/views/followvisit/HistoricalFollow/index.vue | 6
src/components/AudioPlayer/index.vue | 964 +++++++++++++++
src/views/Satisfaction/configurationmyd/batch.vue | 989 ++++++++++-----
src/views/Satisfaction/configurationmyd/components/DetailsAnomaly.vue | 1272 ++++++++++++--------
src/views/Satisfaction/configurationmyd/dispose.vue | 422 ++----
10 files changed, 2,606 insertions(+), 1,146 deletions(-)
diff --git a/dist.zip b/dist.zip
index 71249fa..978792a 100644
--- a/dist.zip
+++ b/dist.zip
Binary files differ
diff --git a/sltd.zip b/sltd.zip
deleted file mode 100644
index 37ef9e2..0000000
--- a/sltd.zip
+++ /dev/null
Binary files differ
diff --git a/src/api/AiCentre/satisfactionse.js b/src/api/AiCentre/satisfactionse.js
index e9901b0..fef0537 100644
--- a/src/api/AiCentre/satisfactionse.js
+++ b/src/api/AiCentre/satisfactionse.js
@@ -35,6 +35,31 @@
method: "get",
});
}
+// 寮傚父澶勭悊鍒楄〃
+export function tracedeallist(data) {
+ return request({
+ url: "/smartor/trace/tracedeallist",
+ method: "post",
+ data: data,
+ });
+}
+// 鎵归噺澶勭悊鍒楄〃
+export function tracelist(data) {
+ return request({
+ url: "/smartor/trace/list",
+ method: "post",
+ data: data,
+ });
+}
+// 浠诲姟鍒楄〃淇敼澶勭悊
+export function traceedit(data) {
+ return request({
+ url: "/smartor/trace/edit",
+ method: "post",
+ data: data,
+ });
+}
+
diff --git a/src/components/AudioPlayer/index.vue b/src/components/AudioPlayer/index.vue
new file mode 100644
index 0000000..0524c1f
--- /dev/null
+++ b/src/components/AudioPlayer/index.vue
@@ -0,0 +1,964 @@
+<template>
+ <div class="audio-player">
+ <!-- 涓绘挱鏀惧櫒 -->
+ <div class="audio-container" v-if="showDefaultPlayer">
+ <audio
+ ref="audioElement"
+ :src="audioSource"
+ preload="metadata"
+ @timeupdate="updateTime"
+ @loadedmetadata="updateDuration"
+ @play="handlePlay"
+ @pause="handlePause"
+ @ended="handleEnded"
+ @error="handleError"
+ style="display: none"
+ ></audio>
+
+ <!-- 鎾斁鎺у埗 -->
+ <div class="audio-controls">
+ <el-button
+ v-if="!isPlaying"
+ type="text"
+ icon="el-icon-video-play"
+ class="play-btn"
+ @click="playAudio"
+ :loading="loading"
+ ></el-button>
+ <el-button
+ v-else
+ type="text"
+ icon="el-icon-video-pause"
+ class="pause-btn"
+ @click="pauseAudio"
+ ></el-button>
+
+ <!-- 杩涘害鏉� -->
+ <div class="progress-container" @click="seekAudio" @mousemove="updateHoverTime">
+ <div class="progress-background">
+ <!-- 缂撳啿杩涘害 -->
+ <div
+ v-if="buffered.length > 0"
+ class="buffered-progress"
+ :style="{ width: `${bufferedPercent}%` }"
+ ></div>
+
+ <!-- 鎾斁杩涘害 -->
+ <div
+ class="played-progress"
+ :style="{ width: `${progressPercent}%` }"
+ ></div>
+
+ <!-- 鎮仠棰勮 -->
+ <div
+ v-if="showHoverPreview"
+ class="hover-preview"
+ :style="{ left: `${hoverPercent}%` }"
+ >
+ <span class="hover-time">{{ formatTime(hoverTime) }}</span>
+ </div>
+
+ <!-- 鎾斁鐐� -->
+ <div
+ class="playhead"
+ :style="{ left: `${progressPercent}%` }"
+ ></div>
+ </div>
+ </div>
+
+ <!-- 鏃堕棿鏄剧ず -->
+ <div class="time-display">
+ <span class="current-time">{{ formatTime(currentTime) }}</span>
+ <span class="time-separator">/</span>
+ <span class="duration">{{ formatTime(duration) }}</span>
+ </div>
+
+ <!-- 闊抽噺鎺у埗 -->
+ <div class="volume-control" v-if="showVolumeControl">
+ <el-popover
+ placement="top"
+ width="40"
+ trigger="hover"
+ popper-class="volume-popover"
+ >
+ <div class="volume-slider-container" @click.stop>
+ <el-slider
+ v-model="volume"
+ vertical
+ height="100px"
+ :show-tooltip="false"
+ @input="changeVolume"
+ ></el-slider>
+ </div>
+
+ <el-button
+ slot="reference"
+ type="text"
+ :icon="volumeIcon"
+ class="volume-btn"
+ @click.stop
+ ></el-button>
+ </el-popover>
+ </div>
+
+ <!-- 鎾斁閫熷害 -->
+ <el-select
+ v-if="showPlaybackRate"
+ v-model="playbackRate"
+ size="mini"
+ class="playback-rate"
+ @change="changePlaybackRate"
+ >
+ <el-option
+ v-for="rate in playbackRates"
+ :key="rate"
+ :label="`${rate}x`"
+ :value="rate"
+ ></el-option>
+ </el-select>
+
+ <!-- 涓嬭浇鎸夐挳 -->
+ <el-button
+ v-if="showDownload"
+ type="text"
+ icon="el-icon-download"
+ class="download-btn"
+ @click="downloadAudio"
+ title="涓嬭浇闊抽"
+ ></el-button>
+
+ <!-- 鏇村鍔熻兘鎸夐挳 -->
+ <el-dropdown
+ v-if="showMoreOptions"
+ trigger="click"
+ class="more-options"
+ >
+ <el-button type="text" icon="el-icon-more" class="more-btn"></el-button>
+ <el-dropdown-menu slot="dropdown">
+ <el-dropdown-item @click.native="loopAudio = !loopAudio">
+ <i :class="loopAudio ? 'el-icon-refresh' : 'el-icon-refresh-left'"></i>
+ {{ loopAudio ? '鍏抽棴寰幆' : '寮�鍚惊鐜�' }}
+ </el-dropdown-item>
+ <el-dropdown-item @click.native="resetAudio">
+ <i class="el-icon-refresh-right"></i>
+ 閲嶇疆
+ </el-dropdown-item>
+ <el-dropdown-item v-if="showDetails" @click.native="showAudioInfo">
+ <i class="el-icon-info"></i>
+ 闊抽淇℃伅
+ </el-dropdown-item>
+ </el-dropdown-menu>
+ </el-dropdown>
+ </div>
+ </div>
+
+ <!-- 闊抽淇℃伅瀵硅瘽妗� -->
+ <el-dialog
+ v-if="showDetailsDialog"
+ title="闊抽淇℃伅"
+ :visible.sync="showDetailsDialog"
+ width="400px"
+ >
+ <div class="audio-info">
+ <div class="info-item">
+ <span class="label">鏂囦欢澶у皬锛�</span>
+ <span class="value">{{ fileSize }}</span>
+ </div>
+ <div class="info-item">
+ <span class="label">闊抽鏃堕暱锛�</span>
+ <span class="value">{{ formatTime(duration) }}</span>
+ </div>
+ <div class="info-item">
+ <span class="label">鏂囦欢鏍煎紡锛�</span>
+ <span class="value">{{ audioFormat }}</span>
+ </div>
+ <div class="info-item">
+ <span class="label">闊抽鍦板潃锛�</span>
+ <a :href="audioSource" target="_blank" class="audio-url">{{ truncateUrl(audioSource) }}</a>
+ </div>
+ </div>
+ </el-dialog>
+
+ <!-- 绠�鏄撴挱鏀惧櫒锛堜粎鏄剧ず鎾斁鎸夐挳锛� -->
+ <div v-else class="simple-player">
+ <el-button
+ v-if="!isPlaying"
+ type="text"
+ icon="el-icon-video-play"
+ size="small"
+ class="simple-play-btn"
+ @click="playAudio"
+ :loading="loading"
+ >
+ 鎾斁褰曢煶
+ </el-button>
+ <el-button
+ v-else
+ type="text"
+ icon="el-icon-video-pause"
+ size="small"
+ class="simple-pause-btn"
+ @click="pauseAudio"
+ >
+ 鏆傚仠鎾斁
+ </el-button>
+ </div>
+ </div>
+</template>
+
+<script>
+export default {
+ name: 'AudioPlayer',
+ props: {
+ // 闊抽婧愬湴鍧�
+ audioSource: {
+ type: String,
+ default: ''
+ },
+
+ // 鏄惁鏄剧ず瀹屾暣鎾斁鍣�
+ showDefaultPlayer: {
+ type: Boolean,
+ default: true
+ },
+
+ // 鏄惁鏄剧ず闊抽噺鎺у埗
+ showVolumeControl: {
+ type: Boolean,
+ default: true
+ },
+
+ // 鏄惁鏄剧ず鎾斁閫熷害鎺у埗
+ showPlaybackRate: {
+ type: Boolean,
+ default: true
+ },
+
+ // 鏄惁鏄剧ず涓嬭浇鎸夐挳
+ showDownload: {
+ type: Boolean,
+ default: true
+ },
+
+ // 鏄惁鏄剧ず鏇村閫夐」
+ showMoreOptions: {
+ type: Boolean,
+ default: true
+ },
+
+ // 鏄惁鏄剧ず闊抽淇℃伅
+ showDetails: {
+ type: Boolean,
+ default: true
+ },
+
+ // 鍒濆闊抽噺锛�0-100锛�
+ initialVolume: {
+ type: Number,
+ default: 80,
+ validator: (value) => value >= 0 && value <= 100
+ },
+
+ // 鍒濆鎾斁閫熷害
+ initialPlaybackRate: {
+ type: Number,
+ default: 1.0
+ },
+
+ // 鑷姩鎾斁
+ autoplay: {
+ type: Boolean,
+ default: false
+ },
+
+ // 寰幆鎾斁
+ loop: {
+ type: Boolean,
+ default: false
+ }
+ },
+
+ data() {
+ return {
+ // 鎾斁鐘舵��
+ isPlaying: false,
+ isLoading: false,
+ loading: false,
+ error: false,
+
+ // 鏃堕棿鐩稿叧
+ currentTime: 0,
+ duration: 0,
+ buffered: [],
+
+ // 闊抽噺
+ volume: this.initialVolume,
+ isMuted: false,
+
+ // 鎾斁閫熷害
+ playbackRate: this.initialPlaybackRate,
+ playbackRates: [0.5, 0.75, 1.0, 1.25, 1.5, 2.0],
+
+ // 寰幆鎾斁
+ loopAudio: this.loop,
+
+ // 杩涘害鏉℃偓鍋�
+ hoverTime: 0,
+ hoverPercent: 0,
+ showHoverPreview: false,
+
+ // 闊抽淇℃伅
+ showDetailsDialog: false,
+ fileSize: '鏈煡',
+ audioFormat: '鏈煡',
+
+ // 鐩戝惉鍣ㄥ紩鐢�
+ resizeObserver: null
+ };
+ },
+
+ computed: {
+ // 鎾斁杩涘害鐧惧垎姣�
+ progressPercent() {
+ if (this.duration <= 0) return 0;
+ return (this.currentTime / this.duration) * 100;
+ },
+
+ // 缂撳啿杩涘害鐧惧垎姣�
+ bufferedPercent() {
+ if (this.duration <= 0) return 0;
+ if (this.buffered.length === 0) return 0;
+
+ const bufferedEnd = this.buffered.end(this.buffered.length - 1);
+ return (bufferedEnd / this.duration) * 100;
+ },
+
+ // 闊抽噺鍥炬爣
+ volumeIcon() {
+ if (this.isMuted || this.volume === 0) {
+ return 'el-icon-turn-off-microphone';
+ } else if (this.volume <= 30) {
+ return 'el-icon-microphone';
+ } else if (this.volume <= 70) {
+ return 'el-icon-microphone';
+ } else {
+ return 'el-icon-microphone';
+ }
+ }
+ },
+
+ watch: {
+ // 鐩戝惉闊抽婧愬彉鍖�
+ audioSource(newSource) {
+ if (newSource) {
+ this.resetAudio();
+ this.loadAudio();
+ }
+ },
+
+ // 鐩戝惉鑷姩鎾斁
+ autoplay(newVal) {
+ if (newVal && this.audioSource) {
+ this.playAudio();
+ }
+ },
+
+ // 鐩戝惉寰幆鎾斁
+ loopAudio(newVal) {
+ this.$emit('loop-change', newVal);
+ }
+ },
+
+ mounted() {
+ if (this.audioSource) {
+ this.loadAudio();
+ }
+
+ // 鐩戝惉绐楀彛澶у皬鍙樺寲
+ this.resizeObserver = new ResizeObserver(() => {
+ this.updateBuffered();
+ });
+
+ if (this.$refs.audioElement) {
+ this.resizeObserver.observe(this.$refs.audioElement);
+ }
+ },
+
+ beforeDestroy() {
+ if (this.resizeObserver) {
+ this.resizeObserver.disconnect();
+ }
+
+ // 鍋滄闊抽鎾斁
+ this.pauseAudio();
+ },
+
+ methods: {
+ // 鍔犺浇闊抽
+ async loadAudio() {
+ this.loading = true;
+ this.error = false;
+
+ try {
+ const audio = this.$refs.audioElement;
+ if (!audio) return;
+
+ // 璁剧疆闊抽噺
+ audio.volume = this.volume / 100;
+ audio.playbackRate = this.playbackRate;
+ audio.loop = this.loopAudio;
+
+ // 灏濊瘯鑾峰彇鏂囦欢淇℃伅
+ this.getAudioInfo();
+
+ // 濡傛灉璁剧疆浜嗚嚜鍔ㄦ挱鏀撅紝寮�濮嬫挱鏀�
+ if (this.autoplay) {
+ await this.playAudio();
+ }
+ } catch (error) {
+ console.error('鍔犺浇闊抽澶辫触:', error);
+ this.error = true;
+ this.$emit('error', error);
+ } finally {
+ this.loading = false;
+ }
+ },
+
+ // 鎾斁闊抽
+ async playAudio() {
+ try {
+ const audio = this.$refs.audioElement;
+ if (!audio) return;
+
+ await audio.play();
+ this.isPlaying = true;
+ this.$emit('play');
+ } catch (error) {
+ console.error('鎾斁澶辫触:', error);
+ this.error = true;
+ this.isPlaying = false;
+ this.$emit('error', error);
+
+ // 濡傛灉鏄敤鎴蜂氦浜掑紩璧风殑閿欒锛屾彁绀虹敤鎴�
+ if (error.name === 'NotAllowedError') {
+ this.$message.warning('璇锋墜鍔ㄧ偣鍑绘挱鏀炬寜閽紑濮嬫挱鏀�');
+ }
+ }
+ },
+
+ // 鏆傚仠闊抽
+ pauseAudio() {
+ const audio = this.$refs.audioElement;
+ if (!audio) return;
+
+ audio.pause();
+ this.isPlaying = false;
+ this.$emit('pause');
+ },
+
+ // 璺宠浆鍒版寚瀹氭椂闂�
+ seekAudio(event) {
+ const audio = this.$refs.audioElement;
+ if (!audio || this.duration <= 0) return;
+
+ const progressContainer = event.currentTarget;
+ const rect = progressContainer.getBoundingClientRect();
+ const x = event.clientX - rect.left;
+ const width = rect.width;
+
+ const percent = Math.max(0, Math.min(1, x / width));
+ const time = percent * this.duration;
+
+ audio.currentTime = time;
+ this.currentTime = time;
+ this.$emit('seek', time);
+ },
+
+ // 鏇存柊鎮仠鏃堕棿
+ updateHoverTime(event) {
+ const progressContainer = event.currentTarget;
+ const rect = progressContainer.getBoundingClientRect();
+ const x = event.clientX - rect.left;
+ const width = rect.width;
+
+ const percent = Math.max(0, Math.min(1, x / width));
+ this.hoverPercent = percent * 100;
+ this.hoverTime = percent * this.duration;
+ this.showHoverPreview = true;
+ },
+
+ // 闅愯棌鎮仠棰勮
+ hideHoverPreview() {
+ this.showHoverPreview = false;
+ },
+
+ // 鏇存柊鏃堕棿
+ updateTime() {
+ const audio = this.$refs.audioElement;
+ if (!audio) return;
+
+ this.currentTime = audio.currentTime;
+ this.$emit('timeupdate', this.currentTime);
+ },
+
+ // 鏇存柊鎬绘椂闀�
+ updateDuration() {
+ const audio = this.$refs.audioElement;
+ if (!audio) return;
+
+ this.duration = audio.duration;
+ this.updateBuffered();
+ this.$emit('loadedmetadata', this.duration);
+ },
+
+ // 鏇存柊缂撳啿鏁版嵁
+ updateBuffered() {
+ const audio = this.$refs.audioElement;
+ if (!audio) return;
+
+ this.buffered = audio.buffered;
+ },
+
+ // 澶勭悊鎾斁
+ handlePlay() {
+ this.isPlaying = true;
+ this.$emit('play');
+ },
+
+ // 澶勭悊鏆傚仠
+ handlePause() {
+ this.isPlaying = false;
+ this.$emit('pause');
+ },
+
+ // 澶勭悊鎾斁缁撴潫
+ handleEnded() {
+ this.isPlaying = false;
+ this.currentTime = 0;
+ this.$emit('ended');
+ },
+
+ // 澶勭悊閿欒
+ handleError(event) {
+ console.error('闊抽鎾斁閿欒:', event);
+ this.error = true;
+ this.isPlaying = false;
+ this.$emit('error', event);
+ },
+
+ // 鏀瑰彉闊抽噺
+ changeVolume(value) {
+ const audio = this.$refs.audioElement;
+ if (!audio) return;
+
+ audio.volume = value / 100;
+ this.volume = value;
+ this.isMuted = value === 0;
+ this.$emit('volume-change', value);
+ },
+
+ // 闈欓煶/鍙栨秷闈欓煶
+ toggleMute() {
+ const audio = this.$refs.audioElement;
+ if (!audio) return;
+
+ this.isMuted = !this.isMuted;
+ audio.muted = this.isMuted;
+ this.$emit('mute-change', this.isMuted);
+ },
+
+ // 鏀瑰彉鎾斁閫熷害
+ changePlaybackRate(rate) {
+ const audio = this.$refs.audioElement;
+ if (!audio) return;
+
+ audio.playbackRate = rate;
+ this.playbackRate = rate;
+ this.$emit('playbackrate-change', rate);
+ },
+
+ // 閲嶇疆闊抽
+ resetAudio() {
+ const audio = this.$refs.audioElement;
+ if (!audio) return;
+
+ audio.currentTime = 0;
+ this.currentTime = 0;
+ this.pauseAudio();
+ this.$emit('reset');
+ },
+
+ // 涓嬭浇闊抽
+ downloadAudio() {
+ if (!this.audioSource) {
+ this.$message.warning('闊抽鍦板潃鏃犳晥');
+ return;
+ }
+
+ const link = document.createElement('a');
+ link.href = this.audioSource;
+ link.download = this.getFileNameFromUrl(this.audioSource);
+ document.body.appendChild(link);
+ link.click();
+ document.body.removeChild(link);
+
+ this.$emit('download');
+ },
+
+ // 鏄剧ず闊抽淇℃伅
+ async showAudioInfo() {
+ this.showDetailsDialog = true;
+ await this.getAudioInfo();
+ },
+
+ // 鑾峰彇闊抽淇℃伅
+ async getAudioInfo() {
+ if (!this.audioSource) return;
+
+ try {
+ // 鑾峰彇鏂囦欢澶у皬
+ const response = await fetch(this.audioSource, { method: 'HEAD' });
+ const contentLength = response.headers.get('content-length');
+
+ if (contentLength) {
+ this.fileSize = this.formatFileSize(contentLength);
+ }
+
+ // 鑾峰彇鏂囦欢鏍煎紡
+ const url = this.audioSource.toLowerCase();
+ if (url.endsWith('.mp3')) this.audioFormat = 'MP3';
+ else if (url.endsWith('.wav')) this.audioFormat = 'WAV';
+ else if (url.endsWith('.ogg')) this.audioFormat = 'OGG';
+ else if (url.endsWith('.m4a')) this.audioFormat = 'M4A';
+ else if (url.endsWith('.aac')) this.audioFormat = 'AAC';
+ else this.audioFormat = '鏈煡鏍煎紡';
+
+ } catch (error) {
+ console.error('鑾峰彇闊抽淇℃伅澶辫触:', error);
+ this.fileSize = '鏈煡';
+ this.audioFormat = '鏈煡';
+ }
+ },
+
+ // 鏍煎紡鍖栨椂闂�
+ formatTime(time) {
+ if (isNaN(time) || time < 0) return '00:00';
+
+ const hours = Math.floor(time / 3600);
+ const minutes = Math.floor((time % 3600) / 60);
+ const seconds = Math.floor(time % 60);
+
+ if (hours > 0) {
+ return `${hours.toString().padStart(2, '0')}:${minutes
+ .toString()
+ .padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
+ } else {
+ return `${minutes.toString().padStart(2, '0')}:${seconds
+ .toString()
+ .padStart(2, '0')}`;
+ }
+ },
+
+ // 鏍煎紡鍖栨枃浠跺ぇ灏�
+ formatFileSize(bytes) {
+ if (bytes === 0) return '0 B';
+
+ const k = 1024;
+ const sizes = ['B', 'KB', 'MB', 'GB'];
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
+
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
+ },
+
+ // 鎴柇URL鏄剧ず
+ truncateUrl(url, maxLength = 40) {
+ if (!url) return '';
+ if (url.length <= maxLength) return url;
+
+ const start = url.substring(0, maxLength / 2 - 3);
+ const end = url.substring(url.length - maxLength / 2 + 3);
+ return start + '...' + end;
+ },
+
+ // 浠嶶RL鑾峰彇鏂囦欢鍚�
+ getFileNameFromUrl(url) {
+ if (!url) return 'audio';
+
+ const fileName = url.split('/').pop();
+ return fileName || 'audio';
+ }
+ }
+};
+</script>
+
+<style lang="scss" scoped>
+.audio-player {
+ width: 100%;
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
+
+ .audio-container {
+ background: #fff;
+ border-radius: 8px;
+ padding: 12px 16px;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+ border: 1px solid #ebeef5;
+
+ .audio-controls {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+
+ .play-btn,
+ .pause-btn {
+ width: 36px;
+ height: 36px;
+ padding: 0;
+ font-size: 20px;
+ color: #409EFF;
+
+ &:hover {
+ color: #66b1ff;
+ }
+
+ &:active {
+ color: #3a8ee6;
+ }
+ }
+
+ .progress-container {
+ flex: 1;
+ height: 36px;
+ display: flex;
+ align-items: center;
+ cursor: pointer;
+
+ .progress-background {
+ position: relative;
+ width: 100%;
+ height: 6px;
+ background: #e4e7ed;
+ border-radius: 3px;
+ overflow: visible;
+
+ .buffered-progress {
+ position: absolute;
+ top: 0;
+ left: 0;
+ height: 100%;
+ background: #c0c4cc;
+ border-radius: 3px;
+ transition: width 0.2s ease;
+ }
+
+ .played-progress {
+ position: absolute;
+ top: 0;
+ left: 0;
+ height: 100%;
+ background: #409EFF;
+ border-radius: 3px;
+ transition: width 0.2s ease;
+ z-index: 2;
+ }
+
+ .hover-preview {
+ position: absolute;
+ top: -30px;
+ width: 1px;
+ height: 20px;
+ background: #909399;
+ transform: translateX(-50%);
+ z-index: 3;
+ pointer-events: none;
+
+ .hover-time {
+ position: absolute;
+ bottom: 100%;
+ left: 50%;
+ transform: translateX(-50%);
+ background: rgba(0, 0, 0, 0.8);
+ color: white;
+ padding: 2px 6px;
+ border-radius: 3px;
+ font-size: 12px;
+ white-space: nowrap;
+ }
+
+ &::after {
+ content: '';
+ position: absolute;
+ top: 100%;
+ left: 50%;
+ transform: translateX(-50%);
+ width: 0;
+ height: 0;
+ border-left: 4px solid transparent;
+ border-right: 4px solid transparent;
+ border-top: 4px solid rgba(0, 0, 0, 0.8);
+ }
+ }
+
+ .playhead {
+ position: absolute;
+ top: 50%;
+ width: 12px;
+ height: 12px;
+ background: #fff;
+ border: 2px solid #409EFF;
+ border-radius: 50%;
+ transform: translate(-50%, -50%);
+ z-index: 4;
+ cursor: pointer;
+ transition: all 0.2s ease;
+
+ &:hover {
+ transform: translate(-50%, -50%) scale(1.2);
+ box-shadow: 0 0 8px rgba(64, 158, 255, 0.5);
+ }
+ }
+ }
+
+ &:hover {
+ .progress-background {
+ height: 8px;
+
+ .playhead {
+ transform: translate(-50%, -50%) scale(1.1);
+ }
+ }
+ }
+ }
+
+ .time-display {
+ min-width: 100px;
+ font-size: 12px;
+ color: #606266;
+ display: flex;
+ align-items: center;
+ gap: 2px;
+
+ .current-time {
+ color: #303133;
+ font-weight: 500;
+ }
+
+ .time-separator {
+ opacity: 0.6;
+ }
+
+ .duration {
+ opacity: 0.8;
+ }
+ }
+
+ .volume-control {
+ .volume-btn {
+ padding: 0;
+ width: 24px;
+ height: 24px;
+ font-size: 16px;
+ color: #606266;
+
+ &:hover {
+ color: #409EFF;
+ }
+ }
+ }
+
+ .playback-rate {
+ width: 60px;
+
+ ::v-deep .el-input__inner {
+ height: 24px;
+ line-height: 24px;
+ padding: 0 5px;
+ font-size: 12px;
+ }
+ }
+
+ .download-btn,
+ .more-btn {
+ padding: 0;
+ width: 24px;
+ height: 24px;
+ font-size: 16px;
+ color: #606266;
+
+ &:hover {
+ color: #409EFF;
+ }
+ }
+ }
+ }
+
+ .simple-player {
+ .simple-play-btn,
+ .simple-pause-btn {
+ padding: 4px 8px;
+ font-size: 12px;
+ color: #409EFF;
+
+ &:hover {
+ color: #66b1ff;
+ }
+ }
+ }
+
+ .audio-info {
+ .info-item {
+ margin-bottom: 12px;
+ display: flex;
+
+ .label {
+ width: 80px;
+ font-weight: 500;
+ color: #303133;
+ }
+
+ .value {
+ flex: 1;
+ color: #606266;
+ }
+
+ .audio-url {
+ color: #409EFF;
+ text-decoration: none;
+
+ &:hover {
+ text-decoration: underline;
+ }
+ }
+ }
+ }
+}
+
+// 闊抽噺寮圭獥鏍峰紡
+::v-deep .volume-popover {
+ padding: 10px;
+ min-width: 40px;
+
+ .volume-slider-container {
+ height: 100px;
+ display: flex;
+ justify-content: center;
+
+ .el-slider {
+ height: 100%;
+
+ .el-slider__runway {
+ background: #e4e7ed;
+ }
+
+ .el-slider__bar {
+ background: #409EFF;
+ }
+
+ .el-slider__button {
+ border-color: #409EFF;
+ width: 12px;
+ height: 12px;
+ }
+ }
+ }
+}
+</style>
diff --git a/src/views/Satisfaction/configurationmyd/batch.vue b/src/views/Satisfaction/configurationmyd/batch.vue
index 10d6619..8e6d01a 100644
--- a/src/views/Satisfaction/configurationmyd/batch.vue
+++ b/src/views/Satisfaction/configurationmyd/batch.vue
@@ -11,8 +11,9 @@
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">
杩斿洖寮傚父鍒楄〃
@@ -33,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>
@@ -79,6 +91,7 @@
:border="true"
style="width: 100%"
@selection-change="handleSelectionChange"
+ row-key="id"
class="exception-table"
>
<el-table-column type="selection" width="55" align="center" />
@@ -92,24 +105,30 @@
<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>
@@ -117,42 +136,50 @@
<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.patientName }}</span>
+ </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>
- <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.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>
@@ -160,14 +187,36 @@
<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>
@@ -191,7 +240,7 @@
size="small"
icon="el-icon-edit"
@click="handleProcess(row)"
- :disabled="row.processStatus === 2"
+ :disabled="row.handleFlag === '1'"
>
澶勭悊
</el-button>
@@ -229,63 +278,76 @@
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">
@@ -310,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>
@@ -358,24 +436,56 @@
@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 { deptTreeSelect } from "@/api/system/user";
+
export default {
name: "BatchProcess",
components: {
@@ -383,10 +493,15 @@
},
data() {
return {
- // 娣诲姞浠ヤ笅鏁版嵁
+ // 璇︽儏寮规鐩稿叧
detailDialogVisible: false,
selectedRecordId: null,
+ selectedRecordData: null,
detailDialogTitle: "寮傚父鍙嶉璇︽儏",
+
+ // 闊抽鎾斁
+ audioUrl: "",
+
// 褰撳墠澶勭悊鐨勫紓甯窱D
currentExceptionId: null,
@@ -395,8 +510,10 @@
// 杩囨护鍙傛暟
filterParams: {
- deptId: "",
- status: "",
+ todeptcode: "",
+ handleFlag: "",
+ templateType: "",
+ scriptid: null,
pageNum: 1,
pageSize: 10,
},
@@ -406,19 +523,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: [],
@@ -427,183 +536,164 @@
// 澶勭悊瀵硅瘽妗�
processDialogVisible: false,
processForm: {
- status: "",
- reportDepts: [],
- remark: "",
+ handleFlag: "",
+ ccdepts: [],
+ handleresult: "",
+ handledesc: "",
+ finaloption: "",
+ },
+ batchProgress: {
+ visible: false,
+ percentage: 0,
+ processed: 0,
+ total: 0,
},
processRules: {
- status: [
+ handleFlag: [
{ required: true, message: "璇烽�夋嫨澶勭悊鐘舵��", trigger: "change" },
],
- remark: [
- { required: true, message: "璇疯緭鍏ュ鐞嗗娉�", trigger: "blur" },
+ handleresult: [
{
- min: 5,
- max: 500,
- message: "澶囨敞闀垮害鍦� 5 鍒� 500 涓瓧绗�",
+ 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
+ if (this.$route.query.questionId) {
+ this.filterParams.scriptid = this.$route.query.questionId || null;
+ this.filterParams.scriptids = null;
+ } else if (this.$route.query.questionIds) {
+ this.filterParams.scriptids = this.$route.query.questionIds;
+ 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:
+ getStatusTagType(handleFlag) {
+ switch (handleFlag) {
+ case "0":
+ return "warning"; // 鏈鐞�
+ case "1":
return "success"; // 宸插鐞�
default:
return "info";
@@ -611,16 +701,79 @@
},
// 鑾峰彇鐘舵�佹枃鏈�
- getStatusText(status) {
- switch (status) {
- case 0:
- return "寰呭鐞�";
- case 1:
- return "澶勭悊涓�";
- case 2:
+ 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;
+ }
+
+ 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;
}
},
@@ -633,11 +786,14 @@
// 閲嶇疆绛涢��
handleResetFilter() {
this.filterParams = {
- deptId: "",
- status: "",
+ todeptcode: "",
+ handleFlag: "",
+ templateType: "",
+ scriptid: null, // 淇濈暀闂ID
pageNum: 1,
pageSize: 10,
};
+ this.selectedExceptionIds = [];
this.loadExceptionList();
},
@@ -652,6 +808,15 @@
this.$message.warning("璇峰厛閫夋嫨瑕佸鐞嗙殑寮傚父鍙嶉");
return;
}
+
+ // 閲嶇疆鎵归噺澶勭悊琛ㄥ崟
+ this.batchProcessForm = {
+ handleFlag: "",
+ ccdepts: [],
+ handleresult: "",
+ handledesc: "",
+ };
+
this.batchDialogVisible = true;
},
@@ -663,44 +828,84 @@
// 鏌ョ湅璇︽儏
handleViewDetail(row) {
this.selectedRecordId = row.id;
- this.detailDialogTitle = `${row.patientName} - 寮傚父鍙嶉璇︽儏`;
+ this.selectedRecordData = row;
+
+ // 鐢熸垚寮规鏍囬
+ let title = "寮傚父鍙嶉璇︽儏";
+ if (row.patdesc) {
+ const patientName = row.patdesc.split("|")[0];
+ 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,
+ // 灏嗘暟缁勮浆鎹负閫楀彿鍒嗛殧鐨勫瓧绗︿覆
+ 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;
}
});
},
@@ -708,21 +913,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.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
);
- this.batchDialogVisible = false;
- this.selectedExceptionIds = [];
- this.loadExceptionList();
- } finally {
- this.batchProcessing = false;
+
+ // 骞跺彂澶勭悊褰撳墠鎵规
+ 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;
}
});
},
@@ -738,27 +1033,6 @@
handlePageChange(page) {
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
- } 涓枃浠禶
- );
},
},
};
@@ -827,37 +1101,78 @@
}
.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: space-between;
+ 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;
@@ -866,25 +1181,29 @@
padding: 2px 0;
.label {
- font-size: 12px;
color: #606266;
min-width: 50px;
}
.value {
- font-size: 13px;
color: #333;
font-weight: 500;
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 {
diff --git a/src/views/Satisfaction/configurationmyd/components/DetailsAnomaly.vue b/src/views/Satisfaction/configurationmyd/components/DetailsAnomaly.vue
index 57b4dff..d25ddf7 100644
--- a/src/views/Satisfaction/configurationmyd/components/DetailsAnomaly.vue
+++ b/src/views/Satisfaction/configurationmyd/components/DetailsAnomaly.vue
@@ -13,147 +13,286 @@
<el-row :gutter="20">
<el-col :span="8">
<div class="info-item">
- <span class="label">鎮h�呭鍚嶏細</span>
- <span class="value">{{ currentRecord.patientName }}</span>
+ <span class="label">闂鍐呭锛�</span>
+ <span class="value">{{ currentRecord.questiontext || '鏃�' }}</span>
</div>
</el-col>
<el-col :span="8">
<div class="info-item">
- <span class="label">鎬у埆锛�</span>
- <span class="value">{{ currentRecord.gender === 1 ? '鐢�' : '濂�' }}</span>
+ <span class="label">鍥炵瓟鍐呭锛�</span>
+ <span class="value">{{ currentRecord.asrtext || '鏃犲洖绛�' }}</span>
</div>
</el-col>
<el-col :span="8">
<div class="info-item">
- <span class="label">骞撮緞锛�</span>
- <span class="value">{{ currentRecord.age }}宀�</span>
- </div>
- </el-col>
- <el-col :span="8">
- <div class="info-item">
- <span class="label">鑱旂郴鏂瑰紡锛�</span>
- <span class="value">{{ currentRecord.phone }}</span>
- </div>
- </el-col>
- <el-col :span="8">
- <div class="info-item">
- <span class="label">鍑洪櫌绉戝锛�</span>
- <span class="value">{{ currentRecord.dischargeDept }}</span>
- </div>
- </el-col>
- <el-col :span="8">
- <div class="info-item">
- <span class="label">鍑洪櫌鐥呭尯锛�</span>
- <span class="value">{{ currentRecord.dischargeWard }}</span>
- </div>
- </el-col>
- <el-col :span="8">
- <div class="info-item">
- <span class="label">濉啓鏃堕棿锛�</span>
- <span class="value">{{ currentRecord.fillTime }}</span>
+ <span class="label">瑙f瀽鍊硷細</span>
+ <span class="value">{{ currentRecord.matchedtext || '鏃�' }}</span>
</div>
</el-col>
<el-col :span="8">
<div class="info-item">
<span class="label">璐熻矗绉戝锛�</span>
- <el-tag type="primary">{{ currentRecord.responsibilityDept }}</el-tag>
+ <el-tag v-if="currentRecord.todeptname" type="primary">{{ currentRecord.todeptname }}</el-tag>
+ <span v-else class="value">鏈垎閰�</span>
</div>
</el-col>
<el-col :span="8">
<div class="info-item">
<span class="label">澶勭悊鐘舵�侊細</span>
<el-tag
- :type="getStatusTagType(currentRecord.processStatus)"
+ :type="getStatusTagType(currentRecord.handleFlag)"
effect="dark"
>
- {{ getStatusText(currentRecord.processStatus) }}
+ {{ getStatusText(currentRecord.handleFlag) }}
</el-tag>
+ </div>
+ </el-col>
+ <el-col :span="8">
+ <div class="info-item">
+ <span class="label">妯℃澘绫诲瀷锛�</span>
+ <el-tag :type="currentRecord.templateType === 1 ? 'primary' : 'success'">
+ {{ currentRecord.templateType === 1 ? '璇煶妯℃澘' : '闂嵎妯℃澘' }}
+ </el-tag>
+ </div>
+ </el-col>
+ <el-col :span="8">
+ <div class="info-item">
+ <span class="label">鍒涘缓鏃堕棿锛�</span>
+ <span class="value">{{ formatDateTime(currentRecord.createTime) }}</span>
+ </div>
+ </el-col>
+ <el-col :span="8">
+ <div class="info-item">
+ <span class="label">澶勭悊鏃堕棿锛�</span>
+ <span class="value">{{ currentRecord.handleTime ? formatDateTime(currentRecord.handleTime) : '鏈鐞�' }}</span>
+ </div>
+ </el-col>
+ <el-col :span="8">
+ <div class="info-item">
+ <span class="label">澶勭悊浜猴細</span>
+ <span class="value">{{ currentRecord.handleBy || '鏈鐞�' }}</span>
+ </div>
+ </el-col>
+ <el-col :span="24" v-if="currentRecord.patdesc">
+ <div class="info-item">
+ <span class="label">鎮h�呬俊鎭細</span>
+ <span class="value">{{ currentRecord.patdesc }}</span>
+ </div>
+ </el-col>
+ <el-col :span="8" v-if="currentRecord.handleresult">
+ <div class="info-item">
+ <span class="label">澶勭悊缁撴灉锛�</span>
+ <span class="value">{{ getHandleresultText(currentRecord.handleresult) }}</span>
+ </div>
+ </el-col>
+ <el-col :span="16" v-if="currentRecord.handledesc">
+ <div class="info-item">
+ <span class="label">澶勭悊璇存槑锛�</span>
+ <span class="value">{{ currentRecord.handledesc }}</span>
+ </div>
+ </el-col>
+ <el-col :span="24" v-if="currentRecord.finaloption">
+ <div class="info-item">
+ <span class="label">鏈�缁堟剰瑙侊細</span>
+ <span class="value">{{ currentRecord.finaloption }}</span>
+ </div>
+ </el-col>
+ <el-col :span="8" v-if="currentRecord.recordurl">
+ <div class="info-item">
+ <span class="label">褰曢煶鍦板潃锛�</span>
+ <el-button
+ type="text"
+ size="small"
+ icon="el-icon-headset"
+ @click="handlePlayAudio(currentRecord.recordurl)"
+ >
+ 鎾斁褰曢煶
+ </el-button>
+ </div>
+ </el-col>
+ <el-col :span="8" v-if="currentRecord.ccdepts">
+ <div class="info-item">
+ <span class="label">鎶勯�佺瀹わ細</span>
+ <span class="value">{{ currentRecord.ccdepts }}</span>
</div>
</el-col>
</el-row>
</div>
- <!-- 闂嵎璇︽儏 -->
- <div class="questionnaire-section">
- <div class="section-title">闂嵎濉啓璇︽儏</div>
- <div class="questionnaire-content">
- <div class="question-item" v-for="(question, index) in questionnaireData" :key="index">
- <div class="question-header">
- <span class="question-index">{{ index + 1 }}.</span>
- <span class="question-text">{{ question.question }}</span>
- <el-tag
- size="mini"
- :type="question.type === 1 ? 'primary' : 'success'"
- class="question-type"
- >
- {{ question.type === 1 ? '鍗曢�夐' : '澶氶�夐' }}
- </el-tag>
- </div>
- <div class="question-options">
- <el-radio-group
- v-model="question.answer"
- v-if="question.type === 1"
- disabled
- >
- <el-radio
- v-for="option in question.options"
- :key="option.value"
- :label="option.value"
- :class="{ 'unsatisfactory-option': isUnsatisfactoryOption(option.value) }"
+ <!-- 闂嵎/璇煶璇︽儏 -->
+ <div class="content-container" v-if="templateData.length > 0">
+ <el-tabs v-model="activeName" type="border-card">
+ <!-- 闂嵎闅忚璇︽儏 -->
+ <el-tab-pane name="wj" v-if="currentRecord.templateType === 2">
+ <span slot="label"><i class="el-icon-notebook-1"></i> 闂嵎闅忚璇︽儏</span>
+ <div class="CONTENT">
+ <div class="title">{{ currentRecord.questiontext || '闂嵎璇︽儏' }}</div>
+ <div class="preview-left" v-if="!isVoiceTemplate">
+ <div
+ class="topic-dev"
+ v-for="(item, index) in templateData"
+ :key="item.id"
>
- {{ option.text }}
- </el-radio>
- </el-radio-group>
- <el-checkbox-group
- v-model="question.answer"
- v-else
- disabled
- >
- <el-checkbox
- v-for="option in question.options"
- :key="option.value"
- :label="option.value"
- :class="{ 'unsatisfactory-option': isUnsatisfactoryOption(option.value) }"
- >
- {{ option.text }}
- </el-checkbox>
- </el-checkbox-group>
+ <!-- 鍗曢�� -->
+ <div
+ :class="getTopicClass(item)"
+ :key="index"
+ v-if="item.scriptType == 1 && !item.astrict"
+ >
+ <div class="dev-text">
+ {{ index + 1 }}銆乕鍗曢�塢<span>{{ item.scriptContent }}</span>
+ </div>
+ <div class="dev-xx">
+ <el-radio-group v-model="item.scriptResult" disabled>
+ <el-radio
+ v-for="(option, optionIndex) in item.svyTaskTemplateTargetoptions"
+ :class="getOptionClass(option)"
+ :key="optionIndex"
+ :label="option.optioncontent"
+ >{{ option.optioncontent }}</el-radio>
+ </el-radio-group>
+ </div>
+ <div
+ v-if="item.showAppendInput || item.answerps"
+ class="append-input-container"
+ >
+ <el-input
+ type="textarea"
+ :rows="2"
+ placeholder="璇疯緭鍏ュ叿浣撲俊鎭�"
+ v-model="item.answerps"
+ readonly
+ ></el-input>
+ </div>
+ <div v-show="item.prompt">
+ <el-alert :title="item.prompt" type="warning"></el-alert>
+ </div>
+ </div>
+ <!-- 澶氶�� -->
+ <div
+ :class="item.isabnormal ? 'scriptTopic-isabnormal' : 'scriptTopic-dev'"
+ :key="index"
+ v-if="item.scriptType == 2 && !item.astrict"
+ >
+ <div class="dev-text">
+ {{ index + 1 }}銆乕澶氶�塢<span>{{ item.scriptContent }}</span>
+ </div>
+ <div class="dev-xx">
+ <el-checkbox-group v-model="item.scriptResult" disabled>
+ <el-checkbox
+ :class="option.isabnormal ? 'red-star' : ''"
+ v-for="(option, optionIndex) in item.svyTaskTemplateTargetoptions"
+ :key="optionIndex"
+ :label="option.optioncontent"
+ >
+ {{ option.optioncontent }}
+ </el-checkbox>
+ </el-checkbox-group>
+ </div>
+ <div v-show="item.prompt && item.scriptResult[0]">
+ <el-alert :title="item.prompt" type="warning"></el-alert>
+ </div>
+ </div>
+ <!-- 濉┖ -->
+ <div
+ class="scriptTopic-dev"
+ :key="index"
+ v-if="item.scriptType == 4 && !item.astrict"
+ >
+ <div class="dev-text">
+ {{ index + 1 }}銆乕闂瓟]<span>{{ item.scriptContent }}</span>
+ <span v-if="item.valueType == 3">(鍙兘杈撳叆鏁板瓧)</span>
+ </div>
+ <div class="dev-xx" v-if="item.valueType == 3">
+ <el-input
+ type="text"
+ placeholder="璇疯緭鍏ョ瓟妗�"
+ v-model="item.scriptResult"
+ readonly
+ ></el-input>
+ </div>
+ <div class="dev-xx" v-else>
+ <el-input
+ type="textarea"
+ :rows="2"
+ placeholder="璇疯緭鍏ョ瓟妗�"
+ v-model="item.scriptResult"
+ readonly
+ ></el-input>
+ </div>
+ </div>
+ </div>
+ </div>
</div>
- <div v-if="question.additional" class="additional-remark">
- <div class="remark-label">琛ュ厖璇存槑锛�</div>
- <div class="remark-content">{{ question.additional }}</div>
+ </el-tab-pane>
+
+ <!-- 璇煶闅忚璇︽儏 -->
+ <el-tab-pane name="yy" v-if="currentRecord.templateType === 1">
+ <span slot="label"><i class="el-icon-headset"></i> 璇煶闅忚璇︽儏</span>
+ <div class="borderdiv">
+ <div class="title">{{ taskName }}</div>
+ <div class="voice-audio" v-if="voiceAudioUrl">
+ 瀹屾暣璇煶锛�
+ <audio-player
+ :audio-source="voiceAudioUrl"
+ ></audio-player>
+ </div>
+ <div class="preview-left" v-if="voiceData.length > 0">
+ <div v-for="(item, index) in voiceData" :key="index">
+ <div class="leftside">
+ <i class="el-icon-phone-outline"></i>
+ <span>{{ item.questiontext || '闂鍐呭' }}</span>
+ </div>
+ <div class="offside">
+ <i class="el-icon-user"></i>
+ <div class="offside-value">
+ <el-input
+ type="textarea"
+ :autosize="{ minRows: 1 }"
+ v-model="item.asrtext"
+ readonly
+ ></el-input>
+ <div v-if="item.questionvoice">
+ <audio-player
+ :audio-source="item.questionvoice"
+ ></audio-player>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
</div>
- </div>
- </div>
+ </el-tab-pane>
+ </el-tabs>
</div>
<!-- 澶勭悊璁板綍 -->
- <div class="process-section">
+ <div class="process-section" v-if="processRecords.length > 0">
<div class="section-title">澶勭悊璁板綍</div>
- <div class="process-timeline" v-if="processRecords.length > 0">
+ <div class="process-timeline">
<el-timeline>
<el-timeline-item
v-for="(record, index) in processRecords"
:key="index"
- :timestamp="record.time"
+ :timestamp="formatDateTime(record.handleTime || record.createTime)"
placement="top"
>
<el-card>
<div class="process-item">
<div class="process-header">
- <span class="process-user">{{ record.user }}</span>
+ <span class="process-user">{{ record.handleBy || '绯荤粺' }}</span>
<el-tag
size="small"
- :type="getStatusTagType(record.status)"
+ :type="getStatusTagType(record.handleFlag)"
>
- {{ getStatusText(record.status) }}
+ {{ getStatusText(record.handleFlag) }}
</el-tag>
</div>
<div class="process-content">
- <div v-if="record.reportDepts && record.reportDepts.length > 0" class="process-depts">
- <span class="label">鎶ュ绉戝锛�</span>
+ <div v-if="record.ccdepts" class="process-depts">
+ <span class="label">鎶勯�佺瀹わ細</span>
<el-tag
- v-for="dept in record.reportDepts"
+ v-for="dept in getDeptArray(record.ccdepts)"
:key="dept"
size="small"
type="info"
@@ -162,31 +301,23 @@
{{ dept }}
</el-tag>
</div>
- <div v-if="record.remark" class="process-remark">
- <span class="label">澶勭悊澶囨敞锛�</span>
- <span class="content">{{ record.remark }}</span>
+ <div v-if="record.handleresult" class="process-remark">
+ <span class="label">澶勭悊缁撴灉锛�</span>
+ <span class="content">{{ getHandleresultText(record.handleresult) }}</span>
</div>
- <div v-if="record.attachments && record.attachments.length > 0" class="process-attachments">
- <span class="label">闄勪欢锛�</span>
- <el-button
- v-for="file in record.attachments"
- :key="file.id"
- type="text"
- size="small"
- icon="el-icon-document"
- @click="handlePreviewFile(file)"
- >
- {{ file.name }}
- </el-button>
+ <div v-if="record.handledesc" class="process-remark">
+ <span class="label">澶勭悊璇存槑锛�</span>
+ <span class="content">{{ record.handledesc }}</span>
+ </div>
+ <div v-if="record.finaloption" class="process-remark">
+ <span class="label">鏈�缁堟剰瑙侊細</span>
+ <span class="content">{{ record.finaloption }}</span>
</div>
</div>
</div>
</el-card>
</el-timeline-item>
</el-timeline>
- </div>
- <div v-else class="no-record">
- 鏆傛棤澶勭悊璁板綍
</div>
</div>
@@ -195,7 +326,7 @@
type="primary"
icon="el-icon-edit"
@click="handleProcess"
- v-if="currentRecord.processStatus !== 2"
+ v-if="currentRecord.handleFlag !== '1'"
>
澶勭悊寮傚父
</el-button>
@@ -217,61 +348,72 @@
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"
- placeholder="璇烽�夋嫨鎶ュ绉戝"
+ 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="handleFilePreview"
- :on-remove="handleFileRemove"
- :before-remove="beforeFileRemove"
- :limit="3"
- :on-exceed="handleFileExceed"
- :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">
@@ -285,24 +427,42 @@
</el-button>
</span>
</el-dialog>
+
+ <!-- 褰曢煶鎾斁鍣� -->
+ <audio
+ v-if="audioUrl"
+ :src="audioUrl"
+ ref="audioPlayer"
+ controls
+ style="display: none"
+ />
</el-dialog>
</template>
<script>
+import { traceedit } from "@/api/AiCentre/index";
+import { getsearchrResults, getPersonVoices, getTaskservelist } from "@/api/AiCentre/index";
+import { deptTreeSelect } from "@/api/system/user";
+import AudioPlayer from "@/components/AudioPlayer"; // 闇�瑕佸垱寤鸿繖涓煶棰戞挱鏀剧粍浠�
+
export default {
name: 'ExceptionDetailDialog',
+ components: {
+ AudioPlayer
+ },
props: {
- // 鏄惁鏄剧ず瀵硅瘽妗�
visible: {
type: Boolean,
default: false
},
- // 璁板綍ID
recordId: {
type: [Number, String],
default: null
},
- // 瀵硅瘽妗嗘爣棰�
+ recordData: {
+ type: Object,
+ default: () => ({})
+ },
title: {
type: String,
default: '寮傚父鍙嶉璇︽儏'
@@ -313,45 +473,71 @@
// 褰撳墠璁板綍
currentRecord: {},
- // 闂嵎鏁版嵁
- questionnaireData: [],
+ // 闂嵎/璇煶鏁版嵁
+ activeName: 'wj',
+ taskName: '',
+ templateData: [],
+ voiceData: [],
+ voiceAudioUrl: '',
// 澶勭悊璁板綍
processRecords: [],
// 绉戝鍒楄〃
- 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: '鍛煎惛鍐呯' }
- ],
+ deptList: [],
// 澶勭悊瀵硅瘽妗�
processDialogVisible: false,
processing: false,
processForm: {
- status: '',
- reportDepts: [],
- remark: ''
+ handleFlag: '',
+ ccdepts: [],
+ handleresult: '',
+ handledesc: '',
+ finaloption: ''
},
processRules: {
- status: [
+ 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: [],
+
+ // 闊抽鎾斁
+ audioUrl: '',
// 鍔犺浇鐘舵��
- loading: false
+ loading: false,
+
+ // 鏉冮檺鎺у埗
+ hasQualityPermission: false
};
},
@@ -363,6 +549,10 @@
set(val) {
this.$emit('update:visible', val);
}
+ },
+
+ isVoiceTemplate() {
+ return this.currentRecord.templateType === 1;
}
},
@@ -370,237 +560,293 @@
visible: {
immediate: true,
handler(val) {
- if (val && this.recordId) {
+ if (val) {
this.loadData();
+ } else {
+ this.resetData();
+ }
+ }
+ },
+
+ recordData: {
+ immediate: true,
+ handler(val) {
+ if (val && Object.keys(val).length > 0) {
+ this.currentRecord = { ...val };
}
}
}
},
methods: {
- // 鍔犺浇鏁版嵁
- async loadData() {
- this.loading = true;
+ // 鏍煎紡鍖栨棩鏈熸椂闂�
+ formatDateTime(dateTime) {
+ if (!dateTime) return '';
try {
- await Promise.all([
- this.loadRecordDetail(),
- this.loadQuestionnaireData(),
- this.loadProcessRecords()
- ]);
- } finally {
- this.loading = false;
+ 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;
}
},
- // 鍔犺浇璁板綍璇︽儏
- async loadRecordDetail() {
- return new Promise(resolve => {
- setTimeout(() => {
- // 鏍规嵁涓嶅悓鐨剅ecordId杩斿洖涓嶅悓鐨刴ock鏁版嵁
- const mockRecords = {
- 1: {
- id: 1,
- patientName: '寮犲厛鐢�',
- gender: 1,
- age: 45,
- phone: '13800138000',
- dischargeDept: '蹇冭绠″唴绉�',
- dischargeWard: '鍐呯涓�鐥呭尯',
- fillTime: '2024-01-15 10:30:25',
- responsibilityDept: '蹇冭绠″唴绉�',
- processStatus: 0
- },
- 2: {
- id: 2,
- patientName: '鏉庡コ澹�',
- gender: 0,
- age: 38,
- phone: '13900139000',
- dischargeDept: '绁炵粡鍐呯',
- dischargeWard: '鍐呯浜岀梾鍖�',
- fillTime: '2024-01-14 16:20:10',
- responsibilityDept: '绁炵粡鍐呯',
- processStatus: 0
- },
- 3: {
- id: 3,
- patientName: '鐜嬪厛鐢�',
- gender: 1,
- age: 52,
- phone: '13700137000',
- dischargeDept: '鏅绉�',
- dischargeWard: '澶栫涓�鐥呭尯',
- fillTime: '2024-01-13 09:15:45',
- responsibilityDept: '鏅绉�',
- processStatus: 1
- }
- };
-
- this.currentRecord = mockRecords[this.recordId] || {
- id: 1,
- patientName: '寮犲厛鐢�',
- gender: 1,
- age: 45,
- phone: '13800138000',
- dischargeDept: '蹇冭绠″唴绉�',
- dischargeWard: '鍐呯涓�鐥呭尯',
- fillTime: '2024-01-15 10:30:25',
- responsibilityDept: '蹇冭绠″唴绉�',
- processStatus: 0
- };
- resolve();
- }, 300);
- });
+ // 妫�鏌ヨ川绠℃潈闄�
+ checkQualityPermission() {
+ const userRoles = this.$store.getters.roles || [];
+ return userRoles.includes('quality_manager') || userRoles.includes('admin');
},
- // 鍔犺浇闂嵎鏁版嵁
- async loadQuestionnaireData() {
- return new Promise(resolve => {
- setTimeout(() => {
- this.questionnaireData = [
- {
- question: '鎮ㄥ鍖绘姢浜哄憳鐨勬湇鍔℃�佸害鏄惁婊℃剰锛�',
- type: 1,
- options: [
- { value: '闈炲父婊℃剰', text: '闈炲父婊℃剰' },
- { value: '婊℃剰', text: '婊℃剰' },
- { value: '涓�鑸�', text: '涓�鑸�' },
- { value: '涓嶆弧鎰�', text: '涓嶆弧鎰�' },
- { value: '闈炲父涓嶆弧鎰�', text: '闈炲父涓嶆弧鎰�' }
- ],
- answer: '涓嶆弧鎰�',
- additional: '鍖荤敓鏌ユ埧鏃堕棿澶煭锛屾矡閫氫笉澶熷厖鍒嗭紝瀵圭梾鎯呰В閲婁笉澶熻缁�'
- },
- {
- question: '鎮ㄥ鍖荤敓鐨勮瘖鐤楁按骞冲拰鎶�鏈兘鍔涜瘎浠峰浣曪紵',
- type: 1,
- options: [
- { value: '闈炲父涓撲笟', text: '闈炲父涓撲笟' },
- { value: '姣旇緝涓撲笟', text: '姣旇緝涓撲笟' },
- { value: '涓�鑸�', text: '涓�鑸�' },
- { value: '涓嶅涓撲笟', text: '涓嶅涓撲笟' },
- { value: '闈炲父涓嶄笓涓�', text: '闈炲父涓嶄笓涓�' }
- ],
- answer: '姣旇緝涓撲笟',
- additional: ''
- },
- {
- question: '鎮ㄥ鍖婚櫌鐨勭幆澧冨拰鍗敓鐘跺喌鏄惁婊℃剰锛�',
- type: 1,
- options: [
- { value: '闈炲父婊℃剰', text: '闈炲父婊℃剰' },
- { value: '婊℃剰', text: '婊℃剰' },
- { value: '涓�鑸�', text: '涓�鑸�' },
- { value: '涓嶆弧鎰�', text: '涓嶆弧鎰�' },
- { value: '闈炲父涓嶆弧鎰�', text: '闈炲父涓嶆弧鎰�' }
- ],
- answer: '涓�鑸�',
- additional: ''
- },
- {
- question: '鎮ㄨ涓哄尰鎶や汉鍛樹笌鎮ㄧ殑娌熼�氭槸鍚﹀厖鍒嗭紵',
- type: 1,
- options: [
- { value: '闈炲父鍏呭垎', text: '闈炲父鍏呭垎' },
- { value: '姣旇緝鍏呭垎', text: '姣旇緝鍏呭垎' },
- { value: '涓�鑸�', text: '涓�鑸�' },
- { value: '涓嶅鍏呭垎', text: '涓嶅鍏呭垎' },
- { value: '闈炲父涓嶅厖鍒�', text: '闈炲父涓嶅厖鍒�' }
- ],
- answer: '涓嶅鍏呭垎',
- additional: '鍖荤敓璁茶В鐥呮儏鏃惰閫熷お蹇紝娌℃湁缁欒冻澶熺殑鏃堕棿鎻愰棶'
- },
- {
- question: '鎮ㄥ绛夊緟灏辫瘖鍜屾不鐤楃殑鏃堕棿鏄惁婊℃剰锛�',
- type: 1,
- options: [
- { value: '闈炲父婊℃剰', text: '闈炲父婊℃剰' },
- { value: '婊℃剰', text: '婊℃剰' },
- { value: '涓�鑸�', text: '涓�鑸�' },
- { value: '涓嶆弧鎰�', text: '涓嶆弧鎰�' },
- { value: '闈炲父涓嶆弧鎰�', text: '闈炲父涓嶆弧鎰�' }
- ],
- answer: '涓嶆弧鎰�',
- additional: '棰勭害鐨�9鐐癸紝瀹為檯10鐐规墠瑙佸埌鍖荤敓'
- }
- ];
- resolve();
- }, 300);
- });
+ // 鑾峰彇绉戝鍒楄〃
+ async getDeptOptions() {
+ try {
+ const res = await deptTreeSelect();
+ if (res.code == 200) {
+ this.deptList = this.flattenArray(res.data) || [];
+ }
+ } catch (error) {
+ console.error('鑾峰彇绉戝鍒楄〃澶辫触:', error);
+ }
},
- // 鍔犺浇澶勭悊璁板綍
- async loadProcessRecords() {
- return new Promise(resolve => {
- setTimeout(() => {
- this.processRecords = [
- {
- id: 1,
- time: '2024-01-15 14:20:30',
- user: '寮犲尰鐢�',
- status: 1, // 澶勭悊涓�
- reportDepts: ['鍖诲姟绉�', '鎶ょ悊閮�'],
- remark: '宸叉敹鍒板弽棣堬紝姝e湪瀹夋帓鐩稿叧浜哄憳鏍告煡鎯呭喌',
- attachments: [
- { id: 1, name: '鍒濇璋冩煡璁板綍.docx' },
- { id: 2, name: '鎮h�呮矡閫氳褰�.jpg' }
- ]
- },
- {
- id: 2,
- time: '2024-01-15 10:45:12',
- user: '绯荤粺',
- status: 0, // 寰呭鐞�
- remark: '绯荤粺鑷姩璇嗗埆涓哄紓甯稿弽棣堬紝宸插垎閰嶅埌璐d换绉戝',
- attachments: []
- }
- ];
- resolve();
- }, 300);
- });
- },
+ // 灞曞钩鏁扮粍
+ flattenArray(multiArray) {
+ let result = [];
- // 鍒ゆ柇鏄惁涓轰笉婊℃剰閫夐」
- isUnsatisfactoryOption(value) {
- const unsatisfactoryValues = [
- '涓嶆弧鎰�',
- '闈炲父涓嶆弧鎰�',
- '涓嶅涓撲笟',
- '闈炲父涓嶄笓涓�',
- '涓嶅鍏呭垎',
- '闈炲父涓嶅厖鍒�'
- ];
- return unsatisfactoryValues.includes(value);
+ 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;
},
// 鑾峰彇鐘舵�佹爣绛剧被鍨�
- getStatusTagType(status) {
- switch (status) {
- case 0: return 'warning'; // 寰呭鐞�
- case 1: return 'primary'; // 澶勭悊涓�
- case 2: return 'success'; // 宸插鐞�
- case 3: return 'danger'; // 宸查┏鍥�
+ 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 '宸插鐞�';
- case 3: return '宸查┏鍥�';
+ getStatusText(handleFlag) {
+ switch (handleFlag) {
+ case '0': return '鏈鐞�';
+ case '1': return '宸插鐞�';
default: return '鏈煡';
+ }
+ },
+
+ // 鑾峰彇澶勭悊缁撴灉鏂囨湰
+ getHandleresultText(handleresult) {
+ const map = {
+ 'resolved': '宸茶В鍐�',
+ 'explained': '宸茶В閲�',
+ 'transferred': '宸茶浆浜�',
+ 'improvement': '闇�鏀硅繘',
+ 'rejected': '宸查┏鍥�'
+ };
+ return map[handleresult] || handleresult;
+ },
+
+ // 鑾峰彇绉戝鏁扮粍
+ getDeptArray(ccdepts) {
+ if (!ccdepts) return [];
+ return ccdepts.split(',');
+ },
+
+ // 鎾斁闊抽
+ handlePlayAudio(url) {
+ this.audioUrl = url;
+ this.$nextTick(() => {
+ const audioPlayer = this.$refs.audioPlayer;
+ if (audioPlayer) {
+ audioPlayer.play().catch(error => {
+ console.error('鎾斁澶辫触:', error);
+ this.$message.error('闊抽鎾斁澶辫触');
+ });
+ }
+ });
+ },
+
+ // 鑾峰彇涓婚鏍峰紡绫�
+ getTopicClass(item) {
+ if (item.isabnormal == 1) {
+ return "scriptTopic-isabnormal";
+ } else if (item.isabnormal == 2) {
+ return "scriptTopic-warning";
+ } else {
+ return "scriptTopic-dev";
+ }
+ },
+
+ // 鑾峰彇閫夐」鏍峰紡绫�
+ getOptionClass(items) {
+ if (items.isabnormal == 1) {
+ return "red-star";
+ } else if (items.isabnormal == 2) {
+ return "yellow-star";
+ }
+ return "";
+ },
+
+ // 鍔犺浇鏁版嵁
+ async loadData() {
+ this.loading = true;
+ try {
+ this.hasQualityPermission = this.checkQualityPermission();
+ await this.getDeptOptions();
+
+ if (Object.keys(this.currentRecord).length === 0) {
+ this.currentRecord = this.recordData || {};
+ }
+
+ // 濡傛灉褰撳墠璁板綍鏄闊虫ā鏉匡紝鍔犺浇璇煶鏁版嵁
+ if (this.currentRecord.templateType === 1) {
+ await this.loadVoiceData();
+ this.activeName = 'yy';
+ } else if (this.currentRecord.templateType === 2) {
+ await this.loadQuestionnaireData();
+ this.activeName = 'wj';
+ }
+
+ await this.loadProcessRecords();
+ } catch (error) {
+ console.error('鍔犺浇璇︽儏鏁版嵁澶辫触:', error);
+ this.$message.error('鍔犺浇鏁版嵁澶辫触');
+ } finally {
+ this.loading = false;
+ }
+ },
+
+ // 閲嶇疆鏁版嵁
+ resetData() {
+ this.currentRecord = {};
+ this.templateData = [];
+ this.voiceData = [];
+ this.processRecords = [];
+ this.voiceAudioUrl = '';
+ this.taskName = '';
+ this.activeName = 'wj';
+ },
+
+ // 鍔犺浇闂嵎鏁版嵁
+ async loadQuestionnaireData() {
+ try {
+ // 杩欓噷闇�瑕佹牴鎹疄闄呮儏鍐佃皟鐢ㄦ帴鍙h幏鍙栭棶鍗锋暟鎹�
+ // 濡傛灉recordData涓凡缁忓寘鍚簡闂嵎鏁版嵁锛屽彲浠ョ洿鎺ヤ娇鐢�
+ if (this.currentRecord.taskid && this.currentRecord.patid) {
+ const params = {
+ taskid: this.currentRecord.taskid,
+ patid: this.currentRecord.patid,
+ subId: this.currentRecord.subId || this.currentRecord.id,
+ isFinish: true
+ };
+
+ const res = await getsearchrResults(params);
+ if (res.code === 200 && res.data) {
+ this.templateData = res.data.scriptResult || [];
+ this.taskName = res.data.taskName || '';
+
+ // 澶勭悊鏁版嵁鏍煎紡
+ this.templateData.forEach((item) => {
+ if (item.scriptType == 2) item.scriptResult = [];
+ if (item.scriptResultId && item.scriptType != 2) {
+ item.isoption = 3;
+ item.scriptResult = item.scriptResult;
+ } else if (item.scriptResultId && item.scriptType == 2) {
+ item.scriptResult = item.scriptResult.split("&");
+ item.isoption = 3;
+ }
+ });
+
+ this.overdata();
+ }
+ }
+ } catch (error) {
+ console.error('鍔犺浇闂嵎鏁版嵁澶辫触:', error);
+ }
+ },
+
+ // 澶勭悊寮傚父鏁版嵁
+ overdata() {
+ this.templateData.forEach((item, index) => {
+ var obj = item.svyTaskTemplateTargetoptions.find(
+ (items) => items.optioncontent == item.scriptResult
+ );
+ if (obj && obj.isabnormal) {
+ this.templateData[index].isabnormal = obj.isabnormal;
+ }
+ this.$forceUpdate();
+ });
+ },
+
+ // 鍔犺浇璇煶鏁版嵁
+ async loadVoiceData() {
+ try {
+ if (this.currentRecord.taskid && this.currentRecord.patid) {
+ const params = {
+ taskid: this.currentRecord.taskid,
+ patid: this.currentRecord.patid,
+ subId: this.currentRecord.subId || this.currentRecord.id
+ };
+
+ const res = await getPersonVoices(params);
+ if (res.code == 200) {
+ this.voiceData = res.data.serviceSubtaskDetails || [];
+ this.voiceAudioUrl = res.data.voice || '';
+ this.taskName = res.data.taskName || '';
+ this.templateData = res.data.filteredDetails || [];
+
+ this.templateData.forEach((item) => {
+ if (item.targetvalue) {
+ item.scriptResult = item.targetvalue.split("&");
+ } else {
+ item.scriptResult = [];
+ }
+ });
+ }
+ }
+ } catch (error) {
+ console.error('鍔犺浇璇煶鏁版嵁澶辫触:', error);
+ }
+ },
+
+ // 鍔犺浇澶勭悊璁板綍
+ async loadProcessRecords() {
+ try {
+ // 杩欓噷鍙互鏍规嵁recordId鍔犺浇澶勭悊鍘嗗彶
+ // 鏆傛椂浣跨敤褰撳墠璁板綍鐨勫鐞嗕俊鎭�
+ if (this.currentRecord.handleTime) {
+ this.processRecords = [{
+ ...this.currentRecord,
+ time: this.currentRecord.handleTime
+ }];
+ }
+ } catch (error) {
+ console.error('鍔犺浇澶勭悊璁板綍澶辫触:', error);
}
},
// 澶勭悊寮傚父
handleProcess() {
this.processForm = {
- status: this.currentRecord.processStatus === 0 ? 1 : this.currentRecord.processStatus,
- reportDepts: [],
- remark: ''
+ handleFlag: this.currentRecord.handleFlag === '0' ? '1' : '0',
+ ccdepts: this.currentRecord.ccdepts ? this.currentRecord.ccdepts.split(',') : [],
+ handleresult: this.currentRecord.handleresult || '',
+ handledesc: this.currentRecord.handledesc || '',
+ finaloption: this.currentRecord.finaloption || ''
};
this.processDialogVisible = true;
},
@@ -608,52 +854,56 @@
// 鎻愪氦澶勭悊
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.processing = true;
+ try {
+ const submitData = {
+ id: this.currentRecord.id,
+ handleFlag: this.processForm.handleFlag,
+ handleresult: this.processForm.handleresult,
+ handledesc: this.processForm.handledesc,
+ finaloption: this.processForm.finaloption,
+ ccdepts: Array.isArray(this.processForm.ccdepts)
+ ? this.processForm.ccdepts.join(",")
+ : this.processForm.ccdepts
+ };
+
+ const res = await traceedit(submitData);
+ if (res.code === 200) {
+ this.$message.success("澶勭悊鎻愪氦鎴愬姛");
this.processDialogVisible = false;
- // 閲嶆柊鍔犺浇鏁版嵁
- await this.loadData();
+ // 鏇存柊褰撳墠璁板綍
+ this.currentRecord = {
+ ...this.currentRecord,
+ ...submitData,
+ handleBy: this.$store.getters.name, // 褰撳墠鐢ㄦ埛
+ handleTime: new Date().toISOString().replace('T', ' ').substr(0, 19)
+ };
+
+ // 閲嶆柊鍔犺浇澶勭悊璁板綍
+ await this.loadProcessRecords();
// 瑙﹀彂鐖剁粍浠跺埛鏂�
this.$emit('processed');
- } finally {
- this.processing = false;
+ } else {
+ this.$message.error(res.msg || "澶勭悊鎻愪氦澶辫触");
}
+ } catch (error) {
+ console.error("澶勭悊鎻愪氦澶辫触:", error);
+ this.$message.error("澶勭悊鎻愪氦澶辫触锛岃绋嶅悗閲嶈瘯");
+ } finally {
+ this.processing = false;
}
});
- },
-
- // 棰勮鏂囦欢
- handlePreviewFile(file) {
- this.$message.info(`棰勮鏂囦欢: ${file.name}`);
},
// 澶勭悊瀵硅瘽妗嗗叧闂�
handleClose() {
this.$emit('close');
- },
-
- // 鏂囦欢涓婁紶鐩稿叧鏂规硶
- handleFilePreview(file) {
- console.log('棰勮鏂囦欢:', file);
- },
-
- handleFileRemove(file, fileList) {
- console.log('绉婚櫎鏂囦欢:', file, fileList);
- },
-
- beforeFileRemove(file) {
- return this.$confirm(`纭畾绉婚櫎 ${file.name}锛焋);
- },
-
- handleFileExceed(files, fileList) {
- this.$message.warning(`褰撳墠闄愬埗閫夋嫨 3 涓枃浠讹紝鏈閫夋嫨浜� ${files.length} 涓枃浠讹紝鍏遍�夋嫨浜� ${files.length + fileList.length} 涓枃浠禶);
}
}
};
@@ -705,116 +955,137 @@
font-size: 14px;
color: #303133;
font-weight: 500;
+ flex: 1;
}
}
}
- .questionnaire-section {
+ .content-container {
margin-bottom: 20px;
- padding: 20px;
- background: #fff;
- border-radius: 8px;
- border: 1px solid #ebeef5;
- .section-title {
- font-size: 16px;
- font-weight: 600;
- color: #303133;
- margin-bottom: 15px;
- padding-bottom: 10px;
- border-bottom: 2px solid #409EFF;
+ ::v-deep .el-tabs__content {
+ padding: 20px;
+ background: #fff;
+ border-radius: 0 0 4px 4px;
}
- .questionnaire-content {
- .question-item {
- margin-bottom: 20px;
- padding: 15px;
- border-radius: 6px;
- border: 1px solid #ebeef5;
- transition: all 0.3s;
+ .CONTENT, .borderdiv {
+ padding: 20px;
+ background: #fff;
+ border-radius: 6px;
- &:hover {
- border-color: #409EFF;
- box-shadow: 0 2px 12px 0 rgba(64, 158, 255, 0.1);
+ .title {
+ font-size: 18px;
+ font-weight: 600;
+ color: #303133;
+ margin-bottom: 20px;
+ padding-bottom: 10px;
+ border-bottom: 2px solid #409EFF;
+ }
+
+ .voice-audio {
+ margin-bottom: 20px;
+ display: flex;
+ align-items: center;
+ gap: 10px;
+
+ .audio-player {
+ flex: 1;
+ }
+ }
+
+ .preview-left {
+ .topic-dev {
+ margin-bottom: 20px;
+ padding: 15px;
+ border-radius: 6px;
+ border: 1px solid #ebeef5;
+ background: #fff;
+
+ .dev-text {
+ font-size: 15px;
+ font-weight: 500;
+ color: #303133;
+ margin-bottom: 15px;
+ line-height: 1.5;
+
+ span {
+ color: #606266;
+ }
+ }
+
+ .dev-xx {
+ ::v-deep .el-radio-group,
+ ::v-deep .el-checkbox-group {
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
+ }
+
+ ::v-deep .el-radio,
+ ::v-deep .el-checkbox {
+ margin: 0;
+ padding: 8px 12px;
+ border-radius: 4px;
+ border: 1px solid #ebeef5;
+ transition: all 0.3s;
+
+ &:hover {
+ background: #f5f7fa;
+ }
+
+ &.red-star {
+ border-color: #f56c6c;
+ background: #fef0f0;
+ }
+
+ &.yellow-star {
+ border-color: #e6a23c;
+ background: #fdf6ec;
+ }
+ }
+ }
+
+ .append-input-container {
+ margin-top: 15px;
+ }
+
+ .el-alert {
+ margin-top: 10px;
+ }
}
- .question-header {
+ .leftside {
display: flex;
align-items: center;
- margin-bottom: 15px;
- padding-bottom: 10px;
- border-bottom: 1px dashed #dcdfe6;
+ gap: 10px;
+ margin-bottom: 10px;
+ font-size: 15px;
+ font-weight: 500;
+ color: #303133;
- .question-index {
- font-weight: 600;
+ i {
color: #409EFF;
- margin-right: 8px;
- font-size: 15px;
+ }
+ }
+
+ .offside {
+ display: flex;
+ align-items: flex-start;
+ gap: 10px;
+ margin-bottom: 20px;
+
+ i {
+ color: #67C23A;
+ margin-top: 8px;
}
- .question-text {
+ .offside-value {
flex: 1;
- font-size: 15px;
- color: #303133;
- font-weight: 500;
- line-height: 1.5;
- }
- .question-type {
- margin-left: 10px;
- }
- }
-
- .question-options {
- ::v-deep .el-radio-group {
- display: flex;
- flex-direction: column;
- gap: 10px;
- }
-
- ::v-deep .el-checkbox-group {
- display: flex;
- flex-wrap: wrap;
- gap: 15px;
- }
-
- ::v-deep .el-radio,
- ::v-deep .el-checkbox {
- margin: 0;
- padding: 8px 12px;
- border-radius: 4px;
- border: 1px solid #ebeef5;
- transition: all 0.3s;
-
- &:hover {
- background: #f5f7fa;
+ .el-textarea {
+ margin-bottom: 10px;
}
-
- &.unsatisfactory-option {
- border-color: #e6a23c;
- background: #fdf6ec;
- }
- }
- }
-
- .additional-remark {
- margin-top: 15px;
- padding: 12px;
- background: #f0f9ff;
- border-radius: 6px;
- border-left: 4px solid #409EFF;
-
- .remark-label {
- font-size: 13px;
- color: #606266;
- font-weight: 500;
- margin-bottom: 5px;
- }
-
- .remark-content {
- font-size: 14px;
- color: #303133;
- line-height: 1.6;
}
}
}
@@ -886,30 +1157,8 @@
line-height: 1.5;
}
}
-
- .process-attachments {
- .label {
- font-size: 13px;
- color: #606266;
- margin-right: 5px;
- }
-
- ::v-deep .el-button {
- margin-right: 8px;
- margin-bottom: 5px;
- }
- }
}
}
- }
-
- .no-record {
- text-align: center;
- padding: 40px 0;
- color: #909399;
- font-style: italic;
- background: #f8f9fa;
- border-radius: 6px;
}
}
@@ -920,4 +1169,15 @@
gap: 10px;
}
}
+
+// 寮傚父鏍峰紡
+.scriptTopic-isabnormal {
+ border-color: #f56c6c !important;
+ background: #fef0f0 !important;
+}
+
+.scriptTopic-warning {
+ border-color: #e6a23c !important;
+ background: #fdf6ec !important;
+}
</style>
diff --git a/src/views/Satisfaction/configurationmyd/dispose.vue b/src/views/Satisfaction/configurationmyd/dispose.vue
index 8a59106..8de73b1 100644
--- a/src/views/Satisfaction/configurationmyd/dispose.vue
+++ b/src/views/Satisfaction/configurationmyd/dispose.vue
@@ -19,9 +19,9 @@
label-width="120px"
class="search-form"
>
- <el-form-item label="婊℃剰搴︽ā鏉�" prop="templateId">
+ <el-form-item label="婊℃剰搴︾被鍨�" prop="templateid">
<el-select
- v-model="queryParams.templateId"
+ v-model="queryParams.templateid"
placeholder="璇烽�夋嫨妯℃澘"
clearable
style="width: 200px"
@@ -35,9 +35,9 @@
</el-select>
</el-form-item>
- <el-form-item label="璐d换绉戝" prop="deptIds">
+ <el-form-item label="璐d换绉戝" prop="todeptcode">
<el-select
- v-model="queryParams.deptIds"
+ v-model="queryParams.todeptcode"
placeholder="璇烽�夋嫨璐d换绉戝"
clearable
filterable
@@ -47,21 +47,21 @@
>
<el-option
v-for="dept in deptList"
- :key="dept.id"
- :label="dept.name"
- :value="dept.id"
+ :key="dept.deptCode"
+ :label="dept.deptName"
+ :value="dept.deptCode"
/>
</el-select>
</el-form-item>
- <el-form-item label="缁熻鏃堕棿" prop="dateRange">
+ <el-form-item label="澶勭悊鏃堕棿" prop="handleTimeRange">
<el-date-picker
- v-model="queryParams.dateRange"
- type="daterange"
+ v-model="queryParams.handleTimeRange"
+ type="datetimerange"
range-separator="鑷�"
- start-placeholder="寮�濮嬫棩鏈�"
- end-placeholder="缁撴潫鏃ユ湡"
- value-format="yyyy-MM-dd"
+ start-placeholder="寮�濮嬫椂闂�"
+ end-placeholder="缁撴潫鏃堕棿"
+ value-format="yyyy-MM-dd HH:mm:ss"
:picker-options="pickerOptions"
style="width: 380px"
/>
@@ -117,7 +117,7 @@
<!-- 寮傚父缁熻姒傝 -->
<div class="overview-section">
<el-row :gutter="20">
- <el-col :span="6">
+ <el-col :span="8">
<el-card shadow="never" class="stat-card">
<div class="stat-content">
<div class="stat-icon" style="background: #f0f9ff;">
@@ -130,7 +130,7 @@
</div>
</el-card>
</el-col>
- <el-col :span="6">
+ <el-col :span="8">
<el-card shadow="never" class="stat-card">
<div class="stat-content">
<div class="stat-icon" style="background: #f0f9ff;">
@@ -143,7 +143,7 @@
</div>
</el-card>
</el-col>
- <el-col :span="6">
+ <el-col :span="8">
<el-card shadow="never" class="stat-card">
<div class="stat-content">
<div class="stat-icon" style="background: #f0f9ff;">
@@ -152,19 +152,6 @@
<div class="stat-info">
<div class="stat-title">宸插鐞嗗紓甯�</div>
<div class="stat-value">{{ overviewData.processedCount }}</div>
- </div>
- </div>
- </el-card>
- </el-col>
- <el-col :span="6">
- <el-card shadow="never" class="stat-card">
- <div class="stat-content">
- <div class="stat-icon" style="background: #f0f9ff;">
- <i class="el-icon-s-order" style="color: #909399;"></i>
- </div>
- <div class="stat-info">
- <div class="stat-title">浠婃棩澶勭悊鏁�</div>
- <div class="stat-value">{{ overviewData.todayProcessedCount }}</div>
</div>
</div>
</el-card>
@@ -198,25 +185,19 @@
<el-table-column
label="棰樼洰鍐呭"
- prop="questionContent"
+ prop="questiontext"
min-width="300"
align="center"
>
<template slot-scope="{ row }">
<div class="question-content">
- <span class="question-text">{{ row.questionContent }}</span>
+ <span class="question-text">{{ row.questiontext }}</span>
<div class="question-tags">
<el-tag
size="mini"
- :type="getQuestionTypeTag(row.questionType)"
+ :type="getTemplateTypeTag(row.templateType)"
>
- {{ row.questionType === 1 ? '鍗曢�夐' : '澶氶�夐' }}
- </el-tag>
- <el-tag
- size="mini"
- type="info"
- >
- {{ row.templateName }}
+ {{ row.templateType === 1 ? '璇煶妯℃澘' : '闂嵎妯℃澘' }}
</el-tag>
</div>
</div>
@@ -225,20 +206,20 @@
<el-table-column
label="璐熻矗绉戝"
- prop="responsibilityDepts"
+ prop="responsibleDept"
width="180"
align="center"
>
<template slot-scope="{ row }">
<div class="dept-list">
<el-tag
- v-for="dept in row.responsibilityDepts"
- :key="dept.id"
+ v-for="dept in row.responsibleDept"
+ :key="dept.deptCode"
size="small"
type="primary"
class="dept-tag"
>
- {{ dept.name }}
+ {{ dept.deptName }}
</el-tag>
</div>
</template>
@@ -253,11 +234,11 @@
<div class="fill-statistics">
<div class="stat-item">
<span class="stat-label">鏈夋晥濉啓锛�</span>
- <span class="stat-value">{{ row.validFillCount }}</span>
+ <span class="stat-value">{{ row.fillSituation.effectiveFillNum }}</span>
</div>
<div class="stat-item">
<span class="stat-label">寮傚父濉啓锛�</span>
- <span class="stat-value exception-count">{{ row.exceptionFillCount }}</span>
+ <span class="stat-value exception-count">{{ row.fillSituation.exceptionFillNum }}</span>
</div>
</div>
</template>
@@ -272,15 +253,15 @@
<div class="exception-tasks">
<div class="task-category">
<div class="task-title">宸插鐞�</div>
- <div class="task-count processed">{{ row.processedCount }}</div>
+ <div class="task-count processed">{{ row.exceptionQuesNum.yesDeal }}</div>
</div>
<div class="task-category">
<div class="task-title">寰呭鐞�</div>
- <div class="task-count pending">{{ row.pendingCount }}</div>
+ <div class="task-count pending">{{ row.exceptionQuesNum.noDeal }}</div>
</div>
<div class="task-category">
<div class="task-title">寮傚父鎬绘暟</div>
- <div class="task-count total">{{ row.totalExceptionCount }}</div>
+ <div class="task-count total">{{ row.exceptionQuesNum.all }}</div>
</div>
</div>
</template>
@@ -288,14 +269,14 @@
<el-table-column
label="鏈�杩戝鐞�"
- prop="lastProcessTime"
+ prop="handleTime"
width="180"
align="center"
>
<template slot-scope="{ row }">
- <div v-if="row.lastProcessTime" class="last-process">
- <div class="process-time">{{ row.lastProcessTime }}</div>
- <div class="process-user">{{ row.lastProcessUser }}</div>
+ <div v-if="row.handleTime" class="last-process">
+ <div class="process-time">{{ formatDateTime(row.handleTime) }}</div>
+ <div class="process-user">{{ row.handleBy || '绯荤粺澶勭悊' }}</div>
</div>
<span v-else class="no-process">鏆傛棤澶勭悊璁板綍</span>
</template>
@@ -308,14 +289,6 @@
fixed="right"
>
<template slot-scope="{ row }">
- <!-- <el-button
- type="primary"
- size="small"
- icon="el-icon-view"
- @click="handleViewDetail(row)"
- >
- 璇︽儏
- </el-button> -->
<el-button
type="warning"
size="small"
@@ -347,15 +320,20 @@
</template>
<script>
+import { tracedeallist } from "@/api/AiCentre/index";
+
export default {
name: 'ExceptionList',
data() {
return {
// 鏌ヨ鍙傛暟
queryParams: {
- templateId: '',
- deptIds: [],
- dateRange: [],
+ todeptcode: [], // 澶勭悊绉戝缂栧彿鏁扮粍
+ todeptname: '', // 澶勭悊绉戝鍚嶇О
+ templateid: '', // 浠诲姟妯℃澘ID
+ handleStartTime: '', // 澶勭悊寮�濮嬫椂闂�
+ handleEndTime: '', // 澶勭悊缁撴潫鏃堕棿
+ handleTimeRange: [], // 鏃堕棿鑼冨洿锛岀敤浜庣晫闈㈠睍绀�
pageNum: 1,
pageSize: 10
},
@@ -368,26 +346,26 @@
// 妯℃澘鍒楄〃
templateList: [
- { id: 1, name: '鍑洪櫌婊℃剰搴﹂棶鍗�' },
- { id: 2, name: '浣忛櫌婊℃剰搴﹂棶鍗�' },
- { id: 3, name: '闂ㄨ瘖婊℃剰搴﹂棶鍗�' },
- { id: 4, name: '甯哥敤婊℃剰搴﹂棶鍗�' }
+ { id: 1, name: '璇煶妯℃澘' },
+ { id: 2, name: '闂嵎妯℃澘' }
+ // 浣犲彲浠ユ牴鎹疄闄呮儏鍐典粠鎺ュ彛鑾峰彇妯℃澘鍒楄〃
],
// 绉戝鍒楄〃
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: '鍐呭垎娉岀' },
- { id: 11, name: '鑲惧唴绉�' },
- { id: 12, name: '鑲跨槫绉�' }
+ // 浣犲彲浠ヤ粠鎺ュ彛鑾峰彇绉戝鍒楄〃锛岃繖閲屽厛鐢ㄩ潤鎬佹暟鎹�
+ { deptCode: '001', deptName: '蹇冭绠″唴绉�' },
+ { deptCode: '002', deptName: '绁炵粡鍐呯' },
+ { deptCode: '003', deptName: '鏅绉�' },
+ { deptCode: '004', deptName: '楠ㄧ' },
+ { deptCode: '005', deptName: '濡囦骇绉�' },
+ { deptCode: '006', deptName: '鍎跨' },
+ { deptCode: '007', deptName: '鎬ヨ瘖绉�' },
+ { deptCode: '008', deptName: '鍛煎惛鍐呯' },
+ { deptCode: '009', deptName: '娑堝寲鍐呯' },
+ { deptCode: '010', deptName: '鍐呭垎娉岀' },
+ { deptCode: '011', deptName: '鑲惧唴绉�' },
+ { deptCode: '012', deptName: '鑲跨槫绉�' }
],
// 寮傚父鍒楄〃鏁版嵁
@@ -445,6 +423,46 @@
},
methods: {
+ // 鏍煎紡鍖栨棩鏈熸椂闂�
+ formatDateTime(dateTime) {
+ if (!dateTime) return '';
+ const date = new Date(dateTime);
+ return date.toLocaleDateString().replace(/\//g, '-') + ' ' +
+ date.toTimeString().split(' ')[0];
+ },
+
+ // 鑾峰彇妯℃澘绫诲瀷鏍囩鏍峰紡
+ getTemplateTypeTag(type) {
+ return type === 1 ? 'primary' : 'success';
+ },
+
+ // 鏋勫缓鏌ヨ鍙傛暟
+ buildQueryParams() {
+ const params = {
+ pageNum: this.queryParams.pageNum,
+ pageSize: this.queryParams.pageSize
+ };
+
+ // 澶勭悊绉戝缂栧彿
+ if (this.queryParams.todeptcode && this.queryParams.todeptcode.length > 0) {
+ // 鎺ュ彛鍙兘闇�瑕佸瓧绗︿覆鏍煎紡鐨勭瀹ょ紪鍙凤紝鏍规嵁瀹為檯鎯呭喌璋冩暣
+ params.todeptcode = this.queryParams.todeptcode.join(',');
+ }
+
+ // 妯℃澘ID
+ if (this.queryParams.templateid) {
+ params.templateid = this.queryParams.templateid;
+ }
+
+ // 澶勭悊鏃堕棿鑼冨洿
+ if (this.queryParams.handleTimeRange && this.queryParams.handleTimeRange.length === 2) {
+ params.handleStartTime = this.queryParams.handleTimeRange[0];
+ params.handleEndTime = this.queryParams.handleTimeRange[1];
+ }
+
+ return params;
+ },
+
// 鍔犺浇鏁版嵁
async loadData() {
this.loading = true;
@@ -460,185 +478,62 @@
// 鍔犺浇寮傚父鍒楄〃
async loadExceptionList() {
- return new Promise((resolve) => {
- setTimeout(() => {
- // Mock 鏁版嵁
- this.exceptionList = [
- {
- id: 1,
- questionId: 101,
- questionContent: '鎮ㄥ鍖绘姢浜哄憳鐨勬湇鍔℃�佸害鏄惁婊℃剰锛�',
- questionType: 1, // 1: 鍗曢�夐, 2: 澶氶�夐
- templateName: '鍑洪櫌婊℃剰搴﹂棶鍗�',
- responsibilityDepts: [
- { id: 1, name: '蹇冭绠″唴绉�' },
- { id: 2, name: '绁炵粡鍐呯' }
- ],
- validFillCount: 145,
- exceptionFillCount: 8,
- processedCount: 5,
- pendingCount: 3,
- totalExceptionCount: 8,
- lastProcessTime: '2024-01-15 10:30:25',
- lastProcessUser: '寮犲尰鐢�'
- },
- {
- id: 2,
- questionId: 102,
- questionContent: '鎮ㄥ鍖荤敓鐨勮瘖鐤楁按骞冲拰鎶�鏈兘鍔涜瘎浠峰浣曪紵',
- questionType: 1,
- templateName: '浣忛櫌婊℃剰搴﹂棶鍗�',
- responsibilityDepts: [
- { id: 3, name: '鏅绉�' },
- { id: 4, name: '楠ㄧ' }
- ],
- validFillCount: 120,
- exceptionFillCount: 12,
- processedCount: 8,
- pendingCount: 4,
- totalExceptionCount: 12,
- lastProcessTime: '2024-01-14 16:20:10',
- lastProcessUser: '鏉庢姢澹暱'
- },
- {
- id: 3,
- questionId: 103,
- questionContent: '鎮ㄥ鍖婚櫌鐨勭幆澧冨拰鍗敓鐘跺喌鏄惁婊℃剰锛�',
- questionType: 1,
- templateName: '闂ㄨ瘖婊℃剰搴﹂棶鍗�',
- responsibilityDepts: [
- { id: 5, name: '濡囦骇绉�' },
- { id: 6, name: '鍎跨' },
- { id: 7, name: '鎬ヨ瘖绉�' }
- ],
- validFillCount: 180,
- exceptionFillCount: 15,
- processedCount: 10,
- pendingCount: 5,
- totalExceptionCount: 15,
- lastProcessTime: '2024-01-13 09:15:45',
- lastProcessUser: '鐜嬩富浠�'
- },
- {
- id: 4,
- questionId: 104,
- questionContent: '鎮ㄨ涓哄尰鎶や汉鍛樹笌鎮ㄧ殑娌熼�氭槸鍚﹀厖鍒嗭紵',
- questionType: 1,
- templateName: '甯哥敤婊℃剰搴﹂棶鍗�',
- responsibilityDepts: [
- { id: 8, name: '鍛煎惛鍐呯' },
- { id: 9, name: '娑堝寲鍐呯' }
- ],
- validFillCount: 95,
- exceptionFillCount: 6,
- processedCount: 4,
- pendingCount: 2,
- totalExceptionCount: 6,
- lastProcessTime: '2024-01-12 14:40:30',
- lastProcessUser: '璧靛尰鐢�'
- },
- {
- id: 5,
- questionId: 105,
- questionContent: '鎮ㄥ绛夊緟灏辫瘖鍜屾不鐤楃殑鏃堕棿鏄惁婊℃剰锛�',
- questionType: 1,
- templateName: '浣忛櫌婊℃剰搴﹂棶鍗�',
- responsibilityDepts: [
- { id: 10, name: '鍐呭垎娉岀' },
- { id: 11, name: '鑲惧唴绉�' }
- ],
- validFillCount: 200,
- exceptionFillCount: 25,
- processedCount: 15,
- pendingCount: 10,
- totalExceptionCount: 25,
- lastProcessTime: '2024-01-11 11:25:15',
- lastProcessUser: '瀛欐姢澹�'
- },
- {
- id: 6,
- questionId: 106,
- questionContent: '鎮ㄥ鍖婚櫌鏀惰垂鐨勯�忔槑搴﹀拰鍚堢悊鎬ц瘎浠峰浣曪紵',
- questionType: 1,
- templateName: '闂ㄨ瘖婊℃剰搴﹂棶鍗�',
- responsibilityDepts: [
- { id: 12, name: '鑲跨槫绉�' }
- ],
- validFillCount: 160,
- exceptionFillCount: 18,
- processedCount: 12,
- pendingCount: 6,
- totalExceptionCount: 18,
- lastProcessTime: '2024-01-10 15:50:20',
- lastProcessUser: '鍛ㄥ尰鐢�'
- },
- {
- id: 7,
- questionId: 107,
- questionContent: '鎮ㄤ細鍚戜翰鍙嬫帹鑽愭垜浠尰闄㈠悧锛�',
- questionType: 1,
- templateName: '鍑洪櫌婊℃剰搴﹂棶鍗�',
- responsibilityDepts: [
- { id: 1, name: '蹇冭绠″唴绉�' },
- { id: 8, name: '鍛煎惛鍐呯' }
- ],
- validFillCount: 110,
- exceptionFillCount: 7,
- processedCount: 5,
- pendingCount: 2,
- totalExceptionCount: 7,
- lastProcessTime: '2024-01-09 10:15:40',
- lastProcessUser: '鍚翠富浠�'
- },
- {
- id: 8,
- questionId: 108,
- questionContent: '鎮ㄥ浠ヤ笅鍝簺鏂归潰姣旇緝婊℃剰锛堝閫夛級锛�',
- questionType: 2,
- templateName: '甯哥敤婊℃剰搴﹂棶鍗�',
- responsibilityDepts: [
- { id: 2, name: '绁炵粡鍐呯' },
- { id: 3, name: '鏅绉�' },
- { id: 5, name: '濡囦骇绉�' }
- ],
- validFillCount: 135,
- exceptionFillCount: 9,
- processedCount: 6,
- pendingCount: 3,
- totalExceptionCount: 9,
- lastProcessTime: '2024-01-08 13:30:55',
- lastProcessUser: '閮戝尰鐢�'
- }
- ];
- this.total = this.exceptionList.length;
- resolve();
- }, 500);
- });
+ try {
+ const params = this.buildQueryParams();
+ const response = await tracedeallist(params);
+
+ if (response.code==200) {
+ this.exceptionList = response.rows.detailTraceDealDTOList || [];
+ this.overviewData.totalExceptionCount=response.rows.totalException
+ this.overviewData.pendingCount=response.rows.noDealException
+ this.overviewData.processedCount=response.rows.yesDealException
+ this.total = response.total || 0;
+ } else {
+ this.exceptionList = [];
+ this.total = 0;
+ }
+ } catch (error) {
+ console.error('鍔犺浇寮傚父鍒楄〃澶辫触:', error);
+ this.$message.error('鍔犺浇寮傚父鍒楄〃澶辫触锛岃绋嶅悗閲嶈瘯');
+ this.exceptionList = [];
+ this.total = 0;
+ }
},
// 鍔犺浇姒傝鏁版嵁
async loadOverviewData() {
- return new Promise((resolve) => {
- setTimeout(() => {
- // 璁$畻缁熻鏁版嵁
- const totalExceptionCount = this.exceptionList.reduce((sum, item) => sum + item.totalExceptionCount, 0);
- const pendingCount = this.exceptionList.reduce((sum, item) => sum + item.pendingCount, 0);
- const processedCount = this.exceptionList.reduce((sum, item) => sum + item.processedCount, 0);
+ try {
+ // 浠庢帴鍙f暟鎹绠楃粺璁℃暟鎹�
+ const totalExceptionCount = this.exceptionList.reduce((sum, item) =>
+ sum + (item.exceptionQuesNum?.all || 0), 0);
+ const pendingCount = this.exceptionList.reduce((sum, item) =>
+ sum + (item.exceptionQuesNum?.noDeal || 0), 0);
+ const processedCount = this.exceptionList.reduce((sum, item) =>
+ sum + (item.exceptionQuesNum?.yesDeal || 0), 0);
- this.overviewData = {
- totalExceptionCount,
- pendingCount,
- processedCount,
- todayProcessedCount: 8 // 浠婃棩澶勭悊鏁� mock
- };
- resolve();
- }, 300);
- });
- },
+ // 璁$畻浠婃棩澶勭悊鏁帮紙杩欓噷鍙互鏍规嵁瀹為檯闇�姹傝皟鏁撮�昏緫锛�
+ const today = new Date().toISOString().split('T')[0];
+ const todayProcessedCount = this.exceptionList.filter(item => {
+ if (!item.handleTime) return false;
+ const handleDate = new Date(item.handleTime).toISOString().split('T')[0];
+ return handleDate === today;
+ }).length;
- // 鑾峰彇棰樼洰绫诲瀷鏍囩鏍峰紡
- getQuestionTypeTag(type) {
- return type === 1 ? 'primary' : 'success';
+ this.overviewData = {
+ totalExceptionCount,
+ pendingCount,
+ processedCount,
+ todayProcessedCount
+ };
+ } catch (error) {
+ console.error('鍔犺浇姒傝鏁版嵁澶辫触:', error);
+ this.overviewData = {
+ totalExceptionCount: 0,
+ pendingCount: 0,
+ processedCount: 0,
+ todayProcessedCount: 0
+ };
+ }
},
// 澶勭悊鏌ヨ
@@ -650,8 +545,9 @@
// 澶勭悊閲嶇疆
handleReset() {
this.$refs.queryForm.resetFields();
- this.queryParams.dateRange = [];
+ this.queryParams.handleTimeRange = [];
this.queryParams.pageNum = 1;
+ this.queryParams.todeptcode = []; // 閲嶇疆绉戝閫夋嫨
this.loadData();
},
@@ -664,7 +560,7 @@
// 璺宠浆鍒版壒閲忓鐞嗛〉闈�
this.$router.push({
- path: '/satisfaction/exception/batch-process',
+ path: '/Intelligentcenter/batch',
query: {
questionIds: this.selectedIds.join(',')
}
@@ -684,17 +580,7 @@
// 澶勭悊閫夋嫨鍙樺寲
handleSelectionChange(selection) {
- this.selectedIds = selection.map(item => item.questionId);
- },
-
- // 澶勭悊鏌ョ湅璇︽儏
- handleViewDetail(row) {
- this.$router.push({
- path: '/satisfaction/exception/detail',
- query: {
- id: row.questionId
- }
- });
+ this.selectedIds = selection.map(item => item.scriptid);
},
// 澶勭悊鍗曚釜棰樼洰鎵归噺澶勭悊
@@ -702,7 +588,8 @@
this.$router.push({
path: '/Intelligentcenter/batch',
query: {
- questionId: row.questionId
+ questionId: row.scriptid,
+ questionText: encodeURIComponent(row.questiontext)
}
});
},
@@ -838,12 +725,13 @@
color: #303133;
margin-bottom: 8px;
line-height: 1.5;
+ text-align: left;
}
.question-tags {
display: flex;
gap: 5px;
- justify-content: center;
+ justify-content: flex-start;
}
}
diff --git a/src/views/Satisfaction/sfstatistics/components/SatisfactionStatistics.vue b/src/views/Satisfaction/sfstatistics/components/SatisfactionStatistics.vue
index c1d3a0a..2d78fdf 100644
--- a/src/views/Satisfaction/sfstatistics/components/SatisfactionStatistics.vue
+++ b/src/views/Satisfaction/sfstatistics/components/SatisfactionStatistics.vue
@@ -414,7 +414,7 @@
</template>
</el-table-column>
- <el-table-column
+ <!-- <el-table-column
label="瓒嬪娍"
prop="trend"
align="center"
@@ -446,7 +446,7 @@
}}</span>
</div>
</template>
- </el-table-column>
+ </el-table-column> -->
<el-table-column
label="鎿嶄綔"
@@ -790,11 +790,11 @@
Object.entries(apiData.rows).forEach(([typeName, typeStat]) => {
const sendCount = typeStat.subidAll || 0;
const receiveCount = typeStat.fillCountAll || 0;
- const recoveryRate = typeStat.receiveRate || 0;
+ const recoveryRate = typeStat.receiveRate.toFixed(2) || 0;
chartData.push({
name: typeName,
- value: recoveryRate * 100, // 杞崲涓虹櫨鍒嗘瘮
+ value: (recoveryRate * 100).toFixed(2), // 杞崲涓虹櫨鍒嗘瘮
sendCount: sendCount,
receiveCount: receiveCount,
averageScore: typeStat.averageScore || 0,
@@ -914,7 +914,9 @@
const response = await satisfactionGraph(params);
if (response.code === 200) {
- this.processTypeDetailData(response.data);
+ this.processTypeDetailData(response);
+ console.log(11);
+
} else {
this.$message.error(response.msg || "鑾峰彇绫诲瀷鏄庣粏鏁版嵁澶辫触");
const mockData = await this.generateMockTypeDetail();
@@ -944,7 +946,7 @@
Object.entries(apiData.rows).forEach(([typeName, typeStat], index) => {
const sendCount = typeStat.subidAll || 0;
const receiveCount = typeStat.fillCountAll || 0;
- const recoveryRate = typeStat.receiveRate || 0;
+ const recoveryRate = typeStat.receiveRate.toFixed(2) || 0;
const averageScore = typeStat.averageScore || 0;
typeDetail.push({
@@ -963,6 +965,8 @@
});
this.typeDetailData = typeDetail;
+ console.log(this.typeDetailData,'this.typeDetailData');
+
this.calculateTypeSummary(typeDetail);
},
@@ -972,7 +976,7 @@
if (score >= 4.0) return "鑹ソ";
if (score >= 3.0) return "涓�鑸�";
if (score >= 2.0) return "杈冨樊";
- return "宸�";
+ return "鏈煡";
},
// 鑾峰彇瓒嬪娍
@@ -1041,24 +1045,24 @@
// 娓叉煋鍥捐〃
renderChart(chartData) {
if (!this.barChart) return;
- if (!chartData || chartData.length === 0) {
- const emptyOption = {
- title: {
- text: "鏆傛棤鏁版嵁",
- left: "center",
- top: "center",
- textStyle: {
- color: "#999",
- fontSize: 16,
- fontWeight: "normal"
- }
- },
- xAxis: { show: false },
- yAxis: { show: false }
- };
- this.barChart.setOption(emptyOption);
- return;
- }
+ if (!chartData || chartData.length === 0) {
+ const emptyOption = {
+ title: {
+ text: "鏆傛棤鏁版嵁",
+ left: "center",
+ top: "center",
+ textStyle: {
+ color: "#999",
+ fontSize: 16,
+ fontWeight: "normal",
+ },
+ },
+ xAxis: { show: false },
+ yAxis: { show: false },
+ };
+ this.barChart.setOption(emptyOption);
+ return;
+ }
const option = {
title: {
text: "",
@@ -1079,7 +1083,7 @@
<span style="display:inline-block;width:10px;height:10px;border-radius:2px;background:${
data.color
};margin-right:5px;"></span>
- 濉姤姣斾緥: <strong>${data.value.toFixed(1)}%</strong>
+ 濉姤姣斾緥: <strong>${data.value}%</strong>
</div>
<div style="margin: 2px 0;">
<span style="display:inline-block;width:10px;height:10px;border-radius:2px;background:#eee;margin-right:5px;"></span>
@@ -1437,12 +1441,12 @@
// 鏍煎紡鍖栫櫨鍒嗘瘮
formatPercent(value) {
- if (value === null || value === undefined) return "-";
- const num = parseFloat(value);
- if (isNaN(num)) return "-";
- // 濡傛灉鍊煎皬浜�1锛岃涓烘槸灏忔暟姣斾緥锛岄渶瑕佷箻浠�100
- const percentValue = num < 1 ? num * 100 : num;
- return `${percentValue.toFixed(2)}%`;
+ if (value === null || value === undefined) return "-";
+ const num = parseFloat(value);
+ if (isNaN(num)) return "-";
+ // 濡傛灉鍊煎皬浜�1锛岃涓烘槸灏忔暟姣斾緥锛岄渶瑕佷箻浠�100
+ const percentValue = num < 1 ? num * 100 : num;
+ return `${percentValue.toFixed(2)}%`;
},
// 鑾峰彇鍥炴敹鐜囨牱寮忕被
@@ -1459,7 +1463,7 @@
鑹ソ: "primary",
涓�鑸�: "warning",
杈冨樊: "danger",
- 宸�: "info",
+ 鏈煡: "info",
};
return levelMap[level] || "info";
},
diff --git a/src/views/followvisit/HistoricalFollow/index.vue b/src/views/followvisit/HistoricalFollow/index.vue
index 4b5b99a..3abdee2 100644
--- a/src/views/followvisit/HistoricalFollow/index.vue
+++ b/src/views/followvisit/HistoricalFollow/index.vue
@@ -662,7 +662,7 @@
value: 4,
label: "涓嶆墽琛�",
},
- {
+ {
value: 5,
label: "鍙戦�佸け璐�",
},
@@ -670,7 +670,7 @@
value: 6,
label: "宸插畬鎴�",
},
- {
+ {
value: 7,
label: "瓒呮椂",
},
@@ -1147,7 +1147,7 @@
/** 瀵煎嚭鎸夐挳鎿嶄綔 */
handleExport() {
console.log(this.topqueryParams);
-
+ this.topqueryParams.pageSize = null;
this.download(
// "smartor/serviceSubtask/export",
"smartor/serviceSubtask/getSubtaskByDiagnameExport",
diff --git a/vue.config.js b/vue.config.js
index 7ce923e..79d9dfb 100644
--- a/vue.config.js
+++ b/vue.config.js
@@ -37,9 +37,9 @@
[process.env.VUE_APP_BASE_API]: {
// target: `https://www.health-y.cn/lssf`,
// target: `http://192.168.100.10:8096`,
- // target: `http://192.168.100.10:8094`,//鐪佺珛鍚屽痉
+ target: `http://192.168.100.10:8094`,//鐪佺珛鍚屽痉
// target: `http://192.168.100.10:8095`,//鏂板崕
- target:`http://localhost:8095`,
+ // target:`http://localhost:8095`,
// target:`http://35z1t16164.qicp.vip`,
// target: `http://192.168.100.172:8095`,
// target: `http://192.168.101.166:8093`,
--
Gitblit v1.9.3