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 | 21 | { message: '操作成功' }, |
22 | 22 | ); |
23 | 23 | |
24 | -export const getWaitListApi = async (params: DemoParams) => { | |
24 | +export const getWaitListApi = async (params: any) => { | |
25 | 25 | const res = await defHttp.post({ |
26 | 26 | url: Api.APPROVE, |
27 | 27 | params, |
28 | 28 | }); |
29 | - | |
30 | 29 | res.records = res.records.map((item) => { |
31 | 30 | return item; |
32 | 31 | }); |
... | ... | @@ -44,7 +43,6 @@ export const getApprovedListApi = async (params: any) => { |
44 | 43 | res.records = res.records.map((item) => { |
45 | 44 | return item; |
46 | 45 | }); |
47 | - | |
48 | 46 | return new Promise((resolve) => { |
49 | 47 | resolve({ items: res.records, total: res.total }); |
50 | 48 | }); | ... | ... |
src/api/project/invoice.ts
... | ... | @@ -52,6 +52,12 @@ enum Api { |
52 | 52 | SERVICEAPPLYEDIT = '/project/applyEditFileds', //申请修改 |
53 | 53 | APPLYLIST = '/project/pageProjectLockFieldApply', //分页查询项目字段申请记录 |
54 | 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 | 63 | export const getRefundDate = async (params: any, data?: any) => { |
... | ... | @@ -429,18 +435,30 @@ export const getServiceApplyEdit = async (params: any) => { |
429 | 435 | }; |
430 | 436 | |
431 | 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 | 451 | url: Api.APPLYLIST, |
435 | 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 | 464 | export const getAuditApply = async (params: any) => { |
... | ... | @@ -476,4 +494,71 @@ export const checkSetFinishStatus = async (params: any) => { |
476 | 494 | url: Api.SETCHECKFINISHSTATUS, |
477 | 495 | params, |
478 | 496 | }); |
479 | -}; | |
480 | 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 | 43 | }, |
44 | 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 | 94 | dataIndex: 'innerNo', |
95 | 95 | width: 150, |
96 | 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 | 102 | dataIndex: 'projectNo', |
103 | 103 | width: 150, |
104 | 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 | 130 | const [registerTable, { reload }] = useTable({ |
131 | 131 | scroll: false, |
132 | 132 | api: props.isApproved ? getApprovedListApi : getWaitListApi, |
133 | - searchInfo: { typeIn: [60, 70] }, | |
133 | + searchInfo: { typeIn: [80, 90] }, | |
134 | 134 | columns, |
135 | 135 | useSearchForm: false, |
136 | 136 | formConfig: getFormConfig('true'), | ... | ... |
src/views/project/approve/ProfitFieldPanel.vue
... | ... | @@ -39,7 +39,7 @@ |
39 | 39 | import { BasicDrawer, useDrawer } from '/@/components/Drawer'; |
40 | 40 | import { approveAuditApi, getApprovedListApi, getWaitListApi } from '/@/api/project/approve'; |
41 | 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 | 43 | import { COLUMNS } from '../finance/financeProfit/ServiceProfit/ServiceProfit/data'; |
44 | 44 | import { find, isEmpty } from 'lodash-es'; |
45 | 45 | import { ROLE } from '../order//type.d'; |
... | ... | @@ -85,7 +85,11 @@ |
85 | 85 | dataIndex: 'auditRoleCodes', |
86 | 86 | width: 150, |
87 | 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 | 70 | : []), |
71 | 71 | ], |
72 | 72 | }; |
73 | -} | |
74 | 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 | 35 | > |
36 | 36 | <PayPanel /> |
37 | 37 | </a-tab-pane> |
38 | - <!-- <a-tab-pane | |
38 | + <a-tab-pane | |
39 | 39 | key="11" |
40 | 40 | tab="利润分析表字段审核" |
41 | 41 | v-if="role == ROLE.FINANCE || role == ROLE.ADMIN" |
... | ... | @@ -44,7 +44,7 @@ |
44 | 44 | </a-tab-pane> |
45 | 45 | <a-tab-pane key="13" tab="明细表字段审核" v-if="role == ROLE.FINANCE || role == ROLE.ADMIN"> |
46 | 46 | <ProduceFieldPanel /> |
47 | - </a-tab-pane> --> | |
47 | + </a-tab-pane> | |
48 | 48 | <a-tab-pane key="2" tab="字段已审核" v-if="role !== ROLE.FINANCE"> |
49 | 49 | <FieldPanel isApproved /> |
50 | 50 | </a-tab-pane> |
... | ... | @@ -79,7 +79,7 @@ |
79 | 79 | > |
80 | 80 | <PayPanel isApproved /> |
81 | 81 | </a-tab-pane> |
82 | - <!-- <a-tab-pane | |
82 | + <a-tab-pane | |
83 | 83 | key="12" |
84 | 84 | tab="利润分析表字段已审核" |
85 | 85 | v-if="role == ROLE.FINANCE || role == ROLE.ADMIN" |
... | ... | @@ -88,7 +88,7 @@ |
88 | 88 | </a-tab-pane> |
89 | 89 | <a-tab-pane key="14" tab="明细表字段审核" v-if="role == ROLE.FINANCE || role == ROLE.ADMIN"> |
90 | 90 | <ProduceFieldPanel isApproved /> |
91 | - </a-tab-pane> --> | |
91 | + </a-tab-pane> | |
92 | 92 | </a-tabs> |
93 | 93 | </div> |
94 | 94 | </template> | ... | ... |
src/views/project/config/ProduCostCreate.vue
... | ... | @@ -22,9 +22,15 @@ |
22 | 22 | <a-input v-model:value="fixCost" |
23 | 23 | /></div> |
24 | 24 | <div |
25 | - ><span style="margin-right: 8px; width: 80%">提成比例:</span> | |
25 | + ><span style="margin-right: 8px; width: 80%">提成单价:</span> | |
26 | 26 | <a-input v-model:value="ratio" /> |
27 | 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 | 34 | </a-space> |
29 | 35 | </BasicModal> |
30 | 36 | </template> |
... | ... | @@ -54,6 +60,13 @@ |
54 | 60 | //获取现有的列表 |
55 | 61 | const listAll = ref(); |
56 | 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 | 70 | const ratio = ref(); |
58 | 71 | // const relationValue = ref(); |
59 | 72 | const customerCode = ref(); |
... | ... | @@ -91,7 +104,7 @@ |
91 | 104 | settingValue: customerCode.value, |
92 | 105 | settingType: 4, |
93 | 106 | relationCode: 'ProduceSettingItem', |
94 | - relationName: '成本配置项集合', | |
107 | + relationName: year.value, | |
95 | 108 | costSettingItemVOS: relationValue.value, |
96 | 109 | }); |
97 | 110 | emit('modal-success'); |
... | ... | @@ -108,6 +121,8 @@ |
108 | 121 | activeUser, |
109 | 122 | fixCost, |
110 | 123 | ratio, |
124 | + year, | |
125 | + yearOptions, | |
111 | 126 | customerCode, |
112 | 127 | customerCodeOptions, |
113 | 128 | handleOk, | ... | ... |
src/views/project/config/ProduCostEdit.vue
... | ... | @@ -16,7 +16,8 @@ |
16 | 16 | > |
17 | 17 | <a-space direction="vertical" style="width: 100%"> |
18 | 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 | 21 | </a-space> |
21 | 22 | </BasicDrawer> |
22 | 23 | </template> |
... | ... | @@ -35,13 +36,14 @@ |
35 | 36 | relationValue.value = JSON.parse(listAll.value.relationValue); |
36 | 37 | fixCost.value = relationValue.value[0].relationValue; |
37 | 38 | ratio.value = relationValue.value[1].relationValue; |
39 | + year.value = listAll.value.relationName; | |
38 | 40 | }); |
39 | 41 | //获取现有的列表 |
40 | 42 | const listAll = ref(); |
41 | 43 | const fixCost = ref(); |
42 | 44 | const ratio = ref(); |
43 | 45 | const relationValue = ref(); |
44 | - | |
46 | + const year = ref(); | |
45 | 47 | //完成编辑 |
46 | 48 | async function handleSubmit() { |
47 | 49 | relationValue.value[0].relationValue = fixCost.value; |
... | ... | @@ -53,7 +55,7 @@ |
53 | 55 | settingValue: listAll.value.settingValue, |
54 | 56 | settingType: 4, |
55 | 57 | relationCode: 'ProduceSettingItem', |
56 | - relationName: '成本配置项集合', | |
58 | + relationName: year.value, | |
57 | 59 | costSettingItemVOS: relationValue.value, |
58 | 60 | }); |
59 | 61 | emit('success'); | ... | ... |
src/views/project/config/TablePanel.vue
... | ... | @@ -46,7 +46,7 @@ |
46 | 46 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; |
47 | 47 | import CreateModal from './CreateModal.vue'; |
48 | 48 | import { deleteConfig, getList, saveConfig } from '/@/api/sys/config'; |
49 | - import { COLUMNS } from './data'; | |
49 | + import { COLUMNS, searchFormSchema } from './data'; | |
50 | 50 | import { useModal } from '/@/components/Modal'; |
51 | 51 | import { useDrawer } from '/@/components/Drawer'; |
52 | 52 | import CostEdit from './costEdit.vue'; |
... | ... | @@ -74,6 +74,10 @@ |
74 | 74 | pagination: false, |
75 | 75 | columns: COLUMNS[props.column!], |
76 | 76 | rowKey: 'id', |
77 | + useSearchForm: props.column === 6 || props.column === 9, | |
78 | + formConfig: { | |
79 | + schemas: props.column === 6 || props.column === 9 ? searchFormSchema : [], | |
80 | + }, | |
77 | 81 | actionColumn: { |
78 | 82 | width: 160, |
79 | 83 | title: 'Action', | ... | ... |
src/views/project/config/costCreate.vue
... | ... | @@ -29,6 +29,12 @@ |
29 | 29 | ><span style="margin-right: 8px; width: 80%">西班牙提成比例:</span> |
30 | 30 | <a-input v-model:value="spainRatio" /> |
31 | 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 | 38 | <!-- <div |
33 | 39 | ><span style="margin-right: 8px; width: 80%">生产提成单价:</span> |
34 | 40 | <a-input v-model:value="price" /> |
... | ... | @@ -65,6 +71,13 @@ |
65 | 71 | const ratio = ref(); |
66 | 72 | const spainRatio = ref(); |
67 | 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 | 81 | // const relationValue = ref(); |
69 | 82 | const customerCode = ref(); |
70 | 83 | const relationValue = ref([ |
... | ... | @@ -89,8 +102,6 @@ |
89 | 102 | // relationValue: '', |
90 | 103 | // }, |
91 | 104 | ]); |
92 | - // const loading = ref(true); | |
93 | - | |
94 | 105 | const { customerCode: customerCodeOptions } = useOrderInfo(orderStore); |
95 | 106 | |
96 | 107 | function handleShow(visible: boolean) { |
... | ... | @@ -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 | 127 | async function handleOk() { |
105 | 128 | try { |
106 | 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 | 132 | await addConfig({ |
110 | 133 | settingCode: 'customerCode', |
111 | 134 | settingName: '客户提成成本配置', |
112 | 135 | settingValue: customerCode.value, |
113 | 136 | settingType: 3, |
114 | 137 | relationCode: 'costSettingItem', |
115 | - relationName: '成本配置项集合', | |
138 | + relationName: year.value, | |
116 | 139 | costSettingItemVOS: relationValue.value, |
117 | 140 | }); |
118 | 141 | emit('modal-success'); |
... | ... | @@ -132,6 +155,8 @@ |
132 | 155 | spainRatio, |
133 | 156 | price, |
134 | 157 | customerCode, |
158 | + year, | |
159 | + yearOptions, | |
135 | 160 | customerCodeOptions, |
136 | 161 | handleOk, |
137 | 162 | }; | ... | ... |
src/views/project/config/costEdit.vue
... | ... | @@ -18,26 +18,30 @@ |
18 | 18 | <a-input v-model:value="fixCost" addonBefore="固定成本 " /> |
19 | 19 | <a-input v-model:value="ratio" addonBefore="提成比例 " /> |
20 | 20 | <a-input v-model:value="spainRatio" addonBefore="西班牙提成比例 " /> |
21 | + <a-input v-model:value="year" :disabled="true" addonBefore="年份 " /> | |
21 | 22 | <!-- <a-input v-model:value="price" addonBefore="生产提成单价" /> --> |
22 | 23 | </a-space> |
23 | 24 | </BasicDrawer> |
24 | 25 | </template> |
25 | 26 | <script lang="ts" setup> |
26 | 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 | 29 | import { saveConfig } from '/@/api/sys/config'; |
30 | 30 | |
31 | - // const emit = defineEmits(['success']); | |
32 | - // const isUpdate = ref(true); | |
33 | 31 | const emit = defineEmits(['success']); |
34 | 32 | |
35 | 33 | const [register, { closeDrawer }] = useDrawerInner((data) => { |
36 | 34 | listAll.value = data.data; |
37 | 35 | relationValue.value = JSON.parse(listAll.value.relationValue); |
38 | 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 | 47 | const listAll = ref(); |
... | ... | @@ -45,12 +49,25 @@ |
45 | 49 | const ratio = ref(); |
46 | 50 | const spainRatio = ref(); |
47 | 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 | 67 | async function handleSubmit() { |
51 | 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 | 71 | await saveConfig({ |
55 | 72 | id: listAll.value.id, |
56 | 73 | settingCode: 'customerCode', |
... | ... | @@ -58,7 +75,7 @@ |
58 | 75 | settingValue: listAll.value.settingValue, |
59 | 76 | settingType: 3, |
60 | 77 | relationCode: 'costSettingItem', |
61 | - relationName: '成本配置项集合', | |
78 | + relationName: year.value, | |
62 | 79 | costSettingItemVOS: relationValue.value, |
63 | 80 | }); |
64 | 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 | 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 | 6 | export const COLUMNS = { |
8 | 7 | 1: [ |
... | ... | @@ -68,6 +67,11 @@ export const COLUMNS = { |
68 | 67 | width: 150, |
69 | 68 | }, |
70 | 69 | { |
70 | + title: '年份', | |
71 | + dataIndex: 'relationName', | |
72 | + width: 150, | |
73 | + }, | |
74 | + { | |
71 | 75 | title: '固定成本', |
72 | 76 | dataIndex: 'relationValue', |
73 | 77 | width: 150, |
... | ... | @@ -82,7 +86,7 @@ export const COLUMNS = { |
82 | 86 | width: 150, |
83 | 87 | customRender: (column) => { |
84 | 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 | 95 | width: 150, |
92 | 96 | customRender: (column) => { |
93 | 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 | 143 | width: 150, |
140 | 144 | }, |
141 | 145 | { |
146 | + title: '年份', | |
147 | + dataIndex: 'relationName', | |
148 | + width: 150, | |
149 | + }, | |
150 | + { | |
142 | 151 | title: '固定成本', |
143 | 152 | dataIndex: 'relationValue', |
144 | 153 | width: 150, |
... | ... | @@ -148,7 +157,7 @@ export const COLUMNS = { |
148 | 157 | }, |
149 | 158 | }, |
150 | 159 | { |
151 | - title: '提成比例', | |
160 | + title: '提成单价', | |
152 | 161 | dataIndex: 'relationValue', |
153 | 162 | width: 150, |
154 | 163 | customRender: (column) => { |
... | ... | @@ -258,3 +267,23 @@ export const columnsProduct: BasicColumn[] = [ |
258 | 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 | 290 | \ No newline at end of file | ... | ... |
src/views/project/config/index.vue
... | ... | @@ -22,7 +22,7 @@ |
22 | 22 | <TablePanel :searchInfo="{ relationCode: 'orderHodTime' }" :column="5" /> |
23 | 23 | </Tabs.TabPane> |
24 | 24 | <Tabs.TabPane key="6" tab="提成成本配置"> |
25 | - <TablePanel :searchInfo="{ relationCode: 'costSettingItem' }" :column="6" /> | |
25 | + <TablePanel :searchInfo="{ relationCode: 'costSettingItem', relationName: currentYear }" :column="6" /> | |
26 | 26 | </Tabs.TabPane> |
27 | 27 | <Tabs.TabPane key="7" tab="销售额配置" v-if="role !== ROLE.FINANCE"> |
28 | 28 | <TablePanel :searchInfo="{ relationCode: 'salesAmount' }" :column="7" /> |
... | ... | @@ -31,7 +31,7 @@ |
31 | 31 | <TablePanel :searchInfo="{ relationCode: 'produHodTime' }" :column="8" /> |
32 | 32 | </Tabs.TabPane> |
33 | 33 | <Tabs.TabPane key="9" tab="生产科固定成本"> |
34 | - <TablePanel :searchInfo="{ relationCode: 'ProduceSettingItem' }" :column="9" /> | |
34 | + <TablePanel :searchInfo="{ relationCode: 'ProduceSettingItem', relationName: currentYear }" :column="9" /> | |
35 | 35 | </Tabs.TabPane> |
36 | 36 | <Tabs.TabPane key="10" tab="客户公司" v-if="role !== ROLE.FINANCE"> |
37 | 37 | <TablePanel :searchInfo="{ relationCode: 'companyConfiguration' }" :column="10" /> |
... | ... | @@ -56,6 +56,7 @@ |
56 | 56 | const orderStore = useOrderStoreWithOut(); |
57 | 57 | const userStore = useUserStoreWithOut(); |
58 | 58 | const user = userStore.getUserInfo; |
59 | + const currentYear = new Date().getFullYear().toString(); | |
59 | 60 | const role = computed(() => { |
60 | 61 | return user?.roleSmallVO?.code; |
61 | 62 | }); | ... | ... |
src/views/project/finance/financeProfit/ProductProfit/InnerData/ApproveReason.vue
... | ... | @@ -32,7 +32,9 @@ |
32 | 32 | orderId: baseFieldValues.value.orderId, |
33 | 33 | productionActualPrice: baseFieldValues.value.productionActualPrice, |
34 | 34 | productionDepartmentPredictPrice: baseFieldValues.value.productionDepartmentPredictPrice, |
35 | - type: 70, | |
35 | + productionDepartmentPredictUnitPrice: baseFieldValues.value.productionDepartmentPredictUnitPrice, | |
36 | + applyRemark: baseFieldValues.value.applyRemark, | |
37 | + type: 90, | |
36 | 38 | }); |
37 | 39 | emit('success'); |
38 | 40 | setTimeout(() => { | ... | ... |
src/views/project/finance/financeProfit/ProductProfit/InnerData/FinanceEdit.vue
... | ... | @@ -9,6 +9,7 @@ |
9 | 9 | @ok="handleSubmit" |
10 | 10 | :showDetailBack="false" |
11 | 11 | okText="保存" |
12 | + @visible-change="handleShow" | |
12 | 13 | showFooter |
13 | 14 | :destroyOnClose="true" |
14 | 15 | > |
... | ... | @@ -19,7 +20,7 @@ |
19 | 20 | <a-input |
20 | 21 | v-model:value="input1" |
21 | 22 | placeholder="请输入" |
22 | - :disabled="status1 === 'LOCKED'" | |
23 | + :disabled="status1 == 'LOCKED'" | |
23 | 24 | auto-size |
24 | 25 | /> |
25 | 26 | <div style="margin: 16px 0"></div> |
... | ... | @@ -27,7 +28,15 @@ |
27 | 28 | <a-input |
28 | 29 | v-model:value="input2" |
29 | 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 | 40 | auto-size |
32 | 41 | /> |
33 | 42 | <div style="margin: 16px 0"></div> |
... | ... | @@ -42,7 +51,7 @@ |
42 | 51 | <script lang="ts" setup> |
43 | 52 | import { BasicDrawer, useDrawerInner } from '@/components/Drawer'; |
44 | 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 | 55 | import { getPackageEdit } from '@/api/project/invoice'; |
47 | 56 | import { useMessage } from '/@/hooks/web/useMessage'; |
48 | 57 | import { ROLE } from './type.d'; |
... | ... | @@ -125,25 +134,37 @@ |
125 | 134 | const update = ref(); |
126 | 135 | const status1 = ref(); |
127 | 136 | const status2 = ref(); |
137 | + const status3 = ref(); | |
128 | 138 | |
129 | 139 | const input1 = ref(); |
130 | 140 | const input2 = ref(); |
141 | + const input3 = ref(); | |
142 | + const orderCount = ref(); | |
131 | 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 | 151 | const [register, { setDrawerProps, closeDrawer }] = useDrawerInner((data) => { |
133 | 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 | 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 | 163 | resetFields(); |
143 | 164 | setDrawerProps({ confirmLoading: false }); |
144 | - setFieldsValue({ | |
145 | - ...toRaw(data.data), | |
146 | - }); | |
165 | + // setFieldsValue({ | |
166 | + // ...toRaw(data.data), | |
167 | + // }); | |
147 | 168 | update.value = data; |
148 | 169 | }); |
149 | 170 | //完成编辑 |
... | ... | @@ -154,16 +175,25 @@ |
154 | 175 | // id: update.value.data.id, |
155 | 176 | // bgUrl: update.value.data.bgUrl, |
156 | 177 | // }; |
157 | - if (!input1.value || !input2.value) { | |
178 | + if (!input1.value || !input2.value || !input3.value) { | |
158 | 179 | error('选项不能为空'); |
159 | 180 | } else { |
160 | 181 | await getPackageEdit({ |
161 | 182 | orderId: id.value, |
162 | 183 | productionDepartmentPredictPrice: input1.value, |
163 | 184 | productionActualPrice: input2.value, |
185 | + orderCount: orderCount.value, | |
186 | + productionDepartmentPredictUnitPrice: input3.value, | |
164 | 187 | }); |
165 | 188 | emit('success'); |
166 | 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 | 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 | 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 | 149 | width: 150, |
142 | 150 | dataIndex: 'productionDepartmentPredictPrice', |
143 | 151 | customRender: (column) => { |
... | ... | @@ -145,9 +153,9 @@ export const COLUMNS = [ |
145 | 153 | }, |
146 | 154 | }, |
147 | 155 | { |
148 | - title: '实际发生费用', | |
156 | + title: '生产科实际花费总金额¥', | |
149 | 157 | dataIndex: 'productionActualPrice', |
150 | - width: 120, | |
158 | + width: 180, | |
151 | 159 | customRender: (column) => { |
152 | 160 | return column.record?.productionActualPrice?.toFixed(2); |
153 | 161 | }, |
... | ... | @@ -158,7 +166,7 @@ export const COLUMNS = [ |
158 | 166 | width: 120, |
159 | 167 | customRender: (column) => { |
160 | 168 | if (column.record?.predictRatio) { |
161 | - return column.record?.predictRatio?.toFixed(2) + '%'; | |
169 | + return (column.record?.predictRatio * 100).toFixed(2) + '%'; | |
162 | 170 | } |
163 | 171 | return column.record?.predictRatio?.toFixed(2); |
164 | 172 | }, |
... | ... | @@ -169,7 +177,7 @@ export const COLUMNS = [ |
169 | 177 | width: 120, |
170 | 178 | customRender: (column) => { |
171 | 179 | if (column.record?.predictAndActualRatio) { |
172 | - return column.record?.predictAndActualRatio?.toFixed(2) + '%'; | |
180 | + return (column.record?.predictAndActualRatio * 100).toFixed(2) + '%'; | |
173 | 181 | } |
174 | 182 | return column.record?.predictAndActualRatio?.toFixed(2); |
175 | 183 | }, |
... | ... | @@ -188,7 +196,7 @@ export const COLUMNS = [ |
188 | 196 | width: 120, |
189 | 197 | customRender: (column) => { |
190 | 198 | if (column.record?.beforeGrossProfitRate) { |
191 | - return column.record?.beforeGrossProfitRate?.toFixed(2) + '%'; | |
199 | + return (column.record?.beforeGrossProfitRate * 100).toFixed(2) + '%'; | |
192 | 200 | } |
193 | 201 | return column.record?.beforeGrossProfitRate?.toFixed(2); |
194 | 202 | }, |
... | ... | @@ -207,11 +215,25 @@ export const COLUMNS = [ |
207 | 215 | width: 120, |
208 | 216 | customRender: (column) => { |
209 | 217 | if (column.record?.grossProfitRate) { |
210 | - return column.record?.grossProfitRate?.toFixed(2) + '%'; | |
218 | + return (column.record?.grossProfitRate * 100).toFixed(2) + '%'; | |
211 | 219 | } |
212 | 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 | 238 | // title: '内部生产固定成本¥', |
217 | 239 | // dataIndex: 'innerProductionFixedCost', | ... | ... |
src/views/project/finance/financeProfit/ProductProfit/InnerData/index.vue
1 | 1 | <template> |
2 | 2 | <div> |
3 | 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 | 23 | <template #bodyCell="{ column, record }"> |
5 | 24 | <template v-if="column.key === 'picUrl'"> |
6 | 25 | <img :z-index="100000" :width="50" :height="50" :src="record?.picUrl" /> |
7 | 26 | </template> |
8 | 27 | <template v-if="column.key === 'action'"> |
9 | - <TableAction :actions="createActions(record)" /> | |
28 | + <TableAction :actions="createActions(record)" :dropDownActions="createDropActions(record)" /> | |
10 | 29 | </template> |
11 | 30 | <!-- <template v-if="column.key === 'relationValue'"> |
12 | 31 | <a-input |
... | ... | @@ -19,6 +38,15 @@ |
19 | 38 | </span> |
20 | 39 | </template> --> |
21 | 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 | 50 | </BasicTable> |
23 | 51 | <!-- <BasicModal |
24 | 52 | title="拒绝原因" |
... | ... | @@ -32,28 +60,48 @@ |
32 | 60 | <a-textarea :rows="6" placeholder="请输入拒绝原因" v-model:value="message" /> |
33 | 61 | </div> |
34 | 62 | </BasicModal> --> |
35 | - <CheckDetail @register="checkModalRegister" /> | |
63 | + <CheckDetail @register="checkModalRegister" :onGoFormDetail="handleGoFormDetail" /> | |
36 | 64 | <FinanceEdit @register="registerFinanceEdit" @success="handleSuccess" /> |
65 | + <HistoryDetail @register="registerHistoryDetail" /> | |
37 | 66 | </div> |
38 | 67 | </template> |
39 | 68 | <script setup lang="ts"> |
40 | 69 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; |
41 | - import { getInnerProfit } from '@/api/project/invoice'; | |
70 | + import { getInnerProfit, setInnerStatus } from '@/api/project/invoice'; | |
42 | 71 | import { searchFormSchema, COLUMNS } from './data'; |
43 | 72 | import { BasicModal, useModal } from '/@/components/Modal'; |
44 | 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 | 76 | import { useDrawer } from '/@/components/Drawer'; |
47 | 77 | import FinanceEdit from './FinanceEdit.vue'; |
48 | 78 | import CheckDetail from './CheckDetail.vue'; |
79 | + import HistoryDetail from './HistoryDetail.vue'; | |
49 | 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 | 85 | const { createMessage } = useMessage(); |
52 | 86 | const { error } = createMessage; |
53 | 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 | 96 | const orderStore = useOrderStoreWithOut(); |
55 | 97 | const [checkModalRegister, { openDrawer: openCheckDetailDrawer }] = useDrawer(); |
56 | 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 | 105 | const handleOk = (record) => { |
58 | 106 | // 修改父组件的状态 |
59 | 107 | closeModal(); |
... | ... | @@ -63,11 +111,28 @@ |
63 | 111 | message.value = ''; |
64 | 112 | } |
65 | 113 | }; |
66 | - const [registerTable, { reload }] = useTable({ | |
114 | + const [registerTable, { reload, setSelectedRowKeys, getForm }] = useTable({ | |
67 | 115 | api: getInnerProfit, |
68 | 116 | bordered: true, |
69 | 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 | 136 | formConfig: { |
72 | 137 | labelWidth: 120, |
73 | 138 | schemas: searchFormSchema, |
... | ... | @@ -80,7 +145,7 @@ |
80 | 145 | setting: false, |
81 | 146 | }, |
82 | 147 | actionColumn: { |
83 | - width: 240, | |
148 | + width: 260, | |
84 | 149 | title: 'Action', |
85 | 150 | dataIndex: 'action', |
86 | 151 | }, |
... | ... | @@ -111,6 +176,18 @@ |
111 | 176 | // }, |
112 | 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 | 193 | return [ |
... | ... | @@ -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 | 220 | onMounted(async () => { |
132 | 221 | await orderStore.getDict(); |
133 | 222 | }); |
... | ... | @@ -175,5 +264,224 @@ |
175 | 264 | reload(); |
176 | 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 | 486 | </script> |
179 | 487 | <style></style> | ... | ... |
src/views/project/finance/financeProfit/ProductProfit/InnerData/tableData.tsx
... | ... | @@ -34,6 +34,13 @@ export const FIELDS_BASE_INFO = [ |
34 | 34 | label: '实际发生费用', |
35 | 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 | 46 | export const EDIT_INFO = [ |
... | ... | @@ -58,5 +65,12 @@ export const EDIT_INFO = [ |
58 | 65 | label: '实际发生费用', |
59 | 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 | 3 | <BasicDrawer |
4 | 4 | @register="register" |
5 | 5 | v-bind="$attrs" |
6 | - title="收入款单" | |
6 | + title="编辑" | |
7 | 7 | width="30%" |
8 | 8 | :isDetail="true" |
9 | 9 | @ok="handleSubmit" |
10 | 10 | :showDetailBack="false" |
11 | 11 | okText="保存" |
12 | + @visible-change="handleShow" | |
12 | 13 | showFooter |
13 | 14 | :destroyOnClose="true" |
14 | 15 | > |
15 | 16 | <!-- <div> |
16 | 17 | <BasicForm @register="registerForm" /> |
17 | 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 | 26 | <div style="margin: 16px 0"></div> |
24 | 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 | 29 | <div style="margin: 16px 0"></div> |
27 | 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 | 56 | <div style="margin: 16px 0"></div> |
30 | - | |
31 | 57 | <!-- <template #titleToolbar> <a-button type="primary"> 申请编辑权限 </a-button></template> --> |
32 | 58 | <template #appendFooter> |
33 | 59 | <!-- <a-button type="primary" @click="onGoCheckDetail"> 申请权限</a-button> --> |
... | ... | @@ -39,10 +65,11 @@ |
39 | 65 | import { BasicDrawer, useDrawerInner } from '@/components/Drawer'; |
40 | 66 | import { BasicForm, FormSchema, useForm } from '@/components/Form'; |
41 | 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 | 69 | import { useMessage } from '/@/hooks/web/useMessage'; |
45 | 70 | import { ROLE } from './type.d'; |
71 | + import type { Dayjs } from 'dayjs'; | |
72 | + import dayjs from 'dayjs'; | |
46 | 73 | |
47 | 74 | const emit = defineEmits(['success']); |
48 | 75 | const role = computed(() => { |
... | ... | @@ -59,16 +86,16 @@ |
59 | 86 | // label: '实际应收金额', |
60 | 87 | // }, |
61 | 88 | { |
62 | - field: 'actualPayedAmount1', | |
89 | + field: 'developmentCopyRmbTotalPrice', | |
63 | 90 | component: 'InputNumber', |
64 | 91 | labelWidth: 250, |
65 | 92 | colProps: { |
66 | 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 | 101 | field: 'actualPayedAmount2', |
... | ... | @@ -77,9 +104,7 @@ |
77 | 104 | colProps: { |
78 | 105 | span: 23, |
79 | 106 | }, |
80 | - componentProps: () => ({ | |
81 | - disabled: status.value === 10, | |
82 | - }), | |
107 | + | |
83 | 108 | label: '实际应收金额2$', |
84 | 109 | }, |
85 | 110 | { |
... | ... | @@ -89,9 +114,7 @@ |
89 | 114 | colProps: { |
90 | 115 | span: 23, |
91 | 116 | }, |
92 | - componentProps: () => ({ | |
93 | - disabled: status.value === 10, | |
94 | - }), | |
117 | + | |
95 | 118 | label: '实际应收金额3$', |
96 | 119 | }, |
97 | 120 | { |
... | ... | @@ -101,9 +124,7 @@ |
101 | 124 | colProps: { |
102 | 125 | span: 23, |
103 | 126 | }, |
104 | - componentProps: () => ({ | |
105 | - disabled: status.value === 10, | |
106 | - }), | |
127 | + | |
107 | 128 | label: '其他费用金额$', |
108 | 129 | }, |
109 | 130 | ]; |
... | ... | @@ -120,21 +141,60 @@ |
120 | 141 | const { error } = createMessage; |
121 | 142 | |
122 | 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 | 151 | const input1 = ref(); |
126 | 152 | const input2 = ref(); |
127 | 153 | const input3 = ref(); |
128 | 154 | const input4 = ref(); |
155 | + | |
156 | + const input5 = ref(); | |
157 | + const input6 = ref(); | |
129 | 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 | 180 | const [register, { setDrawerProps, closeDrawer }] = useDrawerInner((data) => { |
131 | 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 | 198 | resetFields(); |
139 | 199 | setDrawerProps({ confirmLoading: false }); |
140 | 200 | setFieldsValue({ |
... | ... | @@ -150,18 +210,26 @@ |
150 | 210 | // id: update.value.data.id, |
151 | 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 | 214 | error('选项不能为空'); |
155 | 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 | 221 | emit('success'); |
164 | 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 | 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 | 113 | dataIndex: 'orderCount', |
114 | 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 | 125 | title: '生产科总价¥', |
126 | 126 | dataIndex: 'productionDepartmentTotalPrice', |
... | ... | @@ -151,7 +151,7 @@ export const COLUMNS = [ |
151 | 151 | width: 120, |
152 | 152 | customRender: (column) => { |
153 | 153 | if (column.record?.predictRatio) { |
154 | - return column.record?.predictRatio?.toFixed(2) + '%'; | |
154 | + return (column.record?.predictRatio * 100).toFixed(2) + '%'; | |
155 | 155 | } |
156 | 156 | return column.record?.predictRatio?.toFixed(2); |
157 | 157 | }, |
... | ... | @@ -162,7 +162,7 @@ export const COLUMNS = [ |
162 | 162 | width: 190, |
163 | 163 | customRender: (column) => { |
164 | 164 | if (column.record?.predictAndActualRatio) { |
165 | - return column.record?.predictAndActualRatio?.toFixed(2) + '%'; | |
165 | + return (column.record?.predictAndActualRatio * 100).toFixed(2) + '%'; | |
166 | 166 | } |
167 | 167 | return column.record?.predictAndActualRatio?.toFixed(2); |
168 | 168 | }, |
... | ... | @@ -181,7 +181,7 @@ export const COLUMNS = [ |
181 | 181 | width: 120, |
182 | 182 | customRender: (column) => { |
183 | 183 | if (column.record?.beforeGrossProfitRate) { |
184 | - return column.record?.beforeGrossProfitRate?.toFixed(2) + '%'; | |
184 | + return (column.record?.beforeGrossProfitRate * 100).toFixed(2) + '%'; | |
185 | 185 | } |
186 | 186 | return column.record?.beforeGrossProfitRate?.toFixed(2); |
187 | 187 | }, |
... | ... | @@ -200,7 +200,7 @@ export const COLUMNS = [ |
200 | 200 | width: 120, |
201 | 201 | customRender: (column) => { |
202 | 202 | if (column.record?.grossProfitRate) { |
203 | - return column.record?.grossProfitRate?.toFixed(2) + '%'; | |
203 | + return (column.record?.grossProfitRate * 100).toFixed(2) + '%'; | |
204 | 204 | } |
205 | 205 | return column.record?.grossProfitRate?.toFixed(2); |
206 | 206 | }, |
... | ... | @@ -235,12 +235,27 @@ export const COLUMNS = [ |
235 | 235 | width: 150, |
236 | 236 | customRender: (column) => { |
237 | 237 | if (column.record?.innerProductionProfitRate) { |
238 | - return column.record?.innerProductionProfitRate?.toFixed(2) + '%'; | |
238 | + return (column.record?.innerProductionProfitRate * 100).toFixed(2) + '%'; | |
239 | 239 | } |
240 | 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 | 259 | title: '文件', |
245 | 260 | dataIndex: 'fileUrl', |
246 | 261 | width: 120, | ... | ... |
src/views/project/finance/financeProfit/ProductProfit/InnerProduce/index.vue
1 | 1 | <template> |
2 | 2 | <div> |
3 | 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 | 23 | <template #bodyCell="{ column, record }"> |
5 | 24 | <template v-if="column.key === 'picUrl'"> |
6 | 25 | <img :z-index="100000" :width="50" :height="50" :src="record?.picUrl" /> |
7 | 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 | 33 | <!-- <template v-if="column.key === 'relationValue'"> |
12 | 34 | <a-input |
13 | 35 | v-if="record.settingValue === 'A01'" |
... | ... | @@ -19,6 +41,15 @@ |
19 | 41 | </span> |
20 | 42 | </template> --> |
21 | 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 | 53 | </BasicTable> |
23 | 54 | <!-- <BasicModal |
24 | 55 | title="拒绝原因" |
... | ... | @@ -32,25 +63,44 @@ |
32 | 63 | <a-textarea :rows="6" placeholder="请输入拒绝原因" v-model:value="message" /> |
33 | 64 | </div> |
34 | 65 | </BasicModal> --> |
66 | + <CheckDetail @register="checkModalRegister" :onGoFormDetail="handleGoFormDetail" /> | |
35 | 67 | <FinanceEdit @register="registerFinanceEdit" @success="handleSuccess" /> |
68 | + <HistoryDetail @register="registerHistoryDetail" /> | |
36 | 69 | </div> |
37 | 70 | </template> |
38 | 71 | <script setup lang="ts"> |
39 | 72 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; |
40 | - import { getInnerProduceProfit } from '@/api/project/invoice'; | |
73 | + import { getInnerProduceProfit, setInnerProfitSetStatus } from '@/api/project/invoice'; | |
41 | 74 | import { searchFormSchema, COLUMNS } from './data'; |
42 | 75 | import { BasicModal, useModal } from '/@/components/Modal'; |
43 | 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 | 79 | import { useDrawer } from '/@/components/Drawer'; |
46 | 80 | import FinanceEdit from './FinanceEdit.vue'; |
81 | + import CheckDetail from './CheckDetail.vue'; | |
82 | + import HistoryDetail from './HistoryDetail.vue'; | |
47 | 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 | 88 | const { createMessage } = useMessage(); |
50 | 89 | const { error } = createMessage; |
51 | 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 | 95 | const orderStore = useOrderStoreWithOut(); |
96 | + const [checkModalRegister, { openDrawer: openCheckDetailDrawer }] = useDrawer(); | |
53 | 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 | 104 | const handleOk = (record) => { |
55 | 105 | // 修改父组件的状态 |
56 | 106 | closeModal(); |
... | ... | @@ -60,12 +110,18 @@ |
60 | 110 | message.value = ''; |
61 | 111 | } |
62 | 112 | }; |
63 | - const [registerTable, { reload }] = useTable({ | |
113 | + const [registerTable, { reload, setSelectedRowKeys }] = useTable({ | |
64 | 114 | api: getInnerProduceProfit, |
65 | 115 | bordered: true, |
66 | 116 | columns: COLUMNS, |
67 | 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 | 125 | formConfig: { |
70 | 126 | labelWidth: 120, |
71 | 127 | schemas: searchFormSchema, |
... | ... | @@ -77,50 +133,79 @@ |
77 | 133 | tableSetting: { |
78 | 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 | 210 | onMounted(async () => { |
126 | 211 | await orderStore.getDict(); |
... | ... | @@ -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 | 226 | async function handleSave(record) { |
141 | 227 | await saveConfig({ id: record.id, relationValue: record.relationValue }); |
... | ... | @@ -154,8 +240,170 @@ |
154 | 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 | 407 | reload(); |
160 | 408 | } |
161 | 409 | </script> | ... | ... |
src/views/project/finance/financeProfit/ProductProfit/InnerProduce/tableData.tsx
... | ... | @@ -21,74 +21,18 @@ const orderStore = useOrderStoreWithOut(); |
21 | 21 | // 基本信息 |
22 | 22 | export const FIELDS_BASE_INFO = [ |
23 | 23 | { |
24 | - field: 'customerCode', | |
24 | + field: 'projectInnerProfitInfoStartTime', | |
25 | 25 | component: 'Select', |
26 | 26 | labelWidth: 150, |
27 | - label: '客户编码', | |
27 | + label: '项目开始时间', | |
28 | 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 | 32 | component: 'Select', |
40 | - // componentProps: { | |
41 | - // options: productionDepartmentOptions, | |
42 | - // }, | |
43 | 33 | labelWidth: 150, |
44 | - label: '生产科', | |
34 | + label: '项目结束时间', | |
45 | 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 | 32 | orderId: baseFieldValues.value.orderId, |
33 | 33 | packetActualRmbTotalPrice: baseFieldValues.value.packetActualRmbTotalPrice, |
34 | 34 | applyRemark: baseFieldValues.value.applyRemark, |
35 | - type: 60, | |
35 | + type: 80, | |
36 | 36 | }); |
37 | 37 | emit('success'); |
38 | 38 | setTimeout(() => { | ... | ... |
src/views/project/finance/financeProfit/ServiceProfit/PackageProfit/FinanceEdit.vue
... | ... | @@ -122,7 +122,7 @@ |
122 | 122 | const [register, { setDrawerProps, closeDrawer }] = useDrawerInner((data) => { |
123 | 123 | // 方式1 |
124 | 124 | if (data.data.lockFields) { |
125 | - status.value = data.data.lockFields?.packetActualRmbPrice; | |
125 | + status.value = data.data.lockFields?.packetActualRmbTotalPrice; | |
126 | 126 | } |
127 | 127 | id.value = data.data.orderId; |
128 | 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 | 182 | width: 140, |
183 | 183 | customRender: (column) => { |
184 | 184 | if (column.record?.packetProfitRate) { |
185 | - return column.record?.packetProfitRate?.toFixed(2) + '%'; | |
185 | + return (column.record?.packetProfitRate * 100).toFixed(2) + '%'; | |
186 | 186 | } |
187 | 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 | 205 | \ No newline at end of file | ... | ... |
src/views/project/finance/financeProfit/ServiceProfit/PackageProfit/index.vue
1 | 1 | <template> |
2 | 2 | <div> |
3 | 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 | 23 | <template #bodyCell="{ column, record }"> |
5 | 24 | <template v-if="column.key === 'picUrl'"> |
6 | 25 | <img :z-index="100000" :width="50" :height="50" :src="record?.picUrl" /> |
7 | 26 | </template> |
8 | 27 | <template v-if="column.key === 'action'"> |
9 | - <TableAction :actions="createActions(record)" /> | |
28 | + <TableAction | |
29 | + :actions="createActions(record)" | |
30 | + :dropDownActions="createDropActions(record)" | |
31 | + /> | |
10 | 32 | </template> |
11 | 33 | <!-- <template v-if="column.key === 'relationValue'"> |
12 | 34 | <a-input |
... | ... | @@ -19,6 +41,15 @@ |
19 | 41 | </span> |
20 | 42 | </template> --> |
21 | 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 | 53 | </BasicTable> |
23 | 54 | <!-- <BasicModal |
24 | 55 | title="拒绝原因" |
... | ... | @@ -34,27 +65,47 @@ |
34 | 65 | </BasicModal> --> |
35 | 66 | <CheckDetail @register="checkModalRegister" :onGoFormDetail="handleGoFormDetail" /> |
36 | 67 | <FinanceEdit @register="registerFinanceEdit" @success="handleSuccess" /> |
68 | + <HistoryDetail @register="registerHistoryDetail" /> | |
37 | 69 | </div> |
38 | 70 | </template> |
39 | 71 | <script setup lang="ts"> |
40 | 72 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; |
41 | - import { getPackageProfit } from '@/api/project/invoice'; | |
73 | + import { getPackageProfit, setPackStatus } from '@/api/project/invoice'; | |
42 | 74 | import { searchFormSchema, COLUMNS } from './data'; |
43 | 75 | import { BasicModal, useModal } from '/@/components/Modal'; |
44 | 76 | import { useMessage } from '/@/hooks/web/useMessage'; |
45 | - import { onMounted, ref } from 'vue'; | |
77 | + import { onMounted, ref, computed } from 'vue'; | |
46 | 78 | import { useDrawer } from '/@/components/Drawer'; |
47 | 79 | import FinanceEdit from './FinanceEdit.vue'; |
48 | 80 | import CheckDetail from './CheckDetail.vue'; |
81 | + import HistoryDetail from './HistoryDetail.vue'; | |
82 | + import axios from 'axios'; | |
49 | 83 | import { FilePptOutlined } from '@ant-design/icons-vue'; |
50 | 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 | 89 | const { createMessage } = useMessage(); |
53 | 90 | const { error } = createMessage; |
54 | 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 | 100 | const orderStore = useOrderStoreWithOut(); |
56 | 101 | const [checkModalRegister, { openDrawer: openCheckDetailDrawer }] = useDrawer(); |
57 | 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 | 109 | const handleOk = (record) => { |
59 | 110 | // 修改父组件的状态 |
60 | 111 | closeModal(); |
... | ... | @@ -64,16 +115,34 @@ |
64 | 115 | message.value = ''; |
65 | 116 | } |
66 | 117 | }; |
67 | - const [registerTable, { reload }] = useTable({ | |
118 | + const [registerTable, { reload, setSelectedRowKeys, getForm }] = useTable({ | |
68 | 119 | api: getPackageProfit, |
69 | 120 | bordered: true, |
70 | 121 | columns: COLUMNS, |
71 | - rowKey: 'id', | |
122 | + rowKey: (record) => record.orderId, | |
72 | 123 | formConfig: { |
73 | 124 | labelWidth: 120, |
74 | 125 | schemas: searchFormSchema, |
75 | 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 | 146 | useSearchForm: true, |
78 | 147 | showTableSetting: true, |
79 | 148 | showIndexColumn: false, |
... | ... | @@ -81,7 +150,7 @@ |
81 | 150 | setting: false, |
82 | 151 | }, |
83 | 152 | actionColumn: { |
84 | - width: 240, | |
153 | + width: 260, | |
85 | 154 | title: 'Action', |
86 | 155 | dataIndex: 'action', |
87 | 156 | }, |
... | ... | @@ -113,6 +182,18 @@ |
113 | 182 | // }, |
114 | 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 | 199 | return [ |
... | ... | @@ -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 | 226 | function handleFinanceEdit(record) { |
138 | 227 | openFinanceEdit(true, { |
... | ... | @@ -176,5 +265,218 @@ |
176 | 265 | // await deleteConfig({ ids: [record.id] }); |
177 | 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 | 481 | </script> |
180 | 482 | <style></style> | ... | ... |
src/views/project/finance/financeProfit/ServiceProfit/ServiceProfit/ApproveReason.vue
... | ... | @@ -37,6 +37,7 @@ |
37 | 37 | projectEndTime: baseFieldValues.value.projectEndTime, |
38 | 38 | spainPaidRmbCommission: baseFieldValues.value.spainPaidRmbCommission, |
39 | 39 | applyRemark: baseFieldValues.value.applyRemark, |
40 | + type: 'FIELD_EDIT_APPLY', | |
40 | 41 | }); |
41 | 42 | emit('success'); |
42 | 43 | setTimeout(() => { | ... | ... |
src/views/project/finance/financeProfit/ServiceProfit/ServiceProfit/FinanceEdit.vue
... | ... | @@ -9,6 +9,7 @@ |
9 | 9 | @ok="handleSubmit" |
10 | 10 | :showDetailBack="false" |
11 | 11 | okText="保存" |
12 | + @visible-change="handleShow" | |
12 | 13 | showFooter |
13 | 14 | :destroyOnClose="true" |
14 | 15 | > |
... | ... | @@ -45,14 +46,6 @@ |
45 | 46 | auto-size |
46 | 47 | /> |
47 | 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 | 49 | <!-- <template #titleToolbar> <a-button type="primary"> 申请编辑权限 </a-button></template> --> |
57 | 50 | <template #appendFooter> |
58 | 51 | <!-- <a-button type="primary" @click="onGoCheckDetail"> 申请权限</a-button> --> |
... | ... | @@ -145,16 +138,13 @@ |
145 | 138 | const status3 = ref(); |
146 | 139 | const status4 = ref(); |
147 | 140 | const status5 = ref(); |
148 | - const status6 = ref(); | |
149 | 141 | |
150 | 142 | const input1 = ref(); |
151 | 143 | const input2 = ref(); |
152 | 144 | const input3 = ref(); |
153 | - // const input4 = ref(); | |
154 | - const input4 = ref(dayjs('2013-12-01')); | |
145 | + const input4 = ref(); | |
155 | 146 | |
156 | 147 | const input5 = ref(); |
157 | - const input6 = ref(); | |
158 | 148 | const id = ref(); |
159 | 149 | // function formatDate(dateStr: string): string { |
160 | 150 | // const date = new Date(dateStr); |
... | ... | @@ -185,16 +175,14 @@ |
185 | 175 | status3.value = data?.data?.lockFields?.projectStartTime; |
186 | 176 | status4.value = data?.data?.lockFields?.projectEndTime; |
187 | 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 | 179 | id.value = data?.data?.projectNoPrefix; |
192 | 180 | input1.value = data?.data?.developmentCopyRmbTotalPrice.toFixed(2); |
193 | 181 | input2.value = data?.data?.spainPaidRmbCommission.toFixed(2); |
194 | 182 | input3.value = dayjs(formatDateToDateOnly(data?.data?.projectStartTime)); |
195 | 183 | input4.value = dayjs(formatDateToDateOnly(data?.data?.projectEndTime)); |
196 | 184 | input5.value = data?.data?.paidRmbCommission.toFixed(2); |
197 | - input6.value = data?.data?.actualExchangeRate.toFixed(2); | |
185 | + | |
198 | 186 | resetFields(); |
199 | 187 | setDrawerProps({ confirmLoading: false }); |
200 | 188 | setFieldsValue({ |
... | ... | @@ -220,10 +208,18 @@ |
220 | 208 | projectStartTime: input3.value, |
221 | 209 | projectEndTime: input4.value, |
222 | 210 | paidRmbCommission: input5.value, |
223 | - actualExchangeRate: input6.value, | |
224 | 211 | }); |
225 | 212 | emit('success'); |
226 | 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 | 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 | 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 | 115 | title: '客户总金额¥', |
108 | 116 | width: 150, |
109 | 117 | dataIndex: 'customerTotalPrice', |
... | ... | @@ -132,7 +140,7 @@ export const COLUMNS = [ |
132 | 140 | dataIndex: 'packetTotalPrice', |
133 | 141 | width: 150, |
134 | 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 | 237 | width: 120, |
230 | 238 | customRender: (column) => { |
231 | 239 | if (column.record?.profitRate) { |
232 | - return column.record?.profitRate?.toFixed(2) + '%'; | |
240 | + return (column.record?.profitRate * 100).toFixed(2) + '%'; | |
233 | 241 | } |
234 | 242 | return column.record?.profitRate?.toFixed(2); |
235 | 243 | }, |
... | ... | @@ -248,7 +256,7 @@ export const COLUMNS = [ |
248 | 256 | width: 120, |
249 | 257 | customRender: (column) => { |
250 | 258 | if (column.record?.developmentProfitRate) { |
251 | - return column.record?.developmentProfitRate?.toFixed(2) + '%'; | |
259 | + return (column.record?.developmentProfitRate * 100).toFixed(2) + '%'; | |
252 | 260 | } |
253 | 261 | return column.record?.developmentProfitRate?.toFixed(2); |
254 | 262 | }, |
... | ... | @@ -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 | 281 | title: '实际跟单单价¥', |
282 | 282 | dataIndex: 'actualOrderRmbPrice', |
283 | 283 | width: 160, |
... | ... | @@ -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 | 305 | title: '综合收益¥', |
322 | 306 | dataIndex: 'comprehensiveProfit', |
323 | 307 | width: 120, |
... | ... | @@ -380,4 +364,18 @@ export const COLUMNS = [ |
380 | 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 | 382 | \ No newline at end of file | ... | ... |
src/views/project/finance/financeProfit/ServiceProfit/ServiceProfit/index.vue
1 | 1 | <template> |
2 | 2 | <div> |
3 | 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 | 23 | <template #bodyCell="{ column, record }"> |
5 | 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 | 39 | </template> |
19 | 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 | 41 | <CheckDetail @register="checkModalRegister" :onGoFormDetail="handleGoFormDetail" /> |
33 | 42 | <FinanceEdit @register="registerFinanceEdit" @success="handleSuccess" /> |
43 | + <HistoryDetail @register="registerHistoryDetail" /> | |
34 | 44 | </div> |
35 | 45 | </template> |
36 | 46 | <script setup lang="ts"> |
37 | 47 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; |
38 | - import { getServiceProfit } from '@/api/project/invoice'; | |
48 | + import { getServiceProfit, setBusinessProfitSetStatus } from '@/api/project/invoice'; | |
39 | 49 | import { searchFormSchema, COLUMNS } from './data'; |
40 | - import { BasicModal, useModal } from '/@/components/Modal'; | |
50 | + import axios from 'axios'; | |
41 | 51 | import { useMessage } from '/@/hooks/web/useMessage'; |
42 | - import { onMounted, ref } from 'vue'; | |
52 | + import { onMounted, ref, computed, unref } from 'vue'; | |
43 | 53 | import { useDrawer } from '/@/components/Drawer'; |
44 | 54 | import FinanceEdit from './FinanceEdit.vue'; |
55 | + import HistoryDetail from './HistoryDetail.vue'; | |
45 | 56 | import CheckDetail from './CheckDetail.vue'; |
57 | + import { useUserStoreWithOut } from '/@/store/modules/user'; | |
58 | + import { ROLE } from '../../../type.d'; | |
46 | 59 | import { useOrderStoreWithOut } from '/@/store/modules/order'; |
47 | 60 | |
48 | 61 | const { createMessage } = useMessage(); |
49 | - const { error } = createMessage; | |
50 | 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 | 67 | const orderStore = useOrderStoreWithOut(); |
52 | 68 | const [checkModalRegister, { openDrawer: openCheckDetailDrawer }] = useDrawer(); |
53 | 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 | 78 | api: getServiceProfit, |
61 | 79 | bordered: true, |
62 | 80 | columns: COLUMNS, |
63 | 81 | clickToRowSelect: false, |
64 | - rowKey: 'id', | |
65 | 82 | formConfig: { |
66 | 83 | labelWidth: 120, |
67 | 84 | schemas: searchFormSchema, |
68 | 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 | 94 | useSearchForm: true, |
71 | 95 | showTableSetting: true, |
72 | 96 | showIndexColumn: false, |
... | ... | @@ -74,7 +98,7 @@ |
74 | 98 | setting: false, |
75 | 99 | }, |
76 | 100 | actionColumn: { |
77 | - width: 240, | |
101 | + width: 260, | |
78 | 102 | title: 'Action', |
79 | 103 | dataIndex: 'action', |
80 | 104 | }, |
... | ... | @@ -82,31 +106,29 @@ |
82 | 106 | |
83 | 107 | function createActions(record: any): any[] { |
84 | 108 | if (!record.editable) { |
85 | - return [ | |
109 | + const actions = [ | |
86 | 110 | { |
87 | 111 | label: '财务编辑', |
88 | 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 | 115 | label: '申请权限', |
103 | - // popConfirm: { | |
104 | - // title: '确认申请?', | |
105 | - // confirm: handleFalse.bind(null, record), | |
106 | - // }, | |
107 | 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 | 133 | return [ |
112 | 134 | { |
... | ... | @@ -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 | 159 | onMounted(async () => { |
127 | 160 | await orderStore.getDict(); |
... | ... | @@ -139,11 +172,6 @@ |
139 | 172 | return false; |
140 | 173 | } |
141 | 174 | |
142 | - // async function handleFalse(record: any) { | |
143 | - // console.log(record); | |
144 | - // // openModal(true, { record }); | |
145 | - // } | |
146 | - | |
147 | 175 | function handleSuccess() { |
148 | 176 | setTimeout(() => { |
149 | 177 | reload(); |
... | ... | @@ -155,21 +183,185 @@ |
155 | 183 | handleCancel(record); |
156 | 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 | 187 | function handleCancel(record) { |
167 | 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 | 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 | 366 | </script> |
175 | 367 | <style></style> | ... | ... |
src/views/project/finance/financeProfit/ServiceProfit/ServiceProfit/tableData.tsx
... | ... | @@ -55,12 +55,4 @@ export const FIELDS_BASE_INFO = [ |
55 | 55 | label: '中国团队已发提成¥', |
56 | 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 | 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 | 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 | 30 | }, |
31 | 31 | }, |
32 | 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 | 50 | changeOrigin: true, |
36 | 51 | ws: true, |
37 | 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 | 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 | 60 | changeOrigin: true, |
54 | 61 | ws: true, |
55 | 62 | // rewrite: (path) => { | ... | ... |