Browse Source

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

caoliqin 1 week ago
parent
commit
0ccd5207c0

+ 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
+  })
+}

+ 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>