Commit 327b80fac800d683c2293565f56792542d0c9b17

Authored by boyang
1 parent 78ec6a79

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

src/api/project/global.ts
... ... @@ -8,13 +8,13 @@ enum Api {
8 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 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 18 return res;
19 19 };
20 20  
... ...
src/api/project/order.ts
... ... @@ -34,8 +34,8 @@ enum Api {
34 34  
35 35 TRACK_HISTORY = '/order/erp/opinion/log/query_by_id', //跟单结果记录
36 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 40 BUSINESS_PROFIT_RATIO = '/order/erp/calculate_profit/business_profit_ratio', //业务/研发净利润分析
41 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 16 RoleEnum.BUSINESS,
17 17 RoleEnum.TRACKER,
18 18 RoleEnum.INSPECT,
  19 + RoleEnum.FINANCE,
19 20 ],
20 21 orderNo: 3,
21 22 icon: 'ion:grid-outline',
... ...
src/store/modules/user.ts
... ... @@ -189,10 +189,15 @@ export function useUserStoreWithOut() {
189 189 return useUserStore(store);
190 190 }
191 191  
  192 +//分析台订单趋势
  193 +export const dateTime = ref();
  194 +//分析台时期
  195 +export const period = ref();
  196 +
192 197 //分析台切换页面变量
193 198 export const exchangeTab = ref('tab1');
194   -//分析台时期
195   -// export const period = ref('');
  199 +
  200 +//销售额完成率
196 201 //分析台业务员
197 202 export const businessPersonIn = ref();
198 203 //分析台客户编码
... ...
src/views/dashboard/analysis/components/GrowCard.vue
... ... @@ -47,21 +47,40 @@
47 47 import { growCardList } from '../data';
48 48 import { useDataStoreWithOut } from '/@/store/modules/data';
49 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 57 import { number } from 'vue-types';
52   - import { getSalesData, getCustomerSalesData } from '/@/api/project/global';
  58 + import { getSalesData, getApiData } from '/@/api/project/global';
