Compare commits

..

No commits in common. "a7a6c52e18fef2ca81541735c43ecae6f5cb144f" and "68b831e1559798862fd2517d85b85631f49ca5a1" have entirely different histories.

65 changed files with 2911 additions and 21178 deletions

1
.gitignore vendored
View File

@ -3,4 +3,3 @@ rpm-4.18.0
out/ out/
ueditor-1.4.3.3/ ueditor-1.4.3.3/
ueditor/ ueditor/
asset-manifest.json

5
.idea/.gitignore vendored
View File

@ -1,5 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/

1
.npmrc Normal file
View File

@ -0,0 +1 @@
registry=https://registry.npm.taobao.org/

View File

@ -1,7 +1,5 @@
const CracoLessPlugin = require('craco-less'); const CracoLessPlugin = require('craco-less');
function resolve(dir) { const HtmlWebpackPlugin=require('html-webpack-plugin')
return path.join(__dirname, dir);
}
const path = require('path'); const path = require('path');
module.exports = { module.exports = {
plugins: [ plugins: [
@ -21,25 +19,10 @@ module.exports = {
configure: (webpackConfig, { env, paths }) => { configure: (webpackConfig, { env, paths }) => {
// 修改output.publicPath为'./' // 修改output.publicPath为'./'
// webpackConfig.output.publicPath = './'; // webpackConfig.output.publicPath = './';
webpackConfig.output.path = path.join(__dirname,"/build"); webpackConfig.output.path = path.join(__dirname,);
webpackConfig.output.publicPath = "./"; webpackConfig.output.publicPath = "";
// webpackConfig.output.module
// .rule("icons")
// .test(/\.svg$/)
// .include.add(resolve("src/icons"))
// .end()
// .use("svg-sprite-loader")
// .loader("svg-sprite-loader")
// .options({
// symbolId: "icon-[name]",
// })
// .end()
return webpackConfig; return webpackConfig;
}, },
alias: {
// 将@/*映射为src目录
'@': path.resolve(__dirname, 'src/'),
},
} }

View File

@ -14,17 +14,16 @@ class UploadUtils {
}); });
static Bucket = 'note-1324909903' static Bucket = 'note-1324909903'
static Region = 'ap-beijing' static Region = 'ap-beijing'
static staticStore
constructor(store) { constructor(store) {
this.store = store; this.store = store;
UploadUtils.staticStore = store;
} }
getActiveFile() { getActiveFile() {
let tableBarItem = JSON.parse(this.store.get("persist:tableBarItem")); let tableBarItem = JSON.parse(this.store.get("persist:tableBarItem"));
if (!tableBarItem) { if (!tableBarItem) {
return; return;
} }
return tableBarItem.activeKey ? JSON.parse(tableBarItem.activeKey) : undefined; return tableBarItem.activeKey ? tableBarItem.activeKey.replaceAll('"', "") : undefined;
} }
/* /*
@ -34,6 +33,7 @@ class UploadUtils {
let dirMessage = JSON.parse(this.store.get("persist:dirMessage")); let dirMessage = JSON.parse(this.store.get("persist:dirMessage"));
let fileMd5 let fileMd5
if (activeFile && dirMessage && dirMessage.data) { if (activeFile && dirMessage && dirMessage.data) {
console.log("dirMessage.data", JSON.parse(dirMessage.data, []))
let find = JSON.parse(dirMessage.data, []).find(file => file.fileId === activeFile || file.filePath === activeFile); let find = JSON.parse(dirMessage.data, []).find(file => file.fileId === activeFile || file.filePath === activeFile);
if (find) { if (find) {
fileMd5 = find.fileMd5; fileMd5 = find.fileMd5;
@ -53,9 +53,8 @@ class UploadUtils {
Bucket: UploadUtils.Bucket, Bucket: UploadUtils.Bucket,
Region: UploadUtils.Region, Region: UploadUtils.Region,
// 不能以 / 开头 // 不能以 / 开头
Key: process.platform==='win32'?activeFile.replaceAll("\\","/"):activeFile Key: activeFile,
}, function (err, data) { }, function (err, data) {
console.log('upLoadFileUtil:',err || data);
if (data && data.ETag) { if (data && data.ETag) {
// 文件存在比较MD5值 // 文件存在比较MD5值
let onlineMd5 = data.ETag.replaceAll('"', "") let onlineMd5 = data.ETag.replaceAll('"', "")
@ -66,11 +65,10 @@ class UploadUtils {
"buttons": ["确认"], "buttons": ["确认"],
"defaultId": 0 "defaultId": 0
}); });
return
} }
}else {
UploadUtils.selfUploadFile(activeFile)
} }
UploadUtils.selfUploadFile(activeFile,fileMd5)
}) })
} }
@ -81,9 +79,8 @@ class UploadUtils {
Bucket: UploadUtils.Bucket, Bucket: UploadUtils.Bucket,
Region: UploadUtils.Region, Region: UploadUtils.Region,
// 不能以 / 开头 // 不能以 / 开头
Key: process.platform==='win32'?activeFile.replaceAll("\\","/"):activeFile, Key: activeFile,
}, function (err, data) { }, function (err, data) {
console.log('downLoadFileUtil:',err || data);
if (data && data.ETag) { if (data && data.ETag) {
// 文件存在比较MD5值 // 文件存在比较MD5值
let onlineMd5 = data.ETag.replaceAll('"', "") let onlineMd5 = data.ETag.replaceAll('"', "")
@ -94,19 +91,19 @@ class UploadUtils {
"buttons": ["确认"], "buttons": ["确认"],
"defaultId": 0 "defaultId": 0
}); });
return
}
} }
}else {
UploadUtils.selfDownLoadFile(activeFile) UploadUtils.selfDownLoadFile(activeFile)
}
}) })
} }
static selfUploadFile(activeFile,fileMd5) { static selfUploadFile(activeFile) {
console.log("cos.uploadFile",activeFile,fileMd5) console.log("cos.uploadFile")
UploadUtils.cos.uploadFile({ UploadUtils.cos.uploadFile({
Bucket: UploadUtils.Bucket, /* 填入您自己的存储桶,必须字段 */ Bucket: UploadUtils.Bucket, /* 填入您自己的存储桶,必须字段 */
Region: UploadUtils.Region, /* 存储桶所在地域,例如 ap-beijing必须字段 */ Region: UploadUtils.Region, /* 存储桶所在地域,例如 ap-beijing必须字段 */
Key: process.platform==='win32'?activeFile.replaceAll("\\","/"):activeFile, /* 存储在桶里的对象键例如1.jpga/b/test.txt必须字段 */ Key: activeFile, /* 存储在桶里的对象键例如1.jpga/b/test.txt必须字段 */
FilePath: activeFile, /* 必须 */ FilePath: activeFile, /* 必须 */
SliceSize: 1024 * 1024 * 5, /* 触发分块上传的阈值超过5MB使用分块上传非必须 */ SliceSize: 1024 * 1024 * 5, /* 触发分块上传的阈值超过5MB使用分块上传非必须 */
onTaskReady: function (taskId) { /* 非必须 */ onTaskReady: function (taskId) { /* 非必须 */
@ -135,7 +132,7 @@ class UploadUtils {
}, },
// 支持自定义headers 非必须 // 支持自定义headers 非必须
}, function (err, data) { }, function (err, data) {
console.log("uploadFile:callback:",err || data); console.log(err || data);
}); });
} }
@ -145,7 +142,7 @@ class UploadUtils {
UploadUtils.cos.getObject({ UploadUtils.cos.getObject({
Bucket: UploadUtils.Bucket, /* 填入您自己的存储桶,必须字段 */ Bucket: UploadUtils.Bucket, /* 填入您自己的存储桶,必须字段 */
Region: UploadUtils.Region, /* 存储桶所在地域,例如 ap-beijing必须字段 */ Region: UploadUtils.Region, /* 存储桶所在地域,例如 ap-beijing必须字段 */
Key: process.platform==='win32'?activeFile.replaceAll("\\","/"):activeFile, /* 存储在桶里的对象键例如1.jpga/b/test.txt必须字段 */ Key: activeFile, /* 存储在桶里的对象键例如1.jpga/b/test.txt必须字段 */
Output: activeFile Output: activeFile
// 支持自定义headers 非必须 // 支持自定义headers 非必须
}, function (err, data) { }, function (err, data) {
@ -164,20 +161,6 @@ class UploadUtils {
"buttons": ["确认"], "buttons": ["确认"],
"defaultId": 0 "defaultId": 0
}) })
// 修改store中Md5值
let persist = UploadUtils.staticStore.get("persist:dirMessage");
if (persist){
let persistObj = JSON.parse(persist)
let data1 = persistObj.data;
console.log("data1",data1,Array.isArray(data1))
let parseArray = JSON.parse(data1, []);
let find =parseArray.find(file => file.fileId === activeFile || file.filePath === activeFile);
if (find) {
find.fileMd5=data.ETag.replaceAll('"',"");
}
persistObj.data=JSON.stringify(parseArray)
UploadUtils.staticStore.set("persist:dirMessage",JSON.stringify(persistObj))
}
} }
}); });
} }
@ -191,7 +174,7 @@ class UploadUtils {
Bucket: UploadUtils.Bucket, Bucket: UploadUtils.Bucket,
Region: UploadUtils.Region, Region: UploadUtils.Region,
// 不能以 / 开头 // 不能以 / 开头
Key: process.platform==='win32'?activeFile.replaceAll("\\","/"):activeFile, Key: activeFile,
}, function (err, data) { }, function (err, data) {
console.log("err || data.CommonPrefixes" + activeFile, err || data); console.log("err || data.CommonPrefixes" + activeFile, err || data);
if (data && data.ETag) { if (data && data.ETag) {
@ -201,30 +184,26 @@ class UploadUtils {
return return
} }
console.log("fileList[0].ETag", onlineMd5) console.log("fileList[0].ETag", onlineMd5)
dialog.showMessageBox({ let number = dialog.showMessageBoxSync({
"message": "云文件已修改是否同步到本地", "message": "云文件已修改是否同步到本地",
"type": "info", "type": "info",
"buttons": ["是", "否"], "buttons": ["是", "否"],
"defaultId": 0 "defaultId": 0
}).then(result=>{ });
let number = result.response
if (number === 0) { if (number === 0) {
UploadUtils.selfDownLoadFile(activeFile) UploadUtils.selfDownLoadFile(activeFile)
} else if (number === 1) { } else if (number === 1) {
dialog.showMessageBox({ if (dialog.showMessageBoxSync({
"message": "是否使用本地文件覆盖远程文件", "message": "是否使用本地文件覆盖远程文件",
"type": "info", "type": "info",
"buttons": ["是", "否"], "buttons": ["是", "否"],
"defaultId": 0 "defaultId": 0
}).then(result=>{ }) === 0) {
if (result.response===0){ UploadUtils.selfUploadFile(activeFile)
UploadUtils.selfUploadFile(activeFile,fileMd5)
} }
})
} }
});
} else { } else {
UploadUtils.selfUploadFile(activeFile,fileMd5) UploadUtils.selfUploadFile(activeFile)
} }
}); });
} }

