Commit 3123f5a8c208f5678bed015a0877c5fe3b36deea

Authored by boyang
1 parent a8280c01

修改最后一批bug

.env.development
... ... @@ -12,3 +12,5 @@ VITE_GLOB_UPLOAD_URL=/upload
12 12  
13 13 # Interface prefix
14 14 VITE_GLOB_API_URL_PREFIX=
  15 +
  16 +#VITE_ALIYUN_OSS_DOMAIN=https://test-alterego.oss-cn-qingdao.aliyuncs.com
15 17 \ No newline at end of file
... ...
.env.production
... ... @@ -19,3 +19,5 @@ VITE_GLOB_UPLOAD_URL=/upload
19 19  
20 20 # Interface prefix
21 21 VITE_GLOB_API_URL_PREFIX=
  22 +
  23 +#VITE_ALIYUN_OSS_DOMAIN=https://alterego.oss-cn-qingdao.aliyuncs.com
... ...
.env.test
... ... @@ -19,3 +19,5 @@ VITE_GLOB_UPLOAD_URL=/upload
19 19  
20 20 # Interface prefix
21 21 VITE_GLOB_API_URL_PREFIX=
  22 +
  23 +#VITE_ALIYUN_OSS_DOMAIN=https://test-alterego.oss-cn-qingdao.aliyuncs.com
22 24 \ No newline at end of file
... ...
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) =&gt; {
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) =&gt; {
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 &#39;ant-design-vue&#39;;
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
... ... @@ -157,4 +157,5 @@ export interface GlobEnvConfig {
157 157 VITE_GLOB_API_URL_PREFIX?: string;
158 158 // Upload url
159 159 VITE_GLOB_UPLOAD_URL?: string;
  160 + VITE_ALIYUN_OSS_DOMAIN?: string;
160 161 }
... ...
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',
... ...