feat: 添加高级设置和额外启动参数功能,优化配置管理

This commit is contained in:
VirtualHotBar
2026-03-04 23:24:50 +08:00
parent 1923fe9acb
commit d3b24e2692
10 changed files with 136 additions and 2 deletions

View File

@@ -199,6 +199,10 @@
"log": "Log",
"start_hide": "Hide Window on Startup",
"auto_recover_components": "Auto-recover Components",
"advanced_settings": "Advanced Settings",
"extra_startup_args": "Extra Startup Args",
"rclone_extra_args": "Rclone Extra Startup Args",
"openlist_extra_args": "OpenList Extra Startup Args",
"quit": "Quit",
"tray_show": "Show Main Window",
"open_log_dir": "Open Log Folder",
@@ -704,3 +708,4 @@
"export_import_config_description": "Export current configuration or restore configuration from file",
"confirm_import_description": "Importing configuration will overwrite all current settings and automatically restart the software. Continue?"
}

View File

@@ -199,6 +199,10 @@
"log": "日志",
"start_hide": "启动时隐藏窗口",
"auto_recover_components": "组件自愈",
"advanced_settings": "高级设置",
"extra_startup_args": "额外启动参数",
"rclone_extra_args": "Rclone 启动参数",
"openlist_extra_args": "OpenList 启动参数",
"quit": "退出",
"tray_show": "显示主窗口",
"open_log_dir": "打开日志目录",
@@ -704,3 +708,4 @@
"export_import_config_description": "导出当前配置或者从文件恢复配置",
"confirm_import_description": "导入配置将覆盖当前所有配置并自动重启软件,是否继续?"
}

View File

@@ -199,6 +199,10 @@
"log": "日誌",
"start_hide": "啟動時隱藏視窗",
"auto_recover_components": "元件異常自動修復",
"advanced_settings": "高級設置",
"extra_startup_args": "額外啟動參數",
"rclone_extra_args": "Rclone 額外啟動參數",
"openlist_extra_args": "OpenList 額外啟動參數",
"quit": "退出",
"tray_show": "顯示主視窗",
"open_log_dir": "打開日誌目錄",
@@ -704,3 +708,4 @@
"export_import_config_description": "導出當前配置或者從文件恢復配置",
"confirm_import_description": "導入配置將覆蓋當前所有配置並自動重啓軟件,是否繼續?"
}

View File

