detailsPageEdit.vue 17 KB

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