吴树波 16 часов назад
Родитель
Сommit
803cb27314

+ 124 - 24
src/views/course/courseFinishTemp/index.vue

@@ -186,9 +186,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">
@@ -365,12 +371,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">
@@ -546,9 +559,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
@@ -1049,8 +1063,16 @@ export default {
         console.log("this.response.data", response.data)
         this.form = response.data;
 
-        this.setting = JSON.parse(this.form.setting)
-        this.chatSetting = JSON.parse(this.form.chatSetting)
+        try {
+          this.setting = this.form.setting ? JSON.parse(this.form.setting) : [];
+        } catch (e) {
+          this.setting = [];
+        }
+        try {
+          this.chatSetting = this.form.chatSetting ? JSON.parse(this.form.chatSetting) : [];
+        } catch (e) {
+          this.chatSetting = [];
+        }
         if (response.data.companyUserIds != null) {
           this.companyUserIds = this.form.companyUserIds.split(",");
         }
@@ -1058,13 +1080,11 @@ export default {
         videoList(this.form.courseId).then(response => {
           this.videoList = response.list;
         });
-        this.setting.forEach(item => {
-          if (item.contentType == 4 && item.courseId) {
-            // 初始化 videoOptions
+        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;
             });
@@ -1127,35 +1147,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("群聊恭喜规则:语音不能为空")
             }
           }
 
@@ -1213,3 +1262,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>

+ 180 - 60
src/views/course/courseFinishTempParent/deptIndex.vue

@@ -150,9 +150,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">
@@ -329,12 +335,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">
@@ -510,9 +523,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
@@ -815,6 +829,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 = "修改完课模板";
       });
@@ -823,6 +862,89 @@ 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();
+          }
+
+          const processedSetting = this.setting.map(item => {
+            const newItem = {...item};
+            if (newItem.videoOptions) {
+              delete newItem.videoOptions;
+            }
+            if (newItem.videoLoading !== undefined) {
+              delete newItem.videoLoading;
+            }
+            return newItem;
+          });
+
+          this.form.setting = JSON.stringify(processedSetting);
+          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("修改成功");
@@ -830,60 +952,7 @@ export default {
               this.getList();
             });
           } else {
-            if (this.form.isAllCompanyUser == null) {
-              this.form.isAllCompanyUser = 2;
-            }
-            this.form.companyUserIds = this.companyUserIds.toString()
-
-
-            const processedSetting = this.setting.map(item => {
-              const newItem = {...item};
-              if (newItem.videoOptions) {
-                delete newItem.videoOptions;
-              }
-              if (newItem.videoLoading !== undefined) {
-                delete newItem.videoLoading;
-              }
-              return newItem;
-            });
-
-            this.form.setting = JSON.stringify(processedSetting);
-            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.loading = true
               this.msgSuccess("新增成功");
               this.open = false;
               this.getList();
@@ -1005,3 +1074,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>

+ 180 - 60
src/views/course/courseFinishTempParent/index.vue

@@ -140,9 +140,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">
@@ -319,12 +325,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">
@@ -500,9 +513,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
@@ -800,6 +814,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 = "修改完课模板";
       });
