Ver Fonte

Merge remote-tracking branch 'origin/master'

吴树波 há 1 semana atrás
pai
commit
1cca58db60

+ 62 - 0
src/api/crm/assist.js

@@ -0,0 +1,62 @@
+import request from '@/utils/request'
+
+// 查询客户员工协作列表
+export function listAssist(query) {
+  return request({
+    url: '/crm/assist/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询客户员工协作详细
+export function getAssist(id) {
+  return request({
+    url: '/crm/assist/' + id,
+    method: 'get'
+  })
+}
+
+// 新增客户员工协作
+export function addAssist(data) {
+  return request({
+    url: '/crm/assist',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改客户员工协作
+export function updateAssist(data) {
+  return request({
+    url: '/crm/assist',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除客户员工协作
+export function delAssist(id) {
+  return request({
+    url: '/crm/assist/' + id,
+    method: 'delete'
+  })
+}
+
+// 删除客户员工协作
+export function remove(data) {
+  return request({
+    url: '/crm/assist/remove',
+    method: 'post',
+    data: data
+  })
+}
+
+// 导出客户员工协作
+export function exportAssist(query) {
+  return request({
+    url: '/crm/assist/export',
+    method: 'get',
+    params: query
+  })
+}

+ 18 - 0
src/api/crm/customer.js

@@ -42,6 +42,16 @@ export function getMyCustomerList(query) {
   })
 }
 
+
+
+export function getMyAssistList(query) {
+  return request({
+    url: '/crm/customer/getMyAssistList',
+    method: 'get',
+    params: query
+  })
+}
+
 export function getCustomerDetails(query) {
   return request({
     url: '/crm/customer/getCustomerDetails/',
@@ -102,6 +112,14 @@ export function assignToUser(data) {
     data: data
   })
 }
+
+export function assistToUser(data) {
+  return request({
+    url: '/crm/customer/assistToUser',
+    method: 'post',
+    data: data
+  })
+}
 export function assignUser(data) {
   return request({
     url: '/crm/customer/assignUser',

+ 17 - 1
src/api/qw/QwWorkTask.js

@@ -17,6 +17,14 @@ export function getQwWorkTask(id) {
   })
 }
 
+export function glList(query) {
+  return request({
+    url: '/qw/qw/QwWorkTask/glList',
+    method: 'get',
+    params: query
+  })
+}
+
 // 新增企微任务看板
 export function addQwWorkTask(data) {
   return request({
@@ -50,4 +58,12 @@ export function exportQwWorkTask(query) {
     method: 'get',
     params: query
   })
-}
+}
+
+export function allListQwWorkTask(query) {
+  return request({
+    url: '/qw/qw/QwWorkTask/allList',
+    method: 'get',
+    params: query
+  })
+}

+ 9 - 7
src/components/LemonUI/components/chatmsg.vue

@@ -195,7 +195,7 @@ export default {
         if (message.type == 'event'){
             // if(this.user.id == message.fromUser.id){}
             unread = 0;
-        } 
+        }
         if (messageList === undefined) {
           //console.log("qxj appendMessage messageList:"+messageList+",message"+JSON.stringify(message));
           conversation.id=message.toContactId;
@@ -208,7 +208,7 @@ export default {
           let hasMsg = messageList.some(({id})=>id == message.id);
           if (hasMsg) return;
           this._addMessage(message, message.toContactId, 1);
-          
+
           conversation.lastContent=this.lastContentRender(message);
           conversation.lastSendTime=message.sendTime;
           if (message.toContactId == this.currentContactId) {
@@ -487,6 +487,7 @@ export default {
       );
     },
     _renderSidebar(children, name, fixedtop) {
+      console.log("_renderSidebar", children)
       return (
         <div
           class="lemon-sidebar"
@@ -536,7 +537,7 @@ export default {
             </div>,
           );
       }
-      
+
       //聊天消息View
       nodes.push(
         <div
@@ -649,6 +650,7 @@ export default {
       lastContentRender[messageType] = render;
     },
     lastContentRender(message) {
+      console.log("msg", message)
       if (!isFunction(lastContentRender[message.type])) {
         console.error(
           `not found '${
@@ -703,7 +705,7 @@ export default {
         editorValue,
         lastContent,
       });
-      
+
       var tempDraft=this.CacheDraft.get(cid);
       //console.log("qxj editorValue:"+editorValue+",tempDraft:"+JSON.stringify(tempDraft)+"lastContent:"+lastContent);
 
@@ -937,7 +939,7 @@ export default {
     initConversations(data) {
       this.conversations = data;
       this.sortConversations();
-      
+
     },
 
     /**
@@ -1028,7 +1030,7 @@ export default {
      */
     updateContact(data) {
       const conversationId = data.conversationId;
-      const index = this.findConversationIndexById(conversationId);  
+      const index = this.findConversationIndexById(conversationId);
       if (index !== -1) {
         // if(isString(data.unread)) {
         //     if (unread.indexOf("+") === 0 || unread.indexOf("-") === 0) {
@@ -1044,7 +1046,7 @@ export default {
     updateContact1(data) {
       const contactId = data.id;
       delete data.id;
-      const index = this.findContactIndexById(contactId);  
+      const index = this.findContactIndexById(contactId);
       if (index !== -1) {
         const { unread } = data;
         if (isString(unread)) {

+ 4 - 1
src/components/LemonUI/components/index.vue

@@ -394,6 +394,9 @@ export default {
         [
           useScopedSlot(this.$scopedSlots["sidebar-message-top"], null, this),
           this.lastMessages.map(contact => {
+            if (contact.type !== 'text' && isFunction(lastContentRender[contact.type])) {
+              contact.lastContent =  lastContentRender[contact.type].call(this, contact);
+            }
             return this._renderContact(
               {
                 contact,
@@ -646,7 +649,7 @@ export default {
         );
         return "";
       }
-      return lastContentRender[message.type].call(this, message);
+      return lastContentRender[message.type].call(this, message.content);
     },
     /**
      * 将字符串内的 EmojiItem.name 替换为 img

+ 29 - 0
src/components/LemonUI/components/message/emotionDynamic.vue

@@ -0,0 +1,29 @@
+<script>
+export default {
+  name: 'lemonMessageEmotionDynamic',
+  inheritAttrs: false,
+  render() {
+    return (
+      <lemon-message-basic
+        class="lemon-message-emotion-dynamic"
+        props={{ ...this.$attrs }}
+        scopedSlots={{
+          content: props => <img src={props.content} />
+        }}
+      />
+    )
+  }
+}
+</script>
+
+<style lang="stylus">
+@import '../../styles/utils/index'
++b(lemon-message-emotion-dynamic)
+  +b(lemon-message)
+    +e(content)
+      width 100px
+      height 100px
+      img
+        width 100%
+        height 100%
+</style>

+ 34 - 6
src/components/LemonUI/components/message/voice.vue

@@ -5,11 +5,11 @@ export default {
   inject: ["IMUI"],
   data() {
     return {
-       
+
     };
   },
   created() {
-    
+
   },
   render() {
     return (
@@ -25,9 +25,18 @@ export default {
     );
   },
    methods: {
-      renderHtml(data){       
-        return <audio block="true" showDuration='false' duration={data.duration} controls src={data.content}  ></audio>;
-        // return <span>{props.content}&nbsp;🔈</span>;
+      renderHtml(data){
+        const {url, content} = JSON.parse(data.content)
+        return <div class="lemon-message-voice-context">
+            <audio block="true" showDuration='false' controls src={url}
+            controlslist='nodownload noplaybackrate'
+            oncontextmenu="return false"/>
+            <div class="lemon-message-voice-context-text">
+              <span>{content}</span>
+              <span class="el-icon-check lemon-message-voice-context-text-transfer">转换完成</span>
+            </div>
+          </div>
+          ;
       }
   }
 };
@@ -38,10 +47,29 @@ export default {
 .lemon-message.lemon-message-voice
   user-select none
   .lemon-message__content
+    background-color unset
     border 0px solid #000
     font-size 12px
     cursor pointer
     &::before
       display none
-
+    .lemon-message-voice-context
+      display flex
+      flex-direction: column
+      audio
+        width 250px
+        height 35px
+        border solid 1px #CCC
+        border-radius 15px
+      .lemon-message-voice-context-text
+        display flex
+        flex-direction: column
+        background-color #FFF
+        padding 5px 10px
+        margin-top 10px
+        border-radius 5px
+        .lemon-message-voice-context-text-transfer
+          margin 10px 0
+          font-size x-small
+          color #999
 </style>

+ 3 - 1
src/components/LemonUI/index.js

@@ -14,6 +14,7 @@ import lemonMessageFile from "./components/message/file";
 import lemonMessageEvent from "./components/message/event";
 import LemonMessageVoice from "./components/message/voice";
 import LemonMessageVideo from "./components/message/video";
+import LemonMessageEmotionDynamic from "./components/message/emotionDynamic.vue";
 
 
 import LemonIMUI from "./components/index";
@@ -39,7 +40,8 @@ const components = [
   lemonMessageEvent,
   LemonMessageVoice,
   LemonMessageVideo,
-  LemonRecords
+  LemonRecords,
+  LemonMessageEmotionDynamic
 ];
 const install = (Vue) => {
   Vue.directive("LemonContextmenu", Contextmenu);

+ 4 - 1
src/components/LemonUI/lastContentRender.js

@@ -13,9 +13,12 @@ export default {
     return "[视频]";
   },
   text(message) {
-    return this.emojiNameToImage(clearHtml(message.content));
+    return this.emojiNameToImage(clearHtml(message));
   },
   event(message){
     return '[通知]';
   },
+  emotionDynamic(message) {
+    return '[自定义表情]';
+  },
 };

+ 2 - 0
src/views/company/components/userSelect.vue

@@ -73,11 +73,13 @@ import {
   importTemplate,
 } from "@/api/company/companyUser";
 import { treeselect } from "@/api/company/companyDept";
+import { status } from "nprogress";
 export default {
   name: "User",
   
   data() {
     return {
+      status:0,
       selectUser:[],
       users:[],
       // 遮罩层

+ 205 - 0
src/views/crm/components/assistUser.vue

@@ -0,0 +1,205 @@
+<template>
+    <div>
+        <el-form ref="assistForm" :model="assistForm"  label-width="120px">
+            <el-form-item label="未添加协作客户" >
+            <span>{{this.noAssistCount}}个</span>
+            </el-form-item>
+            <el-form-item label="未添加协作客户" >
+            <span>{{this.assistCount}}个</span>
+            </el-form-item>
+
+            <el-form-item label="协作人" prop="users">
+                <el-row :gutter="10" class="mb8">
+                    <el-col :span="1.5">
+                        <el-button @click="handleUserSelect">添加协作人</el-button>
+                    </el-col>
+                </el-row>
+                <el-table border  :data="users" >
+                    <el-table-column label="ID" align="center" prop="userId" />
+                    <el-table-column label="员工帐号" align="center" prop="userName" />
+                    <el-table-column label="员工姓名" align="center" prop="nickName" />
+                    <el-table-column label="所属部门" align="center" prop="deptName" />
+                    <el-table-column label="添加数量" align="center"  prop="count" width="150px" >
+                        <template slot-scope="scope">
+                        <div>
+                            <el-input-number ref="stepTxtNum" :min="0" v-model="scope.row.count"  @change="changeVal(scope.row)"   size="mini"   ></el-input-number>
+                        </div>
+                    </template>
+                    </el-table-column>
+                    <el-table-column label="操作"   align="center" fixed="right" class-name="small-padding fixed-width">
+                        <template slot-scope="scope">
+                            <el-button
+                            size="mini"
+                            type="text"
+                            @click="handleRemoveUser(scope.row.$index)"
+                            >删除</el-button>
+                        </template>
+                    </el-table-column>
+                </el-table>
+            </el-form-item>
+        </el-form>
+        <div   class="footer">
+            <el-button type="primary" @click="submitAssistForm">确 定</el-button>
+        </div>
+        <el-dialog :title="userSelect.title" :visible.sync="userSelect.open" width="1000px" append-to-body>
+            <user-select ref="userSelects" @selectUser="selectUser"  ></user-select>
+        </el-dialog>
+    </div>
+</template>
+  
+<script>
+    import { assistToUser } from "@/api/crm/customer";
+    import userSelect from '../../company/components/userSelect.vue';
+    export default {
+        components: {userSelect },
+        name: "visit",
+        data() {
+            return {
+                noAssistCount:0,
+                assistCount:0,
+                customerIds:[],
+                userSelect:{
+                    title:"选择员工",
+                    open:false,
+                },
+                assistForm: {
+                },
+                // 表单校验
+                assistRules: {
+                    
+                },
+                users:[],
+                 
+            };
+        },
+        created() {
+          
+        },
+        methods: {
+            changeVal(row) {
+                this.$forceUpdate();//解决点击计数器失效问题
+                this.computeCount();
+                if(this.assistCount>this.customerIds.length){
+                    this.$nextTick(() => {
+                         row.count=0;
+                         this.computeCount();
+                    });
+                   
+                }
+            },
+            handleRemoveUser(index){
+                this.users.splice(index,1);
+                this.computeCount();
+                this.$refs.userSelects.delUser(index);
+            },
+            selectUser(data){
+                var users=[];
+                var number=parseInt(this.customerIds.length/data.length);
+                data.forEach(element => {
+                    var user={
+                        userId:element.userId,
+                        userName:element.userName,
+                        nickName:element.nickName,
+                        deptName:element.dept.deptName,
+                        nowDayCustomerCount:element.nowDayCustomerCount,
+                        phonenumber:element.phonenumber,
+                        count:number,
+                    }
+                    users.push(user)
+                });
+                this.users=users;
+                this.userSelect.open=false;
+                this.computeCount()
+            },
+            computeCount(){
+                this.assistCount=0;
+                var that=this;
+                this.users.forEach(element => {
+                    that.assistCount+=element.count;
+                });
+                this.noAssistCount=this.customerIds.length-this.assistCount
+            },
+            handleUserSelect(){
+                var that=this;
+                this.userSelect.open=true;
+                setTimeout(() => {
+                    that.$refs.userSelects.getList();
+                }, 500);
+            },
+            init(customerIds){
+                this.customerIds =  customerIds;
+                this.assistCount=0;
+                this.noAssistCount=this.customerIds.length;
+                this.users=[];
+            },
+            /** 提交按钮 */
+            submitAssistForm() {
+                var that=this;
+                this.$refs["assistForm"].validate(valid => {
+                    if (valid) {
+                        var users=[];
+                        var customerIds=[];
+                        var idIndex=0;
+                        var totalAssistCount=0;
+                        console.log("qxj users",JSON.stringify(this.users));
+                        this.users.forEach(element => {
+                            if(element.count>0){
+                                var ids=that.customerIds.slice(idIndex,idIndex+element.count)
+                                console.log("qxj customerIds:"+that.customerIds+" count:"+element.count);
+                                console.log("qxj ids:"+ids);
+                                customerIds=customerIds.concat(ids);
+                                idIndex=idIndex+element.count;
+                                var data={companyUserId:element.userId,count:element.count};
+                                users.push(data);
+                                totalAssistCount+=element.count;
+                            }
+                        });
+                        if(users.length==0){
+                            this.msgError("请选择员工");
+                            return;
+                        }
+                        if(totalAssistCount>(this.assistCount+this.noAssistCount)){
+                            this.msgError("添加数量有误");
+                            return;
+                        }
+                        this.myloading = this.$loading({
+                            lock: true,
+                            text: '处理中...',
+                            spinner: 'el-icon-loading',
+                            background: 'rgba(0, 0, 0, 0.7)'
+                        });
+                        var data={customerIds:customerIds,users:users}
+                        console.log("qxj data:",JSON.stringify(data));
+                        assistToUser(data).then(response => {
+                            this.myloading.close()
+                            if (response.code === 200) {
+                                this.msgSuccess("操作成功");
+                                this.$emit('close');
+                            }
+                        });
+                    }
+                });
+            },
+            closeAction(){
+                this.$refs.userSelects.users=[];
+            }
+        }
+    };
+</script>
+<style lang="scss" scoped>
+.contents{
+    height: 100%;
+    background-color: #fff;
+    padding: 20px;
+        
+}
+.footer{
+    display: flex;
+    align-items: center;
+    justify-content: flex-end;
+}
+</style>
+
+
+
+ 

+ 806 - 0
src/views/crm/customer/assist.vue

@@ -0,0 +1,806 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="客户编码" prop="customerCode">
+        <el-input
+          style="width:220px"
+          v-model="queryParams.customerCode"
+          placeholder="请输入客户编码"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="客户名称" prop="customerName">
+        <el-input
+          style="width:220px"
+          v-model="queryParams.customerName"
+          placeholder="请输入客户名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="手机" prop="mobile">
+        <el-input
+        style="width:220px"
+          v-model="queryParams.mobile"
+          placeholder="请输入手机"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="跟进阶段" prop="status">
+        <el-select style="width:220px" multiple filterable  v-model="statusArr" placeholder="请选择跟进阶段" clearable size="small">
+           <el-option
+                v-for="item in statusOptions"
+                :key="item.dictValue"
+                :label="item.dictLabel"
+                :value="item.dictValue"
+              />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="客户类型" prop="customerType">
+        <el-select style="width:220px" multiple filterable  v-model="ctsTypeArr" placeholder="请选择客户类型" clearable size="small">
+           <el-option
+                v-for="item in typeOptions"
+                :key="item.dictValue"
+                :label="item.dictLabel"
+                :value="item.dictValue"
+              />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="客户标签" prop="tags">
+            <el-select style="width:220px" multiple  filterable v-model="tagIds" placeholder="请选择客户标签" clearable size="small">
+              <el-option
+                    v-for="item in tagsOptions"
+                    :key="item.dictLabel"
+                    :label="item.dictLabel"
+                    :value="item.dictLabel"
+                  />
+            </el-select>
+          </el-form-item>
+      <el-form-item label="客户来源" prop="source">
+        <el-select style="width:220px" multiple filterable  v-model="sourceArr" placeholder="请选择客户来源" clearable size="small">
+           <el-option
+                v-for="item in sourceOptions"
+                :key="item.dictValue"
+                :label="item.dictLabel"
+                :value="item.dictValue"
+              />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="创建时间" prop="createTimeRange">
+        <el-date-picker
+          style="width:205.4px"
+          clearable size="small"
+          v-model="createTimeRange"
+          type="daterange"
+          value-format="yyyy-MM-dd"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期">
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item label="领取时间" prop="receiveTime">
+        <el-date-picker
+              style="width:220px"
+              clearable size="small"
+              v-model="dateRange"
+              type="daterange"
+              value-format="yyyy-MM-dd"
+              start-placeholder="开始日期"
+              end-placeholder="结束日期">
+            </el-date-picker>
+      </el-form-item>
+      <el-form-item label="历史订单" prop="isHisOrder">
+          <el-select style="width:220px" filterable v-model="queryParams.isHisOrder" placeholder="请选择历史订单" clearable size="small">
+            <el-option key="1"  label="已下单" value="1" />
+            <el-option key="0"  label="未下单" value="0" />
+          </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="multiple"
+          @click="handleAssist"
+          v-hasPermi="['crm:customer:assistToUser']"
+        >客户协作</el-button>
+      </el-col>  
+      
+      
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          size="mini"
+          :disabled="multiple"
+          @click="handleSendBatchSms"
+          v-hasPermi="['crm:customer:sendBatchSms']"
+        >批量发送短信</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-dropdown
+          @command="handleCommand"
+          trigger="click"
+          placement="bottom-start"
+        >
+          <el-dropdown-menu slot="dropdown" style="width: 120px;">
+            <el-dropdown-item
+              v-for="option in sysCreateType"
+              :key="option.dictValue"
+              :command="option.dictValue"
+            >
+              <i :class="option.iconClass" style="margin-right: 10px;"></i>
+              {{ option.dictLabel }}
+            </el-dropdown-item>
+          </el-dropdown-menu>
+          <span class="el-dropdown-link" >
+              <el-button  type="success"   size="mini" >
+                创建订单
+              </el-button>
+            </span>
+        </el-dropdown>
+
+<!--        <el-button-->
+<!--          type="success"-->
+<!--          size="mini"-->
+<!--          @click="addPackageOrder"-->
+<!--        >创建订单</el-button>-->
+      </el-col>
+      
+      <!-- <el-col :span="1.5">
+        <el-button
+          type="warning"
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['crm:customer:export']"
+        >导出</el-button>
+      </el-col> -->
+	  <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table  height="500" border v-loading="loading" :data="customerList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="客户编码" align="center" prop="customerCode" />
+      <el-table-column  label="客户名称"   align="center" prop="customerName" :show-overflow-tooltip="true">
+        <template slot-scope="scope">
+          <el-link @click="handleShow(scope.row)" :underline="false" type="primary" >{{scope.row.customerName}}</el-link>
+        </template>
+      </el-table-column>
+      <el-table-column  label="手机" width="120px"  align="center" prop="mobile"   >
+        <template slot-scope="scope">
+          {{scope.row.mobile}}
+          <el-button type="text"    size="mini" @click="callNumber(scope.row.customerId,null)">拨号</el-button>
+          <el-button v-hasPermi="['crm:customer:addVisit']"  type="text" size="mini" @click="handleAddVisit(scope.row)">写跟进</el-button>
+          <el-button type="text"    size="mini" @click="addPackageOrder()" style="margin-right: 15px;">创建订单</el-button>
+        </template>
+      </el-table-column>
+      <el-table-column  label="客户来源" align="center" prop="source">
+        <template slot-scope="scope">
+            <el-tag prop="status" v-for="(item, index) in sourceOptions"    v-if="scope.row.source==item.dictValue">{{item.dictLabel}}</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column  label="跟进阶段"  width="200" align="center" prop="visitStatus">
+        <template slot-scope="scope">
+            <el-tag prop="visitStatus" v-for="(item, index) in statusOptions"    v-if="scope.row.visitStatus==item.dictValue">{{item.dictLabel}}</el-tag><br/>
+            <el-button  v-hasPermi="['crm:customer:addVisitStatus']"  type="text" size="mini" @click="handleVisitStatus(scope.row)">修改</el-button>
+          </template>
+      </el-table-column>
+      <el-table-column  label="客户类型"  width="200" align="center" prop="customerType">
+        <template slot-scope="scope">
+            <el-tag prop="status" v-for="(item, index) in typeOptions"    v-if="scope.row.customerType==item.dictValue">{{item.dictLabel}}</el-tag>
+            <el-button   v-hasPermi="['crm:customer:addCustomerType']"  type="text" size="mini" @click="handleCustomerType(scope.row)">修改</el-button>
+          </template>
+      </el-table-column>
+      <el-table-column  label="标签" width="120px"  align="center" prop="tags"   >
+        <template slot-scope="scope">
+          {{scope.row.tags}}
+          <el-button  v-hasPermi="['crm:customer:addTag']"  type="text" size="mini" @click="handleAddTag(scope.row)">打标签</el-button>
+        </template>
+      </el-table-column>
+      <el-table-column  label="备注" width="150px"  align="center" prop="remark"   >
+        <template slot-scope="scope">
+          {{scope.row.remark}}
+          <el-button v-hasPermi="['crm:customer:addRemark']" type="text" size="mini" @click="handleAddRemark(scope.row)">修改备注</el-button>
+        </template>
+      </el-table-column>
+      <el-table-column  label="邀请人" width="150px" align="center" >
+        <template slot-scope="scope">
+          <div v-for="(user, index) in scope.row.assistUser" :key="index">
+            {{ user }}
+            <br v-if="index < scope.row.assistUser.length - 1"> <!-- 在最后一个元素之前添加换行 -->
+          </div>
+        </template>
+      </el-table-column>
+      <el-table-column label="进线客户详情" align="center" :show-overflow-tooltip="true" prop="registerDesc" />
+      <el-table-column label="最新跟进时间" align="center" prop="lastTime" />
+      <el-table-column label="领取时间" align="center" prop="receiveTime" />
+      <el-table-column label="进线客户提交日期" align="center" prop="registerSubmitTime" />
+      <el-table-column label="创建时间" align="center" prop="customerCreateTime" width="180">
+      </el-table-column>
+      <el-table-column label="操作"   align="center" fixed="right" width="120px" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            @click="handleShow(scope.row)"
+            v-hasPermi="['crm:customer:query']"
+          >查看</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            @click="handleRecover(scope.row)"
+            v-hasPermi="['crm:customer:recover']"
+          >回收公海</el-button>
+          
+        </template>
+      </el-table-column>
+    </el-table>
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+    <el-drawer size="75%" :title="show.title" :visible.sync="show.open">
+        <customer-details  ref="customerDetails" />
+    </el-drawer>
+    <el-dialog :title="addSms.title" :visible.sync="addSms.open" width="1000px" append-to-body>
+       <add-batch-sms ref="sms" @close="closeSms()"></add-batch-sms>
+    </el-dialog>
+
+
+    <el-dialog :title="source.title" :visible.sync="source.open" width="1000px" append-to-body>
+       <edit-source ref="editSource" @close="closeSource()"></edit-source>
+    </el-dialog>
+
+    <el-dialog :title="visit.title" :visible.sync="visit.open" width="600px" append-to-body>
+      <add-visit @closeVisit="closeVisit"   ref="addVisit" />
+    </el-dialog>
+    <el-dialog :title="customer.title" :visible.sync="customer.open" width="1000px" append-to-body>
+       <add-or-edit-customer ref="customer" @close="closeCustomer()"></add-or-edit-customer>
+    </el-dialog>
+    <el-dialog :title="assign.title" :visible.sync="assign.open" width="800px" append-to-body>
+        <assign-user  ref="assignUser" @close="closeAssign"   />
+    </el-dialog>
+    <el-dialog :title="assist.title" :visible.sync="assist.open" width="800px" append-to-body>
+        <assist-user  ref="assistUser" @close="closeAssist"   />
+    </el-dialog>
+    
+    <el-dialog :title="addTag.title" :visible.sync="addTag.open" width="600px" append-to-body>
+        <add-tag ref="tag" @close="closeTag()"></add-tag>
+    </el-dialog>
+    <el-dialog :title="addRemark.title" :visible.sync="addRemark.open" width="600px" append-to-body>
+        <add-remark ref="remark" @close="closeRemark()"></add-remark>
+    </el-dialog>
+    <el-dialog :title="addCustomerType.title" :visible.sync="addCustomerType.open" width="600px" append-to-body>
+        <add-customer-type ref="customerType" @close="closeCustomerType()"></add-customer-type>
+    </el-dialog>
+    <el-dialog :title="addVisitStatus.title" :visible.sync="addVisitStatus.open" width="600px" append-to-body>
+        <add-visit-status ref="visitStatus" @close="closeVisitStatus()"></add-visit-status>
+    </el-dialog>
+    <el-dialog title="创建线上订单" :visible.sync="addPackageOpen" width="1000px" append-to-body>
+      <addPackage  @closePackage="closePackage"   ref="addPackageVisit" />
+    </el-dialog>
+    <el-dialog title="创建线下订单" :visible.sync="addOfflineOrder.open" width="1000px" append-to-body>
+      <add-order-offline @closeOrderOffline="closeOrderOffline"   ref="addOrderOffline" />
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { getMyAssistList,recover,exportCustomer  } from "@/api/crm/customer";
+import { remove,listAssist, getAssist, delAssist, addAssist, updateAssist, exportAssist } from "@/api/crm/assist";
+import customerDetails from '../components/customerDetails.vue';
+import addVisit from '../components/addVisit.vue';
+import {getCitys} from "@/api/store/city";
+import addBatchSms from '../components/addBatchSms.vue';
+import editSource from '../components/editSource.vue';
+import addOrEditCustomer from '../components/addOrEditCustomer.vue';
+import assignUser from '../components/assignUser.vue';
+import assistUser from '../components/assistUser.vue';
+import addTag from '../components/addTag.vue';
+import addRemark from '../components/addRemark.vue';
+import addCustomerType from '../components/addCustomerType.vue';
+import addVisitStatus from '../components/addVisitStatus.vue';
+import addPackage from "@/views/store/components/addOrder";
+import addOrderOffline from "@/views/store/components/addOrderOffline";
+export default {
+  name: "Customer",
+  components: {addPackage,addOrderOffline,addVisitStatus,addCustomerType,addRemark,addTag,assignUser,assistUser,addOrEditCustomer,editSource, addBatchSms,customerDetails,addVisit },
+  data() {
+    return {
+      addOfflineOrder:{
+        open:false,
+      },
+      sysCreateType:[
+        { dictLabel: "线下订单", dictValue: "1" },
+
+        { dictLabel: "线上订单", dictValue: "2" },
+      ],
+      addPackageOpen:false,
+      addVisitStatus:{
+          open:false,
+          title:"跟进阶段"
+      },
+      addCustomerType:{
+          open:false,
+          title:"客户类型"
+      },
+      addRemark:{
+          open:false,
+          title:"客户备注"
+      },
+      addTag:{
+          open:false,
+          title:"打标签"
+      },
+      tagIds:[],
+      statusArr:[],
+      ctsTypeArr:[],
+      sourceArr:[],
+      tagsOptions:[],
+      createTimeRange:[],
+      customer:{
+          open:false,
+          title:"新增客户"
+      },
+      users:[],
+      visit:{
+          open:false,
+          title:"写跟进"
+      },
+      source:{
+          open:false,
+          title:"修改客户来源"
+      },
+      assign:{
+        title:"分配客户",
+        open:false,
+      },
+      assist:{
+        title:"添加协作人",
+        open:false,
+      },
+      assignForm: {
+      },
+      // 表单校验
+      assignRules: {
+        // companyUserId: [
+        //   { required: true, message: "员工不能为空", trigger: "blur" }
+        // ],
+      },
+      dateRange:[],
+      addSms:{
+          open:false,
+          title:"批量发短信"
+      },
+      cityIds:[],
+      citys:[],
+      tags:[],
+      inputVisible: false,
+      inputValue: '',
+      statusOptions:[],
+      typeOptions:[],
+      sourceOptions:[],
+      sexOptions:[],
+      show:{
+        title:"客户详情",
+        open:false,
+      },
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 客户表格数据
+      customerList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        customerCode: null,
+        customerName: null,
+        mobile: null,
+        sex: null,
+        weixin: null,
+        userId: null,
+        createUserId: null,
+        receiveUserId: null,
+        customerUserId: null,
+        address: null,
+        location: null,
+        detailAddress: null,
+        lng: null,
+        lat: null,
+        status: null,
+        deptId: null,
+        isDel: null,
+        customerType: null,
+        receiveTime: null,
+        poolTime: null,
+        companyId: null,
+        isLine: null,
+        source: null,
+        tags: null
+      },
+      // 表单参数
+      form: {
+        province:null,
+        city:null,
+        district:null,
+      },
+      // 表单校验
+      rules: {
+        customerName: [
+          { required: true, message: "客户名称不能为空", trigger: "blur" }
+        ],
+        mobile: [
+          { required: true, message: "手机号不能为空", trigger: "blur" }
+        ],
+        sex: [
+          { required: true, message: "性别不能为空", trigger: "blur" }
+        ],
+        source: [
+          { required: true, message: "客户来源不能为空", trigger: "blur" }
+        ],
+      },
+      loading:null,
+    };
+  },
+  created() {
+    this.getDicts("crm_customer_source").then((response) => {
+      this.sourceOptions = response.data;
+    });
+    this.getDicts("common_sex").then((response) => {
+      this.sexOptions = response.data;
+    });
+    this.getDicts("crm_customer_user_status").then((response) => {
+      this.statusOptions = response.data;
+    });
+    this.getDicts("crm_customer_type").then((response) => {
+      this.typeOptions = response.data;
+    });
+    this.getDicts("crm_customer_tag").then((response) => {
+        this.tagsOptions = response.data;
+    });
+    this.getCitys();
+    this.getList();
+  },
+  methods: {
+    handleCommand(command){
+      if (command==="1"){
+        this.addOfflineOrder.open = true
+      }else {
+        this.addPackageOpen=true;
+      }
+    },
+    closeOrderOffline(){
+      this.addOfflineOrder.open = false
+    },
+    addPackageOrder(){
+       this.addPackageOpen=true;
+    },
+    closePackage(){
+      this.addPackageOpen=false;
+    },
+    closeVisitStatus(){
+        this.addVisitStatus.open=false;
+        this.getList();
+    },
+    handleVisitStatus(row){
+        this.addVisitStatus.open=true;
+        var that=this;
+        setTimeout(() => {
+            that.$refs.visitStatus.reset(row);
+        }, 500);
+
+    },
+    closeCustomerType(){
+        this.addCustomerType.open=false;
+        this.getList();
+    },
+    handleCustomerType(row){
+        this.addCustomerType.open=true;
+        var that=this;
+        setTimeout(() => {
+            that.$refs.customerType.reset(row);
+        }, 500);
+
+    },
+    closeRemark(){
+        this.addRemark.open=false;
+        this.getList();
+    },
+    handleAddRemark(row){
+        this.addRemark.open=true;
+        var that=this;
+        setTimeout(() => {
+            that.$refs.remark.reset(row);
+        }, 500);
+
+    },
+    closeTag(){
+        this.addTag.open=false;
+        this.getList();
+    },
+    handleAddTag(row){
+        this.addTag.open=true;
+        var that=this;
+        setTimeout(() => {
+            that.$refs.tag.reset(row);
+        }, 500);
+
+    },
+    handleShow(row){
+      this.show.open=true;
+      var that=this;
+      const tab = "visit";
+      setTimeout(() => {
+        that.$refs.customerDetails.getDetails(row.customerId);
+        that.$refs.customerDetails.handleClick(tab);
+
+      }, 200);
+    },
+    handleAdd() {
+      this.customer.open = true;
+      var that=this;
+      setTimeout(() => {
+        that.$refs.customer.handleAdd(2);
+      }, 200);
+    },
+    closeCustomer(){
+        this.customer.open=false;
+        this.getList();
+    },
+    closeVisit(){
+        this.visit.open=false;
+        this.getList();
+    },
+    handleAddVisit(row){
+        this.visit.open=true;
+        setTimeout(() => {
+            this.$refs.addVisit.reset(row.customerId);
+        }, 200);
+    },
+    handleAssist(){
+      var that=this;
+      var ids=this.ids;
+      that.assist.open=true;
+      setTimeout(() => {
+          that.$refs.assistUser.init(ids);
+      }, 200);
+    },
+    handleRemoveAllAssist(){
+      const ids = this.ids;
+      const data = {customerIds:ids,companyUserId:null}
+      this.$confirm('是否确认删除协作人?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return  remove(data);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        }).catch(function() {});
+    },
+    handleRemoveAssist(row,userName){
+      const match = userName.match(/\((\d+)\)/);
+      const companyUserId = match[1];
+      const data = {customerIds:[row.customerId],companyUserId:companyUserId}
+      this.$confirm('是否确认删除"' + userName + '"协作?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return  remove(data);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        }).catch(function() {});
+    },
+    handleAssign(){
+      var that=this;
+      var ids=this.ids;
+      that.assign.open=true;
+      setTimeout(() => {
+          that.$refs.assignUser.init(ids,3);
+      }, 200);
+    },
+    closeAssign(){
+      this.assign.open=false;
+      this.getList();
+    },
+    closeAssist(){
+      this.assist.open=false;
+      this.getList();
+    },
+    handleEditScource(){
+      this.source.open=true;
+      var that=this;
+      setTimeout(() => {
+        that.$refs.editSource.handleEdit(that.ids);
+      }, 200);
+
+    },
+    closeSource(){
+        this.source.open=false;
+        this.getList();
+    },
+    closeSms(){
+        this.addSms.open=false;
+    },
+    handleSendBatchSms(){
+      const customerIds =  this.ids;
+      this.addSms.open=true;
+      var that=this;
+      setTimeout(() => {
+          console.log(customerIds)
+          that.$refs.sms.reset(customerIds);
+      }, 500);
+
+    },
+    handleRecover(row) {
+      this.$confirm('是否确认回收客户"' + row.customerName + '"?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          var data={customerUserId:row.customerUserId}
+          return recover(data);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("操作成功");
+        }).catch(function() {});
+    },
+    handleCityChange(value) {
+      console.log(value);
+      var nodes=this.$refs.citySelect.getCheckedNodes();
+      this.form.address=nodes[0].pathLabels[0]+"-"+nodes[0].pathLabels[1]+"-"+nodes[0].pathLabels[2];
+      this.form.cityIds=value.toString();
+    },
+    getCitys(){
+        getCitys().then(res => {
+          this.loading = false;
+          this.citys=res.data;
+        })
+    },
+
+    /** 查询客户列表 */
+    getList() {
+      this.loading = true;
+      if(this.createTimeRange!=null&&this.createTimeRange.length==2){
+        this.queryParams.createTimeRange=this.createTimeRange[0]+"--"+this.createTimeRange[1]
+      }
+      else{
+        this.queryParams.createTimeRange=null;
+      }
+      if(this.statusArr.length>0){
+        this.queryParams.status=this.statusArr.toString();
+      }
+      else{
+        this.queryParams.status=null
+      }
+
+      if(this.ctsTypeArr.length>0){
+        this.queryParams.customerType=this.ctsTypeArr.toString();
+      }
+      else{
+        this.queryParams.customerType=null
+      }
+
+      if(this.sourceArr.length>0){
+        this.queryParams.source=this.sourceArr.toString();
+      }
+      else{
+        this.queryParams.source=null
+      }
+
+      if(this.tagIds.length>0){
+        this.queryParams.tags=this.tagIds.toString();
+      }
+      else{
+        this.queryParams.tags=null
+      }
+      getMyAssistList(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
+        this.customerList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.customerId)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+
+
+
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const customerIds = row.customerId || this.ids;
+      this.$confirm('是否确认删除客户编号为"' + customerIds + '"的数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return delLineCustomer(customerIds);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        }).catch(function() {});
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有客户数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return exportCustomer(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+        }).catch(function() {});
+    },
+  }
+};
+</script>
+<style>
+  .el-tag + .el-tag {
+    margin-left: 10px;
+  }
+  .button-new-tag {
+    margin-left: 10px;
+    height: 32px;
+    line-height: 30px;
+    padding-top: 0;
+    padding-bottom: 0;
+  }
+  .input-new-tag {
+    width: 90px;
+    margin-left: 10px;
+    vertical-align: bottom;
+  }
+  .el-dialog__wrapper{
+    z-index: 100000;
+  }
+</style>

+ 81 - 2
src/views/crm/customer/my.vue

@@ -115,6 +115,16 @@
             v-hasPermi="['crm:customer:addMyCustomer']"
           >新增客户</el-button>
         </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="multiple"
+          @click="handleAssist"
+          v-hasPermi="['crm:customer:assistToUser']"
+        >客户协作</el-button>
+      </el-col>  
       <el-col :span="1.5">
         <el-button
           type="success"
@@ -172,6 +182,15 @@
 <!--          @click="addPackageOrder"-->
 <!--        >创建订单</el-button>-->
       </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleRemoveAllAssist"
+        >删除协作人</el-button>
+      </el-col> 
       <el-col :span="1.5">
         <el-button
           type="warning"
@@ -226,7 +245,16 @@
       <el-table-column  label="备注" width="150px"  align="center" prop="remark"   >
         <template slot-scope="scope">
           {{scope.row.remark}}
-          <el-button   v-hasPermi="['crm:customer:addRemark']" type="text" size="mini" @click="handleAddRemark(scope.row)">修改备注</el-button>
+          <el-button v-hasPermi="['crm:customer:addRemark']" type="text" size="mini" @click="handleAddRemark(scope.row)">修改备注</el-button>
+        </template>
+      </el-table-column>
+      <el-table-column  label="协作人" width="150px" align="center" >
+        <template slot-scope="scope">
+          <div v-for="(user, index) in scope.row.assistUser" :key="index">
+            {{ user }}
+            <el-button icon="el-icon-remove-outline" type="text" size="mini" @click="handleRemoveAssist(scope.row,user)"></el-button>
+            <br v-if="index < scope.row.assistUser.length - 1"> <!-- 在最后一个元素之前添加换行 -->
+          </div>
         </template>
       </el-table-column>
       <el-table-column label="进线客户详情" align="center" :show-overflow-tooltip="true" prop="registerDesc" />
@@ -287,6 +315,10 @@
     <el-dialog :title="assign.title" :visible.sync="assign.open" width="800px" append-to-body>
         <assign-user  ref="assignUser" @close="closeAssign"   />
     </el-dialog>
+    <el-dialog :title="assist.title" :visible.sync="assist.open" width="800px" append-to-body>
+        <assist-user  ref="assistUser" @close="closeAssist"   />
+    </el-dialog>
+    
     <el-dialog :title="addTag.title" :visible.sync="addTag.open" width="600px" append-to-body>
         <add-tag ref="tag" @close="closeTag()"></add-tag>
     </el-dialog>
@@ -310,6 +342,7 @@
 
 <script>
 import { getMyCustomerList,recover,exportCustomer  } from "@/api/crm/customer";
+import { remove,listAssist, getAssist, delAssist, addAssist, updateAssist, exportAssist } from "@/api/crm/assist";
 import customerDetails from '../components/customerDetails.vue';
 import addVisit from '../components/addVisit.vue';
 import {getCitys} from "@/api/store/city";
@@ -317,6 +350,7 @@ import addBatchSms from '../components/addBatchSms.vue';
 import editSource from '../components/editSource.vue';
 import addOrEditCustomer from '../components/addOrEditCustomer.vue';
 import assignUser from '../components/assignUser.vue';
+import assistUser from '../components/assistUser.vue';
 import addTag from '../components/addTag.vue';
 import addRemark from '../components/addRemark.vue';
 import addCustomerType from '../components/addCustomerType.vue';
@@ -325,7 +359,7 @@ import addPackage from "@/views/store/components/addOrder";
 import addOrderOffline from "@/views/store/components/addOrderOffline";
 export default {
   name: "Customer",
-  components: {addPackage,addOrderOffline,addVisitStatus,addCustomerType,addRemark,addTag,assignUser,addOrEditCustomer,editSource, addBatchSms,customerDetails,addVisit },
+  components: {addPackage,addOrderOffline,addVisitStatus,addCustomerType,addRemark,addTag,assignUser,assistUser,addOrEditCustomer,editSource, addBatchSms,customerDetails,addVisit },
   data() {
     return {
       addOfflineOrder:{
@@ -376,6 +410,10 @@ export default {
         title:"分配客户",
         open:false,
       },
+      assist:{
+        title:"添加协作人",
+        open:false,
+      },
       assignForm: {
       },
       // 表单校验
@@ -586,6 +624,43 @@ export default {
             this.$refs.addVisit.reset(row.customerId);
         }, 200);
     },
+    handleAssist(){
+      var that=this;
+      var ids=this.ids;
+      that.assist.open=true;
+      setTimeout(() => {
+          that.$refs.assistUser.init(ids);
+      }, 200);
+    },
+    handleRemoveAllAssist(){
+      const ids = this.ids;
+      const data = {customerIds:ids,companyUserId:null}
+      this.$confirm('是否确认删除协作人?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return  remove(data);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        }).catch(function() {});
+    },
+    handleRemoveAssist(row,userName){
+      const match = userName.match(/\((\d+)\)/);
+      const companyUserId = match[1];
+      const data = {customerIds:[row.customerId],companyUserId:companyUserId}
+      this.$confirm('是否确认删除"' + userName + '"协作?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return  remove(data);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        }).catch(function() {});
+    },
     handleAssign(){
       var that=this;
       var ids=this.ids;
@@ -598,6 +673,10 @@ export default {
       this.assign.open=false;
       this.getList();
     },
+    closeAssist(){
+      this.assist.open=false;
+      this.getList();
+    },
     handleEditScource(){
       this.source.open=true;
       var that=this;

+ 1 - 1
src/views/index.vue

@@ -41,7 +41,7 @@
               企微数量
             </div>
             <div class="card-value highlight">
-              <count-to :start-val="0" :end-val="memberCount" :duration="3600" class="card-panel-num" /></div>
+              <count-to :start-val="0" :end-val="qwMemberNum" :duration="3600" class="card-panel-num" /></div>
             <div class="card-badge">
             </div>
           </div>

+ 46 - 0
src/views/qw/QwWorkTask/index.vue

@@ -53,6 +53,27 @@
           <span :style="getScoreStyle(scope.row.score)">{{ scope.row.score }}</span>
         </template>
       </el-table-column>
+      <el-table-column label="用户过往看课记录" align="center" width="200px">
+        <template slot-scope="scope">
+          <div style="display: flex; gap: 4px; justify-content: center;">
+	        <span
+            v-for="(log, index) in scope.row.logs"
+            :key="index"
+            :style="{
+	            display: 'inline-block',
+	            width: '16px',
+	            height: '16px',
+	            borderRadius: '2px',
+	            backgroundColor:
+	              log === 2 ? '#67C23A' :
+				  log === 3 ? '#f55a4f' :
+				  log === 4 ? '#FFD700' :
+				  '#909399'
+	          }"
+          ></span>
+          </div>
+        </template>
+      </el-table-column>
       <el-table-column label="sop编号" align="center" prop="sopId" />
       <el-table-column label="公司id" align="center" prop="companyName" />
       <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
@@ -67,6 +88,31 @@
       </el-table-column>
     </el-table>
 
+    <div style="margin-top: 20px; padding: 12px; background: #f8f8f8; border-radius: 4px;" v-if="!isSM">
+      <div style="display: flex; gap: 20px; flex-wrap: wrap;">
+        <div style="display: flex; align-items: center; gap: 8px;">
+          <span style="display: inline-block; width: 16px; height: 16px; border-radius: 2px; background-color: #67C23A;"></span>
+          <span>完课</span>
+        </div>
+        <div style="display: flex; align-items: center; gap: 4px;">
+          <span style="display: inline-block; width: 16px; height: 16px; border-radius: 2px; background-color: #f55a4f;"></span>
+          <span>待看课</span>
+        </div>
+        <div style="display: flex; align-items: center; gap: 4px;">
+          <span style="display: inline-block; width: 16px; height: 16px; border-radius: 2px; background-color: #FFD700;"></span>
+          <span>看课中断</span>
+        </div>
+        <div style="display: flex; align-items: center; gap: 4px;">
+          <span style="display: inline-block; width: 16px; height: 16px; border-radius: 2px; background-color: #909399;"></span>
+          <span>没发课</span>
+        </div>
+        <div style="display: flex; align-items: center; gap: 4px;">
+          <span style="display: inline-block; width: 16px; height: 16px; border-radius: 2px; background-color: #0bc6ff;"></span>
+          <span>看课中</span>
+        </div>
+      </div>
+    </div>
+
     <pagination
       v-show="total>0"
       :total="total"

+ 102 - 83
src/views/qw/QwWorkTask/qw/allTask.vue

@@ -2,15 +2,17 @@
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
       <el-form-item label="企微账号" prop="qwUserName">
-             <el-input
-               v-model="queryParams.qwUserName"
-               placeholder="请输入企微昵称"
-               clearable
-               size="small"
-               @keyup.enter.native="handleQuery"
-             />
+        <el-input
+          v-model="queryParams.qwUserName"
+          placeholder="请输入企微昵称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="时间" prop="createTime">
+        <el-date-picker v-model="createTime" size="small" style="width: 220px" value-format="yyyy-MM-dd" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" @change="change"></el-date-picker>
       </el-form-item>
-
 
       <el-form-item>
         <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
@@ -18,17 +20,17 @@
       </el-form-item>
     </el-form>
 
-      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
-    </el-row>
+    <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
 
     <el-table border v-loading="loading" :data="QwWorkTaskList" @selection-change="handleSelectionChange">
-    <el-table-column type="selection" width="55" align="center" />
-    <el-table-column label="企微账号" align="center" prop="qwUserName" />
-	<el-table-column label="销售昵称" align="center" prop="companyUserName" />
-	<el-table-column label="待处理" align="center" prop="status0" />
-	<el-table-column label="已处理" align="center" prop="status1" />
-	<el-table-column label="待处理完课" align="center" prop="status2" />
-	<el-table-column label="已处理完课" align="center" prop="status3" />
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="企微账号" align="center" prop="qwUserName" />
+      <el-table-column label="销售昵称" align="center" prop="companyUserName" />
+      <el-table-column label="待处理" align="center" prop="status0" />
+      <el-table-column label="已处理" align="center" prop="status1" />
+      <el-table-column label="待处理完课" align="center" prop="status2" />
+      <el-table-column label="已处理完课" align="center" prop="status3" />
+      <el-table-column label="时间" align="center" prop="createTime" />
     </el-table>
 
     <pagination
@@ -61,14 +63,14 @@ export default {
   name: "QwWorkTask",
   data() {
     return {
-	  actName:"0",
+      actName:"0",
       // 遮罩层
       loading: true,
       // 导出遮罩层
       exportLoading: false,
       // 选中数组
       ids: [],
-	  myQwUserList:[],
+      myQwUserList:[],
       // 非单个禁用
       single: true,
       // 非多个禁用
@@ -77,6 +79,9 @@ export default {
       showSearch: true,
       // 总条数
       total: 0,
+      sTime:null,
+      eTime:null,
+      createTime:null,
       // 企微任务看板表格数据
       QwWorkTaskList: [],
       // 弹出层标题
@@ -100,7 +105,6 @@ export default {
         sopId: null,
         companyId: null,
         companyUserId: null,
-		qwUserId: null,
       },
       // 表单参数
       form: {},
@@ -110,7 +114,7 @@ export default {
     };
   },
   created() {
-	this.handleGetMyQwUserList();
+    this.handleGetMyQwUserList();
     this.getDicts("sys_qw_work_task_status").then(response => {
       this.statusOptions = response.data;
     });
@@ -119,38 +123,38 @@ export default {
     });
   },
   methods: {
-	getScoreStyle(score) {
-	let backgroundColor = '';
-	  if (score >= 15) {
-		backgroundColor = '#ff4d4f';    // 红色
-	  } else if (score >= 9) {
-		backgroundColor = '#ff7d45';    // 橘红
-	  } else if (score >= 4) {
-		backgroundColor = '#ffec3d';    // 黄色
-	  } else {
-		backgroundColor = '#ffffff';    // 白色
-	  }
-	  return { 
-		'background-color': backgroundColor,
-		'padding': '5px 10px',
-		'border-radius': '4px'
-	  };
-	},
-	formatTime(timeStr) {
-	      if (!timeStr && timeStr !== 0) return '';
-	      
-	      // 处理数字和字符串输入
-	      const str = String(timeStr).padStart(4, '0');
-	      
-	      // 提取有效部分
-	      const hours = str.substring(0, 2);
-	      const minutes = str.substring(2, 4);
-	      
-	      // 简单验证
-	      if (hours > 23 || minutes > 59) return '无效时间';
-	      
-	      return `${hours}:${minutes}`;
-	    },
+    getScoreStyle(score) {
+      let backgroundColor = '';
+      if (score >= 15) {
+        backgroundColor = '#ff4d4f';    // 红色
+      } else if (score >= 9) {
+        backgroundColor = '#ff7d45';    // 橘红
+      } else if (score >= 4) {
+        backgroundColor = '#ffec3d';    // 黄色
+      } else {
+        backgroundColor = '#ffffff';    // 白色
+      }
+      return {
+        'background-color': backgroundColor,
+        'padding': '5px 10px',
+        'border-radius': '4px'
+      };
+    },
+    formatTime(timeStr) {
+      if (!timeStr && timeStr !== 0) return '';
+
+      // 处理数字和字符串输入
+      const str = String(timeStr).padStart(4, '0');
+
+      // 提取有效部分
+      const hours = str.substring(0, 2);
+      const minutes = str.substring(2, 4);
+
+      // 简单验证
+      if (hours > 23 || minutes > 59) return '无效时间';
+
+      return `${hours}:${minutes}`;
+    },
     /** 查询企微任务看板列表 */
     getList() {
       this.loading = true;
@@ -160,10 +164,20 @@ export default {
         this.loading = false;
       });
     },
-	handleClickX(tab, event) {
-	  this.queryParams.status=tab.name;
-	  this.handleQuery();
-	},
+    handleClickX(tab, event) {
+      this.queryParams.status=tab.name;
+      this.handleQuery();
+    },
+    change(){
+      if(this.createTime!=null){
+        this.queryParams.sTime=this.createTime[0];
+        this.queryParams.eTime=this.createTime[1];
+      }else{
+        this.queryParams.sTime=null;
+        this.queryParams.eTime=null;
+      }
+
+    },
     // 取消按钮
     cancel() {
       this.open = false;
@@ -184,7 +198,9 @@ export default {
         companyId: null,
         companyUserId: null,
         createTime: null,
-        updateTime: null
+        updateTime: null,
+        sTime:null,
+        eTime:null
       };
       this.resetForm("form");
     },
@@ -193,12 +209,15 @@ export default {
       this.queryParams.pageNum = 1;
       this.getList();
     },
-	handleGetMyQwUserList(){
-	 this.getList();
-	},
+    handleGetMyQwUserList(){
+      this.getList();
+    },
     /** 重置按钮操作 */
     resetQuery() {
       this.resetForm("queryForm");
+      this.createTime=null;
+      this.queryParams.sTime=null;
+      this.queryParams.eTime=null;
       this.handleQuery();
     },
     // 多选框选中数据
@@ -217,9 +236,9 @@ export default {
     handleUpdate(row) {
       this.reset();
       const id = row.id || this.ids
-        this.form = row;
-        this.open = true;
-        this.title = "处理任务";
+      this.form = row;
+      this.open = true;
+      this.title = "处理任务";
 
     },
     /** 提交按钮 */
@@ -246,30 +265,30 @@ export default {
     handleDelete(row) {
       const ids = row.id || this.ids;
       this.$confirm('是否确认删除企微任务看板编号为"' + ids + '"的数据项?', "警告", {
-          confirmButtonText: "确定",
-          cancelButtonText: "取消",
-          type: "warning"
-        }).then(function() {
-          return delQwWorkTask(ids);
-        }).then(() => {
-          this.getList();
-          this.msgSuccess("删除成功");
-        }).catch(() => {});
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(function() {
+        return delQwWorkTask(ids);
+      }).then(() => {
+        this.getList();
+        this.msgSuccess("删除成功");
+      }).catch(() => {});
     },
     /** 导出按钮操作 */
     handleExport() {
       const queryParams = this.queryParams;
       this.$confirm('是否确认导出所有企微任务看板数据项?', "警告", {
-          confirmButtonText: "确定",
-          cancelButtonText: "取消",
-          type: "warning"
-        }).then(() => {
-          this.exportLoading = true;
-          return exportQwWorkTask(queryParams);
-        }).then(response => {
-          this.download(response.msg);
-          this.exportLoading = false;
-        }).catch(() => {});
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        this.exportLoading = true;
+        return exportQwWorkTask(queryParams);
+      }).then(response => {
+        this.download(response.msg);
+        this.exportLoading = false;
+      }).catch(() => {});
     }
   }
 };

+ 415 - 170
src/views/qw/QwWorkTask/qw/index.vue

@@ -2,14 +2,14 @@
   <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="企微账号"  size="small" @change="updateQwuser()">
-                <el-option
-                  v-for="dict in myQwUserList"
-                  :key="dict.dictValue"
-                  :label="dict.dictLabel+'('+dict.corpName+')'"
-                  :value="dict.dictValue"
-                />
-              </el-select>
+        <el-select v-model="queryParams.qwUserId" placeholder="企微账号"  size="small" @change="updateQwuser()">
+          <el-option
+            v-for="dict in myQwUserList"
+            :key="dict.dictValue"
+            :label="dict.dictLabel+'('+dict.corpName+')'"
+            :value="dict.dictValue"
+          />
+        </el-select>
       </el-form-item>
       <el-form-item label="类别" prop="type">
         <el-select v-model="queryParams.type" placeholder="请选择类别" clearable size="small">
@@ -22,16 +22,16 @@
         </el-select>
       </el-form-item>
 
-	  <el-form-item label="处理状态" prop="trackType">
-	    <el-select v-model="queryParams.trackType" placeholder="处理状态" clearable size="small">
-	      <el-option
-	        v-for="dict in trackTypeOptions"
-	        :key="dict.dictValue"
-	        :label="dict.dictLabel"
-	        :value="dict.dictValue"
-	      />
-	    </el-select>
-	  </el-form-item>
+      <el-form-item label="处理状态" prop="trackType">
+        <el-select v-model="queryParams.trackType" placeholder="处理状态" clearable size="small">
+          <el-option
+            v-for="dict in trackTypeOptions"
+            :key="dict.dictValue"
+            :label="dict.dictLabel"
+            :value="dict.dictValue"
+          />
+        </el-select>
+      </el-form-item>
 
       <el-form-item label="sop编号" prop="sopId">
         <el-input
@@ -45,33 +45,35 @@
       <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>
+        <el-button icon="el-icon-refresh" size="mini" @click="sm()">色盲模式</el-button>
+
       </el-form-item>
     </el-form>
 
-      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
-	<el-tabs type="card" v-model="actName" @tab-click="handleClickX">
-	  <el-tab-pane v-for="(item,index) in statusOptions" :label="item.dictLabel" :name="item.dictValue"></el-tab-pane>
-	</el-tabs>
+    <el-tabs type="card" v-model="actName" @tab-click="handleClickX">
+      <el-tab-pane v-for="(item,index) in statusOptions" :label="item.dictLabel" :name="item.dictValue"></el-tab-pane>
+    </el-tabs>
     <el-table border v-loading="loading" :data="QwWorkTaskList" @selection-change="handleSelectionChange">
       <el-table-column type="selection" width="55" align="center" />
       <el-table-column label="客户昵称" align="center" prop="name" />
       <el-table-column label="企微账号" align="center" prop="qwUserName" />
       <el-table-column label="状态" align="center" prop="status">
-		 <template slot-scope="scope">
-		   <dict-tag :options="statusOptions" :value="scope.row.status"/>
-		 </template>
+        <template slot-scope="scope">
+          <dict-tag :options="statusOptions" :value="scope.row.status"/>
+        </template>
       </el-table-column>
       <el-table-column label="类别" align="center" prop="type">
         <template slot-scope="scope">
           <dict-tag :options="typeOptions" :value="scope.row.type"/>
         </template>
       </el-table-column>
-	  <el-table-column label="处理状态" align="center" prop="trackType">
-	    <template slot-scope="scope">
-	      <dict-tag :options="trackTypeOptions" :value="scope.row.trackType"/>
-	    </template>
-	  </el-table-column>
+      <el-table-column label="处理状态" align="center" prop="trackType">
+        <template slot-scope="scope">
+          <dict-tag :options="trackTypeOptions" :value="scope.row.trackType"/>
+        </template>
+      </el-table-column>
       <el-table-column label="标题" align="center" prop="title" />
       <el-table-column label="描述" align="center" prop="description" />
       <el-table-column label="分值" align="center" prop="score">
@@ -79,54 +81,136 @@
           <span :style="getScoreStyle(scope.row.score)">{{ scope.row.score }}</span>
         </template>
       </el-table-column>
-	  <el-table-column label="用户过往看课记录" align="center" width="200px">
-	    <template slot-scope="scope">
-	      <div style="display: flex; gap: 4px; justify-content: center;">
+      <el-table-column label="用户过往看课记录" align="center" width="200px">
+        <template slot-scope="scope">
+          <div style="display: flex; gap: 4px; justify-content: center;" v-if="!isSM">
+			  <span
+          v-for="(log, index) in scope.row.logs"
+          :key="index"
+          :style="{
+				  display: 'inline-block',
+				  width: '16px',
+				  height: '16px',
+				  borderRadius: '2px',
+				  backgroundColor:
+					log === 2 ? '#67C23A' :
+							  log === 3 ? '#f55a4f' :
+							  log === 4 ? '#FFD700' :
+							  log === 1 ? '#0bc6ff' :
+							  '#909399'
+				}"
+        ></span>
+          </div>
+
+          <div style="display: flex; gap: 4px; justify-content: center;" v-if="isSM">
 	        <span
-	          v-for="(log, index) in scope.row.logs"
-	          :key="index"
-	          :style="{
+            v-for="(log, index) in scope.row.logs"
+            :key="index"
+            :style="{
 	            display: 'inline-block',
 	            width: '16px',
 	            height: '16px',
-	            borderRadius: '2px',
-	            backgroundColor:
-	              log === 2 ? '#67C23A' :
-				  log === 3 ? '#f55a4f' :
-				  log === 4 ? '#FFD700' :
-				  '#909399'
+	            borderRadius: log === 2 ? '50%' : log === 4 ? '2px 8px' : '2px',
+	            backgroundColor: log === 3 ? 'transparent' : '#f0f0f0',
+	            border: log === 3 ? '2px solid #666' : '1px solid #ddd',
+	            position: 'relative',
+	            transform: log === 4 ? 'rotate(45deg)' : 'none'
 	          }"
-	        ></span>
-	      </div>
-	    </template>
-	  </el-table-column>
-	    <el-table-column label="最晚看课时间" align="center">
-	        <template slot-scope="scope">
-	          {{ formatTime(scope.row.lastWatchTime) }}
-	        </template>
-	      </el-table-column>
+          >
+	          <!-- 已完成 - 圆形 + 对勾 -->
+	          <span v-if="log === 2" style="
+	            position: absolute;
+	            top: 45%;
+	            left: 50%;
+	            width: 6px;
+	            height: 3px;
+	            border: solid #333;
+	            border-width: 0 0 2px 2px;
+	            transform: translate(-50%, -50%) rotate(-45deg);
+	          "></span>
+
+            <!-- 未完成 - 方框 + 叉 -->
+	          <span v-if="log === 3" style="
+	            position: absolute;
+	            top: 50%;
+	            left: 50%;
+	            width: 8px;
+	            height: 2px;
+	            background: #666;
+	            transform: translate(-50%, -50%) rotate(45deg);"></span>
+	          <span v-if="log === 1" style="
+	            position: absolute;
+	            top: 50%;
+	            left: 50%;
+	            width: 8px;
+	            height: 2px;
+	            background: #666;
+	            transform: translate(-50%, -10%) rotate(-15deg);
+	          "></span>
+
+            <!-- 部分完成 - 菱形 -->
+	          <span v-if="log === 4" style="
+	            position: absolute;
+	            top: 50%;
+	            left: 50%;
+	            width: 6px;
+	            height: 6px;
+	            border: 2px solid #333;
+	            transform: translate(-50%, -50%) rotate(-45deg);
+	          "></span>
+
+            <!-- 未开始 - 减号 -->
+	          <span v-if="!log" style="
+	            position: absolute;
+	            top: 50%;
+	            left: 50%;
+	            width: 8px;
+	            height: 2px;
+	            background: #999;
+	            transform: translate(-50%, -50%);
+	          "></span>
+
+            <!-- 图像 - 使用img标签 -->
+	          <img v-if="log === 5" src="/path/to/your-image.png" alt="Custom icon" style="
+	            position: absolute;
+	            top: 50%;
+	            left: 50%;
+	            width: 12px;
+	            height: 12px;
+	            transform: translate(-50%, -50%);
+	          ">
+	        </span>
+          </div>
+        </template>
+      </el-table-column>
+      <el-table-column label="最晚看课时间" align="center">
+        <template slot-scope="scope">
+          {{ formatTime(scope.row.lastWatchTime) }}
+        </template>
+      </el-table-column>
 
       <el-table-column label="sopId" align="center" prop="sopId" />
+      <el-table-column label="通话时长" align="center" prop="duration" />
       <el-table-column label="创建时间" align="center" prop="createTime" />
       <el-table-column label="修改时间" align="center" prop="updateTime" />
       <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
         <template slot-scope="scope">
           <el-button v-if="scope.row.status==0"
-            size="mini"
-            type="text"
-            icon="el-icon-edit"
-            @click="handleUpdate(scope.row)"
+                     size="mini"
+                     type="text"
+                     icon="el-icon-edit"
+                     @click="handleUpdate(scope.row)"
           >处理</el-button>
-		  <el-button v-if="scope.row.status==0"
-		    size="mini"
-		    type="text"
-		    @click="handleUpdate2(scope.row)"
-		  >未接通</el-button>
-		  <el-button v-if="scope.row.status==0"
-		    size="mini"
-		    type="text"
-		    @click="handleUpdate3(scope.row)"
-		  >接通</el-button>
+          <el-button v-if="scope.row.status==0"
+                     size="mini"
+                     type="text"
+                     @click="handleUpdate2(scope.row)"
+          >未接通</el-button>
+          <el-button v-if="scope.row.status==0"
+                     size="mini"
+                     type="text"
+                     @click="handleUpdate3(scope.row)"
+          >接通</el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -138,20 +222,177 @@
       :limit.sync="queryParams.pageSize"
       @pagination="getList"
     />
+    <div style="margin-top: 20px; padding: 12px; background: #f8f8f8; border-radius: 4px;" v-if="!isSM">
+      <div style="display: flex; gap: 20px; flex-wrap: wrap;">
+        <div style="display: flex; align-items: center; gap: 8px;">
+          <span style="display: inline-block; width: 16px; height: 16px; border-radius: 2px; background-color: #67C23A;"></span>
+          <span>完课</span>
+        </div>
+        <div style="display: flex; align-items: center; gap: 4px;">
+          <span style="display: inline-block; width: 16px; height: 16px; border-radius: 2px; background-color: #f55a4f;"></span>
+          <span>待看课</span>
+        </div>
+        <div style="display: flex; align-items: center; gap: 4px;">
+          <span style="display: inline-block; width: 16px; height: 16px; border-radius: 2px; background-color: #FFD700;"></span>
+          <span>看课中断</span>
+        </div>
+        <div style="display: flex; align-items: center; gap: 4px;">
+          <span style="display: inline-block; width: 16px; height: 16px; border-radius: 2px; background-color: #909399;"></span>
+          <span>没发课</span>
+        </div>
+        <div style="display: flex; align-items: center; gap: 4px;">
+          <span style="display: inline-block; width: 16px; height: 16px; border-radius: 2px; background-color: #0bc6ff;"></span>
+          <span>看课中</span>
+        </div>
+      </div>
+    </div>
+
+    <!-- 新增的解释说明区域 -->
+    <div style="margin-top: 20px; padding: 12px; background: #f8f8f8; border-radius: 4px;" v-if="isSM">
+      <div style="display: flex; gap: 20px; flex-wrap: wrap;">
+        <div style="display: flex; align-items: center; gap: 8px;">
+	            <span style="
+	              display: inline-block;
+	              width: 16px;
+	              height: 16px;
+	              border-radius: 50%;
+	              background-color: #f0f0f0;
+	              position: relative;
+	            ">
+	              <span style="
+	                position: absolute;
+	                top: 45%;
+	                left: 50%;
+	                width: 6px;
+	                height: 3px;
+	                border: solid #333;
+	                border-width: 0 0 2px 2px;
+	                transform: translate(-50%, -50%) rotate(-45deg);
+	              "></span>
+	            </span>
+          <span>完课</span>
+        </div>
+
+        <div style="display: flex; align-items: center; gap: 8px;">
+	            <span style="
+	              display: inline-block;
+	              width: 16px;
+	              height: 16px;
+	              border-radius: 2px;
+	              border: 2px solid #666;
+	              background-color: transparent;
+	              position: relative;
+	            ">
+	              <span style="
+	                position: absolute;
+	                top: 50%;
+	                left: 50%;
+	                width: 8px;
+	                height: 2px;
+	                background: #666;
+	                transform: translate(-50%, -50%) rotate(45deg);
+	              "></span>
+	              <span style="
+	                position: absolute;
+	                top: 50%;
+	                left: 50%;
+	                width: 8px;
+	                height: 2px;
+	                background: #666;
+	                transform: translate(-50%, -50%) rotate(-45deg);
+	              "></span>
+	            </span>
+          <span>待看课</span>
+        </div>
+
+        <div style="display: flex; align-items: center; gap: 8px;">
+	            <span style="
+	              display: inline-block;
+	              width: 16px;
+	              height: 16px;
+	              border-radius: 2px 8px;
+	              background-color: #f0f0f0;
+	              border: 1px solid #ddd;
+	              position: relative;
+	              transform: rotate(45deg);
+	            ">
+	              <span style="
+	                position: absolute;
+	                top: 50%;
+	                left: 50%;
+	                width: 6px;
+	                height: 6px;
+	                border: 2px solid #333;
+	                transform: translate(-50%, -50%) rotate(-45deg);
+	              "></span>
+	            </span>
+          <span>看课中断</span>
+        </div>
+
+        <div style="display: flex; align-items: center; gap: 8px;">
+	            <span style="
+	              display: inline-block;
+	              width: 16px;
+	              height: 16px;
+	              border-radius: 2px;
+	              background-color: #f0f0f0;
+	              border: 1px solid #ddd;
+	              position: relative;
+	            ">
+	              <span style="
+	                position: absolute;
+	                top: 50%;
+	                left: 50%;
+	                width: 8px;
+	                height: 2px;
+	                background: #999;
+	                transform: translate(-50%, -50%);
+	              "></span>
+	            </span>
+          <span>没发课</span>
+        </div>
+
+        <div style="display: flex; align-items: center; gap: 8px;">
+			    <span style="
+			      display: inline-block;
+			      width: 16px;
+			      height: 16px;
+			      border-radius: 2px;
+			      background-color: #f0f0f0;
+			      border: 1px solid #ddd;
+			      position: relative;
+			    ">
+			      <span  style="
+			        position: absolute;
+			        top: 50%;
+			        left: 50%;
+			        width: 8px;
+			        height: 2px;
+			        background: #666;
+			        transform: translate(-50%, -10%) rotate(-15deg);
+			      "></span>
+			    </span>
+          <span>看课中</span>
+        </div>
+
+
+      </div>
+    </div>
+
 
     <!-- 添加或修改企微任务看板对话框 -->
     <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
       <el-form ref="form" :model="form" :rules="rules" label-width="80px">
-		<el-form-item label="处理类型" prop="trackType">
-		  <el-select v-model="form.trackType" placeholder="状态" clearable size="small">
-			  <el-option
-				v-for="dict in trackTypeOptions"
-				:key="dict.dictValue"
-				:label="dict.dictLabel"
-				:value="dict.dictValue"
-			  />
-		  </el-select>
-		</el-form-item>
+        <el-form-item label="处理类型" prop="trackType">
+          <el-select v-model="form.trackType" placeholder="状态" clearable size="small">
+            <el-option
+              v-for="dict in trackTypeOptions"
+              :key="dict.dictValue"
+              :label="dict.dictLabel"
+              :value="dict.dictValue"
+            />
+          </el-select>
+        </el-form-item>
         <el-form-item label="描述" prop="description">
           <el-input  v-model="form.description" placeholder="请输入描述"  type="textarea" :rows="3"/>
         </el-form-item>
@@ -165,20 +406,21 @@
 </template>
 
 <script>
-import { listQwWorkTask, getQwWorkTask, delQwWorkTask, addQwWorkTask, updateQwWorkTask, exportQwWorkTask,updateQwWorkTask2,updateQwWorkTask3 } from "@/api/qw/qw/QwWorkTask";
+import { listQwWorkTask, getQwWorkTask, delQwWorkTask, addQwWorkTask, updateQwWorkTask, exportQwWorkTask,updateQwWorkTask2,updateQwWorkTask3 } from "@/api/qw/QwWorkTask";
 import {getMyQwUserList, getMyQwCompanyList, handleInputAuthAppKey, updateUser} from "@/api/qw/user";
 export default {
   name: "QwWorkTask",
   data() {
     return {
-	  actName:"0",
+      actName:"0",
       // 遮罩层
       loading: true,
       // 导出遮罩层
       exportLoading: false,
       // 选中数组
       ids: [],
-	  myQwUserList:[],
+      isSM:false,
+      myQwUserList:[],
       // 非单个禁用
       single: true,
       // 非多个禁用
@@ -195,7 +437,7 @@ export default {
       open: false,
       // 状态 0 待处理 1 已处理 3 过期字典
       statusOptions: [],
-	  trackTypeOptions:[],
+      trackTypeOptions:[],
       // 类别 1先导 2 课程 3 大小转 4 转人工字典
       typeOptions: [],
       // 查询参数
@@ -216,59 +458,59 @@ export default {
       form: {},
       // 表单校验
       rules: {
-		   trackType: [
-		      { required: true, message: '请选择处理类型', trigger: 'change' }
-		    ]
+        trackType: [
+          { required: true, message: '请选择处理类型', trigger: 'change' }
+        ]
       }
     };
   },
   created() {
-	this.handleGetMyQwUserList();
+    this.handleGetMyQwUserList();
     this.getDicts("sys_qw_work_task_status").then(response => {
       this.statusOptions = response.data;
     });
     this.getDicts("sys_qw_work_task_type").then(response => {
       this.typeOptions = response.data;
     });
-	this.getDicts("sys_qw_work_task_track_type").then(response => {
-	  this.trackTypeOptions = response.data;
-	});
+    this.getDicts("sys_qw_work_task_track_type").then(response => {
+      this.trackTypeOptions = response.data;
+    });
 
 
   },
   methods: {
-	getScoreStyle(score) {
-	let backgroundColor = '';
-	  if (score >= 15) {
-		backgroundColor = '#ff4d4f';    // 红色
-	  } else if (score >= 9) {
-		backgroundColor = '#ff7d45';    // 橘红
-	  } else if (score >= 4) {
-		backgroundColor = '#ffec3d';    // 黄色
-	  } else {
-		backgroundColor = '#ffffff';    // 白色
-	  }
-	  return {
-		'background-color': backgroundColor,
-		'padding': '5px 10px',
-		'border-radius': '4px'
-	  };
-	},
-	formatTime(timeStr) {
-	      if (!timeStr && timeStr !== 0) return '';
-
-	      // 处理数字和字符串输入
-	      const str = String(timeStr).padStart(4, '0');
-
-	      // 提取有效部分
-	      const hours = str.substring(0, 2);
-	      const minutes = str.substring(2, 4);
-
-	      // 简单验证
-	      if (hours > 23 || minutes > 59) return '无效时间';
-
-	      return `${hours}:${minutes}`;
-	    },
+    getScoreStyle(score) {
+      let backgroundColor = '';
+      if (score >= 15) {
+        backgroundColor = '#ff4d4f';    // 红色
+      } else if (score >= 9) {
+        backgroundColor = '#ff7d45';    // 橘红
+      } else if (score >= 4) {
+        backgroundColor = '#ffec3d';    // 黄色
+      } else {
+        backgroundColor = '#ffffff';    // 白色
+      }
+      return {
+        'background-color': backgroundColor,
+        'padding': '5px 10px',
+        'border-radius': '4px'
+      };
+    },
+    formatTime(timeStr) {
+      if (!timeStr && timeStr !== 0) return '';
+
+      // 处理数字和字符串输入
+      const str = String(timeStr).padStart(4, '0');
+
+      // 提取有效部分
+      const hours = str.substring(0, 2);
+      const minutes = str.substring(2, 4);
+
+      // 简单验证
+      if (hours > 23 || minutes > 59) return '无效时间';
+
+      return `${hours}:${minutes}`;
+    },
     /** 查询企微任务看板列表 */
     getList() {
       this.loading = true;
@@ -278,10 +520,13 @@ export default {
         this.loading = false;
       });
     },
-	handleClickX(tab, event) {
-	  this.queryParams.status=tab.name;
-	  this.handleQuery();
-	},
+    sm(){
+      this.isSM = this.isSM ? false : true;
+    },
+    handleClickX(tab, event) {
+      this.queryParams.status=tab.name;
+      this.handleQuery();
+    },
     // 取消按钮
     cancel() {
       this.open = false;
@@ -311,18 +556,18 @@ export default {
       this.queryParams.pageNum = 1;
       this.getList();
     },
-	handleGetMyQwUserList(){
-
-	  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();
-	    }
-	  });
-
-	},
+    handleGetMyQwUserList(){
+
+      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();
+        }
+      });
+
+    },
     /** 重置按钮操作 */
     resetQuery() {
       this.resetForm("queryForm");
@@ -344,29 +589,29 @@ export default {
     handleUpdate(row) {
       this.reset();
       const id = row.id || this.ids
-        this.form = row;
-        this.open = true;
-        this.title = "处理任务";
+      this.form = row;
+      this.open = true;
+      this.title = "处理任务";
 
     },
 
-	handleUpdate2(row) {
-	  var from={id:row.id }
-	  	updateQwWorkTask2(from).then(response => {
-	    this.msgSuccess("修改成功");
+    handleUpdate2(row) {
+      var from={id:row.id }
+      updateQwWorkTask2(from).then(response => {
+        this.msgSuccess("修改成功");
 
-	    this.getList();
-	  });
+        this.getList();
+      });
 
-	},
-	handleUpdate3(row) {
-	  var from={id:row.id }
-		updateQwWorkTask3(from).then(response => {
-	  this.msgSuccess("修改成功");
+    },
+    handleUpdate3(row) {
+      var from={id:row.id }
+      updateQwWorkTask3(from).then(response => {
+        this.msgSuccess("修改成功");
 
-	  this.getList();
-	});
-	},
+        this.getList();
+      });
+    },
     /** 提交按钮 */
     submitForm() {
       this.$refs["form"].validate(valid => {
@@ -391,30 +636,30 @@ export default {
     handleDelete(row) {
       const ids = row.id || this.ids;
       this.$confirm('是否确认删除企微任务看板编号为"' + ids + '"的数据项?', "警告", {
-          confirmButtonText: "确定",
-          cancelButtonText: "取消",
-          type: "warning"
-        }).then(function() {
-          return delQwWorkTask(ids);
-        }).then(() => {
-          this.getList();
-          this.msgSuccess("删除成功");
-        }).catch(() => {});
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(function() {
+        return delQwWorkTask(ids);
+      }).then(() => {
+        this.getList();
+        this.msgSuccess("删除成功");
+      }).catch(() => {});
     },
     /** 导出按钮操作 */
     handleExport() {
       const queryParams = this.queryParams;
       this.$confirm('是否确认导出所有企微任务看板数据项?', "警告", {
-          confirmButtonText: "确定",
-          cancelButtonText: "取消",
-          type: "warning"
-        }).then(() => {
-          this.exportLoading = true;
-          return exportQwWorkTask(queryParams);
-        }).then(response => {
-          this.download(response.msg);
-          this.exportLoading = false;
-        }).catch(() => {});
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        this.exportLoading = true;
+        return exportQwWorkTask(queryParams);
+      }).then(response => {
+        this.download(response.msg);
+        this.exportLoading = false;
+      }).catch(() => {});
     }
   }
 };

+ 447 - 133
src/views/qw/QwWorkTask/qw/qwWorkTask.vue

@@ -1,14 +1,30 @@
 <template>
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
-     <el-form-item label="企微账号" prop="qwUserName">
-             <el-input
-               v-model="queryParams.qwUserName"
-               placeholder="请输入企微昵称"
-               clearable
-               size="small"
-               @keyup.enter.native="handleQuery"
-             />
+      <el-form-item label="部门" prop="type">
+        <treeselect style="width: 220px" :clearable="false"  v-model="queryParams.deptId"  :options="deptOptions" clearable :show-count="true" placeholder="请选择归属部门"  />
+      </el-form-item>
+      <el-form-item label="企微账号" prop="qwUserName">
+        <el-input
+          v-model="queryParams.qwUserName"
+          placeholder="请输入企微昵称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="所属销售" prop="companyUserId">
+        <el-select v-model="queryParams.companyUserId" clearable filterable remote
+                   placeholder="请输入关键词" :remote-method="loadCompanyUserOptions"
+                   v-select-load-more="loadMoreCompanyUserOptions"
+                   :loading="companyUserOptionsLoading">
+          <el-option
+            v-for="item in companyUserOptions"
+            :key="item.value"
+            :label="item.label"
+            :value="item.value">
+          </el-option>
+        </el-select>
       </el-form-item>
       <el-form-item label="类别" prop="type">
         <el-select v-model="queryParams.type" placeholder="请选择类别" clearable size="small">
@@ -20,16 +36,17 @@
           />
         </el-select>
       </el-form-item>
-	  <el-form-item label="处理状态" prop="trackType">
-	    <el-select v-model="queryParams.trackType" placeholder="处理状态" clearable size="small">
-	      <el-option
-	        v-for="dict in trackTypeOptions"
-	        :key="dict.dictValue"
-	        :label="dict.dictLabel"
-	        :value="dict.dictValue"
-	      />
-	    </el-select>
-	  </el-form-item>
+
+      <el-form-item label="处理状态" prop="trackType">
+        <el-select v-model="queryParams.trackType" placeholder="处理状态" clearable size="small">
+          <el-option
+            v-for="dict in trackTypeOptions"
+            :key="dict.dictValue"
+            :label="dict.dictLabel"
+            :value="dict.dictValue"
+          />
+        </el-select>
+      </el-form-item>
       <el-form-item label="sop编号" prop="sopId">
         <el-input
           v-model="queryParams.sopId"
@@ -42,80 +59,165 @@
       <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>
+        <el-button icon="el-icon-refresh" size="mini" @click="sm()">色盲模式</el-button>
       </el-form-item>
     </el-form>
 
-      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
-    </el-row>
-	<el-tabs type="card" v-model="actName" @tab-click="handleClickX">
-	  <el-tab-pane v-for="(item,index) in statusOptions" :label="item.dictLabel" :name="item.dictValue"></el-tab-pane>
-	</el-tabs>
+    <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    <el-tabs type="card" v-model="actName" @tab-click="handleClickX">
+      <el-tab-pane v-for="(item,index) in statusOptions" :label="item.dictLabel" :name="item.dictValue"></el-tab-pane>
+    </el-tabs>
     <el-table border v-loading="loading" :data="QwWorkTaskList" @selection-change="handleSelectionChange">
       <el-table-column type="selection" width="55" align="center" />
       <el-table-column label="客户昵称" align="center" prop="name" />
       <el-table-column label="企微账号" align="center" prop="qwUserName" />
+      <el-table-column label="企微昵称" align="center" prop="nickName" />
       <el-table-column label="状态" align="center" prop="status">
-		 <template slot-scope="scope">
-		   <dict-tag :options="statusOptions" :value="scope.row.status"/>
-		 </template>
+        <template slot-scope="scope">
+          <dict-tag :options="statusOptions" :value="scope.row.status"/>
+        </template>
       </el-table-column>
       <el-table-column label="类别" align="center" prop="type">
         <template slot-scope="scope">
           <dict-tag :options="typeOptions" :value="scope.row.type"/>
         </template>
       </el-table-column>
-	  <el-table-column label="处理状态" align="center" prop="trackType">
-	    <template slot-scope="scope">
-	      <dict-tag :options="trackTypeOptions" :value="scope.row.trackType"/>
-	    </template>
-	  </el-table-column>
+      <el-table-column label="处理状态" align="center" prop="trackType">
+        <template slot-scope="scope">
+          <dict-tag :options="trackTypeOptions" :value="scope.row.trackType"/>
+        </template>
+      </el-table-column>
       <el-table-column label="标题" align="center" prop="title" />
-      <el-table-column label="备注" align="center" prop="remark" />
+      <el-table-column label="描述" align="center" prop="description" />
       <el-table-column label="分值" align="center" prop="score">
         <template slot-scope="scope">
           <span :style="getScoreStyle(scope.row.score)">{{ scope.row.score }}</span>
         </template>
       </el-table-column>
-	  <el-table-column label="用户过往看课记录" align="center" width="200px">
-	    <template slot-scope="scope">
-	      <div style="display: flex; gap: 4px; justify-content: center;">
-	        <span 
-	          v-for="(log, index) in scope.row.logs" 
-	          :key="index"
-	          :style="{
+      <el-table-column label="用户过往看课记录" align="center" width="200px">
+        <template slot-scope="scope">
+          <div style="display: flex; gap: 4px; justify-content: center;" v-if="!isSM">
+	    	  <span
+            v-for="(log, index) in scope.row.logs"
+            :key="index"
+            :style="{
+	    		  display: 'inline-block',
+	    		  width: '16px',
+	    		  height: '16px',
+	    		  borderRadius: '2px',
+	    		  backgroundColor:
+	    			log === 2 ? '#67C23A' :
+	    					  log === 3 ? '#f55a4f' :
+	    					  log === 4 ? '#FFD700' :
+	    					  log === 1 ? '#0bc6ff' :
+	    					  '#909399'
+	    		}"
+          ></span>
+          </div>
+
+          <div style="display: flex; gap: 4px; justify-content: center;" v-if="isSM">
+	        <span
+            v-for="(log, index) in scope.row.logs"
+            :key="index"
+            :style="{
 	            display: 'inline-block',
 	            width: '16px',
 	            height: '16px',
-	            borderRadius: '2px',
-	            backgroundColor: 
-	              log === 2 ? '#67C23A' : 
-				  log === 3 ? '#f55a4f' : 
-				  log === 4 ? '#FFD700' : 
-				  '#909399'
+	            borderRadius: log === 2 ? '50%' : log === 4 ? '2px 8px' : '2px',
+	            backgroundColor: log === 3 ? 'transparent' : '#f0f0f0',
+	            border: log === 3 ? '2px solid #666' : '1px solid #ddd',
+	            position: 'relative',
+	            transform: log === 4 ? 'rotate(45deg)' : 'none'
 	          }"
-	        ></span>
-	      </div>
-	    </template>
-	  </el-table-column>
-	    <el-table-column label="最晚看课时间" align="center">
-	        <template slot-scope="scope">
-	          {{ formatTime(scope.row.lastWatchTime) }}
-	        </template>
-	      </el-table-column>
-	  
+          >
+	          <!-- 已完成 - 圆形 + 对勾 -->
+	          <span v-if="log === 2" style="
+	            position: absolute;
+	            top: 45%;
+	            left: 50%;
+	            width: 6px;
+	            height: 3px;
+	            border: solid #333;
+	            border-width: 0 0 2px 2px;
+	            transform: translate(-50%, -50%) rotate(-45deg);
+	          "></span>
+
+            <!-- 未完成 - 方框 + 叉 -->
+	          <span v-if="log === 3" style="
+	            position: absolute;
+	            top: 50%;
+	            left: 50%;
+	            width: 8px;
+	            height: 2px;
+	            background: #666;
+	            transform: translate(-50%, -50%) rotate(45deg);">
+				</span>
+
+
+	          <span v-if="log === 1" style="
+	            position: absolute;
+	            top: 50%;
+	            left: 50%;
+	            width: 8px;
+	            height: 2px;
+	            background: #666;
+	            transform: translate(-50%, -10%) rotate(-15deg);
+	          "></span>
+
+            <!-- 部分完成 - 菱形 -->
+	          <span v-if="log === 4" style="
+	            position: absolute;
+	            top: 50%;
+	            left: 50%;
+	            width: 6px;
+	            height: 6px;
+	            border: 2px solid #333;
+	            transform: translate(-50%, -50%) rotate(-45deg);
+	          "></span>
+
+            <!-- 未开始 - 减号 -->
+	          <span v-if="!log" style="
+	            position: absolute;
+	            top: 50%;
+	            left: 50%;
+	            width: 8px;
+	            height: 2px;
+	            background: #999;
+	            transform: translate(-50%, -50%);
+	          "></span>
+
+            <!-- 图像 - 使用img标签 -->
+	          <img v-if="log === 5" src="/path/to/your-image.png" alt="Custom icon" style="
+	            position: absolute;
+	            top: 50%;
+	            left: 50%;
+	            width: 12px;
+	            height: 12px;
+	            transform: translate(-50%, -50%);
+	          ">
+	        </span>
+          </div>
+        </template>
+      </el-table-column>
+      <el-table-column label="最晚看课时间" align="center">
+        <template slot-scope="scope">
+          {{ formatTime(scope.row.lastWatchTime) }}
+        </template>
+      </el-table-column>
+
       <el-table-column label="sopId" align="center" prop="sopId" />
       <el-table-column label="创建时间" align="center" prop="createTime" />
       <el-table-column label="修改时间" align="center" prop="updateTime" />
-<!--      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
-        <template slot-scope="scope">
-          <el-button v-if="scope.row.status==0"
-            size="mini"
-            type="text"
-            icon="el-icon-edit"
-            @click="handleUpdate(scope.row)"
-          >处理</el-button>
-        </template>
-      </el-table-column> -->
+      <!--      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+              <template slot-scope="scope">
+                <el-button v-if="scope.row.status==0"
+                  size="mini"
+                  type="text"
+                  icon="el-icon-edit"
+                  @click="handleUpdate(scope.row)"
+                >处理</el-button>
+              </template>
+            </el-table-column> -->
     </el-table>
 
     <pagination
@@ -125,7 +227,162 @@
       :limit.sync="queryParams.pageSize"
       @pagination="getList"
     />
+    <div style="margin-top: 20px; padding: 12px; background: #f8f8f8; border-radius: 4px;" v-if="!isSM">
+      <div style="display: flex; gap: 20px; flex-wrap: wrap;">
+        <div style="display: flex; align-items: center; gap: 8px;">
+          <span style="display: inline-block; width: 16px; height: 16px; border-radius: 2px; background-color: #67C23A;"></span>
+          <span>完课</span>
+        </div>
+        <div style="display: flex; align-items: center; gap: 4px;">
+          <span style="display: inline-block; width: 16px; height: 16px; border-radius: 2px; background-color: #f55a4f;"></span>
+          <span>待看课</span>
+        </div>
+        <div style="display: flex; align-items: center; gap: 4px;">
+          <span style="display: inline-block; width: 16px; height: 16px; border-radius: 2px; background-color: #FFD700;"></span>
+          <span>看课中断</span>
+        </div>
+        <div style="display: flex; align-items: center; gap: 4px;">
+          <span style="display: inline-block; width: 16px; height: 16px; border-radius: 2px; background-color: #909399;"></span>
+          <span>没发课</span>
+        </div>
+        <div style="display: flex; align-items: center; gap: 4px;">
+          <span style="display: inline-block; width: 16px; height: 16px; border-radius: 2px; background-color: #0bc6ff;"></span>
+          <span>看课中</span>
+        </div>
+      </div>
+    </div>
+
+    <!-- 新增的解释说明区域 -->
+    <div style="margin-top: 20px; padding: 12px; background: #f8f8f8; border-radius: 4px;" v-if="isSM">
+      <div style="display: flex; gap: 20px; flex-wrap: wrap;">
+        <div style="display: flex; align-items: center; gap: 8px;">
+	        <span style="
+	          display: inline-block;
+	          width: 16px;
+	          height: 16px;
+	          border-radius: 50%;
+	          background-color: #f0f0f0;
+	          position: relative;
+	        ">
+	          <span style="
+	            position: absolute;
+	            top: 45%;
+	            left: 50%;
+	            width: 6px;
+	            height: 3px;
+	            border: solid #333;
+	            border-width: 0 0 2px 2px;
+	            transform: translate(-50%, -50%) rotate(-45deg);
+	          "></span>
+	        </span>
+          <span>完课</span>
+        </div>
+
+        <div style="display: flex; align-items: center; gap: 8px;">
+	        <span style="
+	          display: inline-block;
+	          width: 16px;
+	          height: 16px;
+	          border-radius: 2px;
+	          border: 2px solid #666;
+	          background-color: transparent;
+	          position: relative;
+	        ">
+	          <span style="
+	            position: absolute;
+	            top: 50%;
+	            left: 50%;
+	            width: 8px;
+	            height: 2px;
+	            background: #666;
+	            transform: translate(-50%, -50%) rotate(45deg);
+	          "></span>
+	          <span style="
+	            position: absolute;
+	            top: 50%;
+	            left: 50%;
+	            width: 8px;
+	            height: 2px;
+	            background: #666;
+	            transform: translate(-50%, -50%) rotate(-45deg);
+	          "></span>
+	        </span>
+          <span>待看课</span>
+        </div>
+
+        <div style="display: flex; align-items: center; gap: 8px;">
+	        <span style="
+	          display: inline-block;
+	          width: 16px;
+	          height: 16px;
+	          border-radius: 2px 8px;
+	          background-color: #f0f0f0;
+	          border: 1px solid #ddd;
+	          position: relative;
+	          transform: rotate(45deg);
+	        ">
+	          <span style="
+	            position: absolute;
+	            top: 50%;
+	            left: 50%;
+	            width: 6px;
+	            height: 6px;
+	            border: 2px solid #333;
+	            transform: translate(-50%, -50%) rotate(-45deg);
+	          "></span>
+	        </span>
+          <span>看课中断</span>
+        </div>
+
+        <div style="display: flex; align-items: center; gap: 8px;">
+	        <span style="
+	          display: inline-block;
+	          width: 16px;
+	          height: 16px;
+	          border-radius: 2px;
+	          background-color: #f0f0f0;
+	          border: 1px solid #ddd;
+	          position: relative;
+	        ">
+	          <span style="
+	            position: absolute;
+	            top: 50%;
+	            left: 50%;
+	            width: 8px;
+	            height: 2px;
+	            background: #999;
+	            transform: translate(-50%, -50%);
+	          "></span>
+	        </span>
+          <span>没发课</span>
+        </div>
 
+        <div style="display: flex; align-items: center; gap: 8px;">
+		    <span style="
+		      display: inline-block;
+		      width: 16px;
+		      height: 16px;
+		      border-radius: 2px;
+		      background-color: #f0f0f0;
+		      border: 1px solid #ddd;
+		      position: relative;
+		    ">
+		      <span  style="
+		        position: absolute;
+		        top: 50%;
+		        left: 50%;
+		        width: 8px;
+		        height: 2px;
+		        background: #666;
+		        transform: translate(-50%, -10%) rotate(-15deg);
+		      "></span>
+		    </span>
+          <span>看课中</span>
+        </div>
+
+
+      </div>
+    </div>
     <!-- 添加或修改企微任务看板对话框 -->
     <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
       <el-form ref="form" :model="form" :rules="rules" label-width="80px">
@@ -144,18 +401,34 @@
 <script>
 import { listQwWorkTask, getQwWorkTask, delQwWorkTask, addQwWorkTask, updateQwWorkTask, exportQwWorkTask,glList} from "@/api/qw/QwWorkTask";
 import {getMyQwUserList, getMyQwCompanyList, handleInputAuthAppKey, updateUser} from "@/api/qw/user";
+import { treeselect } from "@/api/company/companyDept";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+import { getCompanyUserListLikeName } from "@/api/company/companyUser";
 export default {
   name: "QwWorkTask",
+  components: { Treeselect  },
   data() {
     return {
-	  actName:"0",
+      actName:"0",
       // 遮罩层
       loading: true,
       // 导出遮罩层
       exportLoading: false,
+      companyUserOptionsParams: {
+        name: undefined,
+        hasNextPage: false,
+        pageNum: 1,
+        pageSize: 10
+      },
+      isSM:false,
+
+      companyUserOptionsLoading: false,
+      companyUserOptions: [],
       // 选中数组
       ids: [],
-	  myQwUserList:[],
+      deptOptions:[],
+      myQwUserList:[],
       // 非单个禁用
       single: true,
       // 非多个禁用
@@ -174,7 +447,7 @@ export default {
       statusOptions: [],
       // 类别 1先导 2 课程 3 大小转 4 转人工字典
       typeOptions: [],
-	  trackTypeOptions:[],
+      trackTypeOptions:[],
       // 查询参数
       queryParams: {
         pageNum: 1,
@@ -197,50 +470,88 @@ export default {
     };
   },
   created() {
-	this.handleGetMyQwUserList();
+    this.handleGetMyQwUserList();
     this.getDicts("sys_qw_work_task_status").then(response => {
       this.statusOptions = response.data;
     });
     this.getDicts("sys_qw_work_task_type").then(response => {
       this.typeOptions = response.data;
     });
-	this.getDicts("sys_qw_work_task_track_type").then(response => {
-	  this.trackTypeOptions = response.data;
-	});
+    this.getDicts("sys_qw_work_task_track_type").then(response => {
+      this.trackTypeOptions = response.data;
+    });
+    this.getTreeselect();
   },
   methods: {
-	getScoreStyle(score) {
-	let backgroundColor = '';
-	  if (score >= 15) {
-		backgroundColor = '#ff4d4f';    // 红色
-	  } else if (score >= 9) {
-		backgroundColor = '#ff7d45';    // 橘红
-	  } else if (score >= 4) {
-		backgroundColor = '#ffec3d';    // 黄色
-	  } else {
-		backgroundColor = '#ffffff';    // 白色
-	  }
-	  return { 
-		'background-color': backgroundColor,
-		'padding': '5px 10px',
-		'border-radius': '4px'
-	  };
-	},
-	formatTime(timeStr) {
-	      if (!timeStr && timeStr !== 0) return '';
-	      
-	      // 处理数字和字符串输入
-	      const str = String(timeStr).padStart(4, '0');
-	      
-	      // 提取有效部分
-	      const hours = str.substring(0, 2);
-	      const minutes = str.substring(2, 4);
-	      
-	      // 简单验证
-	      if (hours > 23 || minutes > 59) return '无效时间';
-	      
-	      return `${hours}:${minutes}`;
-	    },
+    getScoreStyle(score) {
+      let backgroundColor = '';
+      if (score >= 15) {
+        backgroundColor = '#ff4d4f';    // 红色
+      } else if (score >= 9) {
+        backgroundColor = '#ff7d45';    // 橘红
+      } else if (score >= 4) {
+        backgroundColor = '#ffec3d';    // 黄色
+      } else {
+        backgroundColor = '#ffffff';    // 白色
+      }
+      return {
+        'background-color': backgroundColor,
+        'padding': '5px 10px',
+        'border-radius': '4px'
+      };
+    },
+    getTreeselect() {
+      var that=this;
+      var param={companyId:this.companyId}
+      treeselect(param).then((response) => {
+        this.deptOptions = response.data;
+        console.log(this.deptOptions)
+        if(response.data!=null&&response.data.length>0){
+          //this.queryParams.deptId=response.data[0].id;
+        }
+      });
+    },
+    loadCompanyUserOptions(query) {
+      this.companyUserOptions = [];
+      if (query === '') {
+        return;
+      }
+
+      this.companyUserOptionsParams.pageNum = 1
+      this.companyUserOptionsParams.name = query
+      this.companyUserOptionsLoading = true;
+      this.getCompanyUserListLikeName()
+    },
+    getCompanyUserListLikeName() {
+      getCompanyUserListLikeName(this.companyUserOptionsParams).then(response => {
+        this.companyUserOptions = [...this.companyUserOptions, ...response.data.list]
+        this.companyUserOptionsParams.hasNextPage = response.data.hasNextPage
+        this.companyUserOptionsLoading = false;
+      });
+    },
+    loadMoreCompanyUserOptions() {
+      if (!this.companyUserOptionsParams.hasNextPage) {
+        return;
+      }
+
+      this.companyUserOptionsParams.pageNum += 1
+      this.getCompanyUserListLikeName()
+    },
+    formatTime(timeStr) {
+      if (!timeStr && timeStr !== 0) return '';
+
+      // 处理数字和字符串输入
+      const str = String(timeStr).padStart(4, '0');
+
+      // 提取有效部分
+      const hours = str.substring(0, 2);
+      const minutes = str.substring(2, 4);
+
+      // 简单验证
+      if (hours > 23 || minutes > 59) return '无效时间';
+
+      return `${hours}:${minutes}`;
+    },
     /** 查询企微任务看板列表 */
     getList() {
       this.loading = true;
@@ -250,10 +561,13 @@ export default {
         this.loading = false;
       });
     },
-	handleClickX(tab, event) {
-	  this.queryParams.status=tab.name;
-	  this.handleQuery();
-	},
+    handleClickX(tab, event) {
+      this.queryParams.status=tab.name;
+      this.handleQuery();
+    },
+    sm(){
+      this.isSM = this.isSM ? false : true;
+    },
     // 取消按钮
     cancel() {
       this.open = false;
@@ -283,10 +597,10 @@ export default {
       this.queryParams.pageNum = 1;
       this.getList();
     },
-	handleGetMyQwUserList(){
+    handleGetMyQwUserList(){
 
-		this.getList();
-	},
+      this.getList();
+    },
     /** 重置按钮操作 */
     resetQuery() {
       this.resetForm("queryForm");
@@ -308,9 +622,9 @@ export default {
     handleUpdate(row) {
       this.reset();
       const id = row.id || this.ids
-        this.form = row;
-        this.open = true;
-        this.title = "处理任务";
+      this.form = row;
+      this.open = true;
+      this.title = "处理任务";
 
     },
     /** 提交按钮 */
@@ -337,30 +651,30 @@ export default {
     handleDelete(row) {
       const ids = row.id || this.ids;
       this.$confirm('是否确认删除企微任务看板编号为"' + ids + '"的数据项?', "警告", {
-          confirmButtonText: "确定",
-          cancelButtonText: "取消",
-          type: "warning"
-        }).then(function() {
-          return delQwWorkTask(ids);
-        }).then(() => {
-          this.getList();
-          this.msgSuccess("删除成功");
-        }).catch(() => {});
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(function() {
+        return delQwWorkTask(ids);
+      }).then(() => {
+        this.getList();
+        this.msgSuccess("删除成功");
+      }).catch(() => {});
     },
     /** 导出按钮操作 */
     handleExport() {
       const queryParams = this.queryParams;
       this.$confirm('是否确认导出所有企微任务看板数据项?', "警告", {
-          confirmButtonText: "确定",
-          cancelButtonText: "取消",
-          type: "warning"
-        }).then(() => {
-          this.exportLoading = true;
-          return exportQwWorkTask(queryParams);
-        }).then(response => {
-          this.download(response.msg);
-          this.exportLoading = false;
-        }).catch(() => {});
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        this.exportLoading = true;
+        return exportQwWorkTask(queryParams);
+      }).then(response => {
+        this.download(response.msg);
+        this.exportLoading = false;
+      }).catch(() => {});
     }
   }
 };

+ 31 - 22
src/views/qw/qwChat/qq.vue

@@ -30,27 +30,17 @@
                    @menu-avatar-click="handleMenuAvatarClick"
                    @pick-image="handleImageClick"
                    @send="handleSend">
-        <template #cover>
-          <div>
-          </div>
-        </template>
-        <template #message-title="contact">
-          <div>
-          </div>
-        </template>
-
-        <template #sidebar-contact-fixedtop="contact">
-          <div>
-          </div>
-        </template>
-
-        <template #sidebar-message-fixedtop="message">
-          <div>
-          </div>
-        </template>
-
-        <template #message-side="contact">
-          <div>
+        <template #sidebar-message-top>
+          <div style="padding: 8px;">
+            <el-input
+              v-model="searchKeyword"
+              prefix-icon="el-icon-search"
+              placeholder="搜索"
+              size="small"
+              clearable
+              @input="handleSearch"
+              style="width: 100%;"
+            />
           </div>
         </template>
       </lemon-imui>
@@ -157,7 +147,8 @@ export default {
         open: false
       },
       imSocket: null,
-      imUrl: process.env.VUE_APP_IM_WS_URL
+      imUrl: process.env.VUE_APP_IM_WS_URL,
+      searchKeyword: '',
     };
   },
   created(){
@@ -521,6 +512,24 @@ export default {
         this.$refs.userDetail.getDetail(sessionId);
       }, 1);
     },
+    // 搜索
+    handleSearch() {
+      const keyword = this.searchKeyword.trim().toLowerCase();
+      if (!keyword) {
+        // 为空时显示全部
+        this.$refs.IMUI.initConversations(this.conversationData);
+        return;
+      }
+      // 过滤会话列表
+      const filtered = this.conversationData.filter(item => {
+        // 搜索最后一条消息内容和联系人名
+        return (
+          (item.lastContent && item.lastContent.toLowerCase().includes(keyword)) ||
+          (item.displayName && item.displayName.toLowerCase().includes(keyword))
+        );
+      });
+      this.$refs.IMUI.initConversations(filtered);
+    },
   },
 };
 </script>

+ 0 - 12
src/views/qw/qwChat/userDetail/index.vue

@@ -63,13 +63,6 @@
       </el-descriptions>
     </div>
 
-    <div class="contentx" v-if="item.userId != null" >
-      <div class="desct">
-        用户地址
-      </div>
-      <userAddDetails  ref="userAddDetail" />
-    </div>
-
     <div class="contentx" v-if="item.userId != null" >
       <div class="desct">
         用户订单
@@ -88,14 +81,12 @@
 
 <script>
 import {getUserInfoBySessionId} from "@/api/users/user";
-import userAddDetails from "@/views/qw/qwChat/userDetail/userAddDetails.vue";
 import userStorerDetails from "@/views/qw/qwChat/userDetail/userStorerDetails.vue"
 import userCourseWatchLog from "@/views/qw/qwChat/userDetail/userCourseWatchLog.vue";
 
 export default {
   name: "userDetail",
   components: {
-    userAddDetails,
     userStorerDetails,
     userCourseWatchLog
   },
@@ -119,9 +110,6 @@ export default {
       getUserInfoBySessionId(params).then(response => {
         this.item = response.data;
         if (this.item.userId != null) {
-            setTimeout(() => {
-              this.$refs.userAddDetail.getAddList(this.item.userId);
-            }, 1);
             setTimeout(() => {
               this.$refs.userDetails.getUserDetails(this.item.userId);
             }, 1);

+ 0 - 374
src/views/qw/qwChat/userDetail/userAddDetails.vue

@@ -1,374 +0,0 @@
-<template>
-  <div >
-    <el-row :gutter="10" class="mb8" style="float: right; top: -30px;">
-      <el-col :span="1.5">
-        <el-button
-          type="primary"
-          plain
-          icon="el-icon-plus"
-          size="mini"
-          @click="handleAdd"
-          v-hasPermi="['store:userAddress:add']"
-        >新增</el-button>
-      </el-col>
-    </el-row>
-
-    <el-table v-loading="loading" border="" :data="userAddressList" @selection-change="handleSelectionChange" style="top: -30px;">
-      <el-table-column label="收货人姓名" align="center" prop="realName" />
-      <el-table-column label="收货人电话" align="center" prop="phone" />
-      <el-table-column label="收货人所在省" align="center" prop="province" />
-      <el-table-column label="收货人所在市" align="center" prop="city" />
-      <el-table-column label="收货人所在区" align="center" prop="district" />
-      <el-table-column label="收货人详细地址" align="center" prop="detail" />
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
-        <template slot-scope="scope">
-          <el-button
-            size="mini"
-            type="text"
-            icon="el-icon-edit"
-            @click="handleUpdate(scope.row)"
-            v-hasPermi="['store:userAddress:edit']"
-          >修改</el-button>
-          <el-button
-            size="mini"
-            type="text"
-            icon="el-icon-delete"
-            @click="handleDelete(scope.row)"
-            v-hasPermi="['store:userAddress:remove']"
-          >删除</el-button>
-        </template>
-      </el-table-column>
-    </el-table>
-
-    <pagination
-      v-show="total>0"
-      :total="total"
-      :page.sync="queryParams.pageNum"
-      :limit.sync="queryParams.pageSize"
-      @pagination="getList"
-    />
-
-    <!-- 添加或修改用户地址对话框 -->
-    <el-dialog :title="title" :visible.sync="open" width="700px" append-to-body>
-      <el-form ref="form" :model="form" :rules="rules" label-width="110px">
-      <el-form-item label="智能识别" prop="address">
-        <el-input v-model="address" placeholder="输入需要识别的地址" >  <el-button slot="append" icon="el-icon-search" @click="sAddress"></el-button></el-input>
-      </el-form-item>
-        <el-form-item label="收货人姓名" prop="realName">
-          <el-input v-model="form.realName" placeholder="请输入收货人姓名" />
-        </el-form-item>
-        <el-form-item label="收货人电话" prop="phone">
-          <el-input v-model="form.phone" placeholder="请输入收货人电话" />
-        </el-form-item>
-        <el-form-item label="省市区" >
-          <el-cascader
-          ref="citySelect"
-          v-model="cityIds"
-          :options="citys"
-          @change="handleCityChange">
-          </el-cascader>
-        </el-form-item>
-        <el-form-item label="详细地址" prop="detail">
-          <el-input v-model="form.detail" placeholder="请输入收货人详细地址" />
-        </el-form-item>
-        <el-form-item label="是否默认地址" prop="isDefault">
-          <el-radio-group v-model="form.isDefault">
-            <el-radio :label="item.dictValue" v-for="item in orOptions" >{{item.dictLabel}}</el-radio>
-          </el-radio-group>
-        </el-form-item>
-      </el-form>
-      <div slot="footer" class="dialog-footer">
-        <el-button type="primary" @click="submitForm">确 定</el-button>
-        <el-button @click="cancel">取 消</el-button>
-      </div>
-    </el-dialog>
-  </div>
-</template>
-
-<script>
-import { getAddress,listUserAddress, getUserAddress, delUserAddress, addUserAddress, updateUserAddress, exportUserAddress } from "@/api/store/userAddress";
-import {getCitys} from "@/api/store/city";
-export default {
-  name: "UserAddress",
-  data() {
-    return {
-      // 遮罩层
-      loading: true,
-      // 导出遮罩层
-      exportLoading: false,
-      orOptions: [],
-      // 选中数组
-      ids: [],
-      // 非单个禁用
-      single: true,
-      // 非多个禁用
-      multiple: true,
-      // 显示搜索条件
-      showSearch: true,
-      // 总条数
-      total: 0,
-      // 用户地址表格数据
-      userAddressList: [],
-      // 弹出层标题
-      title: "",
-      // 是否显示弹出层
-      open: false,
-      cityIds:null,
-      address:null,
-      // 查询参数
-      queryParams: {
-        pageNum: 1,
-        pageSize: 10,
-        userId: null,
-        realName: null,
-        phone: null,
-        province: null,
-        city: null,
-        district: null,
-        cityIds: null,
-        detail: null,
-        postCode: null,
-        longitude: null,
-        latitude: null,
-        isDefault: null,
-        isDel: 0,
-      },
-      // 表单参数
-      form: {},
-      // 表单校验
-      rules: {
-        userId: [
-          { required: true, message: "用户id不能为空", trigger: "blur" }
-        ],
-        realName: [
-          { required: true, message: "收货人姓名不能为空", trigger: "blur" }
-        ],
-        phone: [
-          { required: true, message: "收货人电话不能为空", trigger: "blur" },
-          {
-                      pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
-                      message: "请输入正确的手机号码",
-                      trigger: "blur"
-                    }
-        ],
-        province: [
-          { required: true, message: "收货人所在省不能为空", trigger: "blur" }
-        ],
-        city: [
-          { required: true, message: "收货人所在市不能为空", trigger: "blur" }
-        ],
-        district: [
-          { required: true, message: "收货人所在区不能为空", trigger: "blur" }
-        ],
-        detail: [
-          { required: true, message: "收货人详细地址不能为空", trigger: "blur" }
-        ],
-        isDefault: [
-          { required: true, message: "是否默认不能为空", trigger: "blur" }
-        ],
-        cityIds: [
-          { required: true, message: "不能为空", trigger: "blur" }
-        ],
-      },
-      citys: []
-    };
-  },
-  created() {
-    this.getCitys();
-    this.getDicts("sys_company_or").then(response => {
-      this.orOptions = response.data;
-    });
-  },
-  methods: {
-    /** 查询用户地址列表 */
-    getList() {
-      this.loading = true;
-      listUserAddress(this.queryParams).then(response => {
-        this.userAddressList = response.rows;
-        this.total = response.total;
-        this.loading = false;
-
-      });
-    },
-    getAddList(id) {
-      this.queryParams.userId=id;
-      this.loading = true;
-      listUserAddress(this.queryParams).then(response => {
-        this.userAddressList = response.rows;
-        this.total = response.total;
-        this.loading = false;
-
-      });
-    },
-
-    // 取消按钮
-    cancel() {
-      this.open = false;
-      this.reset();
-    },
-    // 表单重置
-    reset() {
-      this.form = {
-        id: null,
-        userId: null,
-        realName: null,
-        phone: null,
-        province: null,
-        city: null,
-        district: null,
-        cityIds: null,
-        detail: null,
-        postCode: null,
-        longitude: null,
-        latitude: null,
-        isDefault: null,
-        isDel: null,
-        createTime: null,
-        updateTime: null
-      };
-      this.address=null;
-      this.cityIds=[];
-      this.resetForm("form");
-    },
-    getCitys(){
-        getCitys().then(res => {
-          this.citys=res.data;
-        })
-    },
-    /** 搜索按钮操作 */
-    handleQuery() {
-      this.queryParams.pageNum = 1;
-      this.getList();
-    },
-    /** 重置按钮操作 */
-    resetQuery() {
-      this.resetForm("queryForm");
-      this.handleQuery();
-    },
-    // 多选框选中数据
-    handleSelectionChange(selection) {
-      this.ids = selection.map(item => item.id)
-      this.single = selection.length!==1
-      this.multiple = !selection.length
-    },
-    handleCityChange(value) {
-      var nodes=this.$refs.citySelect.getCheckedNodes();
-      this.cityIds=value.toString();
-      this.form.province=nodes[0].pathLabels[0];
-      this.form.city=nodes[0].pathLabels[1];
-      this.form.district=nodes[0].pathLabels[2];
-    },
-
-    sAddress(){
-
-      getAddress(this.address).then(response => {
-
-        var addressJson = response.data;
-        this.msgSuccess(addressJson.reason);
-        this.form.province=addressJson.data.provinceName;
-        this.form.city=addressJson.data.cityName;
-        this.form.district=addressJson.data.expAreaName;
-        this.form.detail=addressJson.data.streetName+addressJson.data.address;
-        this.form.realName=addressJson.data.name;
-        this.form.phone=addressJson.data.mobile;
-
-        var province= this.citys.find(function(o) {
-           return o.label ==addressJson.data.provinceName ;
-         });
-         var city= province.children.find(function(o) {
-            return o.label == addressJson.data.cityName;
-          });
-        var district= city.children.find(function(o) {
-             return o.label == addressJson.data.expAreaName;
-           });
-        this.cityIds=[province.value,city.value,district.value]
-
-      });
-    },
-
-
-    /** 新增按钮操作 */
-    handleAdd() {
-      this.reset();
-      this.open = true;
-      this.title = "添加用户地址";
-    },
-    /** 修改按钮操作 */
-    handleUpdate(row) {
-      this.reset();
-      const addressId = row.id || this.ids
-      getUserAddress(addressId).then(response => {
-        this.form = response.data;
-        var province= this.citys.find(function(o) {
-           return o.label ==response.data.province ;
-         });
-         var city= province.children.find(function(o) {
-            return o.label == response.data.city;
-          });
-          var district= city.children.find(function(o) {
-             return o.label == response.data.district;
-           });
-        if(this.form.isDefault!=null){
-           this.form.isDefault = String(this.form.isDefault)
-        }
-        this.cityIds=[province.value,city.value,district.value]
-        this.open = true;
-        this.title = "修改用户地址";
-      });
-    },
-    /** 提交按钮 */
-    submitForm() {
-      this.$refs["form"].validate(valid => {
-        if (valid) {
-          if(this.form.city==null||this.form.province==null||this.form.district==null){
-           return this.msgSuccess("省市区不能为空");
-          }
-          if (this.form.id != null) {
-            updateUserAddress(this.form).then(response => {
-              this.msgSuccess("修改成功");
-              this.open = false;
-              this.getList();
-            });
-          } else {
-            this.form.userId=this.queryParams.userId
-            addUserAddress(this.form).then(response => {
-              this.msgSuccess("新增成功");
-              this.open = false;
-              this.getList();
-            });
-          }
-        }
-      });
-    },
-    /** 删除按钮操作 */
-    handleDelete(row) {
-      const addressIds = row.id || this.ids;
-      this.$confirm('是否确认删除用户地址编号为"' + addressIds + '"的数据项?', "警告", {
-          confirmButtonText: "确定",
-          cancelButtonText: "取消",
-          type: "warning"
-        }).then(function() {
-          return delUserAddress(addressIds);
-        }).then(() => {
-          this.getList();
-          this.msgSuccess("删除成功");
-        }).catch(() => {});
-    },
-    /** 导出按钮操作 */
-    handleExport() {
-      const queryParams = this.queryParams;
-      this.$confirm('是否确认导出所有用户地址数据项?', "警告", {
-          confirmButtonText: "确定",
-          cancelButtonText: "取消",
-          type: "warning"
-        }).then(() => {
-          this.exportLoading = true;
-          return exportUserAddress(queryParams);
-        }).then(response => {
-          this.download(response.msg);
-          this.exportLoading = false;
-        }).catch(() => {});
-    }
-  }
-};
-</script>

+ 5 - 5
src/views/qw/user/index.vue

@@ -127,7 +127,7 @@
             icon="el-icon-sunny"
             plain
             @click="handleLoginQwCode(scope.row)"
-            v-hasPermi="['qw:user:login']"
+            v-hasPermi="['qw:user:loginQwIpad']"
           >
             登录企微
           </el-button>
@@ -138,7 +138,7 @@
             icon="el-icon-moon"
             plain
             @click="handleLoginOutQwStatus(scope.row)"
-            v-hasPermi="['qw:user:login']"
+            v-hasPermi="['qw:user:outLoginQwIpad']"
           >
             退出企微
           </el-button>
@@ -149,7 +149,7 @@
             icon="el-icon-moon"
             plain
             @click="handleTwoCode(scope.row)"
-            v-hasPermi="['qw:user:login']">
+            v-hasPermi="['qw:user:twoCode']">
             二次验证
           </el-button>
           <el-button
@@ -159,7 +159,7 @@
             icon="el-icon-moon"
             plain
             @click="handleGetQwIpad(scope.row)"
-            v-hasPermi="['qw:user:login']"
+            v-hasPermi="['qw:user:getQwIpad']"
           >
             获取Ai主机
           </el-button>
@@ -170,7 +170,7 @@
             icon="el-icon-moon"
             plain
             @click="handleDelQwIpad(scope.row)"
-            v-hasPermi="['qw:user:login']"
+            v-hasPermi="['qw:user:delQwIpad']"
           >
             解绑Ai主机
           </el-button>