浏览代码

补充提交

main
hulei 1 个月前
父节点
当前提交
845cbd3380
共有 65 个文件被更改,包括 9066 次插入1138 次删除
  1. 1
    1
      ant-design-pro-vue3/README.md
  2. 1
    9
      ant-design-pro-vue3/src/api/api.js
  3. 34
    0
      ant-design-pro-vue3/src/api/api.js.bak
  4. 54
    0
      ant-design-pro-vue3/src/api/departTreePanel.js
  5. 15
    0
      ant-design-pro-vue3/src/api/report.js
  6. 237
    0
      ant-design-pro-vue3/src/api/treeData.js
  7. 133
    0
      ant-design-pro-vue3/src/api/treeDataApi.js
  8. 338
    0
      ant-design-pro-vue3/src/components/DepartTreePanel/components/DepartTreePanel1.vue
  9. 312
    0
      ant-design-pro-vue3/src/components/DepartTreePanel/index.vue
  10. 1
    1
      ant-design-pro-vue3/src/components/GlobalFooter/index.vue
  11. 12
    2
      ant-design-pro-vue3/src/components/MultiTab/index.vue
  12. 48
    9
      ant-design-pro-vue3/src/components/OpenModelButton/index.vue
  13. 2
    1
      ant-design-pro-vue3/src/components/ProForm/fields/ProDatePicker/index.vue
  14. 14
    5
      ant-design-pro-vue3/src/components/ProForm/fields/ProSelect/index.vue
  15. 276
    0
      ant-design-pro-vue3/src/components/ProForm/fields/ProSelect3/index.vue
  16. 10
    3
      ant-design-pro-vue3/src/components/ProForm/fields/ProSelectTree/index.vue
  17. 169
    0
      ant-design-pro-vue3/src/components/ProForm/fields/ProSelectTree2/index.vue
  18. 381
    0
      ant-design-pro-vue3/src/components/ProForm/fields/ProSelectTree3/index.vue
  19. 9
    0
      ant-design-pro-vue3/src/components/ProForm/main.js
  20. 262
    0
      ant-design-pro-vue3/src/components/ProLayout3/index.vue
  21. 93
    0
      ant-design-pro-vue3/src/components/ProReport/DepartPanel.vue
  22. 173
    0
      ant-design-pro-vue3/src/components/ProReport/ResultPanel.vue
  23. 1142
    1081
      ant-design-pro-vue3/src/components/ProTable/index.vue
  24. 205
    0
      ant-design-pro-vue3/src/components/ProTree2/index.vue
  25. 423
    0
      ant-design-pro-vue3/src/components/ProTree3/index.vue
  26. 102
    0
      ant-design-pro-vue3/src/components/ReportComponent/components/AccLvlComponent.vue
  27. 362
    0
      ant-design-pro-vue3/src/components/ReportComponent/components/DepartPanelComponent.vue
  28. 116
    0
      ant-design-pro-vue3/src/components/ReportComponent/components/QueryComponent.vue
  29. 54
    0
      ant-design-pro-vue3/src/components/ReportComponent/components/ResultComponent.vue
  30. 164
    0
      ant-design-pro-vue3/src/components/ReportComponent/components/SobSelectComponent.vue
  31. 277
    0
      ant-design-pro-vue3/src/components/ReportComponent/index.vue
  32. 8
    0
      ant-design-pro-vue3/src/components/SobComponent/components/SobItemLvlComponent.vue
  33. 0
    0
      ant-design-pro-vue3/src/components/SobComponent/index.vue
  34. 16
    0
      ant-design-pro-vue3/src/components/main.js
  35. 9
    3
      ant-design-pro-vue3/src/layouts/BasicLayout.vue
  36. 17
    1
      ant-design-pro-vue3/src/locales/menu/cn.ts
  37. 2
    1
      ant-design-pro-vue3/src/router/commonRoutes.ts
  38. 81
    10
      ant-design-pro-vue3/src/router/exampleRouterMap.ts
  39. 4
    0
      ant-design-pro-vue3/src/router/routerGuard.ts
  40. 50
    0
      ant-design-pro-vue3/src/style/theme.less
  41. 361
    0
      ant-design-pro-vue3/src/utils/treeUtil.js
  42. 12
    9
      ant-design-pro-vue3/src/views/CurrencyManager/CurrencyManagerView.vue
  43. 298
    0
      ant-design-pro-vue3/src/views/depart/Test.vue
  44. 123
    0
      ant-design-pro-vue3/src/views/depart/departLevel.vue
  45. 171
    0
      ant-design-pro-vue3/src/views/depart/departLevel/DepartLevelDef copy.vue
  46. 173
    0
      ant-design-pro-vue3/src/views/depart/departLevel/DepartLevelDef.vue
  47. 179
    0
      ant-design-pro-vue3/src/views/depart/departLevel/DepartLevelInfo copy.vue
  48. 195
    0
      ant-design-pro-vue3/src/views/depart/departLevel/DepartLevelInfo.vue
  49. 251
    0
      ant-design-pro-vue3/src/views/depart/departLevel/Test.vue
  50. 364
    0
      ant-design-pro-vue3/src/views/depart/departLevel/TestProSelectTree.vue
  51. 180
    0
      ant-design-pro-vue3/src/views/depart/departLevel/TestProSelectTree3.vue
  52. 5
    0
      ant-design-pro-vue3/src/views/depart/departLevel/TestProTree3.vue
  53. 8
    0
      ant-design-pro-vue3/src/views/depart/departLevel/YwzkbReport.vue
  54. 311
    0
      ant-design-pro-vue3/src/views/depart/departLevel/models/DepartLevel.store copy.ts
  55. 227
    0
      ant-design-pro-vue3/src/views/depart/departLevel/models/DepartLevel.store.ts
  56. 137
    0
      ant-design-pro-vue3/src/views/depart/departLevel/services/index.ts
  57. 172
    0
      ant-design-pro-vue3/src/views/depart/departLevelInfo.vue
  58. 170
    0
      ant-design-pro-vue3/src/views/depart/models/departLevel.store.ts
  59. 38
    0
      ant-design-pro-vue3/src/views/depart/services/index.ts
  60. 12
    0
      ant-design-pro-vue3/src/views/depart/test/TestPanel.vue
  61. 49
    0
      ant-design-pro-vue3/src/views/example/ProDatePickerExample.vue
  62. 7
    0
      ant-design-pro-vue3/src/views/front/T2000/T2000.vue
  63. 7
    0
      ant-design-pro-vue3/src/views/front/T2001/T2001.vue
  64. 0
    0
      ant-design-pro-vue3/src/views/front/services/index.ts
  65. 9
    2
      ant-design-pro-vue3/vite.config.ts

+ 1
- 1
ant-design-pro-vue3/README.md 查看文件

@@ -3,7 +3,7 @@
3 3
 ```
4 4
 下载依赖
5 5
 
6
-yarn isntall
6
+yarn install
7 7
 
8 8
 启动服务
9 9
 

+ 1
- 9
ant-design-pro-vue3/src/api/api.js 查看文件

@@ -4,7 +4,7 @@ const systemPrefix = settings.systemPrefix
4 4
 
5 5
 export  function getRole(params) {
6 6
   return request({
7
-    url: `${systemPrefix}/automake/controller/system/login/SelectRoleNameController?userno=${params}`,
7
+    url: `${systemPrefix}/automake/controller/system/login/SelectRoleNameController.do?userno=${params}`,
8 8
     method:'post'
9 9
   });
10 10
 }
@@ -18,14 +18,6 @@ export function login(params) {
18 18
     })
19 19
 }
20 20
 
21
-export function getMenuDataService(params){
22
-    return request({
23
-        url: `${systemPrefix}/workflow/category/list/Auth`,
24
-        method: 'post',
25
-        data:params
26
-    })
27
-}
28
-
29 21
 export function getRoutes(){
30 22
     return request({
31 23
         url: `/__umiDev/routes`,

+ 34
- 0
ant-design-pro-vue3/src/api/api.js.bak 查看文件

@@ -0,0 +1,34 @@
1
+import settings from '@/settings'
2
+import request from '@/utils/request'
3
+const systemPrefix = settings.systemPrefix
4
+
5
+export  function getRole(params) {
6
+  return request({
7
+    url: `${systemPrefix}/automake/controller/system/login/SelectRoleNameController.do?userno=${params}`,
8
+    method:'post'
9
+  });
10
+}
11
+
12
+export function login(params) {
13
+    let datas = {userno:params.username, pwd:params.password, login_role:params.login_role,loginPage:1}
14
+    return request({
15
+        url: `${systemPrefix}/automake/controller/system/login/LoginAction`,
16
+        method: 'post',
17
+        data:datas
18
+    })
19
+}
20
+
21
+export function getMenuDataService(params){
22
+    return request({
23
+        url: `${systemPrefix}/workflow/category/list/Auth`,
24
+        method: 'post',
25
+        data:params
26
+    })
27
+}
28
+
29
+export function getRoutes(){
30
+    return request({
31
+        url: `/__umiDev/routes`,
32
+        method: 'get',
33
+    })
34
+}

+ 54
- 0
ant-design-pro-vue3/src/api/departTreePanel.js 查看文件

@@ -0,0 +1,54 @@
1
+import settings from '@/settings'
2
+import request from '@/utils/request'
3
+const systemPrefix = settings.systemPrefix
4
+
5
+
6
+
7
+export function getRelationInfoNoList(params) {
8
+    return request(`${systemPrefix}/system/select/options/relationInfoNo.do`, {
9
+        method: 'post',
10
+        data: params,
11
+        requestType: 'form',
12
+    })
13
+}
14
+
15
+export function getDepartTreeData(params) {
16
+    return request(`${systemPrefix}/im/dhc/sys/automake/system/department/ReportTreeDataController.do`, {
17
+        method: 'post',
18
+        data: params,
19
+        requestType: 'form',
20
+
21
+    })
22
+}
23
+
24
+export function searchTreePanelDataByNodeId(params) {
25
+    return request(`${systemPrefix}/system/common/action/searchTreePanelDataByNodeId`, {
26
+        method: 'post',
27
+        data: params,
28
+        requestType: 'form',
29
+    })
30
+}
31
+export function getSearchResultByNodeId(params) {
32
+    return request(`${systemPrefix}/system/common/action/searchTreePanelDataByNodeId`, {
33
+        method: 'post',
34
+        data: params,
35
+        requestType: 'form',
36
+    })
37
+}
38
+
39
+
40
+export function fetchSobTreeData(params) {
41
+    return request(`${systemPrefix}/im/dhc/zz/automake/zzmanage/accounting_manager/generalAccount_manager/ComDepartSobTreeController.do`, {
42
+        method: 'post',
43
+        data: params,
44
+        requestType: 'form',
45
+    })
46
+}
47
+
48
+export function fetchItemTreeData(params) {
49
+    return request(`${systemPrefix}/im/dhc/zz/automake/zzmanage/comitem_manager/ComModItemInfoQueryController`, {
50
+        method: 'post',
51
+        data: params,
52
+        requestType: 'form',
53
+    })
54
+}

+ 15
- 0
ant-design-pro-vue3/src/api/report.js 查看文件

@@ -0,0 +1,15 @@
1
+import settings from '@/settings'
2
+import request from '@/utils/request'
3
+const systemPrefix = settings.systemPrefix
4
+/**
5
+ * 
6
+ * @param {*} params 
7
+ * @returns 
8
+ */
9
+export function getReadyReportData(params) {
10
+    return request(`${systemPrefix}/im/dhc/zz/automake/zzmanage/reporformula_manager/ReadyReportDataController.do`, {
11
+        method: 'post',
12
+        data: params,
13
+        requestType: 'form',
14
+    })
15
+}

+ 237
- 0
ant-design-pro-vue3/src/api/treeData.js 查看文件

@@ -0,0 +1,237 @@
1
+import settings from '@/settings';
2
+import request from '@/utils/request';
3
+import { isEmpty } from '@/utils/validate'
4
+import { message } from "ant-design-vue";
5
+import { convertToTree, findNodes } from '@/utils/treeUtil'
6
+
7
+const systemPrefix = settings.systemPrefix;
8
+// 定义一个组合式函数,用于获取和处理树状数据
9
+export const useTreeData = (props, param) => {
10
+    // 定义一个异步函数,用于获取树状数据
11
+    const getTreeData = async () => {
12
+        let apiParams = {};
13
+        let apiUrl = '';
14
+        const { isAsync} = {...props};
15
+        // 根据不同的 treeType 构建请求参数和 URL
16
+        switch (props.treeType) {
17
+            case 'deptTree':
18
+                apiUrl = '/system/common/action/searchTreeData.do';
19
+                const {relationNo} = {...props};
20
+                let {id} = {...param};
21
+                apiParams = {
22
+                    tree_type: 'departRight',
23
+                    isAsync: isAsync,
24
+                    relation_info_no: relationNo,
25
+                    id: isEmpty(id)? '' : id,
26
+                };
27
+                break;
28
+            case'sobTree':
29
+                apiUrl = '/im/dhc/zz/automake/zzmanage/accounting_manager/generalAccount_manager/ComDepartSobTreeController.do';
30
+                const {brNos} = {...props}
31
+                apiParams = { 
32
+                    // tree_type: 'sob_tree',
33
+                    // isAsync: false,
34
+                    // searchFlag: '01',
35
+                    // sts: '1',
36
+                    opt_type:'search',
37
+                    tx_br_no: brNos.join(',')
38
+                };
39
+                break;
40
+            case'sobItemTree':
41
+                apiUrl = '/im/dhc/zz/automake/zzmanage/comitem_manager/ComModItemInfoQueryController.do';
42
+                const {stddNo,sobNo} = {...props} ;
43
+                apiParams = { 
44
+                    type:"sobItemTree",
45
+                    whereSql: `WHERE STDD_NO = ? AND SOB_NO = ? AND USE_YN ='Y'`,
46
+                    params:	`${stddNo},${sobNo}`
47
+                }
48
+                break;
49
+            default:
50
+                break;
51
+        }
52
+        try {
53
+            // 调用 fetchTreeData 函数发送请求
54
+            const resp = await sendRequest(apiUrl, apiParams);
55
+            if(isAsync === true){
56
+                return resp;
57
+            } else {
58
+            // 将获取到的数据转换为树状结构
59
+                return convertToTree(resp);
60
+            }
61
+        } catch (error) {
62
+            message.error(`请求失败: ${error.message}`);
63
+        }
64
+    };
65
+
66
+    // 定义一个函数,用于发送请求
67
+    function sendRequest(apiUrl, apiParams) {
68
+        return request(`${systemPrefix}${apiUrl}`, {
69
+            method: 'post',
70
+            data: apiParams,
71
+            requestType: 'form',
72
+        });
73
+    }
74
+
75
+    // 封装成树形结构的公共方法
76
+    function convertToTree(data) {
77
+        // 用于存储每个节点的映射,键为节点的 id,值为节点对象
78
+        const nodeMap = {};
79
+        // 存储根节点的数组
80
+        const tree = [];
81
+        const localData = [];
82
+        // 第一次遍历,将每个节点存储到 nodeMap 中
83
+        data.forEach(item => {
84
+            // 为每个节点添加 children 属性,用于存储其子节点
85
+            item.children = [];
86
+            // 去重处理, 同一个id只保留一个节点
87
+            if(isEmpty(nodeMap[item.id])){
88
+                nodeMap[item.id] = item;
89
+                localData.push(item);
90
+
91
+            }
92
+        });
93
+
94
+        // 第二次遍历,构建树形结构
95
+        localData.forEach(item => {
96
+            const pid = item.pid;
97
+            if (pid === null || pid === undefined || pid === item.id || !nodeMap[pid]) {
98
+                // 如果 pid 为 null 或 undefined,或者父节点不存在,则将该节点作为根节点
99
+                tree.push(item);
100
+            } else {
101
+                // 否则,将该节点添加到其父节点的 children 数组中
102
+                nodeMap[pid].children.push(item);
103
+            }
104
+        });
105
+        return tree;
106
+    }
107
+
108
+    return {
109
+        getTreeData
110
+    };
111
+};
112
+
113
+
114
+
115
+/**
116
+ * 根据树的类型获取树数据、默认值和默认节点
117
+ * @param {Object} props - 包含树类型、异步标志等属性的对象
118
+ * @param {Object} param - 额外的参数对象
119
+ * @returns {Promise<Object>} - 包含树数据、默认值和默认节点的对象
120
+ */
121
+export const getTreeDataByType = async (props, param) => {
122
+    // 初始化变量
123
+    let treeData = []; // 存储树数据
124
+    let defaultValue = ''; // 存储默认值
125
+    let defaultNode = []; // 存储默认节点
126
+    let stddNo = ''; // 存储标准编号
127
+    let apiParams = {}; // 存储请求的参数
128
+    let apiUrl = ''; // 存储请求的 API 地址
129
+
130
+    // 解构出异步标志
131
+    const { isAsync } = { ...props };
132
+
133
+    // 根据不同的树类型构建请求的 API 地址和参数
134
+    switch (props.treeType) {
135
+        case 'deptTree': {
136
+            // 解构出关联编号
137
+            const { relationNo } = { ...props };
138
+            // 解构出 ID
139
+            const { id } = { ...param };
140
+            apiUrl = '/system/common/action/searchTreeData.do';
141
+            apiParams = {
142
+                tree_type: 'departRight',
143
+                isAsync, // 使用解构出的 isAsync
144
+                relation_info_no: relationNo,
145
+                id: isEmpty(id) ? '' : id,
146
+            };
147
+            break;
148
+        }
149
+        case 'sobTree': {
150
+            // 解构出分支编号数组
151
+            const { brNos } = { ...props };
152
+            apiUrl = '/im/dhc/zz/automake/zzmanage/accounting_manager/generalAccount_manager/ComDepartSobTreeController.do';
153
+            apiParams = {
154
+                opt_type: 'search',
155
+                tx_br_no: brNos.join(','),
156
+            };
157
+            break;
158
+        }
159
+        case 'sobItemTree': {
160
+            // 解构出标准编号和子业务编号
161
+            const { stddNo, sobNo } = { ...props };
162
+            apiUrl = '/im/dhc/zz/automake/zzmanage/comitem_manager/ComModItemInfoQueryController.do';
163
+            apiParams = {
164
+                type: "sobItemTree",
165
+                whereSql: `WHERE STDD_NO = ? AND SOB_NO = ? AND USE_YN ='Y'`,
166
+                params: `${stddNo},${sobNo}`,
167
+            };
168
+            break;
169
+        }
170
+        default:
171
+            break;
172
+    }
173
+
174
+    try {
175
+        // 调用发送请求的函数获取响应数据
176
+        const resp = await sendRequest(apiUrl, apiParams);
177
+
178
+        // 根据异步标志处理响应数据
179
+        if (isAsync) {
180
+            // 异步模式下直接使用响应数据
181
+            treeData = resp; 
182
+        } else {
183
+            // 非异步模式下将响应数据转换为树状结构
184
+            treeData = convertToTree(resp);
185
+        }
186
+
187
+        // 根据不同的树类型设置默认值和默认节点
188
+        switch (props.treeType) {
189
+            case 'deptTree':
190
+                if (treeData.length > 0) {
191
+                    // 去除默认节点的 children 属性
192
+                    const { children, ...nodeWithoutChildren } = treeData[0];
193
+                    defaultNode = nodeWithoutChildren;
194
+                    // 从默认节点中获取默认值
195
+                    defaultValue = defaultNode[props.fieldNames.key];
196
+                }
197
+                break;
198
+            case 'sobTree':
199
+                if (treeData.length > 0) {
200
+                    // 根据属性查找默认节点
201
+                    defaultNode = findNodes(treeData, 'default_yn', 'Y');
202
+                    if (!isEmpty(defaultNode) && defaultNode.length > 0) {
203
+                        // 从默认节点的父节点 ID 中提取标准编号
204
+                        stddNo = defaultNode[0]['pid'].split('@')[0];
205
+                        // 从默认节点中获取默认值
206
+                        defaultValue = [defaultNode[0][props.fieldNames.key]];
207
+                    }
208
+                }
209
+                break;
210
+            case 'sobItemTree':
211
+                // 可根据 sobItemTree 的具体需求添加默认值和默认节点的逻辑
212
+                break;
213
+            default:
214
+                break;
215
+        }
216
+    } catch (error) {
217
+        // 处理请求失败的情况,显示错误消息
218
+        message.error(`请求失败: ${error.message}`);
219
+    }
220
+
221
+    // 返回包含树数据、默认值和默认节点的对象
222
+    return {
223
+        treeData,
224
+        defaultValue,
225
+        defaultNode,
226
+        stddNo
227
+    };
228
+};
229
+
230
+// 定义一个函数,用于发送请求
231
+function sendRequest (apiUrl, apiParams) {
232
+    return request(`${systemPrefix}${apiUrl}`, {
233
+        method: 'post',
234
+        data: apiParams,
235
+        requestType: 'form',
236
+    });
237
+}

+ 133
- 0
ant-design-pro-vue3/src/api/treeDataApi.js 查看文件

@@ -0,0 +1,133 @@
1
+import { isEmpty } from '@/utils/validate';
2
+import settings from '@/settings';
3
+import request from '@/utils/request';
4
+import { message } from "ant-design-vue";
5
+import { convertToTree, findNodes } from '@/utils/treeUtil';
6
+const systemPrefix = settings.systemPrefix;
7
+
8
+/**
9
+ * 根据树的类型获取树数据、默认值和默认节点
10
+ * @param {Object} props - 包含树类型、异步标志等属性的对象
11
+ * @param {Object} param - 额外的参数对象
12
+ * @returns {Promise<Object>} - 包含树数据、默认值和默认节点的对象
13
+ */
14
+export const getTreeData = async (props, param) => {
15
+    // 初始化变量
16
+    let treeData = []; // 存储树数据
17
+    // let defaultValue = []; // 存储默认值
18
+    // let defaultNode = []; // 存储默认节点
19
+    let defaultValue; // 存储默认值
20
+    let defaultNode; // 存储默认节点
21
+    let defaultStddNo = ''; // 存储标准编号
22
+    let apiParams = {}; // 存储请求的参数
23
+    let apiUrl = ''; // 存储请求的 API 地址
24
+
25
+    // 解构出异步标志
26
+    const { isAsync } = { ...props };
27
+
28
+    // 根据不同的树类型构建请求的 API 地址和参数
29
+    switch (props.treeType) {
30
+        case 'deptTree': {
31
+            // 解构出关联编号
32
+            const { relationNo } = { ...props };
33
+            // 解构出 ID
34
+            const { id } = { ...param };
35
+            apiUrl = '/system/common/action/searchTreeData.do';
36
+            apiParams = {
37
+                tree_type: 'departRight',
38
+                isAsync, // 使用解构出的 isAsync
39
+                relation_info_no: relationNo,
40
+                id: isEmpty(id) ? '' : id,
41
+            };
42
+            break;
43
+        }
44
+        case 'sobTree': {
45
+            // 解构出分支编号数组
46
+            const { brNos } = { ...props };
47
+            apiUrl = '/im/dhc/zz/automake/zzmanage/accounting_manager/generalAccount_manager/ComDepartSobTreeController.do';
48
+            apiParams = {
49
+                opt_type: 'search',
50
+                tx_br_no: brNos.join(','),
51
+            };
52
+            break;
53
+        }
54
+        case 'sobItemTree': {
55
+            // 解构出标准编号和子业务编号
56
+            const { stddNo, sobNo } = { ...props };
57
+            apiUrl = '/im/dhc/zz/automake/zzmanage/comitem_manager/ComModItemInfoQueryController.do';
58
+            apiParams = {
59
+                type: "sobItemTree",
60
+                whereSql: `WHERE STDD_NO = ? AND SOB_NO = ? AND USE_YN ='Y'`,
61
+                params: `${stddNo},${sobNo}`,
62
+            };
63
+            break;
64
+        }
65
+        default:
66
+            break;
67
+    }
68
+
69
+    try {
70
+        // 调用发送请求的函数获取响应数据
71
+        const resp = await sendRequest(apiUrl, apiParams);
72
+        // 根据异步标志处理响应数据
73
+        if (isAsync) {
74
+            // 异步模式下直接使用响应数据
75
+            treeData = resp; 
76
+        } else {
77
+            // 非异步模式下将响应数据转换为树状结构
78
+            treeData = convertToTree(resp);
79
+        }
80
+
81
+        // 根据不同的树类型设置默认值和默认节点
82
+        switch (props.treeType) {
83
+            case 'deptTree':
84
+                if (treeData.length > 0) {
85
+                    // 去除默认节点的 children 属性
86
+                    const { children, ...nodeWithoutChildren } = treeData[0];
87
+                    //defaultNode.push(nodeWithoutChildren);
88
+                    defaultNode = [nodeWithoutChildren];
89
+                    // 从默认节点中获取默认值
90
+                    defaultValue = [nodeWithoutChildren[props.fieldNames.key]];
91
+                }
92
+                break;
93
+            case 'sobTree':
94
+                if (treeData.length > 0) {
95
+                    // 根据属性查找默认节点
96
+                    defaultNode = findNodes(treeData, 'default_yn', 'Y');
97
+                    if (!isEmpty(defaultNode) && defaultNode.length > 0) {
98
+                        // 从默认节点的父节点 ID 中提取标准编号
99
+                        defaultStddNo = defaultNode[0]['pid'].split('@')[0];
100
+                        // 从默认节点中获取默认值
101
+                        // defaultValue = [defaultNode[0][props.fieldNames.key]];
102
+                        defaultValue = defaultNode[0][props.fieldNames.key];
103
+                    }
104
+                }
105
+                break;
106
+            case 'sobItemTree':
107
+                // 可根据 sobItemTree 的具体需求添加默认值和默认节点的逻辑
108
+                break;
109
+            default:
110
+                break;
111
+        }
112
+    } catch (error) {
113
+        // 处理请求失败的情况,显示错误消息
114
+        message.error(`请求失败: ${error.message}`);
115
+    }
116
+
117
+    // 返回包含树数据、默认值和默认节点的对象
118
+    return {
119
+        treeData,
120
+        defaultValue,
121
+        defaultNode,
122
+        defaultStddNo
123
+    };
124
+};
125
+
126
+// 定义一个函数,用于发送请求
127
+function sendRequest (apiUrl, apiParams) {
128
+    return request(`${systemPrefix}${apiUrl}`, {
129
+        method: 'post',
130
+        data: apiParams,
131
+        requestType: 'form',
132
+    });
133
+}

+ 338
- 0
ant-design-pro-vue3/src/components/DepartTreePanel/components/DepartTreePanel1.vue 查看文件

@@ -0,0 +1,338 @@
1
+<template>
2
+    <!--1.汇总关系下拉列表-->
3
+    <div class="relation-dropdown">
4
+        <span class="relation-label">汇总关系:</span>
5
+        <a-select v-model:value="relationInfoNo" :options="relationInfoNoOptions" class="relation-select"
6
+            :allowClear="true">
7
+        </a-select>
8
+    </div>
9
+    <!--2.不同树形结构标签页-->
10
+    <div style="margin-bottom: -10px">
11
+        <a-tabs type="card" v-model:activeKey="treeType">
12
+            <a-tab-pane key="0" tab="账务树">
13
+            </a-tab-pane>
14
+            <a-tab-pane key="1" tab="对比树">
15
+            </a-tab-pane>
16
+            <a-tab-pane key="2" tab="报送树">
17
+            </a-tab-pane>
18
+        </a-tabs>
19
+    </div>
20
+    <!--3.搜索框-->
21
+    <div class="search-dropdown">
22
+        <a-input v-model:value="searchValue" @input="onInputChange" placeholder="搜索..." :allowClear="true" />
23
+        <div v-if="searchResultList.length > 0" class="search-select">
24
+            <div class="search-select-li" v-for=" searchResult in searchResultList" :key="searchResult.id"
25
+                @click="onOptionClick(searchResult)">
26
+                {{ searchResult.name }}
27
+            </div>
28
+        </div>
29
+    </div>
30
+    <!--4.机构树-->
31
+    <div>
32
+        <a-tree v-model:expandedKeys="expandedKeys" v-model:selectedKeys="selectedKeys"
33
+            v-model:checkedKeys="checkedKeys" v-model:loadedKeys="loadedKeys" :load-data="onLoadData"
34
+            :tree-data="treeData" :fieldNames="fieldNames" checkable @select="onSelect" @expand="onExpand"
35
+            @check="onCheck" />
36
+    </div>
37
+</template>
38
+
39
+<script setup>
40
+//问题汇总:
41
+//1.机构checked 如何联动下账套, 两个组件不在一块
42
+//2.机构汇总关系下拉列表属性必填项,如何与查询按钮绑定并校验
43
+//3.机构汇总关系获取枚举值时,如何获取当前交易的pageInterfaceNo 
44
+//4.系统日期如何获取到
45
+//5.机构汇总下拉列表如何获取对应的内部值
46
+//6.搜索框,需要判断值是否为空的逻辑处理
47
+//7.控制台报:Tree missing follow keys: '1'
48
+//8.搜索机构时,因为是单选正常应该只展示自己和自己的上级节点
49
+//9.查询时获取查询选中的机构列表也存在问题,需要优化,需要与后台呼应上 父节点下叶子节点全部选中,则返回父节点,否则返回选中的子节点
50
+//10.机构是必填项,如何校验
51
+
52
+// 11.当搜索一个节点时,然后展开整个树,再次重新 checked的话,点击查询获取查询节点有存在问题了
53
+// 12.点击树进行展开,然后再切换树类型或者汇总关系,展开图标消失了,但是数据还是存在
54
+// 13.增加loadedKeys 或者是移动到组件中,展开叶子节点就无效了
55
+// 14.机构面板组件封装到组件中,,业务就特别卡顿
56
+
57
+// 机构汇总关系双向绑定到页面中
58
+import { ref } from 'vue'
59
+import { defineProps, defineExpose, onMounted, watch, nextTick } from 'vue';
60
+import { getRelationInfoNoList, getDepartTreeData, getSearchResultByNodeId } from '@/api/departTreePanel';
61
+defineExpose({ getCheckedNodes });
62
+// 声名接收参数数据
63
+const props = defineProps({});
64
+
65
+// 机构汇总关系双向绑定到页面中
66
+const relationInfoNo = ref('');
67
+// 机构汇总关系枚举值, 组件挂载时向后端发起请求
68
+const relationInfoNoOptions = ref([]);
69
+// 树形结构标签页值双向绑定到页面中
70
+const treeType = ref('');
71
+
72
+
73
+// 钩子函数,页面加载完成后首先获取下汇总关系
74
+onMounted(async () => {
75
+    // 1.获取机构汇总关系枚举值
76
+    await getRelationInfoNoOptions();
77
+});
78
+// 监听汇总关系和树形结构标签页值,只要值发生变化,重新获取树形结构数据
79
+watch(() => [relationInfoNo.value, treeType.value,], async (newVal, oldVal) => {
80
+    // 1.当类型数发生变化时,重新获取树形结构数据
81
+    if (newVal != oldVal) {
82
+        await getDeptTreeData();
83
+    }
84
+});
85
+
86
+// 获取机构汇总关系枚举值及默认值
87
+async function getRelationInfoNoOptions () {
88
+    // 清空 relationInfoNoOptions 数组
89
+    relationInfoNoOptions.value = [];
90
+    // // 1.获取机构汇总关系枚举值
91
+    const resp = await getRelationInfoNoList({
92
+        pageInterfaceNo: 'zzsearch_01_01_02',
93
+    });
94
+    // 2.将枚举值添加到 relationInfoNoOptions 中 并设置下拉列表默认值
95
+    resp.forEach(node => {
96
+        if (node.item_no === 'AAAAAA') {
97
+            relationInfoNo.value = node.item_no;
98
+        }
99
+        relationInfoNoOptions.value.push({ label: node.item_name, value: node.item_no });
100
+    });
101
+    // 3.设置机构树类型的默认值
102
+    treeType.value = '0';
103
+}
104
+
105
+// 搜索框 start
106
+// 搜索框触发事件
107
+const searchValue = ref('');
108
+const searchResultList = ref([]);
109
+
110
+async function onInputChange () {
111
+    // 1.判断搜索框是否为空,为空则清空 options 数组,重新获取树形结构数据
112
+    if (!searchValue || searchValue.value.length === 0) {
113
+        searchResultList.value = [];
114
+        getDeptTreeData();
115
+        return;
116
+    }
117
+    // 2.获取搜索结果
118
+    searchResultList.value = await getDepartTreeData({
119
+        treeSearch: "true",
120
+        kw: searchValue.value,
121
+        relation_info_no: relationInfoNo.value,
122
+        treeType: treeType.value,
123
+        qryDate: '20231117',
124
+    });
125
+}
126
+
127
+// 选择搜索下拉列表项(点击事件)回调
128
+async function onOptionClick (searchResult) {
129
+    // 1.设置搜索框值
130
+    searchValue.value = searchResult.name;
131
+    // 2.点击完成后,隐藏下拉列表设置为空
132
+    searchResultList.value = [];
133
+    // 3.重新获取树形结构数据
134
+    const searchResultList2 = await getSearchResultByNodeId({
135
+        isAsync: "flase",
136
+        nodeId: searchResult.dep_no,
137
+        treeType: treeType.value,
138
+        relation_info_no: relationInfoNo.value,
139
+        qryDate: '20231117',
140
+
141
+    });
142
+
143
+    const treeDataMap = {};
144
+    searchResultList2.forEach(node => {
145
+        treeDataMap[node.id] = node;
146
+    });
147
+
148
+    let parentKeys = [];
149
+    let searchTreeData = [];
150
+    let searchNode = treeDataMap[searchResult.dep_no];
151
+    while (true) {
152
+        const parent = treeDataMap[searchNode.pid];
153
+        if (parent) {
154
+            // 父节点存在,则往父节点添加该子节点
155
+            if (!parent.children) {
156
+                parent.children = [];
157
+            }
158
+            parentKeys.push(parent.id);
159
+            parent.children.push(searchNode);
160
+            searchNode = parent;
161
+        } else {
162
+            // 父节点不存在,则直接添加到树形结构数据中
163
+            searchTreeData.push(searchNode);
164
+            break;
165
+        }
166
+    }
167
+    treeData.value = searchTreeData;
168
+    // 4.设置默认选中节点
169
+    nextTick(() => {
170
+        // 等到数据加载完成后,设置默认选中节点
171
+        checkedKeys.value = [searchNode.id];
172
+        expandedKeys.value = parentKeys;
173
+    });
174
+
175
+}
176
+// 搜索框 send
177
+
178
+const fieldNames = {
179
+    title: 'name',
180
+    key: 'id',
181
+};
182
+const treeData = ref([])// 树的数据
183
+const expandedKeys = ref([]);// 已展开的节点
184
+const selectedKeys = ref([]);// 已选中的节点
185
+const checkedKeys = ref([]);// 已勾选的节点
186
+const loadedKeys = ref([]); // 已加载子节点的节点
187
+// 获取机构树数据
188
+async function getDeptTreeData () {
189
+    expandedKeys.value = [];
190
+    selectedKeys.value = [];
191
+    checkedKeys.value = [];
192
+    // 清空已加载子节点的节点数组,不然切换树类型或者汇总关系时会导致展开图标消失
193
+    //loadedKeys.value = [];
194
+    treeData.value = await getDepartTreeData({
195
+        isParentType: '&&',
196
+        page_code: 'cs',
197
+        isAsync: 'true',
198
+        relation_info_no: relationInfoNo.value,
199
+        treeType: treeType.value,
200
+        qryDate: '20231117',
201
+    });
202
+    nextTick(() => {
203
+        // 等到数据加载完成后,设置默认选中节点
204
+        checkedKeys.value = [treeData.value[0].id];
205
+    });
206
+}
207
+
208
+// 节点选中时的回调
209
+function onSelect (selectedKeys, info) {
210
+}
211
+// 节点展开时的回调
212
+function onExpand (expandedKeys, info) {
213
+    console.log('wyq---------expandedKeys', expandedKeys);
214
+}
215
+// 节点选中时的回调
216
+function onCheck (checkedKeys, info) {
217
+}
218
+// 异步加载数据
219
+const onLoadData = async (treeNode) => {
220
+    return new Promise(async (resolve, reject) => {
221
+        if (treeNode.dataRef.children) {
222
+            resolve();
223
+            return;
224
+        }
225
+        try {
226
+            // data.children 是从后端获取的子节点数据
227
+            treeNode.dataRef.children = await getDepartTreeData({
228
+                id: treeNode.eventKey,
229
+                isParentType: "&&",
230
+                isAsync: "true",
231
+                page_code: 'cs',
232
+                relation_info_no: relationInfoNo.value,
233
+                treeType: treeType.value,
234
+                qryDate: '20231117',
235
+            });
236
+            // 更新 treeData
237
+            treeData.value = [...treeData.value];
238
+            resolve();
239
+        } catch (error) {
240
+            //console.error('获取数据失败', error);
241
+            reject(error);
242
+        }
243
+    });
244
+};
245
+
246
+
247
+function getCheckedNodes () {
248
+    let checkedNodes = [];
249
+    let allNodes = getAllNodes();
250
+    if (checkedKeys.value.length === 1) {
251
+        // 只选中一个节点
252
+        const node = allNodes.find(n => n.id === checkedKeys.value[0]);
253
+        checkedNodes.push(node);
254
+    } else {
255
+        // 选中多个节点
256
+        for (let i = 0; i < checkedKeys.value.length; i++) {
257
+            // 找到当前节点
258
+            const node = allNodes.find(n => n.id === checkedKeys.value[i]);
259
+            if (!checkedKeys.value.includes(node.pid)) {
260
+                // 选择的节点对应的父节点没有被选择, 则添加到结果中
261
+                checkedNodes.push(node);
262
+            }
263
+        }
264
+    }
265
+    return checkedNodes;
266
+}
267
+
268
+
269
+const getAllNodes = (nodes = treeData.value) => {
270
+    let allNodes = [];
271
+    const traverse = (nodeList) => {
272
+        nodeList.forEach(node => {
273
+            allNodes.push(node); // 收集当前节点
274
+            if (node.children) {
275
+                traverse(node.children); // 递归遍历子节点
276
+            }
277
+        });
278
+    };
279
+    traverse(nodes);
280
+    return allNodes;
281
+};
282
+
283
+</script>
284
+<style scoped>
285
+.relation-dropdown {
286
+    margin-bottom: 5px;
287
+}
288
+
289
+.relation-label {
290
+    display: inline-block;
291
+    vertical-align: middle;
292
+}
293
+
294
+.relation-select {
295
+    display: inline-block;
296
+    vertical-align: middle;
297
+    width: 200px;
298
+}
299
+
300
+.search-dropdown {
301
+    position: relative;
302
+    display: inline-block;
303
+    width: 286px;
304
+    margin-bottom: 5px
305
+        /* 设置宽度 */
306
+}
307
+
308
+.search-select {
309
+    position: absolute;
310
+    top: calc(100% + 5px);
311
+    /* 适当调整下拉列表的位置 */
312
+    left: 0;
313
+    right: 0;
314
+    z-index: 1000;
315
+    border: 1px solid #ccc;
316
+    border-radius: 4px;
317
+    /* 圆角 */
318
+    background-color: #fff;
319
+    max-height: 200px;
320
+    overflow-y: auto;
321
+    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
322
+    /* 添加阴影 */
323
+}
324
+
325
+.search-select-li {
326
+    padding: 3px 10px;
327
+    padding-left: 0px;
328
+    /* 调整内边距 */
329
+    cursor: pointer;
330
+}
331
+
332
+.search-select-li:hover {
333
+    background-color: #1890ff;
334
+    /* 使用主题色 */
335
+    color: #fff;
336
+    /* 改变文字颜色 */
337
+}
338
+</style>

+ 312
- 0
ant-design-pro-vue3/src/components/DepartTreePanel/index.vue 查看文件

@@ -0,0 +1,312 @@
1
+<template>
2
+    <a-layout style="height: 100vh;">
3
+        <a-layout-sider ref="sider" :width="siderWidth"
4
+            style="background-color: #fff; overflow: auto; white-space: nowrap;">
5
+            <div v-if="showSider">
6
+                <div class="sider-header">
7
+                    <div class="sider-header-title" style="display:inline-block;  vertical-align: middle;">机构树面板</div>
8
+                    <div class="sider-header-tool" style="display:inline-block;  vertical-align: middle;  ">
9
+                        <DoubleLeftOutlined @click="toggleSider" />
10
+                    </div>
11
+                </div>
12
+                <DepartTreePanel1 ref="departTreePanel"></DepartTreePanel1>
13
+            </div>
14
+            <div v-else>
15
+                <DoubleRightOutlined @click="toggleSider" />
16
+            </div>
17
+        </a-layout-sider>
18
+        <div class="resizer-vertical" @mousedown="startHorizontalResize" @touchstart="startHorizontalResize"
19
+            style="cursor: col-resize; background-color: #ccc; width: 5px;"></div>
20
+        <a-layout>
21
+            <a-layout-header :style="{ flex: '0 0 ' + headerHeight + 'px', padding: 0, backgroundColor: '#fff', }"
22
+                style="overflow: auto;">
23
+                <!-- <a-layout-header :style="{ height: 500 + 'px', padding: 0, backgroundColor: '#fff', }"> -->
24
+
25
+                <div v-if="showHeader">
26
+                    <div class="sider-header">
27
+                        <div class="sider-header-title" style="display:inline-block;  vertical-align: middle;">报表查询
28
+                        </div>
29
+                        <div class="sider-header-tool" style="display:inline-block;  vertical-align: middle;  ">
30
+                            <DoubleLeftOutlined @click="toggleHeader" rotate=90 />
31
+                        </div>
32
+                    </div>
33
+                    <div>
34
+                        <pro-form-grid>
35
+                            <pro-input :formItemProps="{ label: '制表日期', prop: 'levelKey' }" placeholder="请输入层级编号"
36
+                                :allowClear="true">
37
+                            </pro-input>
38
+                            <pro-select :formItemProps="{ label: '周期类型', prop: 'useYn' }" placeholder="请选择启用标志"
39
+                                :allowClear="true">
40
+                            </pro-select>
41
+                            <pro-select :formItemProps="{ label: '币种', prop: 'useYn' }" placeholder="请选择启用标志"
42
+                                :allowClear="true">
43
+                            </pro-select>
44
+                            <pro-select :formItemProps="{ label: '账套', prop: 'useYn' }" placeholder="请选择启用标志"
45
+                                :allowClear="true">
46
+                            </pro-select>
47
+                            <pro-select :formItemProps="{ label: '损益上划', prop: 'useYn' }" placeholder="请选择启用标志"
48
+                                :allowClear="true">
49
+                            </pro-select>
50
+                            <pro-select :formItemProps="{ label: '报表调整类型', prop: 'useYn' }" placeholder="请选择启用标志"
51
+                                :allowClear="true">
52
+                            </pro-select>
53
+                            <!-- <pro-select :formItemProps="{ label: '科目级别', prop: 'useYn' }" placeholder="请选择启用标志"
54
+                            :allowClear="true">
55
+                        </pro-select>
56
+                        <pro-select :formItemProps="{ label: '零余额是否打印', prop: 'useYn' }" placeholder="请选择启用标志"
57
+                            :allowClear="true">
58
+                        </pro-select> -->
59
+                        </pro-form-grid>
60
+                        <pro-form-item>
61
+                            <pro-button id="queryBtn" @click="fetchReport" :icon="h(SearchOutlined)">查询</pro-button>
62
+                        </pro-form-item>
63
+                    </div>
64
+                </div>
65
+                <div v-else class="sider-header">
66
+                    <div class="sider-header-title" style="display:inline-block;  vertical-align: middle;">
67
+                    </div>
68
+                    <div class="sider-header-tool" style="display:inline-block;  vertical-align: middle;  ">
69
+                        <DoubleRightOutlined @click="toggleHeader" rotate=90 />
70
+                    </div>
71
+                </div>
72
+            </a-layout-header>
73
+            <div class="resizer-horizontal" @mousedown="startVerticalResize" @touchstart="startVerticalResize"
74
+                style="cursor: row-resize; background-color: #ccc; height: 5px;"></div>
75
+            <a-layout>
76
+                <a-layout-content style="height: 100%; background-color: #fff; overflow: auto;">
77
+                    <!-- <a-layout-content style=" background-color: #deb887; overflow: auto; white-space: nowrap;">
78
+                    -->
79
+                    <!--遮罩层-->
80
+                    <div v-if="dragging" style="  width: 100%; height: 100%;  background: blue; display: block;">
81
+                    </div>
82
+                    <a-tabs :size="'small'" v-model:activeKey="activeKey" type="editable-card" @edit="handleTabEdit"
83
+                        :hideAdd="true">
84
+                        <a-tab-pane v-for="tab in tabs" :key="tab.key" :tab="tab.title" :closable="tab.closable">
85
+                            <iframe :ref="el => setIframeRef(el, tab.random)" :data-key="tab.key" frameborder="0"
86
+                                style="border: none; background: none; width: 100%; height: 400px">
87
+                            </iframe>
88
+                        </a-tab-pane>
89
+                    </a-tabs>
90
+                </a-layout-content>
91
+            </a-layout>
92
+        </a-layout>
93
+    </a-layout>
94
+</template>
95
+
96
+<script setup lang="jsx">
97
+import { ref, watch, h, computed, onMounted, nextTick, reactive, onBeforeUnmount } from 'vue';
98
+import { DoubleRightOutlined, DoubleLeftOutlined, SearchOutlined } from "@ant-design/icons-vue";
99
+import DepartTreePanel1 from './components/DepartTreePanel1.vue'
100
+const dragging = ref(false);
101
+// 查询结果
102
+const tabs = reactive([]);
103
+const activeKey = ref('');
104
+
105
+onMounted(() => {
106
+    window.REPORT = {
107
+        queryAccordAccNOGetLogs: (data) => {
108
+            // 在这里实现具体的业务逻辑
109
+            console.log("Data received:", data);
110
+            // 可以在这里调用其他方法或发送 AJAX 请求处理数据
111
+        },
112
+        // 可以继续添加其他方法
113
+    };
114
+});
115
+
116
+onBeforeUnmount(() => {
117
+    // 组件销毁前移除 REPORT 对象,避免内存泄漏
118
+    delete window.REPORT;
119
+});
120
+
121
+function fetchReport () {
122
+    const data = {
123
+        reportNameCN: '业务状况表',
124
+        rpt_date: '20231117',
125
+        cyc_type: '06',
126
+    }
127
+    const random = Math.random().toString().split('.')[1];
128
+    const divId = `report_result_div${random}`;
129
+    // Add a new tab
130
+    const newTab = {
131
+        title: data.reportNameCN,
132
+        key: divId,
133
+        closable: true,
134
+        random: random
135
+    };
136
+    tabs.push(newTab);
137
+    activeKey.value = divId;
138
+    nextTick(() => {
139
+        // const iframe = document.getElementById('reportIframe');
140
+        const iframe = document.getElementById(`report_result_iframe${random}`);
141
+
142
+
143
+        let url = '/zz-pack/report/query/zz/ywzkb'
144
+        let html = '<form action="' + url + '" method="post" target="_self" id="postData_form_newZcfzb">' +
145
+            '<input  name="relation_info_noDepartTreePanel" type="hidden" value="AAAAAA"/>' +
146
+            '<input  name="rpt_date" type="hidden" value="20231117"/>' +
147
+            '<input  name="cyc_type" type="hidden" value="06"/>' +
148
+            '<input  name="cur_no" type="hidden" value="1"/>' +
149
+            '<input  name="sob_no" type="hidden" value="10"/>' +
150
+            '<input  name="sh_flag" type="hidden" value=""/>' +
151
+            '<input  name="adj_type" type="hidden" value=""/>' +
152
+            '<input  name="acc_lvl" type="hidden" value="4"/>' +
153
+            '<input  name="zero_print_yn" type="hidden" value="01"/>' +
154
+            '<input  name="exrate_type" type="hidden" value=""/>' +
155
+            '<input  name="is_gather" type="hidden" value=""/>' +
156
+            '<input  name="stdd_no" type="hidden" value="2"/>' +
157
+            '<input  name="tel_no" type="hidden" value="1"/>' +
158
+            '<input  name="dep_no" type="hidden" value="1"/>' +
159
+            '<input  name="rptDepName" type="hidden" value="[1800000009]东华银行"/>' +
160
+            '<input  name="br_no" type="hidden" value="1"/>' +
161
+            '<input  name="tab_name" type="hidden" value="v_gl_sub_coll_day1"/>' +
162
+            '<input  name="reportNameCN" type="hidden" value="业务状况表(年报)人民币20231117"/>' +
163
+            '<input  name="reportNameEN" type="hidden" value="ywzkb"/>' +
164
+            '<input  name="reportFileName" type="hidden" value="ywzkb"/>' +
165
+            '<input  name="title_name" type="hidden" value="业务状况表"/>' +
166
+            '<input  name="reportModuleName" type="hidden" value="zz"/>' +
167
+            '<input  name="curName" type="hidden" value="人民币"/>' +
168
+            '<input  name="timeStamp" type="hidden" value="币种名称"/>' +
169
+            '<input  name="zero_print_ynSql" type="hidden" value=""/>' +
170
+            '</form>';
171
+        iframe.contentWindow.document.write(html);
172
+        iframe.contentWindow.document.getElementById('postData_form_newZcfzb').submit();
173
+        iframe.onload = () => {
174
+            console.log('iframe loaded', random);
175
+
176
+        };
177
+    })
178
+}
179
+
180
+
181
+function setIframeRef (el, random) {
182
+    if (el) {
183
+        el.name = `report_result_iframe${random}`;
184
+        el.id = `report_result_iframe${random}`;
185
+    }
186
+}
187
+
188
+function handleTabEdit (targetKey, action) {
189
+    if (action === 'remove') {
190
+        const index = tabs.findIndex(tab => tab.key === targetKey);
191
+        if (index !== -1) {
192
+            tabs.splice(index, 1);
193
+            // 关闭当前标签页后,默认选中第一个标签页
194
+            if (tabs.length > 0) {
195
+                activeKey.value = tabs[0].key;
196
+            } else {
197
+                activeKey.value = null;
198
+            }
199
+        }
200
+    }
201
+}
202
+
203
+const siderWidth = ref(290);//左布局初始宽度
204
+const headerHeight = ref(220);//顶部布局初始高度
205
+
206
+const startX = ref(0);
207
+const startY = ref(0);
208
+const startWidth = ref(0);
209
+const startHeight = ref(0);
210
+
211
+function startHorizontalResize (event) {
212
+    dragging.value = true;
213
+    startX.value = event.clientX;
214
+    startWidth.value = siderWidth.value;
215
+    document.addEventListener('mousemove', onHorizontalMouseMove);
216
+    document.addEventListener('mouseup', stopHorizontalResize);
217
+}
218
+
219
+function onHorizontalMouseMove (event) {
220
+    const currentX = event.clientX;
221
+    const diffX = currentX - startX.value;
222
+    siderWidth.value = Math.max(startWidth.value + diffX, 0);
223
+}
224
+
225
+function stopHorizontalResize () {
226
+    dragging.value = false;
227
+    document.removeEventListener('mousemove', onHorizontalMouseMove);
228
+    document.removeEventListener('mouseup', stopHorizontalResize);
229
+}
230
+
231
+function startVerticalResize (event) {
232
+    startY.value = event.clientY;
233
+    startHeight.value = headerHeight.value;
234
+    document.addEventListener('mousemove', onVerticalMouseMove);
235
+    document.addEventListener('mouseup', stopVerticalResize);
236
+}
237
+
238
+function onVerticalMouseMove (event) {
239
+    const currentY = event.clientY;
240
+    const diffY = currentY - startY.value;
241
+    headerHeight.value = Math.max(startHeight.value + diffY, 0);
242
+}
243
+
244
+function stopVerticalResize () {
245
+    document.removeEventListener('mousemove', onVerticalMouseMove);
246
+    document.removeEventListener('mouseup', stopVerticalResize);
247
+}
248
+
249
+// 左侧布局显示隐藏
250
+const showSider = ref(true);
251
+const showHeader = ref(true);
252
+function toggleSider () {
253
+    if (showSider.value) {
254
+        siderWidth.value = 15;
255
+    } else {
256
+        siderWidth.value = 290;
257
+    }
258
+    showSider.value = !showSider.value;
259
+}
260
+
261
+function toggleHeader () {
262
+    if (showHeader.value) {
263
+        headerHeight.value = 30;
264
+    } else {
265
+        headerHeight.value = 220;
266
+    }
267
+    showHeader.value = !showHeader.value;
268
+}
269
+
270
+
271
+</script>
272
+
273
+<style>
274
+.resizer-vertical {
275
+    user-select: none;
276
+}
277
+
278
+.resizer-horizontal {
279
+    user-select: none;
280
+}
281
+
282
+
283
+.sider-header {
284
+    height: 34px;
285
+    line-height: 34px;
286
+    border: 0;
287
+    background-color: #1890ff;
288
+    padding: 0 14px;
289
+    margin: 2px 0;
290
+    display: flex;
291
+    position: relative;
292
+}
293
+
294
+.sider-header-title {
295
+    height: 34px;
296
+    line-height: 34px;
297
+    color: #fff;
298
+    font-weight: bold;
299
+    font-size: 16px;
300
+    margin: 0;
301
+    padding: 0;
302
+}
303
+
304
+.sider-header-tool {
305
+    right: 10px;
306
+    width: auto;
307
+    position: absolute;
308
+    top: 50%;
309
+    margin-top: -17px;
310
+    overflow: hidden;
311
+}
312
+</style>

+ 1
- 1
ant-design-pro-vue3/src/components/GlobalFooter/index.vue 查看文件

@@ -16,7 +16,7 @@ import { isMobile } from '@/utils/device'
16 16
 <style lang="less" scoped>
17 17
 .footer {
18 18
     padding: 0 16px;
19
-    margin: 48px 0 24px;
19
+    margin: 5px 0 5px;
20 20
     text-align: center;
21 21
 
22 22
     .links {

+ 12
- 2
ant-design-pro-vue3/src/components/MultiTab/index.vue 查看文件

@@ -6,7 +6,8 @@
6 6
                 <a-tab-pane v-for="page in pages" :key="page.fullPath" :closable="pages.length > 1" style="height: 0">
7 7
                     <template #tab>
8 8
                         <a-dropdown :trigger="['contextmenu']">
9
-                            <span :style="{ userSelect: 'none' }">{{ page.meta.customTitle || $t(page.meta.title) }}</span>
9
+                            <span :style="{ userSelect: 'none' }">{{ page.meta.customTitle || $t(page.meta.title)
10
+                                }}</span>
10 11
                             <template #overlay>
11 12
                                 <a-menu @click="({ key, item, domEvent }) => {
12 13
                                     closeMenuClick(key, page.fullPath);
@@ -78,6 +79,7 @@ const selectedLastPath = () => {
78 79
 
79 80
 const onEdit = (targetKey, action) => {
80 81
     //proxy[action](targetKey)
82
+    console.log('multiTab onEdit', targetKey, action)
81 83
     remove(targetKey)
82 84
 }
83 85
 const remove = (targetKey) => {
@@ -133,6 +135,7 @@ const closeAll = (e) => {
133 135
     })
134 136
 }
135 137
 const closeMenuClick = (key: string, route) => {
138
+    console.log('MultiTab-closeMenuClick', key, route)
136 139
     const allFun = { closeAll, closeRight, closeLeft, closeSelf }
137 140
     allFun[key](route)
138 141
 }
@@ -141,14 +144,21 @@ watch(
141 144
     () => router.currentRoute.value,
142 145
     (newVal) => {
143 146
         activeKey.value = newVal.fullPath
147
+        console.log('MultiTab -newVal', newVal, newVal.fullPath);
148
+        console.log('MultiTab -fullPathList', fullPathList);
149
+
150
+
144 151
         if (fullPathList.indexOf(newVal.fullPath) < 0) {
145 152
             fullPathList.push(newVal.fullPath)
146
-            pages.push(newVal)
153
+            pages.push(newVal);
154
+            console.log('MultiTab -pages', pages);
155
+
147 156
         }
148 157
     }
149 158
 )
150 159
 
151 160
 watch(activeKey, (newPathKey) => {
161
+    console.log('MultiTab -activeKey', activeKey, newPathKey);
152 162
     router.push({ path: newPathKey })
153 163
 })
154 164
 </script>

+ 48
- 9
ant-design-pro-vue3/src/components/OpenModelButton/index.vue 查看文件

@@ -1,9 +1,9 @@
1 1
 <template>
2 2
     <span>
3
-        <a-button type="primary" @click="click" v-bind="$attrs">
3
+        <a-button type="primary" @click="click" @addData="getList" v-bind="$attrs">
4 4
             {{ text ?? '打开' }}
5 5
         </a-button>
6
-        <component v-if="visible" :is="is" :visible="visible" @close:modal="visible = false" />
6
+        <component v-if="visible" :is="is" :visible="visible" @addDataDemo="getList" @close:modal="visible = false" />
7 7
     </span>
8 8
 </template>
9 9
 
@@ -11,6 +11,10 @@
11 11
 import { computed } from 'vue';
12 12
 import { ref } from 'vue'
13 13
 import { useStore } from 'vuex';
14
+import { message } from "ant-design-vue";
15
+const emit = defineEmits(['addData']);
16
+
17
+
14 18
 const store = useStore();
15 19
 
16 20
 const props = defineProps({
@@ -19,6 +23,7 @@ const props = defineProps({
19 23
         required: true
20 24
     },
21 25
     text: String,
26
+    beforeShow: [String, Function],
22 27
     afterShow: [String, Function],
23 28
     payload: Object
24 29
 })
@@ -31,18 +36,52 @@ const is = computed(() => {
31 36
     }
32 37
 })
33 38
 
39
+
34 40
 const visible = ref(false)
35 41
 function click () {
36
-    visible.value = true;
37
-    const afterShow = props.afterShow
38
-    if (afterShow) {
39
-        if (typeof afterShow === 'function') {
40
-            afterShow(props.payload)
41
-        } else if (typeof afterShow === 'string') {
42
-            store.dispatch(afterShow, props.payload)
42
+    const beforeShow = props.beforeShow
43
+    if (beforeShow) {
44
+        beforeShowModal();
45
+    } else {
46
+        // 先显示页面,再执行异步操作
47
+        visible.value = true;
48
+        // 再执行异步操作
49
+        const afterShow = props.afterShow
50
+        if (afterShow) {
51
+            if (typeof afterShow === 'function') {
52
+                console.log("wyq--afterShow-function" + afterShow)
53
+                afterShow(props.payload)
54
+            } else if (typeof afterShow === 'string') {
55
+                console.log("wyq--afterShow-string" + afterShow)
56
+                store.dispatch(afterShow, props.payload)
57
+            }
58
+        }
59
+    }
60
+}
61
+
62
+async function beforeShowModal () {
63
+    try {
64
+        // 先执行异步操作
65
+        const beforeShow = props.beforeShow
66
+        if (typeof beforeShow === 'function') {
67
+            await beforeShow(props.payload)
68
+        } else if (typeof beforeShow === 'string') {
69
+            await store.dispatch(beforeShow, props.payload)
43 70
         }
71
+    } catch (error) {
72
+        message.error('打开模态框前业务处理失败' + error);
73
+    } finally {
74
+        visible.value = true;
44 75
     }
45 76
 }
77
+
78
+
79
+function getList () {
80
+    console.log("wyq--OpenModelButton-getList 触发成功了")
81
+    //this.$emit('addData');
82
+    emit('addData');
83
+
84
+}
46 85
 </script>
47 86
 
48 87
 <style lang="scss" scoped></style>

+ 2
- 1
ant-design-pro-vue3/src/components/ProForm/fields/ProDatePicker/index.vue 查看文件

@@ -6,7 +6,8 @@
6 6
 </template>
7 7
 <script>
8 8
 import dayjs from 'dayjs';
9
-import moment from 'moment'
9
+import 'dayjs/locale/zh-cn';
10
+// import moment from 'moment'
10 11
 export default {
11 12
     name: 'ProDatePicker',
12 13
     props: {

+ 14
- 5
ant-design-pro-vue3/src/components/ProForm/fields/ProSelect/index.vue 查看文件

@@ -16,7 +16,7 @@ import {
16 16
 export default {
17 17
     name: 'ProSelect',
18 18
     props: {
19
-        value: [String, Array],
19
+        modelValue: [String, Array], // 更改为 modelValue
20 20
         optionData: Array,
21 21
         readText: {
22 22
             type: [String, Array],
@@ -25,19 +25,22 @@ export default {
25 25
         readValue: {
26 26
             type: [String, Array],
27 27
             default: null
28
-        }
28
+        },
29
+        formItemProps: Object, // 定义formItemProps prop
29 30
     },
30 31
     inject: {
31 32
         pageIsReadOnly: {
32 33
             default: false
33 34
         }
34 35
     },
36
+    emits: ['update:modelValue', 'change', 'select', 'easyUiSelect', 'input'], // 添加 update:modelValue 事件
35 37
     watch: {
36 38
         //判断下拉框的值是否有改变
37 39
         svalue (val, oldVal) {
38 40
             const that = this
39 41
             if (val != oldVal) {
40 42
                 that.$emit('input', this.svalue)
43
+                that.$emit('update:modelValue', this.svalue) // 确保使用 update:modelValue
41 44
                 if (this.$attrs["collapse-tags"] != undefined) {
42 45
                     this.$nextTick(() => {
43 46
                         //下拉框视口总宽度
@@ -65,8 +68,11 @@ export default {
65 68
                 }
66 69
             }
67 70
         },
68
-        value (val, oldVal) {
69
-            this.svalue = this.value
71
+        modelValue: {
72
+            immediate: true,
73
+            handler (newVal) {
74
+                this.svalue = newVal;
75
+            }
70 76
         },
71 77
         optionData (val, oldVal) {
72 78
             if (JSON.stringify(val) != JSON.stringify(oldVal)) {
@@ -76,6 +82,7 @@ export default {
76 82
 
77 83
     },
78 84
     mounted () {
85
+        console.log("wyq-ProSelect mounted", this.$attrs);
79 86
         const optionData = this.optionData
80 87
         //初始话下拉框的值
81 88
         const {
@@ -117,11 +124,13 @@ export default {
117 124
         handleChange (data, node, event) {
118 125
             // this.$emit('input', data);
119 126
             this.$emit('change', data, node, event)
127
+            this.$emit('update:modelValue', data);  // 确保使用 update:modelValue
120 128
         },
121 129
         handleSelect (value, option) {
122 130
             this.$emit('select', value, option)
123 131
             //兼容easyUi写法
124 132
             this.$emit('easyUiSelect', { item_no: value, item_name: option.title })
133
+            this.$emit('update:modelValue', value); // 在选择时也更新 modelValue
125 134
         },
126 135
         // 设置下拉数据源
127 136
         setSelectOptions (data) {
@@ -143,7 +152,7 @@ export default {
143 152
     data () {
144 153
         return {
145 154
             options: [],
146
-            svalue: this.value
155
+            svalue: this.modelValue // 初始化 svalue
147 156
         }
148 157
     }
149 158
 }

+ 276
- 0
ant-design-pro-vue3/src/components/ProForm/fields/ProSelect3/index.vue 查看文件

@@ -0,0 +1,276 @@
1
+<template>
2
+    <a-select ref="selectRef" v-model:value="localValue" placeholder="请选择" @change="onChange" @select="onSelect"
3
+        v-bind="$attrs">
4
+        <a-select-option v-for="item in localOptions" :key="item[localfieldNames.value]"
5
+            :value="item[localfieldNames.value]" v-bind="item">
6
+            {{ item[localfieldNames.label] }}
7
+        </a-select-option>
8
+    </a-select>
9
+</template>
10
+<script setup lang="jsx">
11
+import { isEmpty } from '@/utils/validate'
12
+
13
+import { getOptions } from '@/api/common'
14
+import { ref, defineProps, defineExpose, defineEmits, onMounted, onBeforeUnmount, watch, nextTick, computed } from 'vue';
15
+const emits = defineEmits(['update:value', 'onChange', 'onSelect']);
16
+const props = defineProps({
17
+    value: {
18
+        type: [String, Array, Number],
19
+        default: '',
20
+        required: true
21
+    },
22
+    url: {
23
+        type: String,
24
+        default: ''
25
+    },
26
+    tableName: {
27
+        type: String,
28
+        default: ''
29
+    },
30
+    colName: {
31
+        type: String,
32
+        default: ''
33
+    },
34
+    options: {
35
+        type: Array,
36
+        default: () => []
37
+    },
38
+    formItemProps: {
39
+        type: Object,
40
+        default: () => { }
41
+    },
42
+    selectType: {
43
+        type: String,
44
+        default: ''
45
+    },
46
+    pageInterfaceNo: {
47
+        type: String,
48
+        default: ''
49
+    },
50
+    sobNo: {
51
+        type: String,
52
+        default: ''
53
+    },
54
+    correct: {
55
+        type: Boolean,
56
+        default: false
57
+    },
58
+    cascadeFlag: {
59
+        type: Boolean,
60
+        default: false
61
+    },
62
+    fieldNames: {
63
+        type: Object,
64
+        default: () => {
65
+            return {
66
+                value: 'item_no',
67
+                label: 'item_name'
68
+            }
69
+        }
70
+    }
71
+});
72
+const selectRef = ref(null);
73
+const localOptions = ref([]);
74
+const localfieldNames = ref(props.fieldNames);
75
+const localValue = computed({
76
+    get: () => {
77
+        console.log('wyq:pro-select-获取localValue值:', props.value);
78
+        return props.value;
79
+    },
80
+    set: (value) => {
81
+        console.log('wyq:pro-select-更改localValue值:', value);
82
+        emits('update:value', value);
83
+    }
84
+});
85
+
86
+watch(() => props.options, (newOptions) => {
87
+    localOptions.value = newOptions;
88
+});
89
+
90
+if (props.selectType === 'accLvl') {
91
+    watch(() => props.sobNo, async () => {
92
+        // 监听
93
+        console.log('wyq:pro-select-监听sobNo值:', props.sobNo);
94
+        await getAccLvlOptionsData();
95
+    });
96
+}
97
+const onSelect = (value, option) => {
98
+    emits('onSelect', value, option);
99
+}
100
+
101
+const onChange = (value, option) => {
102
+    console.log('wyq:pro-select-更改localValue值:', value, option);
103
+    emits('onChange', value, option);
104
+}
105
+
106
+onMounted(async () => {
107
+    await getLocalOptionsData();
108
+});
109
+
110
+async function getLocalOptionsData () {
111
+    if (!isEmpty(props.options)) {
112
+        localOptions.value = props.options;
113
+    } else if (!isEmpty(props.selectType)) {
114
+        if (props.selectType === 'relationNo') {
115
+            await getDepartRelationOptionsData();
116
+        } else if (props.selectType === 'accLvl') {
117
+            await getAccLvlOptionsData();
118
+        } else if (props.selectType === 'curr') {
119
+            await getCurOptionsData();
120
+        } else if (props.selectType === 'perSys') {
121
+            await getPerSysOptionsData();
122
+        } else if (props.selectType === 'periodic') {
123
+            await getPeriodicOptionsData();
124
+        }
125
+    } else {
126
+        let queyUrl = '';
127
+        let params;
128
+        if (!isEmpty(props.tableName) && !isEmpty(props.colName)) {
129
+            queyUrl = '/system/select/options/loadTbl'
130
+            params = {
131
+                tableName: props.tableName,
132
+                colName: props.colName
133
+            }
134
+        } else {
135
+            queyUrl = props.url;
136
+            params = {};
137
+        }
138
+        if (queyUrl) {
139
+            await getOptions(queyUrl, params).then((response) => {
140
+                if (response != null) {
141
+                    localOptions.value = response
142
+                }
143
+            })
144
+            if (!isEmpty(localOptions.value) && localOptions.value.length > 0) {
145
+                const defaultOption = findOptionByField('is_default', 'Y');
146
+                if (!isEmpty(defaultOption)) {
147
+                    localValue.value = defaultOption[localfieldNames.value.value];
148
+                    emits('onSelect', localValue.value, defaultOption);
149
+                }
150
+            }
151
+        }
152
+    }
153
+}
154
+
155
+async function getAccLvlOptionsData () {
156
+    if (!isEmpty(props.sobNo)) {
157
+        let queyUrl = '/system/common/action/serachAccLvl';
158
+        let params = {
159
+            sob_no: props.sobNo,
160
+            addEndFlag: props.addEndFlag
161
+        }
162
+        await getOptions(queyUrl, params).then((response) => {
163
+            if (response != null) {
164
+                localOptions.value = response
165
+            }
166
+        })
167
+
168
+        if (!isEmpty(localOptions.value) && localOptions.value.length > 0) {
169
+            const defaultOption = localOptions.value[localOptions.value.length - 1];
170
+            if (!isEmpty(defaultOption)) {
171
+                localValue.value = defaultOption[localfieldNames.value.value];
172
+                emits('onSelect', localValue.value, defaultOption);
173
+            }
174
+        }
175
+    }
176
+}
177
+
178
+async function getDepartRelationOptionsData () {
179
+    let queyUrl = '/system/select/options/relationInfoNo.do';
180
+    let params = {
181
+        pageInterfaceNo: props.pageInterfaceNo
182
+    };
183
+    await getOptions(queyUrl, params).then((response) => {
184
+        if (response != null) {
185
+            localOptions.value = response
186
+        }
187
+    })
188
+    if (!isEmpty(localOptions.value) && localOptions.value.length > 0) {
189
+        const option = findOption("AAAAAA");
190
+        console.log('wyq:pro-select-获取departRelationOptionsData值:', localOptions.value, option);
191
+        if (!isEmpty(option)) {
192
+            localValue.value = option[localfieldNames.value.value];
193
+            emits('onSelect', localValue.value, option);
194
+        }
195
+    }
196
+}
197
+
198
+async function getCurOptionsData () {
199
+    let queyUrl = '/system/select/options/currencyLoad.do';
200
+    let params = {
201
+        correct: props.correct
202
+    };
203
+    await getOptions(queyUrl, params).then((response) => {
204
+        if (response != null) {
205
+            localOptions.value = response
206
+        }
207
+    })
208
+
209
+    if (!isEmpty(localOptions.value) && localOptions.value.length > 0) {
210
+        let defaultValue = '';
211
+        queyUrl = '/im/dhc/zz/automake/zzmanage/report/GetForeignCurConttroller.do';
212
+        params = {};
213
+        await getOptions(queyUrl, params).then((response) => {
214
+            if (response != null) {
215
+                defaultValue = response.foreign_cur_no;
216
+            }
217
+        })
218
+        const option = findOption(defaultValue);
219
+        if (!isEmpty(option)) {
220
+            localValue.value = option[localfieldNames.value.value];
221
+            emits('onSelect', localValue.value, option);
222
+        }
223
+    }
224
+}
225
+
226
+async function getPerSysOptionsData () {
227
+    let queyUrl = '/system/select/options/getSystemInfo.do';
228
+    let params = {
229
+        cascadeFlag: props.cascadeFlag
230
+    }
231
+
232
+    await getOptions(queyUrl, params).then((response) => {
233
+        if (response != null) {
234
+            localOptions.value = response
235
+            localfieldNames.value = {
236
+                value: 'ITEM_NO',
237
+                label: 'ITEM_NAME'
238
+            }
239
+        }
240
+    })
241
+    console.log('wyq:pro-select-获取getPerSysOptionsData值:', localfieldNames.value);
242
+
243
+    console.log('wyq:pro-select-获取getPerSysOptionsData值:', localOptions.value);
244
+
245
+}
246
+
247
+async function getPeriodicOptionsData () {
248
+    let queyUrl = '/system/select/options/periodicComponent.do';
249
+    let params = {
250
+        cycTypeField: 'zcfzb'
251
+    }
252
+    await getOptions(queyUrl, params).then((response) => {
253
+        if (response != null) {
254
+            localOptions.value = response
255
+        }
256
+    })
257
+    if (!isEmpty(localOptions.value) && localOptions.value.length > 0) {
258
+        const defaultOption = findOptionByField('is_default', 'Y');
259
+        if (!isEmpty(defaultOption)) {
260
+            const defaultValue = defaultOption[localfieldNames.value.value];
261
+            localValue.value = defaultValue;
262
+            console.log('wyq:pro-select-获取CycType值:', defaultValue, defaultOption);
263
+            emits('onSelect', defaultValue, defaultOption);
264
+        }
265
+    }
266
+}
267
+
268
+const findOption = (value) => {
269
+    return findOptionByField(localfieldNames.value.value, value);
270
+};
271
+
272
+const findOptionByField = (field, value) => {
273
+    const option = localOptions.value.find(option => option[field] === value);
274
+    return { ...option }
275
+};
276
+</script>

+ 10
- 3
ant-design-pro-vue3/src/components/ProForm/fields/ProSelectTree/index.vue 查看文件

@@ -15,9 +15,9 @@
15 15
                 </pro-tree>
16 16
                 <!-- 单选树 -->
17 17
                 <pro-tree v-else id="tree-option" ref="selectTree" :accordion="accordion" :data="dataOptions"
18
-                    v-model:selectedKeys="valueId" :dataList="dataList" :props="props" :node-key="props.key"
19
-                    :default-expanded-keys="defaultExpandedKey" :show-checkbox="false" :expand-on-click-node="false"
20
-                    highlight-current :isProSelectTree="true" :expandTier="expandTier"
18
+                    v-model:selectedKeys="valueId" :dataList="dataList" :props="props" :fieldNames="props"
19
+                    :node-key="props.key" :default-expanded-keys="defaultExpandedKey" :show-checkbox="false"
20
+                    :expand-on-click-node="false" highlight-current :isProSelectTree="true" :expandTier="expandTier"
21 21
                     proSelectTreeStyle="max-height: 300px;overflow: auto;" @node-click="handleNodeClick" v-bind="$attrs"
22 22
                     :filterNodeName="filterNodeName">
23 23
                 </pro-tree>
@@ -127,6 +127,11 @@ export default {
127 127
             dataList: [], //列表数据
128 128
             loading: false,
129 129
             visiable: false,
130
+            props: {
131
+                title: 'name',
132
+                key: 'id',
133
+                children: 'children'
134
+            }
130 135
         }
131 136
     },
132 137
     mounted () {
@@ -188,9 +193,11 @@ export default {
188 193
         //处理下拉数据
189 194
         dealData () {
190 195
             //处理下拉数据
196
+            console.log("xxxdealData", this.options);
191 197
             const { options, type, url } = this.$attrs
192 198
             if (options || !isEmpty(this.options)) {
193 199
                 this.dataOptions = options || this.options
200
+                console.log("xxxdataOptions", this.dataOptions);
194 201
             } else {
195 202
                 if (type == 'sob_tree') {
196 203
                     this.getDepartmentTree("sobTree")

+ 169
- 0
ant-design-pro-vue3/src/components/ProForm/fields/ProSelectTree2/index.vue 查看文件

@@ -0,0 +1,169 @@
1
+<template>
2
+    <h2>下拉树控件</h2>
3
+    <a-select ref="selectRef" v-model:value="selectedDisplayValue" :open="isDropdownOpen" placeholder="请选择"
4
+        :allowClear="true" @clear="handleClear" @click="handleSelectClick" style="width: 500px">
5
+        <template #dropdownRender>
6
+            <pro-tree3 ref="treeRef" :treeType="treeType" :relationNo="relationNo" v-model:txBrNo="txBrNo"
7
+                v-model:sobNo="sobNo" v-model:expandedKeys="expandedKeys" v-model:selectedKeys="selectedKeys"
8
+                v-model:checkedKeys="checkedKeys" @select="onSelect" @expand="onExpand" @check="onCheck"
9
+                v-bind="$attrs"></pro-tree3>
10
+        </template>
11
+    </a-select>
12
+</template>
13
+<script setup>
14
+import { ref, defineProps, defineExpose, onMounted, onBeforeUnmount, watch, nextTick, provide, defineEmits } from 'vue';
15
+// 定义组件接收的 props
16
+const props = defineProps({
17
+    // 树类型
18
+    treeType: {
19
+        type: String,
20
+        required: true
21
+    },
22
+    // 机构树汇总关系
23
+    relationNo: {
24
+        type: String,
25
+        default: ''
26
+    },
27
+    // 机构
28
+    txBrNo: {
29
+        type: String,
30
+        default: ''
31
+    },
32
+    // 账套
33
+    sobNo: {
34
+        type: String,
35
+        default: ''
36
+    },
37
+
38
+    selectedKeys: {
39
+        type: Array,
40
+        default: () => []
41
+    },
42
+    checkedKeys: {
43
+        type: Array,
44
+        default: () => []
45
+    },
46
+    expandedKeys: {
47
+        type: Array,
48
+        default: () => []
49
+    }
50
+});
51
+// 定义自定义事件,用于通知父组件
52
+const emits = defineEmits(['update:txBrNo', 'update:sobNo', 'update:selectedKeys', 'update:checkedKeys', 'update:expandedKeys', 'onCheck', 'onSelect', 'onExpand']);
53
+// 由于 props 是响应式的,直接使用解构赋值
54
+const { treeType, relationNo, txBrNo, sobNo, selectedKeys, expandedKeys } = props;
55
+const checkedKeys = ref([...props.checkedKeys]);
56
+
57
+// 用于显示在下拉框中的选中值
58
+const selectedDisplayValue = ref('');
59
+// 是否显示下拉框
60
+const isDropdownOpen = ref(false);
61
+
62
+// 处理 a-select 清除事件
63
+const handleClear = () => {
64
+    console.log('wyq-handleClear', props.checkedKeys);
65
+    console.log('wyq-handleClear', checkedKeys.value);
66
+    // wyq-TODO:待实现功能,一进行清理就死循环了
67
+    // checkedKeys.value = [];
68
+    selectedDisplayValue.value = '';
69
+};
70
+
71
+// 处理选择框点击事件
72
+const handleSelectClick = () => {
73
+    // 清空搜索框 wyq-TODO:实现搜索功能
74
+    // searchValue.value = '';
75
+    // searchResultList.value = [];
76
+    isDropdownOpen.value = true;
77
+};
78
+
79
+
80
+
81
+
82
+const selectRef = ref(null);
83
+const treeRef = ref(null);
84
+const handleDocumentClick = (event) => {
85
+    if (
86
+        selectRef.value &&
87
+        treeRef.value &&
88
+        !selectRef.value.$el.contains(event.target) &&
89
+        !treeRef.value.$el.contains(event.target)
90
+    ) {
91
+        isDropdownOpen.value = false;
92
+    }
93
+};
94
+
95
+onMounted(() => {
96
+    document.addEventListener('click', handleDocumentClick);
97
+});
98
+
99
+onBeforeUnmount(() => {
100
+    document.removeEventListener('click', handleDocumentClick);
101
+});
102
+
103
+// 根据不同类型的树监听相应参数的变化
104
+if (props.treeType === 'deptTree') {
105
+    watch(() => props.relationNo, (newRelationNo) => {
106
+        relationNo = newRelationNo;
107
+    });
108
+    watch(txBrNo, (newTxBrNo) => {
109
+        emits('update:txBrNo', newTxBrNo);
110
+    });
111
+} else if (props.treeType === 'sobTree') {
112
+    watch(() => props.txBrNo, (newtxBrNo) => {
113
+        txBrNo = newtxBrNo;
114
+    });
115
+    watch(sobNo, (newSobNo) => {
116
+        emits('update:sobNo', newSobNo);
117
+    });
118
+} else if (props.treeType === 'sobItemTree') {
119
+    watch(() => props.sobNo, (newSobNo) => {
120
+        sobNo = newSobNo;
121
+    });
122
+}
123
+
124
+watch(() => props.checkedKeys, (newCheckedKeys) => {
125
+    checkedKeys.value = [...newCheckedKeys];
126
+});
127
+watch(() => props.selectedKeys, (newSelectedKeys) => {
128
+    selectedKeys.value = [...newSelectedKeys];
129
+});
130
+watch(() => props.expandedKeys, (newExpandedKeys) => {
131
+    expandedKeys.value = [...newExpandedKeys];
132
+});
133
+
134
+watch(
135
+    checkedKeys,
136
+    (newCheckedKeys) => {
137
+        console.log('wyq-checkedKeys', newCheckedKeys);
138
+        emits('update:checkedKeys', newCheckedKeys);
139
+        //checkedKeys.value = [...newCheckedKeys];
140
+    }
141
+);
142
+watch(
143
+    selectedKeys,
144
+    (newSelectedKeys) => {
145
+        emits('update:selectedKeys', newSelectedKeys);
146
+    },
147
+    { deep: true }
148
+);
149
+watch(
150
+    expandedKeys,
151
+    (newExpandedKeys) => {
152
+        emits('update:expandedKeys', newExpandedKeys);
153
+    },
154
+    { deep: true }
155
+);
156
+
157
+const onCheck = (checkedKeys, info) => {
158
+    emits('onCheck', checkedKeys, info);
159
+};
160
+
161
+const onSelect = (selectedKeys, info) => {
162
+    emits('onSelect', selectedKeys, info);
163
+};
164
+
165
+const onExpand = (expandedKeys, info) => {
166
+    emits('onExpand', expandedKeys, info);
167
+};
168
+
169
+</script>

+ 381
- 0
ant-design-pro-vue3/src/components/ProForm/fields/ProSelectTree3/index.vue 查看文件

@@ -0,0 +1,381 @@
1
+<template>
2
+    <a-select ref="selectRef" v-model:value="localValue" :mode="mode" placeholder="请选择" :tagRender="tagRender"
3
+        :options="optionData" :fieldNames="optionFieldNames" :maxTagCount=1 :allowClear="true" @clear="onClear"
4
+        :open="isDropdownOpen" @click="onSelectClick" :showSearch="false">
5
+        <template #dropdownRender>
6
+            <div ref="dropdownRef">
7
+                <pro-tree3 ref="proTreeRef" :tree-data="localTreeData" :fieldNames="fieldNames"
8
+                    v-model:value="localValue" v-model:stddNo="stddNo" :showCheckbox="showCheckbox" :multiple="multiple"
9
+                    :isAsync="isAsync" :treeType="treeType" :isStopPropagation="isStopPropagation"
10
+                    :isClearSearchResult="isClearSearchResult" :isWithoutDsc="isWithoutDsc" @getNodes="getNodes"
11
+                    @onNode="onNode" v-bind="$attrs">
12
+                </pro-tree3>
13
+            </div>
14
+        </template>
15
+    </a-select>
16
+</template>
17
+<script setup lang="jsx">
18
+import { isEmpty } from '@/utils/validate'
19
+import { findNodes } from '@/utils/treeUtil'
20
+import { getTreeData } from '@/api/treeDataApi';
21
+import { ref, defineProps, defineEmits, onMounted, onBeforeUnmount, watch, nextTick, computed, h } from 'vue';
22
+// 定义组件接收的 props
23
+const props = defineProps({
24
+    value: {
25
+        type: [String, Array, Number],
26
+        required: true
27
+    },
28
+    treeType: {
29
+        type: String,
30
+        default: ''
31
+    },
32
+    isAsync: {
33
+        type: Boolean,
34
+        default: false
35
+    },
36
+    relationNo: {
37
+        type: String,
38
+        default: ''
39
+    },
40
+    brNos: {
41
+        type: Array,
42
+        default: () => []
43
+    },
44
+    stddNo: {
45
+        type: String,
46
+        default: ''
47
+    },
48
+    sobNo: {
49
+        type: [String, Array],
50
+        default: ''
51
+    },
52
+    treeData: {
53
+        type: Array,
54
+        default: () => []
55
+    },
56
+    multiple: {
57
+        type: Boolean,
58
+        default: false
59
+    },
60
+    showCheckbox: {
61
+        type: Boolean,
62
+        default: false
63
+    },
64
+    formItemProps: {
65
+        type: Object,
66
+        default: () => { }
67
+    },
68
+    isStopPropagation: {
69
+        // 是否阻止冒泡
70
+        type: Boolean,
71
+        default: true
72
+    },
73
+    isClearSearchResult: {
74
+        // 是否自动清空搜索结果
75
+        type: Boolean,
76
+        default: false
77
+    },
78
+    isWithoutDsc: {
79
+        // 是否不包含后代节点返回
80
+        type: Boolean,
81
+        default: false
82
+    },
83
+    mode: {
84
+        type: String,
85
+        default: 'multiple'
86
+    },
87
+    fieldNames: {
88
+        type: Object,
89
+        default: () => {
90
+            return {
91
+                key: 'id',
92
+                title: 'name',
93
+                children: 'children'
94
+            }
95
+        }
96
+    }
97
+
98
+});
99
+const emits = defineEmits(['update:value', 'update:stddNo', 'get-nodes']);
100
+console.log('wyq:pro-select-tree-接收参数:', props);
101
+const selectRef = ref(null);
102
+const dropdownRef = ref(null);
103
+const proTreeRef = ref(null);
104
+const isDropdownOpen = ref(false);
105
+const optionData = ref([]);
106
+const localTreeData = ref([]);
107
+const optionFieldNames = {
108
+    value: props.fieldNames.key,
109
+    label: props.fieldNames.title,
110
+};
111
+const localValue = computed({
112
+    // 从父组件获取值
113
+    get: () => {
114
+        console.log('wyq:pro-select-tree-获取localValue值:', props.value);
115
+        return props.value;
116
+    },
117
+    // 向父组件传递更新
118
+    set: (value) => {
119
+        console.log('wyq:pro-select-tree-更改localValue值:', value);
120
+        emits('update:value', value);
121
+    }
122
+});
123
+
124
+const stddNo = computed({
125
+    // 从父组件获取值
126
+    get: () => {
127
+        if (props.treeType === 'sobTree') {
128
+            return props.stddNo;
129
+        }
130
+        return '';
131
+    },
132
+    // 向父组件传递更新
133
+    set: (value) => {
134
+        if (props.treeType === 'sobTree') {
135
+            emits('update:stddNo', value);
136
+        }
137
+    }
138
+});
139
+
140
+function getNodes (value, nodes) {
141
+    console.log('wyq:pro-select-tree-getNodes 获取节点:', value, nodes);
142
+    optionData.value = nodes;
143
+    emits('get-nodes', value, nodes);
144
+}
145
+
146
+function onNode (item) {
147
+    isDropdownOpen.value = false;
148
+}
149
+
150
+// 点击其他区域隐藏下拉框
151
+const handleDocumentClick = (event) => {
152
+    if (
153
+        selectRef.value &&
154
+        dropdownRef.value &&
155
+        !selectRef.value.$el.contains(event.target) &&
156
+        !dropdownRef.value.contains(event.target)
157
+    ) {
158
+        isDropdownOpen.value = false;
159
+    }
160
+};
161
+
162
+const onClear = () => {
163
+    // localValue.value = [];
164
+    console.log('wyq:pro-select-tree-清空选择', Array.isArray(localValue.value) ? [] : '');
165
+    if (Array.isArray(localValue.value)) {
166
+        localValue.value = [];
167
+    } else {
168
+        const val = '10';
169
+        localValue.value = val;
170
+    }
171
+    //localValue.value = Array.isArray(localValue.value) ? [] : '';
172
+};
173
+
174
+// 处理选择框点击事件
175
+const onSelectClick = () => {
176
+    // 清空上一次搜索框内容和结果
177
+    if (proTreeRef.value) {
178
+        proTreeRef.value.onClearSearch();
179
+    }
180
+    isDropdownOpen.value = true;
181
+};
182
+
183
+
184
+// 监听shuTreeData变化,更新localTreeData
185
+watch(() => props.treeData, (newTreeData) => {
186
+    localTreeData.value = newTreeData;
187
+});
188
+
189
+// 根据不同类型的树监听相应参数的变化
190
+if (props.treeType === 'deptTree') {
191
+    watch(() => props.relationNo, async () => {
192
+        // 监听机构汇总关系发生变化,重新请求机构树
193
+        await getTreeTypeData();
194
+    });
195
+} else if (props.treeType === 'sobTree') {
196
+    // 监听账套树
197
+    watch(() => props.brNos, async () => {
198
+        // TODO : 这个地方可能会被 pro-tree 和 pro-select-tree都调用
199
+        // 监听机构发生变化,重新请求账套树
200
+        await getTreeTypeData();
201
+    });
202
+} else if (props.treeType === 'sobItemTree') {
203
+    watch(() => props.sobNo, async () => {
204
+        // 监听账套发生变化,重新请求科目树
205
+        await getTreeTypeData();
206
+    });
207
+}
208
+
209
+// 定义 tagRender 函数
210
+const tagRender = (props) => {
211
+    const isLastValue = localValue.value[localValue.value.length - 1] === props.value;
212
+    return h('span', { class: 'no-wrap' }, [
213
+        props.label,
214
+        !isLastValue && ',',
215
+    ]);
216
+};
217
+
218
+onMounted(async () => {
219
+    document.addEventListener('click', handleDocumentClick);
220
+    await getLocalTreeData();
221
+});
222
+
223
+onBeforeUnmount(() => {
224
+    document.removeEventListener('click', handleDocumentClick);
225
+});
226
+
227
+
228
+async function getLocalTreeData () {
229
+    console.log('wyq:pro-select-tree-准备树数据');
230
+    if (!isEmpty(props.treeData)) {
231
+        localTreeData.value = props.treeData;
232
+        if (!isEmpty(props.value)) {
233
+            const nodes = findNodes(localTreeData, props.fieldNames.key, props.value);
234
+            optionData.value = nodes;
235
+            emits('get-nodes', props.value, nodes);
236
+        }
237
+    } else if (!isEmpty(props.treeType)) {
238
+        // 如果 props.treeData 不存在,则请求后端接口获取树数据
239
+        await getTreeTypeData();
240
+    }
241
+}
242
+
243
+async function getTreeTypeData () {
244
+    const { treeData, defaultValue, defaultNode, defaultStddNo } = await getTreeData(props, {});
245
+    if (!isEmpty(treeData) && treeData.length > 0) {
246
+        localTreeData.value = treeData;
247
+
248
+        // 使用 nextTick 确保在 DOM 更新后执行后续操作
249
+        // await nextTick();
250
+
251
+        if (!isEmpty(defaultValue)) {
252
+            optionData.value = defaultNode;
253
+            localValue.value = defaultValue;
254
+            emits('get-nodes', defaultValue, defaultNode);
255
+        }
256
+
257
+        if (!isEmpty(defaultStddNo) && props.treeType === 'sobTree') {
258
+            stddNo.value = defaultStddNo;
259
+        }
260
+    }
261
+    console.log('wyq:pro-select-tree-获取树数据完成', treeData);
262
+}
263
+
264
+
265
+
266
+// async function prepareTreeData () {
267
+//     try {
268
+//         if (!isEmpty(props.treeData)) {
269
+//             // 如果 props.treeData 存在,则直接使用 props.treeData
270
+//             localTreeData.value = props.treeData;
271
+//             // 处理默认值
272
+//             if (!isEmpty(props.value)) {
273
+//                 optionData.value = findNodes(localTreeData, props.fieldNames.key, [props.value]);
274
+//             }
275
+//         } else if (!isEmpty(props.treeType)) {
276
+//             // 如果 props.treeData 不存在,则请求后端接口获取树数据
277
+//             await fetchTreeData();
278
+//         }
279
+//     } catch (error) {
280
+//         // 处理 fetchTreeData 可能抛出的错误
281
+//         console.error('Error occurred while preparing tree data:', error);
282
+//     }
283
+// }
284
+
285
+// async function fetchTreeData () {
286
+//     try {
287
+//         // 从 useTreeData 中获取 getTreeData 函数
288
+//         const { getTreeData } = useTreeData(props, {});
289
+//         // 调用 getTreeData 函数获取树数据
290
+//         localTreeData.value = await getTreeData();
291
+
292
+//         // 如果树数据为空,提前返回
293
+//         if (isEmpty(localTreeData.value)) {
294
+//             return;
295
+//         }
296
+
297
+//         // 使用 nextTick 确保在 DOM 更新后执行后续操作
298
+//         await nextTick();
299
+
300
+//         // 计算默认值
301
+//         const defaultValues = getDefaultValues(localTreeData.value, props);
302
+
303
+//         // 如果默认值不为空
304
+//         if (!isEmpty(defaultValues)) {
305
+//             if (props.showCheckbox === true) {
306
+//                 // 复选框模式
307
+//                 localValue.value = defaultValues;
308
+//             } else {
309
+//                 localValue.value = defaultValues;
310
+//             }
311
+//         }
312
+//     } catch (error) {
313
+//         // 处理 getTreeData 函数调用时可能出现的错误
314
+//         message.error(`获取数据失败: ${error.message}`);
315
+//     }
316
+// }
317
+
318
+// // 提取计算默认值的逻辑到单独的函数
319
+// function getDefaultValues (treeData, props) {
320
+//     let defaultValues = '';
321
+//     switch (props.treeType) {
322
+//         case 'deptTree':
323
+//             // 机构树默认值为第一个节点
324
+//             if (treeData.length > 0) {
325
+//                 defaultValues = [treeData[0][props.fieldNames.key]];
326
+//                 optionData.value = findNodes(treeData, props.fieldNames.key, [...defaultValues]);
327
+//             }
328
+//             break;
329
+//         case 'sobTree':
330
+//             // 账套树默认值为default_yn为Y的节点
331
+//             const defaultNodes = findNodes(treeData, 'default_yn', 'Y');
332
+//             if (!isEmpty(defaultNodes) && defaultNodes.length > 0) {
333
+//                 stddNo.value = defaultNodes[0]['pid'].split('@')[0];
334
+//                 defaultValues = [defaultNodes[0][props.fieldNames.key]];
335
+//                 optionData.value = [defaultNodes[0]];
336
+//             }
337
+//             break;
338
+//         case 'sobItemTree':
339
+//             // 科目树无默认值
340
+//             break;
341
+//         default:
342
+//             break;
343
+//     }
344
+//     console.log('wyq:pro-select-tree-默认值:', defaultValues, optionData.value);
345
+//     return defaultValues;
346
+// }
347
+</script>
348
+
349
+<style scoped>
350
+.dropdown-content {
351
+    /* 设置固定的高度和宽度 */
352
+    max-height: 300px;
353
+    /* width: 500px; */
354
+    /* 设置溢出时显示滚动条 */
355
+    overflow: auto;
356
+    /* 可以根据需要添加其他样式 */
357
+    /* border: 1px solid #ccc; */
358
+    padding: 8px;
359
+}
360
+
361
+.dropdown-content2 {
362
+    /* 设置固定的高度和宽度 */
363
+    max-height: 300px;
364
+    /* width: 500px; */
365
+    /* 设置溢出时显示滚动条 */
366
+    overflow: auto;
367
+    /* 防止内容换行 */
368
+    white-space: nowrap;
369
+    /* 当内容宽度超过元素宽度时显示横向滚动条 */
370
+    overflow-x: auto;
371
+    /* 可以根据需要添加其他样式 */
372
+    /* border: 1px solid #ccc; */
373
+    padding: 8px;
374
+}
375
+
376
+.no-wrap-tag {
377
+    white-space: nowrap;
378
+    overflow: hidden;
379
+    text-overflow: ellipsis;
380
+}
381
+</style>

+ 9
- 0
ant-design-pro-vue3/src/components/ProForm/main.js 查看文件

@@ -8,7 +8,12 @@ import ProInputNumber from './fields/ProInputNumber/index.vue'
8 8
 import ProInputNumberRange from './fields/ProInputNumberRange/index.vue'
9 9
 
10 10
 import ProSelect from './fields/ProSelect/index.vue'
11
+import ProSelect3 from './fields/ProSelect3/index.vue'
12
+
11 13
 import ProSelectTree from './fields/ProSelectTree/index.vue'
14
+//import ProSelectTree2 from './fields/ProSelectTree2/index.vue'
15
+import ProSelectTree3 from './fields/ProSelectTree3/index.vue'
16
+
12 17
 import ProRadio from './fields/ProRadio/index.vue'
13 18
 import ProCascader from './fields/ProCascader/index.vue'
14 19
 import ProCheckbox from './fields/ProCheckbox/index.vue'
@@ -29,6 +34,10 @@ ProFormMount.install = function (Vue){
29 34
     Vue.component(ProInputNumberRange.name,ProInputNumberRange)
30 35
     Vue.component(ProSelect.name,ProSelect)
31 36
     Vue.component(ProSelectTree.name,ProSelectTree)
37
+    Vue.component('ProSelect3',ProSelect3)
38
+    //Vue.component('ProSelectTree2',ProSelectTree2)
39
+    Vue.component('ProSelectTree3',ProSelectTree3)
40
+
32 41
     Vue.component(ProRadio.name,ProRadio)
33 42
     Vue.component(ProCascader.name,ProCascader)
34 43
     Vue.component(ProCheckbox.name,ProCheckbox)

+ 262
- 0
ant-design-pro-vue3/src/components/ProLayout3/index.vue 查看文件

@@ -0,0 +1,262 @@
1
+<template>
2
+    <div :class="['split-container', direction === 'vertical' ? 'vertical' : 'horizontal']">
3
+        <div class="split-pane" :style="{ flex: firstPaneFlex }">
4
+            <!-- 如果父组件传递了 firstTitle 则展示标题 -->
5
+            <div v-if="firstTitle">
6
+                <div v-if="!firstCollapsed" class="pane-title">
7
+                    <span style="color: #fff;font-size: 16px; font-weight: bold;">{{ firstTitle }}</span>
8
+                    <DoubleLeftOutlined class="title-icon" :rotate="direction === 'vertical' ? 90 : 0"
9
+                        @click="toggleCollapse('first')" />
10
+                </div>
11
+                <div v-else class="pane-title">
12
+                    <span v-if="direction === 'vertical'" style="color: #fff;font-size: 16px; font-weight: bold;">{{
13
+                        firstTitle }}</span>
14
+                    <DoubleRightOutlined :rotate="direction === 'vertical' ? 90 : 0" @click="toggleCollapse('first')" />
15
+                </div>
16
+            </div>
17
+            <div>
18
+                <slot name="first-title"></slot>
19
+            </div>
20
+            <div v-show="!firstCollapsed" class="pane-content">
21
+                <!-- <div v-if="isDragging" style="width: 100%; height: 100%;  background: yellow; display: block;"></div> -->
22
+                <slot name="first"></slot>
23
+                <div v-if="isDragging" class="overlay"
24
+                    style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 10; background: rgba(0, 0, 0, 0);">
25
+                </div>
26
+            </div>
27
+
28
+        </div>
29
+        <div class="split-handle" @mousedown="startDrag" @touchstart="startDrag"></div>
30
+        <div class="split-pane" :style="{ flex: secondPaneFlex }">
31
+            <!-- 如果父组件传递了 secondTitle 则展示标题 -->
32
+            <div v-if="secondTitle">
33
+                <div class="pane-title">
34
+                    <span>{{ secondTitle }}</span>
35
+                    <DoubleLeftOutlined class="title-icon" @click="toggleCollapse('first')" />
36
+                </div>
37
+            </div>
38
+            <div class="pane-content">
39
+                <!-- <div v-if="isDragging" style="width: 100%; height: 100%;  background: blue; display: block;"></div> -->
40
+                <slot name="second"></slot>
41
+                <div v-if="isDragging" class="overlay"
42
+                    style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 10; background: rgba(0, 0, 0, 0);">
43
+                </div>
44
+            </div>
45
+        </div>
46
+    </div>
47
+</template>
48
+
49
+<script lang="ts" setup>
50
+import { ref, onMounted, onUnmounted } from 'vue';
51
+import { DoubleRightOutlined, DoubleLeftOutlined } from "@ant-design/icons-vue";
52
+
53
+const props = defineProps({
54
+    direction: {
55
+        type: String,
56
+        default: 'horizontal',
57
+        // horizontal: 左右布局,vertical: 上下布局
58
+        validator: (value: string) => ['horizontal', 'vertical'].includes(value)
59
+    },
60
+    initialRatio: {
61
+        type: Number,
62
+        default: 0.5
63
+    },
64
+    firstTitle: {
65
+        type: String,
66
+        default: ''
67
+    },
68
+    secondTitle: {
69
+        type: String,
70
+        default: ''
71
+    }
72
+});
73
+
74
+const isDragging = ref(false);
75
+const startX = ref(0);
76
+const startY = ref(0);
77
+const firstPaneFlex = ref(props.initialRatio);
78
+const secondPaneFlex = ref(1 - props.initialRatio);
79
+
80
+const containerRef = ref<HTMLDivElement | null>(null);
81
+
82
+// 新增折叠状态
83
+const firstCollapsed = ref(false);
84
+const secondCollapsed = ref(false);
85
+
86
+const toggleCollapse = (pane: 'first' | 'second') => {
87
+    if (pane === 'first') {
88
+        firstCollapsed.value = !firstCollapsed.value;
89
+        if (firstCollapsed.value) {
90
+            if (props.direction === 'horizontal') {
91
+                firstPaneFlex.value = 0.02;
92
+
93
+            } else {
94
+                firstPaneFlex.value = 0.07;
95
+
96
+            }
97
+            secondPaneFlex.value = 1 - firstPaneFlex.value;
98
+            console.log('firstCollapsed', firstPaneFlex.value, secondPaneFlex.value);
99
+
100
+        } else {
101
+            firstPaneFlex.value = props.initialRatio;
102
+            secondPaneFlex.value = 1 - props.initialRatio;
103
+        }
104
+    } else {
105
+        secondCollapsed.value = !secondCollapsed.value;
106
+        if (secondCollapsed.value) {
107
+            secondPaneFlex.value = 0.02;
108
+            firstPaneFlex.value = 1 - secondPaneFlex.value;
109
+        } else {
110
+            secondPaneFlex.value = 1 - props.initialRatio;
111
+            firstPaneFlex.value = props.initialRatio;
112
+        }
113
+    }
114
+};
115
+
116
+
117
+const startDrag = (event: MouseEvent | TouchEvent) => {
118
+    event.stopPropagation();
119
+    event.preventDefault();
120
+    isDragging.value = true;
121
+    if (event instanceof MouseEvent) {
122
+        startX.value = event.clientX;
123
+        startY.value = event.clientY;
124
+    } else {
125
+        startX.value = event.touches[0].clientX;
126
+        startY.value = event.touches[0].clientY;
127
+    }
128
+    document.addEventListener('mousemove', onDrag);
129
+    document.addEventListener('touchmove', onDrag);
130
+    document.addEventListener('mouseup', endDrag);
131
+    document.addEventListener('touchend', endDrag);
132
+};
133
+
134
+const onDrag = (event: MouseEvent | TouchEvent) => {
135
+    if (!isDragging.value || !containerRef.value) return;
136
+    const containerRect = containerRef.value.getBoundingClientRect();
137
+    let delta;
138
+    if (props.direction === 'horizontal') {
139
+        const currentX = event instanceof MouseEvent ? event.clientX : event.touches[0].clientX;
140
+        delta = currentX - startX.value;
141
+        const totalWidth = containerRect.width;
142
+        const newFlex = firstPaneFlex.value + delta / totalWidth;
143
+        if (newFlex > 0 && newFlex < 1) {
144
+            firstPaneFlex.value = newFlex;
145
+            secondPaneFlex.value = 1 - newFlex;
146
+            startX.value = currentX;
147
+        }
148
+    } else {
149
+        const currentY = event instanceof MouseEvent ? event.clientY : event.touches[0].clientY;
150
+        delta = currentY - startY.value;
151
+        const totalHeight = containerRect.height;
152
+        const newFlex = firstPaneFlex.value + delta / totalHeight;
153
+        if (newFlex > 0 && newFlex < 1) {
154
+            firstPaneFlex.value = newFlex;
155
+            secondPaneFlex.value = 1 - newFlex;
156
+            startY.value = currentY;
157
+        }
158
+    }
159
+};
160
+
161
+const endDrag = () => {
162
+    isDragging.value = false;
163
+    document.removeEventListener('mousemove', onDrag);
164
+    document.removeEventListener('touchmove', onDrag);
165
+    document.removeEventListener('mouseup', endDrag);
166
+    document.removeEventListener('touchend', endDrag);
167
+};
168
+
169
+onMounted(() => {
170
+    containerRef.value = document.querySelector('.split-container') as HTMLDivElement;
171
+});
172
+
173
+onUnmounted(() => {
174
+    document.removeEventListener('mousemove', onDrag);
175
+    document.removeEventListener('touchmove', onDrag);
176
+    document.removeEventListener('mouseup', endDrag);
177
+    document.removeEventListener('touchend', endDrag);
178
+});
179
+</script>
180
+
181
+<style scoped>
182
+.split-container {
183
+    display: flex;
184
+    width: 100%;
185
+    height: 100%;
186
+}
187
+
188
+.horizontal {
189
+    /* 默认为水平方向 */
190
+    flex-direction: row;
191
+}
192
+
193
+.vertical {
194
+    /* 垂直方向 */
195
+    flex-direction: column;
196
+}
197
+
198
+/* .split-pane {
199
+    overflow: auto;
200
+} */
201
+.split-pane {
202
+    display: flex;
203
+    flex-direction: column;
204
+    overflow: hidden;
205
+    /* 改为hidden防止双滚动条 */
206
+    height: 100%;
207
+}
208
+
209
+.split-handle {
210
+    /*水平方向的拖拽手柄 */
211
+    cursor: col-resize;
212
+    background-color: #ccc;
213
+    width: 5px;
214
+
215
+
216
+}
217
+
218
+.vertical .split-handle {
219
+    /* 垂直方向的拖拽手柄 */
220
+    cursor: row-resize;
221
+    height: 5px;
222
+    width: 100%;
223
+
224
+}
225
+
226
+.pane-title {
227
+    height: 34px;
228
+    padding: 5px 12px;
229
+    background-color: #1890ff;
230
+    display: flex;
231
+    justify-content: space-between;
232
+    align-items: center;
233
+    flex-shrink: 0;
234
+    border-bottom: 1px solid #ddd;
235
+}
236
+
237
+/* .pane-content {
238
+    overflow: auto;
239
+} */
240
+
241
+.pane-content {
242
+    flex-grow: 1;
243
+    overflow: auto;
244
+    min-height: 0;
245
+}
246
+
247
+.title-icon {
248
+    /* color: #666;
249
+    font-size: 12px; */
250
+    margin-left: 8px;
251
+
252
+    transition: transform 0.2s;
253
+}
254
+
255
+.split-handle:hover {
256
+    background-color: #999;
257
+}
258
+
259
+.split-handle:active {
260
+    background-color: #666;
261
+}
262
+</style>

+ 93
- 0
ant-design-pro-vue3/src/components/ProReport/DepartPanel.vue 查看文件

@@ -0,0 +1,93 @@
1
+<template>
2
+    <!--1-机构汇总关系-->
3
+    <div>
4
+        <span>汇总关系:</span>
5
+        <pro-select3 v-model:value="localRelationNo" @onSelect="onSelect" class="relation-select" placeholder="请选择汇总关系"
6
+            :allowClear="true" selectType="relationNo" :pageInterfaceNo="pageInterfaceNo">
7
+        </pro-select3>
8
+    </div>
9
+    <!--2-机构树类型-->
10
+    <div style="margin-bottom: -10px">
11
+        <a-tabs type="card" v-model:activeKey="localTreeType" :tabBarGutter="5">
12
+            <a-tab-pane v-for="tab in localTreeTabs" :key="tab.key" :tab="tab.title">
13
+            </a-tab-pane>
14
+        </a-tabs>
15
+    </div>
16
+    <!--3-机构树-->
17
+    <pro-tree3 v-model:value="localBrNos" :relationNo="localRelationNo" treeType="deptTree" @getNodes="getNodes"
18
+        :showCheckbox="true" :isWithoutDsc="true"></pro-tree3>
19
+</template>
20
+<script setup lang="jsx">
21
+import { ref, defineProps, reactive, defineExpose, defineEmits, onMounted, onBeforeUnmount, watch, nextTick, computed } from 'vue';
22
+const props = defineProps({
23
+    relationNo: {
24
+        type: String,
25
+        default: '',
26
+        required: true
27
+    },
28
+    brNos: {
29
+        type: Array,
30
+        default: () => [],
31
+        required: true
32
+    },
33
+    pageInterfaceNo: {
34
+        type: String,
35
+        default: 'zzsearch_01_01_02'
36
+    },
37
+    // treeType: {
38
+    //     type: String,
39
+    //     default: '0'
40
+    // }
41
+});
42
+const emits = defineEmits(['update:brNos', 'update:relationNo', 'get-nodes', 'onSelect']);
43
+const localTreeType = ref('0');
44
+const localTreeTabs = [
45
+    {
46
+        key: '0',
47
+        title: '账务树',
48
+    },
49
+    {
50
+        key: '1',
51
+        title: '对比树',
52
+    },
53
+    {
54
+        key: '2',
55
+        title: '报送树',
56
+    }
57
+];
58
+
59
+const localRelationNo = computed({
60
+    get: () => {
61
+        return props.relationNo;
62
+    },
63
+    set: (value) => {
64
+        emits('update:relationNo', value);
65
+    }
66
+});
67
+
68
+const localBrNos = computed({
69
+    get: () => {
70
+        return props.brNos;
71
+    },
72
+    set: (value) => {
73
+        emits('update:brNos', value);
74
+    }
75
+});
76
+
77
+function getNodes (value, nodes) {
78
+    console.log('DepartPanel-getNodes', value, nodes);
79
+    emits('get-nodes', value, nodes);
80
+}
81
+
82
+const onSelect = (value, option) => {
83
+    emits('onSelect', value, option);
84
+}
85
+</script>
86
+
87
+<style scoped>
88
+.relation-select {
89
+    /* display: inline-block; */
90
+    /* vertical-align: middle; */
91
+    width: 170px;
92
+}
93
+</style>

+ 173
- 0
ant-design-pro-vue3/src/components/ProReport/ResultPanel.vue 查看文件

@@ -0,0 +1,173 @@
1
+<template>
2
+    <div>
3
+        <a-tabs :size="'small'" v-model:activeKey="activeKey" type="editable-card" @edit="handleTabEdit"
4
+            :hideAdd="true">
5
+            <a-tab-pane v-for="tab in tabs" :key="tab.key" :tab="tab.title" :closable="tab.closable">
6
+                <div style="overflow: auto;">
7
+                    <iframe :ref="el => setIframeRef(el, tab.random)" :data-key="tab.key" frameborder="0"
8
+                        style="border: none; background: none; width: 100%; height: 800px">
9
+                    </iframe>
10
+                    <!-- <div style="height:100px;">
11
+                        查询结果<br>
12
+                        查询结果<br>
13
+                    </div> -->
14
+                </div>
15
+            </a-tab-pane>
16
+        </a-tabs>
17
+    </div>
18
+</template>
19
+<script setup lang="jsx">
20
+import settings from '@/settings'
21
+import { ref, defineProps, reactive, defineExpose, defineEmits, onMounted, onBeforeUnmount, watch, nextTick, computed } from 'vue';
22
+const props = defineProps({
23
+});
24
+const systemPrefix = settings.systemPrefix;
25
+const activeKey = ref('');
26
+const tabs = reactive([]);
27
+function handleTabEdit (targetKey, action) {
28
+    if (action === 'remove') {
29
+        const index = tabs.findIndex(tab => tab.key === targetKey);
30
+        if (index !== -1) {
31
+            tabs.splice(index, 1);
32
+            // 关闭当前标签页后,默认选中第一个标签页
33
+            if (tabs.length > 0) {
34
+                activeKey.value = tabs[0].key;
35
+            } else {
36
+                activeKey.value = null;
37
+            }
38
+        }
39
+    }
40
+}
41
+
42
+const iframeRefPrefix = "iframeRef";
43
+function setIframeRef (el, random) {
44
+    if (el) {
45
+        el.id = `${iframeRefPrefix}${random}`;
46
+        el.name = `${iframeRefPrefix}${random}`;
47
+    }
48
+}
49
+
50
+const searchParams = [
51
+    {
52
+        relation_info_noDepartTreePanel: 'AAAAAA',
53
+        rpt_date: '20231117',
54
+        cyc_type: '06',
55
+        cur_no: '1',
56
+        sob_no: '10',
57
+        sh_flag: '',
58
+        adj_type: '',
59
+        acc_lvl: '4',
60
+        zero_print_yn: '01',
61
+        exrate_type: '',
62
+        is_gather: '',
63
+        stdd_no: '2',
64
+        tel_no: '1',
65
+        dep_no: '1',
66
+        rptDepName: '[1800000009]东华银行',
67
+        br_no: '1',
68
+        tab_name: 'v_gl_sub_coll_day1',
69
+        reportNameCN: '业务状况表(年报)人民币20231117',
70
+        reportNameEN: 'ywzkb',
71
+        reportFileName: 'ywzkb',
72
+        reportModuleName: 'zz',
73
+        curName: '人民币',
74
+        timeStamp: '币种名称',
75
+        title_name: '业务状况表',
76
+    }
77
+]
78
+
79
+const search = () => {
80
+    const data = {
81
+        reportNameCN: '业务状况表',
82
+        rpt_date: '20231117',
83
+        cyc_type: '06',
84
+    }
85
+    const random = Math.random().toString().split('.')[1];
86
+    const divId = `report_result_div${random}`;
87
+    // Add a new tab
88
+    const newTab = {
89
+        title: data.reportNameCN,
90
+        key: divId,
91
+        closable: true,
92
+        random: random
93
+    };
94
+    tabs.push(newTab);
95
+    activeKey.value = divId;
96
+    nextTick(() => {
97
+        // const iframe = document.getElementById('reportIframe');
98
+        const iframe = document.getElementById(`${iframeRefPrefix}${random}`);
99
+        let url = '/zz-pack/report/query/zz/ywzkb'
100
+        let html = '<form action="' + url + '" method="post" target="_self" id="postData_form_newZcfzb">' +
101
+            '<input  name="relation_info_noDepartTreePanel" type="hidden" value="AAAAAA"/>' +
102
+            '<input  name="rpt_date" type="hidden" value="20231117"/>' +
103
+            '<input  name="cyc_type" type="hidden" value="06"/>' +
104
+            '<input  name="cur_no" type="hidden" value="1"/>' +
105
+            '<input  name="sob_no" type="hidden" value="10"/>' +
106
+            '<input  name="sh_flag" type="hidden" value=""/>' +
107
+            '<input  name="adj_type" type="hidden" value=""/>' +
108
+            '<input  name="acc_lvl" type="hidden" value="4"/>' +
109
+            '<input  name="zero_print_yn" type="hidden" value="01"/>' +
110
+            '<input  name="exrate_type" type="hidden" value=""/>' +
111
+            '<input  name="is_gather" type="hidden" value=""/>' +
112
+            '<input  name="stdd_no" type="hidden" value="2"/>' +
113
+            '<input  name="tel_no" type="hidden" value="1"/>' +
114
+            '<input  name="dep_no" type="hidden" value="1"/>' +
115
+            '<input  name="rptDepName" type="hidden" value="[1800000009]东华银行"/>' +
116
+            '<input  name="br_no" type="hidden" value="1"/>' +
117
+            '<input  name="tab_name" type="hidden" value="v_gl_sub_coll_day1"/>' +
118
+            '<input  name="reportNameCN" type="hidden" value="业务状况表(年报)人民币20231117"/>' +
119
+            '<input  name="reportNameEN" type="hidden" value="ywzkb"/>' +
120
+            '<input  name="reportFileName" type="hidden" value="ywzkb"/>' +
121
+            '<input  name="title_name" type="hidden" value="业务状况表"/>' +
122
+            '<input  name="reportModuleName" type="hidden" value="zz"/>' +
123
+            '<input  name="curName" type="hidden" value="人民币"/>' +
124
+            '<input  name="timeStamp" type="hidden" value="币种名称"/>' +
125
+            '<input  name="zero_print_ynSql" type="hidden" value=""/>' +
126
+            '</form>';
127
+        iframe.contentWindow.document.write(html);
128
+        iframe.contentWindow.document.getElementById('postData_form_newZcfzb').submit();
129
+        iframe.onload = () => {
130
+            console.log('iframe loaded', random);
131
+        };
132
+    })
133
+}
134
+
135
+const search2 = (formData) => {
136
+    console.log('formData', formData);
137
+}
138
+
139
+
140
+defineExpose({ search, search2 });
141
+
142
+
143
+const searchReport = async (param) => {
144
+    //1.准备数据
145
+
146
+}
147
+
148
+const readyReportData = (param) => {
149
+    const data = {
150
+
151
+    }
152
+}
153
+
154
+
155
+
156
+const parseParam = (param, key) => {
157
+    let paramStr = "";
158
+    // 检查 param 是否是基本数据类型
159
+    if (typeof param === 'string' || typeof param === 'number' || typeof param === 'boolean') {
160
+        paramStr += `<input type='hidden' name='${key}' value='${param}'/>`;
161
+    } else if (param instanceof Object) {
162
+        // 如果是对象或数组,递归处理每个属性或元素
163
+        Object.keys(param).forEach(i => {
164
+            const value = param[i];
165
+            if (value !== undefined && value !== null && value !== window) {
166
+                const newKey = key === null || key === undefined ? i : (Array.isArray(param) ? `${key}[${i}]` : `${key}.${i}`);
167
+                paramStr += parseParam(value, newKey);
168
+            }
169
+        });
170
+    }
171
+    return paramStr;
172
+}
173
+</script>

+ 1142
- 1081
ant-design-pro-vue3/src/components/ProTable/index.vue
文件差异内容过多而无法显示
查看文件


+ 205
- 0
ant-design-pro-vue3/src/components/ProTree2/index.vue 查看文件

@@ -0,0 +1,205 @@
1
+<template>
2
+    <div>
3
+        <h2> 子组件, 树类型{{ treeType }}, 机构汇总关系:{{ relationNo }},机构:{{ txBrNo }},账套:{{ sobNo }},选中:{{ checkedKeys }},展开:{{
4
+            expandedKeys }}</h2>
5
+        <a-tree :tree-data="treeData" @check="onCheck" v-model:checkedKeys="localCheckedKeys"
6
+            v-model:expandedKeys="localExpandedKeys" v-bind="$attrs">
7
+        </a-tree>
8
+    </div>
9
+</template>
10
+
11
+<script setup>
12
+import { ref, defineProps, defineExpose, onMounted, watch, nextTick, provide, defineEmits } from 'vue';
13
+// 定义组件接收的 props
14
+const props = defineProps({
15
+    treeType: {
16
+        type: String,
17
+        required: true
18
+    },
19
+    relationNo: {
20
+        type: String,
21
+        default: ''
22
+    },
23
+    txBrNo: {
24
+        type: String,
25
+        default: ''
26
+    },
27
+    sobNo: {
28
+        type: String,
29
+        default: ''
30
+    },
31
+    checkedKeys: {
32
+        type: Array,
33
+        default: () => []
34
+    },
35
+    expandedKeys: {
36
+        type: Array,
37
+        default: () => []
38
+    },
39
+    // 这里假设传递树数据,实际根据你的业务调整
40
+    treeData: {
41
+        type: Array,
42
+        default: () => []
43
+    }
44
+});
45
+
46
+// 定义自定义事件,用于通知父组件 checkedKeys 变化
47
+const emits = defineEmits(['onCheck', 'update:txBrNo', 'update:sobNo']);
48
+
49
+
50
+// 本地的 checkedKeys 变量,初始化为父组件传递的值
51
+const localCheckedKeys = ref([...props.checkedKeys]);
52
+const localExpandedKeys = ref([...props.expandedKeys]);
53
+
54
+// 监听父组件传递的 checkedKeys 变化
55
+watch(() => props.checkedKeys, (newValue) => {
56
+    localCheckedKeys.value = [...newValue];
57
+});
58
+
59
+// 监听父组件传递的 checkedKeys 变化
60
+watch(() => props.expandedKeys, (newValue) => {
61
+    localExpandedKeys.value = [...newValue];
62
+});
63
+
64
+// 根据不同类型的树监听相应参数的变化
65
+if (props.treeType === 'deptTree') {
66
+    watch(() => props.relationNo, async () => {
67
+        await fetchTreeData();
68
+    });
69
+} else if (props.treeType === 'sobTree') {
70
+    // 监听账套树
71
+    watch(() => props.txBrNo, async () => {
72
+        await fetchTreeData();
73
+    });
74
+} else if (props.treeType === 'sobItemTree') {
75
+    watch(() => props.sobNo, async () => {
76
+        await fetchTreeData();
77
+    });
78
+}
79
+// 树数据
80
+const treeData = ref([]);
81
+
82
+
83
+const fetchTreeData = async () => {
84
+    let params = {};
85
+    let apiUrl = '';
86
+    switch (props.treeType) {
87
+        case 'deptTree':
88
+            // params = { relationNo: props.relationNo };
89
+            // apiUrl = '/api/deptTree'; // 替换为实际的机构树接口地址
90
+            if (props.relationNo === 'AAAAAA') {
91
+                treeData.value = [
92
+                    {
93
+                        title: '[811000]马鞍山市汇总',
94
+                        key: '1',
95
+                        children: [
96
+                            {
97
+                                title: '[811001]马鞍山市花山区',
98
+                                key: '1-1'
99
+                            },
100
+                            {
101
+                                title: '[811001]马鞍山市雨山区',
102
+                                key: '1-2'
103
+                            }
104
+                        ]
105
+                    }
106
+                ];
107
+                // localCheckedKeys.value = ['1-1'];
108
+                // localExpandedKeys.value = ['1'];
109
+            } else {
110
+                treeData.value = [
111
+                    {
112
+                        title: '[812000]当涂市汇总',
113
+                        key: '2',
114
+                        children: [
115
+                            {
116
+                                title: '[812001]当涂市博望区汇总',
117
+                                key: '2-1'
118
+                            },
119
+                            {
120
+                                title: '[812001]当涂市和县区汇总',
121
+                                key: '2-2'
122
+                            }
123
+                        ]
124
+                    }
125
+                ];
126
+                // localCheckedKeys.value = ['2-1'];
127
+                // localExpandedKeys.value = ['2'];
128
+            }
129
+            //console.log('wyq-1--------checkedKeys', localExpandedKeys.value);
130
+            emits('update:txBrNo', localCheckedKeys.value[0]);
131
+            break;
132
+        case 'sobTree':
133
+            params = { txBrNo: props.txBrNo };
134
+            apiUrl = '/api/sobTree'; // 替换为实际的账套树接口地址
135
+
136
+            if (props.txBrNo === '1' || props.txBrNo === '1-1' || props.txBrNo === '1-2') {
137
+                treeData.value = [
138
+                    {
139
+                        title: '新会计准则',
140
+                        key: '1',
141
+                        children: [
142
+                            {
143
+                                title: '默认账套1',
144
+                                key: '1-1'
145
+                            },
146
+                            {
147
+                                title: '非默认账套2',
148
+                                key: '1-2'
149
+                            }
150
+                        ]
151
+                    }
152
+                ];
153
+                localCheckedKeys.value = ['1-1'];
154
+                localExpandedKeys.value = ['1'];
155
+            } else {
156
+                treeData.value = [
157
+                    {
158
+                        title: '旧会计准则',
159
+                        key: '2',
160
+                        children: [
161
+                            {
162
+                                title: '默认账套1',
163
+                                key: '2-1'
164
+                            },
165
+                            {
166
+                                title: '非默认账套2',
167
+                                key: '2-2'
168
+                            }
169
+                        ]
170
+                    }
171
+                ];
172
+                localCheckedKeys.value = ['2-1'];
173
+                localExpandedKeys.value = ['2'];
174
+            }
175
+            emits('update:sobNo', localCheckedKeys.value[0]);
176
+            break;
177
+        case 'sobItemTree':
178
+            params = { sobNo: props.sobNo };
179
+            apiUrl = '/api/sobItemTree'; // 替换为实际的科目树接口地址
180
+            break;
181
+        default:
182
+            break;
183
+    }
184
+
185
+    // try {
186
+    //     const response = await axios.get(apiUrl, { params });
187
+    //     treeData.value = response.data;
188
+    // } catch (error) {
189
+    //     console.error('获取树数据失败:', error);
190
+    // }
191
+};
192
+// 初始化时获取树数据
193
+fetchTreeData();
194
+
195
+// 处理树节点勾选变化的事件
196
+const onCheck = (checkedKeys, info) => {
197
+    // 触发自定义事件通知父组件 checkedKeys 已更新
198
+    if (props.treeType === 'deptTree') {
199
+        emits('update:txBrNo', checkedKeys[0]);
200
+    } else if (props.treeType === 'sobTree') {
201
+        emits('update:sobNo', checkedKeys[0]);
202
+    }
203
+    emits('onCheck', checkedKeys, info);
204
+};
205
+</script>

+ 423
- 0
ant-design-pro-vue3/src/components/ProTree3/index.vue 查看文件

@@ -0,0 +1,423 @@
1
+<template>
2
+    <div>
3
+        <!-- 搜索框 -->
4
+        <a-input v-model:value="searchValue" placeholder="请输入关键字进行过滤" />
5
+        <!-- 搜索结果列表 -->
6
+        <div class="dropdown-content">
7
+            <div v-if="searchResultList.length">
8
+                <div class="search-select-li" v-for="node in searchResultList" :key="node[fieldNames.key]"
9
+                    @click="onNode(node)">
10
+                    {{ node[fieldNames.title] }}
11
+                </div>
12
+            </div>
13
+            <!-- 树结构 -->
14
+            <div v-else>
15
+                <!-- 等待树数据加载完成后再显示 -->
16
+                <a-tree v-if="isLocalTreeDataLoaded" :tree-data="localTreeData" :fieldNames="fieldNames"
17
+                    :checkable="showCheckbox" :multiple="multiple" v-model:selectedKeys="selectedKeys"
18
+                    v-model:checkedKeys="checkedKeys" v-model:expandedKeys="expandedKeys" @select="onSelect"
19
+                    @expand="onExpand" :load-data="props.isAsync ? onLoadData : null" v-bind="$attrs">
20
+                </a-tree>
21
+                <div v-else>加载中...</div>
22
+            </div>
23
+        </div>
24
+    </div>
25
+</template>
26
+
27
+<script setup>
28
+import { isEmpty } from '@/utils/validate'
29
+import { message } from "ant-design-vue";
30
+import { getTreeData } from '@/api/treeDataApi';
31
+import { getAnsKeys, getDscKeys, getWithoutDscKeys, delAnsAndDscKeys, findNodes, searchNodes } from '@/utils/treeUtil'
32
+import { ref, defineProps, defineExpose, defineEmits, onMounted, onBeforeUnmount, watch, nextTick, computed } from 'vue';
33
+// 1.测试复选框树,checked的变化,为啥机构面板需要特殊写个一个方法呢
34
+// 2.本地变量的是直接解构赋值 是否有效,还是放到钩子函数: 答:统一放到钩子函数中处理
35
+
36
+// 20250303
37
+// 1. a-select-tree 引用a-tree 通过v-model:value双向绑定了数据, value及时更新了 option还未更新,会影响翻译嘛
38
+// 解: 通过事件的方式将已经选择的节点传递给父组件,就看父组件加载存在先后问题了,父组件通过事件获取已经选择的节点然后赋值给自己optionData
39
+// 2. 异步树时,a-select-tree将默认异步根节点通过prop传递给a-tree后 ,后续异步加载时后,opntion需要给到a-select-后续异步加载时后,opntion需要给到a-select-tree的同时,当关闭弹窗后再次打开已经加载一部分数据会重新再加载一次吗
40
+// 3. 监听不同类型的数据是否需要重新加载数据如汇总关系发生变化重新获取机构, a-select-tree和a-tree都需要处理 但是a-tree需要加一个判断当prop.treeData有数据则不需要处理否则就需要处理,同时获取树数据和默认值方法需要公共起来
41
+// 解:a-select-tree 根本不会将 relationNo、brNos、sobNo传递给 a-tree 所以根据监控不到
42
+// 定义组件接收的 props
43
+const props = defineProps({
44
+    value: {
45
+        type: [String, Array, Number],
46
+        required: true
47
+    },
48
+    treeType: {
49
+        type: String,
50
+        default: ''
51
+    },
52
+    isAsync: {
53
+        type: Boolean,
54
+        default: false
55
+    },
56
+    relationNo: {
57
+        type: String,
58
+        default: ''
59
+    },
60
+    brNos: {
61
+        type: Array,
62
+        default: () => []
63
+    },
64
+    stddNo: {
65
+        type: String,
66
+        default: ''
67
+    },
68
+    sobNo: {
69
+        type: [String, Array],
70
+        default: ''
71
+    },
72
+    treeData: {
73
+        type: Array,
74
+        default: () => []
75
+    },
76
+    formItemProps: {
77
+        type: Object,
78
+        default: () => { }
79
+    },
80
+    multiple: {
81
+        type: Boolean,
82
+        default: false
83
+    },
84
+    showCheckbox: {
85
+        type: Boolean,
86
+        default: false
87
+    },
88
+    isStopPropagation: {
89
+        // 是否阻止冒泡
90
+        type: Boolean,
91
+        default: false
92
+    },
93
+    isClearSearchResult: {
94
+        // 是否自动清空搜索结果
95
+        type: Boolean,
96
+        default: true
97
+    },
98
+    isWithoutDsc: {
99
+        // 是否不包含后代节点返回
100
+        type: Boolean,
101
+        default: false
102
+    },
103
+    fieldNames: {
104
+        type: Object,
105
+        default: () => {
106
+            return {
107
+                key: 'id',
108
+                title: 'name',
109
+                children: 'children'
110
+            }
111
+        }
112
+    }
113
+});
114
+// 定义自定义事件,用于通知父组件
115
+const emits = defineEmits(['update:value', 'update:stddNo', 'get-nodes', 'on-node']);
116
+console.log('wyq:pro-tree-接收参数:', props);
117
+// 定义搜索框的值
118
+const searchValue = ref('');
119
+// 搜索结果列表
120
+const searchResultList = ref([]);
121
+// 树结构数据
122
+const localTreeData = ref([]);
123
+// 标记 localTreeData 是否加载完成
124
+const isLocalTreeDataLoaded = ref(false);
125
+// 
126
+const selectedKeys = computed({
127
+    // 从父组件获取值
128
+    get: getSelectedKeys,
129
+    // 向父组件传递更新
130
+    set: setSelectedKeys
131
+});
132
+
133
+const checkedKeys = computed({
134
+    // 从父组件获取值
135
+    get: getCheckedKeys,
136
+    // 向父组件传递更新
137
+    set: setCheckedKeys
138
+});
139
+
140
+const expandedKeys = ref([]);
141
+
142
+
143
+function getSelectedKeys () {
144
+    if (props.showCheckbox === false && !isEmpty(localTreeData.value) && localTreeData.value.length > 0) {
145
+        console.log('wyq:pro-tree-获取selectedKeys值:', props.value);
146
+        //return [...props.value];
147
+        //return Array.isArray(props.value) ? [...props.value] : props.value;
148
+        return Array.isArray(props.value) ? props.value : [props.value];
149
+    }
150
+    return [];
151
+}
152
+
153
+function setSelectedKeys (value) {
154
+    if (props.showCheckbox === false) {
155
+        console.log('wyq:pro-tree-更改selectedKeys值:', value);
156
+        const nodes = findNodes(localTreeData.value, props.fieldNames.key, [...value]);
157
+        if (props.treeType === 'sobTree') {
158
+            if (!isEmpty(nodes) && nodes.length > 0) {
159
+                emits('update:stddNo', nodes[0]['pid'].split('@')[0]);
160
+            } else {
161
+                emits('update:stddNo', '');
162
+            }
163
+            emits('update:value', value[0]);
164
+        } else {
165
+            emits('update:value', value);
166
+        }
167
+        console.log('DepartPanel-wyq:pro-tree-更改selectedKeys值:', value, nodes);
168
+        emits('get-nodes', value, nodes);
169
+    }
170
+}
171
+
172
+function getCheckedKeys () {
173
+    if (props.showCheckbox === true && !isEmpty(localTreeData.value) && localTreeData.value.length > 0) {
174
+        console.log('wyq:pro-tree-获取checkedKeys值:', props.value);
175
+        //return [...props.value];
176
+        //return Array.isArray(props.value) ? [...props.value] : props.value;
177
+        return Array.isArray(props.value) ? props.value : [props.value];
178
+    }
179
+    return [];
180
+}
181
+
182
+function setCheckedKeys (value) {
183
+    if (props.showCheckbox === true) {
184
+        console.log('wyq:pro-tree-更改checkedKeys值:', value);
185
+        if (props.isWithoutDsc === true) {
186
+            const { withoutDesKeys, withoutDesNodes } = getWithoutDscKeys(localTreeData.value, value, props.fieldNames);
187
+            console.log('wyq:pro-tree-获取withoutDesKeys值:', withoutDesKeys, withoutDesNodes);
188
+            emits('get-nodes', value, withoutDesNodes);
189
+            emits('update:value', withoutDesKeys);
190
+        } else {
191
+            const nodes = findNodes(localTreeData.value, props.fieldNames.key, [...value]);
192
+            emits('get-nodes', value, nodes);
193
+            emits('update:value', value);
194
+        }
195
+    }
196
+}
197
+
198
+const onSelect = (keys, info) => {
199
+    if (props.showCheckbox === true) {
200
+        const node = { ...info.node };
201
+        const key = node[props.fieldNames.key];
202
+        // 得到被选中的所有节点的 key 值
203
+        console.log('wyq-onSelect-初始', checkedKeys.value);
204
+        // 处理勾选节点:将勾选节点的子、孙节点全部勾选,这个地方调用下是为了下一步判断的当前点击的是否存在
205
+        let dscKeys = getDscKeys(localTreeData.value, checkedKeys.value);
206
+        const index = dscKeys.indexOf(key);
207
+        console.log('wyq-onSelect-处理后', dscKeys);
208
+        if (index > -1) {
209
+            // 如果 key 已存在于 keys 中,则移除
210
+            console.log('wyq-onSelect-已存在移除', key);
211
+            // 调用移除节点的方法: 1.需要将移除的节点上级及上上级节点移除 2.需要将移除的节点子、孙节点移除
212
+            dscKeys = delAnsAndDscKeys(localTreeData.value, key, dscKeys);
213
+        } else {
214
+            // 如果 key 不存在于 checkedKeys 中,则添加
215
+            console.log('wyq-onSelect-不存在添加', key);
216
+            dscKeys.push(key);
217
+            // 这个地方再次调用,是因为如果勾选了父节点,需要将父节点下所有子节点全部勾选,所以需要再次处理勾选节点
218
+            dscKeys = getDscKeys(localTreeData.value, dscKeys);
219
+        }
220
+        checkedKeys.value = dscKeys;
221
+    } else {
222
+        if (props.multiple === false) {
223
+            // 单选模式
224
+            if (props.treeType === 'sobTree') {
225
+                if (info.node.children && info.node.children.length > 0) {
226
+                    message.error('请选择账套信息');
227
+                    nextTick(() => {
228
+                        selectedKeys.value = [];
229
+                    });
230
+                }
231
+            }
232
+        }
233
+    }
234
+};
235
+
236
+const onExpand = (expandedKeys, info) => {
237
+    if (props.isAsync === true) {
238
+        // 展开节点时,关闭冒泡不然会影响父组件
239
+        // TODO 这个地方 与 pro-select-tree有冲突
240
+        if (props.isStopPropagation === true) {
241
+            info.nativeEvent.stopPropagation();
242
+        }
243
+    }
244
+}
245
+
246
+async function onLoadData (treeNode) {
247
+    return new Promise(async (resolve, reject) => {
248
+        if (treeNode.dataRef.children) {
249
+            resolve();
250
+            return;
251
+        }
252
+        try {
253
+            const { treeData } = await getTreeData(props, { id: treeNode.eventKey });
254
+            // data.children 是从后端获取的子节点数据
255
+            treeNode.dataRef.children = treeData;
256
+            // 更新 localTreeData
257
+            localTreeData.value = [...localTreeData.value];
258
+            resolve();
259
+        } catch (error) {
260
+            reject(error);
261
+        }
262
+    });
263
+}
264
+
265
+// TODO : 这个地方点击搜索结果, 通知父组件进行关闭下来弹窗, 那再次触发下拉展示的是树结果还是列表?
266
+function onNode (node) {
267
+    // 勾选当前节点
268
+    console.log('wyq:pro-tree-点击搜索结果', node, props.fieldNames);
269
+    emits('on-node', node);
270
+    if (props.showCheckbox === true) {
271
+        checkedKeys.value = [node[props.fieldNames.key]];
272
+    } else {
273
+        selectedKeys.value = [node[props.fieldNames.key]];
274
+    }
275
+    // 展开父节点和爷节点
276
+    const parentKeys = getAnsKeys(localTreeData.value, node[props.fieldNames.key], props.fieldNames);
277
+    //localExpandedKeys.value = [...new Set([...localExpandedKeys.value, ...parentKeys])];
278
+    expandedKeys.value = [...new Set([...parentKeys])];
279
+    // TODO 这个地方 与 pro-select-tree有冲突
280
+    if (props.isClearSearchResult === true) {
281
+        // 清空搜索框
282
+        searchValue.value = '';
283
+        // 清空搜索结果列表
284
+        searchResultList.value = [];
285
+    }
286
+}
287
+
288
+const onClearSearch = () => {
289
+    console.log('wyq:pro-tree-清空搜索结果');
290
+    // 清空搜索框
291
+    searchValue.value = '';
292
+    // 清空搜索结果列表
293
+    searchResultList.value = [];
294
+}
295
+defineExpose({ onClearSearch });
296
+
297
+
298
+// 监听搜索框的值,过滤列表
299
+watch(searchValue, (value) => {
300
+    if (value) {
301
+        searchResultList.value = searchNodes(localTreeData.value, props.fieldNames.title, value);
302
+    } else {
303
+        searchResultList.value = [];
304
+    }
305
+});
306
+
307
+// 监听shuTreeData变化,更新localTreeData
308
+watch(() => props.treeData, (newTreeData) => {
309
+    localTreeData.value = newTreeData;
310
+});
311
+
312
+// 根据不同类型的树监听相应参数的变化
313
+if (props.treeType === 'deptTree') {
314
+    console.log('wyq:pro-tree-监听机构汇总关系发生变化1', props.relationNo);
315
+
316
+    watch(() => props.relationNo, async () => {
317
+        // 监听机构汇总关系发生变化,重新请求机构树
318
+        console.log('wyq:pro-tree-监听机构汇总关系发生变化');
319
+        await getTreeTypeData();
320
+    });
321
+} else if (props.treeType === 'sobTree') {
322
+    // 监听账套树
323
+    watch(() => props.brNos, async () => {
324
+        // 监听机构发生变化,重新请求账套树
325
+        await getTreeTypeData();
326
+    });
327
+} else if (props.treeType === 'sobItemTree') {
328
+    watch(() => props.sobNo, async () => {
329
+        // 监听账套发生变化,重新请求科目树
330
+        await getTreeTypeData();
331
+    });
332
+}
333
+
334
+
335
+onMounted(async () => {
336
+    console.log('wyq:pro-tree-挂载');
337
+    await initLocalTreeData();
338
+});
339
+
340
+async function initLocalTreeData () {
341
+    console.log('wyq:pro-tree-准备树数据');
342
+    if (!isEmpty(props.treeData)) {
343
+        localTreeData.value = props.treeData;
344
+        if (!isEmpty(props.value)) {
345
+            setDefaultKeys(props, props.value);
346
+        }
347
+    } else if (!isEmpty(props.treeType)) {
348
+        // 如果 props.treeData 不存在,则请求后端接口获取树数据
349
+        await getTreeTypeData();
350
+    }
351
+    if (isLocalTreeDataLoaded.value === false) {
352
+        isLocalTreeDataLoaded.value = true;
353
+    }
354
+}
355
+
356
+async function getTreeTypeData () {
357
+    const { treeData, defaultValue, defaultStddNo } = await getTreeData(props, {});
358
+    if (!isEmpty(treeData) && treeData.length > 0) {
359
+        localTreeData.value = treeData;
360
+        if (!isEmpty(defaultValue)) {
361
+            setDefaultKeys(props, defaultValue);
362
+        }
363
+        // if (!isEmpty(defaultStddNo) && props.treeType === 'sobTree') {
364
+        //     emits('update:stddNo', defaultStddNo);
365
+        // }
366
+    }
367
+    console.log('wyq:pro-tree-获取树数据完成', treeData);
368
+}
369
+
370
+// 封装设置选中/勾选键值的逻辑
371
+const setDefaultKeys = (props, defaultValue) => {
372
+    if (props.showCheckbox === true) {
373
+        //checkedKeys.value = [...value];
374
+        //checkedKeys.value = Array.isArray(defaultValue) ? [...defaultValue] : defaultValue;
375
+        checkedKeys.value = Array.isArray(defaultValue) ? defaultValue : [defaultValue];
376
+    } else {
377
+        //selectedKeys.value = [...value];
378
+        selectedKeys.value = Array.isArray(defaultValue) ? defaultValue : [defaultValue];
379
+    }
380
+};
381
+</script>
382
+
383
+<style scoped>
384
+.dropdown-content {
385
+    /* 设置固定的高度和宽度 */
386
+    max-height: 300px;
387
+    /* width: 500px; */
388
+    /* 设置溢出时显示滚动条 */
389
+    overflow: auto;
390
+    /* 可以根据需要添加其他样式 */
391
+    /* border: 1px solid #ccc; */
392
+    padding: 8px;
393
+}
394
+
395
+.dropdown-content2 {
396
+    /* 设置固定的高度和宽度 */
397
+    max-height: 300px;
398
+    /* width: 500px; */
399
+    /* 设置溢出时显示滚动条 */
400
+    overflow: auto;
401
+    /* 防止内容换行 */
402
+    white-space: nowrap;
403
+    /* 当内容宽度超过元素宽度时显示横向滚动条 */
404
+    overflow-x: auto;
405
+    /* 可以根据需要添加其他样式 */
406
+    /* border: 1px solid #ccc; */
407
+    padding: 8px;
408
+}
409
+
410
+.search-select-li {
411
+    padding: 3px 10px;
412
+    padding-left: 0px;
413
+    /* 调整内边距 */
414
+    cursor: pointer;
415
+}
416
+
417
+.search-select-li:hover {
418
+    background-color: #1890ff;
419
+    /* 使用主题色 */
420
+    color: #fff;
421
+    /* 改变文字颜色 */
422
+}
423
+</style>

+ 102
- 0
ant-design-pro-vue3/src/components/ReportComponent/components/AccLvlComponent.vue 查看文件

@@ -0,0 +1,102 @@
1
+<template>
2
+    <pro-select v-model:modelValue="internalValue" show-search placeholder="请选择科目级别" :optionData="options"
3
+        :filter-option="filterOption" @focus="handleFocus" @blur="handleBlur">
4
+    </pro-select>
5
+    <div>internalValue: {{ internalValue }}</div>
6
+</template>
7
+<script setup>
8
+import { ref, watch, defineProps, defineEmits } from 'vue';
9
+const props = defineProps({
10
+    // 请求参数
11
+    sobNo: {
12
+        type: String,
13
+        default: ''
14
+    },
15
+    addEndFlag: {
16
+        type: String,
17
+        default: 'false'
18
+    },
19
+    accLvl: {
20
+        type: String,
21
+        default: ''
22
+    },
23
+    formItemProps: Object, // 定义formItemProps prop
24
+});
25
+const emit = defineEmits(['update:accLvl']);
26
+const internalValue = ref(props.accLvl);
27
+// 监听内部值的变化,向外传递
28
+watch(internalValue, (newValue) => {
29
+    console.log('wyq --internalValue change', newValue);
30
+    emit('update:accLvl', newValue);
31
+});
32
+
33
+// 确保从父组件接收到的 `value` 更新时,内部状态也能同步
34
+watch(() => props.accLvl, (newValue) => {
35
+    console.log('wyq --props.accLvl change', newValue);
36
+
37
+    if (newValue !== internalValue.value) {
38
+        internalValue.value = newValue;
39
+    }
40
+});
41
+watch(() => props.sobNo, async (newVal, oldVal) => {
42
+    console.log('wyq --props.sobNo change', newVal);
43
+
44
+    if (newVal != oldVal && newVal != '') {
45
+        //await getRelationInfoNoOptions();
46
+        if (newVal == '10') {
47
+            options.value = [
48
+                {
49
+                    item_no: '1',
50
+                    item_name: '一级科目',
51
+                },
52
+                {
53
+                    item_no: '2',
54
+                    item_name: '二级科目',
55
+                },
56
+                {
57
+                    item_no: '3',
58
+                    item_name: '三级科目',
59
+                },
60
+                {
61
+                    item_no: '4',
62
+                    item_name: '四级科目',
63
+                }
64
+            ]
65
+
66
+            internalValue.value = '4'
67
+
68
+        } else {
69
+            options.value = [
70
+                {
71
+                    item_no: '1',
72
+                    item_name: '一级科目',
73
+                },
74
+                {
75
+                    item_no: '2',
76
+                    item_name: '二级科目',
77
+                },
78
+                {
79
+                    item_no: '3',
80
+                    item_name: '三级科目',
81
+                }
82
+            ]
83
+            internalValue.value = '3'
84
+        }
85
+    }
86
+});
87
+
88
+const options = ref([]);
89
+
90
+const handleChange = value => {
91
+    console.log(`selected ${value}`);
92
+};
93
+const handleBlur = () => {
94
+    console.log('blur');
95
+};
96
+const handleFocus = () => {
97
+    console.log('focus');
98
+};
99
+const filterOption = (input, option) => {
100
+    return option.item_name.toLowerCase().indexOf(input.toLowerCase()) >= 0;
101
+};
102
+</script>

+ 362
- 0
ant-design-pro-vue3/src/components/ReportComponent/components/DepartPanelComponent.vue 查看文件

@@ -0,0 +1,362 @@
1
+<template>
2
+    <!--1.汇总关系下拉列表-->
3
+    <div class="relation-dropdown">
4
+        <span class="relation-label">汇总关系:</span>
5
+        <a-select v-model:value="relationInfoNo" :options="relationInfoNoOptions" class="relation-select"
6
+            :allowClear="true">
7
+        </a-select>
8
+    </div>
9
+    <!--2.不同树形结构标签页-->
10
+    <div style="margin-bottom: -10px">
11
+        <a-tabs type="card" v-model:activeKey="treeType">
12
+            <a-tab-pane key="0" tab="账务树">
13
+            </a-tab-pane>
14
+            <a-tab-pane key="1" tab="对比树">
15
+            </a-tab-pane>
16
+            <a-tab-pane key="2" tab="报送树">
17
+            </a-tab-pane>
18
+        </a-tabs>
19
+    </div>
20
+    <!--3.搜索框-->
21
+    <div class="search-dropdown">
22
+        <a-input v-model:value="searchValue" @input="onInputChange" placeholder="搜索..." :allowClear="true" />
23
+        <div v-if="searchResultList.length > 0" class="search-select">
24
+            <div class="search-select-li" v-for=" searchResult in searchResultList" :key="searchResult.id"
25
+                @click="onOptionClick(searchResult)">
26
+                {{ searchResult.name }}
27
+            </div>
28
+        </div>
29
+    </div>
30
+    <!--4.机构树-->
31
+    <div>
32
+        <a-tree v-model:expandedKeys="expandedKeys" v-model:selectedKeys="selectedKeys"
33
+            v-model:checkedKeys="checkedKeys" v-model:loadedKeys="loadedKeys" :load-data="onLoadData"
34
+            :tree-data="treeData" :fieldNames="fieldNames" checkable @select="onSelect" @expand="onExpand"
35
+            @check="onCheck" />
36
+    </div>
37
+</template>
38
+
39
+<script setup>
40
+//问题汇总:
41
+//1.机构checked 如何联动下账套, 两个组件不在一块
42
+//2.机构汇总关系下拉列表属性必填项,如何与查询按钮绑定并校验
43
+//3.机构汇总关系获取枚举值时,如何获取当前交易的pageInterfaceNo 
44
+//4.系统日期如何获取到
45
+//5.机构汇总下拉列表如何获取对应的内部值
46
+//6.搜索框,需要判断值是否为空的逻辑处理
47
+//7.控制台报:Tree missing follow keys: '1'
48
+//8.搜索机构时,因为是单选正常应该只展示自己和自己的上级节点
49
+//9.查询时获取查询选中的机构列表也存在问题,需要优化,需要与后台呼应上 父节点下叶子节点全部选中,则返回父节点,否则返回选中的子节点
50
+//10.机构是必填项,如何校验
51
+
52
+// 11.当搜索一个节点时,然后展开整个树,再次重新 checked的话,点击查询获取查询节点有存在问题了
53
+// 12.点击树进行展开,然后再切换树类型或者汇总关系,展开图标消失了,但是数据还是存在
54
+// 13.增加loadedKeys 或者是移动到组件中,展开叶子节点就无效了
55
+// 14.机构面板组件封装到组件中,,业务就特别卡顿
56
+
57
+// 机构汇总关系双向绑定到页面中
58
+import { ref } from 'vue'
59
+import { defineProps, defineExpose, onMounted, watch, nextTick, provide, defineEmits } from 'vue';
60
+import { getRelationInfoNoList, getDepartTreeData, getSearchResultByNodeId } from '@/api/departTreePanel';
61
+defineExpose({ getCheckedNodes, getNodes });
62
+const getCheckedNodesEmit = defineEmits(['get-checkedNodes']);
63
+// 使用 provide 提供这个方法
64
+// provide('getNodes', getNodes);
65
+
66
+function getNodes (data) {
67
+    console.log("获取机构树数据成功", data);
68
+    return {
69
+        name: "查询组件调用成功",
70
+    };
71
+}
72
+
73
+
74
+// 声名接收参数数据
75
+const props = defineProps({});
76
+// 机构汇总关系双向绑定到页面中
77
+const relationInfoNo = ref('');
78
+// 机构汇总关系枚举值, 组件挂载时向后端发起请求
79
+const relationInfoNoOptions = ref([]);
80
+// 树形结构标签页值双向绑定到页面中
81
+const treeType = ref('');
82
+
83
+// 钩子函数,页面加载完成后首先获取下汇总关系
84
+onMounted(async () => {
85
+    // 1.获取机构汇总关系枚举值
86
+    await getRelationInfoNoOptions();
87
+});
88
+// 监听汇总关系和树形结构标签页值,只要值发生变化,重新获取树形结构数据
89
+watch(() => [relationInfoNo.value, treeType.value,], async (newVal, oldVal) => {
90
+    // 1.当类型数发生变化时,重新获取树形结构数据
91
+    if (newVal != oldVal) {
92
+        await getDeptTreeData();
93
+    }
94
+});
95
+
96
+
97
+
98
+// 获取机构汇总关系枚举值及默认值
99
+async function getRelationInfoNoOptions () {
100
+    // 清空 relationInfoNoOptions 数组
101
+    relationInfoNoOptions.value = [];
102
+    // // 1.获取机构汇总关系枚举值
103
+    const resp = await getRelationInfoNoList({
104
+        pageInterfaceNo: 'zzsearch_01_01_02',
105
+    });
106
+    // 2.将枚举值添加到 relationInfoNoOptions 中 并设置下拉列表默认值
107
+    resp.forEach(node => {
108
+        if (node.item_no === 'AAAAAA') {
109
+            relationInfoNo.value = node.item_no;
110
+        }
111
+        relationInfoNoOptions.value.push({ label: node.item_name, value: node.item_no });
112
+    });
113
+    // 3.设置机构树类型的默认值
114
+    treeType.value = '0';
115
+}
116
+
117
+// 搜索框 start
118
+// 搜索框触发事件
119
+const searchValue = ref('');
120
+const searchResultList = ref([]);
121
+
122
+async function onInputChange () {
123
+    // 1.判断搜索框是否为空,为空则清空 options 数组,重新获取树形结构数据
124
+    if (!searchValue || searchValue.value.length === 0) {
125
+        searchResultList.value = [];
126
+        getDeptTreeData();
127
+        return;
128
+    }
129
+    // 2.获取搜索结果
130
+    searchResultList.value = await getDepartTreeData({
131
+        treeSearch: "true",
132
+        kw: searchValue.value,
133
+        relation_info_no: relationInfoNo.value,
134
+        treeType: treeType.value,
135
+        qryDate: '20231117',
136
+    });
137
+}
138
+
139
+// 选择搜索下拉列表项(点击事件)回调
140
+async function onOptionClick (searchResult) {
141
+    // 1.设置搜索框值
142
+    searchValue.value = searchResult.name;
143
+    // 2.点击完成后,隐藏下拉列表设置为空
144
+    searchResultList.value = [];
145
+    // 3.重新获取树形结构数据
146
+    const searchResultList2 = await getSearchResultByNodeId({
147
+        isAsync: "flase",
148
+        nodeId: searchResult.dep_no,
149
+        treeType: treeType.value,
150
+        relation_info_no: relationInfoNo.value,
151
+        qryDate: '20231117',
152
+
153
+    });
154
+
155
+    const treeDataMap = {};
156
+    searchResultList2.forEach(node => {
157
+        treeDataMap[node.id] = node;
158
+    });
159
+
160
+    let parentKeys = [];
161
+    let searchTreeData = [];
162
+    let searchNode = treeDataMap[searchResult.dep_no];
163
+    while (true) {
164
+        const parent = treeDataMap[searchNode.pid];
165
+        if (parent) {
166
+            // 父节点存在,则往父节点添加该子节点
167
+            if (!parent.children) {
168
+                parent.children = [];
169
+            }
170
+            parentKeys.push(parent.id);
171
+            parent.children.push(searchNode);
172
+            searchNode = parent;
173
+        } else {
174
+            // 父节点不存在,则直接添加到树形结构数据中
175
+            searchTreeData.push(searchNode);
176
+            break;
177
+        }
178
+    }
179
+    treeData.value = searchTreeData;
180
+    // 4.设置默认选中节点
181
+    nextTick(() => {
182
+        // 等到数据加载完成后,设置默认选中节点
183
+        checkedKeys.value = [searchNode.id];
184
+        expandedKeys.value = parentKeys;
185
+
186
+    });
187
+
188
+}
189
+// 搜索框 send
190
+
191
+const fieldNames = {
192
+    title: 'name',
193
+    key: 'id',
194
+};
195
+const treeData = ref([])// 树的数据
196
+const expandedKeys = ref([]);// 已展开的节点
197
+const selectedKeys = ref([]);// 已选中的节点
198
+const checkedKeys = ref([]);// 已勾选的节点
199
+const loadedKeys = ref([]); // 已加载子节点的节点
200
+watch(() => checkedKeys.value, (newVal, oldVal) => {
201
+    // 2.当搜索框值发生变化时,重新获取搜索结果
202
+    if (newVal != oldVal) {
203
+        getCheckedNodesEmit('get-checkedNodes', newVal);
204
+    }
205
+});
206
+// 获取机构树数据
207
+async function getDeptTreeData () {
208
+    expandedKeys.value = [];
209
+    selectedKeys.value = [];
210
+    checkedKeys.value = [];
211
+    // 清空已加载子节点的节点数组,不然切换树类型或者汇总关系时会导致展开图标消失
212
+    //loadedKeys.value = [];
213
+    treeData.value = await getDepartTreeData({
214
+        isParentType: '&&',
215
+        page_code: 'cs',
216
+        isAsync: 'true',
217
+        relation_info_no: relationInfoNo.value,
218
+        treeType: treeType.value,
219
+        qryDate: '20231117',
220
+    });
221
+    nextTick(() => {
222
+        // 等到数据加载完成后,设置默认选中节点
223
+        checkedKeys.value = [treeData.value[0].id];
224
+    });
225
+}
226
+
227
+// 节点选中时的回调
228
+function onSelect (selectedKeys, info) {
229
+}
230
+// 节点展开时的回调
231
+function onExpand (expandedKeys, info) {
232
+    console.log('wyq---------expandedKeys', expandedKeys);
233
+}
234
+// 节点选中时的回调
235
+function onCheck (checkedKeys, info) {
236
+    // getCheckedNodesEmit('get-checkedNodes', checkedKeys);
237
+}
238
+// 异步加载数据
239
+const onLoadData = async (treeNode) => {
240
+    return new Promise(async (resolve, reject) => {
241
+        if (treeNode.dataRef.children) {
242
+            resolve();
243
+            return;
244
+        }
245
+        try {
246
+            // data.children 是从后端获取的子节点数据
247
+            treeNode.dataRef.children = await getDepartTreeData({
248
+                id: treeNode.eventKey,
249
+                isParentType: "&&",
250
+                isAsync: "true",
251
+                page_code: 'cs',
252
+                relation_info_no: relationInfoNo.value,
253
+                treeType: treeType.value,
254
+                qryDate: '20231117',
255
+            });
256
+            // 更新 treeData
257
+            treeData.value = [...treeData.value];
258
+            resolve();
259
+        } catch (error) {
260
+            //console.error('获取数据失败', error);
261
+            reject(error);
262
+        }
263
+    });
264
+};
265
+
266
+
267
+function getCheckedNodes () {
268
+    let checkedNodes = [];
269
+    let allNodes = getAllNodes();
270
+    if (checkedKeys.value.length === 1) {
271
+        // 只选中一个节点
272
+        const node = allNodes.find(n => n.id === checkedKeys.value[0]);
273
+        checkedNodes.push(node);
274
+    } else {
275
+        // 选中多个节点
276
+        for (let i = 0; i < checkedKeys.value.length; i++) {
277
+            // 找到当前节点
278
+            const node = allNodes.find(n => n.id === checkedKeys.value[i]);
279
+            if (!checkedKeys.value.includes(node.pid)) {
280
+                // 选择的节点对应的父节点没有被选择, 则添加到结果中
281
+                checkedNodes.push(node);
282
+            }
283
+        }
284
+    }
285
+    return checkedNodes;
286
+}
287
+
288
+
289
+const getAllNodes = (nodes = treeData.value) => {
290
+    let allNodes = [];
291
+    const traverse = (nodeList) => {
292
+        nodeList.forEach(node => {
293
+            allNodes.push(node); // 收集当前节点
294
+            if (node.children) {
295
+                traverse(node.children); // 递归遍历子节点
296
+            }
297
+        });
298
+    };
299
+    traverse(nodes);
300
+    return allNodes;
301
+};
302
+
303
+
304
+
305
+
306
+
307
+</script>
308
+<style scoped>
309
+.relation-dropdown {
310
+    margin-bottom: 5px;
311
+}
312
+
313
+.relation-label {
314
+    display: inline-block;
315
+    vertical-align: middle;
316
+}
317
+
318
+.relation-select {
319
+    display: inline-block;
320
+    vertical-align: middle;
321
+    width: 200px;
322
+}
323
+
324
+.search-dropdown {
325
+    position: relative;
326
+    display: inline-block;
327
+    width: 286px;
328
+    margin-bottom: 5px
329
+        /* 设置宽度 */
330
+}
331
+
332
+.search-select {
333
+    position: absolute;
334
+    top: calc(100% + 5px);
335
+    /* 适当调整下拉列表的位置 */
336
+    left: 0;
337
+    right: 0;
338
+    z-index: 1000;
339
+    border: 1px solid #ccc;
340
+    border-radius: 4px;
341
+    /* 圆角 */
342
+    background-color: #fff;
343
+    max-height: 200px;
344
+    overflow-y: auto;
345
+    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
346
+    /* 添加阴影 */
347
+}
348
+
349
+.search-select-li {
350
+    padding: 3px 10px;
351
+    padding-left: 0px;
352
+    /* 调整内边距 */
353
+    cursor: pointer;
354
+}
355
+
356
+.search-select-li:hover {
357
+    background-color: #1890ff;
358
+    /* 使用主题色 */
359
+    color: #fff;
360
+    /* 改变文字颜色 */
361
+}
362
+</style>

+ 116
- 0
ant-design-pro-vue3/src/components/ReportComponent/components/QueryComponent.vue 查看文件

@@ -0,0 +1,116 @@
1
+<template>
2
+    <pro-form label-width="120px" tabsProps="2">
3
+        <pro-form-grid style="width: 700px" colNum="2">
4
+
5
+            <!-- <AccLvlComponent :formItemProps="{ label: '层级编号', prop: 'levelKey' }"></AccLvlComponent> -->
6
+            <pro-select :formItemProps="{ label: '启用标志111', prop: 'useYn' }" placeholder="请选择启用标志" v-model:value="useYn"
7
+                :optionData="options" :allowClear="true" tableName="com_usertype_info" colName="use_yn">
8
+            </pro-select>
9
+            <pro-select :formItemProps="{ label: '启用标志', prop: 'useYn' }" placeholder="请选择启用标志" :allowClear="true"
10
+                tableName="com_usertype_info" colName="use_yn">
11
+            </pro-select>
12
+            <pro-select :formItemProps="{ label: '启用标志', prop: 'useYn' }" placeholder="请选择启用标志" :allowClear="true"
13
+                tableName="com_usertype_info" colName="use_yn">
14
+            </pro-select>
15
+            <pro-form-item>
16
+                <pro-button id="queryBtn" @click="search" :icon="h(SearchOutlined)">查询</pro-button>
17
+            </pro-form-item>
18
+        </pro-form-grid>
19
+    </pro-form>
20
+
21
+</template>
22
+
23
+<script setup>
24
+import { ref, watch, h, computed, onMounted, nextTick, reactive, onBeforeUnmount, inject, defineEmits, defineProps } from 'vue';
25
+import { DoubleRightOutlined, DoubleLeftOutlined, SearchOutlined } from "@ant-design/icons-vue";
26
+const useYn = ref('Y');
27
+const options = ref([
28
+    {
29
+        item_no: 'Y',
30
+        item_name: '启用',
31
+    },
32
+    {
33
+        item_no: 'N',
34
+        item_name: '停用',
35
+    }]);
36
+// 声名接收参数数据
37
+const props = defineProps({
38
+    brNos: String
39
+});
40
+
41
+watch(() => props.brNos, (newVal, oldVal) => {
42
+    // 2.当搜索框值发生变化时,重新获取搜索结果
43
+    if (newVal != oldVal) {
44
+        console.log("wyq-2.brNos发生变化", newVal, oldVal)
45
+    }
46
+});
47
+
48
+// watch(() => props.brNos.values, (newValue, oldValue) => {
49
+//     console.log("wyq-2.brNos发生变化", newValue, oldValue)
50
+
51
+// });
52
+
53
+// 从机构面板中组件中,注入getCheckedNodes方法
54
+const getNodes = inject('getNodes');
55
+const emit = defineEmits(['query-report']);
56
+function queryReport () {
57
+    let data = {
58
+        name: 'zhangsan',
59
+        age: '18',
60
+        sex: '男'
61
+    }
62
+
63
+    console.log("wyq-1.触发查询")
64
+    // 调用从 DepartPanelComponent 注入的方法
65
+    if (getNodes) {
66
+        const result = getNodes(data);
67
+        console.log("wyq-2.触发机构面板中的方法获取节点", result)
68
+    } else {
69
+        console.error("未找到方法");
70
+    }
71
+
72
+    // 调用从 DepartPanelComponent 注入的方法
73
+    // if (testProvide) {
74
+    //     const result = testProvide(data);
75
+    //     console.log("wyq-2.testProvide", result)
76
+
77
+    // } else {
78
+    //     console.error("aaa未找到方法");
79
+    // }
80
+
81
+    emit('query-report', data);
82
+
83
+}
84
+
85
+const form = ref(
86
+    {
87
+        formDate: null,
88
+        periodType: null,
89
+        accountSet: null,
90
+        currency: null,
91
+        subjectLevel: null,
92
+    }
93
+);
94
+
95
+const periodTypes = ref(
96
+    [
97
+        { value: 'monthly', label: '月度' },
98
+        { value: 'quarterly', label: '季度' },
99
+        { value: 'yearly', label: '年度' },
100
+    ]
101
+);
102
+
103
+const accountSets = ref([
104
+    { value: 'account1', label: '账套1' },
105
+    { value: 'account2', label: '账套2' },
106
+]);
107
+
108
+const subjectLevels = [
109
+    { value: 'level1', label: '一级科目' },
110
+    { value: 'level2', label: '二级科目' },
111
+];
112
+</script>
113
+
114
+<style scoped>
115
+/* optional: you can add your styles here */
116
+</style>

+ 54
- 0
ant-design-pro-vue3/src/components/ReportComponent/components/ResultComponent.vue 查看文件

@@ -0,0 +1,54 @@
1
+<template>
2
+    我是查询结果组件
3
+    {{ resultData }}
4
+    <pro-form label-width="120px" tabsProps="2">
5
+        <pro-form-grid style="width: 700px" colNum="2">
6
+            <SobSelectComponent v-model:accLvl="sobNo" :formItemProps="{ label: '账套', prop: 'levelKey' }">
7
+            </SobSelectComponent>
8
+            <AccLvlComponent :sobNo="sobNo" :addEndFlag="addEndFlag" v-model:accLvl="accLvl"
9
+                :formItemProps="{ label: '科目级别', prop: 'levelKey' }">
10
+            </AccLvlComponent>
11
+            <pro-form-item>
12
+                <pro-button id="queryBtn" @click="search" :icon="h(SearchOutlined)">查询</pro-button>
13
+            </pro-form-item>
14
+        </pro-form-grid>
15
+    </pro-form>
16
+    <div>sobNo: {{ sobNo }}</div>
17
+    <div>addEndFlag: {{ addEndFlag }}</div>
18
+    <div>accLvl: {{ accLvl }}</div>
19
+
20
+</template>
21
+<script setup>
22
+import { ref, watch, h, computed, onMounted, nextTick, reactive, onBeforeUnmount, provide, defineExpose } from 'vue';
23
+import { SearchOutlined, RedoOutlined, PlusOutlined, EditOutlined } from "@ant-design/icons-vue";
24
+
25
+import AccLvlComponent from './AccLvlComponent.vue';
26
+import SobSelectComponent from './SobSelectComponent.vue';
27
+
28
+const sobNo = ref('');
29
+const addEndFlag = ref('');
30
+const accLvl = ref('');
31
+
32
+function search () {
33
+    if (sobNo.value === '') {
34
+        sobNo.value = '10';
35
+    } else if (sobNo.value === '10') {
36
+        sobNo.value = '11';
37
+    } else {
38
+        sobNo.value = '10';
39
+    }
40
+}
41
+
42
+function changSobNo (value) {
43
+    console.log('wyq-3.接收到sobNo的值', value);
44
+}
45
+
46
+const resultData = ref('');
47
+defineExpose({ getResultData });
48
+function getResultData (queryData) {
49
+    // 这里是获取查询结果数据的逻辑
50
+    console.log('wyq-4.接收到查询组件传来的数据开始展示结果', queryData);
51
+    resultData.value = queryData;
52
+}
53
+</script>
54
+<style scoped></style>

+ 164
- 0
ant-design-pro-vue3/src/components/ReportComponent/components/SobSelectComponent.vue 查看文件

@@ -0,0 +1,164 @@
1
+<template>
2
+    <!-- <pro-select v-model:modelValue="internalValue" show-search placeholder="请选择账套级别" :optionData="options"
3
+        :filter-option="filterOption" @focus="handleFocus" @blur="handleBlur">
4
+    </pro-select>
5
+    <div>internalValue: {{ internalValue }}</div> -->
6
+
7
+    <pro-select-tree :options="subjectTree" :showCheckbox="false" :props="subjectProps" v-model:value="selectedSubject"
8
+        @input="onSubjectSelect">
9
+    </pro-select-tree>
10
+</template>
11
+<script setup>
12
+import { ref, watch, defineProps, defineEmits, onMounted } from 'vue';
13
+
14
+
15
+const subjectTree = ref([
16
+    {
17
+        id: '1',
18
+        name: '科目1',
19
+        children: [
20
+            { id: '1-1', name: '科目1-1' },
21
+            { id: '1-2', name: '科目1-2' }
22
+        ]
23
+    },
24
+    {
25
+        id: '2',
26
+        name: '科目2',
27
+        children: [
28
+            { id: '2-1', name: '科目2-1' },
29
+            { id: '2-2', name: '科目2-2' }
30
+        ]
31
+    }
32
+]);
33
+const subjectProps = {
34
+    key: 'id',
35
+    value: 'id',
36
+    label: 'name',
37
+    no: 'id',
38
+    title: 'name',
39
+    children: 'children',
40
+    title: 'name',
41
+    key: 'id',
42
+};
43
+const fieldNames = {
44
+    title: 'name',
45
+    key: 'id',
46
+};
47
+
48
+const selectedSubject = ref([]);
49
+function onSubjectSelect (value) {
50
+    console.log('wyq --onSubjectSelect', value);
51
+    selectedSubject.value = value;
52
+}
53
+
54
+
55
+const props = defineProps({
56
+    txBrNo: {
57
+        type: String,
58
+        default: ''
59
+    },
60
+    // 请求参数
61
+    sobNo: {
62
+        type: String,
63
+        default: ''
64
+    },
65
+    addEndFlag: {
66
+        type: String,
67
+        default: 'false'
68
+    },
69
+    accLvl: {
70
+        type: String,
71
+        default: ''
72
+    },
73
+    formItemProps: Object, // 定义formItemProps prop
74
+});
75
+const emit = defineEmits(['update:accLvl']);
76
+const internalValue = ref(props.accLvl);
77
+
78
+// 钩子函数,页面加载完成后首先获取下汇总关系
79
+onMounted(async () => {
80
+    // 1.获取机构汇总关系枚举值
81
+    internalValue.value = '10';
82
+});
83
+
84
+// 监听内部值的变化,向外传递
85
+watch(internalValue, (newValue) => {
86
+    console.log('wyq --internalValue change', newValue);
87
+    emit('update:accLvl', newValue);
88
+});
89
+
90
+// 确保从父组件接收到的 `value` 更新时,内部状态也能同步
91
+watch(() => props.accLvl, (newValue) => {
92
+    console.log('wyq --props.accLvl change', newValue);
93
+
94
+    if (newValue !== internalValue.value) {
95
+        internalValue.value = newValue;
96
+    }
97
+});
98
+watch(() => props.sobNo, async (newVal, oldVal) => {
99
+    console.log('wyq --props.sobNo change', newVal);
100
+
101
+    if (newVal != oldVal && newVal != '') {
102
+        //await getRelationInfoNoOptions();
103
+        if (newVal == '10') {
104
+            options.value = [
105
+                {
106
+                    item_no: '1',
107
+                    item_name: '一级科目',
108
+                },
109
+                {
110
+                    item_no: '2',
111
+                    item_name: '二级科目',
112
+                },
113
+                {
114
+                    item_no: '3',
115
+                    item_name: '三级科目',
116
+                },
117
+                {
118
+                    item_no: '4',
119
+                    item_name: '四级科目',
120
+                }
121
+            ]
122
+
123
+            internalValue.value = '4'
124
+
125
+        } else {
126
+            options.value = [
127
+                {
128
+                    item_no: '1',
129
+                    item_name: '一级科目',
130
+                },
131
+                {
132
+                    item_no: '2',
133
+                    item_name: '二级科目',
134
+                },
135
+                {
136
+                    item_no: '3',
137
+                    item_name: '三级科目',
138
+                }
139
+            ]
140
+            internalValue.value = '3'
141
+        }
142
+    }
143
+});
144
+
145
+const options = ref([{
146
+    item_no: '10',
147
+    item_name: '默认账套',
148
+},
149
+{
150
+    item_no: '12',
151
+    item_name: '非默认账套',
152
+}]);
153
+
154
+
155
+const handleBlur = () => {
156
+    console.log('blur');
157
+};
158
+const handleFocus = () => {
159
+    console.log('focus');
160
+};
161
+const filterOption = (input, option) => {
162
+    return option.item_name.toLowerCase().indexOf(input.toLowerCase()) >= 0;
163
+};
164
+</script>

+ 277
- 0
ant-design-pro-vue3/src/components/ReportComponent/index.vue 查看文件

@@ -0,0 +1,277 @@
1
+<template>
2
+    <!-- 绑定 ref 到根元素 -->
3
+    <div ref="container"
4
+        :class="['pro-split', direction === 'horizontal' ? 'pro-split-horizontal' : 'pro-split-vertical']">
5
+        <!-- 顶部标题 -->
6
+        <div v-if="topTitle" class="pro-split-title" :style="{ display: isTopExpanded ? 'flex' : 'none' }">
7
+            <span>{{ topTitle }}</span>
8
+            <button v-if="canTopCollapse" @click="toggleTopCollapse">{{ isTopExpanded ? '收起' : '展开' }}</button>
9
+        </div>
10
+        <!-- 左侧标题 -->
11
+        <div v-if="leftTitle" class="pro-split-title pro-split-title-left"
12
+            :style="{ display: isLeftExpanded ? 'flex' : 'none' }">
13
+            <span>{{ leftTitle }}</span>
14
+            <button v-if="canLeftCollapse" @click="toggleLeftCollapse">{{ isLeftExpanded ? '收起' : '展开' }}</button>
15
+        </div>
16
+        <div class="pro-split-pane" :style="pane1Style">
17
+            <slot name="pane1"></slot>
18
+        </div>
19
+        <div class="pro-split-handle" :class="{ 'pro-split-handle-floating': dragging }" @mousedown="onHandleMouseDown"
20
+            :style="handleStyle">
21
+        </div>
22
+        <div class="pro-split-pane" :style="pane2Style">
23
+            <slot name="pane2"></slot>
24
+        </div>
25
+        <!-- 底部标题 -->
26
+        <div v-if="bottomTitle" class="pro-split-title" :style="{ display: isBottomExpanded ? 'flex' : 'none' }">
27
+            <span>{{ bottomTitle }}</span>
28
+            <button v-if="canBottomCollapse" @click="toggleBottomCollapse">{{ isBottomExpanded ? '收起' : '展开' }}</button>
29
+        </div>
30
+        <!-- 右侧标题 -->
31
+        <div v-if="rightTitle" class="pro-split-title pro-split-title-right"
32
+            :style="{ display: isRightExpanded ? 'flex' : 'none' }">
33
+            <span>{{ rightTitle }}</span>
34
+            <button v-if="canRightCollapse" @click="toggleRightCollapse">{{ isRightExpanded ? '收起' : '展开' }}</button>
35
+        </div>
36
+    </div>
37
+</template>
38
+
39
+<script setup>
40
+import { ref, onMounted, onUnmounted, defineEmits, defineProps } from 'vue';
41
+
42
+const props = defineProps({
43
+    direction: {
44
+        type: String,
45
+        default: 'horizontal',
46
+        validator: (value) => ['horizontal', 'vertical'].includes(value)
47
+    },
48
+    sizeRatio: {
49
+        type: Number,
50
+        default: 0.5
51
+    },
52
+    topTitle: {
53
+        type: String,
54
+        default: ''
55
+    },
56
+    leftTitle: {
57
+        type: String,
58
+        default: ''
59
+    },
60
+    bottomTitle: {
61
+        type: String,
62
+        default: ''
63
+    },
64
+    rightTitle: {
65
+        type: String,
66
+        default: ''
67
+    },
68
+    canTopCollapse: {
69
+        type: Boolean,
70
+        default: false
71
+    },
72
+    canLeftCollapse: {
73
+        type: Boolean,
74
+        default: false
75
+    },
76
+    canBottomCollapse: {
77
+        type: Boolean,
78
+        default: false
79
+    },
80
+    canRightCollapse: {
81
+        type: Boolean,
82
+        default: false
83
+    },
84
+    isTopExpanded: {
85
+        type: Boolean,
86
+        default: true
87
+    },
88
+    isLeftExpanded: {
89
+        type: Boolean,
90
+        default: true
91
+    },
92
+    isBottomExpanded: {
93
+        type: Boolean,
94
+        default: true
95
+    },
96
+    isRightExpanded: {
97
+        type: Boolean,
98
+        default: true
99
+    }
100
+});
101
+
102
+const emits = defineEmits(['update:sizeRatio']);
103
+
104
+const dragging = ref(false);
105
+const startX = ref(0);
106
+const startY = ref(0);
107
+const startSizeRatio = ref(props.sizeRatio);
108
+const tempSizeRatio = ref(props.sizeRatio);
109
+
110
+const handle = ref(null);
111
+const container = ref(null);
112
+
113
+const pane1Style = ref({});
114
+const pane2Style = ref({});
115
+const handleStyle = ref({});
116
+
117
+const isTopExpanded = ref(props.isTopExpanded);
118
+const isLeftExpanded = ref(props.isLeftExpanded);
119
+const isBottomExpanded = ref(props.isBottomExpanded);
120
+const isRightExpanded = ref(props.isRightExpanded);
121
+
122
+const toggleTopCollapse = () => {
123
+    isTopExpanded.value = !isTopExpanded.value;
124
+};
125
+
126
+const toggleLeftCollapse = () => {
127
+    isLeftExpanded.value = !isLeftExpanded.value;
128
+};
129
+
130
+const toggleBottomCollapse = () => {
131
+    isBottomExpanded.value = !isBottomExpanded.value;
132
+};
133
+
134
+const toggleRightCollapse = () => {
135
+    isRightExpanded.value = !isRightExpanded.value;
136
+};
137
+
138
+const updateStyles = () => {
139
+    if (container.value) {
140
+        if (props.direction === 'horizontal') {
141
+            const width = container.value.offsetWidth;
142
+            const pane1Width = width * tempSizeRatio.value;
143
+            const pane2Width = width - pane1Width;
144
+            pane1Style.value = { width: `${pane1Width}px` };
145
+            pane2Style.value = { width: `${pane2Width}px` };
146
+        } else {
147
+            const height = container.value.offsetHeight;
148
+            const pane1Height = height * tempSizeRatio.value;
149
+            const pane2Height = height - pane1Height;
150
+            pane1Style.value = { height: `${pane1Height}px` };
151
+            pane2Style.value = { height: `${pane2Height}px` };
152
+        }
153
+        updateHandleStyle(tempSizeRatio.value);
154
+    }
155
+};
156
+
157
+const updateHandleStyle = (ratio) => {
158
+    if (container.value) {
159
+        if (props.direction === 'horizontal') {
160
+            const width = container.value.offsetWidth;
161
+            const pane1Width = width * ratio;
162
+            handleStyle.value = {
163
+                left: `${pane1Width}px`,
164
+                width: '5px', // 设置水平分割线宽度
165
+                height: '100%' // 设置水平分割线高度
166
+            };
167
+        } else {
168
+            const height = container.value.offsetHeight;
169
+            const pane1Height = height * ratio;
170
+            handleStyle.value = {
171
+                top: `${pane1Height}px`,
172
+                width: '100%', // 设置垂直分割线宽度
173
+                height: '5px' // 设置垂直分割线高度
174
+            };
175
+        }
176
+    }
177
+};
178
+
179
+const onHandleMouseDown = (e) => {
180
+    dragging.value = true;
181
+    startX.value = e.clientX;
182
+    startY.value = e.clientY;
183
+    startSizeRatio.value = props.sizeRatio;
184
+    tempSizeRatio.value = props.sizeRatio;
185
+    document.addEventListener('mousemove', onMouseMove);
186
+    document.addEventListener('mouseup', onMouseUp);
187
+};
188
+
189
+const onMouseMove = (e) => {
190
+    if (dragging.value) {
191
+        const deltaX = e.clientX - startX.value;
192
+        const deltaY = e.clientY - startY.value;
193
+        if (props.direction === 'horizontal') {
194
+            const containerWidth = container.value.offsetWidth;
195
+            const newSizeRatio = startSizeRatio.value + deltaX / containerWidth;
196
+            tempSizeRatio.value = Math.max(0, Math.min(1, newSizeRatio));
197
+        } else {
198
+            const containerHeight = container.value.offsetHeight;
199
+            const newSizeRatio = startSizeRatio.value + deltaY / containerHeight;
200
+            tempSizeRatio.value = Math.max(0, Math.min(1, newSizeRatio));
201
+        }
202
+        updateHandleStyle(tempSizeRatio.value);
203
+    }
204
+};
205
+
206
+const onMouseUp = () => {
207
+    dragging.value = false;
208
+    document.removeEventListener('mousemove', onMouseMove);
209
+    document.removeEventListener('mouseup', onMouseUp);
210
+    emits('update:sizeRatio', tempSizeRatio.value);
211
+    // 确保更新样式时使用 tempSizeRatio 的值
212
+    updateStyles();
213
+};
214
+
215
+onMounted(() => {
216
+    updateStyles();
217
+});
218
+
219
+onUnmounted(() => {
220
+    document.removeEventListener('mousemove', onMouseMove);
221
+    document.removeEventListener('mouseup', onMouseUp);
222
+});
223
+</script>
224
+
225
+<style scoped>
226
+.pro-split {
227
+    position: relative;
228
+    display: flex;
229
+    width: 100%;
230
+    height: 100%;
231
+    flex-direction: column;
232
+}
233
+
234
+.pro-split-title {
235
+    background-color: #f0f0f0;
236
+    padding: 8px;
237
+    font-weight: bold;
238
+    display: flex;
239
+    justify-content: space-between;
240
+    align-items: center;
241
+}
242
+
243
+.pro-split-title-left {
244
+    flex-direction: column;
245
+}
246
+
247
+.pro-split-title-right {
248
+    flex-direction: column;
249
+}
250
+
251
+.pro-split-horizontal {
252
+    flex-direction: row;
253
+}
254
+
255
+.pro-split-vertical {
256
+    flex-direction: column;
257
+}
258
+
259
+.pro-split-pane {
260
+    overflow: auto;
261
+}
262
+
263
+.pro-split-handle {
264
+    background-color: #d71212;
265
+    cursor: col-resize;
266
+    z-index: 1;
267
+}
268
+
269
+.pro-split-vertical .pro-split-handle {
270
+    cursor: row-resize;
271
+}
272
+
273
+.pro-split-handle-floating {
274
+    position: absolute;
275
+    z-index: 2;
276
+}
277
+</style>

+ 8
- 0
ant-design-pro-vue3/src/components/SobComponent/components/SobItemLvlComponent.vue 查看文件

@@ -0,0 +1,8 @@
1
+<template>
2
+
3
+</template>
4
+
5
+<script>
6
+import { ref, watch, h, computed, onMounted, nextTick, reactive, onBeforeUnmount, inject, defineEmits, defineProps } from 'vue';
7
+const accLvl = ref('');
8
+</script>

+ 0
- 0
ant-design-pro-vue3/src/components/SobComponent/index.vue 查看文件


+ 16
- 0
ant-design-pro-vue3/src/components/main.js 查看文件

@@ -2,8 +2,17 @@ import ProTable from './ProTable/index.vue'
2 2
 import TableSelect from './TableSelect/index.vue'
3 3
 import ProTabs from './ProTabs/index.jsx'
4 4
 import ProTree from './ProTree/index.vue'
5
+import ProTree2 from './ProTree2/index.vue'
6
+import ProTree3 from './ProTree3/index.vue'
5 7
 import ProDialog from './ProDialog/index.vue'
6 8
 import OpenModelButton from './OpenModelButton/index.vue'
9
+import DepartTreePanel from './DepartTreePanel/index.vue'
10
+import ReportComponent from './ReportComponent/index.vue'
11
+import ProLayout3 from './ProLayout3/index.vue'
12
+
13
+
14
+
15
+
7 16
 // import Tinymce from './Tinymce/index.vue'
8 17
 
9 18
 import {Button, FormItem, TreeSelect, Modal, Upload, Row, Col, Card} from 'ant-design-vue'
@@ -20,10 +29,17 @@ ProComponentsMount.install = function (Vue){
20 29
     Vue.component('ProButton',Button)
21 30
     Vue.component('ProFormItem',FormItem)
22 31
     Vue.component('ProTreeSelect',TreeSelect)
32
+
23 33
     Vue.component('ProModal',Modal)
24 34
     Vue.component('ProUpload',Upload)
25 35
     Vue.component('ProRow',Row)
26 36
     Vue.component('ProCol',Col)
27 37
     Vue.component('ProCard',Card)
38
+    Vue.component('DepartTreePanel',DepartTreePanel)
39
+    Vue.component('ReportComponent',ReportComponent)
40
+    Vue.component('ProTree2',ProTree2)
41
+    Vue.component('ProTree3',ProTree3)
42
+  Vue.component('ProLayout3',ProLayout3)
43
+
28 44
 }
29 45
 export default ProComponentsMount;

+ 9
- 3
ant-design-pro-vue3/src/layouts/BasicLayout.vue 查看文件

@@ -16,10 +16,16 @@
16 16
                 @toggle="toggle" @refresh="onRefresh" />
17 17
 
18 18
             <!-- layout content -->
19
+
20
+            <!-- <a-layout-content
21
+                :style="{ overflow: 'auto', background: 'blue', padding: '24px', margin: 0, minHeight: '280px' }">
22
+                <route-view v-if="showRouter" />
23
+            </a-layout-content> -->
24
+
19 25
             <a-layout-content :style="{
20
-        height: '100%', margin: '24px 24px 0',
21
-        paddingTop: fixedHeader ? '64px' : '0',
22
-    }">
26
+                height: '100%', margin: '24px 24px 0',
27
+                paddingTop: fixedHeader ? '64px' : '0',
28
+            }">
23 29
                 <multi-tab v-if="multiTab"></multi-tab>
24 30
                 <transition name="page-transition">
25 31
                     <section>

+ 17
- 1
ant-design-pro-vue3/src/locales/menu/cn.ts 查看文件

@@ -46,13 +46,21 @@ export default {
46 46
     'welcome': '欢迎',
47 47
     'home': '首页',
48 48
 
49
-    'system.title': '系统',
49
+    'system.title': '系统设置',
50 50
     'system.loginedlog.title': '用户管理',
51 51
     'system.loginedlog.userOptLog1.title': '用户日志查询',
52 52
     'system.loginedlog.onlineUser.title': '在线用户查询',
53 53
     'system.zzmanage.title': '参数管理',
54 54
     'system.zzmanage.endYear_manager.title': '年结参数维护',
55 55
     'system.zzmanage.currencyManager.title': '币种维护',
56
+    'system.zzmanage.departLevel.title': '机构层级管理',
57
+    'system.zzmanage.departLevelDef.title': '机构层级管理2',
58
+    'system.zzmanage.testVue.title': '测试',
59
+    'system.zzmanage.ywzkbReport.title': '业务状况表',
60
+    'system.zzmanage.testProSelectTree.title': '测试业务树',
61
+    'system.zzmanage.testProTree3.title': '测试树组件3',
62
+    'system.zzmanage.testProSelectTree3.title': '测试下拉树组件3',
63
+
56 64
 
57 65
     'workflow.title': '流程管理',
58 66
     'workflow.mole.title': '分支流程管理',
@@ -67,4 +75,12 @@ export default {
67 75
     'bbhb.bbhbcswh.bbhb_01_01_01.title': '法人信息',
68 76
     'bbhb.bbcx.title': '报表查询',
69 77
     'bbhb.bbcx.bbhb_03_01.title': '报表查询',
78
+
79
+    'example.title': '示例页面',
80
+    'example.proDatePickerExample.title': '日期选择器',
81
+    't2000.title': '柜面交易',
82
+    't2000.t2000.title': '开户',
83
+    't2001.t2001.title': '子账户开户',
84
+
85
+
70 86
 }

+ 2
- 1
ant-design-pro-vue3/src/router/commonRoutes.ts 查看文件

@@ -32,6 +32,7 @@ export default [
32 32
     {
33 33
         path: '/:path(.*)',
34 34
         name: 'NoMatch',
35
-        component: () => import('@/views/exception/404.vue'),
35
+        //component: () => import('@/views/exception/404.vue'),
36
+        component: () => import('@/views/user/Login.vue'),
36 37
     }
37 38
 ] as Router[]

+ 81
- 10
ant-design-pro-vue3/src/router/exampleRouterMap.ts 查看文件

@@ -37,18 +37,54 @@ export const example: Router = {
37 37
                     name: 'systemzzmanage',
38 38
                     meta: { title: 'menu.system.zzmanage.title' },
39 39
                     children: [
40
-                        {   //年结参数维护
41
-                            path: '/zp/automake/system/zzmanage/endYear_manager',
42
-                            name: 'endYear_manager',
43
-                            component: () => import('@/views/endYear_manager/index.vue'),
44
-                            meta: { title: 'menu.system.zzmanage.endYear_manager.title' },
40
+                        {   //机构层级管理
41
+                            path: '/zp/automake/system/zzmanage/departLevel',
42
+                            name: 'departLevel',
43
+                            component: () => import('@/views/depart/departLevel.vue'),
44
+                            meta: { title: 'menu.system.zzmanage.departLevel.title' },
45 45
                         },
46
-                        {   //币种维护
47
-                            path: '/zp/automake/system/zzmanage/CurrencyManager',
48
-                            name: 'currencyManager',
49
-                            component: () => import('@/views/currencyManager/CurrencyManagerView.vue'),
50
-                            meta: { title: 'menu.system.zzmanage.currencyManager.title' },
46
+                        {   //机构层级管理2
47
+                            path: '/zp/automake/system/zzmanage/DepartLevelDef',
48
+                            name: 'departLevelDef',
49
+                            component: () => import('@/views/depart/departLevel/DepartLevelDef.vue'),
50
+                            meta: { title: 'menu.system.zzmanage.departLevelDef.title' },
51
+                        },
52
+                        {   //测试
53
+                            path: '/zp/automake/system/zzmanage/Test',
54
+                            name: 'testVue',
55
+                            component: () => import('@/views/depart/departLevel/Test.vue'),
56
+                            meta: { title: 'menu.system.zzmanage.testVue.title' },
57
+                        },
58
+                        // {   //业务状况表
59
+                        //     path: '/zp/automake/system/zzmanage/YwzkbReport',
60
+                        //     name: 'testVue',
61
+                        //     component: () => import('@/views/depart/departLevel/YwzkbReport.vue'),
62
+                        //     meta: { title: 'menu.system.zzmanage.ywzkbReport.title' },
63
+                        // },
64
+                        // {   //测试下拉树组件
65
+                        //     path: '/zp/automake/system/zzmanage/TestProSelectTree',
66
+                        //     name: 'testVue',
67
+                        //     component: () => import('@/views/depart/departLevel/TestProSelectTree.vue'),
68
+                        //     meta: { title: 'menu.system.zzmanage.testProSelectTree.title' },
69
+                        // },
70
+                        // {   //测试树组件
71
+                        //     path: '/zp/automake/system/zzmanage/TestProTree3',
72
+                        //     name: 'testVue',
73
+                        //     component: () => import('@/views/depart/departLevel/TestProTree3.vue'),
74
+                        //     meta: { title: 'menu.system.zzmanage.testProTree3.title' },
75
+                        // },
76
+                        {   //测试下拉树组件
77
+                            path: '/zp/automake/system/zzmanage/TestProSelectTree3',
78
+                            name: 'testProSelectTree3',
79
+                            component: () => import('@/views/depart/departLevel/TestProSelectTree3.vue'),
80
+                            meta: { title: 'menu.system.zzmanage.testProSelectTree3.title' },
51 81
                         }
82
+                        // {   //币种维护
83
+                        //     path: '/zp/automake/system/zzmanage/CurrencyManager',
84
+                        //     name: 'currencyManager',
85
+                        //     component: () => import('@/views/currencyManager/CurrencyManagerView.vue'),
86
+                        //     meta: { title: 'menu.system.zzmanage.currencyManager.title' },
87
+                        // }
52 88
                     ]
53 89
                 }
54 90
 
@@ -131,6 +167,41 @@ export const example: Router = {
131 167
                     ]
132 168
                 },
133 169
             ]
170
+        },
171
+        {   //组件测试
172
+            path: '/zp/example',
173
+            name: 'example',
174
+            component: RouteView,
175
+            meta: { title: 'menu.example.title' },
176
+            children: [
177
+                {   //日期选择器
178
+                    path: '/zp/example/ProDatePickerExample',
179
+                    name: 'proDatePickerExample',
180
+                    component: () => import('@/views/example/ProDatePickerExample.vue'),
181
+                    meta: { title: 'menu.example.proDatePickerExample.title' },
182
+                }
183
+            ]
184
+        }
185
+        ,
186
+        {   //柜面
187
+            path: '/zp/T2000',
188
+            name: 't2000',
189
+            component: RouteView,
190
+            meta: { title: 'menu.t2000.title' },
191
+            children: [
192
+                {   //日期选择器
193
+                    path: '/zp/t2000/T2000',
194
+                    name: 't2000',
195
+                    component: () => import('@/views/front/t2000/T2000.vue'),
196
+                    meta: { title: 'menu.t2000.t2000.title' },
197
+                },
198
+                {   //日期选择器
199
+                    path: '/zp/t2001/T2001',
200
+                    name: 't2001',
201
+                    component: () => import('@/views/front/t2001/T2001.vue'),
202
+                    meta: { title: 'menu.t2001.t2001.title' },
203
+                }
204
+            ]
134 205
         }
135 206
     ]
136 207
 }

+ 4
- 0
ant-design-pro-vue3/src/router/routerGuard.ts 查看文件

@@ -60,9 +60,13 @@ const defaultRoutePath = '/zp'
60 60
 // }
61 61
 
62 62
 export const setupBeforeEach = (router: Router) => {
63
+    console.log('routerGuard-start')
64
+
63 65
     router.beforeEach((to, from, next) => {
64 66
         NProgress.start() // 加载进度条
65 67
         setDocumentTitle(to)
68
+        console.log('routerGuard', ls.get(USER_INFO), ls.get(ROLE_INFO), ls.get(DEPART_INFO), to.path);
69
+
66 70
         if (ls.get(USER_INFO) && ls.get(ROLE_INFO) && ls.get(DEPART_INFO)) {
67 71
             /* has token */
68 72
             if (to.path === '/user/login') {

+ 50
- 0
ant-design-pro-vue3/src/style/theme.less 查看文件

@@ -0,0 +1,50 @@
1
+// @import 'ant-design-vue/lib/style/themes/default.less';
2
+// @import 'ant-design-vue/dist/antd.dark.less';
3
+// @root-entry-name: variable;
4
+
5
+@white: #fff;
6
+@black: #000;
7
+
8
+html:not(.dark) {
9
+  @component-background: @white;
10
+}
11
+
12
+// html.dark {
13
+// }
14
+
15
+.setStyle(@className, @propName) {
16
+  html {
17
+    &.dark {
18
+      .@{className} {
19
+        @{propName}: @black;
20
+      }
21
+    }
22
+
23
+    &:not(.dark) {
24
+      .@{className} {
25
+        @{propName}: @white;
26
+      }
27
+    }
28
+  }
29
+}
30
+
31
+.themeColor(@classNames, @i: 1) when(@i =< length(@classNames)) {
32
+  @className: extract(@classNames, @i);
33
+
34
+  .setStyle(@className, background-color);
35
+  .setStyle(@className, color);
36
+
37
+  .themeColor(@classNames, (@i + 1));
38
+}
39
+
40
+.themeTextColor(@classNames, @i: 1) when(@i =< length(@classNames)) {
41
+  @className: extract(@classNames, @i);
42
+  .setStyle(@className, color);
43
+  .themeColor(@classNames, (@i + 1));
44
+}
45
+
46
+.themeBgColor(@classNames, @i: 1) when(@i =< length(@classNames)) {
47
+  @className: extract(@classNames, @i);
48
+  .setStyle(@className, background-color);
49
+  .themeColor(@classNames, (@i + 1));
50
+}

+ 361
- 0
ant-design-pro-vue3/src/utils/treeUtil.js 查看文件

@@ -0,0 +1,361 @@
1
+import { isEmpty } from '@/utils/validate';
2
+
3
+/**
4
+ * 获取指定节点的父节点和爷节点的 key
5
+ * @param {Array} treeData - 树形数据数组,每个节点可以包含 children 属性表示子节点
6
+ * @param {string|number} key - 要查找的目标节点的 key 值
7
+ * @param {Object} fieldNames - 节点中表示 key 的字段名配置,默认为 { key: 'key' }
8
+ * @returns {Array} - 包含父节点和爷节点 key 的数组
9
+ */
10
+export function getAnsKeys(treeData, key, fieldNames = { key: 'key' }) {
11
+    const parentKeys = [];
12
+    // 递归查找目标节点并记录其父节点信息
13
+    const findNode = (currentNodes, parentKey = null, grandParentKey = null) => {
14
+        for (const node of currentNodes) {
15
+            if (node[fieldNames.key] === key) {
16
+                // 如果存在父节点,添加到结果数组
17
+                if (parentKey) {
18
+                    parentKeys.push(parentKey);
19
+                }
20
+                // 如果存在爷节点,添加到结果数组
21
+                if (grandParentKey) {
22
+                    parentKeys.push(grandParentKey);
23
+                }
24
+                return;
25
+            }
26
+            if (node.children) {
27
+                // 递归调用,更新父节点和爷节点信息
28
+                findNode(node.children, node[fieldNames.key], parentKey);
29
+            }
30
+        }
31
+    };
32
+    findNode(treeData);
33
+    return parentKeys;
34
+}
35
+
36
+
37
+/**
38
+ * 获取指定节点的子节点和孙节点的 key
39
+ * @param {Array} treeData - 树形结构数据,每个节点包含 id、children 等属性
40
+ * @param {Array} keys - 要选中的节点 ID 数组
41
+ * @returns {Array} - 最终选中的节点 ID 数组
42
+ */
43
+export function getDscKeys(treeData, keys) {
44
+    // 初始化所有节点的选中状态为 false
45
+    function initSelection(tree) {
46
+        tree.forEach((node) => {
47
+            node.selected = false;
48
+            if (node.children) {
49
+                initSelection(node.children);
50
+            }
51
+        });
52
+    }
53
+
54
+    // 选中父节点时,递归选中其所有子节点
55
+    function selectParent(node) {
56
+        node.selected = true;
57
+        if (node.children) {
58
+            node.children.forEach((child) => {
59
+                selectParent(child);
60
+            });
61
+        }
62
+    }
63
+
64
+    // 选中子节点时,更新父节点的选中状态
65
+    function selectChild(node) {
66
+        node.selected = true;
67
+        let parent = node.parent;
68
+        while (parent) {
69
+            const allChildrenSelected = parent.children.every((child) => child.selected);
70
+            parent.selected = allChildrenSelected;
71
+            parent = parent.parent;
72
+        }
73
+    }
74
+
75
+    // 为所有节点设置 parent 属性
76
+    function setParent(tree, parent = null) {
77
+        tree.forEach((node) => {
78
+            node.parent = parent;
79
+            if (node.children) {
80
+                setParent(node.children, node);
81
+            }
82
+        });
83
+    }
84
+
85
+    // 根据传入的 key 选中节点
86
+    function selectNodes(tree, keys) {
87
+        tree.forEach((node) => {
88
+            if (keys.includes(String(node.id))) {
89
+                selectParent(node);
90
+                selectChild(node);
91
+            }
92
+            if (node.children) {
93
+                selectNodes(node.children, keys);
94
+            }
95
+        });
96
+    }
97
+
98
+    // 收集所有选中节点的 id
99
+    function collectSelectedIds(tree) {
100
+        const selectedIds = [];
101
+        const stack = [...tree];
102
+        while (stack.length > 0) {
103
+            const node = stack.pop();
104
+            if (node.selected) {
105
+                selectedIds.push(node.id);
106
+            }
107
+            if (node.children) {
108
+                stack.push(...node.children);
109
+            }
110
+        }
111
+        return selectedIds;
112
+    }
113
+
114
+    // 初始化选中状态
115
+    initSelection(treeData);
116
+    // 设置 parent 属性
117
+    setParent(treeData);
118
+    // 处理节点选中逻辑
119
+    selectNodes(treeData, keys);
120
+    // 收集选中节点的 id
121
+    return collectSelectedIds(treeData);
122
+}
123
+
124
+
125
+export function getWithoutDscKeys (treeData, keys, fieldNames = { key: 'id' }) {
126
+    let withoutDesKeys = [];
127
+    let withoutDesNodes = [];
128
+    const allNodes = getAllNodes(treeData);
129
+    if (keys.length === 1) {
130
+        // 只选中一个节点
131
+        const node = allNodes.find(n => n.id === keys[0]);
132
+        withoutDesKeys.push(node[fieldNames.key]);
133
+        withoutDesNodes.push(node);
134
+    } else {
135
+        // 选中多个节点
136
+        for (let i = 0; i < keys.length; i++) {
137
+            // 找到当前节点
138
+            const node = allNodes.find(n => n.id === keys[i]);
139
+            if (!keys.includes(node.pid)) {
140
+                // 选择的节点对应的父节点没有被选择, 则添加到结果中
141
+                withoutDesKeys.push(node[fieldNames.key]);
142
+                withoutDesNodes.push(node);
143
+            }
144
+        }
145
+    }
146
+    // 返回包含三个数组的对象
147
+    return {
148
+        withoutDesKeys,
149
+        withoutDesNodes
150
+    };
151
+}
152
+
153
+
154
+
155
+/**
156
+ * 
157
+ * @param {Array} treeData 
158
+ * @param {String} targetId 
159
+ * @param {Array} checkedKeys 
160
+ * @returns 
161
+ */
162
+export function delAnsAndDscKeys(treeData, targetId, checkedKeys) {
163
+    // 存储需要移除的节点 ID
164
+    let keysToRemove = [];
165
+
166
+    // 递归收集要删除的节点及其所有子节点的 ID
167
+    function collectKeysToRemove(node) {
168
+        keysToRemove.push(node.id);
169
+        if (node.children && node.children.length > 0) {
170
+            node.children.forEach(child => collectKeysToRemove(child));
171
+        }
172
+    }
173
+
174
+    // 遍历树结构,找到要删除的节点并收集其及子节点的 ID
175
+    function traverseTree(nodes) {
176
+        nodes.forEach(node => {
177
+            if (Array.isArray(targetId) ? targetId.includes(node.id) : node.id === targetId) {
178
+                collectKeysToRemove(node);
179
+            } else if (node.children && node.children.length > 0) {
180
+                traverseTree(node.children);
181
+            }
182
+        });
183
+    }
184
+
185
+    // 递归查找目标节点的所有上级节点的 ID
186
+    function findParentIds(nodes, target, parents = []) {
187
+        for (let node of nodes) {
188
+            if (Array.isArray(target) ? target.includes(node.id) : node.id === target) {
189
+                return parents;
190
+            }
191
+            if (node.children && node.children.length > 0) {
192
+                const newParents = [...parents, node.id];
193
+                const found = findParentIds(node.children, target, newParents);
194
+                if (found.length > 0) {
195
+                    return found;
196
+                }
197
+            }
198
+        }
199
+        return [];
200
+    }
201
+
202
+    traverseTree(treeData);
203
+
204
+    // 收集目标节点的上级节点 ID 并添加到 keysToRemove 中
205
+    if (Array.isArray(targetId)) {
206
+        targetId.forEach(id => {
207
+            const parentIds = findParentIds(treeData, id);
208
+            keysToRemove = keysToRemove.concat(parentIds);
209
+        });
210
+    } else {
211
+        const parentIds = findParentIds(treeData, targetId);
212
+        keysToRemove = keysToRemove.concat(parentIds);
213
+    }
214
+
215
+    // 过滤掉需要移除的节点 ID
216
+    return checkedKeys.filter(key => !keysToRemove.includes(key));
217
+}
218
+
219
+/**
220
+ * 在树形数据中查找具有指定字段名和值的节点。
221
+ * 支持传入单个值或值数组进行匹配。
222
+ * 匹配成功的节点将去除其 `children` 属性后添加到结果数组中。
223
+ * 
224
+ * @param {Array} treeData - 树形数据,是一个包含节点对象的数组。每个节点对象可以有一个 `children` 属性,用于表示子节点数组。
225
+ * @param {string} fieldName - 要匹配的字段名,即节点对象中的属性名。
226
+ * @param {string|Array} value - 要匹配的值,可以是单个字符串或字符串数组。
227
+ * @returns {Array} - 返回一个数组,包含所有匹配到的节点(去除 `children` 属性)。如果传入的 `value` 为空,则返回空数组。
228
+ */
229
+export function findNodes (treeData, fieldName, value) {
230
+    // 如果传入的 value 为空,则直接返回空数组
231
+    if (!value) return [];
232
+    // 用于存储找到的匹配节点
233
+    const result = [];
234
+    // 遍历树形数据中的每个节点
235
+    treeData.forEach(node => {
236
+        // 标记当前节点是否匹配
237
+        let isMatch = false;
238
+        // 判断 value 是否为字符串
239
+        if (typeof value === 'string') {
240
+            // 如果当前节点的指定字段值等于传入的字符串值,则标记为匹配
241
+            if (node[fieldName] === value) {
242
+                isMatch = true;
243
+            }
244
+        } 
245
+        // 判断 value 是否为数组
246
+        else if (Array.isArray(value)) {
247
+            // 如果当前节点的指定字段值存在于传入的数组中,则标记为匹配
248
+            if (value.includes(node[fieldName])) {
249
+                isMatch = true;
250
+            }
251
+        }
252
+        // 如果当前节点匹配
253
+        if (isMatch) {
254
+            // 解构赋值,去除节点的 children 属性
255
+            const { children, ...nodeWithoutChildren } = node;
256
+            // 将去除 children 属性的节点添加到结果数组中
257
+            result.push(nodeWithoutChildren);
258
+        }
259
+        // 如果当前节点有子节点
260
+        if (node.children && node.children.length > 0) {
261
+            // 递归调用 findNodes 函数,在子节点中继续查找匹配的节点,并将结果添加到结果数组中
262
+            result.push(...findNodes(node.children, fieldName, value));
263
+        }
264
+    });
265
+    // 返回结果数组
266
+    return result;
267
+}
268
+
269
+/**
270
+ * 在树形数据中搜索具有指定字段名且该字段值包含指定搜索值的节点。
271
+ * 匹配成功的节点将去除其 `children` 属性后添加到结果数组中。
272
+ * 
273
+ * @param {Array} treeData - 树形数据,是一个包含节点对象的数组。每个节点对象可以有一个 `children` 属性,用于表示子节点数组。
274
+ * @param {string} fieldName - 要搜索的字段名,即节点对象中的属性名。
275
+ * @param {string} value - 要搜索的值,必须是字符串类型。
276
+ * @returns {Array} - 返回一个数组,包含所有匹配到的节点(去除 `children` 属性)。如果传入的 `value` 为空,则返回空数组。
277
+ */
278
+export function searchNodes (treeData, fieldName, value) {
279
+    // 如果传入的 value 为空,则直接返回空数组
280
+    if (!value) return [];
281
+    // 用于存储找到的匹配节点
282
+    const result = [];
283
+    // 定义一个递归函数,用于遍历树形数据
284
+    const traverse = (nodes) => {
285
+        // 遍历当前层级的所有节点
286
+        nodes.forEach((node) => {
287
+            // 如果当前节点的指定字段值包含传入的搜索值
288
+            if (node[fieldName].includes(value)) {
289
+                // 解构赋值,去除节点的 children 属性
290
+                const { children, ...nodeWithoutChildren } = node;
291
+                // 将去除 children 属性的节点添加到结果数组中
292
+                result.push(nodeWithoutChildren);
293
+            }
294
+            // 如果当前节点有子节点
295
+            if (node.children && node.children.length > 0) {
296
+                // 递归调用 traverse 函数,继续遍历子节点
297
+                traverse(node.children);
298
+            }
299
+        });
300
+    };
301
+    // 从根节点开始调用 traverse 函数进行遍历
302
+    traverse(treeData);
303
+    // 返回结果数组
304
+    return result;
305
+};
306
+
307
+
308
+/**
309
+ * 从树形数据中获取所有节点(去除 children 属性)
310
+ * @param {Array} treeData - 树形数据数组,每个节点可以包含 children 属性表示子节点
311
+ * @returns {Array} - 包含所有节点(去除 children 属性)的数组
312
+ */
313
+export function getAllNodes(treeData) {
314
+    let allNodes = [];
315
+    const traverse = (nodeList) => {
316
+        nodeList.forEach(node => {
317
+            const { children, ...nodeWithoutChildren } = node;
318
+            allNodes.push(nodeWithoutChildren); // 收集当前节点
319
+            if (node.children) {
320
+                traverse(node.children); // 递归遍历子节点
321
+            }
322
+        });
323
+    };
324
+    traverse(treeData);
325
+    console.log('wyq-treeUtil-getAllNodes',allNodes);
326
+    return allNodes;
327
+}
328
+
329
+
330
+
331
+// 封装成树形结构的公共方法
332
+export function convertToTree (data) {
333
+    // 用于存储每个节点的映射,键为节点的 id,值为节点对象
334
+    const nodeMap = {};
335
+    // 存储根节点的数组
336
+    const tree = [];
337
+    const localData = [];
338
+    // 第一次遍历,将每个节点存储到 nodeMap 中
339
+    data.forEach(item => {
340
+        // 为每个节点添加 children 属性,用于存储其子节点
341
+        item.children = [];
342
+        // 去重处理, 同一个id只保留一个节点
343
+        if (isEmpty(nodeMap[item.id])) {
344
+            nodeMap[item.id] = item;
345
+            localData.push(item);
346
+
347
+        }
348
+    });
349
+    // 第二次遍历,构建树形结构
350
+    localData.forEach(item => {
351
+        const pid = item.pid;
352
+        if (pid === null || pid === undefined || pid === item.id || !nodeMap[pid]) {
353
+            // 如果 pid 为 null 或 undefined,或者父节点不存在,则将该节点作为根节点
354
+            tree.push(item);
355
+        } else {
356
+            // 否则,将该节点添加到其父节点的 children 数组中
357
+            nodeMap[pid].children.push(item);
358
+        }
359
+    });
360
+    return tree;
361
+}

+ 12
- 9
ant-design-pro-vue3/src/views/CurrencyManager/CurrencyManagerView.vue 查看文件

@@ -6,9 +6,9 @@
6 6
                     v-model:value="formData_3f9a9bdc.key" placeholder="请输入" :allowClear="true"></pro-input>
7 7
                 <pro-input :ref="(el) => formRefs_3f9a9bdc.name = el" :formItemProps="{ label: '币种名称', prop: 'name' }"
8 8
                     v-model:value="formData_3f9a9bdc.name" placeholder="请输入" :allowClear="true"></pro-input>
9
-                <pro-select :ref="(el) => formRefs_3f9a9bdc.use_yn = el" :formItemProps="{ label: '启用标志', prop: 'use_yn' }"
10
-                    v-model:value="formData_3f9a9bdc.use_yn" placeholder="请选择" :allowClear="true"
11
-                    tableName="com_usertype_info" colName="use_yn"></pro-select>
9
+                <pro-select :ref="(el) => formRefs_3f9a9bdc.use_yn = el"
10
+                    :formItemProps="{ label: '启用标志', prop: 'use_yn' }" v-model:value="formData_3f9a9bdc.use_yn"
11
+                    placeholder="请选择" :allowClear="true" tableName="com_usertype_info" colName="use_yn"></pro-select>
12 12
                 <pro-form-item>
13 13
                     <pro-button id="eaa14d90-c51b-11ea-8654-5d95137760bf" @click="queryHandler6da153cb"
14 14
                         :icon="h(SearchOutlined)">查询</pro-button>
@@ -17,13 +17,16 @@
17 17
                     <Expand id="ef472ef0-c51b-11ea-8654-5d95137760bf" downText="收起" upText="展开"></Expand>
18 18
                 </pro-form-item>
19 19
             </pro-form-grid>
20
+
21
+            <pro-table ref="tableRef_594bc79c" :columns="columns_594bc79c" :queryRule="queryRule_594bc79c">
22
+                <template v-slot:header="">
23
+                    <OpenModelButton id="32ce0e30-c528-11ea-ac8a-91bf0c12e282" :modal="CurrencyManagerInsertView"
24
+                        afterShow="CurrencyManager/clickInsertOrModifyBtn" text="新增" :icon="h(PlusOutlined)"
25
+                        type="primary">
26
+                    </OpenModelButton>
27
+                </template>
28
+            </pro-table>
20 29
         </pro-form>
21
-        <pro-table ref="tableRef_594bc79c" :columns="columns_594bc79c" :queryRule="queryRule_594bc79c">
22
-            <template v-slot:header="">
23
-                <OpenModelButton id="32ce0e30-c528-11ea-ac8a-91bf0c12e282" :modal="CurrencyManagerInsertView"
24
-                    afterShow="CurrencyManager/clickInsertOrModifyBtn" text="新增" :icon="h(PlusOutlined)" type="primary">
25
-                </OpenModelButton>
26
-            </template></pro-table>
27 30
     </div>
28 31
 </template>
29 32
 <script setup lang="jsx">

+ 298
- 0
ant-design-pro-vue3/src/views/depart/Test.vue 查看文件

@@ -0,0 +1,298 @@
1
+<template>
2
+    <div id="app">
3
+        <div class="container">
4
+            <div v-if="showLeftPanel" ref="leftPanel" class="left-panel">
5
+                <div class="left-panel-header">
6
+                    <div class="left-panel-title">机构树面板</div>
7
+                    <div class="left-panel-tool">
8
+                        <DoubleLeftOutlined @click="toggleShowLeftPanel" />
9
+                    </div>
10
+                </div>
11
+                <div class="left-panel-body">
12
+                    <span>汇总关系:</span>
13
+                    <pro-select
14
+                        style="width: calc(100% - 50px); height: 25px;position: absolute;right: 10px; margin-top: -13px; top:50%;overflow: hidden; "
15
+                        :allowClear="true">
16
+                    </pro-select>
17
+
18
+                </div>
19
+
20
+                <div>
21
+                    <!-- <a-tabs type="card" v-model:activeKey="activeKey"> -->
22
+                    <a-tabs type="card">
23
+                        <a-tab-pane key="1" tab="账务树">Content of Tab Pane 1</a-tab-pane>
24
+                        <a-tab-pane key="2" tab="对比树">Content of Tab Pane 2</a-tab-pane>
25
+                        <a-tab-pane key="3" tab="报送树">Content of Tab Pane 3</a-tab-pane>
26
+                    </a-tabs>
27
+                </div>
28
+                <div>
29
+                    <a-tree :treeData="treeData" :loadData="onLoadData" :multiple="true" :search="searchValue"
30
+                        @select="onSelect" @deselect="onDeselect" @search="onSearch" />
31
+                </div>
32
+
33
+
34
+
35
+
36
+            </div>
37
+            <div v-else>
38
+                <div class="left-panel-header">
39
+                    <div class="left-panel-tool">
40
+                        <DoubleRightOutlined @click="toggleShowLeftPanel" />
41
+                    </div>
42
+                </div>
43
+            </div>
44
+
45
+            <div class="resizer-horizontal" @mousedown="startDragHorizontal"></div>
46
+            <div ref="rightPanel" class="right-panel">
47
+                <div ref="topPane" class="top-pane">
48
+                    <div>
49
+                        <div class="left-panel-header">
50
+                            <div class="left-panel-title">报表查询</div>
51
+                        </div>
52
+                        <pro-form-grid>
53
+                            <pro-input :formItemProps="{ label: '层级编号', prop: 'levelKey' }" placeholder="请输入层级编号"
54
+                                :allowClear="true">
55
+                            </pro-input>
56
+
57
+                            <pro-select :formItemProps="{ label: '启用标志', prop: 'useYn' }" placeholder="请选择启用标志"
58
+                                :allowClear="true">
59
+                            </pro-select>
60
+                        </pro-form-grid>
61
+
62
+                    </div>
63
+                </div>
64
+                <div class="resizer-vertical" @mousedown="startDragVertical"></div>
65
+                <div ref="bottomPane" class="bottom-pane">
66
+                    <div>底部内容</div>
67
+                </div>
68
+            </div>
69
+        </div>
70
+    </div>
71
+</template>
72
+
73
+<script setup lang="jsx">
74
+import { ref, watch, h, computed } from 'vue';
75
+import { DoubleRightOutlined, DoubleLeftOutlined } from "@ant-design/icons-vue";
76
+
77
+const leftPanel = ref(null);
78
+const rightPanel = ref(null);
79
+const topPane = ref(null);
80
+const bottomPane = ref(null);
81
+
82
+let startX = ref(0);
83
+let startY = ref(0);
84
+
85
+let initialLeftWidth = ref(0); // 左侧面板初始宽度
86
+let initialTopHeight = ref(0); // 顶部面板初始高度
87
+let isResizingHorizontal = ref(false);
88
+let isResizingVertical = ref(false);
89
+
90
+let showLeftPanel = ref(true);
91
+
92
+const searchValue = ref('');
93
+const treeData = [
94
+    {
95
+        title: '总公司',
96
+        key: '0-0',
97
+        children: [
98
+            {
99
+                title: '分公司1',
100
+                key: '0-0-0',
101
+                children: []
102
+            },
103
+            {
104
+                title: '分公司2',
105
+                key: '0-0-1',
106
+                children: []
107
+            }
108
+        ]
109
+    }
110
+
111
+];
112
+const replaceFields = computed(() => {
113
+    return {
114
+        key: 'id',
115
+        title: 'name',
116
+        children: 'children'
117
+    };
118
+});
119
+
120
+function toggleShowLeftPanel () {
121
+    console.log('wyq--切换左侧面板前', showLeftPanel.value);
122
+    showLeftPanel.value = !showLeftPanel.value;
123
+    console.log('wyq--切换左侧面板后', showLeftPanel.value);
124
+}
125
+
126
+function startDragHorizontal (event) {
127
+    console.log('wyq--开始水平拖动');
128
+    isResizingHorizontal = true;
129
+    startX = event.clientX;
130
+    // 转换为百分比
131
+    initialLeftWidth = leftPanel.value.offsetWidth / window.innerWidth * 100;
132
+    document.addEventListener('mousemove', resizeHorizontal);
133
+    document.addEventListener('mouseup', stopResizeHorizontal);
134
+}
135
+
136
+function resizeHorizontal (event) {
137
+    console.log('wyq--开始水平拖动-resizeHorizontal',);
138
+
139
+    if (!isResizingHorizontal) return;
140
+    console.log('wyq--进来了没');
141
+
142
+    const deltaX = event.clientX - startX;
143
+    const newLeftWidthPercent = initialLeftWidth + (deltaX / window.innerWidth * 100);
144
+    const newLeftWidth = (window.innerWidth * newLeftWidthPercent) / 100;
145
+    console.log('wyq--水平拖动', newLeftWidthPercent, newLeftWidth);
146
+
147
+    // 更新左右面板的宽度(使用flex-basis而不是直接设置width,以保持响应式)
148
+    leftPanel.value.style.flexBasis = `${newLeftWidth}px`;
149
+    rightPanel.value.style.flexBasis = `calc(100% - ${newLeftWidth}px)`;
150
+}
151
+
152
+function stopResizeHorizontal () {
153
+    console.log('wyq--开始水平拖动-stopResizeHorizontal');
154
+    isResizingHorizontal = false;
155
+    document.removeEventListener('mousemove', resizeHorizontal);
156
+    document.removeEventListener('mouseup', stopResizeHorizontal);
157
+}
158
+
159
+function startDragVertical (event) {
160
+    console.log('wyq--开始上下拖动');
161
+    isResizingVertical = true;
162
+    startY = event.clientY;
163
+    initialTopHeight = topPane.value.offsetHeight;
164
+    document.addEventListener('mousemove', resizeVertical);
165
+    document.addEventListener('mouseup', stopResizeVertical);
166
+
167
+
168
+}
169
+
170
+function resizeVertical (event) {
171
+    console.log('wyq--开始上下拖动-resizeVertical',);
172
+
173
+    if (!isResizingVertical) return;
174
+    console.log('wyq--进来了没');
175
+
176
+    const deltaY = event.clientY - startY;
177
+    const newHeight = initialTopHeight + deltaY;
178
+
179
+    const minHeight = 50; // 最小高度限制
180
+    const maxHeight = window.innerHeight - minHeight; // 最大高度限制
181
+    let finalHeight = Math.max(minHeight, Math.min(maxHeight, newHeight));
182
+    topPane.value.style.height = `${finalHeight}px`;
183
+    bottomPane.value.style.height = `calc(100% - ${finalHeight}px)`;
184
+}
185
+
186
+function stopResizeVertical () {
187
+    console.log('wyq--开始上下拖动-stopResizeVertical');
188
+    isResizingVertical = false;
189
+    document.removeEventListener('mousemove', resizeVertical);
190
+    document.removeEventListener('mouseup', stopResizeVertical);
191
+
192
+}
193
+</script>
194
+
195
+<style scoped>
196
+#app {
197
+    height: 100vh;
198
+    width: 100vw;
199
+    display: flex;
200
+    justify-content: center;
201
+    align-items: center;
202
+}
203
+
204
+.container {
205
+    display: flex;
206
+    width: 100%;
207
+    height: 100%;
208
+}
209
+
210
+.left-panel {
211
+    /* 纵向排列滚动条*/
212
+    overflow: auto;
213
+    /* background-color: lightblue; */
214
+    flex: 1;
215
+    /* 初始时左面板占10% */
216
+    flex-basis: 18%;
217
+}
218
+
219
+.resizer-horizontal {
220
+    width: 5px;
221
+    cursor: ew-resize;
222
+    background-color: #ccc;
223
+    user-select: none;
224
+}
225
+
226
+.right-panel {
227
+    /* background-color: #e0e0e0; */
228
+    flex: 1;
229
+    /* 初始时左面板占90% */
230
+    flex-basis: 82%;
231
+}
232
+
233
+
234
+
235
+.top-pane {
236
+    /* background-color: blueviolet; */
237
+    height: 20%;
238
+}
239
+
240
+.resizer-vertical {
241
+    height: 5px;
242
+    cursor: ns-resize;
243
+    background-color: #ccc;
244
+    user-select: none;
245
+}
246
+
247
+.bottom-pane {
248
+    background-color: bisque;
249
+    height: 80%;
250
+}
251
+
252
+.div9 {
253
+    /* height: 100px; */
254
+    background-color: #f0f0f0;
255
+}
256
+
257
+.logo {
258
+    height: 32px;
259
+    margin: 16px;
260
+    cursor: pointer;
261
+}
262
+
263
+.left-panel-header {
264
+    height: 34px;
265
+    line-height: 34px;
266
+    border: 0;
267
+    background-color: #94C8C1;
268
+    padding: 0 14px;
269
+    margin: 2px 0;
270
+    display: flex;
271
+    position: relative;
272
+}
273
+
274
+.left-panel-title {
275
+    height: 34px;
276
+    line-height: 34px;
277
+    color: #fff;
278
+    font-weight: bold;
279
+    font-size: 16px;
280
+    margin: 0;
281
+    padding: 0;
282
+}
283
+
284
+.left-panel-tool {
285
+    right: 10px;
286
+    width: auto;
287
+    position: absolute;
288
+    top: 50%;
289
+    margin-top: -17px;
290
+    overflow: hidden;
291
+}
292
+
293
+.left-panel-body {
294
+    padding: 5px;
295
+    position: relative;
296
+
297
+}
298
+</style>

+ 123
- 0
ant-design-pro-vue3/src/views/depart/departLevel.vue 查看文件

@@ -0,0 +1,123 @@
1
+<template>
2
+    <div>
3
+        <pro-form ref="formRef" :model="formData" :rules="formRules" label-width="120px">
4
+            <pro-form-grid>
5
+                <pro-input :ref="(el) => formRefs.levelId = el" :formItemProps="{ label: '层级编号', prop: 'levelId' }"
6
+                    v-model:value="formData.levelId" placeholder="请输入层级编号" :allowClear="true">
7
+                </pro-input>
8
+
9
+                <pro-select :ref="(el) => formRefs.enabledFlag = el"
10
+                    :formItemProps="{ label: '启用标志', prop: 'enabledFlag' }" v-model:value="formData.enabledFlag"
11
+                    placeholder="请选择启用标志" :allowClear="true" :options="enabledOptions">
12
+                </pro-select>
13
+
14
+                <pro-form-item>
15
+                    <pro-button id="queryBtn" @click="query" :icon="h(SearchOutlined)">查询</pro-button>
16
+                    <pro-button id="resetBtn" @click="reset" :icon="h(RedoOutlined)">重置</pro-button>
17
+                    <Expand id="expandBtn" downText="收起" upText="展开"></Expand>
18
+                </pro-form-item>
19
+
20
+            </pro-form-grid>
21
+        </pro-form>
22
+
23
+        <pro-table ref="tableRef" :columns="columns" :queryRule="queryRule" :rowSelection="false">
24
+            <template v-slot:header="">
25
+                <OpenModelButton :modal="departLevelInsertView" afterShow="CurrencyManager/clickInsertOrModifyBtn"
26
+                    text="新增" :icon="h(PlusOutlined)" type="primary">
27
+                </OpenModelButton>
28
+            </template>
29
+        </pro-table>
30
+    </div>
31
+</template>
32
+<script setup lang="jsx">
33
+import { ref, reactive, h, computed } from 'vue';
34
+import { SearchOutlined, RedoOutlined, PlusOutlined, EditOutlined } from "@ant-design/icons-vue";
35
+import { useStore } from 'vuex';
36
+import departLevelInfo from './departLevelInfo.vue';
37
+const store = useStore();
38
+const formData = ref({
39
+    levelId: "",
40
+    enabledFlag: null
41
+});
42
+const formRules = ref({
43
+    // 添加验证规则
44
+});
45
+const formRefs = reactive({
46
+    levelId: "",
47
+    enabledFlag: ""
48
+});
49
+
50
+const enabledOptions = [
51
+    { label: '启用', value: 'Y' },
52
+    { label: '未启用', value: 'N' }
53
+];
54
+
55
+
56
+
57
+function query () {
58
+    // 查询
59
+}
60
+function reset () {
61
+    // 重置
62
+}
63
+function expand () {
64
+    // 展开/收起
65
+}
66
+
67
+function departLevelInsertView () {
68
+    // 弹出新增弹窗
69
+}
70
+
71
+
72
+
73
+const queryParams = ref({});
74
+
75
+// 定义了一个计算属性 departLevelData,它的值来自 Vuex 状态管理中的 departLevel.departLevelData
76
+// 通过使用 computed,当 store.state.departLevel.departLevelData 发生变化时,departLevelData 会自动更新。这种反应式的特性使得数据在 UI 中保持同步。
77
+const departLevelData = computed(() => store.state.departLevel.departLevelData);
78
+
79
+// 该函数是一个异步函数,用于根据传入的 payload 和 params 请求和返回表格数据。
80
+// payload参数‌是一个对象,用于在组件之间传递数据。Payload参数包含要传递给组件的数据,这些数据可以是任何类型,包括字符串、数字、布尔值、对象和数组等‌
81
+async function queryRule (payload, params) {
82
+    // queryParam 变量用于存储查询参数,如果存在 queryParams(可能是通过 Vue 的响应式引用取得的),则将其值赋予 queryParam。
83
+    let queryParam = {};
84
+    if (queryParams) {
85
+        queryParam = queryParams.value;
86
+    }
87
+    // 向后台请求表格数据
88
+    // 通过调用 Vuex 中的 dispatch 方法发送一个名为 CurrencyManager/queryCurrency 的 action。
89
+    await store.dispatch('departLevel/queryDepartLevel', {
90
+        values: {
91
+            page: payload.pageIndex,
92
+            rows: payload.pageSize,
93
+            ...params,
94
+            ...queryParam
95
+        }
96
+    });
97
+    const resp = departLevelData.value;
98
+    return {
99
+        current: payload.pageIndex,
100
+        pageSize: payload.pageSize,
101
+        total: resp.total,
102
+        data: resp.records
103
+    };
104
+
105
+}
106
+
107
+// 列定义
108
+const columns = [
109
+    {
110
+        prop: "ActionColumn", label: "操作", width: 150, render: (scope) => {
111
+            return <div>
112
+                <OpenModelButton id="651rew123" modal={departLevelInfo} afterShow="departLevel/clickInsertOrModifyBtn" text="修改" icon={h(EditOutlined)} type="primary" payload={scope.record}>
113
+                </OpenModelButton>
114
+            </div>
115
+        },
116
+        align: "center",
117
+    },
118
+    { prop: 'key', title: '层级编号', width: 150 },
119
+    { prop: 'name', title: '层级名称', width: 150 },
120
+    { prop: 'use', title: '用途', width: 150 },
121
+    { prop: 'use_yn', title: '启用标志', width: 150 }
122
+];
123
+</script>

+ 171
- 0
ant-design-pro-vue3/src/views/depart/departLevel/DepartLevelDef copy.vue 查看文件

@@ -0,0 +1,171 @@
1
+<template>
2
+    <div>
3
+        <pro-form ref="formRef" :model="formData" :rules="formRules" label-width="120px">
4
+            <pro-form-grid>
5
+                <pro-input :formItemProps="{ label: '层级编号', prop: 'levelKey' }" v-model:value="formData.levelKey"
6
+                    placeholder="请输入层级编号" :allowClear="true">
7
+                </pro-input>
8
+
9
+                <pro-select :formItemProps="{ label: '启用标志', prop: 'useYn' }" v-model:value="formData.useYn"
10
+                    placeholder="请选择启用标志" :allowClear="true" :options="enabledOptions">
11
+                </pro-select>
12
+
13
+                <pro-form-item>
14
+                    <pro-button id="queryBtn" @click="search" :icon="h(SearchOutlined)">查询</pro-button>
15
+                    <pro-button id="resetBtn" @click="reset" :icon="h(RedoOutlined)">重置</pro-button>
16
+                    <!-- 问题3: 根本就没有这个组件 -->
17
+                    <Expand id="expandBtn" downText="收起" upText="展开">
18
+                    </Expand>
19
+                </pro-form-item>
20
+            </pro-form-grid>
21
+        </pro-form>
22
+
23
+        <pro-table ref="tableRef" :columns="columns" :queryRule="queryRule" :rowSelection="false">
24
+            <template v-slot:header="">
25
+                <OpenModelButton :modal="DepartLevelInfo" afterShow="DepartLevel/addOrModify" text="新增"
26
+                    :icon="h(PlusOutlined)" type="primary">
27
+                </OpenModelButton>
28
+            </template>
29
+        </pro-table>
30
+    </div>
31
+</template>
32
+<script setup lang="jsx">
33
+import { ref, reactive, h, computed } from 'vue';
34
+import { SearchOutlined, RedoOutlined, PlusOutlined, EditOutlined } from "@ant-design/icons-vue";
35
+import { useStore } from 'vuex';
36
+import DepartLevelInfo from './DepartLevelInfo.vue';
37
+const emit = defineEmits(['close:modal'])
38
+const store = useStore();
39
+// 表单组件的引用
40
+const formRef = ref();
41
+// 表格组件的引用
42
+const tableRef = ref();
43
+// 表单数据
44
+const formData = ref({
45
+    // 表单字段的初始值
46
+    levelKey: "",
47
+    useYn: ""
48
+});
49
+
50
+// 表单验证规则
51
+const formRules = ref({
52
+    // 添加验证规则
53
+    levelKey: [
54
+        { required: false, trigger: 'blur' },
55
+        // 其他校验规则
56
+    ],
57
+    useYn: [
58
+        { required: false, trigger: 'change' },
59
+        // 其他校验规则
60
+    ]
61
+});
62
+// 定义了一个计算属性 departLevelData,它的值来自 Vuex 状态管理中的 departLevel.departLevelData
63
+// 通过使用 computed,当 store.state.departLevel.departLevelDefData 发生变化时,departLevelDefData 会自动更新。
64
+const departLevelDefData = computed(() => store.state.DepartLevel.departLevelDefData);
65
+const enabledOptions = [
66
+    { label: '启用', value: 'Y' },
67
+    { label: '未启用', value: 'N' }
68
+];
69
+
70
+function search () {
71
+    // 查询
72
+    // 问题1:为什么要在这里调用 validate 方法?,校验是怎么处理调用的对不对
73
+    formRef.value.validate().then(values => {
74
+        //表单校验成功
75
+        // 这一步会触发 queryRule 函数,使用更新后的查询参数重新请求数据并刷新表格。
76
+        tableRef.value.reload();
77
+    });
78
+}
79
+
80
+function reset () {
81
+    // 调用原生组件的重置表单方法
82
+    formRef.value.getOrignRef().resetFields();
83
+}
84
+
85
+function departLevelInsertView () {
86
+    // 弹出新增弹窗
87
+}
88
+
89
+// 该函数是一个异步函数,用于根据传入的 payload 和 params 请求和返回表格数据。
90
+// payload参数‌是一个对象,用于在组件之间传递数据。Payload参数包含要传递给组件的数据,这些数据可以是任何类型,包括字符串、数字、布尔值、对象和数组等‌
91
+async function queryRule (payload, params) {
92
+    // 问题2: params是个啥,而且是一个
93
+    // queryParam 变量用于存储查询参数,如果存在 queryParams(可能是通过 Vue 的响应式引用取得的),则将其值赋予 queryParam。
94
+    let queryParams = {
95
+        page: payload.pageIndex,
96
+        rows: payload.pageSize,
97
+        ...params,
98
+        key: formData.value.levelKey,
99
+        use_yn: formData.value.useYn
100
+    };
101
+
102
+    // 向后台请求表格数据
103
+    // 通过调用 Vuex 中的 dispatch 方法发送一个名为 DepartLevel/queryDepartLevelDefData 的 action。
104
+    await store.dispatch('DepartLevel/queryDepartLevelDefData', {
105
+        values: {
106
+            ...queryParams
107
+        }
108
+    });
109
+    // 由于 store.state.DepartLevel.departLevelDefData 是一个响应式引用,
110
+    // 因此当 store.state.DepartLevel.departLevelDefData 发生变化时,departLevelDefData 也会自动更新。
111
+    const resp = departLevelDefData.value;
112
+    return {
113
+        current: payload.pageIndex,
114
+        pageSize: payload.pageSize,
115
+        total: resp.total,
116
+        data: resp.records
117
+    };
118
+}
119
+
120
+
121
+
122
+var showUseYn = (text, record) => {
123
+    console.log("wyq", text, record);
124
+    let value = false;
125
+    if (record.use_yn == 'Y') {
126
+        console.log("wyq1", text, record);
127
+
128
+        value = true;
129
+    }
130
+
131
+
132
+    return <a-button type="primary" size="small" onClick={() => changeUseYn(value, record)}>
133
+        {value ? "启用" : "未启用"}
134
+    </a-button>
135
+};
136
+
137
+function changeUseYn (value, record) {
138
+    console.log("changeUseYn", value, record);
139
+    // let use_yn = 'N';
140
+    // if (value) {
141
+    //     use_yn = 'Y';
142
+    // }
143
+    // store.dispatch('DepartLevel/updateDepartLevelDefData', {
144
+    //     values: {
145
+    //         id: record.id,
146
+    //         use_yn: use_yn
147
+    //     }
148
+    // });
149
+}
150
+
151
+// 列定义
152
+const columns = [
153
+    {
154
+        prop: "ActionColumn", label: "操作", width: 150, render: (scope) => {
155
+            return <div>
156
+                <OpenModelButton id="651rew123" modal={DepartLevelInfo} afterShow="DepartLevel/addOrModify"
157
+                    text="修改" icon={h(EditOutlined)} type="primary" payload={scope.record}>
158
+                </OpenModelButton>
159
+            </div>
160
+        },
161
+        align: "center",
162
+    },
163
+    { prop: 'key', title: '层级编号', width: 150 },
164
+    { prop: 'name', title: '层级名称', width: 150 },
165
+    { prop: 'use', title: '用途', width: 150 },
166
+    {
167
+        prop: 'use_yn', title: '启用标志', width: 150,
168
+        render: scop => showUseYn(scop.record.use_yn, scop.record)
169
+    }
170
+];
171
+</script>

+ 173
- 0
ant-design-pro-vue3/src/views/depart/departLevel/DepartLevelDef.vue 查看文件

@@ -0,0 +1,173 @@
1
+<template>
2
+    <div>
3
+        <pro-form ref="formRef" :model="formData" :rules="formRules" label-width="120px">
4
+            <pro-form-grid>
5
+                <pro-input :formItemProps="{ label: '层级编号', prop: 'levelKey' }" v-model:value="formData.levelKey"
6
+                    placeholder="请输入层级编号" :allowClear="true">
7
+                </pro-input>
8
+                <pro-select :formItemProps="{ label: '启用标志', prop: 'useYn' }" v-model:value="formData.useYn"
9
+                    placeholder="请选择启用标志" :allowClear="true" tableName="com_usertype_info" colName="use_yn">
10
+                </pro-select>
11
+
12
+                <pro-form-item>
13
+                    <pro-button id="queryBtn" @click="search" :icon="h(SearchOutlined)">查询</pro-button>
14
+                    <pro-button id="resetBtn" @click="reset" :icon="h(RedoOutlined)">重置</pro-button>
15
+                    <!-- 问题3: 根本就没有这个组件 -->
16
+                    <Expand id="expandBtn" downText="收起" upText="展开">
17
+                    </Expand>
18
+                </pro-form-item>
19
+            </pro-form-grid>
20
+        </pro-form>
21
+
22
+        <pro-table ref="tableRef" :columns="columns" :queryRule="queryRule" :rowSelection="false">
23
+            <template v-slot:header="">
24
+                <OpenModelButton :modal="DepartLevelInfo" beforeShow="DepartLevel/loadDialogDataData" text="新增"
25
+                    :icon="h(PlusOutlined)" type="primary" @addData="getList">
26
+                </OpenModelButton>
27
+            </template>
28
+        </pro-table>
29
+    </div>
30
+</template>
31
+<script setup lang="jsx">
32
+import { ref, watch, h, computed } from 'vue';
33
+import { SearchOutlined, RedoOutlined, PlusOutlined, EditOutlined } from "@ant-design/icons-vue";
34
+import { useStore } from 'vuex';
35
+import DepartLevelInfo from './DepartLevelInfo.vue';
36
+const emit = defineEmits(['close:modal'])
37
+const store = useStore();
38
+// 表单组件的引用
39
+const formRef = ref();
40
+// 表格组件的引用
41
+const tableRef = ref();
42
+// 表单数据
43
+const formData = ref({
44
+    // 表单字段的初始值
45
+    levelKey: "",
46
+    useYn: ""
47
+});
48
+function getList () {
49
+    console.log("wyq----getList 触发成功 ");
50
+}
51
+// 表单验证规则
52
+const formRules = ref({
53
+    // 添加验证规则
54
+    levelKey: [
55
+        { required: false, trigger: 'blur' },
56
+        // 其他校验规则
57
+    ],
58
+    useYn: [
59
+        { required: false, trigger: 'change' },
60
+        // 其他校验规则
61
+    ]
62
+});
63
+// 定义了一个计算属性 departLevelData,它的值来自 Vuex 状态管理中的 departLevel.departLevelData
64
+// 通过使用 computed,当 store.state.departLevel.departLevelDefData 发生变化时,departLevelDefData 会自动更新。
65
+const departLevelDefData = computed(() => store.state.DepartLevel.departLevelDefData);
66
+
67
+
68
+// 监听是否保存数据成功的标志位
69
+watch(() => store.state.DepartLevel.saveFlag, async (newVal, oldVal) => {
70
+    if (newVal != oldVal) {
71
+        search();
72
+    }
73
+});
74
+
75
+const enabledOptions = [
76
+    { label: '启用', value: 'Y' },
77
+    { label: '未启用', value: 'N' }
78
+];
79
+
80
+function search () {
81
+    // 查询
82
+    // 问题1:为什么要在这里调用 validate 方法?,校验是怎么处理调用的对不对
83
+    formRef.value.validate().then(values => {
84
+        //表单校验成功
85
+        // 这一步会触发 queryRule 函数,使用更新后的查询参数重新请求数据并刷新表格。
86
+        tableRef.value.reload();
87
+    });
88
+}
89
+
90
+function reset () {
91
+    // 调用原生组件的重置表单方法
92
+    formRef.value.getOrignRef().resetFields();
93
+}
94
+
95
+// 该函数是一个异步函数,用于根据传入的 payload 和 params 请求和返回表格数据。
96
+// payload参数‌是一个对象,用于在组件之间传递数据。Payload参数包含要传递给组件的数据,这些数据可以是任何类型,包括字符串、数字、布尔值、对象和数组等‌
97
+async function queryRule (payload, params) {
98
+    // 问题2: params是个啥,而且是一个
99
+    // queryParam 变量用于存储查询参数,如果存在 queryParams(可能是通过 Vue 的响应式引用取得的),则将其值赋予 queryParam。
100
+    let queryParams = {
101
+        page: payload.pageIndex,
102
+        rows: payload.pageSize,
103
+        ...params,
104
+        key: formData.value.levelKey,
105
+        use_yn: formData.value.useYn
106
+    };
107
+
108
+    // 向后台请求表格数据
109
+    // 通过调用 Vuex 中的 dispatch 方法发送一个名为 DepartLevel/queryDepartLevelDefData 的 action。
110
+    await store.dispatch('DepartLevel/queryDepartLevelDefData', {
111
+        values: {
112
+            ...queryParams
113
+        }
114
+    });
115
+    // 由于 store.state.DepartLevel.departLevelDefData 是一个响应式引用,
116
+    // 因此当 store.state.DepartLevel.departLevelDefData 发生变化时,departLevelDefData 也会自动更新。
117
+    const resp = departLevelDefData.value;
118
+    return {
119
+        current: payload.pageIndex,
120
+        pageSize: payload.pageSize,
121
+        total: resp.total,
122
+        data: resp.records
123
+    };
124
+}
125
+
126
+
127
+
128
+var showUseYn = (text, record) => {
129
+    let value = false;
130
+    if (record.use_yn == 'Y') {
131
+        value = true;
132
+    }
133
+    return <a-button type="primary" size="small" onClick={() => changeUseYn(value, record)}>
134
+        {value ? "启用" : "未启用"}
135
+    </a-button>
136
+};
137
+
138
+async function changeUseYn (value, record) {
139
+    console.log("wyq ------------changeUseYn", value, record);
140
+    // 调用后台接口修改数据
141
+    // 调用 Vuex 中的 dispatch 方法发送一个名为 DepartLevel/changeUseYn 的 action。
142
+    // 这个地方必须等待更新启用标志的操作完成,才能重新查询表格数据。所以设置为同步处理
143
+    await store.dispatch('DepartLevel/changeUseYn', {
144
+        values: {
145
+            no: record.no,
146
+            use_yn: record.use_yn
147
+        }
148
+    });
149
+    // 回调下查询方法
150
+    search();
151
+}
152
+
153
+// 列定义
154
+const columns = [
155
+    {
156
+        prop: "ActionColumn", label: "操作", width: 150, render: (scope) => {
157
+            return <div>
158
+                <OpenModelButton id="651rew123" modal={DepartLevelInfo} beforeShow="DepartLevel/loadDialogDataData"
159
+                    text="修改" icon={h(EditOutlined)} type="primary" payload={scope.record}>
160
+                </OpenModelButton>
161
+            </div>
162
+        },
163
+        align: "center",
164
+    },
165
+    { prop: 'key', title: '层级编号', width: 150 },
166
+    { prop: 'name', title: '层级名称', width: 150 },
167
+    { prop: 'use', title: '用途', width: 150 },
168
+    {
169
+        prop: 'use_yn', title: '启用标志', width: 150,
170
+        render: scop => showUseYn(scop.record.use_yn, scop.record)
171
+    }
172
+];
173
+</script>

+ 179
- 0
ant-design-pro-vue3/src/views/depart/departLevel/DepartLevelInfo copy.vue 查看文件

@@ -0,0 +1,179 @@
1
+<template>
2
+    <div>
3
+        <pro-dialog :visible="$attrs.visible" @close="$emit('close:modal')" :title="title" width="70%" :closable="true"
4
+            :destroyOnClose="true" :maskClosable="true">
5
+            <template v-slot:footer="">
6
+                <pro-button id="f3dd65a2-c52b-11ea-87c3-ff36a904ecf1" @click="$emit('close:modal')"
7
+                    :icon="h(CloseOutlined)">关闭</pro-button>
8
+                <pro-button id="f3dd65a4-c52b-11ea-87c3-ff36a904ecf2" @click="save"
9
+                    :icon="h(SaveOutlined)">保存</pro-button>
10
+            </template>
11
+
12
+            <pro-form ref="formRef" :model="formData" :rules="formRules" label-width="120px">
13
+                <pro-form-grid :header="{ title: '基本信息' }" colNum="4">
14
+                    <pro-input v-show="false" :formItemProps="{ label: 'no', prop: 'no' }" v-model:value="formData.no"
15
+                        placeholder="请输入" :allowClear="true">
16
+                    </pro-input>
17
+
18
+                    <pro-input :formItemProps="{ label: '层级编号', prop: 'key' }" v-model:value="formData.key"
19
+                        placeholder="请输入" :allowClear="true">
20
+                    </pro-input>
21
+
22
+                </pro-form-grid>
23
+
24
+
25
+                <pro-form-grid :header="{ title: '层级信息' }" colNum="3">
26
+                    <div>
27
+                        <pro-table ref="tableRef" :columns="columns" :dataSource="departLevelInfoData">
28
+                            <template v-slot:header="">
29
+                                <pro-button id=" 4b7facf0-94a4-11ee-9af3-e137392c498c" text="增加一行"
30
+                                    :icon="h(PlusOutlined)" icon="plus" type="primary"
31
+                                    @click="addRows">增加一行</pro-button>
32
+                            </template>
33
+                        </pro-table>
34
+                    </div>
35
+                </pro-form-grid>
36
+            </pro-form>
37
+        </pro-dialog>
38
+    </div>
39
+</template>
40
+
41
+<script setup lang="jsx">
42
+import { ref, onUnmounted, computed, h, reactive, onMounted } from 'vue';
43
+import { useStore } from 'vuex';
44
+import { CloseOutlined, SaveOutlined, DeleteOutlined, PlusOutlined } from "@ant-design/icons-vue";
45
+import { Modal } from "ant-design-vue";
46
+const store = useStore();
47
+// 表单组件的引用
48
+const formRef = ref();
49
+const tableRef = ref();
50
+// 表单验证规则
51
+const formRules = ref({
52
+    key: [
53
+        { required: true, trigger: 'blur' },
54
+        // 其他校验规则
55
+    ],
56
+    brf: [
57
+        { required: true, trigger: 'blur' },
58
+        // 其他校验规则
59
+    ]
60
+})
61
+// 表单数据
62
+const formData = computed(() => store.state.DepartLevel.dialogData);
63
+const title = computed(() => store.state.DepartLevel.title);
64
+const departLevelInfoData = computed(() => store.state.DepartLevel.departLevelInfoData);
65
+const columns = ref([
66
+    {
67
+        prop: "ActionColumn",
68
+        label: "操作",
69
+        width: "120px",
70
+        align: "center",
71
+        render: (scope) => {
72
+            return <div>
73
+                <pro-button id="deleteId" onClick={() => deleteRows(scope)} icon={h(DeleteOutlined)}>删除</pro-button>
74
+            </div>
75
+        }
76
+    },
77
+    { prop: "key", label: "层级编号", align: "center", width: "120px", editing: true },
78
+    { prop: "name", label: "层级名称", align: "center", width: "120px", editing: true },
79
+    {
80
+        prop: "brf", label: "层级功能描述", align: "center", width: "240px", editing: true,
81
+        rules: [
82
+            { required: true, message: '请输入层级功能描述', trigger: 'blur' }
83
+        ]
84
+    },
85
+]);
86
+
87
+
88
+onUnmounted(() => {
89
+    store.dispatch("DepartLevel/cleanData");
90
+
91
+});
92
+
93
+function save () {
94
+    //校验表单
95
+    console.log("wyq-------save-------检验开始");
96
+    console.log("wyq-------save-------检验开始", formRef.value.validate().values);
97
+
98
+    formRef.value.validate().then(values => {
99
+        for (const [key, value] of Object.entries(values)) {
100
+            console.log(`表单字段 ${key}: ${value}`);
101
+        }
102
+
103
+        if (values) {
104
+            console.log('数据校验成功,可以提交');
105
+            // 执行保存操作
106
+        } else {
107
+            console.log('数据校验失败,请检查输入');
108
+        }
109
+
110
+        // 表单校验成功
111
+        // 执行保存回调
112
+        console.log("wyq-------save----检验通过", values);
113
+
114
+        store.dispatch('DepartLevel/save', {
115
+            values,
116
+            closeMethod: () => { emit("close:modal") }
117
+        });
118
+        console.log("wyq-------save");
119
+
120
+    }).catch(error => {
121
+        if (error.errorFields) {
122
+            error.errorFields.forEach(field => {
123
+                console.log(`字段 ${field.name} 校验失败: ${field.errors.join(', ')}`);
124
+            });
125
+        } else {
126
+            console.log('未知错误:', error);
127
+        }
128
+    });
129
+
130
+    formRef.value.validate().then(values => {
131
+
132
+        for (const [key, value] of Object.entries(values)) {
133
+            console.log(`表单字段 ${key}: ${value}`);
134
+        }
135
+
136
+        if (values) {
137
+            console.log('数据校验成功,可以提交');
138
+            // 执行保存操作
139
+        } else {
140
+            console.log('数据校验失败,请检查输入');
141
+        }
142
+
143
+        //表单校验成功
144
+        //执行保存回调
145
+        console.log("wyq-------save----检验通过", values);
146
+
147
+        store.dispatch('DepartLevel/save', {
148
+            values,
149
+            closeMethod: () => { emit("close:modal") }
150
+        });
151
+        console.log("wyq-------save");
152
+
153
+    });
154
+}
155
+
156
+function addRows () {
157
+    store.dispatch("DepartLevel/addRows", {});
158
+}
159
+function deleteRows (scope) {
160
+    Modal.confirm({
161
+        title: '删除确认',
162
+        content: '确认删除选中的记录',
163
+        cancelText: '取消',
164
+        onOk () {
165
+            store.dispatch('DepartLevel/deleteRows', { ...scope });
166
+        }
167
+    });
168
+}
169
+// 自定义指令用于聚焦
170
+const vFocus = {
171
+    mounted: (el) => {
172
+        console.log('gzg  vFocus');
173
+        el.focus();
174
+        el.querySelector('input')?.focus();
175
+        el.querySelector('a-input')?.focus();
176
+
177
+    }
178
+};
179
+</script>

+ 195
- 0
ant-design-pro-vue3/src/views/depart/departLevel/DepartLevelInfo.vue 查看文件

@@ -0,0 +1,195 @@
1
+<template>
2
+    <div>
3
+        <pro-dialog :visible="$attrs.visible" @close="$emit('close:modal')" :title="title" width="70%" :closable="true"
4
+            :destroyOnClose="true" :maskClosable="true">
5
+            <template v-slot:footer="">
6
+                <pro-button id="f3dd65a2-c52b-11ea-87c3-ff36a904ecf1" @click="$emit('close:modal')"
7
+                    :icon="h(CloseOutlined)">关闭</pro-button>
8
+                <pro-button id="f3dd65a4-c52b-11ea-87c3-ff36a904ecf2" @click="save"
9
+                    :icon="h(SaveOutlined)">保存</pro-button>
10
+            </template>
11
+
12
+            <pro-form ref="formRef" :model="dialogData" :rules="formRules" label-width="120px">
13
+                <pro-form-grid :header="{ title: '基本信息' }" colNum="4">
14
+                    <pro-input v-show="false" :formItemProps="{ label: 'no', prop: 'no' }" v-model:value="dialogData.no"
15
+                        placeholder="请输入" :allowClear="true">
16
+                    </pro-input>
17
+
18
+                    <pro-input :formItemProps="{ label: '层级编号:', prop: 'key' }" v-model:value="dialogData.key"
19
+                        placeholder="请输入" :allowClear="true">
20
+                    </pro-input>
21
+                    <pro-input :formItemProps="{ label: '层级名称:', prop: 'name' }" v-model:value="dialogData.name"
22
+                        placeholder="请输入" :allowClear="true">
23
+                    </pro-input>
24
+                    <pro-input :formItemProps="{ label: '用途:', prop: 'use' }" v-model:value="dialogData.use"
25
+                        placeholder="请输入" :allowClear="true">
26
+                    </pro-input>
27
+                    <pro-select :formItemProps="{ label: '启用标志', prop: 'use_yn' }" disabled="true"
28
+                        v-model:value="dialogData.use_yn" placeholder="请选择启用标志" :allowClear="true"
29
+                        tableName="com_usertype_info" colName="use_yn">
30
+                    </pro-select>
31
+                </pro-form-grid>
32
+
33
+                <pro-form-grid :header="{ title: '层级信息' }" colNum="3">
34
+                    <div>
35
+                        <pro-table ref="tableRef" :columns="columns" :dataSource="dialogData.departLevelInfoData">
36
+                            <template v-slot:header="">
37
+                                <pro-button id=" 4b7facf0-94a4-11ee-9af3-e137392c498c" text="增加一行"
38
+                                    :icon="h(PlusOutlined)" icon="plus" type="primary" @click="addRows"
39
+                                    style="margin-right: 10px;">增加一行</pro-button>
40
+                                <pro-button id=" 4b7facf0-94a4-11ee-9af3-e137392c498d" text="删除" :icon="h(PlusOutlined)"
41
+                                    icon="plus" type="primary" @click="deleteRows2">删除</pro-button>
42
+                            </template>
43
+                        </pro-table>
44
+                    </div>
45
+                </pro-form-grid>
46
+            </pro-form>
47
+        </pro-dialog>
48
+    </div>
49
+</template>
50
+
51
+<script setup lang="jsx">
52
+import * as service from './services';
53
+import { ref, onUnmounted, computed, h, reactive, onMounted, watch } from 'vue';
54
+import { useStore } from 'vuex';
55
+import { CloseOutlined, SaveOutlined, DeleteOutlined, PlusOutlined } from "@ant-design/icons-vue";
56
+import { Modal, message } from "ant-design-vue";
57
+//const emit = defineEmits(['close:modal'])
58
+const emit = defineEmits(['addDataDemo']);
59
+
60
+const store = useStore();
61
+// 表单组件的引用
62
+const formRef = ref();
63
+const tableRef = ref();
64
+const title = computed(() => store.state.DepartLevel.dialogData.title);
65
+const dialogData = computed(() => store.state.DepartLevel.dialogData);
66
+const originalKeyValue = dialogData.value.key;
67
+// 表单验证规则
68
+const formRules = ref({
69
+    key: [
70
+        { required: true, trigger: 'blur' },
71
+        {
72
+            validator: async (rule, value, callback) => {
73
+                try {
74
+                    if (originalKeyValue !== value) {
75
+                        const resp = await service.validateRecord({
76
+                            sql: `select * from Com_depart_level_info where key = ? `,
77
+                            param: value
78
+                        });
79
+                        if (resp === '0000') {
80
+                            console.log("wyq-------code2", resp);
81
+                            return Promise.resolve();
82
+                        } else {
83
+                            return Promise.reject(new Error('编号已存在'));
84
+                        }
85
+                    }
86
+                } catch (error) {
87
+                    message.error('处理失败' + error);
88
+                    return Promise.reject(new Error('处理失败' + error));
89
+                }
90
+            },
91
+            trigger: 'blur'
92
+        }
93
+    ],
94
+    brf: [
95
+        { required: true, trigger: 'blur' },
96
+        // 其他校验规则
97
+    ]
98
+});
99
+
100
+const columns = ref([
101
+    {
102
+        prop: "ActionColumn",
103
+        label: "操作",
104
+        width: "120px",
105
+        align: "center",
106
+        render: (scope) => {
107
+            return <div>
108
+                <pro-button id="deleteId" onClick={() => deleteRows(scope)} icon={h(DeleteOutlined)}>删除</pro-button>
109
+            </div>
110
+        }
111
+    },
112
+    {
113
+        prop: "key", label: "层级编号", align: "center", width: "120px", editing: true,
114
+        rules: [
115
+            { required: true, message: '请输入层级编号', trigger: 'blur' },
116
+            {
117
+                validator: (rule, value, callback) => {
118
+                    if (!isNumber(value)) {
119
+                        return Promise.reject(new Error('层级编号请填写大于0的整数'));
120
+                    } else {
121
+                        return Promise.resolve();
122
+
123
+                    }
124
+                }
125
+            }
126
+        ]
127
+
128
+    },
129
+    { prop: "name", label: "层级名称", align: "center", width: "120px", editing: true },
130
+    {
131
+        prop: "brf", label: "层级功能描述", align: "center", width: "240px", editing: true,
132
+        rules: [
133
+            { required: true, message: '请输入层级功能描述', trigger: 'blur' }
134
+        ]
135
+    },
136
+]);
137
+
138
+function isNumber (value) {
139
+    // 判断是否为数字、整数、大于0
140
+    return /^\d+(\.\d+)?$/.test(value) && /^\d+$/.test(value) && value > 0;
141
+}
142
+function addRows () {
143
+    store.dispatch("DepartLevel/addDepartLevelInfoData");
144
+}
145
+
146
+function deleteRows2 (scope) {
147
+    console.log('wyq------deleteRows1', scope);
148
+    console.log('wyq------deleteRows2', tableRef.value.getChecked());
149
+    console.log('wyq------dialogData', dialogData.value.departLevelInfoData.records);
150
+
151
+
152
+    dialogData.value.departLevelInfoData.records = dialogData.value.departLevelInfoData.records.filter(item => !tableRef.value.getChecked().includes(item));
153
+
154
+    // tableRef.value.getChecked().forEach(item => {
155
+    //     console.log('wyq------deleteRows3', item.no);
156
+
157
+    //     dialogData.value.departLevelInfoData.records = dialogData.value.departLevelInfoData.records.filter(item1 => item1.no !== item.no);
158
+
159
+    // });
160
+    console.log('wyq------dialogData', dialogData.value.departLevelInfoData.records);
161
+
162
+
163
+}
164
+
165
+
166
+function deleteRows (scope) {
167
+    Modal.confirm({
168
+        title: '删除确认',
169
+        content: '确认删除选中的记录',
170
+        cancelText: '取消',
171
+        onOk () {
172
+            store.dispatch('DepartLevel/deleteDepartLevelInfoData', { ...scope });
173
+        }
174
+    });
175
+}
176
+
177
+function save () {
178
+    console.log('wyqq------save', dialogData.value);
179
+    console.log('wyq------调用addDataDemo11');
180
+    emit('addDataDemo');
181
+    //this.$emit('addDataDemo');
182
+    // 表单校验成功
183
+    formRef.value.getOrignRef().validate().then(() => {
184
+        // 保存数据
185
+        store.dispatch('DepartLevel/saveDepartLevelInfoData', {
186
+            closeMethod: () => { emit("close:modal") }
187
+        });
188
+    }).catch((error) => {
189
+        //console.log('error', error);
190
+        //console.log('error', error.errorFields[0].errors[0]);
191
+        message.error('提交失败:' + error.errorFields[0].errors[0]);
192
+    });
193
+
194
+}
195
+</script>

+ 251
- 0
ant-design-pro-vue3/src/views/depart/departLevel/Test.vue 查看文件

@@ -0,0 +1,251 @@
1
+<template>
2
+    <div style="height: 535px; border: 1px solid #ccc;">
3
+        <pro-layout3 direction="horizontal" :initialRatio=0.21 :firstTitle="'机构树面板'">
4
+            <!-- <template #first-title>
5
+                <div>nihao</div>
6
+            </template> -->
7
+            <template #first>
8
+                <div style="background-color: #e0e0e0; padding: 0px; white-space: nowrap;">
9
+                    <DepartPanel v-model:brNos="formData.brNos" v-model:relationNo="formData.relationNo"
10
+                        @getNodes="getBrNodes">
11
+                    </DepartPanel>
12
+                </div>
13
+            </template>
14
+            <template #second>
15
+                <pro-layout3 direction="vertical" :initialRatio=0.615 :firstTitle="'报表查询'">
16
+                    <!-- <template #first-title>
17
+                        <div>报表查询</div>
18
+                    </template> -->
19
+                    <template #first>
20
+                        <div style="background-color: #fff; padding: 5px;">
21
+                            <pro-form label-width="80px">
22
+                                <pro-form-grid colNum="2" :style="{ width: '900px' }">
23
+                                    <!-- :style="{ width: '300px' }" -->
24
+
25
+                                    <pro-date-picker :formItemProps="{ label: '制表日期1', prop: 'rptDate' }"
26
+                                        v-model:value="formData.rptDate" placeholder="请选择制表日期" :allowClear="true">
27
+                                    </pro-date-picker>
28
+                                    <pro-select3 :formItemProps="{ label: '周期类型', prop: 'cycType' }"
29
+                                        v-model:value="formData.cycType" @onSelect="onSelectCycType"
30
+                                        placeholder="请选择周期类型" :allowClear="true" selectType="periodic">
31
+                                    </pro-select3>
32
+                                    <pro-select3 :formItemProps="{ label: '币种', prop: 'curNo' }"
33
+                                        v-model:value="formData.curNo" @onSelect="onSelectCur" placeholder="请选择币种级别"
34
+                                        :allowClear="true" selectType="curr">
35
+                                    </pro-select3>
36
+                                    <pro-select-tree3 :formItemProps="{ label: '账套', prop: 'sobNo' }" treeType="sobTree"
37
+                                        v-model:value="formData.sobNo" v-model:stddNo="formData.stddNo"
38
+                                        :brNos="formData.brNos" :showCheckbox="false" :multiple="false" mode="default">
39
+                                    </pro-select-tree3>
40
+                                    <pro-select3 :formItemProps="{ label: '损益上划', prop: 'shFlag' }"
41
+                                        v-model:value="formData.shFlag" @onSelect="onSelectShFlag"
42
+                                        placeholder="请选择损益上划类型" :allowClear="true" tableName="gl_rpt_def"
43
+                                        colName="sh_flag">
44
+                                    </pro-select3>
45
+                                    <pro-select3 :formItemProps="{ label: '报表调整类型', prop: 'adjType' }"
46
+                                        v-model:value="formData.adjType" @onSelect="onSelectAdjType"
47
+                                        placeholder="请选择报表调整类型" :allowClear="true" tableName="gls_rpt_def"
48
+                                        colName="adj_type">
49
+                                    </pro-select3>
50
+                                    <pro-select3 :formItemProps="{ label: '科目级别', prop: 'accLvl' }"
51
+                                        v-model:value="formData.accLvl" placeholder="请选择科目级别" :allowClear="true"
52
+                                        selectType="accLvl" :sobNo="formData.sobNo">
53
+                                    </pro-select3>
54
+                                    <pro-select3 :formItemProps="{ label: '零余额是否打印', prop: 'zeroPrintYn' }"
55
+                                        v-model:value="formData.zeroPrintYn" placeholder="请选择零余额是否打印" :allowClear="true"
56
+                                        tableName="gl_rpt_def" colName="zero_print_yn">
57
+                                    </pro-select3>
58
+                                    <pro-select3 v-show="false" :formItemProps="{ label: '汇率类型', prop: 'exrateType' }"
59
+                                        v-model:value="formData.exrateType" placeholder="请选择汇率类型" :allowClear="true"
60
+                                        tableName="exchange_rate_info" colName="exrate_type">
61
+                                    </pro-select3>
62
+                                    <pro-form-item>
63
+                                        <pro-button id="queryBtn" @click="search2"
64
+                                            :icon="h(SearchOutlined)">查询</pro-button>
65
+                                    </pro-form-item>
66
+                                </pro-form-grid>
67
+                            </pro-form>
68
+                        </div>
69
+                    </template>
70
+                    <template #second>
71
+                        <div style="background-color: #e0e0e0; padding: 0px;">
72
+                            <!-- 结果区 -->
73
+                            <ResultPanel ref="resultPanel"></ResultPanel>
74
+                        </div>
75
+                    </template>
76
+                </pro-layout3>
77
+            </template>
78
+        </pro-layout3>
79
+    </div>
80
+</template>
81
+
82
+<!-- <template>
83
+    <div style="height: 496px; border: 1px solid #ccc;">
84
+        <pro-layout3 direction="horizontal" :initialRatio="initialRatio">
85
+            <template #first>
86
+                <pro-layout3 direction="vertical" :initialRatio="initialRatio" firstTitle="'第一个面板标题'"
87
+                    secondTitle="'第二个面板标题'">
88
+                    <template #first>
89
+                        <div style="background-color: #e0e0e0; padding: 20px;">
90
+                            右侧上半区域<br>
91
+                            右侧上半区域<br>
92
+                            右侧上半区域<br>
93
+                            右侧上半区域<br>
94
+                            右侧上半区域<br>
95
+                            右侧上半区域<br>
96
+                            右侧上半区域<br>
97
+                            右侧上半区域<br>
98
+                            右侧上半区域<br>
99
+                            右侧上半区域<br>
100
+                            右侧上半区域<br>
101
+                            右侧上半区域<br>
102
+                        </div>
103
+                    </template>
104
+                    <template #second>
105
+                        <div style="background-color: #d0d0d0; padding: 20px;">
106
+                            右侧下半区域<br>
107
+                            右侧下半区域<br>
108
+                            右侧下半区域<br>
109
+                            右侧下半区域<br>
110
+                            右侧下半区域<br>
111
+                            右侧下半区域<br>
112
+                            右侧下半区域<br>
113
+                            右侧下半区域<br>
114
+                            右侧下半区域<br>
115
+                            右侧下半区域<br>
116
+                            右侧下半区域<br>
117
+                        </div>
118
+                    </template>
119
+                </pro-layout3>
120
+            </template>
121
+            <template #second>
122
+                <pro-layout3 direction="vertical" :initialRatio="initialRatio" firstTitle="'第一个面板标题'"
123
+                    secondTitle="'第二个面板标题'">
124
+                    <template #first>
125
+                        <div style="background-color: #e0e0e0; padding: 20px;">
126
+                            右侧上半区域<br>
127
+                            右侧上半区域<br>
128
+                            右侧上半区域<br>
129
+                            右侧上半区域<br>
130
+                            右侧上半区域<br>
131
+                            右侧上半区域<br>
132
+                            右侧上半区域<br>
133
+                            右侧上半区域<br>
134
+                            右侧上半区域<br>
135
+                            右侧上半区域<br>
136
+                            右侧上半区域<br>
137
+                            右侧上半区域<br>
138
+
139
+                        </div>
140
+                    </template>
141
+                    <template #second>
142
+                        右侧下半区域<br>
143
+                        右侧下半区域<br>
144
+                        右侧下半区域<br>
145
+                        右侧下半区域<br>
146
+                        右侧下半区域<br>
147
+                        右侧下半区域<br>
148
+                        右侧下半区域<br>
149
+                        右侧下半区域<br>
150
+                        右侧下半区域<br>
151
+                        右侧下半区域<br>
152
+                        右侧下半区域<br>
153
+                    </template>
154
+                </pro-layout3>
155
+            </template>
156
+        </pro-layout3>
157
+    </div>
158
+</template> -->
159
+
160
+<script setup lang="jsx">
161
+import { message } from "ant-design-vue";
162
+import { ref, reactive, nextTick, onMounted, onUnmounted, h, } from 'vue';
163
+import { SearchOutlined, RedoOutlined, PlusOutlined, EditOutlined } from "@ant-design/icons-vue";
164
+import DepartPanel from '@/components/ProReport/DepartPanel.vue';
165
+import ResultPanel from '@/components/ProReport/ResultPanel.vue';
166
+const initialRatio = ref(0.5);
167
+const resultPanel = ref(null);
168
+
169
+const formData = ref({
170
+    relationNo: '',
171
+    brNos: [],
172
+    brName: '',
173
+    rptDate: '',
174
+    cycType: '',
175
+    cycTypeName: '',
176
+    curNo: '',
177
+    curName: '',
178
+    stddNo: '',
179
+    sobNo: '',
180
+    shFlag: '',
181
+    shFlagName: '',
182
+    adjType: '',
183
+    adjTypeName: '',
184
+    accLvl: '',
185
+    zeroPrintYn: '',
186
+    exrateType: '',
187
+    isGather: 'N',
188
+    telNo: '',
189
+
190
+    ptabName: ['v_gl_sub_coll_day'],
191
+    tabName: ["gls_gl_sub_tmp_sh_adj_q", "gls_gl_sub_tmp_sh_adj", "gls_gl_sub_tmp_sh_adj_h"],
192
+    reportType: '1',
193
+    rptType: '',
194
+
195
+});
196
+
197
+const onSelectCycType = (value, option) => {
198
+    formData.value.cycTypeName = option.item_name;
199
+}
200
+const onSelectCur = (value, option) => {
201
+    formData.value.curName = option.item_name;
202
+}
203
+const onSelectAdjType = (value, option) => {
204
+    formData.value.adjTypeName = option.item_name;
205
+}
206
+const onSelectShFlag = (value, option) => {
207
+    formData.value.shFlagName = option.item_name;
208
+}
209
+
210
+const getBrNodes = (value, nodes) => {
211
+    console.log('getBrNodes', value, nodes);
212
+    if (nodes.length === 1) {
213
+        formData.value.brName = nodes[0].name;
214
+    } else {
215
+        formData.value.brName = '多机构汇总';
216
+    }
217
+}
218
+
219
+function search () {
220
+    if (resultPanel.value) {
221
+        resultPanel.value.search();
222
+    }
223
+}
224
+
225
+const search2 = () => {
226
+    // 1.机构及汇总关系校验
227
+    if (formData.value.relationNo === '') {
228
+        message.error('请选择汇总关系');
229
+        return;
230
+    }
231
+    if (formData.value.brNos.length === 0) {
232
+        message.error('请选择机构');
233
+        return;
234
+    }
235
+
236
+    // 2.表单校验
237
+    if (formData.value.adjType === '1') {
238
+        //调整前
239
+        ptabName = ['gls_gl_sub_day'];
240
+    } else if (formData.value.adjType === '2') {
241
+        //调整
242
+        ptabName = ['v_gl_sub_adj_day'];
243
+    }
244
+
245
+    if (resultPanel.value) {
246
+        resultPanel.value.search2(formData);
247
+    }
248
+}
249
+
250
+// 查询报表
251
+</script>

+ 364
- 0
ant-design-pro-vue3/src/views/depart/departLevel/TestProSelectTree.vue 查看文件

@@ -0,0 +1,364 @@
1
+<template>
2
+    <div>
3
+        <!-- <pro-input :formItemProps="{ label: '用途:', prop: 'use' }" v-model:value="useYn" placeholder="请输入"
4
+            :allowClear="true">
5
+        </pro-input> -->
6
+
7
+        <a-select ref="selectRef" v-model:value="selectedDisplayValue" :open="isDropdownOpen" @click="handleSelectClick"
8
+            placeholder="请选择" :allowClear="true" @clear="handleClear" style="width: 500px">
9
+            <template #dropdownRender>
10
+                <div ref="dropdownRef" class="dropdown-content">
11
+                    <!-- 搜索框 -->
12
+                    <a-input v-model:value="searchValue" placeholder="搜索..." @input="handleSearch" />
13
+                    <!-- 搜索结果列表 -->
14
+                    <div v-if="searchResultList.length">
15
+                        <a-list :data-source="searchResultList" bordered @itemClick="onItemClick">
16
+                            <a-list-item v-for="item in searchResultList" :key="item.key" @click="onItemClick(item)">
17
+                                {{ item.title }}
18
+                            </a-list-item>
19
+                        </a-list>
20
+                    </div>
21
+                    <!-- 树结构 -->
22
+                    <a-tree v-else :tree-data="filteredTreeData" :checkable="true" v-model:expandedKeys="expandedKeys"
23
+                        v-model:selectedKeys="selectedKeys" v-model:checkedKeys="checkedKeys" @select="onSelect"
24
+                        @expand="onExpand" @check="onCheck" />
25
+                </div>
26
+            </template>
27
+        </a-select>
28
+        <pro-input :formItemProps="{ label: '用途:', prop: 'use' }" v-model:value="useYn" placeholder="请输入"
29
+            :allowClear="true">
30
+        </pro-input>
31
+    </div>
32
+    <button @click="changeRelationNo">改变机构汇总关系 relationNo</button>
33
+    <pro-tree2 v-model:relationNo="relationNo" v-model:txBrNo="txBrNo" treeType="deptTree" :checkable="true"
34
+        v-model:checkedKeys="testCheckedKeys" v-model:expandedKeys="testExpandedKeys" @onCheck="onCheck1"></pro-tree2>
35
+    <div>1父组件选中机构{{ txBrNo }}</div>
36
+    <pro-tree2 v-model:txBrNo="txBrNo" v-model:sobNo="sobNo" treeType="sobTree" :checkable="true"></pro-tree2>
37
+    <div>1父组件选中账套{{ sobNo }}</div>
38
+
39
+
40
+
41
+
42
+
43
+    <!-- <pro-select-tree2 treeType="sobTree"></pro-select-tree2>
44
+    <pro-select-tree2 treeType="deptTree"></pro-select-tree2> -->
45
+
46
+    <!-- <ProSelectTree2 treeType="sobTree"></ProSelectTree2> -->
47
+
48
+    <!-- <pro-tree3 :treeData="treeData" v-treeType="sobTree"model:checkedKeys="testCheckedKeys"
49
+        v-model:expandedKeys="testExpandedKeys"></pro-tree3>
50
+    <div>父组件选中{{ testCheckedKeys }}</div>
51
+    <div>父组件展开{{ testExpandedKeys }}</div> -->
52
+</template>
53
+
54
+<script setup>
55
+import { ref, onMounted, onBeforeUnmount, onUnmounted, watch } from 'vue';
56
+
57
+const relationNo = ref('AAAAAA');
58
+// 改变机构树 relationNo 的函数
59
+const testCheckedKeys = ref(['1-1']);
60
+const testExpandedKeys = ref(['1']);
61
+const changeRelationNo = () => {
62
+    if (relationNo.value === 'AAAAAA') {
63
+        relationNo.value = 'BBBBBB';
64
+        testCheckedKeys.value = ['2-1'];
65
+        testExpandedKeys.value = ['2'];
66
+    } else {
67
+        relationNo.value = 'AAAAAA';
68
+        testCheckedKeys.value = ['1-1'];
69
+        testExpandedKeys.value = ['1'];
70
+    }
71
+};
72
+
73
+const onCheck1 = (checkedKeys, info) => {
74
+    console.log('wyq---------checkedKeys', checkedKeys, info);
75
+    console.log('wyq---------info', info.node.key);
76
+
77
+}
78
+
79
+const txBrNo = ref('1');
80
+const sobNo = ref('');
81
+// const testCheckedKeys = ref([]);// 已勾选的节点
82
+// testCheckedKeys.value = ['1'];
83
+// const testExpandedKeys = ref(['1']);// 已勾选的节点
84
+
85
+
86
+
87
+// 下拉框功能
88
+// 用于显示在下拉框中的选中值
89
+const selectedDisplayValue = ref('');
90
+// 是否显示下拉框
91
+const isDropdownOpen = ref(false);
92
+// 处理 a-select 清除事件
93
+const handleClear = () => {
94
+    checkedKeys.value = [];
95
+    selectedDisplayValue.value = '';
96
+};
97
+
98
+// 处理选择框点击事件
99
+const handleSelectClick = () => {
100
+    // 清空搜索框
101
+    searchValue.value = '';
102
+    searchResultList.value = [];
103
+    isDropdownOpen.value = true;
104
+};
105
+
106
+// 搜索框功能
107
+// 搜索框的值
108
+const searchValue = ref('');
109
+// 搜索结果列表
110
+const searchResultList = ref([]);
111
+// 监听搜索框的值,过滤列表
112
+watch(searchValue, (value) => {
113
+    if (value) {
114
+        const result = [];
115
+        const traverse = (nodes) => {
116
+            nodes.forEach((node) => {
117
+                if (node.title.includes(value)) {
118
+                    result.push(node);
119
+                }
120
+                if (node.children) {
121
+                    traverse(node.children);
122
+                }
123
+            });
124
+        };
125
+        traverse(treeData);
126
+        searchResultList.value = result;
127
+    } else {
128
+        searchResultList.value = [];
129
+    }
130
+});
131
+
132
+const onItemClick = (item) => {
133
+    //selectedKey.value = item.key; // 记录选中的项
134
+    //expandedKeys.value = [getParentKey(item.key, gData.value)]; // 展开父节点
135
+    //autoExpandParent.value = true; // 自动展开父节点
136
+
137
+    selectedDisplayValue.value = item.title;
138
+    checkedKeys.value = [item.key]; // 勾选当前节点
139
+    // 展开父节点和爷节点
140
+    const parentKeys = getParentKeys(item.key, treeData);
141
+    expandedKeys.value = [...new Set([...expandedKeys.value, ...parentKeys])];
142
+    // 关闭下拉框
143
+    isDropdownOpen.value = false;
144
+
145
+};
146
+
147
+// 获取节点的父节点和爷节点的 key
148
+// 获取节点的父节点和爷节点的 key
149
+const getParentKeys = (key, nodes) => {
150
+    const parentKeys = [];
151
+    // 递归查找目标节点并记录其父节点信息
152
+    const findNode = (currentNodes, parentKey = null, grandParentKey = null) => {
153
+        for (const node of currentNodes) {
154
+            if (node.key === key) {
155
+                // 如果存在父节点,添加到结果数组
156
+                if (parentKey) {
157
+                    parentKeys.push(parentKey);
158
+                }
159
+                // 如果存在爷节点,添加到结果数组
160
+                if (grandParentKey) {
161
+                    parentKeys.push(grandParentKey);
162
+                }
163
+                return;
164
+            }
165
+            if (node.children) {
166
+                // 递归调用,更新父节点和爷节点信息
167
+                findNode(node.children, node.key, parentKey);
168
+            }
169
+        }
170
+    };
171
+    findNode(nodes);
172
+    return parentKeys;
173
+};
174
+
175
+
176
+// 树功能
177
+// 选中的树节点的键
178
+const expandedKeys = ref([]);// 已展开的节点
179
+const selectedKeys = ref([]);// 已选中的节点
180
+const checkedKeys = ref([]);// 已勾选的节点
181
+
182
+// 示例树结构数据
183
+const treeData = [
184
+    {
185
+        title: 'node 1',
186
+        key: '1',
187
+        children: [
188
+            {
189
+                title: 'child node 1',
190
+                key: '1-1'
191
+            },
192
+            {
193
+                title: 'child node 2',
194
+                key: '1-2'
195
+            }
196
+        ]
197
+    },
198
+    {
199
+        title: 'node 2',
200
+        key: '2',
201
+        children: [
202
+            {
203
+                title: 'child node 1',
204
+                key: '2-1'
205
+            },
206
+            {
207
+                title: 'child node 2',
208
+                key: '2-2'
209
+            },
210
+            {
211
+                title: 'child node 3',
212
+                key: '2-3'
213
+            },
214
+            {
215
+                title: 'child node 4',
216
+                key: '2-4'
217
+            },
218
+            {
219
+                title: 'child node 5',
220
+                key: '2-5'
221
+            }, {
222
+                title: 'child node 6',
223
+                key: '2-6'
224
+            }, {
225
+                title: 'child node 7',
226
+                key: '2-7'
227
+            }, {
228
+                title: 'child node 8',
229
+                key: '2-8'
230
+            }, {
231
+                title: 'child node 9',
232
+                key: '2-9'
233
+            }, {
234
+                title: 'child node 10',
235
+                key: '2-10'
236
+            }, {
237
+                title: 'child node 11',
238
+                key: '2-11'
239
+            }, {
240
+                title: 'child node 12',
241
+                key: '2-12'
242
+            }
243
+        ]
244
+    }
245
+];
246
+// 过滤后的树结构数据
247
+const filteredTreeData = ref([...treeData]);
248
+
249
+const useYn = ref('');
250
+
251
+// 处理搜索框输入
252
+const handleSearch = () => {
253
+    if (searchValue.value) {
254
+        // filteredTreeData.value = filterTreeData(treeData, searchValue.value);
255
+    } else {
256
+        //filteredTreeData.value = [...treeData];
257
+    }
258
+};
259
+
260
+// 递归过滤树结构数据
261
+const filterTreeData = (data, keyword) => {
262
+    return data.filter(item => {
263
+        if (item.title.includes(keyword)) {
264
+            return true;
265
+        }
266
+        if (item.children && item.children.length > 0) {
267
+            const filteredChildren = filterTreeData(item.children, keyword);
268
+            if (filteredChildren.length > 0) {
269
+                return { ...item, children: filteredChildren };
270
+            }
271
+        }
272
+        return false;
273
+    });
274
+};
275
+
276
+// 点击复选框触发
277
+const onCheck = (checkedKeys, info) => {
278
+    console.log('wyq---------checkedKeys', checkedKeys);
279
+    checkedKeys.value = checkedKeys;
280
+    updateSelectedDisplayValue();
281
+};
282
+
283
+// 点击树节点触发
284
+function onSelect (selectedKeys, info) {
285
+    console.log('wyq---------selectedKeys', selectedKeys);
286
+}
287
+// 展开/收起节点时触发
288
+function onExpand (expandedKeys, info) {
289
+    console.log('wyq---------expandedKeys', expandedKeys);
290
+}
291
+
292
+
293
+
294
+// 更新显示在下拉框中的选中值
295
+const updateSelectedDisplayValue = () => {
296
+    const selectedTitles = [];
297
+    checkedKeys.value.forEach((key) => {
298
+        const findTitle = (nodes) => {
299
+            for (const node of nodes) {
300
+                if (node.key === key) {
301
+                    return node.title;
302
+                }
303
+                if (node.children) {
304
+                    const childTitle = findTitle(node.children);
305
+                    if (childTitle) {
306
+                        return childTitle;
307
+                    }
308
+                }
309
+            }
310
+            return null;
311
+        };
312
+        const title = findTitle(treeData);
313
+        if (title) {
314
+            selectedTitles.push(title);
315
+        }
316
+    });
317
+    selectedDisplayValue.value = selectedTitles.join(', ');
318
+};
319
+
320
+
321
+
322
+// 处理下拉框展开状态变化
323
+const handleOpenChange = (open) => {
324
+    isDropdownOpen.value = open;
325
+};
326
+
327
+// 点击其他区域隐藏下拉框
328
+const selectRef = ref(null);
329
+const dropdownRef = ref(null);
330
+const handleDocumentClick = (event) => {
331
+    if (
332
+        selectRef.value &&
333
+        dropdownRef.value &&
334
+        !selectRef.value.$el.contains(event.target) &&
335
+        !dropdownRef.value.contains(event.target)
336
+    ) {
337
+        isDropdownOpen.value = false;
338
+    }
339
+};
340
+onMounted(() => {
341
+    document.addEventListener('click', handleDocumentClick);
342
+});
343
+
344
+onBeforeUnmount(() => {
345
+    document.removeEventListener('click', handleDocumentClick);
346
+});
347
+</script>
348
+
349
+<style scoped>
350
+/* .dropdown-content {
351
+    padding: 8px;
352
+} */
353
+
354
+.dropdown-content {
355
+    /* 设置固定的高度和宽度 */
356
+    max-height: 300px;
357
+    width: 500px;
358
+    /* 设置溢出时显示滚动条 */
359
+    overflow: auto;
360
+    /* 可以根据需要添加其他样式 */
361
+    border: 1px solid #ccc;
362
+    padding: 8px;
363
+}
364
+</style>

+ 180
- 0
ant-design-pro-vue3/src/views/depart/departLevel/TestProSelectTree3.vue 查看文件

@@ -0,0 +1,180 @@
1
+<template>
2
+    <h2>测试下拉树组件-vue3</h2>
3
+
4
+
5
+    <pro-button id="queryBtn" @click="onClick">点击</pro-button>
6
+    <pro-button id="queryBtn" @click="onClick1">点击改变汇总关系</pro-button>
7
+    <div>汇总:{{ relationNo }}</div>
8
+
9
+    <div>机构:{{ brNos }}</div>
10
+    <div>准则:{{ stddNo }}</div>
11
+    <div>账套:{{ sobNo }}</div>
12
+    <div>科目:{{ accNos }}</div>
13
+    <!-- <div>
14
+        <pro-tree3 v-model:value="brNos" treeType="deptTree" :showCheckbox="true" :isWithoutDsc="true"></pro-tree3>
15
+    </div> -->
16
+    <pro-form label-width="120px">
17
+        <!-- <pro-form-grid colNum="2"> -->
18
+        <pro-form-grid>
19
+
20
+            <!-- 表单-->
21
+            <!-- <pro-select3 :formItemProps="{ label: '汇总关系', prop: 'relationNo' }" v-model:value="formData.relationNo"
22
+                placeholder="请选择汇总关系" :allowClear="true" selectType="relationNo" pageInterfaceNo="zzsearch_01_01_02">
23
+            </pro-select3>
24
+
25
+            <pro-select-tree3 :formItemProps="{ label: '机构', prop: 'brNo' }" treeType="deptTree"
26
+                v-model:value="formData.brNo" :relationNo="formData.relationNo" :showCheckbox="false" :isAsync="false"
27
+                :isWithoutDsc="true" @getNodes="getNodes">
28
+            </pro-select-tree3>
29
+
30
+            <pro-select3 :formItemProps="{ label: '交易系统', prop: 'sysNo' }" v-model:value="formData.sysNo"
31
+                placeholder="请选择交易系统" :allowClear="true" selectType="perSys">
32
+            </pro-select3>
33
+
34
+            <pro-select3 :formItemProps="{ label: '币种', prop: 'curNo' }" v-model:value="formData.curNo"
35
+                placeholder="请选择币种" :allowClear="true" selectType="curr">
36
+            </pro-select3> -->
37
+
38
+            <pro-select-tree3 :formItemProps="{ label: '账套', prop: 'sobNo' }" treeType="sobTree"
39
+                v-model:value="formData.sobNo" v-model:stddNo="formData.stddNo" :brNos="formData.brNo"
40
+                :showCheckbox="false" :multiple="false" mode="default">
41
+            </pro-select-tree3>
42
+
43
+            <!-- <pro-select-tree3 :formItemProps="{ label: '科目', prop: 'accNos' }" treeType="sobItemTree"
44
+                v-model:value="formData.accNos" :stddNo="formData.stddNo" :sobNo="formData.sobNo" :showCheckbox="true">
45
+            </pro-select-tree3>
46
+
47
+            <pro-select3 :formItemProps="{ label: '科目级别', prop: 'accLvl' }" v-model:value="formData.accLvl"
48
+                placeholder="请选择科目级别" :allowClear="true" selectType="accLvl" :sobNo="formData.sobNo">
49
+            </pro-select3> -->
50
+
51
+
52
+
53
+            <!-- <pro-select3 :formItemProps="{ label: '启用标志', prop: 'useYn' }" v-model:value="useYn" placeholder="请选择启用标志"
54
+                :allowClear="true" tableName="com_usertype_info" colName="use_yn">
55
+            </pro-select3>
56
+            <pro-select3 :formItemProps="{ label: '科目级别', prop: 'accLvl' }" v-model:value="accLvl" placeholder="请选择科目级别"
57
+                :allowClear="true" selectType="accLvl" sobNo="10">
58
+            </pro-select3>
59
+
60
+            <pro-select3 :formItemProps="{ label: '汇总关系', prop: 'relationNo' }" v-model:value="relationNo"
61
+                placeholder="请选择汇总关系" :allowClear="true" selectType="relationNo" pageInterfaceNo="zzsearch_01_01_02">
62
+            </pro-select3>
63
+
64
+            <pro-select3 :formItemProps="{ label: '币种', prop: 'curNo' }" v-model:value="curNo" placeholder="请选择币种级别"
65
+                :allowClear="true" selectType="curr">
66
+            </pro-select3> -->
67
+
68
+            <!-- <pro-select3 :formItemProps="{ label: '系统', prop: 'sysNo' }" v-model:value="sysNo" placeholder="请选择系统级别"
69
+                :allowClear="true" selectType="perSys">
70
+            </pro-select3> -->
71
+            <!-- <pro-select-tree3 :formItemProps="{ label: '机构', prop: 'brNos' }" treeType="deptTree" v-model:value="brNos"
72
+                :relationNo="relationNo" :showCheckbox="true" :isAsync="false" :isWithoutDsc="true"
73
+                @getNodes="getNodes">
74
+            </pro-select-tree3> -->
75
+
76
+            <!-- <pro-select-tree3 :formItemProps="{ label: '账套', prop: 'sobNo' }" treeType="sobTree" v-model:value="sobNo"
77
+                v-model:stddNo="stddNo" :brNos="brNos" :showCheckbox="false" :multiple="false">
78
+            </pro-select-tree3> -->
79
+
80
+            <!-- <pro-select-tree3 :formItemProps="{ label: '科目', prop: 'accNos' }" treeType="sobItemTree"
81
+                v-model:value="accNos" :stddNo="stddNo" :sobNo="sobNo" :showCheckbox="true">
82
+            </pro-select-tree3> -->
83
+
84
+            <!-- <pro-select-tree3 :formItemProps="{ label: '异步机构', prop: 'asyncbrNos' }" treeType="deptTree"
85
+                v-model:value="asyncbrNos" :relationNo="relationNo" :showCheckbox="true" :isAsync="true">
86
+            </pro-select-tree3> -->
87
+
88
+            <!-- <pro-select-tree3 :formItemProps="{ label: '其他', prop: 'accNos' }" v-model:value="areaNo"
89
+                :treeData="areaTreeData" :showCheckbox="false">
90
+            </pro-select-tree3> -->
91
+        </pro-form-grid>
92
+    </pro-form>
93
+
94
+    <!--     
95
+    <pro-select-tree3 treeType="deptTree" v-model:value="brNos" :relationNo="relationNo"
96
+        :showCheckbox="true"></pro-select-tree3> -->
97
+    <!-- <pro-select-tree3 treeType="sobTree" v-model:value="sobNo" :brNos="brNos" :showCheckbox="true"></pro-select-tree3> -->
98
+
99
+    <!-- <pro-select-tree3 treeType="sobItemTree" v-model:value="accNos" :showCheckbox="true"></pro-select-tree3> -->
100
+
101
+
102
+
103
+
104
+
105
+    <!-- <pro-tree3 :treeData="treeData" v-model:selectedKeys="selectedKeys" treeType="sobTree"></pro-tree3>
106
+    <pro-tree3 treeType="deptTree" v-model:brNos="brNos" v-model:brKeys="brKeys" :showCheckbox="true"></pro-tree3>
107
+    <div>1选中的机构外部:{{ brKeys }}</div>
108
+    <div>2选中的机构内部:{{ brNos }}</div>
109
+
110
+    <pro-tree3 treeType="sobTree" v-model:brNos="brNos"></pro-tree3> -->
111
+
112
+    <!-- <pro-tree3 treeType="sobItemTree" checkable></pro-tree3> -->
113
+
114
+    <!-- <pro-form label-width="120px">
115
+        <pro-form-grid style="width: 1000px" colNum="2">
116
+            <pro-select-tree3 :formItemProps="{ label: '机构', prop: 'brNos' }" checkable treeType="deptTree"
117
+                @expand="expand"></pro-select-tree3>
118
+            <pro-select-tree3 :formItemProps="{ label: '账套', prop: 'sobNo' }" treeType="sobTree"></pro-select-tree3>
119
+        </pro-form-grid>
120
+    </pro-form>
121
+    <button @click="fetchData">点击</button>
122
+    <div>返回的数据: {{ treeData }}</div> -->
123
+</template>
124
+<script setup>
125
+import { ref, defineProps, defineExpose, onMounted, onBeforeUnmount, watch, nextTick, provide, defineEmits } from 'vue';
126
+
127
+// 表单字段的初始值
128
+const formData = ref({
129
+    relationNo: '',
130
+    brNo: [],
131
+    sysNo: "",
132
+    curNo: "",
133
+    stddNo: "",
134
+    sobNo: '',
135
+    accNos: [],
136
+    accLvl: ""
137
+});
138
+
139
+
140
+const relationNo = ref('');
141
+
142
+// const relationNo = ref('AAAAAA');
143
+function onClick1 () {
144
+    // if (relationNo.value === 'AAAAAA') {
145
+    //     relationNo.value = 'BBBBBB';
146
+    // } else {
147
+    //     relationNo.value = 'AAAAAA';
148
+    // }
149
+}
150
+// const brNos = ref(['1']);
151
+const asyncbrNos = ref(['1']);
152
+
153
+// const brNos = ref(['1']);
154
+const brNos = ref([]);
155
+
156
+function getNodes (value, nodes) {
157
+    console.log('父组件-getNode:', value, nodes);
158
+}
159
+function onClick () {
160
+    if (brNos.value[0] === '1' || brNos.value[0] === '200000') {
161
+        brNos.value = ['800000'];
162
+    } else {
163
+        brNos.value = ['200000'];
164
+    }
165
+}
166
+const stddNo = ref('');
167
+const sobNo = ref([]);
168
+const accNos = ref([]);
169
+
170
+const curNo = ref('');
171
+const useYn = ref('');
172
+const accLvl = ref('');
173
+const sysNo = ref('');
174
+
175
+
176
+
177
+const areaNo = ref(['12']);
178
+const areaTreeData = ref([{ "no": "2", "stdd_no": "2", "sts": "1", "acc_cod_rules_bw": "21", "use_yn": "Y", "name": "新会计准则-1", "pid": "2@", "id": "2@", "show_seqn": "20", "acc_cod_rules_bn": "21", "children": [{ "default_yn": "N", "no": "2", "stdd_no": "12", "sts": "1", "acc_cod_rules_bw": "4/2/2", "use_yn": "Y", "name": "非默认账套-1", "pid": "2@", "id": "12", "show_seqn": "21", "acc_cod_rules_bn": "4/2/2/2", "children": [] }, { "default_yn": "Y", "no": "2", "stdd_no": "10", "sts": "1", "acc_cod_rules_bw": "4/2/2", "use_yn": "Y", "name": "默认账套-1", "pid": "2@", "id": "10", "show_seqn": "22", "acc_cod_rules_bn": "4/2/2/2", "children": [] }] }]);
179
+
180
+</script>

+ 5
- 0
ant-design-pro-vue3/src/views/depart/departLevel/TestProTree3.vue 查看文件

@@ -0,0 +1,5 @@
1
+<template>
2
+    <h2>测试树组件-vue3</h2>
3
+    <div>
4
+    </div>
5
+</template>

+ 8
- 0
ant-design-pro-vue3/src/views/depart/departLevel/YwzkbReport.vue 查看文件

@@ -0,0 +1,8 @@
1
+<template>
2
+    <ReportComponent></ReportComponent>
3
+</template>
4
+<script setup>
5
+
6
+</script>
7
+
8
+<style scoped></style>

+ 311
- 0
ant-design-pro-vue3/src/views/depart/departLevel/models/DepartLevel.store copy.ts 查看文件

@@ -0,0 +1,311 @@
1
+import { clear, Console } from 'console';
2
+import * as service from '../services';
3
+import * as util from "@/utils/index.js";
4
+import { title } from 'process';
5
+export default {
6
+    namespaced: true,
7
+    state: {
8
+        // 机构层级定义-列表查询数据
9
+        departLevelDefData: {
10
+            current: 1,
11
+            pageSize: 0,
12
+            total: 0,
13
+            records: []
14
+        },
15
+        // 机构层级基本-列表查询数据
16
+        departLevelInfoData: {
17
+            current: 1,
18
+            pageSize: 0,
19
+            total: 0,
20
+            records: []
21
+        },
22
+        //新增或修改的数据
23
+        dialogData: {},
24
+
25
+
26
+        ////////////////////////////////////////
27
+
28
+        // 查询页
29
+        departLevelData: {
30
+            current: 1,
31
+            pageSize: 0,
32
+            total: 0,
33
+            records: []
34
+        },
35
+        // 表格数据
36
+        queryParam: {},
37
+        // list页面查询条件
38
+        insertOrModify: 1,
39
+        //新增修改标志:1-新增,2-修改
40
+
41
+        //新增修改
42
+        formData: {},
43
+        //表单数据
44
+        title: '',
45
+        // modal页面标题
46
+        conversion: {
47
+            current: 1,
48
+            pageSize: 0,
49
+            total: 0,
50
+            records: []
51
+        },
52
+        //折算币种
53
+        // 启用数据
54
+        useNo: "",
55
+        validateFlag: true,
56
+        searchCurrency: [],
57
+        // 新增修改页面折算后币种查询条件
58
+        toCurNo: [],
59
+
60
+
61
+        departLevelInfo: {
62
+            current: 1,
63
+            pageSize: 0,
64
+            total: 0,
65
+            records: []
66
+        }
67
+    },
68
+    actions: {
69
+        // 机构层级定义列表查询
70
+        async queryDepartLevelDefData({ commit }, payload) {
71
+            // 1.页面查询条件
72
+            const params = {
73
+                ...payload.values
74
+            };
75
+            // 2.调用接口 获取数据
76
+            const resp = await service.queryDepartLevelDefData(params);
77
+            // 3.更新state数据
78
+            commit("update", {
79
+                departLevelDefData: {
80
+                    current: resp.pageNo,
81
+                    pageSize: resp.pageSize,
82
+                    total: resp.total,
83
+                    records: resp.rows
84
+                }
85
+            });
86
+        },
87
+
88
+        // 新增或修改
89
+        async addOrModify({ commit, state }, payload) {
90
+            // 清理下数据
91
+            console.log("wyq", payload);
92
+            // commit("clearDepartLevelInfo");
93
+            const data = await service.searchCurrency({
94
+                use_yn: "Y"
95
+            });
96
+            if (payload == undefined) {
97
+                // 新增
98
+                const tableKey = await service.getTabKeyRule({
99
+                    tabName: 'currency'
100
+                });
101
+                commit("update", {
102
+                    insertOrModify: 1,
103
+                    //title: '新增',
104
+                    formData: {
105
+                        key: tableKey.value
106
+                    },
107
+                    useNo: "",
108
+                    searchCurrency: data.test,
109
+                    validateFlag: true,
110
+                    toCurNo: ''
111
+                });
112
+            } else {
113
+                console.log("wyq:addOrModifyData 前", state.dialogData);
114
+                // 修改页面
115
+                // 1.查询层级信息
116
+                const resp = await service.queryDepartLevelInfoData({
117
+                    no: payload.no
118
+                });
119
+                //resp.rows.forEach(item => item.from_cur_no = payload.name);
120
+                commit("update",
121
+                    {
122
+                        //title: '修改',
123
+                        dialogData: payload,
124
+                        departLevelInfoData: {
125
+                            total: resp.total,
126
+                            records: resp.rows
127
+                        },
128
+
129
+
130
+                        insertOrModify: 2,
131
+                        formData: payload,
132
+                        useNo: payload.no,
133
+                        searchCurrency: data.test,
134
+                        validateFlag: true,
135
+                        toCurNo: payload.no
136
+                    });
137
+                console.log("wyq:addOrModifyData 后", state.dialogData);
138
+
139
+            }
140
+        },
141
+
142
+        cleanData({
143
+            commit,
144
+            state
145
+        }) {
146
+            commit("clearDepartLevelInfo");
147
+        },
148
+
149
+
150
+        // 新增一行
151
+        async addRows({
152
+            commit,
153
+            state
154
+        }) {
155
+            const resp = state.departLevelInfoData;
156
+            resp.records.push({
157
+                rowsId: Date.now(),
158
+                key: '123',
159
+                name: '321',
160
+                use_yn: "Y"
161
+            });
162
+            // 总行数加1
163
+            resp.total++;
164
+            commit("update", {
165
+                departLevelInfoData: {
166
+                    total: resp.total,
167
+                    records: resp.records
168
+                }
169
+            });
170
+        },
171
+
172
+        // 删除一行
173
+        async deleteRows({
174
+            commit,
175
+            state
176
+        }, payload) {
177
+            const resp = state.departLevelInfoData;
178
+            if (payload.index) {
179
+                resp.records.splice(payload.index, 1);
180
+            }
181
+            // 总行数加1
182
+            resp.total--;
183
+            commit("update", {
184
+                departLevelInfoData: {
185
+                    total: resp.total,
186
+                    records: resp.records
187
+                }
188
+            });
189
+        },
190
+        // 保存
191
+        async save({
192
+            commit,
193
+            state
194
+        }, payload) {
195
+            // const data = state.formData;
196
+            // if (state.insertOrModify == 1) {
197
+            //     // 新增
198
+            //     const tableKey = await service.getTabKeyRule({
199
+            //         tabName: 'currency'
200
+            //     });
201
+            //     data.key = tableKey.value;
202
+            //     const resp = await service.addDepartLevelDefData(data);
203
+            //     if (resp.code == 0) {
204
+            //         commit("update", {
205
+            //             title: '新增',
206
+            //             dialogData: {},
207
+            //             insertOrModify: 1,
208
+            //             formData: {},
209
+            //             useNo: "",
210
+            //             searchCurrency: [],
211
+            //             validateFlag: true,
212
+            //             toCurNo: ''
213
+            //         });
214
+            //         util.successMessage("新增成功");
215
+            //     } else {
216
+            //         util.errorMessage("新增失败");
217
+            //     }
218
+            // } else {
219
+            //     // 修改
220
+            //     const resp = await service.modifyDepartLevelDefData(data);
221
+            //     if (resp.code == 0) {
222
+            //         commit("update", {
223
+            //             title: '修改',
224
+            //             dialogData: {},
225
+            //             insertOrModify: 1,
226
+            //             formData: {},
227
+            //             useNo: "",
228
+            //             searchCurrency: [],
229
+            //             validateFlag: true,
230
+            //             toCurNo: ''
231
+            //         });
232
+            //         util.successMessage("修改成功");
233
+            //     } else {
234
+            //         util.errorMessage("修改失败");
235
+            //     }
236
+            // }
237
+        },
238
+        ////////////////////////////////////////
239
+
240
+
241
+        // 列表查询
242
+        async queryDepartLevel({
243
+            commit,
244
+            state
245
+        }, payload) {
246
+            // 页面查询条件
247
+            const queryParam = state.queryParam;
248
+            payload.values = util.initQueryParam(payload, queryParam);
249
+            const params = {
250
+                use_yn: "Y",
251
+                ...payload.values
252
+            };
253
+            const data = await service.queryDepartLevelDefData(params);
254
+            commit("update", {
255
+                departLevelData: {
256
+                    current: data.pageNo,
257
+                    pageSize: data.pageSize,
258
+                    total: data.total,
259
+                    records: data.rows
260
+                },
261
+                queryParam: payload.values
262
+            });
263
+        },
264
+
265
+
266
+
267
+
268
+        // 新增一行
269
+        async addRows2({
270
+            commit,
271
+            dispatch,
272
+            state
273
+        }, payload) {
274
+            let conversion = state.conversion;
275
+            conversion.records.push({
276
+                rowsId: Date.now(),
277
+                use_yn: "Y",
278
+                key: '123',
279
+                name: '321',
280
+            });
281
+            console.log(conversion.records);
282
+            const name = payload.name;
283
+            if (name) {
284
+                conversion.records.forEach(item => {
285
+                    item.from_cur_no = name;
286
+                });
287
+            }
288
+            commit("update", {
289
+                conversion
290
+            });
291
+        }
292
+    },
293
+    mutations: {
294
+        update(state, payload) {
295
+            for (let key in payload) {
296
+                state[key] = payload[key];
297
+            }
298
+        },
299
+        // 清理数据
300
+        clearDepartLevelInfo(state) {
301
+            state.departLevelInfo = {
302
+                current: 1,
303
+                pageSize: 0,
304
+                total: 0,
305
+                records: []
306
+            },
307
+                state.title = '',
308
+                state.dialogData = {}
309
+        }
310
+    }
311
+}

+ 227
- 0
ant-design-pro-vue3/src/views/depart/departLevel/models/DepartLevel.store.ts 查看文件

@@ -0,0 +1,227 @@
1
+import * as service from '../services';
2
+import * as util from "@/utils/index.js";
3
+import { message } from "ant-design-vue";
4
+export default {
5
+    namespaced: true,
6
+    state: {
7
+        // 机构层级定义-列表查询条件
8
+        tableName: 'com_depart_level_info',
9
+        // 保存按钮状态
10
+        saveFlag: '0',
11
+        // 机构层级定义-列表查询数据
12
+        departLevelDefData: {
13
+            current: 1,
14
+            pageSize: 0,
15
+            total: 0,
16
+            records: []
17
+        },
18
+        //新增或修改的数据
19
+        dialogData: {
20
+            no: '',
21
+            key: '',
22
+            name: '',
23
+            use: '',
24
+            use_yn: 'Y',
25
+            modalType: '',// 1-新增,2-修改
26
+            title: '',
27
+            departLevelInfoData: {
28
+                current: 1,
29
+                pageSize: 0,
30
+                total: 0,
31
+                records: []
32
+            }
33
+        },
34
+    },
35
+    actions: {
36
+        // 机构层级定义列表查询
37
+        async queryDepartLevelDefData({ state, commit }, payload) {
38
+            // 1.获取vuex中的departLevelDefData数据
39
+            const departLevelDefData = state.departLevelDefData;
40
+            // 2.页面查询条件
41
+            const params = {
42
+                ...payload.values
43
+            };
44
+            // 2.调用接口 获取数据
45
+            const resp = await service.queryDepartLevelDefData(params);
46
+            departLevelDefData.total = resp.total;
47
+            departLevelDefData.pageSize = resp.pageSize;
48
+            departLevelDefData.records = resp.rows;
49
+            // 3.提交下vuex中的departLevelDefData数据
50
+            commit("update", { departLevelDefData: departLevelDefData });
51
+        },
52
+
53
+        async loadDialogDataData({ state, commit }, payload) {
54
+            // 1.获取vuex中的dialogData数据
55
+            const dialogData = state.dialogData;
56
+            if (payload == undefined) {
57
+                // 新增对话框数据初始化
58
+                dialogData.modalType = '1';
59
+                dialogData.title = '新增';
60
+                // 2.新增页面获取下机构层级外部编码
61
+                const resp = await service.getTabKeyRule({
62
+                    tabName: state.tableName
63
+                });
64
+                dialogData.key = resp.num;
65
+                dialogData.name = '';
66
+                dialogData.use = '';
67
+                dialogData.departLevelInfoData.current = 1;
68
+                dialogData.departLevelInfoData.pageSize = 0;
69
+                dialogData.departLevelInfoData.total = 0;
70
+                dialogData.departLevelInfoData.records = [];
71
+            } else {
72
+                // 修改对话框数据初始化
73
+                dialogData.modalType = '2';
74
+                dialogData.title = '修改';
75
+                // 2.修改页面查询层级列表信息
76
+                const resp = await service.queryDepartLevelInfoData({
77
+                    no: payload.no,
78
+                    page: 1,
79
+                    rows: 10
80
+                });
81
+                dialogData.no = payload.no;
82
+                dialogData.key = payload.key;
83
+                dialogData.name = payload.name;
84
+                dialogData.use = payload.use;
85
+                dialogData.use_yn = payload.use_yn;
86
+                dialogData.departLevelInfoData.current = 1;
87
+                dialogData.departLevelInfoData.pageSize = resp.pageSize;
88
+                dialogData.departLevelInfoData.total = resp.total;
89
+                dialogData.departLevelInfoData.records = resp.rows;
90
+            }
91
+            // 3.提交下vuex中的dialogData数据
92
+            commit("update", { dialogData: dialogData });
93
+        },
94
+
95
+        async queryDepartLevelInfoData({ state, commit }, payload) {
96
+            // 1.获取vuex中的dialogData数据
97
+            const dialogData = state.dialogData;
98
+            // 2.页面查询条件
99
+            const params = {
100
+                ...payload.values
101
+            };
102
+            // 2.调用接口 获取数据
103
+            const resp = await service.getDepartLevelInfoList(params);
104
+            dialogData.departLevelInfoData.total = resp.total;
105
+            dialogData.departLevelInfoData.records = resp.rows;
106
+            // 3.提交下vuex中的dialogData数据
107
+            commit("update", { dialogData: dialogData });
108
+        },
109
+
110
+        async addDepartLevelInfoData({ state, commit }) {
111
+            // 1.获取vuex中的dialogData数据
112
+            const dialogData = state.dialogData;
113
+            dialogData.departLevelInfoData.records.push({
114
+                no: util.createUniqueString(),
115
+                key: '',
116
+                name: '',
117
+                use_yn: ''
118
+            });
119
+            // 总行数加1
120
+            dialogData.departLevelInfoData.total++;
121
+            // 4.提交下vuex中的dialogData数据
122
+            commit("update", { dialogData: dialogData });
123
+
124
+        },
125
+
126
+        async deleteDepartLevelInfoData({ state, commit }, payload) {
127
+            // 1.获取vuex中的dialogData数据
128
+            const dialogData = state.dialogData;
129
+            if (payload.index) {
130
+                dialogData.departLevelInfoData.records.splice(payload.index, 1);
131
+            }
132
+            // 总行数加1
133
+            dialogData.departLevelInfoData.total--;
134
+            // 3.提交下vuex中的dialogData数据
135
+            commit("update", { dialogData: dialogData });
136
+        },
137
+
138
+        async saveDepartLevelInfoData({ state, commit, dispatch }, payload) {
139
+            // 1.获取vuex中的dialogData数据
140
+            const modalType = state.dialogData.modalType;
141
+            const dialogData = state.dialogData;
142
+            console.log("wyq:saveDepartLevelInfoData 前 dialogData", dialogData);
143
+            if (modalType == 1) {
144
+                console.log("wyq:saveDepartLevelInfoData 新增 dialogData", dialogData);
145
+                // 新增
146
+                // 1.新增页面获取下机构层级外部编码
147
+                if (dialogData.departLevelInfoData.records.length == 0) {
148
+                    message.error("请至少添加一个层级!");
149
+                    return;
150
+                }
151
+
152
+                // 2.调用接口 保存数据
153
+                const params = {
154
+                    key: dialogData.key,
155
+                    name: dialogData.name,
156
+                    use: dialogData.use,
157
+                    use_yn: dialogData.use_yn,
158
+                    _backFromClent: 'Y',
159
+                    data: JSON.stringify(dialogData.departLevelInfoData.records)
160
+                };
161
+                try {
162
+                    await service.insertDepartLevelInfoData(params);
163
+                    // 查询下数据
164
+                    // await dispatch('queryDepartLevelDefData', { values: { key: dialogData.key } });
165
+                    payload.closeMethod();
166
+                    // 处理成功响应
167
+                    message.success("新增成功!");
168
+                } catch (error) {
169
+                    // 处理异常响应,比如弹窗提示等;
170
+                    message.error(`请求失败: ${error.message}`);
171
+                    return
172
+                }
173
+            } else {
174
+                console.log("wyq:saveDepartLevelInfoData 修改 dialogData", dialogData);
175
+                // 修改
176
+                // 2.调用接口 修改数据
177
+                const params = {
178
+                    i_key: dialogData.key,
179
+                    i_name: dialogData.name,
180
+                    i_use: dialogData.use,
181
+                    no: dialogData.no,
182
+                    use_yn: dialogData.use_yn,
183
+                    data: JSON.stringify(dialogData.departLevelInfoData.records)
184
+                }
185
+                try {
186
+                    await service.updateDepartLevelInfoData(params);
187
+                    // service.queryDepartLevelDefData({ values: {} });
188
+                    payload.closeMethod();
189
+                    // 处理成功响应
190
+                    message.success("修改成功!");
191
+                } catch (error) {
192
+                    // 处理异常响应,比如弹窗提示等;
193
+                    message.error(`请求失败: ${error.message}`);
194
+                    return
195
+                }
196
+            }
197
+            commit("update", { saveFlag: state.saveFlag === '0' ? '1' : '0' });
198
+        },
199
+        async changeUseYn({ state, commit, dispatch }, payload) {
200
+            console.log("wyq:changeUseYn 前 payload", payload.values.use_yn, payload.values.no);
201
+            const useYn = payload.values.use_yn;
202
+            const params = {
203
+                no: payload.values.no
204
+            }
205
+            try {
206
+                await service.changeUseYn(params);
207
+                // 处理成功响应
208
+                if (useYn == 'Y') {
209
+                    message.success("停用成功");
210
+                } else {
211
+                    message.success("启用成功");
212
+                }
213
+            } catch (error) {
214
+                // 处理异常响应,比如弹窗提示等;
215
+                message.error(`请求失败: ${error.message}`);
216
+                return
217
+            }
218
+        }
219
+    },
220
+    mutations: {
221
+        update(state, payload) {
222
+            for (let key in payload) {
223
+                state[key] = payload[key];
224
+            }
225
+        },
226
+    }
227
+}

+ 137
- 0
ant-design-pro-vue3/src/views/depart/departLevel/services/index.ts 查看文件

@@ -0,0 +1,137 @@
1
+import request from "@/utils/request";
2
+import settings from "@/settings";
3
+import { message } from "ant-design-vue";
4
+import { Header } from "ant-design-vue/lib/layout/layout";
5
+
6
+const systemPrefix = settings.systemPrefix;
7
+// 查询机构层级列表
8
+export function queryDepartLevelDefData(param) {
9
+    return request(`${systemPrefix}/im/dhc/sys/automake/system/department/param/departlevelListController.do`, {
10
+        method: 'post',
11
+        data: param,
12
+        requestType: 'form'
13
+    });
14
+}
15
+
16
+export function getDepartLevelInfoList(param) {
17
+    return request(`${systemPrefix}/automake/controller/system/department/param/QueryDepartLevelInfoController.do`, {
18
+        method: 'post',
19
+        data: param,
20
+        requestType: 'form',
21
+        headers: {
22
+            "X-Requested-With": "XMLHttpRequest"
23
+        }
24
+    });
25
+}
26
+
27
+export function queryDepartLevelInfoData(param) {
28
+    return request(`${systemPrefix}/automake/controller/system/department/param/QueryDepartLevelInfoController.do`, {
29
+        method: 'post',
30
+        data: param,
31
+        requestType: 'form',
32
+        headers: {
33
+            "X-Requested-With": "XMLHttpRequest"
34
+        }
35
+    });
36
+}
37
+
38
+export function validateRecord(param) {
39
+    return request(`${systemPrefix}/financemanage/validateRecord.do`, {
40
+        method: 'post',
41
+        data: param,
42
+        requestType: 'form',
43
+        headers: {
44
+            "X-Requested-With": "XMLHttpRequest"
45
+        }
46
+    });
47
+}
48
+
49
+export function insertDepartLevelInfoData(param) {
50
+    return request(`${systemPrefix}/im/dhc/sys/automake/system/department/param/departlevelInsertController.do`, {
51
+        method: 'post',
52
+        data: param,
53
+        requestType: 'form',
54
+        headers: { "X-Requested-With": "XMLHttpRequest" }
55
+    });
56
+}
57
+
58
+export function updateDepartLevelInfoData(param) {
59
+    return request(`${systemPrefix}/automake/controller/system/department/param/departlevelModifyController.do`, {
60
+        method: 'post',
61
+        data: param,
62
+        requestType: 'form',
63
+        headers: { "X-Requested-With": "XMLHttpRequest" }
64
+    });
65
+}
66
+
67
+export function changeUseYn(param) {
68
+    return request(`${systemPrefix}/im/dhc/sys/automake/system/department/param/departlevelListChangeStsController.do`, {
69
+        method: 'post',
70
+        data: param,
71
+        requestType: 'form',
72
+        headers: { "X-Requested-With": "XMLHttpRequest" }
73
+    });
74
+}
75
+
76
+
77
+export function getTabKeyRule(param) {
78
+    return request(`${systemPrefix}/system/select/options/getTabKeyRule.do`, {
79
+        method: 'post',
80
+        data: param,
81
+        requestType: 'form'
82
+    });
83
+}
84
+
85
+export function searchCurrency(param) {
86
+    return request(`${systemPrefix}/system/select/options/getTabKeyRule.do`, {
87
+        method: 'post',
88
+        data: param,
89
+        requestType: 'form'
90
+    });
91
+}
92
+export function getRelationInfoNoOptions(params) {
93
+    return request(`${systemPrefix}/system/select/options/relationInfoNo.do`, {
94
+        method: 'post',
95
+        data: params,
96
+        requestType: 'form',
97
+    })
98
+}
99
+
100
+export function reportTreeDataController(params) {
101
+    return request(`${systemPrefix}/im/dhc/sys/automake/system/department/ReportTreeDataController.do`, {
102
+        method: 'post',
103
+        data: params,
104
+        requestType: 'form',
105
+
106
+    })
107
+}
108
+
109
+export function searchTreePanelDataByNodeI(params) {
110
+    return request(`${systemPrefix}/system/common/action/searchTreePanelDataByNodeId`, {
111
+        method: 'post',
112
+        data: params,
113
+        requestType: 'form',
114
+    })
115
+}
116
+
117
+export function searchReport(params) {
118
+    return request(`${systemPrefix}/im/dhc/zz/automake/zzmanage/reporformula_manager/ReadyReportDataController.do`, {
119
+        method: 'post',
120
+        data: params,
121
+        requestType: 'form',
122
+    })
123
+}
124
+
125
+export function searchReportResult(params) {
126
+    return request(`${systemPrefix}/report/query/zz/ywzkb`, {
127
+        method: 'post',
128
+        data: params,
129
+        headers: { "X-Requested-With": "XMLHttpRequest" }
130
+        // headers: {
131
+        //     'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
132
+        //     'Content-Type': 'application/x-www-form-urlencoded',
133
+        //     'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2'
134
+        // }
135
+    })
136
+
137
+}

+ 172
- 0
ant-design-pro-vue3/src/views/depart/departLevelInfo.vue 查看文件

@@ -0,0 +1,172 @@
1
+<template>
2
+
3
+    <div>
4
+        <pro-dialog :visible="$attrs.visible" @close="$emit('close:modal')" :title="title" width="70%" :closable="true"
5
+            :destroyOnClose="true" :maskClosable="true">
6
+            <template v-slot:footer="">
7
+                <pro-button id="f3dd65a2-c52b-11ea-87c3-ff36a904ecf1" @click="$emit('close:modal')"
8
+                    :icon="h(CloseOutlined)">关闭</pro-button>
9
+                <pro-button id="f3dd65a4-c52b-11ea-87c3-ff36a904ecf2" @click="saveHandler_d7fae64c"
10
+                    :icon="h(SaveOutlined)">保存</pro-button>
11
+            </template>
12
+
13
+            <pro-form ref="formRef_a6c2da04" :model="formData_a6c2da04" :rules="formRules_a6c2da04" label-width="120px">
14
+                <pro-form-grid :header="{ title: '基本信息' }" colNum="4">
15
+                    <pro-input v-show="false" :ref="(el) => formRefs_a6c2da04.no = el"
16
+                        :formItemProps="{ label: 'no', prop: 'no' }" v-model:value="formData_a6c2da04.no"
17
+                        placeholder="请输入" :allowClear="true">
18
+                    </pro-input>
19
+                    <pro-input :ref="(el) => formRefs_a6c2da04.key = el" :formItemProps="{ label: '层级编号', prop: 'key' }"
20
+                        v-model:value="formData_a6c2da04.key" placeholder="请输入" :allowClear="true"></pro-input>
21
+                </pro-form-grid>
22
+            </pro-form>
23
+
24
+            <pro-form-grid :header="{ title: '层级信息' }" colNum="3">
25
+                <div>
26
+                    <pro-table ref="tableRef_28fa7a23" :columns="columns_28fa7a23" :dataSource="conversion">
27
+                        <template v-slot:header="">
28
+                            <pro-button id=" 4b7facf0-94a4-11ee-9af3-e137392c498c" text="增加一行" :icon="h(PlusOutlined)"
29
+                                icon="plus" type="primary" @click="addRows">增加一行</pro-button>
30
+                        </template>
31
+                    </pro-table>
32
+                </div>
33
+            </pro-form-grid>
34
+        </pro-dialog>
35
+    </div>
36
+</template>
37
+
38
+<script setup lang="jsx">
39
+import { ref, onMounted, computed, h, useAttrs, watch, reactive } from 'vue';
40
+import settings from '@/settings';
41
+import request from '@/utils/request';
42
+import { useStore } from 'vuex';
43
+import { CloseOutlined, SaveOutlined, DeleteOutlined, PlusOutlined } from "@ant-design/icons-vue";
44
+import { Modal } from "ant-design-vue";
45
+
46
+const store = useStore();
47
+const formRefs_a6c2da04 = ref({
48
+    key: "",
49
+    name: "",
50
+    epn: "",
51
+    sbl: "",
52
+    show_seqn: "",
53
+    correct_yn: "",
54
+    use_yn: "",
55
+    brf: "",
56
+    default_yn: "",
57
+    formtype: "",
58
+    oldKey: ""
59
+});
60
+const formData_a6c2da04 = ref({
61
+    key: "",
62
+    name: "",
63
+    epn: "",
64
+    sbl: "",
65
+    show_seqn: "",
66
+    correct_yn: "N",
67
+    use_yn: "Y",
68
+    brf: "",
69
+    default_yn: "N",
70
+    formtype: "1",
71
+    oldKey: ""
72
+});
73
+
74
+
75
+onMounted(() => {
76
+    if (formData_a6c2da04.value.name) {
77
+        //修改
78
+        formData_a6c2da04.value.formtype = '2';
79
+        let oldKey = formData_a6c2da04.value.key;
80
+        formData_a6c2da04.value.oldKey = oldKey;
81
+    }
82
+    formData_a6c2da04.value = store.state.departLevel.formData
83
+});
84
+
85
+function saveHandler_d7fae64c () {
86
+
87
+}
88
+function formRules_a6c2da04 () {
89
+
90
+}
91
+
92
+const conversion = computed(() => store.state.departLevel.conversion);
93
+const tableRef_28fa7a23 = ref(null);
94
+
95
+const columns_28fa7a23 = ref([
96
+    {
97
+        prop: "ActionColumn",
98
+        label: "操作",
99
+        width: "120px",
100
+        align: "center",
101
+        render: (scope) => {
102
+            return <div>
103
+                <pro-button id="userDelete" onClick={() => confirmHandler_0c5b805d(scope)} icon={h(DeleteOutlined)}>删除</pro-button>
104
+            </div>
105
+        }
106
+    },
107
+    { prop: "key", label: "层级编号", align: "center", width: "120px", editing: true },
108
+    { prop: "name", label: "层级名称", align: "center", width: "120px", editing: true },
109
+    { prop: "brf", label: "层级功能描述", align: "center", width: "240px", editing: true },
110
+]);
111
+
112
+function confirmHandler_0c5b805d (scope) {
113
+    Modal.confirm({
114
+        title: '删除确认',
115
+        content: '确认删除选中的记录',
116
+        cancelText: '删除',
117
+        onOk () {
118
+            // store.dispatch('CurrencyManager/deleteRows', { ...scope.record });
119
+        }
120
+    });
121
+}
122
+
123
+const addRows = () => {
124
+    store.dispatch("departLevel/addRows", {
125
+        name: formData_a6c2da04.value.name
126
+    });
127
+};
128
+
129
+function editRow (item) {
130
+    console.log("------------------<<editRow>>-------------------");
131
+    item.editConfig = {
132
+        el: "input"
133
+    };
134
+
135
+}
136
+function proTableRowClick (value, row, column) {
137
+    console.log("------------------<<handleCellClick>>-------------------");
138
+
139
+    console.log('Cell clicked:', value, row, column);
140
+    // 在这里处理单元格点击事件
141
+}
142
+function onEditCell (value, row, index, key) {
143
+    console.log("------------------<<onEditCell>>-------------------");
144
+
145
+    console.log('编辑的值:', value);
146
+    console.log('当前行数据:', row);
147
+    console.log('当前行索引:', index);
148
+    console.log('编辑的字段:', key);
149
+    // 在这里处理编辑事件,例如更新数据等
150
+}
151
+function finishEdit (item) {
152
+    console.log("------------------<<finishEdit>>-------------------");
153
+
154
+    item.editing = false;
155
+    // 此处可添加其他逻辑,例如保存数据
156
+}
157
+
158
+
159
+const editableData = reactive({});
160
+const edit = key => {
161
+    console.log("------------------<<edit>>-------------------");
162
+
163
+    editableData[key] = cloneDeep(dataSource.value.filter(item => key === item.key)[0]);
164
+};
165
+
166
+const save = key => {
167
+    console.log("------------------<<save>>-------------------");
168
+
169
+    Object.assign(dataSource.value.filter(item => key === item.key)[0], editableData[key]);
170
+    delete editableData[key];
171
+};
172
+</script>

+ 170
- 0
ant-design-pro-vue3/src/views/depart/models/departLevel.store.ts 查看文件

@@ -0,0 +1,170 @@
1
+import { clear } from 'console';
2
+import * as service from '../services';
3
+import * as util from "@/utils/index.js";
4
+export default {
5
+    namespaced: true,
6
+    state: {
7
+        // 查询页
8
+        departLevelData: {
9
+            current: 1,
10
+            pageSize: 0,
11
+            total: 0,
12
+            records: []
13
+        },
14
+        // 表格数据
15
+        queryParam: {},
16
+        // list页面查询条件
17
+        insertOrModify: 1,
18
+        //新增修改标志:1-新增,2-修改
19
+
20
+        //新增修改
21
+        formData: {},
22
+        //表单数据
23
+        title: '',
24
+        // modal页面标题
25
+        conversion: {
26
+            current: 1,
27
+            pageSize: 0,
28
+            total: 0,
29
+            records: []
30
+        },
31
+        //折算币种
32
+        // 启用数据
33
+        useNo: "",
34
+        validateFlag: true,
35
+        searchCurrency: [],
36
+        // 新增修改页面折算后币种查询条件
37
+        toCurNo: [],
38
+
39
+
40
+        departLevelInfo: {
41
+            current: 1,
42
+            pageSize: 0,
43
+            total: 0,
44
+            records: []
45
+        }
46
+    },
47
+    actions: {
48
+        // 列表查询
49
+        async queryDepartLevel({
50
+            commit,
51
+            state
52
+        }, payload) {
53
+            console.log("wyq--", payload);
54
+            console.log("wy1q--", state.queryParam.values);
55
+
56
+            // 页面查询条件
57
+            const queryParam = state.queryParam;
58
+            console.log("wy2q--", queryParam);
59
+
60
+            payload.values = util.initQueryParam(payload, queryParam);
61
+            const params = {
62
+                use_yn: "Y",
63
+                ...payload.values
64
+            };
65
+            const data = await service.queryDepartLevel(params);
66
+            commit("update", {
67
+                departLevelData: {
68
+                    current: data.pageNo,
69
+                    pageSize: data.pageSize,
70
+                    total: data.total,
71
+                    records: data.rows
72
+                },
73
+                queryParam: payload.values
74
+            });
75
+        },
76
+
77
+
78
+        // 新增/修改页面打开
79
+        async clickInsertOrModifyBtn({ commit }, payload) {
80
+            // 清理下数据
81
+            commit("clearDepartLevelInfo");
82
+
83
+            const conversion = {
84
+                current: 1,
85
+                pageSize: 0,
86
+                total: 0,
87
+                records: []
88
+            };
89
+            const data = await service.searchCurrency({
90
+                use_yn: "Y"
91
+            });
92
+            if (payload == undefined) {
93
+                // 新增页面
94
+                const tableKey = await service.getTabKeyRule({
95
+                    tabName: 'currency'
96
+                });
97
+                commit("update", {
98
+                    insertOrModify: 1,
99
+                    title: '币种新增',
100
+                    formData: {
101
+                        key: tableKey.value
102
+                    },
103
+                    conversion,
104
+                    useNo: "",
105
+                    searchCurrency: data.test,
106
+                    validateFlag: true,
107
+                    toCurNo: ''
108
+                });
109
+            } else {
110
+                // 修改页面
111
+                console.log(payload.no);
112
+                const currencyConversion = await service.queryDepartLevelInfo({
113
+                    no: payload.no
114
+                });
115
+                currencyConversion.rows.forEach(item => item.from_cur_no = payload.name);
116
+                conversion.records = currencyConversion.rows;
117
+                commit("update", {
118
+                    insertOrModify: 2,
119
+                    title: '币种修改',
120
+                    formData: payload,
121
+                    conversion,
122
+                    useNo: payload.no,
123
+                    searchCurrency: data.test,
124
+                    validateFlag: true,
125
+                    toCurNo: payload.no
126
+                });
127
+            }
128
+        },
129
+        // 新增一行
130
+        async addRows({
131
+            commit,
132
+            dispatch,
133
+            state
134
+        }, payload) {
135
+            let conversion = state.conversion;
136
+            conversion.records.push({
137
+                rowsId: Date.now(),
138
+                use_yn: "Y",
139
+                key: '123',
140
+                name: '321',
141
+            });
142
+            console.log(conversion.records);
143
+            const name = payload.name;
144
+            if (name) {
145
+                conversion.records.forEach(item => {
146
+                    item.from_cur_no = name;
147
+                });
148
+            }
149
+            commit("update", {
150
+                conversion
151
+            });
152
+        }
153
+    },
154
+    mutations: {
155
+        update(state, payload) {
156
+            for (let key in payload) {
157
+                state[key] = payload[key];
158
+            }
159
+        },
160
+        // 清理数据
161
+        clearDepartLevelInfo(state) {
162
+            state.departLevelInfo = {
163
+                current: 1,
164
+                pageSize: 0,
165
+                total: 0,
166
+                records: []
167
+            }
168
+        }
169
+    }
170
+}

+ 38
- 0
ant-design-pro-vue3/src/views/depart/services/index.ts 查看文件

@@ -0,0 +1,38 @@
1
+import request from "@/utils/request";
2
+import settings from "@/settings";
3
+const systemPrefix = settings.systemPrefix;
4
+// 查询机构层级列表
5
+export function queryDepartLevel(param) {
6
+    return request(`${systemPrefix}/im/dhc/sys/automake/system/department/param/departlevelListController.do`, {
7
+        method: 'post',
8
+        data: param,
9
+        requestType: 'form'
10
+    });
11
+}
12
+
13
+export function getTabKeyRule(param) {
14
+    return request(`${systemPrefix}/system/select/options/getTabKeyRule.do`, {
15
+        method: 'post',
16
+        data: param,
17
+        requestType: 'form'
18
+    });
19
+}
20
+
21
+export function searchCurrency(param) {
22
+    return request(`${systemPrefix}/system/select/options/getTabKeyRule.do`, {
23
+        method: 'post',
24
+        data: param,
25
+        requestType: 'form'
26
+    });
27
+}
28
+
29
+export function queryDepartLevelInfo(param) {
30
+    return request(`${systemPrefix}/automake/controller/system/department/param/QueryDepartLevelInfoController.do`, {
31
+        method: 'post',
32
+        data: param,
33
+        requestType: 'form',
34
+        headers: {
35
+            "X-Requested-With": "XMLHttpRequest"
36
+        }
37
+    });
38
+}

+ 12
- 0
ant-design-pro-vue3/src/views/depart/test/TestPanel.vue 查看文件

@@ -0,0 +1,12 @@
1
+<template>
2
+    <div id="app">
3
+        <h2>Test Panel</h2>
4
+        <div class="content">
5
+            <LeftPanel />
6
+        </div>
7
+    </div>
8
+</template>
9
+
10
+<script>
11
+
12
+</script>

+ 49
- 0
ant-design-pro-vue3/src/views/example/ProDatePickerExample.vue 查看文件

@@ -0,0 +1,49 @@
1
+<template>
2
+    <!-- <pro-date-picker :formItemProps="{ label: '制表日期1', prop: 'rptDate' }" v-model:value="formData.rptDate"
3
+        placeholder="请选择制表日期" :allowClear="true">
4
+    </pro-date-picker> -->
5
+    <a-date-picker v-model:value="value1" />
6
+    <div>你好{{ sysData }}</div>
7
+    <div>你好{{ UserInfo }}</div>
8
+    <div>你好{{ day }}</div>
9
+</template>
10
+<script setup lang="jsx">
11
+import ls from '@/utils/Storage'
12
+import { USER_INFO, GOLBAL_TBSDY } from '@/store/mutation-types'
13
+
14
+import { ref, reactive, nextTick, onMounted, onUnmounted, h, } from 'vue';
15
+const formData = ref({
16
+    relationNo: '',
17
+    brNos: [],
18
+    brName: '',
19
+    rptDate: '20250318',
20
+    cycType: '',
21
+    cycTypeName: '',
22
+    curNo: '',
23
+    curName: '',
24
+    stddNo: '',
25
+    sobNo: '',
26
+    shFlag: '',
27
+    shFlagName: '',
28
+    adjType: '',
29
+    adjTypeName: '',
30
+    accLvl: '',
31
+    zeroPrintYn: '',
32
+    exrateType: '',
33
+    isGather: 'N',
34
+    telNo: '',
35
+
36
+    ptabName: ['v_gl_sub_coll_day'],
37
+    tabName: ["gls_gl_sub_tmp_sh_adj_q", "gls_gl_sub_tmp_sh_adj", "gls_gl_sub_tmp_sh_adj_h"],
38
+    reportType: '1',
39
+    rptType: '',
40
+
41
+});
42
+
43
+const value1 = ref();
44
+let sysData = JSON.parse(sessionStorage.getItem('sysDate'))
45
+const userNoInfo = JSON.parse(sessionStorage.getItem("user"));
46
+const UserInfo = ls.get(USER_INFO)
47
+const day = ls.get(GOLBAL_TBSDY)
48
+</script>
49
+<style></style>

+ 7
- 0
ant-design-pro-vue3/src/views/front/T2000/T2000.vue 查看文件

@@ -0,0 +1,7 @@
1
+<template>
2
+    <div>T2000</div>
3
+</template>
4
+
5
+<script setup>
6
+
7
+</script>

+ 7
- 0
ant-design-pro-vue3/src/views/front/T2001/T2001.vue 查看文件

@@ -0,0 +1,7 @@
1
+<template>
2
+    <div>T2001</div>
3
+</template>
4
+
5
+<script setup>
6
+
7
+</script>

+ 0
- 0
ant-design-pro-vue3/src/views/front/services/index.ts 查看文件


+ 9
- 2
ant-design-pro-vue3/vite.config.ts 查看文件

@@ -101,8 +101,15 @@ export default defineConfig({
101 101
             //-----------------------------财务请求代理--------------------------------
102 102
             '/zz-pack': {
103 103
 
104
-                target: 'http://localhost:8088/zz-pack/',
105
-                // target: 'http://172.16.2.162:16001/zz-pack/',
104
+                // target: 'http://localhost:8090/zz-pack/',
105
+                target: 'http://192.168.1.206:12206/zz-pack/',
106
+                changeOrigin: true,
107
+                rewrite: (path) => path.replace(/^\/zz-pack/, '')
108
+            },
109
+            '/zz_rpt': {
110
+
111
+                // target: 'http://localhost:8090/zz-pack/',
112
+                target: 'http://192.168.1.206:12206/zz-pack/',
106 113
                 changeOrigin: true,
107 114
                 rewrite: (path) => path.replace(/^\/zz-pack/, '')
108 115
             },

正在加载...
取消
保存