Commit 4120cdccc84112b144885f0f424aa6cb76ff4838

Authored by
2 parents 4d1d2e7c 13928607

Merge branch 'zwl-develop' into 'develop'

Zwl develop



See merge request !7
src/views/project/config/index.vue
@@ -18,19 +18,19 @@ @@ -18,19 +18,19 @@
18 <Tabs.TabPane key="4" tab="邮件发送配置" v-if="role !== ROLE.FINANCE" 18 <Tabs.TabPane key="4" tab="邮件发送配置" v-if="role !== ROLE.FINANCE"
19 ><EmailPanel 19 ><EmailPanel
20 /></Tabs.TabPane> 20 /></Tabs.TabPane>
21 - <Tabs.TabPane key="5" tab="最后汇款日期"> 21 + <Tabs.TabPane key="5" tab="最后汇款日期" v-if="role !== ROLE.FINANCE">
22 <TablePanel :searchInfo="{ relationCode: 'orderHodTime' }" :column="5" /> 22 <TablePanel :searchInfo="{ relationCode: 'orderHodTime' }" :column="5" />
23 </Tabs.TabPane> 23 </Tabs.TabPane>
24 - <Tabs.TabPane key="6" tab="提成成本配置"> 24 + <Tabs.TabPane key="6" tab="提成成本配置" v-if="role !== ROLE.FINANCE">
25 <TablePanel :searchInfo="{ relationCode: 'costSettingItem', relationName: currentYear }" :column="6" /> 25 <TablePanel :searchInfo="{ relationCode: 'costSettingItem', relationName: currentYear }" :column="6" />
26 </Tabs.TabPane> 26 </Tabs.TabPane>
27 <Tabs.TabPane key="7" tab="销售额配置" v-if="role !== ROLE.FINANCE"> 27 <Tabs.TabPane key="7" tab="销售额配置" v-if="role !== ROLE.FINANCE">
28 <TablePanel :searchInfo="{ relationCode: 'salesAmount' }" :column="7" /> 28 <TablePanel :searchInfo="{ relationCode: 'salesAmount' }" :column="7" />
29 </Tabs.TabPane> 29 </Tabs.TabPane>
30 - <Tabs.TabPane key="8" tab="生产科应付日期"> 30 + <Tabs.TabPane key="8" tab="生产科应付日期" v-if="role !== ROLE.FINANCE">
31 <TablePanel :searchInfo="{ relationCode: 'produHodTime' }" :column="8" /> 31 <TablePanel :searchInfo="{ relationCode: 'produHodTime' }" :column="8" />
32 </Tabs.TabPane> 32 </Tabs.TabPane>
33 - <Tabs.TabPane key="9" tab="生产科固定成本"> 33 + <Tabs.TabPane key="9" tab="生产科固定成本" v-if="role !== ROLE.FINANCE">
34 <TablePanel :searchInfo="{ relationCode: 'ProduceSettingItem', relationName: currentYear }" :column="9" /> 34 <TablePanel :searchInfo="{ relationCode: 'ProduceSettingItem', relationName: currentYear }" :column="9" />
35 </Tabs.TabPane> 35 </Tabs.TabPane>
36 <Tabs.TabPane key="10" tab="客户公司" v-if="role !== ROLE.FINANCE"> 36 <Tabs.TabPane key="10" tab="客户公司" v-if="role !== ROLE.FINANCE">
src/views/project/finance/financeList/index.vue
@@ -25,7 +25,7 @@ @@ -25,7 +25,7 @@
25 <a-button 25 <a-button
26 type="primary" 26 type="primary"
27 danger 27 danger
28 - v-if="role == ROLE.ADMIN || role == ROLE.FINANCE" 28 + v-if="role == ROLE.ADMIN"
29 :style="{ borderRadius: '5px 5px 5px 5px' }" 29 :style="{ borderRadius: '5px 5px 5px 5px' }"
30 > 30 >
31 设置为已完成 31 设置为已完成
src/views/project/finance/financeProfit/ProductProfit/InnerData/data.tsx
@@ -9,6 +9,8 @@ import { useOrderInfo } from &#39;/@/hooks/component/order&#39;; @@ -9,6 +9,8 @@ import { useOrderInfo } from &#39;/@/hooks/component/order&#39;;
9 9
10 const innerNoOptions = ref([]); 10 const innerNoOptions = ref([]);
11 const projectNoOptions = ref([]); 11 const projectNoOptions = ref([]);
  12 +const allProjectNoOptions = ref([]);
  13 +export { allProjectNoOptions };