@@ -1,5 +1,5 @@
import { useEffect, useReducer, useState } from 'react'
import { Button, Card, Form, Grid, Input, Link, Message, Modal, Select, Space, Switch, Tooltip } from '@arco-design/web-react'
import { Button, Card, Collapse, Form, Grid, Input, Link, Message, Modal, Select, Space, Switch, Tooltip } from '@arco-design/web-react'
import { nmConfig, osInfo, roConfig, saveNmConfig } from '../../services/config';
import { getAutostartState, setAutostartState, setThemeMode } from '../../controller/setting/setting';
import { useTranslation } from 'react-i18next';
@@ -249,6 +249,45 @@ export default function Setting_page() {
</Space>
</Card>
<Card title={t('advanced_settings')} style={{}} size='small'>
<Form autoComplete='off' style={{ paddingRight: '0.8rem' }}>
<Collapse bordered={false} style={{ marginBottom: '0.75rem' }}>
<Collapse.Item name='extra_startup_args' header={t('extra_startup_args')}>
<FormItem label={'Rclone'}>
<Input
value={nmConfig.framework.rclone.extraArgs || ''}
placeholder='e.g. --log-level=DEBUG --rc-enable-metrics'
onChange={(value) => {
nmConfig.framework.rclone.extraArgs = value
forceUpdate()
}}
/>
</FormItem>
<FormItem label={'OpenList'}>
<Input
value={nmConfig.framework.openlist.extraArgs || ''}
placeholder='e.g. --log.level=debug'
onChange={(value) => {
nmConfig.framework.openlist.extraArgs = value
forceUpdate()
}}
/>
</FormItem>
</Collapse.Item>
</Collapse>
<div style={{ width: '100%', textAlign: 'right' }}>
<Button
type='primary'
onClick={async () => {
await saveNmConfig()
Message.success(t('saved'))
}}
>
{t('save')}
</Button>
</div>
</Form>
</Card>
<Card title={t('components')} style={{}} size='small'>
<Link onClick={() => { shell.open(roConfig.url.rclone) }}>Rclone</Link>(<Link onClick={() => {
if ((rcloneInfo.process.log || '').trim()) {

View File

@@ -75,10 +75,12 @@ let nmConfig: NMConfig = {
rclone: {
user: randomString(32),
password: randomString(128),
extraArgs: '',
},
openlist: {
user: 'admin',
password: randomString(16),//process.env.NODE_ENV === 'development' ? 'admin' : randomString(32),!!!!!密码长度为32时rclone会报错
extraArgs: '',
}
}
}

View File

@@ -24,10 +24,12 @@ interface NMConfig {
rclone: {
user: string,
password: string,
extraArgs?: string,
},
openlist: {
user: string,
password: string,
extraArgs?: string,
}
}
}

69
src/utils/cliArgs.ts Normal file
View File

@@ -0,0 +1,69 @@
function parseExtraCliArgs(input?: string): string[] {
if (!input || !input.trim()) return []
const args: string[] = []
let current = ''
let quote: '"' | "'" | null = null
for (let i = 0; i < input.length; i++) {
const ch = input[i]!
const next = input[i + 1]
if (ch === '\\') {
if (quote === '"') {
// In double quotes, allow escaping quote/backslash.
if (next === '"' || next === '\\') {
current += next
i++
continue
}
current += ch
continue
}
if (!quote) {
// Outside quotes, only treat as escape for whitespace/quote/backslash.
if (next && (/\s/.test(next) || next === '"' || next === "'" || next === '\\')) {
current += next
i++
continue
}
// Keep normal Windows paths like C:\temp\logs literally.
current += ch
continue
}
}
if (quote) {
if (ch === quote) {
quote = null
} else {
current += ch
}
continue
}
if (ch === '"' || ch === "'") {
quote = ch
continue
}
if (/\s/.test(ch)) {
if (current) {
args.push(current)
current = ''
}
continue
}
current += ch
}
if (current) {
args.push(current)
}
return args
}
export { parseExtraCliArgs }

View File

@@ -7,6 +7,7 @@ import { openlist_api_ping } from "./request";
import { addParams, openlistDataDir } from "./paths";
import { openlistLogFile } from "../netmountPaths";
import { restartSidecar, startSidecarAndWait, stopSidecarGracefully } from "../sidecarService";
import { parseExtraCliArgs } from "../cliArgs";
async function startOpenlist() {
//设置默认临时(缓存)目录
@@ -32,7 +33,8 @@ async function startOpenlist() {
const args: string[] = [
'server',
...addParams()
...addParams(),
...parseExtraCliArgs(nmConfig.framework.openlist.extraArgs)
];
console.log('OpenList start args:', args)

View File

@@ -8,6 +8,7 @@ import { delStorage } from "../../controller/storage/storage";
import { nmConfig, osInfo } from "../../services/config";
import { netmountLogDir, rcloneConfigFile, rcloneLogFile } from "../netmountPaths";
import { restartSidecar, startSidecarAndWait, stopSidecarGracefully } from "../sidecarService";
import { parseExtraCliArgs } from "../cliArgs";
async function startRclone() {
if (rcloneInfo.process.child) {
@@ -47,6 +48,7 @@ async function startRclone() {
if (nmConfig.framework.rclone.user === '') {
args.push('--rc-no-auth')
}
args.push(...parseExtraCliArgs(nmConfig.framework.rclone.extraArgs))
// 使用 Rust 端启动 sidecar确保由主进程创建
const pid = await startSidecarAndWait({

View File

@@ -274,6 +274,7 @@ export const NMConfigSchema = z.object({
settings: z.object({
themeMode: z.enum(['dark', 'light', 'auto']).or(z.string()),
startHide: z.boolean(),
autoRecoverComponents: z.boolean(),
language: z.string().optional(),
path: z.object({
cacheDir: z.string().optional(),
@@ -283,10 +284,12 @@ export const NMConfigSchema = z.object({
rclone: z.object({
user: z.string(),
password: z.string(),
extraArgs: z.string().optional(),
}),
openlist: z.object({
user: z.string(),
password: z.string(),
extraArgs: z.string().optional(),
}),
}),
});