Commit f267cff7999d05e481ae22a9c1aa3aa7641c38f6
1 parent
cbe36709
feat: 历史记录
Showing
17 changed files
with
1240 additions
and
55 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,7 @@ export const getApprovedListApi = async (params: any) => { |
44 | 43 | res.records = res.records.map((item) => { |
45 | 44 | return item; |
46 | 45 | }); |
47 | - | |
46 | + console.log(res, '56567ressss'); | |
48 | 47 | return new Promise((resolve) => { |
49 | 48 | resolve({ items: res.records, total: res.total }); |
50 | 49 | }); | ... | ... |
src/api/project/invoice.ts
... | ... | @@ -50,6 +50,12 @@ enum Api { |
50 | 50 | SERVICEAPPLYEDIT = '/project/applyEditFileds', //申请修改 |
51 | 51 | APPLYLIST = '/project/pageProjectLockFieldApply', //分页查询项目字段申请记录 |
52 | 52 | AUDITAPPLY = '/project/audit', //审核 |
53 | + ACTIONRECORD = '/projectOptLog/listByPage', //业务/内部研发净利润操作记录以及申请记录 | |
54 | + ORDERCOSTDETAILEDOPTLOG = '/orderCostDetailedOptLog/listByPage', //包装费用明细/内部生产明细操作记录表 | |
55 | + ORDERCOSTDETAILEDEXPORT = '/project/businessProfit/exportExcel', //业务研发净利润分析表导出 | |
56 | + INNERPRODUCEPROFITEXPORT = '/project/innerProfitInfo/exportExcel', //内部生产净利润分析表导出 | |
57 | + BUSINESSPROFITDETAIL = '/order/cost/businessProfitDetail/exportExcel', //包装费用明细导出 | |
58 | + INNERPROFITDETAIL = '/order/cost/innerProfitDetail/exportExcel', //内部生产明细导出 | |
53 | 59 | } |
54 | 60 | |
55 | 61 | export const getRefundDate = async (params: any, data?: any) => { |
... | ... | @@ -427,18 +433,30 @@ export const getServiceApplyEdit = async (params: any) => { |
427 | 433 | }; |
428 | 434 | |
429 | 435 | export const getApplyList = async (params: any) => { |
430 | - const res = ref(); | |
431 | - res.value = await defHttp.post<any>({ | |
436 | + // const res = ref(); | |
437 | + // res.value = await defHttp.post<any>({ | |
438 | + // url: Api.APPLYLIST, | |
439 | + // params, | |
440 | + // }); | |
441 | + // res.value.data.records.forEach((record) => { | |
442 | + // const jsonObj = JSON.parse(record?.fields); | |
443 | + // if (jsonObj) { | |
444 | + // record.fields = jsonObj; | |
445 | + // } | |
446 | + // }); | |
447 | + // return res.value.data.records; | |
448 | + const data = await defHttp.post({ | |
432 | 449 | url: Api.APPLYLIST, |
433 | 450 | params, |
434 | 451 | }); |
435 | - res.value.data.records.forEach((record) => { | |
436 | - const jsonObj = JSON.parse(record?.fields); | |
437 | - if (jsonObj) { | |
438 | - record.fields = jsonObj; | |
439 | - } | |
452 | + const res = data.data; | |
453 | + res.records = res.records.map((item) => { | |
454 | + return item; | |
455 | + }); | |
456 | + | |
457 | + return new Promise((resolve) => { | |
458 | + resolve({ items: res.records, total: res.total }); | |
440 | 459 | }); |
441 | - return res.value.data.records; | |
442 | 460 | }; |
443 | 461 | |
444 | 462 | export const getAuditApply = async (params: any) => { |
... | ... | @@ -461,3 +479,70 @@ export const checkDeleteDeduct = async (params: any) => { |
461 | 479 | params, |
462 | 480 | }); |
463 | 481 | }; |
482 | + | |
483 | +export const getProjectOptLog = async (params: any) => { | |
484 | + const res = await defHttp.post<any>({ | |
485 | + url: Api.ACTIONRECORD, | |
486 | + params, | |
487 | + }); | |
488 | + const formattedRecords = res.records.map((record: any) => { | |
489 | + return { | |
490 | + ...record, | |
491 | + }; | |
492 | + }); | |
493 | + const orderStore = useOrderStoreWithOut(); | |
494 | + orderStore.setTotal(res.total); | |
495 | + orderStore.setQueryVO(params); | |
496 | + return new Promise((resolve) => { | |
497 | + resolve({ | |
498 | + items: formattedRecords, | |
499 | + total: res.total, | |
500 | + }); | |
501 | + }); | |
502 | +}; | |
503 | + | |
504 | +export const getOrderCostDetailedOptLog = async (params: any) => { | |
505 | + const res = await defHttp.post<any>({ | |
506 | + url: Api.ORDERCOSTDETAILEDOPTLOG, | |
507 | + params, | |
508 | + }); | |
509 | + const formattedRecords = res.records.map((record: any) => { | |
510 | + return { | |
511 | + ...record, | |
512 | + }; | |
513 | + }); | |
514 | + const orderStore = useOrderStoreWithOut(); | |
515 | + orderStore.setTotal(res.total); | |
516 | + orderStore.setQueryVO(params); | |
517 | + return new Promise((resolve) => { | |
518 | + resolve({ | |
519 | + items: formattedRecords, | |
520 | + total: res.total, | |
521 | + }); | |
522 | + }); | |
523 | +}; | |
524 | +export const getBusinessProfitExport = async (params: any) => { | |
525 | + return await defHttp.post<any>({ | |
526 | + url: Api.ORDERCOSTDETAILEDEXPORT, | |
527 | + params, | |
528 | + }); | |
529 | +}; | |
530 | + | |
531 | +export const getInnerProfitInfoExport = async (params: any) => { | |
532 | + return await defHttp.post<any>({ | |
533 | + url: Api.INNERPRODUCEPROFITEXPORT, | |
534 | + params, | |
535 | + }); | |
536 | +}; | |
537 | +export const getBusinessProfitDetailExport = async (params: any) => { | |
538 | + return await defHttp.post<any>({ | |
539 | + url: Api.BUSINESSPROFITDETAIL, | |
540 | + params, | |
541 | + }); | |
542 | +}; | |
543 | +export const getInnerProfitDetail = async (params: any) => { | |
544 | + return await defHttp.post<any>({ | |
545 | + url: Api.INNERPROFITDETAIL, | |
546 | + params, | |
547 | + }); | |
548 | +}; | |
464 | 549 | \ No newline at end of file | ... | ... |
src/router/routes/modules/project/finance.ts
... | ... | @@ -116,8 +116,8 @@ const finance: AppRouteModule = { |
116 | 116 | }, |
117 | 117 | children: [ |
118 | 118 | { |
119 | - path: 'InnerData', | |
120 | - name: 'InnerData', | |
119 | + path: 'InnerProduce', | |
120 | + name: 'InnerProduce', | |
121 | 121 | meta: { |
122 | 122 | title: '内部生产净利润分析表', |
123 | 123 | roles: [RoleEnum.ADMIN, RoleEnum.FINANCE, RoleEnum.TRACKER, RoleEnum.BUSINESS], |
... | ... | @@ -129,8 +129,8 @@ const finance: AppRouteModule = { |
129 | 129 | ), |
130 | 130 | }, |
131 | 131 | { |
132 | - path: 'InnerProduce', | |
133 | - name: 'InnerProduce', | |
132 | + path: 'InnerData', | |
133 | + name: 'InnerData', | |
134 | 134 | meta: { |
135 | 135 | title: '内部生产明细表', |
136 | 136 | roles: [RoleEnum.ADMIN, RoleEnum.FINANCE, RoleEnum.TRACKER, RoleEnum.BUSINESS], | ... | ... |
src/views/project/finance/financeProfit/ProductProfit/InnerData/FinanceEdit.vue
... | ... | @@ -32,6 +32,14 @@ |
32 | 32 | auto-size |
33 | 33 | /> |
34 | 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'" | |
40 | + auto-size | |
41 | + /> | |
42 | + <div style="margin: 16px 0"></div> | |
35 | 43 | |
36 | 44 | <!-- <template #titleToolbar> <a-button type="primary"> 申请编辑权限 </a-button></template> --> |
37 | 45 | <template #appendFooter> |
... | ... | @@ -126,20 +134,26 @@ |
126 | 134 | const update = ref(); |
127 | 135 | const status1 = ref(); |
128 | 136 | const status2 = ref(); |
137 | + const status3 = ref(); | |
129 | 138 | |
130 | 139 | const input1 = ref(); |
131 | 140 | const input2 = ref(); |
141 | + const input3 = ref(); | |
142 | + const orderCount = ref(); | |
132 | 143 | const id = ref(); |
133 | 144 | const [register, { setDrawerProps, closeDrawer }] = useDrawerInner((data) => { |
134 | 145 | // 方式1 |
135 | 146 | if (data.data?.lockFields) { |
136 | 147 | status1.value = data.data?.lockFields?.productionDepartmentPredictPrice; |
137 | 148 | status2.value = data.data?.lockFields?.productionActualPrice; |
149 | + status3.value = data.data?.lockFields?.productionDepartmentPredictUnitprice; | |
138 | 150 | } |
139 | 151 | |
140 | 152 | id.value = data.data.orderId; |
141 | 153 | input1.value = data.data?.productionDepartmentPredictPrice.toFixed(2); |
142 | 154 | input2.value = data.data?.productionActualPrice.toFixed(2); |
155 | + orderCount.value = data.data?.orderCount; | |
156 | + input3.value = data.data?.productionDepartmentPredictUnitprice.toFixed(2); | |
143 | 157 | resetFields(); |
144 | 158 | setDrawerProps({ confirmLoading: false }); |
145 | 159 | // setFieldsValue({ |
... | ... | @@ -155,13 +169,15 @@ |
155 | 169 | // id: update.value.data.id, |
156 | 170 | // bgUrl: update.value.data.bgUrl, |
157 | 171 | // }; |
158 | - if (!input1.value || !input2.value) { | |
172 | + if (!input1.value || !input2.value || !input3.value) { | |
159 | 173 | error('选项不能为空'); |
160 | 174 | } else { |
161 | 175 | await getPackageEdit({ |
162 | 176 | orderId: id.value, |
163 | 177 | productionDepartmentPredictPrice: input1.value, |
164 | 178 | productionActualPrice: input2.value, |
179 | + orderCount: orderCount.value, | |
180 | + productionDepartmentPredictUnitprice: input3.value, | |
165 | 181 | }); |
166 | 182 | emit('success'); |
167 | 183 | closeDrawer(); |
... | ... | @@ -171,6 +187,7 @@ |
171 | 187 | if (!visible) { |
172 | 188 | input1.value = ''; |
173 | 189 | input2.value = ''; |
190 | + input3.value = ''; | |
174 | 191 | } |
175 | 192 | } |
176 | 193 | </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: 70, | |
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 | }, |
... | ... | @@ -212,6 +220,20 @@ export const COLUMNS = [ |
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?.status === '-1') { | |
229 | + return '未完成'; | |
230 | + } else if (column.record?.status === '0') { | |
231 | + return '待审核'; | |
232 | + } else if (column.record?.status === '1') { | |
233 | + return '已审核'; | |
234 | + } | |
235 | + }, | |
236 | + }, | |
215 | 237 | // { |
216 | 238 | // title: '内部生产固定成本¥', |
217 | 239 | // dataIndex: 'innerProductionFixedCost', | ... | ... |
src/views/project/finance/financeProfit/ProductProfit/InnerData/index.vue
... | ... | @@ -6,7 +6,7 @@ |
6 | 6 | <img :z-index="100000" :width="50" :height="50" :src="record?.picUrl" /> |
7 | 7 | </template> |
8 | 8 | <template v-if="column.key === 'action'"> |
9 | - <TableAction :actions="createActions(record)" /> | |
9 | + <TableAction :actions="createActions(record)" :dropDownActions="createDropActions(record)" /> | |
10 | 10 | </template> |
11 | 11 | <!-- <template v-if="column.key === 'relationValue'"> |
12 | 12 | <a-input |
... | ... | @@ -32,8 +32,9 @@ |
32 | 32 | <a-textarea :rows="6" placeholder="请输入拒绝原因" v-model:value="message" /> |
33 | 33 | </div> |
34 | 34 | </BasicModal> --> |
35 | - <CheckDetail @register="checkModalRegister" /> | |
35 | + <CheckDetail @register="checkModalRegister" :onGoFormDetail="handleGoFormDetail" /> | |
36 | 36 | <FinanceEdit @register="registerFinanceEdit" @success="handleSuccess" /> |
37 | + <HistoryDetail @register="registerHistoryDetail" /> | |
37 | 38 | </div> |
38 | 39 | </template> |
39 | 40 | <script setup lang="ts"> |
... | ... | @@ -42,11 +43,15 @@ |
42 | 43 | import { searchFormSchema, COLUMNS } from './data'; |
43 | 44 | import { BasicModal, useModal } from '/@/components/Modal'; |
44 | 45 | import { useMessage } from '/@/hooks/web/useMessage'; |
45 | - import { onMounted, ref } from 'vue'; | |
46 | + import { onMounted, ref, computed } from 'vue'; | |
46 | 47 | import { useDrawer } from '/@/components/Drawer'; |
47 | 48 | import FinanceEdit from './FinanceEdit.vue'; |
48 | 49 | import CheckDetail from './CheckDetail.vue'; |
50 | + import HistoryDetail from './HistoryDetail.vue'; | |
49 | 51 | import { useOrderStoreWithOut } from '/@/store/modules/order'; |
52 | + import { useUserStoreWithOut } from '/@/store/modules/user'; | |
53 | + import { RoleEnum } from '/@/enums/roleEnum'; | |
54 | + import { ROLE } from '../../../type.d'; | |
50 | 55 | |
51 | 56 | const { createMessage } = useMessage(); |
52 | 57 | const { error } = createMessage; |
... | ... | @@ -54,6 +59,12 @@ |
54 | 59 | const orderStore = useOrderStoreWithOut(); |
55 | 60 | const [checkModalRegister, { openDrawer: openCheckDetailDrawer }] = useDrawer(); |
56 | 61 | const [registerFinanceEdit, { openDrawer: openFinanceEdit }] = useDrawer(); |
62 | + const [registerHistoryDetail, { openDrawer: openHistoryDetail }] = useDrawer(); | |
63 | + const userStore = useUserStoreWithOut(); | |
64 | + const user = userStore.getUserInfo; | |
65 | + const role = computed(() => { | |
66 | + return user?.roleSmallVO?.code; | |
67 | + }); | |
57 | 68 | const handleOk = (record) => { |
58 | 69 | // 修改父组件的状态 |
59 | 70 | closeModal(); |
... | ... | @@ -80,7 +91,7 @@ |
80 | 91 | setting: false, |
81 | 92 | }, |
82 | 93 | actionColumn: { |
83 | - width: 240, | |
94 | + width: 260, | |
84 | 95 | title: 'Action', |
85 | 96 | dataIndex: 'action', |
86 | 97 | }, |
... | ... | @@ -111,6 +122,18 @@ |
111 | 122 | // }, |
112 | 123 | onClick: handleFalse.bind(null, record), |
113 | 124 | }, |
125 | + { | |
126 | + label: '审批通过', | |
127 | + popConfirm: { | |
128 | + title: '确认审批?', | |
129 | + confirm: () => { | |
130 | + if (record.status === 0 && role.value === ROLE.ADMIN) { | |
131 | + handleStatus(record, true); | |
132 | + } | |
133 | + return; | |
134 | + }, | |
135 | + }, | |
136 | + }, | |
114 | 137 | ]; |
115 | 138 | } |
116 | 139 | return [ |
... | ... | @@ -128,6 +151,18 @@ |
128 | 151 | ]; |
129 | 152 | } |
130 | 153 | |
154 | + function createDropActions(record: any) { | |
155 | + if (!record.editable) { | |
156 | + const actions = [ | |
157 | + { | |
158 | + label: '历史记录', | |
159 | + onClick: handleHistoryDetail.bind(null, record), | |
160 | + }, | |
161 | + ]; | |
162 | + return actions; | |
163 | + } | |
164 | + } | |
165 | + | |
131 | 166 | onMounted(async () => { |
132 | 167 | await orderStore.getDict(); |
133 | 168 | }); |
... | ... | @@ -175,5 +210,25 @@ |
175 | 210 | reload(); |
176 | 211 | }, 50); |
177 | 212 | } |
213 | + | |
214 | + async function handleStatus(record, status) { | |
215 | + try { | |
216 | + // Add your API call here for updating status | |
217 | + // Example: await updateStatus({ id: record.id, status: status ? 1 : 2 }); | |
218 | + reload(); | |
219 | + } catch (error) { | |
220 | + console.error(error); | |
221 | + } | |
222 | + } | |
223 | + | |
224 | + function handleHistoryDetail(record) { | |
225 | + openHistoryDetail(true, { | |
226 | + data: record, | |
227 | + }); | |
228 | + } | |
229 | + | |
230 | + function handleGoFormDetail() { | |
231 | + // Add your logic for form detail navigation | |
232 | + } | |
178 | 233 | </script> |
179 | 234 | <style></style> | ... | ... |
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({ orderId: data, type: 30, page: page, pageSize: 20 }); | |
138 | + list1.value = res.items; | |
139 | + total1.value = res.total; | |
140 | + page1.value = page; | |
141 | + } else { | |
142 | + const res = await getProjectOptLog({ orderId: data, type: 1, page: page, pageSize: 20 }); | |
143 | + list2.value = res.items; | |
144 | + total2.value = res.total; | |
145 | + page2.value = page; | |
146 | + } | |
147 | + }; | |
148 | + const [register] = useDrawerInner((data) => { | |
149 | + orderId.value = data.data.projectNoPrefix; | |
150 | + getOrderOptLogFunc(orderId.value, 1, 1); | |
151 | + getOrderOptLogFunc(orderId.value, 2, 1); | |
152 | + }); | |
153 | + | |
154 | + const pagination1 = computed(() => { | |
155 | + return { | |
156 | + show: true, | |
157 | + pageSize: 20, | |
158 | + page: page1.value, | |
159 | + total: total1.value, | |
160 | + onChange(cur) { | |
161 | + getOrderOptLogFunc(orderId.value, 1, cur); | |
162 | + }, | |
163 | + }; | |
164 | + }); | |
165 | + | |
166 | + const pagination2 = computed(() => { | |
167 | + return { | |
168 | + show: true, | |
169 | + pageSize: 20, | |
170 | + page: page1.value, | |
171 | + total: total1.value, | |
172 | + onChange(cur) { | |
173 | + getOrderOptLogFunc(orderId.value, 2, cur); | |
174 | + }, | |
175 | + }; | |
176 | + }); | |
177 | + | |
178 | + return { | |
179 | + register, | |
180 | + schemas, | |
181 | + achieveList, | |
182 | + list1, | |
183 | + list2, | |
184 | + prefixCls: 'account-center', | |
185 | + pagination1, | |
186 | + pagination2, | |
187 | + activeKey, | |
188 | + formatToDateTime, | |
189 | + }; | |
190 | + }, | |
191 | + }); | |
192 | +</script> | ... | ... |
src/views/project/finance/financeProfit/ProductProfit/InnerProduce/data.tsx
... | ... | @@ -241,6 +241,20 @@ export const COLUMNS = [ |
241 | 241 | }, |
242 | 242 | }, |
243 | 243 | { |
244 | + title: '状态', | |
245 | + dataIndex: 'status', | |
246 | + width: 120, | |
247 | + customRender: (column) => { | |
248 | + if (column.record?.status === '-1') { | |
249 | + return '未完成'; | |
250 | + } else if (column.record?.status === '0') { | |
251 | + return '待审核'; | |
252 | + } else if (column.record?.status === '1') { | |
253 | + return '已审核'; | |
254 | + } | |
255 | + }, | |
256 | + }, | |
257 | + { | |
244 | 258 | title: '文件', |
245 | 259 | dataIndex: 'fileUrl', |
246 | 260 | width: 120, | ... | ... |
src/views/project/finance/financeProfit/ProductProfit/InnerProduce/index.vue
... | ... | @@ -6,7 +6,10 @@ |
6 | 6 | <img :z-index="100000" :width="50" :height="50" :src="record?.picUrl" /> |
7 | 7 | </template> |
8 | 8 | <template v-if="column.key === 'action'"> |
9 | - <TableAction :actions="createActions(record)" /> | |
9 | + <TableAction | |
10 | + :actions="createActions(record)" | |
11 | + :dropDownActions="createDropActions(record)" | |
12 | + /> | |
10 | 13 | </template> |
11 | 14 | <!-- <template v-if="column.key === 'relationValue'"> |
12 | 15 | <a-input |
... | ... | @@ -32,8 +35,9 @@ |
32 | 35 | <a-textarea :rows="6" placeholder="请输入拒绝原因" v-model:value="message" /> |
33 | 36 | </div> |
34 | 37 | </BasicModal> --> |
35 | - <CheckDetail @register="checkModalRegister" /> | |
38 | + <CheckDetail @register="checkModalRegister" :onGoFormDetail="handleGoFormDetail" /> | |
36 | 39 | <FinanceEdit @register="registerFinanceEdit" @success="handleSuccess" /> |
40 | + <HistoryDetail @register="registerHistoryDetail" /> | |
37 | 41 | </div> |
38 | 42 | </template> |
39 | 43 | <script setup lang="ts"> |
... | ... | @@ -42,11 +46,15 @@ |
42 | 46 | import { searchFormSchema, COLUMNS } from './data'; |
43 | 47 | import { BasicModal, useModal } from '/@/components/Modal'; |
44 | 48 | import { useMessage } from '/@/hooks/web/useMessage'; |
45 | - import { onMounted, ref } from 'vue'; | |
49 | + import { onMounted, ref, computed } from 'vue'; | |
46 | 50 | import { useDrawer } from '/@/components/Drawer'; |
47 | 51 | import FinanceEdit from './FinanceEdit.vue'; |
48 | 52 | import CheckDetail from './CheckDetail.vue'; |
53 | + import HistoryDetail from './HistoryDetail.vue'; | |
49 | 54 | import { useOrderStoreWithOut } from '/@/store/modules/order'; |
55 | + import { useUserStoreWithOut } from '/@/store/modules/user'; | |
56 | + import { RoleEnum } from '/@/enums/roleEnum'; | |
57 | + import { ROLE } from '../../../type.d'; | |
50 | 58 | |
51 | 59 | const { createMessage } = useMessage(); |
52 | 60 | const { error } = createMessage; |
... | ... | @@ -54,6 +62,12 @@ |
54 | 62 | const orderStore = useOrderStoreWithOut(); |
55 | 63 | const [checkModalRegister, { openDrawer: openCheckDetailDrawer }] = useDrawer(); |
56 | 64 | const [registerFinanceEdit, { openDrawer: openFinanceEdit }] = useDrawer(); |
65 | + const [registerHistoryDetail, { openDrawer: openHistoryDetail }] = useDrawer(); | |
66 | + const userStore = useUserStoreWithOut(); | |
67 | + const user = userStore.getUserInfo; | |
68 | + const role = computed(() => { | |
69 | + return user?.roleSmallVO?.code; | |
70 | + }); | |
57 | 71 | const handleOk = (record) => { |
58 | 72 | // 修改父组件的状态 |
59 | 73 | closeModal(); |
... | ... | @@ -81,7 +95,7 @@ |
81 | 95 | setting: false, |
82 | 96 | }, |
83 | 97 | actionColumn: { |
84 | - width: 240, | |
98 | + width: 260, | |
85 | 99 | title: 'Action', |
86 | 100 | dataIndex: 'action', |
87 | 101 | }, |
... | ... | @@ -113,6 +127,18 @@ |
113 | 127 | // }, |
114 | 128 | onClick: handleFalse.bind(null, record), |
115 | 129 | }, |
130 | + { | |
131 | + label: '审核通过', | |
132 | + popConfirm: { | |
133 | + title: '确认审核?', | |
134 | + confirm: () => { | |
135 | + if (record.status === 0 && role.value === ROLE.ADMIN) { | |
136 | + handleStatus(record, true); | |
137 | + } | |
138 | + return; | |
139 | + }, | |
140 | + }, | |
141 | + }, | |
116 | 142 | ]; |
117 | 143 | } |
118 | 144 | return [ |
... | ... | @@ -130,6 +156,18 @@ |
130 | 156 | ]; |
131 | 157 | } |
132 | 158 | |
159 | + function createDropActions(record: any) { | |
160 | + if (!record.editable) { | |
161 | + const actions = [ | |
162 | + { | |
163 | + label: '历史记录', | |
164 | + onClick: handleHistoryDetail.bind(null, record), | |
165 | + }, | |
166 | + ]; | |
167 | + return actions; | |
168 | + } | |
169 | + } | |
170 | + | |
133 | 171 | onMounted(async () => { |
134 | 172 | await orderStore.getDict(); |
135 | 173 | }); |
... | ... | @@ -173,5 +211,25 @@ |
173 | 211 | reload(); |
174 | 212 | }, 50); |
175 | 213 | } |
214 | + | |
215 | + async function handleStatus(record, status) { | |
216 | + try { | |
217 | + // Add your API call here for updating status | |
218 | + // Example: await updateStatus({ id: record.id, status: status ? 1 : 2 }); | |
219 | + reload(); | |
220 | + } catch (error) { | |
221 | + console.error(error); | |
222 | + } | |
223 | + } | |
224 | + | |
225 | + function handleHistoryDetail(record) { | |
226 | + openHistoryDetail(true, { | |
227 | + data: record, | |
228 | + }); | |
229 | + } | |
230 | + | |
231 | + function handleGoFormDetail() { | |
232 | + // Add your logic for form detail navigation | |
233 | + } | |
176 | 234 | </script> |
177 | 235 | <style></style> | ... | ... |
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: 60, | |
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
... | ... | @@ -187,4 +187,18 @@ export const COLUMNS = [ |
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?.status === '-1') { | |
196 | + return '未完成'; | |
197 | + } else if (column.record?.status === '0') { | |
198 | + return '待审核'; | |
199 | + } else if (column.record?.status === '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
... | ... | @@ -6,7 +6,10 @@ |
6 | 6 | <img :z-index="100000" :width="50" :height="50" :src="record?.picUrl" /> |
7 | 7 | </template> |
8 | 8 | <template v-if="column.key === 'action'"> |
9 | - <TableAction :actions="createActions(record)" /> | |
9 | + <TableAction | |
10 | + :actions="createActions(record)" | |
11 | + :dropDownActions="createDropActions(record)" | |
12 | + /> | |
10 | 13 | </template> |
11 | 14 | <!-- <template v-if="column.key === 'relationValue'"> |
12 | 15 | <a-input |
... | ... | @@ -34,6 +37,7 @@ |
34 | 37 | </BasicModal> --> |
35 | 38 | <CheckDetail @register="checkModalRegister" :onGoFormDetail="handleGoFormDetail" /> |
36 | 39 | <FinanceEdit @register="registerFinanceEdit" @success="handleSuccess" /> |
40 | + <HistoryDetail @register="registerHistoryDetail" /> | |
37 | 41 | </div> |
38 | 42 | </template> |
39 | 43 | <script setup lang="ts"> |
... | ... | @@ -42,12 +46,16 @@ |
42 | 46 | import { searchFormSchema, COLUMNS } from './data'; |
43 | 47 | import { BasicModal, useModal } from '/@/components/Modal'; |
44 | 48 | import { useMessage } from '/@/hooks/web/useMessage'; |
45 | - import { onMounted, ref } from 'vue'; | |
49 | + import { onMounted, ref, computed } from 'vue'; | |
46 | 50 | import { useDrawer } from '/@/components/Drawer'; |
47 | 51 | import FinanceEdit from './FinanceEdit.vue'; |
48 | 52 | import CheckDetail from './CheckDetail.vue'; |
53 | + import HistoryDetail from './HistoryDetail.vue'; | |
49 | 54 | import { FilePptOutlined } from '@ant-design/icons-vue'; |
50 | 55 | import { useOrderStoreWithOut } from '/@/store/modules/order'; |
56 | + import { useUserStoreWithOut } from '/@/store/modules/user'; | |
57 | + import { RoleEnum } from '/@/enums/roleEnum'; | |
58 | + import { ROLE } from '../../../type.d'; | |
51 | 59 | |
52 | 60 | const { createMessage } = useMessage(); |
53 | 61 | const { error } = createMessage; |
... | ... | @@ -55,6 +63,12 @@ |
55 | 63 | const orderStore = useOrderStoreWithOut(); |
56 | 64 | const [checkModalRegister, { openDrawer: openCheckDetailDrawer }] = useDrawer(); |
57 | 65 | const [registerFinanceEdit, { openDrawer: openFinanceEdit }] = useDrawer(); |
66 | + const [registerHistoryDetail, { openDrawer: openHistoryDetail }] = useDrawer(); | |
67 | + const userStore = useUserStoreWithOut(); | |
68 | + const user = userStore.getUserInfo; | |
69 | + const role = computed(() => { | |
70 | + return user?.roleSmallVO?.code; | |
71 | + }); | |
58 | 72 | const handleOk = (record) => { |
59 | 73 | // 修改父组件的状态 |
60 | 74 | closeModal(); |
... | ... | @@ -81,7 +95,7 @@ |
81 | 95 | setting: false, |
82 | 96 | }, |
83 | 97 | actionColumn: { |
84 | - width: 240, | |
98 | + width: 260, | |
85 | 99 | title: 'Action', |
86 | 100 | dataIndex: 'action', |
87 | 101 | }, |
... | ... | @@ -113,6 +127,18 @@ |
113 | 127 | // }, |
114 | 128 | onClick: handleFalse.bind(null, record), |
115 | 129 | }, |
130 | + { | |
131 | + label: '审核通过', | |
132 | + popConfirm: { | |
133 | + title: '确认审核?', | |
134 | + confirm: () => { | |
135 | + if (record.status === 0 && role.value === ROLE.ADMIN) { | |
136 | + handleStatus(record, true); | |
137 | + } | |
138 | + return; | |
139 | + }, | |
140 | + }, | |
141 | + }, | |
116 | 142 | ]; |
117 | 143 | } |
118 | 144 | return [ |
... | ... | @@ -130,9 +156,17 @@ |
130 | 156 | ]; |
131 | 157 | } |
132 | 158 | |
133 | - onMounted(async () => { | |
134 | - await orderStore.getDict(); | |
135 | - }); | |
159 | + function createDropActions(record: any) { | |
160 | + if (!record.editable) { | |
161 | + const actions = [ | |
162 | + { | |
163 | + label: '历史记录', | |
164 | + onClick: handleHistoryDetail.bind(null, record), | |
165 | + }, | |
166 | + ]; | |
167 | + return actions; | |
168 | + } | |
169 | + } | |
136 | 170 | |
137 | 171 | function handleFinanceEdit(record) { |
138 | 172 | openFinanceEdit(true, { |
... | ... | @@ -176,5 +210,29 @@ |
176 | 210 | // await deleteConfig({ ids: [record.id] }); |
177 | 211 | // reload(); |
178 | 212 | // } |
213 | + | |
214 | + async function handleStatus(record, status) { | |
215 | + try { | |
216 | + // Add your API call here for updating status | |
217 | + // Example: await updateStatus({ id: record.id, status: status ? 1 : 2 }); | |
218 | + reload(); | |
219 | + } catch (error) { | |
220 | + console.error(error); | |
221 | + } | |
222 | + } | |
223 | + | |
224 | + function handleHistoryDetail(record) { | |
225 | + openHistoryDetail(true, { | |
226 | + data: record, | |
227 | + }); | |
228 | + } | |
229 | + | |
230 | + function handleGoFormDetail() { | |
231 | + // Add your logic for form detail navigation | |
232 | + } | |
233 | + | |
234 | + onMounted(async () => { | |
235 | + await orderStore.getDict(); | |
236 | + }); | |
179 | 237 | </script> |
180 | 238 | <style></style> | ... | ... |
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 | + console.log(res, '5656res'); | |
144 | + list1.value = res.items; | |
145 | + total1.value = res.total; | |
146 | + page1.value = page; | |
147 | + } else { | |
148 | + const res = await getProjectOptLog({ | |
149 | + projectNoPrefix: data, | |
150 | + type: 0, | |
151 | + page: page, | |
152 | + pageSize: 20 | |
153 | + }); | |
154 | + list2.value = res.items; | |
155 | + total2.value = res.total; | |
156 | + page2.value = page; | |
157 | + } | |
158 | + }; | |
159 | + const [register] = useDrawerInner((data) => { | |
160 | + orderId.value = data.data.projectNoPrefix; | |
161 | + getOrderOptLogFunc(orderId.value, 1, 1); | |
162 | + getOrderOptLogFunc(orderId.value, 2, 1); | |
163 | + }); | |
164 | + | |
165 | + const pagination1 = computed(() => { | |
166 | + return { | |
167 | + show: true, | |
168 | + pageSize: 20, | |
169 | + page: page1.value, | |
170 | + total: total1.value, | |
171 | + onChange(cur) { | |
172 | + getOrderOptLogFunc(orderId.value, 1, cur); | |
173 | + }, | |
174 | + }; | |
175 | + }); | |
176 | + | |
177 | + const pagination2 = computed(() => { | |
178 | + return { | |
179 | + show: true, | |
180 | + pageSize: 20, | |
181 | + page: page1.value, | |
182 | + total: total1.value, | |
183 | + onChange(cur) { | |
184 | + getOrderOptLogFunc(orderId.value, 2, cur); | |
185 | + }, | |
186 | + }; | |
187 | + }); | |
188 | + | |
189 | + return { | |
190 | + register, | |
191 | + schemas, | |
192 | + achieveList, | |
193 | + list1, | |
194 | + list2, | |
195 | + prefixCls: 'account-center', | |
196 | + pagination1, | |
197 | + pagination2, | |
198 | + activeKey, | |
199 | + formatToDateTime, | |
200 | + }; | |
201 | + }, | |
202 | + }); | |
203 | +</script> | ... | ... |
src/views/project/finance/financeProfit/ServiceProfit/ServiceProfit/data.tsx
... | ... | @@ -140,7 +140,6 @@ export const COLUMNS = [ |
140 | 140 | dataIndex: 'packetTotalPrice', |
141 | 141 | width: 150, |
142 | 142 | customRender: (column) => { |
143 | - console.log(column, '5656666666'); | |
144 | 143 | return column.record?.packetRmbTotalPrice?.toFixed(2); |
145 | 144 | }, |
146 | 145 | }, |
... | ... | @@ -311,14 +310,6 @@ export const COLUMNS = [ |
311 | 310 | }, |
312 | 311 | }, |
313 | 312 | { |
314 | - title: '汇率收益¥', | |
315 | - dataIndex: 'exchangeRateProfit', | |
316 | - width: 120, | |
317 | - customRender: (column) => { | |
318 | - return column.record?.exchangeRateProfit?.toFixed(2); | |
319 | - }, | |
320 | - }, | |
321 | - { | |
322 | 313 | title: '综合收益¥', |
323 | 314 | dataIndex: 'comprehensiveProfit', |
324 | 315 | width: 120, |
... | ... | @@ -381,4 +372,18 @@ export const COLUMNS = [ |
381 | 372 | return <FilePptOutlined style="font-size:25px" onClick={() => handleClick()} />; |
382 | 373 | }, |
383 | 374 | }, |
375 | + { | |
376 | + title: '状态', | |
377 | + dataIndex: 'status', | |
378 | + width: 120, | |
379 | + customRender: (column) => { | |
380 | + if (column.record?.status === '-1') { | |
381 | + return '未完成'; | |
382 | + } else if (column.record?.status === '0') { | |
383 | + return '待审核'; | |
384 | + } else if (column.record?.status === '1') { | |
385 | + return '已审核'; | |
386 | + } | |
387 | + }, | |
388 | + }, | |
384 | 389 | ]; |
385 | 390 | \ No newline at end of file | ... | ... |
src/views/project/finance/financeProfit/ServiceProfit/ServiceProfit/index.vue
... | ... | @@ -3,7 +3,10 @@ |
3 | 3 | <BasicTable @register="registerTable" :bordered="true"> |
4 | 4 | <template #bodyCell="{ column, record }"> |
5 | 5 | <template v-if="column.key === 'action'"> |
6 | - <TableAction :actions="createActions(record)" /> | |
6 | + <TableAction | |
7 | + :actions="createActions(record)" | |
8 | + :dropDownActions="createDropActions(record)" | |
9 | + /> | |
7 | 10 | </template> |
8 | 11 | <!-- <template v-if="column.key === 'relationValue'"> |
9 | 12 | <a-input |
... | ... | @@ -31,32 +34,39 @@ |
31 | 34 | </BasicModal> --> |
32 | 35 | <CheckDetail @register="checkModalRegister" :onGoFormDetail="handleGoFormDetail" /> |
33 | 36 | <FinanceEdit @register="registerFinanceEdit" @success="handleSuccess" /> |
37 | + <HistoryDetail @register="registerHistoryDetail" /> | |
34 | 38 | </div> |
35 | 39 | </template> |
36 | 40 | <script setup lang="ts"> |
37 | 41 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; |
38 | 42 | import { getServiceProfit } from '@/api/project/invoice'; |
39 | 43 | import { searchFormSchema, COLUMNS } from './data'; |
40 | - import { BasicModal, useModal } from '/@/components/Modal'; | |
41 | 44 | import { useMessage } from '/@/hooks/web/useMessage'; |
42 | - import { onMounted, ref } from 'vue'; | |
45 | + import { onMounted, ref, computed, unref } from 'vue'; | |
43 | 46 | import { useDrawer } from '/@/components/Drawer'; |
44 | 47 | import FinanceEdit from './FinanceEdit.vue'; |
48 | + import HistoryDetail from './HistoryDetail.vue'; | |
45 | 49 | import CheckDetail from './CheckDetail.vue'; |
50 | + import { useUserStoreWithOut } from '/@/store/modules/user'; | |
51 | + import { ROLE } from '../../../type.d'; | |
46 | 52 | import { useOrderStoreWithOut } from '/@/store/modules/order'; |
47 | 53 | |
48 | 54 | const { createMessage } = useMessage(); |
49 | - const { error } = createMessage; | |
50 | 55 | const message = ref(); |
56 | + const checkedKeys = ref<string[]>([]); | |
57 | + const invoiceIdKeys = ref<string[]>([]); | |
58 | + const checkIdKeys = ref<string[]>([]); | |
51 | 59 | const orderStore = useOrderStoreWithOut(); |
52 | 60 | const [checkModalRegister, { openDrawer: openCheckDetailDrawer }] = useDrawer(); |
53 | 61 | const [registerFinanceEdit, { openDrawer: openFinanceEdit }] = useDrawer(); |
54 | - const handleClose = (visible: boolean) => { | |
55 | - if (!visible) { | |
56 | - message.value = ''; | |
57 | - } | |
58 | - }; | |
59 | - const [registerTable, { reload }] = useTable({ | |
62 | + const [registerHistoryDetail, { openDrawer: openHistoryDetail }] = useDrawer(); | |
63 | + const userStore = useUserStoreWithOut(); | |
64 | + const user = userStore.getUserInfo; | |
65 | + const role = computed(() => { | |
66 | + return user?.roleSmallVO?.code; | |
67 | + }); | |
68 | + const [registerTable, { reload, getSelectRowKeys, getDataSource, setSelectedRowKeys }] = useTable({ | |
69 | + | |
60 | 70 | api: getServiceProfit, |
61 | 71 | bordered: true, |
62 | 72 | columns: COLUMNS, |
... | ... | @@ -74,7 +84,7 @@ |
74 | 84 | setting: false, |
75 | 85 | }, |
76 | 86 | actionColumn: { |
77 | - width: 240, | |
87 | + width: 260, | |
78 | 88 | title: 'Action', |
79 | 89 | dataIndex: 'action', |
80 | 90 | }, |
... | ... | @@ -82,7 +92,7 @@ |
82 | 92 | |
83 | 93 | function createActions(record: any): any[] { |
84 | 94 | if (!record.editable) { |
85 | - return [ | |
95 | + const actions = [ | |
86 | 96 | { |
87 | 97 | label: '财务编辑', |
88 | 98 | onClick: handleFinanceEdit.bind(null, record), |
... | ... | @@ -106,7 +116,20 @@ |
106 | 116 | // }, |
107 | 117 | onClick: handleFalse.bind(null, record), |
108 | 118 | }, |
119 | + { | |
120 | + label: '审核通过', | |
121 | + popConfirm: { | |
122 | + title: '确认审核?', | |
123 | + confirm: () => { | |
124 | + if (record.status === 0 && role.value === ROLE.ADMIN) { | |
125 | + handleStatus(record, true); | |
126 | + } | |
127 | + return; | |
128 | + }, | |
129 | + }, | |
130 | + }, | |
109 | 131 | ]; |
132 | + return actions; | |
110 | 133 | } |
111 | 134 | return [ |
112 | 135 | { |
... | ... | @@ -122,6 +145,17 @@ |
122 | 145 | }, |
123 | 146 | ]; |
124 | 147 | } |
148 | + function createDropActions(record: any) { | |
149 | + if (!record.editable) { | |
150 | + const actions = [ | |
151 | + { | |
152 | + label: '历史记录', | |
153 | + onClick: handleHistoryDetail.bind(null, record), | |
154 | + }, | |
155 | + ]; | |
156 | + return actions; | |
157 | + } | |
158 | + } | |
125 | 159 | |
126 | 160 | onMounted(async () => { |
127 | 161 | await orderStore.getDict(); |
... | ... | @@ -160,7 +194,6 @@ |
160 | 194 | // error('请勿连续点击生成按钮,需要等待三秒再点击生成'); |
161 | 195 | // } else { |
162 | 196 | record.onEdit?.(true); |
163 | - // } | |
164 | 197 | } |
165 | 198 | |
166 | 199 | function handleCancel(record) { |
... | ... | @@ -171,5 +204,21 @@ |
171 | 204 | // await deleteConfig({ ids: [record.id] }); |
172 | 205 | reload(); |
173 | 206 | } |
207 | + | |
208 | + async function handleStatus(record, status) { | |
209 | + try { | |
210 | + // You can implement the API call here | |
211 | + // await someApiCall({ id: record.id, status }); | |
212 | + reload(); | |
213 | + } catch (error) { | |
214 | + console.error('Error updating status:', error); | |
215 | + } | |
216 | + } | |
217 | + | |
218 | + async function handleHistoryDetail(record) { | |
219 | + openHistoryDetail(true, { | |
220 | + data: record, | |
221 | + }); | |
222 | + } | |
174 | 223 | </script> |
175 | 224 | <style></style> | ... | ... |
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 | +} | ... | ... |