Compare commits

..

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

20 changed files with 1767 additions and 6360 deletions

1
.env
View File

@ -1 +0,0 @@
NODE_ENV=development

View File

@ -1,4 +1,7 @@
const CracoLessPlugin = require('craco-less');
function resolve(dir) {
return path.join(__dirname, dir);
}
const path = require('path');
module.exports = {
plugins: [
@ -15,17 +18,11 @@ module.exports = {
},
],
webpack: {
entry: {
main: ['whatwg-fetch', './src/index.js'],
},
configure: (webpackConfig, { env, paths }) => {
// 修改output.publicPath为'./'
// webpackConfig.output.publicPath = './';
// webpackConfig.output.path = path.join(__dirname,"/build");
// webpackConfig.output.publicPath = "./";
webpackConfig.output.path = path.join(__dirname,);
webpackConfig.output.publicPath = "";
webpackConfig.output.path = path.join(__dirname,"/build");
webpackConfig.output.publicPath = "./";
// webpackConfig.output.module
// .rule("icons")
// .test(/\.svg$/)
@ -43,12 +40,7 @@ module.exports = {
// 将@/*映射为src目录
'@': path.resolve(__dirname, 'src/'),
},
// 确保入口文件正确
// entry: {
// main: ['whatwg-fetch', './src/index.js'],
// },
},
devServer: {
port: 3008, // 设置端口
},
}
};

View File