@@ -808,6 +847,89 @@ 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();
+          }
+
+          const processedSetting = this.setting.map(item => {
+            const newItem = {...item};
+            if (newItem.videoOptions) {
+              delete newItem.videoOptions;
+            }
+            if (newItem.videoLoading !== undefined) {
+              delete newItem.videoLoading;
+            }
+            return newItem;
+          });
+
+          this.form.setting = JSON.stringify(processedSetting);
+          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("修改成功");
@@ -815,60 +937,7 @@ export default {
               this.getList();
             });
           } else {
-            if (this.form.isAllCompanyUser == null) {
-              this.form.isAllCompanyUser = 2;
-            }
-            this.form.companyUserIds = this.companyUserIds.toString()
-
-
-            const processedSetting = this.setting.map(item => {
-              const newItem = {...item};
-              if (newItem.videoOptions) {
-                delete newItem.videoOptions;
-              }
-              if (newItem.videoLoading !== undefined) {
-                delete newItem.videoLoading;
-              }
-              return newItem;
-            });
-
-            this.form.setting = JSON.stringify(processedSetting);
-            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.loading = true
               this.msgSuccess("新增成功");
               this.open = false;
               this.getList();
@@ -1017,3 +1086,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>

+ 182 - 60
src/views/course/courseFinishTempParent/myIndex.vue

@@ -150,9 +150,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">
@@ -329,12 +335,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">
@@ -510,9 +523,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
@@ -742,6 +756,8 @@ export default {
     },
     // 表单重置
     reset() {
+      this.setting = [];
+      this.chatSetting = [];
       this.form = {
         id: null,
         status: 1,
@@ -812,6 +828,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 = "修改完课模板";
       });
@@ -820,6 +861,89 @@ 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();
+          }
+
+          const processedSetting = this.setting.map(item => {
+            const newItem = {...item};
+            if (newItem.videoOptions) {
+              delete newItem.videoOptions;
+            }
+            if (newItem.videoLoading !== undefined) {
+              delete newItem.videoLoading;
+            }
+            return newItem;
+          });
+
+          this.form.setting = JSON.stringify(processedSetting);
+          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("修改成功");
@@ -827,60 +951,7 @@ export default {
               this.getList();
             });
           } else {
-            if (this.form.isAllCompanyUser == null) {
-              this.form.isAllCompanyUser = 2;
-            }
-            this.form.companyUserIds = this.companyUserIds.toString()
-
-
-            const processedSetting = this.setting.map(item => {
-              const newItem = {...item};
-              if (newItem.videoOptions) {
-                delete newItem.videoOptions;
-              }
-              if (newItem.videoLoading !== undefined) {
-                delete newItem.videoLoading;
-              }
-              return newItem;
-            });
-
-            this.form.setting = JSON.stringify(processedSetting);
-            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.loading = true
               this.msgSuccess("新增成功");
               this.open = false;
               this.getList();
@@ -1002,3 +1073,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>

+ 46 - 6
src/views/course/coursePlaySourceConfig/index.vue

@@ -274,7 +274,7 @@
                       type="text"
                       icon="el-icon-edit"
                       class="row-action-btn"
-                      title="修改配置"
+                      title="修改小程序"
                       @click="handleUpdate(scope.row)"
                     />
                     <el-button
@@ -311,9 +311,28 @@
       </el-col>
     </el-row>
 
-    <!-- 修改小程序(状态 + 自定义授权) -->
+    <!-- 修改小程序(基础信息 + 状态 + 自定义授权) -->
     <el-dialog :title="title" :visible.sync="open" width="560px" append-to-body>
       <el-form ref="form" :model="form" :rules="rules" label-width="110px" size="small">
+        <el-divider content-position="left">基础信息</el-divider>
+        <el-form-item label="名称" prop="name">
+          <el-input v-model="form.name" placeholder="请输入小程序名称" maxlength="64" />
+        </el-form-item>
+        <el-form-item label="类型">
+          <el-input :value="form.type == 2 || form.type == '2' ? '公众号' : '小程序'" disabled />
+        </el-form-item>
+        <el-form-item label="原始ID" prop="originalId">
+          <el-input v-model="form.originalId" placeholder="请输入原始ID(gh_xxx)" />
+        </el-form-item>
+        <el-form-item label="AppID" prop="appid">
+          <el-input v-model="form.appid" placeholder="请输入 AppID" />
+        </el-form-item>
+        <el-form-item label="Secret" prop="secret">
+          <el-input v-model="form.secret" placeholder="请输入 Secret" show-password />
+        </el-form-item>
+        <el-form-item label="图标" prop="img">
+          <image-upload v-model="form.img" :file-type='["png", "jpg", "jpeg"]' :limit="1" />
+        </el-form-item>
         <el-form-item label="状态" prop="status">
           <el-select
             v-model="form.status"
@@ -617,6 +636,11 @@ export default {
       open: false,
       form: {},
       rules: {
+        name: [{ required: true, message: '名称不能为空', trigger: 'blur' }],
+        originalId: [{ required: true, message: '原始ID不能为空', trigger: 'blur' }],
+        appid: [{ required: true, message: 'AppID不能为空', trigger: 'blur' }],
+        secret: [{ required: true, message: 'Secret不能为空', trigger: 'blur' }],
+        img: [{ required: true, message: '图标不能为空', trigger: 'change' }],
         status: [
           { required: true, message: '状态不能为空', trigger: 'change' }
         ],
@@ -1125,7 +1149,7 @@ export default {
           miniAppAuthType: data.miniAppAuthType == null ? null : Number(data.miniAppAuthType)
         }
         this.open = true
-        this.title = '修改小程序配置'
+        this.title = '修改小程序'
       })
     },
     submitForm() {
@@ -1143,9 +1167,25 @@ export default {
         } else if (this.form.miniAppAuthType !== 2) {
           this.form.userCourseAuthDomain = null
         }
-        this.form.companyIds = [companyIdNum]
-        this.form.companyId = companyIdNum
-        update(this.form).then(response => {
+        // 仅提交基础信息 + 状态 + 授权相关字段,避免无关字段覆盖
+        const payload = {
+          id: this.form.id,
+          name: this.form.name,
+          originalId: this.form.originalId,
+          appid: this.form.appid,
+          secret: this.form.secret,
+          img: this.form.img,
+          type: this.form.type != null ? Number(this.form.type) : 1,
+          status: this.form.status,
+          customAuthEnabled: this.form.customAuthEnabled || 0,
+          miniAppAuthType: this.form.customAuthEnabled === 1 ? this.form.miniAppAuthType : null,
+          userCourseAuthDomain: this.form.customAuthEnabled === 1 && this.form.miniAppAuthType === 2
+            ? this.form.userCourseAuthDomain
+            : null,
+          companyIds: [companyIdNum],
+          companyId: companyIdNum
+        }
+        update(payload).then(response => {
           const { code, msg } = response
           if (code !== 200) {
             this.msgError(msg)

+ 39 - 19
src/views/qw/friendWelcome/deptFriendWelcome.vue

@@ -205,7 +205,8 @@
                   <div slot="header" style="display: flex;justify-content: space-between;align-items: center; ">
                     <div style="flex: 1;">
                     <span v-if="item.msgtype === 'image'">【图片】: {{ item.image.pic_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;">
@@ -230,13 +231,16 @@
             </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>
                 <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>
@@ -329,7 +333,8 @@
                                 <div slot="header" style="  display: flex;justify-content: space-between;align-items: center; ">
                                   <div style="flex: 1;">
                                     <span v-if="attachment.msgtype === 'image'">【图片】: {{ attachment.image.pic_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;">
@@ -354,13 +359,16 @@
                           </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>
                               <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>
@@ -407,9 +415,9 @@
             <ImageUpload v-model="fileFrom.imagePicUrl"  type="image" :num="10" :width="150" :height="150"  disabled/>
           </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"
@@ -437,17 +445,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>
@@ -809,6 +817,8 @@ export default {
           return '添加图片';
         case 'link':
           return '添加链接';
+        case 'feishu_auth':
+          return '添加飞书(授权)';
         case 'miniprogram':
           return '添加小程序';
       }
@@ -866,7 +876,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);
         }
@@ -901,8 +911,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
       };
@@ -917,9 +927,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') {
@@ -942,7 +954,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 '编辑图片';
@@ -986,17 +1001,22 @@ export default {
             pic_url: this.fileFrom.imagePicUrl
           }
         };
-      } 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'){

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

@@ -207,7 +207,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;">
@@ -232,7 +233,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>
@@ -242,6 +243,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>
@@ -335,7 +339,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;">
@@ -360,7 +365,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>
@@ -370,6 +375,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>
@@ -435,9 +443,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"
@@ -465,17 +473,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>
@@ -857,8 +865,12 @@ export default {
           return '添加图片';
         case 'link':
           return '添加链接';
+        case 'feishu_auth':
+          return '添加飞书(授权)';
         case 'miniprogram':
           return '添加小程序';
+        case 'video':
+          return '添加视频';
       }
     },
 
@@ -914,7 +926,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);
         }
@@ -949,8 +961,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
       };
@@ -967,9 +979,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') {
@@ -992,7 +1006,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 '编辑图片';
@@ -1000,6 +1017,8 @@ export default {
           return '编辑链接';
         case 'miniprogram':
           return '编辑小程序';
+        case 'video':
+          return '编辑视频';
       }
     },
 
@@ -1044,17 +1063,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'){

+ 41 - 19
src/views/qw/friendWelcome/myIndexNew.vue

