Commit 3123f5a8c208f5678bed015a0877c5fe3b36deea
1 parent
a8280c01
修改最后一批bug
Showing
20 changed files
with
716 additions
and
239 deletions
.env.development
.env.production
.env.test
src/api/project/invoice.ts
1 | +import { useOrderStoreWithOut } from '/@/store/modules/order'; | |
1 | 2 | import { defHttp } from '/@/utils/http/axios'; |
2 | 3 | |
3 | 4 | enum Api { |
... | ... | @@ -12,6 +13,8 @@ enum Api { |
12 | 13 | INVOICE_DELETE = '/order/erp/invoice_bill/delete_by_id', //删除数据 |
13 | 14 | COMMIT = '/order/erp/invoice_bill/commit_apply', //提交审核 |
14 | 15 | GETINVOICEDEDUCTURL_BY_ID = '/order/erp/invoice_bill/getDeductUrl_by_id', //获取扣款信息 |
16 | + REUPLOADBGURL = '/order/erp/invoice_bill/reUploadBgUrl', //更新报关单 | |
17 | + INVOICEEXPORTRECEIPT = '/order/erp/invoice_bill/exportReceipt', //收款单导出 | |
15 | 18 | |
16 | 19 | PRODUCT_CREATE = '/order/erp/check_bill/create', //创建生产科应付单据 |
17 | 20 | PAYED_DATE = '/order/erp/check_bill/get_payed_date', //获取生产科应回款日期 |
... | ... | @@ -26,6 +29,7 @@ enum Api { |
26 | 29 | EXPORT_CHECK_ANALYSIS = '/order/erp/check_bill/export', //导出分析列表 |
27 | 30 | GETDEDUCTURL_BY_ID = '/order/erp/check_bill/getDeductUrl_by_id', //获取扣款信息 |
28 | 31 | GETINVOICEURL_BY_ID = '/order/erp/check_bill/getInvoiceUrl_by_id', //获取扣款信息 |
32 | + EXPORTRECEIPT = '/order/erp/check_bill/exportReceipt', //付款单导出 | |
29 | 33 | } |
30 | 34 | |
31 | 35 | export const getRefundDate = async (params: any, data?: any) => { |
... | ... | @@ -48,7 +52,14 @@ export const getInvoice = async (params: any) => { |
48 | 52 | url: Api.INVOICE, |
49 | 53 | params, |
50 | 54 | }); |
51 | - return res.records; | |
55 | + const orderStore = useOrderStoreWithOut(); | |
56 | + orderStore.setTotal(res.total); | |
57 | + return new Promise((resolve) => { | |
58 | + resolve({ | |
59 | + items: res.records, | |
60 | + total: res.total, | |
61 | + }); | |
62 | + }); | |
52 | 63 | }; |
53 | 64 | export const getBaseInvoice = async (params: any) => { |
54 | 65 | const res = await defHttp.post<any>({ |
... | ... | @@ -137,8 +148,15 @@ export const getCheck = async (params: any) => { |
137 | 148 | url: Api.CHECK_BILL, |
138 | 149 | params, |
139 | 150 | }); |
140 | - console.log(res, '5656check'); | |
141 | - return res.records; | |
151 | + const orderStore = useOrderStoreWithOut(); | |
152 | + orderStore.setTotal(res.total); | |
153 | + // return res.records; | |
154 | + return new Promise((resolve) => { | |
155 | + resolve({ | |
156 | + items: res.records, | |
157 | + total: res.total, | |
158 | + }); | |
159 | + }); | |
142 | 160 | }; |
143 | 161 | export const checkDetail = async (params: any) => { |
144 | 162 | return await defHttp.post<any>({ |
... | ... | @@ -185,3 +203,24 @@ export const getInvoiceUrlById = async (params: any) => { |
185 | 203 | params, |
186 | 204 | }); |
187 | 205 | }; |
206 | + | |
207 | +export const reUploadBgUrl = async (params: any) => { | |
208 | + return await defHttp.post<any>({ | |
209 | + url: Api.REUPLOADBGURL, | |
210 | + params, | |
211 | + }); | |
212 | +}; | |
213 | + | |
214 | +export const getExportReceipt = async (params: any) => { | |
215 | + return await defHttp.post<any>({ | |
216 | + url: Api.EXPORTRECEIPT, | |
217 | + params, | |
218 | + }); | |
219 | +}; | |
220 | + | |
221 | +export const getInvoiceExportReceipt = async (params: any) => { | |
222 | + return await defHttp.post<any>({ | |
223 | + url: Api.INVOICEEXPORTRECEIPT, | |
224 | + params, | |
225 | + }); | |
226 | +}; | ... | ... |
src/utils/pdfShow.ts
0 → 100644
1 | +import { getAppEnvConfig } from '/@/utils/env'; | |
2 | + | |
3 | +export async function downloadAndPreviewPDF(url) { | |
4 | + try { | |
5 | + // 使用 fetch 下载 PDF 数据 | |
6 | + const response = await fetch(url); | |
7 | + if (!response.ok) throw new Error('PDF 下载失败'); | |
8 | + | |
9 | + // 转换为 Blob | |
10 | + const pdfBlob = await response.blob(); | |
11 | + | |
12 | + // 创建 Blob URL | |
13 | + const blobUrl = URL.createObjectURL(pdfBlob); | |
14 | + | |
15 | + // 创建一个新窗口或iframe来预览 PDF | |
16 | + const pdfWindow = window.open(blobUrl, '_blank'); | |
17 | + if (!pdfWindow) { | |
18 | + console.error('弹出窗口被阻止,无法预览 PDF'); | |
19 | + } | |
20 | + | |
21 | + // 可以在不需要时释放 Blob URL | |
22 | + pdfWindow.onunload = () => URL.revokeObjectURL(blobUrl); | |
23 | + } catch (error) { | |
24 | + console.error('出现错误:', error); | |
25 | + } | |
26 | +} | |
27 | +export const view = (url) => { | |
28 | + const { VITE_ALIYUN_OSS_DOMAIN } = getAppEnvConfig(); | |
29 | + if (url) { | |
30 | + url = url.replace('https://test-alterego.oss-cn-qingdao.aliyuncs.com', '/aliyun-oss-pdf'); | |
31 | + } | |
32 | + downloadAndPreviewPDF(url); | |
33 | +}; | ... | ... |
src/views/project/approve/PayPanel.vue
... | ... | @@ -15,7 +15,7 @@ |
15 | 15 | v-if="!isApproved" |
16 | 16 | :actions="[ |
17 | 17 | { |
18 | - label: '编辑', | |
18 | + label: '审核', | |
19 | 19 | // icon: 'ic:outline-delete-outline', |
20 | 20 | onClick: handleDetail.bind(null, record), |
21 | 21 | }, |
... | ... | @@ -41,12 +41,13 @@ |
41 | 41 | @register="registerModal" |
42 | 42 | title="申请信息" |
43 | 43 | okText="通过" |
44 | + width="900px" | |
44 | 45 | @ok="handleTrue" |
45 | 46 | @visible-change="handleShow" |
46 | 47 | :showCancelBtn="!isApproved && role === ROLE.ADMIN" |
47 | 48 | :showOkBtn="!isApproved && role === ROLE.ADMIN" |
48 | 49 | > |
49 | - <Description | |
50 | + <!-- <Description | |
50 | 51 | v-if="!showInvoice" |
51 | 52 | class="mt-4" |
52 | 53 | layout="vertical" |
... | ... | @@ -54,7 +55,48 @@ |
54 | 55 | :column="2" |
55 | 56 | :data="mockData" |
56 | 57 | :schema="schema" |
57 | - /> | |
58 | + /> --> | |
59 | + <table | |
60 | + v-if="!showInvoice" | |
61 | + style=" | |
62 | + width: 100%; | |
63 | + border-collapse: collapse; | |
64 | + text-align: center; | |
65 | + border: 1px solid black; | |
66 | + font-size: 16px; | |
67 | + " | |
68 | + > | |
69 | + <thead> | |
70 | + <!-- <tr> | |
71 | + <th colspan="4" style="border: 1px solid black">净利润分析表</th> | |
72 | + </tr> --> | |
73 | + </thead> | |
74 | + <tbody> | |
75 | + <tr | |
76 | + ><td colspan="7" style="text-align: center; font-weight: bold; font-size: 24px" | |
77 | + >付款单</td | |
78 | + ></tr | |
79 | + > | |
80 | + <tr> | |
81 | + <td style="border: 1px solid black; width: 14%">生产科对账单号</td> | |
82 | + <td style="border: 1px solid black; width: 14%">实际应付金额</td> | |
83 | + <td style="border: 1px solid black; width: 14%">扣款金额</td> | |
84 | + <td style="border: 1px solid black; width: 14%">实际付款金额</td> | |
85 | + <td style="border: 1px solid black; width: 14%">未付金额</td> | |
86 | + <td style="border: 1px solid black; width: 14%">必须付款日期</td> | |
87 | + <td style="border: 1px solid black; width: 14%">实际付款日期</td> | |
88 | + </tr> | |
89 | + <tr> | |
90 | + <td style="border: 1px solid black; width: 14%">{{ checkNo }}</td> | |
91 | + <td style="border: 1px solid black; width: 14%">¥{{ actualPayedAmount }}</td> | |
92 | + <td style="border: 1px solid black; width: 14%">¥{{ deductAmount }}</td> | |
93 | + <td style="border: 1px solid black; width: 14%">¥{{ totalActualPayedAmount }}</td> | |
94 | + <td style="border: 1px solid black; width: 14%">¥{{ unPayedAmount }}</td> | |
95 | + <td style="border: 1px solid black; width: 14%">{{ payedDate }}</td> | |
96 | + <td style="border: 1px solid black; width: 14%">{{ actualPayedDate }}</td> | |
97 | + </tr> | |
98 | + </tbody> | |
99 | + </table> | |
58 | 100 | <a v-if="showInvoice" @click="openPic(mockData.invoiceUrl)" rel="noopener noreferrer">{{ |
59 | 101 | mockData.invoiceName |
60 | 102 | }}</a> |
... | ... | @@ -71,6 +113,7 @@ |
71 | 113 | </a-list> --> |
72 | 114 | <template #appendFooter> |
73 | 115 | <a-button v-if="!isApproved && role === ROLE.ADMIN" @click="handleFalse"> 不通过</a-button> |
116 | + <a-button @click="handleExport"> 导出</a-button> | |
74 | 117 | </template> |
75 | 118 | </BasicModal> |
76 | 119 | <MsgModal v-if="msgVisible" @msg-modal-close="handleMsgModalClose" /> |
... | ... | @@ -80,6 +123,9 @@ |
80 | 123 | import { computed, defineComponent, ref } from 'vue'; |
81 | 124 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; |
82 | 125 | import { BasicModal, useModal } from '/@/components/Modal'; |
126 | + import { getExportReceipt } from '@/api/project/invoice'; | |
127 | + import { view } from '@/utils/pdfShow'; | |
128 | + import axios from 'axios'; | |
83 | 129 | |
84 | 130 | import { approveAuditApi, getApprovedListApi, getWaitListApi } from '/@/api/project/approve'; |
85 | 131 | import { FIELDS_BASE_INFO, FIELDS_PROFIT_INFO, FIELDS_REPORT_INFO } from '../order/tableData'; |
... | ... | @@ -122,6 +168,13 @@ |
122 | 168 | } |
123 | 169 | const itemArray = ref<Item[]>([]); |
124 | 170 | const actualPayCalculate = ref(0); |
171 | + const checkNo = ref(); | |
172 | + const actualPayedAmount = ref(); // 生产科实际应付金额汇总 | |
173 | + const payedDate = ref(); // 生产科付款日期 | |
174 | + const actualPayedDate = ref(); // 实际付款日期 | |
175 | + const unPayedAmount = ref(); // 未付金额 | |
176 | + const totalActualPayedAmount = ref(); // 实际付款金额汇总 | |
177 | + const deductAmount = ref(); // 生产科扣款金额汇总 | |
125 | 178 | const schema = [ |
126 | 179 | { |
127 | 180 | field: 'actualPayedAmount', |
... | ... | @@ -161,7 +214,6 @@ |
161 | 214 | width: 150, |
162 | 215 | customRender: (column) => { |
163 | 216 | const { record } = column || {}; |
164 | - console.log(record, '5656record'); | |
165 | 217 | if (record?.type === 40) { |
166 | 218 | return record.createBy; |
167 | 219 | } else if (record?.type == 50) { |
... | ... | @@ -270,6 +322,15 @@ |
270 | 322 | id.value = data.id; |
271 | 323 | itemArray.value = []; |
272 | 324 | mockData.value = data.fieldInfos.checkBillOrderDO; |
325 | + console.log(mockData, '5656mockdata'); | |
326 | + actualPayCalculate.value = mockData.value.actualPayCalculate; // 实际付款金额计算 | |
327 | + checkNo.value = mockData.value.checkNo; // 对账单号 | |
328 | + actualPayedAmount.value = mockData.value.actualPayedAmount; // 实际应付金额 | |
329 | + payedDate.value = mockData.value.payedDate; // 付款日期 | |
330 | + actualPayedDate.value = mockData.value.actualPayedDate; // 实际付款日期 | |
331 | + unPayedAmount.value = mockData.value.unPayedAmount; // 未付金额 | |
332 | + totalActualPayedAmount.value = mockData.value.totalActualPayedAmount; // 实际付款金额汇总 | |
333 | + deductAmount.value = mockData.value.deductAmount; // 扣款金额 | |
273 | 334 | const match = mockData.value.invoiceUrl.match(/aliyuncs\.com\/(.*?)\?/); |
274 | 335 | if (match && match[1]) { |
275 | 336 | // 对提取的部分进行解码 |
... | ... | @@ -294,6 +355,67 @@ |
294 | 355 | // reload(); |
295 | 356 | // closeModal(); |
296 | 357 | } |
358 | + async function handleExport() { | |
359 | + axios | |
360 | + .post( | |
361 | + '/basic-api/order/erp/check_bill/exportReceipt', | |
362 | + { | |
363 | + checkNo: checkNo.value, | |
364 | + actualPayedAmount: actualPayedAmount.value, | |
365 | + deductAmount: deductAmount.value, | |
366 | + totalActualPayedAmount: totalActualPayedAmount.value, | |
367 | + unPayedAmount: unPayedAmount.value, | |
368 | + payedDate: payedDate.value, | |
369 | + actualPayedDate: actualPayedDate.value, | |
370 | + }, | |
371 | + { | |
372 | + responseType: 'blob', // 设置响应类型为 'blob' | |
373 | + }, | |
374 | + ) | |
375 | + .then((response) => { | |
376 | + // 创建一个 Blob 对象来保存二进制数据 | |
377 | + const blob = new Blob([response.data], { type: 'application/octet-stream' }); | |
378 | + const getFormattedDate = (): string => { | |
379 | + const date = new Date(); | |
380 | + | |
381 | + const year = date.getFullYear(); | |
382 | + const month = String(date.getMonth() + 1).padStart(2, '0'); | |
383 | + const day = String(date.getDate()).padStart(2, '0'); | |
384 | + | |
385 | + const hours = String(date.getHours()).padStart(2, '0'); | |
386 | + const minutes = String(date.getMinutes()).padStart(2, '0'); | |
387 | + const seconds = String(date.getSeconds()).padStart(2, '0'); | |
388 | + | |
389 | + return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; | |
390 | + }; | |
391 | + const date = getFormattedDate(); | |
392 | + // 创建一个链接元素用于下载 | |
393 | + const link = document.createElement('a'); | |
394 | + link.href = window.URL.createObjectURL(blob); | |
395 | + link.download = `业务/研发净利润分析${date}.xlsx`; // 你可以为文件命名 | |
396 | + document.body.appendChild(link); | |
397 | + link.click(); // 自动点击链接,触发下载 | |
398 | + console.log(link, 5656); | |
399 | + document.body.removeChild(link); // 下载完成后移除链接 | |
400 | + }) | |
401 | + .catch((error) => { | |
402 | + console.error(error); | |
403 | + }); | |
404 | + closeModal(); | |
405 | + } | |
406 | + // async function handleExport() { | |
407 | + // const res = await getExportReceipt({ | |
408 | + // checkNo: checkNo.value, | |
409 | + // actualPayedAmount: actualPayedAmount.value, | |
410 | + // deductAmount: deductAmount.value, | |
411 | + // totalActualPayedAmount: totalActualPayedAmount.value, | |
412 | + // unPayedAmount: unPayedAmount.value, | |
413 | + // payedDate: payedDate.value, | |
414 | + // actualPayedDate: actualPayedDate.value, | |
415 | + // }); | |
416 | + // console.log(res, '5656res'); | |
417 | + // closeModal(); | |
418 | + // } | |
297 | 419 | |
298 | 420 | const role = computed(() => { |
299 | 421 | return userStore.getUserInfo?.roleSmallVO?.code; |
... | ... | @@ -314,16 +436,42 @@ |
314 | 436 | return false; |
315 | 437 | }; |
316 | 438 | |
317 | - function openPic(url) { | |
318 | - window.open('', '', '').document.write(`<!DOCTYPE html> | |
319 | - <html> | |
320 | - <body | |
321 | - style="display: flex; | |
322 | - justify-content: center; | |
323 | - align-items: center;"> | |
324 | - <img src='${url}' width="500px" height="500px"/> | |
325 | - </body> | |
326 | - </html>`); | |
439 | + // 新增的函数:判断 URL 是否为图片格式 | |
440 | + function isImageUrl(url: string): boolean { | |
441 | + const imageExtensions = ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'svg']; | |
442 | + const baseUrl = url.split('?')[0]; | |
443 | + return imageExtensions.some((ext) => baseUrl.toLowerCase().endsWith(ext)); | |
444 | + } | |
445 | + // function openPic(url) { | |
446 | + // window.open('', '', '').document.write(`<!DOCTYPE html> | |
447 | + // <html> | |
448 | + // <body | |
449 | + // style="display: flex; | |
450 | + // justify-content: center; | |
451 | + // align-items: center;"> | |
452 | + // <img src='${url}' width="500px" height="500px"/> | |
453 | + // </body> | |
454 | + // </html>`); | |
455 | + // } | |
456 | + // 检查 URL 是否为 PDF 格式 | |
457 | + function isPdfUrl(url: string): boolean { | |
458 | + return url.toLowerCase().endsWith('.pdf'); | |
459 | + } | |
460 | + // 打开图片或 PDF | |
461 | + function openPic(url: string) { | |
462 | + const baseUrl = url.split('?')[0]; // 获取问号前的部分 | |
463 | + if (isImageUrl(baseUrl)) { | |
464 | + window.open('', '', '').document.write(`<!DOCTYPE html> | |
465 | + <html> | |
466 | + <body style="display: flex; justify-content: center; align-items: center;"> | |
467 | + <img src='${url}' width="500px" height="500px"/> | |
468 | + </body> | |
469 | + </html>`); | |
470 | + } else if (isPdfUrl(baseUrl)) { | |
471 | + view(url); // 新标签页打开 PDF | |
472 | + } else { | |
473 | + console.log('不支持的文件类型'); | |
474 | + } | |
327 | 475 | } |
328 | 476 | |
329 | 477 | return { |
... | ... | @@ -350,6 +498,15 @@ |
350 | 498 | showInvoice, |
351 | 499 | openPic, |
352 | 500 | handleShow, |
501 | + actualPayCalculate, | |
502 | + checkNo, | |
503 | + actualPayedAmount, | |
504 | + payedDate, | |
505 | + actualPayedDate, | |
506 | + unPayedAmount, | |
507 | + totalActualPayedAmount, | |
508 | + deductAmount, | |
509 | + handleExport, | |
353 | 510 | }; |
354 | 511 | }, |
355 | 512 | }); | ... | ... |
src/views/project/approve/ReceivePanel.vue
... | ... | @@ -15,7 +15,7 @@ |
15 | 15 | v-if="!isApproved" |
16 | 16 | :actions="[ |
17 | 17 | { |
18 | - label: '编辑', | |
18 | + label: '审核', | |
19 | 19 | // icon: 'ic:outline-delete-outline', |
20 | 20 | onClick: handleDetail.bind(null, record), |
21 | 21 | }, |
... | ... | @@ -39,20 +39,74 @@ |
39 | 39 | @register="registerModal" |
40 | 40 | title="申请信息" |
41 | 41 | okText="通过" |
42 | + width="1000px" | |
42 | 43 | @ok="handleTrue" |
44 | + @visible-change="handleShow" | |
43 | 45 | :showCancelBtn="!isApproved && role === ROLE.ADMIN" |
44 | 46 | :showOkBtn="!isApproved && role === ROLE.ADMIN" |
45 | 47 | > |
46 | - <Description | |
48 | + <!-- <Description | |
47 | 49 | class="mt-4" |
48 | 50 | layout="vertical" |
49 | 51 | :collapseOptions="{ canExpand: true, helpMessage: 'help me' }" |
50 | 52 | :column="2" |
51 | 53 | :data="mockData" |
52 | 54 | :schema="schema" |
53 | - /> | |
55 | + /> --> | |
56 | + <table | |
57 | + v-if="!showInvoice" | |
58 | + style=" | |
59 | + width: 100%; | |
60 | + border-collapse: collapse; | |
61 | + text-align: center; | |
62 | + border: 1px solid black; | |
63 | + font-size: 16px; | |
64 | + " | |
65 | + > | |
66 | + <thead> | |
67 | + <!-- <tr> | |
68 | + <th colspan="4" style="border: 1px solid black">净利润分析表</th> | |
69 | + </tr> --> | |
70 | + </thead> | |
71 | + <tbody> | |
72 | + <tr | |
73 | + ><td colspan="7" style="text-align: center; font-weight: bold; font-size: 24px" | |
74 | + >收款单</td | |
75 | + ></tr | |
76 | + > | |
77 | + <tr> | |
78 | + <td style="border: 1px solid black; width: 14%">Invoice编号</td> | |
79 | + <td style="border: 1px solid black; width: 14%">实际收款金额汇总</td> | |
80 | + <td style="border: 1px solid black; width: 14%">客户总价金额汇总</td> | |
81 | + <td style="border: 1px solid black; width: 14%">发生扣款金额汇总</td> | |
82 | + <td style="border: 1px solid black; width: 14%">必须回款日期</td> | |
83 | + <td style="border: 1px solid black; width: 14%">实际回款日期</td> | |
84 | + <td style="border: 1px solid black; width: 14%">其他费用汇总</td> | |
85 | + </tr> | |
86 | + <tr> | |
87 | + <td style="border: 1px solid black; width: 14%">{{ invoiceNo }}</td> | |
88 | + <td style="border: 1px solid black; width: 14%">${{ totalPayAmount }}</td> | |
89 | + <td style="border: 1px solid black; width: 14%">${{ totalCustomerAmount }}</td> | |
90 | + <td style="border: 1px solid black; width: 14%">${{ deductAmount }}</td> | |
91 | + <td style="border: 1px solid black; width: 14%">{{ backRefundDate }}</td> | |
92 | + <td style="border: 1px solid black; width: 14%">{{ actualRefundDate }}</td> | |
93 | + <td style="border: 1px solid black; width: 14%">${{ otherAmount }}</td> | |
94 | + </tr> | |
95 | + <tr> | |
96 | + <td colspan="7" style="border: 1px solid black; padding: 10px"> | |
97 | + <div style="display: flex; justify-content: space-between"> | |
98 | + <span style="width: 20%">收款单位:</span> | |
99 | + <span style="width: 80%"> | |
100 | + {{ payee }} | |
101 | + </span> | |
102 | + </div> | |
103 | + </td> | |
104 | + </tr> | |
105 | + </tbody> | |
106 | + </table> | |
54 | 107 | <template #appendFooter> |
55 | 108 | <a-button v-if="!isApproved && role === ROLE.ADMIN" @click="handleFalse"> 不通过</a-button> |
109 | + <a-button @click="handleExport"> 导出</a-button> | |
56 | 110 | </template> |
57 | 111 | </BasicModal> |
58 | 112 | <MsgModal v-if="msgVisible" @msg-modal-close="handleMsgModalClose" /> |
... | ... | @@ -62,6 +116,7 @@ |
62 | 116 | import { computed, defineComponent, ref } from 'vue'; |
63 | 117 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; |
64 | 118 | import { BasicModal, useModal } from '/@/components/Modal'; |
119 | + import axios from 'axios'; | |
65 | 120 | |
66 | 121 | import { approveAuditApi, getApprovedListApi, getWaitListApi } from '/@/api/project/approve'; |
67 | 122 | import { FIELDS_BASE_INFO, FIELDS_PROFIT_INFO, FIELDS_REPORT_INFO } from '../order/tableData'; |
... | ... | @@ -95,6 +150,14 @@ |
95 | 150 | const fieldInfos = ref({}); |
96 | 151 | const baseInfos = ref({}); |
97 | 152 | const id = ref(''); |
153 | + const invoiceNo = ref(); // 实际收款金额汇总 | |
154 | + const totalPayAmount = ref(); // 实际收款金额汇总 | |
155 | + const totalCustomerAmount = ref(); // 客户总价金额汇总 | |
156 | + const deductAmount = ref(); // 发生扣款金额汇总 | |
157 | + const backRefundDate = ref(); // 必须回款日期 | |
158 | + const actualRefundDate = ref(); // 实际回款日期 | |
159 | + const otherAmount = ref(); // 其他费用汇总 | |
160 | + const payee = ref(); // 其他费用汇总 | |
98 | 161 | |
99 | 162 | const mockData = ref(); |
100 | 163 | const schema: DescItem[] = [ |
... | ... | @@ -226,6 +289,14 @@ |
226 | 289 | openModal(true, { data }); |
227 | 290 | mockData.value = data.fieldInfos.invoiceBillOrderDO; |
228 | 291 | id.value = data.id; |
292 | + totalPayAmount.value = mockData.value.totalPayAmount; | |
293 | + totalCustomerAmount.value = mockData.value.totalCustomerAmount; | |
294 | + deductAmount.value = mockData.value.deductAmount; | |
295 | + backRefundDate.value = mockData.value.backRefundDate; | |
296 | + actualRefundDate.value = mockData.value.actualRefundDate; | |
297 | + otherAmount.value = mockData.value.otherAmount; | |
298 | + invoiceNo.value = mockData.value.invoiceNo; | |
299 | + payee.value = mockData.value.payee; | |
229 | 300 | } |
230 | 301 | |
231 | 302 | async function handleTrue() { |
... | ... | @@ -241,6 +312,11 @@ |
241 | 312 | // closeModal(); |
242 | 313 | } |
243 | 314 | |
315 | + function handleShow(visible: boolean) { | |
316 | + if (!visible) { | |
317 | + } | |
318 | + } | |
319 | + | |
244 | 320 | const role = computed(() => { |
245 | 321 | return userStore.getUserInfo?.roleSmallVO?.code; |
246 | 322 | }); |
... | ... | @@ -260,6 +336,55 @@ |
260 | 336 | return false; |
261 | 337 | }; |
262 | 338 | |
339 | + // 定义处理导出的函数 | |
340 | + const handleExport = async () => { | |
341 | + try { | |
342 | + console.log(payee.value, '5656payee.value'); | |
343 | + const response = await axios.post( | |
344 | + '/basic-api/order/erp/invoice_bill/exportReceipt', | |
345 | + { | |
346 | + invoiceNo: invoiceNo.value, | |
347 | + totalPayAmount: totalPayAmount.value, | |
348 | + totalCustomerAmount: totalCustomerAmount.value, | |
349 | + deductAmount: deductAmount.value, | |
350 | + backRefundDate: backRefundDate.value, | |
351 | + actualRefundDate: actualRefundDate.value, | |
352 | + otherAmount: otherAmount.value, | |
353 | + payee: payee.value, | |
354 | + }, | |
355 | + { | |
356 | + responseType: 'blob', // 设置响应类型为 'blob' | |
357 | + }, | |
358 | + ); | |
359 | + | |
360 | + // 创建一个 Blob 对象来保存二进制数据 | |
361 | + const blob = new Blob([response.data], { type: 'application/octet-stream' }); | |
362 | + | |
363 | + // 获取格式化的当前日期 | |
364 | + const getFormattedDate = () => { | |
365 | + const date = new Date(); | |
366 | + const year = date.getFullYear(); | |
367 | + const month = String(date.getMonth() + 1).padStart(2, '0'); | |
368 | + const day = String(date.getDate()).padStart(2, '0'); | |
369 | + const hours = String(date.getHours()).padStart(2, '0'); | |
370 | + const minutes = String(date.getMinutes()).padStart(2, '0'); | |
371 | + return `${year}-${month}-${day} ${hours}:${minutes}`; | |
372 | + }; | |
373 | + | |
374 | + const date = getFormattedDate(); | |
375 | + | |
376 | + // 创建一个链接元素用来下载文件 | |
377 | + const link = document.createElement('a'); | |
378 | + link.href = window.URL.createObjectURL(blob); | |
379 | + link.download = `付款单_${date}.xlsx`; // 文件命名 | |
380 | + document.body.appendChild(link); | |
381 | + link.click(); // 自动点击链接,触发下载 | |
382 | + document.body.removeChild(link); // 下载完成后移除链接 | |
383 | + } catch (error) { | |
384 | + console.error('获取付款单时出错:', error); | |
385 | + } | |
386 | + }; | |
387 | + | |
263 | 388 | return { |
264 | 389 | handleProfitModal, |
265 | 390 | registerTable, |
... | ... | @@ -281,6 +406,16 @@ |
281 | 406 | handlePreview, |
282 | 407 | mockData, |
283 | 408 | schema, |
409 | + totalPayAmount, | |
410 | + totalCustomerAmount, | |
411 | + deductAmount, | |
412 | + backRefundDate, | |
413 | + actualRefundDate, | |
414 | + otherAmount, | |
415 | + invoiceNo, | |
416 | + payee, | |
417 | + handleExport, | |
418 | + handleShow, | |
284 | 419 | }; |
285 | 420 | }, |
286 | 421 | }); | ... | ... |
src/views/project/finance/pay/Commit.vue
0 → 100644
1 | +<template> | |
2 | + <BasicModal | |
3 | + v-bind="$attrs" | |
4 | + @register="register" | |
5 | + title="提交审核" | |
6 | + width="500px" | |
7 | + :bodyStyle="{ height: '240px' }" | |
8 | + @ok="handleOk" | |
9 | + > | |
10 | + 请选择日期: | |
11 | + <a-date-picker v-model:value="date" /> | |
12 | + </BasicModal> | |
13 | +</template> | |
14 | +<script lang="ts" setup> | |
15 | + import { BasicModal, useModalInner } from '@/components/Modal'; | |
16 | + import { ref } from 'vue'; | |
17 | + import type { Dayjs } from 'dayjs'; | |
18 | + import { checkCommit } from '@/api/project/invoice'; | |
19 | + | |
20 | + const id = ref(); | |
21 | + const date = ref(); | |
22 | + | |
23 | + const [register, { closeModal }] = useModalInner(async (data) => { | |
24 | + id.value = data.data.id; | |
25 | + }); | |
26 | + function formatDate(input: string): string { | |
27 | + // 创建一个 Date 对象 | |
28 | + const date = new Date(input); | |
29 | + | |
30 | + // 获取年月日 | |
31 | + const year = date.getFullYear(); | |
32 | + const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份从 0 开始,所以要加 1 | |
33 | + const day = String(date.getDate()).padStart(2, '0'); | |
34 | + | |
35 | + // 返回格式化后的日期字符串 | |
36 | + return `${year}-${month}-${day}`; | |
37 | + } | |
38 | + | |
39 | + async function handleOk() { | |
40 | + const formattedDate = formatDate(date.value); | |
41 | + | |
42 | + checkCommit({ id: id.value, actualPayedDate: formattedDate }); | |
43 | + closeModal(); | |
44 | + } | |
45 | +</script> | ... | ... |
src/views/project/finance/pay/DeductShow.vue
... | ... | @@ -13,7 +13,20 @@ |
13 | 13 | <a-list-item-meta> |
14 | 14 | <template #title> |
15 | 15 | <!-- <a :href="item.url" target="_blank" rel="noopener noreferrer">{{ item.name }}</a> --> |
16 | - <a @click="openPic(item.url)">{{ item.name }}</a> | |
16 | + <a | |
17 | + v-if="isImageUrl(item.url)" | |
18 | + @click="openPic(item.url)" | |
19 | + style="display: flex; align-items: center" | |
20 | + > | |
21 | + <img | |
22 | + :src="item.url" | |
23 | + alt="Image" | |
24 | + style="max-width: 150px; max-height: 150px; margin-right: 10px" | |
25 | + /> | |
26 | + {{ item.name }} | |
27 | + </a> | |
28 | + <a v-else @click="openPic(item.url)">{{ item.name }}</a> | |
29 | + <!-- <a @click="openPic(item.url)">{{ item.name }}</a> --> | |
17 | 30 | </template> |
18 | 31 | </a-list-item-meta> |
19 | 32 | </a-list-item> |
... | ... | @@ -28,6 +41,7 @@ |
28 | 41 | import { InboxOutlined } from '@ant-design/icons-vue'; |
29 | 42 | import { message } from 'ant-design-vue'; |
30 | 43 | import { getDeductUrlById } from '@/api/project/invoice'; |
44 | + import { view } from '@/utils/pdfShow'; | |
31 | 45 | |
32 | 46 | interface Item { |
33 | 47 | name: string; |
... | ... | @@ -53,15 +67,42 @@ |
53 | 67 | itemArray.value = []; |
54 | 68 | closeModal(); |
55 | 69 | } |
56 | - function openPic(url) { | |
57 | - window.open('', '', '').document.write(`<!DOCTYPE html> | |
58 | - <html> | |
59 | - <body | |
60 | - style="display: flex; | |
61 | - justify-content: center; | |
62 | - align-items: center;"> | |
63 | - <img src='${url}' width="500px" height="500px"/> | |
64 | - </body> | |
65 | - </html>`); | |
70 | + | |
71 | + // 新增的函数:判断 URL 是否为图片格式 | |
72 | + function isImageUrl(url: string): boolean { | |
73 | + const imageExtensions = ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'svg']; | |
74 | + const baseUrl = url.split('?')[0]; | |
75 | + return imageExtensions.some((ext) => baseUrl.toLowerCase().endsWith(ext)); | |
76 | + } | |
77 | + // function openPic(url) { | |
78 | + // window.open('', '', '').document.write(`<!DOCTYPE html> | |
79 | + // <html> | |
80 | + // <body | |
81 | + // style="display: flex; | |
82 | + // justify-content: center; | |
83 | + // align-items: center;"> | |
84 | + // <img src='${url}' width="500px" height="500px"/> | |
85 | + // </body> | |
86 | + // </html>`); | |
87 | + // } | |
88 | + // 检查 URL 是否为 PDF 格式 | |
89 | + function isPdfUrl(url: string): boolean { | |
90 | + return url.toLowerCase().endsWith('.pdf'); | |
91 | + } | |
92 | + // 打开图片或 PDF | |
93 | + function openPic(url: string) { | |
94 | + const baseUrl = url.split('?')[0]; // 获取问号前的部分 | |
95 | + if (isImageUrl(baseUrl)) { | |
96 | + window.open('', '', '').document.write(`<!DOCTYPE html> | |
97 | + <html> | |
98 | + <body style="display: flex; justify-content: center; align-items: center;"> | |
99 | + <img src='${url}' width="500px" height="500px"/> | |
100 | + </body> | |
101 | + </html>`); | |
102 | + } else if (isPdfUrl(baseUrl)) { | |
103 | + view(url); // 新标签页打开 PDF | |
104 | + } else { | |
105 | + console.log('不支持的文件类型'); | |
106 | + } | |
66 | 107 | } |
67 | 108 | </script> | ... | ... |
src/views/project/finance/pay/InvoiceShow.vue
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | <a-list-item-meta> |
14 | 14 | <template #title> |
15 | 15 | <!-- <a :href="item.url" target="_blank" rel="noopener noreferrer">{{ item.name }}</a> --> |
16 | - <a @click="openPic(item.url)">{{ item.name }}</a> | |
16 | + <a @click="view(item.url)">{{ item.name }}</a> | |
17 | 17 | </template> |
18 | 18 | </a-list-item-meta> |
19 | 19 | </a-list-item> |
... | ... | @@ -28,6 +28,7 @@ |
28 | 28 | import { InboxOutlined } from '@ant-design/icons-vue'; |
29 | 29 | import { message } from 'ant-design-vue'; |
30 | 30 | import { getDeductUrlById, getInvoiceUrlById } from '@/api/project/invoice'; |
31 | + import { view } from '@/utils/pdfShow'; | |
31 | 32 | |
32 | 33 | interface Item { |
33 | 34 | name: string; |
... | ... | @@ -53,15 +54,4 @@ |
53 | 54 | itemArray.value = []; |
54 | 55 | closeModal(); |
55 | 56 | } |
56 | - function openPic(url) { | |
57 | - window.open('', '', '').document.write(`<!DOCTYPE html> | |
58 | - <html> | |
59 | - <body | |
60 | - style="display: flex; | |
61 | - justify-content: center; | |
62 | - align-items: center;"> | |
63 | - <img src='${url}' width="500px" height="500px"/> | |
64 | - </body> | |
65 | - </html>`); | |
66 | - } | |
67 | 57 | </script> | ... | ... |
src/views/project/finance/pay/InvoiceUpload.vue
... | ... | @@ -62,10 +62,11 @@ |
62 | 62 | const fileList = ref<UploadProps['fileList']>([]); |
63 | 63 | |
64 | 64 | async function handleOk() { |
65 | - await updateInvoiceInfo({ | |
66 | - id: id.value, | |
67 | - invoiceUrl: invoiceUrl.value, | |
68 | - }); | |
65 | + console.log(invoiceUrl.value, '5656invoiceUrl.value'); | |
66 | + // await updateInvoiceInfo({ | |
67 | + // id: id.value, | |
68 | + // invoiceUrl: invoiceUrl.value, | |
69 | + // }); | |
69 | 70 | // await updateDeduct(requestData); |
70 | 71 | fileList.value = []; |
71 | 72 | emit('success'); | ... | ... |
src/views/project/finance/pay/TrackEdit.vue
... | ... | @@ -30,6 +30,12 @@ |
30 | 30 | v-model:value="selectedProductionDepartment" |
31 | 31 | :options="productionDepartmentOptions" |
32 | 32 | /> --> |
33 | + <!-- <a-select | |
34 | + ref="select" | |
35 | + style="width: 100%" | |
36 | + v-model:value="productionDepartment" | |
37 | + :options="productDepartmentOptions" | |
38 | + /> --> | |
33 | 39 | <div style="margin: 16px 0"></div> |
34 | 40 | <div>上传扣款单</div |
35 | 41 | ><a-space direction="vertical" style="width: 100%" size="large"> |
... | ... | @@ -73,8 +79,10 @@ |
73 | 79 | // const { productionDepartment } = useOrderInfo(orderStore); |
74 | 80 | // console.log(productionDepartment.value, '565656565665orderStore1'); |
75 | 81 | // }); |
76 | - | |
77 | - const input1 = ref(); | |
82 | + const orderStore = useOrderStoreWithOut(); | |
83 | + const { productionDepartment: productDepartmentOptions } = useOrderInfo(orderStore); | |
84 | + const productionDepartment = ref(); | |
85 | + const input1 = ref(0); | |
78 | 86 | const deductUrl = ref(); |
79 | 87 | const id = ref(); |
80 | 88 | const checkNo = ref(); |
... | ... | @@ -88,12 +96,10 @@ |
88 | 96 | const status = ref(); |
89 | 97 | |
90 | 98 | const [register, { setDrawerProps, closeDrawer }] = useDrawerInner((data) => { |
91 | - console.log(data, '5656trackeditdata'); | |
92 | 99 | status.value = data.data.status; |
93 | 100 | id.value = data.data.id; |
94 | 101 | checkNo.value = data.data.checkNo; |
95 | 102 | input1.value = data.data.deductAmount; |
96 | - console.log(input1.value, '5656input1.value'); | |
97 | 103 | deductDept.value = data.data.deductDept; |
98 | 104 | deductUrl.value = data.data.deductUrl; |
99 | 105 | deductUrlOld.value = data.data.deductUrl; |
... | ... | @@ -112,34 +118,29 @@ |
112 | 118 | updateDeductUrl.value = uploadUrl.value + info.name; |
113 | 119 | } |
114 | 120 | function handleShow() { |
115 | - input1.value = ''; | |
116 | - deductUrl.value = ''; | |
117 | - deductDept.value = ''; | |
118 | - updateDeductUrl.value = ''; | |
119 | - fileList.value = []; | |
121 | + // input1.value = ''; | |
122 | + // deductUrl.value = ''; | |
123 | + // deductDept.value = ''; | |
124 | + // updateDeductUrl.value = ''; | |
125 | + // fileList.value = []; | |
120 | 126 | } |
121 | 127 | //完成编辑 |
122 | 128 | async function handleSubmit() { |
123 | 129 | console.log(input1.value, deductUrl.value, deductDept.value, '5656ddd'); |
124 | - if (!input1.value || deductUrl.value == '' || !deductDept.value) { | |
130 | + if (!input1.value || !deductDept.value) { | |
125 | 131 | error('选项不能为空'); |
126 | 132 | } else { |
127 | - //没传新扣款单,不传url | |
128 | - if (deductUrl.value == deductUrlOld.value || deductUrl.value == '') { | |
129 | - error('请上传扣款单'); | |
130 | - } else { | |
131 | - await updateDeductInfo({ | |
132 | - id: id.value, | |
133 | - checkNo: checkNo.value, | |
134 | - deductAmount: input1.value, | |
135 | - deductDept: deductDept.value, | |
136 | - deductUrl: deductUrl.value, | |
137 | - }); | |
138 | - // productionDepartment: selectedProductionDepartment.value, | |
139 | - fileList.value = []; | |
140 | - emit('success'); | |
141 | - closeDrawer(); | |
142 | - } | |
133 | + await updateDeductInfo({ | |
134 | + id: id.value, | |
135 | + checkNo: checkNo.value, | |
136 | + deductAmount: input1.value, | |
137 | + deductDept: deductDept.value, | |
138 | + deductUrl: deductUrl.value, | |
139 | + }); | |
140 | + // productionDepartment: selectedProductionDepartment.value, | |
141 | + fileList.value = []; | |
142 | + emit('success'); | |
143 | + closeDrawer(); | |
143 | 144 | } |
144 | 145 | } |
145 | 146 | </script> | ... | ... |
src/views/project/finance/pay/index.vue
... | ... | @@ -15,6 +15,7 @@ |
15 | 15 | <CheckDetail @register="registerInvoiceDetail" /> |
16 | 16 | <DeductShow @register="registerDeductShow" /> |
17 | 17 | <InvoiceShow @register="registerInvoiceShow" /> |
18 | + <Commit @register="registerCommit" /> | |
18 | 19 | </template> |
19 | 20 | <template #bodyCell="{ column, record }"> |
20 | 21 | <template v-if="column.key === 'action'"> |
... | ... | @@ -36,12 +37,12 @@ |
36 | 37 | :dropDownActions="[ |
37 | 38 | { |
38 | 39 | label: '提交审核', |
39 | - popConfirm: { | |
40 | - title: '是否确认提交审核', | |
41 | - placement: 'left', | |
42 | - confirm: handleCommit.bind(null, record), | |
43 | - }, | |
44 | - // onClick: handleCommit.bind(null, record), | |
40 | + // popConfirm: { | |
41 | + // title: '是否确认提交审核', | |
42 | + // placement: 'left', | |
43 | + // confirm: handleCommit.bind(null, record), | |
44 | + // }, | |
45 | + onClick: handleCommit.bind(null, record), | |
45 | 46 | }, |
46 | 47 | { |
47 | 48 | label: '订单信息', |
... | ... | @@ -82,6 +83,7 @@ |
82 | 83 | import CheckSum from './CheckSum.vue'; |
83 | 84 | import DeductShow from './DeductShow.vue'; |
84 | 85 | import InvoiceShow from './InvoiceShow.vue'; |
86 | + import Commit from './Commit.vue'; | |
85 | 87 | import { useDrawer } from '/@/components/Drawer'; |
86 | 88 | import { useModal } from '/@/components/Modal'; |
87 | 89 | import { getCheck, checkDelete, checkCommit, checkDetail } from '@/api/project/invoice'; |
... | ... | @@ -93,6 +95,7 @@ |
93 | 95 | const [registerTrackEdit, { openDrawer: openTrackEdit }] = useDrawer(); |
94 | 96 | const [registerInvoiceUpload, { openModal: openInvoiceUpload }] = useModal(); |
95 | 97 | const [registerDeductShow, { openModal: openDeductShow }] = useModal(); |
98 | + const [registerCommit, { openModal: openCommit }] = useModal(); | |
96 | 99 | const [registerInvoiceShow, { openModal: openInvoiceShow }] = useModal(); |
97 | 100 | const [registerInvoiceDetail, { openDrawer: openCheckDetail }] = useDrawer(); |
98 | 101 | const checkedKeys = ref<Array<string | number>>([]); |
... | ... | @@ -110,7 +113,7 @@ |
110 | 113 | clickToRowSelect: false, |
111 | 114 | rowKey: 'id', |
112 | 115 | pagination: { |
113 | - pageSize: 20, | |
116 | + pageSize: 10, | |
114 | 117 | }, |
115 | 118 | rowSelection: { |
116 | 119 | type: 'checkbox', |
... | ... | @@ -136,117 +139,6 @@ |
136 | 139 | // slots: { customRender: 'action' }, |
137 | 140 | }, |
138 | 141 | }); |
139 | - //选择 | |
140 | - // function onSelect(record, selected) { | |
141 | - // if (selected) { | |
142 | - // checkedKeys.value = [...checkedKeys.value, record.id]; | |
143 | - // } else { | |
144 | - // checkedKeys.value = checkedKeys.value.filter((id) => id !== record.id); | |
145 | - // } | |
146 | - // } | |
147 | - // function onSelectAll(selected, selectedRows, changeRows) { | |
148 | - // const changeIds = changeRows.map((item) => item.id); | |
149 | - // if (selected) { | |
150 | - // checkedKeys.value = [...checkedKeys.value, ...changeIds]; | |
151 | - // } else { | |
152 | - // checkedKeys.value = checkedKeys.value.filter((id) => { | |
153 | - // return !changeIds.includes(id); | |
154 | - // }); | |
155 | - // } | |
156 | - // } | |
157 | - | |
158 | - // type CustomerCodeEntry = [string, number]; // 定义二维数组类型 [customerCode, count] | |
159 | - | |
160 | - // const selectedCustomCodes = ref<CustomerCodeEntry[]>([]); // 创建一个二维数组的 ref | |
161 | - | |
162 | - // // 选择函数 | |
163 | - // async function onSelect(record: any, selected: boolean) { | |
164 | - // if (selected) { | |
165 | - // const res = await checkDetail({ checkNo: record.checkNo }); | |
166 | - // const customerCode = res[0].customerCode; | |
167 | - | |
168 | - // const index = selectedCustomCodes.value.findIndex(([code]) => code === customerCode); | |
169 | - | |
170 | - // if (index !== -1) { | |
171 | - // // 如果存在,增加计数 | |
172 | - // selectedCustomCodes.value[index][1] += 1; | |
173 | - // } else { | |
174 | - // // 如果不存在,添加新项 [customerCode, 1] | |
175 | - // selectedCustomCodes.value.push([customerCode, 1]); | |
176 | - // } | |
177 | - | |
178 | - // checkedKeys.value = [...checkedKeys.value, record.id]; | |
179 | - // } else { | |
180 | - // const res = await checkDetail({ checkNo: record.checkNo }); | |
181 | - // const customerCode = res[0].customerCode; | |
182 | - | |
183 | - // const index = selectedCustomCodes.value.findIndex(([code]) => code === customerCode); | |
184 | - | |
185 | - // if (index !== -1) { | |
186 | - // if (selectedCustomCodes.value[index][1] > 1) { | |
187 | - // // 如果计数大于 1,减少计数 | |
188 | - // selectedCustomCodes.value[index][1] -= 1; | |
189 | - // } else { | |
190 | - // // 如果计数为 1,移除该项 | |
191 | - // selectedCustomCodes.value.splice(index, 1); | |
192 | - // } | |
193 | - // } | |
194 | - | |
195 | - // checkedKeys.value = checkedKeys.value.filter((id) => id !== record.id); | |
196 | - // } | |
197 | - // console.log(selectedCustomCodes.value, 56561); | |
198 | - // console.log(checkedKeys.value, 56562); | |
199 | - // } | |
200 | - | |
201 | - // async function onSelectAll(selected: boolean, selectedRows: any[], changeRows: any[]) { | |
202 | - // const changeIds = changeRows.map((item) => item.id); | |
203 | - // const changeCustomerCodes = await Promise.all( | |
204 | - // changeRows.map(async (item) => { | |
205 | - // const res = await checkDetail({ checkNo: item.checkNo }); | |
206 | - // return res[0].customerCode; | |
207 | - // }), | |
208 | - // ); | |
209 | - | |
210 | - // if (selected) { | |
211 | - // // 添加到 checkedKeys | |
212 | - // checkedKeys.value = [...checkedKeys.value, ...changeIds]; | |
213 | - | |
214 | - // // 处理每个 customerCode | |
215 | - // changeCustomerCodes.forEach((code) => { | |
216 | - // const index = selectedCustomCodes.value.findIndex( | |
217 | - // ([customerCode]) => customerCode === code, | |
218 | - // ); | |
219 | - // if (index !== -1) { | |
220 | - // // 如果存在,增加计数 | |
221 | - // selectedCustomCodes.value[index][1] += 1; | |
222 | - // } else { | |
223 | - // // 如果不存在,添加新项 [customerCode, 1] | |
224 | - // selectedCustomCodes.value.push([code, 1]); | |
225 | - // } | |
226 | - // }); | |
227 | - // } else { | |
228 | - // // 从 checkedKeys 中移除 | |
229 | - // checkedKeys.value = checkedKeys.value.filter((id) => !changeIds.includes(id)); | |
230 | - | |
231 | - // // 处理每个 customerCode | |
232 | - // changeCustomerCodes.forEach((code) => { | |
233 | - // const index = selectedCustomCodes.value.findIndex( | |
234 | - // ([customerCode]) => customerCode === code, | |
235 | - // ); | |
236 | - // if (index !== -1) { | |
237 | - // if (selectedCustomCodes.value[index][1] > 1) { | |
238 | - // // 如果计数大于 1,减少计数 | |
239 | - // selectedCustomCodes.value[index][1] -= 1; | |
240 | - // } else { | |
241 | - // // 如果计数为 1,移除该项 | |
242 | - // selectedCustomCodes.value.splice(index, 1); | |
243 | - // } | |
244 | - // } | |
245 | - // }); | |
246 | - // } | |
247 | - // console.log(selectedCustomCodes.value, 56561); | |
248 | - // console.log(checkedKeys.value, 56562); | |
249 | - // } | |
250 | 142 | //选择算法:创建二维数组,使客户编码和生产科相同 |
251 | 143 | type CustomerCodeEntry = [string, number]; // 定义二维数组类型 [customerCode, count] |
252 | 144 | type ProductionDepartmentEntry = [string, number]; // 定义二维数组类型 [productionDepartment, count] |
... | ... | @@ -429,17 +321,17 @@ |
429 | 321 | }); |
430 | 322 | } |
431 | 323 | function handleCommit(record) { |
432 | - const currentDate: string = (() => { | |
433 | - const date = new Date(); | |
434 | - const year = date.getFullYear(); | |
435 | - const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份从 0 开始 | |
436 | - const day = String(date.getDate()).padStart(2, '0'); | |
437 | - return `${year}-${month}-${day}`; | |
438 | - })(); | |
439 | - checkCommit({ id: record.id, actualPayedDate: currentDate }); | |
440 | - setTimeout(() => { | |
441 | - reload(); | |
442 | - }, 50); | |
324 | + // const currentDate: string = (() => { | |
325 | + // const date = new Date(); | |
326 | + // const year = date.getFullYear(); | |
327 | + // const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份从 0 开始 | |
328 | + // const day = String(date.getDate()).padStart(2, '0'); | |
329 | + // return `${year}-${month}-${day}`; | |
330 | + // })(); | |
331 | + // checkCommit({ id: record.id, actualPayedDate: currentDate }); | |
332 | + openCommit(true, { | |
333 | + data: record, | |
334 | + }); | |
443 | 335 | } |
444 | 336 | |
445 | 337 | const { createMessage } = useMessage(); | ... | ... |
src/views/project/finance/receive/Commit.vue
0 → 100644
1 | +<template> | |
2 | + <BasicModal | |
3 | + v-bind="$attrs" | |
4 | + @register="register" | |
5 | + title="提交审核" | |
6 | + width="500px" | |
7 | + :bodyStyle="{ height: '240px' }" | |
8 | + @ok="handleOk" | |
9 | + > | |
10 | + 请选择日期: | |
11 | + <a-date-picker v-model:value="date" /> | |
12 | + <div style="height: 10px"></div> | |
13 | + 请选择收款单位: | |
14 | + <a-select v-model="payee" style="width: 100%; padding: 5px; border-radius: 4px"> | |
15 | + <option value="翱特建行城阳支行-美元(5107)">翱特建行城阳支行-美元(5107)</option> | |
16 | + <option value="吉庆建行城阳支行-美元(4820)">吉庆建行城阳支行-美元(4820)</option> | |
17 | + </a-select> | |
18 | + </BasicModal> | |
19 | +</template> | |
20 | +<script lang="ts" setup> | |
21 | + import { BasicModal, useModalInner } from '@/components/Modal'; | |
22 | + import { ref } from 'vue'; | |
23 | + import { commit } from '@/api/project/invoice'; | |
24 | + | |
25 | + const id = ref(); | |
26 | + const payee = ref(); | |
27 | + const date = ref(); | |
28 | + | |
29 | + const [register, { closeModal }] = useModalInner(async (data) => { | |
30 | + id.value = data.data.id; | |
31 | + }); | |
32 | + function formatDate(input: string): string { | |
33 | + // 创建一个 Date 对象 | |
34 | + const date = new Date(input); | |
35 | + | |
36 | + // 获取年月日 | |
37 | + const year = date.getFullYear(); | |
38 | + const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份从 0 开始,所以要加 1 | |
39 | + const day = String(date.getDate()).padStart(2, '0'); | |
40 | + | |
41 | + // 返回格式化后的日期字符串 | |
42 | + return `${year}-${month}-${day}`; | |
43 | + } | |
44 | + | |
45 | + async function handleOk() { | |
46 | + const formattedDate = formatDate(date.value); | |
47 | + | |
48 | + commit({ id: id.value, actualRefundDate: formattedDate, payee: payee.value }); | |
49 | + closeModal(); | |
50 | + } | |
51 | +</script> | ... | ... |
src/views/project/finance/receive/ReUploadBgUrl.vue
0 → 100644
1 | +<template> | |
2 | + <BasicModal | |
3 | + v-bind="$attrs" | |
4 | + @register="register" | |
5 | + title="更新报关单" | |
6 | + width="500px" | |
7 | + :bodyStyle="{ height: '240px' }" | |
8 | + @ok="handleOk" | |
9 | + > | |
10 | + <div>报关单(请上传PDF格式)</div | |
11 | + ><a-space direction="vertical" style="width: 100%" size="large"> | |
12 | + <a-upload | |
13 | + v-model:file-list="fileList" | |
14 | + :beforeUpload="beforeUpload" | |
15 | + list-type="picture" | |
16 | + :max-count="1" | |
17 | + :action="uploadUrl" | |
18 | + @change="handleChange" | |
19 | + > | |
20 | + <a-button> 上传报关单 </a-button> | |
21 | + </a-upload> | |
22 | + </a-space> | |
23 | + </BasicModal> | |
24 | +</template> | |
25 | +<script lang="ts" setup> | |
26 | + import { BasicModal, useModalInner } from '@/components/Modal'; | |
27 | + import { ref } from 'vue'; | |
28 | + import type { UploadProps } from 'ant-design-vue'; | |
29 | + import { reUploadBgUrl } from '@/api/project/invoice'; | |
30 | + import { useMessage } from '/@/hooks/web/useMessage'; | |
31 | + | |
32 | + const fileList = ref<UploadProps['fileList']>([]); | |
33 | + const { createMessage } = useMessage(); | |
34 | + const { error } = createMessage; | |
35 | + | |
36 | + const id = ref(); | |
37 | + const uploadUrl = ref('http://47.104.8.35:8081/api/localStorage/upload_file_oss?name='); | |
38 | + const bgUrl = ref(); | |
39 | + | |
40 | + const [register, { closeModal }] = useModalInner(async (data) => { | |
41 | + id.value = data.data.id; | |
42 | + }); | |
43 | + function handleChange(info) { | |
44 | + if (info.file.status == 'done') { | |
45 | + bgUrl.value = info.file.response.data.fileUrl; | |
46 | + } | |
47 | + } | |
48 | + function beforeUpload(info) { | |
49 | + uploadUrl.value += info.name; | |
50 | + } | |
51 | + | |
52 | + async function handleOk() { | |
53 | + console.log(bgUrl.value, '5656bgUrl.value', uploadUrl.value); | |
54 | + reUploadBgUrl({ id: id.value, bgUrl: bgUrl.value }); | |
55 | + closeModal(); | |
56 | + } | |
57 | +</script> | ... | ... |
src/views/project/finance/receive/TrackEdit.vue
... | ... | @@ -51,7 +51,7 @@ |
51 | 51 | const emit = defineEmits(['success']); |
52 | 52 | const fileList = ref<UploadProps['fileList']>([]); |
53 | 53 | |
54 | - const input1 = ref(); | |
54 | + const input1 = ref(0); | |
55 | 55 | const deductUrl = ref(); |
56 | 56 | const id = ref(); |
57 | 57 | const invoiceNo = ref(); |
... | ... | @@ -85,31 +85,33 @@ |
85 | 85 | updateDeductUrl.value = uploadUrl.value + info.name; |
86 | 86 | } |
87 | 87 | function handleShow() { |
88 | - input1.value = ''; | |
88 | + // if (!visible) { | |
89 | + input1.value = 0; | |
89 | 90 | deductUrl.value = ''; |
90 | 91 | updateDeductUrl.value = ''; |
91 | 92 | fileList.value = []; |
93 | + // } | |
94 | + // input1.value = ''; | |
95 | + // deductUrl.value = ''; | |
96 | + // updateDeductUrl.value = ''; | |
97 | + // fileList.value = []; | |
92 | 98 | } |
93 | 99 | |
94 | 100 | //完成编辑 |
95 | 101 | async function handleSubmit() { |
96 | 102 | console.log(input1.value, '5656', deductUrl.value); |
97 | - if (!input1.value || deductUrl.value == '') { | |
103 | + if (!input1.value) { | |
98 | 104 | error('选项不能为空'); |
99 | 105 | } else { |
100 | - if (deductUrl.value == deductUrlOld.value || deductUrl.value == '') { | |
101 | - error('请上传扣款单'); | |
102 | - } else { | |
103 | - await updateDeduct({ | |
104 | - id: id.value, | |
105 | - invoiceNo: invoiceNo.value, | |
106 | - deductAmount: input1.value, | |
107 | - deductUrl: deductUrl.value, | |
108 | - }); | |
109 | - fileList.value = []; | |
110 | - emit('success'); | |
111 | - closeDrawer(); | |
112 | - } | |
106 | + await updateDeduct({ | |
107 | + id: id.value, | |
108 | + invoiceNo: invoiceNo.value, | |
109 | + deductAmount: input1.value, | |
110 | + deductUrl: deductUrl.value, | |
111 | + }); | |
112 | + fileList.value = []; | |
113 | + emit('success'); | |
114 | + closeDrawer(); | |
113 | 115 | } |
114 | 116 | } |
115 | 117 | </script> | ... | ... |
src/views/project/finance/receive/index.vue
... | ... | @@ -13,6 +13,8 @@ |
13 | 13 | <TrackEdit @register="registerTrackEdit" @success="handleSuccess" /> |
14 | 14 | <InvoiceDetail @register="registerInvoiceDetail" /> |
15 | 15 | <DeductShow @register="registerDeductShow" /> |
16 | + <Commit @register="registerCommit" /> | |
17 | + <ReUploadBgUrl @register="registerReUploadBgUrl" /> | |
16 | 18 | </template> |
17 | 19 | <template #bodyCell="{ column, record }"> |
18 | 20 | <template v-if="column.key === 'action'"> |
... | ... | @@ -28,12 +30,12 @@ |
28 | 30 | }, |
29 | 31 | { |
30 | 32 | label: '提交审核', |
31 | - popConfirm: { | |
32 | - title: '是否确认提交审核', | |
33 | - placement: 'left', | |
34 | - confirm: handleCommit.bind(null, record), | |
35 | - }, | |
36 | - // onClick: handleCommit.bind(null, record), | |
33 | + // popConfirm: { | |
34 | + // title: '是否确认提交审核', | |
35 | + // placement: 'left', | |
36 | + // confirm: handleCommit.bind(null, record), | |
37 | + // }, | |
38 | + onClick: handleCommit.bind(null, record), | |
37 | 39 | }, |
38 | 40 | ]" |
39 | 41 | :dropDownActions="[ |
... | ... | @@ -42,6 +44,10 @@ |
42 | 44 | onClick: handleInvoiceDetail.bind(null, record), |
43 | 45 | }, |
44 | 46 | { |
47 | + label: '更新报关单', | |
48 | + onClick: handleReUploadBgUrl.bind(null, record), | |
49 | + }, | |
50 | + { | |
45 | 51 | label: '删除', |
46 | 52 | popConfirm: { |
47 | 53 | title: '是否确认删除', |
... | ... | @@ -70,6 +76,8 @@ |
70 | 76 | import InvoiceAnalysis from './InvoiceAnalysis.vue'; |
71 | 77 | import InvoiceDetail from './InvoiceDetail.vue'; |
72 | 78 | import DeductShow from './DeductShow.vue'; |
79 | + import Commit from './Commit.vue'; | |
80 | + import ReUploadBgUrl from './ReUploadBgUrl.vue'; | |
73 | 81 | import { useDrawer } from '/@/components/Drawer'; |
74 | 82 | import { getInvoice, deleteInvoice, commit, getBaseInvoice } from '@/api/project/invoice'; |
75 | 83 | import { useModal } from '/@/components/Modal'; |
... | ... | @@ -84,6 +92,8 @@ |
84 | 92 | const [registerFinanceEdit, { openDrawer: openFinanceEdit }] = useDrawer(); |
85 | 93 | const [registerTrackEdit, { openDrawer: openTrackEdit }] = useDrawer(); |
86 | 94 | const [registerInvoiceDetail, { openDrawer: openInvoiceDetail }] = useDrawer(); |
95 | + const [registerCommit, { openModal: openCommit }] = useModal(); | |
96 | + const [registerReUploadBgUrl, { openModal: openReUploadBgUrl }] = useModal(); | |
87 | 97 | const [registerDeductShow, { openModal: openDeductShow }] = useModal(); |
88 | 98 | const checkedKeys = ref<Array<string | number>>([]); |
89 | 99 | const userStore = useUserStoreWithOut(); |
... | ... | @@ -109,9 +119,6 @@ |
109 | 119 | schemas: searchFormSchema, |
110 | 120 | autoSubmitOnEnter: true, |
111 | 121 | }, |
112 | - pagination: { | |
113 | - pageSize: 20, | |
114 | - }, | |
115 | 122 | useSearchForm: true, |
116 | 123 | showTableSetting: true, |
117 | 124 | showIndexColumn: false, |
... | ... | @@ -240,23 +247,31 @@ |
240 | 247 | }); |
241 | 248 | } |
242 | 249 | function handleCommit(record) { |
243 | - const currentDate: string = (() => { | |
244 | - const date = new Date(); | |
245 | - const year = date.getFullYear(); | |
246 | - const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份从 0 开始 | |
247 | - const day = String(date.getDate()).padStart(2, '0'); | |
248 | - return `${year}-${month}-${day}`; | |
249 | - })(); | |
250 | - commit({ id: record.id, actualRefundDate: currentDate }); | |
251 | - setTimeout(() => { | |
252 | - reload(); | |
253 | - }, 50); | |
250 | + // const currentDate: string = (() => { | |
251 | + // const date = new Date(); | |
252 | + // const year = date.getFullYear(); | |
253 | + // const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份从 0 开始 | |
254 | + // const day = String(date.getDate()).padStart(2, '0'); | |
255 | + // return `${year}-${month}-${day}`; | |
256 | + // })(); | |
257 | + // commit({ id: record.id, actualRefundDate: currentDate }); | |
258 | + // setTimeout(() => { | |
259 | + // reload(); | |
260 | + // }, 50); | |
261 | + openCommit(true, { | |
262 | + data: record, | |
263 | + }); | |
254 | 264 | } |
255 | 265 | function handleInvoiceDetail(record) { |
256 | 266 | openInvoiceDetail(true, { |
257 | 267 | data: record, |
258 | 268 | }); |
259 | 269 | } |
270 | + function handleReUploadBgUrl(record) { | |
271 | + openReUploadBgUrl(true, { | |
272 | + data: record, | |
273 | + }); | |
274 | + } | |
260 | 275 | const { createMessage } = useMessage(); |
261 | 276 | const { error } = createMessage; |
262 | 277 | function handleInvoiceAnalysis(record) { | ... | ... |
src/views/project/finance/receive/receive.data.tsx
... | ... | @@ -4,6 +4,7 @@ import { icon } from 'ant-design-vue'; |
4 | 4 | import { FilePptOutlined } from '@ant-design/icons-vue'; |
5 | 5 | import { size } from 'lodash-es'; |
6 | 6 | import { ref } from 'vue'; |
7 | +import { view } from '@/utils/pdfShow'; | |
7 | 8 | |
8 | 9 | export const searchFormSchema: FormSchema[] = [ |
9 | 10 | { |
... | ... | @@ -49,7 +50,7 @@ export const columns: BasicColumn[] = [ |
49 | 50 | width: 80, |
50 | 51 | customRender: (column) => { |
51 | 52 | const bgUrl = column.record.bgUrl; |
52 | - return <FilePptOutlined style="font-size:25px" onClick={() => window.open(bgUrl)} />; | |
53 | + return <FilePptOutlined style="font-size:25px" onClick={() => view(bgUrl)} />; | |
53 | 54 | }, |
54 | 55 | }, |
55 | 56 | { | ... | ... |
types/config.d.ts
vite.config.ts
1 | 1 | import { defineApplicationConfig } from '@vben/vite-config'; |
2 | +import { getAppEnvConfig } from '/@/utils/env'; | |
2 | 3 | |
4 | +// const { VITE_ALIYUN_OSS_DOMAIN } = getAppEnvConfig(); | |
3 | 5 | export default defineApplicationConfig({ |
4 | 6 | overrides: { |
5 | 7 | // build: { |
... | ... | @@ -19,6 +21,14 @@ export default defineApplicationConfig({ |
19 | 21 | }, |
20 | 22 | server: { |
21 | 23 | proxy: { |
24 | + // '/aliyun-oss-pdf': { | |
25 | + // target: VITE_ALIYUN_OSS_DOMAIN, | |
26 | + // changeOrigin: true, | |
27 | + // secure: true, // 确保使用 HTTPS | |
28 | + // rewrite(path) { | |
29 | + // return path.replace(/^\/aliyun-oss-pdf/, ''); | |
30 | + // }, | |
31 | + // }, | |
22 | 32 | '/basic-api/order': { |
23 | 33 | target: 'http://47.104.8.35:18001', |
24 | 34 | // target: 'http://localhost:8001', | ... | ... |