Jelajahi Sumber

Merge remote-tracking branch 'origin/master'

yfh 1 Minggu lalu
induk
melakukan
0e3260cf0b

+ 0 - 28
.env.prod-fcky

@@ -1,28 +0,0 @@
-# 页面标题
-VUE_APP_TITLE =客户管理系统
-# 公司名称
-VUE_APP_COMPANY_NAME =蜂巢快药(北京)医药连锁有限公司
-# ICP备案号
-VUE_APP_ICP_RECORD =京ICP备2025120013号
-# ICP网站访问地址
-VUE_APP_ICP_URL =https://beian.miit.gov.cn
-# 网站LOG
-VUE_APP_LOG_URL =@/assets/logo/fcky.png
-
-# 生产环境配置
-ENV = 'production'
-
-# FS管理系统/开发环境
-VUE_APP_BASE_API = '/prod-api'
-
-
-#默认 1、会员 2、企微
-VUE_APP_COURSE_DEFAULT = 1
-
-# 路由懒加载
-VUE_CLI_BABEL_TRANSPILE_MODULES = true
-
-# 患者信息
-VUE_APP_PATIENT_INFO = '客户信息'
-# 添加病人
-VUE_APP_ADD_PATIENT = '添加信息'

+ 1 - 1
.env.prod-sxjz

@@ -1,5 +1,5 @@
 # 页面标题
-VUE_APP_TITLE =互联网医院管理系统
+VUE_APP_TITLE =挑宝SCRM客服系统
 # 公司名称
 VUE_APP_COMPANY_NAME =银川鑫泰互联网医院有限公司
 # ICP备案号

+ 1 - 1
.env.prod-syysy

@@ -1,5 +1,5 @@
 # 页面标题
-VUE_APP_TITLE =互联网医院管理系统
+VUE_APP_TITLE =益寿缘SCRM客服系统
 # 公司名称
 VUE_APP_COMPANY_NAME =沈阳铁西益寿缘中医院有限责任公司
 # ICP备案号

+ 6 - 0
src/api/company/company.js

@@ -43,3 +43,9 @@ export function allList(query) {
   })
 }
 
+export function getCompanyListByCorId(corId) {
+  return request({
+    url: '/company/company/getCompanyListByCorId/' + corId,
+    method: 'get'
+  })
+}

+ 18 - 1
src/api/qw/externalContact.js

@@ -25,6 +25,15 @@ export function myDeptExtList(query) {
     params: query
   })
 }
+
+export function companyExtList(query) {
+  return request({
+    url: '/qw/externalContact/companyExtList',
+    method: 'get',
+    params: query
+  })
+}
+
 export function myList(query) {
   return request({
     url: '/qw/externalContact/myList',
@@ -296,4 +305,12 @@ export function delLossStatisticsExport(query) {
     method: 'get',
     params: query
   })
-}
+}
+
+export function companyTransfer(data) {
+  return request({
+    url: '/qw/externalContact/companyTransfer',
+    method: 'post',
+    data: data
+  })
+}

+ 23 - 0
src/api/qw/externalContactTransferAudit.js

@@ -0,0 +1,23 @@
+import request from '@/utils/request'
+
+export function listExternalContactTransferAudit(query) {
+  return request({
+    url: '/qw/externalContactTransferCompanyAudit/list',
+    method: 'get',
+    params: query
+  })
+}
+
+export function detail(id) {
+  return request({
+    url: '/qw/externalContactTransferCompanyAudit/detail/' + id,
+    method: 'get'
+  })
+}
+
+export function sync(id) {
+  return request({
+    url: '/qw/externalContactTransferCompanyAudit/sync/' + id,
+    method: 'post'
+  })
+}

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

@@ -390,3 +390,11 @@ export function qwRestartCloudHost(params) {
     params: params
   })
 }
+
+export function companyQwUserlist(params) {
+  return request({
+    url: '/qw/user/companyQwUserlist',
+    method: 'get',
+    params: params
+  })
+}

+ 0 - 5
src/views/company/companyUser/index.vue

@@ -180,11 +180,6 @@
                 :type="scope.row.isNeedRegisterMember === 1 ? 'success' : 'info'">{{scope.row.isNeedRegisterMember === 1 ? '是' : '否' }}</el-tag>
             </template>
           </el-table-column>
-          <el-table-column label="创建时间"  sortable align="center" prop="createTime" width="160">
-            <template slot-scope="scope">
-              <span>{{ parseTime(scope.row.createTime) }}</span>
-            </template>
-          </el-table-column>
           <el-table-column label="允许注册会员" align="center" prop="isNeedRegisterMember" width="80px">
             <template slot-scope="scope">
               <el-tag

+ 188 - 32
src/views/qw/contactWay/index.vue

@@ -204,15 +204,27 @@
               <el-col :span="22">
                 <div style="background-color: #fbfbfb;padding: 15px;  border: 1px solid #e6e6e6; margin-bottom: 20px;">
                   <el-form :model="item"  label-width="80px">
-                    <el-form-item label="员工选择"  style="height: 50px;">
-                       <el-select v-model="item.userIds" remote multiple placeholder="请选择" filterable  style="width: 100%;">
-                         <el-option
-                           v-for="dict in companyUserList"
-                           :key="dict.qwUserId"
-                           :label="dict.qwUserName"
-                           :value="dict.qwUserId">
-                         </el-option>
-                       </el-select>
+                    <el-form-item label="员工选择">
+                      <div>
+                        <el-button
+                          size="medium"
+                          icon="el-icon-circle-plus-outline"
+                          plain
+                          @click="handleListUserForTimeSlot(index)">请选择使用员工
+                        </el-button>
+                      </div>
+                      <div style="margin-top: 10px;">
+                        <el-tag
+                          style="margin-left: 5px; margin-top: 5px;"
+                          size="medium"
+                          :key="user.id"
+                          v-for="user in item.userList || []"
+                          closable
+                          :disable-transitions="false"
+                          @close="handleCloseTimeSlotUser(index, user)">
+                          {{ user.qwUserName }}
+                        </el-tag>
+                      </div>
                     </el-form-item>
                     <el-form-item label="工作周期" prop="week" style="height: 50px;" >
                        <el-select v-model="item.week" remote multiple placeholder="请选择" filterable  style="width: 100%;">
