From 15371b329484632c987e349e50f41cab90d3ae8c Mon Sep 17 00:00:00 2001
From: WXL (wul) <wl_5969728@163.com>
Date: 星期三, 15 四月 2026 09:28:25 +0800
Subject: [PATCH] 测试完成

---
 src/views/sfstatistics/percentage/components/SecondFollowUp.vue           |  679 ++
 src/api/system/user.js                                                    |    8 
 src/views/sfstatistics/percentage/index copy.vue                          | 2898 ++++++++++++
 src/views/followvisit/again/index.vue                                     |   50 
 src/views/sfstatistics/percentage/components/TimelyRateDialog.vue         |  249 +
 vue.config.js                                                             |    5 
 src/components/AudioPlayer/index.vue                                      |  964 ++++
 src/views/sfstatistics/percentage/components/FirstFollowUp.vue            |  728 +++
 src/views/Satisfaction/configurationmyd/batch.vue                         | 1004 ++-
 src/views/sfstatistics/percentage/components/styles.scss                  |   90 
 src/views/Satisfaction/configurationmyd/components/DetailsAnomaly.vue     | 1266 +++--
 src/views/sfstatistics/percentage/components/ChartDialog.vue              |  579 ++
 /dev/null                                                                 |    0 
 src/api/AiCentre/satisfactionse.js                                        |   25 
 src/views/Satisfaction/sfstatistics/components/SatisfactionStatistics.vue |   70 
 src/views/followvisit/HistoricalFollow/index.vue                          |    6 
 src/views/followvisit/record/detailpage/index.vue                         |   39 
 src/views/sfstatistics/percentage/index.vue                               | 3338 +------------
 src/views/sfstatistics/percentage/components/ContinuedCare.vue            |  633 ++
 src/views/sfstatistics/percentage/components/DetailDialog.vue             |  302 +
 src/views/Satisfaction/configurationmyd/index.vue                         |  554 +-
 src/views/Satisfaction/configurationmyd/dispose.vue                       |  570 +-
 src/views/followvisit/discharge/index.vue                                 |    6 
 23 files changed, 9,497 insertions(+), 4,566 deletions(-)

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/api/system/user.js b/src/api/system/user.js
index 53e4168..6d5b155 100644
--- a/src/api/system/user.js
+++ b/src/api/system/user.js
@@ -102,6 +102,14 @@
     data: data,
   });
 }
+// 寤剁画鎶ょ悊缁熻
+export function getContinueNerseCount(data) {
+  return request({
+    url: "/smartor/serviceSubtask/getContinueNerseCount",
+    method: "post",
+    data: data,
+  });
+}
 // 婊℃剰搴︾粺璁¤鎯�
 export function getSfStatisticsJoyInfo(data) {
   return request({
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..bd73abe 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.patdescJson.sendname }}</span>
+                  </div>
+                  <div class="patient-item">
+                    <span class="label">鎬у埆锛�</span>
+                    <span class="value">{{
+                      row.patdescJson.sex
+                    }}</span>
+                  </div>
+                  <div class="patient-item">
+                    <span class="label">骞撮緞锛�</span>
+                    <span class="value">{{ row.patdescJson.age }}宀�</span>
+                  </div>
                 </div>
-                <div class="patient-item">
-                  <span class="label">鎬у埆锛�</span>
-                  <span class="value">{{
-                    row.gender === 1 ? "鐢�" : "濂�"
-                  }}</span>
-                </div>
-                <div class="patient-item">
-                  <span class="label">骞撮緞锛�</span>
-                  <span class="value">{{ row.age }}宀�</span>
-                </div>
-                <div class="patient-item">
-                  <span class="label">鐢佃瘽锛�</span>
-                  <span class="value">{{ row.phone }}</span>
+                <div class="patient-row">
+                  <div class="patient-item full-width">
+                    <span class="label">鐢佃瘽锛�</span>
+                    <span class="value">{{ row.patdescJson.phone }}</span>
+                  </div>
                 </div>
               </div>
             </template>
           </el-table-column>
 
-          <el-table-column label="鍑洪櫌淇℃伅" width="250" align="center">
+          <el-table-column label="濉啓淇℃伅" width="180" align="center">
             <template slot-scope="{ row }">
-              <div class="discharge-info">
+              <div class="fill-info">
                 <div class="info-item">
-                  <span class="label">绉戝锛�</span>
-                  <span class="value">{{ row.dischargeDept }}</span>
+                  <span class="label">濉姤鏃堕棿锛�</span>
+                  <span class="value time">{{
+                    formatDateTime(row.createTime)
+                  }}</span>
                 </div>
-                <div class="info-item">
-                  <span class="label">鐥呭尯锛�</span>
-                  <span class="value">{{ row.dischargeWard }}</span>
-                </div>
-                <div class="info-item">
-                  <span class="label">濉啓鏃堕棿锛�</span>
-                  <span class="value time">{{ row.fillTime }}</span>
+                <div v-if="row.recordurl" class="info-item">
+                  <el-button
+                    type="text"
+                    size="small"
+                    @click="handlePlayAudio(row.recordurl)"
+                    icon="el-icon-headset"
+                  >
+                    鎾斁褰曢煶
+                  </el-button>
                 </div>
               </div>
             </template>
@@ -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,57 @@
           @click="submitBatchProcess"
           :loading="batchProcessing"
         >
-          鎵归噺鎻愪氦
+          鎵归噺鎻愪氦 ({{ selectedExceptionIds.length }})
         </el-button>
       </span>
+    </el-dialog>
+    <!-- 杩涘害瀵硅瘽妗� -->
+    <el-dialog
+      title="鎵归噺澶勭悊杩涘害"
+      :visible.sync="batchProgress.visible"
+      width="400px"
+      :close-on-click-modal="false"
+      :show-close="false"
+      :close-on-press-escape="false"
+    >
+      <div class="progress-content">
+        <el-progress
+          :percentage="batchProgress.percentage"
+          :status="batchProgress.percentage === 100 ? 'success' : ''"
+        />
+        <div class="progress-info">
+          宸插鐞� {{ batchProgress.processed }}/{{ batchProgress.total }} 鏉¤褰�
+        </div>
+      </div>
     </el-dialog>
     <!-- 寮傚父璇︽儏寮规 -->
     <Details-anomaly
       :visible="detailDialogVisible"
       :record-id="selectedRecordId"
       :title="detailDialogTitle"
+      :record-data="selectedRecordData"
       @update:visible="handleDetailDialogClose"
       @processed="handleProcessed"
       @close="handleDetailDialogClose"
+    />
+
+    <!-- 褰曢煶鎾斁鍣� -->
+    <audio
+      v-if="audioUrl"
+      :src="audioUrl"
+      ref="audioPlayer"
+      controls
+      style="display: none"
     />
   </div>
 </template>
 
 <script>
 import DetailsAnomaly from "./components/DetailsAnomaly.vue";
+import { tracelist, traceedit } from "@/api/AiCentre/index";
+import dayjs from "dayjs";
+import { deptTreeSelect } from "@/api/system/user";
+
 export default {
   name: "BatchProcess",
   components: {
@@ -383,10 +494,15 @@
   },
   data() {
     return {
-      // 娣诲姞浠ヤ笅鏁版嵁
+      // 璇︽儏寮规鐩稿叧
       detailDialogVisible: false,
       selectedRecordId: null,
+      selectedRecordData: null,
       detailDialogTitle: "寮傚父鍙嶉璇︽儏",
+
+      // 闊抽鎾斁
+      audioUrl: "",
+
       // 褰撳墠澶勭悊鐨勫紓甯窱D
       currentExceptionId: null,
 
@@ -395,8 +511,10 @@
 
       // 杩囨护鍙傛暟
       filterParams: {
-        deptId: "",
-        status: "",
+        todeptcode: "",
+        handleFlag: "",
+        templateType: null,
+        scriptids: null,
         pageNum: 1,
         pageSize: 10,
       },
@@ -406,19 +524,11 @@
       processing: false,
       batchProcessing: false,
 
+      // 鏉冮檺鎺у埗
+      hasQualityPermission: false, // 鏄惁鍏锋湁璐ㄧ鏉冮檺
+
       // 绉戝鍒楄〃
-      deptList: [
-        { id: 1, name: "蹇冭绠″唴绉�" },
-        { id: 2, name: "绁炵粡鍐呯" },
-        { id: 3, name: "鏅绉�" },
-        { id: 4, name: "楠ㄧ" },
-        { id: 5, name: "濡囦骇绉�" },
-        { id: 6, name: "鍎跨" },
-        { id: 7, name: "鎬ヨ瘖绉�" },
-        { id: 8, name: "鍛煎惛鍐呯" },
-        { id: 9, name: "娑堝寲鍐呯" },
-        { id: 10, name: "鍐呭垎娉岀" },
-      ],
+      deptList: [],
 
       // 寮傚父鍒楄〃鏁版嵁
       exceptionList: [],
@@ -427,183 +537,169 @@
       // 澶勭悊瀵硅瘽妗�
       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
+    this.filterParams.scriptids = this.$route.query.questionId || this.$route.query.questionIds||null;
+    // if (this.$route.query.questionId) {
+    // } else if (this.$route.query.questionIds) {
+    //   console.log(
+    //     this.$route.query.questionIds,
+    //     "this.$route.query.questionIds"
+    //   );
+
+      this.filterParams.templateType = Number(this.$route.query.type)||null;
+
+    //   this.filterParams.scriptid = null;
+    // }
+    this.hasQualityPermission = this.checkQualityPermission();
+  },
+
   mounted() {
     this.loadExceptionList();
+    this.getDeptOptions();
   },
 
   methods: {
-    // 鍔犺浇寮傚父鍒楄〃
-    async loadExceptionList() {
-      this.loading = true;
+    // 鏍煎紡鍖栨棩鏈熸椂闂�
+    formatDateTime(dateTime) {
+      if (!dateTime) return "";
       try {
-        // Mock 鏁版嵁
-        await new Promise((resolve) => {
-          setTimeout(() => {
-            this.exceptionList = [
-              {
-                id: 1,
-                responsibilityDept: "蹇冭绠″唴绉�",
-                unsatisfactoryDetail:
-                  "鍖荤敓鏌ユ埧鏃堕棿澶煭锛屾矡閫氫笉澶熷厖鍒嗭紝瀵圭梾鎯呰В閲婁笉澶熻缁�",
-                patientName: "寮犲厛鐢�",
-                gender: 1,
-                age: 45,
-                phone: "138****1234",
-                dischargeDept: "蹇冭绠″唴绉�",
-                dischargeWard: "鍐呯涓�鐥呭尯",
-                fillTime: "2024-01-15 10:30:25",
-                processStatus: 0,
-                questionnaireId: 1001,
-              },
-              {
-                id: 2,
-                responsibilityDept: "绁炵粡鍐呯",
-                unsatisfactoryDetail:
-                  "鎶ゅ+鎵撻拡鎶�鏈笉浣筹紝鎵庝簡涓夋鎵嶆垚鍔燂紝涓旀�佸害涓嶅鑰愬績",
-                patientName: "鏉庡コ澹�",
-                gender: 0,
-                age: 38,
-                phone: "139****5678",
-                dischargeDept: "绁炵粡鍐呯",
-                dischargeWard: "鍐呯浜岀梾鍖�",
-                fillTime: "2024-01-14 16:20:10",
-                processStatus: 0,
-                questionnaireId: 1002,
-              },
-              {
-                id: 3,
-                responsibilityDept: "鏅绉�",
-                unsatisfactoryDetail: "鏈悗鎹㈣嵂涓嶅強鏃讹紝浼ゅ彛鐤肩棝鏃舵病鏈夊強鏃跺鐞�",
-                patientName: "鐜嬪厛鐢�",
-                gender: 1,
-                age: 52,
-                phone: "137****9012",
-                dischargeDept: "鏅绉�",
-                dischargeWard: "澶栫涓�鐥呭尯",
-                fillTime: "2024-01-13 09:15:45",
-                processStatus: 1,
-                questionnaireId: 1003,
-              },
-              {
-                id: 4,
-                responsibilityDept: "楠ㄧ",
-                unsatisfactoryDetail: "搴峰鎸囧涓嶅涓撲笟锛屽鎭㈠杩囩▼鎻忚堪涓嶆竻妤�",
-                patientName: "鍒樺コ澹�",
-                gender: 0,
-                age: 65,
-                phone: "136****3456",
-                dischargeDept: "楠ㄧ",
-                dischargeWard: "澶栫浜岀梾鍖�",
-                fillTime: "2024-01-12 14:40:30",
-                processStatus: 0,
-                questionnaireId: 1004,
-              },
-              {
-                id: 5,
-                responsibilityDept: "濡囦骇绉�",
-                unsatisfactoryDetail:
-                  "浜у墠妫�鏌ユ帓闃熸椂闂磋繃闀匡紝绛夊緟鏈熼棿娌℃湁浼戞伅搴т綅",
-                patientName: "闄堝コ澹�",
-                gender: 0,
-                age: 28,
-                phone: "135****7890",
-                dischargeDept: "濡囦骇绉�",
-                dischargeWard: "濡囦骇绉戠梾鍖�",
-                fillTime: "2024-01-11 11:25:15",
-                processStatus: 2,
-                questionnaireId: 1005,
-              },
-              {
-                id: 6,
-                responsibilityDept: "鍎跨",
-                unsatisfactoryDetail:
-                  "鍎跨鐢ㄨ嵂鍓傞噺浜や唬涓嶆竻鏅帮紝鐢ㄨ嵂娉ㄦ剰浜嬮」娌℃湁璇存槑",
-                patientName: "璧靛疂瀹�",
-                gender: 1,
-                age: 5,
-                phone: "134****1234",
-                dischargeDept: "鍎跨",
-                dischargeWard: "鍎跨鐥呭尯",
-                fillTime: "2024-01-10 15:50:20",
-                processStatus: 0,
-                questionnaireId: 1006,
-              },
-              {
-                id: 7,
-                responsibilityDept: "鎬ヨ瘖绉�",
-                unsatisfactoryDetail: "鎬ヨ瘖绛夊緟鏃堕棿杩囬暱锛岀梾鎯呮病鏈夊緱鍒板強鏃惰瘎浼�",
-                patientName: "瀛欏厛鐢�",
-                gender: 1,
-                age: 40,
-                phone: "133****5678",
-                dischargeDept: "鎬ヨ瘖绉�",
-                dischargeWard: "鎬ヨ瘖鐥呭尯",
-                fillTime: "2024-01-09 10:15:40",
-                processStatus: 0,
-                questionnaireId: 1007,
-              },
-              {
-                id: 8,
-                responsibilityDept: "鍛煎惛鍐呯",
-                unsatisfactoryDetail: "鍖荤敓寮�鑽緝澶氾紝璐圭敤杈冮珮锛屾病鏈夎鏄庡繀瑕佹��",
-                patientName: "鍛ㄥコ澹�",
-                gender: 0,
-                age: 55,
-                phone: "132****9012",
-                dischargeDept: "鍛煎惛鍐呯",
-                dischargeWard: "鍐呯涓�鐥呭尯",
-                fillTime: "2024-01-08 13:30:55",
-                processStatus: 1,
-                questionnaireId: 1008,
-              },
-            ];
-            this.total = this.exceptionList.length;
-            resolve();
-          }, 500);
+        const date = new Date(dateTime);
+        if (isNaN(date.getTime())) {
+          return dateTime;
+        }
+        return (
+          date.toLocaleDateString().replace(/\//g, "-") +
+          " " +
+          date.toTimeString().split(" ")[0]
+        );
+      } catch (error) {
+        console.error("鏃ユ湡鏍煎紡鍖栭敊璇�:", error);
+        return dateTime;
+      }
+    },
+    /** 鏌ヨ绉戝鍒楄〃 */
+    getDeptOptions() {
+      deptTreeSelect()
+        .then((res) => {
+          if (res.code == 200) {
+            this.deptList = this.flattenArray(res.data) || [];
+          }
+        })
+        .catch((error) => {
+          console.error("鑾峰彇绉戝鍒楄〃澶辫触:", error);
+          this.$message.error("鑾峰彇绉戝鍒楄〃澶辫触");
         });
-      } finally {
-        this.loading = false;
+    },
+    flattenArray(multiArray) {
+      let result = [];
+
+      function flatten(element) {
+        if (element.children && element.children.length > 0) {
+          element.children.forEach((child) => flatten(child));
+        } else {
+          let item = JSON.parse(JSON.stringify(element));
+          result.push(item);
+        }
+      }
+
+      multiArray.forEach((element) => flatten(element));
+      return result;
+    },
+    // 瑙f瀽鎮h�呮弿杩颁俊鎭�
+    parsePatDesc(patdesc) {
+      if (!patdesc) return [];
+
+      try {
+        const parts = patdesc.split("|");
+        const items = [];
+
+        if (parts[0]) items.push({ label: "濮撳悕", value: parts[0] });
+        if (parts[1]) items.push({ label: "鐢佃瘽", value: parts[1] });
+        if (parts[2]) items.push({ label: "绉戝", value: parts[2] });
+
+        return items;
+      } catch (error) {
+        console.error("瑙f瀽鎮h�呬俊鎭け璐�:", error);
+        return [];
       }
     },
 
+    // 妫�鏌ヨ川绠℃潈闄�
+    checkQualityPermission() {
+      // 杩欓噷鍙互鏍规嵁瀹為檯鏉冮檺绯荤粺瀹炵幇
+      const userRoles = this.$store.getters.roles || [];
+      return (
+        userRoles.includes("quality_manager") || userRoles.includes("admin")
+      );
+    },
+
     // 鑾峰彇鐘舵�佹爣绛剧被鍨�
-    getStatusTagType(status) {
-      switch (status) {
-        case 0:
-          return "warning"; // 寰呭鐞�
-        case 1:
-          return "primary"; // 澶勭悊涓�
-        case 2:
+    getStatusTagType(handleFlag) {
+      switch (handleFlag) {
+        case "0":
+          return "warning"; // 鏈鐞�
+        case "1":
           return "success"; // 宸插鐞�
         default:
           return "info";
@@ -611,16 +707,82 @@
     },
 
     // 鑾峰彇鐘舵�佹枃鏈�
-    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;
+      // }
+      if (this.filterParams.scriptids) {
+        params.scriptids = this.filterParams.scriptids.split(",");
+      }
+
+      return params;
+    },
+
+    // 鍔犺浇寮傚父鍒楄〃
+    async loadExceptionList() {
+      this.loading = true;
+      try {
+        const params = this.buildQueryParams();
+        const response = await tracelist(params);
+
+        if (response && response.code === 200) {
+          this.exceptionList = response.rows || [];
+          this.total = response.total || 0;
+        } else {
+          this.exceptionList = [];
+          this.total = 0;
+          this.$message.error(response?.msg || "鍔犺浇寮傚父鍒楄〃澶辫触");
+        }
+      } catch (error) {
+        console.error("鍔犺浇寮傚父鍒楄〃澶辫触:", error);
+        this.$message.error("鍔犺浇寮傚父鍒楄〃澶辫触锛岃绋嶅悗閲嶈瘯");
+        this.exceptionList = [];
+        this.total = 0;
+      } finally {
+        this.loading = false;
       }
     },
 
@@ -633,11 +795,14 @@
     // 閲嶇疆绛涢��
     handleResetFilter() {
       this.filterParams = {
-        deptId: "",
-        status: "",
+        todeptcode: "",
+        handleFlag: "",
+        templateType: "",
+        scriptids: null, // 淇濈暀闂ID
         pageNum: 1,
         pageSize: 10,
       };
+      this.selectedExceptionIds = [];
       this.loadExceptionList();
     },
 
@@ -652,6 +817,15 @@
         this.$message.warning("璇峰厛閫夋嫨瑕佸鐞嗙殑寮傚父鍙嶉");
         return;
       }
+
+      // 閲嶇疆鎵归噺澶勭悊琛ㄥ崟
+      this.batchProcessForm = {
+        handleFlag: "",
+        ccdepts: [],
+        handleresult: "",
+        handledesc: "",
+      };
+
       this.batchDialogVisible = true;
     },
 
@@ -663,44 +837,86 @@
     // 鏌ョ湅璇︽儏
     handleViewDetail(row) {
       this.selectedRecordId = row.id;
-      this.detailDialogTitle = `${row.patientName} - 寮傚父鍙嶉璇︽儏`;
+      this.selectedRecordData = row;
+
+      // 鐢熸垚寮规鏍囬
+      let title = "寮傚父鍙嶉璇︽儏";
+      if (row.patdesc) {
+        const patientName = row.patdescJson.sendname;
+        if (patientName) {
+          title = `${patientName} - ${title}`;
+        }
+      }
+      this.detailDialogTitle = title;
+
       this.detailDialogVisible = true;
     },
+
     // 澶勭悊璇︽儏寮规鍏抽棴
     handleDetailDialogClose() {
       this.detailDialogVisible = false;
       this.selectedRecordId = null;
-    }, // 澶勭悊瀹屾垚鍚庣殑鍥炶皟
+      this.selectedRecordData = null;
+    },
+
+    // 澶勭悊瀹屾垚鍚庣殑鍥炶皟
     handleProcessed() {
-      // 閲嶆柊鍔犺浇鏁版嵁
       this.loadExceptionList();
     },
+
     // 澶勭悊鍗曚釜寮傚父
     handleProcess(row) {
       this.currentExceptionId = row.id;
+
+      // 鍒濆鍖栬〃鍗曟暟鎹�
       this.processForm = {
-        status: row.processStatus === 0 ? 1 : row.processStatus,
-        reportDepts: [],
-        remark: "",
+        handleFlag: row.handleFlag === "0" ? "1" : "0",
+        ccdepts: row.ccdepts ? row.ccdepts.split(",") : [],
+        handleresult: row.handleresult || "",
+        handledesc: row.handledesc || "",
+        finaloption: row.finaloption || "",
       };
+
       this.processDialogVisible = true;
     },
 
     // 鎻愪氦澶勭悊
     async submitProcess() {
       this.$refs.processForm.validate(async (valid) => {
-        if (valid) {
-          this.processing = true;
-          try {
-            // Mock API璋冪敤
-            await new Promise((resolve) => setTimeout(resolve, 1000));
+        if (!valid) {
+          return;
+        }
 
-            this.$message.success("澶勭悊鎻愪氦鎴愬姛");
-            this.processDialogVisible = false;
-            this.loadExceptionList();
-          } finally {
-            this.processing = false;
-          }
+        this.processing = true;
+
+        try {
+          // 鍑嗗鎻愪氦鏁版嵁
+          const submitData = {
+            id: this.currentExceptionId,
+            handleFlag: this.processForm.handleFlag,
+            handleresult: this.processForm.handleresult,
+            handledesc: this.processForm.handledesc,
+            finaloption: this.processForm.finaloption,
+            handleBy: this.$store.state.user.nickName,
+            handleTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
+            // 灏嗘暟缁勮浆鎹负閫楀彿鍒嗛殧鐨勫瓧绗︿覆
+            ccdepts: Array.isArray(this.processForm.ccdepts)
+              ? this.processForm.ccdepts.join(",")
+              : this.processForm.ccdepts,
+          };
+          // TODO: 杩欓噷闇�瑕佽皟鐢ㄥ疄闄呯殑澶勭悊鎺ュ彛
+          await traceedit(submitData);
+
+          // await new Promise((resolve) => setTimeout(resolve, 1000));
+
+          this.$message.success("澶勭悊鎻愪氦鎴愬姛");
+          this.processDialogVisible = false;
+          this.loadExceptionList();
+        } catch (error) {
+          console.error("澶勭悊鎻愪氦澶辫触:", error);
+          this.$message.error("澶勭悊鎻愪氦澶辫触锛岃绋嶅悗閲嶈瘯");
+        } finally {
+          this.processing = false;
         }
       });
     },
@@ -708,21 +924,111 @@
     // 鎻愪氦鎵归噺澶勭悊
     async submitBatchProcess() {
       this.$refs.batchProcessForm.validate(async (valid) => {
-        if (valid) {
-          this.batchProcessing = true;
-          try {
-            // Mock API璋冪敤
-            await new Promise((resolve) => setTimeout(resolve, 1500));
+        if (!valid) {
+          return;
+        }
 
-            this.$message.success(
-              `宸叉壒閲忓鐞� ${this.selectedExceptionIds.length} 鏉″紓甯稿弽棣坄
+        this.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 +1044,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,64 +1112,109 @@
       }
 
       .detail-content {
-        font-size: 13px;
-        color: #606266;
-        line-height: 1.5;
         text-align: left;
+        font-size: 12px;
+        line-height: 1.5;
+
+        .question-text {
+          color: #303133;
+          margin-bottom: 5px;
+          font-weight: 500;
+        }
+
+        .answer-text {
+          color: #f56c6c;
+          margin-bottom: 5px;
+        }
+
+        .matched-text {
+          color: #e6a23c;
+          font-style: italic;
+        }
+
+        strong {
+          color: #606266;
+          font-weight: 600;
+        }
       }
 
       .patient-info {
-        .patient-item {
+        .patient-row {
           display: flex;
           justify-content: space-between;
           align-items: center;
-          margin-bottom: 5px;
-          padding: 2px 0;
+          margin-bottom: 8px;
 
-          .label {
-            font-size: 12px;
-            color: #606266;
-            min-width: 40px;
+          &:last-child {
+            margin-bottom: 0;
           }
 
-          .value {
-            font-size: 13px;
-            color: #333;
-            font-weight: 500;
-            text-align: right;
+          .patient-item {
             flex: 1;
+            display: flex;
+            justify-content: flex-start;
+            align-items: center;
+            padding: 0 5px;
+
+            &.full-width {
+              flex: 1 0 100%;
+              margin-left: 0;
+              margin-right: 0;
+            }
+
+            .label {
+              font-size: 12px;
+              color: #606266;
+              margin-right: 5px;
+              white-space: nowrap;
+            }
+
+            .value {
+              font-size: 12px;
+              color: #333;
+              font-weight: 500;
+              text-align: right;
+              word-break: break-all;
+            }
           }
         }
       }
 
-      .discharge-info {
+      .fill-info,
+      .handle-info {
+        font-size: 12px;
+
         .info-item {
           display: flex;
-          justify-content: space-between;
+          justify-content: flex-start;
           align-items: center;
           margin-bottom: 5px;
           padding: 2px 0;
 
           .label {
-            font-size: 12px;
             color: #606266;
             min-width: 50px;
           }
 
           .value {
-            font-size: 13px;
             color: #333;
             font-weight: 500;
-            text-align: right;
+            // text-align: right;
             flex: 1;
 
             &.time {
-              font-size: 12px;
               color: #909399;
+              font-size: 11px;
             }
           }
         }
       }
+
+      .no-data {
+        color: #909399;
+        font-style: italic;
+        font-size: 12px;
+      }
     }
 
     .pagination-section {
diff --git a/src/views/Satisfaction/configurationmyd/components/DetailsAnomaly.vue b/src/views/Satisfaction/configurationmyd/components/DetailsAnomaly.vue
index 57b4dff..1219d47 100644
--- a/src/views/Satisfaction/configurationmyd/components/DetailsAnomaly.vue
+++ b/src/views/Satisfaction/configurationmyd/components/DetailsAnomaly.vue
@@ -13,147 +13,280 @@
       <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="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 +295,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 +320,7 @@
         type="primary"
         icon="el-icon-edit"
         @click="handleProcess"
-        v-if="currentRecord.processStatus !== 2"
+        v-if="currentRecord.handleFlag !== '1'"
       >
         澶勭悊寮傚父
       </el-button>
@@ -217,61 +342,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 +421,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 +467,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 +543,10 @@
       set(val) {
         this.$emit('update:visible', val);
       }
+    },
+
+    isVoiceTemplate() {
+      return this.currentRecord.templateType === 1;
     }
   },
 
@@ -370,237 +554,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 +848,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 +949,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 +1151,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 +1163,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..4c39707 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.templateType"
               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.label"
+                :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"
             />
@@ -96,11 +96,7 @@
           >
             鎵归噺澶勭悊 ({{ selectedIds.length }})
           </el-button>
-          <el-button
-            type="info"
-            icon="el-icon-download"
-            @click="handleExport"
-          >
+          <el-button type="info" icon="el-icon-download" @click="handleExport">
             瀵煎嚭寮傚父鏁版嵁
           </el-button>
           <el-button
@@ -117,24 +113,26 @@
     <!-- 寮傚父缁熻姒傝 -->
     <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;">
-                <i class="el-icon-s-claim" style="color: #5788FE;"></i>
+              <div class="stat-icon" style="background: #f0f9ff">
+                <i class="el-icon-s-claim" style="color: #5788fe"></i>
               </div>
               <div class="stat-info">
                 <div class="stat-title">鎬诲紓甯告暟閲�</div>
-                <div class="stat-value">{{ overviewData.totalExceptionCount }}</div>
+                <div class="stat-value">
+                  {{ overviewData.totalExceptionCount }}
+                </div>
               </div>
             </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;">
-                <i class="el-icon-s-flag" style="color: #E6A23C;"></i>
+              <div class="stat-icon" style="background: #f0f9ff">
+                <i class="el-icon-s-flag" style="color: #e6a23c"></i>
               </div>
               <div class="stat-info">
                 <div class="stat-title">寰呭鐞嗗紓甯�</div>
@@ -143,28 +141,15 @@
             </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;">
-                <i class="el-icon-check" style="color: #67C23A;"></i>
+              <div class="stat-icon" style="background: #f0f9ff">
+                <i class="el-icon-check" style="color: #67c23a"></i>
               </div>
               <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>
@@ -183,11 +168,7 @@
           @selection-change="handleSelectionChange"
           class="exception-table"
         >
-          <el-table-column
-            type="selection"
-            width="55"
-            align="center"
-          />
+          <el-table-column type="selection" width="55" align="center" />
 
           <el-table-column
             label="搴忓彿"
@@ -198,25 +179,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,62 +200,64 @@
 
           <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>
           </el-table-column>
 
-          <el-table-column
-            label="濉啓鎯呭喌"
-            width="200"
-            align="center"
-          >
+          <el-table-column label="濉啓鎯呭喌" width="200" align="center">
             <template slot-scope="{ row }">
               <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>
           </el-table-column>
 
-          <el-table-column
-            label="寮傚父浠诲姟"
-            width="280"
-            align="center"
-          >
+          <el-table-column label="寮傚父浠诲姟" width="280" align="center">
             <template slot-scope="{ row }">
               <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 +265,16 @@
 
           <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 +287,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,17 +318,23 @@
 </template>
 
 <script>
+import { tracedeallist } from "@/api/AiCentre/index";
+import { deptTreeSelect } from "@/api/system/user";
+
 export default {
-  name: 'ExceptionList',
+  name: "ExceptionList",
   data() {
     return {
       // 鏌ヨ鍙傛暟
       queryParams: {
-        templateId: '',
-        deptIds: [],
-        dateRange: [],
+        todeptcode: [], // 澶勭悊绉戝缂栧彿鏁扮粍
+        todeptname: "", // 澶勭悊绉戝鍚嶇О
+        templateType: 2, // 浠诲姟妯℃澘ID
+        handleStartTime: "", // 澶勭悊寮�濮嬫椂闂�
+        handleEndTime: "", // 澶勭悊缁撴潫鏃堕棿
+        handleTimeRange: [], // 鏃堕棿鑼冨洿锛岀敤浜庣晫闈㈠睍绀�
         pageNum: 1,
-        pageSize: 10
+        pageSize: 10,
       },
 
       // 鍔犺浇鐘舵��
@@ -368,27 +345,13 @@
 
       // 妯℃澘鍒楄〃
       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: '鑲跨槫绉�' }
-      ],
+      deptList: [],
 
       // 寮傚父鍒楄〃鏁版嵁
       exceptionList: [],
@@ -399,60 +362,134 @@
         totalExceptionCount: 0,
         pendingCount: 0,
         processedCount: 0,
-        todayProcessedCount: 0
+        todayProcessedCount: 0,
       },
 
       // 鏃ユ湡閫夋嫨鍣ㄩ�夐」
       pickerOptions: {
         shortcuts: [
           {
-            text: '鏈�杩戜竴鍛�',
+            text: "鏈�杩戜竴鍛�",
             onClick(picker) {
               const end = new Date();
               const start = new Date();
               start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
-              picker.$emit('pick', [start, end]);
-            }
+              picker.$emit("pick", [start, end]);
+            },
           },
           {
-            text: '鏈�杩戜竴涓湀',
+            text: "鏈�杩戜竴涓湀",
             onClick(picker) {
               const end = new Date();
               const start = new Date();
               start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
-              picker.$emit('pick', [start, end]);
-            }
+              picker.$emit("pick", [start, end]);
+            },
           },
           {
-            text: '鏈�杩戜笁涓湀',
+            text: "鏈�杩戜笁涓湀",
             onClick(picker) {
               const end = new Date();
               const start = new Date();
               start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
-              picker.$emit('pick', [start, end]);
-            }
-          }
+              picker.$emit("pick", [start, end]);
+            },
+          },
         ],
         disabledDate(time) {
           return time.getTime() > Date.now();
-        }
-      }
+        },
+      },
     };
   },
 
   mounted() {
     this.loadData();
+    this.getDeptOptions();
   },
 
   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.templateType) {
+        params.templateType = this.queryParams.templateType;
+      }
+
+      // 澶勭悊鏃堕棿鑼冨洿
+      if (
+        this.queryParams.handleTimeRange &&
+        this.queryParams.handleTimeRange.length === 2
+      ) {
+        params.handleStartTime = this.queryParams.handleTimeRange[0];
+        params.handleEndTime = this.queryParams.handleTimeRange[1];
+      }
+
+      return params;
+    },
+    /** 鏌ヨ绉戝鍒楄〃 */
+    getDeptOptions() {
+      deptTreeSelect()
+        .then((res) => {
+          if (res.code == 200) {
+            this.deptList = this.flattenArray(res.data) || [];
+          }
+        })
+        .catch((error) => {
+          console.error("鑾峰彇绉戝鍒楄〃澶辫触:", error);
+          this.$message.error("鑾峰彇绉戝鍒楄〃澶辫触");
+        });
+    },
+    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;
+    },
     // 鍔犺浇鏁版嵁
     async loadData() {
       this.loading = true;
       try {
-        await Promise.all([
-          this.loadExceptionList(),
-          this.loadOverviewData()
-        ]);
+        await Promise.all([this.loadExceptionList(), this.loadOverviewData()]);
       } finally {
         this.loading = false;
       }
@@ -460,185 +497,70 @@
 
     // 鍔犺浇寮傚父鍒楄〃
     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,60 +572,53 @@
     // 澶勭悊閲嶇疆
     handleReset() {
       this.$refs.queryForm.resetFields();
-      this.queryParams.dateRange = [];
+      this.queryParams.handleTimeRange = [];
       this.queryParams.pageNum = 1;
+      this.queryParams.todeptcode = []; // 閲嶇疆绉戝閫夋嫨
       this.loadData();
     },
 
     // 澶勭悊鎵归噺澶勭悊
     handleBatchProcess() {
       if (this.selectedIds.length === 0) {
-        this.$message.warning('璇峰厛閫夋嫨瑕佸鐞嗙殑寮傚父棰樼洰');
+        this.$message.warning("璇峰厛閫夋嫨瑕佸鐞嗙殑寮傚父棰樼洰");
         return;
       }
 
       // 璺宠浆鍒版壒閲忓鐞嗛〉闈�
       this.$router.push({
-        path: '/satisfaction/exception/batch-process',
+        path: "/Intelligentcenter/batch",
         query: {
-          questionIds: this.selectedIds.join(',')
-        }
+          questionIds: this.selectedIds.join(","),
+          type: this.queryParams.templateType,
+        },
       });
     },
 
     // 澶勭悊瀵煎嚭
     handleExport() {
-      this.$message.success('瀵煎嚭鍔熻兘寮�鍙戜腑...');
+      this.$message.success("瀵煎嚭鍔熻兘寮�鍙戜腑...");
     },
 
     // 鍒锋柊鏁版嵁
     refreshData() {
       this.loadData();
-      this.$message.success('鏁版嵁宸插埛鏂�');
+      this.$message.success("鏁版嵁宸插埛鏂�");
     },
 
     // 澶勭悊閫夋嫨鍙樺寲
     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);
     },
 
     // 澶勭悊鍗曚釜棰樼洰鎵归噺澶勭悊
     handleBatchQuestion(row) {
       this.$router.push({
-        path: '/Intelligentcenter/batch',
+        path: "/Intelligentcenter/batch",
         query: {
-          questionId: row.questionId
-        }
+          questionId: row.scriptid,
+          type: this.queryParams.templateType,
+        },
       });
     },
 
@@ -718,8 +633,8 @@
     handlePageChange(page) {
       this.queryParams.pageNum = page;
       this.loadExceptionList();
-    }
-  }
+    },
+  },
 };
 </script>
 
@@ -732,7 +647,7 @@
   .page-header {
     margin-bottom: 20px;
     padding: 20px;
-    background: linear-gradient(135deg, #5788FE 0%, #66b1ff 100%);
+    background: linear-gradient(135deg, #5788fe 0%, #66b1ff 100%);
     border-radius: 8px;
     color: white;
 
@@ -838,12 +753,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;
         }
       }
 
@@ -915,7 +831,7 @@
             }
 
             &.total {
-              color: #5788FE;
+              color: #5788fe;
             }
           }
         }
@@ -930,7 +846,7 @@
 
         .process-user {
           font-size: 13px;
-          color: #5788FE;
+          color: #5788fe;
           font-weight: 500;
         }
       }
diff --git a/src/views/Satisfaction/configurationmyd/index.vue b/src/views/Satisfaction/configurationmyd/index.vue
index b92dfd9..5029a05 100644
--- a/src/views/Satisfaction/configurationmyd/index.vue
+++ b/src/views/Satisfaction/configurationmyd/index.vue
@@ -481,89 +481,95 @@
         </div>
       </div>
     </div>
-<!-- 閫夐」閰嶇疆瀵硅瘽妗� -->
-<el-dialog
-  title="閫夐」寮傚父鐘舵�侀厤缃�"
-  :visible.sync="optionDialogVisible"
-  width="700px"
-  center
-  :close-on-click-modal="false"
->
-  <div v-if="editingQuestion" class="option-config-wrapper">
-    <div class="dialog-header">
-      <h4>{{ editingQuestion.scriptTopic || '鏃犱富棰�' }}</h4>
-      <p class="dialog-subtitle">{{ editingQuestion.scriptContent }}</p>
-    </div>
+    <!-- 閫夐」閰嶇疆瀵硅瘽妗� -->
+    <el-dialog
+      title="閫夐」寮傚父鐘舵�侀厤缃�"
+      :visible.sync="optionDialogVisible"
+      width="700px"
+      center
+      :close-on-click-modal="false"
+    >
+      <div v-if="editingQuestion" class="option-config-wrapper">
+        <div class="dialog-header">
+          <h4>{{ editingQuestion.scriptTopic || "鏃犱富棰�" }}</h4>
+          <p class="dialog-subtitle">{{ editingQuestion.scriptContent }}</p>
+        </div>
 
-    <div class="option-list">
-      <el-alert
-        v-if="!currentOptions.some(opt => opt.isabnormal === 1)"
-        title="璇疯嚦灏戣缃竴涓紓甯搁�夐」锛堟爣璁颁负寮傚父锛�"
-        type="warning"
-        :closable="false"
-        show-icon
-        style="margin-bottom: 20px;"
-      />
+        <div class="option-list">
+          <el-alert
+            v-if="!currentOptions.some((opt) => opt.isabnormal === 1)"
+            title="璇疯嚦灏戣缃竴涓紓甯搁�夐」锛堟爣璁颁负寮傚父锛�"
+            type="warning"
+            :closable="false"
+            show-icon
+            style="margin-bottom: 20px"
+          />
 
-      <div v-for="(option, index) in currentOptions" :key="index" class="option-item">
-        <el-form
-          :model="option"
-          :rules="optionRules"
-          ref="optionForm"
-          size="small"
-          class="option-form"
-        >
-          <el-row :gutter="12" align="middle">
-            <el-col :span="2">
-              <div class="option-index">#{{ index + 1 }}</div>
-            </el-col>
+          <div
+            v-for="(option, index) in currentOptions"
+            :key="index"
+            class="option-item"
+          >
+            <el-form
+              :model="option"
+              :rules="optionRules"
+              ref="optionForm"
+              size="small"
+              class="option-form"
+            >
+              <el-row :gutter="12" align="middle">
+                <el-col :span="2">
+                  <div class="option-index">#{{ index + 1 }}</div>
+                </el-col>
 
-            <el-col :span="12">
-              <el-form-item prop="targetvalue">
-                <el-input
-                  v-model="option.targetvalue"
-                  placeholder="璇疯緭鍏ラ�夐」鍐呭"
-                  clearable
-                  maxlength="200"
-                  show-word-limit
-                />
-              </el-form-item>
-            </el-col>
+                <el-col :span="12">
+                  <el-form-item prop="targetvalue">
+                    <el-input
+                      v-model="option.targetvalue"
+                      placeholder="璇疯緭鍏ラ�夐」鍐呭"
+                      clearable
+                      maxlength="200"
+                      show-word-limit
+                    />
+                  </el-form-item>
+                </el-col>
 
-            <el-col :span="6">
-              <el-form-item prop="isabnormal">
-                <el-select
-                  v-model="option.isabnormal"
-                  placeholder="閫夋嫨鐘舵��"
-                  style="width: 100%"
-                >
-                  <el-option
-                    v-for="status in abnormalOptions"
-                    :key="status.value"
-                    :label="status.label"
-                    :value="status.value"
-                  >
-                    <el-tag :type="status.type" size="small">{{ status.label }}</el-tag>
-                  </el-option>
-                </el-select>
-              </el-form-item>
-            </el-col>
+                <el-col :span="6">
+                  <el-form-item prop="isabnormal">
+                    <el-select
+                      v-model="option.isabnormal"
+                      placeholder="閫夋嫨鐘舵��"
+                      style="width: 100%"
+                    >
+                      <el-option
+                        v-for="status in abnormalOptions"
+                        :key="status.value"
+                        :label="status.label"
+                        :value="status.value"
+                      >
+                        <el-tag :type="status.type" size="small">{{
+                          status.label
+                        }}</el-tag>
+                      </el-option>
+                    </el-select>
+                  </el-form-item>
+                </el-col>
 
-            <el-col :span="4">
-              <el-button
-                type="danger"
-                icon="el-icon-delete"
-                @click="removeOption(index)"
-                size="small"
-                circle
-                plain
-              />
-            </el-col>
-          </el-row>
-        </el-form>
-      </div>
+                <el-col :span="4">
+                  <el-button
+                    type="danger"
+                    icon="el-icon-delete"
+                    @click="removeOption(index)"
+                    size="small"
+                    circle
+                    plain
+                  />
+                </el-col>
+              </el-row>
+            </el-form>
+          </div>
 
-      <!-- <el-button
+          <!-- <el-button
         type="primary"
         icon="el-icon-plus"
         @click="addNewOption"
@@ -573,16 +579,16 @@
       >
         娣诲姞閫夐」
       </el-button> -->
-    </div>
-  </div>
+        </div>
+      </div>
 
-  <span slot="footer" class="dialog-footer">
-    <el-button @click="optionDialogVisible = false">鍙栨秷</el-button>
-    <el-button type="primary" @click="saveOptions" :loading="savingOptions">
-      淇濆瓨閰嶇疆
-    </el-button>
-  </span>
-</el-dialog>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="optionDialogVisible = false">鍙栨秷</el-button>
+        <el-button type="primary" @click="saveOptions" :loading="savingOptions">
+          淇濆瓨閰嶇疆
+        </el-button>
+      </span>
+    </el-dialog>
     <!-- 棰樼洰棰勮瀵硅瘽妗� -->
     <el-dialog
       title="棰樼洰棰勮"
@@ -848,30 +854,12 @@
           this.voiceCategories.includes(q.scriptAssortid)
         ).length;
       }
+      return 0;
     },
-    // 妫�鏌ラ鐩槸鍚︽湁寮傚父閫夐」
-    hasAbnormalOption(question) {
-      return (question) => {
-        if (!question) return false;
 
-        // 闂嵎妯℃澘
-        if (this.templateForm.templateType === 1) {
-          const options = question.svyLibTemplateTargetoptions || [];
-          return options.some((opt) => opt.isabnormal === 1);
-        }
-        // 璇煶妯℃澘
-        else if (this.templateForm.templateType === 2) {
-          const options = question.ivrLibaScriptTargetoptionList || [];
-          return options.some((opt) => opt.isabnormal === 1);
-        }
-
-        return false;
-      };
-    },
     // 绛涢�夊悗鐨勯鐩垪琛�
     filteredQuestionList() {
       let filtered = this.questionList;
-      console.log(this.questionnaireCategorys);
 
       // 绛涢�夋弧鎰忓害棰樼洰
       if (this.templateForm.templateType === 1) {
@@ -888,7 +876,7 @@
       if (this.queryParams.scriptTopic) {
         const keyword = this.queryParams.scriptTopic.toLowerCase();
         filtered = filtered.filter(
-          (q) => q.scriptTopic && q.scriptTopic.toLowerCase().includes(keyword)
+          (q) => q.scriptTopic && q.criptTopic.toLowerCase().includes(keyword)
         );
       }
 
@@ -988,12 +976,16 @@
       return new Promise((resolve) => {
         getQtemplatelist({ pageSize: 1000 })
           .then((res) => {
-            if (res.code === 200) {
+            console.log(res.rows, "res.rows");
+            if (res.code == 200) {
+              console.log(res.rows, 2);
               this.questionnaireTemplates = (res.rows || []).map((item) => ({
                 id: item.svyid,
                 templateName: item.svyname,
                 isavailable: item.isavailable,
               }));
+              console.log(this.followupTemplates, 3);
+
             } else {
               this.$message.error(res.msg || "鍔犺浇闂嵎妯℃澘澶辫触");
             }
@@ -1012,12 +1004,16 @@
       return new Promise((resolve) => {
         getFollowuplist({ pageSize: 1000 })
           .then((res) => {
-            if (res.code === 200) {
+            console.log(res.rows, "res.rows");
+            if (res.code == 200) {
+              console.log(res.rows, 2);
+
               this.followupTemplates = (res.rows || []).map((item) => ({
                 id: item.id,
                 templateName: item.templateName,
                 isavailable: item.isavailable,
               }));
+              console.log(this.followupTemplates, 3);
             } else {
               this.$message.error(res.msg || "鍔犺浇璇煶妯℃澘澶辫触");
             }
@@ -1215,6 +1211,8 @@
         const index = this.filteredQuestionList.findIndex(
           (q) => q.id === question.id
         );
+        console.log(index, "index");
+
         if (index !== -1) {
           const formRef = this.$refs.configForm && this.$refs.configForm[index];
           if (formRef) {
@@ -1261,24 +1259,61 @@
       const changedItems = this.questionList.filter((q) => q.hasChanges);
       this.changedCount = changedItems.length;
       this.hasChanges = changedItems.length > 0;
+
+      // 寮哄埗鏇存柊瑙嗗浘
+      this.$forceUpdate();
+    },
+
+    /** 妫�鏌ラ鐩槸鍚︽湁寮傚父閫夐」 */
+    checkHasAbnormalOptions(question) {
+      if (this.templateForm.templateType === 1) {
+        return (question.svyLibTemplateTargetoptions || []).some(
+          (opt) => opt.isabnormal === 1
+        );
+      } else if (this.templateForm.templateType === 2) {
+        return (question.ivrLibaScriptTargetoptionList || []).some(
+          (opt) => opt.isabnormal === 1
+        );
+      }
+      return false;
     },
 
     /** 淇濆瓨鍗曚釜棰樼洰閰嶇疆 */
-    async saveSingleConfig(question) {
-      if (!question.hasChanges) return;
+    async saveSingleConfig(question, skipAbnormalCheck = false) {
+      // 妫�鏌ユ槸鍚︽湁鍙樻洿
+      if (!question.hasChanges && !skipAbnormalCheck) {
+        this.$message.info("褰撳墠閰嶇疆鏃犲彉鍖�");
+        return;
+      }
 
-      const index = this.filteredQuestionList.findIndex(
-        (q) => q.id === question.id
-      );
-      console.log(index, "filteredQuestionList");
+      // 妫�鏌ユ槸鍚︽湁寮傚父閫夐」
+      if (!skipAbnormalCheck && !this.checkHasAbnormalOptions(question)) {
+        this.$confirm(
+          "璇ラ鐩病鏈夎缃紓甯搁�夐」锛屽繀椤诲厛閰嶇疆寮傚父閫夐」鎵嶈兘淇濆瓨銆傛槸鍚︾珛鍗抽厤缃紵",
+          "鎻愮ず",
+          {
+            confirmButtonText: "鍘婚厤缃�",
+            cancelButtonText: "鍙栨秷",
+            type: "warning",
+          }
+        )
+          .then(() => {
+            this.openOptionDialog(question);
+          })
+          .catch(() => {});
+        return;
+      }
 
+      const index = this.questionList.findIndex((q) => q.id === question.id);
       if (index === -1) return;
 
       const formRef = this.$refs.configForm && this.$refs.configForm[index];
       if (!formRef) return;
 
-      const valid = await formRef.validate();
-      if (!valid) {
+      // 楠岃瘉琛ㄥ崟
+      try {
+        await formRef.validate();
+      } catch (error) {
         this.$message.warning("璇峰厛瀹屾垚蹇呭~椤�");
         return;
       }
@@ -1339,6 +1374,18 @@
           reportDeptName: reportDeptNames.join(","),
         };
 
+        // 濡傛灉闇�瑕侊紝涔熸洿鏂伴�夐」鏁版嵁
+        if (question.hasChanges && this.templateForm.templateType === 1) {
+          questions[questionIndex].svyLibTemplateTargetoptions =
+            question.svyLibTemplateTargetoptions || [];
+        } else if (
+          question.hasChanges &&
+          this.templateForm.templateType === 2
+        ) {
+          questions[questionIndex].ivrLibaScriptTargetoptionList =
+            question.ivrLibaScriptTargetoptionList || [];
+        }
+
         // 鏇存柊妯℃澘
         updatedTemplateDetail[questionsField] = questions;
 
@@ -1375,7 +1422,6 @@
       }
     },
 
-    /** 澶勭悊淇濆瓨鎴愬姛 */
     /** 澶勭悊淇濆瓨鎴愬姛 */
     handleSaveSuccess(question) {
       // 鍚屾椂鏇存柊棰樼洰椤跺眰瀛楁
@@ -1450,6 +1496,36 @@
     async handleBatchSave() {
       if (!this.hasChanges || this.batchSaving) return;
 
+      // 鑾峰彇鏈夊彉鏇寸殑棰樼洰
+      const changedQuestions = this.questionList.filter((q) => q.hasChanges);
+      if (changedQuestions.length === 0) {
+        this.$message.info("娌℃湁闇�瑕佷繚瀛樼殑閰嶇疆鍙樻洿");
+        return;
+      }
+
+      // 妫�鏌ユ槸鍚︽湁棰樼洰缂哄皯寮傚父閫夐」
+      const questionsWithoutAbnormal = changedQuestions.filter(
+        (q) => !this.checkHasAbnormalOptions(q)
+      );
+
+      if (questionsWithoutAbnormal.length > 0) {
+        this.$confirm(
+          `鏈� ${questionsWithoutAbnormal.length} 涓鐩病鏈夎缃紓甯搁�夐」锛屽繀椤婚厤缃紓甯搁�夐」鍚庢墠鑳戒繚瀛樸�傛槸鍚﹀厛鍘婚厤缃紵`,
+          "鎻愮ず",
+          {
+            confirmButtonText: "鍘婚厤缃�",
+            cancelButtonText: "鍙栨秷",
+            type: "warning",
+          }
+        )
+          .then(() => {
+            // 鎵撳紑绗竴涓病鏈夊紓甯搁�夐」鐨勯鐩殑閰嶇疆瀵硅瘽妗�
+            this.openOptionDialog(questionsWithoutAbnormal[0]);
+          })
+          .catch(() => {});
+        return;
+      }
+
       this.$confirm("纭畾瑕佷繚瀛樻墍鏈変慨鏀硅繃鐨勯厤缃悧锛�", "鎵归噺淇濆瓨", {
         confirmButtonText: "纭畾",
         cancelButtonText: "鍙栨秷",
@@ -1458,24 +1534,20 @@
         .then(async () => {
           this.batchSaving = true;
 
-          const changedQuestions = this.questionList.filter(
-            (q) => q.hasChanges
-          );
           const results = [];
-
           for (const question of changedQuestions) {
             try {
-              await this.saveSingleConfig(question);
+              // 璺宠繃寮傚父妫�鏌ワ紝鍥犱负鍦ㄤ笂闈㈠凡缁忔鏌ヨ繃浜�
+              await this.saveSingleConfig(question, true);
               results.push({
                 id: question.id,
-                success:
-                  !question.hasChanges &&
-                  question.saveStatus?.type === "success",
+                success: !question.hasChanges,
               });
             } catch (error) {
               results.push({
                 id: question.id,
                 success: false,
+                error: error.message,
               });
             }
           }
@@ -1492,6 +1564,11 @@
             this.$message.warning(
               `鎴愬姛淇濆瓨 ${successCount} 涓紝澶辫触 ${failCount} 涓猔
             );
+            // 鍙互鏄剧ず鍏蜂綋鍝簺澶辫触浜�
+            const failedQuestions = results
+              .filter((r) => !r.success)
+              .map((r) => r.id);
+            console.error("淇濆瓨澶辫触鐨勯鐩甀D:", failedQuestions);
           }
         })
         .catch(() => {
@@ -1505,39 +1582,38 @@
       this.previewAnswer = "";
       this.previewVisible = true;
     },
-    /** 妫�鏌ラ鐩槸鍚︽湁寮傚父閫夐」 */
-    checkHasAbnormalOptions(question) {
-      if (this.templateForm.templateType === 1) {
-        return (question.svyLibTemplateTargetoptions || []).some(
-          (opt) => opt.isabnormal === 1
-        );
-      } else if (this.templateForm.templateType === 2) {
-        return (question.ivrLibaScriptTargetoptionList || []).some(
-          (opt) => opt.isabnormal === 1
-        );
-      }
-      return false;
-    },
 
-    /** 鎵撳紑閫夐」绠$悊瀵硅瘽妗� */
+    /** 淇敼閫夐」绠$悊瀵硅瘽妗嗙殑鎵撳紑鏂规硶锛屼繚瀛樺師濮嬮�夐」 */
     openOptionDialog(question) {
       this.editingQuestion = question;
+
+      // 淇濆瓨鍘熷閫夐」鐨勫揩鐓�
+      if (this.templateForm.templateType === 1) {
+        this.editingQuestion.originalOptions = JSON.parse(
+          JSON.stringify(question.svyLibTemplateTargetoptions || [])
+        );
+      } else if (this.templateForm.templateType === 2) {
+        this.editingQuestion.originalOptions = JSON.parse(
+          JSON.stringify(question.ivrLibaScriptTargetoptionList || [])
+        );
+      }
 
       // 澶嶅埗閫夐」鏁版嵁
       if (this.templateForm.templateType === 1) {
         this.currentOptions = JSON.parse(
           JSON.stringify(question.svyLibTemplateTargetoptions || [])
-        ).map((opt) => ({
+        ).map((opt, index) => ({
           ...opt,
-          id: opt.id,
+          id: opt.id || `temp_${Date.now()}_${index}`,
           targetvalue: opt.optioncontent || "",
           isabnormal: opt.isabnormal || 0,
         }));
       } else if (this.templateForm.templateType === 2) {
         this.currentOptions = JSON.parse(
           JSON.stringify(question.ivrLibaScriptTargetoptionList || [])
-        ).map((opt) => ({
+        ).map((opt, index) => ({
           ...opt,
+          id: opt.id || `temp_${Date.now()}_${index}`,
           targetvalue: opt.targetvalue || "",
           isabnormal: opt.isabnormal || 0,
         }));
@@ -1549,7 +1625,7 @@
     /** 娣诲姞鏂伴�夐」 */
     addNewOption() {
       this.currentOptions.push({
-        id: Date.now(), // 涓存椂ID
+        id: `temp_${Date.now()}_${this.currentOptions.length}`,
         targetvalue: "",
         isabnormal: 0,
         isNew: true,
@@ -1558,16 +1634,25 @@
 
     /** 鍒犻櫎閫夐」 */
     removeOption(index) {
-      this.currentOptions.splice(index, 1);
+      this.$confirm("纭畾瑕佸垹闄よ繖涓�夐」鍚楋紵", "鎻愮ず", {
+        confirmButtonText: "纭畾",
+        cancelButtonText: "鍙栨秷",
+        type: "warning",
+      })
+        .then(() => {
+          this.currentOptions.splice(index, 1);
+        })
+        .catch(() => {});
     },
 
     /** 淇濆瓨閫夐」閰嶇疆 */
     async saveOptions() {
       try {
         // 楠岃瘉蹇呭~椤�
-        for (const option of this.currentOptions) {
+        for (let i = 0; i < this.currentOptions.length; i++) {
+          const option = this.currentOptions[i];
           if (!option.targetvalue || option.targetvalue.trim() === "") {
-            this.$message.warning("璇峰~鍐欐墍鏈夐�夐」鍐呭");
+            this.$message.warning(`绗� ${i + 1} 涓�夐」鍐呭涓嶈兘涓虹┖`);
             return;
           }
         }
@@ -1582,6 +1667,27 @@
           return;
         }
 
+        // 鍒ゆ柇閫夐」鏄惁鍙戠敓鍙樺寲
+        let isOptionsChanged = false;
+
+        if (this.templateForm.templateType === 1) {
+          const originalOptions =
+            this.editingQuestion.svyLibTemplateTargetoptions || [];
+          isOptionsChanged = this.checkOptionsChanged(
+            originalOptions,
+            this.currentOptions,
+            "questionnaire"
+          );
+        } else if (this.templateForm.templateType === 2) {
+          const originalOptions =
+            this.editingQuestion.ivrLibaScriptTargetoptionList || [];
+          isOptionsChanged = this.checkOptionsChanged(
+            originalOptions,
+            this.currentOptions,
+            "voice"
+          );
+        }
+
         // 淇濆瓨閫昏緫 - 鏇存柊棰樼洰瀵硅薄鐨勯�夐」鏁版嵁
         if (this.templateForm.templateType === 1) {
           this.editingQuestion.svyLibTemplateTargetoptions =
@@ -1589,14 +1695,24 @@
               ...opt,
               optioncontent: opt.targetvalue,
               isabnormal: opt.isabnormal,
+              // 娓呴櫎涓存椂瀛楁
+              targetvalue: undefined,
+              isNew: undefined,
             }));
         } else if (this.templateForm.templateType === 2) {
           this.editingQuestion.ivrLibaScriptTargetoptionList =
-            this.currentOptions;
+            this.currentOptions.map((opt) => ({
+              ...opt,
+              // 娓呴櫎涓存椂瀛楁
+              isNew: undefined,
+            }));
         }
 
-        // 瑙﹀彂閰嶇疆鍙樻洿妫�鏌�
-        this.handleConfigChange(this.editingQuestion);
+        // 濡傛灉閫夐」鏈夊彉鍖栵紝鍒欒缃鐩负鏈夊彉鏇寸姸鎬�
+        if (isOptionsChanged) {
+          this.editingQuestion.hasChanges = true;
+          this.updateChangedStatus();
+        }
 
         this.$message.success("閫夐」閰嶇疆淇濆瓨鎴愬姛");
         this.optionDialogVisible = false;
@@ -1605,126 +1721,39 @@
         this.$message.error("淇濆瓨閫夐」澶辫触");
       }
     },
-
-    /** 淇敼淇濆瓨鍗曚釜棰樼洰閰嶇疆鏂规硶锛屾坊鍔犲紓甯搁�夐」妫�鏌� */
-    async saveSingleConfig(question) {
-      // 妫�鏌ユ槸鍚︽湁寮傚父閫夐」
-      if (!this.checkHasAbnormalOptions(question)) {
-        this.$confirm("璇ラ鐩病鏈夎缃紓甯搁�夐」锛屾槸鍚﹀厛閰嶇疆閫夐」锛�", "鎻愮ず", {
-          confirmButtonText: "鍘婚厤缃�",
-          cancelButtonText: "鍙栨秷",
-          type: "warning",
-        })
-          .then(() => {
-            this.openOptionDialog(question);
-          })
-          .catch(() => {});
-        return;
+    /** 妫�鏌ラ�夐」鏄惁鍙戠敓鍙樺寲 */
+    checkOptionsChanged(originalOptions, newOptions, templateType) {
+      // 濡傛灉鏁伴噺涓嶅悓锛屽垯涓�瀹氬彉鍖栦簡
+      if (originalOptions.length !== newOptions.length) {
+        return true;
       }
 
-      // 鍘熸湁鐨勪繚瀛橀�昏緫...
-      if (!question.hasChanges) return;
+      // 姣旇緝姣忎釜閫夐」鐨勫唴瀹瑰拰寮傚父鐘舵��
+      for (let i = 0; i < originalOptions.length; i++) {
+        const original = originalOptions[i];
+        const current = newOptions[i];
 
-      const index = this.filteredQuestionList.findIndex(
-        (q) => q.id === question.id
-      );
-
-      if (index === -1) return;
-
-      const formRef = this.$refs.configForm && this.$refs.configForm[index];
-      if (!formRef) return;
-
-      const valid = await formRef.validate();
-      if (!valid) {
-        this.$message.warning("璇峰厛瀹屾垚蹇呭~椤�");
-        return;
-      }
-
-      // 缁х画鍘熸湁鐨勪繚瀛橀�昏緫...
-      question.saving = true;
-      question.saveStatus = null;
-
-      try {
-        // ... 鍘熸湁鐨勪繚瀛橀�昏緫涓嶅彉
-      } catch (error) {
-        // ... 閿欒澶勭悊涓嶅彉
-      } finally {
-        question.saving = false;
-      }
-    },
-
-    /** 鎵归噺淇濆瓨鏃朵篃瑕佹鏌� */
-    async handleBatchSave() {
-      if (!this.hasChanges || this.batchSaving) return;
-
-      // 妫�鏌ユ墍鏈夋湁鍙樻洿鐨勯鐩槸鍚﹂兘鏈夊紓甯搁�夐」
-      const changedQuestions = this.questionList.filter((q) => q.hasChanges);
-      const questionsWithoutAbnormal = changedQuestions.filter(
-        (q) => !this.checkHasAbnormalOptions(q)
-      );
-
-      if (questionsWithoutAbnormal.length > 0) {
-        this.$confirm(
-          `鏈� ${questionsWithoutAbnormal.length} 涓鐩病鏈夎缃紓甯搁�夐」锛岃鍏堥厤缃�夐」銆傛槸鍚︾户缁紵`,
-          "鎻愮ず",
-          {
-            confirmButtonText: "缁х画",
-            cancelButtonText: "鍘婚厤缃�",
-            type: "warning",
+        if (templateType === "questionnaire") {
+          // 闂嵎妯℃澘姣旇緝
+          if (
+            original.optioncontent !== current.targetvalue ||
+            original.isabnormal !== current.isabnormal
+          ) {
+            return true;
           }
-        )
-          .then(() => {
-            // 缁х画鎵ц鎵归噺淇濆瓨
-            this.executeBatchSave(changedQuestions);
-          })
-          .catch(() => {
-            // 鍙互鍦ㄨ繖閲岃烦杞埌绗竴涓病鏈夊紓甯搁�夐」鐨勯鐩�
-            if (questionsWithoutAbnormal.length > 0) {
-              this.openOptionDialog(questionsWithoutAbnormal[0]);
-            }
-          });
-      } else {
-        this.executeBatchSave(changedQuestions);
-      }
-    },
-
-    /** 鎵ц鎵归噺淇濆瓨 */
-    async executeBatchSave(changedQuestions) {
-      this.$confirm("纭畾瑕佷繚瀛樻墍鏈変慨鏀硅繃鐨勯厤缃悧锛�", "鎵归噺淇濆瓨", {
-        confirmButtonText: "纭畾",
-        cancelButtonText: "鍙栨秷",
-        type: "warning",
-      })
-        .then(async () => {
-          this.batchSaving = true;
-
-          const results = [];
-          for (const question of changedQuestions) {
-            try {
-              // 杩欓噷璋冪敤淇敼鍚庣殑saveSingleConfig鏂规硶
-              await this.saveSingleConfig(question);
-              results.push({
-                id: question.id,
-                success:
-                  !question.hasChanges &&
-                  question.saveStatus?.type === "success",
-              });
-            } catch (error) {
-              results.push({
-                id: question.id,
-                success: false,
-              });
-            }
+        } else if (templateType === "voice") {
+          // 璇煶妯℃澘姣旇緝
+          if (
+            original.targetvalue !== current.targetvalue ||
+            original.isabnormal !== current.isabnormal
+          ) {
+            return true;
           }
+        }
+      }
 
-          this.batchSaving = false;
-          // ... 鍚庣画澶勭悊涓嶅彉
-        })
-        .catch(() => {
-          this.batchSaving = false;
-        });
+      return false;
     },
-
     /** 鑾峰彇寮傚父閫夐」缁熻 */
     getAbnormalStats(question) {
       if (this.templateForm.templateType === 1) {
@@ -1746,6 +1775,7 @@
       }
       return { total: 0, abnormal: 0, warning: 0, normal: 0 };
     },
+
     /** 鎼滅储 */
     handleQuery() {
       // 浠呯瓫閫夋樉绀猴紝涓嶉渶瑕侀噸鏂板姞杞�
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/src/views/followvisit/again/index.vue b/src/views/followvisit/again/index.vue
index 5a959d1..4911da7 100644
--- a/src/views/followvisit/again/index.vue
+++ b/src/views/followvisit/again/index.vue
@@ -180,7 +180,7 @@
         <el-col :span="1.5">
           <el-button
             type="primary"
-                        icon="el-icon-plus"
+            icon="el-icon-plus"
             size="medium"
             @click="handleAdd"
             >鏂板</el-button
@@ -289,6 +289,15 @@
           </template>
         </el-table-column>
         <el-table-column
+          label="璇婃柇鍚嶇О"
+          align="center"
+          key="leavediagname"
+          prop="leavediagname"
+          width="120"
+          :show-overflow-tooltip="true"
+        >
+        </el-table-column>
+        <el-table-column
           label="浠诲姟鐘舵��"
           align="center"
           key="sendstate"
@@ -325,15 +334,13 @@
                   >鍙戦�佸け璐�</el-tag
                 >
               </div>
-            <div v-if="scope.row.sendstate == 6">
+              <div v-if="scope.row.sendstate == 6">
                 <el-tag type="success" :disable-transitions="false"
                   >宸插畬鎴�</el-tag
                 >
               </div>
               <div v-if="scope.row.sendstate == 7">
-                <el-tag type="danger" :disable-transitions="false"
-                  >瓒呮椂</el-tag
-                >
+                <el-tag type="danger" :disable-transitions="false">瓒呮椂</el-tag>
               </div>
             </el-tooltip>
           </template>
@@ -472,15 +479,6 @@
         >
         </el-table-column>
 
-        <el-table-column
-          label="璇婃柇鍚嶇О"
-          align="center"
-          key="leavediagname"
-          prop="leavediagname"
-          width="120"
-          :show-overflow-tooltip="true"
-        >
-        </el-table-column>
         <el-table-column
           label="闅忚浜哄憳"
           align="center"
@@ -649,7 +647,7 @@
             </el-form-item>
           </el-col>
         </el-row>
-<el-row >
+        <el-row>
           <el-col :span="8">
             <el-form-item label="杩囨护鍖荤敓" width="100" prop="filterDrname">
               <el-input
@@ -1035,7 +1033,7 @@
           value: 4,
           label: "涓嶆墽琛�",
         },
-         {
+        {
           value: 5,
           label: "鍙戦�佸け璐�",
         },
@@ -1043,7 +1041,7 @@
           value: 6,
           label: "宸插畬鎴�",
         },
-         {
+        {
           value: 7,
           label: "瓒呮椂",
         },
@@ -1214,7 +1212,7 @@
       });
     },
     affiliation() {
-      this.topqueryParams.managementDoctorCode= store.getters.hisUserId;
+      this.topqueryParams.managementDoctorCode = store.getters.hisUserId;
 
       this.getList(1);
     },
@@ -1488,7 +1486,7 @@
             .then((response) => {
               console.log(response);
             })
-              .then(() => {
+            .then(() => {
               this.getList(1);
               this.$modal.msgSuccess("鎮h�呰繃婊ゆ垚鍔�");
             });
@@ -1557,11 +1555,11 @@
     },
     // 璺宠浆璇︽儏椤�
     Seedetails(row) {
-    let type = "";
+      let type = "";
       console.log(row, "rwo");
-        if (row.type == 1) {
-          type = 1;
-        }
+      if (row.type == 1) {
+        type = 1;
+      }
       this.$router.push({
         path: "/followvisit/record/detailpage/",
         query: {
@@ -1787,11 +1785,11 @@
   }
 }
 ::v-deep.leftvlue .el-card__body {
-  background: #F2F8FF;
-  color: #324A9B;
+  background: #f2f8ff;
+  color: #324a9b;
 }
 ::v-deep.leftvlue .el-card__body:hover {
-  background: #3664D9;
+  background: #3664d9;
   color: #fff;
   cursor: pointer; /* 榧犳爣鎮诞鏃跺彉涓烘墜褰� */
 }
diff --git a/src/views/followvisit/discharge/index.vue b/src/views/followvisit/discharge/index.vue
index 9b176e5..9e91878 100644
--- a/src/views/followvisit/discharge/index.vue
+++ b/src/views/followvisit/discharge/index.vue
@@ -210,7 +210,7 @@
       </el-form>
       <el-divider></el-divider>
       <el-row :gutter="10" class="mb8">
-        <!-- <el-col :span="1.5">
+        <el-col :span="1.5">
           <div class="documentf">
             <div class="document">
               <el-button
@@ -223,7 +223,7 @@
               >
             </div>
           </div>
-        </el-col> -->
+        </el-col>
         <el-col :span="1.5">
           <el-button
             type="primary"
@@ -2047,7 +2047,7 @@
         {
           ...this.topqueryParams,
         },
-        `user_${new Date().getTime()}.xlsx`
+        `user_${new Date().getTime()}.xlsx`,
       );
     },
     // 寮傚父鍒楁覆鏌�
diff --git a/src/views/followvisit/record/detailpage/index.vue b/src/views/followvisit/record/detailpage/index.vue
index 955da10..65aeb31 100644
--- a/src/views/followvisit/record/detailpage/index.vue
+++ b/src/views/followvisit/record/detailpage/index.vue
@@ -2286,35 +2286,7 @@
         })
         .catch(() => {});
     },
-    aahandleOptionChange(a, b, c) {
-      const result = c.find((item) => item.optioncontent == a);
-      if (result.nextQuestion == 0) {
-        this.tableDatatop = this.tableDatatop.reduce((acc, item, i) => {
-          acc.push(i > b ? { ...item, astrict: 1 } : item);
-          return acc;
-        }, []);
-      } else {
-        this.tableDatatop = this.tableDatatop.reduce((acc, item, i) => {
-          acc.push(i > b ? { ...item, astrict: 0 } : item);
-          return acc;
-        }, []);
-      }
-      if (this.Voicetype) {
-        var obj = this.tableDatatop[b].ivrTaskScriptTargetoptionList.find(
-          (item) => item.optioncontent == a
-        );
-      } else {
-        var obj = this.tableDatatop[b].svyTaskTemplateTargetoptions.find(
-          (item) => item.optioncontent == a
-        );
-      }
-      if (obj.isabnormal) {
-        this.tableDatatop[b].isabnormal = true;
-      } else {
-        this.tableDatatop[b].isabnormal = false;
-      }
-      this.$forceUpdate();
-    },
+
     handleRadioToggles(questionItem, optionValue) {
       if (!questionItem.matchedtext) {
         questionItem.matchedtext == "";
@@ -2373,7 +2345,13 @@
       this.tableDatatop[questionIndex].showAppendInput =
         selectedOptionObj.appendflag == 1;
       console.log(this.tableDatatop);
-
+      if (
+        selectedOptionObj.nextQuestion !== undefined &&
+        selectedOptionObj.nextQuestion !== null
+      ) {
+        this.tableDatatop[questionIndex].nextScriptno =
+          selectedOptionObj.nextQuestion;
+      }
       // if (!this.tableDatatop[questionIndex].showAppendInput) {
       //   this.tableDatatop[questionIndex].answerps = ""; // 娓呴櫎闄勫姞淇℃伅
       // }
@@ -2443,7 +2421,6 @@
           hiddenByEnd: index === questionIndex + 1 ? false : item.hiddenByEnd,
         }));
       }
-      2;
 
       this.$forceUpdate();
     },
diff --git a/src/views/sfstatistics/percentage/components/ChartDialog.vue b/src/views/sfstatistics/percentage/components/ChartDialog.vue
new file mode 100644
index 0000000..4172811
--- /dev/null
+++ b/src/views/sfstatistics/percentage/components/ChartDialog.vue
@@ -0,0 +1,579 @@
+<template>
+  <el-dialog
+    title="闅忚缁熻瓒嬪娍鍥�"
+    :visible.sync="visible"
+    width="80%"
+    :close-on-click-modal="false"
+    @close="handleClose"
+  >
+    <div class="chart-container">
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <div class="chart-title">闅忚鐘舵�佸垎甯�</div>
+          <div id="pieChart" style="width: 100%; height: 400px"></div>
+        </el-col>
+        <el-col :span="12">
+          <div class="chart-title">闅忚瓒嬪娍鍒嗘瀽</div>
+          <div id="barLineChart" style="width: 100%; height: 400px"></div>
+        </el-col>
+      </el-row>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import * as echarts from 'echarts'
+
+export default {
+  name: 'ChartDialog',
+  props: {
+    visible: {
+      type: Boolean,
+      default: false
+    },
+    data: {
+      type: Array,
+      default: () => []
+    },
+    activeTab: {
+      type: String,
+      default: 'first'
+    }
+  },
+  data() {
+    return {
+      pieChart: null,
+      barLineChart: null
+    }
+  },
+  watch: {
+    visible(newVal) {
+      if (newVal) {
+        this.$nextTick(() => {
+          this.initCharts()
+        })
+      } else {
+        this.destroyCharts()
+      }
+    }
+  },
+  mounted() {
+    if (this.visible) {
+      this.$nextTick(() => {
+        this.initCharts()
+      })
+    }
+  },
+  beforeDestroy() {
+    this.destroyCharts()
+  },
+  methods: {
+    initCharts() {
+      this.initPieChart()
+      this.initBarLineChart()
+    },
+
+    initPieChart() {
+      const pieDom = document.getElementById('pieChart')
+      if (!pieDom) return
+
+      if (this.pieChart) {
+        this.pieChart.dispose()
+      }
+
+      this.pieChart = echarts.init(pieDom)
+
+      // 鏍规嵁褰撳墠tab璁$畻楗煎浘鏁版嵁
+      const pieData = this.getPieChartData()
+
+      const pieOption = {
+        title: {
+          text: '闅忚鐘舵�佸垎甯�',
+          left: 'center',
+          textStyle: {
+            color: '#333',
+            fontSize: 16
+          }
+        },
+        tooltip: {
+          trigger: 'item',
+          formatter: '{a} <br/>{b}: {c} ({d}%)'
+        },
+        legend: {
+          orient: 'vertical',
+          left: 'left',
+          data: pieData.legendData,
+          textStyle: {
+            color: '#666'
+          }
+        },
+        color: ['#FF9D4D', '#36B37E', '#FF5C5C'],
+        series: [
+          {
+            name: '闅忚鐘舵��',
+            type: 'pie',
+            radius: ['40%', '70%'],
+            avoidLabelOverlap: true,
+            itemStyle: {
+              borderRadius: 10,
+              borderColor: '#fff',
+              borderWidth: 2
+            },
+            label: {
+              show: true,
+              formatter: '{b}: {c} ({d}%)',
+              color: '#333'
+            },
+            emphasis: {
+              label: {
+                show: true,
+                fontSize: '18',
+                fontWeight: 'bold'
+              },
+              itemStyle: {
+                shadowBlur: 10,
+                shadowOffsetX: 0,
+                shadowColor: 'rgba(0, 0, 0, 0.5)'
+              }
+            },
+            data: pieData.seriesData
+          }
+        ]
+      }
+
+      this.pieChart.setOption(pieOption)
+      window.addEventListener('resize', this.resizePieChart)
+    },
+
+    getPieChartData() {
+      let legendData = []
+      let seriesData = []
+
+      if (this.activeTab === 'first') {
+        legendData = ['寰呴殢璁�', '闅忚鎴愬姛', '闅忚澶辫触']
+        const followUpData = {
+          pending: 0,
+          success: 0,
+          fail: 0
+        }
+
+        this.data.forEach((item) => {
+          followUpData.pending += item.pendingFollowUp || 0
+          followUpData.success += item.followUpSuccess || 0
+          followUpData.fail += item.followUpFail || 0
+        })
+
+        seriesData = [
+          { value: followUpData.pending, name: '寰呴殢璁�' },
+          { value: followUpData.success, name: '闅忚鎴愬姛' },
+          { value: followUpData.fail, name: '闅忚澶辫触' }
+        ]
+      } else if (this.activeTab === 'second') {
+        legendData = ['寰呴殢璁�(鍐嶆)', '闅忚鎴愬姛(鍐嶆)', '闅忚澶辫触(鍐嶆)']
+        const followUpData = {
+          pending: 0,
+          success: 0,
+          fail: 0
+        }
+
+        this.data.forEach((item) => {
+          followUpData.pending += item.pendingFollowUpAgain || 0
+          followUpData.success += item.followUpSuccessAgain || 0
+          followUpData.fail += item.followUpFailAgain || 0
+        })
+
+        seriesData = [
+          { value: followUpData.pending, name: '寰呴殢璁�(鍐嶆)' },
+          { value: followUpData.success, name: '闅忚鎴愬姛(鍐嶆)' },
+          { value: followUpData.fail, name: '闅忚澶辫触(鍐嶆)' }
+        ]
+      } else if (this.activeTab === 'continued') {
+        legendData = ['鎶ょ悊瀹屾垚', '鎶ょ悊杩涜涓�', '鎶ょ悊鏈紑濮�']
+        const careData = {
+          completed: 0,
+          inProgress: 0,
+          notStarted: 0
+        }
+
+        this.data.forEach((item) => {
+          careData.completed += item.careCompleted || 0
+          careData.inProgress += item.careInProgress || 0
+          careData.notStarted += item.careNotStarted || 0
+        })
+
+        seriesData = [
+          { value: careData.completed, name: '鎶ょ悊瀹屾垚' },
+          { value: careData.inProgress, name: '鎶ょ悊杩涜涓�' },
+          { value: careData.notStarted, name: '鎶ょ悊鏈紑濮�' }
+        ]
+      }
+
+      return { legendData, seriesData }
+    },
+
+    initBarLineChart() {
+      const barDom = document.getElementById('barLineChart')
+      if (!barDom) return
+
+      if (this.barLineChart) {
+        this.barLineChart.dispose()
+      }
+
+      this.barLineChart = echarts.init(barDom)
+
+      // 鍑嗗鏁版嵁
+      const chartData = this.getBarLineChartData()
+
+      const option = {
+        title: {
+          text: `${chartData.title}瓒嬪娍`,
+          left: 'center',
+          textStyle: {
+            color: '#333',
+            fontSize: 16
+          }
+        },
+        tooltip: {
+          trigger: 'axis',
+          axisPointer: {
+            type: 'cross',
+            crossStyle: {
+              color: '#999'
+            }
+          }
+        },
+        legend: {
+          data: chartData.legendData,
+          top: 'bottom',
+          textStyle: {
+            color: '#666'
+          }
+        },
+        color: chartData.colors,
+        xAxis: {
+          type: 'category',
+          data: chartData.categories,
+          axisLabel: {
+            interval: 0,
+            rotate: 30,
+            color: '#666'
+          },
+          axisLine: {
+            lineStyle: {
+              color: '#ddd'
+            }
+          }
+        },
+        yAxis: [
+          {
+            type: 'value',
+            name: chartData.yAxisName1,
+            min: 0,
+            axisLabel: {
+              color: '#666'
+            },
+            axisLine: {
+              lineStyle: {
+                color: '#ddd'
+              }
+            },
+            splitLine: {
+              lineStyle: {
+                color: '#f0f0f0'
+              }
+            }
+          },
+          {
+            type: 'value',
+            name: '鐧惧垎姣�(%)',
+            min: 0,
+            max: 100,
+            axisLabel: {
+              color: '#666',
+              formatter: '{value}%'
+            },
+            axisLine: {
+              lineStyle: {
+                color: '#ddd'
+              }
+            },
+            splitLine: {
+              show: false
+            }
+          }
+        ],
+        series: chartData.series,
+        grid: {
+          top: '15%',
+          left: '3%',
+          right: '4%',
+          bottom: '15%',
+          containLabel: true
+        }
+      }
+
+      this.barLineChart.setOption(option)
+      window.addEventListener('resize', this.resizeBarLineChart)
+    },
+
+    getBarLineChartData() {
+      const categories = this.data.map(
+        (item) => item.leavehospitaldistrictname || item.deptname
+      )
+
+      let title = '绉戝/鐥呭尯'
+      let yAxisName1 = '浜烘'
+      let legendData = []
+      let colors = []
+      let series = []
+
+      if (this.activeTab === 'first') {
+        title = '棣栨闅忚'
+        yAxisName1 = '浜烘'
+        legendData = ['鍑洪櫌浜烘', '搴旈殢璁夸汉娆�', '闅忚鐜�(%)', '鍙婃椂鐜�(%)']
+        colors = ['#5470C6', '#91CC75', '#EE6666', '#9A60B4']
+
+        const dischargeData = this.data.map((item) => item.dischargeCount || 0)
+        const followUpData = this.data.map((item) => item.followUpNeeded || 0)
+        const followUpRateData = this.data.map((item) => {
+          if (!item.followUpRate) return 0
+          const rateStr = String(item.followUpRate).replace('%', '')
+          return parseFloat(rateStr) || 0
+        })
+        const timelyRateData = this.data.map((item) =>
+          item.rate ? (Number(item.rate) * 100).toFixed(2) : 0
+        )
+
+        series = [
+          {
+            name: '鍑洪櫌浜烘',
+            type: 'bar',
+            barWidth: '25%',
+            data: dischargeData,
+            itemStyle: {
+              borderRadius: [4, 4, 0, 0]
+            }
+          },
+          {
+            name: '搴旈殢璁夸汉娆�',
+            type: 'bar',
+            barWidth: '25%',
+            data: followUpData,
+            itemStyle: {
+              borderRadius: [4, 4, 0, 0]
+            }
+          },
+          {
+            name: '闅忚鐜�(%)',
+            type: 'line',
+            yAxisIndex: 1,
+            data: followUpRateData,
+            symbolSize: 8,
+            lineStyle: {
+              width: 3
+            },
+            markLine: {
+              silent: true,
+              data: [
+                {
+                  yAxis: 80,
+                  lineStyle: {
+                    color: '#EE6666',
+                    type: 'dashed'
+                  }
+                }
+              ]
+            }
+          },
+          {
+            name: '鍙婃椂鐜�(%)',
+            type: 'line',
+            yAxisIndex: 1,
+            data: timelyRateData,
+            symbolSize: 8,
+            lineStyle: {
+              width: 3,
+              type: 'dotted'
+            },
+            markLine: {
+              silent: true,
+              data: [
+                {
+                  yAxis: 90,
+                  lineStyle: {
+                    color: '#9A60B4',
+                    type: 'dashed'
+                  }
+                }
+              ]
+            }
+          }
+        ]
+      } else if (this.activeTab === 'second') {
+        title = '鍐嶆闅忚'
+        yAxisName1 = '浜烘'
+        legendData = ['鍑洪櫌浜烘', '搴旈殢璁夸汉娆�', '闅忚鐜�(%)']
+        colors = ['#5470C6', '#91CC75', '#EE6666']
+
+        const dischargeData = this.data.map((item) => item.dischargeCount || 0)
+        const followUpData = this.data.map((item) => item.followUpNeeded || 0)
+        const followUpRateAgainData = this.data.map((item) => {
+          if (!item.followUpRateAgain) return 0
+          const rateStr = String(item.followUpRateAgain).replace('%', '')
+          return parseFloat(rateStr) || 0
+        })
+
+        series = [
+          {
+            name: '鍑洪櫌浜烘',
+            type: 'bar',
+            barWidth: '25%',
+            data: dischargeData,
+            itemStyle: {
+              borderRadius: [4, 4, 0, 0]
+            }
+          },
+          {
+            name: '搴旈殢璁夸汉娆�',
+            type: 'bar',
+            barWidth: '25%',
+            data: followUpData,
+            itemStyle: {
+              borderRadius: [4, 4, 0, 0]
+            }
+          },
+          {
+            name: '闅忚鐜�(%)',
+            type: 'line',
+            yAxisIndex: 1,
+            data: followUpRateAgainData,
+            symbolSize: 8,
+            lineStyle: {
+              width: 3
+            },
+            markLine: {
+              silent: true,
+              data: [
+                {
+                  yAxis: 80,
+                  lineStyle: {
+                    color: '#EE6666',
+                    type: 'dashed'
+                  }
+                }
+              ]
+            }
+          }
+        ]
+      } else if (this.activeTab === 'continued') {
+        title = '寤剁画鎶ょ悊'
+        yAxisName1 = '浜烘'
+        legendData = ['寤剁画鎶ょ悊浜烘', '鎶ょ悊瀹屾垚', '瀹屾垚鐜�(%)']
+        colors = ['#5470C6', '#91CC75', '#EE6666']
+
+        const continuedCareData = this.data.map((item) => item.continuedCareCount || 0)
+        const careCompletedData = this.data.map((item) => item.careCompleted || 0)
+        const completionRateData = this.data.map((item) => {
+          if (!item.completionRate) return 0
+          const rateStr = String(item.completionRate).replace('%', '')
+          return parseFloat(rateStr) || 0
+        })
+
+        series = [
+          {
+            name: '寤剁画鎶ょ悊浜烘',
+            type: 'bar',
+            barWidth: '25%',
+            data: continuedCareData,
+            itemStyle: {
+              borderRadius: [4, 4, 0, 0]
+            }
+          },
+          {
+            name: '鎶ょ悊瀹屾垚',
+            type: 'bar',
+            barWidth: '25%',
+            data: careCompletedData,
+            itemStyle: {
+              borderRadius: [4, 4, 0, 0]
+            }
+          },
+          {
+            name: '瀹屾垚鐜�(%)',
+            type: 'line',
+            yAxisIndex: 1,
+            data: completionRateData,
+            symbolSize: 8,
+            lineStyle: {
+              width: 3
+            },
+            markLine: {
+              silent: true,
+              data: [
+                {
+                  yAxis: 85,
+                  lineStyle: {
+                    color: '#EE6666',
+                    type: 'dashed'
+                  }
+                }
+              ]
+            }
+          }
+        ]
+      }
+
+      return {
+        title,
+        yAxisName1,
+        categories,
+        legendData,
+        colors,
+        series
+      }
+    },
+
+    resizePieChart() {
+      if (this.pieChart) {
+        this.pieChart.resize()
+      }
+    },
+
+    resizeBarLineChart() {
+      if (this.barLineChart) {
+        this.barLineChart.resize()
+      }
+    },
+
+    destroyCharts() {
+      if (this.pieChart) {
+        this.pieChart.dispose()
+        this.pieChart = null
+      }
+      if (this.barLineChart) {
+        this.barLineChart.dispose()
+        this.barLineChart = null
+      }
+      window.removeEventListener('resize', this.resizePieChart)
+      window.removeEventListener('resize', this.resizeBarLineChart)
+    },
+
+    handleClose() {
+      this.destroyCharts()
+      this.$emit('close')
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.chart-container {
+  .chart-title {
+    text-align: center;
+    font-size: 16px;
+    font-weight: bold;
+    margin-bottom: 20px;
+    color: #333;
+  }
+}
+</style>
diff --git a/src/views/sfstatistics/percentage/components/ContinuedCare.vue b/src/views/sfstatistics/percentage/components/ContinuedCare.vue
new file mode 100644
index 0000000..2cf6f31
--- /dev/null
+++ b/src/views/sfstatistics/percentage/components/ContinuedCare.vue
@@ -0,0 +1,633 @@
+<template>
+  <div class="continued-care">
+    <div class="your-table-container">
+      <el-table
+        v-loading="loading"
+        :data="tableData"
+        :border="true"
+        show-summary
+        :summary-method="getSummaries"
+      >
+        <!-- 琛ㄦ牸鍒楀畾涔� -->
+        <el-table-column
+          label="搴忓彿"
+          type="index"
+          align="center"
+          width="60"
+        />
+
+        <el-table-column
+          label="鐥呭尯鍚嶇О"
+          align="center"
+          prop="wardName"
+          width="200"
+          :show-overflow-tooltip="true"
+        />
+
+        <el-table-column
+          label="宸插欢缁暟閲�"
+          align="center"
+          prop="continuedCount"
+        >
+          <template slot-scope="scope">
+            <el-button
+              size="medium"
+              type="text"
+              @click="handleViewDetails(scope.row, 'continued', '宸插欢缁垪琛�')"
+            >
+              <span class="button-zx">{{ scope.row.continuedCount }}</span>
+            </el-button>
+          </template>
+        </el-table-column>
+
+        <el-table-column
+          label="鏈欢缁暟閲�"
+          align="center"
+          prop="unContinuedCount"
+        >
+          <template slot-scope="scope">
+            <el-button
+              size="medium"
+              type="text"
+              @click="handleViewDetails(scope.row, 'uncontinued', '鏈欢缁垪琛�')"
+            >
+              <span class="button-zx">{{ scope.row.unContinuedCount }}</span>
+            </el-button>
+          </template>
+        </el-table-column>
+
+        <el-table-column
+          label="寤剁画鐜�"
+          align="center"
+          prop="continuedRate"
+          width="120"
+        />
+
+        <!-- <el-table-column
+          label="鎿嶄綔"
+          align="center"
+          width="150"
+        >
+          <template slot-scope="scope">
+            <el-button
+              size="small"
+              type="primary"
+              @click="handleRowClick(scope.row)"
+            >
+              鏌ョ湅鎶ゅ+璇︽儏
+            </el-button>
+          </template>
+        </el-table-column> -->
+      </el-table>
+    </div>
+
+    <!-- 鎶ゅ+璇︽儏寮圭獥 -->
+    <el-dialog
+      title="鎶ゅ+寤剁画鎶ょ悊璇︽儏"
+      :visible.sync="nurseDialogVisible"
+      width="80%"
+      :close-on-click-modal="false"
+    >
+      <div v-if="currentWardData">
+        <el-table
+          v-loading="nurseLoading"
+          :data="nurseData"
+          :border="true"
+        >
+          <el-table-column
+            label="鎶ゅ+濮撳悕"
+            prop="nurseName"
+            align="center"
+            width="120"
+          />
+          <el-table-column
+            label="绉戝"
+            prop="deptName"
+            align="center"
+            width="150"
+          />
+          <el-table-column
+            label="宸插欢缁暟閲�"
+            prop="continuedCount"
+            align="center"
+          />
+          <el-table-column
+            label="鏈欢缁暟閲�"
+            prop="unContinuedCount"
+            align="center"
+          />
+          <el-table-column
+            label="寤剁画鐜�"
+            prop="continuedRate"
+            align="center"
+            width="120"
+          />
+        </el-table>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { getContinueNerseCount, getNurseContinuedDetail } from "@/api/system/user";
+import ExcelJS from "exceljs";
+import { saveAs } from "file-saver";
+
+export default {
+  name: "ContinuedCare",
+  props: {
+    queryParams: {
+      type: Object,
+      required: true,
+    },
+    flatArrayhospit: {
+      type: Array,
+      default: () => [],
+    },
+    flatArraydept: {
+      type: Array,
+      default: () => [],
+    },
+    options: {
+      type: Array,
+      default: () => [],
+    },
+    orgname: {
+      type: String,
+      default: "",
+    },
+  },
+  data() {
+    return {
+      tableData: [],
+      loading: false,
+      nurseDialogVisible: false,
+      nurseLoading: false,
+      currentWardData: null,
+      nurseData: [],
+      originalData: {},
+      totalData: {
+        continued: 0,
+        uncontinued: 0
+      }
+    };
+  },
+  methods: {
+    loadData() {
+      this.loading = true;
+
+      const params = {
+        leavehospitaldistrictcodes:
+          this.queryParams.leavehospitaldistrictcodes.includes("all")
+            ? this.getAllWardCodes()
+            : this.queryParams.leavehospitaldistrictcodes,
+        deptcodes: this.queryParams.deptcodes.includes("all")
+          ? this.getAllDeptCodes()
+          : this.queryParams.deptcodes,
+
+      };
+
+      delete params.leavehospitaldistrictcodes.all;
+      delete params.deptcodes.all;
+
+      getContinueNerseCount(params)
+        .then((response) => {
+          this.originalData = response.data;
+          this.processData(response.data);
+        })
+        .catch((error) => {
+          console.error("鑾峰彇寤剁画鎶ょ悊鏁版嵁澶辫触:", error);
+          this.$message.error("鑾峰彇寤剁画鎶ょ悊鏁版嵁澶辫触");
+        })
+        .finally(() => {
+          this.loading = false;
+        });
+    },
+
+    processData(data) {
+      this.totalData = {
+        continued: data.宸插欢缁�绘暟閲� || 0,
+        uncontinued: data.鏈欢缁�绘暟閲� || 0
+      };
+
+      const processedData = [];
+
+      if (data.璇︽儏 && Array.isArray(data.璇︽儏)) {
+        data.璇︽儏.forEach((item) => {
+          // 鎻愬彇鐥呭尯鍚嶇О鍜屾暟鎹�
+          Object.keys(item).forEach(key => {
+            if (key.startsWith('宸插欢缁璤')) {
+              const wardName = key.replace('宸插欢缁璤', '');
+              const continuedCount = item[key];
+              const unContinuedCount = item[`鏈欢缁璤${wardName}`] || 0;
+              const total = continuedCount + unContinuedCount;
+              const continuedRate = total > 0 ? ((continuedCount / total) * 100).toFixed(2) + '%' : '0.00%';
+
+              processedData.push({
+                wardName,
+                continuedCount,
+                unContinuedCount,
+                continuedRate,
+                originalData: item
+              });
+            }
+          });
+        });
+      }
+
+      // 鎺掑簭
+      this.tableData = this.customSort(processedData);
+    },
+
+    getAllWardCodes() {
+      return this.flatArrayhospit
+        .filter((item) => item.value !== "all")
+        .map((item) => item.value);
+    },
+
+    getAllDeptCodes() {
+      return this.flatArraydept
+        .filter((item) => item.value !== "all")
+        .map((item) => item.value);
+    },
+
+    customSort(data) {
+      const order = [
+        "涓�", "浜�", "涓�", "鍥�", "浜�", "鍏�", "涓�", "鍏�", "涔�", "鍗�",
+        "鍗佷竴", "鍗佷簩", "鍗佷笁", "鍗佸洓", "鍗佷簲", "鍗佸叚", "鍗佷竷", "鍗佸叓", "鍗佷節", "浜屽崄",
+        "浜屽崄涓�", "浜屽崄浜�", "浜屽崄涓�", "浜屽崄鍥�", "浜屽崄浜�", "浜屽崄鍏�", "浜屽崄涓�", "浜屽崄鍏�", "浜屽崄涔�", "涓夊崄",
+        "涓夊崄涓�", "涓夊崄浜�", "涓夊崄涓�", "涓夊崄鍥�", "涓夊崄浜�", "涓夊崄鍏�", "涓夊崄涓�", "涓夊崄鍏�", "涓夊崄涔�", "鍥涘崄",
+        "鍥涘崄涓�", "鍥涘崄浜�", "鍥涘崄涓�", "鍥涘崄鍥�", "鍥涘崄浜�"
+      ];
+
+      return data.sort((a, b) => {
+        const getIndex = (name) => {
+          if (!name || typeof name !== "string") return -1;
+          const chineseMatch = name.match(/^(\d+)-/);
+          if (chineseMatch && chineseMatch[1]) {
+            const num = parseInt(chineseMatch[1], 10);
+            if (num >= 1 && num <= 45) {
+              return num - 1;
+            }
+          }
+
+          // 灏濊瘯鍖归厤涓枃鏁板瓧
+          for (let i = 0; i < order.length; i++) {
+            if (name.includes(order[i])) {
+              return i;
+            }
+          }
+          return -1;
+        };
+
+        const indexA = getIndex(a.wardName);
+        const indexB = getIndex(b.wardName);
+
+        if (indexA === -1 && indexB === -1) {
+          return (a.wardName || "").localeCompare(b.wardName || "");
+        }
+        if (indexA === -1) return 1;
+        if (indexB === -1) return -1;
+        return indexA - indexB;
+      });
+    },
+
+    getSummaries(param) {
+      const { columns, data } = param;
+      const sums = [];
+
+      columns.forEach((column, index) => {
+        if (index === 0) {
+          sums[index] = "鍚堣";
+          return;
+        }
+
+        if (index === 1) { // 鐥呭尯鍚嶇О鍒�
+          sums[index] = "/";
+          return;
+        }
+
+        if (index === 2) { // 宸插欢缁暟閲忓悎璁�
+          const totalContinued = this.tableData.reduce((sum, item) => sum + item.continuedCount, 0);
+          sums[index] = this.formatNumber(totalContinued);
+        } else if (index === 3) { // 鏈欢缁暟閲忓悎璁�
+          const totalUnContinued = this.tableData.reduce((sum, item) => sum + item.unContinuedCount, 0);
+          sums[index] = this.formatNumber(totalUnContinued);
+        } else if (index === 4) { // 寤剁画鐜囧钩鍧囧��
+          const totalContinued = this.tableData.reduce((sum, item) => sum + item.continuedCount, 0);
+          const totalUnContinued = this.tableData.reduce((sum, item) => sum + item.unContinuedCount, 0);
+          const total = totalContinued + totalUnContinued;
+          const avgRate = total > 0 ? ((totalContinued / total) * 100).toFixed(2) + '%' : '0.00%';
+          sums[index] = avgRate;
+        } else {
+          sums[index] = "";
+        }
+      });
+
+      return sums;
+    },
+
+    formatNumber(num) {
+      if (isNaN(num)) return "-";
+      return Number.isInteger(num) ? num.toString() : num.toFixed(0);
+    },
+
+    handleViewDetails(row, type, titleSuffix) {
+      const title = `${row.wardName}${titleSuffix}`;
+      // 杩欓噷闇�瑕佹牴鎹綘鐨勫疄闄呮儏鍐佃幏鍙栬鎯呮暟鎹�
+      // 浣犲彲浠ヤ粠row.originalData涓幏鍙栵紝鎴栬�呰皟鐢ㄦ柊鐨凙PI
+      const detailData = this.getMockDetailData(row, type);
+      this.$emit("view-details", detailData, title);
+    },
+
+    handleRowClick(row) {
+      this.currentWardData = row;
+      this.nurseDialogVisible = true;
+      this.loadNurseData(row.wardName);
+    },
+
+    async loadNurseData(wardName) {
+      this.nurseLoading = true;
+      try {
+        const params = {
+          wardName: wardName,
+          startTime: this.queryParams.startTime,
+          endTime: this.queryParams.endTime
+        };
+
+        const response = await getNurseContinuedDetail(params);
+        this.nurseData = this.processNurseData(response.data);
+      } catch (error) {
+        console.error("鑾峰彇鎶ゅ+璇︽儏澶辫触:", error);
+        this.$message.error("鑾峰彇鎶ゅ+璇︽儏澶辫触");
+      } finally {
+        this.nurseLoading = false;
+      }
+    },
+
+    processNurseData(data) {
+      // 鏍规嵁浣犵殑瀹為檯API鍝嶅簲缁撴瀯澶勭悊鏁版嵁
+      // 杩欓噷鏄竴涓ず渚�
+      return [
+        {
+          nurseName: "鎶ゅ+A",
+          deptName: this.currentWardData.wardName,
+          continuedCount: Math.floor(this.currentWardData.continuedCount * 0.3),
+          unContinuedCount: Math.floor(this.currentWardData.unContinuedCount * 0.3),
+          continuedRate: "75.00%"
+        },
+        {
+          nurseName: "鎶ゅ+B",
+          deptName: this.currentWardData.wardName,
+          continuedCount: Math.floor(this.currentWardData.continuedCount * 0.4),
+          unContinuedCount: Math.floor(this.currentWardData.unContinuedCount * 0.4),
+          continuedRate: "80.00%"
+        },
+        {
+          nurseName: "鎶ゅ+C",
+          deptName: this.currentWardData.wardName,
+          continuedCount: Math.floor(this.currentWardData.continuedCount * 0.3),
+          unContinuedCount: Math.floor(this.currentWardData.unContinuedCount * 0.3),
+          continuedRate: "70.00%"
+        }
+      ];
+    },
+
+    getMockDetailData(row, type) {
+      // 妯℃嫙璇︽儏鏁版嵁锛屽疄闄呭簲璇ヨ皟鐢ˋPI
+      const detailData = [];
+      const count = type === 'continued' ? row.continuedCount : row.unContinuedCount;
+
+      for (let i = 1; i <= Math.min(count, 10); i++) {
+        detailData.push({
+          sendname: `鎮h��${i}`,
+          taskName: `${row.wardName}寤剁画鎶ょ悊`,
+          sendstate: type === 'continued' ? 6 : 2,
+          preachform: ["浜哄伐闅忚", "鐢佃瘽闅忚"],
+          visitTime: "2024-01-15 10:00:00",
+          finishtime: type === 'continued' ? "2024-01-15 11:00:00" : "",
+          endtime: "2024-01-10 09:00:00",
+          nurseName: "鎶ゅ+A",
+          drname: "鍖荤敓A",
+          excep: 1,
+          suggest: 2,
+          templatename: "寤剁画鎶ょ悊鏈嶅姟妯℃澘",
+          remark: type === 'continued' ? "宸插畬鎴愬欢缁姢鐞�" : "鏈紑濮嬪欢缁姢鐞�",
+          bankcardno: "宸插畬鎴�"
+        });
+      }
+
+      return detailData;
+    },
+
+    async exportTable() {
+      try {
+        let dateRangeString = "";
+        let sheetNameSuffix = "";
+
+        if (
+          this.queryParams.dateRange &&
+          this.queryParams.dateRange.length === 2
+        ) {
+          const startDateStr = this.queryParams.dateRange[0];
+          const endDateStr = this.queryParams.dateRange[1];
+          const formatDateForDisplay = (dateTimeStr) => {
+            return dateTimeStr.split(" ")[0];
+          };
+          const startDateFormatted = formatDateForDisplay(startDateStr);
+          const endDateFormatted = formatDateForDisplay(endDateStr);
+          dateRangeString = `${startDateFormatted}鑷�${endDateFormatted}`;
+          sheetNameSuffix = `${startDateFormatted}鑷�${endDateFormatted}`;
+        } else {
+          const now = new Date();
+          const currentMonth = now.getMonth() + 1;
+          dateRangeString = `${currentMonth}鏈坄;
+          sheetNameSuffix = `${currentMonth}鏈坄;
+        }
+
+        const excelName = `寤剁画鎶ょ悊缁熻琛╛${dateRangeString}.xlsx`;
+        const worksheetName = `寤剁画鎶ょ悊缁熻_${sheetNameSuffix}`;
+
+        if (!this.tableData || this.tableData.length === 0) {
+          this.$message.warning("鏆傛棤寤剁画鎶ょ悊鏁版嵁鍙鍑�");
+          return false;
+        }
+
+        const workbook = new ExcelJS.Workbook();
+        const worksheet = workbook.addWorksheet(worksheetName);
+
+        this.buildExportSheet(worksheet, sheetNameSuffix);
+
+        const buffer = await workbook.xlsx.writeBuffer();
+        const blob = new Blob([buffer], {
+          type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
+        });
+        saveAs(blob, excelName);
+
+        this.$message.success("瀵煎嚭鎴愬姛");
+        return true;
+      } catch (error) {
+        console.error("瀵煎嚭澶辫触:", error);
+        this.$message.error(`瀵煎嚭澶辫触: ${error.message}`);
+        return false;
+      }
+    },
+
+    buildExportSheet(worksheet, sheetNameSuffix) {
+      const titleStyle = {
+        font: {
+          name: "寰蒋闆呴粦",
+          size: 16,
+          bold: true,
+          color: { argb: "FF000000" },
+        },
+        fill: {
+          type: "pattern",
+          pattern: "solid",
+          fgColor: { argb: "FFE6F3FF" },
+        },
+        alignment: { vertical: "middle", horizontal: "center", wrapText: true },
+        border: {
+          top: { style: "thin", color: { argb: "FFD0D0D0" } },
+          left: { style: "thin", color: { argb: "FFD0D0D0" } },
+          bottom: { style: "thin", color: { argb: "FFD0D0D0" } },
+          right: { style: "thin", color: { argb: "FFD0D0D0" } },
+        },
+      };
+
+      const headerStyle = {
+        font: {
+          name: "寰蒋闆呴粦",
+          size: 11,
+          bold: true,
+          color: { argb: "FF000000" },
+        },
+        fill: {
+          type: "pattern",
+          pattern: "solid",
+          fgColor: { argb: "FFF5F7FA" },
+        },
+        alignment: { vertical: "middle", horizontal: "center", wrapText: true },
+        border: {
+          top: { style: "thin", color: { argb: "FFD0D0D0" } },
+          left: { style: "thin", color: { argb: "FFD0D0D0" } },
+          bottom: { style: "thin", color: { argb: "FFD0D0D0" } },
+          right: { style: "thin", color: { argb: "FFD0D0D0" } },
+        },
+      };
+
+      const cellStyle = {
+        font: { name: "瀹嬩綋", size: 10, color: { argb: "FF000000" } },
+        alignment: { vertical: "middle", horizontal: "center" },
+        border: {
+          top: { style: "thin", color: { argb: "FFD0D0D0" } },
+          left: { style: "thin", color: { argb: "FFD0D0D0" } },
+          bottom: { style: "thin", color: { argb: "FFD0D0D0" } },
+          right: { style: "thin", color: { argb: "FFD0D0D0" } },
+        },
+      };
+
+      const summaryStyle = {
+        font: {
+          name: "瀹嬩綋",
+          size: 10,
+          bold: true,
+          color: { argb: "FF409EFF" },
+        },
+        fill: {
+          type: "pattern",
+          pattern: "solid",
+          fgColor: { argb: "FFF5F7FA" },
+        },
+        alignment: { vertical: "middle", horizontal: "center" },
+        border: {
+          top: { style: "thin", color: { argb: "FFD0D0D0" } },
+          left: { style: "thin", color: { argb: "FFD0D0D0" } },
+          bottom: { style: "thin", color: { argb: "FFD0D0D0" } },
+          right: { style: "thin", color: { argb: "FFD0D0D0" } },
+        },
+      };
+
+      // 娣诲姞鏍囬琛�
+      worksheet.mergeCells(1, 1, 1, 6);
+      const titleCell = worksheet.getCell(1, 1);
+      titleCell.value = `寤剁画鎶ょ悊缁熻琛╛${sheetNameSuffix}`;
+      titleCell.style = titleStyle;
+      worksheet.getRow(1).height = 35;
+
+      // 琛ㄥご
+      const headers = ["搴忓彿", "鐥呭尯鍚嶇О", "宸插欢缁暟閲�", "鏈欢缁暟閲�", "寤剁画鐜�", "鎿嶄綔"];
+
+      headers.forEach((header, index) => {
+        const cell = worksheet.getCell(2, index + 1);
+        cell.value = header;
+        cell.style = headerStyle;
+      });
+
+      worksheet.getRow(2).height = 25;
+
+      // 鏁版嵁琛�
+      this.tableData.forEach((item, rowIndex) => {
+        const dataRow = worksheet.addRow(
+          [
+            rowIndex + 1,
+            item.wardName,
+            item.continuedCount,
+            item.unContinuedCount,
+            item.continuedRate,
+            "鏌ョ湅鎶ゅ+璇︽儏"
+          ],
+          rowIndex + 3
+        );
+
+        dataRow.eachCell((cell) => {
+          cell.style = cellStyle;
+        });
+        dataRow.height = 24;
+      });
+
+      // 鍚堣琛�
+      const totalContinued = this.tableData.reduce((sum, item) => sum + item.continuedCount, 0);
+      const totalUnContinued = this.tableData.reduce((sum, item) => sum + item.unContinuedCount, 0);
+      const total = totalContinued + totalUnContinued;
+      const totalRate = total > 0 ? ((totalContinued / total) * 100).toFixed(2) + '%' : '0.00%';
+
+      const summaryRow = worksheet.addRow([
+        "鍚堣",
+        "/",
+        totalContinued,
+        totalUnContinued,
+        totalRate,
+        "/"
+      ]);
+
+      summaryRow.eachCell((cell, colNumber) => {
+        cell.style = summaryStyle;
+      });
+      summaryRow.height = 28;
+
+      // 鍒楀
+      worksheet.columns = [
+        { width: 8 },
+        { width: 30 },
+        { width: 15 },
+        { width: 15 },
+        { width: 12 },
+        { width: 15 }
+      ];
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.continued-care {
+  .your-table-container {
+    margin-top: 10px;
+  }
+
+  .button-zx {
+    color: rgb(70, 204, 238);
+  }
+}
+</style>
diff --git a/src/views/sfstatistics/percentage/components/DetailDialog.vue b/src/views/sfstatistics/percentage/components/DetailDialog.vue
new file mode 100644
index 0000000..2209b13
--- /dev/null
+++ b/src/views/sfstatistics/percentage/components/DetailDialog.vue
@@ -0,0 +1,302 @@
+<template>
+  <el-dialog
+    :title="title"
+    :visible.sync="visible"
+    v-loading="loading"
+    width="70%"
+    :close-on-click-modal="false"
+    @close="handleClose"
+  >
+    <div class="detail-dialog">
+      <div style="margin-bottom: 16px; display: flex; align-items: center">
+        <span style="margin-right: 10px; font-weight: bold">鎮h�呭鍚嶆煡璇�:</span>
+        <el-input
+          v-model="searchName"
+          placeholder="璇疯緭鍏ユ偅鑰呭鍚嶈繘琛岀瓫閫�"
+          clearable
+          style="width: 300px"
+          @input="handleSearch"
+          @clear="handleSearch"
+        />
+        <span style="margin-left: 10px; color: rgb(35, 81, 233); font-size: 16px">
+          鍏� {{ displayList.length }} 鏉¤褰�
+        </span>
+      </div>
+
+      <div class="examine-jic">
+        <div class="jic-value">
+          <el-row :gutter="20">
+            <div class="data-list" ref="dataList" @scroll="handleScroll" v-loading="loading">
+              <el-table :data="currentDisplayList" height="660" style="width: 100%">
+                <el-table-column prop="sendname" align="center" label="濮撳悕" width="100" />
+                <el-table-column prop="taskName" align="center" width="200" show-overflow-tooltip label="浠诲姟鍚嶇О" />
+
+                <el-table-column prop="sendstate" align="center" width="200" label="浠诲姟鐘舵��">
+                  <template slot-scope="scope">
+                    <el-tag
+                      :type="getStateTagType(scope.row.sendstate)"
+                      :disable-transitions="false"
+                    >
+                      {{ getStateText(scope.row.sendstate) }}
+                    </el-tag>
+                  </template>
+                </el-table-column>
+
+                <el-table-column
+                  label="浠诲姟鎵ц鏂瑰紡"
+                  align="center"
+                  key="preachform"
+                  prop="preachform"
+                  width="160"
+                  :show-overflow-tooltip="true"
+                >
+                  <template slot-scope="scope">
+                    <span v-for="(item, index) in scope.row.preachform" :key="index">
+                      {{ item }}{{ index < scope.row.preachform.length - 1 ? '銆�' : '' }}
+                    </span>
+                  </template>
+                </el-table-column>
+
+                <el-table-column
+                  prop="visitTime"
+                  align="center"
+                  label="搴旈殢璁挎椂闂�"
+                  width="200"
+                  show-overflow-tooltip
+                />
+                <el-table-column
+                  prop="finishtime"
+                  align="center"
+                  label="闅忚瀹屾垚鏃堕棿"
+                  width="200"
+                  show-overflow-tooltip
+                />
+                <el-table-column label="鍑洪櫌鏃ユ湡" width="200" align="center" key="endtime" prop="endtime">
+                  <template slot-scope="scope">
+                    <span>{{ formatTime(scope.row.endtime) }}</span>
+                  </template>
+                </el-table-column>
+
+                <el-table-column label="璐d换鎶ゅ+" width="120" align="center" key="nurseName" prop="nurseName" />
+                <el-table-column label="涓绘不鍖荤敓" width="120" align="center" key="drname" prop="drname" />
+
+                <el-table-column label="缁撴灉鐘舵��" align="center" key="excep" prop="excep" width="120">
+                  <template slot-scope="scope">
+                    <dict-tag :options="dict.type.sys_yujing" :value="scope.row.excep" />
+                  </template>
+                </el-table-column>
+
+                <el-table-column label="澶勭悊鎰忚" align="center" key="suggest" prop="suggest" width="120">
+                  <template slot-scope="scope">
+                    <dict-tag :options="dict.type.sys_suggest" :value="scope.row.suggest" />
+                  </template>
+                </el-table-column>
+
+                <el-table-column prop="templatename" align="center" label="鏈嶅姟妯℃澘" width="200" show-overflow-tooltip />
+                <el-table-column prop="remark" align="center" label="鏈嶅姟璁板綍" width="200" show-overflow-tooltip />
+
+                <el-table-column prop="bankcardno" align="center" label="鍛煎彨鐘舵��" width="210" />
+
+                <el-table-column label="鎿嶄綔" fixed="right" align="center" width="200" class-name="small-padding fixed-width">
+                  <template slot-scope="scope">
+                    <el-button size="medium" type="text" @click="handleDetailsGo(scope.row)">
+                      <span class="button-zx">
+                        <i class="el-icon-s-order"></i>鏌ョ湅
+                      </span>
+                    </el-button>
+                  </template>
+                </el-table-column>
+              </el-table>
+            </div>
+          </el-row>
+        </div>
+      </div>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+export default {
+  name: 'DetailDialog',
+  dicts: ['sys_yujing', 'sys_suggest'],
+  props: {
+    visible: {
+      type: Boolean,
+      default: false
+    },
+    title: {
+      type: String,
+      default: ''
+    },
+    data: {
+      type: Array,
+      default: () => []
+    },
+    searchName: {
+      type: String,
+      default: ''
+    },
+    loading: {
+      type: Boolean,
+      default: false
+    }
+  },
+  data() {
+    return {
+      localSearchName: '',
+      displayList: [],
+      currentDisplayList: [],
+      loadIndex: 0,
+      pageSize: 100,
+      isLoading: false
+    }
+  },
+  watch: {
+    data: {
+      immediate: true,
+      handler(newData) {
+        this.initializeData(newData)
+      }
+    },
+    searchName(newVal) {
+      this.localSearchName = newVal
+      this.handleSearch()
+    }
+  },
+  mounted() {
+    if (this.data && this.data.length > 0) {
+      this.initializeData(this.data)
+    }
+  },
+  methods: {
+    initializeData(data) {
+      this.displayList = [...data]
+      this.formatPreachformData()
+      this.loadIndex = 0
+      this.currentDisplayList = []
+      this.$nextTick(() => {
+        this.loadMoreData()
+      })
+    },
+
+    formatPreachformData() {
+      this.displayList.forEach((item) => {
+        if (item.preachform) {
+          if (item.endtime) {
+            item.preachformson = item.preachform
+            const idArray = item.preachform.split(',')
+
+            item.preachform = idArray.map((value) => {
+              const checkboxlist = this.$store.getters.checkboxlist
+              const foundItem = checkboxlist.find((item) => item.value == value)
+              return foundItem ? foundItem.label : null
+            }).filter(label => label !== null)
+          }
+        }
+      })
+    },
+
+    handleSearch() {
+      if (!this.localSearchName.trim()) {
+        this.displayList = [...this.data]
+        this.formatPreachformData()
+      } else {
+        const keyword = this.localSearchName.toLowerCase()
+        this.displayList = this.data.filter((item) => {
+          return item.sendname && item.sendname.toLowerCase().includes(keyword)
+        })
+        this.formatPreachformData()
+      }
+
+      this.loadIndex = 0
+      this.currentDisplayList = []
+      this.$nextTick(() => {
+        this.loadMoreData()
+      })
+
+      this.$emit('search', this.localSearchName)
+    },
+
+    loadMoreData() {
+      if (this.isLoading || this.loadIndex >= this.displayList.length) return
+
+      this.isLoading = true
+
+      setTimeout(() => {
+        const nextChunk = this.displayList.slice(
+          this.loadIndex,
+          this.loadIndex + this.pageSize
+        )
+        this.currentDisplayList = this.currentDisplayList.concat(nextChunk)
+        this.loadIndex += this.pageSize
+        this.isLoading = false
+      }, 200)
+    },
+
+    handleScroll(event) {
+      const scrollContainer = event.target
+      const isAtBottom =
+        scrollContainer.scrollTop + scrollContainer.clientHeight >=
+        scrollContainer.scrollHeight - 10
+
+      if (
+        isAtBottom &&
+        !this.isLoading &&
+        this.loadIndex < this.displayList.length
+      ) {
+        this.loadMoreData()
+      }
+    },
+
+    getStateTagType(state) {
+      const stateMap = {
+        1: 'primary',  // 琛ㄥ崟宸查鍙�
+        2: 'primary',  // 寰呴殢璁�
+        3: 'success',  // 琛ㄥ崟宸插彂閫�
+        4: 'info',     // 涓嶆墽琛�
+        5: 'danger',   // 鍙戦�佸け璐�
+        6: 'success'   // 宸插畬鎴�
+      }
+      return stateMap[state] || 'info'
+    },
+
+    getStateText(state) {
+      const stateTextMap = {
+        1: '琛ㄥ崟宸查鍙�',
+        2: '寰呴殢璁�',
+        3: '琛ㄥ崟宸插彂閫�',
+        4: '涓嶆墽琛�',
+        5: '鍙戦�佸け璐�',
+        6: '宸插畬鎴�'
+      }
+      return stateTextMap[state] || '鏈煡鐘舵��'
+    },
+
+    formatTime(time) {
+      if (!time) return ''
+      return this.parseTime(time)
+    },
+
+    handleDetailsGo(row) {
+      this.$emit('details-go', row)
+    },
+
+    handleClose() {
+      this.$emit('close')
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.detail-dialog {
+  .data-list {
+    max-height: 800px;
+    overflow-y: auto;
+  }
+
+  .button-zx {
+    color: rgb(70, 204, 238);
+  }
+}
+</style>
diff --git a/src/views/sfstatistics/percentage/components/FirstFollowUp.vue b/src/views/sfstatistics/percentage/components/FirstFollowUp.vue
new file mode 100644
index 0000000..3b71ece
--- /dev/null
+++ b/src/views/sfstatistics/percentage/components/FirstFollowUp.vue
@@ -0,0 +1,728 @@
+<template>
+  <div class="first-follow-up">
+    <div class="your-table-container">
+      <el-table
+        ref="exportTable"
+        id="exportTableid"
+        v-loading="loading"
+        :data="tableData"
+        :border="true"
+        @selection-change="handleSelectionChange"
+        @expand-change="handleRowClick"
+        :row-key="getRowKey"
+        show-summary
+        :summary-method="getSummaries"
+        :expand-row-keys="expands"
+      >
+        <!-- 灞曞紑琛岀澶村垪 -->
+        <el-table-column type="expand">
+          <template slot-scope="props">
+            <el-table
+              :data="props.row.doctorStats"
+              border
+              style="width: 95%; margin: 0 auto"
+              class="inner-table"
+              show-summary
+              :summary-method="getInnerSummaries"
+            >
+              <el-table-column label="鍖荤敓濮撳悕" prop="drname" align="center" />
+              <el-table-column label="绉戝" width="120" prop="deptname" align="center" />
+              <el-table-column label="鍑洪櫌浜烘" prop="dischargeCount" align="center" />
+              <el-table-column label="鍑洪櫌浜烘" align="center" key="dischargeCount" prop="dischargeCount" />
+              <el-table-column label="鏃犻渶闅忚浜烘" align="center" width="100" key="nonFollowUp" prop="nonFollowUp" />
+              <el-table-column label="搴旈殢璁夸汉娆�" align="center" width="100" key="followUpNeeded" prop="followUpNeeded" />
+
+              <el-table-column align="center" label="棣栨鍑洪櫌闅忚">
+                <el-table-column label="闇�闅忚" align="center" key="needFollowUp" prop="needFollowUp" />
+                <el-table-column label="寰呴殢璁�" align="center" key="pendingFollowUp" prop="pendingFollowUp" />
+                <el-table-column label="闅忚鎴愬姛" align="center" key="followUpSuccess" prop="followUpSuccess" />
+                <el-table-column label="闅忚澶辫触" align="center" key="followUpFail" prop="followUpFail" />
+                <el-table-column label="闅忚鐜�" align="center" width="120" key="followUpRate" prop="followUpRate" />
+                <el-table-column v-if="orgname != '涓芥按甯備腑鍖婚櫌'" label="鍙婃椂鐜�" align="center" width="120" key="rate" prop="rate">
+                  <template slot-scope="scope">
+                    <el-button size="medium" type="text" @click="handleSeeDetails(scope.row)">
+                      <span class="button-zx">{{ (Number(scope.row.rate) * 100).toFixed(2) }}%</span>
+                    </el-button>
+                  </template>
+                </el-table-column>
+                <el-table-column label="浜哄伐" align="center" key="manual" prop="manual" />
+                <el-table-column label="鐭俊" align="center" key="sms" prop="sms" />
+                <el-table-column label="寰俊" align="center" key="weChat" prop="weChat" />
+              </el-table-column>
+            </el-table>
+          </template>
+        </el-table-column>
+
+        <!-- 琛ㄦ牸鍒楀畾涔� -->
+        <el-table-column
+          label="鍑洪櫌鐥呭尯"
+          align="center"
+          sortable
+          key="leavehospitaldistrictname"
+          prop="leavehospitaldistrictname"
+          width="150"
+          :show-overflow-tooltip="true"
+          :sort-method="sortChineseNumber"
+        />
+        <el-table-column label="绉戝" align="center" key="deptname" prop="deptname" :show-overflow-tooltip="true" />
+        <el-table-column label="鍑洪櫌浜烘" align="center" key="dischargeCount" prop="dischargeCount" />
+        <el-table-column label="鏃犻渶闅忚浜烘" align="center" width="100" key="nonFollowUp" prop="nonFollowUp" />
+        <el-table-column label="搴旈殢璁夸汉娆�" align="center" width="100" key="followUpNeeded" prop="followUpNeeded" />
+
+        <el-table-column align="center" label="棣栨鍑洪櫌闅忚">
+          <el-table-column label="闇�闅忚" align="center" key="needFollowUp" prop="needFollowUp">
+            <template slot-scope="scope">
+              <el-button size="medium" type="text" @click="handleViewDetails(scope.row, 'needFollowUpInfo', '闇�闅忚鍒楄〃')">
+                <span class="button-zx">{{ scope.row.needFollowUp }}</span>
+              </el-button>
+            </template>
+          </el-table-column>
+          <el-table-column label="寰呴殢璁�" align="center" key="pendingFollowUp" prop="pendingFollowUp">
+            <template slot-scope="scope">
+              <el-button size="medium" type="text" @click="handleViewDetails(scope.row, 'pendingFollowUpInfo', '寰呴殢璁垮垪琛�')">
+                <span class="button-zx">{{ scope.row.pendingFollowUp }}</span>
+              </el-button>
+            </template>
+          </el-table-column>
+          <el-table-column label="闅忚鎴愬姛" align="center" key="followUpSuccess" prop="followUpSuccess">
+            <template slot-scope="scope">
+              <el-button size="medium" type="text" @click="handleViewDetails(scope.row, 'followUpSuccessInfo', '闅忚鎴愬姛鍒楄〃')">
+                <span class="button-zx">{{ scope.row.followUpSuccess }}</span>
+              </el-button>
+            </template>
+          </el-table-column>
+          <el-table-column label="闅忚澶辫触" align="center" key="followUpFail" prop="followUpFail">
+            <template slot-scope="scope">
+              <el-button size="medium" type="text" @click="handleViewDetails(scope.row, 'followUpFailInfo', '闅忚澶辫触鍒楄〃')">
+                <span class="button-zx">{{ scope.row.followUpFail }}</span>
+              </el-button>
+            </template>
+          </el-table-column>
+          <el-table-column label="闅忚鐜�" align="center" width="120" key="followUpRate" prop="followUpRate" />
+          <el-table-column v-if="orgname != '涓芥按甯備腑鍖婚櫌'" label="鍙婃椂鐜�" align="center" width="120" key="rate" prop="rate">
+            <template slot-scope="scope">
+              <el-button size="medium" type="text" @click="handleSeeDetails(scope.row)">
+                <span class="button-zx">{{ (Number(scope.row.rate) * 100).toFixed(2) }}%</span>
+              </el-button>
+            </template>
+          </el-table-column>
+          <el-table-column label="浜哄伐" align="center" key="manual" prop="manual">
+            <template slot-scope="scope">
+              <el-button size="medium" type="text" @click="handleViewDetails(scope.row, 'manualInfo', '浜哄伐闅忚鍒楄〃')">
+                <span class="button-zx">{{ scope.row.manual }}</span>
+              </el-button>
+            </template>
+          </el-table-column>
+          <el-table-column label="鐭俊" align="center" key="sms" prop="sms">
+            <template slot-scope="scope">
+              <el-button size="medium" type="text" @click="handleViewDetails(scope.row, 'smsInfo', '鐭俊闅忚鍒楄〃')">
+                <span class="button-zx">{{ scope.row.sms }}</span>
+              </el-button>
+            </template>
+          </el-table-column>
+          <el-table-column label="寰俊" align="center" key="weChat" prop="weChat">
+            <template slot-scope="scope">
+              <el-button size="medium" type="text" @click="handleViewDetails(scope.row, 'weChatInfo', '寰俊闅忚鍒楄〃')">
+                <span class="button-zx">{{ scope.row.weChat }}</span>
+              </el-button>
+            </template>
+          </el-table-column>
+        </el-table-column>
+
+        <!-- 闅忚鎯呭喌鍒楋紙浠呬附姘村競涓尰闄㈡樉绀猴級 -->
+        <el-table-column v-if="orgname == '涓芥按甯備腑鍖婚櫌'" align="center" label="闅忚鎯呭喌">
+          <el-table-column label="姝e父璇煶" align="center" width="100" key="taskSituation1" prop="taskSituation1" />
+          <el-table-column label="鎮h�呮嫆鎺ユ垨鎷掕" align="center" width="100" key="taskSituation2" prop="taskSituation2" />
+          <el-table-column label="闈㈣鎴栬�呮帴璇�" align="center" width="100" key="taskSituation3" prop="taskSituation3" />
+          <el-table-column label="寰俊闅忚" align="center" width="100" key="taskSituation4" prop="taskSituation4" />
+          <el-table-column label="闅忚鐢佃瘽涓嶆纭�" align="center" width="100" key="taskSituation5" prop="taskSituation5" />
+          <el-table-column label="鍏朵粬鎯呭喌涓嶅疁闅忚" align="center" width="100" key="taskSituation6" prop="taskSituation6" />
+        </el-table-column>
+      </el-table>
+    </div>
+  </div>
+</template>
+
+<script>
+import { getSfStatistics, selectTimelyRate } from "@/api/system/user";
+import ExcelJS from "exceljs";
+import { saveAs } from "file-saver";
+
+export default {
+  name: 'FirstFollowUp',
+  props: {
+    queryParams: {
+      type: Object,
+      required: true
+    },
+    flatArrayhospit: {
+      type: Array,
+      default: () => []
+    },
+    flatArraydept: {
+      type: Array,
+      default: () => []
+    },
+    options: {
+      type: Array,
+      default: () => []
+    },
+    orgname: {
+      type: String,
+      default: ''
+    }
+  },
+  data() {
+    return {
+      tableData: [],
+      loading: false,
+      expands: [],
+      ids: []
+    }
+  },
+  methods: {
+    loadData() {
+      this.loading = true
+      const params = {
+        ...this.queryParams,
+        visitCount: 1,
+        leavehospitaldistrictcodes: this.queryParams.leavehospitaldistrictcodes.includes("all")
+          ? this.getAllWardCodes()
+          : this.queryParams.leavehospitaldistrictcodes,
+        deptcodes: this.queryParams.deptcodes.includes("all")
+          ? this.getAllDeptCodes()
+          : this.queryParams.deptcodes
+      }
+
+      delete params.leavehospitaldistrictcodes.all
+      delete params.deptcodes.all
+
+      getSfStatistics(params)
+        .then(response => {
+          this.tableData = this.customSort(response.data)
+        })
+        .catch(error => {
+          console.error("鑾峰彇棣栨闅忚鏁版嵁澶辫触:", error)
+          this.$message.error("鑾峰彇棣栨闅忚鏁版嵁澶辫触")
+        })
+        .finally(() => {
+          this.loading = false
+        })
+    },
+
+    getAllWardCodes() {
+      return this.flatArrayhospit
+        .filter(item => item.value !== 'all')
+        .map(item => item.value)
+    },
+
+    getAllDeptCodes() {
+      return this.flatArraydept
+        .filter(item => item.value !== 'all')
+        .map(item => item.value)
+    },
+
+    customSort(data) {
+      const order = [
+        "涓�","浜�","涓�","鍥�","浜�","鍏�","涓�","鍏�","涔�","鍗�",
+        "鍗佷竴","鍗佷簩","鍗佷笁","鍗佸洓","鍗佷簲","鍗佸叚","鍗佷竷","鍗佸叓","鍗佷節","浜屽崄",
+        "浜屽崄涓�","浜屽崄浜�","浜屽崄涓�","浜屽崄鍥�","浜屽崄浜�","浜屽崄鍏�","浜屽崄涓�","浜屽崄鍏�","浜屽崄涔�","涓夊崄",
+        "涓夊崄涓�","涓夊崄浜�","涓夊崄涓�","涓夊崄鍥�","涓夊崄浜�","涓夊崄鍏�","涓夊崄涓�","涓夊崄鍏�","涓夊崄涔�","鍥涘崄",
+        "鍥涘崄涓�","鍥涘崄浜�","鍥涘崄涓�","鍥涘崄鍥�","鍥涘崄浜�"
+      ]
+
+      return data.sort((a, b) => {
+        const getIndex = (name) => {
+          if (!name || typeof name !== "string") return -1
+          const chineseMatch = name.match(/^([涓�浜屼笁鍥涗簲鍏竷鍏節鍗乚+)/)
+          if (chineseMatch && chineseMatch[1]) {
+            return order.indexOf(chineseMatch[1])
+          }
+          const arabicMatch = name.match(/^(\d+)/)
+          if (arabicMatch && arabicMatch[1]) {
+            const num = parseInt(arabicMatch[1], 10)
+            if (num >= 1 && num <= 45) {
+              return num - 1
+            }
+          }
+          return -1
+        }
+
+        const indexA = getIndex(a.leavehospitaldistrictname)
+        const indexB = getIndex(b.leavehospitaldistrictname)
+
+        if (indexA === -1 && indexB === -1) {
+          return (a.leavehospitaldistrictname || "").localeCompare(b.leavehospitaldistrictname || "")
+        }
+        if (indexA === -1) return 1
+        if (indexB === -1) return -1
+        return indexA - indexB
+      })
+    },
+
+    sortChineseNumber(aRow, bRow) {
+      const a = aRow.leavehospitaldistrictname
+      const b = bRow.leavehospitaldistrictname
+
+      const chineseNumMap = {
+        涓�:1,浜�:2,涓�:3,鍥�:4,浜�:5,鍏�:6,涓�:7,鍏�:8,涔�:9,鍗�:10,
+        鍗佷竴:11,鍗佷簩:12,鍗佷笁:13,鍗佸洓:14,鍗佷簲:15,鍗佸叚:16,鍗佷竷:17,鍗佸叓:18,鍗佷節:19,浜屽崄:20,
+        浜屽崄涓�:21,浜屽崄浜�:22,浜屽崄涓�:23,浜屽崄鍥�:24,浜屽崄浜�:25,浜屽崄鍏�:26,浜屽崄涓�:27,浜屽崄鍏�:28,浜屽崄涔�:29,涓夊崄:30,
+        涓夊崄涓�:31,涓夊崄浜�:32,涓夊崄涓�:33,涓夊崄鍥�:34,涓夊崄浜�:35,涓夊崄鍏�:36,涓夊崄涓�:37,涓夊崄鍏�:38,涓夊崄涔�:39,鍥涘崄:40,
+        鍥涘崄涓�:41,鍥涘崄浜�:42,鍥涘崄涓�:43,鍥涘崄鍥�:44,鍥涘崄浜�:45
+      }
+
+      const getNumberFromText = (text) => {
+        if (!text || typeof text !== "string") return -1
+        const match = text.match(/^([涓�浜屼笁鍥涗簲鍏竷鍏節鍗乚+)/)
+        if (match && match[1]) {
+          const chineseNum = match[1]
+          return chineseNumMap[chineseNum] !== undefined ? chineseNumMap[chineseNum] : -1
+        }
+        const arabicMatch = text.match(/^(\d+)/)
+        if (arabicMatch && arabicMatch[1]) {
+          const num = parseInt(arabicMatch[1], 10)
+          return num >= 1 && num <= 45 ? num : -1
+        }
+        return -1
+      }
+
+      const numA = getNumberFromText(a)
+      const numB = getNumberFromText(b)
+
+      if (numA === -1 && numB === -1) {
+        return (a || "").localeCompare(b || "")
+      }
+      if (numA === -1) return 1
+      if (numB === -1) return -1
+      return numA - numB
+    },
+
+    getRowKey(row) {
+      return row.statisticaltype === 1 ? row.leavehospitaldistrictcode : row.deptcode
+    },
+
+    handleRowClick(row) {
+      if (this.expands.includes(this.getRowKey(row))) {
+        this.expands = []
+        return
+      }
+
+      const params = {
+        ...this.queryParams,
+        deptcodes: this.queryParams.deptcodes.includes("all")
+          ? this.getAllDeptCodes()
+          : this.queryParams.deptcodes,
+        leavehospitaldistrictcodes: [row.leavehospitaldistrictcode],
+        drcode: "1",
+        visitCount: 1
+      }
+
+      delete params.leavehospitaldistrictcodes.all
+      delete params.deptcodes.all
+
+      if (!row.doctorStats) {
+        this.loading = true
+        getSfStatistics(params).then((res) => {
+          this.$set(row, "doctorStats", res.data)
+          this.expands = [this.getRowKey(row)]
+          this.loading = false
+        })
+      } else {
+        this.expands = [this.getRowKey(row)]
+      }
+    },
+
+    getSummaries(param) {
+      const { columns, data } = param
+      const sums = []
+
+      columns.forEach((column, index) => {
+        if (index === 0) {
+          sums[index] = "鍚堣"
+          return
+        }
+        if (index === 1 || index === 2) {
+          sums[index] = "/"
+          return
+        }
+
+        if (column.property === "followUpRate" || column.property === "rate") {
+          const percentageValues = data
+            .map((item) => {
+              const value = item[column.property]
+              if (!value || value === "-" || value === "0%") return null
+              if (typeof value === "string" && value.includes("%")) {
+                const numValue = parseFloat(value.replace("%", "")) / 100
+                return isNaN(numValue) ? null : numValue
+              } else {
+                const numValue = parseFloat(value)
+                return isNaN(numValue) ? null : numValue
+              }
+            })
+            .filter((value) => value !== null && value !== 0)
+
+          if (percentageValues.length > 0) {
+            const average = percentageValues.reduce((sum, value) => sum + value, 0) / percentageValues.length
+            sums[index] = (average * 100).toFixed(2) + "%"
+          } else {
+            sums[index] = "0.00%"
+          }
+        } else {
+          const values = data.map((item) => {
+            const value = item[column.property]
+            if (value === "-" || value === "" || value === null) return 0
+            return Number(value) || 0
+          })
+
+          if (!values.every((value) => isNaN(value))) {
+            sums[index] = values.reduce((prev, curr) => prev + curr, 0)
+            sums[index] = this.formatNumber(sums[index])
+          } else {
+            sums[index] = "-"
+          }
+        }
+      })
+
+      return sums
+    },
+
+    getInnerSummaries(param) {
+      const { columns, data } = param
+      const sums = []
+
+      columns.forEach((column, index) => {
+        if (index === 0) {
+          sums[index] = "灏忚"
+          return
+        }
+
+        if (column.property === "drname" || column.property === "deptname") {
+          sums[index] = "-"
+          return
+        }
+
+        if (column.property === "followUpRate" || column.property === "rate") {
+          const percentageValues = data
+            .map((item) => {
+              const value = item[column.property]
+              if (!value || value === "-" || value === "0%") return null
+              if (typeof value === "string" && value.includes("%")) {
+                const numValue = parseFloat(value.replace("%", "")) / 100
+                return isNaN(numValue) ? null : numValue
+              } else {
+                const numValue = parseFloat(value)
+                return isNaN(numValue) ? null : numValue
+              }
+            })
+            .filter((value) => value !== null && value !== 0)
+
+          if (percentageValues.length > 0) {
+            const average = percentageValues.reduce((sum, value) => sum + value, 0) / percentageValues.length
+            sums[index] = (average * 100).toFixed(2) + "%"
+          } else {
+            sums[index] = "0.00%"
+          }
+        } else {
+          const values = data.map((item) => {
+            const value = item[column.property]
+            if (value === "-" || value === "" || value === null) return 0
+            return Number(value) || 0
+          })
+
+          if (!values.every((value) => isNaN(value))) {
+            sums[index] = values.reduce((prev, curr) => prev + curr, 0)
+            sums[index] = this.formatNumber(sums[index])
+          } else {
+            sums[index] = "-"
+          }
+        }
+      })
+
+      return sums
+    },
+
+    formatNumber(num) {
+      if (isNaN(num)) return "-"
+      return Number.isInteger(num) ? num.toString() : num.toFixed(0)
+    },
+
+    handleSelectionChange(selection) {
+      this.ids = selection.map((item) => item.tagid)
+    },
+
+    handleViewDetails(row, infoKey, titleSuffix) {
+      const title = `${row.leavehospitaldistrictname || row.deptname}${titleSuffix}`
+      this.$emit('view-details', row[infoKey], title)
+    },
+
+    handleSeeDetails(row) {
+      this.$emit('see-details', row)
+    },
+
+    async exportTable() {
+      try {
+        let dateRangeString = ""
+        let sheetNameSuffix = ""
+
+        if (this.queryParams.dateRange && this.queryParams.dateRange.length === 2) {
+          const startDateStr = this.queryParams.dateRange[0]
+          const endDateStr = this.queryParams.dateRange[1]
+          const formatDateForDisplay = (dateTimeStr) => {
+            return dateTimeStr.split(" ")[0]
+          }
+          const startDateFormatted = formatDateForDisplay(startDateStr)
+          const endDateFormatted = formatDateForDisplay(endDateStr)
+          dateRangeString = `${startDateFormatted}鑷�${endDateFormatted}`
+          sheetNameSuffix = `${startDateFormatted}鑷�${endDateFormatted}`
+        } else {
+          const now = new Date()
+          const currentMonth = now.getMonth() + 1
+          dateRangeString = `${currentMonth}鏈坄
+          sheetNameSuffix = `${currentMonth}鏈坄
+        }
+
+        const excelName = `棣栨鍑洪櫌闅忚缁熻琛╛${dateRangeString}.xlsx`
+        const worksheetName = `棣栨闅忚缁熻_${sheetNameSuffix}`
+
+        if (!this.tableData || this.tableData.length === 0) {
+          this.$message.warning("鏆傛棤棣栨闅忚鏁版嵁鍙鍑�")
+          return false
+        }
+
+        const workbook = new ExcelJS.Workbook()
+        const worksheet = workbook.addWorksheet(worksheetName)
+
+        // 鏋勫缓琛ㄦ牸
+        this.buildExportSheet(worksheet, sheetNameSuffix)
+
+        const buffer = await workbook.xlsx.writeBuffer()
+        const blob = new Blob([buffer], {
+          type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
+        })
+        saveAs(blob, excelName)
+
+        this.$message.success("瀵煎嚭鎴愬姛")
+        return true
+      } catch (error) {
+        console.error("瀵煎嚭澶辫触:", error)
+        this.$message.error(`瀵煎嚭澶辫触: ${error.message}`)
+        return false
+      }
+    },
+
+    buildExportSheet(worksheet, sheetNameSuffix) {
+      const titleStyle = {
+        font: { name: "寰蒋闆呴粦", size: 16, bold: true, color: { argb: "FF000000" } },
+        fill: { type: "pattern", pattern: "solid", fgColor: { argb: "FFE6F3FF" } },
+        alignment: { vertical: "middle", horizontal: "center", wrapText: true },
+        border: {
+          top: { style: "thin", color: { argb: "FFD0D0D0" } },
+          left: { style: "thin", color: { argb: "FFD0D0D0" } },
+          bottom: { style: "thin", color: { argb: "FFD0D0D0" } },
+          right: { style: "thin", color: { argb: "FFD0D0D0" } }
+        }
+      }
+
+      const headerStyle = {
+        font: { name: "寰蒋闆呴粦", size: 11, bold: true, color: { argb: "FF000000" } },
+        fill: { type: "pattern", pattern: "solid", fgColor: { argb: "FFF5F7FA" } },
+        alignment: { vertical: "middle", horizontal: "center", wrapText: true },
+        border: {
+          top: { style: "thin", color: { argb: "FFD0D0D0" } },
+          left: { style: "thin", color: { argb: "FFD0D0D0" } },
+          bottom: { style: "thin", color: { argb: "FFD0D0D0" } },
+          right: { style: "thin", color: { argb: "FFD0D0D0" } }
+        }
+      }
+
+      const cellStyle = {
+        font: { name: "瀹嬩綋", size: 10, color: { argb: "FF000000" } },
+        alignment: { vertical: "middle", horizontal: "center" },
+        border: {
+          top: { style: "thin", color: { argb: "FFD0D0D0" } },
+          left: { style: "thin", color: { argb: "FFD0D0D0" } },
+          bottom: { style: "thin", color: { argb: "FFD0D0D0" } },
+          right: { style: "thin", color: { argb: "FFD0D0D0" } }
+        }
+      }
+
+      const summaryStyle = {
+        font: { name: "瀹嬩綋", size: 10, bold: true, color: { argb: "FF409EFF" } },
+        fill: { type: "pattern", pattern: "solid", fgColor: { argb: "FFF5F7FA" } },
+        alignment: { vertical: "middle", horizontal: "center" },
+        border: {
+          top: { style: "thin", color: { argb: "FFD0D0D0" } },
+          left: { style: "thin", color: { argb: "FFD0D0D0" } },
+          bottom: { style: "thin", color: { argb: "FFD0D0D0" } },
+          right: { style: "thin", color: { argb: "FFD0D0D0" } }
+        }
+      }
+
+      // 娣诲姞鏍囬琛�
+      worksheet.mergeCells(1, 1, 1, 16)
+      const titleCell = worksheet.getCell(1, 1)
+      titleCell.value = `棣栨鍑洪櫌闅忚缁熻琛╛${sheetNameSuffix}`
+      titleCell.style = titleStyle
+      worksheet.getRow(1).height = 35
+
+      // 琛ㄥご
+      const secondRowHeaders = [
+        "", "鍑洪櫌鐥呭尯", "绉戝", "鍑洪櫌浜烘", "鏃犻渶闅忚浜烘", "搴旈殢璁夸汉娆�",
+        "闇�闅忚", "寰呴殢璁�", "闅忚鎴愬姛", "闅忚澶辫触", "闅忚鐜�", "鍙婃椂鐜�", "浜哄伐", "鐭俊", "寰俊"
+      ]
+
+      secondRowHeaders.forEach((header, index) => {
+        const cell = worksheet.getCell(3, index + 1)
+        cell.value = header
+        cell.style = headerStyle
+      })
+
+      // 鍚堝苟鍗曞厓鏍�
+      for (let i = 1; i <= 6; i++) {
+        worksheet.mergeCells(2, i, 3, i)
+        const cell = worksheet.getCell(2, i)
+        cell.style = headerStyle
+      }
+
+      worksheet.getCell(2, 1).value = ""
+      worksheet.getCell(2, 2).value = "鍑洪櫌鐥呭尯"
+      worksheet.getCell(2, 3).value = "绉戝"
+      worksheet.getCell(2, 4).value = "鍑洪櫌浜烘"
+      worksheet.getCell(2, 5).value = "鏃犻渶闅忚浜烘"
+      worksheet.getCell(2, 6).value = "搴旈殢璁夸汉娆�"
+
+      worksheet.mergeCells(2, 7, 2, 15)
+      worksheet.getCell(2, 7).value = "棣栨鍑洪櫌闅忚"
+      worksheet.getCell(2, 7).style = headerStyle
+
+      worksheet.getRow(2).height = 28
+      worksheet.getRow(3).height = 25
+
+      // 鏁版嵁琛�
+      this.tableData.forEach((item, rowIndex) => {
+        const dataRow = worksheet.addRow([
+          "",
+          item.leavehospitaldistrictname || "",
+          item.deptname || "",
+          item.dischargeCount || 0,
+          item.nonFollowUp || 0,
+          item.followUpNeeded || 0,
+          item.needFollowUp || 0,
+          item.pendingFollowUp || 0,
+          item.followUpSuccess || 0,
+          item.followUpFail || 0,
+          item.followUpRate || "0%",
+          item.rate ? (Number(item.rate) * 100).toFixed(2) + "%" : "0%",
+          item.manual || 0,
+          item.sms || 0,
+          item.weChat || 0
+        ], rowIndex + 4)
+
+        dataRow.eachCell((cell) => {
+          cell.style = cellStyle
+        })
+        dataRow.height = 24
+      })
+
+      // 鍚堣琛�
+      const summaries = this.getExportSummaries()
+      const summaryRow = worksheet.addRow(summaries)
+      summaryRow.eachCell((cell, colNumber) => {
+        cell.style = summaryStyle
+        if (colNumber === 1) {
+          cell.value = "鍚堣"
+        }
+      })
+      summaryRow.height = 28
+
+      // 鍒楀
+      worksheet.columns = [
+        { width: 8 }, { width: 20 }, { width: 15 }, { width: 12 }, { width: 12 }, { width: 12 },
+        { width: 10 }, { width: 10 }, { width: 10 }, { width: 10 }, { width: 12 }, { width: 12 },
+        { width: 8 }, { width: 8 }, { width: 8 }
+      ]
+    },
+
+    getExportSummaries() {
+      const summaries = ["鍚堣", "/", "/", 0, 0, 0, 0, 0, 0, 0, "0%", "0%", 0, 0, 0]
+
+      this.tableData.forEach((item) => {
+        summaries[3] += Number(item.dischargeCount) || 0
+        summaries[4] += Number(item.nonFollowUp) || 0
+        summaries[5] += Number(item.followUpNeeded) || 0
+        summaries[6] += Number(item.needFollowUp) || 0
+        summaries[7] += Number(item.pendingFollowUp) || 0
+        summaries[8] += Number(item.followUpSuccess) || 0
+        summaries[9] += Number(item.followUpFail) || 0
+        summaries[12] += Number(item.manual) || 0
+        summaries[13] += Number(item.sms) || 0
+        summaries[14] += Number(item.weChat) || 0
+      })
+
+      const followUpRateValues = this.tableData
+        .map((item) => this.extractPercentageValue(item.followUpRate))
+        .filter((value) => value !== null)
+
+      const rateValues = this.tableData
+        .map((item) => this.extractPercentageValue(item.rate))
+        .filter((value) => value !== null)
+
+      if (followUpRateValues.length > 0) {
+        const avgFollowUpRate = followUpRateValues.reduce((sum, val) => sum + val, 0) / followUpRateValues.length
+        summaries[10] = (avgFollowUpRate * 100).toFixed(2) + "%"
+      }
+
+      if (rateValues.length > 0) {
+        const avgRate = rateValues.reduce((sum, val) => sum + val, 0) / rateValues.length
+        summaries[11] = (avgRate * 100).toFixed(2) + "%"
+      }
+
+      summaries[3] = this.formatNumber(summaries[3])
+      summaries[4] = this.formatNumber(summaries[4])
+      summaries[5] = this.formatNumber(summaries[5])
+      summaries[6] = this.formatNumber(summaries[6])
+      summaries[7] = this.formatNumber(summaries[7])
+      summaries[8] = this.formatNumber(summaries[8])
+      summaries[9] = this.formatNumber(summaries[9])
+      summaries[12] = this.formatNumber(summaries[12])
+      summaries[13] = this.formatNumber(summaries[13])
+      summaries[14] = this.formatNumber(summaries[14])
+
+      return summaries
+    },
+
+    extractPercentageValue(value) {
+      if (!value) return null
+      if (typeof value === "string" && value.includes("%")) {
+        const num = parseFloat(value.replace("%", ""))
+        return isNaN(num) ? null : num / 100
+      }
+      const num = parseFloat(value)
+      return isNaN(num) ? null : num
+    },
+
+    selectTimelyRate(row, dateRange) {
+      const params = {
+        ...this.patientqueryParams,
+        starttime: this.parseTime(dateRange[0]),
+        endtime: this.parseTime(dateRange[1]),
+        deptcode: row.deptcode
+      }
+      return selectTimelyRate(params)
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.first-follow-up {
+  .your-table-container {
+    margin-top: 10px;
+  }
+
+  .button-zx {
+    color: rgb(70, 204, 238);
+  }
+}
+</style>
diff --git a/src/views/sfstatistics/percentage/components/SecondFollowUp.vue b/src/views/sfstatistics/percentage/components/SecondFollowUp.vue
new file mode 100644
index 0000000..703b5c2
--- /dev/null
+++ b/src/views/sfstatistics/percentage/components/SecondFollowUp.vue
@@ -0,0 +1,679 @@
+<template>
+  <div class="second-follow-up">
+    <div class="your-table-container">
+      <el-table
+        ref="exportTableSecond"
+        id="exportTableidSecond"
+        v-loading="loading"
+        :data="tableData"
+        :border="true"
+        @selection-change="handleSelectionChange"
+        @expand-change="handleRowClick"
+        :row-key="getRowKey"
+        show-summary
+        :summary-method="getSummaries"
+        :expand-row-keys="expands"
+      >
+        <!-- 灞曞紑琛岀澶村垪 -->
+        <el-table-column type="expand">
+          <template slot-scope="props">
+            <el-table
+              :data="props.row.doctorStats"
+              border
+              style="width: 95%; margin: 0 auto"
+              class="inner-table"
+              show-summary
+              :summary-method="getInnerSummaries"
+            >
+              <el-table-column label="鍖荤敓濮撳悕" prop="drname" align="center" />
+              <el-table-column label="绉戝" width="120" prop="deptname" align="center" />
+              <el-table-column label="鍑洪櫌浜烘" prop="dischargeCount" align="center" />
+              <el-table-column label="鏃犻渶闅忚浜烘" align="center" width="100" key="nonFollowUp" prop="nonFollowUp" />
+              <el-table-column label="搴旈殢璁夸汉娆�" align="center" width="100" key="followUpNeeded" prop="followUpNeeded" />
+
+              <el-table-column align="center" label="鍐嶆鍑洪櫌闅忚">
+                <el-table-column label="闇�闅忚" align="center" key="needFollowUpAgain" prop="needFollowUpAgain" />
+                <el-table-column label="寰呴殢璁�" align="center" key="pendingFollowUpAgain" prop="pendingFollowUpAgain" />
+                <el-table-column label="闅忚鎴愬姛" align="center" key="followUpSuccessAgain" prop="followUpSuccessAgain" />
+                <el-table-column label="闅忚澶辫触" align="center" key="followUpFailAgain" prop="followUpFailAgain" />
+                <el-table-column label="闅忚鐜�" align="center" width="120" key="followUpRateAgain" prop="followUpRateAgain" />
+                <el-table-column label="浜哄伐" align="center" key="manualAgain" prop="manualAgain" />
+                <el-table-column label="鐭俊" align="center" key="smsAgain" prop="smsAgain" />
+                <el-table-column label="寰俊" align="center" key="weChatAgain" prop="weChatAgain" />
+              </el-table-column>
+            </el-table>
+          </template>
+        </el-table-column>
+
+        <!-- 琛ㄦ牸鍒楀畾涔� -->
+        <el-table-column
+          label="鍑洪櫌鐥呭尯"
+          align="center"
+          sortable
+          key="leavehospitaldistrictname"
+          prop="leavehospitaldistrictname"
+          width="150"
+          :show-overflow-tooltip="true"
+          :sort-method="sortChineseNumber"
+        />
+        <el-table-column label="绉戝" align="center" key="deptname" prop="deptname" :show-overflow-tooltip="true" />
+        <el-table-column label="鍑洪櫌浜烘" align="center" key="dischargeCount" prop="dischargeCount" />
+        <el-table-column label="鏃犻渶闅忚浜烘" align="center" width="100" key="nonFollowUp" prop="nonFollowUp" />
+        <el-table-column label="搴旈殢璁夸汉娆�" align="center" width="100" key="followUpNeeded" prop="followUpNeeded" />
+
+        <el-table-column align="center" label="鍐嶆鍑洪櫌闅忚">
+          <el-table-column label="闇�闅忚" align="center" key="needFollowUpAgain" prop="needFollowUpAgain">
+            <template slot-scope="scope">
+              <el-button size="medium" type="text" @click="handleViewDetails(scope.row, 'needFollowUpAgainInfo', '鍐嶆闅忚闇�闅忚鍒楄〃')">
+                <span class="button-zx">{{ scope.row.needFollowUpAgain }}</span>
+              </el-button>
+            </template>
+          </el-table-column>
+          <el-table-column label="寰呴殢璁�" align="center" key="pendingFollowUpAgain" prop="pendingFollowUpAgain">
+            <template slot-scope="scope">
+              <el-button size="medium" type="text" @click="handleViewDetails(scope.row, 'pendingFollowUpAgainInfo', '鍐嶆闅忚寰呴殢璁垮垪琛�')">
+                <span class="button-zx">{{ scope.row.pendingFollowUpAgain }}</span>
+              </el-button>
+            </template>
+          </el-table-column>
+          <el-table-column label="闅忚鎴愬姛" align="center" key="followUpSuccessAgain" prop="followUpSuccessAgain">
+            <template slot-scope="scope">
+              <el-button size="medium" type="text" @click="handleViewDetails(scope.row, 'followUpSuccessAgainInfo', '鍐嶆闅忚闅忚鎴愬姛鍒楄〃')">
+                <span class="button-zx">{{ scope.row.followUpSuccessAgain }}</span>
+              </el-button>
+            </template>
+          </el-table-column>
+          <el-table-column label="闅忚澶辫触" align="center" key="followUpFailAgain" prop="followUpFailAgain">
+            <template slot-scope="scope">
+              <el-button size="medium" type="text" @click="handleViewDetails(scope.row, 'followUpFailAgainInfo', '鍐嶆闅忚闅忚澶辫触鍒楄〃')">
+                <span class="button-zx">{{ scope.row.followUpFailAgain }}</span>
+              </el-button>
+            </template>
+          </el-table-column>
+          <el-table-column label="闅忚鐜�" align="center" width="120" key="followUpRateAgain" prop="followUpRateAgain" />
+          <el-table-column label="浜哄伐" align="center" key="manualAgain" prop="manualAgain">
+            <template slot-scope="scope">
+              <el-button size="medium" type="text" @click="handleViewDetails(scope.row, 'manualAgainInfo', '鍐嶆闅忚浜哄伐闅忚鍒楄〃')">
+                <span class="button-zx">{{ scope.row.manualAgain }}</span>
+              </el-button>
+            </template>
+          </el-table-column>
+          <el-table-column label="鐭俊" align="center" key="smsAgain" prop="smsAgain">
+            <template slot-scope="scope">
+              <el-button size="medium" type="text" @click="handleViewDetails(scope.row, 'smsAgainInfo', '鍐嶆闅忚鐭俊闅忚鍒楄〃')">
+                <span class="button-zx">{{ scope.row.smsAgain }}</span>
+              </el-button>
+            </template>
+          </el-table-column>
+          <el-table-column label="寰俊" align="center" key="weChatAgain" prop="weChatAgain">
+            <template slot-scope="scope">
+              <el-button size="medium" type="text" @click="handleViewDetails(scope.row, 'weChatAgainInfo', '鍐嶆闅忚寰俊闅忚鍒楄〃')">
+                <span class="button-zx">{{ scope.row.weChatAgain }}</span>
+              </el-button>
+            </template>
+          </el-table-column>
+        </el-table-column>
+      </el-table>
+    </div>
+  </div>
+</template>
+
+<script>
+import { getSfStatistics } from "@/api/system/user";
+import ExcelJS from "exceljs";
+import { saveAs } from "file-saver";
+
+export default {
+  name: 'SecondFollowUp',
+  props: {
+    queryParams: {
+      type: Object,
+      required: true
+    },
+    flatArrayhospit: {
+      type: Array,
+      default: () => []
+    },
+    flatArraydept: {
+      type: Array,
+      default: () => []
+    },
+    options: {
+      type: Array,
+      default: () => []
+    },
+    orgname: {
+      type: String,
+      default: ''
+    }
+  },
+  data() {
+    return {
+      tableData: [],
+      loading: false,
+      expands: [],
+      ids: []
+    }
+  },
+  methods: {
+    loadData() {
+      this.loading = true
+      const params = {
+        ...this.queryParams,
+        visitCount: 2,
+        leavehospitaldistrictcodes: this.queryParams.leavehospitaldistrictcodes.includes("all")
+          ? this.getAllWardCodes()
+          : this.queryParams.leavehospitaldistrictcodes,
+        deptcodes: this.queryParams.deptcodes.includes("all")
+          ? this.getAllDeptCodes()
+          : this.queryParams.deptcodes
+      }
+
+      delete params.leavehospitaldistrictcodes.all
+      delete params.deptcodes.all
+
+      getSfStatistics(params)
+        .then(response => {
+          this.tableData = this.customSort(response.data)
+        })
+        .catch(error => {
+          console.error("鑾峰彇鍐嶆闅忚鏁版嵁澶辫触:", error)
+          this.$message.error("鑾峰彇鍐嶆闅忚鏁版嵁澶辫触")
+        })
+        .finally(() => {
+          this.loading = false
+        })
+    },
+
+    getAllWardCodes() {
+      return this.flatArrayhospit
+        .filter(item => item.value !== 'all')
+        .map(item => item.value)
+    },
+
+    getAllDeptCodes() {
+      return this.flatArraydept
+        .filter(item => item.value !== 'all')
+        .map(item => item.value)
+    },
+
+    customSort(data) {
+      const order = [
+        "涓�","浜�","涓�","鍥�","浜�","鍏�","涓�","鍏�","涔�","鍗�",
+        "鍗佷竴","鍗佷簩","鍗佷笁","鍗佸洓","鍗佷簲","鍗佸叚","鍗佷竷","鍗佸叓","鍗佷節","浜屽崄",
+        "浜屽崄涓�","浜屽崄浜�","浜屽崄涓�","浜屽崄鍥�","浜屽崄浜�","浜屽崄鍏�","浜屽崄涓�","浜屽崄鍏�","浜屽崄涔�","涓夊崄",
+        "涓夊崄涓�","涓夊崄浜�","涓夊崄涓�","涓夊崄鍥�","涓夊崄浜�","涓夊崄鍏�","涓夊崄涓�","涓夊崄鍏�","涓夊崄涔�","鍥涘崄",
+        "鍥涘崄涓�","鍥涘崄浜�","鍥涘崄涓�","鍥涘崄鍥�","鍥涘崄浜�"
+      ]
+
+      return data.sort((a, b) => {
+        const getIndex = (name) => {
+          if (!name || typeof name !== "string") return -1
+          const chineseMatch = name.match(/^([涓�浜屼笁鍥涗簲鍏竷鍏節鍗乚+)/)
+          if (chineseMatch && chineseMatch[1]) {
+            return order.indexOf(chineseMatch[1])
+          }
+          const arabicMatch = name.match(/^(\d+)/)
+          if (arabicMatch && arabicMatch[1]) {
+            const num = parseInt(arabicMatch[1], 10)
+            if (num >= 1 && num <= 45) {
+              return num - 1
+            }
+          }
+          return -1
+        }
+
+        const indexA = getIndex(a.leavehospitaldistrictname)
+        const indexB = getIndex(b.leavehospitaldistrictname)
+
+        if (indexA === -1 && indexB === -1) {
+          return (a.leavehospitaldistrictname || "").localeCompare(b.leavehospitaldistrictname || "")
+        }
+        if (indexA === -1) return 1
+        if (indexB === -1) return -1
+        return indexA - indexB
+      })
+    },
+
+    sortChineseNumber(aRow, bRow) {
+      const a = aRow.leavehospitaldistrictname
+      const b = bRow.leavehospitaldistrictname
+
+      const chineseNumMap = {
+        涓�:1,浜�:2,涓�:3,鍥�:4,浜�:5,鍏�:6,涓�:7,鍏�:8,涔�:9,鍗�:10,
+        鍗佷竴:11,鍗佷簩:12,鍗佷笁:13,鍗佸洓:14,鍗佷簲:15,鍗佸叚:16,鍗佷竷:17,鍗佸叓:18,鍗佷節:19,浜屽崄:20,
+        浜屽崄涓�:21,浜屽崄浜�:22,浜屽崄涓�:23,浜屽崄鍥�:24,浜屽崄浜�:25,浜屽崄鍏�:26,浜屽崄涓�:27,浜屽崄鍏�:28,浜屽崄涔�:29,涓夊崄:30,
+        涓夊崄涓�:31,涓夊崄浜�:32,涓夊崄涓�:33,涓夊崄鍥�:34,涓夊崄浜�:35,涓夊崄鍏�:36,涓夊崄涓�:37,涓夊崄鍏�:38,涓夊崄涔�:39,鍥涘崄:40,
+        鍥涘崄涓�:41,鍥涘崄浜�:42,鍥涘崄涓�:43,鍥涘崄鍥�:44,鍥涘崄浜�:45
+      }
+
+      const getNumberFromText = (text) => {
+        if (!text || typeof text !== "string") return -1
+        const match = text.match(/^([涓�浜屼笁鍥涗簲鍏竷鍏節鍗乚+)/)
+        if (match && match[1]) {
+          const chineseNum = match[1]
+          return chineseNumMap[chineseNum] !== undefined ? chineseNumMap[chineseNum] : -1
+        }
+        const arabicMatch = text.match(/^(\d+)/)
+        if (arabicMatch && arabicMatch[1]) {
+          const num = parseInt(arabicMatch[1], 10)
+          return num >= 1 && num <= 45 ? num : -1
+        }
+        return -1
+      }
+
+      const numA = getNumberFromText(a)
+      const numB = getNumberFromText(b)
+
+      if (numA === -1 && numB === -1) {
+        return (a || "").localeCompare(b || "")
+      }
+      if (numA === -1) return 1
+      if (numB === -1) return -1
+      return numA - numB
+    },
+
+    getRowKey(row) {
+      return row.statisticaltype === 1 ? row.leavehospitaldistrictcode : row.deptcode
+    },
+
+    handleRowClick(row) {
+      if (this.expands.includes(this.getRowKey(row))) {
+        this.expands = []
+        return
+      }
+
+      const params = {
+        ...this.queryParams,
+        deptcodes: this.queryParams.deptcodes.includes("all")
+          ? this.getAllDeptCodes()
+          : this.queryParams.deptcodes,
+        leavehospitaldistrictcodes: [row.leavehospitaldistrictcode],
+        drcode: "1",
+        visitCount: 2
+      }
+
+      delete params.leavehospitaldistrictcodes.all
+      delete params.deptcodes.all
+
+      if (!row.doctorStats) {
+        this.loading = true
+        getSfStatistics(params).then((res) => {
+          this.$set(row, "doctorStats", res.data)
+          this.expands = [this.getRowKey(row)]
+          this.loading = false
+        })
+      } else {
+        this.expands = [this.getRowKey(row)]
+      }
+    },
+
+    getSummaries(param) {
+      const { columns, data } = param
+      const sums = []
+
+      columns.forEach((column, index) => {
+        if (index === 0) {
+          sums[index] = "鍚堣"
+          return
+        }
+        if (index === 1 || index === 2) {
+          sums[index] = "/"
+          return
+        }
+
+        if (column.property === "followUpRateAgain") {
+          const percentageValues = data
+            .map((item) => {
+              const value = item[column.property]
+              if (!value || value === "-" || value === "0%") return null
+              if (typeof value === "string" && value.includes("%")) {
+                const numValue = parseFloat(value.replace("%", "")) / 100
+                return isNaN(numValue) ? null : numValue
+              } else {
+                const numValue = parseFloat(value)
+                return isNaN(numValue) ? null : numValue
+              }
+            })
+            .filter((value) => value !== null && value !== 0)
+
+          if (percentageValues.length > 0) {
+            const average = percentageValues.reduce((sum, value) => sum + value, 0) / percentageValues.length
+            sums[index] = (average * 100).toFixed(2) + "%"
+          } else {
+            sums[index] = "0.00%"
+          }
+        } else {
+          const values = data.map((item) => {
+            const value = item[column.property]
+            if (value === "-" || value === "" || value === null) return 0
+            return Number(value) || 0
+          })
+
+          if (!values.every((value) => isNaN(value))) {
+            sums[index] = values.reduce((prev, curr) => prev + curr, 0)
+            sums[index] = this.formatNumber(sums[index])
+          } else {
+            sums[index] = "-"
+          }
+        }
+      })
+
+      return sums
+    },
+
+    getInnerSummaries(param) {
+      const { columns, data } = param
+      const sums = []
+
+      columns.forEach((column, index) => {
+        if (index === 0) {
+          sums[index] = "灏忚"
+          return
+        }
+
+        if (column.property === "drname" || column.property === "deptname") {
+          sums[index] = "-"
+          return
+        }
+
+        if (column.property === "followUpRateAgain") {
+          const percentageValues = data
+            .map((item) => {
+              const value = item[column.property]
+              if (!value || value === "-" || value === "0%") return null
+              if (typeof value === "string" && value.includes("%")) {
+                const numValue = parseFloat(value.replace("%", "")) / 100
+                return isNaN(numValue) ? null : numValue
+              } else {
+                const numValue = parseFloat(value)
+                return isNaN(numValue) ? null : numValue
+              }
+            })
+            .filter((value) => value !== null && value !== 0)
+
+          if (percentageValues.length > 0) {
+            const average = percentageValues.reduce((sum, value) => sum + value, 0) / percentageValues.length
+            sums[index] = (average * 100).toFixed(2) + "%"
+          } else {
+            sums[index] = "0.00%"
+          }
+        } else {
+          const values = data.map((item) => {
+            const value = item[column.property]
+            if (value === "-" || value === "" || value === null) return 0
+            return Number(value) || 0
+          })
+
+          if (!values.every((value) => isNaN(value))) {
+            sums[index] = values.reduce((prev, curr) => prev + curr, 0)
+            sums[index] = this.formatNumber(sums[index])
+          } else {
+            sums[index] = "-"
+          }
+        }
+      })
+
+      return sums
+    },
+
+    formatNumber(num) {
+      if (isNaN(num)) return "-"
+      return Number.isInteger(num) ? num.toString() : num.toFixed(0)
+    },
+
+    handleSelectionChange(selection) {
+      this.ids = selection.map((item) => item.tagid)
+    },
+
+    handleViewDetails(row, infoKey, titleSuffix) {
+      const title = `${row.leavehospitaldistrictname || row.deptname}${titleSuffix}`
+      this.$emit('view-details', row[infoKey], title)
+    },
+
+    async exportTable() {
+      try {
+        let dateRangeString = ""
+        let sheetNameSuffix = ""
+
+        if (this.queryParams.dateRange && this.queryParams.dateRange.length === 2) {
+          const startDateStr = this.queryParams.dateRange[0]
+          const endDateStr = this.queryParams.dateRange[1]
+          const formatDateForDisplay = (dateTimeStr) => {
+            return dateTimeStr.split(" ")[0]
+          }
+          const startDateFormatted = formatDateForDisplay(startDateStr)
+          const endDateFormatted = formatDateForDisplay(endDateStr)
+          dateRangeString = `${startDateFormatted}鑷�${endDateFormatted}`
+          sheetNameSuffix = `${startDateFormatted}鑷�${endDateFormatted}`
+        } else {
+          const now = new Date()
+          const currentMonth = now.getMonth() + 1
+          dateRangeString = `${currentMonth}鏈坄
+          sheetNameSuffix = `${currentMonth}鏈坄
+        }
+
+        const excelName = `鍐嶆鍑洪櫌闅忚缁熻琛╛${dateRangeString}.xlsx`
+        const worksheetName = `鍐嶆闅忚缁熻_${sheetNameSuffix}`
+
+        if (!this.tableData || this.tableData.length === 0) {
+          this.$message.warning("鏆傛棤鍐嶆闅忚鏁版嵁鍙鍑�")
+          return false
+        }
+
+        const workbook = new ExcelJS.Workbook()
+        const worksheet = workbook.addWorksheet(worksheetName)
+
+        // 鏋勫缓琛ㄦ牸
+        this.buildExportSheet(worksheet, sheetNameSuffix)
+
+        const buffer = await workbook.xlsx.writeBuffer()
+        const blob = new Blob([buffer], {
+          type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
+        })
+        saveAs(blob, excelName)
+
+        this.$message.success("瀵煎嚭鎴愬姛")
+        return true
+      } catch (error) {
+        console.error("瀵煎嚭澶辫触:", error)
+        this.$message.error(`瀵煎嚭澶辫触: ${error.message}`)
+        return false
+      }
+    },
+
+    buildExportSheet(worksheet, sheetNameSuffix) {
+      const titleStyle = {
+        font: { name: "寰蒋闆呴粦", size: 16, bold: true, color: { argb: "FF000000" } },
+        fill: { type: "pattern", pattern: "solid", fgColor: { argb: "FFE6F3FF" } },
+        alignment: { vertical: "middle", horizontal: "center", wrapText: true },
+        border: {
+          top: { style: "thin", color: { argb: "FFD0D0D0" } },
+          left: { style: "thin", color: { argb: "FFD0D0D0" } },
+          bottom: { style: "thin", color: { argb: "FFD0D0D0" } },
+          right: { style: "thin", color: { argb: "FFD0D0D0" } }
+        }
+      }
+
+      const headerStyle = {
+        font: { name: "寰蒋闆呴粦", size: 11, bold: true, color: { argb: "FF000000" } },
+        fill: { type: "pattern", pattern: "solid", fgColor: { argb: "FFF5F7FA" } },
+        alignment: { vertical: "middle", horizontal: "center", wrapText: true },
+        border: {
+          top: { style: "thin", color: { argb: "FFD0D0D0" } },
+          left: { style: "thin", color: { argb: "FFD0D0D0" } },
+          bottom: { style: "thin", color: { argb: "FFD0D0D0" } },
+          right: { style: "thin", color: { argb: "FFD0D0D0" } }
+        }
+      }
+
+      const cellStyle = {
+        font: { name: "瀹嬩綋", size: 10, color: { argb: "FF000000" } },
+        alignment: { vertical: "middle", horizontal: "center" },
+        border: {
+          top: { style: "thin", color: { argb: "FFD0D0D0" } },
+          left: { style: "thin", color: { argb: "FFD0D0D0" } },
+          bottom: { style: "thin", color: { argb: "FFD0D0D0" } },
+          right: { style: "thin", color: { argb: "FFD0D0D0" } }
+        }
+      }
+
+      const summaryStyle = {
+        font: { name: "瀹嬩綋", size: 10, bold: true, color: { argb: "FF409EFF" } },
+        fill: { type: "pattern", pattern: "solid", fgColor: { argb: "FFF5F7FA" } },
+        alignment: { vertical: "middle", horizontal: "center" },
+        border: {
+          top: { style: "thin", color: { argb: "FFD0D0D0" } },
+          left: { style: "thin", color: { argb: "FFD0D0D0" } },
+          bottom: { style: "thin", color: { argb: "FFD0D0D0" } },
+          right: { style: "thin", color: { argb: "FFD0D0D0" } }
+        }
+      }
+
+      // 娣诲姞鏍囬琛�
+      worksheet.mergeCells(1, 1, 1, 15)
+      const titleCell = worksheet.getCell(1, 1)
+      titleCell.value = `鍐嶆鍑洪櫌闅忚缁熻琛╛${sheetNameSuffix}`
+      titleCell.style = titleStyle
+      worksheet.getRow(1).height = 35
+
+      // 琛ㄥご
+      const secondRowHeaders = [
+        "", "鍑洪櫌鐥呭尯", "绉戝", "鍑洪櫌浜烘", "鏃犻渶闅忚浜烘", "搴旈殢璁夸汉娆�",
+        "闇�闅忚", "寰呴殢璁�", "闅忚鎴愬姛", "闅忚澶辫触", "闅忚鐜�", "浜哄伐", "鐭俊", "寰俊"
+      ]
+
+      secondRowHeaders.forEach((header, index) => {
+        const cell = worksheet.getCell(3, index + 1)
+        cell.value = header
+        cell.style = headerStyle
+      })
+
+      // 鍚堝苟鍗曞厓鏍�
+      for (let i = 1; i <= 6; i++) {
+        worksheet.mergeCells(2, i, 3, i)
+        const cell = worksheet.getCell(2, i)
+        cell.style = headerStyle
+      }
+
+      worksheet.getCell(2, 1).value = ""
+      worksheet.getCell(2, 2).value = "鍑洪櫌鐥呭尯"
+      worksheet.getCell(2, 3).value = "绉戝"
+      worksheet.getCell(2, 4).value = "鍑洪櫌浜烘"
+      worksheet.getCell(2, 5).value = "鏃犻渶闅忚浜烘"
+      worksheet.getCell(2, 6).value = "搴旈殢璁夸汉娆�"
+
+      worksheet.mergeCells(2, 7, 2, 14)
+      worksheet.getCell(2, 7).value = "鍐嶆鍑洪櫌闅忚"
+      worksheet.getCell(2, 7).style = headerStyle
+
+      worksheet.getRow(2).height = 28
+      worksheet.getRow(3).height = 25
+
+      // 鏁版嵁琛�
+      this.tableData.forEach((item, rowIndex) => {
+        const dataRow = worksheet.addRow([
+          "",
+          item.leavehospitaldistrictname || "",
+          item.deptname || "",
+          item.dischargeCount || 0,
+          item.nonFollowUp || 0,
+          item.followUpNeeded || 0,
+          item.needFollowUpAgain || 0,
+          item.pendingFollowUpAgain || 0,
+          item.followUpSuccessAgain || 0,
+          item.followUpFailAgain || 0,
+          item.followUpRateAgain || "0%",
+          item.manualAgain || 0,
+          item.smsAgain || 0,
+          item.weChatAgain || 0
+        ], rowIndex + 4)
+
+        dataRow.eachCell((cell) => {
+          cell.style = cellStyle
+        })
+        dataRow.height = 24
+      })
+
+      // 鍚堣琛�
+      const summaries = this.getExportSummaries()
+      const summaryRow = worksheet.addRow(summaries)
+      summaryRow.eachCell((cell, colNumber) => {
+        cell.style = summaryStyle
+        if (colNumber === 1) {
+          cell.value = "鍚堣"
+        }
+      })
+      summaryRow.height = 28
+
+      // 鍒楀
+      worksheet.columns = [
+        { width: 8 }, { width: 20 }, { width: 15 }, { width: 12 }, { width: 12 }, { width: 12 },
+        { width: 10 }, { width: 10 }, { width: 10 }, { width: 10 }, { width: 12 },
+        { width: 8 }, { width: 8 }, { width: 8 }
+      ]
+    },
+
+    getExportSummaries() {
+      const summaries = ["鍚堣", "/", "/", 0, 0, 0, 0, 0, 0, 0, "0%", 0, 0, 0]
+
+      this.tableData.forEach((item) => {
+        summaries[3] += Number(item.dischargeCount) || 0
+        summaries[4] += Number(item.nonFollowUp) || 0
+        summaries[5] += Number(item.followUpNeeded) || 0
+        summaries[6] += Number(item.needFollowUpAgain) || 0
+        summaries[7] += Number(item.pendingFollowUpAgain) || 0
+        summaries[8] += Number(item.followUpSuccessAgain) || 0
+        summaries[9] += Number(item.followUpFailAgain) || 0
+        summaries[11] += Number(item.manualAgain) || 0
+        summaries[12] += Number(item.smsAgain) || 0
+        summaries[13] += Number(item.weChatAgain) || 0
+      })
+
+      const followUpRateAgainValues = this.tableData
+        .map((item) => this.extractPercentageValue(item.followUpRateAgain))
+        .filter((value) => value !== null)
+
+      if (followUpRateAgainValues.length > 0) {
+        const avgFollowUpRateAgain = followUpRateAgainValues.reduce((sum, val) => sum + val, 0) / followUpRateAgainValues.length
+        summaries[10] = (avgFollowUpRateAgain * 100).toFixed(2) + "%"
+      }
+
+      summaries[3] = this.formatNumber(summaries[3])
+      summaries[4] = this.formatNumber(summaries[4])
+      summaries[5] = this.formatNumber(summaries[5])
+      summaries[6] = this.formatNumber(summaries[6])
+      summaries[7] = this.formatNumber(summaries[7])
+      summaries[8] = this.formatNumber(summaries[8])
+      summaries[9] = this.formatNumber(summaries[9])
+      summaries[11] = this.formatNumber(summaries[11])
+      summaries[12] = this.formatNumber(summaries[12])
+      summaries[13] = this.formatNumber(summaries[13])
+
+      return summaries
+    },
+
+    extractPercentageValue(value) {
+      if (!value) return null
+      if (typeof value === "string" && value.includes("%")) {
+        const num = parseFloat(value.replace("%", ""))
+        return isNaN(num) ? null : num / 100
+      }
+      const num = parseFloat(value)
+      return isNaN(num) ? null : num
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.second-follow-up {
+  .your-table-container {
+    margin-top: 10px;
+  }
+
+  .button-zx {
+    color: rgb(70, 204, 238);
+  }
+}
+</style>
diff --git a/src/views/sfstatistics/percentage/components/TimelyRateDialog.vue b/src/views/sfstatistics/percentage/components/TimelyRateDialog.vue
new file mode 100644
index 0000000..e3122a4
--- /dev/null
+++ b/src/views/sfstatistics/percentage/components/TimelyRateDialog.vue
@@ -0,0 +1,249 @@
+<template>
+  <el-dialog
+    title="鏈強鏃堕殢璁挎偅鑰呮湇鍔�"
+    :visible.sync="visible"
+    v-loading="loading"
+    width="70%"
+    :close-on-click-modal="false"
+    @close="handleClose"
+  >
+    <div class="timely-rate-dialog">
+      <div class="examine-jic">
+        <div class="jic-value">
+          <el-row :gutter="20">
+            <!-- 鎼滅储琛ㄥ崟 -->
+            <el-form
+              :model="queryParams"
+              ref="queryForm"
+              size="small"
+              :inline="true"
+              label-width="98px"
+              class="search-form"
+            >
+              <el-form-item label="鎮h�咃細">
+                <el-input
+                  v-model="queryParams.name"
+                  placeholder="璇疯緭鍏ユ偅鑰呭鍚�"
+                  @keyup.enter.native="handleSearch"
+                />
+              </el-form-item>
+              <el-form-item label="鎮h�呰瘖鏂細">
+                <el-input
+                  v-model="queryParams.leavediagname"
+                  placeholder="璇疯緭鍏ユ偅鑰呰瘖鏂�"
+                  @keyup.enter.native="handleSearch"
+                />
+              </el-form-item>
+
+              <el-form-item>
+                <el-button
+                  type="primary"
+                  icon="el-icon-search"
+                  size="medium"
+                  @click="handleSearch"
+                >
+                  鎼滅储
+                </el-button>
+                <el-button
+                  icon="el-icon-refresh"
+                  size="medium"
+                  @click="resetQuery"
+                >
+                  閲嶇疆
+                </el-button>
+              </el-form-item>
+            </el-form>
+
+            <!-- 鎮h�呭垪琛� -->
+            <el-table :data="data" style="width: 100%" v-loading="loading">
+              <el-table-column prop="sendname" align="center" label="濮撳悕" width="100" />
+              <el-table-column prop="taskName" align="center" width="200" show-overflow-tooltip label="浠诲姟鍚嶇О" />
+
+              <el-table-column prop="sendstate" align="center" width="200" label="浠诲姟鐘舵��">
+                <template slot-scope="scope">
+                  <el-tag
+                    :type="getStateTagType(scope.row.sendstate)"
+                    :disable-transitions="false"
+                  >
+                    {{ getStateText(scope.row.sendstate) }}
+                  </el-tag>
+                </template>
+              </el-table-column>
+
+              <el-table-column prop="visitTime" align="center" label="搴旈殢璁挎椂闂�" width="200" show-overflow-tooltip />
+              <el-table-column prop="finishtime" align="center" label="闅忚瀹屾垚鏃堕棿" width="200" show-overflow-tooltip />
+
+              <el-table-column label="鍑洪櫌鏃ユ湡" width="200" align="center" key="endtime" prop="endtime">
+                <template slot-scope="scope">
+                  <span>{{ formatTime(scope.row.endtime) }}</span>
+                </template>
+              </el-table-column>
+
+              <el-table-column label="璐d换鎶ゅ+" width="120" align="center" key="nurseName" prop="nurseName" />
+              <el-table-column label="涓绘不鍖荤敓" width="120" align="center" key="drname" prop="drname" />
+
+              <el-table-column label="缁撴灉鐘舵��" align="center" key="excep" prop="excep" width="120">
+                <template slot-scope="scope">
+                  <dict-tag :options="dict.type.sys_yujing" :value="scope.row.excep" />
+                </template>
+              </el-table-column>
+
+              <el-table-column label="澶勭悊鎰忚" align="center" key="suggest" prop="suggest" width="120">
+                <template slot-scope="scope">
+                  <dict-tag :options="dict.type.sys_suggest" :value="scope.row.suggest" />
+                </template>
+              </el-table-column>
+
+              <el-table-column prop="templatename" align="center" label="鏈嶅姟妯℃澘" width="200" show-overflow-tooltip />
+              <el-table-column prop="remark" align="center" label="鏈嶅姟璁板綍" width="200" show-overflow-tooltip />
+
+              <el-table-column prop="bankcardno" align="center" label="鍛煎彨鐘舵��" width="210" />
+
+              <el-table-column label="鎿嶄綔" fixed="right" align="center" width="200" class-name="small-padding fixed-width">
+                <template slot-scope="scope">
+                  <el-button size="medium" type="text" @click="handleDetailsGo(scope.row)">
+                    <span class="button-zx">
+                      <i class="el-icon-s-order"></i>鏌ョ湅
+                    </span>
+                  </el-button>
+                </template>
+              </el-table-column>
+            </el-table>
+          </el-row>
+
+          <!-- 鍒嗛〉 -->
+          <pagination
+            v-show="total > 0"
+            :total="total"
+            :page.sync="queryParams.pn"
+            :limit.sync="queryParams.ps"
+            @pagination="handlePagination"
+          />
+        </div>
+      </div>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import Pagination from '@/components/Pagination'
+
+export default {
+  name: 'TimelyRateDialog',
+  components: {
+    Pagination
+  },
+  dicts: ['sys_yujing', 'sys_suggest'],
+  props: {
+    visible: {
+      type: Boolean,
+      default: false
+    },
+    loading: {
+      type: Boolean,
+      default: false
+    },
+    data: {
+      type: Array,
+      default: () => []
+    },
+    total: {
+      type: Number,
+      default: 0
+    },
+    queryParams: {
+      type: Object,
+      default: () => ({
+        pn: 1,
+        ps: 10
+      })
+    }
+  },
+  data() {
+    return {
+      localQueryParams: { ...this.queryParams }
+    }
+  },
+  watch: {
+    queryParams: {
+      deep: true,
+      handler(newParams) {
+        this.localQueryParams = { ...newParams }
+      }
+    }
+  },
+  mounted() {
+    this.localQueryParams = { ...this.queryParams }
+  },
+  methods: {
+    handleSearch() {
+      this.$emit('search', this.localQueryParams)
+    },
+
+    resetQuery() {
+      this.localQueryParams = {
+        pn: 1,
+        ps: 10,
+        name: '',
+        leavediagname: ''
+      }
+      this.$emit('search', this.localQueryParams)
+    },
+
+    handlePagination(pagination) {
+      this.localQueryParams.pn = pagination.page
+      this.localQueryParams.ps = pagination.limit
+      this.$emit('search', this.localQueryParams)
+    },
+
+    getStateTagType(state) {
+      const stateMap = {
+        1: 'primary',
+        2: 'primary',
+        3: 'success',
+        4: 'info',
+        5: 'danger',
+        6: 'success'
+      }
+      return stateMap[state] || 'info'
+    },
+
+    getStateText(state) {
+      const stateTextMap = {
+        1: '琛ㄥ崟宸查鍙�',
+        2: '寰呴殢璁�',
+        3: '琛ㄥ崟宸插彂閫�',
+        4: '涓嶆墽琛�',
+        5: '鍙戦�佸け璐�',
+        6: '宸插畬鎴�'
+      }
+      return stateTextMap[state] || '鏈煡鐘舵��'
+    },
+
+    formatTime(time) {
+      if (!time) return ''
+      return this.parseTime(time)
+    },
+
+    handleDetailsGo(row) {
+      this.$emit('details-go', row)
+    },
+
+    handleClose() {
+      this.$emit('close')
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.timely-rate-dialog {
+  .search-form {
+    margin-bottom: 20px;
+  }
+
+  .button-zx {
+    color: rgb(70, 204, 238);
+  }
+}
+</style>
diff --git a/src/views/sfstatistics/percentage/components/styles.scss b/src/views/sfstatistics/percentage/components/styles.scss
new file mode 100644
index 0000000..49f2005
--- /dev/null
+++ b/src/views/sfstatistics/percentage/components/styles.scss
@@ -0,0 +1,90 @@
+// 鍏ㄥ眬鏍峰紡
+.follow-up-statistics,
+.first-follow-up,
+.second-follow-up,
+.continued-care {
+  .your-table-container {
+    margin-top: 10px;
+  }
+
+  .button-zx {
+    color: rgb(70, 204, 238);
+  }
+
+  // 缇庡寲鍚堣琛屾牱寮�
+  ::v-deep .el-table__footer {
+    .el-table__cell {
+      background-color: #f5f7fa;
+      font-weight: 600;
+      color: #409eff;
+
+      .cell {
+        font-weight: 600;
+        color: #409eff;
+      }
+    }
+  }
+
+  // 鍐呴儴琛ㄦ牸鍚堣琛屾牱寮�
+  ::v-deep .inner-table .el-table__footer {
+    .el-table__cell {
+      background-color: #ecf5ff;
+      font-weight: 500;
+      color: #67c23a;
+
+      .cell {
+        font-weight: 500;
+        color: #67c23a;
+      }
+    }
+  }
+
+  // 鐧惧垎姣斿瓧娈电壒娈婃牱寮�
+  ::v-deep .el-table__footer .el-table__cell[data-field="followUpRate"] .cell,
+  ::v-deep .el-table__footer .el-table__cell[data-field="rate"] .cell,
+  ::v-deep .el-table__footer .el-table__cell[data-field="followUpRateAgain"] .cell,
+  ::v-deep .el-table__footer .el-table__cell[data-field="completionRate"] .cell {
+    color: #e6a23c !important;
+    font-weight: 700 !important;
+  }
+
+  // 鍐呭眰鍖荤敓琛ㄦ牸鏍峰紡
+  .inner-table {
+    ::v-deep .el-table__header-wrapper {
+      background-color: #f0f7ff !important;
+
+      th {
+        background-color: #f0f7ff !important;
+      }
+    }
+
+    ::v-deep .el-table__body-wrapper {
+      tr {
+        background-color: #f9fbfe !important;
+
+        &:hover {
+          background-color: #e6f1ff !important;
+        }
+      }
+    }
+
+    ::v-deep .el-table--border {
+      border-color: #d9e8ff !important;
+
+      td, th {
+        border-color: #d9e8ff !important;
+      }
+    }
+  }
+
+  /* 浣胯鏈夋墜鍨嬫寚閽� */
+  ::v-deep .el-table__row {
+    cursor: pointer;
+  }
+
+  /* 灞曞紑琛屾牱寮� */
+  ::v-deep .el-table__expanded-cell {
+    padding: 10px 0 !important;
+    background: #f8f8f8;
+  }
+}
diff --git a/src/views/sfstatistics/percentage/index copy.vue b/src/views/sfstatistics/percentage/index copy.vue
new file mode 100644
index 0000000..d025fa2
--- /dev/null
+++ b/src/views/sfstatistics/percentage/index copy.vue
@@ -0,0 +1,2898 @@
+<template>
+  <div class="Questionnairemanagement">
+    <div class="leftvlue">
+      <div class="leftvlue-bg">
+        <el-row :gutter="20">
+          <!--鏍囩鏁版嵁-->
+          <el-col :span="24" :xs="24">
+            <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch"
+              label-width="98px">
+              <el-form-item label="缁熻绫诲瀷" prop="userName">
+                <el-select v-model="queryParams.statisticaltype" placeholder="璇烽�夋嫨缁熻绫诲瀷">
+                  <el-option v-for="item in Statisticallist" :key="item.value" :label="item.label" :value="item.value">
+                  </el-option>
+                </el-select>
+                <el-select style="margin-left: 10px" v-if="queryParams.statisticaltype == 1"
+                  v-model="queryParams.leavehospitaldistrictcodes" size="medium" multiple filterable
+                  placeholder="璇烽�夋嫨鐥呭尯">
+                  <el-option v-for="item in flatArrayhospit" :key="item.value" :label="item.label" :value="item.value">
+                  </el-option>
+                </el-select>
+                <el-select v-else-if="queryParams.statisticaltype == 2" v-model="queryParams.deptcodes" size="medium"
+                  multiple filterable placeholder="璇烽�夋嫨绉戝">
+                  <el-option v-for="item in flatArraydept" :key="item.value" :label="item.label" :value="item.value">
+                  </el-option>
+                </el-select>
+              </el-form-item>
+
+              <el-form-item label="鏈嶅姟绫诲瀷" prop="userName">
+                <el-select v-model="queryParams.serviceType" multiple placeholder="璇烽�夋嫨">
+                  <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value">
+                  </el-option>
+                </el-select>
+              </el-form-item>
+              <el-form-item label-width="200" label="搴旈殢璁挎椂闂磋寖鍥�" prop="userName">
+                <el-date-picker v-model="queryParams.dateRange" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
+                  range-separator="鑷�" start-placeholder="寮�濮嬫棩鏈�" end-placeholder="缁撴潫鏃ユ湡"
+                  :default-time="['00:00:00', '23:59:59']">
+                </el-date-picker>
+              </el-form-item>
+
+              <el-form-item>
+                <el-button type="primary" icon="el-icon-search" size="medium" @click="handleQuery">鎼滅储</el-button>
+                <el-button icon="el-icon-refresh" size="medium" @click="resetQuery">閲嶇疆</el-button>
+              </el-form-item>
+              <el-button type="warning" plain icon="el-icon-download" size="medium" @click="exportTable">瀵煎嚭</el-button>
+              <el-button type="primary" plain icon="el-icon-data-line" size="medium"
+                @click="showChartDialog">缁熻瓒嬪娍鍥�</el-button>
+            </el-form>
+
+            <!-- 鏂板锛歍ab鏍囩椤� -->
+            <el-tabs v-model="activeTab" @tab-click="handleTabClick">
+              <el-tab-pane label="棣栨闅忚" name="first">
+                <div class="your-table-container">
+                  <el-table ref="exportTable" id="exportTableid" v-loading="loading" :data="firstFollowUpList"
+                    :border="true" @selection-change="handleSelectionChange" @expand-change="handleRowClick"
+                    :row-key="getRowKey" show-summary :summary-method="getSummaries" :expand-row-keys="expands">
+                    <!-- 灞曞紑琛岀澶村垪 -->
+                    <el-table-column type="expand">
+                      <template slot-scope="props">
+                        <el-table :data="props.row.doctorStats" border style="width: 95%; margin: 0 auto"
+                          class="inner-table" show-summary :summary-method="getInnerSummaries">
+                          <el-table-column label="鍖荤敓濮撳悕" prop="drname" align="center" />
+                          <el-table-column label="绉戝" width="120" prop="deptname" align="center" />
+                          <el-table-column label="鍑洪櫌浜烘" prop="dischargeCount" align="center" />
+                          <el-table-column label="鍑洪櫌浜烘" align="center" key="dischargeCount" prop="dischargeCount">
+                          </el-table-column>
+
+                          <el-table-column label="鏃犻渶闅忚浜烘" align="center" width="100" key="nonFollowUp"
+                            prop="nonFollowUp">
+                          </el-table-column>
+                          <el-table-column label="搴旈殢璁夸汉娆�" align="center" width="100" key="followUpNeeded"
+                            prop="followUpNeeded">
+                          </el-table-column>
+                          <el-table-column align="center" label="棣栨鍑洪櫌闅忚">
+                            <el-table-column label="闇�闅忚" align="center" key="needFollowUp" prop="needFollowUp">
+                            </el-table-column>
+                            <el-table-column label="寰呴殢璁�" align="center" key="pendingFollowUp" prop="pendingFollowUp">
+                            </el-table-column>
+                            <el-table-column label="闅忚鎴愬姛" align="center" key="followUpSuccess" prop="followUpSuccess">
+                            </el-table-column>
+                            <el-table-column label="闅忚澶辫触" align="center" key="followUpFail" prop="followUpFail">
+                            </el-table-column>
+                            <el-table-column label="闅忚鐜�" align="center" width="120" key="followUpRate"
+                              prop="followUpRate">
+                            </el-table-column>
+                            <el-table-column v-if="orgname != '涓芥按甯備腑鍖婚櫌'" label="鍙婃椂鐜�" align="center" width="120"
+                              key="rate" prop="rate">
+                              <template slot-scope="scope">
+                                <el-button size="medium" type="text" @click="Seedetails(scope.row)"><span
+                                    class="button-zx">{{
+                                      (Number(scope.row.rate) * 100).toFixed(2)
+                                    }}%</span></el-button>
+                              </template>
+                            </el-table-column>
+                            <el-table-column label="浜哄伐" align="center" key="manual" prop="manual">
+                            </el-table-column>
+                            <el-table-column label="鐭俊" align="center" key="sms" prop="sms">
+                            </el-table-column>
+                            <el-table-column label="寰俊" align="center" key="weChat" prop="weChat">
+                            </el-table-column>
+                          </el-table-column>
+                        </el-table>
+                      </template>
+                    </el-table-column>
+                    <el-table-column label="鍑洪櫌鐥呭尯" align="center" sortable key="leavehospitaldistrictname"
+                      prop="leavehospitaldistrictname" width="150" :show-overflow-tooltip="true"
+                      :sort-method="sortChineseNumber" />
+                    <el-table-column label="绉戝" align="center" key="deptname" prop="deptname"
+                      :show-overflow-tooltip="true" />
+                    <el-table-column label="鍑洪櫌浜烘" align="center" key="dischargeCount" prop="dischargeCount">
+                    </el-table-column>
+
+                    <el-table-column label="鏃犻渶闅忚浜烘" align="center" width="100" key="nonFollowUp" prop="nonFollowUp">
+                    </el-table-column>
+                    <el-table-column label="搴旈殢璁夸汉娆�" align="center" width="100" key="followUpNeeded"
+                      prop="followUpNeeded">
+                    </el-table-column>
+                    <el-table-column align="center" label="棣栨鍑洪櫌闅忚">
+                      <el-table-column label="闇�闅忚" align="center" key="needFollowUp" prop="needFollowUp">
+                        <template slot-scope="scope">
+                          <el-button size="medium" type="text" @click="
+                            viewDetails(
+                              scope.row.needFollowUpInfo,
+                              scope.row.leavehospitaldistrictname +
+                              '闇�闅忚鍒楄〃'
+                            )
+                            "><span class="button-zx">{{
+                              scope.row.needFollowUp
+                            }}</span></el-button>
+                        </template>
+                      </el-table-column>
+                      <el-table-column label="寰呴殢璁�" align="center" key="pendingFollowUp" prop="pendingFollowUp">
+                        <template slot-scope="scope">
+                          <el-button size="medium" type="text" @click="
+                            viewDetails(
+                              scope.row.pendingFollowUpInfo,
+                              scope.row.leavehospitaldistrictname +
+                              '寰呴殢璁垮垪琛�'
+                            )
+                            "><span class="button-zx">{{
+                              scope.row.pendingFollowUp
+                            }}</span></el-button>
+                        </template>
+                      </el-table-column>
+                      <el-table-column label="闅忚鎴愬姛" align="center" key="followUpSuccess" prop="followUpSuccess">
+                        <template slot-scope="scope">
+                          <el-button size="medium" type="text" @click="
+                            viewDetails(
+                              scope.row.followUpSuccessInfo,
+                              scope.row.leavehospitaldistrictname +
+                              '闅忚鎴愬姛鍒楄〃'
+                            )
+                            "><span class="button-zx">{{
+                              scope.row.followUpSuccess
+                            }}</span></el-button>
+                        </template>
+                      </el-table-column>
+                      <el-table-column label="闅忚澶辫触" align="center" key="followUpFail" prop="followUpFail">
+                        <template slot-scope="scope">
+                          <el-button size="medium" type="text" @click="
+                            viewDetails(
+                              scope.row.followUpFailInfo,
+                              scope.row.leavehospitaldistrictname +
+                              '闅忚澶辫触鍒楄〃'
+                            )
+                            "><span class="button-zx">{{
+                              scope.row.followUpFail
+                            }}</span></el-button>
+                        </template>
+                      </el-table-column>
+                      <el-table-column label="闅忚鐜�" align="center" width="120" key="followUpRate" prop="followUpRate">
+                      </el-table-column>
+                      <el-table-column v-if="orgname != '涓芥按甯備腑鍖婚櫌'" label="鍙婃椂鐜�" align="center" width="120" key="rate"
+                        prop="rate">
+                        <template slot-scope="scope">
+                          <el-button size="medium" type="text" @click="Seedetails(scope.row)"><span class="button-zx">{{
+                            (Number(scope.row.rate) * 100).toFixed(2)
+                          }}%</span></el-button>
+                        </template>
+                      </el-table-column>
+                      <el-table-column label="浜哄伐" align="center" key="manual" prop="manual">
+                        <template slot-scope="scope">
+                          <el-button size="medium" type="text" @click="
+                            viewDetails(
+                              scope.row.manualInfo,
+                              scope.row.leavehospitaldistrictname +
+                              '浜哄伐闅忚鍒楄〃'
+                            )
+                            "><span class="button-zx">{{
+                              scope.row.manual
+                            }}</span></el-button>
+                        </template>
+                      </el-table-column>
+                      <el-table-column label="鐭俊" align="center" key="sms" prop="sms">
+                        <template slot-scope="scope">
+                          <el-button size="medium" type="text" @click="
+                            viewDetails(
+                              scope.row.smsInfo,
+                              scope.row.leavehospitaldistrictname +
+                              '鐭俊闅忚鍒楄〃'
+                            )
+                            "><span class="button-zx">{{
+                              scope.row.sms
+                            }}</span></el-button>
+                        </template>
+                      </el-table-column>
+                      <el-table-column label="寰俊" align="center" key="weChat" prop="weChat">
+                        <template slot-scope="scope">
+                          <el-button size="medium" type="text" @click="
+                            viewDetails(
+                              scope.row.weChatInfo,
+                              scope.row.leavehospitaldistrictname +
+                              '寰俊闅忚鍒楄〃'
+                            )
+                            "><span class="button-zx">{{
+                              scope.row.weChat
+                            }}</span></el-button>
+                        </template>
+                      </el-table-column>
+                    </el-table-column>
+
+                    <!-- 闅忚鎯呭喌鍒楋紙浠呬附姘村競涓尰闄㈡樉绀猴級 -->
+                    <el-table-column v-if="orgname == '涓芥按甯備腑鍖婚櫌'" align="center" label="闅忚鎯呭喌">
+                      <el-table-column label="姝e父璇煶" align="center" width="100" key="taskSituation1"
+                        prop="taskSituation1">
+                      </el-table-column><el-table-column label="鎮h�呮嫆鎺ユ垨鎷掕" align="center" width="100" key="taskSituation2"
+                        prop="taskSituation2">
+                      </el-table-column><el-table-column label="闈㈣鎴栬�呮帴璇�" align="center" width="100" key="taskSituation3"
+                        prop="taskSituation3">
+                      </el-table-column><el-table-column label="寰俊闅忚" align="center" width="100" key="taskSituation4"
+                        prop="taskSituation4">
+                      </el-table-column><el-table-column label="闅忚鐢佃瘽涓嶆纭�" align="center" width="100" key="taskSituation5"
+                        prop="taskSituation5">
+                      </el-table-column><el-table-column label="鍏朵粬鎯呭喌涓嶅疁闅忚" align="center" width="100"
+                        key="taskSituation6" prop="taskSituation6">
+                      </el-table-column>
+                    </el-table-column>
+                  </el-table>
+                </div>
+              </el-tab-pane>
+
+              <el-tab-pane label="鍐嶆闅忚" name="second">
+                <div class="your-table-container">
+                  <el-table ref="exportTableSecond" id="exportTableidSecond" v-loading="loadingSecond"
+                    :data="secondFollowUpList" :border="true" @selection-change="handleSelectionChangeSecond"
+                    @expand-change="handleRowClickSecond" :row-key="getRowKey" show-summary
+                    :summary-method="getSummariesSecond" :expand-row-keys="expandsSecond">
+                    <!-- 灞曞紑琛岀澶村垪 -->
+                    <el-table-column type="expand">
+                      <template slot-scope="props">
+                        <el-table :data="props.row.doctorStats" border style="width: 95%; margin: 0 auto"
+                          class="inner-table" show-summary :summary-method="getInnerSummariesSecond">
+                          <el-table-column label="鍖荤敓濮撳悕" prop="drname" align="center" />
+                          <el-table-column label="绉戝" width="120" prop="deptname" align="center" />
+                          <el-table-column label="鍑洪櫌浜烘" prop="dischargeCount" align="center" />
+                          <el-table-column label="鍑洪櫌浜烘" align="center" key="dischargeCount" prop="dischargeCount">
+                          </el-table-column>
+
+                          <el-table-column label="鏃犻渶闅忚浜烘" align="center" width="100" key="nonFollowUp"
+                            prop="nonFollowUp">
+                          </el-table-column>
+                          <el-table-column label="搴旈殢璁夸汉娆�" align="center" width="100" key="followUpNeeded"
+                            prop="followUpNeeded">
+                          </el-table-column>
+                          <el-table-column align="center" label="鍐嶆鍑洪櫌闅忚">
+                            <el-table-column label="闇�闅忚" align="center" key="needFollowUpAgain"
+                              prop="needFollowUpAgain">
+                            </el-table-column>
+                            <el-table-column label="寰呴殢璁�" align="center" key="pendingFollowUpAgain"
+                              prop="pendingFollowUpAgain">
+                            </el-table-column>
+                            <el-table-column label="闅忚鎴愬姛" align="center" key="followUpSuccessAgain"
+                              prop="followUpSuccessAgain">
+                            </el-table-column>
+                            <el-table-column label="闅忚澶辫触" align="center" key="followUpFailAgain"
+                              prop="followUpFailAgain">
+                            </el-table-column>
+                            <el-table-column label="闅忚鐜�" align="center" width="120" key="followUpRateAgain"
+                              prop="followUpRateAgain">
+                            </el-table-column>
+                            <el-table-column label="浜哄伐" align="center" key="manualAgain" prop="manualAgain">
+                            </el-table-column>
+                            <el-table-column label="鐭俊" align="center" key="smsAgain" prop="smsAgain">
+                            </el-table-column>
+                            <el-table-column label="寰俊" align="center" key="weChatAgain" prop="weChatAgain">
+                            </el-table-column>
+                          </el-table-column>
+                        </el-table>
+                      </template>
+                    </el-table-column>
+                    <el-table-column label="鍑洪櫌鐥呭尯" align="center" sortable key="leavehospitaldistrictname"
+                      prop="leavehospitaldistrictname" width="150" :show-overflow-tooltip="true"
+                      :sort-method="sortChineseNumber" />
+                    <el-table-column label="绉戝" align="center" key="deptname" prop="deptname"
+                      :show-overflow-tooltip="true" />
+                    <el-table-column label="鍑洪櫌浜烘" align="center" key="dischargeCount" prop="dischargeCount">
+                    </el-table-column>
+
+                    <el-table-column label="鏃犻渶闅忚浜烘" align="center" width="100" key="nonFollowUp" prop="nonFollowUp">
+                    </el-table-column>
+                    <el-table-column label="搴旈殢璁夸汉娆�" align="center" width="100" key="followUpNeeded"
+                      prop="followUpNeeded">
+                    </el-table-column>
+                    <el-table-column align="center" label="鍐嶆鍑洪櫌闅忚">
+                      <el-table-column label="闇�闅忚" align="center" key="needFollowUpAgain" prop="needFollowUpAgain">
+                        <template slot-scope="scope">
+                          <el-button size="medium" type="text" @click="
+                            viewDetails(
+                              scope.row.needFollowUpAgainInfo,
+                              scope.row.leavehospitaldistrictname +
+                              '鍐嶆闅忚闇�闅忚鍒楄〃'
+                            )
+                            "><span class="button-zx">{{
+                              scope.row.needFollowUpAgain
+                            }}</span></el-button>
+                        </template>
+                      </el-table-column>
+                      <el-table-column label="寰呴殢璁�" align="center" key="pendingFollowUpAgain"
+                        prop="pendingFollowUpAgain">
+                        <template slot-scope="scope">
+                          <el-button size="medium" type="text" @click="
+                            viewDetails(
+                              scope.row.pendingFollowUpAgainInfo,
+                              scope.row.leavehospitaldistrictname +
+                              '鍐嶆闅忚寰呴殢璁垮垪琛�'
+                            )
+                            "><span class="button-zx">{{
+                              scope.row.pendingFollowUpAgain
+                            }}</span></el-button>
+                        </template>
+                      </el-table-column>
+                      <el-table-column label="闅忚鎴愬姛" align="center" key="followUpSuccessAgain"
+                        prop="followUpSuccessAgain">
+                        <template slot-scope="scope">
+                          <el-button size="medium" type="text" @click="
+                            viewDetails(
+                              scope.row.followUpSuccessAgainInfo,
+                              scope.row.leavehospitaldistrictname +
+                              '鍐嶆闅忚闅忚鎴愬姛鍒楄〃'
+                            )
+                            "><span class="button-zx">{{
+                              scope.row.followUpSuccessAgain
+                            }}</span></el-button>
+                        </template>
+                      </el-table-column>
+                      <el-table-column label="闅忚澶辫触" align="center" key="followUpFailAgain" prop="followUpFailAgain">
+                        <template slot-scope="scope">
+                          <el-button size="medium" type="text" @click="
+                            viewDetails(
+                              scope.row.followUpFailAgainInfo,
+                              scope.row.leavehospitaldistrictname +
+                              '鍐嶆闅忚闅忚澶辫触鍒楄〃'
+                            )
+                            "><span class="button-zx">{{
+                              scope.row.followUpFailAgain
+                            }}</span></el-button>
+                        </template>
+                      </el-table-column>
+                      <el-table-column label="闅忚鐜�" align="center" width="120" key="followUpRateAgain"
+                        prop="followUpRateAgain">
+                      </el-table-column>
+                      <el-table-column label="浜哄伐" align="center" key="manualAgain" prop="manualAgain">
+                        <template slot-scope="scope">
+                          <el-button size="medium" type="text" @click="
+                            viewDetails(
+                              scope.row.manualAgainInfo,
+                              scope.row.leavehospitaldistrictname +
+                              '鍐嶆闅忚浜哄伐闅忚鍒楄〃'
+                            )
+                            "><span class="button-zx">{{
+                              scope.row.manualAgain
+                            }}</span></el-button>
+                        </template>
+                      </el-table-column>
+                      <el-table-column label="鐭俊" align="center" key="smsAgain" prop="smsAgain">
+                        <template slot-scope="scope">
+                          <el-button size="medium" type="text" @click="
+                            viewDetails(
+                              scope.row.smsAgainInfo,
+                              scope.row.leavehospitaldistrictname +
+                              '鍐嶆闅忚鐭俊闅忚鍒楄〃'
+                            )
+                            "><span class="button-zx">{{
+                              scope.row.smsAgain
+                            }}</span></el-button>
+                        </template>
+                      </el-table-column>
+                      <el-table-column label="寰俊" align="center" key="weChatAgain" prop="weChatAgain">
+                        <template slot-scope="scope">
+                          <el-button size="medium" type="text" @click="
+                            viewDetails(
+                              scope.row.weChatAgainInfo,
+                              scope.row.leavehospitaldistrictname +
+                              '鍐嶆闅忚寰俊闅忚鍒楄〃'
+                            )
+                            "><span class="button-zx">{{
+                              scope.row.weChatAgain
+                            }}</span></el-button>
+                        </template>
+                      </el-table-column>
+                    </el-table-column>
+                  </el-table>
+                </div>
+              </el-tab-pane>
+            </el-tabs>
+          </el-col>
+        </el-row>
+      </div>
+    </div>
+    <!-- 缁熻瓒嬪娍鍥惧脊绐� -->
+    <el-dialog title="闅忚缁熻瓒嬪娍鍥�" :visible.sync="chartDialogVisible" width="80%" :close-on-click-modal="false">
+      <div class="chart-container">
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <div class="chart-title">闅忚鐘舵�佸垎甯�</div>
+            <div id="pieChart" style="width: 100%; height: 400px"></div>
+          </el-col>
+          <el-col :span="12">
+            <div class="chart-title">闅忚瓒嬪娍鍒嗘瀽</div>
+            <div id="barLineChart" style="width: 100%; height: 400px"></div>
+          </el-col>
+        </el-row>
+      </div>
+    </el-dialog>
+    <el-dialog title="鏈強鏃堕殢璁挎偅鑰呮湇鍔�" :visible.sync="SeedetailsVisible" v-loading="Seedloading" width="70%"
+      :close-on-click-modal="false">
+      <div class="examine-jic">
+        <div class="jic-value">
+          <el-row :gutter="20">
+            <!--鐢ㄦ埛鏁版嵁-->
+            <el-form :model="patientqueryParams" ref="queryForm" size="small" :inline="true" label-width="98px">
+              <el-form-item label="鎮h�咃細">
+                <el-input v-model="patientqueryParams.name" @keyup.enter.native="handleQuery"></el-input>
+              </el-form-item>
+              <el-form-item label="鎮h�呰瘖鏂細">
+                <el-input v-model="patientqueryParams.leavediagname" @keyup.enter.native="handleQuery"></el-input>
+              </el-form-item>
+
+              <el-form-item>
+                <el-button type="primary" icon="el-icon-search" size="medium" @click="handleQuery">鎼滅储</el-button>
+                <el-button icon="el-icon-refresh" size="medium" @click="resetQuery">鍙栨秷鍒涘缓</el-button>
+              </el-form-item>
+            </el-form>
+            <!-- 閫夋嫨鎮h�呭垪琛� -->
+            <el-table :data="logsheetlist" style="width: 100%">
+              <el-table-column prop="sendname" align="center" label="濮撳悕" width="100">
+              </el-table-column>
+              <el-table-column prop="taskName" align="center" width="200" show-overflow-tooltip label="浠诲姟鍚嶇О">
+              </el-table-column>
+              <el-table-column prop="sendstate" align="center" width="200" label="浠诲姟鐘舵��">
+                <template slot-scope="scope">
+                  <div v-if="scope.row.sendstate == 1">
+                    <el-tag type="primary" :disable-transitions="false">琛ㄥ崟宸查鍙�</el-tag>
+                  </div>
+                  <div v-if="scope.row.sendstate == 2">
+                    <el-tag type="primary" :disable-transitions="false">寰呴殢璁�</el-tag>
+                  </div>
+                  <div v-if="scope.row.sendstate == 3">
+                    <el-tag type="success" :disable-transitions="false">琛ㄥ崟宸插彂閫�</el-tag>
+                  </div>
+                  <div v-if="scope.row.sendstate == 4">
+                    <el-tag type="info" :disable-transitions="false">涓嶆墽琛�</el-tag>
+                  </div>
+                  <div v-if="scope.row.sendstate == 5">
+                    <el-tag type="danger" :disable-transitions="false">鍙戦�佸け璐�</el-tag>
+                  </div>
+                  <div v-if="scope.row.sendstate == 6">
+                    <el-tag type="success" :disable-transitions="false">宸插畬鎴�</el-tag>
+                  </div>
+                </template>
+              </el-table-column>
+              <el-table-column prop="visitTime" align="center" label="搴旈殢璁挎椂闂�" width="200" show-overflow-tooltip>
+              </el-table-column>
+              <el-table-column prop="finishtime" align="center" label="闅忚瀹屾垚鏃堕棿" width="200" show-overflow-tooltip>
+              </el-table-column>
+              <el-table-column label="鍑洪櫌鏃ユ湡" width="200" align="center" key="endtime" prop="endtime">
+                <template slot-scope="scope">
+                  <span>{{ formatTime(scope.row.endtime) }}</span>
+                </template></el-table-column>
+              <el-table-column label="璐d换鎶ゅ+" width="120" align="center" key="nurseName" prop="nurseName" />
+              <el-table-column label="涓绘不鍖荤敓" width="120" align="center" key="drname" prop="drname" />
+
+              <el-table-column label="缁撴灉鐘舵��" align="center" key="excep" prop="excep" width="120">
+                <template slot-scope="scope">
+                  <dict-tag :options="dict.type.sys_yujing" :value="scope.row.excep" />
+                </template>
+              </el-table-column>
+              <el-table-column label="澶勭悊鎰忚" align="center" key="suggest" prop="suggest" width="120">
+                <template slot-scope="scope">
+                  <dict-tag :options="dict.type.sys_suggest" :value="scope.row.suggest" />
+                </template>
+              </el-table-column>
+
+              <el-table-column prop="templatename" align="center" label="鏈嶅姟妯℃澘" width="200" show-overflow-tooltip>
+              </el-table-column>
+              <el-table-column prop="remark" align="center" label="鏈嶅姟璁板綍" width="200" show-overflow-tooltip>
+              </el-table-column>
+
+              <el-table-column prop="bankcardno" align="center" label="鍛煎彨鐘舵��" width="210">
+              </el-table-column>
+              <el-table-column label="鎿嶄綔" fixed="right" align="center" width="200"
+                class-name="small-padding fixed-width">
+                <template slot-scope="scope">
+                  <el-button size="medium" type="text" @click="SeedetailsgGo(scope.row)"><span class="button-zx"><i
+                        class="el-icon-s-order"></i>鏌ョ湅</span></el-button>
+                </template>
+              </el-table-column>
+            </el-table>
+          </el-row>
+          <pagination v-show="patienttotal > 0 && this.patientqueryParams.allhosp != 6" :total="patienttotal"
+            :page.sync="patientqueryParams.pn" :limit.sync="patientqueryParams.ps" @pagination="Seedetailstion" />
+        </div>
+      </div>
+    </el-dialog>
+    <!-- 鍚勭被璇︽儏 -->
+    <el-dialog :title="infotitle" :visible.sync="infotitleVisible" v-loading="infotitloading" width="70%"
+      :close-on-click-modal="false">
+      <div style="margin-bottom: 16px; display: flex; align-items: center">
+        <span style="margin-right: 10px; font-weight: bold">鎮h�呭鍚嶆煡璇�:</span>
+        <el-input v-model="searchName" placeholder="璇疯緭鍏ユ偅鑰呭鍚嶈繘琛岀瓫閫�" clearable style="width: 300px" @input="handleSearch"
+          @clear="handleSearch">
+        </el-input>
+        <span style="margin-left: 10px; color: rgb(35, 81, 233); font-size: 16px">
+          鍏� {{ infotitlelist.length }} 鏉¤褰�
+        </span>
+      </div>
+      <div class="examine-jic">
+        <div class="jic-value">
+          <el-row :gutter="20">
+            <!-- 閫夋嫨鎮h�呭垪琛� -->
+            <div class="data-list" ref="dataList" @scroll="handleScroll" v-loading="infotitloading">
+              <el-table :data="currentDisplayList" height="660" style="width: 100%">
+                <el-table-column prop="sendname" align="center" label="濮撳悕" width="100">
+                </el-table-column>
+                <el-table-column prop="taskName" align="center" width="200" show-overflow-tooltip label="浠诲姟鍚嶇О">
+                </el-table-column>
+                <el-table-column prop="sendstate" align="center" width="200" label="浠诲姟鐘舵��">
+                  <template slot-scope="scope">
+                    <div v-if="scope.row.sendstate == 1">
+                      <el-tag type="primary" :disable-transitions="false">琛ㄥ崟宸查鍙�</el-tag>
+                    </div>
+                    <div v-if="scope.row.sendstate == 2">
+                      <el-tag type="primary" :disable-transitions="false">寰呴殢璁�</el-tag>
+                    </div>
+                    <div v-if="scope.row.sendstate == 3">
+                      <el-tag type="success" :disable-transitions="false">琛ㄥ崟宸插彂閫�</el-tag>
+                    </div>
+                    <div v-if="scope.row.sendstate == 4">
+                      <el-tag type="info" :disable-transitions="false">涓嶆墽琛�</el-tag>
+                    </div>
+                    <div v-if="scope.row.sendstate == 5">
+                      <el-tag type="danger" :disable-transitions="false">鍙戦�佸け璐�</el-tag>
+                    </div>
+                    <div v-if="scope.row.sendstate == 6">
+                      <el-tag type="success" :disable-transitions="false">宸插畬鎴�</el-tag>
+                    </div>
+                  </template>
+                </el-table-column>
+                <el-table-column label="浠诲姟鎵ц鏂瑰紡" align="center" key="preachform" prop="preachform" width="160"
+                  :show-overflow-tooltip="true">
+                  <template slot-scope="scope">
+                    <span v-for="item in scope.row.preachform">{{ item }}銆�
+                    </span>
+                  </template>
+                </el-table-column>
+                <el-table-column prop="visitTime" align="center" label="搴旈殢璁挎椂闂�" width="200" show-overflow-tooltip>
+                </el-table-column>
+                <el-table-column prop="finishtime" align="center" label="闅忚瀹屾垚鏃堕棿" width="200" show-overflow-tooltip>
+                </el-table-column>
+                <el-table-column label="鍑洪櫌鏃ユ湡" width="200" align="center" key="endtime" prop="endtime">
+                  <template slot-scope="scope">
+                    <span>{{ formatTime(scope.row.endtime) }}</span>
+                  </template></el-table-column>
+                <el-table-column label="璐d换鎶ゅ+" width="120" align="center" key="nurseName" prop="nurseName" />
+                <el-table-column label="涓绘不鍖荤敓" width="120" align="center" key="drname" prop="drname" />
+
+                <el-table-column label="缁撴灉鐘舵��" align="center" key="excep" prop="excep" width="120">
+                  <template slot-scope="scope">
+                    <dict-tag :options="dict.type.sys_yujing" :value="scope.row.excep" />
+                  </template>
+                </el-table-column>
+                <el-table-column label="澶勭悊鎰忚" align="center" key="suggest" prop="suggest" width="120">
+                  <template slot-scope="scope">
+                    <dict-tag :options="dict.type.sys_suggest" :value="scope.row.suggest" />
+                  </template>
+                </el-table-column>
+
+                <el-table-column prop="templatename" align="center" label="鏈嶅姟妯℃澘" width="200" show-overflow-tooltip>
+                </el-table-column>
+                <el-table-column prop="remark" align="center" label="鏈嶅姟璁板綍" width="200" show-overflow-tooltip>
+                </el-table-column>
+
+                <el-table-column prop="bankcardno" align="center" label="鍛煎彨鐘舵��" width="210">
+                </el-table-column>
+                <el-table-column label="鎿嶄綔" fixed="right" align="center" width="200"
+                  class-name="small-padding fixed-width">
+                  <template slot-scope="scope">
+                    <el-button size="medium" type="text" @click="SeedetailsgGo(scope.row)"><span class="button-zx"><i
+                          class="el-icon-s-order"></i>鏌ョ湅</span></el-button>
+                  </template>
+                </el-table-column>
+              </el-table>
+            </div>
+          </el-row>
+        </div>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import {
+  toamendtag,
+  addapitag,
+  deletetag,
+  changetagcategory,
+} from "@/api/system/label";
+import store from "@/store";
+import { getSfStatistics, selectTimelyRate } from "@/api/system/user";
+import * as XLSX from "xlsx";
+import FileSaver from "file-saver";
+import ExcelJS from "exceljs";
+import { saveAs } from "file-saver";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+
+const shortcuts = [
+  {
+    text: "浠婂ぉ",
+    onClick(picker) {
+      picker.$emit("pick", new Date());
+    },
+  },
+  {
+    text: "鏄ㄥぉ",
+    onClick(picker) {
+      const date = new Date();
+      date.setTime(date.getTime() - 3600 * 1000 * 24);
+      picker.$emit("pick", date);
+    },
+  },
+  {
+    text: "涓�鍛ㄥ墠",
+    onClick(picker) {
+      const date = new Date();
+      date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);
+      picker.$emit("pick", date);
+    },
+  },
+];
+
+export default {
+  name: "Percentage",
+  dicts: ["sys_normal_disable", "sys_user_sex"],
+  components: { Treeselect },
+  data() {
+    return {
+      // 鏂板锛歍ab鏍囩椤垫帶鍒�
+      activeTab: "first", // 褰撳墠婵�娲荤殑tab锛宖irst-棣栨闅忚锛宻econd-鍐嶆闅忚
+
+      // 鍒嗙鐨勬暟鎹垪琛�
+      firstFollowUpList: [], // 棣栨闅忚鏁版嵁
+      secondFollowUpList: [], // 鍐嶆闅忚鏁版嵁
+
+      // 鍒嗙鐨勫姞杞界姸鎬�
+      loading: false, // 棣栨闅忚琛ㄦ牸鍔犺浇鐘舵��
+      loadingSecond: false, // 鍐嶆闅忚琛ㄦ牸鍔犺浇鐘舵��
+
+      // 鍒嗙鐨勫睍寮�鐘舵��
+      expands: [], // 棣栨闅忚琛ㄦ牸灞曞紑琛�
+      expandsSecond: [], // 鍐嶆闅忚琛ㄦ牸灞曞紑琛�
+
+      // 鍒嗙鐨勯�夋嫨鐘舵��
+      ids: [], // 棣栨闅忚閫変腑椤�
+      idsSecond: [], // 鍐嶆闅忚閫変腑椤�
+
+      orgname: "",
+      infotitlelist: [],
+      currentDisplayList: [],
+      loadIndex: 0,
+      pageSize: 100,
+      isLoading: false,
+
+      Seedloading: false,
+      chartDialogVisible: false,
+      infotitleVisible: false,
+      searchName: "",
+      infotitloading: false,
+      infotitle: "",
+      pieChart: null,
+      barLineChart: null,
+
+      single: true,
+      multiple: true,
+      showSearch: true,
+      idds: "",
+      total: 0,
+      flatArrayhospit: [],
+      flatArraydept: [],
+      patienttotal: 0,
+      logsheetlist: [],
+      Statisticallist: [
+        {
+          label: "鐥呭尯缁熻",
+          value: 1,
+        },
+        {
+          label: "绉戝缁熻",
+          value: 2,
+        },
+      ],
+      patientqueryParams: {
+        pn: 1,
+        ps: 10,
+      },
+      amendtag: false,
+      lstamendtag: false,
+      scavisible: false,
+      deleteVisible: false,
+      deletefenl: "楂樿鍘�",
+      tagform: {
+        isupload: "",
+        tagname: "",
+        tagcategoryid: "",
+        tagdescription: "",
+      },
+      classifyform: {
+        categoryname: "",
+      },
+      title: "",
+      open: false,
+      dateRange: [],
+      postOptions: [],
+      roleOptions: [],
+      allDeptCodes: [],
+      allWardCodes: [],
+      checkboxlist: [],
+      form: {},
+      forms: {
+        name: "",
+      },
+      numberlb: 22,
+      dialogFormVisible: false,
+      lstamendtagVisible: false,
+      goQRCodeVisible: false,
+      sidecolumnval: "",
+      propss: { multiple: true },
+      SeedetailsVisible: false,
+      options: store.getters.tasktypes,
+      pickerOptions: {
+        disabledDate(time) {
+          return time.getTime() < Date.now() - 3600 * 1000 * 24;
+        },
+        shortcuts: shortcuts,
+      },
+      pickerOptionsa: {
+        disabledDate(time) {
+          return time.getTime() > Date.now();
+        },
+        shortcuts: shortcuts,
+      },
+      queryParams: {
+        serviceType: [2],
+        dateRange: [],
+        statisticaltype: 1,
+        leavehospitaldistrictcodes: ["all"],
+        deptcodes: [],
+        visitCount: 1, // 鏂板锛氶殢璁挎鏁板弬鏁帮紝1-棣栨锛�2-鍐嶆
+      },
+      columns: [
+        { key: 0, label: `鏍囩缂栧彿`, visible: true },
+        { key: 1, label: `鏍囩鍚嶇О`, visible: true },
+        { key: 2, label: `鏍囩鏄电О`, visible: true },
+        { key: 3, label: `閮ㄩ棬`, visible: true },
+        { key: 4, label: `鎵嬫満鍙风爜`, visible: true },
+        { key: 5, label: `鐘舵�乣, visible: true },
+        { key: 6, label: `鍒涘缓鏃堕棿`, visible: true },
+      ],
+    };
+  },
+  watch: {},
+  created() {
+    this.getDeptTree();
+    this.getFirstFollowUpList(); // 榛樿鍔犺浇棣栨闅忚鏁版嵁
+    this.checkboxlist = store.getters.checkboxlist;
+    this.orgname = localStorage.getItem("orgname");
+  },
+
+  methods: {
+    /** 鏌ヨ棣栨闅忚鍒楄〃 */
+    async getFirstFollowUpList() {
+      this.loading = true;
+      this.queryParams.visitCount = 1; // 璁剧疆闅忚娆℃暟涓洪娆�
+
+      const params = {
+        ...this.queryParams,
+        leavehospitaldistrictcodes:
+          this.queryParams.leavehospitaldistrictcodes.includes("all")
+            ? this.allWardCodes
+            : this.queryParams.leavehospitaldistrictcodes,
+        deptcodes: this.queryParams.deptcodes.includes("all")
+          ? this.allDeptCodes
+          : this.queryParams.deptcodes,
+      };
+
+      delete params.leavehospitaldistrictcodes.all;
+      delete params.deptcodes.all;
+
+      try {
+        const response = await getSfStatistics(params);
+        this.firstFollowUpList = this.customSort(response.data);
+        this.total = response.total;
+      } catch (error) {
+        console.error("鑾峰彇棣栨闅忚鏁版嵁澶辫触:", error);
+        this.$message.error("鑾峰彇棣栨闅忚鏁版嵁澶辫触");
+      } finally {
+        this.loading = false;
+      }
+    },
+
+    /** 鏌ヨ鍐嶆闅忚鍒楄〃 */
+    async getSecondFollowUpList() {
+      this.loadingSecond = true;
+      this.queryParams.visitCount = 2; // 璁剧疆闅忚娆℃暟涓哄啀娆�
+
+      const params = {
+        ...this.queryParams,
+        leavehospitaldistrictcodes:
+          this.queryParams.leavehospitaldistrictcodes.includes("all")
+            ? this.allWardCodes
+            : this.queryParams.leavehospitaldistrictcodes,
+        deptcodes: this.queryParams.deptcodes.includes("all")
+          ? this.allDeptCodes
+          : this.queryParams.deptcodes,
+      };
+
+      delete params.leavehospitaldistrictcodes.all;
+      delete params.deptcodes.all;
+
+      try {
+        const response = await getSfStatistics(params);
+        this.secondFollowUpList = this.customSort(response.data);
+        this.total = response.total;
+      } catch (error) {
+        console.error("鑾峰彇鍐嶆闅忚鏁版嵁澶辫触:", error);
+        this.$message.error("鑾峰彇鍐嶆闅忚鏁版嵁澶辫触");
+      } finally {
+        this.loadingSecond = false;
+      }
+    },
+
+    /** Tab鍒囨崲浜嬩欢 */
+    handleTabClick(tab) {
+      if (tab.name === "first") {
+        if (this.firstFollowUpList.length === 0) {
+          this.getFirstFollowUpList();
+        }
+      } else if (tab.name === "second") {
+        if (this.secondFollowUpList.length === 0) {
+          this.getSecondFollowUpList();
+        }
+      }
+    },
+    sortChineseNumber(aRow, bRow) {
+      const a = aRow.leavehospitaldistrictname;
+      const b = bRow.leavehospitaldistrictname;
+
+      // 涓枃鏁板瓧鍒伴樋鎷変集鏁板瓧鐨勬槧灏勶紙鎵╁睍鍒�45锛�
+      const chineseNumMap = {
+        涓�: 1,
+        浜�: 2,
+        涓�: 3,
+        鍥�: 4,
+        浜�: 5,
+        鍏�: 6,
+        涓�: 7,
+        鍏�: 8,
+        涔�: 9,
+        鍗�: 10,
+        鍗佷竴: 11,
+        鍗佷簩: 12,
+        鍗佷笁: 13,
+        鍗佸洓: 14,
+        鍗佷簲: 15,
+        鍗佸叚: 16,
+        鍗佷竷: 17,
+        鍗佸叓: 18,
+        鍗佷節: 19,
+        浜屽崄: 20,
+        浜屽崄涓�: 21,
+        浜屽崄浜�: 22,
+        浜屽崄涓�: 23,
+        浜屽崄鍥�: 24,
+        浜屽崄浜�: 25,
+        浜屽崄鍏�: 26,
+        浜屽崄涓�: 27,
+        浜屽崄鍏�: 28,
+        浜屽崄涔�: 29,
+        涓夊崄: 30,
+        涓夊崄涓�: 31,
+        涓夊崄浜�: 32,
+        涓夊崄涓�: 33,
+        涓夊崄鍥�: 34,
+        涓夊崄浜�: 35,
+        涓夊崄鍏�: 36,
+        涓夊崄涓�: 37,
+        涓夊崄鍏�: 38,
+        涓夊崄涔�: 39,
+        鍥涘崄: 40,
+        鍥涘崄涓�: 41,
+        鍥涘崄浜�: 42,
+        鍥涘崄涓�: 43,
+        鍥涘崄鍥�: 44,
+        鍥涘崄浜�: 45,
+      };
+
+      // 鎻愬彇涓枃鏁板瓧
+      const getNumberFromText = (text) => {
+        if (!text || typeof text !== "string") return -1;
+
+        // 鍖归厤涓枃鏁板瓧锛屾敮鎸佷竴鍒板洓鍗佷簲
+        const match = text.match(/^([涓�浜屼笁鍥涗簲鍏竷鍏節鍗乚+)/);
+
+        if (match && match[1]) {
+          const chineseNum = match[1];
+          return chineseNumMap[chineseNum] !== undefined
+            ? chineseNumMap[chineseNum]
+            : -1;
+        }
+
+        // 濡傛灉娌℃湁鍖归厤鍒颁腑鏂囨暟瀛楋紝灏濊瘯鍖归厤闃挎媺浼暟瀛�
+        const arabicMatch = text.match(/^(\d+)/);
+        if (arabicMatch && arabicMatch[1]) {
+          const num = parseInt(arabicMatch[1], 10);
+          return num >= 1 && num <= 45 ? num : -1;
+        }
+
+        return -1;
+      };
+
+      const numA = getNumberFromText(a);
+      const numB = getNumberFromText(b);
+
+      // 澶勭悊鏃犳硶瑙f瀽鐨勬儏鍐�
+      if (numA === -1 && numB === -1) {
+        return (a || "").localeCompare(b || "");
+      }
+      if (numA === -1) return 1;
+      if (numB === -1) return -1;
+
+      return numA - numB;
+    },
+    // 鎼滅储澶勭悊鍑芥暟
+    handleSearch() {
+      if (!this.searchName.trim()) {
+        // 濡傛灉鎼滅储妗嗕负绌猴紝鏄剧ず鎵�鏈夋暟鎹�
+        this.currentDisplayList = [...this.infotitlelist];
+      } else {
+        // 鏍规嵁鎮h�呭鍚嶈繘琛岀瓫閫夛紙涓嶅尯鍒嗗ぇ灏忓啓锛�
+        const keyword = this.searchName.toLowerCase();
+        this.currentDisplayList = this.infotitlelist.filter((item) => {
+          return item.sendname && item.sendname.toLowerCase().includes(keyword);
+        });
+      }
+    },
+    customSort(data) {
+      // 瀹氫箟鎮ㄦ湡鏈涚殑鐥呭尯椤哄簭锛堟墿灞曞埌鍥涘崄浜旓級
+      const order = [
+        "涓�",
+        "浜�",
+        "涓�",
+        "鍥�",
+        "浜�",
+        "鍏�",
+        "涓�",
+        "鍏�",
+        "涔�",
+        "鍗�",
+        "鍗佷竴",
+        "鍗佷簩",
+        "鍗佷笁",
+        "鍗佸洓",
+        "鍗佷簲",
+        "鍗佸叚",
+        "鍗佷竷",
+        "鍗佸叓",
+        "鍗佷節",
+        "浜屽崄",
+        "浜屽崄涓�",
+        "浜屽崄浜�",
+        "浜屽崄涓�",
+        "浜屽崄鍥�",
+        "浜屽崄浜�",
+        "浜屽崄鍏�",
+        "浜屽崄涓�",
+        "浜屽崄鍏�",
+        "浜屽崄涔�",
+        "涓夊崄",
+        "涓夊崄涓�",
+        "涓夊崄浜�",
+        "涓夊崄涓�",
+        "涓夊崄鍥�",
+        "涓夊崄浜�",
+        "涓夊崄鍏�",
+        "涓夊崄涓�",
+        "涓夊崄鍏�",
+        "涓夊崄涔�",
+        "鍥涘崄",
+        "鍥涘崄涓�",
+        "鍥涘崄浜�",
+        "鍥涘崄涓�",
+        "鍥涘崄鍥�",
+        "鍥涘崄浜�",
+      ];
+
+      return data.sort((a, b) => {
+        // 鎻愬彇鐥呭尯鍚嶇О涓殑涓枃鏁板瓧閮ㄥ垎
+        const getIndex = (name) => {
+          if (!name || typeof name !== "string") return -1;
+
+          // 鍖归厤涓枃鏁板瓧
+          const chineseMatch = name.match(/^([涓�浜屼笁鍥涗簲鍏竷鍏節鍗乚+)/);
+          if (chineseMatch && chineseMatch[1]) {
+            return order.indexOf(chineseMatch[1]);
+          }
+
+          // 鍖归厤闃挎媺浼暟瀛�
+          const arabicMatch = name.match(/^(\d+)/);
+          if (arabicMatch && arabicMatch[1]) {
+            const num = parseInt(arabicMatch[1], 10);
+            if (num >= 1 && num <= 45) {
+              return num - 1; // 鍥犱负鏁扮粍绱㈠紩浠�0寮�濮�
+            }
+          }
+
+          return -1;
+        };
+
+        const indexA = getIndex(a.leavehospitaldistrictname);
+        const indexB = getIndex(b.leavehospitaldistrictname);
+
+        // 鎺掑簭閫昏緫
+        if (indexA === -1 && indexB === -1) {
+          return (a.leavehospitaldistrictname || "").localeCompare(
+            b.leavehospitaldistrictname || ""
+          );
+        }
+        if (indexA === -1) return 1;
+        if (indexB === -1) return -1;
+        return indexA - indexB;
+      });
+    },
+    getRowKey(row) {
+      return row.statisticaltype === 1
+        ? row.leavehospitaldistrictcode
+        : row.deptcode;
+    },
+
+    // 澶勭悊琛岀偣鍑诲睍寮�
+    handleRowClick(row) {
+      console.log(row, "row");
+
+      // 濡傛灉宸茬粡灞曞紑鍒欐敹璧�
+      if (this.expands.includes(this.getRowKey(row))) {
+        this.expands = [];
+        return;
+      }
+      // 澶勭悊鏌ヨ鍙傛暟
+      const params = {
+        ...this.queryParams,
+        // 濡傛灉閫夋嫨浜�"鍏ㄩ儴"锛屽垯浼犳墍鏈夌梾鍖�/绉戝浠g爜
+        deptcodes: this.queryParams.deptcodes.includes("all")
+          ? this.allDeptCodes
+          : this.queryParams.deptcodes,
+        leavehospitaldistrictcodes: [row.leavehospitaldistrictcode],
+        drcode: "1",
+        visitCount: 1, // 璁剧疆涓洪娆¢殢璁�
+      };
+
+      // 绉婚櫎鍙兘瀛樺湪鐨�"all"鍊�
+      delete params.leavehospitaldistrictcodes.all;
+      delete params.deptcodes.all;
+      // 濡傛灉璇ヨ杩樻病鏈夊姞杞藉尰鐢熸暟鎹紝鍒欏姞杞�
+      if (!row.doctorStats) {
+        this.loading = true;
+        getSfStatistics(params).then((res) => {
+          this.$set(row, "doctorStats", res.data);
+          this.expands = [this.getRowKey(row)];
+          this.loading = false;
+        });
+      } else {
+        this.expands = [this.getRowKey(row)];
+      }
+    },
+    getSummaries(param) {
+      const { columns, data } = param;
+      const sums = [];
+
+      columns.forEach((column, index) => {
+        if (index === 0) {
+          sums[index] = "鍚堣";
+          return;
+        }
+        if (index === 1 || index === 2) {
+          sums[index] = "/";
+          return;
+        }
+
+        // 瀵圭櫨鍒嗘瘮瀛楁鐗规畩澶勭悊 - 鍙栧钩鍧囧��
+        if (
+          column.property === "followUpRate" ||
+          column.property === "rate" ||
+          column.property === "followUpRateAgain"
+        ) {
+          // 鎻愬彇鎵�鏈夋湁鏁堢櫨鍒嗘瘮鍊煎苟杞崲涓哄皬鏁�
+          const percentageValues = data
+            .map((item) => {
+              const value = item[column.property];
+              if (!value || value === "-" || value === "0%") return null;
+
+              // 澶勭悊甯︾櫨鍒嗗彿鐨勬暟鎹�
+              if (typeof value === "string" && value.includes("%")) {
+                // 鍘婚櫎鐧惧垎鍙峰苟杞崲涓哄皬鏁�
+                const numValue = parseFloat(value.replace("%", "")) / 100;
+                return isNaN(numValue) ? null : numValue;
+              } else {
+                // 澶勭悊宸茬粡鏄皬鏁扮殑鏁版嵁
+                const numValue = parseFloat(value);
+                return isNaN(numValue) ? null : numValue;
+              }
+            })
+            .filter((value) => value !== null && value !== 0); // 杩囨护鎺塶ull鍜�0鍊�
+
+          if (percentageValues.length > 0) {
+            const average =
+              percentageValues.reduce((sum, value) => sum + value, 0) /
+              percentageValues.length;
+            sums[index] = (average * 100).toFixed(2) + "%";
+          } else {
+            sums[index] = "0.00%";
+          }
+        } else {
+          // 鏅�氭暟瀛楀瓧娈� - 姹傚拰
+          const values = data.map((item) => {
+            const value = item[column.property];
+            if (value === "-" || value === "" || value === null) return 0;
+            return Number(value) || 0;
+          });
+
+          if (!values.every((value) => isNaN(value))) {
+            sums[index] = values.reduce((prev, curr) => prev + curr, 0);
+            sums[index] = this.formatNumber(sums[index]);
+          } else {
+            sums[index] = "-";
+          }
+        }
+      });
+
+      return sums;
+    },
+
+    // 鍐呴儴琛ㄦ牸鍚堣琛岃绠楁柟娉�
+    getInnerSummaries(param) {
+      const { columns, data } = param;
+      const sums = [];
+
+      columns.forEach((column, index) => {
+        if (index === 0) {
+          sums[index] = "灏忚";
+          return;
+        }
+
+        if (column.property === "drname" || column.property === "deptname") {
+          sums[index] = "-";
+          return;
+        }
+
+        // 瀵圭櫨鍒嗘瘮瀛楁鐗规畩澶勭悊 - 鍙栧钩鍧囧��
+        if (column.property === "followUpRate" || column.property === "rate") {
+          // 鎻愬彇鎵�鏈夋湁鏁堢櫨鍒嗘瘮鍊煎苟杞崲涓哄皬鏁�
+          const percentageValues = data
+            .map((item) => {
+              const value = item[column.property];
+              if (!value || value === "-" || value === "0%") return null;
+
+              // 澶勭悊甯︾櫨鍒嗗彿鐨勬暟鎹�
+              if (typeof value === "string" && value.includes("%")) {
+                // 鍘婚櫎鐧惧垎鍙峰苟杞崲涓哄皬鏁�
+                const numValue = parseFloat(value.replace("%", "")) / 100;
+                return isNaN(numValue) ? null : numValue;
+              } else {
+                // 澶勭悊宸茬粡鏄皬鏁扮殑鏁版嵁
+                const numValue = parseFloat(value);
+                return isNaN(numValue) ? null : numValue;
+              }
+            })
+            .filter((value) => value !== null && value !== 0);
+
+          if (percentageValues.length > 0) {
+            const average =
+              percentageValues.reduce((sum, value) => sum + value, 0) /
+              percentageValues.length;
+            sums[index] = (average * 100).toFixed(2) + "%";
+          } else {
+            sums[index] = "0.00%";
+          }
+        } else {
+          // 鏅�氭暟瀛楀瓧娈� - 姹傚拰
+          const values = data.map((item) => {
+            const value = item[column.property];
+            if (value === "-" || value === "" || value === null) return 0;
+            return Number(value) || 0;
+          });
+
+          if (!values.every((value) => isNaN(value))) {
+            sums[index] = values.reduce((prev, curr) => prev + curr, 0);
+            sums[index] = this.formatNumber(sums[index]);
+          } else {
+            sums[index] = "-";
+          }
+        }
+      });
+
+      return sums;
+    },
+
+    // 杈呭姪鏂规硶锛氭彁鍙栫櫨鍒嗘瘮鏁板��
+    extractPercentageValue(value) {
+      if (!value) return null;
+
+      if (typeof value === "string") {
+        // 澶勭悊甯︾櫨鍒嗗彿鐨勫瓧绗︿覆
+        if (value.includes("%")) {
+          const num = parseFloat(value.replace("%", ""));
+          return isNaN(num) ? null : num / 100;
+        }
+        // 澶勭悊绾暟瀛楀瓧绗︿覆
+        const num = parseFloat(value);
+        return isNaN(num) ? null : num;
+      }
+
+      // 澶勭悊鏁板瓧绫诲瀷
+      return typeof value === "number" ? value : null;
+    },
+
+    // 鏁板瓧鏍煎紡鍖栨柟娉�
+    formatNumber(num) {
+      if (isNaN(num)) return "-";
+      return Number.isInteger(num) ? num.toString() : num.toFixed(0);
+    },
+    /** 淇敼鏍囩 */
+    handleUpdate(row) {
+      console.log(row, "淇敼鏍囩");
+      this.lstamendtagVisible = true;
+      this.lstamendtag = true;
+      this.tagform = {
+        isupload: row.isupload,
+        tagname: row.tagname,
+        tagcategoryid: row.tagcategoryid,
+        tagdescription: row.tagdescription,
+        tagid: row.tagid,
+      };
+    },
+    // 鑾峰彇绉戝鏍�
+    getDeptTree() {
+      // 绉戝鍒楄〃
+      this.flatArraydept = store.getters.belongDepts.map((dept) => {
+        return {
+          label: dept.deptName,
+          value: dept.deptCode,
+        };
+      });
+      // 瀛樺偍鎵�鏈夌瀹や唬鐮�
+      this.allDeptCodes = store.getters.belongDepts.map(
+        (dept) => dept.deptCode
+      );
+
+      // 鐥呭尯鍒楄〃
+      this.flatArrayhospit = store.getters.belongWards.map((ward) => {
+        return {
+          label: ward.districtName,
+          value: ward.districtCode,
+        };
+      });
+
+      // 瀛樺偍鎵�鏈夌梾鍖轰唬鐮�
+      this.allWardCodes = store.getters.belongWards.map(
+        (ward) => ward.districtCode
+      );
+      this.flatArraydept.push({ label: "鍏ㄩ儴", value: "all" });
+      this.flatArrayhospit.push({ label: "鍏ㄩ儴", value: "all" });
+    },
+    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; // 杩斿洖鍙寘鍚渶搴曞眰鍏冪礌鐨勪竴缁存暟缁�
+    },
+    addladeltag() {
+      this.lstamendtagVisible = true;
+      this.lstamendtag = false;
+      this.tagform = {
+        isupload: "",
+        tagname: "",
+        tagcategoryid: "",
+        tagdescription: "",
+        tagid: "",
+      };
+    },
+    Seedetails(row) {
+      this.SeedetailsVisible = true;
+      this.Seedloading = true;
+      this.patientqueryParams.starttime = this.parseTime(
+        this.queryParams.dateRange[0]
+      );
+      this.patientqueryParams.endtime = this.parseTime(
+        this.queryParams.dateRange[1]
+      );
+      this.patientqueryParams.deptcode = row.deptcode;
+      selectTimelyRate(this.patientqueryParams).then((response) => {
+        this.logsheetlist = response.data.detail;
+        this.patienttotal = response.data.total;
+        this.Seedloading = false;
+      });
+    },
+    Seedetailstion() {
+      selectTimelyRate(this.patientqueryParams).then((response) => {
+        this.logsheetlist = response.data.detail;
+        this.patienttotal = response.data.total;
+        this.Seedloading = false;
+      });
+    },
+    viewDetails(row, title) {
+      this.infotitleVisible = true;
+      this.infotitle = title;
+      this.infotitlelist = row; // 鍋囪row灏辨槸闇�瑕佸睍绀虹殑璇︾粏鏁扮粍
+      console.log(this.infotitlelist, "this.infotitlelist");
+
+      this.infotitlelist.forEach((item) => {
+        let idArray = null;
+
+        if (item.preachform) {
+          if (item.endtime) {
+            item.preachformson = item.preachform;
+            idArray = item.preachform.split(",");
+          }
+
+          item.preachform = idArray.map((value) => {
+            // 鏌ユ壘id瀵瑰簲鐨勫璞�
+            const item = this.checkboxlist.find((item) => item.value == value);
+            // 濡傛灉鎵惧埌瀵瑰簲鐨刬d锛岃繑鍥瀕abel鍊硷紝鍚﹀垯杩斿洖null
+            return item ? item.label : null;
+          });
+        }
+      });
+      // 鍒濆鍖栧姞杞�
+      this.loadIndex = 0;
+      this.currentDisplayList = [];
+      this.$nextTick(() => {
+        this.loadMoreData();
+      });
+    },
+    loadMoreData() {
+      if (this.isLoading) return;
+      this.isLoading = true;
+
+      // 妯℃嫙寮傛鍔犺浇锛屽疄闄呭彲鑳芥槸鐩存帴鍒囩墖鏈湴鏁版嵁
+      setTimeout(() => {
+        console.log(this.infotitlelist, "this.infotitlelist");
+
+        const nextChunk = this.infotitlelist.slice(
+          this.loadIndex,
+          this.loadIndex + this.pageSize
+        );
+        this.currentDisplayList = this.currentDisplayList.concat(nextChunk);
+        this.loadIndex += this.pageSize;
+        this.isLoading = false;
+      }, 200);
+    },
+    handleScroll(event) {
+      const scrollContainer = event.target;
+      // 鍒ゆ柇鏄惁婊氬姩鍒板簳閮�
+      const isAtBottom =
+        scrollContainer.scrollTop + scrollContainer.clientHeight >=
+        scrollContainer.scrollHeight - 10;
+
+      if (
+        isAtBottom &&
+        !this.isLoading &&
+        this.loadIndex < this.infotitlelist.length
+      ) {
+        this.loadMoreData();
+      }
+    },
+    SeedetailsgGo(row) {
+      this.SeedetailsVisible = false;
+      let type = "";
+      if (row.preachformson && row.preachformson.includes("3")) {
+        type = 1;
+      }
+      setTimeout(() => {
+        this.$router.push({
+          path: "/followvisit/record/detailpage/",
+          query: {
+            taskid: row.taskid,
+            patid: row.patid,
+            id: row.id,
+            Voicetype: type,
+            // visitCount: this.topqueryParams.visitCount,
+          },
+        });
+      }, 300);
+    },
+    // 娣诲姞/淇敼鏍囩
+    Maintenancetag() {
+      if (this.lstamendtag) {
+        toamendtag(this.addDateRange(this.tagform)).then((response) => {
+          console.log(response);
+          this.getList();
+        });
+      } else {
+        addapitag(this.addDateRange(this.tagform)).then((response) => {
+          console.log(response);
+          this.getList();
+        });
+      }
+      this.tagform = {
+        isupload: "",
+        tagname: "",
+        tagcategoryid: "",
+        tagdescription: "",
+        tagid: "",
+      };
+    },
+    routerErr(row) {
+      console.log(row, "璺宠浆寮傚父");
+      this.$router.push({
+        path: "/followvisit/discharge",
+        query: {
+          errtype: 1,
+          leavehospitaldistrictcode: row.leavehospitaldistrictcode,
+        },
+      });
+    },
+
+    // 琛ㄥ崟閲嶇疆
+    reset() {
+      this.form = {
+        userId: undefined,
+        deptId: undefined,
+        userName: undefined,
+        nickName: undefined,
+        password: undefined,
+        phonenumber: undefined,
+        email: undefined,
+        sex: undefined,
+        status: "0",
+        remark: undefined,
+        postIds: [],
+        roleIds: [],
+      };
+      this.resetForm("form");
+    },
+    // 鏍囩鐘舵�佷慨鏀�
+    handleStatusChange(row) {
+      console.log(row.isupload);
+      let text = row.isupload === "0" ? "鍚敤" : "鍋滅敤";
+      this.$modal
+        .confirm('纭瑕�"' + text + '""' + row.tagname + '"鏍囩鍚楋紵')
+        .then(function () {
+          return changetagcategory(row.tagid, row.isupload);
+        })
+        .then(() => {
+          this.$modal.msgSuccess(text + "鎴愬姛");
+        })
+        .catch(function () {
+          row.isupload = row.isupload === "0" ? "1" : "0";
+        });
+    },
+    /** 鎼滅储鎸夐挳鎿嶄綔 - 淇敼涓烘悳绱㈠綋鍓嶆縺娲荤殑tab鏁版嵁 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      if (!this.queryParams.dateRange) this.queryParams.dateRange = [];
+      if (this.queryParams.statisticaltype == 1) {
+        this.queryParams.deptcodes = [];
+      } else if (this.queryParams.statisticaltype == 2) {
+        this.queryParams.leavehospitaldistrictcodes = [];
+      }
+
+      this.queryParams.startTime = this.parseTime(
+        this.queryParams.dateRange[0]
+      );
+      this.queryParams.endTime = this.parseTime(this.queryParams.dateRange[1]);
+
+      // 鏍规嵁褰撳墠婵�娲荤殑tab鍔犺浇瀵瑰簲鏁版嵁
+      if (this.activeTab === "first") {
+        this.getFirstFollowUpList();
+      } else {
+        this.getSecondFollowUpList();
+      }
+    },
+
+    /** 閲嶇疆鎸夐挳鎿嶄綔 */
+    resetQuery() {
+      this.queryParams.dateRange = [];
+      this.queryParams.leavehospitaldistrictcodes = [];
+      this.handleQuery();
+    },
+    // 澶氶�夋閫変腑鏁版嵁
+    handleSelectionChange(selection) {
+      this.ids = selection.map((item) => item.tagid);
+      this.single = selection.length != 1;
+      this.multiple = !selection.length;
+    },
+
+    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+    handleDelete(row) {
+      console.log(row, "鍒犻櫎寮圭獥");
+      const tagids = row.tagid || this.ids;
+      console.log(tagids);
+      const tagname = row.tagname;
+      this.$modal
+        .confirm(
+          tagname
+            ? '鏄惁纭鍒犻櫎鏍囩鍚嶇О涓�"' + tagname + '"鐨勬暟鎹」锛�'
+            : "鏄惁纭鍒犻櫎閫変腑鐨勬暟鎹」锛�"
+        )
+        .then(function () {
+          return deletetag(tagids);
+        })
+        .then(() => {
+          this.getList();
+          this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+        })
+        .catch(() => { });
+    },
+    // 瀵煎嚭鏂规硶
+
+    async exportTable() {
+      try {
+        // 1. 鑾峰彇骞舵牸寮忓寲鏃ユ湡鑼冨洿
+        let dateRangeString = "";
+        let sheetNameSuffix = "";
+
+        if (
+          this.queryParams.dateRange &&
+          this.queryParams.dateRange.length === 2
+        ) {
+          const startDateStr = this.queryParams.dateRange[0];
+          const endDateStr = this.queryParams.dateRange[1];
+          const formatDateForDisplay = (dateTimeStr) => {
+            return dateTimeStr.split(" ")[0];
+          };
+          const startDateFormatted = formatDateForDisplay(startDateStr);
+          const endDateFormatted = formatDateForDisplay(endDateStr);
+          dateRangeString = `${startDateFormatted}鑷�${endDateFormatted}`;
+          sheetNameSuffix = `${startDateFormatted}鑷�${endDateFormatted}`;
+        } else {
+          const now = new Date();
+          const currentMonth = now.getMonth() + 1;
+          dateRangeString = `${currentMonth}鏈坄;
+          sheetNameSuffix = `${currentMonth}鏈坄;
+        }
+
+        // 2. 鏍规嵁褰撳墠婵�娲荤殑tab纭畾瀵煎嚭鐨勬暟鎹�
+        const isFirstFollowUp = this.activeTab === "first";
+        let excelName, worksheetName, dataToExport;
+
+        if (isFirstFollowUp) {
+          excelName = `棣栨鍑洪櫌闅忚缁熻琛╛${dateRangeString}.xlsx`;
+          worksheetName = `棣栨闅忚缁熻_${sheetNameSuffix}`;
+          dataToExport = this.firstFollowUpList;
+
+          if (!dataToExport || dataToExport.length === 0) {
+            this.$message.warning("鏆傛棤棣栨闅忚鏁版嵁鍙鍑�");
+            return false;
+          }
+        } else {
+          excelName = `鍐嶆鍑洪櫌闅忚缁熻琛╛${dateRangeString}.xlsx`;
+          worksheetName = `鍐嶆闅忚缁熻_${sheetNameSuffix}`;
+          dataToExport = this.secondFollowUpList;
+
+          if (!dataToExport || dataToExport.length === 0) {
+            this.$message.warning("鏆傛棤鍐嶆闅忚鏁版嵁鍙鍑�");
+            return false;
+          }
+        }
+
+        // 3. 鍒涘缓宸ヤ綔绨垮拰宸ヤ綔琛�
+        const workbook = new ExcelJS.Workbook();
+        const worksheet = workbook.addWorksheet(worksheetName);
+
+        // 4. 鏋勫缓琛ㄦ牸
+        if (isFirstFollowUp) {
+          this.buildFirstFollowUpExportSheet(
+            worksheet,
+            dataToExport,
+            sheetNameSuffix
+          );
+        } else {
+          this.buildSecondFollowUpExportSheet(
+            worksheet,
+            dataToExport,
+            sheetNameSuffix
+          );
+        }
+
+        // 5. 鐢熸垚骞朵笅杞芥枃浠�
+        const buffer = await workbook.xlsx.writeBuffer();
+        const blob = new Blob([buffer], {
+          type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
+        });
+        saveAs(blob, excelName);
+
+        this.$message.success("瀵煎嚭鎴愬姛");
+        return true;
+      } catch (error) {
+        console.error("瀵煎嚭澶辫触:", error);
+        this.$message.error(`瀵煎嚭澶辫触: ${error.message}`);
+        return false;
+      }
+    },
+    /** 鏋勫缓棣栨闅忚瀵煎嚭琛ㄦ牸 */
+    buildFirstFollowUpExportSheet(worksheet, data, sheetNameSuffix) {
+      const titleStyle = {
+        font: {
+          name: "寰蒋闆呴粦",
+          size: 16,
+          bold: true,
+          color: { argb: "FF000000" },
+        },
+        fill: {
+          type: "pattern",
+          pattern: "solid",
+          fgColor: { argb: "FFE6F3FF" },
+        },
+        alignment: { vertical: "middle", horizontal: "center", wrapText: true },
+        border: {
+          top: { style: "thin", color: { argb: "FFD0D0D0" } },
+          left: { style: "thin", color: { argb: "FFD0D0D0" } },
+          bottom: { style: "thin", color: { argb: "FFD0D0D0" } },
+          right: { style: "thin", color: { argb: "FFD0D0D0" } },
+        },
+      };
+
+      const headerStyle = {
+        font: {
+          name: "寰蒋闆呴粦",
+          size: 11,
+          bold: true,
+          color: { argb: "FF000000" },
+        },
+        fill: {
+          type: "pattern",
+          pattern: "solid",
+          fgColor: { argb: "FFF5F7FA" },
+        },
+        alignment: { vertical: "middle", horizontal: "center", wrapText: true },
+        border: {
+          top: { style: "thin", color: { argb: "FFD0D0D0" } },
+          left: { style: "thin", color: { argb: "FFD0D0D0" } },
+          bottom: { style: "thin", color: { argb: "FFD0D0D0" } },
+          right: { style: "thin", color: { argb: "FFD0D0D0" } },
+        },
+      };
+
+      const cellStyle = {
+        font: { name: "瀹嬩綋", size: 10, color: { argb: "FF000000" } },
+        alignment: { vertical: "middle", horizontal: "center" },
+        border: {
+          top: { style: "thin", color: { argb: "FFD0D0D0" } },
+          left: { style: "thin", color: { argb: "FFD0D0D0" } },
+          bottom: { style: "thin", color: { argb: "FFD0D0D0" } },
+          right: { style: "thin", color: { argb: "FFD0D0D0" } },
+        },
+      };
+
+      const summaryStyle = {
+        font: {
+          name: "瀹嬩綋",
+          size: 10,
+          bold: true,
+          color: { argb: "FF409EFF" },
+        },
+        fill: {
+          type: "pattern",
+          pattern: "solid",
+          fgColor: { argb: "FFF5F7FA" },
+        },
+        alignment: { vertical: "middle", horizontal: "center" },
+        border: {
+          top: { style: "thin", color: { argb: "FFD0D0D0" } },
+          left: { style: "thin", color: { argb: "FFD0D0D0" } },
+          bottom: { style: "thin", color: { argb: "FFD0D0D0" } },
+          right: { style: "thin", color: { argb: "FFD0D0D0" } },
+        },
+      };
+
+      // 1. 娣诲姞鎬绘爣棰樿
+      worksheet.mergeCells(1, 1, 1, 16); // 鍚堝苟A1鍒癙1
+      const titleCell = worksheet.getCell(1, 1);
+      titleCell.value = `棣栨鍑洪櫌闅忚缁熻琛╛${sheetNameSuffix}`;
+      titleCell.style = titleStyle;
+      worksheet.getRow(1).height = 35;
+
+      // 2. 鍒涘缓琛ㄥご
+      const secondRowHeaders = [
+        "", // A2 灞曞紑鍒楀崰浣�
+        "鍑洪櫌鐥呭尯",
+        "绉戝",
+        "鍑洪櫌浜烘",
+        "鏃犻渶闅忚浜烘",
+        "搴旈殢璁夸汉娆�", // B2 to F2
+        // 棣栨鍑洪櫌闅忚瀛愯〃澶�
+        "闇�闅忚",
+        "寰呴殢璁�",
+        "闅忚鎴愬姛",
+        "闅忚澶辫触",
+        "闅忚鐜�",
+        "鍙婃椂鐜�",
+        "浜哄伐",
+        "鐭俊",
+        "寰俊",
+      ];
+
+      // 娣诲姞绗簩琛�
+      secondRowHeaders.forEach((header, index) => {
+        const cell = worksheet.getCell(3, index + 1);
+        cell.value = header;
+        cell.style = headerStyle;
+      });
+
+      // 3. 鍚堝苟鍗曞厓鏍�
+      // 鍚堝苟 A2:A3, B2:B3, C2:C3, D2:D3, E2:E3, F2:F3
+      for (let i = 1; i <= 6; i++) {
+        worksheet.mergeCells(2, i, 3, i);
+        const cell = worksheet.getCell(2, i);
+        cell.style = headerStyle;
+      }
+
+      // 璁剧疆绗竴琛屽悎骞跺崟鍏冩牸鐨勫��
+      worksheet.getCell(2, 1).value = "";
+      worksheet.getCell(2, 2).value = "鍑洪櫌鐥呭尯";
+      worksheet.getCell(2, 3).value = "绉戝";
+      worksheet.getCell(2, 4).value = "鍑洪櫌浜烘";
+      worksheet.getCell(2, 5).value = "鏃犻渶闅忚浜烘";
+      worksheet.getCell(2, 6).value = "搴旈殢璁夸汉娆�";
+
+      // 4. 鍚堝苟"棣栨鍑洪櫌闅忚"鏍囬
+      worksheet.mergeCells(2, 7, 2, 15); // G2:O2
+      worksheet.getCell(2, 7).value = "棣栨鍑洪櫌闅忚";
+      worksheet.getCell(2, 7).style = headerStyle;
+
+      // 5. 璁剧疆琛岄珮
+      worksheet.getRow(2).height = 28;
+      worksheet.getRow(3).height = 25;
+
+      // 6. 娣诲姞鏁版嵁琛�
+      data.forEach((item, rowIndex) => {
+        const dataRow = worksheet.addRow(
+          [
+            "", // 灞曞紑鍒�
+            item.leavehospitaldistrictname || "",
+            item.deptname || "",
+            item.dischargeCount || 0,
+            item.nonFollowUp || 0,
+            item.followUpNeeded || 0,
+            // 棣栨鍑洪櫌闅忚鏁版嵁
+            item.needFollowUp || 0,
+            item.pendingFollowUp || 0,
+            item.followUpSuccess || 0,
+            item.followUpFail || 0,
+            item.followUpRate || "0%",
+            item.rate ? (Number(item.rate) * 100).toFixed(2) + "%" : "0%",
+            item.manual || 0,
+            item.sms || 0,
+            item.weChat || 0,
+          ],
+          rowIndex + 4
+        );
+
+        // 搴旂敤鏁版嵁琛屾牱寮�
+        dataRow.eachCell((cell) => {
+          cell.style = cellStyle;
+        });
+        dataRow.height = 24;
+      });
+
+      // 7. 娣诲姞鍚堣琛�
+      const summaries = this.getFirstFollowUpSummaries(data);
+      const summaryRow = worksheet.addRow(summaries);
+      summaryRow.eachCell((cell, colNumber) => {
+        cell.style = summaryStyle;
+        if (colNumber === 1) {
+          cell.value = "鍚堣";
+        }
+      });
+      summaryRow.height = 28;
+
+      // 8. 璁剧疆鍒楀
+      worksheet.columns = [
+        { width: 8 }, // 灞曞紑鍒�
+        { width: 20 }, // 鍑洪櫌鐥呭尯
+        { width: 15 }, // 绉戝
+        { width: 12 }, // 鍑洪櫌浜烘
+        { width: 12 }, // 鏃犻渶闅忚浜烘
+        { width: 12 }, // 搴旈殢璁夸汉娆�
+        // 棣栨鍑洪櫌闅忚鍒�
+        { width: 10 }, // 闇�闅忚
+        { width: 10 }, // 寰呴殢璁�
+        { width: 10 }, // 闅忚鎴愬姛
+        { width: 10 }, // 闅忚澶辫触
+        { width: 12 }, // 闅忚鐜�
+        { width: 12 }, // 鍙婃椂鐜�
+        { width: 8 }, // 浜哄伐
+        { width: 8 }, // 鐭俊
+        { width: 8 }, // 寰俊
+      ];
+    },
+
+    /** 棣栨闅忚鏁版嵁鍚堣琛岃绠� */
+    getFirstFollowUpSummaries(data) {
+      const summaries = [
+        "鍚堣",
+        "/",
+        "/",
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        "0%",
+        "0%",
+        0,
+        0,
+        0,
+      ];
+
+      data.forEach((item) => {
+        // 鏁板�煎瓧娈垫眰鍜�
+        summaries[3] += Number(item.dischargeCount) || 0;
+        summaries[4] += Number(item.nonFollowUp) || 0;
+        summaries[5] += Number(item.followUpNeeded) || 0;
+        summaries[6] += Number(item.needFollowUp) || 0;
+        summaries[7] += Number(item.pendingFollowUp) || 0;
+        summaries[8] += Number(item.followUpSuccess) || 0;
+        summaries[9] += Number(item.followUpFail) || 0;
+        summaries[12] += Number(item.manual) || 0;
+        summaries[13] += Number(item.sms) || 0;
+        summaries[14] += Number(item.weChat) || 0;
+      });
+
+      // 璁$畻鐧惧垎姣斿瓧娈电殑骞冲潎鍊�
+      const followUpRateValues = data
+        .map((item) => this.extractPercentageValue(item.followUpRate))
+        .filter((value) => value !== null);
+
+      const rateValues = data
+        .map((item) => this.extractPercentageValue(item.rate))
+        .filter((value) => value !== null);
+
+      if (followUpRateValues.length > 0) {
+        const avgFollowUpRate =
+          followUpRateValues.reduce((sum, val) => sum + val, 0) /
+          followUpRateValues.length;
+        summaries[10] = (avgFollowUpRate * 100).toFixed(2) + "%";
+      }
+
+      if (rateValues.length > 0) {
+        const avgRate =
+          rateValues.reduce((sum, val) => sum + val, 0) / rateValues.length;
+        summaries[11] = (avgRate * 100).toFixed(2) + "%";
+      }
+
+      // 鏍煎紡鍖栨暟瀛�
+      summaries[3] = this.formatNumber(summaries[3]);
+      summaries[4] = this.formatNumber(summaries[4]);
+      summaries[5] = this.formatNumber(summaries[5]);
+      summaries[6] = this.formatNumber(summaries[6]);
+      summaries[7] = this.formatNumber(summaries[7]);
+      summaries[8] = this.formatNumber(summaries[8]);
+      summaries[9] = this.formatNumber(summaries[9]);
+      summaries[12] = this.formatNumber(summaries[12]);
+      summaries[13] = this.formatNumber(summaries[13]);
+      summaries[14] = this.formatNumber(summaries[14]);
+
+      return summaries;
+    },
+
+    /** 鏋勫缓鍐嶆闅忚瀵煎嚭琛ㄦ牸 */
+    buildSecondFollowUpExportSheet(worksheet, data, sheetNameSuffix) {
+      const titleStyle = {
+        font: {
+          name: "寰蒋闆呴粦",
+          size: 16,
+          bold: true,
+          color: { argb: "FF000000" },
+        },
+        fill: {
+          type: "pattern",
+          pattern: "solid",
+          fgColor: { argb: "FFE6F3FF" },
+        },
+        alignment: { vertical: "middle", horizontal: "center", wrapText: true },
+        border: {
+          top: { style: "thin", color: { argb: "FFD0D0D0" } },
+          left: { style: "thin", color: { argb: "FFD0D0D0" } },
+          bottom: { style: "thin", color: { argb: "FFD0D0D0" } },
+          right: { style: "thin", color: { argb: "FFD0D0D0" } },
+        },
+      };
+
+      const headerStyle = {
+        font: {
+          name: "寰蒋闆呴粦",
+          size: 11,
+          bold: true,
+          color: { argb: "FF000000" },
+        },
+        fill: {
+          type: "pattern",
+          pattern: "solid",
+          fgColor: { argb: "FFF5F7FA" },
+        },
+        alignment: { vertical: "middle", horizontal: "center", wrapText: true },
+        border: {
+          top: { style: "thin", color: { argb: "FFD0D0D0" } },
+          left: { style: "thin", color: { argb: "FFD0D0D0" } },
+          bottom: { style: "thin", color: { argb: "FFD0D0D0" } },
+          right: { style: "thin", color: { argb: "FFD0D0D0" } },
+        },
+      };
+
+      const cellStyle = {
+        font: { name: "瀹嬩綋", size: 10, color: { argb: "FF000000" } },
+        alignment: { vertical: "middle", horizontal: "center" },
+        border: {
+          top: { style: "thin", color: { argb: "FFD0D0D0" } },
+          left: { style: "thin", color: { argb: "FFD0D0D0" } },
+          bottom: { style: "thin", color: { argb: "FFD0D0D0" } },
+          right: { style: "thin", color: { argb: "FFD0D0D0" } },
+        },
+      };
+
+      const summaryStyle = {
+        font: {
+          name: "瀹嬩綋",
+          size: 10,
+          bold: true,
+          color: { argb: "FF409EFF" },
+        },
+        fill: {
+          type: "pattern",
+          pattern: "solid",
+          fgColor: { argb: "FFF5F7FA" },
+        },
+        alignment: { vertical: "middle", horizontal: "center" },
+        border: {
+          top: { style: "thin", color: { argb: "FFD0D0D0" } },
+          left: { style: "thin", color: { argb: "FFD0D0D0" } },
+          bottom: { style: "thin", color: { argb: "FFD0D0D0" } },
+          right: { style: "thin", color: { argb: "FFD0D0D0" } },
+        },
+      };
+
+      // 1. 娣诲姞鎬绘爣棰樿
+      worksheet.mergeCells(1, 1, 1, 15); // 鍚堝苟A1鍒癘1
+      const titleCell = worksheet.getCell(1, 1);
+      titleCell.value = `鍐嶆鍑洪櫌闅忚缁熻琛╛${sheetNameSuffix}`;
+      titleCell.style = titleStyle;
+      worksheet.getRow(1).height = 35;
+
+      // 2. 鍒涘缓琛ㄥご
+      const secondRowHeaders = [
+        "", // A2 灞曞紑鍒楀崰浣�
+        "鍑洪櫌鐥呭尯",
+        "绉戝",
+        "鍑洪櫌浜烘",
+        "鏃犻渶闅忚浜烘",
+        "搴旈殢璁夸汉娆�", // B2 to F2
+        // 鍐嶆鍑洪櫌闅忚瀛愯〃澶�
+        "闇�闅忚",
+        "寰呴殢璁�",
+        "闅忚鎴愬姛",
+        "闅忚澶辫触",
+        "闅忚鐜�",
+        "浜哄伐",
+        "鐭俊",
+        "寰俊",
+      ];
+
+      // 娣诲姞绗簩琛�
+      secondRowHeaders.forEach((header, index) => {
+        const cell = worksheet.getCell(3, index + 1);
+        cell.value = header;
+        cell.style = headerStyle;
+      });
+
+      // 3. 鍚堝苟鍗曞厓鏍�
+      // 鍚堝苟 A2:A3, B2:B3, C2:C3, D2:D3, E2:E3, F2:F3
+      for (let i = 1; i <= 6; i++) {
+        worksheet.mergeCells(2, i, 3, i);
+        const cell = worksheet.getCell(2, i);
+        cell.style = headerStyle;
+      }
+
+      // 璁剧疆绗竴琛屽悎骞跺崟鍏冩牸鐨勫��
+      worksheet.getCell(2, 1).value = "";
+      worksheet.getCell(2, 2).value = "鍑洪櫌鐥呭尯";
+      worksheet.getCell(2, 3).value = "绉戝";
+      worksheet.getCell(2, 4).value = "鍑洪櫌浜烘";
+      worksheet.getCell(2, 5).value = "鏃犻渶闅忚浜烘";
+      worksheet.getCell(2, 6).value = "搴旈殢璁夸汉娆�";
+
+      // 4. 鍚堝苟"鍐嶆鍑洪櫌闅忚"鏍囬
+      worksheet.mergeCells(2, 7, 2, 14); // G2:N2
+      worksheet.getCell(2, 7).value = "鍐嶆鍑洪櫌闅忚";
+      worksheet.getCell(2, 7).style = headerStyle;
+
+      // 5. 璁剧疆琛岄珮
+      worksheet.getRow(2).height = 28;
+      worksheet.getRow(3).height = 25;
+
+      // 6. 娣诲姞鏁版嵁琛�
+      data.forEach((item, rowIndex) => {
+        const dataRow = worksheet.addRow(
+          [
+            "", // 灞曞紑鍒�
+            item.leavehospitaldistrictname || "",
+            item.deptname || "",
+            item.dischargeCount || 0,
+            item.nonFollowUp || 0,
+            item.followUpNeeded || 0,
+            // 鍐嶆鍑洪櫌闅忚鏁版嵁
+            item.needFollowUpAgain || 0,
+            item.pendingFollowUpAgain || 0,
+            item.followUpSuccessAgain || 0,
+            item.followUpFailAgain || 0,
+            item.followUpRateAgain || "0%",
+            item.manualAgain || 0,
+            item.smsAgain || 0,
+            item.weChatAgain || 0,
+          ],
+          rowIndex + 4
+        );
+
+        // 搴旂敤鏁版嵁琛屾牱寮�
+        dataRow.eachCell((cell) => {
+          cell.style = cellStyle;
+        });
+        dataRow.height = 24;
+      });
+
+      // 7. 娣诲姞鍚堣琛�
+      const summaries = this.getSecondFollowUpSummaries(data);
+      const summaryRow = worksheet.addRow(summaries);
+      summaryRow.eachCell((cell, colNumber) => {
+        cell.style = summaryStyle;
+        if (colNumber === 1) {
+          cell.value = "鍚堣";
+        }
+      });
+      summaryRow.height = 28;
+
+      // 8. 璁剧疆鍒楀
+      worksheet.columns = [
+        { width: 8 }, // 灞曞紑鍒�
+        { width: 20 }, // 鍑洪櫌鐥呭尯
+        { width: 15 }, // 绉戝
+        { width: 12 }, // 鍑洪櫌浜烘
+        { width: 12 }, // 鏃犻渶闅忚浜烘
+        { width: 12 }, // 搴旈殢璁夸汉娆�
+        // 鍐嶆鍑洪櫌闅忚鍒�
+        { width: 10 }, // 闇�闅忚
+        { width: 10 }, // 寰呴殢璁�
+        { width: 10 }, // 闅忚鎴愬姛
+        { width: 10 }, // 闅忚澶辫触
+        { width: 12 }, // 闅忚鐜�
+        { width: 8 }, // 浜哄伐
+        { width: 8 }, // 鐭俊
+        { width: 8 }, // 寰俊
+      ];
+    },
+
+    /** 鍐嶆闅忚鏁版嵁鍚堣琛岃绠� */
+    getSecondFollowUpSummaries(data) {
+      const summaries = ["鍚堣", "/", "/", 0, 0, 0, 0, 0, 0, 0, "0%", 0, 0, 0];
+
+      data.forEach((item) => {
+        // 鏁板�煎瓧娈垫眰鍜�
+        summaries[3] += Number(item.dischargeCount) || 0;
+        summaries[4] += Number(item.nonFollowUp) || 0;
+        summaries[5] += Number(item.followUpNeeded) || 0;
+        summaries[6] += Number(item.needFollowUpAgain) || 0;
+        summaries[7] += Number(item.pendingFollowUpAgain) || 0;
+        summaries[8] += Number(item.followUpSuccessAgain) || 0;
+        summaries[9] += Number(item.followUpFailAgain) || 0;
+        summaries[11] += Number(item.manualAgain) || 0;
+        summaries[12] += Number(item.smsAgain) || 0;
+        summaries[13] += Number(item.weChatAgain) || 0;
+      });
+
+      // 璁$畻闅忚鐜囩櫨鍒嗘瘮瀛楁鐨勫钩鍧囧��
+      const followUpRateAgainValues = data
+        .map((item) => this.extractPercentageValue(item.followUpRateAgain))
+        .filter((value) => value !== null);
+
+      if (followUpRateAgainValues.length > 0) {
+        const avgFollowUpRateAgain =
+          followUpRateAgainValues.reduce((sum, val) => sum + val, 0) /
+          followUpRateAgainValues.length;
+        summaries[10] = (avgFollowUpRateAgain * 100).toFixed(2) + "%";
+      }
+
+      // 鏍煎紡鍖栨暟瀛�
+      summaries[3] = this.formatNumber(summaries[3]);
+      summaries[4] = this.formatNumber(summaries[4]);
+      summaries[5] = this.formatNumber(summaries[5]);
+      summaries[6] = this.formatNumber(summaries[6]);
+      summaries[7] = this.formatNumber(summaries[7]);
+      summaries[8] = this.formatNumber(summaries[8]);
+      summaries[9] = this.formatNumber(summaries[9]);
+      summaries[11] = this.formatNumber(summaries[11]);
+      summaries[12] = this.formatNumber(summaries[12]);
+      summaries[13] = this.formatNumber(summaries[13]);
+
+      return summaries;
+    },
+
+    /** 鍐嶆闅忚琛ㄦ牸鐨勫悎璁¤璁$畻鏂规硶 */
+    getSummariesSecond(param) {
+      const { columns, data } = param;
+      const sums = [];
+
+      columns.forEach((column, index) => {
+        if (index === 0) {
+          sums[index] = "鍚堣";
+          return;
+        }
+        if (index === 1 || index === 2) {
+          sums[index] = "/";
+          return;
+        }
+
+        if (column.property === "followUpRateAgain") {
+          const percentageValues = data
+            .map((item) => {
+              const value = item[column.property];
+              if (!value || value === "-" || value === "0%") return null;
+              if (typeof value === "string" && value.includes("%")) {
+                const numValue = parseFloat(value.replace("%", "")) / 100;
+                return isNaN(numValue) ? null : numValue;
+              } else {
+                const numValue = parseFloat(value);
+                return isNaN(numValue) ? null : numValue;
+              }
+            })
+            .filter((value) => value !== null && value !== 0);
+
+          if (percentageValues.length > 0) {
+            const average =
+              percentageValues.reduce((sum, value) => sum + value, 0) /
+              percentageValues.length;
+            sums[index] = (average * 100).toFixed(2) + "%";
+          } else {
+            sums[index] = "0.00%";
+          }
+        } else {
+          const values = data.map((item) => {
+            const value = item[column.property];
+            if (value === "-" || value === "" || value === null) return 0;
+            return Number(value) || 0;
+          });
+
+          if (!values.every((value) => isNaN(value))) {
+            sums[index] = values.reduce((prev, curr) => prev + curr, 0);
+            sums[index] = this.formatNumber(sums[index]);
+          } else {
+            sums[index] = "-";
+          }
+        }
+      });
+
+      return sums;
+    },
+    /** 鍐嶆闅忚鍐呴儴琛ㄦ牸鍚堣琛岃绠楁柟娉� */
+    getInnerSummariesSecond(param) {
+      const { columns, data } = param;
+      const sums = [];
+
+      columns.forEach((column, index) => {
+        if (index === 0) {
+          sums[index] = "灏忚";
+          return;
+        }
+
+        if (column.property === "drname" || column.property === "deptname") {
+          sums[index] = "-";
+          return;
+        }
+
+        if (column.property === "followUpRateAgain") {
+          const percentageValues = data
+            .map((item) => {
+              const value = item[column.property];
+              if (!value || value === "-" || value === "0%") return null;
+              if (typeof value === "string" && value.includes("%")) {
+                const numValue = parseFloat(value.replace("%", "")) / 100;
+                return isNaN(numValue) ? null : numValue;
+              } else {
+                const numValue = parseFloat(value);
+                return isNaN(numValue) ? null : numValue;
+              }
+            })
+            .filter((value) => value !== null && value !== 0);
+
+          if (percentageValues.length > 0) {
+            const average =
+              percentageValues.reduce((sum, value) => sum + value, 0) /
+              percentageValues.length;
+            sums[index] = (average * 100).toFixed(2) + "%";
+          } else {
+            sums[index] = "0.00%";
+          }
+        } else {
+          const values = data.map((item) => {
+            const value = item[column.property];
+            if (value === "-" || value === "" || value === null) return 0;
+            return Number(value) || 0;
+          });
+
+          if (!values.every((value) => isNaN(value))) {
+            sums[index] = values.reduce((prev, curr) => prev + curr, 0);
+            sums[index] = this.formatNumber(sums[index]);
+          } else {
+            sums[index] = "-";
+          }
+        }
+      });
+
+      return sums;
+    },
+    /** 鍐嶆闅忚琛ㄦ牸鐨勮鐐瑰嚮灞曞紑 */
+    handleRowClickSecond(row) {
+      if (this.expandsSecond.includes(this.getRowKey(row))) {
+        this.expandsSecond = [];
+        return;
+      }
+
+      const params = {
+        ...this.queryParams,
+        deptcodes: this.queryParams.deptcodes.includes("all")
+          ? this.allDeptCodes
+          : this.queryParams.deptcodes,
+        leavehospitaldistrictcodes: [row.leavehospitaldistrictcode],
+        drcode: "1",
+        visitCount: 2, // 璁剧疆涓哄啀娆¢殢璁�
+      };
+
+      delete params.leavehospitaldistrictcodes.all;
+      delete params.deptcodes.all;
+
+      if (!row.doctorStats) {
+        this.loadingSecond = true;
+        getSfStatistics(params).then((res) => {
+          this.$set(row, "doctorStats", res.data);
+          this.expandsSecond = [this.getRowKey(row)];
+          this.loadingSecond = false;
+        });
+      } else {
+        this.expandsSecond = [this.getRowKey(row)];
+      }
+    },
+
+    /** 鍐嶆闅忚琛ㄦ牸鐨勫閫夋閫変腑鏁版嵁 */
+    handleSelectionChangeSecond(selection) {
+      this.idsSecond = selection.map((item) => item.tagid);
+      this.single = selection.length != 1;
+      this.multiple = !selection.length;
+    },
+    // 鏄剧ず鍥捐〃寮圭獥
+
+    showChartDialog() {
+      this.chartDialogVisible = true;
+      this.$nextTick(() => {
+        this.initPieChart();
+        this.initBarLineChart();
+      });
+    },
+    // 鍦╩ethods涓慨鏀圭粺璁℃柟娉�
+    showChartDialog() {
+      this.chartDialogVisible = true;
+      this.$nextTick(() => {
+        console.log(this.userList, "this.userList");
+
+        this.initCharts();
+      });
+    },
+
+    // 鏂板鍒濆鍖栧浘琛ㄦ柟娉�
+    initCharts() {
+      this.initPieChart();
+      this.initBarLineChart();
+    },
+
+    // 鍒濆鍖栭ゼ鍥�
+    initPieChart() {
+      const echarts = require("echarts");
+      const pieDom = document.getElementById("pieChart");
+      if (!pieDom) return;
+
+      if (this.pieChart) {
+        this.pieChart.dispose();
+      }
+
+      this.pieChart = echarts.init(pieDom);
+
+      // 璁$畻楗煎浘鏁版嵁
+      const followUpData = {
+        pending: 0,
+        success: 0,
+        fail: 0,
+      };
+
+      this.userList.forEach((item) => {
+        followUpData.pending += item.pendingFollowUp || 0;
+        followUpData.success += item.followUpSuccess || 0;
+        followUpData.fail += item.followUpFail || 0;
+      });
+
+      // 浣跨敤鏇寸編瑙傜殑棰滆壊鏂规
+      const pieOption = {
+        title: {
+          text: "闅忚鐘舵�佸垎甯�",
+          left: "center",
+          textStyle: {
+            color: "#333",
+            fontSize: 16,
+          },
+        },
+        tooltip: {
+          trigger: "item",
+          formatter: "{a} <br/>{b}: {c} ({d}%)",
+        },
+        legend: {
+          orient: "vertical",
+          left: "left",
+          data: ["寰呴殢璁�", "闅忚鎴愬姛", "闅忚澶辫触"],
+          textStyle: {
+            color: "#666",
+          },
+        },
+        color: ["#FF9D4D", "#36B37E", "#FF5C5C"], // 鏂扮殑閰嶈壊鏂规
+        series: [
+          {
+            name: "闅忚鐘舵��",
+            type: "pie",
+            radius: ["40%", "70%"],
+            avoidLabelOverlap: true,
+            itemStyle: {
+              borderRadius: 10,
+              borderColor: "#fff",
+              borderWidth: 2,
+            },
+            label: {
+              show: true,
+              formatter: "{b}: {c} ({d}%)",
+              color: "#333",
+            },
+            emphasis: {
+              label: {
+                show: true,
+                fontSize: "18",
+                fontWeight: "bold",
+              },
+              itemStyle: {
+                shadowBlur: 10,
+                shadowOffsetX: 0,
+                shadowColor: "rgba(0, 0, 0, 0.5)",
+              },
+            },
+            data: [
+              {
+                value: followUpData.pending,
+                name: "寰呴殢璁�",
+              },
+              {
+                value: followUpData.success,
+                name: "闅忚鎴愬姛",
+              },
+              {
+                value: followUpData.fail,
+                name: "闅忚澶辫触",
+              },
+            ],
+          },
+        ],
+      };
+
+      this.pieChart.setOption(pieOption);
+      window.addEventListener("resize", this.resizePieChart);
+    },
+
+    // 鍒濆鍖栨煴鐘舵姌绾垮浘
+    initBarLineChart() {
+      const echarts = require("echarts");
+      const barDom = document.getElementById("barLineChart");
+      if (!barDom) return;
+
+      if (this.barLineChart) {
+        this.barLineChart.dispose();
+      }
+
+      this.barLineChart = echarts.init(barDom);
+
+      // 鍑嗗鏁版嵁
+      const categories = this.userList.map(
+        (item) => item.leavehospitaldistrictname || item.deptname
+      );
+
+      const dischargeData = this.userList.map(
+        (item) => item.dischargeCount || 0
+      );
+      const followUpData = this.userList.map(
+        (item) => item.followUpNeeded || 0
+      );
+
+      // 鏂板涓ゆ潯鎶樼嚎鏁版嵁
+      const followUpRateData = this.userList.map((item) => {
+        if (!item.followUpRate) return 0;
+        // 鍘绘帀鐧惧垎鍙峰苟杞负鏁板瓧
+        const rateStr = String(item.followUpRate).replace("%", "");
+        return parseFloat(rateStr) || 0;
+      });
+
+      const timelyRateData = this.userList.map((item) =>
+        item.rate ? (Number(item.rate) * 100).toFixed(2) : 0
+      );
+
+      const option = {
+        title: {
+          text: "绉戝/鐥呭尯闅忚瓒嬪娍",
+          left: "center",
+          textStyle: {
+            color: "#333",
+            fontSize: 16,
+          },
+        },
+        tooltip: {
+          trigger: "axis",
+          axisPointer: {
+            type: "cross",
+            crossStyle: {
+              color: "#999",
+            },
+          },
+        },
+        legend: {
+          data: ["鍑洪櫌浜烘", "搴旈殢璁夸汉娆�", "闅忚鐜�(%)", "鍙婃椂鐜�(%)"],
+          top: "bottom",
+          textStyle: {
+            color: "#666",
+          },
+        },
+        color: ["#5470C6", "#91CC75", "#EE6666", "#9A60B4"], // 鏂板绱壊鐢ㄤ簬鍙婃椂鐜�
+        xAxis: {
+          type: "category",
+          data: categories,
+          axisLabel: {
+            interval: 0,
+            rotate: 30,
+            color: "#666",
+          },
+          axisLine: {
+            lineStyle: {
+              color: "#ddd",
+            },
+          },
+        },
+        yAxis: [
+          {
+            type: "value",
+            name: "浜烘",
+            min: 0,
+            axisLabel: {
+              color: "#666",
+            },
+            axisLine: {
+              lineStyle: {
+                color: "#ddd",
+              },
+            },
+            splitLine: {
+              lineStyle: {
+                color: "#f0f0f0",
+              },
+            },
+          },
+          {
+            type: "value",
+            name: "鐧惧垎姣�(%)",
+            min: 0,
+            max: 100,
+            axisLabel: {
+              color: "#666",
+              formatter: "{value}%",
+            },
+            axisLine: {
+              lineStyle: {
+                color: "#ddd",
+              },
+            },
+            splitLine: {
+              show: false,
+            },
+          },
+        ],
+        series: [
+          {
+            name: "鍑洪櫌浜烘",
+            type: "bar",
+            barWidth: "25%",
+            data: dischargeData,
+            itemStyle: {
+              borderRadius: [4, 4, 0, 0],
+            },
+          },
+          {
+            name: "搴旈殢璁夸汉娆�",
+            type: "bar",
+            barWidth: "25%",
+            data: followUpData,
+            itemStyle: {
+              borderRadius: [4, 4, 0, 0],
+            },
+          },
+          {
+            name: "闅忚鐜�(%)",
+            type: "line",
+            yAxisIndex: 1,
+            data: followUpRateData,
+            symbolSize: 8,
+            lineStyle: {
+              width: 3,
+            },
+            markLine: {
+              silent: true,
+              data: [
+                {
+                  yAxis: 80,
+                  lineStyle: {
+                    color: "#EE6666",
+                    type: "dashed",
+                  },
+                  // label: {
+                  //   position: 'end',
+                  //   formatter: '鐩爣80%'
+                  // }
+                },
+              ],
+            },
+          },
+          {
+            name: "鍙婃椂鐜�(%)",
+            type: "line",
+            yAxisIndex: 1,
+            data: timelyRateData,
+            symbolSize: 8,
+            lineStyle: {
+              width: 3,
+              type: "dotted", // 浣跨敤铏氱嚎鍖哄垎
+            },
+            markLine: {
+              silent: true,
+              data: [
+                {
+                  yAxis: 90,
+                  lineStyle: {
+                    color: "#9A60B4",
+                    type: "dashed",
+                  },
+                  // label: {
+                  //   position: 'end',
+                  //   formatter: '鐩爣90%'
+                  // }
+                },
+              ],
+            },
+          },
+        ],
+        grid: {
+          top: "15%",
+          left: "3%",
+          right: "4%",
+          bottom: "15%",
+          containLabel: true,
+        },
+      };
+
+      this.barLineChart.setOption(option);
+      window.addEventListener("resize", this.resizeBarLineChart);
+    },
+
+    // 鍥捐〃鍝嶅簲寮忚皟鏁存柟娉�
+    resizePieChart() {
+      if (this.pieChart) {
+        this.pieChart.resize();
+      }
+    },
+
+    resizeBarLineChart() {
+      if (this.barLineChart) {
+        this.barLineChart.resize();
+      }
+    },
+
+    // 鍦ㄧ粍浠堕攢姣佹椂娓呯悊
+    beforeDestroy() {
+      // 绉婚櫎浜嬩欢鐩戝惉
+      window.removeEventListener("resize", this.resizePieChart);
+      window.removeEventListener("resize", this.resizeBarLineChart);
+
+      // 閿�姣佸浘琛ㄥ疄渚�
+      if (this.pieChart) {
+        this.pieChart.dispose();
+        this.pieChart = null;
+      }
+      if (this.barLineChart) {
+        this.barLineChart.dispose();
+        this.barLineChart = null;
+      }
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+::v-deep .el-tabs__header {
+  margin-bottom: 20px;
+}
+
+::v-deep .el-tabs__item {
+  font-size: 16px;
+  padding: 0 20px;
+  height: 40px;
+  line-height: 40px;
+}
+
+::v-deep .el-tabs__active-bar {
+  height: 3px;
+}
+
+/* Tab鍐呭鍖哄煙鏍峰紡 */
+.el-tab-pane {
+  .your-table-container {
+    margin-top: 10px;
+  }
+}
+
+.sidecolumn {
+  width: 180px;
+  min-height: 100vh;
+  text-align: center;
+  //   display: flex;
+  margin-top: 20px;
+  margin: 20px;
+  padding: 30px;
+  background: #edf1f7;
+  border: 1px solid #dcdfe6;
+  -webkit-box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12),
+    0 0 6px 0 rgba(0, 0, 0, 0.04);
+
+  .sidecolumn-top {
+    display: flex;
+    justify-content: space-between;
+
+    .top-wj {
+      font-size: 20px;
+    }
+
+    .top-tj {
+      font-size: 18px;
+
+      color: rgb(0, 89, 255);
+      cursor: pointer;
+    }
+  }
+
+  .center-ss {
+    margin-top: 30px;
+
+    .input-with-select {
+      height: 40px !important;
+    }
+  }
+
+  .bottom-fl {
+    margin-top: 30px;
+    display: center !important;
+  }
+}
+
+.qrcode-dialo {
+  text-align: center;
+  //   display: flex;
+  margin: 20px;
+  padding: 30px;
+  background: #edf1f7;
+  border: 1px solid #dcdfe6;
+  -webkit-box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12),
+    0 0 6px 0 rgba(0, 0, 0, 0.04);
+
+  .qrcode-text {
+    font-size: 20px;
+
+    span {
+      margin-left: 20px;
+    }
+  }
+
+  .qrcode-img {
+    width: 300px;
+    height: 400px;
+  }
+}
+
+::v-deep.el-tabs--left,
+.el-tabs--right {
+  overflow: hidden;
+  align-items: center;
+  display: flex;
+}
+
+::v-deep.el-input--medium .el-input__inner {
+  height: 40px !important;
+}
+
+::v-deep.el-tabs--right .el-tabs__active-bar.is-right {
+  height: 40px;
+  width: 5px;
+  left: 0;
+}
+
+::v-deep.el-tabs--right .el-tabs__item.is-right {
+  display: block;
+  text-align: left;
+  font-size: 20px;
+}
+
+// 缇庡寲鍚堣琛屾牱寮�
+::v-deep .el-table__footer {
+  .el-table__cell {
+    background-color: #f5f7fa;
+    font-weight: 600;
+    color: #409eff;
+
+    .cell {
+      font-weight: 600;
+      color: #409eff;
+    }
+  }
+}
+
+// 鍐呴儴琛ㄦ牸鍚堣琛屾牱寮�
+::v-deep .inner-table .el-table__footer {
+  .el-table__cell {
+    background-color: #ecf5ff;
+    font-weight: 500;
+    color: #67c23a;
+
+    .cell {
+      font-weight: 500;
+      color: #67c23a;
+    }
+  }
+}
+
+// 鐧惧垎姣斿瓧娈电壒娈婃牱寮�
+.your-table-container ::v-deep .el-table__footer .el-table__cell[data-field="followUpRate"] .cell,
+.your-table-container ::v-deep .el-table__footer .el-table__cell[data-field="rate"] .cell,
+.your-table-container ::v-deep .el-table__footer .el-table__cell[data-field="followUpRateAgain"] .cell {
+  color: #e6a23c !important;
+  font-weight: 700 !important;
+}
+
+.leftvlue {
+  //   display: flex;
+  //   flex: 1;
+  // width: 80%;
+  // margin-top: 20px;
+  margin: 20px;
+  padding: 30px;
+  background: #ffff;
+  border: 1px solid #dcdfe6;
+  -webkit-box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12),
+    0 0 6px 0 rgba(0, 0, 0, 0.04);
+
+  .mulsz {
+    font-size: 20px;
+  }
+}
+
+/* 浣胯鏈夋墜鍨嬫寚閽� */
+.el-table__row {
+  cursor: pointer;
+}
+
+/* 鍐呭眰鍖荤敓琛ㄦ牸鏍峰紡 */
+.inner-table {
+
+  // 琛ㄥご鑳屾櫙鑹�
+  ::v-deep .el-table__header-wrapper {
+    background-color: #f0f7ff !important;
+
+    th {
+      background-color: #f0f7ff !important;
+    }
+  }
+
+  // 琛ㄦ牸琛岃儗鏅壊
+  ::v-deep .el-table__body-wrapper {
+    tr {
+      background-color: #f9fbfe !important;
+
+      &:hover {
+        background-color: #e6f1ff !important;
+      }
+    }
+  }
+
+  // 杈规棰滆壊
+  ::v-deep .el-table--border {
+    border-color: #d9e8ff !important;
+
+    td,
+    th {
+      border-color: #d9e8ff !important;
+    }
+  }
+
+  // 鏂戦┈绾规晥鏋�
+  ::v-deep .el-table--striped .el-table__body tr.el-table__row--striped td {
+    background-color: #f5f9ff !important;
+  }
+}
+
+/* 灞曞紑琛屾牱寮� */
+.el-table__expanded-cell {
+  padding: 10px 0 !important;
+  background: #f8f8f8;
+}
+
+.document {
+  width: 100px;
+  height: 50px;
+}
+
+.data-list {
+  max-height: 800px;
+  overflow-y: auto;
+}
+
+.documentf {
+  display: flex;
+  justify-content: flex-end;
+}
+
+.button-text {
+  color: rgb(70, 204, 238);
+}
+
+.button-textck {
+  color: rgb(39, 167, 67);
+}
+
+.button-textxg {
+  color: rgb(35, 81, 233);
+}
+
+.button-textsc {
+  color: rgb(235, 23, 23);
+}
+</style>
diff --git a/src/views/sfstatistics/percentage/index.vue b/src/views/sfstatistics/percentage/index.vue
index 5cad6ba..911156a 100644
--- a/src/views/sfstatistics/percentage/index.vue
+++ b/src/views/sfstatistics/percentage/index.vue
@@ -1,3103 +1,369 @@
 <template>
-  <div class="Questionnairemanagement">
-    <div class="leftvlue">
-      <div class="leftvlue-bg">
-        <el-row :gutter="20">
-          <!--鏍囩鏁版嵁-->
-          <el-col :span="24" :xs="24">
-            <el-form
-              :model="queryParams"
-              ref="queryForm"
-              size="small"
-              :inline="true"
-              v-show="showSearch"
-              label-width="98px"
-            >
-              <el-form-item label="缁熻绫诲瀷" prop="userName">
-                <el-select
-                  v-model="queryParams.statisticaltype"
-                  placeholder="璇烽�夋嫨缁熻绫诲瀷"
-                >
-                  <el-option
-                    v-for="item in Statisticallist"
-                    :key="item.value"
-                    :label="item.label"
-                    :value="item.value"
-                  >
-                  </el-option>
-                </el-select>
-                <el-select
-                  style="margin-left: 10px"
-                  v-if="queryParams.statisticaltype == 1"
-                  v-model="queryParams.leavehospitaldistrictcodes"
-                  size="medium"
-                  multiple
-                  filterable
-                  placeholder="璇烽�夋嫨鐥呭尯"
-                >
-                  <el-option
-                    v-for="item in flatArrayhospit"
-                    :key="item.value"
-                    :label="item.label"
-                    :value="item.value"
-                  >
-                  </el-option>
-                </el-select>
-                <el-select
-                  v-else-if="queryParams.statisticaltype == 2"
-                  v-model="queryParams.deptcodes"
-                  size="medium"
-                  multiple
-                  filterable
-                  placeholder="璇烽�夋嫨绉戝"
-                >
-                  <el-option
-                    v-for="item in flatArraydept"
-                    :key="item.value"
-                    :label="item.label"
-                    :value="item.value"
-                  >
-                  </el-option>
-                </el-select>
-              </el-form-item>
+  <div class="follow-up-statistics">
+    <!-- 鎼滅储琛ㄥ崟鍖哄煙 -->
+    <div class="search-section">
+      <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="98px">
+        <el-form-item label="缁熻绫诲瀷" prop="userName">
+          <el-select v-model="queryParams.statisticaltype" placeholder="璇烽�夋嫨缁熻绫诲瀷">
+            <el-option v-for="item in Statisticallist" :key="item.value" :label="item.label" :value="item.value" />
+          </el-select>
+          <el-select
+            style="margin-left: 10px"
+            v-if="queryParams.statisticaltype == 1"
+            v-model="queryParams.leavehospitaldistrictcodes"
+            size="medium"
+            multiple
+            filterable
+            placeholder="璇烽�夋嫨鐥呭尯"
+          >
+            <el-option v-for="item in flatArrayhospit" :key="item.value" :label="item.label" :value="item.value" />
+          </el-select>
+          <el-select
+            v-else-if="queryParams.statisticaltype == 2"
+            v-model="queryParams.deptcodes"
+            size="medium"
+            multiple
+            filterable
+            placeholder="璇烽�夋嫨绉戝"
+          >
+            <el-option v-for="item in flatArraydept" :key="item.value" :label="item.label" :value="item.value" />
+          </el-select>
+        </el-form-item>
 
-              <el-form-item label="缁熻绫诲瀷" prop="userName">
-                <el-select
-                  v-model="queryParams.serviceType"
-                  multiple
-                  placeholder="璇烽�夋嫨"
-                >
-                  <el-option
-                    v-for="item in options"
-                    :key="item.value"
-                    :label="item.label"
-                    :value="item.value"
-                  >
-                  </el-option>
-                </el-select>
-              </el-form-item>
-              <el-form-item
-                label-width="200"
-                label="搴旈殢璁挎椂闂磋寖鍥�"
-                prop="userName"
-              >
-                <el-date-picker
-                  v-model="queryParams.dateRange"
-                  value-format="yyyy-MM-dd HH:mm:ss"
-                  type="daterange"
-                  range-separator="鑷�"
-                  start-placeholder="寮�濮嬫棩鏈�"
-                  end-placeholder="缁撴潫鏃ユ湡"
-                  :default-time="['00:00:00', '23:59:59']"
-                >
-                  >
-                </el-date-picker>
-              </el-form-item>
+        <el-form-item label="鏈嶅姟绫诲瀷" prop="userName">
+          <el-select v-model="queryParams.serviceType" multiple placeholder="璇烽�夋嫨">
+            <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
+          </el-select>
+        </el-form-item>
 
-              <el-form-item>
-                <el-button
-                  type="primary"
-                  icon="el-icon-search"
-                  size="medium"
-                  @click="handleQuery"
-                  >鎼滅储</el-button
-                >
-                <el-button
-                  icon="el-icon-refresh"
-                  size="medium"
-                  @click="resetQuery"
-                  >閲嶇疆</el-button
-                >
-              </el-form-item>
-              <el-col :span="19">
-                <el-button
-                  type="warning"
-                  plain
-                  icon="el-icon-download"
-                  size="medium"
-                  @click="exportTable"
-                  >瀵煎嚭</el-button
-                >
-                <el-button
-                  type="primary"
-                  plain
-                  icon="el-icon-data-line"
-                  size="medium"
-                  @click="showChartDialog"
-                  >缁熻瓒嬪娍鍥�</el-button
-                >
-              </el-col>
-            </el-form>
-            <div class="your-table-container">
-              <el-table
-                ref="exportTable"
-                id="exportTableid"
-                v-loading="loading"
-                :data="userList"
-                :border="true"
-                @selection-change="handleSelectionChange"
-                @expand-change="handleRowClick"
-                :row-key="getRowKey"
-                show-summary
-                :summary-method="getSummaries"
-                :expand-row-keys="expands"
-              >
-                <!-- 灞曞紑琛岀澶村垪 -->
-                <el-table-column type="expand">
-                  <template slot-scope="props">
-                    <el-table
-                      :data="props.row.doctorStats"
-                      border
-                      style="width: 95%; margin: 0 auto"
-                      class="inner-table"
-                      show-summary
-                      :summary-method="getInnerSummaries"
-                    >
-                      <el-table-column
-                        label="鍖荤敓濮撳悕"
-                        prop="drname"
-                        align="center"
-                      />
-                      <el-table-column
-                        label="绉戝"
-                        width="120"
-                        prop="deptname"
-                        align="center"
-                      />
-                      <el-table-column
-                        label="鍑洪櫌浜烘"
-                        prop="dischargeCount"
-                        align="center"
-                      />
-                      <el-table-column
-                        label="鍑洪櫌浜烘"
-                        align="center"
-                        key="dischargeCount"
-                        prop="dischargeCount"
-                      >
-                      </el-table-column>
-
-                      <el-table-column
-                        label="鏃犻渶闅忚浜烘"
-                        align="center"
-                        width="100"
-                        key="nonFollowUp"
-                        prop="nonFollowUp"
-                      >
-                      </el-table-column>
-                      <el-table-column
-                        label="搴旈殢璁夸汉娆�"
-                        align="center"
-                        width="100"
-                        key="followUpNeeded"
-                        prop="followUpNeeded"
-                      >
-                      </el-table-column>
-                      <el-table-column align="center" label="棣栨鍑洪櫌闅忚">
-                        <el-table-column
-                          label="闇�闅忚"
-                          align="center"
-                          key="needFollowUp"
-                          prop="needFollowUp"
-                        >
-                        </el-table-column>
-                        <el-table-column
-                          label="寰呴殢璁�"
-                          align="center"
-                          key="pendingFollowUp"
-                          prop="pendingFollowUp"
-                        >
-                        </el-table-column>
-                        <el-table-column
-                          label="闅忚鎴愬姛"
-                          align="center"
-                          key="followUpSuccess"
-                          prop="followUpSuccess"
-                        >
-                        </el-table-column>
-                        <el-table-column
-                          label="闅忚澶辫触"
-                          align="center"
-                          key="followUpFail"
-                          prop="followUpFail"
-                        >
-                        </el-table-column>
-                        <el-table-column
-                          label="闅忚鐜�"
-                          align="center"
-                          width="120"
-                          key="followUpRate"
-                          prop="followUpRate"
-                        >
-                          <!-- <template slot-scope="scope">
-                      <span
-                        >{{
-                          (Number(scope.row.followUpRate) * 100).toFixed(2)
-                        }}%</span
-                      >
-                    </template> -->
-                        </el-table-column>
-                        <el-table-column
-                          label="鍙婃椂鐜�"
-                          align="center"
-                          width="120"
-                          key="rate"
-                          prop="rate"
-                        >
-                          <template slot-scope="scope">
-                            <el-button
-                              size="medium"
-                              type="text"
-                              @click="Seedetails(scope.row)"
-                              ><span class="button-zx"
-                                >{{
-                                  (Number(scope.row.rate) * 100).toFixed(2)
-                                }}%</span
-                              ></el-button
-                            >
-                          </template>
-                        </el-table-column>
-                        <el-table-column
-                          label="浜哄伐"
-                          align="center"
-                          key="manual"
-                          prop="manual"
-                        >
-                        </el-table-column>
-                        <el-table-column
-                          label="鐭俊"
-                          align="center"
-                          key="sms"
-                          prop="sms"
-                        >
-                        </el-table-column>
-                        <el-table-column
-                          label="寰俊"
-                          align="center"
-                          key="weChat"
-                          prop="weChat"
-                        >
-                        </el-table-column>
-                      </el-table-column>
-                      <el-table-column align="center" label="鍐嶆鍑洪櫌闅忚">
-                        <el-table-column
-                          label="闇�闅忚"
-                          align="center"
-                          key="needFollowUpAgain"
-                          prop="needFollowUpAgain"
-                        >
-                        </el-table-column>
-                        <el-table-column
-                          label="寰呴殢璁�"
-                          align="center"
-                          key="pendingFollowUpAgain"
-                          prop="pendingFollowUpAgain"
-                        >
-                        </el-table-column>
-                        <el-table-column
-                          label="闅忚鎴愬姛"
-                          align="center"
-                          key="followUpSuccessAgain"
-                          prop="followUpSuccessAgain"
-                        >
-                        </el-table-column>
-                        <el-table-column
-                          label="闅忚澶辫触"
-                          align="center"
-                          key="followUpFailAgain"
-                          prop="followUpFailAgain"
-                        >
-                        </el-table-column>
-                        <el-table-column
-                          label="闅忚鐜�"
-                          align="center"
-                          width="120"
-                          key="followUpRateAgain"
-                          prop="followUpRateAgain"
-                        >
-                          <!-- <template slot-scope="scope">
-                      <span
-                        >{{
-                          (Number(scope.row.FollowUpRateAgain) * 100).toFixed(2)
-                        }}%</span
-                      >
-                    </template> -->
-                        </el-table-column>
-                        <el-table-column
-                          label="浜哄伐"
-                          align="center"
-                          key="manualAgain"
-                          prop="manualAgain"
-                        >
-                        </el-table-column>
-                        <el-table-column
-                          label="鐭俊"
-                          align="center"
-                          key="smsAgain"
-                          prop="smsAgain"
-                        >
-                        </el-table-column>
-                        <el-table-column
-                          label="寰俊"
-                          align="center"
-                          key="weChatAgain"
-                          prop="weChatAgain"
-                        >
-                        </el-table-column>
-                      </el-table-column>
-                    </el-table>
-                  </template>
-                </el-table-column>
-                <el-table-column
-                  label="鍑洪櫌鐥呭尯"
-                  align="center"
-                  sortable
-                  key="leavehospitaldistrictname"
-                  prop="leavehospitaldistrictname"
-                  width="150"
-                  :show-overflow-tooltip="true"
-                  :sort-method="sortChineseNumber"
-                />
-                <el-table-column
-                  label="绉戝"
-                  align="center"
-                  key="deptname"
-                  prop="deptname"
-                  :show-overflow-tooltip="true"
-                />
-                <el-table-column
-                  label="鍑洪櫌浜烘"
-                  align="center"
-                  key="dischargeCount"
-                  prop="dischargeCount"
-                >
-                </el-table-column>
-
-                <el-table-column
-                  label="鏃犻渶闅忚浜烘"
-                  align="center"
-                  width="100"
-                  key="nonFollowUp"
-                  prop="nonFollowUp"
-                >
-                </el-table-column>
-                <el-table-column
-                  label="搴旈殢璁夸汉娆�"
-                  align="center"
-                  width="100"
-                  key="followUpNeeded"
-                  prop="followUpNeeded"
-                >
-                </el-table-column>
-                <el-table-column align="center" label="棣栨鍑洪櫌闅忚">
-                  <el-table-column
-                    label="闇�闅忚"
-                    align="center"
-                    key="needFollowUp"
-                    prop="needFollowUp"
-                  >
-                    <template slot-scope="scope">
-                      <el-button
-                        size="medium"
-                        type="text"
-                        @click="
-                          viewDetails(
-                            scope.row.needFollowUpInfo,
-                            scope.row.leavehospitaldistrictname + '闇�闅忚鍒楄〃'
-                          )
-                        "
-                        ><span class="button-zx">{{
-                          scope.row.needFollowUp
-                        }}</span></el-button
-                      >
-                    </template>
-                  </el-table-column>
-                  <el-table-column
-                    label="寰呴殢璁�"
-                    align="center"
-                    key="pendingFollowUp"
-                    prop="pendingFollowUp"
-                  >
-                    <template slot-scope="scope">
-                      <el-button
-                        size="medium"
-                        type="text"
-                        @click="
-                          viewDetails(
-                            scope.row.pendingFollowUpInfo,
-                            scope.row.leavehospitaldistrictname + '寰呴殢璁垮垪琛�'
-                          )
-                        "
-                        ><span class="button-zx">{{
-                          scope.row.pendingFollowUp
-                        }}</span></el-button
-                      >
-                    </template>
-                  </el-table-column>
-                  <el-table-column
-                    label="闅忚鎴愬姛"
-                    align="center"
-                    key="followUpSuccess"
-                    prop="followUpSuccess"
-                  >
-                    <template slot-scope="scope">
-                      <el-button
-                        size="medium"
-                        type="text"
-                        @click="
-                          viewDetails(
-                            scope.row.followUpSuccessInfo,
-                            scope.row.leavehospitaldistrictname + '闅忚鎴愬姛鍒楄〃'
-                          )
-                        "
-                        ><span class="button-zx">{{
-                          scope.row.followUpSuccess
-                        }}</span></el-button
-                      >
-                    </template>
-                  </el-table-column>
-                  <el-table-column
-                    label="闅忚澶辫触"
-                    align="center"
-                    key="followUpFail"
-                    prop="followUpFail"
-                  >
-                    <template slot-scope="scope">
-                      <el-button
-                        size="medium"
-                        type="text"
-                        @click="
-                          viewDetails(
-                            scope.row.followUpFailInfo,
-                            scope.row.leavehospitaldistrictname + '闅忚澶辫触鍒楄〃'
-                          )
-                        "
-                        ><span class="button-zx">{{
-                          scope.row.followUpFail
-                        }}</span></el-button
-                      >
-                    </template>
-                  </el-table-column>
-                  <el-table-column
-                    label="闅忚鐜�"
-                    align="center"
-                    width="120"
-                    key="followUpRate"
-                    prop="followUpRate"
-                  >
-                    <!-- <template slot-scope="scope">
-                      <span
-                        >{{
-                          (Number(scope.row.followUpRate) * 100).toFixed(2)
-                        }}%</span
-                      >
-                    </template> -->
-                  </el-table-column>
-                  <el-table-column
-                    label="鍙婃椂鐜�"
-                    align="center"
-                    width="120"
-                    key="rate"
-                    prop="rate"
-                  >
-                    <template slot-scope="scope">
-                      <el-button
-                        size="medium"
-                        type="text"
-                        @click="Seedetails(scope.row)"
-                        ><span class="button-zx"
-                          >{{
-                            (Number(scope.row.rate) * 100).toFixed(2)
-                          }}%</span
-                        ></el-button
-                      >
-                    </template>
-                  </el-table-column>
-                  <el-table-column
-                    label="浜哄伐"
-                    align="center"
-                    key="manual"
-                    prop="manual"
-                  >
-                    <template slot-scope="scope">
-                      <el-button
-                        size="medium"
-                        type="text"
-                        @click="
-                          viewDetails(
-                            scope.row.manualInfo,
-                            scope.row.leavehospitaldistrictname + '浜哄伐闅忚鍒楄〃'
-                          )
-                        "
-                        ><span class="button-zx">{{
-                          scope.row.manual
-                        }}</span></el-button
-                      >
-                    </template>
-                  </el-table-column>
-                  <el-table-column
-                    label="鐭俊"
-                    align="center"
-                    key="sms"
-                    prop="sms"
-                  >
-                    <template slot-scope="scope">
-                      <el-button
-                        size="medium"
-                        type="text"
-                        @click="
-                          viewDetails(
-                            scope.row.smsInfo,
-                            scope.row.leavehospitaldistrictname + '鐭俊闅忚鍒楄〃'
-                          )
-                        "
-                        ><span class="button-zx">{{
-                          scope.row.sms
-                        }}</span></el-button
-                      >
-                    </template>
-                  </el-table-column>
-                  <el-table-column
-                    label="寰俊"
-                    align="center"
-                    key="weChat"
-                    prop="weChat"
-                  >
-                    <template slot-scope="scope">
-                      <el-button
-                        size="medium"
-                        type="text"
-                        @click="
-                          viewDetails(
-                            scope.row.weChatInfo,
-                            scope.row.leavehospitaldistrictname + '寰俊闅忚鍒楄〃'
-                          )
-                        "
-                        ><span class="button-zx">{{
-                          scope.row.weChat
-                        }}</span></el-button
-                      >
-                    </template>
-                  </el-table-column>
-                </el-table-column>
-                <el-table-column align="center" label="鍐嶆鍑洪櫌闅忚">
-                  <el-table-column
-                    label="闇�闅忚"
-                    align="center"
-                    key="needFollowUpAgain"
-                    prop="needFollowUpAgain"
-                  >
-                    <template slot-scope="scope">
-                      <el-button
-                        size="medium"
-                        type="text"
-                        @click="
-                          viewDetails(
-                            scope.row.needFollowUpAgainInfo,
-                            scope.row.leavehospitaldistrictname +
-                              '鍐嶆闅忚闇�闅忚鍒楄〃'
-                          )
-                        "
-                        ><span class="button-zx">{{
-                          scope.row.needFollowUpAgain
-                        }}</span></el-button
-                      >
-                    </template>
-                  </el-table-column>
-                  <el-table-column
-                    label="寰呴殢璁�"
-                    align="center"
-                    key="pendingFollowUpAgain"
-                    prop="pendingFollowUpAgain"
-                  >
-                    <template slot-scope="scope">
-                      <el-button
-                        size="medium"
-                        type="text"
-                        @click="
-                          viewDetails(
-                            scope.row.pendingFollowUpAgainInfo,
-                            scope.row.leavehospitaldistrictname +
-                              '鍐嶆闅忚寰呴殢璁垮垪琛�'
-                          )
-                        "
-                        ><span class="button-zx">{{
-                          scope.row.pendingFollowUpAgain
-                        }}</span></el-button
-                      >
-                    </template>
-                  </el-table-column>
-                  <el-table-column
-                    label="闅忚鎴愬姛"
-                    align="center"
-                    key="followUpSuccessAgain"
-                    prop="followUpSuccessAgain"
-                  >
-                    <template slot-scope="scope">
-                      <el-button
-                        size="medium"
-                        type="text"
-                        @click="
-                          viewDetails(
-                            scope.row.followUpSuccessAgainInfo,
-                            scope.row.leavehospitaldistrictname +
-                              '鍐嶆闅忚闅忚鎴愬姛鍒楄〃'
-                          )
-                        "
-                        ><span class="button-zx">{{
-                          scope.row.followUpSuccessAgain
-                        }}</span></el-button
-                      >
-                    </template>
-                  </el-table-column>
-                  <el-table-column
-                    label="闅忚澶辫触"
-                    align="center"
-                    key="followUpFailAgain"
-                    prop="followUpFailAgain"
-                  >
-                    <template slot-scope="scope">
-                      <el-button
-                        size="medium"
-                        type="text"
-                        @click="
-                          viewDetails(
-                            scope.row.followUpFailAgainInfo,
-                            scope.row.leavehospitaldistrictname +
-                              '鍐嶆闅忚闅忚澶辫触鍒楄〃'
-                          )
-                        "
-                        ><span class="button-zx">{{
-                          scope.row.followUpFailAgain
-                        }}</span></el-button
-                      >
-                    </template>
-                  </el-table-column>
-                  <el-table-column
-                    label="闅忚鐜�"
-                    align="center"
-                    width="120"
-                    key="followUpRateAgain"
-                    prop="followUpRateAgain"
-                  >
-                    <!-- <template slot-scope="scope">
-                      <span
-                        >{{
-                          (Number(scope.row.FollowUpRateAgain) * 100).toFixed(2)
-                        }}%</span
-                      >
-                    </template> -->
-                  </el-table-column>
-                  <el-table-column
-                    label="浜哄伐"
-                    align="center"
-                    key="manualAgain"
-                    prop="manualAgain"
-                  >
-                    <template slot-scope="scope">
-                      <el-button
-                        size="medium"
-                        type="text"
-                        @click="
-                          viewDetails(
-                            scope.row.manualAgainInfo,
-                            scope.row.leavehospitaldistrictname +
-                              '鍐嶆闅忚浜哄伐闅忚鍒楄〃'
-                          )
-                        "
-                        ><span class="button-zx">{{
-                          scope.row.manualAgain
-                        }}</span></el-button
-                      >
-                    </template>
-                  </el-table-column>
-                  <el-table-column
-                    label="鐭俊"
-                    align="center"
-                    key="smsAgain"
-                    prop="smsAgain"
-                  >
-                    <template slot-scope="scope">
-                      <el-button
-                        size="medium"
-                        type="text"
-                        @click="
-                          viewDetails(
-                            scope.row.smsAgainInfo,
-                            scope.row.leavehospitaldistrictname +
-                              '鍐嶆闅忚鐭俊闅忚鍒楄〃'
-                          )
-                        "
-                        ><span class="button-zx">{{
-                          scope.row.smsAgain
-                        }}</span></el-button
-                      >
-                    </template>
-                  </el-table-column>
-                  <el-table-column
-                    label="寰俊"
-                    align="center"
-                    key="weChatAgain"
-                    prop="weChatAgain"
-                  >
-                    <template slot-scope="scope">
-                      <el-button
-                        size="medium"
-                        type="text"
-                        @click="
-                          viewDetails(
-                            scope.row.weChatAgainInfo,
-                            scope.row.leavehospitaldistrictname +
-                              '鍐嶆闅忚寰俊闅忚鍒楄〃'
-                          )
-                        "
-                        ><span class="button-zx">{{
-                          scope.row.weChatAgain
-                        }}</span></el-button
-                      >
-                    </template>
-                  </el-table-column>
-                </el-table-column>
-                <el-table-column
-                  v-if="orgname == '涓芥按甯備腑鍖婚櫌'"
-                  align="center"
-                  label="闅忚鎯呭喌"
-                >
-                  <el-table-column
-                    label="姝e父璇煶"
-                    align="center"
-                    width="100"
-                    key="taskSituation1"
-                    prop="taskSituation1"
-                  >
-                  </el-table-column
-                  ><el-table-column
-                    label="鎮h�呮嫆鎺ユ垨鎷掕"
-                    align="center"
-                    width="100"
-                    key="taskSituation2"
-                    prop="taskSituation2"
-                  >
-                  </el-table-column
-                  ><el-table-column
-                    label="闈㈣鎴栬�呮帴璇�"
-                    align="center"
-                    width="100"
-                    key="taskSituation3"
-                    prop="taskSituation3"
-                  >
-                  </el-table-column
-                  ><el-table-column
-                    label="寰俊闅忚"
-                    align="center"
-                    width="100"
-                    key="taskSituation4"
-                    prop="taskSituation4"
-                  >
-                  </el-table-column
-                  ><el-table-column
-                    label="闅忚鐢佃瘽涓嶆纭�"
-                    align="center"
-                    width="100"
-                    key="taskSituation5"
-                    prop="taskSituation5"
-                  >
-                  </el-table-column
-                  ><el-table-column
-                    label="鍏朵粬鎯呭喌涓嶅疁闅忚"
-                    align="center"
-                    width="100"
-                    key="taskSituation6"
-                    prop="taskSituation6"
-                  >
-                  </el-table-column>
-                </el-table-column>
-              </el-table>
-            </div>
-
-            <!-- <pagination
-              v-show="total > 0"
-              :total="total"
-              :page.sync="queryParams.pageNum"
-              :limit.sync="queryParams.pageSize"
-              @pagination="getList"
-            /> -->
-          </el-col>
-        </el-row>
-      </div>
-    </div>
-    <!-- 缁熻瓒嬪娍鍥惧脊绐� -->
-    <el-dialog
-      title="闅忚缁熻瓒嬪娍鍥�"
-      :visible.sync="chartDialogVisible"
-      width="80%"
-      :close-on-click-modal="false"
-    >
-      <div class="chart-container">
-        <el-row :gutter="20">
-          <el-col :span="12">
-            <div class="chart-title">闅忚鐘舵�佸垎甯�</div>
-            <div id="pieChart" style="width: 100%; height: 400px"></div>
-          </el-col>
-          <el-col :span="12">
-            <div class="chart-title">闅忚瓒嬪娍鍒嗘瀽</div>
-            <div id="barLineChart" style="width: 100%; height: 400px"></div>
-          </el-col>
-        </el-row>
-      </div>
-    </el-dialog>
-    <el-dialog
-      title="鏈強鏃堕殢璁挎偅鑰呮湇鍔�"
-      :visible.sync="SeedetailsVisible"
-      v-loading="Seedloading"
-      width="70%"
-      :close-on-click-modal="false"
-    >
-      <div class="examine-jic">
-        <div class="jic-value">
-          <el-row :gutter="20">
-            <!--鐢ㄦ埛鏁版嵁-->
-            <el-form
-              :model="patientqueryParams"
-              ref="queryForm"
-              size="small"
-              :inline="true"
-              label-width="98px"
-            >
-              <el-form-item label="鎮h�咃細">
-                <el-input
-                  v-model="patientqueryParams.name"
-                  @keyup.enter.native="handleQuery"
-                ></el-input>
-              </el-form-item>
-              <el-form-item label="鎮h�呰瘖鏂細">
-                <el-input
-                  v-model="patientqueryParams.leavediagname"
-                  @keyup.enter.native="handleQuery"
-                ></el-input>
-              </el-form-item>
-
-              <el-form-item>
-                <el-button
-                  type="primary"
-                  icon="el-icon-search"
-                  size="medium"
-                  @click="handleQuery"
-                  >鎼滅储</el-button
-                >
-                <el-button
-                  icon="el-icon-refresh"
-                  size="medium"
-                  @click="resetQuery"
-                  >鍙栨秷鍒涘缓</el-button
-                >
-              </el-form-item>
-            </el-form>
-            <!-- 閫夋嫨鎮h�呭垪琛� -->
-            <el-table :data="logsheetlist" style="width: 100%">
-              <el-table-column
-                prop="sendname"
-                align="center"
-                label="濮撳悕"
-                width="100"
-              >
-              </el-table-column>
-              <el-table-column
-                prop="taskName"
-                align="center"
-                width="200"
-                show-overflow-tooltip
-                label="浠诲姟鍚嶇О"
-              >
-              </el-table-column>
-              <el-table-column
-                prop="sendstate"
-                align="center"
-                width="200"
-                label="浠诲姟鐘舵��"
-              >
-                <template slot-scope="scope">
-                  <div v-if="scope.row.sendstate == 1">
-                    <el-tag type="primary" :disable-transitions="false"
-                      >琛ㄥ崟宸查鍙�</el-tag
-                    >
-                  </div>
-                  <div v-if="scope.row.sendstate == 2">
-                    <el-tag type="primary" :disable-transitions="false"
-                      >寰呴殢璁�</el-tag
-                    >
-                  </div>
-                  <div v-if="scope.row.sendstate == 3">
-                    <el-tag type="success" :disable-transitions="false"
-                      >琛ㄥ崟宸插彂閫�</el-tag
-                    >
-                  </div>
-                  <div v-if="scope.row.sendstate == 4">
-                    <el-tag type="info" :disable-transitions="false"
-                      >涓嶆墽琛�</el-tag
-                    >
-                  </div>
-                  <div v-if="scope.row.sendstate == 5">
-                    <el-tag type="danger" :disable-transitions="false"
-                      >鍙戦�佸け璐�</el-tag
-                    >
-                  </div>
-                  <div v-if="scope.row.sendstate == 6">
-                    <el-tag type="success" :disable-transitions="false"
-                      >宸插畬鎴�</el-tag
-                    >
-                  </div>
-                </template>
-              </el-table-column>
-              <el-table-column
-                prop="visitTime"
-                align="center"
-                label="搴旈殢璁挎椂闂�"
-                width="200"
-                show-overflow-tooltip
-              >
-              </el-table-column>
-              <el-table-column
-                prop="finishtime"
-                align="center"
-                label="闅忚瀹屾垚鏃堕棿"
-                width="200"
-                show-overflow-tooltip
-              >
-              </el-table-column>
-              <el-table-column
-                label="鍑洪櫌鏃ユ湡"
-                width="200"
-                align="center"
-                key="endtime"
-                prop="endtime"
-              >
-                <template slot-scope="scope">
-                  <span>{{ formatTime(scope.row.endtime) }}</span>
-                </template></el-table-column
-              >
-              <el-table-column
-                label="璐d换鎶ゅ+"
-                width="120"
-                align="center"
-                key="nurseName"
-                prop="nurseName"
-              />
-              <el-table-column
-                label="涓绘不鍖荤敓"
-                width="120"
-                align="center"
-                key="drname"
-                prop="drname"
-              />
-
-              <el-table-column
-                label="缁撴灉鐘舵��"
-                align="center"
-                key="excep"
-                prop="excep"
-                width="120"
-              >
-                <template slot-scope="scope">
-                  <dict-tag
-                    :options="dict.type.sys_yujing"
-                    :value="scope.row.excep"
-                  />
-                </template>
-              </el-table-column>
-              <el-table-column
-                label="澶勭悊鎰忚"
-                align="center"
-                key="suggest"
-                prop="suggest"
-                width="120"
-              >
-                <template slot-scope="scope">
-                  <dict-tag
-                    :options="dict.type.sys_suggest"
-                    :value="scope.row.suggest"
-                  />
-                </template>
-              </el-table-column>
-
-              <el-table-column
-                prop="templatename"
-                align="center"
-                label="鏈嶅姟妯℃澘"
-                width="200"
-                show-overflow-tooltip
-              >
-              </el-table-column>
-              <el-table-column
-                prop="remark"
-                align="center"
-                label="鏈嶅姟璁板綍"
-                width="200"
-                show-overflow-tooltip
-              >
-              </el-table-column>
-
-              <el-table-column
-                prop="bankcardno"
-                align="center"
-                label="鍛煎彨鐘舵��"
-                width="210"
-              >
-              </el-table-column>
-              <el-table-column
-                label="鎿嶄綔"
-                fixed="right"
-                align="center"
-                width="200"
-                class-name="small-padding fixed-width"
-              >
-                <template slot-scope="scope">
-                  <el-button
-                    size="medium"
-                    type="text"
-                    @click="SeedetailsgGo(scope.row)"
-                    ><span class="button-zx"
-                      ><i class="el-icon-s-order"></i>鏌ョ湅</span
-                    ></el-button
-                  >
-                </template>
-              </el-table-column>
-            </el-table>
-          </el-row>
-          <pagination
-            v-show="patienttotal > 0 && this.patientqueryParams.allhosp != 6"
-            :total="patienttotal"
-            :page.sync="patientqueryParams.pn"
-            :limit.sync="patientqueryParams.ps"
-            @pagination="Seedetailstion"
+        <el-form-item label-width="200" label="搴旈殢璁挎椂闂磋寖鍥�" prop="userName">
+          <el-date-picker
+            v-model="queryParams.dateRange"
+            value-format="yyyy-MM-dd HH:mm:ss"
+            type="daterange"
+            range-separator="鑷�"
+            start-placeholder="寮�濮嬫棩鏈�"
+            end-placeholder="缁撴潫鏃ユ湡"
+            :default-time="['00:00:00', '23:59:59']"
           />
-        </div>
-      </div>
-    </el-dialog>
-    <!-- 鍚勭被璇︽儏 -->
-    <el-dialog
+        </el-form-item>
+
+        <el-form-item>
+          <el-button type="primary" icon="el-icon-search" size="medium" @click="handleQuery">鎼滅储</el-button>
+          <el-button icon="el-icon-refresh" size="medium" @click="resetQuery">閲嶇疆</el-button>
+        </el-form-item>
+
+        <el-button type="warning" plain icon="el-icon-download" size="medium" @click="handleExport">瀵煎嚭</el-button>
+        <el-button type="primary" plain icon="el-icon-data-line" size="medium" @click="showChartDialog">缁熻瓒嬪娍鍥�</el-button>
+      </el-form>
+    </div>
+
+    <!-- Tab鍒囨崲鍖哄煙 -->
+    <div class="tab-section">
+      <el-tabs v-model="activeTab" @tab-click="handleTabClick">
+        <el-tab-pane label="棣栨闅忚" name="first">
+          <FirstFollowUp
+            ref="firstFollowUp"
+            :query-params="queryParams"
+            :flat-array-hospit="flatArrayhospit"
+            :flat-array-dept="flatArraydept"
+            :options="options"
+            :orgname="orgname"
+            @view-details="viewDetails"
+            @see-details="Seedetails"
+          />
+        </el-tab-pane>
+
+        <el-tab-pane label="鍐嶆闅忚" name="second">
+          <SecondFollowUp
+            ref="secondFollowUp"
+            :query-params="queryParams"
+            :flat-array-hospit="flatArrayhospit"
+            :flat-array-dept="flatArraydept"
+            :options="options"
+            :orgname="orgname"
+            @view-details="viewDetails"
+          />
+        </el-tab-pane>
+
+        <el-tab-pane label="寤剁画鎶ょ悊缁熻" name="continued" v-if="orgname == '鐪佺珛鍚屽痉缈犺嫅闄㈠尯'">
+          <ContinuedCare
+            ref="continuedCare"
+            :query-params="queryParams"
+            :flat-array-hospit="flatArrayhospit"
+            :flat-array-dept="flatArraydept"
+            :options="options"
+            :orgname="orgname"
+            @view-details="viewDetails"
+          />
+        </el-tab-pane>
+      </el-tabs>
+    </div>
+
+    <!-- 寮圭獥鍖哄煙 -->
+    <ChartDialog
+      :visible="chartDialogVisible"
+      :data="chartData"
+      :active-tab="activeTab"
+      @close="chartDialogVisible = false"
+    />
+
+    <DetailDialog
+      :visible="infotitleVisible"
       :title="infotitle"
-      :visible.sync="infotitleVisible"
-      v-loading="infotitloading"
-      width="70%"
-      :close-on-click-modal="false"
-    >
-      <div style="margin-bottom: 16px; display: flex; align-items: center">
-        <span style="margin-right: 10px; font-weight: bold">鎮h�呭鍚嶆煡璇�:</span>
-        <el-input
-          v-model="searchName"
-          placeholder="璇疯緭鍏ユ偅鑰呭鍚嶈繘琛岀瓫閫�"
-          clearable
-          style="width: 300px"
-          @input="handleSearch"
-          @clear="handleSearch"
-        >
-        </el-input>
-        <span
-          style="margin-left: 10px; color: rgb(35, 81, 233); font-size: 16px"
-        >
-          鍏� {{ infotitlelist.length }} 鏉¤褰�
-        </span>
-      </div>
-      <div class="examine-jic">
-        <div class="jic-value">
-          <el-row :gutter="20">
-            <!-- 閫夋嫨鎮h�呭垪琛� -->
-            <div
-              class="data-list"
-              ref="dataList"
-              @scroll="handleScroll"
-              v-loading="infotitloading"
-            >
-              <el-table
-                :data="currentDisplayList"
-                height="660"
-                style="width: 100%"
-              >
-                <el-table-column
-                  prop="sendname"
-                  align="center"
-                  label="濮撳悕"
-                  width="100"
-                >
-                </el-table-column>
-                <el-table-column
-                  prop="taskName"
-                  align="center"
-                  width="200"
-                  show-overflow-tooltip
-                  label="浠诲姟鍚嶇О"
-                >
-                </el-table-column>
-                <el-table-column
-                  prop="sendstate"
-                  align="center"
-                  width="200"
-                  label="浠诲姟鐘舵��"
-                >
-                  <template slot-scope="scope">
-                    <div v-if="scope.row.sendstate == 1">
-                      <el-tag type="primary" :disable-transitions="false"
-                        >琛ㄥ崟宸查鍙�</el-tag
-                      >
-                    </div>
-                    <div v-if="scope.row.sendstate == 2">
-                      <el-tag type="primary" :disable-transitions="false"
-                        >寰呴殢璁�</el-tag
-                      >
-                    </div>
-                    <div v-if="scope.row.sendstate == 3">
-                      <el-tag type="success" :disable-transitions="false"
-                        >琛ㄥ崟宸插彂閫�</el-tag
-                      >
-                    </div>
-                    <div v-if="scope.row.sendstate == 4">
-                      <el-tag type="info" :disable-transitions="false"
-                        >涓嶆墽琛�</el-tag
-                      >
-                    </div>
-                    <div v-if="scope.row.sendstate == 5">
-                      <el-tag type="danger" :disable-transitions="false"
-                        >鍙戦�佸け璐�</el-tag
-                      >
-                    </div>
-                    <div v-if="scope.row.sendstate == 6">
-                      <el-tag type="success" :disable-transitions="false"
-                        >宸插畬鎴�</el-tag
-                      >
-                    </div>
-                  </template>
-                </el-table-column>
-                <el-table-column
-                  label="浠诲姟鎵ц鏂瑰紡"
-                  align="center"
-                  key="preachform"
-                  prop="preachform"
-                  width="160"
-                  :show-overflow-tooltip="true"
-                >
-                  <template slot-scope="scope">
-                    <span v-for="item in scope.row.preachform"
-                      >{{ item }}銆�
-                    </span>
-                  </template>
-                </el-table-column>
-                <el-table-column
-                  prop="visitTime"
-                  align="center"
-                  label="搴旈殢璁挎椂闂�"
-                  width="200"
-                  show-overflow-tooltip
-                >
-                </el-table-column>
-                <el-table-column
-                  prop="finishtime"
-                  align="center"
-                  label="闅忚瀹屾垚鏃堕棿"
-                  width="200"
-                  show-overflow-tooltip
-                >
-                </el-table-column>
-                <el-table-column
-                  label="鍑洪櫌鏃ユ湡"
-                  width="200"
-                  align="center"
-                  key="endtime"
-                  prop="endtime"
-                >
-                  <template slot-scope="scope">
-                    <span>{{ formatTime(scope.row.endtime) }}</span>
-                  </template></el-table-column
-                >
-                <el-table-column
-                  label="璐d换鎶ゅ+"
-                  width="120"
-                  align="center"
-                  key="nurseName"
-                  prop="nurseName"
-                />
-                <el-table-column
-                  label="涓绘不鍖荤敓"
-                  width="120"
-                  align="center"
-                  key="drname"
-                  prop="drname"
-                />
+      :data="infotitlelist"
+      :search-name="searchName"
+      @close="infotitleVisible = false"
+      @search="handleSearch"
+      @details-go="SeedetailsgGo"
+    />
 
-                <el-table-column
-                  label="缁撴灉鐘舵��"
-                  align="center"
-                  key="excep"
-                  prop="excep"
-                  width="120"
-                >
-                  <template slot-scope="scope">
-                    <dict-tag
-                      :options="dict.type.sys_yujing"
-                      :value="scope.row.excep"
-                    />
-                  </template>
-                </el-table-column>
-                <el-table-column
-                  label="澶勭悊鎰忚"
-                  align="center"
-                  key="suggest"
-                  prop="suggest"
-                  width="120"
-                >
-                  <template slot-scope="scope">
-                    <dict-tag
-                      :options="dict.type.sys_suggest"
-                      :value="scope.row.suggest"
-                    />
-                  </template>
-                </el-table-column>
-
-                <el-table-column
-                  prop="templatename"
-                  align="center"
-                  label="鏈嶅姟妯℃澘"
-                  width="200"
-                  show-overflow-tooltip
-                >
-                </el-table-column>
-                <el-table-column
-                  prop="remark"
-                  align="center"
-                  label="鏈嶅姟璁板綍"
-                  width="200"
-                  show-overflow-tooltip
-                >
-                </el-table-column>
-
-                <el-table-column
-                  prop="bankcardno"
-                  align="center"
-                  label="鍛煎彨鐘舵��"
-                  width="210"
-                >
-                </el-table-column>
-                <el-table-column
-                  label="鎿嶄綔"
-                  fixed="right"
-                  align="center"
-                  width="200"
-                  class-name="small-padding fixed-width"
-                >
-                  <template slot-scope="scope">
-                    <el-button
-                      size="medium"
-                      type="text"
-                      @click="SeedetailsgGo(scope.row)"
-                      ><span class="button-zx"
-                        ><i class="el-icon-s-order"></i>鏌ョ湅</span
-                      ></el-button
-                    >
-                  </template>
-                </el-table-column>
-              </el-table>
-            </div>
-          </el-row>
-        </div>
-      </div>
-    </el-dialog>
+    <TimelyRateDialog
+      :visible="SeedetailsVisible"
+      :loading="Seedloading"
+      :data="logsheetlist"
+      :total="patienttotal"
+      :query-params="patientqueryParams"
+      @close="SeedetailsVisible = false"
+      @search="Seedetailstion"
+      @details-go="SeedetailsgGo"
+    />
   </div>
 </template>
 
 <script>
-import {
-  toamendtag,
-  addapitag,
-  deletetag,
-  changetagcategory,
-} from "@/api/system/label";
-import store from "@/store";
-import { getSfStatistics, selectTimelyRate } from "@/api/system/user";
-import * as XLSX from "xlsx";
-import FileSaver from "file-saver";
-import ExcelJS from "exceljs";
-import { saveAs } from "file-saver";
-import Treeselect from "@riophae/vue-treeselect";
-import "@riophae/vue-treeselect/dist/vue-treeselect.css";
-const shortcuts = [
-  {
-    text: "浠婂ぉ",
-    onClick(picker) {
-      picker.$emit("pick", new Date());
-    },
-  },
-  {
-    text: "鏄ㄥぉ",
-    onClick(picker) {
-      const date = new Date();
-      date.setTime(date.getTime() - 3600 * 1000 * 24);
-      picker.$emit("pick", date);
-    },
-  },
-  {
-    text: "涓�鍛ㄥ墠",
-    onClick(picker) {
-      const date = new Date();
-      date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);
-      picker.$emit("pick", date);
-    },
-  },
-];
+import FirstFollowUp from './components/FirstFollowUp.vue'
+import SecondFollowUp from './components/SecondFollowUp.vue'
+import ContinuedCare from './components/ContinuedCare.vue'
+import ChartDialog from './components/ChartDialog.vue'
+import DetailDialog from './components/DetailDialog.vue'
+import TimelyRateDialog from './components/TimelyRateDialog.vue'
+
+
 export default {
-  name: "Percentage",
-  dicts: ["sys_normal_disable", "sys_user_sex"],
-  components: { Treeselect },
+  name: 'FollowUpStatistics',
+  components: {
+    FirstFollowUp,
+    SecondFollowUp,
+    ContinuedCare,
+    ChartDialog,
+    DetailDialog,
+    TimelyRateDialog
+  },
   data() {
     return {
-      topactiveName: "Local", //椤堕儴閫夋嫨
-      activeName: "first", //渚ц竟閫夋嫨
-      orgname: "",
-      expands: [],
-      infotitlelist: [],
-      currentDisplayList: [], // 褰撳墠鏄剧ず鐨勬暟鎹�
-      loadIndex: 0, // 褰撳墠宸插姞杞界殑鏁版嵁绱㈠紩
-      pageSize: 100, // 姣忔鍔犺浇鐨勬暟鎹噺
-      isLoading: false, // 闃叉婊氬姩鏃堕噸澶嶅姞杞�
-      // 閬僵灞�
-      loading: false,
-      Seedloading: false,
-      chartDialogVisible: false,
-      infotitleVisible: false,
-      searchName: "", // 鎼滅储鍏抽敭璇�
-      infotitloading: false,
-      infotitle: "",
-      pieChart: null,
-      barLineChart: null,
-      // 閫変腑鏁扮粍
-      ids: [],
-      // 闈炲崟涓鐢�
-      single: true,
-      // 闈炲涓鐢�
-      multiple: true,
-      // 鏄剧ず鎼滅储鏉′欢
-      showSearch: true,
-      idds: "", //鍒嗙被id
-      // 鎬绘潯鏁�
-      total: 0,
-      flatArrayhospit: [],
-      flatArraydept: [],
-      patienttotal: 0,
-      logsheetlist: [],
+      activeTab: 'first',
+      orgname: localStorage.getItem('orgname') || '',
       Statisticallist: [
-        {
-          label: "鐥呭尯缁熻",
-          value: 1,
-        },
-        {
-          label: "绉戝缁熻",
-          value: 2,
-        },
+        { label: '鐥呭尯缁熻', value: 1 },
+        { label: '绉戝缁熻', value: 2 }
       ],
-      patientqueryParams: {
-        pn: 1,
-        ps: 10,
-      },
-      amendtag: false, //鏄惁淇敼绫诲埆
-      lstamendtag: false, //鏄惁淇敼鏍囩
-      scavisible: false, //鍒犻櫎寮规
-      deleteVisible: false, //鍒嗙被鍒犻櫎寮规
-      deletefenl: "楂樿鍘�", //鍒犻櫎椤�
-      //淇敼娣诲姞鏍囩寮规鏁版嵁
-      tagform: {
-        isupload: "",
-        tagname: "",
-        tagcategoryid: "",
-        tagdescription: "",
-      },
-      classifyform: {
-        categoryname: "",
-      },
-      // 鏍囩琛ㄦ牸鏁版嵁
-      userList: [],
-      // 寮瑰嚭灞傛爣棰�
-      title: "",
-      // 鏄惁鏄剧ず寮瑰嚭灞�
-      open: false,
-      // 鏃ユ湡鑼冨洿
-      dateRange: [],
-      // 宀椾綅閫夐」
-      postOptions: [],
-      // 瑙掕壊閫夐」
-      roleOptions: [],
-      // 瀛樺偍鎵�鏈夌瀹や唬鐮�
-      allDeptCodes: [],
-      // 瀛樺偍鎵�鏈夌梾鍖轰唬鐮�
-      allWardCodes: [],
-      checkboxlist: [],
-      // 琛ㄥ崟鍙傛暟
-      form: {},
-      forms: {
-        name: "",
-      },
-      numberlb: 22,
-      dialogFormVisible: false, //娣诲姞銆佷慨鏀圭被鍒脊妗�
-      lstamendtagVisible: false, //娣诲姞銆佷慨鏀规爣绛惧脊妗�
-      goQRCodeVisible: false, //浜岀淮鐮佸脊妗�
-      sidecolumnval: "", //绫诲埆鎼滅储
-      propss: { multiple: true },
-      SeedetailsVisible: false,
-      options: store.getters.tasktypes,
-      pickerOptions: {
-        disabledDate(time) {
-          return time.getTime() < Date.now() - 3600 * 1000 * 24;
-        },
-        shortcuts: shortcuts,
-      },
-      pickerOptionsa: {
-        disabledDate(time) {
-          return time.getTime() > Date.now();
-        },
-        shortcuts: shortcuts,
-      },
-      // 鏌ヨ鏍囩鍒楄〃鍙傛暟
+      options: this.$store.getters.tasktypes,
       queryParams: {
         serviceType: [2],
         dateRange: [],
         statisticaltype: 1,
-        leavehospitaldistrictcodes: ["all"], // 榛樿閫変腑鍏ㄩ儴鐥呭尯
-        deptcodes: [], // 榛樿閫変腑鍏ㄩ儴绉戝
+        leavehospitaldistrictcodes: ['all'],
+        deptcodes: []
       },
-      // 鍒椾俊鎭�
-      columns: [
-        { key: 0, label: `鏍囩缂栧彿`, visible: true },
-        { key: 1, label: `鏍囩鍚嶇О`, visible: true },
-        { key: 2, label: `鏍囩鏄电О`, visible: true },
-        { key: 3, label: `閮ㄩ棬`, visible: true },
-        { key: 4, label: `鎵嬫満鍙风爜`, visible: true },
-        { key: 5, label: `鐘舵�乣, visible: true },
-        { key: 6, label: `鍒涘缓鏃堕棿`, visible: true },
-      ],
-    };
+      flatArrayhospit: [],
+      flatArraydept: [],
+      allDeptCodes: [],
+      allWardCodes: [],
+      showSearch: true,
+
+      // 寮圭獥鐩稿叧鐘舵��
+      chartDialogVisible: false,
+      chartData: [],
+      infotitleVisible: false,
+      SeedetailsVisible: false,
+      searchName: '',
+      infotitle: '',
+      infotitlelist: [],
+      patienttotal: 0,
+      logsheetlist: [],
+      Seedloading: false,
+      patientqueryParams: {
+        pn: 1,
+        ps: 10
+      }
+    }
   },
-  watch: {},
   created() {
-    this.getDeptTree();
-    this.getList();
-    this.checkboxlist = store.getters.checkboxlist;
-    this.orgname = localStorage.getItem("orgname");
+    this.getDeptTree()
   },
-
   methods: {
-    /** 鏌ヨ鏍囩鍒楄〃 */
-    getList() {
-      // 澶勭悊鏌ヨ鍙傛暟
-      const params = {
-        ...this.queryParams,
-        // 濡傛灉閫夋嫨浜�"鍏ㄩ儴"锛屽垯浼犳墍鏈夌梾鍖�/绉戝浠g爜
-        leavehospitaldistrictcodes:
-          this.queryParams.leavehospitaldistrictcodes.includes("all")
-            ? this.allWardCodes
-            : this.queryParams.leavehospitaldistrictcodes,
-        deptcodes: this.queryParams.deptcodes.includes("all")
-          ? this.allDeptCodes
-          : this.queryParams.deptcodes,
-      };
-      this.loading = true;
-      // 绉婚櫎鍙兘瀛樺湪鐨�"all"鍊�
-      delete params.leavehospitaldistrictcodes.all;
-      delete params.deptcodes.all;
-      getSfStatistics(params).then((response) => {
-        this.loading = false;
-
-        this.total = response.total;
-        // this.userList = response.data;
-        this.userList = this.customSort(response.data);
-      });
-    },
-    sortChineseNumber(aRow, bRow) {
-      const a = aRow.leavehospitaldistrictname;
-      const b = bRow.leavehospitaldistrictname;
-
-      // 涓枃鏁板瓧鍒伴樋鎷変集鏁板瓧鐨勬槧灏勶紙鎵╁睍鍒�45锛�
-      const chineseNumMap = {
-        涓�: 1,
-        浜�: 2,
-        涓�: 3,
-        鍥�: 4,
-        浜�: 5,
-        鍏�: 6,
-        涓�: 7,
-        鍏�: 8,
-        涔�: 9,
-        鍗�: 10,
-        鍗佷竴: 11,
-        鍗佷簩: 12,
-        鍗佷笁: 13,
-        鍗佸洓: 14,
-        鍗佷簲: 15,
-        鍗佸叚: 16,
-        鍗佷竷: 17,
-        鍗佸叓: 18,
-        鍗佷節: 19,
-        浜屽崄: 20,
-        浜屽崄涓�: 21,
-        浜屽崄浜�: 22,
-        浜屽崄涓�: 23,
-        浜屽崄鍥�: 24,
-        浜屽崄浜�: 25,
-        浜屽崄鍏�: 26,
-        浜屽崄涓�: 27,
-        浜屽崄鍏�: 28,
-        浜屽崄涔�: 29,
-        涓夊崄: 30,
-        涓夊崄涓�: 31,
-        涓夊崄浜�: 32,
-        涓夊崄涓�: 33,
-        涓夊崄鍥�: 34,
-        涓夊崄浜�: 35,
-        涓夊崄鍏�: 36,
-        涓夊崄涓�: 37,
-        涓夊崄鍏�: 38,
-        涓夊崄涔�: 39,
-        鍥涘崄: 40,
-        鍥涘崄涓�: 41,
-        鍥涘崄浜�: 42,
-        鍥涘崄涓�: 43,
-        鍥涘崄鍥�: 44,
-        鍥涘崄浜�: 45,
-      };
-
-      // 鎻愬彇涓枃鏁板瓧
-      const getNumberFromText = (text) => {
-        if (!text || typeof text !== "string") return -1;
-
-        // 鍖归厤涓枃鏁板瓧锛屾敮鎸佷竴鍒板洓鍗佷簲
-        const match = text.match(/^([涓�浜屼笁鍥涗簲鍏竷鍏節鍗乚+)/);
-
-        if (match && match[1]) {
-          const chineseNum = match[1];
-          return chineseNumMap[chineseNum] !== undefined
-            ? chineseNumMap[chineseNum]
-            : -1;
-        }
-
-        // 濡傛灉娌℃湁鍖归厤鍒颁腑鏂囨暟瀛楋紝灏濊瘯鍖归厤闃挎媺浼暟瀛�
-        const arabicMatch = text.match(/^(\d+)/);
-        if (arabicMatch && arabicMatch[1]) {
-          const num = parseInt(arabicMatch[1], 10);
-          return num >= 1 && num <= 45 ? num : -1;
-        }
-
-        return -1;
-      };
-
-      const numA = getNumberFromText(a);
-      const numB = getNumberFromText(b);
-
-      // 澶勭悊鏃犳硶瑙f瀽鐨勬儏鍐�
-      if (numA === -1 && numB === -1) {
-        return (a || "").localeCompare(b || "");
-      }
-      if (numA === -1) return 1;
-      if (numB === -1) return -1;
-
-      return numA - numB;
-    },
-    // 鎼滅储澶勭悊鍑芥暟
-    handleSearch() {
-      if (!this.searchName.trim()) {
-        // 濡傛灉鎼滅储妗嗕负绌猴紝鏄剧ず鎵�鏈夋暟鎹�
-        this.currentDisplayList = [...this.infotitlelist];
-      } else {
-        // 鏍规嵁鎮h�呭鍚嶈繘琛岀瓫閫夛紙涓嶅尯鍒嗗ぇ灏忓啓锛�
-        const keyword = this.searchName.toLowerCase();
-        this.currentDisplayList = this.infotitlelist.filter((item) => {
-          return item.sendname && item.sendname.toLowerCase().includes(keyword);
-        });
-      }
-    },
-    customSort(data) {
-      // 瀹氫箟鎮ㄦ湡鏈涚殑鐥呭尯椤哄簭锛堟墿灞曞埌鍥涘崄浜旓級
-      const order = [
-        "涓�",
-        "浜�",
-        "涓�",
-        "鍥�",
-        "浜�",
-        "鍏�",
-        "涓�",
-        "鍏�",
-        "涔�",
-        "鍗�",
-        "鍗佷竴",
-        "鍗佷簩",
-        "鍗佷笁",
-        "鍗佸洓",
-        "鍗佷簲",
-        "鍗佸叚",
-        "鍗佷竷",
-        "鍗佸叓",
-        "鍗佷節",
-        "浜屽崄",
-        "浜屽崄涓�",
-        "浜屽崄浜�",
-        "浜屽崄涓�",
-        "浜屽崄鍥�",
-        "浜屽崄浜�",
-        "浜屽崄鍏�",
-        "浜屽崄涓�",
-        "浜屽崄鍏�",
-        "浜屽崄涔�",
-        "涓夊崄",
-        "涓夊崄涓�",
-        "涓夊崄浜�",
-        "涓夊崄涓�",
-        "涓夊崄鍥�",
-        "涓夊崄浜�",
-        "涓夊崄鍏�",
-        "涓夊崄涓�",
-        "涓夊崄鍏�",
-        "涓夊崄涔�",
-        "鍥涘崄",
-        "鍥涘崄涓�",
-        "鍥涘崄浜�",
-        "鍥涘崄涓�",
-        "鍥涘崄鍥�",
-        "鍥涘崄浜�",
-      ];
-
-      return data.sort((a, b) => {
-        // 鎻愬彇鐥呭尯鍚嶇О涓殑涓枃鏁板瓧閮ㄥ垎
-        const getIndex = (name) => {
-          if (!name || typeof name !== "string") return -1;
-
-          // 鍖归厤涓枃鏁板瓧
-          const chineseMatch = name.match(/^([涓�浜屼笁鍥涗簲鍏竷鍏節鍗乚+)/);
-          if (chineseMatch && chineseMatch[1]) {
-            return order.indexOf(chineseMatch[1]);
-          }
-
-          // 鍖归厤闃挎媺浼暟瀛�
-          const arabicMatch = name.match(/^(\d+)/);
-          if (arabicMatch && arabicMatch[1]) {
-            const num = parseInt(arabicMatch[1], 10);
-            if (num >= 1 && num <= 45) {
-              return num - 1; // 鍥犱负鏁扮粍绱㈠紩浠�0寮�濮�
-            }
-          }
-
-          return -1;
-        };
-
-        const indexA = getIndex(a.leavehospitaldistrictname);
-        const indexB = getIndex(b.leavehospitaldistrictname);
-
-        // 鎺掑簭閫昏緫
-        if (indexA === -1 && indexB === -1) {
-          return (a.leavehospitaldistrictname || "").localeCompare(
-            b.leavehospitaldistrictname || ""
-          );
-        }
-        if (indexA === -1) return 1;
-        if (indexB === -1) return -1;
-        return indexA - indexB;
-      });
-    },
-    getRowKey(row) {
-      return row.statisticaltype === 1
-        ? row.leavehospitaldistrictcode
-        : row.deptcode;
-    },
-
-    // 澶勭悊琛岀偣鍑诲睍寮�
-    handleRowClick(row) {
-      console.log(row, "row");
-
-      // 濡傛灉宸茬粡灞曞紑鍒欐敹璧�
-      if (this.expands.includes(this.getRowKey(row))) {
-        this.expands = [];
-        return;
-      }
-      // 澶勭悊鏌ヨ鍙傛暟
-      const params = {
-        ...this.queryParams,
-        // 濡傛灉閫夋嫨浜�"鍏ㄩ儴"锛屽垯浼犳墍鏈夌梾鍖�/绉戝浠g爜
-        deptcodes: this.queryParams.deptcodes.includes("all")
-          ? this.allDeptCodes
-          : this.queryParams.deptcodes,
-        leavehospitaldistrictcodes: [row.leavehospitaldistrictcode],
-        drcode: "1",
-      };
-
-      // 绉婚櫎鍙兘瀛樺湪鐨�"all"鍊�
-      delete params.leavehospitaldistrictcodes.all;
-      delete params.deptcodes.all;
-      // 濡傛灉璇ヨ杩樻病鏈夊姞杞藉尰鐢熸暟鎹紝鍒欏姞杞�
-      if (!row.doctorStats) {
-        this.loading = true;
-        getSfStatistics(params).then((res) => {
-          this.$set(row, "doctorStats", res.data);
-          this.expands = [this.getRowKey(row)];
-          this.loading = false;
-        });
-      } else {
-        this.expands = [this.getRowKey(row)];
-      }
-    },
-    getSummaries(param) {
-      const { columns, data } = param;
-      const sums = [];
-
-      columns.forEach((column, index) => {
-        if (index === 0) {
-          sums[index] = "鍚堣";
-          return;
-        }
-        if (index === 1 || index === 2) {
-          sums[index] = "/";
-          return;
-        }
-
-        // 瀵圭櫨鍒嗘瘮瀛楁鐗规畩澶勭悊 - 鍙栧钩鍧囧��
-        if (
-          column.property === "followUpRate" ||
-          column.property === "rate" ||
-          column.property === "followUpRateAgain"
-        ) {
-          // 鎻愬彇鎵�鏈夋湁鏁堢櫨鍒嗘瘮鍊煎苟杞崲涓哄皬鏁�
-          const percentageValues = data
-            .map((item) => {
-              const value = item[column.property];
-              if (!value || value === "-" || value === "0%") return null;
-
-              // 澶勭悊甯︾櫨鍒嗗彿鐨勬暟鎹�
-              if (typeof value === "string" && value.includes("%")) {
-                // 鍘婚櫎鐧惧垎鍙峰苟杞崲涓哄皬鏁�
-                const numValue = parseFloat(value.replace("%", "")) / 100;
-                return isNaN(numValue) ? null : numValue;
-              } else {
-                // 澶勭悊宸茬粡鏄皬鏁扮殑鏁版嵁
-                const numValue = parseFloat(value);
-                return isNaN(numValue) ? null : numValue;
-              }
-            })
-            .filter((value) => value !== null && value !== 0); // 杩囨护鎺塶ull鍜�0鍊�
-
-          if (percentageValues.length > 0) {
-            const average =
-              percentageValues.reduce((sum, value) => sum + value, 0) /
-              percentageValues.length;
-            sums[index] = (average * 100).toFixed(2) + "%";
-          } else {
-            sums[index] = "0.00%";
-          }
-        } else {
-          // 鏅�氭暟瀛楀瓧娈� - 姹傚拰
-          const values = data.map((item) => {
-            const value = item[column.property];
-            if (value === "-" || value === "" || value === null) return 0;
-            return Number(value) || 0;
-          });
-
-          if (!values.every((value) => isNaN(value))) {
-            sums[index] = values.reduce((prev, curr) => prev + curr, 0);
-            sums[index] = this.formatNumber(sums[index]);
-          } else {
-            sums[index] = "-";
-          }
-        }
-      });
-
-      return sums;
-    },
-
-    // 鍐呴儴琛ㄦ牸鍚堣琛岃绠楁柟娉�
-    getInnerSummaries(param) {
-      const { columns, data } = param;
-      const sums = [];
-
-      columns.forEach((column, index) => {
-        if (index === 0) {
-          sums[index] = "灏忚";
-          return;
-        }
-
-        if (column.property === "drname" || column.property === "deptname") {
-          sums[index] = "-";
-          return;
-        }
-
-        // 瀵圭櫨鍒嗘瘮瀛楁鐗规畩澶勭悊 - 鍙栧钩鍧囧��
-        if (column.property === "followUpRate" || column.property === "rate") {
-          // 鎻愬彇鎵�鏈夋湁鏁堢櫨鍒嗘瘮鍊煎苟杞崲涓哄皬鏁�
-          const percentageValues = data
-            .map((item) => {
-              const value = item[column.property];
-              if (!value || value === "-" || value === "0%") return null;
-
-              // 澶勭悊甯︾櫨鍒嗗彿鐨勬暟鎹�
-              if (typeof value === "string" && value.includes("%")) {
-                // 鍘婚櫎鐧惧垎鍙峰苟杞崲涓哄皬鏁�
-                const numValue = parseFloat(value.replace("%", "")) / 100;
-                return isNaN(numValue) ? null : numValue;
-              } else {
-                // 澶勭悊宸茬粡鏄皬鏁扮殑鏁版嵁
-                const numValue = parseFloat(value);
-                return isNaN(numValue) ? null : numValue;
-              }
-            })
-            .filter((value) => value !== null && value !== 0);
-
-          if (percentageValues.length > 0) {
-            const average =
-              percentageValues.reduce((sum, value) => sum + value, 0) /
-              percentageValues.length;
-            sums[index] = (average * 100).toFixed(2) + "%";
-          } else {
-            sums[index] = "0.00%";
-          }
-        } else {
-          // 鏅�氭暟瀛楀瓧娈� - 姹傚拰
-          const values = data.map((item) => {
-            const value = item[column.property];
-            if (value === "-" || value === "" || value === null) return 0;
-            return Number(value) || 0;
-          });
-
-          if (!values.every((value) => isNaN(value))) {
-            sums[index] = values.reduce((prev, curr) => prev + curr, 0);
-            sums[index] = this.formatNumber(sums[index]);
-          } else {
-            sums[index] = "-";
-          }
-        }
-      });
-
-      return sums;
-    },
-
-    // 杈呭姪鏂规硶锛氭彁鍙栫櫨鍒嗘瘮鏁板��
-    extractPercentageValue(value) {
-      if (!value) return null;
-
-      if (typeof value === "string") {
-        // 澶勭悊甯︾櫨鍒嗗彿鐨勫瓧绗︿覆
-        if (value.includes("%")) {
-          const num = parseFloat(value.replace("%", ""));
-          return isNaN(num) ? null : num / 100;
-        }
-        // 澶勭悊绾暟瀛楀瓧绗︿覆
-        const num = parseFloat(value);
-        return isNaN(num) ? null : num;
-      }
-
-      // 澶勭悊鏁板瓧绫诲瀷
-      return typeof value === "number" ? value : null;
-    },
-
-    // 鏁板瓧鏍煎紡鍖栨柟娉�
-    formatNumber(num) {
-      if (isNaN(num)) return "-";
-      return Number.isInteger(num) ? num.toString() : num.toFixed(0);
-    },
-    /** 淇敼鏍囩 */
-    handleUpdate(row) {
-      console.log(row, "淇敼鏍囩");
-      this.lstamendtagVisible = true;
-      this.lstamendtag = true;
-      this.tagform = {
-        isupload: row.isupload,
-        tagname: row.tagname,
-        tagcategoryid: row.tagcategoryid,
-        tagdescription: row.tagdescription,
-        tagid: row.tagid,
-      };
-    },
-    // 鑾峰彇绉戝鏍�
     getDeptTree() {
       // 绉戝鍒楄〃
-      this.flatArraydept = store.getters.belongDepts.map((dept) => {
+      this.flatArraydept = this.$store.getters.belongDepts.map((dept) => {
         return {
           label: dept.deptName,
-          value: dept.deptCode,
-        };
-      });
-      // 瀛樺偍鎵�鏈夌瀹や唬鐮�
-      this.allDeptCodes = store.getters.belongDepts.map(
-        (dept) => dept.deptCode
-      );
+          value: dept.deptCode
+        }
+      })
+      this.allDeptCodes = this.$store.getters.belongDepts.map((dept) => dept.deptCode)
 
       // 鐥呭尯鍒楄〃
-      this.flatArrayhospit = store.getters.belongWards.map((ward) => {
+      this.flatArrayhospit = this.$store.getters.belongWards.map((ward) => {
         return {
           label: ward.districtName,
-          value: ward.districtCode,
-        };
-      });
-
-      // 瀛樺偍鎵�鏈夌梾鍖轰唬鐮�
-      this.allWardCodes = store.getters.belongWards.map(
-        (ward) => ward.districtCode
-      );
-      this.flatArraydept.push({ label: "鍏ㄩ儴", value: "all" });
-      this.flatArrayhospit.push({ label: "鍏ㄩ儴", value: "all" });
-    },
-    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); // 灏嗘渶搴曞眰鐨勫厓绱犳坊鍔犲埌缁撴灉鏁扮粍
+          value: ward.districtCode
         }
+      })
+      this.allWardCodes = this.$store.getters.belongWards.map((ward) => ward.districtCode)
+
+      this.flatArraydept.push({ label: '鍏ㄩ儴', value: 'all' })
+      this.flatArrayhospit.push({ label: '鍏ㄩ儴', value: 'all' })
+    },
+
+    handleTabClick(tab) {
+      this.activeTab = tab.name
+      this.loadCurrentTabData()
+    },
+
+    loadCurrentTabData() {
+      switch (this.activeTab) {
+        case 'first':
+          this.$refs.firstFollowUp.loadData()
+          break
+        case 'second':
+          this.$refs.secondFollowUp.loadData()
+          break
+        case 'continued':
+          this.$refs.continuedCare.loadData()
+          break
+      }
+    },
+
+    handleQuery() {
+      this.queryParams.startTime = this.parseTime(this.queryParams.dateRange[0])
+      this.queryParams.endTime = this.parseTime(this.queryParams.dateRange[1])
+
+      if (this.queryParams.statisticaltype == 1) {
+        this.queryParams.deptcodes = []
+      } else if (this.queryParams.statisticaltype == 2) {
+        this.queryParams.leavehospitaldistrictcodes = []
       }
 
-      // 浠庨《灞傚厓绱犲紑濮嬮�掑綊
-      multiArray.forEach((element) => flatten(element));
-      return result; // 杩斿洖鍙寘鍚渶搴曞眰鍏冪礌鐨勪竴缁存暟缁�
+      this.loadCurrentTabData()
     },
-    addladeltag() {
-      this.lstamendtagVisible = true;
-      this.lstamendtag = false;
-      this.tagform = {
-        isupload: "",
-        tagname: "",
-        tagcategoryid: "",
-        tagdescription: "",
-        tagid: "",
-      };
+
+    resetQuery() {
+      this.queryParams.dateRange = []
+      this.queryParams.leavehospitaldistrictcodes = []
+      this.handleQuery()
     },
-    Seedetails(row) {
-      this.SeedetailsVisible = true;
-      this.Seedloading = true;
-      this.patientqueryParams.starttime = this.parseTime(
-        this.queryParams.dateRange[0]
-      );
-      this.patientqueryParams.endtime = this.parseTime(
-        this.queryParams.dateRange[1]
-      );
-      this.patientqueryParams.deptcode = row.deptcode;
-      selectTimelyRate(this.patientqueryParams).then((response) => {
-        this.logsheetlist = response.data.detail;
-        this.patienttotal = response.data.total;
-        this.Seedloading = false;
-      });
+
+    async handleExport() {
+      switch (this.activeTab) {
+        case 'first':
+          await this.$refs.firstFollowUp.exportTable()
+          break
+        case 'second':
+          await this.$refs.secondFollowUp.exportTable()
+          break
+        case 'continued':
+          await this.$refs.continuedCare.exportTable()
+          break
+      }
     },
-    Seedetailstion() {
-      selectTimelyRate(this.patientqueryParams).then((response) => {
-        this.logsheetlist = response.data.detail;
-        this.patienttotal = response.data.total;
-        this.Seedloading = false;
-      });
+
+    showChartDialog() {
+      this.chartData = this.getCurrentTabData()
+      this.chartDialogVisible = true
     },
+
+    getCurrentTabData() {
+      switch (this.activeTab) {
+        case 'first':
+          return this.$refs.firstFollowUp.tableData
+        case 'second':
+          return this.$refs.secondFollowUp.tableData
+        case 'continued':
+          return this.$refs.continuedCare.tableData
+        default:
+          return []
+      }
+    },
+
     viewDetails(row, title) {
-      this.infotitleVisible = true;
-      this.infotitle = title;
-      this.infotitlelist = row; // 鍋囪row灏辨槸闇�瑕佸睍绀虹殑璇︾粏鏁扮粍
-      console.log(this.infotitlelist, "this.infotitlelist");
-
-      this.infotitlelist.forEach((item) => {
-        let idArray = null;
-
-        if (item.preachform) {
-          if (item.endtime) {
-            item.preachformson = item.preachform;
-            idArray = item.preachform.split(",");
-          }
-
-          item.preachform = idArray.map((value) => {
-            // 鏌ユ壘id瀵瑰簲鐨勫璞�
-            const item = this.checkboxlist.find((item) => item.value == value);
-            // 濡傛灉鎵惧埌瀵瑰簲鐨刬d锛岃繑鍥瀕abel鍊硷紝鍚﹀垯杩斿洖null
-            return item ? item.label : null;
-          });
-        }
-      });
-      // 鍒濆鍖栧姞杞�
-      this.loadIndex = 0;
-      this.currentDisplayList = [];
-      this.$nextTick(() => {
-        this.loadMoreData();
-      });
+      this.infotitle = title
+      this.infotitlelist = row
+      this.infotitleVisible = true
     },
-    loadMoreData() {
-      if (this.isLoading) return;
-      this.isLoading = true;
 
-      // 妯℃嫙寮傛鍔犺浇锛屽疄闄呭彲鑳芥槸鐩存帴鍒囩墖鏈湴鏁版嵁
-      setTimeout(() => {
-        console.log(this.infotitlelist, "this.infotitlelist");
+    Seedetails(row) {
+      this.SeedetailsVisible = true
+      this.Seedloading = true
 
-        const nextChunk = this.infotitlelist.slice(
-          this.loadIndex,
-          this.loadIndex + this.pageSize
-        );
-        this.currentDisplayList = this.currentDisplayList.concat(nextChunk);
-        this.loadIndex += this.pageSize;
-        this.isLoading = false;
-      }, 200);
+      this.$refs.firstFollowUp.selectTimelyRate(row, this.queryParams.dateRange)
+        .then(response => {
+          this.logsheetlist = response.data.detail
+          this.patienttotal = response.data.total
+          this.Seedloading = false
+        })
     },
-    handleScroll(event) {
-      const scrollContainer = event.target;
-      // 鍒ゆ柇鏄惁婊氬姩鍒板簳閮�
-      const isAtBottom =
-        scrollContainer.scrollTop + scrollContainer.clientHeight >=
-        scrollContainer.scrollHeight - 10;
 
-      if (
-        isAtBottom &&
-        !this.isLoading &&
-        this.loadIndex < this.infotitlelist.length
-      ) {
-        this.loadMoreData();
-      }
+    Seedetailstion() {
+      this.$refs.firstFollowUp.selectTimelyRate(this.patientqueryParams)
+        .then(response => {
+          this.logsheetlist = response.data.detail
+          this.patienttotal = response.data.total
+        })
     },
+
     SeedetailsgGo(row) {
-      this.SeedetailsVisible = false;
-      let type = "";
-      if (row.preachformson && row.preachformson.includes("3")) {
-        type = 1;
+      this.SeedetailsVisible = false
+      let type = ''
+      if (row.preachformson && row.preachformson.includes('3')) {
+        type = 1
       }
       setTimeout(() => {
         this.$router.push({
-          path: "/followvisit/record/detailpage/",
+          path: '/followvisit/record/detailpage/',
           query: {
             taskid: row.taskid,
             patid: row.patid,
             id: row.id,
-            Voicetype: type,
-            // visitCount: this.topqueryParams.visitCount,
-          },
-        });
-      }, 300);
-    },
-    // 娣诲姞/淇敼鏍囩
-    Maintenancetag() {
-      if (this.lstamendtag) {
-        toamendtag(this.addDateRange(this.tagform)).then((response) => {
-          console.log(response);
-          this.getList();
-        });
-      } else {
-        addapitag(this.addDateRange(this.tagform)).then((response) => {
-          console.log(response);
-          this.getList();
-        });
-      }
-      this.tagform = {
-        isupload: "",
-        tagname: "",
-        tagcategoryid: "",
-        tagdescription: "",
-        tagid: "",
-      };
-    },
-    routerErr(row) {
-      console.log(row, "璺宠浆寮傚父");
-      this.$router.push({
-        path: "/followvisit/discharge",
-        query: {
-          errtype: 1,
-          leavehospitaldistrictcode: row.leavehospitaldistrictcode,
-        },
-      });
-    },
-
-    // 琛ㄥ崟閲嶇疆
-    reset() {
-      this.form = {
-        userId: undefined,
-        deptId: undefined,
-        userName: undefined,
-        nickName: undefined,
-        password: undefined,
-        phonenumber: undefined,
-        email: undefined,
-        sex: undefined,
-        status: "0",
-        remark: undefined,
-        postIds: [],
-        roleIds: [],
-      };
-      this.resetForm("form");
-    },
-    // 鏍囩鐘舵�佷慨鏀�
-    handleStatusChange(row) {
-      console.log(row.isupload);
-      let text = row.isupload === "0" ? "鍚敤" : "鍋滅敤";
-      this.$modal
-        .confirm('纭瑕�"' + text + '""' + row.tagname + '"鏍囩鍚楋紵')
-        .then(function () {
-          return changetagcategory(row.tagid, row.isupload);
-        })
-        .then(() => {
-          this.$modal.msgSuccess(text + "鎴愬姛");
-        })
-        .catch(function () {
-          row.isupload = row.isupload === "0" ? "1" : "0";
-        });
-    },
-    /** 鎼滅储鎸夐挳鎿嶄綔 */
-    handleQuery() {
-      this.queryParams.pageNum = 1;
-      if (!this.queryParams.dateRange) this.queryParams.dateRange = [];
-      if (this.queryParams.statisticaltype == 1) {
-        this.queryParams.deptcodes = [];
-      } else if (this.queryParams.statisticaltype == 2) {
-        this.queryParams.leavehospitaldistrictcodes = [];
-      }
-      console.log(this.queryParams.dateRange);
-
-      this.queryParams.startTime = this.parseTime(
-        this.queryParams.dateRange[0]
-      );
-      this.queryParams.endTime = this.parseTime(this.queryParams.dateRange[1]);
-      this.getList();
-    },
-    /** 閲嶇疆鎸夐挳鎿嶄綔 */
-    resetQuery() {
-      this.queryParams.dateRange = [];
-      this.queryParams.leavehospitaldistrictcodes = [];
-      this.handleQuery();
-    },
-    // 澶氶�夋閫変腑鏁版嵁
-    handleSelectionChange(selection) {
-      this.ids = selection.map((item) => item.tagid);
-      this.single = selection.length != 1;
-      this.multiple = !selection.length;
-    },
-
-    /** 鍒犻櫎鎸夐挳鎿嶄綔 */
-    handleDelete(row) {
-      console.log(row, "鍒犻櫎寮圭獥");
-      const tagids = row.tagid || this.ids;
-      console.log(tagids);
-      const tagname = row.tagname;
-      this.$modal
-        .confirm(
-          tagname
-            ? '鏄惁纭鍒犻櫎鏍囩鍚嶇О涓�"' + tagname + '"鐨勬暟鎹」锛�'
-            : "鏄惁纭鍒犻櫎閫変腑鐨勬暟鎹」锛�"
-        )
-        .then(function () {
-          return deletetag(tagids);
-        })
-        .then(() => {
-          this.getList();
-          this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
-        })
-        .catch(() => {});
-    },
-    // 瀵煎嚭鏂规硶
-    // 鏇挎崲鎮ㄥ師鏉ョ殑 exportTable 鏂规硶
-    async exportTable() {
-      try {
-        // 1. 鑾峰彇骞舵牸寮忓寲鏃ユ湡鑼冨洿
-        let dateRangeString = ""; // 鐢ㄤ簬鏂囦欢鍚�
-        let sheetNameSuffix = ""; // 鐢ㄤ簬宸ヤ綔琛ㄥ悕
-
-        // 妫�鏌ユ槸鍚﹀瓨鍦ㄩ�変腑鐨勬棩鏈熻寖鍥�
-        if (
-          this.queryParams.dateRange &&
-          this.queryParams.dateRange.length === 2
-        ) {
-          const startDateStr = this.queryParams.dateRange[0]; // 寮�濮嬫棩鏈熷瓧绗︿覆锛屼緥濡� "2026-01-01 00:00:00"
-          const endDateStr = this.queryParams.dateRange[1]; // 缁撴潫鏃ユ湡瀛楃涓�
-
-          // 鏍煎紡鍖栨棩鏈熶负 YYYY-MM-DD锛堝幓鎺夋椂闂撮儴鍒嗭級
-          const formatDateForDisplay = (dateTimeStr) => {
-            return dateTimeStr.split(" ")[0]; // 鍙栫┖鏍煎墠鐨勯儴鍒嗭紝鍗� "YYYY-MM-DD"
-          };
-
-          const startDateFormatted = formatDateForDisplay(startDateStr);
-          const endDateFormatted = formatDateForDisplay(endDateStr);
-
-          // 鏋勫缓鏃ユ湡鑼冨洿瀛楃涓�
-          dateRangeString = `${startDateFormatted}鑷�${endDateFormatted}`;
-          sheetNameSuffix = `${startDateFormatted}鑷�${endDateFormatted}`;
-        } else {
-          // 濡傛灉娌℃湁閫夋嫨鏃ユ湡鑼冨洿锛屽垯浣跨敤褰撳墠鏈堜唤浣滀负澶囬�夋柟妗�
-          const now = new Date();
-          const currentMonth = now.getMonth() + 1;
-          dateRangeString = `${currentMonth}鏈坄;
-          sheetNameSuffix = `${currentMonth}鏈坄;
-        }
-
-        // 2. 鍔ㄦ�佹瀯寤烘枃浠跺悕鍜屽伐浣滆〃鍚�
-        const excelName = `鍑洪櫌闅忚缁熻琛╛${dateRangeString}.xlsx`;
-        const worksheetName = `闅忚缁熻_${sheetNameSuffix}`; // 宸ヤ綔琛ㄥ悕涓嶈兘瓒呰繃31涓瓧绗2](@ref)
-        // 鍒涘缓鏂扮殑宸ヤ綔绨垮拰宸ヤ綔琛�
-        const workbook = new ExcelJS.Workbook();
-        const worksheet = workbook.addWorksheet(worksheetName); // 浣跨敤鍔ㄦ�佸伐浣滆〃鍚�
-        // 瀹氫箟鏍峰紡锛堟柊澧炴�绘爣棰樻牱寮忥級
-        const titleStyle = {
-          font: {
-            name: "寰蒋闆呴粦",
-            size: 16,
-            bold: true,
-            color: { argb: "FF000000" },
-          },
-          fill: {
-            type: "pattern",
-            pattern: "solid",
-            fgColor: { argb: "FFE6F3FF" },
-          },
-          alignment: {
-            vertical: "middle",
-            horizontal: "center",
-            wrapText: true,
-          },
-          border: {
-            top: { style: "thin", color: { argb: "FFD0D0D0" } },
-            left: { style: "thin", color: { argb: "FFD0D0D0" } },
-            bottom: { style: "thin", color: { argb: "FFD0D0D0" } },
-            right: { style: "thin", color: { argb: "FFD0D0D0" } },
-          },
-        };
-        // 瀹氫箟鏍峰紡
-        const headerStyle = {
-          font: {
-            name: "寰蒋闆呴粦",
-            size: 11,
-            bold: true,
-            color: { argb: "FF000000" },
-          },
-          fill: {
-            type: "pattern",
-            pattern: "solid",
-            fgColor: { argb: "FFF5F7FA" },
-          },
-          alignment: {
-            vertical: "middle",
-            horizontal: "center",
-            wrapText: true,
-          },
-          border: {
-            top: { style: "thin", color: { argb: "FFD0D0D0" } },
-            left: { style: "thin", color: { argb: "FFD0D0D0" } },
-            bottom: { style: "thin", color: { argb: "FFD0D0D0" } },
-            right: { style: "thin", color: { argb: "FFD0D0D0" } },
-          },
-        };
-
-        const cellStyle = {
-          font: {
-            name: "瀹嬩綋",
-            size: 10,
-            color: { argb: "FF000000" },
-          },
-          alignment: {
-            vertical: "middle",
-            horizontal: "center",
-          },
-          border: {
-            top: { style: "thin", color: { argb: "FFD0D0D0" } },
-            left: { style: "thin", color: { argb: "FFD0D0D0" } },
-            bottom: { style: "thin", color: { argb: "FFD0D0D0" } },
-            right: { style: "thin", color: { argb: "FFD0D0D0" } },
-          },
-        };
-
-        const summaryStyle = {
-          font: {
-            name: "瀹嬩綋",
-            size: 10,
-            bold: true,
-            color: { argb: "FF409EFF" },
-          },
-          fill: {
-            type: "pattern",
-            pattern: "solid",
-            fgColor: { argb: "FFF5F7FA" },
-          },
-          alignment: {
-            vertical: "middle",
-            horizontal: "center",
-          },
-          border: {
-            top: { style: "thin", color: { argb: "FFD0D0D0" } },
-            left: { style: "thin", color: { argb: "FFD0D0D0" } },
-            bottom: { style: "thin", color: { argb: "FFD0D0D0" } },
-            right: { style: "thin", color: { argb: "FFD0D0D0" } },
-          },
-        };
-        // 1. 娣诲姞鎬绘爣棰樿锛堢涓�琛岋級
-        worksheet.mergeCells(1, 1, 1, 23); // 鍚堝苟A1鍒癢1鐨勬墍鏈夊垪[1,4](@ref)
-        const titleCell = worksheet.getCell(1, 1);
-        titleCell.value = `${sheetNameSuffix}鍑洪櫌闅忚缁熻琛╜; // 浣跨敤鏂囦欢鍚嶄綔涓烘�绘爣棰�
-        titleCell.style = titleStyle;
-        worksheet.getRow(1).height = 35; // 璁剧疆鎬绘爣棰樿楂�
-        // 1. 棣栧厛锛屽垱寤哄苟璁剧疆绗簩琛岋紙瀛愯〃澶达級鐨勬墍鏈夊崟鍏冩牸
-        const secondRowHeaders = [
-          "", // A2 灞曞紑鍒楀崰浣嶏紙鍏跺�煎皢鐢辩涓�琛屽悎骞跺悗鐨勪富鍗曞厓鏍煎喅瀹氾級
-          "鍑洪櫌鐥呭尯",
-          "绉戝",
-          "鍑洪櫌浜烘",
-          "鏃犻渶闅忚浜烘",
-          "搴旈殢璁夸汉娆�", // B2 to F2
-          // 棣栨鍑洪櫌闅忚瀛愯〃澶�
-          "闇�闅忚",
-          "寰呴殢璁�",
-          "闅忚鎴愬姛",
-          "闅忚澶辫触",
-          "闅忚鐜�",
-          "鍙婃椂鐜�",
-          "浜哄伐",
-          "鐭俊",
-          "寰俊",
-          // 鍐嶆鍑洪櫌闅忚瀛愯〃澶�
-          "闇�闅忚",
-          "寰呴殢璁�",
-          "闅忚鎴愬姛",
-          "闅忚澶辫触",
-          "闅忚鐜�",
-          "浜哄伐",
-          "鐭俊",
-          "寰俊",
-        ];
-
-        // 娣诲姞绗簩琛岋紙鍘熺涓�琛屼笅绉伙級
-        secondRowHeaders.forEach((header, index) => {
-          const cell = worksheet.getCell(3, index + 1); // 鏀逛负绗�3琛�
-          cell.value = header;
-          cell.style = headerStyle;
-        });
-
-        // 3. 璋冩暣鍘熷悎骞跺崟鍏冩牸浣嶇疆锛堝師绗�1琛屽悎骞跺崟鍏冩牸涓嬬Щ鍒扮2琛岋級
-        // 鍚堝苟 A2:A3
-        worksheet.mergeCells(2, 1, 3, 1);
-        worksheet.getCell(2, 1).value = "";
-        worksheet.getCell(2, 1).style = headerStyle;
-
-        // 鍚堝苟 B2:B3
-        worksheet.mergeCells(2, 2, 3, 2);
-        worksheet.getCell(2, 2).value = "鍑洪櫌鐥呭尯";
-        worksheet.getCell(2, 2).style = headerStyle;
-
-        // 鍚堝苟 C2:C3
-        worksheet.mergeCells(2, 3, 3, 3);
-        worksheet.getCell(2, 3).value = "绉戝";
-        worksheet.getCell(2, 3).style = headerStyle;
-
-        // 鍚堝苟 D2:D3
-        worksheet.mergeCells(2, 4, 3, 4);
-        worksheet.getCell(2, 4).value = "鍑洪櫌浜烘";
-        worksheet.getCell(2, 4).style = headerStyle;
-
-        // 鍚堝苟 E2:E3
-        worksheet.mergeCells(2, 5, 3, 5);
-        worksheet.getCell(2, 5).value = "鏃犻渶闅忚浜烘";
-        worksheet.getCell(2, 5).style = headerStyle;
-
-        // 鍚堝苟 F2:F3
-        worksheet.mergeCells(2, 6, 3, 6);
-        worksheet.getCell(2, 6).value = "搴旈殢璁夸汉娆�";
-        worksheet.getCell(2, 6).style = headerStyle;
-
-        // 4. 璋冩暣妯悜鍚堝苟鏍囬浣嶇疆锛堜笅绉诲埌绗�2琛岋級
-        // 棣栨鍑洪櫌闅忚锛堝悎骞禛2:O2锛�
-        worksheet.mergeCells(2, 7, 2, 15); // G2:O2
-        worksheet.getCell(2, 7).value = "棣栨鍑洪櫌闅忚";
-        worksheet.getCell(2, 7).style = headerStyle;
-
-        // 鍐嶆鍑洪櫌闅忚锛堝悎骞禤2:W2锛�
-        worksheet.mergeCells(2, 16, 2, 23); // P2:W2
-        worksheet.getCell(2, 16).value = "鍐嶆鍑洪櫌闅忚";
-        worksheet.getCell(2, 16).style = headerStyle;
-
-        // 5. 璁剧疆琛岄珮
-        worksheet.getRow(1).height = 35; // 鎬绘爣棰樿楂�
-        worksheet.getRow(2).height = 28; // 鍘熺涓�琛屼笅绉�
-        worksheet.getRow(3).height = 25; // 鍘熺浜岃涓嬬Щ
-
-        // 6. 娣诲姞鏁版嵁琛岋紙娉ㄦ剰琛岀储寮曢渶瑕�+1锛屽洜涓轰笂闈㈡彃鍏ヤ簡涓�琛岋級
-        this.userList.forEach((item, rowIndex) => {
-          const dataRow = worksheet.addRow(
-            [
-              "", // 灞曞紑鍒�
-              item.leavehospitaldistrictname || "",
-              item.deptname || "",
-              item.dischargeCount || 0,
-              item.nonFollowUp || 0,
-              item.followUpNeeded || 0,
-              // 棣栨鍑洪櫌闅忚鏁版嵁
-              item.needFollowUp || 0,
-              item.pendingFollowUp || 0,
-              item.followUpSuccess || 0,
-              item.followUpFail || 0,
-              item.followUpRate || "0%",
-              item.rate ? (Number(item.rate) * 100).toFixed(2) + "%" : "0%",
-              item.manual || 0,
-              item.sms || 0,
-              item.weChat || 0,
-              // 鍐嶆鍑洪櫌闅忚鏁版嵁
-              item.needFollowUpAgain || 0,
-              item.pendingFollowUpAgain || 0,
-              item.followUpSuccessAgain || 0,
-              item.followUpFailAgain || 0,
-              item.followUpRateAgain || "0%",
-              item.manualAgain || 0,
-              item.smsAgain || 0,
-              item.weChatAgain || 0,
-            ],
-            rowIndex + 4
-          ); // 浠庣4琛屽紑濮嬫坊鍔犳暟鎹紙鍘熺3琛岋級
-
-          // 搴旂敤鏁版嵁琛屾牱寮�
-          dataRow.eachCell((cell) => {
-            cell.style = cellStyle;
-          });
-          dataRow.height = 24;
-        });
-
-        // 娣诲姞鍚堣琛�
-        const summaries = this.getSummaries({
-          columns: [
-            { property: "" },
-            { property: "leavehospitaldistrictname" },
-            { property: "deptname" },
-            { property: "dischargeCount" },
-            { property: "nonFollowUp" },
-            { property: "followUpNeeded" },
-            { property: "needFollowUp" },
-            { property: "pendingFollowUp" },
-            { property: "followUpSuccess" },
-            { property: "followUpFail" },
-            { property: "followUpRate" },
-            { property: "rate" },
-            { property: "manual" },
-            { property: "sms" },
-            { property: "weChat" },
-            { property: "needFollowUpAgain" },
-            { property: "pendingFollowUpAgain" },
-            { property: "followUpSuccessAgain" },
-            { property: "followUpFailAgain" },
-            { property: "followUpRateAgain" },
-            { property: "manualAgain" },
-            { property: "smsAgain" },
-            { property: "weChatAgain" },
-          ],
-          data: this.userList,
-        });
-
-        const summaryRow = worksheet.addRow(summaries);
-        summaryRow.eachCell((cell, colNumber) => {
-          cell.style = summaryStyle;
-          // 绗竴鍒楁樉绀�"鍚堣"
-          if (colNumber === 1) {
-            cell.value = "鍚堣";
+            Voicetype: type
           }
-        });
-        summaryRow.height = 28;
-
-        // 璁剧疆鍒楀
-        worksheet.columns = [
-          { width: 8 }, // 灞曞紑鍒�
-          { width: 20 }, // 鍑洪櫌鐥呭尯
-          { width: 15 }, // 绉戝
-          { width: 12 }, // 鍑洪櫌浜烘
-          { width: 12 }, // 鏃犻渶闅忚浜烘
-          { width: 12 }, // 搴旈殢璁夸汉娆�
-          // 棣栨鍑洪櫌闅忚鍒�
-          { width: 10 },
-          { width: 10 },
-          { width: 10 },
-          { width: 10 },
-          { width: 12 },
-          { width: 12 },
-          { width: 8 },
-          { width: 8 },
-          { width: 8 },
-          // 鍐嶆鍑洪櫌闅忚鍒�
-          { width: 10 },
-          { width: 10 },
-          { width: 10 },
-          { width: 10 },
-          { width: 12 },
-          { width: 8 },
-          { width: 8 },
-          { width: 8 },
-        ];
-
-        // 鐢熸垚骞朵笅杞芥枃浠�
-        const buffer = await workbook.xlsx.writeBuffer();
-        const blob = new Blob([buffer], {
-          type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
-        });
-        saveAs(blob, excelName);
-
-        this.$message.success("瀵煎嚭鎴愬姛");
-        return true;
-      } catch (error) {
-        console.error("瀵煎嚭澶辫触:", error);
-        this.$message.error(`瀵煎嚭澶辫触: ${error.message}`);
-        return false;
-      }
+        })
+      }, 300)
     },
 
-    // 鏄剧ず鍥捐〃寮圭獥
-
-    showChartDialog() {
-      this.chartDialogVisible = true;
-      this.$nextTick(() => {
-        this.initPieChart();
-        this.initBarLineChart();
-      });
-    },
-    // 鍦╩ethods涓慨鏀圭粺璁℃柟娉�
-    showChartDialog() {
-      this.chartDialogVisible = true;
-      this.$nextTick(() => {
-        console.log(this.userList, "this.userList");
-
-        this.initCharts();
-      });
-    },
-
-    // 鏂板鍒濆鍖栧浘琛ㄦ柟娉�
-    initCharts() {
-      this.initPieChart();
-      this.initBarLineChart();
-    },
-
-    // 鍒濆鍖栭ゼ鍥�
-    initPieChart() {
-      const echarts = require("echarts");
-      const pieDom = document.getElementById("pieChart");
-      if (!pieDom) return;
-
-      if (this.pieChart) {
-        this.pieChart.dispose();
-      }
-
-      this.pieChart = echarts.init(pieDom);
-
-      // 璁$畻楗煎浘鏁版嵁
-      const followUpData = {
-        pending: 0,
-        success: 0,
-        fail: 0,
-      };
-
-      this.userList.forEach((item) => {
-        followUpData.pending += item.pendingFollowUp || 0;
-        followUpData.success += item.followUpSuccess || 0;
-        followUpData.fail += item.followUpFail || 0;
-      });
-
-      // 浣跨敤鏇寸編瑙傜殑棰滆壊鏂规
-      const pieOption = {
-        title: {
-          text: "闅忚鐘舵�佸垎甯�",
-          left: "center",
-          textStyle: {
-            color: "#333",
-            fontSize: 16,
-          },
-        },
-        tooltip: {
-          trigger: "item",
-          formatter: "{a} <br/>{b}: {c} ({d}%)",
-        },
-        legend: {
-          orient: "vertical",
-          left: "left",
-          data: ["寰呴殢璁�", "闅忚鎴愬姛", "闅忚澶辫触"],
-          textStyle: {
-            color: "#666",
-          },
-        },
-        color: ["#FF9D4D", "#36B37E", "#FF5C5C"], // 鏂扮殑閰嶈壊鏂规
-        series: [
-          {
-            name: "闅忚鐘舵��",
-            type: "pie",
-            radius: ["40%", "70%"],
-            avoidLabelOverlap: true,
-            itemStyle: {
-              borderRadius: 10,
-              borderColor: "#fff",
-              borderWidth: 2,
-            },
-            label: {
-              show: true,
-              formatter: "{b}: {c} ({d}%)",
-              color: "#333",
-            },
-            emphasis: {
-              label: {
-                show: true,
-                fontSize: "18",
-                fontWeight: "bold",
-              },
-              itemStyle: {
-                shadowBlur: 10,
-                shadowOffsetX: 0,
-                shadowColor: "rgba(0, 0, 0, 0.5)",
-              },
-            },
-            data: [
-              {
-                value: followUpData.pending,
-                name: "寰呴殢璁�",
-              },
-              {
-                value: followUpData.success,
-                name: "闅忚鎴愬姛",
-              },
-              {
-                value: followUpData.fail,
-                name: "闅忚澶辫触",
-              },
-            ],
-          },
-        ],
-      };
-
-      this.pieChart.setOption(pieOption);
-      window.addEventListener("resize", this.resizePieChart);
-    },
-
-    // 鍒濆鍖栨煴鐘舵姌绾垮浘
-    initBarLineChart() {
-      const echarts = require("echarts");
-      const barDom = document.getElementById("barLineChart");
-      if (!barDom) return;
-
-      if (this.barLineChart) {
-        this.barLineChart.dispose();
-      }
-
-      this.barLineChart = echarts.init(barDom);
-
-      // 鍑嗗鏁版嵁
-      const categories = this.userList.map(
-        (item) => item.leavehospitaldistrictname || item.deptname
-      );
-
-      const dischargeData = this.userList.map(
-        (item) => item.dischargeCount || 0
-      );
-      const followUpData = this.userList.map(
-        (item) => item.followUpNeeded || 0
-      );
-
-      // 鏂板涓ゆ潯鎶樼嚎鏁版嵁
-      const followUpRateData = this.userList.map((item) => {
-        if (!item.followUpRate) return 0;
-        // 鍘绘帀鐧惧垎鍙峰苟杞负鏁板瓧
-        const rateStr = String(item.followUpRate).replace("%", "");
-        return parseFloat(rateStr) || 0;
-      });
-
-      const timelyRateData = this.userList.map((item) =>
-        item.rate ? (Number(item.rate) * 100).toFixed(2) : 0
-      );
-
-      const option = {
-        title: {
-          text: "绉戝/鐥呭尯闅忚瓒嬪娍",
-          left: "center",
-          textStyle: {
-            color: "#333",
-            fontSize: 16,
-          },
-        },
-        tooltip: {
-          trigger: "axis",
-          axisPointer: {
-            type: "cross",
-            crossStyle: {
-              color: "#999",
-            },
-          },
-        },
-        legend: {
-          data: ["鍑洪櫌浜烘", "搴旈殢璁夸汉娆�", "闅忚鐜�(%)", "鍙婃椂鐜�(%)"],
-          top: "bottom",
-          textStyle: {
-            color: "#666",
-          },
-        },
-        color: ["#5470C6", "#91CC75", "#EE6666", "#9A60B4"], // 鏂板绱壊鐢ㄤ簬鍙婃椂鐜�
-        xAxis: {
-          type: "category",
-          data: categories,
-          axisLabel: {
-            interval: 0,
-            rotate: 30,
-            color: "#666",
-          },
-          axisLine: {
-            lineStyle: {
-              color: "#ddd",
-            },
-          },
-        },
-        yAxis: [
-          {
-            type: "value",
-            name: "浜烘",
-            min: 0,
-            axisLabel: {
-              color: "#666",
-            },
-            axisLine: {
-              lineStyle: {
-                color: "#ddd",
-              },
-            },
-            splitLine: {
-              lineStyle: {
-                color: "#f0f0f0",
-              },
-            },
-          },
-          {
-            type: "value",
-            name: "鐧惧垎姣�(%)",
-            min: 0,
-            max: 100,
-            axisLabel: {
-              color: "#666",
-              formatter: "{value}%",
-            },
-            axisLine: {
-              lineStyle: {
-                color: "#ddd",
-              },
-            },
-            splitLine: {
-              show: false,
-            },
-          },
-        ],
-        series: [
-          {
-            name: "鍑洪櫌浜烘",
-            type: "bar",
-            barWidth: "25%",
-            data: dischargeData,
-            itemStyle: {
-              borderRadius: [4, 4, 0, 0],
-            },
-          },
-          {
-            name: "搴旈殢璁夸汉娆�",
-            type: "bar",
-            barWidth: "25%",
-            data: followUpData,
-            itemStyle: {
-              borderRadius: [4, 4, 0, 0],
-            },
-          },
-          {
-            name: "闅忚鐜�(%)",
-            type: "line",
-            yAxisIndex: 1,
-            data: followUpRateData,
-            symbolSize: 8,
-            lineStyle: {
-              width: 3,
-            },
-            markLine: {
-              silent: true,
-              data: [
-                {
-                  yAxis: 80,
-                  lineStyle: {
-                    color: "#EE6666",
-                    type: "dashed",
-                  },
-                  // label: {
-                  //   position: 'end',
-                  //   formatter: '鐩爣80%'
-                  // }
-                },
-              ],
-            },
-          },
-          {
-            name: "鍙婃椂鐜�(%)",
-            type: "line",
-            yAxisIndex: 1,
-            data: timelyRateData,
-            symbolSize: 8,
-            lineStyle: {
-              width: 3,
-              type: "dotted", // 浣跨敤铏氱嚎鍖哄垎
-            },
-            markLine: {
-              silent: true,
-              data: [
-                {
-                  yAxis: 90,
-                  lineStyle: {
-                    color: "#9A60B4",
-                    type: "dashed",
-                  },
-                  // label: {
-                  //   position: 'end',
-                  //   formatter: '鐩爣90%'
-                  // }
-                },
-              ],
-            },
-          },
-        ],
-        grid: {
-          top: "15%",
-          left: "3%",
-          right: "4%",
-          bottom: "15%",
-          containLabel: true,
-        },
-      };
-
-      this.barLineChart.setOption(option);
-      window.addEventListener("resize", this.resizeBarLineChart);
-    },
-
-    // 鍥捐〃鍝嶅簲寮忚皟鏁存柟娉�
-    resizePieChart() {
-      if (this.pieChart) {
-        this.pieChart.resize();
-      }
-    },
-
-    resizeBarLineChart() {
-      if (this.barLineChart) {
-        this.barLineChart.resize();
-      }
-    },
-
-    // 鍦ㄧ粍浠堕攢姣佹椂娓呯悊
-    beforeDestroy() {
-      // 绉婚櫎浜嬩欢鐩戝惉
-      window.removeEventListener("resize", this.resizePieChart);
-      window.removeEventListener("resize", this.resizeBarLineChart);
-
-      // 閿�姣佸浘琛ㄥ疄渚�
-      if (this.pieChart) {
-        this.pieChart.dispose();
-        this.pieChart = null;
-      }
-      if (this.barLineChart) {
-        this.barLineChart.dispose();
-        this.barLineChart = null;
-      }
-    },
-  },
-};
+    handleSearch() {
+      // 鎼滅储閫昏緫
+    }
+  }
+}
 </script>
 
 <style lang="scss" scoped>
-.sidecolumn {
-  width: 180px;
-  min-height: 100vh;
-  text-align: center;
-  //   display: flex;
-  margin-top: 20px;
-  margin: 20px;
-  padding: 30px;
-  background: #edf1f7;
-  border: 1px solid #dcdfe6;
-  -webkit-box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12),
-    0 0 6px 0 rgba(0, 0, 0, 0.04);
-  .sidecolumn-top {
-    display: flex;
-    justify-content: space-between;
-    .top-wj {
-      font-size: 20px;
-    }
-    .top-tj {
-      font-size: 18px;
-
-      color: rgb(0, 89, 255);
-      cursor: pointer;
-    }
-  }
-  .center-ss {
-    margin-top: 30px;
-    .input-with-select {
-      height: 40px !important;
-    }
-  }
-  .bottom-fl {
-    margin-top: 30px;
-    display: center !important;
-  }
-}
-.qrcode-dialo {
-  text-align: center;
-  //   display: flex;
-  margin: 20px;
-  padding: 30px;
-  background: #edf1f7;
-  border: 1px solid #dcdfe6;
-  -webkit-box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12),
-    0 0 6px 0 rgba(0, 0, 0, 0.04);
-  .qrcode-text {
-    font-size: 20px;
-    span {
-      margin-left: 20px;
-    }
-  }
-  .qrcode-img {
-    width: 300px;
-    height: 400px;
-  }
-}
-::v-deep.el-tabs--left,
-.el-tabs--right {
-  overflow: hidden;
-  align-items: center;
-  display: flex;
-}
-::v-deep.el-input--medium .el-input__inner {
-  height: 40px !important;
-}
-::v-deep.el-tabs--right .el-tabs__active-bar.is-right {
-  height: 40px;
-  width: 5px;
-  left: 0;
-}
-::v-deep.el-tabs--right .el-tabs__item.is-right {
-  display: block;
-  text-align: left;
-  font-size: 20px;
-}
-// 缇庡寲鍚堣琛屾牱寮�
-::v-deep .el-table__footer {
-  .el-table__cell {
-    background-color: #f5f7fa;
-    font-weight: 600;
-    color: #409eff;
-
-    .cell {
-      font-weight: 600;
-      color: #409eff;
-    }
-  }
-}
-
-// 鍐呴儴琛ㄦ牸鍚堣琛屾牱寮�
-::v-deep .inner-table .el-table__footer {
-  .el-table__cell {
-    background-color: #ecf5ff;
-    font-weight: 500;
-    color: #67c23a;
-
-    .cell {
-      font-weight: 500;
-      color: #67c23a;
-    }
-  }
-}
-
-// 鐧惧垎姣斿瓧娈电壒娈婃牱寮�
-.your-table-container
-  ::v-deep
-  .el-table__footer
-  .el-table__cell[data-field="followUpRate"]
-  .cell,
-.your-table-container
-  ::v-deep
-  .el-table__footer
-  .el-table__cell[data-field="rate"]
-  .cell,
-.your-table-container
-  ::v-deep
-  .el-table__footer
-  .el-table__cell[data-field="followUpRateAgain"]
-  .cell {
-  color: #e6a23c !important;
-  font-weight: 700 !important;
-}
-
-.leftvlue {
-  //   display: flex;
-  //   flex: 1;
-  // width: 80%;
-  // margin-top: 20px;
-  margin: 20px;
-  padding: 30px;
+.follow-up-statistics {
+  padding: 20px;
   background: #ffff;
   border: 1px solid #dcdfe6;
-  -webkit-box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12),
-    0 0 6px 0 rgba(0, 0, 0, 0.04);
-  .mulsz {
-    font-size: 20px;
-  }
-}
-/* 浣胯鏈夋墜鍨嬫寚閽� */
-.el-table__row {
-  cursor: pointer;
-}
-/* 鍐呭眰鍖荤敓琛ㄦ牸鏍峰紡 */
-.inner-table {
-  // 琛ㄥご鑳屾櫙鑹�
-  ::v-deep .el-table__header-wrapper {
-    background-color: #f0f7ff !important;
+  box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12), 0 0 6px 0 rgba(0, 0, 0, 0.04);
 
-    th {
-      background-color: #f0f7ff !important;
+  .search-section {
+    margin-bottom: 20px;
+  }
+
+  .tab-section {
+    ::v-deep .el-tabs__header {
+      margin-bottom: 20px;
+    }
+
+    ::v-deep .el-tabs__item {
+      font-size: 16px;
+      padding: 0 20px;
+      height: 40px;
+      line-height: 40px;
+    }
+
+    ::v-deep .el-tabs__active-bar {
+      height: 3px;
     }
   }
-
-  // 琛ㄦ牸琛岃儗鏅壊
-  ::v-deep .el-table__body-wrapper {
-    tr {
-      background-color: #f9fbfe !important;
-
-      &:hover {
-        background-color: #e6f1ff !important;
-      }
-    }
-  }
-
-  // 杈规棰滆壊
-  ::v-deep .el-table--border {
-    border-color: #d9e8ff !important;
-
-    td,
-    th {
-      border-color: #d9e8ff !important;
-    }
-  }
-
-  // 鏂戦┈绾规晥鏋�
-  ::v-deep .el-table--striped .el-table__body tr.el-table__row--striped td {
-    background-color: #f5f9ff !important;
-  }
-}
-/* 灞曞紑琛屾牱寮� */
-.el-table__expanded-cell {
-  padding: 10px 0 !important;
-  background: #f8f8f8;
-}
-.document {
-  width: 100px;
-  height: 50px;
-}
-.data-list {
-  max-height: 800px;
-  overflow-y: auto;
-}
-.documentf {
-  display: flex;
-  justify-content: flex-end;
-}
-.button-text {
-  color: rgb(70, 204, 238);
-}
-.button-textck {
-  color: rgb(39, 167, 67);
-}
-.button-textxg {
-  color: rgb(35, 81, 233);
-}
-.button-textsc {
-  color: rgb(235, 23, 23);
 }
 </style>
diff --git a/vue.config.js b/vue.config.js
index 2542f56..1ce99d9 100644
--- a/vue.config.js
+++ b/vue.config.js
@@ -37,9 +37,10 @@
       [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://192.168.100.10:8098`,//甯備竴
+        // target:`http://localhost:8095`,
         // target:`http://35z1t16164.qicp.vip`,
         // target: `http://192.168.100.183:8095`,
         // target: `http://192.168.101.166:8093`,
diff --git a/xhyy.zip b/xhyy.zip
deleted file mode 100644
index 98caa1f..0000000
--- a/xhyy.zip
+++ /dev/null
Binary files differ

--
Gitblit v1.9.3