瀏覽代碼

Merge remote-tracking branch 'origin/master'

yjwang 2 天之前
父節點
當前提交
4af58260d9
共有 33 個文件被更改,包括 2063 次插入1309 次删除
  1. 1 1
      src/api/course/courseRedPacketLog.js
  2. 9 0
      src/api/course/courseWatchLog.js
  3. 8 0
      src/api/qw/sop.js
  4. 1 1
      src/components/Pagination/index.vue
  5. 28 0
      src/utils/common.js
  6. 10 0
      src/views/course/courseAnswerlogs/index.vue
  7. 11 3
      src/views/course/courseAnswerlogs/myCourseAnswerlogs.vue
  8. 2 3
      src/views/course/courseRedPacketLog/index.vue
  9. 9 2
      src/views/course/courseRedPacketLog/myCourseRedPacketLog.vue
  10. 57 0
      src/views/course/courseWatchLog/deptWatchLog.vue
  11. 135 22
      src/views/course/courseWatchLog/index.vue
  12. 110 21
      src/views/course/courseWatchLog/myCourseWatchLog.vue
  13. 11 0
      src/views/course/courseWatchLog/qw/statistics.vue
  14. 11 0
      src/views/course/courseWatchLog/statistics.vue
  15. 103 23
      src/views/course/courseWatchLog/watchLog.vue
  16. 22 0
      src/views/course/courseWatchLog/watchLogStatistics.vue
  17. 42 21
      src/views/fastGpt/fastGptRole/fastGptRoleUpdate.vue
  18. 32 11
      src/views/qw/autoTags/dayPartingIndex.vue
  19. 35 11
      src/views/qw/autoTags/groupIndex.vue
  20. 38 10
      src/views/qw/contactWay/index.vue
  21. 67 32
      src/views/qw/externalContact/deptIndex.vue
  22. 61 29
      src/views/qw/externalContact/index.vue
  23. 88 36
      src/views/qw/externalContact/myExternalContact.vue
  24. 1 1
      src/views/qw/externalContactTransfer/index.vue
  25. 38 11
      src/views/qw/groupMsg/index.vue
  26. 41 10
      src/views/qw/sop/addSop.vue
  27. 371 355
      src/views/qw/sop/deptSop.vue
  28. 370 385
      src/views/qw/sop/mySop.vue
  29. 302 279
      src/views/qw/sopUserLogsInfo/sopUserLogsInfoDetails.vue
  30. 2 2
      src/views/statistics/section/channel.vue
  31. 2 2
      src/views/statistics/section/index.vue
  32. 43 36
      src/views/statistics/section/inline.vue
  33. 2 2
      src/views/statistics/section/today.vue

+ 1 - 1
src/api/course/courseRedPacketLog.js

@@ -33,7 +33,7 @@ export function getCourseRedPacketLog(logId) {
 }
 export function courseList() {
   return request({
-    url: '/course/courseRedPacketLog//courseList',
+    url: '/course/courseRedPacketLog/courseList',
     method: 'get',
   })
 }

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

@@ -113,6 +113,15 @@ export function exportCourseWatchLog(query) {
   })
 }
 
