吴树波 1 день назад
Родитель
Сommit
16a382bd06

+ 111 - 17
src/views/course/courseFinishTemp/index.vue

@@ -232,9 +232,15 @@
             />
           </el-select>
         </el-form-item>
-        <el-form-item label="规则" prop="setting">
+        <el-form-item prop="setting">
+          <span slot="label" class="finish-rule-label finish-rule-label--watch">
+            <el-tag type="primary" size="mini" effect="dark">私聊</el-tag>
+            <span>看课规则</span>
+          </span>
+          <div class="finish-rule-panel finish-rule-panel--watch">
+            <div class="finish-rule-panel__tip">发给客户本人(私聊),与下方「群聊恭喜」完全独立,请勿混用</div>
           <div v-for="(item, index) in setting" :key="index"
-               style="background-color: #fdfdfd; border: 1px solid #e6e6e6; margin-bottom: 20px;">
+               class="finish-rule-item finish-rule-item--watch">
             <el-row>
               <el-col :span="22">
                 <el-form :model="item" label-width="70px">
@@ -329,12 +335,19 @@
             </el-row>
           </div>
           <el-link type="primary" class="el-icon-plus" :underline="false" @click='addSetList(0)' v-if="formType==1">
-            添加内容
+            添加私聊内容
           </el-link>
+          </div>
         </el-form-item>
-        <el-form-item label="群聊恭喜规则" prop="setting">
+        <el-form-item prop="chatSetting">
+          <span slot="label" class="finish-rule-label finish-rule-label--chat">
+            <el-tag type="warning" size="mini" effect="dark">群聊</el-tag>
+            <span>群聊恭喜规则</span>
+          </span>
+          <div class="finish-rule-panel finish-rule-panel--chat">
+            <div class="finish-rule-panel__tip">发到客户群(群聊恭喜),与上方「看课私聊」完全独立,请勿混用</div>
           <div v-for="(item, index) in chatSetting" :key="index"
-               style="background-color: #fdfdfd; border: 1px solid #e6e6e6; margin-bottom: 20px;">
+               class="finish-rule-item finish-rule-item--chat">
             <el-row>
               <el-col :span="22">
                 <el-form :model="item" label-width="70px">
@@ -428,9 +441,10 @@
               </el-col>
             </el-row>
           </div>
-          <el-link type="primary" class="el-icon-plus" :underline="false" @click='addSetList(1)' v-if="formType==1">
-            添加内容
+          <el-link type="warning" class="el-icon-plus" :underline="false" @click='addSetList(1)' v-if="formType==1">
+            添加群聊内容
           </el-link>
+          </div>
         </el-form-item>
         <el-form-item label="全选销售" prop="isAllCompanyUser">
           <el-switch
@@ -852,35 +866,64 @@ export default {
           this.form.chatSetting = JSON.stringify(this.chatSetting)
 
           if (this.setting.length <= 0) {
-            return this.$message("请添加规则")
+            return this.$message("请添加看课规则")
           }
           for (let i = 0; i < this.setting.length; i++) {
             if (this.setting[i].contentType == 1 && (this.setting[i].value == null || this.setting[i].value == "")) {
-              return this.$message.error("内容不能为空")
+              return this.$message.error("看课规则:内容不能为空")
             }
             if (this.setting[i].contentType == 2 && (this.setting[i].imgUrl == null || this.setting[i].imgUrl == "")) {
-              return this.$message.error("图片不能为空")
+              return this.$message.error("看课规则:图片不能为空")
             }
             if (this.setting[i].contentType == 3 && (this.setting[i].linkTitle == null || this.setting[i].linkTitle == "")) {
-              return this.$message.error("链接标题不能为空")
+              return this.$message.error("看课规则:链接标题不能为空")
             }
             if (this.setting[i].contentType == 3 && (this.setting[i].linkDescribe == null || this.setting[i].linkDescribe == "")) {
-              return this.$message.error("链接描述不能为空")
+              return this.$message.error("看课规则:链接描述不能为空")
             }
             if (this.setting[i].contentType == 3 && (this.setting[i].linkImageUrl == null || this.setting[i].linkImageUrl == "")) {
-              return this.$message.error("链接图片不能为空")
+              return this.$message.error("看课规则:链接图片不能为空")
             }
             if (this.setting[i].contentType == 3 && this.setting[i].type == 1 && (this.setting[i].linkUrl == null || this.setting[i].linkUrl == "")) {
-              return this.$message.error("链接地址不能为空")
+              return this.$message.error("看课规则:链接地址不能为空")
             }
             if (this.setting[i].contentType == 5 && (this.setting[i].fileUrl == null || this.setting[i].fileUrl == "")) {
-              return this.$message.error("文件不能为空")
+              return this.$message.error("看课规则:文件不能为空")
             }
             if (this.setting[i].contentType == 6 && (this.setting[i].videoUrl == null || this.setting[i].videoUrl == "")) {
-              return this.$message.error("视频不能为空")
+              return this.$message.error("看课规则:视频不能为空")
             }
             if (this.setting[i].contentType == 7 && (this.setting[i].value == null || this.setting[i].value == "")) {
-              return this.$message.error("语音不能为空")
+              return this.$message.error("看课规则:语音不能为空")
+            }
+          }
+          for (let i = 0; i < this.chatSetting.length; i++) {
+            if (this.chatSetting[i].contentType == 1 && (this.chatSetting[i].value == null || this.chatSetting[i].value == "")) {
+              return this.$message.error("群聊恭喜规则:内容不能为空")
+            }
+            if (this.chatSetting[i].contentType == 2 && (this.chatSetting[i].imgUrl == null || this.chatSetting[i].imgUrl == "")) {
+              return this.$message.error("群聊恭喜规则:图片不能为空")
+            }
+            if (this.chatSetting[i].contentType == 3 && (this.chatSetting[i].linkTitle == null || this.chatSetting[i].linkTitle == "")) {
+              return this.$message.error("群聊恭喜规则:链接标题不能为空")
+            }
+            if (this.chatSetting[i].contentType == 3 && (this.chatSetting[i].linkDescribe == null || this.chatSetting[i].linkDescribe == "")) {
+              return this.$message.error("群聊恭喜规则:链接描述不能为空")
+            }
+            if (this.chatSetting[i].contentType == 3 && (this.chatSetting[i].linkImageUrl == null || this.chatSetting[i].linkImageUrl == "")) {
+              return this.$message.error("群聊恭喜规则:链接图片不能为空")
+            }
+            if (this.chatSetting[i].contentType == 3 && this.chatSetting[i].type == 1 && (this.chatSetting[i].linkUrl == null || this.chatSetting[i].linkUrl == "")) {
+              return this.$message.error("群聊恭喜规则:链接地址不能为空")
+            }
+            if (this.chatSetting[i].contentType == 5 && (this.chatSetting[i].fileUrl == null || this.chatSetting[i].fileUrl == "")) {
+              return this.$message.error("群聊恭喜规则:文件不能为空")
+            }
+            if (this.chatSetting[i].contentType == 6 && (this.chatSetting[i].videoUrl == null || this.chatSetting[i].videoUrl == "")) {
+              return this.$message.error("群聊恭喜规则:视频不能为空")
+            }
+            if (this.chatSetting[i].contentType == 7 && (this.chatSetting[i].value == null || this.chatSetting[i].value == "")) {
+              return this.$message.error("群聊恭喜规则:语音不能为空")
             }
           }
 
@@ -946,3 +989,54 @@ export default {
   }
 };
 </script>
