add.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684
  1. <template>
  2. <view class="mainBox">
  3. <uni-nav-bar
  4. background-color="#157A2C"
  5. color="#fff"
  6. fixed="true"
  7. statusBar="true"
  8. left-icon="back"
  9. :title="this.form.id ? '修改采购需求' : '新建采购需求'"
  10. @clickLeft="back"
  11. >
  12. </uni-nav-bar>
  13. <u-subsection
  14. :list="list"
  15. :current="current"
  16. @change="sectionChange"
  17. ></u-subsection>
  18. <u-cell-group v-show="current == 0">
  19. <u-cell :title="'需求类型'" arrow-direction="down">
  20. <view slot="title" style="display: flex; align-items: center">
  21. <text class="required-mark">*</text>
  22. 需求类型
  23. </view>
  24. <uni-data-picker
  25. v-model="form.sourceType"
  26. slot="value"
  27. placeholder="请选择"
  28. :localdata="requirementSourceType"
  29. @change="sourceCodeOnchange"
  30. >
  31. </uni-data-picker>
  32. </u-cell>
  33. <u-cell :title="'需求单名称'" arrow-direction="down">
  34. <view slot="title" style="display: flex; align-items: center">
  35. <text class="required-mark">*</text>
  36. 需求单名称
  37. </view>
  38. <u--input
  39. slot="value"
  40. placeholder="请输入"
  41. border="surround"
  42. v-model="form.requirementName"
  43. ></u--input>
  44. </u-cell>
  45. <u-cell :title="'需求部门'" arrow-direction="down">
  46. <view slot="title" style="display: flex; align-items: center">
  47. <text class="required-mark">*</text>
  48. 需求部门
  49. </view>
  50. <!-- <u--input slot="value" placeholder="请输入" border="surround" v-model="form.requireDeptId"></u--input> -->
  51. <u--input
  52. slot="value"
  53. @click.native="classification"
  54. style="flex: 1"
  55. border="surround"
  56. placeholder="请选择需求部门"
  57. v-model="form.requireDeptName"
  58. >
  59. </u--input>
  60. </u-cell>
  61. <u-cell :title="'需求人'" arrow-direction="down">
  62. <view slot="title" style="display: flex; align-items: center">
  63. <text class="required-mark">*</text>
  64. 需求人
  65. </view>
  66. <!-- <u--input slot="value" placeholder="请输入" border="requireUserId" v-model="form.name"></u--input> -->
  67. <u--input
  68. slot="value"
  69. style="flex: 1"
  70. border="surround"
  71. v-model="form.requireUserName"
  72. placeholder="请选择需求人"
  73. @click.native="openSelector"
  74. >
  75. </u--input>
  76. </u-cell>
  77. <u-cell
  78. v-if="form.sourceType == 1"
  79. title="销售合同"
  80. arrow-direction="down"
  81. >
  82. <u--input
  83. slot="value"
  84. style="flex: 1"
  85. placeholder="请选择销售合同"
  86. border="surround"
  87. v-model="form.saleContractNo"
  88. @click.native="selectContractShow"
  89. ></u--input>
  90. </u-cell>
  91. <u-cell
  92. v-if="form.sourceType == 1"
  93. title="销售订单"
  94. arrow-direction="down"
  95. >
  96. <!-- <u--input slot="value" placeholder="请输入" border="requireUserId" v-model="form.name"></u--input> -->
  97. <u--input
  98. slot="value"
  99. style="flex: 1"
  100. border="surround"
  101. v-model="form.saleOrderNo"
  102. placeholder="请选择销售订单"
  103. @click.native="slectOrderShow"
  104. >
  105. </u--input>
  106. </u-cell>
  107. <u-cell title="是否接受拆单" arrow-direction="down">
  108. <uni-data-picker
  109. v-model="form.acceptUnpack"
  110. slot="value"
  111. placeholder="请选择"
  112. :localdata="acceptUnpackList"
  113. >
  114. </uni-data-picker>
  115. </u-cell>
  116. <u-cell title="'用途" arrow-direction="down">
  117. <view slot="title" style="display: flex; align-items: center">
  118. <text class="required-mark">*</text>
  119. 用途
  120. </view>
  121. <u--textarea
  122. slot="value"
  123. placeholder="请输入"
  124. border="surround"
  125. v-model="form.useTo"
  126. ></u--textarea>
  127. </u-cell>
  128. <u-cell title="附件" arrow-direction="down">
  129. <view slot="value" style="display: flex; align-items: center">
  130. <fileMain v-model="form.fileId"></fileMain>
  131. </view>
  132. </u-cell>
  133. <!-- <u-cell title="附件" arrow-direction="down">
  134. <view slot="value" style="display: flex; align-items: center">
  135. <fileMain v-model="files"></fileMain>
  136. </view>
  137. </u-cell> -->
  138. <u-cell title="备注" arrow-direction="down">
  139. <u--textarea
  140. slot="value"
  141. placeholder="请输入"
  142. border="surround"
  143. v-model="form.remark"
  144. ></u--textarea>
  145. </u-cell>
  146. </u-cell-group>
  147. <view class="footerButton">
  148. <u-button type="default" text="返回" @click="back"></u-button>
  149. <u-button type="primary" @click="save" text="保存"></u-button>
  150. </view>
  151. <produceList
  152. ref="produceListRef"
  153. v-show="current == 1"
  154. :isTemporary="true"
  155. ></produceList>
  156. <ba-tree-picker
  157. ref="treePicker"
  158. key="verify"
  159. :multiple="false"
  160. @select-change="confirm"
  161. title="选择部门"
  162. :selectedData="selectedData"
  163. :localdata="classificationList"
  164. valueKey="id"
  165. textKey="name"
  166. childrenKey="children"
  167. />
  168. <search-select
  169. ref="selector"
  170. v-model="form.requireUserId"
  171. :data-list="executorList"
  172. title="选择需求人"
  173. @change="onClose"
  174. >
  175. </search-select>
  176. <u-toast ref="uToast"></u-toast>
  177. </view>
  178. </template>
  179. <script>
  180. import { getByCode } from "@/api/pda/common.js";
  181. import searchSelect from "@/pages/salesServiceManagement/accessory/components/searchSelect.vue";
  182. import produceList from "../components/produceList.vue";
  183. import fileMain from "@/pages/doc/index.vue";
  184. import { requirementSourceType } from "@/enum/dict";
  185. import { listOrganizations } from "@/api/salesServiceManagement/workOrder/index.js";
  186. import { toTreeData } from "@/utils/utils.js";
  187. import { getUserPage } from "@/api/common.js";
  188. import {
  189. getTableList,
  190. getSaleOrderDetail,
  191. } from "@/api/saleManage/saleorder/index";
  192. import {
  193. getDetail,
  194. addPurchaseNeedManage,
  195. UpdateInformation,
  196. } from "@/api/purchasingManage/purchaseNeedManage.js";
  197. import { getInventoryTotal } from "@/api/pda/workOrder";
  198. import { contactQueryByCategoryIdsAPI } from "@/api/warehouseManagement/index";
  199. export default {
  200. components: {
  201. produceList,
  202. fileMain,
  203. searchSelect,
  204. },
  205. data() {
  206. return {
  207. list: ["基本信息", "需求清单"],
  208. acceptUnpackList: [
  209. { text: "接受", value: 1 },
  210. { text: "不接受", value: 0 },
  211. ],
  212. current: 0,
  213. show: false,
  214. requirementSourceType,
  215. classificationList: [],
  216. isUpdate: false,
  217. purchase_origin: [],
  218. files: [],
  219. form: {
  220. id: "",
  221. receiveDate: null,
  222. remark: null,
  223. requireDeptId: "",
  224. requireDeptName: "",
  225. requireUserId: "",
  226. requireUserName: "",
  227. sourceCode: "",
  228. sourceId: "",
  229. sourceType: "",
  230. sourceTypeName: "",
  231. requirementName: "",
  232. saleContractName: "",
  233. saleContractNo: "",
  234. saleContractId: "",
  235. saleOrderId: "",
  236. saleOrderNo: "",
  237. files: [], //附件集合
  238. acceptUnpack: 1,
  239. detailList: [],
  240. fileId: [],
  241. },
  242. business_opport_code: [],
  243. linkList: [],
  244. selectedData: [], // 使用部门绑定值
  245. executorList: [],
  246. };
  247. },
  248. created() {
  249. this.getByCode();
  250. //选择合同回调
  251. uni.$off("setContractList");
  252. uni.$on("setContractList", async (data) => {
  253. if (data && data.length > 0) {
  254. this.form = Object.assign({}, this.form, {
  255. saleContractId: data[0].id,
  256. saleContractName: data[0].contractName,
  257. saleContractNo: data[0].contractNo,
  258. });
  259. console.log("ddd~~~", data[0]);
  260. this.getSaleOrderList(data[0].id);
  261. }
  262. });
  263. uni.$off("setSaleOrder");
  264. uni.$on("setSaleOrder", async (data) => {
  265. if (data && data.length > 0) {
  266. this.form = Object.assign({}, this.form, {
  267. saleContractId: "",
  268. saleContractName: "",
  269. saleContractNo: "",
  270. saleOrderId: data[0].id,
  271. saleOrderNo: data[0].orderNo,
  272. });
  273. this.getSaleOrderDetail(this.form.saleOrderId);
  274. }
  275. });
  276. },
  277. onLoad(data) {
  278. this.getTreeList();
  279. if (data && data.id) {
  280. this.isUpdate = true;
  281. getDetail(data.id).then(async (res) => {
  282. if (res.fileId) {
  283. res.fileId = JSON.parse(res.fileId);
  284. } else {
  285. res.fileId = [];
  286. }
  287. if (res.requireDeptId) {
  288. this.getUserList(res.requireDeptId);
  289. }
  290. let validItems = res.detailList.filter((item) => item.productCode);
  291. let productIds = validItems.map((item) => item.productId);
  292. let productCodes = validItems.map((item) => item.productCode);
  293. // 批量获取库存和供应商信息
  294. let inventoryTotalList = [];
  295. let supplierObj = {};
  296. if (productIds.length > 0) {
  297. inventoryTotalList = await getInventoryTotal(productCodes);
  298. supplierObj = await contactQueryByCategoryIdsAPI({
  299. categoryIds: productIds,
  300. });
  301. // 更新每个产品的供应商和库存信息
  302. validItems.forEach((item, index) => {
  303. // 找到对应的索引位置
  304. let actualIndex = res.detailList.findIndex(
  305. (i) => i.productCode === item.productCode
  306. );
  307. if (actualIndex !== -1) {
  308. this.$set(
  309. res.detailList[actualIndex],
  310. "supplierList",
  311. supplierObj[item.productId]?.map((i) => ({
  312. ...i,
  313. text: i.name,
  314. value: i.id,
  315. })) || []
  316. );
  317. let find =
  318. inventoryTotalList.find(
  319. (key) => key.code == item.productCode
  320. ) || {};
  321. this.$set(
  322. res.detailList[actualIndex],
  323. "availableCountBase",
  324. find.availableCountBase
  325. );
  326. }
  327. });
  328. }
  329. // 处理数据格式
  330. res.detailList = res.detailList.map((item) => ({
  331. ...item,
  332. // files: item.files || [],
  333. // technicalDrawings: item.technicalDrawings || [],
  334. provenanceName: item.provenance
  335. ? this.getProvenance(item.provenance)
  336. : "",
  337. // modelKey: item.modelKey?.split(',') || [],
  338. // colorKey: item.colorKey?.split(',') || [],
  339. packageDispositionList:
  340. item.packageDispositionList?.map((i) => ({
  341. ...i,
  342. text: i.conversionUnit,
  343. value: i.id,
  344. })) || [],
  345. }));
  346. this.$set(this, "form", res);
  347. this.$nextTick(() => {
  348. this.$refs.produceListRef.init(res.detailList);
  349. });
  350. // }, 300)
  351. });
  352. } else {
  353. const userInfo = uni.getStorageSync("userInfo");
  354. this.$set(this.form, "requireUserId", userInfo.userId);
  355. this.$set(this.form, "requireUserName", userInfo.name);
  356. this.$set(this.form, "requireDeptId", userInfo.groupId);
  357. this.$set(this.form, "requireDeptName", userInfo.groupName);
  358. }
  359. },
  360. onUnload() {
  361. uni.$off("setContractList");
  362. uni.$off("setSaleOrder");
  363. },
  364. methods: {
  365. getProvenance(item) {
  366. console.log("getProvenance~~~~~", item);
  367. // try {
  368. // 检查item和provenance是否存在
  369. if (!item) {
  370. return "";
  371. }
  372. let arr = item;
  373. if (!Array.isArray(arr)) {
  374. console.log("arr is not array, convert to array");
  375. arr = arr.split(",");
  376. }
  377. return arr && arr.length
  378. ? arr
  379. .map((i) => {
  380. return this.purchase_origin.find((p) => p.value == i)?.text;
  381. })
  382. .join(",")
  383. : "";
  384. },
  385. async getSaleOrderList(contractId) {
  386. let res = await getTableList({
  387. pageNum: 1,
  388. size: 10,
  389. contractId,
  390. });
  391. this.form.saleOrderId = res.list[0]?.id;
  392. this.form.saleOrderNo = res.list[0]?.orderNo;
  393. this.getSaleOrderDetail(this.form.saleOrderId);
  394. },
  395. async getSaleOrderDetail(id) {
  396. const data = await getSaleOrderDetail(id);
  397. data.productList.forEach((item) => {
  398. item.expectReceiveDate = item.produceDeliveryDeadline;
  399. item.arrivalWay = 1;
  400. item["packageDispositionList"] =
  401. item.packageDispositionList?.map((i) => {
  402. return {
  403. ...i,
  404. text: i.conversionUnit,
  405. value: i.id,
  406. };
  407. }) || [];
  408. });
  409. this.$nextTick(() => {
  410. this.$refs.produceListRef.init(data.productList);
  411. });
  412. },
  413. async getTreeList() {
  414. const data = await listOrganizations({});
  415. let treeList = toTreeData({
  416. data: data || [],
  417. idField: "id",
  418. parentIdField: "parentId",
  419. });
  420. this.classificationList = treeList;
  421. },
  422. // 打开部门弹窗
  423. classification() {
  424. this.$refs.treePicker._show();
  425. },
  426. // 使用部门选择
  427. confirm(id, name) {
  428. this.form.requireDeptName = name;
  429. this.form.requireDeptId = id[0];
  430. this.form.requireUserId = "";
  431. this.form.requireUserName = "";
  432. this.executorList = [];
  433. this.getUserList(id[0]);
  434. this.$refs.selector.clearSearchText();
  435. },
  436. // 打开需求人弹窗
  437. openSelector() {
  438. this.$refs.selector.open();
  439. },
  440. // 获取需求人数据
  441. async getUserList(id) {
  442. let params = {
  443. pageNum: 1,
  444. size: -1,
  445. groupId: id,
  446. };
  447. try {
  448. const res = await getUserPage(params);
  449. let list =
  450. res.list &&
  451. res.list.map((el) => {
  452. return {
  453. text: el.name,
  454. value: el.id,
  455. };
  456. });
  457. this.executorList = list;
  458. } catch (error) {
  459. this.executorList = [];
  460. }
  461. },
  462. // 需求人选择
  463. onClose(item) {
  464. this.form.requireUserName = item.text;
  465. },
  466. //选择合同
  467. selectContractShow() {
  468. console.log("ddd~~~");
  469. uni.navigateTo({
  470. url: "/pages/purchasingManage/components/selectContract?isAll=" + 2,
  471. });
  472. },
  473. slectOrderShow() {
  474. uni.navigateTo({
  475. url: "/pages/purchasingManage/components/selectSaleOrder?isAll=" + 2,
  476. });
  477. },
  478. getByCode() {
  479. const codeS = ["business_opport_code", "purchase_origin"];
  480. codeS.forEach(async (code) => {
  481. const codeValue = await getByCode(code);
  482. this[code] = codeValue.map((item) => {
  483. const key = Object.keys(item)[0];
  484. return {
  485. value: key,
  486. text: item[key],
  487. };
  488. });
  489. });
  490. },
  491. sourceCodeOnchange(e) {
  492. const value = e.detail.value;
  493. this.form.sourceCode = value.map((item) => item.value).toString();
  494. this.form.sourceTypeName = value.map((item) => item.text).toString();
  495. this.form.saleOrderId = "";
  496. this.form.saleOrderNo = "";
  497. this.form.saleContractNo = "";
  498. this.form.saleContractId = "";
  499. this.form.saleContractName = "";
  500. },
  501. radioChange(e) {
  502. this.form.pricingWay = e.detail.value;
  503. this.$nextTick(() => {
  504. this.$refs.produceListRef.getTotalPrice();
  505. });
  506. },
  507. sectionChange(index) {
  508. this.current = index;
  509. },
  510. async save() {
  511. try {
  512. if (!this.form.sourceType) {
  513. this.$refs.uToast.show({
  514. type: "error",
  515. message: "请选择需求类型",
  516. });
  517. return;
  518. }
  519. if (!this.form.requirementName) {
  520. this.$refs.uToast.show({
  521. type: "error",
  522. message: "请输入需求名称",
  523. });
  524. return;
  525. }
  526. if (!this.form.requireDeptName) {
  527. this.$refs.uToast.show({
  528. type: "error",
  529. message: "请选择需求部门",
  530. });
  531. return;
  532. }
  533. if (!this.form.requireUserName) {
  534. this.$refs.uToast.show({
  535. type: "error",
  536. message: "请选择需求人",
  537. });
  538. return;
  539. }
  540. const detailList = this.$refs.produceListRef.getValue();
  541. if (detailList.length == 0) {
  542. this.$refs.uToast.show({
  543. type: "error",
  544. message: "产品清单不能为空",
  545. });
  546. return;
  547. }
  548. let isArrivalBatch = false;
  549. let isError = false;
  550. detailList.forEach((v) => {
  551. if (
  552. v.arrivalWay == 2 &&
  553. (!v.arrivalBatch || v.arrivalBatch.length == 0)
  554. ) {
  555. isArrivalBatch = true;
  556. }
  557. if (
  558. !v.purchaseCount ||
  559. !v.productName ||
  560. !v.arrivalWay ||
  561. (!v.expectReceiveDate && v.arrivalWay == 1)
  562. ) {
  563. isError = true;
  564. }
  565. });
  566. if (isError) {
  567. uni.showToast({ icon: "none", title: "请完善产品信息" });
  568. return;
  569. }
  570. if (isArrivalBatch) {
  571. uni.showToast({ icon: "none", title: "请设置分批时间" });
  572. return;
  573. }
  574. uni.showLoading({
  575. title: "加载中",
  576. });
  577. const data = {
  578. ...this.form,
  579. detailList: detailList,
  580. };
  581. data.fileId = JSON.stringify(data.fileId);
  582. data.detailList.forEach((item) => {
  583. if (item.provenance && typeof item.provenance == "string") {
  584. item.provenance = item.provenance.split(",");
  585. }
  586. });
  587. console.log("data~~~", data);
  588. const requestApi = this.isUpdate
  589. ? UpdateInformation
  590. : addPurchaseNeedManage;
  591. requestApi(data)
  592. .then((res) => {
  593. uni.hideLoading();
  594. this.back();
  595. })
  596. .catch((e) => {
  597. uni.hideLoading();
  598. });
  599. } catch (error) {
  600. uni.hideLoading();
  601. console.log(error, "error");
  602. }
  603. },
  604. },
  605. };
  606. </script>
  607. <style lang="scss" scoped>
  608. .required-mark {
  609. color: #ff3333;
  610. margin-right: 4rpx;
  611. }
  612. /deep/.u-cell__body__content {
  613. flex: none;
  614. margin-right: 16rpx;
  615. }
  616. .mainBox {
  617. padding-bottom: 84rpx;
  618. }
  619. .footerButton {
  620. width: 100%;
  621. height: 84rpx;
  622. display: flex;
  623. position: fixed;
  624. bottom: 0;
  625. z-index: 10;
  626. background-color: #fff;
  627. /deep/.u-button {
  628. height: 100%;
  629. }
  630. > view {
  631. flex: 1;
  632. }
  633. }
  634. // /deep/.u-button {
  635. // // height: 100%;
  636. // }
  637. /deep/.u-subsection__item__text {
  638. font-size: 28rpx !important;
  639. }
  640. /deep/.uni-input-placeholder {
  641. font-size: 28rpx !important;
  642. }
  643. /deep/.selected-item {
  644. font-size: 28rpx !important;
  645. }
  646. /deep/.uni-input-input {
  647. font-size: 28rpx !important;
  648. }
  649. </style>