Преглед изворни кода

销售端优化信息采集表的排版提示

cgp пре 3 недеља
родитељ
комит
960183b895

+ 117 - 6
src/views/qw/collectionUnBind/addCollectionDialog.vue

@@ -24,10 +24,24 @@
               v-model="answer.value"
               size="mini"
               :disabled="!canEditAnswers"
-              @change="onAnswerChange">
-              <el-checkbox v-for="option in answer.options" :key="option.value" :label="option.value">
-                {{ option.name }}
-              </el-checkbox>
+              @change="onCheckboxGroupChange(answer)">
+              <div v-for="(option, optionIndex) in answer.options" :key="`${index}-${optionIndex}`" style="display: flex; align-items: center; margin-bottom: 10px;">
+                <el-checkbox :label="option.value" style="margin-right: 10px; flex-shrink: 0;">
+                  {{ option.name }}
+                </el-checkbox>
+
+                <!-- 如果选项的open为true且选项被选中,显示备注输入框 -->
+                <el-input
+                  v-if="option.open && isOptionSelected(answer, option)"
+                  v-model="option.remarkText"
+                  placeholder="请输入备注信息"
+                  size="mini"
+                  maxlength="20"
+                  show-word-limit
+                  style="width: 200px; margin-left: 5px;"
+                  :disabled="!canEditAnswers"
+                  @blur="onRemarkBlur(option)"/>
+              </div>
             </el-checkbox-group>
           </div>
         </div>
@@ -135,6 +149,7 @@ export default {
       }
       callback();
     };
+
     return {
       // ========== 答案修改标识相关字段 ==========
       originalAnswers: null,
@@ -263,6 +278,30 @@ export default {
       }
     },
 
+    // 监听复选框组的变化
+    onCheckboxGroupChange(answer) {
+      // 遍历所有选项,如果选项未被选中,则清除其备注文本
+      answer.options.forEach(option => {
+        if (!answer.value.includes(option.value)) {
+          option.remarkText = '';
+        }
+      });
+      this.onAnswerChange();
+    },
+
+    // 检查选项是否被选中
+    isOptionSelected(answer, option) {
+      return answer.value && answer.value.includes(option.value);
+    },
+
+    // 备注输入框失去焦点时的处理
+    onRemarkBlur(option) {
+      // 如果备注文本为空,则清空
+      if (!option.remarkText?.trim()) {
+        option.remarkText = '';
+      }
+    },
+
     isAnswersEqual(original, current) {
       if (!original || !current) return original === current;
       if (original.length !== current.length) return false;
@@ -271,6 +310,14 @@ export default {
         const origAnswer = original[i];
         const currAnswer = current[i];
 
+        // 比较基本属性
+        if (origAnswer.title !== currAnswer.title ||
+          origAnswer.sort !== currAnswer.sort ||
+          origAnswer.flag !== currAnswer.flag) {
+          return false;
+        }
+
+        // 比较选择的值
         if (!origAnswer.value || !currAnswer.value) {
           if (origAnswer.value !== currAnswer.value) return false;
         } else {
@@ -281,6 +328,24 @@ export default {
             if (sortedOrig[j] !== sortedCurr[j]) return false;
           }
         }
+
+        // 比较选项
+        if (origAnswer.options && currAnswer.options) {
+          if (origAnswer.options.length !== currAnswer.options.length) return false;
+
+          for (let k = 0; k < origAnswer.options.length; k++) {
+            const origOption = origAnswer.options[k];
+            const currOption = currAnswer.options[k];
+
+            // 比较基本选项属性
+            if (origOption.name !== currOption.name ||
+              origOption.value !== currOption.value ||
+              origOption.open !== currOption.open ||
+              origOption.remarkText !== currOption.remarkText) {
+              return false;
+            }
+          }
+        }
       }
       return true;
     },