@@ -198,7 +198,8 @@
                   <div slot="header" style="display: flex;justify-content: space-between;align-items: center; ">
                     <div style="flex: 1;">
                       <span v-if="item.msgtype === 'image'">【图片】: {{ item.image.pic_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;">
@@ -225,13 +226,16 @@
             </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>
                 <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>
@@ -337,7 +341,10 @@
                                   <span v-if="attachment.msgtype === 'image'">【图片】: {{
                                       attachment.image.pic_url
                                     }}</span>
-                                  <span v-if="attachment.msgtype === 'link'">【链接】: {{
+                                  <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'">【小程序】: {{
@@ -369,13 +376,16 @@
 
                         <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>
                             <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>-->
@@ -427,9 +437,9 @@
             <ImageUpload v-model="fileFrom.imagePicUrl" type="image" :num="10" :width="150" :height="150" disabled/>
           </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
@@ -461,17 +471,17 @@
             <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>
@@ -847,6 +857,8 @@ export default {
           return '添加图片';
         case 'link':
           return '添加链接';
+        case 'feishu_auth':
+          return '添加飞书(授权)';
         case 'miniprogram':
           return '添加小程序';
       }
@@ -904,7 +916,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);
         }
@@ -939,8 +951,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
       };
@@ -955,9 +967,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') {
@@ -979,7 +993,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,17 +1046,22 @@ export default {
             pic_url: this.fileFrom.imagePicUrl
           }
         };
-      } 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') {

+ 41 - 22
src/views/qw/friendWelcome/myWelcome.vue

@@ -205,7 +205,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;">
@@ -230,7 +231,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>
@@ -240,6 +241,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>
@@ -332,7 +336,8 @@
                                 <div slot="header" style="  display: flex;justify-content: space-between;align-items: center; ">
                                   <div style="flex: 1;">
                                     <span v-if="attachment.msgtype === 'image'">【图片】: {{ attachment.image.pic_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;">
@@ -357,7 +362,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>
@@ -367,6 +372,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>
@@ -432,9 +440,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"
@@ -462,17 +470,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>
@@ -483,9 +491,6 @@
               </el-row>
             </el-form-item>
           </div>
-<!--          <el-form-item label="图文链接:" prop="linkUrl">-->
-<!--            <el-input v-model="fileFrom.linkUrl" :rows="2"  placeholder="选择了课程小节会自动设置地址" />-->
-<!--          </el-form-item>-->
         </div>
         <div v-if="welcomeItem.type==='miniprogram'">
 
@@ -856,6 +861,8 @@ export default {
           return '添加视频';
         case 'link':
           return '添加链接';
+        case 'feishu_auth':
+          return '添加飞书(授权)';
         case 'miniprogram':
           return '添加小程序';
       }
@@ -913,7 +920,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);
         }
@@ -948,8 +955,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
       };
@@ -966,9 +973,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') {
@@ -991,7 +1000,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 '编辑图片';
@@ -999,6 +1011,8 @@ export default {
           return '编辑链接';
         case 'miniprogram':
           return '编辑小程序';
+        case 'video':
+          return '编辑视频';
       }
     },
 
@@ -1043,17 +1057,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'){

+ 2 - 1
src/views/qw/massSendLog/index.vue

@@ -78,6 +78,7 @@
                   <span v-if="item.contentType == 8">视频号</span>
                   <span v-if="item.contentType == 9">APP</span>
                   <span v-if="item.contentType == 17">飞书</span>
+                  <span v-if="item.contentType == 18">飞书NEW</span>
                   <span v-if="item.contentType == 10">自定义小程序</span>
                   <span v-if="item.contentType == 11">群公告</span>
                 </div>
@@ -89,7 +90,7 @@
                     fit="contain"
                     @click.prevent="openImageViewer(item.imgUrl)" />
                 </div>
-                <div v-if="item.contentType == 3 || item.contentType == 9 || item.contentType == 17" class="message-style">
+                <div v-if="item.contentType == 3 || item.contentType == 9 || item.contentType == 17 || item.contentType == 18" class="message-style">
                   <div
                     style="background-color: white; padding: 10px; width: 100%"
                     @click="openLink(item.linkUrl)">

+ 28 - 23
src/views/qw/sop/sop.vue

@@ -867,7 +867,8 @@
                           <ImageUpload v-model="item.linkImageUrl" type="image" :num="1" :file-size="2" :width="150" :height="150" style="margin-top: 1%;" />
                         </el-form-item>
                         <el-form-item label="链接地址:"  label-width="100px" >
-                          <el-tag type="warning" v-model="item.isBindUrl=1">选择的课程小节 即为卡片链接地址</el-tag>
+                          <el-tag v-if="item.contentType == 18 || item.contentType == '18'" type="info">飞书NEW领取链接由服务端根据所选课程、课节自动生成</el-tag>
+                          <el-tag v-else type="warning" v-model="item.isBindUrl=1">选择的课程小节 即为卡片链接地址</el-tag>
                         </el-form-item>
                       </el-card>
                     </div>
@@ -903,14 +904,7 @@
                           <ImageUpload v-model="item.linkImageUrl" type="image" :num="1" :file-size="2" :width="150" :height="150" style="margin-top: 1%;" />
                         </el-form-item>
                         <el-form-item label="链接说明" label-width="100px">
-                          <el-tag type="info">飞书看课链接由服务端根据上方所选课程、课节自动生成</el-tag>
-                        </el-form-item>
-                        <el-form-item label="客户授权" label-width="100px">
-                          <el-radio-group v-model="item.feishuNeedAuth">
-                            <el-radio :label="1">需要授权</el-radio>
-                            <el-radio :label="0">免授权</el-radio>
-                          </el-radio-group>
-                          <div style="color: #909399; font-size: 12px; margin-top: 4px;">免授权:客户可直接看课</div>
+                          <el-tag type="info">飞书看课链接由服务端根据上方所选课程、课节自动生成(固定免授权)</el-tag>
                         </el-form-item>
                       </el-card>
                     </div>
