Browse Source

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

ct 1 tuần trước cách đây
mục cha
commit
001f04490c

+ 22 - 0
.env.prod-jnsyj

@@ -0,0 +1,22 @@
+# 页面标题
+VUE_APP_TITLE =互联网医院管理系统
+# 公司名称
+VUE_APP_COMPANY_NAME =济南顺亿景互联网医院有限公司
+# ICP备案号
+VUE_APP_ICP_RECORD =蜀ICP备2024052643号
+# ICP网站访问地址
+VUE_APP_ICP_URL =https://beian.miit.gov.cn
+# 网站LOG
+VUE_APP_LOG_URL =@/assets/logo/jnmy.png
+
+# 生产环境配置
+ENV = 'production'
+
+# FS管理系统/开发环境
+VUE_APP_BASE_API = '/prod-api'
+
+#默认 1、会员 2、企微
+VUE_APP_COURSE_DEFAULT = 2
+
+# 路由懒加载
+VUE_CLI_BABEL_TRANSPILE_MODULES = true

+ 1 - 0
package.json

@@ -48,6 +48,7 @@
     "build:prod-hat": "vue-cli-service build --mode prod-hat",
     "build:prod-ddgy": "vue-cli-service build --mode prod-ddgy",
     "build:prod-czt": "vue-cli-service build --mode prod-czt",
+    "build:prod-jnsyj": "vue-cli-service build --mode prod-jnsyj",
     "preview": "node build/index.js --preview",
     "lint": "eslint --ext .js,.vue src",
     "test:unit": "jest --clearCache && vue-cli-service test:unit",

+ 9 - 0
src/api/course/userCourseVideo.js

@@ -39,6 +39,15 @@ export function addUserCourseVideo(data) {
   })
 }
 
