Commit 54f173388c23554790a6d3dcccca3b3b2d8eb1fe

Authored by boyang
1 parent 35752d89

合并应付应收

Showing 49 changed files with 4461 additions and 66 deletions

Too many changes to show.

To preserve performance only 49 of 59 files are displayed.

src/api/project/global.ts
... ... @@ -12,6 +12,5 @@ export const getApiData = async () => {
12 12  
13 13 export const getChartData = async () => {
14 14 const res = await defHttp.get<any>({ url: Api.CHART_DATA });
15   - console.log(res, '5656reschatdata');
16 15 return res;
17 16 };
... ...
src/api/project/invoice.ts
... ... @@ -16,6 +16,7 @@ enum Api {
16 16 REUPLOADBGURL = '/order/erp/invoice_bill/reUploadBgUrl', //更新报关单
17 17 INVOICEEXPORTRECEIPT = '/order/erp/invoice_bill/exportReceipt', //收款单导出
18 18 SETBACKREFUNDDATE = '/order/erp/invoice_bill/setBackRefundDate', //必须回款日期
  19 + NOTE = '/order/erp/invoice_bill/notes', //备注
19 20  
20 21 PRODUCT_CREATE = '/order/erp/check_bill/create', //创建生产科应付单据
21 22 PAYED_DATE = '/order/erp/check_bill/get_payed_date', //获取生产科应回款日期
... ... @@ -32,6 +33,7 @@ enum Api {
32 33 GETINVOICEURL_BY_ID = '/order/erp/check_bill/getInvoiceUrl_by_id', //获取扣款信息
33 34 EXPORTRECEIPT = '/order/erp/check_bill/exportReceipt', //付款单导出
34 35 SETPADYEDDATE = '/order/erp/check_bill/setPayedDate', //修改应付款日期
  36 + CHECKNOTE = '/order/erp/check_bill/notes', //备注
35 37 }
36 38  
37 39 export const getRefundDate = async (params: any, data?: any) => {
... ... @@ -266,3 +268,17 @@ export const getSetPayedDate = async (params: any) =&gt; {
266 268 params,
267 269 });
268 270 };
  271 +
  272 +export const getInvoiceNote = async (params: any) => {
  273 + return await defHttp.post<any>({
  274 + url: Api.NOTE,
  275 + params,
  276 + });
  277 +};
  278 +
  279 +export const getCheckNote = async (params: any) => {
  280 + return await defHttp.post<any>({
  281 + url: Api.CHECKNOTE,
  282 + params,
  283 + });
  284 +};
... ...
src/router/routes/modules/project/finance.ts
... ... @@ -8,8 +8,9 @@ const finance: AppRouteModule = {
8 8 path: '/finance',
9 9 name: 'Finance',
10 10 component: LAYOUT,
11   - redirect: '/finance/receive',
  11 + redirect: '/finance',
12 12 meta: {
  13 + hideChildrenInMenu: true,
13 14 orderNo: 3,
14 15 icon: 'ant-design:pay-circle-outlined',
15 16 title: '财务管理',
... ... @@ -23,32 +24,42 @@ const finance: AppRouteModule = {
23 24 },
24 25 children: [
25 26 {
26   - path: 'receive',
  27 + path: '',
27 28 name: 'Receive',
28 29 meta: {
29   - title: '应收款',
  30 + title: '财务管理',
30 31 roles: [RoleEnum.ADMIN, RoleEnum.FINANCE, RoleEnum.TRACKER, RoleEnum.BUSINESS],
31 32 ignoreKeepAlive: false,
32 33 },
33   - component: () => import('/@/views/project/finance/receive/index.vue'),
34   - },
35   - {
36   - path: 'pay',
37   - name: 'Pay',
38   - meta: {
39   - title: '应付款',
40   - ignoreKeepAlive: true,
41   - roles: [
42   - RoleEnum.ADMIN,
43   - RoleEnum.FINANCE,
44   - RoleEnum.TRACKER,
45   - RoleEnum.BUSINESS,
46   - RoleEnum.PRODUCE,
47   - RoleEnum.DATA_REPORT_USER,
48   - ],
49   - },
50   - component: () => import('/@/views/project/finance/pay/index.vue'),
  34 + component: () => import('/@/views/project/finance/index.vue'),
51 35 },
  36 + // {
  37 + // path: 'receive',
  38 + // name: 'Receive',
  39 + // meta: {
  40 + // title: '应收款',
  41 + // roles: [RoleEnum.ADMIN, RoleEnum.FINANCE, RoleEnum.TRACKER, RoleEnum.BUSINESS],
  42 + // ignoreKeepAlive: false,
  43 + // },
  44 + // component: () => import('/@/views/project/finance/receive/index.vue'),
  45 + // },
  46 + // {
  47 + // path: 'pay',
  48 + // name: 'Pay',
  49 + // meta: {
  50 + // title: '应付款',
  51 + // ignoreKeepAlive: true,
  52 + // roles: [
  53 + // RoleEnum.ADMIN,
  54 + // RoleEnum.FINANCE,
  55 + // RoleEnum.TRACKER,
  56 + // RoleEnum.BUSINESS,
  57 + // RoleEnum.PRODUCE,
  58 + // RoleEnum.DATA_REPORT_USER,
  59 + // ],
  60 + // },
  61 + // component: () => import('/@/views/project/finance/pay/index.vue'),
  62 + // },
52 63 ],
53 64 };
54 65  
... ...
src/store/modules/data.ts
... ... @@ -50,7 +50,6 @@ export const useDataStore = defineStore({
50 50 async getFetchChartData(): Promise<any> {
51 51 try {
52 52 const data = await getChartData();
53   - console.log(data, '5656chartData');
54 53 const x = [],
55 54 y = [];
56 55 data.forEach((value) => {
... ... @@ -58,7 +57,6 @@ export const useDataStore = defineStore({
58 57 y.push(value.orderCount);
59 58 });
60 59 this.chartData = { x, y };
61   - console.log(this.getChartData, '5656 this.chartData');
62 60 } catch (error) {
63 61 return Promise.reject(error);
64 62 }
... ...
src/utils/pdfShow.ts
... ... @@ -27,7 +27,7 @@ export async function downloadAndPreviewPDF(url) {
27 27 export const view = (url) => {
28 28 const { VITE_ALIYUN_OSS_DOMAIN } = getAppEnvConfig();
29 29 if (url) {
30   - url = url.replace('https://test-alterego.oss-cn-qingdao.aliyuncs.com', '/aliyun-oss-pdf');
  30 + url = url.replace('https://alterego.oss-cn-qingdao.aliyuncs.com', '/aliyun-oss-pdf');
31 31 }
32 32 downloadAndPreviewPDF(url);
33 33 };
... ...
src/views/project/approve/FieldPanel.vue
... ... @@ -173,7 +173,7 @@
173 173 searchInfo: { type: 0 },
174 174 columns,
175 175 useSearchForm: true,
176   - formConfig: getFormConfig(true),
  176 + formConfig: getFormConfig('true'),
177 177 rowKey: 'id',
178 178 actionColumn: {
179 179 width: 160,
... ...
src/views/project/approve/PayPanel.vue
... ... @@ -6,8 +6,8 @@
6 6 <img
7 7 :width="50"
8 8 :height="50"
9   - :src="record?.orderBaseInfo?.smallPicUrl"
10   - @click="handlePreview(record?.orderBaseInfo?.picUrl)"
  9 + :src="record?.producePaymentCheckBillFieldVO?.smallPicUrl"
  10 + @click="handlePreview(record?.producePaymentCheckBillFieldVO?.picUrl)"
11 11 />
12 12 </template>
13 13 <template v-if="column.key === 'action'">
... ... @@ -229,9 +229,9 @@
229 229 customRender: (column) => {
230 230 const { record } = column || {};
231 231 if (record?.type === 40) {
232   - return record?.fieldInfos?.checkBillOrderDO?.financePerson;
  232 + return record?.fieldInfos?.producePaymentCheckBillFieldVO?.financePerson;
233 233 } else if (record?.type == 50) {
234   - return record?.fieldInfos?.checkBillOrderDO?.productionName;
  234 + return record?.fieldInfos?.producePaymentCheckBillFieldVO?.productionName;
235 235 }
236 236 },
237 237 },
... ... @@ -241,7 +241,13 @@
241 241 width: 150,
242 242 customRender: (column) => {
243 243 const { record } = column || {};
244   - return record?.orderBaseInfo?.innerNo;
  244 + console.log(record, '565656565');
  245 + const extractedValues = ref<string[]>(
  246 + record?.fieldInfos?.producePaymentCheckBillFieldVO?.innerNo.map((item) => item),
  247 + );
  248 + // projectNo.value = extractedValues.value.join(',');
  249 + // return record?.fieldInfos?.producePaymentCheckBillFieldVO?.innerNo[0];
  250 + return extractedValues.value.join(',');
245 251 },
246 252 },
247 253 {
... ... @@ -263,7 +269,7 @@
263 269 width: 150,
264 270 customRender: (column) => {
265 271 const { record } = column || {};
266   - return record?.fieldInfos?.checkBillOrderDO?.productionName;
  272 + return record?.fieldInfos?.producePaymentCheckBillFieldVO?.productionName;
267 273 },
268 274 },
269 275 ];
... ... @@ -292,7 +298,7 @@
292 298 // },
293 299 columns,
294 300 useSearchForm: true,
295   - formConfig: getFormConfig(),
  301 + formConfig: getFormConfig('checkNo'),
296 302 rowKey: 'id',
297 303 actionColumn: {
298 304 width: 160,
... ... @@ -334,7 +340,7 @@
334 340 openModal(true, { data });
335 341 id.value = data.id;
336 342 itemArray.value = [];
337   - mockData.value = data.fieldInfos.checkBillOrderDO;
  343 + mockData.value = data.fieldInfos.producePaymentCheckBillFieldVO;
338 344 actualPayCalculate.value = mockData.value.actualPayCalculate?.toFixed(2); // 实际付款金额计算
339 345 checkNo.value = mockData.value.checkNo; // 对账单号
340 346 actualPayedAmount.value = mockData.value.actualPayedAmount?.toFixed(2); // 实际应付金额
... ...
src/views/project/approve/ReceivePanel.vue
... ... @@ -6,8 +6,8 @@
6 6 <img
7 7 :width="50"
8 8 :height="50"
9   - :src="record?.orderBaseInfo?.smallPicUrl"
10   - @click="handlePreview(record?.orderBaseInfo?.picUrl)"
  9 + :src="record?.invoiceFieldVo?.smallPicUrl"
  10 + @click="handlePreview(record?.invoiceFieldVo?.picUrl)"
11 11 />
12 12 </template>
13 13 <template v-if="column.key === 'action'">
... ... @@ -209,7 +209,7 @@
209 209 width: 150,
210 210 customRender: (column) => {
211 211 const { record } = column || {};
212   - return record?.fieldInfos?.invoiceBillOrderDO?.invoiceNo;
  212 + return record?.fieldInfos?.invoiceFieldVO?.invoiceNo;
213 213 },
214 214 },
215 215 {
... ... @@ -218,18 +218,13 @@
218 218 width: 150,
219 219 customRender: (column) => {
220 220 const { record } = column || {};
221   - return record?.orderBaseInfo?.innerNo;
  221 + const extractedValues = ref<string[]>(
  222 + record?.fieldInfos?.invoiceFieldVO?.innerNo?.map((item) => item),
  223 + );
  224 + // return record?.invoiceFieldVo?.innerNo;
  225 + return extractedValues?.value?.join(',');
222 226 },
223 227 },
224   - // {
225   - // title: '内部编号',
226   - // dataIndex: 'innerNo',
227   - // width: 150,
228   - // customRender: (column) => {
229   - // const { record } = column || {};
230   - // return record?.fieldInfos?.invoiceBillOrderDO?.innerNo;
231   - // },
232   - // },
233 228 ];
234 229  
235 230 if (props.isApproved) {
... ... @@ -256,7 +251,7 @@
256 251 // },
257 252 columns,
258 253 useSearchForm: true,
259   - formConfig: getFormConfig(),
  254 + formConfig: getFormConfig('invoiceNo'),
260 255 rowKey: 'id',
261 256 actionColumn: {
262 257 width: 160,
... ... @@ -274,7 +269,7 @@
274 269 }
275 270 }
276 271 function onSelectAll(selected, selectedRows, changeRows) {
277   - const changeIds = changeRows.map((item) => item.id);
  272 + const changeIds = changeRows?.map((item) => item.id);
278 273 if (selected) {
279 274 checkedKeys.value = [...checkedKeys.value, ...changeIds];
280 275 } else {
... ... @@ -292,7 +287,7 @@
292 287  
293 288 async function handleDetail(data) {
294 289 openModal(true, { data });
295   - mockData.value = data.fieldInfos.invoiceBillOrderDO;
  290 + mockData.value = data.fieldInfos.invoiceFieldVO;
296 291 id.value = data.id;
297 292 totalPayAmount.value = mockData.value.totalPayAmount?.toFixed(2);
298 293 totalCustomerAmount.value = mockData.value.totalCustomerAmount?.toFixed(2);
... ...
src/views/project/approve/data.ts
1 1 import { ref } from 'vue';
2 2 import { queryNoOptions } from '../../../api/project/order';
3 3  
4   -export function getFormConfig(showFieldConfig: boolean) {
  4 +export function getFormConfig(showFieldConfig: string) {
5 5 const innerNoOptions = ref([]);
6 6 return {
7 7 labelWidth: 100,
... ... @@ -9,21 +9,21 @@ export function getFormConfig(showFieldConfig: boolean) {
9 9 {
10 10 field: `innerNo`,
11 11 label: `内部编号`,
12   - component: 'Select',
  12 + component: 'Input',
13 13 colProps: {
14 14 span: 6,
15 15 },
16 16 labelWidth: 70,
17   - componentProps: {
18   - options: innerNoOptions,
19   - showSearch: true,
20   - mode: 'multiple',
21   - onSearch: async (value: any) => {
22   - innerNoOptions.value = await queryNoOptions('innerNo', value);
23   - },
24   - },
  17 + // componentProps: {
  18 + // options: innerNoOptions,
  19 + // showSearch: true,
  20 + // mode: 'multiple',
  21 + // onSearch: async (value: any) => {
  22 + // innerNoOptions.value = await queryNoOptions('innerNo', value);
  23 + // },
  24 + // },
25 25 },
26   - ...(showFieldConfig
  26 + ...(showFieldConfig == 'true'
27 27 ? [
28 28 {
29 29 field: `auditType`,
... ... @@ -42,6 +42,32 @@ export function getFormConfig(showFieldConfig: boolean) {
42 42 },
43 43 ]
44 44 : []),
  45 + ...(showFieldConfig == 'invoiceNo'
  46 + ? [
  47 + {
  48 + field: `invoiceNo`,
  49 + label: `invoice编号`,
  50 + component: 'Input',
  51 + colProps: {
  52 + span: 6,
  53 + },
  54 + labelWidth: 140,
  55 + },
  56 + ]
  57 + : []),
  58 + ...(showFieldConfig == 'checkNo'
  59 + ? [
  60 + {
  61 + field: `checkNo`,
  62 + label: `checkNo编号`,
  63 + component: 'Input',
  64 + colProps: {
  65 + span: 6,
  66 + },
  67 + labelWidth: 140,
  68 + },
  69 + ]
  70 + : []),
45 71 ],
46 72 };
47 73 }
... ...
src/views/project/finance/CheckDetailCheck.vue 0 → 100644
  1 +<template>
  2 + <template>
  3 + <BasicDrawer
  4 + @register="register"
  5 + v-bind="$attrs"
  6 + title="订单信息"
  7 + width="60%"
  8 + :isDetail="true"
  9 + :showDetailBack="false"
  10 + :destroyOnClose="true"
  11 + >
  12 + <div class="p-4">
  13 + <BasicTable @register="registerTable">
  14 + <template #bodyCell="{ column, record }">
  15 + <template v-if="column.key === 'action'"> </template>
  16 + <template v-if="column.key === 'picUrl'">
  17 + <img :z-index="100000" :width="50" :height="50" :src="record?.smallPicUrl" />
  18 + </template>
  19 + </template>
  20 + </BasicTable>
  21 + </div>
  22 + </BasicDrawer>
  23 + </template>
  24 +</template>
  25 +<script lang="ts" setup>
  26 + import { BasicDrawer, useDrawerInner } from '@/components/Drawer';
  27 + import { defineComponent, ref, computed, unref, toRaw, reactive } from 'vue';
  28 + import { BasicColumn, useTable, BasicTable, ColumnChangeParam } from '/@/components/Table';
  29 + import { checkDetail } from '/@/api/project/invoice';
  30 + import { useDesign } from '@/hooks/web/useDesign';
  31 +
  32 + // const handlePreview = (url) => {
  33 + // createImgPreview({ imageList: [url], defaultWidth: 500 });
  34 + // return false;
  35 + // };
  36 + const columns: BasicColumn[] = [
  37 + {
  38 + title: '客户编码',
  39 + dataIndex: 'customerCode',
  40 + width: 100,
  41 + },
  42 + {
  43 + title: '项目号',
  44 + dataIndex: 'projectNo',
  45 + width: 100,
  46 + },
  47 + {
  48 + title: '内部编码',
  49 + dataIndex: 'innerNo',
  50 + width: 100,
  51 + },
  52 + {
  53 + title: '客户po号',
  54 + dataIndex: 'customerPo',
  55 + width: 100,
  56 + },
  57 + {
  58 + title: '客户STYLE',
  59 + width: 150,
  60 + dataIndex: 'customerStyle',
  61 + },
  62 + {
  63 + title: 'Model(REFERENCE)',
  64 + width: 150,
  65 + dataIndex: 'modeleLo',
  66 + },
  67 + {
  68 + title: '订单图片',
  69 + width: 150,
  70 + dataIndex: 'picUrl',
  71 + },
  72 + {
  73 + title: '数量',
  74 + width: 150,
  75 + dataIndex: 'orderCount',
  76 + },
  77 + {
  78 + title: '生产科单价¥',
  79 + width: 150,
  80 + dataIndex: 'productionDepartmentPrice',
  81 + customRender: (column) => {
  82 + const { record } = column || {};
  83 + return record?.profitAnalysisInfo?.productionDepartmentPrice?.toFixed(2);
  84 + // ? `¥ ${record?.profitAnalysisInfo?.productionDepartmentPrice}`
  85 + // : '';
  86 + },
  87 + },
  88 + {
  89 + title: '生产科总价¥',
  90 + width: 150,
  91 + dataIndex: 'productionDepartmentTotalPrice',
  92 + customRender: (column) => {
  93 + const { record } = column || {};
  94 + return record?.profitAnalysisInfo?.productionDepartmentTotalPrice?.toFixed(2);
  95 + // ? `¥ ${record?.profitAnalysisInfo?.productionDepartmentTotalPrice}`
  96 + // : '';
  97 + },
  98 + },
  99 + ];
  100 + const checkNo = ref();
  101 +
  102 + const [register, { setDrawerProps, closeDrawer }] = useDrawerInner((data) => {
  103 + // 方式1
  104 + checkNo.value = data.data.checkNo;
  105 + // checkDetail({ checkNo: checkNo.value });
  106 + });
  107 + const params = ref({
  108 + checkNo: checkNo.value,
  109 + });
  110 + const [registerTable] = useTable({
  111 + api: () => {
  112 + const res = checkDetail({ checkNo: checkNo.value });
  113 + return res;
  114 + },
  115 + columns: columns,
  116 + bordered: true,
  117 + });
  118 +</script>
... ...
src/views/project/finance/CheckSumCheck.vue 0 → 100644
  1 +<template>
  2 + <BasicModal
  3 + v-bind="$attrs"
  4 + @register="register"
  5 + title="应付款汇总"
  6 + width="60%"
  7 + okText="导出"
  8 + :isDetail="true"
  9 + :showDetailBack="false"
  10 + @ok="handleOk"
  11 + @visible-change="handleShow"
  12 + >
  13 + <div class="p-4">
  14 + <BasicTable @register="registerTable">
  15 + <template #bodyCell="{ column, record }">
  16 + <template v-if="column.key === 'action'"> </template>
  17 + </template>
  18 + </BasicTable>
  19 + </div>
  20 + </BasicModal>
  21 +</template>
  22 +<script lang="ts" setup>
  23 + import { BasicModal, useModalInner } from '@/components/Modal';
  24 + import { computed, ref } from 'vue';
  25 + import { checkAnalysis, exportCheckAnalysis } from '@/api/project/invoice';
  26 + import { BasicColumn, useTable, BasicTable, ColumnChangeParam } from '/@/components/Table';
  27 + // 处理弹窗的确定按钮点击事件
  28 + import axios from 'axios';
  29 +
  30 + const columnsAnalysis: BasicColumn[] = [
  31 + {
  32 + title: '生产科名称',
  33 + dataIndex: 'productionDepartment',
  34 + width: 150,
  35 + customRender: (res) => {
  36 + return res.record.exportVOS[0].productionDepartment;
  37 + },
  38 + },
  39 + {
  40 + title: '生产科总价汇总¥',
  41 + dataIndex: 'checkProductionDepartmentTotalPrice',
  42 + width: 150,
  43 + customRender: (res) => {
  44 + return res.record.productionDepartmentTotalPrice.toFixed(2);
  45 + },
  46 + },
  47 + {
  48 + title: '生产科扣款金额汇总¥',
  49 + dataIndex: 'deductAmount',
  50 + width: 160,
  51 + customRender: (res) => {
  52 + return res.record.deductAmount.toFixed(2);
  53 + },
  54 + },
  55 + {
  56 + title: '生产科实际应付金额¥',
  57 + dataIndex: 'calculateActualPayedAmount',
  58 + width: 160,
  59 + customRender: (res) => {
  60 + return res.record.calculateActualPayedAmount.toFixed(2);
  61 + },
  62 + },
  63 + {
  64 + title: '实际付款金额汇总¥',
  65 + dataIndex: 'actualPayedAmount',
  66 + width: 160,
  67 + customRender: (res) => {
  68 + return res.record.actualPayedAmount.toFixed(2);
  69 + },
  70 + },
  71 + {
  72 + title: '未付金额¥',
  73 + dataIndex: 'unPayedAmount',
  74 + width: 150,
  75 + customRender: (res) => {
  76 + return res.record.unPayedAmount.toFixed(2);
  77 + },
  78 + },
  79 + ];
  80 + // const ids = ref<number[]>([]);
  81 + const ids = ref();
  82 + // const res = ref();
  83 +
  84 + const [register, { closeModal }] = useModalInner(async (data) => {
  85 + // ids.value = data.data;
  86 + ids.value = data.data;
  87 + setTimeout(() => {
  88 + reload();
  89 + }, 50);
  90 + });
  91 + const [registerTable, { reload }] = useTable({
  92 + // api: () => invoiceAnalysis({ ids: ids.value }),
  93 + api: async () => {
  94 + const res = await checkAnalysis({ ids: ids.value });
  95 + // 计算合计行
  96 + const sum = {
  97 + productionDepartmentTotalPrice: 0,
  98 + deductAmount: 0,
  99 + calculateActualPayedAmount: 0,
  100 + actualPayedAmount: 0,
  101 + unPayedAmount: 0,
  102 + exportVOS: res[0].exportVOS ? JSON.parse(JSON.stringify(res[0].exportVOS)) : [],
  103 + };
  104 +
  105 + res.forEach((item: any) => {
  106 + sum.productionDepartmentTotalPrice += item.productionDepartmentTotalPrice || 0;
  107 + sum.deductAmount += item.deductAmount || 0;
  108 + sum.calculateActualPayedAmount += item.calculateActualPayedAmount || 0;
  109 + sum.actualPayedAmount += item.actualPayedAmount || 0;
  110 + sum.unPayedAmount += item.unPayedAmount || 0;
  111 + });
  112 + if (sum.exportVOS && sum.exportVOS[0]) {
  113 + sum.exportVOS[0].productionDepartment = '合计';
  114 + }
  115 + res.push(sum);
  116 + return res;
  117 + },
  118 + columns: columnsAnalysis,
  119 + bordered: true,
  120 + });
  121 + function handleShow(visible: boolean) {
  122 + reload();
  123 + }
  124 + const searchData = ref({});
  125 + async function handleOk() {
  126 + // 构造符合 API 要求的参数
  127 + // const ids = [23];
  128 + // const requestData = {
  129 + // ids: ids.value,
  130 + // };
  131 + const idss = ids.value;
  132 + // await exportCheckAnalysis({ ids: ids });
  133 + axios
  134 + .post(
  135 + '/basic-api/order/erp/check_bill/export',
  136 + { ids: idss },
  137 + {
  138 + responseType: 'blob', // 设置响应类型为 'blob'
  139 + },
  140 + )
  141 + .then((response) => {
  142 + // 创建一个 Blob 对象来保存二进制数据
  143 + const blob = new Blob([response.data], { type: 'application/zip' });
  144 + const getFormattedDate = (): string => {
  145 + const date = new Date();
  146 +
  147 + const year = date.getFullYear();
  148 + const month = String(date.getMonth() + 1).padStart(2, '0');
  149 + const day = String(date.getDate()).padStart(2, '0');
  150 +
  151 + const hours = String(date.getHours()).padStart(2, '0');
  152 + const minutes = String(date.getMinutes()).padStart(2, '0');
  153 + const seconds = String(date.getSeconds()).padStart(2, '0');
  154 +
  155 + return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
  156 + };
  157 + const date = getFormattedDate();
  158 + // 创建一个链接元素用于下载
  159 + const link = document.createElement('a');
  160 + link.href = window.URL.createObjectURL(blob);
  161 + link.download = `应付款分析${date}.xlsx`; // 你可以为文件命名
  162 + document.body.appendChild(link);
  163 + link.click(); // 自动点击链接,触发下载
  164 + document.body.removeChild(link); // 下载完成后移除链接
  165 + })
  166 + .catch((error) => {
  167 + console.error(error);
  168 + });
  169 + reload();
  170 + closeModal();
  171 + }
  172 +</script>
  173 +<style scoped>
  174 + .divAll {
  175 + display: flex;
  176 + justify-content: center;
  177 + align-items: center;
  178 + }
  179 +</style>
... ...
src/views/project/finance/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 + @visible-change="handleShow"
  10 + >
  11 + 请选择日期:
  12 + <a-date-picker v-model:value="date" />
  13 + <div style="height: 10px"></div>
  14 + 请选择收款单位:
  15 + <a-select v-model:value="payee" style="width: 100%; padding: 5px; border-radius: 4px">
  16 + <option value="翱特建行城阳支行-美元(5107)">翱特建行城阳支行-美元(5107)</option>
  17 + <option value="吉庆建行城阳支行-美元(4820)">吉庆建行城阳支行-美元(4820)</option>
  18 + </a-select>
  19 + </BasicModal>
  20 +</template>
  21 +<script lang="ts" setup>
  22 + import { BasicModal, useModalInner } from '@/components/Modal';
  23 + import { ref } from 'vue';
  24 + import { commit } from '@/api/project/invoice';
  25 + import { useMessage } from '/@/hooks/web/useMessage';
  26 +
  27 + const id = ref();
  28 + const payee = ref();
  29 + const date = ref();
  30 + const emit = defineEmits(['success']);
  31 + const { createMessage } = useMessage();
  32 + const { error } = createMessage;
  33 + const [register, { closeModal }] = useModalInner(async (data) => {
  34 + // id.value = data.checkedKeys;
  35 + id.value = data.data;
  36 + });
  37 + function handleShow(visible: boolean) {
  38 + if (!visible) {
  39 + date.value = null;
  40 + payee.value = null;
  41 + }
  42 + }
  43 + function formatDate(input: string): string {
  44 + // 创建一个 Date 对象
  45 + const date = new Date(input);
  46 +
  47 + // 获取年月日
  48 + const year = date.getFullYear();
  49 + const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份从 0 开始,所以要加 1
  50 + const day = String(date.getDate()).padStart(2, '0');
  51 +
  52 + // 返回格式化后的日期字符串
  53 + return `${year}-${month}-${day}`;
  54 + }
  55 + const isDisabled = ref(false);
  56 + async function handleOk() {
  57 + if (isDisabled.value) {
  58 + error('请勿连续点击生成按钮,需要等待三秒再点击生成');
  59 + return;
  60 + }
  61 + const formattedDate = formatDate(date.value);
  62 + isDisabled.value = true;
  63 + setTimeout(() => {
  64 + isDisabled.value = false;
  65 + }, 3000);
  66 + commit({ id: id.value, actualRefundDate: formattedDate, payee: payee.value });
  67 + emit('success');
  68 + closeModal();
  69 + }
  70 +</script>
... ...
src/views/project/finance/CommitCheck.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 + @visible-change="handleShow"
  10 + >
  11 + 请选择日期:
  12 + <a-date-picker v-model:value="date" />
  13 + </BasicModal>
  14 +</template>
  15 +<script lang="ts" setup>
  16 + import { BasicModal, useModalInner } from '@/components/Modal';
  17 + import { ref } from 'vue';
  18 + import { checkCommit } from '@/api/project/invoice';
  19 + import { useMessage } from '/@/hooks/web/useMessage';
  20 +
  21 + const id = ref();
  22 + const date = ref();
  23 + const emit = defineEmits(['success']);
  24 + const { createMessage } = useMessage();
  25 + const { error } = createMessage;
  26 + const [register, { closeModal }] = useModalInner(async (data) => {
  27 + id.value = data.data;
  28 + });
  29 + function handleShow(visible: boolean) {
  30 + if (!visible) {
  31 + date.value = null;
  32 + }
  33 + }
  34 + function formatDate(input: string): string {
  35 + // 创建一个 Date 对象
  36 + const date = new Date(input);
  37 +
  38 + // 获取年月日
  39 + const year = date.getFullYear();
  40 + const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份从 0 开始,所以要加 1
  41 + const day = String(date.getDate()).padStart(2, '0');
  42 +
  43 + // 返回格式化后的日期字符串
  44 + return `${year}-${month}-${day}`;
  45 + }
  46 + const isDisabled = ref(false);
  47 + async function handleOk() {
  48 + if (isDisabled.value) {
  49 + error('请勿连续点击生成按钮,需要等待三秒再点击生成');
  50 + return;
  51 + }
  52 + const formattedDate = formatDate(date.value);
  53 + isDisabled.value = true;
  54 + setTimeout(() => {
  55 + isDisabled.value = false;
  56 + }, 3000);
  57 + checkCommit({ id: id.value, actualPayedDate: formattedDate });
  58 + emit('success');
  59 + closeModal();
  60 + }
  61 +</script>
... ...
src/views/project/finance/DeductShow.vue 0 → 100644
  1 +<template>
  2 + <BasicModal
  3 + v-bind="$attrs"
  4 + @register="register"
  5 + title="扣款单"
  6 + width="700px"
  7 + :bodyStyle="{ height: '240px' }"
  8 + @ok="handleOk"
  9 + >
  10 + <a-list item-layout="horizontal" :data-source="itemArray">
  11 + <template #renderItem="{ item }">
  12 + <a-list-item>
  13 + <a-list-item-meta>
  14 + <template #title>
  15 + <!-- <a :href="item.url" target="_blank" rel="noopener noreferrer">{{ item.name }}</a> -->
  16 + <!-- <a @click="openPic(item.url)">{{ item.name }}</a> -->
  17 + <a
  18 + v-if="isImageUrl(item.url)"
  19 + @click="openPic(item.url)"
  20 + style="display: flex; align-items: center"
  21 + >
  22 + <img
  23 + :src="item.url"
  24 + alt="Image"
  25 + style="max-width: 150px; max-height: 150px; margin-right: 10px"
  26 + />
  27 + {{ item.name }}
  28 + </a>
  29 + <a v-else @click="openPic(item.url)">{{ item.name }}</a>
  30 + </template>
  31 + </a-list-item-meta>
  32 + </a-list-item>
  33 + </template>
  34 + </a-list>
  35 + </BasicModal>
  36 +</template>
  37 +<script lang="ts" setup>
  38 + import { BasicModal, useModalInner } from '@/components/Modal';
  39 + import { computed, ref } from 'vue';
  40 + import type { UploadProps, UploadChangeParam } from 'ant-design-vue';
  41 + import { InboxOutlined } from '@ant-design/icons-vue';
  42 + import { message } from 'ant-design-vue';
  43 + import { getInvoiceDeductUrlById } from '@/api/project/invoice';
  44 + import { view } from '@/utils/pdfShow';
  45 +
  46 + interface Item {
  47 + name: string;
  48 + url: string;
  49 + }
  50 +
  51 + const list = ref();
  52 + const id = ref();
  53 + const itemArray = ref<Item[]>([]);
  54 +
  55 + const [register, { closeModal }] = useModalInner(async (data) => {
  56 + itemArray.value = [];
  57 + const res = await getInvoiceDeductUrlById({ id: data.data.invoiceId });
  58 + for (let item in res) {
  59 + const url = res[item];
  60 + const name = item;
  61 + // 将 name 和 url 放入对象并添加到数组中
  62 + itemArray.value.push({ name, url });
  63 + }
  64 + });
  65 +
  66 + async function handleOk() {
  67 + itemArray.value = [];
  68 + closeModal();
  69 + }
  70 + // function openPic(url) {
  71 + // window.open('', '', '').document.write(`<!DOCTYPE html>
  72 + // <html>
  73 + // <body
  74 + // style="display: flex;
  75 + // justify-content: center;
  76 + // align-items: center;">
  77 + // <img src='${url}' width="500px" height="500px"/>
  78 + // </body>
  79 + // </html>`);
  80 + // }
  81 + // 新增的函数:判断 URL 是否为图片格式
  82 + function isImageUrl(url: string): boolean {
  83 + const imageExtensions = ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'svg'];
  84 + const baseUrl = url.split('?')[0];
  85 + return imageExtensions.some((ext) => baseUrl.toLowerCase().endsWith(ext));
  86 + }
  87 + // 检查 URL 是否为 PDF 格式
  88 + function isPdfUrl(url: string): boolean {
  89 + return url.toLowerCase().endsWith('.pdf');
  90 + }
  91 + // 打开图片或 PDF
  92 + function openPic(url: string) {
  93 + const baseUrl = url.split('?')[0]; // 获取问号前的部分
  94 + if (isImageUrl(baseUrl)) {
  95 + window.open('', '', '').document.write(`<!DOCTYPE html>
  96 + <html>
  97 + <body style="display: flex; justify-content: center; align-items: center;">
  98 + <img src='${url}' width="300px" height="auto"/>
  99 + </body>
  100 + </html>`);
  101 + } else if (isPdfUrl(baseUrl)) {
  102 + view(url); // 新标签页打开 PDF
  103 + } else {
  104 + console.log('不支持的文件类型');
  105 + }
  106 + }
  107 +</script>
... ...
src/views/project/finance/DeductShowCheck.vue 0 → 100644
  1 +<template>
  2 + <BasicModal
  3 + v-bind="$attrs"
  4 + @register="register"
  5 + title="扣款单"
  6 + width="700px"
  7 + :bodyStyle="{ height: '240px' }"
  8 + @ok="handleOk"
  9 + >
  10 + <a-list item-layout="horizontal" :data-source="itemArray">
  11 + <template #renderItem="{ item }">
  12 + <a-list-item>
  13 + <a-list-item-meta>
  14 + <template #title>
  15 + <!-- <a :href="item.url" target="_blank" rel="noopener noreferrer">{{ 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> -->
  30 + </template>
  31 + </a-list-item-meta>
  32 + </a-list-item>
  33 + </template>
  34 + </a-list>
  35 + </BasicModal>
  36 +</template>
  37 +<script lang="ts" setup>
  38 + import { BasicModal, useModalInner } from '@/components/Modal';
  39 + import { computed, ref } from 'vue';
  40 + import type { UploadProps, UploadChangeParam } from 'ant-design-vue';
  41 + import { InboxOutlined } from '@ant-design/icons-vue';
  42 + import { message } from 'ant-design-vue';
  43 + import { getDeductUrlById } from '@/api/project/invoice';
  44 + import { view } from '@/utils/pdfShow';
  45 +
  46 + interface Item {
  47 + name: string;
  48 + url: string;
  49 + }
  50 +
  51 + const list = ref();
  52 + const id = ref();
  53 + const itemArray = ref<Item[]>([]);
  54 +
  55 + const [register, { closeModal }] = useModalInner(async (data) => {
  56 + itemArray.value = [];
  57 + const res = await getDeductUrlById({ id: data.data.checkId });
  58 + for (let item in res) {
  59 + const url = res[item];
  60 + const name = item;
  61 + // 将 name 和 url 放入对象并添加到数组中
  62 + itemArray.value.push({ name, url });
  63 + }
  64 + });
  65 +
  66 + async function handleOk() {
  67 + itemArray.value = [];
  68 + closeModal();
  69 + }
  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 + // 检查 URL 是否为 PDF 格式
  78 + function isPdfUrl(url: string): boolean {
  79 + return url.toLowerCase().endsWith('.pdf');
  80 + }
  81 + // 打开图片或 PDF
  82 + function openPic(url: string) {
  83 + const baseUrl = url.split('?')[0]; // 获取问号前的部分
  84 + if (isImageUrl(baseUrl)) {
  85 + window.open('', '', '').document.write(`<!DOCTYPE html>
  86 + <html>
  87 + <body style="display: flex; justify-content: center; align-items: center;">
  88 + <img src='${url}' width="300px" height="auto"/>
  89 + </body>
  90 + </html>`);
  91 + } else if (isPdfUrl(baseUrl)) {
  92 + view(url); // 新标签页打开 PDF
  93 + } else {
  94 + console.log('不支持的文件类型');
  95 + }
  96 + }
  97 +</script>
... ...
src/views/project/finance/EditRefundTime.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 + @visible-change="handleShow"
  10 + >
  11 + 请选择日期:
  12 + <a-date-picker v-model:value="date" />
  13 + <div style="height: 10px"></div>
  14 + </BasicModal>
  15 +</template>
  16 +<script lang="ts" setup>
  17 + import { BasicModal, useModalInner } from '@/components/Modal';
  18 + import { ref } from 'vue';
  19 + import { getSetBackRefundDate } from '@/api/project/invoice';
  20 + import { useMessage } from '/@/hooks/web/useMessage';
  21 +
  22 + const id = ref();
  23 + const date = ref();
  24 + const emit = defineEmits(['success']);
  25 + const { createMessage } = useMessage();
  26 + const { error } = createMessage;
  27 + const [register, { closeModal }] = useModalInner(async (data) => {
  28 + id.value = data.data.invoiceId;
  29 + });
  30 + function formatDate(input: string): string {
  31 + // 创建一个 Date 对象
  32 + const date = new Date(input);
  33 +
  34 + // 获取年月日
  35 + const year = date.getFullYear();
  36 + const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份从 0 开始,所以要加 1
  37 + const day = String(date.getDate()).padStart(2, '0');
  38 +
  39 + // 返回格式化后的日期字符串
  40 + return `${year}-${month}-${day}`;
  41 + }
  42 + const isDisabled = ref(false);
  43 + async function handleOk() {
  44 + if (isDisabled.value) {
  45 + error('请勿连续点击生成按钮,需要等待三秒再点击生成');
  46 + return;
  47 + }
  48 + const formattedDate = formatDate(date.value);
  49 + isDisabled.value = true;
  50 + setTimeout(() => {
  51 + isDisabled.value = false;
  52 + }, 3000);
  53 + getSetBackRefundDate({ id: id.value, backRefundDate: formattedDate });
  54 + emit('success');
  55 + closeModal();
  56 + }
  57 + function handleShow(visible: boolean) {
  58 + if (!visible) {
  59 + date.value = null;
  60 + }
  61 + }
  62 +</script>
... ...
src/views/project/finance/EditRefundTimeCheck.vue 0 → 100644
  1 +<template>
  2 + <BasicModal
  3 + v-bind="$attrs"
  4 + @register="register"
  5 + title="修改应付款日期"
  6 + width="500px"
  7 + :bodyStyle="{ height: '240px' }"
  8 + @visible-change="handleShow"
  9 + @ok="handleOk"
  10 + >
  11 + 请选择日期:
  12 + <a-date-picker v-model:value="date" />
  13 + <div style="height: 10px"></div>
  14 + </BasicModal>
  15 +</template>
  16 +<script lang="ts" setup>
  17 + import { BasicModal, useModalInner } from '@/components/Modal';
  18 + import { ref } from 'vue';
  19 + import { getSetPayedDate } from '@/api/project/invoice';
  20 + import { useMessage } from '/@/hooks/web/useMessage';
  21 +
  22 + const id = ref();
  23 + const date = ref();
  24 + const emit = defineEmits(['success']);
  25 + const { createMessage } = useMessage();
  26 + const { error } = createMessage;
  27 + const [register, { closeModal }] = useModalInner(async (data) => {
  28 + id.value = data.data.checkId;
  29 + });
  30 + function formatDate(input: string): string {
  31 + // 创建一个 Date 对象
  32 + const date = new Date(input);
  33 +
  34 + // 获取年月日
  35 + const year = date.getFullYear();
  36 + const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份从 0 开始,所以要加 1
  37 + const day = String(date.getDate()).padStart(2, '0');
  38 +
  39 + // 返回格式化后的日期字符串
  40 + return `${year}-${month}-${day}`;
  41 + }
  42 + const isDisabled = ref(false);
  43 + async function handleOk() {
  44 + if (isDisabled.value) {
  45 + error('请勿连续点击生成按钮,需要等待三秒再点击生成');
  46 + return;
  47 + }
  48 + const formattedDate = formatDate(date.value);
  49 + isDisabled.value = true;
  50 + setTimeout(() => {
  51 + isDisabled.value = false;
  52 + }, 3000);
  53 + getSetPayedDate({ id: id.value, payedDate: formattedDate });
  54 + emit('success');
  55 + closeModal();
  56 + }
  57 + function handleShow(visible: boolean) {
  58 + if (!visible) {
  59 + date.value = null;
  60 + }
  61 + }
  62 +</script>
... ...
src/views/project/finance/FinanceEdit.vue 0 → 100644
  1 +<template>
  2 + <template>
  3 + <BasicDrawer
  4 + @register="register"
  5 + v-bind="$attrs"
  6 + title="收入款单"
  7 + width="30%"
  8 + :isDetail="true"
  9 + @ok="handleSubmit"
  10 + :showDetailBack="false"
  11 + okText="保存"
  12 + showFooter
  13 + :destroyOnClose="true"
  14 + >
  15 + <!-- <div>
  16 + <BasicForm @register="registerForm" />
  17 + </div> -->
  18 + <div style="font-size: 15px">实际收款金额1$</div>
  19 + <a-input v-model:value="input1" placeholder="请输入" :disabled="status === 10" auto-size />
  20 + <div style="margin: 16px 0"></div>
  21 + <div style="font-size: 15px">实际收款金额2$</div>
  22 + <a-input v-model:value="input2" placeholder="请输入" :disabled="status === 10" auto-size />
  23 + <div style="margin: 16px 0"></div>
  24 + <div style="font-size: 15px">实际收款金额3$</div>
  25 + <a-input v-model:value="input3" placeholder="请输入" :disabled="status === 10" auto-size />
  26 + <div style="margin: 16px 0"></div>
  27 + <div style="font-size: 15px">其他费用金额$</div>
  28 + <a-input v-model:value="input4" placeholder="请输入" :disabled="status === 10" auto-size />
  29 + <div style="margin: 16px 0"></div>
  30 +
  31 + <!-- <template #titleToolbar> <a-button type="primary"> 申请编辑权限 </a-button></template> -->
  32 + <template #appendFooter>
  33 + <!-- <a-button type="primary" @click="onGoCheckDetail"> 申请权限</a-button> -->
  34 + </template>
  35 + </BasicDrawer>
  36 + </template>
  37 +</template>
  38 +<script lang="ts" setup>
  39 + import { BasicDrawer, useDrawerInner } from '@/components/Drawer';
  40 + import { BasicForm, FormSchema, useForm } from '@/components/Form';
  41 + import { defineComponent, ref, computed, unref, toRaw, reactive } from 'vue';
  42 + import { getEmailList } from '/@/api/sys/config';
  43 + import { updateAmount } from '@/api/project/invoice';
  44 + import { useMessage } from '/@/hooks/web/useMessage';
  45 + import { ROLE } from './type.d';
  46 +
  47 + const emit = defineEmits(['success']);
  48 + const role = computed(() => {
  49 + return user?.roleSmallVO?.code;
  50 + });
  51 + const schemas: FormSchema[] = [
  52 + // {
  53 + // field: 'totalPayAmount',
  54 + // component: 'InputNumber',
  55 + // labelWidth: 250,
  56 + // colProps: {
  57 + // span: 23,
  58 + // },
  59 + // label: '实际应收金额',
  60 + // },
  61 + {
  62 + field: 'actualPayedAmount1',
  63 + component: 'InputNumber',
  64 + labelWidth: 250,
  65 + colProps: {
  66 + span: 23,
  67 + },
  68 + componentProps: () => ({
  69 + disabled: status.value === 10,
  70 + }),
  71 + label: '实际应收金额1$',
  72 + },
  73 + {
  74 + field: 'actualPayedAmount2',
  75 + component: 'InputNumber',
  76 + labelWidth: 250,
  77 + colProps: {
  78 + span: 23,
  79 + },
  80 + componentProps: () => ({
  81 + disabled: status.value === 10,
  82 + }),
  83 + label: '实际应收金额2$',
  84 + },
  85 + {
  86 + field: 'actualPayedAmount3',
  87 + component: 'InputNumber',
  88 + labelWidth: 250,
  89 + colProps: {
  90 + span: 23,
  91 + },
  92 + componentProps: () => ({
  93 + disabled: status.value === 10,
  94 + }),
  95 + label: '实际应收金额3$',
  96 + },
  97 + {
  98 + field: 'otherAmount',
  99 + component: 'InputNumber',
  100 + labelWidth: 250,
  101 + colProps: {
  102 + span: 23,
  103 + },
  104 + componentProps: () => ({
  105 + disabled: status.value === 10,
  106 + }),
  107 + label: '其他费用金额$',
  108 + },
  109 + ];
  110 + const [registerForm, { setFieldsValue, resetFields, validate }] = useForm({
  111 + labelWidth: 120,
  112 + schemas,
  113 + layout: 'vertical',
  114 + showActionButtonGroup: false,
  115 + actionColOptions: {
  116 + span: 24,
  117 + },
  118 + });
  119 + const { createMessage } = useMessage();
  120 + const { error } = createMessage;
  121 +
  122 + const update = ref();
  123 + const status = ref();
  124 +
  125 + const input1 = ref();
  126 + const input2 = ref();
  127 + const input3 = ref();
  128 + const input4 = ref();
  129 + const id = ref();
  130 + const [register, { setDrawerProps, closeDrawer }] = useDrawerInner((data) => {
  131 + // 方式1
  132 + status.value = data.data.invoiceStatus;
  133 + id.value = data.data.invoiceId;
  134 + input1.value = data.data.invoiceActualPayedAmount1;
  135 + input2.value = data.data.invoiceActualPayedAmount2;
  136 + input3.value = data.data.invoiceActualPayedAmount3;
  137 + input4.value = data.data.invoiceOtherAmount;
  138 + resetFields();
  139 + setDrawerProps({ confirmLoading: false });
  140 + setFieldsValue({
  141 + ...toRaw(data.data),
  142 + });
  143 + update.value = data;
  144 + });
  145 + //完成编辑
  146 + async function handleSubmit() {
  147 + // const values = await validate();
  148 + // const updatedValues = {
  149 + // ...values,
  150 + // id: update.value.data.id,
  151 + // bgUrl: update.value.data.bgUrl,
  152 + // };
  153 + if (!input1.value || !input2.value || !input3.value || !input4.value) {
  154 + error('选项不能为空');
  155 + } else {
  156 + await updateAmount({
  157 + id: id.value,
  158 + actualPayedAmount1: input1.value,
  159 + actualPayedAmount2: input2.value,
  160 + actualPayedAmount3: input3.value,
  161 + otherAmount: input4.value,
  162 + });
  163 + emit('success');
  164 + closeDrawer();
  165 + }
  166 + }
  167 +</script>
... ...
src/views/project/finance/FinanceEditCheck.vue 0 → 100644
  1 +<template>
  2 + <template>
  3 + <BasicDrawer
  4 + @register="register"
  5 + v-bind="$attrs"
  6 + title="编辑"
  7 + width="30%"
  8 + :isDetail="true"
  9 + @ok="handleSubmit"
  10 + :showDetailBack="false"
  11 + okText="保存"
  12 + showFooter
  13 + :destroyOnClose="true"
  14 + >
  15 + <!-- <div>
  16 + <BasicForm @register="registerForm" />
  17 + </div> -->
  18 + <div style="font-size: 15px">实际付款金额1¥</div>
  19 + <a-input v-model:value="input1" placeholder="请输入" :disabled="status === 10" auto-size />
  20 + <div style="margin: 16px 0"></div>
  21 + <div style="font-size: 15px">实际付款金额2¥</div>
  22 + <a-input v-model:value="input2" placeholder="请输入" :disabled="status === 10" auto-size />
  23 + <div style="margin: 16px 0"></div>
  24 + <div style="font-size: 15px">实际付款金额3¥</div>
  25 + <a-input v-model:value="input3" placeholder="请输入" :disabled="status === 10" auto-size />
  26 + <div style="margin: 16px 0"></div>
  27 +
  28 + <!-- <template #titleToolbar> <a-button type="primary"> 申请编辑权限 </a-button></template> -->
  29 + <template #appendFooter>
  30 + <!-- <a-button type="primary" @click="onGoCheckDetail"> 申请权限</a-button> -->
  31 + </template>
  32 + </BasicDrawer>
  33 + </template>
  34 +</template>
  35 +<script lang="ts" setup>
  36 + import { BasicDrawer, useDrawerInner } from '@/components/Drawer';
  37 + import { BasicForm, FormSchema, useForm } from '@/components/Form';
  38 + import { defineComponent, ref, computed, unref, toRaw, reactive } from 'vue';
  39 + import { getEmailList } from '/@/api/sys/config';
  40 + import { updateAmountInfo } from '@/api/project/invoice';
  41 + import { useMessage } from '/@/hooks/web/useMessage';
  42 +
  43 + const emit = defineEmits(['success']);
  44 + const schemas: FormSchema[] = [
  45 + // {
  46 + // field: 'actualPayedAmount',
  47 + // component: 'InputNumber',
  48 + // labelWidth: 250,
  49 + // colProps: {
  50 + // span: 23,
  51 + // },
  52 + // label: '生产科实际应付金额',
  53 + // },
  54 + {
  55 + field: 'actualPayedAmount1',
  56 + component: 'InputNumber',
  57 + labelWidth: 250,
  58 + colProps: {
  59 + span: 23,
  60 + },
  61 + label: '实际应付金额1¥',
  62 + componentProps: () => ({
  63 + disabled: status.value === 10,
  64 + }),
  65 + },
  66 + {
  67 + field: 'actualPayedAmount2',
  68 + component: 'InputNumber',
  69 + labelWidth: 250,
  70 + colProps: {
  71 + span: 23,
  72 + },
  73 + label: '实际应付金额2¥',
  74 + componentProps: () => ({
  75 + disabled: status.value === 10,
  76 + }),
  77 + },
  78 + {
  79 + field: 'actualPayedAmount3',
  80 + component: 'InputNumber',
  81 + labelWidth: 250,
  82 + colProps: {
  83 + span: 23,
  84 + },
  85 + label: '实际应付金额3¥',
  86 + componentProps: () => ({
  87 + disabled: status.value === 10,
  88 + }),
  89 + },
  90 + ];
  91 + const [registerForm, { setFieldsValue, resetFields, validate }] = useForm({
  92 + labelWidth: 120,
  93 + schemas,
  94 + layout: 'vertical',
  95 + showActionButtonGroup: false,
  96 + actionColOptions: {
  97 + span: 24,
  98 + },
  99 + });
  100 + const { createMessage } = useMessage();
  101 + const { error } = createMessage;
  102 + const update = ref();
  103 + const status = ref();
  104 + const input1 = ref();
  105 + const input2 = ref();
  106 + const input3 = ref();
  107 + const id = ref();
  108 + const [register, { setDrawerProps, closeDrawer }] = useDrawerInner((data) => {
  109 + // 方式1
  110 + resetFields();
  111 + status.value = data.data.checkStatus;
  112 + id.value = data.data.checkId;
  113 + input1.value = data.data.checkActualPayedAmount1;
  114 + input2.value = data.data.checkActualPayedAmount2;
  115 + input3.value = data.data.checkActualPayedAmount3;
  116 + setDrawerProps({ confirmLoading: false });
  117 + // 将金额格式化为两位小数
  118 + // setFieldsValue({
  119 + // actualPayedAmount1:
  120 + // data.data.actualPayedAmount1 !== null ? data.data.actualPayedAmount1.toFixed(2) : undefined,
  121 + // actualPayedAmount2:
  122 + // data.data.actualPayedAmount2 !== null ? data.data.actualPayedAmount2.toFixed(2) : undefined,
  123 + // actualPayedAmount3:
  124 + // data.data.actualPayedAmount3 !== null ? data.data.actualPayedAmount3.toFixed(2) : undefined,
  125 + // ...toRaw(data.data), // 其他字段
  126 + // });
  127 + setFieldsValue({
  128 + ...toRaw(data.data),
  129 + });
  130 + update.value = data;
  131 + });
  132 + //完成编辑
  133 + async function handleSubmit() {
  134 + // const values = await validate();
  135 + // const updatedValues = {
  136 + // ...values,
  137 + // id: update.value.data.id,
  138 + // };
  139 + if (!input1.value || !input2.value || !input3.value) {
  140 + error('选项不能为空');
  141 + } else {
  142 + await updateAmountInfo({
  143 + id: id.value,
  144 + actualPayedAmount1: input1.value,
  145 + actualPayedAmount2: input2.value,
  146 + actualPayedAmount3: input3.value,
  147 + });
  148 + emit('success');
  149 + closeDrawer();
  150 + }
  151 + }
  152 +</script>
... ...
src/views/project/finance/InvoiceAnalysis.vue 0 → 100644
  1 +<template>
  2 + <BasicModal
  3 + v-bind="$attrs"
  4 + @register="register"
  5 + title="收款单分析"
  6 + width="60%"
  7 + okText="导出"
  8 + :isDetail="true"
  9 + :showDetailBack="false"
  10 + @ok="handleOk"
  11 + @visible-change="handleShow"
  12 + >
  13 + <div class="p-4">
  14 + <BasicTable @register="registerTable">
  15 + <template #bodyCell="{ column, record }">
  16 + <template v-if="column.key === 'action'"> </template>
  17 + </template>
  18 + </BasicTable>
  19 + </div>
  20 + </BasicModal>
  21 +</template>
  22 +<script lang="ts" setup>
  23 + import { BasicModal, useModalInner } from '@/components/Modal';
  24 + import { computed, ref } from 'vue';
  25 + import { invoiceAnalysis, exportAnalysis } from '@/api/project/invoice';
  26 + import { BasicColumn, useTable, BasicTable, ColumnChangeParam } from '/@/components/Table';
  27 + // 处理弹窗的确定按钮点击事件
  28 + import axios from 'axios';
  29 +
  30 + const columnsAnalysis: BasicColumn[] = [
  31 + {
  32 + title: '客户编码',
  33 + dataIndex: 'actualPayedAmount',
  34 + width: 50,
  35 + customRender: (res) => {
  36 + return res?.record?.exportVOS[0]?.customerCode;
  37 + },
  38 + },
  39 + {
  40 + title: '客户总金额汇总$',
  41 + dataIndex: 'customerTotalPrice',
  42 + width: 50,
  43 + customRender: (res) => {
  44 + return res?.record?.customerTotalPrice.toFixed(2);
  45 + },
  46 + },
  47 + {
  48 + title: '客户扣款金额汇总$',
  49 + dataIndex: 'deductAmount',
  50 + width: 50,
  51 + customRender: (res) => {
  52 + return res?.record?.deductAmount.toFixed(2);
  53 + },
  54 + },
  55 + {
  56 + title: '实际应收款$',
  57 + dataIndex: 'otherAmount',
  58 + width: 50,
  59 + customRender: (res) => {
  60 + return res?.record?.otherAmount.toFixed(2);
  61 + },
  62 + },
  63 + {
  64 + title: '实际收款金额汇总$',
  65 + dataIndex: 'actualReceivableAmount',
  66 + width: 50,
  67 + customRender: (res) => {
  68 + return res?.record?.actualReceivableAmount.toFixed(2);
  69 + },
  70 + },
  71 + {
  72 + title: '其他费用金额汇总$',
  73 + dataIndex: 'otherTotalAmount',
  74 + width: 50,
  75 + customRender: (res) => {
  76 + return res?.record?.otherTotalAmount.toFixed(2);
  77 + },
  78 + },
  79 + {
  80 + title: '未收金额合计$',
  81 + dataIndex: 'actualPayedAmount',
  82 + width: 50,
  83 + customRender: (res) => {
  84 + return res?.record?.actualPayedAmount.toFixed(2);
  85 + },
  86 + },
  87 + ];
  88 + // const ids = ref<number[]>([]);
  89 + const ids = ref();
  90 + const tableData = ref([]);
  91 + // const res = ref();
  92 +
  93 + const [register, { closeModal }] = useModalInner(async (data) => {
  94 + ids.value = data.data;
  95 + setTimeout(() => {
  96 + reload();
  97 + }, 50);
  98 + });
  99 + const [registerTable, { reload }] = useTable({
  100 + // api: () => invoiceAnalysis({ ids: ids.value }),
  101 + api: async () => {
  102 + const res = await invoiceAnalysis({ ids: ids.value });
  103 + // 计算合计行
  104 + const sum = {
  105 + customerTotalPrice: 0,
  106 + deductAmount: 0,
  107 + otherAmount: 0,
  108 + actualReceivableAmount: 0,
  109 + otherTotalAmount: 0,
  110 + actualPayedAmount: 0,
  111 + exportVOS: res[0].exportVOS ? JSON.parse(JSON.stringify(res[0].exportVOS)) : [],
  112 + };
  113 +
  114 + res.forEach((item: any) => {
  115 + sum.customerTotalPrice += item.customerTotalPrice || 0;
  116 + sum.deductAmount += item.deductAmount || 0;
  117 + sum.otherAmount += item.otherAmount || 0;
  118 + sum.actualReceivableAmount += item.actualReceivableAmount || 0;
  119 + sum.otherTotalAmount += item.otherTotalAmount || 0;
  120 + sum.actualPayedAmount += item.actualPayedAmount || 0;
  121 + });
  122 + if (sum.exportVOS && sum.exportVOS[0]) {
  123 + sum.exportVOS[0].customerCode = '合计';
  124 + }
  125 + res.push(sum);
  126 + return res;
  127 + },
  128 + columns: columnsAnalysis,
  129 + bordered: true,
  130 + });
  131 + function handleShow(visible: boolean) {
  132 + reload();
  133 + }
  134 + const searchData = ref({});
  135 + async function handleOk() {
  136 + // 构造符合 API 要求的参数
  137 + const idss = ids.value;
  138 + // await exportAnalysis({ ids: ids });
  139 + axios
  140 + .post(
  141 + '/basic-api/order/erp/invoice_bill/export',
  142 + { ids: idss },
  143 + {
  144 + responseType: 'blob', // 设置响应类型为 'blob'
  145 + },
  146 + )
  147 + .then((response) => {
  148 + // 创建一个 Blob 对象来保存二进制数据
  149 + const blob = new Blob([response.data], { type: 'application/zip' });
  150 + const getFormattedDate = (): string => {
  151 + const date = new Date();
  152 +
  153 + const year = date.getFullYear();
  154 + const month = String(date.getMonth() + 1).padStart(2, '0');
  155 + const day = String(date.getDate()).padStart(2, '0');
  156 +
  157 + const hours = String(date.getHours()).padStart(2, '0');
  158 + const minutes = String(date.getMinutes()).padStart(2, '0');
  159 + const seconds = String(date.getSeconds()).padStart(2, '0');
  160 +
  161 + return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
  162 + };
  163 + const date = getFormattedDate();
  164 + // 创建一个链接元素用于下载
  165 + const link = document.createElement('a');
  166 + link.href = window.URL.createObjectURL(blob);
  167 + link.download = `收款单分析${date}.xlsx`; // 你可以为文件命名
  168 + document.body.appendChild(link);
  169 + link.click(); // 自动点击链接,触发下载
  170 + document.body.removeChild(link); // 下载完成后移除链接
  171 + })
  172 + .catch((error) => {
  173 + console.error(error);
  174 + });
  175 + closeModal();
  176 + }
  177 +</script>
  178 +<style scoped>
  179 + .divAll {
  180 + display: flex;
  181 + justify-content: center;
  182 + align-items: center;
  183 + }
  184 +</style>
... ...
src/views/project/finance/InvoiceDetail.vue 0 → 100644
  1 +<template>
  2 + <template>
  3 + <BasicDrawer
  4 + @register="register"
  5 + v-bind="$attrs"
  6 + title="订单信息"
  7 + width="60%"
  8 + :isDetail="true"
  9 + :showDetailBack="false"
  10 + :destroyOnClose="true"
  11 + >
  12 + <div class="p-4">
  13 + <BasicTable @register="registerTable">
  14 + <template #bodyCell="{ column, record }">
  15 + <template v-if="column.key === 'action'"> </template>
  16 + <template v-if="column.key === 'picUrl'">
  17 + <img :z-index="100000" :width="50" :height="50" :src="record?.smallPicUrl" />
  18 + </template>
  19 + </template>
  20 + </BasicTable>
  21 + </div>
  22 + </BasicDrawer>
  23 + </template>
  24 +</template>
  25 +<script lang="ts" setup>
  26 + import { BasicDrawer, useDrawerInner } from '@/components/Drawer';
  27 + import { BasicForm, FormSchema, useForm } from '@/components/Form';
  28 + import { defineComponent, ref, computed, unref, toRaw, reactive } from 'vue';
  29 + import { demoListApi } from '/@/api/demo/table';
  30 + import { BasicColumn, useTable, BasicTable, ColumnChangeParam } from '/@/components/Table';
  31 + import { getBaseInvoice } from '/@/api/project/invoice';
  32 +
  33 + const columns: BasicColumn[] = [
  34 + {
  35 + title: '客户编码',
  36 + dataIndex: 'customerCode',
  37 + width: 100,
  38 + },
  39 + {
  40 + title: '项目号',
  41 + dataIndex: 'projectNo',
  42 + width: 100,
  43 + },
  44 + {
  45 + title: '内部编码',
  46 + dataIndex: 'innerNo',
  47 + width: 100,
  48 + },
  49 + {
  50 + title: '客户po号',
  51 + dataIndex: 'customerPo',
  52 + width: 100,
  53 + },
  54 + {
  55 + title: '客户STYLE',
  56 + width: 150,
  57 + dataIndex: 'customerStyle',
  58 + },
  59 + {
  60 + title: 'Model(REFERENCE)',
  61 + width: 150,
  62 + dataIndex: 'modeleLo',
  63 + },
  64 + {
  65 + title: '订单图片',
  66 + width: 150,
  67 + dataIndex: 'picUrl',
  68 + },
  69 + {
  70 + title: '数量',
  71 + width: 150,
  72 + dataIndex: 'orderCount',
  73 + },
  74 + {
  75 + title: '客户单价$',
  76 + width: 150,
  77 + dataIndex: 'customerPrice',
  78 + },
  79 + {
  80 + title: '客户总价$',
  81 + width: 150,
  82 + dataIndex: 'customerTotalPrice',
  83 + },
  84 + ];
  85 + const invoiceNo = ref();
  86 + const [register, { setDrawerProps, closeDrawer }] = useDrawerInner((data) => {
  87 + // 方式1
  88 + invoiceNo.value = data.data.invoiceNo;
  89 + // getBaseInvoice({ invoiceNo: invoiceNo.value });
  90 + });
  91 + const params = ref({
  92 + invoiceNo: invoiceNo.value,
  93 + });
  94 + const [registerTable] = useTable({
  95 + api: () => {
  96 + const res = getBaseInvoice({ invoiceNo: invoiceNo.value });
  97 + return res;
  98 + },
  99 + columns: columns,
  100 + bordered: true,
  101 + });
  102 +</script>
... ...
src/views/project/finance/InvoiceShowCheck.vue 0 → 100644
  1 +<template>
  2 + <BasicModal
  3 + v-bind="$attrs"
  4 + @register="register"
  5 + title="生产科发票"
  6 + width="700px"
  7 + :bodyStyle="{ height: '240px' }"
  8 + @ok="handleOk"
  9 + >
  10 + <a-list item-layout="horizontal" :data-source="itemArray">
  11 + <template #renderItem="{ item }">
  12 + <a-list-item>
  13 + <a-list-item-meta>
  14 + <template #title>
  15 + <!-- <a :href="item.url" target="_blank" rel="noopener noreferrer">{{ item.name }}</a> -->
  16 + <a @click="view(item.url)">{{ item.name }}</a>
  17 + </template>
  18 + </a-list-item-meta>
  19 + </a-list-item>
  20 + </template>
  21 + </a-list>
  22 + </BasicModal>
  23 +</template>
  24 +<script lang="ts" setup>
  25 + import { BasicModal, useModalInner } from '@/components/Modal';
  26 + import { computed, ref } from 'vue';
  27 + import type { UploadProps, UploadChangeParam } from 'ant-design-vue';
  28 + import { InboxOutlined } from '@ant-design/icons-vue';
  29 + import { message } from 'ant-design-vue';
  30 + import { getDeductUrlById, getInvoiceUrlById } from '@/api/project/invoice';
  31 + import { view } from '@/utils/pdfShow';
  32 +
  33 + interface Item {
  34 + name: string;
  35 + url: string;
  36 + }
  37 +
  38 + const list = ref();
  39 + const id = ref();
  40 + const itemArray = ref<Item[]>([]);
  41 +
  42 + const [register, { closeModal }] = useModalInner(async (data) => {
  43 + itemArray.value = [];
  44 + const res = await getInvoiceUrlById({ id: data.data.checkId });
  45 + for (let item in res) {
  46 + const url = res[item];
  47 + const name = item;
  48 + // 将 name 和 url 放入对象并添加到数组中
  49 + itemArray.value.push({ name, url });
  50 + }
  51 + });
  52 +
  53 + async function handleOk() {
  54 + itemArray.value = [];
  55 + closeModal();
  56 + }
  57 +</script>
... ...
src/views/project/finance/InvoiceUploadCheck.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 + ><a-upload-dragger
  10 + v-model:fileList="fileList"
  11 + name="file"
  12 + :beforeUpload="beforeUpload"
  13 + :max-count="1"
  14 + :multiple="true"
  15 + :action="updateInvoiceUrl"
  16 + @change="handleChange"
  17 + @drop="handleDrop"
  18 + :disabled="status === 10"
  19 + >
  20 + <p class="ant-upload-drag-icon">
  21 + <inbox-outlined></inbox-outlined>
  22 + </p>
  23 + <p class="ant-upload-text">点击或将文件拖拽到这里上传</p>
  24 + </a-upload-dragger>
  25 + </BasicModal>
  26 +</template>
  27 +<script lang="ts" setup>
  28 + import { BasicModal, useModalInner } from '@/components/Modal';
  29 + import { computed, ref } from 'vue';
  30 + import type { UploadProps, UploadChangeParam } from 'ant-design-vue';
  31 + import { InboxOutlined } from '@ant-design/icons-vue';
  32 + import { message } from 'ant-design-vue';
  33 + import { updateInvoiceInfo } from '@/api/project/invoice';
  34 +
  35 + const emit = defineEmits(['success']);
  36 + const uploadUrl = ref('http://47.104.8.35:80/api/localStorage/upload_file_oss?name=');
  37 + const updateInvoiceUrl = ref('http://47.104.8.35:80/api/localStorage/upload_file_oss?name=');
  38 + const invoiceUrl = ref();
  39 + const id = ref();
  40 + const status = ref();
  41 + const [register, { closeModal }] = useModalInner(async (data) => {
  42 + console.log(data);
  43 + status.value = data.data.checkStatus;
  44 + // fileList.value = [];
  45 + fileList.value = [];
  46 + invoiceUrl.value = data.data.invoiceUrl;
  47 + id.value = data.data.checkId;
  48 + });
  49 +
  50 + const handleChange = (info) => {
  51 + if (info.file.status == 'done') {
  52 + updateInvoiceUrl.value = info.file.response.data.fileUrl;
  53 + invoiceUrl.value = updateInvoiceUrl.value;
  54 + }
  55 + };
  56 + function beforeUpload(info) {
  57 + updateInvoiceUrl.value = uploadUrl.value + info.name;
  58 + }
  59 + function handleDrop(e: DragEvent) {
  60 + console.log(e);
  61 + }
  62 + const fileList = ref<UploadProps['fileList']>([]);
  63 +
  64 + async function handleOk() {
  65 + await updateInvoiceInfo({
  66 + id: id.value,
  67 + invoiceUrl: invoiceUrl.value,
  68 + });
  69 + fileList.value = [];
  70 + emit('success');
  71 + closeModal();
  72 + }
  73 +</script>
... ...
src/views/project/finance/Note.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 + @visible-change="handleShow"
  10 + >
  11 + 备注:
  12 + <a-textarea v-model:value="notes" placeholder="请输入" :rows="6" />
  13 + <div style="height: 10px"></div>
  14 + </BasicModal>
  15 +</template>
  16 +<script lang="ts" setup>
  17 + import { BasicModal, useModalInner } from '@/components/Modal';
  18 + import { ref } from 'vue';
  19 + import { getInvoiceNote } from '@/api/project/invoice';
  20 + import { useMessage } from '/@/hooks/web/useMessage';
  21 +
  22 + const id = ref();
  23 + const notes = ref();
  24 + const emit = defineEmits(['success']);
  25 + const { createMessage } = useMessage();
  26 + const { error } = createMessage;
  27 + const [register, { closeModal }] = useModalInner(async (data) => {
  28 + id.value = data.data.invoiceId;
  29 + });
  30 + const isDisabled = ref(false);
  31 + async function handleOk() {
  32 + if (isDisabled.value) {
  33 + error('请勿连续点击生成按钮,需要等待三秒再点击生成');
  34 + return;
  35 + }
  36 + isDisabled.value = true;
  37 + setTimeout(() => {
  38 + isDisabled.value = false;
  39 + }, 3000);
  40 + getInvoiceNote({ id: id.value, notes: notes.value });
  41 + emit('success');
  42 + closeModal();
  43 + }
  44 + function handleShow(visible: boolean) {
  45 + if (!visible) {
  46 + notes.value = null;
  47 + }
  48 + }
  49 +</script>
... ...
src/views/project/finance/NoteCheck.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 + @visible-change="handleShow"
  10 + >
  11 + 备注:
  12 + <a-textarea v-model:value="notes" placeholder="请输入" :rows="6" />
  13 + <div style="height: 10px"></div>
  14 + </BasicModal>
  15 +</template>
  16 +<script lang="ts" setup>
  17 + import { BasicModal, useModalInner } from '@/components/Modal';
  18 + import { ref } from 'vue';
  19 + import { getCheckNote } from '@/api/project/invoice';
  20 + import { useMessage } from '/@/hooks/web/useMessage';
  21 +
  22 + const id = ref();
  23 + const notes = ref();
  24 + const emit = defineEmits(['success']);
  25 + const { createMessage } = useMessage();
  26 + const { error } = createMessage;
  27 + const [register, { closeModal }] = useModalInner(async (data) => {
  28 + id.value = data.data.checkId;
  29 + });
  30 + const isDisabled = ref(false);
  31 + async function handleOk() {
  32 + if (isDisabled.value) {
  33 + error('请勿连续点击生成按钮,需要等待三秒再点击生成');
  34 + return;
  35 + }
  36 + isDisabled.value = true;
  37 + setTimeout(() => {
  38 + isDisabled.value = false;
  39 + }, 3000);
  40 + getCheckNote({ id: id.value, notes: notes.value });
  41 + emit('success');
  42 + closeModal();
  43 + }
  44 + function handleShow(visible: boolean) {
  45 + if (!visible) {
  46 + notes.value = null;
  47 + }
  48 + }
  49 +</script>
... ...
src/views/project/finance/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 + @visible-change="handleShow"
  10 + >
  11 + <div>报关单(请上传PDF格式)</div
  12 + ><a-space direction="vertical" style="width: 100%" size="large">
  13 + <a-upload
  14 + v-model:file-list="fileList"
  15 + :beforeUpload="beforeUpload"
  16 + list-type="picture"
  17 + :max-count="1"
  18 + :action="updateUrl"
  19 + @change="handleChange"
  20 + >
  21 + <a-button> 上传报关单 </a-button>
  22 + </a-upload>
  23 + </a-space>
  24 + </BasicModal>
  25 +</template>
  26 +<script lang="ts" setup>
  27 + import { BasicModal, useModalInner } from '@/components/Modal';
  28 + import { ref } from 'vue';
  29 + import type { UploadProps } from 'ant-design-vue';
  30 + import { reUploadBgUrl } from '@/api/project/invoice';
  31 + import { useMessage } from '/@/hooks/web/useMessage';
  32 +
  33 + const fileList = ref<UploadProps['fileList']>([]);
  34 + const { createMessage } = useMessage();
  35 + const { error } = createMessage;
  36 + const emit = defineEmits(['success']);
  37 +
  38 + const id = ref();
  39 + const uploadUrl = ref('http://47.104.8.35:80/api/localStorage/upload_file_oss?name=');
  40 + const updateUrl = ref('http://47.104.8.35:80/api/localStorage/upload_file_oss?name=');
  41 + const bgUrl = ref();
  42 + const urlOld = ref();
  43 +
  44 + const [register, { closeModal }] = useModalInner(async (data) => {
  45 + id.value = data.data.invoiceId;
  46 + });
  47 + function handleChange(info) {
  48 + if (info.file.status == 'done') {
  49 + updateUrl.value = info.file.response.data.fileUrl;
  50 + bgUrl.value = updateUrl.value;
  51 + }
  52 + if (info.fileList.length == 0) {
  53 + info.file = null;
  54 + bgUrl.value = '';
  55 + }
  56 + }
  57 + function beforeUpload(info) {
  58 + updateUrl.value += uploadUrl.value + info.name;
  59 + }
  60 + function handleShow(visible: boolean) {
  61 + if (!visible) {
  62 + updateUrl.value = '';
  63 + fileList.value = null;
  64 + }
  65 + }
  66 +
  67 + async function handleOk() {
  68 + reUploadBgUrl({ id: id.value, bgUrl: bgUrl.value });
  69 + emit('success');
  70 + closeModal();
  71 + }
  72 +</script>
... ...
src/views/project/finance/TrackEdit.vue 0 → 100644
  1 +<template>
  2 + <template>
  3 + <BasicDrawer
  4 + @register="register"
  5 + v-bind="$attrs"
  6 + title="收入款单"
  7 + width="30%"
  8 + :isDetail="true"
  9 + @ok="handleSubmit"
  10 + @visible-change="handleShow"
  11 + :showDetailBack="false"
  12 + okText="保存"
  13 + showFooter
  14 + :destroyOnClose="true"
  15 + >
  16 + <div>
  17 + <div style="font-size: 15px">客户扣款金额$</div>
  18 + <a-input v-model:value="input1" placeholder="请输入" :disabled="status === 10" auto-size />
  19 + <div style="margin: 16px 0"></div>
  20 + <div>上传扣款单</div
  21 + ><a-space direction="vertical" style="width: 100%" size="large">
  22 + <a-upload
  23 + v-model:file-list="fileList"
  24 + :beforeUpload="beforeUpload"
  25 + list-type="picture"
  26 + :max-count="1"
  27 + :action="updateDeductUrl"
  28 + @change="handleChange"
  29 + :disabled="status === 10"
  30 + >
  31 + <a-button> 上传扣款单 </a-button>
  32 + </a-upload>
  33 + </a-space>
  34 + </div>
  35 + <!-- <template #titleToolbar> <a-button type="primary"> 申请编辑权限 </a-button></template> -->
  36 + <template #appendFooter>
  37 + <!-- <a-button type="primary" @click="onGoCheckDetail"> 申请权限</a-button> -->
  38 + </template>
  39 + </BasicDrawer>
  40 + </template>
  41 +</template>
  42 +<script lang="ts" setup>
  43 + import { BasicDrawer, useDrawerInner } from '@/components/Drawer';
  44 + import { defineComponent, ref, computed, unref, toRaw, reactive } from 'vue';
  45 + import { getEmailList } from '/@/api/sys/config';
  46 + import { UploadOutlined } from '@ant-design/icons-vue';
  47 + import type { UploadProps } from 'ant-design-vue';
  48 + import { updateDeduct } from '@/api/project/invoice';
  49 + import { useMessage } from '/@/hooks/web/useMessage';
  50 +
  51 + const emit = defineEmits(['success']);
  52 + const fileList = ref<UploadProps['fileList']>([]);
  53 +
  54 + const input1 = ref(0);
  55 + const deductUrl = ref();
  56 + const id = ref();
  57 + const invoiceNo = ref();
  58 + const uploadUrl = ref('http://47.104.8.35:80/api/localStorage/upload_file_oss?name=');
  59 + // const uploadUrl = ref('');
  60 + const updateDeductUrl = ref('http://47.104.8.35:80/api/localStorage/upload_file_oss?name=');
  61 + // const updateDeductUrl = ref('');
  62 + const deductUrlOld = ref();
  63 + const { createMessage } = useMessage();
  64 + const { error } = createMessage;
  65 + const status = ref();
  66 +
  67 + const [register, { setDrawerProps, closeDrawer }] = useDrawerInner((data) => {
  68 + status.value = data.data.invoiceStatus;
  69 + id.value = data.data.invoiceId;
  70 + invoiceNo.value = data.data.invoiceNo;
  71 + input1.value = data.data.invoiceDeductAmount;
  72 + deductUrl.value = data.data.invoiceDeductUrl;
  73 + deductUrlOld.value = data.data.invoiceDeductUrl;
  74 + });
  75 +
  76 + function handleChange(info) {
  77 + if (info.file.status == 'done') {
  78 + updateDeductUrl.value = info.file.response.data.fileUrl;
  79 + deductUrl.value = updateDeductUrl.value;
  80 + }
  81 + if (info.fileList.length == 0) {
  82 + info.file = null;
  83 + deductUrl.value = '';
  84 + }
  85 + }
  86 + function beforeUpload(info) {
  87 + updateDeductUrl.value = uploadUrl.value + info.name;
  88 + }
  89 + function handleShow() {
  90 + // if (!visible) {
  91 + // input1.value = 0;
  92 + // deductUrl.value = '';
  93 + // updateDeductUrl.value = '';
  94 + // fileList.value = [];
  95 + // }
  96 + // input1.value = '';
  97 + // deductUrl.value = '';
  98 + // updateDeductUrl.value = '';
  99 + // fileList.value = [];
  100 + }
  101 +
  102 + //完成编辑
  103 + async function handleSubmit() {
  104 + if (!input1.value) {
  105 + error('选项不能为空');
  106 + } else {
  107 + await updateDeduct({
  108 + id: id.value,
  109 + invoiceNo: invoiceNo.value,
  110 + deductAmount: input1.value,
  111 + deductUrl: deductUrl.value,
  112 + });
  113 + fileList.value = [];
  114 + emit('success');
  115 + closeDrawer();
  116 + }
  117 + }
  118 +</script>
... ...
src/views/project/finance/TrackEditCheck.vue 0 → 100644
  1 +<template>
  2 + <template>
  3 + <BasicDrawer
  4 + @register="register"
  5 + v-bind="$attrs"
  6 + title="跟单编辑"
  7 + width="30%"
  8 + :isDetail="true"
  9 + @ok="handleSubmit"
  10 + :showDetailBack="false"
  11 + @visible-change="handleShow"
  12 + okText="保存"
  13 + showFooter
  14 + :destroyOnClose="true"
  15 + >
  16 + <div>
  17 + <div style="font-size: 15px">生产科扣款金额¥</div>
  18 + <a-input v-model:value="input1" placeholder="请输入" :disabled="status === 10" auto-size />
  19 + <div style="margin: 16px 0"></div>
  20 + <div style="font-size: 15px">扣款责任部门</div>
  21 + <a-input
  22 + v-model:value="deductDept"
  23 + placeholder="请输入"
  24 + :disabled="status === 10"
  25 + auto-size
  26 + />
  27 + <!-- <a-select
  28 + ref="select"
  29 + style="width: 60%"
  30 + v-model:value="selectedProductionDepartment"
  31 + :options="productionDepartmentOptions"
  32 + /> -->
  33 + <!-- <a-select
  34 + ref="select"
  35 + style="width: 100%"
  36 + v-model:value="productionDepartment"
  37 + :options="productDepartmentOptions"
  38 + /> -->
  39 + <div style="margin: 16px 0"></div>
  40 + <div>上传扣款单</div
  41 + ><a-space direction="vertical" style="width: 100%" size="large">
  42 + <a-upload
  43 + v-model:file-list="fileList"
  44 + :beforeUpload="beforeUpload"
  45 + list-type="picture"
  46 + :max-count="1"
  47 + :disabled="status === 10"
  48 + :action="updateDeductUrl"
  49 + @change="handleChange"
  50 + >
  51 + <a-button> 上传扣款单 </a-button>
  52 + </a-upload>
  53 + </a-space>
  54 + </div>
  55 + <!-- <template #titleToolbar> <a-button type="primary"> 申请编辑权限 </a-button></template> -->
  56 + <template #appendFooter>
  57 + <!-- <a-button type="primary" @click="onGoCheckDetail"> 申请权限</a-button> -->
  58 + </template>
  59 + </BasicDrawer>
  60 + </template>
  61 +</template>
  62 +<script lang="ts" setup>
  63 + import { BasicDrawer, useDrawerInner } from '@/components/Drawer';
  64 + import { defineComponent, ref, computed, unref, toRaw, reactive, onMounted } from 'vue';
  65 + import { getEmailList } from '/@/api/sys/config';
  66 + import { UploadOutlined } from '@ant-design/icons-vue';
  67 + import type { UploadProps } from 'ant-design-vue';
  68 + import { updateDeductInfo } from '@/api/project/invoice';
  69 + import { useMessage } from '/@/hooks/web/useMessage';
  70 + import { useOrderInfo } from '/@/hooks/component/order';
  71 + import { useOrderStoreWithOut } from '/@/store/modules/order';
  72 +
  73 + const emit = defineEmits(['success']);
  74 + const fileList = ref<UploadProps['fileList']>([]);
  75 + // const orderStore = useOrderStoreWithOut();
  76 + // const { productionDepartment: productionDepartmentOptions } = useOrderInfo(orderStore);
  77 + // console.log(productionDepartmentOptions.value, '565656565665orderStore');
  78 + // onMounted(() => {
  79 + // const { productionDepartment } = useOrderInfo(orderStore);
  80 + // console.log(productionDepartment.value, '565656565665orderStore1');
  81 + // });
  82 + const orderStore = useOrderStoreWithOut();
  83 + const { productionDepartment: productDepartmentOptions } = useOrderInfo(orderStore);
  84 + const productionDepartment = ref();
  85 + const input1 = ref(0);
  86 + const deductUrl = ref();
  87 + const id = ref();
  88 + const checkNo = ref();
  89 + const deductDept = ref();
  90 + const uploadUrl = ref('http://47.104.8.35:80/api/localStorage/upload_file_oss?name=');
  91 + const updateDeductUrl = ref('http://47.104.8.35:80/api/localStorage/upload_file_oss?name=');
  92 + // const uploadUrl = ref('');
  93 + // const updateDeductUrl = ref('');
  94 + const deductUrlOld = ref();
  95 + const selectedProductionDepartment = ref(); // 新增: 用于存储选中的生产科
  96 + const { createMessage } = useMessage();
  97 + const { error } = createMessage;
  98 + const status = ref();
  99 +
  100 + const [register, { setDrawerProps, closeDrawer }] = useDrawerInner((data) => {
  101 + status.value = data.data.checkStatus;
  102 + id.value = data.data.checkId;
  103 + checkNo.value = data.data.checkNo;
  104 + input1.value = data.data.checkDeductAmount;
  105 + deductDept.value = data.data.checkDeductDept;
  106 + deductUrl.value = data.data.checkDeductUrl;
  107 + deductUrlOld.value = data.data.checkDeductUrl;
  108 + });
  109 + function handleChange(info) {
  110 + if (info.file.status == 'done') {
  111 + updateDeductUrl.value = info.file.response.data.fileUrl;
  112 + deductUrl.value = updateDeductUrl.value;
  113 + }
  114 + if (info.fileList.length == 0) {
  115 + info.file = null;
  116 + deductUrl.value = '';
  117 + }
  118 + }
  119 + function beforeUpload(info) {
  120 + updateDeductUrl.value = uploadUrl.value + info.name;
  121 + }
  122 + function handleShow() {
  123 + // input1.value = '';
  124 + // deductUrl.value = '';
  125 + // deductDept.value = '';
  126 + // updateDeductUrl.value = '';
  127 + // fileList.value = [];
  128 + }
  129 + //完成编辑
  130 + async function handleSubmit() {
  131 + if (!input1.value || !deductDept.value) {
  132 + error('选项不能为空');
  133 + } else {
  134 + await updateDeductInfo({
  135 + id: id.value,
  136 + checkNo: checkNo.value,
  137 + deductAmount: input1.value,
  138 + deductDept: deductDept.value,
  139 + deductUrl: deductUrl.value,
  140 + });
  141 + // productionDepartment: selectedProductionDepartment.value,
  142 + fileList.value = [];
  143 + emit('success');
  144 + closeDrawer();
  145 + }
  146 + }
  147 +</script>
... ...
src/views/project/finance/finance.data.tsx 0 → 100644
  1 +import { FormSchema } from '/@/components/Form';
  2 +import { BasicColumn } from '/@/components/Table';
  3 +import { icon } from 'ant-design-vue';
  4 +import { FolderAddOutlined, FilePptOutlined } from '@ant-design/icons-vue';
  5 +import { size } from 'lodash-es';
  6 +import { view } from '@/utils/pdfShow';
  7 +
  8 +export const searchFormSchema: FormSchema[] = [
  9 + {
  10 + field: 'invoiceNo',
  11 + label: '发票单号',
  12 + component: 'Input',
  13 + colProps: { span: 8 },
  14 + },
  15 + {
  16 + field: 'checkNo',
  17 + label: '生产科对账单号',
  18 + component: 'Input',
  19 + colProps: { span: 8 },
  20 + },
  21 + {
  22 + field: 'invoiceStatus',
  23 + label: '发票状态',
  24 + component: 'Select',
  25 + colProps: { span: 8 },
  26 + componentProps: {
  27 + options: [
  28 + { label: '未创建', value: -1 },
  29 + { label: '未收款', value: 0 },
  30 + { label: '已收款', value: 10 },
  31 + ],
  32 + },
  33 + },
  34 + {
  35 + field: 'checkNoStatus',
  36 + label: '对账单号状态',
  37 + component: 'Select',
  38 + colProps: { span: 8 },
  39 + componentProps: {
  40 + options: [
  41 + { label: '未创建', value: -1 },
  42 + { label: '未收款', value: 0 },
  43 + { label: '已收款', value: 10 },
  44 + ],
  45 + },
  46 + },
  47 + {
  48 + field: 'customerCode',
  49 + label: '客户编码',
  50 + component: 'Input',
  51 + colProps: { span: 8 },
  52 + },
  53 + {
  54 + field: 'projectNo',
  55 + label: '项目号',
  56 + component: 'Input',
  57 + colProps: { span: 8 },
  58 + },
  59 + {
  60 + field: 'productionDepartment',
  61 + label: '生产科',
  62 + component: 'Input',
  63 + colProps: { span: 8 },
  64 + },
  65 + {
  66 + field: 'innerNo',
  67 + label: '内部编号',
  68 + component: 'Input',
  69 + colProps: { span: 8 },
  70 + },
  71 + {
  72 + field: 'customerPo',
  73 + label: '客户PO号',
  74 + component: 'Input',
  75 + colProps: { span: 8 },
  76 + },
  77 + {
  78 + field: 'invoiceStartTime',
  79 + label: '发票开始时间',
  80 + component: 'DatePicker',
  81 + colProps: { span: 8 },
  82 + labelWidth: 150,
  83 + },
  84 + {
  85 + field: 'invoiceEndTime',
  86 + label: '发票结束时间',
  87 + component: 'DatePicker',
  88 + colProps: { span: 8 },
  89 + labelWidth: 150,
  90 + },
  91 + {
  92 + field: 'checkStartTime',
  93 + label: '对账开始时间',
  94 + component: 'DatePicker',
  95 + colProps: { span: 8 },
  96 + labelWidth: 150,
  97 + },
  98 + {
  99 + field: 'checkEndTime',
  100 + label: '对账结束时间',
  101 + component: 'DatePicker',
  102 + colProps: { span: 8 },
  103 + labelWidth: 150,
  104 + },
  105 + {
  106 + field: 'createStartTime',
  107 + label: '订单开始时间',
  108 + component: 'DatePicker',
  109 + colProps: { span: 8 },
  110 + labelWidth: 150,
  111 + },
  112 + {
  113 + field: 'createEndTime',
  114 + label: '订单结束时间',
  115 + component: 'DatePicker',
  116 + colProps: { span: 8 },
  117 + labelWidth: 150,
  118 + },
  119 + {
  120 + field: 'productionDepartmentConsignStartTime',
  121 + label: '生产科拖货开始时间',
  122 + component: 'DatePicker',
  123 + colProps: { span: 8 },
  124 + labelWidth: 150,
  125 + },
  126 + {
  127 + field: 'productionDepartmentConsignEndTime',
  128 + label: '生产科拖货结束时间',
  129 + component: 'DatePicker',
  130 + colProps: { span: 8 },
  131 + labelWidth: 150,
  132 + },
  133 + {
  134 + field: 'orderHodStartTime',
  135 + label: 'HOD开始时间',
  136 + component: 'DatePicker',
  137 + colProps: { span: 8 },
  138 + labelWidth: 150,
  139 + },
  140 + {
  141 + field: 'orderHodEndTime',
  142 + label: 'HOD结束时间',
  143 + component: 'DatePicker',
  144 + colProps: { span: 8 },
  145 + labelWidth: 150,
  146 + },
  147 +];
  148 +
  149 +export const columns: BasicColumn[] = [
  150 + {
  151 + title: '客户编码',
  152 + dataIndex: 'customerCode',
  153 + width: 100,
  154 + },
  155 + {
  156 + title: '项目号',
  157 + dataIndex: 'projectNo',
  158 + width: 100,
  159 + },
  160 + {
  161 + title: '生产科',
  162 + dataIndex: 'productionDepartment',
  163 + width: 100,
  164 + },
  165 + {
  166 + title: '内部编码',
  167 + dataIndex: 'innerNo',
  168 + width: 100,
  169 + },
  170 + {
  171 + title: '订单图片',
  172 + width: 150,
  173 + dataIndex: 'picUrl',
  174 + },
  175 + {
  176 + title: '数量',
  177 + width: 150,
  178 + dataIndex: 'orderCount',
  179 + },
  180 + {
  181 + title: '生产科拖货时间',
  182 + width: 150,
  183 + dataIndex: 'productionDepartmentConsignTime',
  184 + customRender: (column) => {
  185 + return formatDate(column.record?.productionDepartmentConsignTime);
  186 + },
  187 + },
  188 + {
  189 + title: '订单上HOD时间',
  190 + width: 150,
  191 + dataIndex: 'orderHodTime',
  192 + customRender: (column) => {
  193 + return formatDate(column.record?.orderHodTime);
  194 + },
  195 + },
  196 + {
  197 + title: '客户单价$',
  198 + width: 150,
  199 + dataIndex: 'customerPrice',
  200 + customRender: (column) => {
  201 + return column.record.customerPrice?.toFixed(2);
  202 + },
  203 + },
  204 + {
  205 + title: '客户总价$',
  206 + width: 150,
  207 + dataIndex: 'customerTotalPrice',
  208 + customRender: (column) => {
  209 + return column.record.customerTotalPrice?.toFixed(2);
  210 + },
  211 + },
  212 + {
  213 + title: 'Invoice编号',
  214 + dataIndex: 'invoiceNo',
  215 + width: 180,
  216 + },
  217 + {
  218 + title: '报关单',
  219 + dataIndex: 'invoiceBgUrl',
  220 + width: 80,
  221 + customRender: (column) => {
  222 + const bgUrl = column.record.invoiceBgUrl;
  223 + if (bgUrl == undefined) {
  224 + return;
  225 + }
  226 + return <FilePptOutlined style="font-size:25px" onClick={() => view(bgUrl)} />;
  227 + },
  228 + },
  229 + {
  230 + title: '必须回款日期',
  231 + dataIndex: 'invoiceBackRefundDate',
  232 + width: 120,
  233 + },
  234 + {
  235 + title: '发生扣款金额$',
  236 + dataIndex: 'invoiceDeductAmount',
  237 + width: 120,
  238 + customRender: (column) => {
  239 + return column.record.invoiceDeductAmount?.toFixed(2);
  240 + },
  241 + },
  242 + {
  243 + title: '上传扣款单',
  244 + dataIndex: 'invoiceDeductUrl',
  245 + width: 80,
  246 + customRender: (column) => {
  247 + const deductUrl = column.record.invoiceDeductUrl;
  248 + if (deductUrl == undefined) {
  249 + return;
  250 + }
  251 + // return <FilePptOutlined style="font-size:25px" onClick={() => window.open(deductUrl[0])} />;
  252 + return <FilePptOutlined style="font-size:25px" />;
  253 + },
  254 + },
  255 + {
  256 + title: '实际应收金额$',
  257 + dataIndex: 'invoiceActualReceivableAmount',
  258 + width: 120,
  259 + customRender: (column) => {
  260 + return column.record.invoiceActualReceivableAmount?.toFixed(2);
  261 + },
  262 + },
  263 + {
  264 + title: '实际收款金额1$',
  265 + dataIndex: 'invoiceActualPayedAmount1',
  266 + width: 120,
  267 + customRender: (column) => {
  268 + return column.record.invoiceActualPayedAmount1?.toFixed(2);
  269 + },
  270 + },
  271 + {
  272 + title: '实际收款金额2$',
  273 + dataIndex: 'invoiceActualPayedAmount2',
  274 + width: 120,
  275 + customRender: (column) => {
  276 + return column.record.invoiceActualPayedAmount2?.toFixed(2);
  277 + },
  278 + },
  279 + {
  280 + title: '实际收款金额3$',
  281 + dataIndex: 'invoiceActualPayedAmount3',
  282 + width: 120,
  283 + customRender: (column) => {
  284 + return column.record.invoiceActualPayedAmount3?.toFixed(2);
  285 + },
  286 + },
  287 + {
  288 + title: '其他费用$',
  289 + dataIndex: 'invoiceOtherAmount',
  290 + width: 120,
  291 + customRender: (column) => {
  292 + return column.record.invoiceOtherAmount?.toFixed(2);
  293 + },
  294 + },
  295 + {
  296 + title: 'invoice备注',
  297 + dataIndex: 'invoiceNotes',
  298 + width: 200,
  299 + },
  300 + {
  301 + title: 'INVOICE状态',
  302 + dataIndex: 'invoiceStatus',
  303 + width: 120,
  304 + customRender: (column) => {
  305 + if (column.record.invoiceStatus == null || column.record.invoiceStatus == undefined) {
  306 + return '未创建';
  307 + } else if (column.record.invoiceStatus == 0) {
  308 + return '未收款';
  309 + } else if (column.record.invoiceStatus == 10) {
  310 + return '已收款';
  311 + }
  312 + },
  313 + },
  314 + {
  315 + title: 'Action',
  316 + key: 'action', // 对应 #bodyCell 中的 column.key
  317 + width: 280,
  318 + },
  319 + {
  320 + title: '生产科单价¥',
  321 + dataIndex: 'productionDepartmentPrice',
  322 + width: 120,
  323 + customRender: (column) => {
  324 + return column.record.productionDepartmentPrice?.toFixed(2);
  325 + },
  326 + },
  327 + {
  328 + title: '生产科总价¥',
  329 + dataIndex: 'productionDepartmentTotalPrice',
  330 + width: 120,
  331 + customRender: (column) => {
  332 + return column.record.productionDepartmentTotalPrice?.toFixed(2);
  333 + },
  334 + },
  335 + {
  336 + title: 'CheckNo编号',
  337 + dataIndex: 'checkNo',
  338 + width: 120,
  339 + },
  340 + {
  341 + title: '生产科应付款日期',
  342 + dataIndex: 'checkPayedDate',
  343 + width: 140,
  344 + },
  345 + {
  346 + title: '生产科扣款金额¥',
  347 + dataIndex: 'checkDeductAmount',
  348 + width: 160,
  349 + customRender: (column) => {
  350 + return column.record.checkDeductAmount?.toFixed(2);
  351 + },
  352 + },
  353 + {
  354 + title: '扣款责任部门',
  355 + dataIndex: 'checkDeductDept',
  356 + width: 120,
  357 + },
  358 + {
  359 + title: '上传扣款单',
  360 + dataIndex: 'checkDeductUrl',
  361 + width: 120,
  362 + customRender: (column) => {
  363 + const deductUrl = column.record.checkDeductUrl;
  364 + if (deductUrl == undefined) {
  365 + return;
  366 + }
  367 + return <FilePptOutlined style="font-size:25px" />;
  368 + },
  369 + },
  370 + {
  371 + title: '生产科实际应付金额¥',
  372 + dataIndex: 'checkActualPayedAmount',
  373 + width: 180,
  374 + customRender: (column) => {
  375 + return column.record.checkActualPayedAmount?.toFixed(2);
  376 + },
  377 + },
  378 + {
  379 + title: '生产科发票上传',
  380 + dataIndex: 'checkInvoiceUrl',
  381 + width: 80,
  382 + customRender: (column) => {
  383 + const deductUrl = column.record.checkInvoiceUrl;
  384 + if (deductUrl == undefined) {
  385 + return;
  386 + }
  387 + return <FilePptOutlined style="font-size:25px" />;
  388 + },
  389 + },
  390 + {
  391 + title: '实际付款金额1¥',
  392 + dataIndex: 'checkActualPayedAmount1',
  393 + width: 160,
  394 + customRender: (column) => {
  395 + return column.record.checkActualPayedAmount1?.toFixed(2);
  396 + },
  397 + },
  398 + {
  399 + title: '实际付款金额2¥',
  400 + dataIndex: 'checkActualPayedAmount2',
  401 + width: 160,
  402 + customRender: (column) => {
  403 + return column.record.checkActualPayedAmount2?.toFixed(2);
  404 + },
  405 + },
  406 + {
  407 + title: '实际付款金额3¥',
  408 + dataIndex: 'checkActualPayedAmount3',
  409 + width: 160,
  410 + customRender: (column) => {
  411 + return column.record.checkActualPayedAmount3?.toFixed(2);
  412 + },
  413 + },
  414 + {
  415 + title: '生产科发票审核',
  416 + dataIndex: 'checkDepartmentInvoiceStatus',
  417 + width: 120,
  418 + customRender: (column) => {
  419 + if (column.record.checkDepartmentInvoiceStatus == 0) {
  420 + return '待审核';
  421 + } else if (column.record.checkDepartmentInvoiceStatus == 10) {
  422 + return '审核通过';
  423 + } else if (column.record.checkDepartmentInvoiceStatus == 20) {
  424 + return '审核驳回';
  425 + }
  426 + },
  427 + },
  428 + {
  429 + title: '生产科对账单号备注',
  430 + dataIndex: 'checkNotes',
  431 + width: 200,
  432 + },
  433 + {
  434 + title: 'CHECKNO状态',
  435 + dataIndex: 'checkPayStatus',
  436 + width: 120,
  437 + customRender: (column) => {
  438 + if (column.record.checkPayStatus == null || column.record.checkPayStatus == undefined) {
  439 + return '未创建';
  440 + } else if (column.record.checkPayStatus == 0) {
  441 + return '未收款';
  442 + } else if (column.record.checkPayStatus == 10) {
  443 + return '已收款';
  444 + }
  445 + },
  446 + },
  447 + {
  448 + title: 'Action',
  449 + key: 'action2', // 对应 #bodyCell 中的 column.key
  450 + width: 280,
  451 + },
  452 +];
  453 +function formatDate(input: string): string {
  454 + // 创建一个 Date 对象
  455 + const date = new Date(input);
  456 +
  457 + // 获取年月日
  458 + const year = date.getFullYear();
  459 + const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份从 0 开始,所以要加 1
  460 + const day = String(date.getDate()).padStart(2, '0');
  461 +
  462 + // 返回格式化后的日期字符串
  463 + return `${year}-${month}-${day}`;
  464 +}
0 465 \ No newline at end of file
... ...
src/views/project/finance/index.vue 0 → 100644
  1 +<template>
  2 + <div class="p-4">
  3 + <BasicTable @register="registerTable">
  4 + <template #toolbar>
  5 + <a-button
  6 + type="primary"
  7 + @click="handleCommit"
  8 + v-if="role == ROLE.ADMIN || role == ROLE.FINANCE"
  9 + :style="{ borderRadius: '5px 5px 5px 5px' }"
  10 + >提交应收审核</a-button
  11 + >
  12 + <a-button
  13 + type="primary"
  14 + @click="handleCommitCheck"
  15 + v-if="role == ROLE.ADMIN || role == ROLE.FINANCE"
  16 + :style="{ borderRadius: '5px 5px 5px 5px' }"
  17 + >提交应付审核</a-button
  18 + >
  19 + <a-button
  20 + type="primary"
  21 + @click="handleInvoiceAnalysis"
  22 + :style="{ borderRadius: '5px 5px 5px 5px' }"
  23 + v-if="role == ROLE.ADMIN || role == ROLE.FINANCE"
  24 + >收款单分析</a-button
  25 + >
  26 + <a-button
  27 + type="primary"
  28 + @click="handleCheckSumCheck"
  29 + v-if="role == ROLE.ADMIN || role == ROLE.FINANCE"
  30 + :style="{ borderRadius: '5px 5px 5px 5px' }"
  31 + >应付款汇总</a-button
  32 + >
  33 + <a-popconfirm
  34 + title="请确认是否删除?"
  35 + ok-text="是"
  36 + cancel-text="否"
  37 + @confirm="handleDeleteInvoiceIds"
  38 + >
  39 + <a-button type="primary" :style="{ borderRadius: '5px 5px 5px 5px' }"
  40 + >应付款删除</a-button
  41 + >
  42 + </a-popconfirm>
  43 + <a-popconfirm
  44 + title="请确认是否删除?"
  45 + ok-text="是"
  46 + cancel-text="否"
  47 + @confirm="handleDeleteCheckIds"
  48 + >
  49 + <a-button type="primary" :style="{ borderRadius: '5px 5px 5px 5px' }"
  50 + >应收款删除</a-button
  51 + >
  52 + </a-popconfirm>
  53 + <FinanceEdit @register="registerFinanceEdit" @success="handleSuccess" />
  54 + <InvoiceAnalysis @register="registerInvoiceAnalysis" />
  55 + <TrackEdit @register="registerTrackEdit" @success="handleSuccess" />
  56 + <InvoiceDetail @register="registerInvoiceDetail" />
  57 + <DeductShow @register="registerDeductShow" />
  58 + <Commit @register="registerCommit" @success="handleSuccess" />
  59 + <EditRefundTime @register="registerEditRefundTime" @success="handleSuccess" />
  60 + <ReUploadBgUrl @register="registerReUploadBgUrl" @success="handleSuccess" />
  61 + <Note @register="registerNote" @success="handleSuccess" />
  62 + <FinanceEditCheck @register="registerFinanceEditCheck" @success="handleSuccess" />
  63 + <TrackEditCheck @register="registerTrackEditCheck" @success="handleSuccess" />
  64 + <CheckSumCheck @register="registerCheckSumCheck" />
  65 + <InvoiceUploadCheck @register="registerInvoiceUploadCheck" @success="handleSuccess" />
  66 + <CheckDetailCheck @register="registerInvoiceDetailCheck" />
  67 + <DeductShowCheck @register="registerDeductShowCheck" />
  68 + <InvoiceShowCheck @register="registerInvoiceShowCheck" />
  69 + <CommitCheck @register="registerCommitCheck" @success="handleSuccess" />
  70 + <EditRefundTimeCheck @register="registerEditRefundTimeCheck" @success="handleSuccess" />
  71 + <NoteCheck @register="registerNoteCheck" @success="handleSuccess" />
  72 + </template>
  73 + <template #bodyCell="{ column, record }">
  74 + <template v-if="column.key === 'picUrl'">
  75 + <img :z-index="100000" :width="50" :height="50" :src="record?.smallPicUrl" />
  76 + </template>
  77 + <template v-if="column.key === 'action'">
  78 + <TableAction
  79 + :actions="[
  80 + // {
  81 + // label: '财务编辑',
  82 + // onClick: handleFinanceEdit.bind(null, record),
  83 + // },
  84 + ...(role == ROLE.ADMIN || role == ROLE.FINANCE
  85 + ? [
  86 + {
  87 + label: '财务编辑',
  88 + onClick: handleFinanceEdit.bind(null, record),
  89 + },
  90 + ]
  91 + : []),
  92 + {
  93 + label: '跟单编辑',
  94 + onClick: handleTrackEdit.bind(null, record),
  95 + },
  96 + // ...(role == ROLE.ADMIN || role == ROLE.FINANCE
  97 + // ? [
  98 + // {
  99 + // label: '提交审核',
  100 + // onClick: handleCommit.bind(null, record),
  101 + // },
  102 + // ]
  103 + // : []),
  104 + ]"
  105 + :dropDownActions="[
  106 + {
  107 + label: '订单信息',
  108 + onClick: handleInvoiceDetail.bind(null, record),
  109 + },
  110 + {
  111 + label: '更新报关单',
  112 + onClick: handleReUploadBgUrl.bind(null, record),
  113 + },
  114 + // {
  115 + // label: '删除',
  116 + // popConfirm: {
  117 + // title: '是否确认删除',
  118 + // placement: 'left',
  119 + // confirm: handleDelete.bind(null, record),
  120 + // },
  121 + // // onClick: handleDelete.bind(null, record),
  122 + // },
  123 + {
  124 + label: '扣款单',
  125 + onClick: handleDeductShow.bind(null, record),
  126 + },
  127 + ...(role == ROLE.ADMIN
  128 + ? [
  129 + {
  130 + label: '修改必须回款日期',
  131 + onClick: handleEditRefundTime.bind(null, record),
  132 + },
  133 + ]
  134 + : []),
  135 + {
  136 + label: '添加备注',
  137 + onClick: handleNote.bind(null, record),
  138 + },
  139 + ]"
  140 + />
  141 + </template>
  142 + <template v-if="column.key === 'action2'">
  143 + <TableAction
  144 + v-if="
  145 + role == ROLE.ADMIN ||
  146 + role == ROLE.FINANCE ||
  147 + role == ROLE.TRACKER ||
  148 + role == ROLE.BUSINESS
  149 + "
  150 + :actions="[
  151 + ...(role == ROLE.ADMIN || role == ROLE.FINANCE
  152 + ? [
  153 + {
  154 + label: '财务编辑',
  155 + onClick: handleFinanceEditCheck.bind(null, record),
  156 + },
  157 + ]
  158 + : []),
  159 + {
  160 + label: '跟单编辑',
  161 + onClick: handleTrackEditCheck.bind(null, record),
  162 + },
  163 + {
  164 + label: '发票上传',
  165 + onClick: handleInvoiceUploadCheck.bind(null, record),
  166 + },
  167 + ]"
  168 + :dropDownActions="[
  169 + // ...(role == ROLE.ADMIN || role == ROLE.FINANCE
  170 + // ? [
  171 + // {
  172 + // label: '提交审核',
  173 + // onClick: handleCommitCheck.bind(null, record),
  174 + // },
  175 + // ]
  176 + // : []),
  177 + {
  178 + label: '订单信息',
  179 + onClick: handleDetail.bind(null, record),
  180 + },
  181 + // {
  182 + // label: '删除',
  183 + // popConfirm: {
  184 + // title: '是否确认删除',
  185 + // placement: 'left',
  186 + // confirm: handleDelete.bind(null, record),
  187 + // },
  188 + // // onClick: handleDelete.bind(null, record),
  189 + // },
  190 + {
  191 + label: '生产科发票',
  192 + onClick: handleInvoiceShowCheck.bind(null, record),
  193 + },
  194 + {
  195 + label: '扣款单',
  196 + onClick: handleDeductShowCheck.bind(null, record),
  197 + },
  198 + ...(role == ROLE.ADMIN
  199 + ? [
  200 + {
  201 + label: '修改应付款日期',
  202 + onClick: handleEditRefundTimeCheck.bind(null, record),
  203 + },
  204 + ]
  205 + : []),
  206 + {
  207 + label: '添加备注',
  208 + onClick: handleNoteCheck.bind(null, record),
  209 + },
  210 + ]"
  211 + />
  212 + <TableAction
  213 + v-if="role == ROLE.PRODUCE"
  214 + :actions="[
  215 + {
  216 + label: '发票上传',
  217 + onClick: handleInvoiceUploadCheck.bind(null, record),
  218 + },
  219 + {
  220 + label: '生产科发票',
  221 + onClick: handleInvoiceShowCheck.bind(null, record),
  222 + },
  223 + ]"
  224 + />
  225 + </template>
  226 + </template>
  227 + </BasicTable>
  228 + </div>
  229 +</template>
  230 +<script lang="ts" setup>
  231 + import { computed, defineComponent, ref } from 'vue';
  232 + import { BasicTable, useTable, BasicColumn, TableAction } from '/@/components/Table';
  233 + // import { searchFormSchema, columns } from './receive.data';
  234 + import { searchFormSchema, columns } from './finance.data';
  235 + import FinanceEdit from './FinanceEdit.vue';
  236 + import TrackEdit from './TrackEdit.vue';
  237 + import InvoiceAnalysis from './InvoiceAnalysis.vue';
  238 + import InvoiceDetail from './InvoiceDetail.vue';
  239 + import DeductShow from './DeductShow.vue';
  240 + import Commit from './Commit.vue';
  241 + import EditRefundTime from './EditRefundTime.vue';
  242 + import ReUploadBgUrl from './ReUploadBgUrl.vue';
  243 + import Note from './Note.vue';
  244 + import TrackEditCheck from './TrackEditCheck.vue';
  245 + import FinanceEditCheck from './FinanceEditCheck.vue';
  246 + import InvoiceUploadCheck from './InvoiceUploadCheck.vue';
  247 + import CheckDetailCheck from './CheckDetailCheck.vue';
  248 + import CheckSumCheck from './CheckSumCheck.vue';
  249 + import DeductShowCheck from './DeductShowCheck.vue';
  250 + import InvoiceShowCheck from './InvoiceShowCheck.vue';
  251 + import CommitCheck from './CommitCheck.vue';
  252 + import EditRefundTimeCheck from './EditRefundTimeCheck.vue';
  253 + import NoteCheck from './NoteCheck.vue';
  254 + import { useDrawer } from '/@/components/Drawer';
  255 + import {
  256 + getCheck,
  257 + checkDelete,
  258 + checkCommit,
  259 + checkDetail,
  260 + getInvoice,
  261 + deleteInvoice,
  262 + commit,
  263 + getBaseInvoice,
  264 + } from '@/api/project/invoice';
  265 + import { useModal } from '/@/components/Modal';
  266 + import { CheckOutlined, FilePptOutlined } from '@ant-design/icons-vue';
  267 + import { icon } from 'ant-design-vue';
  268 + import { ROLE } from './type.d';
  269 + import { useUserStoreWithOut } from '/@/store/modules/user';
  270 + import { useMessage } from '/@/hooks/web/useMessage';
  271 +
  272 + const [registerInvoiceAnalysis, { openModal: openInvoiceAnalysis }] = useModal();
  273 + const [registerFinanceEdit, { openDrawer: openFinanceEdit }] = useDrawer();
  274 + const [registerTrackEdit, { openDrawer: openTrackEdit }] = useDrawer();
  275 + const [registerInvoiceDetail, { openDrawer: openInvoiceDetail }] = useDrawer();
  276 + const [registerCommit, { openModal: openCommit }] = useModal();
  277 + const [registerEditRefundTime, { openModal: openEditRefundTime }] = useModal();
  278 + const [registerReUploadBgUrl, { openModal: openReUploadBgUrl }] = useModal();
  279 + const [registerNote, { openModal: openNote }] = useModal();
  280 + const [registerDeductShow, { openModal: openDeductShow }] = useModal();
  281 + const [registerCheckSumCheck, { openModal: openCheckSumCheck }] = useModal();
  282 + const [registerFinanceEditCheck, { openDrawer: openFinanceEditCheck }] = useDrawer();
  283 + const [registerTrackEditCheck, { openDrawer: openTrackEditCheck }] = useDrawer();
  284 + const [registerInvoiceUploadCheck, { openModal: openInvoiceUploadCheck }] = useModal();
  285 + const [registerDeductShowCheck, { openModal: openDeductShowCheck }] = useModal();
  286 + const [registerCommitCheck, { openModal: openCommitCheck }] = useModal();
  287 + const [registerEditRefundTimeCheck, { openModal: openEditRefundTimeCheck }] = useModal();
  288 + const [registerInvoiceShowCheck, { openModal: openInvoiceShowCheck }] = useModal();
  289 + const [registerNoteCheck, { openModal: openNoteCheck }] = useModal();
  290 + const [registerInvoiceDetailCheck, { openDrawer: openCheckDetailCheck }] = useDrawer();
  291 + const checkedKeys = ref<Array<string | number>>([]);
  292 + const invoiceIdKeys = ref<Array<string | number>>([]);
  293 + const checkIdKeys = ref<Array<string | number>>([]);
  294 + const userStore = useUserStoreWithOut();
  295 + const user = userStore.getUserInfo;
  296 + const role = computed(() => {
  297 + return user?.roleSmallVO?.code;
  298 + });
  299 + const [registerTable, { reload: reloadTable }] = useTable({
  300 + title: '',
  301 + api: getInvoice,
  302 + columns: columns,
  303 + bordered: true,
  304 + clickToRowSelect: false,
  305 + rowKey: 'id',
  306 + rowSelection: {
  307 + type: 'checkbox',
  308 + selectedRowKeys: checkedKeys,
  309 + onSelect,
  310 + onSelectAll,
  311 + },
  312 + formConfig: {
  313 + labelWidth: 120,
  314 + schemas: searchFormSchema,
  315 + autoSubmitOnEnter: true,
  316 + },
  317 + useSearchForm: true,
  318 + showTableSetting: true,
  319 + showIndexColumn: false,
  320 + tableSetting: {
  321 + setting: false,
  322 + },
  323 + // actionColumn: {
  324 + // width: 330,
  325 + // title: 'Action',
  326 + // dataIndex: 'action',
  327 + // // slots: { customRender: 'action' },
  328 + // },
  329 + });
  330 +
  331 + // 单选函数
  332 + async function onSelect(record, selected: boolean) {
  333 + console.log(record, '5656565656record');
  334 +
  335 + if (selected) {
  336 + checkedKeys.value = [...checkedKeys.value, record.id];
  337 +
  338 + // 仅当 invoiceId 不为 undefined 时,才加入
  339 + if (record.invoiceId !== undefined) {
  340 + invoiceIdKeys.value = [...invoiceIdKeys.value, record.invoiceId];
  341 + }
  342 +
  343 + // 仅当 checkId 不为 undefined 时,才加入
  344 + if (record.checkId !== undefined) {
  345 + checkIdKeys.value = [...checkIdKeys.value, record.checkId];
  346 + }
  347 + } else {
  348 + checkedKeys.value = checkedKeys.value.filter((id) => id !== record.id);
  349 +
  350 + // 仅当 invoiceId 不为 undefined 时,才删除
  351 + if (record.invoiceId !== undefined) {
  352 + invoiceIdKeys.value = invoiceIdKeys.value.filter(
  353 + (invoiceId) => invoiceId !== record.invoiceId,
  354 + );
  355 + }
  356 +
  357 + // 仅当 checkId 不为 undefined 时,才删除
  358 + if (record.checkId !== undefined) {
  359 + checkIdKeys.value = checkIdKeys.value.filter((checkId) => checkId !== record.checkId);
  360 + }
  361 + }
  362 +
  363 + console.log(checkedKeys.value, 565666666); // 输出当前的 checkedKeys 值
  364 + console.log(invoiceIdKeys.value, 565666666); // 输出当前的 selectedCustomCodes 值
  365 + console.log(checkIdKeys.value, 565666666); // 输出当前的 selectedProductionDepartment 值
  366 + }
  367 +
  368 + // 全选函数
  369 + async function onSelectAll(selected: boolean, selectedRows: any[], changeRows: any[]) {
  370 + const changeIds = changeRows.map((item) => item.id);
  371 + const invoiceIds = changeRows.map((item) => item.invoiceId);
  372 + const checkIds = changeRows.map((item) => item.checkId);
  373 +
  374 + if (selected) {
  375 + checkedKeys.value = [...checkedKeys.value, ...changeIds];
  376 +
  377 + // 过滤掉 undefined 的 invoiceId 和 checkId
  378 + invoiceIdKeys.value = [
  379 + ...invoiceIdKeys.value,
  380 + ...invoiceIds.filter((invoiceId) => invoiceId !== undefined),
  381 + ];
  382 + checkIdKeys.value = [
  383 + ...checkIdKeys.value,
  384 + ...checkIds.filter((checkId) => checkId !== undefined),
  385 + ];
  386 + } else {
  387 + checkedKeys.value = checkedKeys.value.filter((id) => !changeIds.includes(id));
  388 +
  389 + // 仅当 invoiceId 不为 undefined 时,才删除
  390 + invoiceIdKeys.value = invoiceIdKeys.value.filter(
  391 + (invoiceId) => invoiceIds.indexOf(invoiceId) === -1,
  392 + );
  393 +
  394 + // 仅当 checkId 不为 undefined 时,才删除
  395 + checkIdKeys.value = checkIdKeys.value.filter((checkId) => checkIds.indexOf(checkId) === -1);
  396 + }
  397 +
  398 + console.log(checkedKeys.value, 565666666); // 输出当前的 checkedKeys 值
  399 + console.log(invoiceIdKeys.value, 565666666); // 输出当前的 selectedCustomCodes 值
  400 + console.log(checkIdKeys.value, 565666666); // 输出当前的 selectedProductionDepartment 值
  401 + }
  402 +
  403 + function handleFinanceEdit(record) {
  404 + openFinanceEdit(true, {
  405 + data: record,
  406 + });
  407 + }
  408 + function handleTrackEdit(record) {
  409 + openTrackEdit(true, {
  410 + data: record,
  411 + });
  412 + }
  413 + function handleDelete(record) {
  414 + const id: string[] = Array.isArray(record.id) ? record.id : [record.id];
  415 + deleteInvoice({ ids: id });
  416 + setTimeout(() => {
  417 + reloadTable();
  418 + }, 50);
  419 + }
  420 + function handleDeleteInvoiceIds() {
  421 + // console.log(checkedKeys.value, '5656checkedKeys.value');
  422 + deleteInvoice({ ids: invoiceIdKeys.value });
  423 + setTimeout(() => {
  424 + reloadTable();
  425 + }, 50);
  426 + }
  427 + function handleDeleteCheckIds() {
  428 + // console.log(checkedKeys.value, '5656checkedKeys.value');
  429 + deleteInvoice({ ids: checkIdKeys.value });
  430 + setTimeout(() => {
  431 + reloadTable();
  432 + }, 50);
  433 + }
  434 + function handleDeductShow(record) {
  435 + openDeductShow(true, {
  436 + data: record,
  437 + });
  438 + }
  439 + function handleCommit(record) {
  440 + openCommit(true, {
  441 + data: invoiceIdKeys.value,
  442 + });
  443 + }
  444 + function handleEditRefundTime(record) {
  445 + openEditRefundTime(true, {
  446 + data: record,
  447 + });
  448 + }
  449 + function handleInvoiceDetail(record) {
  450 + openInvoiceDetail(true, {
  451 + data: record,
  452 + });
  453 + }
  454 + function handleReUploadBgUrl(record) {
  455 + openReUploadBgUrl(true, {
  456 + data: record,
  457 + });
  458 + }
  459 + function handleNote(record) {
  460 + openNote(true, {
  461 + data: record,
  462 + });
  463 + }
  464 + const { createMessage } = useMessage();
  465 + const { error } = createMessage;
  466 + function handleInvoiceAnalysis(record) {
  467 + if (invoiceIdKeys.value.length == 0) {
  468 + error('请选择订单');
  469 + return;
  470 + }
  471 + openInvoiceAnalysis(true, {
  472 + data: invoiceIdKeys.value,
  473 + });
  474 + }
  475 +
  476 + function handleSuccess() {
  477 + setTimeout(() => {
  478 + reloadTable();
  479 + }, 50);
  480 + }
  481 +
  482 + function handleFinanceEditCheck(record) {
  483 + openFinanceEditCheck(true, {
  484 + data: record,
  485 + });
  486 + }
  487 + function handleTrackEditCheck(record) {
  488 + openTrackEditCheck(true, {
  489 + data: record,
  490 + });
  491 + }
  492 + function handleInvoiceUploadCheck(record) {
  493 + openInvoiceUploadCheck(true, {
  494 + data: record,
  495 + });
  496 + }
  497 + function handleInvoiceShowCheck(record) {
  498 + openInvoiceShowCheck(true, {
  499 + data: record,
  500 + });
  501 + }
  502 + function handleNoteCheck(record) {
  503 + openNoteCheck(true, {
  504 + data: record,
  505 + });
  506 + }
  507 + function handleDeductShowCheck(record) {
  508 + openDeductShowCheck(true, {
  509 + data: record,
  510 + });
  511 + }
  512 + function handleDetail(record) {
  513 + openCheckDetailCheck(true, {
  514 + data: record,
  515 + });
  516 + }
  517 + function handleCommitCheck(record) {
  518 + openCommitCheck(true, {
  519 + data: checkIdKeys.value,
  520 + });
  521 + }
  522 + function handleEditRefundTimeCheck(record) {
  523 + openEditRefundTimeCheck(true, {
  524 + data: record,
  525 + });
  526 + }
  527 + function handleCheckSumCheck(record) {
  528 + if (checkIdKeys.value.length == 0) {
  529 + error('请选择订单');
  530 + return;
  531 + }
  532 + openCheckSumCheck(true, {
  533 + data: checkIdKeys.value,
  534 + });
  535 + }
  536 +</script>
... ...
src/views/project/finance/pay/CheckSum.vue
... ... @@ -98,6 +98,7 @@
98 98 const res = await checkAnalysis({ ids: ids.value });
99 99 const arrayRes = ref([]);
100 100 arrayRes.value.push(res);
  101 + console.log(res, '5656payana');
101 102 return res;
102 103 },
103 104 columns: columnsAnalysis,
... ...
src/views/project/finance/pay/InvoiceUpload.vue
... ... @@ -33,8 +33,8 @@
33 33 import { updateInvoiceInfo } from '@/api/project/invoice';
34 34  
35 35 const emit = defineEmits(['success']);
36   - const uploadUrl = ref('http://47.104.8.35:8081/api/localStorage/upload_file_oss?name=');
37   - const updateInvoiceUrl = ref('http://47.104.8.35:8081/api/localStorage/upload_file_oss?name=');
  36 + const uploadUrl = ref('http://47.104.8.35:80/api/localStorage/upload_file_oss?name=');
  37 + const updateInvoiceUrl = ref('http://47.104.8.35:80/api/localStorage/upload_file_oss?name=');
38 38 const invoiceUrl = ref();
39 39 const id = ref();
40 40 const status = ref();
... ...
src/views/project/finance/pay/Note.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 + @visible-change="handleShow"
  10 + >
  11 + 备注:
  12 + <a-textarea v-model:value="notes" placeholder="请输入" :rows="6" />
  13 + <div style="height: 10px"></div>
  14 + </BasicModal>
  15 +</template>
  16 +<script lang="ts" setup>
  17 + import { BasicModal, useModalInner } from '@/components/Modal';
  18 + import { ref } from 'vue';
  19 + import { getSetBackRefundDate } from '@/api/project/invoice';
  20 + import { useMessage } from '/@/hooks/web/useMessage';
  21 +
  22 + const id = ref();
  23 + const notes = ref();
  24 + const checkedKeys = ref();
  25 + const emit = defineEmits(['success']);
  26 + const { createMessage } = useMessage();
  27 + const { error } = createMessage;
  28 + const [register, { closeModal }] = useModalInner(async (data) => {
  29 + // id.value = data.data.id;
  30 + checkedKeys.value = data.checkedKeys;
  31 + });
  32 + const isDisabled = ref(false);
  33 + async function handleOk() {
  34 + if (isDisabled.value) {
  35 + error('请勿连续点击生成按钮,需要等待三秒再点击生成');
  36 + return;
  37 + }
  38 + isDisabled.value = true;
  39 + setTimeout(() => {
  40 + isDisabled.value = false;
  41 + }, 3000);
  42 + getSetBackRefundDate({ id: checkedKeys.value, notes: notes.value });
  43 + emit('success');
  44 + closeModal();
  45 + }
  46 + function handleShow(visible: boolean) {
  47 + if (!visible) {
  48 + notes.value = null;
  49 + }
  50 + }
  51 +</script>
... ...
src/views/project/finance/pay/TrackEdit.vue
... ... @@ -87,8 +87,10 @@
87 87 const id = ref();
88 88 const checkNo = ref();
89 89 const deductDept = ref();
90   - const uploadUrl = ref('http://47.104.8.35:8081/api/localStorage/upload_file_oss?name=');
91   - const updateDeductUrl = ref('http://47.104.8.35:8081/api/localStorage/upload_file_oss?name=');
  90 + const uploadUrl = ref('http://47.104.8.35:80/api/localStorage/upload_file_oss?name=');
  91 + const updateDeductUrl = ref('http://47.104.8.35:80/api/localStorage/upload_file_oss?name=');
  92 + // const uploadUrl = ref('');
  93 + // const updateDeductUrl = ref('');
92 94 const deductUrlOld = ref();
93 95 const selectedProductionDepartment = ref(); // 新增: 用于存储选中的生产科
94 96 const { createMessage } = useMessage();
... ...
src/views/project/finance/pay/index.vue
... ... @@ -17,6 +17,7 @@
17 17 <InvoiceShow @register="registerInvoiceShow" />
18 18 <Commit @register="registerCommit" @success="handleSuccess" />
19 19 <EditRefundTime @register="registerEditRefundTime" @success="handleSuccess" />
  20 + <Note @register="registerNote" @success="handleSuccess" />
20 21 </template>
21 22 <template #bodyCell="{ column, record }">
22 23 <template v-if="column.key === 'action'">
... ... @@ -83,6 +84,10 @@
83 84 },
84 85 ]
85 86 : []),
  87 + {
  88 + label: '添加备注',
  89 + onClick: handleNote.bind(null, record),
  90 + },
86 91 ]"
87 92 />
88 93 <TableAction
... ... @@ -116,6 +121,7 @@
116 121 import InvoiceShow from './InvoiceShow.vue';
117 122 import Commit from './Commit.vue';
118 123 import EditRefundTime from './EditRefundTime.vue';
  124 + import Note from './Note.vue';
119 125 import { useDrawer } from '/@/components/Drawer';
120 126 import { useModal } from '/@/components/Modal';
121 127 import { getCheck, checkDelete, checkCommit, checkDetail } from '@/api/project/invoice';
... ... @@ -132,6 +138,7 @@
132 138 const [registerCommit, { openModal: openCommit }] = useModal();
133 139 const [registerEditRefundTime, { openModal: openEditRefundTime }] = useModal();
134 140 const [registerInvoiceShow, { openModal: openInvoiceShow }] = useModal();
  141 + const [registerNote, { openModal: openNote }] = useModal();
135 142 const [registerInvoiceDetail, { openDrawer: openCheckDetail }] = useDrawer();
136 143 const userStore = useUserStoreWithOut();
137 144 const user = userStore.getUserInfo;
... ... @@ -350,6 +357,11 @@
350 357 data: record,
351 358 });
352 359 }
  360 + function handleNote(record) {
  361 + openNote(true, {
  362 + data: record,
  363 + });
  364 + }
