WXL (wul)
昨天 fb34ba28cb908bd328cf6690ab0b19a56428f4e2
测试完成
已删除4个文件
已修改13个文件
677 ■■■■■ 文件已修改
11.3.zip 补丁 | 查看 | 原始文档 | blame | 历史
dist.zip 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Satisfaction/sfstatistics/components/FollowupStatistics.vue 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/SatisfactionRelay.vue 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/followvisit/discharge/index.vue 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/followvisit/mzsatisfaction/index.vue 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/followvisit/zysatisfaction/index.vue 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/login.vue 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/patient/patient/behospitalized.vue 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/patient/patient/hospital.vue 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/patient/propaganda/QuestionnaireTask.vue 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/patient/propaganda/particty.vue 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/sfstatistics/percentage/components/CombinedFollowUp.vue 194 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/sfstatistics/percentage/components/FirstFollowUp.vue 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
vue.config.js 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
随访使用11.10.zip 补丁 | 查看 | 原始文档 | blame | 历史
随访适用11.10.zip 补丁 | 查看 | 原始文档 | blame | 历史
11.3.zip
Binary files differ
dist.zip
Binary files differ
src/views/Satisfaction/sfstatistics/components/FollowupStatistics.vue
@@ -9,7 +9,11 @@
        label-width="100px"
        class="query-form"
      >
        <el-form-item label="满意度类型" prop="satisfactionScope">
        <el-form-item
          v-if="isTongdeOrg"
          label="满意度类型"
          prop="satisfactionScope"
        >
          <el-select
            v-model="satisfactionScope"
            placeholder="默认在院"
@@ -546,7 +550,7 @@
  created() {
    this.orgname = localStorage.getItem("orgname");
    this.queryParams.serviceType = this.isTongdeOrg ? [6] : [2];
    this.initData();
    // é¡¶éƒ¨æ‚£è€…表单 / é—®é¢˜è¯¦æƒ…分析 tab:默认按当前统计口径加载一次
    this.maybeRefreshCompletedGroups();
src/views/SatisfactionRelay.vue
@@ -44,7 +44,8 @@
          console.log(res,'初始');
          if (res.code == 200) {
            console.log(res.msg);
            console.log(res.msg,'res.msg');
            // return
            window.location.href = res.msg;
            console.log("window后");
          } else {
src/views/followvisit/discharge/index.vue
@@ -142,6 +142,16 @@
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item
          v-if="isTongdeCampus"
          label="日间标记"
          prop="importanceFlagCode"
        >
          <el-input
            v-model="topqueryParams.importanceFlagCode"
            placeholder="请输入日间标记"
          ></el-input>
        </el-form-item>
        <el-form-item>
          <el-button
@@ -467,6 +477,16 @@
          key="currentPreachform"
          prop="currentPreachform"
          width="160"
          :show-overflow-tooltip="true"
        >
        </el-table-column>
        <el-table-column
          v-if="isTongdeCampus"
          label="日间标记"
          align="center"
          key="importanceFlagCode"
          prop="importanceFlagCode"
          width="120"
          :show-overflow-tooltip="true"
        >
        </el-table-column>
@@ -1421,6 +1441,7 @@
        leaveldeptcodes: [],
        leavehospitaldistrictcodes: [],
        currentPreachforms: [],
        importanceFlagCode: "",
      },
      orgname: "",
      propss: { multiple: true },
@@ -1702,9 +1723,13 @@
        // âœ… ç¬¬å››æ­¥ï¼šå¤„理其他数据
        if (refresh) {
          this.yfsvalue = response.rows[0].yfs;
          // é¡¶éƒ¨å¡ç‰‡çš„æ•°å­—不跟「随访状态/异常」走:单独查一次去掉状态条件的统计,
          // å¦åˆ™ç­›äº†ã€Œå¾…随访」后「已完成」永远是 0,看着像算错了
          this.refreshCardCounts(params);
          if (this.isTongdeOrg) {
            // çœç«‹åŒå¾·/南华:顶部卡片数字不跟「随访状态/异常」走,单独查一次去掉状态条件的统计
            this.refreshCardCounts(params);
          } else {
            // å…¶ä»–医院:顶部数据跟随筛选条件变动,单次查询即可
            this.setCardValues(response.rows[0]);
          }
        }
        // âœ… ç¬¬äº”步:处理 preachform ç­‰å…¶ä»–数据
@@ -1713,7 +1738,7 @@
          if (item.endtime) {
            item.endDay = this.daysBetween(item.endtime);
          }
          console.log(item,'3');
          console.log(item, "3");
          if (item.preachform) {
            item.preachformson = item.preachform;
@@ -2152,6 +2177,7 @@
        leaveldeptcodes: [],
        leavehospitaldistrictcodes: [],
        currentPreachforms: [],
        importanceFlagCode: "",
      };
      this.handleQuery(1);
    },
