WXL (wul)
昨天 d3c60e18b95b50751f8088fa2d23cd8ff7f173bc
测试完成
已删除2个文件
已重命名2个文件
已修改17个文件
1552 ■■■■■ 文件已修改
dist (2).zip 补丁 | 查看 | 原始文档 | blame | 历史
dist.zip 补丁 | 查看 | 原始文档 | blame | 历史
src/api/smartor/smstemplet.js 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Assistant/index.vue 382 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/followvisit/HistoricalFollow/index.vue 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/followvisit/discharge/index.vue 164 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/followvisit/record/detailpage/MergeAndModify.vue 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/followvisit/record/detailpage/index.vue 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/knowledge/questionbank/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/knowledge/questionbank/particulars/index.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/knowledge/questionnaire/smsConfig/index.vue 735 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/outsideChainwtnew.vue 76 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/repositoryai/intention/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/repositoryai/verbaltrick/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/repositoryai/verbaltrick/particulars/index.vue 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/sfstatistics/percentage/components/FirstFollowUp.vue 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/sfstatistics/percentage/components/SecondFollowUp.vue 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
vue.config.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
外链.zip 补丁 | 查看 | 原始文档 | blame | 历史
随访通用 (2).zip 补丁 | 查看 | 原始文档 | blame | 历史
随访通用.zip 补丁 | 查看 | 原始文档 | blame | 历史
dist (2).zip
Binary files differ
dist.zip
Binary files differ
src/api/smartor/smstemplet.js
@@ -4,8 +4,8 @@
export function listSmstemplet(query) {
  return request({
    url: '/smartor/smstemplet/list',
    method: 'get',
    params: query
    method: 'post',
    data: query
  })
}
@@ -20,7 +20,7 @@
// æ–°å¢žçŸ­ä¿¡æ¨¡æ¿
export function addSmstemplet(data) {
  return request({
    url: '/smartor/smstemplet',
    url: '/smartor/smstemplet/add',
    method: 'post',
    data: data
  })
src/components/Assistant/index.vue
@@ -175,29 +175,99 @@
    <el-dialog
      title="短信发送"
      :visible.sync="smsDialogVisible"
      width="500px"
      width="800px"
      :close-on-click-modal="false"
      append-to-body
    >
      <el-form ref="smsForm" :model="smsForm" label-width="100px">
        <el-form-item label="患者名称">
          <el-input v-model="smsForm.sendname" readonly></el-input>
          <el-input v-model="smsForm.sendname"></el-input>
        </el-form-item>
        <el-form-item label="年龄">
          <el-input v-model="smsForm.age" readonly></el-input>
          <el-input v-model="smsForm.age"></el-input>
        </el-form-item>
        <el-form-item label="电话">
          <el-input v-model="smsForm.telcode" readonly></el-input>
          <el-input v-model="smsForm.telcode"></el-input>
        </el-form-item>
        <el-form-item label="科室">
          <el-input v-model="smsForm.deptname" readonly></el-input>
          <el-input v-model="smsForm.deptname"></el-input>
        </el-form-item>
        <el-form-item label="病区">
          <el-input
            v-model="smsForm.leavehospitaldistrictname"
            readonly
          ></el-input>
          <el-input v-model="smsForm.leavehospitaldistrictname"></el-input>
        </el-form-item>
        <!-- çŸ­ä¿¡å‘送对话框 - æ¨¡æ¿é€‰æ‹©åŒºåŸŸï¼ˆå¢žå¼ºç‰ˆï¼‰ -->
        <el-form-item label="选择模板">
          <el-row :gutter="10">
            <el-col :span="7">
              <el-select
                v-model="templateFilterDept"
                placeholder="按科室"
                filterable
                clearable
                style="width: 100%"
                @change="filterTemplates"
              >
                <el-option
                  v-for="dept in departmentOptions"
                  :key="dept.value"
                  :label="dept.label"
                  :value="dept.value"
                />
              </el-select>
            </el-col>
            <el-col :span="7">
              <el-select
                v-model="templateFilterWard"
                placeholder="按病区"
                filterable
                clearable
                style="width: 100%"
                @change="filterTemplates"
              >
                <el-option
                  v-for="ward in wardOptions"
                  :key="ward.value"
                  :label="ward.label"
                  :value="ward.value"
                />
              </el-select>
            </el-col>
            <el-col :span="10">
              <el-select
                v-model="selectedTemplateId"
                placeholder="请选择短信模板"
                filterable
                clearable
                style="width: 100%"
                @change="handleTemplateSelect"
              >
                <el-option
                  v-for="tmpl in filteredTemplateOptions"
                  :key="tmpl.templetid"
                  :label="`【${tmpl.templetno}】${tmpl.templetname}`"
                  :value="tmpl.templetid"
                >
                  <span style="float: left">{{ tmpl.templetname }}</span>
                  <span style="float: right; color: #909399; font-size: 12px">
                    {{ tmpl.deptName || "通用" }} /
                    {{ tmpl.wardName || "全部" }}
                  </span>
                </el-option>
              </el-select>
            </el-col>
            <el-col :span="6">
              <el-button
                type="primary"
                plain
                icon="el-icon-plus"
                @click="openQuickCreateTemplate"
              >
                æ–°å»º
              </el-button>
            </el-col>
          </el-row>
        </el-form-item>
        <el-form-item label="短信内容">
          <el-input
            type="textarea"
@@ -215,13 +285,109 @@
          ç¡®è®¤å‘送
        </el-button>
      </div>
      <!-- å†…嵌:快速新建模板对话框 -->
      <!-- å¿«é€Ÿæ–°å»ºæ¨¡æ¿å¯¹è¯æ¡†ï¼ˆå¢žå¼ºç‰ˆï¼‰ -->
      <el-dialog
        title="新建短信模板"
        :visible.sync="quickCreateVisible"
        width="500px"
        append-to-body
        :close-on-click-modal="false"
      >
        <el-form
          :model="quickTemplateForm"
          :rules="quickTemplateRules"
          ref="quickTemplateForm"
          label-width="90px"
        >
          <el-form-item label="模板编号" prop="templetno">
            <el-input
              v-model="quickTemplateForm.templetno"
              placeholder="请输入模板编号"
            />
          </el-form-item>
          <el-form-item label="模板名称" prop="templetname">
            <el-input
              v-model="quickTemplateForm.templetname"
              placeholder="请输入模板名称"
            />
          </el-form-item>
          <el-form-item label="所属科室">
            <el-select
              v-model="quickTemplateForm.deptCode"
              placeholder="请选择科室"
              filterable
              clearable
              style="width: 100%"
              @change="
                (val) => {
                  const dept = departmentOptions.find((d) => d.value === val);
                  quickTemplateForm.deptName = dept ? dept.label : '';
                }
              "
            >
              <el-option
                v-for="dept in departmentOptions"
                :key="dept.value"
                :label="dept.label"
                :value="dept.value"
              />
            </el-select>
          </el-form-item>
          <el-form-item label="所属病区">
            <el-select
              v-model="quickTemplateForm.wardCode"
              placeholder="请选择病区"
              filterable
              clearable
              style="width: 100%"
            >
              <el-option
                v-for="ward in wardOptions"
                :key="ward.value"
                :label="ward.label"
                :value="ward.value"
              />
            </el-select>
          </el-form-item>
          <el-form-item label="模板内容" prop="templetcontent">
            <el-input
              v-model="quickTemplateForm.templetcontent"
              type="textarea"
              :rows="4"
              placeholder="请输入短信模板内容"
              maxlength="500"
              show-word-limit
            />
          </el-form-item>
        </el-form>
        <div slot="footer">
          <el-button @click="quickCreateVisible = false">取 æ¶ˆ</el-button>
          <el-button
            type="primary"
            @click="submitQuickTemplate"
            :loading="quickCreateLoading"
          >
            ä¿å­˜å¹¶ä½¿ç”¨
          </el-button>
        </div>
      </el-dialog>
    </el-dialog>
  </div>
</template>
<script>
import { getCurrentUserServiceSubtaskCount } from "@/api/AiCentre/index";
import { sendMsg } from "@/api/AiCentre/index";
import {
  getCurrentUserServiceSubtaskCount,
  sendMsg,
} from "@/api/AiCentre/index";
import {
  listSmstemplet,
  getSmstemplet,
  addSmstemplet,
  updateSmstemplet,
  delSmstemplet,
} from "@/api/smartor/smstemplet";
export default {
  name: "FloatBall",
@@ -269,6 +435,34 @@
      hideTimer: null,
      updateTime: "",
      roles: null,
      templateOptions: [], // æ¨¡æ¿ä¸‹æ‹‰åˆ—表
      selectedTemplateId: "", // é€‰ä¸­çš„æ¨¡æ¿ID
      templateLoading: false, // æ¨¡æ¿åˆ—表加载状态
      // æ¨¡æ¿ç­›é€‰
      templateFilterDept: "",
      templateFilterWard: "", // æ–°å¢žï¼šç—…区筛选
      filteredTemplateOptions: [],
      // ç§‘室选项(从 Vuex èŽ·å–ï¼‰
      departmentOptions: [],
      // æ–°å¢žï¼šç—…区选项(从 Vuex èŽ·å–ï¼‰
      wardOptions: [],
      // å¿«é€Ÿæ–°å»ºæ¨¡æ¿
      quickCreateVisible: false,
      quickCreateLoading: false,
      quickTemplateForm: {
        templetno: "",
        templetname: "",
        templetcontent: "",
      },
      quickTemplateRules: {
        templetname: [
          { required: true, message: "请输入模板名称", trigger: "blur" },
        ],
        templetcontent: [
          { required: true, message: "请输入模板内容", trigger: "blur" },
        ],
      },
      // çŸ­ä¿¡å‘送对话框
      // smsDialogVisible: false,
      smsLoading: false, // âœ… æ–°å¢žåŠ è½½çŠ¶æ€
@@ -367,7 +561,8 @@
  },
  watch: {
    // âœ… ç›‘听 Vuex å¯¹è¯æ¡†çŠ¶æ€
    "$store.state.sms.smsDialogVisible"(val) {
    "$store.state.sms.smsDialogVisible": {
      handler(val) {
      if (val) {
        const patientData = this.$store.state.sms.patientData;
        this.smsForm = { ...patientData };
@@ -379,7 +574,12 @@
          this.isHidden = false;
          clearTimeout(this.hideTimer);
        }
          // â˜…★★ å…³é”®ä¿®å¤ï¼šåœ¨è¿™é‡Œåˆå§‹åŒ–模板相关数据 â˜…★★
          this.initTemplateData();
      }
      },
      immediate: false,
    },
  },
  mounted() {
@@ -404,6 +604,33 @@
  },
  methods: {
    initTemplateData() {
      // åˆå§‹åŒ–科室选项
      if (this.$store.getters.belongDepts) {
        this.departmentOptions = this.$store.getters.belongDepts.map(
          (dept) => ({
            label: dept.deptName,
            value: dept.deptCode,
          })
        );
      }
      // â˜…★★ æ–°å¢žï¼šåˆå§‹åŒ–病区选项 â˜…★★
      if (this.$store.getters.belongWards) {
        this.wardOptions = this.$store.getters.belongWards.map((ward) => ({
          label: ward.districtName,
          value: ward.districtCode,
        }));
      }
      // é‡ç½®ç­›é€‰
      this.templateFilterDept = "";
      this.templateFilterWard = ""; // æ–°å¢ž
      this.selectedTemplateId = "";
      // åŠ è½½æ¨¡æ¿åˆ—è¡¨
      this.loadTemplates();
    },
    toggleExpand() {
      this.isExpanded = !this.isExpanded;
      if (this.isExpanded) {
@@ -412,7 +639,85 @@
        this.updateStats();
      }
    },
    async loadTemplates() {
      this.templateLoading = true;
      try {
        // const { listSmstemplet } = await import("@/api/smartor/smstemplet");
        const res = await listSmstemplet({ pageNum: 1, pageSize: 999 });
        this.templateOptions = res.rows || [];
        this.filterTemplates(); // åº”用筛选
      } catch (error) {
        console.error("加载短信模板失败:", error);
        this.templateOptions = [];
        this.filteredTemplateOptions = [];
      } finally {
        this.templateLoading = false;
      }
    },
    handleTemplateSelect(templateId) {
      if (!templateId) {
        this.smsContent = "";
        return;
      }
      const selected = this.templateOptions.find(
        (t) => t.templetid === templateId
      );
      if (selected) {
        this.smsContent = selected.templetcontent || "";
      }
    },
    openQuickCreateTemplate() {
      this.quickTemplateForm = {
        templetno: "",
        templetname: "",
        templetcontent: "",
      };
      this.quickCreateVisible = true;
      this.$nextTick(() => {
        if (this.$refs.quickTemplateForm) {
          this.$refs.quickTemplateForm.clearValidate();
        }
      });
    },
    /**
     * æäº¤å¿«é€Ÿæ–°å»ºæ¨¡æ¿
     */
    async submitQuickTemplate() {
      this.$refs.quickTemplateForm.validate(async (valid) => {
        if (!valid) return;
        this.quickCreateLoading = true;
        try {
          // const { addSmstemplet } = await import("@/api/smartor/smstemplet");
          const res = await addSmstemplet(this.quickTemplateForm);
          if (res.code === 200) {
            this.$modal.msgSuccess("模板创建成功");
            // åˆ·æ–°æ¨¡æ¿åˆ—表
            await this.loadTemplates();
            // è‡ªåŠ¨é€‰ä¸­åˆšåˆ›å»ºçš„æ¨¡æ¿
            const newTmpl = this.templateOptions.find(
              (t) => t.templetname === this.quickTemplateForm.templetname
            );
            if (newTmpl) {
              this.selectedTemplateId = newTmpl.templetid;
              this.smsContent = newTmpl.templetcontent;
            }
            this.quickCreateVisible = false;
          } else {
            this.$modal.msgError(res.msg || "创建失败");
          }
        } catch (error) {
          console.error("创建模板失败:", error);
          this.$modal.msgError("创建失败,请稍后重试");
        } finally {
          this.quickCreateLoading = false;
        }
      });
    },
    handleMouseEnter() {
      this.isHovering = true;
      if (this.autoHide) {
@@ -542,18 +847,54 @@
      }
    },
    // æ‰“开短信发送对话框
    openSmsDialog() {
      // ä»Žæ‚¬æµ®çƒå†…部打开时,清空表单(因为没有选中患者)
    /**
     * æ”¹é€ åŽŸæœ‰çš„ openSmsDialog æ–¹æ³•
     */
    openSmsDialog(patientData = {}) {
      // é‡ç½®ç­›é€‰
      this.templateFilterDept = "";
      // é‡ç½®é€‰æ‹©
      this.selectedTemplateId = "";
      this.smsContent = patientData.smsTemplate || "";
      // åŠ è½½æ¨¡æ¿åˆ—è¡¨
      this.loadTemplates();
      // æ‰“开对话框(通过 Vuex)
      this.$store.dispatch("sms/openSmsDialog", {
        name: "",
        age: "",
        phone: "",
        deptName: "",
        wardName: "",
        smsTemplate: "",
        name: patientData.name || "",
        age: patientData.age || "",
        phone: patientData.phone || "",
        deptName: patientData.deptName || "",
        wardName: patientData.wardName || "",
        smsTemplate: patientData.smsTemplate || "",
      });
    },
    // æ–°å¢žï¼šç­›é€‰æ¨¡æ¿
    filterTemplates() {
      let filtered = [...this.templateOptions];
      // æŒ‰ç§‘室筛选
      if (this.templateFilterDept) {
        filtered = filtered.filter(
          (tmpl) => tmpl.deptCode === this.templateFilterDept || !tmpl.deptCode
        );
      }
      // â˜…★★ æ–°å¢žï¼šæŒ‰ç—…区筛选 â˜…★★
      if (this.templateFilterWard) {
        filtered = filtered.filter(
          (tmpl) => tmpl.wardCode === this.templateFilterWard || !tmpl.wardCode
        );
      }
      this.filteredTemplateOptions = filtered;
      // æ¸…空已选
      this.selectedTemplateId = "";
      this.smsContent = "";
    },
    // å‘送短信
    async sendSms() {
      if (!this.smsContent.trim()) {
@@ -586,6 +927,7 @@
        this.$modal.msgError("发送失败,请稍后重试");
      } finally {
        this.smsLoading = false;
        this.selectedTemplateId = "";
      }
    },
    async updateStats() {
src/views/followvisit/HistoricalFollow/index.vue
@@ -10,7 +10,7 @@
        size="small"
        :inline="true"
        v-show="showSearch"
        label-width="98px"
        label-width="110px"
      >
        <el-form-item label="任务名称">
          <el-input
@@ -30,6 +30,18 @@
            v-model="topqueryParams.leavediagname"
            placeholder="请输入诊断名称"
          ></el-input>
        </el-form-item>
        <el-form-item label="出院时间范围" required>
          <el-date-picker
            type="daterange"
            v-model="TimeRange"
            range-separator="至"
            start-placeholder="开始时间"
            end-placeholder="结束时间"
            value-format="yyyy-MM-dd"
            placeholder="选择时间范围"
          >
          </el-date-picker>
        </el-form-item>
        <el-form-item label="随访状态" prop="status">
          <el-cascader
@@ -513,7 +525,7 @@
  historservelist,
  buidegetTasklist,
  query360PatInfo,
  query360PatInfonh
  query360PatInfonh,
} from "@/api/AiCentre/index";
import Treeselect from "@riophae/vue-treeselect";
import store from "@/store";
@@ -550,8 +562,8 @@
      deptName: undefined,
      // é»˜è®¤å¯†ç 
      initPassword: undefined,
      // æ—¥æœŸèŒƒå›´
      dateRange: [],
      TimeRange: [],
      // å²—位选项
      postOptions: [],
      ruleForm: {
@@ -1000,8 +1012,8 @@
          store.getters.belongWards.map((obj) => obj.districtCode);
      }
      this.topqueryParams.pageNum = 1;
      this.topqueryParams.startOutHospTime = this.dateRange[0];
      this.topqueryParams.endOutHospTime = this.dateRange[1];
      this.topqueryParams.startOutHospTime = this.TimeRange[0];
      this.topqueryParams.endOutHospTime = this.TimeRange[1];
      this.getList(refresh);
    },
@@ -1057,7 +1069,7 @@
    },
    /** é‡ç½®æŒ‰é’®æ“ä½œ */
    resetQuery() {
      this.dateRange = [];
      this.TimeRange = [];
      this.topqueryParams = {
        pageNum: 1,
        pageSize: 10,
src/views/followvisit/discharge/index.vue
@@ -243,12 +243,27 @@
          </div>
        </el-col>
      </el-row>
      <div class="selected-info">
        å·²é€‰ä¸­
        <span style="color: #409eff; font-weight: bold">{{
          getSelectedCount()
        }}</span>
        æ¡æ•°æ®
        <el-button
          v-if="getSelectedCount() > 0"
          type="text"
          @click="clearAllSelection"
        >
          æ¸…除选中
        </el-button>
      </div>
      <el-table
        v-loading="loading"
        ref="userform"
        :data="userList"
        :row-class-name="tableRowClassName"
        @selection-change="handleSelectionChange"
        @select-all="handleSelectAll"
      >
        <el-table-column type="selection" width="50" align="center" />
        <el-table-column
@@ -1103,6 +1118,7 @@
      inputValue: "",
      preachform: "",
      previewVisible: false, //影像随访预览弹框
      isRestoring: false,
      radio: "",
      radios: [],
      previewtype: 2, //预览影像随访类型
@@ -1110,6 +1126,8 @@
      // æ»¡æ„åº¦è°ƒæŸ¥æ•°æ®
      scoreDialogVisible: false,
      selectedRows: [],
      selectedRowMap: new Map(), // key: row.id, value: row æ•°æ®
      // çº§è”选择器绑定值
      serviceStatusValue: 10,
      cascaderProps: {
@@ -1435,7 +1453,7 @@
  },
  methods: {
    /** æŸ¥è¯¢éšè®¿æœåŠ¡åˆ—è¡¨ */
    getList(refresh) {
    async getList(refresh) {
      // é»˜è®¤å…¨éƒ¨
      if (this.topqueryParams.searchscope == 3) {
        this.topqueryParams.leaveldeptcodes = store.getters.belongDepts.map(
@@ -1448,16 +1466,17 @@
        this.topqueryParams.endSendDateTime = this.formatDateToYYYYMMDDHHMMSS(
          this.getEndOfDay()
        );
      } else {
        // this.topqueryParams.endSendDateTime = null;
      }
      // æŽ¥å—异常跳转
      if (this.errtype) {
        this.topqueryParams.leavehospitaldistrictcodes.push(
          this.leavehospitaldistrictcode
        );
      }
      this.loading = true;
      if (
        this.topqueryParams.leavehospitaldistrictcodes[0] &&
        this.topqueryParams.leaveldeptcodes[0]
@@ -1466,18 +1485,33 @@
      } else {
        this.topqueryParams.deptOrDistrict = 1;
      }
      if (!this.followupAuthority()) {
        this.$message.warning("未配置科室/病区相关权限不可查询");
        this.loading = false;
        return Promise.reject(new Error("无权限查询"));
      }
      getTaskservelist(this.topqueryParams).then((response) => {
      try {
        const response = await getTaskservelist(this.topqueryParams);
        // âœ… ç¬¬ä¸€æ­¥ï¼šå…ˆé”å®šæ¢å¤çŠ¶æ€
        this.isRestoring = true;
        // âœ… ç¬¬äºŒæ­¥ï¼šå†æ›´æ–°æ•°æ®ï¼ˆè¿™ä¼šè§¦å‘ selection-change,但被锁住了)
        this.userList = response.rows[0].serviceSubtaskList;
        this.total = response.total;
        // âœ… ç¬¬ä¸‰æ­¥ï¼šæ¢å¤é€‰ä¸­çŠ¶æ€
        // this.restoreSelection();
        this.$nextTick(() => {
          this.restoreSelection();
        });
        // âœ… ç¬¬å››æ­¥ï¼šå¤„理其他数据
        if (refresh) {
          this.cardlist[0].value =
            Number(response.rows[0].wxsf) + Number(response.rows[0].xsf) || 0;
          // this.cardlist[1].value = response.rows[0].wzx;
          this.cardlist[1].value = response.rows[0].wxsf || 0;
          this.ycvalue = Number(response.rows[0].yc) || 0;
          this.jgvalue = response.rows[0].jg;
@@ -1486,7 +1520,8 @@
          this.cardlist[4].value = response.rows[0].ywc || 0;
          this.yfsvalue = response.rows[0].yfs;
        }
        this.loading = false;
        // âœ… ç¬¬äº”步:处理 preachform ç­‰å…¶ä»–数据
        this.userList.forEach((item) => {
          let idArray = null;
          if (item.endtime) {
@@ -1500,17 +1535,26 @@
            }
            item.preachform = idArray.map((value) => {
              // æŸ¥æ‰¾id对应的对象
              const item = this.checkboxlist.find(
                (item) => item.value == value
              );
              // å¦‚果找到对应的id,返回label值,否则返回null
              return item ? item.label : null;
            });
          }
        });
        this.total = response.total;
        this.loading = false;
        // âœ… ç¬¬å…­æ­¥ï¼šè§£é”
        this.$nextTick(() => {
          this.isRestoring = false;
      });
      } catch (error) {
        console.error("获取列表失败:", error);
        this.loading = false;
        this.isRestoring = false;
      }
    },
    loadData() {
      this.errtype = this.$route.query.errtype;
@@ -1772,11 +1816,17 @@
      this.handleQuery(1);
    },
    handleSelectionChange(rows) {
      console.log(rows, 911);
      // âœ… å¦‚果是恢复选中状态触发的,直接返回
      if (this.isRestoring) {
        console.log("正在恢复选中状态,跳过 handleSelectionChange");
        return;
      }
      this.selectedRows = rows.map((row) => {
        // åˆå§‹åŒ–评分字段
        return {
      console.log("handleSelectionChange è¢«è§¦å‘,选中行数:", rows.length);
      // åªåšæ·»åŠ æ“ä½œ
      rows.forEach((row) => {
        this.selectedRowMap.set(row.id, {
          ...row,
          authenticity: row.authenticity || 0,
          weekFinish: row.weekFinish || 0,
@@ -1786,14 +1836,11 @@
          environment: row.environment || 0,
          doctorSatisfaction: row.doctorSatisfaction || 0,
          nurseSatisfaction: row.nurseSatisfaction || 0,
        };
        });
      });
      if (this.selectedRows.length > 0) {
        this.multiple = false;
      } else {
        this.multiple = true;
      }
      this.selectedRows = Array.from(this.selectedRowMap.values());
      this.multiple = this.selectedRows.length === 0;
    },
    // è®¡ç®—总分
@@ -2116,6 +2163,76 @@
      }
      return "";
    },
    restoreSelection() {
      if (!this.$refs.userform) {
        console.log("表格引用不存在");
        return;
      }
      console.log("执行 restoreSelection");
      // æ¸…除当前页的所有选中状态
      this.$refs.userform.clearSelection();
      // æ‰¾å‡ºå½“前页中哪些行是被选中的
      const toBeSelected = this.userList.filter((row) =>
        this.selectedRowMap.has(row.id)
      );
      console.log("需要恢复的行数:", toBeSelected.length);
      // é‡æ–°é€‰ä¸­è¿™äº›è¡Œ
      toBeSelected.forEach((row) => {
        this.$refs.userform.toggleRowSelection(row, true);
      });
    },
    // âœ… å¤„理表头全选事件
    handleSelectAll(selection) {
      console.log("全选事件触发,选中行数:", selection.length);
      // å¦‚æžœ selection é•¿åº¦ç­‰äºŽå½“前页行数,说明是全选
      if (selection.length === this.userList.length) {
        // å…¨é€‰å½“前页
        this.userList.forEach((row) => {
          this.selectedRowMap.set(row.id, {
            ...row,
            authenticity: row.authenticity || 0,
            weekFinish: row.weekFinish || 0,
            standard: row.standard || 0,
            timeliness: row.timeliness || 0,
            library: row.library || 0,
            environment: row.environment || 0,
            doctorSatisfaction: row.doctorSatisfaction || 0,
            nurseSatisfaction: row.nurseSatisfaction || 0,
          });
        });
      } else {
        // å–消全选:清除当前页的选中状态
        this.userList.forEach((row) => {
          this.selectedRowMap.delete(row.id);
        });
      }
      // æ›´æ–° selectedRows
      this.selectedRows = Array.from(this.selectedRowMap.values());
      this.multiple = this.selectedRows.length === 0;
    },
    // æ¸…除所有选中
    clearAllSelection() {
      this.selectedRowMap.clear();
      this.selectedRows = [];
      this.multiple = true;
      if (this.$refs.userform) {
        this.$refs.userform.clearSelection();
      }
    },
    // èŽ·å–é€‰ä¸­æ•°é‡
    getSelectedCount() {
      return this.selectedRowMap.size;
    },
    // åˆ›å»ºå†æ¬¡éšè®¿æœåŠ¡
    setupsubtask() {
      this.$refs["zcform"].validate((valid) => {
@@ -2385,4 +2502,15 @@
  flex-shrink: 0;
  margin-top: 2px;
}
::v-deep .el-table__row.selected-row:hover > td {
  background-color: #e6f7ff !important;
}
/* é€‰ä¸­ä¿¡æ¯æ˜¾ç¤º */
.selected-info {
  padding: 10px 0;
  font-size: 14px;
  color: #666;
}
</style>
src/views/followvisit/record/detailpage/MergeAndModify.vue
@@ -39,7 +39,7 @@
                  handleOptionChange(
                    $event,
                    index,
                    question.svyLibTemplateTargetoptions,
                    question.svyTaskTemplateTargetoptions,
                    question
                  )
                "
@@ -47,7 +47,7 @@
                <el-radio
                  v-for="(
                    option, optIndex
                  ) in question.svyLibTemplateTargetoptions"
                  ) in question.svyTaskTemplateTargetoptions"
                  :key="optIndex"
                  :label="option.optioncontent"
                  :class="option.isabnormal ? 'red-star' : ''"
@@ -61,10 +61,10 @@
            <div class="dev-xx" v-if="question.scriptType == 2">
              <el-checkbox-group
                v-model="question.mergedResult"
                @change="updateScore($event, index, question.options, question)"
                @change="updateScore($event, index, question.svyTaskTemplateTargetoptions, question)"
              >
                <el-checkbox
                  v-for="(option, optIndex) in question.options"
                  v-for="(option, optIndex) in question.svyTaskTemplateTargetoptions"
                  :key="optIndex"
                  :label="option.optioncontent"
                  :class="option.isabnormal ? 'red-star' : ''"
src/views/followvisit/record/detailpage/index.vue
@@ -2417,8 +2417,15 @@
    },
    // è°ƒèµ·çŸ­ä¿¡å‘送对话框
    sendAgainmsg() {
      this.smsDialogVisible = true;
      // å¯ä»¥åœ¨è¿™é‡Œåˆå§‹åŒ– smsContent,例如 this.smsContent = '';
      // this.smsDialogVisible = true;
      this.$store.dispatch("sms/openSmsDialog", {
        name: this.form.sendname,
        age: this.form.age,
        phone: this.userform.telcode,
        deptName: this.form.deptname,
        wardName: this.form.leavehospitaldistrictname,
        smsTemplate: `尊敬的${this.form.sendname},您好!`,
      });
    },
    // å‘送短信的方法
src/views/knowledge/questionbank/index.vue
@@ -456,7 +456,7 @@
import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
export default {
  name: "questionnaire",
  name: "Questionbank",
  components: { Treeselect },
  data() {
    return {
src/views/knowledge/questionbank/particulars/index.vue
@@ -745,6 +745,7 @@
        svyLibScriptTagList: [],
        suitway: "1",
        scoretype: "4",
        isavailable: "0",
        language: "普通话",
      },
      headers: {
src/views/knowledge/questionnaire/smsConfig/index.vue
@@ -1,64 +1,6 @@
<template>
  <div class="smsConfig-management">
    <!-- å·¦ä¾§æ  -->
    <div class="sidecolumn">
      <div class="sidecolumn-top">
        <div class="top-wj">模板分类</div>
        <div class="top-tj" @click="Newcategory">+添加</div>
      </div>
      <div class="center-ss">
        <el-input
          placeholder="请输入内容"
          v-model="sidecolumnval"
          class="input-with-select"
          size="medium"
        >
        </el-input>
      </div>
      <div class="head-container" style="margin-top: 20px">
        <el-tree
          :data="deptOptions"
          :props="defaultProps"
          :expand-on-click-node="false"
          :filter-node-method="filterNode"
          ref="tree"
          node-key="id"
          default-expand-all
          highlight-current
          @node-click="handleNodeClick"
        >
          <span class="custom-tree-node" slot-scope="{ node, data }">
            <span class="tree-node-label">{{ node.label }}</span>
            <span v-if="data.id > 0">
              <el-button
                type="text"
                icon="el-icon-delete"
                circle
                size="mini"
                @click="() => remove(node, data)"
              >
              </el-button>
            </span>
            <span v-if="data.id > 0">
              <el-button
                type="text"
                circle
                size="mini"
                @click="() => altertag(node, data)"
              >
                <span class="button-textxg">
                  <i class="el-icon-edit-outline"></i>
                </span>
              </el-button>
            </span>
          </span>
        </el-tree>
      </div>
    </div>
    <!-- å³ä¾§æ•°æ® -->
    <div class="leftvlue">
      <div class="leftvlue-bg">
    <div class="main-content">
        <el-row :gutter="20">
          <el-col :span="24" :xs="24">
            <el-form
@@ -67,8 +9,18 @@
              size="small"
              :inline="true"
              v-show="showSearch"
              label-width="98px"
            label-width="88px"
            >
            <el-form-item label="模板编号" prop="templetno">
              <el-input
                v-model="queryParams.templetno"
                placeholder="请输入模板编号"
                clearable
                style="width: 200px"
                @keyup.enter.native="handleQuery"
              />
            </el-form-item>
              <el-form-item label="模板名称" prop="templetname">
                <el-input
                  v-model="queryParams.templetname"
@@ -79,31 +31,14 @@
                />
              </el-form-item>
              <el-form-item label="短信签名" prop="signature">
            <el-form-item label="部门名称" prop="deptName">
                <el-input
                  v-model="queryParams.signature"
                  placeholder="请输入短信签名"
                v-model="queryParams.deptName"
                placeholder="请输入部门名称"
                  clearable
                  style="width: 200px"
                  @keyup.enter.native="handleQuery"
                />
              </el-form-item>
              <el-form-item label="启用状态" prop="isenable">
                <el-select
                  v-model="queryParams.isenable"
                  placeholder="请选择状态"
                  clearable
                  style="width: 200px"
                >
                  <el-option
                    v-for="item in statusOptions"
                    :key="item.value"
                    :label="item.label"
                    :value="item.value"
                  >
                  </el-option>
                </el-select>
              </el-form-item>
              <el-form-item>
@@ -112,12 +47,14 @@
                  icon="el-icon-search"
                  size="medium"
                  @click="handleQuery"
                >搜索</el-button>
                >搜索</el-button
              >
                <el-button
                  icon="el-icon-refresh"
                  size="medium"
                  @click="resetQuery"
                >重置</el-button>
                >重置</el-button
              >
              </el-form-item>
            </el-form>
@@ -131,7 +68,8 @@
                  icon="el-icon-plus"
                  size="medium"
                  @click="handleAdd"
                >新增</el-button>
                >新增</el-button
              >
              </el-col>
              <el-col :span="1.5">
                <el-button
@@ -141,7 +79,8 @@
                  size="medium"
                  :disabled="multiple"
                  @click="handleDelete"
                >删除</el-button>
                >删除</el-button
              >
              </el-col>
            </el-row>
@@ -154,20 +93,21 @@
              <el-table-column type="selection" width="50" align="center" />
              <el-table-column
              label="模板编号"
              align="center"
              key="templetno"
              prop="templetno"
              width="140"
              :show-overflow-tooltip="true"
            />
            <el-table-column
                label="模板名称"
                align="center"
                key="templetname"
                prop="templetname"
                width="160"
                :show-overflow-tooltip="true"
              />
              <el-table-column
                label="短信签名"
                align="center"
                key="signature"
                prop="signature"
                width="120"
              />
              <el-table-column
@@ -180,43 +120,52 @@
              />
              <el-table-column
                label="模板类型"
              label="部门名称"
                align="center"
                key="templettype"
                prop="templettype"
              key="deptName"
              prop="deptName"
                width="120"
              >
                <template slot-scope="scope">
                  <dict-tag :options="typeOptions" :value="scope.row.templettype" />
                </template>
              </el-table-column>
              <el-table-column
                label="启用状态"
                align="center"
                key="isenable"
                prop="isenable"
                width="100"
              >
                <template slot-scope="scope">
                  <dict-tag :options="statusOptions" :value="scope.row.isenable" />
                </template>
              </el-table-column>
              <el-table-column
                label="备注"
                align="center"
                key="remark"
                prop="remark"
                width="180"
                :show-overflow-tooltip="true"
              />
              <el-table-column
                label="创建时间"
              label="病区名称"
                align="center"
                key="createTime"
                prop="createTime"
              key="wardName"
              prop="wardName"
              width="140"
              :show-overflow-tooltip="true"
            />
            <el-table-column
              label="用户工号"
              align="center"
              key="userName"
              prop="userName"
              width="120"
            />
            <el-table-column
              label="用户昵称"
              align="center"
              key="nickName"
              prop="nickName"
              width="120"
            />
            <el-table-column
              label="是否上传"
              align="center"
              key="isupload"
              prop="isupload"
              width="90"
            />
            <el-table-column
              label="上传时间"
              align="center"
              key="uploadTime"
              prop="uploadTime"
                width="160"
              />
@@ -224,7 +173,7 @@
                label="操作"
                fixed="right"
                align="center"
                width="240"
              width="200"
                class-name="small-padding fixed-width"
              >
                <template slot-scope="scope">
@@ -269,7 +218,6 @@
          </el-col>
        </el-row>
      </div>
    </div>
    <!-- æ·»åŠ /修改短信模板弹框 -->
    <el-dialog
@@ -285,36 +233,19 @@
        label-width="100px"
        size="medium"
      >
        <el-form-item label="模板分类" prop="categoryid">
          <el-select
            v-model="form.categoryid"
            placeholder="请选择模板分类"
            clearable
            style="width: 100%"
          >
            <el-option
              v-for="item in categoryOptions"
              :key="item.id"
              :label="item.name"
              :value="item.id"
            >
            </el-option>
          </el-select>
        <el-form-item label="模板编号" prop="templetno">
          <el-input
            v-model="form.templetno"
            placeholder="请输入模板编号"
            maxlength="50"
          />
        </el-form-item>
        <el-form-item label="模板名称" prop="templetname">
          <el-input
            v-model="form.templetname"
            placeholder="请输入模板名称"
            maxlength="50"
          />
        </el-form-item>
        <el-form-item label="短信签名" prop="signature">
          <el-input
            v-model="form.signature"
            placeholder="请输入短信签名(如:【丽水人民医院】)"
            maxlength="20"
            maxlength="100"
          />
        </el-form-item>
@@ -329,118 +260,77 @@
          />
        </el-form-item>
        <el-form-item label="模板类型" prop="templettype">
        <el-form-item label="科室" prop="deptCode">
          <el-select
            v-model="form.templettype"
            placeholder="请选择模板类型"
            v-model="form.deptCode"
            placeholder="请选择科室"
            filterable
            clearable
            style="width: 100%"
            @change="handleDeptChange"
          >
            <el-option
              v-for="item in typeOptions"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            >
            </el-option>
              v-for="dept in departmentOptions"
              :key="dept.value"
              :label="dept.label"
              :value="dept.value"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="启用状态" prop="isenable">
          <el-radio-group v-model="form.isenable">
            <el-radio
              v-for="item in statusOptions"
              :key="item.value"
              :label="item.value"
            >{{ item.label }}</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="备注" prop="remark">
          <el-input
            v-model="form.remark"
            type="textarea"
            :rows="3"
            placeholder="请输入备注信息"
            maxlength="200"
            show-word-limit
        <el-form-item label="病区" prop="wardCode">
          <el-select
            v-model="form.wardCode"
            placeholder="请选择病区"
            filterable
            clearable
            style="width: 100%"
            @change="handleWardChange"
          >
            <el-option
              v-for="ward in wardOptions"
              :key="ward.value"
              :label="ward.label"
              :value="ward.value"
          />
          </el-select>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="cancelForm">取 æ¶ˆ</el-button>
        <el-button type="primary" @click="submitForm" :loading="submitLoading">ç¡® å®š</el-button>
        <el-button type="primary" @click="submitForm" :loading="submitLoading"
          >ç¡® å®š</el-button
        >
      </div>
    </el-dialog>
    <!-- æ¨¡æ¿é¢„览弹框 -->
    <el-dialog
      title="短信模板预览"
      :visible.sync="previewVisible"
      width="40%"
    >
    <el-dialog title="短信模板预览" :visible.sync="previewVisible" width="40%">
      <div class="preview-box">
        <div class="preview-item">
          <div class="preview-label">模板编号:</div>
          <div class="preview-value">{{ previewData.templetno || "-" }}</div>
        </div>
        <div class="preview-item">
          <div class="preview-label">模板名称:</div>
          <div class="preview-value">{{ previewData.templetname }}</div>
          <div class="preview-value">{{ previewData.templetname || "-" }}</div>
        </div>
        <div class="preview-item">
          <div class="preview-label">短信签名:</div>
          <div class="preview-value">{{ previewData.signature }}</div>
          <div class="preview-label">部门名称:</div>
          <div class="preview-value">{{ previewData.deptName || "-" }}</div>
        </div>
        <div class="preview-item">
          <div class="preview-label">模板类型:</div>
          <div class="preview-value">
            <dict-tag :options="typeOptions" :value="previewData.templettype" />
          <div class="preview-label">病区名称:</div>
          <div class="preview-value">{{ previewData.wardName || "-" }}</div>
          </div>
        </div>
        <div class="preview-item">
          <div class="preview-label">启用状态:</div>
          <div class="preview-value">
            <dict-tag :options="statusOptions" :value="previewData.isenable" />
          </div>
        </div>
        <el-divider></el-divider>
        <div class="preview-content">
          <div class="preview-content-label">短信内容预览:</div>
          <div class="preview-content-box">
            {{ previewData.templetcontent || '暂无内容' }}
            {{ previewData.templetcontent || "暂无内容" }}
          </div>
        </div>
        <div class="preview-item" v-if="previewData.remark">
          <div class="preview-label">备注:</div>
          <div class="preview-value">{{ previewData.remark }}</div>
        </div>
      </div>
    </el-dialog>
    <!-- æ·»åŠ ç±»åˆ«å¼¹æ¡† -->
    <el-dialog title="类别编辑" width="30%" :visible.sync="dialogFormVisible">
      <div style="text-align: center; margin-bottom: 20px">
        <el-radio-group v-model="radio">
          <el-radio-button label="主分类"></el-radio-button>
          <el-radio-button label="子分类"></el-radio-button>
        </el-radio-group>
      </div>
      <el-divider></el-divider>
      <el-form :model="classifyform">
        <el-form-item label="请选择模板大类" v-if="radio == '子分类'">
          <el-select v-model="classifyform.pid" placeholder="请选择">
            <el-option
              v-for="item in deptOptions"
              :key="item.id"
              :label="item.name"
              :value="item.id"
            >
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="请输入类别名称">
          <el-input v-model="classifyform.name" autocomplete="off"></el-input>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="getDeptTree()">取 æ¶ˆ</el-button>
        <el-button type="primary" @click="submitsidecolumn">ç¡® å®š</el-button>
      </div>
    </el-dialog>
  </div>
@@ -484,35 +374,10 @@
      previewVisible: false,
      // é¢„览数据
      previewData: {},
      // ç±»åˆ«å¼¹æ¡†
      dialogFormVisible: false,
      // ç±»åˆ«form
      classifyform: {},
      // ä¸»/子分类
      radio: "主分类",
      // ç±»åˆ«æœç´¢
      sidecolumnval: "",
      // æ ‘数据
      deptOptions: [],
      // åˆ†ç±»ä¸‹æ‹‰é€‰é¡¹
      categoryOptions: [],
      // æ ‘props
      defaultProps: {
        children: "children",
        label: "name",
      },
      // çŠ¶æ€é€‰é¡¹
      statusOptions: [
        { label: "启用", value: "0" },
        { label: "停用", value: "1" },
      ],
      // ç±»åž‹é€‰é¡¹
      typeOptions: [
        { label: "验证码", value: "0" },
        { label: "通知", value: "1" },
        { label: "营销", value: "2" },
        { label: "随访", value: "3" },
      ],
      // ç§‘室选项
      departmentOptions: [],
      // ç—…区选项
      wardOptions: [],
      // æŸ¥è¯¢å‚æ•°
      queryParams: {
        pageNum: 1,
@@ -528,24 +393,40 @@
        templetcontent: [
          { required: true, message: "请输入模板内容", trigger: "blur" },
        ],
        signature: [
          { required: true, message: "请输入短信签名", trigger: "blur" },
        ],
        isenable: [
          { required: true, message: "请选择启用状态", trigger: "change" },
        ],
      },
    };
  },
  watch: {
    // ç›‘听类别搜索
    sidecolumnval(val) {
      this.$refs.tree.filter(val);
  computed: {
    // ä»Ž store getters èŽ·å–ç§‘å®¤é€‰é¡¹
    computedDepartmentOptions() {
      if (this.$store.getters.belongDepts) {
        return this.$store.getters.belongDepts.map((dept) => ({
          label: dept.deptName,
          value: dept.deptCode,
        }));
      }
      return [];
    },
    // ä»Ž store getters èŽ·å–ç—…åŒºé€‰é¡¹
    computedWardOptions() {
      console.log(
        this.$store.getters.belongWards,
        "this.$store.getters.belongWards"
      );
      if (this.$store.getters.belongWards) {
        return this.$store.getters.belongWards.map((ward) => ({
          label: ward.districtName,
          value: ward.districtCode,
        }));
      }
      return [];
    },
  },
  created() {
    this.getList();
    this.getDeptTree();
    this.departmentOptions = this.computedDepartmentOptions;
    this.wardOptions = this.computedWardOptions;
  },
  methods: {
    /** æŸ¥è¯¢åˆ—表 */
@@ -581,14 +462,7 @@
    handleAdd() {
      this.dialogTitle = "新增短信模板";
      this.dialogVisible = true;
      this.form = {
        isenable: "0",
        templettype: "1",
      };
      // å¦‚果有树选中分类,默认带入
      if (this.queryParams.categoryid) {
        this.form.categoryid = this.queryParams.categoryid;
      }
      this.form = {};
      this.$nextTick(() => {
        if (this.$refs.formRef) {
          this.$refs.formRef.clearValidate();
@@ -618,6 +492,30 @@
      getSmstemplet(templetid).then((response) => {
        this.previewData = response.data;
      });
    },
    /** ç§‘室选择变化 - è‡ªåŠ¨å¡«å……ç§‘å®¤åç§° */
    handleDeptChange(value) {
      const selectedDept = this.departmentOptions.find(
        (dept) => dept.value === value
      );
      if (selectedDept) {
        this.form.deptName = selectedDept.label;
      } else {
        this.form.deptName = "";
      }
    },
    /** ç—…区选择变化 - è‡ªåŠ¨å¡«å……ç—…åŒºåç§° */
    handleWardChange(value) {
      const selectedWard = this.wardOptions.find(
        (ward) => ward.value === value
      );
      if (selectedWard) {
        this.form.wardName = selectedWard.label;
      } else {
        this.form.wardName = "";
      }
    },
    /** æäº¤è¡¨å• */
@@ -677,260 +575,21 @@
        })
        .catch(() => {});
    },
    // è¡¨å•重置
    reset() {
      this.form = {
        templetid: undefined,
        templetname: undefined,
        signature: undefined,
        templetcontent: undefined,
        templettype: "1",
        isenable: "0",
        categoryid: undefined,
        remark: undefined,
      };
      this.resetForm("form");
    },
    /** æŸ¥è¯¢åˆ†ç±»æ ‘ */
    getDeptTree() {
      // æ¨¡æ‹Ÿåˆ†ç±»æ ‘数据 - å®žé™…项目中应替换为真实API
      this.deptOptions = [
        {
          id: 1,
          name: "随访短信",
          children: [
            { id: 11, name: "出院随访" },
            { id: 12, name: "复诊提醒" },
            { id: 13, name: "健康宣教" },
          ],
        },
        {
          id: 2,
          name: "通知短信",
          children: [
            { id: 21, name: "预约通知" },
            { id: 22, name: "报告通知" },
          ],
        },
        {
          id: 3,
          name: "验证码",
          children: [
            { id: 31, name: "登录验证" },
            { id: 32, name: "注册验证" },
          ],
        },
      ];
      this.categoryOptions = this.flattenTree(this.deptOptions);
    },
    /** æ‰å¹³åŒ–树数据用于下拉选择 */
    flattenTree(tree) {
      let result = [];
      tree.forEach((item) => {
        result.push({ id: item.id, name: item.name });
        if (item.children && item.children.length) {
          result = result.concat(item.children);
        }
      });
      return result;
    },
    /** ç­›é€‰èŠ‚ç‚¹ */
    filterNode(value, data) {
      if (!value) return true;
      return data.name.indexOf(value) !== -1;
    },
    /** ç‚¹å‡»æ ‘节点 */
    handleNodeClick(data) {
      if (data.children && data.children.length) return;
      this.queryParams.categoryid = data.id;
      this.getList();
    },
    // åˆ†ç±»æ ‘-----------------------
    /** æ–°å»ºåˆ†ç±» */
    Newcategory() {
      this.classifyform = {};
      this.radio = "主分类";
      this.dialogFormVisible = true;
    },
    /** ä¿®æ”¹åˆ†ç±» */
    altertag(node, data) {
      this.dialogFormVisible = true;
      if (data.children && data.children.length) {
        this.radio = "主分类";
      } else {
        this.radio = "子分类";
      }
      this.classifyform = { ...data };
    },
    /** æäº¤åˆ†ç±» */
    submitsidecolumn() {
      if (this.classifyform.id) {
        // ä¿®æ”¹åˆ†ç±» - å®žé™…项目中应替换为真实API
        const index = this.deptOptions.findIndex(
          (obj) => obj.id === this.classifyform.id
        );
        if (index > -1) {
          this.deptOptions[index].name = this.classifyform.name;
          this.$set(this.deptOptions, index, this.deptOptions[index]);
        }
        this.$modal.msgSuccess("修改成功");
        this.dialogFormVisible = false;
        return;
      }
      if (this.radio === "主分类" && this.classifyform.name) {
        // æ–°å¢žä¸»åˆ†ç±»
        const newId = Math.max(...this.deptOptions.map((d) => d.id), 0) + 1;
        this.deptOptions.push({
          id: newId,
          name: this.classifyform.name,
          children: [],
        });
        this.$modal.msgSuccess("新增成功");
        this.dialogFormVisible = false;
      } else if (
        this.radio === "子分类" &&
        this.classifyform.pid &&
        this.classifyform.name
      ) {
        // æ–°å¢žå­åˆ†ç±»
        const parent = this.deptOptions.find(
          (obj) => obj.id === this.classifyform.pid
        );
        if (parent) {
          const newChildId =
            Math.max(...parent.children.map((c) => c.id), parent.id * 10) + 1;
          parent.children.push({
            id: newChildId,
            name: this.classifyform.name,
          });
        }
        this.$modal.msgSuccess("新增成功");
        this.dialogFormVisible = false;
      } else {
        this.$modal.msgError("请填写完整信息");
      }
      this.classifyform = {};
    },
    /** åˆ é™¤åˆ†ç±» */
    remove(node, data) {
      if (data.children && data.children.length) {
        this.$modal
          .confirm(
            '是否确认删除一级分类"' + data.name + '"?删除后其下分类将无法使用'
          )
          .then(() => {
            const index = this.deptOptions.findIndex(
              (obj) => obj.id === data.id
            );
            if (index > -1) {
              this.deptOptions.splice(index, 1);
            }
            this.$modal.msgSuccess("删除成功");
          })
          .catch(() => {});
      } else {
        this.$modal
          .confirm('是否确认删除分类项为"' + data.name + '"的数据项?')
          .then(() => {
            this.deptOptions.forEach((parent) => {
              const idx = parent.children.findIndex(
                (child) => child.id === data.id
              );
              if (idx > -1) {
                parent.children.splice(idx, 1);
              }
            });
            this.$modal.msgSuccess("删除成功");
          })
          .catch(() => {});
      }
    },
  },
};
</script>
<style lang="scss" scoped>
.smsConfig-management {
  display: flex;
  padding: 20px;
}
.sidecolumn {
  width: 380px;
  min-height: 100vh;
  text-align: center;
  margin-top: 20px;
  margin: 20px;
.main-content {
  padding: 30px;
  background: #fff;
  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;
    }
  }
  /* æ ¸å¿ƒï¼šè®¾ç½®å›ºå®šå®½åº¦ï¼Œè¶…出部分显示省略号 */
  .tree-node-label {
    display: inline-block;
    max-width: 160px;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    vertical-align: bottom;
  }
  /* å¯é€‰ï¼šé¼ æ ‡æ‚¬åœæ—¶å–消限制,显示全文 */
  .custom-tree-node:hover .tree-node-label {
    max-width: none;
    white-space: normal;
    overflow: visible;
  }
  .center-ss {
    margin-top: 30px;
    .input-with-select {
      height: 40px !important;
    }
  }
  .bottom-fl {
    margin-top: 30px;
    display: center !important;
  }
}
.leftvlue {
  width: 80%;
  margin-top: 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;
  }
}
// é¢„览弹框样式
@@ -980,46 +639,8 @@
  }
}
// æ·±åº¦é€‰æ‹©å™¨
::v-deep .el-input--medium .el-input__inner {
  height: 40px !important;
}
::v-deep .el-tree-node__content {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-align: center;
  -ms-flex-align: center;
  align-items: center;
  height: 46px;
  font-size: 20px;
  cursor: pointer;
}
::v-deep .el-tree {
  position: relative;
  cursor: default;
  border-radius: 5px;
  background: #eff8fe;
  color: #606266;
  border: 1px solid #bbe1fa;
  -webkit-box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12),
    0 0 6px 0 rgba(0, 0, 0, 0.04);
}
::v-deep
  .el-tree--highlight-current
  .el-tree-node.is-current
  > .el-tree-node__content {
  background-color: #7799fb;
  color: #fff;
}
::v-deep .el-button--mini.is-circle {
  padding: 7px;
  margin: 0;
  color: red;
}
// æŒ‰é’®æ–‡å­—颜色
src/views/outsideChainwtnew.vue
@@ -897,11 +897,18 @@
}
.questionnaire-title {
  color: #175997;
  color: #0d3b6b; // åŸºç¡€æ·±è“è‰²
  font-size: 28px;
  font-weight: 700;
  margin-bottom: 15px;
  line-height: 1.3;
  text-shadow: 0 1px 3px rgba(255, 255, 255, 0.4);
  // é’ˆå¯¹å¤œé—´æ¨¡å¼çš„优化
  @media (prefers-color-scheme: dark) {
    color: #4a90d9; // å¤œé—´æ¨¡å¼ä½¿ç”¨æ›´äº®çš„蓝色
    text-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
  }
}
.questionnaire-description {
@@ -1023,40 +1030,81 @@
}
.question-options {
  margin: 15px 0;
  margin: 12px 0;
  padding: 0 4px;
}
// ä¿®æ”¹ options-group çš„æ ·å¼
.options-group {
  display: flex;
  flex-direction: column;
  gap: 12px;
  display: grid;
  grid-template-columns: repeat(2, 1fr); // æ”¹ä¸ºä¸¤åˆ—网格
  gap: 10px;
  width: 100%;
}
// é’ˆå¯¹å¤šé€‰çš„ checkbox-group ä¹Ÿåº”用同样的网格布局
:deep(.el-checkbox-group) {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
  width: 100%;
  @media (max-width: 420px) {
    grid-template-columns: 1fr;
  }
}
// ä¿®æ”¹é€‰é¡¹çš„æ ·å¼
.option-radio,
.option-checkbox {
  margin: 0;
  padding: 12px 15px;
  padding: 10px 12px;
  border-radius: 6px;
  border: 1px solid #e0e0e0;
  transition: all 0.2s;
  display: flex;
  align-items: center;
  width: 100%;
  box-sizing: border-box;
  &:hover {
    border-color: #c0c4cc;
    background-color: #f8fafc;
  }
  // ç¡®ä¿å†…部内容自适应
  :deep(.el-radio__label),
  :deep(.el-checkbox__label) {
    display: inline;
    font-size: 15px;
    line-height: 1.4;
    word-break: break-all; // å…è®¸åœ¨ä»»æ„å­—符处换行
    white-space: normal; // å…è®¸è‡ªåŠ¨æ¢è¡Œ
    padding-left: 6px;
}
:deep(.option-radio .el-radio__label),
:deep(.option-checkbox .el-checkbox__label) {
  display: flex;
  align-items: center;
  font-size: 16px;
  // ç¡®ä¿ radio/checkbox å›¾æ ‡ä¸åŽ‹ç¼©
  :deep(.el-radio__input),
  :deep(.el-checkbox__input) {
    flex-shrink: 0;
}
}
// :deep(.option-radio .el-radio__label),
// :deep(.option-checkbox .el-checkbox__label) {
//   display: flex;
//   align-items: center;
//   font-size: 16px;
// }
.option-text {
  margin-right: 5px;
  word-break: break-all;
  white-space: normal;
  line-height: 1.4;
}
// åœ¨å°å±å¹•上调整为单列
@media (max-width: 300px) {
  .options-group {
    grid-template-columns: 1fr; // è¶…小屏幕恢复单列
  }
}
.abnormal-indicator {
  color: #f56c6c;
  font-weight: bold;
src/views/repositoryai/intention/index.vue
@@ -717,7 +717,7 @@
import store from "@/store";
export default {
  name: "questionnaire",
  name: "Intention",
  dicts: ["sys_normal_disable", "sys_user_sex"],
  components: { Treeselect, Regular },
  data() {
src/views/repositoryai/verbaltrick/index.vue
@@ -473,7 +473,7 @@
import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
export default {
  name: "questionnaire",
  name: "Verbaltrick",
  components: { Treeselect },
  data() {
    return {
src/views/repositoryai/verbaltrick/particulars/index.vue
@@ -90,7 +90,7 @@
            </el-col>
            <el-col :span="12">
              <el-form-item label="可用状态" prop="status">
                <el-select
                <!-- <el-select
                  v-model="indexform.isAvailable"
                  placeholder="请选择状态"
                >
@@ -101,7 +101,15 @@
                    :value="item.value"
                  >
                  </el-option>
                </el-select>
                </el-select> -->
                <el-radio-group v-model="indexform.isAvailable">
                  <el-radio
                    @change="$forceUpdate()"
                    v-for="(item, index) in usable"
                    :label="item.value"
                    >{{ item.label }}</el-radio
                  >
                </el-radio-group>
              </el-form-item>
            </el-col>
          </el-row>
@@ -740,9 +748,10 @@
        ivrLibaScriptTargetoptionList: [],
        ivrLibaScriptTagList: [],
        suitway: "2",
        noMatchText:'抱歉,我没有听懂,您能再说一遍吗?',
        noClearlyText:'抱歉,我没有听清您说的话,您可以再说一次吗?',
        slienceText:'抱歉,我没有听到您说的话,您可以再说一次吗?',
        isAvailable: "0",
        noMatchText: "抱歉,我没有听懂,您能再说一遍吗?",
        noClearlyText: "抱歉,我没有听清您说的话,您可以再说一次吗?",
        slienceText: "抱歉,我没有听到您说的话,您可以再说一次吗?",
      },
      mode: [],
      questionclass: [],
@@ -796,7 +805,7 @@
    getverbaltrick() {
      let id = this.$route.query.id;
      this.indexform.language = "普通话";
      this.indexform.isAvailable = "1";
      this.indexform.isAvailable = "0";
      if (id) {
        getverbaltrick({ id: id }).then((res) => {
src/views/sfstatistics/percentage/components/FirstFollowUp.vue
@@ -236,6 +236,7 @@
                  width="120"
                  key="successRate"
                  prop="successRate"
                  :render-header="Tooltipcgl"
                >
                  <template slot-scope="scope">
                    <span class="success-rate">{{
@@ -253,6 +254,7 @@
                  width="120"
                  key="followUpRate"
                  prop="followUpRate"
                  :render-header="Tooltipsfl"
                />
                <el-table-column
                  v-if="orgname != '丽水市中医院'"
@@ -261,6 +263,7 @@
                  width="120"
                  key="rate"
                  prop="rate"
                  :render-header="Tooltipjsl"
                >
                  <template slot-scope="scope">
                    <el-button
@@ -543,6 +546,7 @@
            width="120"
            key="successRate"
            prop="successRate"
            :render-header="Tooltipcgl"
          >
            <template slot-scope="scope">
              <span class="success-rate">{{
@@ -560,6 +564,7 @@
            width="120"
            key="followUpRate"
            prop="followUpRate"
            :render-header="Tooltipsfl"
          />
          <el-table-column
            v-if="orgname != '丽水市中医院'"
@@ -568,6 +573,7 @@
            width="120"
            key="rate"
            prop="rate"
            :render-header="Tooltipjsl"
          >
            <template slot-scope="scope">
              <el-button
@@ -863,7 +869,45 @@
        return indexA - indexB;
      });
    },
    Tooltipcgl(h, { column }) {
      return h(
        "el-tooltip",
        {
          props: {
            content: "随访成功/(需随访-待随访)",
            placement: "top",
            effect: "dark",
          },
        },
        [h("span", column.label)]
      );
    },
    Tooltipjsl(h, { column }) {
      return h(
        "el-tooltip",
        {
          props: {
            content: "(应随访时间+任务周期)小于完成时间即为超时;(需随访-超时)/需随访",
            placement: "top",
            effect: "dark",
          },
        },
        [h("span", column.label)]
      );
    },
    Tooltipsfl(h, { column }) {
      return h(
        "el-tooltip",
        {
          props: {
            content: "(随访成功+首次随访失败)/首次应随访",
            placement: "top",
            effect: "dark",
          },
        },
        [h("span", column.label)]
      );
    },
    sortChineseNumber(aRow, bRow) {
      const a = aRow.leavehospitaldistrictname;
      const b = bRow.leavehospitaldistrictname;
@@ -1237,10 +1281,14 @@
    let serviceTypeName = "首次出院随访"; // æ–‡ä»¶åä½¿ç”¨çš„名称
    let sheetTypeName = "首次随访"; // å·¥ä½œè¡¨ä½¿ç”¨çš„名称(简化版)
    if (this.queryParams.serviceType && Array.isArray(this.queryParams.serviceType) && this.queryParams.serviceType.length > 0) {
        if (
          this.queryParams.serviceType &&
          Array.isArray(this.queryParams.serviceType) &&
          this.queryParams.serviceType.length > 0
        ) {
      if (this.tasktypes && Array.isArray(this.tasktypes)) {
        // è¿‡æ»¤å‡ºåŒ¹é…çš„随访类型
        const matchedTypes = this.tasktypes.filter(task =>
            const matchedTypes = this.tasktypes.filter((task) =>
          this.queryParams.serviceType.includes(task.value)
        );
@@ -1251,7 +1299,7 @@
          sheetTypeName = `首次${label}`;
        } else if (matchedTypes.length > 1) {
          // å¤šä¸ªç±»åž‹
          const typeNames = matchedTypes.map(task => task.label);
              const typeNames = matchedTypes.map((task) => task.label);
          // æ–‡ä»¶åï¼šç”¨æ–œæ åˆ†éš”
          serviceTypeName = `首次${typeNames.join("/")}`;
@@ -1283,10 +1331,12 @@
    // æ¸…理工作表名称,移除非法字符
    const cleanSheetName = (name) => {
      // Excel工作表名不能包含的字符: * ? : \ / [ ]
      return name.replace(/[*?:\\/[\]]/g, ' ');
          return name.replace(/[*?:\\/[\]]/g, " ");
    };
    const worksheetName = cleanSheetName(`${sheetTypeName}统计_${sheetNameSuffix}`);
        const worksheetName = cleanSheetName(
          `${sheetTypeName}统计_${sheetNameSuffix}`
        );
    if (!this.tableData || this.tableData.length === 0) {
      this.$message.warning(`暂无${serviceTypeName}数据可导出`);
src/views/sfstatistics/percentage/components/SecondFollowUp.vue
@@ -234,6 +234,7 @@
                  width="120"
                  key="successRateAgain"
                  prop="successRateAgain"
                  :render-header="Tooltipcgl"
                >
                  <template slot-scope="scope">
                    <span class="success-rate">{{
@@ -251,6 +252,7 @@
                  width="120"
                  key="followUpRateAgain"
                  prop="followUpRateAgain"
                  :render-header="Tooltipsfl"
                />
                <el-table-column
                  label="人工"
@@ -529,6 +531,7 @@
            width="120"
            key="successRateAgain"
            prop="successRateAgain"
            :render-header="Tooltipcgl"
          >
            <template slot-scope="scope">
              <span class="success-rate">{{
@@ -546,6 +549,7 @@
            width="120"
            key="followUpRateAgain"
            prop="followUpRateAgain"
            :render-header="Tooltipsfl"
          />
          <el-table-column
            label="人工"
@@ -707,7 +711,45 @@
          this.loading = false;
        });
    },
    Tooltipcgl(h, { column }) {
      return h(
        "el-tooltip",
        {
          props: {
            content: "随访成功/(需随访-待随访)",
            placement: "top",
            effect: "dark",
          },
        },
        [h("span", column.label)]
      );
    },
    Tooltipjsl(h, { column }) {
      return h(
        "el-tooltip",
        {
          props: {
            content: "(应随访时间+任务周期)小于完成时间即为超时;(需随访-超时)/需随访",
            placement: "top",
            effect: "dark",
          },
        },
        [h("span", column.label)]
      );
    },
    Tooltipsfl(h, { column }) {
      return h(
        "el-tooltip",
        {
          props: {
            content: "(随访成功+首次随访失败)/首次应随访",
            placement: "top",
            effect: "dark",
          },
        },
        [h("span", column.label)]
      );
    },
    getAllWardCodes() {
      return this.flatArrayhospit
        .filter((item) => item.value !== "all")
@@ -1214,10 +1256,12 @@
    // æ¸…理工作表名称,移除非法字符
    const cleanSheetName = (name) => {
      // Excel工作表名不能包含的字符: * ? : \ / [ ]
      return name.replace(/[*?:\\/[\]]/g, ' ');
          return name.replace(/[*?:\\/[\]]/g, " ");
    };
    const worksheetName = cleanSheetName(`再次${sheetTypeName}统计_${sheetNameSuffix}`);
        const worksheetName = cleanSheetName(
          `再次${sheetTypeName}统计_${sheetNameSuffix}`
        );
    if (!this.tableData || this.tableData.length === 0) {
      this.$message.warning(`暂无再次${serviceTypeName}数据可导出`);
vue.config.js
@@ -40,10 +40,10 @@
        // target: `http://192.168.100.10:8094`,//省立同德
        // target: `http://192.168.100.10:8095`,//新华
        // target: `http://192.168.100.10:8098`,//市一
        // target:`http://localhost:8095`,
        target:`http://localhost:8095`,
        // target:`http://35z1t16164.qicp.vip`,
        // target: `http://192.168.100.172:8095`,
        target: `http://192.168.100.10:8089`,//南华
        // target: `http://192.168.100.10:8089`,//南华
        // target: `http://192.168.191.181:8095`,
        changeOrigin: true,
        pathRewrite: {
ÍâÁ´.zip
Binary files differ
Ëæ·ÃͨÓà (2).zip
Binary files differ
Ëæ·ÃͨÓÃ.zip
Binary files differ