Skip to content

Commit 74ea1b8

Browse files
authored
Merge pull request OtterMind#2 from chat2db/main
update
2 parents 99580ed + a7b3026 commit 74ea1b8

28 files changed

Lines changed: 248 additions & 77 deletions

File tree

.github/workflows/pushdocker.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,10 @@ jobs:
4949
cd chat2db-client
5050
yarn install
5151
yarn run build:web:prod --app_version=${{ steps.chat2db_version.outputs.substring }}
52-
cp -r dist ../chat2db-server/chat2db-server-web-start/src/main/resources/static/front
53-
cp -r dist/index.html ../chat2db-server/chat2db-server-web-start/src/main/resources/thymeleaf/
52+
mkdir -p ../chat2db-server/chat2db-server-web-start/src/main/resources/static/
53+
mkdir -p ../chat2db-server/chat2db-server-web-start/src/main/resources/thymeleaf/
54+
cp -r dist ../chat2db-server/chat2db-server-start/src/main/resources/static/front
55+
cp -r dist/index.html ../chat2db-server/chat2db-server-start/src/main/resources/thymeleaf/
5456
5557
# 安装java
5658
- name: Install Java and Maven

CHANGELOG.md

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,42 @@
1+
## 3.1.15
2+
3+
`2023-12-20`
4+
5+
**Changelog**
6+
7+
- 🐞【Fixed】Every time I open the application, I occasionally cannot select the database problem
8+
- 🐞【Fixed】Compatible with old data types can not show deletion problems
9+
- 🐞【Fixed】Some databases cannot display the database /Schema structure
10+
11+
## 3.1.14
12+
13+
`2023-12-17`
14+
15+
**Changelog**
16+
17+
- 🐞【Fixed】Tree structure search for bugs
18+
- 🐞【Fixed】Switching tab causes edit data reset problem
19+
- 🐞【Fixed】Rename is reset after switching tab
20+
21+
22+
## 3.1.12
23+
24+
`2023-12-15`
25+
26+
**Changelog**
27+
28+
- ⚡️【Optimize】Optimized tree structure search
29+
- ⚡️【Optimize】Tree structure search box resident
30+
31+
## 3.1.11
32+
33+
`2023-12-13`
34+
35+
**Changelog**
36+
37+
- 🐞【Fixed】A chart with a Schema cannot be saved and executed
38+
- 🐞【Fixed】Failure to start after the upgrade
39+
140
## 3.1.1
241

342
`2023-12-13`
@@ -50,7 +89,7 @@
5089

5190
`2023-11-13`
5291

53-
**更新日志**
92+
**Changelog**
5493

5594
- 🐞【Fixed】Copy as insert first row lost problem
5695
- 🐞【Fixed】DM database index bug

CHANGELOG_CN.md

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,44 @@
1-
## 3.1.1
1+
## 3.1.15
2+
3+
`2023-12-20`
4+
5+
**更新日志**
6+
7+
- 🐞【修复】每次打开应用时,偶现无法选择数据库问题
8+
- 🐞【修复】兼容老数据类型无法显示删除问题
9+
- 🐞【修复】部分数据库无法显示数据库/Schema结构的问题
10+
11+
12+
## 3.1.14
13+
14+
`2023-12-17`
15+
16+
**更新日志**
17+
18+
- 🐞【修复】树结构搜索bug
19+
- 🐞【修复】切换tab导致编辑数据重置问题
20+
- 🐞【修复】切换tab后重命名被重置
21+
22+
23+
## 3.1.12
24+
25+
`2023-12-15`
26+
27+
**更新日志**
28+
29+
- ⚡️【优化】优化树结构搜索
30+
- ⚡️【优化】树结构搜索框常驻
31+
32+
## 3.1.11
33+
34+
`2023-12-13`
35+
36+
**更新日志**
37+
38+
- 🐞【修复】带Schema的图表无法保存和执行
39+
- 🐞【修复】升级后无法启动问题
40+
41+
## 3.1.10
242

343
`2023-12-13`
444

chat2db-client/src/blocks/Setting/About/index.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@ export default function AboutUs(props: IProps) {
2929
};
3030
});
3131

