index.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605
  1. <template>
  2. <div>
  3. <basic-container v-show="show && showInfo" class="page-crad">
  4. <table border="0" width="100%" style="margin-bottom:20px;" v-loading="loading" :option="option">
  5. <tr>
  6. <td class="stat-td">
  7. <img src="@/assets/img/contractAmountBg.png" class="stat-img">
  8. <div class="stat-tip">
  9. <div class="money">
  10. <span style="font-size:20px;">¥</span>
  11. <avue-count-up :end="form.debitAmount"></avue-count-up>
  12. </div>
  13. <div class="title">合同金额</div>
  14. </div>
  15. </td>
  16. <td class="stat-td">
  17. <img src="@/assets/img/deliveredBg.png" class="stat-img">
  18. <div class="stat-tip">
  19. <div class="money">
  20. <span style="font-size:20px;">¥</span>
  21. <avue-count-up :end="form.deliveringAmount"></avue-count-up>
  22. </div>
  23. <div class="title">已送货</div>
  24. </div>
  25. </td>
  26. <td class="stat-td">
  27. <img src="@/assets/img/advanceCollectionBg.png" class="stat-img">
  28. <div class="stat-tip">
  29. <div class="money">
  30. <span style="font-size:20px;">¥</span>
  31. <avue-count-up :end="form.advancePayment"></avue-count-up>
  32. </div>
  33. <div class="title">预收款</div>
  34. <div class="title">(积累预收:)</div>
  35. </div>
  36. </td>
  37. <td class="stat-td">
  38. <img src="@/assets/img/uncollectedBg.png" class="stat-img">
  39. <div class="stat-tip">
  40. <div class="money">
  41. <span style="font-size:20px;">¥</span>
  42. <avue-count-up :end="form.balanceAmount"></avue-count-up>
  43. </div>
  44. <div class="title">未收款</div>
  45. <div class="title">(积累欠款:)</div>
  46. </div>
  47. </td>
  48. <td class="stat-td">
  49. <img src="@/assets/img/receivableBg.png" class="stat-img">
  50. <div class="stat-tip">
  51. <div class="money">
  52. <span style="font-size:20px;">¥</span>
  53. <avue-count-up :end="form.settlmentAmount"></avue-count-up>
  54. </div>
  55. <div class="title">已收款</div>
  56. </div>
  57. </td>
  58. </tr>
  59. </table>
  60. <el-row>
  61. <el-col :span="4">
  62. <avue-tree :option="treeOption" :data="treeData" @node-click="nodeClick" style="height:73vh;"
  63. @save="corpTypeVisible = true">
  64. <template slot="addBtn">
  65. <i class="el-icon-setting" style="font-size:18px;line-height: 30px;width: 20px;padding: 0 10px;"
  66. @click="corpTypeVisible = true"></i>
  67. </template>
  68. </avue-tree>
  69. </el-col>
  70. <el-col :span="20">
  71. <avue-crud ref="crud" :option="option" :data="dataList" :page.sync="page" :search.sync="search"
  72. @search-change="searchChange" @current-change="currentChange" @size-change="sizeChange"
  73. @refresh-change="refreshChange" @on-load="onLoad" :table-loading="loading" @saveColumn="saveColumn"
  74. @resetColumn="resetColumn" :cell-style="cellStyle" @search-criteria-switch="searchCriteriaSwitch">
  75. <template slot="menuLeft">
  76. <el-button type="primary" size="mini" @click.stop="newAdd()">新建客户
  77. </el-button>
  78. <el-button type="primary" size="mini" icon="el-icon-bottom" @click="excelBox = true">导入
  79. </el-button>
  80. <el-button type="primary" size="mini" icon="el-icon-bottom" @click="outExport">导出
  81. </el-button>
  82. </template>
  83. <template slot-scope="{ row, index }" slot="cname">
  84. <span style="color: #409EFF;cursor: pointer" @click.stop="viewInfo(row)">{{ row.cname }}
  85. </span>
  86. </template>
  87. <template slot="idsSearch">
  88. <crop-select v-model="search.ids" corpType="KH"></crop-select>
  89. </template>
  90. <template slot="dateSearch">
  91. <el-date-picker v-model="search.date" type="daterange" start-placeholder="开始日期" end-placeholder="结束日期"
  92. format="yyyy-MM-dd" value-format="yyyy-MM-dd HH:mm:ss" :default-time="['00:00:00', '23:59:59']"
  93. :picker-options="pickerOptions">
  94. </el-date-picker>
  95. </template>
  96. <template slot-scope="{ row, index }" slot="menu">
  97. <el-tooltip class="item" effect="dark" content="删除" placement="top">
  98. <i class="tradingIcon icon-del" @click.stop="rowDel(row)" />
  99. </el-tooltip>
  100. <el-tooltip class="item" effect="dark" content="编辑" placement="top">
  101. <i class="tradingIcon icon-edit" @click.stop="editOpen(row, 2)" />
  102. </el-tooltip>
  103. <el-tooltip class="item" effect="dark" content="收款" placement="top">
  104. <i class="tradingIcon icon-proceeds" />
  105. </el-tooltip>
  106. <el-tooltip class="item" effect="dark" content="发货" placement="top">
  107. <i class="tradingIcon icon-deliver" />
  108. </el-tooltip>
  109. <el-tooltip class="item" effect="dark" content="对账" placement="top">
  110. <i class="tradingIcon icon-reconciliation" />
  111. </el-tooltip>
  112. <!-- <el-button type="text" size="small" @click.stop="editOpen(row, 2)">
  113. 查看
  114. </el-button>
  115. <el-button type="text" size="small" @click.stop="rowDel(row, index)">
  116. 删除
  117. </el-button> -->
  118. </template>
  119. </avue-crud>
  120. </el-col>
  121. </el-row>
  122. </basic-container>
  123. <details-page v-if="!show" @goBack="goBack()" :detailData="detailData" />
  124. <details-info v-if="!showInfo" @goBack="goBack()" @editOpen="editOpen" :detailData="detailData" />
  125. <el-dialog title="设置客户分类" v-dialogDrag :visible.sync="corpTypeVisible" class="avue-dialog" width="80%"
  126. append-to-body @closed="corpTypeClosed">
  127. <span>
  128. <corp-type></corp-type>
  129. <!-- <avue-form :key="reload" ref="corpType" v-model="form4" :option="option4" style="margin-top:20px">
  130. </avue-form> -->
  131. </span>
  132. <div class="avue-dialog__footer">
  133. <el-button @click="corpTypeVisible = false" size="mini">取 消</el-button>
  134. <el-button @click="addCorpType" type="primary" size="mini">确 定</el-button>
  135. </div>
  136. </el-dialog>
  137. <el-dialog title="导入客户" append-to-body :visible.sync="excelBox" width="555px" :close-on-click-modal="false"
  138. v-dialog-drag>
  139. <avue-form :option="excelOption" v-model="excelForm" table-loading="excelLoading"
  140. :upload-before="uploadBefore" :upload-after="uploadAfter">
  141. <template slot="excelTemplate">
  142. <el-button type="primary" @click="derivation">
  143. 点击下载<i class="el-icon-download el-icon--right"></i>
  144. </el-button>
  145. </template>
  146. </avue-form>
  147. <p style="text-align: center;color: #DC0505">
  148. 温馨提示 第一次导入时请先下载模板
  149. </p>
  150. </el-dialog>
  151. </div>
  152. </template>
  153. <script>
  154. import detailsInfo from "./detailsInfo";
  155. import detailsPage from "./detailsPage";
  156. import { option } from "./js/optionList";
  157. import { getList, getCorpType, pageStatistics, remove, addCorpType, customerList } from "@/api/basicData/client";
  158. import corpType from '@/components/corpType/index'
  159. import {getToken} from "@/util/auth";
  160. export default {
  161. name: "index",
  162. data() {
  163. return {
  164. corpTypeVisible: false,
  165. excelForm:{},
  166. excelOption: {
  167. submitBtn: false,
  168. emptyBtn: false,
  169. column: [
  170. {
  171. label: "模板下载",
  172. prop: "excelTemplate",
  173. formslot: true,
  174. span: 24
  175. },
  176. {
  177. label: "导入客户",
  178. prop: "excelFile",
  179. type: "upload",
  180. drag: true,
  181. loadText: "客户上传中,请稍等",
  182. accept:'.xls,.xlsx',
  183. span: 24,
  184. propsHttp: {
  185. res: "data"
  186. },
  187. tip: "请上传 .xls,.xlsx 标准格式文件",
  188. action: "/api/blade-client/partsCorps/import-desc"
  189. }
  190. ]
  191. },
  192. src: '',
  193. show: true,
  194. excelBox: false,
  195. showInfo: true,
  196. loading: false,
  197. search: {},
  198. detailData: {},
  199. dataList: [],
  200. selectionList: [],
  201. page: {
  202. pageSize: 20,
  203. currentPage: 1,
  204. total: 0,
  205. pageSizes: [10, 20, 30, 40, 50, 100, 200, 300, 400, 500]
  206. },
  207. form: {
  208. debitAmount: 0,
  209. deliveringAmount: 0,
  210. advancePayment: 0,
  211. balanceAmount: 0,
  212. settlmentAmount: 0
  213. },
  214. formSerach: {},
  215. pickerOptions: {
  216. shortcuts: [
  217. {
  218. text: '当天',
  219. onClick(picker) {
  220. const date = new Date();
  221. const start = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);
  222. const end = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59);
  223. picker.$emit('pick', [start, end]);
  224. }
  225. },
  226. {
  227. text: '昨天',
  228. onClick(picker) {
  229. const date = new Date();
  230. const start = new Date(date.getFullYear(), date.getMonth(), date.getDate() - 1, 0, 0, 0);
  231. const end = new Date(date.getFullYear(), date.getMonth(), date.getDate() - 1, 23, 59, 59);
  232. picker.$emit('pick', [start, end]);
  233. }
  234. }, {
  235. text: '当月',
  236. onClick(picker) {
  237. const date = new Date();
  238. const start = new Date(date.getFullYear(), date.getMonth(), 1, 0, 0, 0);
  239. const end = new Date(date.getFullYear(), date.getMonth() + 1, 0, 23, 59, 59);
  240. picker.$emit('pick', [start, end]);
  241. }
  242. }, {
  243. text: '当季',
  244. onClick(picker) {
  245. const date = new Date();
  246. const start = new Date(date.getFullYear(), parseInt(date.getMonth() / 3) * 3, 1, 0, 0, 0);
  247. const end = new Date(date.getFullYear(), parseInt(date.getMonth() / 3) * 3 + 3, 0, 23, 59, 59);
  248. picker.$emit('pick', [start, end]);
  249. }
  250. }, {
  251. text: '当年',
  252. onClick(picker) {
  253. const date = new Date();
  254. const start = new Date(date.getFullYear(), date.getMonth(), 1, 0, 0, 0);
  255. const end = new Date(date.getFullYear() + 1, 0, 0, 23, 59, 59);
  256. picker.$emit('pick', [start, end]);
  257. }
  258. }, {
  259. text: '最近一周',
  260. onClick(picker) {
  261. const date = new Date();
  262. const start = new Date(date.getFullYear(), date.getMonth(), date.getDate() - 7, 0, 0, 0);
  263. const end = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59);
  264. picker.$emit('pick', [start, end]);
  265. }
  266. }, {
  267. text: '最近二周',
  268. onClick(picker) {
  269. const date = new Date();
  270. const start = new Date(date.getFullYear(), date.getMonth(), date.getDate() - 7 * 2, 0, 0, 0);
  271. const end = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59);
  272. picker.$emit('pick', [start, end]);
  273. }
  274. }, {
  275. text: '最近三周',
  276. onClick(picker) {
  277. const date = new Date();
  278. const start = new Date(date.getFullYear(), date.getMonth(), date.getDate() - 7 * 3, 0, 0, 0);
  279. const end = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59);
  280. picker.$emit('pick', [start, end]);
  281. }
  282. }]
  283. },
  284. treeOption: {
  285. addBtn: false,
  286. menu: false,
  287. size: "small",
  288. props: {
  289. labelText: "标题",
  290. label: "title",
  291. value: "value",
  292. }
  293. },
  294. treeData: [],
  295. form4: {},
  296. option4: {
  297. menuBtn: false,
  298. labelWidth: 80,
  299. column: [
  300. {
  301. label: "分类名称",
  302. prop: "cname",
  303. rules: [
  304. {
  305. required: true,
  306. message: "",
  307. trigger: "blur"
  308. }
  309. ],
  310. span: 24,
  311. },
  312. {
  313. label: "上级类型",
  314. prop: "parentId",
  315. dicData: [],
  316. type: "tree",
  317. props: {
  318. label: "cname",
  319. value: "id"
  320. },
  321. span: 24,
  322. }
  323. ]
  324. },
  325. hostUrl: '',
  326. option:{}
  327. };
  328. },
  329. components: {
  330. detailsPage,
  331. detailsInfo,
  332. corpType
  333. },
  334. async created() {
  335. this.option = await this.getColumnData(this.getColumnName(207), option);
  336. this.option.height = window.innerHeight - 330;
  337. this.getAllWorkDicts()
  338. },
  339. activated() {
  340. this.$refs.crud.refreshTable();
  341. },
  342. methods: {
  343. derivation() {
  344. window.open(
  345. `/api/blade-client/partsCorps/export-template?${this.website.tokenHeader
  346. }=${getToken()}`
  347. );
  348. },
  349. //导出
  350. outExport() {
  351. let config = {params: {...this.search}}
  352. if (config.params) {
  353. for (const propName of Object.keys(config.params)) {
  354. const value = config.params[propName];
  355. if (value !== null && typeof (value) !== "undefined") {
  356. if (value instanceof Array) {
  357. for (const key of Object.keys(value)) {
  358. let params = propName + '[' + key + ']';
  359. config.params[params] = value[key]
  360. }
  361. delete config.params[propName]
  362. }
  363. }
  364. }
  365. }
  366. const routeData = this.$router.resolve({
  367. path: '/api/blade-client/partsCorps/export-desc', //跳转目标窗口的地址
  368. query: {
  369. ...config.params, //括号内是要传递给新窗口的参数
  370. identification:this.url
  371. }
  372. })
  373. window.open(routeData.href.slice(1, routeData.href.length) + '&' + `${this.website.tokenHeader}=${getToken()}`);
  374. },
  375. uploadBefore(file, done, loading) {
  376. done();
  377. loading = true;
  378. },
  379. uploadAfter(res, done, loading, column) {
  380. this.excelBox = false;
  381. let myError=res.toString();//转字符串
  382. myError=myError.replace("Error: ","") // 去掉前面的" Error: "
  383. this.$message.success(myError);
  384. this.refreshChange();
  385. loading = false;
  386. done();
  387. },
  388. filterNode(value, data) {
  389. console.log(value, data)
  390. if (!value) return true;
  391. return data.label.indexOf(value) !== -1;
  392. },
  393. nodeClick(data) {
  394. this.search.corpsTypeId = data.value
  395. this.page.currentPage = 1;
  396. this.onLoad(this.page, this.search);
  397. },
  398. getAllWorkDicts() {
  399. this.getWorkDicts("client_status").then(res => {
  400. this.findObject(this.option.column, "status").dicData = res.data.data;
  401. });
  402. getCorpType({ corpType: 'KH' }).then(res => {
  403. this.treeData = res.data.data
  404. });
  405. customerList({ corpType: "KH" }).then(res => {
  406. this.findObject(this.option4.column, "parentId").dicData = res.data.data.records
  407. });
  408. this.$refs.crud.init();
  409. },
  410. searchCriteriaSwitch(type) {
  411. if (type) {
  412. this.option.height = this.option.height - 46;
  413. } else {
  414. this.option.height = this.option.height + 46;
  415. }
  416. this.$refs.crud.getTableHeight();
  417. },
  418. cellStyle() {
  419. return "padding:0;height:40px;";
  420. },
  421. //点击搜索按钮触发
  422. searchChange(params, done) {
  423. this.page.currentPage = 1;
  424. this.onLoad(this.page, params);
  425. done();
  426. },
  427. refreshChange() {
  428. this.onLoad(this.page, this.search);
  429. },
  430. newAdd() {
  431. this.show = false;
  432. },
  433. onLoad(page, params = {}) {
  434. let data = this.deepClone(Object.assign(params, this.search));
  435. if (data.date && data.date.length > 0) {
  436. data.startTime = data.date[0]
  437. data.endTime = data.date[1]
  438. }
  439. delete data.date
  440. data.corpType = "KH"
  441. this.loading = true;
  442. getList(
  443. page.currentPage,
  444. page.pageSize,
  445. data
  446. )
  447. .then(res => {
  448. this.dataList = res.data.data.records ? res.data.data.records : [];
  449. this.page.total = res.data.data.total;
  450. })
  451. .finally(() => {
  452. pageStatistics(data).then(res => {
  453. this.form = res.data.data
  454. })
  455. this.loading = false;
  456. });
  457. },
  458. addCorpType() {
  459. // this.$refs["corpType"].validate((valid, done) => {
  460. // done();
  461. // if (valid) {
  462. // addCorpType({ ...this.form4, corpType: 'KH', status: 0 })
  463. // .then(res => {
  464. // this.$message.success("保存成功");
  465. // this.getAllWorkDicts()
  466. // this.corpTypeVisible = false
  467. // })
  468. // } else {
  469. // return false;
  470. // }
  471. // });
  472. this.getAllWorkDicts()
  473. this.corpTypeVisible = false
  474. },
  475. corpTypeClosed() {
  476. // this.reload = Math.random();
  477. // this.form4 = this.$options.data().form4
  478. },
  479. viewInfo(row) {
  480. this.show = true;
  481. this.detailData = {
  482. id: row.id,
  483. status: status
  484. };
  485. this.showInfo = false;
  486. },
  487. editOpen(row, status) {
  488. this.showInfo = true;
  489. this.detailData = {
  490. id: row.id,
  491. status: status
  492. };
  493. this.show = false;
  494. },
  495. currentChange(val) {
  496. this.page.currentPage = val;
  497. },
  498. sizeChange(val) {
  499. this.page.currentPage = 1;
  500. this.page.pageSize = val;
  501. },
  502. rowDel(row, index, done) {
  503. this.$confirm("确定删除数据?", {
  504. confirmButtonText: "确定",
  505. cancelButtonText: "取消",
  506. type: "warning"
  507. }).then(() => {
  508. remove({ id: row.id, corpType: "KH" }).then(res => {
  509. if (res.data.code == 200) {
  510. this.$message({
  511. type: "success",
  512. message: "删除成功!"
  513. });
  514. this.onLoad(this.page, this.search);
  515. }
  516. });
  517. });
  518. },
  519. async saveColumn() {
  520. const inSave = await this.saveColumnData(
  521. this.getColumnName(207),
  522. this.option
  523. );
  524. if (inSave) {
  525. this.$nextTick(() => {
  526. this.$refs.crud.doLayout();
  527. });
  528. this.$message.success("保存成功");
  529. //关闭窗口
  530. this.$refs.crud.$refs.dialogColumn.columnBox = false;
  531. }
  532. },
  533. async resetColumn() {
  534. this.option = option;
  535. const inSave = await this.delColumnData(this.getColumnName(207), option);
  536. if (inSave) {
  537. this.$nextTick(() => {
  538. this.$refs.crud.doLayout();
  539. });
  540. this.getAllWorkDicts()
  541. this.$message.success("重置成功");
  542. this.$refs.crud.$refs.dialogColumn.columnBox = false;
  543. }
  544. },
  545. //返回列表
  546. goBack() {
  547. this.detailData = this.$options.data().detailData;
  548. this.show = true;
  549. this.showInfo = true;
  550. this.onLoad(this.page, this.search);
  551. },
  552. }
  553. }
  554. </script>
  555. <style lang="scss" scoped>
  556. .page-crad ::v-deep .basic-container__card {
  557. height: 94.2vh;
  558. }
  559. ::v-deep .el-form-item__error {
  560. display: none !important;
  561. }
  562. ::v-deep .el-input-group__append {
  563. padding: 0 0px !important;
  564. }
  565. .el-dialog ::v-deep .el-form-item__error {
  566. display: none !important;
  567. }
  568. .stat-td {
  569. text-align: center;
  570. position: relative;
  571. }
  572. .stat-img {
  573. width: 95%;
  574. height: 100px;
  575. }
  576. .stat-tip {
  577. position: absolute;
  578. left: 15px;
  579. top: 5px;
  580. .money {
  581. color: #fff;
  582. font-size: 28px;
  583. text-align: left;
  584. font-weight: 600;
  585. }
  586. .title {
  587. color: #fff;
  588. font-size: 14px;
  589. text-align: left;
  590. margin-top: 5px;
  591. margin-bottom: 0px;
  592. }
  593. }
  594. </style>