@@ -2173,6 +2199,7 @@
        leaveldeptcodes: [],
        leavehospitaldistrictcodes: [],
        currentPreachforms: [],
        importanceFlagCode: "",
      };
    },
    handleSelectionChange(rows) {
@@ -2495,6 +2522,18 @@
    // é¡¶éƒ¨ç»Ÿè®¡å¡ç‰‡ç‚¹å‡»ï¼šæŠŠå¯¹åº”筛选条件下带到下面的列表(数值为 0 çš„卡片同样可点)
    // é¡¶éƒ¨å¡ç‰‡ç»Ÿè®¡ï¼šåŽ»æŽ‰ã€Œéšè®¿çŠ¶æ€ / å¼‚常」条件后再统计,
    // è¿™æ ·å¡ç‰‡æ•°å­—只跟日期、科室/病区等条件走,不会因为筛了「待随访」就把「已完成」算成 0
    // æŠŠä¸€æ¬¡æŸ¥è¯¢è¿”回的统计行写入顶部卡片
    setCardValues(row) {
      if (!row) return;
      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.fssb) || 0;
      this.cardlist[5].value = Number(row.ywc) || 0;
      this.ycvalue = Number(row.yc) || 0;
      this.jgvalue = Number(row.jg) || 0;
    },
    async refreshCardCounts(baseQuery) {
      const query = {
        ...(baseQuery || this.topqueryParams),
@@ -2512,14 +2551,7 @@
        if (!res || !res.rows || !res.rows.length) {
          return;
        }
        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.fssb) || 0;
        this.cardlist[5].value = Number(row.ywc) || 0;
        this.ycvalue = Number(row.yc) || 0;
        this.jgvalue = Number(row.jg) || 0;
        this.setCardValues(row);
      } catch (e) {
        console.warn("刷新顶部卡片统计失败", e);
      }
src/views/followvisit/mzsatisfaction/index.vue
@@ -56,6 +56,23 @@
            @change="handleChange"
          ></el-cascader>
        </el-form-item>
        <el-form-item label="点位" prop="pointLocations" v-if="isTongdeCampus">
          <el-select
            v-model="topqueryParams.pointLocations"
            multiple
            filterable
            clearable
            placeholder="请选择点位"
            style="width: 240px"
          >
            <el-option
              v-for="item in pointOptions"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            ></el-option>
          </el-select>
        </el-form-item>
        <!-- <el-form-item label="服务状态" prop="status">
          <el-select
@@ -378,12 +395,15 @@
        </el-table-column>
        <el-table-column
          v-if="isTongdeCampus"
          label="点位编码"
          label="点位"
          width="120"
          align="center"
          key="pointLocation"
          prop="pointLocation"
        />
        >
          <template slot-scope="scope">
            {{ pointNameOf(scope.row) }}
          </template>
        </el-table-column>
        <el-table-column
          label="处理人员"
@@ -933,6 +953,7 @@
  updateUser,
  resetUserPwd,
  changeUserStatus,
  deptTreeSelect,
} from "@/api/system/user";
import {
  getTaskservelist,
@@ -1138,6 +1159,7 @@
        scopetype: [],
        leaveldeptcodes: [],
        leavehospitaldistrictcodes: [],
        pointLocations: [],
      },
      propss: { multiple: true },
      options: [],
@@ -1229,6 +1251,8 @@
      leavehospitaldistrictcode: "",
      serviceState: [],
      checkboxlist: [],
      // ç‚¹ä½åˆ—表(同德院区,deptType=3)
      pointOptions: [],
      // è¡¨å•校验
      rules: {},
    };
@@ -1259,6 +1283,7 @@
    } else {
      this.getList(1);
    }
    this.getPointOptions();
    this.getConfigKey("sys.user.initPassword").then((response) => {
      this.initPassword = response.msg;
    });
