detailsPage.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692
  1. <template>
  2. <div class="borderless">
  3. <div class="customer-head">
  4. <div class="customer-back">
  5. <!-- <i class="back-icon el-icon-arrow-left"></i><i style="font-style:normal">返回管理列表</i>-->
  6. <el-button
  7. type="danger"
  8. style="border: none;background: none;color: red"
  9. icon="el-icon-arrow-left"
  10. @click="backToList"
  11. >返回列表
  12. </el-button>
  13. </div>
  14. <el-button type="success" class="copy-customer-btn" disabled>
  15. 复制新单
  16. </el-button>
  17. <el-button
  18. class="el-button--small-yh add-customer-btn"
  19. type="primary"
  20. :disabled="disabled"
  21. @click="editCustomer"
  22. >{{ form.id ? "确认修改" : "确认新增" }}
  23. </el-button>
  24. </div>
  25. <div style="margin-top: 60px;margin-bottom:35px">
  26. <containerTitle title="基础信息"></containerTitle>
  27. <basic-container style="margin-bottom: 10px">
  28. <avue-form ref="form" v-model="form" :option="option">
  29. <template slot="corpId">
  30. <select-component
  31. v-model="form.corpId"
  32. :configuration="configuration"
  33. :disabled="detailData.status == 1"
  34. ></select-component>
  35. </template>
  36. </avue-form>
  37. </basic-container>
  38. <containerTitle title="商品信息"></containerTitle>
  39. <basic-container>
  40. <avue-crud
  41. ref="crud"
  42. :data="data"
  43. :option="tableOption"
  44. @row-del="rowDel"
  45. @saveColumn="saveColumn"
  46. >
  47. <template slot="menuLeft">
  48. <el-button
  49. type="primary"
  50. icon="el-icon-plus"
  51. size="small"
  52. @click.stop="newDetails"
  53. :disabled="detailData.status == 1"
  54. >新增明细</el-button
  55. >
  56. <el-button
  57. type="info"
  58. icon="el-icon-printer"
  59. size="small"
  60. @click.stop="openReport()"
  61. >报 表</el-button
  62. >
  63. </template>
  64. <template slot="itemType" slot-scope="{ row }">
  65. <el-select
  66. v-if="row.$cellEdit"
  67. v-model="row.itemType"
  68. filterable
  69. allow-create
  70. default-first-option
  71. placeholder="请输入"
  72. @focus="itemTypeFocus(row)"
  73. >
  74. <el-option
  75. v-for="(item, index) in itemtypeList"
  76. :key="index"
  77. :label="item.value"
  78. :value="item.value"
  79. >
  80. </el-option>
  81. </el-select>
  82. <span v-else>{{ row.itemType }}</span>
  83. </template>
  84. <template slot="taxRate" slot-scope="{ row }">
  85. <el-input
  86. v-if="row.$cellEdit"
  87. size="mini"
  88. v-model="row.taxRate"
  89. oninput='this.value=this.value.replace(/[^(\d.)]/g,"").replace(/^(\d+)\.(\d\d).*$/, "$1.$2")'
  90. @change="rateChange(row)"
  91. placeholder="请输入"
  92. />
  93. <span v-else>{{ row.taxRate }}</span>
  94. </template>
  95. <template slot="menu" slot-scope="{ row, index }">
  96. <el-button
  97. size="small"
  98. icon="el-icon-edit"
  99. type="text"
  100. @click="rowCell(row, index)"
  101. :disabled="disabled"
  102. >{{ row.$cellEdit ? "保存" : "修改" }}</el-button
  103. >
  104. <el-button
  105. size="small"
  106. icon="el-icon-edit"
  107. type="text"
  108. @click="rowDel(row, index)"
  109. >删 除</el-button
  110. >
  111. </template>
  112. <template slot="price" slot-scope="{ row }">
  113. <el-input
  114. v-if="row.$cellEdit"
  115. v-model="row.price"
  116. size="small"
  117. oninput='this.value=this.value.replace(/[^(\d.)]/g,"").replace(/^(\d+)\.(\d\d).*$/, "$1.$2")'
  118. @change="priceChange(row)"
  119. ></el-input>
  120. <span v-else>{{ row.price }}</span>
  121. </template>
  122. <template slot="actualQuantity" slot-scope="{ row }">
  123. <el-input
  124. v-if="row.$cellEdit"
  125. v-model="row.actualQuantity"
  126. size="small"
  127. oninput='this.value=this.value.replace(/[^(\d.)]/g,"").replace(/^(\d+)\.(\d\d).*$/, "$1.$2")'
  128. @change="quantityChange(row)"
  129. ></el-input>
  130. <span v-else>{{ row.actualQuantity }}</span>
  131. </template>
  132. </avue-crud>
  133. </basic-container>
  134. <fee-info
  135. ref="feeInfo"
  136. :orderFeesList="orderFeesList"
  137. :disabled="detailData.status == 1"
  138. feeUrl="/blade-deliver-goods/deliveryfees/update"
  139. />
  140. <upload-file
  141. ref="uploadFile"
  142. title="合同附件"
  143. :orderFilesList="orderFilesList"
  144. :disabled="detailData.status == 1"
  145. delUrl="/blade-deliver-goods/deliveryfiles/update"
  146. />
  147. </div>
  148. <el-dialog
  149. title="导入商品"
  150. append-to-body
  151. class="el-dialogDeep"
  152. :visible.sync="dialogVisible"
  153. width="60%"
  154. :close-on-click-modal="false"
  155. :destroy-on-close="true"
  156. :close-on-press-escape="false"
  157. @close="closeGoods"
  158. top="10vh"
  159. >
  160. <span>
  161. <el-row>
  162. <el-col :span="5">
  163. <div>
  164. <el-scrollbar>
  165. <basic-container style="margin-top:45px">
  166. <avue-tree :option="treeOption" @node-click="nodeClick" />
  167. </basic-container>
  168. </el-scrollbar>
  169. </div>
  170. </el-col>
  171. <el-col :span="19">
  172. <avue-crud
  173. :option="goodsOption"
  174. :table-loading="loading"
  175. :data="goodsList"
  176. ref="goodsCrud"
  177. @refresh-change="refreshChange"
  178. @selection-change="selectionChange"
  179. @row-click="rowClick"
  180. :page.sync="page"
  181. @on-load="onLoad"
  182. @saveColumn="saveGoodsColumn"
  183. ></avue-crud>
  184. </el-col>
  185. </el-row>
  186. </span>
  187. <span slot="footer" class="dialog-footer">
  188. <el-button @click="dialogVisible = false">取 消</el-button>
  189. <el-button
  190. type="primary"
  191. @click="importGoods"
  192. :disabled="selectionList.length == 0"
  193. >导入</el-button
  194. >
  195. </span>
  196. </el-dialog>
  197. <report-dialog
  198. :switchDialog="switchDialog"
  199. :reportId="form.id"
  200. reportName="客户询价"
  201. @onClose="onClose()"
  202. ></report-dialog>
  203. </div>
  204. </template>
  205. <script>
  206. import tableOption from "./config/customerContact.json";
  207. import goodsOption from "./config/commodity.json";
  208. import feeInfo from "@/components/fee-info/main";
  209. import {
  210. detail,
  211. submit,
  212. delItem,
  213. getDeptLazyTree,
  214. getGoods,
  215. getSpecification
  216. } from "@/api/basicData/invoice";
  217. import uploadFile from "@/components/upload-file/main";
  218. import reportDialog from "@/components/report-dialog/main";
  219. import { isvalidatemobile, validatename } from "@/util/validate";
  220. import _ from "lodash";
  221. export default {
  222. name: "detailsPageEdit",
  223. data() {
  224. const validatePhone = (rule, value, callback) => {
  225. if (value != "") {
  226. if (isvalidatemobile(value)[0]) {
  227. this.$message.error("手机号码格式不正确");
  228. callback(new Error(isvalidatemobile(value)[1]));
  229. } else {
  230. callback();
  231. }
  232. } else {
  233. callback();
  234. }
  235. };
  236. const validateName = (rule, value, callback) => {
  237. if (value != "") {
  238. if (validatename(value)) {
  239. this.$message.error("联系人格式不正确");
  240. callback(new Error(validatename(value)));
  241. } else {
  242. callback();
  243. }
  244. } else {
  245. callback();
  246. }
  247. };
  248. return {
  249. configuration: {
  250. multipleChoices: false,
  251. multiple: false,
  252. collapseTags: false,
  253. placeholder: "请点击右边按钮选择",
  254. dicData: []
  255. },
  256. switchDialog: false,
  257. form: {},
  258. disabled: false,
  259. dialogVisible: false,
  260. tableOption: {},
  261. option: {
  262. menuBtn: false,
  263. labelWidth: 100,
  264. column: [
  265. {
  266. label: "客户名称",
  267. prop: "corpId",
  268. rules: [
  269. {
  270. required: true,
  271. message: "",
  272. trigger: "blur"
  273. }
  274. ],
  275. span: 8,
  276. slot: true
  277. },
  278. {
  279. label: "系统号",
  280. prop: "sysNo",
  281. span: 8
  282. },
  283. {
  284. label: "销售订单号",
  285. prop: "orderNo",
  286. span: 8
  287. },
  288. {
  289. label: "订单状态",
  290. prop: "deliveryStatus",
  291. span: 8
  292. },
  293. {
  294. label: "仓库名称",
  295. prop: "storageId",
  296. span: 8
  297. },
  298. {
  299. label: "仓库类型",
  300. prop: "warehouseType",
  301. span: 8
  302. },
  303. {
  304. label: "发货日期",
  305. prop: "businessDate",
  306. span: 8,
  307. type: "date",
  308. format: "yyyy-MM-dd",
  309. valueFormat: "yyyy-MM-dd 00:00:00"
  310. },
  311. {
  312. label: "出库金额",
  313. prop: "deliveryAmount",
  314. span: 8
  315. },
  316. {
  317. label: "出库数量",
  318. prop: "totalQuantity",
  319. span: 8
  320. },
  321. {
  322. label: "费用合计",
  323. prop: "totalCost",
  324. span: 8
  325. },
  326. {
  327. label: "收货地址",
  328. prop: "arrivalAddress",
  329. span: 8
  330. },
  331. {
  332. label: "联系人",
  333. prop: "arrivalContact",
  334. span: 8,
  335. rules: [{ validator: validateName, trigger: "blur" }]
  336. },
  337. {
  338. label: "电话",
  339. prop: "arrivalTel",
  340. span: 8,
  341. rules: [{ validator: validatePhone, trigger: "blur" }]
  342. },
  343. {
  344. label: "制单时间",
  345. prop: "createTime",
  346. span: 8,
  347. type: "date",
  348. format: "yyyy-MM-dd",
  349. valueFormat: "yyyy-MM-dd 00:00:00",
  350. disabled: true
  351. },
  352. {
  353. label: "备注",
  354. prop: "deliveryRemarks",
  355. type: "textarea",
  356. minRows: 2,
  357. span: 8
  358. }
  359. ]
  360. },
  361. treeOption: {
  362. nodeKey: "id",
  363. lazy: true,
  364. treeLoad: function(node, resolve) {
  365. const parentId = node.level === 0 ? 0 : node.data.id;
  366. getDeptLazyTree(parentId).then(res => {
  367. resolve(
  368. res.data.data.map(item => {
  369. return {
  370. ...item,
  371. leaf: !item.hasChildren
  372. };
  373. })
  374. );
  375. });
  376. },
  377. addBtn: false,
  378. menu: false,
  379. size: "small",
  380. props: {
  381. label: "title",
  382. value: "value",
  383. children: "children"
  384. }
  385. },
  386. page: {
  387. pageSize: 10,
  388. currentPage: 1,
  389. total: 0
  390. },
  391. loading: false,
  392. goodsOption: goodsOption,
  393. data: [],
  394. goodsList: [],
  395. selectionList: [],
  396. treeDeptId: null,
  397. orderFeesList: [],
  398. orderFilesList: [],
  399. itemtypeList: []
  400. };
  401. },
  402. props: {
  403. detailData: {
  404. type: Object
  405. }
  406. },
  407. components: {
  408. reportDialog,
  409. feeInfo,
  410. uploadFile
  411. },
  412. async created() {
  413. this.tableOption = await this.getColumnData(
  414. this.getColumnName(9),
  415. tableOption
  416. );
  417. if (this.$route.query.pageType == "Generate") {
  418. this.getGenerate(JSON.parse(this.$route.query.data));
  419. }
  420. if (this.detailData.id) {
  421. this.getDetail(this.detailData.id);
  422. }
  423. if (this.detailData.status == 1) {
  424. this.option.disabled = true;
  425. }
  426. let _this = this;
  427. this.tableOption.column.forEach(e => {
  428. if (e.prop == "taxRate") {
  429. e.formatter = function(row) {
  430. return _this.textFormat(
  431. Number(row.taxRate ? row.taxRate : 0) / 100,
  432. "0.00%"
  433. );
  434. };
  435. }
  436. if (e.prop == "contractAmount" || e.prop == "price") {
  437. e.formatter = function(row) {
  438. return _this.textFormat(
  439. Number(row.contractAmount ? row.contractAmount : 0),
  440. "#,##0.00"
  441. );
  442. };
  443. }
  444. });
  445. },
  446. methods: {
  447. itemTypeFocus(row) {
  448. this.itemtypeList = [];
  449. getSpecification({ goodId: row.itemId }).then(res => {
  450. const data = res.data.data;
  451. this.itemtypeList = data.map(item => ({ value: item }));
  452. });
  453. },
  454. //编辑
  455. rowCell(row, index) {
  456. if (row.$cellEdit == true) {
  457. this.$set(row, "$cellEdit", false);
  458. } else {
  459. this.$set(row, "$cellEdit", true);
  460. }
  461. },
  462. priceChange(row) {
  463. console.log(row);
  464. if (!row.price) {
  465. row.price = 0;
  466. } else {
  467. row.contractAmount = _.multiply(row.price, row.actualQuantity).toFixed(
  468. 2
  469. );
  470. }
  471. },
  472. quantityChange(row) {
  473. if (!row.actualQuantity) {
  474. row.actualQuantity = 0;
  475. } else {
  476. row.contractAmount = _.multiply(row.price, row.actualQuantity).toFixed(
  477. 2
  478. );
  479. }
  480. },
  481. rateChange(row) {
  482. if (row >= 100) {
  483. row.taxRate = 0;
  484. this.$message.error("汇率不能超过100%");
  485. }
  486. },
  487. rowSave(row) {
  488. console.log(row);
  489. this.$set(row, "$cellEdit", false);
  490. },
  491. rowDel(row, index) {
  492. this.$confirm("确定删除数据?", {
  493. confirmButtonText: "确定",
  494. cancelButtonText: "取消",
  495. type: "warning"
  496. }).then(() => {
  497. if (row.id) {
  498. delItem(row.id).then(res => {
  499. this.$message({
  500. type: "success",
  501. message: "删除成功!"
  502. });
  503. this.data.splice(index, 1);
  504. });
  505. } else {
  506. this.$message({
  507. type: "success",
  508. message: "删除成功!"
  509. });
  510. this.data.splice(index, 1);
  511. }
  512. });
  513. },
  514. importGoods() {
  515. this.selectionList.forEach(e => {
  516. this.data.push({
  517. itemId: e.id,
  518. code: e.code,
  519. cname: e.cname,
  520. priceCategory: e.goodsTypeName,
  521. itemUrl: e.url,
  522. itemProp: null,
  523. itemDescription: null,
  524. itemType: null,
  525. actualQuantity: 0,
  526. tradeTerms: null,
  527. price: 0,
  528. contractAmount: 0,
  529. taxRate: 0,
  530. unit: e.unit,
  531. remarks: null,
  532. $cellEdit: true
  533. });
  534. });
  535. this.dialogVisible = false;
  536. },
  537. closeGoods() {
  538. this.selectionList = [];
  539. this.treeDeptId = "";
  540. },
  541. selectionChange(list) {
  542. this.selectionList = list;
  543. },
  544. rowClick(row) {
  545. this.$refs.goodsCrud.toggleSelection([this.goodsList[row.$index]]);
  546. },
  547. nodeClick(data) {
  548. this.treeDeptId = data.id;
  549. this.page.currentPage = 1;
  550. this.onLoad(this.page);
  551. },
  552. //费用查询
  553. onLoad(page, params = {}) {
  554. this.loading = true;
  555. getGoods(page.currentPage, page.pageSize, this.treeDeptId).then(res => {
  556. const data = res.data.data;
  557. this.page.total = data.total;
  558. this.goodsList = data.records;
  559. this.loading = false;
  560. if (this.page.total) {
  561. this.goodsOption.height = window.innerHeight - 550;
  562. } else {
  563. this.goodsOption.height = window.innerHeight - 475;
  564. }
  565. });
  566. },
  567. //商品明细导入
  568. newDetails() {
  569. this.dialogVisible = !this.dialogVisible;
  570. },
  571. getDetail(id) {
  572. detail(id).then(res => {
  573. this.form = res.data.data;
  574. this.data = res.data.data.deliveryItemsList;
  575. this.orderFeesList = res.data.data.deliveryFeesList;
  576. this.orderFilesList = res.data.data.deliveryFilesList;
  577. this.configuration.dicData = this.form.corpName;
  578. });
  579. },
  580. getGenerate(data) {
  581. this.form = data;
  582. this.data = data.orderItemsList;
  583. this.orderFeesList = data.deliveryFeesList;
  584. this.configuration.dicData = data.corpName;
  585. },
  586. //修改提交触发
  587. editCustomer() {
  588. this.$refs["form"].validate((valid, done) => {
  589. done();
  590. if (valid) {
  591. let orderFeesList = this.$refs.feeInfo.submitData();
  592. for (let i = 0; i < orderFeesList.length; i++) {
  593. if (orderFeesList[i].corpId == null) {
  594. return this.$message.error(`请输入第${i + 1}行的结算中心`);
  595. }
  596. if (orderFeesList[i].price == 0) {
  597. return this.$message.error(`请正确输入第${i + 1}行的价格`);
  598. }
  599. if (orderFeesList[i].actualQuantity == 0) {
  600. return this.$message.error(`请正确输入第${i + 1}行的数量`);
  601. }
  602. }
  603. const orderFilesList = this.$refs.uploadFile.submitData();
  604. submit({
  605. ...this.form,
  606. deliveryItemsList: this.data,
  607. deliveryFeesList: orderFeesList,
  608. deliveryFilesList: orderFilesList
  609. }).then(res => {
  610. this.$message.success(this.form.id ? "修改成功" : "提交成功");
  611. this.form = res.data.data;
  612. this.data = res.data.data.deliveryItemsList;
  613. this.orderFeesList = res.data.data.deliveryFeesList;
  614. this.orderFilesList = res.data.data.deliveryFilesList;
  615. });
  616. } else {
  617. return false;
  618. }
  619. });
  620. },
  621. //返回列表
  622. backToList() {
  623. this.$emit("goBack");
  624. },
  625. openReport() {
  626. this.switchDialog = !this.switchDialog;
  627. },
  628. onClose(val) {
  629. this.switchDialog = val;
  630. },
  631. async saveColumn() {
  632. const inSave = await this.saveColumnData(
  633. this.getColumnName(9),
  634. this.tableOption
  635. );
  636. if (inSave) {
  637. this.$message.success("保存成功");
  638. //关闭窗口
  639. this.$refs.crud.$refs.dialogColumn.columnBox = false;
  640. }
  641. }
  642. }
  643. };
  644. </script>
  645. <style lang="scss" scoped>
  646. .customer-head {
  647. position: fixed;
  648. top: 105px;
  649. width: 100%;
  650. margin-left: -10px;
  651. height: 62px;
  652. background: #ffffff;
  653. box-shadow: 0 4px 12px 0px rgba(232, 232, 235, 1);
  654. z-index: 999;
  655. }
  656. .customer-back {
  657. cursor: pointer;
  658. line-height: 62px;
  659. font-size: 16px;
  660. color: #323233;
  661. font-weight: 400;
  662. }
  663. .back-icon {
  664. line-height: 64px;
  665. font-size: 20px;
  666. margin-right: 8px;
  667. }
  668. .copy-customer-btn {
  669. position: fixed;
  670. right: 140px;
  671. top: 115px;
  672. }
  673. .add-customer-btn {
  674. position: fixed;
  675. right: 36px;
  676. top: 115px;
  677. }
  678. ::v-deep .el-form-item {
  679. margin-bottom: 8px;
  680. }
  681. ::v-deep .el-form-item__error {
  682. display: none;
  683. }
  684. ::v-deep .select-component {
  685. display: flex;
  686. }
  687. </style>