feat:文件dir保存

This commit is contained in:
shixiaohua 2024-03-04 16:14:12 +08:00
parent b9d63dd313
commit bf30771d66
8 changed files with 291 additions and 170 deletions

View File

@ -16,6 +16,7 @@ import DirAddFile from "./DirAddFile";
import DirDeleteFile from "./DirDeleteFile"; import DirDeleteFile from "./DirDeleteFile";
import DirAddDir from "./DirAddDir"; import DirAddDir from "./DirAddDir";
import {createPortal} from "react-dom"; import {createPortal} from "react-dom";
import {isArray} from "@craco/craco/lib/utils";
// const defaultData = []; // const defaultData = [];
// //
const dataList = []; const dataList = [];
@ -77,12 +78,55 @@ function generateChildList(fileList) {
const titleExtended = (fileName, filePath) => { const titleExtended = (fileName, filePath) => {
return <span title={filePath}>{fileName}</span> return <span title={filePath}>{fileName}</span>
} }
function findFirstEndGEZ(childrenList,child){
if (isArray(childrenList)&& childrenList.length>0){
if (childrenList.find(fileDir=> fileDir.dirFlag&&fileDir.end>0)){
child.push(...childrenList)
return childrenList;
}else {
childrenList.forEach(fileDir=>{
if (fileDir.dirFlag&&isArray(fileDir.children)&&fileDir.children.length>0){
findFirstEndGEZ(fileDir.children,child)
}
})
}
}
}
/** /**
* 将文件信息改为树信息 * 将文件信息改为树信息
* @param fileDirDate * @param fileDirDate
* @returns {*[]} * @returns {*[]}
*/ */
const flushTree = (fileDirDate) => { const flushTree = (fileDirTree) => {
// end>o
//
let fileList = []
findFirstEndGEZ(fileDirTree.children,fileList)
const defaultValueStateSet = [];
if (Array.isArray(fileList) && fileList.length > 0) {
for (let i = 0; i < fileList.length; i++) {
const node = fileList[i];
console.log("node:", node)
const {fileName, filePath, children, dirFlag} = node;
const childrenM = []
if (Array.isArray(children) && children.length > 0) {
childrenM.push(...generateChildList(children));
}
defaultValueStateSet.push({
"key": filePath,
//
"title": titleExtended(getFileNameByPath(fileName), filePath),
"icon": <FolderOutlined/>,
"dirFlag": dirFlag,
"children": childrenM
});
}
}
return defaultValueStateSet;
}
const flushTreeList = (fileDirDate) => {
const defaultValueStateSet = []; const defaultValueStateSet = [];
if (Array.isArray(fileDirDate) && fileDirDate.length > 0) { if (Array.isArray(fileDirDate) && fileDirDate.length > 0) {
for (let i = 0; i < fileDirDate.length; i++) { for (let i = 0; i < fileDirDate.length; i++) {
@ -123,7 +167,7 @@ const ItemTree = (prop) => {
// const [expandedKeys, setExpandedKeys] = useState([]); // const [expandedKeys, setExpandedKeys] = useState([]);
const expandedKeys = useSelector(state => state.tableBarItem.expandedKeyList) const expandedKeys = useSelector(state => state.tableBarItem.expandedKeyList)
const [searchValue, setSearchValue] = useState(''); const [searchValue, setSearchValue] = useState('');
const [autoExpandParent, setAutoExpandParent] = useState(true); const [autoExpandParent, setAutoExpandParent] = useState(false);
// let filePath = useSelector(state => state.dirMessage.data); // let filePath = useSelector(state => state.dirMessage.data);
const [defaultValueState, setDefaultValueState] = useState(flushTree(prop.filePath)); const [defaultValueState, setDefaultValueState] = useState(flushTree(prop.filePath));
const [state, setState] = useState(); const [state, setState] = useState();
@ -197,7 +241,7 @@ const ItemTree = (prop) => {
if (Array.isArray(fileStateList[0].children) && fileStateList[0].children.length > 0) { if (Array.isArray(fileStateList[0].children) && fileStateList[0].children.length > 0) {
dispatch(refreshDirReducer({selectDirKey: filePath, fileStateList})) dispatch(refreshDirReducer({selectDirKey: filePath, fileStateList}))
// //
addChildNode(defaultValueState, flushTree(fileStateList)) addChildNode(defaultValueState, flushTreeList(fileStateList))
const result = [...defaultValueState] const result = [...defaultValueState]
console.log("[...defaultValueState]:", result) console.log("[...defaultValueState]:", result)
setDefaultValueState(result) setDefaultValueState(result)
@ -217,7 +261,7 @@ const ItemTree = (prop) => {
if (Array.isArray(fileStateList[0].children) && fileStateList[0].children.length > 0) { if (Array.isArray(fileStateList[0].children) && fileStateList[0].children.length > 0) {
dispatch(nextDirAdd({selectDirKey: e.node.key, fileStateList})) dispatch(nextDirAdd({selectDirKey: e.node.key, fileStateList}))
// //
addChildNode(defaultValueState, flushTree(fileStateList)) addChildNode(defaultValueState, flushTreeList(fileStateList))
const result = [...defaultValueState] const result = [...defaultValueState]
console.log("[...defaultValueState]:", result) console.log("[...defaultValueState]:", result)
setDefaultValueState(result) setDefaultValueState(result)

View File

@ -13,6 +13,7 @@ import {
CUT_COMMAND, CUT_COMMAND,
PASTE_COMMAND, PASTE_COMMAND,
} from 'lexical'; } from 'lexical';
import "./index.less"
function ContextMenuItem({ function ContextMenuItem({
index, index,
isSelected, isSelected,

View File

@ -0,0 +1,92 @@
.typeahead-popover {
background: #fff;
box-shadow: 0px 5px 10px rgba(0, 0, 0, 0.3);
border-radius: 8px;
position: fixed;
}
.typeahead-popover ul {
padding: 0;
list-style: none;
margin: 0;
border-radius: 8px;
max-height: 200px;
overflow-y: scroll;
}
.typeahead-popover ul::-webkit-scrollbar {
display: none;
}
.typeahead-popover ul {
-ms-overflow-style: none;
scrollbar-width: none;
}
.typeahead-popover ul li {
margin: 0;
min-width: 180px;
font-size: 14px;
outline: none;
cursor: pointer;
border-radius: 8px;
}
.typeahead-popover ul li.selected {
background: #eee;
}
.typeahead-popover li {
margin: 0 8px 0 8px;
padding: 8px;
color: #050505;
cursor: pointer;
line-height: 16px;
font-size: 15px;
display: flex;
align-content: center;
flex-direction: row;
flex-shrink: 0;
background-color: #fff;
border-radius: 8px;
border: 0;
}
.typeahead-popover li.active {
display: flex;
width: 20px;
height: 20px;
background-size: contain;
}
.typeahead-popover li:first-child {
border-radius: 8px 8px 0px 0px;
}
.typeahead-popover li:last-child {
border-radius: 0px 0px 8px 8px;
}
.typeahead-popover li:hover {
background-color: #eee;
}
.typeahead-popover li .text {
display: flex;
line-height: 20px;
flex-grow: 1;
min-width: 150px;
}
.typeahead-popover li .icon {
display: flex;
width: 20px;
height: 20px;
user-select: none;
margin-right: 8px;
line-height: 16px;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
}

View File

@ -21,7 +21,7 @@ const Note = () => {
const activeKey=useSelector(state => state.tableBarItem.activeKey); const activeKey=useSelector(state => state.tableBarItem.activeKey);
const items = useSelector(state => state.tableBarItem.data) const items = useSelector(state => state.tableBarItem.data)
let filePath = useSelector(state => state.dirMessage.data); let filePath = useSelector(state => state.dirMessage.dirTree);
const itemTreeTab=[ const itemTreeTab=[
{ {

View File

@ -1,6 +1,8 @@
import {createSlice} from '@reduxjs/toolkit' import {createSlice} from '@reduxjs/toolkit'
import {isEmpty} from "../utils/ObjectUtils"; import {isEmpty} from "../utils/ObjectUtils";
import {fullFileNameFormat, getFileFullNameByPath} from "../utils/PathOperate"; import {fileDirFormat, filePathSplit, getFileDirByPath, getFileFullNameByPath} from "../utils/PathOperate";
import {FileTree, insertNode, removeNode, updateNode} from "../utils/FileTree"
import {func} from "prop-types";
/* /*
fileTitle:文件名 fileTitle:文件名
fileName:文件名.文件扩展名 fileName:文件名.文件扩展名
@ -16,101 +18,43 @@ export const dirMessageSlice = createSlice({
name: 'dirMessage', name: 'dirMessage',
initialState: { initialState: {
data: [], data: [],
// selectDirKey:"" dirTree:new FileTree("root","/root",true,[])
}, },
reducers: { reducers: {
// 一级目录有相同的就要和并,从第一次展开处和并,不需要展示上一级。
dirAdd: (state, action) => { dirAdd: (state, action) => {
console.log("dirMessage:dirAdd", state, action) console.log("dirMessage:dirAdd", state, action)
if (action.payload) { // 添加目录
// 新添加进来的目录,要判断是否包含或者被包含,如果包含则统一树结构 insertNode(state.dirTree,action.payload[0])
let fileFilter = state.data.filter((fileMessage) =>
fileMessage.filePath.startsWith(action.payload[0].filePath)
);
let actionFilter = state.data.filter((fileMessage) =>
action.payload[0].filePath.startsWith(fileMessage.filePath)
);
let equalsFilter = state.data.filter((fileMessage) =>
action.payload[0].filePath===fileMessage.filePath
);
// 打开相同目录不用处理
if (equalsFilter.length > 0) {
console.log('equalsFilter', filter)
}
// 打开上级目录
else if (actionFilter.length>0){
}
// 打开下级目录
else if (fileFilter.length>0){
}
// 无关目录
else {
// 添加进当前目录
state.data = [...new Set([...state.data, ...action.payload])];
console.log('state.data:', state.data)
}
}
}, },
newFileAdd :(state,action)=>{ newFileAdd :(state,action)=>{
console.log("dirMessage:newFileAdd", state, action)
insertNode(state.dirTree,action.payload[0])
}, },
dirRemove:(state,action)=>{ dirRemove:(state,action)=>{
console.log("dirMessage:dirRemove", state, action) console.log("dirMessage:dirRemove", state, action)
// 获取当前选中的key // 获取当前选中的key
let selectDirKey = action.payload.selectDirKey; let selectDirKey = action.payload.selectDirKey;
state.data = state.data.filter(file=>{ if (isEmpty(state.dirTree.filePath)){
if (file.filePath === selectDirKey && file.dirFlag) { return
return false;
} else if (file.children.length > 0 && selectDirKey.startsWith(file.filePath)) {
file.children = filterChild(file.children, selectDirKey)
return true;
}else {
return true;
} }
}) removeNode(state.dirTree,{fileName:getFileFullNameByPath(selectDirKey),filePath:selectDirKey,dirFlag:true,children:[]})
}, },
nextDirAdd: (state, action) => { nextDirAdd: (state, action) => {
console.log("dirMessage:nextDirAdd", state, action) console.log("dirMessage:nextDirAdd", state, action)
// 获取当前选中的key insertNode(state.dirTree,action.payload.fileStateList[0])
let selectDirKey = action.payload.selectDirKey;
// 遍历文件树找到对应的key并加入其中
// 如果包含下级目录则不更新,在刷新中更新。
state.data.forEach(file => {
if (file.filePath === selectDirKey && file.dirFlag && file.children.length === 0) {
file.children.push(action.payload.fileStateList[0].children)
} else if (file.children.length > 0) {
findChild(file.children, action, selectDirKey)
}
})
}, },
refreshDir: (state, action) => { refreshDir: (state, action) => {
console.log("dirMessage:refreshDir", state, action) console.log("dirMessage:refreshDir", state, action)
// 获取当前选中的key insertNode(state.dirTree,action.payload.fileStateList[0])
let selectDirKey = action.payload.selectDirKey;
// 遍历文件树找到对应的key并加入其中
state.data.forEach(file => {
if (file.filePath === selectDirKey && file.dirFlag) {
file.children=action.payload.fileStateList[0].children
} else if (file.children.length > 0) {
refreshChild(file.children, action, selectDirKey)
}
})
}, },
updateFileName:(state,action)=>{ updateFileName:(state,action)=>{
console.log("dirMessage:updateFileName", state, action) console.log("dirMessage:updateFileName", state, action)
let newFilePath = action.payload.newFilePath let newFilePath = action.payload.newFilePath
let oldFilePath = action.payload.oldFilePath let oldFilePath = action.payload.oldFilePath
// 查找旧文件并且修改文件信息 updateNode(state.dirTree,
state.data.forEach(file => { {fileName:getFileFullNameByPath(oldFilePath),filePath:oldFilePath,dirFlag:false,children:[]},
if (file.filePath === oldFilePath) { {fileName:getFileFullNameByPath(newFilePath),filePath:newFilePath,dirFlag:false,children:[]}
file.filePath = newFilePath )
file.fileName = getFileFullNameByPath(newFilePath)
} else if (file.children.length > 0 && oldFilePath.startsWith(file.filePath)) {
updateFileNameChild(file.children, oldFilePath, newFilePath)
}
})
}, },
dirFileAdd:(state,action)=>{ dirFileAdd:(state,action)=>{
console.log("dirMessage:dirFileAdd", state, action) console.log("dirMessage:dirFileAdd", state, action)
@ -123,18 +67,7 @@ export const dirMessageSlice = createSlice({
"dirFlag": false, "dirFlag": false,
"children": [] "children": []
} }
// 查找旧文件并且修改文件信息 insertNode(state.dirTree,fileMessage)
state.data.forEach(file => {
if (file.filePath === fileDir) {
if (Array.isArray(file.children)){
file.children.push(fileMessage)
}else {
file.children=[fileMessage]
}
} else if (file.children.length > 0 && filePath.startsWith(file.filePath)) {
dirFileAddChild(file.children, fileDir, fileMessage)
}
})
}, },
dirDirAdd:(state,action)=>{ dirDirAdd:(state,action)=>{
console.log("dirMessage:dirDirAdd", state, action) console.log("dirMessage:dirDirAdd", state, action)
@ -147,87 +80,16 @@ export const dirMessageSlice = createSlice({
"dirFlag": true, "dirFlag": true,
"children": [] "children": []
} }
// 查找旧文件并且修改文件信息 insertNode(state.dirTree,fileMessage)
state.data.forEach(file => {
if (file.filePath === fileDir) {
if (Array.isArray(file.children)){
file.children.push(fileMessage)
}else {
file.children=[fileMessage]
}
} else if (file.children.length > 0 && fileDir.startsWith(file.filePath)) {
dirFileAddChild(file.children, fileDir, fileMessage)
}
})
}, },
dirFileRemove:(state,action)=>{ dirFileRemove:(state,action)=>{
console.log("dirMessage:dirFileRemove", state, action) console.log("dirMessage:dirFileRemove", state, action)
let filePath = action.payload.filePath; let filePath = action.payload.filePath;
state.data = state.data.filter(file=>{ removeNode(state.dirTree,{fileName:getFileFullNameByPath(filePath),filePath:filePath,dirFlag:false,children:[]})
if (file.filePath === filePath && !file.dirFlag) {
return false;
} else if (file.children.length > 0 && filePath.startsWith(file.filePath)) {
file.children = dirFileRemoveChild(file.children, filePath)
return true;
}else {
return true;
}
})
} }
} }
}) })
function dirFileRemoveChild(fileList, selectDirKey) {
return fileList.filter(file => {
if (file.filePath === selectDirKey && !file.dirFlag) {
return false
}else if (file.dirFlag && selectDirKey.startsWith(file.filePath) && Array.isArray(file.children) && file.children.length > 0) {
file.children = dirFileRemoveChild(file.children, selectDirKey)
return true
}else {
return true
}
})
}
function dirFileAddChild(fileList, fileDir, fileMessage){
fileList.forEach(file => {
if (file.filePath === fileDir) {
if (Array.isArray(file.children)){
file.children.push(fileMessage)
}else {
file.children=[fileMessage]
}
} else if (file.children.length > 0 && fileDir.startsWith(file.filePath)) {
dirFileAddChild(file.children, fileDir, fileMessage)
}
})
}
function filterChild(fileList, selectDirKey) {
return fileList.filter(file => {
if (file.filePath === selectDirKey && file.dirFlag) {
return false
}else if (file.dirFlag && selectDirKey.startsWith(file.filePath) && Array.isArray(file.children) && file.children.length > 0) {
filterChild(file.children, selectDirKey)
return true
}else {
return true
}
})
}
function refreshChild(fileList, action, selectDirKey) {
fileList.forEach(file => {
if (file.filePath === selectDirKey && file.dirFlag) {
file.children = action.payload.fileStateList[0].children
return
}
if (file.dirFlag && Array.isArray(file.children) && file.children.length > 0) {
refreshChild(file.children, action, selectDirKey)
}
})
}
function findChild(fileList, action, selectDirKey) { function findChild(fileList, action, selectDirKey) {
fileList.forEach(file => { fileList.forEach(file => {
if (file.filePath === selectDirKey && file.dirFlag && if (file.filePath === selectDirKey && file.dirFlag &&

View File

@ -80,9 +80,6 @@ export const tableBarItemSlice = createSlice({
console.log("tableBarItemSlice:setExpandedKeys",action.payload) console.log("tableBarItemSlice:setExpandedKeys",action.payload)
state.expandedKeyList=action.payload state.expandedKeyList=action.payload
}, },
removeExpandedKeys:(state, action)=>{
state.expandedKeyList=state.expandedKeyList.filter(key=>key!==action.payload)
},
editLeftTableOfContents:(state, action)=>{ editLeftTableOfContents:(state, action)=>{
state.leftTableOfContents=action.payload.leftTableOfContents state.leftTableOfContents=action.payload.leftTableOfContents
} }
@ -93,7 +90,6 @@ export const { addTableBarItem,
setActiveKey, setActiveKey,
updatedSavedFile, updatedSavedFile,
setExpandedKeys, setExpandedKeys,
removeExpandedKeys,
addExpandedKeys, addExpandedKeys,
updateFileName, updateFileName,
editLeftTableOfContents editLeftTableOfContents

118
src/utils/FileTree.js Normal file
View File

@ -0,0 +1,118 @@
import {fileDirFormat, fileDirFormatArray, filePathSplit, getFileDirByPath} from "./PathOperate";
import {isObject} from "formik";
import {isEmpty} from "./ObjectUtils";
export class FileTree {
constructor(fileName,filePath,dirFlag,children) {
this.fileName = fileName;
this.filePath = filePath;
this.dirFlag = dirFlag;
this.children = children;
this.pass=0
this.end=0
}
}
export function insertNode(root,fileMessage) {
// let copy = JSON.parse(JSON.stringify(root))
// let currentNode = copy;
let currentNode = root;
let fileDir;
if (fileMessage.dirFlag){
fileDir=fileMessage.filePath
}else {
fileDir=getFileDirByPath(fileMessage.filePath)
}
let fileDirSplit = filePathSplit(fileDir).filter(fileD=>!isObject(fileD)&&fileD!=="");
for (let i = 0; i < fileDirSplit.length; i++) {
let find = currentNode.children.find(file=>file.dirFlag&&file.fileName===fileDirSplit[i]);
if (find &&!isEmpty(find.fileName)){
currentNode=find;
currentNode.pass=currentNode.pass+1
}else {
let newNode = new FileTree(fileDirSplit[i],fileDirFormatArray(fileDirSplit.slice(0,i+1)),true,[]);
currentNode.children.push(newNode)
currentNode=newNode
currentNode.pass=currentNode.pass+1
}
if (i===fileDirSplit.length-1){
currentNode.end =1
if (!fileMessage.dirFlag){
currentNode.children.push(fileMessage)
} else {
currentNode.children = fileMessage.children
}
}
}
// return copy;
}
export function removeNode(root,fileMessage) {
let currentNode = root;
let fileDir;
if (fileMessage.dirFlag){
fileDir=fileMessage.filePath
}else {
fileDir=getFileDirByPath(fileMessage.filePath)
}
let fileDirSplit = filePathSplit(fileDir).filter(fileD=>!isObject(fileD)&&fileD!=="");
for (let i = 0; i < fileDirSplit.length; i++) {
if (i===fileDirSplit.length-1) {
if (fileMessage.dirFlag) {
currentNode.children = currentNode.children.filter(file =>
file.fileName !== fileDirSplit[i] && file.dirFlag)
break
} else {
currentNode.children = currentNode.children.filter(file =>
file.fileName !== fileMessage.fileName && !file.dirFlag)
break
}
}
let find = currentNode.children.find(file=>file.dirFlag&&file.fileName===fileDirSplit[i]);
if (!isEmpty(find)){
currentNode=find;
}else {
break
}
}
}
export function updateNode(root,fileMessage,newFileMessage) {
let currentNode = root;
let fileDir;
if (fileMessage.dirFlag){
fileDir=fileMessage.filePath
}else {
fileDir=getFileDirByPath(fileMessage.filePath)
}
let fileDirSplit = filePathSplit(fileDir).filter(fileD=>!isObject(fileD)&&fileD!=="");
for (let i = 0; i < fileDirSplit.length; i++) {
if (fileMessage.dirFlag){
if (i===fileDirSplit.length-1){
let node =currentNode.children.find(file=>
file.fileName===fileDirSplit[i]&&file.dirFlag);
node.fileName=newFileMessage.fileName
node.filePath=newFileMessage.filePath
node.dirFlag=newFileMessage.dirFlag
node.children=newFileMessage.children
}
}else {
if (i===fileDirSplit.length-1){
let node=currentNode.children.find(file=>
file.fileName===fileMessage.fileName&&!file.dirFlag)
node.fileName=newFileMessage.fileName
node.filePath=newFileMessage.filePath
node.dirFlag=newFileMessage.dirFlag
node.children=newFileMessage.children
}
}
let find = currentNode.children.find(file=>file.dirFlag&&file.fileName===fileDirSplit[i]);
if (!isEmpty(find)){
currentNode=find;
}else {
break
}
}
}

View File

@ -24,7 +24,15 @@ export function fileNameFormat(dir,fileName,ext){
export function fileDirFormat(dir,fileName){ export function fileDirFormat(dir,fileName){
return dir+pathOperate.sep+fileName return dir+pathOperate.sep+fileName
} }
export function fileDirFormatArray(dirArray){
// todo
return pathOperate.sep+dirArray.join(pathOperate.sep)
}
export function fullFileNameFormat(dir,fileName){ export function fullFileNameFormat(dir,fileName){
return pathOperate.format({"dir":dir,"base":fileName}) return pathOperate.format({"dir":dir,"base":fileName})
} }
export function filePathSplit(filePath){
return filePath.split(pathOperate.sep)
}