mirror of
https://github.com/whyour/qinglong.git
synced 2026-08-12 19:30:48 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
742d0b2135 | ||
|
|
2081364325 | ||
|
|
39dc31916e | ||
|
|
5395cebdb4 | ||
|
|
fe934fa4af | ||
|
|
461fa8e131 | ||
|
|
4618a19c04 | ||
|
|
e2bd15683e | ||
|
|
648b9c4520 | ||
|
|
b4e4e84bbd | ||
|
|
aa5d6f3cb6 | ||
|
|
e9416c23df | ||
|
|
ef4999be55 | ||
|
|
e7be4999b0 | ||
|
|
5907553670 | ||
|
|
0b9066525a | ||
|
|
ac904cae61 | ||
|
|
4d5fa320ea | ||
|
|
003defedcf | ||
|
|
40e8041401 | ||
|
|
a8174e89be | ||
|
|
cce83f7a4c | ||
|
|
4f7649f157 | ||
|
|
b002cbef3a | ||
|
|
1d93fe0de0 | ||
|
|
2d936f1341 | ||
|
|
b40673e9ac | ||
|
|
637874e426 | ||
|
|
de71d1a258 | ||
|
|
e174e190ee |
+1
-1
@@ -20,7 +20,7 @@ src/.umi
|
|||||||
src/.umi-production
|
src/.umi-production
|
||||||
src/.umi-test
|
src/.umi-test
|
||||||
.env.local
|
.env.local
|
||||||
env
|
.env
|
||||||
history
|
history
|
||||||
version.ts
|
version.ts
|
||||||
config
|
config
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ const CompressionPlugin = require('compression-webpack-plugin');
|
|||||||
const baseUrl = process.env.QlBaseUrl || '/';
|
const baseUrl = process.env.QlBaseUrl || '/';
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
hash: true,
|
hash: true,
|
||||||
|
jsMinifier: 'terser',
|
||||||
antd: {},
|
antd: {},
|
||||||
locale: {
|
locale: {
|
||||||
antd: true,
|
antd: true,
|
||||||
|
|||||||
+2
-1
@@ -6,6 +6,7 @@ import { celebrate, Joi } from 'celebrate';
|
|||||||
import multer from 'multer';
|
import multer from 'multer';
|
||||||
import config from '../config';
|
import config from '../config';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
|
import { safeJSONParse } from '../config/util';
|
||||||
const route = Router();
|
const route = Router();
|
||||||
|
|
||||||
const storage = multer.diskStorage({
|
const storage = multer.diskStorage({
|
||||||
@@ -200,7 +201,7 @@ export default (app: Router) => {
|
|||||||
try {
|
try {
|
||||||
const envService = Container.get(EnvService);
|
const envService = Container.get(EnvService);
|
||||||
const fileContent = await fs.promises.readFile(req!.file!.path, 'utf8');
|
const fileContent = await fs.promises.readFile(req!.file!.path, 'utf8');
|
||||||
const parseContent = JSON.parse(fileContent);
|
const parseContent = safeJSONParse(fileContent);
|
||||||
const data = Array.isArray(parseContent)
|
const data = Array.isArray(parseContent)
|
||||||
? parseContent
|
? parseContent
|
||||||
: [parseContent];
|
: [parseContent];
|
||||||
|
|||||||
@@ -265,9 +265,11 @@ export default (app: Router) => {
|
|||||||
let { filename, path, pid } = req.body;
|
let { filename, path, pid } = req.body;
|
||||||
const { name, ext } = parse(filename);
|
const { name, ext } = parse(filename);
|
||||||
const filePath = join(config.scriptPath, path, `${name}.swap${ext}`);
|
const filePath = join(config.scriptPath, path, `${name}.swap${ext}`);
|
||||||
|
const logPath = join(config.logPath, path, `${name}.swap`);
|
||||||
|
|
||||||
const scriptService = Container.get(ScriptService);
|
const scriptService = Container.get(ScriptService);
|
||||||
const result = await scriptService.stopScript(filePath, pid);
|
const result = await scriptService.stopScript(filePath, pid);
|
||||||
|
emptyDir(logPath);
|
||||||
res.send(result);
|
res.send(result);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return next(e);
|
return next(e);
|
||||||
|
|||||||
+17
-1
@@ -174,7 +174,10 @@ export default (app: Router) => {
|
|||||||
async (req: Request, res: Response, next: NextFunction) => {
|
async (req: Request, res: Response, next: NextFunction) => {
|
||||||
try {
|
try {
|
||||||
const systemService = Container.get(SystemService);
|
const systemService = Container.get(SystemService);
|
||||||
const uniqPath = await getUniqPath(req.body.command);
|
const command = req.body.command
|
||||||
|
const idStr = `cat ${config.crontabFile} | grep -E "${command}" | perl -pe "s|.*ID=(.*) ${command}.*|\\1|" | head -1 | awk -F " " '{print $1}' | xargs echo -n`;
|
||||||
|
let id = await promiseExec(idStr);
|
||||||
|
const uniqPath = await getUniqPath(command, id);
|
||||||
const logTime = dayjs().format('YYYY-MM-DD-HH-mm-ss-SSS');
|
const logTime = dayjs().format('YYYY-MM-DD-HH-mm-ss-SSS');
|
||||||
const logPath = `${uniqPath}/${logTime}.log`;
|
const logPath = `${uniqPath}/${logTime}.log`;
|
||||||
res.setHeader('Content-type', 'application/octet-stream');
|
res.setHeader('Content-type', 'application/octet-stream');
|
||||||
@@ -249,4 +252,17 @@ export default (app: Router) => {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
route.get(
|
||||||
|
'/log',
|
||||||
|
async (req: Request, res: Response, next: NextFunction) => {
|
||||||
|
try {
|
||||||
|
const systemService = Container.get(SystemService);
|
||||||
|
await systemService.getSystemLog(res);
|
||||||
|
} catch (e) {
|
||||||
|
return next(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -18,10 +18,12 @@ async function startServer() {
|
|||||||
const server = app
|
const server = app
|
||||||
.listen(config.port, () => {
|
.listen(config.port, () => {
|
||||||
Logger.debug(`✌️ 后端服务启动成功!`);
|
Logger.debug(`✌️ 后端服务启动成功!`);
|
||||||
|
console.debug(`✌️ 后端服务启动成功!`);
|
||||||
process.send?.('ready');
|
process.send?.('ready');
|
||||||
})
|
})
|
||||||
.on('error', (err) => {
|
.on('error', (err) => {
|
||||||
Logger.error(err);
|
Logger.error(err);
|
||||||
|
console.error(err);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import dotenv from 'dotenv';
|
import dotenv from 'dotenv';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { createRandomString } from './util';
|
import { createRandomString } from './share';
|
||||||
|
|
||||||
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
|
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
|
||||||
|
|
||||||
@@ -30,6 +30,7 @@ const logPath = path.join(dataPath, 'log/');
|
|||||||
const dbPath = path.join(dataPath, 'db/');
|
const dbPath = path.join(dataPath, 'db/');
|
||||||
const uploadPath = path.join(dataPath, 'upload/');
|
const uploadPath = path.join(dataPath, 'upload/');
|
||||||
const sshdPath = path.join(dataPath, 'ssh.d/');
|
const sshdPath = path.join(dataPath, 'ssh.d/');
|
||||||
|
const systemLogPath = path.join(dataPath, 'syslog/');
|
||||||
|
|
||||||
const envFile = path.join(configPath, 'env.sh');
|
const envFile = path.join(configPath, 'env.sh');
|
||||||
const confFile = path.join(configPath, 'config.sh');
|
const confFile = path.join(configPath, 'config.sh');
|
||||||
@@ -110,4 +111,5 @@ export default {
|
|||||||
lastVersionFile,
|
lastVersionFile,
|
||||||
sqliteFile,
|
sqliteFile,
|
||||||
sshdPath,
|
sshdPath,
|
||||||
|
systemLogPath,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
export function createRandomString(min: number, max: number): string {
|
||||||
|
const num = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
|
||||||
|
const english = [
|
||||||
|
'a',
|
||||||
|
'b',
|
||||||
|
'c',
|
||||||
|
'd',
|
||||||
|
'e',
|
||||||
|
'f',
|
||||||
|
'g',
|
||||||
|
'h',
|
||||||
|
'i',
|
||||||
|
'j',
|
||||||
|
'k',
|
||||||
|
'l',
|
||||||
|
'm',
|
||||||
|
'n',
|
||||||
|
'o',
|
||||||
|
'p',
|
||||||
|
'q',
|
||||||
|
'r',
|
||||||
|
's',
|
||||||
|
't',
|
||||||
|
'u',
|
||||||
|
'v',
|
||||||
|
'w',
|
||||||
|
'x',
|
||||||
|
'y',
|
||||||
|
'z',
|
||||||
|
];
|
||||||
|
const ENGLISH = [
|
||||||
|
'A',
|
||||||
|
'B',
|
||||||
|
'C',
|
||||||
|
'D',
|
||||||
|
'E',
|
||||||
|
'F',
|
||||||
|
'G',
|
||||||
|
'H',
|
||||||
|
'I',
|
||||||
|
'J',
|
||||||
|
'K',
|
||||||
|
'L',
|
||||||
|
'M',
|
||||||
|
'N',
|
||||||
|
'O',
|
||||||
|
'P',
|
||||||
|
'Q',
|
||||||
|
'R',
|
||||||
|
'S',
|
||||||
|
'T',
|
||||||
|
'U',
|
||||||
|
'V',
|
||||||
|
'W',
|
||||||
|
'X',
|
||||||
|
'Y',
|
||||||
|
'Z',
|
||||||
|
];
|
||||||
|
const special = ['-', '_'];
|
||||||
|
const config = num.concat(english).concat(ENGLISH).concat(special);
|
||||||
|
|
||||||
|
const arr = [];
|
||||||
|
arr.push(getOne(num));
|
||||||
|
arr.push(getOne(english));
|
||||||
|
arr.push(getOne(ENGLISH));
|
||||||
|
arr.push(getOne(special));
|
||||||
|
|
||||||
|
const len = min + Math.floor(Math.random() * (max - min + 1));
|
||||||
|
|
||||||
|
for (let i = 4; i < len; i++) {
|
||||||
|
arr.push(config[Math.floor(Math.random() * config.length)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const newArr = [];
|
||||||
|
for (let j = 0; j < len; j++) {
|
||||||
|
newArr.push(arr.splice(Math.random() * arr.length, 1)[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getOne(arr: any[]) {
|
||||||
|
return arr[Math.floor(Math.random() * arr.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
return newArr.join('');
|
||||||
|
}
|
||||||
+30
-95
@@ -9,6 +9,9 @@ import { promisify } from 'util';
|
|||||||
import { load } from 'js-yaml';
|
import { load } from 'js-yaml';
|
||||||
import config from './index';
|
import config from './index';
|
||||||
import { TASK_COMMAND } from './const';
|
import { TASK_COMMAND } from './const';
|
||||||
|
import Logger from '../loaders/logger';
|
||||||
|
|
||||||
|
export * from './share';
|
||||||
|
|
||||||
export function getFileContentByName(fileName: string) {
|
export function getFileContentByName(fileName: string) {
|
||||||
if (fs.existsSync(fileName)) {
|
if (fs.existsSync(fileName)) {
|
||||||
@@ -36,91 +39,6 @@ export function getLastModifyFilePath(dir: string) {
|
|||||||
return filePath;
|
return filePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createRandomString(min: number, max: number): string {
|
|
||||||
const num = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
|
|
||||||
const english = [
|
|
||||||
'a',
|
|
||||||
'b',
|
|
||||||
'c',
|
|
||||||
'd',
|
|
||||||
'e',
|
|
||||||
'f',
|
|
||||||
'g',
|
|
||||||
'h',
|
|
||||||
'i',
|
|
||||||
'j',
|
|
||||||
'k',
|
|
||||||
'l',
|
|
||||||
'm',
|
|
||||||
'n',
|
|
||||||
'o',
|
|
||||||
'p',
|
|
||||||
'q',
|
|
||||||
'r',
|
|
||||||
's',
|
|
||||||
't',
|
|
||||||
'u',
|
|
||||||
'v',
|
|
||||||
'w',
|
|
||||||
'x',
|
|
||||||
'y',
|
|
||||||
'z',
|
|
||||||
];
|
|
||||||
const ENGLISH = [
|
|
||||||
'A',
|
|
||||||
'B',
|
|
||||||
'C',
|
|
||||||
'D',
|
|
||||||
'E',
|
|
||||||
'F',
|
|
||||||
'G',
|
|
||||||
'H',
|
|
||||||
'I',
|
|
||||||
'J',
|
|
||||||
'K',
|
|
||||||
'L',
|
|
||||||
'M',
|
|
||||||
'N',
|
|
||||||
'O',
|
|
||||||
'P',
|
|
||||||
'Q',
|
|
||||||
'R',
|
|
||||||
'S',
|
|
||||||
'T',
|
|
||||||
'U',
|
|
||||||
'V',
|
|
||||||
'W',
|
|
||||||
'X',
|
|
||||||
'Y',
|
|
||||||
'Z',
|
|
||||||
];
|
|
||||||
const special = ['-', '_'];
|
|
||||||
const config = num.concat(english).concat(ENGLISH).concat(special);
|
|
||||||
|
|
||||||
const arr = [];
|
|
||||||
arr.push(getOne(num));
|
|
||||||
arr.push(getOne(english));
|
|
||||||
arr.push(getOne(ENGLISH));
|
|
||||||
arr.push(getOne(special));
|
|
||||||
|
|
||||||
const len = min + Math.floor(Math.random() * (max - min + 1));
|
|
||||||
|
|
||||||
for (let i = 4; i < len; i++) {
|
|
||||||
arr.push(config[Math.floor(Math.random() * config.length)]);
|
|
||||||
}
|
|
||||||
|
|
||||||
const newArr = [];
|
|
||||||
for (let j = 0; j < len; j++) {
|
|
||||||
newArr.push(arr.splice(Math.random() * arr.length, 1)[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getOne(arr: any[]) {
|
|
||||||
return arr[Math.floor(Math.random() * arr.length)];
|
|
||||||
}
|
|
||||||
|
|
||||||
return newArr.join('');
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getToken(req: any) {
|
export function getToken(req: any) {
|
||||||
const { authorization = '' } = req.headers;
|
const { authorization = '' } = req.headers;
|
||||||
if (authorization && authorization.split(' ')[0] === 'Bearer') {
|
if (authorization && authorization.split(' ')[0] === 'Bearer') {
|
||||||
@@ -307,22 +225,28 @@ interface IFile {
|
|||||||
type: 'directory' | 'file';
|
type: 'directory' | 'file';
|
||||||
parent: string;
|
parent: string;
|
||||||
mtime: number;
|
mtime: number;
|
||||||
|
size?: number;
|
||||||
children?: IFile[];
|
children?: IFile[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function dirSort(a: IFile, b: IFile) {
|
export function dirSort(a: IFile, b: IFile): number {
|
||||||
if (a.type !== b.type) return FileType[a.type] < FileType[b.type] ? -1 : 1;
|
if (a.type !== b.type) {
|
||||||
else if (a.mtime !== b.mtime) return a.mtime > b.mtime ? -1 : 1;
|
return FileType[a.type] < FileType[b.type] ? -1 : 1
|
||||||
|
} else if (a.mtime !== b.mtime) {
|
||||||
|
return a.mtime > b.mtime ? -1 : 1
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function readDirs(
|
export function readDirs(
|
||||||
dir: string,
|
dir: string,
|
||||||
baseDir: string = '',
|
baseDir: string = '',
|
||||||
blacklist: string[] = [],
|
blacklist: string[] = [],
|
||||||
) {
|
): IFile[] {
|
||||||
const relativePath = path.relative(baseDir, dir);
|
const relativePath = path.relative(baseDir, dir);
|
||||||
const files = fs.readdirSync(dir);
|
const files = fs.readdirSync(dir);
|
||||||
const result: any = files
|
const result: IFile[] = files
|
||||||
.filter((x) => !blacklist.includes(x))
|
.filter((x) => !blacklist.includes(x))
|
||||||
.map((file: string) => {
|
.map((file: string) => {
|
||||||
const subPath = path.join(dir, file);
|
const subPath = path.join(dir, file);
|
||||||
@@ -344,6 +268,7 @@ export function readDirs(
|
|||||||
isLeaf: true,
|
isLeaf: true,
|
||||||
key,
|
key,
|
||||||
parent: relativePath,
|
parent: relativePath,
|
||||||
|
size: stats.size,
|
||||||
mtime: stats.mtime.getTime(),
|
mtime: stats.mtime.getTime(),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@@ -522,11 +447,8 @@ export async function parseContentVersion(content: string): Promise<IVersion> {
|
|||||||
return load(content) as IVersion;
|
return load(content) as IVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getUniqPath(command: string): Promise<string> {
|
export async function getUniqPath(command: string, id: string): Promise<string> {
|
||||||
const idStr = `cat ${config.crontabFile} | grep -E "${command}" | perl -pe "s|.*ID=(.*) ${command}.*|\\1|" | head -1 | awk -F " " '{print $1}' | xargs echo -n`;
|
if (/^\d+$/.test(id)) {
|
||||||
let id = await promiseExec(idStr);
|
|
||||||
|
|
||||||
if (/^\d\d*\d$/.test(id)) {
|
|
||||||
id = `_${id}`;
|
id = `_${id}`;
|
||||||
} else {
|
} else {
|
||||||
id = '';
|
id = '';
|
||||||
@@ -558,3 +480,16 @@ export async function getUniqPath(command: string): Promise<string> {
|
|||||||
|
|
||||||
return `${str}${id}`;
|
return `${str}${id}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function safeJSONParse(value?: string) {
|
||||||
|
if (!value) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return JSON.parse(value);
|
||||||
|
} catch (error) {
|
||||||
|
Logger.error('[JSON.parse失败]', error)
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
+24
-14
@@ -7,18 +7,28 @@ import linkDeps from './deps';
|
|||||||
import initTask from './initTask';
|
import initTask from './initTask';
|
||||||
|
|
||||||
export default async ({ expressApp }: { expressApp: Application }) => {
|
export default async ({ expressApp }: { expressApp: Application }) => {
|
||||||
await depInjectorLoader();
|
try {
|
||||||
Logger.info('✌️ Dependency Injector loaded');
|
depInjectorLoader();
|
||||||
|
Logger.info('✌️ Dependency Injector loaded');
|
||||||
await expressLoader({ app: expressApp });
|
console.log('✌️ Dependency Injector loaded');
|
||||||
Logger.info('✌️ Express loaded');
|
|
||||||
|
expressLoader({ app: expressApp });
|
||||||
await initData();
|
Logger.info('✌️ Express loaded');
|
||||||
Logger.info('✌️ init data loaded');
|
console.log('✌️ Express loaded');
|
||||||
|
|
||||||
await linkDeps();
|
await initData();
|
||||||
Logger.info('✌️ link deps loaded');
|
Logger.info('✌️ init data loaded');
|
||||||
|
console.log('✌️ init data loaded');
|
||||||
initTask();
|
|
||||||
Logger.info('✌️ init task loaded');
|
await linkDeps();
|
||||||
|
Logger.info('✌️ link deps loaded');
|
||||||
|
console.log('✌️ link deps loaded');
|
||||||
|
|
||||||
|
initTask();
|
||||||
|
Logger.info('✌️ init task loaded');
|
||||||
|
console.log('✌️ init task loaded');
|
||||||
|
} catch (error) {
|
||||||
|
Logger.error(`✌️ depInjectorLoader expressLoader initData linkDeps failed, ${error}`);
|
||||||
|
console.error(`✌️ depInjectorLoader expressLoader initData linkDeps failed ${error}`);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
+3
-2
@@ -122,9 +122,10 @@ export default async () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('✌️ DB loaded');
|
||||||
Logger.info('✌️ DB loaded');
|
Logger.info('✌️ DB loaded');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
Logger.info('✌️ DB load failed');
|
console.error('✌️ DB load failed');
|
||||||
Logger.info(error);
|
Logger.error(error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import routes from '../api';
|
|||||||
import config from '../config';
|
import config from '../config';
|
||||||
import jwt, { UnauthorizedError } from 'express-jwt';
|
import jwt, { UnauthorizedError } from 'express-jwt';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import { getPlatform, getToken } from '../config/util';
|
import { getPlatform, getToken, safeJSONParse } from '../config/util';
|
||||||
import Container from 'typedi';
|
import Container from 'typedi';
|
||||||
import OpenService from '../services/open';
|
import OpenService from '../services/open';
|
||||||
import rewrite from 'express-urlrewrite';
|
import rewrite from 'express-urlrewrite';
|
||||||
@@ -15,6 +15,7 @@ import { EnvModel } from '../data/env';
|
|||||||
import { errors } from 'celebrate';
|
import { errors } from 'celebrate';
|
||||||
import { createProxyMiddleware } from 'http-proxy-middleware';
|
import { createProxyMiddleware } from 'http-proxy-middleware';
|
||||||
import { serveEnv } from '../config/serverEnv';
|
import { serveEnv } from '../config/serverEnv';
|
||||||
|
import Logger from './logger';
|
||||||
|
|
||||||
export default ({ app }: { app: Application }) => {
|
export default ({ app }: { app: Application }) => {
|
||||||
app.enable('trust proxy');
|
app.enable('trust proxy');
|
||||||
@@ -25,9 +26,10 @@ export default ({ app }: { app: Application }) => {
|
|||||||
app.use(
|
app.use(
|
||||||
'/api/public',
|
'/api/public',
|
||||||
createProxyMiddleware({
|
createProxyMiddleware({
|
||||||
target: `http://localhost:${config.publicPort}/api`,
|
target: `http://0.0.0.0:${config.publicPort}/api`,
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
pathRewrite: { '/api/public': '' },
|
pathRewrite: { '/api/public': '' },
|
||||||
|
logProvider: () => Logger
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -36,7 +38,7 @@ export default ({ app }: { app: Application }) => {
|
|||||||
|
|
||||||
app.use(
|
app.use(
|
||||||
jwt({
|
jwt({
|
||||||
secret: config.secret as string,
|
secret: config.secret,
|
||||||
algorithms: ['HS384'],
|
algorithms: ['HS384'],
|
||||||
}).unless({
|
}).unless({
|
||||||
path: [...config.apiWhiteList, /^\/open\//],
|
path: [...config.apiWhiteList, /^\/open\//],
|
||||||
@@ -83,7 +85,7 @@ export default ({ app }: { app: Application }) => {
|
|||||||
|
|
||||||
const data = fs.readFileSync(config.authConfigFile, 'utf8');
|
const data = fs.readFileSync(config.authConfigFile, 'utf8');
|
||||||
if (data && headerToken) {
|
if (data && headerToken) {
|
||||||
const { token = '', tokens = {} } = JSON.parse(data);
|
const { token = '', tokens = {} } = safeJSONParse(data);
|
||||||
if (headerToken === token || tokens[req.platform] === headerToken) {
|
if (headerToken === token || tokens[req.platform] === headerToken) {
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ const TaskAfterFile = path.join(configPath, 'task_after.sh');
|
|||||||
const homedir = os.homedir();
|
const homedir = os.homedir();
|
||||||
const sshPath = path.resolve(homedir, '.ssh');
|
const sshPath = path.resolve(homedir, '.ssh');
|
||||||
const sshdPath = path.join(dataPath, 'ssh.d');
|
const sshdPath = path.join(dataPath, 'ssh.d');
|
||||||
|
const systemLogPath = path.join(dataPath, 'syslog');
|
||||||
|
|
||||||
export default async () => {
|
export default async () => {
|
||||||
const authFileExist = await fileExist(authConfigFile);
|
const authFileExist = await fileExist(authConfigFile);
|
||||||
@@ -39,6 +40,7 @@ export default async () => {
|
|||||||
const sshDirExist = await fileExist(sshPath);
|
const sshDirExist = await fileExist(sshPath);
|
||||||
const bakDirExist = await fileExist(bakPath);
|
const bakDirExist = await fileExist(bakPath);
|
||||||
const sshdDirExist = await fileExist(sshdPath);
|
const sshdDirExist = await fileExist(sshdPath);
|
||||||
|
const systemLogDirExist = await fileExist(systemLogPath);
|
||||||
const tmpDirExist = await fileExist(tmpPath);
|
const tmpDirExist = await fileExist(tmpPath);
|
||||||
const scriptNotifyJsFileExist = await fileExist(scriptNotifyJsFile);
|
const scriptNotifyJsFileExist = await fileExist(scriptNotifyJsFile);
|
||||||
const scriptNotifyPyFileExist = await fileExist(scriptNotifyPyFile);
|
const scriptNotifyPyFileExist = await fileExist(scriptNotifyPyFile);
|
||||||
@@ -77,6 +79,10 @@ export default async () => {
|
|||||||
fs.mkdirSync(sshdPath);
|
fs.mkdirSync(sshdPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!systemLogDirExist) {
|
||||||
|
fs.mkdirSync(systemLogPath);
|
||||||
|
}
|
||||||
|
|
||||||
// 初始化文件
|
// 初始化文件
|
||||||
if (!authFileExist) {
|
if (!authFileExist) {
|
||||||
fs.writeFileSync(authConfigFile, fs.readFileSync(sampleAuthFile));
|
fs.writeFileSync(authConfigFile, fs.readFileSync(sampleAuthFile));
|
||||||
@@ -105,4 +111,5 @@ export default async () => {
|
|||||||
dotenv.config({ path: confFile });
|
dotenv.config({ path: confFile });
|
||||||
|
|
||||||
Logger.info('✌️ Init file down');
|
Logger.info('✌️ Init file down');
|
||||||
|
console.log('✌️ Init file down');
|
||||||
};
|
};
|
||||||
|
|||||||
+27
-21
@@ -1,32 +1,38 @@
|
|||||||
import winston from 'winston';
|
import winston from 'winston';
|
||||||
|
import 'winston-daily-rotate-file';
|
||||||
import config from '../config';
|
import config from '../config';
|
||||||
|
import path from 'path';
|
||||||
|
|
||||||
const transports = [];
|
const levelMap: Record<string, string> = {
|
||||||
if (process.env.NODE_ENV !== 'development') {
|
info: '🔵',
|
||||||
transports.push(new winston.transports.Console());
|
warn: '🟡',
|
||||||
} else {
|
error: '🔴',
|
||||||
transports.push(
|
debug: '🔶'
|
||||||
new winston.transports.Console({
|
|
||||||
format: winston.format.combine(
|
|
||||||
winston.format.cli(),
|
|
||||||
winston.format.splat(),
|
|
||||||
),
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const customFormat = winston.format.combine(
|
||||||
|
winston.format.splat(),
|
||||||
|
winston.format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }),
|
||||||
|
winston.format.align(),
|
||||||
|
winston.format.printf((i) => `[${levelMap[i.level]}${i.level}] [${[i.timestamp]}]: ${i.message}`),
|
||||||
|
);
|
||||||
|
|
||||||
|
const defaultOptions = {
|
||||||
|
format: customFormat,
|
||||||
|
datePattern: "YYYY-MM-DD",
|
||||||
|
maxSize: "20m",
|
||||||
|
maxFiles: "7d",
|
||||||
|
};
|
||||||
|
|
||||||
const LoggerInstance = winston.createLogger({
|
const LoggerInstance = winston.createLogger({
|
||||||
level: config.logs.level,
|
level: config.logs.level,
|
||||||
levels: winston.config.npm.levels,
|
levels: winston.config.npm.levels,
|
||||||
format: winston.format.combine(
|
transports: [
|
||||||
winston.format.timestamp({
|
new winston.transports.DailyRotateFile({
|
||||||
format: 'YYYY-MM-DD HH:mm:ss',
|
filename: path.join(config.systemLogPath, '%DATE%.log'),
|
||||||
}),
|
...defaultOptions,
|
||||||
winston.format.errors({ stack: true }),
|
})
|
||||||
winston.format.splat(),
|
],
|
||||||
winston.format.json(),
|
|
||||||
),
|
|
||||||
transports,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default LoggerInstance;
|
export default LoggerInstance;
|
||||||
|
|||||||
@@ -29,4 +29,5 @@ export default async ({ expressApp }: { expressApp: Application }) => {
|
|||||||
expressApp.use(Sentry.Handlers.tracingHandler());
|
expressApp.use(Sentry.Handlers.tracingHandler());
|
||||||
|
|
||||||
Logger.info('✌️ Sentry loaded');
|
Logger.info('✌️ Sentry loaded');
|
||||||
|
console.log('✌️ Sentry loaded');
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,9 +10,11 @@ export default async ({ server }: { server: Server }) => {
|
|||||||
|
|
||||||
process.on('SIGINT', (singal) => {
|
process.on('SIGINT', (singal) => {
|
||||||
Logger.warn(`Server need close, singal ${singal}`);
|
Logger.warn(`Server need close, singal ${singal}`);
|
||||||
|
console.warn(`Server need close, singal ${singal}`);
|
||||||
exitTime++;
|
exitTime++;
|
||||||
if (exitTime >= 3) {
|
if (exitTime >= 3) {
|
||||||
Logger.warn('Forcing server close');
|
Logger.warn('Forcing server close');
|
||||||
|
console.warn('Forcing server close');
|
||||||
clearTimeout(timer);
|
clearTimeout(timer);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
@@ -28,11 +30,13 @@ export default async ({ server }: { server: Server }) => {
|
|||||||
|
|
||||||
process.on('uncaughtException', (error) => {
|
process.on('uncaughtException', (error) => {
|
||||||
Logger.error('Uncaught exception:', error);
|
Logger.error('Uncaught exception:', error);
|
||||||
|
console.error('Uncaught exception:', error);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
process.on('unhandledRejection', (reason, promise) => {
|
process.on('unhandledRejection', (reason, promise) => {
|
||||||
Logger.error('Unhandled rejection:', reason);
|
Logger.error('Unhandled rejection:', reason, promise);
|
||||||
|
console.error('Unhandled rejection:', reason, promise);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { Container } from 'typedi';
|
|||||||
import SockService from '../services/sock';
|
import SockService from '../services/sock';
|
||||||
import config from '../config/index';
|
import config from '../config/index';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import { getPlatform } from '../config/util';
|
import { getPlatform, safeJSONParse } from '../config/util';
|
||||||
|
|
||||||
export default async ({ server }: { server: Server }) => {
|
export default async ({ server }: { server: Server }) => {
|
||||||
const echo = sockJs.createServer({ prefix: '/api/ws', log: () => {} });
|
const echo = sockJs.createServer({ prefix: '/api/ws', log: () => {} });
|
||||||
@@ -20,7 +20,7 @@ export default async ({ server }: { server: Server }) => {
|
|||||||
const platform = getPlatform(conn.headers['user-agent'] || '') || 'desktop';
|
const platform = getPlatform(conn.headers['user-agent'] || '') || 'desktop';
|
||||||
const headerToken = conn.url.replace(`${conn.pathname}?token=`, '');
|
const headerToken = conn.url.replace(`${conn.pathname}?token=`, '');
|
||||||
if (data) {
|
if (data) {
|
||||||
const { token = '', tokens = {} } = JSON.parse(data);
|
const { token = '', tokens = {} } = safeJSONParse(data);
|
||||||
if (headerToken === token || tokens[platform] === headerToken) {
|
if (headerToken === token || tokens[platform] === headerToken) {
|
||||||
conn.write(JSON.stringify({ type: 'ping', message: 'hanhh' }));
|
conn.write(JSON.stringify({ type: 'ping', message: 'hanhh' }));
|
||||||
sockService.addClient(conn);
|
sockService.addClient(conn);
|
||||||
|
|||||||
+3
-1
@@ -6,7 +6,7 @@ import { credentials } from '@grpc/grpc-js';
|
|||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
const client = new HealthClient(
|
const client = new HealthClient(
|
||||||
`localhost:${config.cronPort}`,
|
`0.0.0.0:${config.cronPort}`,
|
||||||
credentials.createInsecure(),
|
credentials.createInsecure(),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -25,9 +25,11 @@ app
|
|||||||
await require('./loaders/db').default();
|
await require('./loaders/db').default();
|
||||||
|
|
||||||
Logger.debug(`✌️ 公共服务启动成功!`);
|
Logger.debug(`✌️ 公共服务启动成功!`);
|
||||||
|
console.debug(`✌️ 公共服务启动成功!`);
|
||||||
process.send?.('ready');
|
process.send?.('ready');
|
||||||
})
|
})
|
||||||
.on('error', (err) => {
|
.on('error', (err) => {
|
||||||
Logger.error(err);
|
Logger.error(err);
|
||||||
|
console.error(err);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -22,13 +22,18 @@ const addCron = (
|
|||||||
cmdStr = `${TASK_PREFIX}${cmdStr}`;
|
cmdStr = `${TASK_PREFIX}${cmdStr}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Logger.info(
|
||||||
|
'[schedule][创建定时任务], 任务ID: %s, cron: %s, 执行命令: %s',
|
||||||
|
id,
|
||||||
|
schedule,
|
||||||
|
command,
|
||||||
|
);
|
||||||
|
|
||||||
scheduleStacks.set(
|
scheduleStacks.set(
|
||||||
id,
|
id,
|
||||||
nodeSchedule.scheduleJob(id, schedule, async () => {
|
nodeSchedule.scheduleJob(id, schedule, async () => {
|
||||||
Logger.info(
|
Logger.info(
|
||||||
`当前时间: ${dayjs().format(
|
`[schedule][准备运行任务] 命令: ${cmdStr}`,
|
||||||
'YYYY-MM-DD HH:mm:ss',
|
|
||||||
)},运行命令: ${cmdStr}`,
|
|
||||||
);
|
);
|
||||||
runCron(`ID=${id} ${cmdStr}`);
|
runCron(`ID=${id} ${cmdStr}`);
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import config from '../config';
|
|||||||
|
|
||||||
class Client {
|
class Client {
|
||||||
private client = new CronClient(
|
private client = new CronClient(
|
||||||
`localhost:${config.cronPort}`,
|
`0.0.0.0:${config.cronPort}`,
|
||||||
credentials.createInsecure(),
|
credentials.createInsecure(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { ServerUnaryCall, sendUnaryData } from '@grpc/grpc-js';
|
import { ServerUnaryCall, sendUnaryData } from '@grpc/grpc-js';
|
||||||
import { DeleteCronRequest, DeleteCronResponse } from '../protos/cron';
|
import { DeleteCronRequest, DeleteCronResponse } from '../protos/cron';
|
||||||
import { scheduleStacks } from './data';
|
import { scheduleStacks } from './data';
|
||||||
|
import Logger from '../loaders/logger';
|
||||||
|
|
||||||
const delCron = (
|
const delCron = (
|
||||||
call: ServerUnaryCall<DeleteCronRequest, DeleteCronResponse>,
|
call: ServerUnaryCall<DeleteCronRequest, DeleteCronResponse>,
|
||||||
@@ -8,6 +9,10 @@ const delCron = (
|
|||||||
) => {
|
) => {
|
||||||
for (const id of call.request.ids) {
|
for (const id of call.request.ids) {
|
||||||
if (scheduleStacks.has(id)) {
|
if (scheduleStacks.has(id)) {
|
||||||
|
Logger.info(
|
||||||
|
'[schedule][取消定时任务], 任务ID: %s',
|
||||||
|
id,
|
||||||
|
);
|
||||||
scheduleStacks.get(id)?.cancel();
|
scheduleStacks.get(id)?.cancel();
|
||||||
scheduleStacks.delete(id);
|
scheduleStacks.delete(id);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ const check = async (
|
|||||||
switch (call.request.service) {
|
switch (call.request.service) {
|
||||||
case 'cron':
|
case 'cron':
|
||||||
const res = await promiseExec(
|
const res = await promiseExec(
|
||||||
`curl -s http://localhost:${config.port}/api/system`,
|
`curl -s http://0.0.0.0:${config.port}/api/system`,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (res.includes('200')) {
|
if (res.includes('200')) {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ const server = new Server();
|
|||||||
server.addService(HealthService, { check });
|
server.addService(HealthService, { check });
|
||||||
server.addService(CronService, { addCron, delCron });
|
server.addService(CronService, { addCron, delCron });
|
||||||
server.bindAsync(
|
server.bindAsync(
|
||||||
`localhost:${config.cronPort}`,
|
`0.0.0.0:${config.cronPort}`,
|
||||||
ServerCredentials.createInsecure(),
|
ServerCredentials.createInsecure(),
|
||||||
(err, port) => {
|
(err, port) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -19,6 +19,7 @@ server.bindAsync(
|
|||||||
}
|
}
|
||||||
server.start();
|
server.start();
|
||||||
Logger.debug(`✌️ 定时服务启动成功!`);
|
Logger.debug(`✌️ 定时服务启动成功!`);
|
||||||
|
console.debug(`✌️ 定时服务启动成功!`);
|
||||||
process.send?.('ready');
|
process.send?.('ready');
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
+22
-20
@@ -5,7 +5,7 @@ import { Crontab, CrontabModel, CrontabStatus } from '../data/cron';
|
|||||||
import { exec, execSync } from 'child_process';
|
import { exec, execSync } from 'child_process';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import cron_parser from 'cron-parser';
|
import cron_parser from 'cron-parser';
|
||||||
import { getFileContentByName, fileExist, killTask } from '../config/util';
|
import { getFileContentByName, fileExist, killTask, getUniqPath, safeJSONParse } from '../config/util';
|
||||||
import { promises, existsSync } from 'fs';
|
import { promises, existsSync } from 'fs';
|
||||||
import { Op, where, col as colFn, FindOptions, fn } from 'sequelize';
|
import { Op, where, col as colFn, FindOptions, fn } from 'sequelize';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
@@ -13,10 +13,11 @@ import { TASK_PREFIX, QL_PREFIX } from '../config/const';
|
|||||||
import cronClient from '../schedule/client';
|
import cronClient from '../schedule/client';
|
||||||
import taskLimit from '../shared/pLimit';
|
import taskLimit from '../shared/pLimit';
|
||||||
import { spawn } from 'cross-spawn';
|
import { spawn } from 'cross-spawn';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export default class CronService {
|
export default class CronService {
|
||||||
constructor(@Inject('logger') private logger: winston.Logger) {}
|
constructor(@Inject('logger') private logger: winston.Logger) { }
|
||||||
|
|
||||||
private isSixCron(cron: Crontab) {
|
private isSixCron(cron: Crontab) {
|
||||||
const { schedule } = cron;
|
const { schedule } = cron;
|
||||||
@@ -161,7 +162,7 @@ export default class CronService {
|
|||||||
case 'In':
|
case 'In':
|
||||||
q[Op.or] = [
|
q[Op.or] = [
|
||||||
{
|
{
|
||||||
[property]: value,
|
[property]: Array.isArray(value) ? value : [value],
|
||||||
},
|
},
|
||||||
property === 'status' && value.includes(2)
|
property === 'status' && value.includes(2)
|
||||||
? { isDisabled: 1 }
|
? { isDisabled: 1 }
|
||||||
@@ -172,7 +173,7 @@ export default class CronService {
|
|||||||
q[Op.and] = [
|
q[Op.and] = [
|
||||||
{
|
{
|
||||||
[property]: {
|
[property]: {
|
||||||
[Op.notIn]: value,
|
[Op.notIn]: Array.isArray(value) ? value : [value],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
property === 'status' && value.includes(2)
|
property === 'status' && value.includes(2)
|
||||||
@@ -308,9 +309,9 @@ export default class CronService {
|
|||||||
const searchText = params?.searchValue;
|
const searchText = params?.searchValue;
|
||||||
const page = Number(params?.page || '0');
|
const page = Number(params?.page || '0');
|
||||||
const size = Number(params?.size || '0');
|
const size = Number(params?.size || '0');
|
||||||
const viewQuery = JSON.parse(params?.queryString || '{}');
|
const viewQuery = safeJSONParse(params?.queryString);
|
||||||
const filterQuery = JSON.parse(params?.filters || '{}');
|
const filterQuery = safeJSONParse(params?.filters);
|
||||||
const sorterQuery = JSON.parse(params?.sorter || '{}');
|
const sorterQuery = safeJSONParse(params?.sorter);
|
||||||
|
|
||||||
let query: any = {};
|
let query: any = {};
|
||||||
let order = [
|
let order = [
|
||||||
@@ -370,7 +371,7 @@ export default class CronService {
|
|||||||
try {
|
try {
|
||||||
await killTask(doc.pid);
|
await killTask(doc.pid);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.silly(error);
|
this.logger.error(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -391,8 +392,14 @@ export default class CronService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let { id, command, log_path } = cron;
|
let { id, command, log_path } = cron;
|
||||||
const absolutePath = path.resolve(config.logPath, `${log_path}`);
|
const uniqPath = await getUniqPath(command, `${id}`);
|
||||||
const logFileExist = log_path && (await fileExist(absolutePath));
|
const logTime = dayjs().format('YYYY-MM-DD-HH-mm-ss-SSS');
|
||||||
|
const logDirPath = path.resolve(config.logPath, `${uniqPath}`);
|
||||||
|
if (log_path?.split('/')?.every(x => x !== uniqPath)) {
|
||||||
|
fs.mkdirSync(logDirPath, { recursive: true });
|
||||||
|
}
|
||||||
|
const logPath = `${uniqPath}/${logTime}.log`;
|
||||||
|
const absolutePath = path.resolve(config.logPath, `${logPath}`);
|
||||||
|
|
||||||
this.logger.silly('Running job');
|
this.logger.silly('Running job');
|
||||||
this.logger.silly('ID: ' + id);
|
this.logger.silly('ID: ' + id);
|
||||||
@@ -412,26 +419,22 @@ export default class CronService {
|
|||||||
cmdStr = `${cmdStr} now`;
|
cmdStr = `${cmdStr} now`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const cp = spawn(`ID=${id} ${cmdStr}`, { shell: '/bin/bash' });
|
const cp = spawn(`real_log_path=${logPath} ID=${id} ${cmdStr}`, { shell: '/bin/bash' });
|
||||||
|
|
||||||
await CrontabModel.update(
|
await CrontabModel.update(
|
||||||
{ status: CrontabStatus.running, pid: cp.pid },
|
{ status: CrontabStatus.running, pid: cp.pid, log_path: logPath },
|
||||||
{ where: { id } },
|
{ where: { id } },
|
||||||
);
|
);
|
||||||
cp.stderr.on('data', (data) => {
|
cp.stderr.on('data', (data) => {
|
||||||
if (logFileExist) {
|
fs.appendFileSync(`${absolutePath}`, `${data.toString()}`);
|
||||||
fs.appendFileSync(`${absolutePath}`, `${data.toString()}`);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
cp.on('error', (err) => {
|
cp.on('error', (err) => {
|
||||||
if (logFileExist) {
|
fs.appendFileSync(`${absolutePath}`, `${JSON.stringify(err)}`);
|
||||||
fs.appendFileSync(`${absolutePath}`, `${JSON.stringify(err)}`);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
cp.on('exit', async (code, signal) => {
|
cp.on('exit', async (code, signal) => {
|
||||||
this.logger.info(
|
this.logger.info(
|
||||||
`任务 ${command} 进程id: ${cp.pid} 退出,退出码 ${code}`,
|
`[panel][任务退出] 任务 ${command} 进程id: ${cp.pid}, 退出码 ${code}`,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
cp.on('close', async (code) => {
|
cp.on('close', async (code) => {
|
||||||
@@ -530,7 +533,6 @@ export default class CronService {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.logger.silly(crontab_string);
|
|
||||||
fs.writeFileSync(config.crontabFile, crontab_string);
|
fs.writeFileSync(config.crontabFile, crontab_string);
|
||||||
|
|
||||||
execSync(`crontab ${config.crontabFile}`);
|
execSync(`crontab ${config.crontabFile}`);
|
||||||
|
|||||||
@@ -202,11 +202,9 @@ export default class EnvService {
|
|||||||
let value = group
|
let value = group
|
||||||
.map((x) => x.value)
|
.map((x) => x.value)
|
||||||
.join('&')
|
.join('&')
|
||||||
.replace(/(\\)[^n]/g, '\\\\')
|
.replace(/'/g, "'\\''")
|
||||||
.replace(/(\\$)/, '\\\\')
|
|
||||||
.replace(/"/g, '\\"')
|
|
||||||
.trim();
|
.trim();
|
||||||
env_string += `export ${key}="${value}"\n`;
|
env_string += `export ${key}='${value}'\n`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-14
@@ -66,9 +66,8 @@ export default class ScheduleService {
|
|||||||
|
|
||||||
cp.stderr.on('data', async (data) => {
|
cp.stderr.on('data', async (data) => {
|
||||||
this.logger.info(
|
this.logger.info(
|
||||||
'[执行任务失败] %s,时间:%s, 错误信息:%j',
|
'[panel][执行任务失败] 命令: %s, 错误信息: %j',
|
||||||
command,
|
command,
|
||||||
new Date().toLocaleString(),
|
|
||||||
data.toString(),
|
data.toString(),
|
||||||
);
|
);
|
||||||
await callbacks.onError?.(data.toString());
|
await callbacks.onError?.(data.toString());
|
||||||
@@ -76,9 +75,8 @@ export default class ScheduleService {
|
|||||||
|
|
||||||
cp.on('error', async (err) => {
|
cp.on('error', async (err) => {
|
||||||
this.logger.error(
|
this.logger.error(
|
||||||
'[创建任务失败] %s,时间:%s, 错误信息:%j',
|
'[panel][创建任务失败] 命令: %s, 错误信息: %j',
|
||||||
command,
|
command,
|
||||||
new Date().toLocaleString(),
|
|
||||||
err,
|
err,
|
||||||
);
|
);
|
||||||
await callbacks.onError?.(JSON.stringify(err));
|
await callbacks.onError?.(JSON.stringify(err));
|
||||||
@@ -86,7 +84,7 @@ export default class ScheduleService {
|
|||||||
|
|
||||||
cp.on('exit', async (code, signal) => {
|
cp.on('exit', async (code, signal) => {
|
||||||
this.logger.info(
|
this.logger.info(
|
||||||
`[任务退出] ${command} 进程id: ${cp.pid},退出码 ${code}`,
|
`[panel][任务退出] ${command} 进程id: ${cp.pid}, 退出码 ${code}`,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -100,10 +98,9 @@ export default class ScheduleService {
|
|||||||
resolve(null);
|
resolve(null);
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
await this.logger.error(
|
this.logger.error(
|
||||||
'执行任务%s失败,时间:%s, 错误信息:%j',
|
'[panel][执行任务失败] 命令: %s, 错误信息: %j',
|
||||||
command,
|
command,
|
||||||
new Date().toLocaleString(),
|
|
||||||
error,
|
error,
|
||||||
);
|
);
|
||||||
await callbacks.onError?.(JSON.stringify(error));
|
await callbacks.onError?.(JSON.stringify(error));
|
||||||
@@ -119,7 +116,7 @@ export default class ScheduleService {
|
|||||||
) {
|
) {
|
||||||
const _id = this.formatId(id);
|
const _id = this.formatId(id);
|
||||||
this.logger.info(
|
this.logger.info(
|
||||||
'[创建cron任务],任务ID: %s,cron: %s,任务名: %s,执行命令: %s',
|
'[panel][创建cron任务], 任务ID: %s, cron: %s, 任务名: %s, 执行命令: %s',
|
||||||
_id,
|
_id,
|
||||||
schedule,
|
schedule,
|
||||||
name,
|
name,
|
||||||
@@ -140,7 +137,7 @@ export default class ScheduleService {
|
|||||||
|
|
||||||
async cancelCronTask({ id = 0, name }: ScheduleTaskType) {
|
async cancelCronTask({ id = 0, name }: ScheduleTaskType) {
|
||||||
const _id = this.formatId(id);
|
const _id = this.formatId(id);
|
||||||
this.logger.info('[取消定时任务],任务名:%s', name);
|
this.logger.info('[panel][取消定时任务], 任务名: %s', name);
|
||||||
if (this.scheduleStacks.has(_id)) {
|
if (this.scheduleStacks.has(_id)) {
|
||||||
this.scheduleStacks.get(_id)?.cancel();
|
this.scheduleStacks.get(_id)?.cancel();
|
||||||
this.scheduleStacks.delete(_id);
|
this.scheduleStacks.delete(_id);
|
||||||
@@ -155,7 +152,7 @@ export default class ScheduleService {
|
|||||||
) {
|
) {
|
||||||
const _id = this.formatId(id);
|
const _id = this.formatId(id);
|
||||||
this.logger.info(
|
this.logger.info(
|
||||||
'[创建interval任务],任务ID: %s,任务名: %s,执行命令: %s',
|
'[panel][创建interval任务], 任务ID: %s, 任务名: %s, 执行命令: %s',
|
||||||
_id,
|
_id,
|
||||||
name,
|
name,
|
||||||
command,
|
command,
|
||||||
@@ -167,9 +164,8 @@ export default class ScheduleService {
|
|||||||
},
|
},
|
||||||
(err) => {
|
(err) => {
|
||||||
this.logger.error(
|
this.logger.error(
|
||||||
'执行任务%s失败,时间:%s, 错误信息:%j',
|
'[执行任务失败] 命令: %s, 错误信息: %j',
|
||||||
command,
|
command,
|
||||||
new Date().toLocaleString(),
|
|
||||||
err,
|
err,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -190,7 +186,7 @@ export default class ScheduleService {
|
|||||||
|
|
||||||
async cancelIntervalTask({ id = 0, name }: ScheduleTaskType) {
|
async cancelIntervalTask({ id = 0, name }: ScheduleTaskType) {
|
||||||
const _id = this.formatId(id);
|
const _id = this.formatId(id);
|
||||||
this.logger.info('[取消interval任务],任务ID: %s,任务名:%s', _id, name);
|
this.logger.info('[取消interval任务], 任务ID: %s, 任务名: %s', _id, name);
|
||||||
this.intervalSchedule.removeById(_id);
|
this.intervalSchedule.removeById(_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,10 +53,9 @@ export default class ScriptService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async stopScript(filePath: string, pid: number) {
|
public async stopScript(filePath: string, pid: number) {
|
||||||
let str = '';
|
|
||||||
if (!pid) {
|
if (!pid) {
|
||||||
const relativePath = path.relative(config.scriptPath, filePath);
|
const relativePath = path.relative(config.scriptPath, filePath);
|
||||||
pid = await getPid(`${TASK_COMMAND} -l ${relativePath} now`);
|
pid = await getPid(`${TASK_COMMAND} -l ${relativePath} now`) as number;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await killTask(pid);
|
await killTask(pid);
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ export default class SshKeyService {
|
|||||||
|
|
||||||
private generateSingleSshConfig(alias: string, host: string, proxy?: string) {
|
private generateSingleSshConfig(alias: string, host: string, proxy?: string) {
|
||||||
if (host === 'github.com') {
|
if (host === 'github.com') {
|
||||||
host = `ssh.github.com\n Port 443\n HostkeyAlgorithms +ssh-rsa\n PubkeyAcceptedAlgorithms +ssh-rsa`;
|
host = `ssh.github.com\n Port 443\n HostkeyAlgorithms +ssh-rsa`;
|
||||||
}
|
}
|
||||||
const proxyStr = proxy
|
const proxyStr = proxy
|
||||||
? ` ProxyCommand nc -v -x ${proxy} %h %p 2>/dev/null\n`
|
? ` ProxyCommand nc -v -x ${proxy} %h %p 2>/dev/null\n`
|
||||||
|
|||||||
@@ -301,17 +301,9 @@ export default class SubscriptionService {
|
|||||||
try {
|
try {
|
||||||
await killTask(doc.pid);
|
await killTask(doc.pid);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.silly(error);
|
this.logger.error(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const absolutePath = await handleLogPath(doc.log_path as string);
|
|
||||||
|
|
||||||
fs.appendFileSync(
|
|
||||||
`${absolutePath}`,
|
|
||||||
`\n## 执行结束... ${dayjs().format(
|
|
||||||
'YYYY-MM-DD HH:mm:ss',
|
|
||||||
)}${LOG_END_SYMBOL}`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await SubscriptionModel.update(
|
await SubscriptionModel.update(
|
||||||
|
|||||||
@@ -21,11 +21,14 @@ import {
|
|||||||
parseContentVersion,
|
parseContentVersion,
|
||||||
parseVersion,
|
parseVersion,
|
||||||
promiseExec,
|
promiseExec,
|
||||||
|
readDirs,
|
||||||
} from '../config/util';
|
} from '../config/util';
|
||||||
import { TASK_COMMAND } from '../config/const';
|
import { TASK_COMMAND } from '../config/const';
|
||||||
import taskLimit from '../shared/pLimit';
|
import taskLimit from '../shared/pLimit';
|
||||||
import tar from 'tar';
|
import tar from 'tar';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
import fs from 'fs';
|
||||||
|
import { sum } from 'lodash';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export default class SystemService {
|
export default class SystemService {
|
||||||
@@ -275,4 +278,29 @@ export default class SystemService {
|
|||||||
return { code: 400, message: error.message };
|
return { code: 400, message: error.message };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async getSystemLog(res: Response) {
|
||||||
|
const result = readDirs(config.systemLogPath, config.systemLogPath);
|
||||||
|
const logs = result.reverse().filter((x) => x.title.endsWith('.log'));
|
||||||
|
res.set({
|
||||||
|
'Content-Length': sum(logs.map((x) => x.size)),
|
||||||
|
});
|
||||||
|
(function sendFiles(res, fileNames) {
|
||||||
|
if (fileNames.length === 0) {
|
||||||
|
res.end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentLog = fileNames.shift();
|
||||||
|
if (currentLog) {
|
||||||
|
const currentFileStream = fs.createReadStream(
|
||||||
|
path.join(config.systemLogPath, currentLog.title),
|
||||||
|
);
|
||||||
|
currentFileStream.on('end', () => {
|
||||||
|
sendFiles(res, fileNames);
|
||||||
|
});
|
||||||
|
currentFileStream.pipe(res, { end: false });
|
||||||
|
}
|
||||||
|
})(res, logs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
fileExist,
|
fileExist,
|
||||||
getNetIp,
|
getNetIp,
|
||||||
getPlatform,
|
getPlatform,
|
||||||
|
safeJSONParse,
|
||||||
} from '../config/util';
|
} from '../config/util';
|
||||||
import config from '../config';
|
import config from '../config';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
@@ -327,7 +328,7 @@ export default class UserService {
|
|||||||
|
|
||||||
private getAuthInfo() {
|
private getAuthInfo() {
|
||||||
const content = fs.readFileSync(config.authConfigFile, 'utf8');
|
const content = fs.readFileSync(config.authConfigFile, 'utf8');
|
||||||
return JSON.parse(content || '{}');
|
return safeJSONParse(content);
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateAuthInfo(authInfo: any, info: any) {
|
private updateAuthInfo(authInfo: any, info: any) {
|
||||||
|
|||||||
@@ -1,12 +1,22 @@
|
|||||||
import pLimit from 'p-limit';
|
import pLimit from 'p-limit';
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
import { AuthDataType, AuthModel } from '../data/auth';
|
import { AuthDataType, AuthModel } from '../data/auth';
|
||||||
|
import Logger from '../loaders/logger';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
class TaskLimit {
|
class TaskLimit {
|
||||||
private oneLimit = pLimit(1);
|
private oneLimit = pLimit(1);
|
||||||
private updateLogLimit = pLimit(1);
|
private updateLogLimit = pLimit(1);
|
||||||
private cpuLimit = pLimit(Math.max(os.cpus().length, 4));
|
private cpuLimit = pLimit(Math.max(os.cpus().length, 4));
|
||||||
|
|
||||||
|
get cpuLimitActiveCount() {
|
||||||
|
return this.cpuLimit.activeCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
get cpuLimitPendingCount() {
|
||||||
|
return this.cpuLimit.pendingCount;
|
||||||
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.setCustomLimit();
|
this.setCustomLimit();
|
||||||
}
|
}
|
||||||
@@ -26,6 +36,9 @@ class TaskLimit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public runWithCpuLimit<T>(fn: () => Promise<T>): Promise<T> {
|
public runWithCpuLimit<T>(fn: () => Promise<T>): Promise<T> {
|
||||||
|
Logger.info(
|
||||||
|
`[schedule][任务加入队列] 运行中任务数: ${this.cpuLimitActiveCount}, 等待中任务数: ${this.cpuLimitPendingCount}`,
|
||||||
|
);
|
||||||
return this.cpuLimit(fn);
|
return this.cpuLimit(fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,29 +5,27 @@ import Logger from '../loaders/logger';
|
|||||||
export function runCron(cmd: string): Promise<number> {
|
export function runCron(cmd: string): Promise<number> {
|
||||||
return taskLimit.runWithCpuLimit(() => {
|
return taskLimit.runWithCpuLimit(() => {
|
||||||
return new Promise(async (resolve: any) => {
|
return new Promise(async (resolve: any) => {
|
||||||
Logger.silly('运行命令: ' + cmd);
|
Logger.info(`[schedule][开始执行任务] 运行命令: ${cmd}`);
|
||||||
|
|
||||||
const cp = spawn(cmd, { shell: '/bin/bash' });
|
const cp = spawn(cmd, { shell: '/bin/bash' });
|
||||||
|
|
||||||
cp.stderr.on('data', (data) => {
|
cp.stderr.on('data', (data) => {
|
||||||
Logger.info(
|
Logger.info(
|
||||||
'[执行任务失败] %s,时间:%s, 错误信息:%j',
|
'[schedule][执行任务失败] 命令: %s, 错误信息: %j',
|
||||||
cmd,
|
cmd,
|
||||||
new Date().toLocaleString(),
|
|
||||||
data.toString(),
|
data.toString(),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
cp.on('error', (err) => {
|
cp.on('error', (err) => {
|
||||||
Logger.error(
|
Logger.error(
|
||||||
'[创建任务失败] %s,时间:%s, 错误信息:%j',
|
'[schedule][创建任务失败] 命令: %s, 错误信息: %j',
|
||||||
cmd,
|
cmd,
|
||||||
new Date().toLocaleString(),
|
|
||||||
err,
|
err,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
cp.on('close', async (code) => {
|
cp.on('close', async (code) => {
|
||||||
Logger.info(`[任务退出] ${cmd} 进程id: ${cp.pid} 退出,退出码 ${code}`);
|
Logger.info(`[schedule][任务退出] ${cmd} 进程id: ${cp.pid} 退出, 退出码 ${code}`);
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
+3
-2
@@ -96,6 +96,7 @@
|
|||||||
"typedi": "^0.10.0",
|
"typedi": "^0.10.0",
|
||||||
"uuid": "^8.3.2",
|
"uuid": "^8.3.2",
|
||||||
"winston": "^3.6.0",
|
"winston": "^3.6.0",
|
||||||
|
"winston-daily-rotate-file": "^4.7.1",
|
||||||
"yargs": "^17.3.1"
|
"yargs": "^17.3.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -127,6 +128,8 @@
|
|||||||
"@types/sockjs-client": "^1.5.1",
|
"@types/sockjs-client": "^1.5.1",
|
||||||
"@types/tar": "^6.1.5",
|
"@types/tar": "^6.1.5",
|
||||||
"@types/uuid": "^8.3.4",
|
"@types/uuid": "^8.3.4",
|
||||||
|
"@uiw/codemirror-extensions-langs": "^4.21.9",
|
||||||
|
"@uiw/react-codemirror": "^4.21.9",
|
||||||
"@umijs/max": "^4.0.72",
|
"@umijs/max": "^4.0.72",
|
||||||
"@umijs/ssr-darkreader": "^4.9.45",
|
"@umijs/ssr-darkreader": "^4.9.45",
|
||||||
"ahooks": "^3.7.8",
|
"ahooks": "^3.7.8",
|
||||||
@@ -134,7 +137,6 @@
|
|||||||
"antd": "^4.24.8",
|
"antd": "^4.24.8",
|
||||||
"antd-img-crop": "^4.2.3",
|
"antd-img-crop": "^4.2.3",
|
||||||
"axios": "^1.4.0",
|
"axios": "^1.4.0",
|
||||||
"codemirror": "^5.65.2",
|
|
||||||
"compression-webpack-plugin": "9.2.0",
|
"compression-webpack-plugin": "9.2.0",
|
||||||
"concurrently": "^7.0.0",
|
"concurrently": "^7.0.0",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
@@ -148,7 +150,6 @@
|
|||||||
"rc-tween-one": "^3.0.6",
|
"rc-tween-one": "^3.0.6",
|
||||||
"rc-virtual-list": "3.5.3",
|
"rc-virtual-list": "3.5.3",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-codemirror2": "^7.2.1",
|
|
||||||
"react-copy-to-clipboard": "^5.1.0",
|
"react-copy-to-clipboard": "^5.1.0",
|
||||||
"react-diff-viewer": "^3.1.1",
|
"react-diff-viewer": "^3.1.1",
|
||||||
"react-dnd": "^14.0.2",
|
"react-dnd": "^14.0.2",
|
||||||
|
|||||||
Generated
+649
-21
@@ -124,6 +124,9 @@ dependencies:
|
|||||||
winston:
|
winston:
|
||||||
specifier: ^3.6.0
|
specifier: ^3.6.0
|
||||||
version: 3.9.0
|
version: 3.9.0
|
||||||
|
winston-daily-rotate-file:
|
||||||
|
specifier: ^4.7.1
|
||||||
|
version: 4.7.1(winston@3.9.0)
|
||||||
yargs:
|
yargs:
|
||||||
specifier: ^17.3.1
|
specifier: ^17.3.1
|
||||||
version: 17.7.2
|
version: 17.7.2
|
||||||
@@ -213,6 +216,12 @@ devDependencies:
|
|||||||
'@types/uuid':
|
'@types/uuid':
|
||||||
specifier: ^8.3.4
|
specifier: ^8.3.4
|
||||||
version: 8.3.4
|
version: 8.3.4
|
||||||
|
'@uiw/codemirror-extensions-langs':
|
||||||
|
specifier: ^4.21.9
|
||||||
|
version: 4.21.9(@codemirror/autocomplete@6.9.0)(@codemirror/language-data@6.3.1)(@codemirror/language@6.9.0)(@codemirror/legacy-modes@6.3.3)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.4)(@lezer/highlight@1.1.6)(@lezer/javascript@1.4.5)(@lezer/lr@1.3.10)
|
||||||
|
'@uiw/react-codemirror':
|
||||||
|
specifier: ^4.21.9
|
||||||
|
version: 4.21.9(@babel/runtime@7.22.3)(@codemirror/autocomplete@6.9.0)(@codemirror/language@6.9.0)(@codemirror/lint@6.4.0)(@codemirror/search@6.5.1)(@codemirror/state@6.2.1)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.16.0)(codemirror@6.0.1)(react-dom@18.2.0)(react@18.2.0)
|
||||||
'@umijs/max':
|
'@umijs/max':
|
||||||
specifier: ^4.0.72
|
specifier: ^4.0.72
|
||||||
version: 4.0.72(@types/node@17.0.45)(@types/react-dom@18.2.4)(@types/react@18.2.8)(prettier@2.8.8)(react-dom@18.2.0)(react@18.2.0)(sockjs-client@1.6.1)(typescript@4.8.4)(webpack@5.85.1)
|
version: 4.0.72(@types/node@17.0.45)(@types/react-dom@18.2.4)(@types/react@18.2.8)(prettier@2.8.8)(react-dom@18.2.0)(react@18.2.0)(sockjs-client@1.6.1)(typescript@4.8.4)(webpack@5.85.1)
|
||||||
@@ -234,9 +243,6 @@ devDependencies:
|
|||||||
axios:
|
axios:
|
||||||
specifier: ^1.4.0
|
specifier: ^1.4.0
|
||||||
version: 1.4.0
|
version: 1.4.0
|
||||||
codemirror:
|
|
||||||
specifier: ^5.65.2
|
|
||||||
version: 5.65.13
|
|
||||||
compression-webpack-plugin:
|
compression-webpack-plugin:
|
||||||
specifier: 9.2.0
|
specifier: 9.2.0
|
||||||
version: 9.2.0(webpack@5.85.1)
|
version: 9.2.0(webpack@5.85.1)
|
||||||
@@ -276,9 +282,6 @@ devDependencies:
|
|||||||
react:
|
react:
|
||||||
specifier: 18.2.0
|
specifier: 18.2.0
|
||||||
version: 18.2.0
|
version: 18.2.0
|
||||||
react-codemirror2:
|
|
||||||
specifier: ^7.2.1
|
|
||||||
version: 7.2.1(codemirror@5.65.13)(react@18.2.0)
|
|
||||||
react-copy-to-clipboard:
|
react-copy-to-clipboard:
|
||||||
specifier: ^5.1.0
|
specifier: ^5.1.0
|
||||||
version: 5.1.0(react@18.2.0)
|
version: 5.1.0(react@18.2.0)
|
||||||
@@ -2762,6 +2765,298 @@ packages:
|
|||||||
tinycolor2: 1.6.0
|
tinycolor2: 1.6.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@codemirror/autocomplete@6.9.0(@codemirror/language@6.9.0)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.4):
|
||||||
|
resolution: {integrity: sha512-Fbwm0V/Wn3BkEJZRhr0hi5BhCo5a7eBL6LYaliPjOSwCyfOpnjXY59HruSxOUNV+1OYer0Tgx1zRNQttjXyDog==}
|
||||||
|
peerDependencies:
|
||||||
|
'@codemirror/language': ^6.0.0
|
||||||
|
'@codemirror/state': ^6.0.0
|
||||||
|
'@codemirror/view': ^6.0.0
|
||||||
|
'@lezer/common': ^1.0.0
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/language': 6.9.0
|
||||||
|
'@codemirror/state': 6.2.1
|
||||||
|
'@codemirror/view': 6.16.0
|
||||||
|
'@lezer/common': 1.0.4
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@codemirror/commands@6.2.4:
|
||||||
|
resolution: {integrity: sha512-42lmDqVH0ttfilLShReLXsDfASKLXzfyC36bzwcqzox9PlHulMcsUOfHXNo2X2aFMVNUoQ7j+d4q5bnfseYoOA==}
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/language': 6.9.0
|
||||||
|
'@codemirror/state': 6.2.1
|
||||||
|
'@codemirror/view': 6.16.0
|
||||||
|
'@lezer/common': 1.0.4
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@codemirror/lang-angular@0.1.2:
|
||||||
|
resolution: {integrity: sha512-Nq7lmx9SU+JyoaRcs6SaJs7uAmW2W06HpgJVQYeZptVGNWDzDvzhjwVb/ZuG1rwTlOocY4Y9GwNOBuKCeJbKtw==}
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/lang-html': 6.4.5
|
||||||
|
'@codemirror/lang-javascript': 6.1.9
|
||||||
|
'@codemirror/language': 6.9.0
|
||||||
|
'@lezer/common': 1.0.4
|
||||||
|
'@lezer/highlight': 1.1.6
|
||||||
|
'@lezer/lr': 1.3.10
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@codemirror/lang-cpp@6.0.2:
|
||||||
|
resolution: {integrity: sha512-6oYEYUKHvrnacXxWxYa6t4puTlbN3dgV662BDfSH8+MfjQjVmP697/KYTDOqpxgerkvoNm7q5wlFMBeX8ZMocg==}
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/language': 6.9.0
|
||||||
|
'@lezer/cpp': 1.1.1
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@codemirror/lang-css@6.2.1(@codemirror/view@6.16.0):
|
||||||
|
resolution: {integrity: sha512-/UNWDNV5Viwi/1lpr/dIXJNWiwDxpw13I4pTUAsNxZdg6E0mI2kTQb0P2iHczg1Tu+H4EBgJR+hYhKiHKko7qg==}
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/autocomplete': 6.9.0(@codemirror/language@6.9.0)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.4)
|
||||||
|
'@codemirror/language': 6.9.0
|
||||||
|
'@codemirror/state': 6.2.1
|
||||||
|
'@lezer/common': 1.0.4
|
||||||
|
'@lezer/css': 1.1.3
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@codemirror/view'
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@codemirror/lang-html@6.4.5:
|
||||||
|
resolution: {integrity: sha512-dUCSxkIw2G+chaUfw3Gfu5kkN83vJQN8gfQDp9iEHsIZluMJA0YJveT12zg/28BJx+uPsbQ6VimKCgx3oJrZxA==}
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/autocomplete': 6.9.0(@codemirror/language@6.9.0)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.4)
|
||||||
|
'@codemirror/lang-css': 6.2.1(@codemirror/view@6.16.0)
|
||||||
|
'@codemirror/lang-javascript': 6.1.9
|
||||||
|
'@codemirror/language': 6.9.0
|
||||||
|
'@codemirror/state': 6.2.1
|
||||||
|
'@codemirror/view': 6.16.0
|
||||||
|
'@lezer/common': 1.0.4
|
||||||
|
'@lezer/css': 1.1.3
|
||||||
|
'@lezer/html': 1.3.6
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@codemirror/lang-java@6.0.1:
|
||||||
|
resolution: {integrity: sha512-OOnmhH67h97jHzCuFaIEspbmsT98fNdhVhmA3zCxW0cn7l8rChDhZtwiwJ/JOKXgfm4J+ELxQihxaI7bj7mJRg==}
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/language': 6.9.0
|
||||||
|
'@lezer/java': 1.0.4
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@codemirror/lang-javascript@6.1.9:
|
||||||
|
resolution: {integrity: sha512-z3jdkcqOEBT2txn2a87A0jSy6Te3679wg/U8QzMeftFt+4KA6QooMwfdFzJiuC3L6fXKfTXZcDocoaxMYfGz0w==}
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/autocomplete': 6.9.0(@codemirror/language@6.9.0)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.4)
|
||||||
|
'@codemirror/language': 6.9.0
|
||||||
|
'@codemirror/lint': 6.4.0
|
||||||
|
'@codemirror/state': 6.2.1
|
||||||
|
'@codemirror/view': 6.16.0
|
||||||
|
'@lezer/common': 1.0.4
|
||||||
|
'@lezer/javascript': 1.4.5
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@codemirror/lang-json@6.0.1:
|
||||||
|
resolution: {integrity: sha512-+T1flHdgpqDDlJZ2Lkil/rLiRy684WMLc74xUnjJH48GQdfJo/pudlTRreZmKwzP8/tGdKf83wlbAdOCzlJOGQ==}
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/language': 6.9.0
|
||||||
|
'@lezer/json': 1.0.1
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@codemirror/lang-less@6.0.1(@codemirror/view@6.16.0):
|
||||||
|
resolution: {integrity: sha512-ABcsKBjLbyPZwPR5gePpc8jEKCQrFF4pby2WlMVdmJOOr7OWwwyz8DZonPx/cKDE00hfoSLc8F7yAcn/d6+rTQ==}
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/lang-css': 6.2.1(@codemirror/view@6.16.0)
|
||||||
|
'@codemirror/language': 6.9.0
|
||||||
|
'@lezer/highlight': 1.1.6
|
||||||
|
'@lezer/lr': 1.3.10
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@codemirror/view'
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@codemirror/lang-lezer@6.0.1:
|
||||||
|
resolution: {integrity: sha512-WHwjI7OqKFBEfkunohweqA5B/jIlxaZso6Nl3weVckz8EafYbPZldQEKSDb4QQ9H9BUkle4PVELP4sftKoA0uQ==}
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/language': 6.9.0
|
||||||
|
'@codemirror/state': 6.2.1
|
||||||
|
'@lezer/common': 1.0.4
|
||||||
|
'@lezer/lezer': 1.1.2
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@codemirror/lang-markdown@6.2.0:
|
||||||
|
resolution: {integrity: sha512-deKegEQVzfBAcLPqsJEa+IxotqPVwWZi90UOEvQbfa01NTAw8jNinrykuYPTULGUj+gha0ZG2HBsn4s5d64Qrg==}
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/autocomplete': 6.9.0(@codemirror/language@6.9.0)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.4)
|
||||||
|
'@codemirror/lang-html': 6.4.5
|
||||||
|
'@codemirror/language': 6.9.0
|
||||||
|
'@codemirror/state': 6.2.1
|
||||||
|
'@codemirror/view': 6.16.0
|
||||||
|
'@lezer/common': 1.0.4
|
||||||
|
'@lezer/markdown': 1.1.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@codemirror/lang-php@6.0.1:
|
||||||
|
resolution: {integrity: sha512-ublojMdw/PNWa7qdN5TMsjmqkNuTBD3k6ndZ4Z0S25SBAiweFGyY68AS3xNcIOlb6DDFDvKlinLQ40vSLqf8xA==}
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/lang-html': 6.4.5
|
||||||
|
'@codemirror/language': 6.9.0
|
||||||
|
'@codemirror/state': 6.2.1
|
||||||
|
'@lezer/common': 1.0.4
|
||||||
|
'@lezer/php': 1.0.1
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@codemirror/lang-python@6.1.3(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.4):
|
||||||
|
resolution: {integrity: sha512-S9w2Jl74hFlD5nqtUMIaXAq9t5WlM0acCkyuQWUUSvZclk1sV+UfnpFiZzuZSG+hfEaOmxKR5UxY/Uxswn7EhQ==}
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/autocomplete': 6.9.0(@codemirror/language@6.9.0)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.4)
|
||||||
|
'@codemirror/language': 6.9.0
|
||||||
|
'@lezer/python': 1.1.8
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@codemirror/state'
|
||||||
|
- '@codemirror/view'
|
||||||
|
- '@lezer/common'
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@codemirror/lang-rust@6.0.1:
|
||||||
|
resolution: {integrity: sha512-344EMWFBzWArHWdZn/NcgkwMvZIWUR1GEBdwG8FEp++6o6vT6KL9V7vGs2ONsKxxFUPXKI0SPcWhyYyl2zPYxQ==}
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/language': 6.9.0
|
||||||
|
'@lezer/rust': 1.0.1
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@codemirror/lang-sass@6.0.2(@codemirror/view@6.16.0):
|
||||||
|
resolution: {integrity: sha512-l/bdzIABvnTo1nzdY6U+kPAC51czYQcOErfzQ9zSm9D8GmNPD0WTW8st/CJwBTPLO8jlrbyvlSEcN20dc4iL0Q==}
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/lang-css': 6.2.1(@codemirror/view@6.16.0)
|
||||||
|
'@codemirror/language': 6.9.0
|
||||||
|
'@codemirror/state': 6.2.1
|
||||||
|
'@lezer/common': 1.0.4
|
||||||
|
'@lezer/sass': 1.0.3
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@codemirror/view'
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@codemirror/lang-sql@6.5.4(@codemirror/view@6.16.0)(@lezer/common@1.0.4):
|
||||||
|
resolution: {integrity: sha512-5Gq7fYtT/5HbNyIG7a8vYaqOYQU3JbgtBe3+derkrFUXRVcjkf8WVgz++PIbMFAQsOFMDdDR+uiNM8ZRRuXH+w==}
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/autocomplete': 6.9.0(@codemirror/language@6.9.0)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.4)
|
||||||
|
'@codemirror/language': 6.9.0
|
||||||
|
'@codemirror/state': 6.2.1
|
||||||
|
'@lezer/highlight': 1.1.6
|
||||||
|
'@lezer/lr': 1.3.10
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@codemirror/view'
|
||||||
|
- '@lezer/common'
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@codemirror/lang-vue@0.1.2:
|
||||||
|
resolution: {integrity: sha512-D4YrefiRBAr+CfEIM4S3yvGSbYW+N69mttIfGMEf7diHpRbmygDxS+R/5xSqjgtkY6VO6qmUrre1GkRcWeZa9A==}
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/lang-html': 6.4.5
|
||||||
|
'@codemirror/lang-javascript': 6.1.9
|
||||||
|
'@codemirror/language': 6.9.0
|
||||||
|
'@lezer/common': 1.0.4
|
||||||
|
'@lezer/highlight': 1.1.6
|
||||||
|
'@lezer/lr': 1.3.10
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@codemirror/lang-wast@6.0.1:
|
||||||
|
resolution: {integrity: sha512-sQLsqhRjl2MWG3rxZysX+2XAyed48KhLBHLgq9xcKxIJu3npH/G+BIXW5NM5mHeDUjG0jcGh9BcjP0NfMStuzA==}
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/language': 6.9.0
|
||||||
|
'@lezer/highlight': 1.1.6
|
||||||
|
'@lezer/lr': 1.3.10
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@codemirror/lang-xml@6.0.2(@codemirror/view@6.16.0):
|
||||||
|
resolution: {integrity: sha512-JQYZjHL2LAfpiZI2/qZ/qzDuSqmGKMwyApYmEUUCTxLM4MWS7sATUEfIguZQr9Zjx/7gcdnewb039smF6nC2zw==}
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/autocomplete': 6.9.0(@codemirror/language@6.9.0)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.4)
|
||||||
|
'@codemirror/language': 6.9.0
|
||||||
|
'@codemirror/state': 6.2.1
|
||||||
|
'@lezer/common': 1.0.4
|
||||||
|
'@lezer/xml': 1.0.2
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@codemirror/view'
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@codemirror/language-data@6.3.1(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.4):
|
||||||
|
resolution: {integrity: sha512-p6jhJmvhGe1TG1EGNhwH7nFWWFSTJ8NDKnB2fVx5g3t+PpO0+63R7GJNxjS0TmmH3cdMxZbzejsik+rlEh1EyQ==}
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/lang-angular': 0.1.2
|
||||||
|
'@codemirror/lang-cpp': 6.0.2
|
||||||
|
'@codemirror/lang-css': 6.2.1(@codemirror/view@6.16.0)
|
||||||
|
'@codemirror/lang-html': 6.4.5
|
||||||
|
'@codemirror/lang-java': 6.0.1
|
||||||
|
'@codemirror/lang-javascript': 6.1.9
|
||||||
|
'@codemirror/lang-json': 6.0.1
|
||||||
|
'@codemirror/lang-less': 6.0.1(@codemirror/view@6.16.0)
|
||||||
|
'@codemirror/lang-markdown': 6.2.0
|
||||||
|
'@codemirror/lang-php': 6.0.1
|
||||||
|
'@codemirror/lang-python': 6.1.3(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.4)
|
||||||
|
'@codemirror/lang-rust': 6.0.1
|
||||||
|
'@codemirror/lang-sass': 6.0.2(@codemirror/view@6.16.0)
|
||||||
|
'@codemirror/lang-sql': 6.5.4(@codemirror/view@6.16.0)(@lezer/common@1.0.4)
|
||||||
|
'@codemirror/lang-vue': 0.1.2
|
||||||
|
'@codemirror/lang-wast': 6.0.1
|
||||||
|
'@codemirror/lang-xml': 6.0.2(@codemirror/view@6.16.0)
|
||||||
|
'@codemirror/language': 6.9.0
|
||||||
|
'@codemirror/legacy-modes': 6.3.3
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@codemirror/state'
|
||||||
|
- '@codemirror/view'
|
||||||
|
- '@lezer/common'
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@codemirror/language@6.9.0:
|
||||||
|
resolution: {integrity: sha512-nFu311/0ne/qGuGCL3oKuktBgzVOaxCHZPZv1tLSZkNjPYxxvkjSbzno3MlErG2tgw1Yw1yF8BxMCegeMXqpiw==}
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/state': 6.2.1
|
||||||
|
'@codemirror/view': 6.16.0
|
||||||
|
'@lezer/common': 1.0.4
|
||||||
|
'@lezer/highlight': 1.1.6
|
||||||
|
'@lezer/lr': 1.3.10
|
||||||
|
style-mod: 4.0.3
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@codemirror/legacy-modes@6.3.3:
|
||||||
|
resolution: {integrity: sha512-X0Z48odJ0KIoh/HY8Ltz75/4tDYc9msQf1E/2trlxFaFFhgjpVHjZ/BCXe1Lk7s4Gd67LL/CeEEHNI+xHOiESg==}
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/language': 6.9.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@codemirror/lint@6.4.0:
|
||||||
|
resolution: {integrity: sha512-6VZ44Ysh/Zn07xrGkdtNfmHCbGSHZzFBdzWi0pbd7chAQ/iUcpLGX99NYRZTa7Ugqg4kEHCqiHhcZnH0gLIgSg==}
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/state': 6.2.1
|
||||||
|
'@codemirror/view': 6.16.0
|
||||||
|
crelt: 1.0.6
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@codemirror/search@6.5.1:
|
||||||
|
resolution: {integrity: sha512-4jupk4JwkeVbrN2pStY74q6OJEYqwosB4koA66nyLeVedadtX9MHI38j2vbYmnfDGurDApP3OZO46MrWalcjiQ==}
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/state': 6.2.1
|
||||||
|
'@codemirror/view': 6.16.0
|
||||||
|
crelt: 1.0.6
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@codemirror/state@6.2.1:
|
||||||
|
resolution: {integrity: sha512-RupHSZ8+OjNT38zU9fKH2sv+Dnlr8Eb8sl4NOnnqz95mCFTZUaiRP8Xv5MeeaG0px2b8Bnfe7YGwCV3nsBhbuw==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@codemirror/theme-one-dark@6.1.2:
|
||||||
|
resolution: {integrity: sha512-F+sH0X16j/qFLMAfbciKTxVOwkdAS336b7AXTKOZhy8BR3eH/RelsnLgLFINrpST63mmN2OuwUt0W2ndUgYwUA==}
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/language': 6.9.0
|
||||||
|
'@codemirror/state': 6.2.1
|
||||||
|
'@codemirror/view': 6.16.0
|
||||||
|
'@lezer/highlight': 1.1.6
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@codemirror/view@6.16.0:
|
||||||
|
resolution: {integrity: sha512-1Z2HkvkC3KR/oEZVuW9Ivmp8TWLzGEd8T8TA04TTwPvqogfkHBdYSlflytDOqmkUxM2d1ywTg7X2dU5mC+SXvg==}
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/state': 6.2.1
|
||||||
|
style-mod: 4.0.3
|
||||||
|
w3c-keyname: 2.2.8
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@colors/colors@1.5.0:
|
/@colors/colors@1.5.0:
|
||||||
resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==}
|
resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==}
|
||||||
engines: {node: '>=0.1.90'}
|
engines: {node: '>=0.1.90'}
|
||||||
@@ -3562,6 +3857,114 @@ packages:
|
|||||||
resolution: {integrity: sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==}
|
resolution: {integrity: sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@lezer/common@1.0.4:
|
||||||
|
resolution: {integrity: sha512-lZHlk8p67x4aIDtJl6UQrXSOP6oi7dQR3W/geFVrENdA1JDaAJWldnVqVjPMJupbTKbzDfFcePfKttqVidS/dg==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@lezer/cpp@1.1.1:
|
||||||
|
resolution: {integrity: sha512-eS1M3L3U2mDowoFVPG7tEp01SWu9/68Nx3HEBgLJVn3N9ku7g5S7WdFv0jzmcTipAyONYfZJ+7x4WRkfdB2Ung==}
|
||||||
|
dependencies:
|
||||||
|
'@lezer/highlight': 1.1.6
|
||||||
|
'@lezer/lr': 1.3.10
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@lezer/css@1.1.3:
|
||||||
|
resolution: {integrity: sha512-SjSM4pkQnQdJDVc80LYzEaMiNy9txsFbI7HsMgeVF28NdLaAdHNtQ+kB/QqDUzRBV/75NTXjJ/R5IdC8QQGxMg==}
|
||||||
|
dependencies:
|
||||||
|
'@lezer/highlight': 1.1.6
|
||||||
|
'@lezer/lr': 1.3.10
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@lezer/highlight@1.1.6:
|
||||||
|
resolution: {integrity: sha512-cmSJYa2us+r3SePpRCjN5ymCqCPv+zyXmDl0ciWtVaNiORT/MxM7ZgOMQZADD0o51qOaOg24qc/zBViOIwAjJg==}
|
||||||
|
dependencies:
|
||||||
|
'@lezer/common': 1.0.4
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@lezer/html@1.3.6:
|
||||||
|
resolution: {integrity: sha512-Kk9HJARZTc0bAnMQUqbtuhFVsB4AnteR2BFUWfZV7L/x1H0aAKz6YabrfJ2gk/BEgjh9L3hg5O4y2IDZRBdzuQ==}
|
||||||
|
dependencies:
|
||||||
|
'@lezer/common': 1.0.4
|
||||||
|
'@lezer/highlight': 1.1.6
|
||||||
|
'@lezer/lr': 1.3.10
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@lezer/java@1.0.4:
|
||||||
|
resolution: {integrity: sha512-POc53LHf2AuNeRXjqZbXNu88GKj0KZTjjSx0L7tYeXlrEHF+3NAQx+dEwKVuCbkl0ZMtpRy2VsDYOV7KKV0oyg==}
|
||||||
|
dependencies:
|
||||||
|
'@lezer/highlight': 1.1.6
|
||||||
|
'@lezer/lr': 1.3.10
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@lezer/javascript@1.4.5:
|
||||||
|
resolution: {integrity: sha512-FmBUHz8K1V22DgjTd6SrIG9owbzOYZ1t3rY6vGEmw+e2RVBd7sqjM8uXEVRFmfxKFn1Mx2ABJehHjrN3G2ZpmA==}
|
||||||
|
dependencies:
|
||||||
|
'@lezer/highlight': 1.1.6
|
||||||
|
'@lezer/lr': 1.3.10
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@lezer/json@1.0.1:
|
||||||
|
resolution: {integrity: sha512-nkVC27qiEZEjySbi6gQRuMwa2sDu2PtfjSgz0A4QF81QyRGm3kb2YRzLcOPcTEtmcwvrX/cej7mlhbwViA4WJw==}
|
||||||
|
dependencies:
|
||||||
|
'@lezer/highlight': 1.1.6
|
||||||
|
'@lezer/lr': 1.3.10
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@lezer/lezer@1.1.2:
|
||||||
|
resolution: {integrity: sha512-O8yw3CxPhzYHB1hvwbdozjnAslhhR8A5BH7vfEMof0xk3p+/DFDfZkA9Tde6J+88WgtwaHy4Sy6ThZSkaI0Evw==}
|
||||||
|
dependencies:
|
||||||
|
'@lezer/highlight': 1.1.6
|
||||||
|
'@lezer/lr': 1.3.10
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@lezer/lr@1.3.10:
|
||||||
|
resolution: {integrity: sha512-BZfVvf7Re5BIwJHlZXbJn9L8lus5EonxQghyn+ih8Wl36XMFBPTXC0KM0IdUtj9w/diPHsKlXVgL+AlX2jYJ0Q==}
|
||||||
|
dependencies:
|
||||||
|
'@lezer/common': 1.0.4
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@lezer/markdown@1.1.0:
|
||||||
|
resolution: {integrity: sha512-JYOI6Lkqbl83semCANkO3CKbKc0pONwinyagBufWBm+k4yhIcqfCF8B8fpEpvJLmIy7CAfwiq7dQ/PzUZA340g==}
|
||||||
|
dependencies:
|
||||||
|
'@lezer/common': 1.0.4
|
||||||
|
'@lezer/highlight': 1.1.6
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@lezer/php@1.0.1:
|
||||||
|
resolution: {integrity: sha512-aqdCQJOXJ66De22vzdwnuC502hIaG9EnPK2rSi+ebXyUd+j7GAX1mRjWZOVOmf3GST1YUfUCu6WXDiEgDGOVwA==}
|
||||||
|
dependencies:
|
||||||
|
'@lezer/highlight': 1.1.6
|
||||||
|
'@lezer/lr': 1.3.10
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@lezer/python@1.1.8:
|
||||||
|
resolution: {integrity: sha512-1T/XsmeF57ijrjpC0Zmrf9YeO5mn2zC1XeSNrOnc0KB+6PgxJ5m7kWKt0CnwyS74oHQXbJxUUL+QDQJR26c1Gw==}
|
||||||
|
dependencies:
|
||||||
|
'@lezer/highlight': 1.1.6
|
||||||
|
'@lezer/lr': 1.3.10
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@lezer/rust@1.0.1:
|
||||||
|
resolution: {integrity: sha512-j+ToFKM6Wpglv3OQ4ebHYdYIMT2dh0ziCCV0rTf47AWiHOVhR0WjaKrBq+yuvDQNEhr5sxPxVI7+naJIgpqcsQ==}
|
||||||
|
dependencies:
|
||||||
|
'@lezer/highlight': 1.1.6
|
||||||
|
'@lezer/lr': 1.3.10
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@lezer/sass@1.0.3:
|
||||||
|
resolution: {integrity: sha512-n4l2nVOB7gWiGU/Cg2IVxpt2Ic9Hgfgy/7gk+p/XJibAsPXs0lSbsfGwQgwsAw9B/euYo3oS6lEFr9WytoqcZg==}
|
||||||
|
dependencies:
|
||||||
|
'@lezer/highlight': 1.1.6
|
||||||
|
'@lezer/lr': 1.3.10
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@lezer/xml@1.0.2:
|
||||||
|
resolution: {integrity: sha512-dlngsWceOtQBMuBPw5wtHpaxdPJ71aVntqjbpGkFtWsp4WtQmCnuTjQGocviymydN6M18fhj6UQX3oiEtSuY7w==}
|
||||||
|
dependencies:
|
||||||
|
'@lezer/highlight': 1.1.6
|
||||||
|
'@lezer/lr': 1.3.10
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@loadable/component@5.15.2(react@18.1.0):
|
/@loadable/component@5.15.2(react@18.1.0):
|
||||||
resolution: {integrity: sha512-ryFAZOX5P2vFkUdzaAtTG88IGnr9qxSdvLRvJySXcUA4B4xVWurUNADu3AnKPksxOZajljqTrDEDcYjeL4lvLw==}
|
resolution: {integrity: sha512-ryFAZOX5P2vFkUdzaAtTG88IGnr9qxSdvLRvJySXcUA4B4xVWurUNADu3AnKPksxOZajljqTrDEDcYjeL4lvLw==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@@ -3644,6 +4047,19 @@ packages:
|
|||||||
state-local: 1.0.7
|
state-local: 1.0.7
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@nextjournal/lang-clojure@1.0.0:
|
||||||
|
resolution: {integrity: sha512-gOCV71XrYD0DhwGoPMWZmZ0r92/lIHsqQu9QWdpZYYBwiChNwMO4sbVMP7eTuAqffFB2BTtCSC+1skSH9d3bNg==}
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/language': 6.9.0
|
||||||
|
'@nextjournal/lezer-clojure': 1.0.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@nextjournal/lezer-clojure@1.0.0:
|
||||||
|
resolution: {integrity: sha512-VZyuGu4zw5mkTOwQBTaGVNWmsOZAPw5ZRxu1/Knk/Xfs7EDBIogwIs5UXTYkuECX5ZQB8eOB+wKA2pc7VyqaZQ==}
|
||||||
|
dependencies:
|
||||||
|
'@lezer/lr': 1.3.10
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents.3:
|
/@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents.3:
|
||||||
resolution: {integrity: sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ==}
|
resolution: {integrity: sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ==}
|
||||||
requiresBuild: true
|
requiresBuild: true
|
||||||
@@ -3878,6 +4294,82 @@ packages:
|
|||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@replit/codemirror-lang-csharp@6.1.0(@codemirror/autocomplete@6.9.0)(@codemirror/language@6.9.0)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.4)(@lezer/highlight@1.1.6)(@lezer/lr@1.3.10):
|
||||||
|
resolution: {integrity: sha512-Dtyk9WVrdPPgkgTp8MUX9HyXd87O7UZnFrE647gjHUZY8p0UN+z0m6dPfk6rJMsTTvMcl7YbDUykxfeqB6EQOQ==}
|
||||||
|
peerDependencies:
|
||||||
|
'@codemirror/autocomplete': ^6.0.0
|
||||||
|
'@codemirror/language': ^6.0.0
|
||||||
|
'@codemirror/state': ^6.0.0
|
||||||
|
'@codemirror/view': ^6.0.0
|
||||||
|
'@lezer/common': ^1.0.0
|
||||||
|
'@lezer/highlight': ^1.0.0
|
||||||
|
'@lezer/lr': ^1.0.0
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/autocomplete': 6.9.0(@codemirror/language@6.9.0)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.4)
|
||||||
|
'@codemirror/language': 6.9.0
|
||||||
|
'@codemirror/state': 6.2.1
|
||||||
|
'@codemirror/view': 6.16.0
|
||||||
|
'@lezer/common': 1.0.4
|
||||||
|
'@lezer/highlight': 1.1.6
|
||||||
|
'@lezer/lr': 1.3.10
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@replit/codemirror-lang-nix@6.0.1(@codemirror/autocomplete@6.9.0)(@codemirror/language@6.9.0)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.4)(@lezer/highlight@1.1.6)(@lezer/lr@1.3.10):
|
||||||
|
resolution: {integrity: sha512-lvzjoYn9nfJzBD5qdm3Ut6G3+Or2wEacYIDJ49h9+19WSChVnxv4ojf+rNmQ78ncuxIt/bfbMvDLMeMP0xze6g==}
|
||||||
|
peerDependencies:
|
||||||
|
'@codemirror/autocomplete': ^6.0.0
|
||||||
|
'@codemirror/language': ^6.0.0
|
||||||
|
'@codemirror/state': ^6.0.0
|
||||||
|
'@codemirror/view': ^6.0.0
|
||||||
|
'@lezer/common': ^1.0.0
|
||||||
|
'@lezer/highlight': ^1.0.0
|
||||||
|
'@lezer/lr': ^1.0.0
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/autocomplete': 6.9.0(@codemirror/language@6.9.0)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.4)
|
||||||
|
'@codemirror/language': 6.9.0
|
||||||
|
'@codemirror/state': 6.2.1
|
||||||
|
'@codemirror/view': 6.16.0
|
||||||
|
'@lezer/common': 1.0.4
|
||||||
|
'@lezer/highlight': 1.1.6
|
||||||
|
'@lezer/lr': 1.3.10
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@replit/codemirror-lang-solidity@6.0.1(@codemirror/language@6.9.0):
|
||||||
|
resolution: {integrity: sha512-kDnak0xZelGmvzJwKTpMTl6gYSfFq9hnxrkbLaMV0CARq/MFvDQJmcmYon/k8uZqXy6DfzewKDV8tx9kY2WUZg==}
|
||||||
|
peerDependencies:
|
||||||
|
'@codemirror/language': ^6.0.0
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/language': 6.9.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@replit/codemirror-lang-svelte@6.0.0(@codemirror/autocomplete@6.9.0)(@codemirror/lang-css@6.2.1)(@codemirror/lang-html@6.4.5)(@codemirror/lang-javascript@6.1.9)(@codemirror/language@6.9.0)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.4)(@lezer/highlight@1.1.6)(@lezer/javascript@1.4.5)(@lezer/lr@1.3.10):
|
||||||
|
resolution: {integrity: sha512-U2OqqgMM6jKelL0GNWbAmqlu1S078zZNoBqlJBW+retTc5M4Mha6/Y2cf4SVg6ddgloJvmcSpt4hHrVoM4ePRA==}
|
||||||
|
peerDependencies:
|
||||||
|
'@codemirror/autocomplete': ^6.0.0
|
||||||
|
'@codemirror/lang-css': ^6.0.1
|
||||||
|
'@codemirror/lang-html': ^6.2.0
|
||||||
|
'@codemirror/lang-javascript': ^6.1.1
|
||||||
|
'@codemirror/language': ^6.0.0
|
||||||
|
'@codemirror/state': ^6.0.0
|
||||||
|
'@codemirror/view': ^6.0.0
|
||||||
|
'@lezer/common': ^1.0.0
|
||||||
|
'@lezer/highlight': ^1.0.0
|
||||||
|
'@lezer/javascript': ^1.2.0
|
||||||
|
'@lezer/lr': ^1.0.0
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/autocomplete': 6.9.0(@codemirror/language@6.9.0)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.4)
|
||||||
|
'@codemirror/lang-css': 6.2.1(@codemirror/view@6.16.0)
|
||||||
|
'@codemirror/lang-html': 6.4.5
|
||||||
|
'@codemirror/lang-javascript': 6.1.9
|
||||||
|
'@codemirror/language': 6.9.0
|
||||||
|
'@codemirror/state': 6.2.1
|
||||||
|
'@codemirror/view': 6.16.0
|
||||||
|
'@lezer/common': 1.0.4
|
||||||
|
'@lezer/highlight': 1.1.6
|
||||||
|
'@lezer/javascript': 1.4.5
|
||||||
|
'@lezer/lr': 1.3.10
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@sentry-internal/tracing@7.54.0:
|
/@sentry-internal/tracing@7.54.0:
|
||||||
resolution: {integrity: sha512-JsyhZ0wWZ+VqbHJg+azqRGdYJDkcI5R9+pnkO6SzbzxrRewqMAIwzkpPee3oI7vG99uhMEkOkMjHu0nQGwkOQw==}
|
resolution: {integrity: sha512-JsyhZ0wWZ+VqbHJg+azqRGdYJDkcI5R9+pnkO6SzbzxrRewqMAIwzkpPee3oI7vG99uhMEkOkMjHu0nQGwkOQw==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@@ -4828,6 +5320,101 @@ packages:
|
|||||||
eslint-visitor-keys: 3.4.1
|
eslint-visitor-keys: 3.4.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@uiw/codemirror-extensions-basic-setup@4.21.9(@codemirror/autocomplete@6.9.0)(@codemirror/commands@6.2.4)(@codemirror/language@6.9.0)(@codemirror/lint@6.4.0)(@codemirror/search@6.5.1)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0):
|
||||||
|
resolution: {integrity: sha512-TQT6aF8brxZpFnk/K4fm/K/9k9eF3PMav/KKjHlYrGUT8BTNk/qL+ximLtIzvTUhmBFchjM1lrqSJdvpVom7/w==}
|
||||||
|
peerDependencies:
|
||||||
|
'@codemirror/autocomplete': '>=6.0.0'
|
||||||
|
'@codemirror/commands': '>=6.0.0'
|
||||||
|
'@codemirror/language': '>=6.0.0'
|
||||||
|
'@codemirror/lint': '>=6.0.0'
|
||||||
|
'@codemirror/search': '>=6.0.0'
|
||||||
|
'@codemirror/state': '>=6.0.0'
|
||||||
|
'@codemirror/view': '>=6.0.0'
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/autocomplete': 6.9.0(@codemirror/language@6.9.0)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.4)
|
||||||
|
'@codemirror/commands': 6.2.4
|
||||||
|
'@codemirror/language': 6.9.0
|
||||||
|
'@codemirror/lint': 6.4.0
|
||||||
|
'@codemirror/search': 6.5.1
|
||||||
|
'@codemirror/state': 6.2.1
|
||||||
|
'@codemirror/view': 6.16.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@uiw/codemirror-extensions-langs@4.21.9(@codemirror/autocomplete@6.9.0)(@codemirror/language-data@6.3.1)(@codemirror/language@6.9.0)(@codemirror/legacy-modes@6.3.3)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.4)(@lezer/highlight@1.1.6)(@lezer/javascript@1.4.5)(@lezer/lr@1.3.10):
|
||||||
|
resolution: {integrity: sha512-s1VT1rss0iyvrtRl7BZtC5H7U5uQtCKTaD8wxjQrgZz5un9wHVvy9twU97aJGQR0FwbKWqK8/1iiICRJTRCoZA==}
|
||||||
|
peerDependencies:
|
||||||
|
'@codemirror/language-data': '>=6.0.0'
|
||||||
|
'@codemirror/legacy-modes': '>=6.0.0'
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/lang-angular': 0.1.2
|
||||||
|
'@codemirror/lang-cpp': 6.0.2
|
||||||
|
'@codemirror/lang-css': 6.2.1(@codemirror/view@6.16.0)
|
||||||
|
'@codemirror/lang-html': 6.4.5
|
||||||
|
'@codemirror/lang-java': 6.0.1
|
||||||
|
'@codemirror/lang-javascript': 6.1.9
|
||||||
|
'@codemirror/lang-json': 6.0.1
|
||||||
|
'@codemirror/lang-less': 6.0.1(@codemirror/view@6.16.0)
|
||||||
|
'@codemirror/lang-lezer': 6.0.1
|
||||||
|
'@codemirror/lang-markdown': 6.2.0
|
||||||
|
'@codemirror/lang-php': 6.0.1
|
||||||
|
'@codemirror/lang-python': 6.1.3(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.4)
|
||||||
|
'@codemirror/lang-rust': 6.0.1
|
||||||
|
'@codemirror/lang-sass': 6.0.2(@codemirror/view@6.16.0)
|
||||||
|
'@codemirror/lang-sql': 6.5.4(@codemirror/view@6.16.0)(@lezer/common@1.0.4)
|
||||||
|
'@codemirror/lang-vue': 0.1.2
|
||||||
|
'@codemirror/lang-wast': 6.0.1
|
||||||
|
'@codemirror/lang-xml': 6.0.2(@codemirror/view@6.16.0)
|
||||||
|
'@codemirror/language-data': 6.3.1(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.4)
|
||||||
|
'@codemirror/legacy-modes': 6.3.3
|
||||||
|
'@nextjournal/lang-clojure': 1.0.0
|
||||||
|
'@replit/codemirror-lang-csharp': 6.1.0(@codemirror/autocomplete@6.9.0)(@codemirror/language@6.9.0)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.4)(@lezer/highlight@1.1.6)(@lezer/lr@1.3.10)
|
||||||
|
'@replit/codemirror-lang-nix': 6.0.1(@codemirror/autocomplete@6.9.0)(@codemirror/language@6.9.0)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.4)(@lezer/highlight@1.1.6)(@lezer/lr@1.3.10)
|
||||||
|
'@replit/codemirror-lang-solidity': 6.0.1(@codemirror/language@6.9.0)
|
||||||
|
'@replit/codemirror-lang-svelte': 6.0.0(@codemirror/autocomplete@6.9.0)(@codemirror/lang-css@6.2.1)(@codemirror/lang-html@6.4.5)(@codemirror/lang-javascript@6.1.9)(@codemirror/language@6.9.0)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.4)(@lezer/highlight@1.1.6)(@lezer/javascript@1.4.5)(@lezer/lr@1.3.10)
|
||||||
|
codemirror-lang-mermaid: 0.2.2
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@codemirror/autocomplete'
|
||||||
|
- '@codemirror/language'
|
||||||
|
- '@codemirror/state'
|
||||||
|
- '@codemirror/view'
|
||||||
|
- '@lezer/common'
|
||||||
|
- '@lezer/highlight'
|
||||||
|
- '@lezer/javascript'
|
||||||
|
- '@lezer/lr'
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@uiw/react-codemirror@4.21.9(@babel/runtime@7.22.3)(@codemirror/autocomplete@6.9.0)(@codemirror/language@6.9.0)(@codemirror/lint@6.4.0)(@codemirror/search@6.5.1)(@codemirror/state@6.2.1)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.16.0)(codemirror@6.0.1)(react-dom@18.2.0)(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-aeLegPz2iCvqJjhzXp2WUMqpMZDqxsTnF3rX9kGRlfY6vQLsrjoctj0cQ29uxEtFYJChOVjtCOtnQUlyIuNAHQ==}
|
||||||
|
peerDependencies:
|
||||||
|
'@babel/runtime': '>=7.11.0'
|
||||||
|
'@codemirror/state': '>=6.0.0'
|
||||||
|
'@codemirror/theme-one-dark': '>=6.0.0'
|
||||||
|
'@codemirror/view': '>=6.0.0'
|
||||||
|
codemirror: '>=6.0.0'
|
||||||
|
react: '>=16.8.0 || 18'
|
||||||
|
react-dom: '>=16.8.0 || 18'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
react:
|
||||||
|
optional: true
|
||||||
|
react-dom:
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.22.3
|
||||||
|
'@codemirror/commands': 6.2.4
|
||||||
|
'@codemirror/state': 6.2.1
|
||||||
|
'@codemirror/theme-one-dark': 6.1.2
|
||||||
|
'@codemirror/view': 6.16.0
|
||||||
|
'@uiw/codemirror-extensions-basic-setup': 4.21.9(@codemirror/autocomplete@6.9.0)(@codemirror/commands@6.2.4)(@codemirror/language@6.9.0)(@codemirror/lint@6.4.0)(@codemirror/search@6.5.1)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)
|
||||||
|
codemirror: 6.0.1(@lezer/common@1.0.4)
|
||||||
|
react: 18.2.0
|
||||||
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@codemirror/autocomplete'
|
||||||
|
- '@codemirror/language'
|
||||||
|
- '@codemirror/lint'
|
||||||
|
- '@codemirror/search'
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@umijs/ast@4.0.72:
|
/@umijs/ast@4.0.72:
|
||||||
resolution: {integrity: sha512-WatRvU09vsx4Hlu5hemPA7a+QK4pJvzmQz/9LxN/KVgn+wZXi717qHFLu5eoV6XO7HlFZaEBGq2aHpDj0ngA8w==}
|
resolution: {integrity: sha512-WatRvU09vsx4Hlu5hemPA7a+QK4pJvzmQz/9LxN/KVgn+wZXi717qHFLu5eoV6XO7HlFZaEBGq2aHpDj0ngA8w==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -6657,8 +7244,26 @@ packages:
|
|||||||
mimic-response: 1.0.1
|
mimic-response: 1.0.1
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/codemirror@5.65.13:
|
/codemirror-lang-mermaid@0.2.2:
|
||||||
resolution: {integrity: sha512-SVWEzKXmbHmTQQWaz03Shrh4nybG0wXx2MEu3FO4ezbPW8IbnZEd5iGHGEffSUaitKYa3i+pHpBsSvw8sPHtzg==}
|
resolution: {integrity: sha512-AqSzkQgfWsjBbifio3dy/zDj6WXEw4g52Mq6bltIWLMWryWWRMpFwjQSlHtCGOol1FENYObUF5KI4ofiv8bjXA==}
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/language': 6.9.0
|
||||||
|
'@lezer/highlight': 1.1.6
|
||||||
|
'@lezer/lr': 1.3.10
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/codemirror@6.0.1(@lezer/common@1.0.4):
|
||||||
|
resolution: {integrity: sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==}
|
||||||
|
dependencies:
|
||||||
|
'@codemirror/autocomplete': 6.9.0(@codemirror/language@6.9.0)(@codemirror/state@6.2.1)(@codemirror/view@6.16.0)(@lezer/common@1.0.4)
|
||||||
|
'@codemirror/commands': 6.2.4
|
||||||
|
'@codemirror/language': 6.9.0
|
||||||
|
'@codemirror/lint': 6.4.0
|
||||||
|
'@codemirror/search': 6.5.1
|
||||||
|
'@codemirror/state': 6.2.1
|
||||||
|
'@codemirror/view': 6.16.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@lezer/common'
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/color-convert@1.9.3:
|
/color-convert@1.9.3:
|
||||||
@@ -6970,6 +7575,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==}
|
resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/crelt@1.0.6:
|
||||||
|
resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/cron-parser@4.8.1:
|
/cron-parser@4.8.1:
|
||||||
resolution: {integrity: sha512-jbokKWGcyU4gl6jAfX97E1gDpY12DJ1cLJZmoDzaAln/shZ+S3KBFBuA2Q6WeUN4gJf/8klnV1EfvhA2lK5IRQ==}
|
resolution: {integrity: sha512-jbokKWGcyU4gl6jAfX97E1gDpY12DJ1cLJZmoDzaAln/shZ+S3KBFBuA2Q6WeUN4gJf/8klnV1EfvhA2lK5IRQ==}
|
||||||
engines: {node: '>=12.0.0'}
|
engines: {node: '>=12.0.0'}
|
||||||
@@ -8273,6 +8882,12 @@ packages:
|
|||||||
resolution: {integrity: sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==}
|
resolution: {integrity: sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/file-stream-rotator@0.6.1:
|
||||||
|
resolution: {integrity: sha512-u+dBid4PvZw17PmDeRcNOtCP9CCK/9lRN2w+r1xIS7yOL9JFrIBKTvrYsxT4P0pGtThYTn++QS5ChHaUov3+zQ==}
|
||||||
|
dependencies:
|
||||||
|
moment: 2.29.4
|
||||||
|
dev: false
|
||||||
|
|
||||||
/file-uri-to-path@2.0.0:
|
/file-uri-to-path@2.0.0:
|
||||||
resolution: {integrity: sha512-hjPFI8oE/2iQPVe4gbrJ73Pp+Xfub2+WI2LlXDbsaJBwT5wuMh35WNWVYYTpnz895shtwfyutMFLFywpQAFdLg==}
|
resolution: {integrity: sha512-hjPFI8oE/2iQPVe4gbrJ73Pp+Xfub2+WI2LlXDbsaJBwT5wuMh35WNWVYYTpnz895shtwfyutMFLFywpQAFdLg==}
|
||||||
engines: {node: '>= 6'}
|
engines: {node: '>= 6'}
|
||||||
@@ -10787,6 +11402,11 @@ packages:
|
|||||||
engines: {node: '>= 0.10.0'}
|
engines: {node: '>= 0.10.0'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/object-hash@2.2.0:
|
||||||
|
resolution: {integrity: sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==}
|
||||||
|
engines: {node: '>= 6'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/object-inspect@1.12.3:
|
/object-inspect@1.12.3:
|
||||||
resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==}
|
resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==}
|
||||||
|
|
||||||
@@ -12903,19 +13523,6 @@ packages:
|
|||||||
react-dom: 18.2.0(react@18.2.0)
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/react-codemirror2@7.2.1(codemirror@5.65.13)(react@18.2.0):
|
|
||||||
resolution: {integrity: sha512-t7YFmz1AXdlImgHXA9Ja0T6AWuopilub24jRaQdPVbzUJVNKIYuy3uCFZYa7CE5S3UW6SrSa5nAqVQvtzRF9gw==}
|
|
||||||
peerDependencies:
|
|
||||||
codemirror: 5.x
|
|
||||||
react: '>=15.5 <=16.x || 18'
|
|
||||||
peerDependenciesMeta:
|
|
||||||
react:
|
|
||||||
optional: true
|
|
||||||
dependencies:
|
|
||||||
codemirror: 5.65.13
|
|
||||||
react: 18.2.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/react-copy-to-clipboard@5.1.0(react@18.2.0):
|
/react-copy-to-clipboard@5.1.0(react@18.2.0):
|
||||||
resolution: {integrity: sha512-k61RsNgAayIJNoy9yDsYzDe/yAZAzEbEgcz3DZMhF686LEyukcE1hzurxe85JandPUG+yTfGVFzuEw3xt8WP/A==}
|
resolution: {integrity: sha512-k61RsNgAayIJNoy9yDsYzDe/yAZAzEbEgcz3DZMhF686LEyukcE1hzurxe85JandPUG+yTfGVFzuEw3xt8WP/A==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -14307,6 +14914,10 @@ packages:
|
|||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/style-mod@4.0.3:
|
||||||
|
resolution: {integrity: sha512-78Jv8kYJdjbvRwwijtCevYADfsI0lGzYJe4mMFdceO8l75DFFDoqBhR1jVDicDRRaX4//g1u9wKeo+ztc2h1Rw==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/style-search@0.1.0:
|
/style-search@0.1.0:
|
||||||
resolution: {integrity: sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==}
|
resolution: {integrity: sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==}
|
||||||
dev: true
|
dev: true
|
||||||
@@ -15308,6 +15919,10 @@ packages:
|
|||||||
acorn-walk: 8.2.0
|
acorn-walk: 8.2.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/w3c-keyname@2.2.8:
|
||||||
|
resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/walker@1.0.8:
|
/walker@1.0.8:
|
||||||
resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==}
|
resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -15489,6 +16104,19 @@ packages:
|
|||||||
semver: 5.7.1
|
semver: 5.7.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/winston-daily-rotate-file@4.7.1(winston@3.9.0):
|
||||||
|
resolution: {integrity: sha512-7LGPiYGBPNyGHLn9z33i96zx/bd71pjBn9tqQzO3I4Tayv94WPmBNwKC7CO1wPHdP9uvu+Md/1nr6VSH9h0iaA==}
|
||||||
|
engines: {node: '>=8'}
|
||||||
|
peerDependencies:
|
||||||
|
winston: ^3
|
||||||
|
dependencies:
|
||||||
|
file-stream-rotator: 0.6.1
|
||||||
|
object-hash: 2.2.0
|
||||||
|
triple-beam: 1.3.0
|
||||||
|
winston: 3.9.0
|
||||||
|
winston-transport: 4.5.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/winston-transport@4.5.0:
|
/winston-transport@4.5.0:
|
||||||
resolution: {integrity: sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q==}
|
resolution: {integrity: sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q==}
|
||||||
engines: {node: '>= 6.4.0'}
|
engines: {node: '>= 6.4.0'}
|
||||||
|
|||||||
+1
-1
@@ -456,7 +456,7 @@ class WeCom:
|
|||||||
return respone["errmsg"]
|
return respone["errmsg"]
|
||||||
|
|
||||||
def send_mpnews(self, title, message, media_id, touser="@all"):
|
def send_mpnews(self, title, message, media_id, touser="@all"):
|
||||||
send_url = f"https://{self.HOST}/cgi-bin/message/send?access_token={self.get_access_token()}"
|
send_url = f"{self.ORIGIN}/cgi-bin/message/send?access_token={self.get_access_token()}"
|
||||||
send_values = {
|
send_values = {
|
||||||
"touser": touser,
|
"touser": touser,
|
||||||
"msgtype": "mpnews",
|
"msgtype": "mpnews",
|
||||||
|
|||||||
+1
-1
@@ -36,7 +36,7 @@ add_cron_api() {
|
|||||||
local sub_id="$4"
|
local sub_id="$4"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ ! $sub_id ]];then
|
if [[ ! $sub_id ]]; then
|
||||||
sub_id="null"
|
sub_id="null"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
+19
-11
@@ -86,6 +86,11 @@ check_server() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
env_str_to_array() {
|
||||||
|
local IFS="&"
|
||||||
|
read -ra array <<<"${!env_param}"
|
||||||
|
}
|
||||||
|
|
||||||
## 正常运行单个脚本,$1:传入参数
|
## 正常运行单个脚本,$1:传入参数
|
||||||
run_normal() {
|
run_normal() {
|
||||||
local file_param=$1
|
local file_param=$1
|
||||||
@@ -113,8 +118,7 @@ run_concurrent() {
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local envs=$(eval echo "\$${env_param}")
|
env_str_to_array
|
||||||
local array=($(echo $envs | sed 's/&/ /g'))
|
|
||||||
local tempArr=$(echo $num_param | sed "s/-max/-${#array[@]}/g" | sed "s/max-/${#array[@]}-/g" | perl -pe "s|(\d+)(-\|~\|_)(\d+)|{\1..\3}|g")
|
local tempArr=$(echo $num_param | sed "s/-max/-${#array[@]}/g" | sed "s/max-/${#array[@]}-/g" | perl -pe "s|(\d+)(-\|~\|_)(\d+)|{\1..\3}|g")
|
||||||
local runArr=($(eval echo $tempArr))
|
local runArr=($(eval echo $tempArr))
|
||||||
runArr=($(awk -v RS=' ' '!a[$1]++' <<<${runArr[@]}))
|
runArr=($(awk -v RS=' ' '!a[$1]++' <<<${runArr[@]}))
|
||||||
@@ -125,11 +129,13 @@ run_concurrent() {
|
|||||||
let n++
|
let n++
|
||||||
done
|
done
|
||||||
|
|
||||||
local cookieStr=$(echo ${array_run[*]} | sed 's/\ /\&/g')
|
local cookieStr=$(
|
||||||
[[ ! -z $cookieStr ]] && export ${env_param}=${cookieStr}
|
IFS="&"
|
||||||
|
echo "${array_run[*]}"
|
||||||
|
)
|
||||||
|
[[ ! -z $cookieStr ]] && export "${env_param}=${cookieStr}"
|
||||||
|
|
||||||
local envs=$(eval echo "\$${env_param}")
|
env_str_to_array
|
||||||
local array=($(echo $envs | sed 's/&/ /g'))
|
|
||||||
single_log_time=$(date "+%Y-%m-%d-%H-%M-%S.%3N")
|
single_log_time=$(date "+%Y-%m-%d-%H-%M-%S.%3N")
|
||||||
|
|
||||||
cd $dir_scripts
|
cd $dir_scripts
|
||||||
@@ -139,7 +145,7 @@ run_concurrent() {
|
|||||||
file_param=${file_param/$relative_path\//}
|
file_param=${file_param/$relative_path\//}
|
||||||
fi
|
fi
|
||||||
for i in "${!array[@]}"; do
|
for i in "${!array[@]}"; do
|
||||||
export ${env_param}=${array[i]}
|
export "${env_param}=${array[i]}"
|
||||||
single_log_path="$dir_log/$log_dir/${single_log_time}_$((i + 1)).log"
|
single_log_path="$dir_log/$log_dir/${single_log_time}_$((i + 1)).log"
|
||||||
eval $timeoutCmd $which_program $file_param &>$single_log_path &
|
eval $timeoutCmd $which_program $file_param &>$single_log_path &
|
||||||
done
|
done
|
||||||
@@ -161,8 +167,7 @@ run_designated() {
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local envs=$(eval echo "\$${env_param}")
|
env_str_to_array
|
||||||
local array=($(echo $envs | sed 's/&/ /g'))
|
|
||||||
local tempArr=$(echo $num_param | sed "s/-max/-${#array[@]}/g" | sed "s/max-/${#array[@]}-/g" | perl -pe "s|(\d+)(-\|~\|_)(\d+)|{\1..\3}|g")
|
local tempArr=$(echo $num_param | sed "s/-max/-${#array[@]}/g" | sed "s/max-/${#array[@]}-/g" | perl -pe "s|(\d+)(-\|~\|_)(\d+)|{\1..\3}|g")
|
||||||
local runArr=($(eval echo $tempArr))
|
local runArr=($(eval echo $tempArr))
|
||||||
runArr=($(awk -v RS=' ' '!a[$1]++' <<<${runArr[@]}))
|
runArr=($(awk -v RS=' ' '!a[$1]++' <<<${runArr[@]}))
|
||||||
@@ -173,8 +178,11 @@ run_designated() {
|
|||||||
let n++
|
let n++
|
||||||
done
|
done
|
||||||
|
|
||||||
local cookieStr=$(echo ${array_run[*]} | sed 's/\ /\&/g')
|
local cookieStr=$(
|
||||||
[[ ! -z $cookieStr ]] && export ${env_param}=${cookieStr}
|
IFS="&"
|
||||||
|
echo "${array_run[*]}"
|
||||||
|
)
|
||||||
|
[[ ! -z $cookieStr ]] && export "${env_param}=${cookieStr}"
|
||||||
|
|
||||||
cd $dir_scripts
|
cd $dir_scripts
|
||||||
local relative_path="${file_param%/*}"
|
local relative_path="${file_param%/*}"
|
||||||
|
|||||||
+1
-1
@@ -296,7 +296,7 @@ git_clone_scripts() {
|
|||||||
|
|
||||||
set_proxy "$proxy"
|
set_proxy "$proxy"
|
||||||
|
|
||||||
git clone --depth=1 $part_cmd $url $dir
|
git clone --depth=1 $part_cmd $url $dir 2>&1
|
||||||
exit_status=$?
|
exit_status=$?
|
||||||
|
|
||||||
unset_proxy
|
unset_proxy
|
||||||
|
|||||||
+1
-1
@@ -69,7 +69,7 @@ handle_log_path() {
|
|||||||
if [[ $real_log_path ]]; then
|
if [[ $real_log_path ]]; then
|
||||||
log_path="$real_log_path"
|
log_path="$real_log_path"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cmd=">> $dir_log/$log_path 2>&1"
|
cmd=">> $dir_log/$log_path 2>&1"
|
||||||
make_dir "$dir_log/$log_dir"
|
make_dir "$dir_log/$log_dir"
|
||||||
if [[ "$show_log" == "true" ]]; then
|
if [[ "$show_log" == "true" ]]; then
|
||||||
|
|||||||
+3
-3
@@ -31,7 +31,7 @@ output_list_add_drop() {
|
|||||||
local list=$1
|
local list=$1
|
||||||
local type=$2
|
local type=$2
|
||||||
if [[ -s $list ]]; then
|
if [[ -s $list ]]; then
|
||||||
echo -e "检测到有${type}的定时任务:\n"
|
echo -e "检测到有${type}的定时任务:"
|
||||||
cat $list
|
cat $list
|
||||||
echo
|
echo
|
||||||
fi
|
fi
|
||||||
@@ -134,10 +134,10 @@ update_repo() {
|
|||||||
git_clone_scripts "${formatUrl}" ${repo_path} "${branch}" "${proxy}"
|
git_clone_scripts "${formatUrl}" ${repo_path} "${branch}" "${proxy}"
|
||||||
|
|
||||||
if [[ $exit_status -eq 0 ]]; then
|
if [[ $exit_status -eq 0 ]]; then
|
||||||
echo -e "\n更新${repo_path}成功...\n"
|
echo -e "\n拉取 ${uniq_path} 成功...\n"
|
||||||
diff_scripts "$repo_path" "$author" "$path" "$blackword" "$dependence" "$extensions" "$autoAddCron" "$autoDelCron"
|
diff_scripts "$repo_path" "$author" "$path" "$blackword" "$dependence" "$extensions" "$autoAddCron" "$autoDelCron"
|
||||||
else
|
else
|
||||||
echo -e "\n更新${repo_path}失败,请检查网络...\n"
|
echo -e "\n拉取 ${uniq_path} 失败,请检查网络...\n"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
const baseUrl = window.__ENV__QlBaseUrl || '/';
|
const baseUrl = window.__ENV__QlBaseUrl || '/';
|
||||||
|
import { setLocale } from '@umijs/max';
|
||||||
import intl from 'react-intl-universal';
|
import intl from 'react-intl-universal';
|
||||||
|
|
||||||
export function rootContainer(container: any) {
|
export function rootContainer(container: any) {
|
||||||
@@ -9,6 +10,7 @@ export function rootContainer(container: any) {
|
|||||||
let currentLocale = intl.determineLocale({
|
let currentLocale = intl.determineLocale({
|
||||||
urlLocaleKey: 'lang',
|
urlLocaleKey: 'lang',
|
||||||
cookieLocaleKey: 'lang',
|
cookieLocaleKey: 'lang',
|
||||||
|
localStorageLocaleKey: 'lang',
|
||||||
}).slice(0, 2);
|
}).slice(0, 2);
|
||||||
|
|
||||||
if (!currentLocale || !Object.keys(locales).includes(currentLocale)) {
|
if (!currentLocale || !Object.keys(locales).includes(currentLocale)) {
|
||||||
@@ -16,6 +18,7 @@ export function rootContainer(container: any) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
intl.init({ currentLocale, locales });
|
intl.init({ currentLocale, locales });
|
||||||
|
setLocale(currentLocale === 'zh' ? 'zh-CN' : 'en-US');
|
||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+31
-9
@@ -1,6 +1,5 @@
|
|||||||
@import '~antd/es/style/themes/default.less';
|
@import '~antd/es/style/themes/default.less';
|
||||||
@import '~@/styles/variable.less';
|
@import '~@/styles/variable.less';
|
||||||
@import '~codemirror/lib/codemirror.css';
|
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Source Code Pro';
|
font-family: 'Source Code Pro';
|
||||||
@@ -32,9 +31,24 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.log-modal {
|
.log-modal {
|
||||||
.ant-modal {
|
&.ant-modal {
|
||||||
padding-bottom: 0 !important;
|
max-width: 1000px !important;
|
||||||
width: 580px !important;
|
width: 80vw !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-modal-body {
|
||||||
|
overflow-y: auto;
|
||||||
|
min-height: 300px;
|
||||||
|
max-height: calc(80vh - 110px);
|
||||||
|
max-height: calc(80vh - var(--vh-offset, 110px));
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.log-container {
|
||||||
|
width: 100%;
|
||||||
|
padding: 24px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
@@ -87,10 +101,12 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.ant-tooltip {
|
.ant-tooltip {
|
||||||
max-width: 500px !important;
|
max-width: 300px !important;
|
||||||
|
|
||||||
.ant-tooltip-inner {
|
.ant-tooltip-inner {
|
||||||
word-break: break-all !important;
|
word-break: break-all !important;
|
||||||
|
max-height: 300px !important;
|
||||||
|
overflow-y: auto !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,8 +198,14 @@ body {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.log-modal {
|
||||||
|
&.ant-modal {
|
||||||
|
width: calc(100vw - 16px) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.ant-tooltip {
|
.ant-tooltip {
|
||||||
max-width: 250px !important;
|
max-width: 300px !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -368,9 +390,9 @@ select:-webkit-autofill:focus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
word-break: break-all !important;
|
word-break: break-all;
|
||||||
white-space: break-spaces !important;
|
white-space: break-spaces;
|
||||||
padding: 0 !important;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.virtuallist {
|
.virtuallist {
|
||||||
|
|||||||
@@ -32,9 +32,6 @@ import {
|
|||||||
import SockJS from 'sockjs-client';
|
import SockJS from 'sockjs-client';
|
||||||
import * as Sentry from '@sentry/react';
|
import * as Sentry from '@sentry/react';
|
||||||
import { init } from '../utils/init';
|
import { init } from '../utils/init';
|
||||||
import 'codemirror/mode/javascript/javascript';
|
|
||||||
import 'codemirror/mode/python/python';
|
|
||||||
import 'codemirror/mode/shell/shell';
|
|
||||||
|
|
||||||
export interface SharedContext {
|
export interface SharedContext {
|
||||||
headerStyle: React.CSSProperties;
|
headerStyle: React.CSSProperties;
|
||||||
|
|||||||
@@ -448,5 +448,8 @@
|
|||||||
"编辑订阅": "Edit Subscription",
|
"编辑订阅": "Edit Subscription",
|
||||||
"Subscription表达式格式有误": "Incorrect Subscription Expression Format",
|
"Subscription表达式格式有误": "Incorrect Subscription Expression Format",
|
||||||
"一对多推送的“群组编码”(一对多推送下面->您的群组(如无则新建)->群组编码,如果您是创建群组人。也需点击“查看二维码”扫描绑定,否则不能接受群组消息推送)": "The 'Group Code' for One-to-Many Push (Below One-to-Many Push->Your Group (if not, create one)->Group Code, if you are the creator of the group, you also need to click 'View QR Code' to scan and bind, otherwise you cannot receive group messages)",
|
"一对多推送的“群组编码”(一对多推送下面->您的群组(如无则新建)->群组编码,如果您是创建群组人。也需点击“查看二维码”扫描绑定,否则不能接受群组消息推送)": "The 'Group Code' for One-to-Many Push (Below One-to-Many Push->Your Group (if not, create one)->Group Code, if you are the creator of the group, you also need to click 'View QR Code' to scan and bind, otherwise you cannot receive group messages)",
|
||||||
"登录已过期,请重新登录": "Login session has expired, please log in again"
|
"登录已过期,请重新登录": "Login session has expired, please log in again",
|
||||||
|
"系统日志": "System Logs",
|
||||||
|
"主题": "Theme",
|
||||||
|
"语言": "Language"
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-9
@@ -337,7 +337,7 @@
|
|||||||
"飞书机器人": "飞书机器人",
|
"飞书机器人": "飞书机器人",
|
||||||
"自定义通知": "自定义通知",
|
"自定义通知": "自定义通知",
|
||||||
"已关闭": "已关闭",
|
"已关闭": "已关闭",
|
||||||
"gotify的url地址,例如 https://push.example.de:8080": "gotify的url地址,例如 https://push.example.de:8080",
|
"gotify的url地址,例如 https://push.example.de:8080": "gotify的url地址,例如 https://push.example.de:8080",
|
||||||
"gotify的消息应用token码": "gotify的消息应用token码",
|
"gotify的消息应用token码": "gotify的消息应用token码",
|
||||||
"推送消息的优先级": "推送消息的优先级",
|
"推送消息的优先级": "推送消息的优先级",
|
||||||
"chat的url地址": "chat的url地址",
|
"chat的url地址": "chat的url地址",
|
||||||
@@ -349,21 +349,21 @@
|
|||||||
"PushDeer的Key,https://github.com/easychen/pushdeer": "PushDeer的Key,https://github.com/easychen/pushdeer",
|
"PushDeer的Key,https://github.com/easychen/pushdeer": "PushDeer的Key,https://github.com/easychen/pushdeer",
|
||||||
"PushDeer的自架API endpoint,默认是 https://api2.pushdeer.com/message/push": "PushDeer的自架API endpoint,默认是 https://api2.pushdeer.com/message/push",
|
"PushDeer的自架API endpoint,默认是 https://api2.pushdeer.com/message/push": "PushDeer的自架API endpoint,默认是 https://api2.pushdeer.com/message/push",
|
||||||
"Bark的信息IP/设备码,例如:https://api.day.app/XXXXXXXX": "Bark的信息IP/设备码,例如:https://api.day.app/XXXXXXXX",
|
"Bark的信息IP/设备码,例如:https://api.day.app/XXXXXXXX": "Bark的信息IP/设备码,例如:https://api.day.app/XXXXXXXX",
|
||||||
"BARK推送图标,自定义推送图标 (需iOS15或以上才能显示)": "BARK推送图标,自定义推送图标 (需iOS15或以上才能显示)",
|
"BARK推送图标,自定义推送图标 (需iOS15或以上才能显示)": "BARK推送图标,自定义推送图标 (需iOS15或以上才能显示)",
|
||||||
"BARK推送铃声,铃声列表去APP查看复制填写": "BARK推送铃声,铃声列表去APP查看复制填写",
|
"BARK推送铃声,铃声列表去APP查看复制填写": "BARK推送铃声,铃声列表去APP查看复制填写",
|
||||||
"BARK推送消息的分组, 默认为qinglong": "BARK推送消息的分组, 默认为qinglong",
|
"BARK推送消息的分组,默认为qinglong": "BARK推送消息的分组,默认为qinglong",
|
||||||
"telegram机器人的token,例如:1077xxx4424:AAFjv0FcqxxxxxxgEMGfi22B4yh15R5uw": "telegram机器人的token,例如:1077xxx4424:AAFjv0FcqxxxxxxgEMGfi22B4yh15R5uw",
|
"telegram机器人的token,例如:1077xxx4424:AAFjv0FcqxxxxxxgEMGfi22B4yh15R5uw": "telegram机器人的token,例如:1077xxx4424:AAFjv0FcqxxxxxxgEMGfi22B4yh15R5uw",
|
||||||
"telegram用户的id,例如:129xxx206": "telegram用户的id,例如:129xxx206",
|
"telegram用户的id,例如:129xxx206": "telegram用户的id,例如:129xxx206",
|
||||||
"代理IP": "代理IP",
|
"代理IP": "代理IP",
|
||||||
"代理端口": "代理端口",
|
"代理端口": "代理端口",
|
||||||
"telegram代理配置认证参数, 用户名与密码用英文冒号连接 user:password": "telegram代理配置认证参数, 用户名与密码用英文冒号连接 user:password",
|
"telegram代理配置认证参数,用户名与密码用英文冒号连接 user:password": "telegram代理配置认证参数, 用户名与密码用英文冒号连接 user:password",
|
||||||
"telegram api自建的反向代理地址,默认tg官方api": "telegram api自建的反向代理地址,默认tg官方api",
|
"telegram api自建的反向代理地址,默认tg官方api": "telegram api自建的反向代理地址,默认tg官方api",
|
||||||
"钉钉机器人webhook token,例如:5a544165465465645d0f31dca676e7bd07415asdasd": "钉钉机器人webhook token,例如:5a544165465465645d0f31dca676e7bd07415asdasd",
|
"钉钉机器人webhook token,例如:5a544165465465645d0f31dca676e7bd07415asdasd": "钉钉机器人webhook token,例如:5a544165465465645d0f31dca676e7bd07415asdasd",
|
||||||
"密钥,机器人安全设置页面,加签一栏下面显示的SEC开头的字符串": "密钥,机器人安全设置页面,加签一栏下面显示的SEC开头的字符串",
|
"密钥,机器人安全设置页面,加签一栏下面显示的SEC开头的字符串": "密钥,机器人安全设置页面,加签一栏下面显示的SEC开头的字符串",
|
||||||
"企业微信机器人的 webhook(详见文档 https://work.weixin.qq.com/api/doc/90000/90136/91770),例如:693a91f6-7xxx-4bc4-97a0-0ec2sifa5aaa": "企业微信机器人的 webhook(详见文档 https://work.weixin.qq.com/api/doc/90000/90136/91770),例如:693a91f6-7xxx-4bc4-97a0-0ec2sifa5aaa",
|
"企业微信机器人的webhook(详见文档 https://work.weixin.qq.com/api/doc/90000/90136/91770),例如:693a91f6-7xxx-4bc4-97a0-0ec2sifa5aaa": "企业微信机器人的 webhook(详见文档 https://work.weixin.qq.com/api/doc/90000/90136/91770),例如:693a91f6-7xxx-4bc4-97a0-0ec2sifa5aaa",
|
||||||
"企业微信代理地址": "企业微信代理地址",
|
"企业微信代理地址": "企业微信代理地址",
|
||||||
"corpid,corpsecret,touser(注:多个成员ID使用|隔开),agentid,消息类型(选填,不填默认文本消息类型) 注意用,号隔开(英文输入法的逗号),例如:wwcfrs,B-76WERQ,qinglong,1000001,2COat": "corpid,corpsecret,touser(注:多个成员ID使用|隔开),agentid,消息类型(选填,不填默认文本消息类型) 注意用,号隔开(英文输入法的逗号),例如:wwcfrs,B-76WERQ,qinglong,1000001,2COat",
|
"corpid、corpsecret、touser(注:多个成员ID使用|隔开)、agentid、消息类型(选填,不填默认文本消息类型) 注意用,号隔开(英文输入法的逗号),例如:wwcfrs,B-76WERQ,qinglong,1000001,2COat": "corpid,corpsecret,touser(注:多个成员ID使用|隔开),agentid,消息类型(选填,不填默认文本消息类型) 注意用,号隔开(英文输入法的逗号),例如:wwcfrs,B-76WERQ,qinglong,1000001,2COat",
|
||||||
"密钥key,智能微秘书个人中心获取apikey,申请地址:https://wechat.aibotk.com/signup?from=ql": "密钥key,智能微秘书个人中心获取apikey,申请地址:https://wechat.aibotk.com/signup?from=ql",
|
"密钥key,智能微秘书个人中心获取apikey,申请地址:https://wechat.aibotk.com/signup?from=ql": "密钥key,智能微秘书个人中心获取apikey,申请地址:https://wechat.aibotk.com/signup?from=ql",
|
||||||
"发送的目标,群组或者好友": "发送的目标,群组或者好友",
|
"发送的目标,群组或者好友": "发送的目标,群组或者好友",
|
||||||
"请输入要发送的目标": "请输入要发送的目标",
|
"请输入要发送的目标": "请输入要发送的目标",
|
||||||
"群聊": "群聊",
|
"群聊": "群聊",
|
||||||
@@ -448,5 +448,8 @@
|
|||||||
"编辑订阅": "编辑订阅",
|
"编辑订阅": "编辑订阅",
|
||||||
"Subscription表达式格式有误": "Subscription表达式格式有误",
|
"Subscription表达式格式有误": "Subscription表达式格式有误",
|
||||||
"一对多推送的“群组编码”(一对多推送下面->您的群组(如无则新建)->群组编码,如果您是创建群组人。也需点击“查看二维码”扫描绑定,否则不能接受群组消息推送)": "一对多推送的“群组编码”(一对多推送下面->您的群组(如无则新建)->群组编码,如果您是创建群组人。也需点击“查看二维码”扫描绑定,否则不能接受群组消息推送)",
|
"一对多推送的“群组编码”(一对多推送下面->您的群组(如无则新建)->群组编码,如果您是创建群组人。也需点击“查看二维码”扫描绑定,否则不能接受群组消息推送)": "一对多推送的“群组编码”(一对多推送下面->您的群组(如无则新建)->群组编码,如果您是创建群组人。也需点击“查看二维码”扫描绑定,否则不能接受群组消息推送)",
|
||||||
"登录已过期,请重新登录": "登录已过期,请重新登录"
|
"登录已过期,请重新登录": "登录已过期,请重新登录",
|
||||||
|
"系统日志": "系统日志",
|
||||||
|
"主题": "主题",
|
||||||
|
"语言": "语言"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,9 +11,10 @@ import config from '@/utils/config';
|
|||||||
import { PageContainer } from '@ant-design/pro-layout';
|
import { PageContainer } from '@ant-design/pro-layout';
|
||||||
import { request } from '@/utils/http';
|
import { request } from '@/utils/http';
|
||||||
import Editor from '@monaco-editor/react';
|
import Editor from '@monaco-editor/react';
|
||||||
import { Controlled as CodeMirror } from 'react-codemirror2';
|
import CodeMirror from '@uiw/react-codemirror';
|
||||||
import { useOutletContext } from '@umijs/max';
|
import { useOutletContext } from '@umijs/max';
|
||||||
import { SharedContext } from '@/layouts';
|
import { SharedContext } from '@/layouts';
|
||||||
|
import { langs } from '@uiw/codemirror-extensions-langs';
|
||||||
|
|
||||||
const Config = () => {
|
const Config = () => {
|
||||||
const { headerStyle, isPhone, theme } = useOutletContext<SharedContext>();
|
const { headerStyle, isPhone, theme } = useOutletContext<SharedContext>();
|
||||||
@@ -104,16 +105,11 @@ const Config = () => {
|
|||||||
{isPhone ? (
|
{isPhone ? (
|
||||||
<CodeMirror
|
<CodeMirror
|
||||||
value={value}
|
value={value}
|
||||||
options={{
|
theme={theme.includes('dark') ? 'dark' : 'light'}
|
||||||
lineNumbers: true,
|
extensions={[langs.shell()]}
|
||||||
styleActiveLine: true,
|
onChange={(value) => {
|
||||||
matchBrackets: true,
|
|
||||||
mode: 'shell',
|
|
||||||
}}
|
|
||||||
onBeforeChange={(editor, data, value) => {
|
|
||||||
setValue(value);
|
setValue(value);
|
||||||
}}
|
}}
|
||||||
onChange={(editor, data, value) => {}}
|
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<Editor
|
<Editor
|
||||||
|
|||||||
@@ -94,7 +94,7 @@
|
|||||||
.log-item {
|
.log-item {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
&:hover {
|
&:hover {
|
||||||
background: #fafafa;
|
background: #f2f2f2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,18 +186,6 @@ tr.drop-over-upward td {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.log-modal {
|
|
||||||
.log-container {
|
|
||||||
overflow-y: auto;
|
|
||||||
min-height: 300px;
|
|
||||||
max-height: calc(80vh - 110px);
|
|
||||||
max-height: calc(80vh - var(--vh-offset, 110px));
|
|
||||||
|
|
||||||
padding: 24px;
|
|
||||||
margin: -24px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
body[data-mode='desktop'] {
|
body[data-mode='desktop'] {
|
||||||
.crontab-wrapper {
|
.crontab-wrapper {
|
||||||
tbody .ant-table-cell {
|
tbody .ant-table-cell {
|
||||||
@@ -205,3 +193,7 @@ body[data-mode='desktop'] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cron.pinned-cron > td {
|
||||||
|
background: #f2f2f2;
|
||||||
|
}
|
||||||
+38
-72
@@ -68,53 +68,25 @@ const Crontab = () => {
|
|||||||
title: intl.get('名称'),
|
title: intl.get('名称'),
|
||||||
dataIndex: 'name',
|
dataIndex: 'name',
|
||||||
key: 'name',
|
key: 'name',
|
||||||
fixed: isPhone ? undefined : 'left',
|
fixed: 'left',
|
||||||
width: 120,
|
width: 120,
|
||||||
render: (text: string, record: any) => (
|
render: (text: string, record: any) => (
|
||||||
<>
|
<Paragraph
|
||||||
|
style={{
|
||||||
|
wordBreak: 'break-all',
|
||||||
|
marginBottom: 0,
|
||||||
|
}}
|
||||||
|
ellipsis={{ tooltip: text, rows: 2 }}
|
||||||
|
>
|
||||||
<a
|
<a
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setDetailCron(record);
|
setDetailCron(record);
|
||||||
setIsDetailModalVisible(true);
|
setIsDetailModalVisible(true);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{record.labels?.length > 0 && record.labels[0] !== '' && false ? (
|
{record.name || '-'}
|
||||||
<Popover
|
|
||||||
placement="right"
|
|
||||||
trigger={isPhone ? 'click' : 'hover'}
|
|
||||||
content={
|
|
||||||
<div>
|
|
||||||
{record.labels?.map((label: string) => (
|
|
||||||
<Tag
|
|
||||||
color="blue"
|
|
||||||
key={label}
|
|
||||||
style={{ cursor: 'point' }}
|
|
||||||
onClick={(e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
setSearchValue(`label:${label}`);
|
|
||||||
setSearchText(`label:${label}`);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<a>{label}</a>
|
|
||||||
</Tag>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{record.name || '-'}
|
|
||||||
</Popover>
|
|
||||||
) : (
|
|
||||||
record.name || '-'
|
|
||||||
)}
|
|
||||||
{record.isPinned ? (
|
|
||||||
<span>
|
|
||||||
<PushpinOutlined />
|
|
||||||
</span>
|
|
||||||
) : (
|
|
||||||
''
|
|
||||||
)}
|
|
||||||
</a>
|
</a>
|
||||||
</>
|
</Paragraph>
|
||||||
),
|
),
|
||||||
sorter: {
|
sorter: {
|
||||||
compare: (a, b) => a?.name?.localeCompare(b?.name),
|
compare: (a, b) => a?.name?.localeCompare(b?.name),
|
||||||
@@ -124,7 +96,7 @@ const Crontab = () => {
|
|||||||
title: intl.get('命令/脚本'),
|
title: intl.get('命令/脚本'),
|
||||||
dataIndex: 'command',
|
dataIndex: 'command',
|
||||||
key: 'command',
|
key: 'command',
|
||||||
width: 200,
|
width: 240,
|
||||||
render: (text, record) => {
|
render: (text, record) => {
|
||||||
return (
|
return (
|
||||||
<Paragraph
|
<Paragraph
|
||||||
@@ -214,7 +186,7 @@ const Crontab = () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: intl.get('最后运行时长'),
|
title: intl.get('最后运行时长'),
|
||||||
width: 180,
|
width: 167,
|
||||||
dataIndex: 'last_running_time',
|
dataIndex: 'last_running_time',
|
||||||
key: 'last_running_time',
|
key: 'last_running_time',
|
||||||
sorter: {
|
sorter: {
|
||||||
@@ -232,7 +204,7 @@ const Crontab = () => {
|
|||||||
title: intl.get('最后运行时间'),
|
title: intl.get('最后运行时间'),
|
||||||
dataIndex: 'last_execution_time',
|
dataIndex: 'last_execution_time',
|
||||||
key: 'last_execution_time',
|
key: 'last_execution_time',
|
||||||
width: 150,
|
width: 141,
|
||||||
sorter: {
|
sorter: {
|
||||||
compare: (a, b) => {
|
compare: (a, b) => {
|
||||||
return (a.last_execution_time || 0) - (b.last_execution_time || 0);
|
return (a.last_execution_time || 0) - (b.last_execution_time || 0);
|
||||||
@@ -259,7 +231,7 @@ const Crontab = () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: intl.get('下次运行时间'),
|
title: intl.get('下次运行时间'),
|
||||||
width: 150,
|
width: 144,
|
||||||
sorter: {
|
sorter: {
|
||||||
compare: (a: any, b: any) => {
|
compare: (a: any, b: any) => {
|
||||||
return a.nextRunTime - b.nextRunTime;
|
return a.nextRunTime - b.nextRunTime;
|
||||||
@@ -276,7 +248,7 @@ const Crontab = () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: intl.get('关联订阅'),
|
title: intl.get('关联订阅'),
|
||||||
width: 190,
|
width: 185,
|
||||||
render: (text, record: any) =>
|
render: (text, record: any) =>
|
||||||
record.sub_id ? (
|
record.sub_id ? (
|
||||||
<Name
|
<Name
|
||||||
@@ -292,46 +264,40 @@ const Crontab = () => {
|
|||||||
{
|
{
|
||||||
title: intl.get('操作'),
|
title: intl.get('操作'),
|
||||||
key: 'action',
|
key: 'action',
|
||||||
width: 130,
|
width: 140,
|
||||||
fixed: isPhone ? undefined : 'right',
|
fixed: isPhone ? undefined : 'right',
|
||||||
render: (text, record, index) => {
|
render: (text, record, index) => {
|
||||||
const isPc = !isPhone;
|
const isPc = !isPhone;
|
||||||
return (
|
return (
|
||||||
<Space size="middle">
|
<Space size="middle">
|
||||||
{record.status === CrontabStatus.idle && (
|
{record.status === CrontabStatus.idle && (
|
||||||
<Tooltip title={isPc ? intl.get('运行') : ''}>
|
|
||||||
<a
|
|
||||||
onClick={(e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
runCron(record, index);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<PlayCircleOutlined />
|
|
||||||
</a>
|
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
{record.status !== CrontabStatus.idle && (
|
|
||||||
<Tooltip title={isPc ? intl.get('停止') : ''}>
|
|
||||||
<a
|
|
||||||
onClick={(e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
stopCron(record, index);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<PauseCircleOutlined />
|
|
||||||
</a>
|
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
<Tooltip title={isPc ? intl.get('日志') : ''}>
|
|
||||||
<a
|
<a
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
setLogCron({ ...record, timestamp: Date.now() });
|
runCron(record, index);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<FileTextOutlined />
|
{intl.get('运行')}
|
||||||
</a>
|
</a>
|
||||||
</Tooltip>
|
)}
|
||||||
|
{record.status !== CrontabStatus.idle && (
|
||||||
|
<a
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
stopCron(record, index);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{intl.get('停止')}
|
||||||
|
</a>
|
||||||
|
)}
|
||||||
|
<a
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
setLogCron({ ...record, timestamp: Date.now() });
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{intl.get('日志')}
|
||||||
|
</a>
|
||||||
<MoreBtn key="more" record={record} index={index} />
|
<MoreBtn key="more" record={record} index={index} />
|
||||||
</Space>
|
</Space>
|
||||||
);
|
);
|
||||||
@@ -1041,7 +1007,7 @@ const Crontab = () => {
|
|||||||
dataSource={value}
|
dataSource={value}
|
||||||
rowKey="id"
|
rowKey="id"
|
||||||
size="middle"
|
size="middle"
|
||||||
scroll={{ x: 1000, y: tableScrollHeight }}
|
scroll={{ x: 1200, y: tableScrollHeight }}
|
||||||
loading={loading}
|
loading={loading}
|
||||||
rowSelection={rowSelection}
|
rowSelection={rowSelection}
|
||||||
rowClassName={getRowClassName}
|
rowClassName={getRowClassName}
|
||||||
|
|||||||
@@ -50,8 +50,8 @@ const CronLogModal = ({
|
|||||||
log && !logEnded(log) && !log.includes('任务未运行'),
|
log && !logEnded(log) && !log.includes('任务未运行'),
|
||||||
);
|
);
|
||||||
setExecuting(hasNext);
|
setExecuting(hasNext);
|
||||||
autoScroll();
|
|
||||||
if (hasNext) {
|
if (hasNext) {
|
||||||
|
autoScroll();
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
getCronLog();
|
getCronLog();
|
||||||
}, 2000);
|
}, 2000);
|
||||||
@@ -74,7 +74,7 @@ const CronLogModal = ({
|
|||||||
document
|
document
|
||||||
.querySelector('#log-flag')!
|
.querySelector('#log-flag')!
|
||||||
.scrollIntoView({ behavior: 'smooth' });
|
.scrollIntoView({ behavior: 'smooth' });
|
||||||
}, 1000);
|
}, 600);
|
||||||
};
|
};
|
||||||
|
|
||||||
const cancel = () => {
|
const cancel = () => {
|
||||||
@@ -124,9 +124,6 @@ const CronLogModal = ({
|
|||||||
open={visible}
|
open={visible}
|
||||||
centered
|
centered
|
||||||
className="log-modal"
|
className="log-modal"
|
||||||
bodyStyle={{
|
|
||||||
minHeight: '300px',
|
|
||||||
}}
|
|
||||||
forceRender
|
forceRender
|
||||||
onOk={() => cancel()}
|
onOk={() => cancel()}
|
||||||
onCancel={() => cancel()}
|
onCancel={() => cancel()}
|
||||||
@@ -145,7 +142,6 @@ const CronLogModal = ({
|
|||||||
isPhone
|
isPhone
|
||||||
? {
|
? {
|
||||||
fontFamily: 'Source Code Pro',
|
fontFamily: 'Source Code Pro',
|
||||||
width: 375,
|
|
||||||
zoom: 0.83,
|
zoom: 0.83,
|
||||||
}
|
}
|
||||||
: {}
|
: {}
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ const CronModal = ({
|
|||||||
>
|
>
|
||||||
<Input.TextArea
|
<Input.TextArea
|
||||||
rows={4}
|
rows={4}
|
||||||
autoSize={true}
|
autoSize={{ minRows: 1, maxRows: 5 }}
|
||||||
placeholder={intl.get(
|
placeholder={intl.get(
|
||||||
'支持输入脚本路径/任意系统可执行命令/task 脚本路径',
|
'支持输入脚本路径/任意系统可执行命令/task 脚本路径',
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -400,7 +400,7 @@ const Dependence = () => {
|
|||||||
const { type, message, references } = socketMessage;
|
const { type, message, references } = socketMessage;
|
||||||
if (
|
if (
|
||||||
type === 'installDependence' &&
|
type === 'installDependence' &&
|
||||||
message.includes(intl.get('开始时间')) &&
|
message.includes('开始时间') &&
|
||||||
references.length > 0
|
references.length > 0
|
||||||
) {
|
) {
|
||||||
const result = [...value];
|
const result = [...value];
|
||||||
@@ -409,7 +409,7 @@ const Dependence = () => {
|
|||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
result.splice(index, 1, {
|
result.splice(index, 1, {
|
||||||
...value[index],
|
...value[index],
|
||||||
status: message.includes(intl.get('安装')) ? Status.安装中 : Status.删除中,
|
status: message.includes('安装') ? Status.安装中 : Status.删除中,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -417,14 +417,14 @@ const Dependence = () => {
|
|||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
type === 'installDependence' &&
|
type === 'installDependence' &&
|
||||||
message.includes(intl.get('结束时间')) &&
|
message.includes('结束时间') &&
|
||||||
references.length > 0
|
references.length > 0
|
||||||
) {
|
) {
|
||||||
let status;
|
let status;
|
||||||
if (message.includes(intl.get('安装'))) {
|
if (message.includes('安装')) {
|
||||||
status = message.includes(intl.get('成功')) ? Status.已安装 : Status.安装失败;
|
status = message.includes('成功') ? Status.已安装 : Status.安装失败;
|
||||||
} else {
|
} else {
|
||||||
status = message.includes(intl.get('成功')) ? Status.已删除 : Status.删除失败;
|
status = message.includes('成功') ? Status.已删除 : Status.删除失败;
|
||||||
}
|
}
|
||||||
const result = [...value];
|
const result = [...value];
|
||||||
for (let i = 0; i < references.length; i++) {
|
for (let i = 0; i < references.length; i++) {
|
||||||
|
|||||||
@@ -56,8 +56,8 @@ const DependenceLogModal = ({
|
|||||||
) {
|
) {
|
||||||
const log = (data.log || []).join('') as string;
|
const log = (data.log || []).join('') as string;
|
||||||
setValue(log);
|
setValue(log);
|
||||||
setExecuting(!log.includes(intl.get('结束时间')));
|
setExecuting(!log.includes('结束时间'));
|
||||||
setIsRemoveFailed(log.includes(intl.get('删除失败')));
|
setIsRemoveFailed(log.includes('删除失败'));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
@@ -103,9 +103,9 @@ const DependenceLogModal = ({
|
|||||||
references.length > 0 &&
|
references.length > 0 &&
|
||||||
references.includes(dependence.id)
|
references.includes(dependence.id)
|
||||||
) {
|
) {
|
||||||
if (message.includes(intl.get('结束时间'))) {
|
if (message.includes('结束时间')) {
|
||||||
setExecuting(false);
|
setExecuting(false);
|
||||||
setIsRemoveFailed(message.includes(intl.get('删除失败')));
|
setIsRemoveFailed(message.includes('删除失败'));
|
||||||
}
|
}
|
||||||
setValue(`${value}${message}`);
|
setValue(`${value}${message}`);
|
||||||
}
|
}
|
||||||
@@ -121,11 +121,6 @@ const DependenceLogModal = ({
|
|||||||
open={visible}
|
open={visible}
|
||||||
centered
|
centered
|
||||||
className="log-modal"
|
className="log-modal"
|
||||||
bodyStyle={{
|
|
||||||
overflowY: 'auto',
|
|
||||||
maxHeight: 'calc(70vh - var(--vh-offset, 0px))',
|
|
||||||
minHeight: '300px',
|
|
||||||
}}
|
|
||||||
forceRender
|
forceRender
|
||||||
onOk={() => cancel()}
|
onOk={() => cancel()}
|
||||||
onCancel={() => cancel()}
|
onCancel={() => cancel()}
|
||||||
@@ -135,23 +130,24 @@ const DependenceLogModal = ({
|
|||||||
</Button>,
|
</Button>,
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
{loading ? (
|
<div className="log-container">
|
||||||
<PageLoading />
|
{loading ? (
|
||||||
) : (
|
<PageLoading />
|
||||||
<pre
|
) : (
|
||||||
style={
|
<pre
|
||||||
isPhone
|
style={
|
||||||
? {
|
isPhone
|
||||||
fontFamily: 'Source Code Pro',
|
? {
|
||||||
width: 375,
|
fontFamily: 'Source Code Pro',
|
||||||
zoom: 0.83,
|
zoom: 0.83,
|
||||||
}
|
}
|
||||||
: {}
|
: {}
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Ansi>{value}</Ansi>
|
<Ansi>{value}</Ansi>
|
||||||
</pre>
|
</pre>
|
||||||
)}
|
)}
|
||||||
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ const DependenceModal = ({
|
|||||||
>
|
>
|
||||||
<Input.TextArea
|
<Input.TextArea
|
||||||
rows={4}
|
rows={4}
|
||||||
autoSize={true}
|
autoSize={{ minRows: 1, maxRows: 5 }}
|
||||||
placeholder={intl.get('请输入依赖名称')}
|
placeholder={intl.get('请输入依赖名称')}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|||||||
Vendored
+44
-14
@@ -1,4 +1,4 @@
|
|||||||
import intl from 'react-intl-universal'
|
import intl from 'react-intl-universal';
|
||||||
import React, {
|
import React, {
|
||||||
useCallback,
|
useCallback,
|
||||||
useRef,
|
useRef,
|
||||||
@@ -42,7 +42,7 @@ import useTableScrollHeight from '@/hooks/useTableScrollHeight';
|
|||||||
import Copy from '../../components/copy';
|
import Copy from '../../components/copy';
|
||||||
import { useVT } from 'virtualizedtableforantd4';
|
import { useVT } from 'virtualizedtableforantd4';
|
||||||
|
|
||||||
const { Text } = Typography;
|
const { Paragraph } = Typography;
|
||||||
const { Search } = Input;
|
const { Search } = Input;
|
||||||
|
|
||||||
enum Status {
|
enum Status {
|
||||||
@@ -149,7 +149,7 @@ const Env = () => {
|
|||||||
title: intl.get('状态'),
|
title: intl.get('状态'),
|
||||||
key: 'status',
|
key: 'status',
|
||||||
dataIndex: 'status',
|
dataIndex: 'status',
|
||||||
width: 80,
|
width: 100,
|
||||||
filters: [
|
filters: [
|
||||||
{
|
{
|
||||||
text: intl.get('已启用'),
|
text: intl.get('已启用'),
|
||||||
@@ -186,7 +186,11 @@ const Env = () => {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
title={
|
title={
|
||||||
isPc ? (record.status === Status.已禁用 ? intl.get('启用') : intl.get('禁用')) : ''
|
isPc
|
||||||
|
? record.status === Status.已禁用
|
||||||
|
? intl.get('启用')
|
||||||
|
: intl.get('禁用')
|
||||||
|
: ''
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<a onClick={() => enabledOrDisabledEnv(record, index)}>
|
<a onClick={() => enabledOrDisabledEnv(record, index)}>
|
||||||
@@ -232,14 +236,24 @@ const Env = () => {
|
|||||||
|
|
||||||
const enabledOrDisabledEnv = (record: any, index: number) => {
|
const enabledOrDisabledEnv = (record: any, index: number) => {
|
||||||
Modal.confirm({
|
Modal.confirm({
|
||||||
title: `确认${record.status === Status.已禁用 ? intl.get('启用') : intl.get('禁用')}`,
|
title: `确认${
|
||||||
|
record.status === Status.已禁用 ? intl.get('启用') : intl.get('禁用')
|
||||||
|
}`,
|
||||||
content: (
|
content: (
|
||||||
<>
|
<>
|
||||||
{intl.get('确认')}{record.status === Status.已禁用 ? intl.get('启用') : intl.get('禁用')}
|
{intl.get('确认')}
|
||||||
|
{record.status === Status.已禁用
|
||||||
|
? intl.get('启用')
|
||||||
|
: intl.get('禁用')}
|
||||||
Env{' '}
|
Env{' '}
|
||||||
<Text style={{ wordBreak: 'break-all' }} type="warning">
|
<Paragraph
|
||||||
|
style={{ wordBreak: 'break-all', display: 'inline' }}
|
||||||
|
ellipsis={{ rows: 6, expandable: true }}
|
||||||
|
type="warning"
|
||||||
|
copyable
|
||||||
|
>
|
||||||
{record.value}
|
{record.value}
|
||||||
</Text>{' '}
|
</Paragraph>{' '}
|
||||||
{intl.get('吗')}
|
{intl.get('吗')}
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
@@ -254,7 +268,11 @@ const Env = () => {
|
|||||||
.then(({ code, data }) => {
|
.then(({ code, data }) => {
|
||||||
if (code === 200) {
|
if (code === 200) {
|
||||||
message.success(
|
message.success(
|
||||||
`${record.status === Status.已禁用 ? intl.get('启用') : intl.get('禁用')}${intl.get('成功')}`,
|
`${
|
||||||
|
record.status === Status.已禁用
|
||||||
|
? intl.get('启用')
|
||||||
|
: intl.get('禁用')
|
||||||
|
}${intl.get('成功')}`,
|
||||||
);
|
);
|
||||||
const newStatus =
|
const newStatus =
|
||||||
record.status === Status.已禁用 ? Status.已启用 : Status.已禁用;
|
record.status === Status.已禁用 ? Status.已启用 : Status.已禁用;
|
||||||
@@ -289,9 +307,14 @@ const Env = () => {
|
|||||||
content: (
|
content: (
|
||||||
<>
|
<>
|
||||||
{intl.get('确认删除变量')}{' '}
|
{intl.get('确认删除变量')}{' '}
|
||||||
<Text style={{ wordBreak: 'break-all' }} type="warning">
|
<Paragraph
|
||||||
|
style={{ wordBreak: 'break-all', display: 'inline' }}
|
||||||
|
ellipsis={{ rows: 6, expandable: true }}
|
||||||
|
type="warning"
|
||||||
|
copyable
|
||||||
|
>
|
||||||
{record.name}: {record.value}
|
{record.name}: {record.value}
|
||||||
</Text>{' '}
|
</Paragraph>{' '}
|
||||||
{intl.get('吗')}
|
{intl.get('吗')}
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
@@ -435,7 +458,13 @@ const Env = () => {
|
|||||||
const operateEnvs = (operationStatus: number) => {
|
const operateEnvs = (operationStatus: number) => {
|
||||||
Modal.confirm({
|
Modal.confirm({
|
||||||
title: `确认${OperationName[operationStatus]}`,
|
title: `确认${OperationName[operationStatus]}`,
|
||||||
content: <>{intl.get('确认')}{OperationName[operationStatus]}{intl.get('选中的变量吗')}</>,
|
content: (
|
||||||
|
<>
|
||||||
|
{intl.get('确认')}
|
||||||
|
{OperationName[operationStatus]}
|
||||||
|
{intl.get('选中的变量吗')}
|
||||||
|
</>
|
||||||
|
),
|
||||||
onOk() {
|
onOk() {
|
||||||
request
|
request
|
||||||
.put(
|
.put(
|
||||||
@@ -567,7 +596,8 @@ const Env = () => {
|
|||||||
</Button>
|
</Button>
|
||||||
<span style={{ marginLeft: 8 }}>
|
<span style={{ marginLeft: 8 }}>
|
||||||
{intl.get('已选择')}
|
{intl.get('已选择')}
|
||||||
<a>{selectedRowIds?.length}</a>{intl.get('项')}
|
<a>{selectedRowIds?.length}</a>
|
||||||
|
{intl.get('项')}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -579,7 +609,7 @@ const Env = () => {
|
|||||||
dataSource={value}
|
dataSource={value}
|
||||||
rowKey="id"
|
rowKey="id"
|
||||||
size="middle"
|
size="middle"
|
||||||
scroll={{ x: 1000, y: tableScrollHeight }}
|
scroll={{ x: 1200, y: tableScrollHeight }}
|
||||||
components={vt}
|
components={vt}
|
||||||
loading={loading}
|
loading={loading}
|
||||||
onRow={(record: any, index: number | undefined) => {
|
onRow={(record: any, index: number | undefined) => {
|
||||||
|
|||||||
Vendored
+15
-6
@@ -1,4 +1,4 @@
|
|||||||
import intl from 'react-intl-universal'
|
import intl from 'react-intl-universal';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { Modal, message, Input, Form, Radio } from 'antd';
|
import { Modal, message, Input, Form, Radio } from 'antd';
|
||||||
import { request } from '@/utils/http';
|
import { request } from '@/utils/http';
|
||||||
@@ -44,7 +44,9 @@ const EnvModal = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (code === 200) {
|
if (code === 200) {
|
||||||
message.success(env ? intl.get('更新变量成功') : intl.get('创建变量成功'));
|
message.success(
|
||||||
|
env ? intl.get('更新变量成功') : intl.get('创建变量成功'),
|
||||||
|
);
|
||||||
handleCancel(data);
|
handleCancel(data);
|
||||||
}
|
}
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
@@ -82,7 +84,11 @@ const EnvModal = ({
|
|||||||
name="name"
|
name="name"
|
||||||
label={intl.get('名称')}
|
label={intl.get('名称')}
|
||||||
rules={[
|
rules={[
|
||||||
{ required: true, message: intl.get('请输入环境变量名称'), whitespace: true },
|
{
|
||||||
|
required: true,
|
||||||
|
message: intl.get('请输入环境变量名称'),
|
||||||
|
whitespace: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
pattern: /^[a-zA-Z_][0-9a-zA-Z_]*$/,
|
pattern: /^[a-zA-Z_][0-9a-zA-Z_]*$/,
|
||||||
message: intl.get('只能输入字母数字下划线,且不能以数字开头'),
|
message: intl.get('只能输入字母数字下划线,且不能以数字开头'),
|
||||||
@@ -108,12 +114,15 @@ const EnvModal = ({
|
|||||||
name="value"
|
name="value"
|
||||||
label={intl.get('值')}
|
label={intl.get('值')}
|
||||||
rules={[
|
rules={[
|
||||||
{ required: true, message: intl.get('请输入环境变量值'), whitespace: true },
|
{
|
||||||
|
required: true,
|
||||||
|
message: intl.get('请输入环境变量值'),
|
||||||
|
whitespace: true,
|
||||||
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Input.TextArea
|
<Input.TextArea
|
||||||
rows={4}
|
autoSize={{ minRows: 1, maxRows: 8 }}
|
||||||
autoSize={true}
|
|
||||||
placeholder={intl.get('请输入环境变量值')}
|
placeholder={intl.get('请输入环境变量值')}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ const Initialization = () => {
|
|||||||
style={{ maxWidth: 400 }}
|
style={{ maxWidth: 400 }}
|
||||||
>
|
>
|
||||||
<Input.TextArea
|
<Input.TextArea
|
||||||
autoSize={true}
|
autoSize={{ minRows: 1, maxRows: 5 }}
|
||||||
placeholder={`请输入${x.label}`}
|
placeholder={`请输入${x.label}`}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|||||||
+4
-10
@@ -16,7 +16,7 @@ import { PageContainer } from '@ant-design/pro-layout';
|
|||||||
import Editor from '@monaco-editor/react';
|
import Editor from '@monaco-editor/react';
|
||||||
import { request } from '@/utils/http';
|
import { request } from '@/utils/http';
|
||||||
import styles from './index.module.less';
|
import styles from './index.module.less';
|
||||||
import { Controlled as CodeMirror } from 'react-codemirror2';
|
import CodeMirror from '@uiw/react-codemirror';
|
||||||
import SplitPane from 'react-split-pane';
|
import SplitPane from 'react-split-pane';
|
||||||
import { useOutletContext } from '@umijs/max';
|
import { useOutletContext } from '@umijs/max';
|
||||||
import { SharedContext } from '@/layouts';
|
import { SharedContext } from '@/layouts';
|
||||||
@@ -278,17 +278,11 @@ const Log = () => {
|
|||||||
{isPhone && (
|
{isPhone && (
|
||||||
<CodeMirror
|
<CodeMirror
|
||||||
value={value}
|
value={value}
|
||||||
options={{
|
readOnly={true}
|
||||||
lineNumbers: true,
|
theme={theme.includes('dark') ? 'dark' : 'light'}
|
||||||
lineWrapping: true,
|
onChange={(value, viewUpdate) => {
|
||||||
styleActiveLine: true,
|
|
||||||
matchBrackets: true,
|
|
||||||
readOnly: true,
|
|
||||||
}}
|
|
||||||
onBeforeChange={(editor, data, value) => {
|
|
||||||
setValue(value);
|
setValue(value);
|
||||||
}}
|
}}
|
||||||
onChange={(editor, data, value) => {}}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -224,6 +224,7 @@ const EditModal = ({
|
|||||||
minSize={200}
|
minSize={200}
|
||||||
defaultSize="50%"
|
defaultSize="50%"
|
||||||
style={{ height: 'calc(100vh - 55px)' }}
|
style={{ height: 'calc(100vh - 55px)' }}
|
||||||
|
pane2Style={{ overflowY: 'auto' }}
|
||||||
>
|
>
|
||||||
<Editor
|
<Editor
|
||||||
language={language}
|
language={language}
|
||||||
@@ -241,7 +242,6 @@ const EditModal = ({
|
|||||||
/>
|
/>
|
||||||
<pre
|
<pre
|
||||||
style={{
|
style={{
|
||||||
height: '100%',
|
|
||||||
padding: '0 15px',
|
padding: '0 15px',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import Editor from '@monaco-editor/react';
|
|||||||
import { request } from '@/utils/http';
|
import { request } from '@/utils/http';
|
||||||
import styles from './index.module.less';
|
import styles from './index.module.less';
|
||||||
import EditModal from './editModal';
|
import EditModal from './editModal';
|
||||||
import { Controlled as CodeMirror } from 'react-codemirror2';
|
import CodeMirror from '@uiw/react-codemirror';
|
||||||
import SplitPane from 'react-split-pane';
|
import SplitPane from 'react-split-pane';
|
||||||
import {
|
import {
|
||||||
DeleteOutlined,
|
DeleteOutlined,
|
||||||
@@ -43,6 +43,7 @@ import useFilterTreeData from '@/hooks/useFilterTreeData';
|
|||||||
import uniq from 'lodash/uniq';
|
import uniq from 'lodash/uniq';
|
||||||
import IconFont from '@/components/iconfont';
|
import IconFont from '@/components/iconfont';
|
||||||
import RenameModal from './renameModal';
|
import RenameModal from './renameModal';
|
||||||
|
import { langs } from '@uiw/codemirror-extensions-langs';
|
||||||
|
|
||||||
const { Text } = Typography;
|
const { Text } = Typography;
|
||||||
|
|
||||||
@@ -580,18 +581,14 @@ const Script = () => {
|
|||||||
{isPhone && (
|
{isPhone && (
|
||||||
<CodeMirror
|
<CodeMirror
|
||||||
value={value}
|
value={value}
|
||||||
options={{
|
extensions={
|
||||||
lineNumbers: true,
|
mode ? [langs[mode as keyof typeof langs]()] : undefined
|
||||||
lineWrapping: true,
|
}
|
||||||
styleActiveLine: true,
|
theme={theme.includes('dark') ? 'dark' : 'light'}
|
||||||
matchBrackets: true,
|
readOnly={!isEditing}
|
||||||
mode,
|
onChange={(value) => {
|
||||||
readOnly: !isEditing,
|
|
||||||
}}
|
|
||||||
onBeforeChange={(editor, data, value) => {
|
|
||||||
setValue(value);
|
setValue(value);
|
||||||
}}
|
}}
|
||||||
onChange={(editor, data, value) => {}}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<EditModal
|
<EditModal
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ const { Link } = Typography;
|
|||||||
enum TVersion {
|
enum TVersion {
|
||||||
'develop' = '开发版',
|
'develop' = '开发版',
|
||||||
'master' = '正式版',
|
'master' = '正式版',
|
||||||
|
'debian' = '正式版'
|
||||||
}
|
}
|
||||||
|
|
||||||
const About = ({ systemInfo }: { systemInfo: SharedContext['systemInfo'] }) => {
|
const About = ({ systemInfo }: { systemInfo: SharedContext['systemInfo'] }) => {
|
||||||
|
|||||||
@@ -75,16 +75,7 @@ const CheckUpdate = ({ socketMessage, systemInfo }: any) => {
|
|||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
content: (
|
content: <pre>{lastLog}</pre>,
|
||||||
<pre
|
|
||||||
style={{
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: 400,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{lastLog}
|
|
||||||
</pre>
|
|
||||||
),
|
|
||||||
okText: intl.get('下载更新'),
|
okText: intl.get('下载更新'),
|
||||||
cancelText: intl.get('以后再说'),
|
cancelText: intl.get('以后再说'),
|
||||||
onOk() {
|
onOk() {
|
||||||
@@ -109,16 +100,7 @@ const CheckUpdate = ({ socketMessage, systemInfo }: any) => {
|
|||||||
okButtonProps: { disabled: true },
|
okButtonProps: { disabled: true },
|
||||||
title: intl.get('下载更新中...'),
|
title: intl.get('下载更新中...'),
|
||||||
centered: true,
|
centered: true,
|
||||||
content: (
|
content: <pre>{value}</pre>,
|
||||||
<pre
|
|
||||||
style={{
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: 400,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{value}
|
|
||||||
</pre>
|
|
||||||
),
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -177,7 +159,7 @@ const CheckUpdate = ({ socketMessage, systemInfo }: any) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const newMessage = `${value}${_message}`;
|
const newMessage = `${value}${_message}`;
|
||||||
const updateFailed = newMessage.includes(intl.get('失败'));
|
const updateFailed = newMessage.includes('失败');
|
||||||
|
|
||||||
modalRef.current.update({
|
modalRef.current.update({
|
||||||
maskClosable: updateFailed,
|
maskClosable: updateFailed,
|
||||||
@@ -185,20 +167,13 @@ const CheckUpdate = ({ socketMessage, systemInfo }: any) => {
|
|||||||
okButtonProps: { disabled: !updateFailed },
|
okButtonProps: { disabled: !updateFailed },
|
||||||
content: (
|
content: (
|
||||||
<>
|
<>
|
||||||
<pre
|
<pre>{newMessage}</pre>
|
||||||
style={{
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: 400,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{newMessage}
|
|
||||||
</pre>
|
|
||||||
<div id="log-identifier" style={{ paddingBottom: 5 }}></div>
|
<div id="log-identifier" style={{ paddingBottom: 5 }}></div>
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (updateFailed && !value.includes(intl.get('失败,请检查'))) {
|
if (updateFailed && !value.includes('失败,请检查')) {
|
||||||
message.error(intl.get('更新失败,请检查网络及日志或稍后再试'));
|
message.error(intl.get('更新失败,请检查网络及日志或稍后再试'));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,7 +184,7 @@ const CheckUpdate = ({ socketMessage, systemInfo }: any) => {
|
|||||||
.getElementById('log-identifier')!
|
.getElementById('log-identifier')!
|
||||||
.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
||||||
|
|
||||||
if (_message.includes(intl.get('更新包下载成功'))) {
|
if (_message.includes('更新包下载成功')) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
showReloadModal();
|
showReloadModal();
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|||||||
+111
-61
@@ -1,5 +1,5 @@
|
|||||||
import intl from 'react-intl-universal';
|
import intl from 'react-intl-universal';
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect, useRef } from 'react';
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
InputNumber,
|
InputNumber,
|
||||||
@@ -32,6 +32,8 @@ import About from './about';
|
|||||||
import { useOutletContext } from '@umijs/max';
|
import { useOutletContext } from '@umijs/max';
|
||||||
import { SharedContext } from '@/layouts';
|
import { SharedContext } from '@/layouts';
|
||||||
import './index.less';
|
import './index.less';
|
||||||
|
import CodeMirror from '@uiw/react-codemirror';
|
||||||
|
import useResizeObserver from '@react-hook/resize-observer';
|
||||||
|
|
||||||
const { Text } = Typography;
|
const { Text } = Typography;
|
||||||
const isDemoEnv = window.__ENV__DeployEnv === 'demo';
|
const isDemoEnv = window.__ENV__DeployEnv === 'demo';
|
||||||
@@ -41,6 +43,7 @@ const Setting = () => {
|
|||||||
headerStyle,
|
headerStyle,
|
||||||
isPhone,
|
isPhone,
|
||||||
user,
|
user,
|
||||||
|
theme,
|
||||||
reloadUser,
|
reloadUser,
|
||||||
reloadTheme,
|
reloadTheme,
|
||||||
socketMessage,
|
socketMessage,
|
||||||
@@ -113,7 +116,17 @@ const Setting = () => {
|
|||||||
const [editedApp, setEditedApp] = useState<any>();
|
const [editedApp, setEditedApp] = useState<any>();
|
||||||
const [tabActiveKey, setTabActiveKey] = useState('security');
|
const [tabActiveKey, setTabActiveKey] = useState('security');
|
||||||
const [loginLogData, setLoginLogData] = useState<any[]>([]);
|
const [loginLogData, setLoginLogData] = useState<any[]>([]);
|
||||||
|
const [systemLogData, setSystemLogData] = useState<string>('');
|
||||||
const [notificationInfo, setNotificationInfo] = useState<any>();
|
const [notificationInfo, setNotificationInfo] = useState<any>();
|
||||||
|
const containergRef = useRef<HTMLDivElement>(null);
|
||||||
|
const [height, setHeight] = useState<number>(0);
|
||||||
|
|
||||||
|
useResizeObserver(containergRef, (entry) => {
|
||||||
|
const _height = entry.target.parentElement?.parentElement?.offsetHeight;
|
||||||
|
if (_height && height !== _height - 66) {
|
||||||
|
setHeight(_height - 66);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const getApps = () => {
|
const getApps = () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
@@ -232,6 +245,19 @@ const Setting = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getSystemLog = () => {
|
||||||
|
request
|
||||||
|
.get<Blob>(`${config.apiPrefix}system/log`, {
|
||||||
|
responseType: 'blob',
|
||||||
|
})
|
||||||
|
.then(async (res) => {
|
||||||
|
setSystemLogData(await res.text());
|
||||||
|
})
|
||||||
|
.catch((error: any) => {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const tabChange = (activeKey: string) => {
|
const tabChange = (activeKey: string) => {
|
||||||
setTabActiveKey(activeKey);
|
setTabActiveKey(activeKey);
|
||||||
if (activeKey === 'app') {
|
if (activeKey === 'app') {
|
||||||
@@ -240,6 +266,8 @@ const Setting = () => {
|
|||||||
getLoginLog();
|
getLoginLog();
|
||||||
} else if (activeKey === 'notification') {
|
} else if (activeKey === 'notification') {
|
||||||
getNotification();
|
getNotification();
|
||||||
|
} else if (activeKey === 'syslog') {
|
||||||
|
getSystemLog();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -279,66 +307,88 @@ const Setting = () => {
|
|||||||
: []
|
: []
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Tabs
|
<div ref={containergRef}>
|
||||||
defaultActiveKey="security"
|
<Tabs
|
||||||
size="small"
|
defaultActiveKey="security"
|
||||||
tabPosition="top"
|
size="small"
|
||||||
onChange={tabChange}
|
tabPosition="top"
|
||||||
items={[
|
onChange={tabChange}
|
||||||
...(!isDemoEnv
|
items={[
|
||||||
? [
|
...(!isDemoEnv
|
||||||
{
|
? [
|
||||||
key: 'security',
|
{
|
||||||
label: intl.get('安全设置'),
|
key: 'security',
|
||||||
children: (
|
label: intl.get('安全设置'),
|
||||||
<SecuritySettings user={user} userChange={reloadUser} />
|
children: (
|
||||||
),
|
<SecuritySettings user={user} userChange={reloadUser} />
|
||||||
},
|
),
|
||||||
]
|
},
|
||||||
: []),
|
]
|
||||||
{
|
: []),
|
||||||
key: 'app',
|
{
|
||||||
label: intl.get('应用设置'),
|
key: 'app',
|
||||||
children: (
|
label: intl.get('应用设置'),
|
||||||
<Table
|
children: (
|
||||||
columns={columns}
|
<Table
|
||||||
pagination={false}
|
columns={columns}
|
||||||
dataSource={dataSource}
|
pagination={false}
|
||||||
rowKey="id"
|
dataSource={dataSource}
|
||||||
size="middle"
|
rowKey="id"
|
||||||
scroll={{ x: 768 }}
|
size="middle"
|
||||||
loading={loading}
|
scroll={{ x: 768 }}
|
||||||
/>
|
loading={loading}
|
||||||
),
|
/>
|
||||||
},
|
),
|
||||||
{
|
},
|
||||||
key: 'notification',
|
{
|
||||||
label: intl.get('通知设置'),
|
key: 'notification',
|
||||||
children: <NotificationSetting data={notificationInfo} />,
|
label: intl.get('通知设置'),
|
||||||
},
|
children: <NotificationSetting data={notificationInfo} />,
|
||||||
{
|
},
|
||||||
key: 'login',
|
{
|
||||||
label: intl.get('登录日志'),
|
key: 'syslog',
|
||||||
children: <LoginLog data={loginLogData} />,
|
label: intl.get('系统日志'),
|
||||||
},
|
children: (
|
||||||
{
|
<CodeMirror
|
||||||
key: 'other',
|
maxHeight={`${height}px`}
|
||||||
label: intl.get('其他设置'),
|
value={systemLogData}
|
||||||
children: (
|
onCreateEditor={(view) => {
|
||||||
<Other
|
setTimeout(() => {
|
||||||
reloadTheme={reloadTheme}
|
view.scrollDOM.scrollTo({
|
||||||
socketMessage={socketMessage}
|
top: view.scrollDOM.scrollHeight,
|
||||||
systemInfo={systemInfo}
|
behavior: 'smooth',
|
||||||
/>
|
});
|
||||||
),
|
}, 300);
|
||||||
},
|
}}
|
||||||
{
|
readOnly={true}
|
||||||
key: 'about',
|
theme={theme.includes('dark') ? 'dark' : 'light'}
|
||||||
label: intl.get('关于'),
|
/>
|
||||||
children: <About systemInfo={systemInfo} />,
|
),
|
||||||
},
|
},
|
||||||
]}
|
{
|
||||||
></Tabs>
|
key: 'login',
|
||||||
|
label: intl.get('登录日志'),
|
||||||
|
children: <LoginLog data={loginLogData} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'other',
|
||||||
|
label: intl.get('其他设置'),
|
||||||
|
children: (
|
||||||
|
<Other
|
||||||
|
reloadTheme={reloadTheme}
|
||||||
|
socketMessage={socketMessage}
|
||||||
|
systemInfo={systemInfo}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'about',
|
||||||
|
label: intl.get('关于'),
|
||||||
|
children: <About systemInfo={systemInfo} />,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
></Tabs>
|
||||||
|
</div>
|
||||||
<AppModal
|
<AppModal
|
||||||
visible={isModalVisible}
|
visible={isModalVisible}
|
||||||
handleCancel={handleCancel}
|
handleCancel={handleCancel}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ enum LoginStatusColor {
|
|||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
title: intl.get('序号'),
|
title: intl.get('序号'),
|
||||||
width: 40,
|
width: 50,
|
||||||
render: (text: string, record: any, index: number) => {
|
render: (text: string, record: any, index: number) => {
|
||||||
return index + 1;
|
return index + 1;
|
||||||
},
|
},
|
||||||
@@ -75,7 +75,7 @@ const LoginLog = ({ data }: any) => {
|
|||||||
dataSource={data}
|
dataSource={data}
|
||||||
rowKey="id"
|
rowKey="id"
|
||||||
size="middle"
|
size="middle"
|
||||||
scroll={{ x: 768 }}
|
scroll={{ x: 1000 }}
|
||||||
sticky
|
sticky
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ const NotificationSetting = ({ data }: any) => {
|
|||||||
) : (
|
) : (
|
||||||
<Input.TextArea
|
<Input.TextArea
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
autoSize={true}
|
autoSize={{ minRows: 1, maxRows: 5 }}
|
||||||
placeholder={x.placeholder || `请输入${x.label}`}
|
placeholder={x.placeholder || `请输入${x.label}`}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
+48
-12
@@ -9,7 +9,7 @@ import {
|
|||||||
Input,
|
Input,
|
||||||
Upload,
|
Upload,
|
||||||
Modal,
|
Modal,
|
||||||
Progress,
|
Select,
|
||||||
} from 'antd';
|
} from 'antd';
|
||||||
import * as DarkReader from '@umijs/ssr-darkreader';
|
import * as DarkReader from '@umijs/ssr-darkreader';
|
||||||
import config from '@/utils/config';
|
import config from '@/utils/config';
|
||||||
@@ -22,12 +22,6 @@ import { UploadOutlined } from '@ant-design/icons';
|
|||||||
import Countdown from 'antd/lib/statistic/Countdown';
|
import Countdown from 'antd/lib/statistic/Countdown';
|
||||||
import useProgress from './progress';
|
import useProgress from './progress';
|
||||||
|
|
||||||
const optionsWithDisabled = [
|
|
||||||
{ label: intl.get('亮色'), value: 'light' },
|
|
||||||
{ label: intl.get('暗色'), value: 'dark' },
|
|
||||||
{ label: intl.get('跟随系统'), value: 'auto' },
|
|
||||||
];
|
|
||||||
|
|
||||||
const Other = ({
|
const Other = ({
|
||||||
systemInfo,
|
systemInfo,
|
||||||
socketMessage,
|
socketMessage,
|
||||||
@@ -67,6 +61,13 @@ const Other = ({
|
|||||||
reloadTheme();
|
reloadTheme();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleLangChange = (v: string) => {
|
||||||
|
localStorage.setItem('lang', v);
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.reload();
|
||||||
|
}, 500);
|
||||||
|
};
|
||||||
|
|
||||||
const getSystemConfig = () => {
|
const getSystemConfig = () => {
|
||||||
request
|
request
|
||||||
.get(`${config.apiPrefix}system/config`)
|
.get(`${config.apiPrefix}system/config`)
|
||||||
@@ -167,12 +168,27 @@ const Other = ({
|
|||||||
initialValue={defaultTheme}
|
initialValue={defaultTheme}
|
||||||
>
|
>
|
||||||
<Radio.Group
|
<Radio.Group
|
||||||
options={optionsWithDisabled}
|
|
||||||
onChange={themeChange}
|
onChange={themeChange}
|
||||||
value={defaultTheme}
|
value={defaultTheme}
|
||||||
optionType="button"
|
optionType="button"
|
||||||
buttonStyle="solid"
|
buttonStyle="solid"
|
||||||
/>
|
>
|
||||||
|
<Radio.Button
|
||||||
|
value="light"
|
||||||
|
style={{ width: 70, textAlign: 'center' }}
|
||||||
|
>
|
||||||
|
{intl.get('亮色')}
|
||||||
|
</Radio.Button>
|
||||||
|
<Radio.Button value="dark" style={{ width: 66, textAlign: 'center' }}>
|
||||||
|
{intl.get('暗色')}
|
||||||
|
</Radio.Button>
|
||||||
|
<Radio.Button
|
||||||
|
value="auto"
|
||||||
|
style={{ width: 129, textAlign: 'center' }}
|
||||||
|
>
|
||||||
|
{intl.get('跟随系统')}
|
||||||
|
</Radio.Button>
|
||||||
|
</Radio.Group>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={intl.get('日志删除频率')}
|
label={intl.get('日志删除频率')}
|
||||||
@@ -190,7 +206,11 @@ const Other = ({
|
|||||||
setSystemConfig({ ...systemConfig, logRemoveFrequency: value });
|
setSystemConfig({ ...systemConfig, logRemoveFrequency: value });
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Button type="primary" onClick={updateSystemConfig}>
|
<Button
|
||||||
|
type="primary"
|
||||||
|
onClick={updateSystemConfig}
|
||||||
|
style={{ width: 84 }}
|
||||||
|
>
|
||||||
{intl.get('确认')}
|
{intl.get('确认')}
|
||||||
</Button>
|
</Button>
|
||||||
</Input.Group>
|
</Input.Group>
|
||||||
@@ -198,18 +218,34 @@ const Other = ({
|
|||||||
<Form.Item label={intl.get('定时任务并发数')} name="frequency">
|
<Form.Item label={intl.get('定时任务并发数')} name="frequency">
|
||||||
<Input.Group compact>
|
<Input.Group compact>
|
||||||
<InputNumber
|
<InputNumber
|
||||||
style={{ width: 150 }}
|
style={{ width: 180 }}
|
||||||
min={1}
|
min={1}
|
||||||
value={systemConfig?.cronConcurrency}
|
value={systemConfig?.cronConcurrency}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
setSystemConfig({ ...systemConfig, cronConcurrency: value });
|
setSystemConfig({ ...systemConfig, cronConcurrency: value });
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Button type="primary" onClick={updateSystemConfig}>
|
<Button
|
||||||
|
type="primary"
|
||||||
|
onClick={updateSystemConfig}
|
||||||
|
style={{ width: 84 }}
|
||||||
|
>
|
||||||
{intl.get('确认')}
|
{intl.get('确认')}
|
||||||
</Button>
|
</Button>
|
||||||
</Input.Group>
|
</Input.Group>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item label={intl.get('语言')} name="lang">
|
||||||
|
<Select
|
||||||
|
defaultValue={localStorage.getItem('lang') || ''}
|
||||||
|
style={{ width: 264 }}
|
||||||
|
onChange={handleLangChange}
|
||||||
|
options={[
|
||||||
|
{ value: '', label: intl.get('跟随系统') },
|
||||||
|
{ value: 'zh', label: '简体中文' },
|
||||||
|
{ value: 'en', label: 'English' },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
<Form.Item label={intl.get('数据备份还原')} name="frequency">
|
<Form.Item label={intl.get('数据备份还原')} name="frequency">
|
||||||
<Button type="primary" onClick={exportData} loading={exportLoading}>
|
<Button type="primary" onClick={exportData} loading={exportLoading}>
|
||||||
{exportLoading ? intl.get('生成数据中...') : intl.get('备份')}
|
{exportLoading ? intl.get('生成数据中...') : intl.get('备份')}
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ const SecuritySettings = ({ user, userChange }: any) => {
|
|||||||
hasFeedback
|
hasFeedback
|
||||||
style={{ maxWidth: 300 }}
|
style={{ maxWidth: 300 }}
|
||||||
>
|
>
|
||||||
<Input placeholder={intl.get('用户名')} />
|
<Input autoComplete="username" placeholder={intl.get('用户名')} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={intl.get('密码')}
|
label={intl.get('密码')}
|
||||||
@@ -203,7 +203,11 @@ const SecuritySettings = ({ user, userChange }: any) => {
|
|||||||
hasFeedback
|
hasFeedback
|
||||||
style={{ maxWidth: 300 }}
|
style={{ maxWidth: 300 }}
|
||||||
>
|
>
|
||||||
<Input type="password" placeholder={intl.get('密码')} />
|
<Input
|
||||||
|
type="password"
|
||||||
|
autoComplete="current-password"
|
||||||
|
placeholder={intl.get('密码')}
|
||||||
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Button type="primary" htmlType="submit">
|
<Button type="primary" htmlType="submit">
|
||||||
{intl.get('保存')}
|
{intl.get('保存')}
|
||||||
|
|||||||
@@ -184,45 +184,39 @@ const Subscription = () => {
|
|||||||
{
|
{
|
||||||
title: intl.get('操作'),
|
title: intl.get('操作'),
|
||||||
key: 'action',
|
key: 'action',
|
||||||
width: 130,
|
width: 140,
|
||||||
render: (text: string, record: any, index: number) => {
|
render: (text: string, record: any, index: number) => {
|
||||||
const isPc = !isPhone;
|
const isPc = !isPhone;
|
||||||
return (
|
return (
|
||||||
<Space size="middle">
|
<Space size="middle">
|
||||||
{record.status === SubscriptionStatus.idle && (
|
{record.status === SubscriptionStatus.idle && (
|
||||||
<Tooltip title={isPc ? intl.get('运行') : ''}>
|
|
||||||
<a
|
|
||||||
onClick={(e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
runSubscription(record, index);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<PlayCircleOutlined />
|
|
||||||
</a>
|
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
{record.status !== SubscriptionStatus.idle && (
|
|
||||||
<Tooltip title={isPc ? intl.get('停止') : ''}>
|
|
||||||
<a
|
|
||||||
onClick={(e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
stopSubsciption(record, index);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<PauseCircleOutlined />
|
|
||||||
</a>
|
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
<Tooltip title={isPc ? intl.get('日志') : ''}>
|
|
||||||
<a
|
<a
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
setLogSubscription({ ...record, timestamp: Date.now() });
|
runSubscription(record, index);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<FileTextOutlined />
|
{intl.get('运行')}
|
||||||
</a>
|
</a>
|
||||||
</Tooltip>
|
)}
|
||||||
|
{record.status !== SubscriptionStatus.idle && (
|
||||||
|
<a
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
stopSubsciption(record, index);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{intl.get('停止')}
|
||||||
|
</a>
|
||||||
|
)}
|
||||||
|
<a
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
setLogSubscription({ ...record, timestamp: Date.now() });
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{intl.get('日志')}
|
||||||
|
</a>
|
||||||
<MoreBtn key="more" record={record} index={index} />
|
<MoreBtn key="more" record={record} index={index} />
|
||||||
</Space>
|
</Space>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -99,9 +99,6 @@ const SubscriptionLogModal = ({
|
|||||||
open={visible}
|
open={visible}
|
||||||
centered
|
centered
|
||||||
className="log-modal"
|
className="log-modal"
|
||||||
bodyStyle={{
|
|
||||||
minHeight: '300px',
|
|
||||||
}}
|
|
||||||
forceRender
|
forceRender
|
||||||
onOk={() => cancel()}
|
onOk={() => cancel()}
|
||||||
onCancel={() => cancel()}
|
onCancel={() => cancel()}
|
||||||
@@ -111,23 +108,24 @@ const SubscriptionLogModal = ({
|
|||||||
</Button>,
|
</Button>,
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
{loading ? (
|
<div className="log-container">
|
||||||
<PageLoading />
|
{loading ? (
|
||||||
) : (
|
<PageLoading />
|
||||||
<pre
|
) : (
|
||||||
style={
|
<pre
|
||||||
isPhone
|
style={
|
||||||
? {
|
isPhone
|
||||||
fontFamily: 'Source Code Pro',
|
? {
|
||||||
width: 375,
|
fontFamily: 'Source Code Pro',
|
||||||
zoom: 0.83,
|
zoom: 0.83,
|
||||||
}
|
}
|
||||||
: {}
|
: {}
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{value}
|
{value}
|
||||||
</pre>
|
</pre>
|
||||||
)}
|
)}
|
||||||
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -241,10 +241,9 @@ const SubscriptionModal = ({
|
|||||||
|
|
||||||
const onNamePaste = useCallback((e) => {
|
const onNamePaste = useCallback((e) => {
|
||||||
const text = e.clipboardData.getData('text') as string;
|
const text = e.clipboardData.getData('text') as string;
|
||||||
if (text.startsWith('ql ')) {
|
if (text.includes('ql repo') || text.includes('ql raw')) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
onPaste(e);
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const formatParams = (sub) => {
|
const formatParams = (sub) => {
|
||||||
@@ -327,10 +326,9 @@ const SubscriptionModal = ({
|
|||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Input.TextArea
|
<Input.TextArea
|
||||||
rows={4}
|
autoSize={{ minRows: 1, maxRows: 5 }}
|
||||||
autoSize={true}
|
|
||||||
placeholder={intl.get('请输入订阅链接')}
|
placeholder={intl.get('请输入订阅链接')}
|
||||||
onPaste={onUrlChange}
|
onPaste={onNamePaste}
|
||||||
onChange={onUrlChange}
|
onChange={onUrlChange}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
@@ -338,7 +336,7 @@ const SubscriptionModal = ({
|
|||||||
<Form.Item name="branch" label={intl.get('分支')}>
|
<Form.Item name="branch" label={intl.get('分支')}>
|
||||||
<Input
|
<Input
|
||||||
placeholder={intl.get('请输入分支')}
|
placeholder={intl.get('请输入分支')}
|
||||||
onPaste={onBranchChange}
|
onPaste={onNamePaste}
|
||||||
onChange={onBranchChange}
|
onChange={onBranchChange}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
@@ -401,7 +399,10 @@ const SubscriptionModal = ({
|
|||||||
{scheduleType === 'interval' ? (
|
{scheduleType === 'interval' ? (
|
||||||
<IntervalSelect />
|
<IntervalSelect />
|
||||||
) : (
|
) : (
|
||||||
<Input placeholder={intl.get('秒(可选) 分 时 天 月 周')} />
|
<Input
|
||||||
|
onPaste={onNamePaste}
|
||||||
|
placeholder={intl.get('秒(可选) 分 时 天 月 周')}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
{type !== 'file' && (
|
{type !== 'file' && (
|
||||||
@@ -413,10 +414,11 @@ const SubscriptionModal = ({
|
|||||||
>
|
>
|
||||||
<Input.TextArea
|
<Input.TextArea
|
||||||
rows={4}
|
rows={4}
|
||||||
autoSize={true}
|
autoSize={{ minRows: 1, maxRows: 5 }}
|
||||||
placeholder={intl.get(
|
placeholder={intl.get(
|
||||||
'请输入脚本筛选白名单关键词,多个关键词竖线分割',
|
'请输入脚本筛选白名单关键词,多个关键词竖线分割',
|
||||||
)}
|
)}
|
||||||
|
onPaste={onNamePaste}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
@@ -426,10 +428,11 @@ const SubscriptionModal = ({
|
|||||||
>
|
>
|
||||||
<Input.TextArea
|
<Input.TextArea
|
||||||
rows={4}
|
rows={4}
|
||||||
autoSize={true}
|
autoSize={{ minRows: 1, maxRows: 5 }}
|
||||||
placeholder={intl.get(
|
placeholder={intl.get(
|
||||||
'请输入脚本筛选黑名单关键词,多个关键词竖线分割',
|
'请输入脚本筛选黑名单关键词,多个关键词竖线分割',
|
||||||
)}
|
)}
|
||||||
|
onPaste={onNamePaste}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
@@ -439,10 +442,11 @@ const SubscriptionModal = ({
|
|||||||
>
|
>
|
||||||
<Input.TextArea
|
<Input.TextArea
|
||||||
rows={4}
|
rows={4}
|
||||||
autoSize={true}
|
autoSize={{ minRows: 1, maxRows: 5 }}
|
||||||
placeholder={intl.get(
|
placeholder={intl.get(
|
||||||
'请输入脚本依赖文件关键词,多个关键词竖线分割',
|
'请输入脚本依赖文件关键词,多个关键词竖线分割',
|
||||||
)}
|
)}
|
||||||
|
onPaste={onNamePaste}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
@@ -452,7 +456,10 @@ const SubscriptionModal = ({
|
|||||||
'仓库需要拉取的文件后缀,多个后缀空格分隔,默认使用配置文件中的RepoFileExtensions',
|
'仓库需要拉取的文件后缀,多个后缀空格分隔,默认使用配置文件中的RepoFileExtensions',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Input placeholder={intl.get('请输入文件后缀')} />
|
<Input
|
||||||
|
onPaste={onNamePaste}
|
||||||
|
placeholder={intl.get('请输入文件后缀')}
|
||||||
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="sub_before"
|
name="sub_before"
|
||||||
@@ -462,8 +469,9 @@ const SubscriptionModal = ({
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Input.TextArea
|
<Input.TextArea
|
||||||
|
onPaste={onNamePaste}
|
||||||
rows={4}
|
rows={4}
|
||||||
autoSize={true}
|
autoSize={{ minRows: 1, maxRows: 5 }}
|
||||||
placeholder={intl.get('请输入运行订阅前要执行的命令')}
|
placeholder={intl.get('请输入运行订阅前要执行的命令')}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
@@ -475,8 +483,9 @@ const SubscriptionModal = ({
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Input.TextArea
|
<Input.TextArea
|
||||||
|
onPaste={onNamePaste}
|
||||||
rows={4}
|
rows={4}
|
||||||
autoSize={true}
|
autoSize={{ minRows: 1, maxRows: 5 }}
|
||||||
placeholder={intl.get('请输入运行订阅后要执行的命令')}
|
placeholder={intl.get('请输入运行订阅后要执行的命令')}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
@@ -490,6 +499,7 @@ const SubscriptionModal = ({
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Input
|
<Input
|
||||||
|
onPaste={onNamePaste}
|
||||||
placeholder={
|
placeholder={
|
||||||
type === 'private-repo'
|
type === 'private-repo'
|
||||||
? 'SOCK5代理,例如 IP:PORT'
|
? 'SOCK5代理,例如 IP:PORT'
|
||||||
|
|||||||
+1
-1
@@ -174,7 +174,7 @@ export default {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'barkGroup',
|
label: 'barkGroup',
|
||||||
tip: intl.get('BARK推送消息的分组, 默认为qinglong'),
|
tip: intl.get('BARK推送消息的分组,默认为qinglong'),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
telegramBot: [
|
telegramBot: [
|
||||||
|
|||||||
+12
-11
@@ -1,12 +1,13 @@
|
|||||||
version: 2.16.0
|
version: 2.16.2
|
||||||
changeLogLink: https://t.me/jiao_long/388
|
changeLogLink: https://t.me/jiao_long/393
|
||||||
publishTime: 2023-08-06 16:00
|
publishTime: 2023-09-02 07:00
|
||||||
changeLog: |
|
changeLog: |
|
||||||
1. 多语言支持英文界面
|
1. 系统设置增加语言设置
|
||||||
2. 定时任务增加关联订阅
|
2. 修复环境变量有空格时并发数量错误
|
||||||
3. 删除订阅支持自动删除任务和脚本
|
3. 修复环境变量特殊字符转义
|
||||||
4. 定时任务支持运行 mjs 后缀文件
|
4. 修复仓库订阅 ssh 配置
|
||||||
5. PushMe消息通道增加 params 参数
|
5. 修复停止订阅执行日志
|
||||||
6. 修复 6 位 cron 不以 task 开头定时任务运行失败
|
6. 修改定时任务置顶样式
|
||||||
7. 修复任务详情日志列表过多卡顿
|
7. 修改任务日志样式
|
||||||
8. 修复定时任务列表虚拟滚动
|
8. 修复环境变量值 tip 样式
|
||||||
|
9. 其他 bug 修复
|
||||||
|
|||||||
Reference in New Issue
Block a user