index.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833
  1. <template>
  2. <div class="tenant">
  3. <!-- <Banner /> -->
  4. <div class="content">
  5. <byTable
  6. :source="sourceList.data"
  7. :pagination="sourceList.pagination"
  8. :config="config"
  9. :loading="loading"
  10. highlight-current-row
  11. :selectConfig="selectConfig"
  12. :table-events="{
  13. //element talbe事件都能传
  14. select: select,
  15. }"
  16. :action-list="[
  17. {
  18. text: '添加物流数据',
  19. action: () => openModal('add'),
  20. },
  21. ]"
  22. @get-list="getList"
  23. >
  24. <template #one="{ item }">
  25. <div
  26. style="cursor: pointer; color: #409eff"
  27. @click="handleClickLinkCode(item)"
  28. >
  29. {{ item.businessCode }}
  30. </div>
  31. </template>
  32. <template #two="{ item }">
  33. <div
  34. style="cursor: pointer; color: #409eff"
  35. @click="handleClickCode(item)"
  36. >
  37. {{ item.code }}
  38. </div>
  39. </template>
  40. </byTable>
  41. </div>
  42. <el-dialog
  43. :title="
  44. modalType == 'add'
  45. ? '添加物流数据'
  46. : modalType == 'edit'
  47. ? '编辑物流数据'
  48. : '到货通知'
  49. "
  50. v-model="dialogVisible"
  51. width="800"
  52. v-loading="loading"
  53. >
  54. <byForm
  55. v-if="modalType != 'other'"
  56. :formConfig="formConfig"
  57. :formOption="formOption"
  58. v-model="formData.data"
  59. :rules="rules"
  60. ref="byform"
  61. >
  62. </byForm>
  63. <byForm
  64. v-else
  65. :formConfig="formConfigOne"
  66. :formOption="formOption"
  67. v-model="formData.data"
  68. :rules="rules"
  69. ref="byform"
  70. >
  71. <template #detailSlot>
  72. <div style="width: 100%">
  73. <el-table :data="formData.data.arrivalDetailList">
  74. <el-table-column
  75. prop="productDefinition"
  76. label="物品类型"
  77. :formatter="
  78. (row) =>
  79. row.productDefinition == 1
  80. ? '产品'
  81. : row.productDefinition == 2
  82. ? '物料'
  83. : ''
  84. "
  85. />
  86. <el-table-column prop="productCode" label="物品编码" />
  87. <el-table-column prop="productName" label="物品名称" />
  88. <!-- <el-table-column prop="productSpec" label="规格型号" /> -->
  89. <el-table-column prop="productUnit" label="单位" />
  90. <el-table-column prop="count" label="采购数量" />
  91. <el-table-column prop="transitQuantity" label="剩余在途" />
  92. <el-table-column prop="deliverGoodsQuantity" label="本次发货" />
  93. </el-table>
  94. </div>
  95. </template>
  96. </byForm>
  97. <template #footer>
  98. <el-button @click="dialogVisible = false" size="large">取 消</el-button>
  99. <el-button
  100. type="primary"
  101. @click="submitForm('byform')"
  102. size="large"
  103. :loading="submitLoading"
  104. >
  105. 确 定
  106. </el-button>
  107. </template>
  108. </el-dialog>
  109. <el-dialog
  110. title="物流数据"
  111. v-model="openRecord"
  112. width="40%"
  113. top="50px"
  114. destroy-on-close
  115. >
  116. <!-- <div style="padding-left: 40px; margin-bottom: 20px">
  117. <el-button size="mini" @click="handleAddRecord">
  118. 添加物流记录
  119. </el-button>
  120. </div> -->
  121. <div>
  122. <el-timeline :reverse="false">
  123. <el-timeline-item
  124. placement="top"
  125. v-for="(activity, index) in activities"
  126. :key="index"
  127. :timestamp="activity.ftime"
  128. >
  129. {{ activity.context }}
  130. </el-timeline-item>
  131. </el-timeline>
  132. </div>
  133. <template #footer>
  134. <el-button @click="openRecord = false" size="large">关闭</el-button>
  135. </template>
  136. </el-dialog>
  137. <el-dialog
  138. :title="'到货详情'"
  139. v-model="dialogVisibleOne"
  140. width="80%"
  141. destroy-on-close
  142. >
  143. <byForm
  144. :formConfig="formConfigTwo"
  145. :formOption="formOption"
  146. v-model="formData.dataOne"
  147. :rules="rules"
  148. ref="byformOne"
  149. >
  150. <template #detailSlot>
  151. <div style="width: 100%">
  152. <el-table :data="formData.dataOne.purchaseDetailVoList">
  153. <el-table-column prop="productCustomCode" label="物品编码" />
  154. <el-table-column prop="productName" label="物品名称" />
  155. <el-table-column prop="count" label="采购数量" />
  156. <el-table-column prop="deliverGoodsQuantity" label="已发货">
  157. <template #default="{ row }">
  158. <div>
  159. <el-popover
  160. placement="bottom-start"
  161. title="发货详情"
  162. :width="500"
  163. trigger="hover"
  164. >
  165. <div default>
  166. <el-table :data="row.deliverGoodsDetailList">
  167. <el-table-column
  168. label="发货时间"
  169. prop="createTime"
  170. width="155"
  171. />
  172. <el-table-column
  173. label="物流单号"
  174. prop="logisticsCode"
  175. />
  176. <el-table-column
  177. label="数量"
  178. prop="deliverGoodsQuantity"
  179. width="100"
  180. />
  181. </el-table>
  182. </div>
  183. <template #reference>
  184. <div style="cursor: pointer; color: #0084ff">
  185. {{ row.deliverGoodsQuantity }}
  186. </div>
  187. </template>
  188. </el-popover>
  189. </div>
  190. </template>
  191. </el-table-column>
  192. <el-table-column prop="receiptQuantity" label="已入库">
  193. <template #default="{ row }">
  194. <div>
  195. <el-popover
  196. placement="bottom-start"
  197. title="入库详情"
  198. :width="500"
  199. trigger="hover"
  200. >
  201. <div default>
  202. <el-table :data="row.receiptList">
  203. <el-table-column
  204. label="入库时间"
  205. prop="createTime"
  206. width="155"
  207. />
  208. <el-table-column
  209. label="入库单号"
  210. prop="logisticsCode"
  211. />
  212. <el-table-column
  213. label="数量"
  214. prop="quantity"
  215. width="100"
  216. />
  217. </el-table>
  218. </div>
  219. <template #reference>
  220. <div style="cursor: pointer; color: #0084ff">
  221. {{ row.receiptQuantity }}
  222. </div>
  223. </template>
  224. </el-popover>
  225. </div>
  226. </template>
  227. </el-table-column>
  228. <el-table-column prop="purchaseBackQuantity" label="退货">
  229. <template #default="{ row }">
  230. <div>
  231. <el-popover
  232. placement="bottom-start"
  233. title="退货详情"
  234. :width="500"
  235. trigger="hover"
  236. >
  237. <div default>
  238. <el-table :data="row.purchaseBackDetailsList">
  239. <el-table-column label="申请时间" prop="createTime" />
  240. <el-table-column label="申请数量" prop="quantity" />
  241. <el-table-column
  242. label="已退数量"
  243. prop="returnedQuantity"
  244. />
  245. </el-table>
  246. </div>
  247. <template #reference>
  248. <div style="cursor: pointer; color: #0084ff">
  249. {{ row.purchaseBackQuantity }}
  250. </div>
  251. </template>
  252. </el-popover>
  253. </div>
  254. </template>
  255. </el-table-column>
  256. <el-table-column prop="qualityQuantity" label="已质检数量" />
  257. <el-table-column prop="noQualifiedCount" label="不合格数量" />
  258. </el-table>
  259. </div>
  260. </template>
  261. </byForm>
  262. <template #footer>
  263. <el-button @click="dialogVisibleOne = false" size="large"
  264. >取 消</el-button
  265. >
  266. </template>
  267. </el-dialog>
  268. </div>
  269. </template>
  270. <script setup>
  271. /* eslint-disable vue/no-unused-components */
  272. import { ElMessage, ElMessageBox } from "element-plus";
  273. import byTable from "@/components/byTable/index";
  274. import byForm from "@/components/byForm/index";
  275. import { computed, defineComponent, ref } from "vue";
  276. import useUserStore from "@/store/modules/user";
  277. import SelectProduct from "@/components/WDLY/product/SelectProduct";
  278. const loading = ref(false);
  279. const submitLoading = ref(false);
  280. const sourceList = ref({
  281. data: [],
  282. pagination: {
  283. total: 3,
  284. pageNum: 1,
  285. pageSize: 10,
  286. },
  287. });
  288. let dialogVisible = ref(false);
  289. let dialogVisibleOne = ref(false);
  290. let openProduct = ref(false);
  291. let openRecord = ref(false);
  292. const activities = ref([]);
  293. let roomDialogVisible = ref(false);
  294. let modalType = ref("add");
  295. let rules = ref({
  296. businessType: [
  297. { required: true, message: "请选择数据来源", trigger: "change" },
  298. ],
  299. logisticsCompanyCode: [
  300. { required: true, message: "请选择物流/快递公司", trigger: "change" },
  301. ],
  302. code: [{ required: true, message: "请输入物流/快递单号", trigger: "blur" }],
  303. isKd100: [{ required: true, message: "请选择是否同步", trigger: "change" }],
  304. });
  305. const { proxy } = getCurrentInstance();
  306. const statusData = ref([
  307. {
  308. label: "在途",
  309. value: "0",
  310. },
  311. {
  312. label: "揽收",
  313. value: "1",
  314. },
  315. {
  316. label: "疑难",
  317. value: "2",
  318. },
  319. {
  320. label: "签收",
  321. value: "3",
  322. },
  323. {
  324. label: "退签",
  325. value: "4",
  326. },
  327. {
  328. label: "派件",
  329. value: "5",
  330. },
  331. {
  332. label: "退回",
  333. value: "6",
  334. },
  335. {
  336. label: "转投",
  337. value: "7",
  338. },
  339. {
  340. label: "清关",
  341. value: "8",
  342. },
  343. {
  344. label: "拒签",
  345. value: "14",
  346. },
  347. {
  348. label: "完成",
  349. value: "15",
  350. },
  351. ]);
  352. const businessType = ref([
  353. {
  354. dictValue: "采购入库",
  355. dictKey: "1",
  356. },
  357. {
  358. dictValue: "京东订单出库",
  359. dictKey: "2",
  360. },
  361. {
  362. dictValue: "销售订单出库",
  363. dictKey: "3",
  364. },
  365. {
  366. dictValue: "京东退货",
  367. dictKey: "4",
  368. },
  369. {
  370. dictValue: "采购退货",
  371. dictKey: "5",
  372. },
  373. ]);
  374. const deptData = ref([]);
  375. const selectConfig = computed(() => [
  376. {
  377. label: "数据来源",
  378. prop: "businessType",
  379. data: businessType.value,
  380. },
  381. {
  382. label: "物流状态",
  383. prop: "logisticsStatus",
  384. data: statusData.value,
  385. },
  386. {
  387. label: "项目组",
  388. prop: "deptId",
  389. data: deptData.value,
  390. },
  391. ]);
  392. const config = computed(() => {
  393. return [
  394. {
  395. attrs: {
  396. label: "数据来源",
  397. prop: "businessType",
  398. },
  399. render(type) {
  400. return proxy.dictDataEcho(type, businessType.value);
  401. },
  402. },
  403. {
  404. attrs: {
  405. label: "关联单号",
  406. prop: "businessCode",
  407. slot: "one",
  408. },
  409. },
  410. {
  411. attrs: {
  412. label: "项目组",
  413. prop: "deptName",
  414. width: 150,
  415. },
  416. },
  417. {
  418. attrs: {
  419. label: "物流/快递公司",
  420. prop: "logisticsCompanyName",
  421. },
  422. },
  423. {
  424. attrs: {
  425. label: "物流/快递单号",
  426. prop: "code",
  427. slot: "two",
  428. },
  429. },
  430. {
  431. attrs: {
  432. label: "物流状态",
  433. prop: "logisticsStatus",
  434. },
  435. render(logisticsStatus) {
  436. let current = statusData.value.find((x) => x.value == logisticsStatus);
  437. return current ? current.label : "异常";
  438. },
  439. },
  440. {
  441. attrs: {
  442. label: "创建时间",
  443. prop: "createTime",
  444. },
  445. },
  446. {
  447. attrs: {
  448. label: "操作",
  449. width: "200",
  450. align: "right",
  451. },
  452. // 渲染 el-button,一般用在最后一列。
  453. renderHTML(row) {
  454. return [
  455. {
  456. attrs: {
  457. label: "修改",
  458. type: "primary",
  459. text: true,
  460. },
  461. el: "button",
  462. click() {
  463. getDtl(row);
  464. },
  465. },
  466. {
  467. attrs: {
  468. label: "更新状态",
  469. type: "primary",
  470. text: true,
  471. },
  472. el: "button",
  473. click() {
  474. editStatus(row);
  475. },
  476. },
  477. row.businessType == 1
  478. ? {
  479. attrs: {
  480. label: "到货通知",
  481. type: "primary",
  482. text: true,
  483. },
  484. el: "button",
  485. click() {
  486. handleArrival(row);
  487. },
  488. }
  489. : {},
  490. ];
  491. },
  492. },
  493. ];
  494. });
  495. let formData = reactive({
  496. data: {},
  497. dataOne: {},
  498. treeData: [],
  499. });
  500. const formOption = reactive({
  501. inline: true,
  502. labelWidth: 100,
  503. itemWidth: 100,
  504. rules: [],
  505. });
  506. const byform = ref(null);
  507. const treeData = ref([]);
  508. const formConfig = reactive([
  509. {
  510. type: "select",
  511. prop: "businessType",
  512. label: "数据来源",
  513. data: [],
  514. itemWidth: 61,
  515. },
  516. {
  517. type: "select",
  518. prop: "logisticsCompanyCode",
  519. label: "物流/快递信息",
  520. filterable: true,
  521. data: [],
  522. itemWidth: 40,
  523. style: {
  524. width: "100%",
  525. },
  526. },
  527. {
  528. type: "input",
  529. prop: "code",
  530. label: " ",
  531. itemWidth: 60,
  532. },
  533. {
  534. type: "radio",
  535. prop: "isKd100",
  536. label: "是否同步",
  537. required: true,
  538. border: true,
  539. data: [
  540. { label: "是", value: "1" },
  541. { label: "否", value: "2" },
  542. ],
  543. },
  544. {
  545. type: "input",
  546. prop: "remark",
  547. label: "备注",
  548. itemType: "textarea",
  549. },
  550. ]);
  551. const formConfigOne = reactive([
  552. {
  553. type: "title",
  554. title: "基础信息",
  555. },
  556. {
  557. type: "input",
  558. prop: "supplyName",
  559. label: "供应商",
  560. disabled: true,
  561. itemWidth: 50,
  562. },
  563. {
  564. type: "input",
  565. prop: "purchaseCode",
  566. label: "采购单号",
  567. disabled: true,
  568. itemWidth: 50,
  569. },
  570. {
  571. type: "select",
  572. label: "物流/快递单号",
  573. prop: "code",
  574. itemWidth: 50,
  575. disabled: true,
  576. style: {
  577. width: "100%",
  578. },
  579. },
  580. {
  581. type: "slot",
  582. slotName: "detailSlot",
  583. label: "发货明细",
  584. },
  585. ]);
  586. let formConfigTwo = computed(() => [
  587. {
  588. type: "title",
  589. title: "基础信息",
  590. },
  591. {
  592. type: "input",
  593. prop: "supplyName",
  594. label: "供应商",
  595. disabled: true,
  596. itemWidth: 50,
  597. },
  598. {
  599. type: "input",
  600. prop: "purchaseCode",
  601. label: "采购单号",
  602. disabled: true,
  603. itemWidth: 50,
  604. },
  605. {
  606. type: "title",
  607. title: "采购明细",
  608. },
  609. {
  610. type: "slot",
  611. slotName: "detailSlot",
  612. label: "",
  613. },
  614. ]);
  615. const getList = async (req) => {
  616. sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
  617. loading.value = true;
  618. proxy
  619. .post("/logisticsInfos/page", sourceList.value.pagination)
  620. .then((message) => {
  621. console.log(message);
  622. sourceList.value.data = message.rows;
  623. sourceList.value.pagination.total = message.total;
  624. setTimeout(() => {
  625. loading.value = false;
  626. }, 200);
  627. });
  628. };
  629. const openModal = () => {
  630. dialogVisible.value = true;
  631. modalType.value = "add";
  632. formConfig[0].disabled = false;
  633. formData.data = {
  634. isKd100: "1",
  635. };
  636. };
  637. const submitForm = () => {
  638. console.log(byform.value);
  639. byform.value.handleSubmit((valid) => {
  640. if (modalType.value == "other") {
  641. loading.value = true;
  642. submitLoading.value = true;
  643. formData.data.arrivalDetailList = formData.data.arrivalDetailList.map(
  644. (x) => ({
  645. bussinessId: x.bussinessId,
  646. purchaseDetailId: x.purchaseDetailId,
  647. deliverGoodsDetailsId: x.deliverGoodsDetailsId,
  648. count: x.deliverGoodsQuantity,
  649. })
  650. );
  651. const victoriatouristJson = {
  652. deliverGoodsId: formData.data.deliverGoodsId,
  653. logisticsCompanyCode: formData.data.logisticsCompanyCode,
  654. code: formData.data.code,
  655. };
  656. formData.data.victoriatouristJson = JSON.stringify(victoriatouristJson);
  657. proxy.post("/arrival/addByWdly", formData.data).then(
  658. (res) => {
  659. ElMessage({
  660. message: `操作成功!`,
  661. type: "success",
  662. });
  663. dialogVisible.value = false;
  664. loading.value = false;
  665. getList();
  666. },
  667. (err) => (submitLoading.value = false)
  668. );
  669. } else {
  670. loading.value = true;
  671. submitLoading.value = true;
  672. proxy.post("/logisticsInfos/" + modalType.value, formData.data).then(
  673. (res) => {
  674. ElMessage({
  675. message: modalType.value == "add" ? "添加成功" : "编辑成功",
  676. type: "success",
  677. });
  678. dialogVisible.value = false;
  679. submitLoading.value = false;
  680. getList();
  681. },
  682. (err) => (submitLoading.value = false)
  683. );
  684. }
  685. });
  686. };
  687. const getDtl = (row) => {
  688. modalType.value = "edit";
  689. proxy.post("/logisticsInfos/detail", { id: row.id }).then((res) => {
  690. formConfig[0].disabled = true;
  691. formData.data = {
  692. id: res.id,
  693. businessType: res.businessType + "",
  694. logisticsCompanyCode: res.logisticsCompanyCode,
  695. code: res.code,
  696. isKd100: res.isKd100 + "",
  697. remark: "",
  698. };
  699. dialogVisible.value = true;
  700. });
  701. };
  702. const editStatus = (row) => {
  703. ElMessageBox.confirm("是否确定进行此操作?", "提示", {
  704. confirmButtonText: "确定",
  705. cancelButtonText: "取消",
  706. type: "warning",
  707. }).then(() => {
  708. // 删除
  709. proxy
  710. .post("/logisticsInfos/dataInfoEdit", {
  711. id: row.id,
  712. })
  713. .then((res) => {
  714. ElMessage({
  715. message: "更新成功",
  716. type: "success",
  717. });
  718. getList();
  719. });
  720. });
  721. };
  722. const logisticsData = ref([]);
  723. const getLogisticsData = (row) => {
  724. proxy.post("/companyInfo/list", { pageNum: 1, pageSize: 999 }).then((res) => {
  725. // logisticsData.value = res.reverse().slice(0, 100); //截取前100
  726. logisticsData.value = res.reverse();
  727. formConfig[1].data = logisticsData.value.map((x) => ({
  728. label: x.name,
  729. value: x.code,
  730. }));
  731. });
  732. };
  733. const handleClickCode = (row) => {
  734. let id = row.id;
  735. proxy.post("/logisticsInfos/getLogistics", { id }).then((res) => {
  736. if (res.data && res.data.length > 0) {
  737. activities.value = res.data;
  738. openRecord.value = true;
  739. } else {
  740. return ElMessage({
  741. message: res.message,
  742. type: "info",
  743. });
  744. }
  745. });
  746. };
  747. const deliverData = ref([]);
  748. const handleArrival = (row) => {
  749. modalType.value = "other";
  750. proxy.post("/deliverGoods/detail", { id: row.businessId }).then((res) => {
  751. formData.data = {
  752. purchaseId: row.id,
  753. businessId: row.id,
  754. supplyName: row.supplyName,
  755. purchaseCode: row.businessCode,
  756. supplyId: row.supplyId,
  757. code: row.code,
  758. logisticsCompanyCode: row.logisticsCompanyCode,
  759. deliverGoodsId: res[0] ? res[0].deliverGoodsId : "",
  760. arrivalDetailList: res.map((x) => ({
  761. count: x.count,
  762. productName: x.name,
  763. productSpec: x.spec,
  764. productUnit: x.unit,
  765. productType: x.type,
  766. productCode: x.code,
  767. bussinessId: x.productId,
  768. purchaseDetailId: x.purchaseDetailId,
  769. deliverGoodsDetailsId: x.id,
  770. transitQuantity: x.transitQuantity,
  771. deliverGoodsQuantity: x.deliverGoodsQuantity,
  772. productDefinition: x.definition,
  773. })),
  774. };
  775. dialogVisible.value = true;
  776. });
  777. };
  778. const handleClickLinkCode = (row) => {
  779. if (row.businessType == 1 || row.businessType == 5) {
  780. ElMessage({
  781. message: "数据请求中,请稍后",
  782. type: "info",
  783. });
  784. proxy
  785. .post("/deliverGoods/arrivalDetail", { purchaseId: row.purchaseId })
  786. .then((res) => {
  787. formData.dataOne = {
  788. supplyName: res.supplyName,
  789. purchaseCode: row.businessCode,
  790. purchaseDetailVoList: res.purchaseDetailVoList,
  791. };
  792. dialogVisibleOne.value = true;
  793. });
  794. }
  795. };
  796. const getDict = () => {
  797. proxy.get("/logisticsInfos/getDepts").then((res) => {
  798. deptData.value = res.data.map((x) => ({
  799. ...x,
  800. label: x.deptName,
  801. value: x.deptId,
  802. }));
  803. });
  804. };
  805. getDict();
  806. getList();
  807. getLogisticsData();
  808. onMounted(() => {
  809. formConfig[0].data = businessType.value.map((x) => ({
  810. label: x.dictValue,
  811. value: x.dictKey,
  812. }));
  813. });
  814. </script>
  815. <style lang="scss" scoped>
  816. .tenant {
  817. padding: 20px;
  818. }
  819. </style>