@@ -372,8 +437,8 @@ export default {
 
         const answers = questions.map(item => ({
           title: item.title,
-          options: item.options || [],
-          value: item.value || [],
+          options: this.processOptions(item.options || []),
+          value: item.value ? [...item.value] : [],
           sort: item.sort,
           flag: item.flag || false
         }));
@@ -409,6 +474,20 @@ export default {
         this.$message.error('获取问题模板失败,请稍后重试');
       });
     },
+
+    // 处理选项数据,添加备注相关的默认值
+    processOptions(options) {
+      return options.map(option => {
+        return {
+          name: option.name || '',
+          value: option.value,
+          open: option.open || false,
+          // 添加备注相关的字段
+          remarkText: ''
+        };
+      });
+    },
+
     onAnswerChange() {
       console.log('答案已修改,修改标识:', this.isAnswersModified);
     },
@@ -436,14 +515,41 @@ export default {
     submitForm() {
       this.$refs["form"].validate(valid => {
         if (valid) {
+          // 1. 构建提交用的 answers 副本,组装 remarksList 并清理临时字段
+          const answersForSubmit = this.form.answers.map(answer => {
+            // 1. 构建 remarksList
+            const remarks = [];
+            answer.options.forEach(option => {
+              if (option.remarkText && option.remarkText.trim()) {
+                remarks.push({
+                  value: option.value,
+                  text: option.remarkText.trim()
+                });
+              }
+            });
+
+            // 2. 清理 options,移除临时字段 remarkText
+            const cleanOptions = answer.options.map(({ remarkText, ...opt }) => opt);
+
+            // 3. 返回符合后端 AnswerVO 结构的对象
+            return {
+              ...answer,
+              remarksList: remarks,   // 标准备注字段
+              options: cleanOptions       // 纯净的选项列表
+            };
+          });
+
+          // 2. 构建提交数据,使用处理后的 answers
           const submitData = {
             ...this.form,
+            answers: answersForSubmit,
             companyId: this.extraParams.companyId,
             companyUserId: this.extraParams.companyUserId,
             source: 'pc',
             fillFlag: this.isAnswersModified
           };
 
+          // 3. 根据是否关联套餐包清理无关字段
           if (submitData.isPackage !== 1) {
             delete submitData.packageId;
             delete submitData.payType;
@@ -456,6 +562,7 @@ export default {
 
           const appId = this.form.appId;
 
+          // 4. 提交请求
           createSimpleUserInfo(submitData).then(res => {
             this.$message.success("新增成功");
             this.dialogVisible = false;
@@ -478,3 +585,7 @@ export default {
   }
 };
 </script>
+
+<style scoped>
+/* 移除了原有的 remark-toggle 样式,因为我们不再使用 */
+</style>

+ 221 - 69
src/views/qw/externalContact/collection.vue

@@ -3,19 +3,18 @@
     <el-form validate-on-rule-change :rules="rules" ref="form" :model="form" label-width="140px">
       <el-form-item label="小程序" prop="appId">
         <el-select v-model="form.appId" placeholder="小程序" clearable>
-          <el-option v-for="dict in sourceList" :key="dict.dictValue1" :label="dict.dictLabel"
-            :value="dict.dictValue1" />
+          <el-option v-for="dict in sourceList" :key="dict.dictValue1" :label="dict.dictLabel" :value="dict.dictValue1" />
         </el-select>
       </el-form-item>
       <el-form-item label="信息模板" prop="questionId">
         <el-select @change="selectQuestion" v-model="form.questionId" placeholder="请选择问答">
           <el-option v-for="dict in questionOptions" :key="dict.dictValue" :label="dict.dictLabel"
-            :value="parseInt(dict.dictValue)" />
+                     :value="parseInt(dict.dictValue)" />
         </el-select>
       </el-form-item>
 
       <!-- 动态渲染问题区域 -->
-      <!-- <div v-if="form.answers && form.answers.length > 0">
+      <div v-if="form.answers && form.answers.length > 0">
         <div style="margin-bottom: 20px;margin-top: 20px;" v-for="(answer, index) in form.answers" :key="index">
           <div style="margin-bottom: 20px;margin-top: 20px;">
             <span style="font-size: 15px;font-weight: bold; margin-left: 31px">{{ answer.title }}</span>
@@ -23,38 +22,31 @@
           <div style="margin-left: 31px;">
             <el-checkbox-group
               v-model="answer.value"
+              @change="onCheckboxGroupChange(answer)"
               size="mini"
               :disabled="!canEditAnswers">
-              <el-checkbox v-for="option in answer.options" :key="option.value" :label="option.value">
-                {{ option.name }}
-              </el-checkbox>
-            </el-checkbox-group>
-          </div>
-        </div>
-      </div> -->
-
-      <!-- 动态渲染问题区域 -->
-      <div v-if="form.answers && form.answers.length > 0">
-        <div style="margin-bottom: 20px;margin-top: 20px;" v-for="(answer, index) in form.answers" :key="index">
-          <div style="margin-bottom: 20px;margin-top: 20px;">
-            <span style="font-size: 15px;font-weight: bold; margin-left: 31px">{{ answer.title }}</span>
-          </div>
-          <div style="margin-left: 31px;">
-            <el-checkbox-group v-model="answer.value" size="mini" :disabled="!canEditAnswers">
-              <div v-for="option in answer.options" :key="option.value" style="margin-bottom: 10px;">
-                <el-checkbox :label="option.value">
+              <div v-for="(option, optionIndex) in answer.options" :key="`${index}-${optionIndex}`" style="display: flex; align-items: center; margin-bottom: 10px;">
+                <el-checkbox :label="option.value" style="margin-right: 10px; flex-shrink: 0;">
                   {{ option.name }}
                 </el-checkbox>
-                <el-input v-if="option.open === true" v-model="option.inputValue" size="mini"
-                  :placeholder="option.placeholder || '请输入'" style="width: 200px; margin-left: 10px;"
-                  :disabled="!canEditAnswers" @click.stop />
+
+                <!-- 如果选项的open为true且选项被选中,显示备注输入框 -->
+                <el-input
+                  v-if="option.open && isOptionSelected(answer, option)"
+                  v-model="option.remarkText"
+                  placeholder="请输入备注信息"
+                  size="mini"
+                  maxlength="20"
+                  show-word-limit
+                  style="width: 200px; margin-left: 5px;"
+                  :disabled="!canEditAnswers"
+                  @blur="onRemarkBlur(option)"/>
               </div>
             </el-checkbox-group>
           </div>
         </div>
       </div>
 
-
       <el-form-item label="用户姓名" prop="userName">
         <el-input v-model="form.userName" placeholder="请输入用户姓名"></el-input>
       </el-form-item>
@@ -68,7 +60,7 @@
         </el-select>
       </el-form-item>
       <el-form-item label="年龄" prop="age">
-        <el-input-number v-model="form.age" placeholder="请输入年龄" style="width: 20%" />
+        <el-input-number v-model="form.age" placeholder="请输入年龄"  style="width: 20%"/>
       </el-form-item>
 
       <el-form-item label="过敏情况" prop="allergy">
@@ -88,7 +80,7 @@
       <el-form-item v-if="form.isPackage == 1" label="产品疗法" prop="packageId">
         <el-select filterable v-model="form.packageId" placeholder="请选择产品疗法">
           <el-option v-for="dict in privatePackageOptions" :key="dict.dictValue" :label="dict.dictLabel"
-            :value="parseInt(dict.dictValue)" />
+                     :value="parseInt(dict.dictValue)" />
         </el-select>
       </el-form-item>
       <el-form-item v-if="form.packageId && form.isPackage && form.isPackage == 1" label="支付类型" prop="payType">
@@ -97,8 +89,8 @@
           <el-radio :label="2">物流代收</el-radio>
         </el-radio-group>
       </el-form-item>
-      <el-form-item v-if="form.packageId && form.payType == 2 && form.isPackage && form.isPackage == 1" label="预付金额"
-        prop="amount">
+      <el-form-item v-if="form.packageId && form.payType == 2 && form.isPackage && form.isPackage == 1"
+                    label="预付金额" prop="amount">
         <el-input v-model="form.amount" placeholder="请输入物流代收金额" type="number" />
       </el-form-item>
     </el-form>
@@ -107,7 +99,7 @@
     </div>
 
     <el-dialog :title="collectionForm.title" v-if="collectionForm.open" :visible.sync="collectionForm.open"
-      width="450px" append-to-body>
+               width="450px" append-to-body>
       <div style="padding-bottom:15px;">
         <img :src="codeImage" width="400px">
       </div>
@@ -152,7 +144,7 @@ export default {
       originalAnswers: null, // 保存原始 answers 数据
       isAnswersModified: 0, // 0-未修改, 1-已修改
       isSalesProxyFill: true, // 控制问题是否可编辑
-      sourceList: [],
+      sourceList:[],
       extraParams: {
         companyId: null,
         companyUserId: null
@@ -243,7 +235,7 @@ export default {
       return this.isSalesProxyFill === true;
     }
   },
-  // 监听 answers 的变化
+// 监听 answers 的变化
   watch: {
     'form.answers': {
       handler(newVal) {
@@ -270,6 +262,30 @@ export default {
       console.log('【collection】接收到 extraParams:', params);
       this.extraParams = { ...params };
     },
+
+    // 监听复选框组的变化
+    onCheckboxGroupChange(answer) {
+      // 遍历所有选项,如果选项未被选中,则清除其备注文本
+      answer.options.forEach(option => {
+        if (!answer.value.includes(option.value)) {
+          option.remarkText = '';
+        }
+      });
+    },
+
+    // 检查选项是否被选中
+    isOptionSelected(answer, option) {
+      return answer.value && answer.value.includes(option.value);
+    },
+
+    // 备注输入框失去焦点时的处理
+    onRemarkBlur(option) {
+      // 如果备注文本为空,则清空
+      if (!option.remarkText?.trim()) {
+        option.remarkText = '';
+      }
+    },
+
     handleIsPackageChange(value) {
       if (value === 0) {
         this.form.packageId = null;
@@ -288,7 +304,7 @@ export default {
       link.click();
       document.body.removeChild(link);
     },
-    handleShare(id, appId) {
+    handleShare(id,appId) {
       let loadingRock = this.$loading({
         lock: true,
         text: '生成二维码中~~请不要刷新页面!!',
@@ -296,7 +312,7 @@ export default {
         background: 'rgba(0, 0, 0, 0.7)'
       });
 
-      getWxaCodeCollectionUnLimit(id, appId).then(response => {
+      getWxaCodeCollectionUnLimit(id,appId).then(response => {
         this.codeImage = response.url
         this.collectionForm.open = true;
         this.collectionForm.name = id;
@@ -333,10 +349,31 @@ export default {
     processFormData(data) {
       let processedAnswers = [];
       if (data.answers && Array.isArray(data.answers)) {
-        processedAnswers = data.answers.map(answer => ({
-          ...answer,
-          value: Array.isArray(answer.value) ? [...answer.value] : [] // 深拷贝
-        }));
+        processedAnswers = data.answers.map(answer => {
+          // 首先处理选项数据,添加备注相关的默认值
+          const processedOptions = this.processOptions(answer.options || []);
+
+          // 根据 remarksList 设置选项的备注状态
+          const remarksMap = {};
+          if (Array.isArray(answer.remarksList)) {
+            answer.remarksList.forEach(remark => {
+              remarksMap[remark.value] = remark.text;
+            });
+          }
+
+          // 更新选项的备注状态 - 如果该选项被选中且有备注信息,则设置备注文本
+          processedOptions.forEach(option => {
+            if (this.isOptionSelected(answer, option) && remarksMap.hasOwnProperty(option.value)) {
+              option.remarkText = remarksMap[option.value];
+            }
+          });
+
+          return {
+            ...answer,
+            options: processedOptions,
+            value: Array.isArray(answer.value) ? [...answer.value] : [] // 深拷贝
+          };
+        });
       }
 
       // 保存原始数据的深拷贝
@@ -361,6 +398,19 @@ export default {
       };
     },
 
+    // 处理选项数据,添加备注相关的默认值
+    processOptions(options) {
+      return options.map(option => {
+        return {
+          name: option.name || '',
+          value: option.value,
+          open: option.open || false,
+          // 添加备注相关的字段
+          remarkText: ''
+        };
+      });
+    },
+
     resetFormData() {
       this.form = {
         ...this.form,
@@ -391,6 +441,13 @@ export default {
         const origAnswer = original[i];
         const currAnswer = current[i];
 
+        // 比较基本属性
+        if (origAnswer.title !== currAnswer.title ||
+          origAnswer.sort !== currAnswer.sort ||
+          origAnswer.flag !== currAnswer.flag) {
+          return false;
+        }
+
         // 比较 value 数组
         if (!origAnswer.value || !currAnswer.value) {
           if (origAnswer.value !== currAnswer.value) return false;
@@ -398,13 +455,31 @@ export default {
           if (origAnswer.value.length !== currAnswer.value.length) return false;
 
           // 排序后比较(因为顺序可能不影响业务逻辑)
-          const sortedOrig = [...origAnswer.value].sort((a, b) => a - b);
-          const sortedCurr = [...currAnswer.value].sort((a, b) => a - b);
+          const sortedOrig = [...origAnswer.value].sort((a,b) => a-b);
+          const sortedCurr = [...currAnswer.value].sort((a,b) => a-b);
 
           for (let j = 0; j < sortedOrig.length; j++) {
             if (sortedOrig[j] !== sortedCurr[j]) return false;
           }
         }
+
+        // 比较选项
+        if (origAnswer.options && currAnswer.options) {
+          if (origAnswer.options.length !== currAnswer.options.length) return false;
+
+          for (let k = 0; k < origAnswer.options.length; k++) {
+            const origOption = origAnswer.options[k];
+            const currOption = currAnswer.options[k];
+
+            // 比较基本选项属性
+            if (origOption.name !== currOption.name ||
+              origOption.value !== currOption.value ||
+              origOption.open !== currOption.open ||
+              origOption.remarkText !== currOption.remarkText) {
+              return false;
+            }
+          }
+        }
       }
       return true;
     },
@@ -420,57 +495,130 @@ export default {
         remark: this.form.remark,
       };
 
-      // 先重置表单
-      this.form = {
-        ...preservedFields,
-        questionId: val,
-        answers: [],
-        isPackage: null,
-        packageId: null,
-        payType: null,
-        amount: null,
-        id: null
-      };
-      // 查询该用户+该模板下是否有历史采集记录
-      if (this.userId && val) {
-        getInfo({ userId: this.userId, questionId: val }).then(res => {
-          console.log('查询历史记录:', res.data); // 调试日志
-          if (res.data) {
-            this.processFormData(res.data);
-          }
-        }).catch(error => {
-          console.error('查询历史记录失败:', error);
-        });
-      }
+      if (!val) return;
+
+      const loading = this.$loading({
+        lock: true,
+        text: '加载问题模板中...',
+        spinner: 'el-icon-loading',
+        background: 'rgba(0, 0, 0, 0.7)'
+      });
+
+      getAnswer(val).then(response => {
+        loading.close();
+
+        let questions = [];
+        if (response.data && response.data.answers) {
+          questions = response.data.answers;
+        } else if (response.rows) {
+          questions = response.rows;
+        } else if (response.data && Array.isArray(response.data)) {
+          questions = response.data;
+        }
+
+        if (!questions || questions.length === 0) {
+          this.$message.warning('该模板没有问题数据');
+          return;
+        }
+
+        const answers = questions.map(item => ({
+          title: item.title,
+          options: this.processOptions(item.options || []),
+          value: item.value ? [...item.value] : [],
+          sort: item.sort,
+          flag: item.flag || false
+        }));
+
+        // 保存原始 answers
+        this.originalAnswers = JSON.parse(JSON.stringify(answers));
+        this.isAnswersModified = 0;
+
+        // 先重置表单
+        this.form = {
+          ...preservedFields,
+          questionId: val,
+          answers: answers,
+          isPackage: null,
+          packageId: null,
+          payType: null,
+          amount: null,
+          id: null
+        };
+
+        // 查询该用户+该模板下是否有历史采集记录
+        if (this.userId && val) {
+          getInfo({ userId: this.userId, questionId: val }).then(res => {
+            console.log('查询历史记录:', res.data); // 调试日志
+            if (res.data) {
+              this.processFormData(res.data);
+            }
+          }).catch(error => {
+            console.error('查询历史记录失败:', error);
+          });
+        }
+      }).catch(error => {
+        loading.close();
+        console.error('获取问题详情失败:', error);
+        this.$message.error('获取问题模板失败,请稍后重试');
+      });
     },
 
     submitForm() {
       this.$refs["form"].validate(valid => {
         if (valid) {
-          // 深拷贝表单数据,避免直接修改原始 form
+          // 构建基础提交数据
           const submitData = {
             ...this.form,
             userId: this.userId,
             companyId: this.extraParams.companyId,
             companyUserId: this.extraParams.companyUserId,
             source: 'pc',
-            // 添加修改标识
-            fillFlag: this.isAnswersModified// 添加修改标识:0-未修改,1-已修改
+            fillFlag: this.isAnswersModified
           };
-          submitData.userId = this.userId;
 
-          // 如果未关联产品疗法,清除相关字段(避免传 null/0 等无效值)
+          // 处理答案:将 option.remarkText 转换为 remarksList 格式
+          const processedAnswers = this.form.answers.map(answer => {
+            // 1. 构建 remarksList
+            const remarksList = [];
+            answer.options.forEach(option => {
+              if (option.remarkText && option.remarkText.trim()) {
+                remarksList.push({
+                  value: option.value,
+                  text: option.remarkText.trim()
+                });
+              }
+            });
+
+            // 2. 清理 options,移除临时字段 remarkText
+            const cleanOptions = answer.options.map(({ remarkText, ...opt }) => opt);
+
+            // 3. 返回符合后端 AnswerVO 结构的对象
+            return {
+              title: answer.title,
+              value: [...answer.value],
+              sort: answer.sort,
+              flag: answer.flag,
+              remarksList: remarksList,   // 标准备注字段
+              options: cleanOptions       // 纯净的选项列表
+            };
+          });
+
+          submitData.answers = processedAnswers;
+
+          // 处理套餐关联逻辑(原逻辑不变)
           if (submitData.isPackage !== 1) {
             delete submitData.packageId;
             delete submitData.payType;
             delete submitData.amount;
           } else {
-            // 如果关联了疗法,但支付类型不是物流代收,则清除 amount
             if (submitData.payType !== 2) {
               delete submitData.amount;
             }
           }
+
           const appId = this.form.appId;
+
+          // 根据 id 判断新增或修改(原逻辑不变)
           if (submitData.id != null) {
             updateCollection(submitData).then(res => {
               this.msgSuccess("修改成功");
@@ -497,3 +645,7 @@ export default {
   },
 };
 </script>
+
+<style scoped>
+/* 移除了原有的 remark-toggle 样式,因为我们不再使用 */
+</style>