Commit cfeaf8a04714a1fc5d8d07db2a3034e71e3b5b0d

Authored by boyang
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 &#39;vue&#39;; @@ -18,12 +18,36 @@ import { h } from &#39;vue&#39;;
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',