CustomerSelect.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. <template>
  2. <el-drawer size="75%" title="客户选择" :visible.sync="shows" append-to-body>
  3. <div class="app-container">
  4. <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
  5. <el-form-item label="公司名" prop="companyId">
  6. <el-select filterable v-model="queryParams.companyId" placeholder="请选择公司名" @change="companyChange" clearable size="small">
  7. <el-option
  8. v-for="item in companys"
  9. :key="item.companyId"
  10. :label="item.companyName"
  11. :value="item.companyId"
  12. />
  13. </el-select>
  14. </el-form-item>
  15. <el-form-item >
  16. <treeselect style="width: 220px" :clearable="false" v-model="queryParams.deptId" :options="deptOptions" :show-count="true" placeholder="请选择归属部门" />
  17. </el-form-item>
  18. <el-form-item label="认领人" prop="companyUserNickName">
  19. <el-input
  20. v-model="queryParams.companyUserNickName"
  21. placeholder="请输入认领人"
  22. clearable
  23. size="small"
  24. @keyup.enter.native="handleQuery"
  25. />
  26. </el-form-item>
  27. <el-form-item label="客户状态" prop="status">
  28. <el-select v-model="queryParams.status" placeholder="请选择客户状态" clearable size="small">
  29. <el-option
  30. v-for="item in statusOptions"
  31. :key="'status'+item.dictValue"
  32. :label="item.dictLabel"
  33. :value="item.dictValue"
  34. />
  35. </el-select>
  36. </el-form-item>
  37. <el-form-item label="客户类型" prop="customerType">
  38. <el-select multiple v-model="ctsTypeArr" placeholder="请选择客户类型" clearable size="small">
  39. <el-option
  40. v-for="(item, index) in typeOptions"
  41. :key="`${item.dictValue}-${index}`"
  42. :label="item.dictLabel"
  43. :value="item.dictValue"
  44. />
  45. </el-select>
  46. </el-form-item>
  47. <el-form-item label="创建时间" prop="createTime">
  48. <el-date-picker clearable size="small" style="width: 205.4px"
  49. v-model="dateRange"
  50. type="daterange"
  51. value-format="yyyy-MM-dd"
  52. start-placeholder="开始日期" end-placeholder="结束日期">
  53. </el-date-picker>
  54. </el-form-item>
  55. <el-form-item label="领取时间" prop="receiveTimeRange">
  56. <el-date-picker
  57. style="width:205.4px"
  58. clearable size="small"
  59. v-model="receiveTimeRange"
  60. type="daterange"
  61. value-format="yyyy-MM-dd"
  62. start-placeholder="开始日期"
  63. end-placeholder="结束日期">
  64. </el-date-picker>
  65. </el-form-item>
  66. <el-form-item label="客户来源" prop="source">
  67. <el-select multiple v-model="sourceArr" placeholder="请选择客户来源" clearable size="small">
  68. <el-option
  69. v-for="item in sourceOptions"
  70. :key="'source'+item.dictValue"
  71. :label="item.dictLabel"
  72. :value="item.dictValue"
  73. />
  74. </el-select>
  75. </el-form-item>
  76. <el-form-item label="客户标签" prop="tags">
  77. <el-select multiple v-model="tagIds" placeholder="请选择客户标签" clearable size="small">
  78. <el-option
  79. v-for="(item, index) in tagsOptions"
  80. :key="`${item.dictValue}-${index}`"
  81. :label="item.dictLabel"
  82. :value="item.dictLabel"
  83. />
  84. </el-select>
  85. </el-form-item>
  86. <el-form-item>
  87. <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
  88. <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
  89. </el-form-item>
  90. </el-form>
  91. <el-table border v-loading="loading" :data="customerList" :row-key="getRowKeys" @selection-change="handleSelectionChange" size="mini" ref="table" height="460">
  92. <el-table-column type="selection" width="55" align="center" :reserve-selection="true" />
  93. <el-table-column label="ID" align="center" prop="customerId" />
  94. <el-table-column label="所属公司" align="center" prop="companyName" width="300"/>
  95. <el-table-column label="客户编码" align="center" prop="customerCode" width="150"/>
  96. <el-table-column label="客户名称" align="center" prop="customerName" />
  97. <el-table-column label="手机" align="center" prop="mobile" width="90"/>
  98. <el-table-column label="性别" align="center" prop="sex" width="55">
  99. <template slot-scope="scope">
  100. <el-tag prop="sex" v-for="(item, index) in sexOptions" :key="'sex'+index" v-if="scope.row.sex==item.dictValue">{{item.dictLabel}}</el-tag>
  101. </template>
  102. </el-table-column>
  103. <el-table-column label="微信号" align="center" prop="weixin" width="95"/>
  104. <el-table-column label="所在地" align="center" prop="address" />
  105. <el-table-column label="标签" align="center" prop="tags" width="100" show-overflow-tooltip="true"/>
  106. <el-table-column label="客户来源" align="center" prop="source">
  107. <template slot-scope="scope">
  108. <el-tag prop="source" v-for="(item, index) in sourceOptions" :key="'source'+index" v-if="scope.row.source==item.dictValue">{{item.dictLabel}}</el-tag>
  109. </template>
  110. </el-table-column>
  111. <el-table-column label="客户类型" align="center" prop="customerType">
  112. <template slot-scope="scope">
  113. <el-tag prop="customerType" v-for="(item, index) in typeOptions" :key="'customerType'+index" v-if="scope.row.customerType==item.dictValue">{{item.dictLabel}}</el-tag>
  114. </template>
  115. </el-table-column>
  116. <el-table-column label="客户状态" align="center" prop="status">
  117. <template slot-scope="scope">
  118. <el-tag prop="status" v-for="(item, index) in statusOptions" :key="'status'+index" v-if="scope.row.status==item.dictValue">{{item.dictLabel}}</el-tag>
  119. </template>
  120. </el-table-column>
  121. <el-table-column label="认领人" align="center" prop="companyUserNickName" />
  122. <el-table-column label="领取时间" align="center" prop="receiveTime" width="135"/>
  123. <el-table-column label="创建时间" align="center" prop="createTime" width="135"/>
  124. <el-table-column label="最后一次跟进时间" align="center" prop="lastTime" width="180">
  125. </el-table-column>
  126. <el-table-column label="入公海时间" align="center" prop="poolTime" width="180" />
  127. <el-table-column label="操作" fixed="right" width="180px" align="center" class-name="small-padding fixed-width">
  128. <template slot-scope="scope">
  129. <el-button
  130. size="mini"
  131. type="text"
  132. @click="handleShow(scope.row)"
  133. v-hasPermi="['crm:customer:query']"
  134. >查看</el-button>
  135. </template>
  136. </el-table-column>
  137. </el-table>
  138. <div slot="footer" class="dialog-footer" style="width: 100%;display: flex;flex-direction: row-reverse;margin-top: 20px;z-index: 9898989;padding-top: 5px">
  139. <el-button type="primary" @click="submitForm" style="margin-bottom: 5px">确 定</el-button>
  140. </div>
  141. <el-drawer
  142. size="75%"
  143. :title="show.title" :visible.sync="show.open" append-to-body>
  144. <customer-details ref="customerDetails" />
  145. </el-drawer>
  146. </div>
  147. </el-drawer>
  148. </template>
  149. <script>
  150. import { listCustomerAll } from "@/api/crm/customer";
  151. import { getCompanyList } from "@/api/company/company";
  152. import customerDetails from '@/views/crm/components/customerDetails.vue';
  153. import editCustomerSource from '@/views/crm/components/editCustomerSource.vue';
  154. import {getCitys} from "@/api/store/city";
  155. import { throwStatement } from "@babel/types";
  156. import { treeselect } from "@/api/company/companyDept";
  157. import Treeselect from "@riophae/vue-treeselect";
  158. import "@riophae/vue-treeselect/dist/vue-treeselect.css";
  159. export default {
  160. name: "CustomerSelect",
  161. components: { customerDetails,editCustomerSource,Treeselect },
  162. data() {
  163. return {
  164. source:{
  165. title:"修改客户来源",
  166. open:false,
  167. },
  168. shows:false,
  169. deptOptions:[],
  170. receiveTimeRange:[],
  171. tagId:null,
  172. deptId:undefined,
  173. companyId:undefined,
  174. tagsOptions:[],
  175. ctsTypeArr:[],
  176. sourceArr:[],
  177. dateRange:[],
  178. cityIds:[],
  179. citys:[],
  180. tags:[],
  181. tagIds:[],
  182. inputVisible: false,
  183. inputValue: '',
  184. statusOptions:[],
  185. typeOptions:[],
  186. sourceOptions:[],
  187. sexOptions:[],
  188. pageSizes: [10, 20, 30, 50,100,500 ],
  189. show:{
  190. title:"客户详情",
  191. open:false,
  192. },
  193. companys:[],
  194. // 遮罩层
  195. loading: true,
  196. // 选中数组
  197. ids: [],
  198. names: [],
  199. userIds: [],
  200. // 非单个禁用
  201. single: true,
  202. // 非多个禁用
  203. multiple: true,
  204. // 显示搜索条件
  205. showSearch: true,
  206. // 总条数
  207. total: 0,
  208. // 客户表格数据
  209. customerList: [],
  210. // 弹出层标题
  211. title: "",
  212. // 是否显示弹出层
  213. open: false,
  214. // 查询参数
  215. queryParams: {
  216. customerCode: null,
  217. customerName: null,
  218. mobile: null,
  219. sex: null,
  220. weixin: null,
  221. userId: null,
  222. createUserId: null,
  223. receiveUserId: null,
  224. customerUserId: null,
  225. address: null,
  226. location: null,
  227. detailAddress: null,
  228. lng: null,
  229. lat: null,
  230. status: null,
  231. isReceive: null,
  232. deptId: null,
  233. isDel: null,
  234. customerType: null,
  235. receiveTime: null,
  236. poolTime: null,
  237. companyId: null,
  238. isLine: null,
  239. source: null,
  240. tags: null
  241. },
  242. // 表单参数
  243. form: {},
  244. // 表单校验
  245. rules: {
  246. // customerName: [
  247. // { required: true, message: "客户名称不能为空", trigger: "blur" }
  248. // ],
  249. mobile: [
  250. { required: true, message: "手机号不能为空", trigger: "blur" }
  251. ],
  252. // sex: [
  253. // { required: true, message: "性别不能为空", trigger: "blur" }
  254. // ],
  255. source: [
  256. { required: true, message: "客户来源不能为空", trigger: "blur" }
  257. ],
  258. }
  259. };
  260. },
  261. created() {
  262. this.getDicts("crm_customer_tag").then((response) => {
  263. this.tagsOptions = response.data;
  264. });
  265. this.getDicts("crm_customer_source").then((response) => {
  266. this.sourceOptions = response.data;
  267. });
  268. this.getDicts("common_sex").then((response) => {
  269. this.sexOptions = response.data;
  270. });
  271. this.getDicts("crm_customer_status").then((response) => {
  272. this.statusOptions = response.data;
  273. });
  274. this.getDicts("crm_customer_type").then((response) => {
  275. this.typeOptions = response.data;
  276. });
  277. getCompanyList().then(response => {
  278. this.companys = response.data;
  279. });
  280. this.getCitys();
  281. // this.getList();
  282. },
  283. methods: {
  284. setRows(rows){
  285. this.shows = true;
  286. this.rows = rows;
  287. this.initSelect();
  288. },
  289. initSelect(){
  290. if(this.rows && this.rows.length > 0){
  291. this.rows.forEach(row => {
  292. this.$refs.table.toggleRowSelection(row);
  293. })
  294. }
  295. },
  296. getRowKeys(item){
  297. return item.customerId;
  298. },
  299. handleEditSource(){
  300. this.source.open=true;
  301. var that=this;
  302. setTimeout(() => {
  303. that.$refs.editSource.handleEdit(that.ids);
  304. }, 200);
  305. },
  306. closeSource(){
  307. this.source.open=false;
  308. this.getList();
  309. },
  310. tagsChange(e){
  311. var item=this.tagsOptions.find(val => val.dictValue === e);
  312. console.log(item);
  313. this.tags.push(item.dictLabel);
  314. this.form.tags=this.tags.toString();
  315. },
  316. handleCityChange(value) {
  317. console.log(value);
  318. var nodes=this.$refs.citySelect.getCheckedNodes();
  319. this.form.address=nodes[0].pathLabels[0]+"-"+nodes[0].pathLabels[1]+"-"+nodes[0].pathLabels[2];
  320. this.form.cityIds=value.toString();
  321. },
  322. getCitys(){
  323. getCitys().then(res => {
  324. this.loading = false;
  325. this.citys=res.data;
  326. })
  327. },
  328. handleClose(tag) {
  329. this.tags.splice(this.tags.indexOf(tag), 1);
  330. this.form.tags=this.tags.toString();
  331. },
  332. showInput() {
  333. this.inputVisible = true;
  334. this.$nextTick(_ => {
  335. this.$refs.saveTagInput.$refs.input.focus();
  336. });
  337. },
  338. handleInputConfirm() {
  339. let inputValue = this.inputValue;
  340. if (inputValue) {
  341. this.tags.push(inputValue);
  342. }
  343. this.inputVisible = false;
  344. this.inputValue = '';
  345. this.form.tags=this.tags.toString();
  346. },
  347. handleShow(row){
  348. var that=this;
  349. that.show.open=true;
  350. setTimeout(() => {
  351. that.$refs.customerDetails.getDetails(row.customerId);
  352. }, 200);
  353. },
  354. /** 查询客户列表 */
  355. getList() {
  356. this.loading = true;
  357. if(this.receiveTimeRange!=null&&this.receiveTimeRange.length==2){
  358. this.queryParams.receiveTimeRange=this.receiveTimeRange[0]+"--"+this.receiveTimeRange[1]
  359. }
  360. else{
  361. this.queryParams.receiveTimeRange=null;
  362. }
  363. if(this.ctsTypeArr.length>0){
  364. this.queryParams.customerType=this.ctsTypeArr.toString();
  365. }
  366. else{
  367. this.queryParams.customerType=null
  368. }
  369. if(this.sourceArr.length>0){
  370. this.queryParams.source=this.sourceArr.toString();
  371. }
  372. else{
  373. this.queryParams.source=null
  374. }
  375. if(this.tagIds.length>0){
  376. this.queryParams.tags=this.tagIds.toString();
  377. }
  378. else{
  379. this.queryParams.tags=null
  380. }
  381. listCustomerAll(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
  382. this.customerList = response.rows;
  383. this.total = response.total;
  384. this.loading = false;
  385. this.initSelect();
  386. });
  387. },
  388. // 取消按钮
  389. cancel() {
  390. this.open = false;
  391. this.reset();
  392. },
  393. /** 搜索按钮操作 */
  394. handleQuery() {
  395. this.getList();
  396. },
  397. /** 重置按钮操作 */
  398. resetQuery() {
  399. this.resetForm("queryForm");
  400. },
  401. // 多选框选中数据
  402. handleSelectionChange(selection) {
  403. this.rows = selection;
  404. this.ids = selection.map(item => item.customerId)
  405. this.names = selection.map(item => item.customerName)
  406. this.single = selection.length!==1
  407. this.multiple = !selection.length
  408. },
  409. getTreeselect() {
  410. var that=this;
  411. var param={companyId:this.companyId}
  412. treeselect(param).then((response) => {
  413. this.deptOptions = response.data;
  414. console.log(this.deptOptions)
  415. if(response.data!=null&&response.data.length>0){
  416. //this.queryParams.deptId=response.data[0].id;
  417. }
  418. });
  419. },
  420. companyChange(val){
  421. console.log(val);
  422. this.companyId=val;
  423. this.getTreeselect();
  424. },
  425. currDeptChange(val){
  426. this.queryParams.deptId=val;
  427. this.getList();
  428. },
  429. submitForm(){
  430. this.$nextTick(() => {
  431. this.$emit("success", {ids: this.ids, names: this.names, rows: this.rows})
  432. this.shows = false;
  433. this.$refs.table.clearSelection();
  434. })
  435. },
  436. }
  437. };
  438. </script>
  439. <style scoped>
  440. .el-tag + .el-tag {
  441. margin-left: 10px;
  442. }
  443. .button-new-tag {
  444. margin-left: 10px;
  445. height: 32px;
  446. line-height: 30px;
  447. padding-top: 0;
  448. padding-bottom: 0;
  449. }
  450. .input-new-tag {
  451. width: 90px;
  452. margin-left: 10px;
  453. vertical-align: bottom;
  454. }
  455. .el-dialog__wrapper{
  456. z-index: 100000;
  457. }
  458. .app-container{padding: 0}
  459. .dialog-footer{
  460. position: absolute;
  461. bottom: 0;
  462. right: 20px;
  463. background: #FFF;
  464. }
  465. </style>