index.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580
  1. <template>
  2. <div class="app-container">
  3. <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="110px">
  4. <el-form-item label="企微公司" prop="corpId">
  5. <el-select v-model="queryParams.corpId" placeholder="企微公司" size="small" @change="updateCorpId()">
  6. <el-option
  7. v-for="dict in myQwCompanyList"
  8. :key="dict.dictValue"
  9. :label="dict.dictLabel"
  10. :value="dict.dictValue"
  11. />
  12. </el-select>
  13. </el-form-item>
  14. <el-form-item label="原所属员工" prop="qwUserName">
  15. <el-select @change="handleSelectChange" v-model="queryParams.qwUserName" remote filterable clearable reserve-keyword
  16. placeholder="请输入原所属员工名称" :remote-method="qwUserMethod">
  17. <el-option
  18. v-for="item in qwUserNameList"
  19. :key="item.id"
  20. :label="item.qwUserName"
  21. :value="item.qwUserName">
  22. <span style="float: left">{{ item.qwUserName }}</span>
  23. </el-option>
  24. </el-select>
  25. </el-form-item>
  26. <el-form-item label="客户名称" prop="name">
  27. <el-input
  28. v-model="queryParams.name"
  29. placeholder="请输入客户名称"
  30. clearable
  31. size="small"
  32. @keyup.enter.native="handleQuery"
  33. />
  34. </el-form-item>
  35. <el-form-item label="用户类别" prop="type">
  36. <el-select v-model="queryParams.type" placeholder="请选择用户类别" clearable size="small">
  37. <el-option
  38. v-for="dict in typeOptions"
  39. :key="dict.dictValue"
  40. :label="dict.dictLabel"
  41. :value="dict.dictValue"
  42. />
  43. </el-select>
  44. </el-form-item>
  45. <el-form-item label="性别" prop="gender">
  46. <el-input
  47. v-model="queryParams.gender"
  48. placeholder="请输入性别"
  49. clearable
  50. size="small"
  51. @keyup.enter.native="handleQuery"
  52. />
  53. </el-form-item>
  54. <el-form-item label="转接状态" prop="addWay">
  55. <el-select v-model="queryParams.transferStatus" placeholder="转接状态" clearable size="small">
  56. <el-option
  57. v-for="dict in transferStatusOptions"
  58. :key="dict.dictValue"
  59. :label="dict.dictLabel"
  60. :value="dict.dictValue"
  61. />
  62. </el-select>
  63. </el-form-item>
  64. <el-form-item>
  65. <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
  66. <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
  67. </el-form-item>
  68. </el-form>
  69. <el-row :gutter="10" class="mb8">
  70. <el-col :span="1.5">
  71. <el-button
  72. type="primary"
  73. plain
  74. size="mini"
  75. @click="handleAdd"
  76. v-hasPermi="['qw:externalContact:add']"
  77. >同步</el-button>
  78. </el-col>
  79. <el-col :span="1.5">
  80. <el-button
  81. type="warning"
  82. plain
  83. icon="el-icon-download"
  84. size="mini"
  85. :loading="exportLoading"
  86. @click="handleExport"
  87. v-hasPermi="['qw:externalContact:export']"
  88. >导出</el-button>
  89. </el-col>
  90. <el-col :span="1.5">
  91. <el-button
  92. type="primary"
  93. plain
  94. size="mini"
  95. @click="handleTransfer"
  96. v-hasPermi="['qw:externalContact:transfer']"
  97. >分配客户</el-button>
  98. </el-col>
  99. <el-col :span="1.5">
  100. <el-button v-if="isQwUserISNull"
  101. type="primary"
  102. plain
  103. size="mini"
  104. @click="handleTransferAll"
  105. v-hasPermi="['qw:externalContact:transfer']"
  106. >分配此员工所有客户</el-button>
  107. </el-col>
  108. <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
  109. </el-row>
  110. <el-table v-loading="loading" :data="externalContactList" @selection-change="handleSelectionChange" border>
  111. <el-table-column type="selection" width="55" align="center" />
  112. <el-table-column label="原所属员工" align="center" prop="qwUserName" width="120px"/>
  113. <el-table-column label="原员工部门" align="center" prop="departmentName" width="120px"/>
  114. <el-table-column label="外部联系人账号" align="center" prop="externalUserId" width="120px"/>
  115. <el-table-column label="客户名称" align="center" prop="name" />
  116. <el-table-column label="头像" align="center" prop="avatar" width="120px">
  117. <template slot-scope="scope">
  118. <el-popover
  119. placement="right"
  120. title=""
  121. trigger="hover">
  122. <img slot="reference" :src="scope.row.avatar" width="100px">
  123. <img :src="scope.row.avatar" style="max-width: 150px;">
  124. </el-popover>
  125. </template>
  126. </el-table-column>
  127. <el-table-column label="用户类别" align="center" prop="type">
  128. <template slot-scope="scope">
  129. <dict-tag :options="typeOptions" :value="scope.row.type"/>
  130. </template>
  131. </el-table-column>
  132. <el-table-column label="性别" align="center" prop="gender">
  133. <template slot-scope="scope">
  134. <dict-tag :options="genderOptions" :value="scope.row.gender"/>
  135. </template>
  136. </el-table-column>
  137. <el-table-column label="备注" align="center" prop="remark" />
  138. <el-table-column label="描述信息" align="center" prop="description" />
  139. <el-table-column label="标签" align="center" prop="tagIds" width="150px">
  140. <template slot-scope="scope">
  141. <div class="tag-container">
  142. <div class="tag-list">
  143. <div v-for="i in JSON.parse(scope.row.tagIds)" :key="i" style="display: inline;">
  144. <el-tag type="success" v-for="ii in tagList" :key="ii.id" style="margin: 3px;" v-if="ii.tagId==i">{{ii.name}}</el-tag>
  145. </div>
  146. </div>
  147. </div>
  148. </template>
  149. </el-table-column>
  150. <el-table-column label="备注电话号码" align="center" prop="remarkMobiles" width="150px">
  151. <template slot-scope="scope">
  152. <span v-for="i in JSON.parse(scope.row.remarkMobiles)" :key="i">{{i}}</span>
  153. </template>
  154. </el-table-column>
  155. <el-table-column label="备注企业名称" align="center" prop="remarkCorpName" />
  156. <el-table-column label="来源" align="center" prop="addWay" width="100px">
  157. <template slot-scope="scope">
  158. <dict-tag :options="addWayOptions" :value="scope.row.addWay"/>
  159. </template>
  160. </el-table-column>
  161. <el-table-column label="状态" align="center" prop="status" width="100px">
  162. <template slot-scope="scope">
  163. <dict-tag :options="statusOptions" :value="scope.row.status"/>
  164. </template>
  165. </el-table-column>
  166. <el-table-column label="转接状态" align="center" prop="transferStatus" width="100px">
  167. <template slot-scope="scope">
  168. <dict-tag :options="transferStatusOptions" :value="scope.row.transferStatus"/>
  169. </template>
  170. </el-table-column>
  171. <el-table-column label="企业id" align="center" prop="corpId" />
  172. <!-- <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
  173. <template slot-scope="scope">
  174. <el-button
  175. size="mini"
  176. type="text"
  177. icon="el-icon-edit"
  178. @click="handleUpdate(scope.row)"
  179. v-hasPermi="['qw:externalContact:edit']"
  180. >修改</el-button>
  181. </template>
  182. </el-table-column> -->
  183. </el-table>
  184. <pagination
  185. v-show="total>0"
  186. :total="total"
  187. :page.sync="queryParams.pageNum"
  188. :limit.sync="queryParams.pageSize"
  189. :page-sizes="[100, 200, 300, 500]"
  190. @pagination="getList"
  191. />
  192. <!-- 添加或修改企业微信客户对话框 -->
  193. <el-dialog :title="title" :visible.sync="open" width="800px" append-to-body>
  194. <el-form ref="form" :model="form" :rules="rules" label-width="100px" style="height: 100%">
  195. <div style="background-color: rgb(239, 250, 255); margin: 10px;padding: 15px;">
  196. <div>原跟进成员离职时间不能超过1年且离职前一年内至少登录过一次企业微信</div>
  197. <div>接替成员最近一年内至少登陆过一次企业微信。</div>
  198. </div>
  199. <el-form-item label="接替员工:" prop="userId">
  200. <el-input style="width: 150px" disabled>
  201. <template slot="prefix">
  202. <el-button
  203. plain
  204. size="small"
  205. type="success"
  206. v-if="this.nickName">
  207. {{ nickName }}
  208. </el-button>
  209. </template>
  210. </el-input>
  211. </el-form-item>
  212. <el-form-item label="清除标签" prop="needClearTag">
  213. <el-radio v-model="form.needClearTag" :label="0">不清除</el-radio>
  214. <el-radio v-model="form.needClearTag" :label="1">清除</el-radio>
  215. <div style="color: #999;font-size: 14px;display: flex;align-items: center;">
  216. <i class="el-icon-info"></i>
  217. <span v-if="form.needClearTag === 0">不清除标签:客户转接后会保留原标签,不会被清除。</span>
  218. <span v-else>清除标签:客户转接后原标签不会保留,仅会存在自动添加的标签。</span>
  219. </div>
  220. </el-form-item>
  221. <el-card>
  222. <qwUserSelectOne ref="qwUserSelectOne" @selectUser="selectUser"></qwUserSelectOne>
  223. </el-card>
  224. </el-form>
  225. <div slot="footer" class="dialog-footer">
  226. <el-button type="primary" @click="submitForm">确 定</el-button>
  227. <el-button @click="cancel">取 消</el-button>
  228. </div>
  229. </el-dialog>
  230. </div>
  231. </template>
  232. <script>
  233. import { addUnassigned,resignedTransfer,listExternalContact, getExternalContact, delExternalContact, addExternalContact, updateExternalContact, exportExternalContact } from "@/api/qw/externalContact";
  234. import { listTag, getTag, delTag, addTag, updateTag, exportTag } from "@/api/qw/tag";
  235. import { qwUserList,userList } from "@/api/qw/user";
  236. import qwUserSelectOne from "@/views/qw/user/qwUserSelectOne.vue";
  237. import { getMyQwUserList,getMyQwCompanyList } from "@/api/qw/user";
  238. export default {
  239. name: "ExternalContact",
  240. components:{qwUserSelectOne},
  241. data() {
  242. return {
  243. // 遮罩层
  244. loading: true,
  245. // 导出遮罩层
  246. exportLoading: false,
  247. // 选中数组
  248. ids: [],
  249. // 非单个禁用
  250. single: true,
  251. // 非多个禁用
  252. multiple: true,
  253. // 显示搜索条件
  254. showSearch: true,
  255. // 总条数
  256. total: 0,
  257. // 企业微信客户表格数据
  258. externalContactList: [],
  259. // 弹出层标题
  260. title: "",
  261. // 是否显示弹出层
  262. open: false,
  263. // 用户类别字典
  264. typeOptions: [],
  265. myQwCompanyList:[],
  266. genderOptions: [],
  267. // 来源字典
  268. addWayOptions: [],
  269. qwUserList:[],
  270. isQwUserISNull:false,
  271. qwUserName:null,
  272. type:'0',
  273. qwUserNameList:[],
  274. qwUserNameParam:{
  275. qwUserName:null
  276. },
  277. // 查询参数
  278. queryParams: {
  279. pageNum: 1,
  280. pageSize: 500,
  281. userId: null,
  282. qwUserName: null,
  283. externalUserId: null,
  284. name: null,
  285. avatar: null,
  286. type: null,
  287. gender: null,
  288. description: null,
  289. tagIds: null,
  290. remarkMobiles: null,
  291. remarkCorpName: null,
  292. addWay: null,
  293. operUserid: null,
  294. corpId: null,
  295. companyId: null,
  296. status:1,
  297. transferStatus:null
  298. },
  299. nickName:null,
  300. // 表单参数
  301. form: {
  302. needClearTag: 0
  303. },
  304. tagList:[],
  305. transferStatusOptions:[],
  306. statusOptions:[],
  307. // 表单校验
  308. rules: {
  309. userId:[ { required: true, message: "接替员工不能为空", trigger: "blur" }]
  310. }
  311. };
  312. },
  313. created() {
  314. getMyQwCompanyList().then(response => {
  315. this.myQwCompanyList = response.data;
  316. if(this.myQwCompanyList!=null){
  317. this.queryParams.corpId=this.myQwCompanyList[0].dictValue
  318. listTag({corpId:this.queryParams.corpId}).then(response => {
  319. this.tagList = response.rows;
  320. });
  321. this.getList();
  322. }
  323. });
  324. this.getDicts("sys_qw_externalContact_type").then(response => {
  325. this.typeOptions = response.data;
  326. });
  327. this.getDicts("sys_sex").then(response => {
  328. this.genderOptions = response.data;
  329. });
  330. this.getDicts("sys_qw_externalContact_addWay").then(response => {
  331. this.addWayOptions = response.data;
  332. });
  333. this.getDicts("sys_qw_external_contact_status").then(response => {
  334. this.statusOptions = response.data;
  335. });
  336. this.getDicts("sys_qw_transfer_status").then(response => {
  337. this.transferStatusOptions = response.data;
  338. });
  339. // qwUserList().then(response => {
  340. // this.qwUserList = response.rows;
  341. // });
  342. },
  343. methods: {
  344. qwUserMethod(query) {
  345. if (query !== '') {
  346. this.qwUserNameParam.qwUserName = query;
  347. userList(this.qwUserNameParam).then(response => {
  348. this.qwUserNameList = response.rows;
  349. });
  350. }
  351. },
  352. handleSelectChange(value) {
  353. console.log('选中的值:', value);
  354. if(value == ''){
  355. this.qwUserNameList=null
  356. this.isQwUserISNull = false;
  357. }else{
  358. this.isQwUserISNull = true;
  359. }
  360. },
  361. updateCorpId(){
  362. listTag({corpId:this.queryParams.corpId}).then(response => {
  363. this.tagList = response.rows;
  364. });
  365. this.getList();
  366. },
  367. getList() {
  368. this.loading = true;
  369. listExternalContact(this.queryParams).then(response => {
  370. this.externalContactList = response.rows;
  371. this.total = response.total;
  372. this.loading = false;
  373. });
  374. },
  375. // 取消按钮
  376. cancel() {
  377. this.open = false;
  378. this.reset();
  379. },
  380. // 表单重置
  381. reset() {
  382. this.form = {
  383. id: null,
  384. userId: null,
  385. externalUserId: null,
  386. name: null,
  387. avatar: null,
  388. type: null,
  389. gender: null,
  390. remark: null,
  391. description: null,
  392. tagIds: null,
  393. remarkMobiles: null,
  394. remarkCorpName: null,
  395. addWay: null,
  396. operUserid: null,
  397. corpId: null,
  398. companyId: null,
  399. needClearTag: 0
  400. };
  401. this.resetForm("form");
  402. },
  403. selectUser(row){
  404. this.form.userId=row.id
  405. // console.log("row",row)
  406. this.nickName=row.nickName
  407. },
  408. /** 搜索按钮操作 */
  409. handleQuery() {
  410. this.queryParams.pageNum = 1;
  411. this.getList();
  412. },
  413. /** 重置按钮操作 */
  414. resetQuery() {
  415. this.qwUserNameList=null
  416. this.isQwUserISNull = false;
  417. this.resetForm("queryForm");
  418. this.queryParams.corpId= this.myQwCompanyList[0].dictValue
  419. this.queryParams.transferStatus = null;
  420. this.handleQuery();
  421. },
  422. // 多选框选中数据
  423. handleSelectionChange(selection) {
  424. this.ids = selection.map(item => item.id)
  425. this.single = selection.length!==1
  426. this.multiple = !selection.length
  427. },
  428. /** 新增按钮操作 */
  429. handleAdd() {
  430. this.form.corpId=this.queryParams.corpId;
  431. addUnassigned(this.form).then(response => {
  432. this.msgSuccess("同步成功");
  433. this.getList();
  434. });
  435. },
  436. handleTransfer(row) {
  437. this.reset();
  438. this.type = '0'
  439. if(this.ids==null||this.ids==""){
  440. return this.$message('请选择需要分配的客户');
  441. }
  442. setTimeout(() => {
  443. this.$refs.qwUserSelectOne.getDetails(this.queryParams.corpId);
  444. }, 1);
  445. this.open = true;
  446. this.title = "分配客户";
  447. },
  448. handleTransferAll(row) {
  449. this.reset();
  450. this.qwUserName=this.queryParams.qwUserName;
  451. this.type="1";
  452. setTimeout(() => {
  453. this.$refs.qwUserSelectOne.getDetails(this.queryParams.corpId);
  454. }, 1);
  455. this.open = true;
  456. this.title = "分配该员工所有客户";
  457. },
  458. /** 提交按钮 */
  459. submitForm() {
  460. this.nickName=null;
  461. this.$refs["form"].validate(valid => {
  462. if (valid) {
  463. var form={
  464. qwUserName:this.qwUserName,
  465. type:this.type,
  466. ids:this.ids,
  467. userId:this.form.userId,
  468. corpId:this.queryParams.corpId,
  469. needClearTag: this.form.needClearTag
  470. }
  471. resignedTransfer(form).then(response => {
  472. this.msgSuccess(response.msg);
  473. this.open = false;
  474. this.getList();
  475. });
  476. }
  477. });
  478. this.qwUserName=null;
  479. },
  480. /** 删除按钮操作 */
  481. handleDelete(row) {
  482. const ids = row.id || this.ids;
  483. this.$confirm('是否确认删除企业微信客户编号为"' + ids + '"的数据项?', "警告", {
  484. confirmButtonText: "确定",
  485. cancelButtonText: "取消",
  486. type: "warning"
  487. }).then(function() {
  488. return delExternalContact(ids);
  489. }).then(() => {
  490. this.getList();
  491. this.msgSuccess("删除成功");
  492. }).catch(() => {});
  493. },
  494. /** 导出按钮操作 */
  495. handleExport() {
  496. const queryParams = this.queryParams;
  497. this.$confirm('是否确认导出所有企业微信客户数据项?', "警告", {
  498. confirmButtonText: "确定",
  499. cancelButtonText: "取消",
  500. type: "warning"
  501. }).then(() => {
  502. this.exportLoading = true;
  503. return exportExternalContact(queryParams);
  504. }).then(response => {
  505. this.download(response.msg);
  506. this.exportLoading = false;
  507. }).catch(() => {});
  508. }
  509. }
  510. };
  511. </script>
  512. <style scoped>
  513. .tag-container {
  514. max-height: 120px;
  515. overflow-y: auto;
  516. padding: 1px;
  517. border: 1px solid #ebeef5;
  518. border-radius: 1px;
  519. background-color: #fafafa;
  520. }
  521. .tag-list {
  522. display: flex;
  523. flex-wrap: wrap;
  524. gap: 8px;
  525. }
  526. .scroll-hint {
  527. text-align: center;
  528. color: #909399;
  529. font-size: 12px;
  530. padding: 1px 0;
  531. }
  532. .container {
  533. max-width: 800px;
  534. margin: 0 auto;
  535. padding: 10px;
  536. }
  537. .title {
  538. text-align: center;
  539. color: #303133;
  540. margin-bottom: 30px;
  541. }
  542. .demo-table {
  543. width: 100%;
  544. margin-bottom: 30px;
  545. }
  546. .instructions {
  547. background-color: #f5f7fa;
  548. padding: 15px;
  549. border-radius: 1px;
  550. margin-bottom: 20px;
  551. }
  552. </style>