mirror of
https://github.com/whyour/qinglong.git
synced 2025-05-22 22:36:06 +08:00
日志和脚本增加文件大小展示,修改脚本管理列表排序
This commit is contained in:
parent
52a89a21f6
commit
f8aba4b1fb
7
.gitignore
vendored
7
.gitignore
vendored
|
@ -22,11 +22,4 @@
|
||||||
.env
|
.env
|
||||||
.history
|
.history
|
||||||
.version.ts
|
.version.ts
|
||||||
|
|
||||||
/config
|
|
||||||
/log
|
|
||||||
/db
|
|
||||||
/manual_log
|
|
||||||
/scripts
|
|
||||||
/bak
|
|
||||||
/.tmp
|
/.tmp
|
|
@ -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
|
|
|
@ -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({
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue
Block a user