index.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
  1. <template>
  2. <div class="pageIndexClass">
  3. <byTable :source="sourceList.data" :pagination="sourceList.pagination" :config="config" :loading="loading" highlight-current-row
  4. :selectConfig="selectConfig" :action-list="[]" @get-list="getList">
  5. <template #money="{ item }">
  6. {{ item.currency }} {{ moneyFormat(item.amount) }}
  7. </template>
  8. <template #isClaim="{ item }">
  9. <div style="width: 100%">
  10. <span v-if="item.isClaim == 0">未认领</span>
  11. <a style="color: #409eff; cursor: pointer" @click="clickRecord(item)" v-else-if="item.isClaim == 1">已认领</a>
  12. <a style="color: #409eff; cursor: pointer" @click="clickRecord(item)" v-else>部分认领</a>
  13. </div>
  14. </template>
  15. </byTable>
  16. <el-dialog title="认领" v-if="dialogVisible" v-model="dialogVisible" width="50%" v-loading="loading">
  17. <byForm :formConfig="formConfig" :formOption="formOption" v-model="formData.data" :rules="rules" ref="byform">
  18. <template #detail>
  19. <div style="width: 100%">
  20. <el-button type="primary" style="margin-bottom: 10px" @click="dialogVisibleOne = true">选择合同</el-button>
  21. <el-table :data="formData.data.claimContractList">
  22. <el-table-column prop="contractCode" label="合同编码" width="140" />
  23. <el-table-column label="合同金额" width="140">
  24. <template #default="{ row, $index }">
  25. {{ row.currency }}{{ moneyFormat(row.contractTotal, 2) }}
  26. </template>
  27. </el-table-column>
  28. <el-table-column prop="sumContractNotClaimMoney" label="未结清金额" width="100" />
  29. <el-table-column prop="money" label="关联金额" min-width="150">
  30. <template #default="{ row, $index }">
  31. <el-form-item :prop="'claimContractList.' + $index + '.money'" :rules="rules.money" :inline-message="true">
  32. <el-input-number v-model="row.money" :precision="2" :controls="false" :min="0" onmousewheel="return false;" />
  33. </el-form-item>
  34. </template>
  35. </el-table-column>
  36. <el-table-column prop="claimType" label="到账类型" min-width="150">
  37. <template #default="{ row, $index }">
  38. <el-form-item :prop="'claimContractList.' + $index + '.claimType'" :rules="rules.claimType" :inline-message="true">
  39. <el-select v-model="row.claimType" style="width: 100%">
  40. <el-option v-for="item in claimTypeList" :key="item.value" :label="item.label" :value="item.value" />
  41. </el-select>
  42. </el-form-item>
  43. </template>
  44. </el-table-column>
  45. <el-table-column prop="contractMoney" label="换算金额" min-width="150">
  46. <template #default="{ row, $index }">
  47. <el-form-item :prop="'claimContractList.' + $index + '.contractMoney'" :rules="rules.contractMoney" :inline-message="true">
  48. <el-input-number v-model="row.contractMoney" :precision="2" :controls="false" :min="0" onmousewheel="return false;" />
  49. </el-form-item>
  50. </template>
  51. </el-table-column>
  52. <el-table-column prop="zip" label="操作" width="60" align="center">
  53. <template #default="{ $index }">
  54. <el-button type="primary" link @click="handleRemove($index)">删除</el-button>
  55. </template>
  56. </el-table-column>
  57. </el-table>
  58. </div>
  59. </template>
  60. <template #fileSlot>
  61. <div>
  62. <el-upload v-model:fileList="fileList" :show-file-list="false" class="upload-demo" :action="uploadUrl" :data="uploadData"
  63. :on-preview="handlePreview" :on-remove="handleRemove" :on-success="handleSuccess" :before-upload="handleBeforeUpload">
  64. <el-button type="primary">选择</el-button>
  65. </el-upload>
  66. <div>
  67. <div style="margin-top: 15px">
  68. <el-tag style="margin-right: 10px" class="ml-2" type="info" v-for="(item, index) in fileListCopy" :key="index" closable
  69. @close="handleClose(index)">
  70. {{ item.fileName }}
  71. </el-tag>
  72. </div>
  73. </div>
  74. </div>
  75. </template>
  76. </byForm>
  77. <template #footer>
  78. <el-button @click="dialogVisible = false" size="default">取 消</el-button>
  79. <el-button type="primary" @click="submitForm('byform')" size="default" :loading="submitLoading">
  80. 确 定
  81. </el-button>
  82. </template>
  83. </el-dialog>
  84. <el-dialog title="合同选择" v-if="dialogVisibleOne" v-model="dialogVisibleOne" width="80%" v-loading="loading" destroy-on-close>
  85. <ContractSelect @handleSelectContrct="handleSelectContrct"></ContractSelect>
  86. </el-dialog>
  87. <el-dialog title="认领记录" v-if="openRecord" v-model="openRecord" width="500">
  88. <byForm :formConfig="formRecordConfig" :formOption="formOption" v-model="rowData.data">
  89. <template #recordList>
  90. <div>
  91. <div style="width: 100%" v-if="
  92. rowData.data.recordList && rowData.data.recordList.length > 0
  93. ">
  94. <div v-for="(item, index) in rowData.data.recordList" :key="index">
  95. <div style="color: #ccc">{{ item.createTime }}</div>
  96. <div>认领人: {{ item.claimUserName }}</div>
  97. <div>合同编号: {{ item.contractCode }}</div>
  98. <div>认领金额: {{ item.currency }}{{ item.money }}</div>
  99. <br />
  100. </div>
  101. </div>
  102. <div v-else>无</div>
  103. </div>
  104. </template>
  105. </byForm>
  106. <template #footer>
  107. <el-button @click="openRecord = false" size="default">取 消</el-button>
  108. </template>
  109. </el-dialog>
  110. </div>
  111. </template>
  112. <script setup>
  113. import { ElMessage, ElMessageBox } from "element-plus";
  114. import byTable from "@/components/byTable/index";
  115. import byForm from "@/components/byForm/index";
  116. import { computed, ref } from "vue";
  117. import useUserStore from "@/store/modules/user";
  118. import ContractSelect from "@/views/salesMange/saleContract/contractSelect/index";
  119. const { proxy } = getCurrentInstance();
  120. const uploadData = ref({});
  121. let fileList = ref([]);
  122. let fileListCopy = ref([]);
  123. const loading = ref(false);
  124. const submitLoading = ref(false);
  125. const sourceList = ref({
  126. data: [],
  127. pagination: {
  128. total: 3,
  129. pageNum: 1,
  130. pageSize: 10,
  131. type: 1,
  132. dataType: "1",
  133. },
  134. });
  135. let dialogVisible = ref(false);
  136. let dialogVisibleOne = ref(false);
  137. let modalType = ref("add");
  138. let rules = ref({
  139. money: [{ required: true, message: "请输入关联金额", trigger: "blur" }],
  140. claimType: [{ required: true, message: "请选择到账类型", trigger: "change" }],
  141. moneyCny: [{ required: true, message: "请输入换算 CNY", trigger: "blur" }],
  142. contractMoney: [
  143. { required: true, message: "请输入换算金额", trigger: "blur" },
  144. ],
  145. });
  146. const claim = ref([
  147. {
  148. label: "未认领",
  149. value: "0",
  150. },
  151. {
  152. label: "已认领",
  153. value: "1",
  154. },
  155. {
  156. label: "部分认领",
  157. value: "2",
  158. },
  159. ]);
  160. const claimTypeList = ref([]);
  161. const accountList = ref([]);
  162. const selectConfig = computed(() => [
  163. {
  164. label: "认领状态",
  165. prop: "isClaim",
  166. data: claim.value,
  167. },
  168. {
  169. label: "账户名称",
  170. prop: "accountManagementId",
  171. data: accountList.value,
  172. },
  173. ]);
  174. const config = computed(() => {
  175. return [
  176. {
  177. attrs: {
  178. label: "账户名称",
  179. prop: "accountManagementName",
  180. },
  181. },
  182. {
  183. attrs: {
  184. label: "到账金额",
  185. prop: "amount",
  186. slot: "money",
  187. },
  188. },
  189. {
  190. attrs: {
  191. label: "到账时间",
  192. prop: "transactionTime",
  193. },
  194. },
  195. {
  196. attrs: {
  197. label: "对方账户名称",
  198. prop: "name",
  199. },
  200. },
  201. {
  202. attrs: {
  203. label: "对方开户银行",
  204. prop: "openingBank",
  205. },
  206. },
  207. {
  208. attrs: {
  209. label: "对方账号",
  210. prop: "accountOpening",
  211. },
  212. },
  213. {
  214. attrs: {
  215. label: "摘要",
  216. prop: "remarks",
  217. },
  218. },
  219. {
  220. attrs: {
  221. label: "认领状态",
  222. slot: "isClaim",
  223. width: 120,
  224. },
  225. },
  226. {
  227. attrs: {
  228. label: "操作",
  229. width: "140",
  230. align: "right",
  231. },
  232. renderHTML(row) {
  233. return [
  234. row.isClaim != 1
  235. ? {
  236. attrs: {
  237. label: "认领",
  238. type: "primary",
  239. text: true,
  240. bg: true,
  241. disabled: false,
  242. },
  243. el: "button",
  244. click() {
  245. getDtl(row);
  246. },
  247. }
  248. : {},
  249. row.isClaim != 0
  250. ? {
  251. attrs: {
  252. label: "取消认领",
  253. text: true,
  254. bg: true,
  255. type: "primary",
  256. disabled: false,
  257. style: {
  258. color: "#e6a23c",
  259. },
  260. },
  261. el: "button",
  262. click() {
  263. proxy.$router.replace({
  264. path: "/platform_manage/process/processApproval",
  265. query: {
  266. flowKey: "claim_del_flow",
  267. flowName: "取消认领发起",
  268. random: proxy.random(),
  269. businessId: row.id,
  270. },
  271. });
  272. // ElMessageBox.confirm("是否确定取消认领?", "提示", {
  273. // confirmButtonText: "确定",
  274. // cancelButtonText: "取消",
  275. // type: "warning",
  276. // }).then(() => {
  277. // // 删除
  278. // proxy
  279. // .post("/claim/delete", {
  280. // id: row.id,
  281. // })
  282. // .then((res) => {
  283. // ElMessage({
  284. // message: "操作成功",
  285. // type: "success",
  286. // });
  287. // getList();
  288. // });
  289. // });
  290. },
  291. }
  292. : {},
  293. ];
  294. },
  295. },
  296. ];
  297. });
  298. let formData = reactive({
  299. data: {},
  300. });
  301. const formOption = reactive({
  302. inline: true,
  303. labelWidth: 100,
  304. itemWidth: 100,
  305. rules: [],
  306. });
  307. const byform = ref(null);
  308. const formConfig = reactive([
  309. {
  310. type: "title",
  311. title: "账户信息",
  312. },
  313. {
  314. type: "select",
  315. prop: "accountManagementName",
  316. label: "选择账户",
  317. required: true,
  318. disabled: true,
  319. },
  320. {
  321. type: "title",
  322. title: "交易信息",
  323. },
  324. {
  325. type: "date",
  326. itemType: "datetime",
  327. prop: "claimTime",
  328. label: "交易时间",
  329. disabled: true,
  330. },
  331. {
  332. type: "select",
  333. prop: "status",
  334. label: "交易金额",
  335. itemWidth: 30,
  336. disabled: true,
  337. data: [
  338. {
  339. label: "收入",
  340. value: "10",
  341. },
  342. {
  343. label: "支出",
  344. value: "20",
  345. },
  346. ],
  347. },
  348. {
  349. type: "selectInput",
  350. prop: "waitAmount",
  351. selectProp: "currency",
  352. label: " ",
  353. itemWidth: 70,
  354. disabled: true,
  355. },
  356. {
  357. type: "number",
  358. prop: "amountCny",
  359. label: "汇算人民币金额",
  360. itemWidth: 30,
  361. disabled: true,
  362. precision: 2,
  363. controls: false,
  364. min: 0,
  365. style: {
  366. width: "100%",
  367. },
  368. },
  369. {
  370. type: "number",
  371. prop: "rate",
  372. label: "汇率",
  373. itemWidth: 30,
  374. disabled: true,
  375. precision: 2,
  376. controls: false,
  377. min: 0,
  378. style: {
  379. width: "100%",
  380. },
  381. },
  382. {
  383. type: "title",
  384. title: "认领信息",
  385. },
  386. {
  387. type: "slot",
  388. slotName: "detail",
  389. label: "",
  390. },
  391. {
  392. type: "slot",
  393. slotName: "fileSlot",
  394. label: "上传附件",
  395. },
  396. ]);
  397. const getList = async (req) => {
  398. sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
  399. loading.value = true;
  400. proxy
  401. .post("/sale/accountRunningWater/page", sourceList.value.pagination)
  402. .then((message) => {
  403. sourceList.value.data = message.rows;
  404. sourceList.value.pagination.total = message.total;
  405. setTimeout(() => {
  406. loading.value = false;
  407. }, 200);
  408. });
  409. };
  410. const submitForm = () => {
  411. byform.value.handleSubmit((valid) => {
  412. const list = formData.data.claimContractList;
  413. if (!(list.length > 0)) {
  414. return ElMessage({
  415. message: `请添加认领信息!`,
  416. type: "info",
  417. });
  418. }
  419. for (let i = 0; i < list.length; i++) {
  420. const e = list[i];
  421. if (!(e.money > 0)) {
  422. return ElMessage({
  423. message: "关联金额不能为0!",
  424. type: "info",
  425. });
  426. }
  427. // if (!(e.moneyCny > 0)) {
  428. // return ElMessage({
  429. // message: "换算CNY不能为0!",
  430. // type: "info",
  431. // });
  432. // }
  433. }
  434. const total = list.reduce((total, x) => (total += Number(x.money)), 0);
  435. if (total > Number(formData.data.waitAmount)) {
  436. return ElMessage({
  437. message: "认领金额总合不能大于交易金额!",
  438. type: "info",
  439. });
  440. }
  441. formData.data.amount = total;
  442. formData.data.fileList =
  443. fileListCopy.value.map((x) => ({
  444. id: x.id,
  445. fileName: x.fileName,
  446. })) || [];
  447. submitLoading.value = true;
  448. proxy.post("/claim/add", formData.data).then(
  449. (res) => {
  450. ElMessage({
  451. message: "操作成功",
  452. type: "success",
  453. });
  454. dialogVisible.value = false;
  455. submitLoading.value = false;
  456. getList();
  457. },
  458. (err) => (submitLoading.value = false)
  459. );
  460. });
  461. };
  462. const rowCurrency = ref("");
  463. const rowRate = ref("");
  464. const getDtl = (row) => {
  465. rowCurrency.value = row.currency;
  466. rowRate.value = row.rate;
  467. proxy.get(`/claim/sumClaimMoney?businessId=${row.id}`).then((res) => {
  468. modalType.value = "edit";
  469. dialogVisible.value = true;
  470. formData.data = {
  471. businessId: row.id,
  472. status: row.status + "",
  473. currency: row.currency,
  474. waitAmount: Number(row.amount) - Number(res.data),
  475. accountManagementId: row.accountManagementId,
  476. accountManagementName: row.accountManagementName,
  477. claimTime: row.transactionTime,
  478. amountCny: row.amountCny,
  479. claimContractList: [],
  480. rate: rowRate.value,
  481. };
  482. dialogVisible.value = true;
  483. });
  484. };
  485. const getDict = () => {
  486. proxy
  487. .post("/accountManagement/page", { pageNum: 1, pageSize: 999 })
  488. .then((res) => {
  489. if (res.rows && res.rows.length > 0) {
  490. accountList.value = res.rows.map((item) => {
  491. return {
  492. label: item.alias,
  493. value: item.id,
  494. };
  495. });
  496. }
  497. });
  498. proxy.getDictOne(["claim_type"]).then((res) => {
  499. claimTypeList.value = res["claim_type"].map((x) => ({
  500. label: x.dictValue,
  501. value: x.dictKey,
  502. }));
  503. });
  504. };
  505. const handleBeforeUpload = async (file) => {
  506. const res = await proxy.post("/fileInfo/getSing", { fileName: file.name });
  507. uploadData.value = res.uploadBody;
  508. fileListCopy.value.push({
  509. id: res.id,
  510. fileName: res.fileName,
  511. path: res.fileUrl,
  512. url: res.fileUrl,
  513. uid: file.uid,
  514. });
  515. };
  516. const handleClose = (index) => {
  517. // if (fileListCopy.value.length === 1) {
  518. // return ElMessage({
  519. // message: "最后一个附件啦!",
  520. // type: "info",
  521. // });
  522. // }
  523. fileList.value.splice(index, 1);
  524. fileListCopy.value.splice(index, 1);
  525. };
  526. const handleRemove = (index) => {
  527. formData.data.claimContractList.splice(index, 1);
  528. return ElMessage({
  529. message: "删除成功",
  530. type: "success",
  531. });
  532. };
  533. const handleSelectContrct = (row) => {
  534. const flag = formData.data.claimContractList.some(
  535. (x) => x.contractId === row.id
  536. );
  537. if (flag)
  538. return ElMessage({
  539. message: "该合同已选择",
  540. type: "info",
  541. });
  542. formData.data.claimContractList.push({
  543. dataType: row.dataType,
  544. contractId: row.id,
  545. contractCode: row.code,
  546. money: 0,
  547. currency: row.currency,
  548. rate: rowRate.value,
  549. claimType: "",
  550. moneyCny: null,
  551. contractTotal: row.amount,
  552. sumContractNotClaimMoney: row.sumContractNotClaimMoney,
  553. contractMoney: null,
  554. });
  555. return ElMessage({
  556. message: "选择成功",
  557. type: "success",
  558. });
  559. };
  560. getList();
  561. getDict();
  562. onMounted(() => {});
  563. const openRecord = ref(false);
  564. const rowData = reactive({
  565. data: {},
  566. });
  567. const formRecordConfig = reactive([
  568. {
  569. type: "title",
  570. title: "账户信息",
  571. label: "",
  572. },
  573. {
  574. type: "select",
  575. prop: "accountManagementName",
  576. label: "选择账户",
  577. required: true,
  578. disabled: true,
  579. },
  580. {
  581. type: "title",
  582. title: "交易信息",
  583. label: "",
  584. },
  585. {
  586. type: "date",
  587. itemType: "datetime",
  588. prop: "claimTime",
  589. label: "交易时间",
  590. disabled: true,
  591. },
  592. {
  593. type: "select",
  594. prop: "status",
  595. label: "交易金额",
  596. itemWidth: 30,
  597. disabled: true,
  598. data: [
  599. {
  600. label: "收入",
  601. value: "10",
  602. },
  603. {
  604. label: "支出",
  605. value: "20",
  606. },
  607. ],
  608. },
  609. {
  610. type: "selectInput",
  611. prop: "waitAmount",
  612. selectProp: "currency",
  613. label: " ",
  614. itemWidth: 70,
  615. disabled: true,
  616. },
  617. {
  618. type: "slot",
  619. slotName: "recordList",
  620. label: "认领记录",
  621. },
  622. ]);
  623. const clickRecord = (row) => {
  624. rowData.data = {
  625. businessId: row.id,
  626. status: row.status + "",
  627. currency: row.currency,
  628. waitAmount: Number(row.amount),
  629. accountManagementId: row.accountManagementId,
  630. accountManagementName: row.accountManagementName,
  631. claimTime: row.transactionTime,
  632. recordList: [],
  633. };
  634. openRecord.value = true;
  635. proxy.post("/claim/claimRecord", { businessId: row.id }).then((res) => {
  636. rowData.data.recordList = res;
  637. });
  638. };
  639. </script>
  640. <style lang="scss" scoped>
  641. .tenant {
  642. padding: 20px;
  643. }
  644. ::v-deep(.el-input-number .el-input__inner) {
  645. text-align: left;
  646. }
  647. </style>