index.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. <template>
  2. <div class="tenant">
  3. <div class="content">
  4. <byTable
  5. :source="sourceList.data"
  6. :pagination="sourceList.pagination"
  7. :config="config"
  8. :loading="loading"
  9. highlight-current-row
  10. :selectConfig="selectConfig"
  11. :action-list="[
  12. {
  13. text: '发起请款',
  14. action: () => openModal(),
  15. },
  16. ]"
  17. @moreSearch="moreSearch"
  18. @get-list="getList">
  19. <template #total="{ item }">
  20. <div style="width: 100%">
  21. <a style="color: #409eff; cursor: pointer" @click="pushProcessApproval(item)">{{ item.currency }}{{ item.total }}</a>
  22. </div>
  23. </template>
  24. <template #type="{ item }">
  25. <div style="width: 100%">
  26. <span>
  27. {{ dictValueLabel(item.type, fundsType) }}
  28. </span>
  29. <span v-if="item.type == 1">(<span v-if="item.writeOffStatus == 0">未核销</span><span v-if="item.writeOffStatus == 1">已核销</span>)</span>
  30. </div>
  31. </template>
  32. </byTable>
  33. </div>
  34. <el-dialog title="打印" v-if="openPrint" v-model="openPrint" width="640px">
  35. <div id="printMe">
  36. <FundsPDF :rowData="rowData"></FundsPDF>
  37. </div>
  38. <template #footer>
  39. <el-button @click="openPrint = false" size="large">取消</el-button>
  40. <el-button v-print="printObj" size="large">打印</el-button>
  41. <el-button type="primary" @click="clickDownload()" size="large">下载PDF</el-button>
  42. </template>
  43. </el-dialog>
  44. <el-dialog title="高级检索" v-if="openSearch" v-model="openSearch" width="600" :before-close="cancelSearch">
  45. <byForm :formConfig="formSearchConfig" :formOption="formOption" v-model="sourceList.pagination">
  46. <template #departmentId>
  47. <div>
  48. <el-tree-select
  49. v-model="sourceList.pagination.departmentId"
  50. :data="deptTreeData"
  51. check-strictly
  52. :render-after-expand="false"
  53. node-key="deptId"
  54. style="width: 100%"
  55. :props="defaultProps"
  56. clearable />
  57. </div>
  58. </template>
  59. <template #time>
  60. <div style="width: 100%">
  61. <el-row :gutter="10">
  62. <el-col :span="11">
  63. <el-date-picker
  64. v-model="sourceList.pagination.beginTime"
  65. type="datetime"
  66. placeholder="请选择"
  67. style="width: 100%"
  68. value-format="YYYY-MM-DD HH:mm:ss" />
  69. </el-col>
  70. <el-col :span="2" style="text-align: center">到</el-col>
  71. <el-col :span="11">
  72. <el-date-picker
  73. v-model="sourceList.pagination.endTime"
  74. type="datetime"
  75. placeholder="请选择"
  76. style="width: 100%"
  77. value-format="YYYY-MM-DD HH:mm:ss" />
  78. </el-col>
  79. </el-row>
  80. </div>
  81. </template>
  82. <template #money>
  83. <div style="width: 100%">
  84. <el-row :gutter="10">
  85. <el-col :span="11">
  86. <el-input-number
  87. onmousewheel="return false;"
  88. v-model="sourceList.pagination.minAdvanceAmounts"
  89. placeholder="请输入"
  90. style="width: 100%"
  91. :precision="2"
  92. :controls="false"
  93. :min="0" />
  94. </el-col>
  95. <el-col :span="2" style="text-align: center">到</el-col>
  96. <el-col :span="11">
  97. <el-input-number
  98. onmousewheel="return false;"
  99. v-model="sourceList.pagination.maxAdvanceAmounts"
  100. placeholder="请输入"
  101. style="width: 100%"
  102. :precision="2"
  103. :controls="false"
  104. :min="0" />
  105. </el-col>
  106. </el-row>
  107. </div>
  108. </template>
  109. </byForm>
  110. <template #footer>
  111. <el-button @click="cancelSearch()" size="large">取 消</el-button>
  112. <el-button type="primary" @click="submitSearch()" size="large">确 定</el-button>
  113. </template>
  114. </el-dialog>
  115. </div>
  116. </template>
  117. <script setup>
  118. import byTable from "@/components/byTable/index";
  119. import useUserStore from "@/store/modules/user";
  120. import { ref } from "vue";
  121. import byForm from "@/components/byForm/index";
  122. import FundsPDF from "@/components/PDF/fundsPDF.vue";
  123. const loading = ref(false);
  124. const sourceList = ref({
  125. data: [],
  126. pagination: {
  127. total: 0,
  128. pageNum: 1,
  129. pageSize: 10,
  130. type: "",
  131. keyword: "",
  132. writeOffStatus: "",
  133. corporationId: "",
  134. departmentId: "",
  135. createUser: "",
  136. currency: "",
  137. beginTime: "",
  138. endTime: "",
  139. minAdvanceAmounts: undefined,
  140. maxAdvanceAmounts: undefined,
  141. paymentRemarks: "",
  142. paymentMethod: "",
  143. status: "",
  144. paymentStatus: "",
  145. },
  146. });
  147. const { proxy } = getCurrentInstance();
  148. const fundsType = ref([]);
  149. const userList = ref([]);
  150. const companyData = ref([]);
  151. const accountCurrency = ref([]);
  152. const fundsPaymentMethod = ref([]);
  153. const deptTreeData = ref([]);
  154. const status = ref([
  155. {
  156. label: "审批中",
  157. value: "10",
  158. },
  159. {
  160. label: "驳回",
  161. value: "20",
  162. },
  163. {
  164. label: "审批通过",
  165. value: "30",
  166. },
  167. ]);
  168. const paymentStatus = ref([
  169. {
  170. label: "已打款",
  171. value: "10",
  172. },
  173. {
  174. label: "未打款",
  175. value: "20",
  176. },
  177. ]);
  178. const selectConfig = computed(() => {
  179. return [
  180. {
  181. label: "类型",
  182. prop: "type",
  183. data: fundsType.value,
  184. },
  185. {
  186. label: "审批状态",
  187. prop: "status",
  188. data: status.value,
  189. },
  190. {
  191. label: "放款状态",
  192. prop: "paymentStatus",
  193. data: paymentStatus.value,
  194. },
  195. ];
  196. });
  197. const config = computed(() => {
  198. return [
  199. {
  200. attrs: {
  201. label: "归属公司",
  202. prop: "corporationName",
  203. width: 180,
  204. },
  205. },
  206. {
  207. attrs: {
  208. label: "归属部门",
  209. prop: "deptName",
  210. width: 140,
  211. },
  212. },
  213. {
  214. attrs: {
  215. label: "请款类型",
  216. prop: "type",
  217. width: 130,
  218. slot: "type",
  219. },
  220. },
  221. {
  222. attrs: {
  223. label: "请款人",
  224. prop: "userName",
  225. width: 120,
  226. },
  227. },
  228. {
  229. attrs: {
  230. label: "请款时间",
  231. prop: "createTime",
  232. width: 160,
  233. },
  234. },
  235. {
  236. attrs: {
  237. label: "请款金额",
  238. slot: "total",
  239. width: 120,
  240. },
  241. },
  242. {
  243. attrs: {
  244. label: "用款说明",
  245. prop: "paymentRemarks",
  246. "min-width": 180,
  247. },
  248. },
  249. {
  250. attrs: {
  251. label: "付款方式",
  252. prop: "paymentMethod",
  253. width: 120,
  254. },
  255. render(paymentMethod) {
  256. return proxy.dictValueLabel(paymentMethod, fundsPaymentMethod.value);
  257. },
  258. },
  259. {
  260. attrs: {
  261. label: "付款账户",
  262. prop: "accountManagementName",
  263. width: 160,
  264. },
  265. },
  266. {
  267. attrs: {
  268. label: "审批状态",
  269. prop: "status",
  270. width: 120,
  271. },
  272. render(status) {
  273. return status == 10 ? "审批中" : status == 20 ? "驳回" : status == 30 ? "审批通过" : "";
  274. },
  275. },
  276. {
  277. attrs: {
  278. label: "放款状态",
  279. prop: "accountPaymentStatus",
  280. width: 120,
  281. },
  282. render(status) {
  283. return proxy.dictValueLabel(status, paymentStatus.value);
  284. },
  285. },
  286. {
  287. attrs: {
  288. label: "操作",
  289. width: "120",
  290. align: "center",
  291. fixed: "right",
  292. },
  293. renderHTML(row) {
  294. return [
  295. row.type == 1 && row.writeOffStatus == 0 && row.status == "30"
  296. ? {
  297. attrs: {
  298. label: "核销",
  299. type: "primary",
  300. text: true,
  301. },
  302. el: "button",
  303. click() {
  304. openModal(row);
  305. },
  306. }
  307. : {},
  308. {
  309. attrs: {
  310. label: "打印",
  311. type: "primary",
  312. text: true,
  313. },
  314. el: "button",
  315. click() {
  316. clickPrint(row);
  317. },
  318. },
  319. ];
  320. },
  321. },
  322. ];
  323. });
  324. const getList = async (req) => {
  325. sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
  326. loading.value = true;
  327. proxy.post("/accountRequestFunds/page", sourceList.value.pagination).then((message) => {
  328. sourceList.value.data = message.rows;
  329. sourceList.value.pagination.total = message.total;
  330. setTimeout(() => {
  331. loading.value = false;
  332. }, 200);
  333. });
  334. };
  335. const openModal = (row = {}) => {
  336. const flowName = `${userInfo.nickName}的请款申请(发起)`;
  337. let query = {
  338. flowKey: "account_request_funds_flow",
  339. random: proxy.random(),
  340. flowName,
  341. };
  342. if (row.id) {
  343. query.advanceId = row.id;
  344. query.corporationId = row.corporationId;
  345. }
  346. proxy.$router.replace({
  347. path: "/platform_manage/process/processApproval",
  348. query,
  349. });
  350. };
  351. const userInfo = useUserStore().user;
  352. const recursive = (data) => {
  353. data.map((item) => {
  354. item.label = item.deptName;
  355. item.id = item.corporationId;
  356. if (item.children) {
  357. recursive(item.children);
  358. } else {
  359. item.children = [];
  360. }
  361. });
  362. };
  363. const getDictData = () => {
  364. proxy.getDictOne(["founds_type", "funds_payment_method", "account_currency"]).then((res) => {
  365. fundsType.value = res["founds_type"].map((x) => ({
  366. label: x.dictValue,
  367. value: x.dictKey,
  368. }));
  369. fundsPaymentMethod.value = res["funds_payment_method"].map((x) => ({
  370. label: x.dictValue,
  371. value: x.dictKey,
  372. }));
  373. accountCurrency.value = res["account_currency"].map((x) => ({
  374. label: x.dictValue,
  375. value: x.dictKey,
  376. }));
  377. });
  378. proxy
  379. .get("/tenantUser/list", {
  380. pageNum: 1,
  381. pageSize: 10000,
  382. tenantId: useUserStore().user.tenantId,
  383. })
  384. .then((res) => {
  385. if (res.rows && res.rows.length > 0) {
  386. userList.value = res.rows.map((item) => {
  387. return {
  388. deptId: item.deptId,
  389. label: item.nickName,
  390. value: item.userId,
  391. };
  392. });
  393. }
  394. });
  395. proxy.post("/corporation/page", { pageNum: 1, pageSize: 9999 }).then((res) => {
  396. if (res.rows && res.rows.length > 0) {
  397. companyData.value = res.rows.map((item) => {
  398. return {
  399. label: item.name,
  400. value: item.id,
  401. };
  402. });
  403. }
  404. });
  405. proxy
  406. .get("/tenantDept/list", {
  407. pageNum: 1,
  408. pageSize: 9999,
  409. tenantId: userInfo.tenantId,
  410. })
  411. .then((message) => {
  412. recursive(message.data);
  413. deptTreeData.value = [];
  414. let data = proxy.handleTree(message.data, "deptId");
  415. if (data && data.length > 0) {
  416. for (let i = 0; i < data.length; i++) {
  417. if (data[i].children && data[i].children.length > 0) {
  418. deptTreeData.value = deptTreeData.value.concat(data[i].children);
  419. }
  420. }
  421. }
  422. });
  423. };
  424. getDictData();
  425. getList();
  426. const openPrint = ref(false);
  427. const rowData = ref({});
  428. const clickPrint = (row) => {
  429. rowData.value = row;
  430. openPrint.value = true;
  431. };
  432. const clickDownload = () => {
  433. proxy.getPdf("请款PDF文件");
  434. };
  435. const formOption = reactive({
  436. inline: true,
  437. labelWidth: 100,
  438. itemWidth: 100,
  439. rules: [],
  440. });
  441. const defaultProps = {
  442. children: "children",
  443. label: "deptName",
  444. };
  445. const openSearch = ref(false);
  446. const formSearchConfig = computed(() => {
  447. return [
  448. {
  449. type: "select",
  450. prop: "corporationId",
  451. label: "归属公司",
  452. data: companyData.value,
  453. clearable: true,
  454. },
  455. {
  456. type: "slot",
  457. slotName: "departmentId",
  458. label: "归属部门",
  459. itemWidth: 50,
  460. },
  461. {
  462. type: "select",
  463. prop: "createUser",
  464. label: "请款人",
  465. data: userList.value,
  466. itemWidth: 50,
  467. clearable: true,
  468. },
  469. {
  470. type: "select",
  471. prop: "type",
  472. label: "请款类型",
  473. data: fundsType.value,
  474. clearable: true,
  475. },
  476. {
  477. type: "select",
  478. prop: "currency",
  479. label: "币种",
  480. data: accountCurrency.value,
  481. clearable: true,
  482. },
  483. {
  484. type: "slot",
  485. slotName: "time",
  486. label: "请款时间",
  487. },
  488. {
  489. type: "slot",
  490. slotName: "money",
  491. label: "请款金额",
  492. },
  493. {
  494. type: "input",
  495. itemType: "textarea",
  496. prop: "paymentRemarks",
  497. label: "用款说明",
  498. },
  499. {
  500. type: "select",
  501. prop: "paymentMethod",
  502. label: "付款方式",
  503. data: fundsPaymentMethod.value,
  504. clearable: true,
  505. },
  506. {
  507. type: "select",
  508. prop: "status",
  509. label: "流程状态",
  510. data: status.value,
  511. itemWidth: 50,
  512. clearable: true,
  513. },
  514. {
  515. type: "select",
  516. prop: "paymentStatus",
  517. label: "打款状态",
  518. data: paymentStatus.value,
  519. itemWidth: 50,
  520. clearable: true,
  521. },
  522. ];
  523. });
  524. let copySearch = ref({});
  525. const moreSearch = () => {
  526. copySearch.value = proxy.deepClone(sourceList.value.pagination);
  527. openSearch.value = true;
  528. };
  529. const cancelSearch = () => {
  530. sourceList.value.pagination = copySearch.value;
  531. openSearch.value = false;
  532. };
  533. const submitSearch = () => {
  534. if (
  535. sourceList.value.pagination.minAdvanceAmounts &&
  536. sourceList.value.pagination.maxAdvanceAmounts &&
  537. Number(sourceList.value.pagination.minAdvanceAmounts) > Number(sourceList.value.pagination.maxAdvanceAmounts)
  538. ) {
  539. return ElMessage("交易金额输入错误");
  540. }
  541. if (
  542. sourceList.value.pagination.beginTime &&
  543. sourceList.value.pagination.endTime &&
  544. sourceList.value.pagination.beginTime > sourceList.value.pagination.endTime
  545. ) {
  546. return ElMessage("开始时间不能大于结束时间");
  547. }
  548. openSearch.value = false;
  549. sourceList.value.pagination.keyword = "";
  550. sourceList.value.pagination.pageNum = 1;
  551. getList();
  552. };
  553. const pushProcessApproval = (row) => {
  554. proxy.$router.push({
  555. path: "/platform_manage/process/processApproval",
  556. query: {
  557. flowKey: "account_request_funds_flow",
  558. id: row.flowInfoId,
  559. processType: 20,
  560. random: proxy.random(),
  561. flowName: "请款详情",
  562. },
  563. });
  564. return;
  565. };
  566. const printObj = ref({
  567. id: "printMe",
  568. popTitle: "",
  569. extraCss: "https://cdn.bootcdn.net/ajax/libs/animate.css/4.1.1/animate.compat.css, https://cdn.bootcdn.net/ajax/libs/hover.css/2.3.1/css/hover-min.css",
  570. extraHead: '<meta http-equiv="Content-Language"content="zh-cn"/>',
  571. });
  572. </script>
  573. <style lang="scss" scoped>
  574. .tenant {
  575. padding: 20px;
  576. }
  577. ::v-deep(.el-input-number .el-input__inner) {
  578. text-align: left;
  579. }
  580. </style>