12 const orderStore = useOrderStoreWithOut(); 14 const orderStore = useOrderStoreWithOut();
13 const { 15 const {
14 customerCode, 16 customerCode,
@@ -38,11 +40,10 @@ export const searchFormSchema = [ @@ -38,11 +40,10 @@ export const searchFormSchema = [
38 showSearch: true, 40 showSearch: true,
39 mode: 'multiple', 41 mode: 'multiple',
40 onSearch: async (value: any) => { 42 onSearch: async (value: any) => {
41 - projectNoOptions.value = await queryNoOptions('projectNo', value); 43 + const result = await queryNoOptions('projectNo', value);
  44 + projectNoOptions.value = result;
  45 + allProjectNoOptions.value = result;
42 }, 46 },
43 - // onSearch: async (value: any) => {  
44 - // projectNoOptions.value = await queryNoOptions('projectNo', value);  
45 - // },  
46 }, 47 },
47 }, 48 },
48 { 49 {
src/views/project/finance/financeProfit/ProductProfit/InnerData/index.vue
1 <template> 1 <template>
2 <div> 2 <div>
3 - <BasicTable @register="registerTable" :bordered="true"> 3 + <BasicTable @register="registerTable" :bordered="true" @field-value-change="handleFieldValueChange">
4 <template #headerTop> 4 <template #headerTop>
5 <a-alert type="info" show-icon> 5 <a-alert type="info" show-icon>
6 <template #message> 6 <template #message>
@@ -46,6 +46,11 @@ @@ -46,6 +46,11 @@
46 :style="{ borderRadius: '5px 5px 5px 5px' }" 46 :style="{ borderRadius: '5px 5px 5px 5px' }"
47 >导出</a-button 47 >导出</a-button
48 > 48 >
  49 + <a-button
  50 + type="primary"
  51 + @click="handleAllProjectNoQuery"
  52 + style="margin-left: 8px;position: fixed;right: 29%;top: 107.5px;"
  53 + >全选</a-button>
49 </template> 54 </template>
50 </BasicTable> 55 </BasicTable>
51 <!-- <BasicModal 56 <!-- <BasicModal
@@ -68,7 +73,7 @@ @@ -68,7 +73,7 @@
68 <script setup lang="ts"> 73 <script setup lang="ts">
69 import { BasicTable, useTable, TableAction } from '/@/components/Table'; 74 import { BasicTable, useTable, TableAction } from '/@/components/Table';
70 import { getInnerProfit, setInnerStatus } from '@/api/project/invoice'; 75 import { getInnerProfit, setInnerStatus } from '@/api/project/invoice';
71 - import { searchFormSchema, COLUMNS } from './data'; 76 + import { searchFormSchema, COLUMNS, allProjectNoOptions } from './data';
72 import { BasicModal, useModal } from '/@/components/Modal'; 77 import { BasicModal, useModal } from '/@/components/Modal';
73 import { useMessage } from '/@/hooks/web/useMessage'; 78 import { useMessage } from '/@/hooks/web/useMessage';
74 import { onMounted, ref, computed } from 'vue'; 79 import { onMounted, ref, computed } from 'vue';
@@ -111,11 +116,47 @@ @@ -111,11 +116,47 @@
111 message.value = ''; 116 message.value = '';
112 } 117 }
113 }; 118 };
114 - const [registerTable, { reload, setSelectedRowKeys, getForm }] = useTable({ 119 + const [registerTable, { reload, getSelectRowKeys, getDataSource, setSelectedRowKeys, setProps, getForm }] = useTable({
  120 + title: '',
115 api: getInnerProfit, 121 api: getInnerProfit,
116 bordered: true, 122 bordered: true,
117 columns: COLUMNS, 123 columns: COLUMNS,
118 rowKey: 'orderId', 124 rowKey: 'orderId',
  125 + formConfig: {
  126 + labelWidth: 120,
  127 + schemas: searchFormSchema,
  128 + autoSubmitOnEnter: true,
  129 + resetFunc: async () => {
  130 + localStorage.removeItem('isAllSelected');
  131 + },
  132 + },
  133 + // 处理查询参数,确保项目号数组正确传递
  134 + handleSearchInfoFn: (searchInfo) => {
  135 + // 获取表单实例
  136 + const formInstance = getForm();
  137 + if (formInstance) {
  138 + const formValues = formInstance.getFieldsValue();
  139 +
  140 + // 强制覆盖searchInfo,确保使用表单中的值
  141 + if (formValues.projectNo && formValues.projectNo.length > 0) {
  142 + // 确保传递的是数组而不是Proxy对象,并去重
  143 + const projectNoArray = [...new Set(formValues.projectNo)];
  144 + // 强制覆盖,不使用原始值
  145 + searchInfo = {
  146 + ...searchInfo,
  147 + projectNo: projectNoArray
  148 + };
  149 + } else {
  150 + // 如果表单中没有项目号,清空查询条件
  151 + searchInfo = {
  152 + ...searchInfo,
  153 + projectNo: []
  154 + };
  155 + }
  156 + }
  157 +
  158 + return searchInfo;
  159 + },
119 customRow: () => { 160 customRow: () => {
120 return { 161 return {
121 onClick: (e) => { 162 onClick: (e) => {
@@ -133,11 +174,6 @@ @@ -133,11 +174,6 @@
133 onSelectAll: onSelectAll, 174 onSelectAll: onSelectAll,
134 checkStrictly: true, 175 checkStrictly: true,
135 }, 176 },
136 - formConfig: {  
137 - labelWidth: 120,  
138 - schemas: searchFormSchema,  
139 - autoSubmitOnEnter: true,  
140 - },  
141 useSearchForm: true, 177 useSearchForm: true,
142 showTableSetting: true, 178 showTableSetting: true,
143 showIndexColumn: false, 179 showIndexColumn: false,
@@ -485,5 +521,75 @@ @@ -485,5 +521,75 @@
485 } 521 }
486 setSelectedRowKeys(checkedKeys.value as any); 522 setSelectedRowKeys(checkedKeys.value as any);
487 } 523 }
  524 +
  525 + function handleAllProjectNoQuery() {
  526 + // 检查是否有项目号选项
  527 + if (!allProjectNoOptions.value || allProjectNoOptions.value.length === 0) {
  528 + createMessage.warn('没有可查询的项目号!');
  529 + return;
  530 + }
  531 +
  532 + // 获取所有项目号的value值
  533 + const allProjectNos = allProjectNoOptions.value.map(item => {
  534 + // 处理不同的数据结构
  535 + if (typeof item === 'string') {
  536 + return item;
  537 + } else if (item && typeof item === 'object' && 'value' in item) {
  538 + return item.value;
  539 + } else if (item && typeof item === 'object' && 'label' in item) {
  540 + return item.label;
  541 + }
  542 + return item;
  543 + }).filter(Boolean); // 过滤掉空值
  544 +
  545 + if (allProjectNos.length === 0) {
  546 + createMessage.warn('没有有效的项目号!');
  547 + return;
  548 + }
  549 +
  550 + try {
  551 + // 提示用户全选成功
  552 + createMessage.success(`已全选 ${allProjectNos.length} 个项目号`);
  553 +
  554 + // 获取表单实例并设置表单值,将项目号填入搜索框
  555 + const formInstance = getForm();
  556 + if (formInstance && formInstance.setFieldsValue) {
  557 + formInstance.setFieldsValue({
  558 + projectNo: allProjectNos
  559 + });
  560 + }
  561 +
  562 + // 将allProjectNoOptions更新为已勾选的项目号数组,这样用户取消勾选时数组会同步更新
  563 + allProjectNoOptions.value = allProjectNos.map(projectNo => ({
  564 + label: projectNo,
  565 + value: projectNo
  566 + }));
  567 +
  568 + // 标记为全选状态
  569 + localStorage.setItem('isAllSelected', 'true');
  570 + } catch (error) {
  571 + console.error('全选失败:', error);
  572 + createMessage.error('全选失败,请检查网络连接!');
  573 + }
  574 + }
  575 +
  576 + // 监听表单字段变化
  577 + function handleFieldValueChange(field: string, value: any) {
  578 + // 如果是项目号字段变化且处于全选状态,同步更新查询条件
  579 + if (field === 'projectNo' && localStorage.getItem('isAllSelected') === 'true') {
  580 + // 确保value是数组格式,并去重
  581 + const projectNoArray = Array.isArray(value) ? [...new Set(value)] : [];
  582 +
  583 + // 强制重新加载表格,使用新的查询条件
  584 + reload({
  585 + searchInfo: {
  586 + projectNo: projectNoArray
  587 + }
  588 + });
  589 +
  590 + // 同时更新detailProjectNoKeys数组
  591 + detailProjectNoKeys.value = projectNoArray;
  592 + }
  593 + }
488 </script> 594 </script>
489 <style></style> 595 <style></style>
src/views/project/finance/financeProfit/ProductProfit/InnerProduce/data.tsx
@@ -27,6 +27,8 @@ const userStore = useUserStoreWithOut(); @@ -27,6 +27,8 @@ const userStore = useUserStoreWithOut();
27 // ]; 27 // ];
28 const innerNoOptions = ref([]); 28 const innerNoOptions = ref([]);
29 const projectNoOptions = ref([]); 29 const projectNoOptions = ref([]);
  30 +const allProjectNoOptions = ref([]);
  31 +export { allProjectNoOptions };
30 const orderStore = useOrderStoreWithOut(); 32 const orderStore = useOrderStoreWithOut();
31 const { 33 const {
32 customerCode, 34 customerCode,
@@ -56,11 +58,10 @@ export const searchFormSchema = [ @@ -56,11 +58,10 @@ export const searchFormSchema = [
56 showSearch: true, 58 showSearch: true,
57 mode: 'multiple', 59 mode: 'multiple',
58 onSearch: async (value: any) => { 60 onSearch: async (value: any) => {
59 - projectNoOptions.value = await queryNoOptions('projectNo', value); 61 + const result = await queryNoOptions('projectNo', value);
  62 + projectNoOptions.value = result;
  63 + allProjectNoOptions.value = result;
60 }, 64 },
61 - // onSearch: async (value: any) => {  
62 - // projectNoOptions.value = await queryNoOptions('projectNo', value);  
63 - // },  
64 }, 65 },
65 }, 66 },
66 { 67 {
src/views/project/finance/financeProfit/ProductProfit/InnerProduce/index.vue
1 <template> 1 <template>
2 <div> 2 <div>
3 - <BasicTable @register="registerTable" :bordered="true"> 3 + <BasicTable @register="registerTable" :bordered="true" @field-value-change="handleFieldValueChange">
4 <template #headerTop> 4 <template #headerTop>
5 <a-alert type="info" show-icon> 5 <a-alert type="info" show-icon>
6 <template #message> 6 <template #message>
@@ -49,6 +49,11 @@ @@ -49,6 +49,11 @@
49 :style="{ borderRadius: '5px 5px 5px 5px' }" 49 :style="{ borderRadius: '5px 5px 5px 5px' }"
50 >导出</a-button 50 >导出</a-button
51 > 51 >
  52 + <a-button
  53 + type="primary"
  54 + @click="handleAllProjectNoQuery"
  55 + style="margin-left: 8px;position: fixed;right: 29%;top: 107.5px;"
  56 + >全选</a-button>
52 </template> 57 </template>
53 </BasicTable> 58 </BasicTable>
54 <!-- <BasicModal 59 <!-- <BasicModal
@@ -71,7 +76,7 @@ @@ -71,7 +76,7 @@
71 <script setup lang="ts"> 76 <script setup lang="ts">
72 import { BasicTable, useTable, TableAction } from '/@/components/Table'; 77 import { BasicTable, useTable, TableAction } from '/@/components/Table';
73 import { getInnerProduceProfit, setInnerProfitSetStatus } from '@/api/project/invoice'; 78 import { getInnerProduceProfit, setInnerProfitSetStatus } from '@/api/project/invoice';
74 - import { searchFormSchema, COLUMNS } from './data'; 79 + import { searchFormSchema, COLUMNS, allProjectNoOptions } from './data';
75 import { BasicModal, useModal } from '/@/components/Modal'; 80 import { BasicModal, useModal } from '/@/components/Modal';
76 import { useMessage } from '/@/hooks/web/useMessage'; 81 import { useMessage } from '/@/hooks/web/useMessage';
77 import { onMounted, ref, computed } from 'vue'; 82 import { onMounted, ref, computed } from 'vue';
@@ -110,11 +115,47 @@ @@ -110,11 +115,47 @@
110 message.value = ''; 115 message.value = '';
111 } 116 }
112 }; 117 };
113 - const [registerTable, { reload, setSelectedRowKeys }] = useTable({ 118 + const [registerTable, { reload, getSelectRowKeys, getDataSource, setSelectedRowKeys, setProps, getForm }] = useTable({
  119 + title: '',
114 api: getInnerProduceProfit, 120 api: getInnerProduceProfit,
115 bordered: true, 121 bordered: true,
116 columns: COLUMNS, 122 columns: COLUMNS,
117 clickToRowSelect: false, 123 clickToRowSelect: false,
  124 + formConfig: {
  125 + labelWidth: 120,
  126 + schemas: searchFormSchema,
  127 + autoSubmitOnEnter: true,
  128 + resetFunc: async () => {
  129 + localStorage.removeItem('isAllSelected');
  130 + },
  131 + },
  132 + // 处理查询参数,确保项目号数组正确传递
  133 + handleSearchInfoFn: (searchInfo) => {
  134 + // 获取表单实例
  135 + const formInstance = getForm();
  136 + if (formInstance) {
  137 + const formValues = formInstance.getFieldsValue();
  138 +
  139 + // 强制覆盖searchInfo,确保使用表单中的值
  140 + if (formValues.projectNo && formValues.projectNo.length > 0) {
  141 + // 确保传递的是数组而不是Proxy对象,并去重
  142 + const projectNoArray = [...new Set(formValues.projectNo)];
  143 + // 强制覆盖,不使用原始值
  144 + searchInfo = {
  145 + ...searchInfo,
  146 + projectNo: projectNoArray
  147 + };
  148 + } else {
  149 + // 如果表单中没有项目号,清空查询条件
  150 + searchInfo = {
  151 + ...searchInfo,
  152 + projectNo: []
  153 + };
  154 + }
  155 + }
  156 +
  157 + return searchInfo;
  158 + },
118 rowKey: (record) => record.projectNoPrefix || record.id || record.serialNumber, 159 rowKey: (record) => record.projectNoPrefix || record.id || record.serialNumber,
119 rowSelection: { 160 rowSelection: {
120 type: 'checkbox', 161 type: 'checkbox',
@@ -122,11 +163,6 @@ @@ -122,11 +163,6 @@
122 onSelect: onSelect, 163 onSelect: onSelect,
123 onSelectAll: onSelectAll, 164 onSelectAll: onSelectAll,
124 }, 165 },
125 - formConfig: {  
126 - labelWidth: 120,  
127 - schemas: searchFormSchema,  
128 - autoSubmitOnEnter: true,  
129 - },  
130 useSearchForm: true, 166 useSearchForm: true,
131 showTableSetting: true, 167 showTableSetting: true,
132 showIndexColumn: false, 168 showIndexColumn: false,
@@ -408,5 +444,75 @@ @@ -408,5 +444,75 @@
408 handleClearChoose(); 444 handleClearChoose();
409 reload(); 445 reload();
410 } 446 }
  447 +
  448 + function handleAllProjectNoQuery() {
  449 + // 检查是否有项目号选项
  450 + if (!allProjectNoOptions.value || allProjectNoOptions.value.length === 0) {
  451 + createMessage.warn('没有可查询的项目号!');
  452 + return;
  453 + }
  454 +
  455 + // 获取所有项目号的value值
  456 + const allProjectNos = allProjectNoOptions.value.map(item => {
  457 + // 处理不同的数据结构
  458 + if (typeof item === 'string') {
  459 + return item;
  460 + } else if (item && typeof item === 'object' && 'value' in item) {
  461 + return item.value;
  462 + } else if (item && typeof item === 'object' && 'label' in item) {
  463 + return item.label;
  464 + }
  465 + return item;
  466 + }).filter(Boolean); // 过滤掉空值
  467 +
  468 + if (allProjectNos.length === 0) {
  469 + createMessage.warn('没有有效的项目号!');
  470 + return;
  471 + }
  472 +
  473 + try {
  474 + // 提示用户全选成功
  475 + createMessage.success(`已全选 ${allProjectNos.length} 个项目号`);
  476 +
  477 + // 获取表单实例并设置表单值,将项目号填入搜索框
  478 + const formInstance = getForm();
  479 + if (formInstance && formInstance.setFieldsValue) {
  480 + formInstance.setFieldsValue({
  481 + projectNo: allProjectNos
  482 + });
  483 + }
  484 +
  485 + // 将allProjectNoOptions更新为已勾选的项目号数组,这样用户取消勾选时数组会同步更新
  486 + allProjectNoOptions.value = allProjectNos.map(projectNo => ({
  487 + label: projectNo,
  488 + value: projectNo
  489 + }));
  490 +
  491 + // 标记为全选状态
  492 + localStorage.setItem('isAllSelected', 'true');
  493 + } catch (error) {
  494 + console.error('全选失败:', error);
  495 + createMessage.error('全选失败,请检查网络连接!');
  496 + }
  497 + }
  498 +
  499 + // 监听表单字段变化
  500 + function handleFieldValueChange(field: string, value: any) {
  501 + // 如果是项目号字段变化且处于全选状态,同步更新查询条件
  502 + if (field === 'projectNo' && localStorage.getItem('isAllSelected') === 'true') {
  503 + // 确保value是数组格式,并去重
  504 + const projectNoArray = Array.isArray(value) ? [...new Set(value)] : [];
  505 +
  506 + // 强制重新加载表格,使用新的查询条件
  507 + reload({
  508 + searchInfo: {
  509 + projectNo: projectNoArray
  510 + }
  511 + });
  512 +
  513 + // 同时更新detailProjectNoKeys数组
  514 + detailProjectNoKeys.value = projectNoArray;
  515 + }
  516 + }
411 </script> 517 </script>
412 <style></style> 518 <style></style>
src/views/project/finance/financeProfit/ServiceProfit/PackageProfit/data.tsx
@@ -9,6 +9,8 @@ import { useOrderInfo } from &#39;/@/hooks/component/order&#39;; @@ -9,6 +9,8 @@ import { useOrderInfo } from &#39;/@/hooks/component/order&#39;;
9 9
10 const innerNoOptions = ref([]); 10 const innerNoOptions = ref([]);
11 const projectNoOptions = ref([]); 11 const projectNoOptions = ref([]);
  12 +const allProjectNoOptions = ref([]);
  13 +export { allProjectNoOptions };
12 const orderStore = useOrderStoreWithOut(); 14 const orderStore = useOrderStoreWithOut();
13 const { 15 const {
14 customerCode, 16 customerCode,
@@ -38,11 +40,10 @@ export const searchFormSchema = [ @@ -38,11 +40,10 @@ export const searchFormSchema = [
38 showSearch: true, 40 showSearch: true,
39 mode: 'multiple', 41 mode: 'multiple',
40 onSearch: async (value: any) => { 42 onSearch: async (value: any) => {
41 - projectNoOptions.value = await queryNoOptions('projectNo', value); 43 + const result = await queryNoOptions('projectNo', value);
  44 + projectNoOptions.value = result;
  45 + allProjectNoOptions.value = result;
42 }, 46 },
43 - // onSearch: async (value: any) => {  
44 - // projectNoOptions.value = await queryNoOptions('projectNo', value);  
45 - // },  
46 }, 47 },
47 }, 48 },
48 { 49 {
src/views/project/finance/financeProfit/ServiceProfit/PackageProfit/index.vue
1 <template> 1 <template>
2 <div> 2 <div>
3 - <BasicTable @register="registerTable" :bordered="true"> 3 + <BasicTable @register="registerTable" :bordered="true" @field-value-change="handleFieldValueChange">
4 <template #headerTop> 4 <template #headerTop>
5 <a-alert type="info" show-icon> 5 <a-alert type="info" show-icon>
6 <template #message> 6 <template #message>
@@ -49,6 +49,11 @@ @@ -49,6 +49,11 @@
49 :style="{ borderRadius: '5px 5px 5px 5px' }" 49 :style="{ borderRadius: '5px 5px 5px 5px' }"
50 >导出</a-button 50 >导出</a-button
51 > 51 >
  52 + <a-button
  53 + type="primary"
  54 + @click="handleAllProjectNoQuery"
  55 + style="margin-left: 8px;position: fixed;right: 29%;top: 107.5px;"
  56 + >全选</a-button>
52 </template> 57 </template>
53 </BasicTable> 58 </BasicTable>
54 <!-- <BasicModal 59 <!-- <BasicModal
@@ -71,7 +76,7 @@ @@ -71,7 +76,7 @@
71 <script setup lang="ts"> 76 <script setup lang="ts">
72 import { BasicTable, useTable, TableAction } from '/@/components/Table'; 77 import { BasicTable, useTable, TableAction } from '/@/components/Table';
73 import { getPackageProfit, setPackStatus } from '@/api/project/invoice'; 78 import { getPackageProfit, setPackStatus } from '@/api/project/invoice';
74 - import { searchFormSchema, COLUMNS } from './data'; 79 + import { searchFormSchema, COLUMNS, allProjectNoOptions } from './data';
75 import { BasicModal, useModal } from '/@/components/Modal'; 80 import { BasicModal, useModal } from '/@/components/Modal';
76 import { useMessage } from '/@/hooks/web/useMessage'; 81 import { useMessage } from '/@/hooks/web/useMessage';
77 import { onMounted, ref, computed } from 'vue'; 82 import { onMounted, ref, computed } from 'vue';
@@ -115,16 +120,48 @@ @@ -115,16 +120,48 @@
115 message.value = ''; 120 message.value = '';
116 } 121 }
117 }; 122 };
118 - const [registerTable, { reload, setSelectedRowKeys, getForm }] = useTable({ 123 + const [registerTable, { reload, getSelectRowKeys, getDataSource, setSelectedRowKeys, setProps, getForm }] = useTable({
  124 + title: '',
119 api: getPackageProfit, 125 api: getPackageProfit,
120 bordered: true, 126 bordered: true,
121 columns: COLUMNS, 127 columns: COLUMNS,
122 - rowKey: (record) => record.orderId, 128 + clickToRowSelect: false,
123 formConfig: { 129 formConfig: {
124 labelWidth: 120, 130 labelWidth: 120,
125 schemas: searchFormSchema, 131 schemas: searchFormSchema,
126 autoSubmitOnEnter: true, 132 autoSubmitOnEnter: true,
  133 + resetFunc: async () => {
  134 + localStorage.removeItem('isAllSelected');
  135 + },
  136 + },
  137 + // 处理查询参数,确保项目号数组正确传递
  138 + handleSearchInfoFn: (searchInfo) => {
  139 + // 获取表单实例
  140 + const formInstance = getForm();
  141 + if (formInstance) {
  142 + const formValues = formInstance.getFieldsValue();
  143 +
  144 + // 强制覆盖searchInfo,确保使用表单中的值
  145 + if (formValues.projectNo && formValues.projectNo.length > 0) {
  146 + // 确保传递的是数组而不是Proxy对象,并去重
  147 + const projectNoArray = [...new Set(formValues.projectNo)];
  148 + // 强制覆盖,不使用原始值
  149 + searchInfo = {
  150 + ...searchInfo,
  151 + projectNo: projectNoArray
  152 + };
  153 + } else {
  154 + // 如果表单中没有项目号,清空查询条件
  155 + searchInfo = {
  156 + ...searchInfo,
  157 + projectNo: []
  158 + };
  159 + }
  160 + }
  161 +
  162 + return searchInfo;
127 }, 163 },
  164 + rowKey: (record) => record.orderId,
128 // Add custom row props to prevent selection when clicking rows 165 // Add custom row props to prevent selection when clicking rows
129 customRow: () => { 166 customRow: () => {
130 return { 167 return {
@@ -479,5 +516,75 @@ @@ -479,5 +516,75 @@
479 } 516 }
480 setSelectedRowKeys(checkedKeys.value as any); 517 setSelectedRowKeys(checkedKeys.value as any);
481 } 518 }
  519 +
  520 + function handleAllProjectNoQuery() {
  521 + // 检查是否有项目号选项
  522 + if (!allProjectNoOptions.value || allProjectNoOptions.value.length === 0) {
  523 + createMessage.warn('没有可查询的项目号!');
  524 + return;
  525 + }
  526 +
  527 + // 获取所有项目号的value值
  528 + const allProjectNos = allProjectNoOptions.value.map(item => {
  529 + // 处理不同的数据结构
  530 + if (typeof item === 'string') {
  531 + return item;
  532 + } else if (item && typeof item === 'object' && 'value' in item) {
  533 + return item.value;
  534 + } else if (item && typeof item === 'object' && 'label' in item) {
  535 + return item.label;
  536 + }
  537 + return item;
  538 + }).filter(Boolean); // 过滤掉空值
  539 +
  540 + if (allProjectNos.length === 0) {
  541 + createMessage.warn('没有有效的项目号!');
  542 + return;
  543 + }
  544 +
  545 + try {
  546 + // 提示用户全选成功
  547 + createMessage.success(`已全选 ${allProjectNos.length} 个项目号`);
  548 +
  549 + // 获取表单实例并设置表单值,将项目号填入搜索框
  550 + const formInstance = getForm();
  551 + if (formInstance && formInstance.setFieldsValue) {
  552 + formInstance.setFieldsValue({
  553 + projectNo: allProjectNos
  554 + });
  555 + }
  556 +
  557 + // 将allProjectNoOptions更新为已勾选的项目号数组,这样用户取消勾选时数组会同步更新
  558 + allProjectNoOptions.value = allProjectNos.map(projectNo => ({
  559 + label: projectNo,
  560 + value: projectNo
  561 + }));
  562 +
  563 + // 标记为全选状态
  564 + localStorage.setItem('isAllSelected', 'true');
  565 + } catch (error) {
  566 + console.error('全选失败:', error);
  567 + createMessage.error('全选失败,请检查网络连接!');
  568 + }
  569 + }
  570 +
  571 + // 监听表单字段变化
  572 + function handleFieldValueChange(field: string, value: any) {
  573 + // 如果是项目号字段变化且处于全选状态,同步更新查询条件
  574 + if (field === 'projectNo' && localStorage.getItem('isAllSelected') === 'true') {
  575 + // 确保value是数组格式,并去重
  576 + const projectNoArray = Array.isArray(value) ? [...new Set(value)] : [];
  577 +
  578 + // 强制重新加载表格,使用新的查询条件
  579 + reload({
  580 + searchInfo: {
  581 + projectNo: projectNoArray
  582 + }
  583 + });
  584 +
  585 + // 同时更新detailProjectNoKeys数组
  586 + detailProjectNoKeys.value = projectNoArray;
  587 + }
  588 + }
482 </script> 589 </script>
483 <style></style> 590 <style></style>
src/views/project/finance/financeProfit/ServiceProfit/ServiceProfit/FinanceEdit.vue
@@ -25,10 +25,24 @@ @@ -25,10 +25,24 @@
25 /> 25 />
26 <div style="margin: 16px 0"></div> 26 <div style="margin: 16px 0"></div>
27 <div style="font-size: 15px">项目开始时间</div> 27 <div style="font-size: 15px">项目开始时间</div>
28 - <a-date-picker v-model:value="input3" :disabled="status3 === 'LOCKED'" auto-size /> 28 + <a-date-picker
  29 + v-model:value="input3"
  30 + :disabled="status3 === 'LOCKED'"
  31 + auto-size
  32 + placeholder="请选择项目开始时间"
  33 + format="YYYY-MM-DD"
  34 + value-format="YYYY-MM-DD"
  35 + />
29 <div style="margin: 16px 0"></div> 36 <div style="margin: 16px 0"></div>
30 <div style="font-size: 15px">项目结束时间</div> 37 <div style="font-size: 15px">项目结束时间</div>
31 - <a-date-picker v-model:value="input4" :disabled="status4 === 'LOCKED'" auto-size /> 38 + <a-date-picker
  39 + v-model:value="input4"
  40 + :disabled="status4 === 'LOCKED'"
  41 + auto-size
  42 + placeholder="请选择项目结束时间"
  43 + format="YYYY-MM-DD"
  44 + value-format="YYYY-MM-DD"
  45 + />
32 <div style="margin: 16px 0"></div> 46 <div style="margin: 16px 0"></div>
33 <div style="font-size: 15px">西班牙已发提成¥</div> 47 <div style="font-size: 15px">西班牙已发提成¥</div>
34 <a-input 48 <a-input
@@ -59,11 +73,14 @@ @@ -59,11 +73,14 @@
59 import { defineComponent, ref, computed, unref, toRaw, reactive } from 'vue'; 73 import { defineComponent, ref, computed, unref, toRaw, reactive } from 'vue';
60 import { getServiceEdit } from '@/api/project/invoice'; 74 import { getServiceEdit } from '@/api/project/invoice';
61 import { useMessage } from '/@/hooks/web/useMessage'; 75 import { useMessage } from '/@/hooks/web/useMessage';
  76 + import { useUserStoreWithOut } from '/@/store/modules/user';
62 import { ROLE } from './type.d'; 77 import { ROLE } from './type.d';
63 import type { Dayjs } from 'dayjs'; 78 import type { Dayjs } from 'dayjs';
64 import dayjs from 'dayjs'; 79 import dayjs from 'dayjs';
65 80
66 const emit = defineEmits(['success']); 81 const emit = defineEmits(['success']);
  82 + const userStore = useUserStoreWithOut();
  83 + const user = userStore.getUserInfo;
67 const role = computed(() => { 84 const role = computed(() => {
68 return user?.roleSmallVO?.code; 85 return user?.roleSmallVO?.code;
69 }); 86 });
@@ -141,8 +158,8 @@ @@ -141,8 +158,8 @@
141 158
142 const input1 = ref(); 159 const input1 = ref();
143 const input2 = ref(); 160 const input2 = ref();
144 - const input3 = ref();  
145 - const input4 = ref(); 161 + const input3 = ref<Dayjs | null>(null);
  162 + const input4 = ref<Dayjs | null>(null);
146 163
147 const input5 = ref(); 164 const input5 = ref();
148 const id = ref(); 165 const id = ref();
@@ -177,11 +194,23 @@ @@ -177,11 +194,23 @@
177 status5.value = data?.data?.lockFields?.paidRmbCommission; 194 status5.value = data?.data?.lockFields?.paidRmbCommission;
178 } 195 }
179 id.value = data?.data?.projectNoPrefix; 196 id.value = data?.data?.projectNoPrefix;
180 - input1.value = data?.data?.developmentCopyRmbTotalPrice.toFixed(2);  
181 - input2.value = data?.data?.spainPaidRmbCommission.toFixed(2);  
182 - input3.value = dayjs(formatDateToDateOnly(data?.data?.projectStartTime));  
183 - input4.value = dayjs(formatDateToDateOnly(data?.data?.projectEndTime));  
184 - input5.value = data?.data?.paidRmbCommission.toFixed(2); 197 + input1.value = data?.data?.developmentCopyRmbTotalPrice?.toFixed(2) || '';
  198 + input2.value = data?.data?.spainPaidRmbCommission?.toFixed(2) || '';
  199 +
  200 + // 确保日期值正确设置
  201 + if (data?.data?.projectStartTime) {
  202 + input3.value = dayjs(formatDateToDateOnly(data.data.projectStartTime));
  203 + } else {
  204 + input3.value = null;
  205 + }
  206 +
  207 + if (data?.data?.projectEndTime) {
  208 + input4.value = dayjs(formatDateToDateOnly(data.data.projectEndTime));
  209 + } else {
  210 + input4.value = null;
  211 + }
  212 +
  213 + input5.value = data?.data?.paidRmbCommission?.toFixed(2) || '';
185 214
186 resetFields(); 215 resetFields();
187 setDrawerProps({ confirmLoading: false }); 216 setDrawerProps({ confirmLoading: false });
@@ -217,8 +246,8 @@ @@ -217,8 +246,8 @@
217 if (!visible) { 246 if (!visible) {
218 input1.value = ''; 247 input1.value = '';
219 input2.value = ''; 248 input2.value = '';
220 - input3.value = '';  
221 - input4.value = ''; 249 + input3.value = null;
  250 + input4.value = null;
222 input5.value = ''; 251 input5.value = '';
223 } 252 }
224 } 253 }
src/views/project/finance/financeProfit/ServiceProfit/ServiceProfit/data.tsx
@@ -27,6 +27,8 @@ const userStore = useUserStoreWithOut(); @@ -27,6 +27,8 @@ const userStore = useUserStoreWithOut();
27 // ]; 27 // ];
28 const innerNoOptions = ref([]); 28 const innerNoOptions = ref([]);
29 const projectNoOptions = ref([]); 29 const projectNoOptions = ref([]);
  30 +const allProjectNoOptions = ref([]);
  31 +export { allProjectNoOptions };
30 const orderStore = useOrderStoreWithOut(); 32 const orderStore = useOrderStoreWithOut();
31 const { 33 const {
32 customerCode, 34 customerCode,
@@ -55,12 +57,17 @@ export const searchFormSchema = [ @@ -55,12 +57,17 @@ export const searchFormSchema = [
55 options: projectNoOptions, 57 options: projectNoOptions,
56 showSearch: true, 58 showSearch: true,
57 mode: 'multiple', 59 mode: 'multiple',
58 - onSearch: async (value: any) => {  
59 - projectNoOptions.value = await queryNoOptions('projectNo', value); 60 + onSearch: async (value) => {
  61 + const result = await queryNoOptions('projectNo', value);
  62 + projectNoOptions.value = result;
  63 + allProjectNoOptions.value = projectNoOptions.value;
  64 + },
  65 + onChange: (value) => {
  66 + // 当项目号选择变化时,更新查询条件
  67 + if (localStorage.getItem('isAllSelected') === 'true') {
  68 +
  69 + }
60 }, 70 },
61 - // onSearch: async (value: any) => {  
62 - // projectNoOptions.value = await queryNoOptions('projectNo', value);  
63 - // },  
64 }, 71 },
65 }, 72 },
66 // { 73 // {
@@ -321,11 +328,13 @@ export const COLUMNS = [ @@ -321,11 +328,13 @@ export const COLUMNS = [
321 axios 328 axios
322 .post( 329 .post(
323 '/basic-api/project/businessProfit/export', 330 '/basic-api/project/businessProfit/export',
324 - {}, // 请求体为空  
325 { 331 {
326 - params: {  
327 - projectNoPrefix: column.record.projectNoPrefix, // 将参数放到查询字符串中  
328 - }, 332 + ProjectNo:column.record.detailProjectNo
  333 + }, // 请求体为空
  334 + {
  335 + // params: {
  336 + // projectNoPrefix: column.record.projectNoPrefix, // 将参数放到查询字符串中
  337 + // },
329 headers: { 338 headers: {
330 Authorization: `${token}`, // 去掉引号 339 Authorization: `${token}`, // 去掉引号
331 }, 340 },
src/views/project/finance/financeProfit/ServiceProfit/ServiceProfit/index.vue
1 <template> 1 <template>
2 <div> 2 <div>
3 - <BasicTable @register="registerTable" :bordered="true"> 3 + <BasicTable @register="registerTable" :bordered="true" @field-value-change="handleFieldValueChange">
4 <template #headerTop> 4 <template #headerTop>
5 <a-alert type="info" show-icon> 5 <a-alert type="info" show-icon>
6 <template #message> 6 <template #message>
@@ -36,6 +36,11 @@ @@ -36,6 +36,11 @@
36 :style="{ borderRadius: '5px 5px 5px 5px' }" 36 :style="{ borderRadius: '5px 5px 5px 5px' }"
37 >导出</a-button 37 >导出</a-button
38 > 38 >
  39 + <a-button
  40 + type="primary"
  41 + @click="handleAllProjectNoQuery"
  42 + style="margin-left: 8px;position: fixed;right: 29%;top: 107.5px;"
  43 + >全选</a-button>
39 </template> 44 </template>
40 </BasicTable> 45 </BasicTable>
41 <CheckDetail @register="checkModalRegister" :onGoFormDetail="handleGoFormDetail" /> 46 <CheckDetail @register="checkModalRegister" :onGoFormDetail="handleGoFormDetail" />
@@ -46,7 +51,8 @@ @@ -46,7 +51,8 @@
46 <script setup lang="ts"> 51 <script setup lang="ts">
47 import { BasicTable, useTable, TableAction } from '/@/components/Table'; 52 import { BasicTable, useTable, TableAction } from '/@/components/Table';
48 import { getServiceProfit, setBusinessProfitSetStatus } from '@/api/project/invoice'; 53 import { getServiceProfit, setBusinessProfitSetStatus } from '@/api/project/invoice';
49 - import { searchFormSchema, COLUMNS } from './data'; 54 + import { saveConfig } from '@/api/sys/config';
  55 + import { searchFormSchema, COLUMNS, allProjectNoOptions } from './data';
50 import axios from 'axios'; 56 import axios from 'axios';
51 import { useMessage } from '/@/hooks/web/useMessage'; 57 import { useMessage } from '/@/hooks/web/useMessage';
52 import { onMounted, ref, computed, unref } from 'vue'; 58 import { onMounted, ref, computed, unref } from 'vue';
@@ -73,7 +79,7 @@ @@ -73,7 +79,7 @@
73 const role = computed(() => { 79 const role = computed(() => {
74 return user?.roleSmallVO?.code; 80 return user?.roleSmallVO?.code;
75 }); 81 });
76 - const [registerTable, { reload, getSelectRowKeys, getDataSource, setSelectedRowKeys }] = useTable({ 82 + const [registerTable, { reload, getSelectRowKeys, getDataSource, setSelectedRowKeys, setProps, getForm }] = useTable({
77 title: '', 83 title: '',
78 api: getServiceProfit, 84 api: getServiceProfit,
79 bordered: true, 85 bordered: true,
@@ -83,6 +89,49 @@ @@ -83,6 +89,49 @@
83 labelWidth: 120, 89 labelWidth: 120,
84 schemas: searchFormSchema, 90 schemas: searchFormSchema,
85 autoSubmitOnEnter: true, 91 autoSubmitOnEnter: true,
  92 + resetFunc: async () => {
  93 + localStorage.removeItem('isAllSelected');
  94 + setProps({
  95 + searchInfo: {
  96 + projectNo: []
  97 + }
  98 + });
  99 + },
  100 + },
  101 + handleSearchInfoFn: (searchInfo) => {
  102 + console.log('=== handleSearchInfoFn 开始 ===');
  103 + console.log('原始 searchInfo:', searchInfo);
  104 +
  105 + // 获取表单实例
  106 + const formInstance = getForm();
  107 + if (formInstance) {
  108 + const formValues = formInstance.getFieldsValue();
  109 + console.log('表单值:', formValues);
  110 +
  111 + // 强制覆盖searchInfo,确保使用表单中的值
  112 + if (formValues.projectNo && formValues.projectNo.length > 0) {
  113 + // 确保传递的是数组而不是Proxy对象,并去重
  114 + const projectNoArray = [...new Set(formValues.projectNo)];
  115 + // 强制覆盖,不使用原始值
  116 + searchInfo = {
  117 + ...searchInfo,
  118 + projectNo: projectNoArray
  119 + };
  120 + console.log('强制使用表单中的项目号:', projectNoArray);
  121 + } else {
  122 + // 如果表单中没有项目号,清空查询条件
  123 + searchInfo = {
  124 + ...searchInfo,
  125 + projectNo: []
  126 + };
  127 + console.log('清空项目号查询条件');
  128 + }
  129 + }
  130 +
  131 + console.log('处理后的 searchInfo:', searchInfo);
  132 + console.log('=== handleSearchInfoFn 结束 ===');
  133 +
  134 + return searchInfo;
86 }, 135 },
87 rowKey: (record) => record.detailProjectNo || record.id || record.serialNumber, 136 rowKey: (record) => record.detailProjectNo || record.id || record.serialNumber,
88 rowSelection: { 137 rowSelection: {
@@ -162,6 +211,34 @@ @@ -162,6 +211,34 @@
162 await orderStore.getDict(); 211 await orderStore.getDict();
163 }); 212 });
164 213
  214 + // 监听表单字段变化
  215 + function handleFieldValueChange(field: string, value: any) {
  216 + // 如果是项目号字段变化且处于全选状态,同步更新查询条件
  217 + if (field === 'projectNo' && localStorage.getItem('isAllSelected') === 'true') {
  218 + console.log('=== handleFieldValueChange 开始 ===');
  219 + console.log('field:', field);
  220 + console.log('value:', value);
  221 +
  222 + // 确保value是数组格式,并去重
  223 + const projectNoArray = Array.isArray(value) ? [...new Set(value)] : [];
  224 +
  225 + console.log('处理后的项目号数组:', projectNoArray);
  226 +
  227 + // 强制重新加载表格,使用新的查询条件
  228 + reload({
  229 + searchInfo: {
  230 + projectNo: projectNoArray
  231 + }
  232 + });
  233 +
  234 + // 同时更新detailProjectNoKeys数组
  235 + detailProjectNoKeys.value = projectNoArray;
  236 +
  237 + console.log('更新后的查询条件:', projectNoArray);
  238 + console.log('=== handleFieldValueChange 结束 ===');
  239 + }
  240 + }
  241 +
165 function handleFinanceEdit(record) { 242 function handleFinanceEdit(record) {
166 openFinanceEdit(true, { 243 openFinanceEdit(true, {
167 data: record, 244 data: record,
@@ -192,13 +269,23 @@ @@ -192,13 +269,23 @@
192 269
193 async function handleStatus(record, status) { 270 async function handleStatus(record, status) {
194 try { 271 try {
  272 + // 检查必要参数是否存在
  273 + if (!record.customerCode || !record.projectNoPrefix) {
  274 + createMessage.error('缺少必要的参数:客户编码或项目号');
  275 + return;
  276 + }
  277 +
195 await setBusinessProfitSetStatus({ 278 await setBusinessProfitSetStatus({
196 customerCode: record.customerCode, 279 customerCode: record.customerCode,
197 projectNo: record.projectNoPrefix, 280 projectNo: record.projectNoPrefix,
  281 + status: status // 添加状态参数
198 }); 282 });
  283 +
  284 + createMessage.success('状态更新成功!');
199 reload(); 285 reload();
200 } catch (error) { 286 } catch (error) {
201 console.error('Error updating status:', error); 287 console.error('Error updating status:', error);
  288 + createMessage.error('状态更新失败:' + (error.message || '未知错误'));
202 } 289 }
203 } 290 }
204 291
@@ -365,5 +452,56 @@ @@ -365,5 +452,56 @@
365 } 452 }
366 setSelectedRowKeys(checkedKeys.value as any); 453 setSelectedRowKeys(checkedKeys.value as any);
367 } 454 }
  455 + // 6/25未完成工作:全选查询
  456 + function handleAllProjectNoQuery() {
  457 + // 检查是否有项目号选项
  458 + if (!allProjectNoOptions.value || allProjectNoOptions.value.length === 0) {
  459 + createMessage.warn('没有可查询的项目号!');
  460 + return;
  461 + }
  462 +
  463 + // 获取所有项目号的value值
  464 + const allProjectNos = allProjectNoOptions.value.map(item => {
  465 + // 处理不同的数据结构
  466 + if (typeof item === 'string') {
  467 + return item;
  468 + } else if (item && typeof item === 'object' && 'value' in item) {
  469 + return item.value;
  470 + } else if (item && typeof item === 'object' && 'label' in item) {
  471 + return item.label;
  472 + }
  473 + return item;
  474 + }).filter(Boolean); // 过滤掉空值
  475 +
  476 + if (allProjectNos.length === 0) {
  477 + createMessage.warn('没有有效的项目号!');
  478 + return;
  479 + }
  480 +
  481 + try {
  482 + // 提示用户全选成功
  483 + createMessage.success(`已全选 ${allProjectNos.length} 个项目号`);
  484 +
  485 + // 获取表单实例并设置表单值,将项目号填入搜索框
  486 + const formInstance = getForm();
  487 + if (formInstance && formInstance.setFieldsValue) {
  488 + formInstance.setFieldsValue({
  489 + projectNo: allProjectNos
  490 + });
  491 + }
  492 +
  493 + // 将allProjectNoOptions更新为已勾选的项目号数组,这样用户取消勾选时数组会同步更新
  494 + allProjectNoOptions.value = allProjectNos.map(projectNo => ({
  495 + label: projectNo,
  496 + value: projectNo
  497 + }));
  498 +
  499 + // 标记为全选状态
  500 + localStorage.setItem('isAllSelected', 'true');
  501 + } catch (error) {
  502 + console.error('全选失败:', error);
  503 + createMessage.error('全选失败,请检查网络连接!');
  504 + }
  505 + }
368 </script> 506 </script>
369 <style></style> 507 <style></style>