+
+<style scoped>
+.finish-rule-label {
+  display: inline-flex;
+  flex-direction: column;
+  align-items: flex-start;
+  line-height: 1.4;
+  gap: 4px;
+}
+.finish-rule-label span:last-child {
+  font-weight: 600;
+}
+.finish-rule-panel {
+  width: 100%;
+  box-sizing: border-box;
+  border-radius: 4px;
+  padding: 12px;
+}
+.finish-rule-panel--watch {
+  background: #ecf5ff;
+  border: 1px solid #b3d8ff;
+  border-left: 4px solid #409eff;
+}
+.finish-rule-panel--chat {
+  background: #fdf6ec;
+  border: 1px solid #f5dab1;
+  border-left: 4px solid #e6a23c;
+}
+.finish-rule-panel__tip {
+  font-size: 12px;
+  margin-bottom: 10px;
+  line-height: 1.5;
+}
+.finish-rule-panel--watch .finish-rule-panel__tip {
+  color: #337ecc;
+}
+.finish-rule-panel--chat .finish-rule-panel__tip {
+  color: #b88230;
+}
+.finish-rule-item {
+  margin-bottom: 16px;
+  border-radius: 4px;
+  background: #fff;
+}
+.finish-rule-item--watch {
+  border: 1px solid #b3d8ff;
+}
+.finish-rule-item--chat {
+  border: 1px solid #f5dab1;
+}
+</style>

+ 172 - 48
src/views/course/courseFinishTempParent/index.vue

@@ -160,9 +160,15 @@
             />
           </el-select>
         </el-form-item>
-        <el-form-item label="规则" prop="setting" v-if="!form.id">
+        <el-form-item prop="setting">
+          <span slot="label" class="finish-rule-label finish-rule-label--watch">
+            <el-tag type="primary" size="mini" effect="dark">私聊</el-tag>
+            <span>看课规则</span>
+          </span>
+          <div class="finish-rule-panel finish-rule-panel--watch">
+            <div class="finish-rule-panel__tip">发给客户本人(私聊),与下方「群聊恭喜」完全独立,请勿混用</div>
           <div v-for="(item, index) in setting" :key="index"
-               style="background-color: #fdfdfd; border: 1px solid #e6e6e6; margin-bottom: 20px;">
+               class="finish-rule-item finish-rule-item--watch">
             <el-row>
               <el-col :span="22">
                 <el-form :model="item" label-width="70px">
@@ -257,12 +263,19 @@
             </el-row>
           </div>
           <el-link type="primary" class="el-icon-plus" :underline="false" @click='addSetList(0)'>
-            添加内容
+            添加私聊内容
           </el-link>
+          </div>
         </el-form-item>
-        <el-form-item label="群聊恭喜规则" prop="setting" v-if="!form.id">
+        <el-form-item prop="chatSetting">
+          <span slot="label" class="finish-rule-label finish-rule-label--chat">
+            <el-tag type="warning" size="mini" effect="dark">群聊</el-tag>
+            <span>群聊恭喜规则</span>
+          </span>
+          <div class="finish-rule-panel finish-rule-panel--chat">
+            <div class="finish-rule-panel__tip">发到客户群(群聊恭喜),与上方「看课私聊」完全独立,请勿混用</div>
           <div v-for="(item, index) in chatSetting" :key="index"
-               style="background-color: #fdfdfd; border: 1px solid #e6e6e6; margin-bottom: 20px;">
+               class="finish-rule-item finish-rule-item--chat">
             <el-row>
               <el-col :span="22">
                 <el-form :model="item" label-width="70px">
@@ -356,9 +369,10 @@
               </el-col>
             </el-row>
           </div>
-          <el-link type="primary" class="el-icon-plus" :underline="false" @click='addSetList(1)'>
-            添加内容
+          <el-link type="warning" class="el-icon-plus" :underline="false" @click='addSetList(1)'>
+            添加群聊内容
           </el-link>