@@ -256,14 +268,27 @@
            <el-link type="primary" class="el-icon-plus" :underline="false" @click='addUserTime()'>添加其他工作周期</el-link>
         </el-form-item>
         <el-form-item label=""  v-if="form.userType==1">
-         <el-select v-model="userIds" remote multiple placeholder="选择全天在线员工" filterable  style="width: 800px;" :change="userChange()">
-           <el-option
-             v-for="dict in companyUserList"
-             :label="dict.qwUserName"
-             :value="dict.qwUserId">
-           </el-option>
+          <div>
+            <el-button
+              size="medium"
+              icon="el-icon-circle-plus-outline"
+              plain
+              @click="handleListUser(form.type,form.sendType, true)">请选择使用员工
+            </el-button>
+          </div>
+          <div>
+            <el-tag
+              style="margin-left: 5px"
+              size="medium"
+              :key="user.id"
+              v-for="user in userSelectList"
+              closable
+              :disable-transitions="false"
+              @close="handleCloseGroupUser(user)">
+              {{ user.qwUserName }}
+            </el-tag>
+          </div>
 
-         </el-select>
         </el-form-item>
         <el-form-item label="员工添加上限"v-if="form.userType==1" prop="isUserLimit">
           <el-switch
@@ -595,7 +620,7 @@
           </div>
           <div v-if="fileFrom.videoId!=null">
             <el-form-item label="图文链接:"  label-width="100px" >
-              <el-tag type="warning" v-model="fileFrom.linkUrl='待生成'">选择的课程小节 即为卡片链接地址</el-tag>
+              <el-tag type="warning">选择的课程小节 即为卡片链接地址</el-tag>
             </el-form-item>
           </div>
           <div v-if="fileFrom.videoId!=null">
@@ -646,6 +671,9 @@
       </div>
     </el-dialog>
 
+    <el-dialog :title="listUser.title" :visible.sync="listUser.open" width="700px" append-to-body>
+      <qwUserList ref="QwUserList" @selectUserList="selectUserList"></qwUserList>
+    </el-dialog>
 
     </div>
         <el-drawer
@@ -667,9 +695,10 @@ import ImageUpload from '@/views/qw/material/ImageUpload.vue'
 import statisDetails from '@/views/qw/contactWay/statisDetails';
 import { getMyQwUserList,getMyQwCompanyList } from "@/api/qw/user";
 import {courseList, videoList} from "@/api/qw/sop";
