Просмотр исходного кода

Merge branch 'master' of http://1.14.104.71:10880/root/ylrz_his_scrm_adminUI

lmx 2 недель назад
Родитель
Сommit
8c9f17d8af

BIN
src/assets/logo/bjzmlxsh.png


+ 46 - 9
src/views/course/courseQuestionBank/index.vue

@@ -148,7 +148,7 @@
         </template>
       </el-table-column>
       <el-table-column label="排序" align="center" prop="sort" />
-      <el-table-column label="答案" align="center" prop="answer" />
+      <el-table-column v-if="!hideAnswerFields" label="答案" align="center" prop="answer" />
       <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
         <template slot-scope="scope">
           <el-button
@@ -179,7 +179,7 @@
 
     <!-- 添加或修改题库对话框 -->
     <el-dialog :title="title" :visible.sync="open" width="1000px" append-to-body>
-      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+      <el-form ref="form" :model="form" :rules="dynamicRules" label-width="80px">
         <el-form-item label="标题" prop="title">
           <el-input v-model="form.title" placeholder="请输入问题" />
         </el-form-item>
@@ -239,7 +239,7 @@
                 <el-input v-model="scope.row.name" :placeholder="getOptionLabel(scope.$index) + ':' + '请输入标题'" ></el-input>
               </template>
             </el-table-column>
-            <el-table-column label="是否为答案" prop="isWrite" >
+            <el-table-column v-if="!hideAnswerFields" label="是否为答案" prop="isWrite" >
               <template slot-scope="scope">
                 <el-tooltip
                   v-if="!scope.row.name"
@@ -272,12 +272,10 @@
             </el-table-column>
           </el-table>
         </el-form-item>
-        <el-form-item label="答案:" prop="answer">
-          <template slot-scope="scope">
-            <span style="background-color: #faedc9; font-size: 20px;">
-              {{ form.answer }}
-            </span>
-          </template>
+        <el-form-item v-if="!hideAnswerFields" label="答案:" prop="answer">
+          <span style="background-color: #faedc9; font-size: 20px;">
+            {{ form.answer }}
+          </span>
         </el-form-item>
       </el-form>
       <div slot="footer" class="dialog-footer">
@@ -338,6 +336,7 @@ import {
   getCatePidList,
   getCateListByPid
 } from '@/api/course/userCourseCategory'