@@ -1285,21 +1310,26 @@
        );
        console.log(this.topqueryParams.leavehospitaldistrictcodes, "11");
      }
      const queryParams = this.buildQueryParams();
      this.loading = true;
      if (
        this.topqueryParams.leavehospitaldistrictcodes[0] &&
        this.topqueryParams.leaveldeptcodes[0]
        queryParams.leavehospitaldistrictcodes &&
        queryParams.leavehospitaldistrictcodes[0] &&
        queryParams.leaveldeptcodes &&
        queryParams.leaveldeptcodes[0]
      ) {
        this.topqueryParams.deptOrDistrict = 2;
        queryParams.deptOrDistrict = 2;
      } else {
        this.topqueryParams.deptOrDistrict = 1;
        queryParams.deptOrDistrict = 1;
      }
      if (!this.followupAuthority()) {
        this.$message.warning("未配置科室/病区相关权限不可查询");
        return Promise.reject(new Error("无权限查询"));
      }
      getTaskservelist(this.topqueryParams).then((response) => {
      getTaskservelist(queryParams).then((response) => {
        this.userList = response.rows[0].serviceSubtaskList;
        this.total = response.total;
        if (refresh) {
@@ -1359,6 +1389,40 @@
    getCurrentDate() {
      const now = new Date();
      return now.toISOString().slice(0, 10); // æˆªå–前10个字符,即 YYYY-MM-DD
    },
    // ç‚¹ä½åˆ—表(同德院区,deptType=3)
    getPointOptions() {
      if (!this.isTongdeCampus) return;
      deptTreeSelect(3).then((response) => {
        const flat = [];
        const walk = (nodes) => {
          (Array.isArray(nodes) ? nodes : []).forEach((n) => {
            if (n.label && n.deptCode) {
              flat.push({ label: n.label, value: String(n.deptCode) });
            }
            if (n.children && n.children.length) walk(n.children);
          });
        };
        walk(response && response.data);
        this.pointOptions = flat;
      });
    },
    // ç‚¹ä½åç§°ï¼šå°† pointLocation ç¼–码映射为点位名称
    pointNameOf(row) {
      if (
        !row ||
        row.pointLocation === undefined ||
        row.pointLocation === null ||
        row.pointLocation === ""
      ) {
        return "";
      }
      const found = this.pointOptions.find(
        (p) => String(p.value) === String(row.pointLocation)
      );
      return found ? found.label : row.pointLocation;
    },
    buidegetTasklist(type) {
      // ç”¨æˆ·æƒé™ä¸‹æ‰€æœ‰å¾…随访任务:传递全部科室和病区
@@ -1519,6 +1583,18 @@
      this.getList(refresh);
    },
    // æž„造查询/导出参数:选择点位时科室/病区传 null,否则保持原值
    buildQueryParams() {
      const params = { ...this.topqueryParams };
      if (
        this.topqueryParams.pointLocations &&
        this.topqueryParams.pointLocations.length > 0
      ) {
        params.leaveldeptcodes = null;
        params.leavehospitaldistrictcodes = null;
      }
      return params;
    },
    // æ‚£è€…范围处理
    handleChange(value) {
      let type = value[0];
@@ -1555,6 +1631,7 @@
        scopetype: [],
        leaveldeptcodes: [],
        leavehospitaldistrictcodes: [],
        pointLocations: [],
      };
      this.handleQuery(1);
    },
@@ -1828,7 +1905,7 @@
      this.download(
        "smartor/serviceSubtask/patItemExport",
        {
          ...this.topqueryParams,
          ...this.buildQueryParams(),
        },
        `user_${new Date().getTime()}.xlsx`
      ).finally(() => {
src/views/followvisit/zysatisfaction/index.vue
@@ -79,6 +79,23 @@
            @change="handleChange"
          ></el-cascader>
        </el-form-item>
        <el-form-item label="点位" prop="pointLocations" v-if="isTongdeCampus">
          <el-select
            v-model="topqueryParams.pointLocations"
            multiple
            filterable
            clearable
            placeholder="请选择点位"
            style="width: 240px"
          >
            <el-option
              v-for="item in pointOptions"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            ></el-option>
          </el-select>
        </el-form-item>
        <!-- <el-form-item label="服务状态" prop="status">
          <el-select
@@ -409,12 +426,15 @@
        </el-table-column>
        <el-table-column
          v-if="isTongdeCampus"
          label="点位编码"
          label="点位"
          width="120"
          align="center"
          key="pointLocation"
          prop="pointLocation"
        />
        >
          <template slot-scope="scope">
            {{ pointNameOf(scope.row) }}
          </template>
        </el-table-column>
        <el-table-column
          label="处理人员"
@@ -926,6 +946,7 @@
  updateUser,
  resetUserPwd,
  changeUserStatus,
  deptTreeSelect,
} from "@/api/system/user";
import {
  getTaskservelist,
@@ -1134,6 +1155,7 @@
        scopetype: [],
        leaveldeptcodes: [],
        leavehospitaldistrictcodes: [],
        pointLocations: [],
      },
      propss: { multiple: true },
      options: [],
@@ -1225,6 +1247,8 @@
      leavehospitaldistrictcode: "",
      serviceState: [],
      checkboxlist: [],
      // ç‚¹ä½åˆ—表(同德院区,deptType=3)
      pointOptions: [],
      // è¡¨å•校验
      rules: {},
    };
@@ -1255,6 +1279,7 @@
    } else {
      this.getList(1);
    }
    this.getPointOptions();
    this.getConfigKey("sys.user.initPassword").then((response) => {
      this.initPassword = response.msg;
    });
@@ -1281,21 +1306,26 @@
        );
        console.log(this.topqueryParams.leavehospitaldistrictcodes, "11");
      }
      const queryParams = this.buildQueryParams();
      this.loading = true;
      if (
        this.topqueryParams.leavehospitaldistrictcodes[0] &&
        this.topqueryParams.leaveldeptcodes[0]
        queryParams.leavehospitaldistrictcodes &&
        queryParams.leavehospitaldistrictcodes[0] &&
        queryParams.leaveldeptcodes &&
        queryParams.leaveldeptcodes[0]
      ) {
        this.topqueryParams.deptOrDistrict = 2;
        queryParams.deptOrDistrict = 2;
      } else {
        this.topqueryParams.deptOrDistrict = 1;
        queryParams.deptOrDistrict = 1;
      }
      if (!this.followupAuthority()) {
        this.$message.warning("未配置科室/病区相关权限不可查询");
        return Promise.reject(new Error("无权限查询"));
      }
      getTaskservelist(this.buildScopePayload(this.topqueryParams)).then((response) => {
      getTaskservelist(this.buildScopePayload(queryParams)).then((response) => {
        this.userList = response.rows[0].serviceSubtaskList;
        this.total = response.total;
        if (refresh) {
@@ -1353,8 +1383,9 @@
    buildScopePayload(params) {
      const payload = { ...params };
      if (this.satisfactionScope === "hospital") {
        payload.deptcodes = params.leaveldeptcodes || [];
        payload.hospitaldistrictcodes = params.leavehospitaldistrictcodes || [];
        // é€‰ç‚¹ä½æ—¶ leaveldeptcodes/leavehospitaldistrictcodes ä¸º null,需原样透传,不能 || [] å…œæˆç©ºæ•°ç»„
        payload.deptcodes = params.leaveldeptcodes;
        payload.hospitaldistrictcodes = params.leavehospitaldistrictcodes;
        delete payload.leaveldeptcodes;
        delete payload.leavehospitaldistrictcodes;
      }
@@ -1379,6 +1410,40 @@
          ? row.hospitaldistrictname || row.leavehospitaldistrictname
          : row.leavehospitaldistrictname || row.hospitaldistrictname) || "-"
      );
    },
    // ç‚¹ä½åˆ—表(同德院区,deptType=3)
    getPointOptions() {
      if (!this.isTongdeCampus) return;
      deptTreeSelect(3).then((response) => {
        const flat = [];
        const walk = (nodes) => {
          (Array.isArray(nodes) ? nodes : []).forEach((n) => {
            if (n.label && n.deptCode) {
              flat.push({ label: n.label, value: String(n.deptCode) });
            }
            if (n.children && n.children.length) walk(n.children);
          });
        };
        walk(response && response.data);
        this.pointOptions = flat;
      });
    },
    // ç‚¹ä½åç§°ï¼šå°† pointLocation ç¼–码映射为点位名称
    pointNameOf(row) {
      if (
        !row ||
        row.pointLocation === undefined ||
        row.pointLocation === null ||
        row.pointLocation === ""
      ) {
        return "";
      }
      const found = this.pointOptions.find(
        (p) => String(p.value) === String(row.pointLocation)
      );
      return found ? found.label : row.pointLocation;
    },
    // æœåŠ¡çŠ¶æ€å˜æ›´å¤„ç†
@@ -1559,6 +1624,18 @@
      this.topqueryParams.finishtimeEnd = this.dateRangefs[1];
      this.getList(refresh);
    },
    // æž„造查询/导出参数:选择点位时科室/病区传 null,否则保持原值
    buildQueryParams() {
      const params = { ...this.topqueryParams };
      if (
        this.topqueryParams.pointLocations &&
        this.topqueryParams.pointLocations.length > 0
      ) {
        params.leaveldeptcodes = null;
        params.leavehospitaldistrictcodes = null;
      }
      return params;
    },
    // æ‚£è€…范围处理
    handleChange(value) {
      let type = value[0];
@@ -1594,6 +1671,7 @@
        scopetype: [],
        leaveldeptcodes: [],
        leavehospitaldistrictcodes: [],
        pointLocations: [],
      };
      this.handleQuery(1);
    },
@@ -1615,6 +1693,7 @@
        scopetype: [],
        leaveldeptcodes: [],
        leavehospitaldistrictcodes: [],
        pointLocations: [],
      };
    },
    handleSelectionChange(rows) {
@@ -1916,7 +1995,7 @@
      this.download(
        "smartor/serviceSubtask/patItemExport",
        {
          ...this.buildScopePayload(this.topqueryParams),
          ...this.buildScopePayload(this.buildQueryParams()),
        },
        `user_${new Date().getTime()}.xlsx`
      ).finally(() => {
src/views/login.vue
@@ -39,16 +39,16 @@
        </el-input>
      </el-form-item>
      <!-- ä¸½===================æ°´ -->
      <el-form-item prop="campusid">
      <el-form-item prop="orgid">
        <el-select
          style="width: 100%"
          v-model="loginForm.campusid"
          v-model="loginForm.orgid"
          placeholder="请选择院区"
        >
          <el-option
            v-for="item in options"
            :label="item.label"
            :value="item.campusid"
            :value="item.value"
          >
          </el-option>
          <i slot="prefix" class="el-icon-mobile"></i>
@@ -127,7 +127,7 @@
        password: "",
        rememberMe: false,
        code: "",
        orgid: "H41010500003",
        orgid: "",
      },
      options: [],
      loginRules: {
@@ -137,7 +137,7 @@
        password: [
          { required: true, trigger: "blur", message: "请输入您的密码" },
        ],
        campusid: [{ required: true, trigger: "blur", message: "请选择院区" }],
        orgid: [{ required: true, trigger: "change", message: "请选择院区" }],
      },
      loading: false,
      // éªŒè¯ç å¼€å…³
@@ -164,11 +164,11 @@
    //   this.loginForm.orgid = localStorage.getItem('orgid');
    // }
  },
    computed: {
  computed: {
    isAdmin() {
      const roles = this.$store.getters.roles || [];
      return roles.includes("mydstaff");
    }
    },
  },
  methods: {
    getCode() {
@@ -184,11 +184,23 @@
    getorganization() {
      getorganization({ pageSize: 30 }).then((res) => {
        if (res.code == 200) {
          this.options = res.rows.map((item) => ({
            value: item.orgid,
            label: item.organizationName,
            campusid: item.organizationID,
          }));
          // åŒå¾·ç³»åˆ— / å—华系列 / æµ™æ±Ÿçœæ–°åŽåŒ»é™¢ï¼šç”¨ campusid(organizationID) ä½œä¸‹æ‹‰é”®å€¼ï¼›
          // å…¶ä½™ï¼ˆä¸½æ°´åŒºåŸŸ organizationID å…¨ä¸º "1" ä¸å”¯ä¸€ï¼‰ï¼šç”¨ orgid ä½œä¸‹æ‹‰é”®å€¼
          const campusidKeywords = ["同德", "南华", "浙江省新华医院"];
          this.options = (res.rows || []).map((item) => {
            console.log(item.organizationName);
            const name = item.organizationName || "";
            const useCampusid = campusidKeywords.some((kw) =>
              name.includes(kw)
            );
            return {
              value: String(useCampusid ? item.organizationID : item.orgid),
              label: name,
              campusid: item.organizationID,
              orgid: item.orgid,
            };
          });
        }
      });
    },
@@ -233,13 +245,16 @@
            Cookies.remove("rememberMe");
          }
          // åŠ¨æ€è®¾ç½® campusid å‚æ•°
          // é”®å€¼è§„则:丽水区域用 orgid(organizationID/campusid å‡ä¸º "1" ä¸å”¯ä¸€ï¼‰ï¼›
          // åŒå¾·/南华/浙江省新华医院等区域用 campusid(organizationID) ä½œä¸‹æ‹‰é”®å€¼
          const selectedOrg = this.options.find(
            (item) => item.campusid === this.loginForm.campusid
            (item) => String(item.value) === String(this.loginForm.orgid)
          );
          this.loginForm.campusid = selectedOrg.campusid || 1;
          this.loginForm.orgid = selectedOrg.value || 1;
          this.loginForm.orgname = selectedOrg.label || "";
          if (selectedOrg) {
            this.loginForm.campusid = selectedOrg.campusid;
            this.loginForm.orgid = selectedOrg.orgid;
            this.loginForm.orgname = selectedOrg.label;
          }
          // å¸‚一处理-----------------
          // if (selectedOrg) {
          //   if (selectedOrg.label.includes("湖滨")) {
@@ -259,7 +274,7 @@
              } else if (this.isAdmin) {
                console.log(1);
                 this.$router
                this.$router
                  .push({ path: "/Intelligentcenter/dispose" })
                  .catch(() => {});
              } else {
@@ -281,7 +296,6 @@
        }
      });
    },
  },
};
</script>
src/views/patient/patient/behospitalized.vue
@@ -1089,7 +1089,8 @@
            templateid: this.selectedTask.templateid,
            libtemplateid: this.selectedTask.libtemplateid,
            sendstate: 2, // å‘送状态
            continueFlag: 1, // å»¶ç»­æŠ¤ç†æ ‡å¿—(在院患者)
            continueFlag: 2, // å»¶ç»­æŠ¤ç†æ ‡å¿—(在院患者)
            hospType: 6, // æ‚£è€…类型:6=住院
            ...patient,
            sendname: patient.patname,
            // åœ¨é™¢æ‚£è€…使用当前时间作为任务开始时间
