From 9903954c85f651dd5cc6d4b538cfe66b17fc5baa Mon Sep 17 00:00:00 2001
From: liusheng <337615773@qq.com>
Date: 星期三, 28 十月 2026 18:23:45 +0800
Subject: [PATCH] 提交

---
 src/components/PendingTaskBox/index.vue                               |  568 +++++++++++++++++++++
 src/views/Satisfaction/sfstatistics/components/DataOverview.vue       |  164 ++++-
 tmp-svy4/Probe41.java                                                 |   45 +
 骨科中心一病区_出院数据统计_20260430-20261023.xlsx                                 |    0 
 tmp-probe9/Probe42.java                                               |   45 +
 src/api/smartor/pendingTask.js                                        |   32 +
 src/views/Satisfaction/configurationmyd/components/DetailsAnomaly.vue |    4 
 tmp-svy4/probe41.txt                                                  |   28 +
 src/views/Satisfaction/sfstatistics/components/FollowupStatistics.vue |  185 ++++-
 tmp-probe4/Probe17.java                                               |   52 +
 src/views/followvisit/discharge/outpatientService.vue                 |   79 ++
 src/components/StatisticsCards/index.vue                              |   16 
 tmp-probe4/Probe18.class                                              |    0 
 tmp-probe4/probe17.txt                                                |   16 
 src/store/modules/user.js                                             |   21 
 tmp-probe4/Probe18.java                                               |   46 +
 tmp-probe9/probe42.txt                                                |   21 
 src/views/system/user/profile/index.vue                               |   48 +
 tmp-probe4/Probe17.class                                              |    0 
 src/views/Satisfaction/configurationmyd/batch.vue                     |    4 
 tmp-svy4/Probe41.class                                                |    0 
 tmp-probe4/probe18.txt                                                |   13 
 tmp-probe9/Probe42.class                                              |    0 
 src/App.vue                                                           |    3 
 src/views/followvisit/discharge/index.vue                             |  183 ++++++
 25 files changed, 1,447 insertions(+), 126 deletions(-)

diff --git a/src/App.vue b/src/App.vue
index fe7e9a8..0866a4a 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -10,6 +10,8 @@
       :hide-delay="3000"
       primary-color="#1890ff"
     />
+    <!-- 鍙充笅瑙掞細褰撳墠鐧诲綍浜哄緟澶勭悊闅忚浠诲姟锛堟寜鍑洪櫌骞存湀锛� -->
+    <PendingTaskBox v-if="Assvite" />
     <!-- 涓磋繎瓒呮椂浠诲姟鐧诲綍鍚庡脊绐楋紙浠呮櫙瀹�/鏂板崕涓ゅ鏈烘瀯瑙﹀彂锛� -->
     <!-- <NearTimeoutDialog v-if="Assvite" /> -->
   </div>
