Commit 3123f5a8c208f5678bed015a0877c5fe3b36deea

Authored by boyang
1 parent a8280c01

修改最后一批bug

.env.development
@@ -12,3 +12,5 @@ VITE_GLOB_UPLOAD_URL=/upload @@ -12,3 +12,5 @@ VITE_GLOB_UPLOAD_URL=/upload
12 12
13 # Interface prefix 13 # Interface prefix
14 VITE_GLOB_API_URL_PREFIX= 14 VITE_GLOB_API_URL_PREFIX=
  15 +
  16 +#VITE_ALIYUN_OSS_DOMAIN=https://test-alterego.oss-cn-qingdao.aliyuncs.com
15 \ No newline at end of file 17 \ No newline at end of file
.env.production
@@ -19,3 +19,5 @@ VITE_GLOB_UPLOAD_URL=/upload @@ -19,3 +19,5 @@ VITE_GLOB_UPLOAD_URL=/upload
19 19
20 # Interface prefix 20 # Interface prefix
21 VITE_GLOB_API_URL_PREFIX= 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,3 +19,5 @@ VITE_GLOB_UPLOAD_URL=/upload
19 19
20 # Interface prefix 20 # Interface prefix
21 VITE_GLOB_API_URL_PREFIX= 21 VITE_GLOB_API_URL_PREFIX=
  22 +
  23 +#VITE_ALIYUN_OSS_DOMAIN=https://test-alterego.oss-cn-qingdao.aliyuncs.com
22 \ No newline at end of file 24 \ No newline at end of file
src/api/project/invoice.ts
  1 +import { useOrderStoreWithOut } from '/@/store/modules/order';