32-
console.log('holdingService', holdingService);
33-
3432
const onChangeUpdateRul = (e) => {
3533
configService.setAppUpdateType(e.target.value).then(() => {
3634
setUpdateRule(e.target.value);

chat2db-client/src/blocks/Tree/functions/refresh.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,4 @@ export const refreshTreeNode = (props:{
44
treeNodeData: ITreeNode;
55
}) => {
66
const { treeNodeData } = props;
7-
console.log(treeNodeData)
87
}

chat2db-client/src/blocks/Tree/index.tsx

Lines changed: 114 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { memo, useEffect, useMemo, useState, createContext, useContext, useRef } from 'react';
1+
import React, { memo, useEffect, useMemo, useState, createContext, useContext } from 'react';
22
import styles from './index.less';
33
import classnames from 'classnames';
44
import Iconfont from '@/components/Iconfont';
@@ -29,6 +29,8 @@ interface TreeNodeIProps {
2929
interface IContext {
3030
treeData: ITreeNode[];
3131
setTreeData: (value: ITreeNode[] | null) => void;
32+
searchTreeData: ITreeNode[] | null;
33+
setSearchTreeData: (value: ITreeNode[] | null) => void;
3234
}
3335

3436
export const Context = createContext<IContext>({} as any);
@@ -48,6 +50,59 @@ const smoothTree = (treeData: ITreeNode[], result: ITreeNode[] = [], parentNode?
4850
return result;
4951
};
5052

53+
// 平级转树
54+
function tranListToTreeData(list:ITreeNode[], rootValue) {
55+
const arr:ITreeNode[] = []
56+
list.forEach((item:ITreeNode) => {
57+
if (item.parentNode?.uuid === rootValue) {
58+
arr.push(item)
59+
const children = tranListToTreeData(list, item.uuid)
60+
if (children.length) {
61+
item.children = children
62+
}
63+
}
64+
})
65+
return arr
66+
}
67+
68+
// 判断是否匹配
69+
const isMatch = (target: string, searchValue: string) => {
70+
const reg = new RegExp(searchValue, 'i');
71+
return reg.test(target || '');
72+
};
73+
74+
// 树结构搜索
75+
function searchTree(treeData: ITreeNode[], searchValue: string): ITreeNode[] {
76+
let result: ITreeNode[] = [];
77+
78+
// 深度优先遍历
79+
function dfs(node: ITreeNode, path: ITreeNode[] = []) {
80+
if (isMatch(node.name, searchValue)) {
81+
result = [...result, ...path, node];
82+
return;
83+
}
84+
if (!node.children) return;
85+
node.children.forEach((child) => {
86+
dfs(child, [...path, node]);
87+
});
88+
}
89+
90+
// 遍历树
91+
treeData.forEach((node) => dfs(node));
92+
93+
// 根据uuid去重
94+
const deWeightList: ITreeNode[] = [];
95+
result.forEach((item) => {
96+
// 如果不匹配,说明该节点为path,不需要保留该节点的子元素,就把children置空
97+
if (!isMatch(item.name, searchValue)) {
98+
item.children = null;
99+
}
100+
deWeightList.findIndex((i) => i.uuid === item.uuid) === -1 && deWeightList.push(item);
101+
});
102+
103+
return tranListToTreeData(deWeightList, undefined);
104+
}
105+
51106
const itemHeight = 26; // 每个 item 的高度
52107
const paddingCount = 2;
53108

@@ -56,6 +111,8 @@ const Tree = (props: IProps) => {
56111
const [treeData, setTreeData] = useState<ITreeNode[] | null>(null);
57112
const [smoothTreeData, setSmoothTreeData] = useState<ITreeNode[]>([]);
58113
const [searchTreeData, setSearchTreeData] = useState<ITreeNode[] | null>(null); // 搜索结果
114+
const [searchSmoothTreeData, setSearchSmoothTreeData] = useState<ITreeNode[] | null>(null); // 搜索结果 平级
115+
59116
const [scrollTop, setScrollTop] = useState(0); // 滚动位置 // 继续需要渲染的 item 索引有哪些
60117

61118
const startIdx = useMemo(() => {
@@ -81,39 +138,53 @@ const Tree = (props: IProps) => {
81138
}
82139
}, [treeData]);
83140

141+
// 搜索结果转平级
142+
useEffect(() => {
143+
if (searchTreeData) {
144+
const result: ITreeNode[] = [];
145+
smoothTree(searchTreeData, result);
146+
setSearchSmoothTreeData(result);
147+
} else {
148+
setSearchSmoothTreeData(null);
149+
}
150+
}, [searchTreeData]);
151+
84152
const treeNodes = useMemo(() => {
85-
const realNodeList = (searchTreeData || smoothTreeData).slice(startIdx, startIdx + 50);
153+
const realNodeList = (searchSmoothTreeData || smoothTreeData).slice(startIdx, startIdx + 50);
86154
return realNodeList.map((item) => {
87155
return <TreeNode key={item.uuid} level={item.level || 0} data={item} />;
88156
});
89-
}, [smoothTreeData, searchTreeData, startIdx]);
157+
}, [smoothTreeData, searchSmoothTreeData, startIdx]);
90158

91159
useEffect(() => {
92-
if (searchValue) {
93-
const ls = smoothTreeData.filter((item) => {
94-
const reg = new RegExp(searchValue, 'i');
95-
return reg.test(item.name || '');
96-
});
97-
setSearchTreeData(ls);
160+
if (searchValue && treeData) {
161+
const _searchTreeData = searchTree(cloneDeep(treeData), searchValue);
162+
setSearchTreeData(_searchTreeData);
163+
setScrollTop(0);
98164
} else {
99165
setSearchTreeData(null);
100166
}
101-
setScrollTop(0);
102167
}, [searchValue]);
103168

104169
return (
105170
<LoadingContent isLoading={!treeData} className={classnames(className)}>
106-
<Context.Provider value={{ treeData: cloneDeep(treeData!), setTreeData: setTreeData! }}>
171+
<Context.Provider
172+
value={{
173+
treeData: treeData!,
174+
setTreeData: setTreeData!,
175+
searchTreeData,
176+
setSearchTreeData
177+
}}
178+
>
107179
<div
108180
className={classnames(styles.scrollBox)}
109181
onScroll={(e: any) => {
110-
console.log(e.target.scrollTop);
111182
setScrollTop(e.target.scrollTop);
112183
}}
113184
>
114185
<div
115186
className={styles.treeListHolder}
116-
style={{ '--tree-node-count': (searchTreeData || smoothTreeData)?.length } as any}
187+
style={{ '--tree-node-count': (searchSmoothTreeData || smoothTreeData)?.length } as any}
117188
>
118189
<div style={{ height: top }} />
119190
{treeNodes}
@@ -128,15 +199,18 @@ const TreeNode = memo((props: TreeNodeIProps) => {
128199
const { data: treeNodeData, level } = props;
129200
const [isLoading, setIsLoading] = useState(false);
130201
const indentArr = new Array(level).fill('indent');
131-
const { treeData, setTreeData } = useContext(Context);
202+
const { treeData, setTreeData, searchTreeData, setSearchTreeData } = useContext(Context);
132203

133204
// 加载数据
134205
function loadData(_props?: { refresh: boolean; pageNo: number; treeNodeData?: ITreeNode }) {
135206
const _treeNodeData = _props?.treeNodeData || props.data;
136207
const treeNodeConfig: ITreeConfigItem = treeConfig[_treeNodeData.pretendNodeType || _treeNodeData.treeNodeType];
137208
setIsLoading(true);
138209
if (_props?.pageNo === 1 || !_props?.pageNo) {
139-
insertData(treeData!, _treeNodeData.uuid!, null);
210+
insertData(treeData!, _treeNodeData.uuid!, null,[treeData, setTreeData]);
211+
if(searchTreeData){
212+
insertData(searchTreeData!, _treeNodeData.uuid!, null,[searchTreeData, setSearchTreeData]);
213+
}
140214
}
141215

142216
treeNodeConfig
@@ -151,16 +225,21 @@ const TreeNode = memo((props: TreeNodeIProps) => {
151225
.then((res: any) => {
152226
if (res.length || res.data) {
153227
if (res.data) {
154-
insertData(treeData!, _treeNodeData.uuid!, res.data);
155-
// TODO:
228+
insertData(treeData!, _treeNodeData.uuid!, res.data, [treeData, setTreeData]);
229+
if(searchTreeData){
230+
insertData(searchTreeData!, _treeNodeData.uuid!, res.data,[searchTreeData, setSearchTreeData]);
231+
}
156232
if (res.hasNextPage) {
157233
loadData({
158234
refresh: _props?.refresh || false,
159235
pageNo: res.pageNo + 1,
160236
});
161237
}
162238
} else {
163-
insertData(treeData!, _treeNodeData.uuid!, res);
239+
insertData(treeData!, _treeNodeData.uuid!, res,[treeData, setTreeData]);
240+
if(searchTreeData){
241+
insertData(searchTreeData!, _treeNodeData.uuid!, res,[searchTreeData, setSearchTreeData]);
242+
}
164243
}
165244
setIsLoading(false);
166245
} else {
@@ -169,7 +248,10 @@ const TreeNode = memo((props: TreeNodeIProps) => {
169248
_treeNodeData.pretendNodeType = treeNodeConfig.next;
170249
loadData();
171250
} else {
172-
insertData(treeData!, _treeNodeData.uuid!, []);
251+
insertData(treeData!, _treeNodeData.uuid!, [],[treeData, setTreeData]);
252+
if(searchTreeData){
253+
insertData(searchTreeData!, _treeNodeData.uuid!, [],[searchTreeData, setSearchTreeData]);
254+
}
173255
setIsLoading(false);
174256
}
175257
}
@@ -183,23 +265,25 @@ const TreeNode = memo((props: TreeNodeIProps) => {
183265
const isFocus = useTreeStore((state) => state.focusId) === treeNodeData.uuid;
184266

185267
// 在treeData中找到对应的节点,插入数据
186-
const insertData = (_treeData: ITreeNode[], uuid: string, data: any): ITreeNode | null => {
268+
const insertData = (_treeData: ITreeNode[], uuid: string, data: any, originalDataList:any): ITreeNode | null => {
269+
const [originalData,setOriginalData] = originalDataList
187270
let result: ITreeNode | null = null;
188271
for (let i = 0; i < _treeData?.length; i++) {
189272
if (_treeData[i].uuid === uuid) {
190273
result = _treeData[i];
191274
if (data) {
275+
data.map((item: any) => {
276+
item.parentNode = result;
277+
});
192278
result.children = [...(result.children || []), ...(data || [])];
193279
} else {
194280
result.children = null;
195281
}
196-
result.expanded = !!data;
197-
// 这里没写错 就是要改变treeData的引用
198-
setTreeData?.(cloneDeep(treeData || []));
282+
setOriginalData?.(cloneDeep([...(originalData || [])]));
199283
break;
200284
} else {
201285
if (_treeData[i].children) {
202-
result = insertData(_treeData[i].children!, uuid, data);
286+
result = insertData(_treeData[i].children!, uuid, data, originalDataList);
203287
if (result) {
204288
break;
205289
}
@@ -211,8 +295,11 @@ const TreeNode = memo((props: TreeNodeIProps) => {
211295

212296
//展开-收起
213297
const handleClick = () => {
214-
if (treeNodeData.expanded) {
215-
insertData(treeData!, treeNodeData.uuid!, null);
298+
if (treeNodeData?.children) {
299+
insertData(treeData!, treeNodeData.uuid!, null,[treeData, setTreeData]);
300+
if(searchTreeData){
301+
insertData(searchTreeData!, treeNodeData.uuid!, null,[searchTreeData, setSearchTreeData]);
302+
}
216303
} else {
217304
loadData();
218305
}
@@ -267,7 +354,6 @@ const TreeNode = memo((props: TreeNodeIProps) => {
267354
label: <MenuLabel icon={item.labelProps.icon} label={item.labelProps.label} />,
268355
};
269356
});
270-
271357
return (
272358
<Dropdown
273359
trigger={['contextMenu']}
@@ -326,7 +412,7 @@ const TreeNode = memo((props: TreeNodeIProps) => {
326412
</Tooltip>
327413
</Dropdown>
328414
);
329-
}, [isFocus, isLoading, rightClickMenu]);
415+
}, [isFocus, isLoading, rightClickMenu, treeNodeData.children]);
330416

331417
return treeNodeDom;
332418
});

0 commit comments

Comments
 (0)