+// 导出我的短链课程看课记录
+export function myExportCourseWatchLog(query) {
+  return request({
+    url: '/course/courseWatchLog/myExport',
+    method: 'get',
+    params: query
+  })
+}
+
 export function watchLogStatisticsExport(query) {
   return request({
     url: '/course/courseWatchLog/watchLogStatisticsExport',

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

@@ -118,6 +118,14 @@ export function exportSop(query) {
     params: query
   })
 }
+// 导出我的企微sop
+export function myExportSop(query) {
+  return request({
+    url: '/qw/sop/myExport',
+    method: 'get',
+    params: query
+  })
+}
 
 // 导出企微sop
 export function getSopVoiceList(params) {

+ 1 - 1
src/components/Pagination/index.vue

@@ -36,7 +36,7 @@ export default {
     pageSizes: {
       type: Array,
       default() {
-        return [10, 20, 30, 50,100,200,300]
+        return [5,10, 20, 30, 50,100,200,300]
       }
     },
     // 移动端页码按钮的数量端默认值5

+ 28 - 0
src/utils/common.js

@@ -288,6 +288,34 @@ export function formatTime(timer) {
 	}
 }
 
+/**
+ * 获取日期范围
+ * @param {number} days - 从今天往前推的天数  
+ * @returns {Array} 返回格式化的日期数组 [开始日期, 结束日期]
+ * @example
+ * // 获取最近7天的日期范围
+ * const dateRange = getDateRange(7);
+ * // 返回: ["2024-01-01", "2024-01-08"]
+ */
+export function getDateRange(days) {
+	const today = new Date();
+	const startDate = new Date();
+	startDate.setDate(today.getDate() - days);
+
+	// 格式化日期为年-月-日格式
+	const formatDate = (date) => {
+		const year = date.getFullYear();
+		const month = String(date.getMonth() + 1).padStart(2, '0');
+		const day = String(date.getDate()).padStart(2, '0');
+		return `${year}-${month}-${day}`;
+	};
+
+	return [
+		formatDate(startDate), // days天前
+		formatDate(today)      // 今天
+	];
+}
+
 
 // export function callNumber(mobile){
 // 	var that=this;

+ 10 - 0
src/views/course/courseAnswerlogs/index.vue

@@ -1,6 +1,15 @@
 <template>
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="120px">
+      <el-form-item label="用户ID" prop="userId">
+        <el-input
+          v-model="queryParams.userId"
+          placeholder="请输入用户ID"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
       <el-form-item label="客户电话" prop="phone">
         <el-input
           v-model="queryParams.phone"
@@ -193,6 +202,7 @@ export default {
         phoneMk: null,
         courseId: null,
         videoId: null,
+        userId:null,
         companyUserName: null,
         companyId: null,
         isRight: null,

+ 11 - 3
src/views/course/courseAnswerlogs/myCourseAnswerlogs.vue

@@ -2,7 +2,7 @@
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="120px">
       <el-form-item label="企微账号" prop="qwUserId">
-        <el-select v-model="queryParams.qwUserId" placeholder="企微账号" clearable size="small" @change="updateQwuser()">
+        <el-select v-model="queryParams.qwUserId" placeholder="企微账号"  size="small" @change="updateQwuser()">
           <el-option
             v-for="dict in myQwUserList"
             :key="dict.dictValue"
@@ -157,7 +157,7 @@ export default {
   data() {
     return {
       // 遮罩层
-      loading: true,
+      loading: false,
       // 导出遮罩层
       exportLoading: false,
       // 选中数组
@@ -218,11 +218,17 @@ export default {
 
     getMyQwUserList().then(response => {
       this.myQwUserList = response.data;
+      if(this.myQwUserList!=null){
+        this.queryParams.qwUserId=this.myQwUserList[0].dictValue
+        this.queryParams.corpId=this.myQwUserList[0].corpId
+        this.getList();
+      }
     });
     this.getDicts("sys_company_or").then(response => {
       this.sysCompanyOr = response.data;
     });
-    this.getList();
+
+    // this.getList();
 
   },
   methods: {
@@ -293,6 +299,8 @@ export default {
     /** 重置按钮操作 */
     resetQuery() {
       this.resetForm("queryForm");
+      this.queryParams.qwUserId=this.myQwUserList[0].dictValue;
+      this.queryParams.corpId=this.myQwUserList[0].corpId;
       this.createTime=null;
       this.queryParams.sTime=null;
       this.queryParams.eTime=null;

+ 2 - 3
src/views/course/courseRedPacketLog/index.vue

@@ -153,7 +153,6 @@
             >重新发送</el-button>
           </template>
         </el-table-column>
-      </el-table>
     </el-table>
 
     <pagination
@@ -170,8 +169,8 @@
         <el-form-item label="课程id" prop="courseId">
           <el-input v-model="form.courseId" placeholder="请输入课程id" />
         </el-form-item>
-        <el-form-item label="用户id" prop="userId">
-          <el-input v-model="form.userId" placeholder="请输入用户id" />
+        <el-form-item label="会员id" prop="userId">
+          <el-input v-model="form.userId" placeholder="请输入会员id" />
         </el-form-item>
         <el-form-item label="小节id" prop="videoId">
           <el-input v-model="form.videoId" placeholder="请输入小节id" />

+ 9 - 2
src/views/course/courseRedPacketLog/myCourseRedPacketLog.vue

@@ -2,7 +2,7 @@
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
       <el-form-item label="企微账号" prop="qwUserId">
-        <el-select v-model="queryParams.qwUserId" placeholder="企微账号" clearable size="small" @change="updateQwuser()">
+        <el-select v-model="queryParams.qwUserId" placeholder="企微账号"  size="small" @change="updateQwuser()">
           <el-option
             v-for="dict in myQwUserList"
             :key="dict.dictValue"
@@ -197,7 +197,7 @@ export default {
 
       deptOptions:[],
       // 遮罩层
-      loading: true,
+      loading: false,
       // 导出遮罩层
       exportLoading: false,
       // 选中数组
@@ -255,6 +255,11 @@ export default {
 
     getMyQwUserList().then(response => {
       this.myQwUserList = response.data;
+      if(this.myQwUserList!=null){
+        this.queryParams.qwUserId=this.myQwUserList[0].dictValue
+        this.queryParams.corpId=this.myQwUserList[0].corpId
+        this.getList();
+      }
     });
   },
   methods: {
@@ -334,6 +339,8 @@ export default {
     /** 重置按钮操作 */
     resetQuery() {
       this.resetForm("queryForm");
+      this.queryParams.qwUserId=this.myQwUserList[0].dictValue;
+      this.queryParams.corpId=this.myQwUserList[0].corpId;
       this.createTime=null;
       this.queryParams.sTime=null;
       this.queryParams.eTime=null;

+ 57 - 0
src/views/course/courseWatchLog/deptWatchLog.vue

@@ -109,6 +109,20 @@
         <el-date-picker v-model="updateTime" size="small" style="width: 220px" value-format="yyyy-MM-dd" type="daterange"
                         range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" @change="updateChange"></el-date-picker>
       </el-form-item>
+      <el-form-item label="进线时间" prop="updateTime">
+        <el-date-picker
+          v-model="qecCreateTime"
+          size="small"
+          style="width: 220px"
+          value-format="yyyy-MM-dd"
+          type="daterange"
+          range-separator="-"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          @change="qecCreateTimeChange"
+          :picker-options="pickerOptions"
+        ></el-date-picker>
+      </el-form-item>
       <el-form-item>
         <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@@ -138,6 +152,16 @@
       <el-table-column type="selection" width="55" align="center" />
       <el-table-column label="记录编号" align="center" prop="logId" />
       <el-table-column label="企微客户" align="center" prop="externalUserName"/>
+      <el-table-column label="客户头像" align="center" prop="externalUserAvatar">
+        <template slot-scope="scope">
+          <el-popover
+            placement="right"
+            trigger="hover">
+            <img slot="reference" :src="scope.row.externalUserAvatar" style="width: 40px;height: 40px">
+            <img :src="scope.row.externalUserAvatar" style="max-width: 250px;max-height: 250px">
+          </el-popover>
+        </template>
+      </el-table-column>
       <el-table-column label="会员ID" align="center" prop="userId" />
       <el-table-column label="会员昵称" align="center" prop="fsNickName">
         <template slot-scope="scope">
@@ -171,6 +195,7 @@
       <el-table-column label="更新时间" align="center" prop="updateTime" />
       <el-table-column label="完课时间" align="center" prop="finishTime" />
       <el-table-column label="营期时间" align="center" prop="campPeriodTime" />
+      <el-table-column label="进线时间" align="center" prop="qecCreateTime" />
     </el-table>
 
     <pagination
@@ -219,6 +244,23 @@ export default {
       title: "",
       // 是否显示弹出层
       open: false,
+
+      qecCreateTime:null,
+      pickerOptions: {
+        disabledDate(time) {
+          // 获取6天前的日期(加上今天就是7天)
+          const sixDaysAgo = new Date();
+          sixDaysAgo.setDate(sixDaysAgo.getDate() - 6);
+          sixDaysAgo.setHours(0, 0, 0, 0);
+
+          // 获取明天的日期(不包括今天)
+          const tomorrow = new Date();
+          tomorrow.setDate(tomorrow.getDate() + 1);
+          tomorrow.setHours(0, 0, 0, 0);
+
+          return time.getTime() < sixDaysAgo.getTime() || time.getTime() >= tomorrow.getTime();
+        }
+      },
       // 查询参数
       queryParams: {
         pageNum: 1,
@@ -241,6 +283,8 @@ export default {
         eTime:null,
         upSTime:null,
         upETime:null,
+        qecSTime:null,
+        qecETime:null,
         scheduleStartTime: null,
         scheduleEndTime: null,
       },
@@ -300,6 +344,16 @@ export default {
         this.queryParams.upETime = null;
       }
     },
+
+    qecCreateTimeChange(){
+      if (this.qecCreateTime != null) {
+        this.queryParams.qecSTime = this.qecCreateTime[0];
+        this.queryParams.qecETime = this.qecCreateTime[1];
+      } else {
+        this.queryParams.qecSTime = null;
+        this.queryParams.qecETime = null;
+      }
+    },
     handleClickX(tab,event){
       this.activeName=tab.name;
       if(tab.name=="00"){
@@ -358,10 +412,13 @@ export default {
       this.resetForm("queryForm");
       this.createTime = null;
       this.scheduleTime = null;
+      this.qecCreateTime=null;
       this.queryParams.sTime = null;
       this.queryParams.eTime = null;
       this.queryParams.upSTime = null;
       this.queryParams.upETime = null;
+      this.queryParams.qecSTime = null;
+      this.queryParams.qecETime = null;
       this.queryParams.scheduleStartTime = null;
       this.queryParams.scheduleEndTime = null;
       this.scheduleTime=null;

+ 135 - 22
src/views/course/courseWatchLog/index.vue

@@ -79,6 +79,25 @@
         <el-date-picker v-model="updateTime" size="small" style="width: 220px" value-format="yyyy-MM-dd" type="daterange"
                         range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" @change="updateChange"></el-date-picker>
       </el-form-item>
+<!--      <el-form-item label="进线时间" prop="updateTime">-->
+<!--        <el-date-picker v-model="qecCreateTime" size="small" style="width: 220px" value-format="yyyy-MM-dd" type="daterange"-->
+<!--                        range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" @change="qecCreateTimeChange"></el-date-picker>-->
+<!--      </el-form-item>-->
+      <el-form-item label="进线时间" prop="updateTime">
+        <el-date-picker
+          v-model="qecCreateTime"
+          size="small"
+          style="width: 220px"
+          value-format="yyyy-MM-dd"
+          type="daterange"
+          range-separator="-"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          @change="qecCreateTimeChange"
+          :picker-options="pickerOptions"
+        ></el-date-picker>
+      </el-form-item>
+
       <el-form-item>
         <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@@ -136,6 +155,23 @@
           <img v-else :src="scope.row.externalUserAvatar" style="width:50px;height:50px" />
         </template>
       </el-table-column>
+      <el-table-column label="会员ID" align="center" prop="userId" />
+      <el-table-column label="会员昵称" align="center" prop="fsNickName">
+        <template slot-scope="scope">
+          <div style="display: flex;white-space: nowrap">
+            <div style="margin: auto">
+              {{scope.row.fsNickName}}
+            </div>
+            <el-popover
+              placement="right"
+              title=""
+              trigger="hover">
+              <img slot="reference" :src="scope.row.fsAvatar" style="width: 30px;height: 30px">
+              <img :src="scope.row.fsAvatar" style="max-width: 200px;max-height: 200px">
+            </el-popover>
+          </div>
+        </template>
+      </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="logType">
@@ -152,6 +188,7 @@
       <el-table-column label="更新时间" align="center" prop="updateTime" />
       <el-table-column label="完课时间" align="center" prop="finishTime" />
       <el-table-column label="营期时间" align="center" prop="campPeriodTime" />
+      <el-table-column label="进线时间" align="center" prop="qecCreateTime" />
     </el-table>
 
     <pagination
@@ -173,16 +210,29 @@
           <div style="font-size: 20px;margin-top: 20px;margin-bottom: 20px;">
             <span class="name-background">{{ item.name }}</span>
           </div>
-          <div class="tag-container">
-            <a
-              v-for="tagItem in item.tag"
-              class="tag-box"
-              @click="tagSelection(tagItem)"
-              :class="{ 'tag-selected': tagItem.isSelected }"
-            >
-              {{ tagItem.name }}
-            </a>
+          <!-- 添加外层滚动容器 -->
+          <div class="scroll-wrapper">
+            <div class="tag-container">
+              <a
+                v-for="tagItem in item.tag"
+                class="tag-box"
+                @click="tagSelection(tagItem)"
+                :class="{ 'tag-selected': tagItem.isSelected }"
+              >
+                {{ tagItem.name }}
+              </a>
+            </div>
           </div>
+<!--          <div class="tag-container">-->
+<!--            <a-->
+<!--              v-for="tagItem in item.tag"-->
+<!--              class="tag-box"-->
+<!--              @click="tagSelection(tagItem)"-->
+<!--              :class="{ 'tag-selected': tagItem.isSelected }"-->
+<!--            >-->
+<!--              {{ tagItem.name }}-->
+<!--            </a>-->
+<!--          </div>-->
         </div>
       </el-form>
       <pagination
@@ -209,15 +259,18 @@
           <div style="font-size: 20px;margin-top: 20px;margin-bottom: 20px;">
             <span class="name-background">{{ item.name }}</span>
           </div>
-          <div class="tag-container">
-            <a
-              v-for="tagItem in item.tag"
-              class="tag-box"
-              @click="tagSelection(tagItem)"
-              :class="{ 'tag-selected': tagItem.isSelected }"
-            >
-              {{ tagItem.name }}
-            </a>
+          <!-- 添加外层滚动容器 -->
+          <div class="scroll-wrapper">
+            <div class="tag-container">
+              <a
+                v-for="tagItem in item.tag"
+                class="tag-box"
+                @click="tagSelection(tagItem)"
+                :class="{ 'tag-selected': tagItem.isSelected }"
+              >
+                {{ tagItem.name }}
+              </a>
+            </div>
           </div>
         </div>
       </el-form>
@@ -268,6 +321,22 @@ export default {
       activeName:"2",
       createTime:null,
       updateTime:null,
+      qecCreateTime:null,
+      pickerOptions: {
+        disabledDate(time) {
+          // 获取6天前的日期(加上今天就是7天)
+          const sixDaysAgo = new Date();
+          sixDaysAgo.setDate(sixDaysAgo.getDate() - 6);
+          sixDaysAgo.setHours(0, 0, 0, 0);
+
+          // 获取明天的日期(不包括今天)
+          const tomorrow = new Date();
+          tomorrow.setDate(tomorrow.getDate() + 1);
+          tomorrow.setHours(0, 0, 0, 0);
+
+          return time.getTime() < sixDaysAgo.getTime() || time.getTime() >= tomorrow.getTime();
+        }
+      },
       courseLists:[],
       videoList:[],
       logTypeOptions:[],
@@ -316,7 +385,7 @@ export default {
 
       queryTagParams:{
         pageNum: 1,
-        pageSize: 10,
+        pageSize: 5,
         total:0,
         name:null,
         corpId:null,
@@ -343,6 +412,8 @@ export default {
         eTime:null,
         upSTime:null,
         upETime:null,
+        qecSTime:null,
+        qecETime:null,
         scheduleStartTime: null,
         scheduleEndTime: null,
         sendType:process.env.VUE_APP_COURSE_DEFAULT,
@@ -394,6 +465,19 @@ export default {
         this.queryParams.upETime = null;
       }
     },
+
+    qecCreateTimeChange(){
+      if (this.qecCreateTime != null) {
+        this.queryParams.qecSTime = this.qecCreateTime[0];
+        this.queryParams.qecETime = this.qecCreateTime[1];
+      } else {
+        this.queryParams.qecSTime = null;
+        this.queryParams.qecETime = null;
+      }
+    },
+
+
+
     handleClickX(tab,event){
       this.activeName=tab.name;
       if(tab.name=="00"){
@@ -452,11 +536,13 @@ export default {
     resetQuery() {
       this.resetForm("queryForm");
       this.createTime = null;
-      this.scheduleTime = null;
+      this.qecCreateTime=null;
       this.queryParams.sTime = null;
       this.queryParams.eTime = null;
       this.queryParams.upSTime = null;
       this.queryParams.upETime = null;
+      this.queryParams.qecSTime = null;
+      this.queryParams.qecETime = null;
       this.queryParams.scheduleStartTime = null;
       this.queryParams.scheduleEndTime = null;
       this.scheduleTime=null;
@@ -604,10 +690,22 @@ export default {
 
     handleSearchTags(name){
 
-      searchTags({name:name,corpId:this.queryParams.corpId}).then(response => {
+      if (!name){
+        return this.$message.error("请输入要搜索的标签")
+      }
+
+      this.queryTagParams.name=name;
+      this.queryTagParams.corpId=this.queryParams.corpId;
+
+      searchTags(this.queryTagParams).then(response => {
         this.tagGroupList = response.rows;
       });
 
+      // searchTags({name:name,corpId:this.queryParams.corpId}).then(response => {
+      //   this.tagGroupList = response.rows;
+      // });
+
+
     },
 
     cancelSearchTags(){
@@ -620,7 +718,7 @@ export default {
 
       this.queryTagParams= {
         pageNum: 1,
-        pageSize: 10,
+        pageSize: 5,
         total:0,
         name:null,
       };
@@ -791,4 +889,19 @@ export default {
   margin-left: 10px;
   vertical-align: bottom;
 }
+/* 新增的滚动容器样式(不影响原有样式) */
+.scroll-wrapper {
+  max-height: 130px; /* 大约三行的高度 */
+  overflow-y: auto;  /* 垂直滚动 */
+  padding-right: 5px; /* 为滚动条留出空间 */
+}
+
+/* 美化滚动条(可选) */
+.scroll-wrapper::-webkit-scrollbar {
+  width: 6px;
+}
+.scroll-wrapper::-webkit-scrollbar-thumb {
+  background: rgba(0, 0, 0, 0.2);
+  border-radius: 3px;
+}
 </style>

+ 110 - 21
src/views/course/courseWatchLog/myCourseWatchLog.vue

@@ -72,6 +72,20 @@
       </el-form-item>
       <el-table-column label="完课时间" align="center" prop="finishTime" />
       <el-table-column label="营期时间" align="center" prop="campPeriodTime" />
+      <el-form-item label="进线时间" prop="updateTime">
+        <el-date-picker
+          v-model="qecCreateTime"
+          size="small"
+          style="width: 220px"
+          value-format="yyyy-MM-dd"
+          type="daterange"
+          range-separator="-"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          @change="qecCreateTimeChange"
+          :picker-options="pickerOptions"
+        ></el-date-picker>
+      </el-form-item>
       <el-form-item>
         <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@@ -119,6 +133,16 @@
       <el-table-column type="selection" width="55" align="center" />
       <el-table-column label="记录编号" align="center" prop="logId" />
       <el-table-column label="企微客户" align="center" prop="externalUserName"/>
+      <el-table-column label="客户头像" align="center" prop="externalUserAvatar">
+        <template slot-scope="scope">
+          <el-popover
+            placement="right"
+            trigger="hover">
+            <img slot="reference" :src="scope.row.externalUserAvatar" style="width: 40px;height: 40px">
+            <img :src="scope.row.externalUserAvatar" style="max-width: 250px;max-height: 250px">
+          </el-popover>
+        </template>
+      </el-table-column>
       <el-table-column label="会员ID" align="center" prop="userId" />
       <el-table-column label="会员昵称" align="center" prop="fsNickName">
         <template slot-scope="scope">
@@ -152,6 +176,7 @@
       <el-table-column label="创建时间" align="center" prop="createTime" />
 <!--      <el-table-column label="更新时间" align="center" prop="updateTime" />-->
       <el-table-column label="完课时间" align="center" prop="lastHeartbeatTime" />
+      <el-table-column label="进线时间" align="center" prop="qecCreateTime" />
     </el-table>
 
     <pagination
@@ -174,15 +199,18 @@
           <div style="font-size: 20px;margin-top: 20px;margin-bottom: 20px;">
             <span class="name-background">{{ item.name }}</span>
           </div>
-          <div class="tag-container">
-            <a
-              v-for="tagItem in item.tag"
-              class="tag-box"
-              @click="tagSelection(tagItem)"
-              :class="{ 'tag-selected': tagItem.isSelected }"
-            >
-              {{ tagItem.name }}
-            </a>
+          <!-- 添加外层滚动容器 -->
+          <div class="scroll-wrapper">
+            <div class="tag-container">
+              <a
+                v-for="tagItem in item.tag"
+                class="tag-box"
+                @click="tagSelection(tagItem)"
+                :class="{ 'tag-selected': tagItem.isSelected }"
+              >
+                {{ tagItem.name }}
+              </a>
+            </div>
           </div>
         </div>
       </el-form>
@@ -210,15 +238,18 @@
           <div style="font-size: 20px;margin-top: 20px;margin-bottom: 20px;">
             <span class="name-background">{{ item.name }}</span>
           </div>
-          <div class="tag-container">
-            <a
-              v-for="tagItem in item.tag"
-              class="tag-box"
-              @click="tagSelection(tagItem)"
-              :class="{ 'tag-selected': tagItem.isSelected }"
-            >
-              {{ tagItem.name }}
-            </a>
+          <!-- 添加外层滚动容器 -->
+          <div class="scroll-wrapper">
+            <div class="tag-container">
+              <a
+                v-for="tagItem in item.tag"
+                class="tag-box"
+                @click="tagSelection(tagItem)"
+                :class="{ 'tag-selected': tagItem.isSelected }"
+              >
+                {{ tagItem.name }}
+              </a>
+            </div>
           </div>
         </div>
       </el-form>
@@ -267,6 +298,22 @@ export default {
       resultTitle:'',
 
       createTime:null,
+      qecCreateTime:null,
+      pickerOptions: {
+        disabledDate(time) {
+          // 获取6天前的日期(加上今天就是7天)
+          const sixDaysAgo = new Date();
+          sixDaysAgo.setDate(sixDaysAgo.getDate() - 6);
+          sixDaysAgo.setHours(0, 0, 0, 0);
+
+          // 获取明天的日期(不包括今天)
+          const tomorrow = new Date();
+          tomorrow.setDate(tomorrow.getDate() + 1);
+          tomorrow.setHours(0, 0, 0, 0);
+
+          return time.getTime() < sixDaysAgo.getTime() || time.getTime() >= tomorrow.getTime();
+        }
+      },
       courseLists:[],
       videoList:[],
       myQwUserList:[],
@@ -310,7 +357,7 @@ export default {
 
       queryTagParams:{
         pageNum: 1,
-        pageSize: 10,
+        pageSize: 5,
         total:0,
         name:null,
         corpId:null,
@@ -336,6 +383,8 @@ export default {
         eTime:null,
         scheduleStartTime: null,
         scheduleEndTime: null,
+        qecSTime:null,
+        qecETime:null,
       },
       // 表单参数
       form: {},
@@ -387,6 +436,17 @@ export default {
       }
     },
 
+    qecCreateTimeChange(){
+      if (this.qecCreateTime != null) {
+        this.queryParams.qecSTime = this.qecCreateTime[0];
+        this.queryParams.qecETime = this.qecCreateTime[1];
+      } else {
+        this.queryParams.qecSTime = null;
+        this.queryParams.qecETime = null;
+      }
+    },
+
+
     handleClickX(tab){
       if(tab.name==="10"){
         this.queryParams.logType=null;
@@ -440,8 +500,11 @@ export default {
     resetQuery() {
       this.resetForm("queryForm");
       this.createTime = null;
+      this.qecCreateTime=null;
       this.queryParams.sTime = null;
       this.queryParams.eTime = null;
+      this.queryParams.qecSTime = null;
+      this.queryParams.qecETime = null;
       this.queryParams.scheduleStartTime = null;
       this.queryParams.scheduleEndTime = null;
       this.scheduleTime=null;
@@ -575,10 +638,21 @@ export default {
 
     handleSearchTags(name){
 
-      searchTags({name:name,corpId:this.queryParams.corpId}).then(response => {
+      if (!name){
+        return this.$message.error("请输入要搜索的标签")
+      }
+
+      this.queryTagParams.name=name;
+      this.queryTagParams.corpId=this.queryParams.corpId;
+
+      searchTags(this.queryTagParams).then(response => {
         this.tagGroupList = response.rows;
       });
 
+      // searchTags({name:name,corpId:this.queryParams.corpId}).then(response => {
+      //   this.tagGroupList = response.rows;
+      // });
+
     },
 
     cancelSearchTags(){
@@ -591,7 +665,7 @@ export default {
 
       this.queryTagParams= {
         pageNum: 1,
-        pageSize: 10,
+        pageSize: 5,
         total:0,
         name:null,
       };
@@ -762,4 +836,19 @@ export default {
   margin-left: 10px;
   vertical-align: bottom;
 }
+/* 新增的滚动容器样式(不影响原有样式) */
+.scroll-wrapper {
+  max-height: 130px; /* 大约三行的高度 */
+  overflow-y: auto;  /* 垂直滚动 */
+  padding-right: 5px; /* 为滚动条留出空间 */
+}
+
+/* 美化滚动条(可选) */
+.scroll-wrapper::-webkit-scrollbar {
+  width: 6px;
+}
+.scroll-wrapper::-webkit-scrollbar-thumb {
+  background: rgba(0, 0, 0, 0.2);
+  border-radius: 3px;
+}
 </style>

+ 11 - 0
src/views/course/courseWatchLog/qw/statistics.vue

@@ -67,6 +67,7 @@
 <script>
 import { listCourseWatchLog, getCourseWatchLog, delCourseWatchLog, addCourseWatchLog, updateCourseWatchLog, exportCourseWatchLog,statisticsList } from "@/api/course/qw/courseWatchLog";
 import { courseList,videoList } from '@/api/course/courseRedPacketLog'
+import { getDateRange } from '@/utils/common'
 export default {
   name: "CourseWatchLog",
   data() {
@@ -124,6 +125,12 @@ export default {
     };
   },
   created() {
+    // // 设置默认时间范围为最近7天
+    // this.createTime = getDateRange(7);
+    // // 设置查询参数的时间
+    // this.queryParams.sTime = this.createTime[0];
+    // this.queryParams.eTime = this.createTime[1];
+
     courseList().then(response => {
       this.courseLists = response.list;
     });
@@ -195,6 +202,10 @@ export default {
     },
     /** 搜索按钮操作 */
     handleQuery() {
+      if (!this.queryParams.sTime || !this.queryParams.eTime) {
+        this.$message.warning("请选择创建时间");
+        return;
+      }
       this.queryParams.pageNum = 1;
       this.getList();
     },

+ 11 - 0
src/views/course/courseWatchLog/statistics.vue

@@ -68,6 +68,7 @@
 import { listCourseWatchLog, getCourseWatchLog, delCourseWatchLog, addCourseWatchLog, updateCourseWatchLog, exportCourseWatchLog,statisticsList } from "@/api/course/courseWatchLog";
 import { courseList,videoList } from '@/api/course/courseRedPacketLog'
 import PaginationMore from "../../../components/PaginationMore/index.vue";
+import {getDateRange} from "@/utils/common";
 export default {
   name: "CourseWatchLog",
   components: {PaginationMore},
@@ -126,6 +127,12 @@ export default {
     };
   },
   created() {
+    // // 设置默认时间范围为最近7天
+    // this.createTime = getDateRange(7);
+    // // 设置查询参数的时间
+    // this.queryParams.sTime = this.createTime[0];
+    // this.queryParams.eTime = this.createTime[1];
+
     courseList().then(response => {
       this.courseLists = response.list;
     });
@@ -197,6 +204,10 @@ export default {
     },
     /** 搜索按钮操作 */
     handleQuery() {
+      if (!this.queryParams.sTime || !this.queryParams.eTime) {
+        this.$message.warning("请选择创建时间");
+        return;
+      }
       this.queryParams.pageNum = 1;
       this.getList();
     },

+ 103 - 23
src/views/course/courseWatchLog/watchLog.vue

@@ -102,6 +102,21 @@
                         range-separator="-" start-placeholder="开始日期"
                         end-placeholder="结束日期" @change="updateChange"></el-date-picker>
       </el-form-item>
+      <el-form-item label="进线时间" prop="updateTime">
+        <el-date-picker
+          v-model="qecCreateTime"
+          size="small"
+          style="width: 220px"
+          value-format="yyyy-MM-dd"
+          type="daterange"
+          range-separator="-"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          @change="qecCreateTimeChange"
+          :picker-options="pickerOptions"
+        ></el-date-picker>
+      </el-form-item>
+
       <el-form-item>
         <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@@ -319,15 +334,18 @@
           <div style="font-size: 20px;margin-top: 20px;margin-bottom: 20px;">
             <span class="name-background">{{ item.name }}</span>
           </div>
-          <div class="tag-container">
-            <a
-              v-for="tagItem in item.tag"
-              class="tag-box"
-              @click="tagSelection(tagItem)"
-              :class="{ 'tag-selected': tagItem.isSelected }"
-            >
-              {{ tagItem.name }}
-            </a>
+          <!-- 添加外层滚动容器 -->
+          <div class="scroll-wrapper">
+            <div class="tag-container">
+              <a
+                v-for="tagItem in item.tag"
+                class="tag-box"
+                @click="tagSelection(tagItem)"
+                :class="{ 'tag-selected': tagItem.isSelected }"
+              >
+                {{ tagItem.name }}
+              </a>
+            </div>
           </div>
         </div>
       </el-form>
@@ -355,15 +373,18 @@
           <div style="font-size: 20px;margin-top: 20px;margin-bottom: 20px;">
             <span class="name-background">{{ item.name }}</span>
           </div>
-          <div class="tag-container">
-            <a
-              v-for="tagItem in item.tag"
-              class="tag-box"
-              @click="tagSelection(tagItem)"
-              :class="{ 'tag-selected': tagItem.isSelected }"
-            >
-              {{ tagItem.name }}
-            </a>
+          <!-- 添加外层滚动容器 -->
+          <div class="scroll-wrapper">
+            <div class="tag-container">
+              <a
+                v-for="tagItem in item.tag"
+                class="tag-box"
+                @click="tagSelection(tagItem)"
+                :class="{ 'tag-selected': tagItem.isSelected }"
+              >
+                {{ tagItem.name }}
+              </a>
+            </div>
           </div>
         </div>
       </el-form>
@@ -401,7 +422,7 @@ import {
   addCourseWatchLog,
   delCourseWatchLog,
   exportCourseWatchLog,
-  getCourseWatchLog,
+  getCourseWatchLog, myExportCourseWatchLog,
   myListCourseWatchLog,
   updateCourseWatchLog
 } from "@/api/course/courseWatchLog";
@@ -425,6 +446,23 @@ export default {
       activeName:"2",
       createTime: null,
       updateTime:null,
+
+      qecCreateTime:null,
+      pickerOptions: {
+        disabledDate(time) {
+          // 获取6天前的日期(加上今天就是7天)
+          const sixDaysAgo = new Date();
+          sixDaysAgo.setDate(sixDaysAgo.getDate() - 6);
+          sixDaysAgo.setHours(0, 0, 0, 0);
+
+          // 获取明天的日期(不包括今天)
+          const tomorrow = new Date();
+          tomorrow.setDate(tomorrow.getDate() + 1);
+          tomorrow.setHours(0, 0, 0, 0);
+
+          return time.getTime() < sixDaysAgo.getTime() || time.getTime() >= tomorrow.getTime();
+        }
+      },
       courseLists: [],
       videoList: [],
       myQwUserList: [],
@@ -497,7 +535,7 @@ export default {
 
       queryTagParams:{
         pageNum: 1,
-        pageSize: 10,
+        pageSize: 5,
         total:0,
         name:null,
         corpId:null,
@@ -522,6 +560,8 @@ export default {
         eTime: null,
         upSTime:null,
         upETime:null,
+        qecSTime:null,
+        qecETime:null,
         scheduleStartTime: null,
         scheduleEndTime: null,
         sendType:process.env.VUE_APP_COURSE_DEFAULT,
@@ -586,6 +626,17 @@ export default {
         this.queryParams.upETime = null;
       }
     },
+
+    qecCreateTimeChange(){
+      if (this.qecCreateTime != null) {
+        this.queryParams.qecSTime = this.qecCreateTime[0];
+        this.queryParams.qecETime = this.qecCreateTime[1];
+      } else {
+        this.queryParams.qecSTime = null;
+        this.queryParams.qecETime = null;
+      }
+    },
+
     handleClickX(tab) {
       this.activeName=tab.name;
       if(tab.name=="00"){
@@ -654,10 +705,13 @@ export default {
     resetQuery() {
       this.resetForm("queryForm");
       this.createTime = null;
+      this.qecCreateTime=null;
       this.queryParams.sTime = null;
       this.queryParams.eTime = null;
       this.queryParams.upSTime = null;
       this.queryParams.upETime = null;
+      this.queryParams.qecSTime = null;
+      this.queryParams.qecETime = null;
       this.queryParams.scheduleStartTime = null;
       this.queryParams.scheduleEndTime = null;
       this.scheduleTime=null;
@@ -730,7 +784,7 @@ export default {
         type: "warning"
       }).then(() => {
         this.exportLoading = true;
-        return exportCourseWatchLog(queryParams);
+        return myExportCourseWatchLog(queryParams);
       }).then(response => {
         this.download(response.msg);
         this.exportLoading = false;
@@ -821,10 +875,21 @@ export default {
 
     handleSearchTags(name){
 
-      searchTags({name:name,corpId:this.queryParams.corpId}).then(response => {
+      if (!name){
+        return this.$message.error("请输入要搜索的标签")
+      }
+
+      this.queryTagParams.name=name;
+      this.queryTagParams.corpId=this.queryParams.corpId;
+
+      searchTags(this.queryTagParams).then(response => {
         this.tagGroupList = response.rows;
       });
 
+      // searchTags({name:name,corpId:this.queryParams.corpId}).then(response => {
+      //   this.tagGroupList = response.rows;
+      // });
+
     },
 
     cancelSearchTags(){
@@ -837,7 +902,7 @@ export default {
 
       this.queryTagParams= {
         pageNum: 1,
-        pageSize: 10,
+        pageSize: 5,
         total:0,
         name:null,
       };
@@ -1008,4 +1073,19 @@ export default {
   margin-left: 10px;
   vertical-align: bottom;
 }
+/* 新增的滚动容器样式(不影响原有样式) */
+.scroll-wrapper {
+  max-height: 130px; /* 大约三行的高度 */
+  overflow-y: auto;  /* 垂直滚动 */
+  padding-right: 5px; /* 为滚动条留出空间 */
+}
+
+/* 美化滚动条(可选) */
+.scroll-wrapper::-webkit-scrollbar {
+  width: 6px;
+}
+.scroll-wrapper::-webkit-scrollbar-thumb {
+  background: rgba(0, 0, 0, 0.2);
+  border-radius: 3px;
+}
 </style>

+ 22 - 0
src/views/course/courseWatchLog/watchLogStatistics.vue

@@ -40,6 +40,17 @@
 
     <el-table border v-loading="loading" :data="courseWatchLogList" @selection-change="handleSelectionChange">
       <el-table-column label="企微客户" align="center" prop="externalUserName"/>
+      <el-table-column label="客户头像" align="center" prop="avatar">
+        <template slot-scope="scope">
+            <el-popover
+              placement="right"
+              title=""
+              trigger="hover">
+              <img slot="reference" :src="scope.row.avatar" style="width: 40px;height: 40px">
+              <img :src="scope.row.avatar" style="max-width: 250px;max-height: 250px">
+            </el-popover>
+        </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="createTime" />
@@ -61,6 +72,7 @@
 import { listCourseWatchLog, getCourseWatchLog, delCourseWatchLog, addCourseWatchLog, updateCourseWatchLog, exportCourseWatchLog,watchLogStatistics,watchLogStatisticsExport } from "@/api/course/courseWatchLog";
 import {allList}from "@/api/company/company";
 import { courseList,videoList } from '@/api/course/courseRedPacketLog'
+import {getDateRange} from "@/utils/common";
 export default {
   name: "CourseWatchLog",
   data() {
@@ -122,6 +134,12 @@ export default {
     };
   },
   created() {
+    // // 设置默认时间范围为最近7天
+    // this.createTime = getDateRange(7);
+    // // 设置查询参数的时间
+    // this.queryParams.sTime = this.createTime[0];
+    // this.queryParams.eTime = this.createTime[1];
+
     courseList().then(response => {
       this.courseLists = response.list;
     });
@@ -211,6 +229,10 @@ export default {
     },
     /** 搜索按钮操作 */
     handleQuery() {
+      if (!this.queryParams.sTime || !this.queryParams.eTime) {
+        this.$message.warning("请选择创建时间");
+        return;
+      }
       this.queryParams.pageNum = 1;
       this.getList();
     },

+ 42 - 21
src/views/fastGpt/fastGptRole/fastGptRoleUpdate.vue

@@ -37,7 +37,7 @@
                                 @click="handleEditRoleTag(tagsForm, index)"
                                 @close="handleCloseRoleTag(tagsForm, index)"
                                 style="margin: 3px;">
-                          {{ getTagNames(tagsForm.tagIds) }} 
+                          {{ getTagNames(tagsForm.tagIds) }}
                         </el-tag>
                       </div>
                     </div>
@@ -51,7 +51,7 @@
                     v-hasPermi="['fastGptRole:fastGptRole:edit']"
                   >添加标签人设</el-button>
               </el-form-item> -->
-			  
+
 <!--      		<el-form-item label="修改栏目" prop="contactInfo">
       		  <el-select v-model="contactInfo"  multiple filterable placeholder="请选择修改栏目" clearable size="small" style="width: 50%" >
       		    <el-option
@@ -102,15 +102,18 @@
         <div style="font-size: 20px;margin-top: 20px;margin-bottom: 20px;">
           <span class="name-background">{{ item.name }}</span>
         </div>
-        <div class="tag-container">
-          <a
-            v-for="tagItem in item.tag"
-            class="tag-box"
-            @click="tagSelection(tagItem)"
-            :class="{ 'tag-selected': tagItem.isSelected }"
-          >
-            {{ tagItem.name }}
-          </a>
+        <!-- 添加外层滚动容器 -->
+        <div class="scroll-wrapper">
+          <div class="tag-container">
+            <a
+              v-for="tagItem in item.tag"
+              class="tag-box"
+              @click="tagSelection(tagItem)"
+              :class="{ 'tag-selected': tagItem.isSelected }"
+            >
+              {{ tagItem.name }}
+            </a>
+          </div>
         </div>
       </div>
       <div slot="footer" class="dialog-footer">
@@ -153,15 +156,18 @@
         <div style="font-size: 20px;margin-top: 20px;margin-bottom: 20px;">
           <span class="name-background">{{ item.name }}</span>
         </div>
-        <div class="tag-container">
-          <a
-            v-for="tagItem in item.tag"
-            class="tag-box"
-            @click="tagSelection(tagItem)"
-            :class="{ 'tag-selected': tagItem.isSelected }"
-          >
-            {{ tagItem.name }}
-          </a>
+        <!-- 添加外层滚动容器 -->
+        <div class="scroll-wrapper">
+          <div class="tag-container">
+            <a
+              v-for="tagItem in item.tag"
+              class="tag-box"
+              @click="tagSelection(tagItem)"
+              :class="{ 'tag-selected': tagItem.isSelected }"
+            >
+              {{ tagItem.name }}
+            </a>
+          </div>
         </div>
       </div>
       <div slot="footer" class="dialog-footer">
@@ -370,7 +376,7 @@ export default {
     this.getDicts("sys_fastgpt_role_external_info").then((response) => {
     	  this.externalInfoOptions = response.data;
     });
-	
+
 	getAllRoleType().then(response => {
         this.typeOptions = response.data;
       });
@@ -796,4 +802,19 @@ export default {
   overflow-y: auto; /* 内容超出时显示滚动条 */
   line-height: 1.5em; /* 行高设置,确保每行高度一致 */
 }
+/* 新增的滚动容器样式(不影响原有样式) */
+.scroll-wrapper {
+  max-height: 130px; /* 大约三行的高度 */
+  overflow-y: auto;  /* 垂直滚动 */
+  padding-right: 5px; /* 为滚动条留出空间 */
+}
+
+/* 美化滚动条(可选) */
+.scroll-wrapper::-webkit-scrollbar {
+  width: 6px;
+}
+.scroll-wrapper::-webkit-scrollbar-thumb {
+  background: rgba(0, 0, 0, 0.2);
+  border-radius: 3px;
+}
 </style>

+ 32 - 11
src/views/qw/autoTags/dayPartingIndex.vue

@@ -275,15 +275,18 @@
         <div style="font-size: 20px;margin-top: 20px;margin-bottom: 20px;">
           <span class="name-background">{{ item.name }}</span>
         </div>
-        <div class="tag-container">
-          <a
-            v-for="tagItem in item.tag"
-            class="tag-box"
-            @click="tagSelection(tagItem)"
-            :class="{ 'tag-selected': tagItem.isSelected }"
-          >
-            {{ tagItem.name }}
-          </a>
+        <!-- 添加外层滚动容器 -->
+        <div class="scroll-wrapper">
+          <div class="tag-container">
+            <a
+              v-for="tagItem in item.tag"
+              class="tag-box"
+              @click="tagSelection(tagItem)"
+              :class="{ 'tag-selected': tagItem.isSelected }"
+            >
+              {{ tagItem.name }}
+            </a>
+          </div>
         </div>
       </div>
       <pagination
@@ -389,7 +392,7 @@ export default {
 
       queryTagParams: {
         pageNum: 1,
-        pageSize: 10,
+        pageSize: 5,
         total:0,
         name:null,
         corpId:null,
@@ -585,7 +588,7 @@ export default {
 
       this.queryTagParams= {
         pageNum: 1,
-        pageSize: 10,
+        pageSize: 5,
         total:0,
         name:null,
       };
@@ -638,6 +641,9 @@ export default {
 
     handleSearchTags(){
 
+      if (!this.queryTagParams.name){
+        return this.$message.error("请输入要搜索的标签")
+      }
       this.queryTagParams.corpId=this.queryParams.corpId;
       searchTags(this.queryTagParams).then(response => {
         this.tagGroupList = response.rows;
@@ -1007,4 +1013,19 @@ export default {
   overflow-y: auto; /* 内容超出时显示滚动条 */
   line-height: 1.5em; /* 行高设置,确保每行高度一致 */
 }
+/* 新增的滚动容器样式(不影响原有样式) */
+.scroll-wrapper {
+  max-height: 130px; /* 大约三行的高度 */
+  overflow-y: auto;  /* 垂直滚动 */
+  padding-right: 5px; /* 为滚动条留出空间 */
+}
+
+/* 美化滚动条(可选) */
+.scroll-wrapper::-webkit-scrollbar {
+  width: 6px;
+}
+.scroll-wrapper::-webkit-scrollbar-thumb {
+  background: rgba(0, 0, 0, 0.2);
+  border-radius: 3px;
+}
 </style>

+ 35 - 11
src/views/qw/autoTags/groupIndex.vue

@@ -222,15 +222,19 @@
         <div style="font-size: 20px;margin-top: 20px;margin-bottom: 20px;">
           <span class="name-background">{{ item.name }}</span>
         </div>
-        <div class="tag-container">
-          <a
-            v-for="tagItem in item.tag"
-            class="tag-box"
-            @click="tagSelection(tagItem)"
-            :class="{ 'tag-selected': tagItem.isSelected }"
-          >
-            {{ tagItem.name }}
-          </a>
+
+        <!-- 添加外层滚动容器 -->
+        <div class="scroll-wrapper">
+          <div class="tag-container">
+            <a
+              v-for="tagItem in item.tag"
+              class="tag-box"
+              @click="tagSelection(tagItem)"
+              :class="{ 'tag-selected': tagItem.isSelected }"
+            >
+              {{ tagItem.name }}
+            </a>
+          </div>
         </div>
       </div>
       <pagination
@@ -319,7 +323,7 @@ export default {
 
       queryTagParams: {
         pageNum: 1,
-        pageSize: 10,
+        pageSize: 5,
         total:0,
         name:null,
         corpId:null,
@@ -431,7 +435,7 @@ export default {
 
       this.queryTagParams= {
         pageNum: 1,
-        pageSize: 10,
+        pageSize: 5,
         total:0,
         name:null,
       };
@@ -506,6 +510,11 @@ export default {
     },
 
     handleSearchTags(){
+
+      if (!this.queryTagParams.name){
+        return this.$message.error("请输入要搜索的标签")
+      }
+
       this.queryTagParams.corpId=this.queryParams.corpId;
       searchTags(this.queryTagParams).then(response => {
         this.tagGroupList = response.rows;
@@ -805,4 +814,19 @@ export default {
   overflow-y: auto; /* 内容超出时显示滚动条 */
   line-height: 1.5em; /* 行高设置,确保每行高度一致 */
 }
+/* 新增的滚动容器样式(不影响原有样式) */
+.scroll-wrapper {
+  max-height: 130px; /* 大约三行的高度 */
+  overflow-y: auto;  /* 垂直滚动 */
+  padding-right: 5px; /* 为滚动条留出空间 */
+}
+
+/* 美化滚动条(可选) */
+.scroll-wrapper::-webkit-scrollbar {
+  width: 6px;
+}
+.scroll-wrapper::-webkit-scrollbar-thumb {
+  background: rgba(0, 0, 0, 0.2);
+  border-radius: 3px;
+}
 </style>

+ 38 - 10
src/views/qw/contactWay/index.vue

@@ -625,15 +625,18 @@
         <div style="font-size: 20px;margin-top: 20px;margin-bottom: 20px;">
           <span class="name-background">{{ item.name }}</span>
         </div>
-        <div class="tag-container">
-          <a
-            v-for="tagItem in item.tag"
-            class="tag-box"
-            @click="tagSelection(tagItem)"
-            :class="{ 'tag-selected': tagItem.isSelected }"
-          >
-            {{ tagItem.name }}
-          </a>
+        <!-- 添加外层滚动容器 -->
+        <div class="scroll-wrapper">
+          <div class="tag-container">
+            <a
+              v-for="tagItem in item.tag"
+              class="tag-box"
+              @click="tagSelection(tagItem)"
+              :class="{ 'tag-selected': tagItem.isSelected }"
+            >
+              {{ tagItem.name }}
+            </a>
+          </div>
         </div>
       </div>
       <div slot="footer" class="dialog-footer">
@@ -883,9 +886,19 @@ export default {
     },
     handleSearchTags(name){
 
-      searchTags({name:name,corpId:this.queryParams.corpId}).then(response => {
+      if (!name){
+        return this.$message.error("请输入要搜索的标签")
+      }
+
+      this.queryTagParams.name=name;
+      this.queryTagParams.corpId=this.queryParams.corpId;
+
+      searchTags(this.queryTagParams).then(response => {
         this.tagGroupList = response.rows;
       });
+      // searchTags({name:name,corpId:this.queryParams.corpId}).then(response => {
+      //   this.tagGroupList = response.rows;
+      // });
 
     },
     cancelSearchTags(){
@@ -1497,4 +1510,19 @@ export default {
   margin-left: 10px;
   vertical-align: bottom;
 }
+/* 新增的滚动容器样式(不影响原有样式) */
+.scroll-wrapper {
+  max-height: 130px; /* 大约三行的高度 */
+  overflow-y: auto;  /* 垂直滚动 */
+  padding-right: 5px; /* 为滚动条留出空间 */
+}
+
+/* 美化滚动条(可选) */
+.scroll-wrapper::-webkit-scrollbar {
+  width: 6px;
+}
+.scroll-wrapper::-webkit-scrollbar-thumb {
+  background: rgba(0, 0, 0, 0.2);
+  border-radius: 3px;
+}
 </style>

+ 67 - 32
src/views/qw/externalContact/deptIndex.vue

@@ -231,7 +231,7 @@
           icon="el-icon-edit"
           size="mini"
           @click="handleBatchUpdateNotes"
-          v-hasPermi="['qw:externalContact:edit']"
+          v-hasPermi="['qw:externalContact:deptEdit']"
         >批量修改备注</el-button>
       </el-col>
 
@@ -252,7 +252,7 @@
           plain
           size="mini"
           @click="addUserTag"
-          v-hasPermi="['qw:externalContact:addTag']"
+          v-hasPermi="['qw:externalContact:deptAddTag']"
         >批量添加标签</el-button>
       </el-col>
       <el-col :span="1.5">
@@ -261,7 +261,7 @@
           plain
           size="mini"
           @click="delUserTag"
-          v-hasPermi="['qw:externalContact:delTag']"
+          v-hasPermi="['qw:externalContact:deptDelTag']"
         >批量移除标签</el-button>
       </el-col>
       <el-col :span="1.5">
@@ -270,6 +270,7 @@
           plain
           size="mini"
           @click="updateTalk"
+          v-hasPermi="['qw:externalContactInfo:deptUpdateTalk']"
         >批量更改交流状态</el-button>
       </el-col>
       <!--       <el-col :span="1.5">-->
@@ -490,15 +491,18 @@
         <div style="font-size: 20px;margin-top: 20px;margin-bottom: 20px;">
           <span class="name-background">{{ item.name }}</span>
         </div>
-        <div class="tag-container">
-          <a
-            v-for="tagItem in item.tag"
-            class="tag-box"
-            @click="tagSelection(tagItem)"
-            :class="{ 'tag-selected': tagItem.isSelected }"
-          >
-            {{ tagItem.name }}
-          </a>
+        <!-- 添加外层滚动容器 -->
+        <div class="scroll-wrapper">
+          <div class="tag-container">
+            <a
+              v-for="tagItem in item.tag"
+              class="tag-box"
+              @click="tagSelection(tagItem)"
+              :class="{ 'tag-selected': tagItem.isSelected }"
+            >
+              {{ tagItem.name }}
+            </a>
+          </div>
         </div>
       </div>
 
@@ -571,15 +575,18 @@
           <div style="font-size: 20px;margin-top: 20px;margin-bottom: 20px;">
             <span class="name-background">{{ item.name }}</span>
           </div>
-          <div class="tag-container">
-            <a
-              v-for="tagItem in item.tag"
-              class="tag-box"
-              @click="tagSelection(tagItem)"
-              :class="{ 'tag-selected': tagItem.isSelected }"
-            >
-              {{ tagItem.name }}
-            </a>
+          <!-- 添加外层滚动容器 -->
+          <div class="scroll-wrapper">
+            <div class="tag-container">
+              <a
+                v-for="tagItem in item.tag"
+                class="tag-box"
+                @click="tagSelection(tagItem)"
+                :class="{ 'tag-selected': tagItem.isSelected }"
+              >
+                {{ tagItem.name }}
+              </a>
+            </div>
           </div>
         </div>
       </el-form>
@@ -607,15 +614,18 @@
           <div style="font-size: 20px;margin-top: 20px;margin-bottom: 20px;">
             <span class="name-background">{{ item.name }}</span>
           </div>
-          <div class="tag-container">
-            <a
-              v-for="tagItem in item.tag"
-              class="tag-box"
-              @click="tagSelection(tagItem)"
-              :class="{ 'tag-selected': tagItem.isSelected }"
-            >
-              {{ tagItem.name }}
-            </a>
+          <!-- 添加外层滚动容器 -->
+          <div class="scroll-wrapper">
+            <div class="tag-container">
+              <a
+                v-for="tagItem in item.tag"
+                class="tag-box"
+                @click="tagSelection(tagItem)"
+                :class="{ 'tag-selected': tagItem.isSelected }"
+              >
+                {{ tagItem.name }}
+              </a>
+            </div>
           </div>
         </div>
       </el-form>
@@ -941,7 +951,7 @@ export default {
 
       queryTagParams:{
         pageNum: 1,
-        pageSize: 10,
+        pageSize: 5,
         total:0,
         name:null,
         corpId:null,
@@ -1558,10 +1568,20 @@ export default {
     },
     handleSearchTags(name){
 
-      searchTags({name:name,corpId:this.queryParams.corpId}).then(response => {
+      if (!name){
+        return this.$message.error("请输入要搜索的标签")
+      }
+      this.queryTagParams.name=name;
+      this.queryTagParams.corpId=this.queryParams.corpId;
+
+      searchTags(this.queryTagParams).then(response => {
         this.tagGroupList = response.rows;
       });
 
+      // searchTags({name:name,corpId:this.queryParams.corpId}).then(response => {
+      //   this.tagGroupList = response.rows;
+      // });
+
     },
 
     cancelSearchTags(){
@@ -2043,4 +2063,19 @@ export default {
   padding: 20px;
   box-sizing: border-box; /* 确保 padding 不影响总宽度 */
 }
+/* 新增的滚动容器样式(不影响原有样式) */
+.scroll-wrapper {
+  max-height: 130px; /* 大约三行的高度 */
+  overflow-y: auto;  /* 垂直滚动 */
+  padding-right: 5px; /* 为滚动条留出空间 */
+}
+
+/* 美化滚动条(可选) */
+.scroll-wrapper::-webkit-scrollbar {
+  width: 6px;
+}
+.scroll-wrapper::-webkit-scrollbar-thumb {
+  background: rgba(0, 0, 0, 0.2);
+  border-radius: 3px;
+}
 </style>

+ 61 - 29
src/views/qw/externalContact/index.vue

@@ -271,6 +271,7 @@
 	      plain
 	      size="mini"
 	      @click="updateTalk"
+        v-hasPermi="['qw:externalContactInfo:updateTalk']"
 	    >批量更改交流状态</el-button>
 	  </el-col>
 <!--       <el-col :span="1.5">-->
@@ -465,15 +466,18 @@
         <div style="font-size: 20px;margin-top: 20px;margin-bottom: 20px;">
           <span class="name-background">{{ item.name }}</span>
         </div>
-        <div class="tag-container">
-          <a
-            v-for="tagItem in item.tag"
-            class="tag-box"
-            @click="tagSelection(tagItem)"
-            :class="{ 'tag-selected': tagItem.isSelected }"
-          >
-            {{ tagItem.name }}
-          </a>
+        <!-- 添加外层滚动容器 -->
+        <div class="scroll-wrapper">
+          <div class="tag-container">
+            <a
+              v-for="tagItem in item.tag"
+              class="tag-box"
+              @click="tagSelection(tagItem)"
+              :class="{ 'tag-selected': tagItem.isSelected }"
+            >
+              {{ tagItem.name }}
+            </a>
+          </div>
         </div>
       </div>
 
@@ -501,15 +505,18 @@
           <div style="font-size: 20px;margin-top: 20px;margin-bottom: 20px;">
             <span class="name-background">{{ item.name }}</span>
           </div>
-          <div class="tag-container">
-            <a
-              v-for="tagItem in item.tag"
-              class="tag-box"
-              @click="tagSelection(tagItem)"
-              :class="{ 'tag-selected': tagItem.isSelected }"
-            >
-              {{ tagItem.name }}
-            </a>
+          <!-- 添加外层滚动容器 -->
+          <div class="scroll-wrapper">
+            <div class="tag-container">
+              <a
+                v-for="tagItem in item.tag"
+                class="tag-box"
+                @click="tagSelection(tagItem)"
+                :class="{ 'tag-selected': tagItem.isSelected }"
+              >
+                {{ tagItem.name }}
+              </a>
+            </div>
           </div>
         </div>
       </el-form>
@@ -537,15 +544,18 @@
           <div style="font-size: 20px;margin-top: 20px;margin-bottom: 20px;">
             <span class="name-background">{{ item.name }}</span>
           </div>
-          <div class="tag-container">
-            <a
-              v-for="tagItem in item.tag"
-              class="tag-box"
-              @click="tagSelection(tagItem)"
-              :class="{ 'tag-selected': tagItem.isSelected }"
-            >
-              {{ tagItem.name }}
-            </a>
+          <!-- 添加外层滚动容器 -->
+          <div class="scroll-wrapper">
+            <div class="tag-container">
+              <a
+                v-for="tagItem in item.tag"
+                class="tag-box"
+                @click="tagSelection(tagItem)"
+                :class="{ 'tag-selected': tagItem.isSelected }"
+              >
+                {{ tagItem.name }}
+              </a>
+            </div>
           </div>
         </div>
       </el-form>
@@ -797,7 +807,7 @@ export default {
 
       queryTagParams:{
         pageNum: 1,
-        pageSize: 10,
+        pageSize: 5,
         total:0,
         name:null,
         corpId:null,
@@ -1359,7 +1369,14 @@ export default {
     },
     handleSearchTags(name){
 
-      searchTags({name:name,corpId:this.queryParams.corpId}).then(response => {
+      if (!name){
+        return this.$message.error("请输入要搜索的标签")
+      }
+
+      this.queryTagParams.name=name;
+      this.queryTagParams.corpId=this.queryParams.corpId;
+
+      searchTags(this.queryTagParams).then(response => {
         this.tagGroupList = response.rows;
       });
 
@@ -1788,4 +1805,19 @@ export default {
 .suggestion-item:hover {
   background-color: #f5f7fa;
 }
+/* 新增的滚动容器样式(不影响原有样式) */
+.scroll-wrapper {
+  max-height: 130px; /* 大约三行的高度 */
+  overflow-y: auto;  /* 垂直滚动 */
+  padding-right: 5px; /* 为滚动条留出空间 */
+}
+
+/* 美化滚动条(可选) */
+.scroll-wrapper::-webkit-scrollbar {
+  width: 6px;
+}
+.scroll-wrapper::-webkit-scrollbar-thumb {
+  background: rgba(0, 0, 0, 0.2);
+  border-radius: 3px;
+}
 </style>

+ 88 - 36
src/views/qw/externalContact/myExternalContact.vue

@@ -196,7 +196,7 @@
           size="mini"
           :disabled="single"
           @click="handleUpdate"
-          v-hasPermi="['qw:externalContact:edit']"
+
         >修改备注</el-button>
       </el-col>
       <el-col :span="1.5">
@@ -207,7 +207,7 @@
           size="mini"
           :loading="exportLoading"
           @click="handleSyncMyExternalContact"
-          v-hasPermi="['qw:externalContact:myExport']"
+
         >同步我的客户</el-button>
 		<el-button
 		  type="warning"
@@ -216,7 +216,7 @@
 		  size="mini"
 		  :loading="exportLoading"
 		  @click="handleSyncAddMyExternalContact"
-		  v-hasPermi="['qw:externalContact:myExport']"
+
 		>新客同步</el-button>
       </el-col>
       <el-col :span="1.5">
@@ -236,7 +236,7 @@
           plain
           size="mini"
           @click="addUserTag"
-          v-hasPermi="['qw:externalContact:addTag']"
+
         >批量添加标签</el-button>
       </el-col>
       <el-col :span="1.5">
@@ -245,7 +245,7 @@
           plain
           size="mini"
           @click="delUserTag"
-          v-hasPermi="['qw:externalContact:delTag']"
+
         >批量移除标签</el-button>
       </el-col>
 	  <el-col :span="1.5">
@@ -254,6 +254,7 @@
 	      plain
 	      size="mini"
 	      @click="updateTalk"
+        v-hasPermi="['qw:externalContactInfo:myUpdateTalk']"
 	    >批量更改交流状态</el-button>
 	  </el-col>
 	  <el-col :span="1.5">
@@ -262,6 +263,7 @@
 	      plain
 	      size="mini"
 	      @click="updateAllTalk"
+        v-hasPermi="['qw:externalContactInfo:myUpdateAllTalk']"
 	    >更改全部交流状态</el-button>
 	  </el-col>
 <!--     <el-col :span="1.5">-->
@@ -454,21 +456,40 @@
         <el-button type="primary" icon="el-icon-search" size="mini" @click="handleSearchTags(queryTagParams.name)">搜索</el-button>
         <el-button type="primary" icon="el-icon-plus" size="mini" @click="cancelSearchTags">重置</el-button>
       </div>
-      <div v-for="item in tagGroupList" :key="item.id"  >
+      <div v-for="item in tagGroupList" :key="item.id">
         <div style="font-size: 20px;margin-top: 20px;margin-bottom: 20px;">
           <span class="name-background">{{ item.name }}</span>
         </div>
-        <div class="tag-container">
-          <a
-            v-for="tagItem in item.tag"
-            class="tag-box"
-            @click="tagSelection(tagItem)"
-            :class="{ 'tag-selected': tagItem.isSelected }"
-          >
-            {{ tagItem.name }}
-          </a>
+
+        <!-- 添加外层滚动容器 -->
+        <div class="scroll-wrapper">
+          <div class="tag-container">
+            <a
+              v-for="tagItem in item.tag"
+              class="tag-box"
+              @click="tagSelection(tagItem)"
+              :class="{ 'tag-selected': tagItem.isSelected }"
+            >
+              {{ tagItem.name }}
+            </a>
+          </div>
         </div>
       </div>
+<!--      <div v-for="item in tagGroupList" :key="item.id"  >-->
+<!--        <div style="font-size: 20px;margin-top: 20px;margin-bottom: 20px;">-->
+<!--          <span class="name-background">{{ item.name }}</span>-->
+<!--        </div>-->
+<!--        <div class="tag-container">-->
+<!--          <a-->
+<!--            v-for="tagItem in item.tag"-->
+<!--            class="tag-box"-->
+<!--            @click="tagSelection(tagItem)"-->
+<!--            :class="{ 'tag-selected': tagItem.isSelected }"-->
+<!--          >-->
+<!--            {{ tagItem.name }}-->
+<!--          </a>-->
+<!--        </div>-->
+<!--      </div>-->
 
       <pagination
         v-show="tagTotal>0"
@@ -494,15 +515,17 @@
           <div style="font-size: 20px;margin-top: 20px;margin-bottom: 20px;">
             <span class="name-background">{{ item.name }}</span>
           </div>
-          <div class="tag-container">
-            <a
-              v-for="tagItem in item.tag"
-              class="tag-box"
-              @click="tagSelection(tagItem)"
-              :class="{ 'tag-selected': tagItem.isSelected }"
-            >
-              {{ tagItem.name }}
-            </a>
+          <div class="scroll-wrapper">
+            <div class="tag-container">
+              <a
+                v-for="tagItem in item.tag"
+                class="tag-box"
+                @click="tagSelection(tagItem)"
+                :class="{ 'tag-selected': tagItem.isSelected }"
+              >
+                {{ tagItem.name }}
+              </a>
+            </div>
           </div>
         </div>
       </el-form>
@@ -530,15 +553,17 @@
           <div style="font-size: 20px;margin-top: 20px;margin-bottom: 20px;">
             <span class="name-background">{{ item.name }}</span>
           </div>
-          <div class="tag-container">
-            <a
-              v-for="tagItem in item.tag"
-              class="tag-box"
-              @click="tagSelection(tagItem)"
-              :class="{ 'tag-selected': tagItem.isSelected }"
-            >
-              {{ tagItem.name }}
-            </a>
+          <div class="scroll-wrapper">
+            <div class="tag-container">
+              <a
+                v-for="tagItem in item.tag"
+                class="tag-box"
+                @click="tagSelection(tagItem)"
+                :class="{ 'tag-selected': tagItem.isSelected }"
+              >
+                {{ tagItem.name }}
+              </a>
+            </div>
           </div>
         </div>
       </el-form>
@@ -814,7 +839,7 @@ export default {
 
       queryTagParams:{
         pageNum: 1,
-        pageSize: 10,
+        pageSize: 5,
         total:0,
         name:null,
         corpId:null,
@@ -1014,10 +1039,21 @@ export default {
 
     handleSearchTags(name){
 
-      searchTags({name:name,corpId:this.queryParams.corpId}).then(response => {
+      if (!name){
+        return this.$message.error("请输入要搜索的标签")
+      }
+
+      this.queryTagParams.name=name;
+      this.queryTagParams.corpId=this.queryParams.corpId;
+
+      searchTags(this.queryTagParams).then(response => {
         this.tagGroupList = response.rows;
       });
 
+      // searchTags({name:name,corpId:this.queryParams.corpId}).then(response => {
+      //   this.tagGroupList = response.rows;
+      // });
+
     },
 
     handleGetMyQwUserList(){
@@ -1046,7 +1082,7 @@ export default {
 
       this.queryTagParams= {
         pageNum: 1,
-        pageSize: 10,
+        pageSize: 5,
         total:0,
         name:null,
       };
@@ -1746,4 +1782,20 @@ export default {
   margin-left: 10px;
   vertical-align: bottom;
 }
+
+/* 新增的滚动容器样式(不影响原有样式) */
+.scroll-wrapper {
+  max-height: 130px; /* 大约三行的高度 */
+  overflow-y: auto;  /* 垂直滚动 */
+  padding-right: 5px; /* 为滚动条留出空间 */
+}
+
+/* 美化滚动条(可选) */
+.scroll-wrapper::-webkit-scrollbar {
+  width: 6px;
+}
+.scroll-wrapper::-webkit-scrollbar-thumb {
+  background: rgba(0, 0, 0, 0.2);
+  border-radius: 3px;
+}
 </style>

+ 1 - 1
src/views/qw/externalContactTransfer/index.vue

@@ -312,7 +312,7 @@ export default {
       // 查询参数
       queryParams: {
         pageNum: 1,
-        pageSize: 500,
+        pageSize: 300,
         userId: null,
         externalUserId: null,
         name: null,

+ 38 - 11
src/views/qw/groupMsg/index.vue

@@ -369,15 +369,18 @@
           <div style="font-size: 20px;margin-top: 20px;margin-bottom: 20px;">
             <span class="name-background">{{ item.name }}</span>
           </div>
-          <div class="tag-container">
-            <a
-              v-for="tagItem in item.tag"
-              class="tag-box"
-              @click="tagSelection(tagItem)"
-              :class="{ 'tag-selected': tagItem.isSelected }"
-            >
-              {{ tagItem.name }}
-            </a>
+          <!-- 添加外层滚动容器 -->
+          <div class="scroll-wrapper">
+            <div class="tag-container">
+              <a
+                v-for="tagItem in item.tag"
+                class="tag-box"
+                @click="tagSelection(tagItem)"
+                :class="{ 'tag-selected': tagItem.isSelected }"
+              >
+                {{ tagItem.name }}
+              </a>
+            </div>
           </div>
         </div>
         <pagination
@@ -676,7 +679,7 @@ export default {
 
       queryTagParams:{
         pageNum: 1,
-        pageSize: 10,
+        pageSize: 5,
         total:0,
         name:null,
         corpId:null,
@@ -906,9 +909,19 @@ export default {
     },
     handleSearchTags(name){
 
-      searchTags({name:name,corpId:this.queryParams.corpId}).then(response => {
+      if (!name){
+        return this.$message.error("请输入要搜索的标签")
+      }
+
+      this.queryTagParams.name=name;
+      this.queryTagParams.corpId=this.queryParams.corpId;
+
+      searchTags(this.queryTagParams).then(response => {
         this.tagGroupList = response.rows;
       });
+      // searchTags({name:name,corpId:this.queryParams.corpId}).then(response => {
+      //   this.tagGroupList = response.rows;
+      // });
 
     },
     cancelSearchTags(){
@@ -1619,5 +1632,19 @@ export default {
   overflow-y: auto; /* 内容超出时显示滚动条 */
   line-height: 1.5em; /* 行高设置,确保每行高度一致 */
 }
+/* 新增的滚动容器样式(不影响原有样式) */
+.scroll-wrapper {
+  max-height: 130px; /* 大约三行的高度 */
+  overflow-y: auto;  /* 垂直滚动 */
+  padding-right: 5px; /* 为滚动条留出空间 */
+}
 
+/* 美化滚动条(可选) */
+.scroll-wrapper::-webkit-scrollbar {
+  width: 6px;
+}
+.scroll-wrapper::-webkit-scrollbar-thumb {
+  background: rgba(0, 0, 0, 0.2);
+  border-radius: 3px;
+}
 </style>

+ 41 - 10
src/views/qw/sop/addSop.vue

@@ -394,16 +394,29 @@
           <div style="font-size: 20px;margin-top: 20px;margin-bottom: 20px;">
             <span class="name-background">{{ item.name }}</span>
           </div>
-          <div class="tag-container">
-            <a
-              v-for="tagItem in item.tag"
-              class="tag-box"
-              @click="tagSelection(tagItem)"
-              :class="{ 'tag-selected': tagItem.isSelected }"
-            >
-              {{ tagItem.name }}
-            </a>
+          <!-- 添加外层滚动容器 -->
+          <div class="scroll-wrapper">
+            <div class="tag-container">
+              <a
+                v-for="tagItem in item.tag"
+                class="tag-box"
+                @click="tagSelection(tagItem)"
+                :class="{ 'tag-selected': tagItem.isSelected }"
+              >
+                {{ tagItem.name }}
+              </a>
+            </div>
           </div>
+<!--          <div class="tag-container">-->
+<!--            <a-->
+<!--              v-for="tagItem in item.tag"-->
+<!--              class="tag-box"-->
+<!--              @click="tagSelection(tagItem)"-->
+<!--              :class="{ 'tag-selected': tagItem.isSelected }"-->
+<!--            >-->
+<!--              {{ tagItem.name }}-->
+<!--            </a>-->
+<!--          </div>-->
         </div>
 
         <pagination
@@ -487,7 +500,7 @@ export default {
 
       queryTagParams: {
         pageNum: 1,
-        pageSize: 10,
+        pageSize: 5,
         total: 0,
         name: null,
         corpId: null,
@@ -613,6 +626,9 @@ export default {
 
     handleSearchTags() {
 
+      if (!this.queryTagParams.name){
+        return this.$message.error("请输入要搜索的标签")
+      }
       searchTags(this.queryTagParams).then(response => {
         this.tagGroupList = response.rows;
         this.total = response.total;
@@ -1233,4 +1249,19 @@ export default {
   overflow-y: auto; /* 内容超出时显示滚动条 */
   line-height: 1.5em; /* 行高设置,确保每行高度一致 */
 }
+/* 新增的滚动容器样式(不影响原有样式) */
+.scroll-wrapper {
+  max-height: 130px; /* 大约三行的高度 */
+  overflow-y: auto;  /* 垂直滚动 */
+  padding-right: 5px; /* 为滚动条留出空间 */
+}
+
+/* 美化滚动条(可选) */
+.scroll-wrapper::-webkit-scrollbar {
+  width: 6px;
+}
+.scroll-wrapper::-webkit-scrollbar-thumb {
+  background: rgba(0, 0, 0, 0.2);
+  border-radius: 3px;
+}
 </style>

文件差異過大導致無法顯示
+ 371 - 355
src/views/qw/sop/deptSop.vue


文件差異過大導致無法顯示
+ 370 - 385
src/views/qw/sop/mySop.vue


+ 302 - 279
src/views/qw/sopUserLogsInfo/sopUserLogsInfoDetails.vue

@@ -1,20 +1,26 @@
 <template>
   <div class="app-container">
-    <Tip :title="'搜索【客户备注】【标签】【进线时间】 只能搜索/筛选出 【当前页】的数据)【可以用客户id来搜(客户id来源-》企微/我的企微客户-》列表的企微客户ID)'" />
-    <Tip :title="'【一键群发】:用于给 选中的 客户 发送插件信息'" />
-    <Tip :title="'【批量修改客户营期】:选中 相应的客户 修改到 想进的相应的营期'" />
-    <Tip :title="'【官方群发许可】:只有这里显示为【是】的,才能通过模板中的 官方群发 来发送(允许条件是 客户点击过【非官方群发】发送的课程!)'" />
-
+    <el-alert
+      title="注意事项"
+      type="warning"
+      :closable="false"
+      show-icon>
+      <template #title>
+              <span style="font-size: 20px; line-height: 1.5;">
+                    搜索【客户备注】【标签】【进线时间】 只能搜索/筛选出 【当前页】的数据)【可以用客户id来搜(客户id来源-》企微/我的企微客户-》列表的企微客户ID)】
+              </span>
+      </template>
+    </el-alert>
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="100px">
-<!--      <el-form-item label="企微员工账号" prop="qwUserId">-->
-<!--        <el-input-->
-<!--          v-model="queryParams.qwUserId"-->
-<!--          placeholder="请输入企微员工账号"-->
-<!--          clearable-->
-<!--          size="small"-->
-<!--          @keyup.enter.native="handleQuery"-->
-<!--        />-->
-<!--      </el-form-item>-->
+      <!--      <el-form-item label="企微员工账号" prop="qwUserId">-->
+      <!--        <el-input-->
+      <!--          v-model="queryParams.qwUserId"-->
+      <!--          placeholder="请输入企微员工账号"-->
+      <!--          clearable-->
+      <!--          size="small"-->
+      <!--          @keyup.enter.native="handleQuery"-->
+      <!--        />-->
+      <!--      </el-form-item>-->
       <el-form-item label="客户名称" prop="externalUserName">
         <el-input
           v-model="queryParams.externalUserName"
@@ -33,14 +39,31 @@
           @keyup.enter.native="handleQuery"
         />
       </el-form-item>
+      <el-form-item label="客户id" prop="externalId">
+        <el-input
+          v-model="queryParams.externalId"
+          placeholder="请输入企微客户id"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="进线时间" prop="entryTime" v-if="queryParams.filterMode == 1">
+        <el-date-picker clearable size="small"
+                        v-model="queryParams.entryTime"
+                        type="date"
+                        value-format="yyyy-MM-dd"
+                        placeholder="选择营期时间">
+        </el-date-picker>
+      </el-form-item>
       <el-form-item label="标签" prop="tagIds">
-<!--        <el-select v-model="selectTags" remote multiple placeholder="请选择" filterable  style="width: 100%;">-->
-<!--          <el-option-->
-<!--            v-for="dict in tagList"-->
-<!--            :label="dict.name"-->
-<!--            :value="dict.tagId">-->
-<!--          </el-option>-->
-<!--        </el-select>-->
+        <!--        <el-select v-model="selectTags" remote multiple placeholder="请选择" filterable  style="width: 100%;">-->
+        <!--          <el-option-->
+        <!--            v-for="dict in tagList"-->
+        <!--            :label="dict.name"-->
+        <!--            :value="dict.tagId">-->
+        <!--          </el-option>-->
+        <!--        </el-select>-->
 
         <div @click="hangleChangeTags()" style="cursor: pointer; border: 1px solid #e6e6e6; background-color: white; overflow: hidden; flex-grow: 1;width: 250px">
           <div style="min-height: 35px; max-height: 200px; overflow-y: auto;">
@@ -62,7 +85,8 @@
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
       </el-form-item>
     </el-form>
-    <el-row :gutter="10" class="mb8">
+
+    <el-row :gutter="10" class="mb8" v-if="queryParams.filterMode == 1">
       <el-col :span="1.5">
         <el-button
           type="warning"
@@ -81,52 +105,54 @@
           size="medium"
           :disabled="multiple"
           @click="handleUpdate"
-          v-if="queryParams.filterMode == 1"
           v-hasPermi="['qw:sopUserLogsInfo:edit']"
         >批量修改客户营期</el-button>
       </el-col>
-
-<!--      <el-col :span="1.5">-->
-<!--        <el-button-->
-<!--          type="success"-->
-<!--          plain-->
-<!--          icon="el-icon-download"-->
-<!--          size="mini"-->
-<!--          :loading="exportLoading"-->
-<!--          @click="handleExport"-->
-<!--          v-hasPermi="['qw:sop:export']"-->
-<!--        >导出</el-button>-->
-<!--      </el-col>-->
     </el-row>
+    <div style="color: #999;font-size: 14px;display: flex;align-items: center;margin-bottom: 5px" v-if="queryParams.filterMode == 1">
+      <i class="el-icon-info"></i>
+      【一键群发】:用于给 选中的 客户 发送插件信息
+    </div>
+    <div style="color: #999;font-size: 14px;display: flex;align-items: center;margin-bottom: 5px" v-if="queryParams.filterMode == 1">
+      <i class="el-icon-info"></i>
+      【批量修改客户营期】:选中 相应的客户 修改到 想进的相应的营期
+    </div>
+    <div style="color: #999;font-size: 14px;display: flex;align-items: center;margin-bottom: 5px" v-if="queryParams.filterMode == 1">
+      <i class="el-icon-info"></i>
+      【官方群发许可】:只有这里显示为【是】的,才能通过模板中的 官方群发 来发送(允许条件是 客户点击过【非官方群发】发送的课程!)
+    </div>
 
     <el-table border v-loading="loading" :data="sopUserLogsInfoList" @selection-change="handleSelectionChange" v-if="queryParams.filterMode == 1">
       <el-table-column type="selection" width="55" align="center" />
       <el-table-column label="编号" align="center" prop="id" width="100"/>
-<!--      <el-table-column label="企微员工账号" align="center" prop="qwUserId" width="100"/>-->
+      <!--      <el-table-column label="企微员工账号" align="center" prop="qwUserId" width="100"/>-->
       <el-table-column label="客户ID" align="center" prop="externalId" width="100"/>
-<!--      <el-table-column label="客户小程序id" align="center" prop="fsUserId" width="100">-->
-<!--        <template slot-scope="scope">-->
-<!--          <el-tag type="success">-->
-<!--            {{ scope.row.fsUserId === 0 || scope.row.fsUserId ===  null ? '无' : scope.row.fsUserId }}-->
-<!--          </el-tag>-->
-<!--        </template>-->
-<!--      </el-table-column>-->
+      <!--      <el-table-column label="客户小程序id" align="center" prop="fsUserId" width="100">-->
+      <!--        <template slot-scope="scope">-->
+      <!--          <el-tag type="success">-->
+      <!--            {{ scope.row.fsUserId === 0 || scope.row.fsUserId === null ? '无' : scope.row.fsUserId }}-->
+      <!--          </el-tag>-->
+      <!--        </template>-->
+      <!--      </el-table-column>-->
       <el-table-column label="客户名称" align="center" prop="externalUserName" />
       <el-table-column label="备注" align="center" prop="remark" />
-      <el-table-column label="客户标签" align="center" prop="tagIds" width="240">
+      <el-table-column label="客户标签" align="center" prop="tagIdsName" width="250px">
         <template slot-scope="scope">
-          <div v-for="name in scope.row.tagIdsName" v-if="scope.row.tagIdsName && scope.row.tagIdsName.length > 0 && scope.row.tagIdsName[0] != '无标签'" style="display: inline;">
+          <div v-for="name in scope.row.tagIdsName" style="display: inline;">
             <el-tag type="success">{{ name }}</el-tag>
           </div>
-          <div v-else>
-            <span style="color: red;">无标签</span>
-          </div>
         </template>
       </el-table-column>
       <el-table-column label="进线时间" align="center" prop="inComTime" width="180"/>
       <el-table-column label="添加日期" align="center" prop="createTime" width="180"/>
       <el-table-column label="添加时间" align="center" prop="crtTime" width="180"/>
       <el-table-column label="修改时间" align="center" prop="updateTime" width="180"/>
+      <!--      <el-table-column label="官方群发许可" align="center" prop="fsUserId" width="70">-->
+      <!--        <template slot-scope="scope">-->
+      <!--          <el-tag v-if="scope.row.fsUserId > 0" type="success">是</el-tag>-->
+      <!--          <el-tag v-else type="danger">否</el-tag>-->
+      <!--        </template>-->
+      <!--      </el-table-column>-->
       <el-table-column label="官方群发许可" align="center" prop="fsUserId" width="70">
         <!-- 表头提示 -->
         <template slot="header">
@@ -149,13 +175,13 @@
       </el-table-column>
       <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="120" fixed="right">
         <template slot-scope="scope">
-<!--          <el-button-->
-<!--            size="mini"-->
-<!--            type="text"-->
-<!--            icon="el-icon-edit"-->
-<!--            @click="handleUpdate(scope.row)"-->
-<!--            v-hasPermi="['qw:sopUserLogsInfo:edit']"-->
-<!--          >修改客户营期</el-button>-->
+          <!--          <el-button-->
+          <!--            size="mini"-->
+          <!--            type="text"-->
+          <!--            icon="el-icon-edit"-->
+          <!--            @click="handleUpdate(scope.row)"-->
+          <!--            v-hasPermi="['qw:sopUserLogsInfo:edit']"-->
+          <!--          >修改客户营期</el-button>-->
           <el-button
             size="mini"
             type="text"
@@ -172,18 +198,15 @@
       <el-table-column label="编号" align="center" prop="id" width="100"/>
       <el-table-column label="客户名称" align="center" prop="name" />
       <el-table-column label="备注" align="center" prop="remark" />
-      <el-table-column label="客户标签" align="center" prop="tagIds" width="240">
+      <el-table-column label="客户标签" align="center" prop="tagIdsName" width="250px">
         <template slot-scope="scope">
-          <div v-for="name in scope.row.tagNames" v-if="scope.row.tagNames && scope.row.tagNames.length > 0 && scope.row.tagNames[0] != '无标签'" style="display: inline;">
+          <div v-for="name in scope.row.tagIdsName" style="display: inline;">
             <el-tag type="success">{{ name }}</el-tag>
           </div>
-          <div v-else>
-            <span style="color: red;">无标签</span>
-          </div>
         </template>
       </el-table-column>
       <el-table-column label="加群时间" align="center" prop="joinTime" width="180"/>
-      <el-table-column label="进线时间" align="center" prop="inComTime" width="180"/>
+      <!--      <el-table-column label="进线时间" align="center" prop="inComTime" width="180"/>-->
     </el-table>
 
     <pagination-more
@@ -195,200 +218,200 @@
     />
 
     <el-dialog :title="sendMsgOpen.title" :visible.sync="sendMsgOpen.open"  width="1000px" append-to-body>
-        <el-form ref="msgForm" :model="msgForm" :rules="msgRules" label-width="100px">
-          <el-form-item label="选择课程">
-            <el-select  v-model="msgForm.courseId" placeholder="请选择课程" style=" margin-right: 10px;" size="mini" remote  filterable  @change="courseChange()">
-              <el-option
-                v-for="dict in courseList"
-                :key="dict.dictValue"
-                :label="dict.dictLabel"
-                :value="parseInt(dict.dictValue)"
-              />
-            </el-select>
-            <el-select  v-model="msgForm.videoId" placeholder="请选择小节" size="mini" style=" margin-right: 10px;" remote  filterable @change="videoIdChange()"  >
-              <el-option
-                v-for="dict in videoList"
-                :key="dict.dictValue"
-                :label="dict.dictLabel"
-                :value="parseInt(dict.dictValue)"
-              />
-            </el-select>
-            <el-select  v-model="msgForm.courseType" placeholder="请选择消息类型" size="mini" style=" margin-right: 10px;">
-              <el-option
-                v-for="dict in sysFsSopWatchStatus"
-                :key="dict.dictValue"
-                :label="dict.dictLabel"
-                :value="parseInt(dict.dictValue)"
-              />
-            </el-select>
-          </el-form-item>
-          <el-form-item label="规则" prop="setting"  >
-            <div v-for="(item, index) in setting" :key="index" style="background-color: #fdfdfd; border: 1px solid #e6e6e6; margin-bottom: 20px;">
-              <el-row>
-                <el-col :span="22">
-                  <el-form :model="item" label-width="70px">
-                    <el-form-item label="内容类别" style="margin: 2%">
-                      <el-radio-group  v-model="item.contentType">
-                        <el-radio   :label="item.dictValue" v-for="item in sysQwSopAiContentType"  :key="item.dictLabel" @change="handleContentTypeChange()">{{item.dictLabel}}</el-radio>
-                      </el-radio-group>
-                    </el-form-item>
-                    <el-form-item label="内容" style="margin-bottom: 2%" >
-                      <el-input
-                        v-if="item.contentType == 1"
-                        v-model="item.value"
-                        type="textarea"
-                        :rows="3"
-                        placeholder="内容"
-                        style="width: 90%; margin-top: 10px;"
-                        @keydown.native="handleKeydown($event, index)"
-                        :ref="`textarea-${index}`"
-                      >
-                      </el-input>
-                      <el-link
-                        v-if="item.contentType == 1"
-                        type="primary"
-                        @click="toggleSalesCall(index)"
-                        style="margin-top: 10px;"
-                      >
-                        {{ item.isSalesCallAdded ? '移除#销售称呼#' : '添加#销售称呼#' }}
-                      </el-link>
-                      <el-link
-                        v-if="item.contentType == 1"
-                        type="primary"
-                        @click="toggleSalesCallCustomer(index)"
-                        style="margin-top: 10px;margin-left: 2%"
-                      >
-                        {{ item.isSalesCallCustomerAdded ? '移除#客户称呼#' : '添加#客户称呼#' }}
-                      </el-link>
-
-
-                      <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 ">
-                        <el-card class="box-card">
-                          <el-form-item label="链接标题:"  label-width="100px">
-                            <el-input v-model="item.linkTitle" placeholder="请输入链接标题" style="width: 90%;"/>
-                          </el-form-item>
-                          <el-form-item label="链接描述:"   label-width="100px" >
-                            <el-input type="textarea" :rows="3" v-model="item.linkDescribe" placeholder="请输入链接描述" style="width: 90%;margin-top: 1%;"/>
-                          </el-form-item>
-                          <el-form-item label="链接封面:"   label-width="100px">
-                            <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-form-item>
-                        </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='wx73f85f8d62769119' " 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 ">
-
-                        <el-form-item label="上传文件:" prop="fileUrl" label-width="100px">
-                          <el-upload
-                            v-model="item.fileUrl"
-                            class="avatar-uploader"
-                            :action="uploadUrl"
-                            :show-file-list="false"
-                            :on-success="(res, file) => handleAvatarSuccessFile(res, file, item)"
-                            :before-upload="beforeAvatarUploadFile">
-                            <i class="el-icon-plus avatar-uploader-icon"></i>
-                          </el-upload>
-                          <el-link v-if="item.fileUrl" type="primary" :href="downloadUrl(item.fileUrl)" download>
-                            {{item.fileUrl}}
-                          </el-link>
+      <el-form ref="msgForm" :model="msgForm" :rules="msgRules" label-width="100px">
+        <el-form-item label="选择课程">
+          <el-select  v-model="msgForm.courseId" placeholder="请选择课程" style=" margin-right: 10px;" size="mini" remote  filterable  @change="courseChange()">
+            <el-option
+              v-for="dict in courseList"
+              :key="dict.dictValue"
+              :label="dict.dictLabel"
+              :value="parseInt(dict.dictValue)"
+            />
+          </el-select>
+          <el-select  v-model="msgForm.videoId" placeholder="请选择小节" size="mini" style=" margin-right: 10px;" remote  filterable @change="videoIdChange()"  >
+            <el-option
+              v-for="dict in videoList"
+              :key="dict.dictValue"
+              :label="dict.dictLabel"
+              :value="parseInt(dict.dictValue)"
+            />
+          </el-select>
+          <el-select  v-model="msgForm.courseType" placeholder="请选择消息类型" size="mini" style=" margin-right: 10px;">
+            <el-option
+              v-for="dict in sysFsSopWatchStatus"
+              :key="dict.dictValue"
+              :label="dict.dictLabel"
+              :value="parseInt(dict.dictValue)"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="规则" prop="setting"  >
+          <div v-for="(item, index) in setting" :key="index" style="background-color: #fdfdfd; border: 1px solid #e6e6e6; margin-bottom: 20px;">
+            <el-row>
+              <el-col :span="22">
+                <el-form :model="item" label-width="70px">
+                  <el-form-item label="内容类别" style="margin: 2%">
+                    <el-radio-group  v-model="item.contentType">
+                      <el-radio   :label="item.dictValue" v-for="item in sysQwSopAiContentType"  @change="handleContentTypeChange()">{{item.dictLabel}}</el-radio>
+                    </el-radio-group>
+                  </el-form-item>
+                  <el-form-item label="内容" style="margin-bottom: 2%" >
+                    <el-input
+                      v-if="item.contentType == 1"
+                      v-model="item.value"
+                      type="textarea"
+                      :rows="3"
+                      placeholder="内容"
+                      style="width: 90%; margin-top: 10px;"
+                      @keydown.native="handleKeydown($event, index)"
+                      :ref="`textarea-${index}`"
+                    >
+                    </el-input>
+                    <el-link
+                      v-if="item.contentType == 1"
+                      type="primary"
+                      @click="toggleSalesCall(index)"
+                      style="margin-top: 10px;"
+                    >
+                      {{ item.isSalesCallAdded ? '移除#销售称呼#' : '添加#销售称呼#' }}
+                    </el-link>
+                    <el-link
+                      v-if="item.contentType == 1"
+                      type="primary"
+                      @click="toggleSalesCallCustomer(index)"
+                      style="margin-top: 10px;margin-left: 2%"
+                    >
+                      {{ item.isSalesCallCustomerAdded ? '移除#客户称呼#' : '添加#客户称呼#' }}
+                    </el-link>
+
+
+                    <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 ">
+                      <el-card class="box-card">
+                        <el-form-item label="链接标题:"  label-width="100px">
+                          <el-input v-model="item.linkTitle" placeholder="请输入链接标题" style="width: 90%;"/>
                         </el-form-item>
-
-                      </div>
-
-                      <div v-if="item.contentType == 6 ">
-                        <el-form-item label="上传视频:" prop="videoUrl" label-width="100px">
-                          <el-upload
-                            v-model="item.videoUrl"
-                            class="avatar-uploader"
-                            :action="uploadUrl"
-                            :show-file-list="false"
-                            :on-success="(res, file) => handleAvatarSuccessVideo(res, file, item)"
-                            :before-upload="beforeAvatarUploadVideo">
-                            <i class="el-icon-plus avatar-uploader-icon"></i>
-                          </el-upload>
-                          <video v-if="item.videoUrl"
-                                 :src="item.videoUrl"
-                                 controls style="width: 200px;height: 100px">
-                          </video>
+                        <el-form-item label="链接描述:"   label-width="100px" >
+                          <el-input type="textarea" :rows="3" v-model="item.linkDescribe" placeholder="请输入链接描述" style="width: 90%;margin-top: 1%;"/>
+                        </el-form-item>
+                        <el-form-item label="链接封面:"   label-width="100px">
+                          <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-form-item>
+                      </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>
-                      </div>
-                      <div v-if="item.contentType == 7 ">
-                        <el-input
-                          v-model="item.value"
-                          type="textarea" :rows="3" maxlength="66" show-word-limit
-                          placeholder="输入要转为语音的内容" style="width: 90%;margin-top: 10px;"
-                          @input="handleInputVideoText(item.value,item)"/>
-                      </div>
-                      <div v-if="item.contentType == 8">
-
-                      </div>
-
-                    </el-form-item>
-
-                    <el-form-item label="添加短链" v-if="item.contentType == 1 "  >
-                      <el-tooltip content="请先根据课程选定课程小节之后再添加" effect="dark" :disabled="!!msgForm.videoId">
-                        <el-switch
-                          v-model="item.isBindUrl"
-                          :disabled="!msgForm.videoId"
-                          active-color="#13ce66"
-                          inactive-color="#DCDFE6"
-                          active-value="1"
-                          inactive-value="2">
-                        </el-switch>
-                      </el-tooltip>
-
-                      <span v-if="item.isBindUrl == '1'" style="margin-left: 10px; color: #13ce66">添加URL</span>
-                      <span v-if="item.isBindUrl == '2'" style="margin-left: 10px; color: #b1b4ba">不加URL</span>
-                    </el-form-item>
-                    <el-form-item label="课节过期时间" v-if="item.isBindUrl == '1'
+                        <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='wx73f85f8d62769119' " 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 ">
+
+                      <el-form-item label="上传文件:" prop="fileUrl" label-width="100px">
+                        <el-upload
+                          v-model="item.fileUrl"
+                          class="avatar-uploader"
+                          :action="uploadUrl"
+                          :show-file-list="false"
+                          :on-success="(res, file) => handleAvatarSuccessFile(res, file, item)"
+                          :before-upload="beforeAvatarUploadFile">
+                          <i class="el-icon-plus avatar-uploader-icon"></i>
+                        </el-upload>
+                        <el-link v-if="item.fileUrl" type="primary" :href="downloadUrl(item.fileUrl)" download>
+                          {{item.fileUrl}}
+                        </el-link>
+                      </el-form-item>
+
+                    </div>
+
+                    <div v-if="item.contentType == 6 ">
+                      <el-form-item label="上传视频:" prop="videoUrl" label-width="100px">
+                        <el-upload
+                          v-model="item.videoUrl"
+                          class="avatar-uploader"
+                          :action="uploadUrl"
+                          :show-file-list="false"
+                          :on-success="(res, file) => handleAvatarSuccessVideo(res, file, item)"
+                          :before-upload="beforeAvatarUploadVideo">
+                          <i class="el-icon-plus avatar-uploader-icon"></i>
+                        </el-upload>
+                        <video v-if="item.videoUrl"
+                               :src="item.videoUrl"
+                               controls style="width: 200px;height: 100px">
+                        </video>
+                      </el-form-item>
+                    </div>
+                    <div v-if="item.contentType == 7 ">
+                      <el-input
+                        v-model="item.value"
+                        type="textarea" :rows="3" maxlength="66" show-word-limit
+                        placeholder="输入要转为语音的内容" style="width: 90%;margin-top: 10px;"
+                        @input="handleInputVideoText(item.value,item)"/>
+                    </div>
+                    <div v-if="item.contentType == 8">
+
+                    </div>
+
+                  </el-form-item>
+
+                  <el-form-item label="添加短链" v-if="item.contentType == 1 "  >
+                    <el-tooltip content="请先根据课程选定课程小节之后再添加" effect="dark" :disabled="!!msgForm.videoId">
+                      <el-switch
+                        v-model="item.isBindUrl"
+                        :disabled="!msgForm.videoId"
+                        active-color="#13ce66"
+                        inactive-color="#DCDFE6"
+                        active-value="1"
+                        inactive-value="2">
+                      </el-switch>
+                    </el-tooltip>
+
+                    <span v-if="item.isBindUrl == '1'" style="margin-left: 10px; color: #13ce66">添加URL</span>
+                    <span v-if="item.isBindUrl == '2'" style="margin-left: 10px; color: #b1b4ba">不加URL</span>
+                  </el-form-item>
+                  <el-form-item label="课节过期时间" v-if="item.isBindUrl == '1'
                                                           && item.contentType != 2
                                                           && item.contentType != 5
                                                           && item.contentType != 6
                                                           && item.contentType != 8"
-                                  style="margin-top: 1%" label-width="100px">
-                      <el-row>
-                        <el-input-number  v-model="item.expiresDays"  :min="1" :max="100" ></el-input-number>
-                        (天)
-                      </el-row>
-                      <el-row>
-                        <span class="tip">填写0或不填时,默认为系统配置的默认时间</span>
-                      </el-row>
-                    </el-form-item>
-                  </el-form>
-                </el-col>
-                <el-col :span="1" :offset="1">
-                  <i class="el-icon-delete" @click="delSetList(index)" style="margin-top: 20px;" v-if="setting.length>1"></i>
-                </el-col>
-              </el-row>
-            </div>
-            <el-link type="primary" class="el-icon-plus" :underline="false" @click='addSetList()'  >添加内容</el-link>
-
-          </el-form-item>
-        </el-form>
-        <div slot="footer" class="dialog-footer">
-          <el-button type="primary" @click="submitMsgForm">确 定</el-button>
-          <el-button @click="cancelMsgForm">取 消</el-button>
-        </div>
+                                style="margin-top: 1%" label-width="100px">
+                    <el-row>
+                      <el-input-number  v-model="item.expiresDays"  :min="1" :max="100" ></el-input-number>
+                      (天)
+                    </el-row>
+                    <el-row>
+                      <span class="tip">填写0或不填时,默认为系统配置的默认时间</span>
+                    </el-row>
+                  </el-form-item>
+                </el-form>
+              </el-col>
+              <el-col :span="1" :offset="1">
+                <i class="el-icon-delete" @click="delSetList(index)" style="margin-top: 20px;" v-if="setting.length>1"></i>
+              </el-col>
+            </el-row>
+          </div>
+          <el-link type="primary" class="el-icon-plus" :underline="false" @click='addSetList()'  >添加内容</el-link>
+
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitMsgForm">确 定</el-button>
+        <el-button @click="cancelMsgForm">取 消</el-button>
+      </div>
     </el-dialog>
 
     <!-- 添加或修改sopUserLogsInfo对话框 -->
@@ -396,10 +419,10 @@
       <el-form ref="updateLogsInfoFrom" :model="updateLogsInfoFrom" :rules="batchRules" label-width="120px">
         <el-form-item label="选择营期时间" prop="paramTime">
           <el-date-picker clearable size="small"
-            v-model="updateLogsInfoFrom.paramTime"
-            type="date"
-            value-format="yyyy-MM-dd"
-            placeholder="选择营期时间">
+                          v-model="updateLogsInfoFrom.paramTime"
+                          type="date"
+                          value-format="yyyy-MM-dd"
+                          placeholder="选择营期时间">
           </el-date-picker>
         </el-form-item>
       </el-form>
@@ -465,17 +488,16 @@ import {addCourseFinishTemp, updateCourseFinishTemp} from "@/api/course/courseFi
 import {allListTagGroup} from "@/api/qw/tagGroup";
 import {listTag} from "@/api/qw/tag";
 import {searchTags} from "../../../api/qw/tag";
-import Tip from "../../../components/Tip/index.vue";
-import PaginationMore from "../../../components/PaginationMore/index.vue";
+import PaginationMore from '@/components/PaginationMore/index.vue'
 
 export default {
   name: "sopUserLogsInfoDetails",
-  components: {PaginationMore, Tip, ImageUpload},
+  components: { PaginationMore, ImageUpload},
   data() {
     return {
       //上传语音的遮罩层
       voiceLoading :false,
-      uploadUrl:process.env.VUE_APP_BASE_API+"/common/uploadOSS",
+      uploadUrl:process.env.VUE_APP_BASE_API+"/common/uploadOSS2",
       uploadUrlByVoice:process.env.VUE_APP_BASE_API+"/common/uploadOSSByHOOKVoice",
       // 遮罩层
       loading: true,
@@ -519,6 +541,7 @@ export default {
         fsUserId: null,
         externalUserName: null,
         createTime: null,
+        entryTime: null,
       },
 
       tagGroupList: [],
@@ -1121,8 +1144,8 @@ export default {
     },
 
     /**
-    * 一键群发
-    */
+     * 一键群发
+     */
     handleSendMsg(){
       this.sendMsgOpen.open=true;
       this.sendMsgOpen.ids=this.ids;
@@ -1148,7 +1171,7 @@ export default {
             return this.$message.error("请添加规则")
           }
           if (this.msgForm.courseId===null || this.msgForm.courseId===''){
-           return this.$message.error("课程不能为空")
+            return this.$message.error("课程不能为空")
           }
 
           if (this.msgForm.videoId===null || this.msgForm.videoId===''){
@@ -1264,30 +1287,30 @@ export default {
     handleDelete(row) {
       const ids = row.id || this.ids;
       this.$confirm('是否确认删除sopUserLogsInfo编号为"' + ids + '"的数据项?', "警告", {
-          confirmButtonText: "确定",
-          cancelButtonText: "取消",
-          type: "warning"
-        }).then(function() {
-          return delSopUserLogsInfo(ids);
-        }).then(() => {
-          this.getList();
-          this.msgSuccess("删除成功");
-        }).catch(() => {});
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(function() {
+        return delSopUserLogsInfo(ids);
+      }).then(() => {
+        this.getList();
+        this.msgSuccess("删除成功");
+      }).catch(() => {});
     },
     /** 导出按钮操作 */
     handleExport() {
       const queryParams = this.queryParams;
       this.$confirm('是否确认导出所有营期数据项?', "警告", {
-          confirmButtonText: "确定",
-          cancelButtonText: "取消",
-          type: "warning"
-        }).then(() => {
-          this.exportLoading = true;
-          return exportSopUserLogsInfo(queryParams);
-        }).then(response => {
-          this.download(response.msg);
-          this.exportLoading = false;
-        }).catch(() => {});
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        this.exportLoading = true;
+        return exportSopUserLogsInfo(queryParams);
+      }).then(response => {
+        this.download(response.msg);
+        this.exportLoading = false;
+      }).catch(() => {});
     }
   }
 };

+ 2 - 2
src/views/statistics/section/channel.vue

@@ -344,8 +344,8 @@ export default {
     /** 搜索按钮操作 */
     handleQuery() {
       console.log(this.selectedCompanyList == null || this.selectedCompanyList.length < 0)
-      if(this.selectedCompanyList == null || this.selectedCompanyList.length <= 0) {
-        this.$message.error("公司和时间为必选!");
+      if (!this.dateRange || this.dateRange.length !== 2) {
+        this.$message.warning("请选择时间范围");
         return;
       }
       this.queryParams.pageNum = 1;

+ 2 - 2
src/views/statistics/section/index.vue

@@ -325,8 +325,8 @@ export default {
     },
     /** 搜索按钮操作 */
     handleQuery() {
-      if(this.selectedCompanyList == null || this.selectedCompanyList.length <= 0) {
-        this.$message.error("公司和时间为必选!");
+      if (!this.dateRange || this.dateRange.length !== 2) {
+        this.$message.warning("请选择时间范围");
         return;
       }
       this.queryParams.pageNum = 1;

+ 43 - 36
src/views/statistics/section/inline.vue

@@ -131,8 +131,10 @@ import {
   getDeptData,
   exportSellerData, listInlineList,exportInlineList
 } from '@/api/system/employeeStats'
+import {getCompanyList} from "@/api/company/company";
 import {getUserList} from "@/api/company/companyUser";
 import SelectTree from "@/components/TreeSelect/index.vue";
+import { exportLineCustomer } from '@/api/crm/customer'
 
 export default {
   name: "EmployeeStats",
@@ -211,48 +213,48 @@ export default {
           return;
         }
 
-        const values = data.map(item => Number(item[column.property]));
+        // 定义所有需要求和的列
+        const sumColumns = [
+          'periodPersonNum', 'periodNum', 'sendNum', 'notRegisteredNum', 'registeredNum',
+          'interruptNum', 'completedNum', 'qwRepeatNum', 'userRepeatNum', 'blackNum', 'deletedNum',
+          'orderNum', 'orderMoneyTotal', 'redPackageMoneyTotal', 'callNum', 'receivePassNum',
+          'receiveNotNum', 'callTimeTotal', 'remindPendingNum', 'remindProcessedNum',
+          // 增加其他所有需要计算的数值列
+          'deleteNum', 'lineNum', 'orderTotalNum'
+        ];
 
-        if (['periodPersonNum','periodNum', 'sendNum', 'notRegisteredNum', 'registeredNum',
-        'interruptNum', 'completedNum', 'qwRepeatNum', 'userRepeatNum','blackNum','deletedNum',
-        'orderNum','orderMoneyTotal','redPackageMoneyTotal','callNum','receivePassNum','receiveNotNum',
-      'callTimeTotal','remindPendingNum','remindProcessedNum'].includes(column.property)) {
-          if (!values.every(value => isNaN(value))) {
-            sums[index] = values.reduce((prev, curr) => {
-              const value = Number(curr);
-              if (!isNaN(value)) {
-                return prev + curr;
-              } else {
-                return prev;
-              }
-            }, 0);
-          } else {
-            sums[index] = 'N/A';
-          }
-          if(['orderMoneyTotal','redPackageMoneyTotal'].includes(column.property)){
+        const rateColumns = ['regRate', 'finishedRate'];
+
+        if (sumColumns.includes(column.property)) {
+          const values = data.map(item => Number(item[column.property]) || 0);
+          sums[index] = values.reduce((prev, curr) => prev + curr, 0);
+
+          if(['orderMoneyTotal', 'redPackageMoneyTotal'].includes(column.property)){
             sums[index] = sums[index].toFixed(2);
           }
         }
-        else if (column.property === 'regRate') {
-          const totalRegistered = data.reduce((sum, item) => sum + (Number(item.registeredNum) || 0), 0);
-          const totalSendNum = data.reduce((sum, item) => sum + (Number(item.sendNum) || 0), 0);
+        else if (rateColumns.includes(column.property)) {
+          if (column.property === 'regRate') {
+            const totalRegistered = data.reduce((sum, item) => sum + (Number(item.registeredNum) || 0), 0);
+            const totalSendNum = data.reduce((sum, item) => sum + (Number(item.sendNum) || 0), 0);
 
-          if (totalSendNum > 0) {
-            const rate = (totalRegistered / totalSendNum * 100).toFixed(2);
-            sums[index] = `${rate}%`;
-          } else {
-            sums[index] = '0.00%';
+            if (totalSendNum > 0) {
+              const rate = (totalRegistered / totalSendNum * 100).toFixed(2);
+              sums[index] = `${rate}%`;
+            } else {
+              sums[index] = '0.00%';
+            }
           }
-        }
-        else if (column.property === 'finishedRate') {
-          const totalCompleted = data.reduce((sum, item) => sum + (Number(item.completedNum) || 0), 0);
-          const totalSendNum = data.reduce((sum, item) => sum + (Number(item.sendNum) || 0), 0);
+          else if (column.property === 'finishedRate') {
+            const totalCompleted = data.reduce((sum, item) => sum + (Number(item.completedNum) || 0), 0);
+            const totalSendNum = data.reduce((sum, item) => sum + (Number(item.sendNum) || 0), 0);
 
-          if (totalSendNum > 0) {
-            const rate = (totalCompleted / totalSendNum * 100).toFixed(2);
-            sums[index] = `${rate}%`;
-          } else {
-            sums[index] = '0.00%';
+            if (totalSendNum > 0) {
+              const rate = (totalCompleted / totalSendNum * 100).toFixed(2);
+              sums[index] = `${rate}%`;
+            } else {
+              sums[index] = '0.00%';
+            }
           }
         }
         else {
@@ -261,7 +263,8 @@ export default {
       });
 
       return sums;
-    },
+    }
+    ,
     handleCompanyUserId(val){
       if(val == null || val === '') {
         this.queryParams.companyUserId = null;
@@ -315,6 +318,10 @@ export default {
     },
     /** 搜索按钮操作 */
     handleQuery() {
+      if (!this.dateRange || this.dateRange.length !== 2) {
+        this.$message.warning("请选择时间范围");
+        return;
+      }
       this.queryParams.pageNum = 1;
       this.getList();
     },

+ 2 - 2
src/views/statistics/section/today.vue

@@ -340,8 +340,8 @@ export default {
     },
     /** 搜索按钮操作 */
     handleQuery() {
-      if(this.selectedCompanyList == null || this.selectedCompanyList.length <= 0) {
-        this.$message.error("公司和时间为必选!");
+      if (!this.dateRange || this.dateRange.length !== 2) {
+        this.$message.warning("请选择时间范围");
         return;
       }
       this.queryParams.pageNum = 1;

部分文件因文件數量過多而無法顯示