From 38c2fe23d77c9f27d52941dab77a100bb1839dd7 Mon Sep 17 00:00:00 2001
From: WXL (wul) <wl_5969728@163.com>
Date: 星期二, 02 九月 2025 16:31:10 +0800
Subject: [PATCH] 测试完成

---
 vue.config.js                                              |    2 
 src/views/followvisit/record/detailpage/index.vue          |  114 ++++++++++
 src/views/patient/patient/outpatient.vue                   |    6 
 src/views/followvisit/record/detailpage/MergeAndModify.vue |  449 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 563 insertions(+), 8 deletions(-)

diff --git a/src/views/followvisit/record/detailpage/MergeAndModify.vue b/src/views/followvisit/record/detailpage/MergeAndModify.vue
new file mode 100644
index 0000000..6449d1e
--- /dev/null
+++ b/src/views/followvisit/record/detailpage/MergeAndModify.vue
@@ -0,0 +1,449 @@
+<template>
+  <div class="merge-questionnaire-container">
+    <div class="merge-header">
+      <h3>鍚堝苟缂栬緫闂嵎 (鍏� {{ services.length }} 涓湭瀹屾垚鏈嶅姟)</h3>
+      <el-tag
+        v-for="service in services"
+        :key="service.id"
+        type="info"
+        style="margin-right: 10px"
+      >
+        {{ service.taskName }} ({{ service.sendname }})
+      </el-tag>
+    </div>
+
+    <div class="merge-content">
+      <div class="question-list">
+        <div
+          v-for="(question, index) in mergedQuestions"
+          :key="question.uniqueKey"
+          class="question-item"
+        >
+          <!-- 棰樼洰灞曠ず - 涓庣埗缁勪欢淇濇寔涓�鑷� -->
+          <div
+            :class="
+              question.isabnormal ? 'scriptTopic-isabnormal' : 'scriptTopic-dev'
+            "
+          >
+            <div class="dev-text">
+              {{ index + 1 }}銆乕{{
+                getQuestionType(question.scriptType)
+              }}]<span> {{ question.scriptContent }}</span>
+            </div>
+
+            <!-- 鍗曢�� -->
+            <div class="dev-xx" v-if="question.scriptType == 1">
+              <el-radio-group
+                v-model="question.mergedResult"
+                @change="
+                  handleOptionChange(
+                    $event,
+                    index,
+                    question.svyLibTemplateTargetoptions,
+                    question
+                  )
+                "
+                >11
+                <el-radio
+                  v-for="(
+                    option, optIndex
+                  ) in question.svyLibTemplateTargetoptions"
+                  :key="optIndex"
+                  :label="option.optioncontent"
+                  :class="option.isabnormal ? 'red-star' : ''"
+                >
+                  {{ option.optioncontent }}
+                </el-radio>
+              </el-radio-group>
+            </div>
+
+            <!-- 澶氶�� -->
+            <div class="dev-xx" v-if="question.scriptType == 2">
+              <el-checkbox-group
+                v-model="question.mergedResult"
+                @change="updateScore($event, index, question.options, question)"
+              >
+                <el-checkbox
+                  v-for="(option, optIndex) in question.options"
+                  :key="optIndex"
+                  :label="option.optioncontent"
+                  :class="option.isabnormal ? 'red-star' : ''"
+                >
+                  {{ option.optioncontent }}
+                </el-checkbox>
+              </el-checkbox-group>
+            </div>
+
+            <!-- 濉┖ -->
+            <div class="dev-xx" v-if="question.scriptType == 4">
+              <el-input
+                type="textarea"
+                :rows="2"
+                placeholder="璇疯緭鍏ョ瓟妗�"
+                v-model="question.mergedResult"
+                clearable
+              />
+            </div>
+
+            <!-- 闄勫姞杈撳叆妗� -->
+            <div v-if="question.showAppendInput" class="append-input-container">
+              <el-input
+                type="textarea"
+                :rows="2"
+                placeholder="璇疯緭鍏ュ叿浣撲俊鎭�"
+                v-model="question.answerps"
+                clearable
+              />
+            </div>
+
+            <!-- 鎻愮ず淇℃伅 -->
+            <div v-show="question.prompt">
+              <el-alert :title="question.prompt" type="warning" />
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <div class="merge-footer">
+      <el-button @click="handleCancel">鍙栨秷</el-button>
+      <el-button type="primary" @click="handleSave" :loading="isSaving"
+        >淇濆瓨鍒版墍鏈夐棶鍗�</el-button
+      >
+    </div>
+  </div>
+</template>
+
+<script>
+import {
+  getsearchrResults,
+  serviceSubtaskDetailedit,
+  serviceSubtaskDetailadd,
+  Editsingletaskson,
+  getTaskservelist,
+  alterpatient,
+} from "@/api/AiCentre/index";
+
+export default {
+  props: {
+    selectedServices: {
+      type: Array,
+      required: true,
+    },
+    patid: {
+      type: [String, Number],
+      required: true,
+    },
+  },
+  data() {
+    return {
+      services: [],
+      mergedQuestions: [], // 鍚堝苟鍚庣殑闂鏁版嵁
+      isSaving: false,
+    };
+  },
+  created() {
+    this.loadServicesData();
+  },
+  methods: {
+    getQuestionType(type) {
+      const types = { 1: "鍗曢��", 2: "澶氶��", 4: "闂瓟" };
+      return types[type] || "鏈煡";
+    },
+
+    async loadServicesData() {
+      this.services = this.selectedServices;
+
+      const loading = this.$loading({
+        lock: true,
+        text: "姝e湪鍔犺浇鏈畬鎴愰棶鍗锋暟鎹�...",
+        spinner: "el-icon-loading",
+        background: "rgba(0, 0, 0, 0.7)",
+      });
+
+      try {
+        // 鍙姞杞芥湭瀹屾垚鐨勬湇鍔¢棶鍗锋暟鎹�
+        const requests = this.services.map((service) =>
+          getsearchrResults({
+            taskid: service.taskid,
+            patid: this.patid,
+            subId: service.id,
+            isFinish: false, // 纭繚鍙幏鍙栨湭瀹屾垚鐨勯棶鍗�
+          })
+        );
+
+        const responses = await Promise.all(requests);
+
+        // 鍚堝苟鎵�鏈夐棶棰橈紝鍘婚噸
+        const allQuestions = [];
+        const questionMap = {};
+
+        responses.forEach((response, index) => {
+          if (response.code == 200 && response.data.scriptResult) {
+            response.data.scriptResult.forEach((q) => {
+              const key = `${q.scriptContent}_${q.scriptType}`;
+              if (!questionMap[key]) {
+                questionMap[key] = {
+                  ...q,
+                  uniqueKey: key,
+                  mergedResult: q.scriptType == 2 ? [] : null,
+                  originalServices: [], // 璁板綍鍘熷鏈嶅姟ID
+                };
+                allQuestions.push(questionMap[key]);
+              }
+              questionMap[key].originalServices.push(this.services[index].id);
+            });
+          }
+        });
+
+        // 鍒濆鍖栧悎骞剁粨鏋�
+        this.mergedQuestions = allQuestions.map((q) => ({
+          ...q,
+          mergedResult: q.scriptType == 2 ? [] : q.scriptResult || null,
+        }));
+        console.log(this.mergedQuestions);
+      } catch (error) {
+        this.$message.error("鍔犺浇闂嵎鏁版嵁澶辫触: " + error.message);
+      } finally {
+        loading.close();
+      }
+    },
+
+    // 澶勭悊閫夐」鍙樺寲 (涓庣埗缁勪欢淇濇寔涓�鑷�)
+    handleOptionChange(selectedOption, questionIndex, options, question) {
+      const selectedOptionObj = options.find(
+        (item) => item.optioncontent == selectedOption
+      );
+
+      // 璁剧疆寮傚父鐘舵��
+      question.isabnormal = !!selectedOptionObj?.isabnormal;
+
+      // 澶勭悊闄勫姞杈撳叆妗嗘樉绀�
+      question.showAppendInput = selectedOptionObj?.appendflag == 1;
+      if (!question.showAppendInput) {
+        question.answerps = "";
+      }
+
+      this.$forceUpdate();
+    },
+
+    // 鏇存柊澶氶�夊垎鏁� (涓庣埗缁勪欢淇濇寔涓�鑷�)
+    updateScore(selectedValues, questionIndex, options, question) {
+      const abnormalOptions = options.filter((opt) => opt.isabnormal);
+      question.isabnormal = abnormalOptions.some((opt) =>
+        selectedValues.includes(opt.optioncontent)
+      );
+      this.$forceUpdate();
+    },
+
+    handleCancel() {
+      this.$emit("cancel");
+    },
+
+    async handleSave() {
+      this.isSaving = true;
+
+      try {
+        const saveResults = [];
+        const updateServicePromises = [];
+
+        // 1. 淇濆瓨鎵�鏈夐棶鍗烽棶棰�
+        for (const service of this.services) {
+          const serviceId = service.id;
+          const questionsToSave = this.mergedQuestions
+            .filter((q) => q.originalServices.includes(serviceId))
+            .map((question) => ({
+              scriptid: question.id,
+              scriptResultId: question.scriptResultId,
+              scriptType: question.scriptType,
+              questiontext: question.scriptContent,
+              asrtext:
+                question.scriptType == 2
+                  ? question.mergedResult.join("&")
+                  : question.mergedResult,
+              answerps: question.answerps || null,
+              isabnormal: question.isabnormal || false,
+            }));
+
+          // 淇濆瓨闂鏁版嵁
+          for (const question of questionsToSave) {
+            const saveData = {
+              taskid: service.taskid,
+              patid: this.patid,
+              subId: serviceId,
+              ...question,
+            };
+
+            if (saveData.isabnormal) {
+              saveData.excep = 1;
+            }
+
+            try {
+              const response = question.scriptResultId
+                ? await serviceSubtaskDetailedit(saveData)
+                : await serviceSubtaskDetailadd(saveData);
+
+              saveResults.push({
+                serviceId,
+                success: response.code === 200,
+                message:
+                  response.message ||
+                  (response.code === 200 ? "淇濆瓨鎴愬姛" : "淇濆瓨澶辫触"),
+              });
+            } catch (error) {
+              saveResults.push({
+                serviceId,
+                success: false,
+                message: error.message || "淇濆瓨澶辫触",
+              });
+            }
+          }
+
+          // 2. 鏇存柊鏈嶅姟鐘舵�佷负宸插畬鎴� (sendstate = 6)
+          updateServicePromises.push(this.updateServiceStatus(serviceId));
+        }
+
+        // 绛夊緟鎵�鏈夋湇鍔$姸鎬佹洿鏂板畬鎴�
+        const updateResults = await Promise.all(updateServicePromises);
+        updateResults.forEach((result) => {
+          if (!result.success) {
+            saveResults.push({
+              serviceId: result.serviceId,
+              success: false,
+              message: result.message || "鏈嶅姟鐘舵�佹洿鏂板け璐�",
+            });
+          }
+        });
+
+        // 缁熻缁撴灉
+        const successCount = saveResults.filter((r) => r.success).length;
+        const totalCount = saveResults.length;
+
+        // 閫氱煡鐖剁粍浠�
+        this.$emit("save", {
+          successCount,
+          totalCount,
+          results: saveResults,
+        });
+
+        if (successCount === totalCount) {
+          this.$message.success("鎵�鏈夐棶鍗峰拰鏈嶅姟鐘舵�佹洿鏂版垚鍔�");
+        } else {
+          this.$message.warning(
+            `鎴愬姛淇濆瓨 ${successCount} 椤癸紝澶辫触 ${totalCount - successCount} 椤筦
+          );
+        }
+      } catch (error) {
+        this.$message.error("淇濆瓨杩囩▼涓彂鐢熼敊璇�: " + error.message);
+      } finally {
+        this.isSaving = false;
+      }
+    },
+    // 鏂板鏂规硶锛氭洿鏂版湇鍔$姸鎬�
+    async updateServiceStatus(serviceId) {
+      try {
+        // 鑾峰彇鏈嶅姟褰撳墠鏁版嵁
+        const res = await getTaskservelist({
+          patid: this.patid,
+          subId: serviceId,
+        });
+
+        if (res.code === 200) {
+          const serviceData = res.rows[0].serviceSubtaskList.find(
+            (item) => item.id === serviceId
+          );
+
+          if (serviceData) {
+            // 鏇存柊鏈嶅姟鐘舵�佷负宸插畬鎴� (sendstate = 6)
+            const updateRes = await Editsingletaskson({
+              ...serviceData,
+              sendstate: 6, // 璁剧疆涓哄凡瀹屾垚鐘舵��
+              remark: "閫氳繃鍚堝苟缂栬緫瀹屾垚", // 鍙�夛細娣诲姞澶囨敞
+            });
+
+            return {
+              serviceId,
+              success: updateRes.code === 200,
+              message: updateRes.message || "鏈嶅姟鐘舵�佹洿鏂版垚鍔�",
+            };
+          }
+        }
+        return {
+          serviceId,
+          success: false,
+          message: "鑾峰彇鏈嶅姟鏁版嵁澶辫触",
+        };
+      } catch (error) {
+        return {
+          serviceId,
+          success: false,
+          message: error.message || "鏇存柊鏈嶅姟鐘舵�佸け璐�",
+        };
+      }
+    },
+  },
+};
+</script>
+
+<style scoped>
+.merge-questionnaire-container {
+  display: flex;
+  flex-direction: column;
+  height: 100%;
+  padding: 20px;
+}
+
+.merge-header {
+  margin-bottom: 20px;
+}
+
+.merge-content {
+  flex: 1;
+  overflow-y: auto;
+}
+
+.question-list {
+  padding: 10px;
+}
+
+/* 涓庣埗缁勪欢涓�鑷寸殑棰樼洰鏍峰紡 */
+.scriptTopic-dev {
+  margin-bottom: 20px;
+  padding: 15px;
+  border: 1px solid #ebeef5;
+  border-radius: 4px;
+}
+
+.scriptTopic-isabnormal {
+  margin-bottom: 20px;
+  padding: 15px;
+  border: 1px solid #f56c6c;
+  border-radius: 4px;
+  background-color: #fff6f6;
+}
+
+.dev-text {
+  font-size: 16px;
+  margin-bottom: 15px;
+  color: #333;
+}
+
+.dev-xx {
+  margin-left: 20px;
+}
+
+.append-input-container {
+  margin-top: 15px;
+}
+
+.red-star {
+  color: #f56c6c;
+}
+
+.merge-footer {
+  margin-top: 20px;
+  text-align: right;
+  padding-top: 15px;
+  border-top: 1px solid #ebeef5;
+}
+</style>
diff --git a/src/views/followvisit/record/detailpage/index.vue b/src/views/followvisit/record/detailpage/index.vue
index e2ff50a..426e933 100644
--- a/src/views/followvisit/record/detailpage/index.vue
+++ b/src/views/followvisit/record/detailpage/index.vue
@@ -27,6 +27,23 @@
                 鍓嶅線CDSS鏌ヨ
               </el-link>
             </div>
+            <div class="merge-controls" v-if="Whetherall">
+              <el-button
+                type="primary"
+                @click="toggleMergeMode"
+                :disabled="selectedServices.length < 2"
+              >
+                {{ isMergeMode ? "鍙栨秷鍚堝苟" : "鍚堝苟缂栬緫闂嵎" }}
+              </el-button>
+              <el-button
+                v-if="isMergeMode"
+                type="success"
+                @click="openMergeDialog"
+                :disabled="selectedServices.length < 2"
+              >
+                寮�濮嬪悎骞� (宸查�� {{ selectedServices.length }} 涓湇鍔�)
+              </el-button>
+            </div>
           </div>
           <!-- <el-button type="success">闅忚鍚庣煭淇�</el-button> -->
         </div>
@@ -36,7 +53,14 @@
           :data="logsheetlist"
           :row-class-name="tableRowClassName"
           style="width: 100%"
+          @selection-change="handleSelectionChange"
         >
+          <el-table-column
+            type="selection"
+            width="55"
+            :selectable="checkSelectable"
+            v-if="Whetherall"
+          ></el-table-column>
           <el-table-column
             prop="sendname"
             align="center"
@@ -213,7 +237,22 @@
         </el-table>
       </div>
     </div>
-
+    <!-- 娣诲姞鍚堝苟缂栬緫瀵硅瘽妗� -->
+    <el-dialog
+      title="鍚堝苟缂栬緫闂嵎"
+      :visible.sync="mergeDialogVisible"
+      width="80%"
+      top="5vh"
+      v-dialogDrag
+    >
+      <MergeAndModify
+        v-if="mergeDialogVisible"
+        :selected-services="selectedServices"
+        :patid="patid"
+        @save="handleMergeSave"
+        @cancel="mergeDialogVisible = false"
+      />
+    </el-dialog>
     <div class="action-container">
       <div class="call-action">
         <div class="call-container">
@@ -278,7 +317,7 @@
                           </el-radio-group>
                         </div>
                         <div
-                          v-if="item.showAppendInput"
+                          v-if="item.showAppendInput||item.answerps"
                           class="append-input-container"
                         >
                           <el-input
@@ -843,9 +882,11 @@
   listcontactinformation,
 } from "@/api/patient/homepage";
 import CallButton from "@/components/CallButton";
+import MergeAndModify from "./MergeAndModify.vue";
 export default {
   components: {
     CallButton,
+    MergeAndModify,
   },
 
   dicts: ["sys_normal_disable", "sys_user_sex", "sys_yujing", "sys_suggest"],
@@ -882,6 +923,9 @@
       tableDatatop: [], //棰樼洰琛�
       voiceDatatop: [], //棰樼洰琛�
       dynamicTags: [],
+      isMergeMode: false,
+      mergeDialogVisible: false,
+      selectedServices: [], // 閫変腑鐨勬湇鍔″垪琛�
       zcrules: {
         resource: [
           { required: true, message: "璇烽�夋嫨闅忚鏂瑰紡", trigger: "change" },
@@ -1312,6 +1356,7 @@
           console.error("鍙戠敓閿欒锛�", error);
         });
     },
+    // 鐢佃瘽============================
     // 楠岃瘉鐢佃瘽鍙风爜鏍煎紡骞惰繑鍥為敊璇俊鎭�
     validatePhoneNumber(phone) {
       if (!phone) {
@@ -1343,7 +1388,6 @@
         };
       }
     },
-
     // 浣跨敤绀轰緥
     isValidPhone(phone) {
       return this.validatePhoneNumber(phone).isValid;
@@ -1367,7 +1411,6 @@
         });
       });
     },
-
     // 澶勭悊閫氳瘽鐘舵�佸彉鍖�
     handleCallStatusChange(status) {
       console.log(status, "status");
@@ -1389,7 +1432,6 @@
         this.$message.error(`鍛煎彨澶辫触: ${status.text}`);
       }
     },
-
     // 缁撴潫褰撳墠閫氳瘽
     endCurrentCall() {
       if (!this.currentCall) return;
@@ -1642,7 +1684,7 @@
 
       this.tableDatatop[questionIndex].showAppendInput =
         selectedOptionObj.appendflag == 1;
-        console.log(this.tableDatatop);
+      console.log(this.tableDatatop);
 
       // if (!this.tableDatatop[questionIndex].showAppendInput) {
       //   this.tableDatatop[questionIndex].answerps = ""; // 娓呴櫎闄勫姞淇℃伅
@@ -1793,6 +1835,60 @@
       return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
     },
     updateScore(a, b, c) {},
+    // 鍚堝苟淇敼鐩稿叧=============================
+    toggleMergeMode() {
+      this.isMergeMode = !this.isMergeMode;
+      if (!this.isMergeMode) {
+        this.selectedServices = [];
+      }
+    },
+
+    handleSelectionChange(selection) {
+      this.selectedServices = selection
+        .filter(
+          (item) => !item.preachformson || !item.preachformson.includes("3")
+        )
+        .map((item) => ({
+          id: item.id,
+          taskid: item.taskid,
+          taskName: item.taskName,
+          sendname: item.sendname,
+        }));
+    },
+    checkSelectable(row, index) {
+      // 褰� sendstate 涓� 6 鏃朵笉鍙��
+      return row.sendstate !== 6;
+    },
+    openMergeDialog() {
+      if (this.selectedServices.length < 2) {
+        this.$message.warning("璇疯嚦灏戦�夋嫨2涓棶鍗锋湇鍔¤繘琛屽悎骞�");
+        return;
+      }
+      this.mergeDialogVisible = true;
+    },
+
+    handleMergeSave(mergedData) {
+      // 澶勭悊鍚堝苟淇濆瓨閫昏緫
+      this.mergeDialogVisible = false;
+      this.isMergeMode = false;
+      this.selectedServices = [];
+
+      // 鏄剧ず淇濆瓨缁撴灉
+      if (mergedData.successCount == mergedData.totalCount) {
+        this.$message.success(`鎴愬姛淇濆瓨 ${mergedData.successCount} 涓棶鍗穈);
+      } else if (mergedData.successCount > 0) {
+        this.$message.warning(
+          `鎴愬姛淇濆瓨 ${mergedData.successCount} 涓棶鍗凤紝澶辫触 ${
+            mergedData.totalCount - mergedData.successCount
+          } 涓猔
+        );
+      } else {
+        this.$message.error("鎵�鏈夐棶鍗蜂繚瀛樺け璐�");
+      }
+
+      // 鍒锋柊鏁版嵁
+      this.getTaskservelist();
+    },
   },
 };
 </script>
@@ -1852,7 +1948,11 @@
     margin-top: 20px;
   }
 }
-
+.merge-controls {
+  background: #f5f7fa;
+  border-radius: 4px;
+  margin-left: 20px;
+}
 .Followuserinfo {
   margin: 10px 10px 0 10px;
   align-items: center;
diff --git a/src/views/patient/patient/outpatient.vue b/src/views/patient/patient/outpatient.vue
index a323439..7ee6864 100644
--- a/src/views/patient/patient/outpatient.vue
+++ b/src/views/patient/patient/outpatient.vue
@@ -440,6 +440,12 @@
                   <span>{{ formatTime(scope.row.createTime) }}</span>
                 </template>
               </el-table-column>
+              <template #empty>
+                <div class="empty-message">
+                  <i class="el-icon-warning"></i>
+                  <span>鎮h�呯瀹ゆ棤鍖归厤鏈嶅姟</span>
+                </div>
+              </template>
             </el-table>
           </div>
         </el-col>
diff --git a/vue.config.js b/vue.config.js
index 382765f..447ffb1 100644
--- a/vue.config.js
+++ b/vue.config.js
@@ -37,7 +37,7 @@
       [process.env.VUE_APP_BASE_API]: {
         // target: `https://www.health-y.cn/lssf`,
         // target: `http://10.202.20.185:8095`,
-        // target: `http://9.208.2.190:8095`,
+        // target: `http://192.168.100.195:8095`,
         target:`http://localhost:8095`,
         // target: `http://192.168.100.193:8095`,
         // target: `http://192.168.101.166:8093`,

--
Gitblit v1.9.3