src/views/patient/patient/hospital.vue
@@ -1014,6 +1014,7 @@
            libtemplateid: this.selectedTask.libtemplateid,
            sendstate: 2,
            continueFlag: 2,
            hospType: 2, // æ‚£è€…类型:2=出院
            ...patient,
            sendname: patient.patname,
            starttime: patient.starttime ? patient.starttime + " 00:00:00" : "",
src/views/patient/propaganda/QuestionnaireTask.vue
@@ -70,18 +70,27 @@
                  />
                </el-form-item>
                <el-form-item
                <!-- <el-form-item
                  label="点位编码"
                  v-if="
                    isTongdeCampus && (serviceType == 6 || serviceType == 14)
                  "
                >
                  <el-input
                    style="width: 220px"
                  <el-select
                    v-model="form.pointLocation"
                    placeholder="请输入点位编码"
                  />
                </el-form-item>
                    style="width: 220px"
                    clearable
                    filterable
                    placeholder="请选择点位"
                  >
                    <el-option
                      v-for="item in pointOptions"
                      :key="item.value"
                      :label="item.label"
                      :value="item.value"
                    />
                  </el-select>
                </el-form-item> -->
                <el-form-item label="服务形式">
                  <SortCheckbox
@@ -222,8 +231,29 @@
                      >药品关联</el-radio
                    >
                    <el-radio label="5">任务组</el-radio>
                    <el-radio label="7" v-if="isTongdeCampus&& (serviceType == 6 || serviceType == 14)">点位关联</el-radio>
                  </el-radio-group>
                </el-form-item>
                <!-- ç‚¹ä½å…³è” -->
                <el-row v-if="form.appltype == 7">
                  <el-form-item label="关联点位" prop="pointLocation">
                    <el-select
                      v-model="form.pointLocation"
                      style="width: 400px"
                      clearable
                      filterable
                      placeholder="请选择点位"
                    >
                      <el-option
                        v-for="item in pointOptions"
                        :key="item.value"
                        :label="item.label"
                        :value="item.value"
                      />
                    </el-select>
                  </el-form-item>
                </el-row>
                <!-- è¯å“å…³è” -->
                <el-row v-if="form.appltype == 6">
