Commit c1f5be7741d0723a3ecd908473a8ca720ba3dcfe
fix: bug修复
Showing
41 changed files
with
2862 additions
and
492 deletions
src/api/project/approve.ts
@@ -21,12 +21,11 @@ export const approveAuditApi = async (params: any) => | @@ -21,12 +21,11 @@ export const approveAuditApi = async (params: any) => | ||
21 | { message: '操作成功' }, | 21 | { message: '操作成功' }, |
22 | ); | 22 | ); |
23 | 23 | ||
24 | -export const getWaitListApi = async (params: DemoParams) => { | 24 | +export const getWaitListApi = async (params: any) => { |
25 | const res = await defHttp.post({ | 25 | const res = await defHttp.post({ |
26 | url: Api.APPROVE, | 26 | url: Api.APPROVE, |
27 | params, | 27 | params, |
28 | }); | 28 | }); |
29 | - | ||
30 | res.records = res.records.map((item) => { | 29 | res.records = res.records.map((item) => { |
31 | return item; | 30 | return item; |
32 | }); | 31 | }); |
@@ -44,7 +43,6 @@ export const getApprovedListApi = async (params: any) => { | @@ -44,7 +43,6 @@ export const getApprovedListApi = async (params: any) => { | ||
44 | res.records = res.records.map((item) => { | 43 | res.records = res.records.map((item) => { |
45 | return item; | 44 | return item; |
46 | }); | 45 | }); |
47 | - | ||
48 | return new Promise((resolve) => { | 46 | return new Promise((resolve) => { |
49 | resolve({ items: res.records, total: res.total }); | 47 | resolve({ items: res.records, total: res.total }); |
50 | }); | 48 | }); |
src/api/project/invoice.ts
@@ -52,6 +52,12 @@ enum Api { | @@ -52,6 +52,12 @@ enum Api { | ||
52 | SERVICEAPPLYEDIT = '/project/applyEditFileds', //申请修改 | 52 | SERVICEAPPLYEDIT = '/project/applyEditFileds', //申请修改 |
53 | APPLYLIST = '/project/pageProjectLockFieldApply', //分页查询项目字段申请记录 | 53 | APPLYLIST = '/project/pageProjectLockFieldApply', //分页查询项目字段申请记录 |
54 | AUDITAPPLY = '/project/audit', //审核 | 54 | AUDITAPPLY = '/project/audit', //审核 |
55 | + ACTIONRECORD = '/projectOptLog/listByPage', //业务/内部研发净利润操作记录以及申请记录 | ||
56 | + ORDERCOSTDETAILEDOPTLOG = '/orderCostDetailedOptLog/listByPage', //包装费用明细/内部生产明细操作记录表 | ||
57 | + SETPACKSTATUS = '/order/cost/setPackStatus', //包装费用明细表审批 | ||
58 | + SETINNERSTATUS = '/order/cost/setInnerStatus', //内部生产明细表审批 | ||
59 | + PROJECTBUSINESSPROFITSETSTATUS = '/project/businessProfit/setStatus', //业务研发净利润分析表审批 | ||
60 | + PROJECTINNERPROFITSETSTATUS = '/project/innerProfitInfo/setStatus', //内部研发净利润分析表审批 | ||
55 | } | 61 | } |
56 | 62 | ||
57 | export const getRefundDate = async (params: any, data?: any) => { | 63 | export const getRefundDate = async (params: any, data?: any) => { |
@@ -429,18 +435,30 @@ export const getServiceApplyEdit = async (params: any) => { | @@ -429,18 +435,30 @@ export const getServiceApplyEdit = async (params: any) => { | ||
429 | }; | 435 | }; |
430 | 436 | ||
431 | export const getApplyList = async (params: any) => { | 437 | export const getApplyList = async (params: any) => { |
432 | - const res = ref(); | ||
433 | - res.value = await defHttp.post<any>({ | 438 | + // const res = ref(); |
439 | + // res.value = await defHttp.post<any>({ | ||
440 | + // url: Api.APPLYLIST, | ||
441 | + // params, | ||
442 | + // }); | ||
443 | + // res.value.data.records.forEach((record) => { | ||
444 | + // const jsonObj = JSON.parse(record?.fields); | ||
445 | + // if (jsonObj) { | ||
446 | + // record.fields = jsonObj; | ||
447 | + // } | ||
448 | + // }); | ||
449 | + // return res.value.data.records; | ||
450 | + const data = await defHttp.post({ | ||
434 | url: Api.APPLYLIST, | 451 | url: Api.APPLYLIST, |
435 | params, | 452 | params, |
436 | }); | 453 | }); |
437 | - res.value.data.records.forEach((record) => { | ||
438 | - const jsonObj = JSON.parse(record?.fields); | ||
439 | - if (jsonObj) { | ||
440 | - record.fields = jsonObj; | ||
441 | - } | 454 | + const res = data.data; |
455 | + res.records = res.records.map((item) => { | ||
456 | + return item; | ||
457 | + }); | ||
458 | + | ||
459 | + return new Promise((resolve) => { | ||
460 | + resolve({ items: res.records, total: res.total }); | ||
442 | }); | 461 | }); |
443 | - return res.value.data.records; | ||
444 | }; | 462 | }; |
445 | 463 | ||
446 | export const getAuditApply = async (params: any) => { | 464 | export const getAuditApply = async (params: any) => { |
@@ -476,4 +494,71 @@ export const checkSetFinishStatus = async (params: any) => { | @@ -476,4 +494,71 @@ export const checkSetFinishStatus = async (params: any) => { | ||
476 | url: Api.SETCHECKFINISHSTATUS, | 494 | url: Api.SETCHECKFINISHSTATUS, |
477 | params, | 495 | params, |
478 | }); | 496 | }); |
479 | -}; | ||
480 | \ No newline at end of file | 497 | \ No newline at end of file |
498 | +}; | ||
499 | +export const getProjectOptLog = async (params: any) => { | ||
500 | + const res = await defHttp.post<any>({ | ||
501 | + url: Api.ACTIONRECORD, | ||
502 | + params, | ||
503 | + }); | ||
504 | + const formattedRecords = res.records.map((record: any) => { | ||
505 | + return { | ||
506 | + ...record, | ||
507 | + }; | ||
508 | + }); | ||
509 | + const orderStore = useOrderStoreWithOut(); | ||
510 | + orderStore.setTotal(res.total); | ||
511 | + orderStore.setQueryVO(params); | ||
512 | + return new Promise((resolve) => { | ||
513 | + resolve({ | ||
514 | + items: formattedRecords, | ||
515 | + total: res.total, | ||
516 | + }); | ||
517 | + }); | ||
518 | +}; | ||
519 | + | ||
520 | +export const getOrderCostDetailedOptLog = async (params: any) => { | ||
521 | + const res = await defHttp.post<any>({ | ||
522 | + url: Api.ORDERCOSTDETAILEDOPTLOG, | ||
523 | + params, | ||
524 | + }); | ||
525 | + const formattedRecords = res.records.map((record: any) => { | ||
526 | + return { | ||
527 | + ...record, | ||
528 | + }; | ||
529 | + }); | ||
530 | + const orderStore = useOrderStoreWithOut(); | ||
531 | + orderStore.setTotal(res.total); | ||
532 | + orderStore.setQueryVO(params); | ||
533 | + return new Promise((resolve) => { | ||
534 | + resolve({ | ||
535 | + items: formattedRecords, | ||
536 | + total: res.total, | ||
537 | + }); | ||
538 | + }); | ||
539 | +}; | ||
540 | +export const setPackStatus = async (params: any) => { | ||
541 | + return await defHttp.post<any>({ | ||
542 | + url: Api.SETPACKSTATUS, | ||
543 | + params, | ||
544 | + }); | ||
545 | +}; | ||
546 | +export const setInnerStatus = async (params: any) => { | ||
547 | + return await defHttp.post<any>({ | ||
548 | + url: Api.SETINNERSTATUS, | ||
549 | + params, | ||
550 | + }); | ||
551 | +}; | ||
552 | + | ||
553 | +export const setBusinessProfitSetStatus = async (params: any) => { | ||
554 | + return await defHttp.post<any>({ | ||
555 | + url: Api.PROJECTBUSINESSPROFITSETSTATUS, | ||
556 | + params, | ||
557 | + }); | ||
558 | +}; | ||
559 | + | ||
560 | +export const setInnerProfitSetStatus = async (params: any) => { | ||
561 | + return await defHttp.post<any>({ | ||
562 | + url: Api.PROJECTINNERPROFITSETSTATUS, | ||
563 | + params, | ||
564 | + }); | ||
565 | +}; |
src/router/routes/modules/project/finance.ts
@@ -43,106 +43,106 @@ const finance: AppRouteModule = { | @@ -43,106 +43,106 @@ const finance: AppRouteModule = { | ||
43 | }, | 43 | }, |
44 | component: () => import('/@/views/project/finance/financeList/index.vue'), | 44 | component: () => import('/@/views/project/finance/financeList/index.vue'), |
45 | }, | 45 | }, |
46 | - // { | ||
47 | - // path: 'financeProfit', | ||
48 | - // name: 'FinanceProfit', | ||
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 | - // children: [ | ||
62 | - // // { | ||
63 | - // // path: '', | ||
64 | - // // name: 'Receive', | ||
65 | - // // meta: { | ||
66 | - // // title: '财务管理', | ||
67 | - // // roles: [RoleEnum.ADMIN, RoleEnum.FINANCE, RoleEnum.TRACKER, RoleEnum.BUSINESS], | ||
68 | - // // ignoreKeepAlive: false, | ||
69 | - // // }, | ||
70 | - // // // component: () => import('/@/views/project/finance/index.vue'), | ||
71 | - // // }, | ||
72 | - // { | ||
73 | - // path: 'serviceProfit', | ||
74 | - // name: 'ServiceProfit', | ||
75 | - // meta: { | ||
76 | - // title: '业务研发净利润分析', | ||
77 | - // roles: [RoleEnum.ADMIN, RoleEnum.FINANCE, RoleEnum.TRACKER, RoleEnum.BUSINESS], | ||
78 | - // ignoreKeepAlive: false, | ||
79 | - // }, | ||
80 | - // children: [ | ||
81 | - // { | ||
82 | - // path: 'ServiceProfit', | ||
83 | - // name: 'ServiceProfit', | ||
84 | - // meta: { | ||
85 | - // title: '业务研发净利润分析表', | ||
86 | - // roles: [RoleEnum.ADMIN, RoleEnum.FINANCE, RoleEnum.TRACKER, RoleEnum.BUSINESS], | ||
87 | - // ignoreKeepAlive: false, | ||
88 | - // }, | ||
89 | - // component: () => | ||
90 | - // import( | ||
91 | - // '/@/views/project/finance/financeProfit/ServiceProfit/ServiceProfit/index.vue' | ||
92 | - // ), | ||
93 | - // }, | ||
94 | - // { | ||
95 | - // path: 'PackageProfit', | ||
96 | - // name: 'PackageProfit', | ||
97 | - // meta: { | ||
98 | - // title: '包装费用明细表', | ||
99 | - // roles: [RoleEnum.ADMIN, RoleEnum.FINANCE, RoleEnum.TRACKER, RoleEnum.BUSINESS], | ||
100 | - // ignoreKeepAlive: false, | ||
101 | - // }, | ||
102 | - // component: () => | ||
103 | - // import( | ||
104 | - // '/@/views/project/finance/financeProfit/ServiceProfit/PackageProfit/index.vue' | ||
105 | - // ), | ||
106 | - // }, | ||
107 | - // ], | ||
108 | - // }, | ||
109 | - // { | ||
110 | - // path: 'ProductProfit', | ||
111 | - // name: 'ProductProfit', | ||
112 | - // meta: { | ||
113 | - // title: '内部生产净利润分析', | ||
114 | - // roles: [RoleEnum.ADMIN, RoleEnum.FINANCE, RoleEnum.TRACKER, RoleEnum.BUSINESS], | ||
115 | - // ignoreKeepAlive: false, | ||
116 | - // }, | ||
117 | - // children: [ | ||
118 | - // { | ||
119 | - // path: 'InnerData', | ||
120 | - // name: 'InnerData', | ||
121 | - // meta: { | ||
122 | - // title: '内部生产净利润分析表', | ||
123 | - // roles: [RoleEnum.ADMIN, RoleEnum.FINANCE, RoleEnum.TRACKER, RoleEnum.BUSINESS], | ||
124 | - // ignoreKeepAlive: false, | ||
125 | - // }, | ||
126 | - // component: () => | ||
127 | - // import( | ||
128 | - // '/@/views/project/finance/financeProfit/ProductProfit/InnerProduce/index.vue' | ||
129 | - // ), | ||
130 | - // }, | ||
131 | - // { | ||
132 | - // path: 'InnerProduce', | ||
133 | - // name: 'InnerProduce', | ||
134 | - // meta: { | ||
135 | - // title: '内部生产明细表', | ||
136 | - // roles: [RoleEnum.ADMIN, RoleEnum.FINANCE, RoleEnum.TRACKER, RoleEnum.BUSINESS], | ||
137 | - // ignoreKeepAlive: false, | ||
138 | - // }, | ||
139 | - // component: () => | ||
140 | - // import('/@/views/project/finance/financeProfit/ProductProfit/InnerData/index.vue'), | ||
141 | - // }, | ||
142 | - // ], | ||
143 | - // }, | ||
144 | - // ], | ||
145 | - // }, | 46 | + { |
47 | + path: 'financeProfit', | ||
48 | + name: 'FinanceProfit', | ||
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 | + children: [ | ||
62 | + // { | ||
63 | + // path: '', | ||
64 | + // name: 'Receive', | ||
65 | + // meta: { | ||
66 | + // title: '财务管理', | ||
67 | + // roles: [RoleEnum.ADMIN, RoleEnum.FINANCE, RoleEnum.TRACKER, RoleEnum.BUSINESS], | ||
68 | + // ignoreKeepAlive: false, | ||
69 | + // }, | ||
70 | + // // component: () => import('/@/views/project/finance/index.vue'), | ||
71 | + // }, | ||
72 | + { | ||
73 | + path: 'serviceProfit', | ||
74 | + name: 'ServiceProfit', | ||
75 | + meta: { | ||
76 | + title: '业务研发净利润分析', | ||
77 | + roles: [RoleEnum.ADMIN, RoleEnum.FINANCE, RoleEnum.TRACKER, RoleEnum.BUSINESS], | ||
78 | + ignoreKeepAlive: false, | ||
79 | + }, | ||
80 | + children: [ | ||
81 | + { | ||
82 | + path: 'ServiceProfit', | ||
83 | + name: 'ServiceProfit', | ||
84 | + meta: { | ||
85 | + title: '业务研发净利润分析表', | ||
86 | + roles: [RoleEnum.ADMIN, RoleEnum.FINANCE, RoleEnum.TRACKER, RoleEnum.BUSINESS], | ||
87 | + ignoreKeepAlive: false, | ||
88 | + }, | ||
89 | + component: () => | ||
90 | + import( | ||
91 | + '/@/views/project/finance/financeProfit/ServiceProfit/ServiceProfit/index.vue' | ||
92 | + ), | ||
93 | + }, | ||
94 | + { | ||
95 | + path: 'PackageProfit', | ||
96 | + name: 'PackageProfit', | ||
97 | + meta: { | ||
98 | + title: '包装费用明细表', | ||
99 | + roles: [RoleEnum.ADMIN, RoleEnum.FINANCE, RoleEnum.TRACKER, RoleEnum.BUSINESS], | ||
100 | + ignoreKeepAlive: false, | ||
101 | + }, | ||
102 | + component: () => | ||
103 | + import( | ||
104 | + '/@/views/project/finance/financeProfit/ServiceProfit/PackageProfit/index.vue' | ||
105 | + ), | ||
106 | + }, | ||
107 | + ], | ||
108 | + }, | ||
109 | + { | ||
110 | + path: 'ProductProfit', | ||
111 | + name: 'ProductProfit', | ||
112 | + meta: { | ||
113 | + title: '内部生产净利润分析', | ||
114 | + roles: [RoleEnum.ADMIN, RoleEnum.FINANCE, RoleEnum.TRACKER, RoleEnum.BUSINESS], | ||
115 | + ignoreKeepAlive: false, | ||
116 | + }, | ||
117 | + children: [ | ||
118 | + { | ||
119 | + path: 'InnerProduce', | ||
120 | + name: 'InnerProduce', | ||
121 | + meta: { | ||
122 | + title: '内部生产净利润分析表', | ||
123 | + roles: [RoleEnum.ADMIN, RoleEnum.FINANCE, RoleEnum.TRACKER, RoleEnum.BUSINESS], | ||
124 | + ignoreKeepAlive: false, | ||
125 | + }, | ||
126 | + component: () => | ||
127 | + import( | ||
128 | + '/@/views/project/finance/financeProfit/ProductProfit/InnerProduce/index.vue' | ||
129 | + ), | ||
130 | + }, | ||
131 | + { | ||
132 | + path: 'InnerData', | ||
133 | + name: 'InnerData', | ||
134 | + meta: { | ||
135 | + title: '内部生产明细表', | ||
136 | + roles: [RoleEnum.ADMIN, RoleEnum.FINANCE, RoleEnum.TRACKER, RoleEnum.BUSINESS], | ||
137 | + ignoreKeepAlive: false, | ||
138 | + }, | ||
139 | + component: () => | ||
140 | + import('/@/views/project/finance/financeProfit/ProductProfit/InnerData/index.vue'), | ||
141 | + }, | ||
142 | + ], | ||
143 | + }, | ||
144 | + ], | ||
145 | + }, | ||
146 | ], | 146 | ], |
147 | }; | 147 | }; |
148 | 148 |
src/views/project/approve/ProduceFieldPanel.vue
@@ -94,7 +94,7 @@ | @@ -94,7 +94,7 @@ | ||
94 | dataIndex: 'innerNo', | 94 | dataIndex: 'innerNo', |
95 | width: 150, | 95 | width: 150, |
96 | customRender: (column) => { | 96 | customRender: (column) => { |
97 | - return column.record.orderBaseInfo.innerNo; | 97 | + return column.record.orderBaseInfo?.innerNo || '-'; |
98 | }, | 98 | }, |
99 | }, | 99 | }, |
100 | { | 100 | { |
@@ -102,7 +102,7 @@ | @@ -102,7 +102,7 @@ | ||
102 | dataIndex: 'projectNo', | 102 | dataIndex: 'projectNo', |
103 | width: 150, | 103 | width: 150, |
104 | customRender: (column) => { | 104 | customRender: (column) => { |
105 | - return column.record.orderBaseInfo.projectNo; | 105 | + return column.record.orderBaseInfo?.projectNo || '-'; |
106 | }, | 106 | }, |
107 | }, | 107 | }, |
108 | { | 108 | { |
@@ -130,7 +130,7 @@ | @@ -130,7 +130,7 @@ | ||
130 | const [registerTable, { reload }] = useTable({ | 130 | const [registerTable, { reload }] = useTable({ |
131 | scroll: false, | 131 | scroll: false, |
132 | api: props.isApproved ? getApprovedListApi : getWaitListApi, | 132 | api: props.isApproved ? getApprovedListApi : getWaitListApi, |
133 | - searchInfo: { typeIn: [60, 70] }, | 133 | + searchInfo: { typeIn: [80, 90] }, |
134 | columns, | 134 | columns, |
135 | useSearchForm: false, | 135 | useSearchForm: false, |
136 | formConfig: getFormConfig('true'), | 136 | formConfig: getFormConfig('true'), |
src/views/project/approve/ProfitFieldPanel.vue
@@ -39,7 +39,7 @@ | @@ -39,7 +39,7 @@ | ||
39 | import { BasicDrawer, useDrawer } from '/@/components/Drawer'; | 39 | import { BasicDrawer, useDrawer } from '/@/components/Drawer'; |
40 | import { approveAuditApi, getApprovedListApi, getWaitListApi } from '/@/api/project/approve'; | 40 | import { approveAuditApi, getApprovedListApi, getWaitListApi } from '/@/api/project/approve'; |
41 | import { getAuditApply, getApplyList } from '/@/api/project/invoice'; | 41 | import { getAuditApply, getApplyList } from '/@/api/project/invoice'; |
42 | - import { FIELDS_BASE_INFO } from '../finance/financeProfit/ServiceProfit/ServiceProfit/tableData'; | 42 | + import { FIELDS_BASE_INFO } from './data'; |
43 | import { COLUMNS } from '../finance/financeProfit/ServiceProfit/ServiceProfit/data'; | 43 | import { COLUMNS } from '../finance/financeProfit/ServiceProfit/ServiceProfit/data'; |
44 | import { find, isEmpty } from 'lodash-es'; | 44 | import { find, isEmpty } from 'lodash-es'; |
45 | import { ROLE } from '../order//type.d'; | 45 | import { ROLE } from '../order//type.d'; |
@@ -85,7 +85,11 @@ | @@ -85,7 +85,11 @@ | ||
85 | dataIndex: 'auditRoleCodes', | 85 | dataIndex: 'auditRoleCodes', |
86 | width: 150, | 86 | width: 150, |
87 | customRender: (column) => { | 87 | customRender: (column) => { |
88 | - return '业务研发净利字段'; | 88 | + if (column.record.type === 'FIELD_EDIT_APPLY') { |
89 | + return '业务利润字段编辑申请'; | ||
90 | + } else if (column.record.type === 'INNER_PROFIT_FIELD_EDIT_APPLY') { | ||
91 | + return '内部利润字段编辑申请'; | ||
92 | + } | ||
89 | }, | 93 | }, |
90 | }, | 94 | }, |
91 | { | 95 | { |
src/views/project/approve/data.ts
@@ -70,4 +70,63 @@ export function getFormConfig(showFieldConfig: string) { | @@ -70,4 +70,63 @@ export function getFormConfig(showFieldConfig: string) { | ||
70 | : []), | 70 | : []), |
71 | ], | 71 | ], |
72 | }; | 72 | }; |
73 | -} | ||
74 | \ No newline at end of file | 73 | \ No newline at end of file |
74 | +} | ||
75 | + | ||
76 | +export const FIELDS_BASE_INFO = [ | ||
77 | + { | ||
78 | + field: 'developmentCopyRmbTotalPrice', | ||
79 | + component: 'Select', | ||
80 | + labelWidth: 150, | ||
81 | + label: '研发复制费合计¥', | ||
82 | + rules: [{ required: true }], | ||
83 | + }, | ||
84 | + { | ||
85 | + field: 'projectStartTime', | ||
86 | + component: 'Select', | ||
87 | + labelWidth: 150, | ||
88 | + label: '项目开始时间', | ||
89 | + rules: [{ required: true }], | ||
90 | + }, | ||
91 | + { | ||
92 | + field: 'projectEndTime', | ||
93 | + component: 'Select', | ||
94 | + labelWidth: 150, | ||
95 | + label: '项目结束时间', | ||
96 | + rules: [{ required: true }], | ||
97 | + }, | ||
98 | + { | ||
99 | + field: 'spainPaidRmbCommission', | ||
100 | + component: 'Select', | ||
101 | + labelWidth: 150, | ||
102 | + label: '西班牙已发提成¥', | ||
103 | + rules: [{ required: true }], | ||
104 | + }, | ||
105 | + { | ||
106 | + field: 'paidRmbCommission', | ||
107 | + component: 'Select', | ||
108 | + labelWidth: 150, | ||
109 | + label: '中国团队已发提成¥', | ||
110 | + rules: [{ required: true }], | ||
111 | + }, | ||
112 | + { | ||
113 | + field: 'actualExchangeRate', | ||
114 | + component: 'Select', | ||
115 | + labelWidth: 150, | ||
116 | + label: '实际汇率¥', | ||
117 | + rules: [{ required: true }], | ||
118 | + }, | ||
119 | + { | ||
120 | + field: 'projectInnerProfitInfoStartTime', | ||
121 | + component: 'Select', | ||
122 | + labelWidth: 150, | ||
123 | + label: '项目开始时间', | ||
124 | + rules: [{ required: true }], | ||
125 | + }, | ||
126 | + { | ||
127 | + field: 'projectInnerProfitInfoEndTime', | ||
128 | + component: 'Select', | ||
129 | + labelWidth: 150, | ||
130 | + label: '项目结束时间', | ||
131 | + rules: [{ required: true }], | ||
132 | + }, | ||
133 | +]; |
src/views/project/approve/index.vue
@@ -35,7 +35,7 @@ | @@ -35,7 +35,7 @@ | ||
35 | > | 35 | > |
36 | <PayPanel /> | 36 | <PayPanel /> |
37 | </a-tab-pane> | 37 | </a-tab-pane> |
38 | - <!-- <a-tab-pane | 38 | + <a-tab-pane |
39 | key="11" | 39 | key="11" |
40 | tab="利润分析表字段审核" | 40 | tab="利润分析表字段审核" |
41 | v-if="role == ROLE.FINANCE || role == ROLE.ADMIN" | 41 | v-if="role == ROLE.FINANCE || role == ROLE.ADMIN" |
@@ -44,7 +44,7 @@ | @@ -44,7 +44,7 @@ | ||
44 | </a-tab-pane> | 44 | </a-tab-pane> |
45 | <a-tab-pane key="13" tab="明细表字段审核" v-if="role == ROLE.FINANCE || role == ROLE.ADMIN"> | 45 | <a-tab-pane key="13" tab="明细表字段审核" v-if="role == ROLE.FINANCE || role == ROLE.ADMIN"> |
46 | <ProduceFieldPanel /> | 46 | <ProduceFieldPanel /> |
47 | - </a-tab-pane> --> | 47 | + </a-tab-pane> |
48 | <a-tab-pane key="2" tab="字段已审核" v-if="role !== ROLE.FINANCE"> | 48 | <a-tab-pane key="2" tab="字段已审核" v-if="role !== ROLE.FINANCE"> |
49 | <FieldPanel isApproved /> | 49 | <FieldPanel isApproved /> |
50 | </a-tab-pane> | 50 | </a-tab-pane> |
@@ -79,7 +79,7 @@ | @@ -79,7 +79,7 @@ | ||
79 | > | 79 | > |
80 | <PayPanel isApproved /> | 80 | <PayPanel isApproved /> |
81 | </a-tab-pane> | 81 | </a-tab-pane> |
82 | - <!-- <a-tab-pane | 82 | + <a-tab-pane |
83 | key="12" | 83 | key="12" |
84 | tab="利润分析表字段已审核" | 84 | tab="利润分析表字段已审核" |
85 | v-if="role == ROLE.FINANCE || role == ROLE.ADMIN" | 85 | v-if="role == ROLE.FINANCE || role == ROLE.ADMIN" |
@@ -88,7 +88,7 @@ | @@ -88,7 +88,7 @@ | ||
88 | </a-tab-pane> | 88 | </a-tab-pane> |
89 | <a-tab-pane key="14" tab="明细表字段审核" v-if="role == ROLE.FINANCE || role == ROLE.ADMIN"> | 89 | <a-tab-pane key="14" tab="明细表字段审核" v-if="role == ROLE.FINANCE || role == ROLE.ADMIN"> |
90 | <ProduceFieldPanel isApproved /> | 90 | <ProduceFieldPanel isApproved /> |
91 | - </a-tab-pane> --> | 91 | + </a-tab-pane> |
92 | </a-tabs> | 92 | </a-tabs> |
93 | </div> | 93 | </div> |
94 | </template> | 94 | </template> |
src/views/project/config/ProduCostCreate.vue
@@ -22,9 +22,15 @@ | @@ -22,9 +22,15 @@ | ||
22 | <a-input v-model:value="fixCost" | 22 | <a-input v-model:value="fixCost" |
23 | /></div> | 23 | /></div> |
24 | <div | 24 | <div |
25 | - ><span style="margin-right: 8px; width: 80%">提成比例:</span> | 25 | + ><span style="margin-right: 8px; width: 80%">提成单价:</span> |
26 | <a-input v-model:value="ratio" /> | 26 | <a-input v-model:value="ratio" /> |
27 | </div> | 27 | </div> |
28 | + <div | ||
29 | + ><span style="margin-right: 8px; width: 80%">年份:</span> | ||
30 | + <a-select v-model:value="year" style="width: 100%"> | ||
31 | + <a-select-option v-for="y in yearOptions" :key="y" :value="y">{{ y }}</a-select-option> | ||
32 | + </a-select> | ||
33 | + </div> | ||
28 | </a-space> | 34 | </a-space> |
29 | </BasicModal> | 35 | </BasicModal> |
30 | </template> | 36 | </template> |
@@ -54,6 +60,13 @@ | @@ -54,6 +60,13 @@ | ||
54 | //获取现有的列表 | 60 | //获取现有的列表 |
55 | const listAll = ref(); | 61 | const listAll = ref(); |
56 | const fixCost = ref(); | 62 | const fixCost = ref(); |
63 | + const year = ref(new Date().getFullYear().toString()); | ||
64 | + // Generate year options from 2023 to current year | ||
65 | + const currentYear = new Date().getFullYear(); | ||
66 | + const yearOptions = ref<string[]>([]); | ||
67 | + for (let y = 2023; y <= currentYear; y++) { | ||
68 | + yearOptions.value.push(y.toString()); | ||
69 | + } | ||
57 | const ratio = ref(); | 70 | const ratio = ref(); |
58 | // const relationValue = ref(); | 71 | // const relationValue = ref(); |
59 | const customerCode = ref(); | 72 | const customerCode = ref(); |
@@ -91,7 +104,7 @@ | @@ -91,7 +104,7 @@ | ||
91 | settingValue: customerCode.value, | 104 | settingValue: customerCode.value, |
92 | settingType: 4, | 105 | settingType: 4, |
93 | relationCode: 'ProduceSettingItem', | 106 | relationCode: 'ProduceSettingItem', |
94 | - relationName: '成本配置项集合', | 107 | + relationName: year.value, |
95 | costSettingItemVOS: relationValue.value, | 108 | costSettingItemVOS: relationValue.value, |
96 | }); | 109 | }); |
97 | emit('modal-success'); | 110 | emit('modal-success'); |
@@ -108,6 +121,8 @@ | @@ -108,6 +121,8 @@ | ||
108 | activeUser, | 121 | activeUser, |
109 | fixCost, | 122 | fixCost, |
110 | ratio, | 123 | ratio, |
124 | + year, | ||
125 | + yearOptions, | ||
111 | customerCode, | 126 | customerCode, |
112 | customerCodeOptions, | 127 | customerCodeOptions, |
113 | handleOk, | 128 | handleOk, |
src/views/project/config/ProduCostEdit.vue
@@ -16,7 +16,8 @@ | @@ -16,7 +16,8 @@ | ||
16 | > | 16 | > |
17 | <a-space direction="vertical" style="width: 100%"> | 17 | <a-space direction="vertical" style="width: 100%"> |
18 | <a-input v-model:value="fixCost" addonBefore="固定成本 " /> | 18 | <a-input v-model:value="fixCost" addonBefore="固定成本 " /> |
19 | - <a-input v-model:value="ratio" addonBefore="提成比例 " /> | 19 | + <a-input v-model:value="ratio" addonBefore="提成单价 " /> |
20 | + <a-input v-model:value="year" :disabled="true" addonBefore="年份 " /> | ||
20 | </a-space> | 21 | </a-space> |
21 | </BasicDrawer> | 22 | </BasicDrawer> |
22 | </template> | 23 | </template> |
@@ -35,13 +36,14 @@ | @@ -35,13 +36,14 @@ | ||
35 | relationValue.value = JSON.parse(listAll.value.relationValue); | 36 | relationValue.value = JSON.parse(listAll.value.relationValue); |
36 | fixCost.value = relationValue.value[0].relationValue; | 37 | fixCost.value = relationValue.value[0].relationValue; |
37 | ratio.value = relationValue.value[1].relationValue; | 38 | ratio.value = relationValue.value[1].relationValue; |
39 | + year.value = listAll.value.relationName; | ||
38 | }); | 40 | }); |
39 | //获取现有的列表 | 41 | //获取现有的列表 |
40 | const listAll = ref(); | 42 | const listAll = ref(); |
41 | const fixCost = ref(); | 43 | const fixCost = ref(); |
42 | const ratio = ref(); | 44 | const ratio = ref(); |
43 | const relationValue = ref(); | 45 | const relationValue = ref(); |
44 | - | 46 | + const year = ref(); |
45 | //完成编辑 | 47 | //完成编辑 |
46 | async function handleSubmit() { | 48 | async function handleSubmit() { |
47 | relationValue.value[0].relationValue = fixCost.value; | 49 | relationValue.value[0].relationValue = fixCost.value; |
@@ -53,7 +55,7 @@ | @@ -53,7 +55,7 @@ | ||
53 | settingValue: listAll.value.settingValue, | 55 | settingValue: listAll.value.settingValue, |
54 | settingType: 4, | 56 | settingType: 4, |
55 | relationCode: 'ProduceSettingItem', | 57 | relationCode: 'ProduceSettingItem', |
56 | - relationName: '成本配置项集合', | 58 | + relationName: year.value, |
57 | costSettingItemVOS: relationValue.value, | 59 | costSettingItemVOS: relationValue.value, |
58 | }); | 60 | }); |
59 | emit('success'); | 61 | emit('success'); |
src/views/project/config/TablePanel.vue
@@ -46,7 +46,7 @@ | @@ -46,7 +46,7 @@ | ||
46 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; | 46 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; |
47 | import CreateModal from './CreateModal.vue'; | 47 | import CreateModal from './CreateModal.vue'; |
48 | import { deleteConfig, getList, saveConfig } from '/@/api/sys/config'; | 48 | import { deleteConfig, getList, saveConfig } from '/@/api/sys/config'; |
49 | - import { COLUMNS } from './data'; | 49 | + import { COLUMNS, searchFormSchema } from './data'; |
50 | import { useModal } from '/@/components/Modal'; | 50 | import { useModal } from '/@/components/Modal'; |
51 | import { useDrawer } from '/@/components/Drawer'; | 51 | import { useDrawer } from '/@/components/Drawer'; |
52 | import CostEdit from './costEdit.vue'; | 52 | import CostEdit from './costEdit.vue'; |
@@ -74,6 +74,10 @@ | @@ -74,6 +74,10 @@ | ||
74 | pagination: false, | 74 | pagination: false, |
75 | columns: COLUMNS[props.column!], | 75 | columns: COLUMNS[props.column!], |
76 | rowKey: 'id', | 76 | rowKey: 'id', |
77 | + useSearchForm: props.column === 6 || props.column === 9, | ||
78 | + formConfig: { | ||
79 | + schemas: props.column === 6 || props.column === 9 ? searchFormSchema : [], | ||
80 | + }, | ||
77 | actionColumn: { | 81 | actionColumn: { |
78 | width: 160, | 82 | width: 160, |
79 | title: 'Action', | 83 | title: 'Action', |
src/views/project/config/costCreate.vue
@@ -29,6 +29,12 @@ | @@ -29,6 +29,12 @@ | ||
29 | ><span style="margin-right: 8px; width: 80%">西班牙提成比例:</span> | 29 | ><span style="margin-right: 8px; width: 80%">西班牙提成比例:</span> |
30 | <a-input v-model:value="spainRatio" /> | 30 | <a-input v-model:value="spainRatio" /> |
31 | </div> | 31 | </div> |
32 | + <div | ||
33 | + ><span style="margin-right: 8px; width: 80%">年份:</span> | ||
34 | + <a-select v-model:value="year" style="width: 100%"> | ||
35 | + <a-select-option v-for="y in yearOptions" :key="y" :value="y">{{ y }}</a-select-option> | ||
36 | + </a-select> | ||
37 | + </div> | ||
32 | <!-- <div | 38 | <!-- <div |
33 | ><span style="margin-right: 8px; width: 80%">生产提成单价:</span> | 39 | ><span style="margin-right: 8px; width: 80%">生产提成单价:</span> |
34 | <a-input v-model:value="price" /> | 40 | <a-input v-model:value="price" /> |
@@ -65,6 +71,13 @@ | @@ -65,6 +71,13 @@ | ||
65 | const ratio = ref(); | 71 | const ratio = ref(); |
66 | const spainRatio = ref(); | 72 | const spainRatio = ref(); |
67 | const price = ref(); | 73 | const price = ref(); |
74 | + const year = ref(new Date().getFullYear().toString()); | ||
75 | + // Generate year options from 2023 to current year | ||
76 | + const currentYear = new Date().getFullYear(); | ||
77 | + const yearOptions = ref<string[]>([]); | ||
78 | + for (let y = 2023; y <= currentYear; y++) { | ||
79 | + yearOptions.value.push(y.toString()); | ||
80 | + } | ||
68 | // const relationValue = ref(); | 81 | // const relationValue = ref(); |
69 | const customerCode = ref(); | 82 | const customerCode = ref(); |
70 | const relationValue = ref([ | 83 | const relationValue = ref([ |
@@ -89,8 +102,6 @@ | @@ -89,8 +102,6 @@ | ||
89 | // relationValue: '', | 102 | // relationValue: '', |
90 | // }, | 103 | // }, |
91 | ]); | 104 | ]); |
92 | - // const loading = ref(true); | ||
93 | - | ||
94 | const { customerCode: customerCodeOptions } = useOrderInfo(orderStore); | 105 | const { customerCode: customerCodeOptions } = useOrderInfo(orderStore); |
95 | 106 | ||
96 | function handleShow(visible: boolean) { | 107 | function handleShow(visible: boolean) { |
@@ -101,18 +112,30 @@ | @@ -101,18 +112,30 @@ | ||
101 | } | 112 | } |
102 | } | 113 | } |
103 | 114 | ||
115 | + // 格式化百分比值,去除百分号并除以100 | ||
116 | + function formatPercentage(value) { | ||
117 | + if (!value) return ''; | ||
118 | + // 检查值是否包含百分号 | ||
119 | + if (typeof value === 'string' && value.includes('%')) { | ||
120 | + // 去除百分号并转为数值,然后除以100 | ||
121 | + return (parseFloat(value.replace('%', '')) / 100).toString(); | ||
122 | + } | ||
123 | + // 如果没有百分号但是是数值,直接除以100 | ||
124 | + return value; | ||
125 | + } | ||
126 | + | ||
104 | async function handleOk() { | 127 | async function handleOk() { |
105 | try { | 128 | try { |
106 | relationValue.value[0].relationValue = fixCost.value; | 129 | relationValue.value[0].relationValue = fixCost.value; |
107 | - relationValue.value[1].relationValue = ratio.value; | ||
108 | - relationValue.value[2].relationValue = spainRatio.value; | 130 | + relationValue.value[1].relationValue = formatPercentage(ratio.value); |
131 | + relationValue.value[2].relationValue = formatPercentage(spainRatio.value); | ||
109 | await addConfig({ | 132 | await addConfig({ |
110 | settingCode: 'customerCode', | 133 | settingCode: 'customerCode', |
111 | settingName: '客户提成成本配置', | 134 | settingName: '客户提成成本配置', |
112 | settingValue: customerCode.value, | 135 | settingValue: customerCode.value, |
113 | settingType: 3, | 136 | settingType: 3, |
114 | relationCode: 'costSettingItem', | 137 | relationCode: 'costSettingItem', |
115 | - relationName: '成本配置项集合', | 138 | + relationName: year.value, |
116 | costSettingItemVOS: relationValue.value, | 139 | costSettingItemVOS: relationValue.value, |
117 | }); | 140 | }); |
118 | emit('modal-success'); | 141 | emit('modal-success'); |
@@ -132,6 +155,8 @@ | @@ -132,6 +155,8 @@ | ||
132 | spainRatio, | 155 | spainRatio, |
133 | price, | 156 | price, |
134 | customerCode, | 157 | customerCode, |
158 | + year, | ||
159 | + yearOptions, | ||
135 | customerCodeOptions, | 160 | customerCodeOptions, |
136 | handleOk, | 161 | handleOk, |
137 | }; | 162 | }; |
src/views/project/config/costEdit.vue
@@ -18,26 +18,30 @@ | @@ -18,26 +18,30 @@ | ||
18 | <a-input v-model:value="fixCost" addonBefore="固定成本 " /> | 18 | <a-input v-model:value="fixCost" addonBefore="固定成本 " /> |
19 | <a-input v-model:value="ratio" addonBefore="提成比例 " /> | 19 | <a-input v-model:value="ratio" addonBefore="提成比例 " /> |
20 | <a-input v-model:value="spainRatio" addonBefore="西班牙提成比例 " /> | 20 | <a-input v-model:value="spainRatio" addonBefore="西班牙提成比例 " /> |
21 | + <a-input v-model:value="year" :disabled="true" addonBefore="年份 " /> | ||
21 | <!-- <a-input v-model:value="price" addonBefore="生产提成单价" /> --> | 22 | <!-- <a-input v-model:value="price" addonBefore="生产提成单价" /> --> |
22 | </a-space> | 23 | </a-space> |
23 | </BasicDrawer> | 24 | </BasicDrawer> |
24 | </template> | 25 | </template> |
25 | <script lang="ts" setup> | 26 | <script lang="ts" setup> |
26 | import { BasicDrawer, useDrawerInner } from '@/components/Drawer'; | 27 | import { BasicDrawer, useDrawerInner } from '@/components/Drawer'; |
27 | - import { BasicForm, FormSchema, useForm } from '@/components/Form'; | ||
28 | - import { defineComponent, ref, computed, unref, toRaw, reactive, onMounted } from 'vue'; | 28 | + import { ref } from 'vue'; |
29 | import { saveConfig } from '/@/api/sys/config'; | 29 | import { saveConfig } from '/@/api/sys/config'; |
30 | 30 | ||
31 | - // const emit = defineEmits(['success']); | ||
32 | - // const isUpdate = ref(true); | ||
33 | const emit = defineEmits(['success']); | 31 | const emit = defineEmits(['success']); |
34 | 32 | ||
35 | const [register, { closeDrawer }] = useDrawerInner((data) => { | 33 | const [register, { closeDrawer }] = useDrawerInner((data) => { |
36 | listAll.value = data.data; | 34 | listAll.value = data.data; |
37 | relationValue.value = JSON.parse(listAll.value.relationValue); | 35 | relationValue.value = JSON.parse(listAll.value.relationValue); |
38 | fixCost.value = relationValue.value[0].relationValue; | 36 | fixCost.value = relationValue.value[0].relationValue; |
39 | - ratio.value = relationValue.value[1].relationValue; | ||
40 | - spainRatio.value = relationValue.value[2].relationValue; | 37 | + // 将小数转换为百分比格式显示 |
38 | + ratio.value = relationValue.value[1].relationValue | ||
39 | + ? (parseFloat(relationValue.value[1].relationValue) * 100).toFixed(2) + '%' | ||
40 | + : ''; | ||
41 | + spainRatio.value = relationValue.value[2].relationValue | ||
42 | + ? (parseFloat(relationValue.value[2].relationValue) * 100).toFixed(2) + '%' | ||
43 | + : ''; | ||
44 | + year.value = listAll.value.relationName; | ||
41 | }); | 45 | }); |
42 | //获取现有的列表 | 46 | //获取现有的列表 |
43 | const listAll = ref(); | 47 | const listAll = ref(); |
@@ -45,12 +49,25 @@ | @@ -45,12 +49,25 @@ | ||
45 | const ratio = ref(); | 49 | const ratio = ref(); |
46 | const spainRatio = ref(); | 50 | const spainRatio = ref(); |
47 | const relationValue = ref(); | 51 | const relationValue = ref(); |
52 | + const year = ref(); | ||
53 | + | ||
54 | + // 格式化百分比值,去除百分号并除以100 | ||
55 | + function formatPercentage(value) { | ||
56 | + if (!value) return ''; | ||
57 | + // 检查值是否包含百分号 | ||
58 | + if (typeof value === 'string' && value.includes('%')) { | ||
59 | + // 去除百分号并转为数值,然后除以100 | ||
60 | + return (parseFloat(value.replace('%', '')) / 100).toString(); | ||
61 | + } | ||
62 | + // 如果没有百分号但是是数值,直接除以100 | ||
63 | + return value; | ||
64 | + } | ||
48 | 65 | ||
49 | //完成编辑 | 66 | //完成编辑 |
50 | async function handleSubmit() { | 67 | async function handleSubmit() { |
51 | relationValue.value[0].relationValue = fixCost.value; | 68 | relationValue.value[0].relationValue = fixCost.value; |
52 | - relationValue.value[1].relationValue = ratio.value; | ||
53 | - relationValue.value[2].relationValue = spainRatio.value; | 69 | + relationValue.value[1].relationValue = formatPercentage(ratio.value); |
70 | + relationValue.value[2].relationValue = formatPercentage(spainRatio.value); | ||
54 | await saveConfig({ | 71 | await saveConfig({ |
55 | id: listAll.value.id, | 72 | id: listAll.value.id, |
56 | settingCode: 'customerCode', | 73 | settingCode: 'customerCode', |
@@ -58,7 +75,7 @@ | @@ -58,7 +75,7 @@ | ||
58 | settingValue: listAll.value.settingValue, | 75 | settingValue: listAll.value.settingValue, |
59 | settingType: 3, | 76 | settingType: 3, |
60 | relationCode: 'costSettingItem', | 77 | relationCode: 'costSettingItem', |
61 | - relationName: '成本配置项集合', | 78 | + relationName: year.value, |
62 | costSettingItemVOS: relationValue.value, | 79 | costSettingItemVOS: relationValue.value, |
63 | }); | 80 | }); |
64 | emit('success'); | 81 | emit('success'); |
src/views/project/config/data.tsx
1 | -import { InputNumber, Tag } from 'ant-design-vue'; | 1 | +import { Tag } from 'ant-design-vue'; |
2 | import { BasicColumn } from '@/components/Table'; | 2 | import { BasicColumn } from '@/components/Table'; |
3 | -import { func } from 'vue-types'; | ||
4 | -import { h, ref } from 'vue'; | ||
5 | - | 3 | +import { h } from 'vue'; |
4 | +import { queryNoOptions } from '/@/api/project/order'; | ||
6 | 5 | ||
7 | export const COLUMNS = { | 6 | export const COLUMNS = { |
8 | 1: [ | 7 | 1: [ |
@@ -68,6 +67,11 @@ export const COLUMNS = { | @@ -68,6 +67,11 @@ export const COLUMNS = { | ||
68 | width: 150, | 67 | width: 150, |
69 | }, | 68 | }, |
70 | { | 69 | { |
70 | + title: '年份', | ||
71 | + dataIndex: 'relationName', | ||
72 | + width: 150, | ||
73 | + }, | ||
74 | + { | ||
71 | title: '固定成本', | 75 | title: '固定成本', |
72 | dataIndex: 'relationValue', | 76 | dataIndex: 'relationValue', |
73 | width: 150, | 77 | width: 150, |
@@ -82,7 +86,7 @@ export const COLUMNS = { | @@ -82,7 +86,7 @@ export const COLUMNS = { | ||
82 | width: 150, | 86 | width: 150, |
83 | customRender: (column) => { | 87 | customRender: (column) => { |
84 | const value = JSON.parse(column.record.relationValue); | 88 | const value = JSON.parse(column.record.relationValue); |
85 | - return value[1].relationValue; | 89 | + return (value[1]?.relationValue * 100).toFixed(2) + '%'; |
86 | }, | 90 | }, |
87 | }, | 91 | }, |
88 | { | 92 | { |
@@ -91,7 +95,7 @@ export const COLUMNS = { | @@ -91,7 +95,7 @@ export const COLUMNS = { | ||
91 | width: 150, | 95 | width: 150, |
92 | customRender: (column) => { | 96 | customRender: (column) => { |
93 | const value = JSON.parse(column.record.relationValue); | 97 | const value = JSON.parse(column.record.relationValue); |
94 | - return value[2].relationValue; | 98 | + return (value[2]?.relationValue * 100).toFixed(2) + '%'; |
95 | }, | 99 | }, |
96 | }, | 100 | }, |
97 | // { | 101 | // { |
@@ -139,6 +143,11 @@ export const COLUMNS = { | @@ -139,6 +143,11 @@ export const COLUMNS = { | ||
139 | width: 150, | 143 | width: 150, |
140 | }, | 144 | }, |
141 | { | 145 | { |
146 | + title: '年份', | ||
147 | + dataIndex: 'relationName', | ||
148 | + width: 150, | ||
149 | + }, | ||
150 | + { | ||
142 | title: '固定成本', | 151 | title: '固定成本', |
143 | dataIndex: 'relationValue', | 152 | dataIndex: 'relationValue', |
144 | width: 150, | 153 | width: 150, |
@@ -148,7 +157,7 @@ export const COLUMNS = { | @@ -148,7 +157,7 @@ export const COLUMNS = { | ||
148 | }, | 157 | }, |
149 | }, | 158 | }, |
150 | { | 159 | { |
151 | - title: '提成比例', | 160 | + title: '提成单价', |
152 | dataIndex: 'relationValue', | 161 | dataIndex: 'relationValue', |
153 | width: 150, | 162 | width: 150, |
154 | customRender: (column) => { | 163 | customRender: (column) => { |
@@ -258,3 +267,23 @@ export const columnsProduct: BasicColumn[] = [ | @@ -258,3 +267,23 @@ export const columnsProduct: BasicColumn[] = [ | ||
258 | editRow: true, | 267 | editRow: true, |
259 | }, | 268 | }, |
260 | ]; | 269 | ]; |
270 | + | ||
271 | +export const searchFormSchema = [ | ||
272 | + { | ||
273 | + field: 'relationName', | ||
274 | + label: '年份', | ||
275 | + component: 'Select', | ||
276 | + colProps: { span: 8 }, | ||
277 | + componentProps: { | ||
278 | + showSearch: true, | ||
279 | + options: (() => { | ||
280 | + const options = []; | ||
281 | + const currentYear = new Date().getFullYear(); | ||
282 | + for (let y = 2023; y <= currentYear; y++) { | ||
283 | + options.push({ label: y.toString(), value: y.toString() }); | ||
284 | + } | ||
285 | + return options; | ||
286 | + })(), | ||
287 | + }, | ||
288 | + }, | ||
289 | +] | ||
261 | \ No newline at end of file | 290 | \ No newline at end of file |
src/views/project/config/index.vue
@@ -22,7 +22,7 @@ | @@ -22,7 +22,7 @@ | ||
22 | <TablePanel :searchInfo="{ relationCode: 'orderHodTime' }" :column="5" /> | 22 | <TablePanel :searchInfo="{ relationCode: 'orderHodTime' }" :column="5" /> |
23 | </Tabs.TabPane> | 23 | </Tabs.TabPane> |
24 | <Tabs.TabPane key="6" tab="提成成本配置"> | 24 | <Tabs.TabPane key="6" tab="提成成本配置"> |
25 | - <TablePanel :searchInfo="{ relationCode: 'costSettingItem' }" :column="6" /> | 25 | + <TablePanel :searchInfo="{ relationCode: 'costSettingItem', relationName: currentYear }" :column="6" /> |
26 | </Tabs.TabPane> | 26 | </Tabs.TabPane> |
27 | <Tabs.TabPane key="7" tab="销售额配置" v-if="role !== ROLE.FINANCE"> | 27 | <Tabs.TabPane key="7" tab="销售额配置" v-if="role !== ROLE.FINANCE"> |
28 | <TablePanel :searchInfo="{ relationCode: 'salesAmount' }" :column="7" /> | 28 | <TablePanel :searchInfo="{ relationCode: 'salesAmount' }" :column="7" /> |
@@ -31,7 +31,7 @@ | @@ -31,7 +31,7 @@ | ||
31 | <TablePanel :searchInfo="{ relationCode: 'produHodTime' }" :column="8" /> | 31 | <TablePanel :searchInfo="{ relationCode: 'produHodTime' }" :column="8" /> |
32 | </Tabs.TabPane> | 32 | </Tabs.TabPane> |
33 | <Tabs.TabPane key="9" tab="生产科固定成本"> | 33 | <Tabs.TabPane key="9" tab="生产科固定成本"> |
34 | - <TablePanel :searchInfo="{ relationCode: 'ProduceSettingItem' }" :column="9" /> | 34 | + <TablePanel :searchInfo="{ relationCode: 'ProduceSettingItem', relationName: currentYear }" :column="9" /> |
35 | </Tabs.TabPane> | 35 | </Tabs.TabPane> |
36 | <Tabs.TabPane key="10" tab="客户公司" v-if="role !== ROLE.FINANCE"> | 36 | <Tabs.TabPane key="10" tab="客户公司" v-if="role !== ROLE.FINANCE"> |
37 | <TablePanel :searchInfo="{ relationCode: 'companyConfiguration' }" :column="10" /> | 37 | <TablePanel :searchInfo="{ relationCode: 'companyConfiguration' }" :column="10" /> |
@@ -56,6 +56,7 @@ | @@ -56,6 +56,7 @@ | ||
56 | const orderStore = useOrderStoreWithOut(); | 56 | const orderStore = useOrderStoreWithOut(); |
57 | const userStore = useUserStoreWithOut(); | 57 | const userStore = useUserStoreWithOut(); |
58 | const user = userStore.getUserInfo; | 58 | const user = userStore.getUserInfo; |
59 | + const currentYear = new Date().getFullYear().toString(); | ||
59 | const role = computed(() => { | 60 | const role = computed(() => { |
60 | return user?.roleSmallVO?.code; | 61 | return user?.roleSmallVO?.code; |
61 | }); | 62 | }); |
src/views/project/finance/financeProfit/ProductProfit/InnerData/ApproveReason.vue
@@ -32,7 +32,9 @@ | @@ -32,7 +32,9 @@ | ||
32 | orderId: baseFieldValues.value.orderId, | 32 | orderId: baseFieldValues.value.orderId, |
33 | productionActualPrice: baseFieldValues.value.productionActualPrice, | 33 | productionActualPrice: baseFieldValues.value.productionActualPrice, |
34 | productionDepartmentPredictPrice: baseFieldValues.value.productionDepartmentPredictPrice, | 34 | productionDepartmentPredictPrice: baseFieldValues.value.productionDepartmentPredictPrice, |
35 | - type: 70, | 35 | + productionDepartmentPredictUnitPrice: baseFieldValues.value.productionDepartmentPredictUnitPrice, |
36 | + applyRemark: baseFieldValues.value.applyRemark, | ||
37 | + type: 90, | ||
36 | }); | 38 | }); |
37 | emit('success'); | 39 | emit('success'); |
38 | setTimeout(() => { | 40 | setTimeout(() => { |
src/views/project/finance/financeProfit/ProductProfit/InnerData/FinanceEdit.vue
@@ -9,6 +9,7 @@ | @@ -9,6 +9,7 @@ | ||
9 | @ok="handleSubmit" | 9 | @ok="handleSubmit" |
10 | :showDetailBack="false" | 10 | :showDetailBack="false" |
11 | okText="保存" | 11 | okText="保存" |
12 | + @visible-change="handleShow" | ||
12 | showFooter | 13 | showFooter |
13 | :destroyOnClose="true" | 14 | :destroyOnClose="true" |
14 | > | 15 | > |
@@ -19,7 +20,7 @@ | @@ -19,7 +20,7 @@ | ||
19 | <a-input | 20 | <a-input |
20 | v-model:value="input1" | 21 | v-model:value="input1" |
21 | placeholder="请输入" | 22 | placeholder="请输入" |
22 | - :disabled="status1 === 'LOCKED'" | 23 | + :disabled="status1 == 'LOCKED'" |
23 | auto-size | 24 | auto-size |
24 | /> | 25 | /> |
25 | <div style="margin: 16px 0"></div> | 26 | <div style="margin: 16px 0"></div> |
@@ -27,7 +28,15 @@ | @@ -27,7 +28,15 @@ | ||
27 | <a-input | 28 | <a-input |
28 | v-model:value="input2" | 29 | v-model:value="input2" |
29 | placeholder="请输入" | 30 | placeholder="请输入" |
30 | - :disabled="status2 === 'LOCKED'" | 31 | + :disabled="status2 == 'LOCKED'" |
32 | + auto-size | ||
33 | + /> | ||
34 | + <div style="margin: 16px 0"></div> | ||
35 | + <div style="font-size: 15px">生产科预算单价</div> | ||
36 | + <a-input | ||
37 | + v-model:value="input3" | ||
38 | + placeholder="请输入" | ||
39 | + :disabled="status3 == 'LOCKED'" | ||
31 | auto-size | 40 | auto-size |
32 | /> | 41 | /> |
33 | <div style="margin: 16px 0"></div> | 42 | <div style="margin: 16px 0"></div> |
@@ -42,7 +51,7 @@ | @@ -42,7 +51,7 @@ | ||
42 | <script lang="ts" setup> | 51 | <script lang="ts" setup> |
43 | import { BasicDrawer, useDrawerInner } from '@/components/Drawer'; | 52 | import { BasicDrawer, useDrawerInner } from '@/components/Drawer'; |
44 | import { BasicForm, FormSchema, useForm } from '@/components/Form'; | 53 | import { BasicForm, FormSchema, useForm } from '@/components/Form'; |
45 | - import { defineComponent, ref, computed, unref, toRaw, reactive } from 'vue'; | 54 | + import { defineComponent, ref, computed, watch, toRaw, reactive } from 'vue'; |
46 | import { getPackageEdit } from '@/api/project/invoice'; | 55 | import { getPackageEdit } from '@/api/project/invoice'; |
47 | import { useMessage } from '/@/hooks/web/useMessage'; | 56 | import { useMessage } from '/@/hooks/web/useMessage'; |
48 | import { ROLE } from './type.d'; | 57 | import { ROLE } from './type.d'; |
@@ -125,25 +134,37 @@ | @@ -125,25 +134,37 @@ | ||
125 | const update = ref(); | 134 | const update = ref(); |
126 | const status1 = ref(); | 135 | const status1 = ref(); |
127 | const status2 = ref(); | 136 | const status2 = ref(); |
137 | + const status3 = ref(); | ||
128 | 138 | ||
129 | const input1 = ref(); | 139 | const input1 = ref(); |
130 | const input2 = ref(); | 140 | const input2 = ref(); |
141 | + const input3 = ref(); | ||
142 | + const orderCount = ref(); | ||
131 | const id = ref(); | 143 | const id = ref(); |
144 | + watch(input3, (newVal) => { | ||
145 | + if (newVal && orderCount.value) { | ||
146 | + input1.value = (parseFloat(newVal) * parseFloat(orderCount.value)).toFixed(2); | ||
147 | + } else { | ||
148 | + input1.value = ''; | ||
149 | + } | ||
150 | + }); | ||
132 | const [register, { setDrawerProps, closeDrawer }] = useDrawerInner((data) => { | 151 | const [register, { setDrawerProps, closeDrawer }] = useDrawerInner((data) => { |
133 | // 方式1 | 152 | // 方式1 |
134 | - if (data.data.lockFields) { | ||
135 | - status1.value = data.data?.productionDepartmentPredictPrice; | ||
136 | - status2.value = data.data?.productionActualPrice; | 153 | + if (data.data?.lockFields) { |
154 | + status1.value = data.data?.lockFields?.productionDepartmentPredictPrice; | ||
155 | + status2.value = data.data?.lockFields?.productionActualPrice; | ||
156 | + status3.value = data.data?.lockFields?.productionDepartmentPredictUnitPrice; | ||
137 | } | 157 | } |
138 | - | ||
139 | id.value = data.data.orderId; | 158 | id.value = data.data.orderId; |
140 | - input1.value = data.data?.productionDepartmentPredictPrice.toFixed(2); | ||
141 | - input2.value = data.data?.productionActualPrice.toFixed(2); | 159 | + input1.value = data.data?.productionDepartmentPredictPrice?.toFixed(2); |
160 | + input2.value = data.data?.productionActualPrice?.toFixed(2); | ||
161 | + orderCount.value = data.data?.orderCount; | ||
162 | + input3.value = data.data?.productionDepartmentPredictUnitPrice?.toFixed(2); | ||
142 | resetFields(); | 163 | resetFields(); |
143 | setDrawerProps({ confirmLoading: false }); | 164 | setDrawerProps({ confirmLoading: false }); |
144 | - setFieldsValue({ | ||
145 | - ...toRaw(data.data), | ||
146 | - }); | 165 | + // setFieldsValue({ |
166 | + // ...toRaw(data.data), | ||
167 | + // }); | ||
147 | update.value = data; | 168 | update.value = data; |
148 | }); | 169 | }); |
149 | //完成编辑 | 170 | //完成编辑 |
@@ -154,16 +175,25 @@ | @@ -154,16 +175,25 @@ | ||
154 | // id: update.value.data.id, | 175 | // id: update.value.data.id, |
155 | // bgUrl: update.value.data.bgUrl, | 176 | // bgUrl: update.value.data.bgUrl, |
156 | // }; | 177 | // }; |
157 | - if (!input1.value || !input2.value) { | 178 | + if (!input1.value || !input2.value || !input3.value) { |
158 | error('选项不能为空'); | 179 | error('选项不能为空'); |
159 | } else { | 180 | } else { |
160 | await getPackageEdit({ | 181 | await getPackageEdit({ |
161 | orderId: id.value, | 182 | orderId: id.value, |
162 | productionDepartmentPredictPrice: input1.value, | 183 | productionDepartmentPredictPrice: input1.value, |
163 | productionActualPrice: input2.value, | 184 | productionActualPrice: input2.value, |
185 | + orderCount: orderCount.value, | ||
186 | + productionDepartmentPredictUnitPrice: input3.value, | ||
164 | }); | 187 | }); |
165 | emit('success'); | 188 | emit('success'); |
166 | closeDrawer(); | 189 | closeDrawer(); |
167 | } | 190 | } |
168 | } | 191 | } |
192 | + function handleShow(visible: boolean) { | ||
193 | + if (!visible) { | ||
194 | + input1.value = ''; | ||
195 | + input2.value = ''; | ||
196 | + input3.value = ''; | ||
197 | + } | ||
198 | + } | ||
169 | </script> | 199 | </script> |
src/views/project/finance/financeProfit/ProductProfit/InnerData/HistoryDetail.vue
0 → 100644
1 | +<template> | ||
2 | + <BasicDrawer | ||
3 | + @register="register" | ||
4 | + v-bind="$attrs" | ||
5 | + title="操作记录" | ||
6 | + width="60%" | ||
7 | + :isDetail="true" | ||
8 | + :showDetailBack="false" | ||
9 | + okText="保存" | ||
10 | + :destroyOnClose="true" | ||
11 | + > | ||
12 | + <Tabs v-model:activeKey="activeKey" className="my-0"> | ||
13 | + <TabPanel :key="1" tab="操作记录" className="w-full"> | ||
14 | + <a-list :pagination="pagination1" className="w-full"> | ||
15 | + <template v-for="item in list1" :key="item.id"> | ||
16 | + <a-list-item class="list"> | ||
17 | + <a-list-item-meta> | ||
18 | + <template #avatar> </template> | ||
19 | + <template #title> | ||
20 | + <span>{{ item.userName }}</span> | ||
21 | + </template> | ||
22 | + <template #description> | ||
23 | + <div class="description"> | ||
24 | + {{ item.optType }} | ||
25 | + </div> | ||
26 | + <div class="info"> | ||
27 | + <div><span>操作时间:</span>{{ formatToDateTime(item.createTime) }}</div> | ||
28 | + </div> | ||
29 | + </template> | ||
30 | + </a-list-item-meta> | ||
31 | + </a-list-item> | ||
32 | + </template> | ||
33 | + </a-list> | ||
34 | + </TabPanel> | ||
35 | + <TabPanel :key="2" tab="审批记录" className="w-full"> | ||
36 | + <a-list :pagination="pagination2" className="w-full"> | ||
37 | + <template v-for="item in list2" :key="item.id"> | ||
38 | + <a-list-item class="list"> | ||
39 | + <a-list-item-meta> | ||
40 | + <template #avatar> </template> | ||
41 | + <template #title> | ||
42 | + <span>{{ item.userName }}</span> | ||
43 | + </template> | ||
44 | + <template #description> | ||
45 | + <div class="description"> | ||
46 | + {{ item.optType }} | ||
47 | + </div> | ||
48 | + <div class="info"> | ||
49 | + <div><span>操作时间:</span>{{ formatToDateTime(item.createTime) }}</div> | ||
50 | + </div> | ||
51 | + </template> | ||
52 | + </a-list-item-meta> | ||
53 | + </a-list-item> | ||
54 | + </template> | ||
55 | + </a-list> | ||
56 | + </TabPanel> | ||
57 | + </Tabs> | ||
58 | + | ||
59 | + <!-- <template #titleToolbar> <a-button type="primary"> 申请编辑权限 </a-button></template> --> | ||
60 | + <template #appendFooter> | ||
61 | + <!-- <a-button type="primary" @click="onGoCheckDetail"> 申请权限</a-button> --> | ||
62 | + </template> | ||
63 | + </BasicDrawer> | ||
64 | +</template> | ||
65 | +<script lang="ts"> | ||
66 | + import { defineComponent, ref, computed } from 'vue'; | ||
67 | + import { Tabs, List } from 'ant-design-vue'; | ||
68 | + import { FormSchema } from '/@/components/Form/index'; | ||
69 | + | ||
70 | + import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; | ||
71 | + import { getOrderCostDetailedOptLog } from '/@/api/project/invoice'; | ||
72 | + import { formatToDateTime } from '/@/utils/dateUtil'; | ||
73 | + | ||
74 | + const TabPanel = Tabs.TabPane; | ||
75 | + | ||
76 | + const schemas: FormSchema[] = [ | ||
77 | + { | ||
78 | + field: '订单号', | ||
79 | + component: 'Input', | ||
80 | + label: '字段1', | ||
81 | + componentProps: { | ||
82 | + readonly: true, | ||
83 | + disabled: true, | ||
84 | + }, | ||
85 | + colProps: { | ||
86 | + span: 12, | ||
87 | + }, | ||
88 | + defaultValue: '111', | ||
89 | + }, | ||
90 | + { | ||
91 | + field: 'field2', | ||
92 | + component: 'Input', | ||
93 | + label: '字段2', | ||
94 | + colProps: { | ||
95 | + span: 12, | ||
96 | + }, | ||
97 | + }, | ||
98 | + ]; | ||
99 | + const achieveList = [ | ||
100 | + { | ||
101 | + key: '1', | ||
102 | + name: '操作记录', | ||
103 | + }, | ||
104 | + { | ||
105 | + key: '2', | ||
106 | + name: '审批记录', | ||
107 | + }, | ||
108 | + ]; | ||
109 | + export default defineComponent({ | ||
110 | + components: { | ||
111 | + BasicDrawer, | ||
112 | + Tabs, | ||
113 | + TabPanel, | ||
114 | + [List.name]: List, | ||
115 | + [List.Item.name]: List.Item, | ||
116 | + AListItemMeta: List.Item.Meta, | ||
117 | + }, | ||
118 | + props: { | ||
119 | + onGoCheckDetail: { | ||
120 | + type: Function, | ||
121 | + }, | ||
122 | + }, | ||
123 | + setup() { | ||
124 | + const list1 = ref([]); | ||
125 | + const total1 = ref(0); | ||
126 | + const page1 = ref(1); | ||
127 | + | ||
128 | + const list2 = ref([]); | ||
129 | + const total2 = ref(0); | ||
130 | + const page2 = ref(1); | ||
131 | + const orderId = ref(''); | ||
132 | + const activeKey = ref(1); | ||
133 | + | ||
134 | + const getOrderOptLogFunc = async (data, index, page) => { | ||
135 | + console.log('%c [ data ]-135', 'font-size:13px; background:pink; color:#bf2c9f;', data); | ||
136 | + if (index === 1) { | ||
137 | + const res = await getOrderCostDetailedOptLog({ | ||
138 | + orderId: data, | ||
139 | + type: [40], | ||
140 | + page: page, | ||
141 | + pageSize: 20, | ||
142 | + }); | ||
143 | + list1.value = res.items; | ||
144 | + total1.value = res.total; | ||
145 | + page1.value = page; | ||
146 | + } else { | ||
147 | + const res = await getOrderCostDetailedOptLog({ | ||
148 | + orderId: data, | ||
149 | + type: [90,91], | ||
150 | + page: page, | ||
151 | + pageSize: 20, | ||
152 | + }); | ||
153 | + list2.value = res.items; | ||
154 | + total2.value = res.total; | ||
155 | + page2.value = page; | ||
156 | + } | ||
157 | + }; | ||
158 | + const [register] = useDrawerInner((data) => { | ||
159 | + orderId.value = data.data.orderId; | ||
160 | + getOrderOptLogFunc(orderId.value, 1, 1); | ||
161 | + getOrderOptLogFunc(orderId.value, 2, 1); | ||
162 | + }); | ||
163 | + | ||
164 | + const pagination1 = computed(() => { | ||
165 | + return { | ||
166 | + show: true, | ||
167 | + pageSize: 20, | ||
168 | + page: page1.value, | ||
169 | + total: total1.value, | ||
170 | + onChange(cur) { | ||
171 | + getOrderOptLogFunc(orderId.value, 1, cur); | ||
172 | + }, | ||
173 | + }; | ||
174 | + }); | ||
175 | + | ||
176 | + const pagination2 = computed(() => { | ||
177 | + return { | ||
178 | + show: true, | ||
179 | + pageSize: 20, | ||
180 | + page: page1.value, | ||
181 | + total: total1.value, | ||
182 | + onChange(cur) { | ||
183 | + getOrderOptLogFunc(orderId.value, 2, cur); | ||
184 | + }, | ||
185 | + }; | ||
186 | + }); | ||
187 | + | ||
188 | + return { | ||
189 | + register, | ||
190 | + schemas, | ||
191 | + achieveList, | ||
192 | + list1, | ||
193 | + list2, | ||
194 | + prefixCls: 'account-center', | ||
195 | + pagination1, | ||
196 | + pagination2, | ||
197 | + activeKey, | ||
198 | + formatToDateTime, | ||
199 | + }; | ||
200 | + }, | ||
201 | + }); | ||
202 | +</script> |
src/views/project/finance/financeProfit/ProductProfit/InnerData/data.tsx
@@ -137,7 +137,15 @@ export const COLUMNS = [ | @@ -137,7 +137,15 @@ export const COLUMNS = [ | ||
137 | }, | 137 | }, |
138 | }, | 138 | }, |
139 | { | 139 | { |
140 | - title: '生产科预算金额¥', | 140 | + title: '生产科预算单价¥', |
141 | + width: 150, | ||
142 | + dataIndex: 'productionDepartmentPredictUnitPrice', | ||
143 | + customRender: (column) => { | ||
144 | + return column.record?.productionDepartmentPredictUnitPrice?.toFixed(2); | ||
145 | + }, | ||
146 | + }, | ||
147 | + { | ||
148 | + title: '生产科预算总金额¥', | ||
141 | width: 150, | 149 | width: 150, |
142 | dataIndex: 'productionDepartmentPredictPrice', | 150 | dataIndex: 'productionDepartmentPredictPrice', |
143 | customRender: (column) => { | 151 | customRender: (column) => { |
@@ -145,9 +153,9 @@ export const COLUMNS = [ | @@ -145,9 +153,9 @@ export const COLUMNS = [ | ||
145 | }, | 153 | }, |
146 | }, | 154 | }, |
147 | { | 155 | { |
148 | - title: '实际发生费用', | 156 | + title: '生产科实际花费总金额¥', |
149 | dataIndex: 'productionActualPrice', | 157 | dataIndex: 'productionActualPrice', |
150 | - width: 120, | 158 | + width: 180, |
151 | customRender: (column) => { | 159 | customRender: (column) => { |
152 | return column.record?.productionActualPrice?.toFixed(2); | 160 | return column.record?.productionActualPrice?.toFixed(2); |
153 | }, | 161 | }, |
@@ -158,7 +166,7 @@ export const COLUMNS = [ | @@ -158,7 +166,7 @@ export const COLUMNS = [ | ||
158 | width: 120, | 166 | width: 120, |
159 | customRender: (column) => { | 167 | customRender: (column) => { |
160 | if (column.record?.predictRatio) { | 168 | if (column.record?.predictRatio) { |
161 | - return column.record?.predictRatio?.toFixed(2) + '%'; | 169 | + return (column.record?.predictRatio * 100).toFixed(2) + '%'; |
162 | } | 170 | } |
163 | return column.record?.predictRatio?.toFixed(2); | 171 | return column.record?.predictRatio?.toFixed(2); |
164 | }, | 172 | }, |
@@ -169,7 +177,7 @@ export const COLUMNS = [ | @@ -169,7 +177,7 @@ export const COLUMNS = [ | ||
169 | width: 120, | 177 | width: 120, |
170 | customRender: (column) => { | 178 | customRender: (column) => { |
171 | if (column.record?.predictAndActualRatio) { | 179 | if (column.record?.predictAndActualRatio) { |
172 | - return column.record?.predictAndActualRatio?.toFixed(2) + '%'; | 180 | + return (column.record?.predictAndActualRatio * 100).toFixed(2) + '%'; |
173 | } | 181 | } |
174 | return column.record?.predictAndActualRatio?.toFixed(2); | 182 | return column.record?.predictAndActualRatio?.toFixed(2); |
175 | }, | 183 | }, |
@@ -188,7 +196,7 @@ export const COLUMNS = [ | @@ -188,7 +196,7 @@ export const COLUMNS = [ | ||
188 | width: 120, | 196 | width: 120, |
189 | customRender: (column) => { | 197 | customRender: (column) => { |
190 | if (column.record?.beforeGrossProfitRate) { | 198 | if (column.record?.beforeGrossProfitRate) { |
191 | - return column.record?.beforeGrossProfitRate?.toFixed(2) + '%'; | 199 | + return (column.record?.beforeGrossProfitRate * 100).toFixed(2) + '%'; |
192 | } | 200 | } |
193 | return column.record?.beforeGrossProfitRate?.toFixed(2); | 201 | return column.record?.beforeGrossProfitRate?.toFixed(2); |
194 | }, | 202 | }, |
@@ -207,11 +215,25 @@ export const COLUMNS = [ | @@ -207,11 +215,25 @@ export const COLUMNS = [ | ||
207 | width: 120, | 215 | width: 120, |
208 | customRender: (column) => { | 216 | customRender: (column) => { |
209 | if (column.record?.grossProfitRate) { | 217 | if (column.record?.grossProfitRate) { |
210 | - return column.record?.grossProfitRate?.toFixed(2) + '%'; | 218 | + return (column.record?.grossProfitRate * 100).toFixed(2) + '%'; |
211 | } | 219 | } |
212 | return column.record?.grossProfitRate?.toFixed(2); | 220 | return column.record?.grossProfitRate?.toFixed(2); |
213 | }, | 221 | }, |
214 | }, | 222 | }, |
223 | + { | ||
224 | + title: '状态', | ||
225 | + dataIndex: 'status', | ||
226 | + width: 120, | ||
227 | + customRender: (column) => { | ||
228 | + if (column.record?.innerProduceStatus === null || column.record?.innerProduceStatus === -1) { | ||
229 | + return '未完成'; | ||
230 | + } else if (column.record?.innerProduceStatus === 0) { | ||
231 | + return '待审核'; | ||
232 | + } else if (column.record?.innerProduceStatus === 1) { | ||
233 | + return '已审核'; | ||
234 | + } | ||
235 | + }, | ||
236 | + }, | ||
215 | // { | 237 | // { |
216 | // title: '内部生产固定成本¥', | 238 | // title: '内部生产固定成本¥', |
217 | // dataIndex: 'innerProductionFixedCost', | 239 | // dataIndex: 'innerProductionFixedCost', |
src/views/project/finance/financeProfit/ProductProfit/InnerData/index.vue
1 | <template> | 1 | <template> |
2 | <div> | 2 | <div> |
3 | <BasicTable @register="registerTable" :bordered="true"> | 3 | <BasicTable @register="registerTable" :bordered="true"> |
4 | + <template #headerTop> | ||
5 | + <a-alert type="info" show-icon> | ||
6 | + <template #message> | ||
7 | + <template v-if="checkedKeys.length > 0"> | ||
8 | + <span>已选中{{ checkedKeys.length }}条记录(可跨页)</span> | ||
9 | + <a-button | ||
10 | + :style="{ borderRadius: '5px 5px 5px 5px' }" | ||
11 | + type="link" | ||
12 | + @click="handleClearChoose" | ||
13 | + size="small" | ||
14 | + >清空</a-button | ||
15 | + > | ||
16 | + </template> | ||
17 | + <template v-else> | ||
18 | + <span>未选中任何订单</span> | ||
19 | + </template> | ||
20 | + </template> | ||
21 | + </a-alert> | ||
22 | + </template> | ||
4 | <template #bodyCell="{ column, record }"> | 23 | <template #bodyCell="{ column, record }"> |
5 | <template v-if="column.key === 'picUrl'"> | 24 | <template v-if="column.key === 'picUrl'"> |
6 | <img :z-index="100000" :width="50" :height="50" :src="record?.picUrl" /> | 25 | <img :z-index="100000" :width="50" :height="50" :src="record?.picUrl" /> |
7 | </template> | 26 | </template> |
8 | <template v-if="column.key === 'action'"> | 27 | <template v-if="column.key === 'action'"> |
9 | - <TableAction :actions="createActions(record)" /> | 28 | + <TableAction :actions="createActions(record)" :dropDownActions="createDropActions(record)" /> |
10 | </template> | 29 | </template> |
11 | <!-- <template v-if="column.key === 'relationValue'"> | 30 | <!-- <template v-if="column.key === 'relationValue'"> |
12 | <a-input | 31 | <a-input |
@@ -19,6 +38,15 @@ | @@ -19,6 +38,15 @@ | ||
19 | </span> | 38 | </span> |
20 | </template> --> | 39 | </template> --> |
21 | </template> | 40 | </template> |
41 | + <template #toolbar> | ||
42 | + <a-button | ||
43 | + type="primary" | ||
44 | + @click="handleExport" | ||
45 | + v-if="role == ROLE.ADMIN || role == ROLE.FINANCE" | ||
46 | + :style="{ borderRadius: '5px 5px 5px 5px' }" | ||
47 | + >导出</a-button | ||
48 | + > | ||
49 | + </template> | ||
22 | </BasicTable> | 50 | </BasicTable> |
23 | <!-- <BasicModal | 51 | <!-- <BasicModal |
24 | title="拒绝原因" | 52 | title="拒绝原因" |
@@ -32,28 +60,48 @@ | @@ -32,28 +60,48 @@ | ||
32 | <a-textarea :rows="6" placeholder="请输入拒绝原因" v-model:value="message" /> | 60 | <a-textarea :rows="6" placeholder="请输入拒绝原因" v-model:value="message" /> |
33 | </div> | 61 | </div> |
34 | </BasicModal> --> | 62 | </BasicModal> --> |
35 | - <CheckDetail @register="checkModalRegister" /> | 63 | + <CheckDetail @register="checkModalRegister" :onGoFormDetail="handleGoFormDetail" /> |
36 | <FinanceEdit @register="registerFinanceEdit" @success="handleSuccess" /> | 64 | <FinanceEdit @register="registerFinanceEdit" @success="handleSuccess" /> |
65 | + <HistoryDetail @register="registerHistoryDetail" /> | ||
37 | </div> | 66 | </div> |
38 | </template> | 67 | </template> |
39 | <script setup lang="ts"> | 68 | <script setup lang="ts"> |
40 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; | 69 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; |
41 | - import { getInnerProfit } from '@/api/project/invoice'; | 70 | + import { getInnerProfit, setInnerStatus } from '@/api/project/invoice'; |
42 | import { searchFormSchema, COLUMNS } from './data'; | 71 | import { searchFormSchema, COLUMNS } from './data'; |
43 | import { BasicModal, useModal } from '/@/components/Modal'; | 72 | import { BasicModal, useModal } from '/@/components/Modal'; |
44 | import { useMessage } from '/@/hooks/web/useMessage'; | 73 | import { useMessage } from '/@/hooks/web/useMessage'; |
45 | - import { onMounted, ref } from 'vue'; | 74 | + import { onMounted, ref, computed } from 'vue'; |
75 | + import axios from 'axios'; | ||
46 | import { useDrawer } from '/@/components/Drawer'; | 76 | import { useDrawer } from '/@/components/Drawer'; |
47 | import FinanceEdit from './FinanceEdit.vue'; | 77 | import FinanceEdit from './FinanceEdit.vue'; |
48 | import CheckDetail from './CheckDetail.vue'; | 78 | import CheckDetail from './CheckDetail.vue'; |
79 | + import HistoryDetail from './HistoryDetail.vue'; | ||
49 | import { useOrderStoreWithOut } from '/@/store/modules/order'; | 80 | import { useOrderStoreWithOut } from '/@/store/modules/order'; |
81 | + import { useUserStoreWithOut } from '/@/store/modules/user'; | ||
82 | + import { RoleEnum } from '/@/enums/roleEnum'; | ||
83 | + import { ROLE } from '../../../type.d'; | ||
50 | 84 | ||
51 | const { createMessage } = useMessage(); | 85 | const { createMessage } = useMessage(); |
52 | const { error } = createMessage; | 86 | const { error } = createMessage; |
53 | const message = ref(); | 87 | const message = ref(); |
88 | + const checkedKeys = ref<string[]>([]); | ||
89 | + // Define arrays to store collected data from selected rows | ||
90 | + const orderIds = ref<number[]>([]); | ||
91 | + const projectNo = ref<string[]>([]); | ||
92 | + const customerCode = ref<string[]>([]); | ||
93 | + const innerNo = ref<string[]>([]); | ||
94 | + const productionDepartment = ref<string[]>([]); | ||
95 | + const detailProjectNoKeys = ref<string[]>([]); | ||
54 | const orderStore = useOrderStoreWithOut(); | 96 | const orderStore = useOrderStoreWithOut(); |
55 | const [checkModalRegister, { openDrawer: openCheckDetailDrawer }] = useDrawer(); | 97 | const [checkModalRegister, { openDrawer: openCheckDetailDrawer }] = useDrawer(); |
56 | const [registerFinanceEdit, { openDrawer: openFinanceEdit }] = useDrawer(); | 98 | const [registerFinanceEdit, { openDrawer: openFinanceEdit }] = useDrawer(); |
99 | + const [registerHistoryDetail, { openDrawer: openHistoryDetail }] = useDrawer(); | ||
100 | + const userStore = useUserStoreWithOut(); | ||
101 | + const user = userStore.getUserInfo; | ||
102 | + const role = computed(() => { | ||
103 | + return user?.roleSmallVO?.code; | ||
104 | + }); | ||
57 | const handleOk = (record) => { | 105 | const handleOk = (record) => { |
58 | // 修改父组件的状态 | 106 | // 修改父组件的状态 |
59 | closeModal(); | 107 | closeModal(); |
@@ -63,11 +111,28 @@ | @@ -63,11 +111,28 @@ | ||
63 | message.value = ''; | 111 | message.value = ''; |
64 | } | 112 | } |
65 | }; | 113 | }; |
66 | - const [registerTable, { reload }] = useTable({ | 114 | + const [registerTable, { reload, setSelectedRowKeys, getForm }] = useTable({ |
67 | api: getInnerProfit, | 115 | api: getInnerProfit, |
68 | bordered: true, | 116 | bordered: true, |
69 | columns: COLUMNS, | 117 | columns: COLUMNS, |
70 | - rowKey: 'id', | 118 | + rowKey: 'orderId', |
119 | + customRow: () => { | ||
120 | + return { | ||
121 | + onClick: (e) => { | ||
122 | + // Prevent row selection when clicking anywhere except checkboxes | ||
123 | + if (!e.target.closest('.ant-checkbox-wrapper')) { | ||
124 | + e.stopPropagation(); | ||
125 | + } | ||
126 | + }, | ||
127 | + }; | ||
128 | + }, | ||
129 | + rowSelection: { | ||
130 | + type: 'checkbox', | ||
131 | + selectedRowKeys: checkedKeys as any, | ||
132 | + onSelect: onSelect, | ||
133 | + onSelectAll: onSelectAll, | ||
134 | + checkStrictly: true, | ||
135 | + }, | ||
71 | formConfig: { | 136 | formConfig: { |
72 | labelWidth: 120, | 137 | labelWidth: 120, |
73 | schemas: searchFormSchema, | 138 | schemas: searchFormSchema, |
@@ -80,7 +145,7 @@ | @@ -80,7 +145,7 @@ | ||
80 | setting: false, | 145 | setting: false, |
81 | }, | 146 | }, |
82 | actionColumn: { | 147 | actionColumn: { |
83 | - width: 240, | 148 | + width: 260, |
84 | title: 'Action', | 149 | title: 'Action', |
85 | dataIndex: 'action', | 150 | dataIndex: 'action', |
86 | }, | 151 | }, |
@@ -111,6 +176,18 @@ | @@ -111,6 +176,18 @@ | ||
111 | // }, | 176 | // }, |
112 | onClick: handleFalse.bind(null, record), | 177 | onClick: handleFalse.bind(null, record), |
113 | }, | 178 | }, |
179 | + { | ||
180 | + label: '审批通过', | ||
181 | + popConfirm: { | ||
182 | + title: '确认审批?', | ||
183 | + confirm: () => { | ||
184 | + if (record.innerProduceStatus === 0 && role.value === ROLE.ADMIN) { | ||
185 | + handleStatus(record, true); | ||
186 | + } | ||
187 | + return; | ||
188 | + }, | ||
189 | + }, | ||
190 | + }, | ||
114 | ]; | 191 | ]; |
115 | } | 192 | } |
116 | return [ | 193 | return [ |
@@ -128,6 +205,18 @@ | @@ -128,6 +205,18 @@ | ||
128 | ]; | 205 | ]; |
129 | } | 206 | } |
130 | 207 | ||
208 | + function createDropActions(record: any) { | ||
209 | + if (!record.editable) { | ||
210 | + const actions = [ | ||
211 | + { | ||
212 | + label: '历史记录', | ||
213 | + onClick: handleHistoryDetail.bind(null, record), | ||
214 | + }, | ||
215 | + ]; | ||
216 | + return actions; | ||
217 | + } | ||
218 | + } | ||
219 | + | ||
131 | onMounted(async () => { | 220 | onMounted(async () => { |
132 | await orderStore.getDict(); | 221 | await orderStore.getDict(); |
133 | }); | 222 | }); |
@@ -175,5 +264,224 @@ | @@ -175,5 +264,224 @@ | ||
175 | reload(); | 264 | reload(); |
176 | }, 50); | 265 | }, 50); |
177 | } | 266 | } |
267 | + | ||
268 | + async function handleStatus(record, status) { | ||
269 | + try { | ||
270 | + // Add your API call here for updating status | ||
271 | + // Example: await updateStatus({ id: record.id, status: status ? 1 : 2 }); | ||
272 | + await setInnerStatus({ orderId: record.orderId }); | ||
273 | + reload(); | ||
274 | + } catch (error) { | ||
275 | + console.error(error); | ||
276 | + } | ||
277 | + } | ||
278 | + | ||
279 | + function handleHistoryDetail(record) { | ||
280 | + openHistoryDetail(true, { | ||
281 | + data: record, | ||
282 | + }); | ||
283 | + } | ||
284 | + | ||
285 | + function handleGoFormDetail() { | ||
286 | + reload(); | ||
287 | + } | ||
288 | + | ||
289 | + function handleClearChoose() { | ||
290 | + checkedKeys.value = []; | ||
291 | + orderIds.value = []; | ||
292 | + projectNo.value = []; | ||
293 | + customerCode.value = []; | ||
294 | + innerNo.value = []; | ||
295 | + productionDepartment.value = []; | ||
296 | + detailProjectNoKeys.value = []; | ||
297 | + setSelectedRowKeys([]); | ||
298 | + } | ||
299 | + | ||
300 | + function handleExport() { | ||
301 | + // Get current search parameters from the form | ||
302 | + const values = getForm().getFieldsValue(); | ||
303 | + | ||
304 | + // Create export parameters based on whether orderIds are selected | ||
305 | + let exportParams; | ||
306 | + | ||
307 | + // If orderIds are selected, only use those and ignore search params | ||
308 | + if (orderIds.value.length > 0) { | ||
309 | + exportParams = { | ||
310 | + orderIds: orderIds.value | ||
311 | + }; | ||
312 | + } | ||
313 | + // Otherwise use the search parameters | ||
314 | + else { | ||
315 | + exportParams = { | ||
316 | + ...values, | ||
317 | + projectNo: values.projectNo || undefined, | ||
318 | + customerCode: values.customerCode || undefined, | ||
319 | + innerNo: values.innerNo || undefined, | ||
320 | + productionDepartment: values.productionDepartment || undefined | ||
321 | + }; | ||
322 | + } | ||
323 | + | ||
324 | + | ||
325 | + const token = userStore.getToken; | ||
326 | + axios | ||
327 | + .post( | ||
328 | + '/basic-api/order/cost/innerProfitDetail/exportExcel', | ||
329 | + exportParams, | ||
330 | + { | ||
331 | + headers: { | ||
332 | + Authorization: `${token}`, | ||
333 | + }, | ||
334 | + responseType: 'blob', | ||
335 | + }, | ||
336 | + ) | ||
337 | + .then((response) => { | ||
338 | + // 创建一个 Blob 对象来保存二进制数据 | ||
339 | + const blob = new Blob([response.data], { type: 'application/zip' }); | ||
340 | + const getFormattedDate = (): string => { | ||
341 | + const date = new Date(); | ||
342 | + | ||
343 | + const year = date.getFullYear(); | ||
344 | + const month = String(date.getMonth() + 1).padStart(2, '0'); | ||
345 | + const day = String(date.getDate()).padStart(2, '0'); | ||
346 | + | ||
347 | + const hours = String(date.getHours()).padStart(2, '0'); | ||
348 | + const minutes = String(date.getMinutes()).padStart(2, '0'); | ||
349 | + const seconds = String(date.getSeconds()).padStart(2, '0'); | ||
350 | + | ||
351 | + return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; | ||
352 | + }; | ||
353 | + const date = getFormattedDate(); | ||
354 | + // 创建一个链接元素用于下载 | ||
355 | + const link = document.createElement('a'); | ||
356 | + link.href = window.URL.createObjectURL(blob); | ||
357 | + link.download = `内研数据筛选净利润分析表${date}.xlsx`; | ||
358 | + document.body.appendChild(link); | ||
359 | + link.click(); // 自动点击链接,触发下载 | ||
360 | + document.body.removeChild(link); // 下载完成后移除链接 | ||
361 | + }) | ||
362 | + .catch((error) => { | ||
363 | + console.error(error); | ||
364 | + }); | ||
365 | + handleClearChoose(); | ||
366 | + reload(); | ||
367 | + } | ||
368 | + | ||
369 | + async function onSelect(record, selected: boolean) { | ||
370 | + const rowKey = record.orderId; | ||
371 | + if (selected) { | ||
372 | + checkedKeys.value = [...checkedKeys.value, rowKey]; | ||
373 | + | ||
374 | + // Add data from the selected row to the corresponding arrays | ||
375 | + if (record.orderId !== undefined && !orderIds.value.includes(record.orderId)) { | ||
376 | + orderIds.value.push(record.orderId); | ||
377 | + } | ||
378 | + | ||
379 | + if (record.projectNo !== undefined && !projectNo.value.includes(record.projectNo)) { | ||
380 | + projectNo.value.push(record.projectNo); | ||
381 | + } | ||
382 | + | ||
383 | + if (record.customerCode !== undefined && !customerCode.value.includes(record.customerCode)) { | ||
384 | + customerCode.value.push(record.customerCode); | ||
385 | + } | ||
386 | + | ||
387 | + if (record.innerNo !== undefined && !innerNo.value.includes(record.innerNo)) { | ||
388 | + innerNo.value.push(record.innerNo); | ||
389 | + } | ||
390 | + | ||
391 | + if (record.productionDepartment !== undefined && !productionDepartment.value.includes(record.productionDepartment)) { | ||
392 | + productionDepartment.value.push(record.productionDepartment); | ||
393 | + } | ||
394 | + | ||
395 | + if (record.detailProjectNo !== undefined && !detailProjectNoKeys.value.includes(record.detailProjectNo)) { | ||
396 | + detailProjectNoKeys.value.push(record.detailProjectNo); | ||
397 | + } | ||
398 | + } else { | ||
399 | + checkedKeys.value = checkedKeys.value.filter((key) => key !== rowKey); | ||
400 | + | ||
401 | + // Remove data from the deselected row from the corresponding arrays | ||
402 | + if (record.orderId !== undefined) { | ||
403 | + orderIds.value = orderIds.value.filter((id) => id !== record.orderId); | ||
404 | + } | ||
405 | + | ||
406 | + if (record.projectNo !== undefined) { | ||
407 | + projectNo.value = projectNo.value.filter((no) => no !== record.projectNo); | ||
408 | + } | ||
409 | + | ||
410 | + if (record.customerCode !== undefined) { | ||
411 | + customerCode.value = customerCode.value.filter((code) => code !== record.customerCode); | ||
412 | + } | ||
413 | + | ||
414 | + if (record.innerNo !== undefined) { | ||
415 | + innerNo.value = innerNo.value.filter((no) => no !== record.innerNo); | ||
416 | + } | ||
417 | + | ||
418 | + if (record.productionDepartment !== undefined) { | ||
419 | + productionDepartment.value = productionDepartment.value.filter( | ||
420 | + (dept) => dept !== record.productionDepartment, | ||
421 | + ); | ||
422 | + } | ||
423 | + | ||
424 | + if (record.detailProjectNo !== undefined) { | ||
425 | + detailProjectNoKeys.value = detailProjectNoKeys.value.filter( | ||
426 | + (projectNo) => projectNo !== record.detailProjectNo, | ||
427 | + ); | ||
428 | + } | ||
429 | + } | ||
430 | + setSelectedRowKeys(checkedKeys.value as any); | ||
431 | + } | ||
432 | + | ||
433 | + function onSelectAll(selected: boolean, selectedRows: any[]) { | ||
434 | + if (selected) { | ||
435 | + // First clear all previous selections to avoid duplicates | ||
436 | + checkedKeys.value = []; | ||
437 | + orderIds.value = []; | ||
438 | + projectNo.value = []; | ||
439 | + customerCode.value = []; | ||
440 | + innerNo.value = []; | ||
441 | + productionDepartment.value = []; | ||
442 | + detailProjectNoKeys.value = []; | ||
443 | + | ||
444 | + // Add all selected rows | ||
445 | + selectedRows.forEach((row) => { | ||
446 | + const rowKey = row.orderId; | ||
447 | + checkedKeys.value.push(rowKey); | ||
448 | + | ||
449 | + // Add data from each selected row to the corresponding arrays | ||
450 | + if (row.orderId !== undefined) { | ||
451 | + orderIds.value.push(row.orderId); | ||
452 | + } | ||
453 | + | ||
454 | + if (row.projectNo !== undefined) { | ||
455 | + projectNo.value.push(row.projectNo); | ||
456 | + } | ||
457 | + | ||
458 | + if (row.customerCode !== undefined) { | ||
459 | + customerCode.value.push(row.customerCode); | ||
460 | + } | ||
461 | + | ||
462 | + if (row.innerNo !== undefined) { | ||
463 | + innerNo.value.push(row.innerNo); | ||
464 | + } | ||
465 | + | ||
466 | + if (row.productionDepartment !== undefined) { | ||
467 | + productionDepartment.value.push(row.productionDepartment); | ||
468 | + } | ||
469 | + | ||
470 | + if (row.detailProjectNo !== undefined) { | ||
471 | + detailProjectNoKeys.value.push(row.detailProjectNo); | ||
472 | + } | ||
473 | + }); | ||
474 | + } else { | ||
475 | + // Clear all selections when deselecting all | ||
476 | + checkedKeys.value = []; | ||
477 | + orderIds.value = []; | ||
478 | + projectNo.value = []; | ||
479 | + customerCode.value = []; | ||
480 | + innerNo.value = []; | ||
481 | + productionDepartment.value = []; | ||
482 | + detailProjectNoKeys.value = []; | ||
483 | + } | ||
484 | + setSelectedRowKeys(checkedKeys.value as any); | ||
485 | + } | ||
178 | </script> | 486 | </script> |
179 | <style></style> | 487 | <style></style> |
src/views/project/finance/financeProfit/ProductProfit/InnerData/tableData.tsx
@@ -34,6 +34,13 @@ export const FIELDS_BASE_INFO = [ | @@ -34,6 +34,13 @@ export const FIELDS_BASE_INFO = [ | ||
34 | label: '实际发生费用', | 34 | label: '实际发生费用', |
35 | rules: [{ required: true }], | 35 | rules: [{ required: true }], |
36 | }, | 36 | }, |
37 | + { | ||
38 | + field: 'productionDepartmentPredictUnitPrice', | ||
39 | + component: 'Select', | ||
40 | + labelWidth: 150, | ||
41 | + label: '生产科预算单价', | ||
42 | + rules: [{ required: true }], | ||
43 | + }, | ||
37 | ]; | 44 | ]; |
38 | 45 | ||
39 | export const EDIT_INFO = [ | 46 | export const EDIT_INFO = [ |
@@ -58,5 +65,12 @@ export const EDIT_INFO = [ | @@ -58,5 +65,12 @@ export const EDIT_INFO = [ | ||
58 | label: '实际发生费用', | 65 | label: '实际发生费用', |
59 | rules: [{ required: true }], | 66 | rules: [{ required: true }], |
60 | }, | 67 | }, |
68 | + { | ||
69 | + field: 'productionDepartmentPredictUnitPrice', | ||
70 | + component: 'Select', | ||
71 | + labelWidth: 150, | ||
72 | + label: '生产科预算单价', | ||
73 | + rules: [{ required: true }], | ||
74 | + }, | ||
61 | ]; | 75 | ]; |
62 | 76 |
src/views/project/finance/financeProfit/ProductProfit/InnerProduce/ApproveReason.vue
0 → 100644
1 | +<template> | ||
2 | + <BasicModal | ||
3 | + v-bind="$attrs" | ||
4 | + destroyOnClose | ||
5 | + @register="register" | ||
6 | + title="申请原因" | ||
7 | + :helpMessage="['提示1', '提示2']" | ||
8 | + @open-change="handleShow" | ||
9 | + :bodyStyle="{ height: '200px' }" | ||
10 | + @ok="handleOk" | ||
11 | + z-index="9999" | ||
12 | + > | ||
13 | + <a-textarea v-model:value="input" :rows="7" /> | ||
14 | + </BasicModal> | ||
15 | +</template> | ||
16 | +<script lang="ts" setup> | ||
17 | + import { ref, watch } from 'vue'; | ||
18 | + import { BasicModal, useModalInner } from '@/components/Modal'; | ||
19 | + import { orderAuth } from '/@/api/project/order'; | ||
20 | + import { getServiceApplyEdit } from '/@/api/project/invoice'; | ||
21 | + | ||
22 | + const emit = defineEmits(['success']); | ||
23 | + const input = ref(''); | ||
24 | + const baseFieldValues = ref(); | ||
25 | + const [register, { setModalProps, redoModalHeight, closeModal }] = useModalInner(async (data) => { | ||
26 | + baseFieldValues.value = data.data; | ||
27 | + baseFieldValues.value.projectNoPrefix = data.id; | ||
28 | + }); | ||
29 | + async function handleOk() { | ||
30 | + baseFieldValues.value.applyRemark = input.value; | ||
31 | + await getServiceApplyEdit({ | ||
32 | + projectNoPrefix: baseFieldValues.value.projectNoPrefix, | ||
33 | + projectInnerProfitInfoEndTime: baseFieldValues.value.projectInnerProfitInfoEndTime, | ||
34 | + projectInnerProfitInfoStartTime: baseFieldValues.value.projectInnerProfitInfoStartTime, | ||
35 | + applyRemark: baseFieldValues.value.applyRemark, | ||
36 | + type: 'INNER_PROFIT_FIELD_EDIT_APPLY', | ||
37 | + }); | ||
38 | + emit('success'); | ||
39 | + setTimeout(() => { | ||
40 | + closeModal(); | ||
41 | + }, 50); | ||
42 | + } | ||
43 | + function handleShow() { | ||
44 | + input.value = ''; | ||
45 | + closeModal(); | ||
46 | + } | ||
47 | +</script> |
src/views/project/finance/financeProfit/ProductProfit/InnerProduce/CheckDetail.vue
0 → 100644
1 | +<template> | ||
2 | + <div class="container"> | ||
3 | + <BasicDrawer | ||
4 | + @register="register" | ||
5 | + v-bind="$attrs" | ||
6 | + showFooter | ||
7 | + title="字段编辑权限申请" | ||
8 | + width="60%" | ||
9 | + :destroyOnClose="true" | ||
10 | + :isDetail="true" | ||
11 | + @ok="handleSubmit" | ||
12 | + :showDetailBack="false" | ||
13 | + okText="申请" | ||
14 | + ><input /> | ||
15 | + <div> | ||
16 | + <template v-if="role === ROLE.ADMIN || role === ROLE.FINANCE"> | ||
17 | + <BasicForm @register="registerForm" /> | ||
18 | + </template> | ||
19 | + </div> | ||
20 | + <!-- <template #titleToolbar> <a-button type="primary"> 申请编辑权限 </a-button></template> --> | ||
21 | + | ||
22 | + <!-- <template #appendFooter> | ||
23 | + <a-button type="primary" @click="onGoFormDetail"> 返回编辑</a-button> | ||
24 | + </template> --> | ||
25 | + </BasicDrawer> | ||
26 | + <ApproveReason @register="approveReasonRegister" @success="handleCloseModal" /> | ||
27 | + </div> | ||
28 | +</template> | ||
29 | +<script lang="ts"> | ||
30 | + import { computed, defineComponent, reactive, ref } from 'vue'; | ||
31 | + import { BasicForm, useForm } from '/@/components/Form/index'; | ||
32 | + import { getPackageApplyEdit } from '/@/api/project/invoice'; | ||
33 | + import { ROLE } from '../../../financeList/type.d'; | ||
34 | + import { useModal } from '/@/components/Modal'; | ||
35 | + import ApproveReason from './ApproveReason.vue'; | ||
36 | + import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; | ||
37 | + import { FIELDS_BASE_INFO } from './tableData'; | ||
38 | + import { useUserStoreWithOut } from '/@/store/modules/user'; | ||
39 | + | ||
40 | + const userStore = useUserStoreWithOut(); | ||
41 | + const getSchema = (fields) => | ||
42 | + fields.map((item) => ({ | ||
43 | + field: `${item.field}`, | ||
44 | + dataIndex: `${item.field}`, | ||
45 | + label: item.label, | ||
46 | + component: 'Switch', | ||
47 | + componentProps: { | ||
48 | + checkedValue: 'UN_LOCKED', | ||
49 | + unCheckedValue: 'LOCKED', | ||
50 | + }, | ||
51 | + colProps: { | ||
52 | + span: 8, | ||
53 | + }, | ||
54 | + })); | ||
55 | + | ||
56 | + export default defineComponent({ | ||
57 | + components: { BasicDrawer, BasicForm, ApproveReason }, | ||
58 | + props: { | ||
59 | + onGoFormDetail: { | ||
60 | + type: Function, | ||
61 | + }, | ||
62 | + }, | ||
63 | + setup() { | ||
64 | + const id = ref(''); | ||
65 | + const schemas = getSchema(FIELDS_BASE_INFO); | ||
66 | + const [registerForm, { getFieldsValue }] = useForm({ | ||
67 | + labelWidth: 180, | ||
68 | + schemas, | ||
69 | + showActionButtonGroup: false, | ||
70 | + actionColOptions: { | ||
71 | + span: 24, | ||
72 | + }, | ||
73 | + }); | ||
74 | + const [approveReasonRegister, { openModal: openApproveReasonDrawer }] = useModal(); | ||
75 | + | ||
76 | + const lockFields = reactive({}); | ||
77 | + const [register, { closeDrawer }] = useDrawerInner((data) => { | ||
78 | + Object.assign(lockFields, data.lockFields); | ||
79 | + id.value = data.projectNoPrefix; | ||
80 | + }); | ||
81 | + function handleCloseModal() { | ||
82 | + closeDrawer(); | ||
83 | + } | ||
84 | + | ||
85 | + const role = computed(() => { | ||
86 | + return userStore.getUserInfo?.roleSmallVO?.code; | ||
87 | + }); | ||
88 | + | ||
89 | + const handleSubmit = async () => { | ||
90 | + const baseFieldValues = getFieldsValue(); | ||
91 | + openApproveReasonDrawer(true, { | ||
92 | + data: baseFieldValues, | ||
93 | + id: id.value, | ||
94 | + }); | ||
95 | + }; | ||
96 | + | ||
97 | + return { | ||
98 | + register, | ||
99 | + schemas, | ||
100 | + registerForm, | ||
101 | + handleSubmit, | ||
102 | + handleCloseModal, | ||
103 | + approveReasonRegister, | ||
104 | + openApproveReasonDrawer, | ||
105 | + ROLE, | ||
106 | + role, | ||
107 | + }; | ||
108 | + }, | ||
109 | + }); | ||
110 | +</script> | ||
111 | +<style> | ||
112 | + .container { | ||
113 | + position: fixed; /* 或 absolute, fixed */ | ||
114 | + z-index: 10; | ||
115 | + } | ||
116 | +</style> |
src/views/project/finance/financeProfit/ProductProfit/InnerProduce/FinanceEdit.vue
@@ -3,31 +3,57 @@ | @@ -3,31 +3,57 @@ | ||
3 | <BasicDrawer | 3 | <BasicDrawer |
4 | @register="register" | 4 | @register="register" |
5 | v-bind="$attrs" | 5 | v-bind="$attrs" |
6 | - title="收入款单" | 6 | + title="编辑" |
7 | width="30%" | 7 | width="30%" |
8 | :isDetail="true" | 8 | :isDetail="true" |
9 | @ok="handleSubmit" | 9 | @ok="handleSubmit" |
10 | :showDetailBack="false" | 10 | :showDetailBack="false" |
11 | okText="保存" | 11 | okText="保存" |
12 | + @visible-change="handleShow" | ||
12 | showFooter | 13 | showFooter |
13 | :destroyOnClose="true" | 14 | :destroyOnClose="true" |
14 | > | 15 | > |
15 | <!-- <div> | 16 | <!-- <div> |
16 | <BasicForm @register="registerForm" /> | 17 | <BasicForm @register="registerForm" /> |
17 | </div> --> | 18 | </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 /> | 19 | + <!-- <div style="font-size: 15px">研发复制费合计¥</div> |
20 | + <a-input | ||
21 | + v-model:value="input1" | ||
22 | + placeholder="请输入" | ||
23 | + :disabled="status1 === 'LOCKED'" | ||
24 | + auto-size | ||
25 | + /> --> | ||
23 | <div style="margin: 16px 0"></div> | 26 | <div style="margin: 16px 0"></div> |
24 | <div style="font-size: 15px">项目开始时间</div> | 27 | <div style="font-size: 15px">项目开始时间</div> |
25 | - <a-date-picker v-model:value="input3" :disabled="status === 10" auto-size /> | 28 | + <a-date-picker v-model:value="input3" :disabled="status3 === 'LOCKED'" auto-size /> |
26 | <div style="margin: 16px 0"></div> | 29 | <div style="margin: 16px 0"></div> |
27 | <div style="font-size: 15px">项目结束时间</div> | 30 | <div style="font-size: 15px">项目结束时间</div> |
28 | - <a-date-picker v-model:value="input4" :disabled="status === 10" auto-size /> | 31 | + <a-date-picker v-model:value="input4" :disabled="status4 === 'LOCKED'" auto-size /> |
32 | + <!-- <div style="margin: 16px 0"></div> | ||
33 | + <div style="font-size: 15px">西班牙已发提成¥</div> | ||
34 | + <a-input | ||
35 | + v-model:value="input2" | ||
36 | + placeholder="请输入" | ||
37 | + :disabled="status2 === 'LOCKED'" | ||
38 | + auto-size | ||
39 | + /> | ||
40 | + <div style="margin: 16px 0"></div> | ||
41 | + <div style="font-size: 15px">中国团队已发提成¥</div> | ||
42 | + <a-input | ||
43 | + v-model:value="input5" | ||
44 | + placeholder="请输入" | ||
45 | + :disabled="status5 === 'LOCKED'" | ||
46 | + auto-size | ||
47 | + /> | ||
48 | + <div style="margin: 16px 0"></div> | ||
49 | + <div style="font-size: 15px">实际汇率¥</div> | ||
50 | + <a-input | ||
51 | + v-model:value="input6" | ||
52 | + placeholder="请输入" | ||
53 | + :disabled="status6 === 'LOCKED'" | ||
54 | + auto-size | ||
55 | + /> --> | ||
29 | <div style="margin: 16px 0"></div> | 56 | <div style="margin: 16px 0"></div> |
30 | - | ||
31 | <!-- <template #titleToolbar> <a-button type="primary"> 申请编辑权限 </a-button></template> --> | 57 | <!-- <template #titleToolbar> <a-button type="primary"> 申请编辑权限 </a-button></template> --> |
32 | <template #appendFooter> | 58 | <template #appendFooter> |
33 | <!-- <a-button type="primary" @click="onGoCheckDetail"> 申请权限</a-button> --> | 59 | <!-- <a-button type="primary" @click="onGoCheckDetail"> 申请权限</a-button> --> |
@@ -39,10 +65,11 @@ | @@ -39,10 +65,11 @@ | ||
39 | import { BasicDrawer, useDrawerInner } from '@/components/Drawer'; | 65 | import { BasicDrawer, useDrawerInner } from '@/components/Drawer'; |
40 | import { BasicForm, FormSchema, useForm } from '@/components/Form'; | 66 | import { BasicForm, FormSchema, useForm } from '@/components/Form'; |
41 | import { defineComponent, ref, computed, unref, toRaw, reactive } from 'vue'; | 67 | import { defineComponent, ref, computed, unref, toRaw, reactive } from 'vue'; |
42 | - import { getEmailList } from '/@/api/sys/config'; | ||
43 | - import { updateAmount } from '@/api/project/invoice'; | 68 | + import { getServiceEdit } from '@/api/project/invoice'; |
44 | import { useMessage } from '/@/hooks/web/useMessage'; | 69 | import { useMessage } from '/@/hooks/web/useMessage'; |
45 | import { ROLE } from './type.d'; | 70 | import { ROLE } from './type.d'; |
71 | + import type { Dayjs } from 'dayjs'; | ||
72 | + import dayjs from 'dayjs'; | ||
46 | 73 | ||
47 | const emit = defineEmits(['success']); | 74 | const emit = defineEmits(['success']); |
48 | const role = computed(() => { | 75 | const role = computed(() => { |
@@ -59,16 +86,16 @@ | @@ -59,16 +86,16 @@ | ||
59 | // label: '实际应收金额', | 86 | // label: '实际应收金额', |
60 | // }, | 87 | // }, |
61 | { | 88 | { |
62 | - field: 'actualPayedAmount1', | 89 | + field: 'developmentCopyRmbTotalPrice', |
63 | component: 'InputNumber', | 90 | component: 'InputNumber', |
64 | labelWidth: 250, | 91 | labelWidth: 250, |
65 | colProps: { | 92 | colProps: { |
66 | span: 23, | 93 | span: 23, |
67 | }, | 94 | }, |
68 | - componentProps: () => ({ | ||
69 | - disabled: status.value === 10, | ||
70 | - }), | ||
71 | - label: '实际应收金额1$', | 95 | + // componentProps: () => ({ |
96 | + // disabled: status.value === 10, | ||
97 | + // }), | ||
98 | + label: '研发复制费合计¥', | ||
72 | }, | 99 | }, |
73 | { | 100 | { |
74 | field: 'actualPayedAmount2', | 101 | field: 'actualPayedAmount2', |
@@ -77,9 +104,7 @@ | @@ -77,9 +104,7 @@ | ||
77 | colProps: { | 104 | colProps: { |
78 | span: 23, | 105 | span: 23, |
79 | }, | 106 | }, |
80 | - componentProps: () => ({ | ||
81 | - disabled: status.value === 10, | ||
82 | - }), | 107 | + |
83 | label: '实际应收金额2$', | 108 | label: '实际应收金额2$', |
84 | }, | 109 | }, |
85 | { | 110 | { |
@@ -89,9 +114,7 @@ | @@ -89,9 +114,7 @@ | ||
89 | colProps: { | 114 | colProps: { |
90 | span: 23, | 115 | span: 23, |
91 | }, | 116 | }, |
92 | - componentProps: () => ({ | ||
93 | - disabled: status.value === 10, | ||
94 | - }), | 117 | + |
95 | label: '实际应收金额3$', | 118 | label: '实际应收金额3$', |
96 | }, | 119 | }, |
97 | { | 120 | { |
@@ -101,9 +124,7 @@ | @@ -101,9 +124,7 @@ | ||
101 | colProps: { | 124 | colProps: { |
102 | span: 23, | 125 | span: 23, |
103 | }, | 126 | }, |
104 | - componentProps: () => ({ | ||
105 | - disabled: status.value === 10, | ||
106 | - }), | 127 | + |
107 | label: '其他费用金额$', | 128 | label: '其他费用金额$', |
108 | }, | 129 | }, |
109 | ]; | 130 | ]; |
@@ -120,21 +141,60 @@ | @@ -120,21 +141,60 @@ | ||
120 | const { error } = createMessage; | 141 | const { error } = createMessage; |
121 | 142 | ||
122 | const update = ref(); | 143 | const update = ref(); |
123 | - const status = ref(); | 144 | + const status1 = ref(); |
145 | + const status2 = ref(); | ||
146 | + const status3 = ref(); | ||
147 | + const status4 = ref(); | ||
148 | + const status5 = ref(); | ||
149 | + const status6 = ref(); | ||
124 | 150 | ||
125 | const input1 = ref(); | 151 | const input1 = ref(); |
126 | const input2 = ref(); | 152 | const input2 = ref(); |
127 | const input3 = ref(); | 153 | const input3 = ref(); |
128 | const input4 = ref(); | 154 | const input4 = ref(); |
155 | + | ||
156 | + const input5 = ref(); | ||
157 | + const input6 = ref(); | ||
129 | const id = ref(); | 158 | const id = ref(); |
159 | + // function formatDate(dateStr: string): string { | ||
160 | + // const date = new Date(dateStr); | ||
161 | + // const year = date.getFullYear(); | ||
162 | + // const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份从0开始,+1 | ||
163 | + // const day = String(date.getDate()).padStart(2, '0'); | ||
164 | + // const hours = String(date.getHours()).padStart(2, '0'); | ||
165 | + // const minutes = String(date.getMinutes()).padStart(2, '0'); | ||
166 | + // const seconds = String(date.getSeconds()).padStart(2, '0'); | ||
167 | + | ||
168 | + // // 返回格式化后的字符串:'YYYY-MM-DD HH:mm:ss' | ||
169 | + // return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; | ||
170 | + // } | ||
171 | + // function formatDateToDateOnly(dateStr: string): string { | ||
172 | + // const date = new Date(dateStr); | ||
173 | + // const year = date.getFullYear(); | ||
174 | + // const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份从0开始,+1 | ||
175 | + // const day = String(date.getDate()).padStart(2, '0'); | ||
176 | + | ||
177 | + // // 返回格式化后的日期字符串:'YYYY-MM-DD' | ||
178 | + // return `${year}-${month}-${day}`; | ||
179 | + // } | ||
130 | const [register, { setDrawerProps, closeDrawer }] = useDrawerInner((data) => { | 180 | const [register, { setDrawerProps, closeDrawer }] = useDrawerInner((data) => { |
131 | // 方式1 | 181 | // 方式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; | 182 | + if (data.data.lockFields) { |
183 | + status1.value = data?.data?.lockFields?.developmentCopyRmbTotalPrice; | ||
184 | + status2.value = data?.data?.lockFields?.spainPaidRmbCommission; | ||
185 | + status3.value = data?.data?.lockFields?.projectInnerProfitInfoStartTime; | ||
186 | + status4.value = data?.data?.lockFields?.projectInnerProfitInfoEndTime; | ||
187 | + status5.value = data?.data?.lockFields?.paidRmbCommission; | ||
188 | + status6.value = data?.data?.lockFields?.actualExchangeRate; | ||
189 | + } | ||
190 | + id.value = data?.data?.projectNoPrefix; | ||
191 | + input1.value = data?.data?.developmentCopyRmbTotalPrice?.toFixed(2); | ||
192 | + input2.value = data?.data?.spainPaidRmbCommission?.toFixed(2); | ||
193 | + input3.value = data?.data?.produceStartTime ? dayjs(data?.data?.produceStartTime) : null; | ||
194 | + input4.value = data?.data?.produceEndTime ? dayjs(data?.data?.produceEndTime) : null; | ||
195 | + input5.value = data?.data?.paidRmbCommission?.toFixed(2); | ||
196 | + input6.value = data?.data?.actualExchangeRate?.toFixed(2); | ||
197 | + | ||
138 | resetFields(); | 198 | resetFields(); |
139 | setDrawerProps({ confirmLoading: false }); | 199 | setDrawerProps({ confirmLoading: false }); |
140 | setFieldsValue({ | 200 | setFieldsValue({ |
@@ -150,18 +210,26 @@ | @@ -150,18 +210,26 @@ | ||
150 | // id: update.value.data.id, | 210 | // id: update.value.data.id, |
151 | // bgUrl: update.value.data.bgUrl, | 211 | // bgUrl: update.value.data.bgUrl, |
152 | // }; | 212 | // }; |
153 | - if (!input1.value || !input2.value || !input3.value || !input4.value) { | 213 | + if (!input3.value || !input4.value) { |
154 | error('选项不能为空'); | 214 | error('选项不能为空'); |
155 | } else { | 215 | } else { |
156 | - await updateAmount({ | ||
157 | - id: id.value, | ||
158 | - actualPayedAmount1: input1.value, | ||
159 | - actualPayedAmount2: input2.value, | ||
160 | - actualPayedAmount3: input3.value, | ||
161 | - otherAmount: input4.value, | 216 | + await getServiceEdit({ |
217 | + projectNoPrefix: id.value, | ||
218 | + projectInnerProfitInfoStartTime: input3.value, | ||
219 | + projectInnerProfitInfoEndTime: input4.value, | ||
162 | }); | 220 | }); |
163 | emit('success'); | 221 | emit('success'); |
164 | closeDrawer(); | 222 | closeDrawer(); |
165 | } | 223 | } |
166 | } | 224 | } |
225 | + function handleShow(visible: boolean) { | ||
226 | + if (!visible) { | ||
227 | + input1.value = ''; | ||
228 | + input2.value = ''; | ||
229 | + input3.value = ''; | ||
230 | + input4.value = ''; | ||
231 | + input5.value = ''; | ||
232 | + input6.value = ''; | ||
233 | + } | ||
234 | + } | ||
167 | </script> | 235 | </script> |
src/views/project/finance/financeProfit/ProductProfit/InnerProduce/HistoryDetail.vue
0 → 100644
1 | +<template> | ||
2 | + <BasicDrawer | ||
3 | + @register="register" | ||
4 | + v-bind="$attrs" | ||
5 | + title="操作记录" | ||
6 | + width="60%" | ||
7 | + :isDetail="true" | ||
8 | + :showDetailBack="false" | ||
9 | + okText="保存" | ||
10 | + :destroyOnClose="true" | ||
11 | + > | ||
12 | + <Tabs v-model:activeKey="activeKey" className="my-0"> | ||
13 | + <TabPanel :key="1" tab="操作记录" className="w-full"> | ||
14 | + <a-list :pagination="pagination1" className="w-full"> | ||
15 | + <template v-for="item in list1" :key="item.id"> | ||
16 | + <a-list-item class="list"> | ||
17 | + <a-list-item-meta> | ||
18 | + <template #avatar> </template> | ||
19 | + <template #title> | ||
20 | + <span>{{ item.userName }}</span> | ||
21 | + </template> | ||
22 | + <template #description> | ||
23 | + <div class="description"> | ||
24 | + {{ item.optType }} | ||
25 | + </div> | ||
26 | + <div class="info"> | ||
27 | + <div><span>操作时间:</span>{{ formatToDateTime(item.createTime) }}</div> | ||
28 | + </div> | ||
29 | + </template> | ||
30 | + </a-list-item-meta> | ||
31 | + </a-list-item> | ||
32 | + </template> | ||
33 | + </a-list> | ||
34 | + </TabPanel> | ||
35 | + <TabPanel :key="2" tab="审批记录" className="w-full"> | ||
36 | + <a-list :pagination="pagination2" className="w-full"> | ||
37 | + <template v-for="item in list2" :key="item.id"> | ||
38 | + <a-list-item class="list"> | ||
39 | + <a-list-item-meta> | ||
40 | + <template #avatar> </template> | ||
41 | + <template #title> | ||
42 | + <span>{{ item.userName }}</span> | ||
43 | + </template> | ||
44 | + <template #description> | ||
45 | + <div class="description"> | ||
46 | + {{ item.optType }} | ||
47 | + </div> | ||
48 | + <div class="info"> | ||
49 | + <div><span>操作时间:</span>{{ formatToDateTime(item.createTime) }}</div> | ||
50 | + </div> | ||
51 | + </template> | ||
52 | + </a-list-item-meta> | ||
53 | + </a-list-item> | ||
54 | + </template> | ||
55 | + </a-list> | ||
56 | + </TabPanel> | ||
57 | + </Tabs> | ||
58 | + | ||
59 | + <!-- <template #titleToolbar> <a-button type="primary"> 申请编辑权限 </a-button></template> --> | ||
60 | + <template #appendFooter> | ||
61 | + <!-- <a-button type="primary" @click="onGoCheckDetail"> 申请权限</a-button> --> | ||
62 | + </template> | ||
63 | + </BasicDrawer> | ||
64 | +</template> | ||
65 | +<script lang="ts"> | ||
66 | + import { defineComponent, ref, computed } from 'vue'; | ||
67 | + import { Tabs, List } from 'ant-design-vue'; | ||
68 | + import { FormSchema } from '/@/components/Form/index'; | ||
69 | + | ||
70 | + import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; | ||
71 | + import { getProjectOptLog } from '/@/api/project/invoice'; | ||
72 | + import { formatToDateTime } from '/@/utils/dateUtil'; | ||
73 | + | ||
74 | + const TabPanel = Tabs.TabPane; | ||
75 | + | ||
76 | + const schemas: FormSchema[] = [ | ||
77 | + { | ||
78 | + field: '订单号', | ||
79 | + component: 'Input', | ||
80 | + label: '字段1', | ||
81 | + componentProps: { | ||
82 | + readonly: true, | ||
83 | + disabled: true, | ||
84 | + }, | ||
85 | + colProps: { | ||
86 | + span: 12, | ||
87 | + }, | ||
88 | + defaultValue: '111', | ||
89 | + }, | ||
90 | + { | ||
91 | + field: 'field2', | ||
92 | + component: 'Input', | ||
93 | + label: '字段2', | ||
94 | + colProps: { | ||
95 | + span: 12, | ||
96 | + }, | ||
97 | + }, | ||
98 | + ]; | ||
99 | + const achieveList = [ | ||
100 | + { | ||
101 | + key: '1', | ||
102 | + name: '操作记录', | ||
103 | + }, | ||
104 | + { | ||
105 | + key: '2', | ||
106 | + name: '审批记录', | ||
107 | + }, | ||
108 | + ]; | ||
109 | + export default defineComponent({ | ||
110 | + components: { | ||
111 | + BasicDrawer, | ||
112 | + Tabs, | ||
113 | + TabPanel, | ||
114 | + [List.name]: List, | ||
115 | + [List.Item.name]: List.Item, | ||
116 | + AListItemMeta: List.Item.Meta, | ||
117 | + }, | ||
118 | + props: { | ||
119 | + onGoCheckDetail: { | ||
120 | + type: Function, | ||
121 | + }, | ||
122 | + }, | ||
123 | + setup() { | ||
124 | + const list1 = ref([]); | ||
125 | + const total1 = ref(0); | ||
126 | + const page1 = ref(1); | ||
127 | + | ||
128 | + const list2 = ref([]); | ||
129 | + const total2 = ref(0); | ||
130 | + const page2 = ref(1); | ||
131 | + const orderId = ref(''); | ||
132 | + const activeKey = ref(1); | ||
133 | + | ||
134 | + const getOrderOptLogFunc = async (data, index, page) => { | ||
135 | + console.log('%c [ data ]-135', 'font-size:13px; background:pink; color:#bf2c9f;', data); | ||
136 | + if (index === 1) { | ||
137 | + const res = await getProjectOptLog({ | ||
138 | + projectNoPrefix: data, | ||
139 | + type: [30], | ||
140 | + page: page, | ||
141 | + pageSize: 20 | ||
142 | + }); | ||
143 | + list1.value = res.items; | ||
144 | + total1.value = res.total; | ||
145 | + page1.value = page; | ||
146 | + } else { | ||
147 | + const res = await getProjectOptLog({ | ||
148 | + projectNoPrefix: data, | ||
149 | + type: [1,3], | ||
150 | + page: page, | ||
151 | + pageSize: 20 | ||
152 | + }); | ||
153 | + list2.value = res.items; | ||
154 | + total2.value = res.total; | ||
155 | + page2.value = page; | ||
156 | + } | ||
157 | + }; | ||
158 | + const [register] = useDrawerInner((data) => { | ||
159 | + orderId.value = data.data.projectNoPrefix; | ||
160 | + getOrderOptLogFunc(orderId.value, 1, 1); | ||
161 | + getOrderOptLogFunc(orderId.value, 2, 1); | ||
162 | + }); | ||
163 | + | ||
164 | + const pagination1 = computed(() => { | ||
165 | + return { | ||
166 | + show: true, | ||
167 | + pageSize: 20, | ||
168 | + page: page1.value, | ||
169 | + total: total1.value, | ||
170 | + onChange(cur) { | ||
171 | + getOrderOptLogFunc(orderId.value, 1, cur); | ||
172 | + }, | ||
173 | + }; | ||
174 | + }); | ||
175 | + | ||
176 | + const pagination2 = computed(() => { | ||
177 | + return { | ||
178 | + show: true, | ||
179 | + pageSize: 20, | ||
180 | + page: page1.value, | ||
181 | + total: total1.value, | ||
182 | + onChange(cur) { | ||
183 | + getOrderOptLogFunc(orderId.value, 2, cur); | ||
184 | + }, | ||
185 | + }; | ||
186 | + }); | ||
187 | + | ||
188 | + return { | ||
189 | + register, | ||
190 | + schemas, | ||
191 | + achieveList, | ||
192 | + list1, | ||
193 | + list2, | ||
194 | + prefixCls: 'account-center', | ||
195 | + pagination1, | ||
196 | + pagination2, | ||
197 | + activeKey, | ||
198 | + formatToDateTime, | ||
199 | + }; | ||
200 | + }, | ||
201 | + }); | ||
202 | +</script> |
src/views/project/finance/financeProfit/ProductProfit/InnerProduce/data.tsx
@@ -113,14 +113,14 @@ export const COLUMNS = [ | @@ -113,14 +113,14 @@ export const COLUMNS = [ | ||
113 | dataIndex: 'orderCount', | 113 | dataIndex: 'orderCount', |
114 | width: 100, | 114 | width: 100, |
115 | }, | 115 | }, |
116 | - { | ||
117 | - title: '生产科单价¥', | ||
118 | - dataIndex: 'productionDepartmentPrice', | ||
119 | - width: 120, | ||
120 | - customRender: (column) => { | ||
121 | - return column.record?.productionDepartmentPrice?.toFixed(2); | ||
122 | - }, | ||
123 | - }, | 116 | + // { |
117 | + // title: '生产科单价¥', | ||
118 | + // dataIndex: 'productionDepartmentPrice', | ||
119 | + // width: 120, | ||
120 | + // customRender: (column) => { | ||
121 | + // return column.record?.productionDepartmentPrice?.toFixed(2); | ||
122 | + // }, | ||
123 | + // }, | ||
124 | { | 124 | { |
125 | title: '生产科总价¥', | 125 | title: '生产科总价¥', |
126 | dataIndex: 'productionDepartmentTotalPrice', | 126 | dataIndex: 'productionDepartmentTotalPrice', |
@@ -151,7 +151,7 @@ export const COLUMNS = [ | @@ -151,7 +151,7 @@ export const COLUMNS = [ | ||
151 | width: 120, | 151 | width: 120, |
152 | customRender: (column) => { | 152 | customRender: (column) => { |
153 | if (column.record?.predictRatio) { | 153 | if (column.record?.predictRatio) { |
154 | - return column.record?.predictRatio?.toFixed(2) + '%'; | 154 | + return (column.record?.predictRatio * 100).toFixed(2) + '%'; |
155 | } | 155 | } |
156 | return column.record?.predictRatio?.toFixed(2); | 156 | return column.record?.predictRatio?.toFixed(2); |
157 | }, | 157 | }, |
@@ -162,7 +162,7 @@ export const COLUMNS = [ | @@ -162,7 +162,7 @@ export const COLUMNS = [ | ||
162 | width: 190, | 162 | width: 190, |
163 | customRender: (column) => { | 163 | customRender: (column) => { |
164 | if (column.record?.predictAndActualRatio) { | 164 | if (column.record?.predictAndActualRatio) { |
165 | - return column.record?.predictAndActualRatio?.toFixed(2) + '%'; | 165 | + return (column.record?.predictAndActualRatio * 100).toFixed(2) + '%'; |
166 | } | 166 | } |
167 | return column.record?.predictAndActualRatio?.toFixed(2); | 167 | return column.record?.predictAndActualRatio?.toFixed(2); |
168 | }, | 168 | }, |
@@ -181,7 +181,7 @@ export const COLUMNS = [ | @@ -181,7 +181,7 @@ export const COLUMNS = [ | ||
181 | width: 120, | 181 | width: 120, |
182 | customRender: (column) => { | 182 | customRender: (column) => { |
183 | if (column.record?.beforeGrossProfitRate) { | 183 | if (column.record?.beforeGrossProfitRate) { |
184 | - return column.record?.beforeGrossProfitRate?.toFixed(2) + '%'; | 184 | + return (column.record?.beforeGrossProfitRate * 100).toFixed(2) + '%'; |
185 | } | 185 | } |
186 | return column.record?.beforeGrossProfitRate?.toFixed(2); | 186 | return column.record?.beforeGrossProfitRate?.toFixed(2); |
187 | }, | 187 | }, |
@@ -200,7 +200,7 @@ export const COLUMNS = [ | @@ -200,7 +200,7 @@ export const COLUMNS = [ | ||
200 | width: 120, | 200 | width: 120, |
201 | customRender: (column) => { | 201 | customRender: (column) => { |
202 | if (column.record?.grossProfitRate) { | 202 | if (column.record?.grossProfitRate) { |
203 | - return column.record?.grossProfitRate?.toFixed(2) + '%'; | 203 | + return (column.record?.grossProfitRate * 100).toFixed(2) + '%'; |
204 | } | 204 | } |
205 | return column.record?.grossProfitRate?.toFixed(2); | 205 | return column.record?.grossProfitRate?.toFixed(2); |
206 | }, | 206 | }, |
@@ -235,12 +235,27 @@ export const COLUMNS = [ | @@ -235,12 +235,27 @@ export const COLUMNS = [ | ||
235 | width: 150, | 235 | width: 150, |
236 | customRender: (column) => { | 236 | customRender: (column) => { |
237 | if (column.record?.innerProductionProfitRate) { | 237 | if (column.record?.innerProductionProfitRate) { |
238 | - return column.record?.innerProductionProfitRate?.toFixed(2) + '%'; | 238 | + return (column.record?.innerProductionProfitRate * 100).toFixed(2) + '%'; |
239 | } | 239 | } |
240 | return column.record?.innerProductionProfitRate?.toFixed(2); | 240 | return column.record?.innerProductionProfitRate?.toFixed(2); |
241 | }, | 241 | }, |
242 | }, | 242 | }, |
243 | { | 243 | { |
244 | + title: '状态', | ||
245 | + dataIndex: 'status', | ||
246 | + width: 120, | ||
247 | + customRender: (column) => { | ||
248 | + if (column.record?.innerProductionStatus === null || | ||
249 | + column.record?.innerProductionStatus === -1) { | ||
250 | + return '未完成'; | ||
251 | + } else if (column.record?.innerProductionStatus === 0) { | ||
252 | + return '待审核'; | ||
253 | + } else if (column.record?.innerProductionStatus === 1) { | ||
254 | + return '已审核'; | ||
255 | + } | ||
256 | + }, | ||
257 | + }, | ||
258 | + { | ||
244 | title: '文件', | 259 | title: '文件', |
245 | dataIndex: 'fileUrl', | 260 | dataIndex: 'fileUrl', |
246 | width: 120, | 261 | width: 120, |
src/views/project/finance/financeProfit/ProductProfit/InnerProduce/index.vue
1 | <template> | 1 | <template> |
2 | <div> | 2 | <div> |
3 | <BasicTable @register="registerTable" :bordered="true"> | 3 | <BasicTable @register="registerTable" :bordered="true"> |
4 | + <template #headerTop> | ||
5 | + <a-alert type="info" show-icon> | ||
6 | + <template #message> | ||
7 | + <template v-if="checkedKeys.length > 0"> | ||
8 | + <span>已选中{{ checkedKeys.length }}条记录(可跨页)</span> | ||
9 | + <a-button | ||
10 | + :style="{ borderRadius: '5px 5px 5px 5px' }" | ||
11 | + type="link" | ||
12 | + @click="handleClearChoose" | ||
13 | + size="small" | ||
14 | + >清空</a-button | ||
15 | + > | ||
16 | + </template> | ||
17 | + <template v-else> | ||
18 | + <span>未选中任何订单</span> | ||
19 | + </template> | ||
20 | + </template> | ||
21 | + </a-alert> | ||
22 | + </template> | ||
4 | <template #bodyCell="{ column, record }"> | 23 | <template #bodyCell="{ column, record }"> |
5 | <template v-if="column.key === 'picUrl'"> | 24 | <template v-if="column.key === 'picUrl'"> |
6 | <img :z-index="100000" :width="50" :height="50" :src="record?.picUrl" /> | 25 | <img :z-index="100000" :width="50" :height="50" :src="record?.picUrl" /> |
7 | </template> | 26 | </template> |
8 | - <!-- <template v-if="column.key === 'action'"> | ||
9 | - <TableAction :actions="createActions(record)" /> | ||
10 | - </template> --> | 27 | + <template v-if="column.key === 'action'"> |
28 | + <TableAction | ||
29 | + :actions="createActions(record)" | ||
30 | + :dropDownActions="createDropActions(record)" | ||
31 | + /> | ||
32 | + </template> | ||
11 | <!-- <template v-if="column.key === 'relationValue'"> | 33 | <!-- <template v-if="column.key === 'relationValue'"> |
12 | <a-input | 34 | <a-input |
13 | v-if="record.settingValue === 'A01'" | 35 | v-if="record.settingValue === 'A01'" |
@@ -19,6 +41,15 @@ | @@ -19,6 +41,15 @@ | ||
19 | </span> | 41 | </span> |
20 | </template> --> | 42 | </template> --> |
21 | </template> | 43 | </template> |
44 | + <template #toolbar> | ||
45 | + <a-button | ||
46 | + type="primary" | ||
47 | + @click="handleExport" | ||
48 | + v-if="role == ROLE.ADMIN || role == ROLE.FINANCE" | ||
49 | + :style="{ borderRadius: '5px 5px 5px 5px' }" | ||
50 | + >导出</a-button | ||
51 | + > | ||
52 | + </template> | ||
22 | </BasicTable> | 53 | </BasicTable> |
23 | <!-- <BasicModal | 54 | <!-- <BasicModal |
24 | title="拒绝原因" | 55 | title="拒绝原因" |
@@ -32,25 +63,44 @@ | @@ -32,25 +63,44 @@ | ||
32 | <a-textarea :rows="6" placeholder="请输入拒绝原因" v-model:value="message" /> | 63 | <a-textarea :rows="6" placeholder="请输入拒绝原因" v-model:value="message" /> |
33 | </div> | 64 | </div> |
34 | </BasicModal> --> | 65 | </BasicModal> --> |
66 | + <CheckDetail @register="checkModalRegister" :onGoFormDetail="handleGoFormDetail" /> | ||
35 | <FinanceEdit @register="registerFinanceEdit" @success="handleSuccess" /> | 67 | <FinanceEdit @register="registerFinanceEdit" @success="handleSuccess" /> |
68 | + <HistoryDetail @register="registerHistoryDetail" /> | ||
36 | </div> | 69 | </div> |
37 | </template> | 70 | </template> |
38 | <script setup lang="ts"> | 71 | <script setup lang="ts"> |
39 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; | 72 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; |
40 | - import { getInnerProduceProfit } from '@/api/project/invoice'; | 73 | + import { getInnerProduceProfit, setInnerProfitSetStatus } from '@/api/project/invoice'; |
41 | import { searchFormSchema, COLUMNS } from './data'; | 74 | import { searchFormSchema, COLUMNS } from './data'; |
42 | import { BasicModal, useModal } from '/@/components/Modal'; | 75 | import { BasicModal, useModal } from '/@/components/Modal'; |
43 | import { useMessage } from '/@/hooks/web/useMessage'; | 76 | import { useMessage } from '/@/hooks/web/useMessage'; |
44 | - import { onMounted, ref } from 'vue'; | 77 | + import { onMounted, ref, computed } from 'vue'; |
78 | + import axios from 'axios'; | ||
45 | import { useDrawer } from '/@/components/Drawer'; | 79 | import { useDrawer } from '/@/components/Drawer'; |
46 | import FinanceEdit from './FinanceEdit.vue'; | 80 | import FinanceEdit from './FinanceEdit.vue'; |
81 | + import CheckDetail from './CheckDetail.vue'; | ||
82 | + import HistoryDetail from './HistoryDetail.vue'; | ||
47 | import { useOrderStoreWithOut } from '/@/store/modules/order'; | 83 | import { useOrderStoreWithOut } from '/@/store/modules/order'; |
84 | + import { useUserStoreWithOut } from '/@/store/modules/user'; | ||
85 | + import { RoleEnum } from '/@/enums/roleEnum'; | ||
86 | + import { ROLE } from '../../../type.d'; | ||
48 | 87 | ||
49 | const { createMessage } = useMessage(); | 88 | const { createMessage } = useMessage(); |
50 | const { error } = createMessage; | 89 | const { error } = createMessage; |
51 | const message = ref(); | 90 | const message = ref(); |
91 | + const checkedKeys = ref<string[]>([]); | ||
92 | + const invoiceIdKeys = ref<string[]>([]); | ||
93 | + const checkIdKeys = ref<string[]>([]); | ||
94 | + const detailProjectNoKeys = ref<string[]>([]); | ||
52 | const orderStore = useOrderStoreWithOut(); | 95 | const orderStore = useOrderStoreWithOut(); |
96 | + const [checkModalRegister, { openDrawer: openCheckDetailDrawer }] = useDrawer(); | ||
53 | const [registerFinanceEdit, { openDrawer: openFinanceEdit }] = useDrawer(); | 97 | const [registerFinanceEdit, { openDrawer: openFinanceEdit }] = useDrawer(); |
98 | + const [registerHistoryDetail, { openDrawer: openHistoryDetail }] = useDrawer(); | ||
99 | + const userStore = useUserStoreWithOut(); | ||
100 | + const user = userStore.getUserInfo; | ||
101 | + const role = computed(() => { | ||
102 | + return user?.roleSmallVO?.code; | ||
103 | + }); | ||
54 | const handleOk = (record) => { | 104 | const handleOk = (record) => { |
55 | // 修改父组件的状态 | 105 | // 修改父组件的状态 |
56 | closeModal(); | 106 | closeModal(); |
@@ -60,12 +110,18 @@ | @@ -60,12 +110,18 @@ | ||
60 | message.value = ''; | 110 | message.value = ''; |
61 | } | 111 | } |
62 | }; | 112 | }; |
63 | - const [registerTable, { reload }] = useTable({ | 113 | + const [registerTable, { reload, setSelectedRowKeys }] = useTable({ |
64 | api: getInnerProduceProfit, | 114 | api: getInnerProduceProfit, |
65 | bordered: true, | 115 | bordered: true, |
66 | columns: COLUMNS, | 116 | columns: COLUMNS, |
67 | clickToRowSelect: false, | 117 | clickToRowSelect: false, |
68 | - rowKey: 'id', | 118 | + rowKey: (record) => record.projectNoPrefix || record.id || record.serialNumber, |
119 | + rowSelection: { | ||
120 | + type: 'checkbox', | ||
121 | + selectedRowKeys: checkedKeys as any, | ||
122 | + onSelect: onSelect, | ||
123 | + onSelectAll: onSelectAll, | ||
124 | + }, | ||
69 | formConfig: { | 125 | formConfig: { |
70 | labelWidth: 120, | 126 | labelWidth: 120, |
71 | schemas: searchFormSchema, | 127 | schemas: searchFormSchema, |
@@ -77,50 +133,79 @@ | @@ -77,50 +133,79 @@ | ||
77 | tableSetting: { | 133 | tableSetting: { |
78 | setting: false, | 134 | setting: false, |
79 | }, | 135 | }, |
136 | + actionColumn: { | ||
137 | + width: 260, | ||
138 | + title: 'Action', | ||
139 | + dataIndex: 'action', | ||
140 | + }, | ||
80 | }); | 141 | }); |
81 | 142 | ||
82 | - // function createActions(record: any): any[] { | ||
83 | - // if (!record.editable) { | ||
84 | - // return [ | ||
85 | - // // { | ||
86 | - // // label: '财务编辑', | ||
87 | - // // onClick: handleFinanceEdit.bind(null, record), | ||
88 | - // // }, | ||
89 | - // // { | ||
90 | - // // label: '编辑', | ||
91 | - // // onClick: handleEdit.bind(null, record), | ||
92 | - // // }, | ||
93 | - // // { | ||
94 | - // // label: '删除', | ||
95 | - // // popConfirm: { | ||
96 | - // // title: '确认删除?', | ||
97 | - // // confirm: handleDelete.bind(null, record), | ||
98 | - // // }, | ||
99 | - // // }, | ||
100 | - // // { | ||
101 | - // // label: '申请权限', | ||
102 | - // // // popConfirm: { | ||
103 | - // // // title: '确认申请?', | ||
104 | - // // // confirm: handleFalse.bind(null, record), | ||
105 | - // // // }, | ||
106 | - // // onClick: handleFalse.bind(null, record), | ||
107 | - // // }, | ||
108 | - // ]; | ||
109 | - // } | ||
110 | - // return [ | ||
111 | - // { | ||
112 | - // label: '保存', | ||
113 | - // onClick: handleSave.bind(null, record), | ||
114 | - // }, | ||
115 | - // { | ||
116 | - // label: '取消', | ||
117 | - // popConfirm: { | ||
118 | - // title: '是否取消编辑', | ||
119 | - // confirm: handleCancel.bind(null, record), | ||
120 | - // }, | ||
121 | - // }, | ||
122 | - // ]; | ||
123 | - // } | 143 | + function createActions(record: any): any[] { |
144 | + if (!record.editable) { | ||
145 | + return [ | ||
146 | + { | ||
147 | + label: '财务编辑', | ||
148 | + onClick: handleFinanceEdit.bind(null, record), | ||
149 | + }, | ||
150 | + // { | ||
151 | + // label: '编辑', | ||
152 | + // onClick: handleEdit.bind(null, record), | ||
153 | + // }, | ||
154 | + // { | ||
155 | + // label: '删除', | ||
156 | + // popConfirm: { | ||
157 | + // title: '确认删除?', | ||
158 | + // confirm: handleDelete.bind(null, record), | ||
159 | + // }, | ||
160 | + // }, | ||
161 | + { | ||
162 | + label: '申请权限', | ||
163 | + // popConfirm: { | ||
164 | + // title: '确认申请?', | ||
165 | + // confirm: handleFalse.bind(null, record), | ||
166 | + // }, | ||
167 | + onClick: handleFalse.bind(null, record), | ||
168 | + }, | ||
169 | + { | ||
170 | + label: '审核通过', | ||
171 | + popConfirm: { | ||
172 | + title: '确认审核?', | ||
173 | + confirm: () => { | ||
174 | + if (record.innerProductionStatus === 0 && role.value === ROLE.ADMIN) { | ||
175 | + handleStatus(record, true); | ||
176 | + } | ||
177 | + return; | ||
178 | + }, | ||
179 | + }, | ||
180 | + }, | ||
181 | + ]; | ||
182 | + } | ||
183 | + return [ | ||
184 | + { | ||
185 | + label: '保存', | ||
186 | + onClick: handleSave.bind(null, record), | ||
187 | + }, | ||
188 | + { | ||
189 | + label: '取消', | ||
190 | + popConfirm: { | ||
191 | + title: '是否取消编辑', | ||
192 | + confirm: handleCancel.bind(null, record), | ||
193 | + }, | ||
194 | + }, | ||
195 | + ]; | ||
196 | + } | ||
197 | + | ||
198 | + function createDropActions(record: any) { | ||
199 | + if (!record.editable) { | ||
200 | + const actions = [ | ||
201 | + { | ||
202 | + label: '历史记录', | ||
203 | + onClick: handleHistoryDetail.bind(null, record), | ||
204 | + }, | ||
205 | + ]; | ||
206 | + return actions; | ||
207 | + } | ||
208 | + } | ||
124 | 209 | ||
125 | onMounted(async () => { | 210 | onMounted(async () => { |
126 | await orderStore.getDict(); | 211 | await orderStore.getDict(); |
@@ -132,10 +217,11 @@ | @@ -132,10 +217,11 @@ | ||
132 | }); | 217 | }); |
133 | } | 218 | } |
134 | 219 | ||
135 | - // async function handleFalse(record: any) { | ||
136 | - // console.log(record); | ||
137 | - // // openModal(true, { record }); | ||
138 | - // } | 220 | + function handleFalse(record, e) { |
221 | + openCheckDetailDrawer(true, record); | ||
222 | + e?.stopPropagation(); | ||
223 | + return false; | ||
224 | + } | ||
139 | 225 | ||
140 | async function handleSave(record) { | 226 | async function handleSave(record) { |
141 | await saveConfig({ id: record.id, relationValue: record.relationValue }); | 227 | await saveConfig({ id: record.id, relationValue: record.relationValue }); |
@@ -154,8 +240,170 @@ | @@ -154,8 +240,170 @@ | ||
154 | record.onEdit?.(false, false); | 240 | record.onEdit?.(false, false); |
155 | } | 241 | } |
156 | 242 | ||
157 | - async function handleDelete(record) { | ||
158 | - await deleteConfig({ ids: [record.id] }); | 243 | + // async function handleDelete(record) { |
244 | + // await deleteConfig({ ids: [record.id] }); | ||
245 | + // reload(); | ||
246 | + // } | ||
247 | + function handleSuccess() { | ||
248 | + setTimeout(() => { | ||
249 | + reload(); | ||
250 | + }, 50); | ||
251 | + } | ||
252 | + | ||
253 | + async function handleStatus(record, status) { | ||
254 | + try { | ||
255 | + await setInnerProfitSetStatus({ | ||
256 | + projectNo: record.projectNoPrefix, | ||
257 | + customerCode: record.customerCode | ||
258 | + }); | ||
259 | + reload(); | ||
260 | + } catch (error) { | ||
261 | + console.error(error); | ||
262 | + } | ||
263 | + } | ||
264 | + | ||
265 | + function handleHistoryDetail(record) { | ||
266 | + openHistoryDetail(true, { | ||
267 | + data: record, | ||
268 | + }); | ||
269 | + } | ||
270 | + | ||
271 | + function handleGoFormDetail() { | ||
272 | + // Add your logic for form detail navigation | ||
273 | + } | ||
274 | + | ||
275 | + function handleClearChoose() { | ||
276 | + checkedKeys.value = []; | ||
277 | + detailProjectNoKeys.value = []; | ||
278 | + invoiceIdKeys.value = []; | ||
279 | + checkIdKeys.value = []; | ||
280 | + } | ||
281 | + async function onSelect(record, selected: boolean) { | ||
282 | + const rowKey = record.projectNoPrefix || record.id || record.serialNumber; | ||
283 | + if (selected) { | ||
284 | + checkedKeys.value = [...checkedKeys.value, rowKey]; | ||
285 | + | ||
286 | + // 使用projectNoPrefix作为单个值,添加到detailProjectNoKeys中 | ||
287 | + if (record.projectNoPrefix !== undefined) { | ||
288 | + // 如果是单个值,检查是否已存在,然后添加到数组 | ||
289 | + if (!detailProjectNoKeys.value.includes(record.projectNoPrefix)) { | ||
290 | + detailProjectNoKeys.value.push(record.projectNoPrefix); | ||
291 | + } | ||
292 | + } | ||
293 | + | ||
294 | + if (record.invoiceId !== undefined) { | ||
295 | + invoiceIdKeys.value = [...invoiceIdKeys.value, record.invoiceId]; | ||
296 | + } | ||
297 | + | ||
298 | + if (record.checkId !== undefined) { | ||
299 | + checkIdKeys.value = [...checkIdKeys.value, record.checkId]; | ||
300 | + } | ||
301 | + } else { | ||
302 | + checkedKeys.value = checkedKeys.value.filter((key) => key !== rowKey); | ||
303 | + | ||
304 | + // 从detailProjectNoKeys中移除projectNoPrefix | ||
305 | + if (record.projectNoPrefix !== undefined) { | ||
306 | + // 直接移除单个值 | ||
307 | + detailProjectNoKeys.value = detailProjectNoKeys.value.filter( | ||
308 | + (projectNo) => projectNo !== record.projectNoPrefix | ||
309 | + ); | ||
310 | + } | ||
311 | + | ||
312 | + if (record.invoiceId !== undefined) { | ||
313 | + invoiceIdKeys.value = invoiceIdKeys.value.filter( | ||
314 | + (invoiceId) => invoiceId !== record.invoiceId, | ||
315 | + ); | ||
316 | + } | ||
317 | + | ||
318 | + if (record.checkId !== undefined) { | ||
319 | + checkIdKeys.value = checkIdKeys.value.filter((checkId) => checkId !== record.checkId); | ||
320 | + } | ||
321 | + } | ||
322 | + setSelectedRowKeys(checkedKeys.value as any); | ||
323 | + } | ||
324 | + | ||
325 | + function onSelectAll(selected: boolean, selectedRows: any[]) { | ||
326 | + if (selected) { | ||
327 | + // 先清空之前的选择,避免重复添加 | ||
328 | + checkedKeys.value = []; | ||
329 | + detailProjectNoKeys.value = []; | ||
330 | + invoiceIdKeys.value = []; | ||
331 | + checkIdKeys.value = []; | ||
332 | + | ||
333 | + // 重新添加所有选中的行 | ||
334 | + selectedRows.forEach((row) => { | ||
335 | + const rowKey = row.projectNoPrefix || row.id || row.serialNumber; | ||
336 | + checkedKeys.value.push(rowKey); | ||
337 | + | ||
338 | + // 使用projectNoPrefix作为单个值,添加到detailProjectNoKeys中 | ||
339 | + if (row.projectNoPrefix !== undefined) { | ||
340 | + // 由于已经清空了数组,不需要检查是否存在 | ||
341 | + detailProjectNoKeys.value.push(row.projectNoPrefix); | ||
342 | + } | ||
343 | + | ||
344 | + if (row.invoiceId !== undefined) { | ||
345 | + invoiceIdKeys.value.push(row.invoiceId); | ||
346 | + } | ||
347 | + | ||
348 | + if (row.checkId !== undefined) { | ||
349 | + checkIdKeys.value.push(row.checkId); | ||
350 | + } | ||
351 | + }); | ||
352 | + } else { | ||
353 | + // 取消全选时,清空所有选择 | ||
354 | + checkedKeys.value = []; | ||
355 | + detailProjectNoKeys.value = []; | ||
356 | + invoiceIdKeys.value = []; | ||
357 | + checkIdKeys.value = []; | ||
358 | + } | ||
359 | + setSelectedRowKeys(checkedKeys.value as any); | ||
360 | + } | ||
361 | + function handleExport() { | ||
362 | + if (checkedKeys.value.length <= 0) { | ||
363 | + createMessage.warn('请选择数据!'); | ||
364 | + return; | ||
365 | + } | ||
366 | + const token = userStore.getToken; | ||
367 | + axios | ||
368 | + .post( | ||
369 | + '/basic-api/project/innerProfitInfo/exportExcel', | ||
370 | + { detailProjectNo: detailProjectNoKeys.value }, | ||
371 | + { | ||
372 | + headers: { | ||
373 | + Authorization: `${token}`, // 去掉引号 | ||
374 | + }, | ||
375 | + responseType: 'blob', // 设置响应类型为 'blob' | ||
376 | + }, | ||
377 | + ) | ||
378 | + .then((response) => { | ||
379 | + // 创建一个 Blob 对象来保存二进制数据 | ||
380 | + const blob = new Blob([response.data], { type: 'application/zip' }); | ||
381 | + const getFormattedDate = (): string => { | ||
382 | + const date = new Date(); | ||
383 | + | ||
384 | + const year = date.getFullYear(); | ||
385 | + const month = String(date.getMonth() + 1).padStart(2, '0'); | ||
386 | + const day = String(date.getDate()).padStart(2, '0'); | ||
387 | + | ||
388 | + const hours = String(date.getHours()).padStart(2, '0'); | ||
389 | + const minutes = String(date.getMinutes()).padStart(2, '0'); | ||
390 | + const seconds = String(date.getSeconds()).padStart(2, '0'); | ||
391 | + | ||
392 | + return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; | ||
393 | + }; | ||
394 | + const date = getFormattedDate(); | ||
395 | + // 创建一个链接元素用于下载 | ||
396 | + const link = document.createElement('a'); | ||
397 | + link.href = window.URL.createObjectURL(blob); | ||
398 | + link.download = `内产生产净利润分析表${date}.xlsx`; // 你可以为文件命名 | ||
399 | + document.body.appendChild(link); | ||
400 | + link.click(); // 自动点击链接,触发下载 | ||
401 | + document.body.removeChild(link); // 下载完成后移除链接 | ||
402 | + }) | ||
403 | + .catch((error) => { | ||
404 | + console.error(error); | ||
405 | + }); | ||
406 | + handleClearChoose(); | ||
159 | reload(); | 407 | reload(); |
160 | } | 408 | } |
161 | </script> | 409 | </script> |
src/views/project/finance/financeProfit/ProductProfit/InnerProduce/tableData.tsx
@@ -21,74 +21,18 @@ const orderStore = useOrderStoreWithOut(); | @@ -21,74 +21,18 @@ const orderStore = useOrderStoreWithOut(); | ||
21 | // 基本信息 | 21 | // 基本信息 |
22 | export const FIELDS_BASE_INFO = [ | 22 | export const FIELDS_BASE_INFO = [ |
23 | { | 23 | { |
24 | - field: 'customerCode', | 24 | + field: 'projectInnerProfitInfoStartTime', |
25 | component: 'Select', | 25 | component: 'Select', |
26 | labelWidth: 150, | 26 | labelWidth: 150, |
27 | - label: '客户编码', | 27 | + label: '项目开始时间', |
28 | rules: [{ required: true }], | 28 | rules: [{ required: true }], |
29 | }, | 29 | }, |
30 | { | 30 | { |
31 | - field: 'projectNo', | ||
32 | - component: 'Input', | ||
33 | - labelWidth: 150, | ||
34 | - label: '项目号', | ||
35 | - rules: [{ required: true }], | ||
36 | - }, | ||
37 | - { | ||
38 | - field: 'productionDepartment', | 31 | + field: 'projectInnerProfitInfoEndTime', |
39 | component: 'Select', | 32 | component: 'Select', |
40 | - // componentProps: { | ||
41 | - // options: productionDepartmentOptions, | ||
42 | - // }, | ||
43 | labelWidth: 150, | 33 | labelWidth: 150, |
44 | - label: '生产科', | 34 | + label: '项目结束时间', |
45 | rules: [{ required: true }], | 35 | rules: [{ required: true }], |
46 | }, | 36 | }, |
47 | - | ||
48 | - { | ||
49 | - field: 'innerNo', | ||
50 | - component: 'Input', | ||
51 | - labelWidth: 150, | ||
52 | - label: '内部编号', | ||
53 | - rules: [ | ||
54 | - { required: true }, | ||
55 | - { | ||
56 | - validator: async (rule, value) => { | ||
57 | - if (value.includes(' ')) { | ||
58 | - return Promise.reject(); | ||
59 | - } | ||
60 | - return Promise.resolve(); | ||
61 | - }, | ||
62 | - message: '内容存在空格,请检查', | ||
63 | - trigger: ['change', 'blur'], | ||
64 | - }, | ||
65 | - ], | ||
66 | - }, | ||
67 | - { | ||
68 | - field: 'customerPo', | ||
69 | - component: 'Input', | ||
70 | - labelWidth: 150, | ||
71 | - label: '客户po号', | ||
72 | - rules: [{ required: true }], | ||
73 | - }, | ||
74 | - { | ||
75 | - field: 'customerStyle', | ||
76 | - component: 'Input', | ||
77 | - labelWidth: 150, | ||
78 | - label: '客户STYLE', | ||
79 | - rules: [ | ||
80 | - { required: true }, | ||
81 | - { | ||
82 | - validator: async (rule, value) => { | ||
83 | - if (value.includes(' ')) { | ||
84 | - return Promise.reject(); | ||
85 | - } | ||
86 | - return Promise.resolve(); | ||
87 | - }, | ||
88 | - message: '内容存在空格,请检查', | ||
89 | - trigger: ['change', 'blur'], | ||
90 | - }, | ||
91 | - ], | ||
92 | - }, | ||
93 | ]; | 37 | ]; |
94 | 38 |
src/views/project/finance/financeProfit/ServiceProfit/PackageProfit/ApproveReason.vue
@@ -32,7 +32,7 @@ | @@ -32,7 +32,7 @@ | ||
32 | orderId: baseFieldValues.value.orderId, | 32 | orderId: baseFieldValues.value.orderId, |
33 | packetActualRmbTotalPrice: baseFieldValues.value.packetActualRmbTotalPrice, | 33 | packetActualRmbTotalPrice: baseFieldValues.value.packetActualRmbTotalPrice, |
34 | applyRemark: baseFieldValues.value.applyRemark, | 34 | applyRemark: baseFieldValues.value.applyRemark, |
35 | - type: 60, | 35 | + type: 80, |
36 | }); | 36 | }); |
37 | emit('success'); | 37 | emit('success'); |
38 | setTimeout(() => { | 38 | setTimeout(() => { |
src/views/project/finance/financeProfit/ServiceProfit/PackageProfit/FinanceEdit.vue
@@ -122,7 +122,7 @@ | @@ -122,7 +122,7 @@ | ||
122 | const [register, { setDrawerProps, closeDrawer }] = useDrawerInner((data) => { | 122 | const [register, { setDrawerProps, closeDrawer }] = useDrawerInner((data) => { |
123 | // 方式1 | 123 | // 方式1 |
124 | if (data.data.lockFields) { | 124 | if (data.data.lockFields) { |
125 | - status.value = data.data.lockFields?.packetActualRmbPrice; | 125 | + status.value = data.data.lockFields?.packetActualRmbTotalPrice; |
126 | } | 126 | } |
127 | id.value = data.data.orderId; | 127 | id.value = data.data.orderId; |
128 | input1.value = data.data?.packetActualRmbTotalPrice; | 128 | input1.value = data.data?.packetActualRmbTotalPrice; |
src/views/project/finance/financeProfit/ServiceProfit/PackageProfit/HistoryDetail.vue
0 → 100644
1 | +<template> | ||
2 | + <BasicDrawer | ||
3 | + @register="register" | ||
4 | + v-bind="$attrs" | ||
5 | + title="操作记录" | ||
6 | + width="60%" | ||
7 | + :isDetail="true" | ||
8 | + :showDetailBack="false" | ||
9 | + okText="保存" | ||
10 | + :destroyOnClose="true" | ||
11 | + > | ||
12 | + <Tabs v-model:activeKey="activeKey" className="my-0"> | ||
13 | + <TabPanel :key="1" tab="操作记录" className="w-full"> | ||
14 | + <a-list :pagination="pagination1" className="w-full"> | ||
15 | + <template v-for="item in list1" :key="item.id"> | ||
16 | + <a-list-item class="list"> | ||
17 | + <a-list-item-meta> | ||
18 | + <template #avatar> </template> | ||
19 | + <template #title> | ||
20 | + <span>{{ item.userName }}</span> | ||
21 | + </template> | ||
22 | + <template #description> | ||
23 | + <div class="description"> | ||
24 | + {{ item.optType }} | ||
25 | + </div> | ||
26 | + <div class="info"> | ||
27 | + <div><span>操作时间:</span>{{ formatToDateTime(item.createTime) }}</div> | ||
28 | + </div> | ||
29 | + </template> | ||
30 | + </a-list-item-meta> | ||
31 | + </a-list-item> | ||
32 | + </template> | ||
33 | + </a-list> | ||
34 | + </TabPanel> | ||
35 | + <TabPanel :key="2" tab="审批记录" className="w-full"> | ||
36 | + <a-list :pagination="pagination2" className="w-full"> | ||
37 | + <template v-for="item in list2" :key="item.id"> | ||
38 | + <a-list-item class="list"> | ||
39 | + <a-list-item-meta> | ||
40 | + <template #avatar> </template> | ||
41 | + <template #title> | ||
42 | + <span>{{ item.userName }}</span> | ||
43 | + </template> | ||
44 | + <template #description> | ||
45 | + <div class="description"> | ||
46 | + {{ item.optType }} | ||
47 | + </div> | ||
48 | + <div class="info"> | ||
49 | + <div><span>操作时间:</span>{{ formatToDateTime(item.createTime) }}</div> | ||
50 | + </div> | ||
51 | + </template> | ||
52 | + </a-list-item-meta> | ||
53 | + </a-list-item> | ||
54 | + </template> | ||
55 | + </a-list> | ||
56 | + </TabPanel> | ||
57 | + </Tabs> | ||
58 | + | ||
59 | + <!-- <template #titleToolbar> <a-button type="primary"> 申请编辑权限 </a-button></template> --> | ||
60 | + <template #appendFooter> | ||
61 | + <!-- <a-button type="primary" @click="onGoCheckDetail"> 申请权限</a-button> --> | ||
62 | + </template> | ||
63 | + </BasicDrawer> | ||
64 | +</template> | ||
65 | +<script lang="ts"> | ||
66 | + import { defineComponent, ref, computed } from 'vue'; | ||
67 | + import { Tabs, Progress, Row, Col, List } from 'ant-design-vue'; | ||
68 | + import { FormSchema, useForm } from '/@/components/Form/index'; | ||
69 | + | ||
70 | + import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; | ||
71 | + import { getOrderCostDetailedOptLog } from '/@/api/project/invoice'; | ||
72 | + import { formatToDateTime } from '/@/utils/dateUtil'; | ||
73 | + | ||
74 | + const TabPanel = Tabs.TabPane; | ||
75 | + | ||
76 | + const schemas: FormSchema[] = [ | ||
77 | + { | ||
78 | + field: '订单号', | ||
79 | + component: 'Input', | ||
80 | + label: '字段1', | ||
81 | + componentProps: { | ||
82 | + readonly: true, | ||
83 | + disabled: true, | ||
84 | + }, | ||
85 | + colProps: { | ||
86 | + span: 12, | ||
87 | + }, | ||
88 | + defaultValue: '111', | ||
89 | + }, | ||
90 | + { | ||
91 | + field: 'field2', | ||
92 | + component: 'Input', | ||
93 | + label: '字段2', | ||
94 | + colProps: { | ||
95 | + span: 12, | ||
96 | + }, | ||
97 | + }, | ||
98 | + ]; | ||
99 | + const achieveList = [ | ||
100 | + { | ||
101 | + key: '1', | ||
102 | + name: '操作记录', | ||
103 | + }, | ||
104 | + { | ||
105 | + key: '2', | ||
106 | + name: '审批记录', | ||
107 | + }, | ||
108 | + ]; | ||
109 | + export default defineComponent({ | ||
110 | + components: { | ||
111 | + BasicDrawer, | ||
112 | + Tabs, | ||
113 | + TabPanel, | ||
114 | + [List.name]: List, | ||
115 | + [List.Item.name]: List.Item, | ||
116 | + AListItemMeta: List.Item.Meta, | ||
117 | + }, | ||
118 | + props: { | ||
119 | + onGoCheckDetail: { | ||
120 | + type: Function, | ||
121 | + }, | ||
122 | + }, | ||
123 | + setup() { | ||
124 | + const list1 = ref([]); | ||
125 | + const total1 = ref(0); | ||
126 | + const page1 = ref(1); | ||
127 | + | ||
128 | + const list2 = ref([]); | ||
129 | + const total2 = ref(0); | ||
130 | + const page2 = ref(1); | ||
131 | + const orderId = ref(''); | ||
132 | + const activeKey = ref(1); | ||
133 | + | ||
134 | + const getOrderOptLogFunc = async (data, index, page) => { | ||
135 | + console.log('%c [ data ]-135', 'font-size:13px; background:pink; color:#bf2c9f;', data); | ||
136 | + if (index === 1) { | ||
137 | + const res = await getOrderCostDetailedOptLog({ | ||
138 | + orderId: data, | ||
139 | + type: [20], | ||
140 | + page: page, | ||
141 | + pageSize: 20 | ||
142 | + }); | ||
143 | + list1.value = res.items; | ||
144 | + total1.value = res.total; | ||
145 | + page1.value = page; | ||
146 | + } else { | ||
147 | + const res = await getOrderCostDetailedOptLog({ | ||
148 | + orderId: data, | ||
149 | + type: [80,81], | ||
150 | + page: page, | ||
151 | + pageSize: 20 | ||
152 | + }); | ||
153 | + list2.value = res.items; | ||
154 | + total2.value = res.total; | ||
155 | + page2.value = page; | ||
156 | + } | ||
157 | + }; | ||
158 | + const [register] = useDrawerInner((data) => { | ||
159 | + orderId.value = data.data.orderId; | ||
160 | + getOrderOptLogFunc(orderId.value, 1, 1); | ||
161 | + getOrderOptLogFunc(orderId.value, 2, 1); | ||
162 | + }); | ||
163 | + | ||
164 | + const pagination1 = computed(() => { | ||
165 | + return { | ||
166 | + show: true, | ||
167 | + pageSize: 20, | ||
168 | + page: page1.value, | ||
169 | + total: total1.value, | ||
170 | + onChange(cur) { | ||
171 | + getOrderOptLogFunc(orderId.value, 1, cur); | ||
172 | + }, | ||
173 | + }; | ||
174 | + }); | ||
175 | + | ||
176 | + const pagination2 = computed(() => { | ||
177 | + return { | ||
178 | + show: true, | ||
179 | + pageSize: 20, | ||
180 | + page: page1.value, | ||
181 | + total: total1.value, | ||
182 | + onChange(cur) { | ||
183 | + getOrderOptLogFunc(orderId.value, 2, cur); | ||
184 | + }, | ||
185 | + }; | ||
186 | + }); | ||
187 | + | ||
188 | + return { | ||
189 | + register, | ||
190 | + schemas, | ||
191 | + achieveList, | ||
192 | + list1, | ||
193 | + list2, | ||
194 | + prefixCls: 'account-center', | ||
195 | + pagination1, | ||
196 | + pagination2, | ||
197 | + activeKey, | ||
198 | + formatToDateTime, | ||
199 | + }; | ||
200 | + }, | ||
201 | + }); | ||
202 | +</script> |
src/views/project/finance/financeProfit/ServiceProfit/PackageProfit/data.tsx
@@ -182,9 +182,23 @@ export const COLUMNS = [ | @@ -182,9 +182,23 @@ export const COLUMNS = [ | ||
182 | width: 140, | 182 | width: 140, |
183 | customRender: (column) => { | 183 | customRender: (column) => { |
184 | if (column.record?.packetProfitRate) { | 184 | if (column.record?.packetProfitRate) { |
185 | - return column.record?.packetProfitRate?.toFixed(2) + '%'; | 185 | + return (column.record?.packetProfitRate * 100).toFixed(2) + '%'; |
186 | } | 186 | } |
187 | return column.record?.packetProfitRate?.toFixed(2); | 187 | return column.record?.packetProfitRate?.toFixed(2); |
188 | }, | 188 | }, |
189 | }, | 189 | }, |
190 | + { | ||
191 | + title: '状态', | ||
192 | + dataIndex: 'status', | ||
193 | + width: 120, | ||
194 | + customRender: (column) => { | ||
195 | + if (column.record?.packStatus === null || column.record?.packStatus === -1) { | ||
196 | + return '未完成'; | ||
197 | + } else if (column.record?.packStatus === 0) { | ||
198 | + return '待审核'; | ||
199 | + } else if (column.record?.packStatus === 1) { | ||
200 | + return '已审核'; | ||
201 | + } | ||
202 | + }, | ||
203 | + }, | ||
190 | ]; | 204 | ]; |
191 | \ No newline at end of file | 205 | \ No newline at end of file |
src/views/project/finance/financeProfit/ServiceProfit/PackageProfit/index.vue
1 | <template> | 1 | <template> |
2 | <div> | 2 | <div> |
3 | <BasicTable @register="registerTable" :bordered="true"> | 3 | <BasicTable @register="registerTable" :bordered="true"> |
4 | + <template #headerTop> | ||
5 | + <a-alert type="info" show-icon> | ||
6 | + <template #message> | ||
7 | + <template v-if="checkedKeys.length > 0"> | ||
8 | + <span>已选中{{ checkedKeys.length }}条记录(可跨页)</span> | ||
9 | + <a-button | ||
10 | + :style="{ borderRadius: '5px 5px 5px 5px' }" | ||
11 | + type="link" | ||
12 | + @click="handleClearChoose" | ||
13 | + size="small" | ||
14 | + >清空</a-button | ||
15 | + > | ||
16 | + </template> | ||
17 | + <template v-else> | ||
18 | + <span>未选中任何订单</span> | ||
19 | + </template> | ||
20 | + </template> | ||
21 | + </a-alert> | ||
22 | + </template> | ||
4 | <template #bodyCell="{ column, record }"> | 23 | <template #bodyCell="{ column, record }"> |
5 | <template v-if="column.key === 'picUrl'"> | 24 | <template v-if="column.key === 'picUrl'"> |
6 | <img :z-index="100000" :width="50" :height="50" :src="record?.picUrl" /> | 25 | <img :z-index="100000" :width="50" :height="50" :src="record?.picUrl" /> |
7 | </template> | 26 | </template> |
8 | <template v-if="column.key === 'action'"> | 27 | <template v-if="column.key === 'action'"> |
9 | - <TableAction :actions="createActions(record)" /> | 28 | + <TableAction |
29 | + :actions="createActions(record)" | ||
30 | + :dropDownActions="createDropActions(record)" | ||
31 | + /> | ||
10 | </template> | 32 | </template> |
11 | <!-- <template v-if="column.key === 'relationValue'"> | 33 | <!-- <template v-if="column.key === 'relationValue'"> |
12 | <a-input | 34 | <a-input |
@@ -19,6 +41,15 @@ | @@ -19,6 +41,15 @@ | ||
19 | </span> | 41 | </span> |
20 | </template> --> | 42 | </template> --> |
21 | </template> | 43 | </template> |
44 | + <template #toolbar> | ||
45 | + <a-button | ||
46 | + type="primary" | ||
47 | + @click="handleExport" | ||
48 | + v-if="role == ROLE.ADMIN || role == ROLE.FINANCE" | ||
49 | + :style="{ borderRadius: '5px 5px 5px 5px' }" | ||
50 | + >导出</a-button | ||
51 | + > | ||
52 | + </template> | ||
22 | </BasicTable> | 53 | </BasicTable> |
23 | <!-- <BasicModal | 54 | <!-- <BasicModal |
24 | title="拒绝原因" | 55 | title="拒绝原因" |
@@ -34,27 +65,47 @@ | @@ -34,27 +65,47 @@ | ||
34 | </BasicModal> --> | 65 | </BasicModal> --> |
35 | <CheckDetail @register="checkModalRegister" :onGoFormDetail="handleGoFormDetail" /> | 66 | <CheckDetail @register="checkModalRegister" :onGoFormDetail="handleGoFormDetail" /> |
36 | <FinanceEdit @register="registerFinanceEdit" @success="handleSuccess" /> | 67 | <FinanceEdit @register="registerFinanceEdit" @success="handleSuccess" /> |
68 | + <HistoryDetail @register="registerHistoryDetail" /> | ||
37 | </div> | 69 | </div> |
38 | </template> | 70 | </template> |
39 | <script setup lang="ts"> | 71 | <script setup lang="ts"> |
40 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; | 72 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; |
41 | - import { getPackageProfit } from '@/api/project/invoice'; | 73 | + import { getPackageProfit, setPackStatus } from '@/api/project/invoice'; |
42 | import { searchFormSchema, COLUMNS } from './data'; | 74 | import { searchFormSchema, COLUMNS } from './data'; |
43 | import { BasicModal, useModal } from '/@/components/Modal'; | 75 | import { BasicModal, useModal } from '/@/components/Modal'; |
44 | import { useMessage } from '/@/hooks/web/useMessage'; | 76 | import { useMessage } from '/@/hooks/web/useMessage'; |
45 | - import { onMounted, ref } from 'vue'; | 77 | + import { onMounted, ref, computed } from 'vue'; |
46 | import { useDrawer } from '/@/components/Drawer'; | 78 | import { useDrawer } from '/@/components/Drawer'; |
47 | import FinanceEdit from './FinanceEdit.vue'; | 79 | import FinanceEdit from './FinanceEdit.vue'; |
48 | import CheckDetail from './CheckDetail.vue'; | 80 | import CheckDetail from './CheckDetail.vue'; |
81 | + import HistoryDetail from './HistoryDetail.vue'; | ||
82 | + import axios from 'axios'; | ||
49 | import { FilePptOutlined } from '@ant-design/icons-vue'; | 83 | import { FilePptOutlined } from '@ant-design/icons-vue'; |
50 | import { useOrderStoreWithOut } from '/@/store/modules/order'; | 84 | import { useOrderStoreWithOut } from '/@/store/modules/order'; |
85 | + import { useUserStoreWithOut } from '/@/store/modules/user'; | ||
86 | + import { RoleEnum } from '/@/enums/roleEnum'; | ||
87 | + import { ROLE } from '../../../type.d'; | ||
51 | 88 | ||
52 | const { createMessage } = useMessage(); | 89 | const { createMessage } = useMessage(); |
53 | const { error } = createMessage; | 90 | const { error } = createMessage; |
54 | const message = ref(); | 91 | const message = ref(); |
92 | + const checkedKeys = ref<string[]>([]); | ||
93 | + // Define arrays to store collected data from selected rows | ||
94 | + const orderIds = ref<number[]>([]); | ||
95 | + const projectNo = ref<string[]>([]); | ||
96 | + const customerCode = ref<string[]>([]); | ||
97 | + const innerNo = ref<string[]>([]); | ||
98 | + const productionDepartment = ref<string[]>([]); | ||
99 | + const detailProjectNoKeys = ref<string[]>([]); | ||
55 | const orderStore = useOrderStoreWithOut(); | 100 | const orderStore = useOrderStoreWithOut(); |
56 | const [checkModalRegister, { openDrawer: openCheckDetailDrawer }] = useDrawer(); | 101 | const [checkModalRegister, { openDrawer: openCheckDetailDrawer }] = useDrawer(); |
57 | const [registerFinanceEdit, { openDrawer: openFinanceEdit }] = useDrawer(); | 102 | const [registerFinanceEdit, { openDrawer: openFinanceEdit }] = useDrawer(); |
103 | + const [registerHistoryDetail, { openDrawer: openHistoryDetail }] = useDrawer(); | ||
104 | + const userStore = useUserStoreWithOut(); | ||
105 | + const user = userStore.getUserInfo; | ||
106 | + const role = computed(() => { | ||
107 | + return user?.roleSmallVO?.code; | ||
108 | + }); | ||
58 | const handleOk = (record) => { | 109 | const handleOk = (record) => { |
59 | // 修改父组件的状态 | 110 | // 修改父组件的状态 |
60 | closeModal(); | 111 | closeModal(); |
@@ -64,16 +115,34 @@ | @@ -64,16 +115,34 @@ | ||
64 | message.value = ''; | 115 | message.value = ''; |
65 | } | 116 | } |
66 | }; | 117 | }; |
67 | - const [registerTable, { reload }] = useTable({ | 118 | + const [registerTable, { reload, setSelectedRowKeys, getForm }] = useTable({ |
68 | api: getPackageProfit, | 119 | api: getPackageProfit, |
69 | bordered: true, | 120 | bordered: true, |
70 | columns: COLUMNS, | 121 | columns: COLUMNS, |
71 | - rowKey: 'id', | 122 | + rowKey: (record) => record.orderId, |
72 | formConfig: { | 123 | formConfig: { |
73 | labelWidth: 120, | 124 | labelWidth: 120, |
74 | schemas: searchFormSchema, | 125 | schemas: searchFormSchema, |
75 | autoSubmitOnEnter: true, | 126 | autoSubmitOnEnter: true, |
76 | }, | 127 | }, |
128 | + // Add custom row props to prevent selection when clicking rows | ||
129 | + customRow: () => { | ||
130 | + return { | ||
131 | + onClick: (e) => { | ||
132 | + // Prevent row selection when clicking anywhere except checkboxes | ||
133 | + if (!e.target.closest('.ant-checkbox-wrapper')) { | ||
134 | + e.stopPropagation(); | ||
135 | + } | ||
136 | + }, | ||
137 | + }; | ||
138 | + }, | ||
139 | + rowSelection: { | ||
140 | + type: 'checkbox', | ||
141 | + selectedRowKeys: checkedKeys as any, | ||
142 | + onSelect: onSelect, | ||
143 | + onSelectAll: onSelectAll, | ||
144 | + checkStrictly: true, | ||
145 | + }, | ||
77 | useSearchForm: true, | 146 | useSearchForm: true, |
78 | showTableSetting: true, | 147 | showTableSetting: true, |
79 | showIndexColumn: false, | 148 | showIndexColumn: false, |
@@ -81,7 +150,7 @@ | @@ -81,7 +150,7 @@ | ||
81 | setting: false, | 150 | setting: false, |
82 | }, | 151 | }, |
83 | actionColumn: { | 152 | actionColumn: { |
84 | - width: 240, | 153 | + width: 260, |
85 | title: 'Action', | 154 | title: 'Action', |
86 | dataIndex: 'action', | 155 | dataIndex: 'action', |
87 | }, | 156 | }, |
@@ -113,6 +182,18 @@ | @@ -113,6 +182,18 @@ | ||
113 | // }, | 182 | // }, |
114 | onClick: handleFalse.bind(null, record), | 183 | onClick: handleFalse.bind(null, record), |
115 | }, | 184 | }, |
185 | + { | ||
186 | + label: '审核通过', | ||
187 | + popConfirm: { | ||
188 | + title: '确认审核?', | ||
189 | + confirm: () => { | ||
190 | + if (record.packStatus === 0 && role.value === ROLE.ADMIN) { | ||
191 | + handleStatus(record, true); | ||
192 | + } | ||
193 | + return; | ||
194 | + }, | ||
195 | + }, | ||
196 | + }, | ||
116 | ]; | 197 | ]; |
117 | } | 198 | } |
118 | return [ | 199 | return [ |
@@ -130,9 +211,17 @@ | @@ -130,9 +211,17 @@ | ||
130 | ]; | 211 | ]; |
131 | } | 212 | } |
132 | 213 | ||
133 | - onMounted(async () => { | ||
134 | - await orderStore.getDict(); | ||
135 | - }); | 214 | + function createDropActions(record: any) { |
215 | + if (!record.editable) { | ||
216 | + const actions = [ | ||
217 | + { | ||
218 | + label: '历史记录', | ||
219 | + onClick: handleHistoryDetail.bind(null, record), | ||
220 | + }, | ||
221 | + ]; | ||
222 | + return actions; | ||
223 | + } | ||
224 | + } | ||
136 | 225 | ||
137 | function handleFinanceEdit(record) { | 226 | function handleFinanceEdit(record) { |
138 | openFinanceEdit(true, { | 227 | openFinanceEdit(true, { |
@@ -176,5 +265,218 @@ | @@ -176,5 +265,218 @@ | ||
176 | // await deleteConfig({ ids: [record.id] }); | 265 | // await deleteConfig({ ids: [record.id] }); |
177 | // reload(); | 266 | // reload(); |
178 | // } | 267 | // } |
268 | + | ||
269 | + async function handleStatus(record, status) { | ||
270 | + try { | ||
271 | + await setPackStatus({ orderId: record.orderId }); | ||
272 | + reload(); | ||
273 | + } catch (error) { | ||
274 | + console.error(error); | ||
275 | + } | ||
276 | + } | ||
277 | + | ||
278 | + function handleHistoryDetail(record) { | ||
279 | + openHistoryDetail(true, { | ||
280 | + data: record, | ||
281 | + }); | ||
282 | + } | ||
283 | + | ||
284 | + function handleGoFormDetail() { | ||
285 | + // Add your logic for form detail navigation | ||
286 | + } | ||
287 | + | ||
288 | + onMounted(async () => { | ||
289 | + await orderStore.getDict(); | ||
290 | + }); | ||
291 | + | ||
292 | + function handleClearChoose() { | ||
293 | + checkedKeys.value = []; | ||
294 | + // Clear all collected data arrays | ||
295 | + orderIds.value = []; | ||
296 | + projectNo.value = []; | ||
297 | + customerCode.value = []; | ||
298 | + innerNo.value = []; | ||
299 | + productionDepartment.value = []; | ||
300 | + detailProjectNoKeys.value = []; // Add this line | ||
301 | + } | ||
302 | + | ||
303 | + function handleExport() { | ||
304 | + // Get current search parameters from the form | ||
305 | + const values = getForm().getFieldsValue(); | ||
306 | + | ||
307 | + // Create export parameters based on whether orderIds are selected | ||
308 | + let exportParams; | ||
309 | + | ||
310 | + // If orderIds are selected, only use those and ignore search params | ||
311 | + if (orderIds.value.length > 0) { | ||
312 | + exportParams = { | ||
313 | + orderIds: orderIds.value | ||
314 | + }; | ||
315 | + } | ||
316 | + // Otherwise use the search parameters | ||
317 | + else { | ||
318 | + exportParams = { | ||
319 | + ...values, | ||
320 | + projectNo: values.projectNo || undefined, | ||
321 | + customerCode: values.customerCode || undefined, | ||
322 | + innerNo: values.innerNo || undefined, | ||
323 | + productionDepartment: values.productionDepartment || undefined | ||
324 | + }; | ||
325 | + } | ||
326 | + | ||
327 | + console.log('Export parameters:', exportParams); | ||
328 | + | ||
329 | + const token = userStore.getToken; | ||
330 | + axios | ||
331 | + .post( | ||
332 | + '/basic-api/order/cost/businessProfitDetail/exportExcel', | ||
333 | + exportParams, | ||
334 | + { | ||
335 | + headers: { | ||
336 | + Authorization: `${token}`, // 去掉引号 | ||
337 | + }, | ||
338 | + responseType: 'blob', // 设置响应类型为 'blob' | ||
339 | + }, | ||
340 | + ) | ||
341 | + .then((response) => { | ||
342 | + // 创建一个 Blob 对象来保存二进制数据 | ||
343 | + const blob = new Blob([response.data], { type: 'application/zip' }); | ||
344 | + const getFormattedDate = (): string => { | ||
345 | + const date = new Date(); | ||
346 | + | ||
347 | + const year = date.getFullYear(); | ||
348 | + const month = String(date.getMonth() + 1).padStart(2, '0'); | ||
349 | + const day = String(date.getDate()).padStart(2, '0'); | ||
350 | + | ||
351 | + const hours = String(date.getHours()).padStart(2, '0'); | ||
352 | + const minutes = String(date.getMinutes()).padStart(2, '0'); | ||
353 | + const seconds = String(date.getSeconds()).padStart(2, '0'); | ||
354 | + | ||
355 | + return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; | ||
356 | + }; | ||
357 | + const date = getFormattedDate(); | ||
358 | + // 创建一个链接元素用于下载 | ||
359 | + const link = document.createElement('a'); | ||
360 | + link.href = window.URL.createObjectURL(blob); | ||
361 | + link.download = `业务利润分析表${date}.xlsx`; // 你可以为文件命名 | ||
362 | + document.body.appendChild(link); | ||
363 | + link.click(); // 自动点击链接,触发下载 | ||
364 | + document.body.removeChild(link); // 下载完成后移除链接 | ||
365 | + }) | ||
366 | + .catch((error) => { | ||
367 | + console.error(error); | ||
368 | + }); | ||
369 | + handleClearChoose(); | ||
370 | + reload(); | ||
371 | + } | ||
372 | + async function onSelect(record, selected: boolean, _selectedRows, nativeEvent) { | ||
373 | + // Only process selection if it's coming from a checkbox click or programmatically | ||
374 | + // This checks if the event is from clicking the row - then we ignore it | ||
375 | + if (nativeEvent && nativeEvent.target && !nativeEvent.target.closest('.ant-checkbox-wrapper')) { | ||
376 | + return; | ||
377 | + } | ||
378 | + | ||
379 | + const rowKey = record.orderId; | ||
380 | + if (selected) { | ||
381 | + checkedKeys.value = [...checkedKeys.value, rowKey]; | ||
382 | + | ||
383 | + // Add data from the selected row to the corresponding arrays | ||
384 | + if (record.orderId !== undefined && !orderIds.value.includes(record.orderId)) { | ||
385 | + orderIds.value.push(record.orderId); | ||
386 | + } | ||
387 | + | ||
388 | + if (record.projectNo !== undefined && !projectNo.value.includes(record.projectNo)) { | ||
389 | + projectNo.value.push(record.projectNo); | ||
390 | + } | ||
391 | + | ||
392 | + if (record.customerCode !== undefined && !customerCode.value.includes(record.customerCode)) { | ||
393 | + customerCode.value.push(record.customerCode); | ||
394 | + } | ||
395 | + | ||
396 | + if (record.innerNo !== undefined && !innerNo.value.includes(record.innerNo)) { | ||
397 | + innerNo.value.push(record.innerNo); | ||
398 | + } | ||
399 | + | ||
400 | + if (record.productionDepartment !== undefined && !productionDepartment.value.includes(record.productionDepartment)) { | ||
401 | + productionDepartment.value.push(record.productionDepartment); | ||
402 | + } | ||
403 | + | ||
404 | + if (record.detailProjectNoKey !== undefined && !detailProjectNoKeys.value.includes(record.detailProjectNoKey)) { | ||
405 | + detailProjectNoKeys.value.push(record.detailProjectNoKey); | ||
406 | + } | ||
407 | + } else { | ||
408 | + checkedKeys.value = checkedKeys.value.filter((key) => key !== rowKey); | ||
409 | + | ||
410 | + // Remove data from the deselected row from the corresponding arrays | ||
411 | + if (record.orderId !== undefined) { | ||
412 | + orderIds.value = orderIds.value.filter(id => id !== record.orderId); | ||
413 | + } | ||
414 | + | ||
415 | + if (record.projectNo !== undefined) { | ||
416 | + projectNo.value = projectNo.value.filter(no => no !== record.projectNo); | ||
417 | + } | ||
418 | + | ||
419 | + if (record.customerCode !== undefined) { | ||
420 | + customerCode.value = customerCode.value.filter(code => code !== record.customerCode); | ||
421 | + } | ||
422 | + | ||
423 | + if (record.innerNo !== undefined) { | ||
424 | + innerNo.value = innerNo.value.filter(no => no !== record.innerNo); | ||
425 | + } | ||
426 | + | ||
427 | + if (record.productionDepartment !== undefined) { | ||
428 | + productionDepartment.value = productionDepartment.value.filter(dept => dept !== record.productionDepartment); | ||
429 | + } | ||
430 | + } | ||
431 | + setSelectedRowKeys(checkedKeys.value as any); | ||
432 | + } | ||
433 | + | ||
434 | + function onSelectAll(selected: boolean, selectedRows: any[]) { | ||
435 | + if (selected) { | ||
436 | + // First clear all previous selections to avoid duplicates | ||
437 | + checkedKeys.value = []; | ||
438 | + orderIds.value = []; | ||
439 | + projectNo.value = []; | ||
440 | + customerCode.value = []; | ||
441 | + innerNo.value = []; | ||
442 | + productionDepartment.value = []; | ||
443 | + | ||
444 | + // Add all selected rows | ||
445 | + selectedRows.forEach((row) => { | ||
446 | + const rowKey = row.orderId; | ||
447 | + checkedKeys.value.push(rowKey); | ||
448 | + | ||
449 | + // Add data from each selected row to the corresponding arrays | ||
450 | + if (row.orderId !== undefined) { | ||
451 | + orderIds.value.push(row.orderId); | ||
452 | + } | ||
453 | + | ||
454 | + if (row.projectNo !== undefined) { | ||
455 | + projectNo.value.push(row.projectNo); | ||
456 | + } | ||
457 | + | ||
458 | + if (row.customerCode !== undefined) { | ||
459 | + customerCode.value.push(row.customerCode); | ||
460 | + } | ||
461 | + | ||
462 | + if (row.innerNo !== undefined) { | ||
463 | + innerNo.value.push(row.innerNo); | ||
464 | + } | ||
465 | + | ||
466 | + if (row.productionDepartment !== undefined) { | ||
467 | + productionDepartment.value.push(row.productionDepartment); | ||
468 | + } | ||
469 | + }); | ||
470 | + } else { | ||
471 | + // Clear all selections when deselecting all | ||
472 | + checkedKeys.value = []; | ||
473 | + orderIds.value = []; | ||
474 | + projectNo.value = []; | ||
475 | + customerCode.value = []; | ||
476 | + innerNo.value = []; | ||
477 | + productionDepartment.value = []; | ||
478 | + } | ||
479 | + setSelectedRowKeys(checkedKeys.value as any); | ||
480 | + } | ||
179 | </script> | 481 | </script> |
180 | <style></style> | 482 | <style></style> |
src/views/project/finance/financeProfit/ServiceProfit/ServiceProfit/ApproveReason.vue
@@ -37,6 +37,7 @@ | @@ -37,6 +37,7 @@ | ||
37 | projectEndTime: baseFieldValues.value.projectEndTime, | 37 | projectEndTime: baseFieldValues.value.projectEndTime, |
38 | spainPaidRmbCommission: baseFieldValues.value.spainPaidRmbCommission, | 38 | spainPaidRmbCommission: baseFieldValues.value.spainPaidRmbCommission, |
39 | applyRemark: baseFieldValues.value.applyRemark, | 39 | applyRemark: baseFieldValues.value.applyRemark, |
40 | + type: 'FIELD_EDIT_APPLY', | ||
40 | }); | 41 | }); |
41 | emit('success'); | 42 | emit('success'); |
42 | setTimeout(() => { | 43 | setTimeout(() => { |
src/views/project/finance/financeProfit/ServiceProfit/ServiceProfit/FinanceEdit.vue
@@ -9,6 +9,7 @@ | @@ -9,6 +9,7 @@ | ||
9 | @ok="handleSubmit" | 9 | @ok="handleSubmit" |
10 | :showDetailBack="false" | 10 | :showDetailBack="false" |
11 | okText="保存" | 11 | okText="保存" |
12 | + @visible-change="handleShow" | ||
12 | showFooter | 13 | showFooter |
13 | :destroyOnClose="true" | 14 | :destroyOnClose="true" |
14 | > | 15 | > |
@@ -45,14 +46,6 @@ | @@ -45,14 +46,6 @@ | ||
45 | auto-size | 46 | auto-size |
46 | /> | 47 | /> |
47 | <div style="margin: 16px 0"></div> | 48 | <div style="margin: 16px 0"></div> |
48 | - <div style="font-size: 15px">实际汇率¥</div> | ||
49 | - <a-input | ||
50 | - v-model:value="input6" | ||
51 | - placeholder="请输入" | ||
52 | - :disabled="status6 === 'LOCKED'" | ||
53 | - auto-size | ||
54 | - /> | ||
55 | - <div style="margin: 16px 0"></div> | ||
56 | <!-- <template #titleToolbar> <a-button type="primary"> 申请编辑权限 </a-button></template> --> | 49 | <!-- <template #titleToolbar> <a-button type="primary"> 申请编辑权限 </a-button></template> --> |
57 | <template #appendFooter> | 50 | <template #appendFooter> |
58 | <!-- <a-button type="primary" @click="onGoCheckDetail"> 申请权限</a-button> --> | 51 | <!-- <a-button type="primary" @click="onGoCheckDetail"> 申请权限</a-button> --> |
@@ -145,16 +138,13 @@ | @@ -145,16 +138,13 @@ | ||
145 | const status3 = ref(); | 138 | const status3 = ref(); |
146 | const status4 = ref(); | 139 | const status4 = ref(); |
147 | const status5 = ref(); | 140 | const status5 = ref(); |
148 | - const status6 = ref(); | ||
149 | 141 | ||
150 | const input1 = ref(); | 142 | const input1 = ref(); |
151 | const input2 = ref(); | 143 | const input2 = ref(); |
152 | const input3 = ref(); | 144 | const input3 = ref(); |
153 | - // const input4 = ref(); | ||
154 | - const input4 = ref(dayjs('2013-12-01')); | 145 | + const input4 = ref(); |
155 | 146 | ||
156 | const input5 = ref(); | 147 | const input5 = ref(); |
157 | - const input6 = ref(); | ||
158 | const id = ref(); | 148 | const id = ref(); |
159 | // function formatDate(dateStr: string): string { | 149 | // function formatDate(dateStr: string): string { |
160 | // const date = new Date(dateStr); | 150 | // const date = new Date(dateStr); |
@@ -185,16 +175,14 @@ | @@ -185,16 +175,14 @@ | ||
185 | status3.value = data?.data?.lockFields?.projectStartTime; | 175 | status3.value = data?.data?.lockFields?.projectStartTime; |
186 | status4.value = data?.data?.lockFields?.projectEndTime; | 176 | status4.value = data?.data?.lockFields?.projectEndTime; |
187 | status5.value = data?.data?.lockFields?.paidRmbCommission; | 177 | status5.value = data?.data?.lockFields?.paidRmbCommission; |
188 | - status6.value = data?.data?.lockFields?.actualExchangeRate; | ||
189 | } | 178 | } |
190 | - console.log(data.data.lockFields, '5656vdata.data.lockFields'); | ||
191 | id.value = data?.data?.projectNoPrefix; | 179 | id.value = data?.data?.projectNoPrefix; |
192 | input1.value = data?.data?.developmentCopyRmbTotalPrice.toFixed(2); | 180 | input1.value = data?.data?.developmentCopyRmbTotalPrice.toFixed(2); |
193 | input2.value = data?.data?.spainPaidRmbCommission.toFixed(2); | 181 | input2.value = data?.data?.spainPaidRmbCommission.toFixed(2); |
194 | input3.value = dayjs(formatDateToDateOnly(data?.data?.projectStartTime)); | 182 | input3.value = dayjs(formatDateToDateOnly(data?.data?.projectStartTime)); |
195 | input4.value = dayjs(formatDateToDateOnly(data?.data?.projectEndTime)); | 183 | input4.value = dayjs(formatDateToDateOnly(data?.data?.projectEndTime)); |
196 | input5.value = data?.data?.paidRmbCommission.toFixed(2); | 184 | input5.value = data?.data?.paidRmbCommission.toFixed(2); |
197 | - input6.value = data?.data?.actualExchangeRate.toFixed(2); | 185 | + |
198 | resetFields(); | 186 | resetFields(); |
199 | setDrawerProps({ confirmLoading: false }); | 187 | setDrawerProps({ confirmLoading: false }); |
200 | setFieldsValue({ | 188 | setFieldsValue({ |
@@ -220,10 +208,18 @@ | @@ -220,10 +208,18 @@ | ||
220 | projectStartTime: input3.value, | 208 | projectStartTime: input3.value, |
221 | projectEndTime: input4.value, | 209 | projectEndTime: input4.value, |
222 | paidRmbCommission: input5.value, | 210 | paidRmbCommission: input5.value, |
223 | - actualExchangeRate: input6.value, | ||
224 | }); | 211 | }); |
225 | emit('success'); | 212 | emit('success'); |
226 | closeDrawer(); | 213 | closeDrawer(); |
227 | } | 214 | } |
228 | } | 215 | } |
216 | + function handleShow(visible: boolean) { | ||
217 | + if (!visible) { | ||
218 | + input1.value = ''; | ||
219 | + input2.value = ''; | ||
220 | + input3.value = ''; | ||
221 | + input4.value = ''; | ||
222 | + input5.value = ''; | ||
223 | + } | ||
224 | + } | ||
229 | </script> | 225 | </script> |
src/views/project/finance/financeProfit/ServiceProfit/ServiceProfit/HistoryDetail.vue
0 → 100644
1 | +<template> | ||
2 | + <BasicDrawer | ||
3 | + @register="register" | ||
4 | + v-bind="$attrs" | ||
5 | + title="操作记录" | ||
6 | + width="60%" | ||
7 | + :isDetail="true" | ||
8 | + :showDetailBack="false" | ||
9 | + okText="保存" | ||
10 | + :destroyOnClose="true" | ||
11 | + > | ||
12 | + <Tabs v-model:activeKey="activeKey" className="my-0"> | ||
13 | + <TabPanel :key="1" tab="操作记录" className="w-full"> | ||
14 | + <a-list :pagination="pagination1" className="w-full"> | ||
15 | + <template v-for="item in list1" :key="item.id"> | ||
16 | + <a-list-item class="list"> | ||
17 | + <a-list-item-meta> | ||
18 | + <template #avatar> </template> | ||
19 | + <template #title> | ||
20 | + <span>{{ item.userName }}</span> | ||
21 | + </template> | ||
22 | + <template #description> | ||
23 | + <div class="description"> | ||
24 | + {{ item.optType }} | ||
25 | + </div> | ||
26 | + <div class="info"> | ||
27 | + <div><span>操作时间:</span>{{ formatToDateTime(item.createTime) }}</div> | ||
28 | + </div> | ||
29 | + </template> | ||
30 | + </a-list-item-meta> | ||
31 | + </a-list-item> | ||
32 | + </template> | ||
33 | + </a-list> | ||
34 | + </TabPanel> | ||
35 | + <TabPanel :key="2" tab="审批记录" className="w-full"> | ||
36 | + <a-list :pagination="pagination2" className="w-full"> | ||
37 | + <template v-for="item in list2" :key="item.id"> | ||
38 | + <a-list-item class="list"> | ||
39 | + <a-list-item-meta> | ||
40 | + <template #avatar> </template> | ||
41 | + <template #title> | ||
42 | + <span>{{ item.userName }}</span> | ||
43 | + </template> | ||
44 | + <template #description> | ||
45 | + <div class="description"> | ||
46 | + {{ item.optType }} | ||
47 | + </div> | ||
48 | + <div class="info"> | ||
49 | + <div><span>操作时间:</span>{{ formatToDateTime(item.createTime) }}</div> | ||
50 | + </div> | ||
51 | + </template> | ||
52 | + </a-list-item-meta> | ||
53 | + </a-list-item> | ||
54 | + </template> | ||
55 | + </a-list> | ||
56 | + </TabPanel> | ||
57 | + </Tabs> | ||
58 | + | ||
59 | + <!-- <template #titleToolbar> <a-button type="primary"> 申请编辑权限 </a-button></template> --> | ||
60 | + <template #appendFooter> | ||
61 | + <!-- <a-button type="primary" @click="onGoCheckDetail"> 申请权限</a-button> --> | ||
62 | + </template> | ||
63 | + </BasicDrawer> | ||
64 | +</template> | ||
65 | +<script lang="ts"> | ||
66 | + import { defineComponent, ref, computed } from 'vue'; | ||
67 | + import { Tabs, Progress, Row, Col, List } from 'ant-design-vue'; | ||
68 | + import { FormSchema, useForm } from '/@/components/Form/index'; | ||
69 | + | ||
70 | + import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; | ||
71 | + import { getProjectOptLog } from '/@/api/project/invoice'; | ||
72 | + import { formatToDateTime } from '/@/utils/dateUtil'; | ||
73 | + | ||
74 | + const TabPanel = Tabs.TabPane; | ||
75 | + | ||
76 | + const schemas: FormSchema[] = [ | ||
77 | + { | ||
78 | + field: '订单号', | ||
79 | + component: 'Input', | ||
80 | + label: '字段1', | ||
81 | + componentProps: { | ||
82 | + readonly: true, | ||
83 | + disabled: true, | ||
84 | + }, | ||
85 | + colProps: { | ||
86 | + span: 12, | ||
87 | + }, | ||
88 | + defaultValue: '111', | ||
89 | + }, | ||
90 | + { | ||
91 | + field: 'field2', | ||
92 | + component: 'Input', | ||
93 | + label: '字段2', | ||
94 | + colProps: { | ||
95 | + span: 12, | ||
96 | + }, | ||
97 | + }, | ||
98 | + ]; | ||
99 | + const achieveList = [ | ||
100 | + { | ||
101 | + key: '1', | ||
102 | + name: '操作记录', | ||
103 | + }, | ||
104 | + { | ||
105 | + key: '2', | ||
106 | + name: '审批记录', | ||
107 | + }, | ||
108 | + ]; | ||
109 | + export default defineComponent({ | ||
110 | + components: { | ||
111 | + BasicDrawer, | ||
112 | + Tabs, | ||
113 | + TabPanel, | ||
114 | + [List.name]: List, | ||
115 | + [List.Item.name]: List.Item, | ||
116 | + AListItemMeta: List.Item.Meta, | ||
117 | + }, | ||
118 | + props: { | ||
119 | + onGoCheckDetail: { | ||
120 | + type: Function, | ||
121 | + }, | ||
122 | + }, | ||
123 | + setup() { | ||
124 | + const list1 = ref([]); | ||
125 | + const total1 = ref(0); | ||
126 | + const page1 = ref(1); | ||
127 | + | ||
128 | + const list2 = ref([]); | ||
129 | + const total2 = ref(0); | ||
130 | + const page2 = ref(1); | ||
131 | + const orderId = ref(''); | ||
132 | + const activeKey = ref(1); | ||
133 | + | ||
134 | + const getOrderOptLogFunc = async (data, index, page) => { | ||
135 | + console.log('%c [ data ]-135', 'font-size:13px; background:pink; color:#bf2c9f;', data); | ||
136 | + if (index === 1) { | ||
137 | + const res = await getProjectOptLog({ | ||
138 | + projectNoPrefix: data, | ||
139 | + type: [10], | ||
140 | + page: page, | ||
141 | + pageSize: 20 | ||
142 | + }); | ||
143 | + list1.value = res.items; | ||
144 | + total1.value = res.total; | ||
145 | + page1.value = page; | ||
146 | + } else { | ||
147 | + const res = await getProjectOptLog({ | ||
148 | + projectNoPrefix: data, | ||
149 | + type: [0,2], | ||
150 | + page: page, | ||
151 | + pageSize: 20 | ||
152 | + }); | ||
153 | + list2.value = res.items; | ||
154 | + total2.value = res.total; | ||
155 | + page2.value = page; | ||
156 | + } | ||
157 | + }; | ||
158 | + const [register] = useDrawerInner((data) => { | ||
159 | + orderId.value = data.data.projectNoPrefix; | ||
160 | + getOrderOptLogFunc(orderId.value, 1, 1); | ||
161 | + getOrderOptLogFunc(orderId.value, 2, 1); | ||
162 | + }); | ||
163 | + | ||
164 | + const pagination1 = computed(() => { | ||
165 | + return { | ||
166 | + show: true, | ||
167 | + pageSize: 20, | ||
168 | + page: page1.value, | ||
169 | + total: total1.value, | ||
170 | + onChange(cur) { | ||
171 | + getOrderOptLogFunc(orderId.value, 1, cur); | ||
172 | + }, | ||
173 | + }; | ||
174 | + }); | ||
175 | + | ||
176 | + const pagination2 = computed(() => { | ||
177 | + return { | ||
178 | + show: true, | ||
179 | + pageSize: 20, | ||
180 | + page: page1.value, | ||
181 | + total: total1.value, | ||
182 | + onChange(cur) { | ||
183 | + getOrderOptLogFunc(orderId.value, 2, cur); | ||
184 | + }, | ||
185 | + }; | ||
186 | + }); | ||
187 | + | ||
188 | + return { | ||
189 | + register, | ||
190 | + schemas, | ||
191 | + achieveList, | ||
192 | + list1, | ||
193 | + list2, | ||
194 | + prefixCls: 'account-center', | ||
195 | + pagination1, | ||
196 | + pagination2, | ||
197 | + activeKey, | ||
198 | + formatToDateTime, | ||
199 | + }; | ||
200 | + }, | ||
201 | + }); | ||
202 | +</script> |
src/views/project/finance/financeProfit/ServiceProfit/ServiceProfit/data.tsx
@@ -104,6 +104,14 @@ export const COLUMNS = [ | @@ -104,6 +104,14 @@ export const COLUMNS = [ | ||
104 | width: 100, | 104 | width: 100, |
105 | }, | 105 | }, |
106 | { | 106 | { |
107 | + title: '订单总数量', | ||
108 | + dataIndex: 'orderCount', | ||
109 | + width: 120, | ||
110 | + customRender: (column) => { | ||
111 | + return column.record?.orderCount; | ||
112 | + }, | ||
113 | + }, | ||
114 | + { | ||
107 | title: '客户总金额¥', | 115 | title: '客户总金额¥', |
108 | width: 150, | 116 | width: 150, |
109 | dataIndex: 'customerTotalPrice', | 117 | dataIndex: 'customerTotalPrice', |
@@ -132,7 +140,7 @@ export const COLUMNS = [ | @@ -132,7 +140,7 @@ export const COLUMNS = [ | ||
132 | dataIndex: 'packetTotalPrice', | 140 | dataIndex: 'packetTotalPrice', |
133 | width: 150, | 141 | width: 150, |
134 | customRender: (column) => { | 142 | customRender: (column) => { |
135 | - return column.record?.packetTotalPrice?.toFixed(2); | 143 | + return column.record?.packetRmbTotalPrice?.toFixed(2); |
136 | }, | 144 | }, |
137 | }, | 145 | }, |
138 | { | 146 | { |
@@ -229,7 +237,7 @@ export const COLUMNS = [ | @@ -229,7 +237,7 @@ export const COLUMNS = [ | ||
229 | width: 120, | 237 | width: 120, |
230 | customRender: (column) => { | 238 | customRender: (column) => { |
231 | if (column.record?.profitRate) { | 239 | if (column.record?.profitRate) { |
232 | - return column.record?.profitRate?.toFixed(2) + '%'; | 240 | + return (column.record?.profitRate * 100).toFixed(2) + '%'; |
233 | } | 241 | } |
234 | return column.record?.profitRate?.toFixed(2); | 242 | return column.record?.profitRate?.toFixed(2); |
235 | }, | 243 | }, |
@@ -248,7 +256,7 @@ export const COLUMNS = [ | @@ -248,7 +256,7 @@ export const COLUMNS = [ | ||
248 | width: 120, | 256 | width: 120, |
249 | customRender: (column) => { | 257 | customRender: (column) => { |
250 | if (column.record?.developmentProfitRate) { | 258 | if (column.record?.developmentProfitRate) { |
251 | - return column.record?.developmentProfitRate?.toFixed(2) + '%'; | 259 | + return (column.record?.developmentProfitRate * 100).toFixed(2) + '%'; |
252 | } | 260 | } |
253 | return column.record?.developmentProfitRate?.toFixed(2); | 261 | return column.record?.developmentProfitRate?.toFixed(2); |
254 | }, | 262 | }, |
@@ -270,14 +278,6 @@ export const COLUMNS = [ | @@ -270,14 +278,6 @@ export const COLUMNS = [ | ||
270 | }, | 278 | }, |
271 | }, | 279 | }, |
272 | { | 280 | { |
273 | - title: '订单总数量', | ||
274 | - dataIndex: 'orderCount', | ||
275 | - width: 120, | ||
276 | - customRender: (column) => { | ||
277 | - return column.record?.orderCount; | ||
278 | - }, | ||
279 | - }, | ||
280 | - { | ||
281 | title: '实际跟单单价¥', | 281 | title: '实际跟单单价¥', |
282 | dataIndex: 'actualOrderRmbPrice', | 282 | dataIndex: 'actualOrderRmbPrice', |
283 | width: 160, | 283 | width: 160, |
@@ -302,22 +302,6 @@ export const COLUMNS = [ | @@ -302,22 +302,6 @@ export const COLUMNS = [ | ||
302 | }, | 302 | }, |
303 | }, | 303 | }, |
304 | { | 304 | { |
305 | - title: '实际汇率¥', | ||
306 | - dataIndex: 'actualExchangeRate', | ||
307 | - width: 120, | ||
308 | - customRender: (column) => { | ||
309 | - return column.record?.actualExchangeRate?.toFixed(2); | ||
310 | - }, | ||
311 | - }, | ||
312 | - { | ||
313 | - title: '汇率收益¥', | ||
314 | - dataIndex: 'exchangeRateProfit', | ||
315 | - width: 120, | ||
316 | - customRender: (column) => { | ||
317 | - return column.record?.exchangeRateProfit?.toFixed(2); | ||
318 | - }, | ||
319 | - }, | ||
320 | - { | ||
321 | title: '综合收益¥', | 305 | title: '综合收益¥', |
322 | dataIndex: 'comprehensiveProfit', | 306 | dataIndex: 'comprehensiveProfit', |
323 | width: 120, | 307 | width: 120, |
@@ -380,4 +364,18 @@ export const COLUMNS = [ | @@ -380,4 +364,18 @@ export const COLUMNS = [ | ||
380 | return <FilePptOutlined style="font-size:25px" onClick={() => handleClick()} />; | 364 | return <FilePptOutlined style="font-size:25px" onClick={() => handleClick()} />; |
381 | }, | 365 | }, |
382 | }, | 366 | }, |
367 | + { | ||
368 | + title: '状态', | ||
369 | + dataIndex: 'status', | ||
370 | + width: 120, | ||
371 | + customRender: (column) => { | ||
372 | + if (column.record?.developmentStatus === null || column.record?.developmentStatus === -1) { | ||
373 | + return '未完成'; | ||
374 | + } else if (column.record?.developmentStatus === 0) { | ||
375 | + return '待审核'; | ||
376 | + } else if (column.record?.developmentStatus === 1) { | ||
377 | + return '已审核'; | ||
378 | + } | ||
379 | + }, | ||
380 | + }, | ||
383 | ]; | 381 | ]; |
384 | \ No newline at end of file | 382 | \ No newline at end of file |
src/views/project/finance/financeProfit/ServiceProfit/ServiceProfit/index.vue
1 | <template> | 1 | <template> |
2 | <div> | 2 | <div> |
3 | <BasicTable @register="registerTable" :bordered="true"> | 3 | <BasicTable @register="registerTable" :bordered="true"> |
4 | + <template #headerTop> | ||
5 | + <a-alert type="info" show-icon> | ||
6 | + <template #message> | ||
7 | + <template v-if="checkedKeys.length > 0"> | ||
8 | + <span>已选中{{ checkedKeys.length }}条记录(可跨页)</span> | ||
9 | + <a-button | ||
10 | + :style="{ borderRadius: '5px 5px 5px 5px' }" | ||
11 | + type="link" | ||
12 | + @click="handleClearChoose" | ||
13 | + size="small" | ||
14 | + >清空</a-button | ||
15 | + > | ||
16 | + </template> | ||
17 | + <template v-else> | ||
18 | + <span>未选中任何订单</span> | ||
19 | + </template> | ||
20 | + </template> | ||
21 | + </a-alert> | ||
22 | + </template> | ||
4 | <template #bodyCell="{ column, record }"> | 23 | <template #bodyCell="{ column, record }"> |
5 | <template v-if="column.key === 'action'"> | 24 | <template v-if="column.key === 'action'"> |
6 | - <TableAction :actions="createActions(record)" /> | ||
7 | - </template> | ||
8 | - <!-- <template v-if="column.key === 'relationValue'"> | ||
9 | - <a-input | ||
10 | - v-if="record.settingValue === 'A01'" | ||
11 | - v-model:value="record.settingValue" | ||
12 | - :max-length="50" | 25 | + <TableAction |
26 | + :actions="createActions(record)" | ||
27 | + :dropDownActions="createDropActions(record)" | ||
13 | /> | 28 | /> |
14 | - <span v-else style="color: red"> | ||
15 | - {{ record.settingValue }} | ||
16 | - </span> | ||
17 | - </template> --> | 29 | + </template> |
30 | + </template> | ||
31 | + <template #toolbar> | ||
32 | + <a-button | ||
33 | + type="primary" | ||
34 | + @click="handleExport" | ||
35 | + v-if="role == ROLE.ADMIN || role == ROLE.FINANCE" | ||
36 | + :style="{ borderRadius: '5px 5px 5px 5px' }" | ||
37 | + >导出</a-button | ||
38 | + > | ||
18 | </template> | 39 | </template> |
19 | </BasicTable> | 40 | </BasicTable> |
20 | - <!-- <BasicModal | ||
21 | - title="拒绝原因" | ||
22 | - width="30%" | ||
23 | - @register="registerModal" | ||
24 | - @visible-change="handleClose" | ||
25 | - @ok="handleOk" | ||
26 | - wrapClassName="approve-modal" | ||
27 | - > | ||
28 | - <div className="pa-8"> | ||
29 | - <a-textarea :rows="6" placeholder="请输入拒绝原因" v-model:value="message" /> | ||
30 | - </div> | ||
31 | - </BasicModal> --> | ||
32 | <CheckDetail @register="checkModalRegister" :onGoFormDetail="handleGoFormDetail" /> | 41 | <CheckDetail @register="checkModalRegister" :onGoFormDetail="handleGoFormDetail" /> |
33 | <FinanceEdit @register="registerFinanceEdit" @success="handleSuccess" /> | 42 | <FinanceEdit @register="registerFinanceEdit" @success="handleSuccess" /> |
43 | + <HistoryDetail @register="registerHistoryDetail" /> | ||
34 | </div> | 44 | </div> |
35 | </template> | 45 | </template> |
36 | <script setup lang="ts"> | 46 | <script setup lang="ts"> |
37 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; | 47 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; |
38 | - import { getServiceProfit } from '@/api/project/invoice'; | 48 | + import { getServiceProfit, setBusinessProfitSetStatus } from '@/api/project/invoice'; |
39 | import { searchFormSchema, COLUMNS } from './data'; | 49 | import { searchFormSchema, COLUMNS } from './data'; |
40 | - import { BasicModal, useModal } from '/@/components/Modal'; | 50 | + import axios from 'axios'; |
41 | import { useMessage } from '/@/hooks/web/useMessage'; | 51 | import { useMessage } from '/@/hooks/web/useMessage'; |
42 | - import { onMounted, ref } from 'vue'; | 52 | + import { onMounted, ref, computed, unref } from 'vue'; |
43 | import { useDrawer } from '/@/components/Drawer'; | 53 | import { useDrawer } from '/@/components/Drawer'; |
44 | import FinanceEdit from './FinanceEdit.vue'; | 54 | import FinanceEdit from './FinanceEdit.vue'; |
55 | + import HistoryDetail from './HistoryDetail.vue'; | ||
45 | import CheckDetail from './CheckDetail.vue'; | 56 | import CheckDetail from './CheckDetail.vue'; |
57 | + import { useUserStoreWithOut } from '/@/store/modules/user'; | ||
58 | + import { ROLE } from '../../../type.d'; | ||
46 | import { useOrderStoreWithOut } from '/@/store/modules/order'; | 59 | import { useOrderStoreWithOut } from '/@/store/modules/order'; |
47 | 60 | ||
48 | const { createMessage } = useMessage(); | 61 | const { createMessage } = useMessage(); |
49 | - const { error } = createMessage; | ||
50 | const message = ref(); | 62 | const message = ref(); |
63 | + const checkedKeys = ref<string[]>([]); | ||
64 | + const invoiceIdKeys = ref<string[]>([]); | ||
65 | + const checkIdKeys = ref<string[]>([]); | ||
66 | + const detailProjectNoKeys = ref<string[]>([]); | ||
51 | const orderStore = useOrderStoreWithOut(); | 67 | const orderStore = useOrderStoreWithOut(); |
52 | const [checkModalRegister, { openDrawer: openCheckDetailDrawer }] = useDrawer(); | 68 | const [checkModalRegister, { openDrawer: openCheckDetailDrawer }] = useDrawer(); |
53 | const [registerFinanceEdit, { openDrawer: openFinanceEdit }] = useDrawer(); | 69 | const [registerFinanceEdit, { openDrawer: openFinanceEdit }] = useDrawer(); |
54 | - const handleClose = (visible: boolean) => { | ||
55 | - if (!visible) { | ||
56 | - message.value = ''; | ||
57 | - } | ||
58 | - }; | ||
59 | - const [registerTable, { reload }] = useTable({ | 70 | + const [registerHistoryDetail, { openDrawer: openHistoryDetail }] = useDrawer(); |
71 | + const userStore = useUserStoreWithOut(); | ||
72 | + const user = userStore.getUserInfo; | ||
73 | + const role = computed(() => { | ||
74 | + return user?.roleSmallVO?.code; | ||
75 | + }); | ||
76 | + const [registerTable, { reload, getSelectRowKeys, getDataSource, setSelectedRowKeys }] = useTable({ | ||
77 | + title: '', | ||
60 | api: getServiceProfit, | 78 | api: getServiceProfit, |
61 | bordered: true, | 79 | bordered: true, |
62 | columns: COLUMNS, | 80 | columns: COLUMNS, |
63 | clickToRowSelect: false, | 81 | clickToRowSelect: false, |
64 | - rowKey: 'id', | ||
65 | formConfig: { | 82 | formConfig: { |
66 | labelWidth: 120, | 83 | labelWidth: 120, |
67 | schemas: searchFormSchema, | 84 | schemas: searchFormSchema, |
68 | autoSubmitOnEnter: true, | 85 | autoSubmitOnEnter: true, |
69 | }, | 86 | }, |
87 | + rowKey: (record) => record.detailProjectNo || record.id || record.serialNumber, | ||
88 | + rowSelection: { | ||
89 | + type: 'checkbox', | ||
90 | + selectedRowKeys: checkedKeys as any, | ||
91 | + onSelect: onSelect, | ||
92 | + onSelectAll: onSelectAll, | ||
93 | + }, | ||
70 | useSearchForm: true, | 94 | useSearchForm: true, |
71 | showTableSetting: true, | 95 | showTableSetting: true, |
72 | showIndexColumn: false, | 96 | showIndexColumn: false, |
@@ -74,7 +98,7 @@ | @@ -74,7 +98,7 @@ | ||
74 | setting: false, | 98 | setting: false, |
75 | }, | 99 | }, |
76 | actionColumn: { | 100 | actionColumn: { |
77 | - width: 240, | 101 | + width: 260, |
78 | title: 'Action', | 102 | title: 'Action', |
79 | dataIndex: 'action', | 103 | dataIndex: 'action', |
80 | }, | 104 | }, |
@@ -82,31 +106,29 @@ | @@ -82,31 +106,29 @@ | ||
82 | 106 | ||
83 | function createActions(record: any): any[] { | 107 | function createActions(record: any): any[] { |
84 | if (!record.editable) { | 108 | if (!record.editable) { |
85 | - return [ | 109 | + const actions = [ |
86 | { | 110 | { |
87 | label: '财务编辑', | 111 | label: '财务编辑', |
88 | onClick: handleFinanceEdit.bind(null, record), | 112 | onClick: handleFinanceEdit.bind(null, record), |
89 | }, | 113 | }, |
90 | - // { | ||
91 | - // label: '编辑', | ||
92 | - // onClick: handleEdit.bind(null, record), | ||
93 | - // }, | ||
94 | - // { | ||
95 | - // label: '删除', | ||
96 | - // popConfirm: { | ||
97 | - // title: '确认删除?', | ||
98 | - // confirm: handleDelete.bind(null, record), | ||
99 | - // }, | ||
100 | - // }, | ||
101 | { | 114 | { |
102 | label: '申请权限', | 115 | label: '申请权限', |
103 | - // popConfirm: { | ||
104 | - // title: '确认申请?', | ||
105 | - // confirm: handleFalse.bind(null, record), | ||
106 | - // }, | ||
107 | onClick: handleFalse.bind(null, record), | 116 | onClick: handleFalse.bind(null, record), |
108 | }, | 117 | }, |
118 | + { | ||
119 | + label: '审核通过', | ||
120 | + popConfirm: { | ||
121 | + title: '确认审核?', | ||
122 | + confirm: () => { | ||
123 | + if (record.developmentStatus === 0 && role.value === ROLE.ADMIN) { | ||
124 | + handleStatus(record, true); | ||
125 | + } | ||
126 | + return; | ||
127 | + }, | ||
128 | + }, | ||
129 | + }, | ||
109 | ]; | 130 | ]; |
131 | + return actions; | ||
110 | } | 132 | } |
111 | return [ | 133 | return [ |
112 | { | 134 | { |
@@ -122,6 +144,17 @@ | @@ -122,6 +144,17 @@ | ||
122 | }, | 144 | }, |
123 | ]; | 145 | ]; |
124 | } | 146 | } |
147 | + function createDropActions(record: any) { | ||
148 | + if (!record.editable) { | ||
149 | + const actions = [ | ||
150 | + { | ||
151 | + label: '历史记录', | ||
152 | + onClick: handleHistoryDetail.bind(null, record), | ||
153 | + }, | ||
154 | + ]; | ||
155 | + return actions; | ||
156 | + } | ||
157 | + } | ||
125 | 158 | ||
126 | onMounted(async () => { | 159 | onMounted(async () => { |
127 | await orderStore.getDict(); | 160 | await orderStore.getDict(); |
@@ -139,11 +172,6 @@ | @@ -139,11 +172,6 @@ | ||
139 | return false; | 172 | return false; |
140 | } | 173 | } |
141 | 174 | ||
142 | - // async function handleFalse(record: any) { | ||
143 | - // console.log(record); | ||
144 | - // // openModal(true, { record }); | ||
145 | - // } | ||
146 | - | ||
147 | function handleSuccess() { | 175 | function handleSuccess() { |
148 | setTimeout(() => { | 176 | setTimeout(() => { |
149 | reload(); | 177 | reload(); |
@@ -155,21 +183,185 @@ | @@ -155,21 +183,185 @@ | ||
155 | handleCancel(record); | 183 | handleCancel(record); |
156 | reload(); | 184 | reload(); |
157 | } | 185 | } |
158 | - function handleEdit(record: any) { | ||
159 | - // if (record.settingValue == 'A01') { | ||
160 | - // error('请勿连续点击生成按钮,需要等待三秒再点击生成'); | ||
161 | - // } else { | ||
162 | - record.onEdit?.(true); | ||
163 | - // } | ||
164 | - } | ||
165 | 186 | ||
166 | function handleCancel(record) { | 187 | function handleCancel(record) { |
167 | record.onEdit?.(false, false); | 188 | record.onEdit?.(false, false); |
168 | } | 189 | } |
169 | 190 | ||
170 | - async function handleDelete(record) { | ||
171 | - // await deleteConfig({ ids: [record.id] }); | 191 | + async function handleStatus(record, status) { |
192 | + try { | ||
193 | + await setBusinessProfitSetStatus({ | ||
194 | + customerCode: record.customerCode, | ||
195 | + projectNo: record.projectNoPrefix, | ||
196 | + }); | ||
197 | + reload(); | ||
198 | + } catch (error) { | ||
199 | + console.error('Error updating status:', error); | ||
200 | + } | ||
201 | + } | ||
202 | + | ||
203 | + async function handleHistoryDetail(record) { | ||
204 | + openHistoryDetail(true, { | ||
205 | + data: record, | ||
206 | + }); | ||
207 | + } | ||
208 | + | ||
209 | + function handleExport() { | ||
210 | + if (checkedKeys.value.length <= 0) { | ||
211 | + createMessage.warn('请选择数据!'); | ||
212 | + return; | ||
213 | + } | ||
214 | + const token = userStore.getToken; | ||
215 | + axios | ||
216 | + .post( | ||
217 | + '/basic-api/project/businessProfit/exportExcel', | ||
218 | + { detailProjectNo: detailProjectNoKeys.value }, | ||
219 | + { | ||
220 | + headers: { | ||
221 | + Authorization: `${token}`, // 去掉引号 | ||
222 | + }, | ||
223 | + responseType: 'blob', // 设置响应类型为 'blob' | ||
224 | + }, | ||
225 | + ) | ||
226 | + .then((response) => { | ||
227 | + // 创建一个 Blob 对象来保存二进制数据 | ||
228 | + const blob = new Blob([response.data], { type: 'application/zip' }); | ||
229 | + const getFormattedDate = (): string => { | ||
230 | + const date = new Date(); | ||
231 | + | ||
232 | + const year = date.getFullYear(); | ||
233 | + const month = String(date.getMonth() + 1).padStart(2, '0'); | ||
234 | + const day = String(date.getDate()).padStart(2, '0'); | ||
235 | + | ||
236 | + const hours = String(date.getHours()).padStart(2, '0'); | ||
237 | + const minutes = String(date.getMinutes()).padStart(2, '0'); | ||
238 | + const seconds = String(date.getSeconds()).padStart(2, '0'); | ||
239 | + | ||
240 | + return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; | ||
241 | + }; | ||
242 | + const date = getFormattedDate(); | ||
243 | + // 创建一个链接元素用于下载 | ||
244 | + const link = document.createElement('a'); | ||
245 | + link.href = window.URL.createObjectURL(blob); | ||
246 | + link.download = `业务利润分析表${date}.xlsx`; // 你可以为文件命名 | ||
247 | + document.body.appendChild(link); | ||
248 | + link.click(); // 自动点击链接,触发下载 | ||
249 | + document.body.removeChild(link); // 下载完成后移除链接 | ||
250 | + }) | ||
251 | + .catch((error) => { | ||
252 | + console.error(error); | ||
253 | + }); | ||
254 | + handleClearChoose(); | ||
172 | reload(); | 255 | reload(); |
173 | } | 256 | } |
257 | + | ||
258 | + function handleClearChoose() { | ||
259 | + checkedKeys.value = []; | ||
260 | + detailProjectNoKeys.value = []; | ||
261 | + invoiceIdKeys.value = []; | ||
262 | + checkIdKeys.value = []; | ||
263 | + } | ||
264 | + | ||
265 | + async function onSelect(record, selected: boolean) { | ||
266 | + const rowKey = record.detailProjectNo || record.id || record.serialNumber; | ||
267 | + if (selected) { | ||
268 | + checkedKeys.value = [...checkedKeys.value, rowKey]; | ||
269 | + | ||
270 | + // 如果detailProjectNo是数组,将每个元素添加到detailProjectNoKeys中 | ||
271 | + if (record.detailProjectNo !== undefined) { | ||
272 | + if (Array.isArray(record.detailProjectNo)) { | ||
273 | + record.detailProjectNo.forEach((projectNo) => { | ||
274 | + if (!detailProjectNoKeys.value.includes(projectNo)) { | ||
275 | + detailProjectNoKeys.value.push(projectNo); | ||
276 | + } | ||
277 | + }); | ||
278 | + } else { | ||
279 | + // 如果是单个值,直接添加 | ||
280 | + if (!detailProjectNoKeys.value.includes(record.detailProjectNo)) { | ||
281 | + detailProjectNoKeys.value.push(record.detailProjectNo); | ||
282 | + } | ||
283 | + } | ||
284 | + } | ||
285 | + | ||
286 | + if (record.invoiceId !== undefined) { | ||
287 | + invoiceIdKeys.value = [...invoiceIdKeys.value, record.invoiceId]; | ||
288 | + } | ||
289 | + | ||
290 | + if (record.checkId !== undefined) { | ||
291 | + checkIdKeys.value = [...checkIdKeys.value, record.checkId]; | ||
292 | + } | ||
293 | + } else { | ||
294 | + checkedKeys.value = checkedKeys.value.filter((key) => key !== rowKey); | ||
295 | + | ||
296 | + // 如果detailProjectNo是数组,从detailProjectNoKeys中移除每个元素 | ||
297 | + if (record.detailProjectNo !== undefined) { | ||
298 | + if (Array.isArray(record.detailProjectNo)) { | ||
299 | + detailProjectNoKeys.value = detailProjectNoKeys.value.filter( | ||
300 | + (projectNo) => !record.detailProjectNo.includes(projectNo) | ||
301 | + ); | ||
302 | + } else { | ||
303 | + // 如果是单个值,直接移除 | ||
304 | + detailProjectNoKeys.value = detailProjectNoKeys.value.filter( | ||
305 | + (projectNo) => projectNo !== record.detailProjectNo | ||
306 | + ); | ||
307 | + } | ||
308 | + } | ||
309 | + | ||
310 | + if (record.invoiceId !== undefined) { | ||
311 | + invoiceIdKeys.value = invoiceIdKeys.value.filter( | ||
312 | + (invoiceId) => invoiceId !== record.invoiceId, | ||
313 | + ); | ||
314 | + } | ||
315 | + | ||
316 | + if (record.checkId !== undefined) { | ||
317 | + checkIdKeys.value = checkIdKeys.value.filter((checkId) => checkId !== record.checkId); | ||
318 | + } | ||
319 | + } | ||
320 | + setSelectedRowKeys(checkedKeys.value as any); | ||
321 | + } | ||
322 | + | ||
323 | + function onSelectAll(selected: boolean, selectedRows: any[]) { | ||
324 | + if (selected) { | ||
325 | + // 先清空之前的选择,避免重复添加 | ||
326 | + checkedKeys.value = []; | ||
327 | + detailProjectNoKeys.value = []; | ||
328 | + invoiceIdKeys.value = []; | ||
329 | + checkIdKeys.value = []; | ||
330 | + | ||
331 | + // 重新添加所有选中的行 | ||
332 | + selectedRows.forEach((row) => { | ||
333 | + const rowKey = row.detailProjectNo || row.id || row.serialNumber; | ||
334 | + checkedKeys.value.push(rowKey); | ||
335 | + | ||
336 | + // 如果detailProjectNo是数组,将每个元素添加到detailProjectNoKeys中 | ||
337 | + if (row.detailProjectNo !== undefined) { | ||
338 | + if (Array.isArray(row.detailProjectNo)) { | ||
339 | + row.detailProjectNo.forEach((projectNo) => { | ||
340 | + // 由于已经清空了数组,不需要检查是否存在 | ||
341 | + detailProjectNoKeys.value.push(projectNo); | ||
342 | + }); | ||
343 | + } else { | ||
344 | + // 如果是单个值,直接添加 | ||
345 | + detailProjectNoKeys.value.push(row.detailProjectNo); | ||
346 | + } | ||
347 | + } | ||
348 | + | ||
349 | + if (row.invoiceId !== undefined) { | ||
350 | + invoiceIdKeys.value.push(row.invoiceId); | ||
351 | + } | ||
352 | + | ||
353 | + if (row.checkId !== undefined) { | ||
354 | + checkIdKeys.value.push(row.checkId); | ||
355 | + } | ||
356 | + }); | ||
357 | + } else { | ||
358 | + // 取消全选时,清空所有选择 | ||
359 | + checkedKeys.value = []; | ||
360 | + detailProjectNoKeys.value = []; | ||
361 | + invoiceIdKeys.value = []; | ||
362 | + checkIdKeys.value = []; | ||
363 | + } | ||
364 | + setSelectedRowKeys(checkedKeys.value as any); | ||
365 | + } | ||
174 | </script> | 366 | </script> |
175 | <style></style> | 367 | <style></style> |
src/views/project/finance/financeProfit/ServiceProfit/ServiceProfit/tableData.tsx
@@ -55,12 +55,4 @@ export const FIELDS_BASE_INFO = [ | @@ -55,12 +55,4 @@ export const FIELDS_BASE_INFO = [ | ||
55 | label: '中国团队已发提成¥', | 55 | label: '中国团队已发提成¥', |
56 | rules: [{ required: true }], | 56 | rules: [{ required: true }], |
57 | }, | 57 | }, |
58 | - { | ||
59 | - field: 'actualExchangeRate', | ||
60 | - component: 'Select', | ||
61 | - labelWidth: 150, | ||
62 | - label: '实际汇率¥', | ||
63 | - rules: [{ required: true }], | ||
64 | - }, | ||
65 | ]; | 58 | ]; |
66 | - |
src/views/project/finance/pay/index.vue
@@ -322,9 +322,6 @@ | @@ -322,9 +322,6 @@ | ||
322 | }); | 322 | }); |
323 | } | 323 | } |
324 | 324 | ||
325 | - // console.log(checkedKeys.value, 565666666); // 输出当前的 selectedCustomCodes 值 | ||
326 | - // console.log(selectedCustomCodes.value, 565666666); // 输出当前的 selectedCustomCodes 值 | ||
327 | - // console.log(selectedProductionDepartment.value, 565666666); // 输出当前的 selectedCustomCodes 值 | ||
328 | } | 325 | } |
329 | 326 | ||
330 | function handleFinanceEdit(record) { | 327 | function handleFinanceEdit(record) { |
src/views/project/finance/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 | +} |
vite.config.ts
@@ -30,26 +30,33 @@ export default defineApplicationConfig({ | @@ -30,26 +30,33 @@ export default defineApplicationConfig({ | ||
30 | }, | 30 | }, |
31 | }, | 31 | }, |
32 | '/basic-api/order': { | 32 | '/basic-api/order': { |
33 | - // target: 'http://localhost:18001', | ||
34 | - target: 'http://47.104.8.35:18001', | 33 | + target: 'http://47.104.8.35:8000', |
34 | + // target: 'http://localhost:18000', | ||
35 | + // target: 'http://39.108.227.113:8000', | ||
36 | + // target: 'http://localhost:8000', | ||
37 | + // target: 'http://39.108.227.113:3000/mock/35', | ||
38 | + // http://39.108.227.113:8000/order/erp/captcha/get_img_captcha_code | ||
39 | + changeOrigin: true, | ||
40 | + ws: true, | ||
41 | + rewrite: (path) => path.replace(new RegExp(`^/basic-api`), ''), | ||
42 | + }, | ||
43 | + '/basic-api/project': { | ||
44 | + target: 'http://47.104.8.35:8000', | ||
45 | + // target: 'http://localhost:18000', | ||
46 | + // target: 'http://39.108.227.113:8000', | ||
47 | + // target: 'http://localhost:8000', | ||
48 | + // target: 'http://39.108.227.113:3000/mock/35', | ||
49 | + // http://39.108.227.113:8000/order/erp/captcha/get_img_captcha_code | ||
35 | changeOrigin: true, | 50 | changeOrigin: true, |
36 | ws: true, | 51 | ws: true, |
37 | rewrite: (path) => path.replace(new RegExp(`^/basic-api`), ''), | 52 | rewrite: (path) => path.replace(new RegExp(`^/basic-api`), ''), |
38 | }, | 53 | }, |
39 | - // '/basic-api/project': { | ||
40 | - // target: 'http://47.104.8.35:8000', | ||
41 | - // // target: 'http://localhost:18000', | ||
42 | - // // target: 'http://39.108.227.113:8000', | ||
43 | - // // target: 'http://localhost:8000', | ||
44 | - // // target: 'http://39.108.227.113:3000/mock/35', | ||
45 | - // // http://39.108.227.113:8000/order/erp/captcha/get_img_captcha_code | ||
46 | - // changeOrigin: true, | ||
47 | - // ws: true, | ||
48 | - // rewrite: (path) => path.replace(new RegExp(`^/basic-api`), ''), | ||
49 | - // }, | ||
50 | '/api/localStorage/upload': { | 54 | '/api/localStorage/upload': { |
51 | - // target: 'http://localhost:18001', | ||
52 | - target: 'http://47.104.8.35:18001', | 55 | + target: 'http://47.104.8.35:8000', |
56 | + // target: 'http://localhost:18000', | ||
57 | + // target: 'http://39.108.227.113:8000', | ||
58 | + // target: '192.168.31.250:18000', | ||
59 | + // target: 'http://localhost:8000', | ||
53 | changeOrigin: true, | 60 | changeOrigin: true, |
54 | ws: true, | 61 | ws: true, |
55 | // rewrite: (path) => { | 62 | // rewrite: (path) => { |