index.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547
  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: selectRow,
  15. }"
  16. :action-list="[
  17. {
  18. text: '合并付款',
  19. disabled: selectData.length === 0,
  20. action: () => handlePayment(20),
  21. },
  22. ]"
  23. @get-list="getList"
  24. >
  25. <template #contractCode="{ item }">
  26. <div
  27. style="cursor: pointer; color: #409eff"
  28. @click="handleClickContractCode(item)"
  29. >
  30. {{ item.contractCode }}
  31. </div>
  32. </template>
  33. <template #payStatus="{ item }">
  34. <div
  35. style="cursor: pointer; color: #409eff"
  36. @click="handleClickPayStatus(item)"
  37. >
  38. {{ dictValueLabel(item.payStatus, paymentStatus) }}
  39. </div>
  40. </template>
  41. <template #btn="{ item }">
  42. <div>
  43. <el-button
  44. type="primary"
  45. link
  46. v-if="item.payStatus != 30"
  47. @click="handlePayment(10, item)"
  48. >付款</el-button
  49. >
  50. <el-button
  51. type="primary"
  52. link
  53. v-if="item.payStatus != 30"
  54. @click="handleEnd(item)"
  55. >结束</el-button
  56. >
  57. <el-button type="primary" link @click="handleClear(item)"
  58. >清空</el-button
  59. >
  60. </div>
  61. </template>
  62. </byTable>
  63. </div>
  64. <el-dialog
  65. :title="'付款'"
  66. v-model="dialogVisible"
  67. width="800"
  68. v-loading="submitLoading"
  69. destroy-on-close
  70. :before-close="handleClose"
  71. >
  72. <byForm
  73. :formConfig="formConfig"
  74. :formOption="formOption"
  75. v-model="formData.data"
  76. :rules="rules"
  77. ref="byform"
  78. >
  79. <template #details>
  80. <div style="width: 100%">
  81. <el-table :data="formData.data.purchasePayRecordDetailList">
  82. <el-table-column prop="code" label="采购单号" />
  83. <el-table-column prop="waitAmount" label="采购金额" />
  84. <el-table-column prop="alreadyAmount" label="已付款金额" />
  85. <el-table-column prop="amount" label="付款金额" min-width="150">
  86. <template #default="{ row, $index }">
  87. <el-form-item
  88. :prop="'purchasePayRecordDetailList.' + $index + '.amount'"
  89. :rules="rules.amount"
  90. :inline-message="true"
  91. >
  92. <el-input-number
  93. v-model="row.amount"
  94. :precision="4"
  95. :controls="false"
  96. :min="0"
  97. onmousewheel="return false;"
  98. />
  99. </el-form-item>
  100. </template>
  101. </el-table-column>
  102. </el-table>
  103. </div>
  104. </template>
  105. </byForm>
  106. <template #footer>
  107. <el-button @click="handleClose" size="large">取 消</el-button>
  108. <el-button
  109. type="primary"
  110. @click="submitForm('byform')"
  111. size="large"
  112. :loading="submitLoading"
  113. >
  114. 确 定
  115. </el-button>
  116. </template>
  117. </el-dialog>
  118. <el-dialog
  119. v-model="dialogVisibleOne"
  120. title="付款记录"
  121. width="500"
  122. append-to-body
  123. destroy-on-close
  124. >
  125. <div>
  126. <el-timeline :reverse="false">
  127. <el-timeline-item
  128. placement="top"
  129. v-for="(activity, index) in activities"
  130. :key="index"
  131. :timestamp="activity.payUserName"
  132. >
  133. <div>
  134. 付款账号: {{ dictValueLabel(activity.payAccount, accountData) }}
  135. </div>
  136. <div style="margin-top: 5px">
  137. 付款金额:{{ moneyFormat(activity.amount, 2) }}
  138. </div>
  139. <div style="margin-top: 5px">付款时间: {{ activity.payDate }}</div>
  140. </el-timeline-item>
  141. </el-timeline>
  142. </div>
  143. <template #footer>
  144. <el-button @click="dialogVisibleOne = false">关闭</el-button>
  145. </template>
  146. </el-dialog>
  147. </div>
  148. </template>
  149. <script setup>
  150. import { ElMessage, ElMessageBox } from "element-plus";
  151. import byTable from "@/components/byTable/index";
  152. import byForm from "@/components/byForm/index";
  153. const loading = ref(false);
  154. const submitLoading = ref(false);
  155. const sourceList = ref({
  156. data: [],
  157. pagination: {
  158. total: 3,
  159. pageNum: 1,
  160. pageSize: 10,
  161. type: "",
  162. keyword: "",
  163. },
  164. });
  165. let dialogVisible = ref(false);
  166. let dialogVisibleOne = ref(false);
  167. let activities = ref([]);
  168. let modalType = ref("add");
  169. let rules = ref({
  170. amount: [{ required: true, message: "请输入付款金额", trigger: "blur" }],
  171. payDate: [{ required: true, message: "请选择付款时间", trigger: "change" }],
  172. payAccount: [
  173. { required: true, message: "请选择付款账号", trigger: "change" },
  174. ],
  175. });
  176. const { proxy } = getCurrentInstance();
  177. const arrivalStatus = ref([
  178. {
  179. label: "未到货",
  180. value: "0",
  181. },
  182. {
  183. label: "部分到货",
  184. value: "10",
  185. },
  186. {
  187. label: "已到货",
  188. value: "20",
  189. },
  190. ]);
  191. const paymentStatus = ref([
  192. {
  193. label: "未付款",
  194. value: "0",
  195. },
  196. {
  197. label: "部分付款",
  198. value: "10",
  199. },
  200. {
  201. label: "已付款",
  202. value: "20",
  203. },
  204. {
  205. label: "付款结束",
  206. value: "30",
  207. },
  208. ]);
  209. const selectConfig = computed(() => [
  210. {
  211. label: "到货状态",
  212. prop: "arrivalStatus",
  213. data: arrivalStatus.value,
  214. },
  215. {
  216. label: "付款状态",
  217. prop: "payStatus",
  218. data: paymentStatus.value,
  219. },
  220. ]);
  221. const config = computed(() => {
  222. return [
  223. {
  224. type: "selection",
  225. attrs: {
  226. checkAtt: "isCheck",
  227. },
  228. },
  229. {
  230. attrs: {
  231. label: "采购单号",
  232. slot: "contractCode",
  233. },
  234. },
  235. {
  236. attrs: {
  237. label: "供应商",
  238. prop: "supplyName",
  239. },
  240. },
  241. {
  242. attrs: {
  243. label: "收货仓库",
  244. prop: "receiptWarehouseName",
  245. },
  246. },
  247. {
  248. attrs: {
  249. label: "采购金额",
  250. prop: "amount",
  251. width: 100,
  252. },
  253. render(amount) {
  254. return proxy.moneyFormat(amount, 2);
  255. },
  256. },
  257. {
  258. attrs: {
  259. label: "已付款金额",
  260. prop: "paidAmount",
  261. width: 100,
  262. },
  263. render(paidAmount) {
  264. return proxy.moneyFormat(paidAmount, 2);
  265. },
  266. },
  267. {
  268. attrs: {
  269. label: "采购人",
  270. prop: "purchaseName",
  271. width: 150,
  272. },
  273. },
  274. {
  275. attrs: {
  276. label: "采购时间",
  277. prop: "createTime",
  278. width: 155,
  279. },
  280. },
  281. {
  282. attrs: {
  283. label: "到货状态",
  284. prop: "arrivalStatus",
  285. width: 100,
  286. },
  287. render(status) {
  288. return proxy.dictValueLabel(status, arrivalStatus.value);
  289. },
  290. },
  291. {
  292. attrs: {
  293. label: "付款状态",
  294. slot: "payStatus",
  295. width: 100,
  296. },
  297. },
  298. {
  299. attrs: {
  300. label: "操作",
  301. slot: "btn",
  302. width: "180",
  303. align: "center",
  304. fixed: "right",
  305. },
  306. },
  307. ];
  308. });
  309. let formData = reactive({
  310. data: {
  311. type: "1",
  312. },
  313. });
  314. const formOption = reactive({
  315. inline: true,
  316. labelWidth: 100,
  317. itemWidth: 100,
  318. rules: [],
  319. });
  320. const byform = ref(null);
  321. let formConfig = computed(() => [
  322. {
  323. type: "input",
  324. prop: "supplyName",
  325. label: "供应商",
  326. disabled: true,
  327. },
  328. {
  329. type: "date",
  330. itemType: "datetime",
  331. prop: "payDate",
  332. label: "付款时间",
  333. format: "YYYY-MM-DD HH:mm:ss",
  334. itemWidth: 35,
  335. },
  336. {
  337. type: "select",
  338. prop: "payAccount",
  339. label: "付款账号",
  340. data: accountData.value,
  341. itemWidth: 50,
  342. },
  343. {
  344. type: "number",
  345. prop: "amount",
  346. label: "付款金额",
  347. precision: 4,
  348. min: 0,
  349. controls: false,
  350. },
  351. {
  352. type: "title",
  353. title: "付款明细",
  354. },
  355. {
  356. type: "slot",
  357. slotName: "details",
  358. label: "",
  359. },
  360. ]);
  361. const getList = async (req) => {
  362. sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
  363. loading.value = true;
  364. proxy
  365. .post("/purchase/pageByWdly", sourceList.value.pagination)
  366. .then((res) => {
  367. sourceList.value.data = res.rows.map((x) => ({
  368. ...x,
  369. ...JSON.parse(x.victoriatouristJson),
  370. isCheck: true,
  371. }));
  372. sourceList.value.pagination.total = res.total;
  373. setTimeout(() => {
  374. loading.value = false;
  375. }, 200);
  376. });
  377. };
  378. const submitForm = () => {
  379. byform.value.handleSubmit((valid) => {
  380. const list = formData.data.purchasePayRecordDetailList;
  381. for (let i = 0; i < list.length; i++) {
  382. const e = list[i];
  383. if (Number(e.amount) + Number(e.alreadyAmount) > Number(e.waitAmount)) {
  384. return ElMessage({
  385. message: `本次付款加已付款金额不可大于采购金额`,
  386. type: "info",
  387. });
  388. }
  389. }
  390. const total = list.reduce((total, x) => (total += Number(x.amount)), 0);
  391. if (Number(formData.data.amount) != total) {
  392. return ElMessage({
  393. message: "本次付款合计必须等于上方的付款金额",
  394. type: "info",
  395. });
  396. }
  397. proxy.post("/purchasePayRecord/add", formData.data).then(
  398. (res) => {
  399. ElMessage({
  400. message: "操作成功",
  401. type: "success",
  402. });
  403. handleClose();
  404. setTimeout(() => {
  405. submitLoading.value = false;
  406. }, 5000);
  407. getList();
  408. },
  409. (err) => {
  410. submitLoading.value = false;
  411. }
  412. );
  413. });
  414. };
  415. const selectData = ref([]);
  416. const selectRow = (data) => {
  417. selectData.value = data;
  418. };
  419. const handleClose = () => {
  420. selectData.value = [];
  421. dialogVisible.value = false;
  422. };
  423. watch(selectData, (newVal, oldVal) => {
  424. if (newVal.length == 0) {
  425. sourceList.value.data.forEach((x) => {
  426. x.isCheck = true;
  427. });
  428. } else if (newVal.length == 1) {
  429. const current = newVal[0];
  430. sourceList.value.data.forEach((x) => {
  431. if (x.supplyId !== current.supplyId) {
  432. x.isCheck = false;
  433. }
  434. });
  435. }
  436. });
  437. const handlePayment = (type, data) => {
  438. modalType.value = "add";
  439. if (type === 10) {
  440. selectData.value = [data];
  441. } else if (type === 20) {
  442. }
  443. formData.data = {
  444. supplyName: selectData.value[0].supplyName,
  445. amount: "",
  446. payDate: "",
  447. purchasePayRecordDetailList: selectData.value.map((x) => ({
  448. purchaseId: x.id,
  449. code: x.contractCode,
  450. waitAmount: x.amount,
  451. alreadyAmount: x.paidAmount,
  452. amount: null,
  453. })),
  454. };
  455. dialogVisible.value = true;
  456. };
  457. const handleClickPayStatus = (row) => {
  458. proxy
  459. .post("/purchasePayRecordDetail/page", { purchaseId: row.id })
  460. .then((res) => {
  461. if (res && res.rows && res.rows.length > 0) {
  462. activities.value = res.rows;
  463. dialogVisibleOne.value = true;
  464. } else {
  465. return ElMessage({
  466. message: `暂无付款记录`,
  467. type: "info",
  468. });
  469. }
  470. });
  471. };
  472. const handleEnd = (row) => {
  473. // 弹窗提示是否删除
  474. ElMessageBox.confirm("是否确认结束?", "提示", {
  475. confirmButtonText: "确定",
  476. cancelButtonText: "取消",
  477. type: "warning",
  478. }).then(() => {
  479. // 删除
  480. proxy
  481. .post("/purchase/edit", {
  482. ...row,
  483. payStatus: 30,
  484. })
  485. .then((res) => {
  486. ElMessage({
  487. message: "操作成功",
  488. type: "success",
  489. });
  490. getList();
  491. });
  492. });
  493. };
  494. const handleClear = (row) => {
  495. // 弹窗提示是否删除
  496. ElMessageBox.confirm("是否确认清空付款记录?", "提示", {
  497. confirmButtonText: "确定",
  498. cancelButtonText: "取消",
  499. type: "warning",
  500. }).then(() => {
  501. // 删除
  502. proxy
  503. .post("/purchasePayRecordDetail/empty", {
  504. purchaseId: row.id,
  505. })
  506. .then((res) => {
  507. ElMessage({
  508. message: "操作成功",
  509. type: "success",
  510. });
  511. getList();
  512. });
  513. });
  514. };
  515. const accountData = ref([]);
  516. const getDict = () => {
  517. proxy.getDictOne(["purchase_payment_account"]).then((res) => {
  518. accountData.value = res["purchase_payment_account"].map((x) => ({
  519. label: x.dictValue,
  520. value: x.dictKey,
  521. }));
  522. });
  523. };
  524. getList();
  525. getDict();
  526. </script>
  527. <style lang="scss" scoped>
  528. .tenant {
  529. padding: 20px;
  530. }
  531. :deep(.el-table__header-wrapper .el-checkbox) {
  532. display: none;
  533. }
  534. </style>