View File

@ -1,10 +0,0 @@
{
"compilerOptions":{
"baseUrl":"./",
"paths":{
"@/*":[
"src/*"
]
}
}
}

23062
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -5,8 +5,7 @@
"main": "main.js", "main": "main.js",
"author": "hua", "author": "hua",
"license": "MIT", "license": "MIT",
"dependencies": { "devDependencies": {
"@ant-design/icons": "^5.3.7",
"@ant-design/pro-components": "^2.3.57", "@ant-design/pro-components": "^2.3.57",
"@craco/craco": "^6.0.0", "@craco/craco": "^6.0.0",
"@electron-forge/cli": "^6.0.4", "@electron-forge/cli": "^6.0.4",
@ -20,23 +19,15 @@
"@testing-library/jest-dom": "^5.16.5", "@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0", "@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0", "@testing-library/user-event": "^13.5.0",
"antd": "^5.17.0", "antd": "^4.24.8",
"axios": "^1.3.3", "axios": "^1.3.3",
"concurrently": "^4.1.1", "concurrently": "^4.1.1",
"cos-nodejs-sdk-v5": "^2.13.3",
"craco-less": "^2.0.0", "craco-less": "^2.0.0",
"cross-env": "^5.2.0", "cross-env": "^5.2.0",
"electron": "^22.1.0", "electron": "^22.1.0",
"electron-is-dev": "^1.1.0",
"electron-squirrel-startup": "^1.0.0",
"electron-store": "^8.1.0",
"formik": "^2.2.9", "formik": "^2.2.9",
"less": "^4.2.0",
"less-loader": "^12.2.0",
"lexical": "^0.12.6", "lexical": "^0.12.6",
"localStorage": "^1.0.4", "localStorage": "^1.0.4",
"md5": "^2.3.0",
"mousetrap": "^1.6.5",
"nanoid": "^4.0.2", "nanoid": "^4.0.2",
"prop-types": "^15.8.1", "prop-types": "^15.8.1",
"react": "^18.2.0", "react": "^18.2.0",
@ -45,7 +36,6 @@
"react-router-dom": "^6.8.1", "react-router-dom": "^6.8.1",
"react-scripts": "5.0.1", "react-scripts": "5.0.1",
"redux": "^4.2.1", "redux": "^4.2.1",
"redux-persist": "^6.0.0",
"redux-thunk": "^2.4.2", "redux-thunk": "^2.4.2",
"umi-request": "^1.4.0", "umi-request": "^1.4.0",
"wait-on": "^3.3.0", "wait-on": "^3.3.0",
@ -54,24 +44,23 @@
"yjs": ">=13.5.42" "yjs": ">=13.5.42"
}, },
"scripts": { "scripts": {
"dev": "concurrently \"wait-on http://localhost:3000 && electron .\" \"cross-env BROWSER=none npm start\"", "dev": "concurrently \"wait-on http://localhost:3000 && electron-forge start\" \"cross-env BROWSER=none npm start\"",
"start": "craco start --verbose", "start": "craco start",
"build": "craco build", "build": "craco build",
"startel": "electron .", "startel": "electron .",
"package": "electron-forge package", "package": "electron-forge package",
"make": "electron-forge make" "make": "electron-forge make"
}, },
"dependencies": { "dependencies": {
"@ant-design/icons": "^5.3.7",
"cos-nodejs-sdk-v5": "^2.13.3", "cos-nodejs-sdk-v5": "^2.13.3",
"electron-is-dev": "^1.1.0", "electron-is-dev": "^1.1.0",
"electron-squirrel-startup": "^1.0.0", "electron-squirrel-startup": "^1.0.0",
"electron-store": "^8.1.0", "electron-store": "^8.1.0",
"less": "^4.2.0",
"less-loader": "^12.2.0",
"md5": "^2.3.0", "md5": "^2.3.0",
"mousetrap": "^1.6.5", "mousetrap": "^1.6.5",
"redux-persist": "^6.0.0" "node-sass": "^7.0.3",
"redux-persist": "^6.0.0",
"redux-persist-electron-storage": "^2.1.0"
}, },
"browser": { "browser": {
"fs": false "fs": false

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 68 KiB

View File

@ -14,7 +14,7 @@
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" /> <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!-- 应用加壳 --> <!-- 应用加壳 -->
<!-- <link rel="manifest" href="%PUBLIC_URL%/manifest.json" /> --> <!-- <link rel="manifest" href="%PUBLIC_URL%/manifest.json" /> -->
<title>Note</title> <title>送给最亲爱的小宝贝</title>
<!--[if IE]> <!--[if IE]>
<script src="js/html5.js"></script> <script src="js/html5.js"></script>
<![endif]--> <![endif]-->

View File

@ -10,11 +10,4 @@ node version manage
## npm ## npm
node package manage node package manage
## nrm ## nrm
npm remote manage nrm node remote manage
npm install -g nrm
jpg转iconhttps://cn.pic2ico.com/
1. npm build 将react应用打包为html
2. 将打包出来的文件放到根目录下
3. npm package 将项目打包

View File

@ -33,8 +33,8 @@ function App() {
return ( return (
<> <>
{/* 注册路由 */} {/* 注册路由 */}
{/*{element}*/} {element}
<Note/> {/*<Note/>*/}
</> </>
) )

View File

@ -1,6 +1,7 @@
import React from 'react'; import React from 'react';
import {Menu} from 'antd';
import {useDispatch} from "react-redux"; import {useDispatch} from "react-redux";
import {dirRemove} from "@/redux/dirMessage_reducer"; import {dirRemove} from "../../../redux/dirMessage_reducer";
function CloseDir (prop) { function CloseDir (prop) {
console.log("prop",prop) console.log("prop",prop)
@ -8,6 +9,6 @@ function CloseDir (prop) {
const closeDir = ()=>{ const closeDir = ()=>{
dispatch(dirRemove({selectDirKey: prop.filePath})) dispatch(dirRemove({selectDirKey: prop.filePath}))
} }
return <a className="menuItemClick" onClick={closeDir}>关闭目录</a> return <span className="menuItemClick" onClick={closeDir}>关闭目录</span>
} }
export default CloseDir; export default CloseDir;

View File

@ -1,10 +1,10 @@
import React, {useRef, useState} from 'react'; import React, {useRef, useState} from 'react';
import {Input, message, Modal} from 'antd'; import {Input, message, Modal} from 'antd';
import {useDispatch, useSelector} from "react-redux"; import {useDispatch, useSelector} from "react-redux";
import {newDir} from "@/utils/File"; import {newDir} from "../../../utils/File";
import {dirDirAdd} from "@/redux/dirMessage_reducer"; import {dirDirAdd} from "../../../redux/dirMessage_reducer";
import {isEmpty} from "@/utils/ObjectUtils"; import {isEmpty} from "../../../utils/ObjectUtils";
import {fileDirFormat} from "@/utils/PathOperate"; import {fileDirFormat} from "../../../utils/PathOperate";
const DirAddDir = (prop) => { const DirAddDir = (prop) => {
console.log("prop",prop) console.log("prop",prop)
@ -40,7 +40,7 @@ const DirAddDir = (prop) => {
}; };
return <> return <>
{contextHolder} {contextHolder}
<a className="menuItemClick" onClick={showModal}>添加文件夹</a> <span className="menuItemClick" onClick={showModal}>添加文件夹</span>
<Modal title="新建文件夹" open={isModalOpen} onOk={handleOk} onCancel={handleCancel}> <Modal title="新建文件夹" open={isModalOpen} onOk={handleOk} onCancel={handleCancel}>
<Input ref={inputValue} placeholder="文件夹名不能为空" /> <Input ref={inputValue} placeholder="文件夹名不能为空" />
</Modal> </Modal>

View File

@ -1,11 +1,11 @@
import React, {useRef, useState} from 'react'; import React, {useRef, useState} from 'react';
import {Input, message, Modal} from 'antd'; import {Input, message, Modal} from 'antd';
import {useDispatch, useSelector} from "react-redux"; import {useDispatch, useSelector} from "react-redux";
import {newFile} from "@/utils/File"; import {newFile} from "../../../utils/File";
import {dirFileAdd} from "@/redux/dirMessage_reducer"; import {dirFileAdd} from "../../../redux/dirMessage_reducer";
import {addTableBarItem} from "@/redux/tableBarItem_reducer"; import {addTableBarItem} from "../../../redux/tableBarItem_reducer";
import {isEmpty} from "@/utils/ObjectUtils"; import {isEmpty} from "../../../utils/ObjectUtils";
import {fileNameFormat, fullFileNameFormat} from "@/utils/PathOperate"; import {fileNameFormat, fullFileNameFormat} from "../../../utils/PathOperate";
const DirAddFile = (prop) => { const DirAddFile = (prop) => {
console.log("prop",prop) console.log("prop",prop)
@ -47,7 +47,7 @@ const DirAddFile = (prop) => {
}; };
return <> return <>
{contextHolder} {contextHolder}
<a className="menuItemClick" onClick={showModal}>{prop.fileExt}</a> <span className="menuItemClick" onClick={showModal}>{prop.fileExt}</span>
<Modal title="新建文件名" open={isModalOpen} onOk={handleOk} onCancel={handleCancel}> <Modal title="新建文件名" open={isModalOpen} onOk={handleOk} onCancel={handleCancel}>
<Input ref={inputValue} placeholder="文件名不能为空" /> <Input ref={inputValue} placeholder="文件名不能为空" />
</Modal> </Modal>

View File

@ -1,9 +1,9 @@
import React from 'react'; import React from 'react';
import {Popconfirm} from 'antd'; import {Popconfirm} from 'antd';
import {deleteFileAndDir} from "@/utils/File"; import {deleteFileAndDir} from "../../../utils/File";
import {useDispatch, useSelector} from "react-redux"; import {useDispatch, useSelector} from "react-redux";
import {dirFileRemove} from "@/redux/dirMessage_reducer"; import {dirFileRemove} from "../../../redux/dirMessage_reducer";
import {removeTableBarItem, setActiveKey} from "@/redux/tableBarItem_reducer"; import {removeTableBarItem, setActiveKey} from "../../../redux/tableBarItem_reducer";
const DirDeleteFile = (prop) => { const DirDeleteFile = (prop) => {
console.log("prop",prop) console.log("prop",prop)
const dispatch= useDispatch() const dispatch= useDispatch()
@ -47,7 +47,7 @@ const DirDeleteFile = (prop) => {
okText="确认" okText="确认"
cancelText="取消" cancelText="取消"
> >
<a className="menuItemClick">删除文件</a> <span className="menuItemClick">删除文件</span>
</Popconfirm>; </Popconfirm>;
}; };
export default DirDeleteFile; export default DirDeleteFile;

View File

@ -1,6 +0,0 @@
import React from 'react';
import {openInDir} from "@/utils/File"
const OpenInDir = (prop) => {
return <a className="menuItemClick" onClick={()=>openInDir(prop)}>文件夹中打开</a>
};
export default OpenInDir;

View File

@ -6,7 +6,7 @@ const RefreshDir = (prop) => {
prop.refreshDir(prop.filePath) prop.refreshDir(prop.filePath)
}; };
return ( return (
<a className="menuItemClick" onClick={refreshDir}>更新目录</a> <span className="menuItemClick" onClick={refreshDir}>更新目录</span>
); );
}; };
export default RefreshDir; export default RefreshDir;

View File

@ -1,10 +1,10 @@
import React, {useRef, useState} from 'react'; import React, {useRef, useState} from 'react';
import {Input, Menu, Modal} from 'antd'; import {Input, Menu, Modal} from 'antd';
import {updateFileName} from "@/utils/File"; import {updateFileName} from "../../../utils/File";
import {useDispatch} from "react-redux"; import {useDispatch} from "react-redux";
import {updateFileName as updateFileNameRedux} from "../../../redux/dirMessage_reducer"; import {updateFileName as updateFileNameRedux} from "../../../redux/dirMessage_reducer";
import {updateFileName as updateFileNameBar} from "../../../redux/tableBarItem_reducer"; import {updateFileName as updateFileNameBar} from "../../../redux/tableBarItem_reducer";
import {replaceFileNameByFilePath} from "@/utils/PathOperate"; import {replaceFileNameByFilePath} from "../../../utils/PathOperate";
const UpdateFileName = (prop) => { const UpdateFileName = (prop) => {
console.log("prop",prop) console.log("prop",prop)
@ -36,7 +36,7 @@ const UpdateFileName = (prop) => {
}; };
return ( return (
<> <>
<a className="menuItemClick" onClick={showModal}>修改文件名</a> <span className="menuItemClick" onClick={showModal}>修改文件名</span>
<Modal title="修改文件名" open={isModalOpen} onOk={handleOk} onCancel={handleCancel}> <Modal title="修改文件名" open={isModalOpen} onOk={handleOk} onCancel={handleCancel}>
<Input ref={inputValue} placeholder={prop.fileName} /> <Input ref={inputValue} placeholder={prop.fileName} />
</Modal> </Modal>

View File

@ -2,13 +2,13 @@ import React, {Fragment, useEffect, useMemo, useState} from 'react';
import {Input, Menu, Tree} from 'antd'; import {Input, Menu, Tree} from 'antd';
import {FolderOutlined, FileMarkdownOutlined, FileOutlined} from '@ant-design/icons'; import {FolderOutlined, FileMarkdownOutlined, FileOutlined} from '@ant-design/icons';
import "./index.less" import "./index.less"
import {getFileDirByPath, getFileFullNameByPath, getFileNameByPath} from "@/utils/PathOperate"; import {getFileDirByPath, getFileFullNameByPath, getFileNameByPath} from "../../utils/PathOperate";
const {Search} = Input; const {Search} = Input;
import {useSelector, useDispatch} from "react-redux"; import {useSelector, useDispatch} from "react-redux";
import {addExpandedKeys, addTableBarItem, setExpandedKeys} from "@/redux/tableBarItem_reducer"; import {addExpandedKeys, addTableBarItem, setExpandedKeys} from "../../redux/tableBarItem_reducer";
import {readDir} from "@/utils/File"; import {readDir} from "../../utils/File";
import {nextDirAdd,refreshDir as refreshDirReducer} from "../../redux/dirMessage_reducer"; import {nextDirAdd,refreshDir as refreshDirReducer} from "../../redux/dirMessage_reducer";
import {isEmpty} from "@/utils/ObjectUtils"; import {isEmpty} from "../../utils/ObjectUtils";
import UpdateFileName from "./UpdateFileName"; import UpdateFileName from "./UpdateFileName";
import RefreshDir from "./RefreshDir"; import RefreshDir from "./RefreshDir";
import CloseDir from "./CloseDir"; import CloseDir from "./CloseDir";
@ -17,7 +17,7 @@ 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"; import {isArray} from "@craco/craco/lib/utils";
import OpenInDir from "@/components/ItemTree/OpenInDir"; // const defaultData = [];
// //
const dataList = []; const dataList = [];
const generateList = (data) => { const generateList = (data) => {
@ -26,7 +26,7 @@ const generateList = (data) => {
const {key, title, icon} = node; const {key, title, icon} = node;
dataList.push({ dataList.push({
key, key,
"title":title.props.children, title,
icon icon
}); });
if (node.children) { if (node.children) {
@ -34,7 +34,7 @@ const generateList = (data) => {
} }
} }
}; };
// generateList(defaultData);
const getParentKey = (key, tree) => { const getParentKey = (key, tree) => {
let parentKey; let parentKey;
for (let i = 0; i < tree.length; i++) { for (let i = 0; i < tree.length; i++) {
@ -50,6 +50,12 @@ const getParentKey = (key, tree) => {
return parentKey; return parentKey;
}; };
const menuItemClickMap = new Map();
menuItemClickMap.set('1', <DirAddDir/>);
menuItemClickMap.set('b', 2);
menuItemClickMap.set('c', 3);
function generateChildList(fileList) { function generateChildList(fileList) {
const result = [] const result = []
for (let i = 0; i < fileList.length; i++) { for (let i = 0; i < fileList.length; i++) {
@ -164,7 +170,6 @@ const ItemTree = (prop) => {
const [autoExpandParent, setAutoExpandParent] = useState(false); 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));
generateList(defaultValueState);
const [state, setState] = useState(); const [state, setState] = useState();
useEffect(() => { useEffect(() => {
setDefaultValueState(flushTree(prop.filePath)) setDefaultValueState(flushTree(prop.filePath))
@ -185,6 +190,36 @@ const ItemTree = (prop) => {
} }
}) })
} }
const itemTreeAddFile = (dirMessage)=>{
setDefaultValueState(flushTree(dirMessage))
// return
// let newFile = {
// "fileName": getFileFullNameByPath(filePath),
// "filePath": filePath,
// "dirFlag": false,
// "children": []
// }
// //
// let fileDir = getFileDirByPath(filePath)
// let updateValueState = [...prop.filePath]
// updateValueState.forEach(file=>{
// if (fileDir===file.filePath && file.dirFlag){
// file.children=[...file.children,newFile]
// } else if (fileDir.startsWith(file.filePath) && file.dirFlag ){
// treeItemChildAddFile(file.children,newFile,fileDir)
// }
// })
// setDefaultValueState(flushTree(updateValueState))
}
function treeItemChildAddFile(treeItemList,newFile,fileDir){
treeItemList.forEach(file=>{
if (fileDir===file.filePath && file.dirFlag){
file.children=[...file.children,newFile]
} else if (fileDir.startsWith(file.filePath) && file.dirFlag){
treeItemChildAddFile(file.children,newFile,fileDir)
}
})
}
const onChange = (e) => { const onChange = (e) => {
const {value} = e.target; const {value} = e.target;
@ -309,7 +344,7 @@ const ItemTree = (prop) => {
const menuItem = [] const menuItem = []
if (dirFlag){ if (dirFlag){
menuItem.push(getMenuItem('1',<DirAddDir fileDir={key} />)) menuItem.push(getMenuItem('1',<DirAddDir fileDir={key} />))
menuItem.push(getMenuItem('2',<a>添加文件</a>,[ menuItem.push(getMenuItem('2',"添加文件",[
getMenuItem("2-1",<DirAddFile fileDir={key} fileExt=".md"/>), getMenuItem("2-1",<DirAddFile fileDir={key} fileExt=".md"/>),
getMenuItem("2-2",<DirAddFile fileDir={key} fileExt=".lexical"/>)] getMenuItem("2-2",<DirAddFile fileDir={key} fileExt=".lexical"/>)]
),null, 'group' ),null, 'group'
@ -320,7 +355,6 @@ const ItemTree = (prop) => {
menuItem.push(getMenuItem('5',<UpdateFileName fileName={title} filePath={key}/>)) menuItem.push(getMenuItem('5',<UpdateFileName fileName={title} filePath={key}/>))
menuItem.push(getMenuItem('6',<DirDeleteFile filePath={key} />)) menuItem.push(getMenuItem('6',<DirDeleteFile filePath={key} />))
} }
menuItem.push(getMenuItem('7',<OpenInDir filePath={key} />))
return <Fragment> return <Fragment>
{createPortal( {createPortal(
<Menu style={tmpStyle} onClick={e => <Menu style={tmpStyle} onClick={e =>

View File

@ -1,4 +1,4 @@
@import '~antd/dist/reset.css'; @import '~antd/dist/antd.less';
.ant-tree{ .ant-tree{
overflow: auto scroll; overflow: auto scroll;
height: 95.7%; height: 95.7%;

View File

@ -1,4 +1,4 @@
@import '~antd/dist/reset.css'; @import '~antd/dist/antd.less';
#components-grid-demo-playground [class~='ant-col'] { #components-grid-demo-playground [class~='ant-col'] {
background: transparent; background: transparent;

View File

@ -1,5 +1,5 @@
import {useEffect, useLayoutEffect} from 'react'; import {useEffect, useLayoutEffect} from 'react';
import {CAN_USE_DOM} from '@/pages/Note/Hlexical/context/shared/canUseDOM'; import {CAN_USE_DOM} from './canUseDOM';
const useLayoutEffectImpl = CAN_USE_DOM const useLayoutEffectImpl = CAN_USE_DOM
? useLayoutEffect ? useLayoutEffect

View File

@ -1,7 +1,7 @@
import {useCallback, useMemo, useState} from 'react'; import {useCallback, useMemo, useState} from 'react';
import * as React from 'react'; import * as React from 'react';
import Modal from '@/pages/Note/Hlexical/plugins/Input/Modal'; import Modal from '../plugins/Input/Modal';
export default function useModal(){ export default function useModal(){
const [modalContent, setModalContent] = useState(null); const [modalContent, setModalContent] = useState(null);

0
src/pages/Note/Hlexical/images/icons/camera.svg Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 613 B

After

Width:  |  Height:  |  Size: 613 B

View File

Before

Width:  |  Height:  |  Size: 708 B

After

Width:  |  Height:  |  Size: 708 B

0
src/pages/Note/Hlexical/images/icons/clipboard.svg Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 469 B

After

Width:  |  Height:  |  Size: 469 B

0
src/pages/Note/Hlexical/images/icons/code.svg Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 338 B

After

Width:  |  Height:  |  Size: 338 B

0
src/pages/Note/Hlexical/images/icons/download.svg Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 400 B

After

Width:  |  Height:  |  Size: 400 B

0
src/pages/Note/Hlexical/images/icons/gear.svg Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

0
src/pages/Note/Hlexical/images/icons/journal-code.svg Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 742 B

After

Width:  |  Height:  |  Size: 742 B

0
src/pages/Note/Hlexical/images/icons/journal-text.svg Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 729 B

After

Width:  |  Height:  |  Size: 729 B

0
src/pages/Note/Hlexical/images/icons/link.svg Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 376 B

After

Width:  |  Height:  |  Size: 376 B

0
src/pages/Note/Hlexical/images/icons/list-ol.svg Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 956 B

After

Width:  |  Height:  |  Size: 956 B

0
src/pages/Note/Hlexical/images/icons/list-ul.svg Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 423 B

After

Width:  |  Height:  |  Size: 423 B

0
src/pages/Note/Hlexical/images/icons/pencil-fill.svg Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 565 B

After

Width:  |  Height:  |  Size: 565 B

View File

Before

Width:  |  Height:  |  Size: 393 B

After

Width:  |  Height:  |  Size: 393 B

0
src/pages/Note/Hlexical/images/icons/type-bold.svg Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 446 B

After

Width:  |  Height:  |  Size: 446 B

0
src/pages/Note/Hlexical/images/icons/type-h1.svg Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 258 B

After

Width:  |  Height:  |  Size: 258 B

0
src/pages/Note/Hlexical/images/icons/type-h2.svg Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 458 B

After

Width:  |  Height:  |  Size: 458 B

0
src/pages/Note/Hlexical/images/icons/type-h3.svg Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 622 B

After

Width:  |  Height:  |  Size: 622 B

0
src/pages/Note/Hlexical/images/icons/type-h4.svg Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 304 B

0
src/pages/Note/Hlexical/images/icons/type-h5.svg Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 595 B

After

Width:  |  Height:  |  Size: 595 B

0
src/pages/Note/Hlexical/images/icons/type-h6.svg Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

0
src/pages/Note/Hlexical/images/icons/type-italic.svg Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 327 B

After

Width:  |  Height:  |  Size: 327 B

View File

Before

Width:  |  Height:  |  Size: 555 B

After

Width:  |  Height:  |  Size: 555 B

View File

Before

Width:  |  Height:  |  Size: 310 B

After

Width:  |  Height:  |  Size: 310 B

View File

@ -1,41 +1,40 @@
import FirstTheme from "@/pages/Note/Hlexical/themes/FirstTheme"; import FirstTheme from "./themes/FirstTheme";
import {LexicalComposer} from "@lexical/react/LexicalComposer"; import {LexicalComposer} from "@lexical/react/LexicalComposer";
import {RichTextPlugin} from "@lexical/react/LexicalRichTextPlugin"; import {RichTextPlugin} from "@lexical/react/LexicalRichTextPlugin";
import {ContentEditable} from "@lexical/react/LexicalContentEditable"; import {ContentEditable} from "@lexical/react/LexicalContentEditable";
import {HistoryPlugin} from "@lexical/react/LexicalHistoryPlugin"; import {HistoryPlugin} from "@lexical/react/LexicalHistoryPlugin";
import {AutoFocusPlugin} from "@lexical/react/LexicalAutoFocusPlugin"; import {AutoFocusPlugin} from "@lexical/react/LexicalAutoFocusPlugin";
import LexicalErrorBoundary from "@lexical/react/LexicalErrorBoundary"; import LexicalErrorBoundary from "@lexical/react/LexicalErrorBoundary";
import ToolbarPlugin from "@/pages/Note/Hlexical/plugins/ToolbarPlugin"; import ToolbarPlugin from "./plugins/ToolbarPlugin";
import {MarkdownShortcutPlugin} from "@lexical/react/LexicalMarkdownShortcutPlugin"; import {MarkdownShortcutPlugin} from "@lexical/react/LexicalMarkdownShortcutPlugin";
import { import {
TRANSFORMERS, $convertFromMarkdownString, TRANSFORMERS, $convertFromMarkdownString,
} from "@lexical/markdown"; } from "@lexical/markdown";
import "@/pages/Note/Hlexical/index.less" import "./index.less"
import {importFile} from "@/utils/File" import {importFile} from "../../../utils/File"
import {isEmpty} from "@/utils/ObjectUtils"; import {isEmpty} from "../../../utils/ObjectUtils";
import {ListPlugin} from "@lexical/react/LexicalListPlugin"; import {ListPlugin} from "@lexical/react/LexicalListPlugin";
import {LinkPlugin} from "@lexical/react/LexicalLinkPlugin"; import {LinkPlugin} from "@lexical/react/LexicalLinkPlugin";
import AutoLinkPlugin from "@/pages/Note/Hlexical/plugins/AutoLinkPlugin"; import AutoLinkPlugin from "./plugins/AutoLinkPlugin";
import ListMaxIndentLevelPlugin from "@/pages/Note/Hlexical/plugins/ListMaxIndentLevelPlugin"; import ListMaxIndentLevelPlugin from "./plugins/ListMaxIndentLevelPlugin";
import CodeHighlightPlugin from "@/pages/Note/Hlexical/plugins/CodeHighlightPlugin"; import CodeHighlightPlugin from "./plugins/CodeHighlightPlugin";
import ImportFilePlugin from "@/pages/Note/Hlexical/plugins/ImportFilePlugin"; import ImportFilePlugin from "./plugins/ImportFilePlugin";
import SaveFilePlugin from "@/pages/Note/Hlexical/plugins/SaveFilePlugin";
import SaveFilePlugin from "./plugins/SaveFilePlugin";
import {TabIndentationPlugin} from "@lexical/react/LexicalTabIndentationPlugin"; import {TabIndentationPlugin} from "@lexical/react/LexicalTabIndentationPlugin";
import UsefulNodes from "@/pages/Note/Hlexical/nodes/UsefulNodes"; import UsefulNodes from "./nodes/UsefulNodes";
import ImagesPlugin from "@/pages/Note/Hlexical/plugins/ImagesPlugin"; import ImagesPlugin from "./plugins/ImagesPlugin";
import {HorizontalRulePlugin} from "@lexical/react/LexicalHorizontalRulePlugin" import {HorizontalRulePlugin} from "@lexical/react/LexicalHorizontalRulePlugin"
import InlineImagePlugin from "@/pages/Note/Hlexical/plugins/InlineImagePlugin"; import InlineImagePlugin from "./plugins/InlineImagePlugin";
import {TablePlugin} from "@lexical/react/LexicalTablePlugin"; import {TablePlugin} from "@lexical/react/LexicalTablePlugin";
import TableCellActionMenuPlugin from '@/pages/Note/Hlexical/plugins/TableActionMenuPlugin'; import TableCellActionMenuPlugin from './plugins/TableActionMenuPlugin';
import ExcalidrawPlugin from "@/pages/Note/Hlexical/plugins/ExcalidrawPlugin"; import ExcalidrawPlugin from "./plugins/ExcalidrawPlugin";
import TableOfContentsPlugin from "@/pages/Note/Hlexical/plugins/TableOfContentsPlugin"; import TableOfContentsPlugin from "./plugins/TableOfContentsPlugin";
import ContextMenuPlugin from "@/pages/Note/Hlexical/plugins/ContextMenuPlugin" import ContextMenuPlugin from "./plugins/ContextMenuPlugin"
import {Spin,FloatButton } from "antd"; import {Spin} from "antd";
import { CommentOutlined, CustomerServiceOutlined } from '@ant-design/icons';
import {useState} from "react"; import {useState} from "react";
import DragDropPaste from "@/pages/Note/Hlexical/plugins/DragDropPastePlugin";
import TreeViewPlugin from "@/pages/Note/Hlexical/plugins/TreeViewPlugin";
function Placeholder() { function Placeholder() {
return <div className="editor-placeholder">记录一些灵感吧</div>; return <div className="editor-placeholder">记录一些灵感吧</div>;
} }
@ -96,7 +95,7 @@ export default function Hlexical(props) {
{/*markdown 快捷键*/} {/*markdown 快捷键*/}
<MarkdownShortcutPlugin transformers={TRANSFORMERS}/> <MarkdownShortcutPlugin transformers={TRANSFORMERS}/>
{/*图片加载*/} {/*图片加载*/}
<ImagesPlugin captionsEnabled={true}/> <ImagesPlugin/>
<InlineImagePlugin/> <InlineImagePlugin/>
{/*分割线 */} {/*分割线 */}
@ -109,23 +108,11 @@ export default function Hlexical(props) {
<ContextMenuPlugin/> <ContextMenuPlugin/>
{/* 画图 */} {/* 画图 */}
<ExcalidrawPlugin/> <ExcalidrawPlugin/>
{/* 拖拽复制*/}
<DragDropPaste />
<ImportFilePlugin filePath={props.filePath} setSpinningState={setSpinningState}/> <ImportFilePlugin filePath={props.filePath} setSpinningState={setSpinningState}/>
<SaveFilePlugin filePath={props.filePath}/> <SaveFilePlugin filePath={props.filePath}/>
{/*文件操作导入文件*/} {/*文件操作导入文件*/}
{/*<ActionPlugin/>*/} {/*<ActionPlugin/>*/}
<FloatButton.Group
trigger="hover"
type="primary"
style={{
right: 94,
}}
icon={<CustomerServiceOutlined />}
>
<FloatButton />
<FloatButton icon={<CommentOutlined />} />
</FloatButton.Group>
</div> </div>
</div> </div>

View File

@ -225,60 +225,22 @@ h1 {
} }
.editor-heading-h1 { .editor-heading-h1 {
font-size: 50px; font-size: 24px;
color: rgb(5, 5, 5); color: rgb(5, 5, 5);
font-weight: 400; font-weight: 400;
margin: 0; margin: 0;
margin-bottom: 25px; margin-bottom: 12px;
padding: 0; padding: 0;
} }
.editor-heading-h2 { .editor-heading-h2 {
font-size: 45px; font-size: 15px;
//color: rgb(101, 103, 107); color: rgb(101, 103, 107);
//font-weight: 400; font-weight: 700;
color: rgb(5, 5, 5);
font-weight: 400;
margin: 0; margin: 0;
margin-top: 25px; margin-top: 10px;
padding: 0; padding: 0;
//text-transform: uppercase; text-transform: uppercase;
}
.editor-heading-h3 {
font-size: 40px;
color: rgb(5, 5, 5);
font-weight: 400;
margin: 0;
margin-top: 20px;
padding: 0;
//text-transform: uppercase;
}
.editor-heading-h4 {
font-size: 35px;
color: rgb(5, 5, 5);
font-weight: 400;
margin: 0;
margin-top: 20px;
padding: 0;
//text-transform: uppercase;
}
.editor-heading-h5 {
font-size: 30px;
color: rgb(5, 5, 5);
font-weight: 400;
margin: 0;
margin-top: 15px;
padding: 0;
//text-transform: uppercase;
}
.editor-heading-h6 {
font-size: 25px;
color: rgb(5, 5, 5);
font-weight: 400;
margin: 0;
margin-top: 15px;
padding: 0;
//text-transform: uppercase;
} }
.editor-quote { .editor-quote {

View File

@ -1,4 +1,4 @@
import '@/pages/Note/Hlexical/nodes/ImageNode/index.less'; import '../index.less';
import {AutoFocusPlugin} from '@lexical/react/LexicalAutoFocusPlugin'; import {AutoFocusPlugin} from '@lexical/react/LexicalAutoFocusPlugin';
import {useCollaborationContext} from '@lexical/react/LexicalCollaborationContext'; import {useCollaborationContext} from '@lexical/react/LexicalCollaborationContext';
import {CollaborationPlugin} from '@lexical/react/LexicalCollaborationPlugin'; import {CollaborationPlugin} from '@lexical/react/LexicalCollaborationPlugin';
@ -30,25 +30,20 @@ import {Suspense, useCallback, useEffect, useRef, useState} from 'react';
// import {createWebsocketProvider} from '../../../createWebsocketProvider'; // import {createWebsocketProvider} from '../../../createWebsocketProvider';
import {useSharedHistoryContext} from '../../../context/SharedHistoryContext'; import {useSharedHistoryContext} from '../../../context/SharedHistoryContext';
import EmojisPlugin from '@/pages/Note/Hlexical/plugins/EmojisPlugin'; import EmojisPlugin from '../../../plugins/EmojisPlugin';
import KeywordsPlugin from '@/pages/Note/Hlexical/plugins/KeywordsPlugin'; import KeywordsPlugin from '../../../plugins/KeywordsPlugin';
import LinkPlugin from '@/pages/Note/Hlexical/plugins/LinkPlugin'; import LinkPlugin from '../../../plugins/LinkPlugin';
// import MentionsPlugin from '../../../plugins/MentionsPlugin'; // import MentionsPlugin from '../../../plugins/MentionsPlugin';
import TreeViewPlugin from '@/pages/Note/Hlexical/plugins/TreeViewPlugin'; import TreeViewPlugin from '../../../plugins/TreeViewPlugin';
import ContentEditable from '@/pages/Note/Hlexical/plugins/Input/ContentEditable'; import ContentEditable from '../../../plugins/Input/ContentEditable';
import ImageResizer from '@/pages/Note/Hlexical/plugins/Input/ImageResizer'; import ImageResizer from '../../../plugins/Input/ImageResizer';
import Placeholder from '@/pages/Note/Hlexical/plugins/Input/Placeholder'; import Placeholder from '../../../plugins/Input/Placeholder';
import {$isImageNode} from '../index';
import {$isImageNode} from '@/pages/Note/Hlexical/nodes/ImageNode';
import {Image as AntImage} from "antd";
/*
* 缓存图片后期使用预览所有图片
*/
const imageCache = new Set(); const imageCache = new Set();
/*
* 添加图片到缓存列表
*/
function useSuspenseImage(src) { function useSuspenseImage(src) {
if (!imageCache.has(src)) { if (!imageCache.has(src)) {
throw new Promise((resolve) => { throw new Promise((resolve) => {
@ -64,8 +59,7 @@ function useSuspenseImage(src) {
function LazyImage({altText, className, imageRef, src, width, height, maxWidth,}) { function LazyImage({altText, className, imageRef, src, width, height, maxWidth,}) {
useSuspenseImage(src); useSuspenseImage(src);
const [editor] = useLexicalComposerContext(); return (<img
return editor.isEditable()?(<img
className={className || undefined} className={className || undefined}
src={src} src={src}
alt={altText} alt={altText}
@ -74,13 +68,7 @@ function LazyImage({altText, className, imageRef, src, width, height, maxWidth,}
height, maxWidth, width, height, maxWidth, width,
}} }}
draggable="false" draggable="false"
/>):(<AntImage />);
src={src}
alt={altText}
height={height}
width={width}
ref={imageRef}
/>)
} }
export default function ImageComponent({ export default function ImageComponent({
@ -99,7 +87,6 @@ export default function ImageComponent({
const buttonRef = useRef(null); const buttonRef = useRef(null);
const [isSelected, setSelected, clearSelection] = useLexicalNodeSelection(nodeKey); const [isSelected, setSelected, clearSelection] = useLexicalNodeSelection(nodeKey);
const [isResizing, setIsResizing] = useState(false); const [isResizing, setIsResizing] = useState(false);
//
const {isCollabActive} = useCollaborationContext(); const {isCollabActive} = useCollaborationContext();
const [editor] = useLexicalComposerContext(); const [editor] = useLexicalComposerContext();
const [selection, setSelection] = useState(null); const [selection, setSelection] = useState(null);
@ -152,7 +139,6 @@ export default function ImageComponent({
}, [caption, editor, setSelected],); }, [caption, editor, setSelected],);
useEffect(() => { useEffect(() => {
//
let isMounted = true; let isMounted = true;
const unregister = mergeRegister( const unregister = mergeRegister(
editor.registerUpdateListener(({editorState}) => { editor.registerUpdateListener(({editorState}) => {
@ -166,15 +152,12 @@ export default function ImageComponent({
}, COMMAND_PRIORITY_LOW,), }, COMMAND_PRIORITY_LOW,),
editor.registerCommand(CLICK_COMMAND, (payload) => { editor.registerCommand(CLICK_COMMAND, (payload) => {
const event = payload; const event = payload;
console.log("点击图片:",event,isResizing)
if (isResizing) { if (isResizing) {
return true; return true;
} }
if (event.target === imageRef.current) { if (event.target === imageRef.current) {
if (event.ctrlKey){ if (event.shiftKey) {
// ctrl
}else if (event.shiftKey) {
// shift
setSelected(!isSelected); setSelected(!isSelected);
} else { } else {
clearSelection(); clearSelection();
@ -185,7 +168,6 @@ export default function ImageComponent({
return false; return false;
}, COMMAND_PRIORITY_LOW,), }, COMMAND_PRIORITY_LOW,),
//
editor.registerCommand(DRAGSTART_COMMAND, (event) => { editor.registerCommand(DRAGSTART_COMMAND, (event) => {
if (event.target === imageRef.current) { if (event.target === imageRef.current) {
// TODO This is just a temporary workaround for FF to behave like other browsers. // TODO This is just a temporary workaround for FF to behave like other browsers.
@ -209,7 +191,6 @@ export default function ImageComponent({
editor.update(() => { editor.update(() => {
const node = $getNodeByKey(nodeKey); const node = $getNodeByKey(nodeKey);
if ($isImageNode(node)) { if ($isImageNode(node)) {
//
node.setShowCaption(true); node.setShowCaption(true);
} }
}); });

View File

@ -3,7 +3,7 @@ import * as React from 'react';
import {Suspense} from 'react'; import {Suspense} from 'react';
const ImageComponent = React.lazy( const ImageComponent = React.lazy(
() => import('@/pages/Note/Hlexical/nodes/ImageNode/ImageComponent'), () => import('./ImageComponent'),
); );
function convertImageElement(domNode) { function convertImageElement(domNode) {
@ -15,18 +15,17 @@ function convertImageElement(domNode) {
return null; return null;
} }
export class ImageNode extends DecoratorNode { export class ImageNode extends DecoratorNode {
//
__src; __src;
__altText; __altText;
//
__width; __width;
__height; __height;
__maxWidth; __maxWidth;
//
__showCaption; __showCaption;
__caption; __caption;
__captionsEnabled; __captionsEnabled;
static getType() { static getType() {
return 'image'; return 'image';
} }
@ -155,7 +154,6 @@ export class ImageNode extends DecoratorNode {
} }
decorate() { decorate() {
console.log('ImageNode.decorate()')
return ( return (
<Suspense fallback={null}> <Suspense fallback={null}>
<ImageComponent <ImageComponent
@ -178,7 +176,7 @@ export class ImageNode extends DecoratorNode {
export function $createImageNode({ export function $createImageNode({
altText, altText,
height, height,
maxWidth = 600, maxWidth = 500,
captionsEnabled, captionsEnabled,
src, src,
width, width,

View File

@ -41,236 +41,3 @@
.image-control-wrapper--resizing { .image-control-wrapper--resizing {
touch-action: none; touch-action: none;
} }
.editor-container span.editor-image {
cursor: default;
display: inline-block;
position: relative;
user-select: none;
}
.editor-container .editor-image img {
max-width: 200%;
cursor: default;
}
.editor-container .editor-image img.focused {
outline: 2px solid rgb(60, 132, 244);
user-select: none;
}
.editor-container .editor-image img.focused.draggable {
cursor: grab;
}
.editor-container .editor-image img.focused.draggable:active {
cursor: grabbing;
}
.editor-container .editor-image .image-caption-container .tree-view-output {
margin: 0;
border-radius: 0;
}
.editor-container .editor-image .image-caption-container {
display: block;
position: absolute;
bottom: 4px;
left: 0;
right: 0;
padding: 0;
margin: 0;
border-top: 1px solid #fff;
background-color: rgba(255, 255, 255, 0.9);
min-width: 100px;
color: #000;
overflow: hidden;
}
.editor-container .editor-image .image-caption-button {
display: block;
position: absolute;
bottom: 20px;
left: 0;
right: 0;
width: 30%;
padding: 10px;
margin: 0 auto;
border: 1px solid rgba(255, 255, 255, 0.3);
border-radius: 5px;
background-color: rgba(0, 0, 0, 0.5);
min-width: 100px;
color: #fff;
cursor: pointer;
user-select: none;
}
.editor-container .editor-image .image-caption-button:hover {
background-color: rgba(60, 132, 244, 0.5);
}
.editor-container .editor-image .image-edit-button {
border: 1px solid rgba(0, 0, 0, 0.3);
border-radius: 5px;
background-image: url(../../images/icons/pencil-fill.svg);
background-size: 16px;
background-position: center;
background-repeat: no-repeat;
width: 35px;
height: 35px;
vertical-align: -0.25em;
position: absolute;
right: 4px;
top: 4px;
cursor: pointer;
user-select: none;
}
.editor-container .editor-image .image-edit-button:hover {
background-color: rgba(60, 132, 244, 0.1);
}
.editor-container .editor-image .image-resizer {
display: block;
width: 7px;
height: 7px;
position: absolute;
background-color: rgb(60, 132, 244);
border: 1px solid #fff;
}
.editor-container .editor-image .image-resizer.image-resizer-n {
top: -6px;
left: 48%;
cursor: n-resize;
}
.editor-container .editor-image .image-resizer.image-resizer-ne {
top: -6px;
right: -6px;
cursor: ne-resize;
}
.editor-container .editor-image .image-resizer.image-resizer-e {
bottom: 48%;
right: -6px;
cursor: e-resize;
}
.editor-container .editor-image .image-resizer.image-resizer-se {
bottom: -2px;
right: -6px;
cursor: nwse-resize;
}
.editor-container .editor-image .image-resizer.image-resizer-s {
bottom: -2px;
left: 48%;
cursor: s-resize;
}
.editor-container .editor-image .image-resizer.image-resizer-sw {
bottom: -2px;
left: -6px;
cursor: sw-resize;
}
.editor-container .editor-image .image-resizer.image-resizer-w {
bottom: 48%;
left: -6px;
cursor: w-resize;
}
.editor-container .editor-image .image-resizer.image-resizer-nw {
top: -6px;
left: -6px;
cursor: nw-resize;
}
.editor-container span.inline-editor-image {
cursor: default;
display: inline-block;
position: relative;
z-index: 1;
}
.editor-container .inline-editor-image img {
max-width: 200%;
cursor: default;
}
.editor-container .inline-editor-image img.focused {
outline: 2px solid rgb(60, 132, 244);
}
.editor-container .inline-editor-image img.focused.draggable {
cursor: grab;
}
.editor-container .inline-editor-image img.focused.draggable:active {
cursor: grabbing;
}
.editor-container .inline-editor-image .image-caption-container .tree-view-output {
margin: 0;
border-radius: 0;
}
.editor-container .inline-editor-image.position-full {
margin: 1em 0 1em 0;
}
.editor-container .inline-editor-image.position-left {
float: left;
width: 50%;
margin: 1em 1em 0 0;
}
.editor-container .inline-editor-image.position-right {
float: right;
width: 50%;
margin: 1em 0 0 1em;
}
.editor-container .inline-editor-image .image-edit-button {
display: block;
position: absolute;
top: 12px;
right: 12px;
padding: 6px 8px;
margin: 0 auto;
border: 1px solid rgba(255, 255, 255, 0.3);
border-radius: 5px;
background-color: rgba(0, 0, 0, 0.5);
min-width: 60px;
color: #fff;
cursor: pointer;
user-select: none;
}
.editor-container .inline-editor-image .image-edit-button:hover {
background-color: rgba(60, 132, 244, 0.5);
}
.editor-container .inline-editor-image .image-caption-container {
display: block;
background-color: #f4f4f4;
min-width: 100%;
color: #000;
overflow: hidden;
}
.editor-container .editor-image img.focused.draggable {
cursor: grab;
}
.editor-container .editor-image img.focused.draggable:active {
cursor: grabbing;
}
.editor-container .inline-editor-image img.focused.draggable {
cursor: grab;
}
.editor-container .inline-editor-image img.focused.draggable:active {
cursor: grabbing;
}

View File

@ -100,7 +100,7 @@ export default function ContextMenuPlugin(){
const items = await navigator.clipboard.read(); const items = await navigator.clipboard.read();
const item = items[0]; const item = items[0];
console.log("navigator.clipboard.read:item",item)
const permission = await navigator.permissions.query({ const permission = await navigator.permissions.query({
// @ts-expect-error These types are incorrect. // @ts-expect-error These types are incorrect.
name: 'clipboard-read', name: 'clipboard-read',
@ -109,7 +109,7 @@ export default function ContextMenuPlugin(){
alert('Not allowed to paste from clipboard.'); alert('Not allowed to paste from clipboard.');
return; return;
} }
// image/png
for (const type of item.types) { for (const type of item.types) {
const dataString = await (await item.getType(type)).text(); const dataString = await (await item.getType(type)).text();
data.setData(type, dataString); data.setData(type, dataString);

View File

@ -1,43 +0,0 @@
import {useLexicalComposerContext} from '@lexical/react/LexicalComposerContext';
import {DRAG_DROP_PASTE} from '@lexical/rich-text';
import {isMimeType, mediaFileReader} from '@lexical/utils';
import {COMMAND_PRIORITY_LOW} from 'lexical';
import {useEffect} from 'react';
import {INSERT_IMAGE_COMMAND} from '../ImagesPlugin';
const ACCEPTABLE_IMAGE_TYPES = [
'image/',
'image/heic',
'image/heif',
'image/gif',
'image/webp',
];
export default function DragDropPaste() {
const [editor] = useLexicalComposerContext();
useEffect(() => {
return editor.registerCommand(
DRAG_DROP_PASTE,
(files) => {
(async () => {
const filesResult = await mediaFileReader(
files,
[ACCEPTABLE_IMAGE_TYPES].flatMap((x) => x),
);
for (const {file, result} of filesResult) {
if (isMimeType(file, ACCEPTABLE_IMAGE_TYPES)) {
editor.dispatchCommand(INSERT_IMAGE_COMMAND, {
altText: file.name,
src: result,
});
}
}
})();
return true;
},
COMMAND_PRIORITY_LOW,
);
}, [editor]);
return null;
}

View File

@ -30,34 +30,33 @@ import {DialogActions, DialogButtonsList} from '../Input/Dialog';
import FileInput from '../Input/FileInput'; import FileInput from '../Input/FileInput';
import TextInput from '../Input/TextInput'; import TextInput from '../Input/TextInput';
import {Button} from "antd"; import {Button} from "antd";
export const INSERT_IMAGE_COMMAND = export const INSERT_IMAGE_COMMAND =
createCommand('INSERT_IMAGE_COMMAND'); createCommand('INSERT_IMAGE_COMMAND');
/**
* 插入路径图片对话框
* @param onClick
* @returns {Element}
* @constructor
*/
export function InsertImageUriDialogBody({ export function InsertImageUriDialogBody({
onClick, onClick,
}) { }) {
const [src, setSrc] = useState(''); const [src, setSrc] = useState('');
const [altText, setAltText] = useState(''); const [altText, setAltText] = useState('');
const [resizable,setResizable] = useState(true);
const isDisabled = src === ''; const isDisabled = src === '';
return ( return (
<> <>
<TextInput <TextInput
label="文件url" label="Image URL"
placeholder="例如:https://tenfei03.cfp.cn/creative/vcg/800/new/VCG41175510742.jpg" placeholder="i.e. https://source.unsplash.com/random"
onChange={setSrc} onChange={setSrc}
value={src} value={src}
data-test-id="image-modal-url-input" data-test-id="image-modal-url-input"
/> />
<TextInput <TextInput
label="图片描述" label="Alt Text"
placeholder="例如:风景" placeholder="Random unsplash image"
onChange={setAltText} onChange={setAltText}
value={altText} value={altText}
data-test-id="image-modal-alt-text-input" data-test-id="image-modal-alt-text-input"
@ -66,7 +65,7 @@ export function InsertImageUriDialogBody({
<Button <Button
data-test-id="image-modal-confirm-btn" data-test-id="image-modal-confirm-btn"
disabled={isDisabled} disabled={isDisabled}
onClick={() => onClick({altText, src,resizable})}> onClick={() => onClick({altText, src})}>
确认 确认
</Button> </Button>
</DialogActions> </DialogActions>
@ -74,18 +73,14 @@ export function InsertImageUriDialogBody({
); );
} }
/**
* 插入上传文件对话框
* @param onClick
* @returns {Element}
* @constructor
*/
export function InsertImageUploadedDialogBody({ export function InsertImageUploadedDialogBody({
onClick, onClick,
}) { }) {
const [src, setSrc] = useState(''); const [src, setSrc] = useState('');
const [altText, setAltText] = useState(''); const [altText, setAltText] = useState('');
const isDisabled = src === ''; const isDisabled = src === '';
const loadImage = (files) => { const loadImage = (files) => {
const reader = new FileReader(); const reader = new FileReader();
reader.onload = function () { reader.onload = function () {
@ -126,13 +121,6 @@ export function InsertImageUploadedDialogBody({
); );
} }
/**
* 插入文件对话框
* @param activeEditor
* @param onClose
* @returns {Element}
* @constructor
*/
export function InsertImageDialog({ export function InsertImageDialog({
activeEditor, activeEditor,
onClose, onClose,
@ -178,12 +166,6 @@ export function InsertImageDialog({
); );
} }
/**
* 图片插件
* @param captionsEnabled
* @returns {null}
* @constructor
*/
export default function ImagesPlugin({captionsEnabled,}){ export default function ImagesPlugin({captionsEnabled,}){
const [editor] = useLexicalComposerContext(); const [editor] = useLexicalComposerContext();
@ -232,10 +214,7 @@ export default function ImagesPlugin({captionsEnabled,}){
return null; return null;
} }
/**
* 拖拽图标
* @type {string}
*/
const TRANSPARENT_IMAGE = const TRANSPARENT_IMAGE =
'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'; 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';
const img = document.createElement('img'); const img = document.createElement('img');

View File

@ -86,18 +86,15 @@ const SaveFilePlugin=(props)=> {
// 后期不再读取文件直接读取文件MD5 // 后期不再读取文件直接读取文件MD5
importFile(filePath).then(value => { importFile(filePath).then(value => {
let save =true; let save
let oldFileMd5 let newFileMd5
let newFileMd5 =md5(resultSave)
if (!isEmpty(value)){
if (props.filePath.endsWith(".md")){ if (props.filePath.endsWith(".md")){
// editorState // editorState
oldFileMd5 = md5(value.toString()); newFileMd5 = md5(value.toString());
save = (isEmpty(value)) || newFileMd5 !== oldFileMd5; save = (isEmpty(value)) || md5(resultSave) !== newFileMd5;
}else { }else {
oldFileMd5 = md5(JSON.stringify(JSON.parse(value.toString()))); newFileMd5 = md5(JSON.stringify(JSON.parse(value.toString())));
save = (isEmpty(value)) || newFileMd5 !== oldFileMd5; save = (isEmpty(value)) || md5(resultSave) !== newFileMd5;
}
} }
if (save) { if (save) {
overWriteFile(filePath, resultSave).then(()=>{ overWriteFile(filePath, resultSave).then(()=>{

View File

@ -54,7 +54,7 @@
flex-direction: row; flex-direction: row;
justify-content: flex-start; justify-content: flex-start;
z-index: 1; z-index: 1;
height: 100vh; height: 300px;
} }
.first-heading { .first-heading {
@ -70,7 +70,7 @@
padding: 0; padding: 0;
overflow: scroll; overflow: scroll;
width: 200px; width: 200px;
height: 100vh; height: 220px;
overflow-x: hidden; overflow-x: hidden;
overflow-y: auto; overflow-y: auto;
-ms-overflow-style: none; /* IE and Edge */ -ms-overflow-style: none; /* IE and Edge */
@ -85,7 +85,7 @@
.headings::before { .headings::before {
content: ' '; content: ' ';
position: absolute; position: absolute;
height: 100vh; height: 220px;
width: 4px; width: 4px;
right: 240px; right: 240px;
margin-top: 5px; margin-top: 5px;

View File

@ -39,41 +39,49 @@ import {
getDefaultCodeLanguage, getDefaultCodeLanguage,
getCodeLanguages getCodeLanguages
} from "@lexical/code"; } from "@lexical/code";
import DropDown, {DropDownItem} from "@/pages/Note/Hlexical/plugins/Input/DropDown"; import DropDown, {DropDownItem} from "./Input/DropDown";
import {InsertImageDialog} from "@/pages/Note/Hlexical/plugins/ImagesPlugin"; import {InsertImageDialog} from "./ImagesPlugin";
import useModal from "@/pages/Note/Hlexical/hook/userModal"; import useModal from "../hook/userModal";
import {InsertTableDialog} from "@/pages/Note/Hlexical/plugins/TablePlugin"; import {InsertTableDialog} from "./TablePlugin";
import {INSERT_HORIZONTAL_RULE_COMMAND} from "@lexical/react/LexicalHorizontalRuleNode"; import {INSERT_HORIZONTAL_RULE_COMMAND} from "@lexical/react/LexicalHorizontalRuleNode";
import {InsertInlineImageDialog} from "@/pages/Note/Hlexical/plugins/InlineImagePlugin"; import {InsertInlineImageDialog} from "./InlineImagePlugin";
import {INSERT_EXCALIDRAW_COMMAND} from "@/pages/Note/Hlexical/plugins/ExcalidrawPlugin"; import {INSERT_EXCALIDRAW_COMMAND} from "./ExcalidrawPlugin";
const LowPriority = 1; const LowPriority = 1;
// 支持的块类型
const supportedBlockTypes = new Set(["paragraph", "quote", "code", "h1", "h2", "h3", "h4", "h5", "h6", "ul", "ol" const supportedBlockTypes = new Set([
"paragraph",
"quote",
"code",
"h1",
"h2",
"h3",
"h4",
"h5",
"h6",
"ul",
"ol"
]); ]);
// 块类型对应的名称
const blockTypeToBlockName = {code: "代码块", const blockTypeToBlockName = {
h1: "一级标题", h2: "二级标题", h3: "三级标题", h4: "四级标题", h5: "五级标题", h6: "六级标题", code: "代码块",
ol: "有序序列", ul: "无序序列", h1: "一级标题",
h2: "二级标题",
h3: "三级标题",
h4: "四级标题",
h5: "五级标题",
h6: "六级标题",
ol: "有序序列",
paragraph: "普通文本", paragraph: "普通文本",
quote: "引用", quote: "引用",
ul: "无序序列"
}; };
/**
* 工具栏分割符
* @returns {JSX.Element}
* @constructor
*/
function Divider() { function Divider() {
return <div className="divider"/>; return <div className="divider"/>;
} }
/**
* 位置计算
* @param editor
* @param rect
*/
function positionEditorElement(editor, rect) { function positionEditorElement(editor, rect) {
if (rect === null) { if (rect === null) {
editor.style.opacity = "0"; editor.style.opacity = "0";
@ -88,12 +96,6 @@ function positionEditorElement(editor, rect) {
} }
} }
/**
* 浮动连接设置
* @param editor
* @returns {JSX.Element}
* @constructor
*/
function FloatingLinkEditor({editor}) { function FloatingLinkEditor({editor}) {
const editorRef = useRef(null); const editorRef = useRef(null);
const inputRef = useRef(null); const inputRef = useRef(null);
@ -234,15 +236,6 @@ function FloatingLinkEditor({editor}) {
); );
} }
/**
* 下拉选择
* @param onChange
* @param className
* @param options
* @param value
* @returns {JSX.Element}
* @constructor
*/
function Select({onChange, className, options, value}) { function Select({onChange, className, options, value}) {
return ( return (
<select className={className} onChange={onChange} value={value}> <select className={className} onChange={onChange} value={value}>
@ -259,7 +252,6 @@ function Select({onChange, className, options, value}) {
function getSelectedNode(selection) { function getSelectedNode(selection) {
const anchor = selection.anchor; const anchor = selection.anchor;
const focus = selection.focus; const focus = selection.focus;
console.log('selection',anchor,focus)
const anchorNode = selection.anchor.getNode(); const anchorNode = selection.anchor.getNode();
const focusNode = selection.focus.getNode(); const focusNode = selection.focus.getNode();
if (anchorNode === focusNode) { if (anchorNode === focusNode) {
@ -383,7 +375,6 @@ function BlockOptionsDropdownList({
}; };
const formatCode = () => { const formatCode = () => {
console.log('blockType !== "code"',blockType)
if (blockType !== "code") { if (blockType !== "code") {
editor.update(() => { editor.update(() => {
const selection = $getSelection(); const selection = $getSelection();
@ -457,7 +448,6 @@ export default function ToolbarPlugin() {
const [isUnderline, setIsUnderline] = useState(false); const [isUnderline, setIsUnderline] = useState(false);
const [isStrikethrough, setIsStrikethrough] = useState(false); const [isStrikethrough, setIsStrikethrough] = useState(false);
const [isCode, setIsCode] = useState(false); const [isCode, setIsCode] = useState(false);
const [isEditable, setIsEditable] = useState(() => editor.isEditable());
const updateToolbar = useCallback(() => { const updateToolbar = useCallback(() => {
const selection = $getSelection(); const selection = $getSelection();
@ -538,7 +528,7 @@ export default function ToolbarPlugin() {
); );
}, [editor, updateToolbar]); }, [editor, updateToolbar]);
const codeLanguages = useMemo(() => getCodeLanguages(), []); const codeLanguges = useMemo(() => getCodeLanguages(), []);
const onCodeLanguageSelect = useCallback( const onCodeLanguageSelect = useCallback(
(e) => { (e) => {
editor.update(() => { editor.update(() => {
@ -564,18 +554,7 @@ export default function ToolbarPlugin() {
return ( return (
<div className="toolbar" ref={toolbarRef}> <div className="toolbar" ref={toolbarRef}>
<button <button
onClick={() => { disabled={!canUndo}
editor.setEditable(!isEditable)
setIsEditable(!isEditable)
}}
className={"toolbar-item spaced " + (isBold ? "active" : "")}
aria-label="Format Bold"
>
{isEditable?'阅读':'编辑'}
</button>
<Divider/>
<button
disabled={!canUndo||!isEditable}
onClick={() => { onClick={() => {
editor.dispatchCommand(UNDO_COMMAND); editor.dispatchCommand(UNDO_COMMAND);
}} }}
@ -585,7 +564,7 @@ export default function ToolbarPlugin() {
<i className="format undo"/> <i className="format undo"/>
</button> </button>
<button <button
disabled={!canRedo||!isEditable} disabled={!canRedo}
onClick={() => { onClick={() => {
editor.dispatchCommand(REDO_COMMAND); editor.dispatchCommand(REDO_COMMAND);
}} }}
@ -598,7 +577,6 @@ export default function ToolbarPlugin() {
{supportedBlockTypes.has(blockType) && ( {supportedBlockTypes.has(blockType) && (
<> <>
<button <button
disabled={!isEditable}
className="toolbar-item block-controls" className="toolbar-item block-controls"
onClick={() => onClick={() =>
setShowBlockOptionsDropDown(!showBlockOptionsDropDown) setShowBlockOptionsDropDown(!showBlockOptionsDropDown)
@ -627,7 +605,7 @@ export default function ToolbarPlugin() {
<Select <Select
className="toolbar-item code-language" className="toolbar-item code-language"
onChange={onCodeLanguageSelect} onChange={onCodeLanguageSelect}
options={codeLanguages} options={codeLanguges}
value={codeLanguage} value={codeLanguage}
/> />
<i className="chevron-down inside"/> <i className="chevron-down inside"/>

View File

@ -9,8 +9,7 @@ const firstTheme = {
h2: "editor-heading-h2", h2: "editor-heading-h2",
h3: "editor-heading-h3", h3: "editor-heading-h3",
h4: "editor-heading-h4", h4: "editor-heading-h4",
h5: "editor-heading-h5", h5: "editor-heading-h5"
h6: "editor-heading-h6"
}, },
list: { list: {
nested: { nested: {

View File

@ -2,12 +2,12 @@ import React, {useRef, useState} from 'react';
import { import {
UserOutlined, UserOutlined,
} from '@ant-design/icons'; } from '@ant-design/icons';
import {Layout, Avatar, Tabs} from 'antd'; import {Layout, Avatar, Tabs, Button} from 'antd';
import Hlexical from '@/pages/Note/Hlexical'; import Hlexical from './Hlexical';
import ItemTree from "@/components/ItemTree"; import ItemTree from "../../components/ItemTree";
import '@/pages/Note/index.less' import './index.less'
import {useSelector, useDispatch} from "react-redux"; import {useSelector, useDispatch} from "react-redux";
import {addTableBarItem, removeTableBarItem, setActiveKey,editLeftTableOfContents} from "@/redux/tableBarItem_reducer" import {addTableBarItem, removeTableBarItem, setActiveKey,editLeftTableOfContents} from "../../redux/tableBarItem_reducer"
const {Sider} = Layout; const {Sider} = Layout;
const Note = () => { const Note = () => {

View File

@ -28,12 +28,3 @@
#itemTreeTabs .ant-tabs-tab-btn{ #itemTreeTabs .ant-tabs-tab-btn{
width: 100%; width: 100%;
} }
.ant-tabs-nav .ant-tabs-nav-add,
/* 显示新增标签按钮 */
.ant-tabs-nav-operations {
display: inline-block;
}
/* 隐藏触发隐藏操作按钮的样式 */
.ant-tabs-nav-operations-hidden {
display: none !important;
}

View File

@ -0,0 +1,57 @@
import { Button,InputNumber,message } from 'antd'
import React, { Component } from 'react'
import axios from 'axios'
import HistoryRecord from '../../components/HistoryRecord'
import { connect } from 'react-redux';
import { historyRecordSync } from '../../redux/historyRecord_reducer';
class SyncContext extends Component {
state={size:1}
eidtSyncContextSize=(event)=>{
this.setState({size:event})
}
historySync=(data)=>{
console.info("historySync(data)",data)
this.props.historyRecordSync(data)
}
syncContext = () => {
const key = 'SYNC_CONTEXT';
message.loading({content:'Loading...',key,duration:0});
axios.get(`/ticai/sync/context/${this.state.size}`)
.then(response => {
const result = response.data;
if (result.status.code === 200) {
console.log(result.data.length)
message.destroy(key)
message.success({
content: "成功同步"+result.data.length+"条",
duration: 2,
})
this.historySync(result.data)
} else {
message.destroy(key)
message.error(result.status.message)
}
})
.catch(function (error) {
message.destroy(key)
message.error(error)
})
}
render() {
return (
<div>
<span>同步最近</span><InputNumber min={1} max={10000} defaultValue={this.state.size} onChange={this.eidtSyncContextSize}/>条数据,
<Button onClick={this.syncContext}>确认</Button>.
<hr/>
<HistoryRecord/>
</div>
)
}
}
export default connect(
null,
// state => ({
// }),//
{historyRecordSync}//
)(SyncContext)

View File

@ -3,7 +3,7 @@ import historyReducer from './historyRecord_reducer'
import dirMessageReducer from './dirMessage_reducer' import dirMessageReducer from './dirMessage_reducer'
import pushHotkeysReducer from "./pushHotkeys_reducer"; import pushHotkeysReducer from "./pushHotkeys_reducer";
import tableBarItemReducer from "./tableBarItem_reducer"; import tableBarItemReducer from "./tableBarItem_reducer";
import {electronStorage} from "@/utils/LocalStorage"; import {electronStorage} from "../utils/LocalStorage";
import { persistStore, persistReducer } from 'redux-persist' import { persistStore, persistReducer } from 'redux-persist'
// 持久化配置 // 持久化配置
const historyRecordPersistConfig = { const historyRecordPersistConfig = {

View File

@ -1,15 +1,15 @@
// const {createProxyMiddleware} = require('http-proxy-middleware') const {createProxyMiddleware} = require('http-proxy-middleware')
// module.exports=function(app){ module.exports=function(app){
// app.use( app.use(
// createProxyMiddleware('/ticai',{ createProxyMiddleware('/ticai',{
// target:'http://localhost:8090/', target:'http://localhost:8090/',
// changeOrigin:false, changeOrigin:false,
// pathRewrite:{'^/ticai':''} pathRewrite:{'^/ticai':''}
// }), }),
// createProxyMiddleware('/oauth',{ createProxyMiddleware('/oauth',{
// target:'http://localhost:1112', target:'http://localhost:1112',
// changeOrigin:true, changeOrigin:true,
// pathRewrite:{'^/oauth':''} pathRewrite:{'^/oauth':''}
// }) })
// ) )
// } }

View File

@ -1,5 +1,5 @@
const fs = window.require("fs").promises const fs = window.require("fs").promises
const {ipcRenderer,dialog} = window.require('electron') const {ipcRenderer} = window.require('electron')
const pathOp = window.require("path") const pathOp = window.require("path")
export async function readDir(filePath){ export async function readDir(filePath){
const files = await fs.readdir(filePath); const files = await fs.readdir(filePath);
@ -52,7 +52,3 @@ export async function updateFileName(oldFileName,newFileName){
export async function saveFileWithName(){ export async function saveFileWithName(){
return ipcRenderer.invoke("saveFileWithName" ) return ipcRenderer.invoke("saveFileWithName" )
} }
export async function openInDir(filePath){
return dialog.showOpenDialog({defaultPath:"filePath",properties: ['openDirectory']} )
}