@@ -23,6 +25,7 @@
   components: {
     ThemePicker,
     Assistant: () => import("./components/Assistant"),
+    PendingTaskBox: () => import("./components/PendingTaskBox"),
     NearTimeoutDialog: () => import("./components/NearTimeoutDialog"),
   },
   data() {
diff --git a/src/api/smartor/pendingTask.js b/src/api/smartor/pendingTask.js
new file mode 100644
index 0000000..d54c40c
--- /dev/null
+++ b/src/api/smartor/pendingTask.js
@@ -0,0 +1,32 @@
+import axios from 'axios'
+import { getToken } from '@/utils/auth'
+
+/**
+ * 褰撳墠鐧诲綍浜哄緟澶勭悊闅忚浠诲姟缁熻锛堟寜鍑洪櫌骞存湀鍒嗙粍锛�
+ *
+ * 鍚庣鍙e緞锛歴ervice_subtask 涓�
+ *   service_type = '2' 鍑洪櫌闅忚 / '3' 闂ㄨ瘖闅忚锛堝垎寮�璁℃暟锛�
+ *   current_preachform = '1'锛堜汉宸ワ級
+ *   寰呴殢璁跨姸鎬侊紙sendstate in 1,2,3,5,7锛�
+ *   鍑洪櫌鏃堕棿 endtime 鏃╀簬绛変簬浠婂ぉ - 7 澶�
+ *   鍙粺璁℃渶杩� 4 涓嚭闄㈡湀浠斤紙鍚綋鏈堬級
+ *
+ * 璇ユ帴鍙g敤浜庡彸涓嬭甯搁┗鍗$墖锛屽睘浜庡悗鍙拌疆璇細
+ * 涓嶈蛋 @/utils/request 鐨勫叏灞�鎷︽埅鍣紝閬垮厤鎺ュ彛鏈儴缃�/缃戠粶寮傚父鏃跺弽澶嶅脊鍏ㄥ眬閿欒鎻愮ず锛�
+ * 澶辫触淇℃伅鐢卞崱鐗囧唴閮ㄨ嚜琛屽睍绀恒��
+ *
+ * @returns {Promise<{userName: string, nickName: string, total: number,
+ *   months: Array<{month: string, dischargeCount: number, outpatientCount: number}>}>}
+ *   months 鍙寘鍚湁鏁版嵁鐨勬湀浠斤紝娌℃暟鎹殑鏈堜唤鐢卞崱鐗囪ˉ 0
+ */
+export function getPendingTaskMonthStats() {
+  return axios({
+    baseURL: process.env.VUE_APP_BASE_API,
+    url: '/smartor/serviceSubtask/pendingTaskMonthStats',
+    method: 'post',
+    timeout: 15000,
+    headers: {
+      Authorization: 'Bearer ' + getToken()
+    }
+  }).then(res => res.data)
+}
diff --git a/src/components/PendingTaskBox/index.vue b/src/components/PendingTaskBox/index.vue
new file mode 100644
index 0000000..fa1bfb9
--- /dev/null
+++ b/src/components/PendingTaskBox/index.vue
@@ -0,0 +1,568 @@
+<template>
+  <div class="ptb-root">
+    <!-- 鏀惰捣鎬侊細鍙充笅瑙掑皬鑳跺泭 -->
+    <button
+      v-if="collapsed"
+      class="ptb-pill"
+      type="button"
+      title="灞曞紑寰呭鐞嗕换鍔�"
+      @click="toggle"
+    >
+      <span class="ptb-pill-dot"></span>
+      <span class="ptb-pill-text">寰呭鐞�</span>
+      <span class="ptb-pill-num">{{ total }}</span>
+    </button>
+
+    <!-- 灞曞紑鎬侊細褰撳墠鐧诲綍浜� + 杩� 4 涓湀鍑洪櫌/闂ㄨ瘖闅忚寰呭鐞� -->
+    <div v-else class="ptb-card">
+      <div class="ptb-header">
+        <div class="ptb-header-left">
+          <svg
+            class="ptb-header-icon"
+            viewBox="0 0 24 24"
+            fill="none"
+            stroke="currentColor"
+            stroke-width="2"
+          >
+            <path d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2" />
+            <path d="M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
+            <path d="M9 14l2 2 4-4" />
+          </svg>
+          <span class="ptb-header-title" title="鍑洪櫌婊� 7 澶┿�佷粛寰呴殢璁跨殑鍑洪櫌/闂ㄨ瘖浠诲姟">
+            寰呭鐞嗛殢璁夸换鍔�
+          </span>
+        </div>
+        <div class="ptb-header-actions">
+          <span
+            class="ptb-icon-btn"
+            :class="{ 'is-loading': loading }"
+            title="鍒锋柊"
+            @click="load"
+          >&#8635;</span>
+          <span class="ptb-icon-btn" title="鏀惰捣" @click="toggle">&#8211;</span>
+        </div>
+      </div>
+
+      <div class="ptb-body">
+        <div class="ptb-user">
+          <div class="ptb-avatar">{{ userInitial }}</div>
+          <div class="ptb-user-meta">
+            <div class="ptb-user-name" :title="displayName">{{ displayName }}</div>
+            <div class="ptb-user-scope" :title="scopeText">{{ scopeText }}</div>
+          </div>
+        </div>
+
+        <div class="ptb-months">
+          <div
+            v-for="row in monthRows"
+            :key="row.key"
+            class="ptb-month-row"
+          >
+            <span class="ptb-month-label">{{ row.label }}</span>
+            <span
+              class="ptb-month-seg is-clickable"
+              title="鐐瑰嚮鏌ョ湅璇ユ湀寰呴殢璁挎偅鑰�"
+              @click="goToTasks(row, 2)"
+            >鍑洪櫌闅忚寰呭鐞�<b class="ptb-num is-discharge">{{ row.dischargeCount }}</b>涓�</span>
+            <span class="ptb-month-comma">锛�</span>
+            <span
+              class="ptb-month-seg is-clickable"
+              title="鐐瑰嚮鏌ョ湅璇ユ湀寰呴殢璁挎偅鑰�"
+              @click="goToTasks(row, 3)"
+            >闂ㄨ瘖闅忚寰呭鐞�<b class="ptb-num is-outpatient">{{ row.outpatientCount }}</b>涓�</span>
+          </div>
+        </div>
+
+        <div v-if="errorMsg" class="ptb-error">{{ errorMsg }}</div>
+      </div>
+
+      <div class="ptb-footer">
+        <span class="ptb-update-time">鏇存柊浜� {{ updateTime || '--:--' }}</span>
+        <span class="ptb-footer-refresh" @click="load">鍒锋柊</span>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { getPendingTaskMonthStats } from '@/api/smartor/pendingTask'
+import { getToken } from '@/utils/auth'
+
+const COLLAPSE_KEY = 'pendingTaskBoxCollapsed'
+const REFRESH_INTERVAL = 5 * 60 * 1000
+// 鍥哄畾灞曠ず锛氬綋鏈� + 寰�鍓� 3 涓湀
+const MONTH_COUNT = 4
+
+export default {
+  name: 'PendingTaskBox',
+  data() {
+    return {
+      collapsed: localStorage.getItem(COLLAPSE_KEY) === '1',
+      loading: false,
+      errorMsg: '',
+      userName: '',
+      nickName: '',
+      total: 0,
+      months: [],
+      updateTime: '',
+      timer: null,
+      retryTimer: null,
+      retryCount: 0,
+      lastLoadAt: 0
+    }
+  },
+  computed: {
+    displayName() {
+      return (
+        this.nickName ||
+        this.$store.getters.nickName ||
+        this.userName ||
+        this.$store.getters.name ||
+        '鏈櫥褰�'
+      )
+    },
+    userInitial() {
+      const name = this.displayName
+      return name ? name.slice(0, 1) : '-'
+    },
+    scopeText() {
+      const depts = (this.$store.getters.belongDepts || [])
+        .map(item => item.deptName)
+        .filter(Boolean)
+      const wards = (this.$store.getters.belongWards || [])
+        .map(item => item.districtName)
+        .filter(Boolean)
+      const scope = wards.length ? wards : depts
+      if (!scope.length) {
+        return '褰撳墠鐧诲綍浜�'
+      }
+      return scope.length > 2 ? scope.slice(0, 2).join('銆�') + ' 绛�' : scope.join('銆�')
+    },
+    monthMap() {
+      const map = {}
+      this.months.forEach(item => {
+        if (item && item.month) {
+          map[item.month] = {
+            dischargeCount: Number(item.dischargeCount) || 0,
+            outpatientCount: Number(item.outpatientCount) || 0
+          }
+        }
+      })
+      return map
+    },
+    // 褰撴湀 + 鍓� 3 涓湀锛屾病鏈夋暟鎹殑鏈堜唤琛� 0
+    monthRows() {
+      const rows = []
+      const now = new Date()
+      for (let i = 0; i < MONTH_COUNT; i++) {
+        const date = new Date(now.getFullYear(), now.getMonth() - i, 1)
+        const month = String(date.getMonth() + 1).padStart(2, '0')
+        const key = date.getFullYear() + '-' + month
+        const data = this.monthMap[key] || { dischargeCount: 0, outpatientCount: 0 }
+        rows.push({
+          key,
+          label: date.getFullYear() + '骞�' + month + '鏈�',
+          dischargeCount: data.dischargeCount,
+          outpatientCount: data.outpatientCount
+        })
+      }
+      return rows
+    }
+  },
+  mounted() {
+    this.load()
+    this.timer = setInterval(() => this.load(), REFRESH_INTERVAL)
+    document.addEventListener('visibilitychange', this.handleVisible)
+  },
+  beforeDestroy() {
+    clearInterval(this.timer)
+    this.clearRetry()
+    document.removeEventListener('visibilitychange', this.handleVisible)
+  },
+  methods: {
+    toggle() {
+      this.collapsed = !this.collapsed
+      localStorage.setItem(COLLAPSE_KEY, this.collapsed ? '1' : '0')
+      if (!this.collapsed && Date.now() - this.lastLoadAt > 60 * 1000) {
+        this.load()
+      }
+    },
+    handleVisible() {
+      if (document.visibilityState === 'visible' && Date.now() - this.lastLoadAt > 60 * 1000) {
+        this.load()
+      }
+    },
+    async load() {
+      if (this.loading) {
+        return
+      }
+      if (!getToken()) {
+        // 鍒氬埛鏂伴〉闈㈡椂鐧诲綍鎬佸彲鑳借繕娌″氨缁紝绋嶅悗閲嶈瘯
+        this.scheduleRetry(4000)
+        return
+      }
+      this.loading = true
+      try {
+        const res = await getPendingTaskMonthStats()
+        const payload = res && res.data && res.data.months ? res.data : res || {}
+        this.nickName = payload.nickName || this.nickName
+        this.userName = payload.userName || this.userName
+        this.months = Array.isArray(payload.months) ? payload.months : []
+        const sum = this.months.reduce((acc, item) => {
+          return acc + (Number(item.dischargeCount) || 0) + (Number(item.outpatientCount) || 0)
+        }, 0)
+        this.total = Number(payload.total) || sum
+        this.errorMsg = ''
+        this.updateTime = this.formatTime(new Date())
+        this.retryCount = 0
+        this.clearRetry()
+      } catch (error) {
+        // 鍚庣閲嶅惎/缃戠粶鎶栧姩鏃惰嚜鍔ㄩ噸璇曪紝涓嶇敤绛� 5 鍒嗛挓
+        this.errorMsg = '缁熻鎺ュ彛鏆備笉鍙敤锛岀◢鍚庤嚜鍔ㄩ噸璇�'
+        this.scheduleRetry(20000)
+      } finally {
+        this.lastLoadAt = Date.now()
+        this.loading = false
+      }
+    },
+    scheduleRetry(delay) {
+      if (this.retryCount >= 5) {
+        return
+      }
+      this.retryCount += 1
+      this.clearRetry()
+      this.retryTimer = setTimeout(() => this.load(), delay)
+    },
+    clearRetry() {
+      if (this.retryTimer) {
+        clearTimeout(this.retryTimer)
+        this.retryTimer = null
+      }
+    },
+    formatTime(date) {
+      const pad = value => String(value).padStart(2, '0')
+      return pad(date.getHours()) + ':' + pad(date.getMinutes())
+    },
+    // 鐐瑰嚮鏌愪釜鏈堢殑鏁板瓧锛岃烦鍒伴殢璁垮垪琛ㄦ煡鐪嬪搴旂殑寰呴殢璁挎偅鑰�
+    goToTasks(row, serviceType) {
+      const path =
+        serviceType === 3 ? '/followvisit/outpatientService' : '/followvisit/discharge'
+      this.$router
+        .push({
+          path,
+          query: {
+            month: row.key,
+            serviceType: String(serviceType),
+            fromPendingTask: '1',
+            _t: String(Date.now())
+          }
+        })
+        .catch(() => {})
+    }
+  }
+}
+</script>
+
+<style scoped>
+.ptb-root {
+  position: fixed;
+  right: 24px;
+  bottom: 24px;
+  z-index: 1998;
+  color: #1f2d3d;
+  font-size: 13px;
+  line-height: 1.4;
+}
+
+/* 鏀惰捣鎬� */
+.ptb-pill {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+  height: 42px;
+  padding: 0 16px 0 14px;
+  border: none;
+  border-radius: 21px;
+  background: linear-gradient(135deg, #1890ff 0%, #4f8cff 100%);
+  color: #fff;
+  font-size: 13px;
+  cursor: pointer;
+  outline: none;
+  box-shadow: 0 8px 20px rgba(24, 144, 255, 0.35);
+  transition: transform 0.2s ease, box-shadow 0.2s ease;
+}
+
+.ptb-pill:hover {
+  transform: translateY(-2px);
+  box-shadow: 0 12px 24px rgba(24, 144, 255, 0.42);
+}
+
+.ptb-pill-dot {
+  width: 8px;
+  height: 8px;
+  border-radius: 50%;
+  background: #fff;
+  box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.22);
+}
+
+.ptb-pill-num {
+  display: inline-flex;
+  align-items: center;
+  justify-content: center;
+  min-width: 24px;
+  height: 22px;
+  padding: 0 7px;
+  border-radius: 11px;
+  background: rgba(255, 255, 255, 0.94);
+  color: #1890ff;
+  font-weight: 600;
+}
+
+/* 灞曞紑鎬� */
+.ptb-card {
+  width: 364px;
+  max-width: calc(100vw - 24px);
+  background: #fff;
+  border: 1px solid rgba(24, 144, 255, 0.12);
+  border-radius: 14px;
+  box-shadow: 0 12px 32px rgba(15, 23, 42, 0.14), 0 2px 6px rgba(15, 23, 42, 0.06);
+  overflow: hidden;
+  animation: ptb-fade-in 0.18s ease-out;
+}
+
+@keyframes ptb-fade-in {
+  from {
+    opacity: 0;
+    transform: translateY(8px);
+  }
+  to {
+    opacity: 1;
+    transform: translateY(0);
+  }
+}
+
+.ptb-header {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 11px 12px 11px 14px;
+  background: linear-gradient(135deg, #1890ff 0%, #4f8cff 100%);
+  color: #fff;
+}
+
+.ptb-header-left {
+  display: flex;
+  align-items: center;
+  gap: 7px;
+  min-width: 0;
+}
+
+.ptb-header-icon {
+  width: 16px;
+  height: 16px;
+  flex: none;
+}
+
+.ptb-header-title {
+  font-size: 13px;
+  font-weight: 600;
+  letter-spacing: 0.3px;
+  white-space: nowrap;
+}
+
+.ptb-header-actions {
+  display: flex;
+  align-items: center;
+  gap: 2px;
+}
+
+.ptb-icon-btn {
+  display: inline-flex;
+  align-items: center;
+  justify-content: center;
+  width: 22px;
+  height: 22px;
+  border-radius: 6px;
+  font-size: 15px;
+  line-height: 1;
+  cursor: pointer;
+  opacity: 0.85;
+  transition: background-color 0.15s ease, opacity 0.15s ease;
+}
+
+.ptb-icon-btn:hover {
+  background: rgba(255, 255, 255, 0.2);
+  opacity: 1;
+}
+
+.ptb-icon-btn.is-loading {
+  animation: ptb-spin 0.9s linear infinite;
+}
+
+@keyframes ptb-spin {
+  to {
+    transform: rotate(360deg);
+  }
+}
+
+.ptb-body {
+  padding: 12px 14px 8px;
+}
+
+.ptb-user {
+  display: flex;
+  align-items: center;
+  gap: 9px;
+  padding-bottom: 10px;
+  border-bottom: 1px solid #f2f4f8;
+}
+
+.ptb-avatar {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: 32px;
+  height: 32px;
+  flex: none;
+  border-radius: 50%;
+  background: linear-gradient(135deg, #e6f4ff 0%, #bae0ff 100%);
+  color: #1890ff;
+  font-size: 14px;
+  font-weight: 600;
+}
+
+.ptb-user-meta {
+  min-width: 0;
+  flex: 1;
+}
+
+.ptb-user-name {
+  overflow: hidden;
+  color: #1f2d3d;
+  font-size: 14px;
+  font-weight: 600;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.ptb-user-scope {
+  overflow: hidden;
+  color: #8c98a8;
+  font-size: 11px;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+/* 4 琛岋細2026骞�10鏈堝嚭闄㈤殢璁垮緟澶勭悊109涓紝闂ㄨ瘖闅忚寰呭鐞�109涓� */
+.ptb-months {
+  margin-top: 4px;
+}
+
+.ptb-month-row {
+  display: flex;
+  align-items: center;
+  padding: 6px 6px;
+  margin: 0 -6px;
+  border-radius: 6px;
+  font-size: 12px;
+  line-height: 1.5;
+  white-space: nowrap;
+  transition: background-color 0.15s ease;
+}
+
+.ptb-month-row:hover {
+  background: #f5faff;
+}
+
+.ptb-month-label {
+  color: #3f4d5f;
+  font-weight: 600;
+  font-variant-numeric: tabular-nums;
+}
+
+.ptb-month-seg {
+  color: #5a6b80;
+}
+
+/* 鏁板瓧鍙偣鍑昏烦杞埌闅忚鍒楄〃 */
+.ptb-month-seg.is-clickable {
+  cursor: pointer;
+  transition: color 0.15s ease;
+}
+
+.ptb-month-seg.is-clickable:hover {
+  color: #1890ff;
+}
+
+.ptb-month-seg.is-clickable:hover .ptb-num {
+  text-decoration: underline;
+}
+
+.ptb-month-comma {
+  color: #b6c0cc;
+}
+
+.ptb-num {
+  margin: 0 2px;
+  font-size: 13px;
+  font-weight: 700;
+  font-variant-numeric: tabular-nums;
+}
+
+.ptb-num.is-discharge {
+  color: #1890ff;
+}
+
+.ptb-num.is-outpatient {
+  color: #13a8a8;
+}
+
+.ptb-error {
+  margin-top: 8px;
+  padding: 5px 8px;
+  border-radius: 6px;
+  background: #fff7e6;
+  color: #d46b08;
+  font-size: 11px;
+}
+
+.ptb-footer {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 7px 14px;
+  border-top: 1px solid #f2f4f8;
+  background: #fafcff;
+}
+
+.ptb-update-time {
+  color: #a3adba;
+  font-size: 11px;
+}
+
+.ptb-footer-refresh {
+  color: #1890ff;
+  font-size: 11px;
+  cursor: pointer;
+}
+
+.ptb-footer-refresh:hover {
+  text-decoration: underline;
+}
+
+@media (max-width: 768px) {
+  .ptb-root {
+    right: 12px;
+    bottom: 12px;
+  }
+
+  .ptb-card {
+    width: calc(100vw - 24px);
+  }
+
+  .ptb-month-row {
+    white-space: normal;
+    flex-wrap: wrap;
+  }
+}
+</style>
diff --git a/src/components/StatisticsCards/index.vue b/src/components/StatisticsCards/index.vue
index 1b45c11..3f072b2 100644
--- a/src/components/StatisticsCards/index.vue
+++ b/src/components/StatisticsCards/index.vue
@@ -17,10 +17,14 @@
         >
           <el-card
             shadow="hover"
-            :body-style="item.router ? 'cursor: pointer' : 'cursor: default'"
+            :body-style="isClickable(item) ? 'cursor: pointer' : 'cursor: default'"
             :class="getCardClass(item.name)"
+            @click.native="handleCardClick(item)"
           >
-            <div class="card-content" @click="handleCardClick(item)">
+            <div
+              class="card-content"
+              :style="{ cursor: isClickable(item) ? 'pointer' : 'default' }"
+            >
               <div class="card-label">
                 <span class="label-text">{{ item.name }}</span>
               </div>
@@ -64,6 +68,11 @@
       default: 0,
     },
     showWarningCondition: {
+      type: Boolean,
+      default: false,
+    },
+    // 鏄惁鍏佽鐐瑰嚮鍗$墖锛堢偣鍑诲悗鐢辩埗缁勪欢鍐冲畾濡備綍绛涢�変笅闈㈢殑鍒楄〃锛�
+    clickable: {
       type: Boolean,
       default: false,
     },
@@ -135,6 +144,9 @@
       return tooltips[name] || "";
     },
 
+    isClickable(item) {
+      return !!(item && item.router) || this.clickable;
+    },
     handleCardClick(item) {
       if (item.router) {
         this.$router.push(item.router);
diff --git a/src/store/modules/user.js b/src/store/modules/user.js
index d98a63f..cb10ea4 100644
--- a/src/store/modules/user.js
+++ b/src/store/modules/user.js
@@ -2,6 +2,23 @@
 import { getConfig, getConfigKey, listConfig } from "@/api/system/config";
 import { getToken, setToken, removeToken } from "@/utils/auth";
 
+/**
+ * sys_user_dept 閲屽悓涓�绉戝/鐥呭尯鍙兘瀛樺湪澶ч噺閲嶅琛岋紙HIS 鍚屾/閲嶅淇濆瓨瀵艰嚧锛夛紝
+ * 鎺ュ彛浼氬師鏍疯繑鍥烇紝杩欓噷鎸夌紪鐮佸幓閲嶏紝閬垮厤涓汉涓績銆佸緟澶勭悊鍗$墖绛夊閲嶅灞曠ず
+ */
+function uniqueByCode(list) {
+  const seen = {};
+  return (list || []).filter((item) => {
+    if (!item) return false;
+    const code =
+      item.districtCode || item.deptCode || item.districtId || item.deptId;
+    const key = String(code === undefined || code === null ? "" : code);
+    if (!key || seen[key]) return false;
+    seen[key] = true;
+    return true;
+  });
+}
+
 const user = {
   state: {
     token: getToken(),
@@ -294,8 +311,8 @@
             commit("SET_Id", user.userId);
             commit("SET_hisUserId", user.hisUserId);
             commit("SET_satisfactionCategories", user.satisfactionCategories);
-            commit("SET_leavehospitaldistrictcodes", user.belongWards);
-            commit("SET_leaveldeptcodes", user.belongDepts);
+            commit("SET_leavehospitaldistrictcodes", uniqueByCode(user.belongWards));
+            commit("SET_leaveldeptcodes", uniqueByCode(user.belongDepts));
             commit("SET_AVATAR", avatar);
             // 姝g‘璋冪敤鏂瑰紡锛氶�氳繃 dispatch
             dispatch("GetConfig")
diff --git a/src/views/Satisfaction/configurationmyd/batch.vue b/src/views/Satisfaction/configurationmyd/batch.vue
index 6d85fff..a865b59 100644
--- a/src/views/Satisfaction/configurationmyd/batch.vue
+++ b/src/views/Satisfaction/configurationmyd/batch.vue
@@ -126,8 +126,8 @@
                 <div class="answer-text">
                   <strong>鍥炵瓟锛�</strong>{{ row.asrtext || "鏃犲洖绛�" }}
                 </div>
-                <div class="matched-text" v-if="row.matchedtext">
-                  <strong>瑙f瀽鍊硷細</strong>{{ row.matchedtext }}
+                <div class="matched-text">
+                  <strong>澶囨敞锛�</strong>{{ row.answerps || "" }}
                 </div>
               </div>
             </template>
diff --git a/src/views/Satisfaction/configurationmyd/components/DetailsAnomaly.vue b/src/views/Satisfaction/configurationmyd/components/DetailsAnomaly.vue
index 436d46e..75dcba7 100644
--- a/src/views/Satisfaction/configurationmyd/components/DetailsAnomaly.vue
+++ b/src/views/Satisfaction/configurationmyd/components/DetailsAnomaly.vue
@@ -25,8 +25,8 @@
         </el-col>
         <el-col :span="8">
           <div class="info-item">
-            <span class="label">瑙f瀽鍊硷細</span>
-            <span class="value">{{ currentRecord.matchedtext || '鏃�' }}</span>
+            <span class="label">澶囨敞锛�</span>
+            <span class="value">{{ currentRecord.answerps || '鏃�' }}</span>
           </div>
         </el-col>
         <el-col :span="8">
diff --git a/src/views/Satisfaction/sfstatistics/components/DataOverview.vue b/src/views/Satisfaction/sfstatistics/components/DataOverview.vue
index f189c1f..4539a87 100644
--- a/src/views/Satisfaction/sfstatistics/components/DataOverview.vue
+++ b/src/views/Satisfaction/sfstatistics/components/DataOverview.vue
@@ -114,6 +114,7 @@
     <el-card shadow="never" class="overview-card">
       <div slot="header" class="card-header">
         <span class="card-title">鍚勬湇鍔¢」鐩弧鎰忓害缁熻</span>
+        <span class="card-subtitle">锛堝叚妗h瘎鍒嗛锛氬緢婊℃剰/婊℃剰/涓�鑸�/涓嶆弧鎰�/寰堜笉婊℃剰/鏈粡鍘嗭級</span>
         <el-button
           type="warning"
           size="small"
@@ -174,7 +175,8 @@
     <!-- 琛ㄦ牸浜岋細鍗曢�夐/澶氶�夐缁熻锛堝叾浣欓鐩級 -->
     <el-card shadow="never" class="overview-card">
       <div slot="header" class="card-header">
-        <span class="card-title">鍗曢�夐/澶氶�夐缁熻</span>
+        <span class="card-title">鍏朵粬棰樼洰缁熻</span>
+        <span class="card-subtitle">锛堝叚妗f弧鎰忓害棰樺凡鍦ㄤ笂琛紝杩欓噷鍙垪鍏朵綑棰樺瀷锛氭帹鑽愩�佹姳鎬ㄥ洖搴斻�佹剰瑙佺瓑锛�</span>
         <div class="header-right">
           <el-input
             v-model="questionSearch"
@@ -333,6 +335,7 @@
 
 <script>
 import { sltdMydTotalByScore,statQuestionOptionByKsOrBq } from "@/api/AiCentre/satisfaction";
+import { deptTreeSelect } from "@/api/system/user";
 import XLSX from "xlsx";
 
 // 婊℃剰搴﹂鐨勫浐瀹氶�夐」锛堥『搴忓嵆琛ㄦ牸鍒楅『搴忥級鈥斺�旇繖浜涢�夐」鐨勯鐩繘琛ㄤ竴锛屽叾浣欒繘琛ㄤ簩
@@ -360,9 +363,10 @@
 // 鏈嶅姟绫诲瀷榛樿閫変腑椤癸紙鎸� label 鍖归厤锛岄�傞厤涓嶅悓瀛楀吀鐨� value 宸紓锛�
 const DEFAULT_SERVICE_LABELS = ["浣忛櫌婊℃剰搴�", "闂ㄨ瘖婊℃剰搴�"];
 
-// 鍏滃簳锛歴tore 涓棤绉戝/鐥呭尯鏁版嵁鏃朵娇鐢紙琛ㄤ笁瀵规瘮 + 绛涢�変笅鎷夛級
-const DEPTS = ["鍐呭垎娉岀", "鐨偆绉�", "鑲跨槫鍐呯", "娑堝寲鍐呯", "鑲惧唴绉�"];
-const WARDS = ["涓�鐥呭尯", "浜岀梾鍖�", "涓夌梾鍖�", "鍥涚梾鍖�", "浜旂梾鍖�"];
+// 娉ㄦ剰锛氳繖閲屼互鍓嶇敤 DEPTS / WARDS 涓や釜銆屾紨绀虹敤銆嶅悕绉版暟缁勫厹搴曪紝
+// 缁撴灉琚綋鎴愮紪鐮佸杩� leavehospitaldistrictcodes / leaveldeptcodes锛�
+// 鍚庣鎸� leavehospitaldistrictcode IN ('涓�鐥呭尯','浜岀梾鍖�'鈥�) 杩囨护 鈫� 涓�鏉′篃鍖归厤涓嶄笂銆�
+// 绉戝/鐥呭尯涓�寰嬪彧鐢ㄧ湡瀹炵紪鐮侊細鏈夊綊灞炲彇 store锛屾棤褰掑睘锛堝绠$悊鍛橈級鍙� deptTreeSelect 瀛楀吀銆�
 
 /**
  * 鎺ュ彛鏁版嵁 鈫� 椤甸潰鍐呴儴棰樼洰缁撴瀯
@@ -537,22 +541,27 @@
       // 琛ㄤ笁锛氱瀹�/鐥呭尯璇勫垎瀵规瘮锛坮ows=琛屾暟鎹紝questions=鍔ㄦ�佸垪锛�
       deptComparison: { rows: [], questions: [] },
       wardComparison: { rows: [], questions: [] },
+
+      // 绉戝/鐥呭尯瀛楀吀锛氬綋鍓嶈处鍙锋病鏈夊綊灞炵瀹�/鐥呭尯鏃讹紙濡傜鐞嗗憳锛変粠 deptTreeSelect 鎷夊彇锛�
+      // 淇濊瘉涓嬫媺閲屾斁鐨勬槸鐪熷疄缂栫爜锛坉eptCode / districtCode锛夛紝鑰屼笉鏄悕绉�
+      deptDict: [],
+      wardDict: [],
     };
   },
   computed: {
-    // 绉戝閫夐」锛氫紭鍏堝彇褰撳墠鐢ㄦ埛鎵�灞炵瀹わ紝鏃犲垯鍏滃簳
+    // 绉戝閫夐」锛氫紭鍏堝彇褰撳墠鐢ㄦ埛鎵�灞炵瀹わ紱娌℃湁褰掑睘鏃剁敤绉戝瀛楀吀锛堢湡瀹� deptCode锛�
     deptOptions() {
-      const list = this.$store.getters.belongDepts || [];
-      return list.length
-        ? list.map((d) => ({ label: d.deptName, value: d.deptCode }))
-        : DEPTS.map((d) => ({ label: d, value: d }));
+      const list = (this.$store.getters.belongDepts || [])
+        .map((d) => ({ label: d.deptName, value: d.deptCode }))
+        .filter((d) => d.label && d.value);
+      return list.length ? list : this.deptDict;
     },
-    // 鐥呭尯閫夐」锛氫紭鍏堝彇褰撳墠鐢ㄦ埛鎵�灞炵梾鍖猴紝鏃犲垯鍏滃簳
+    // 鐥呭尯閫夐」锛氫紭鍏堝彇褰撳墠鐢ㄦ埛鎵�灞炵梾鍖猴紱娌℃湁褰掑睘鏃剁敤鐥呭尯瀛楀吀锛堢湡瀹� districtCode锛�
     wardOptions() {
-      const list = this.$store.getters.belongWards || [];
-      return list.length
-        ? list.map((w) => ({ label: w.districtName, value: w.districtCode }))
-        : WARDS.map((w) => ({ label: w, value: w }));
+      const list = (this.$store.getters.belongWards || [])
+        .map((w) => ({ label: w.districtName, value: w.districtCode }))
+        .filter((w) => w.label && w.value);
+      return list.length ? list : this.wardDict;
     },
     // 鏈嶅姟绫诲瀷涓嬫媺锛氬彇 store 鐨勯殢璁跨被鍨嬪瓧鍏� tasktypes锛屽彇涓嶅埌鏃跺厹搴曟湰鍦� SERVICE_TYPES
     serviceTypeOptions() {
@@ -566,18 +575,22 @@
       const taskTypes = toOptions(this.$store.getters.tasktypes);
       return taskTypes.length ? taskTypes : SERVICE_TYPES;
     },
-    // 鏈�夌梾鍖烘椂鐨勯粯璁ゆ煡璇㈣寖鍥达細鍏ㄩ儴鐥呭尯缂栫爜
+    // 鏈�夌梾鍖烘椂鐨勯粯璁ゆ煡璇㈣寖鍥达細鍏ㄩ儴鐥呭尯缂栫爜锛堢┖鏁扮粍 = 涓嶉檺锛屽悗绔笉鎷艰繃婊ゆ潯浠讹級
     defaultWardCodes() {
-      return Array.from(new Set(this.wardOptions.map((w) => w.value)));
+      return Array.from(
+        new Set(this.wardOptions.map((w) => w.value).filter(Boolean))
+      );
     },
     // 鏄惁鎸夈�屽湪闄㈡弧鎰忓害銆嶅彛寰勬煡璇細鍦ㄩ櫌婊℃剰搴︾敤 deptcodes/hospitaldistrictcodes锛�
     // 绂婚櫌婊℃剰搴︼紙浠ュ強娓呯┖涓嬫媺鏃剁殑榛樿鍙e緞锛夌敤 leaveldeptcodes/leavehospitaldistrictcodes
     isInHospitalSatisfaction() {
       return this.satisfactionScope === "hospital";
     },
-    // 鏈�夌瀹ゆ椂鐨勯粯璁ゆ煡璇㈣寖鍥达細鍏ㄩ儴绉戝缂栫爜
+    // 鏈�夌瀹ゆ椂鐨勯粯璁ゆ煡璇㈣寖鍥达細鍏ㄩ儴绉戝缂栫爜锛堢┖鏁扮粍 = 涓嶉檺锛�
     defaultDeptCodes() {
-      return Array.from(new Set(this.deptOptions.map((d) => d.value)));
+      return Array.from(
+        new Set(this.deptOptions.map((d) => d.value).filter(Boolean))
+      );
     },
     // 鍥哄畾鍏」閫夐」鐨勯鐩� => 琛ㄤ竴
     satisfactionQuestions() {
@@ -714,7 +727,9 @@
     }
     this.queryParams.serviceTypeList = this.defaultServiceTypes();
   },
-  mounted() {
+  async mounted() {
+    // 鍏堟妸绉戝/鐥呭尯瀛楀吀琛ラ綈锛屼繚璇侀娆℃煡璇㈢敤鐨勫氨鏄湡瀹炵紪鐮�
+    await this.ensureOrgDict();
     this.fetchData();
   },
   methods: {
@@ -725,6 +740,52 @@
         return item ? item.value : null;
       }).filter((v) => v != null);
       return Array.from(new Set(hit));
+    },
+    // 褰掍竴鍖栫瀹�/鐥呭尯缂栫爜锛氶�変腑椤逛紭鍏堬紝鍏舵榛樿鍏ㄩ儴锛涘幓閲嶃�佸幓绌�
+    // 杩斿洖绌烘暟缁勮〃绀恒�屼笉闄愩�嶏紙鍚庣 mapper 鐢� size() > 0 鍒ゆ柇锛岀┖闆嗗悎涓嶆嫾杩囨护鏉′欢锛�
+    codeList(selected, fallback) {
+      const list = (selected && selected.length ? selected : fallback) || [];
+      return Array.from(
+        new Set(
+          list.filter((v) => v !== null && v !== undefined && String(v).trim() !== "")
+        )
+      );
+    },
+    // 琛ュ叏绉戝/鐥呭尯瀛楀吀锛氫粎褰� store 閲屾病鏈夊綊灞炴暟鎹椂锛堝吀鍨嬫槸绠$悊鍛樿处鍙凤級鎵嶈姹�
+    async ensureOrgDict() {
+      const tasks = [];
+      if (!(this.$store.getters.belongDepts || []).length) {
+        tasks.push(this.loadOrgDict(1));
+      }
+      if (!(this.$store.getters.belongWards || []).length) {
+        tasks.push(this.loadOrgDict(2));
+      }
+      if (tasks.length) await Promise.all(tasks);
+    },
+    // deptType锛�1=绉戝锛�2=鐥呭尯锛涚粨鏋滄棦浣滀笅鎷夐�夐」锛屼篃浣溿�屽叏閮ㄣ�嶆椂鐨勭紪鐮佹潵婧�
+    async loadOrgDict(deptType) {
+      let flat = [];
+      try {
+        const res = await deptTreeSelect(deptType);
+        const walk = (nodes) => {
+          (Array.isArray(nodes) ? nodes : []).forEach((n) => {
+            // deptTreeSelect 杩斿洖 TreeSelect锛歿 id, label, deptCode, children }
+            // 鍙 deptCode锛岀己澶卞氨璺宠繃鈥斺�旂敤 deptId 鍐掑厖缂栫爜鍚屾牱鏌ヤ笉鍒版暟鎹�
+            if (n.label && n.deptCode) {
+              flat.push({ label: n.label, value: String(n.deptCode) });
+            }
+            if (n.children && n.children.length) walk(n.children);
+          });
+        };
+        walk(res && res.data);
+      } catch (e) {
+        console.warn("[DataOverview] 鑾峰彇绉戝/鐥呭尯瀛楀吀澶辫触锛屽皢鎸夆�滃叏閮ㄢ�濇煡璇�", e);
+      }
+      if (deptType === 1) {
+        this.deptDict = flat;
+      } else {
+        this.wardDict = flat;
+      }
     },
     // 琛ㄤ笁鐙珛鏉′欢锛�'inherit' 鏃舵部鐢ㄩ《閮ㄦ墍閫夛紱杩斿洖閫変腑鐨勫悕绉版暟缁勶紙鎺ュ彛鍙洖鍚嶇О锛夛紝绌烘暟缁勮〃绀轰笉闄�
     statFilterNames() {
@@ -862,22 +923,26 @@
         endFinishTime: range[1],
       };
       if (this.queryParams.statMode === "dept") {
-        const deptCodes = depts.length
-          ? Array.from(new Set(depts))
-          : this.defaultDeptCodes;
-        if (this.isInHospitalSatisfaction) {
-          payload.deptcodes = deptCodes;
-        } else {
-          payload.leaveldeptcodes = deptCodes;
+        const deptCodes = this.codeList(depts, this.defaultDeptCodes);
+        // 鏈夌紪鐮佹墠浼狅紱绌烘暟缁勭瓑浠蜂簬銆屽叏閮ㄣ�嶏紙鍚庣 mapper 瀵圭┖闆嗗悎涓嶆嫾鏉′欢锛�
+        if (deptCodes.length) {
+          if (this.isInHospitalSatisfaction) {
+            payload.deptcodes = deptCodes;
+          } else {
+            payload.leaveldeptcodes = deptCodes;
+          }
         }
       } else {
-        const wardCodes = wards.length
-          ? Array.from(new Set(wards))
-          : this.defaultWardCodes;
-        if (this.isInHospitalSatisfaction) {
-          payload.hospitaldistrictcodes = wardCodes;
-        } else {
-          payload.leavehospitaldistrictcodes = wardCodes;
+        // 鍙紶銆岀敤鎴风湡姝i�変腑鐨勭梾鍖恒�嶏細娌¢�夛紙= 鍏ㄩ儴鐥呭尯锛夊氨涓嶄紶锛屽悗绔寜涓嶉檺澶勭悊銆�
+        // 闂ㄨ瘖婊℃剰搴︾瓑浠诲姟鐨� leavehospitaldistrictcode 涓虹┖锛�
+        // 鍘熸潵鎶娿�屽叏閮ㄧ梾鍖虹紪鐮併�嶄紶涓嬪幓浼氳杩欎簺浠诲姟琚� IN 鏉′欢鏁存杩囨护鎺夛紙25 棰樺彧鍓� 10 棰橈級銆�
+        const wardCodes = this.codeList(wards, []);
+        if (wardCodes.length) {
+          if (this.isInHospitalSatisfaction) {
+            payload.hospitaldistrictcodes = wardCodes;
+          } else {
+            payload.leavehospitaldistrictcodes = wardCodes;
+          }
         }
       }
       // 鏈嶅姟绫诲瀷澶氶�夛細閫楀彿鍒嗛殧锛堟帴鍙e瓧娈典负 serviceType 瀛楃涓诧級
@@ -927,12 +992,25 @@
       try {
         // 鎸夌瀹ょ粺璁°�佹寜鐥呭尯缁熻鍚勬煡涓�娆★紝鏉′欢闅忋�屾弧鎰忓害绫诲瀷銆嶅垏鎹細
         // 鍦ㄩ櫌婊℃剰搴� => deptcodes / hospitaldistrictcodes锛涚闄㈡弧鎰忓害 => leaveldeptcodes / leavehospitaldistrictcodes
-        const deptParam = this.isInHospitalSatisfaction
-          ? { deptcodes: this.defaultDeptCodes }
-          : { leaveldeptcodes: this.defaultDeptCodes };
-        const wardParam = this.isInHospitalSatisfaction
-          ? { hospitaldistrictcodes: this.defaultWardCodes }
-          : { leavehospitaldistrictcodes: this.defaultWardCodes };
+        // 娌℃湁鐪熷疄缂栫爜鏃朵笉浼犺瀛楁锛�= 鍏ㄩ儴锛夛紝缁濅笉鎶婂悕绉板綋缂栫爜浼�
+        const deptParam = {};
+        const deptCodes = this.codeList([], this.defaultDeptCodes);
+        if (deptCodes.length) {
+          if (this.isInHospitalSatisfaction) {
+            deptParam.deptcodes = deptCodes;
+          } else {
+            deptParam.leaveldeptcodes = deptCodes;
+          }
+        }
+        const wardParam = {};
+        const wardCodes = this.codeList([], this.defaultWardCodes);
+        if (wardCodes.length) {
+          if (this.isInHospitalSatisfaction) {
+            wardParam.hospitaldistrictcodes = wardCodes;
+          } else {
+            wardParam.leavehospitaldistrictcodes = wardCodes;
+          }
+        }
         const [deptRes, wardRes] = await Promise.all([
           statQuestionOptionByKsOrBq({ ...base, ...deptParam }),
           statQuestionOptionByKsOrBq({ ...base, ...wardParam }),
@@ -1053,7 +1131,7 @@
     exportTable(tableId) {
       const tableNames = {
         table1: "鍚勬湇鍔¢」鐩弧鎰忓害缁熻",
-        table2: "鍗曢�夐澶氶�夐缁熻",
+        table2: "鍏朵粬棰樼洰缁熻",
         table3: "鍚勭瀹ゆ弧鎰忓害璇勫垎瀵规瘮",
       };
       const name = tableNames[tableId] || "缁熻鏁版嵁";
@@ -1137,6 +1215,12 @@
   font-weight: 600;
   color: #303133;
 }
+.card-subtitle {
+  margin-left: 6px;
+  font-size: 12px;
+  font-weight: 400;
+  color: #909399;
+}
 .header-right {
   display: flex;
   align-items: center;
diff --git a/src/views/Satisfaction/sfstatistics/components/FollowupStatistics.vue b/src/views/Satisfaction/sfstatistics/components/FollowupStatistics.vue
index e5eb304..754e244 100644
--- a/src/views/Satisfaction/sfstatistics/components/FollowupStatistics.vue
+++ b/src/views/Satisfaction/sfstatistics/components/FollowupStatistics.vue
@@ -12,7 +12,7 @@
         <el-form-item label="婊℃剰搴︾被鍨�" prop="satisfactionScope">
           <el-select
             v-model="satisfactionScope"
-            placeholder="榛樿绂婚櫌"
+            placeholder="榛樿鍦ㄩ櫌"
             clearable
             style="width: 150px"
             @change="handleSatisfactionScopeChange"
@@ -150,33 +150,67 @@
         @selection-change="handleSelectionChange"
         :row-key="getRowKey"
       >
-        <!-- 鐥呭尯鍒楋細浣忛櫌婊℃剰搴︾粺璁″湪闄㈢梾鍖猴紝鍏朵綑缁熻鍑洪櫌鐥呭尯 -->
+        <!-- 鐥呭尯缁熻锛氬湪闄㈢梾鍖� + 绂婚櫌鐥呭尯 -->
         <el-table-column
           v-if="queryParams.statisticaltype == 1"
-          :label="wardColumnLabel"
+          label="鍦ㄩ櫌鐥呭尯"
+          align="center"
+          sortable
+          key="hospitaldistrictname"
+          prop="hospitaldistrictname"
+          :show-overflow-tooltip="true"
+          :sort-method="sortHospitalWard"
+          min-width="120"
+        >
+          <template slot-scope="scope">
+            {{ scope.row.hospitaldistrictname || "-" }}
+          </template>
+        </el-table-column>
+
+        <el-table-column
+          v-if="queryParams.statisticaltype == 1"
+          label="绂婚櫌鐥呭尯"
           align="center"
           sortable
           key="leavehospitaldistrictname"
           prop="leavehospitaldistrictname"
           :show-overflow-tooltip="true"
-          :sort-method="sortChineseNumber"
+          :sort-method="sortLeaveWard"
           min-width="120"
         >
           <template slot-scope="scope">
-            {{ getWardName(scope.row) || "-" }}
+            {{ scope.row.leavehospitaldistrictname || "-" }}
           </template>
         </el-table-column>
 
-        <!-- 绉戝鍒� -->
+        <!-- 绉戝缁熻锛氬湪闄㈢瀹� + 绂婚櫌绉戝 -->
         <el-table-column
           v-if="queryParams.statisticaltype == 2"
-          label="绉戝"
+          label="鍦ㄩ櫌绉戝"
+          align="center"
+          key="hospitaldeptname"
+          prop="hospitaldeptname"
+          :show-overflow-tooltip="true"
+          min-width="120"
+        >
+          <template slot-scope="scope">
+            {{ scope.row.hospitaldeptname || "-" }}
+          </template>
+        </el-table-column>
+
+        <el-table-column
+          v-if="queryParams.statisticaltype == 2"
+          label="绂婚櫌绉戝"
           align="center"
           key="deptname"
           prop="deptname"
           :show-overflow-tooltip="true"
           min-width="120"
-        />
+        >
+          <template slot-scope="scope">
+            {{ scope.row.deptname || "-" }}
+          </template>
+        </el-table-column>
 
         <el-table-column
           label="鍑洪櫌浜烘"
@@ -367,14 +401,16 @@
   data() {
     return {
       // 婊℃剰搴︾被鍨嬶細leave=绂婚櫌婊℃剰搴︼紙鎸夊嚭闄㈢梾鍖虹粺璁★級锛宧ospital=鍦ㄩ櫌婊℃剰搴︼紙鎸夊湪闄㈢梾鍖虹粺璁★級
-      satisfactionScope: "leave",
+      // 榛樿鍦ㄩ櫌婊℃剰搴�
+      satisfactionScope: "hospital",
 
       // 鏌ヨ鍙傛暟
       queryParams: {
         statisticaltype: 1,
         leavehospitaldistrictcodes: ["all"],
         deptcodes: [],
-        serviceType: [2],
+        // 榛樿鏈嶅姟绫诲瀷锛�6=浣忛櫌婊℃剰搴︼紙鍑哄叆闄㈡弧鎰忓害锛�
+        serviceType: [6],
         dateRange: [],
         pageNum: 1,
         pageSize: 20,
@@ -480,15 +516,11 @@
   },
 
   computed: {
-    // 鏄惁鎸夈�屽湪闄㈡弧鎰忓害銆嶅彛寰勭粺璁★細鍦ㄩ櫌鎮h�呮寜鍦ㄩ櫌鐥呭尯(hospitaldistrictcodes)缁熻锛�
-    // 绂婚櫌婊℃剰搴︿粛鎸夊嚭闄㈢梾鍖�(leavehospitaldistrictcodes)缁熻
+    // 鏄惁鎸夈�屽湪闄㈡弧鎰忓害銆嶅彛寰勭粺璁★細鍦ㄩ櫌鐢� hospitaldistrictcodes / hospitaldeptcodes锛�
+    // 绂婚櫌鐢� leavehospitaldistrictcodes / leaveldeptcodes
+    // 榛樿鍦ㄩ櫌锛屾墍浠ユ竻绌轰笅鎷夋椂浠嶆寜鍦ㄩ櫌鍙e緞澶勭悊
     isInHospitalSatisfaction() {
-      return this.satisfactionScope === "hospital";
-    },
-
-    // 鐥呭尯鍒楁爣棰�
-    wardColumnLabel() {
-      return this.isInHospitalSatisfaction ? "鍦ㄩ櫌鐥呭尯" : "鍑洪櫌鐥呭尯";
+      return this.satisfactionScope !== "leave";
     },
   },
 
@@ -554,7 +586,8 @@
           params.endTime = this.queryParams.dateRange[1];
         }
 
-        // 澶勭悊鐥呭尯/绉戝閫夋嫨
+        // 澶勭悊鐥呭尯/绉戝閫夋嫨锛氬彧淇濈暀褰撳墠缁熻绫诲瀷 + 褰撳墠婊℃剰搴︾被鍨嬪搴旂殑瀛楁锛�
+        // 閬垮厤鍦ㄩ櫌/绂婚櫌涓ゅ鏉′欢鍚屾椂鎷艰繘 SQL
         if (params.statisticaltype == 1) {
           // 鐥呭尯缁熻
           let wardCodes = params.leavehospitaldistrictcodes || [];
@@ -564,9 +597,11 @@
               (ward) => ward.districtCode
             );
           }
-          // 浣忛櫌婊℃剰搴﹂拡瀵瑰湪闄㈡偅鑰咃紝鎸夊湪闄㈢梾鍖�(hospitaldistrictcodes)缁熻锛�
-          // 鍑洪櫌闅忚绛夊叾浠栨湇鍔$被鍨嬩粛鎸夊嚭闄㈢梾鍖�(leavehospitaldistrictcodes)缁熻
           delete params.leavehospitaldistrictcodes;
+          delete params.hospitaldistrictcodes;
+          delete params.deptcodes;
+          delete params.leaveldeptcodes;
+          delete params.hospitaldeptcodes;
           if (this.isInHospitalSatisfaction) {
             params.hospitaldistrictcodes = wardCodes;
           } else {
@@ -574,20 +609,33 @@
           }
         } else if (params.statisticaltype == 2) {
           // 绉戝缁熻
-          if (params.deptcodes.includes("all")) {
+          let deptCodes = params.deptcodes || [];
+          if (deptCodes.includes("all")) {
             // 濡傛灉閫夋嫨浜�"鍏ㄩ儴"锛屽垯绉婚櫎"all"鍊�
-            params.deptcodes = params.deptcodes.filter(
-              (item) => item !== "all"
-            );
+            deptCodes = deptCodes.filter((item) => item !== "all");
             // 濡傛灉闇�瑕佷紶鎵�鏈夌瀹や唬鐮侊紝鍙互浠巗tore涓幏鍙�
-            params.deptcodes = (this.$store.getters.belongDepts || []).map(
+            deptCodes = (this.$store.getters.belongDepts || []).map(
               (dept) => dept.deptCode
             );
+          }
+          delete params.deptcodes;
+          delete params.leaveldeptcodes;
+          delete params.hospitaldeptcodes;
+          delete params.leavehospitaldistrictcodes;
+          delete params.hospitaldistrictcodes;
+          if (this.isInHospitalSatisfaction) {
+            params.hospitaldeptcodes = deptCodes;
+          } else {
+            params.leaveldeptcodes = deptCodes;
           }
         }
 
         const response = await getSfStatisticsJoy(params);
-        this.userList = this.customSort(response.data) || [];
+        // 绉戝缁熻鎸夋帴鍙h繑鍥為『搴忥紝鐥呭尯缁熻淇濇寔鍘熸湁鐨勪腑鏂囧簭鍙锋帓搴�
+        this.userList =
+          this.queryParams.statisticaltype == 1
+            ? this.customSort(response.data) || []
+            : response.data || [];
         this.total = response.total || 0;
       } catch (error) {
         console.error("鑾峰彇缁熻鍒楄〃澶辫触:", error);
@@ -597,9 +645,22 @@
       }
     },
     sortChineseNumber(aRow, bRow) {
-      const a = this.getWardName(aRow);
-      const b = this.getWardName(bRow);
-
+      return this.compareWardNames(this.getWardName(aRow), this.getWardName(bRow));
+    },
+    sortHospitalWard(aRow, bRow) {
+      return this.compareWardNames(
+        aRow && aRow.hospitaldistrictname,
+        bRow && bRow.hospitaldistrictname
+      );
+    },
+    sortLeaveWard(aRow, bRow) {
+      return this.compareWardNames(
+        aRow && aRow.leavehospitaldistrictname,
+        bRow && bRow.leavehospitaldistrictname
+      );
+    },
+    // 姣旇緝涓や釜鐥呭尯鍚嶇О鐨勪腑鏂囧簭鍙凤紱鏃犲簭鍙锋椂鎸夊瓧绗︿覆姣旇緝
+    compareWardNames(a, b) {
       // 涓枃鏁板瓧鍒伴樋鎷変集鏁板瓧鐨勬槧灏勶紙鎵╁睍鍒�45锛�
       const chineseNumMap = {
         涓�: 1,
@@ -793,13 +854,14 @@
       this.getList();
     },
 
-    // 閲嶇疆鏌ヨ
+    // 閲嶇疆鏌ヨ锛堟仮澶嶉粯璁わ細鍦ㄩ櫌婊℃剰搴� + 鏈嶅姟绫诲瀷 6锛�
     resetQuery() {
+      this.satisfactionScope = "hospital";
       this.queryParams = {
         statisticaltype: 1,
         leavehospitaldistrictcodes: [],
         deptcodes: [],
-        serviceType: [2],
+        serviceType: [6],
         dateRange: [],
         pageNum: 1,
         pageSize: 20,
@@ -827,17 +889,19 @@
       this.multiple = !selection.length;
     },
 
-    // 鑾峰彇琛宬ey
+    // 鑾峰彇琛宬ey锛堟寜褰撳墠缁熻绫诲瀷鍙栧搴旂淮搴︾紪鐮侊級
     getRowKey(row) {
-      return row.statisticaltype === 1
+      return this.queryParams.statisticaltype == 1
         ? row.hospitaldistrictcode || row.leavehospitaldistrictcode
-        : row.deptcode;
+        : row.hospitaldeptcode || row.deptcode;
     },
 
-    // 鐥呭尯鍚嶇О锛氫綇闄㈡弧鎰忓害鎺ュ彛杩斿洖鍦ㄩ櫌鐥呭尯瀛楁锛屽叾浣欒繑鍥炲嚭闄㈢梾鍖哄瓧娈�
+    // 褰撳墠婊℃剰搴︾被鍨嬪搴旂殑鐥呭尯鍚嶇О锛堢敤浜庢帓搴�/瀵煎嚭/璇︽儏鏍囬锛�
     getWardName(row) {
       if (!row) return "";
-      return row.hospitaldistrictname || row.leavehospitaldistrictname || "";
+      return this.isInHospitalSatisfaction
+        ? row.hospitaldistrictname || ""
+        : row.leavehospitaldistrictname || "";
     },
 
     // 鏍煎紡鍖栫櫨鍒嗘瘮
@@ -874,22 +938,33 @@
           params.endTime = this.queryParams.dateRange[1];
         }
 
+        // 璇︽儏鍙寜褰撳墠鍒嗙粍缁村害杩囨护锛屾竻鎺夊叾浣欑淮搴︼紝閬垮厤鍦ㄩ櫌/绂婚櫌鏉′欢浜掔浉骞叉壈
+        delete params.deptcodes;
+        delete params.leaveldeptcodes;
+        delete params.hospitaldeptcodes;
+        delete params.leavehospitaldistrictcodes;
+        delete params.hospitaldistrictcodes;
+
         if (this.queryParams.statisticaltype == 1) {
-          this.topicvalue.name = this.getWardName(row);
-          // 浣忛櫌婊℃剰搴︽寜鍦ㄩ櫌鐥呭尯缁熻锛屽叾浣欐寜鍑洪櫌鐥呭尯缁熻
           if (this.isInHospitalSatisfaction) {
-            delete params.leavehospitaldistrictcodes;
-            params.hospitaldistrictcodes = [
-              row.hospitaldistrictcode || row.leavehospitaldistrictcode,
-            ];
+            this.topicvalue.name = row.hospitaldistrictname || "-";
+            params.hospitaldistrictcodes = [row.hospitaldistrictcode].filter(
+              Boolean
+            );
           } else {
+            this.topicvalue.name = row.leavehospitaldistrictname || "-";
             params.leavehospitaldistrictcodes = [
               row.leavehospitaldistrictcode,
-            ];
+            ].filter(Boolean);
           }
         } else {
-          this.topicvalue.name = row.deptname;
-          params.deptcodes = [row.deptcode];
+          if (this.isInHospitalSatisfaction) {
+            this.topicvalue.name = row.hospitaldeptname || "-";
+            params.hospitaldeptcodes = [row.hospitaldeptcode].filter(Boolean);
+          } else {
+            this.topicvalue.name = row.deptname || "-";
+            params.leaveldeptcodes = [row.deptcode].filter(Boolean);
+          }
         }
 
         const response = await getSfStatisticsJoyInfo(params);
@@ -1012,16 +1087,18 @@
           },
         };
 
-        // 娣诲姞鎬绘爣棰�
+        // 娣诲姞鎬绘爣棰橈紙涓ゅ垪缁村害 + 鍏釜鎸囨爣鍒楋紝鍏� 10 鍒楋級
         worksheet.mergeCells(1, 1, 1, 10);
         const titleCell = worksheet.getCell(1, 1);
         titleCell.value = `婊℃剰搴﹂殢璁跨粺璁¤〃锛�${sheetNameSuffix}锛塦;
         titleCell.style = titleStyle;
         worksheet.getRow(1).height = 35;
 
-        // 娣诲姞琛ㄥご
+        // 娣诲姞琛ㄥご锛堢瀹ょ粺璁″鍑哄湪闄㈢瀹�+绂婚櫌绉戝锛岀梾鍖虹粺璁″鍑哄湪闄㈢梾鍖�+绂婚櫌鐥呭尯锛�
+        const isWardStatistics = this.queryParams.statisticaltype == 1;
         const headers = [
-          this.queryParams.statisticaltype == 1 ? this.wardColumnLabel : "绉戝",
+          isWardStatistics ? "鍦ㄩ櫌鐥呭尯" : "鍦ㄩ櫌绉戝",
+          isWardStatistics ? "绂婚櫌鐥呭尯" : "绂婚櫌绉戝",
           "鍑洪櫌浜烘",
           "鏃犻渶闅忚浜烘",
           "搴旈殢璁夸汉娆�",
@@ -1041,9 +1118,12 @@
         // 娣诲姞鏁版嵁琛�
         this.userList.forEach((item) => {
           const dataRow = worksheet.addRow([
-            this.queryParams.statisticaltype == 1
-              ? this.getWardName(item)
-              : item.deptname,
+            isWardStatistics
+              ? item.hospitaldistrictname || "-"
+              : item.hospitaldeptname || "-",
+            isWardStatistics
+              ? item.leavehospitaldistrictname || "-"
+              : item.deptname || "-",
             item.dischargeCount || 0,
             item.nonFollowUp || 0,
             item.followUpNeeded || 0,
@@ -1063,6 +1143,7 @@
         // 璁剧疆鍒楀
         worksheet.columns = [
           { width: 20 },
+          { width: 20 },
           { width: 12 },
           { width: 12 },
           { width: 12 },
diff --git a/src/views/followvisit/discharge/index.vue b/src/views/followvisit/discharge/index.vue
index 37c3236..fb47a9e 100644
--- a/src/views/followvisit/discharge/index.vue
+++ b/src/views/followvisit/discharge/index.vue
@@ -5,6 +5,8 @@
       :ycvalue="ycvalue"
       :jgvalue="jgvalue"
       :show-warning-condition="orgname == '鐪佺珛鍚屽痉缈犺嫅闄㈠尯'"
+      clickable
+      @card-click="handleCardClick"
     />
     <el-row :gutter="20">
       <!--鐢ㄦ埛鏁版嵁-->
@@ -255,6 +257,11 @@
           </span>
         </div>
       </el-row>
+      <div v-if="cardFilter" class="card-filter-tip">
+        褰撳墠鎸夐《閮ㄥ崱鐗囩瓫閫夛細<b>{{ cardFilter }}</b>
+        <span class="tip-desc">锛堜笉褰卞搷涓婃柟琛ㄥ崟鏉′欢锛岀偣銆屾悳绱€�嶅彲鎭㈠琛ㄥ崟鏉′欢锛�</span>
+        <el-button type="text" size="mini" @click="clearCardFilter">娓呴櫎</el-button>
+      </div>
       <div class="selected-info">
         宸查�変腑
         <span style="color: #409eff; font-weight: bold">{{
@@ -1278,6 +1285,8 @@
       ],
       lastScopeType: 3, // 鎮h�呰寖鍥翠笂娆¢�夋嫨鐨勪竴绾х被鍨嬶紙1=绉戝锛�2=鐥呭尯锛�3=鍏ㄩ儴锛�
       loading: false,
+      // 椤堕儴鍗$墖鐐瑰嚮甯︽潵鐨勪复鏃剁瓫閫夛紙鍙綔鐢ㄤ簬涓嬮潰鍒楄〃锛屼笉鍔ㄨ〃鍗曘�佷笉鏀瑰崱鐗囨暟瀛楋紱鐐广�屾悳绱€�嶆椂娓呯┖锛�
+      cardFilter: null,
       cardlist: [
         {
           name: "鎮h�呮湇鍔℃�婚噺",
@@ -1506,6 +1515,15 @@
     // 鐩戝惉璺敱鍙傛暟鍙樺寲
     "$route.query": {
       handler(newQuery, oldQuery) {
+        // 鍙充笅瑙掋�屽緟澶勭悊闅忚浠诲姟銆嶅崱鐗囧啀娆$偣鍑伙紙褰撳墠宸插湪鏈〉锛�
+        if (
+          newQuery?.month &&
+          newQuery?.fromPendingTask === "1" &&
+          this.taskQueryReady
+        ) {
+          this.applyPendingTaskQuery();
+          return;
+        }
         if (newQuery?.errtype !== oldQuery?.errtype) {
           console.log(22);
           this.loadData();
@@ -1536,7 +1554,10 @@
     });
     // 鍏嶇櫥鐩磋揪锛氭牴鎹瀹�/鐥呭尯缂栫爜棰勫~鎮h�呰寖鍥�
     this.applyFollowUpScope();
-    if (this.errtype == 1) {
+    // 鍙充笅瑙掋�屽緟澶勭悊闅忚浠诲姟銆嶅崱鐗囪烦杞細鎸夊嚭闄㈠勾鏈� + 寰呴殢璁� + 鍑洪櫌婊� 7 澶╄繃婊�
+    if (this.applyPendingTaskQuery()) {
+      // 宸叉寜鍗$墖鏉′欢鏌ヨ锛屼笉鍐嶈蛋榛樿鍒嗘敮
+    } else if (this.errtype == 1) {
       this.toleadExport(2);
     } else if (this.errtype == 2) {
       // 寰呴殢璁�
@@ -1556,9 +1577,16 @@
     this.getConfigKey("sys.user.initPassword").then((response) => {
       this.initPassword = response.msg;
     });
+    // created 鍒濆鍖栧畬鎴愶紝涔嬪悗璺敱 query 鍙樺寲鎵嶆寜鍗$墖鏉′欢閲嶆柊鏌ヨ
+    this.taskQueryReady = true;
   },
   activated() {
+    // 浠庡埆鐨勬爣绛鹃〉鍒囧洖鏉ユ椂锛屼互琛ㄥ崟鏉′欢涓哄噯锛屼涪寮冨崱鐗囧甫鏉ョ殑涓�娆℃�х瓫閫�
+    this.cardFilter = null;
     this.errtype = this.$route.query.errtype;
+    if (this.applyPendingTaskQuery()) {
+      return;
+    }
     if (this.errtype == 1) {
       this.toleadExport(2);
     } else if (this.errtype == 2) {
@@ -1613,7 +1641,9 @@
       }
 
       try {
-        const response = await getTaskservelist(this.topqueryParams);
+        // 椤堕儴鍗$墖鐐瑰嚮鐨勪复鏃舵潯浠跺彧鍔犲湪鏈璇锋眰涓婏紝涓嶅啓鍥炶〃鍗�
+        const query = this.applyCardFilter({ ...this.topqueryParams });
+        const response = await getTaskservelist(query);
 
         // 鉁� 绗竴姝ワ細鍏堥攣瀹氭仮澶嶇姸鎬�
         this.isRestoring = true;
@@ -1630,15 +1660,10 @@
 
         // 鉁� 绗洓姝ワ細澶勭悊鍏朵粬鏁版嵁
         if (refresh) {
-          this.cardlist[0].value =
-            Number(response.rows[0].wxsf) + Number(response.rows[0].xsf) || 0;
-          this.cardlist[1].value = response.rows[0].wxsf || 0;
-          this.ycvalue = Number(response.rows[0].yc) || 0;
-          this.jgvalue = response.rows[0].jg;
-          this.cardlist[2].value = response.rows[0].xsf || 0;
-          this.cardlist[3].value = response.rows[0].dsf || 0;
-          this.cardlist[4].value = response.rows[0].ywc || 0;
           this.yfsvalue = response.rows[0].yfs;
+          // 椤堕儴鍗$墖鐨勬暟瀛椾笉璺熴�岄殢璁跨姸鎬�/寮傚父銆嶈蛋锛氬崟鐙煡涓�娆″幓鎺夌姸鎬佹潯浠剁殑缁熻锛�
+          // 鍚﹀垯绛涗簡銆屽緟闅忚銆嶅悗銆屽凡瀹屾垚銆嶆案杩滄槸 0锛岀湅鐫�鍍忕畻閿欎簡
+          this.refreshCardCounts(query);
         }
 
         // 鉁� 绗簲姝ワ細澶勭悊 preachform 绛夊叾浠栨暟鎹�
@@ -1875,6 +1900,8 @@
     },
     /** 鎼滅储鎸夐挳鎿嶄綔 */
     handleQuery(refresh) {
+      // 鐐广�屾悳绱€�嶆椂浠ヨ〃鍗曟潯浠朵负鍑嗭紝娓呮帀鍗$墖鐐瑰嚮甯︽潵鐨勪复鏃舵潯浠�
+      this.cardFilter = null;
       this.applyDeptWardScope();
       this.clearAllSelection();
       this.topqueryParams.pageNum = 1;
@@ -1897,6 +1924,60 @@
       if (wardCode) scope.push([2, wardCode]);
       this.topqueryParams.scopetype = scope;
       this.lastScopeType = deptCode ? 1 : 2;
+    },
+    /**
+     * 鍙充笅瑙掋�屽緟澶勭悊闅忚浠诲姟銆嶅崱鐗囩偣鍑绘暟瀛楄烦杞繃鏉ワ細
+     * 鎸夊嚭闄㈠勾鏈� + 寰呴殢璁匡紙sendstate 1/2/3/5/7锛�+ 鍑洪櫌婊� 7 澶� 杩囨护锛屽彛寰勪笌鍗$墖涓�鑷�
+     * @returns {boolean} 鏄惁宸叉寜鍗$墖鏉′欢鍙戣捣鏌ヨ
+     */
+    applyPendingTaskQuery() {
+      const query = this.$route.query || {};
+      if (!query.month || query.fromPendingTask !== "1") {
+        return false;
+      }
+      // 椤甸潰琚� keep-alive 澶嶇敤鏃朵細閲嶅瑙﹀彂 activated锛屽悓涓�娆$偣鍑诲彧澶勭悊涓�娆�
+      if (this.pendingTaskToken && this.pendingTaskToken === query._t) {
+        return false;
+      }
+      this.pendingTaskToken = query._t;
+
+      const month = String(query.month);
+      const serviceType = Number(query.serviceType) === 3 ? 3 : 2;
+      this.errtype = undefined;
+      const start = month + "-01";
+      let end = this.pendingTaskMonthEnd(month);
+      // 鏈堝垵 7 澶╁唴锛�"浠婂ぉ-7澶�" 浼氭棭浜庢湀鍒濓紝鍏滃簳鎴愭湀鍒濓紝閬垮厤鏃ユ湡鍖洪棿鍊掓寕
+      if (end < start) {
+        end = start;
+      }
+      this.dateRange = [start, end];
+      this.topqueryParams.serviceType = serviceType;
+      this.topqueryParams.sendstateView = 1;
+      this.topqueryParams.sendstate = null;
+      // 鍗$墖缁熻鐨勬槸鍏ㄩ儴寰呴殢璁夸换鍔★紙涓嶅尯鍒嗛杞�/澶嶈瘖锛夛紝鍒楄〃杩欓噷鍚屾鏀惧紑
+      this.topqueryParams.visitCount = null;
+      this.topqueryParams.pageNum = 1;
+      this.handleQuery(1);
+      return true;
+    },
+    /**
+     * 鍗$墖鍙e緞鐨勬湀浠界粨鏉熸棩锛�
+     * 褰撴湀鍙粺璁″嚭闄㈡弧 7 澶╃殑锛屾墍浠ュ彇銆屼粖澶� - 7 澶┿�嶏紱鍘嗗彶鏈堜唤鍙栧綋鏈堟渶鍚庝竴澶�
+     */
+    pendingTaskMonthEnd(month) {
+      const parts = String(month).split("-");
+      const year = Number(parts[0]);
+      const mon = Number(parts[1]);
+      const now = new Date();
+      let date;
+      if (year === now.getFullYear() && mon === now.getMonth() + 1) {
+        date = new Date(year, mon - 1, now.getDate() - 7);
+      } else {
+        date = new Date(year, mon, 0);
+      }
+      const mm = String(date.getMonth() + 1).padStart(2, "0");
+      const dd = String(date.getDate()).padStart(2, "0");
+      return date.getFullYear() + "-" + mm + "-" + dd;
     },
     // 鎮h�呰寖鍥村鐞嗭細浠庡閫夌骇鑱� scopetype 瑙f瀽绉戝/鐥呭尯
     applyDeptWardScope() {
@@ -2340,6 +2421,74 @@
         this.topqueryParams.scopetype = null;
       }
       this.handleQuery(1);
+    },
+    // 椤堕儴缁熻鍗$墖鐐瑰嚮锛氭妸瀵瑰簲绛涢�夋潯浠朵笅甯﹀埌涓嬮潰鐨勫垪琛紙鏁板�间负 0 鐨勫崱鐗囧悓鏍峰彲鐐癸級
+    // 椤堕儴鍗$墖缁熻锛氬幓鎺夈�岄殢璁跨姸鎬� / 寮傚父銆嶆潯浠跺悗鍐嶇粺璁★紝
+    // 杩欐牱鍗$墖鏁板瓧鍙窡鏃ユ湡銆佺瀹�/鐥呭尯绛夋潯浠惰蛋锛屼笉浼氬洜涓虹瓫浜嗐�屽緟闅忚銆嶅氨鎶娿�屽凡瀹屾垚銆嶇畻鎴� 0
+    async refreshCardCounts(baseQuery) {
+      const query = {
+        ...(baseQuery || this.topqueryParams),
+        pageNum: 1,
+        pageSize: 1,
+        sendstate: null,
+        sendstateView: null,
+        sendstates: null,
+        excep: null,
+      };
+      try {
+        const res = await getTaskservelist(query);
+        const row = (res && res.rows && res.rows[0]) || {};
+        this.cardlist[0].value = Number(row.wxsf || 0) + Number(row.xsf || 0);
+        this.cardlist[1].value = Number(row.wxsf) || 0;
+        this.cardlist[2].value = Number(row.xsf) || 0;
+        this.cardlist[3].value = Number(row.dsf) || 0;
+        this.cardlist[4].value = Number(row.ywc) || 0;
+        this.ycvalue = Number(row.yc) || 0;
+        this.jgvalue = Number(row.jg) || 0;
+      } catch (e) {
+        console.warn("鍒锋柊椤堕儴鍗$墖缁熻澶辫触", e);
+      }
+    },
+    // 椤堕儴缁熻鍗$墖鐐瑰嚮锛氬彧缁欎笅闈㈢殑鍒楄〃鍔犱复鏃舵潯浠讹紝涓嶅姩涓婃柟琛ㄥ崟銆佷篃涓嶆敼鍗$墖鏁板瓧锛�
+    // 鍗$墖鏁板瓧鍙湪鐐广�屾悳绱€�嶆椂鎸夎〃鍗曟潯浠堕噸绠�
+    handleCardClick(item) {
+      this.cardFilter = item && item.name ? item.name : null;
+      this.topqueryParams.pageNum = 1;
+      // 浼� 0锛氬埛鏂板垪琛紝浣嗕笉鍥炲啓椤堕儴鍗$墖鏁板瓧
+      this.getList(0);
+    },
+    // 鎶婂崱鐗囩偣鍑荤殑鏉′欢鍙犲姞鍒版煡璇㈠弬鏁帮紙杩斿洖鏂板璞★紝涓嶄慨鏀硅〃鍗曟湰韬級
+    applyCardFilter(query) {
+      const name = this.cardFilter;
+      if (!name) return query;
+      // 鍗$墖鏁板瓧鏄�屼笉鍚殢璁跨姸鎬�/寮傚父銆嶇殑鎬婚噺锛屾墍浠ョ偣鍗$墖鏃朵篃鎶婅〃鍗曢噷鐨勭姸鎬佹潯浠跺幓鎺夛紝
+      // 鍙寜鍗$墖鑷繁鐨勬潯浠舵煡锛屽惁鍒欎細鍑虹幇銆屽崱鐗� 922銆佸垪琛� 3 鏉°��
+      query.sendstate = null;
+      query.sendstateView = null;
+      query.sendstates = null;
+      query.excep = null;
+
+      if (name === "鏃犻渶闅忚") {
+        query.sendstateView = 3;
+      } else if (name === "寰呴殢璁�") {
+        query.sendstateView = 1;
+      } else if (name === "宸插畬鎴�") {
+        query.sendstateView = 2;
+      } else if (name === "闇�闅忚") {
+        query.sendstates = [1, 2, 3, 5, 6, 7];
+      } else if (name === "寮傚父") {
+        query.excep = "1";
+      } else if (name === "璀﹀憡") {
+        query.excep = "2";
+      }
+      // 銆屾偅鑰呮湇鍔℃�婚噺銆�= 鍙幓鎺夌姸鎬佹潯浠讹紝涓嶅姞鍒殑
+      return query;
+    },
+    // 娓呴櫎鍗$墖绛涢�夛紝鍥炲埌琛ㄥ崟鏉′欢
+    clearCardFilter() {
+      this.cardFilter = null;
+      this.topqueryParams.pageNum = 1;
+      this.getList(0);
     },
     /** 瀵煎嚭鎸夐挳鎿嶄綔 */
     handleExport() {
@@ -2882,6 +3031,20 @@
   font-size: 14px;
   color: #666;
 }
+.card-filter-tip {
+  margin: 2px 0 4px;
+  padding: 6px 10px;
+  font-size: 13px;
+  color: #303133;
+  background: #f0f7ff;
+  border: 1px solid #d6e9ff;
+  border-radius: 4px;
+}
+.card-filter-tip .tip-desc {
+  margin: 0 6px;
+  font-size: 12px;
+  color: #909399;
+}
 /* ================= 娓呮柊楂樼骇绠�绾﹂ ================= */
 .app-container {
   background: #f5f7fb;
diff --git a/src/views/followvisit/discharge/outpatientService.vue b/src/views/followvisit/discharge/outpatientService.vue
index 77c0b1d..243496d 100644
--- a/src/views/followvisit/discharge/outpatientService.vue
+++ b/src/views/followvisit/discharge/outpatientService.vue
@@ -1117,7 +1117,21 @@
       rules: {},
     };
   },
-  watch: {},
+  watch: {
+    // 鍙充笅瑙掋�屽緟澶勭悊闅忚浠诲姟銆嶅崱鐗囧啀娆$偣鍑伙紙褰撳墠宸插湪鏈〉锛�
+    "$route.query": {
+      handler(newQuery) {
+        if (
+          newQuery?.month &&
+          newQuery?.fromPendingTask === "1" &&
+          this.taskQueryReady
+        ) {
+          this.applyPendingTaskQuery();
+        }
+      },
+      immediate: true,
+    },
+  },
   created() {
     this.serviceState = store.getters.serviceState;
     this.checkboxlist = store.getters.checkboxlist;
@@ -1136,7 +1150,9 @@
         value: dept.districtCode,
       };
     });
-    if (this.errtype) {
+    if (this.applyPendingTaskQuery()) {
+      // 鍙充笅瑙掋�屽緟澶勭悊闅忚浠诲姟銆嶅崱鐗囪烦杞細宸叉寜骞存湀 + 寰呴殢璁挎潯浠舵煡璇�
+    } else if (this.errtype) {
       this.toleadExport(2);
     } else {
       this.getList(1);
@@ -1144,8 +1160,13 @@
     this.getConfigKey("sys.user.initPassword").then((response) => {
       this.initPassword = response.msg;
     });
+    // created 鍒濆鍖栧畬鎴愶紝涔嬪悗璺敱 query 鍙樺寲鎵嶆寜鍗$墖鏉′欢閲嶆柊鏌ヨ
+    this.taskQueryReady = true;
   },
   activated() {
+    if (this.applyPendingTaskQuery()) {
+      return;
+    }
     this.getList(1);
   },
   methods: {
@@ -1350,6 +1371,60 @@
       };
       this.resetForm("form");
     },
+    /**
+     * 鍙充笅瑙掋�屽緟澶勭悊闅忚浠诲姟銆嶅崱鐗囩偣鍑绘暟瀛楄烦杞繃鏉ワ細
+     * 鎸夊嚭闄㈠勾鏈� + 寰呴殢璁匡紙sendstate 1/2/3/5/7锛�+ 鍑洪櫌婊� 7 澶� 杩囨护锛屽彛寰勪笌鍗$墖涓�鑷�
+     * @returns {boolean} 鏄惁宸叉寜鍗$墖鏉′欢鍙戣捣鏌ヨ
+     */
+    applyPendingTaskQuery() {
+      const query = this.$route.query || {};
+      if (!query.month || query.fromPendingTask !== "1") {
+        return false;
+      }
+      // 椤甸潰琚� keep-alive 澶嶇敤鏃朵細閲嶅瑙﹀彂 activated锛屽悓涓�娆$偣鍑诲彧澶勭悊涓�娆�
+      if (this.pendingTaskToken && this.pendingTaskToken === query._t) {
+        return false;
+      }
+      this.pendingTaskToken = query._t;
+
+      const month = String(query.month);
+      const serviceType = Number(query.serviceType) === 3 ? 3 : 2;
+      this.errtype = undefined;
+      const start = month + "-01";
+      let end = this.pendingTaskMonthEnd(month);
+      // 鏈堝垵 7 澶╁唴锛�"浠婂ぉ-7澶�" 浼氭棭浜庢湀鍒濓紝鍏滃簳鎴愭湀鍒濓紝閬垮厤鏃ユ湡鍖洪棿鍊掓寕
+      if (end < start) {
+        end = start;
+      }
+      this.dateRange = [start, end];
+      this.topqueryParams.serviceType = serviceType;
+      this.topqueryParams.sendstateView = 1;
+      this.topqueryParams.sendstate = null;
+      // 鍗$墖缁熻鐨勬槸鍏ㄩ儴寰呴殢璁夸换鍔★紙涓嶅尯鍒嗛杞�/澶嶈瘖锛夛紝鍒楄〃杩欓噷鍚屾鏀惧紑
+      this.topqueryParams.visitCount = null;
+      this.topqueryParams.pageNum = 1;
+      this.handleQuery(1);
+      return true;
+    },
+    /**
+     * 鍗$墖鍙e緞鐨勬湀浠界粨鏉熸棩锛�
+     * 褰撴湀鍙粺璁″嚭闄㈡弧 7 澶╃殑锛屾墍浠ュ彇銆屼粖澶� - 7 澶┿�嶏紱鍘嗗彶鏈堜唤鍙栧綋鏈堟渶鍚庝竴澶�
+     */
+    pendingTaskMonthEnd(month) {
+      const parts = String(month).split("-");
+      const year = Number(parts[0]);
+      const mon = Number(parts[1]);
+      const now = new Date();
+      let date;
+      if (year === now.getFullYear() && mon === now.getMonth() + 1) {
+        date = new Date(year, mon - 1, now.getDate() - 7);
+      } else {
+        date = new Date(year, mon, 0);
+      }
+      const mm = String(date.getMonth() + 1).padStart(2, "0");
+      const dd = String(date.getDate()).padStart(2, "0");
+      return date.getFullYear() + "-" + mm + "-" + dd;
+    },
     /** 鎼滅储鎸夐挳鎿嶄綔 */
     handleQuery(refresh) {
       if (this.topqueryParams.searchscope == 3) {
diff --git a/src/views/system/user/profile/index.vue b/src/views/system/user/profile/index.vue
index 2533e08..63e63de 100644
--- a/src/views/system/user/profile/index.vue
+++ b/src/views/system/user/profile/index.vue
@@ -25,7 +25,7 @@
               </li>
 
               <!-- ===== 鎵�灞炵梾鍖� ===== -->
-              <li class="list-group-item" v-if="user.belongWards && user.belongWards.length">
+              <li class="list-group-item" v-if="uniqueWards && uniqueWards.length">
                 <svg-icon icon-class="tree" />鎵�灞炵梾鍖�
                 <div class="pull-right">
                   <!-- 鍗楀崕闄勪竴锛氬彲缂栬緫妯″紡 -->
@@ -44,7 +44,7 @@
                   <!-- 鍗楀崕闄勪竴锛氬彧璇绘ā寮� -->
                   <template v-else-if="isNanhua">
                     <el-tag
-                      v-for="ward in user.belongWards"
+                      v-for="ward in uniqueWards"
                       :key="ward.districtId"
                       size="small"
                       class="ward-tag"
@@ -60,7 +60,7 @@
                       popper-class="ward-popover"
                     >
                       <div class="popover-content">
-                        <p v-for="ward in user.belongWards" :key="ward.districtId" class="popover-item">
+                        <p v-for="ward in uniqueWards" :key="ward.districtId" class="popover-item">
                           {{ ward.districtName }}
                         </p>
                       </div>
@@ -72,11 +72,11 @@
                           class="ward-tag"
                         >{{ ward.districtName }}</el-tag>
                         <el-tag
-                          v-if="user.belongWards.length > maxTagCount"
+                          v-if="uniqueWards.length > maxTagCount"
                           size="small"
                           class="more-tag"
                           @click="showAllWardsPopover = !showAllWardsPopover"
-                        >+{{ user.belongWards.length - maxTagCount }}</el-tag>
+                        >+{{ uniqueWards.length - maxTagCount }}</el-tag>
                       </div>
                     </el-popover>
                   </template>
@@ -88,7 +88,7 @@
               </li>
 
               <!-- ===== 鎵�灞炵瀹� ===== -->
-              <li class="list-group-item" v-if="user.belongDepts && user.belongDepts.length">
+              <li class="list-group-item" v-if="uniqueDepts && uniqueDepts.length">
                 <svg-icon icon-class="tree" />鎵�灞炵瀹�
                 <div class="pull-right">
                   <!-- 鍗楀崕闄勪竴锛氬彲缂栬緫妯″紡 -->
@@ -107,7 +107,7 @@
                   <!-- 鍗楀崕闄勪竴锛氬彧璇绘ā寮� -->
                   <template v-else-if="isNanhua">
                     <el-tag
-                      v-for="dept in user.belongDepts"
+                      v-for="dept in uniqueDepts"
                       :key="dept.deptId"
                       size="small"
                       class="dept-tag"
@@ -123,7 +123,7 @@
                       popper-class="dept-popover"
                     >
                       <div class="popover-content">
-                        <p v-for="dept in user.belongDepts" :key="dept.deptId" class="popover-item">
+                        <p v-for="dept in uniqueDepts" :key="dept.deptId" class="popover-item">
                           {{ dept.deptName }}
                         </p>
                       </div>
@@ -135,11 +135,11 @@
                           class="dept-tag"
                         >{{ dept.deptName }}</el-tag>
                         <el-tag
-                          v-if="user.belongDepts.length > maxTagCount"
+                          v-if="uniqueDepts.length > maxTagCount"
                           size="small"
                           class="more-tag"
                           @click="showAllDeptsPopover = !showAllDeptsPopover"
-                        >+{{ user.belongDepts.length - maxTagCount }}</el-tag>
+                        >+{{ uniqueDepts.length - maxTagCount }}</el-tag>
                       </div>
                     </el-popover>
                   </template>
@@ -223,15 +223,22 @@
     };
   },
   computed: {
+    // sys_user_dept 閲屽悓涓�鐥呭尯鍙兘鏈夊嚑鍗佹潯閲嶅琛岋紝鎺ュ彛鍘熸牱杩斿洖锛岃繖閲屾寜缂栫爜鍘婚噸
+    uniqueWards() {
+      return this.uniqueByCode(this.user.belongWards);
+    },
+    uniqueDepts() {
+      return this.uniqueByCode(this.user.belongDepts);
+    },
     // 璁$畻瑕佹樉绀虹殑鐥呭尯鏍囩锛堝墠maxTagCount涓級
     displayWards() {
-      if (!this.user.belongWards) return [];
-      return this.user.belongWards.slice(0, this.maxTagCount);
+      if (!this.uniqueWards) return [];
+      return this.uniqueWards.slice(0, this.maxTagCount);
     },
     // 璁$畻瑕佹樉绀虹殑绉戝鏍囩锛堝墠maxTagCount涓級
     displayDepts() {
-      if (!this.user.belongDepts) return [];
-      return this.user.belongDepts.slice(0, this.maxTagCount);
+      if (!this.uniqueDepts) return [];
+      return this.uniqueDepts.slice(0, this.maxTagCount);
     },
     // 鍗楀崕澶у闄勫睘绗竴鍖婚櫌 鍏佽缂栬緫绉戝/鐥呭尯
     isNanhua() {
@@ -245,6 +252,19 @@
     }
   },
   methods: {
+    // 鎸夌瀹�/鐥呭尯缂栫爜鍘婚噸锛坰ys_user_dept 瀛樺湪閲嶅琛岋級
+    uniqueByCode(list) {
+      const seen = {};
+      return (list || []).filter((item) => {
+        if (!item) return false;
+        const code =
+          item.districtCode || item.deptCode || item.districtId || item.deptId;
+        const key = String(code === undefined || code === null ? "" : code);
+        if (!key || seen[key]) return false;
+        seen[key] = true;
+        return true;
+      });
+    },
     getUser() {
       getUserProfile().then((response) => {
         this.user = response.data;
diff --git a/tmp-probe4/Probe17.class b/tmp-probe4/Probe17.class
new file mode 100644
index 0000000..26ca8d8
--- /dev/null
+++ b/tmp-probe4/Probe17.class
Binary files differ
diff --git a/tmp-probe4/Probe17.java b/tmp-probe4/Probe17.java
new file mode 100644
index 0000000..c9ccafb
--- /dev/null
+++ b/tmp-probe4/Probe17.java
@@ -0,0 +1,52 @@
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.sql.*;
+
+public class Probe17 {
+    static final String URL = "jdbc:mysql://haiershi.a1.luyouxia.net:23844/smartor_sltd"
+            + "?useUnicode=true&characterEncoding=utf8&useSSL=false"
+            + "&serverTimezone=GMT%2B8&connectTimeout=15000&socketTimeout=90000";
+
+    public static void main(String[] args) throws Exception {
+        Class.forName("com.mysql.cj.jdbc.Driver");
+        try (Connection c = DriverManager.getConnection(URL, "smartor", "Smartor.2023");
+             PrintWriter out = new PrintWriter(new OutputStreamWriter(
+                     new FileOutputStream("probe17.txt"), StandardCharsets.UTF_8))) {
+            run(c, out, "select config_key, config_value from sys_config where config_key='sys.authority.campus.all'");
+            run(c, out, "select d.dept_code, d.dept_name, d.campusid, count(*) dup from sys_dept d "
+                    + "inner join sys_user_dept ud on d.dept_code = ud.dept_code "
+                    + "where d.del_flag=0 and ud.del_flag=0 and d.orgid='20001001' and ud.orgid='20001001' "
+                    + "and ud.user_id=2609 and d.dept_type='2' group by d.dept_code, d.dept_name, d.campusid");
+            run(c, out, "select d.dept_code, d.dept_name, d.campusid from sys_dept d "
+                    + "inner join sys_user_dept ud on d.dept_code = ud.dept_code "
+                    + "where d.del_flag=0 and ud.del_flag=0 and d.orgid='20001001' and ud.orgid='20001001' "
+                    + "and d.campusid='30001002' and ud.user_id=2609 and d.dept_type='2' group by d.dept_code, d.dept_name, d.campusid");
+            run(c, out, "select leavehospitaldistrictcode, leavehospitaldistrictname, count(*) cnt from service_subtask "
+                    + "where del_flag='0' and service_type='2' and sendstate in (1,2,3,5,7) "
+                    + "and endtime>='2026-10-01' and endtime<'2026-11-01' and endtime <= DATE_SUB(CURDATE(), INTERVAL 7 DAY) "
+                    + "and leavehospitaldistrictcode in ('40003047','40003048') group by leavehospitaldistrictcode, leavehospitaldistrictname");
+            out.flush();
+        }
+        System.out.println("done");
+    }
+
+    static void run(Connection c, PrintWriter out, String sql) {
+        out.println("\n--- " + sql);
+        try (Statement st = c.createStatement(); ResultSet rs = st.executeQuery(sql)) {
+            ResultSetMetaData md = rs.getMetaData();
+            int n = md.getColumnCount();
+            StringBuilder head = new StringBuilder();
+            for (int i = 1; i <= n; i++) head.append(md.getColumnLabel(i)).append(i == n ? "" : " | ");
+            out.println(head);
+            int rows = 0;
+            while (rs.next() && rows < 40) {
+                StringBuilder line = new StringBuilder();
+                for (int i = 1; i <= n; i++) line.append(rs.getString(i)).append(i == n ? "" : " | ");
+                out.println(line);
+                rows++;
+            }
+        } catch (Exception e) {
+            out.println("SQL ERROR: " + e.getMessage());
+        }
+    }
+}
diff --git a/tmp-probe4/Probe18.class b/tmp-probe4/Probe18.class
new file mode 100644
index 0000000..446edf1
--- /dev/null
+++ b/tmp-probe4/Probe18.class
Binary files differ
diff --git a/tmp-probe4/Probe18.java b/tmp-probe4/Probe18.java
new file mode 100644
index 0000000..0fe3cbc
--- /dev/null
+++ b/tmp-probe4/Probe18.java
@@ -0,0 +1,46 @@
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.sql.*;
+
+public class Probe18 {
+    static final String URL = "jdbc:mysql://haiershi.a1.luyouxia.net:23844/smartor_sltd"
+            + "?useUnicode=true&characterEncoding=utf8&useSSL=false"
+            + "&serverTimezone=GMT%2B8&connectTimeout=15000&socketTimeout=90000";
+
+    public static void main(String[] args) throws Exception {
+        Class.forName("com.mysql.cj.jdbc.Driver");
+        try (Connection c = DriverManager.getConnection(URL, "smartor", "Smartor.2023");
+             PrintWriter out = new PrintWriter(new OutputStreamWriter(
+                     new FileOutputStream("probe18.txt"), StandardCharsets.UTF_8))) {
+            String base = "from service_subtask where del_flag='0' and service_type='2' and sendstate in (1,2,3,5,7) "
+                    + "and leavehospitaldistrictcode='40003047' and endtime>='2026-10-01' ";
+            run(c, out, "select "
+                    + "(select count(*) " + base + "and endtime <= DATE_SUB(CURDATE(), INTERVAL 7 DAY)) old_cut, "
+                    + "(select count(*) " + base + "and endtime < DATE_ADD(DATE_SUB(CURDATE(), INTERVAL 7 DAY), INTERVAL 1 DAY)) new_cut, "
+                    + "(select count(*) " + base + "and endtime >= '2026-10-21' and endtime < '2026-10-22') on_1021");
+            run(c, out, "select DATE(endtime) d, count(*) cnt " + base + "and endtime < DATE_ADD(DATE_SUB(CURDATE(), INTERVAL 7 DAY), INTERVAL 1 DAY) group by DATE(endtime) order by d desc limit 6");
+            out.flush();
+        }
+        System.out.println("done");
+    }
+
+    static void run(Connection c, PrintWriter out, String sql) {
+        out.println("\n--- " + sql);
+        try (Statement st = c.createStatement(); ResultSet rs = st.executeQuery(sql)) {
+            ResultSetMetaData md = rs.getMetaData();
+            int n = md.getColumnCount();
+            StringBuilder head = new StringBuilder();
+            for (int i = 1; i <= n; i++) head.append(md.getColumnLabel(i)).append(i == n ? "" : " | ");
+            out.println(head);
+            int rows = 0;
+            while (rs.next() && rows < 20) {
+                StringBuilder line = new StringBuilder();
+                for (int i = 1; i <= n; i++) line.append(rs.getString(i)).append(i == n ? "" : " | ");
+                out.println(line);
+                rows++;
+            }
+        } catch (Exception e) {
+            out.println("SQL ERROR: " + e.getMessage());
+        }
+    }
+}
diff --git a/tmp-probe4/probe17.txt b/tmp-probe4/probe17.txt
new file mode 100644
index 0000000..091c305
--- /dev/null
+++ b/tmp-probe4/probe17.txt
@@ -0,0 +1,16 @@
+
+--- select config_key, config_value from sys_config where config_key='sys.authority.campus.all'
+config_key | config_value
+
+--- select d.dept_code, d.dept_name, d.campusid, count(*) dup from sys_dept d inner join sys_user_dept ud on d.dept_code = ud.dept_code where d.del_flag=0 and ud.del_flag=0 and d.orgid='20001001' and ud.orgid='20001001' and ud.user_id=2609 and d.dept_type='2' group by d.dept_code, d.dept_name, d.campusid
+dept_code | dept_name | campusid | dup
+40003047 | 2-6涓滅梾鍖猴紙楠ㄤ激涓績涓�锛� | 30001002 | 40
+
+--- select d.dept_code, d.dept_name, d.campusid from sys_dept d inner join sys_user_dept ud on d.dept_code = ud.dept_code where d.del_flag=0 and ud.del_flag=0 and d.orgid='20001001' and ud.orgid='20001001' and d.campusid='30001002' and ud.user_id=2609 and d.dept_type='2' group by d.dept_code, d.dept_name, d.campusid
+dept_code | dept_name | campusid
+40003047 | 2-6涓滅梾鍖猴紙楠ㄤ激涓績涓�锛� | 30001002
+
+--- select leavehospitaldistrictcode, leavehospitaldistrictname, count(*) cnt from service_subtask where del_flag='0' and service_type='2' and sendstate in (1,2,3,5,7) and endtime>='2026-10-01' and endtime<'2026-11-01' and endtime <= DATE_SUB(CURDATE(), INTERVAL 7 DAY) and leavehospitaldistrictcode in ('40003047','40003048') group by leavehospitaldistrictcode, leavehospitaldistrictname
+leavehospitaldistrictcode | leavehospitaldistrictname | cnt
+40003047 | 2-6涓滅梾鍖猴紙楠ㄤ激涓績涓�锛� | 90
+40003048 | 2-6瑗跨梾鍖猴紙楠ㄤ激涓績浜岋級 | 25
diff --git a/tmp-probe4/probe18.txt b/tmp-probe4/probe18.txt
new file mode 100644
index 0000000..8b4fa12
--- /dev/null
+++ b/tmp-probe4/probe18.txt
@@ -0,0 +1,13 @@
+
+--- select (select count(*) from service_subtask where del_flag='0' and service_type='2' and sendstate in (1,2,3,5,7) and leavehospitaldistrictcode='40003047' and endtime>='2026-10-01' and endtime <= DATE_SUB(CURDATE(), INTERVAL 7 DAY)) old_cut, (select count(*) from service_subtask where del_flag='0' and service_type='2' and sendstate in (1,2,3,5,7) and leavehospitaldistrictcode='40003047' and endtime>='2026-10-01' and endtime < DATE_ADD(DATE_SUB(CURDATE(), INTERVAL 7 DAY), INTERVAL 1 DAY)) new_cut, (select count(*) from service_subtask where del_flag='0' and service_type='2' and sendstate in (1,2,3,5,7) and leavehospitaldistrictcode='40003047' and endtime>='2026-10-01' and endtime >= '2026-10-21' and endtime < '2026-10-22') on_1021
+old_cut | new_cut | on_1021
+90 | 99 | 9
+
+--- select DATE(endtime) d, count(*) cnt from service_subtask where del_flag='0' and service_type='2' and sendstate in (1,2,3,5,7) and leavehospitaldistrictcode='40003047' and endtime>='2026-10-01' and endtime < DATE_ADD(DATE_SUB(CURDATE(), INTERVAL 7 DAY), INTERVAL 1 DAY) group by DATE(endtime) order by d desc limit 6
+d | cnt
+2026-10-21 | 9
+2026-10-20 | 7
+2026-10-19 | 10
+2026-10-18 | 2
+2026-10-17 | 3
+2026-10-16 | 6
diff --git a/tmp-probe9/Probe42.class b/tmp-probe9/Probe42.class
new file mode 100644
index 0000000..1b02420
--- /dev/null
+++ b/tmp-probe9/Probe42.class
Binary files differ
diff --git a/tmp-probe9/Probe42.java b/tmp-probe9/Probe42.java
new file mode 100644
index 0000000..da824ca
--- /dev/null
+++ b/tmp-probe9/Probe42.java
@@ -0,0 +1,45 @@
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.sql.*;
+
+public class Probe42 {
+    static final String URL = "jdbc:mysql://haiershi.a1.luyouxia.net:23844/smartor_sltd"
+            + "?useUnicode=true&characterEncoding=utf8&useSSL=false"
+            + "&serverTimezone=GMT%2B8&connectTimeout=15000&socketTimeout=90000";
+
+    public static void main(String[] args) throws Exception {
+        Class.forName("com.mysql.cj.jdbc.Driver");
+        try (Connection c = DriverManager.getConnection(URL, "smartor", "Smartor.2023");
+             PrintWriter out = new PrintWriter(new OutputStreamWriter(
+                     new FileOutputStream("probe42.txt"), StandardCharsets.UTF_8))) {
+            String base = "from service_subtask where del_flag='0' and endtime >= '2026-10-01' and endtime < '2026-10-31' and leavehospitaldistrictcode='40003047' ";
+            run(c, out, "select count(*) db_total " + base);
+            run(c, out, "select service_type, visit_count, count(*) cnt " + base + "group by service_type, visit_count order by service_type, visit_count");
+            run(c, out, "select count(*) page_like " + base + "and service_type='2' and visit_count=1");
+            run(c, out, "select count(*) page_like_no_vc " + base + "and service_type='2'");
+            run(c, out, "select count(*) all_status " + base + "and service_type='2' and visit_count=1 and sendstate in (1,2,3,4,5,6,7)");
+            out.flush();
+        }
+        System.out.println("done");
+    }
+
+    static void run(Connection c, PrintWriter out, String sql) {
+        out.println("\n--- " + sql);
+        try (Statement st = c.createStatement(); ResultSet rs = st.executeQuery(sql)) {
+            ResultSetMetaData md = rs.getMetaData();
+            int n = md.getColumnCount();
+            StringBuilder head = new StringBuilder();
+            for (int i = 1; i <= n; i++) head.append(md.getColumnLabel(i)).append(i == n ? "" : " | ");
+            out.println(head);
+            int rows = 0;
+            while (rs.next() && rows < 20) {
+                StringBuilder line = new StringBuilder();
+                for (int i = 1; i <= n; i++) line.append(rs.getString(i)).append(i == n ? "" : " | ");
+                out.println(line);
+                rows++;
+            }
+        } catch (Exception e) {
+            out.println("SQL ERROR: " + e.getMessage());
+        }
+    }
+}
diff --git a/tmp-probe9/probe42.txt b/tmp-probe9/probe42.txt
new file mode 100644
index 0000000..4876af3
--- /dev/null
+++ b/tmp-probe9/probe42.txt
@@ -0,0 +1,21 @@
+
+--- select count(*) db_total from service_subtask where del_flag='0' and endtime >= '2026-10-01' and endtime < '2026-10-31' and leavehospitaldistrictcode='40003047' 
+db_total
+119
+
+--- select service_type, visit_count, count(*) cnt from service_subtask where del_flag='0' and endtime >= '2026-10-01' and endtime < '2026-10-31' and leavehospitaldistrictcode='40003047' group by service_type, visit_count order by service_type, visit_count
+service_type | visit_count | cnt
+2 | 1 | 110
+4 | 1 | 9
+
+--- select count(*) page_like from service_subtask where del_flag='0' and endtime >= '2026-10-01' and endtime < '2026-10-31' and leavehospitaldistrictcode='40003047' and service_type='2' and visit_count=1
+page_like
+110
+
+--- select count(*) page_like_no_vc from service_subtask where del_flag='0' and endtime >= '2026-10-01' and endtime < '2026-10-31' and leavehospitaldistrictcode='40003047' and service_type='2'
+page_like_no_vc
+110
+
+--- select count(*) all_status from service_subtask where del_flag='0' and endtime >= '2026-10-01' and endtime < '2026-10-31' and leavehospitaldistrictcode='40003047' and service_type='2' and visit_count=1 and sendstate in (1,2,3,4,5,6,7)
+all_status
+110
diff --git a/tmp-svy4/Probe41.class b/tmp-svy4/Probe41.class
new file mode 100644
index 0000000..c0956bb
--- /dev/null
+++ b/tmp-svy4/Probe41.class
Binary files differ
diff --git a/tmp-svy4/Probe41.java b/tmp-svy4/Probe41.java
new file mode 100644
index 0000000..9a81873
--- /dev/null
+++ b/tmp-svy4/Probe41.java
@@ -0,0 +1,45 @@
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.sql.*;
+
+public class Probe41 {
+    static final String URL = "jdbc:mysql://haiershi.a1.luyouxia.net:23844/smartor_sltd"
+            + "?useUnicode=true&characterEncoding=utf8&useSSL=false"
+            + "&serverTimezone=GMT%2B8&connectTimeout=15000&socketTimeout=90000";
+
+    public static void main(String[] args) throws Exception {
+        Class.forName("com.mysql.cj.jdbc.Driver");
+        try (Connection c = DriverManager.getConnection(URL, "smartor", "Smartor.2023");
+             PrintWriter out = new PrintWriter(new OutputStreamWriter(
+                     new FileOutputStream("probe41.txt"), StandardCharsets.UTF_8))) {
+            run(c, out, "select d.questiontext, sum(case when d.asrtext is null or trim(d.asrtext)='' then 1 else 0 end) blank, count(*) total "
+                    + "from service_subtask s join service_subtask_detail d on d.sub_id=s.id "
+                    + "where s.del_flag='0' and d.del_flag='0' and s.service_type in ('6','14') and s.sendstate=6 "
+                    + "and s.finishtime >= '2026-07-29' and s.finishtime < '2026-10-29' "
+                    + "and d.id = (select max(d2.id) from service_subtask_detail d2 where d2.sub_id=d.sub_id and d2.questiontext <=> d.questiontext and d2.del_flag='0') "
+                    + "group by d.questiontext order by blank desc");
+            out.flush();
+        }
+        System.out.println("done");
+    }
+
+    static void run(Connection c, PrintWriter out, String sql) {
+        out.println("\n--- " + sql);
+        try (Statement st = c.createStatement(); ResultSet rs = st.executeQuery(sql)) {
+            ResultSetMetaData md = rs.getMetaData();
+            int n = md.getColumnCount();
+            StringBuilder head = new StringBuilder();
+            for (int i = 1; i <= n; i++) head.append(md.getColumnLabel(i)).append(i == n ? "" : " | ");
+            out.println(head);
+            int rows = 0;
+            while (rs.next() && rows < 30) {
+                StringBuilder line = new StringBuilder();
+                for (int i = 1; i <= n; i++) line.append(rs.getString(i)).append(i == n ? "" : " | ");
+                out.println(line);
+                rows++;
+            }
+        } catch (Exception e) {
+            out.println("SQL ERROR: " + e.getMessage());
+        }
+    }
+}
diff --git a/tmp-svy4/probe41.txt b/tmp-svy4/probe41.txt
new file mode 100644
index 0000000..daa05c4
--- /dev/null
+++ b/tmp-svy4/probe41.txt
@@ -0,0 +1,28 @@
+
+--- select d.questiontext, sum(case when d.asrtext is null or trim(d.asrtext)='' then 1 else 0 end) blank, count(*) total from service_subtask s join service_subtask_detail d on d.sub_id=s.id where s.del_flag='0' and d.del_flag='0' and s.service_type in ('6','14') and s.sendstate=6 and s.finishtime >= '2026-07-29' and s.finishtime < '2026-10-29' and d.id = (select max(d2.id) from service_subtask_detail d2 where d2.sub_id=d.sub_id and d2.questiontext <=> d.questiontext and d2.del_flag='0') group by d.questiontext order by blank desc
+questiontext | blank | total
+璇锋偍鐣欎笅瀹濊吹鐨勬剰瑙�/寤鸿 | 6 | 25
+鎮ㄥ鎴戦櫌鎶曡瘔婊″鐞嗘弧涓嶆弧鎰忥紵 | 1 | 8
+绐楀彛/鍚庡嫟/淇濆畨浜哄憳鏈嶅姟 | 0 | 17
+鎮ㄥ鎴戦櫌鐭ユ儏鍛婄煡婊′笉婊℃剰锛� | 0 | 8
+鎮ㄥ渚挎皯鏈嶅姟鏄惁婊℃剰 | 0 | 17
+鎮ㄥ鎴戦櫌鏈嶅姟鏁堢巼婊′笉婊℃剰锛� | 0 | 8
+鎸囩ず鐗屻�佸鍖荤墝娓呮绋嬪害 | 0 | 17
+鎮ㄥ鎴戦櫌浼欓鎯呭喌婊′笉婊℃剰锛� | 0 | 8
+闂ㄨ瘖鐜鍗敓/澹伴煶(鍘曟墍銆佺幆澧冨崼鐢熴�佸櫔闊崇瓑) | 0 | 17
+鎮ㄥ鎴戦櫌鏁翠綋鐜婊′笉婊℃剰锛� | 0 | 8
+鎸傚彿棰勭害/涓撳淇℃伅鑾峰彇 | 0 | 17
+鐪嬬梾鏈熼棿锛屾偍鐨勬姳鎬ㄥ拰涓嶆弧鑳藉惁鍙婃椂寰楀埌鍥炲簲锛� | 0 | 17
+鎸傚彿/灏辫瘖/妫�楠�/妫�鏌ョ瓑鐜妭绛夊�欐椂闂� | 0 | 17
+鎬讳綋婊℃剰搴� | 0 | 17
+鎮ㄦ槸鍚﹀悜浜插弸鎺ㄨ崘杩欏鍖婚櫌 | 0 | 8
+鎮ㄥ鍖绘姢璇婄枟杩囩▼鏄惁婊℃剰*(鐪嬭瘖鏃堕棿/鍋ュ悍瀹f暀/鎵嬪崼鐢�/闅愮淇濇姢) | 0 | 17
+鎮ㄦ槸鍚︿細鍚戜翰鍙嬫帹鑽愯繖瀹跺尰闄� | 0 | 17
+鍖荤敓鏈嶅姟
+ | 0 | 17
+鎶ゅ+鏈嶅姟 | 0 | 17
+鎮ㄥ鎴戦櫌宸ヤ綔浜哄憳鐨勬湇鍔¤川閲忔弧涓嶆弧鎰忥紵 | 0 | 8
+妫�鏌ヤ汉鍛樻湇鍔★紙B瓒�/蹇冪數鍥�/CT/纾佸叡鎸�/X绾�/鍐呴暅绛夛級 | 0 | 17
+鎮ㄥ鎴戦櫌宸ヤ綔浜哄憳鐨勬湇鍔℃�佸害婊′笉婊℃剰锛� | 0 | 8
+鑽埧浜哄憳鏈嶅姟 | 0 | 17
+鎮ㄥ鎴戦櫌闅愮淇濇姢婊′笉婊℃剰锛� | 0 | 8
diff --git "a/\351\252\250\347\247\221\344\270\255\345\277\203\344\270\200\347\227\205\345\214\272_\345\207\272\351\231\242\346\225\260\346\215\256\347\273\237\350\256\241_20260430-20261023.xlsx" "b/\351\252\250\347\247\221\344\270\255\345\277\203\344\270\200\347\227\205\345\214\272_\345\207\272\351\231\242\346\225\260\346\215\256\347\273\237\350\256\241_20260430-20261023.xlsx"
new file mode 100644
index 0000000..82b4ef7
--- /dev/null
+++ "b/\351\252\250\347\247\221\344\270\255\345\277\203\344\270\200\347\227\205\345\214\272_\345\207\272\351\231\242\346\225\260\346\215\256\347\273\237\350\256\241_20260430-20261023.xlsx"
Binary files differ

--
Gitblit v1.9.3