+// 更新课程小节
+export function updateUserCourseVideoUpdate(data) {
+  return request({
+    url: '/course/userCourseVideo/update',
+    method: 'post',
+    data: data
+  })
+}
+
 // 修改课堂视频
 export function updateUserCourseVideo(data) {
   return request({

+ 18 - 0
src/api/wechat.js

@@ -0,0 +1,18 @@
+import request from '@/utils/request'
+
+// 获取绑定二维码
+export function getWechatBindQrcode() {
+  return request({
+    url: '/wechat/bind/qrcode',
+    method: 'get'
+  });
+}
+
+// 检测绑定状态
+export function checkWechatBindStatus(sceneId) {
+  return request({
+    url: '/wechat/bind/status',
+    method: 'get',
+    params: { sceneId }
+  });
+}

+ 18 - 2
src/views/company/companyUser/index.vue

@@ -1342,9 +1342,25 @@ export default {
     },
     /** 删除按钮操作 */
     handleDelete(row) {
+
       const userIds = row.userId || this.ids;
+
+      // 筛选出 userType 为 '00' 的 userId
+      const excludedUserIds = this.userList
+        .filter(user => user.userType == '00')
+        .map(user => user.userId);
+
+      // 从 userIds 中剔除这些 userId
+      const finalUserIds = userIds.filter(userId =>
+        !excludedUserIds.includes(userId)
+      );
+
+      if (finalUserIds.length === 0) {
+        return this.msgInfo("除管理员外无其他的账号,请重新选择");
+      }
+
       this.$confirm(
-        '是否确认删除员工编号为"' + userIds + '"的数据项?【注意:删除后绑定的企业微信相关信息可能会错乱!!】',
+        '是否确认删除员工编号为"' + finalUserIds + '"的数据项?【注意:删除后绑定的企业微信相关信息可能会错乱!!】',
         "警告",
         {
           confirmButtonText: "确定",
@@ -1353,7 +1369,7 @@ export default {
         }
       )
         .then(function() {
-          return delUser(userIds);
+          return delUser(finalUserIds);
         })
         .then(() => {
           this.getList();

+ 59 - 2
src/views/company/companyUser/profile/index.vue

@@ -36,6 +36,16 @@
                 <div class="pull-right">{{ user.createTime }}</div>
               </li>
             </ul>
+            <div class="text-center" style="margin-top: 20px;" v-if="needWxTemplateMsg">
+              <div v-if="user.wechatBindStatus">
+                <el-tag type="success">已绑定服务号通知</el-tag>
+              </div>
+              <div v-else>
+                <el-button type="primary" @click="openWechatBindDialog">
+                  订阅服务号通知
+                </el-button>
+              </div>
+            </div>
           </div>
         </el-card>
       </el-col>
@@ -55,6 +65,20 @@
         </el-card>
       </el-col>
     </el-row>
+    <el-dialog
+      title="订阅服务号通知"
+      :visible.sync="bindDialogVisible"
+      width="360px"
+      :close-on-click-modal="false"
+    >
+      <div class="text-center">
+        <img v-if="wechatQrcode" :src="wechatQrcode" style="width: 260px; height: 260px;" />
+        <p style="margin-top: 10px;">请使用微信扫码绑定服务号通知</p>
+      </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="bindDialogVisible = false">关闭</el-button>
+      </span>
+    </el-dialog>
   </div>
 </template>
 
@@ -63,7 +87,7 @@ import userAvatar from "./userAvatar";
 import userInfo from "./userInfo";
 import resetPwd from "./resetPwd";
 import { getUserProfile } from "@/api/company/companyUser";
-
+import { getWechatBindQrcode, checkWechatBindStatus } from "@/api/wechat";
 export default {
   name: "Profile",
   components: { userAvatar, userInfo, resetPwd },
@@ -72,10 +96,17 @@ export default {
       user: {},
       roleGroup: {},
       postGroup: {},
-      activeTab: "userinfo"
+      activeTab: "userinfo",
+      bindDialogVisible: false,
+      wechatQrcode: "",
+      wechatBindTimer: null,
+      needWxTemplateMsg: false,
     };
   },
   created() {
+    if (process.env.VUE_APP_COMPANY_NAME ==="河北红德堂医药连锁有限公司保定第五十七分公司"){
+      this.needWxTemplateMsg = true
+    }
     this.getUser();
   },
   methods: {
@@ -85,7 +116,33 @@ export default {
         this.roleGroup = response.roleGroup;
         this.postGroup = response.postGroup;
       });
+    },
+    openWechatBindDialog() {
+      getWechatBindQrcode().then(res => {
+        console.log(res)
+        this.wechatQrcode = res.data.qrcodeUrl;
+        this.bindDialogVisible = true;
+        this.startCheckWechatBind(res.data.sceneId);
+      });
+    },
+    startCheckWechatBind(sceneId) {
+      // 清除旧定时器
+      if (this.wechatBindTimer) clearInterval(this.wechatBindTimer);
+
+      this.wechatBindTimer = setInterval(() => {
+        checkWechatBindStatus(sceneId).then(res => {
+          if (res.data === true) {
+            this.$message.success("绑定成功!");
+            clearInterval(this.wechatBindTimer);
+            this.bindDialogVisible = false;
+            this.getUser(); // 刷新绑定状态
+          }
+        });
+      }, 2000);
     }
+  },
+  beforeDestroy() {
+    if (this.wechatBindTimer) clearInterval(this.wechatBindTimer);
   }
 };
 </script>

+ 181 - 22
src/views/components/course/userCourseCatalogDetails.vue

@@ -33,6 +33,9 @@
       <el-table-column label="上传时间" align="center" prop="createTime" />
       <el-table-column label="默认红包" align="center" prop="redPacketMoney" />
       <el-table-column label="公司红包" align="center" prop="companyRedPacketMoney" />
+      <el-table-column label="标签组名称" align="center" prop="tagGroupName" />
+      <el-table-column label="看课标签" align="center" prop="watchingTagName" />
+      <el-table-column label="完课标签" align="center" prop="watchedTagName" />
 
       <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
         <template slot-scope="scope">
@@ -49,12 +52,10 @@
             @click="updateMoney(scope.row)"
           >设置红包金额</el-button>
 
-<!--          <el-button-->
-<!--            size="mini"-->
-<!--            type="text"-->
-<!--            @click="openDialog(scope.row)"-->
-<!--            v-hasPermi="['course:courseLink:create']"-->
-<!--          >生成应急短链</el-button>-->
+          <el-button size="mini"
+                     type="text" @click="openTagDialog(scope.row)">
+            绑定看课标签
+          </el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -72,6 +73,7 @@
       :visible.sync="open" append-to-body>
       <userCourseVideoDetails  ref="userCourseVideoDetails" />
     </el-drawer>
+
     <el-dialog title="设置红包金额" :visible.sync="moneyOpen" width="600px" append-to-body>
       <el-form ref="form"  label-width="100px">
         <el-form-item label="红包金额" prop="corpId">
@@ -108,34 +110,107 @@
         <el-button type="primary" @click="confirm">确认</el-button>
       </div>
     </el-dialog>
-<!--    <el-dialog title="设置红包金额" :visible.sync="moneyOpen" width="600px" append-to-body>-->
-<!--      <el-form ref="form"  label-width="100px">-->
-<!--        <el-form-item label="红包金额" prop="corpId">-->
-<!--          <el-input-number v-model="redPacketMoneyForm.redPacketMoney" :min="0.1" :max="200" :step="0.1" ></el-input-number>-->
-<!--        </el-form-item>-->
-<!--      </el-form>-->
-<!--      <div slot="footer" class="dialog-footer">-->
-<!--        <el-button @click="cancel">取 消</el-button>-->
-<!--      </div>-->
-<!--    </el-dialog>-->
+
+    <!-- 弹框 -->
+    <el-dialog
+      title="绑定看课标签"
+      :visible.sync="tagDialogVisible"
+      width="500px"
+      @closed="resetDialog"
+      append-to-body
+    >
+      <el-form :model="tagDialog" label-width="120px">
+        <!-- 标签组选择 -->
+        <el-form-item label="标签组" required>
+          <el-select
+            v-model="tagDialog.groupId"
+            placeholder="请选择标签组"
+            @change="onGroupChange"
+            filterable
+          >
+            <el-option
+              v-for="group in tagGroups"
+              :key="group.groupId"
+              :label="group.name"
+              :value="group.groupId"
+            />
+          </el-select>
+        </el-form-item>
+        <!-- 看课标签选择 -->
+        <el-form-item label="看课标签" required>
+          <el-select
+            v-model="tagDialog.watchTagId"
+            placeholder="请选择看课标签"
+            :disabled="!tagDialog.groupId"
+            @change="handleWatchingChange"
+            filterable
+          >
+            <el-option
+              v-for="tag in tagsInGroup"
+              :key="tag.tagId"
+              :label="tag.name"
+              :value="tag.tagId"
+            />
+          </el-select>
+        </el-form-item>
+        <!-- 完课标签选择 -->
+        <el-form-item label="完课标签" required>
+          <el-select
+            v-model="tagDialog.finishTagId"
+            placeholder="请选择完课标签"
+            :disabled="!tagDialog.groupId"
+            @change="handleWatchedChange"
+            filterable>
+            <el-option
+              v-for="tag in tagsInGroup"
+              :key="tag.tagId"
+              :label="tag.name"
+              :value="tag.tagId"
+            />
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="cancelDialog">取消</el-button>
+        <el-button type="primary" @click="submitTagBinding">确定</el-button>
+      </span>
+    </el-dialog>
   </div>
 </template>
 
 <script>
-import { updatePacketMoney,getSort,getVideoListByCourseId,delUserCourseVideo,getUserCourseVideo,addUserCourseVideo,updateUserCourseVideo } from "@/api/course/userCourseVideo";
+import {getVideoListByCourseId, updatePacketMoney, updateUserCourseVideoUpdate} from "@/api/course/userCourseVideo";
 import userCourseVideoDetails from '../../components/course/userCourseVideoDetails.vue';
-import { createLinkUrl } from "@/api/course/sopCourseLink";
-import { userList } from "@/api/qw/user";
+import {createLinkUrl} from "@/api/course/sopCourseLink";
+import {listTagGroup} from "@/api/qw/tagGroup";
 
-import request from '@/utils/request'
-
-  export default {
+export default {
     name: "userCourseCatalog",
     components: {
       userCourseVideoDetails
     },
+    props: {
+      video: {
+        type: Object,
+        required: true,
+      },
+    },
     data() {
       return {
+        currentRow: null,
+        // 假设这里有当前课程小节的数据传入,里面含id等
+        tagDialogVisible: false,
+        tagGroups: [],
+        tagsInGroup: [],
+        tagDialog: {
+          videoId: null,
+          groupId: null,
+          watchTagId: null,
+          finishTagId: null,
+          tgId: null,
+          watchingTgId: null,
+          watchedTgId: null
+        },
         linkForm:{
           days:null,
           courseId:null,
@@ -218,6 +293,90 @@ import request from '@/utils/request'
       });
     },
     methods: {
+      handleWatchingChange(tagId){
+        this.tagDialog.watchingTgId = this.tagsInGroup.find(e => e.tagId === tagId)?.id;
+      },
+      handleWatchedChange(tagId){
+        this.tagDialog.watchedTgId = this.tagsInGroup.find(e => e.tagId === tagId)?.id;
+      },
+      openTagDialog(row) {
+        this.currentRow = row;
+        this.tagDialogVisible = true;
+        this.tagDialog.videoId = row.videoId;
+        this.tagDialog.groupId = this.currentRow.tagGroupId;
+        this.tagDialog.watchTagId = this.currentRow.watchingTagId;
+        this.tagDialog.finishTagId = this.currentRow.watchedTagId;
+
+
+        // 查询所有的标签组
+        listTagGroup({
+          pageNum: 1,
+          pageSize: 1000
+        }).then((res) => {
+          if(res.code === 200) {
+            this.tagGroups = res.rows;
+
+            let tagGroup = this.tagGroups.find(e=>e.groupId === this.currentRow.tagGroupId);
+            this.tagsInGroup = tagGroup.tag || [];
+          }
+        });
+      },
+      updateTagsInGroup(groupId) {
+        let tagGroup = this.tagGroups.find(e=> e.groupId === groupId);
+
+        this.tagsInGroup = tagGroup.tag || [];
+        // 切换组时清空标签选择
+        this.tagDialog.watchTagId = null;
+        this.tagDialog.finishTagId = null;
+        this.tagDialog.tgId = tagGroup.id;
+      },
+      onGroupChange(groupId) {
+        this.updateTagsInGroup(groupId);
+      },
+      cancelDialog() {
+        this.tagDialogVisible = false;
+        this.resetDialog();
+      },
+      resetDialog() {
+        this.tagDialog = {
+          videoId: null,
+          groupId: null,
+          watchTagId: null,
+          finishTagId: null,
+        };
+        this.tagGroups = [];
+        this.tagsInGroup = [];
+      },
+      submitTagBinding() {
+        // 使用表单校验
+        if(!this.tagDialog.groupId){
+          this.$message.warning("标签组必选!");
+          return;
+        }
+        if(!this.tagDialog.watchTagId){
+          this.$message.warning("看课标签必选!");
+          return;
+        }
+        if(!this.tagDialog.finishTagId){
+          this.$message.warning("完课标签必选!");
+          return;
+        }
+        this.currentRow.tagGroupId = this.tagDialog.groupId;
+        this.currentRow.watchingTagId = this.tagDialog.watchTagId;
+        this.currentRow.watchedTagId = this.tagDialog.finishTagId;
+
+        this.currentRow.watchingTgId = this.tagDialog.watchingTgId;
+        this.currentRow.watchedTgId = this.tagDialog.watchedTgId;
+        this.currentRow.tgId = this.tagDialog.tgId;
+
+        updateUserCourseVideoUpdate(this.currentRow).then(res=>{
+          this.$message.success("绑定成功");
+          this.resetDialog();
+          this.currentRow = null;
+          this.tagDialogVisible = false;
+          this.getList();
+        })
+      },
       // 打开弹框
       openDialog(row) {
         this.linkForm.courseId = row.courseId;

+ 6 - 5
src/views/course/courseWatchLog/deptWatchLog.vue

@@ -383,11 +383,12 @@
         </el-table-column>
         <el-table-column label="课程名称" align="center" prop="courseName"/>
         <el-table-column label="小节名称" align="center" prop="videoName"/>
-        <el-table-column label="是否全部正确" align="center" prop="isRight">
-          <template slot-scope="scope">
-            <dict-tag :options="sysCompanyOr" :value="scope.row.isRight"></dict-tag>
-          </template>
-        </el-table-column>
+        <el-table-column label="是否全部正确" align="center" prop="isRightText"/>
+<!--        <el-table-column label="是否全部正确" align="center" prop="isRight">-->
+<!--          <template slot-scope="scope">-->
+<!--            <dict-tag :options="sysCompanyOr" :value="scope.row.isRight"></dict-tag>-->
+<!--          </template>-->
+<!--        </el-table-column>-->
         <el-table-column label="销售名称" align="center" prop="companyUserName"/>
         <el-table-column label="企微员工名称" align="center" prop="qwUserName"/>
         <el-table-column label="公司名称" align="center" prop="companyName"/>

+ 0 - 7
src/views/crm/customer/full.vue

@@ -487,13 +487,6 @@ export default {
           this.citys=res.data;
         })
     },
-    handleShow(row){
-      var that=this;
-      that.show.open=true;
-      setTimeout(() => {
-          that.$refs.customerDetails.getDetails(row.customerId);
-      }, 200);
-    },
     /** 查询客户列表 */
     getList() {
       this.loading = true;

+ 92 - 67
src/views/qw/friendWelcome/indexNew.vue

@@ -484,7 +484,7 @@
         </div>
         <div v-if="welcomeItem.type==='miniprogram'">
 
-          <el-form-item label="选择课程">
+          <el-form-item label="选择课程" prop="miniprogramCourseId">
             <el-select  v-model="fileFrom.courseId" placeholder="请选择课程" style=" margin-right: 10px;" size="mini"  @change="courseChange(fileFrom,welcomeItem.index,welcomeItem.itemIndex)">
               <el-option
                 v-for="dict in courseList"
@@ -532,7 +532,7 @@
         </div>
       </el-form>
       <div slot="footer" class="dialog-footer" style="text-align: center">
-        <el-button type="primary" @click="confirmUpload">确定</el-button>
+        <el-button type="primary" @click="confirmUpload('fileFrom')">确定</el-button>
         <el-button type="primary" @click="cancelUpload">取消</el-button>
       </div>
     </el-dialog>
@@ -593,6 +593,24 @@ export default {
         linkTitle:[ { required: true, message: "图文标题不能为空", trigger: "submit" }],
         linkUrl:[ { required: true, message: "图文链接不能为空", trigger: "submit" }],
         miniprogramTitle:[ { required: true, message: "图文链接不能为空", trigger: "submit" }],
+        miniprogramCourseId:[
+          {
+            required: true,
+            validator: (rule, value, callback) => {
+              // 检查id是否为空
+              if (!this.fileFrom.courseId) {
+                return callback(new Error('请选择课程'));
+              }
+              // 检查ddId是否为空
+              if (!this.fileFrom.videoId) {
+                return callback(new Error('请选择小节'));
+              }
+              // 校验通过
+              callback();
+            },
+            trigger: 'change' // 下拉选择变化时触发校验
+          }
+        ]
       },
 
 
@@ -999,72 +1017,79 @@ export default {
 
     //提交附件
     confirmUpload(fileFrom) {
-      const { type, index, itemIndex } = this.welcomeItem;
-      let attachment = {};
-      if (type === 'image') {
-        attachment = {
-          msgtype: 'image',
-          image: {
-            pic_url: this.fileFrom.imagePicUrl
-          }
-        };
-      } else if (type === 'video') {
-        attachment = {
-          msgtype: 'video',
-          video: {
-            url:this.fileFrom.videoUrl,
-          }
-        };
-      } else if (type === 'link') {
-        attachment = {
-          msgtype: 'link',
-          link: {
-            title: this.fileFrom.linkTitle,
-            picurl: this.fileFrom.linkPicUrl,
-            desc: this.fileFrom.linkDesc,
-            url: this.fileFrom.linkUrl,
-            courseId:this.fileFrom.courseId,
-            videoId:this.fileFrom.videoId,
-            expiresDays:this.fileFrom.expiresDays,
-          }
-        };
-      }else if (type==='miniprogram'){
-        attachment = {
-          msgtype: 'miniprogram',
-          miniprogram: {
-            title: this.fileFrom.miniprogramTitle,
-            pic_media_id: "待查询",
-            appid: "wx73f85f8d62769119",
-            page: this.fileFrom.miniprogramPage,
-            courseId:this.fileFrom.courseId,
-            videoId:this.fileFrom.videoId,
-            expiresDays:this.fileFrom.expiresDays,
-          }
-        };
-      }
-
-      if (itemIndex === -1) {
-        // 默认欢迎语附件处理
-        if (index < this.form.attachments.length) {
-          // 存在附件则更新
-          this.form.attachments.splice(index, 1, attachment);
-        } else {
-          // 不存在附件则插入
-          this.form.attachments.push(attachment);
-        }
-
-      } else {
-        // 分时段欢迎语附件处理
-        if (index < this.form.daypartingItemlist[itemIndex].attachments.length) {
-          // 存在附件则更新
-          this.form.daypartingItemlist[itemIndex].attachments.splice(index, 1, attachment);
-        } else {
-          // 不存在附件则插入
-          this.form.daypartingItemlist[itemIndex].attachments.push(attachment);
-        }
-      }
+     this.$refs[fileFrom].validate((valid) => {
+          if (valid) {
+            const { type, index, itemIndex } = this.welcomeItem;
+            let attachment = {};
+            if (type === 'image') {
+              attachment = {
+                msgtype: 'image',
+                image: {
+                  pic_url: this.fileFrom.imagePicUrl
+                }
+              };
+            } else if (type === 'video') {
+              attachment = {
+                msgtype: 'video',
+                video: {
+                  url:this.fileFrom.videoUrl,
+                }
+              };
+            } else if (type === 'link') {
+              attachment = {
+                msgtype: 'link',
+                link: {
+                  title: this.fileFrom.linkTitle,
+                  picurl: this.fileFrom.linkPicUrl,
+                  desc: this.fileFrom.linkDesc,
+                  url: this.fileFrom.linkUrl,
+                  courseId:this.fileFrom.courseId,
+                  videoId:this.fileFrom.videoId,
+                  expiresDays:this.fileFrom.expiresDays,
+                }
+              };
+            }else if (type==='miniprogram'){
+              attachment = {
+                msgtype: 'miniprogram',
+                miniprogram: {
+                  title: this.fileFrom.miniprogramTitle,
+                  pic_media_id: "待查询",
+                  appid: "wx73f85f8d62769119",
+                  page: this.fileFrom.miniprogramPage,
+                  courseId:this.fileFrom.courseId,
+                  videoId:this.fileFrom.videoId,
+                  expiresDays:this.fileFrom.expiresDays,
+                }
+              };
+            }
 
-      this.resetFileFrom();
+            if (itemIndex === -1) {
+              // 默认欢迎语附件处理
+              if (index < this.form.attachments.length) {
+                // 存在附件则更新
+                this.form.attachments.splice(index, 1, attachment);
+              } else {
+                // 不存在附件则插入
+                this.form.attachments.push(attachment);
+              }
+
+            } else {
+              // 分时段欢迎语附件处理
+              if (index < this.form.daypartingItemlist[itemIndex].attachments.length) {
+                // 存在附件则更新
+                this.form.daypartingItemlist[itemIndex].attachments.splice(index, 1, attachment);
+              } else {
+                // 不存在附件则插入
+                this.form.daypartingItemlist[itemIndex].attachments.push(attachment);
+              }
+            }
+            this.resetFileFrom();
+          } else {
+            console.log('error submit!!');
+            return false;
+          }
+        });
+     
     },
 
     //取消附件

+ 92 - 66
src/views/qw/friendWelcome/myWelcome.vue

@@ -481,7 +481,7 @@
         </div>
         <div v-if="welcomeItem.type==='miniprogram'">
 
-          <el-form-item label="选择课程">
+          <el-form-item label="选择课程" prop="miniprogramCourseId">
             <el-select  v-model="fileFrom.courseId" placeholder="请选择课程" style=" margin-right: 10px;" size="mini"  @change="courseChange(fileFrom,welcomeItem.index,welcomeItem.itemIndex)">
               <el-option
                 v-for="dict in courseList"
@@ -529,7 +529,7 @@
         </div>
       </el-form>
       <div slot="footer" class="dialog-footer" style="text-align: center">
-        <el-button type="primary" @click="confirmUpload">确定</el-button>
+        <el-button type="primary" @click="confirmUpload('fileFrom')">确定</el-button>
         <el-button type="primary" @click="cancelUpload">取消</el-button>
       </div>
     </el-dialog>
@@ -591,6 +591,24 @@ export default {
         linkTitle:[ { required: true, message: "图文标题不能为空", trigger: "submit" }],
         linkUrl:[ { required: true, message: "图文链接不能为空", trigger: "submit" }],
         miniprogramTitle:[ { required: true, message: "图文链接不能为空", trigger: "submit" }],
+        miniprogramCourseId:[
+          {
+            required: true,
+            validator: (rule, value, callback) => {
+              // 检查id是否为空
+              if (!this.fileFrom.courseId) {
+                return callback(new Error('请选择课程'));
+              }
+              // 检查ddId是否为空
+              if (!this.fileFrom.videoId) {
+                return callback(new Error('请选择小节'));
+              }
+              // 校验通过
+              callback();
+            },
+            trigger: 'change' // 下拉选择变化时触发校验
+          }
+        ]
       },
 
 
@@ -999,73 +1017,81 @@ export default {
 
     //提交附件
     confirmUpload(fileFrom) {
+    this.$refs[fileFrom].validate((valid) => {
+      if (valid) {
+        const { type, index, itemIndex } = this.welcomeItem;
+            let attachment = {};
+            if (type === 'image') {
+              attachment = {
+                msgtype: 'image',
+                image: {
+                  pic_url: this.fileFrom.imagePicUrl
+                }
+              };
+            } else if (type === 'video') {
+              attachment = {
+                msgtype: 'video',
+                video: {
+                  url:this.fileFrom.videoUrl,
+                }
+              };
+            } else if (type === 'link') {
+              attachment = {
+                msgtype: 'link',
+                link: {
+                  title: this.fileFrom.linkTitle,
+                  picurl: this.fileFrom.linkPicUrl,
+                  desc: this.fileFrom.linkDesc,
+                  url: this.fileFrom.linkUrl,
+                  courseId:this.fileFrom.courseId,
+                  videoId:this.fileFrom.videoId,
+                  expiresDays:this.fileFrom.expiresDays,
+                }
+              };
+            }else if (type==='miniprogram'){
+              attachment = {
+                msgtype: 'miniprogram',
+                miniprogram: {
+                  title: this.fileFrom.miniprogramTitle,
+                  pic_media_id: "待查询",
+                  appid: "wx73f85f8d62769119",
+                  page: this.fileFrom.miniprogramPage,
+                  courseId:this.fileFrom.courseId,
+                  videoId:this.fileFrom.videoId,
+                  expiresDays:this.fileFrom.expiresDays,
+                }
+              };
+            }
 
-      const { type, index, itemIndex } = this.welcomeItem;
-      let attachment = {};
-      if (type === 'image') {
-        attachment = {
-          msgtype: 'image',
-          image: {
-            pic_url: this.fileFrom.imagePicUrl
-          }
-        };
-      } else if (type === 'video') {
-        attachment = {
-          msgtype: 'video',
-          video: {
-            url:this.fileFrom.videoUrl,
-          }
-        };
-      } else if (type === 'link') {
-        attachment = {
-          msgtype: 'link',
-          link: {
-            title: this.fileFrom.linkTitle,
-            picurl: this.fileFrom.linkPicUrl,
-            desc: this.fileFrom.linkDesc,
-            url: this.fileFrom.linkUrl,
-            courseId:this.fileFrom.courseId,
-            videoId:this.fileFrom.videoId,
-            expiresDays:this.fileFrom.expiresDays,
-          }
-        };
-      }else if (type==='miniprogram'){
-        attachment = {
-          msgtype: 'miniprogram',
-          miniprogram: {
-            title: this.fileFrom.miniprogramTitle,
-            pic_media_id: "待查询",
-            appid: "wx73f85f8d62769119",
-            page: this.fileFrom.miniprogramPage,
-            courseId:this.fileFrom.courseId,
-            videoId:this.fileFrom.videoId,
-            expiresDays:this.fileFrom.expiresDays,
-          }
-        };
-      }
-
-      if (itemIndex === -1) {
-        // 默认欢迎语附件处理
-        if (index < this.form.attachments.length) {
-          // 存在附件则更新
-          this.form.attachments.splice(index, 1, attachment);
-        } else {
-          // 不存在附件则插入
-          this.form.attachments.push(attachment);
-        }
+            if (itemIndex === -1) {
+              // 默认欢迎语附件处理
+              if (index < this.form.attachments.length) {
+                // 存在附件则更新
+                this.form.attachments.splice(index, 1, attachment);
+              } else {
+                // 不存在附件则插入
+                this.form.attachments.push(attachment);
+              }
+
+            } else {
+              // 分时段欢迎语附件处理
+              if (index < this.form.daypartingItemlist[itemIndex].attachments.length) {
+                // 存在附件则更新
+                this.form.daypartingItemlist[itemIndex].attachments.splice(index, 1, attachment);
+              } else {
+                // 不存在附件则插入
+                this.form.daypartingItemlist[itemIndex].attachments.push(attachment);
+              }
+            }
 
-      } else {
-        // 分时段欢迎语附件处理
-        if (index < this.form.daypartingItemlist[itemIndex].attachments.length) {
-          // 存在附件则更新
-          this.form.daypartingItemlist[itemIndex].attachments.splice(index, 1, attachment);
-        } else {
-          // 不存在附件则插入
-          this.form.daypartingItemlist[itemIndex].attachments.push(attachment);
+            this.resetFileFrom();
+        }else {
+          console.log('error submit!!');
+          return false;
         }
-      }
-
-      this.resetFileFrom();
+          
+      });
+      
     },
 
     //取消附件

+ 120 - 38
src/views/qw/sop/deptSop.vue

@@ -104,6 +104,18 @@
         >删除
         </el-button>
       </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleSopLogsDelete"
+          v-hasPermi="['qw:sopLogs:removeAll']"
+        >批量删除执行任务
+        </el-button>
+      </el-col>
       <el-col :span="1.5">
         <el-button
           type="success"
@@ -128,6 +140,18 @@
         >批量执行SOP
         </el-button>
       </el-col>
+      <el-col :span="1.5">
+        <el-tooltip class="item" effect="dark" content="此功能用于给 选中的 SOP任务营期 内【所有的】客户发送 消息【或者发送草稿-/-清楚草稿】" placement="top">
+          <el-button
+            type="warning"
+            icon="el-icon-s-promotion"
+            size="mini"
+            :disabled="multiple"
+            @click="handleCampSendMsg"
+            v-hasPermi="['qw:sopUserLogsInfo:msgSop']"
+          >SOP营期一键群发(或草稿)</el-button>
+        </el-tooltip>
+      </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
     <el-table v-loading="loading" border :data="sopList" @selection-change="handleSelectionChange">
@@ -313,6 +337,7 @@
       @pagination="getList"
     />
 
+    <send-msg-sop-open-tool ref="sendMsgSopOpenTool" ></send-msg-sop-open-tool>
     <!-- 添加或修改企微sop对话框 -->
     <el-dialog :title="title" :visible.sync="open" width="1000px" append-to-body>
       <el-form ref="form" :model="form" :rules="rules" label-width="100px">
@@ -734,7 +759,20 @@
                       </el-card>
                     </div>
                     <div v-if="item.contentType == 4">
-
+                      <el-card class="box-card">
+                        <el-form-item label="标题" prop="miniprogramTitle">
+                          <el-input v-model="item.miniprogramTitle" placeholder="请输入小程序消息标题,最长为64字"  />
+                        </el-form-item>
+                        <el-form-item label="封面" prop="miniprogramPicUrl">
+                          <ImageUpload v-model="item.miniprogramPicUrl"  type="image" :num="10" :width="150" :height="150" />
+                        </el-form-item>
+                        <el-form-item label="appid" prop="miniprogramAppid" v-show="false" >
+                          <el-input v-model="item.miniprogramAppid" disabled />
+                        </el-form-item>
+                        <el-form-item label="page路径" prop="miniprogramPage" v-show="false" label-width="100px" style="margin-left: -30px" >
+                          <el-input v-model="item.miniprogramPage" placeholder="小程序消息打开后的路径"  disabled />
+                        </el-form-item>
+                      </el-card>
                     </div>
                     <div v-if="item.contentType == 5 ">
 
@@ -853,7 +891,7 @@
 import {
   addSop,
   courseList,
-  delSop,
+  delSop, delSopLogs,
   exportSop,
   getSopVoiceList, listDeptSop,
   listSop,
@@ -873,10 +911,11 @@ import sopLogsDetails from '@/views/qw/sopLogs/sopLogsList.vue'
 import {listTag,} from "@/api/qw/tag";
 import {getMyQwCompanyList} from "@/api/qw/user";
 import {allList} from "@/api/qw/groupChat";
+import SendMsgSopOpenTool from '@/views/qw/sopUserLogsInfo/sendMsgSopOpenTool.vue'
 
 export default {
   name: "Sop",
-  components: {CustomerGroupDetails, qwUserList, ImageUpload, sopLogsDetails},
+  components: {CustomerGroupDetails, qwUserList, ImageUpload, sopLogsDetails, SendMsgSopOpenTool},
   data() {
     return {
       // 存储每一行的展开状态
@@ -1071,6 +1110,16 @@ export default {
     }
   },
   methods: {
+    /**
+     * SOP任务营期一键群发
+     */
+    handleCampSendMsg(){
+
+      setTimeout(() => {
+        this.$refs.sendMsgSopOpenTool.oneClickGroupSending(this.ids,2,this.queryParams.corpId);
+      }, 500);
+
+    },
     voice(id) {
       this.voiceForm.queryParams.id = id;
       getSopVoiceList(this.voiceForm.queryParams).then(res => {
@@ -1342,9 +1391,9 @@ export default {
       });
     },
 
-    addSetList() {
+    addSetList(){
       const newSetting = {
-        contentType: '1',
+        contentType:'1',
         value: '',
       };
       // 将新设置项添加到 content.setting 数组中
@@ -1355,7 +1404,7 @@ export default {
     handleContentTypeChange() {
 
       //如果是链接的才上
-      if (this.msgForm.courseId != null) {
+      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++) {
           //响应式直接给链接的标题/封面上值
@@ -1363,6 +1412,9 @@ export default {
             this.$set(this.setting[i], 'linkTitle', selectedCourse.dictLabel);
             this.$set(this.setting[i], 'linkImageUrl', selectedCourse.dictImgUrl);
           }
+          if (selectedCourse && this.setting[i].contentType == 4 && this.msgForm.courseId != null) {
+            this.$set(this.setting[i], 'miniprogramPicUrl', selectedCourse.dictImgUrl);
+          }
 
         }
 
@@ -1373,12 +1425,20 @@ export default {
 
         for (let i = 0; i < this.setting.length; i++) {
           //响应式直接给链接的描述上值
-          if (selectedVideo && this.setting[i].contentType == 3 && this.msgForm.videoId != null) {
-            this.$set(this.setting[i], 'linkDescribe', selectedVideo.dictLabel);
+          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.$set(this.setting[i], 'linkDescribe', selectedVideo.dictLabel);
+            }
+            if (this.setting[i].contentType == 4) {
+              this.$set(this.setting[i], 'miniprogramTitle', selectedVideo.dictLabel);
+            }
+
           }
         }
       }
 
+
     },
     videoIdChange() {
       if (this.msgForm.videoId != null) {
@@ -1387,8 +1447,16 @@ export default {
 
         for (let i = 0; i < this.setting.length; i++) {
           //响应式直接给链接的描述上值
-          if (selectedVideo && this.setting[i].contentType == 3 && this.msgForm.videoId != null) {
-            this.$set(this.setting[i], 'linkDescribe', selectedVideo.dictLabel);
+          if (selectedVideo && this.msgForm.videoId != null) {
+            if (this.setting[i].contentType == 3 || this.setting[i].contentType == 9) {
+              this.$set(this.setting[i], 'linkDescribe', selectedVideo.dictLabel);
+            }
+
+            if (this.setting[i].contentType == 4) {
+              this.$set(this.setting[i], 'miniprogramTitle', selectedVideo.dictLabel);
+            }
+
+
           }
         }
       }
@@ -1420,7 +1488,7 @@ export default {
         createBy: null,
         createTime: null,
         isAutoSop: null,
-        autoSopTime: { autoSopType: 2, autoStartTime: '00:00', autoEndTime: '24:00', autoSopSend: 2 },
+        autoSopTime: {autoSopType: 2, autoStartTime: '00:00', autoEndTime: '24:00', autoSopSend: 2},
       };
       this.resetForm("form");
       this.tags = null;
@@ -1469,7 +1537,7 @@ export default {
         tempId: row.tempId,
         filterMode: row.filterMode,
         corpId: row.corpId,
-        type:1,
+        type: 1,
       }
       // 使用 params 传递参数
       this.$router.push({
@@ -1496,7 +1564,7 @@ export default {
         this.msgError(res.msg);
       }
     },
-    beforeAvatarUploadFile(file) {
+    beforeAvatarUploadFile(file){
       const isLt1M = file.size / 1024 / 1024 < 10;
       if (!isLt1M) {
         this.$message.error('上传大小不能超过 10MB!');
@@ -1510,7 +1578,7 @@ export default {
     },
 
     handleAvatarSuccessVideo(res, file, item) {
-      if (res.code == 200) {
+      if(res.code==200){
         // 使用 $set 确保响应式更新
         this.$set(item, 'videoUrl', res.url);
       } else {
@@ -1518,7 +1586,7 @@ export default {
       }
     },
 
-    beforeAvatarUploadVideo(file) {
+    beforeAvatarUploadVideo(file){
       const isLt30M = file.size / 1024 / 1024 < 10;
       const isMP4 = file.type === 'video/mp4';
 
@@ -1535,7 +1603,7 @@ export default {
       return true;
     },
 
-    handleInputVideoText(value, content) {
+    handleInputVideoText(value,content){
       // 允许的字符:中文、英文(大小写)、数字和指定标点符号(,。!?)
       const regex = /^[\u4e00-\u9fa5,。!?,!?]+$/;
 
@@ -1626,7 +1694,7 @@ export default {
         confirmButtonText: "确定",
         cancelButtonText: "取消",
         type: "warning"
-      }).then(function() {
+      }).then(function () {
         return delSop(ids);
       }).then(() => {
         this.getList();
@@ -1634,6 +1702,17 @@ export default {
       }).catch(() => {
       });
     },
+    /** 删除按钮操作 */
+    handleSopLogsDelete() {
+      this.$confirm('是否确认删除企微sop编号为"' + this.ids + '"的所有发送任务(执行记录)数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => delSopLogs(this.ids)).then(() => {
+        this.msgSuccess("删除成功");
+      }).catch(() => {
+      });
+    },
     /**
      * 批量执行SOP任务
      */
@@ -1706,32 +1785,32 @@ export default {
     /**
      * 一键群发
      */
-    handleSendMsg(row) {
+    handleSendMsg(row){
       this.sendMsgOpen.open = true;
       this.sendMsgOpen.id = row.id;
       this.sendMsgOpen.row = row;
       this.msgForm.chatIds = row.chatId.split(",");
     },
-    submitMsgForm() {
+    submitMsgForm(){
       this.$refs["msgForm"].validate(valid => {
         if (valid) {
-          this.msgForm.setting = JSON.stringify(this.setting)
-          this.msgForm.sopId = this.sendMsgOpen.row.id;
-          this.msgForm.corpId = this.sendMsgOpen.row.corpId;
-          this.msgForm.filterMode = this.sendMsgOpen.row.filterMode;
+          this.msgForm.setting=JSON.stringify(this.setting)
+          this.msgForm.sopId=this.sendMsgOpen.row.id;
+          this.msgForm.corpId=this.sendMsgOpen.row.corpId;
+          this.msgForm.filterMode=this.sendMsgOpen.row.filterMode;
 
           if (this.setting.length <= 0) {
             return this.$message.error("请添加规则")
           }
-          if (this.msgForm.courseId === null || this.msgForm.courseId === '') {
+          if (this.msgForm.courseId===null || this.msgForm.courseId===''){
             return this.$message.error("课程不能为空")
           }
 
-          if (this.msgForm.videoId === null || this.msgForm.videoId === '') {
+          if (this.msgForm.videoId===null || this.msgForm.videoId===''){
             return this.$message.error("课节不能为空")
           }
 
-          if (this.msgForm.courseType === null || this.msgForm.courseType === '') {
+          if (this.msgForm.courseType===null || this.msgForm.courseType===''){
             return this.$message.error("消息类型不能为空")
           }
 
@@ -1777,19 +1856,19 @@ export default {
           sendMsgSop(this.msgForm).then(response => {
             this.msgSuccess("一键群发成功");
             loading.close();
-            this.setting = [];
+            this.setting=[];
             this.msgForm = {
-              videoId: null,
-              courseId: null,
-              courseType: null,
-              setting: null,
-              isRegister: 2,
-              sendType: 1,
-              filterMode: 2,
+              videoId:null,
+              courseId:null,
+              courseType:null,
+              setting:null,
+              isRegister:2,
+              sendType:1,
+              filterMode:2,
 
             }
             this.getList();
-          }).finally(() => {
+          }).finally(()=>{
             loading.close();
           });
 
@@ -1805,6 +1884,9 @@ export default {
             this.$set(this.setting[i], 'linkTitle', selectedCourse.dictLabel);
             this.$set(this.setting[i], 'linkImageUrl', selectedCourse.dictImgUrl);
           }
+          if (selectedCourse && this.setting[i].contentType == 4 && this.msgForm.courseId != null) {
+            this.$set(this.setting[i], 'miniprogramPicUrl', selectedCourse.dictImgUrl);
+          }
 
         }
 
@@ -1813,12 +1895,12 @@ export default {
         this.videoList = response.list;
       });
     },
-    cancelMsgForm() {
+    cancelMsgForm(){
       this.sendMsgOpen.open = false;
       this.resetSendMsgSop();
     },
-    delSetList(index) {
-      this.setting.splice(index, 1)
+    delSetList(index){
+      this.setting.splice(index,1)
     },
   }
 };

+ 107 - 25
src/views/qw/sop/mySop.vue

@@ -104,6 +104,18 @@
         >删除
         </el-button>
       </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleSopLogsDelete"
+          v-hasPermi="['qw:sopLogs:removeAll']"
+        >批量删除执行任务
+        </el-button>
+      </el-col>
       <el-col :span="1.5">
         <el-button
           type="success"
@@ -128,6 +140,18 @@
         >批量执行SOP
         </el-button>
       </el-col>
+      <el-col :span="1.5">
+        <el-tooltip class="item" effect="dark" content="此功能用于给 选中的 SOP任务营期 内【所有的】客户发送 消息【或者发送草稿-/-清楚草稿】" placement="top">
+          <el-button
+            type="warning"
+            icon="el-icon-s-promotion"
+            size="mini"
+            :disabled="multiple"
+            @click="handleCampSendMsg"
+            v-hasPermi="['qw:sopUserLogsInfo:msgSop']"
+          >SOP营期一键群发(或草稿)</el-button>
+        </el-tooltip>
+      </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
     <el-table v-loading="loading" border :data="sopList" @selection-change="handleSelectionChange">
@@ -313,6 +337,7 @@
       @pagination="getList"
     />
 
+    <send-msg-sop-open-tool ref="sendMsgSopOpenTool" ></send-msg-sop-open-tool>
     <!-- 添加或修改企微sop对话框 -->
     <el-dialog :title="title" :visible.sync="open" width="1000px" append-to-body>
       <el-form ref="form" :model="form" :rules="rules" label-width="100px">
@@ -734,7 +759,20 @@
                       </el-card>
                     </div>
                     <div v-if="item.contentType == 4">
-
+                      <el-card class="box-card">
+                        <el-form-item label="标题" prop="miniprogramTitle">
+                          <el-input v-model="item.miniprogramTitle" placeholder="请输入小程序消息标题,最长为64字"  />
+                        </el-form-item>
+                        <el-form-item label="封面" prop="miniprogramPicUrl">
+                          <ImageUpload v-model="item.miniprogramPicUrl"  type="image" :num="10" :width="150" :height="150" />
+                        </el-form-item>
+                        <el-form-item label="appid" prop="miniprogramAppid" v-show="false" >
+                          <el-input v-model="item.miniprogramAppid" disabled />
+                        </el-form-item>
+                        <el-form-item label="page路径" prop="miniprogramPage" v-show="false" label-width="100px" style="margin-left: -30px" >
+                          <el-input v-model="item.miniprogramPage" placeholder="小程序消息打开后的路径"  disabled />
+                        </el-form-item>
+                      </el-card>
                     </div>
                     <div v-if="item.contentType == 5 ">
 
@@ -853,7 +891,7 @@
 import {
   addSop,
   courseList,
-  delSop,
+  delSop, delSopLogs,
   exportSop,
   getSopVoiceList, listMySop,
   listSop,
@@ -873,10 +911,11 @@ import sopLogsDetails from '@/views/qw/sopLogs/sopLogsList.vue'
 import {listTag,} from "@/api/qw/tag";
 import {getMyQwCompanyList} from "@/api/qw/user";
 import {allList} from "@/api/qw/groupChat";
+import SendMsgSopOpenTool from '@/views/qw/sopUserLogsInfo/sendMsgSopOpenTool.vue'
 
 export default {
   name: "Sop",
-  components: {CustomerGroupDetails, qwUserList, ImageUpload, sopLogsDetails},
+  components: {CustomerGroupDetails, qwUserList, ImageUpload, sopLogsDetails, SendMsgSopOpenTool},
   data() {
     return {
       // 存储每一行的展开状态
@@ -1071,6 +1110,16 @@ export default {
     }
   },
   methods: {
+    /**
+     * SOP任务营期一键群发
+     */
+    handleCampSendMsg(){
+
+      setTimeout(() => {
+        this.$refs.sendMsgSopOpenTool.oneClickGroupSending(this.ids,2,this.queryParams.corpId);
+      }, 500);
+
+    },
     voice(id) {
       this.voiceForm.queryParams.id = id;
       getSopVoiceList(this.voiceForm.queryParams).then(res => {
@@ -1342,9 +1391,9 @@ export default {
       });
     },
 
-    addSetList() {
+    addSetList(){
       const newSetting = {
-        contentType: '1',
+        contentType:'1',
         value: '',
       };
       // 将新设置项添加到 content.setting 数组中
@@ -1355,7 +1404,7 @@ export default {
     handleContentTypeChange() {
 
       //如果是链接的才上
-      if (this.msgForm.courseId != null) {
+      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++) {
           //响应式直接给链接的标题/封面上值
@@ -1363,6 +1412,9 @@ export default {
             this.$set(this.setting[i], 'linkTitle', selectedCourse.dictLabel);
             this.$set(this.setting[i], 'linkImageUrl', selectedCourse.dictImgUrl);
           }
+          if (selectedCourse && this.setting[i].contentType == 4 && this.msgForm.courseId != null) {
+            this.$set(this.setting[i], 'miniprogramPicUrl', selectedCourse.dictImgUrl);
+          }
 
         }
 
@@ -1373,12 +1425,20 @@ export default {
 
         for (let i = 0; i < this.setting.length; i++) {
           //响应式直接给链接的描述上值
-          if (selectedVideo && this.setting[i].contentType == 3 && this.msgForm.videoId != null) {
-            this.$set(this.setting[i], 'linkDescribe', selectedVideo.dictLabel);
+          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.$set(this.setting[i], 'linkDescribe', selectedVideo.dictLabel);
+            }
+            if (this.setting[i].contentType == 4) {
+              this.$set(this.setting[i], 'miniprogramTitle', selectedVideo.dictLabel);
+            }
+
           }
         }
       }
 
+
     },
     videoIdChange() {
       if (this.msgForm.videoId != null) {
@@ -1387,8 +1447,16 @@ export default {
 
         for (let i = 0; i < this.setting.length; i++) {
           //响应式直接给链接的描述上值
-          if (selectedVideo && this.setting[i].contentType == 3 && this.msgForm.videoId != null) {
-            this.$set(this.setting[i], 'linkDescribe', selectedVideo.dictLabel);
+          if (selectedVideo && this.msgForm.videoId != null) {
+            if (this.setting[i].contentType == 3 || this.setting[i].contentType == 9) {
+              this.$set(this.setting[i], 'linkDescribe', selectedVideo.dictLabel);
+            }
+
+            if (this.setting[i].contentType == 4) {
+              this.$set(this.setting[i], 'miniprogramTitle', selectedVideo.dictLabel);
+            }
+
+
           }
         }
       }
@@ -1420,7 +1488,7 @@ export default {
         createBy: null,
         createTime: null,
         isAutoSop: null,
-        autoSopTime: { autoSopType: 2, autoStartTime: '00:00', autoEndTime: '24:00', autoSopSend: 2 },
+        autoSopTime: {autoSopType: 2, autoStartTime: '00:00', autoEndTime: '24:00', autoSopSend: 2},
       };
       this.resetForm("form");
       this.tags = null;
@@ -1496,7 +1564,7 @@ export default {
         this.msgError(res.msg);
       }
     },
-    beforeAvatarUploadFile(file) {
+    beforeAvatarUploadFile(file){
       const isLt1M = file.size / 1024 / 1024 < 10;
       if (!isLt1M) {
         this.$message.error('上传大小不能超过 10MB!');
@@ -1510,7 +1578,7 @@ export default {
     },
 
     handleAvatarSuccessVideo(res, file, item) {
-      if (res.code == 200) {
+      if(res.code==200){
         // 使用 $set 确保响应式更新
         this.$set(item, 'videoUrl', res.url);
       } else {
@@ -1518,7 +1586,7 @@ export default {
       }
     },
 
-    beforeAvatarUploadVideo(file) {
+    beforeAvatarUploadVideo(file){
       const isLt30M = file.size / 1024 / 1024 < 10;
       const isMP4 = file.type === 'video/mp4';
 
@@ -1535,7 +1603,7 @@ export default {
       return true;
     },
 
-    handleInputVideoText(value, content) {
+    handleInputVideoText(value,content){
       // 允许的字符:中文、英文(大小写)、数字和指定标点符号(,。!?)
       const regex = /^[\u4e00-\u9fa5,。!?,!?]+$/;
 
@@ -1626,7 +1694,7 @@ export default {
         confirmButtonText: "确定",
         cancelButtonText: "取消",
         type: "warning"
-      }).then(function() {
+      }).then(function () {
         return delSop(ids);
       }).then(() => {
         this.getList();
@@ -1634,6 +1702,17 @@ export default {
       }).catch(() => {
       });
     },
+    /** 删除按钮操作 */
+    handleSopLogsDelete() {
+      this.$confirm('是否确认删除企微sop编号为"' + this.ids + '"的所有发送任务(执行记录)数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => delSopLogs(this.ids)).then(() => {
+        this.msgSuccess("删除成功");
+      }).catch(() => {
+      });
+    },
     /**
      * 批量执行SOP任务
      */
@@ -1706,32 +1785,32 @@ export default {
     /**
      * 一键群发
      */
-    handleSendMsg(row) {
+    handleSendMsg(row){
       this.sendMsgOpen.open = true;
       this.sendMsgOpen.id = row.id;
       this.sendMsgOpen.row = row;
       this.msgForm.chatIds = row.chatId.split(",");
     },
-    submitMsgForm() {
+    submitMsgForm(){
       this.$refs["msgForm"].validate(valid => {
         if (valid) {
-          this.msgForm.setting = JSON.stringify(this.setting)
-          this.msgForm.sopId = this.sendMsgOpen.row.id;
-          this.msgForm.corpId = this.sendMsgOpen.row.corpId;
-          this.msgForm.filterMode = this.sendMsgOpen.row.filterMode;
+          this.msgForm.setting=JSON.stringify(this.setting)
+          this.msgForm.sopId=this.sendMsgOpen.row.id;
+          this.msgForm.corpId=this.sendMsgOpen.row.corpId;
+          this.msgForm.filterMode=this.sendMsgOpen.row.filterMode;
 
           if (this.setting.length <= 0) {
             return this.$message.error("请添加规则")
           }
-          if (this.msgForm.courseId === null || this.msgForm.courseId === '') {
+          if (this.msgForm.courseId===null || this.msgForm.courseId===''){
             return this.$message.error("课程不能为空")
           }
 
-          if (this.msgForm.videoId === null || this.msgForm.videoId === '') {
+          if (this.msgForm.videoId===null || this.msgForm.videoId===''){
             return this.$message.error("课节不能为空")
           }
 
-          if (this.msgForm.courseType === null || this.msgForm.courseType === '') {
+          if (this.msgForm.courseType===null || this.msgForm.courseType===''){
             return this.$message.error("消息类型不能为空")
           }
 
@@ -1805,6 +1884,9 @@ export default {
             this.$set(this.setting[i], 'linkTitle', selectedCourse.dictLabel);
             this.$set(this.setting[i], 'linkImageUrl', selectedCourse.dictImgUrl);
           }
+          if (selectedCourse && this.setting[i].contentType == 4 && this.msgForm.courseId != null) {
+            this.$set(this.setting[i], 'miniprogramPicUrl', selectedCourse.dictImgUrl);
+          }
 
         }
 

+ 41 - 1
src/views/qw/user/cuDeptIdIndex.vue

@@ -12,6 +12,9 @@
           />
         </el-select>
       </el-form-item>
+      <el-form-item label="企微部门">
+        <treeselect :clearable="false"  v-model="queryParams.deptId"  :options="deptOptions" :show-count="true" placeholder="请选择归属部门"/>
+      </el-form-item>
       <el-form-item label="企微账号" prop="qwUserId">
         <el-input
           v-model="queryParams.qwUserId"
@@ -77,6 +80,7 @@
       <el-table-column label="企微账号" align="center" prop="qwUserId" />
       <el-table-column label="企微昵称" align="center" prop="qwUserName" />
       <el-table-column label="员工称呼" align="center" prop="welcomeText" />
+      <el-table-column label="部门" align="center" prop="departmentName" />
       <el-table-column label="员工状态" align="center" prop="isDel">
         <template slot-scope="scope">
           <el-tag v-if="scope.row.isDel == 0" type="success">正常</el-tag>
@@ -460,12 +464,16 @@ import {
   qwBindCloudHost, qwUnbindCloudHost, handleAuthAppKey, handleInputAuthAppKey, selectCloudAP, myDepartListUser
 } from '../../../api/qw/user'
 import fastGptRole from "@/views/fastGpt/fastGptRole/fastGptRole";
+import { treeselect } from "@/api/qw/qwDept";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
 
 export default {
   name: "cuDeptIdIndex",
-  components: { fastGptRole},
+  components: { Treeselect, fastGptRole},
   data() {
     return {
+      deptOptions:[], // 企微部门
       updateIp:{
         open:false,
         title: "修改云主机IP"
@@ -567,6 +575,7 @@ export default {
         qwUserId: null,
         corpId: null,
         qwUserName: null,
+        deptId:null,
       },
 	  qwUserId:null,
       companyUserList:[],
@@ -595,6 +604,10 @@ export default {
       this.myQwCompanyList = response.data;
       if(this.myQwCompanyList!=null){
         this.queryParams.corpId=this.myQwCompanyList[0].dictValue;
+        // 查询部门下拉树结构
+        if(this.queryParams.corpId){
+          this.getTreeselect()
+        }
         this.getList();
       }
     });
@@ -612,6 +625,25 @@ export default {
     },
   },
   methods: {
+    /** 查询部门下拉树结构 */
+    getTreeselect() {
+      var that=this;
+      let query = {
+        corpId: this.queryParams.corpId
+      }
+      // 企微主体不能为空
+      if(!query.corpId){
+        this.$message.error("请选择企微主体");
+        return;
+      }
+      treeselect(query).then((response) => {
+        this.deptOptions = response.data;
+        console.log(this.deptOptions)
+        if(response.data!=null&&response.data.length>0){
+          this.queryParams.deptId=response.data[0].id;
+        }
+      });
+    },
     getList() {
       this.loading = true;
       myDepartListUser(this.queryParams).then(response => {
@@ -989,6 +1021,7 @@ export default {
         qwUserId: null,
         corpId: null,
         qwUserName: null,
+
       };
       this.resetForm("form");
 
@@ -1040,6 +1073,7 @@ export default {
     resetQuery() {
       this.resetForm("queryForm");
       this.queryParams.corpId=this.myQwCompanyList[0].dictValue;
+      this.queryParams.deptId = this.deptOptions[0] && this.deptOptions[0].id;
       this.handleQuery();
     },
     // 多选框选中数据
@@ -1120,4 +1154,10 @@ export default {
   width: 80%;
 }
 
+.vue-treeselect{
+  width: 217px;
+  height: 36px;
+}
+
+
 </style>

+ 4 - 1
src/views/qw/user/index.vue

@@ -711,7 +711,9 @@ export default {
       if(this.myQwCompanyList && this.myQwCompanyList.length>0){
         this.queryParams.corpId=this.myQwCompanyList[0].dictValue;
         // 查询部门下拉树结构
-        this.getTreeselect()
+        if(this.queryParams.corpId){
+          this.getTreeselect()
+        }
         this.getList();
       }
     });
@@ -1197,6 +1199,7 @@ export default {
     resetQuery() {
       this.resetForm("queryForm");
       this.queryParams.corpId = this.myQwCompanyList[0].dictValue;
+      this.queryParams.deptId = this.deptOptions[0] && this.deptOptions[0].id;
       this.handleQuery();
     },
     // 多选框选中数据