index.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. <!--
  2. * @Author: liuzhenlin 461480418@qq.ocm
  3. * @Date: 2023-01-05 11:28:51
  4. * @LastEditors: wanglj
  5. * @LastEditTime: 2023-03-22 14:53:09
  6. * @FilePath: \opms_frontend\src\views\contract\index.vue
  7. -->
  8. <template>
  9. <div class="contract-container">
  10. <vab-query-form>
  11. <vab-query-form-top-panel>
  12. <el-form :inline="true" label-width="0px" :model="queryForm" @submit.native.prevent>
  13. <el-form-item prop="contractCode">
  14. <el-input
  15. v-model="queryForm.contractCode"
  16. clearable
  17. placeholder="合同编号"
  18. @keyup.enter.native="queryData" />
  19. </el-form-item>
  20. <el-form-item prop="contractName">
  21. <el-input
  22. v-model="queryForm.contractName"
  23. clearable
  24. placeholder="合同名称"
  25. @keyup.enter.native="queryData" />
  26. </el-form-item>
  27. <el-form-item prop="custId">
  28. <el-input v-model="queryForm.custName" clearable placeholder="客户名称" @keyup.enter.native="queryData" />
  29. </el-form-item>
  30. <el-form-item prop="custId">
  31. <el-input v-model="queryForm.nboName" clearable placeholder="项目名称" @keyup.enter.native="queryData" />
  32. </el-form-item>
  33. <el-form-item prop="custId">
  34. <el-select v-model="queryForm.approStatus" clearable placeholder="审批状态">
  35. <el-option v-for="(v, k) in approStatusOption" :key="k" :label="v" :value="k" />
  36. </el-select>
  37. </el-form-item>
  38. <el-form-item prop="inchargeName">
  39. <el-input
  40. v-model="queryForm.inchargeName"
  41. clearable
  42. placeholder="销售工程师"
  43. @keyup.enter.native="queryData" />
  44. </el-form-item>
  45. <el-form-item prop="custProvince">
  46. <el-select v-model="queryForm.custProvince" clearable placeholder="所在省" value-key="id">
  47. <el-option v-for="item in provinceOptions" :key="item.id" :label="item.distName" :value="item" />
  48. </el-select>
  49. </el-form-item>
  50. <el-form-item prop="custCity">
  51. <el-select v-model="queryForm.custCity" clearable placeholder="所在市" value-key="id">
  52. <el-option
  53. v-for="item in queryForm.custProvince ? queryForm.custProvince.children : []"
  54. :key="item.id"
  55. clearable
  56. :label="item.distName"
  57. :value="item" />
  58. </el-select>
  59. </el-form-item>
  60. <el-form-item prop="filterDate">
  61. <el-date-picker
  62. v-model="queryForm.filterDate"
  63. end-placeholder="合同签订结束时间"
  64. range-separator="至"
  65. start-placeholder="合同签订开始时间"
  66. style="width: 100%"
  67. type="daterange"
  68. value-format="yyyy-MM-dd" />
  69. </el-form-item>
  70. <el-form-item>
  71. <el-button icon="el-icon-search" type="primary" @click="queryData">查询</el-button>
  72. </el-form-item>
  73. </el-form>
  74. </vab-query-form-top-panel>
  75. <vab-query-form-left-panel :span="12">
  76. <el-button v-permissions="['contract:manage:add']" icon="el-icon-plus" type="primary" @click="handleEdit()">
  77. 新建
  78. </el-button>
  79. <el-button
  80. v-permissions="['contract:manage:transfer']"
  81. icon="el-icon-refresh"
  82. type="primary"
  83. @click="handleTransfer()">
  84. 转移
  85. </el-button>
  86. <el-button
  87. v-permissions="['contract:manage:delete']"
  88. icon="el-icon-delete"
  89. type="danger"
  90. @click="handleDelete()">
  91. 删除
  92. </el-button>
  93. </vab-query-form-left-panel>
  94. <vab-query-form-right-panel :span="12">
  95. <table-tool :columns="columns" :show-columns.sync="showColumns" table-type="contractTable" />
  96. </vab-query-form-right-panel>
  97. </vab-query-form>
  98. <el-table ref="table" v-loading="listLoading" :data="list" :height="height" @selection-change="setSelectRows">
  99. <el-table-column align="center" show-overflow-tooltip type="selection" />
  100. <el-table-column
  101. v-for="(item, index) in showColumns"
  102. :key="index"
  103. align="center"
  104. :label="item.label"
  105. :min-width="item.width"
  106. :prop="item.prop"
  107. show-overflow-tooltip
  108. :sortable="item.sortable">
  109. <template #default="{ row }">
  110. <el-button
  111. v-if="item.prop === 'custName' && row.custId != 0"
  112. class="link-button"
  113. type="text"
  114. @click="handleCustDetail(row)">
  115. {{ row.custName }}
  116. </el-button>
  117. <span v-else-if="item.prop === 'contractAmount'">
  118. {{ formatPrice(row.contractAmount) }}
  119. </span>
  120. <span v-else-if="item.prop === 'approStatus'">
  121. {{ approStatusOption[row.approStatus] }}
  122. </span>
  123. <span v-else-if="item.prop === 'productLine'">
  124. {{ productLineOptions[row.productLine] }}
  125. </span>
  126. <span v-else-if="item.label === '合同有效时间'">
  127. {{ parseTime(row.contractStartTime, '{y}-{m}-{d}') }}~{{ parseTime(row.contractEndTime, '{y}-{m}-{d}') }}
  128. </span>
  129. <span v-else-if="item.label === '合同类型'">
  130. {{ contractOptions[row.contractType] }}
  131. </span>
  132. <span v-else-if="item.label === '签订单位类型'">
  133. {{
  134. row.signatoryType == '10'
  135. ? '终端用户'
  136. : row.signatoryType == '20'
  137. ? '经销商'
  138. : row.signatoryType == '30'
  139. ? '代理商'
  140. : ''
  141. }}
  142. </span>
  143. <span v-else-if="item.label === '合同签订单位'">
  144. {{
  145. row.signatoryType == '10'
  146. ? row.custName
  147. : row.signatoryType == '20'
  148. ? row.distributorName
  149. : row.signatoryType == '30'
  150. ? row.distributorName
  151. : ''
  152. }}
  153. </span>
  154. <span v-else-if="item.label === '合同签订时间'">
  155. {{ parseTime(row.contractSignTime, '{y}-{m}-{d}') }}
  156. </span>
  157. <span v-else-if="item.label === '回款金额'">
  158. {{ formatPrice(row.collectedAmount) }}
  159. </span>
  160. <span v-else-if="item.label === '开票金额'">
  161. {{ formatPrice(row.invoiceAmount) }}
  162. </span>
  163. <el-button
  164. v-else-if="item.prop === 'contractCode'"
  165. style="font-size: 14px"
  166. type="text"
  167. @click="handleContractDetail(row)">
  168. {{ row.contractCode }}
  169. </el-button>
  170. <span v-else>{{ row[item.prop] }}</span>
  171. </template>
  172. </el-table-column>
  173. <el-table-column align="center" fixed="right" label="操作" width="110px">
  174. <template slot-scope="scope">
  175. <el-button
  176. v-if="scope.row.approStatus == '10'"
  177. v-permissions="['contract:manage:apply']"
  178. type="text"
  179. @click="handleApply(scope.row.id)">
  180. 提交审核
  181. </el-button>
  182. <el-button
  183. v-if="scope.row.approStatus == '10'"
  184. v-permissions="['contract:manage:edit']"
  185. type="text"
  186. @click="handleEdit(scope.row)">
  187. 编辑
  188. </el-button>
  189. <el-button v-permissions="['contract:manage:delete']" type="text" @click="handleDelete(scope.row)">
  190. 删除
  191. </el-button>
  192. </template>
  193. </el-table-column>
  194. </el-table>
  195. <el-pagination
  196. background
  197. :current-page="queryForm.pageNum"
  198. :layout="layout"
  199. :page-size="queryForm.pageSize"
  200. :total="total"
  201. @current-change="handleCurrentChange"
  202. @size-change="handleSizeChange" />
  203. <!-- 新增编辑客户弹窗 -->
  204. <Edit ref="edit" @contractSave="contractSave" />
  205. <!-- 转移合同 -->
  206. <Transfer ref="transfer" :contract-id="contractId" @transferSave="contractSave" />
  207. <ApplyContract ref="applyContract" @refresh="queryData" />
  208. </div>
  209. </template>
  210. <script>
  211. import to from 'await-to-js'
  212. import contractApi from '@/api/contract'
  213. import Edit from './components/Edit'
  214. import TableTool from '@/components/table/TableTool'
  215. import Transfer from './components/Transfer'
  216. import ApplyContract from './components/ApplyContract'
  217. import api from '@/api/customer'
  218. export default {
  219. name: 'Contract',
  220. components: {
  221. Edit,
  222. TableTool,
  223. Transfer,
  224. ApplyContract,
  225. },
  226. data() {
  227. return {
  228. height: this.$baseTableHeight(2),
  229. approStatusOption: {
  230. 10: '待提交审核',
  231. 20: '待审核',
  232. 30: '审核已同意',
  233. 40: '审核已拒绝',
  234. 50: '审核已撤销',
  235. },
  236. contractId: [], //当前合同id
  237. listLoading: false,
  238. layout: 'total, sizes, prev, pager, next, jumper',
  239. list: [],
  240. total: 0,
  241. queryForm: {
  242. pageNum: 1,
  243. pageSize: 10,
  244. contractCode: '', // 合同编号
  245. contractName: '', //合同名称
  246. custName: '', // 客户名称 ()
  247. nboName: '', //项目名称
  248. approStatus: '', //审批状态
  249. inchargeName: '', // 负责人(销售工程师)
  250. custProvinceId: 0,
  251. custProvince: null,
  252. custCityId: 0,
  253. custCity: null,
  254. filterDate: [],
  255. },
  256. provinceOptions: [],
  257. selectRows: [], //选择的表格数据
  258. industryOptions: [], //客户行业
  259. levelOptions: [], //客户级别
  260. contractOptions: {}, //合同类型
  261. productLineOptions: {}, //产品线
  262. // 自定义列表
  263. showColumns: [],
  264. columns: [
  265. {
  266. label: '合同编号',
  267. width: '160px',
  268. prop: 'contractCode',
  269. sortable: false,
  270. disableCheck: false,
  271. },
  272. {
  273. label: '合同类型',
  274. width: '100px',
  275. prop: 'contractType',
  276. sortable: false,
  277. disableCheck: false,
  278. },
  279. {
  280. label: '所在省',
  281. width: '100px',
  282. prop: 'custProvince',
  283. sortable: false,
  284. disableCheck: false,
  285. },
  286. {
  287. label: '所在市',
  288. width: '100px',
  289. prop: 'custCity',
  290. sortable: false,
  291. disableCheck: false,
  292. },
  293. {
  294. label: '客户名称',
  295. width: '280px',
  296. prop: 'custName',
  297. sortable: false,
  298. disableCheck: false,
  299. },
  300. {
  301. label: '产品线',
  302. prop: 'productLine',
  303. width: '140px',
  304. },
  305. {
  306. label: '签订单位类型',
  307. width: '120px',
  308. prop: 'signatoryType',
  309. sortable: false,
  310. disableCheck: false,
  311. },
  312. {
  313. label: '合同签订单位',
  314. width: '120px',
  315. prop: 'distributorName',
  316. sortable: false,
  317. disableCheck: false,
  318. },
  319. {
  320. label: '合同签订时间',
  321. width: '120px',
  322. prop: 'contractSignTime',
  323. sortable: false,
  324. disableCheck: false,
  325. },
  326. {
  327. label: '合同有效时间',
  328. width: '200px',
  329. prop: 'contractStartTime',
  330. sortable: false,
  331. disableCheck: false,
  332. },
  333. {
  334. label: '合同金额',
  335. width: '120px',
  336. prop: 'contractAmount',
  337. sortable: false,
  338. disableCheck: false,
  339. },
  340. {
  341. label: '回款金额',
  342. width: '120px',
  343. prop: 'collectedAmount',
  344. sortable: false,
  345. disableCheck: false,
  346. },
  347. {
  348. label: '开票金额',
  349. width: '120px',
  350. prop: 'invoiceAmount',
  351. sortable: false,
  352. disableCheck: false,
  353. },
  354. {
  355. label: '销售工程师',
  356. width: '120px',
  357. prop: 'inchargeName',
  358. sortable: false,
  359. disableCheck: false,
  360. },
  361. {
  362. label: '审批状态',
  363. width: '100px',
  364. prop: 'approStatus',
  365. sortable: false,
  366. disableCheck: false,
  367. },
  368. ],
  369. }
  370. },
  371. watch: {
  372. showColumns: function () {
  373. this.$nextTick(() => this.$refs.table.doLayout())
  374. },
  375. },
  376. activated() {
  377. this.queryData()
  378. },
  379. mounted() {
  380. this.queryData()
  381. this.getOptions()
  382. },
  383. methods: {
  384. getOptions() {
  385. Promise.all([api.getProvinceDetail(), this.getDicts('contract_type'), this.getDicts('sys_product_line')])
  386. .then(([province, contract, productLine]) => {
  387. this.contractOptions = {}
  388. contract.data.values.filter((i) => {
  389. this.contractOptions[i.key] = i.value
  390. })
  391. this.productLineOptions = {}
  392. productLine.data.values.filter((i) => {
  393. this.productLineOptions[i.key] = i.value
  394. })
  395. this.provinceOptions = province.data.list || []
  396. })
  397. .catch((err) => console.log(err))
  398. },
  399. async queryData() {
  400. this.listLoading = true
  401. const params = { ...this.queryForm }
  402. params.custProvinceId = params.custProvince ? params.custProvince.id : 0
  403. params.custCityId = params.custCity ? params.custCity.id : 0
  404. if (this.queryForm.filterDate && this.queryForm.filterDate.length === 2) {
  405. params.contractSignTimeStart = this.queryForm.filterDate[0]
  406. params.contractSignTimeEnd = this.queryForm.filterDate[1]
  407. }
  408. const [err, res] = await to(contractApi.getList(params))
  409. if (err) return (this.listLoading = false)
  410. this.list = res.data.list || []
  411. this.total = res.data.total
  412. this.listLoading = false
  413. this.$nextTick(() => this.$refs.table.doLayout())
  414. },
  415. handleApply(id) {
  416. this.$refs.applyContract.form.id = id
  417. this.$refs.applyContract.visible = true
  418. },
  419. reset() {
  420. this.queryForm = {
  421. pageNum: 1,
  422. pageSize: 10,
  423. custCode: '', // 客户编码
  424. custName: '', //客户名称
  425. custIndustry: '', // 客户行业 ()
  426. custLevel: '', //客户级别
  427. }
  428. this.queryData()
  429. },
  430. handleSizeChange(val) {
  431. this.queryForm.pageSize = val
  432. this.queryData()
  433. },
  434. handleCurrentChange(val) {
  435. this.queryForm.pageNum = val
  436. this.queryData()
  437. },
  438. setSelectRows(val) {
  439. this.selectRows = val.map((item) => item.id)
  440. },
  441. // 客户编辑
  442. async handleEdit(row = null) {
  443. row ? this.$refs.edit.init(row.id) : this.$refs.edit.init()
  444. },
  445. // 合同详情
  446. handleContractDetail(row) {
  447. this.$router.push({
  448. path: '/contract/detail',
  449. query: {
  450. id: row.id,
  451. },
  452. })
  453. },
  454. // 客户详情
  455. handleCustDetail(row) {
  456. this.$router.push({
  457. path: '/customer/detail',
  458. query: {
  459. id: row.custId,
  460. },
  461. })
  462. },
  463. // 转移合同
  464. handleTransfer(row) {
  465. this.contractId = row ? [row.id] : this.selectRows
  466. if (!this.contractId[0]) return this.$baseMessage('请先选择转移的数据', 'warning')
  467. this.$refs.transfer.open()
  468. },
  469. // 合同删除
  470. handleDelete(row = null) {
  471. let ids = row ? [row.id] : this.selectRows
  472. if (!ids[0]) return this.$baseMessage('请先选择删除的数据', 'warning')
  473. this.$confirm('确认删除?', '提示', {
  474. confirmButtonText: '确定',
  475. cancelButtonText: '取消',
  476. type: 'warning',
  477. })
  478. .then(async () => {
  479. const [err, res] = await to(contractApi.delContract({ id: ids }))
  480. if (err) return
  481. if (res.code == 200) {
  482. this.$message({
  483. type: 'success',
  484. message: '删除成功!',
  485. })
  486. this.queryData()
  487. }
  488. })
  489. .catch(() => {})
  490. },
  491. contractSave() {
  492. this.queryData()
  493. },
  494. },
  495. }
  496. </script>
  497. <style lang="scss" scoped>
  498. $base: '.contract-container';
  499. </style>