353 365 function handleDeductShow(record) {
354 366 openDeductShow(true, {
355 367 data: record,
... ...
src/views/project/finance/payBack/CheckDetailCheck.vue 0 → 100644
  1 +<template>
  2 + <template>
  3 + <BasicDrawer
  4 + @register="register"
  5 + v-bind="$attrs"
  6 + title="订单信息"
  7 + width="60%"
  8 + :isDetail="true"
  9 + :showDetailBack="false"
  10 + :destroyOnClose="true"
  11 + >
  12 + <div class="p-4">
  13 + <BasicTable @register="registerTable">
  14 + <template #bodyCell="{ column, record }">
  15 + <template v-if="column.key === 'action'"> </template>
  16 + <template v-if="column.key === 'picUrl'">
  17 + <img :z-index="100000" :width="50" :height="50" :src="record?.smallPicUrl" />
  18 + </template>
  19 + </template>
  20 + </BasicTable>
  21 + </div>
  22 + </BasicDrawer>
  23 + </template>
  24 +</template>
  25 +<script lang="ts" setup>
  26 + import { BasicDrawer, useDrawerInner } from '@/components/Drawer';
  27 + import { defineComponent, ref, computed, unref, toRaw, reactive } from 'vue';
  28 + import { BasicColumn, useTable, BasicTable, ColumnChangeParam } from '/@/components/Table';
  29 + import { checkDetail } from '/@/api/project/invoice';
  30 + import { useDesign } from '@/hooks/web/useDesign';
  31 +
  32 + // const handlePreview = (url) => {
  33 + // createImgPreview({ imageList: [url], defaultWidth: 500 });
  34 + // return false;
  35 + // };
  36 + const columns: BasicColumn[] = [
  37 + {
  38 + title: '客户编码',
  39 + dataIndex: 'customerCode',
  40 + width: 100,
  41 + },
  42 + {
  43 + title: '项目号',
  44 + dataIndex: 'projectNo',
  45 + width: 100,
  46 + },
  47 + {
  48 + title: '内部编码',
  49 + dataIndex: 'innerNo',
  50 + width: 100,
  51 + },
  52 + {
  53 + title: '客户po号',
  54 + dataIndex: 'customerPo',
  55 + width: 100,
  56 + },
  57 + {
  58 + title: '客户STYLE',
  59 + width: 150,
  60 + dataIndex: 'customerStyle',
  61 + },
  62 + {
  63 + title: 'Model(REFERENCE)',
  64 + width: 150,
  65 + dataIndex: 'modeleLo',
  66 + },
  67 + {
  68 + title: '订单图片',
  69 + width: 150,
  70 + dataIndex: 'picUrl',
  71 + },
  72 + {
  73 + title: '数量',
  74 + width: 150,
  75 + dataIndex: 'orderCount',
  76 + },
  77 + {
  78 + title: '生产科单价¥',
  79 + width: 150,
  80 + dataIndex: 'productionDepartmentPrice',
  81 + customRender: (column) => {
  82 + const { record } = column || {};
  83 + return record?.profitAnalysisInfo?.productionDepartmentPrice?.toFixed(2);
  84 + // ? `¥ ${record?.profitAnalysisInfo?.productionDepartmentPrice}`
  85 + // : '';
  86 + },
  87 + },
  88 + {
  89 + title: '生产科总价¥',
  90 + width: 150,
  91 + dataIndex: 'productionDepartmentTotalPrice',
  92 + customRender: (column) => {
  93 + const { record } = column || {};
  94 + return record?.profitAnalysisInfo?.productionDepartmentTotalPrice?.toFixed(2);
  95 + // ? `¥ ${record?.profitAnalysisInfo?.productionDepartmentTotalPrice}`
  96 + // : '';
  97 + },
  98 + },
  99 + ];
  100 + const checkNo = ref();
  101 +
  102 + const [register, { setDrawerProps, closeDrawer }] = useDrawerInner((data) => {
  103 + // 方式1
  104 + checkNo.value = data.data.checkNo;
  105 + // checkDetail({ checkNo: checkNo.value });
  106 + });
  107 + const params = ref({
  108 + checkNo: checkNo.value,
  109 + });
  110 + const [registerTable] = useTable({
  111 + api: () => {
  112 + const res = checkDetail({ checkNo: checkNo.value });
  113 + return res;
  114 + },
  115 + columns: columns,
  116 + bordered: true,
  117 + });
  118 +</script>
... ...
src/views/project/finance/payBack/CheckSumCheck.vue 0 → 100644
  1 +<template>
  2 + <BasicModal
  3 + v-bind="$attrs"
  4 + @register="register"
  5 + title="应收款汇总"
  6 + width="60%"
  7 + okText="导出"
  8 + :isDetail="true"
  9 + :showDetailBack="false"
  10 + @ok="handleOk"
  11 + @visible-change="handleShow"
  12 + >
  13 + <div class="p-4">
  14 + <BasicTable @register="registerTable">
  15 + <template #bodyCell="{ column, record }">
  16 + <template v-if="column.key === 'action'"> </template>
  17 + </template>
  18 + </BasicTable>
  19 + </div>
  20 + </BasicModal>
  21 +</template>
  22 +<script lang="ts" setup>
  23 + import { BasicModal, useModalInner } from '@/components/Modal';
  24 + import { computed, ref } from 'vue';
  25 + import { checkAnalysis, exportCheckAnalysis } from '@/api/project/invoice';
  26 + import { BasicColumn, useTable, BasicTable, ColumnChangeParam } from '/@/components/Table';
  27 + // 处理弹窗的确定按钮点击事件
  28 + import axios from 'axios';
  29 +
  30 + const columnsAnalysis: BasicColumn[] = [
  31 + {
  32 + title: '生产科名称',
  33 + dataIndex: 'productionDepartment',
  34 + width: 150,
  35 + customRender: (res) => {
  36 + // console.log(res, 56562);
  37 + return res.record.exportVOS[0].productionDepartment;
  38 + },
  39 + },
  40 + {
  41 + title: '生产科总价汇总¥',
  42 + dataIndex: 'productionDepartmentTotalPrice',
  43 + width: 150,
  44 + customRender: (res) => {
  45 + // console.log(res, 56562);
  46 + return res.record.productionDepartmentTotalPrice.toFixed(2);
  47 + },
  48 + },
  49 + {
  50 + title: '生产科扣款金额汇总¥',
  51 + dataIndex: 'deductAmount',
  52 + width: 160,
  53 + customRender: (res) => {
  54 + // console.log(res, 56562);
  55 + return res.record.deductAmount.toFixed(2);
  56 + },
  57 + },
  58 + {
  59 + title: '生产科实际应付金额¥',
  60 + dataIndex: 'calculateActualPayedAmount',
  61 + width: 160,
  62 + customRender: (res) => {
  63 + return res.record.calculateActualPayedAmount.toFixed(2);
  64 + },
  65 + },
  66 + {
  67 + title: '实际付款金额汇总¥',
  68 + dataIndex: 'actualPayedAmount',
  69 + width: 160,
  70 + customRender: (res) => {
  71 + // console.log(res, 56562);
  72 + return res.record.actualPayedAmount.toFixed(2);
  73 + },
  74 + },
  75 + {
  76 + title: '未付金额¥',
  77 + dataIndex: 'unPayedAmount',
  78 + width: 150,
  79 + customRender: (res) => {
  80 + // console.log(res, 56562);
  81 + return res.record.unPayedAmount.toFixed(2);
  82 + },
  83 + },
  84 + ];
  85 + // const ids = ref<number[]>([]);
  86 + const ids = ref();
  87 + // const res = ref();
  88 +
  89 + const [register, { closeModal }] = useModalInner(async (data) => {
  90 + ids.value = data.data;
  91 + setTimeout(() => {
  92 + reload();
  93 + }, 50);
  94 + });
  95 + const [registerTable, { reload }] = useTable({
  96 + // api: () => invoiceAnalysis({ ids: ids.value }),
  97 + api: async () => {
  98 + const res = await checkAnalysis({ ids: ids.value });
  99 + const arrayRes = ref([]);
  100 + arrayRes.value.push(res);
  101 + console.log(res, '5656payana');
  102 + return res;
  103 + },
  104 + columns: columnsAnalysis,
  105 + bordered: true,
  106 + });
  107 + function handleShow(visible: boolean) {
  108 + reload();
  109 + }
  110 + const searchData = ref({});
  111 + async function handleOk() {
  112 + // 构造符合 API 要求的参数
  113 + // const ids = [23];
  114 + // const requestData = {
  115 + // ids: ids.value,
  116 + // };
  117 + const idss = ids.value;
  118 + // await exportCheckAnalysis({ ids: ids });
  119 + axios
  120 + .post(
  121 + '/basic-api/order/erp/check_bill/export',
  122 + { ids: idss },
  123 + {
  124 + responseType: 'blob', // 设置响应类型为 'blob'
  125 + },
  126 + )
  127 + .then((response) => {
  128 + // 创建一个 Blob 对象来保存二进制数据
  129 + const blob = new Blob([response.data], { type: 'application/zip' });
  130 + const getFormattedDate = (): string => {
  131 + const date = new Date();
  132 +
  133 + const year = date.getFullYear();
  134 + const month = String(date.getMonth() + 1).padStart(2, '0');
  135 + const day = String(date.getDate()).padStart(2, '0');
  136 +
  137 + const hours = String(date.getHours()).padStart(2, '0');
  138 + const minutes = String(date.getMinutes()).padStart(2, '0');
  139 + const seconds = String(date.getSeconds()).padStart(2, '0');
  140 +
  141 + return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
  142 + };
  143 + const date = getFormattedDate();
  144 + // 创建一个链接元素用于下载
  145 + const link = document.createElement('a');
  146 + link.href = window.URL.createObjectURL(blob);
  147 + link.download = `应付款分析${date}.xlsx`; // 你可以为文件命名
  148 + document.body.appendChild(link);
  149 + link.click(); // 自动点击链接,触发下载
  150 + document.body.removeChild(link); // 下载完成后移除链接
  151 + })
  152 + .catch((error) => {
  153 + console.error(error);
  154 + });
  155 + reload();
  156 + closeModal();
  157 + }
  158 +</script>
  159 +<style scoped>
  160 + .divAll {
  161 + display: flex;
  162 + justify-content: center;
  163 + align-items: center;
  164 + }
  165 +</style>
... ...
src/views/project/finance/payBack/CommitCheck.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 { checkCommit } from '@/api/project/invoice';
  18 + import { useMessage } from '/@/hooks/web/useMessage';
  19 +
  20 + const id = ref();
  21 + const date = ref();
  22 + const emit = defineEmits(['success']);
  23 + const { createMessage } = useMessage();
  24 + const { error } = createMessage;
  25 + const [register, { closeModal }] = useModalInner(async (data) => {
  26 + id.value = data.data.id;
  27 + });
  28 + function formatDate(input: string): string {
  29 + // 创建一个 Date 对象
  30 + const date = new Date(input);
  31 +
  32 + // 获取年月日
  33 + const year = date.getFullYear();
  34 + const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份从 0 开始,所以要加 1
  35 + const day = String(date.getDate()).padStart(2, '0');
  36 +
  37 + // 返回格式化后的日期字符串
  38 + return `${year}-${month}-${day}`;
  39 + }
  40 + const isDisabled = ref(false);
  41 + async function handleOk() {
  42 + if (isDisabled.value) {
  43 + error('请勿连续点击生成按钮,需要等待三秒再点击生成');
  44 + return;
  45 + }
  46 + const formattedDate = formatDate(date.value);
  47 + isDisabled.value = true;
  48 + setTimeout(() => {
  49 + isDisabled.value = false;
  50 + }, 3000);
  51 + checkCommit({ id: id.value, actualPayedDate: formattedDate });
  52 + emit('success');
  53 + closeModal();
  54 + }
  55 +</script>
... ...
src/views/project/finance/payBack/DeductShowCheck.vue 0 → 100644
  1 +<template>
  2 + <BasicModal
  3 + v-bind="$attrs"
  4 + @register="register"
  5 + title="扣款单"
  6 + width="700px"
  7 + :bodyStyle="{ height: '240px' }"
  8 + @ok="handleOk"
  9 + >
  10 + <a-list item-layout="horizontal" :data-source="itemArray">
  11 + <template #renderItem="{ item }">
  12 + <a-list-item>
  13 + <a-list-item-meta>
  14 + <template #title>
  15 + <!-- <a :href="item.url" target="_blank" rel="noopener noreferrer">{{ 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> -->
  30 + </template>
  31 + </a-list-item-meta>
  32 + </a-list-item>
  33 + </template>
  34 + </a-list>
  35 + </BasicModal>
  36 +</template>
  37 +<script lang="ts" setup>
  38 + import { BasicModal, useModalInner } from '@/components/Modal';
  39 + import { computed, ref } from 'vue';
  40 + import type { UploadProps, UploadChangeParam } from 'ant-design-vue';
  41 + import { InboxOutlined } from '@ant-design/icons-vue';
  42 + import { message } from 'ant-design-vue';
  43 + import { getDeductUrlById } from '@/api/project/invoice';
  44 + import { view } from '@/utils/pdfShow';
  45 +
  46 + interface Item {
  47 + name: string;
  48 + url: string;
  49 + }
  50 +
  51 + const list = ref();
  52 + const id = ref();
  53 + const itemArray = ref<Item[]>([]);
  54 +
  55 + const [register, { closeModal }] = useModalInner(async (data) => {
  56 + itemArray.value = [];
  57 + const res = await getDeductUrlById({ id: data.data.id });
  58 + for (let item in res) {
  59 + const url = res[item];
  60 + const name = item;
  61 + // 将 name 和 url 放入对象并添加到数组中
  62 + itemArray.value.push({ name, url });
  63 + }
  64 + });
  65 +
  66 + async function handleOk() {
  67 + itemArray.value = [];
  68 + closeModal();
  69 + }
  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 + // 检查 URL 是否为 PDF 格式
  78 + function isPdfUrl(url: string): boolean {
  79 + return url.toLowerCase().endsWith('.pdf');
  80 + }
  81 + // 打开图片或 PDF
  82 + function openPic(url: string) {
  83 + const baseUrl = url.split('?')[0]; // 获取问号前的部分
  84 + if (isImageUrl(baseUrl)) {
  85 + window.open('', '', '').document.write(`<!DOCTYPE html>
  86 + <html>
  87 + <body style="display: flex; justify-content: center; align-items: center;">
  88 + <img src='${url}' width="300px" height="auto"/>
  89 + </body>
  90 + </html>`);
  91 + } else if (isPdfUrl(baseUrl)) {
  92 + view(url); // 新标签页打开 PDF
  93 + } else {
  94 + console.log('不支持的文件类型');
  95 + }
  96 + }
  97 +</script>
... ...
src/views/project/finance/payBack/EditRefundTimeCheck.vue 0 → 100644
  1 +<template>
  2 + <BasicModal
  3 + v-bind="$attrs"
  4 + @register="register"
  5 + title="修改应付款日期"
  6 + width="500px"
  7 + :bodyStyle="{ height: '240px' }"
  8 + @visible-change="handleShow"
  9 + @ok="handleOk"
  10 + >
  11 + 请选择日期:
  12 + <a-date-picker v-model:value="date" />
  13 + <div style="height: 10px"></div>
  14 + </BasicModal>
  15 +</template>
  16 +<script lang="ts" setup>
  17 + import { BasicModal, useModalInner } from '@/components/Modal';
  18 + import { ref } from 'vue';
  19 + import { getSetPayedDate } from '@/api/project/invoice';
  20 + import { useMessage } from '/@/hooks/web/useMessage';
  21 +
  22 + const id = ref();
  23 + const date = ref();
  24 + const emit = defineEmits(['success']);
  25 + const { createMessage } = useMessage();
  26 + const { error } = createMessage;
  27 + const [register, { closeModal }] = useModalInner(async (data) => {
  28 + id.value = data.data.id;
  29 + });
  30 + function formatDate(input: string): string {
  31 + // 创建一个 Date 对象
  32 + const date = new Date(input);
  33 +
  34 + // 获取年月日
  35 + const year = date.getFullYear();
  36 + const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份从 0 开始,所以要加 1
  37 + const day = String(date.getDate()).padStart(2, '0');
  38 +
  39 + // 返回格式化后的日期字符串
  40 + return `${year}-${month}-${day}`;
  41 + }
  42 + const isDisabled = ref(false);
  43 + async function handleOk() {
  44 + if (isDisabled.value) {
  45 + error('请勿连续点击生成按钮,需要等待三秒再点击生成');
  46 + return;
  47 + }
  48 + const formattedDate = formatDate(date.value);
  49 + isDisabled.value = true;
  50 + setTimeout(() => {
  51 + isDisabled.value = false;
  52 + }, 3000);
  53 + getSetPayedDate({ id: id.value, payedDate: formattedDate });
  54 + emit('success');
  55 + closeModal();
  56 + }
  57 + function handleShow(visible: boolean) {
  58 + if (!visible) {
  59 + date.value = null;
  60 + }
  61 + }
  62 +</script>
... ...
src/views/project/finance/payBack/FinanceEditCheck.vue 0 → 100644
  1 +<template>
  2 + <template>
  3 + <BasicDrawer
  4 + @register="register"
  5 + v-bind="$attrs"
  6 + title="编辑"
  7 + width="30%"
  8 + :isDetail="true"
  9 + @ok="handleSubmit"
  10 + :showDetailBack="false"
  11 + okText="保存"
  12 + showFooter
  13 + :destroyOnClose="true"
  14 + >
  15 + <!-- <div>
  16 + <BasicForm @register="registerForm" />
  17 + </div> -->
  18 + <div style="font-size: 15px">实际付款金额1¥</div>
  19 + <a-input v-model:value="input1" placeholder="请输入" :disabled="status === 10" auto-size />
  20 + <div style="margin: 16px 0"></div>
  21 + <div style="font-size: 15px">实际付款金额2¥</div>
  22 + <a-input v-model:value="input2" placeholder="请输入" :disabled="status === 10" auto-size />
  23 + <div style="margin: 16px 0"></div>
  24 + <div style="font-size: 15px">实际付款金额3¥</div>
  25 + <a-input v-model:value="input3" placeholder="请输入" :disabled="status === 10" auto-size />
  26 + <div style="margin: 16px 0"></div>
  27 +
  28 + <!-- <template #titleToolbar> <a-button type="primary"> 申请编辑权限 </a-button></template> -->
  29 + <template #appendFooter>
  30 + <!-- <a-button type="primary" @click="onGoCheckDetail"> 申请权限</a-button> -->
  31 + </template>
  32 + </BasicDrawer>
  33 + </template>
  34 +</template>
  35 +<script lang="ts" setup>
  36 + import { BasicDrawer, useDrawerInner } from '@/components/Drawer';
  37 + import { BasicForm, FormSchema, useForm } from '@/components/Form';
  38 + import { defineComponent, ref, computed, unref, toRaw, reactive } from 'vue';
  39 + import { getEmailList } from '/@/api/sys/config';
  40 + import { updateAmountInfo } from '@/api/project/invoice';
  41 + import { useMessage } from '/@/hooks/web/useMessage';
  42 +
  43 + const emit = defineEmits(['success']);
  44 + const schemas: FormSchema[] = [
  45 + // {
  46 + // field: 'actualPayedAmount',
  47 + // component: 'InputNumber',
  48 + // labelWidth: 250,
  49 + // colProps: {
  50 + // span: 23,
  51 + // },
  52 + // label: '生产科实际应付金额',
  53 + // },
  54 + {
  55 + field: 'actualPayedAmount1',
  56 + component: 'InputNumber',
  57 + labelWidth: 250,
  58 + colProps: {
  59 + span: 23,
  60 + },
  61 + label: '实际应付金额1¥',
  62 + componentProps: () => ({
  63 + disabled: status.value === 10,
  64 + }),
  65 + },
  66 + {
  67 + field: 'actualPayedAmount2',
  68 + component: 'InputNumber',
  69 + labelWidth: 250,
  70 + colProps: {
  71 + span: 23,
  72 + },
  73 + label: '实际应付金额2¥',
  74 + componentProps: () => ({
  75 + disabled: status.value === 10,
  76 + }),
  77 + },
  78 + {
  79 + field: 'actualPayedAmount3',
  80 + component: 'InputNumber',
  81 + labelWidth: 250,
  82 + colProps: {
  83 + span: 23,
  84 + },
  85 + label: '实际应付金额3¥',
  86 + componentProps: () => ({
  87 + disabled: status.value === 10,
  88 + }),
  89 + },
  90 + ];
  91 + const [registerForm, { setFieldsValue, resetFields, validate }] = useForm({
  92 + labelWidth: 120,
  93 + schemas,
  94 + layout: 'vertical',
  95 + showActionButtonGroup: false,
  96 + actionColOptions: {
  97 + span: 24,
  98 + },
  99 + });
  100 + const { createMessage } = useMessage();
  101 + const { error } = createMessage;
  102 + const update = ref();
  103 + const status = ref();
  104 + const input1 = ref();
  105 + const input2 = ref();
  106 + const input3 = ref();
  107 + const id = ref();
  108 + const [register, { setDrawerProps, closeDrawer }] = useDrawerInner((data) => {
  109 + // 方式1
  110 + resetFields();
  111 + status.value = data.data.status;
  112 + id.value = data.data.id;
  113 + input1.value = data.data.actualPayedAmount1;
  114 + input2.value = data.data.actualPayedAmount2;
  115 + input3.value = data.data.actualPayedAmount3;
  116 + setDrawerProps({ confirmLoading: false });
  117 + // 将金额格式化为两位小数
  118 + // setFieldsValue({
  119 + // actualPayedAmount1:
  120 + // data.data.actualPayedAmount1 !== null ? data.data.actualPayedAmount1.toFixed(2) : undefined,
  121 + // actualPayedAmount2:
  122 + // data.data.actualPayedAmount2 !== null ? data.data.actualPayedAmount2.toFixed(2) : undefined,
  123 + // actualPayedAmount3:
  124 + // data.data.actualPayedAmount3 !== null ? data.data.actualPayedAmount3.toFixed(2) : undefined,
  125 + // ...toRaw(data.data), // 其他字段
  126 + // });
  127 + setFieldsValue({
  128 + ...toRaw(data.data),
  129 + });
  130 + update.value = data;
  131 + });
  132 + //完成编辑
  133 + async function handleSubmit() {
  134 + // const values = await validate();
  135 + // const updatedValues = {
  136 + // ...values,
  137 + // id: update.value.data.id,
  138 + // };
  139 + if (!input1.value || !input2.value || !input3.value) {
  140 + error('选项不能为空');
  141 + } else {
  142 + await updateAmountInfo({
  143 + id: id.value,
  144 + actualPayedAmount1: input1.value,
  145 + actualPayedAmount2: input2.value,
  146 + actualPayedAmount3: input3.value,
  147 + });
  148 + emit('success');
  149 + closeDrawer();
  150 + }
  151 + }
  152 +</script>
... ...
src/views/project/finance/payBack/InvoiceShowCheck.vue 0 → 100644
  1 +<template>
  2 + <BasicModal
  3 + v-bind="$attrs"
  4 + @register="register"
  5 + title="生产科发票"
  6 + width="700px"
  7 + :bodyStyle="{ height: '240px' }"
  8 + @ok="handleOk"
  9 + >
  10 + <a-list item-layout="horizontal" :data-source="itemArray">
  11 + <template #renderItem="{ item }">
  12 + <a-list-item>
  13 + <a-list-item-meta>
  14 + <template #title>
  15 + <!-- <a :href="item.url" target="_blank" rel="noopener noreferrer">{{ item.name }}</a> -->
  16 + <a @click="view(item.url)">{{ item.name }}</a>
  17 + </template>
  18 + </a-list-item-meta>
  19 + </a-list-item>
  20 + </template>
  21 + </a-list>
  22 + </BasicModal>
  23 +</template>
  24 +<script lang="ts" setup>
  25 + import { BasicModal, useModalInner } from '@/components/Modal';
  26 + import { computed, ref } from 'vue';
  27 + import type { UploadProps, UploadChangeParam } from 'ant-design-vue';
  28 + import { InboxOutlined } from '@ant-design/icons-vue';
  29 + import { message } from 'ant-design-vue';
  30 + import { getDeductUrlById, getInvoiceUrlById } from '@/api/project/invoice';
  31 + import { view } from '@/utils/pdfShow';
  32 +
  33 + interface Item {
  34 + name: string;
  35 + url: string;
  36 + }
  37 +
  38 + const list = ref();
  39 + const id = ref();
  40 + const itemArray = ref<Item[]>([]);
  41 +
  42 + const [register, { closeModal }] = useModalInner(async (data) => {
  43 + itemArray.value = [];
  44 + const res = await getInvoiceUrlById({ id: data.data.id });
  45 + for (let item in res) {
  46 + const url = res[item];
  47 + const name = item;
  48 + // 将 name 和 url 放入对象并添加到数组中
  49 + itemArray.value.push({ name, url });
  50 + }
  51 + });
  52 +
  53 + async function handleOk() {
  54 + itemArray.value = [];
  55 + closeModal();
  56 + }
  57 +</script>
... ...
src/views/project/finance/payBack/InvoiceUploadCheck.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 + ><a-upload-dragger
  10 + v-model:fileList="fileList"
  11 + name="file"
  12 + :beforeUpload="beforeUpload"
  13 + :max-count="1"
  14 + :multiple="true"
  15 + :action="updateInvoiceUrl"
  16 + @change="handleChange"
  17 + @drop="handleDrop"
  18 + :disabled="status === 10"
  19 + >
  20 + <p class="ant-upload-drag-icon">
  21 + <inbox-outlined></inbox-outlined>
  22 + </p>
  23 + <p class="ant-upload-text">点击或将文件拖拽到这里上传</p>
  24 + </a-upload-dragger>
  25 + </BasicModal>
  26 +</template>
  27 +<script lang="ts" setup>
  28 + import { BasicModal, useModalInner } from '@/components/Modal';
  29 + import { computed, ref } from 'vue';
  30 + import type { UploadProps, UploadChangeParam } from 'ant-design-vue';
  31 + import { InboxOutlined } from '@ant-design/icons-vue';
  32 + import { message } from 'ant-design-vue';
  33 + import { updateInvoiceInfo } from '@/api/project/invoice';
  34 +
  35 + const emit = defineEmits(['success']);
  36 + const uploadUrl = ref('http://47.104.8.35:80/api/localStorage/upload_file_oss?name=');
  37 + const updateInvoiceUrl = ref('http://47.104.8.35:80/api/localStorage/upload_file_oss?name=');
  38 + const invoiceUrl = ref();
  39 + const id = ref();
  40 + const status = ref();
  41 + const [register, { closeModal }] = useModalInner(async (data) => {
  42 + console.log(data);
  43 + status.value = data.data.status;
  44 + // fileList.value = [];
  45 + fileList.value = [];
  46 + invoiceUrl.value = data.data.invoiceUrl;
  47 + id.value = data.data.id;
  48 + });
  49 +
  50 + const handleChange = (info) => {
  51 + if (info.file.status == 'done') {
  52 + updateInvoiceUrl.value = info.file.response.data.fileUrl;
  53 + invoiceUrl.value = updateInvoiceUrl.value;
  54 + }
  55 + };
  56 + function beforeUpload(info) {
  57 + updateInvoiceUrl.value = uploadUrl.value + info.name;
  58 + }
  59 + function handleDrop(e: DragEvent) {
  60 + console.log(e);
  61 + }
  62 + const fileList = ref<UploadProps['fileList']>([]);
  63 +
  64 + async function handleOk() {
  65 + await updateInvoiceInfo({
  66 + id: id.value,
  67 + invoiceUrl: invoiceUrl.value,
  68 + });
  69 + fileList.value = [];
  70 + emit('success');
  71 + closeModal();
  72 + }
  73 +</script>
... ...
src/views/project/finance/payBack/NoteCheck.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 + @visible-change="handleShow"
  10 + >
  11 + 备注:
  12 + <a-textarea v-model:value="notes" placeholder="请输入" :rows="6" />
  13 + <div style="height: 10px"></div>
  14 + </BasicModal>
  15 +</template>
  16 +<script lang="ts" setup>
  17 + import { BasicModal, useModalInner } from '@/components/Modal';
  18 + import { ref } from 'vue';
  19 + import { getSetBackRefundDate } from '@/api/project/invoice';
  20 + import { useMessage } from '/@/hooks/web/useMessage';
  21 +
  22 + const id = ref();
  23 + const notes = ref();
  24 + const checkedKeys = ref();
  25 + const emit = defineEmits(['success']);
  26 + const { createMessage } = useMessage();
  27 + const { error } = createMessage;
  28 + const [register, { closeModal }] = useModalInner(async (data) => {
  29 + // id.value = data.data.id;
  30 + checkedKeys.value = data.checkedKeys;
  31 + });
  32 + const isDisabled = ref(false);
  33 + async function handleOk() {
  34 + if (isDisabled.value) {
  35 + error('请勿连续点击生成按钮,需要等待三秒再点击生成');
  36 + return;
  37 + }
  38 + isDisabled.value = true;
  39 + setTimeout(() => {
  40 + isDisabled.value = false;
  41 + }, 3000);
  42 + getSetBackRefundDate({ id: checkedKeys.value, notes: notes.value });
  43 + emit('success');
  44 + closeModal();
  45 + }
  46 + function handleShow(visible: boolean) {
  47 + if (!visible) {
  48 + notes.value = null;
  49 + }
  50 + }
  51 +</script>
... ...
src/views/project/finance/payBack/TrackEditCheck.vue 0 → 100644
  1 +<template>
  2 + <template>
  3 + <BasicDrawer
  4 + @register="register"
  5 + v-bind="$attrs"
  6 + title="跟单编辑"
  7 + width="30%"
  8 + :isDetail="true"
  9 + @ok="handleSubmit"
  10 + :showDetailBack="false"
  11 + @visible-change="handleShow"
  12 + okText="保存"
  13 + showFooter
  14 + :destroyOnClose="true"
  15 + >
  16 + <div>
  17 + <div style="font-size: 15px">生产科扣款金额¥</div>
  18 + <a-input v-model:value="input1" placeholder="请输入" :disabled="status === 10" auto-size />
  19 + <div style="margin: 16px 0"></div>
  20 + <div style="font-size: 15px">扣款责任部门</div>
  21 + <a-input
  22 + v-model:value="deductDept"
  23 + placeholder="请输入"
  24 + :disabled="status === 10"
  25 + auto-size
  26 + />
  27 + <!-- <a-select
  28 + ref="select"
  29 + style="width: 60%"
  30 + v-model:value="selectedProductionDepartment"
  31 + :options="productionDepartmentOptions"
  32 + /> -->
  33 + <!-- <a-select
  34 + ref="select"
  35 + style="width: 100%"
  36 + v-model:value="productionDepartment"
  37 + :options="productDepartmentOptions"
  38 + /> -->
  39 + <div style="margin: 16px 0"></div>
  40 + <div>上传扣款单</div
  41 + ><a-space direction="vertical" style="width: 100%" size="large">
  42 + <a-upload
  43 + v-model:file-list="fileList"
  44 + :beforeUpload="beforeUpload"
  45 + list-type="picture"
  46 + :max-count="1"
  47 + :disabled="status === 10"
  48 + :action="updateDeductUrl"
  49 + @change="handleChange"
  50 + >
  51 + <a-button> 上传扣款单 </a-button>
  52 + </a-upload>
  53 + </a-space>
  54 + </div>
  55 + <!-- <template #titleToolbar> <a-button type="primary"> 申请编辑权限 </a-button></template> -->
  56 + <template #appendFooter>
  57 + <!-- <a-button type="primary" @click="onGoCheckDetail"> 申请权限</a-button> -->
  58 + </template>
  59 + </BasicDrawer>
  60 + </template>
  61 +</template>
  62 +<script lang="ts" setup>
  63 + import { BasicDrawer, useDrawerInner } from '@/components/Drawer';
  64 + import { defineComponent, ref, computed, unref, toRaw, reactive, onMounted } from 'vue';
  65 + import { getEmailList } from '/@/api/sys/config';
  66 + import { UploadOutlined } from '@ant-design/icons-vue';
  67 + import type { UploadProps } from 'ant-design-vue';
  68 + import { updateDeductInfo } from '@/api/project/invoice';
  69 + import { useMessage } from '/@/hooks/web/useMessage';
  70 + import { useOrderInfo } from '/@/hooks/component/order';
  71 + import { useOrderStoreWithOut } from '/@/store/modules/order';
  72 +
  73 + const emit = defineEmits(['success']);
  74 + const fileList = ref<UploadProps['fileList']>([]);
  75 + // const orderStore = useOrderStoreWithOut();
  76 + // const { productionDepartment: productionDepartmentOptions } = useOrderInfo(orderStore);
  77 + // console.log(productionDepartmentOptions.value, '565656565665orderStore');
  78 + // onMounted(() => {
  79 + // const { productionDepartment } = useOrderInfo(orderStore);
  80 + // console.log(productionDepartment.value, '565656565665orderStore1');
  81 + // });
  82 + const orderStore = useOrderStoreWithOut();
  83 + const { productionDepartment: productDepartmentOptions } = useOrderInfo(orderStore);
  84 + const productionDepartment = ref();
  85 + const input1 = ref(0);
  86 + const deductUrl = ref();
  87 + const id = ref();
  88 + const checkNo = ref();
  89 + const deductDept = ref();
  90 + const uploadUrl = ref('http://47.104.8.35:80/api/localStorage/upload_file_oss?name=');
  91 + const updateDeductUrl = ref('http://47.104.8.35:80/api/localStorage/upload_file_oss?name=');
  92 + // const uploadUrl = ref('');
  93 + // const updateDeductUrl = ref('');
  94 + const deductUrlOld = ref();
  95 + const selectedProductionDepartment = ref(); // 新增: 用于存储选中的生产科
  96 + const { createMessage } = useMessage();
  97 + const { error } = createMessage;
  98 + const status = ref();
  99 +
  100 + const [register, { setDrawerProps, closeDrawer }] = useDrawerInner((data) => {
  101 + status.value = data.data.status;
  102 + id.value = data.data.id;
  103 + checkNo.value = data.data.checkNo;
  104 + input1.value = data.data.deductAmount;
  105 + deductDept.value = data.data.deductDept;
  106 + deductUrl.value = data.data.deductUrl;
  107 + deductUrlOld.value = data.data.deductUrl;
  108 + });
  109 + function handleChange(info) {
  110 + if (info.file.status == 'done') {
  111 + updateDeductUrl.value = info.file.response.data.fileUrl;
  112 + deductUrl.value = updateDeductUrl.value;
  113 + }
  114 + if (info.fileList.length == 0) {
  115 + info.file = null;
  116 + deductUrl.value = '';
  117 + }
  118 + }
  119 + function beforeUpload(info) {
  120 + updateDeductUrl.value = uploadUrl.value + info.name;
  121 + }
  122 + function handleShow() {
  123 + // input1.value = '';
  124 + // deductUrl.value = '';
  125 + // deductDept.value = '';
  126 + // updateDeductUrl.value = '';
  127 + // fileList.value = [];
  128 + }
  129 + //完成编辑
  130 + async function handleSubmit() {
  131 + if (!input1.value || !deductDept.value) {
  132 + error('选项不能为空');
  133 + } else {
  134 + await updateDeductInfo({
  135 + id: id.value,
  136 + checkNo: checkNo.value,
  137 + deductAmount: input1.value,
  138 + deductDept: deductDept.value,
  139 + deductUrl: deductUrl.value,
  140 + });
  141 + // productionDepartment: selectedProductionDepartment.value,
  142 + fileList.value = [];
  143 + emit('success');
  144 + closeDrawer();
  145 + }
  146 + }
  147 +</script>
... ...
src/views/project/finance/payBack/pay.data.tsx 0 → 100644
  1 +import { FormSchema } from '/@/components/Form';
  2 +import { BasicColumn } from '/@/components/Table';
  3 +import { icon } from 'ant-design-vue';
  4 +import { FolderAddOutlined, FilePptOutlined } from '@ant-design/icons-vue';
  5 +import { size } from 'lodash-es';
  6 +
  7 +export const searchFormSchema: FormSchema[] = [
  8 + {
  9 + field: 'checkNo',
  10 + label: '生产科对账单号',
  11 + component: 'Input',
  12 + colProps: { span: 8 },
  13 + },
  14 + {
  15 + field: 'productionDepartment',
  16 + label: '生产科',
  17 + component: 'Input',
  18 + colProps: { span: 8 },
  19 + },
  20 + {
  21 + field: 'status',
  22 + label: '总经理审核',
  23 + component: 'Select',
  24 + colProps: { span: 8 },
  25 + componentProps: {
  26 + options: [
  27 + { label: '未提交审核', value: -1 },
  28 + { label: '待审核', value: 0 },
  29 + { label: '审核通过', value: 10 },
  30 + { label: '审核驳回', value: 20 },
  31 + ],
  32 + },
  33 + },
  34 + {
  35 + field: 'customerCode',
  36 + label: '客户编码',
  37 + component: 'Input',
  38 + colProps: {
  39 + span: 8,
  40 + },
  41 + },
  42 +];
  43 +
  44 +export const columns: BasicColumn[] = [
  45 + {
  46 + title: '生产科对账单号',
  47 + dataIndex: 'checkNo',
  48 + width: 120,
  49 + },
  50 + {
  51 + title: '生产科应付款日期',
  52 + dataIndex: 'payedDate',
  53 + width: 140,
  54 + },
  55 + {
  56 + title: '生产科扣款金额¥',
  57 + dataIndex: 'deductAmount',
  58 + width: 160,
  59 + // customRender: (column) => {
  60 + // return column.record.deductAmount?.toFixed(2);
  61 + // },
  62 + },
  63 + {
  64 + title: '扣款责任部门',
  65 + dataIndex: 'deductDept',
  66 + width: 120,
  67 + },
  68 + {
  69 + title: '上传扣款单',
  70 + dataIndex: 'deductUrl',
  71 + width: 120,
  72 + customRender: (column) => {
  73 + const deductUrl = column.record.deductUrl;
  74 + if (deductUrl == undefined) {
  75 + return;
  76 + }
  77 + return <FilePptOutlined style="font-size:25px" />;
  78 + },
  79 + },
  80 + {
  81 + title: '生产科实际应付金额¥',
  82 + dataIndex: 'actualPayedAmount',
  83 + width: 180,
  84 + // customRender: (column) => {
  85 + // return column.record.actualPayedAmount?.toFixed(2);
  86 + // },
  87 + },
  88 + {
  89 + title: '生产科发票上传',
  90 + dataIndex: 'invoiceUrl',
  91 + width: 80,
  92 + customRender: (column) => {
  93 + const deductUrl = column.record.invoiceUrl;
  94 + if (deductUrl == undefined) {
  95 + return;
  96 + }
  97 + return <FilePptOutlined style="font-size:25px" />;
  98 + },
  99 + },
  100 + {
  101 + title: '实际付款金额1¥',
  102 + dataIndex: 'actualPayedAmount1',
  103 + width: 160,
  104 + // customRender: (column) => {
  105 + // console.log(column, '5656ccc');
  106 + // return column.record.actualPayedAmount1?.toFixed(2);
  107 + // },
  108 + },
  109 + {
  110 + title: '实际付款金额2¥',
  111 + dataIndex: 'actualPayedAmount2',
  112 + width: 160,
  113 + // customRender: (column) => {
  114 + // return column.record.actualPayedAmount2?.toFixed(2);
  115 + // },
  116 + },
  117 + {
  118 + title: '实际付款金额3¥',
  119 + dataIndex: 'actualPayedAmount3',
  120 + width: 160,
  121 + // customRender: (column) => {
  122 + // return column.record.actualPayedAmount3?.toFixed(2);
  123 + // },
  124 + },
  125 + {
  126 + title: '生产科发票审核',
  127 + dataIndex: 'departmentInvoiceStatus',
  128 + width: 120,
  129 + customRender: (column) => {
  130 + if (column.record.departmentInvoiceStatus == 0) {
  131 + return '待审核';
  132 + } else if (column.record.departmentInvoiceStatus == 10) {
  133 + return '审核通过';
  134 + } else if (column.record.departmentInvoiceStatus == 20) {
  135 + return '审核驳回';
  136 + }
  137 + },
  138 + },
  139 + {
  140 + title: '总经理审核',
  141 + dataIndex: 'status',
  142 + width: 120,
  143 + customRender: (column) => {
  144 + if (column.record.status == -1) {
  145 + return '未提交审核';
  146 + } else if (column.record.status == 0) {
  147 + return '待审核';
  148 + } else if (column.record.status == 10) {
  149 + return '审核通过';
  150 + } else if (column.record.status == 20) {
  151 + return '审核驳回';
  152 + }
  153 + },
  154 + },
  155 +];
... ...
src/views/project/finance/payBack/type.d.ts 0 → 100644
  1 +export enum ROLE {
  2 + ADMIN = 'admin', // 超管
  3 + CUSTOM_ADMIN = 'custom_admin', // 客户管理员
  4 + DATA_REPORT_USER = 'data_report_user', //数据分析员
  5 + BUSINESS = 'business_user', // 业务员
  6 + TRACKER = 'tracker_user', // 跟单员
  7 + INSPECT = 'inspect_user', // 质检员
  8 + PRODUCE = 'produce_user', //生产科
  9 + FINANCE = 'finance_user', //生产科
  10 +}
... ...
src/views/project/finance/receive.data.tsx 0 → 100644
  1 +import { FormSchema } from '/@/components/Form';
  2 +import { BasicColumn } from '/@/components/Table';
  3 +import { icon } from 'ant-design-vue';
  4 +import { FilePptOutlined } from '@ant-design/icons-vue';
  5 +import { size } from 'lodash-es';
  6 +import { ref } from 'vue';
  7 +import { view } from '@/utils/pdfShow';
  8 +
  9 +export const searchFormSchema: FormSchema[] = [
  10 + {
  11 + field: 'invoiceNo',
  12 + label: 'Invoice编号',
  13 + component: 'Input',
  14 + colProps: { span: 6 },
  15 + },
  16 + {
  17 + field: 'status',
  18 + label: '总经理审核',
  19 + component: 'Select',
  20 + colProps: { span: 6 },
  21 + componentProps: {
  22 + options: [
  23 + { label: '未提交审核', value: -1 },
  24 + { label: '待审核', value: 0 },
  25 + { label: '审核通过', value: 10 },
  26 + { label: '审核驳回', value: 20 },
  27 + ],
  28 + },
  29 + },
  30 + {
  31 + field: 'customerCode',
  32 + label: '客户编码',
  33 + component: 'Input',
  34 + colProps: {
  35 + span: 6,
  36 + },
  37 + // labelWidth: 140,
  38 + },
  39 +];
  40 +
  41 +export const columns: BasicColumn[] = [
  42 + {
  43 + title: 'Invoice编号',
  44 + dataIndex: 'invoiceNo',
  45 + width: 180,
  46 + },
  47 + {
  48 + title: '报关单',
  49 + dataIndex: 'bgUrl',
  50 + width: 80,
  51 + customRender: (column) => {
  52 + const bgUrl = column.record.bgUrl;
  53 + if (bgUrl == undefined) {
  54 + return;
  55 + }
  56 + return <FilePptOutlined style="font-size:25px" onClick={() => view(bgUrl)} />;
  57 + },
  58 + },
  59 + {
  60 + title: '必须回款日期',
  61 + dataIndex: 'backRefundDate',
  62 + width: 120,
  63 + },
  64 + {
  65 + title: '发生扣款金额$',
  66 + dataIndex: 'deductAmount',
  67 + width: 120,
  68 + // customRender: (column) => {
  69 + // return column.record.deductAmount?.toFixed(2);
  70 + // },
  71 + },
  72 + {
  73 + title: '上传扣款单',
  74 + dataIndex: 'deductUrl',
  75 + width: 80,
  76 + customRender: (column) => {
  77 + const deductUrl = column.record.deductUrl;
  78 + if (deductUrl == undefined) {
  79 + return;
  80 + }
  81 + // return <FilePptOutlined style="font-size:25px" onClick={() => window.open(deductUrl[0])} />;
  82 + return <FilePptOutlined style="font-size:25px" />;
  83 + },
  84 + },
  85 + {
  86 + title: '实际应收金额$',
  87 + dataIndex: 'actualReceivableAmount',
  88 + width: 120,
  89 + // customRender: (column) => {
  90 + // return column.record.actualReceivableAmount?.toFixed(2);
  91 + // },
  92 + },
  93 + {
  94 + title: '实际收款金额1$',
  95 + dataIndex: 'actualPayedAmount1',
  96 + width: 120,
  97 + // customRender: (column) => {
  98 + // return column.record.actualPayedAmount1?.toFixed(2);
  99 + // },
  100 + },
  101 + {
  102 + title: '实际收款金额2$',
  103 + dataIndex: 'actualPayedAmount2',
  104 + width: 120,
  105 + // customRender: (column) => {
  106 + // return column.record.actualPayedAmount2?.toFixed(2);
  107 + // },
  108 + },
  109 + {
  110 + title: '实际收款金额3$',
  111 + dataIndex: 'actualPayedAmount3',
  112 + width: 120,
  113 + // customRender: (column) => {
  114 + // return column.record.actualPayedAmount3?.toFixed(2);
  115 + // },
  116 + },
  117 + {
  118 + title: '其他费用$',
  119 + dataIndex: 'otherAmount',
  120 + width: 120,
  121 + customRender: (column) => {
  122 + return column.record.otherAmount?.toFixed(2);
  123 + },
  124 + },
  125 + {
  126 + title: '总经理审核',
  127 + dataIndex: 'status',
  128 + width: 120,
  129 + customRender: (column) => {
  130 + if (column.record.status == -1) {
  131 + return '未提交审核';
  132 + } else if (column.record.status == 0) {
  133 + return '待审核';
  134 + } else if (column.record.status == 10) {
  135 + return '审核通过';
  136 + } else if (column.record.status == 20) {
  137 + return '审核驳回';
  138 + }
  139 + },
  140 + },
  141 + {
  142 + title: '操作1',
  143 + key: 'action', // 对应 #bodyCell 中的 column.key
  144 + width: 280,
  145 + },
  146 + {
  147 + title: '操作2',
  148 + key: 'action2', // 对应 #bodyCell 中的 column.key
  149 + width: 280,
  150 + },
  151 +];
  152 +
  153 +export const columnsAnalysis: BasicColumn[] = [
  154 + {
  155 + title: '实际应付金额总计$',
  156 + dataIndex: 'actualPayedAmount',
  157 + width: 50,
  158 + customRender: (column) => {
  159 + return column.record.actualPayedAmount?.toFixed(2);
  160 + },
  161 + },
  162 + {
  163 + title: '实际应收金额总计$',
  164 + dataIndex: 'actualReceivableAmount',
  165 + width: 50,
  166 + customRender: (column) => {
  167 + return column.record.actualReceivableAmount?.toFixed(2);
  168 + },
  169 + },
  170 + {
  171 + title: '客户总价$',
  172 + dataIndex: 'customerTotalPrice',
  173 + width: 50,
  174 + customRender: (column) => {
  175 + return column.record.customerTotalPrice?.toFixed(2);
  176 + },
  177 + },
  178 + {
  179 + title: '发生扣款金额总计$',
  180 + dataIndex: 'deductAmount',
  181 + width: 50,
  182 + customRender: (column) => {
  183 + return column.record.deductAmount?.toFixed(2);
  184 + },
  185 + },
  186 + {
  187 + title: '实际应收金额总计$',
  188 + dataIndex: 'actualReceivableAmount',
  189 + width: 50,
  190 + customRender: (column) => {
  191 + return column.record.actualReceivableAmount?.toFixed(2);
  192 + },
  193 + },
  194 + {
  195 + title: '实际应收$',
  196 + dataIndex: 'otherAmount',
  197 + width: 50,
  198 + customRender: (column) => {
  199 + return column.record.otherAmount?.toFixed(2);
  200 + },
  201 + },
  202 + {
  203 + title: '其他费用金额汇总$',
  204 + dataIndex: 'otherTotalAmount',
  205 + width: 50,
  206 + customRender: (column) => {
  207 + return column.record.otherTotalAmount?.toFixed(2);
  208 + },
  209 + },
  210 +];
... ...
src/views/project/finance/receive/Commit.vue
... ... @@ -30,7 +30,7 @@
30 30 const { createMessage } = useMessage();
31 31 const { error } = createMessage;
32 32 const [register, { closeModal }] = useModalInner(async (data) => {
33   - id.value = data.data.id;
  33 + id.value = data.checkedKeys;
34 34 });
35 35 function formatDate(input: string): string {
36 36 // 创建一个 Date 对象
... ...