1 import { defHttp } from '/@/utils/http/axios'; 2 import { defHttp } from '/@/utils/http/axios';
2 3
3 enum Api { 4 enum Api {
@@ -12,6 +13,8 @@ enum Api { @@ -12,6 +13,8 @@ enum Api {
12 INVOICE_DELETE = '/order/erp/invoice_bill/delete_by_id', //删除数据 13 INVOICE_DELETE = '/order/erp/invoice_bill/delete_by_id', //删除数据
13 COMMIT = '/order/erp/invoice_bill/commit_apply', //提交审核 14 COMMIT = '/order/erp/invoice_bill/commit_apply', //提交审核
14 GETINVOICEDEDUCTURL_BY_ID = '/order/erp/invoice_bill/getDeductUrl_by_id', //获取扣款信息 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 PRODUCT_CREATE = '/order/erp/check_bill/create', //创建生产科应付单据 19 PRODUCT_CREATE = '/order/erp/check_bill/create', //创建生产科应付单据
17 PAYED_DATE = '/order/erp/check_bill/get_payed_date', //获取生产科应回款日期 20 PAYED_DATE = '/order/erp/check_bill/get_payed_date', //获取生产科应回款日期
@@ -26,6 +29,7 @@ enum Api { @@ -26,6 +29,7 @@ enum Api {
26 EXPORT_CHECK_ANALYSIS = '/order/erp/check_bill/export', //导出分析列表 29 EXPORT_CHECK_ANALYSIS = '/order/erp/check_bill/export', //导出分析列表
27 GETDEDUCTURL_BY_ID = '/order/erp/check_bill/getDeductUrl_by_id', //获取扣款信息 30 GETDEDUCTURL_BY_ID = '/order/erp/check_bill/getDeductUrl_by_id', //获取扣款信息
28 GETINVOICEURL_BY_ID = '/order/erp/check_bill/getInvoiceUrl_by_id', //获取扣款信息 31 GETINVOICEURL_BY_ID = '/order/erp/check_bill/getInvoiceUrl_by_id', //获取扣款信息
  32 + EXPORTRECEIPT = '/order/erp/check_bill/exportReceipt', //付款单导出
29 } 33 }
30 34
31 export const getRefundDate = async (params: any, data?: any) => { 35 export const getRefundDate = async (params: any, data?: any) => {
@@ -48,7 +52,14 @@ export const getInvoice = async (params: any) => { @@ -48,7 +52,14 @@ export const getInvoice = async (params: any) => {
48 url: Api.INVOICE, 52 url: Api.INVOICE,
49 params, 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 export const getBaseInvoice = async (params: any) => { 64 export const getBaseInvoice = async (params: any) => {
54 const res = await defHttp.post<any>({ 65 const res = await defHttp.post<any>({
@@ -137,8 +148,15 @@ export const getCheck = async (params: any) =&gt; { @@ -137,8 +148,15 @@ export const getCheck = async (params: any) =&gt; {
137 url: Api.CHECK_BILL, 148 url: Api.CHECK_BILL,
138 params, 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 export const checkDetail = async (params: any) => { 161 export const checkDetail = async (params: any) => {
144 return await defHttp.post<any>({ 162 return await defHttp.post<any>({
@@ -185,3 +203,24 @@ export const getInvoiceUrlById = async (params: any) =&gt; { @@ -185,3 +203,24 @@ export const getInvoiceUrlById = async (params: any) =&gt; {
185 params, 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,7 +15,7 @@
15 v-if="!isApproved" 15 v-if="!isApproved"
16 :actions="[ 16 :actions="[
17 { 17 {
18 - label: '编辑', 18 + label: '审核',
19 // icon: 'ic:outline-delete-outline', 19 // icon: 'ic:outline-delete-outline',
20 onClick: handleDetail.bind(null, record), 20 onClick: handleDetail.bind(null, record),
21 }, 21 },
@@ -41,12 +41,13 @@ @@ -41,12 +41,13 @@
41 @register="registerModal" 41 @register="registerModal"
42 title="申请信息" 42 title="申请信息"
43 okText="通过" 43 okText="通过"
  44 + width="900px"
44 @ok="handleTrue" 45 @ok="handleTrue"
45 @visible-change="handleShow" 46 @visible-change="handleShow"
46 :showCancelBtn="!isApproved && role === ROLE.ADMIN" 47 :showCancelBtn="!isApproved && role === ROLE.ADMIN"
47 :showOkBtn="!isApproved && role === ROLE.ADMIN" 48 :showOkBtn="!isApproved && role === ROLE.ADMIN"
48 > 49 >
49 - <Description 50 + <!-- <Description
50 v-if="!showInvoice" 51 v-if="!showInvoice"
51 class="mt-4" 52 class="mt-4"
52 layout="vertical" 53 layout="vertical"
@@ -54,7 +55,48 @@ @@ -54,7 +55,48 @@
54 :column="2" 55 :column="2"
55 :data="mockData" 56 :data="mockData"
56 :schema="schema" 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 <a v-if="showInvoice" @click="openPic(mockData.invoiceUrl)" rel="noopener noreferrer">{{ 100 <a v-if="showInvoice" @click="openPic(mockData.invoiceUrl)" rel="noopener noreferrer">{{
59 mockData.invoiceName 101 mockData.invoiceName
60 }}</a> 102 }}</a>
@@ -71,6 +113,7 @@ @@ -71,6 +113,7 @@
71 </a-list> --> 113 </a-list> -->
72 <template #appendFooter> 114 <template #appendFooter>
73 <a-button v-if="!isApproved && role === ROLE.ADMIN" @click="handleFalse"> 不通过</a-button> 115 <a-button v-if="!isApproved && role === ROLE.ADMIN" @click="handleFalse"> 不通过</a-button>
  116 + <a-button @click="handleExport"> 导出</a-button>
74 </template> 117 </template>
75 </BasicModal> 118 </BasicModal>
76 <MsgModal v-if="msgVisible" @msg-modal-close="handleMsgModalClose" /> 119 <MsgModal v-if="msgVisible" @msg-modal-close="handleMsgModalClose" />
@@ -80,6 +123,9 @@ @@ -80,6 +123,9 @@
80 import { computed, defineComponent, ref } from 'vue'; 123 import { computed, defineComponent, ref } from 'vue';
81 import { BasicTable, useTable, TableAction } from '/@/components/Table'; 124 import { BasicTable, useTable, TableAction } from '/@/components/Table';
82 import { BasicModal, useModal } from '/@/components/Modal'; 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 import { approveAuditApi, getApprovedListApi, getWaitListApi } from '/@/api/project/approve'; 130 import { approveAuditApi, getApprovedListApi, getWaitListApi } from '/@/api/project/approve';
85 import { FIELDS_BASE_INFO, FIELDS_PROFIT_INFO, FIELDS_REPORT_INFO } from '../order/tableData'; 131 import { FIELDS_BASE_INFO, FIELDS_PROFIT_INFO, FIELDS_REPORT_INFO } from '../order/tableData';
@@ -122,6 +168,13 @@ @@ -122,6 +168,13 @@
122 } 168 }
123 const itemArray = ref<Item[]>([]); 169 const itemArray = ref<Item[]>([]);
124 const actualPayCalculate = ref(0); 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 const schema = [ 178 const schema = [
126 { 179 {
127 field: 'actualPayedAmount', 180 field: 'actualPayedAmount',
@@ -161,7 +214,6 @@ @@ -161,7 +214,6 @@
161 width: 150, 214 width: 150,
162 customRender: (column) => { 215 customRender: (column) => {
163 const { record } = column || {}; 216 const { record } = column || {};
164 - console.log(record, '5656record');  
165 if (record?.type === 40) { 217 if (record?.type === 40) {
166 return record.createBy; 218 return record.createBy;
167 } else if (record?.type == 50) { 219 } else if (record?.type == 50) {
@@ -270,6 +322,15 @@ @@ -270,6 +322,15 @@
270 id.value = data.id; 322 id.value = data.id;
271 itemArray.value = []; 323 itemArray.value = [];
272 mockData.value = data.fieldInfos.checkBillOrderDO; 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 const match = mockData.value.invoiceUrl.match(/aliyuncs\.com\/(.*?)\?/); 334 const match = mockData.value.invoiceUrl.match(/aliyuncs\.com\/(.*?)\?/);
274 if (match && match[1]) { 335 if (match && match[1]) {
275 // 对提取的部分进行解码 336 // 对提取的部分进行解码
@@ -294,6 +355,67 @@ @@ -294,6 +355,67 @@
294 // reload(); 355 // reload();
295 // closeModal(); 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 const role = computed(() => { 420 const role = computed(() => {
299 return userStore.getUserInfo?.roleSmallVO?.code; 421 return userStore.getUserInfo?.roleSmallVO?.code;
@@ -314,16 +436,42 @@ @@ -314,16 +436,42 @@
314 return false; 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 return { 477 return {
@@ -350,6 +498,15 @@ @@ -350,6 +498,15 @@
350 showInvoice, 498 showInvoice,
351 openPic, 499 openPic,
352 handleShow, 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,7 +15,7 @@
15 v-if="!isApproved" 15 v-if="!isApproved"
16 :actions="[ 16 :actions="[
17 { 17 {
18 - label: '编辑', 18 + label: '审核',
19 // icon: 'ic:outline-delete-outline', 19 // icon: 'ic:outline-delete-outline',
20 onClick: handleDetail.bind(null, record), 20 onClick: handleDetail.bind(null, record),
21 }, 21 },
@@ -39,20 +39,74 @@ @@ -39,20 +39,74 @@
39 @register="registerModal" 39 @register="registerModal"
40 title="申请信息" 40 title="申请信息"
41 okText="通过" 41 okText="通过"
  42 + width="1000px"
42 @ok="handleTrue" 43 @ok="handleTrue"
  44 + @visible-change="handleShow"
43 :showCancelBtn="!isApproved && role === ROLE.ADMIN" 45 :showCancelBtn="!isApproved && role === ROLE.ADMIN"
44 :showOkBtn="!isApproved && role === ROLE.ADMIN" 46 :showOkBtn="!isApproved && role === ROLE.ADMIN"
45 > 47 >
46 - <Description 48 + <!-- <Description
47 class="mt-4" 49 class="mt-4"
48 layout="vertical" 50 layout="vertical"
49 :collapseOptions="{ canExpand: true, helpMessage: 'help me' }" 51 :collapseOptions="{ canExpand: true, helpMessage: 'help me' }"
50 :column="2" 52 :column="2"
51 :data="mockData" 53 :data="mockData"
52 :schema="schema" 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 <template #appendFooter> 107 <template #appendFooter>
55 <a-button v-if="!isApproved && role === ROLE.ADMIN" @click="handleFalse"> 不通过</a-button> 108 <a-button v-if="!isApproved && role === ROLE.ADMIN" @click="handleFalse"> 不通过</a-button>
  109 + <a-button @click="handleExport"> 导出</a-button>
56 </template> 110 </template>
57 </BasicModal> 111 </BasicModal>
58 <MsgModal v-if="msgVisible" @msg-modal-close="handleMsgModalClose" /> 112 <MsgModal v-if="msgVisible" @msg-modal-close="handleMsgModalClose" />
@@ -62,6 +116,7 @@ @@ -62,6 +116,7 @@
62 import { computed, defineComponent, ref } from 'vue'; 116 import { computed, defineComponent, ref } from 'vue';
63 import { BasicTable, useTable, TableAction } from '/@/components/Table'; 117 import { BasicTable, useTable, TableAction } from '/@/components/Table';
64 import { BasicModal, useModal } from '/@/components/Modal'; 118 import { BasicModal, useModal } from '/@/components/Modal';
  119 + import axios from 'axios';
65 120
66 import { approveAuditApi, getApprovedListApi, getWaitListApi } from '/@/api/project/approve'; 121 import { approveAuditApi, getApprovedListApi, getWaitListApi } from '/@/api/project/approve';
67 import { FIELDS_BASE_INFO, FIELDS_PROFIT_INFO, FIELDS_REPORT_INFO } from '../order/tableData'; 122 import { FIELDS_BASE_INFO, FIELDS_PROFIT_INFO, FIELDS_REPORT_INFO } from '../order/tableData';
@@ -95,6 +150,14 @@ @@ -95,6 +150,14 @@
95 const fieldInfos = ref({}); 150 const fieldInfos = ref({});
96 const baseInfos = ref({}); 151 const baseInfos = ref({});
97 const id = ref(''); 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 const mockData = ref(); 162 const mockData = ref();
100 const schema: DescItem[] = [ 163 const schema: DescItem[] = [
@@ -226,6 +289,14 @@ @@ -226,6 +289,14 @@
226 openModal(true, { data }); 289 openModal(true, { data });
227 mockData.value = data.fieldInfos.invoiceBillOrderDO; 290 mockData.value = data.fieldInfos.invoiceBillOrderDO;
228 id.value = data.id; 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 async function handleTrue() { 302 async function handleTrue() {
@@ -241,6 +312,11 @@ @@ -241,6 +312,11 @@
241 // closeModal(); 312 // closeModal();
242 } 313 }
243 314
  315 + function handleShow(visible: boolean) {
  316 + if (!visible) {
  317 + }
  318 + }
  319 +
244 const role = computed(() => { 320 const role = computed(() => {
245 return userStore.getUserInfo?.roleSmallVO?.code; 321 return userStore.getUserInfo?.roleSmallVO?.code;
246 }); 322 });
@@ -260,6 +336,55 @@ @@ -260,6 +336,55 @@
260 return false; 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 return { 388 return {
264 handleProfitModal, 389 handleProfitModal,
265 registerTable, 390 registerTable,
@@ -281,6 +406,16 @@ @@ -281,6 +406,16 @@
281 handlePreview, 406 handlePreview,
282 mockData, 407 mockData,
283 schema, 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,7 +13,20 @@
13 <a-list-item-meta> 13 <a-list-item-meta>
14 <template #title> 14 <template #title>
15 <!-- <a :href="item.url" target="_blank" rel="noopener noreferrer">{{ item.name }}</a> --> 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 </template> 30 </template>
18 </a-list-item-meta> 31 </a-list-item-meta>
19 </a-list-item> 32 </a-list-item>
@@ -28,6 +41,7 @@ @@ -28,6 +41,7 @@
28 import { InboxOutlined } from '@ant-design/icons-vue'; 41 import { InboxOutlined } from '@ant-design/icons-vue';
29 import { message } from 'ant-design-vue'; 42 import { message } from 'ant-design-vue';
30 import { getDeductUrlById } from '@/api/project/invoice'; 43 import { getDeductUrlById } from '@/api/project/invoice';
  44 + import { view } from '@/utils/pdfShow';
31 45
32 interface Item { 46 interface Item {
33 name: string; 47 name: string;
@@ -53,15 +67,42 @@ @@ -53,15 +67,42 @@
53 itemArray.value = []; 67 itemArray.value = [];
54 closeModal(); 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 </script> 108 </script>
src/views/project/finance/pay/InvoiceShow.vue
@@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
13 <a-list-item-meta> 13 <a-list-item-meta>
14 <template #title> 14 <template #title>
15 <!-- <a :href="item.url" target="_blank" rel="noopener noreferrer">{{ item.name }}</a> --> 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 </template> 17 </template>
18 </a-list-item-meta> 18 </a-list-item-meta>
19 </a-list-item> 19 </a-list-item>
@@ -28,6 +28,7 @@ @@ -28,6 +28,7 @@
28 import { InboxOutlined } from '@ant-design/icons-vue'; 28 import { InboxOutlined } from '@ant-design/icons-vue';
29 import { message } from 'ant-design-vue'; 29 import { message } from 'ant-design-vue';
30 import { getDeductUrlById, getInvoiceUrlById } from '@/api/project/invoice'; 30 import { getDeductUrlById, getInvoiceUrlById } from '@/api/project/invoice';
  31 + import { view } from '@/utils/pdfShow';
31 32
32 interface Item { 33 interface Item {
33 name: string; 34 name: string;
@@ -53,15 +54,4 @@ @@ -53,15 +54,4 @@
53 itemArray.value = []; 54 itemArray.value = [];
54 closeModal(); 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 </script> 57 </script>
src/views/project/finance/pay/InvoiceUpload.vue
@@ -62,10 +62,11 @@ @@ -62,10 +62,11 @@
62 const fileList = ref<UploadProps['fileList']>([]); 62 const fileList = ref<UploadProps['fileList']>([]);
63 63
64 async function handleOk() { 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 // await updateDeduct(requestData); 70 // await updateDeduct(requestData);
70 fileList.value = []; 71 fileList.value = [];
71 emit('success'); 72 emit('success');
src/views/project/finance/pay/TrackEdit.vue
@@ -30,6 +30,12 @@ @@ -30,6 +30,12 @@
30 v-model:value="selectedProductionDepartment" 30 v-model:value="selectedProductionDepartment"
31 :options="productionDepartmentOptions" 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 <div style="margin: 16px 0"></div> 39 <div style="margin: 16px 0"></div>
34 <div>上传扣款单</div 40 <div>上传扣款单</div
35 ><a-space direction="vertical" style="width: 100%" size="large"> 41 ><a-space direction="vertical" style="width: 100%" size="large">
@@ -73,8 +79,10 @@ @@ -73,8 +79,10 @@
73 // const { productionDepartment } = useOrderInfo(orderStore); 79 // const { productionDepartment } = useOrderInfo(orderStore);
74 // console.log(productionDepartment.value, '565656565665orderStore1'); 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 const deductUrl = ref(); 86 const deductUrl = ref();
79 const id = ref(); 87 const id = ref();
80 const checkNo = ref(); 88 const checkNo = ref();
@@ -88,12 +96,10 @@ @@ -88,12 +96,10 @@
88 const status = ref(); 96 const status = ref();
89 97
90 const [register, { setDrawerProps, closeDrawer }] = useDrawerInner((data) => { 98 const [register, { setDrawerProps, closeDrawer }] = useDrawerInner((data) => {
91 - console.log(data, '5656trackeditdata');  
92 status.value = data.data.status; 99 status.value = data.data.status;
93 id.value = data.data.id; 100 id.value = data.data.id;
94 checkNo.value = data.data.checkNo; 101 checkNo.value = data.data.checkNo;
95 input1.value = data.data.deductAmount; 102 input1.value = data.data.deductAmount;
96 - console.log(input1.value, '5656input1.value');  
97 deductDept.value = data.data.deductDept; 103 deductDept.value = data.data.deductDept;
98 deductUrl.value = data.data.deductUrl; 104 deductUrl.value = data.data.deductUrl;
99 deductUrlOld.value = data.data.deductUrl; 105 deductUrlOld.value = data.data.deductUrl;
@@ -112,34 +118,29 @@ @@ -112,34 +118,29 @@
112 updateDeductUrl.value = uploadUrl.value + info.name; 118 updateDeductUrl.value = uploadUrl.value + info.name;
113 } 119 }
114 function handleShow() { 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 async function handleSubmit() { 128 async function handleSubmit() {
123 console.log(input1.value, deductUrl.value, deductDept.value, '5656ddd'); 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 error('选项不能为空'); 131 error('选项不能为空');
126 } else { 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 </script> 146 </script>
src/views/project/finance/pay/index.vue
@@ -15,6 +15,7 @@ @@ -15,6 +15,7 @@
15 <CheckDetail @register="registerInvoiceDetail" /> 15 <CheckDetail @register="registerInvoiceDetail" />
16 <DeductShow @register="registerDeductShow" /> 16 <DeductShow @register="registerDeductShow" />
17 <InvoiceShow @register="registerInvoiceShow" /> 17 <InvoiceShow @register="registerInvoiceShow" />
  18 + <Commit @register="registerCommit" />
18 </template> 19 </template>
19 <template #bodyCell="{ column, record }"> 20 <template #bodyCell="{ column, record }">
20 <template v-if="column.key === 'action'"> 21 <template v-if="column.key === 'action'">
@@ -36,12 +37,12 @@ @@ -36,12 +37,12 @@
36 :dropDownActions="[ 37 :dropDownActions="[
37 { 38 {
38 label: '提交审核', 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 label: '订单信息', 48 label: '订单信息',
@@ -82,6 +83,7 @@ @@ -82,6 +83,7 @@
82 import CheckSum from './CheckSum.vue'; 83 import CheckSum from './CheckSum.vue';
83 import DeductShow from './DeductShow.vue'; 84 import DeductShow from './DeductShow.vue';
84 import InvoiceShow from './InvoiceShow.vue'; 85 import InvoiceShow from './InvoiceShow.vue';
  86 + import Commit from './Commit.vue';
85 import { useDrawer } from '/@/components/Drawer'; 87 import { useDrawer } from '/@/components/Drawer';
86 import { useModal } from '/@/components/Modal'; 88 import { useModal } from '/@/components/Modal';
87 import { getCheck, checkDelete, checkCommit, checkDetail } from '@/api/project/invoice'; 89 import { getCheck, checkDelete, checkCommit, checkDetail } from '@/api/project/invoice';
@@ -93,6 +95,7 @@ @@ -93,6 +95,7 @@
93 const [registerTrackEdit, { openDrawer: openTrackEdit }] = useDrawer(); 95 const [registerTrackEdit, { openDrawer: openTrackEdit }] = useDrawer();
94 const [registerInvoiceUpload, { openModal: openInvoiceUpload }] = useModal(); 96 const [registerInvoiceUpload, { openModal: openInvoiceUpload }] = useModal();
95 const [registerDeductShow, { openModal: openDeductShow }] = useModal(); 97 const [registerDeductShow, { openModal: openDeductShow }] = useModal();
  98 + const [registerCommit, { openModal: openCommit }] = useModal();
96 const [registerInvoiceShow, { openModal: openInvoiceShow }] = useModal(); 99 const [registerInvoiceShow, { openModal: openInvoiceShow }] = useModal();
97 const [registerInvoiceDetail, { openDrawer: openCheckDetail }] = useDrawer(); 100 const [registerInvoiceDetail, { openDrawer: openCheckDetail }] = useDrawer();
98 const checkedKeys = ref<Array<string | number>>([]); 101 const checkedKeys = ref<Array<string | number>>([]);
@@ -110,7 +113,7 @@ @@ -110,7 +113,7 @@
110 clickToRowSelect: false, 113 clickToRowSelect: false,
111 rowKey: 'id', 114 rowKey: 'id',
112 pagination: { 115 pagination: {
113 - pageSize: 20, 116 + pageSize: 10,
114 }, 117 },
115 rowSelection: { 118 rowSelection: {
116 type: 'checkbox', 119 type: 'checkbox',
@@ -136,117 +139,6 @@ @@ -136,117 +139,6 @@
136 // slots: { customRender: 'action' }, 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 type CustomerCodeEntry = [string, number]; // 定义二维数组类型 [customerCode, count] 143 type CustomerCodeEntry = [string, number]; // 定义二维数组类型 [customerCode, count]
252 type ProductionDepartmentEntry = [string, number]; // 定义二维数组类型 [productionDepartment, count] 144 type ProductionDepartmentEntry = [string, number]; // 定义二维数组类型 [productionDepartment, count]
@@ -429,17 +321,17 @@ @@ -429,17 +321,17 @@
429 }); 321 });
430 } 322 }
431 function handleCommit(record) { 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 const { createMessage } = useMessage(); 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,7 +51,7 @@
51 const emit = defineEmits(['success']); 51 const emit = defineEmits(['success']);
52 const fileList = ref<UploadProps['fileList']>([]); 52 const fileList = ref<UploadProps['fileList']>([]);
53 53
54 - const input1 = ref(); 54 + const input1 = ref(0);
55 const deductUrl = ref(); 55 const deductUrl = ref();
56 const id = ref(); 56 const id = ref();
57 const invoiceNo = ref(); 57 const invoiceNo = ref();
@@ -85,31 +85,33 @@ @@ -85,31 +85,33 @@
85 updateDeductUrl.value = uploadUrl.value + info.name; 85 updateDeductUrl.value = uploadUrl.value + info.name;
86 } 86 }
87 function handleShow() { 87 function handleShow() {
88 - input1.value = ''; 88 + // if (!visible) {
  89 + input1.value = 0;
89 deductUrl.value = ''; 90 deductUrl.value = '';
90 updateDeductUrl.value = ''; 91 updateDeductUrl.value = '';
91 fileList.value = []; 92 fileList.value = [];
  93 + // }
  94 + // input1.value = '';
  95 + // deductUrl.value = '';
  96 + // updateDeductUrl.value = '';
  97 + // fileList.value = [];
92 } 98 }
93 99
94 //完成编辑 100 //完成编辑
95 async function handleSubmit() { 101 async function handleSubmit() {
96 console.log(input1.value, '5656', deductUrl.value); 102 console.log(input1.value, '5656', deductUrl.value);
97 - if (!input1.value || deductUrl.value == '') { 103 + if (!input1.value) {
98 error('选项不能为空'); 104 error('选项不能为空');
99 } else { 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 </script> 117 </script>
src/views/project/finance/receive/index.vue
@@ -13,6 +13,8 @@ @@ -13,6 +13,8 @@
13 <TrackEdit @register="registerTrackEdit" @success="handleSuccess" /> 13 <TrackEdit @register="registerTrackEdit" @success="handleSuccess" />
14 <InvoiceDetail @register="registerInvoiceDetail" /> 14 <InvoiceDetail @register="registerInvoiceDetail" />
15 <DeductShow @register="registerDeductShow" /> 15 <DeductShow @register="registerDeductShow" />
  16 + <Commit @register="registerCommit" />
  17 + <ReUploadBgUrl @register="registerReUploadBgUrl" />
16 </template> 18 </template>
17 <template #bodyCell="{ column, record }"> 19 <template #bodyCell="{ column, record }">
18 <template v-if="column.key === 'action'"> 20 <template v-if="column.key === 'action'">
@@ -28,12 +30,12 @@ @@ -28,12 +30,12 @@
28 }, 30 },
29 { 31 {
30 label: '提交审核', 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 :dropDownActions="[ 41 :dropDownActions="[
@@ -42,6 +44,10 @@ @@ -42,6 +44,10 @@
42 onClick: handleInvoiceDetail.bind(null, record), 44 onClick: handleInvoiceDetail.bind(null, record),
43 }, 45 },
44 { 46 {
  47 + label: '更新报关单',
  48 + onClick: handleReUploadBgUrl.bind(null, record),
  49 + },
  50 + {
45 label: '删除', 51 label: '删除',
46 popConfirm: { 52 popConfirm: {
47 title: '是否确认删除', 53 title: '是否确认删除',
@@ -70,6 +76,8 @@ @@ -70,6 +76,8 @@
70 import InvoiceAnalysis from './InvoiceAnalysis.vue'; 76 import InvoiceAnalysis from './InvoiceAnalysis.vue';
71 import InvoiceDetail from './InvoiceDetail.vue'; 77 import InvoiceDetail from './InvoiceDetail.vue';
72 import DeductShow from './DeductShow.vue'; 78 import DeductShow from './DeductShow.vue';
  79 + import Commit from './Commit.vue';
  80 + import ReUploadBgUrl from './ReUploadBgUrl.vue';
73 import { useDrawer } from '/@/components/Drawer'; 81 import { useDrawer } from '/@/components/Drawer';
74 import { getInvoice, deleteInvoice, commit, getBaseInvoice } from '@/api/project/invoice'; 82 import { getInvoice, deleteInvoice, commit, getBaseInvoice } from '@/api/project/invoice';
75 import { useModal } from '/@/components/Modal'; 83 import { useModal } from '/@/components/Modal';
@@ -84,6 +92,8 @@ @@ -84,6 +92,8 @@
84 const [registerFinanceEdit, { openDrawer: openFinanceEdit }] = useDrawer(); 92 const [registerFinanceEdit, { openDrawer: openFinanceEdit }] = useDrawer();
85 const [registerTrackEdit, { openDrawer: openTrackEdit }] = useDrawer(); 93 const [registerTrackEdit, { openDrawer: openTrackEdit }] = useDrawer();
86 const [registerInvoiceDetail, { openDrawer: openInvoiceDetail }] = useDrawer(); 94 const [registerInvoiceDetail, { openDrawer: openInvoiceDetail }] = useDrawer();
  95 + const [registerCommit, { openModal: openCommit }] = useModal();
  96 + const [registerReUploadBgUrl, { openModal: openReUploadBgUrl }] = useModal();
87 const [registerDeductShow, { openModal: openDeductShow }] = useModal(); 97 const [registerDeductShow, { openModal: openDeductShow }] = useModal();
88 const checkedKeys = ref<Array<string | number>>([]); 98 const checkedKeys = ref<Array<string | number>>([]);
89 const userStore = useUserStoreWithOut(); 99 const userStore = useUserStoreWithOut();
@@ -109,9 +119,6 @@ @@ -109,9 +119,6 @@
109 schemas: searchFormSchema, 119 schemas: searchFormSchema,
110 autoSubmitOnEnter: true, 120 autoSubmitOnEnter: true,
111 }, 121 },
112 - pagination: {  
113 - pageSize: 20,  
114 - },  
115 useSearchForm: true, 122 useSearchForm: true,
116 showTableSetting: true, 123 showTableSetting: true,
117 showIndexColumn: false, 124 showIndexColumn: false,
@@ -240,23 +247,31 @@ @@ -240,23 +247,31 @@
240 }); 247 });
241 } 248 }
242 function handleCommit(record) { 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 function handleInvoiceDetail(record) { 265 function handleInvoiceDetail(record) {
256 openInvoiceDetail(true, { 266 openInvoiceDetail(true, {
257 data: record, 267 data: record,
258 }); 268 });
259 } 269 }
  270 + function handleReUploadBgUrl(record) {
  271 + openReUploadBgUrl(true, {
  272 + data: record,
  273 + });
  274 + }
260 const { createMessage } = useMessage(); 275 const { createMessage } = useMessage();
261 const { error } = createMessage; 276 const { error } = createMessage;
262 function handleInvoiceAnalysis(record) { 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,6 +4,7 @@ import { icon } from &#39;ant-design-vue&#39;;
4 import { FilePptOutlined } from '@ant-design/icons-vue'; 4 import { FilePptOutlined } from '@ant-design/icons-vue';
5 import { size } from 'lodash-es'; 5 import { size } from 'lodash-es';
6 import { ref } from 'vue'; 6 import { ref } from 'vue';
  7 +import { view } from '@/utils/pdfShow';
7 8
8 export const searchFormSchema: FormSchema[] = [ 9 export const searchFormSchema: FormSchema[] = [
9 { 10 {
@@ -49,7 +50,7 @@ export const columns: BasicColumn[] = [ @@ -49,7 +50,7 @@ export const columns: BasicColumn[] = [
49 width: 80, 50 width: 80,
50 customRender: (column) => { 51 customRender: (column) => {
51 const bgUrl = column.record.bgUrl; 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,4 +157,5 @@ export interface GlobEnvConfig {
157 VITE_GLOB_API_URL_PREFIX?: string; 157 VITE_GLOB_API_URL_PREFIX?: string;
158 // Upload url 158 // Upload url
159 VITE_GLOB_UPLOAD_URL?: string; 159 VITE_GLOB_UPLOAD_URL?: string;
  160 + VITE_ALIYUN_OSS_DOMAIN?: string;
160 } 161 }
vite.config.ts
1 import { defineApplicationConfig } from '@vben/vite-config'; 1 import { defineApplicationConfig } from '@vben/vite-config';
  2 +import { getAppEnvConfig } from '/@/utils/env';
2 3
  4 +// const { VITE_ALIYUN_OSS_DOMAIN } = getAppEnvConfig();
3 export default defineApplicationConfig({ 5 export default defineApplicationConfig({
4 overrides: { 6 overrides: {
5 // build: { 7 // build: {
@@ -19,6 +21,14 @@ export default defineApplicationConfig({ @@ -19,6 +21,14 @@ export default defineApplicationConfig({
19 }, 21 },
20 server: { 22 server: {
21 proxy: { 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 '/basic-api/order': { 32 '/basic-api/order': {
23 target: 'http://47.104.8.35:18001', 33 target: 'http://47.104.8.35:18001',
24 // target: 'http://localhost:8001', 34 // target: 'http://localhost:8001',