index.vue 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778
  1. <script>
  2. import orderApi from "@/api/business/purchase/purchase-order";
  3. import { initColumns, initDicts, initRules, initParams } from "@/utils/init";
  4. import { Columns, TabColumns } from "./column";
  5. const NewColumns = initColumns(Columns);
  6. const NewTabColumns = TabColumns.map((element) => ({
  7. ...element,
  8. tableColumns: initColumns(element.tableColumns),
  9. }));
  10. const SelectColumns = NewColumns.filter(
  11. (column) => column.inputType === "Select"
  12. );
  13. NewTabColumns.forEach((column) => {
  14. SelectColumns.push(
  15. ...column.tableColumns.filter((cColumn) => cColumn.inputType === "Select")
  16. );
  17. });
  18. export default {
  19. name: "AddPurchaseOrderDrawer",
  20. dicts: initDicts(SelectColumns),
  21. components: {
  22. FileUploadCenter: () => import("../components/FileUploadCenter/index.vue"),
  23. popDialog: () => import("@/components/PopDialog/index.vue"),
  24. },
  25. data() {
  26. return {
  27. visible: false,
  28. columns: NewColumns,
  29. rules: initRules(NewColumns),
  30. params: {
  31. ...initParams(NewColumns),
  32. puOrderItemList: [],
  33. puOrderExecuteList: [],
  34. },
  35. tabColumns: NewTabColumns,
  36. tabName: "puOrderItemList",
  37. isCopy:false,
  38. };
  39. },
  40. computed: {},
  41. watch: {
  42. "params.puOrderItemList": {
  43. handler(nVal, oVal) {
  44. this.visible &&
  45. this.handleSynchronousMaterial(
  46. "puOrderItemList",
  47. "puOrderExecuteList"
  48. );
  49. },
  50. deep: true,
  51. },
  52. "params.puOrderExecuteList": {
  53. handler(nVal, oVal) {
  54. this.visible &&
  55. this.handleSynchronousMaterial(
  56. "puOrderExecuteList",
  57. "puOrderItemList"
  58. );
  59. },
  60. deep: true,
  61. },
  62. },
  63. methods: {
  64. beforeOpen() {
  65. if(!this.isCopy){
  66. const { deptName, deptId, name, nickName, orgName, orgId } = this.$store.state.user;
  67. this.params.puOrg = orgId;
  68. this.params.puOrgName = orgName;
  69. this.params.buyer = name;
  70. this.params.buyerName = nickName;
  71. this.params.puDept = deptId;
  72. this.params.puDeptName = deptName;
  73. this.params.billDate = new Date().Format('yyyy-MM-dd');
  74. console.log(this.params,'this.params');
  75. this.addTableRow();
  76. }
  77. },
  78. setVisible(prop,iscopy) {
  79. this.visible = prop;
  80. this.isCopy = iscopy;
  81. if(!this.visible){
  82. this.$refs['orderAddForm'].clearValidate();
  83. }
  84. },
  85. // 复制赋值
  86. async setCopyParams(id) {
  87. try {
  88. const { code, msg, data } = await orderApi.details(id);
  89. if (code === 200) {
  90. this.params = {
  91. ...data,
  92. id: "",
  93. code: "",
  94. isEnd:'N',
  95. status: "0",
  96. source: "3",
  97. isClose:'N',
  98. closeTime:'',
  99. isInvoice:'N',
  100. isSendWms:'N',
  101. rebateMoney:'',
  102. invoiceMoney:'',
  103. paymentMoney:'',
  104. applyPaymentMoney:'',
  105. };
  106. for (const key in this.params) {
  107. // if (Array.isArray(this.params[key])) {
  108. if (key === 'puOrderItemList' || key === 'puOrderExecuteList') {
  109. this.params[key].forEach((v) => {
  110. v.id = "";
  111. });
  112. }
  113. }
  114. // 清空 累计本币开票金额、
  115. // 累计付款金额、累计付款申请金额、累计开票主数量、最终关闭时间
  116. // 、最终关闭、已同步WMS 、订单抵扣余额金额、订单使用返利金额、 发票标识
  117. }
  118. } catch (err) {
  119. //
  120. } finally {
  121. // this.loading = false;
  122. }
  123. },
  124. // 增行
  125. addTableRow(prop) {
  126. for (const key in this.params) {
  127. // if (Array.isArray(this.params[key])) {
  128. if (key === 'puOrderItemList' || key === 'puOrderExecuteList') {
  129. const arr = this.tabColumns.find(
  130. (element) => element.key === key
  131. ).tableColumns;
  132. let rowData = initParams(arr, "key", "value");
  133. "rowno" in rowData &&
  134. (rowData["rowno"] = this.params[key].length + 1);
  135. // 物料
  136. if("rowNo" in rowData){
  137. rowData["rowNo"] = this.params[key].length + 1;
  138. // 扣税类别
  139. rowData["taxDeductClassify"] = '1';
  140. // 价格类型
  141. rowData["priceType"] = 'order';
  142. // 币种
  143. rowData["currency"] = '1002Z0100000000001K1';
  144. rowData["currencyName"] = '人民币';
  145. }
  146. // 是否完成询价,新增明细行需默认明细为false
  147. rowData["whetherCompleteInquiry"] = false;
  148. this.params[key].push(rowData);
  149. }
  150. }
  151. // const arr = this.tabColumns.find(
  152. // (element) => element.key === this.tabName
  153. // ).tableColumns;
  154. // prop.push(initParams(arr, "key", "value"));
  155. },
  156. // 删行
  157. async delTableRow(prop, index) {
  158. for (const key in this.params) {
  159. // if (Array.isArray(this.params[key])) {
  160. if (key === 'puOrderItemList' || key === 'puOrderExecuteList') {
  161. this.params[key].splice(index, 1);
  162. }
  163. }
  164. await this.handleGetPrice();
  165. // prop.splice(index, 1);
  166. },
  167. // 同步子表物料
  168. handleSynchronousMaterial(tableOne, tableTwo) {
  169. let _this = this;
  170. // this.params[tableOne]-- -> this.params[tableTwo]
  171. this.params[tableOne] &&
  172. this.params[tableOne].forEach((item, index) => {
  173. for (const key in item) {
  174. if(!_this.params[tableTwo][index]){
  175. const arr = _this.tabColumns.find(
  176. (element) => element.key === tableTwo
  177. ).tableColumns;
  178. _this.params[tableTwo].push(initParams(arr, "key", "value"));
  179. }
  180. if (key in _this.params[tableTwo][index]) {
  181. _this.params[tableTwo][index].material = item.material;
  182. key !== 'id' && ( _this.params[tableTwo][index][key] = item[key]);
  183. }
  184. }
  185. });
  186. },
  187. // 取消
  188. handleCancel() {
  189. this.params = {
  190. ...initParams(this.columns),
  191. puOrderItemList: [],
  192. puOrderExecuteList: [],
  193. };
  194. this.setVisible(false);
  195. },
  196. // 判断保存条件
  197. judgeSaveCondition(cb){
  198. this.$refs['orderAddForm'].validate(async (valid) => {
  199. if (valid) {
  200. if(!this.params['puOrderItemList'].length || !this.params['puOrderExecuteList'].length){
  201. this.$message.error('请填写订单行!');
  202. return false;
  203. }
  204. // puOrderItemList
  205. let isPrice = this.params.puOrderItemList.filter(item => !item.whetherCompleteInquiry);
  206. if(isPrice.length){
  207. this.$message.error('询价失败!');
  208. return false
  209. }
  210. console.log(isPrice,'isPrice');
  211. cb();
  212. } else {
  213. this.$message.error('存在必填项未填写');
  214. console.log('error submit!!');
  215. return false;
  216. }
  217. });
  218. },
  219. // 保存
  220. handleSava() {
  221. console.log(this.params,'this.params---------');
  222. this.judgeSaveCondition(async()=>{
  223. try {
  224. this.loading = true;
  225. const { code, msg } = await orderApi.create(this.params);
  226. if (code === 200) {
  227. this.handleCancel();
  228. }
  229. } catch (err) {
  230. //
  231. } finally {
  232. this.loading = false;
  233. }
  234. })
  235. },
  236. // 主表参照改变之后
  237. async handleReferChange(val, type, source){
  238. // 供应商选择
  239. if( type === 'SUPPLIER_PARAM' ){
  240. let page = { pageNum: 1 , pageSize: 10 };
  241. let relevanceRefer = [
  242. {
  243. // 供应商联系人
  244. key:'supplierContacts',
  245. params:{
  246. type:'SUPPLIERCONTACTS_PARAM',
  247. supplierId:val.id,
  248. }
  249. },
  250. {
  251. // 供应商业务员
  252. key:'supplierPersonal',
  253. params:{
  254. type:'PSNLICENSE_PARAM',
  255. supplierId:val.id,
  256. pkOrg: source.puOrg,
  257. }
  258. }
  259. ]
  260. await relevanceRefer.forEach(async (refer) =>{
  261. try {
  262. const { code, rows} = await orderApi.REFER(
  263. {
  264. ...refer.params,
  265. search: "",
  266. isPage: true,
  267. }, page );
  268. if (code === 200) {
  269. source[refer.key] = rows[0]? rows[0].id :'';
  270. source[`${refer.key}Name`] = rows[0] ? rows[0].name :'';
  271. }
  272. } catch (error) {}
  273. })
  274. }
  275. // 组织
  276. if(type === 'ORG_PARAM'){
  277. for (const key in this.params) {
  278. // if (Array.isArray(this.params[key])) {
  279. if (key === 'puOrderItemList' || key === 'puOrderExecuteList') {
  280. this.params[key] = [];
  281. }
  282. else if(key === 'sysFileRecordList'){
  283. this.params[key] = [];
  284. }
  285. else if (
  286. key != "puOrg" &&
  287. key != "puOrgName" &&
  288. key != "buyer" &&
  289. key != "buyerName" &&
  290. key != "puDept" &&
  291. key != "puDeptName" &&
  292. key != "status"
  293. ) {
  294. this.params[key] = "";
  295. } else {
  296. }
  297. }
  298. }
  299. },
  300. // 下拉框选择改变
  301. handleSelectChange(val,typeName){
  302. if(val === 'billType'){
  303. this.params['billTypeName'] = this.dict.type[typeName].find(item => item.value == this.params[val]).label;
  304. }
  305. },
  306. // 子表参照改变之后
  307. async handleTabReferChange(val, type, source) {
  308. // 触发物料参照询价
  309. if (type == "MATERIAL_PARAM" && source.qty && source.qty != "") {
  310. source['qty'] = 0;
  311. source['whetherCompleteInquiry'] = false;
  312. source['taxPrice'] = 0;
  313. source['money'] = 0;
  314. source['taxDeductMoneya'] = 0;
  315. source['price'] = 0;
  316. source['notaxMoney'] = 0;
  317. source['tax'] = 0;
  318. this.params['qty'] = 0;
  319. this.params['originalQty'] = 0;
  320. this.params['money'] = 0;
  321. this.params['originalMoney'] = 0;
  322. this.params['notaxMoney'] = 0;
  323. source.isDrug = val.materialMedcine.isDrug == '0' ? 'Y' : 'N';
  324. // await this.handleGetPrice();
  325. }
  326. },
  327. // 子表下拉框改变
  328. async handleTabSelectChange(type,row){
  329. if(type == 'priceType' && row.material && row.qty && row.qty != ""){
  330. row['whetherCompleteInquiry'] = false;
  331. await this.handleGetPrice();
  332. }
  333. },
  334. // 子表inputNumber
  335. handleInputChange(row, type) {
  336. // 物料数量变化----询价
  337. if (type == "qty" && row.material) {
  338. row['whetherCompleteInquiry'] = false;
  339. row.qty && this.handleGetPrice();
  340. }
  341. },
  342. // 子表多选框改变
  343. handleTabCheckbox(type,source){
  344. // 勾选赠品,价税合计更新为0,含税单价、无税单价更新为0
  345. if(type === 'isGift' && source.material && source.qty && source.qty != ""){
  346. source['whetherCompleteInquiry'] = false;
  347. this.handleGetPrice()
  348. }
  349. },
  350. // 询价 getPrice
  351. async handleGetPrice() {
  352. try {
  353. let { code, data } = await orderApi.getPrice({ ...this.params });
  354. if (code == 200) {
  355. this.params = data;
  356. }
  357. } catch (error) {}
  358. },
  359. },
  360. created() {
  361. console.log("ADD CREATED", this.params);
  362. },
  363. mounted() {},
  364. destroyed() {},
  365. };
  366. </script>
  367. <template>
  368. <el-drawer
  369. direction="btt"
  370. size="100%"
  371. :with-header="false"
  372. :visible.sync="visible"
  373. @open="beforeOpen"
  374. @close="$emit('close')"
  375. >
  376. <el-form
  377. size="mini"
  378. label-position="right"
  379. ref="orderAddForm"
  380. label-width="140px"
  381. :model="params"
  382. :rules="rules"
  383. >
  384. <el-card
  385. :body-style="{
  386. padding: '20px',
  387. display: 'flex',
  388. 'flex-wrap': 'wrap',
  389. }"
  390. style="margin: 10px"
  391. >
  392. <div
  393. slot="header"
  394. style="
  395. display: flex;
  396. justify-content: space-between;
  397. align-items: center;
  398. "
  399. >
  400. <h3>新增</h3>
  401. <div style="text-align: right">
  402. <el-button size="mini" @click="handleCancel">取消</el-button>
  403. <el-button
  404. size="mini"
  405. type="danger"
  406. @click="handleSava"
  407. >保存</el-button>
  408. <!-- <el-button size="mini" type="info" @click="handleSubmit">
  409. 保存并新增
  410. </el-button> -->
  411. </div>
  412. </div>
  413. <el-row style="display: flex; flex-wrap: wrap">
  414. <el-col
  415. v-for="(column, index) in columns"
  416. :key="index"
  417. :span="column.span || 6"
  418. >
  419. <el-form-item
  420. :prop="column.key"
  421. :label="column.title"
  422. v-if="column.isShow"
  423. >
  424. <el-input
  425. v-if="column.inputType === 'Input'"
  426. v-model="params[column.key]"
  427. :placeholder="column.placeholder"
  428. :clearable="column.clearable"
  429. :disabled="column.disabled"
  430. style="width: 100%"
  431. >
  432. </el-input>
  433. <dr-popover-select
  434. v-if="column.inputType === 'PopoverSelect'"
  435. v-model="params[column.key]"
  436. :value-key="column.valueKey"
  437. :source.sync="params"
  438. :title="column.title"
  439. :type="column.referName"
  440. :disabled="column.disabled"
  441. :multiple="column.multiple"
  442. :placeholder="column.placeholder"
  443. :data-mapping="column.dataMapping"
  444. :query-params="column.queryParams"
  445. @change="handleReferChange"
  446. ></dr-popover-select>
  447. <el-input
  448. v-if="column.inputType === 'Textarea'"
  449. v-model="params[column.key]"
  450. type="textarea"
  451. :placeholder="column.placeholder"
  452. :clearable="column.clearable"
  453. :disabled="column.disabled"
  454. style="width: 100%"
  455. ></el-input>
  456. <el-input-number
  457. v-if="column.inputType === 'InputNumber'"
  458. v-model="params[column.key]"
  459. :precision="column.precision"
  460. :controls-position="column.controlsPosition"
  461. :placeholder="column.placeholder"
  462. :clearable="column.clearable"
  463. :disabled="column.disabled"
  464. style="width: 100%"
  465. >
  466. </el-input-number>
  467. <el-select
  468. v-if="column.inputType === 'Select'"
  469. v-model="params[column.key]"
  470. :disabled="column.disabled"
  471. :clearable="column.clearable"
  472. :placeholder="column.placeholder"
  473. style="width: 100%"
  474. @change="handleSelectChange(column.key,column.referName)"
  475. >
  476. <el-option
  477. v-for="item in dict.type[column.referName]"
  478. :key="item.value"
  479. :label="item.label"
  480. :value="item.value"
  481. ></el-option>
  482. </el-select>
  483. <el-select
  484. v-if="column.inputType === 'TagSelect'"
  485. v-model="params[column.key]"
  486. multiple
  487. clearable
  488. collapse-tags
  489. :placeholder="column.placeholder"
  490. :clearable="column.clearable"
  491. :disabled="column.disabled"
  492. style="width: 100%"
  493. >
  494. <template #prefix>
  495. <el-icon
  496. class="el-icon-view"
  497. style="cursor: pointer"
  498. @click.stop="$message.info(234)"
  499. >
  500. </el-icon>
  501. </template>
  502. <el-option
  503. v-for="item in options"
  504. :key="item.value"
  505. :label="item.label"
  506. :value="item.value"
  507. ></el-option>
  508. </el-select>
  509. <el-date-picker
  510. v-if="column.inputType === 'DatePicker'"
  511. v-model="params[column.key]"
  512. :type="column.type"
  513. :placeholder="column.placeholder"
  514. :clearable="column.clearable"
  515. :disabled="column.disabled"
  516. :picker-options="column.pickerOptions"
  517. style="width: 100%"
  518. ></el-date-picker>
  519. <el-checkbox
  520. v-if="column.inputType === 'Checkbox'"
  521. v-model="params[column.key]"
  522. :disabled="column.disabled"
  523. true-label="Y"
  524. false-label="N"
  525. ></el-checkbox>
  526. <file-upload-center
  527. v-if="column.inputType === 'Upload'"
  528. v-model="params[column.key]"
  529. :file-type="column.fileType"
  530. ></file-upload-center>
  531. </el-form-item>
  532. </el-col>
  533. </el-row>
  534. </el-card>
  535. <el-card
  536. :body-style="{
  537. padding: '20px',
  538. display: 'flex',
  539. 'flex-wrap': 'wrap',
  540. position: 'relative',
  541. }"
  542. style="margin: 10px"
  543. >
  544. <el-tabs v-model="tabName" style="width: 100%">
  545. <el-tab-pane
  546. v-for="(column, index) in tabColumns"
  547. :key="index"
  548. :label="column.title"
  549. :name="column.key"
  550. >
  551. <el-table
  552. :data="params[column.key]"
  553. style="width: 100%"
  554. :height="params[column.key].length ? 300 : 100"
  555. >
  556. <el-table-column
  557. v-for="(cColumn, cIndex) in column.tableColumns"
  558. :key="cIndex"
  559. :label="cColumn.title"
  560. :width="cColumn.width || 80"
  561. >
  562. <template slot-scope="scope">
  563. <el-form-item
  564. label-width="0"
  565. :prop="`${column.key}.${scope.$index}.${[cColumn.key]}`"
  566. :rules="{ required: cColumn.require || false, message: `${cColumn.title}不能为空`, trigger: 'change' }"
  567. >
  568. <el-tag v-if="cColumn.key === 'index'" >
  569. {{ scope.$index + 1 }}
  570. </el-tag>
  571. <el-input
  572. v-if="cColumn.inputType === 'Input'"
  573. v-model="scope.row[cColumn.key]"
  574. :placeholder="cColumn.placeholder"
  575. :clearable="cColumn.clearable"
  576. :disabled="cColumn.disabled"
  577. size="mini"
  578. style="width: 100%"
  579. ></el-input>
  580. <!-- -->
  581. <dr-popover-select
  582. v-if="cColumn.inputType === 'PopoverSelect'"
  583. v-model="scope.row[cColumn.key]"
  584. :source.sync="scope.row"
  585. :title="cColumn.title"
  586. :value-key="cColumn.valueKey"
  587. :type="cColumn.referName"
  588. :disabled="cColumn.disabled"
  589. :multiple="cColumn.multiple"
  590. :placeholder="cColumn.placeholder"
  591. :data-mapping="cColumn.dataMapping"
  592. :query-params="cColumn.queryParams"
  593. @change="handleTabReferChange"
  594. size="mini"
  595. >
  596. </dr-popover-select>
  597. <el-input-number
  598. v-if="cColumn.inputType === 'InputNumber'"
  599. v-model="scope.row[cColumn.key]"
  600. :precision="cColumn.precision"
  601. :controls-position="cColumn.controlsPosition"
  602. :placeholder="cColumn.placeholder"
  603. @change="handleInputChange(scope.row, cColumn.key)"
  604. :clearable="cColumn.clearable"
  605. :disabled="cColumn.disabled"
  606. size="mini"
  607. style="width: 100%"
  608. ></el-input-number>
  609. <el-select
  610. v-if="cColumn.inputType === 'Select'"
  611. v-model="scope.row[cColumn.key]"
  612. size="mini"
  613. :disabled="cColumn.disabled"
  614. :clearable="cColumn.clearable"
  615. :placeholder="cColumn.placeholder"
  616. style="width: 100%"
  617. @change="handleTabSelectChange(cColumn.key,scope.row)"
  618. >
  619. <el-option
  620. v-for="item in dict.type[cColumn.referName]"
  621. :key="item.value"
  622. :label="item.label"
  623. :value="item.value"
  624. ></el-option>
  625. </el-select>
  626. <el-checkbox
  627. v-if="cColumn.inputType === 'Checkbox'"
  628. v-model="scope.row[cColumn.key]"
  629. :disabled="cColumn.disabled"
  630. true-label="Y"
  631. false-label="N"
  632. @change="handleTabCheckbox(cColumn.key,scope.row)"
  633. ></el-checkbox>
  634. </el-form-item>
  635. </template>
  636. </el-table-column>
  637. <el-table-column fixed="right" label="操作" width="80">
  638. <template slot-scope="scope">
  639. <el-button
  640. @click.native.prevent="
  641. delTableRow(params[tabName], scope.$index)
  642. "
  643. type="text"
  644. size="small"
  645. >
  646. 删行
  647. </el-button>
  648. </template>
  649. </el-table-column>
  650. </el-table>
  651. </el-tab-pane>
  652. </el-tabs>
  653. <el-row style="position: absolute; top: 20px; right: 20px">
  654. <el-button size="mini" @click="addTableRow(params[tabName])"
  655. >增行</el-button
  656. >
  657. </el-row>
  658. </el-card>
  659. </el-form>
  660. </el-drawer>
  661. </template>