openSea.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. <!--
  2. * @Author: wanglj 471442253@qq.com
  3. * @Date: 2022-12-15 15:38:21
  4. * @LastEditors: wanglj
  5. * @LastEditTime: 2023-02-13 17:47:45
  6. * @Description: file content
  7. * @FilePath: \opms_frontend\src\views\customer\openSea.vue
  8. -->
  9. <template>
  10. <div class="open-sea-container">
  11. <vab-query-form>
  12. <vab-query-form-top-panel>
  13. <el-form :inline="true" :model="queryForm" @submit.native.prevent>
  14. <el-form-item>
  15. <el-input v-model="queryForm.custCode" placeholder="客户编码" />
  16. </el-form-item>
  17. <el-form-item>
  18. <el-input v-model="queryForm.custName" placeholder="客户名称" />
  19. </el-form-item>
  20. <el-form-item>
  21. <el-select v-model="queryForm.custIndustry" placeholder="客户类型" style="width: 100%">
  22. <el-option v-for="item in industryOptions" :key="item.value" :label="item.value" :value="item.value" />
  23. </el-select>
  24. </el-form-item>
  25. <!-- <el-form-item>
  26. <el-select v-model="queryForm.custLevel" placeholder="客户级别" style="width: 100%">
  27. <el-option v-for="item in levelOptions" :key="item.value" :label="item.value" :value="item.value" />
  28. </el-select>
  29. </el-form-item> -->
  30. <el-form-item>
  31. <el-date-picker
  32. v-model="queryForm.followUpDate"
  33. placeholder="最后跟进时间"
  34. style="width: 100%"
  35. type="date"
  36. value-format="yyyy-MM-dd" />
  37. </el-form-item>
  38. <el-form-item>
  39. <el-button icon="el-icon-plus" type="primary" @click="handleSearch">查询</el-button>
  40. <el-button icon="el-icon-refresh-right" @click="reset">重置</el-button>
  41. </el-form-item>
  42. </el-form>
  43. </vab-query-form-top-panel>
  44. <vab-query-form-left-panel :span="12">
  45. <el-button v-permissions="['cust:open:add']" icon="el-icon-plus" type="primary" @click="$refs.edit.init()">
  46. 新建
  47. </el-button>
  48. <el-button v-permissions="['cust:open:allocate']" icon="el-icon-plus" type="primary" @click="handleAllocate">
  49. 分配
  50. </el-button>
  51. <el-button v-permissions="['cust:open:receive']" icon="el-icon-plus" type="primary" @click="handleReceive">
  52. 领取
  53. </el-button>
  54. </vab-query-form-left-panel>
  55. <vab-query-form-right-panel :span="12">
  56. <el-button icon="el-icon-download" @click="exportData" />
  57. <table-tool :check-list.sync="checkList" :columns="columns" />
  58. </vab-query-form-right-panel>
  59. </vab-query-form>
  60. <el-table
  61. v-loading="listLoading"
  62. border
  63. :data="list"
  64. :height="$baseTableHeight(2)"
  65. @selection-change="setSelectRows">
  66. <el-table-column align="center" show-overflow-tooltip type="selection" />
  67. <el-table-column
  68. v-for="(item, index) in finallyColumns"
  69. :key="index"
  70. align="center"
  71. :label="item.label"
  72. :min-width="item.width"
  73. :prop="item.prop"
  74. show-overflow-tooltip
  75. :sortable="item.sortable">
  76. <template #default="{ row }">
  77. <el-button v-if="item.prop === 'custName'" class="link-button" type="text" @click="handleDetail(row)">
  78. {{ row.custName }}
  79. </el-button>
  80. <span v-else-if="item.prop === 'custStatus'">
  81. {{ row.custStatus == 10 ? '正常' : '异常' }}
  82. </span>
  83. <span v-else-if="item.prop === 'custIndustry'">
  84. {{ selectDictLabel(industryOptions, row.custIndustry) }}
  85. </span>
  86. <span v-else-if="item.prop === 'followUpDate'">
  87. {{ parseTime(row.followUpDate, '{y}-{m}-{d} {h}:{i}') }}
  88. </span>
  89. <span v-else-if="item.prop === 'createdTime'">
  90. {{ parseTime(row.createdTime, '{y}-{m}-{d} {h}:{i}') }}
  91. </span>
  92. <span v-else>{{ row[item.prop] }}</span>
  93. </template>
  94. </el-table-column>
  95. <!-- <el-table-column
  96. align="center"
  97. label="客户编码"
  98. min-width="120px"
  99. prop="custCode" />
  100. <el-table-column
  101. align="center"
  102. label="客户名称"
  103. min-width="120px"
  104. prop="custName">
  105. <template slot-scope="scope">
  106. <el-button
  107. style="font-size: 14px"
  108. type="text"
  109. @click="handleDetail(scope.row)">
  110. {{ scope.row.custName }}
  111. </el-button>
  112. </template>
  113. </el-table-column>
  114. <el-table-column align="center" label="助记名" prop="abbrName" />
  115. <el-table-column align="center" label="所在地区" prop="custLocation" />
  116. <el-table-column align="center" label="客户类型" prop="custIndustry" />
  117. <el-table-column align="center" label="客户级别" prop="custLevel" />
  118. <el-table-column align="center" label="客户状态" prop="custStatus">
  119. <template slot-scope="scope">
  120. {{ scope.row.custStatus == 10 ? '正常' : '异常' }}
  121. </template>
  122. </el-table-column>
  123. <el-table-column
  124. align="center"
  125. label="最后跟进时间"
  126. min-width="140px"
  127. prop="followUpDate" />
  128. <el-table-column align="center" label="创建人" prop="createdName" />
  129. <el-table-column
  130. align="center"
  131. label="创建时间"
  132. min-width="140px"
  133. prop="createdTime" /> -->
  134. <el-table-column align="center" fixed="right" label="操作" width="90px">
  135. <template slot-scope="scope">
  136. <el-button v-permissions="['cust:open:edit']" type="text" @click="handleEdit(scope.row)">编辑</el-button>
  137. <el-button v-permissions="['cust:open:delete']" type="text" @click="handleDelete(scope.row)">删除</el-button>
  138. </template>
  139. </el-table-column>
  140. </el-table>
  141. <el-pagination
  142. background
  143. :current-page="queryForm.pageNum"
  144. :layout="layout"
  145. :page-size="queryForm.pageSize"
  146. :total="total"
  147. @current-change="handleCurrentChange"
  148. @size-change="handleSizeChange" />
  149. <!-- 新增编辑客户弹窗 -->
  150. <Edit ref="edit" @createContact="createContact" @customerSave="customerSave" />
  151. <!-- 新建联系人弹窗 -->
  152. <Contact ref="contact" />
  153. <!-- 分配客户 -->
  154. <Allocate ref="allocate" @refresh="fetchData" />
  155. <!-- 领取客户 -->
  156. <Pick ref="pick" @refresh="fetchData" />
  157. </div>
  158. </template>
  159. <script>
  160. import to from 'await-to-js'
  161. import api from '@/api/customer'
  162. import Contact from './components/Contact'
  163. import Edit from './components/Edit'
  164. import Allocate from './components/Allocate'
  165. import Pick from './components/Pick'
  166. import TableTool from '@/components/table/TableTool'
  167. import downloadFileByByte from '@/utils/base64ToFile'
  168. export default {
  169. name: 'OpenSea',
  170. components: {
  171. Contact,
  172. Edit,
  173. Allocate,
  174. Pick,
  175. TableTool,
  176. },
  177. data() {
  178. return {
  179. listLoading: false,
  180. layout: 'total, sizes, prev, pager, next, jumper',
  181. list: [],
  182. total: 0,
  183. queryForm: {
  184. pageNum: 1,
  185. pageSize: 10,
  186. custCode: '', // 客户编码
  187. custName: '', //客户名称
  188. custIndustry: '', // 客户类型 ()
  189. custLevel: '', //客户级别
  190. followUpDate: '', //最后跟进时间
  191. isPublic: true,
  192. },
  193. selectRows: [],
  194. industryOptions: [], //客户类型
  195. levelOptions: [], //客户级别
  196. // 自定义列表
  197. checkList: [],
  198. columns: [
  199. {
  200. label: '客户编码',
  201. width: '120px',
  202. prop: 'custCode',
  203. sortable: false,
  204. disableCheck: false,
  205. },
  206. {
  207. label: '客户名称',
  208. width: '160px',
  209. prop: 'custName',
  210. sortable: false,
  211. disableCheck: true,
  212. },
  213. {
  214. label: '助记名',
  215. width: '100px',
  216. prop: 'abbrName',
  217. sortable: false,
  218. disableCheck: false,
  219. },
  220. {
  221. label: '所在省',
  222. width: '120px',
  223. prop: 'custProvince',
  224. sortable: false,
  225. disableCheck: false,
  226. },
  227. {
  228. label: '所在市',
  229. width: '100px',
  230. prop: 'custCity',
  231. sortable: false,
  232. disableCheck: false,
  233. },
  234. {
  235. label: '客户类型',
  236. width: '100px',
  237. prop: 'custIndustry',
  238. sortable: false,
  239. disableCheck: false,
  240. },
  241. // {
  242. // label: '客户级别',
  243. // width: 'auto',
  244. // prop: 'custLevel',
  245. // sortable: false,
  246. // disableCheck: false,
  247. // },
  248. // {
  249. // label: '客户状态',
  250. // width: '100px',
  251. // prop: 'custStatus',
  252. // sortable: false,
  253. // disableCheck: false,
  254. // },
  255. {
  256. label: '最后跟进时间',
  257. width: '150px',
  258. prop: 'followUpDate',
  259. sortable: false,
  260. disableCheck: false,
  261. },
  262. {
  263. label: '最后跟进人',
  264. width: '100px',
  265. prop: 'followUpMan',
  266. sortable: false,
  267. disableCheck: false,
  268. },
  269. {
  270. label: '创建人',
  271. width: '100px',
  272. prop: 'createdName',
  273. sortable: false,
  274. disableCheck: false,
  275. },
  276. {
  277. label: '创建时间',
  278. width: '150px',
  279. prop: 'createdTime',
  280. sortable: false,
  281. disableCheck: false,
  282. },
  283. ],
  284. }
  285. },
  286. computed: {
  287. finallyColumns() {
  288. return this.columns.filter((item) => this.checkList.includes(item.label))
  289. },
  290. },
  291. mounted() {
  292. this.fetchData()
  293. this.getOptions()
  294. },
  295. methods: {
  296. getOptions() {
  297. Promise.all([this.getDicts('cust_level'), this.getDicts('cust_idy')])
  298. .then(([level, industry]) => {
  299. this.levelOptions = level.data.values || []
  300. this.industryOptions = industry.data.values || []
  301. })
  302. .catch((err) => console.log(err))
  303. },
  304. async fetchData() {
  305. this.listLoading = true
  306. const params = { ...this.queryForm }
  307. if (!params.followUpDate) params.followUpDate = null
  308. const [err, res] = await to(api.getPublicList(params))
  309. if (err) return (this.listLoading = false)
  310. this.list = res.data.list || []
  311. this.total = res.data.total
  312. this.listLoading = false
  313. },
  314. handleSearch() {
  315. this.queryForm.pageNum = 1
  316. this.fetchData()
  317. },
  318. exportData() {
  319. this.queryForm.isPublic = true
  320. let exportFrom = JSON.parse(JSON.stringify(this.queryForm))
  321. exportFrom.columns = this.finallyColumns.map((item) => item.label)
  322. api
  323. .deriveList(exportFrom)
  324. .then((res) => {
  325. if (res.data.list.content) {
  326. downloadFileByByte(res.data.list.content, '公海客户数据.xlsx')
  327. }
  328. })
  329. .catch((err) => {
  330. console.error(err)
  331. })
  332. },
  333. reset() {
  334. this.queryForm = {
  335. pageNum: 1,
  336. pageSize: 10,
  337. custCode: '', // 客户编码
  338. custName: '', //客户名称
  339. custIndustry: '', // 客户类型 ()
  340. custLevel: '', //客户级别
  341. }
  342. this.fetchData()
  343. },
  344. handleSizeChange(val) {
  345. this.queryForm.pageSize = val
  346. this.fetchData()
  347. },
  348. handleCurrentChange(val) {
  349. this.queryForm.pageNum = val
  350. this.fetchData()
  351. },
  352. setSelectRows(val) {
  353. this.selectRows = val
  354. },
  355. // 客户编辑
  356. async handleEdit(row) {
  357. this.$refs.edit.init([row.id])
  358. },
  359. // 客户详情
  360. handleDetail(row) {
  361. this.$router.push({
  362. path: '/customer/detail',
  363. query: {
  364. id: row.id,
  365. },
  366. })
  367. },
  368. // 客户删除
  369. handleDelete(row) {
  370. this.$confirm('确认删除?', '提示', {
  371. confirmButtonText: '确定',
  372. cancelButtonText: '取消',
  373. type: 'warning',
  374. })
  375. .then(async () => {
  376. const [err, res] = await to(api.deleteCustomer({ Ids: [row.id] }))
  377. if (err) return
  378. if (res.code == 200) {
  379. this.$message({
  380. type: 'success',
  381. message: '删除成功!',
  382. })
  383. this.fetchData()
  384. }
  385. })
  386. .catch(() => {})
  387. },
  388. // 联系人弹窗
  389. createContact(res) {
  390. this.$refs.contact.contactForm.custId = res.id
  391. this.$refs.contact.contactForm.custName = res.name
  392. this.$refs.contact.contactVisible = true
  393. },
  394. customerSave() {
  395. this.fetchData()
  396. },
  397. handleClose(form) {
  398. this.$refs[form].resetFields()
  399. },
  400. // 分配
  401. handleAllocate() {
  402. if (!this.selectRows.length) return this.$message.warning('请选择客户')
  403. const arr = this.selectRows.map((item) => item.id)
  404. this.$refs.allocate.ids = arr
  405. this.$refs.allocate.visible = true
  406. },
  407. // 领取
  408. handleReceive() {
  409. if (!this.selectRows.length) return this.$message.warning('请选择客户')
  410. const arr = this.selectRows.map((item) => item.id)
  411. this.$refs.pick.ids = arr
  412. this.$refs.pick.visible = true
  413. // this.$confirm('确认领取客户?', '提示', {
  414. // confirmButtonText: '确定',
  415. // cancelButtonText: '取消',
  416. // type: 'warning',
  417. // })
  418. // .then(async () => {
  419. // const [err, res] = await to(
  420. // api.receiveCustomer({
  421. // ids: arr,
  422. // salesId: this.$store.state.user.id,
  423. // salesName: this.$store.state.user.nickName,
  424. // receive: '1',
  425. // })
  426. // )
  427. // if (err) return
  428. // if (res.code == 200) {
  429. // this.$message({
  430. // type: 'success',
  431. // message: '领取成功!',
  432. // })
  433. // this.fetchData()
  434. // }
  435. // })
  436. // .catch((err) => console.log(err))
  437. },
  438. },
  439. }
  440. </script>
  441. <style lang="scss" scoped>
  442. $base: '.open-sea';
  443. .link-button {
  444. font-size: 14px;
  445. width: 100%;
  446. overflow: hidden;
  447. text-overflow: ellipsis;
  448. white-space: nowrap;
  449. }
  450. </style>