Commit 327b80fac800d683c2293565f56792542d0c9b17

Authored by boyang
1 parent 78ec6a79

业务利润分析完成,应付/应收审核完成

src/api/project/global.ts
@@ -8,13 +8,13 @@ enum Api { @@ -8,13 +8,13 @@ enum Api {
8 CUSTOMER_SALES = '/order/erp/index/salesStatusEveryCustomer', //每个客户销售额情况 8 CUSTOMER_SALES = '/order/erp/index/salesStatusEveryCustomer', //每个客户销售额情况
9 } 9 }
10 10
11 -export const getApiData = async () => {  
12 - const res = await defHttp.get<any>({ url: Api.DATA }); 11 +export const getApiData = async (params?) => {
  12 + const res = await defHttp.get<any>({ url: Api.DATA, params });
13 return res; 13 return res;
14 }; 14 };
15 15
16 -export const getChartData = async () => {  
17 - const res = await defHttp.get<any>({ url: Api.CHART_DATA }); 16 +export const getChartData = async (params?) => {
  17 + const res = await defHttp.get<any>({ url: Api.CHART_DATA, params });
18 return res; 18 return res;
19 }; 19 };
20 20
src/api/project/order.ts
@@ -34,8 +34,8 @@ enum Api { @@ -34,8 +34,8 @@ enum Api {
34 34
35 TRACK_HISTORY = '/order/erp/opinion/log/query_by_id', //跟单结果记录 35 TRACK_HISTORY = '/order/erp/opinion/log/query_by_id', //跟单结果记录
36 PASS_CALCULATE = '/order/erp/order/passRate', //一次性通过率 36 PASS_CALCULATE = '/order/erp/order/passRate', //一次性通过率
37 - CREATE_PRODUCT_TEXT = '/order/erp/order/produceReport', //生成生产指标书  
38 - EXPORT_PRODUCT_TEXT = '/order/erp/order/send', //导出生产指标书 37 + CREATE_PRODUCT_TEXT = '/order/erp/order/produceReport', //生成生产指示书
  38 + EXPORT_PRODUCT_TEXT = '/order/erp/order/send', //导出生产指示书
39 39
40 BUSINESS_PROFIT_RATIO = '/order/erp/calculate_profit/business_profit_ratio', //业务/研发净利润分析 40 BUSINESS_PROFIT_RATIO = '/order/erp/calculate_profit/business_profit_ratio', //业务/研发净利润分析
41 BUSINESS_PROFIT_RATIO_EXPORT = '/order/erp/calculate_profit/business_profit_ratio_export', //业务/研发净利润分析_导出 41 BUSINESS_PROFIT_RATIO_EXPORT = '/order/erp/calculate_profit/business_profit_ratio_export', //业务/研发净利润分析_导出
src/router/routes/modules/project/approve.ts
@@ -16,6 +16,7 @@ const order: AppRouteModule = { @@ -16,6 +16,7 @@ const order: AppRouteModule = {
16 RoleEnum.BUSINESS, 16 RoleEnum.BUSINESS,
17 RoleEnum.TRACKER, 17 RoleEnum.TRACKER,
18 RoleEnum.INSPECT, 18 RoleEnum.INSPECT,
  19 + RoleEnum.FINANCE,
19 ], 20 ],
20 orderNo: 3, 21 orderNo: 3,
21 icon: 'ion:grid-outline', 22 icon: 'ion:grid-outline',
src/store/modules/user.ts
@@ -189,10 +189,15 @@ export function useUserStoreWithOut() { @@ -189,10 +189,15 @@ export function useUserStoreWithOut() {
189 return useUserStore(store); 189 return useUserStore(store);
190 } 190 }
191 191
  192 +//分析台订单趋势
  193 +export const dateTime = ref();
  194 +//分析台时期
  195 +export const period = ref();
  196 +
192 //分析台切换页面变量 197 //分析台切换页面变量
193 export const exchangeTab = ref('tab1'); 198 export const exchangeTab = ref('tab1');
194 -//分析台时期  
195 -// export const period = ref(''); 199 +
  200 +//销售额完成率
196 //分析台业务员 201 //分析台业务员
197 export const businessPersonIn = ref(); 202 export const businessPersonIn = ref();
198 //分析台客户编码 203 //分析台客户编码
src/views/dashboard/analysis/components/GrowCard.vue
@@ -47,21 +47,40 @@ @@ -47,21 +47,40 @@
47 import { growCardList } from '../data'; 47 import { growCardList } from '../data';
48 import { useDataStoreWithOut } from '/@/store/modules/data'; 48 import { useDataStoreWithOut } from '/@/store/modules/data';
49 import { computed, onMounted, ref, watch, watchEffect } from 'vue'; 49 import { computed, onMounted, ref, watch, watchEffect } from 'vue';
50 - import { exchangeTab, businessPersonIn, customerCodeIn } from '/@/store/modules/user'; 50 + import {
  51 + exchangeTab,
  52 + businessPersonIn,
  53 + customerCodeIn,
  54 + dateTime,
  55 + period,
  56 + } from '/@/store/modules/user';
51 import { number } from 'vue-types'; 57 import { number } from 'vue-types';
52 - import { getSalesData, getCustomerSalesData } from '/@/api/project/global'; 58 + import { getSalesData, getApiData } from '/@/api/project/global';
53 import { useOrderStoreWithOut } from '/@/store/modules/order'; 59 import { useOrderStoreWithOut } from '/@/store/modules/order';
54 60
55 const dataStore = useDataStoreWithOut(); 61 const dataStore = useDataStoreWithOut();
  62 + const data1 = ref();
  63 + watch(
  64 + [dateTime, period],
  65 + async ([newDateTime, newPeriod], [oldBusinessPersonIn, oldCustomerCodeIn]) => {
  66 + console.log('businessPersonIn changed from', oldBusinessPersonIn, 'to', newDateTime);
  67 + console.log('customerCodeIn changed from', oldCustomerCodeIn, 'to', newPeriod);
56 68
  69 + // 在这里添加你希望在这两个值改变时执行的逻辑
  70 + data1.value = await getApiData({
  71 + dateTime: newDateTime,
  72 + period: newPeriod,
  73 + });
  74 + },
  75 + );
57 const growCardList = computed(() => { 76 const growCardList = computed(() => {
58 const data = dataStore.getData; 77 const data = dataStore.getData;
59 - 78 + console.log(data1.value, '5656data1.value');
60 return [ 79 return [
61 { 80 {
62 title: '订单完成', 81 title: '订单完成',
63 icon: 'visit-count|svg', 82 icon: 'visit-count|svg',
64 - value: data?.orderFinishedCount || 0, 83 + value: data1.value?.allCount || 0,
65 total: 120000, 84 total: 120000,
66 color: 'green', 85 color: 'green',
67 action: '月', 86 action: '月',
@@ -69,7 +88,7 @@ @@ -69,7 +88,7 @@
69 { 88 {
70 title: '跟单和质检中', 89 title: '跟单和质检中',
71 icon: 'total-sales|svg', 90 icon: 'total-sales|svg',
72 - value: data?.orderInspectingCount || 0, 91 + value: data1.value?.trackingAndInspectingList || 0,
73 total: 500000, 92 total: 500000,
74 color: 'blue', 93 color: 'blue',
75 action: '月', 94 action: '月',
@@ -77,7 +96,7 @@ @@ -77,7 +96,7 @@
77 { 96 {
78 title: '利润分析表待审核', 97 title: '利润分析表待审核',
79 icon: 'download-count|svg', 98 icon: 'download-count|svg',
80 - value: data?.orderProfitWaitAuditCount || 0, 99 + value: data1.value?.profitList || 0,
81 total: 120000, 100 total: 120000,
82 color: 'orange', 101 color: 'orange',
83 action: '周', 102 action: '周',
@@ -85,7 +104,7 @@ @@ -85,7 +104,7 @@
85 { 104 {
86 title: '项目报告书待审核', 105 title: '项目报告书待审核',
87 icon: 'transaction|svg', 106 icon: 'transaction|svg',
88 - value: data?.orderReportWaitAuditCount || 0, 107 + value: data1.value?.reportList || 0,
89 total: 50000, 108 total: 50000,
90 color: 'purple', 109 color: 'purple',
91 action: '年', 110 action: '年',
@@ -93,7 +112,7 @@ @@ -93,7 +112,7 @@
93 { 112 {
94 title: '订单初始化', 113 title: '订单初始化',
95 icon: 'transaction|svg', 114 icon: 'transaction|svg',
96 - value: data?.orderCount || 0, 115 + value: data1.value?.orderInitList || 0,
97 total: 50000, 116 total: 50000,
98 color: 'purple', 117 color: 'purple',
99 action: '年', 118 action: '年',
@@ -108,6 +127,11 @@ @@ -108,6 +127,11 @@
108 // }); 127 // });
109 // }); 128 // });
110 onMounted(async () => { 129 onMounted(async () => {
  130 + data1.value = await getApiData({
  131 + dateTime: dateTime.value,
  132 + period: period.value,
  133 + });
  134 + console.log(data1.value, '56565656');
111 data2.value = await getSalesData({ 135 data2.value = await getSalesData({
112 businessPersonIn: businessPersonIn.value, 136 businessPersonIn: businessPersonIn.value,
113 customerCodeIn: customerCodeIn.value, 137 customerCodeIn: customerCodeIn.value,
@@ -115,14 +139,14 @@ @@ -115,14 +139,14 @@
115 }); 139 });
116 watch( 140 watch(
117 [businessPersonIn, customerCodeIn], 141 [businessPersonIn, customerCodeIn],
118 - async ([newBusinessPersonIn, newCustomerCodeIn], [oldBusinessPersonIn, oldCustomerCodeIn]) => {  
119 - console.log('businessPersonIn changed from', oldBusinessPersonIn, 'to', newBusinessPersonIn);  
120 - console.log('customerCodeIn changed from', oldCustomerCodeIn, 'to', newCustomerCodeIn); 142 + async ([newDateTime, newPeriod], [oldBusinessPersonIn, oldCustomerCodeIn]) => {
  143 + console.log('businessPersonIn changed from', oldBusinessPersonIn, 'to', newDateTime);
  144 + console.log('customerCodeIn changed from', oldCustomerCodeIn, 'to', newPeriod);
121 145
122 // 在这里添加你希望在这两个值改变时执行的逻辑 146 // 在这里添加你希望在这两个值改变时执行的逻辑
123 data2.value = await getSalesData({ 147 data2.value = await getSalesData({
124 - businessPersonIn: newBusinessPersonIn,  
125 - customerCodeIn: newCustomerCodeIn, 148 + businessPersonIn: newDateTime,
  149 + customerCodeIn: newPeriod,
126 }); 150 });
127 }, 151 },
128 ); 152 );
src/views/dashboard/analysis/components/VisitAnalysis.vue
1 <template> 1 <template>
  2 + <span style="margin-left: 50px; font-size: 18px">选择年份:</span>
  3 + <a-select
  4 + v-model:value="yearValue"
  5 + show-search
  6 + placeholder="请选择"
  7 + style="width: 200px"
  8 + :options="yearOptions"
  9 + :filter-option="filterOption"
  10 + @change="handleChangeYear"
  11 + />
  12 + <div style="position: fixed; top: 80px; right: 70px">
  13 + <a-radio-group
  14 + v-model:value="periodCopy"
  15 + class="custom-radio-group"
  16 + :style="{ marginLeft: '100px' }"
  17 + >
  18 + <a-radio-button value="月" @click="handlePeriodChange('月')">月</a-radio-button>
  19 + <a-radio-button value="年" @click="handlePeriodChange('年')">年</a-radio-button>
  20 + </a-radio-group>
  21 + </div>
2 <div ref="chartRef" :style="{ height: '500px', width }"></div> 22 <div ref="chartRef" :style="{ height: '500px', width }"></div>
3 </template> 23 </template>
4 24
@@ -8,15 +28,71 @@ @@ -8,15 +28,71 @@
8 import { basicProps } from './props'; 28 import { basicProps } from './props';
9 import { max } from 'lodash-es'; 29 import { max } from 'lodash-es';
10 import { useDataStoreWithOut } from '/@/store/modules/data'; 30 import { useDataStoreWithOut } from '/@/store/modules/data';
  31 + import { getChartData } from '/@/api/project/global';
  32 + import { dateTime, period } from '/@/store/modules/user';
  33 + import { useMessage } from '/@/hooks/web/useMessage';
11 34
12 defineProps({ 35 defineProps({
13 ...basicProps, 36 ...basicProps,
14 }); 37 });
  38 + const yearValue = ref();
  39 + const yearOptions = [
  40 + // {
  41 + // label: '2025',
  42 + // value: 2025,
  43 + // },
  44 + {
  45 + label: '2024',
  46 + value: 2024,
  47 + },
  48 + {
  49 + label: '2023',
  50 + value: 2023,
  51 + },
  52 + ];
  53 + const periodCopy = ref();
  54 + const { createMessage } = useMessage(); //错误提示组件
  55 + const { error } = createMessage;
15 const chartRef = ref<HTMLDivElement | null>(null); 56 const chartRef = ref<HTMLDivElement | null>(null);
16 const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>); 57 const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>);
  58 + const filterOption = (input: string, option: any) => {
  59 + return option.value.toLowerCase().indexOf(input.toLowerCase()) >= 0;
  60 + };
  61 + function handlePeriodChange(value) {
  62 + //没选年份报错
  63 + if (value == '月') {
  64 + if (dateTime.value == undefined) {
  65 + error('请选择年份');
  66 + return;
  67 + }
  68 + } else if (value == '年') {
  69 + yearValue.value = null;
  70 + }
  71 + period.value = value;
  72 + }
  73 + function handleChangeYear(value) {
  74 + if (period.value == null) {
  75 + period.value = '月';
  76 + periodCopy.value = '月';
  77 + }
  78 + yearValue.value = value;
  79 + dateTime.value = yearValue.value;
  80 + }
17 const dataStore = useDataStoreWithOut(); 81 const dataStore = useDataStoreWithOut();
18 - watchEffect(() => {  
19 - const data = dataStore?.getChartData || {}; 82 + //监控选择器变化
  83 + watchEffect(async () => {
  84 + // const data = dataStore?.getChartData || {};
  85 + const chartData = await getChartData({
  86 + dateTime: dateTime.value,
  87 + period: period.value,
  88 + });
  89 + const x = [],
  90 + y = [];
  91 + for (const key in chartData) {
  92 + x.push(chartData[key].date);
  93 + y.push(chartData[key].count);
  94 + }
  95 + const data = { x, y };
20 const maxY = data?.y ? max(data?.y) : 0; 96 const maxY = data?.y ? max(data?.y) : 0;
21 setOptions({ 97 setOptions({
22 tooltip: { 98 tooltip: {
@@ -30,7 +106,6 @@ @@ -30,7 +106,6 @@
30 }, 106 },
31 xAxis: { 107 xAxis: {
32 type: 'category', 108 type: 'category',
33 - boundaryGap: false,  
34 data: data?.x, 109 data: data?.x,
35 splitLine: { 110 splitLine: {
36 show: true, 111 show: true,
@@ -87,3 +162,29 @@ @@ -87,3 +162,29 @@
87 }); 162 });
88 }); 163 });
89 </script> 164 </script>
  165 +<style scoped>
  166 + .custom-radio-group .ant-radio-button-wrapper {
  167 + border-color: #1684fc; /* 未选中按钮的边框颜色 */
  168 + background-color: white; /* 未选中按钮的背景颜色为白色 */
  169 + color: #1684fc; /* 未选中按钮的文字颜色为 #1684fc */
  170 + }
  171 +
  172 + .custom-radio-group .ant-radio-button-wrapper-checked {
  173 + border-color: #1684fc; /* 选中按钮的边框颜色 */
  174 + background-color: #1684fc; /* 选中按钮的背景颜色为 #1684fc */
  175 + color: white; /* 选中按钮的文字颜色为白色 */
  176 + }
  177 +
  178 + .custom-radio-group .ant-radio-button-wrapper-checked:hover {
  179 + background-color: #1684fc; /* 悬停在选中按钮时保持相同的背景颜色 */
  180 + color: white; /* 悬停在选中按钮时保持文字为白色 */
  181 + }
  182 +
  183 + .custom-radio-group .ant-radio-button-wrapper:hover {
  184 + border-color: #1684fc; /* 悬停在未选中按钮时的边框颜色 */
  185 + }
  186 +
  187 + .custom-radio-group .ant-radio-button-wrapper:not(.ant-radio-button-wrapper-checked):hover {
  188 + color: #1684fc; /* 悬停在未选中按钮时文字颜色为 #1684fc */
  189 + }
  190 +</style>
src/views/dashboard/analysis/components/VisitAnalysisBar.vue
@@ -55,7 +55,7 @@ @@ -55,7 +55,7 @@
55 </div></div 55 </div></div
56 > 56 >
57 <div v-if="role !== ROLE.ADMIN" style="margin-bottom: 60px"></div> 57 <div v-if="role !== ROLE.ADMIN" style="margin-bottom: 60px"></div>
58 - <div ref="chartRef" :style="{ height, width }"></div> 58 + <div ref="chartRef" :style="{ height: '400px', width }"></div>
59 </template> 59 </template>
60 <script lang="ts"> 60 <script lang="ts">
61 import { basicProps } from './props'; 61 import { basicProps } from './props';
@@ -177,23 +177,28 @@ @@ -177,23 +177,28 @@
177 }, 177 },
178 }, 178 },
179 }, 179 },
180 - grid: { left: '1%', right: '1%', top: '2 %', bottom: 0, containLabel: true }, 180 + legend: {
  181 + data: ['销售额', '销售目标'],
  182 + },
  183 + grid: { left: '1%', right: '1%', top: '10 %', bottom: 0, containLabel: true },
181 xAxis: { 184 xAxis: {
182 type: 'category', 185 type: 'category',
183 data: customerChartData1?.x, 186 data: customerChartData1?.x,
184 }, 187 },
185 yAxis: { 188 yAxis: {
186 type: 'value', 189 type: 'value',
187 - // max: 8000,  
188 - splitNumber: 4, 190 + // // max: 8000,
  191 + // splitNumber: 4,
189 }, 192 },
190 series: [ 193 series: [
191 { 194 {
  195 + name: '销售额',
192 data: customerChartData1?.y, 196 data: customerChartData1?.y,
193 type: 'bar', 197 type: 'bar',
194 barMaxWidth: 80, 198 barMaxWidth: 80,
195 }, 199 },
196 { 200 {
  201 + name: '销售目标',
197 smooth: true, 202 smooth: true,
198 data: customerChartData1?.z, 203 data: customerChartData1?.z,
199 type: 'line', 204 type: 'line',
src/views/project/approve/FieldPanel.vue
@@ -143,6 +143,11 @@ @@ -143,6 +143,11 @@
143 dataIndex: 'picUrl', 143 dataIndex: 'picUrl',
144 width: 150, 144 width: 150,
145 }, 145 },
  146 + {
  147 + title: '申请原因',
  148 + dataIndex: 'applyRemark',
  149 + width: 150,
  150 + },
146 ]; 151 ];
147 152
148 if (props.isApproved) { 153 if (props.isApproved) {
src/views/project/approve/PayPanel.vue
@@ -12,6 +12,7 @@ @@ -12,6 +12,7 @@
12 </template> 12 </template>
13 <template v-if="column.key === 'action'"> 13 <template v-if="column.key === 'action'">
14 <TableAction 14 <TableAction
  15 + v-if="!isApproved"
15 :actions="[ 16 :actions="[
16 { 17 {
17 label: '编辑', 18 label: '编辑',
@@ -20,15 +21,29 @@ @@ -20,15 +21,29 @@
20 }, 21 },
21 ]" 22 ]"
22 /> 23 />
  24 + <TableAction
  25 + v-if="isApproved"
  26 + :actions="[
  27 + {
  28 + label: '详情',
  29 + // icon: 'ic:outline-delete-outline',
  30 + onClick: handleDetail.bind(null, record),
  31 + },
  32 + ]"
  33 + />
23 </template> 34 </template>
24 </template> 35 </template>
25 </BasicTable> 36 </BasicTable>
  37 + <!-- :showFooter="!isApproved && role === ROLE.ADMIN" -->
  38 +
26 <BasicModal 39 <BasicModal
27 - :showFooter="!isApproved && role === ROLE.ADMIN" 40 + :formFooter="!isApproved && role === ROLE.ADMIN"
28 @register="registerModal" 41 @register="registerModal"
29 title="申请信息" 42 title="申请信息"
30 okText="通过" 43 okText="通过"
31 @ok="handleTrue" 44 @ok="handleTrue"
  45 + :showCancelBtn="!isApproved && role === ROLE.ADMIN"
  46 + :showOkBtn="!isApproved && role === ROLE.ADMIN"
32 > 47 >
33 <Description 48 <Description
34 class="mt-4" 49 class="mt-4"
@@ -39,7 +54,7 @@ @@ -39,7 +54,7 @@
39 :schema="schema" 54 :schema="schema"
40 /> 55 />
41 <template #appendFooter> 56 <template #appendFooter>
42 - <a-button @click="handleFalse"> 不通过</a-button> 57 + <a-button v-if="!isApproved && role === ROLE.ADMIN" @click="handleFalse"> 不通过</a-button>
43 </template> 58 </template>
44 </BasicModal> 59 </BasicModal>
45 <MsgModal v-if="msgVisible" @msg-modal-close="handleMsgModalClose" /> 60 <MsgModal v-if="msgVisible" @msg-modal-close="handleMsgModalClose" />
@@ -84,29 +99,30 @@ @@ -84,29 +99,30 @@
84 const id = ref(''); 99 const id = ref('');
85 100
86 const mockData = ref(); 101 const mockData = ref();
87 - const schema: DescItem[] = [ 102 + const actualPayCalculate = ref(0);
  103 + const schema = [
88 { 104 {
89 - field: 'actualReceivableAmount', 105 + field: 'actualPayedAmount',
90 label: '生产科实际应付金额汇总', 106 label: '生产科实际应付金额汇总',
91 }, 107 },
92 { 108 {
93 - field: 'all', 109 + field: 'payedDate',
94 label: '生产科付款日期', 110 label: '生产科付款日期',
95 }, 111 },
96 { 112 {
97 - field: 'deductAmount', 113 + field: 'actualPayedDate',
98 label: '实际付款日期', 114 label: '实际付款日期',
99 }, 115 },
100 { 116 {
101 - field: 'productionDepartmentTotalPrice', 117 + field: 'totalProductionAmount',
102 label: '生产科总金额汇总', 118 label: '生产科总金额汇总',
103 }, 119 },
104 { 120 {
105 - field: 'actualPayedAmount', 121 + field: 'totalActualPayedAmount',
106 label: '实际付款金额汇总', 122 label: '实际付款金额汇总',
107 }, 123 },
108 { 124 {
109 - field: 'actualReceivableAmount', 125 + field: 'deductAmount',
110 label: '生产科扣款金额汇总', 126 label: '生产科扣款金额汇总',
111 }, 127 },
112 ]; 128 ];
@@ -128,19 +144,31 @@ @@ -128,19 +144,31 @@
128 width: 150, 144 width: 150,
129 customRender: (column) => { 145 customRender: (column) => {
130 const { record } = column || {}; 146 const { record } = column || {};
131 - console.log(record, '56565repro');  
132 - return record?.fieldInfos?.invoiceBillOrderDO?.innerNo; 147 + return record?.orderBaseInfo?.innerNo;
133 }, 148 },
134 }, 149 },
135 { 150 {
136 title: '审核类型', 151 title: '审核类型',
137 dataIndex: 'productionDepartment', 152 dataIndex: 'productionDepartment',
138 width: 150, 153 width: 150,
  154 + customRender: (column) => {
  155 + const { record } = column || {};
  156 + if (record?.type === 40) {
  157 + return '生产科应付款';
  158 + } else if (record?.type == 50) {
  159 + return '生产科发票';
  160 + }
  161 + },
139 }, 162 },
140 { 163 {
141 title: '生产科', 164 title: '生产科',
142 dataIndex: 'productionDepartment', 165 dataIndex: 'productionDepartment',
143 width: 150, 166 width: 150,
  167 + customRender: (column) => {
  168 + const { record } = column || {};
  169 + console.log(record, '56565repro');
  170 + return record?.fieldInfos?.checkBillOrderDO?.deductDept;
  171 + },
144 }, 172 },
145 ]; 173 ];
146 174
@@ -204,8 +232,7 @@ @@ -204,8 +232,7 @@
204 232
205 async function handleDetail(data) { 233 async function handleDetail(data) {
206 openModal(true, { data }); 234 openModal(true, { data });
207 - mockData.value = data.fieldInfos.invoiceBillOrderDO;  
208 - console.log(mockData.value, 5656); 235 + mockData.value = data.fieldInfos.checkBillOrderDO;
209 id.value = data.id; 236 id.value = data.id;
210 } 237 }
211 238
src/views/project/approve/ProfitPanel.vue
@@ -93,7 +93,7 @@ @@ -93,7 +93,7 @@
93 const { record } = column || {}; 93 const { record } = column || {};
94 return record?.orderBaseInfo?.innerNo; 94 return record?.orderBaseInfo?.innerNo;
95 }, 95 },
96 - }, 96 + },
97 { 97 {
98 title: '图片', 98 title: '图片',
99 dataIndex: 'picUrl', 99 dataIndex: 'picUrl',
src/views/project/approve/ReceivePanel.vue
@@ -12,6 +12,7 @@ @@ -12,6 +12,7 @@
12 </template> 12 </template>
13 <template v-if="column.key === 'action'"> 13 <template v-if="column.key === 'action'">
14 <TableAction 14 <TableAction
  15 + v-if="!isApproved"
15 :actions="[ 16 :actions="[
16 { 17 {
17 label: '编辑', 18 label: '编辑',
@@ -20,15 +21,27 @@ @@ -20,15 +21,27 @@
20 }, 21 },
21 ]" 22 ]"
22 /> 23 />
  24 + <TableAction
  25 + v-if="isApproved"
  26 + :actions="[
  27 + {
  28 + label: '详情',
  29 + // icon: 'ic:outline-delete-outline',
  30 + onClick: handleDetail.bind(null, record),
  31 + },
  32 + ]"
  33 + />
23 </template> 34 </template>
24 </template> 35 </template>
25 </BasicTable> 36 </BasicTable>
26 <BasicModal 37 <BasicModal
27 - :showFooter="!isApproved && role === ROLE.ADMIN" 38 + :formFooter="!isApproved && role === ROLE.ADMIN"
28 @register="registerModal" 39 @register="registerModal"
29 title="申请信息" 40 title="申请信息"
30 okText="通过" 41 okText="通过"
31 @ok="handleTrue" 42 @ok="handleTrue"
  43 + :showCancelBtn="!isApproved && role === ROLE.ADMIN"
  44 + :showOkBtn="!isApproved && role === ROLE.ADMIN"
32 > 45 >
33 <Description 46 <Description
34 class="mt-4" 47 class="mt-4"
@@ -39,7 +52,7 @@ @@ -39,7 +52,7 @@
39 :schema="schema" 52 :schema="schema"
40 /> 53 />
41 <template #appendFooter> 54 <template #appendFooter>
42 - <a-button @click="handleFalse"> 不通过</a-button> 55 + <a-button v-if="!isApproved && role === ROLE.ADMIN" @click="handleFalse"> 不通过</a-button>
43 </template> 56 </template>
44 </BasicModal> 57 </BasicModal>
45 <MsgModal v-if="msgVisible" @msg-modal-close="handleMsgModalClose" /> 58 <MsgModal v-if="msgVisible" @msg-modal-close="handleMsgModalClose" />
@@ -90,7 +103,7 @@ @@ -90,7 +103,7 @@
90 label: '实际收款金额汇总', 103 label: '实际收款金额汇总',
91 }, 104 },
92 { 105 {
93 - field: 'all', 106 + field: 'totalCustomerAmount',
94 label: '客户总价金额汇总', 107 label: '客户总价金额汇总',
95 }, 108 },
96 { 109 {
@@ -102,7 +115,7 @@ @@ -102,7 +115,7 @@
102 label: '必须回款日期', 115 label: '必须回款日期',
103 }, 116 },
104 { 117 {
105 - field: 'addr', 118 + field: 'actualRefundDate',
106 label: '实际回款日期', 119 label: '实际回款日期',
107 }, 120 },
108 { 121 {
@@ -138,7 +151,7 @@ @@ -138,7 +151,7 @@
138 width: 150, 151 width: 150,
139 customRender: (column) => { 152 customRender: (column) => {
140 const { record } = column || {}; 153 const { record } = column || {};
141 - return record?.fieldInfos?.invoiceBillOrderDO?.innnerNo; 154 + return record?.orderBaseInfo?.innerNo;
142 }, 155 },
143 }, 156 },
144 // { 157 // {
@@ -213,7 +226,7 @@ @@ -213,7 +226,7 @@
213 async function handleDetail(data) { 226 async function handleDetail(data) {
214 openModal(true, { data }); 227 openModal(true, { data });
215 mockData.value = data.fieldInfos.invoiceBillOrderDO; 228 mockData.value = data.fieldInfos.invoiceBillOrderDO;
216 - console.log(mockData.value, 5656); 229 + console.log(data, 5656777);
217 id.value = data.id; 230 id.value = data.id;
218 } 231 }
219 232
src/views/project/config/CreateModal.vue
@@ -58,16 +58,7 @@ @@ -58,16 +58,7 @@
58 { 58 {
59 field: 'relationValue', 59 field: 'relationValue',
60 component: 'InputNumber', 60 component: 'InputNumber',
61 - label:  
62 - props.column === 1  
63 - ? '利润率'  
64 - : props.column === 5  
65 - ? '回款时间'  
66 - : props.column === 6  
67 - ? '固定成本'  
68 - : props.column === 7  
69 - ? '销售额'  
70 - : '包装费用', 61 + label: props.column === 1 ? '利润率' : '包装费用',
71 rules: [{ required: true }], 62 rules: [{ required: true }],
72 colProps: { 63 colProps: {
73 span: 24, 64 span: 24,
@@ -105,16 +96,7 @@ @@ -105,16 +96,7 @@
105 settingName: '客户编码', 96 settingName: '客户编码',
106 settingValue: values.settingValue, 97 settingValue: values.settingValue,
107 settingType: 1, 98 settingType: 1,
108 - // relationCode: props.column === 1 ? 'profitRate' : 'packetPrice',  
109 - relationCode:  
110 - props.column === 1  
111 - ? 'profitRate'  
112 - : props.column === 5  
113 - ? 'orderHodTime'  
114 - : props.column === 7  
115 - ? 'salesAmount'  
116 - : 'packetPrice',  
117 - 99 + relationCode: props.column === 1 ? 'profitRate' : 'packetPrice',
118 relationName: '包装费用', 100 relationName: '包装费用',
119 relationValue: values.relationValue, 101 relationValue: values.relationValue,
120 }; 102 };
src/views/project/config/TablePanel.vue
1 <template> 1 <template>
2 <BasicTable @register="registerTable" :bordered="true"> 2 <BasicTable @register="registerTable" :bordered="true">
3 <template #toolbar> 3 <template #toolbar>
4 - <a-button v-if="props.column !== 3" type="primary" @click="handleCreateModal">新建</a-button> 4 + <a-button
  5 + v-if="props.column !== 3 && props.column !== 6"
  6 + type="primary"
  7 + @click="handleCreateModal"
  8 + >新建</a-button
  9 + >
  10 + <a-button v-if="props.column == 6" type="primary" @click="handleCostCreate">新建</a-button>
5 </template> 11 </template>
6 <template #bodyCell="{ column, record }"> 12 <template #bodyCell="{ column, record }">
7 <template v-if="column.key === 'action'"> 13 <template v-if="column.key === 'action'">
@@ -9,6 +15,8 @@ @@ -9,6 +15,8 @@
9 </template> 15 </template>
10 </template> 16 </template>
11 </BasicTable> 17 </BasicTable>
  18 + <CostEdit @register="registerEdit" @success="handleModalSuccess" />
  19 + <CostCreate @register="registerCostCreate" @modal-success="handleModalSuccess" />
12 <CreateModal 20 <CreateModal
13 @register="createModalRegister" 21 @register="createModalRegister"
14 @modal-success="handleModalSuccess" 22 @modal-success="handleModalSuccess"
@@ -21,6 +29,9 @@ @@ -21,6 +29,9 @@
21 import { deleteConfig, getList, saveConfig } from '/@/api/sys/config'; 29 import { deleteConfig, getList, saveConfig } from '/@/api/sys/config';
22 import { COLUMNS } from './data'; 30 import { COLUMNS } from './data';
23 import { useModal } from '/@/components/Modal'; 31 import { useModal } from '/@/components/Modal';
  32 + import { useDrawer } from '/@/components/Drawer';
  33 + import CostEdit from './costEdit.vue';
  34 + import CostCreate from './costCreate.vue';
24 35
25 const props = defineProps({ 36 const props = defineProps({
26 searchInfo: { 37 searchInfo: {
@@ -31,6 +42,8 @@ @@ -31,6 +42,8 @@
31 }, 42 },
32 }); 43 });
33 const [createModalRegister, { openModal }] = useModal(); 44 const [createModalRegister, { openModal }] = useModal();
  45 + const [registerCostCreate, { openModal: openCostCreateModal }] = useModal();
  46 + const [registerEdit, { openDrawer: openDrawerEdit }] = useDrawer();
34 47
35 const [registerTable, { reload }] = useTable({ 48 const [registerTable, { reload }] = useTable({
36 api: getList, 49 api: getList,
@@ -52,10 +65,27 @@ @@ -52,10 +65,27 @@
52 function createActions(record: any): any[] { 65 function createActions(record: any): any[] {
53 if (!record.editable) { 66 if (!record.editable) {
54 return [ 67 return [
55 - {  
56 - label: '编辑',  
57 - onClick: handleEdit.bind(null, record),  
58 - }, 68 + // {
  69 + // ...(props.column !== 6 && {
  70 + // label: '编辑',
  71 + // onClick: handleEdit.bind(null, record),
  72 + // }),
  73 + // },
  74 + ...(props.column === 6
  75 + ? [
  76 + {
  77 + label: '编辑',
  78 + onClick: handleCostEdit.bind(null, record),
  79 + },
  80 + ]
  81 + : props.column !== 6
  82 + ? [
  83 + {
  84 + label: '编辑',
  85 + onClick: handleEdit.bind(null, record),
  86 + },
  87 + ]
  88 + : []),
59 { 89 {
60 ...(props.column !== 3 && { 90 ...(props.column !== 3 && {
61 label: '删除', 91 label: '删除',
@@ -92,7 +122,21 @@ @@ -92,7 +122,21 @@
92 handleCancel(record); 122 handleCancel(record);
93 reload(); 123 reload();
94 } 124 }
95 - 125 + function handleCostEdit(record: any) {
  126 + console.log('5656hasedit');
  127 + openDrawerEdit(true, {
  128 + data: record,
  129 + isUpdate: true,
  130 + });
  131 + }
  132 + function handleCostCreate(record: any) {
  133 + console.log(56561);
  134 + openCostCreateModal(true, {
  135 + data: record,
  136 + isUpdate: true,
  137 + });
  138 + console.log(56562);
  139 + }
96 function handleEdit(record: any) { 140 function handleEdit(record: any) {
97 record.onEdit?.(true); 141 record.onEdit?.(true);
98 } 142 }
src/views/project/config/costCreate.vue 0 → 100644
  1 +<template>
  2 + <BasicModal
  3 + v-bind="$attrs"
  4 + destroyOnClose
  5 + @register="register"
  6 + title="创建配置"
  7 + width="600px"
  8 + @visible-change="handleShow"
  9 + @ok="handleOk"
  10 + >
  11 + <a-space direction="vertical" style="width: 100%">
  12 + <div
  13 + ><span style="margin-right: 8px">客户编码:</span>
  14 + <a-select
  15 + ref="select"
  16 + style="width: 100%"
  17 + v-model:value="customerCode"
  18 + :options="customerCodeOptions"
  19 + /></div>
  20 + <div
  21 + ><span style="margin-right: 8px; width: 80%">固定成本:</span>
  22 + <a-input v-model:value="fixCost"
  23 + /></div>
  24 + <div
  25 + ><span style="margin-right: 8px; width: 80%">提成比例:</span>
  26 + <a-input v-model:value="ratio" />
  27 + </div>
  28 + <div
  29 + ><span style="margin-right: 8px; width: 80%">西班牙提成比例:</span>
  30 + <a-input v-model:value="spainRatio" />
  31 + </div>
  32 + <div
  33 + ><span style="margin-right: 8px; width: 80%">生产提成单价:</span>
  34 + <a-input v-model:value="price" />
  35 + </div>
  36 + </a-space>
  37 + </BasicModal>
  38 +</template>
  39 +<script lang="ts">
  40 + import { defineComponent, ref, defineEmits } from 'vue';
  41 + import { BasicModal, useModalInner } from '/@/components/Modal';
  42 + import { orderGravity } from '/@/api/project/order';
  43 + import { useOrderStoreWithOut } from '/@/store/modules/order';
  44 + import { useOrderInfo } from '/@/hooks/component/order';
  45 + import { BasicForm, useForm } from '/@/components/Form/index';
  46 + import { addConfig } from '/@/api/sys/config';
  47 +
  48 + export default defineComponent({
  49 + components: { BasicModal, BasicForm },
  50 + props: {
  51 + column: { type: Number },
  52 + },
  53 + emits: ['modal-success'],
  54 + setup(props, { emit }) {
  55 + const orderStore = useOrderStoreWithOut();
  56 + const loading = ref(true);
  57 + const activeUser = ref();
  58 + const info = ref();
  59 + const [register, { setModalProps, closeModal }] = useModalInner(async (data) => {
  60 + listAll.value = data;
  61 + console.log(listAll.value, '5656modaldata.value');
  62 + });
  63 + //获取现有的列表
  64 + const listAll = ref();
  65 + const fixCost = ref();
  66 + const ratio = ref();
  67 + const spainRatio = ref();
  68 + const price = ref();
  69 + // const relationValue = ref();
  70 + const customerCode = ref();
  71 + const relationValue = ref([
  72 + {
  73 + relationCode: 'fixCost',
  74 + relationName: '固定成本',
  75 + relationValue: '',
  76 + },
  77 + {
  78 + relationCode: 'ratio',
  79 + relationName: '提成比例',
  80 + relationValue: '',
  81 + },
  82 + {
  83 + relationCode: 'spainRatio',
  84 + relationName: '西班牙提成比例',
  85 + relationValue: '',
  86 + },
  87 + {
  88 + relationCode: 'price',
  89 + relationName: '生产提成单价',
  90 + relationValue: '',
  91 + },
  92 + ]);
  93 + // const loading = ref(true);
  94 +
  95 + const { customerCode: customerCodeOptions } = useOrderInfo(orderStore);
  96 +
  97 + function handleShow(visible: boolean) {
  98 + if (visible) {
  99 + loading.value = true;
  100 + // setModalProps({ loading: true, confirmLoading: true });
  101 + setModalProps({ loading: false, confirmLoading: false });
  102 + }
  103 + }
  104 +
  105 + async function handleOk() {
  106 + try {
  107 + relationValue.value[0].relationValue = fixCost.value;
  108 + relationValue.value[1].relationValue = ratio.value;
  109 + relationValue.value[2].relationValue = spainRatio.value;
  110 + relationValue.value[3].relationValue = price.value;
  111 + await addConfig({
  112 + settingCode: 'customerCode',
  113 + settingName: '客户提成成本配置',
  114 + settingValue: customerCode.value,
  115 + settingType: 3,
  116 + relationCode: 'costSettingItem',
  117 + relationName: '成本配置项集合',
  118 + costSettingItemVOS: relationValue.value,
  119 + });
  120 + emit('modal-success');
  121 + closeModal();
  122 + } catch (error) {
  123 + console.log('%c [ error ]-108', 'font-size:13px; background:pink; color:#bf2c9f;', error);
  124 + }
  125 + }
  126 + return {
  127 + register,
  128 + loading,
  129 + handleShow,
  130 + info,
  131 + activeUser,
  132 + fixCost,
  133 + ratio,
  134 + spainRatio,
  135 + price,
  136 + customerCode,
  137 + customerCodeOptions,
  138 + handleOk,
  139 + };
  140 + },
  141 + });
  142 +</script>
  143 +<style scoped>
  144 + .empty-tips {
  145 + height: 100px;
  146 + line-height: 100px;
  147 + text-align: center;
  148 + }
  149 +</style>
src/views/project/config/costEdit.vue 0 → 100644
  1 +<template>
  2 + <BasicDrawer
  3 + v-cloakv-bind="$attrs"
  4 + @register="register"
  5 + title="编辑"
  6 + width="35%"
  7 + showFooter
  8 + @ok="handleSubmit"
  9 + ref="formRef"
  10 + okText="保存"
  11 + :destroyOnClose="true"
  12 + :isDetail="true"
  13 + :showDetailBack="false"
  14 + :mask="false"
  15 + class="z-20"
  16 + >
  17 + <a-space direction="vertical" style="width: 100%">
  18 + <a-input v-model:value="fixCost" addonBefore="固定成本 " />
  19 + <a-input v-model:value="ratio" addonBefore="提成比例 " />
  20 + <a-input v-model:value="spainRatio" addonBefore="西班牙提成比例 " />
  21 + <a-input v-model:value="price" addonBefore="生产提成单价" />
  22 + </a-space>
  23 + </BasicDrawer>
  24 +</template>
  25 +<script lang="ts" setup>
  26 + import { BasicDrawer, useDrawerInner } from '@/components/Drawer';
  27 + import { BasicForm, FormSchema, useForm } from '@/components/Form';
  28 + import { defineComponent, ref, computed, unref, toRaw, reactive, onMounted } from 'vue';
  29 + import { saveConfig } from '/@/api/sys/config';
  30 +
  31 + // const emit = defineEmits(['success']);
  32 + // const isUpdate = ref(true);
  33 + const emit = defineEmits(['success']);
  34 +
  35 + const [register, { closeDrawer }] = useDrawerInner((data) => {
  36 + listAll.value = data.data;
  37 + console.log(listAll.value, '5656listAll.value');
  38 + relationValue.value = JSON.parse(listAll.value.relationValue);
  39 + fixCost.value = relationValue.value[0].relationValue;
  40 + ratio.value = relationValue.value[1].relationValue;
  41 + spainRatio.value = relationValue.value[2].relationValue;
  42 + price.value = relationValue.value[3].relationValue;
  43 + });
  44 + //获取现有的列表
  45 + const listAll = ref();
  46 + const fixCost = ref();
  47 + const ratio = ref();
  48 + const spainRatio = ref();
  49 + const price = ref();
  50 + const relationValue = ref();
  51 +
  52 + //完成编辑
  53 + async function handleSubmit() {
  54 + relationValue.value[0].relationValue = fixCost.value;
  55 + relationValue.value[1].relationValue = ratio.value;
  56 + relationValue.value[2].relationValue = spainRatio.value;
  57 + relationValue.value[3].relationValue = price.value;
  58 + console.log(relationValue.value, '5656relationValue.value');
  59 + await saveConfig({
  60 + id: listAll.value.id,
  61 + settingCode: 'customerCode',
  62 + settingName: '客户提成成本配置',
  63 + settingValue: listAll.value.settingValue,
  64 + settingType: 3,
  65 + relationCode: 'costSettingItem',
  66 + relationName: '成本配置项集合',
  67 + costSettingItemVOS: relationValue.value,
  68 + });
  69 + emit('success');
  70 + closeDrawer();
  71 + }
  72 +</script>
src/views/project/config/data.tsx
@@ -70,22 +70,37 @@ export const COLUMNS = { @@ -70,22 +70,37 @@ export const COLUMNS = {
70 title: '固定成本', 70 title: '固定成本',
71 dataIndex: 'relationValue', 71 dataIndex: 'relationValue',
72 width: 150, 72 width: 150,
73 - editComponent: 'InputNumber',  
74 - editRow: true, 73 + customRender: (column) => {
  74 + const value = JSON.parse(column.record.relationValue);
  75 + return value[0].relationValue;
  76 + },
75 }, 77 },
76 { 78 {
77 title: '提成比例', 79 title: '提成比例',
78 dataIndex: 'relationValue', 80 dataIndex: 'relationValue',
79 width: 150, 81 width: 150,
80 - editComponent: 'InputNumber',  
81 - editRow: true, 82 + customRender: (column) => {
  83 + const value = JSON.parse(column.record.relationValue);
  84 + return value[1].relationValue;
  85 + },
82 }, 86 },
83 { 87 {
84 - title: '生产科提成单价', 88 + title: '西班牙提成比例',
85 dataIndex: 'relationValue', 89 dataIndex: 'relationValue',
86 width: 150, 90 width: 150,
87 - editComponent: 'InputNumber',  
88 - editRow: true, 91 + customRender: (column) => {
  92 + const value = JSON.parse(column.record.relationValue);
  93 + return value[2].relationValue;
  94 + },
  95 + },
  96 + {
  97 + title: '生产提成单价',
  98 + dataIndex: 'relationValue',
  99 + width: 150,
  100 + customRender: (column) => {
  101 + const value = JSON.parse(column.record.relationValue);
  102 + return value[3].relationValue;
  103 + },
89 }, 104 },
90 ], 105 ],
91 7: [ 106 7: [
src/views/project/config/index.vue
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 <TablePanel :searchInfo="{ relationCode: 'orderHodTime' }" :column="5" /> 20 <TablePanel :searchInfo="{ relationCode: 'orderHodTime' }" :column="5" />
21 </Tabs.TabPane> 21 </Tabs.TabPane>
22 <Tabs.TabPane key="6" tab="提成成本配置"> 22 <Tabs.TabPane key="6" tab="提成成本配置">
23 - <TablePanel :searchInfo="{ relationCode: 'orderHodTime' }" :column="6" /> 23 + <TablePanel :searchInfo="{ relationCode: 'costSettingItem' }" :column="6" />
24 </Tabs.TabPane> 24 </Tabs.TabPane>
25 <Tabs.TabPane key="7" tab="销售额配置"> 25 <Tabs.TabPane key="7" tab="销售额配置">
26 <TablePanel :searchInfo="{ relationCode: 'salesAmount' }" :column="7" /> 26 <TablePanel :searchInfo="{ relationCode: 'salesAmount' }" :column="7" />
src/views/project/finance/pay/DeductShow.vue 0 → 100644
  1 +<template>
  2 + <BasicModal
  3 + v-bind="$attrs"
  4 + @register="register"
  5 + title="扣款单"
  6 + width="500px"
  7 + :bodyStyle="{ height: '240px' }"
  8 + @ok="handleOk"
  9 + >
  10 + </BasicModal>
  11 +</template>
  12 +<script lang="ts" setup>
  13 + import { BasicModal, useModalInner } from '@/components/Modal';
  14 + import { computed, ref } from 'vue';
  15 + import type { UploadProps, UploadChangeParam } from 'ant-design-vue';
  16 + import { InboxOutlined } from '@ant-design/icons-vue';
  17 + import { message } from 'ant-design-vue';
  18 + import { updateInvoiceInfo } from '@/api/project/invoice';
  19 +
  20 + const deductUrl = ref();
  21 + const id = ref();
  22 +
  23 + const [register, { closeModal }] = useModalInner(async (data) => {
  24 + deductUrl.value = data;
  25 + });
  26 +
  27 + async function handleOk() {
  28 + closeModal();
  29 + }
  30 +</script>
src/views/project/finance/pay/index.vue
@@ -2,12 +2,18 @@ @@ -2,12 +2,18 @@
2 <div class="p-4"> 2 <div class="p-4">
3 <BasicTable @register="registerTable"> 3 <BasicTable @register="registerTable">
4 <template #toolbar> 4 <template #toolbar>
5 - <a-button type="primary" @click="handleCheckSum">应付款汇总</a-button> 5 + <a-button
  6 + type="primary"
  7 + @click="handleCheckSum"
  8 + :style="{ borderRadius: '5px 5px 5px 5px' }"
  9 + >应付款汇总</a-button
  10 + >
6 <FinanceEdit @register="registerFinanceEdit" @success="handleSuccess" /> 11 <FinanceEdit @register="registerFinanceEdit" @success="handleSuccess" />
7 <TrackEdit @register="registerTrackEdit" @success="handleSuccess" /> 12 <TrackEdit @register="registerTrackEdit" @success="handleSuccess" />
8 <CheckSum @register="registerCheckSum" /> 13 <CheckSum @register="registerCheckSum" />
9 <InvoiceUpload @register="registerInvoiceUpload" @success="handleSuccess" /> 14 <InvoiceUpload @register="registerInvoiceUpload" @success="handleSuccess" />
10 <CheckDetail @register="registerInvoiceDetail" /> 15 <CheckDetail @register="registerInvoiceDetail" />
  16 + <DeductShow @register="registerDeductShow" />
11 </template> 17 </template>
12 <template #bodyCell="{ column, record }"> 18 <template #bodyCell="{ column, record }">
13 <template v-if="column.key === 'action'"> 19 <template v-if="column.key === 'action'">
@@ -39,6 +45,14 @@ @@ -39,6 +45,14 @@
39 label: '删除', 45 label: '删除',
40 onClick: handleDelete.bind(null, record), 46 onClick: handleDelete.bind(null, record),
41 }, 47 },
  48 + {
  49 + label: '生产科发票',
  50 + onClick: handleInvoiceShow.bind(null, record),
  51 + },
  52 + {
  53 + label: '扣款单',
  54 + onClick: handleDeductShow.bind(null, record),
  55 + },
42 ]" 56 ]"
43 /> 57 />
44 </template> 58 </template>
@@ -55,6 +69,7 @@ @@ -55,6 +69,7 @@
55 import InvoiceUpload from './InvoiceUpload.vue'; 69 import InvoiceUpload from './InvoiceUpload.vue';
56 import CheckDetail from './CheckDetail.vue'; 70 import CheckDetail from './CheckDetail.vue';
57 import CheckSum from './CheckSum.vue'; 71 import CheckSum from './CheckSum.vue';
  72 + import DeductShow from './DeductShow.vue';
58 import { useDrawer } from '/@/components/Drawer'; 73 import { useDrawer } from '/@/components/Drawer';
59 import { useModal } from '/@/components/Modal'; 74 import { useModal } from '/@/components/Modal';
60 import { getCheck, checkDelete, checkCommit, checkDetail } from '@/api/project/invoice'; 75 import { getCheck, checkDelete, checkCommit, checkDetail } from '@/api/project/invoice';
@@ -64,6 +79,7 @@ @@ -64,6 +79,7 @@
64 const [registerFinanceEdit, { openDrawer: openFinanceEdit }] = useDrawer(); 79 const [registerFinanceEdit, { openDrawer: openFinanceEdit }] = useDrawer();
65 const [registerTrackEdit, { openDrawer: openTrackEdit }] = useDrawer(); 80 const [registerTrackEdit, { openDrawer: openTrackEdit }] = useDrawer();
66 const [registerInvoiceUpload, { openModal: openInvoiceUpload }] = useModal(); 81 const [registerInvoiceUpload, { openModal: openInvoiceUpload }] = useModal();
  82 + const [registerDeductShow, { openModal: openDeductShow }] = useModal();
67 const [registerInvoiceDetail, { openDrawer: openCheckDetail }] = useDrawer(); 83 const [registerInvoiceDetail, { openDrawer: openCheckDetail }] = useDrawer();
68 const checkedKeys = ref<Array<string | number>>([]); 84 const checkedKeys = ref<Array<string | number>>([]);
69 85
@@ -209,7 +225,7 @@ @@ -209,7 +225,7 @@
209 // console.log(selectedCustomCodes.value, 56561); 225 // console.log(selectedCustomCodes.value, 56561);
210 // console.log(checkedKeys.value, 56562); 226 // console.log(checkedKeys.value, 56562);
211 // } 227 // }
212 - 228 + //选择算法:创建二维数组,使客户编码和生产科相同
213 type CustomerCodeEntry = [string, number]; // 定义二维数组类型 [customerCode, count] 229 type CustomerCodeEntry = [string, number]; // 定义二维数组类型 [customerCode, count]
214 type ProductionDepartmentEntry = [string, number]; // 定义二维数组类型 [productionDepartment, count] 230 type ProductionDepartmentEntry = [string, number]; // 定义二维数组类型 [productionDepartment, count]
215 231
@@ -376,6 +392,14 @@ @@ -376,6 +392,14 @@
376 reload(); 392 reload();
377 }, 50); 393 }, 50);
378 } 394 }
  395 + function handleInvoiceShow(record) {
  396 + window.open(record.invoiceUrl);
  397 + }
  398 + function handleDeductShow(record) {
  399 + openDeductShow(true, {
  400 + data: record.deductUrl,
  401 + });
  402 + }
379 function handleDetail(record) { 403 function handleDetail(record) {
380 openCheckDetail(true, { 404 openCheckDetail(true, {
381 data: record, 405 data: record,
src/views/project/finance/receive/index.vue
@@ -2,7 +2,12 @@ @@ -2,7 +2,12 @@
2 <div class="p-4"> 2 <div class="p-4">
3 <BasicTable @register="registerTable"> 3 <BasicTable @register="registerTable">
4 <template #toolbar> 4 <template #toolbar>
5 - <a-button type="primary" @click="handleInvoiceAnalysis">收款单分析</a-button> 5 + <a-button
  6 + type="primary"
  7 + @click="handleInvoiceAnalysis"
  8 + :style="{ borderRadius: '5px 5px 5px 5px' }"
  9 + >收款单分析</a-button
  10 + >
6 <FinanceEdit @register="registerFinanceEdit" @success="handleSuccess" /> 11 <FinanceEdit @register="registerFinanceEdit" @success="handleSuccess" />
7 <InvoiceAnalysis @register="registerInvoiceAnalysis" /> 12 <InvoiceAnalysis @register="registerInvoiceAnalysis" />
8 <TrackEdit @register="registerTrackEdit" @success="handleSuccess" /> 13 <TrackEdit @register="registerTrackEdit" @success="handleSuccess" />
src/views/project/order/CheckDetail.vue
1 <template> 1 <template>
2 - <BasicDrawer  
3 - @register="register"  
4 - v-bind="$attrs"  
5 - showFooter  
6 - title="字段编辑权限申请"  
7 - width="60%"  
8 - :destroyOnClose="true"  
9 - :isDetail="true"  
10 - @ok="handleSubmit"  
11 - :showDetailBack="false"  
12 - okText="申请"  
13 - ><input />  
14 - <div>  
15 - <template v-if="role === ROLE.ADMIN || role === ROLE.TRACKER">  
16 - <h3>基本信息</h3>  
17 - <BasicForm @register="registerForm" />  
18 - </template>  
19 - <template v-if="role === ROLE.ADMIN || role === ROLE.BUSINESS">  
20 - <h3>利润分析</h3>  
21 - <BasicForm @register="registerProfitForm" />  
22 - </template>  
23 - <template v-if="role === ROLE.ADMIN || role === ROLE.BUSINESS">  
24 - <h3>项目报告书</h3>  
25 - <BasicForm @register="registerReportForm" />  
26 - </template>  
27 - <template v-if="role === ROLE.ADMIN || role === ROLE.TRACKER">  
28 - <h3>跟单信息</h3>  
29 - <BasicForm @register="registerTrackForm" />  
30 - </template>  
31 - <template v-if="role === ROLE.ADMIN || role === ROLE.INSPECT">  
32 - <h3>质量信息</h3>  
33 - <BasicForm @register="registryInspectForm" />  
34 - </template>  
35 - </div>  
36 - <!-- <template #titleToolbar> <a-button type="primary"> 申请编辑权限 </a-button></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 + <template v-if="role === ROLE.ADMIN || role === ROLE.BUSINESS">
  21 + <h3>利润分析</h3>
  22 + <BasicForm @register="registerProfitForm" />
  23 + </template>
  24 + <template v-if="role === ROLE.ADMIN || role === ROLE.BUSINESS">
  25 + <h3>项目报告书</h3>
  26 + <BasicForm @register="registerReportForm" />
  27 + </template>
  28 + <template v-if="role === ROLE.ADMIN || role === ROLE.TRACKER">
  29 + <h3>跟单信息</h3>
  30 + <BasicForm @register="registerTrackForm" />
  31 + </template>
  32 + <template v-if="role === ROLE.ADMIN || role === ROLE.INSPECT">
  33 + <h3>质量信息</h3>
  34 + <BasicForm @register="registryInspectForm" />
  35 + </template>
  36 + </div>
  37 + <!-- <template #titleToolbar> <a-button type="primary"> 申请编辑权限 </a-button></template> -->
37 38
38 - <!-- <template #appendFooter> 39 + <!-- <template #appendFooter>
39 <a-button type="primary" @click="onGoFormDetail"> 返回编辑</a-button> 40 <a-button type="primary" @click="onGoFormDetail"> 返回编辑</a-button>
40 </template> --> 41 </template> -->
41 - </BasicDrawer> 42 + </BasicDrawer>
  43 + <ApproveReason @register="approveReasonModalRegister" @success="handleCloseModal" />
  44 + </div>
42 </template> 45 </template>
43 <script lang="ts"> 46 <script lang="ts">
44 import { computed, defineComponent, reactive, ref } from 'vue'; 47 import { computed, defineComponent, reactive, ref } from 'vue';
45 import { BasicForm, useForm } from '/@/components/Form/index'; 48 import { BasicForm, useForm } from '/@/components/Form/index';
46 import { orderAuth } from '/@/api/project/order'; 49 import { orderAuth } from '/@/api/project/order';
47 import { ROLE } from './type.d'; 50 import { ROLE } from './type.d';
  51 + import { useModal } from '/@/components/Modal';
  52 + import ApproveReason from './FormDetail/ApproveReason.vue';
48 53
49 import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; 54 import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
50 import { 55 import {
@@ -79,7 +84,7 @@ @@ -79,7 +84,7 @@
79 ); 84 );
80 85
81 export default defineComponent({ 86 export default defineComponent({
82 - components: { BasicDrawer, BasicForm }, 87 + components: { BasicDrawer, BasicForm, ApproveReason },
83 props: { 88 props: {
84 onGoFormDetail: { 89 onGoFormDetail: {
85 type: Function, 90 type: Function,
@@ -92,6 +97,7 @@ @@ -92,6 +97,7 @@
92 const reportSchemas = getSchema(FIELDS_REPORT_INFO); 97 const reportSchemas = getSchema(FIELDS_REPORT_INFO);
93 const inspecSchemas = getSchema(FIELDS_INSPECTION_INFO); 98 const inspecSchemas = getSchema(FIELDS_INSPECTION_INFO);
94 const trackSchemas = getSchema(FIELDS_TRACK_STAGE_INFO); 99 const trackSchemas = getSchema(FIELDS_TRACK_STAGE_INFO);
  100 + const [approveReasonModalRegister, { openModal: openReasonModal }] = useModal();
95 const [registerForm, { getFieldsValue }] = useForm({ 101 const [registerForm, { getFieldsValue }] = useForm({
96 labelWidth: 120, 102 labelWidth: 120,
97 schemas, 103 schemas,
@@ -137,6 +143,9 @@ @@ -137,6 +143,9 @@
137 Object.assign(lockFields, data.lockFields); 143 Object.assign(lockFields, data.lockFields);
138 id.value = data.id; 144 id.value = data.id;
139 }); 145 });
  146 + function handleCloseModal() {
  147 + closeDrawer();
  148 + }
140 149
141 const role = computed(() => { 150 const role = computed(() => {
142 return userStore.getUserInfo?.roleSmallVO?.code; 151 return userStore.getUserInfo?.roleSmallVO?.code;
@@ -148,7 +157,6 @@ @@ -148,7 +157,6 @@
148 const reportFieldValues = getReportFieldsValue(); 157 const reportFieldValues = getReportFieldsValue();
149 const inspectFieldValues = getInspectFieldsValue(); 158 const inspectFieldValues = getInspectFieldsValue();
150 const trackFieldValues = getTrackFieldsValue(); 159 const trackFieldValues = getTrackFieldsValue();
151 -  
152 if (baseFieldValues) { 160 if (baseFieldValues) {
153 FIELDS_BASE_INFO.map( 161 FIELDS_BASE_INFO.map(
154 ({ field }) => 162 ({ field }) =>
@@ -156,14 +164,12 @@ @@ -156,14 +164,12 @@
156 baseFieldValues[field] === 'UN_LOCKED' ? 'UN_LOCKED' : 'LOCKED'), 164 baseFieldValues[field] === 'UN_LOCKED' ? 'UN_LOCKED' : 'LOCKED'),
157 ); 165 );
158 } 166 }
159 -  
160 if (reportFieldValues) 167 if (reportFieldValues)
161 FIELDS_REPORT_INFO.map( 168 FIELDS_REPORT_INFO.map(
162 ({ field }) => 169 ({ field }) =>
163 (reportFieldValues[field] = 170 (reportFieldValues[field] =
164 reportFieldValues[field] === 'UN_LOCKED' ? 'UN_LOCKED' : 'LOCKED'), 171 reportFieldValues[field] === 'UN_LOCKED' ? 'UN_LOCKED' : 'LOCKED'),
165 ); 172 );
166 -  
167 if (profitFieldValues) 173 if (profitFieldValues)
168 FIELDS_PROFIT_INFO.map( 174 FIELDS_PROFIT_INFO.map(
169 ({ field }) => 175 ({ field }) =>
@@ -176,21 +182,18 @@ @@ -176,21 +182,18 @@
176 (trackFieldValues[field] = 182 (trackFieldValues[field] =
177 trackFieldValues[field] === 'UN_LOCKED' ? 'UN_LOCKED' : 'LOCKED'), 183 trackFieldValues[field] === 'UN_LOCKED' ? 'UN_LOCKED' : 'LOCKED'),
178 ); 184 );
179 -  
180 if (inspectFieldValues) 185 if (inspectFieldValues)
181 FIELDS_INSPECTION_INFO.map( 186 FIELDS_INSPECTION_INFO.map(
182 ({ field }) => 187 ({ field }) =>
183 (inspectFieldValues[field] = 188 (inspectFieldValues[field] =
184 inspectFieldValues[field] === 'UN_LOCKED' ? 'UN_LOCKED' : 'LOCKED'), 189 inspectFieldValues[field] === 'UN_LOCKED' ? 'UN_LOCKED' : 'LOCKED'),
185 ); 190 );
186 -  
187 // !isEmpty(baseFieldValues) && 191 // !isEmpty(baseFieldValues) &&
188 // Object.keys(baseFieldValues.baseFields)?.map((key) => { 192 // Object.keys(baseFieldValues.baseFields)?.map((key) => {
189 // baseFieldValues.baseFields[key] = baseFieldValues.baseFields[key] 193 // baseFieldValues.baseFields[key] = baseFieldValues.baseFields[key]
190 // ? 'UN_LOCKED' 194 // ? 'UN_LOCKED'
191 // : 'LOCKED'; 195 // : 'LOCKED';
192 // }); 196 // });
193 -  
194 // !isEmpty(profitFieldValues) && 197 // !isEmpty(profitFieldValues) &&
195 // Object.keys(profitFieldValues.profitAnalysisFields).map((key) => { 198 // Object.keys(profitFieldValues.profitAnalysisFields).map((key) => {
196 // profitFieldValues.profitAnalysisFields[key] = profitFieldValues.profitAnalysisFields[ 199 // profitFieldValues.profitAnalysisFields[key] = profitFieldValues.profitAnalysisFields[
@@ -199,14 +202,12 @@ @@ -199,14 +202,12 @@
199 // ? 'UN_LOCKED' 202 // ? 'UN_LOCKED'
200 // : 'LOCKED'; 203 // : 'LOCKED';
201 // }); 204 // });
202 -  
203 // !isEmpty(reportFieldValues) && 205 // !isEmpty(reportFieldValues) &&
204 // Object.keys(reportFieldValues.reportFields).map((key) => { 206 // Object.keys(reportFieldValues.reportFields).map((key) => {
205 // reportFieldValues.reportFields[key] = reportFieldValues.reportFields[key] 207 // reportFieldValues.reportFields[key] = reportFieldValues.reportFields[key]
206 // ? 'UN_LOCKED' 208 // ? 'UN_LOCKED'
207 // : 'LOCKED'; 209 // : 'LOCKED';
208 // }); 210 // });
209 -  
210 const values = Object.assign( 211 const values = Object.assign(
211 { orderId: id.value }, 212 { orderId: id.value },
212 { baseFields: baseFieldValues }, 213 { baseFields: baseFieldValues },
@@ -215,9 +216,25 @@ @@ -215,9 +216,25 @@
215 { trackStageFields: trackFieldValues }, 216 { trackStageFields: trackFieldValues },
216 { inspectionStageFields: inspectFieldValues }, 217 { inspectionStageFields: inspectFieldValues },
217 ); 218 );
218 - await orderAuth(values);  
219 - closeDrawer(); 219 +
  220 + if (
  221 + values.baseFields.projectNo == 'UN_LOCKED' ||
  222 + values.baseFields.productionDepartment == 'UN_LOCKED' ||
  223 + values.baseFields.innerNo == 'UN_LOCKED' ||
  224 + values.baseFields.customerCode == 'UN_LOCKED' ||
  225 + values.baseFields.customerPo == 'UN_LOCKED' ||
  226 + values.baseFields.customerStyle == 'UN_LOCKED'
  227 + ) {
  228 + openReasonModal(true, {
  229 + data: values,
  230 + });
  231 + } else {
  232 + values.applyRemark = '';
  233 + await orderAuth(values);
  234 + closeDrawer();
  235 + }
220 }; 236 };
  237 +
221 return { 238 return {
222 register, 239 register,
223 schemas, 240 schemas,
@@ -227,9 +244,17 @@ @@ -227,9 +244,17 @@
227 registryInspectForm, 244 registryInspectForm,
228 registerTrackForm, 245 registerTrackForm,
229 handleSubmit, 246 handleSubmit,
  247 + handleCloseModal,
  248 + approveReasonModalRegister,
230 ROLE, 249 ROLE,
231 role, 250 role,
232 }; 251 };
233 }, 252 },
234 }); 253 });
235 </script> 254 </script>
  255 +<style>
  256 + .container {
  257 + position: fixed; /* 或 absolute, fixed */
  258 + z-index: 10;
  259 + }
  260 +</style>
src/views/project/order/ExportModal.vue
@@ -84,6 +84,15 @@ @@ -84,6 +84,15 @@
84 { label: '质检信息', value: 'inspectionStageFields' }, 84 { label: '质检信息', value: 'inspectionStageFields' },
85 ]; 85 ];
86 } 86 }
  87 + if (props.role === ROLE.FINANCE) {
  88 + return [
  89 + { label: '基本信息', value: 'baseFields' },
  90 + { label: '项目报告', value: 'reportFields' },
  91 + { label: '利润分析', value: 'profitAnalysisFields' },
  92 + { label: '跟单信息', value: 'trackStageFields' },
  93 + { label: '质检信息', value: 'inspectionStageFields' },
  94 + ];
  95 + }
87 if (props.role === ROLE.TRACKER) { 96 if (props.role === ROLE.TRACKER) {
88 return [ 97 return [
89 { label: '基本信息', value: 'baseFields' }, 98 { label: '基本信息', value: 'baseFields' },
src/views/project/order/FormDetail/ApproveReason.vue 0 → 100644
  1 +<template>
  2 + <BasicModal
  3 + v-bind="$attrs"
  4 + destroyOnClose
  5 + @register="register"
  6 + title="申请原因"
  7 + :helpMessage="['提示1', '提示2']"
  8 + @open-change="handleShow"
  9 + :bodyStyle="{ height: '200px' }"
  10 + @ok="handleOk"
  11 + z-index="9999"
  12 + >
  13 + <a-textarea v-model:value="input" :rows="7" />
  14 + </BasicModal>
  15 +</template>
  16 +<script lang="ts" setup>
  17 + import { ref, watch } from 'vue';
  18 + import { BasicModal, useModalInner } from '@/components/Modal';
  19 + import { orderAuth } from '/@/api/project/order';
  20 +
  21 + const emit = defineEmits(['success']);
  22 + const input = ref('');
  23 + const res = ref();
  24 + const [register, { setModalProps, redoModalHeight, closeModal }] = useModalInner(async (data) => {
  25 + console.log(data, '5656approvedata');
  26 + res.value = data;
  27 + });
  28 + async function handleOk() {
  29 + res.value.data.applyRemark = input.value;
  30 + await orderAuth(res.value.data);
  31 + emit('success');
  32 + setTimeout(() => {
  33 + closeModal();
  34 + }, 50);
  35 + }
  36 + function handleShow() {
  37 + closeModal();
  38 + }
  39 +</script>
src/views/project/order/FormDetail/BaseFormPanel.vue
@@ -202,34 +202,34 @@ @@ -202,34 +202,34 @@
202 label: '产品意见', 202 label: '产品意见',
203 }; 203 };
204 } 204 }
205 - if (item.field === 'returnOrder') {  
206 - return {  
207 - field: 'returnOrder',  
208 - component: 'Select',  
209 - rules: [{ required: true }],  
210 - componentProps: {  
211 - options: [  
212 - {  
213 - label: '是',  
214 - value: '1',  
215 - },  
216 - {  
217 - label: '否',  
218 - value: '0',  
219 - },  
220 - ],  
221 - disabled: getBaseDisable(  
222 - item.field,  
223 - get(fields.value, `${item.field}`),  
224 - props.id,  
225 - role.value,  
226 - ),  
227 - },  
228 - labelWidth: 600,  
229 - // default: '请选择',  
230 - label: '是否返单 ',  
231 - };  
232 - } 205 + // if (item.field === 'returnOrder') {
  206 + // return {
  207 + // field: 'returnOrder',
  208 + // component: 'Select',
  209 + // rules: [{ required: true }],
  210 + // componentProps: {
  211 + // options: [
  212 + // {
  213 + // label: '是',
  214 + // value: '1',
  215 + // },
  216 + // {
  217 + // label: '否',
  218 + // value: '0',
  219 + // },
  220 + // ],
  221 + // disabled: getBaseDisable(
  222 + // item.field,
  223 + // get(fields.value, `${item.field}`),
  224 + // props.id,
  225 + // role.value,
  226 + // ),
  227 + // },
  228 + // labelWidth: 600,
  229 + // // default: '请选择',
  230 + // label: '是否返单 ',
  231 + // };
  232 + // }
233 // const businessNotDisabledFields = ['customerCode', 'projectNo', 'innerNo']; 233 // const businessNotDisabledFields = ['customerCode', 'projectNo', 'innerNo'];
234 // const trackerNotDisabledFields = [ 234 // const trackerNotDisabledFields = [
235 // 'customerPo', 235 // 'customerPo',
@@ -254,7 +254,9 @@ @@ -254,7 +254,9 @@
254 field: `${item.field}`, 254 field: `${item.field}`,
255 componentProps: { 255 componentProps: {
256 ...(item.component === 'Select' && { showSearch: true }), 256 ...(item.component === 'Select' && { showSearch: true }),
257 - ...(item.component === 'Select' && { options: options[item.field] }), 257 + ...(item.component === 'Select' && {
  258 + options: options[item.field] || item?.componentProps?.options,
  259 + }),
258 // disabled: 260 // disabled:
259 // role.value === ROLE.BUSINESS 261 // role.value === ROLE.BUSINESS
260 // ? !isFieldNotDisabledForBusiness 262 // ? !isFieldNotDisabledForBusiness
src/views/project/order/ProductProfit.vue
@@ -121,6 +121,7 @@ @@ -121,6 +121,7 @@
121 import { payDate, checkCreate } from '@/api/project/invoice'; 121 import { payDate, checkCreate } from '@/api/project/invoice';
122 import type { Dayjs } from 'dayjs'; 122 import type { Dayjs } from 'dayjs';
123 import { calculateInnerProfitRatio, exportInnerProfitRatio } from '@/api/project/order'; 123 import { calculateInnerProfitRatio, exportInnerProfitRatio } from '@/api/project/order';
  124 + import axios from 'axios';
124 125
125 const Input1 = ref(''); 126 const Input1 = ref('');
126 const Input2 = ref(); 127 const Input2 = ref();
@@ -153,6 +154,50 @@ @@ -153,6 +154,50 @@
153 filteredItems.value = data.filteredItems; 154 filteredItems.value = data.filteredItems;
154 }); 155 });
155 async function handleOk() { 156 async function handleOk() {
  157 + axios
  158 + .post(
  159 + '/basic-api/order/erp/calculate_profit/inner_profit_ratio_export',
  160 + {
  161 + customerCode: customerCode.value,
  162 + projectNo: projectNo.value,
  163 + projectStartTime: projectStartTime.value,
  164 + projectEndTime: projectEndTime.value,
  165 + productionDepartmentPredictPrice: productionDepartmentPredictPrice.value,
  166 + productionActualPrice: productionActualPrice.value,
  167 + },
  168 + {
  169 + responseType: 'blob', // 设置响应类型为 'blob'
  170 + },
  171 + )
  172 + .then((response) => {
  173 + // 创建一个 Blob 对象来保存二进制数据
  174 + const blob = new Blob([response.data], { type: 'application/octet-stream' });
  175 + const getFormattedDate = (): string => {
  176 + const date = new Date();
  177 +
  178 + const year = date.getFullYear();
  179 + const month = String(date.getMonth() + 1).padStart(2, '0');
  180 + const day = String(date.getDate()).padStart(2, '0');
  181 +
  182 + const hours = String(date.getHours()).padStart(2, '0');
  183 + const minutes = String(date.getMinutes()).padStart(2, '0');
  184 + const seconds = String(date.getSeconds()).padStart(2, '0');
  185 +
  186 + return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
  187 + };
  188 + const date = getFormattedDate();
  189 + // 创建一个链接元素用于下载
  190 + const link = document.createElement('a');
  191 + link.href = window.URL.createObjectURL(blob);
  192 + link.download = `内部生产净利润分析${date}.pdf`; // 你可以为文件命名
  193 + document.body.appendChild(link);
  194 + link.click(); // 自动点击链接,触发下载
  195 + console.log(link, 5656);
  196 + document.body.removeChild(link); // 下载完成后移除链接
  197 + })
  198 + .catch((error) => {
  199 + console.error(error);
  200 + });
156 closeModal(); 201 closeModal();
157 } 202 }
158 function handleShow(visible: boolean) { 203 function handleShow(visible: boolean) {
src/views/project/order/ProductText.vue
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 v-bind="$attrs" 3 v-bind="$attrs"
4 destroyOnClose 4 destroyOnClose
5 @register="register" 5 @register="register"
6 - title="生产指书" 6 + title="生产指书"
7 width="500px" 7 width="500px"
8 :height="80" 8 :height="80"
9 wrapClassName="h-[340px]" 9 wrapClassName="h-[340px]"
@@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
14 v-bind="$attrs" 14 v-bind="$attrs"
15 destroyOnClose 15 destroyOnClose
16 @register="register" 16 @register="register"
17 - title="生产指书" 17 + title="生产指书"
18 width="500px" 18 width="500px"
19 @visible-change="handleShow" 19 @visible-change="handleShow"
20 :footer="null" 20 :footer="null"
@@ -27,7 +27,7 @@ @@ -27,7 +27,7 @@
27 <div class="showPdf" v-if="isShow2 == true" style="margin-top: 35px; text-align: center"> 27 <div class="showPdf" v-if="isShow2 == true" style="margin-top: 35px; text-align: center">
28 <!-- <img src="/pdf.png" /> --> 28 <!-- <img src="/pdf.png" /> -->
29 <FilePptOutlined :style="{ fontSize: '20px' }" class="FilePptOutlined" /> 29 <FilePptOutlined :style="{ fontSize: '20px' }" class="FilePptOutlined" />
30 - <div style="margin-top: 1px; margin-left: 10px">生产指书</div> 30 + <div style="margin-top: 1px; margin-left: 10px">生产指书</div>
31 <EyeOutlined :style="{ fontSize: '20px' }" class="EyeOutlined" @click="handlePdf" /> 31 <EyeOutlined :style="{ fontSize: '20px' }" class="EyeOutlined" @click="handlePdf" />
32 </div> 32 </div>
33 <div class="bottom"> 33 <div class="bottom">
@@ -83,7 +83,7 @@ @@ -83,7 +83,7 @@
83 // 运营总监-基本信息,跟单,质检 83 // 运营总监-基本信息,跟单,质检
84 return [ 84 return [
85 { label: '青岛翱特逸格饰品有限公司', value: '青岛翱特逸格饰品有限公司' }, 85 { label: '青岛翱特逸格饰品有限公司', value: '青岛翱特逸格饰品有限公司' },
86 - { label: ' 青岛吉庆天成饰品有限公司', value: '青岛吉庆天成饰品有限公司' }, 86 + { label: '青岛吉庆天成饰品有限公司', value: '青岛吉庆天成饰品有限公司' },
87 ]; 87 ];
88 }); 88 });
89 const { createMessage } = useMessage(); 89 const { createMessage } = useMessage();
@@ -173,17 +173,18 @@ @@ -173,17 +173,18 @@
173 } 173 }
174 //查看pdf 174 //查看pdf
175 function handlePdf() { 175 function handlePdf() {
176 - window.open(resText.value.produceFile); 176 + window.open(resText.value.productionUrl);
177 } 177 }
178 //发送按钮 178 //发送按钮
179 async function handleExport() { 179 async function handleExport() {
180 const res = await exportProductText({ 180 const res = await exportProductText({
181 productionUrl: resText.value.productionUrl, 181 productionUrl: resText.value.productionUrl,
182 productionDepartment: resText.value.productionDepartment, 182 productionDepartment: resText.value.productionDepartment,
  183 + personList: resText.value.personList,
183 isSend: true, 184 isSend: true,
184 }); 185 });
185 console.log(); 186 console.log();
186 - success('操作成功,' + res); 187 + success('操作成功,已发送给生产科、业务员、跟单员');
187 closeModal(); 188 closeModal();
188 } 189 }
189 return { 190 return {
src/views/project/order/ServiceProfit.vue
@@ -49,18 +49,20 @@ @@ -49,18 +49,20 @@
49 <tr> 49 <tr>
50 <td style="border: 1px solid black"></td> 50 <td style="border: 1px solid black"></td>
51 <td style="border: 1px solid black">项目开始时间</td> 51 <td style="border: 1px solid black">项目开始时间</td>
52 - <td style="border: 1px solid black"  
53 - ><a-date-picker v-model:value="projectStartTime"  
54 - /></td>  
55 - <td style="border: 1px solid black"><a-date-picker v-model:value="projectEndTime" /></td> 52 + <td style="border: 1px solid black">
  53 + <input type="date" v-model="projectStartTime" style="width: 100%" />
  54 + </td>
  55 + <input type="date" v-model="projectEndTime" style="width: 100%" />
56 </tr> 56 </tr>
57 <tr> 57 <tr>
58 <td style="border: 1px solid black"></td> 58 <td style="border: 1px solid black"></td>
59 <td style="border: 1px solid black">生产进行时间</td> 59 <td style="border: 1px solid black">生产进行时间</td>
60 - <td style="border: 1px solid black"  
61 - ><a-date-picker v-model:value="produceStartTime" 60 + <td style="border: 1px solid black">
  61 + <input type="date" v-model="produceStartTime" style="width: 100%" />
  62 + </td>
  63 + <td style="border: 1px solid black">
  64 + <input type="date" v-model="produceEndTime" style="width: 100%"
62 /></td> 65 /></td>
63 - <td style="border: 1px solid black"><a-date-picker v-model:value="produceEndTime" /></td>  
64 </tr> 66 </tr>
65 <tr> 67 <tr>
66 <td style="border: 1px solid black">客户编码</td> 68 <td style="border: 1px solid black">客户编码</td>
@@ -70,17 +72,17 @@ @@ -70,17 +72,17 @@
70 </tr> 72 </tr>
71 <tr> 73 <tr>
72 <td style="border: 1px solid black" colspan="2">客户总金额合计</td> 74 <td style="border: 1px solid black" colspan="2">客户总金额合计</td>
73 - <td style="border: 1px solid black"></td> 75 + <td style="border: 1px solid black">{{ customerTotalPrice }}</td>
74 <td style="border: 1px solid black"></td> 76 <td style="border: 1px solid black"></td>
75 </tr> 77 </tr>
76 <tr> 78 <tr>
77 <td style="border: 1px solid black" colspan="2">生产科总价合计</td> 79 <td style="border: 1px solid black" colspan="2">生产科总价合计</td>
78 - <td style="border: 1px solid black"></td> 80 + <td style="border: 1px solid black">{{ productionDepartmentTotalPrice }}</td>
79 <td style="border: 1px solid black"></td> 81 <td style="border: 1px solid black"></td>
80 </tr> 82 </tr>
81 <tr> 83 <tr>
82 <td style="border: 1px solid black" colspan="2">包装费用合计</td> 84 <td style="border: 1px solid black" colspan="2">包装费用合计</td>
83 - <td style="border: 1px solid black"></td> 85 + <td style="border: 1px solid black">{{ packetTotalPrice }}</td>
84 <td style="border: 1px solid black"></td> 86 <td style="border: 1px solid black"></td>
85 </tr> 87 </tr>
86 <tr> 88 <tr>
@@ -99,37 +101,37 @@ @@ -99,37 +101,37 @@
99 </tr> 101 </tr>
100 <tr> 102 <tr>
101 <td style="border: 1px solid black" colspan="2">固定成本</td> 103 <td style="border: 1px solid black" colspan="2">固定成本</td>
102 - <td style="border: 1px solid black"></td> 104 + <td style="border: 1px solid black">{{ fixCost }}</td>
103 <td style="border: 1px solid black"></td> 105 <td style="border: 1px solid black"></td>
104 </tr> 106 </tr>
105 <tr> 107 <tr>
106 <td style="border: 1px solid black" colspan="2">西班牙提成</td> 108 <td style="border: 1px solid black" colspan="2">西班牙提成</td>
107 - <td style="border: 1px solid black"></td> 109 + <td style="border: 1px solid black">{{ spainRatioProfitPrice }}</td>
108 <td style="border: 1px solid black"></td> 110 <td style="border: 1px solid black"></td>
109 </tr> 111 </tr>
110 <tr> 112 <tr>
111 <td style="border: 1px solid black" colspan="2">中国团队提成</td> 113 <td style="border: 1px solid black" colspan="2">中国团队提成</td>
112 - <td style="border: 1px solid black"></td> 114 + <td style="border: 1px solid black">{{ chinaRatioProfitPrice }}</td>
113 <td style="border: 1px solid black"></td> 115 <td style="border: 1px solid black"></td>
114 </tr> 116 </tr>
115 <tr> 117 <tr>
116 <td style="border: 1px solid black" colspan="2">支出合计</td> 118 <td style="border: 1px solid black" colspan="2">支出合计</td>
117 - <td style="border: 1px solid black"></td> 119 + <td style="border: 1px solid black">{{ outTotalPrice }}</td>
118 <td style="border: 1px solid black"></td> 120 <td style="border: 1px solid black"></td>
119 </tr> 121 </tr>
120 <tr> 122 <tr>
121 <td style="border: 1px solid black" colspan="2">毛利润</td> 123 <td style="border: 1px solid black" colspan="2">毛利润</td>
122 - <td style="border: 1px solid black"></td> 124 + <td style="border: 1px solid black">{{ grossProfit }}</td>
123 <td style="border: 1px solid black"></td> 125 <td style="border: 1px solid black"></td>
124 </tr> 126 </tr>
125 <tr> 127 <tr>
126 <td style="border: 1px solid black" colspan="2">研发贸易净利润</td> 128 <td style="border: 1px solid black" colspan="2">研发贸易净利润</td>
127 - <td style="border: 1px solid black"></td> 129 + <td style="border: 1px solid black">{{ developProfit }}</td>
128 <td style="border: 1px solid black"></td> 130 <td style="border: 1px solid black"></td>
129 </tr> 131 </tr>
130 <tr> 132 <tr>
131 <td style="border: 1px solid black" colspan="2">包装费用合计金额</td> 133 <td style="border: 1px solid black" colspan="2">包装费用合计金额</td>
132 - <td style="border: 1px solid black"></td> 134 + <td style="border: 1px solid black">{{ packetTotalPrice }}</td>
133 <td style="border: 1px solid black"></td> 135 <td style="border: 1px solid black"></td>
134 </tr> 136 </tr>
135 <tr> 137 <tr>
@@ -141,32 +143,32 @@ @@ -141,32 +143,32 @@
141 </tr> 143 </tr>
142 <tr> 144 <tr>
143 <td style="border: 1px solid black" colspan="2">订单总数量</td> 145 <td style="border: 1px solid black" colspan="2">订单总数量</td>
144 - <td style="border: 1px solid black"></td> 146 + <td style="border: 1px solid black">{{ orderCount }}</td>
145 <td style="border: 1px solid black"></td> 147 <td style="border: 1px solid black"></td>
146 </tr> 148 </tr>
147 <tr> 149 <tr>
148 <td style="border: 1px solid black" colspan="2">实际跟单单价=实际跟单费用/件数</td> 150 <td style="border: 1px solid black" colspan="2">实际跟单单价=实际跟单费用/件数</td>
149 - <td style="border: 1px solid black"></td> 151 + <td style="border: 1px solid black">{{ actualRmbPrice }}</td>
150 <td style="border: 1px solid black"></td> 152 <td style="border: 1px solid black"></td>
151 </tr> 153 </tr>
152 <tr> 154 <tr>
153 <td style="border: 1px solid black" colspan="2">实际跟单单价折算美金</td> 155 <td style="border: 1px solid black" colspan="2">实际跟单单价折算美金</td>
154 - <td style="border: 1px solid black"></td> 156 + <td style="border: 1px solid black">{{ actualPrice }}</td>
155 <td style="border: 1px solid black"></td> 157 <td style="border: 1px solid black"></td>
156 </tr> 158 </tr>
157 <tr> 159 <tr>
158 <td style="border: 1px solid black" colspan="2">包装费用收益</td> 160 <td style="border: 1px solid black" colspan="2">包装费用收益</td>
159 - <td style="border: 1px solid black"></td> 161 + <td style="border: 1px solid black">{{ packetProfitPrice }}</td>
160 <td style="border: 1px solid black"></td> 162 <td style="border: 1px solid black"></td>
161 </tr> 163 </tr>
162 <tr> 164 <tr>
163 <td style="border: 1px solid black" colspan="2">汇率收益</td> 165 <td style="border: 1px solid black" colspan="2">汇率收益</td>
164 - <td style="border: 1px solid black"></td> 166 + <td style="border: 1px solid black">{{ actualRatioProfitPrice }}</td>
165 <td style="border: 1px solid black"></td> 167 <td style="border: 1px solid black"></td>
166 </tr> 168 </tr>
167 <tr> 169 <tr>
168 <td style="border: 1px solid black" colspan="2">综合收益</td> 170 <td style="border: 1px solid black" colspan="2">综合收益</td>
169 - <td style="border: 1px solid black"></td> 171 + <td style="border: 1px solid black">{{ totalProfitPrice }}</td>
170 <td style="border: 1px solid black"></td> 172 <td style="border: 1px solid black"></td>
171 </tr> 173 </tr>
172 </tbody> 174 </tbody>
@@ -178,7 +180,9 @@ @@ -178,7 +180,9 @@
178 import { computed, ref, toRaw } from 'vue'; 180 import { computed, ref, toRaw } from 'vue';
179 // import { payDate, checkCreate } from '@/api/project/invoice'; 181 // import { payDate, checkCreate } from '@/api/project/invoice';
180 import { calculateBusinessProfit, exportBusinessProfit } from '@/api/project/order'; 182 import { calculateBusinessProfit, exportBusinessProfit } from '@/api/project/order';
  183 + import { getList } from '/@/api/sys/config';
181 import type { Dayjs } from 'dayjs'; 184 import type { Dayjs } from 'dayjs';
  185 + import axios from 'axios';
182 186
183 const projectStartTime = ref(); 187 const projectStartTime = ref();
184 const projectEndTime = ref(); 188 const projectEndTime = ref();
@@ -195,11 +199,14 @@ @@ -195,11 +199,14 @@
195 const developTotalPrice = ref(); 199 const developTotalPrice = ref();
196 const copyTotalPrice = ref(); 200 const copyTotalPrice = ref();
197 const packetActualTotalPrice = ref(); 201 const packetActualTotalPrice = ref();
198 - const spainRatio = ref();  
199 - const chinaRatio = ref(); 202 + const spainRatio = ref(0);
  203 + const chinaRatio = ref(0);
200 const actualRmbPrice = ref(0); //实际跟单单价 204 const actualRmbPrice = ref(0); //实际跟单单价
201 const actualPrice = ref(0); //实际跟单单价折算美金 205 const actualPrice = ref(0); //实际跟单单价折算美金
202 const actualRatio = ref(6.2); //实际汇率 206 const actualRatio = ref(6.2); //实际汇率
  207 + const customerTotalPrice = ref(); //客户总价合计
  208 + const actualRatioProfitPrice = ref(); //汇率收益
  209 + const grossProfit = ref(); //毛利润合计
203 const actualRatiactualRatioProfitPriceo = ref(); //汇率收益计算 210 const actualRatiactualRatioProfitPriceo = ref(); //汇率收益计算
204 const chinaRatioProfitPrice = ref(); //中国团队提成比例 211 const chinaRatioProfitPrice = ref(); //中国团队提成比例
205 const developProfit = ref(); //研发贸易利润 212 const developProfit = ref(); //研发贸易利润
@@ -222,6 +229,58 @@ @@ -222,6 +229,58 @@
222 console.log(orderList.value, 565656); 229 console.log(orderList.value, 565656);
223 }); 230 });
224 async function handleOk() { 231 async function handleOk() {
  232 + axios
  233 + .post(
  234 + '/basic-api/order/erp/calculate_profit/business_profit_ratio_export',
  235 + {
  236 + customerCode: customerCode.value,
  237 + projectNo: projectNo.value,
  238 + projectStartTime: projectStartTime.value,
  239 + projectEndTime: projectEndTime.value,
  240 + produceStartTime: produceStartTime.value,
  241 + produceEndTime: produceEndTime.value,
  242 + developTotalPrice: developTotalPrice.value,
  243 + copyTotalPrice: copyTotalPrice.value,
  244 + spainRatio: spainRatio.value,
  245 + chinaRatio: chinaRatio.value,
  246 + packetActualTotalPrice: packetActualTotalPrice.value,
  247 + actualRmbPrice: actualRmbPrice.value,
  248 + actualPrice: actualPrice.value,
  249 + actualRatio: actualRatio.value,
  250 + },
  251 + {
  252 + responseType: 'blob', // 设置响应类型为 'blob'
  253 + },
  254 + )
  255 + .then((response) => {
  256 + // 创建一个 Blob 对象来保存二进制数据
  257 + const blob = new Blob([response.data], { type: 'application/octet-stream' });
  258 + const getFormattedDate = (): string => {
  259 + const date = new Date();
  260 +
  261 + const year = date.getFullYear();
  262 + const month = String(date.getMonth() + 1).padStart(2, '0');
  263 + const day = String(date.getDate()).padStart(2, '0');
  264 +
  265 + const hours = String(date.getHours()).padStart(2, '0');
  266 + const minutes = String(date.getMinutes()).padStart(2, '0');
  267 + const seconds = String(date.getSeconds()).padStart(2, '0');
  268 +
  269 + return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
  270 + };
  271 + const date = getFormattedDate();
  272 + // 创建一个链接元素用于下载
  273 + const link = document.createElement('a');
  274 + link.href = window.URL.createObjectURL(blob);
  275 + link.download = `业务/研发净利润分析${date}.pdf`; // 你可以为文件命名
  276 + document.body.appendChild(link);
  277 + link.click(); // 自动点击链接,触发下载
  278 + console.log(link, 5656);
  279 + document.body.removeChild(link); // 下载完成后移除链接
  280 + })
  281 + .catch((error) => {
  282 + console.error(error);
  283 + });
225 closeModal(); 284 closeModal();
226 } 285 }
227 function handleShow(visible: boolean) { 286 function handleShow(visible: boolean) {
@@ -237,6 +296,25 @@ @@ -237,6 +296,25 @@
237 packetActualTotalPrice.value = null; 296 packetActualTotalPrice.value = null;
238 } 297 }
239 } 298 }
  299 + //提成接口
  300 + interface RatioListItem {
  301 + createBy: string;
  302 + createTime: string;
  303 + enableFlag: number;
  304 + id: number;
  305 + modifyBy: string;
  306 + modifyTime: string;
  307 + relationCode: string;
  308 + relationName: string;
  309 + relationValue: string; // 这里 relationValue 是一个字符串,但内部是一个 JSON 数组,需要进一步解析
  310 + settingCode: string;
  311 + settingName: string;
  312 + settingType: number;
  313 + settingValue: string;
  314 + }
  315 + interface RatioList {
  316 + items: RatioListItem[];
  317 + }
240 async function handleCalculate() { 318 async function handleCalculate() {
241 const packetCalculatePrice = ref(0); 319 const packetCalculatePrice = ref(0);
242 const orderCalculateCount = ref(0); 320 const orderCalculateCount = ref(0);
@@ -250,8 +328,32 @@ @@ -250,8 +328,32 @@
250 actualRmbPrice.value += packetCalculatePrice.value / orderCalculateCount.value; 328 actualRmbPrice.value += packetCalculatePrice.value / orderCalculateCount.value;
251 }); 329 });
252 actualPrice.value = actualRmbPrice.value / actualRatio.value; 330 actualPrice.value = actualRmbPrice.value / actualRatio.value;
253 - console.log(actualPrice.value, '5656actualPrice');  
254 - 331 + // const ratioList = (await getList({ settingType: 3 })) as Array<RatioListItem>;
  332 + const ratioList = (await getList({ settingType: 3 })) as RatioList;
  333 + const ratios = ratioList.items.filter((item) => item.settingValue === customerCode.value);
  334 + console.log(ratios, '5656ratios');
  335 + const ratioAll = JSON.parse(ratios[0].relationValue);
  336 + console.log(ratioAll, '5656ratios', ratioAll[1].relationValue, ratioAll[2].relationValue);
  337 + chinaRatio.value = ratioAll[1].relationValue;
  338 + spainRatio.value = ratioAll[2].relationValue;
  339 + //提成比例为0,提成设为0
  340 + const params = {
  341 + customerCode: customerCode.value,
  342 + projectNo: projectNo.value,
  343 + projectStartTime: projectStartTime.value,
  344 + projectEndTime: projectEndTime.value,
  345 + produceStartTime: produceStartTime.value,
  346 + produceEndTime: produceEndTime.value,
  347 + developTotalPrice: developTotalPrice.value,
  348 + copyTotalPrice: copyTotalPrice.value,
  349 + spainRatio: spainRatio.value,
  350 + chinaRatio: chinaRatio.value,
  351 + packetActualTotalPrice: packetActualTotalPrice.value,
  352 + actualRmbPrice: actualRmbPrice.value,
  353 + actualPrice: actualPrice.value,
  354 + actualRatio: actualRatio.value,
  355 + };
  356 + console.log(params, '5656params');
255 const res = await calculateBusinessProfit({ 357 const res = await calculateBusinessProfit({
256 customerCode: customerCode.value, 358 customerCode: customerCode.value,
257 projectNo: projectNo.value, 359 projectNo: projectNo.value,
@@ -270,20 +372,23 @@ @@ -270,20 +372,23 @@
270 }); 372 });
271 console.log(res, '5656resservice'); 373 console.log(res, '5656resservice');
272 374
273 - actualRmbPrice.value = res.data.actualRmbPrice;  
274 - actualPrice.value = res.data.actualPrice;  
275 - actualRatio.value = res.data.actualRatio;  
276 - actualRatiactualRatioProfitPriceo.value = res.data.actualRatioProfitPrice; //汇率收益计算  
277 - chinaRatioProfitPrice.value = res.data.chinaRatioProfitPrice; //中国团队提成比例  
278 - developProfit.value = res.data.developProfit; //研发贸易利润  
279 - fixCost.value = res.data.fixCost; // 固定成本  
280 - orderCount.value = res.data.orderCount; //订单总数量  
281 - outTotalPrice.value = res.data.outTotalPrice; //支出合计  
282 - packetProfitPrice.value = res.data.packetProfitPrice; //包装费用收益计算  
283 - packetTotalPrice.value = res.data.packetTotalPrice; //包装费用合计  
284 - productionDepartmentTotalPrice.value = res.data.productionDepartmentTotalPrice; //生成科总价  
285 - totalProfitPrice.value = res.data.totalProfitPrice; //综合收益计算  
286 - spainRatioProfitPrice.value = res.data.spainRatioProfitPrice; //西班牙提成金额 375 + customerTotalPrice.value = res.customerTotalPrice;
  376 + grossProfit.value = res.grossProfit;
  377 + actualRatioProfitPrice.value = res.actualRatioProfitPrice;
  378 + actualRmbPrice.value = res.actualRmbPrice;
  379 + actualPrice.value = res.actualPrice;
  380 + actualRatio.value = res.actualRatio;
  381 + actualRatiactualRatioProfitPriceo.value = res.actualRatioProfitPrice; //汇率收益计算
  382 + chinaRatioProfitPrice.value = res.chinaRatioProfitPrice; //中国团队提成比例
  383 + developProfit.value = res.developProfit; //研发贸易利润
  384 + fixCost.value = res.fixCost; // 固定成本
  385 + orderCount.value = res.orderCount; //订单总数量
  386 + outTotalPrice.value = res.outTotalPrice; //支出合计
  387 + packetProfitPrice.value = res.packetProfitPrice; //包装费用收益计算
  388 + packetTotalPrice.value = res.packetTotalPrice; //包装费用合计
  389 + productionDepartmentTotalPrice.value = res.productionDepartmentTotalPrice; //生成科总价
  390 + totalProfitPrice.value = res.totalProfitPrice; //综合收益计算
  391 + spainRatioProfitPrice.value = res.spainRatioProfitPrice; //西班牙提成金额
287 } 392 }
288 </script> 393 </script>
289 <style scoped> 394 <style scoped>
src/views/project/order/index.vue
@@ -23,7 +23,7 @@ @@ -23,7 +23,7 @@
23 <a-button 23 <a-button
24 :style="{ borderRadius: '5px 5px 5px 5px' }" 24 :style="{ borderRadius: '5px 5px 5px 5px' }"
25 type="link" 25 type="link"
26 - @click="checkedKeys = []" 26 + @click="handleClearChoose"
27 size="small" 27 size="small"
28 >清空</a-button 28 >清空</a-button
29 > 29 >
@@ -38,7 +38,7 @@ @@ -38,7 +38,7 @@
38 <template v-if="column.key === 'action'"> 38 <template v-if="column.key === 'action'">
39 <TableAction 39 <TableAction
40 :actions=" 40 :actions="
41 - role !== ROLE.PRODUCE 41 + role !== ROLE.PRODUCE && role !== ROLE.FINANCE
42 ? [ 42 ? [
43 { 43 {
44 // 数据分析没有编辑权限 44 // 数据分析没有编辑权限
@@ -78,7 +78,9 @@ @@ -78,7 +78,9 @@
78 }, 78 },
79 { 79 {
80 // 数据分析没有编辑权限 80 // 数据分析没有编辑权限
81 - ...((role === ROLE.ADMIN || role === ROLE.TRACKER) && { 81 + ...((role === ROLE.ADMIN ||
  82 + role === ROLE.TRACKER ||
  83 + role === ROLE.FINANCE) && {
82 label: '复制', 84 label: '复制',
83 // icon: 'ic:outline-delete-outline', 85 // icon: 'ic:outline-delete-outline',
84 onClick: handleCopy.bind(null, record), 86 onClick: handleCopy.bind(null, record),
@@ -111,93 +113,100 @@ @@ -111,93 +113,100 @@
111 </template> 113 </template>
112 114
113 <template #toolbar> 115 <template #toolbar>
114 - <div style="width: 1050px; padding-left: 50px">  
115 - <!-- <a-space wrap :size="[8, 16]" :style="{ marginBottom: '2px', marginLeft: '10px' }"> -->  
116 - <a-space wrap :style="{ marginBottom: '2px', marginTop: '2px' }">  
117 - <a-button  
118 - :style="{ borderRadius: '5px 5px 5px 5px' }"  
119 - type="primary"  
120 - @click="handleProductInvoiceModal"  
121 - v-if="role === ROLE.ADMIN || role === ROLE.BUSINESS || role === ROLE.TRACKER"  
122 - >生产对账单创建</a-button  
123 - >  
124 - <a-button  
125 - :style="{ borderRadius: '5px 5px 5px 5px' }"  
126 - shape="default"  
127 - type="primary"  
128 - @click="handleInvoiceCreateModal"  
129 - v-if="role === ROLE.ADMIN || role === ROLE.BUSINESS || role === ROLE.TRACKER"  
130 - >Invoice创建</a-button  
131 - >  
132 - <a-select  
133 - ref="select"  
134 - v-model:value="value1"  
135 - @change="handleChange"  
136 - class="passCalculate"  
137 - dropdown-class-name="dropdown-class"  
138 - v-if="role === ROLE.ADMIN || role === ROLE.TRACKER || role === ROLE.BUSINESS"  
139 - >  
140 - <a-select-option value1="一次通过率">一次通过率</a-select-option>  
141 - <a-select-option value="确认样品" @click="handlePassModal('确认意见')"  
142 - >确认样品</a-select-option 116 + <div style="position: relative">
  117 + <div style="padding-left: 50px; right: 123px">
  118 + <!-- <a-space wrap :size="[8, 16]" :style="{ marginBottom: '2px', marginLeft: '10px' }"> -->
  119 + <a-space wrap :style="{ marginBottom: '2px', marginTop: '2px' }">
  120 + <a-button
  121 + :style="{ borderRadius: '5px 5px 5px 5px' }"
  122 + type="primary"
  123 + @click="handleProductInvoiceModal"
  124 + v-if="role === ROLE.ADMIN || role === ROLE.BUSINESS || role === ROLE.TRACKER"
  125 + >生产对账单创建</a-button
143 > 126 >
144 - <a-select-option value="生产样品" @click="handlePassModal('生产样品')"  
145 - >生产样品</a-select-option 127 + <a-button
  128 + :style="{ borderRadius: '5px 5px 5px 5px' }"
  129 + shape="default"
  130 + type="primary"
  131 + @click="handleInvoiceCreateModal"
  132 + v-if="role === ROLE.ADMIN || role === ROLE.BUSINESS || role === ROLE.TRACKER"
  133 + >Invoice创建</a-button
146 > 134 >
147 - <a-select-option value="测试样品" @click="handlePassModal('测试样品')"  
148 - >测试样品</a-select-option 135 + <a-select
  136 + ref="select"
  137 + v-model:value="value1"
  138 + @change="handleChange"
  139 + class="passCalculate"
  140 + dropdown-class-name="dropdown-class"
  141 + v-if="role === ROLE.ADMIN || role === ROLE.TRACKER || role === ROLE.BUSINESS"
149 > 142 >
150 - </a-select>  
151 - <a-button  
152 - :style="{ borderRadius: '5px 5px 5px 5px' }"  
153 - type="primary"  
154 - @click="handleProductProfitModal"  
155 - >内部生产净利润分析</a-button  
156 - >  
157 - <a-button  
158 - :style="{ borderRadius: '5px 5px 5px 5px' }"  
159 - type="primary"  
160 - @click="handleServiceProfitModal"  
161 - >业务/研发净利润分析</a-button  
162 - >  
163 - <a-button  
164 - :style="{ borderRadius: '5px 5px 5px 5px' }"  
165 - type="primary"  
166 - @click="handleProductModal"  
167 - v-if="role === ROLE.ADMIN || role === ROLE.TRACKER"  
168 - >生产指标书</a-button  
169 - >  
170 - <a-button  
171 - :style="{ borderRadius: '5px 5px 5px 5px' }"  
172 - type="primary"  
173 - @click="handleRateModal"  
174 - v-if="role === ROLE.ADMIN"  
175 - >比重计算</a-button  
176 - >  
177 - <!-- 质检角色不能导出任何信息 -->  
178 - <a-button  
179 - :style="{ borderRadius: '5px 5px 5px 5px' }"  
180 - type="primary"  
181 - @click="handleExportModal"  
182 - v-if="role === ROLE.ADMIN || role === ROLE.TRACKER || role === ROLE.BUSINESS"  
183 - >导出</a-button  
184 - >  
185 - <a-button  
186 - :style="{ borderRadius: '5px 5px 5px 5px' }"  
187 - type="primary"  
188 - @click="handleProfitModal"  
189 - v-if="role === ROLE.ADMIN || role === ROLE.BUSINESS"  
190 - >分析利润</a-button 143 + <a-select-option value1="一次通过率">一次通过率</a-select-option>
  144 + <a-select-option value="确认样品" @click="handlePassModal('确认意见')"
  145 + >确认样品</a-select-option
  146 + >
  147 + <a-select-option value="生产样品" @click="handlePassModal('生产样品')"
  148 + >生产样品</a-select-option
  149 + >
  150 + <a-select-option value="测试样品" @click="handlePassModal('测试样品')"
  151 + >测试样品</a-select-option
  152 + >
  153 + </a-select>
  154 + <a-button
  155 + :style="{ borderRadius: '5px 5px 5px 5px' }"
  156 + type="primary"
  157 + @click="handleProductProfitModal"
  158 + >内部生产净利润分析</a-button
  159 + >
  160 + <a-button
  161 + :style="{ borderRadius: '5px 5px 5px 5px' }"
  162 + type="primary"
  163 + @click="handleServiceProfitModal"
  164 + >业务/研发净利润分析</a-button
  165 + >
  166 + <a-button
  167 + :style="{ borderRadius: '5px 5px 5px 5px' }"
  168 + type="primary"
  169 + @click="handleProductModal"
  170 + v-if="role === ROLE.ADMIN || role === ROLE.TRACKER"
  171 + >生产指示书</a-button
  172 + >
  173 + <a-button
  174 + :style="{ borderRadius: '5px 5px 5px 5px' }"
  175 + type="primary"
  176 + @click="handleRateModal"
  177 + v-if="role === ROLE.ADMIN"
  178 + >比重计算</a-button
  179 + >
  180 + <!-- 质检角色不能导出任何信息 -->
  181 + <a-button
  182 + :style="{ borderRadius: '5px 5px 5px 5px' }"
  183 + type="primary"
  184 + @click="handleExportModal"
  185 + v-if="
  186 + role === ROLE.ADMIN ||
  187 + role === ROLE.TRACKER ||
  188 + role === ROLE.BUSINESS ||
  189 + role === ROLE.FINANCE
  190 + "
  191 + >导出</a-button
  192 + >
  193 + <a-button
  194 + :style="{ borderRadius: '5px 5px 5px 5px' }"
  195 + type="primary"
  196 + @click="handleProfitModal"
  197 + v-if="role === ROLE.ADMIN || role === ROLE.BUSINESS"
  198 + >分析利润</a-button
  199 + >
  200 + <a-button
  201 + :style="{ borderRadius: '5px 5px 5px 5px' }"
  202 + type="primary"
  203 + @click="handleAdd"
  204 + v-if="role === ROLE.ADMIN || role === ROLE.TRACKER"
  205 + >创建订单</a-button
  206 + ></a-space
191 > 207 >
192 - <a-button  
193 - :style="{ borderRadius: '5px 5px 5px 5px' }"  
194 - type="primary"  
195 - @click="handleAdd"  
196 - v-if="role === ROLE.ADMIN || role === ROLE.TRACKER"  
197 - >创建订单</a-button  
198 - ></a-space  
199 - >  
200 - </div> 208 + </div></div
  209 + >
201 </template> 210 </template>
202 </BasicTable> 211 </BasicTable>
203 <FormDetail 212 <FormDetail
@@ -368,13 +377,20 @@ @@ -368,13 +377,20 @@
368 377
369 // type CustomerCodeEntry = [string, number]; // 定义二维数组类型 [customerCode, count] 378 // type CustomerCodeEntry = [string, number]; // 定义二维数组类型 [customerCode, count]
370 // type ProductionDepartmentEntry = [string, number]; // 定义二维数组类型 [productionDepartment, count] 379 // type ProductionDepartmentEntry = [string, number]; // 定义二维数组类型 [productionDepartment, count]
  380 + // type ProjectNoEntry = [string, number]; // 定义二维数组类型 [innerNo, count]
371 381
372 // const selectedCustomCodes = ref<CustomerCodeEntry[]>([]); // 创建一个二维数组的 ref 382 // const selectedCustomCodes = ref<CustomerCodeEntry[]>([]); // 创建一个二维数组的 ref
373 // const selectedProductionDepartment = ref<ProductionDepartmentEntry[]>([]); // 创建一个二维数组的 ref 383 // const selectedProductionDepartment = ref<ProductionDepartmentEntry[]>([]); // 创建一个二维数组的 ref
  384 + // const selectedProjectNos = ref<ProjectNoEntry[]>([]); // 创建一个二维数组的 ref
374 385
375 // // 单选处理函数 386 // // 单选处理函数
376 // function onSelect( 387 // function onSelect(
377 - // record: { customerCode: string; productionDepartment: string; id: string }, 388 + // record: {
  389 + // customerCode: string;
  390 + // productionDepartment: string;
  391 + // projectNo: string;
  392 + // id: string;
  393 + // },
378 // selected: boolean, 394 // selected: boolean,
379 // ) { 395 // ) {
380 // // 查找 customerCode 在 selectedCustomCodes 中的位置 396 // // 查找 customerCode 在 selectedCustomCodes 中的位置
@@ -387,6 +403,11 @@ @@ -387,6 +403,11 @@
387 // ([department]) => department === record.productionDepartment, 403 // ([department]) => department === record.productionDepartment,
388 // ); 404 // );
389 405
  406 + // // 查找 projectNo 在 selectedProjectNos 中的位置
  407 + // const projectNoIndex = selectedProjectNos.value.findIndex(
  408 + // ([projectNo]) => projectNo === record.projectNo,
  409 + // );
  410 +
390 // if (selected) { 411 // if (selected) {
391 // // 添加到 checkedKeys 412 // // 添加到 checkedKeys
392 // checkedKeys.value = [...checkedKeys.value, record.id]; 413 // checkedKeys.value = [...checkedKeys.value, record.id];
@@ -408,6 +429,15 @@ @@ -408,6 +429,15 @@
408 // // 如果不存在,添加新项 [productionDepartment, 1] 429 // // 如果不存在,添加新项 [productionDepartment, 1]
409 // selectedProductionDepartment.value.push([record.productionDepartment, 1]); 430 // selectedProductionDepartment.value.push([record.productionDepartment, 1]);
410 // } 431 // }
  432 +
  433 + // // 更新 selectedProjectNos
  434 + // if (projectNoIndex !== -1) {
  435 + // // 如果已存在,增加计数
  436 + // selectedProjectNos.value[projectNoIndex][1] += 1;
  437 + // } else {
  438 + // // 如果不存在,添加新项 [projectNo, 1]
  439 + // selectedProjectNos.value.push([record.projectNo, 1]);
  440 + // }
411 // } else { 441 // } else {
412 // // 从 checkedKeys 中移除 442 // // 从 checkedKeys 中移除
413 // checkedKeys.value = checkedKeys.value.filter((id) => id !== record.id); 443 // checkedKeys.value = checkedKeys.value.filter((id) => id !== record.id);
@@ -429,19 +459,127 @@ @@ -429,19 +459,127 @@
429 // selectedProductionDepartment.value.splice(productionDepartmentIndex, 1); 459 // selectedProductionDepartment.value.splice(productionDepartmentIndex, 1);
430 // } 460 // }
431 // } 461 // }
  462 +
  463 + // // 更新 selectedProjectNos
  464 + // if (projectNoIndex !== -1) {
  465 + // if (selectedProjectNos.value[projectNoIndex][1] > 1) {
  466 + // selectedProjectNos.value[projectNoIndex][1] -= 1;
  467 + // } else {
  468 + // selectedProjectNos.value.splice(projectNoIndex, 1);
  469 + // }
  470 + // }
  471 + // }
  472 +
  473 + // console.log('5656Checked Keys:', checkedKeys.value);
  474 + // console.log('5656Selected Customer Codes:', selectedCustomCodes.value);
  475 + // console.log('56565Selected Production Departments:', selectedProductionDepartment.value);
  476 + // console.log('5656Selected projectNo:', selectedProjectNos.value);
  477 + // }
  478 +
  479 + // // 全选处理函数
  480 + // function onSelectAll(selected: boolean, selectedRows: any[], changeRows: any[]) {
  481 + // const changeIds = changeRows.map((item) => item.id);
  482 + // const changeCustomerCodes = changeRows.map((item) => item.customerCode);
  483 + // const changeProductionDepartments = changeRows.map((item) => item.productionDepartment);
  484 + // const changeProjectNos = changeRows.map((item) => item.projectNo);
  485 +
  486 + // if (selected) {
  487 + // // 添加到 checkedKeys
  488 + // checkedKeys.value = [...checkedKeys.value, ...changeIds];
  489 +
  490 + // // 更新 selectedCustomCodes
  491 + // changeCustomerCodes.forEach((code) => {
  492 + // const index = selectedCustomCodes.value.findIndex(
  493 + // ([customerCode]) => customerCode === code,
  494 + // );
  495 + // if (index !== -1) {
  496 + // selectedCustomCodes.value[index][1] += 1;
  497 + // } else {
  498 + // selectedCustomCodes.value.push([code, 1]);
  499 + // }
  500 + // });
  501 +
  502 + // // 更新 selectedProductionDepartment
  503 + // changeProductionDepartments.forEach((department) => {
  504 + // const index = selectedProductionDepartment.value.findIndex(
  505 + // ([prodDepartment]) => prodDepartment === department,
  506 + // );
  507 + // if (index !== -1) {
  508 + // selectedProductionDepartment.value[index][1] += 1;
  509 + // } else {
  510 + // selectedProductionDepartment.value.push([department, 1]);
  511 + // }
  512 + // });
  513 +
  514 + // // 更新 selectedProjectNos
  515 + // changeProjectNos.forEach((projectNo) => {
  516 + // const index = selectedProjectNos.value.findIndex(([no]) => no === projectNo);
  517 + // if (index !== -1) {
  518 + // selectedProjectNos.value[index][1] += 1;
  519 + // } else {
  520 + // selectedProjectNos.value.push([projectNo, 1]);
  521 + // }
  522 + // });
  523 + // } else {
  524 + // // 从 checkedKeys 中移除
  525 + // checkedKeys.value = checkedKeys.value.filter((id) => !changeIds.includes(id));
  526 +
  527 + // // 更新 selectedCustomCodes
  528 + // changeCustomerCodes.forEach((code) => {
  529 + // const index = selectedCustomCodes.value.findIndex(
  530 + // ([customerCode]) => customerCode === code,
  531 + // );
  532 + // if (index !== -1) {
  533 + // if (selectedCustomCodes.value[index][1] > 1) {
  534 + // selectedCustomCodes.value[index][1] -= 1;
  535 + // } else {
  536 + // selectedCustomCodes.value.splice(index, 1);
  537 + // }
  538 + // }
  539 + // });
  540 +
  541 + // // 更新 selectedProductionDepartment
  542 + // changeProductionDepartments.forEach((department) => {
  543 + // const index = selectedProductionDepartment.value.findIndex(
  544 + // ([prodDepartment]) => prodDepartment === department,
  545 + // );
  546 + // if (index !== -1) {
  547 + // if (selectedProductionDepartment.value[index][1] > 1) {
  548 + // selectedProductionDepartment.value[index][1] -= 1;
  549 + // } else {
  550 + // selectedProductionDepartment.value.splice(index, 1);
  551 + // }
  552 + // }
  553 + // });
  554 +
  555 + // // 更新 selectedProjectNos
  556 + // changeProjectNos.forEach((projectNo) => {
  557 + // const index = selectedProjectNos.value.findIndex(([no]) => no === projectNo);
  558 + // if (index !== -1) {
  559 + // if (selectedProjectNos.value[index][1] > 1) {
  560 + // selectedProjectNos.value[index][1] -= 1;
  561 + // } else {
  562 + // selectedProjectNos.value.splice(index, 1);
  563 + // }
  564 + // }
  565 + // });
432 // } 566 // }
433 567
434 // console.log('5656Checked Keys:', checkedKeys.value); 568 // console.log('5656Checked Keys:', checkedKeys.value);
435 // console.log('5656Selected Customer Codes:', selectedCustomCodes.value); 569 // console.log('5656Selected Customer Codes:', selectedCustomCodes.value);
436 // console.log('5656Selected Production Departments:', selectedProductionDepartment.value); 570 // console.log('5656Selected Production Departments:', selectedProductionDepartment.value);
  571 + // console.log('5656Selected projectNos:', selectedProjectNos.value);
437 // } 572 // }
  573 +
438 type CustomerCodeEntry = [string, number]; // 定义二维数组类型 [customerCode, count] 574 type CustomerCodeEntry = [string, number]; // 定义二维数组类型 [customerCode, count]
439 type ProductionDepartmentEntry = [string, number]; // 定义二维数组类型 [productionDepartment, count] 575 type ProductionDepartmentEntry = [string, number]; // 定义二维数组类型 [productionDepartment, count]
440 type ProjectNoEntry = [string, number]; // 定义二维数组类型 [innerNo, count] 576 type ProjectNoEntry = [string, number]; // 定义二维数组类型 [innerNo, count]
  577 + type BusinessPersonEntry = [string, number]; // 定义二维数组类型 [businessPerson, count]
441 578
442 const selectedCustomCodes = ref<CustomerCodeEntry[]>([]); // 创建一个二维数组的 ref 579 const selectedCustomCodes = ref<CustomerCodeEntry[]>([]); // 创建一个二维数组的 ref
443 const selectedProductionDepartment = ref<ProductionDepartmentEntry[]>([]); // 创建一个二维数组的 ref 580 const selectedProductionDepartment = ref<ProductionDepartmentEntry[]>([]); // 创建一个二维数组的 ref
444 const selectedProjectNos = ref<ProjectNoEntry[]>([]); // 创建一个二维数组的 ref 581 const selectedProjectNos = ref<ProjectNoEntry[]>([]); // 创建一个二维数组的 ref
  582 + const selectedBusinessPersons = ref<BusinessPersonEntry[]>([]); // 创建一个二维数组的 ref
445 583
446 // 单选处理函数 584 // 单选处理函数
447 function onSelect( 585 function onSelect(
@@ -449,57 +587,58 @@ @@ -449,57 +587,58 @@
449 customerCode: string; 587 customerCode: string;
450 productionDepartment: string; 588 productionDepartment: string;
451 projectNo: string; 589 projectNo: string;
  590 + businessPerson: string; // 添加 businessPerson 属性
452 id: string; 591 id: string;
453 }, 592 },
454 selected: boolean, 593 selected: boolean,
455 ) { 594 ) {
456 - // 查找 customerCode 在 selectedCustomCodes 中的位置  
457 const customerCodeIndex = selectedCustomCodes.value.findIndex( 595 const customerCodeIndex = selectedCustomCodes.value.findIndex(
458 ([customerCode]) => customerCode === record.customerCode, 596 ([customerCode]) => customerCode === record.customerCode,
459 ); 597 );
460 598
461 - // 查找 productionDepartment 在 selectedProductionDepartment 中的位置  
462 const productionDepartmentIndex = selectedProductionDepartment.value.findIndex( 599 const productionDepartmentIndex = selectedProductionDepartment.value.findIndex(
463 ([department]) => department === record.productionDepartment, 600 ([department]) => department === record.productionDepartment,
464 ); 601 );
465 602
466 - // 查找 projectNo 在 selectedProjectNos 中的位置  
467 const projectNoIndex = selectedProjectNos.value.findIndex( 603 const projectNoIndex = selectedProjectNos.value.findIndex(
468 ([projectNo]) => projectNo === record.projectNo, 604 ([projectNo]) => projectNo === record.projectNo,
469 ); 605 );
470 606
  607 + const businessPersonIndex = selectedBusinessPersons.value.findIndex(
  608 + ([businessPerson]) => businessPerson === record.businessPerson,
  609 + );
  610 +
471 if (selected) { 611 if (selected) {
472 - // 添加到 checkedKeys  
473 checkedKeys.value = [...checkedKeys.value, record.id]; 612 checkedKeys.value = [...checkedKeys.value, record.id];
474 613
475 // 更新 selectedCustomCodes 614 // 更新 selectedCustomCodes
476 if (customerCodeIndex !== -1) { 615 if (customerCodeIndex !== -1) {
477 - // 如果已存在,增加计数  
478 selectedCustomCodes.value[customerCodeIndex][1] += 1; 616 selectedCustomCodes.value[customerCodeIndex][1] += 1;
479 } else { 617 } else {
480 - // 如果不存在,添加新项 [customerCode, 1]  
481 selectedCustomCodes.value.push([record.customerCode, 1]); 618 selectedCustomCodes.value.push([record.customerCode, 1]);
482 } 619 }
483 620
484 // 更新 selectedProductionDepartment 621 // 更新 selectedProductionDepartment
485 if (productionDepartmentIndex !== -1) { 622 if (productionDepartmentIndex !== -1) {
486 - // 如果已存在,增加计数  
487 selectedProductionDepartment.value[productionDepartmentIndex][1] += 1; 623 selectedProductionDepartment.value[productionDepartmentIndex][1] += 1;
488 } else { 624 } else {
489 - // 如果不存在,添加新项 [productionDepartment, 1]  
490 selectedProductionDepartment.value.push([record.productionDepartment, 1]); 625 selectedProductionDepartment.value.push([record.productionDepartment, 1]);
491 } 626 }
492 627
493 // 更新 selectedProjectNos 628 // 更新 selectedProjectNos
494 if (projectNoIndex !== -1) { 629 if (projectNoIndex !== -1) {
495 - // 如果已存在,增加计数  
496 selectedProjectNos.value[projectNoIndex][1] += 1; 630 selectedProjectNos.value[projectNoIndex][1] += 1;
497 } else { 631 } else {
498 - // 如果不存在,添加新项 [projectNo, 1]  
499 selectedProjectNos.value.push([record.projectNo, 1]); 632 selectedProjectNos.value.push([record.projectNo, 1]);
500 } 633 }
  634 +
  635 + // 更新 selectedBusinessPersons
  636 + if (businessPersonIndex !== -1) {
  637 + selectedBusinessPersons.value[businessPersonIndex][1] += 1;
  638 + } else {
  639 + selectedBusinessPersons.value.push([record.businessPerson, 1]);
  640 + }
501 } else { 641 } else {
502 - // 从 checkedKeys 中移除  
503 checkedKeys.value = checkedKeys.value.filter((id) => id !== record.id); 642 checkedKeys.value = checkedKeys.value.filter((id) => id !== record.id);
504 643
505 // 更新 selectedCustomCodes 644 // 更新 selectedCustomCodes
@@ -528,94 +667,33 @@ @@ -528,94 +667,33 @@
528 selectedProjectNos.value.splice(projectNoIndex, 1); 667 selectedProjectNos.value.splice(projectNoIndex, 1);
529 } 668 }
530 } 669 }
  670 +
  671 + // 更新 selectedBusinessPersons
  672 + if (businessPersonIndex !== -1) {
  673 + if (selectedBusinessPersons.value[businessPersonIndex][1] > 1) {
  674 + selectedBusinessPersons.value[businessPersonIndex][1] -= 1;
  675 + } else {
  676 + selectedBusinessPersons.value.splice(businessPersonIndex, 1);
  677 + }
  678 + }
531 } 679 }
532 680
533 - console.log('5656Checked Keys:', checkedKeys.value);  
534 - console.log('5656Selected Customer Codes:', selectedCustomCodes.value);  
535 - console.log('56565Selected Production Departments:', selectedProductionDepartment.value);  
536 - console.log('5656Selected projectNo:', selectedProjectNos.value); 681 + console.log('Checked Keys:', checkedKeys.value);
  682 + console.log('Selected Customer Codes:', selectedCustomCodes.value);
  683 + console.log('Selected Production Departments:', selectedProductionDepartment.value);
  684 + console.log('Selected Project Nos:', selectedProjectNos.value);
  685 + console.log('Selected Business Persons:', selectedBusinessPersons.value);
537 } 686 }
538 687
539 - // // 全选处理函数  
540 - // function onSelectAll(selected: boolean, selectedRows: any[], changeRows: any[]) {  
541 - // const changeIds = changeRows.map((item) => item.id);  
542 - // const changeCustomerCodes = changeRows.map((item) => item.customerCode);  
543 - // const changeProductionDepartments = changeRows.map((item) => item.productionDepartment);  
544 -  
545 - // if (selected) {  
546 - // // 添加到 checkedKeys  
547 - // checkedKeys.value = [...checkedKeys.value, ...changeIds];  
548 -  
549 - // // 更新 selectedCustomCodes  
550 - // changeCustomerCodes.forEach((code) => {  
551 - // const index = selectedCustomCodes.value.findIndex(  
552 - // ([customerCode]) => customerCode === code,  
553 - // );  
554 - // if (index !== -1) {  
555 - // selectedCustomCodes.value[index][1] += 1;  
556 - // } else {  
557 - // selectedCustomCodes.value.push([code, 1]);  
558 - // }  
559 - // });  
560 -  
561 - // // 更新 selectedProductionDepartment  
562 - // changeProductionDepartments.forEach((department) => {  
563 - // const index = selectedProductionDepartment.value.findIndex(  
564 - // ([prodDepartment]) => prodDepartment === department,  
565 - // );  
566 - // if (index !== -1) {  
567 - // selectedProductionDepartment.value[index][1] += 1;  
568 - // } else {  
569 - // selectedProductionDepartment.value.push([department, 1]);  
570 - // }  
571 - // });  
572 - // } else {  
573 - // // 从 checkedKeys 中移除  
574 - // checkedKeys.value = checkedKeys.value.filter((id) => !changeIds.includes(id));  
575 -  
576 - // // 更新 selectedCustomCodes  
577 - // changeCustomerCodes.forEach((code) => {  
578 - // const index = selectedCustomCodes.value.findIndex(  
579 - // ([customerCode]) => customerCode === code,  
580 - // );  
581 - // if (index !== -1) {  
582 - // if (selectedCustomCodes.value[index][1] > 1) {  
583 - // selectedCustomCodes.value[index][1] -= 1;  
584 - // } else {  
585 - // selectedCustomCodes.value.splice(index, 1);  
586 - // }  
587 - // }  
588 - // });  
589 -  
590 - // // 更新 selectedProductionDepartment  
591 - // changeProductionDepartments.forEach((department) => {  
592 - // const index = selectedProductionDepartment.value.findIndex(  
593 - // ([prodDepartment]) => prodDepartment === department,  
594 - // );  
595 - // if (index !== -1) {  
596 - // if (selectedProductionDepartment.value[index][1] > 1) {  
597 - // selectedProductionDepartment.value[index][1] -= 1;  
598 - // } else {  
599 - // selectedProductionDepartment.value.splice(index, 1);  
600 - // }  
601 - // }  
602 - // });  
603 - // }  
604 -  
605 - // console.log('5656Checked Keys:', checkedKeys.value);  
606 - // console.log('5656Selected Customer Codes:', selectedCustomCodes.value);  
607 - // console.log('5656Selected Production Departments:', selectedProductionDepartment.value);  
608 - // }  
609 -  
610 // 全选处理函数 688 // 全选处理函数
611 function onSelectAll(selected: boolean, selectedRows: any[], changeRows: any[]) { 689 function onSelectAll(selected: boolean, selectedRows: any[], changeRows: any[]) {
612 const changeIds = changeRows.map((item) => item.id); 690 const changeIds = changeRows.map((item) => item.id);
613 const changeCustomerCodes = changeRows.map((item) => item.customerCode); 691 const changeCustomerCodes = changeRows.map((item) => item.customerCode);
614 const changeProductionDepartments = changeRows.map((item) => item.productionDepartment); 692 const changeProductionDepartments = changeRows.map((item) => item.productionDepartment);
615 const changeProjectNos = changeRows.map((item) => item.projectNo); 693 const changeProjectNos = changeRows.map((item) => item.projectNo);
  694 + const changeBusinessPersons = changeRows.map((item) => item.businessPerson); // 新增处理 businessPerson
616 695
617 if (selected) { 696 if (selected) {
618 - // 添加到 checkedKeys  
619 checkedKeys.value = [...checkedKeys.value, ...changeIds]; 697 checkedKeys.value = [...checkedKeys.value, ...changeIds];
620 698
621 // 更新 selectedCustomCodes 699 // 更新 selectedCustomCodes
@@ -651,8 +729,17 @@ @@ -651,8 +729,17 @@
651 selectedProjectNos.value.push([projectNo, 1]); 729 selectedProjectNos.value.push([projectNo, 1]);
652 } 730 }
653 }); 731 });
  732 +
  733 + // 更新 selectedBusinessPersons
  734 + changeBusinessPersons.forEach((businessPerson) => {
  735 + const index = selectedBusinessPersons.value.findIndex(([bp]) => bp === businessPerson);
  736 + if (index !== -1) {
  737 + selectedBusinessPersons.value[index][1] += 1;
  738 + } else {
  739 + selectedBusinessPersons.value.push([businessPerson, 1]);
  740 + }
  741 + });
654 } else { 742 } else {
655 - // 从 checkedKeys 中移除  
656 checkedKeys.value = checkedKeys.value.filter((id) => !changeIds.includes(id)); 743 checkedKeys.value = checkedKeys.value.filter((id) => !changeIds.includes(id));
657 744
658 // 更新 selectedCustomCodes 745 // 更新 selectedCustomCodes
@@ -684,7 +771,7 @@ @@ -684,7 +771,7 @@
684 }); 771 });
685 772
686 // 更新 selectedProjectNos 773 // 更新 selectedProjectNos
687 - changeInnerNos.forEach((projectNo) => { 774 + changeProjectNos.forEach((projectNo) => {
688 const index = selectedProjectNos.value.findIndex(([no]) => no === projectNo); 775 const index = selectedProjectNos.value.findIndex(([no]) => no === projectNo);
689 if (index !== -1) { 776 if (index !== -1) {
690 if (selectedProjectNos.value[index][1] > 1) { 777 if (selectedProjectNos.value[index][1] > 1) {
@@ -694,12 +781,33 @@ @@ -694,12 +781,33 @@
694 } 781 }
695 } 782 }
696 }); 783 });
  784 +
  785 + // 更新 selectedBusinessPersons
  786 + changeBusinessPersons.forEach((businessPerson) => {
  787 + const index = selectedBusinessPersons.value.findIndex(([bp]) => bp === businessPerson);
  788 + if (index !== -1) {
  789 + if (selectedBusinessPersons.value[index][1] > 1) {
  790 + selectedBusinessPersons.value[index][1] -= 1;
  791 + } else {
  792 + selectedBusinessPersons.value.splice(index, 1);
  793 + }
  794 + }
  795 + });
697 } 796 }
698 797
699 - console.log('5656Checked Keys:', checkedKeys.value);  
700 - console.log('5656Selected Customer Codes:', selectedCustomCodes.value);  
701 - console.log('5656Selected Production Departments:', selectedProductionDepartment.value);  
702 - console.log('5656Selected projectNos:', selectedProjectNos.value); 798 + console.log('Checked Keys:', checkedKeys.value);
  799 + console.log('Selected Customer Codes:', selectedCustomCodes.value);
  800 + console.log('Selected Production Departments:', selectedProductionDepartment.value);
  801 + console.log('Selected Project Nos:', selectedProjectNos.value);
  802 + console.log('Selected Business Persons:', selectedBusinessPersons.value);
  803 + }
  804 +
  805 + function handleClearChoose() {
  806 + checkedKeys.value = [];
  807 + selectedCustomCodes.value = [];
  808 + selectedProductionDepartment.value = [];
  809 + selectedProjectNos.value = [];
  810 + selectedBusinessPersons.value = [];
703 } 811 }
704 812
705 function handleEdit(record, e) { 813 function handleEdit(record, e) {
@@ -820,10 +928,18 @@ @@ -820,10 +928,18 @@
820 const form = getForm(); 928 const form = getForm();
821 const values = form.getFieldsValue(); 929 const values = form.getFieldsValue();
822 console.log(selectedCustomCodes.value, 5656); 930 console.log(selectedCustomCodes.value, 5656);
823 - if (selectedCustomCodes.value.length == 0) { 931 + if (checkedKeys.value.length == 0) {
824 error('请选择订单'); 932 error('请选择订单');
825 return; 933 return;
826 } 934 }
  935 + if (selectedCustomCodes.value.length > 1) {
  936 + error('客户编码需一致');
  937 + return;
  938 + }
  939 + if (selectedBusinessPersons.value.length > 1) {
  940 + error('业务员需一致');
  941 + return;
  942 + }
827 openProductModal(true, { 943 openProductModal(true, {
828 checkedKeys: checkedKeys.value, 944 checkedKeys: checkedKeys.value,
829 customers: selectedCustomCodes.value, 945 customers: selectedCustomCodes.value,
@@ -980,6 +1096,7 @@ @@ -980,6 +1096,7 @@
980 handleDelete, 1096 handleDelete,
981 handleServiceProfitModal, 1097 handleServiceProfitModal,
982 handleProductProfitModal, 1098 handleProductProfitModal,
  1099 + handleClearChoose,
983 selectedCustomCodes, 1100 selectedCustomCodes,
984 role, 1101 role,
985 ROLE, 1102 ROLE,
src/views/project/order/tableData.tsx
@@ -161,9 +161,21 @@ export const ORDER_LIST_BASE_FIELDS = [ @@ -161,9 +161,21 @@ export const ORDER_LIST_BASE_FIELDS = [
161 { 161 {
162 field: 'returnOrder', 162 field: 'returnOrder',
163 component: 'Select', 163 component: 'Select',
164 - default: '请选择',  
165 - label: '是否返单 ', 164 + labelWidth: 150,
  165 + label: '是否返单',
166 rules: [{ required: true }], 166 rules: [{ required: true }],
  167 + componentProps: {
  168 + options: [
  169 + {
  170 + label: '是',
  171 + value: '1',
  172 + },
  173 + {
  174 + label: '否',
  175 + value: '0',
  176 + },
  177 + ],
  178 + },
167 }, 179 },
168 ]; 180 ];
169 181
@@ -692,6 +704,17 @@ export function getOrderColumns(role: ROLE) { @@ -692,6 +704,17 @@ export function getOrderColumns(role: ROLE) {
692 ...ORDER_LIST_SCHEDULE, 704 ...ORDER_LIST_SCHEDULE,
693 ]; 705 ];
694 } 706 }
  707 + //财务看到所有列
  708 + if (role === ROLE.FINANCE) {
  709 + return [
  710 + ...ORDER_LIST_BASE_FIELDS,
  711 + ...ORDER_LIST_PROFIT_FIELDS,
  712 + ...ORDER_LIST_REPORT_FIELDS,
  713 + ...ORDER_LIST_TRACK_FIELDS,
  714 + ...ORDER_LIST_INSPECT_FIELDS,
  715 + ...ORDER_LIST_SCHEDULE,
  716 + ];
  717 + }
695 //业务员看到-基本,项目报告书,利润分析,跟单信息,质检 718 //业务员看到-基本,项目报告书,利润分析,跟单信息,质检
696 if (role === ROLE.BUSINESS) { 719 if (role === ROLE.BUSINESS) {
697 return [ 720 return [
vite.config.ts
@@ -20,7 +20,7 @@ export default defineApplicationConfig({ @@ -20,7 +20,7 @@ export default defineApplicationConfig({
20 server: { 20 server: {
21 proxy: { 21 proxy: {
22 '/basic-api/order': { 22 '/basic-api/order': {
23 - target: 'http://47.104.8.35:18000', 23 + target: 'http://47.104.8.35:18001',
24 // target: 'http://localhost:8001', 24 // target: 'http://localhost:8001',
25 // target: 'http://39.108.227.113:8000', 25 // target: 'http://39.108.227.113:8000',
26 // target: 'http://localhost:8000', 26 // target: 'http://localhost:8000',
@@ -31,7 +31,7 @@ export default defineApplicationConfig({ @@ -31,7 +31,7 @@ export default defineApplicationConfig({
31 rewrite: (path) => path.replace(new RegExp(`^/basic-api`), ''), 31 rewrite: (path) => path.replace(new RegExp(`^/basic-api`), ''),
32 }, 32 },
33 '/api/localStorage/upload': { 33 '/api/localStorage/upload': {
34 - target: 'http://47.104.8.35:18000', 34 + target: 'http://47.104.8.35:18001',
35 // target: 'http://localhost:8001', 35 // target: 'http://localhost:8001',
36 // target: 'http://39.108.227.113:8000', 36 // target: 'http://39.108.227.113:8000',
37 // target: '192.168.31.250:18000', 37 // target: '192.168.31.250:18000',