+import qwUserList from "@/views/qw/user/qwUserList.vue";
 export default {
   name: "ContactWay",
-   components: { contactWayGroup,ImageUpload,statisDetails},
+   components: {qwUserList, contactWayGroup,ImageUpload,statisDetails},
   data() {
     return {
       // 遮罩层
@@ -679,7 +708,8 @@ export default {
       exportLoading: false,
       // 选中数组
       ids: [],
-      userTimeJson:[{userIds:null,week:[1,2,3,4,5,6,7],startTime:null,endTime:null}],
+      userTimeJson:[{userIds:null,userList:[],week:[1,2,3,4,5,6,7],startTime:null,endTime:null}],
+      currentEditingTimeSlotIndex: -1, // 当前正在编辑的时间段索引
       userIds:[],
       show:{
            title:"医院详情",
@@ -829,6 +859,13 @@ export default {
       tagGroupList:[],
       tagList:[],
       tagListForm:[],
+      // 选择使用员工相关参数
+      userSelectList: [],
+      //企业微信员工
+      listUser: {
+        title: "",
+        open: false
+      },
     };
   },
   created() {
@@ -1172,7 +1209,7 @@ export default {
       });
     },
     addUserTime(){
-      this.userTimeJson.push({userIds:null,week:[1,2,3,4,5,6,7],startTime:null,endTime:null})
+      this.userTimeJson.push({userIds:null,userList:[],week:[1,2,3,4,5,6,7],startTime:null,endTime:null})
     },
     delUserTime(index){
       this.userTimeJson.splice(index,1)
@@ -1270,9 +1307,11 @@ export default {
               userTimeJson: null,
               userType: 2
             };
-              this.userTimeJson=[{userIds:null,week:[1,2,3,4,5,6,7],startTime:null,endTime:null}];
+              this.userTimeJson=[{userIds:null,userList:[],week:[1,2,3,4,5,6,7],startTime:null,endTime:null}];
+              this.currentEditingTimeSlotIndex = -1;
               this.userLimitJson=[];
               this.userIds=[];
+              this.userSelectList=[];
               this.spareUserIds=[];
               this.tagListForm=[];
               this.closeWelcomeWord=[];
@@ -1332,15 +1371,42 @@ export default {
       getContactWay(id).then(response => {
         this.form = response.data;
         this.open = true;
-        if(this.form.userTimeJson!=null){
-          this.userTimeJson=JSON.parse(this.form.userTimeJson)
-        }else{ this.userTimeJson=[{userIds:null,week:[1,2,3,4,5,6,7],startTime:null,endTime:null}]}
+
+        // 根据 userType 区分处理
+        if(this.form.userType === 2) {
+          // 自动上下线模式 - 只回显 userTimeJson
+          if(this.form.userTimeJson!=null){
+            this.userTimeJson=JSON.parse(this.form.userTimeJson)
+            // 根据 userIds回显userList
+            this.userTimeJson.forEach(timeSlot => {
+              if (!timeSlot.userList) {
+                timeSlot.userList = [];
+              }
+              if (timeSlot.userIds && Array.isArray(timeSlot.userIds)) {
+                timeSlot.userList = timeSlot.userIds.map(qwUserId => {
+                  return this.companyUserList.find(u => u.qwUserId === qwUserId);
+                }).filter(u => u); // 过滤掉 undefined
+              }
+            });
+          }else{
+            this.userTimeJson=[{userIds:null,userList:[],week:[1,2,3,4,5,6,7],startTime:null,endTime:null}]
+          }
+        } else if(this.form.userType === 1) {
+          // 全天在线模式 - 只回显 userSelectList
+          if(this.form.userIds!=null){
+            this.userIds=JSON.parse(this.form.userIds)
+            this.userSelectList = this.userIds.map(qwUserId => {
+              return this.companyUserList.find(u => u.qwUserId === qwUserId);
+            }).filter(u => u); // 过滤掉 undefined
+          }else{
+            this.userIds=[]
+            this.userSelectList=[]
+          }
+        }
+
         if(this.form.userLimitJson!=null){
           this.userLimitJson=JSON.parse(this.form.userLimitJson)
         }else{ this.userLimitJson=[]}
-        if(this.form.userIds!=null){
-          this.userIds=JSON.parse(this.form.userIds)
-        }else{ this.userIds=[]}
         if(this.form.spareUserIds!=null){
           this.spareUserIds=JSON.parse(this.form.spareUserIds)
         }else{ this.spareUserIds=[]}
@@ -1362,10 +1428,23 @@ export default {
       this.$refs["form"].validate(valid => {
         if (valid) {
           this.form.corpId=this.queryParams.corpId
+          if(this.form.userType === 1){
+            if(Object.keys(this.userIds).length === 0){
+              return this.$message({
+                message: '请选择客服类型-使用员工',
+                type: 'warning'
+              });
+            }
+          }
           if(this.form.userType==2){
             var jsonUserIds=[];
             for (let i = 0; i < this.userTimeJson.length; i++) {
-                if(this.userTimeJson[i].userIds==null||this.userTimeJson[i].userIds==""){
+                // 确保 userIds 与 userList 同步
+                if(this.userTimeJson[i].userList && this.userTimeJson[i].userList.length > 0){
+                  this.userTimeJson[i].userIds = this.userTimeJson[i].userList.map(u => u.qwUserId);
+                }
+
+                if(this.userTimeJson[i].userIds==null||this.userTimeJson[i].userIds=="" || this.userTimeJson[i].userIds.length==0){
                   return this.$message('人员不能为空');
                 }
                 if(this.userTimeJson[i].week==null||this.userTimeJson[i].week==""){
@@ -1379,9 +1458,7 @@ export default {
                 }
 
                 for (let j = 0; j < this.userTimeJson[i].userIds.length; j++) {
-                  console.log("!jsonUserIds.find(item=>item==this.userTimeJson[i].userIds[j])")
                   if(!jsonUserIds.find(item=>item==this.userTimeJson[i].userIds[j])){
-
                     jsonUserIds.push(this.userTimeJson[i].userIds[j]);
                   }
                 }
@@ -1392,7 +1469,12 @@ export default {
           }
           this.form.closeWelcomeWord=JSON.stringify(this.closeWelcomeWord)
           this.form.userIds=JSON.stringify(this.userIds)
-          this.form.userTimeJson=JSON.stringify(this.userTimeJson)
+          // 提交前移除 userList 字段(因为后端只需要 userIds)
+          const userTimeJsonForSubmit = this.userTimeJson.map(item => {
+            const {userList, ...rest} = item;
+            return rest;
+          });
+          this.form.userTimeJson=JSON.stringify(userTimeJsonForSubmit)
           this.form.userLimitJson=JSON.stringify(this.userLimitJson)
           this.form.spareUserIds=JSON.stringify(this.spareUserIds)
           this.form.tags=JSON.stringify(this.tagListForm)
@@ -1441,7 +1523,81 @@ export default {
           this.download(response.msg);
           this.exportLoading = false;
         }).catch(() => {});
-    }
+    },
+    //选择企微员工时
+    handleListUser(type, sendType, selectOne) {
+      setTimeout(() => {
+        this.$refs.QwUserList.getDetails(this.form.corpId, type, sendType, selectOne);
+      }, 1);
+
+      this.listUser.title = "选择企微员工"
+      this.listUser.open = true;
+
+    },
+    //企业微信员工信息子组件返回
+    selectUserList(list) {
+      this.listUser.open = false;
+      console.log("选择的员工",list)
+
+      // 判断是全天在线还是自动上下线
+      if (this.currentEditingTimeSlotIndex === -1) {
+        // 全天在线模式
+        list.forEach(obj => {
+          if (!this.userSelectList.some(item => item.id === obj.id)) {
+            this.userSelectList.push(obj);  // 存储完整对象
+            this.userIds.push(obj.qwUserId);
+          }
+        });
+      } else {
+        // 自动上下线模式 - 为特定时间段添加员工
+        const timeSlot = this.userTimeJson[this.currentEditingTimeSlotIndex];
+        if (!timeSlot.userList) {
+          this.$set(timeSlot, 'userList', []);
+        }
+        if (!timeSlot.userIds) {
+          this.$set(timeSlot, 'userIds', []);
+        }
+
+        list.forEach(obj => {
+          if (!timeSlot.userList.some(item => item.id === obj.id)) {
+            timeSlot.userList.push(obj);
+            timeSlot.userIds.push(obj.qwUserId);
+          }
+        });
+
+        // 重置索引
+        this.currentEditingTimeSlotIndex = -1;
+      }
+    },
+    // 全天在线模式 - 删除员工标签
+    handleCloseGroupUser(user) {
+      const index = this.userSelectList.findIndex(t => t.id === user.id);
+      if (index !== -1) {
+        this.userSelectList.splice(index, 1);
+        this.userIds.splice(index, 1);
+      }
+    },
+    // 自动上下线模式 - 打开员工选择弹窗
+    handleListUserForTimeSlot(timeSlotIndex) {
+      this.currentEditingTimeSlotIndex = timeSlotIndex;
+      setTimeout(() => {
+        this.$refs.QwUserList.getDetails(this.form.corpId, this.form.type, this.form.sendType, true);
+      }, 1);
+      this.listUser.title = "选择企微员工"
+      this.listUser.open = true;
+    },
+    // 自动上下线模式 - 删除时间段员工标签
+    handleCloseTimeSlotUser(timeSlotIndex, user) {
+      const timeSlot = this.userTimeJson[timeSlotIndex];
+      const userListIndex = timeSlot.userList.findIndex(t => t.id === user.id);
+      if (userListIndex !== -1) {
+        // 使用 splice 删除并强制更新
+        timeSlot.userList.splice(userListIndex, 1);
+        timeSlot.userIds.splice(userListIndex, 1);
+        // 强制更新整个 userTimeJson 数组以触发响应式更新
+        this.$set(this.userTimeJson, timeSlotIndex, {...timeSlot});
+      }
+    },
   }
 };
 </script>

+ 445 - 0
src/views/qw/externalContactTransfer/companyTransfer.vue

@@ -0,0 +1,445 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="110px">
+      <el-form-item label="企微公司" prop="corpId">
+        <el-select v-model="queryParams.corpId" placeholder="企微公司"  size="small" @change="updateCorpId()">
+          <el-option
+            v-for="dict in myQwCompanyList"
+            :key="dict.dictValue"
+            :label="dict.dictLabel"
+            :value="dict.dictValue"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="客户名称" prop="name">
+        <el-input
+          v-model="queryParams.name"
+          placeholder="请输入客户名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </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="type">
+        <el-select v-model="queryParams.type" placeholder="请选择用户类别" clearable size="small">
+          <el-option
+            v-for="dict in typeOptions"
+            :key="dict.dictValue"
+            :label="dict.dictLabel"
+            :value="dict.dictValue"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="客户等级" prop="level">
+        <el-select v-model="queryParams.level" placeholder="客户等级" clearable size="small">
+          <el-option
+            v-for="dict in ratingType"
+            :key="dict.dictValue"
+            :label="dict.dictLabel"
+            :value="dict.dictValue"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="性别" prop="gender">
+        <el-input
+          v-model="queryParams.gender"
+          placeholder="请输入性别"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="转接状态" prop="addWay">
+        <el-select v-model="queryParams.transferStatus" placeholder="转接状态" clearable size="small">
+          <el-option
+            v-for="dict in transferStatusOptions"
+            :key="dict.dictValue"
+            :label="dict.dictLabel"
+            :value="dict.dictValue"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="标签" prop="tagIds">
+        <el-select v-model="selectTags" remote multiple placeholder="请选择" filterable  style="width: 100%;">
+          <el-option
+            v-for="dict in tagList"
+            :label="dict.name"
+            :value="dict.tagId">
+          </el-option>
+        </el-select>
+      </el-form-item>
+      <el-form-item label="添加时间" prop="createTime">
+        <el-date-picker clearable size="small"
+                        v-model="queryParams.createTime"
+                        type="date"
+                        value-format="yyyy-MM-dd"
+                        placeholder="选择添加时间">
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          :loading="exportLoading"
+          @click="handleExport"
+          v-hasPermi="['qw:externalContact:companyExport']"
+        >导出</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          size="mini"
+          @click="handleTransfer"
+          :disabled="multiple"
+          v-hasPermi="['qw:externalContact:companyTransfer']"
+        >分配客户</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="externalContactList" @selection-change="handleSelectionChange" border>
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="所属员工" align="center" prop="qwUserName" width="120px"/>
+      <el-table-column label="员工部门" align="center" prop="departmentName" width="120px"/>
+      <el-table-column label="客户名称" align="center" prop="name" />
+      <el-table-column label="头像" align="center" prop="avatar" width="100px">
+        <template slot-scope="scope">
+          <el-popover
+            placement="right"
+            title=""
+            trigger="hover">
+            <img slot="reference" :src="scope.row.avatar" width="60px">
+            <img :src="scope.row.avatar" style="max-width: 200px;">
+          </el-popover>
+        </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="gender">
+        <template slot-scope="scope">
+          <dict-tag :options="genderOptions" :value="scope.row.gender"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="备注" align="center" prop="remark" />
+      <el-table-column label="描述信息" align="center" prop="description" />
+      <el-table-column label="标签" align="center" prop="tagIds" width="300px">
+        <template slot-scope="scope">
+          <div class="tag-container">
+            <div class="tag-list">
+              <div v-for="i in JSON.parse(scope.row.tagIds)" :key="i" style="display: inline;">
+                <el-tag type="success" v-for="ii in tagList" :key="ii.id" style="margin: 3px;" v-if="ii.tagId==i">{{ii.name}}</el-tag>
+              </div>
+            </div>
+          </div>
+        </template>
+      </el-table-column>
+      <el-table-column label="客户等级" align="center" prop="level" width="120px" >
+        <template slot-scope="scope">
+          <dict-tag :options="ratingType" :value="scope.row.level"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="添加时间" align="center" prop="createTime" width="100px"/>
+      <el-table-column label="状态" align="center" prop="status" width="100px">
+        <template slot-scope="scope">
+          <dict-tag :options="statusOptions" :value="scope.row.status"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="转接状态" align="center" prop="transferStatus" width="100px">
+        <template slot-scope="scope">
+          <dict-tag :options="transferStatusOptions" :value="scope.row.transferStatus"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="企业id" align="center" prop="corpId" />
+      <el-table-column label="备注电话号码" align="center" prop="remarkMobiles" width="150px">
+        <template slot-scope="scope">
+          <span v-for="i in JSON.parse(scope.row.remarkMobiles)" :key="i">{{i}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="备注企业名称" align="center" prop="remarkCorpName" />
+      <el-table-column label="来源" align="center" prop="addWay" width="100px">
+        <template slot-scope="scope">
+          <dict-tag :options="addWayOptions" :value="scope.row.addWay"/>
+        </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="1000px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <div style="background-color: rgb(239, 250, 255); margin: 10px;padding: 15px;">
+          <div>可将选中的客户转接给其他员工,进行后续服务</div>
+          <div>注意:90天内客户只能被转接一次,一个客户最多只能被转接两次</div>
+          <div>需等待总后台审核才会进行转接</div>
+        </div>
+
+        <el-form-item label="接替员工" prop="nickName">
+          <el-input style="width: 150px" disabled>
+            <template slot="prefix">
+              <el-button
+                plain
+                size="small"
+                type="success"
+                v-if="form.nickName">
+                {{ form.nickName }}
+              </el-button>
+            </template>
+          </el-input>
+        </el-form-item>
+        <el-form-item label="消息内容" prop="content">
+          <el-input v-model="form.content" placeholder="请输入内容" />
+          <div style="color: #999;font-size: 14px;display: flex;align-items: center;">
+            <i class="el-icon-info"></i>
+            自定义转接的时候发给客户的消息内容(选填)ps:不填则是官方默认话术
+          </div>
+        </el-form-item>
+        <el-card>
+          <companyTransferQwUserSelect :corpId="queryParams.corpId" :companyId="companyId" @selectUser="selectUser"/>
+        </el-card>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary"
+                   @click="submitForm"
+                   :disabled="submitLoading"
+                   :loading="submitLoading">提交审核</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listTag } from '@/api/qw/tag'
+import { getMyQwCompanyList } from '@/api/qw/user'
+import { companyExtList, companyTransfer, exportExternalContact } from '@/api/qw/externalContact'
+import companyTransferQwUserSelect from '@/views/qw/externalContactTransfer/companyTransferQwUserSelect.vue'
+
+export default {
+  name: "companyTransfer",
+  components: { companyTransferQwUserSelect },
+  data() {
+    return {
+      loading: false,
+      showSearch: true,
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        corpId: null,
+        name: null,
+        qwUserName: null,
+        type: null,
+        level: null,
+        gender: null,
+        transferStatus: null,
+        tagIds: null,
+        createTime: null,
+        status: 0
+      },
+      myQwCompanyList:[],
+      tagList:[],
+      selectTags:[],
+      typeOptions: [],
+      ratingType: [],
+      transferStatusOptions:[],
+      exportLoading: false,
+      statusOptions: [],
+      genderOptions: [],
+      addWayOptions:[],
+      externalContactList: [],
+      total: 0,
+      ids: [],
+      multiple: true,
+      form: {
+        qwUserId: null,
+        nickName: null,
+        content: null
+      },
+      rules: {
+        nickName: [
+          { required: true, message: "接替员工不能为空", trigger: "blur" }
+        ]
+      },
+      open: false,
+      title: "",
+      companyId: null,
+      submitLoading: false,
+    };
+  },
+  created() {
+    // 从store中获取当前用户的companyId
+    this.companyId = this.$store.state.user.user?.companyId || null;
+
+    this.getQwCompanyList();
+    this.getDicts("sys_qw_externalContact_type").then(response => {
+      this.typeOptions = response.data;
+    });
+    this.getDicts("sys_user_sex").then(response => {
+      this.genderOptions = response.data;
+    });
+    this.getDicts("sys_qw_externalContact_addWay").then(response => {
+      this.addWayOptions = response.data;
+    });
+    this.getDicts("sys_qw_sop_rating_type").then(response => {
+      this.ratingType = response.data;
+    });
+    this.getDicts("sys_qw_external_contact_status").then(response => {
+      this.statusOptions = response.data;
+    });
+    this.getDicts("sys_qw_transfer_status").then(response => {
+      this.transferStatusOptions = response.data;
+    });
+  },
+  methods: {
+    handleQuery() {
+      this.queryParams.tagIds=this.selectTags.join(',')
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    resetQuery() {
+      this.queryParams = {
+        pageNum: 1,
+        pageSize: 10,
+        corpId: null,
+        name: null,
+        qwUserName: null,
+        type: null,
+        level: null,
+        gender: null,
+        transferStatus: null,
+        tagIds: null,
+        createTime: null,
+        status: 0
+      };
+      this.selectTags=[];
+      this.resetForm("queryForm");
+      this.queryParams.corpId = this.myQwCompanyList?.[0]?.dictValue || null
+      this.getList();
+    },
+    getList() {
+      this.loading = true
+      companyExtList(this.queryParams).then(response => {
+        this.externalContactList = response.rows;
+        this.total = response.total;
+        this.loading = false
+      })
+    },
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.multiple = !selection.length
+    },
+    updateCorpId(){
+      listTag({corpId:this.queryParams.corpId}).then(response => {
+        this.tagList = response.rows;
+      });
+      this.getList();
+    },
+    getQwCompanyList() {
+      getMyQwCompanyList().then(response => {
+        this.myQwCompanyList = response.data;
+        if(this.myQwCompanyList!=null){
+          this.queryParams.corpId=this.myQwCompanyList[0].dictValue;
+          listTag({corpId:this.queryParams.corpId}).then(response => {
+            this.tagList = response.rows;
+          });
+          this.getList();
+        }
+      });
+    },
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有企业微信客户数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        this.exportLoading = true;
+        return exportExternalContact(queryParams);
+      }).then(response => {
+        this.download(response.msg);
+        this.exportLoading = false;
+      }).catch(() => {});
+    },
+    reset() {
+      this.form = {
+        qwUserId: null,
+        nickName: null,
+        content: null
+      };
+      this.resetForm("form");
+    },
+    handleTransfer() {
+      this.reset()
+      if(!this.ids){
+        this.$message('请选择需要分配的客户')
+        return
+      }
+
+      this.submitLoading = false
+      this.title = "分配客户"
+      this.open = true
+    },
+    selectUser(selection) {
+      this.form.qwUserId = selection.id
+      this.form.nickName = selection.qwUserName
+    },
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+
+          if (this.submitLoading) {
+            return;
+          }
+          this.submitLoading = true
+
+          const params = {
+            ids: this.ids,
+            qwUserId: this.form.qwUserId,
+            content: this.form.content,
+            transferType: 1
+          }
+
+          companyTransfer(params).then(() => {
+            this.$message.success("审核已提交,等待管理员审核");
+            this.open = false;
+          })
+        }
+      });
+    }
+  },
+};
+</script>
+
+<style scoped>
+
+</style>

+ 144 - 0
src/views/qw/externalContactTransfer/companyTransferQwUserSelect.vue

@@ -0,0 +1,144 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="100px">
+      <el-form-item label="销售公司" prop="companyId">
+        <el-select v-model="queryParams.companyId" placeholder="销售公司"  size="small">
+          <el-option
+            v-for="dict in companyList"
+            :key="dict.dictValue"
+            :label="dict.dictLabel"
+            :value="dict.dictValue"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="员工昵称" prop="nickName">
+        <el-input
+          v-model="queryParams.nickName"
+          placeholder="请输入员工昵称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">刷新/重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-table v-loading="loading" :data="userList" ref="userList" border>
+      <el-table-column label="归属销售公司" align="center" prop="companyName" />
+      <el-table-column label="企微员工账号" align="center" prop="qwUserId" />
+      <el-table-column label="员工昵称" align="center" prop="qwUserName" />
+      <el-table-column label="员工部门" align="center" prop="departmentName" />
+      <el-table-column label="员工昵称" align="center" prop="nickName"/>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="120px" >
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleSelectionChange(scope.row)"
+          >选择此人</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="handlePaginationChange"
+    />
+  </div>
+</template>
+
+<script>
+import { companyQwUserlist, listUser } from '@/api/qw/user'
+import { getCompanyListByCorId } from '@/api/company/company'
+
+
+export default {
+  name: "companyTransferQwUserSelect",
+  props: {
+    corpId: {
+      type: String,
+      default: null
+    },
+    companyId: {
+      type: Number,
+      default: null
+    }
+  },
+  data() {
+    return {
+      // 遮罩层
+      loading: false,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 企微用户表格数据
+      userList: [],
+      companyList: [],
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        companyId: null,
+        corpId: null,
+        nickName: null
+      },
+    };
+  },
+  created() {
+    getCompanyListByCorId(this.corpId).then(response => {
+      this.companyList = response.data.filter(item => item.dictValue !== this.companyId)
+      if (!Array.isArray(this.companyList) || this.companyList.length === 0) {
+        return
+      }
+      this.queryParams.companyId = this.companyList[0].dictValue;
+      this.handleQuery();
+    })
+  },
+  methods: {
+    /** 查询企微用户列表 */
+    getList() {
+      this.loading = true;
+      companyQwUserlist(this.queryParams).then(response => {
+        this.userList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    handlePaginationChange(row) {
+      this.queryParams.pageNum = row.page;
+      this.queryParams.pageSize = row.limit;
+      this.getList();
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.queryParams.corpId = this.corpId;
+      if (!Array.isArray(this.companyList) || this.companyList.length === 0) {
+        return
+      }
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      if (!Array.isArray(this.companyList) || this.companyList.length === 0) {
+        return
+      }
+      this.queryParams.companyId = this.companyList[0].dictValue;
+      this.handleQuery();
+    },
+    // 选中数据
+    handleSelectionChange(selection) {
+      this.$emit("selectUser",selection);
+    },
+  }
+};
+</script>

+ 213 - 0
src/views/qw/externalContactTransferLog/companyTransferDetail.vue

@@ -0,0 +1,213 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="公司名称" prop="companyName">
+        <el-input
+          v-model="queryParams.companyName"
+          placeholder="请输入销售公司名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="主体名称" prop="corpName">
+        <el-input
+          v-model="queryParams.corpName"
+          placeholder="请输入企微主体名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="销售名称" prop="companyUserName">
+        <el-input
+          v-model="queryParams.companyUserName"
+          placeholder="请输入销售名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="审核状态" prop="status">
+        <el-select v-model="queryParams.status" placeholder="请选择" clearable >
+          <el-option :value="0" label="全部"/>
+          <el-option
+            v-for="item in auditStatusOptions"
+            :key="item.dictValue"
+            :label="item.dictLabel"
+            :value="item.dictValue"
+          />
+        </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-table v-loading="loading" :data="list" border>
+      <el-table-column label="主体名称" align="center" prop="corpName" />
+      <el-table-column label="接替公司名称" align="center" prop="companyName" />
+      <el-table-column label="接替销售名称" align="center" prop="companyUserName" />
+      <el-table-column label="接替企微用户名称" align="center" prop="qwUserName" />
+      <el-table-column label="审核状态" align="center" prop="status">
+        <template slot-scope="scope">
+          <dict-tag :options="auditStatusOptions" :value="scope.row.status"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="提交时间" align="center" prop="createTime" />
+      <el-table-column label="审核时间" align="center" prop="auditTime" />
+      <el-table-column label="被拒原因" align="center" prop="reason" />
+      <el-table-column label="提交人" align="center" prop="createBy" />
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            @click="handleView(scope.row)"
+            v-hasPermi="['qw:externalContactTransferCompanyAudit:detail']"
+          >详情</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 title="详情" size="75%" :visible.sync="dialogViewVisible" append-to-body>
+      <el-row :gutter="10" class="mb8">
+        <el-col :span="1.5">
+          <el-button
+            style="margin-left: 10px"
+            type="primary"
+            plain
+            size="mini"
+            v-if="currentAudit.status === 2"
+            :loading="syncLoading"
+            @click="sync"
+            v-hasPermi="['qw:externalContactTransferCompanyAudit:sync']"
+          >同步</el-button>
+        </el-col>
+      </el-row>
+      <el-table v-loading="detailLoading" :data="userList" border>
+        <el-table-column label="客户名称" align="center" prop="externalUserName" />
+        <el-table-column label="原公司名称" align="center" prop="companyName" />
+        <el-table-column label="原销售名称" align="center" prop="companyUserName" />
+        <el-table-column label="原企微用户名称" align="center" prop="qwUserName" />
+        <el-table-column label="备注" align="center" prop="remark" />
+        <el-table-column label="接替状态" align="center" prop="status">
+          <template slot-scope="scope">
+            <dict-tag :options="replaceStatusOptions" :value="scope.row.status"/>
+          </template>
+        </el-table-column>
+      </el-table>
+    </el-drawer>
+  </div>
+</template>
+
+<script>
+import { detail, listExternalContactTransferAudit, sync } from '@/api/qw/externalContactTransferAudit'
+
+export default {
+  name: "companyTransferDetail",
+  data() {
+    return {
+      loading: false,
+      showSearch: true,
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        companyName: null,
+        corpName: null,
+        companyUserName: null,
+        status: 0,
+      },
+      total: 0,
+      list: [],
+      auditStatusOptions: [],
+      replaceStatusOptions: [],
+      dialogAuditVisible: false,
+      dialogViewVisible: false,
+      detailLoading: false,
+      userList: [],
+      currentAudit: {},
+      syncLoading: false,
+    }
+  },
+  created() {
+    this.getDicts("sys_qw_transfer_audit_status").then((response) => {
+      this.auditStatusOptions = response.data;
+    });
+    this.getDicts("sys_qw_transfer_status").then((response) => {
+      this.replaceStatusOptions = response.data;
+    });
+    this.handleQuery()
+  },
+  methods: {
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    resetQuery() {
+      this.queryParams = {
+        pageNum: 1,
+        pageSize: 10,
+        companyName: null,
+        corpName: null,
+        companyUserName: null,
+        status: 0,
+      };
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    getList() {
+      this.loading = true
+      const params = {
+        ...this.queryParams,
+        status: this.queryParams.status === 0 ? null : this.queryParams.status
+      }
+      listExternalContactTransferAudit(params).then(response => {
+        this.list = response.rows.map(item => {
+          return {
+            ...item,
+            createTime: item.createTime ? item.createTime.replace("T", " ") : null,
+            auditTime: item.auditTime ? item.auditTime.replace("T", " ") : null,
+          }
+        })
+        this.total = response.total
+        this.loading = false
+      })
+    },
+    handleView(row) {
+      this.currentAudit = row
+      this.detailLoading = true
+      detail(row.id).then(response => {
+        this.userList = response.data
+        this.detailLoading = false
+      })
+      this.dialogViewVisible = true
+    },
+    sync() {
+      const id = this.currentAudit.id
+      this.syncLoading = true
+      sync(id).then(() => {
+        this.detailLoading = true
+        detail(id).then(response => {
+          this.userList = response.data
+          this.detailLoading = false
+        })
+        this.syncLoading = false
+      })
+    },
+  }
+};
+</script>
+
+<style scoped>
+
+</style>

+ 464 - 0
src/views/qw/externalContactUnassigned/companyUnassigned.vue

@@ -0,0 +1,464 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="110px">
+      <el-form-item label="企微公司" prop="corpId">
+        <el-select v-model="queryParams.corpId" placeholder="企微公司"  size="small" @change="updateCorpId()">
+          <el-option
+            v-for="dict in myQwCompanyList"
+            :key="dict.dictValue"
+            :label="dict.dictLabel"
+            :value="dict.dictValue"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="原所属员工" prop="qwUserName">
+        <el-select @change="handleSelectChange" v-model="queryParams.qwUserName" remote filterable clearable reserve-keyword
+                   placeholder="请输入原所属员工名称" :remote-method="qwUserMethod">
+          <el-option
+            v-for="item in qwUserNameList"
+            :key="item.id"
+            :label="item.qwUserName"
+            :value="item.qwUserName">
+            <span style="float: left">{{ item.qwUserName }}</span>
+          </el-option>
+        </el-select>
+      </el-form-item>
+      <el-form-item label="客户名称" prop="name">
+        <el-input
+          v-model="queryParams.name"
+          placeholder="请输入客户名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="用户类别" prop="type">
+        <el-select v-model="queryParams.type" placeholder="请选择用户类别" clearable size="small">
+          <el-option
+            v-for="dict in typeOptions"
+            :key="dict.dictValue"
+            :label="dict.dictLabel"
+            :value="dict.dictValue"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="性别" prop="gender">
+        <el-input
+          v-model="queryParams.gender"
+          placeholder="请输入性别"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="转接状态" prop="addWay">
+        <el-select v-model="queryParams.transferStatus" placeholder="转接状态" clearable size="small">
+          <el-option
+            v-for="dict in transferStatusOptions"
+            :key="dict.dictValue"
+            :label="dict.dictLabel"
+            :value="dict.dictValue"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          size="mini"
+          @click="handleSync"
+          v-hasPermi="['qw:externalContact:addUnassigned']"
+        >同步</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          :loading="exportLoading"
+          @click="handleExport"
+          v-hasPermi="['qw:externalContact:export']"
+        >导出</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          size="mini"
+          @click="handleTransfer"
+          :disabled="multiple"
+          v-hasPermi="['qw:externalContact:companyTransfer']"
+        >分配客户</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          v-if="isQwUserISNull"
+          type="primary"
+          plain
+          size="mini"
+          @click="handleTransferAll"
+          v-hasPermi="['qw:externalContact:companyTransfer']"
+        >分配此员工所有客户</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="externalContactList" @selection-change="handleSelectionChange" border>
+      <el-table-column type="selection" width="55" align="center" />
+
+      <el-table-column label="原所属员工" align="center" prop="qwUserName" width="120px"/>
+      <el-table-column label="原员工部门" align="center" prop="departmentName" width="120px"/>
+      <el-table-column label="外部联系人账号" align="center" prop="externalUserId" width="120px"/>
+      <el-table-column label="客户名称" align="center" prop="name" />
+      <el-table-column label="头像" align="center" prop="avatar" width="120px">
+        <template slot-scope="scope">
+          <el-popover
+            placement="right"
+            title=""
+            trigger="hover">
+            <img slot="reference" :src="scope.row.avatar" width="100px">
+            <img :src="scope.row.avatar" style="max-width: 150px;">
+          </el-popover>
+        </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="gender">
+        <template slot-scope="scope">
+          <dict-tag :options="genderOptions" :value="scope.row.gender"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="备注" align="center" prop="remark" />
+      <el-table-column label="描述信息" align="center" prop="description" />
+      <el-table-column label="标签" align="center" prop="tagIds" width="150px">
+        <template slot-scope="scope">
+          <div class="tag-container">
+            <div class="tag-list">
+              <div v-for="i in JSON.parse(scope.row.tagIds)" :key="i" style="display: inline;">
+                <el-tag type="success" v-for="ii in tagList" :key="ii.id" style="margin: 3px;" v-if="ii.tagId==i">{{ii.name}}</el-tag>
+              </div>
+            </div>
+          </div>
+        </template>
+      </el-table-column>
+      <el-table-column label="备注电话号码" align="center" prop="remarkMobiles" width="150px">
+        <template slot-scope="scope">
+          <span v-for="i in JSON.parse(scope.row.remarkMobiles)" :key="i">{{i}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="备注企业名称" align="center" prop="remarkCorpName" />
+      <el-table-column label="来源" align="center" prop="addWay" width="100px">
+        <template slot-scope="scope">
+          <dict-tag :options="addWayOptions" :value="scope.row.addWay"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="状态" align="center" prop="status" width="100px">
+        <template slot-scope="scope">
+          <dict-tag :options="statusOptions" :value="scope.row.status"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="转接状态" align="center" prop="transferStatus" width="100px">
+        <template slot-scope="scope">
+          <dict-tag :options="transferStatusOptions" :value="scope.row.transferStatus"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="企业id" align="center" prop="corpId" />
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      :page-sizes="[100, 200, 300, 500]"
+      @pagination="getList"
+    />
+
+    <el-dialog :title="title" :visible.sync="open" width="1000px"  append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="100px" style="height: 100%">
+        <div style="background-color: rgb(239, 250, 255); margin: 10px;padding: 15px;">
+          <div>原跟进成员离职时间不能超过1年且离职前一年内至少登录过一次企业微信</div>
+          <div>接替成员最近一年内至少登陆过一次企业微信。</div>
+          <div>需等待总后台审核才会进行转接</div>
+        </div>
+        <el-form-item label="接替员工:" prop="nickName">
+
+          <el-input style="width: 150px" disabled>
+            <template slot="prefix">
+              <el-button
+                plain
+                size="small"
+                type="success"
+                v-if="form.nickName">
+                {{ form.nickName }}
+              </el-button>
+            </template>
+          </el-input>
+        </el-form-item>
+        <el-card>
+          <companyTransferQwUserSelect :corpId="queryParams.corpId" :companyId="companyId" @selectUser="selectUser"/>
+        </el-card>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary"
+                   @click="submitForm"
+                   :disabled="submitLoading"
+                   :loading="submitLoading">提交审核</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listTag } from '@/api/qw/tag'
+import { getMyQwCompanyList, userList } from '@/api/qw/user'
+import { addUnassigned, companyExtList, companyTransfer, exportExternalContact } from '@/api/qw/externalContact'
+import companyTransferQwUserSelect from '@/views/qw/externalContactTransfer/companyTransferQwUserSelect.vue'
+
+export default {
+  name: "companyUnassigned",
+  components: { companyTransferQwUserSelect },
+  data() {
+    return {
+      showSearch: true,
+      loading: false,
+      ids: [],
+      multiple: true,
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        corpId: null,
+        qwUserName: null,
+        name: null,
+        type: null,
+        gender: null,
+        transferStatus: null,
+        status: 1
+      },
+      total: 0,
+      externalContactList: [],
+      myQwCompanyList: [],
+      typeOptions: [],
+      genderOptions: [],
+      addWayOptions: [],
+      statusOptions: [],
+      transferStatusOptions: [],
+      qwUserNameParam: {
+        qwUserName: null,
+      },
+      qwUserNameList: [],
+      isQwUserISNull: false,
+      form: {
+        corpId: null,
+        qwUserId: null,
+        nickName: null,
+        content: null,
+        type: 0,
+        oldQwUserId: null
+      },
+      rules: {
+        nickName: [
+          { required: true, message: "接替员工不能为空", trigger: "blur" }
+        ]
+      },
+      exportLoading: false,
+      companyId: null,
+      submitLoading: false,
+      tagList: [],
+      open: false,
+      title: "",
+    };
+  },
+  created() {
+    // 从store中获取当前用户的companyId
+    this.companyId = this.$store.state.user.user?.companyId || null;
+
+    this.getQwCompanyList();
+    this.getDicts("sys_qw_externalContact_type").then(response => {
+      this.typeOptions = response.data;
+    });
+    this.getDicts("sys_sex").then(response => {
+      this.genderOptions = response.data;
+    });
+    this.getDicts("sys_qw_externalContact_addWay").then(response => {
+      this.addWayOptions = response.data;
+    });
+    this.getDicts("sys_qw_external_contact_status").then(response => {
+      this.statusOptions = response.data;
+    });
+    this.getDicts("sys_qw_transfer_status").then(response => {
+      this.transferStatusOptions = response.data;
+    });
+  },
+  methods: {
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    resetQuery() {
+      this.queryParams = {
+        pageNum: 1,
+        pageSize: 10,
+        corpId: null,
+        qwUserName: null,
+        name: null,
+        type: null,
+        gender: null,
+        transferStatus: null,
+        status: 1
+      };
+      this.qwUserNameList = null
+      this.isQwUserISNull = false
+      this.resetForm("queryForm")
+      this.queryParams.corpId = this.myQwCompanyList?.[0]?.dictValue || null
+      this.getList()
+    },
+    getList() {
+      this.loading = true
+      companyExtList(this.queryParams).then(response => {
+        this.externalContactList = response.rows;
+        this.total = response.total;
+        this.loading = false
+      })
+    },
+    getQwCompanyList() {
+      getMyQwCompanyList().then(response => {
+        this.myQwCompanyList = response.data;
+        if(this.myQwCompanyList!=null){
+          this.queryParams.corpId=this.myQwCompanyList[0].dictValue;
+          listTag({corpId:this.queryParams.corpId}).then(response => {
+            this.tagList = response.rows;
+          });
+          this.getList();
+        }
+      });
+    },
+    updateCorpId() {
+      listTag({corpId:this.queryParams.corpId}).then(response => {
+        this.tagList = response.rows;
+      });
+      this.getList();
+    },
+    handleSelectChange(value) {
+      if(!value){
+        this.qwUserNameList=null
+        this.isQwUserISNull = false;
+      }else{
+        this.isQwUserISNull = true;
+      }
+    },
+    qwUserMethod(query) {
+      if (query) {
+        this.qwUserNameParam.qwUserName = query;
+        userList(this.qwUserNameParam).then(response => {
+          this.qwUserNameList = response.rows;
+        });
+      }
+    },
+    handleSync() {
+      this.form.corpId=this.queryParams.corpId;
+      addUnassigned(this.form).then(() => {
+        this.msgSuccess("同步成功");
+        this.getList();
+      });
+    },
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有企业微信客户数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        this.exportLoading = true;
+        return exportExternalContact(queryParams);
+      }).then(response => {
+        this.download(response.msg);
+        this.exportLoading = false;
+      }).catch(() => {});
+    },
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.multiple = !selection.length
+    },
+    reset() {
+      this.form = {
+        corpId: null,
+        qwUserId: null,
+        nickName: null,
+        content: null,
+        type: 0,
+        oldQwUserId: null
+      };
+      this.resetForm("form");
+    },
+    handleTransfer() {
+      this.reset()
+      if(!this.ids){
+        this.$message('请选择需要分配的客户')
+        return
+      }
+
+      this.submitLoading = false
+      this.title = "分配客户"
+      this.open = true
+    },
+    handleTransferAll() {
+      this.reset()
+      this.form.type = 1
+      this.form.oldQwUserId = this.qwUserNameList.find(item => item.qwUserName === this.queryParams.qwUserName)?.id || null
+      this.submitLoading = false
+      this.title = "分配该员工所有客户"
+      this.open = true
+    },
+    selectUser(selection) {
+      this.form.qwUserId = selection.id
+      this.form.nickName = selection.qwUserName
+    },
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+
+          if (this.submitLoading) {
+            return;
+          }
+          this.submitLoading = true
+
+          const params = {
+            ids: this.ids,
+            qwUserId: this.form.qwUserId,
+            content: this.form.content,
+            type: this.form.type,
+            transferType: 2,
+            oldQwUserId: this.form.oldQwUserId
+          }
+
+          companyTransfer(params).then(() => {
+            this.$message.success("审核已提交,等待管理员审核");
+            this.open = false;
+          })
+        }
+      });
+    }
+  },
+};
+</script>
+
+<style scoped>
+
+</style>