+          </div>
         </el-form-item>
         <el-form-item label="全选销售" prop="isAllCompanyUser" v-if="!form.id">
           <el-switch
@@ -393,7 +407,7 @@
 <script>
 import {getCompanyList} from "@/api/company/company";
 import { listCourseFinishTempParent, getCourseFinishTempParent, delCourseFinishTempParent, addCourseFinishTempParent, updateCourseFinishTempParent, exportCourseFinishTempParent } from "@/api/course/courseFinishTempParent";
-import {courseList} from '@/api/qw/sop'
+import {courseList, videoList} from '@/api/qw/sop'
 import ImageUpload from '@/views/qw/sop/ImageUpload.vue'
 import { getUserList } from '@/api/company/companyUser'
 
@@ -438,6 +452,8 @@ export default {
       setting: [],
       companyList: [],
       chatSetting: [],
+      videoOptions: [],
+      videoOptionsLoading: false,
       // 查询参数
       queryParams: {
         pageNum: 1,
@@ -548,6 +564,31 @@ export default {
       const id = row.id || this.ids
       getCourseFinishTempParent(id).then(response => {
         this.form = response.data;
+        try {
+          this.setting = response.data.setting ? JSON.parse(response.data.setting) : [];
+        } catch (e) {
+          this.setting = [];
+        }
+        try {
+          this.chatSetting = response.data.chatSetting ? JSON.parse(response.data.chatSetting) : [];
+        } catch (e) {
+          this.chatSetting = [];
+        }
+        if (response.data.companyUserIds != null && response.data.companyUserIds !== '') {
+          this.companyUserIds = String(this.form.companyUserIds).split(",");
+        } else {
+          this.companyUserIds = [];
+        }
+        const allRuleItems = [].concat(this.setting || [], this.chatSetting || []);
+        allRuleItems.forEach(item => {
+          if (item && (item.contentType == 4 || item.contentType == '4') && item.courseId) {
+            this.videoOptions = [];
+            this.videoOptionsLoading = false;
+            videoList(item.courseId).then((videoResponse) => {
+              this.videoOptions = videoResponse.list;
+            });
+          }
+        });
         this.open = true;
         this.title = "修改完课模板";
       });
@@ -556,6 +597,78 @@ export default {
     submitForm() {
       this.$refs["form"].validate(valid => {
         if (valid) {
+          if (this.form.isAllCompanyUser == null) {
+            this.form.isAllCompanyUser = 2;
+          }
+          if (this.companyUserIds != null) {
+            this.form.companyUserIds = this.companyUserIds.toString();
+          }
+
+          this.form.setting = JSON.stringify(this.setting)
+          this.form.chatSetting = JSON.stringify(this.chatSetting)
+
+          if (this.setting.length <= 0) {
+            return this.$message("请添加看课规则")
+          }
+          for (let i = 0; i < this.setting.length; i++) {
+            if (this.setting[i].contentType == 1 && (this.setting[i].value == null || this.setting[i].value == "")) {
+              return this.$message.error("看课规则:内容不能为空")
+            }
+            if (this.setting[i].contentType == 2 && (this.setting[i].imgUrl == null || this.setting[i].imgUrl == "")) {
+              return this.$message.error("看课规则:图片不能为空")
+            }
+            if (this.setting[i].contentType == 3 && (this.setting[i].linkTitle == null || this.setting[i].linkTitle == "")) {
+              return this.$message.error("看课规则:链接标题不能为空")
+            }
+            if (this.setting[i].contentType == 3 && (this.setting[i].linkDescribe == null || this.setting[i].linkDescribe == "")) {
+              return this.$message.error("看课规则:链接描述不能为空")
+            }
+            if (this.setting[i].contentType == 3 && (this.setting[i].linkImageUrl == null || this.setting[i].linkImageUrl == "")) {
+              return this.$message.error("看课规则:链接图片不能为空")
+            }
+            if (this.setting[i].contentType == 3 && this.setting[i].type == 1 && (this.setting[i].linkUrl == null || this.setting[i].linkUrl == "")) {
+              return this.$message.error("看课规则:链接地址不能为空")
+            }
+            if (this.setting[i].contentType == 5 && (this.setting[i].fileUrl == null || this.setting[i].fileUrl == "")) {
+              return this.$message.error("看课规则:文件不能为空")
+            }
+            if (this.setting[i].contentType == 6 && (this.setting[i].videoUrl == null || this.setting[i].videoUrl == "")) {
+              return this.$message.error("看课规则:视频不能为空")
+            }
+            if (this.setting[i].contentType == 7 && (this.setting[i].value == null || this.setting[i].value == "")) {
+              return this.$message.error("看课规则:语音不能为空")
+            }
+          }
+          for (let i = 0; i < this.chatSetting.length; i++) {
+            if (this.chatSetting[i].contentType == 1 && (this.chatSetting[i].value == null || this.chatSetting[i].value == "")) {
+              return this.$message.error("群聊恭喜规则:内容不能为空")
+            }
+            if (this.chatSetting[i].contentType == 2 && (this.chatSetting[i].imgUrl == null || this.chatSetting[i].imgUrl == "")) {
+              return this.$message.error("群聊恭喜规则:图片不能为空")
+            }
+            if (this.chatSetting[i].contentType == 3 && (this.chatSetting[i].linkTitle == null || this.chatSetting[i].linkTitle == "")) {
+              return this.$message.error("群聊恭喜规则:链接标题不能为空")
+            }
+            if (this.chatSetting[i].contentType == 3 && (this.chatSetting[i].linkDescribe == null || this.chatSetting[i].linkDescribe == "")) {
+              return this.$message.error("群聊恭喜规则:链接描述不能为空")
+            }
+            if (this.chatSetting[i].contentType == 3 && (this.chatSetting[i].linkImageUrl == null || this.chatSetting[i].linkImageUrl == "")) {
+              return this.$message.error("群聊恭喜规则:链接图片不能为空")
+            }
+            if (this.chatSetting[i].contentType == 3 && this.chatSetting[i].type == 1 && (this.chatSetting[i].linkUrl == null || this.chatSetting[i].linkUrl == "")) {
+              return this.$message.error("群聊恭喜规则:链接地址不能为空")
+            }
+            if (this.chatSetting[i].contentType == 5 && (this.chatSetting[i].fileUrl == null || this.chatSetting[i].fileUrl == "")) {
+              return this.$message.error("群聊恭喜规则:文件不能为空")
+            }
+            if (this.chatSetting[i].contentType == 6 && (this.chatSetting[i].videoUrl == null || this.chatSetting[i].videoUrl == "")) {
+              return this.$message.error("群聊恭喜规则:视频不能为空")
+            }
+            if (this.chatSetting[i].contentType == 7 && (this.chatSetting[i].value == null || this.chatSetting[i].value == "")) {
+              return this.$message.error("群聊恭喜规则:语音不能为空")
+            }
+          }
+
           if (this.form.id != null) {
             updateCourseFinishTempParent(this.form).then(response => {
               this.msgSuccess("修改成功");
@@ -563,46 +676,6 @@ export default {
               this.getList();
             });
           } else {
-            if (this.form.isAllCompanyUser == null) {
-              this.form.isAllCompanyUser = 2;
-            }
-            this.form.companyUserIds = this.companyUserIds.toString()
-
-            this.form.setting = JSON.stringify(this.setting)
-            this.form.chatSetting = JSON.stringify(this.chatSetting)
-
-            if (this.setting.length <= 0) {
-              return this.$message("请添加规则")
-            }
-            for (let i = 0; i < this.setting.length; i++) {
-              if (this.setting[i].contentType == 1 && (this.setting[i].value == null || this.setting[i].value == "")) {
-                return this.$message.error("内容不能为空")
-              }
-              if (this.setting[i].contentType == 2 && (this.setting[i].imgUrl == null || this.setting[i].imgUrl == "")) {
-                return this.$message.error("图片不能为空")
-              }
-              if (this.setting[i].contentType == 3 && (this.setting[i].linkTitle == null || this.setting[i].linkTitle == "")) {
-                return this.$message.error("链接标题不能为空")
-              }
-              if (this.setting[i].contentType == 3 && (this.setting[i].linkDescribe == null || this.setting[i].linkDescribe == "")) {
-                return this.$message.error("链接描述不能为空")
-              }
-              if (this.setting[i].contentType == 3 && (this.setting[i].linkImageUrl == null || this.setting[i].linkImageUrl == "")) {
-                return this.$message.error("链接图片不能为空")
-              }
-              if (this.setting[i].contentType == 3 && this.setting[i].type == 1 && (this.setting[i].linkUrl == null || this.setting[i].linkUrl == "")) {
-                return this.$message.error("链接地址不能为空")
-              }
-              if (this.setting[i].contentType == 5 && (this.setting[i].fileUrl == null || this.setting[i].fileUrl == "")) {
-                return this.$message.error("文件不能为空")
-              }
-              if (this.setting[i].contentType == 6 && (this.setting[i].videoUrl == null || this.setting[i].videoUrl == "")) {
-                return this.$message.error("视频不能为空")
-              }
-              if (this.setting[i].contentType == 7 && (this.setting[i].value == null || this.setting[i].value == "")) {
-                return this.$message.error("语音不能为空")
-              }
-            }
             addCourseFinishTempParent(this.form).then(response => {
               this.msgSuccess("新增成功");
               this.open = false;
@@ -725,3 +798,54 @@ export default {
   },
 };
 </script>
+
+<style scoped>
+.finish-rule-label {
+  display: inline-flex;
+  flex-direction: column;
+  align-items: flex-start;
+  line-height: 1.4;
+  gap: 4px;
+}
+.finish-rule-label span:last-child {
+  font-weight: 600;
+}
+.finish-rule-panel {
+  width: 100%;
+  box-sizing: border-box;
+  border-radius: 4px;
+  padding: 12px;
+}
+.finish-rule-panel--watch {
+  background: #ecf5ff;
+  border: 1px solid #b3d8ff;
+  border-left: 4px solid #409eff;
+}
+.finish-rule-panel--chat {
+  background: #fdf6ec;
+  border: 1px solid #f5dab1;
+  border-left: 4px solid #e6a23c;
+}
+.finish-rule-panel__tip {
+  font-size: 12px;
+  margin-bottom: 10px;
+  line-height: 1.5;
+}
+.finish-rule-panel--watch .finish-rule-panel__tip {
+  color: #337ecc;
+}
+.finish-rule-panel--chat .finish-rule-panel__tip {
+  color: #b88230;
+}
+.finish-rule-item {
+  margin-bottom: 16px;
+  border-radius: 4px;
+  background: #fff;
+}
+.finish-rule-item--watch {
+  border: 1px solid #b3d8ff;
+}
+.finish-rule-item--chat {
+  border: 1px solid #f5dab1;
+}
+</style>

+ 42 - 1
src/views/course/sop/userIdList.vue

@@ -141,12 +141,14 @@
       </el-form-item>
     </el-form>
 
-    <!-- 表格数据 -->
+    <!-- 表格数据:合计行为当前筛选条件下全部公司汇总,非当前页 -->
     <el-table
       border
       v-loading="loading"
       :data="appRegisterList"
       style="width: 100%; margin-top: 20px;"
+      show-summary
+      :summary-method="getSummaries"
     >
       <el-table-column label="序号" type="index" align="center" width="60" />
       <el-table-column label="公司名称" align="center" prop="companyName" />
@@ -180,6 +182,13 @@ export default {
       exportLoading: false,
       total: 0,
       appRegisterList: [],
+      // 服务端全量合计(不分页)
+      summaryRow: {
+        typeOneAll: 0,
+        typeTwoAll: 0,
+        typeAll: 0,
+        allUserId: 0
+      },
       appMallOptions:[],
       projectOptions: [],
       courseOptions: [],
@@ -375,6 +384,31 @@ export default {
       return params;
     },
 
+    /** 合计行:使用接口返回的全量汇总,不对当前页 rows 求和 */
+    getSummaries(param) {
+      const { columns } = param;
+      const sums = [];
+      const summary = this.summaryRow || {};
+      columns.forEach((column, index) => {
+        if (index === 0) {
+          sums[index] = '合计';
+          return;
+        }
+        const prop = column.property;
+        if (prop === 'companyName') {
+          sums[index] = '';
+          return;
+        }
+        if (prop === 'typeOneAll' || prop === 'typeTwoAll' || prop === 'typeAll' || prop === 'allUserId') {
+          const val = summary[prop];
+          sums[index] = val == null || val === '' ? 0 : val;
+          return;
+        }
+        sums[index] = '';
+      });
+      return sums;
+    },
+
     getList() {
       if (!this.queryParams.createTime) {
         this.$message.warning('请选择创建时间')
@@ -388,6 +422,13 @@ export default {
       getUserIdList(this.buildQueryParams()).then(response => {
         this.appRegisterList = response.rows || [];
         this.total = response.total || 0;
+        const summary = (response.ext && response.ext.summary) ? response.ext.summary : null;
+        this.summaryRow = {
+          typeOneAll: summary && summary.typeOneAll != null ? summary.typeOneAll : 0,
+          typeTwoAll: summary && summary.typeTwoAll != null ? summary.typeTwoAll : 0,
+          typeAll: summary && summary.typeAll != null ? summary.typeAll : 0,
+          allUserId: summary && summary.allUserId != null ? summary.allUserId : 0
+        };
         this.loading = false;
       }).catch(() => {
         this.loading = false;

+ 4 - 2
src/views/qw/friendWelcome/index.vue

@@ -177,7 +177,8 @@
                     <div style="flex: 1;">
                       <span v-if="item.msgtype === 'image'">【图片】: {{ item.image.pic_url }}</span>
                       <span v-if="item.msgtype === 'video'">【视频】: {{ item.video.url }}</span>
-                      <span v-if="item.msgtype === 'link'">【链接】: {{ item.link.title }}-{{item.link.desc}}</span>
+                      <span v-if="item.msgtype === 'link' && item.link.linkType === 'feishu_auth'">【飞书(授权)】: {{ item.link.title }}-{{item.link.desc}}</span>
+                      <span v-if="item.msgtype === 'link' && item.link.linkType !== 'feishu_auth'">【链接】: {{ item.link.title }}-{{item.link.desc}}</span>
                       <span v-if="item.msgtype === 'miniprogram'">【小程序】: {{ item.miniprogram.title }}</span>
                     </div>
                   </div>
@@ -265,7 +266,8 @@
                                 <div style="flex: 1;">
                                   <span v-if="attachment.msgtype === 'image'">【图片】: {{ attachment.image.pic_url }}</span>
                                   <span v-if="attachment.msgtype === 'video'">【视频】: {{ attachment.video.url }}</span>
-                                  <span v-if="attachment.msgtype === 'link'">【链接】: {{ attachment.link.title }}-{{attachment.link.desc}}</span>
+                                  <span v-if="attachment.msgtype === 'link' && attachment.link.linkType === 'feishu_auth'">【飞书(授权)】: {{ attachment.link.title }}-{{attachment.link.desc}}</span>
+                                  <span v-if="attachment.msgtype === 'link' && attachment.link.linkType !== 'feishu_auth'">【链接】: {{ attachment.link.title }}-{{attachment.link.desc}}</span>
                                   <span v-if="attachment.msgtype === 'miniprogram'">【小程序】: {{ attachment.miniprogram.title }}</span>
                                 </div>
                               </div>

+ 43 - 19
src/views/qw/friendWelcome/indexNew.vue

@@ -217,7 +217,8 @@
                     <div style="flex: 1;">
                     <span v-if="item.msgtype === 'image'">【图片】: {{ item.image.pic_url }}</span>
                     <span v-if="item.msgtype === 'video'">【视频】: {{ item.video.url }}</span>
-                    <span v-if="item.msgtype === 'link'">【链接】: {{ item.link.title }}-{{item.link.desc}}</span>
+                    <span v-if="item.msgtype === 'link' && item.link.linkType === 'feishu_auth'">【飞书(授权)】: {{ item.link.title }}-{{item.link.desc}}</span>
+                    <span v-if="item.msgtype === 'link' && item.link.linkType !== 'feishu_auth'">【链接】: {{ item.link.title }}-{{item.link.desc}}</span>
                     <span v-if="item.msgtype === 'miniprogram'">【小程序】: {{ item.miniprogram.title }}</span>
                     </div>
                     <div style="  display: flex;gap: 10px;">
@@ -242,7 +243,7 @@
             </el-row>
 
             <el-dropdown @command="(command) => handleCommand(command, -1)" trigger="click" placement="top-start">
-              <el-dropdown-menu slot="dropdown" style="width: 120px;">
+              <el-dropdown-menu slot="dropdown" style="width: 160px;">
                 <el-dropdown-item command="image">
                   <i class="el-icon-picture" style="margin-right: 10px;"></i>图片
                 </el-dropdown-item>
@@ -252,6 +253,9 @@
                 <el-dropdown-item command="link">
                   <i class="el-icon-link" style="margin-right: 10px;"></i>链接
                 </el-dropdown-item>
+                <el-dropdown-item command="feishu_auth">
+                  <i class="el-icon-link" style="margin-right: 10px;"></i>飞书(授权)
+                </el-dropdown-item>
                 <el-dropdown-item command="miniprogram">
                   <i class="el-icon-link" style="margin-right: 10px;"></i>小程序
                 </el-dropdown-item>
@@ -345,7 +349,8 @@
                                   <div style="flex: 1;">
                                     <span v-if="attachment.msgtype === 'image'">【图片】: {{ attachment.image.pic_url }}</span>
                                     <span v-if="attachment.msgtype === 'video'">【视频】: {{ attachment.video.url }}</span>
-                                    <span v-if="attachment.msgtype === 'link'">【链接】: {{ attachment.link.title }}-{{attachment.link.desc}}</span>
+                                    <span v-if="attachment.msgtype === 'link' && attachment.link.linkType === 'feishu_auth'">【飞书(授权)】: {{ attachment.link.title }}-{{attachment.link.desc}}</span>
+                                    <span v-if="attachment.msgtype === 'link' && attachment.link.linkType !== 'feishu_auth'">【链接】: {{ attachment.link.title }}-{{attachment.link.desc}}</span>
                                     <span v-if="attachment.msgtype === 'miniprogram'">【小程序】: {{ attachment.miniprogram.title }}</span>
                                   </div>
                                   <div style="  display: flex;gap: 10px;">
@@ -370,7 +375,7 @@
                           </el-row>
 
                           <el-dropdown @command="(command) => handleCommand(command, index)" trigger="click" placement="top-start">
-                            <el-dropdown-menu slot="dropdown" style="width: 120px;">
+                            <el-dropdown-menu slot="dropdown" style="width: 160px;">
                               <el-dropdown-item command="image">
                                 <i class="el-icon-picture" style="margin-right: 10px;"></i>图片
                               </el-dropdown-item>
@@ -380,6 +385,9 @@
                               <el-dropdown-item command="link">
                                 <i class="el-icon-link" style="margin-right: 10px;"></i>链接
                               </el-dropdown-item>
+                              <el-dropdown-item command="feishu_auth">
+                                <i class="el-icon-link" style="margin-right: 10px;"></i>飞书(授权)
+                              </el-dropdown-item>
                               <el-dropdown-item command="miniprogram">
                                 <i class="el-icon-link" style="margin-right: 10px;"></i>小程序
                               </el-dropdown-item>
@@ -445,9 +453,9 @@
             </video>
           </el-form-item>
         </div>
-        <div v-if="welcomeItem.type==='link'">
+        <div v-if="welcomeItem.type==='link' || welcomeItem.type==='feishu_auth'">
 
-          <el-form-item label="选择课程">
+          <el-form-item label="选择课程" :prop="welcomeItem.type==='feishu_auth' ? 'miniprogramCourseId' : undefined">
             <el-select  v-model="fileFrom.courseId" placeholder="请选择课程" style=" margin-right: 10px;" size="mini" filterable  @change="courseChange(fileFrom,welcomeItem.index,welcomeItem.itemIndex)">
               <el-option
                 v-for="dict in courseList"
@@ -475,17 +483,17 @@
           <el-form-item label="图文的描述:" prop="linkDesc">
             <el-input v-model="fileFrom.linkDesc" :rows="4" maxlength="170" show-word-limit type="textarea" placeholder="请输入内容,,最长为170字" />
           </el-form-item>
-          <div v-if="fileFrom.videoId==null" style="margin-top: 1%">
+          <div v-if="welcomeItem.type!=='feishu_auth' && fileFrom.videoId==null" style="margin-top: 1%">
             <el-form-item label="图文链接:"  label-width="100px" >
               <el-input v-model="fileFrom.linkUrl" placeholder="请输入链接地址" style="width: 90%;"/>
             </el-form-item>
           </div>
-          <div v-if="fileFrom.videoId!=null">
+          <div v-if="welcomeItem.type==='feishu_auth' || fileFrom.videoId!=null">
             <el-form-item label="图文链接:"  label-width="100px" >
-              <el-tag type="warning" v-model="fileFrom.linkUrl='待生成'">选择的课程小节 即为卡片链接地址</el-tag>
+              <el-tag type="warning" v-model="fileFrom.linkUrl='待生成'">{{ welcomeItem.type==='feishu_auth' ? '飞书(授权)链接将在发送时自动生成' : '选择的课程小节 即为卡片链接地址' }}</el-tag>
             </el-form-item>
           </div>
-          <div v-if="fileFrom.videoId!=null">
+          <div v-if="welcomeItem.type==='feishu_auth' || fileFrom.videoId!=null">
             <el-form-item label="课节过期时间" style="margin-top: 1%" required label-width="110px">
               <el-row>
                 <el-input-number  v-model="fileFrom.expiresDays"  :min="1" :max="9999" ></el-input-number>
@@ -886,8 +894,12 @@ export default {
           return '添加图片';
         case 'link':
           return '添加链接';
+        case 'feishu_auth':
+          return '添加飞书(授权)';
         case 'miniprogram':
           return '添加小程序';
+        case 'video':
+          return '添加视频';
       }
     },
 
@@ -943,7 +955,7 @@ export default {
       if (fileFrom.videoId != null) {
         // 根据 videoId 获取相关信息(假设有相关的 API 调用)
         let  selectedVideo = this.videoList.find(course => parseInt(course.dictValue) === fileFrom.videoId);
-        if (selectedVideo && type==='link') {
+        if (selectedVideo && (type==='link' || type==='feishu_auth')) {
           this.$set(fileFrom, 'linkDesc', selectedVideo.dictLabel);
           this.$set(fileFrom, 'expiresDays', 30);
         }
@@ -978,8 +990,8 @@ export default {
 
       this.welcomeItem = {
         open: true,
-        title: this.getEditTitleByMsgType(item.msgtype),
-        type: item.msgtype,
+        title: this.getEditTitleByMsgType(item.msgtype, item),
+        type: item.msgtype === 'link' && item.link && item.link.linkType === 'feishu_auth' ? 'feishu_auth' : item.msgtype,
         index,
         itemIndex
       };
@@ -996,9 +1008,11 @@ export default {
         this.fileFrom.courseId = item.link.courseId;
         this.fileFrom.expiresDays = item.link.expiresDays;
 
-        videoList(item.link.courseId).then(response => {
-          this.videoList = response.list;
-        });
+        if (item.link.courseId) {
+          videoList(item.link.courseId).then(response => {
+            this.videoList = response.list;
+          });
+        }
 
 
       }else if (item.msgtype === 'miniprogram') {
@@ -1021,7 +1035,10 @@ export default {
 
 
 
-    getEditTitleByMsgType(msgType) {
+    getEditTitleByMsgType(msgType, item) {
+      if (msgType === 'link' && item && item.link && item.link.linkType === 'feishu_auth') {
+        return '编辑飞书(授权)';
+      }
       switch (msgType) {
         case 'image':
           return '编辑图片';
@@ -1029,6 +1046,8 @@ export default {
           return '编辑链接';
         case 'miniprogram':
           return '编辑小程序';
+        case 'video':
+          return '编辑视频';
       }
     },
 
@@ -1073,17 +1092,22 @@ export default {
                   url:this.fileFrom.videoUrl,
                 }
               };
-            } else if (type === 'link') {
+            } else if (type === 'link' || type === 'feishu_auth') {
+              if (type === 'feishu_auth' && (!this.fileFrom.courseId || !this.fileFrom.videoId)) {
+                this.$message.error('飞书(授权)必须选择课程和小节');
+                return false;
+              }
               attachment = {
                 msgtype: 'link',
                 link: {
                   title: this.fileFrom.linkTitle,
                   picurl: this.fileFrom.linkPicUrl,
                   desc: this.fileFrom.linkDesc,
-                  url: this.fileFrom.linkUrl,
+                  url: type === 'feishu_auth' ? '待生成' : this.fileFrom.linkUrl,
                   courseId:this.fileFrom.courseId,
                   videoId:this.fileFrom.videoId,
                   expiresDays:this.fileFrom.expiresDays,
+                  linkType: type === 'feishu_auth' ? 'feishu_auth' : null,
                 }
               };
             }else if (type==='miniprogram'){

+ 12 - 11
src/views/qw/sopTemp/updateSopTemp.vue

@@ -267,7 +267,7 @@
                                               <el-radio
                                                 :key="item.dictValue"
                                                 :label="item.dictValue"
-                                                :disabled="(content.type!=2 && (item.dictValue === '9' || item.dictValue === '17')) || (content.isOfficial==1 && ['5','6','7','8','9','17'].includes(item.dictValue))"
+                                                :disabled="(content.type!=2 && (item.dictValue === '9' || item.dictValue === '17' || item.dictValue === '18')) || (content.isOfficial==1 && ['5','6','7','8','9','17','18'].includes(item.dictValue))"
                                                 v-for="item in sysQwSopAiContentType">{{ item.dictLabel }}
                                               </el-radio>
                                             </el-radio-group>
@@ -279,7 +279,7 @@
                                               <el-radio
                                                 :key="item.dictValue"
                                                 :label="item.dictValue"
-                                                :disabled="(content.type!=2 && (item.dictValue === '9' || item.dictValue === '17')) || (content.isOfficial==1 && ['5','6','7','8','9','17'].includes(item.dictValue))"
+                                                :disabled="(content.type!=2 && (item.dictValue === '9' || item.dictValue === '17' || item.dictValue === '18')) || (content.isOfficial==1 && ['5','6','7','8','9','17','18'].includes(item.dictValue))"
                                                 v-for="item in sysQwSopAiContentType" v-if="setIndex == 0 ? courseTypeList.includes(item.dictValue) : !courseTypeList.includes(item.dictValue)">{{ item.dictLabel }}
                                               </el-radio>
                                             </el-radio-group>
@@ -309,7 +309,7 @@
                                                        type="image" :num="1" :width="150" :height="150"/>
 
                                           <div
-                                            v-if="setList.contentType == 3  || ((setList.contentType == 9 || setList.contentType == 17) && content.type==2 )">
+                                            v-if="setList.contentType == 3  || ((setList.contentType == 9 || setList.contentType == 17 || setList.contentType == 18) && content.type==2 )">
                                             <el-card class="box-card">
                                               <el-form-item label="链接标题:" label-width="100px" required>
                                                 <el-input :disabled="formType == 3 || (form.sendType == 11 && contentIndex != 0 && setIndex == 0)" v-model="setList.linkTitle"
@@ -341,6 +341,7 @@
                                               <div v-if="content.type == 2 ">
                                                 <el-form-item label="链接地址:" label-width="100px">
                                                   <el-tag v-if="setList.contentType == 17" type="info">飞书看课链接由服务端根据所选课程、课节自动生成</el-tag>
+                                                  <el-tag v-else-if="setList.contentType == 18" type="info">飞书NEW领取链接由服务端根据所选课程、课节自动生成</el-tag>
                                                   <el-tag v-else type="warning" v-model="setList.isBindUrl = 1 ">选择的课程小节
                                                     即为卡片链接地址
                                                   </el-tag>
@@ -739,7 +740,7 @@ export default {
       dayList: [],
       ruleList: [],
       ids: [],
-      courseTypeList: ['1','3', '4', '9', '17'],
+      courseTypeList: ['1','3', '4', '9', '17','18'],
       sysFsSopWatchStatus: [],
       //消息内容类型 企微版
       sysQwSopContentType: [],
@@ -1115,15 +1116,15 @@ export default {
                 this.$message.error("图片不能为空")
                 return false;
               }
-              if ((data.content[j].setting[k].contentType == 3 || data.content[j].setting[k].contentType == 9 || data.content[j].setting[k].contentType == 17 || data.content[j].setting[k].contentType == 10) && (data.content[j].setting[k].linkTitle == null || data.content[j].setting[k].linkTitle == "")) {
+              if ((data.content[j].setting[k].contentType == 3 || data.content[j].setting[k].contentType == 9 || data.content[j].setting[k].contentType == 17 || data.content[j].setting[k].contentType == 18 || data.content[j].setting[k].contentType == 10) && (data.content[j].setting[k].linkTitle == null || data.content[j].setting[k].linkTitle == "")) {
                 this.$message.error("链接标题不能为空")
                 return false;
               }
-              if ((data.content[j].setting[k].contentType == 3 || data.content[j].setting[k].contentType == 9 || data.content[j].setting[k].contentType == 17 || data.content[j].setting[k].contentType == 10) && (data.content[j].setting[k].linkDescribe == null || data.content[j].setting[k].linkDescribe == "")) {
+              if ((data.content[j].setting[k].contentType == 3 || data.content[j].setting[k].contentType == 9 || data.content[j].setting[k].contentType == 17 || data.content[j].setting[k].contentType == 18 || data.content[j].setting[k].contentType == 10) && (data.content[j].setting[k].linkDescribe == null || data.content[j].setting[k].linkDescribe == "")) {
                 this.$message.error("链接描述不能为空")
                 return false;
               }
-              if ((data.content[j].setting[k].contentType == 3 || data.content[j].setting[k].contentType == 9 || data.content[j].setting[k].contentType == 17 || data.content[j].setting[k].contentType == 10) && (data.content[j].setting[k].linkImageUrl == null || data.content[j].setting[k].linkImageUrl == "")) {
+              if ((data.content[j].setting[k].contentType == 3 || data.content[j].setting[k].contentType == 9 || data.content[j].setting[k].contentType == 17 || data.content[j].setting[k].contentType == 18 || data.content[j].setting[k].contentType == 10) && (data.content[j].setting[k].linkImageUrl == null || data.content[j].setting[k].linkImageUrl == "")) {
                 this.$message.error("链接图片不能为空")
                 return false;
               }
@@ -1356,7 +1357,7 @@ export default {
         if (selectedCourse && content.type == 2 && content.courseId != null) {
           //响应式直接给链接的标题/封面上值
 
-          if (content.setting[i].contentType == 3 || content.setting[i].contentType == 9 || content.setting[i].contentType == 17) {
+          if (content.setting[i].contentType == 3 || content.setting[i].contentType == 9 || content.setting[i].contentType == 17 || content.setting[i].contentType == 18) {
             this.$set(content.setting[i], 'linkTitle', selectedCourse.dictLabel);
             this.$set(content.setting[i], 'linkImageUrl', selectedCourse.dictImgUrl);
           }
@@ -1468,7 +1469,7 @@ export default {
         for (let i = 0; i < content.setting.length; i++) {
           //响应式直接给链接的标题/封面上值
           if (selectedCourse && content.type == 2 && content.courseId != null) {
-            if (content.setting[i].contentType == 3 || content.setting[i].contentType == 9 || content.setting[i].contentType == 17) {
+            if (content.setting[i].contentType == 3 || content.setting[i].contentType == 9 || content.setting[i].contentType == 17 || content.setting[i].contentType == 18) {
               this.$set(content.setting[i], 'linkTitle', selectedCourse.dictLabel);
               this.$set(content.setting[i], 'linkImageUrl', selectedCourse.dictImgUrl);
             }
@@ -1490,7 +1491,7 @@ export default {
           //响应式直接给链接的描述上值
           if (selectedVideo && content.type == 2 && content.videoId != null) {
 
-            if (content.setting[i].contentType == 3 || content.setting[i].contentType == 9 || content.setting[i].contentType == 17) {
+            if (content.setting[i].contentType == 3 || content.setting[i].contentType == 9 || content.setting[i].contentType == 17 || content.setting[i].contentType == 18) {
               this.$set(content.setting[i], 'linkDescribe', selectedVideo.dictLabel);
             }
             if (content.setting[i].contentType == 4) {
@@ -1524,7 +1525,7 @@ export default {
         //如果是链接的才上
         if (selectedVideo && content.type == 2 && content.videoId != null) {
 
-          if (content.setting[i].contentType == 3 || content.setting[i].contentType == 9 || content.setting[i].contentType == 17) {
+          if (content.setting[i].contentType == 3 || content.setting[i].contentType == 9 || content.setting[i].contentType == 17 || content.setting[i].contentType == 18) {
             this.$set(content.setting[i], 'linkDescribe', selectedVideo.dictLabel);
           }
           if (content.setting[i].contentType == 4) {