Commit cfeaf8a04714a1fc5d8d07db2a3034e71e3b5b0d
1 parent
7a8f528e
审核调试
Showing
32 changed files
with
3284 additions
and
138 deletions
src/api/project/invoice.ts
@@ -34,6 +34,19 @@ enum Api { | @@ -34,6 +34,19 @@ enum Api { | ||
34 | EXPORTRECEIPT = '/order/erp/check_bill/exportReceipt', //付款单导出 | 34 | EXPORTRECEIPT = '/order/erp/check_bill/exportReceipt', //付款单导出 |
35 | SETPADYEDDATE = '/order/erp/check_bill/setPayedDate', //修改应付款日期 | 35 | SETPADYEDDATE = '/order/erp/check_bill/setPayedDate', //修改应付款日期 |
36 | CHECKNOTE = '/order/erp/check_bill/notes', //备注 | 36 | CHECKNOTE = '/order/erp/check_bill/notes', //备注 |
37 | + | ||
38 | + PACKAGEPROFIT = '/order/cost/BusinessProfitDetail/listByPage', //包装费用明细表 | ||
39 | + INNERPROFIT = '/order/cost/InnerProfitDetail/listByPage', //内部生产费用明细表 | ||
40 | + PACKAGEEDIT = '/order/cost/edit', //编辑 | ||
41 | + PACKAGEAPPLYEDIT = '/order/cost/applyEditFileds', //申请编辑字段 | ||
42 | + SERVICEPROFIT = '/project/BusinessProfitInfo/listByPage', //业务研发净利润分析表 | ||
43 | + INNERPRODUCEPROFIT = '/project/InnerProfitInfo/listByPage', //内部生产利润分析表 | ||
44 | + SERVICEPROFITEXPORT = '/project/businessProfit/export', //业务研发净利润分析表导出 | ||
45 | + INNERPROFITEXPORT = '/project/innerProfit/export', //内部研发净利润分析表导出 | ||
46 | + SERVICEEDIT = '/project/edit', //编辑 | ||
47 | + SERVICEAPPLYEDIT = '/project/applyEditFileds', //申请修改 | ||
48 | + APPLYLIST = '/project/pageProjectLockFieldApply', //分页查询项目字段申请记录 | ||
49 | + AUDITAPPLY = '/project/audit', //审核 | ||
37 | } | 50 | } |
38 | 51 | ||
39 | export const getRefundDate = async (params: any, data?: any) => { | 52 | export const getRefundDate = async (params: any, data?: any) => { |
@@ -71,6 +84,7 @@ export const getInvoice = async (params: any) => { | @@ -71,6 +84,7 @@ export const getInvoice = async (params: any) => { | ||
71 | }); | 84 | }); |
72 | const orderStore = useOrderStoreWithOut(); | 85 | const orderStore = useOrderStoreWithOut(); |
73 | orderStore.setTotal(res.total); | 86 | orderStore.setTotal(res.total); |
87 | + orderStore.setQueryVO(params); | ||
74 | return new Promise((resolve) => { | 88 | return new Promise((resolve) => { |
75 | resolve({ | 89 | resolve({ |
76 | items: formattedRecords, | 90 | items: formattedRecords, |
@@ -282,3 +296,143 @@ export const getCheckNote = async (params: any) => { | @@ -282,3 +296,143 @@ export const getCheckNote = async (params: any) => { | ||
282 | params, | 296 | params, |
283 | }); | 297 | }); |
284 | }; | 298 | }; |
299 | + | ||
300 | +export const getPackageProfit = async (params: any) => { | ||
301 | + const res = await defHttp.post<any>({ | ||
302 | + url: Api.PACKAGEPROFIT, | ||
303 | + params, | ||
304 | + }); | ||
305 | + const formattedRecords = res.records.map((record: any) => { | ||
306 | + return { | ||
307 | + ...record, | ||
308 | + }; | ||
309 | + }); | ||
310 | + const orderStore = useOrderStoreWithOut(); | ||
311 | + orderStore.setTotal(res.total); | ||
312 | + orderStore.setQueryVO(params); | ||
313 | + return new Promise((resolve) => { | ||
314 | + resolve({ | ||
315 | + items: formattedRecords, | ||
316 | + total: res.total, | ||
317 | + }); | ||
318 | + }); | ||
319 | +}; | ||
320 | + | ||
321 | +export const getInnerProfit = async (params: any) => { | ||
322 | + const res = await defHttp.post<any>({ | ||
323 | + url: Api.INNERPROFIT, | ||
324 | + params, | ||
325 | + }); | ||
326 | + const formattedRecords = res.records.map((record: any) => { | ||
327 | + return { | ||
328 | + ...record, | ||
329 | + }; | ||
330 | + }); | ||
331 | + const orderStore = useOrderStoreWithOut(); | ||
332 | + orderStore.setTotal(res.total); | ||
333 | + orderStore.setQueryVO(params); | ||
334 | + return new Promise((resolve) => { | ||
335 | + resolve({ | ||
336 | + items: formattedRecords, | ||
337 | + total: res.total, | ||
338 | + }); | ||
339 | + }); | ||
340 | +}; | ||
341 | + | ||
342 | +export const getPackageEdit = async (params: any) => { | ||
343 | + return await defHttp.post<any>({ | ||
344 | + url: Api.PACKAGEEDIT, | ||
345 | + params, | ||
346 | + }); | ||
347 | +}; | ||
348 | + | ||
349 | +export const getPackageApplyEdit = async (params: any) => { | ||
350 | + return await defHttp.post<any>({ | ||
351 | + url: Api.PACKAGEAPPLYEDIT, | ||
352 | + params, | ||
353 | + }); | ||
354 | +}; | ||
355 | + | ||
356 | +export const getServiceProfit = async (params: any) => { | ||
357 | + const res = await defHttp.post<any>({ | ||
358 | + url: Api.SERVICEPROFIT, | ||
359 | + params, | ||
360 | + }); | ||
361 | + const formattedRecords = res.records.map((record: any) => { | ||
362 | + return { | ||
363 | + ...record, | ||
364 | + }; | ||
365 | + }); | ||
366 | + const orderStore = useOrderStoreWithOut(); | ||
367 | + orderStore.setTotal(res.total); | ||
368 | + orderStore.setQueryVO(params); | ||
369 | + return new Promise((resolve) => { | ||
370 | + resolve({ | ||
371 | + items: formattedRecords, | ||
372 | + total: res.total, | ||
373 | + }); | ||
374 | + }); | ||
375 | +}; | ||
376 | + | ||
377 | +export const getInnerProduceProfit = async (params: any) => { | ||
378 | + const res = await defHttp.post<any>({ | ||
379 | + url: Api.INNERPRODUCEPROFIT, | ||
380 | + params, | ||
381 | + }); | ||
382 | + const formattedRecords = res.records.map((record: any) => { | ||
383 | + return { | ||
384 | + ...record, | ||
385 | + }; | ||
386 | + }); | ||
387 | + const orderStore = useOrderStoreWithOut(); | ||
388 | + orderStore.setTotal(res.total); | ||
389 | + orderStore.setQueryVO(params); | ||
390 | + return new Promise((resolve) => { | ||
391 | + resolve({ | ||
392 | + items: formattedRecords, | ||
393 | + total: res.total, | ||
394 | + }); | ||
395 | + }); | ||
396 | +}; | ||
397 | + | ||
398 | +export const getServiceProfitExport = async (params: any) => { | ||
399 | + return await defHttp.post<any>({ | ||
400 | + url: Api.SERVICEPROFITEXPORT, | ||
401 | + params, | ||
402 | + }); | ||
403 | +}; | ||
404 | + | ||
405 | +export const getInnerProfitExport = async (params: any) => { | ||
406 | + return await defHttp.post<any>({ | ||
407 | + url: Api.INNERPROFITEXPORT, | ||
408 | + params, | ||
409 | + }); | ||
410 | +}; | ||
411 | + | ||
412 | +export const getServiceEdit = async (params: any) => { | ||
413 | + return await defHttp.post<any>({ | ||
414 | + url: Api.SERVICEEDIT, | ||
415 | + params, | ||
416 | + }); | ||
417 | +}; | ||
418 | + | ||
419 | +export const getServiceApplyEdit = async (params: any) => { | ||
420 | + return await defHttp.post<any>({ | ||
421 | + url: Api.SERVICEAPPLYEDIT, | ||
422 | + params, | ||
423 | + }); | ||
424 | +}; | ||
425 | + | ||
426 | +export const getApplyList = async (params: any) => { | ||
427 | + return await defHttp.post<any>({ | ||
428 | + url: Api.APPLYLIST, | ||
429 | + params, | ||
430 | + }); | ||
431 | +}; | ||
432 | + | ||
433 | +export const getAuditApply = async (params: any) => { | ||
434 | + return await defHttp.post<any>({ | ||
435 | + url: Api.AUDITAPPLY, | ||
436 | + params, | ||
437 | + }); | ||
438 | +}; |
src/router/routes/modules/project/finance.ts
@@ -43,96 +43,106 @@ const finance: AppRouteModule = { | @@ -43,96 +43,106 @@ const finance: AppRouteModule = { | ||
43 | }, | 43 | }, |
44 | component: () => import('/@/views/project/finance/financeList/index.vue'), | 44 | component: () => import('/@/views/project/finance/financeList/index.vue'), |
45 | }, | 45 | }, |
46 | - // { | ||
47 | - // path: 'financeProfit', | ||
48 | - // name: 'FinanceProfit', | ||
49 | - // meta: { | ||
50 | - // title: '净利润分析', | ||
51 | - // ignoreKeepAlive: true, | ||
52 | - // roles: [ | ||
53 | - // RoleEnum.ADMIN, | ||
54 | - // RoleEnum.FINANCE, | ||
55 | - // RoleEnum.TRACKER, | ||
56 | - // RoleEnum.BUSINESS, | ||
57 | - // RoleEnum.PRODUCE, | ||
58 | - // RoleEnum.DATA_REPORT_USER, | ||
59 | - // ], | ||
60 | - // }, | ||
61 | - // children: [ | ||
62 | - // // { | ||
63 | - // // path: '', | ||
64 | - // // name: 'Receive', | ||
65 | - // // meta: { | ||
66 | - // // title: '财务管理', | ||
67 | - // // roles: [RoleEnum.ADMIN, RoleEnum.FINANCE, RoleEnum.TRACKER, RoleEnum.BUSINESS], | ||
68 | - // // ignoreKeepAlive: false, | ||
69 | - // // }, | ||
70 | - // // // component: () => import('/@/views/project/finance/index.vue'), | ||
71 | - // // }, | ||
72 | - // { | ||
73 | - // path: 'serviceProfit', | ||
74 | - // name: 'ServiceProfit', | ||
75 | - // meta: { | ||
76 | - // title: '业务研发净利润分析', | ||
77 | - // roles: [RoleEnum.ADMIN, RoleEnum.FINANCE, RoleEnum.TRACKER, RoleEnum.BUSINESS], | ||
78 | - // ignoreKeepAlive: false, | ||
79 | - // }, | ||
80 | - // children: [ | ||
81 | - // { | ||
82 | - // path: 'serviceProfit', | ||
83 | - // name: 'ServiceProfit', | ||
84 | - // meta: { | ||
85 | - // title: '业务研发净利润分析', | ||
86 | - // roles: [RoleEnum.ADMIN, RoleEnum.FINANCE, RoleEnum.TRACKER, RoleEnum.BUSINESS], | ||
87 | - // ignoreKeepAlive: false, | ||
88 | - // }, | ||
89 | - // component: () => import('/@/views/project/finance/financeProfit/index.vue'), | ||
90 | - // }, | ||
91 | - // { | ||
92 | - // path: 'serviceProfit', | ||
93 | - // name: 'ServiceProfit', | ||
94 | - // meta: { | ||
95 | - // title: '业务研发净利润分析', | ||
96 | - // roles: [RoleEnum.ADMIN, RoleEnum.FINANCE, RoleEnum.TRACKER, RoleEnum.BUSINESS], | ||
97 | - // ignoreKeepAlive: false, | ||
98 | - // }, | ||
99 | - // component: () => import('/@/views/project/finance/financeProfit/index.vue'), | ||
100 | - // }, | ||
101 | - // ], | ||
102 | - // }, | ||
103 | - // { | ||
104 | - // path: 'productProfit', | ||
105 | - // name: 'ProductProfit', | ||
106 | - // meta: { | ||
107 | - // title: '内部生产净利润分析', | ||
108 | - // roles: [RoleEnum.ADMIN, RoleEnum.FINANCE, RoleEnum.TRACKER, RoleEnum.BUSINESS], | ||
109 | - // ignoreKeepAlive: false, | ||
110 | - // }, | ||
111 | - // children: [ | ||
112 | - // { | ||
113 | - // path: 'serviceProfit', | ||
114 | - // name: 'ServiceProfit', | ||
115 | - // meta: { | ||
116 | - // title: '业务研发净利润分析', | ||
117 | - // roles: [RoleEnum.ADMIN, RoleEnum.FINANCE, RoleEnum.TRACKER, RoleEnum.BUSINESS], | ||
118 | - // ignoreKeepAlive: false, | ||
119 | - // }, | ||
120 | - // component: () => import('/@/views/project/finance/index.vue'), | ||
121 | - // }, | ||
122 | - // { | ||
123 | - // path: 'serviceProfit', | ||
124 | - // name: 'ServiceProfit', | ||
125 | - // meta: { | ||
126 | - // title: '业务研发净利润分析', | ||
127 | - // roles: [RoleEnum.ADMIN, RoleEnum.FINANCE, RoleEnum.TRACKER, RoleEnum.BUSINESS], | ||
128 | - // ignoreKeepAlive: false, | ||
129 | - // }, | ||
130 | - // component: () => import('/@/views/project/finance/index.vue'), | ||
131 | - // }, | ||
132 | - // ], | ||
133 | - // }, | ||
134 | - // ], | ||
135 | - // }, | 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 | + }, | ||
136 | ], | 146 | ], |
137 | }; | 147 | }; |
138 | 148 |
src/settings/componentSetting.ts
@@ -18,7 +18,7 @@ export default { | @@ -18,7 +18,7 @@ export default { | ||
18 | totalField: 'total', | 18 | totalField: 'total', |
19 | }, | 19 | }, |
20 | // Number of pages that can be selected | 20 | // Number of pages that can be selected |
21 | - pageSizeOptions: ['10', '50', '80', '100'], | 21 | + pageSizeOptions: ['10', '50', '80', '100', '1000'], |
22 | // Default display quantity on one page | 22 | // Default display quantity on one page |
23 | defaultPageSize: 10, | 23 | defaultPageSize: 10, |
24 | // Default Size | 24 | // Default Size |
src/store/modules/order.ts
@@ -18,12 +18,36 @@ import { h } from 'vue'; | @@ -18,12 +18,36 @@ import { h } from 'vue'; | ||
18 | import { getInitDictData } from '/@/api/project/order'; | 18 | import { getInitDictData } from '/@/api/project/order'; |
19 | import { groupBy } from 'lodash-es'; | 19 | import { groupBy } from 'lodash-es'; |
20 | 20 | ||
21 | +interface QueryVO { | ||
22 | + checkEndTime?: string; | ||
23 | + checkNo?: string; | ||
24 | + checkNoStatus?: number; | ||
25 | + checkStartTime?: string; | ||
26 | + createEndTime?: string; | ||
27 | + createStartTime?: string; | ||
28 | + customerCode?: string[]; | ||
29 | + innerNo?: string[]; | ||
30 | + invoiceEndTime?: string; | ||
31 | + invoiceNo?: string; | ||
32 | + invoiceStartTime?: string; | ||
33 | + invoiceStatus?: number; | ||
34 | + orderHodEndTime?: string; | ||
35 | + orderHodStartTime?: string; | ||
36 | + page: number; | ||
37 | + pageSize: number; | ||
38 | + productionDepartment?: string[]; | ||
39 | + productionDepartmentConsignEndTime?: string; | ||
40 | + productionDepartmentConsignStartTime?: string; | ||
41 | + projectNo?: string[]; | ||
42 | +} | ||
43 | + | ||
21 | interface UserState { | 44 | interface UserState { |
22 | userInfo: Nullable<UserInfo>; | 45 | userInfo: Nullable<UserInfo>; |
23 | token?: string; | 46 | token?: string; |
24 | roleList: RoleEnum[]; | 47 | roleList: RoleEnum[]; |
25 | sessionTimeout?: boolean; | 48 | sessionTimeout?: boolean; |
26 | lastUpdateTime: number; | 49 | lastUpdateTime: number; |
50 | + queryVO: QueryVO[]; | ||
27 | } | 51 | } |
28 | 52 | ||
29 | export const useOrderStore = defineStore({ | 53 | export const useOrderStore = defineStore({ |
@@ -39,6 +63,7 @@ export const useOrderStore = defineStore({ | @@ -39,6 +63,7 @@ export const useOrderStore = defineStore({ | ||
39 | sessionTimeout: false, | 63 | sessionTimeout: false, |
40 | // Last fetch time | 64 | // Last fetch time |
41 | lastUpdateTime: 0, | 65 | lastUpdateTime: 0, |
66 | + queryVO: [], | ||
42 | }), | 67 | }), |
43 | getters: { | 68 | getters: { |
44 | getDictInfo(state): UserInfo { | 69 | getDictInfo(state): UserInfo { |
@@ -59,6 +84,9 @@ export const useOrderStore = defineStore({ | @@ -59,6 +84,9 @@ export const useOrderStore = defineStore({ | ||
59 | getLastUpdateTime(state): number { | 84 | getLastUpdateTime(state): number { |
60 | return state.lastUpdateTime; | 85 | return state.lastUpdateTime; |
61 | }, | 86 | }, |
87 | + getQueryVO(state) { | ||
88 | + return state.queryVO; // 新增 getter 返回 queryVO | ||
89 | + }, | ||
62 | }, | 90 | }, |
63 | actions: { | 91 | actions: { |
64 | setToken(info: string | undefined) { | 92 | setToken(info: string | undefined) { |
@@ -80,6 +108,11 @@ export const useOrderStore = defineStore({ | @@ -80,6 +108,11 @@ export const useOrderStore = defineStore({ | ||
80 | setSessionTimeout(flag: boolean) { | 108 | setSessionTimeout(flag: boolean) { |
81 | this.sessionTimeout = flag; | 109 | this.sessionTimeout = flag; |
82 | }, | 110 | }, |
111 | + setQueryVO(params: QueryVO[]) { | ||
112 | + params.page = undefined; | ||
113 | + params.pageSize = undefined; | ||
114 | + this.queryVO = params; | ||
115 | + }, | ||
83 | resetState() { | 116 | resetState() { |
84 | this.userInfo = null; | 117 | this.userInfo = null; |
85 | this.token = ''; | 118 | this.token = ''; |
src/views/project/approve/PayPanel.vue
@@ -114,15 +114,18 @@ | @@ -114,15 +114,18 @@ | ||
114 | <template #appendFooter> | 114 | <template #appendFooter> |
115 | <a-button | 115 | <a-button |
116 | v-if=" | 116 | v-if=" |
117 | - ((!isApproved && role === ROLE.ADMIN) || (!isApproved && showInvoice)) && | ||
118 | - (role !== ROLE.BUSINESS || role !== ROLE.TRACKER) | 117 | + (!isApproved && role === ROLE.ADMIN) || |
118 | + (!isApproved && showInvoice && role === ROLE.FINANCE) | ||
119 | " | 119 | " |
120 | @click="handleFalse" | 120 | @click="handleFalse" |
121 | > | 121 | > |
122 | 不通过</a-button | 122 | 不通过</a-button |
123 | > | 123 | > |
124 | <a-button | 124 | <a-button |
125 | - v-if="(isApproved && role === ROLE.ADMIN) || (isApproved && showInvoice)" | 125 | + v-if=" |
126 | + (isApproved && role === ROLE.ADMIN) || | ||
127 | + (isApproved && showInvoice && role === ROLE.FINANCE) | ||
128 | + " | ||
126 | @click="handleFalse" | 129 | @click="handleFalse" |
127 | > | 130 | > |
128 | 驳回重填</a-button | 131 | 驳回重填</a-button |
@@ -232,7 +235,7 @@ | @@ -232,7 +235,7 @@ | ||
232 | if (record?.type === 40) { | 235 | if (record?.type === 40) { |
233 | data.value = record?.fieldInfos?.producePaymentCheckBillFieldVO; | 236 | data.value = record?.fieldInfos?.producePaymentCheckBillFieldVO; |
234 | } else if (record?.type == 50) { | 237 | } else if (record?.type == 50) { |
235 | - data.value = record?.fieldInfos?.checkBillOrderDO; | 238 | + data.value = record?.fieldInfos?.checkBillVO; |
236 | } | 239 | } |
237 | if (record?.type === 40) { | 240 | if (record?.type === 40) { |
238 | return data.value?.financePerson; | 241 | return data.value?.financePerson; |
@@ -253,9 +256,7 @@ | @@ -253,9 +256,7 @@ | ||
253 | const extractedValues = ref<string[]>(data.value?.innerNo.map((item) => item)); | 256 | const extractedValues = ref<string[]>(data.value?.innerNo.map((item) => item)); |
254 | return extractedValues.value.join(','); | 257 | return extractedValues.value.join(','); |
255 | } else if (record?.type == 50) { | 258 | } else if (record?.type == 50) { |
256 | - if (record?.orderBaseInfo) { | ||
257 | - return record?.orderBaseInfo?.innerNo; | ||
258 | - } | 259 | + return record?.fieldInfos?.checkBillVO?.innerNo; |
259 | } | 260 | } |
260 | }, | 261 | }, |
261 | }, | 262 | }, |
@@ -282,7 +283,7 @@ | @@ -282,7 +283,7 @@ | ||
282 | if (record?.type === 40) { | 283 | if (record?.type === 40) { |
283 | data.value = record?.fieldInfos?.producePaymentCheckBillFieldVO; | 284 | data.value = record?.fieldInfos?.producePaymentCheckBillFieldVO; |
284 | } else if (record?.type == 50) { | 285 | } else if (record?.type == 50) { |
285 | - data.value = record?.fieldInfos?.checkBillOrderDO; | 286 | + data.value = record?.fieldInfos?.checkBillVO; |
286 | } | 287 | } |
287 | return data.value?.productionName; | 288 | return data.value?.productionName; |
288 | }, | 289 | }, |
@@ -349,7 +350,7 @@ | @@ -349,7 +350,7 @@ | ||
349 | async function handleDetail(data) { | 350 | async function handleDetail(data) { |
350 | if (data.type == 50) { | 351 | if (data.type == 50) { |
351 | showInvoice.value = true; | 352 | showInvoice.value = true; |
352 | - mockData.value = data.fieldInfos.checkBillOrderDO; | 353 | + mockData.value = data.fieldInfos.checkBillVO; |
353 | } else if (data.type == 40) { | 354 | } else if (data.type == 40) { |
354 | showInvoice.value = false; | 355 | showInvoice.value = false; |
355 | mockData.value = data.fieldInfos.producePaymentCheckBillFieldVO; | 356 | mockData.value = data.fieldInfos.producePaymentCheckBillFieldVO; |
src/views/project/config/data.tsx
@@ -17,15 +17,6 @@ export const COLUMNS = { | @@ -17,15 +17,6 @@ export const COLUMNS = { | ||
17 | width: 150, | 17 | width: 150, |
18 | editComponent: 'InputNumber', | 18 | editComponent: 'InputNumber', |
19 | editRow: true, | 19 | editRow: true, |
20 | - // Function to determine if the row is editable based on the value of 'relationValue' | ||
21 | - // editRow: (text) => { | ||
22 | - // console.log(text, '56565665editrecord'); // Log the text value for debugging | ||
23 | - // return false; // Only make the row editable if the value is 0.34 | ||
24 | - // }, | ||
25 | - // onEditRow: (text, record) => { | ||
26 | - // console.log(text, '56565665editrecord', record); // Log the text value for debugging | ||
27 | - // return false; // Only make the row editable if the value is 0.34 | ||
28 | - // }, | ||
29 | }, | 20 | }, |
30 | ], | 21 | ], |
31 | 2: [ | 22 | 2: [ |
@@ -253,8 +244,3 @@ export const columnsProduct: BasicColumn[] = [ | @@ -253,8 +244,3 @@ export const columnsProduct: BasicColumn[] = [ | ||
253 | editRow: true, | 244 | editRow: true, |
254 | }, | 245 | }, |
255 | ]; | 246 | ]; |
256 | -const handleEdit = (key, value) => { | ||
257 | - // Logic to update the data based on key and value | ||
258 | - // You can update the state or call your API depending on how your data is structured | ||
259 | - console.log(`Editing row ${key}, new value: ${value}`); | ||
260 | -}; |
src/views/project/finance/financeList/CheckSumCheck.vue
@@ -21,11 +21,13 @@ | @@ -21,11 +21,13 @@ | ||
21 | </template> | 21 | </template> |
22 | <script lang="ts" setup> | 22 | <script lang="ts" setup> |
23 | import { BasicModal, useModalInner } from '@/components/Modal'; | 23 | import { BasicModal, useModalInner } from '@/components/Modal'; |
24 | - import { computed, ref } from 'vue'; | 24 | + import { computed, ref, watch } from 'vue'; |
25 | import { checkAnalysis, exportCheckAnalysis } from '@/api/project/invoice'; | 25 | import { checkAnalysis, exportCheckAnalysis } from '@/api/project/invoice'; |
26 | import { BasicColumn, useTable, BasicTable, ColumnChangeParam } from '/@/components/Table'; | 26 | import { BasicColumn, useTable, BasicTable, ColumnChangeParam } from '/@/components/Table'; |
27 | // 处理弹窗的确定按钮点击事件 | 27 | // 处理弹窗的确定按钮点击事件 |
28 | import axios from 'axios'; | 28 | import axios from 'axios'; |
29 | + import { store } from '/@/store'; | ||
30 | + import { useOrderStoreWithOut } from '/@/store/modules/order'; | ||
29 | 31 | ||
30 | const columnsAnalysis: BasicColumn[] = [ | 32 | const columnsAnalysis: BasicColumn[] = [ |
31 | { | 33 | { |
@@ -81,6 +83,16 @@ | @@ -81,6 +83,16 @@ | ||
81 | const ids = ref(); | 83 | const ids = ref(); |
82 | const orderIds = ref(); | 84 | const orderIds = ref(); |
83 | // const res = ref(); | 85 | // const res = ref(); |
86 | + const dataStore = useOrderStoreWithOut(); // 获取 store 实例 | ||
87 | + const queryVO = ref(); | ||
88 | + watch( | ||
89 | + () => store.state, // 监控 queryVO | ||
90 | + (newQueryVO, oldQueryVO) => { | ||
91 | + queryVO.value = dataStore.getQueryVO; | ||
92 | + // 在这里可以根据 queryVO 的变化进行其他操作,比如重新请求数据等 | ||
93 | + }, | ||
94 | + { deep: true }, // 深度监控 queryVO 数组或对象的变化 | ||
95 | + ); | ||
84 | 96 | ||
85 | const [register, { closeModal }] = useModalInner(async (data) => { | 97 | const [register, { closeModal }] = useModalInner(async (data) => { |
86 | // ids.value = data.data; | 98 | // ids.value = data.data; |
@@ -93,7 +105,11 @@ | @@ -93,7 +105,11 @@ | ||
93 | const [registerTable, { reload }] = useTable({ | 105 | const [registerTable, { reload }] = useTable({ |
94 | // api: () => invoiceAnalysis({ ids: ids.value }), | 106 | // api: () => invoiceAnalysis({ ids: ids.value }), |
95 | api: async () => { | 107 | api: async () => { |
96 | - const res = await checkAnalysis({ ids: ids.value, orderIds: orderIds.value }); | 108 | + const res = await checkAnalysis({ |
109 | + ids: ids.value, | ||
110 | + orderIds: orderIds.value, | ||
111 | + queryVO: queryVO.value, | ||
112 | + }); | ||
97 | // 计算合计行 | 113 | // 计算合计行 |
98 | const sum = { | 114 | const sum = { |
99 | productionDepartmentTotalPrice: 0, | 115 | productionDepartmentTotalPrice: 0, |
@@ -135,7 +151,7 @@ | @@ -135,7 +151,7 @@ | ||
135 | axios | 151 | axios |
136 | .post( | 152 | .post( |
137 | '/basic-api/order/erp/check_bill/export', | 153 | '/basic-api/order/erp/check_bill/export', |
138 | - { ids: idss, orderIds: orderIds.value }, | 154 | + { ids: idss, orderIds: orderIds.value, queryVO: queryVO.value }, |
139 | { | 155 | { |
140 | responseType: 'blob', // 设置响应类型为 'blob' | 156 | responseType: 'blob', // 设置响应类型为 'blob' |
141 | }, | 157 | }, |
src/views/project/finance/financeList/FinanceEdit.vue
@@ -131,6 +131,7 @@ | @@ -131,6 +131,7 @@ | ||
131 | // 方式1 | 131 | // 方式1 |
132 | status.value = data.data.invoiceStatus; | 132 | status.value = data.data.invoiceStatus; |
133 | id.value = data.data.invoiceId; | 133 | id.value = data.data.invoiceId; |
134 | + console.log(data, '5656afds'); | ||
134 | input1.value = data.data.invoiceActualPayedAmount1; | 135 | input1.value = data.data.invoiceActualPayedAmount1; |
135 | input2.value = data.data.invoiceActualPayedAmount2; | 136 | input2.value = data.data.invoiceActualPayedAmount2; |
136 | input3.value = data.data.invoiceActualPayedAmount3; | 137 | input3.value = data.data.invoiceActualPayedAmount3; |
src/views/project/finance/financeList/InvoiceAnalysis.vue
@@ -21,11 +21,14 @@ | @@ -21,11 +21,14 @@ | ||
21 | </template> | 21 | </template> |
22 | <script lang="ts" setup> | 22 | <script lang="ts" setup> |
23 | import { BasicModal, useModalInner } from '@/components/Modal'; | 23 | import { BasicModal, useModalInner } from '@/components/Modal'; |
24 | - import { computed, ref } from 'vue'; | 24 | + import { computed, ref, watch } from 'vue'; |
25 | import { invoiceAnalysis, exportAnalysis } from '@/api/project/invoice'; | 25 | import { invoiceAnalysis, exportAnalysis } from '@/api/project/invoice'; |
26 | import { BasicColumn, useTable, BasicTable, ColumnChangeParam } from '/@/components/Table'; | 26 | import { BasicColumn, useTable, BasicTable, ColumnChangeParam } from '/@/components/Table'; |
27 | // 处理弹窗的确定按钮点击事件 | 27 | // 处理弹窗的确定按钮点击事件 |
28 | import axios from 'axios'; | 28 | import axios from 'axios'; |
29 | + import { useDataStoreWithOut } from '/@/store/modules/data'; | ||
30 | + import { useOrderStoreWithOut } from '/@/store/modules/order'; | ||
31 | + import { store } from '/@/store'; | ||
29 | 32 | ||
30 | const columnsAnalysis: BasicColumn[] = [ | 33 | const columnsAnalysis: BasicColumn[] = [ |
31 | { | 34 | { |
@@ -89,6 +92,16 @@ | @@ -89,6 +92,16 @@ | ||
89 | const ids = ref(); | 92 | const ids = ref(); |
90 | const orderIds = ref(); | 93 | const orderIds = ref(); |
91 | const tableData = ref([]); | 94 | const tableData = ref([]); |
95 | + const dataStore = useOrderStoreWithOut(); // 获取 store 实例 | ||
96 | + const queryVO = ref(); | ||
97 | + watch( | ||
98 | + () => store.state, // 监控 queryVO | ||
99 | + (newQueryVO, oldQueryVO) => { | ||
100 | + queryVO.value = dataStore.getQueryVO; | ||
101 | + // 在这里可以根据 queryVO 的变化进行其他操作,比如重新请求数据等 | ||
102 | + }, | ||
103 | + { deep: true }, // 深度监控 queryVO 数组或对象的变化 | ||
104 | + ); | ||
92 | // const res = ref(); | 105 | // const res = ref(); |
93 | 106 | ||
94 | const [register, { closeModal }] = useModalInner(async (data) => { | 107 | const [register, { closeModal }] = useModalInner(async (data) => { |
@@ -101,7 +114,11 @@ | @@ -101,7 +114,11 @@ | ||
101 | const [registerTable, { reload }] = useTable({ | 114 | const [registerTable, { reload }] = useTable({ |
102 | // api: () => invoiceAnalysis({ ids: ids.value }), | 115 | // api: () => invoiceAnalysis({ ids: ids.value }), |
103 | api: async () => { | 116 | api: async () => { |
104 | - const res = await invoiceAnalysis({ ids: ids.value, orderId: orderIds.value }); | 117 | + const res = await invoiceAnalysis({ |
118 | + ids: ids.value, | ||
119 | + orderIds: orderIds.value, | ||
120 | + queryVO: queryVO.value, | ||
121 | + }); | ||
105 | // 计算合计行 | 122 | // 计算合计行 |
106 | const sum = { | 123 | const sum = { |
107 | customerTotalPrice: 0, | 124 | customerTotalPrice: 0, |
@@ -141,7 +158,11 @@ | @@ -141,7 +158,11 @@ | ||
141 | axios | 158 | axios |
142 | .post( | 159 | .post( |
143 | '/basic-api/order/erp/invoice_bill/export', | 160 | '/basic-api/order/erp/invoice_bill/export', |
144 | - { ids: idss, orderId: orderIds.value }, | 161 | + { |
162 | + ids: idss, | ||
163 | + orderIds: orderIds.value, | ||
164 | + queryVO: queryVO.value, | ||
165 | + }, | ||
145 | { | 166 | { |
146 | responseType: 'blob', // 设置响应类型为 'blob' | 167 | responseType: 'blob', // 设置响应类型为 'blob' |
147 | }, | 168 | }, |
src/views/project/finance/financeList/finance.data.tsx
@@ -51,8 +51,8 @@ export const searchFormSchema: FormSchema[] = [ | @@ -51,8 +51,8 @@ export const searchFormSchema: FormSchema[] = [ | ||
51 | componentProps: { | 51 | componentProps: { |
52 | options: [ | 52 | options: [ |
53 | { label: '未创建', value: -1 }, | 53 | { label: '未创建', value: -1 }, |
54 | - { label: '未收款', value: 0 }, | ||
55 | - { label: '已收款', value: 10 }, | 54 | + { label: '未付款', value: 0 }, |
55 | + { label: '已付款', value: 10 }, | ||
56 | ], | 56 | ], |
57 | }, | 57 | }, |
58 | }, | 58 | }, |
@@ -484,9 +484,9 @@ export const columns: BasicColumn[] = [ | @@ -484,9 +484,9 @@ export const columns: BasicColumn[] = [ | ||
484 | if (column.record.checkPayStatus == null || column.record.checkPayStatus == undefined) { | 484 | if (column.record.checkPayStatus == null || column.record.checkPayStatus == undefined) { |
485 | return '未创建'; | 485 | return '未创建'; |
486 | } else if (column.record.checkPayStatus == 0) { | 486 | } else if (column.record.checkPayStatus == 0) { |
487 | - return '未收款'; | 487 | + return '未付款'; |
488 | } else if (column.record.checkPayStatus == 10) { | 488 | } else if (column.record.checkPayStatus == 10) { |
489 | - return '已收款'; | 489 | + return '已付款'; |
490 | } | 490 | } |
491 | }, | 491 | }, |
492 | }, | 492 | }, |
src/views/project/finance/financeList/index.vue
@@ -167,10 +167,13 @@ | @@ -167,10 +167,13 @@ | ||
167 | role == ROLE.BUSINESS | 167 | role == ROLE.BUSINESS |
168 | " | 168 | " |
169 | :actions="[ | 169 | :actions="[ |
170 | - ...(role == ROLE.ADMIN || role == ROLE.FINANCE | 170 | + ...(role == ROLE.ADMIN || |
171 | + role == ROLE.FINANCE || | ||
172 | + role == ROLE.TRACKER || | ||
173 | + role == ROLE.BUSINESS | ||
171 | ? [ | 174 | ? [ |
172 | { | 175 | { |
173 | - label: '财务编辑', | 176 | + label: '付款编辑', |
174 | onClick: handleFinanceEditCheck.bind(null, record), | 177 | onClick: handleFinanceEditCheck.bind(null, record), |
175 | }, | 178 | }, |
176 | ] | 179 | ] |
@@ -247,7 +250,7 @@ | @@ -247,7 +250,7 @@ | ||
247 | </div> | 250 | </div> |
248 | </template> | 251 | </template> |
249 | <script lang="ts" setup> | 252 | <script lang="ts" setup> |
250 | - import { computed, defineComponent, onMounted, ref } from 'vue'; | 253 | + import { computed, defineComponent, onMounted, ref, watchEffect } from 'vue'; |
251 | import { BasicTable, useTable, BasicColumn, TableAction } from '/@/components/Table'; | 254 | import { BasicTable, useTable, BasicColumn, TableAction } from '/@/components/Table'; |
252 | // import { searchFormSchema, columns } from './receive.data'; | 255 | // import { searchFormSchema, columns } from './receive.data'; |
253 | import { searchFormSchema, columns } from './finance.data'; | 256 | import { searchFormSchema, columns } from './finance.data'; |
@@ -483,10 +486,6 @@ | @@ -483,10 +486,6 @@ | ||
483 | const { createMessage } = useMessage(); | 486 | const { createMessage } = useMessage(); |
484 | const { error } = createMessage; | 487 | const { error } = createMessage; |
485 | function handleInvoiceAnalysis(record) { | 488 | function handleInvoiceAnalysis(record) { |
486 | - if (invoiceIdKeys.value.length == 0) { | ||
487 | - error('请选择订单'); | ||
488 | - return; | ||
489 | - } | ||
490 | openInvoiceAnalysis(true, { | 489 | openInvoiceAnalysis(true, { |
491 | data: invoiceIdKeys.value, | 490 | data: invoiceIdKeys.value, |
492 | id: checkedKeys.value, | 491 | id: checkedKeys.value, |
@@ -545,10 +544,6 @@ | @@ -545,10 +544,6 @@ | ||
545 | }); | 544 | }); |
546 | } | 545 | } |
547 | function handleCheckSumCheck(record) { | 546 | function handleCheckSumCheck(record) { |
548 | - if (checkIdKeys.value.length == 0) { | ||
549 | - error('请选择订单'); | ||
550 | - return; | ||
551 | - } | ||
552 | openCheckSumCheck(true, { | 547 | openCheckSumCheck(true, { |
553 | data: checkIdKeys.value, | 548 | data: checkIdKeys.value, |
554 | id: checkedKeys.value, | 549 | id: checkedKeys.value, |
src/views/project/finance/financeProfit/ProductProfit/InnerData/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.TRACKER"> | ||
17 | + <h3>基本信息</h3> | ||
18 | + <BasicForm @register="registerForm" /> | ||
19 | + </template> | ||
20 | + </div> | ||
21 | + <!-- <template #titleToolbar> <a-button type="primary"> 申请编辑权限 </a-button></template> --> | ||
22 | + | ||
23 | + <!-- <template #appendFooter> | ||
24 | + <a-button type="primary" @click="onGoFormDetail"> 返回编辑</a-button> | ||
25 | + </template> --> | ||
26 | + </BasicDrawer> | ||
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 { orderAuth } from '/@/api/project/order'; | ||
33 | + import { ROLE } from '../../../financeList/type.d'; | ||
34 | + import { useModal } from '/@/components/Modal'; | ||
35 | + | ||
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 | ||
43 | + .map((item) => ({ | ||
44 | + field: `${item.field}`, | ||
45 | + dataIndex: `${item.field}`, | ||
46 | + label: item.label, | ||
47 | + component: 'Switch', | ||
48 | + componentProps: { | ||
49 | + checkedValue: 'UN_LOCKED', | ||
50 | + unCheckedValue: 'LOCKED', | ||
51 | + }, | ||
52 | + colProps: { | ||
53 | + span: 6, | ||
54 | + }, | ||
55 | + })) | ||
56 | + .filter( | ||
57 | + (item) => | ||
58 | + // item.field !== 'packetPrice' && | ||
59 | + item.field !== 'exchangeRate' && item.field !== 'profitRate', | ||
60 | + ); | ||
61 | + | ||
62 | + export default defineComponent({ | ||
63 | + components: { BasicDrawer, BasicForm }, | ||
64 | + props: { | ||
65 | + onGoFormDetail: { | ||
66 | + type: Function, | ||
67 | + }, | ||
68 | + }, | ||
69 | + setup() { | ||
70 | + const id = ref(''); | ||
71 | + const schemas = getSchema(FIELDS_BASE_INFO); | ||
72 | + const [registerForm, { getFieldsValue }] = useForm({ | ||
73 | + labelWidth: 120, | ||
74 | + schemas, | ||
75 | + showActionButtonGroup: false, | ||
76 | + actionColOptions: { | ||
77 | + span: 24, | ||
78 | + }, | ||
79 | + }); | ||
80 | + const lockFields = reactive({}); | ||
81 | + const [register, { closeDrawer }] = useDrawerInner((data) => { | ||
82 | + Object.assign(lockFields, data.lockFields); | ||
83 | + id.value = data.id; | ||
84 | + }); | ||
85 | + function handleCloseModal() { | ||
86 | + closeDrawer(); | ||
87 | + } | ||
88 | + | ||
89 | + const role = computed(() => { | ||
90 | + return userStore.getUserInfo?.roleSmallVO?.code; | ||
91 | + }); | ||
92 | + | ||
93 | + const handleSubmit = async () => { | ||
94 | + const baseFieldValues = getFieldsValue(); | ||
95 | + | ||
96 | + if (baseFieldValues) { | ||
97 | + FIELDS_BASE_INFO.map( | ||
98 | + ({ field }) => | ||
99 | + (baseFieldValues[field] = | ||
100 | + baseFieldValues[field] === 'UN_LOCKED' ? 'UN_LOCKED' : 'LOCKED'), | ||
101 | + ); | ||
102 | + } | ||
103 | + const values = Object.assign({ orderId: id.value }, { baseFields: baseFieldValues }); | ||
104 | + | ||
105 | + if ( | ||
106 | + values.baseFields && | ||
107 | + (values.baseFields.projectNo === 'UN_LOCKED' || | ||
108 | + values.baseFields.productionDepartment === 'UN_LOCKED' || | ||
109 | + values.baseFields.innerNo === 'UN_LOCKED' || | ||
110 | + values.baseFields.customerCode === 'UN_LOCKED' || | ||
111 | + values.baseFields.customerPo === 'UN_LOCKED' || | ||
112 | + values.baseFields.customerStyle === 'UN_LOCKED') | ||
113 | + ) { | ||
114 | + openReasonModal(true, { | ||
115 | + data: values, | ||
116 | + }); | ||
117 | + } else { | ||
118 | + await orderAuth(values); | ||
119 | + closeDrawer(); | ||
120 | + } | ||
121 | + }; | ||
122 | + | ||
123 | + return { | ||
124 | + register, | ||
125 | + schemas, | ||
126 | + registerForm, | ||
127 | + handleSubmit, | ||
128 | + handleCloseModal, | ||
129 | + ROLE, | ||
130 | + role, | ||
131 | + }; | ||
132 | + }, | ||
133 | + }); | ||
134 | +</script> | ||
135 | +<style> | ||
136 | + .container { | ||
137 | + position: fixed; /* 或 absolute, fixed */ | ||
138 | + z-index: 10; | ||
139 | + } | ||
140 | +</style> |
src/views/project/finance/financeProfit/ProductProfit/InnerData/FinanceEdit.vue
0 → 100644
1 | +<template> | ||
2 | + <template> | ||
3 | + <BasicDrawer | ||
4 | + @register="register" | ||
5 | + v-bind="$attrs" | ||
6 | + title="编辑" | ||
7 | + width="30%" | ||
8 | + :isDetail="true" | ||
9 | + @ok="handleSubmit" | ||
10 | + :showDetailBack="false" | ||
11 | + okText="保存" | ||
12 | + showFooter | ||
13 | + :destroyOnClose="true" | ||
14 | + > | ||
15 | + <!-- <div> | ||
16 | + <BasicForm @register="registerForm" /> | ||
17 | + </div> --> | ||
18 | + <div style="font-size: 15px">生产科预算金额</div> | ||
19 | + <a-input | ||
20 | + v-model:value="input1" | ||
21 | + placeholder="请输入" | ||
22 | + :disabled="status1 === 'LOCKED'" | ||
23 | + auto-size | ||
24 | + /> | ||
25 | + <div style="margin: 16px 0"></div> | ||
26 | + <div style="font-size: 15px">实际发生费用</div> | ||
27 | + <a-input | ||
28 | + v-model:value="input2" | ||
29 | + placeholder="请输入" | ||
30 | + :disabled="status2 === 'LOCKED'" | ||
31 | + auto-size | ||
32 | + /> | ||
33 | + <div style="margin: 16px 0"></div> | ||
34 | + | ||
35 | + <!-- <template #titleToolbar> <a-button type="primary"> 申请编辑权限 </a-button></template> --> | ||
36 | + <template #appendFooter> | ||
37 | + <!-- <a-button type="primary" @click="onGoCheckDetail"> 申请权限</a-button> --> | ||
38 | + </template> | ||
39 | + </BasicDrawer> | ||
40 | + </template> | ||
41 | +</template> | ||
42 | +<script lang="ts" setup> | ||
43 | + import { BasicDrawer, useDrawerInner } from '@/components/Drawer'; | ||
44 | + import { BasicForm, FormSchema, useForm } from '@/components/Form'; | ||
45 | + import { defineComponent, ref, computed, unref, toRaw, reactive } from 'vue'; | ||
46 | + import { getPackageEdit } from '@/api/project/invoice'; | ||
47 | + import { useMessage } from '/@/hooks/web/useMessage'; | ||
48 | + import { ROLE } from './type.d'; | ||
49 | + | ||
50 | + const emit = defineEmits(['success']); | ||
51 | + const role = computed(() => { | ||
52 | + return user?.roleSmallVO?.code; | ||
53 | + }); | ||
54 | + const schemas: FormSchema[] = [ | ||
55 | + // { | ||
56 | + // field: 'totalPayAmount', | ||
57 | + // component: 'InputNumber', | ||
58 | + // labelWidth: 250, | ||
59 | + // colProps: { | ||
60 | + // span: 23, | ||
61 | + // }, | ||
62 | + // label: '实际应收金额', | ||
63 | + // }, | ||
64 | + { | ||
65 | + field: 'actualPayedAmount1', | ||
66 | + component: 'InputNumber', | ||
67 | + labelWidth: 250, | ||
68 | + colProps: { | ||
69 | + span: 23, | ||
70 | + }, | ||
71 | + componentProps: () => ({ | ||
72 | + disabled: status.value === 10, | ||
73 | + }), | ||
74 | + label: '实际应收金额1$', | ||
75 | + }, | ||
76 | + { | ||
77 | + field: 'actualPayedAmount2', | ||
78 | + component: 'InputNumber', | ||
79 | + labelWidth: 250, | ||
80 | + colProps: { | ||
81 | + span: 23, | ||
82 | + }, | ||
83 | + componentProps: () => ({ | ||
84 | + disabled: status.value === 10, | ||
85 | + }), | ||
86 | + label: '实际应收金额2$', | ||
87 | + }, | ||
88 | + { | ||
89 | + field: 'actualPayedAmount3', | ||
90 | + component: 'InputNumber', | ||
91 | + labelWidth: 250, | ||
92 | + colProps: { | ||
93 | + span: 23, | ||
94 | + }, | ||
95 | + componentProps: () => ({ | ||
96 | + disabled: status.value === 10, | ||
97 | + }), | ||
98 | + label: '实际应收金额3$', | ||
99 | + }, | ||
100 | + { | ||
101 | + field: 'otherAmount', | ||
102 | + component: 'InputNumber', | ||
103 | + labelWidth: 250, | ||
104 | + colProps: { | ||
105 | + span: 23, | ||
106 | + }, | ||
107 | + componentProps: () => ({ | ||
108 | + disabled: status.value === 10, | ||
109 | + }), | ||
110 | + label: '其他费用金额$', | ||
111 | + }, | ||
112 | + ]; | ||
113 | + const [registerForm, { setFieldsValue, resetFields, validate }] = useForm({ | ||
114 | + labelWidth: 120, | ||
115 | + schemas, | ||
116 | + layout: 'vertical', | ||
117 | + showActionButtonGroup: false, | ||
118 | + actionColOptions: { | ||
119 | + span: 24, | ||
120 | + }, | ||
121 | + }); | ||
122 | + const { createMessage } = useMessage(); | ||
123 | + const { error } = createMessage; | ||
124 | + | ||
125 | + const update = ref(); | ||
126 | + const status1 = ref(); | ||
127 | + const status2 = ref(); | ||
128 | + | ||
129 | + const input1 = ref(); | ||
130 | + const input2 = ref(); | ||
131 | + const id = ref(); | ||
132 | + const [register, { setDrawerProps, closeDrawer }] = useDrawerInner((data) => { | ||
133 | + // 方式1 | ||
134 | + if (data.data.lockFields) { | ||
135 | + status1.value = data.data?.productionDepartmentPredictPrice; | ||
136 | + status2.value = data.data?.productionActualPrice; | ||
137 | + } | ||
138 | + | ||
139 | + id.value = data.data.orderId; | ||
140 | + input1.value = data.data?.productionDepartmentPredictPrice.toFixed(2); | ||
141 | + input2.value = data.data?.productionActualPrice.toFixed(2); | ||
142 | + resetFields(); | ||
143 | + setDrawerProps({ confirmLoading: false }); | ||
144 | + setFieldsValue({ | ||
145 | + ...toRaw(data.data), | ||
146 | + }); | ||
147 | + update.value = data; | ||
148 | + }); | ||
149 | + //完成编辑 | ||
150 | + async function handleSubmit() { | ||
151 | + // const values = await validate(); | ||
152 | + // const updatedValues = { | ||
153 | + // ...values, | ||
154 | + // id: update.value.data.id, | ||
155 | + // bgUrl: update.value.data.bgUrl, | ||
156 | + // }; | ||
157 | + if (!input1.value || !input2.value) { | ||
158 | + error('选项不能为空'); | ||
159 | + } else { | ||
160 | + await getPackageEdit({ | ||
161 | + orderId: id.value, | ||
162 | + productionDepartmentPredictPrice: input1.value, | ||
163 | + productionActualPrice: input2.value, | ||
164 | + }); | ||
165 | + emit('success'); | ||
166 | + closeDrawer(); | ||
167 | + } | ||
168 | + } | ||
169 | +</script> |
src/views/project/finance/financeProfit/ProductProfit/InnerData/data.tsx
0 → 100644
1 | +import { InputNumber, Tag } from 'ant-design-vue'; | ||
2 | +import { BasicColumn } from '@/components/Table'; | ||
3 | +import { func } from 'vue-types'; | ||
4 | +import { h, ref } from 'vue'; | ||
5 | +import { FilePptOutlined } from '@ant-design/icons-vue'; | ||
6 | + | ||
7 | +// export const COLUMNS = [ | ||
8 | +// { | ||
9 | +// title: '客户编码', | ||
10 | +// dataIndex: 'settingValue', | ||
11 | +// width: 150, | ||
12 | +// }, | ||
13 | +// { | ||
14 | +// title: '利润率', | ||
15 | +// dataIndex: 'relationValue', | ||
16 | +// width: 150, | ||
17 | +// editComponent: 'InputNumber', | ||
18 | +// editRow: true, | ||
19 | +// scopedSlots: { customRender: 'name' } | ||
20 | +// }, | ||
21 | +// ]; | ||
22 | +export const COLUMNS = [ | ||
23 | + { | ||
24 | + title: '客户编码', | ||
25 | + dataIndex: 'customerCode', | ||
26 | + width: 150, | ||
27 | + }, | ||
28 | + { | ||
29 | + title: '项目号', | ||
30 | + dataIndex: 'projectNo', | ||
31 | + width: 100, | ||
32 | + }, | ||
33 | + { | ||
34 | + title: '生产科', | ||
35 | + dataIndex: 'productionDepartment', | ||
36 | + width: 100, | ||
37 | + }, | ||
38 | + { | ||
39 | + title: '内部编号', | ||
40 | + dataIndex: 'innerNo', | ||
41 | + width: 100, | ||
42 | + }, | ||
43 | + { | ||
44 | + title: '订单图片', | ||
45 | + dataIndex: 'picUrl', | ||
46 | + width: 100, | ||
47 | + }, | ||
48 | + { | ||
49 | + title: '数量', | ||
50 | + dataIndex: 'orderCount', | ||
51 | + width: 100, | ||
52 | + }, | ||
53 | + { | ||
54 | + title: '生产科总价¥', | ||
55 | + width: 150, | ||
56 | + dataIndex: 'productionDepartmentTotalPrice', | ||
57 | + customRender: (column) => { | ||
58 | + console.log(column, '5656csd'); | ||
59 | + return column.record?.productionDepartmentTotalPrice?.toFixed(2); | ||
60 | + }, | ||
61 | + }, | ||
62 | + { | ||
63 | + title: '生产科预算金额¥', | ||
64 | + width: 150, | ||
65 | + dataIndex: 'productionDepartmentPredictPrice', | ||
66 | + customRender: (column) => { | ||
67 | + return column.record?.productionDepartmentPredictPrice?.toFixed(2); | ||
68 | + }, | ||
69 | + }, | ||
70 | + { | ||
71 | + title: '实际发生费用¥', | ||
72 | + dataIndex: 'productionActualPrice', | ||
73 | + width: 120, | ||
74 | + customRender: (column) => { | ||
75 | + return column.record?.productionActualPrice?.toFixed(2); | ||
76 | + }, | ||
77 | + }, | ||
78 | + { | ||
79 | + title: '预算占比', | ||
80 | + dataIndex: 'predictRatio', | ||
81 | + width: 120, | ||
82 | + customRender: (column) => { | ||
83 | + return column.record?.predictRatio?.toFixed(2); | ||
84 | + }, | ||
85 | + }, | ||
86 | + { | ||
87 | + title: '预算占比差', | ||
88 | + dataIndex: 'predictAndActualRatio', | ||
89 | + width: 120, | ||
90 | + customRender: (column) => { | ||
91 | + return column.record?.predictAndActualRatio?.toFixed(2); | ||
92 | + }, | ||
93 | + }, | ||
94 | + { | ||
95 | + title: '事前毛利润', | ||
96 | + dataIndex: 'beforeGrossProfit', | ||
97 | + width: 120, | ||
98 | + customRender: (column) => { | ||
99 | + return column.record?.beforeGrossProfit?.toFixed(2); | ||
100 | + }, | ||
101 | + }, | ||
102 | + { | ||
103 | + title: '事前毛利率', | ||
104 | + dataIndex: 'beforeGrossProfitRate', | ||
105 | + width: 120, | ||
106 | + customRender: (column) => { | ||
107 | + return column.record?.beforeGrossProfitRate?.toFixed(2); | ||
108 | + }, | ||
109 | + }, | ||
110 | + { | ||
111 | + title: '事后毛利润', | ||
112 | + dataIndex: 'grossProfit', | ||
113 | + width: 120, | ||
114 | + customRender: (column) => { | ||
115 | + return column.record?.grossProfit?.toFixed(2); | ||
116 | + }, | ||
117 | + }, | ||
118 | + { | ||
119 | + title: '事后毛利率', | ||
120 | + dataIndex: 'grossProfitRate', | ||
121 | + width: 120, | ||
122 | + customRender: (column) => { | ||
123 | + return column.record?.grossProfitRate?.toFixed(2); | ||
124 | + }, | ||
125 | + }, | ||
126 | + { | ||
127 | + title: '内部生产固定成本¥', | ||
128 | + dataIndex: 'innerProductionFixedCost', | ||
129 | + width: 120, | ||
130 | + customRender: (column) => { | ||
131 | + return column.record?.innerProductionFixedCost?.toFixed(2); | ||
132 | + }, | ||
133 | + }, | ||
134 | + { | ||
135 | + title: '内部生产提成¥', | ||
136 | + dataIndex: 'innerProductionCommission', | ||
137 | + width: 120, | ||
138 | + customRender: (column) => { | ||
139 | + return column.record?.innerProductionCommission?.toFixed(2); | ||
140 | + }, | ||
141 | + }, | ||
142 | + { | ||
143 | + title: '内部生产净利润¥', | ||
144 | + dataIndex: 'innerProductionProfit', | ||
145 | + width: 120, | ||
146 | + customRender: (column) => { | ||
147 | + return column.record?.innerProductionProfit?.toFixed(2); | ||
148 | + }, | ||
149 | + }, | ||
150 | + { | ||
151 | + title: '内部生产净利润率', | ||
152 | + dataIndex: 'innerProductionProfitRate', | ||
153 | + width: 120, | ||
154 | + customRender: (column) => { | ||
155 | + return column.record?.innerProductionProfitRate?.toFixed(2); | ||
156 | + }, | ||
157 | + }, | ||
158 | +]; | ||
0 | \ No newline at end of file | 159 | \ No newline at end of file |
src/views/project/finance/financeProfit/ProductProfit/InnerData/index.vue
0 → 100644
1 | +<template> | ||
2 | + <div> | ||
3 | + <BasicTable @register="registerTable" :bordered="true"> | ||
4 | + <template #bodyCell="{ column, record }"> | ||
5 | + <template v-if="column.key === 'picUrl'"> | ||
6 | + <img :z-index="100000" :width="50" :height="50" :src="record?.picUrl" /> | ||
7 | + </template> | ||
8 | + <template v-if="column.key === 'action'"> | ||
9 | + <TableAction :actions="createActions(record)" /> | ||
10 | + </template> | ||
11 | + <!-- <template v-if="column.key === 'relationValue'"> | ||
12 | + <a-input | ||
13 | + v-if="record.settingValue === 'A01'" | ||
14 | + v-model:value="record.settingValue" | ||
15 | + :max-length="50" | ||
16 | + /> | ||
17 | + <span v-else style="color: red"> | ||
18 | + {{ record.settingValue }} | ||
19 | + </span> | ||
20 | + </template> --> | ||
21 | + </template> | ||
22 | + </BasicTable> | ||
23 | + <!-- <BasicModal | ||
24 | + title="拒绝原因" | ||
25 | + width="30%" | ||
26 | + @register="registerModal" | ||
27 | + @visible-change="handleClose" | ||
28 | + @ok="handleOk" | ||
29 | + wrapClassName="approve-modal" | ||
30 | + > | ||
31 | + <div className="pa-8"> | ||
32 | + <a-textarea :rows="6" placeholder="请输入拒绝原因" v-model:value="message" /> | ||
33 | + </div> | ||
34 | + </BasicModal> --> | ||
35 | + <CheckDetail @register="checkModalRegister" /> | ||
36 | + <FinanceEdit @register="registerFinanceEdit" @success="handleSuccess" /> | ||
37 | + </div> | ||
38 | +</template> | ||
39 | +<script setup lang="ts"> | ||
40 | + import { BasicTable, useTable, TableAction } from '/@/components/Table'; | ||
41 | + import { getInnerProfit } from '@/api/project/invoice'; | ||
42 | + import { COLUMNS } from './data'; | ||
43 | + import { BasicModal, useModal } from '/@/components/Modal'; | ||
44 | + import { useMessage } from '/@/hooks/web/useMessage'; | ||
45 | + import { ref } from 'vue'; | ||
46 | + import { useDrawer } from '/@/components/Drawer'; | ||
47 | + import FinanceEdit from './FinanceEdit.vue'; | ||
48 | + import CheckDetail from './CheckDetail.vue'; | ||
49 | + | ||
50 | + const { createMessage } = useMessage(); | ||
51 | + const { error } = createMessage; | ||
52 | + const message = ref(); | ||
53 | + const [checkModalRegister, { openDrawer: openCheckDetailDrawer }] = useDrawer(); | ||
54 | + const [registerFinanceEdit, { openDrawer: openFinanceEdit }] = useDrawer(); | ||
55 | + const handleOk = (record) => { | ||
56 | + // 修改父组件的状态 | ||
57 | + console.log(message.value, '5656messsage', record); | ||
58 | + closeModal(); | ||
59 | + }; | ||
60 | + const handleClose = (visible: boolean) => { | ||
61 | + if (!visible) { | ||
62 | + message.value = ''; | ||
63 | + } | ||
64 | + }; | ||
65 | + const [registerTable, { reload }] = useTable({ | ||
66 | + api: getInnerProfit, | ||
67 | + bordered: true, | ||
68 | + columns: COLUMNS, | ||
69 | + rowKey: 'id', | ||
70 | + useSearchForm: true, | ||
71 | + actionColumn: { | ||
72 | + width: 240, | ||
73 | + title: 'Action', | ||
74 | + dataIndex: 'action', | ||
75 | + }, | ||
76 | + }); | ||
77 | + function createActions(record: any): any[] { | ||
78 | + if (!record.editable) { | ||
79 | + return [ | ||
80 | + { | ||
81 | + label: '财务编辑', | ||
82 | + onClick: handleFinanceEdit.bind(null, record), | ||
83 | + }, | ||
84 | + // { | ||
85 | + // label: '编辑', | ||
86 | + // onClick: handleEdit.bind(null, record), | ||
87 | + // }, | ||
88 | + // { | ||
89 | + // label: '删除', | ||
90 | + // popConfirm: { | ||
91 | + // title: '确认删除?', | ||
92 | + // confirm: handleDelete.bind(null, record), | ||
93 | + // }, | ||
94 | + // }, | ||
95 | + { | ||
96 | + label: '申请权限', | ||
97 | + // popConfirm: { | ||
98 | + // title: '确认申请?', | ||
99 | + // confirm: handleFalse.bind(null, record), | ||
100 | + // }, | ||
101 | + onClick: handleFalse.bind(null, record), | ||
102 | + }, | ||
103 | + ]; | ||
104 | + } | ||
105 | + return [ | ||
106 | + { | ||
107 | + label: '保存', | ||
108 | + onClick: handleSave.bind(null, record), | ||
109 | + }, | ||
110 | + { | ||
111 | + label: '取消', | ||
112 | + popConfirm: { | ||
113 | + title: '是否取消编辑', | ||
114 | + confirm: handleCancel.bind(null, record), | ||
115 | + }, | ||
116 | + }, | ||
117 | + ]; | ||
118 | + } | ||
119 | + | ||
120 | + function handleFinanceEdit(record) { | ||
121 | + openFinanceEdit(true, { | ||
122 | + data: record, | ||
123 | + }); | ||
124 | + } | ||
125 | + | ||
126 | + function handleFalse(record, e) { | ||
127 | + openCheckDetailDrawer(true, record); | ||
128 | + e?.stopPropagation(); | ||
129 | + return false; | ||
130 | + } | ||
131 | + | ||
132 | + // async function handleFalse(record: any) { | ||
133 | + // console.log(record); | ||
134 | + // // openModal(true, { record }); | ||
135 | + // } | ||
136 | + | ||
137 | + async function handleSave(record) { | ||
138 | + await saveConfig({ id: record.id, relationValue: record.relationValue }); | ||
139 | + handleCancel(record); | ||
140 | + reload(); | ||
141 | + } | ||
142 | + function handleEdit(record: any) { | ||
143 | + console.log(record, '5656edit'); | ||
144 | + // if (record.settingValue == 'A01') { | ||
145 | + // error('请勿连续点击生成按钮,需要等待三秒再点击生成'); | ||
146 | + // } else { | ||
147 | + record.onEdit?.(true); | ||
148 | + // } | ||
149 | + } | ||
150 | + | ||
151 | + function handleCancel(record) { | ||
152 | + record.onEdit?.(false, false); | ||
153 | + } | ||
154 | + | ||
155 | + async function handleDelete(record) { | ||
156 | + await deleteConfig({ ids: [record.id] }); | ||
157 | + reload(); | ||
158 | + } | ||
159 | + function handleSuccess() { | ||
160 | + setTimeout(() => { | ||
161 | + reload(); | ||
162 | + }, 50); | ||
163 | + } | ||
164 | +</script> | ||
165 | +<style></style> |
src/views/project/finance/financeProfit/ProductProfit/InnerData/tableData.tsx
0 → 100644
1 | +import { ref } from 'vue'; | ||
2 | +import { ROLE } from '../../../financeList/type.d'; | ||
3 | +import { queryNoOptions } from '/@/api/project/order'; | ||
4 | +import { useOrderInfo } from '/@/hooks/component/order'; | ||
5 | +import { useOrderStoreWithOut } from '/@/store/modules/order'; | ||
6 | +import { formatToDate } from '/@/utils/dateUtil'; | ||
7 | + | ||
8 | +// 角色 | ||
9 | +// 业务员- 查看all,编辑-利润分析,报告书 | ||
10 | +// 跟单员- 查看利润分析(单价和总金额),跟单,质检,编辑 | ||
11 | +// 质检员- 查看跟单,质检,编辑质检 | ||
12 | + | ||
13 | +const innerNoOptions = ref([]); | ||
14 | +const projectNoOptions = ref([]); | ||
15 | +const orderStore = useOrderStoreWithOut(); | ||
16 | +// const { productionDepartment: productionDepartmentOptions } = useOrderInfo(orderStore); | ||
17 | + | ||
18 | +/** | ||
19 | + * drawer面板的字段 | ||
20 | + */ | ||
21 | +// 基本信息 | ||
22 | +export const FIELDS_BASE_INFO = [ | ||
23 | + { | ||
24 | + field: 'customerCode', | ||
25 | + component: 'Select', | ||
26 | + labelWidth: 150, | ||
27 | + label: '客户编码', | ||
28 | + rules: [{ required: true }], | ||
29 | + }, | ||
30 | + { | ||
31 | + field: 'projectNo', | ||
32 | + component: 'Input', | ||
33 | + labelWidth: 150, | ||
34 | + label: '项目号', | ||
35 | + rules: [{ required: true }], | ||
36 | + }, | ||
37 | + { | ||
38 | + field: 'productionDepartment', | ||
39 | + component: 'Select', | ||
40 | + // componentProps: { | ||
41 | + // options: productionDepartmentOptions, | ||
42 | + // }, | ||
43 | + labelWidth: 150, | ||
44 | + label: '生产科', | ||
45 | + rules: [{ required: true }], | ||
46 | + }, | ||
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 | +]; | ||
94 | + |
src/views/project/finance/financeProfit/ProductProfit/InnerProduce/FinanceEdit.vue
0 → 100644
1 | +<template> | ||
2 | + <template> | ||
3 | + <BasicDrawer | ||
4 | + @register="register" | ||
5 | + v-bind="$attrs" | ||
6 | + title="收入款单" | ||
7 | + width="30%" | ||
8 | + :isDetail="true" | ||
9 | + @ok="handleSubmit" | ||
10 | + :showDetailBack="false" | ||
11 | + okText="保存" | ||
12 | + showFooter | ||
13 | + :destroyOnClose="true" | ||
14 | + > | ||
15 | + <!-- <div> | ||
16 | + <BasicForm @register="registerForm" /> | ||
17 | + </div> --> | ||
18 | + <div style="font-size: 15px">实际收款金额1$</div> | ||
19 | + <a-input v-model:value="input1" placeholder="请输入" :disabled="status === 10" auto-size /> | ||
20 | + <div style="margin: 16px 0"></div> | ||
21 | + <div style="font-size: 15px">实际收款金额2$</div> | ||
22 | + <a-input v-model:value="input2" placeholder="请输入" :disabled="status === 10" auto-size /> | ||
23 | + <div style="margin: 16px 0"></div> | ||
24 | + <div style="font-size: 15px">项目开始时间</div> | ||
25 | + <a-date-picker v-model:value="input3" :disabled="status === 10" auto-size /> | ||
26 | + <div style="margin: 16px 0"></div> | ||
27 | + <div style="font-size: 15px">项目结束时间</div> | ||
28 | + <a-date-picker v-model:value="input4" :disabled="status === 10" auto-size /> | ||
29 | + <div style="margin: 16px 0"></div> | ||
30 | + | ||
31 | + <!-- <template #titleToolbar> <a-button type="primary"> 申请编辑权限 </a-button></template> --> | ||
32 | + <template #appendFooter> | ||
33 | + <!-- <a-button type="primary" @click="onGoCheckDetail"> 申请权限</a-button> --> | ||
34 | + </template> | ||
35 | + </BasicDrawer> | ||
36 | + </template> | ||
37 | +</template> | ||
38 | +<script lang="ts" setup> | ||
39 | + import { BasicDrawer, useDrawerInner } from '@/components/Drawer'; | ||
40 | + import { BasicForm, FormSchema, useForm } from '@/components/Form'; | ||
41 | + import { defineComponent, ref, computed, unref, toRaw, reactive } from 'vue'; | ||
42 | + import { getEmailList } from '/@/api/sys/config'; | ||
43 | + import { updateAmount } from '@/api/project/invoice'; | ||
44 | + import { useMessage } from '/@/hooks/web/useMessage'; | ||
45 | + import { ROLE } from './type.d'; | ||
46 | + | ||
47 | + const emit = defineEmits(['success']); | ||
48 | + const role = computed(() => { | ||
49 | + return user?.roleSmallVO?.code; | ||
50 | + }); | ||
51 | + const schemas: FormSchema[] = [ | ||
52 | + // { | ||
53 | + // field: 'totalPayAmount', | ||
54 | + // component: 'InputNumber', | ||
55 | + // labelWidth: 250, | ||
56 | + // colProps: { | ||
57 | + // span: 23, | ||
58 | + // }, | ||
59 | + // label: '实际应收金额', | ||
60 | + // }, | ||
61 | + { | ||
62 | + field: 'actualPayedAmount1', | ||
63 | + component: 'InputNumber', | ||
64 | + labelWidth: 250, | ||
65 | + colProps: { | ||
66 | + span: 23, | ||
67 | + }, | ||
68 | + componentProps: () => ({ | ||
69 | + disabled: status.value === 10, | ||
70 | + }), | ||
71 | + label: '实际应收金额1$', | ||
72 | + }, | ||
73 | + { | ||
74 | + field: 'actualPayedAmount2', | ||
75 | + component: 'InputNumber', | ||
76 | + labelWidth: 250, | ||
77 | + colProps: { | ||
78 | + span: 23, | ||
79 | + }, | ||
80 | + componentProps: () => ({ | ||
81 | + disabled: status.value === 10, | ||
82 | + }), | ||
83 | + label: '实际应收金额2$', | ||
84 | + }, | ||
85 | + { | ||
86 | + field: 'actualPayedAmount3', | ||
87 | + component: 'InputNumber', | ||
88 | + labelWidth: 250, | ||
89 | + colProps: { | ||
90 | + span: 23, | ||
91 | + }, | ||
92 | + componentProps: () => ({ | ||
93 | + disabled: status.value === 10, | ||
94 | + }), | ||
95 | + label: '实际应收金额3$', | ||
96 | + }, | ||
97 | + { | ||
98 | + field: 'otherAmount', | ||
99 | + component: 'InputNumber', | ||
100 | + labelWidth: 250, | ||
101 | + colProps: { | ||
102 | + span: 23, | ||
103 | + }, | ||
104 | + componentProps: () => ({ | ||
105 | + disabled: status.value === 10, | ||
106 | + }), | ||
107 | + label: '其他费用金额$', | ||
108 | + }, | ||
109 | + ]; | ||
110 | + const [registerForm, { setFieldsValue, resetFields, validate }] = useForm({ | ||
111 | + labelWidth: 120, | ||
112 | + schemas, | ||
113 | + layout: 'vertical', | ||
114 | + showActionButtonGroup: false, | ||
115 | + actionColOptions: { | ||
116 | + span: 24, | ||
117 | + }, | ||
118 | + }); | ||
119 | + const { createMessage } = useMessage(); | ||
120 | + const { error } = createMessage; | ||
121 | + | ||
122 | + const update = ref(); | ||
123 | + const status = ref(); | ||
124 | + | ||
125 | + const input1 = ref(); | ||
126 | + const input2 = ref(); | ||
127 | + const input3 = ref(); | ||
128 | + const input4 = ref(); | ||
129 | + const id = ref(); | ||
130 | + const [register, { setDrawerProps, closeDrawer }] = useDrawerInner((data) => { | ||
131 | + // 方式1 | ||
132 | + status.value = data.data.invoiceStatus; | ||
133 | + id.value = data.data.invoiceId; | ||
134 | + input1.value = data.data.invoiceActualPayedAmount1; | ||
135 | + input2.value = data.data.invoiceActualPayedAmount2; | ||
136 | + input3.value = data.data.invoiceActualPayedAmount3; | ||
137 | + input4.value = data.data.invoiceOtherAmount; | ||
138 | + resetFields(); | ||
139 | + setDrawerProps({ confirmLoading: false }); | ||
140 | + setFieldsValue({ | ||
141 | + ...toRaw(data.data), | ||
142 | + }); | ||
143 | + update.value = data; | ||
144 | + }); | ||
145 | + //完成编辑 | ||
146 | + async function handleSubmit() { | ||
147 | + // const values = await validate(); | ||
148 | + // const updatedValues = { | ||
149 | + // ...values, | ||
150 | + // id: update.value.data.id, | ||
151 | + // bgUrl: update.value.data.bgUrl, | ||
152 | + // }; | ||
153 | + if (!input1.value || !input2.value || !input3.value || !input4.value) { | ||
154 | + error('选项不能为空'); | ||
155 | + } else { | ||
156 | + await updateAmount({ | ||
157 | + id: id.value, | ||
158 | + actualPayedAmount1: input1.value, | ||
159 | + actualPayedAmount2: input2.value, | ||
160 | + actualPayedAmount3: input3.value, | ||
161 | + otherAmount: input4.value, | ||
162 | + }); | ||
163 | + emit('success'); | ||
164 | + closeDrawer(); | ||
165 | + } | ||
166 | + } | ||
167 | +</script> |
src/views/project/finance/financeProfit/ProductProfit/InnerProduce/data.tsx
0 → 100644
1 | +import { InputNumber, Tag } from 'ant-design-vue'; | ||
2 | +import { BasicColumn } from '@/components/Table'; | ||
3 | +import { func } from 'vue-types'; | ||
4 | +import { h, ref } from 'vue'; | ||
5 | +import { FilePptOutlined } from '@ant-design/icons-vue'; | ||
6 | +import axios from 'axios'; | ||
7 | + | ||
8 | +// export const COLUMNS = [ | ||
9 | +// { | ||
10 | +// title: '客户编码', | ||
11 | +// dataIndex: 'settingValue', | ||
12 | +// width: 150, | ||
13 | +// }, | ||
14 | +// { | ||
15 | +// title: '利润率', | ||
16 | +// dataIndex: 'relationValue', | ||
17 | +// width: 150, | ||
18 | +// editComponent: 'InputNumber', | ||
19 | +// editRow: true, | ||
20 | +// scopedSlots: { customRender: 'name' } | ||
21 | +// }, | ||
22 | +// ]; | ||
23 | +export const COLUMNS = [ | ||
24 | + { | ||
25 | + title: '客户编码', | ||
26 | + dataIndex: 'customerCode', | ||
27 | + width: 150, | ||
28 | + }, | ||
29 | + { | ||
30 | + title: '项目号', | ||
31 | + dataIndex: 'projectNoPrefix', | ||
32 | + width: 100, | ||
33 | + }, | ||
34 | + { | ||
35 | + title: '生产科', | ||
36 | + dataIndex: 'productionDepartment', | ||
37 | + width: 100, | ||
38 | + }, | ||
39 | + { | ||
40 | + title: '数量', | ||
41 | + dataIndex: 'orderCount', | ||
42 | + width: 100, | ||
43 | + }, | ||
44 | + { | ||
45 | + title: '生产科单价¥', | ||
46 | + dataIndex: 'productionDepartmentPrice', | ||
47 | + width: 120, | ||
48 | + customRender: (column) => { | ||
49 | + console.log(column, '5656column'); | ||
50 | + return column.record?.productionDepartmentPrice?.toFixed(2); | ||
51 | + }, | ||
52 | + }, | ||
53 | + { | ||
54 | + title: '生产科总价¥', | ||
55 | + dataIndex: 'productionDepartmentTotalPrice', | ||
56 | + width: 120, | ||
57 | + customRender: (column) => { | ||
58 | + console.log(column, '5656column'); | ||
59 | + return column.record?.productionDepartmentTotalPrice?.toFixed(2); | ||
60 | + }, | ||
61 | + }, | ||
62 | + { | ||
63 | + title: '生产科预算金额', | ||
64 | + dataIndex: 'productionDepartmentPredictPrice', | ||
65 | + width: 120, | ||
66 | + customRender: (column) => { | ||
67 | + return column.record?.productionDepartmentPredictPrice?.toFixed(2); | ||
68 | + }, | ||
69 | + }, | ||
70 | + { | ||
71 | + title: '实际发生费用', | ||
72 | + dataIndex: 'productionActualPrice', | ||
73 | + width: 120, | ||
74 | + customRender: (column) => { | ||
75 | + return column.record?.productionActualPrice?.toFixed(2); | ||
76 | + }, | ||
77 | + }, | ||
78 | + { | ||
79 | + title: '预算占比', | ||
80 | + dataIndex: 'predictRatio', | ||
81 | + width: 120, | ||
82 | + customRender: (column) => { | ||
83 | + return column.record?.predictRatio?.toFixed(2); | ||
84 | + }, | ||
85 | + }, | ||
86 | + { | ||
87 | + title: '预算占比与实际占比差', | ||
88 | + dataIndex: 'predictAndActualRatio', | ||
89 | + width: 150, | ||
90 | + customRender: (column) => { | ||
91 | + return column.record?.predictAndActualRatio?.toFixed(2); | ||
92 | + }, | ||
93 | + }, | ||
94 | + { | ||
95 | + title: '事前毛利润', | ||
96 | + dataIndex: 'beforeGrossProfit', | ||
97 | + width: 120, | ||
98 | + customRender: (column) => { | ||
99 | + return column.record?.beforeGrossProfit?.toFixed(2); | ||
100 | + }, | ||
101 | + }, | ||
102 | + { | ||
103 | + title: '事前毛利率', | ||
104 | + dataIndex: 'beforeGrossProfitRate', | ||
105 | + width: 120, | ||
106 | + customRender: (column) => { | ||
107 | + return column.record?.beforeGrossProfitRate?.toFixed(2); | ||
108 | + }, | ||
109 | + }, | ||
110 | + { | ||
111 | + title: '事后毛利润', | ||
112 | + dataIndex: 'grossProfit', | ||
113 | + width: 120, | ||
114 | + customRender: (column) => { | ||
115 | + return column.record?.grossProfit?.toFixed(2); | ||
116 | + }, | ||
117 | + }, | ||
118 | + { | ||
119 | + title: '事后毛利率', | ||
120 | + dataIndex: 'grossProfitRate', | ||
121 | + width: 120, | ||
122 | + customRender: (column) => { | ||
123 | + return column.record?.grossProfitRate?.toFixed(2); | ||
124 | + }, | ||
125 | + }, | ||
126 | + { | ||
127 | + title: '文件', | ||
128 | + dataIndex: 'fileUrl', | ||
129 | + width: 120, | ||
130 | + customRender: (column) => { | ||
131 | + // 构造符合 API 要求的参数 | ||
132 | + // await exportAnalysis({ ids: ids }); | ||
133 | + const handleClick = () => { | ||
134 | + axios | ||
135 | + .post( | ||
136 | + '/basic-api/project/innerProfit/export', | ||
137 | + { | ||
138 | + projectNoPrefix: column.record.projectNoPrefix, | ||
139 | + }, | ||
140 | + { | ||
141 | + responseType: 'blob', // 设置响应类型为 'blob' | ||
142 | + }, | ||
143 | + ) | ||
144 | + .then((response) => { | ||
145 | + // 创建一个 Blob 对象来保存二进制数据 | ||
146 | + const blob = new Blob([response.data], { type: 'application/zip' }); | ||
147 | + const getFormattedDate = (): string => { | ||
148 | + const date = new Date(); | ||
149 | + | ||
150 | + const year = date.getFullYear(); | ||
151 | + const month = String(date.getMonth() + 1).padStart(2, '0'); | ||
152 | + const day = String(date.getDate()).padStart(2, '0'); | ||
153 | + | ||
154 | + const hours = String(date.getHours()).padStart(2, '0'); | ||
155 | + const minutes = String(date.getMinutes()).padStart(2, '0'); | ||
156 | + const seconds = String(date.getSeconds()).padStart(2, '0'); | ||
157 | + | ||
158 | + return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; | ||
159 | + }; | ||
160 | + const date = getFormattedDate(); | ||
161 | + // 创建一个链接元素用于下载 | ||
162 | + const link = document.createElement('a'); | ||
163 | + link.href = window.URL.createObjectURL(blob); | ||
164 | + link.download = `${date}.xlsx`; // 你可以为文件命名 | ||
165 | + document.body.appendChild(link); | ||
166 | + link.click(); // 自动点击链接,触发下载 | ||
167 | + document.body.removeChild(link); // 下载完成后移除链接 | ||
168 | + }) | ||
169 | + .catch((error) => { | ||
170 | + console.error(error); | ||
171 | + }); | ||
172 | + }; | ||
173 | + return <FilePptOutlined style="font-size:25px" onClick={() => handleClick()} />; | ||
174 | + }, | ||
175 | + }, | ||
176 | +]; | ||
0 | \ No newline at end of file | 177 | \ No newline at end of file |
src/views/project/finance/financeProfit/ProductProfit/InnerProduce/index.vue
0 → 100644
1 | +<template> | ||
2 | + <div> | ||
3 | + <BasicTable @register="registerTable" :bordered="true"> | ||
4 | + <template #bodyCell="{ column, record }"> | ||
5 | + <template v-if="column.key === 'picUrl'"> | ||
6 | + <img :z-index="100000" :width="50" :height="50" :src="record?.picUrl" /> | ||
7 | + </template> | ||
8 | + <!-- <template v-if="column.key === 'action'"> | ||
9 | + <TableAction :actions="createActions(record)" /> | ||
10 | + </template> --> | ||
11 | + <!-- <template v-if="column.key === 'relationValue'"> | ||
12 | + <a-input | ||
13 | + v-if="record.settingValue === 'A01'" | ||
14 | + v-model:value="record.settingValue" | ||
15 | + :max-length="50" | ||
16 | + /> | ||
17 | + <span v-else style="color: red"> | ||
18 | + {{ record.settingValue }} | ||
19 | + </span> | ||
20 | + </template> --> | ||
21 | + </template> | ||
22 | + </BasicTable> | ||
23 | + <!-- <BasicModal | ||
24 | + title="拒绝原因" | ||
25 | + width="30%" | ||
26 | + @register="registerModal" | ||
27 | + @visible-change="handleClose" | ||
28 | + @ok="handleOk" | ||
29 | + wrapClassName="approve-modal" | ||
30 | + > | ||
31 | + <div className="pa-8"> | ||
32 | + <a-textarea :rows="6" placeholder="请输入拒绝原因" v-model:value="message" /> | ||
33 | + </div> | ||
34 | + </BasicModal> --> | ||
35 | + <FinanceEdit @register="registerFinanceEdit" @success="handleSuccess" /> | ||
36 | + </div> | ||
37 | +</template> | ||
38 | +<script setup lang="ts"> | ||
39 | + import { BasicTable, useTable, TableAction } from '/@/components/Table'; | ||
40 | + import { getInnerProduceProfit } from '@/api/project/invoice'; | ||
41 | + import { COLUMNS } from './data'; | ||
42 | + import { BasicModal, useModal } from '/@/components/Modal'; | ||
43 | + import { useMessage } from '/@/hooks/web/useMessage'; | ||
44 | + import { ref } from 'vue'; | ||
45 | + import { useDrawer } from '/@/components/Drawer'; | ||
46 | + import FinanceEdit from './FinanceEdit.vue'; | ||
47 | + | ||
48 | + const { createMessage } = useMessage(); | ||
49 | + const { error } = createMessage; | ||
50 | + const message = ref(); | ||
51 | + const [registerFinanceEdit, { openDrawer: openFinanceEdit }] = useDrawer(); | ||
52 | + const handleOk = (record) => { | ||
53 | + // 修改父组件的状态 | ||
54 | + console.log(message.value, '5656messsage', record); | ||
55 | + closeModal(); | ||
56 | + }; | ||
57 | + const handleClose = (visible: boolean) => { | ||
58 | + if (!visible) { | ||
59 | + message.value = ''; | ||
60 | + } | ||
61 | + }; | ||
62 | + const [registerTable, { reload }] = useTable({ | ||
63 | + api: getInnerProduceProfit, | ||
64 | + bordered: true, | ||
65 | + columns: COLUMNS, | ||
66 | + rowKey: 'id', | ||
67 | + useSearchForm: true, | ||
68 | + // actionColumn: { | ||
69 | + // width: 240, | ||
70 | + // title: 'Action', | ||
71 | + // dataIndex: 'action', | ||
72 | + // }, | ||
73 | + }); | ||
74 | + | ||
75 | + // function createActions(record: any): any[] { | ||
76 | + // if (!record.editable) { | ||
77 | + // return [ | ||
78 | + // // { | ||
79 | + // // label: '财务编辑', | ||
80 | + // // onClick: handleFinanceEdit.bind(null, record), | ||
81 | + // // }, | ||
82 | + // // { | ||
83 | + // // label: '编辑', | ||
84 | + // // onClick: handleEdit.bind(null, record), | ||
85 | + // // }, | ||
86 | + // // { | ||
87 | + // // label: '删除', | ||
88 | + // // popConfirm: { | ||
89 | + // // title: '确认删除?', | ||
90 | + // // confirm: handleDelete.bind(null, record), | ||
91 | + // // }, | ||
92 | + // // }, | ||
93 | + // // { | ||
94 | + // // label: '申请权限', | ||
95 | + // // // popConfirm: { | ||
96 | + // // // title: '确认申请?', | ||
97 | + // // // confirm: handleFalse.bind(null, record), | ||
98 | + // // // }, | ||
99 | + // // onClick: handleFalse.bind(null, record), | ||
100 | + // // }, | ||
101 | + // ]; | ||
102 | + // } | ||
103 | + // return [ | ||
104 | + // { | ||
105 | + // label: '保存', | ||
106 | + // onClick: handleSave.bind(null, record), | ||
107 | + // }, | ||
108 | + // { | ||
109 | + // label: '取消', | ||
110 | + // popConfirm: { | ||
111 | + // title: '是否取消编辑', | ||
112 | + // confirm: handleCancel.bind(null, record), | ||
113 | + // }, | ||
114 | + // }, | ||
115 | + // ]; | ||
116 | + // } | ||
117 | + | ||
118 | + function handleFinanceEdit(record) { | ||
119 | + openFinanceEdit(true, { | ||
120 | + data: record, | ||
121 | + }); | ||
122 | + } | ||
123 | + | ||
124 | + // async function handleFalse(record: any) { | ||
125 | + // console.log(record); | ||
126 | + // // openModal(true, { record }); | ||
127 | + // } | ||
128 | + | ||
129 | + async function handleSave(record) { | ||
130 | + await saveConfig({ id: record.id, relationValue: record.relationValue }); | ||
131 | + handleCancel(record); | ||
132 | + reload(); | ||
133 | + } | ||
134 | + function handleEdit(record: any) { | ||
135 | + console.log(record, '5656edit'); | ||
136 | + // if (record.settingValue == 'A01') { | ||
137 | + // error('请勿连续点击生成按钮,需要等待三秒再点击生成'); | ||
138 | + // } else { | ||
139 | + record.onEdit?.(true); | ||
140 | + // } | ||
141 | + } | ||
142 | + | ||
143 | + function handleCancel(record) { | ||
144 | + record.onEdit?.(false, false); | ||
145 | + } | ||
146 | + | ||
147 | + async function handleDelete(record) { | ||
148 | + await deleteConfig({ ids: [record.id] }); | ||
149 | + reload(); | ||
150 | + } | ||
151 | +</script> | ||
152 | +<style></style> |
src/views/project/finance/financeProfit/ProductProfit/InnerProduce/tableData.tsx
0 → 100644
1 | +import { ref } from 'vue'; | ||
2 | +import { ROLE } from '../../../financeList/type.d'; | ||
3 | +import { queryNoOptions } from '/@/api/project/order'; | ||
4 | +import { useOrderInfo } from '/@/hooks/component/order'; | ||
5 | +import { useOrderStoreWithOut } from '/@/store/modules/order'; | ||
6 | +import { formatToDate } from '/@/utils/dateUtil'; | ||
7 | + | ||
8 | +// 角色 | ||
9 | +// 业务员- 查看all,编辑-利润分析,报告书 | ||
10 | +// 跟单员- 查看利润分析(单价和总金额),跟单,质检,编辑 | ||
11 | +// 质检员- 查看跟单,质检,编辑质检 | ||
12 | + | ||
13 | +const innerNoOptions = ref([]); | ||
14 | +const projectNoOptions = ref([]); | ||
15 | +const orderStore = useOrderStoreWithOut(); | ||
16 | +// const { productionDepartment: productionDepartmentOptions } = useOrderInfo(orderStore); | ||
17 | + | ||
18 | +/** | ||
19 | + * drawer面板的字段 | ||
20 | + */ | ||
21 | +// 基本信息 | ||
22 | +export const FIELDS_BASE_INFO = [ | ||
23 | + { | ||
24 | + field: 'customerCode', | ||
25 | + component: 'Select', | ||
26 | + labelWidth: 150, | ||
27 | + label: '客户编码', | ||
28 | + rules: [{ required: true }], | ||
29 | + }, | ||
30 | + { | ||
31 | + field: 'projectNo', | ||
32 | + component: 'Input', | ||
33 | + labelWidth: 150, | ||
34 | + label: '项目号', | ||
35 | + rules: [{ required: true }], | ||
36 | + }, | ||
37 | + { | ||
38 | + field: 'productionDepartment', | ||
39 | + component: 'Select', | ||
40 | + // componentProps: { | ||
41 | + // options: productionDepartmentOptions, | ||
42 | + // }, | ||
43 | + labelWidth: 150, | ||
44 | + label: '生产科', | ||
45 | + rules: [{ required: true }], | ||
46 | + }, | ||
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 | +]; | ||
94 | + |
src/views/project/finance/financeProfit/ServiceProfit/PackageProfit/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.TRACKER"> | ||
17 | + <h3>基本信息</h3> | ||
18 | + <BasicForm @register="registerForm" /> | ||
19 | + </template> | ||
20 | + </div> | ||
21 | + <!-- <template #titleToolbar> <a-button type="primary"> 申请编辑权限 </a-button></template> --> | ||
22 | + | ||
23 | + <!-- <template #appendFooter> | ||
24 | + <a-button type="primary" @click="onGoFormDetail"> 返回编辑</a-button> | ||
25 | + </template> --> | ||
26 | + </BasicDrawer> | ||
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 { orderAuth } from '/@/api/project/order'; | ||
33 | + import { ROLE } from '../../../financeList/type.d'; | ||
34 | + import { useModal } from '/@/components/Modal'; | ||
35 | + | ||
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 | ||
43 | + .map((item) => ({ | ||
44 | + field: `${item.field}`, | ||
45 | + dataIndex: `${item.field}`, | ||
46 | + label: item.label, | ||
47 | + component: 'Switch', | ||
48 | + componentProps: { | ||
49 | + checkedValue: 'UN_LOCKED', | ||
50 | + unCheckedValue: 'LOCKED', | ||
51 | + }, | ||
52 | + colProps: { | ||
53 | + span: 6, | ||
54 | + }, | ||
55 | + })) | ||
56 | + .filter( | ||
57 | + (item) => | ||
58 | + // item.field !== 'packetPrice' && | ||
59 | + item.field !== 'exchangeRate' && item.field !== 'profitRate', | ||
60 | + ); | ||
61 | + | ||
62 | + export default defineComponent({ | ||
63 | + components: { BasicDrawer, BasicForm }, | ||
64 | + props: { | ||
65 | + onGoFormDetail: { | ||
66 | + type: Function, | ||
67 | + }, | ||
68 | + }, | ||
69 | + setup() { | ||
70 | + const id = ref(''); | ||
71 | + const schemas = getSchema(FIELDS_BASE_INFO); | ||
72 | + const [registerForm, { getFieldsValue }] = useForm({ | ||
73 | + labelWidth: 120, | ||
74 | + schemas, | ||
75 | + showActionButtonGroup: false, | ||
76 | + actionColOptions: { | ||
77 | + span: 24, | ||
78 | + }, | ||
79 | + }); | ||
80 | + const lockFields = reactive({}); | ||
81 | + const [register, { closeDrawer }] = useDrawerInner((data) => { | ||
82 | + Object.assign(lockFields, data.lockFields); | ||
83 | + id.value = data.id; | ||
84 | + }); | ||
85 | + function handleCloseModal() { | ||
86 | + closeDrawer(); | ||
87 | + } | ||
88 | + | ||
89 | + const role = computed(() => { | ||
90 | + return userStore.getUserInfo?.roleSmallVO?.code; | ||
91 | + }); | ||
92 | + | ||
93 | + const handleSubmit = async () => { | ||
94 | + const baseFieldValues = getFieldsValue(); | ||
95 | + | ||
96 | + if (baseFieldValues) { | ||
97 | + FIELDS_BASE_INFO.map( | ||
98 | + ({ field }) => | ||
99 | + (baseFieldValues[field] = | ||
100 | + baseFieldValues[field] === 'UN_LOCKED' ? 'UN_LOCKED' : 'LOCKED'), | ||
101 | + ); | ||
102 | + } | ||
103 | + const values = Object.assign({ orderId: id.value }, { baseFields: baseFieldValues }); | ||
104 | + | ||
105 | + if ( | ||
106 | + values.baseFields && | ||
107 | + (values.baseFields.projectNo === 'UN_LOCKED' || | ||
108 | + values.baseFields.productionDepartment === 'UN_LOCKED' || | ||
109 | + values.baseFields.innerNo === 'UN_LOCKED' || | ||
110 | + values.baseFields.customerCode === 'UN_LOCKED' || | ||
111 | + values.baseFields.customerPo === 'UN_LOCKED' || | ||
112 | + values.baseFields.customerStyle === 'UN_LOCKED') | ||
113 | + ) { | ||
114 | + openReasonModal(true, { | ||
115 | + data: values, | ||
116 | + }); | ||
117 | + } else { | ||
118 | + await orderAuth(values); | ||
119 | + closeDrawer(); | ||
120 | + } | ||
121 | + }; | ||
122 | + | ||
123 | + return { | ||
124 | + register, | ||
125 | + schemas, | ||
126 | + registerForm, | ||
127 | + handleSubmit, | ||
128 | + handleCloseModal, | ||
129 | + ROLE, | ||
130 | + role, | ||
131 | + }; | ||
132 | + }, | ||
133 | + }); | ||
134 | +</script> | ||
135 | +<style> | ||
136 | + .container { | ||
137 | + position: fixed; /* 或 absolute, fixed */ | ||
138 | + z-index: 10; | ||
139 | + } | ||
140 | +</style> |
src/views/project/finance/financeProfit/ServiceProfit/PackageProfit/FinanceEdit.vue
0 → 100644
1 | +<template> | ||
2 | + <template> | ||
3 | + <BasicDrawer | ||
4 | + @register="register" | ||
5 | + v-bind="$attrs" | ||
6 | + title="编辑" | ||
7 | + width="30%" | ||
8 | + :isDetail="true" | ||
9 | + @ok="handleSubmit" | ||
10 | + :showDetailBack="false" | ||
11 | + okText="保存" | ||
12 | + showFooter | ||
13 | + :destroyOnClose="true" | ||
14 | + > | ||
15 | + <!-- <div> | ||
16 | + <BasicForm @register="registerForm" /> | ||
17 | + </div> --> | ||
18 | + <div style="font-size: 15px">包装费用实际金额¥</div> | ||
19 | + <a-input | ||
20 | + v-model:value="input1" | ||
21 | + placeholder="请输入" | ||
22 | + :disabled="status === 'LOCKED'" | ||
23 | + auto-size | ||
24 | + /> | ||
25 | + <div style="margin: 16px 0"></div> | ||
26 | + | ||
27 | + <!-- <template #titleToolbar> <a-button type="primary"> 申请编辑权限 </a-button></template> --> | ||
28 | + <template #appendFooter> | ||
29 | + <!-- <a-button type="primary" @click="onGoCheckDetail"> 申请权限</a-button> --> | ||
30 | + </template> | ||
31 | + </BasicDrawer> | ||
32 | + </template> | ||
33 | +</template> | ||
34 | +<script lang="ts" setup> | ||
35 | + import { BasicDrawer, useDrawerInner } from '@/components/Drawer'; | ||
36 | + import { BasicForm, FormSchema, useForm } from '@/components/Form'; | ||
37 | + import { defineComponent, ref, computed, unref, toRaw, reactive } from 'vue'; | ||
38 | + import { getPackageEdit } from '@/api/project/invoice'; | ||
39 | + import { useMessage } from '/@/hooks/web/useMessage'; | ||
40 | + import { ROLE } from './type.d'; | ||
41 | + | ||
42 | + const emit = defineEmits(['success']); | ||
43 | + const role = computed(() => { | ||
44 | + return user?.roleSmallVO?.code; | ||
45 | + }); | ||
46 | + const schemas: FormSchema[] = [ | ||
47 | + // { | ||
48 | + // field: 'totalPayAmount', | ||
49 | + // component: 'InputNumber', | ||
50 | + // labelWidth: 250, | ||
51 | + // colProps: { | ||
52 | + // span: 23, | ||
53 | + // }, | ||
54 | + // label: '实际应收金额', | ||
55 | + // }, | ||
56 | + { | ||
57 | + field: 'actualPayedAmount1', | ||
58 | + component: 'InputNumber', | ||
59 | + labelWidth: 250, | ||
60 | + colProps: { | ||
61 | + span: 23, | ||
62 | + }, | ||
63 | + componentProps: () => ({ | ||
64 | + disabled: status.value === 10, | ||
65 | + }), | ||
66 | + label: '实际应收金额1$', | ||
67 | + }, | ||
68 | + { | ||
69 | + field: 'actualPayedAmount2', | ||
70 | + component: 'InputNumber', | ||
71 | + labelWidth: 250, | ||
72 | + colProps: { | ||
73 | + span: 23, | ||
74 | + }, | ||
75 | + componentProps: () => ({ | ||
76 | + disabled: status.value === 10, | ||
77 | + }), | ||
78 | + label: '实际应收金额2$', | ||
79 | + }, | ||
80 | + { | ||
81 | + field: 'actualPayedAmount3', | ||
82 | + component: 'InputNumber', | ||
83 | + labelWidth: 250, | ||
84 | + colProps: { | ||
85 | + span: 23, | ||
86 | + }, | ||
87 | + componentProps: () => ({ | ||
88 | + disabled: status.value === 10, | ||
89 | + }), | ||
90 | + label: '实际应收金额3$', | ||
91 | + }, | ||
92 | + { | ||
93 | + field: 'otherAmount', | ||
94 | + component: 'InputNumber', | ||
95 | + labelWidth: 250, | ||
96 | + colProps: { | ||
97 | + span: 23, | ||
98 | + }, | ||
99 | + componentProps: () => ({ | ||
100 | + disabled: status.value === 10, | ||
101 | + }), | ||
102 | + label: '其他费用金额$', | ||
103 | + }, | ||
104 | + ]; | ||
105 | + const [registerForm, { setFieldsValue, resetFields, validate }] = useForm({ | ||
106 | + labelWidth: 120, | ||
107 | + schemas, | ||
108 | + layout: 'vertical', | ||
109 | + showActionButtonGroup: false, | ||
110 | + actionColOptions: { | ||
111 | + span: 24, | ||
112 | + }, | ||
113 | + }); | ||
114 | + const { createMessage } = useMessage(); | ||
115 | + const { error } = createMessage; | ||
116 | + | ||
117 | + const update = ref(); | ||
118 | + const status = ref(); | ||
119 | + | ||
120 | + const input1 = ref(); | ||
121 | + const id = ref(); | ||
122 | + const [register, { setDrawerProps, closeDrawer }] = useDrawerInner((data) => { | ||
123 | + // 方式1 | ||
124 | + if (data.data.lockFields) { | ||
125 | + status.value = data.data.lockFields?.packetActualRmbPrice; | ||
126 | + } | ||
127 | + id.value = data.data.orderId; | ||
128 | + input1.value = data.data?.packetActualRmbTotalPrice; | ||
129 | + resetFields(); | ||
130 | + setDrawerProps({ confirmLoading: false }); | ||
131 | + setFieldsValue({ | ||
132 | + ...toRaw(data.data), | ||
133 | + }); | ||
134 | + update.value = data; | ||
135 | + }); | ||
136 | + //完成编辑 | ||
137 | + async function handleSubmit() { | ||
138 | + // const values = await validate(); | ||
139 | + // const updatedValues = { | ||
140 | + // ...values, | ||
141 | + // id: update.value.data.id, | ||
142 | + // bgUrl: update.value.data.bgUrl, | ||
143 | + // }; | ||
144 | + if (!input1.value) { | ||
145 | + error('选项不能为空'); | ||
146 | + } else { | ||
147 | + await getPackageEdit({ | ||
148 | + orderId: id.value, | ||
149 | + packetActualRmbTotalPrice: input1.value, | ||
150 | + }); | ||
151 | + emit('success'); | ||
152 | + closeDrawer(); | ||
153 | + } | ||
154 | + } | ||
155 | +</script> |
src/views/project/finance/financeProfit/ServiceProfit/PackageProfit/data.tsx
0 → 100644
1 | +import { InputNumber, Tag } from 'ant-design-vue'; | ||
2 | +import { BasicColumn } from '@/components/Table'; | ||
3 | +import { func } from 'vue-types'; | ||
4 | +import { h, ref } from 'vue'; | ||
5 | +import { FilePptOutlined } from '@ant-design/icons-vue'; | ||
6 | + | ||
7 | +// export const COLUMNS = [ | ||
8 | +// { | ||
9 | +// title: '客户编码', | ||
10 | +// dataIndex: 'settingValue', | ||
11 | +// width: 150, | ||
12 | +// }, | ||
13 | +// { | ||
14 | +// title: '利润率', | ||
15 | +// dataIndex: 'relationValue', | ||
16 | +// width: 150, | ||
17 | +// editComponent: 'InputNumber', | ||
18 | +// editRow: true, | ||
19 | +// scopedSlots: { customRender: 'name' } | ||
20 | +// }, | ||
21 | +// ]; | ||
22 | +export const COLUMNS = [ | ||
23 | + { | ||
24 | + title: '客户编码', | ||
25 | + dataIndex: 'customerCode', | ||
26 | + width: 150, | ||
27 | + }, | ||
28 | + { | ||
29 | + title: '项目号', | ||
30 | + dataIndex: 'projectNo', | ||
31 | + width: 100, | ||
32 | + }, | ||
33 | + { | ||
34 | + title: '生产科', | ||
35 | + dataIndex: 'productionDepartment', | ||
36 | + width: 100, | ||
37 | + }, | ||
38 | + { | ||
39 | + title: '内部编号', | ||
40 | + dataIndex: 'innerNo', | ||
41 | + width: 100, | ||
42 | + }, | ||
43 | + { | ||
44 | + title: '订单图片', | ||
45 | + dataIndex: 'picUrl', | ||
46 | + width: 100, | ||
47 | + }, | ||
48 | + { | ||
49 | + title: '数量', | ||
50 | + dataIndex: 'orderCount', | ||
51 | + width: 100, | ||
52 | + }, | ||
53 | + { | ||
54 | + title: '包装费用$', | ||
55 | + dataIndex: 'packetPrice', | ||
56 | + width: 120, | ||
57 | + customRender: (column) => { | ||
58 | + console.log(column, '565665pa'); | ||
59 | + return column.record?.packetPrice?.toFixed(2); | ||
60 | + }, | ||
61 | + }, | ||
62 | + { | ||
63 | + title: '包装费用合计¥', | ||
64 | + dataIndex: 'packetRmbTotalPrice', | ||
65 | + width: 120, | ||
66 | + customRender: (column) => { | ||
67 | + console.log(column, '565665pa'); | ||
68 | + return column.record?.packetRmbTotalPrice?.toFixed(2); | ||
69 | + }, | ||
70 | + }, | ||
71 | + { | ||
72 | + title: '包装费用合计$', | ||
73 | + dataIndex: 'packetTotalPrice', | ||
74 | + width: 120, | ||
75 | + customRender: (column) => { | ||
76 | + console.log(column, '5656column'); | ||
77 | + | ||
78 | + return column.record?.packetTotalPrice?.toFixed(2); | ||
79 | + }, | ||
80 | + }, | ||
81 | + { | ||
82 | + title: '包装费用实际金额¥', | ||
83 | + dataIndex: 'packetActualRmbTotalPrice', | ||
84 | + width: 150, | ||
85 | + customRender: (column) => { | ||
86 | + return column.record?.packetActualRmbTotalPrice?.toFixed(2); | ||
87 | + }, | ||
88 | + }, | ||
89 | + { | ||
90 | + title: '实际跟单单价¥', | ||
91 | + dataIndex: 'packetActualRmbPrice', | ||
92 | + width: 120, | ||
93 | + customRender: (column) => { | ||
94 | + return column.record?.packetActualRmbPrice?.toFixed(2); | ||
95 | + }, | ||
96 | + }, | ||
97 | + { | ||
98 | + title: '实际跟单单价折算美金$', | ||
99 | + dataIndex: 'packetActualPrice', | ||
100 | + width: 170, | ||
101 | + customRender: (column) => { | ||
102 | + return column.record?.packetActualPrice?.toFixed(2); | ||
103 | + }, | ||
104 | + }, | ||
105 | + { | ||
106 | + title: '包装费用收益¥', | ||
107 | + dataIndex: 'packetProfitRmbPrice', | ||
108 | + width: 120, | ||
109 | + customRender: (column) => { | ||
110 | + return column.record?.packetProfitRmbPrice?.toFixed(2); | ||
111 | + }, | ||
112 | + }, | ||
113 | + { | ||
114 | + title: '包装费用净利润率', | ||
115 | + dataIndex: 'packetProfitRate', | ||
116 | + width: 140, | ||
117 | + customRender: (column) => { | ||
118 | + return column.record?.packetProfitRate?.toFixed(2); | ||
119 | + }, | ||
120 | + }, | ||
121 | +]; | ||
0 | \ No newline at end of file | 122 | \ No newline at end of file |
src/views/project/finance/financeProfit/ServiceProfit/PackageProfit/index.vue
0 → 100644
1 | +<template> | ||
2 | + <div> | ||
3 | + <BasicTable @register="registerTable" :bordered="true"> | ||
4 | + <template #bodyCell="{ column, record }"> | ||
5 | + <template v-if="column.key === 'picUrl'"> | ||
6 | + <img :z-index="100000" :width="50" :height="50" :src="record?.picUrl" /> | ||
7 | + </template> | ||
8 | + <template v-if="column.key === 'action'"> | ||
9 | + <TableAction :actions="createActions(record)" /> | ||
10 | + </template> | ||
11 | + <!-- <template v-if="column.key === 'relationValue'"> | ||
12 | + <a-input | ||
13 | + v-if="record.settingValue === 'A01'" | ||
14 | + v-model:value="record.settingValue" | ||
15 | + :max-length="50" | ||
16 | + /> | ||
17 | + <span v-else style="color: red"> | ||
18 | + {{ record.settingValue }} | ||
19 | + </span> | ||
20 | + </template> --> | ||
21 | + </template> | ||
22 | + </BasicTable> | ||
23 | + <!-- <BasicModal | ||
24 | + title="拒绝原因" | ||
25 | + width="30%" | ||
26 | + @register="registerModal" | ||
27 | + @visible-change="handleClose" | ||
28 | + @ok="handleOk" | ||
29 | + wrapClassName="approve-modal" | ||
30 | + > | ||
31 | + <div className="pa-8"> | ||
32 | + <a-textarea :rows="6" placeholder="请输入拒绝原因" v-model:value="message" /> | ||
33 | + </div> | ||
34 | + </BasicModal> --> | ||
35 | + <CheckDetail @register="checkModalRegister" :onGoFormDetail="handleGoFormDetail" /> | ||
36 | + <FinanceEdit @register="registerFinanceEdit" @success="handleSuccess" /> | ||
37 | + </div> | ||
38 | +</template> | ||
39 | +<script setup lang="ts"> | ||
40 | + import { BasicTable, useTable, TableAction } from '/@/components/Table'; | ||
41 | + import { getPackageProfit } from '@/api/project/invoice'; | ||
42 | + import { COLUMNS } from './data'; | ||
43 | + import { BasicModal, useModal } from '/@/components/Modal'; | ||
44 | + import { useMessage } from '/@/hooks/web/useMessage'; | ||
45 | + import { ref } from 'vue'; | ||
46 | + import { useDrawer } from '/@/components/Drawer'; | ||
47 | + import FinanceEdit from './FinanceEdit.vue'; | ||
48 | + import CheckDetail from './CheckDetail.vue'; | ||
49 | + | ||
50 | + const { createMessage } = useMessage(); | ||
51 | + const { error } = createMessage; | ||
52 | + const message = ref(); | ||
53 | + const [checkModalRegister, { openDrawer: openCheckDetailDrawer }] = useDrawer(); | ||
54 | + const [registerFinanceEdit, { openDrawer: openFinanceEdit }] = useDrawer(); | ||
55 | + const handleOk = (record) => { | ||
56 | + // 修改父组件的状态 | ||
57 | + console.log(message.value, '5656messsage', record); | ||
58 | + closeModal(); | ||
59 | + }; | ||
60 | + const handleClose = (visible: boolean) => { | ||
61 | + if (!visible) { | ||
62 | + message.value = ''; | ||
63 | + } | ||
64 | + }; | ||
65 | + const [registerTable, { reload }] = useTable({ | ||
66 | + api: getPackageProfit, | ||
67 | + bordered: true, | ||
68 | + columns: COLUMNS, | ||
69 | + rowKey: 'id', | ||
70 | + useSearchForm: true, | ||
71 | + actionColumn: { | ||
72 | + width: 240, | ||
73 | + title: 'Action', | ||
74 | + dataIndex: 'action', | ||
75 | + }, | ||
76 | + }); | ||
77 | + | ||
78 | + function createActions(record: any): any[] { | ||
79 | + if (!record.editable) { | ||
80 | + return [ | ||
81 | + { | ||
82 | + label: '财务编辑', | ||
83 | + onClick: handleFinanceEdit.bind(null, record), | ||
84 | + }, | ||
85 | + // { | ||
86 | + // label: '编辑', | ||
87 | + // onClick: handleEdit.bind(null, record), | ||
88 | + // }, | ||
89 | + // { | ||
90 | + // label: '删除', | ||
91 | + // popConfirm: { | ||
92 | + // title: '确认删除?', | ||
93 | + // confirm: handleDelete.bind(null, record), | ||
94 | + // }, | ||
95 | + // }, | ||
96 | + { | ||
97 | + label: '申请权限', | ||
98 | + // popConfirm: { | ||
99 | + // title: '确认申请?', | ||
100 | + // confirm: handleFalse.bind(null, record), | ||
101 | + // }, | ||
102 | + onClick: handleFalse.bind(null, record), | ||
103 | + }, | ||
104 | + ]; | ||
105 | + } | ||
106 | + return [ | ||
107 | + { | ||
108 | + label: '保存', | ||
109 | + onClick: handleSave.bind(null, record), | ||
110 | + }, | ||
111 | + { | ||
112 | + label: '取消', | ||
113 | + popConfirm: { | ||
114 | + title: '是否取消编辑', | ||
115 | + confirm: handleCancel.bind(null, record), | ||
116 | + }, | ||
117 | + }, | ||
118 | + ]; | ||
119 | + } | ||
120 | + | ||
121 | + function handleFinanceEdit(record) { | ||
122 | + openFinanceEdit(true, { | ||
123 | + data: record, | ||
124 | + }); | ||
125 | + } | ||
126 | + | ||
127 | + function handleFalse(record, e) { | ||
128 | + openCheckDetailDrawer(true, record); | ||
129 | + e?.stopPropagation(); | ||
130 | + return false; | ||
131 | + } | ||
132 | + function handleSuccess() { | ||
133 | + setTimeout(() => { | ||
134 | + reload(); | ||
135 | + }, 50); | ||
136 | + } | ||
137 | + // async function handleFalse(record: any) { | ||
138 | + // console.log(record); | ||
139 | + // // openModal(true, { record }); | ||
140 | + // } | ||
141 | + | ||
142 | + async function handleSave(record) { | ||
143 | + await saveConfig({ id: record.id, relationValue: record.relationValue }); | ||
144 | + handleCancel(record); | ||
145 | + reload(); | ||
146 | + } | ||
147 | + function handleEdit(record: any) { | ||
148 | + console.log(record, '5656edit'); | ||
149 | + // if (record.settingValue == 'A01') { | ||
150 | + // error('请勿连续点击生成按钮,需要等待三秒再点击生成'); | ||
151 | + // } else { | ||
152 | + record.onEdit?.(true); | ||
153 | + // } | ||
154 | + } | ||
155 | + | ||
156 | + function handleCancel(record) { | ||
157 | + record.onEdit?.(false, false); | ||
158 | + } | ||
159 | + | ||
160 | + // async function handleDelete(record) { | ||
161 | + // await deleteConfig({ ids: [record.id] }); | ||
162 | + // reload(); | ||
163 | + // } | ||
164 | +</script> | ||
165 | +<style></style> |
src/views/project/finance/financeProfit/ServiceProfit/PackageProfit/tableData.tsx
0 → 100644
1 | +import { ref } from 'vue'; | ||
2 | +import { ROLE } from '../../../financeList/type.d'; | ||
3 | +import { queryNoOptions } from '/@/api/project/order'; | ||
4 | +import { useOrderInfo } from '/@/hooks/component/order'; | ||
5 | +import { useOrderStoreWithOut } from '/@/store/modules/order'; | ||
6 | +import { formatToDate } from '/@/utils/dateUtil'; | ||
7 | + | ||
8 | +// 角色 | ||
9 | +// 业务员- 查看all,编辑-利润分析,报告书 | ||
10 | +// 跟单员- 查看利润分析(单价和总金额),跟单,质检,编辑 | ||
11 | +// 质检员- 查看跟单,质检,编辑质检 | ||
12 | + | ||
13 | +const innerNoOptions = ref([]); | ||
14 | +const projectNoOptions = ref([]); | ||
15 | +const orderStore = useOrderStoreWithOut(); | ||
16 | +// const { productionDepartment: productionDepartmentOptions } = useOrderInfo(orderStore); | ||
17 | + | ||
18 | +/** | ||
19 | + * drawer面板的字段 | ||
20 | + */ | ||
21 | +// 基本信息 | ||
22 | +export const FIELDS_BASE_INFO = [ | ||
23 | + { | ||
24 | + field: 'customerCode', | ||
25 | + component: 'Select', | ||
26 | + labelWidth: 150, | ||
27 | + label: '客户编码', | ||
28 | + rules: [{ required: true }], | ||
29 | + }, | ||
30 | + { | ||
31 | + field: 'projectNo', | ||
32 | + component: 'Input', | ||
33 | + labelWidth: 150, | ||
34 | + label: '项目号', | ||
35 | + rules: [{ required: true }], | ||
36 | + }, | ||
37 | + { | ||
38 | + field: 'productionDepartment', | ||
39 | + component: 'Select', | ||
40 | + // componentProps: { | ||
41 | + // options: productionDepartmentOptions, | ||
42 | + // }, | ||
43 | + labelWidth: 150, | ||
44 | + label: '生产科', | ||
45 | + rules: [{ required: true }], | ||
46 | + }, | ||
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 | +]; | ||
94 | + |
src/views/project/finance/financeProfit/ServiceProfit/ServiceProfit/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.TRACKER"> | ||
17 | + <h3>基本信息</h3> | ||
18 | + <BasicForm @register="registerForm" /> | ||
19 | + </template> | ||
20 | + </div> | ||
21 | + <!-- <template #titleToolbar> <a-button type="primary"> 申请编辑权限 </a-button></template> --> | ||
22 | + | ||
23 | + <!-- <template #appendFooter> | ||
24 | + <a-button type="primary" @click="onGoFormDetail"> 返回编辑</a-button> | ||
25 | + </template> --> | ||
26 | + </BasicDrawer> | ||
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 { orderAuth } from '/@/api/project/order'; | ||
33 | + import { ROLE } from '../../../financeList/type.d'; | ||
34 | + import { useModal } from '/@/components/Modal'; | ||
35 | + | ||
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 | ||
43 | + .map((item) => ({ | ||
44 | + field: `${item.field}`, | ||
45 | + dataIndex: `${item.field}`, | ||
46 | + label: item.label, | ||
47 | + component: 'Switch', | ||
48 | + componentProps: { | ||
49 | + checkedValue: 'UN_LOCKED', | ||
50 | + unCheckedValue: 'LOCKED', | ||
51 | + }, | ||
52 | + colProps: { | ||
53 | + span: 6, | ||
54 | + }, | ||
55 | + })) | ||
56 | + .filter( | ||
57 | + (item) => | ||
58 | + // item.field !== 'packetPrice' && | ||
59 | + item.field !== 'exchangeRate' && item.field !== 'profitRate', | ||
60 | + ); | ||
61 | + | ||
62 | + export default defineComponent({ | ||
63 | + components: { BasicDrawer, BasicForm }, | ||
64 | + props: { | ||
65 | + onGoFormDetail: { | ||
66 | + type: Function, | ||
67 | + }, | ||
68 | + }, | ||
69 | + setup() { | ||
70 | + const id = ref(''); | ||
71 | + const schemas = getSchema(FIELDS_BASE_INFO); | ||
72 | + const [registerForm, { getFieldsValue }] = useForm({ | ||
73 | + labelWidth: 120, | ||
74 | + schemas, | ||
75 | + showActionButtonGroup: false, | ||
76 | + actionColOptions: { | ||
77 | + span: 24, | ||
78 | + }, | ||
79 | + }); | ||
80 | + const lockFields = reactive({}); | ||
81 | + const [register, { closeDrawer }] = useDrawerInner((data) => { | ||
82 | + Object.assign(lockFields, data.lockFields); | ||
83 | + id.value = data.id; | ||
84 | + }); | ||
85 | + function handleCloseModal() { | ||
86 | + closeDrawer(); | ||
87 | + } | ||
88 | + | ||
89 | + const role = computed(() => { | ||
90 | + return userStore.getUserInfo?.roleSmallVO?.code; | ||
91 | + }); | ||
92 | + | ||
93 | + const handleSubmit = async () => { | ||
94 | + const baseFieldValues = getFieldsValue(); | ||
95 | + | ||
96 | + if (baseFieldValues) { | ||
97 | + FIELDS_BASE_INFO.map( | ||
98 | + ({ field }) => | ||
99 | + (baseFieldValues[field] = | ||
100 | + baseFieldValues[field] === 'UN_LOCKED' ? 'UN_LOCKED' : 'LOCKED'), | ||
101 | + ); | ||
102 | + } | ||
103 | + const values = Object.assign({ orderId: id.value }, { baseFields: baseFieldValues }); | ||
104 | + | ||
105 | + if ( | ||
106 | + values.baseFields && | ||
107 | + (values.baseFields.projectNo === 'UN_LOCKED' || | ||
108 | + values.baseFields.productionDepartment === 'UN_LOCKED' || | ||
109 | + values.baseFields.innerNo === 'UN_LOCKED' || | ||
110 | + values.baseFields.customerCode === 'UN_LOCKED' || | ||
111 | + values.baseFields.customerPo === 'UN_LOCKED' || | ||
112 | + values.baseFields.customerStyle === 'UN_LOCKED') | ||
113 | + ) { | ||
114 | + openReasonModal(true, { | ||
115 | + data: values, | ||
116 | + }); | ||
117 | + } else { | ||
118 | + await orderAuth(values); | ||
119 | + closeDrawer(); | ||
120 | + } | ||
121 | + }; | ||
122 | + | ||
123 | + return { | ||
124 | + register, | ||
125 | + schemas, | ||
126 | + registerForm, | ||
127 | + handleSubmit, | ||
128 | + handleCloseModal, | ||
129 | + ROLE, | ||
130 | + role, | ||
131 | + }; | ||
132 | + }, | ||
133 | + }); | ||
134 | +</script> | ||
135 | +<style> | ||
136 | + .container { | ||
137 | + position: fixed; /* 或 absolute, fixed */ | ||
138 | + z-index: 10; | ||
139 | + } | ||
140 | +</style> |
src/views/project/finance/financeProfit/ServiceProfit/ServiceProfit/FinanceEdit.vue
0 → 100644
1 | +<template> | ||
2 | + <template> | ||
3 | + <BasicDrawer | ||
4 | + @register="register" | ||
5 | + v-bind="$attrs" | ||
6 | + title="编辑" | ||
7 | + width="30%" | ||
8 | + :isDetail="true" | ||
9 | + @ok="handleSubmit" | ||
10 | + :showDetailBack="false" | ||
11 | + okText="保存" | ||
12 | + showFooter | ||
13 | + :destroyOnClose="true" | ||
14 | + > | ||
15 | + <!-- <div> | ||
16 | + <BasicForm @register="registerForm" /> | ||
17 | + </div> --> | ||
18 | + <div style="font-size: 15px">研发复制费合计¥</div> | ||
19 | + <a-input | ||
20 | + v-model:value="input1" | ||
21 | + placeholder="请输入" | ||
22 | + :disabled="status1 === 'LOCKED'" | ||
23 | + auto-size | ||
24 | + /> | ||
25 | + <div style="margin: 16px 0"></div> | ||
26 | + <div style="font-size: 15px">项目开始时间</div> | ||
27 | + <a-date-picker v-model:value="input3" :disabled="status3 === 'LOCKED'" auto-size /> | ||
28 | + <div style="margin: 16px 0"></div> | ||
29 | + <div style="font-size: 15px">项目结束时间</div> | ||
30 | + <a-date-picker v-model:value="input4" :disabled="status4 === 'LOCKED'" auto-size /> | ||
31 | + <div style="margin: 16px 0"></div> | ||
32 | + <div style="font-size: 15px">西班牙已发提成¥</div> | ||
33 | + <a-input | ||
34 | + v-model:value="input2" | ||
35 | + placeholder="请输入" | ||
36 | + :disabled="status2 === 'LOCKED'" | ||
37 | + auto-size | ||
38 | + /> | ||
39 | + <div style="margin: 16px 0"></div> | ||
40 | + <div style="font-size: 15px">中国团队已发提成¥</div> | ||
41 | + <a-input | ||
42 | + v-model:value="input5" | ||
43 | + placeholder="请输入" | ||
44 | + :disabled="status5 === 'LOCKED'" | ||
45 | + auto-size | ||
46 | + /> | ||
47 | + <div style="margin: 16px 0"></div> | ||
48 | + <div style="font-size: 15px">实际汇率¥</div> | ||
49 | + <a-input | ||
50 | + v-model:value="input6" | ||
51 | + placeholder="请输入" | ||
52 | + :disabled="status6 === 'LOCKED'" | ||
53 | + auto-size | ||
54 | + /> | ||
55 | + <div style="margin: 16px 0"></div> | ||
56 | + <!-- <template #titleToolbar> <a-button type="primary"> 申请编辑权限 </a-button></template> --> | ||
57 | + <template #appendFooter> | ||
58 | + <!-- <a-button type="primary" @click="onGoCheckDetail"> 申请权限</a-button> --> | ||
59 | + </template> | ||
60 | + </BasicDrawer> | ||
61 | + </template> | ||
62 | +</template> | ||
63 | +<script lang="ts" setup> | ||
64 | + import { BasicDrawer, useDrawerInner } from '@/components/Drawer'; | ||
65 | + import { BasicForm, FormSchema, useForm } from '@/components/Form'; | ||
66 | + import { defineComponent, ref, computed, unref, toRaw, reactive } from 'vue'; | ||
67 | + import { getServiceEdit } from '@/api/project/invoice'; | ||
68 | + import { useMessage } from '/@/hooks/web/useMessage'; | ||
69 | + import { ROLE } from './type.d'; | ||
70 | + import type { Dayjs } from 'dayjs'; | ||
71 | + import dayjs from 'dayjs'; | ||
72 | + | ||
73 | + const emit = defineEmits(['success']); | ||
74 | + const role = computed(() => { | ||
75 | + return user?.roleSmallVO?.code; | ||
76 | + }); | ||
77 | + const schemas: FormSchema[] = [ | ||
78 | + // { | ||
79 | + // field: 'totalPayAmount', | ||
80 | + // component: 'InputNumber', | ||
81 | + // labelWidth: 250, | ||
82 | + // colProps: { | ||
83 | + // span: 23, | ||
84 | + // }, | ||
85 | + // label: '实际应收金额', | ||
86 | + // }, | ||
87 | + { | ||
88 | + field: 'developmentCopyRmbTotalPrice', | ||
89 | + component: 'InputNumber', | ||
90 | + labelWidth: 250, | ||
91 | + colProps: { | ||
92 | + span: 23, | ||
93 | + }, | ||
94 | + // componentProps: () => ({ | ||
95 | + // disabled: status.value === 10, | ||
96 | + // }), | ||
97 | + label: '研发复制费合计¥', | ||
98 | + }, | ||
99 | + { | ||
100 | + field: 'actualPayedAmount2', | ||
101 | + component: 'InputNumber', | ||
102 | + labelWidth: 250, | ||
103 | + colProps: { | ||
104 | + span: 23, | ||
105 | + }, | ||
106 | + | ||
107 | + label: '实际应收金额2$', | ||
108 | + }, | ||
109 | + { | ||
110 | + field: 'actualPayedAmount3', | ||
111 | + component: 'InputNumber', | ||
112 | + labelWidth: 250, | ||
113 | + colProps: { | ||
114 | + span: 23, | ||
115 | + }, | ||
116 | + | ||
117 | + label: '实际应收金额3$', | ||
118 | + }, | ||
119 | + { | ||
120 | + field: 'otherAmount', | ||
121 | + component: 'InputNumber', | ||
122 | + labelWidth: 250, | ||
123 | + colProps: { | ||
124 | + span: 23, | ||
125 | + }, | ||
126 | + | ||
127 | + label: '其他费用金额$', | ||
128 | + }, | ||
129 | + ]; | ||
130 | + const [registerForm, { setFieldsValue, resetFields, validate }] = useForm({ | ||
131 | + labelWidth: 120, | ||
132 | + schemas, | ||
133 | + layout: 'vertical', | ||
134 | + showActionButtonGroup: false, | ||
135 | + actionColOptions: { | ||
136 | + span: 24, | ||
137 | + }, | ||
138 | + }); | ||
139 | + const { createMessage } = useMessage(); | ||
140 | + const { error } = createMessage; | ||
141 | + | ||
142 | + const update = ref(); | ||
143 | + const status1 = ref(); | ||
144 | + const status2 = ref(); | ||
145 | + const status3 = ref(); | ||
146 | + const status4 = ref(); | ||
147 | + const status5 = ref(); | ||
148 | + const status6 = ref(); | ||
149 | + | ||
150 | + const input1 = ref(); | ||
151 | + const input2 = ref(); | ||
152 | + const input3 = ref(); | ||
153 | + // const input4 = ref(); | ||
154 | + const input4 = ref(dayjs('2013-12-01')); | ||
155 | + | ||
156 | + const input5 = ref(); | ||
157 | + const input6 = ref(); | ||
158 | + const id = ref(); | ||
159 | + // function formatDate(dateStr: string): string { | ||
160 | + // const date = new Date(dateStr); | ||
161 | + // const year = date.getFullYear(); | ||
162 | + // const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份从0开始,+1 | ||
163 | + // const day = String(date.getDate()).padStart(2, '0'); | ||
164 | + // const hours = String(date.getHours()).padStart(2, '0'); | ||
165 | + // const minutes = String(date.getMinutes()).padStart(2, '0'); | ||
166 | + // const seconds = String(date.getSeconds()).padStart(2, '0'); | ||
167 | + | ||
168 | + // // 返回格式化后的字符串:'YYYY-MM-DD HH:mm:ss' | ||
169 | + // return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; | ||
170 | + // } | ||
171 | + function formatDateToDateOnly(dateStr: string): string { | ||
172 | + const date = new Date(dateStr); | ||
173 | + const year = date.getFullYear(); | ||
174 | + const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份从0开始,+1 | ||
175 | + const day = String(date.getDate()).padStart(2, '0'); | ||
176 | + | ||
177 | + // 返回格式化后的日期字符串:'YYYY-MM-DD' | ||
178 | + return `${year}-${month}-${day}`; | ||
179 | + } | ||
180 | + const [register, { setDrawerProps, closeDrawer }] = useDrawerInner((data) => { | ||
181 | + // 方式1 | ||
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?.projectStartTime; | ||
186 | + status4.value = data?.data?.lockFields?.projectEndTime; | ||
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 = dayjs(formatDateToDateOnly(data?.data?.projectStartTime)); | ||
194 | + input4.value = dayjs(formatDateToDateOnly(data?.data?.projectEndTime)); | ||
195 | + input5.value = data?.data?.paidRmbCommission.toFixed(2); | ||
196 | + input6.value = data?.data?.actualExchangeRate.toFixed(2); | ||
197 | + // console.log(input3.value, '5656gbg', input4.value); | ||
198 | + resetFields(); | ||
199 | + setDrawerProps({ confirmLoading: false }); | ||
200 | + setFieldsValue({ | ||
201 | + ...toRaw(data.data), | ||
202 | + }); | ||
203 | + update.value = data; | ||
204 | + }); | ||
205 | + //完成编辑 | ||
206 | + async function handleSubmit() { | ||
207 | + // const values = await validate(); | ||
208 | + // const updatedValues = { | ||
209 | + // ...values, | ||
210 | + // id: update.value.data.id, | ||
211 | + // bgUrl: update.value.data.bgUrl, | ||
212 | + // }; | ||
213 | + if (!input1.value || !input2.value || !input3.value || !input4.value) { | ||
214 | + error('选项不能为空'); | ||
215 | + } else { | ||
216 | + await getServiceEdit({ | ||
217 | + projectNoPrefix: id.value, | ||
218 | + developmentCopyRmbTotalPrice: input1.value, | ||
219 | + spainPaidRmbCommission: input2.value, | ||
220 | + projectStartTime: input3.value, | ||
221 | + projectEndTime: input4.value, | ||
222 | + paidRmbCommission: input5.value, | ||
223 | + actualExchangeRate: input6.value, | ||
224 | + }); | ||
225 | + emit('success'); | ||
226 | + closeDrawer(); | ||
227 | + } | ||
228 | + } | ||
229 | +</script> |
src/views/project/finance/financeProfit/ServiceProfit/ServiceProfit/data.tsx
0 → 100644
1 | +import { InputNumber, Tag } from 'ant-design-vue'; | ||
2 | +import { BasicColumn } from '@/components/Table'; | ||
3 | +import { func } from 'vue-types'; | ||
4 | +import { h, ref } from 'vue'; | ||
5 | +import { FilePptOutlined } from '@ant-design/icons-vue'; | ||
6 | +import axios from 'axios'; | ||
7 | + | ||
8 | +// export const COLUMNS = [ | ||
9 | +// { | ||
10 | +// title: '客户编码', | ||
11 | +// dataIndex: 'settingValue', | ||
12 | +// width: 150, | ||
13 | +// }, | ||
14 | +// { | ||
15 | +// title: '利润率', | ||
16 | +// dataIndex: 'relationValue', | ||
17 | +// width: 150, | ||
18 | +// editComponent: 'InputNumber', | ||
19 | +// editRow: true, | ||
20 | +// scopedSlots: { customRender: 'name' } | ||
21 | +// }, | ||
22 | +// ]; | ||
23 | +export const COLUMNS = [ | ||
24 | + { | ||
25 | + title: '客户编码', | ||
26 | + dataIndex: 'customerCode', | ||
27 | + width: 150, | ||
28 | + }, | ||
29 | + { | ||
30 | + title: '项目号', | ||
31 | + dataIndex: 'projectNoPrefix', | ||
32 | + width: 100, | ||
33 | + }, | ||
34 | + { | ||
35 | + title: '客户总价¥', | ||
36 | + width: 150, | ||
37 | + dataIndex: 'customerTotalPrice', | ||
38 | + customRender: (column) => { | ||
39 | + return column.record?.customerRmbTotalPrice?.toFixed(2); | ||
40 | + }, | ||
41 | + }, | ||
42 | + { | ||
43 | + title: '客户总价$', | ||
44 | + width: 150, | ||
45 | + dataIndex: 'customerTotalPrice', | ||
46 | + customRender: (column) => { | ||
47 | + return column.record?.customerTotalPrice?.toFixed(2); | ||
48 | + }, | ||
49 | + }, | ||
50 | + { | ||
51 | + title: '生产科总价¥', | ||
52 | + dataIndex: 'productionDepartmentTotalPrice', | ||
53 | + width: 120, | ||
54 | + customRender: (column) => { | ||
55 | + return column.record?.productionDepartmentTotalPrice?.toFixed(2); | ||
56 | + }, | ||
57 | + }, | ||
58 | + { | ||
59 | + title: '包装费用合计¥', | ||
60 | + dataIndex: 'packetTotalPrice', | ||
61 | + width: 120, | ||
62 | + customRender: (column) => { | ||
63 | + return column.record?.packetTotalPrice?.toFixed(2); | ||
64 | + }, | ||
65 | + }, | ||
66 | + { | ||
67 | + title: '包装费用合计$', | ||
68 | + dataIndex: 'packetTotalPrice', | ||
69 | + width: 120, | ||
70 | + customRender: (column) => { | ||
71 | + return column.record?.packetTotalPrice?.toFixed(2); | ||
72 | + }, | ||
73 | + }, | ||
74 | + { | ||
75 | + title: '研发复制费合计¥', | ||
76 | + dataIndex: 'developmentCopyRmbTotalPrice', | ||
77 | + width: 120, | ||
78 | + customRender: (column) => { | ||
79 | + return column.record?.developmentCopyRmbTotalPrice?.toFixed(2); | ||
80 | + }, | ||
81 | + }, | ||
82 | + { | ||
83 | + title: '固定成本¥', | ||
84 | + dataIndex: 'fixedCost', | ||
85 | + width: 120, | ||
86 | + customRender: (column) => { | ||
87 | + return column.record?.fixedCost?.toFixed(2); | ||
88 | + }, | ||
89 | + }, | ||
90 | + { | ||
91 | + title: '西班牙提成¥', | ||
92 | + dataIndex: 'spainRmbCommission', | ||
93 | + width: 120, | ||
94 | + customRender: (column) => { | ||
95 | + return column.record?.spainRmbCommission?.toFixed(2); | ||
96 | + }, | ||
97 | + }, | ||
98 | + { | ||
99 | + title: '已发提成¥', | ||
100 | + dataIndex: 'spainPaidRmbCommission', | ||
101 | + width: 120, | ||
102 | + customRender: (column) => { | ||
103 | + return column.record?.spainPaidRmbCommission?.toFixed(2); | ||
104 | + }, | ||
105 | + }, | ||
106 | + { | ||
107 | + title: '未发提成¥', | ||
108 | + dataIndex: 'spainUnpaidRmbCommission', | ||
109 | + width: 120, | ||
110 | + customRender: (column) => { | ||
111 | + return column.record?.spainUnpaidRmbCommission?.toFixed(2); | ||
112 | + }, | ||
113 | + }, | ||
114 | + { | ||
115 | + title: '中国团队提成¥', | ||
116 | + dataIndex: 'rmbCommission', | ||
117 | + width: 120, | ||
118 | + customRender: (column) => { | ||
119 | + return column.record?.rmbCommission?.toFixed(2); | ||
120 | + }, | ||
121 | + }, | ||
122 | + { | ||
123 | + title: '已发提成¥', | ||
124 | + dataIndex: 'paidRmbCommission', | ||
125 | + width: 120, | ||
126 | + customRender: (column) => { | ||
127 | + return column.record?.paidRmbCommission?.toFixed(2); | ||
128 | + }, | ||
129 | + }, | ||
130 | + { | ||
131 | + title: '未发提成¥', | ||
132 | + dataIndex: 'unpaidRmbCommission', | ||
133 | + width: 120, | ||
134 | + customRender: (column) => { | ||
135 | + return column.record?.unpaidRmbCommission?.toFixed(2); | ||
136 | + }, | ||
137 | + }, | ||
138 | + { | ||
139 | + title: '支出合计¥', | ||
140 | + dataIndex: 'rmbTotalExpense', | ||
141 | + width: 120, | ||
142 | + customRender: (column) => { | ||
143 | + return column.record?.rmbTotalExpense?.toFixed(2); | ||
144 | + }, | ||
145 | + }, | ||
146 | + { | ||
147 | + title: '毛利润¥', | ||
148 | + dataIndex: 'profit', | ||
149 | + width: 120, | ||
150 | + customRender: (column) => { | ||
151 | + return column.record?.profit?.toFixed(2); | ||
152 | + }, | ||
153 | + }, | ||
154 | + { | ||
155 | + title: '毛利率', | ||
156 | + dataIndex: 'profitRate', | ||
157 | + width: 120, | ||
158 | + customRender: (column) => { | ||
159 | + return column.record?.profitRate?.toFixed(2); | ||
160 | + }, | ||
161 | + }, | ||
162 | + { | ||
163 | + title: '研发贸易净利润¥', | ||
164 | + dataIndex: 'developmentProfit', | ||
165 | + width: 120, | ||
166 | + customRender: (column) => { | ||
167 | + return column.record?.developmentProfit?.toFixed(2); | ||
168 | + }, | ||
169 | + }, | ||
170 | + { | ||
171 | + title: '净利润率', | ||
172 | + dataIndex: 'developmentProfitRate', | ||
173 | + width: 120, | ||
174 | + customRender: (column) => { | ||
175 | + return column.record?.developmentProfitRate?.toFixed(2); | ||
176 | + }, | ||
177 | + }, | ||
178 | + { | ||
179 | + title: '包装费用合计¥', | ||
180 | + dataIndex: 'packetRmbTotalPrice', | ||
181 | + width: 120, | ||
182 | + customRender: (column) => { | ||
183 | + return column.record?.packetRmbTotalPrice?.toFixed(2); | ||
184 | + }, | ||
185 | + }, | ||
186 | + { | ||
187 | + title: '包装费用实际金额¥', | ||
188 | + dataIndex: 'packetActualRmbTotalPrice', | ||
189 | + width: 120, | ||
190 | + customRender: (column) => { | ||
191 | + return column.record?.packetActualRmbTotalPrice?.toFixed(2); | ||
192 | + }, | ||
193 | + }, | ||
194 | + { | ||
195 | + title: '订单总数量', | ||
196 | + dataIndex: 'orderCount', | ||
197 | + width: 120, | ||
198 | + customRender: (column) => { | ||
199 | + return column.record?.orderCount; | ||
200 | + }, | ||
201 | + }, | ||
202 | + { | ||
203 | + title: '实际跟单单价¥', | ||
204 | + dataIndex: 'actualOrderRmbPrice', | ||
205 | + width: 120, | ||
206 | + customRender: (column) => { | ||
207 | + return column.record?.actualOrderRmbPrice?.toFixed(2); | ||
208 | + }, | ||
209 | + }, | ||
210 | + { | ||
211 | + title: '实际跟单单价折算美金¥', | ||
212 | + dataIndex: 'actualOrderPrice', | ||
213 | + width: 120, | ||
214 | + customRender: (column) => { | ||
215 | + return column.record?.actualOrderPrice?.toFixed(2); | ||
216 | + }, | ||
217 | + }, | ||
218 | + { | ||
219 | + title: '包装费用收益¥', | ||
220 | + dataIndex: 'packetProfitRmbPrice', | ||
221 | + width: 120, | ||
222 | + customRender: (column) => { | ||
223 | + return column.record?.packetProfitRmbPrice?.toFixed(2); | ||
224 | + }, | ||
225 | + }, | ||
226 | + { | ||
227 | + title: '实际汇率¥', | ||
228 | + dataIndex: 'actualExchangeRate', | ||
229 | + width: 120, | ||
230 | + customRender: (column) => { | ||
231 | + return column.record?.actualExchangeRate?.toFixed(2); | ||
232 | + }, | ||
233 | + }, | ||
234 | + { | ||
235 | + title: '汇率收益¥', | ||
236 | + dataIndex: 'exchangeRateProfit', | ||
237 | + width: 120, | ||
238 | + customRender: (column) => { | ||
239 | + return column.record?.exchangeRateProfit?.toFixed(2); | ||
240 | + }, | ||
241 | + }, | ||
242 | + { | ||
243 | + title: '综合收益¥', | ||
244 | + dataIndex: 'comprehensiveProfit', | ||
245 | + width: 120, | ||
246 | + customRender: (column) => { | ||
247 | + return column.record?.comprehensiveProfit?.toFixed(2); | ||
248 | + }, | ||
249 | + }, | ||
250 | + { | ||
251 | + title: '文件', | ||
252 | + dataIndex: 'fileUrl', | ||
253 | + width: 120, | ||
254 | + customRender: (column) => { | ||
255 | + // 构造符合 API 要求的参数 | ||
256 | + // await exportAnalysis({ ids: ids }); | ||
257 | + const handleClick = () => { | ||
258 | + axios | ||
259 | + .post( | ||
260 | + '/basic-api/project/businessProfit/export', | ||
261 | + { | ||
262 | + projectNoPrefix: column.record.projectNoPrefix, | ||
263 | + }, | ||
264 | + { | ||
265 | + responseType: 'blob', // 设置响应类型为 'blob' | ||
266 | + }, | ||
267 | + ) | ||
268 | + .then((response) => { | ||
269 | + // 创建一个 Blob 对象来保存二进制数据 | ||
270 | + const blob = new Blob([response.data], { type: 'application/zip' }); | ||
271 | + const getFormattedDate = (): string => { | ||
272 | + const date = new Date(); | ||
273 | + | ||
274 | + const year = date.getFullYear(); | ||
275 | + const month = String(date.getMonth() + 1).padStart(2, '0'); | ||
276 | + const day = String(date.getDate()).padStart(2, '0'); | ||
277 | + | ||
278 | + const hours = String(date.getHours()).padStart(2, '0'); | ||
279 | + const minutes = String(date.getMinutes()).padStart(2, '0'); | ||
280 | + const seconds = String(date.getSeconds()).padStart(2, '0'); | ||
281 | + | ||
282 | + return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; | ||
283 | + }; | ||
284 | + const date = getFormattedDate(); | ||
285 | + // 创建一个链接元素用于下载 | ||
286 | + const link = document.createElement('a'); | ||
287 | + link.href = window.URL.createObjectURL(blob); | ||
288 | + link.download = `${date}.xlsx`; // 你可以为文件命名 | ||
289 | + document.body.appendChild(link); | ||
290 | + link.click(); // 自动点击链接,触发下载 | ||
291 | + document.body.removeChild(link); // 下载完成后移除链接 | ||
292 | + }) | ||
293 | + .catch((error) => { | ||
294 | + console.error(error); | ||
295 | + }); | ||
296 | + }; | ||
297 | + return <FilePptOutlined style="font-size:25px" onClick={() => handleClick()} />; | ||
298 | + }, | ||
299 | + }, | ||
300 | +]; | ||
0 | \ No newline at end of file | 301 | \ No newline at end of file |
src/views/project/finance/financeProfit/ServiceProfit/ServiceProfit/index.vue
0 → 100644
1 | +<template> | ||
2 | + <div> | ||
3 | + <BasicTable @register="registerTable" :bordered="true"> | ||
4 | + <template #bodyCell="{ column, record }"> | ||
5 | + <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" | ||
13 | + /> | ||
14 | + <span v-else style="color: red"> | ||
15 | + {{ record.settingValue }} | ||
16 | + </span> | ||
17 | + </template> --> | ||
18 | + </template> | ||
19 | + </BasicTable> | ||
20 | + <!-- <BasicModal | ||
21 | + title="拒绝原因" | ||
22 | + width="30%" | ||
23 | + @register="registerModal" | ||
24 | + @visible-change="handleClose" | ||
25 | + @ok="handleOk" | ||
26 | + wrapClassName="approve-modal" | ||
27 | + > | ||
28 | + <div className="pa-8"> | ||
29 | + <a-textarea :rows="6" placeholder="请输入拒绝原因" v-model:value="message" /> | ||
30 | + </div> | ||
31 | + </BasicModal> --> | ||
32 | + <CheckDetail @register="checkModalRegister" :onGoFormDetail="handleGoFormDetail" /> | ||
33 | + <FinanceEdit @register="registerFinanceEdit" @success="handleSuccess" /> | ||
34 | + </div> | ||
35 | +</template> | ||
36 | +<script setup lang="ts"> | ||
37 | + import { BasicTable, useTable, TableAction } from '/@/components/Table'; | ||
38 | + import { getServiceProfit } from '@/api/project/invoice'; | ||
39 | + import { COLUMNS } from './data'; | ||
40 | + import { BasicModal, useModal } from '/@/components/Modal'; | ||
41 | + import { useMessage } from '/@/hooks/web/useMessage'; | ||
42 | + import { ref } from 'vue'; | ||
43 | + import { useDrawer } from '/@/components/Drawer'; | ||
44 | + import FinanceEdit from './FinanceEdit.vue'; | ||
45 | + import CheckDetail from './CheckDetail.vue'; | ||
46 | + | ||
47 | + const { createMessage } = useMessage(); | ||
48 | + const { error } = createMessage; | ||
49 | + const message = ref(); | ||
50 | + const [checkModalRegister, { openDrawer: openCheckDetailDrawer }] = useDrawer(); | ||
51 | + const [registerFinanceEdit, { openDrawer: openFinanceEdit }] = useDrawer(); | ||
52 | + // const handleOk = (record) => { | ||
53 | + // // 修改父组件的状态 | ||
54 | + // console.log(message.value, '5656messsage', record); | ||
55 | + // closeModal(); | ||
56 | + // }; | ||
57 | + const handleClose = (visible: boolean) => { | ||
58 | + if (!visible) { | ||
59 | + message.value = ''; | ||
60 | + } | ||
61 | + }; | ||
62 | + const [registerTable, { reload }] = useTable({ | ||
63 | + api: getServiceProfit, | ||
64 | + bordered: true, | ||
65 | + columns: COLUMNS, | ||
66 | + rowKey: 'id', | ||
67 | + useSearchForm: true, | ||
68 | + actionColumn: { | ||
69 | + width: 240, | ||
70 | + title: 'Action', | ||
71 | + dataIndex: 'action', | ||
72 | + }, | ||
73 | + }); | ||
74 | + | ||
75 | + function createActions(record: any): any[] { | ||
76 | + if (!record.editable) { | ||
77 | + return [ | ||
78 | + { | ||
79 | + label: '财务编辑', | ||
80 | + onClick: handleFinanceEdit.bind(null, record), | ||
81 | + }, | ||
82 | + // { | ||
83 | + // label: '编辑', | ||
84 | + // onClick: handleEdit.bind(null, record), | ||
85 | + // }, | ||
86 | + // { | ||
87 | + // label: '删除', | ||
88 | + // popConfirm: { | ||
89 | + // title: '确认删除?', | ||
90 | + // confirm: handleDelete.bind(null, record), | ||
91 | + // }, | ||
92 | + // }, | ||
93 | + { | ||
94 | + label: '申请权限', | ||
95 | + // popConfirm: { | ||
96 | + // title: '确认申请?', | ||
97 | + // confirm: handleFalse.bind(null, record), | ||
98 | + // }, | ||
99 | + onClick: handleFalse.bind(null, record), | ||
100 | + }, | ||
101 | + ]; | ||
102 | + } | ||
103 | + return [ | ||
104 | + { | ||
105 | + label: '保存', | ||
106 | + onClick: handleSave.bind(null, record), | ||
107 | + }, | ||
108 | + { | ||
109 | + label: '取消', | ||
110 | + popConfirm: { | ||
111 | + title: '是否取消编辑', | ||
112 | + confirm: handleCancel.bind(null, record), | ||
113 | + }, | ||
114 | + }, | ||
115 | + ]; | ||
116 | + } | ||
117 | + | ||
118 | + function handleFinanceEdit(record) { | ||
119 | + console.log(record, '5656reer'); | ||
120 | + openFinanceEdit(true, { | ||
121 | + data: record, | ||
122 | + }); | ||
123 | + } | ||
124 | + | ||
125 | + function handleFalse(record, e) { | ||
126 | + openCheckDetailDrawer(true, record); | ||
127 | + e?.stopPropagation(); | ||
128 | + return false; | ||
129 | + } | ||
130 | + | ||
131 | + // async function handleFalse(record: any) { | ||
132 | + // console.log(record); | ||
133 | + // // openModal(true, { record }); | ||
134 | + // } | ||
135 | + | ||
136 | + function handleSuccess() { | ||
137 | + setTimeout(() => { | ||
138 | + reload(); | ||
139 | + }, 50); | ||
140 | + } | ||
141 | + | ||
142 | + async function handleSave(record) { | ||
143 | + await saveConfig({ id: record.id, relationValue: record.relationValue }); | ||
144 | + handleCancel(record); | ||
145 | + reload(); | ||
146 | + } | ||
147 | + function handleEdit(record: any) { | ||
148 | + console.log(record, '5656edit'); | ||
149 | + // if (record.settingValue == 'A01') { | ||
150 | + // error('请勿连续点击生成按钮,需要等待三秒再点击生成'); | ||
151 | + // } else { | ||
152 | + record.onEdit?.(true); | ||
153 | + // } | ||
154 | + } | ||
155 | + | ||
156 | + function handleCancel(record) { | ||
157 | + record.onEdit?.(false, false); | ||
158 | + } | ||
159 | + | ||
160 | + async function handleDelete(record) { | ||
161 | + // await deleteConfig({ ids: [record.id] }); | ||
162 | + reload(); | ||
163 | + } | ||
164 | +</script> | ||
165 | +<style></style> |
src/views/project/finance/financeProfit/ServiceProfit/ServiceProfit/tableData.tsx
0 → 100644
1 | +import { ref } from 'vue'; | ||
2 | +import { ROLE } from '../../../financeList/type.d'; | ||
3 | +import { queryNoOptions } from '/@/api/project/order'; | ||
4 | +import { useOrderInfo } from '/@/hooks/component/order'; | ||
5 | +import { useOrderStoreWithOut } from '/@/store/modules/order'; | ||
6 | +import { formatToDate } from '/@/utils/dateUtil'; | ||
7 | + | ||
8 | +// 角色 | ||
9 | +// 业务员- 查看all,编辑-利润分析,报告书 | ||
10 | +// 跟单员- 查看利润分析(单价和总金额),跟单,质检,编辑 | ||
11 | +// 质检员- 查看跟单,质检,编辑质检 | ||
12 | + | ||
13 | +const innerNoOptions = ref([]); | ||
14 | +const projectNoOptions = ref([]); | ||
15 | +const orderStore = useOrderStoreWithOut(); | ||
16 | +// const { productionDepartment: productionDepartmentOptions } = useOrderInfo(orderStore); | ||
17 | + | ||
18 | +/** | ||
19 | + * drawer面板的字段 | ||
20 | + */ | ||
21 | +// 基本信息 | ||
22 | +export const FIELDS_BASE_INFO = [ | ||
23 | + { | ||
24 | + field: 'customerCode', | ||
25 | + component: 'Select', | ||
26 | + labelWidth: 150, | ||
27 | + label: '客户编码', | ||
28 | + rules: [{ required: true }], | ||
29 | + }, | ||
30 | + { | ||
31 | + field: 'projectNo', | ||
32 | + component: 'Input', | ||
33 | + labelWidth: 150, | ||
34 | + label: '项目号', | ||
35 | + rules: [{ required: true }], | ||
36 | + }, | ||
37 | + { | ||
38 | + field: 'productionDepartment', | ||
39 | + component: 'Select', | ||
40 | + // componentProps: { | ||
41 | + // options: productionDepartmentOptions, | ||
42 | + // }, | ||
43 | + labelWidth: 150, | ||
44 | + label: '生产科', | ||
45 | + rules: [{ required: true }], | ||
46 | + }, | ||
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 | +]; | ||
94 | + |
src/views/project/order/InvoiceCreate.vue
@@ -41,7 +41,7 @@ | @@ -41,7 +41,7 @@ | ||
41 | const { error } = createMessage; | 41 | const { error } = createMessage; |
42 | const Input1 = ref(''); | 42 | const Input1 = ref(''); |
43 | const Input2 = ref(); | 43 | const Input2 = ref(); |
44 | - const uploadUrl = ref('http://47.104.8.35:8081/api/localStorage/upload_file_oss?name='); | 44 | + const uploadUrl = ref('http://47.104.8.35:80/api/localStorage/upload_file_oss?name='); |
45 | const bgUrl = ref(); | 45 | const bgUrl = ref(); |
46 | const orderIds = ref(); | 46 | const orderIds = ref(); |
47 | 47 |
vite.config.ts
@@ -30,7 +30,18 @@ export default defineApplicationConfig({ | @@ -30,7 +30,18 @@ export default defineApplicationConfig({ | ||
30 | }, | 30 | }, |
31 | }, | 31 | }, |
32 | '/basic-api/order': { | 32 | '/basic-api/order': { |
33 | - target: 'http://47.104.8.35:8000', | 33 | + target: 'http://47.104.8.35:18000', |
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:18000', | ||
34 | // target: 'http://localhost:18000', | 45 | // target: 'http://localhost:18000', |
35 | // target: 'http://39.108.227.113:8000', | 46 | // target: 'http://39.108.227.113:8000', |
36 | // target: 'http://localhost:8000', | 47 | // target: 'http://localhost:8000', |
@@ -41,7 +52,7 @@ export default defineApplicationConfig({ | @@ -41,7 +52,7 @@ export default defineApplicationConfig({ | ||
41 | rewrite: (path) => path.replace(new RegExp(`^/basic-api`), ''), | 52 | rewrite: (path) => path.replace(new RegExp(`^/basic-api`), ''), |
42 | }, | 53 | }, |
43 | '/api/localStorage/upload': { | 54 | '/api/localStorage/upload': { |
44 | - target: 'http://47.104.8.35:8000', | 55 | + target: 'http://47.104.8.35:18000', |
45 | // target: 'http://localhost:18000', | 56 | // target: 'http://localhost:18000', |
46 | // target: 'http://39.108.227.113:8000', | 57 | // target: 'http://39.108.227.113:8000', |
47 | // target: '192.168.31.250:18000', | 58 | // target: '192.168.31.250:18000', |