@ -20,10 +20,6 @@ class UploadUtils {
UploadUtils.staticStore = store;
}
getActiveFile() {
let persist = this.store.get("persist:tableBarItem");
if (persist === undefined){
return undefined
}
let tableBarItem = JSON.parse(this.store.get("persist:tableBarItem"));
if (!tableBarItem) {
return;

19
main.js
View File

@ -1,4 +1,4 @@
const {app, Menu, BrowserWindow,ipcMain,dialog,shell } = require('electron')
const {app, Menu, BrowserWindow,ipcMain,dialog} = require('electron')
const path = require('path')
const {menuRebuild} = require('./elsrc/TopMenu.js')
const UploadUtils = require("./elsrc/sync/tencent/UploadUtils")
@ -15,24 +15,21 @@ const createWindow = () => {
nodeIntegration: true,
// 启用后nodeIntegration会无效
contextIsolation: false,
// 添加预加载脚本
// __dirname 字符串指向当前正在执行脚本的路径
// path.join API 将多个路径联结在一起,创建一个跨平台的路径字符串。
preload: path.join(__dirname, 'preload.js')
}
})
console.log("isDev", isDev)
if (isDev){
// 加载 index.html
win.loadURL('http://localhost:3008')
win.loadURL('http://localhost:3000')
// 打开开发工具
win.webContents.openDevTools()
}else {
// 加载 index.html
win.loadFile('./index.html')
}
win.maximize()
// let okPush =false
let devToolPush = false
win.webContents.on('before-input-event', (event, input) => {
console.log("input.type.toLowerCase()", input)
if (input.control && input.key.toLowerCase() === 's' && input.type.toLowerCase() === "keydown" && input.isAutoRepeat === false) {
@ -43,7 +40,7 @@ const createWindow = () => {
event.preventDefault()
}
// console.log('Pressed ',input.key)
if (input.key.toUpperCase() === 'F5' && input.isAutoRepeat === false) {
if (input.key.toUpperCase() === 'F5' && input.type.toLowerCase() === "keydown" && input.isAutoRepeat === false) {
win.reload()
}
if (input.key.toUpperCase() === 'F12' && input.type.toLowerCase() === "keydown" && input.isAutoRepeat === false) {
@ -93,12 +90,6 @@ app.whenReady().then(() => {
console.log("electronStoreDelete")
return store.delete(args)
})
ipcMain.handle("showOpenDialog",(listen,args)=>{
console.log("showOpenDialog:"+args)
// return dialog.showOpenDialog({defaultPath:args.filePath,
// properties: ['openFile']} )
return shell.openPath(args)
})
console.log("配置文件地址",app.getPath('userData')+"/config.json")
console.log("操作系统:"+process.platform)
})

6787
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +1,14 @@
{
"name": "assistant-note",
"name": "my-electron-app",
"version": "1.0.0",
"description": "note",
"description": "Hello World!",
"main": "main.js",
"author": "hua",
"license": "MIT",
"devDependencies": {
"dependencies": {
"@ant-design/icons": "^5.3.7",
"@ant-design/pro-components": "^2.3.57",
"@craco/craco": "^6.4.5",
"@craco/craco": "^6.0.0",
"@electron-forge/cli": "^6.0.4",
"@electron-forge/maker-deb": "^6.0.4",
"@electron-forge/maker-rpm": "^6.0.4",
@ -54,10 +54,10 @@
"yjs": ">=13.5.42"
},
"scripts": {
"dev": "concurrently \"wait-on --log http://127.0.0.1:3008 && electron .\" \"cross-env BROWSER=none npm start\"",
"dev": "concurrently \"wait-on http://localhost:3000 && electron .\" \"cross-env BROWSER=none npm start\"",
"start": "craco start --verbose",
"build": "craco build",
"startel": "set NODE_ENV=development&&electron .",
"startel": "electron .",
"package": "electron-forge package",
"make": "electron-forge make"
},

View File

@ -1,4 +1,3 @@
// 通过预加载脚本从渲染器访问Node.js
// 预加载脚本 在上下文隔离渲染器进程中导入 Node.js 和 Electron 模块的概念
// 所有的 Node.js API接口 都可以在 preload 进程中被调用.
// 它拥有与Chrome扩展一样的沙盒。

View File

@ -4,7 +4,7 @@
<head>
<meta charset="utf-8" />
<!-- %PUBLIC_URL% public 文件夹 -->
<link rel="icon" href="favicon.ico" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<!-- 移动端网页适配 -->
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- 配置浏览器页签+地址颜色,仅适用于android -->
@ -15,7 +15,11 @@
<!-- 应用加壳 -->
<!-- <link rel="manifest" href="%PUBLIC_URL%/manifest.json" /> -->
<title>Note</title>
<!-- <script src="index.jsx"></script>-->
<!--[if IE]>
<script src="js/html5.js"></script>
<![endif]-->
<script src="index.jsx"></script>
</head>
<body>

View File

@ -1,4 +1,4 @@
import React, {Fragment, useId} from 'react';
import React, {useId} from 'react';
import routes from './routes'
import {Outlet, useNavigate, useRoutes} from 'react-router-dom'
import useIpcRenderer from '../src/utils/useIpcRenderer'
@ -31,11 +31,11 @@ function App() {
useIpcRenderer({'openDirectory':addNewDir})
// useIpcRenderer({'pushHotkeys':pushHotkeysAction})
return (
<Fragment>
<>
{/* 注册路由 */}
{/*{element}*/}
<Note/>
</Fragment>
</>
)
}

View File

@ -166,7 +166,6 @@ const ItemTree = (prop) => {
const [defaultValueState, setDefaultValueState] = useState(flushTree(prop.filePath));
generateList(defaultValueState);
const [state, setState] = useState();
const [inFrame, setInFrame] = useState(true);
useEffect(() => {
setDefaultValueState(flushTree(prop.filePath))
}, [prop]);
@ -295,18 +294,7 @@ const ItemTree = (prop) => {
});
}
const getNodeTreeRightClickMenu = () => {
useEffect(() => {
const handleKeyDown = (event) => {
if (!inFrame) {
event.preventDefault(); //
setState("");
}
};
document.addEventListener('click', handleKeyDown);
return () => {
document.removeEventListener('click', handleKeyDown);
};
});
console.log("state", state, isEmpty(state))
if (isEmpty(state)) {
return
}
@ -333,7 +321,6 @@ const ItemTree = (prop) => {
menuItem.push(getMenuItem('6',<DirDeleteFile filePath={key} />))
}
menuItem.push(getMenuItem('7',<OpenInDir filePath={key} />))
return <Fragment>
{createPortal(
<Menu style={tmpStyle} onClick={e =>
@ -341,18 +328,7 @@ const ItemTree = (prop) => {
console.log('onClick',e)
}
}
//
onMouseLeave={e => {
console.log('onMouseLeave',e)
// setState("");
setInFrame(false)
}}
//
onMouseEnter={e => {
console.log('onMouseEnter',e)
// setState("");
setInFrame(true)
}}
onMouseLeave={e => {setState("");}}
items={menuItem}>
</Menu>,
document.body

View File

@ -1,6 +1,6 @@
@import '~antd/dist/reset.css';
.ant-tree{
overflow: auto;
overflow: auto scroll;
height: 95.7%;
}
.ant-tree-node-content-wrapper {

View File

@ -8,7 +8,7 @@ import { BrowserRouter } from 'react-router-dom';
import {PersistGate} from "redux-persist/integration/react";
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
// <React.StrictMode>
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<BrowserRouter>
@ -16,5 +16,5 @@ root.render(
</BrowserRouter>
</PersistGate>
</Provider>
</React.StrictMode>
// </React.StrictMode>
);

View File

@ -11,7 +11,6 @@ import {
TRANSFORMERS, $convertFromMarkdownString,
} from "@lexical/markdown";
import "@/pages/Note/Hlexical/index.less"
import "@/pages/Note/Hlexical/theme.less"
import {importFile} from "@/utils/File"
import {isEmpty} from "@/utils/ObjectUtils";
@ -32,12 +31,11 @@ import TableCellActionMenuPlugin from '@/pages/Note/Hlexical/plugins/TableAction
import ExcalidrawPlugin from "@/pages/Note/Hlexical/plugins/ExcalidrawPlugin";
import TableOfContentsPlugin from "@/pages/Note/Hlexical/plugins/TableOfContentsPlugin";
import ContextMenuPlugin from "@/pages/Note/Hlexical/plugins/ContextMenuPlugin"
import {Spin, FloatButton} from "antd";
import {CommentOutlined, CustomerServiceOutlined} from '@ant-design/icons';
import {Spin,FloatButton } from "antd";
import { CommentOutlined, CustomerServiceOutlined } from '@ant-design/icons';
import {useState} from "react";
import DragDropPaste from "@/pages/Note/Hlexical/plugins/DragDropPastePlugin";
import TreeViewPlugin from "@/pages/Note/Hlexical/plugins/TreeViewPlugin";
function Placeholder() {
return <div className="editor-placeholder">记录一些灵感吧</div>;
}
@ -50,38 +48,34 @@ export default function Hlexical(props) {
},
nodes: UsefulNodes
};
const [spinningState, setSpinningState] = useState(!isEmpty(props.filePath))
const [spinningState,setSpinningState]=useState(!isEmpty(props.filePath))
console.log("Hlexical(props):this.props.filePath:", props.filePath)
if (!isEmpty(props.filePath) && props.filePath.endsWith(".md")) {
if (!isEmpty(props.filePath)&&props.filePath.endsWith(".md")){
let promise = importFile(props.filePath);
promise.then(value => {
if (isEmpty(value)) {
setSpinningState(false)
return
}
editorConfig = {
...editorConfig,
editorState: () => $convertFromMarkdownString(value.toString(), TRANSFORMERS)
}
editorConfig={...editorConfig,editorState: () => $convertFromMarkdownString(value.toString(), TRANSFORMERS)}
setSpinningState(false)
}).catch(error =>
console.error(error)
)
}
return (
// <Spin size="large" fullscreen="ture" spinning={spinningState}>
<LexicalComposer initialConfig={editorConfig}>
<div className="editor-container">
{/* 富文本插件 */}
<ToolbarPlugin/>
<div className="editor-inner">
<Spin size="large" fullscreen="ture" spinning={spinningState}>
<RichTextPlugin
contentEditable={<ContentEditable className="editor-input"/>}
placeholder={<Placeholder/>}
ErrorBoundary={LexicalErrorBoundary}
/>
/> </Spin>
<HistoryPlugin/>
{/*黑窗口动态记录当前操作*/}
{/*<TreeViewPlugin/>*/}
@ -116,7 +110,7 @@ export default function Hlexical(props) {
{/* 画图 */}
<ExcalidrawPlugin/>
{/* 拖拽复制*/}
<DragDropPaste/>
<DragDropPaste />
<ImportFilePlugin filePath={props.filePath} setSpinningState={setSpinningState}/>
<SaveFilePlugin filePath={props.filePath}/>
{/*文件操作导入文件*/}
@ -127,13 +121,15 @@ export default function Hlexical(props) {
style={{
right: 94,
}}
icon={<CustomerServiceOutlined/>}>
<FloatButton/>
<FloatButton icon={<CommentOutlined/>}/>
icon={<CustomerServiceOutlined />}
>
<FloatButton />
<FloatButton icon={<CommentOutlined />} />
</FloatButton.Group>
</div>
</div>
</LexicalComposer>
// </Spin>
);
}

View File

@ -55,11 +55,16 @@ h1 {
border-top-right-radius: 10px;
height: 100%;
}
.toolbar {
height: 4.9%;
margin-bottom: 0.1%
}
.editor-inner {
background: #fff;
position: relative;
margin:20px;
height: 90%;
height: 95%;
overflow: hidden auto;
}
@ -88,6 +93,38 @@ h1 {
pointer-events: none;
}
.editor-text-bold {
font-weight: bold;
}
.editor-text-italic {
font-style: italic;
}
.editor-text-underline {
text-decoration: underline;
}
.editor-text-strikethrough {
text-decoration: line-through;
}
.editor-text-underlineStrikethrough {
text-decoration: underline line-through;
}
.editor-text-code {
background-color: rgb(240, 242, 245);
padding: 1px 0.25rem;
font-family: Menlo, Consolas, Monaco, monospace;
font-size: 94%;
}
.editor-link {
color: rgb(33, 111, 219);
text-decoration: none;
}
.tree-view-output {
display: block;
background: #222;
@ -104,6 +141,177 @@ h1 {
line-height: 14px;
}
.editor-code {
background-color: rgb(240, 242, 245);
font-family: Menlo, Consolas, Monaco, monospace;
display: block;
padding: 8px 8px 8px 52px;
line-height: 1.53;
font-size: 13px;
margin: 0;
margin-top: 8px;
margin-bottom: 8px;
tab-size: 2;
white-space: pre;
overflow: auto;
position: relative;
}
.editor-code:before {
content: attr(data-gutter);
position: absolute;
background-color: #eee;
left: 0;
top: 0;
border-right: 1px solid #ccc;
padding: 8px;
color: #777;
white-space: pre-wrap;
text-align: right;
min-width: 25px;
}
.editor-code:after {
content: attr(data-highlight-language);
top: 0;
right: 3px;
padding: 3px;
font-size: 10px;
text-transform: uppercase;
position: absolute;
color: rgba(0, 0, 0, 0.5);
}
.editor-tokenComment {
color: slategray;
}
.editor-tokenPunctuation {
color: #999;
}
.editor-tokenProperty {
color: #905;
}
.editor-tokenSelector {
color: #690;
}
.editor-tokenOperator {
color: #9a6e3a;
}
.editor-tokenAttr {
color: #07a;
}
.editor-tokenVariable {
color: #e90;
}
.editor-tokenFunction {
color: #dd4a68;
}
.editor-paragraph {
margin: 0;
margin-bottom: 8px;
position: relative;
}
.editor-paragraph:last-child {
margin-bottom: 0;
}
.editor-heading-h1 {
font-size: 50px;
color: rgb(5, 5, 5);
font-weight: 400;
margin: 0;
margin-bottom: 25px;
padding: 0;
}
.editor-heading-h2 {
font-size: 45px;
//color: rgb(101, 103, 107);
//font-weight: 400;
color: rgb(5, 5, 5);
font-weight: 400;
margin: 0;
margin-top: 25px;
padding: 0;
//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 {
margin: 0;
margin-left: 20px;
font-size: 15px;
color: rgb(101, 103, 107);
border-left-color: rgb(206, 208, 212);
border-left-width: 4px;
border-left-style: solid;
padding-left: 16px;
}
.editor-list-ol {
padding: 0;
margin: 0;
margin-left: 16px;
}
.editor-list-ul {
padding: 0;
margin: 0;
margin-left: 16px;
}
.editor-listitem {
margin: 8px 32px 8px 32px;
}
.editor-nested-listitem {
list-style-type: none;
}
pre::-webkit-scrollbar {
background: transparent;
width: 10px;
@ -181,9 +389,6 @@ pre::-webkit-scrollbar-thumb {
}
.toolbar {
margin-left: 20px;
margin-right: 20px;
height: 46px;
display: flex;
margin-bottom: 1px;
background: #fff;
@ -609,6 +814,143 @@ i.justify-align {
background-image: url(images/icons/justify.svg);
}
.editor-table {
border-collapse: collapse;
border-spacing: 0;
overflow-y: scroll;
overflow-x: scroll;
table-layout: fixed;
width: max-content;
margin: 30px 0;
}
.editor-tableSelection *::selection {
background-color: transparent;
}
.editor-tableSelected {
outline: 2px solid rgb(60, 132, 244);
}
.editor-tableCell {
border: 1px solid #bbb;
width: 75px;
min-width: 75px;
vertical-align: top;
text-align: start;
padding: 6px 8px;
position: relative;
outline: none;
}
.editor-tableCellSortedIndicator {
display: block;
opacity: 0.5;
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 4px;
background-color: #999;
}
.editor-tableCellResizer {
position: absolute;
right: -4px;
height: 100%;
width: 8px;
cursor: ew-resize;
z-index: 10;
top: 0;
}
.editor-tableCellHeader {
background-color: #f2f3f5;
text-align: start;
}
.editor-tableCellSelected {
background-color: #c9dbf0;
}
.editor-tableCellPrimarySelected {
border: 2px solid rgb(60, 132, 244);
display: block;
height: calc(100% - 2px);
position: absolute;
width: calc(100% - 2px);
left: -1px;
top: -1px;
z-index: 2;
}
.editor-tableCellEditing {
box-shadow: 0 0 5px rgba(0, 0, 0, 0.4);
border-radius: 3px;
}
.editor-tableAddColumns {
position: absolute;
top: 0;
width: 20px;
background-color: #eee;
height: 100%;
right: -25px;
animation: table-controls 0.2s ease;
border: 0;
cursor: pointer;
}
.editor-tableAddColumns:after {
background-image: url(images/icons/plus.svg);
background-size: contain;
background-position: center;
background-repeat: no-repeat;
display: block;
content: ' ';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0.4;
}
.editor-tableAddColumns:hover {
background-color: #c9dbf0;
}
.editor-tableAddRows {
position: absolute;
bottom: -25px;
width: calc(100% - 25px);
background-color: #eee;
height: 20px;
left: 0;
animation: table-controls 0.2s ease;
border: 0;
cursor: pointer;
}
.editor-tableAddRows:after {
background-image: url(images/icons/plus.svg);
background-size: contain;
background-position: center;
background-repeat: no-repeat;
display: block;
content: ' ';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0.4;
}
.editor-tableAddRows:hover {
background-color: #c9dbf0;
}
@keyframes table-controls {
0% {
opacity: 0;
@ -618,4 +960,37 @@ i.justify-align {
}
}
.editor-tableCellResizeRuler {
display: block;
position: absolute;
width: 1px;
background-color: rgb(60, 132, 244);
height: 100%;
top: 0;
}
.editor-tableCellActionButtonContainer {
display: block;
right: 5px;
top: 6px;
position: absolute;
z-index: 4;
width: 20px;
height: 20px;
}
.editor-tableCellActionButton {
background-color: #eee;
display: block;
border: 0;
border-radius: 20px;
width: 20px;
height: 20px;
color: #222;
cursor: pointer;
}
.editor-tableCellActionButton:hover {
background-color: #ddd;
}

View File

@ -1,31 +1,30 @@
import {useLexicalComposerContext} from "@lexical/react/LexicalComposerContext";
import {useEffect, useState} from "react";
import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
import {Fragment, useEffect, useState} from "react";
import {importFile, overWriteFile, saveFileWithName} from "../../../../utils/File";
import {isEmpty} from "../../../../utils/ObjectUtils";
import {TRANSFORMERS, $convertToMarkdownString,} from "@lexical/markdown";
import {CLEAR_HISTORY_COMMAND} from "lexical";
import {TRANSFORMERS, $convertFromMarkdownString, $convertToMarkdownString,} from "@lexical/markdown";
import {getFileExtByPath, getFileFullNameByPath, getFileNameByPath} from "../../../../utils/PathOperate";
import {updatedSavedFile} from "../../../../redux/tableBarItem_reducer";
import {useDispatch, useSelector} from "react-redux";
import md5 from "md5"
import {message} from "antd";
const {ipcRenderer} = window.require('electron')
import "./ToobarPlugin.less"
import {newFileAdd, updateFileMd5} from "../../../../redux/dirMessage_reducer";
const SaveFilePlugin = (props) => {
const SaveFilePlugin=(props)=> {
let activeKey = useSelector(state => state.tableBarItem.activeKey);
const dispatch = useDispatch();
// const [messageApi,contextHolder] = message.useMessage();
const [editor] = useLexicalComposerContext();
const [editorState, setEditorState] = useState();
const [editorState,setEditorState]=useState();
function onChange(editorState) {
if (!isEmpty(props.filePath) && props.filePath.endsWith(".md")) {
if (!isEmpty(props.filePath)&&props.filePath.endsWith(".md")){
let read = editorState.read(() => $convertToMarkdownString(TRANSFORMERS));
setEditorState(read)
} else {
}else {
// Call toJSON on the EditorState object, which produces a serialization safe string
const editorStateJSON = editorState.toJSON();
console.log('onChange-editorStateJSON')
@ -40,11 +39,11 @@ const SaveFilePlugin = (props) => {
return
}
let filePath = props.filePath;
if (!isEmpty(filePath) && filePath !== activeKey) {
if (!isEmpty(filePath)&&filePath !== activeKey) {
console.log("文件不同", filePath, activeKey)
return;
}
console.log("触发保存filePath:", editorState,filePath)
console.log("触发保存filePath:", filePath)
if (isEmpty(editorState)) {
return
}
@ -57,14 +56,14 @@ const SaveFilePlugin = (props) => {
console.log("saveDialogReturnValuePromise", saveDialogReturnValuePromise)
saveDialogReturnValuePromise.then(result => {
if (!result.canceled) {
let filePath = result.filePath
let filePath =result.filePath
let fileExt = getFileExtByPath(result.filePath)
if (isEmpty(fileExt)) {
filePath = filePath + ".lexical"
if (isEmpty(fileExt)){
filePath = filePath+".lexical"
}
if (filePath.endsWith(".md")) {
resultSave = editorState
} else {
if (filePath.endsWith(".md")){
resultSave=editorState
}else {
const editorStateSave = {"editorState": JSON.parse(editorState)};
resultSave = JSON.stringify(editorStateSave);
}
@ -72,41 +71,39 @@ const SaveFilePlugin = (props) => {
// 修改当前文件名
dispatch(updatedSavedFile({filePath: filePath}))
// 文件目录更新
dispatch(newFileAdd({
fileName: getFileFullNameByPath(filePath), dirFlag: false, children: [], filePath: filePath,
fileId: filePath, fileMd5: md5(resultSave)
}))
dispatch(newFileAdd({fileName:getFileFullNameByPath(filePath),dirFlag:false,children:[],filePath: filePath,
fileId:filePath,fileMd5:md5(resultSave)}))
}
})
return
}
if (props.filePath.endsWith(".md")) {
resultSave = editorState
} else {
if (props.filePath.endsWith(".md")){
resultSave=editorState
}else {
const editorStateSave = {"editorState": JSON.parse(editorState)};
resultSave = JSON.stringify(editorStateSave);
}
// 后期不再读取文件直接读取文件MD5
importFile(filePath).then(value => {
let save = true;
let save =true;
let oldFileMd5
let newFileMd5 = md5(resultSave)
if (!isEmpty(value)) {
if (props.filePath.endsWith(".md")) {
let newFileMd5 =md5(resultSave)
if (!isEmpty(value)){
if (props.filePath.endsWith(".md")){
// editorState
oldFileMd5 = md5(value.toString());
save = (isEmpty(value)) || newFileMd5 !== oldFileMd5;
} else {
}else {
oldFileMd5 = md5(JSON.stringify(JSON.parse(value.toString())));
save = (isEmpty(value)) || newFileMd5 !== oldFileMd5;
}
}
if (save) {
overWriteFile(filePath, resultSave).then(() => {
console.log("保存成功" + filePath)
overWriteFile(filePath, resultSave).then(()=>{
console.log("保存成功"+ filePath)
// 修改文件Md5
dispatch(updateFileMd5({filePath, "fileMd5": newFileMd5}))
dispatch(updateFileMd5({filePath,"fileMd5":newFileMd5}))
// messageApi.open({type:"success",content:"保存成功:" + filePath,duration:1})
message.success("保存成功:" + filePath)
})
@ -119,7 +116,7 @@ const SaveFilePlugin = (props) => {
useEffect(() => {
ipcRenderer.on("pushHotkeys", saveFile);
let updateListener = editor.registerUpdateListener(({editorState}) => {
console.log("SaveFilePlugin:editorState", editorState)
console.log("SaveFilePlugin:editorState",editorState)
onChange(editorState);
})
return () => {
@ -127,7 +124,7 @@ const SaveFilePlugin = (props) => {
updateListener()
ipcRenderer.removeListener("pushHotkeys", saveFile)
};
}, [editor, onChange]
},[editor,onChange]
)
}
export default SaveFilePlugin

View File

@ -1,371 +0,0 @@
.editor-text-bold {
font-weight: bold;
}
.editor-text-italic {
font-style: italic;
}
.editor-text-underline {
text-decoration: underline;
}
.editor-text-strikethrough {
text-decoration: line-through;
}
.editor-text-underlineStrikethrough {
text-decoration: underline line-through;
}
.editor-text-code {
background-color: rgb(240, 242, 245);
padding: 1px 0.25rem;
font-family: Menlo, Consolas, Monaco, monospace;
font-size: 94%;
}
.editor-link {
color: rgb(33, 111, 219);
text-decoration: none;
}
.editor-code {
background-color: rgb(240, 242, 245);
font-family: Menlo, Consolas, Monaco, monospace;
display: block;
padding: 8px 8px 8px 52px;
line-height: 1.53;
font-size: 13px;
margin: 0;
margin-top: 8px;
margin-bottom: 8px;
tab-size: 2;
white-space: pre;
overflow: auto;
position: relative;
}
.editor-code:before {
content: attr(data-gutter);
position: absolute;
background-color: #eee;
left: 0;
top: 0;
border-right: 1px solid #ccc;
padding: 8px;
color: #777;
white-space: pre-wrap;
text-align: right;
min-width: 25px;
}
.editor-code:after {
content: attr(data-highlight-language);
top: 0;
right: 3px;
padding: 3px;
font-size: 10px;
text-transform: uppercase;
position: absolute;
color: rgba(0, 0, 0, 0.5);
}
.editor-tokenComment {
color: slategray;
}
.editor-tokenPunctuation {
color: #999;
}
.editor-tokenProperty {
color: #905;
}
.editor-tokenSelector {
color: #690;
}
.editor-tokenOperator {
color: #9a6e3a;
}
.editor-tokenAttr {
color: #07a;
}
.editor-tokenVariable {
color: #e90;
}
.editor-tokenFunction {
color: #dd4a68;
}
.editor-paragraph {
margin: 0;
margin-bottom: 8px;
position: relative;
}
.editor-paragraph:last-child {
margin-bottom: 0;
}
.editor-heading-h1 {
//font-size: 50px;
//color: rgb(5, 5, 5);
//font-weight: 400;
//margin: 0;
//margin-bottom: 25px;
//padding: 0;
}
.editor-heading-h2 {
//font-size: 45px;
//color: rgb(101, 103, 107);
//font-weight: 400;
//color: rgb(5, 5, 5);
//font-weight: 400;
//margin: 0;
//margin-top: 25px;
//padding: 0;
//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 {
margin: 0;
margin-left: 20px;
font-size: 15px;
color: rgb(101, 103, 107);
border-left-color: rgb(206, 208, 212);
border-left-width: 4px;
border-left-style: solid;
padding-left: 16px;
}
.editor-list-ol {
padding: 0;
margin: 0;
margin-left: 16px;
}
.editor-list-ul {
padding: 0;
margin: 0;
margin-left: 16px;
}
.editor-listitem {
margin: 8px 32px 8px 32px;
}
.editor-nested-listitem {
list-style-type: none;
}
.editor-table {
border-collapse: collapse;
border-spacing: 0;
overflow-y: scroll;
overflow-x: scroll;
table-layout: fixed;
width: max-content;
margin: 30px 0;
}
.editor-tableSelection *::selection {
background-color: transparent;
}
.editor-tableSelected {
outline: 2px solid rgb(60, 132, 244);
}
.editor-tableCell {
border: 1px solid #bbb;
width: 75px;
min-width: 75px;
vertical-align: top;
text-align: start;
padding: 6px 8px;
position: relative;
outline: none;
}
.editor-tableCellSortedIndicator {
display: block;
opacity: 0.5;
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 4px;
background-color: #999;
}
.editor-tableCellResizer {
position: absolute;
right: -4px;
height: 100%;
width: 8px;
cursor: ew-resize;
z-index: 10;
top: 0;
}
.editor-tableCellHeader {
background-color: #f2f3f5;
text-align: start;
}
.editor-tableCellSelected {
background-color: #c9dbf0;
}
.editor-tableCellPrimarySelected {
border: 2px solid rgb(60, 132, 244);
display: block;
height: calc(100% - 2px);
position: absolute;
width: calc(100% - 2px);
left: -1px;
top: -1px;
z-index: 2;
}
.editor-tableCellEditing {
box-shadow: 0 0 5px rgba(0, 0, 0, 0.4);
border-radius: 3px;
}
.editor-tableAddColumns {
position: absolute;
top: 0;
width: 20px;
background-color: #eee;
height: 100%;
right: -25px;
animation: table-controls 0.2s ease;
border: 0;
cursor: pointer;
}
.editor-tableAddColumns:after {
background-image: url(images/icons/plus.svg);
background-size: contain;
background-position: center;
background-repeat: no-repeat;
display: block;
content: ' ';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0.4;
}
.editor-tableAddColumns:hover {
background-color: #c9dbf0;
}
.editor-tableAddRows {
position: absolute;
bottom: -25px;
width: calc(100% - 25px);
background-color: #eee;
height: 20px;
left: 0;
animation: table-controls 0.2s ease;
border: 0;
cursor: pointer;
}
.editor-tableAddRows:after {
background-image: url(images/icons/plus.svg);
background-size: contain;
background-position: center;
background-repeat: no-repeat;
display: block;
content: ' ';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0.4;
}
.editor-tableAddRows:hover {
background-color: #c9dbf0;
}
.editor-tableCellResizeRuler {
display: block;
position: absolute;
width: 1px;
background-color: rgb(60, 132, 244);
height: 100%;
top: 0;
}
.editor-tableCellActionButtonContainer {
display: block;
right: 5px;
top: 6px;
position: absolute;
z-index: 4;
width: 20px;
height: 20px;
}
.editor-tableCellActionButton {
background-color: #eee;
display: block;
border: 0;
border-radius: 20px;
width: 20px;
height: 20px;
color: #222;
cursor: pointer;
}
.editor-tableCellActionButton:hover {
background-color: #ddd;
}

View File

@ -20,9 +20,9 @@ const Note = () => {
const newTabIndex = useRef(0);
const activeKey=useSelector(state => state.tableBarItem.activeKey);
const itemList = useSelector(state => state.tableBarItem.data)
const items = useSelector(state => state.tableBarItem.data)
let filePath = useSelector(state => state.dirMessage.dirTree);
console.log("itemList",itemList)
const itemTreeTab=[
{
key: '1',
@ -84,39 +84,30 @@ const Note = () => {
return (
<Layout>
{/*<Sider margin='5' collapsedWidth={0} collapsed="true">*/}
{/* <div>*/}
{/* <Avatar size={60} src='http://localhost/20231114150555.jpg' icon={<UserOutlined/>}/>*/}
{/* </div>*/}
{/* <div>*/}
{/* <p style={{color: colorBgContainer, 'fontSize': 60}}>上善若水</p>*/}
{/* </div>*/}
{/*</Sider>*/}
<Sider margin='5' collapsedWidth={0} collapsed="true">
<div>
<Avatar size={60} src='http://localhost/20231114150555.jpg' icon={<UserOutlined/>}/>
</div>
<div>
<p style={{color: colorBgContainer, 'fontSize': 60}}>上善若水</p>
</div>
</Sider>
<Sider trigger={null} collapsedWidth={0} width="300px" collapsible collapsed={collapsed}
style={{overflow:"hidden"}}
// style={{overflow:"auto"}}
>
{/* 文件 标题 */}
<Tabs id="itemTreeTabs"
defaultActiveKey={useSelector(state => state.tableBarItem.leftTableOfContents)}
items={itemTreeTab}
<Tabs id="itemTreeTabs" defaultActiveKey={useSelector(state => state.tableBarItem.leftTableOfContents)} items={itemTreeTab}
onChange={onChangeLeftTableOfContents}
style ={{background:"#fff",width:'100%'}}
style ={{background:"#fff"}}
/>
</Sider>
<Layout>
<Tabs
id="layout-note"
type="editable-card"
onChange={onChange}
activeKey={activeKey}
onEdit={onEdit}
items={itemList.map(item=>{
return {
label:item.label,
children: <div className="HlexicalName"><Hlexical filePath={item.children}/></div>,
key:item.key
}
items={items.map(item=>{
return {label:item.label,children: <div className="HlexicalName"><Hlexical filePath={item.children}/></div>,key:item.key}
})}
/>
</Layout>

View File

@ -1,6 +1,3 @@
.ant-layout .ant-layout-has-sider .css-dev-only-do-not-override-1okl62o{
overflow: hidden;
}
.HlexicalName {
// 顶上有标题设置100h后下面会多处一部分
height: 100%;
@ -13,15 +10,11 @@
margin: 0;
height: 100%;
}
#layout-note .ant-tabs-nav{
//width: calc(100% - 300px);
margin: 0px 20px;
}
#itemTreeTabs .ant-tabs-nav {
height: 60px;
#itemTreeTabs .ant-tabs-nav{
height: 6%;
}
#itemTreeTabs .ant-tabs-content-holder{
height: calc (100%-60px);
height: 94%;
}
#itemTreeTabs .ant-tabs-tab{
margin: 0;
@ -35,12 +28,12 @@
#itemTreeTabs .ant-tabs-tab-btn{
width: 100%;
}
//.ant-tabs-nav .ant-tabs-nav-add,
///* 显示新增标签按钮 */
//.ant-tabs-nav-operations {
// display: inline-block;
//}
.ant-tabs-nav .ant-tabs-nav-add,
/* 显示新增标签按钮 */
.ant-tabs-nav-operations {
display: inline-block;
}
/* 隐藏触发隐藏操作按钮的样式 */
//.ant-tabs-nav-operations-hidden {
// display: none !important;
//}
.ant-tabs-nav-operations-hidden {
display: none !important;
}

View File

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

View File

@ -54,7 +54,5 @@ export async function saveFileWithName(){
}
export async function openInDir(filePath){
// return dialog.showOpenDialog({defaultPath:filePath,properties: ['openDirectory']} )
console.log("pathOp.dirname(filePath.filePath)"+pathOp.dirname(filePath.filePath))
return ipcRenderer.invoke("showOpenDialog",pathOp.dirname(filePath.filePath))
return dialog.showOpenDialog({defaultPath:"filePath",properties: ['openDirectory']} )
}