@@ -1502,6 +1532,7 @@
} from "@/api/AiCentre/index";
import { listMedication } from "@/api/knowledge/drug";
import { getIvrtask } from "@/api/smartor/ivrtask";
import { deptTreeSelect } from "@/api/system/user";
import OptionalForm from "@/components/OptionalForm";
import SFtable from "@/components/SFtable";
import SortCheckbox from "@/components/SortCheckbox";
@@ -1765,6 +1796,8 @@
      queryParamsdept: {},
      quote: false,
      serviceType: null,
      // å¯é€‰ç‚¹ä½ï¼ˆåŒå¾·é™¢åŒºï¼ŒdeptType=3)
      pointOptions: [],
      // å†æ¬¡éšè®¿å…³è”任务(缙云县人民医院)
      nextTaskDialogVisible: false,
      nextTaskLoading: false,
@@ -1793,6 +1826,7 @@
    this.getillnesslist();
    this.Getdetails();
    this.getQtemplateclassify();
    this.getPointOptions();
  },
  activated() {
    if (this.id != this.$route.query.id) {
@@ -1864,6 +1898,23 @@
    },
    // ---------- æ•°æ®åŠ è½½ ----------
    getPointOptions() {
      // ä»…同德院区:点位下拉(deptType=3)
      if (!this.isTongdeCampus) return;
      deptTreeSelect(3).then((response) => {
        const flat = [];
        const walk = (nodes) => {
          (Array.isArray(nodes) ? nodes : []).forEach((n) => {
            if (n.label && n.deptCode) {
              flat.push({ label: n.label, value: String(n.deptCode) });
            }
            if (n.children && n.children.length) walk(n.children);
          });
        };
        walk(response && response.data);
        this.pointOptions = flat;
      });
    },
    Acquisitiontype() {
      let queryParams = {
        pageNum: this.topqueryParams.pageNum,
@@ -2936,6 +2987,12 @@
          this.leavehospitaldistrictcodes = [];
          this.illnesscodes = [];
          this.form.oplevelcode = null;
        } else if (this.form.appltype == 7) {
          this.deptcodesWards = [];
          this.leavehospitaldistrictcodes = [];
          this.illnesscodes = [];
          this.form.oplevelcode = null;
          this.medicalCodes = [];
        }
        // æœåŠ¡å½¢å¼æ ¡éªŒ
@@ -2955,6 +3012,7 @@
          this.diagglist[0] ||
          this.form.oplevelcode ||
          this.medicalCodes[0] ||
          this.form.pointLocation ||
          this.form.longTask == 2 ||
          this.serviceType == 3 ||
          this.form.appltype == 5;
src/views/patient/propaganda/particty.vue
@@ -70,13 +70,22 @@
                  />
                </el-form-item>
                <el-form-item label="点位编码" v-if="isTongdeCampus&& (serviceType == 6 || serviceType == 14)">
                  <el-input
                    style="width: 220px"
                <!-- <el-form-item label="点位编码" v-if="isTongdeCampus&& (serviceType == 6 || serviceType == 14)">
                  <el-select
                    v-model="form.pointLocation"
                    placeholder="请输入点位编码"
                  />
                </el-form-item>
                    style="width: 220px"
                    clearable
                    filterable
                    placeholder="请选择点位"
                  >
                    <el-option
                      v-for="item in pointOptions"
                      :key="item.value"
                      :label="item.label"
                      :value="item.value"
                    />
                  </el-select>
                </el-form-item> -->
                <el-form-item label="服务形式">
                  <SortCheckbox
@@ -214,8 +223,29 @@
                    <el-radio label="4">手术关联</el-radio>
                    <el-radio label="5">任务组</el-radio>
                    <el-radio label="6">药品关联</el-radio>
                    <el-radio label="7"v-if="isTongdeCampus&& (serviceType == 6 || serviceType == 14)">点位关联</el-radio>
                  </el-radio-group>
                </el-form-item>
                <!-- ç‚¹ä½å…³è” -->
                <el-row v-if="form.appltype == 7">
                  <el-form-item label="关联点位" prop="pointLocation">
                    <el-select
                      v-model="form.pointLocation"
                      style="width: 400px"
                      clearable
                      filterable
                      placeholder="请选择点位"
                    >
                      <el-option
                        v-for="item in pointOptions"
                        :key="item.value"
                        :label="item.label"
                        :value="item.value"
                      />
                    </el-select>
                  </el-form-item>
                </el-row>
                <!-- è¯å“å…³è” -->
                <el-row v-if="form.appltype == 6">
@@ -1772,6 +1802,8 @@
      belongDepts: [],
      quote: false,
      serviceType: null,
      // å¯é€‰ç‚¹ä½ï¼ˆåŒå¾·é™¢åŒºï¼ŒdeptType=3)
      pointOptions: [],
      // å†æ¬¡éšè®¿å…³è”任务(缙云县人民医院)
      orgname: localStorage.getItem("orgname"),
      nextTaskDialogVisible: false,
@@ -1802,6 +1834,7 @@
    this.getillnesslist();
    this.Getdetails();
    this.getFollowupclassify();
    this.getPointOptions();
  },
  activated() {
    if (this.id != this.$route.query.id) {
@@ -1882,6 +1915,23 @@
    },
    // ---------- æ•°æ®åŠ è½½ ----------
    getPointOptions() {
      // ä»…同德院区:点位下拉(deptType=3)
      if (!this.isTongdeCampus) return;
      deptTreeSelect(3).then((response) => {
        const flat = [];
        const walk = (nodes) => {
          (Array.isArray(nodes) ? nodes : []).forEach((n) => {
            if (n.label && n.deptCode) {
              flat.push({ label: n.label, value: String(n.deptCode) });
            }
            if (n.children && n.children.length) walk(n.children);
          });
        };
        walk(response && response.data);
        this.pointOptions = flat;
      });
    },
    Acquisitiontype() {
      let queryParams = {
        pageNum: this.topqueryParams.pageNum,
@@ -2963,6 +3013,12 @@
          this.leavehospitaldistrictcodes = [];
          this.illnesscodes = [];
          this.operationcodes = [];
        } else if (this.form.appltype == 7) {
          this.deptcodesWards = [];
          this.leavehospitaldistrictcodes = [];
          this.illnesscodes = [];
          this.operationcodes = [];
          this.medicalCodes = [];
        }
        // æœåŠ¡å½¢å¼æ ¡éªŒ
@@ -2982,6 +3038,7 @@
          this.diagglist[0] ||
          this.operationcodes[0] ||
          this.medicalCodes[0] ||
          this.form.pointLocation ||
          this.form.longTask == 2 ||
          this.serviceType == 3 ||
          this.form.appltype == 5; // ä»»åŠ¡ç»„è·³è¿‡å¼ºåˆ¶å…³è”
src/views/sfstatistics/percentage/components/CombinedFollowUp.vue
@@ -1301,7 +1301,7 @@
      };
      // æ ‡é¢˜è¡Œ
      worksheet.mergeCells(1, 1, 1, 20);
      worksheet.mergeCells(1, 1, 1, 26);
      worksheet.getCell(
        1,
        1
@@ -1356,13 +1356,40 @@
        worksheet.getCell(3, col).style = headerStyle;
      });
      // æ–°å¢žè®¡ç®—指标
      worksheet.mergeCells(2, 16, 3, 16);
      worksheet.getCell(2, 16).value = "随访率";
      // éšè®¿æƒ…况大列(正常语音/拒接或拒访/面访或接诊/微信/电话不正确/其他)
      worksheet.mergeCells(2, 16, 2, 21);
      worksheet.getCell(2, 16).value = "随访情况";
      worksheet.getCell(2, 16).style = headerStyle;
      worksheet.mergeCells(2, 17, 3, 17);
      worksheet.getCell(2, 17).value = "推送率";
      worksheet.getCell(2, 17).style = headerStyle;
      const situationCols = [
        "正常语音",
        "患者拒接或拒访",
        "面访或者接诊",
        "微信随访",
        "随访电话不正确",
        "其他情况不宜随访",
      ];
      situationCols.forEach((label, idx) => {
        const col = 16 + idx;
        worksheet.getCell(3, col).value = label;
        worksheet.getCell(3, col).style = headerStyle;
      });
      // æ–°å¢žè®¡ç®—指标
      worksheet.mergeCells(2, 22, 3, 22);
      worksheet.getCell(2, 22).value = "随访率";
      worksheet.getCell(2, 22).style = headerStyle;
      worksheet.mergeCells(2, 23, 3, 23);
      worksheet.getCell(2, 23).value = "推送率";
      worksheet.getCell(2, 23).style = headerStyle;
      worksheet.mergeCells(2, 24, 3, 24);
      worksheet.getCell(2, 24).value = "已拨通";
      worksheet.getCell(2, 24).style = headerStyle;
      worksheet.mergeCells(2, 25, 3, 25);
      worksheet.getCell(2, 25).value = "再次随访推送人数";
      worksheet.getCell(2, 25).style = headerStyle;
      worksheet.mergeCells(2, 26, 3, 26);
      worksheet.getCell(2, 26).value = "追踪随访推送率";
      worksheet.getCell(2, 26).style = headerStyle;
      // æ•°æ®è¡Œ
      this.tableData.forEach((item) => {
@@ -1390,8 +1417,17 @@
            item.needFollowUpAgain,
            item.pendingFollowUpAgain
          ),
          item.taskSituation1 || 0,
          item.taskSituation2 || 0,
          item.taskSituation3 || 0,
          item.taskSituation4 || 0,
          item.taskSituation5 || 0,
          item.taskSituation6 || 0,
          this.calculateFollowUpRate(item),
          this.calculatePushRate(item),
          item.manuallyCalled || 0,
          item.againFollowUpPushCount || 0,
          this.calculateAgainFollowUpPushRate(item),
        ];
        const row = worksheet.addRow(rowData);
        row.eachCell((cell) => {
@@ -1426,61 +1462,77 @@
        { width: 12 },
        { width: 12 },
        { width: 12 },
        { width: 12 },
        { width: 12 },
        { width: 12 },
        { width: 12 },
        { width: 12 },
        { width: 12 },
        { width: 12 },
        { width: 12 },
        { width: 12 },
      ];
    },
    getExportSummaries() {
      // æå–数据,计算合计行
      // æå–数据,计算合计行(26 åˆ—:与主表导出表头一致)
      const data = this.tableData;
      const sums = [
        "合计",
        "/",
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        "0%",
        0,
        0,
        0,
        0,
        "0%",
        "0%",
        "0%",
        "合计", // 0
        "/", // 1
        0, // 2 å‡ºé™¢äººæ¬¡
        0, // 3 æ— éœ€éšè®¿
        0, // 4 åº”随访
        0, // 5 éœ€éšè®¿(首次)
        0, // 6 å¾…随访(首次)
        0, // 7 å®Œæˆ(首次)
        0, // 8 å¤±è´¥(首次)
        "0.00%", // 9 æˆåŠŸçŽ‡(首次)
        0, // 10 éœ€éšè®¿(再次)
        0, // 11 å¾…随访(再次)
        0, // 12 å®Œæˆ(再次)
        0, // 13 å¤±è´¥(再次)
        "0.00%", // 14 æˆåŠŸçŽ‡(再次)
        0, // 15 æ­£å¸¸è¯­éŸ³
        0, // 16 æ‚£è€…拒接或拒访
        0, // 17 é¢è®¿æˆ–者接诊
        0, // 18 å¾®ä¿¡éšè®¿
        0, // 19 éšè®¿ç”µè¯ä¸æ­£ç¡®
        0, // 20 å…¶ä»–情况不宜随访
        "0.00%", // 21 éšè®¿çއ
        "0.00%", // 22 æŽ¨é€çއ
        0, // 23 å·²æ‹¨é€š
        0, // 24 å†æ¬¡éšè®¿æŽ¨é€äººæ•°
        "0.00%", // 25 è¿½è¸ªéšè®¿æŽ¨é€çއ
      ];
      // æ•°å­—列索引
      const numIndices = [2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13];
      data.forEach((row) => {
        numIndices.forEach((idx) => {
          const val = Number(row[this.getFieldByIndex(idx)]) || 0;
          sums[idx] += val;
        });
      // æ•°å­—列求和(索引 -> å­—段名)
      const numFields = [
        [2, "dischargeCount"],
        [3, "nonFollowUp"],
        [4, "followUpNeeded"],
        [5, "needFollowUp"],
        [6, "pendingFollowUp"],
        [7, "followUpSuccess"],
        [8, "followUpFail"],
        [10, "needFollowUpAgain"],
        [11, "pendingFollowUpAgain"],
        [12, "followUpSuccessAgain"],
        [13, "followUpFailAgain"],
        [15, "taskSituation1"],
        [16, "taskSituation2"],
        [17, "taskSituation3"],
        [18, "taskSituation4"],
        [19, "taskSituation5"],
        [20, "taskSituation6"],
        [23, "manuallyCalled"],
        [24, "againFollowUpPushCount"],
      ];
      numFields.forEach(([idx, field]) => {
        sums[idx] = this.formatNumber(
          data.reduce((s, row) => s + (Number(row[field]) || 0), 0)
        );
      });
      // æ ¼å¼åŒ–æ•°å­—
      numIndices.forEach((idx) => {
        sums[idx] = this.formatNumber(sums[idx]);
      });
      // è®¡ç®—两个百分比列的平均值
      const followUpRates = data
        .map((row) =>
          parseFloat(this.calculateFollowUpRate(row).replace("%", ""))
        )
        .filter((v) => !isNaN(v));
      const pushRates = data
        .map((row) => parseFloat(this.calculatePushRate(row).replace("%", "")))
        .filter((v) => !isNaN(v));
      sums[15] = followUpRates.length
        ? (
            followUpRates.reduce((a, b) => a + b, 0) / followUpRates.length
          ).toFixed(2) + "%"
        : "0.00%";
      sums[16] = pushRates.length
        ? (pushRates.reduce((a, b) => a + b, 0) / pushRates.length).toFixed(2) +
          "%"
        : "0.00%";
      // æˆåŠŸçŽ‡çš„åˆè®¡ç”¨æ•´ä½“æ³•è®¡ç®—
      const totalSuccess = data.reduce(
        (s, row) => s + (Number(row.followUpSuccess) || 0),
@@ -1514,6 +1566,40 @@
        denomAgain > 0
          ? ((totalSuccessAgain / denomAgain) * 100).toFixed(2) + "%"
          : "0.00%";
      // éšè®¿çއ / æŽ¨é€çŽ‡ï¼šå–å„è¡Œçš„å¹³å‡å€¼
      const followUpRates = data
        .map((row) =>
          parseFloat(this.calculateFollowUpRate(row).replace("%", ""))
        )
        .filter((v) => !isNaN(v));
      sums[21] = followUpRates.length
        ? (
            followUpRates.reduce((a, b) => a + b, 0) / followUpRates.length
          ).toFixed(2) + "%"
        : "0.00%";
      const pushRates = data
        .map((row) => parseFloat(this.calculatePushRate(row).replace("%", "")))
        .filter((v) => !isNaN(v));
      sums[22] = pushRates.length
        ? (pushRates.reduce((a, b) => a + b, 0) / pushRates.length).toFixed(2) +
          "%"
        : "0.00%";
      // è¿½è¸ªéšè®¿æŽ¨é€çŽ‡ï¼šæ•´ä½“æ³• = å†æ¬¡éšè®¿æŽ¨é€äººæ•°åˆè®¡ / å‡ºé™¢äººæ¬¡åˆè®¡
      const totalPush = data.reduce(
        (s, row) => s + (Number(row.againFollowUpPushCount) || 0),
        0
      );
      const totalDischarge = data.reduce(
        (s, row) => s + (Number(row.dischargeCount) || 0),
        0
      );
      sums[25] =
        totalDischarge > 0
          ? ((totalPush / totalDischarge) * 100).toFixed(2) + "%"
          : "0.00%";
      return sums;
    },
src/views/sfstatistics/percentage/components/FirstFollowUp.vue
@@ -1660,19 +1660,9 @@
            sheetNameSuffix = `${startDateFormatted}至${endDateFormatted}`;
          }
        } else {
          const now = new Date();
          const currentMonth = now.getMonth() + 1;
          const currentYear = now.getFullYear();
          if (isLishuiHospital) {
            // ä¸½æ°´å¸‚中医院:显示年月
            dateRangeString = `${currentYear}å¹´${currentMonth}月`;
            sheetNameSuffix = `${currentYear}å¹´${currentMonth}月`;
          } else {
            // å…¶ä»–医院:显示月份
            dateRangeString = `${currentMonth}月`;
            sheetNameSuffix = `${currentMonth}月`;
          }
          // æœªé€‰æ‹©æ—¶é—´ï¼šæ•°æ®æœªåšæ—¶é—´ç­›é€‰ï¼Œä¸ºå…¨éƒ¨æ•°æ®ï¼Œæ–‡ä»¶åæ ‡æ³¨â€œå…¨éƒ¨â€
          dateRangeString = "全部";
          sheetNameSuffix = "全部";
        }
        // æ ¹æ® serviceType ç”Ÿæˆéšè®¿ç±»åž‹åç§°ï¼ˆå…¼å®¹å•选/多选)
@@ -1768,7 +1758,8 @@
          const end = this.queryParams.dateRange[1].split(" ")[0];
          dateRangeString = `${start}至${end}`;
        } else {
          dateRangeString = `${new Date().getMonth() + 1}月`;
          // æœªé€‰æ‹©æ—¶é—´ï¼šæ•°æ®ä¸ºå…¨éƒ¨
          dateRangeString = "全部";
        }
        const fileName = `${areaName}医生随访列表_${dateRangeString}.xlsx`;
vue.config.js
@@ -36,14 +36,14 @@
      // detail: https://cli.vuejs.org/config/#devserver-proxy
      [process.env.VUE_APP_BASE_API]: {
        // target: `https://www.health-y.cn/lssf`,
        target: `http://192.168.100.10:8096`,
        // target: `http://192.168.100.10:8094`,//省立同德
        // target: `http://192.168.100.10:8096`,
        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://192.168.100.168:8095`,
        // target:`http://35z1t16164.qicp.vip`,
        // target: `http://192.168.100.172:8095`,
        // target: `http://220.66.153.137:8095`,
        // target: `http://192.168.100.10:8089`,//南华
        // target: `https://9.208.38.93:8092/`,
        changeOrigin: true,
Ëæ·ÃʹÓÃ11.10.zip
Binary files differ
Ëæ·ÃÊÊÓÃ11.10.zip
Binary files differ