日志和脚本增加文件大小展示,修改脚本管理列表排序

This commit is contained in:
whyour 2023-12-21 09:57:06 +08:00
parent 52a89a21f6
commit f8aba4b1fb
6 changed files with 78 additions and 54 deletions

7
.gitignore vendored
View File

@ -22,11 +22,4 @@
.env .env
.history .history
.version.ts .version.ts
/config
/log
/db
/manual_log
/scripts
/bak
/.tmp /.tmp

View File

@ -21,12 +21,5 @@ src/.umi-production
src/.umi-test src/.umi-test
.env.local .env.local
.env .env
history
version.ts version.ts
config /.tmp
log
db
manual_log
scripts
bak
.tmp

View File

@ -46,6 +46,13 @@ export default (app: Router) => {
config.scriptPath, config.scriptPath,
config.scriptPath, config.scriptPath,
blacklist, blacklist,
(a, b) => {
if (a.type === b.type) {
return a.title.localeCompare(b.title);
} else {
return a.type === 'directory' ? -1 : 1;
}
},
); );
} }
res.send({ res.send({

View File

@ -234,12 +234,12 @@ interface IFile {
} }
export function dirSort(a: IFile, b: IFile): number { export function dirSort(a: IFile, b: IFile): number {
if (a.type !== b.type) { if (a.type === 'file' && b.type === 'file') {
return FileType[a.type] < FileType[b.type] ? -1 : 1 return b.mtime - a.mtime;
} else if (a.mtime !== b.mtime) { } else if (a.type === 'directory' && b.type === 'directory') {
return a.mtime > b.mtime ? -1 : 1 return a.title.localeCompare(b.title);
} else { } else {
return 0; return a.type === 'directory' ? -1 : 1;
} }
} }
@ -247,36 +247,39 @@ export async function readDirs(
dir: string, dir: string,
baseDir: string = '', baseDir: string = '',
blacklist: string[] = [], blacklist: string[] = [],
sort: (a: IFile, b: IFile) => number = dirSort,
): Promise<IFile[]> { ): Promise<IFile[]> {
const relativePath = path.relative(baseDir, dir); const relativePath = path.relative(baseDir, dir);
const files = await fs.readdir(dir); const files = await fs.readdir(dir);
const result: IFile[] = await Promise.all(files const result: IFile[] = await Promise.all(
.filter((x) => !blacklist.includes(x)) files
.map(async (file: string) => { .filter((x) => !blacklist.includes(x))
const subPath = path.join(dir, file); .map(async (file: string) => {
const stats = await fs.stat(subPath); const subPath = path.join(dir, file);
const key = path.join(relativePath, file); const stats = await fs.stat(subPath);
if (stats.isDirectory()) { const key = path.join(relativePath, file);
if (stats.isDirectory()) {
return {
title: file,
key,
type: 'directory',
parent: relativePath,
mtime: stats.mtime.getTime(),
children: (await readDirs(subPath, baseDir)).sort(sort),
};
}
return { return {
title: file, title: file,
type: 'file',
isLeaf: true,
key, key,
type: 'directory',
parent: relativePath, parent: relativePath,
size: stats.size,
mtime: stats.mtime.getTime(), mtime: stats.mtime.getTime(),
children: (await readDirs(subPath, baseDir)).sort(dirSort),
}; };
} }),
return { );
title: file, return result.sort(sort);
type: 'file',
isLeaf: true,
key,
parent: relativePath,
size: stats.size,
mtime: stats.mtime.getTime(),
};
}));
return result.sort(dirSort);
} }
export async function readDir( export async function readDir(
@ -304,7 +307,10 @@ export async function readDir(
export async function promiseExec(command: string): Promise<string> { export async function promiseExec(command: string): Promise<string> {
try { try {
const { stderr, stdout } = await promisify(exec)(command, { maxBuffer: 200 * 1024 * 1024, encoding: 'utf8' }); const { stderr, stdout } = await promisify(exec)(command, {
maxBuffer: 200 * 1024 * 1024,
encoding: 'utf8',
});
return stdout || stderr; return stdout || stderr;
} catch (error) { } catch (error) {
return JSON.stringify(error); return JSON.stringify(error);
@ -313,7 +319,10 @@ export async function promiseExec(command: string): Promise<string> {
export async function promiseExecSuccess(command: string): Promise<string> { export async function promiseExecSuccess(command: string): Promise<string> {
try { try {
const { stdout } = await promisify(exec)(command, { maxBuffer: 200 * 1024 * 1024, encoding: 'utf8' }); const { stdout } = await promisify(exec)(command, {
maxBuffer: 200 * 1024 * 1024,
encoding: 'utf8',
});
return stdout || ''; return stdout || '';
} catch (error) { } catch (error) {
return ''; return '';
@ -413,7 +422,7 @@ export async function killTask(pid: number) {
[pid, ...pids].reverse().forEach((x) => { [pid, ...pids].reverse().forEach((x) => {
process.kill(x, 15); process.kill(x, 15);
}); });
} catch (error) { } } catch (error) {}
} else { } else {
process.kill(pid, 2); process.kill(pid, 2);
} }
@ -440,7 +449,10 @@ export async function parseContentVersion(content: string): Promise<IVersion> {
return load(content) as IVersion; return load(content) as IVersion;
} }
export async function getUniqPath(command: string, id: string): Promise<string> { export async function getUniqPath(
command: string,
id: string,
): Promise<string> {
if (/^\d+$/.test(id)) { if (/^\d+$/.test(id)) {
id = `_${id}`; id = `_${id}`;
} else { } else {
@ -482,7 +494,7 @@ export function safeJSONParse(value?: string) {
try { try {
return JSON.parse(value); return JSON.parse(value);
} catch (error) { } catch (error) {
Logger.error('[JSON.parse失败]', error) Logger.error('[JSON.parse失败]', error);
return {}; return {};
} }
} }
@ -494,6 +506,6 @@ export async function rmPath(path: string) {
await fs.rm(path, { force: true, recursive: true, maxRetries: 5 }); await fs.rm(path, { force: true, recursive: true, maxRetries: 5 });
} }
} catch (error) { } catch (error) {
Logger.error('[rmPath失败]', error) Logger.error('[rmPath失败]', error);
} }
} }

View File

@ -1,4 +1,4 @@
import intl from 'react-intl-universal' import intl from 'react-intl-universal';
import { useState, useEffect, useCallback, Key, useRef } from 'react'; import { useState, useEffect, useCallback, Key, useRef } from 'react';
import { import {
TreeSelect, TreeSelect,
@ -31,7 +31,7 @@ const { Text } = Typography;
const Log = () => { const Log = () => {
const { headerStyle, isPhone, theme } = useOutletContext<SharedContext>(); const { headerStyle, isPhone, theme } = useOutletContext<SharedContext>();
const [value, setValue] = useState(intl.get('请选择日志文件')); const [value, setValue] = useState(intl.get('请选择日志文件'));
const [select, setSelect] = useState<string>(''); const [select, setSelect] = useState<string>(intl.get('请选择日志文件'));
const [data, setData] = useState<any[]>([]); const [data, setData] = useState<any[]>([]);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [height, setHeight] = useState<number>(); const [height, setHeight] = useState<number>();
@ -117,7 +117,8 @@ const Log = () => {
<Text style={{ wordBreak: 'break-all' }} type="warning"> <Text style={{ wordBreak: 'break-all' }} type="warning">
{select} {select}
</Text> </Text>
{intl.get('文件')}{currentNode.type === 'directory' ? intl.get('夹下所以日志') : ''} {intl.get('文件')}
{currentNode.type === 'directory' ? intl.get('夹下所以日志') : ''}
{intl.get(',删除后不可恢复')} {intl.get(',删除后不可恢复')}
</> </>
), ),
@ -181,7 +182,16 @@ const Log = () => {
return ( return (
<PageContainer <PageContainer
className="ql-container-wrapper log-wrapper" className="ql-container-wrapper log-wrapper"
title={select} title={
<>
{select}
{currentNode?.type === 'file' && (
<span style={{ marginLeft: 6, fontSize: 12, color: '#999' }}>
{(currentNode.size / 1024).toFixed(3)}KB
</span>
)}
</>
}
loading={loading} loading={loading}
extra={ extra={
isPhone isPhone

View File

@ -50,7 +50,7 @@ const { Text } = Typography;
const Script = () => { const Script = () => {
const { headerStyle, isPhone, theme } = useOutletContext<SharedContext>(); const { headerStyle, isPhone, theme } = useOutletContext<SharedContext>();
const [value, setValue] = useState(intl.get('请选择脚本文件')); const [value, setValue] = useState(intl.get('请选择脚本文件'));
const [select, setSelect] = useState<string>(''); const [select, setSelect] = useState<string>(intl.get('请选择脚本文件'));
const [data, setData] = useState<any[]>([]); const [data, setData] = useState<any[]>([]);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [mode, setMode] = useState(''); const [mode, setMode] = useState('');
@ -363,7 +363,7 @@ const Script = () => {
}; };
const initState = () => { const initState = () => {
setSelect(''); setSelect(intl.get('请选择脚本文件'));
setCurrentNode(null); setCurrentNode(null);
setValue(intl.get('请选择脚本文件')); setValue(intl.get('请选择脚本文件'));
}; };
@ -462,7 +462,16 @@ const Script = () => {
return ( return (
<PageContainer <PageContainer
className="ql-container-wrapper log-wrapper" className="ql-container-wrapper log-wrapper"
title={select} title={
<>
{select}
{currentNode?.type === 'file' && (
<span style={{ marginLeft: 6, fontSize: 12, color: '#999' }}>
{(currentNode.size / 1024).toFixed(3)}KB
</span>
)}
</>
}
loading={loading} loading={loading}
extra={ extra={
isPhone isPhone