完成基础功能
This commit is contained in:
parent
855d0c8c28
commit
4370189e81
2
TODO.md
2
TODO.md
@ -9,7 +9,7 @@
|
|||||||
---
|
---
|
||||||
|
|
||||||
- [x] 实现子网路由功能
|
- [x] 实现子网路由功能
|
||||||
- [ ] 实现配置保存和加载功能(支持加密私钥)
|
- [x] 实现配置保存和加载功能(支持加密私钥)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
28
src/App.tsx
28
src/App.tsx
@ -151,12 +151,14 @@ function FlowContent(): ReactNode {
|
|||||||
const handleSaveConfig = async (pass?: string): Promise<void> => {
|
const handleSaveConfig = async (pass?: string): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const saveConfig: SaveConfig = {settings: settings, nodes: [], edges: [], encrypted: false}
|
const saveConfig: SaveConfig = {settings: settings, nodes: [], edges: [], encrypted: false}
|
||||||
if(pass) saveConfig.encrypted = true;
|
|
||||||
|
|
||||||
nodes.forEach(node => {
|
nodes.forEach(node => {
|
||||||
const nodeData = node.data;
|
const nodeData = node.data;
|
||||||
let privateKey = nodeData.privateKey;
|
let privateKey: string = nodeData.privateKey;
|
||||||
if(pass && typeof privateKey === 'string') privateKey = CryptoJS.AES.encrypt(privateKey, pass).toString();
|
if(pass) {
|
||||||
|
privateKey = CryptoJS.AES.encrypt(privateKey, pass).toString();
|
||||||
|
saveConfig.encrypted = true;
|
||||||
|
}
|
||||||
saveConfig.nodes.push({...node, data: {...nodeData, privateKey: privateKey}});
|
saveConfig.nodes.push({...node, data: {...nodeData, privateKey: privateKey}});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -184,14 +186,14 @@ function FlowContent(): ReactNode {
|
|||||||
|
|
||||||
if (saveConfig.encrypted) {
|
if (saveConfig.encrypted) {
|
||||||
if (!pass) { toast.error('需要密码以解密私钥'); return; }
|
if (!pass) { toast.error('需要密码以解密私钥'); return; }
|
||||||
try {
|
|
||||||
for(let node of saveConfig.nodes) {
|
for(let node of saveConfig.nodes) {
|
||||||
node.data.privateKey = CryptoJS.AES.decrypt(node.data.privateKey, pass).toString(CryptoJS.enc.Utf8);
|
const privateKey = CryptoJS.AES.decrypt(node.data.privateKey, pass).toString(CryptoJS.enc.Utf8);
|
||||||
}
|
if(!privateKey) {
|
||||||
} catch (err) {
|
toast.error('密码错误');
|
||||||
toast.error('解密失败: ' + err);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
node.data.privateKey = privateKey;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
setSettings(saveConfig.settings);
|
setSettings(saveConfig.settings);
|
||||||
setNodes(saveConfig.nodes);
|
setNodes(saveConfig.nodes);
|
||||||
@ -233,11 +235,6 @@ function FlowContent(): ReactNode {
|
|||||||
|
|
||||||
<div className="toolbar">
|
<div className="toolbar">
|
||||||
<div className="toolbar-group">
|
<div className="toolbar-group">
|
||||||
<div className="action-section">
|
|
||||||
<div className="section-title">文件操作</div>
|
|
||||||
<SaveLoadPanel onSave={handleSaveConfig} onLoad={handleLoadConfig} />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="action-section">
|
<div className="action-section">
|
||||||
<div className="section-title">图表操作</div>
|
<div className="section-title">图表操作</div>
|
||||||
<Toggle
|
<Toggle
|
||||||
@ -253,6 +250,11 @@ function FlowContent(): ReactNode {
|
|||||||
📋 设置
|
📋 设置
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="action-section">
|
||||||
|
<div className="section-title">文件操作</div>
|
||||||
|
<SaveLoadPanel onSave={handleSaveConfig} onLoad={handleLoadConfig} />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -26,7 +26,7 @@
|
|||||||
border-radius:4px;
|
border-radius:4px;
|
||||||
}
|
}
|
||||||
/* Use .toolbar-btn for button styles so Save/Load matches other toolbar actions */
|
/* Use .toolbar-btn for button styles so Save/Load matches other toolbar actions */
|
||||||
.save-load-panel .toolbar-btn{width:100%;text-align:left;padding:8px 16px;border-radius:4px}
|
.save-load-panel .toolbar-btn{width:100%;text-align:center;padding:8px 16px;border-radius:4px}
|
||||||
/* divider removed to match toolbar style */
|
/* divider removed to match toolbar style */
|
||||||
|
|
||||||
/* Modal styles */
|
/* Modal styles */
|
||||||
|
|||||||
@ -73,7 +73,7 @@ export default function SaveLoadPanel({ onSave, onLoad }: Props) {
|
|||||||
<button className="sl-close" onClick={closeModal}>✕</button>
|
<button className="sl-close" onClick={closeModal}>✕</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="sl-modal-body">
|
<div className="sl-modal-body">
|
||||||
<label className="sl-label">加密密码(可选)</label>
|
<label className="sl-label">加密密码</label>
|
||||||
<input type="password" className="sl-input" value={password} onChange={e => setPassword(e.target.value)} />
|
<input type="password" className="sl-input" value={password} onChange={e => setPassword(e.target.value)} />
|
||||||
|
|
||||||
{modalType === 'load' ? (
|
{modalType === 'load' ? (
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user