53 59 import { useOrderStoreWithOut } from '/@/store/modules/order';
54 60  
55 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 76 const growCardList = computed(() => {
58 77 const data = dataStore.getData;
59   -
  78 + console.log(data1.value, '5656data1.value');
60 79 return [
61 80 {
62 81 title: '订单完成',
63 82 icon: 'visit-count|svg',
64   - value: data?.orderFinishedCount || 0,
  83 + value: data1.value?.allCount || 0,
65 84 total: 120000,
66 85 color: 'green',
67 86 action: '月',
... ... @@ -69,7 +88,7 @@
69 88 {
70 89 title: '跟单和质检中',
71 90 icon: 'total-sales|svg',
72   - value: data?.orderInspectingCount || 0,
  91 + value: data1.value?.trackingAndInspectingList || 0,
73 92 total: 500000,
74 93 color: 'blue',
75 94 action: '月',
... ... @@ -77,7 +96,7 @@
77 96 {
78 97 title: '利润分析表待审核',
79 98 icon: 'download-count|svg',
80   - value: data?.orderProfitWaitAuditCount || 0,
  99 + value: data1.value?.profitList || 0,
81 100 total: 120000,
82 101 color: 'orange',
83 102 action: '周',
... ... @@ -85,7 +104,7 @@
85 104 {
86 105 title: '项目报告书待审核',
87 106 icon: 'transaction|svg',
88   - value: data?.orderReportWaitAuditCount || 0,
  107 + value: data1.value?.reportList || 0,
89 108 total: 50000,
90 109 color: 'purple',
91 110 action: '年',
... ... @@ -93,7 +112,7 @@
93 112 {
94 113 title: '订单初始化',
95 114 icon: 'transaction|svg',
96   - value: data?.orderCount || 0,
  115 + value: data1.value?.orderInitList || 0,
97 116 total: 50000,
98 117 color: 'purple',
99 118 action: '年',
... ... @@ -108,6 +127,11 @@
108 127 // });
109 128 // });
110 129 onMounted(async () => {
  130 + data1.value = await getApiData({
  131 + dateTime: dateTime.value,
  132 + period: period.value,
  133 + });
  134 + console.log(data1.value, '56565656');
111 135 data2.value = await getSalesData({
112 136 businessPersonIn: businessPersonIn.value,
113 137 customerCodeIn: customerCodeIn.value,
... ... @@ -115,14 +139,14 @@
115 139 });
116 140 watch(
117 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 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 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 22 <div ref="chartRef" :style="{ height: '500px', width }"></div>
3 23 </template>
4 24  
... ... @@ -8,15 +28,71 @@
8 28 import { basicProps } from './props';
9 29 import { max } from 'lodash-es';
10 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 35 defineProps({
13 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 56 const chartRef = ref<HTMLDivElement | null>(null);
16 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 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 96 const maxY = data?.y ? max(data?.y) : 0;
21 97 setOptions({
22 98 tooltip: {
... ... @@ -30,7 +106,6 @@
30 106 },
31 107 xAxis: {
32 108 type: 'category',
33   - boundaryGap: false,
34 109 data: data?.x,
35 110 splitLine: {
36 111 show: true,
... ... @@ -87,3 +162,29 @@
87 162 });
88 163 });
89 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 55 </div></div
56 56 >
57 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 59 </template>
60 60 <script lang="ts">
61 61 import { basicProps } from './props';
... ... @@ -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 184 xAxis: {
182 185 type: 'category',
183 186 data: customerChartData1?.x,
184 187 },
185 188 yAxis: {
186 189 type: 'value',
187   - // max: 8000,
188   - splitNumber: 4,
  190 + // // max: 8000,
  191 + // splitNumber: 4,
189 192 },
190 193 series: [
191 194 {
  195 + name: '销售额',
192 196 data: customerChartData1?.y,
193 197 type: 'bar',
194 198 barMaxWidth: 80,
195 199 },
196 200 {
  201 + name: '销售目标',
197 202 smooth: true,
198 203 data: customerChartData1?.z,
199 204 type: 'line',
... ...
src/views/project/approve/FieldPanel.vue
... ... @@ -143,6 +143,11 @@
143 143 dataIndex: 'picUrl',
144 144 width: 150,
145 145 },
  146 + {
  147 + title: '申请原因',
  148 + dataIndex: 'applyRemark',
  149 + width: 150,
  150 + },
146 151 ];
147 152  
148 153 if (props.isApproved) {
... ...
src/views/project/approve/PayPanel.vue
... ... @@ -12,6 +12,7 @@
12 12 </template>
13 13 <template v-if="column.key === 'action'">
14 14 <TableAction
  15 + v-if="!isApproved"
15 16 :actions="[
16 17 {
17 18 label: '编辑',
... ... @@ -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 34 </template>
24 35 </template>
25 36 </BasicTable>
  37 + <!-- :showFooter="!isApproved && role === ROLE.ADMIN" -->
  38 +
26 39 <BasicModal
27   - :showFooter="!isApproved && role === ROLE.ADMIN"
  40 + :formFooter="!isApproved && role === ROLE.ADMIN"
28 41 @register="registerModal"
29 42 title="申请信息"
30 43 okText="通过"
31 44 @ok="handleTrue"
  45 + :showCancelBtn="!isApproved && role === ROLE.ADMIN"
  46 + :showOkBtn="!isApproved && role === ROLE.ADMIN"
32 47 >
33 48 <Description
34 49 class="mt-4"
... ... @@ -39,7 +54,7 @@
39 54 :schema="schema"
40 55 />
41 56 <template #appendFooter>
42   - <a-button @click="handleFalse"> 不通过</a-button>
  57 + <a-button v-if="!isApproved && role === ROLE.ADMIN" @click="handleFalse"> 不通过</a-button>
43 58 </template>
44 59 </BasicModal>
45 60 <MsgModal v-if="msgVisible" @msg-modal-close="handleMsgModalClose" />
... ... @@ -84,29 +99,30 @@
84 99 const id = ref('');
85 100  
86 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 106 label: '生产科实际应付金额汇总',
91 107 },
92 108 {
93   - field: 'all',
  109 + field: 'payedDate',
94 110 label: '生产科付款日期',
95 111 },
96 112 {
97   - field: 'deductAmount',
  113 + field: 'actualPayedDate',
98 114 label: '实际付款日期',
99 115 },
100 116 {
101   - field: 'productionDepartmentTotalPrice',
  117 + field: 'totalProductionAmount',
102 118 label: '生产科总金额汇总',
103 119 },
104 120 {
105   - field: 'actualPayedAmount',
  121 + field: 'totalActualPayedAmount',
106 122 label: '实际付款金额汇总',
107 123 },
108 124 {
109   - field: 'actualReceivableAmount',
  125 + field: 'deductAmount',
110 126 label: '生产科扣款金额汇总',
111 127 },
112 128 ];
... ... @@ -128,19 +144,31 @@
128 144 width: 150,
129 145 customRender: (column) => {
130 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 151 title: '审核类型',
137 152 dataIndex: 'productionDepartment',
138 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 164 title: '生产科',
142 165 dataIndex: 'productionDepartment',
143 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 232  
205 233 async function handleDetail(data) {
206 234 openModal(true, { data });
207   - mockData.value = data.fieldInfos.invoiceBillOrderDO;
208   - console.log(mockData.value, 5656);
  235 + mockData.value = data.fieldInfos.checkBillOrderDO;
209 236 id.value = data.id;
210 237 }
211 238  
... ...
src/views/project/approve/ProfitPanel.vue
... ... @@ -93,7 +93,7 @@
93 93 const { record } = column || {};
94 94 return record?.orderBaseInfo?.innerNo;
95 95 },
96   - },
  96 + },
97 97 {
98 98 title: '图片',
99 99 dataIndex: 'picUrl',
... ...
src/views/project/approve/ReceivePanel.vue
... ... @@ -12,6 +12,7 @@
12 12 </template>
13 13 <template v-if="column.key === 'action'">
14 14 <TableAction
  15 + v-if="!isApproved"
15 16 :actions="[
16 17 {
17 18 label: '编辑',
... ... @@ -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 34 </template>
24 35 </template>
25 36 </BasicTable>
26 37 <BasicModal
27   - :showFooter="!isApproved && role === ROLE.ADMIN"
  38 + :formFooter="!isApproved && role === ROLE.ADMIN"
28 39 @register="registerModal"
29 40 title="申请信息"
30 41 okText="通过"
31 42 @ok="handleTrue"
  43 + :showCancelBtn="!isApproved && role === ROLE.ADMIN"
  44 + :showOkBtn="!isApproved && role === ROLE.ADMIN"
32 45 >
33 46 <Description
34 47 class="mt-4"
... ... @@ -39,7 +52,7 @@
39 52 :schema="schema"
40 53 />
41 54 <template #appendFooter>
42   - <a-button @click="handleFalse"> 不通过</a-button>
  55 + <a-button v-if="!isApproved && role === ROLE.ADMIN" @click="handleFalse"> 不通过</a-button>
43 56 </template>
44 57 </BasicModal>
45 58 <MsgModal v-if="msgVisible" @msg-modal-close="handleMsgModalClose" />
... ... @@ -90,7 +103,7 @@
90 103 label: '实际收款金额汇总',
91 104 },
92 105 {
93   - field: 'all',
  106 + field: 'totalCustomerAmount',
94 107 label: '客户总价金额汇总',
95 108 },
96 109 {
... ... @@ -102,7 +115,7 @@
102 115 label: '必须回款日期',
103 116 },
104 117 {
105   - field: 'addr',
  118 + field: 'actualRefundDate',
106 119 label: '实际回款日期',
107 120 },
108 121 {
... ... @@ -138,7 +151,7 @@
138 151 width: 150,
139 152 customRender: (column) => {
140 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 226 async function handleDetail(data) {
214 227 openModal(true, { data });
215 228 mockData.value = data.fieldInfos.invoiceBillOrderDO;
216   - console.log(mockData.value, 5656);
  229 + console.log(data, 5656777);
217 230 id.value = data.id;
218 231 }
219 232  
... ...
src/views/project/config/CreateModal.vue
... ... @@ -58,16 +58,7 @@
58 58 {
59 59 field: 'relationValue',
60 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 62 rules: [{ required: true }],
72 63 colProps: {
73 64 span: 24,
... ... @@ -105,16 +96,7 @@
105 96 settingName: '客户编码',
106 97 settingValue: values.settingValue,
107 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 100 relationName: '包装费用',
119 101 relationValue: values.relationValue,
120 102 };
... ...
src/views/project/config/TablePanel.vue
1 1 <template>
2 2 <BasicTable @register="registerTable" :bordered="true">
3 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 11 </template>
6 12 <template #bodyCell="{ column, record }">
7 13 <template v-if="column.key === 'action'">
... ... @@ -9,6 +15,8 @@
9 15 </template>
10 16 </template>
11 17 </BasicTable>
  18 + <CostEdit @register="registerEdit" @success="handleModalSuccess" />
  19 + <CostCreate @register="registerCostCreate" @modal-success="handleModalSuccess" />
12 20 <CreateModal
13 21 @register="createModalRegister"
14 22 @modal-success="handleModalSuccess"
... ... @@ -21,6 +29,9 @@
21 29 import { deleteConfig, getList, saveConfig } from '/@/api/sys/config';
22 30 import { COLUMNS } from './data';
23 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 36 const props = defineProps({
26 37 searchInfo: {
... ... @@ -31,6 +42,8 @@
31 42 },
32 43 });
33 44 const [createModalRegister, { openModal }] = useModal();
  45 + const [registerCostCreate, { openModal: openCostCreateModal }] = useModal();
  46 + const [registerEdit, { openDrawer: openDrawerEdit }] = useDrawer();
34 47  
35 48 const [registerTable, { reload }] = useTable({
36 49 api: getList,
... ... @@ -52,10 +65,27 @@
52 65 function createActions(record: any): any[] {
53 66 if (!record.editable) {
54 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 90 ...(props.column !== 3 && {
61 91 label: '删除',
... ... @@ -92,7 +122,21 @@
92 122 handleCancel(record);
93 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 140 function handleEdit(record: any) {
97 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 70 title: '固定成本',
71 71 dataIndex: 'relationValue',
72 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 79 title: '提成比例',
78 80 dataIndex: 'relationValue',
79 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 89 dataIndex: 'relationValue',
86 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 106 7: [
... ...
src/views/project/config/index.vue
... ... @@ -20,7 +20,7 @@
20 20 <TablePanel :searchInfo="{ relationCode: 'orderHodTime' }" :column="5" />
21 21 </Tabs.TabPane>
22 22 <Tabs.TabPane key="6" tab="提成成本配置">
23   - <TablePanel :searchInfo="{ relationCode: 'orderHodTime' }" :column="6" />
  23 + <TablePanel :searchInfo="{ relationCode: 'costSettingItem' }" :column="6" />
24 24 </Tabs.TabPane>
25 25 <Tabs.TabPane key="7" tab="销售额配置">
26 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 2 <div class="p-4">
3 3 <BasicTable @register="registerTable">
4 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 11 <FinanceEdit @register="registerFinanceEdit" @success="handleSuccess" />
7 12 <TrackEdit @register="registerTrackEdit" @success="handleSuccess" />
8 13 <CheckSum @register="registerCheckSum" />
9 14 <InvoiceUpload @register="registerInvoiceUpload" @success="handleSuccess" />
10 15 <CheckDetail @register="registerInvoiceDetail" />
  16 + <DeductShow @register="registerDeductShow" />
11 17 </template>
12 18 <template #bodyCell="{ column, record }">
13 19 <template v-if="column.key === 'action'">
... ... @@ -39,6 +45,14 @@
39 45 label: '删除',
40 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 58 </template>
... ... @@ -55,6 +69,7 @@
55 69 import InvoiceUpload from './InvoiceUpload.vue';
56 70 import CheckDetail from './CheckDetail.vue';
57 71 import CheckSum from './CheckSum.vue';
  72 + import DeductShow from './DeductShow.vue';
58 73 import { useDrawer } from '/@/components/Drawer';
59 74 import { useModal } from '/@/components/Modal';
60 75 import { getCheck, checkDelete, checkCommit, checkDetail } from '@/api/project/invoice';
... ... @@ -64,6 +79,7 @@
64 79 const [registerFinanceEdit, { openDrawer: openFinanceEdit }] = useDrawer();
65 80 const [registerTrackEdit, { openDrawer: openTrackEdit }] = useDrawer();
66 81 const [registerInvoiceUpload, { openModal: openInvoiceUpload }] = useModal();
  82 + const [registerDeductShow, { openModal: openDeductShow }] = useModal();
67 83 const [registerInvoiceDetail, { openDrawer: openCheckDetail }] = useDrawer();
68 84 const checkedKeys = ref<Array<string | number>>([]);
69 85  
... ... @@ -209,7 +225,7 @@
209 225 // console.log(selectedCustomCodes.value, 56561);
210 226 // console.log(checkedKeys.value, 56562);
211 227 // }
212   -
  228 + //选择算法:创建二维数组,使客户编码和生产科相同
213 229 type CustomerCodeEntry = [string, number]; // 定义二维数组类型 [customerCode, count]
214 230 type ProductionDepartmentEntry = [string, number]; // 定义二维数组类型 [productionDepartment, count]
215 231  
... ... @@ -376,6 +392,14 @@
376 392 reload();
377 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 403 function handleDetail(record) {
380 404 openCheckDetail(true, {
381 405 data: record,
... ...
src/views/project/finance/receive/index.vue
... ... @@ -2,7 +2,12 @@
2 2 <div class="p-4">
3 3 <BasicTable @register="registerTable">
4 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 11 <FinanceEdit @register="registerFinanceEdit" @success="handleSuccess" />
7 12 <InvoiceAnalysis @register="registerInvoiceAnalysis" />
8 13 <TrackEdit @register="registerTrackEdit" @success="handleSuccess" />
... ...
src/views/project/order/CheckDetail.vue
1 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 40 <a-button type="primary" @click="onGoFormDetail"> 返回编辑</a-button>
40 41 </template> -->
41   - </BasicDrawer>
  42 + </BasicDrawer>
  43 + <ApproveReason @register="approveReasonModalRegister" @success="handleCloseModal" />
  44 + </div>
42 45 </template>
43 46 <script lang="ts">
44 47 import { computed, defineComponent, reactive, ref } from 'vue';
45 48 import { BasicForm, useForm } from '/@/components/Form/index';
46 49 import { orderAuth } from '/@/api/project/order';
47 50 import { ROLE } from './type.d';
  51 + import { useModal } from '/@/components/Modal';
  52 + import ApproveReason from './FormDetail/ApproveReason.vue';
48 53  
49 54 import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
50 55 import {
... ... @@ -79,7 +84,7 @@
79 84 );
80 85  
81 86 export default defineComponent({
82   - components: { BasicDrawer, BasicForm },
  87 + components: { BasicDrawer, BasicForm, ApproveReason },
83 88 props: {
84 89 onGoFormDetail: {
85 90 type: Function,
... ... @@ -92,6 +97,7 @@
92 97 const reportSchemas = getSchema(FIELDS_REPORT_INFO);
93 98 const inspecSchemas = getSchema(FIELDS_INSPECTION_INFO);
94 99 const trackSchemas = getSchema(FIELDS_TRACK_STAGE_INFO);
  100 + const [approveReasonModalRegister, { openModal: openReasonModal }] = useModal();
95 101 const [registerForm, { getFieldsValue }] = useForm({
96 102 labelWidth: 120,
97 103 schemas,
... ... @@ -137,6 +143,9 @@
137 143 Object.assign(lockFields, data.lockFields);
138 144 id.value = data.id;
139 145 });
  146 + function handleCloseModal() {
  147 + closeDrawer();
  148 + }
140 149  
141 150 const role = computed(() => {
142 151 return userStore.getUserInfo?.roleSmallVO?.code;
... ... @@ -148,7 +157,6 @@
148 157 const reportFieldValues = getReportFieldsValue();
149 158 const inspectFieldValues = getInspectFieldsValue();
150 159 const trackFieldValues = getTrackFieldsValue();
151   -
152 160 if (baseFieldValues) {
153 161 FIELDS_BASE_INFO.map(
154 162 ({ field }) =>
... ... @@ -156,14 +164,12 @@
156 164 baseFieldValues[field] === 'UN_LOCKED' ? 'UN_LOCKED' : 'LOCKED'),
157 165 );
158 166 }
159   -
160 167 if (reportFieldValues)
161 168 FIELDS_REPORT_INFO.map(
162 169 ({ field }) =>
163 170 (reportFieldValues[field] =
164 171 reportFieldValues[field] === 'UN_LOCKED' ? 'UN_LOCKED' : 'LOCKED'),
165 172 );
166   -
167 173 if (profitFieldValues)
168 174 FIELDS_PROFIT_INFO.map(
169 175 ({ field }) =>
... ... @@ -176,21 +182,18 @@
176 182 (trackFieldValues[field] =
177 183 trackFieldValues[field] === 'UN_LOCKED' ? 'UN_LOCKED' : 'LOCKED'),
178 184 );
179   -
180 185 if (inspectFieldValues)
181 186 FIELDS_INSPECTION_INFO.map(
182 187 ({ field }) =>
183 188 (inspectFieldValues[field] =
184 189 inspectFieldValues[field] === 'UN_LOCKED' ? 'UN_LOCKED' : 'LOCKED'),
185 190 );
186   -
187 191 // !isEmpty(baseFieldValues) &&
188 192 // Object.keys(baseFieldValues.baseFields)?.map((key) => {
189 193 // baseFieldValues.baseFields[key] = baseFieldValues.baseFields[key]
190 194 // ? 'UN_LOCKED'
191 195 // : 'LOCKED';
192 196 // });
193   -
194 197 // !isEmpty(profitFieldValues) &&
195 198 // Object.keys(profitFieldValues.profitAnalysisFields).map((key) => {
196 199 // profitFieldValues.profitAnalysisFields[key] = profitFieldValues.profitAnalysisFields[
... ... @@ -199,14 +202,12 @@
199 202 // ? 'UN_LOCKED'
200 203 // : 'LOCKED';
201 204 // });
202   -
203 205 // !isEmpty(reportFieldValues) &&
204 206 // Object.keys(reportFieldValues.reportFields).map((key) => {
205 207 // reportFieldValues.reportFields[key] = reportFieldValues.reportFields[key]
206 208 // ? 'UN_LOCKED'
207 209 // : 'LOCKED';
208 210 // });
209   -
210 211 const values = Object.assign(
211 212 { orderId: id.value },
212 213 { baseFields: baseFieldValues },
... ... @@ -215,9 +216,25 @@
215 216 { trackStageFields: trackFieldValues },
216 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 238 return {
222 239 register,
223 240 schemas,
... ... @@ -227,9 +244,17 @@
227 244 registryInspectForm,
228 245 registerTrackForm,
229 246 handleSubmit,
  247 + handleCloseModal,
  248 + approveReasonModalRegister,
230 249 ROLE,
231 250 role,
232 251 };
233 252 },
234 253 });
235 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 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 96 if (props.role === ROLE.TRACKER) {
88 97 return [
89 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 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 233 // const businessNotDisabledFields = ['customerCode', 'projectNo', 'innerNo'];
234 234 // const trackerNotDisabledFields = [
235 235 // 'customerPo',
... ... @@ -254,7 +254,9 @@
254 254 field: `${item.field}`,
255 255 componentProps: {
256 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 260 // disabled:
259 261 // role.value === ROLE.BUSINESS
260 262 // ? !isFieldNotDisabledForBusiness
... ...
src/views/project/order/ProductProfit.vue
... ... @@ -121,6 +121,7 @@
121 121 import { payDate, checkCreate } from '@/api/project/invoice';
122 122 import type { Dayjs } from 'dayjs';
123 123 import { calculateInnerProfitRatio, exportInnerProfitRatio } from '@/api/project/order';
  124 + import axios from 'axios';
124 125  
125 126 const Input1 = ref('');
126 127 const Input2 = ref();
... ... @@ -153,6 +154,50 @@
153 154 filteredItems.value = data.filteredItems;
154 155 });
155 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 201 closeModal();
157 202 }
158 203 function handleShow(visible: boolean) {
... ...
src/views/project/order/ProductText.vue
... ... @@ -3,7 +3,7 @@
3 3 v-bind="$attrs"
4 4 destroyOnClose
5 5 @register="register"
6   - title="生产指书"
  6 + title="生产指书"
7 7 width="500px"
8 8 :height="80"
9 9 wrapClassName="h-[340px]"
... ... @@ -14,7 +14,7 @@
14 14 v-bind="$attrs"
15 15 destroyOnClose
16 16 @register="register"
17   - title="生产指书"
  17 + title="生产指书"
18 18 width="500px"
19 19 @visible-change="handleShow"
20 20 :footer="null"
... ... @@ -27,7 +27,7 @@
27 27 <div class="showPdf" v-if="isShow2 == true" style="margin-top: 35px; text-align: center">
28 28 <!-- <img src="/pdf.png" /> -->
29 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 31 <EyeOutlined :style="{ fontSize: '20px' }" class="EyeOutlined" @click="handlePdf" />
32 32 </div>
33 33 <div class="bottom">
... ... @@ -83,7 +83,7 @@
83 83 // 运营总监-基本信息,跟单,质检
84 84 return [
85 85 { label: '青岛翱特逸格饰品有限公司', value: '青岛翱特逸格饰品有限公司' },
86   - { label: ' 青岛吉庆天成饰品有限公司', value: '青岛吉庆天成饰品有限公司' },
  86 + { label: '青岛吉庆天成饰品有限公司', value: '青岛吉庆天成饰品有限公司' },
87 87 ];
88 88 });
89 89 const { createMessage } = useMessage();
... ... @@ -173,17 +173,18 @@
173 173 }
174 174 //查看pdf
175 175 function handlePdf() {
176   - window.open(resText.value.produceFile);
  176 + window.open(resText.value.productionUrl);
177 177 }
178 178 //发送按钮
179 179 async function handleExport() {
180 180 const res = await exportProductText({
181 181 productionUrl: resText.value.productionUrl,
182 182 productionDepartment: resText.value.productionDepartment,
  183 + personList: resText.value.personList,
183 184 isSend: true,
184 185 });
185 186 console.log();
186   - success('操作成功,' + res);
  187 + success('操作成功,已发送给生产科、业务员、跟单员');
187 188 closeModal();
188 189 }
189 190 return {
... ...
src/views/project/order/ServiceProfit.vue
... ... @@ -49,18 +49,20 @@
49 49 <tr>
50 50 <td style="border: 1px solid black"></td>
51 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 56 </tr>
57 57 <tr>
58 58 <td style="border: 1px solid black"></td>
59 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 65 /></td>
63   - <td style="border: 1px solid black"><a-date-picker v-model:value="produceEndTime" /></td>
64 66 </tr>
65 67 <tr>
66 68 <td style="border: 1px solid black">客户编码</td>
... ... @@ -70,17 +72,17 @@
70 72 </tr>
71 73 <tr>
72 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 76 <td style="border: 1px solid black"></td>
75 77 </tr>
76 78 <tr>
77 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 81 <td style="border: 1px solid black"></td>
80 82 </tr>
81 83 <tr>
82 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 86 <td style="border: 1px solid black"></td>
85 87 </tr>
86 88 <tr>
... ... @@ -99,37 +101,37 @@
99 101 </tr>
100 102 <tr>
101 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 105 <td style="border: 1px solid black"></td>
104 106 </tr>
105 107 <tr>
106 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 110 <td style="border: 1px solid black"></td>
109 111 </tr>
110 112 <tr>
111 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 115 <td style="border: 1px solid black"></td>
114 116 </tr>
115 117 <tr>
116 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 120 <td style="border: 1px solid black"></td>
119 121 </tr>
120 122 <tr>
121 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 125 <td style="border: 1px solid black"></td>
124 126 </tr>
125 127 <tr>
126 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 130 <td style="border: 1px solid black"></td>
129 131 </tr>
130 132 <tr>
131 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 135 <td style="border: 1px solid black"></td>
134 136 </tr>
135 137 <tr>
... ... @@ -141,32 +143,32 @@
141 143 </tr>
142 144 <tr>
143 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 147 <td style="border: 1px solid black"></td>
146 148 </tr>
147 149 <tr>
148 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 152 <td style="border: 1px solid black"></td>
151 153 </tr>
152 154 <tr>
153 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 157 <td style="border: 1px solid black"></td>
156 158 </tr>
157 159 <tr>
158 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 162 <td style="border: 1px solid black"></td>
161 163 </tr>
162 164 <tr>
163 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 167 <td style="border: 1px solid black"></td>
166 168 </tr>
167 169 <tr>
168 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 172 <td style="border: 1px solid black"></td>
171 173 </tr>
172 174 </tbody>
... ... @@ -178,7 +180,9 @@
178 180 import { computed, ref, toRaw } from 'vue';
179 181 // import { payDate, checkCreate } from '@/api/project/invoice';
180 182 import { calculateBusinessProfit, exportBusinessProfit } from '@/api/project/order';
  183 + import { getList } from '/@/api/sys/config';
181 184 import type { Dayjs } from 'dayjs';
  185 + import axios from 'axios';
182 186  
183 187 const projectStartTime = ref();
184 188 const projectEndTime = ref();
... ... @@ -195,11 +199,14 @@
195 199 const developTotalPrice = ref();
196 200 const copyTotalPrice = ref();
197 201 const packetActualTotalPrice = ref();
198   - const spainRatio = ref();
199   - const chinaRatio = ref();
  202 + const spainRatio = ref(0);
  203 + const chinaRatio = ref(0);
200 204 const actualRmbPrice = ref(0); //实际跟单单价
201 205 const actualPrice = ref(0); //实际跟单单价折算美金
202 206 const actualRatio = ref(6.2); //实际汇率
  207 + const customerTotalPrice = ref(); //客户总价合计
  208 + const actualRatioProfitPrice = ref(); //汇率收益
  209 + const grossProfit = ref(); //毛利润合计
203 210 const actualRatiactualRatioProfitPriceo = ref(); //汇率收益计算
204 211 const chinaRatioProfitPrice = ref(); //中国团队提成比例
205 212 const developProfit = ref(); //研发贸易利润
... ... @@ -222,6 +229,58 @@
222 229 console.log(orderList.value, 565656);
223 230 });
224 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 284 closeModal();
226 285 }
227 286 function handleShow(visible: boolean) {
... ... @@ -237,6 +296,25 @@
237 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 318 async function handleCalculate() {
241 319 const packetCalculatePrice = ref(0);
242 320 const orderCalculateCount = ref(0);
... ... @@ -250,8 +328,32 @@
250 328 actualRmbPrice.value += packetCalculatePrice.value / orderCalculateCount.value;
251 329 });
252 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 357 const res = await calculateBusinessProfit({
256 358 customerCode: customerCode.value,
257 359 projectNo: projectNo.value,
... ... @@ -270,20 +372,23 @@
270 372 });
271 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 393 </script>
289 394 <style scoped>
... ...
src/views/project/order/index.vue
... ... @@ -23,7 +23,7 @@
23 23 <a-button
24 24 :style="{ borderRadius: '5px 5px 5px 5px' }"
25 25 type="link"
26   - @click="checkedKeys = []"
  26 + @click="handleClearChoose"
27 27 size="small"
28 28 >清空</a-button
29 29 >
... ... @@ -38,7 +38,7 @@
38 38 <template v-if="column.key === 'action'">
39 39 <TableAction
40 40 :actions="
41   - role !== ROLE.PRODUCE
  41 + role !== ROLE.PRODUCE && role !== ROLE.FINANCE
42 42 ? [
43 43 {
44 44 // 数据分析没有编辑权限
... ... @@ -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 84 label: '复制',
83 85 // icon: 'ic:outline-delete-outline',
84 86 onClick: handleCopy.bind(null, record),
... ... @@ -111,93 +113,100 @@
111 113 </template>
112 114  
113 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 210 </template>
202 211 </BasicTable>
203 212 <FormDetail
... ... @@ -368,13 +377,20 @@
368 377  
369 378 // type CustomerCodeEntry = [string, number]; // 定义二维数组类型 [customerCode, count]
370 379 // type ProductionDepartmentEntry = [string, number]; // 定义二维数组类型 [productionDepartment, count]
  380 + // type ProjectNoEntry = [string, number]; // 定义二维数组类型 [innerNo, count]
371 381  
372 382 // const selectedCustomCodes = ref<CustomerCodeEntry[]>([]); // 创建一个二维数组的 ref
373 383 // const selectedProductionDepartment = ref<ProductionDepartmentEntry[]>([]); // 创建一个二维数组的 ref
  384 + // const selectedProjectNos = ref<ProjectNoEntry[]>([]); // 创建一个二维数组的 ref
374 385  
375 386 // // 单选处理函数
376 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 394 // selected: boolean,
379 395 // ) {
380 396 // // 查找 customerCode 在 selectedCustomCodes 中的位置
... ... @@ -387,6 +403,11 @@
387 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 411 // if (selected) {
391 412 // // 添加到 checkedKeys
392 413 // checkedKeys.value = [...checkedKeys.value, record.id];
... ... @@ -408,6 +429,15 @@
408 429 // // 如果不存在,添加新项 [productionDepartment, 1]
409 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 441 // } else {
412 442 // // 从 checkedKeys 中移除
413 443 // checkedKeys.value = checkedKeys.value.filter((id) => id !== record.id);
... ... @@ -429,19 +459,127 @@
429 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 568 // console.log('5656Checked Keys:', checkedKeys.value);
435 569 // console.log('5656Selected Customer Codes:', selectedCustomCodes.value);
436 570 // console.log('5656Selected Production Departments:', selectedProductionDepartment.value);
  571 + // console.log('5656Selected projectNos:', selectedProjectNos.value);
437 572 // }
  573 +
438 574 type CustomerCodeEntry = [string, number]; // 定义二维数组类型 [customerCode, count]
439 575 type ProductionDepartmentEntry = [string, number]; // 定义二维数组类型 [productionDepartment, count]
440 576 type ProjectNoEntry = [string, number]; // 定义二维数组类型 [innerNo, count]
  577 + type BusinessPersonEntry = [string, number]; // 定义二维数组类型 [businessPerson, count]
441 578  
442 579 const selectedCustomCodes = ref<CustomerCodeEntry[]>([]); // 创建一个二维数组的 ref
443 580 const selectedProductionDepartment = ref<ProductionDepartmentEntry[]>([]); // 创建一个二维数组的 ref
444 581 const selectedProjectNos = ref<ProjectNoEntry[]>([]); // 创建一个二维数组的 ref
  582 + const selectedBusinessPersons = ref<BusinessPersonEntry[]>([]); // 创建一个二维数组的 ref
445 583  
446 584 // 单选处理函数
447 585 function onSelect(
... ... @@ -449,57 +587,58 @@
449 587 customerCode: string;
450 588 productionDepartment: string;
451 589 projectNo: string;
  590 + businessPerson: string; // 添加 businessPerson 属性
452 591 id: string;
453 592 },
454 593 selected: boolean,
455 594 ) {
456   - // 查找 customerCode 在 selectedCustomCodes 中的位置
457 595 const customerCodeIndex = selectedCustomCodes.value.findIndex(
458 596 ([customerCode]) => customerCode === record.customerCode,
459 597 );
460 598  
461   - // 查找 productionDepartment 在 selectedProductionDepartment 中的位置
462 599 const productionDepartmentIndex = selectedProductionDepartment.value.findIndex(
463 600 ([department]) => department === record.productionDepartment,
464 601 );
465 602  
466   - // 查找 projectNo 在 selectedProjectNos 中的位置
467 603 const projectNoIndex = selectedProjectNos.value.findIndex(
468 604 ([projectNo]) => projectNo === record.projectNo,
469 605 );
470 606  
  607 + const businessPersonIndex = selectedBusinessPersons.value.findIndex(
  608 + ([businessPerson]) => businessPerson === record.businessPerson,
  609 + );
  610 +
471 611 if (selected) {
472   - // 添加到 checkedKeys
473 612 checkedKeys.value = [...checkedKeys.value, record.id];
474 613  
475 614 // 更新 selectedCustomCodes
476 615 if (customerCodeIndex !== -1) {
477   - // 如果已存在,增加计数
478 616 selectedCustomCodes.value[customerCodeIndex][1] += 1;
479 617 } else {
480   - // 如果不存在,添加新项 [customerCode, 1]
481 618 selectedCustomCodes.value.push([record.customerCode, 1]);
482 619 }
483 620  
484 621 // 更新 selectedProductionDepartment
485 622 if (productionDepartmentIndex !== -1) {
486   - // 如果已存在,增加计数
487 623 selectedProductionDepartment.value[productionDepartmentIndex][1] += 1;
488 624 } else {
489   - // 如果不存在,添加新项 [productionDepartment, 1]
490 625 selectedProductionDepartment.value.push([record.productionDepartment, 1]);
491 626 }
492 627  
493 628 // 更新 selectedProjectNos
494 629 if (projectNoIndex !== -1) {
495   - // 如果已存在,增加计数
496 630 selectedProjectNos.value[projectNoIndex][1] += 1;
497 631 } else {
498   - // 如果不存在,添加新项 [projectNo, 1]
499 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 641 } else {
502   - // 从 checkedKeys 中移除
503 642 checkedKeys.value = checkedKeys.value.filter((id) => id !== record.id);
504 643  
505 644 // 更新 selectedCustomCodes
... ... @@ -528,94 +667,33 @@
528 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 689 function onSelectAll(selected: boolean, selectedRows: any[], changeRows: any[]) {
612 690 const changeIds = changeRows.map((item) => item.id);
613 691 const changeCustomerCodes = changeRows.map((item) => item.customerCode);
614 692 const changeProductionDepartments = changeRows.map((item) => item.productionDepartment);
615 693 const changeProjectNos = changeRows.map((item) => item.projectNo);
  694 + const changeBusinessPersons = changeRows.map((item) => item.businessPerson); // 新增处理 businessPerson
616 695  
617 696 if (selected) {
618   - // 添加到 checkedKeys
619 697 checkedKeys.value = [...checkedKeys.value, ...changeIds];
620 698  
621 699 // 更新 selectedCustomCodes
... ... @@ -651,8 +729,17 @@
651 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 742 } else {
655   - // 从 checkedKeys 中移除
656 743 checkedKeys.value = checkedKeys.value.filter((id) => !changeIds.includes(id));
657 744  
658 745 // 更新 selectedCustomCodes
... ... @@ -684,7 +771,7 @@
684 771 });
685 772  
686 773 // 更新 selectedProjectNos
687   - changeInnerNos.forEach((projectNo) => {
  774 + changeProjectNos.forEach((projectNo) => {
688 775 const index = selectedProjectNos.value.findIndex(([no]) => no === projectNo);
689 776 if (index !== -1) {
690 777 if (selectedProjectNos.value[index][1] > 1) {
... ... @@ -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 813 function handleEdit(record, e) {
... ... @@ -820,10 +928,18 @@
820 928 const form = getForm();
821 929 const values = form.getFieldsValue();
822 930 console.log(selectedCustomCodes.value, 5656);
823   - if (selectedCustomCodes.value.length == 0) {
  931 + if (checkedKeys.value.length == 0) {
824 932 error('请选择订单');
825 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 943 openProductModal(true, {
828 944 checkedKeys: checkedKeys.value,
829 945 customers: selectedCustomCodes.value,
... ... @@ -980,6 +1096,7 @@
980 1096 handleDelete,
981 1097 handleServiceProfitModal,
982 1098 handleProductProfitModal,
  1099 + handleClearChoose,
983 1100 selectedCustomCodes,
984 1101 role,
985 1102 ROLE,
... ...
src/views/project/order/tableData.tsx
... ... @@ -161,9 +161,21 @@ export const ORDER_LIST_BASE_FIELDS = [
161 161 {
162 162 field: 'returnOrder',
163 163 component: 'Select',
164   - default: '请选择',
165   - label: '是否返单 ',
  164 + labelWidth: 150,
  165 + label: '是否返单',
166 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 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 719 if (role === ROLE.BUSINESS) {
697 720 return [
... ...
vite.config.ts
... ... @@ -20,7 +20,7 @@ export default defineApplicationConfig({
20 20 server: {
21 21 proxy: {
22 22 '/basic-api/order': {
23   - target: 'http://47.104.8.35:18000',
  23 + target: 'http://47.104.8.35:18001',
24 24 // target: 'http://localhost:8001',
25 25 // target: 'http://39.108.227.113:8000',
26 26 // target: 'http://localhost:8000',
... ... @@ -31,7 +31,7 @@ export default defineApplicationConfig({
31 31 rewrite: (path) => path.replace(new RegExp(`^/basic-api`), ''),
32 32 },
33 33 '/api/localStorage/upload': {
34   - target: 'http://47.104.8.35:18000',
  34 + target: 'http://47.104.8.35:18001',
35 35 // target: 'http://localhost:8001',
36 36 // target: 'http://39.108.227.113:8000',
37 37 // target: '192.168.31.250:18000',
... ...