index.vue 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673
  1. <template>
  2. <basic-container>
  3. <el-tabs v-model="activeName" type="card" @tab-click="handleClick">
  4. <el-tab-pane label="明细" name="first">
  5. <avue-crud :option="option" :table-loading="loading" :data="data" :page.sync="page" :search.sync="query"
  6. v-model="form" ref="crud" id="out-table" :header-cell-class-name="headerClassName" @row-del="rowDel"
  7. @search-change="searchChange" @search-reset="searchReset" @selection-change="selectionChange"
  8. @current-change="currentChange" @size-change="sizeChange" @refresh-change="refreshChange"
  9. @resetColumn="resetColumnTwo('crud', 'option', 'optionBack', 408)"
  10. @saveColumn="saveColumnTwo('crud', 'option', 'optionBack', 408)" @on-load="onLoad"
  11. @search-criteria-switch="searchCriteriaSwitch">
  12. <template slot="menuLeft">
  13. <el-button type="success" size="small" plain @click="outExport">导出</el-button>
  14. </template>
  15. <template slot="header">
  16. <avue-crud :data="commodityData" :table-loading="itemLoading" :option="itemOption"></avue-crud>
  17. </template>
  18. <template slot="corpName" slot-scope="{row}">
  19. <span
  20. style="color: #1e9fff;cursor: pointer;width: 100%;overflow:hidden;white-space: nowrap;text-overflow: ellipsis;"
  21. @click.stop="rowCell(row)">
  22. {{ row.corpName }}
  23. </span>
  24. </template>
  25. </avue-crud>
  26. <el-dialog title="销售订单" :visible.sync="dialogVisible" width="70%" :close-on-click-modal="false"
  27. v-dialog-drag append-to-body :before-close="saleClosed">
  28. <span>
  29. <avue-crud :data="saleData" :table-loading="saleLoading" :page.sync="salePage" :option="saleOption"
  30. @current-change="saleCurrentChange" @size-change="saleSizeChange"
  31. @on-load="saleOnLoad"></avue-crud>
  32. </span>
  33. </el-dialog>
  34. </el-tab-pane>
  35. <el-tab-pane label="图表" name="second">
  36. <div v-loading="loading" ref="echartsContainer" style="width: 90vw; height: 56vh;margin-top: 10px;"></div>
  37. </el-tab-pane>
  38. </el-tabs>
  39. </basic-container>
  40. </template>
  41. <script>
  42. import { getList, corpBuySingularSum, corpBuySingularStatistics } from "@/api/tirePartsMall/salesManagement/customAnalysis";
  43. import { getList as getSaleList } from "@/api/tirePartsMall/salesManagement/saleOrder";
  44. import { getToken } from "@/util/auth";
  45. import * as echarts from 'echarts';
  46. export default {
  47. data() {
  48. return {
  49. saleLoading: false,
  50. dialogVisible: false,
  51. saleForm: {},
  52. activeName: 'first',
  53. form: {},
  54. search: {
  55. chart: 1,
  56. type: 1,
  57. },
  58. query: {
  59. chart: 1,
  60. type: 1,
  61. },
  62. loading: false,
  63. itemLoading: false,
  64. page: {
  65. pageSize: 20,
  66. currentPage: 1,
  67. total: 0
  68. },
  69. saleData: [],
  70. salePage: {
  71. pageSize: 20,
  72. currentPage: 1,
  73. total: 0
  74. },
  75. selectionList: [],
  76. option: {},
  77. saleOption: {
  78. height: '360px',
  79. calcHeight: 30,
  80. border: true,
  81. index: true,
  82. addBtn: false,
  83. menu: false,
  84. header: false,
  85. column: [
  86. {
  87. label: "客户名称",
  88. prop: "customerName",
  89. overHidden: true,
  90. },
  91. {
  92. label: "销售单号",
  93. prop: "ordNo",
  94. overHidden: true,
  95. },
  96. {
  97. label: "来源单号",
  98. prop: "srcOrdNo",
  99. overHidden: true,
  100. },
  101. {
  102. label: "业务日期",
  103. prop: "businesDate",
  104. overHidden: true,
  105. },
  106. {
  107. label: "业务来源",
  108. prop: "businessSource",
  109. overHidden: true,
  110. },
  111. {
  112. label: "数量",
  113. prop: "goodsTotalNum",
  114. overHidden: true,
  115. },
  116. {
  117. label: "业务员",
  118. prop: "salerName",
  119. overHidden: true,
  120. },
  121. {
  122. label: "仓库",
  123. prop: "storageName",
  124. overHidden: true,
  125. }
  126. ]
  127. },
  128. optionBack: {
  129. height: 'auto',
  130. calcHeight: 30,
  131. searchShow: true,
  132. searchMenuSpan: 6,
  133. border: true,
  134. index: true,
  135. addBtn: false,
  136. menu: false,
  137. searchIcon: true,
  138. searchIndex: 3,
  139. column: [
  140. {
  141. label: "客户名称",
  142. prop: "corpName",
  143. type: 'select',
  144. search: true,
  145. filterable: true,
  146. remote: true,
  147. overHidden: true,
  148. props: {
  149. label: 'cname',
  150. value: 'cname'
  151. },
  152. dicUrl: '/api/blade-sales-part/corpsDesc/listAll?cname={{key}}&corpType=KH&enableOrNot=1',
  153. },
  154. {
  155. label: "单量",
  156. prop: "num",
  157. overHidden: true,
  158. },
  159. {
  160. label: "条数",
  161. prop: "number",
  162. overHidden: true,
  163. },
  164. {
  165. label: "最后一次购买日期",
  166. prop: "date",
  167. overHidden: true,
  168. },
  169. {
  170. label: "业务日期",
  171. prop: "date",
  172. search: true,
  173. hide: true,
  174. showColumn: false,
  175. overHidden: true,
  176. searchProp: "dateList",
  177. type: "date",
  178. unlinkPanels: true,
  179. searchRange: true,
  180. format: "yyyy-MM-dd",
  181. valueFormat: "yyyy-MM-dd HH:mm:ss",
  182. searchDefaultTime: ["00:00:00", "23:59:59"],
  183. },
  184. {
  185. label: "仓库",
  186. prop: "deliveryWarehouseName",
  187. overHidden: true,
  188. },
  189. {
  190. label: '业务员',
  191. prop: "salesmanName",
  192. search: true,
  193. type: "select",
  194. props: {
  195. label: "name",
  196. value: "name"
  197. },
  198. dicUrl: "/api/blade-user/salerList",
  199. filterable: true,
  200. },
  201. {
  202. label: "购买途径",
  203. prop: "purchaseMethod",
  204. overHidden: true,
  205. }
  206. ]
  207. },
  208. data: [],
  209. commodityData: [],
  210. itemOption: {
  211. border: true,
  212. align: 'center',
  213. header: false,
  214. menu: false,
  215. height: '90',
  216. column: [
  217. {
  218. label: "单量",
  219. prop: "num",
  220. overHidden: true,
  221. },
  222. {
  223. label: "条数",
  224. prop: "number",
  225. overHidden: true,
  226. }
  227. ]
  228. },
  229. chartOption: {
  230. height: '130px',
  231. calcHeight: 30,
  232. searchShow: true,
  233. searchMenuSpan: 12,
  234. border: true,
  235. addBtn: false,
  236. menu: false,
  237. header: false,
  238. searchLabelWidth: "80",
  239. align: 'center',
  240. column: [
  241. {
  242. label: "业务来源",
  243. prop: "srcType",
  244. search: true,
  245. type: 'select',
  246. filterable: true,
  247. dicUrl: '/api/blade-system/dict-biz/dictionary?code=src_type_los',
  248. hide: true,
  249. showColumn: false,
  250. overHidden: true,
  251. disabled: true,
  252. props: {
  253. label: "dictValue",
  254. value: "dictKey"
  255. },
  256. },
  257. {
  258. label: "委托人",
  259. prop: "corpCnName",
  260. type: 'select',
  261. search: true,
  262. filterable: true,
  263. hide: true,
  264. showColumn: false,
  265. remote: true,
  266. dicUrl: "/api/blade-los/bcorps/listByType?cnName={{key}}",
  267. props: {
  268. label: 'cnName',
  269. value: 'cnName',
  270. res: 'data.records'
  271. },
  272. width: '100',
  273. overHidden: true,
  274. },
  275. {
  276. label: "业务员",
  277. prop: "srcCnName",
  278. search: true,
  279. width: '100',
  280. overHidden: true,
  281. filterable: true,
  282. hide: true,
  283. showColumn: false,
  284. remote: true,
  285. type: "select",
  286. dicUrl: "/api/blade-user/page?size=20&current=1&account={{key}}",
  287. props: {
  288. label: "account",
  289. value: "account",
  290. res: 'data.records'
  291. }
  292. },
  293. {
  294. label: "场站",
  295. prop: "cyCnName",
  296. search: true,
  297. width: '100',
  298. overHidden: true,
  299. filterable: true,
  300. hide: true,
  301. showColumn: false,
  302. remote: true,
  303. type: "select",
  304. dicUrl: "/api/blade-los/bcorps/listByType?status=0&current=1&size=10&corpTypeName=场站&cnName={{key}}",
  305. props: {
  306. label: "cnName",
  307. value: "cnName",
  308. res: 'data.records'
  309. }
  310. },
  311. {
  312. label: "船公司",
  313. prop: "carrierCnName",
  314. search: true,
  315. width: '100',
  316. overHidden: true,
  317. filterable: true,
  318. hide: true,
  319. showColumn: false,
  320. remote: true,
  321. type: "select",
  322. dicUrl: "/api/blade-los/bcorps/listByType?status=0&corpTypeName=船公司&current=1&size=10&cnName={{key}}",
  323. props: {
  324. label: "cnName",
  325. value: "cnName",
  326. res: 'data.records'
  327. }
  328. },
  329. {
  330. label: "开船日期",
  331. prop: "date",
  332. search: true,
  333. hide: true,
  334. showColumn: false,
  335. overHidden: true,
  336. searchProp: "dateList",
  337. type: "date",
  338. unlinkPanels: true,
  339. searchRange: true,
  340. format: "yyyy-MM-dd",
  341. valueFormat: "yyyy-MM-dd HH:mm:ss",
  342. searchDefaultTime: ["00:00:00", "23:59:59"],
  343. },
  344. {
  345. label: "航线",
  346. prop: "lineCnName",
  347. search: true,
  348. hide: true,
  349. showColumn: false,
  350. overHidden: true,
  351. filterable: true,
  352. remote: true,
  353. type: "select",
  354. dicUrl: "api/blade-los/blines/list?status=0&current=1&size=10&cnName={{key}}",
  355. props: {
  356. label: "cnName",
  357. value: "cnName",
  358. res: 'data.records'
  359. }
  360. },
  361. {
  362. label: "业务类型",
  363. prop: "businessType",
  364. search: true,
  365. hide: true,
  366. showColumn: false,
  367. overHidden: true,
  368. filterable: true,
  369. type: 'select',
  370. dicUrl: '/api/blade-system/dict-biz/dictionary?code=decisionAnalysis_business_type',
  371. props: {
  372. label: "dictValue",
  373. value: "dictKey"
  374. },
  375. },
  376. {
  377. label: "选择图表",
  378. prop: "chart",
  379. search: true,
  380. hide: true,
  381. showColumn: false,
  382. },
  383. {
  384. label: "类型",
  385. prop: "type",
  386. search: true,
  387. hide: true,
  388. showColumn: false,
  389. }],
  390. },
  391. chartDic: [{
  392. label: '箱量图',
  393. value: 1
  394. }, {
  395. label: '利润图',
  396. value: 2
  397. }, {
  398. label: '利润率图',
  399. value: 3
  400. }],
  401. typeDic: [{
  402. label: '船公司',
  403. value: 1
  404. }, {
  405. label: '客户',
  406. value: 2
  407. }, {
  408. label: '业务员',
  409. value: 3
  410. }],
  411. chartList: [],
  412. chartData: []
  413. };
  414. },
  415. async created() {
  416. this.option = await this.getColumnData(this.getColumnName(408), this.optionBack)
  417. this.loading = true
  418. },
  419. methods: {
  420. saleClosed(done) {
  421. this.saleData = []
  422. this.salePage.currentPage = 1
  423. this.salePage.pageSize = 20
  424. this.salePage.total = 0
  425. this.saleForm = {}
  426. done()
  427. },
  428. getChartData() {
  429. this.loading = true
  430. corpBuySingularStatistics(this.search).then(res => {
  431. this.getChart(res.data.data)
  432. }).finally(() => {
  433. this.loading = false;
  434. })
  435. },
  436. saleCurrentChange(currentPage) {
  437. this.salePage.currentPage = currentPage;
  438. },
  439. saleSizeChange(pageSize) {
  440. this.salePage.pageSize = pageSize;
  441. },
  442. rowCell(row) {
  443. this.dialogVisible = true
  444. this.saleForm = {
  445. customerName: row.corpName,
  446. notComplete: 1,
  447. }
  448. this.saleOnLoad(this.salePage)
  449. },
  450. saleOnLoad(page, params = {}) {
  451. params = {
  452. current: page.currentPage,
  453. size: page.pageSize,
  454. bsType: "XS",
  455. ...Object.assign(params, this.saleForm)
  456. }
  457. this.saleLoading = true
  458. getSaleList(params).then(res => {
  459. this.salePage.total = res.data.data.total;
  460. this.saleData = res.data.data.records
  461. }).finally(() => {
  462. this.saleLoading = false;
  463. })
  464. },
  465. handleClick() {
  466. if (this.activeName == 'first') {
  467. this.query = this.search
  468. this.onLoad(this.page, this.query)
  469. } else {
  470. this.getChartData()
  471. }
  472. },
  473. searchReset() {
  474. this.query = {
  475. chart: 1,
  476. type: 1,
  477. };
  478. this.onLoad(this.page);
  479. },
  480. searchCriteriaSwitch(type) {
  481. if (type) {
  482. this.option.height = this.option.height - 73;
  483. } else {
  484. this.option.height = this.option.height + 73;
  485. }
  486. this.$refs.crud.getTableHeight();
  487. },
  488. // 搜索点击回调
  489. searchChange(params, done) {
  490. this.page.currentPage = 1;
  491. if (params.dateList) {
  492. params = {
  493. ...params,
  494. dateStart: params.dateList[0],
  495. dateEnd: params.dateList[1],
  496. }
  497. }
  498. this.query = params
  499. this.onLoad(this.page, params);
  500. done();
  501. },
  502. selectionChange(list) {
  503. this.selectionList = list;
  504. },
  505. currentChange(currentPage) {
  506. this.page.currentPage = currentPage;
  507. },
  508. sizeChange(pageSize) {
  509. this.page.pageSize = pageSize;
  510. },
  511. refreshChange() {
  512. this.onLoad(this.page, this.query);
  513. },
  514. onLoad(page, params = {}) {
  515. this.loading = true;
  516. if (params.dateList) {
  517. params = {
  518. ...params,
  519. dateStart: params.dateList[0],
  520. dateEnd: params.dateList[1],
  521. }
  522. }
  523. getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
  524. this.page.total = res.data.data.total;
  525. this.data = res.data.data.records
  526. this.getStatisticsSum(Object.assign(params, this.query))
  527. this.$nextTick(() => {
  528. this.$refs.crud.refreshTable()
  529. this.$refs.crud.dicInit()
  530. })
  531. }).finally(() => {
  532. this.loading = false;
  533. })
  534. },
  535. getStatisticsSum(params) {
  536. this.itemLoading = true
  537. corpBuySingularSum(params).then(res => {
  538. this.commodityData = [res.data.data]
  539. }).finally(() => {
  540. this.itemLoading = false;
  541. })
  542. },
  543. outExport() {
  544. const routeData = this.$router.resolve({
  545. path: '/api/blade-sales-part/statistics/corpBuySingularExport',//跳转目标窗口的地址
  546. query: {
  547. 'Blade-Auth': getToken(),
  548. ...this.query
  549. }
  550. })
  551. window.open(routeData.href.slice(1, routeData.href.length));
  552. },
  553. getChart(chartData) {
  554. let texts = ''
  555. let typeName = ''
  556. let seriesData = []
  557. let myChart = echarts.init(this.$refs.echartsContainer);
  558. // 指定图表的配置项和数据
  559. let option = {
  560. tooltip: {
  561. trigger: 'axis',
  562. axisPointer: {
  563. type: 'cross',
  564. crossStyle: {
  565. color: '#999'
  566. }
  567. }
  568. },
  569. toolbox: {},
  570. legend: {
  571. data: ['客户数量']
  572. },
  573. xAxis: [
  574. {
  575. type: 'category',
  576. data: chartData.frequency,
  577. axisPointer: {
  578. type: 'shadow'
  579. }
  580. }
  581. ],
  582. yAxis: [
  583. {
  584. type: 'value',
  585. name: '客户数量',
  586. min: 0,
  587. interval: 50,
  588. axisLabel: {
  589. formatter: '{value} 人'
  590. }
  591. }
  592. ],
  593. series: [
  594. {
  595. name: '客户数量',
  596. type: 'bar',
  597. tooltip: {
  598. valueFormatter: function (value) {
  599. return value + ' 人';
  600. }
  601. },
  602. data: chartData.number
  603. },
  604. ]
  605. };
  606. myChart.setOption(option);
  607. },
  608. chartChange() {
  609. this.getChart(this.chartData)
  610. },
  611. //自定义列保存
  612. async saveColumnTwo(ref, option, optionBack, code) {
  613. /**
  614. * 已定义全局方法,直接使用,saveColumnData保存列数据方法,参数传值(表格名称,当前表格的option数据)
  615. * 已定义全局方法,直接使用,getColumnName方法用来获取枚举值,参数根据自己定义的code值获取中文名
  616. * 一定要执行异步操作,要等接口成功返回,才能执行下一行代码
  617. */
  618. const inSave = await this.saveColumnData(this.getColumnName(code), this[option]);
  619. if (inSave) {
  620. this.$message.success("保存成功");
  621. //关闭窗口
  622. this.$refs[ref].$refs.dialogColumn.columnBox = false;
  623. }
  624. },
  625. //自定义列重置
  626. async resetColumnTwo(ref, option, optionBack, code) {
  627. this[option] = this[optionBack];
  628. const inSave = await this.delColumnData(this.getColumnName(code), this[optionBack]);
  629. if (inSave) {
  630. this.$message.success("重置成功");
  631. this.$refs[ref].$refs.dialogColumn.columnBox = false;
  632. }
  633. },
  634. // 更改表格颜色
  635. headerClassName(tab) {
  636. //颜色间隔
  637. let back = ""
  638. if (tab.columnIndex >= 0 && tab.column.level === 1) {
  639. if (tab.columnIndex % 2 === 0) {
  640. back = "back-one"
  641. } else if (tab.columnIndex % 2 === 1) {
  642. back = "back-two"
  643. }
  644. }
  645. return back;
  646. },
  647. }
  648. };
  649. </script>
  650. <style scoped>
  651. ::v-deep#out-table .back-one {
  652. background: #ecf5ff !important;
  653. text-align: center;
  654. }
  655. ::v-deep#out-table .back-two {
  656. background: #ecf5ff !important;
  657. text-align: center;
  658. }
  659. ::v-deep .el-col-md-8 {
  660. width: 24.33333%;
  661. }
  662. ::v-deep.el-form-item {
  663. margin-bottom: 0;
  664. }
  665. </style>