浏览代码

Merge branch 'bjcz_his_scrm' of http://1.14.104.71:10880/root/ylrz_his_scrm_companyUI into bjcz_his_scrm

xw 1 周之前
父节点
当前提交
2392d46e12

+ 8 - 0
src/api/qw/sop.js

@@ -99,6 +99,14 @@ export function updateSopStatus(data) {
     data: data
   })
 }
+export function handleSkipSop(date) {
+  return request({
+    url: '/qw/sop/handleSkipSop',
+    method: 'post',
+   data: date
+  })
+}
+
 // 删除企微sop
 export function delSop(id) {
   return request({

+ 28 - 5
src/views/course/courseWatchLog/index.vue

@@ -33,7 +33,7 @@
       <el-form-item label="客户id" prop="userId" >
         <el-input
           v-model="queryParams.userId"
-          placeholder="请输入会员昵称"
+          placeholder="请输入会员id"
           clearable
           size="small"
           @keyup.enter.native="handleQuery"
@@ -714,7 +714,7 @@ export default {
       qecCalendarKey: 0,
       periodTimeKey: 0,
 
-      createTimeText: '',
+      createTimeText: [],
       scheduleTimeText: '',  // 新增
       updateTimeText: '',    // 新增
       qecCreateTimeText: '', // 新增
@@ -908,6 +908,7 @@ export default {
   created() {
     // 初始化时根据默认的sendType加载课程列表
     this.loadCourseList();
+     this.initDefaultCreateTime();
     this.getList();
     this.getDicts("sys_course_watch_log_type_new").then(response => {
       this.logTypeOptions = response.data;
@@ -921,6 +922,26 @@ export default {
     this.getCompanyUserListLikeName(true);
   },
   methods: {
+
+    initDefaultCreateTime() {
+      // 获取当前日期
+      const today = new Date();
+      // 格式化日期为 yyyy-MM-dd
+      const year = today.getFullYear();
+      const month = String(today.getMonth() + 1).padStart(2, '0');
+      const day = String(today.getDate()).padStart(2, '0');
+      const todayStr = `${year}-${month}-${day}`;
+
+      // 设置默认时间范围为当天 00:00:00 到 23:59:59
+      this.createTimeText = [
+        `${todayStr} 00:00:00`,
+        `${todayStr} 23:59:59`
+      ];
+
+      // 同步更新查询参数
+      this.queryParams.sTime = `${todayStr} 00:00:00`;
+      this.queryParams.eTime = `${todayStr} 23:59:59`;
+    },
     /**
      * 处理所属销售下拉框显示状态变化
      */
@@ -1208,13 +1229,12 @@ export default {
       }
     },
     // 创建时间
-    createChange(createTime) {
+     createChange(createTime) {
       if (createTime && createTime.length >= 2) {
-        // this.createTimeText = this.formatDateRange(createTime);
         this.queryParams.sTime = this.formatDate(createTime[0]) || null;
         this.queryParams.eTime = this.formatDate(createTime[1]) || null;
       } else {
-        this.createTimeText = '';
+        this.createTimeText = [];
         this.queryParams.sTime = null;
         this.queryParams.eTime = null;
       }
@@ -1427,6 +1447,9 @@ export default {
       // 统一重置日历组件
       this.resetCalendars();
 
+      // ========== 重置后恢复创建时间默认值 ==========
+      this.initDefaultCreateTime();
+
       this.handleQuery();
     },
     // 多选框选中数据

+ 245 - 1
src/views/qw/sop/sop.vue

@@ -326,6 +326,13 @@
             v-hasPermi="['qw:sop:remove']"
           >删除
           </el-button>
+          <el-button
+            size="mini"
+            type="text"
+            @click="handleSkipSop(scope.row,1)"
+            v-hasPermi="['qw:sop:edit']"
+          >跳过sop
+          </el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -469,6 +476,67 @@
       <qwUserList ref="QwUserList" @selectUserList="selectUserList"></qwUserList>
     </el-dialog>
 
+    <el-dialog
+  :title="skipSopDialog.title"
+  :visible.sync="skipSopDialog.open"
+  width="600px"
+  append-to-body
+>
+  <el-form
+    ref="skipSopForm"
+    :model="skipSopForm"
+    :rules="skipSopRules"
+    label-width="80px"
+  >
+    <div v-for="(item, index) in skipSopForm.conditions" :key="index" class="condition-item" style="margin-bottom: 15px; padding: 10px; border: 1px solid #eee; border-radius: 4px;">
+      <el-form-item :label="`第几天`" :prop="`conditions[${index}].dayNum`">
+        <el-input
+          v-model.number="item.dayNum"
+          placeholder="输入天数(大于0)"
+          style="width: 120px;"
+        />
+      </el-form-item>
+      <el-form-item :label="`开始时间`" :prop="`conditions[${index}].startDate`">
+        <el-time-select
+          v-model="item.startDate"
+          placeholder="选择开始时间"
+          :picker-options="{ start: '00:00', step: '00:15', end: '23:45' }"
+          style="width: 120px;"
+        />
+      </el-form-item>
+      <el-form-item :label="`结束时间`" :prop="`conditions[${index}].endDate`">
+        <el-time-select
+          v-model="item.endDate"
+          placeholder="选择结束时间"
+          :picker-options="{ start: '00:00', step: '00:15', end: '23:45' }"
+          style="width: 120px;"
+        />
+      </el-form-item>
+      <el-button
+        type="text"
+        icon="el-icon-delete"
+        style="color: #ff4949;"
+        @click="removeCondition(index)"
+      >删除</el-button>
+    </div>
+    <el-button
+      type="text"
+      icon="el-icon-plus"
+      style="color: #409eff;"
+      @click="addCondition"
+      v-if="skipSopForm.conditions.length < 10"
+    >添加条件</el-button>
+    <div style="color: #999; font-size: 12px; margin-top: 10px;">
+      <p>提示:</p>
+      <p>2. 时间可填/不填(不填表示跳过整天)</p>
+    </div>
+  </el-form>
+  <div slot="footer" class="dialog-footer">
+    <el-button @click="cancelSkipSop">取消</el-button>
+    <el-button type="primary" @click="submitSkipSop">确认跳过</el-button>
+  </div>
+</el-dialog>
+
     <!-- 单独的修改时间   -->
     <el-dialog :title="outTimeOpen.title" :visible.sync="outTimeOpen.open" width="800px">
       <el-card class="box-card">
@@ -900,7 +968,9 @@ import {
   updateSop,
   updateSopStatus,
   updateStatus,
-  videoList
+  videoList,
+  handleSkipSop,
+  getSop
 } from '@/api/qw/sop'
 import {sendMsgSop} from "@/api/qw/sopUserLogsInfo";
 import {listSopTemp} from "@/api/qw/sopTemp";
@@ -919,6 +989,36 @@ export default {
   components: {CustomerGroupDetails, qwUserList, ImageUpload, sopLogsDetails, SendMsgSopOpenTool},
   data() {
     return {
+
+      skipSopDialog: {
+      open: false,
+      title: "跳过SOP操作",
+      rowId: null, // 目标SOP的ID
+    },
+          // 跳过SOP表单
+    skipSopForm: {
+      conditions: [
+        {
+          dayNum: 1, // 第几天
+          startDate: "", // 开始时间
+          endDate: "", // 结束时间
+        },
+      ],
+    },
+    // 跳过SOP表单验证规则
+    skipSopRules: {
+      dayNum: [
+        { required: true, message: "天数不能为空", trigger: "blur" },
+        { type: "number", min: 1, message: "天数必须大于0", trigger: "blur" },
+      ],
+      startDate: [
+        { pattern: /^([01]\d|2[0-3]):[0-5]\d$/, message: "时间格式为HH:mm", trigger: "blur" },
+      ],
+      endDate: [
+        { pattern: /^([01]\d|2[0-3]):[0-5]\d$/, message: "时间格式为HH:mm", trigger: "blur" },
+      ],
+    },
+
       // 存储每一行的展开状态
       expandedRows: {},
       //模板查询
@@ -1111,7 +1211,151 @@ export default {
     }
   },
   methods: {
+  handleSkipSop(row) {
+      const ids = row.id || this.ids;
+      // 获取原始数据详情
+
+      getSop(ids).then(response => {
+        // 解析skipSopJson字段中的数据
+        if (response.data && response.data.skipSopJson) {
+          try {
+            const skipData = JSON.parse(response.data.skipSopJson);
+             if (Array.isArray(skipData)) {
+            // 如果是数组格式,直接赋值
+            this.skipSopForm.conditions = skipData.length > 0 ? skipData : [
+              { dayNum: 1, startDate: "", endDate: "" }
+            ];
+          } else if (skipData.conditions && Array.isArray(skipData.conditions)) {
+            // 如果是对象格式且包含conditions数组
+            this.skipSopForm.conditions = skipData.conditions.length > 0 ? skipData.conditions : [
+              { dayNum: 1, startDate: "", endDate: "" }
+            ];
+          } else {
+            // 如果是其他格式,尝试直接使用skipData(假设它本身就是条件数组)
+            this.skipSopForm.conditions = Array.isArray(skipData) ? skipData : [
+              { dayNum: 1, startDate: "", endDate: "" }
+            ];
+          }
+          } catch (e) {
+            console.error('解析skipSopJson失败', e);
+            // 如果解析失败,使用默认值
+            this.skipSopForm.conditions = [
+              { dayNum: 1, startDate: "", endDate: "" }
+            ];
+          }
+        } else {
+          // 如果没有skipSopJson数据,使用默认值
+          this.skipSopForm.conditions = [
+            { dayNum: 1, startDate: "", endDate: "" }
+          ];
+        }
 
+        // 设置弹窗数据
+        this.skipSopDialog.rowId = ids;
+        this.skipSopDialog.open = true;
+      }).catch(error => {
+        console.error('获取SOP详情失败', error);
+        // 出错时也打开弹窗,使用默认数据
+        this.skipSopForm.conditions = [
+          { dayNum: 1, startDate: "", endDate: "" }
+        ];
+        this.skipSopDialog.rowId = ids;
+        this.skipSopDialog.open = true;
+      });
+    },
+  // 添加条件
+  addCondition() {
+    if (this.skipSopForm.conditions.length >= 10) {
+      this.$message.warning("最多只能添加10个条件");
+      return;
+    }
+    this.skipSopForm.conditions.push({
+      dayNum: this.skipSopForm.conditions.length + 1,
+      startDate: "",
+      endDate: "",
+    });
+  },
+  // 删除条件
+  removeCondition(index) {
+    // if (this.skipSopForm.conditions.length <= 1) {
+    //   this.$message.warning("至少需要保留一个条件");
+    //   return;
+    // }
+    this.skipSopForm.conditions.splice(index, 1);
+    this.validateDuplicateDays(); // 删后验证天数重复
+  },
+  // 验证天数是否重复
+  validateDuplicateDays() {
+    const days = this.skipSopForm.conditions.map((c) => c.dayNum);
+    const uniqueDays = [...new Set(days)];
+    if (days.length !== uniqueDays.length) {
+      // this.$message.warning("不能有重复的天数");
+      // return false;
+    }
+    return true;
+  },
+  // 提交跳过SOP
+  submitSkipSop() {
+    this.$refs.skipSopForm.validate((valid) => {
+      if (!valid) return;
+
+      // 验证天数不重复
+      if (!this.validateDuplicateDays()) return;
+
+      // 验证时间逻辑
+      let timeValid = true;
+      this.skipSopForm.conditions.forEach((item, idx) => {
+        if (item.startDate && item.endDate) {
+          // 比较时间(HH:mm格式)
+          const start = item.startDate.replace(":", "");
+          const end = item.endDate.replace(":", "");
+          if (start >= end) {
+            this.$message.warning(`第${idx + 1}个条件:结束时间必须晚于开始时间`);
+            timeValid = false;
+          }
+        } else if ((item.startDate && !item.endDate) || (!item.startDate && item.endDate)) {
+          this.$message.warning(`第${idx + 1}个条件:开始/结束时间需同时填写或同时为空`);
+          timeValid = false;
+        }
+      });
+      if (!timeValid) return;
+
+      // 构造请求参数(根据后端接口调整)
+      const params = {
+        sopId: this.skipSopDialog.rowId,
+        paramList: this.skipSopForm.conditions.map((item) => ({
+          dayNum: item.dayNum,
+          startDate: item.startDate || null,
+          endDate: item.endDate || null,
+        })),
+      };
+
+      // 调用后端接口(需替换为实际接口)
+      // 示例:apiSkipSop(params).then(...)
+      this.$confirm("确定要跳过这些SOP任务吗?", "确认", {
+        type: "warning",
+      }).then(() => {
+        // 这里替换为实际的接口请求 handleSkipSop
+        setTimeout(() => {
+          handleSkipSop(params).then(response => {
+          }).catch(error => {
+            console.error('跳过SOP操作失败:', error);
+            this.$message.error('跳过SOP操作失败');
+          });
+          this.$message.success("跳过SOP操作成功");
+          this.skipSopDialog.open = false;
+          this.getList(); // 刷新列表
+        }, 500);
+      });
+    });
+  },
+  // 取消跳过SOP
+  cancelSkipSop() {
+    this.skipSopDialog.open = false;
+    if (this.$refs.skipSopForm) {
+      this.$refs.skipSopForm.resetFields();
+    }
+  },
     /**
      * SOP任务营期一键群发
      */

+ 5 - 5
src/views/qw/sopTemp/updateSopTemp.vue

@@ -621,7 +621,7 @@
                                           size="mini"
                                           circle
                                           @click="moveSetListUp(index,contentIndex,setIndex)"
-                                          v-if="setIndex > 0 && (formType != 3 && form.templateType != 1) && roles.includes('edit_sop_temp_content')"
+                                          v-if="setIndex > 0 && (formType != 3 && form.templateType != 1) "
                                           title="上移">
                                         </el-button>
                                         <el-button
@@ -630,7 +630,7 @@
                                           size="mini"
                                           circle
                                           @click="moveSetListDown(index,contentIndex,setIndex)"
-                                          v-if="setIndex < content.setting.length - 1 && (formType != 3 && form.templateType != 1) && roles.includes('edit_sop_temp_content')"
+                                          v-if="setIndex < content.setting.length - 1 && (formType != 3 && form.templateType != 1) "
                                           title="下移">
                                         </el-button>
                                         <el-button
@@ -640,7 +640,7 @@
                                           size="mini"
                                           circle
                                           @click="delSetList(index,contentIndex,setIndex)"
-                                          v-if="content.setting.length>1 && (formType != 3 && form.templateType != 1) && roles.includes('del_sop_temp_content') && !(form.sendType == 11 && setIndex == 0)"
+                                          v-if="content.setting.length>1 && (formType != 3 && form.templateType != 1)  && !(form.sendType == 11 && setIndex == 0)"
                                           title="删除">
                                         </el-button>
                                       </div>
@@ -680,7 +680,7 @@
                                   size="mini"
                                   circle
                                   @click="delContent(index,contentIndex)"
-                                  v-if="item.content.length>1 && formType != 3 && form.templateType != 1 && roles.includes('del_sop_temp_rule')"
+                                  v-if="item.content.length>1 && formType != 3 && form.templateType != 1 "
                                   title="删除">
                                 </el-button>
                               </div>
@@ -694,7 +694,7 @@
                     </el-form>
 
                   </div>
-                  <div style="float: right;" v-if="formType != 3 && form.templateType != 1 && roles.includes('update_sop_temp_day')">
+                  <div style="float: right;" v-if="formType != 3 && form.templateType != 1 ">
                     <el-button type="primary" @click="save" v-if="!item.voice || item.voice == 0">
                       保存({{ '第' + (1 + (form.gap * index)) + '天' }})
                     </el-button>

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

@@ -66,7 +66,7 @@
         </el-select>
       </el-form-item>
       <el-form-item>
-        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索1</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
@@ -258,6 +258,15 @@
           >
             禁用插件
           </el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-user-solid"
+            plain
+            @click="handleTime(scope.row)"
+          >
+            设置延迟执行时间
+          </el-button>
         </template>
       </el-table-column>
       <el-table-column label="主机" align="center" class-name="small-padding fixed-width" width="110px" fixed="right">
@@ -360,6 +369,27 @@
       <fast-gpt-role ref="fastGptRole" @refreshFastGptList="refreshFastGptList" ></fast-gpt-role>
     </el-dialog>
 
+    <!-- 设置执行时间对话框 -->
+<el-dialog :title="timeSettingOpen.title" :visible.sync="timeSettingOpen.open" width="500px" append-to-body>
+  <el-form ref="timeSettingForm" :model="timeSettingForm" :rules="timeSettingRules" label-width="120px">
+    <el-form-item label="延迟执行开始(ms)" prop="delayStart">
+      <el-input-number
+        v-model="timeSettingForm.delayStart"
+        controls-position="right"
+        placeholder="请输入开始延迟执行" />
+    </el-form-item>
+    <el-form-item label="延迟执行结束(ms)" prop="delayEnd">
+      <el-input-number
+        v-model="timeSettingForm.delayEnd"
+        controls-position="right"
+        placeholder="请输入结束延迟执行" />
+    </el-form-item>
+  </el-form>
+  <div slot="footer" class="dialog-footer">
+    <el-button @click="cancelTimeSetting">取 消</el-button>
+    <el-button type="primary" @click="submitTimeSettingForm">确 定</el-button>
+  </div>
+</el-dialog>
     <!--    <el-dialog :visible.sync="updateIp.open" width="600px" append-to-body>-->
     <!--      <el-form ref="updateIpForm" :model="updateIpForm" :rules="updateIpRule" label-width="100px">-->
     <!--        <el-form-item label="新云主机IP" prop="Ip">-->
@@ -580,6 +610,21 @@ export default {
   components: { fastGptRole,Treeselect},
   data() {
     return {
+      // 设置执行时间对话框相关数据
+      timeSettingOpen: {
+        open: false,
+        title: '设置延迟执行时间'
+      },
+      timeSettingForm: {
+        id: null,
+        delayStart: null,
+        delayEnd: null
+      },
+      timeSettingRules: {
+        delayStart: [{ required: true, message: '消息发送延迟开始不能为空', trigger: 'blur' }],
+        delayEnd: [{ required: true, message: '消息发送延迟结束不能为空', trigger: 'blur' }]
+      },
+
       deptOptions:[], // 企微部门
       isAutoOptions:[],
       updateIp:{
@@ -749,6 +794,51 @@ export default {
     },
   },
   methods: {
+
+    /**
+     * 处理设置执行时间
+     */
+    handleTime(row) {
+      this.timeSettingOpen.open = true
+      this.timeSettingForm.id = row.id
+      this.timeSettingForm.delayStart = row.delayStart
+      this.timeSettingForm.delayEnd = row.delayEnd
+    },
+
+    /**
+     * 提交执行时间设置
+     */
+    submitTimeSettingForm() {
+      this.$refs['timeSettingForm'].validate(valid => {
+        if (valid) {
+          updateUser(this.timeSettingForm).then(res => {
+            this.$message.success('设置延迟执行时间成功')
+            this.timeSettingOpen.open = false
+            this.getList()
+          })
+        }
+      })
+    },
+
+    /**
+     * 取消执行时间设置
+     */
+    cancelTimeSetting() {
+      this.timeSettingOpen.open = false
+      this.resetTimeSettingForm()
+    },
+
+    /**
+     * 重置执行时间表单
+     */
+    resetTimeSettingForm() {
+      this.timeSettingForm = {
+        id: null,
+        delayStart: null,
+        delayEnd: null
+      }
+      this.resetForm('timeSettingForm')
+    },
     /** 查询部门下拉树结构 */
     getTreeselect() {
       var that=this;