@@ -1901,6 +1895,15 @@ export default {
       return String(ct).trim() === '17';
     },
     isLinkH5ContentType(ct) {
+      if (ct === undefined || ct === null || ct === '') {
+        return false;
+      }
+      // 3=H5链接,18=飞书NEW(按链接卡片展示,不做飞书17授权 UI)
+      const s = String(ct).trim();
+      return s === '3' || s === '18';
+    },
+    /** 仅手动填写链接地址的 H5(不含飞书NEW 18,18 由服务端生成) */
+    isManualLinkH5ContentType(ct) {
       if (ct === undefined || ct === null || ct === '') {
         return false;
       }
@@ -1919,9 +1922,8 @@ export default {
         }
         if (this.isFeishuContentType(row.contentType)) {
           o.contentType = '17';
-          if (o.feishuNeedAuth === undefined || o.feishuNeedAuth === null || o.feishuNeedAuth === '') {
-            o.feishuNeedAuth = 1;
-          }
+          // 飞书链接(contentType=17)仅支持免授权
+          o.feishuNeedAuth = 0;
         }
         return o;
       });
@@ -1929,18 +1931,21 @@ export default {
 
     handleContentTypeChange() {
 
+      // 飞书链接(contentType=17)仅支持免授权
+      for (let i = 0; i < this.setting.length; i++) {
+        if (this.setting[i].contentType == 7 && !this.setting[i].voiceInputMode) {
+          this.$set(this.setting[i], 'voiceInputMode', 'dropdown');
+        }
+        if (this.isFeishuContentType(this.setting[i].contentType)) {
+          this.$set(this.setting[i], 'feishuNeedAuth', 0);
+        }
+      }
       //如果是链接的才上
       if (this.msgForm.courseId != null ) {
         const selectedCourse = this.courseList.find(course => parseInt(course.dictValue) === this.msgForm.courseId);
         for (let i = 0; i < this.setting.length; i++) {
-          if (this.setting[i].contentType == 7 && !this.setting[i].voiceInputMode) {
-            this.$set(this.setting[i], 'voiceInputMode', 'dropdown');
-          }
-          if (this.isFeishuContentType(this.setting[i].contentType) && (this.setting[i].feishuNeedAuth === undefined || this.setting[i].feishuNeedAuth === null || this.setting[i].feishuNeedAuth === '')) {
-            this.$set(this.setting[i], 'feishuNeedAuth', 1);
-          }
           //响应式直接给链接的标题/封面上值
-          if (selectedCourse && (this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.isFeishuContentType(this.setting[i].contentType)) && this.msgForm.courseId != null) {
+          if (selectedCourse && (this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 18 || this.isFeishuContentType(this.setting[i].contentType)) && this.msgForm.courseId != null) {
             this.$set(this.setting[i], 'linkTitle', selectedCourse.dictLabel);
             this.$set(this.setting[i], 'linkImageUrl', selectedCourse.dictImgUrl);
           }
@@ -1959,7 +1964,7 @@ export default {
           //响应式直接给链接的描述上值
           if (selectedVideo && this.msgForm.videoId != null) {
             console.log(2, this.setting[i].contentType)
-            if (this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.isFeishuContentType(this.setting[i].contentType)) {
+            if (this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 18 || this.isFeishuContentType(this.setting[i].contentType)) {
               this.$set(this.setting[i], 'linkDescribe', selectedVideo.dictLabel);
             }
             if (this.setting[i].contentType == 4) {
@@ -1980,7 +1985,7 @@ export default {
         for (let i = 0; i < this.setting.length; i++) {
           //响应式直接给链接的描述上值
           if (selectedVideo && this.msgForm.videoId != null) {
-            if (this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.isFeishuContentType(this.setting[i].contentType)) {
+            if (this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 18 || this.isFeishuContentType(this.setting[i].contentType)) {
               this.$set(this.setting[i], 'linkDescribe', selectedVideo.dictLabel);
             }
 
@@ -2456,7 +2461,7 @@ export default {
             if ((this.isLinkH5ContentType(this.setting[i].contentType) || this.isAppContentType(this.setting[i].contentType) || this.isFeishuContentType(this.setting[i].contentType)) && (this.setting[i].linkImageUrl == null || this.setting[i].linkImageUrl == "")) {
               return this.$message.error(this.isAppContentType(this.setting[i].contentType) ? "APP 封面不能为空" : (this.isFeishuContentType(this.setting[i].contentType) ? "飞书封面不能为空" : "链接图片不能为空"))
             }
-            if (this.isLinkH5ContentType(this.setting[i].contentType) && this.setting[i].type == 1 && (this.setting[i].linkUrl == null || this.setting[i].linkUrl == "")) {
+            if (this.isManualLinkH5ContentType(this.setting[i].contentType) && 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 == "")) {
@@ -2510,7 +2515,7 @@ export default {
         const selectedCourse = this.courseList.find(course => parseInt(course.dictValue) === this.msgForm.courseId);
         for (let i = 0; i < this.setting.length; i++) {
           //响应式直接给链接的标题/封面上值
-          if (selectedCourse && (this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.isFeishuContentType(this.setting[i].contentType)) && this.msgForm.courseId != null) {
+          if (selectedCourse && (this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 18 || this.isFeishuContentType(this.setting[i].contentType)) && this.msgForm.courseId != null) {
             this.$set(this.setting[i], 'linkTitle', selectedCourse.dictLabel);
             this.$set(this.setting[i], 'linkImageUrl', selectedCourse.dictImgUrl);
           }

+ 2 - 1
src/views/qw/sopLogs/sopLogsList.vue

@@ -199,6 +199,7 @@
                 <span v-if="item.contentType == 8">视频号</span>
                 <span v-if="item.contentType == 9">APP</span>
                 <span v-if="item.contentType == 17">飞书</span>
+                <span v-if="item.contentType == 18">飞书NEW</span>
                 <span v-if="item.contentType == 10">自定义小程序</span>
                 <span v-if="item.contentType == 11">群公告</span>
                 <span v-if="item.contentType == 4"><el-button size="mini" type="primary" @click="generateShortLink(item)" style="margin-left: 330px;">生成短链</el-button></span>
@@ -218,7 +219,7 @@
                 fit="contain"
                 @click.prevent="openImageViewer(item.imgUrl)" />
             </div>
-            <div v-if="item.contentType == 3 || item.contentType == 9 || item.contentType == 17" class="message-style">
+            <div v-if="item.contentType == 3 || item.contentType == 9 || item.contentType == 17 || item.contentType == 18" class="message-style">
               <div
                 style="background-color: white; padding: 10px; width: 100%"
                 @click="openLink(item.linkUrl)">

+ 24 - 27
src/views/qw/sopTemp/updateSopTemp.vue

@@ -303,7 +303,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>
@@ -315,7 +315,7 @@
                                               <el-radio
                                                 :key="item.dictValue"
                                                 :label="item.dictValue"
-                                                :disabled="((content.type!=2 || form.sendType == 4) && (item.dictValue === '8' || item.dictValue === '9' || item.dictValue === '17') || (content.isOfficial==1 && ['5','6','7','8','9','17'].includes(item.dictValue)))"
+                                                :disabled="((content.type!=2 || form.sendType == 4) && (item.dictValue === '8' || 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>
@@ -327,7 +327,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="courseTypeList.includes(item.dictValue)">{{ item.dictLabel }}
                                               </el-radio>
@@ -395,7 +395,7 @@
                                                        type="image" :num="1" :width="150" :height="150"/>
 
                                           <div
-                                            v-if="(setList.contentType == 3 || item.contentType ==9) || ((setList.contentType == 9 || setList.contentType == 17) && content.type==2 )">
+                                            v-if="(setList.contentType == 3 || item.contentType ==9) || ((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"
@@ -426,20 +426,12 @@
                                               </div>
                                               <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-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>
                                                 </el-form-item>
-                                                <el-form-item v-if="setList.contentType == 17" label="客户授权:" label-width="100px">
-                                                  <el-radio-group v-model="setList.feishuNeedAuth"
-                                                                   :disabled="formType == 3 || (form.sendType == 11 && contentIndex != 0 && setIndex == 0)"
-                                                                   @change="updateAll(setIndex, item, 'feishuNeedAuth', $event)">
-                                                    <el-radio :label="1">需要授权</el-radio>
-                                                    <el-radio :label="0">免授权</el-radio>
-                                                  </el-radio-group>
-                                                  <div style="color: #909399; font-size: 12px; margin-top: 4px;">免授权:客户可直接看课</div>
-                                                </el-form-item>
                                               </div>
                                             </el-card>
                                           </div>
@@ -1007,7 +999,7 @@ export default {
       ruleList: [],
       ids: [],
       // startTimeRange: [],
-      courseTypeList: ['1','2', '4','5','6', '7','8','9','10','11','17'],
+      courseTypeList: ['1','2', '4','5','6', '7','8','9','10','11','17','18'],
       sysFsSopWatchStatus: [],
       //消息内容类型 企微版
       sysQwSopContentType: [],
@@ -1593,15 +1585,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;
               }
@@ -1672,15 +1664,15 @@ export default {
                 this.$message.error("图片不能为空")
                 return false;
               }
-              if ((set.contentType == 3 || set.contentType == 9 || set.contentType == 17) && (set.linkTitle == null || set.linkTitle == "")) {
+              if ((set.contentType == 3 || set.contentType == 9 || set.contentType == 17 || set.contentType == 18) && (set.linkTitle == null || set.linkTitle == "")) {
                 this.$message.error("链接标题不能为空")
                 return false;
               }
-              if ((set.contentType == 3 || set.contentType == 9 || set.contentType == 17) && (set.linkDescribe == null || set.linkDescribe == "")) {
+              if ((set.contentType == 3 || set.contentType == 9 || set.contentType == 17 || set.contentType == 18) && (set.linkDescribe == null || set.linkDescribe == "")) {
                 this.$message.error("链接描述不能为空")
                 return false;
               }
-              if ((set.contentType == 3 || set.contentType == 9 || set.contentType == 17) && (set.linkImageUrl == null || set.linkImageUrl == "")) {
+              if ((set.contentType == 3 || set.contentType == 9 || set.contentType == 17 || set.contentType == 18) && (set.linkImageUrl == null || set.linkImageUrl == "")) {
                 this.$message.error("链接图片不能为空")
                 return false;
               }
@@ -1950,7 +1942,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);
           }
@@ -2103,6 +2095,10 @@ export default {
       if (!setting) {
         return;
       }
+      // 飞书链接(contentType=17)仅支持免授权
+      if (setting.contentType == 17 || setting.contentType === '17') {
+        setting.feishuNeedAuth = 0;
+      }
       if (setting.isRandomSend == 1 && Array.isArray(setting.randomValueList)) {
         setting.randomValueList = setting.randomValueList
           .map(item => (item == null ? '' : item.trim()))
@@ -2156,8 +2152,9 @@ export default {
     },
     handleContentTypeChange(content, index, countIndex, setIndex, item, fieldName, val) {
 
-      if (val == 17 && content.setting[setIndex] && (content.setting[setIndex].feishuNeedAuth === undefined || content.setting[setIndex].feishuNeedAuth === null || content.setting[setIndex].feishuNeedAuth === '')) {
-        this.$set(content.setting[setIndex], 'feishuNeedAuth', 1);
+      // 飞书链接(contentType=17)仅支持免授权
+      if (val == 17 && content.setting[setIndex]) {
+        this.$set(content.setting[setIndex], 'feishuNeedAuth', 0);
       }
 
       //消息类别是直播间&&选择了发送直播间
@@ -2184,7 +2181,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);
             }
@@ -2205,7 +2202,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 (this.projectFrom == 'sxjz' && selectedVideo.dictImgUrl) {
@@ -2249,7 +2246,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 (this.projectFrom == 'sxjz' && selectedVideo.dictImgUrl) {

+ 21 - 17
src/views/qw/sopUserLogsInfo/sendMsgOpenTool.vue

@@ -178,7 +178,7 @@
 
                     <ImageUpload v-if="item.contentType == 2 " v-model="item.imgUrl" type="image" :num="1"  :width="150" :height="150" />
 
-                    <div v-if="item.contentType == 3 || item.contentType == 9 || item.contentType == 17">
+                    <div v-if="item.contentType == 3 || item.contentType == 9 || item.contentType == 17 || item.contentType == 18">
                       <el-card class="box-card">
                         <el-form-item label="链接标题:"  label-width="100px">
                           <el-input v-model="item.linkTitle" placeholder="请输入链接标题" style="width: 90%;"/>
@@ -190,16 +190,10 @@
                           <ImageUpload v-model="item.linkImageUrl" type="image" :num="1" :file-size="2" :width="150" :height="150" style="margin-top: 1%;" />
                         </el-form-item>
                         <el-form-item label="链接地址:"  label-width="100px" >
-                          <el-tag v-if="item.contentType == 17" type="info">飞书看课链接由服务端根据所选课程、课节自动生成</el-tag>
+                          <el-tag v-if="item.contentType == 17" type="info">飞书看课链接由服务端根据所选课程、课节自动生成(固定免授权)</el-tag>
+                          <el-tag v-else-if="item.contentType == 18" type="info">飞书NEW领取链接由服务端根据所选课程、课节自动生成</el-tag>
                           <el-tag v-else type="warning" v-model="item.isBindUrl=1">选择的课程小节 即为卡片链接地址</el-tag>
                         </el-form-item>
-                        <el-form-item v-if="item.contentType == 17" label="客户授权:" label-width="100px">
-                          <el-radio-group v-model="item.feishuNeedAuth">
-                            <el-radio :label="1">需要授权</el-radio>
-                            <el-radio :label="0">免授权</el-radio>
-                          </el-radio-group>
-                          <div style="color: #909399; font-size: 12px; margin-top: 4px;">免授权:客户可直接看课</div>
-                        </el-form-item>
                       </el-card>
                     </div>
                     <div v-if="item.contentType == 4 || item.contentType == 10 ">
@@ -636,7 +630,7 @@ export default {
         for (let i = 0; i < this.setting.length; i++) {
           //响应式直接给链接的标题/封面上值
           if (selectedCourse && this.msgForm.courseId != null) {
-            if ( this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 17 ){
+            if ( this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 17 || this.setting[i].contentType == 18 ){
               this.$set(this.setting[i], 'linkTitle', selectedCourse.dictLabel);
               this.$set(this.setting[i], 'linkImageUrl', selectedCourse.dictImgUrl);
             }
@@ -663,7 +657,7 @@ export default {
         for (let i = 0; i < this.setting.length; i++) {
           //响应式直接给链接的描述上值
           if (selectedVideo && this.msgForm.videoId != null) {
-            if (this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 17 ){
+            if (this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 17 || this.setting[i].contentType == 18 ){
               this.$set(this.setting[i], 'linkDescribe', selectedVideo.dictLabel);
 
               if (this.projectFrom == 'sxjz' && selectedVideo.dictImgUrl) {
@@ -929,6 +923,10 @@ export default {
       if (!item) {
         return;
       }
+      // 飞书链接(contentType=17)仅支持免授权
+      if (item.contentType == 17 || item.contentType === '17') {
+        item.feishuNeedAuth = 0;
+      }
       if (item.isRandomSend == 1 && Array.isArray(item.randomValueList)) {
         item.randomValueList = item.randomValueList
           .map(v => (v == null ? '' : v.trim()))
@@ -942,6 +940,12 @@ export default {
     },
 
     handleContentTypeChange() {
+      // 飞书链接(contentType=17)仅支持免授权
+      for (let i = 0; i < this.setting.length; i++) {
+        if (this.setting[i].contentType == 17 || this.setting[i].contentType === '17') {
+          this.$set(this.setting[i], 'feishuNeedAuth', 0);
+        }
+      }
       //如果是链接的才上
       if (this.msgForm.courseId != null ) {
         const selectedCourse = this.courseList.find(course => parseInt(course.dictValue) === this.msgForm.courseId);
@@ -949,7 +953,7 @@ export default {
           //响应式直接给链接的标题/封面上值
           if (selectedCourse  && this.msgForm.courseId != null) {
 
-            if (this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 17){
+            if (this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 17 || this.setting[i].contentType == 18){
               this.$set(this.setting[i], 'linkTitle', selectedCourse.dictLabel);
               this.$set(this.setting[i], 'linkImageUrl', selectedCourse.dictImgUrl);
             }
@@ -971,7 +975,7 @@ export default {
           //响应式直接给链接的描述上值
           if (selectedVideo  && this.msgForm.videoId != null) {
 
-            if (this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 17){
+            if (this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 17 || this.setting[i].contentType == 18){
               this.$set(this.setting[i], 'linkDescribe', selectedVideo.dictLabel);
 
               if (this.projectFrom == 'sxjz' && selectedVideo.dictImgUrl) {
@@ -1071,16 +1075,16 @@ export default {
               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].contentType == 9 || this.setting[i].contentType == 17  ) && (this.setting[i].linkTitle == null || this.setting[i].linkTitle == "")) {
+              if ((this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 17 || this.setting[i].contentType == 18  ) && (this.setting[i].linkTitle == null || this.setting[i].linkTitle == "")) {
                 return this.$message.error("链接标题不能为空")
               }
-              if ((this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 17 ) && (this.setting[i].linkDescribe == null || this.setting[i].linkDescribe == "")) {
+              if ((this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 17 || this.setting[i].contentType == 18 ) && (this.setting[i].linkDescribe == null || this.setting[i].linkDescribe == "")) {
                 return this.$message.error("链接描述不能为空")
               }
-              if ((this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 17 ) && (this.setting[i].linkImageUrl == null || this.setting[i].linkImageUrl == "")) {
+              if ((this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 17 || this.setting[i].contentType == 18 ) && (this.setting[i].linkImageUrl == null || this.setting[i].linkImageUrl == "")) {
                 return this.$message.error("链接图片不能为空")
               }
-              if ((this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 17 )&& this.setting[i].type == 1 && (this.setting[i].linkUrl == null || this.setting[i].linkUrl == "")) {
+              if (this.setting[i].contentType == 3 && this.setting[i].type == 1 && (this.setting[i].linkUrl == null || this.setting[i].linkUrl == "")) {
                 return this.$message.error("链接地址不能为空")
               }
 

+ 25 - 17
src/views/qw/sopUserLogsInfo/sendMsgSopOpenTool.vue

@@ -105,7 +105,8 @@
                           <ImageUpload v-model="item.linkImageUrl" type="image" :num="1" :file-size="2" :width="150" :height="150" style="margin-top: 1%;" />
                         </el-form-item>
                         <el-form-item label="链接地址:"  label-width="100px" >
-                          <el-tag type="warning" v-model="item.isBindUrl=1">选择的课程小节 即为卡片链接地址</el-tag>
+                          <el-tag v-if="item.contentType == 18 || item.contentType == '18'" type="info">飞书NEW领取链接由服务端根据所选课程、课节自动生成</el-tag>
+                          <el-tag v-else type="warning" v-model="item.isBindUrl=1">选择的课程小节 即为卡片链接地址</el-tag>
                         </el-form-item>
                       </el-card>
                     </div>
@@ -141,14 +142,7 @@
                           <ImageUpload v-model="item.linkImageUrl" type="image" :num="1" :file-size="2" :width="150" :height="150" style="margin-top: 1%;" />
                         </el-form-item>
                         <el-form-item label="链接说明" label-width="100px">
-                          <el-tag type="info">飞书看课链接由服务端根据上方所选课程、课节自动生成</el-tag>
-                        </el-form-item>
-                        <el-form-item label="客户授权" label-width="100px">
-                          <el-radio-group v-model="item.feishuNeedAuth">
-                            <el-radio :label="1">需要授权</el-radio>
-                            <el-radio :label="0">免授权</el-radio>
-                          </el-radio-group>
-                          <div style="color: #909399; font-size: 12px; margin-top: 4px;">免授权:客户可直接看课</div>
+                          <el-tag type="info">飞书看课链接由服务端根据上方所选课程、课节自动生成(固定免授权)</el-tag>
                         </el-form-item>
                       </el-card>
                     </div>
@@ -666,6 +660,15 @@ export default {
       return String(ct).trim() === '17';
     },
     isLinkH5ContentType(ct) {
+      if (ct === undefined || ct === null || ct === '') {
+        return false;
+      }
+      // 3=H5链接,18=飞书NEW(按链接卡片展示,不做飞书17授权 UI)
+      const s = String(ct).trim();
+      return s === '3' || s === '18';
+    },
+    /** 仅手动填写链接地址的 H5(不含飞书NEW 18,18 由服务端生成) */
+    isManualLinkH5ContentType(ct) {
       if (ct === undefined || ct === null || ct === '') {
         return false;
       }
@@ -687,9 +690,8 @@ export default {
         }
         if (this.isFeishuContentType(row.contentType)) {
           o.contentType = '17';
-          if (o.feishuNeedAuth === undefined || o.feishuNeedAuth === null || o.feishuNeedAuth === '') {
-            o.feishuNeedAuth = 1;
-          }
+          // 飞书链接(contentType=17)仅支持免授权
+          o.feishuNeedAuth = 0;
         }
         return o;
       });
@@ -700,7 +702,7 @@ export default {
         for (let i = 0; i < this.setting.length; i++) {
           //响应式直接给链接的标题/封面上值
           if (selectedCourse && this.msgForm.courseId != null) {
-            if ( this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 17 ){
+            if ( this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 17 || this.setting[i].contentType == 18 ){
               this.$set(this.setting[i], 'linkTitle', selectedCourse.dictLabel);
               this.$set(this.setting[i], 'linkImageUrl', selectedCourse.dictImgUrl);
             }
@@ -727,7 +729,7 @@ export default {
         for (let i = 0; i < this.setting.length; i++) {
           //响应式直接给链接的描述上值
           if (selectedVideo && this.msgForm.videoId != null) {
-            if (this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 17 ){
+            if (this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 17 || this.setting[i].contentType == 18 ){
               this.$set(this.setting[i], 'linkDescribe', selectedVideo.dictLabel);
 
               if (this.projectFrom == 'sxjz' && selectedVideo.dictImgUrl) {
@@ -951,6 +953,12 @@ export default {
 
     handleContentTypeChange() {
 
+      // 飞书链接(contentType=17)仅支持免授权
+      for (let i = 0; i < this.setting.length; i++) {
+        if (this.isFeishuContentType(this.setting[i].contentType)) {
+          this.$set(this.setting[i], 'feishuNeedAuth', 0);
+        }
+      }
       //如果是链接的才上
       if (this.msgForm.courseId != null ) {
         const selectedCourse = this.courseList.find(course => parseInt(course.dictValue) === this.msgForm.courseId);
@@ -958,7 +966,7 @@ export default {
           //响应式直接给链接的标题/封面上值
           if (selectedCourse  && this.msgForm.courseId != null) {
 
-            if (this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 17){
+            if (this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 17 || this.setting[i].contentType == 18){
               this.$set(this.setting[i], 'linkTitle', selectedCourse.dictLabel);
               this.$set(this.setting[i], 'linkImageUrl', selectedCourse.dictImgUrl);
 
@@ -982,7 +990,7 @@ export default {
           //响应式直接给链接的描述上值
           if (selectedVideo  && this.msgForm.videoId != null) {
 
-            if (this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 17){
+            if (this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 17 || this.setting[i].contentType == 18){
               this.$set(this.setting[i], 'linkDescribe', selectedVideo.dictLabel);
 
               if (this.projectFrom == 'sxjz' && selectedVideo.dictImgUrl) {
@@ -1067,7 +1075,7 @@ export default {
               if ((this.isLinkH5ContentType(this.setting[i].contentType) || this.isAppContentType(this.setting[i].contentType) || this.isFeishuContentType(this.setting[i].contentType)) && (this.setting[i].linkImageUrl == null || this.setting[i].linkImageUrl == "")) {
                 return this.$message.error(this.isAppContentType(this.setting[i].contentType) ? "APP 封面不能为空" : (this.isFeishuContentType(this.setting[i].contentType) ? "飞书封面不能为空" : "链接图片不能为空"))
               }
-              if (this.isLinkH5ContentType(this.setting[i].contentType) && this.setting[i].type == 1 && (this.setting[i].linkUrl == null || this.setting[i].linkUrl == "")) {
+              if (this.isManualLinkH5ContentType(this.setting[i].contentType) && this.setting[i].type == 1 && (this.setting[i].linkUrl == null || this.setting[i].linkUrl == "")) {
                 return this.$message.error("链接地址不能为空")
               }
 

+ 21 - 17
src/views/qw/sopUserLogsInfo/sopUserLogsInfoDetails.vue

@@ -374,7 +374,7 @@
 
                     <ImageUpload v-if="item.contentType == 2 " v-model="item.imgUrl" type="image" :num="1"  :width="150" :height="150" />
 
-                    <div v-if="item.contentType == 3 || item.contentType ==9 ">
+                    <div v-if="item.contentType == 3 || item.contentType == 9 || item.contentType == 18">
                       <el-card class="box-card">
                         <el-form-item label="链接标题:"  label-width="100px">
                           <el-input v-model="item.linkTitle" placeholder="请输入链接标题" style="width: 90%;"/>
@@ -386,7 +386,8 @@
                           <ImageUpload v-model="item.linkImageUrl" type="image" :num="1" :file-size="2" :width="150" :height="150" style="margin-top: 1%;" />
                         </el-form-item>
                         <el-form-item label="链接地址:"  label-width="100px" >
-                          <el-tag type="warning" v-model="item.isBindUrl=1">选择的课程小节 即为卡片链接地址</el-tag>
+                          <el-tag v-if="item.contentType == 18 || item.contentType == '18'" type="info">飞书NEW领取链接由服务端根据所选课程、课节自动生成</el-tag>
+                          <el-tag v-else type="warning" v-model="item.isBindUrl=1">选择的课程小节 即为卡片链接地址</el-tag>
                         </el-form-item>
                       </el-card>
                     </div>
@@ -402,14 +403,7 @@
                           <ImageUpload v-model="item.linkImageUrl" type="image" :num="1" :file-size="2" :width="150" :height="150" style="margin-top: 1%;" />
                         </el-form-item>
                         <el-form-item label="链接说明" label-width="100px">
-                          <el-tag type="info">飞书看课链接由服务端根据上方所选课程、课节自动生成</el-tag>
-                        </el-form-item>
-                        <el-form-item label="客户授权" label-width="100px">
-                          <el-radio-group v-model="item.feishuNeedAuth">
-                            <el-radio :label="1">需要授权</el-radio>
-                            <el-radio :label="0">免授权</el-radio>
-                          </el-radio-group>
-                          <div style="color: #909399; font-size: 12px; margin-top: 4px;">免授权:客户可直接看课</div>
+                          <el-tag type="info">飞书看课链接由服务端根据上方所选课程、课节自动生成(固定免授权)</el-tag>
                         </el-form-item>
                       </el-card>
                     </div>
@@ -1230,7 +1224,7 @@ export default {
         for (let i = 0; i < this.setting.length; i++) {
           //响应式直接给链接的标题/封面上值
           if (selectedCourse && this.msgForm.courseId != null) {
-            if ( this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 17 ){
+            if ( this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 17 || this.setting[i].contentType == 18 ){
               this.$set(this.setting[i], 'linkTitle', selectedCourse.dictLabel);
               this.$set(this.setting[i], 'linkImageUrl', selectedCourse.dictImgUrl);
             }
@@ -1257,7 +1251,7 @@ export default {
         for (let i = 0; i < this.setting.length; i++) {
           //响应式直接给链接的描述上值
           if (selectedVideo && this.msgForm.videoId != null) {
-            if (this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 17 ){
+            if (this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 17 || this.setting[i].contentType == 18 ){
               this.$set(this.setting[i], 'linkDescribe', selectedVideo.dictLabel);
 
               if (this.projectFrom == 'sxjz' && selectedVideo.dictImgUrl) {
@@ -1515,6 +1509,10 @@ export default {
       if (!item) {
         return;
       }
+      // 飞书链接(contentType=17)仅支持免授权
+      if (item.contentType == 17 || item.contentType === '17') {
+        item.feishuNeedAuth = 0;
+      }
       if (item.isRandomSend == 1 && Array.isArray(item.randomValueList)) {
         item.randomValueList = item.randomValueList
           .map(v => (v == null ? '' : v.trim()))
@@ -1529,6 +1527,12 @@ export default {
 
     handleContentTypeChange() {
 
+      // 飞书链接(contentType=17)仅支持免授权
+      for (let i = 0; i < this.setting.length; i++) {
+        if (this.setting[i].contentType == 17 || this.setting[i].contentType === '17') {
+          this.$set(this.setting[i], 'feishuNeedAuth', 0);
+        }
+      }
       //如果是链接的才上
       if (this.msgForm.courseId != null ) {
         const selectedCourse = this.courseList.find(course => parseInt(course.dictValue) === this.msgForm.courseId);
@@ -1536,7 +1540,7 @@ export default {
           //响应式直接给链接的标题/封面上值
           if (selectedCourse  && this.msgForm.courseId != null) {
 
-            if (this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 17){
+            if (this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 17 || this.setting[i].contentType == 18){
               this.$set(this.setting[i], 'linkTitle', selectedCourse.dictLabel);
               this.$set(this.setting[i], 'linkImageUrl', selectedCourse.dictImgUrl);
             }
@@ -1557,7 +1561,7 @@ export default {
           //响应式直接给链接的描述上值
           if (selectedVideo  && this.msgForm.videoId != null) {
 
-            if (this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 17){
+            if (this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 17 || this.setting[i].contentType == 18){
               this.$set(this.setting[i], 'linkDescribe', selectedVideo.dictLabel);
 
               if (this.msgForm.videoId != null) {
@@ -1774,13 +1778,13 @@ export default {
             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].contentType == 9 || this.setting[i].contentType == 17 ) && (this.setting[i].linkTitle == null || this.setting[i].linkTitle == "")) {
+            if ((this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 17 || this.setting[i].contentType == 18 ) && (this.setting[i].linkTitle == null || this.setting[i].linkTitle == "")) {
               return this.$message.error(this.isFeishuContentType(this.setting[i].contentType) ? "飞书消息标题不能为空" : "链接标题不能为空")
             }
-            if ((this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 17 ) && (this.setting[i].linkDescribe == null || this.setting[i].linkDescribe == "")) {
+            if ((this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 17 || this.setting[i].contentType == 18 ) && (this.setting[i].linkDescribe == null || this.setting[i].linkDescribe == "")) {
               return this.$message.error(this.isFeishuContentType(this.setting[i].contentType) ? "飞书描述不能为空" : "链接描述不能为空")
             }
-            if ((this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 17 ) && (this.setting[i].linkImageUrl == null || this.setting[i].linkImageUrl == "")) {
+            if ((this.setting[i].contentType == 3 || this.setting[i].contentType == 9 || this.setting[i].contentType == 17 || this.setting[i].contentType == 18 ) && (this.setting[i].linkImageUrl == null || this.setting[i].linkImageUrl == "")) {
               return this.$message.error(this.isFeishuContentType(this.setting[i].contentType) ? "飞书封面不能为空" : "链接图片不能为空")
             }
             if ((this.setting[i].contentType == 3 || this.setting[i].contentType == 9 )&& this.setting[i].type == 1 && (this.setting[i].linkUrl == null || this.setting[i].linkUrl == "")) {