+import { getConfigByKey } from '@/api/system/config'
 
 export default {
   name: "CourseQuestionBank",
@@ -345,6 +344,22 @@ export default {
     alphabet() {
       return 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
     },
+    /** 点播配置:不校验答案时隐藏列表/表单中的答案相关项(与 validateAnswerWhenWatch 为 false / "0" 一致) */
+    hideAnswerFields() {
+      const cfg = this.courseConfig;
+      if (!cfg || !Object.prototype.hasOwnProperty.call(cfg, 'validateAnswerWhenWatch')) {
+        return false;
+      }
+      const v = cfg.validateAnswerWhenWatch;
+      return v === false || v === '0' || v === 0 || v === 'false';
+    },
+    dynamicRules() {
+      const r = { ...this.rules };
+      if (this.hideAnswerFields) {
+        delete r.answer;
+      }
+      return r;
+    },
   },
   watch: {
   },
@@ -352,6 +367,8 @@ export default {
   },
   data() {
     return {
+      /** course.config 解析后的对象 */
+      courseConfig: {},
       exportFailLoading: false,
       //单选
       selectedAnswer:null,
@@ -433,6 +450,15 @@ export default {
   },
   created() {
     this.getList();
+    getConfigByKey('course.config').then(response => {
+      if (response.data && response.data.configValue) {
+        try {
+          this.courseConfig = JSON.parse(response.data.configValue) || {};
+        } catch (e) {
+          this.courseConfig = {};
+        }
+      }
+    }).catch(() => { this.courseConfig = {}; });
     this.getDicts("sys_course_temp_type").then(response => {
       this.typeOptions = response.data;
     });
@@ -631,6 +657,17 @@ export default {
             return
           }
 
+          if (this.hideAnswerFields) {
+            this.question.forEach(q => { q.isAnswer = 0 });
+            this.selectedAnswer = null;
+            this.selectedAnswers = [];
+            if (this.form.type === 2) {
+              this.form.answer = [];
+            } else {
+              this.form.answer = '';
+            }
+          }
+
           this.form.question=JSON.stringify(this.question)
 
           if (this.form.type===2){

+ 51 - 3
src/views/course/userCoursePeriod/courseStatistics.vue

@@ -303,7 +303,18 @@
             </template>
           </el-table-column>
           <el-table-column label="分公司名称" align="center" prop="companyName" width="150" />
-          <el-table-column label="销售名称" align="center" prop="salesName" />
+          <el-table-column label="销售名称" align="center" prop="salesName" width="120" />
+          <el-table-column
+            label="课程评分"
+            align="center"
+            prop="courseRating"
+            min-width="260"
+            show-overflow-tooltip
+          >
+            <template slot-scope="scope">
+              <span class="course-rating-cell">{{ formatCourseRating(scope.row.courseRating) }}</span>
+            </template>
+          </el-table-column>
         </el-table>
 
         <!-- 分页 -->
@@ -532,9 +543,11 @@ export default {
       this.userDetailDialog.loading = true;
       getCourseStatisticsUserDetailList(this.userDetailDialog.queryParams).then(response => {
         if (response.code === 200 && response.data) {
-          const d = response.data;
+          const raw = response.data;
+          // 兼容 PageInfo 直接放在 data,或再包一层 data
+          const d = raw.data != null && raw.list == null && raw.rows == null ? raw.data : raw;
           this.userDetailDialog.list = d.list || d.rows || [];
-          this.userDetailDialog.total = d.total ?? 0;
+          this.userDetailDialog.total = d.total != null ? d.total : 0;
         } else {
           this.userDetailDialog.list = [];
           this.userDetailDialog.total = 0;
@@ -571,6 +584,29 @@ export default {
         });
       }).catch(() => {});
     },
+    /**
+     * 课程评分:后端在关闭「看课校验答案」时返回答题 JSON(courseRating);否则为空
+     */
+    formatCourseRating(val) {
+      if (val == null || val === '') {
+        return '—';
+      }
+      if (typeof val === 'string') {
+        const s = val.trim();
+        if (!s) return '—';
+        try {
+          const parsed = JSON.parse(s);
+          return typeof parsed === 'object' ? JSON.stringify(parsed) : String(val);
+        } catch (e) {
+          return val;
+        }
+      }
+      try {
+        return typeof val === 'object' ? JSON.stringify(val) : String(val);
+      } catch (e) {
+        return String(val);
+      }
+    },
     /** 格式化时长 */
     formatDuration(seconds) {
       if (seconds == null || isNaN(seconds)) return '0秒';
@@ -635,4 +671,16 @@ export default {
     overflow-y: auto;
   }
 }
+
+.course-rating-cell {
+  display: inline-block;
+  max-width: 100%;
+  text-align: left;
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  font-size: 12px;
+  line-height: 1.4;
+  vertical-align: middle;
+}
 </style>

+ 2 - 2
src/views/hisStore/store/recommend.vue

@@ -148,7 +148,7 @@
     <!-- 添加或修改推荐店铺对话框 -->
     <el-dialog :title="title" :visible.sync="open" width="600px" append-to-body>
       <el-form ref="form" :model="form" :rules="rules" label-width="120px">
-        <el-form-item label="推荐店铺Id" prop="storeName">
+        <el-form-item label="推荐店铺Id" prop="storeId">
           <el-select
             v-model="form.storeId"
             filterable
@@ -289,7 +289,7 @@ export default {
         this.storeLoading = true;
         // 这里应该调用实际的API来搜索店铺
         // 示例代码,需要根据实际API调整
-        listStore({ storeName: query }).then(response => {
+        listStore({ storeId: query }).then(response => {
           this.storeOptions = response.rows;
           this.storeLoading = false;
         }).catch(() => {

+ 12 - 2
src/views/hisStore/storeProduct/index.vue

@@ -1269,6 +1269,9 @@ export default {
       if (row.isAudit == 0) {
         return '待审核';
       }
+      if (row.isAudit == 2) {
+        return '审核退回';
+      }
       const option = this.isShowOptions.find(item => item.dictValue == row.isShow);
       return option ? option.dictLabel : '未知状态';
     },
@@ -1277,8 +1280,15 @@ export default {
       if (row.isAudit == 0) {
         return 'warning';
       }
-      // 根据你的业务逻辑返回不同的类型,如:success, danger, info等
-      return row.isShow == 1 ? 'success' : 'info';
+      if (row.isAudit == 2) {
+        return 'danger';
+      }
+      const statusMap = {
+        0: 'warning',
+        1: 'success',
+        2: 'danger'
+      };
+      return statusMap[row.isShow] || 'info';
     },
     cancel1(){
       this.open1 = false;

+ 25 - 0
src/views/hisStore/storeProduct/indexZm.vue

@@ -879,6 +879,19 @@
           </el-col>
 
         </el-row>
+        <el-row>
+          <el-col :span="8">
+            <el-form-item label="单次购买数量" prop="singlePurchaseLimit">
+              <el-input-number
+                :min="0"
+                v-model="form.singlePurchaseLimit"
+                placeholder="单次下单最多件数,0不限"
+                :controls="true"
+                @input="handleSinglePurchaseLimitInput"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
         <el-form-item label="推广分类" prop="tuiCateId">
           <el-select style="width: 240px" v-model="form.tuiCateId" placeholder="请选择推广分类" clearable size="small" >
             <el-option
@@ -1514,6 +1527,17 @@ export default {
         }
       }
     },
+    handleSinglePurchaseLimitInput(value) {
+      if (value !== null && value !== undefined && value !== '') {
+        if (isNaN(value) || value < 0) {
+          this.$nextTick(() => {
+            this.form.singlePurchaseLimit = null;
+          });
+        } else {
+          this.form.singlePurchaseLimit = Math.floor(Number(value));
+        }
+      }
+    },
     // 删除规格
     handleRemoveRole (index) {
       this.attrs.splice(index, 1);
@@ -1779,6 +1803,7 @@ export default {
         contraindications: null, // 禁忌
         precautions: null ,// 注意事项
         purchaseLimit: null, // 限购数量
+        singlePurchaseLimit: null, // 单次购买数量上限
         userEndCategoryIds: [],
         tagIds: []
       };

+ 15 - 1
src/views/system/config/config.vue

@@ -1319,6 +1319,14 @@
               <el-input-number v-model="form18.answerErrorCount" :min="1"></el-input-number>
             </el-tooltip>
           </el-form-item>
+          <el-form-item label="看课是否校验答案">
+            <el-tooltip class="item" effect="dark" content="默认为「是」:需校验答题正确性;选「否」则不做答案校验" placement="top-end">
+              <el-radio-group v-model="form18.validateAnswerWhenWatch">
+                <el-radio label="1">是</el-radio>
+                <el-radio label="0">否</el-radio>
+              </el-radio-group>
+            </el-tooltip>
+          </el-form-item>
           <el-form-item label="每十分钟获取积分">
             <el-tooltip class="item" effect="dark" content="每十分钟获取多少积分" placement="top-end">
               <el-input-number v-model="form18.videoIntegral" :min="1"></el-input-number>
@@ -2903,6 +2911,8 @@ export default {
         smsDomainName: '', // 初始化为空字符串或其他默认值
         completionCountdown: false,//是否开启点播完课倒计时
         camelCase:'',
+        /** 看课是否校验答案:1-是(默认) 0-否,随 course.config JSON 保存 */
+        validateAnswerWhenWatch: '1',
       },
       form19: {},
       form20: {
@@ -3504,7 +3514,11 @@ export default {
           console.log(this.form16)
         }
         if (key == 'course.config') {
-          this.form18 = JSON.parse(response.data.configValue)
+          const parsed = JSON.parse(response.data.configValue)
+          if (parsed.validateAnswerWhenWatch == null || parsed.validateAnswerWhenWatch === '') {
+            parsed.validateAnswerWhenWatch = '1'
+          }
+          this.form18 = parsed
         }
         if (key == 'redPacket.config') {
           this.form19 = JSON.parse(response.data.configValue)