From 946731ac8d4fe5bdbfb2f4df030288cf852ea02d Mon Sep 17 00:00:00 2001 From: whyour Date: Wed, 10 Jun 2026 01:53:10 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=BF=90=E8=A1=8C=E5=AE=9E?= =?UTF-8?q?=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/api/cron.ts | 47 ++ back/api/dashboard.ts | 42 +- back/data/runningInstance.ts | 81 +++ back/loaders/db.ts | 2 + back/loaders/initData.ts | 7 + back/services/cron.ts | 105 +++- back/shared/runCron.ts | 11 + src/locales/en-US.json | 1114 +++++++++++++++++---------------- src/locales/zh-CN.json | 1114 +++++++++++++++++---------------- src/pages/crontab/detail.tsx | 200 ++++-- src/pages/crontab/index.tsx | 30 +- src/pages/dashboard/index.tsx | 9 +- 12 files changed, 1594 insertions(+), 1168 deletions(-) create mode 100644 back/data/runningInstance.ts diff --git a/back/api/cron.ts b/back/api/cron.ts index 1bc99062..2c1b6609 100644 --- a/back/api/cron.ts +++ b/back/api/cron.ts @@ -5,6 +5,10 @@ import CronService from '../services/cron'; import CronViewService from '../services/cronView'; import { celebrate, Joi } from 'celebrate'; import { commonCronSchema } from '../validation/schedule'; +import { + RunningInstanceModel, + InstanceStatus, +} from '../data/runningInstance'; const route = Router(); @@ -446,6 +450,49 @@ export default (app: Router) => { }, ); + route.get( + '/:id/instances', + celebrate({ + params: Joi.object({ + id: Joi.number().required(), + }), + }), + async (req: Request<{ id: number }>, res: Response, next: NextFunction) => { + try { + const instances = await RunningInstanceModel.findAll({ + where: { + cron_id: req.params.id, + status: InstanceStatus.running, + }, + order: [['started_at', 'DESC']], + raw: true, + }); + return res.send({ code: 200, data: instances }); + } catch (e) { + return next(e); + } + }, + ); + + route.post( + '/:id/instances/:instanceId/stop', + celebrate({ + params: Joi.object({ + id: Joi.number().required(), + instanceId: Joi.number().required(), + }), + }), + async (req: Request<{ id: number; instanceId: number }>, res: Response, next: NextFunction) => { + try { + const cronService = Container.get(CronService); + const data = await cronService.stopInstance(req.params.instanceId); + return res.send(data); + } catch (e) { + return next(e); + } + }, + ); + route.get( '/:id/logs', celebrate({ diff --git a/back/api/dashboard.ts b/back/api/dashboard.ts index 2e23daa5..799503aa 100644 --- a/back/api/dashboard.ts +++ b/back/api/dashboard.ts @@ -3,6 +3,10 @@ import { Container } from 'typedi'; import { fn, col, where, Op } from 'sequelize'; import { CrontabModel } from '../data/cron'; import { CrontabStatModel } from '../data/cronStats'; +import { + RunningInstanceModel, + InstanceStatus, +} from '../data/runningInstance'; import dayjs from 'dayjs'; import os from 'os'; @@ -239,9 +243,9 @@ export default (app: Router) => { '/runtime', async (req: Request, res: Response, next: NextFunction) => { try { - const runningCrons = await CrontabModel.findAll({ + const runningInstances = await RunningInstanceModel.findAll({ where: { - status: 0, // running + status: InstanceStatus.running, }, raw: true, }); @@ -253,15 +257,31 @@ export default (app: Router) => { raw: true, }); - const running = runningCrons.map((c: any) => ({ - id: c.id, - name: c.name || c.command || `任务#${c.id}`, - pid: c.pid, - elapsed: c.last_execution_time - ? Math.floor((Date.now() / 1000) - c.last_execution_time) - : 0, - logPath: c.log_path, - })); + // Fetch cron names for running instances + const cronIds = [ + ...new Set(runningInstances.map((i: any) => i.cron_id)), + ]; + const crons = + cronIds.length > 0 + ? await CrontabModel.findAll({ + where: { id: cronIds }, + raw: true, + }) + : []; + const cronMap = new Map(crons.map((c: any) => [c.id, c])); + + const now = dayjs().unix(); + const running = runningInstances.map((inst: any) => { + const cron = cronMap.get(inst.cron_id); + return { + instanceId: inst.id, + id: inst.cron_id, + name: cron?.name || cron?.command || `任务#${inst.cron_id}`, + pid: inst.pid, + elapsed: inst.started_at ? now - inst.started_at : 0, + logPath: inst.log_path, + }; + }); const dayAgo = dayjs().subtract(24, 'hour').unix(); const idleTasks = await CrontabModel.findAll({ diff --git a/back/data/runningInstance.ts b/back/data/runningInstance.ts new file mode 100644 index 00000000..5d8b3be4 --- /dev/null +++ b/back/data/runningInstance.ts @@ -0,0 +1,81 @@ +import { sequelize } from '.'; +import { DataTypes, Model } from 'sequelize'; + +export enum InstanceStatus { + 'running' = 0, + 'finished' = 1, + 'stopped' = 2, + 'error' = 3, +} + +export interface RunningInstanceAttributes { + id?: number; + cron_id: number; + pid?: number; + log_path?: string; + started_at: number; + finished_at?: number; + status: InstanceStatus; + exit_code?: number; +} + +export class RunningInstance { + id?: number; + cron_id!: number; + pid?: number; + log_path?: string; + started_at!: number; + finished_at?: number; + status!: InstanceStatus; + exit_code?: number; + + constructor(options: RunningInstanceAttributes) { + this.id = options.id; + this.cron_id = options.cron_id; + this.pid = options.pid; + this.log_path = options.log_path; + this.started_at = options.started_at; + this.finished_at = options.finished_at; + this.status = options.status; + this.exit_code = options.exit_code; + } +} + +export interface RunningInstanceModel + extends Model, + RunningInstanceAttributes {} + +export const RunningInstanceModel = sequelize.define( + 'RunningInstance', + { + cron_id: { + type: DataTypes.NUMBER, + allowNull: false, + }, + pid: { + type: DataTypes.NUMBER, + allowNull: true, + }, + log_path: { + type: DataTypes.STRING, + allowNull: true, + }, + started_at: { + type: DataTypes.NUMBER, + allowNull: false, + }, + finished_at: { + type: DataTypes.NUMBER, + allowNull: true, + }, + status: { + type: DataTypes.NUMBER, + allowNull: false, + defaultValue: InstanceStatus.running, + }, + exit_code: { + type: DataTypes.NUMBER, + allowNull: true, + }, + }, +); diff --git a/back/loaders/db.ts b/back/loaders/db.ts index 389c2c1e..a8769d38 100644 --- a/back/loaders/db.ts +++ b/back/loaders/db.ts @@ -7,6 +7,7 @@ import { SystemModel } from '../data/system'; import { SubscriptionModel } from '../data/subscription'; import { CrontabViewModel } from '../data/cronView'; import { CrontabStatModel } from '../data/cronStats'; +import { RunningInstanceModel } from '../data/runningInstance'; import { sequelize } from '../data'; export default async () => { @@ -19,6 +20,7 @@ export default async () => { await SubscriptionModel.sync(); await CrontabViewModel.sync(); await CrontabStatModel.sync(); + await RunningInstanceModel.sync(); // 初始化新增字段 const migrations = [ diff --git a/back/loaders/initData.ts b/back/loaders/initData.ts index 264d7e05..f8dc7758 100644 --- a/back/loaders/initData.ts +++ b/back/loaders/initData.ts @@ -18,6 +18,7 @@ import OpenService from '../services/open'; import { shareStore } from '../shared/store'; import Logger from './logger'; import { AppModel } from '../data/open'; +import { InstanceStatus, RunningInstanceModel } from '../data/runningInstance'; export default async () => { const cronService = Container.get(CronService); @@ -139,6 +140,12 @@ export default async () => { // 初始化更新所有任务状态为空闲 await CrontabModel.update({ status: CrontabStatus.idle }, { where: {} }); + // 清空所有运行中的实例记录(服务重启后进程已不存在) + await RunningInstanceModel.update( + { status: InstanceStatus.stopped }, + { where: { status: InstanceStatus.running } }, + ); + // 初始化时执行一次所有的 ql repo 任务 CrontabModel.findAll({ where: { diff --git a/back/services/cron.ts b/back/services/cron.ts index 798ef37a..f2a80276 100644 --- a/back/services/cron.ts +++ b/back/services/cron.ts @@ -2,6 +2,10 @@ import { Service, Inject } from 'typedi'; import winston from 'winston'; import config from '../config'; import { Crontab, CrontabModel, CrontabStatus } from '../data/cron'; +import { + RunningInstanceModel, + InstanceStatus, +} from '../data/runningInstance'; import { exec, execSync } from 'child_process'; import fs from 'fs/promises'; import CronExpressionParser from 'cron-parser'; @@ -189,6 +193,35 @@ export default class CronService { if (status === CrontabStatus.idle && log_path !== cron.log_path) { options = omit(options, ['status', 'log_path', 'pid']); } + + // Manage RunningInstance records for status transitions from shell scripts + if (status === CrontabStatus.running) { + // Create a new running instance record + await RunningInstanceModel.create({ + cron_id: id, + pid: pid || undefined, + log_path: log_path || undefined, + started_at: last_execution_time || dayjs().unix(), + status: InstanceStatus.running, + }); + } else if (status === CrontabStatus.idle) { + // Mark the matching running instance as finished + const finishedAt = dayjs().unix(); + await RunningInstanceModel.update( + { + finished_at: finishedAt, + status: InstanceStatus.finished, + }, + { + where: { + cron_id: id, + pid: pid || undefined, + status: InstanceStatus.running, + }, + }, + ); + } + await CrontabModel.update( { ...pickBy(options, (v) => v === 0 || !!v) }, { where: { id } }, @@ -499,12 +532,53 @@ export default class CronService { } } + // Mark all running instances as stopped + const finishedAt = dayjs().unix(); + await RunningInstanceModel.update( + { status: InstanceStatus.stopped, finished_at: finishedAt }, + { where: { cron_id: ids, status: InstanceStatus.running } }, + ); + await CrontabModel.update( { status: CrontabStatus.idle, pid: undefined }, { where: { id: ids } }, ); } + public async stopInstance(instanceId: number) { + const instance = await RunningInstanceModel.findOne({ + where: { id: instanceId, status: InstanceStatus.running }, + }); + if (!instance) { + return { code: 400, message: '实例不存在或已停止' }; + } + if (instance.pid) { + try { + await killTask(instance.pid); + } catch (error) { + this.logger.error( + `[panel][停止实例失败] 实例ID: ${instanceId}, PID: ${instance.pid}, 错误: ${error}`, + ); + } + } + await RunningInstanceModel.update( + { status: InstanceStatus.stopped, finished_at: dayjs().unix() }, + { where: { id: instanceId } }, + ); + + // Check if there are still other running instances for this cron + const otherRunning = await RunningInstanceModel.count({ + where: { cron_id: instance.cron_id, status: InstanceStatus.running }, + }); + if (otherRunning === 0) { + await CrontabModel.update( + { status: CrontabStatus.idle, pid: undefined }, + { where: { id: instance.cron_id } }, + ); + } + return { code: 200, message: '实例已停止' }; + } + private async runSingle(cronId: number): Promise { return taskLimit.manualRunWithCronLimit(() => { return new Promise(async (resolve: any) => { @@ -543,6 +617,15 @@ export default class CronService { { shell: '/bin/bash' }, ); + const startedAt = dayjs().unix(); + const instance = await RunningInstanceModel.create({ + cron_id: id!, + pid: cp.pid, + log_path: logPath, + started_at: startedAt, + status: InstanceStatus.running, + }); + await CrontabModel.update( { status: CrontabStatus.running, pid: cp.pid, log_path: logPath }, { where: { id } }, @@ -574,10 +657,26 @@ export default class CronService { code, ); await logStreamManager.closeStream(absolutePath); - await CrontabModel.update( - { status: CrontabStatus.idle, pid: undefined }, - { where: { id } }, + const finishedAt = dayjs().unix(); + await RunningInstanceModel.update( + { + finished_at: finishedAt, + status: code === 0 ? InstanceStatus.finished : InstanceStatus.error, + exit_code: code ?? undefined, + }, + { where: { id: instance.id } }, ); + + // Only set cron to idle if no other running instances exist + const otherRunning = await RunningInstanceModel.count({ + where: { cron_id: id!, status: InstanceStatus.running }, + }); + if (otherRunning === 0) { + await CrontabModel.update( + { status: CrontabStatus.idle, pid: undefined }, + { where: { id } }, + ); + } resolve({ ...params, pid: cp.pid, code }); }); }); diff --git a/back/shared/runCron.ts b/back/shared/runCron.ts index 9ccfdb05..c451bf4f 100644 --- a/back/shared/runCron.ts +++ b/back/shared/runCron.ts @@ -4,6 +4,11 @@ import Logger from '../loaders/logger'; import { ICron } from '../protos/cron'; import { CrontabModel, CrontabStatus } from '../data/cron'; import { killTask } from '../config/util'; +import { + RunningInstanceModel, + InstanceStatus, +} from '../data/runningInstance'; +import dayjs from 'dayjs'; export function runCron(cmd: string, cron: ICron): Promise { return taskLimit.runWithCronLimit(cron, () => { @@ -29,6 +34,12 @@ export function runCron(cmd: string, cron: ICron): Promise { `[schedule][停止已运行任务] 任务ID: ${cron.id}, PID: ${existingCron.pid}`, ); await killTask(existingCron.pid); + // Mark old running instances as stopped + const stoppedAt = dayjs().unix(); + await RunningInstanceModel.update( + { status: InstanceStatus.stopped, finished_at: stoppedAt }, + { where: { cron_id: Number(cron.id), status: InstanceStatus.running } }, + ); // Update the status to idle after killing await CrontabModel.update( { status: CrontabStatus.idle, pid: undefined }, diff --git a/src/locales/en-US.json b/src/locales/en-US.json index d727cab8..762342a8 100644 --- a/src/locales/en-US.json +++ b/src/locales/en-US.json @@ -1,592 +1,598 @@ { - "复制成功": "Copy successful", - "复制": "Copy", - "新建": "New", - "登录": "Login", - "初始化": "Initialize", - "错误": "Error", - "定时任务": "Scheduled Tasks", - "订阅管理": "Subscription Management", - "环境变量": "Environment Variables", - "配置文件": "Configuration Files", - "脚本管理": "Script Management", - "依赖管理": "Dependency Management", - "日志管理": "Log Management", - "对比工具": "Comparison Tool", - "系统设置": "System Settings", - "退出登录": "Logout", - "青龙": "Qinglong", - "返回首页": "Return to Home", - "保存": "Save", - "日志": "Log", - "脚本": "Script", - "确认保存文件": "Confirm to Save File", - ",保存后不可恢复": ", it can't be recovered after saving.", - "确认运行": "Confirm to Run", - "确认运行定时任务": "Confirm to Run Scheduled Task", - "吗": "?", - "确认停止": "Confirm to Stop", - "确认停止定时任务": "Confirm to Stop Scheduled Task", - "确认": "Confirm", - "任务": "Task", - "状态": "Status", - "空闲中": "Idle", - "运行中": "Running", - "队列中": "In Queue", - "已禁用": "Disabled", - "定时": "Schedule", - "最后运行时间": "Last Run Time", - "最后运行时长": "Last Run Duration", - "下次运行时间": "Next Run Time", - "名称": "Name", - "命令/脚本": "Command/Script", - "定时规则": "Schedule Rule", - "操作": "Action", - "确认删除": "Confirm to Delete", - "确认删除定时任务": "Confirm to Delete Scheduled Task", - "编辑": "Edit", - "删除": "Delete", - "确认删除选中的定时任务吗": "Confirm to delete the selected scheduled tasks?", - "选中的定时任务吗": "selected scheduled tasks?", - "创建视图": "Create View", - "视图管理": "View Management", - "请输入名称或者关键词": "Please enter a name or keyword", - "创建任务": "Create Task", - "更多": "More", - "批量删除": "Batch Delete", - "批量启用": "Batch Enable", - "批量禁用": "Batch Disable", - "批量运行": "Batch Run", - "批量停止": "Batch Stop", - "批量置顶": "Batch Top", - "批量取消置顶": "Batch Un-top", - "批量修改标签": "Batch Modify Tags", - "已选择": "Selected", - "项": "items", - "知道了": "Got it", - "请输入任务名称": "Please enter the task name", - "支持输入脚本路径/任意系统可执行命令/task 脚本路径": "Supports input of script paths / any system executable commands / task script paths", - "秒(可选) 分 时 天 月 周": "Seconds (optional) Minutes Hours Day Month Week", - "标签": "Tags", - "取消": "Cancel", - "添加": "Add", - "启用": "Enable", - "禁用": "Disable", - "运行": "Run", - "停止": "Stop", - "置顶": "Top", - "取消置顶": "Un-top", - "命令": "Command", - "包含": "Include", - "不包含": "Exclude", - "属于": "Belong to", - "不属于": "Not Belong to", - "顺序": "Order", - "倒序": "Reverse", - "且": "And", - "或": "Or", - "输入后回车增加自定义选项": "Press Enter to add custom options", - "视图名称": "View Name", - "请输入视图名称": "Please enter the view name", - "请输入内容": "Please enter the content", - "新增筛选条件": "Add Filter", - "新增排序方式": "Add Sort", - "类型": "Type", - "显示": "Display", - "确认删除视图": "Confirm to delete the view", - "安装中": "Installing", - "已安装": "Installed", - "安装失败": "Installation Failed", - "删除中": "Deleting", - "已删除": "Deleted", - "删除失败": "Deletion Failed", - "已取消": "Cancelled", - "序号": "Number", - "备注": "Remarks", - "更新时间": "Update Time", - "创建时间": "Created Time", - "确认删除依赖": "Confirm to delete the dependency", - "确认重新安装": "Confirm to reinstall", - "确认取消安装": "Confirm to cancel install", - "确认删除选中的依赖吗": "Confirm to delete the selected dependencies?", - "确认重新安装选中的依赖吗": "Confirm to reinstall the selected dependencies?", - "请输入名称": "Please enter a name", - "创建依赖": "Create Dependency", - "批量安装": "Batch Install", - "批量强制删除": "Batch Force Delete", - "日志 -": "Log -", - "依赖类型": "Dependency Type", - "自动拆分": "Auto Split", - "多个依赖是否换行分割": "Whether to separate multiple dependencies with new lines", - "是": "Yes", - "否": "No", - "请输入依赖名称,支持指定版本": "Please enter the dependency name, version specification is supported", - "请输入依赖名称": "Please enter the dependency name", - "请输入备注": "Please enter remarks", - "源文件": "Source File", - "当前文件": "Current File", - "修改环境变量名称": "Modify Environment Variable Name", - "请输入新的环境变量名称": "Please enter the new environment variable name", - "已启用": "Enabled", - "值": "Value", - "确认删除变量": "Confirm to delete the variable", - "确认删除选中的变量吗": "Confirm to delete the selected variables?", - "选中的变量吗": "selected variables?", - "请输入名称/值/备注": "Please enter name/value/remarks", - "导入": "Import", - "创建变量": "Create Variable", - "批量修改变量名称": "Batch Modify Variable Names", - "批量导出": "Batch Export", - "请输入环境变量名称": "Please enter the environment variable name", - "只能输入字母数字下划线,且不能以数字开头": "Only letters, numbers, and underscores are allowed, and cannot start with a number", - "请输入环境变量值": "Please enter the environment variable value", - "服务启动超时": "Service startup timeout", - "请先按如下方式修复:": "Please fix it as follows:", "1. 宿主机执行 docker run --rm -v\n /var/run/docker.sock:/var/run/docker.sock\n containrrr/watchtower -cR <容器名>": "1. Execute 'docker run --rm -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtower -cR ' on the host machine", "2. 容器内执行 ql check、ql update": "2. Execute 'ql check' and 'ql update' inside the container", + "24小时未运行": "Idle 24h+", "3. 如果无法解决,容器内执行 pm2 logs,拷贝执行结果": "3. If the problem persists, execute 'pm2 logs' inside the container and copy the results", - "提交 issue": "Submit an issue", - "启动中,请稍后...": "Starting, please wait...", - "欢迎使用": "Welcome to use", - "欢迎使用青龙": "Welcome to use Qinglong", - "支持python3、javascript、shell、typescript 的定时任务管理面板": "A scheduling task management panel that supports python3, javascript, shell, and typescript", - "开始安装": "Start Installation", - "账户设置": "Account Settings", - "用户名": "Username", - "密码": "Password", - "密码不能为admin": "The password cannot be 'admin'", - "确认密码": "Confirm Password", - "您输入的两个密码不匹配!": "The two passwords you entered do not match!", - "提交": "Submit", - "通知设置": "Notification Settings", - "通知方式": "Notification Method", - "请选择通知方式": "Please select a notification method", - "跳过": "Skip", - "完成安装": "Installation Completed", - "恭喜安装完成!": "Congratulations, the installation is completed!", - "Telegram频道": "Telegram Channel", - "去登录": "Go to Login", - "初始化配置": "Initialize Configuration", - "文件": "File", - ",删除后不可恢复": ", it can't be recovered after deletion", - "请选择日志": "Please select a log", - "请输入日志名": "Please enter the log name", - "暂无日志": "No logs available", - "登录成功!": "Login successful!", - "上次登录时间:": "Last login time: ", - "上次登录地点:": "Last login location: ", - "上次登录IP:": "Last login IP: ", - "上次登录设备:": "Last login device: ", - "上次登录状态:": "Last login status: ", - "验证码": "Verification Code", - "验证码为6位数字": "Verification code is a 6-digit number", "6位数字": "6-digit number", - "验证": "Verify", - "请": "Please", - "秒后重试": "Retry after seconds", - "在您的设备上打开两步验证应用程序以查看您的身份验证代码并验证您的身份。": "Open the two-factor authentication application on your device to view your authentication code and verify your identity.", - "请选择脚本文件": "Please select a script file", - "当前文件不支持预览": "Current file type is not supported for preview", - "清空日志": "Clear Logs", - "设置": "Settings", - "退出": "Exit", - "空文件": "Empty File", - "本地文件": "Local File", - "文件夹": "Folder", - "文件名": "File Name", - "请输入文件名": "Please enter the file name", - "文件名不能包含斜杠": "File names cannot contain slashes", - "文件夹名": "Folder Name", - "请输入文件夹名": "Please enter the folder name", - "父目录": "Parent Directory", - "请选择父目录": "Please select a parent directory", - "点击或者拖拽文件到此区域上传": "Click or drag files here to upload", - "当前修改未保存,确定离开吗": "The current changes are not saved. Are you sure you want to leave?", - "退出编辑": "Exit Editing", - "重命名": "Rename", - "请选择脚本": "Please select a script", - "调试": "Debug", - "请输入脚本名": "Please enter the script name", - "暂无脚本": "No scripts available", - "请输入新名称": "Please enter a new name", - "保存文件": "Save File", - "保存目录": "Save Directory", - "请输入保存目录,默认scripts目录": "Please enter the save directory, default is 'scripts'", - "运行设置": "Run Settings", - "待开发": "To Be Developed", - "开发版": "Developer Edition", - "正式版": "Official Edition", - "版本": "Version", - "更新日志": "Changelog", - "查看": "View", - "提交BUG": "Submit Bug", - "名称不能为保留关键字": "The name cannot be a reserved keyword", - "请输入应用名称": "Please enter the application name", - "权限": "Permission", - "请选择模块权限": "Please select module permissions", - "更新": "Update", - "已经是最新版了!": "It is already the latest version!", - "是目前检测到的最新可用版本了。": "It is the latest available version currently detected.", - "重新下载": "Redownload", - "更新可用": "Update Available", - "新版本": "Create Version", - "可用,你使用的版本为": "available, the version you are using is", - "下载更新": "Download Update", - "以后再说": "Later", - "下载更新中...": "Downloading Update...", - "确认重启": "Confirm to Restart", - "系统安装包下载成功,确认重启": "System installation package downloaded successfully, confirm to restart", - "重启": "Restart", - "系统将在": "The system will restart in", - "秒后自动刷新": "seconds and automatically refresh", - "检查更新": "Check for Updates", - "重新启动": "Reboot", - "确认删除应用": "Confirm to delete the application", - "确认重置": "Confirm to reset", - "确认重置应用": "Confirm to reset the application", - "的Secret吗": "'s Secret?", - "重置Secret会让当前应用所有token失效": "Resetting the Secret will invalidate all tokens for the current application", - "创建应用": "Create Application", - "安全设置": "Security Settings", - "应用设置": "Application Settings", - "登录日志": "Login Logs", - "其他设置": "Other Settings", - "关于": "About", - "成功": "Successfully", - "失败": "Failure", - "登录时间": "Login Time", - "登录地址": "Login Address", - "登录IP": "Login IP", - "登录设备": "Login Device", - "登录状态": "Login Status", - "亮色": "Light", - "暗色": "Dark", - "跟随系统": "Follow System", - "备份数据上传成功,确认覆盖数据": "Data backup uploaded successfully, confirm data overwrite", - "主题设置": "Theme Settings", - "日志删除频率": "Log Deletion Frequency", - "每x天自动删除x天以前的日志": "Automatically delete logs older than x days every x days", - "每": "Every", - "天": "day(s)", - "定时任务并发数": "Concurrent Scheduled Tasks", - "数据备份还原": "Data Backup & Restore", - "还原数据": "Restore Data", - "第一步": "Step 1", - "下载两步验证手机应用,比如 Google Authenticator 、": "Download a two-factor authentication mobile app, like Google Authenticator,", - "第二步": "Step 2", - "使用手机应用扫描二维码,或者输入秘钥": "Scan the QR code with the mobile app or enter the key", - "第三步": "Step 3", - "输入手机应用上的6位数字": "Enter the 6-digit code from the mobile app", - "完成设置": "Finish Setup", - "修改用户名密码": "Change Username and Password", - "两步验证": "Two-Factor Authentication", - "头像": "Profile Picture", - "更换头像": "Change Profile Picture", - "时": "hour(s)", - "分": "minute(s)", - "秒": "second(s)", - "私有仓库": "Private Repository", - "公开仓库": "Public Repository", - "单文件": "Single File", - "链接": "Link", - "分支": "Branch", - "确认删除定时订阅": "Confirm Deletion of Scheduled Subscription", - "定时订阅": "Scheduled Subscription", - "创建订阅": "Create Subscription", - "私钥": "Private Key", - "请输入私钥": "Please enter the private key", - "请输入认证用户名": "Please enter the authentication username", - "Github已不支持密码认证,请使用Token方式": "Github no longer supports password authentication. Please use the Token method.", - "密码/Token": "Password/Token", - "请输入密码或者Token": "Please enter the password or Token", - "支持拷贝 ql repo/raw 命令,粘贴导入": "Supports copying ql repo/raw command for import", - "请输入订阅链接": "Please enter the subscription link", - "请输入分支": "Please enter the branch", - "唯一值": "Unique Value", - "唯一值用于日志目录和私钥别名": "Unique value used for log directory and private key alias", - "自动生成": "Auto-generated", - "拉取方式": "Pull Method", - "用户名密码/Token": "Username/Password or Token", - "定时类型": "Schedule Type", - "白名单": "Whitelist", - "多个关键词竖线分割,支持正则表达式": "Multiple keywords separated by vertical lines (|), supports regular expressions", - "请输入脚本筛选白名单关键词,多个关键词竖线分割": "Please enter script filtering whitelist keywords, multiple keywords separated by vertical lines (|)", - "黑名单": "Blacklist", - "请输入脚本筛选黑名单关键词,多个关键词竖线分割": "Please enter script filtering blacklist keywords, multiple keywords separated by vertical lines (|)", - "依赖文件": "Dependency Files", - "请输入脚本依赖文件关键词,多个关键词竖线分割": "Please enter script dependency file keywords, multiple keywords separated by vertical lines (|)", - "文件后缀": "File Extension", - "仓库需要拉取的文件后缀,多个后缀空格分隔,默认使用配置文件中的RepoFileExtensions": "Repository requires pulling specific file extensions, multiple extensions separated by spaces, uses RepoFileExtensions from the configuration file by default", - "请输入文件后缀": "Please enter the file extension", - "执行前": "Before Execution", - "运行订阅前执行的命令,比如 cp/mv/python3 xxx.py/node xxx.js": "Run commands before executing the subscription, e.g., cp/mv/python3 xxx.py/node xxx.js", - "请输入运行订阅前要执行的命令": "Please enter the command to run before executing the subscription", - "执行后": "After Execution", - "运行订阅后执行的命令,比如 cp/mv/python3 xxx.py/node xxx.js": "Run commands after executing the subscription, e.g., cp/mv/python3 xxx.py/node xxx.js", - "请输入运行订阅后要执行的命令": "Please enter the command to run after executing the subscription", - "代理": "Proxy", - "公开仓库支持HTTP/SOCK5代理,私有仓库支持SOCK5代理": "Public repositories support HTTP/SOCK5 proxies, private repositories support SOCK5 proxies", - "自动添加任务": "Automatically Add Tasks", - "自动删除任务": "Automatically Delete Tasks", - "中文": "Chinese", - "系统信息": "System Information", - "Server酱": "ServerChan", - "Telegram机器人": "Telegram Bot", - "钉钉机器人": "DingTalk Bot", - "企业微信机器人": "WeChat Work Bot", - "企业微信应用": "WeChat Work App", - "智能微秘书": "Smart WeChat Assistant", - "群晖chat": "Synology Chat", - "微加机器人": "WePlusBot", - "邮箱": "Email", - "飞书机器人": "Feishu Bot", - "自定义通知": "Custom Notification", - "已关闭": "Disabled", - "gotify的url地址,例如 https://push.example.de:8080": "gotify URL address, e.g., https://push.example.de:8080", - "gotify的消息应用token码": "gotify message application token code", - "推送消息的优先级": "Priority of Push Messages", - "synologyChat的url地址": "Synology Chat Webhook URL address", - "chat的token码": "Chat token code", - "推送到个人QQ: http://127.0.0.1/send_private_msg,群:http://127.0.0.1/send_group_msg": "Push to personal QQ: http://127.0.0.1/send_private_msg, group: http://127.0.0.1/send_group_msg", - "访问密钥": "Access Key", - "如果GOBOT_URL设置 /send_private_msg 则需要填入 user_id=个人QQ 相反如果是 /send_group_msg 则需要填入 group_id=QQ群": "If GOBOT_URL is set to /send_private_msg, enter user_id=personal QQ; if set to /send_group_msg, enter group_id=QQ group", - "Server酱SENDKEY": "ServerChan SENDKEY, https://sct.ftqq.com/r/13363", - "PushDeer的Key,https://github.com/easychen/pushdeer": "PushDeer Key, https://github.com/easychen/pushdeer", - "PushDeer的自架API endpoint,默认是 https://api2.pushdeer.com/message/push": "PushDeer's self-hosted API endpoint, default is https://api2.pushdeer.com/message/push", - "Bark的信息IP/设备码,例如:https://api.day.app/XXXXXXXX": "Bark information IP/device code, e.g., https://api.day.app/XXXXXXXX", "BARK推送图标,自定义推送图标 (需iOS15或以上才能显示)": "BARK push icon, custom push icon (requires iOS 15 or above to display)", - "BARK推送铃声,铃声列表去APP查看复制填写": "BARK push ringtone, check and copy from the APP's ringtone list", "BARK推送消息的分组,默认为qinglong": "BARK push message grouping, default is qinglong", "BARK推送消息的时效性,默认为active": "BARK push message timeliness, default is active", "BARK推送消息的跳转URL": "BARK push message redirecting URL", + "BARK推送铃声,铃声列表去APP查看复制填写": "BARK push ringtone, check and copy from the APP's ringtone list", "BARK是否保存推送消息": "Does BARK save push messages", + "Bark的信息IP/设备码,例如:https://api.day.app/XXXXXXXX": "Bark information IP/device code, e.g., https://api.day.app/XXXXXXXX", + "CPU 核心": "CPU Cores", + "Chronocat Red 服务的连接地址 https://chronocat.vercel.app/install/docker/official/": "Connection address of the Chronocat Red service https://chronocat.vercel.app/install/docker/official/", + "Cron表达式格式有误": "Incorrect Cron Expression Format", + "Github已不支持密码认证,请使用Token方式": "Github no longer supports password authentication. Please use the Token method.", + "Linux 软件包镜像源": "Linux Software Package Mirror Source", + "Minimum is 4": "Minimum is 4", + "NPM 镜像源": "NPM Mirror Source", + "Node 软件包镜像源": "Node Software Package Mirror Source", + "PushDeer的Key,https://github.com/easychen/pushdeer": "PushDeer Key, https://github.com/easychen/pushdeer", + "PushDeer的自架API endpoint,默认是 https://api2.pushdeer.com/message/push": "PushDeer's self-hosted API endpoint, default is https://api2.pushdeer.com/message/push", + "PushMe的Key,https://push.i-i.me/": "PushMe key, https://push.i-i.me/", + "PyPI 镜像源": "PyPI Mirror Source", + "Python 软件包镜像源": "Python Software Package Mirror Source", + "SMTP 登录密码,也可能为特殊口令,视具体邮件服务商说明而定": "The SMTP login password may also be a special passphrase, depending on the specific email service provider's instructions", + "SSH 文件缓存": "SSH file cache", + "SSH密钥": "SSH Keys", + "Server酱": "ServerChan", + "Server酱SENDKEY": "ServerChan SENDKEY, https://sct.ftqq.com/r/13363", + "Subscription表达式格式有误": "Incorrect Subscription Expression Format", + "Telegram机器人": "Telegram Bot", + "Telegram频道": "Telegram Channel", + "alpine linux 镜像源": "Alpine Linux Mirror Source", + "chat的token码": "Chat token code", + "corpid、corpsecret、touser(注:多个成员ID使用|隔开)、agentid、消息类型(选填,不填默认文本消息类型) 注意用,号隔开(英文输入法的逗号),例如:wwcfrs,B-76WERQ,qinglong,1000001,2COat": "corpid, corpsecret, touser (note: separate multiple member IDs with |), agentid, message type (optional, defaults to text message type) – separated by commas (`,`), e.g., wwcfrs, B-76WERQ, qinglong, 1000001, 2COat", + "docker安装在持久化config目录下的chronocat.yml文件可找到": "The docker installation can be found in the persistence config directory in the chronocat.yml file", + "gotify的url地址,例如 https://push.example.de:8080": "gotify URL address, e.g., https://push.example.de:8080", + "gotify的消息应用token码": "gotify message application token code", + "iGot的信息推送key,例如:https://push.hellyw.com/XXXXXXXX": "iGot information push key, e.g., https://push.hellyw.com/XXXXXXXX", + "ntfy应用token": "The token for ntfy's application, see https://docs.ntfy.sh/config/#access-tokens", + "ntfy应用topic": "The topic for ntfy's application.", + "ntfy应用密码": "The password for ntfy's application, see https://docs.ntfy.sh/config/#users-and-roles", + "ntfy应用用户名": "The username for ntfy's application, see https://docs.ntfy.sh/config/#users-and-roles", + "ntfy用户动作": "The user actions for ntfy's application, up to three actions, see https://docs.ntfy.sh/publish/?h=actions#action-buttons", + "ntfy的url地址,例如 https://ntfy.sh": "The URL address of ntfy, for example, https://ntfy.sh.", + "synologyChat的url地址": "Synology Chat Webhook URL address", + "telegram api自建的反向代理地址,默认tg官方api": "Telegram API's self-built reverse proxy address, default is official tg API", + "telegram代理配置认证参数,用户名与密码用英文冒号连接 user:password": "Telegram proxy configuration authentication parameters, connect username and password with a colon, e.g., user:password", "telegram机器人的token,例如:1077xxx4424:AAFjv0FcqxxxxxxgEMGfi22B4yh15R5uw": "Telegram Bot token, e.g., 1077xxx4424:AAFjv0FcqxxxxxxgEMGfi22B4yh15R5uw", "telegram用户的id,例如:129xxx206": "Telegram user ID, e.g., 129xxx206", - "代理IP": "Proxy IP", - "代理端口": "Proxy Port", - "telegram代理配置认证参数,用户名与密码用英文冒号连接 user:password": "Telegram proxy configuration authentication parameters, connect username and password with a colon, e.g., user:password", - "telegram api自建的反向代理地址,默认tg官方api": "Telegram API's self-built reverse proxy address, default is official tg API", - "钉钉机器人webhook token,例如:5a544165465465645d0f31dca676e7bd07415asdasd": "DingTalk Bot webhook token, e.g., 5a544165465465645d0f31dca676e7bd07415asdasd", - "密钥,机器人安全设置页面,加签一栏下面显示的SEC开头的字符串": "Secret key, shown below the signing section on the robot's security settings page, starts with SEC", - "企业微信机器人的webhook(详见文档 https://work.weixin.qq.com/api/doc/90000/90136/91770),例如:693a91f6-7xxx-4bc4-97a0-0ec2sifa5aaa": "WeChat Work Bot webhook (see documentation at https://work.weixin.qq.com/api/doc/90000/90136/91770), e.g., 693a91f6-7xxx-4bc4-97a0-0ec2sifa5aaa", - "企业微信代理地址": "WeChat Work Proxy Address", - "corpid、corpsecret、touser(注:多个成员ID使用|隔开)、agentid、消息类型(选填,不填默认文本消息类型) 注意用,号隔开(英文输入法的逗号),例如:wwcfrs,B-76WERQ,qinglong,1000001,2COat": "corpid, corpsecret, touser (note: separate multiple member IDs with |), agentid, message type (optional, defaults to text message type) – separated by commas (`,`), e.g., wwcfrs, B-76WERQ, qinglong, 1000001, 2COat", - "密钥key,智能微秘书个人中心获取apikey,申请地址:https://wechat.aibotk.com/signup?from=ql": "Key, obtain the API key from the Smart WeChat Assistant's personal center, apply at: https://wechat.aibotk.com/signup?from=ql", - "发送的目标,群组或者好友": "Recipient, group, or friend", - "请输入要发送的目标": "Please enter the recipient's name (group or friend)", - "群聊": "Group Chat", - "好友": "Friend", - "要发送的用户昵称或群名,如果目标是群,需要填群名,如果目标是好友,需要填好友昵称": "Enter the recipient's nickname if it's a friend or the group name if it's a group", - "iGot的信息推送key,例如:https://push.hellyw.com/XXXXXXXX": "iGot information push key, e.g., https://push.hellyw.com/XXXXXXXX", - "微信扫码登录后一对一推送或一对多推送下面的token(您的Token),不提供PUSH_PLUS_USER则默认为一对一推送,参考 https://www.pushplus.plus/": "After WeChat scan login, one-to-one or one-to-many push using the provided token (your Token). If PUSH_PLUS_USER is not provided, it defaults to one-to-one push. See reference at https://www.pushplus.plus/", - "一对多推送的“群组编码”(一对多推送下面->您的群组(如无则创建)->群组编码,如果您是创建群组人。也需点击“查看二维码”扫描绑定,否则不能接受群组消息推送)": "The 'group code' for one-to-many push (one-to-many push -> your group (if none, create one) -> group code). If you are the creator of the group, you need to click 'View QR code' to scan and bind, otherwise, you won't receive group messages.", - "发送模板": "send template, can use type: 'html,txt,json,markdown,cloudMonitor,jenkins,route,pay'", - "发送渠道": "send channel, can use type: 'wechat,webhook,cp,mail,sms'", "webhook编码": "webhook code", - "发送结果回调地址": "send result callback url", - "好友令牌": "friend token", - "用户令牌,扫描登录后 我的—>设置->令牌 中获取,参考 https://www.weplusbot.com/": "Token, which can be obtained after scanning and logging in, is available under 'My Account' -> 'Settings' -> 'Tokens'. Please refer to the instructions for detailed steps: https://www.weplusbot.com/", - "消息接收人": "message recipient", - "调用版本;专业版填写pro,个人版填写personal,为空默认使用专业版": "Version, you can specify 'pro' for the Professional version and 'personal' for the Personal version. If left blank, it will default to the Professional version.", - "飞书群组机器人:https://www.feishu.cn/hc/zh-CN/articles/360024984973": "Feishu group bot: https://www.feishu.cn/hc/zh-CN/articles/360024984973", - "飞书群组机器人加签密钥,安全设置中开启签名校验后获得": "Feishu group bot signature secret, obtained after enabling signature verification in security settings", - "邮箱服务名称,比如126、163、Gmail、QQ等,支持列表https://github.com/nodemailer/nodemailer/blob/master/lib/well-known/services.json": "Email service name, e.g., 126, 163, Gmail, QQ, etc. Supported list: https://github.com/nodemailer/nodemailer/blob/master/lib/well-known/services.json", - "邮箱地址": "Email Address", - "SMTP 登录密码,也可能为特殊口令,视具体邮件服务商说明而定": "The SMTP login password may also be a special passphrase, depending on the specific email service provider's instructions", - "PushMe的Key,https://push.i-i.me/": "PushMe key, https://push.i-i.me/", - "自建的PushMeServer消息接口地址,例如:http://127.0.0.1:3010,不填则使用官方消息接口": "The self built PushMeServer message interface address, for example: http://127.0.0.1:3010 If left blank, use the official message interface", - "ntfy的url地址,例如 https://ntfy.sh": "The URL address of ntfy, for example, https://ntfy.sh.", - "ntfy应用topic": "The topic for ntfy's application.", - "ntfy应用token": "The token for ntfy's application, see https://docs.ntfy.sh/config/#access-tokens", - "ntfy应用用户名": "The username for ntfy's application, see https://docs.ntfy.sh/config/#users-and-roles", - "ntfy应用密码": "The password for ntfy's application, see https://docs.ntfy.sh/config/#users-and-roles", - "ntfy用户动作": "The user actions for ntfy's application, up to three actions, see https://docs.ntfy.sh/publish/?h=actions#action-buttons", "wxPusherBot的appToken": "wxPusherBot's appToken, obtain according to docs https://wxpusher.zjiecode.com/docs/", "wxPusherBot的topicIds": "wxPusherBot's topicIds, at least one of topicIds or uids must be configured", "wxPusherBot的uids": "wxPusherBot's uids, at least one of topicIds or uids must be configured", - "请求方法": "Request Method", - "请求头Content-Type": "Request Header Content-Type", - "请求链接以http或者https开头。url或者body中必须包含$title,$content可选,对应api内容的位置": "Request URL should start with http or https. URL or body must contain $title, $content is optional and corresponds to the API content position.", - "请求头格式Custom-Header1: Header1,多个换行分割": "Request header format: Custom-Header1: Header1 (separate multiple headers with line breaks)", - "请求体格式key1: value1,多个换行分割。url或者body中必须包含$title,$content可选,对应api内容的位置": "Request body format: key1: value1 (separate multiple keys with line breaks). URL or body must contain $title, $content is optional and corresponds to the API content position.", - "错误日志": "Error Log", - "执行结束": "Execution Finished", - "备份": "Backup", - "生成数据中...": "Generating data...", - "请选择日志文件": "Please select a log file", - "筛选条件": "Filter Conditions", - "系统": "System", - "个人": "Personal", - "重新安装": "Reinstall", - "取消安装": "Cancel Install", - "强制删除": "Force Delete", - "全部任务": "All Tasks", - "关联订阅": "Associate Subscription", - "订阅": "Subscription", - "创建": "Create", - "同时删除关联任务和脚本": "Delete associated tasks and scripts as well", - "未找到": "Not Found", - "保存成功": "Saved successfully", - "删除成功": "Deleted successfully", - "批量删除成功": "Batch deleted successfully", - "启动中...": "Starting...", - "任务未运行": "Task not running", - "更新任务成功": "Task updated successfully", - "创建任务成功": "Task created successfully", - "编辑任务": "Edit Task", - "Cron表达式格式有误": "Incorrect Cron Expression Format", - "添加Labels成功": "Labels added successfully", - "删除Labels成功": "Labels deleted successfully", - "添加标签成功": "Tags added successfully", - "删除标签成功": "Tags deleted successfully", - "请至少输入一个标签": "Please enter at least one tag", - "编辑视图": "Edit View", - "排序方式": "Sort Order", - "开始时间": "Start Time", - "安装": "Install", - "结束时间": "End Time", - "编辑依赖": "Edit Dependency", - "更新环境变量名称成功": "Environment Variable Name updated successfully", - "更新变量成功": "Variable updated successfully", - "创建变量成功": "Variable created successfully", - "编辑变量": "Edit Variable", - "加载中...": "Loading...", - "夹下所有日志": "Folder and All Subfiles", - "创建文件夹成功": "Folder created successfully", - "创建文件成功": "File created successfully", - "夹及其子文件": "Folder and Its Subfiles", - "更新名称成功": "Name updated successfully", - "保存文件成功": "File saved successfully", - "更新应用成功": "Application updated successfully", - "创建应用成功": "Application created successfully", - "编辑应用": "Edit Application", - "检查更新中...": "Checking for updates...", - "失败,请检查": "Failed, please check", - "更新失败,请检查网络及日志或稍后再试": "Update failed, please check network and logs or try again later", - "更新包下载成功": "Update package download successful", - "重置secret": "Reset secret", - "重置成功": "Reset successful", - "通知发送成功": "Notification sent successfully", - "通知关闭成功": "Notification closed successfully", - "测试中...": "Testing...", - "上传": "Upload", - "下载": "Download", - "更新成功": "Update successful", - "激活成功": "Activation successful", - "验证失败": "Validation failed", - "更新订阅成功": "Subscription updated successfully", - "创建订阅成功": "Subscription created successfully", - "编辑订阅": "Edit Subscription", - "Subscription表达式格式有误": "Incorrect Subscription Expression Format", + "一对多推送的“群组编码”(一对多推送下面->您的群组(如无则创建)->群组编码,如果您是创建群组人。也需点击“查看二维码”扫描绑定,否则不能接受群组消息推送)": "The 'group code' for one-to-many push (one-to-many push -> your group (if none, create one) -> group code). If you are the creator of the group, you need to click 'View QR code' to scan and bind, otherwise, you won't 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", - "系统日志": "System Logs", - "主题": "Theme", - "语言": "Language", - "中...": "ing...", - "请选择操作符": "Please select operator", - "新增定时规则": "Add Timing Rules", - "运行任务前执行的命令,比如 cp/mv/python3 xxx.py/node xxx.js": "Run commands before executing the task, e.g., cp/mv/python3 xxx.py/node xxx.js", - "运行任务后执行的命令,比如 cp/mv/python3 xxx.py/node xxx.js": "Run commands after executing the task, e.g., cp/mv/python3 xxx.py/node xxx.js", - "请输入运行任务前要执行的命令,不能包含 task 命令": "Please enter the command to run before executing the task, cannot contain task commands", - "请输入运行任务后要执行的命令,不能包含 task 命令": "Please enter the command to run after executing the task, cannot contain task commands", + "上传": "Upload", + "上次登录IP:": "Last login IP: ", + "上次登录地点:": "Last login location: ", + "上次登录时间:": "Last login time: ", + "上次登录状态:": "Last login status: ", + "上次登录设备:": "Last login device: ", + "下次运行时间": "Next Run Time", + "下载": "Download", + "下载两步验证手机应用,比如 Google Authenticator 、": "Download a two-factor authentication mobile app, like Google Authenticator,", + "下载更新": "Download Update", + "下载更新中...": "Downloading Update...", + "不包含": "Exclude", + "不属于": "Not Belong to", "不能包含 task 命令": "Cannot contain task commands", - "工作目录": "Working Directory", - "脚本执行时的工作目录,留空则自动检测。相对路径基于 scripts 目录,也支持绝对路径": "Working directory for script execution. Leave blank for auto-detection. Relative paths are based on the scripts directory. Absolute paths are also supported.", - "留空自动检测,或输入相对/绝对路径": "Leave blank to auto-detect, or enter a relative/absolute path", - "Chronocat Red 服务的连接地址 https://chronocat.vercel.app/install/docker/official/": "Connection address of the Chronocat Red service https://chronocat.vercel.app/install/docker/official/", + "且": "And", + "两步验证": "Two-Factor Authentication", + "个人": "Personal", "个人:user_id=个人QQ 群则填入group_id=QQ群 多个用英文;隔开同时支持个人和群 如:user_id=xxx;group_id=xxxx;group_id=xxxxx": "Individuals: user_id=individual QQ Groups fill in group_id=QQ Groups more than one with English; separated by the same time to support individuals and groups such as: user_id=xxx;group_id=xxxx;group_id=xxxxx", - "docker安装在持久化config目录下的chronocat.yml文件可找到": "The docker installation can be found in the persistence config directory in the chronocat.yml file", - "请选择": "Please select", - "请输入": "Please input", - "依赖设置": "Dependence Settings", - "Node 软件包镜像源": "Node Software Package Mirror Source", - "Python 软件包镜像源": "Python Software Package Mirror Source", - "Linux 软件包镜像源": "Linux Software Package Mirror Source", + "中...": "ing...", + "中文": "Chinese", + "主题": "Theme", + "主题设置": "Theme Settings", + "亮色": "Light", + "今日失败": "Failed", + "今日成功": "Success", + "今日执行": "Today Runs", + "今日执行次数 Top 5": "Top 5 by Runs", + "今日耗时 Top 5": "Top 5 by Time", + "仓库需要拉取的文件后缀,多个后缀空格分隔,默认使用配置文件中的RepoFileExtensions": "Repository requires pulling specific file extensions, multiple extensions separated by spaces, uses RepoFileExtensions from the configuration file by default", + "代理": "Proxy", + "代理IP": "Proxy IP", "代理与镜像源二选一即可": "Either Proxy or Mirror Source can be chosen", "代理地址, 支持HTTP(S)/SOCK5": "Proxy Address, supports HTTP(S)/SOCK5", - "NPM 镜像源": "NPM Mirror Source", - "PyPI 镜像源": "PyPI Mirror Source", - "alpine linux 镜像源": "Alpine Linux Mirror Source", + "代理端口": "Proxy Port", + "以后再说": "Later", + "仪表盘": "Dashboard", + "任务": "Task", + "任务数": "Tasks", + "任务未运行": "Task not running", + "企业微信代理地址": "WeChat Work Proxy Address", + "企业微信应用": "WeChat Work App", + "企业微信机器人": "WeChat Work Bot", + "企业微信机器人的webhook(详见文档 https://work.weixin.qq.com/api/doc/90000/90136/91770),例如:693a91f6-7xxx-4bc4-97a0-0ec2sifa5aaa": "WeChat Work Bot webhook (see documentation at https://work.weixin.qq.com/api/doc/90000/90136/91770), e.g., 693a91f6-7xxx-4bc4-97a0-0ec2sifa5aaa", + "使用手机应用扫描二维码,或者输入秘钥": "Scan the QR code with the mobile app or enter the key", + "依赖文件": "Dependency Files", + "依赖管理": "Dependency Management", + "依赖类型": "Dependency Type", + "依赖缓存": "Dependency cache", + "依赖设置": "Dependence Settings", + "保存": "Save", + "保存成功": "Saved successfully", + "保存文件": "Save File", + "保存文件成功": "File saved successfully", + "保存目录": "Save Directory", + "修改环境变量名称": "Modify Environment Variable Name", + "修改用户名密码": "Change Username and Password", + "倒序": "Reverse", + "值": "Value", + "停止": "Stop", + "全局SSH私钥": "Global SSH Private Key", + "全部任务": "All Tasks", + "公开仓库": "Public Repository", + "公开仓库支持HTTP/SOCK5代理,私有仓库支持SOCK5代理": "Public repositories support HTTP/SOCK5 proxies, private repositories support SOCK5 proxies", + "关于": "About", + "关联订阅": "Associate Subscription", + "其他设置": "Other Settings", + "内存": "Memory", + "内存使用": "Memory", + "分": "minute(s)", + "分支": "Branch", + "创建": "Create", + "创建SSH密钥": "Create SSH Key", + "创建SSH密钥成功": "SSH key created successfully", + "创建任务": "Create Task", + "创建任务成功": "Task created successfully", + "创建依赖": "Create Dependency", + "创建变量": "Create Variable", + "创建变量成功": "Variable created successfully", + "创建应用": "Create Application", + "创建应用成功": "Application created successfully", + "创建文件夹成功": "Folder created successfully", + "创建文件成功": "File created successfully", + "创建时间": "Created Time", + "创建视图": "Create View", + "创建订阅": "Create Subscription", + "创建订阅成功": "Subscription created successfully", + "初始化": "Initialize", + "初始化配置": "Initialize Configuration", + "删除": "Delete", + "删除Labels成功": "Labels deleted successfully", + "删除中": "Deleting", + "删除失败": "Deletion Failed", + "删除成功": "Deleted successfully", + "删除标签成功": "Tags deleted successfully", + "别名": "Alias", + "加载中...": "Loading...", + "包含": "Include", + "单实例": "Single Instance", + "单实例模式:定时启动新任务前会自动停止旧任务;多实例模式:允许同时运行多个任务实例": "Single instance mode: automatically stop old task before starting new scheduled task; Multi-instance mode: allow multiple task instances to run simultaneously", + "单文件": "Single File", + "去登录": "Go to Login", + "发送模板": "send template, can use type: 'html,txt,json,markdown,cloudMonitor,jenkins,route,pay'", + "发送渠道": "send channel, can use type: 'wechat,webhook,cp,mail,sms'", + "发送的目标,群组或者好友": "Recipient, group, or friend", + "发送结果回调地址": "send result callback url", + "取消": "Cancel", + "取消安装": "Cancel Install", + "取消置顶": "Un-top", + "只能输入字母数字下划线,且不能以数字开头": "Only letters, numbers, and underscores are allowed, and cannot start with a number", + "可用,你使用的版本为": "available, the version you are using is", + "同时删除关联任务和脚本": "Delete associated tasks and scripts as well", + "名称": "Name", + "名称不能为保留关键字": "The name cannot be a reserved keyword", + "吗": "?", + "否": "No", + "启动": "Start", + "启动中...": "Starting...", + "启动中,请稍后...": "Starting, please wait...", + "启用": "Enable", + "命令": "Command", + "命令/脚本": "Command/Script", + "唯一值": "Unique Value", + "唯一值用于日志目录和私钥别名": "Unique value used for log directory and private key alias", + "在您的设备上打开两步验证应用程序以查看您的身份验证代码并验证您的身份。": "Open the two-factor authentication application on your device to view your authentication code and verify your identity.", + "基础数据": "Basic data", + "堆内存": "Heap", + "备份": "Backup", + "备份数据上传成功,确认覆盖数据": "Data backup uploaded successfully, confirm data overwrite", + "备注": "Remarks", + "复制": "Copy", + "复制成功": "Copy successful", + "多个依赖是否换行分割": "Whether to separate multiple dependencies with new lines", + "多个关键词竖线分割,支持正则表达式": "Multiple keywords separated by vertical lines (|), supports regular expressions", + "多实例": "Multi-Instance", + "天": "day(s)", + "失败": "Failure", + "失败,请检查": "Failed, please check", + "头像": "Profile Picture", + "夹下所有日志": "Folder and All Subfiles", + "夹及其子文件": "Folder and Its Subfiles", + "好友": "Friend", + "好友令牌": "friend token", + "如果GOBOT_URL设置 /send_private_msg 则需要填入 user_id=个人QQ 相反如果是 /send_group_msg 则需要填入 group_id=QQ群": "If GOBOT_URL is set to /send_private_msg, enter user_id=personal QQ; if set to /send_group_msg, enter group_id=QQ group", "如果恢复失败,可进入容器执行": "If recovery fails, you can enter the container and execute", + "安全设置": "Security Settings", + "安装": "Install", + "安装中": "Installing", + "安装失败": "Installation Failed", + "完成安装": "Installation Completed", + "完成设置": "Finish Setup", + "定时": "Schedule", + "定时任务": "Scheduled Tasks", + "定时任务并发数": "Concurrent Scheduled Tasks", + "定时类型": "Schedule Type", + "定时规则": "Schedule Rule", + "定时订阅": "Scheduled Subscription", + "实例模式": "Instance Mode", + "实时运行态": "Runtime", + "密码": "Password", + "密码/Token": "Password/Token", + "密码不能为admin": "The password cannot be 'admin'", + "密钥key,智能微秘书个人中心获取apikey,申请地址:https://wechat.aibotk.com/signup?from=ql": "Key, obtain the API key from the Smart WeChat Assistant's personal center, apply at: https://wechat.aibotk.com/signup?from=ql", + "密钥,机器人安全设置页面,加签一栏下面显示的SEC开头的字符串": "Secret key, shown below the signing section on the robot's security settings page, starts with SEC", + "对比工具": "Comparison Tool", + "导入": "Import", + "属于": "Belong to", + "工作目录": "Working Directory", + "已关闭": "Disabled", + "已删除": "Deleted", + "已取消": "Cancelled", + "已启用": "Enabled", + "已安装": "Installed", + "已禁用": "Disabled", + "实例已停止": "Instance stopped", + "已经是最新版了!": "It is already the latest version!", + "已运行": "Elapsed", + "已选择": "Selected", "常规定时": "Normal Timing", - "手动运行": "Manual Run", + "平台": "Platform", + "平均耗时": "Avg Time", + "序号": "Number", + "应用设置": "Application Settings", + "开发版": "Developer Edition", + "开始备份": "Start backup", + "开始安装": "Start Installation", + "开始时间": "Start Time", "开机运行": "Boot Run", - "时区": "Timezone", + "强制删除": "Force Delete", "强制打开": "Force Open", "强制打开可能会导致编辑器显示异常": "Force opening may cause display issues in the editor", - "确认离开": "Confirm Leave", + "当前修改未保存,确定离开吗": "The current changes are not saved. Are you sure you want to leave?", + "当前文件": "Current File", + "当前文件不支持预览": "Current file type is not supported for preview", "当前文件未保存,确认离开吗": "Current file is not saved, are you sure to leave?", + "待开发": "To Be Developed", + "微信扫码登录后一对一推送或一对多推送下面的token(您的Token),不提供PUSH_PLUS_USER则默认为一对一推送,参考 https://www.pushplus.plus/": "After WeChat scan login, one-to-one or one-to-many push using the provided token (your Token). If PUSH_PLUS_USER is not provided, it defaults to one-to-one push. See reference at https://www.pushplus.plus/", + "微加机器人": "WePlusBot", + "总任务": "Total Tasks", + "总执行": "Total", + "恭喜安装完成!": "Congratulations, the installation is completed!", + "您输入的两个密码不匹配!": "The two passwords you entered do not match!", + "成功": "Successfully", + "成功率": "Success Rate", + "或": "Or", + "手动运行": "Manual Run", + "执行前": "Before Execution", + "执行后": "After Execution", + "执行结束": "Execution Finished", + "批量": "Batch", + "批量修改变量名称": "Batch Modify Variable Names", + "批量修改标签": "Batch Modify Tags", + "批量停止": "Batch Stop", + "批量删除": "Batch Delete", + "批量删除成功": "Batch deleted successfully", + "批量取消置顶": "Batch Un-top", + "批量启用": "Batch Enable", + "批量安装": "Batch Install", + "批量导出": "Batch Export", + "批量强制删除": "Batch Force Delete", + "批量禁用": "Batch Disable", + "批量置顶": "Batch Top", + "批量运行": "Batch Run", + "拉取方式": "Pull Method", + "排序方式": "Sort Order", + "排队中": "Queued", + "推送到个人QQ: http://127.0.0.1/send_private_msg,群:http://127.0.0.1/send_group_msg": "Push to personal QQ: http://127.0.0.1/send_private_msg, group: http://127.0.0.1/send_group_msg", + "推送消息的优先级": "Priority of Push Messages", + "提交": "Submit", + "提交 issue": "Submit an issue", + "提交BUG": "Submit Bug", + "操作": "Action", + "支持python3、javascript、shell、typescript 的定时任务管理面板": "A scheduling task management panel that supports python3, javascript, shell, and typescript", + "支持拷贝 ql repo/raw 命令,粘贴导入": "Supports copying ql repo/raw command for import", + "支持输入脚本路径/任意系统可执行命令/task 脚本路径": "Supports input of script paths / any system executable commands / task script paths", "收件邮箱地址,多个分号分隔,默认发送给发件邮箱地址": "Receiving email address, multiple semicolon separated, sent to the sending email address by default", - "选择备份模块": "Select backup module", - "开始备份": "Start backup", - "基础数据": "Basic data", - "脚本文件": "Script files", + "数据备份还原": "Data Backup & Restore", + "文件": "File", + "文件名": "File Name", + "文件名不能包含斜杠": "File names cannot contain slashes", + "文件后缀": "File Extension", + "文件夹": "Folder", + "文件夹名": "Folder Name", + "新增定时规则": "Add Timing Rules", + "新增排序方式": "Add Sort", + "新增筛选条件": "Add Filter", + "新建": "New", + "新版本": "Create Version", + "日志": "Log", + "日志 -": "Log -", + "日志删除频率": "Log Deletion Frequency", + "日志名称": "Log Name", + "日志名称不能超过100个字符": "Log name cannot exceed 100 characters", + "日志名称只能包含字母、数字、下划线和连字符": "Log name can only contain letters, numbers, underscores and hyphens", "日志文件": "Log files", - "依赖缓存": "Dependency cache", - "远程脚本缓存": "Remote script cache", - "远程仓库缓存": "Remote repository cache", - "SSH 文件缓存": "SSH file cache", + "日志管理": "Log Management", + "时": "hour(s)", + "时区": "Timezone", + "是": "Yes", + "是目前检测到的最新可用版本了。": "It is the latest available version currently detected.", + "显示": "Display", + "智能微秘书": "Smart WeChat Assistant", + "暂无数据": "No data", + "暂无日志": "No logs available", + "暂无脚本": "No scripts available", + "暂无运行中任务": "No running tasks", + "暗色": "Dark", + "更多": "More", + "更换头像": "Change Profile Picture", + "更新": "Update", + "更新SSH密钥成功": "SSH key updated successfully", + "更新任务成功": "Task updated successfully", + "更新包下载成功": "Update package download successful", + "更新变量成功": "Variable updated successfully", + "更新可用": "Update Available", + "更新名称成功": "Name updated successfully", + "更新失败,请检查网络及日志或稍后再试": "Update failed, please check network and logs or try again later", + "更新应用成功": "Application updated successfully", + "更新成功": "Update successful", + "更新日志": "Changelog", + "更新时间": "Update Time", + "更新环境变量名称成功": "Environment Variable Name updated successfully", + "更新订阅成功": "Subscription updated successfully", + "最后运行时长": "Last Run Duration", + "最后运行时间": "Last Run Time", + "最长单次": "Max Time", + "服务启动超时": "Service startup timeout", + "未启用": "Not enabled", + "未找到": "Not Found", + "本地文件": "Local File", + "权限": "Permission", + "查看": "View", + "查看日志": "View Log", + "标签": "Tags", + "标签统计": "Label Stats", + "检查更新": "Check for Updates", + "检查更新中...": "Checking for updates...", + "次数": "Runs", + "欢迎使用": "Welcome to use", + "欢迎使用青龙": "Welcome to use Qinglong", + "正式版": "Official Edition", + "每": "Every", + "每x天自动删除x天以前的日志": "Automatically delete logs older than x days every x days", + "测试中...": "Testing...", + "消息接收人": "message recipient", + "添加": "Add", + "添加Labels成功": "Labels added successfully", + "添加标签成功": "Tags added successfully", + "清空日志": "Clear Logs", "清除依赖缓存": "Clean dependency cache", "清除成功": "Clean successful", - "日志名称": "Log Name", - "自定义日志文件夹名称,用于区分不同任务的日志,留空则自动生成": "Custom log folder name to distinguish logs from different tasks. Leave blank to auto-generate", - "自定义日志文件夹名称,用于区分不同任务的日志,留空则自动生成。支持绝对路径如 /dev/null": "Custom log folder name to distinguish logs from different tasks. Leave blank to auto-generate. Supports absolute paths like /dev/null", - "自定义日志文件夹名称,用于区分不同任务的日志,留空则自动生成。支持 /dev/null 丢弃日志,其他绝对路径必须在日志目录内": "Custom log folder name to distinguish logs from different tasks. Leave blank to auto-generate. Supports /dev/null to discard logs, other absolute paths must be within log directory", - "请输入自定义日志文件夹名称": "Please enter a custom log folder name", - "请输入自定义日志文件夹名称或绝对路径": "Please enter a custom log folder name or absolute path", - "请输入自定义日志文件夹名称或 /dev/null": "Please enter a custom log folder name or /dev/null", - "日志名称只能包含字母、数字、下划线和连字符": "Log name can only contain letters, numbers, underscores and hyphens", - "日志名称不能超过100个字符": "Log name cannot exceed 100 characters", - "未启用": "Not enabled", - "默认为 CPU 个数": "Default is the number of CPUs", - "Minimum is 4": "Minimum is 4", - "实例模式": "Instance Mode", - "单实例模式:定时启动新任务前会自动停止旧任务;多实例模式:允许同时运行多个任务实例": "Single instance mode: automatically stop old task before starting new scheduled task; Multi-instance mode: allow multiple task instances to run simultaneously", - "请选择实例模式": "Please select instance mode", - "单实例": "Single Instance", - "多实例": "Multi-Instance", - "SSH密钥": "SSH Keys", - "别名": "Alias", + "源文件": "Source File", + "激活成功": "Activation successful", + "点击或者拖拽文件到此区域上传": "Click or drag files here to upload", + "父目录": "Parent Directory", + "版本": "Version", + "状态": "Status", + "环境变量": "Environment Variables", + "生成数据中...": "Generating data...", + "用于访问所有私有仓库的全局SSH私钥": "Global SSH private key for accessing all private repositories", + "用户令牌,扫描登录后 我的—>设置->令牌 中获取,参考 https://www.weplusbot.com/": "Token, which can be obtained after scanning and logging in, is available under 'My Account' -> 'Settings' -> 'Tokens'. Please refer to the instructions for detailed steps: https://www.weplusbot.com/", + "用户名": "Username", + "用户名密码/Token": "Username/Password or Token", + "留空自动检测,或输入相对/绝对路径": "Leave blank to auto-detect, or enter a relative/absolute path", + "登录": "Login", + "登录IP": "Login IP", + "登录地址": "Login Address", + "登录已过期,请重新登录": "Login session has expired, please log in again", + "登录成功!": "Login successful!", + "登录日志": "Login Logs", + "登录时间": "Login Time", + "登录状态": "Login Status", + "登录设备": "Login Device", + "白名单": "Whitelist", + "的Secret吗": "'s Secret?", + "知道了": "Got it", + "确认": "Confirm", + "确认保存文件": "Confirm to Save File", + "确认停止": "Confirm to Stop", + "确认停止定时任务": "Confirm to Stop Scheduled Task", + "确认停止实例": "Confirm to Stop Instance", + "确认停止运行实例": "Confirm to stop the running instance", + "确认删除": "Confirm to Delete", + "确认删除SSH密钥": "Confirm to delete SSH key", + "确认删除依赖": "Confirm to delete the dependency", + "确认删除变量": "Confirm to delete the variable", + "确认删除定时任务": "Confirm to Delete Scheduled Task", + "确认删除定时订阅": "Confirm Deletion of Scheduled Subscription", + "确认删除应用": "Confirm to delete the application", + "确认删除视图": "Confirm to delete the view", + "确认删除选中的依赖吗": "Confirm to delete the selected dependencies?", + "确认删除选中的变量吗": "Confirm to delete the selected variables?", + "确认删除选中的定时任务吗": "Confirm to delete the selected scheduled tasks?", + "确认取消安装": "Confirm to cancel install", + "确认密码": "Confirm Password", + "确认离开": "Confirm Leave", + "确认运行": "Confirm to Run", + "确认运行定时任务": "Confirm to Run Scheduled Task", + "确认重启": "Confirm to Restart", + "确认重新安装": "Confirm to reinstall", + "确认重新安装选中的依赖吗": "Confirm to reinstall the selected dependencies?", + "确认重置": "Confirm to reset", + "确认重置应用": "Confirm to reset the application", + "禁用": "Disable", + "私有仓库": "Private Repository", + "私钥": "Private Key", + "秒": "second(s)", + "秒(可选) 分 时 天 月 周": "Seconds (optional) Minutes Hours Day Month Week", + "秒后自动刷新": "seconds and automatically refresh", + "秒后重试": "Retry after seconds", + "空文件": "Empty File", + "空闲中": "Idle", + "第一步": "Step 1", + "第三步": "Step 3", + "第二步": "Step 2", + "筛选条件": "Filter Conditions", + "类型": "Type", + "系统": "System", + "系统信息": "System Information", + "系统安装包下载成功,确认重启": "System installation package downloaded successfully, confirm to restart", + "系统将在": "The system will restart in", + "系统日志": "System Logs", + "系统设置": "System Settings", + "系统资源": "System", + "系统运行": "System Uptime", + "结束时间": "End Time", + "编辑": "Edit", "编辑SSH密钥": "Edit SSH Key", - "创建SSH密钥": "Create SSH Key", - "更新SSH密钥成功": "SSH key updated successfully", - "创建SSH密钥成功": "SSH key created successfully", + "编辑任务": "Edit Task", + "编辑依赖": "Edit Dependency", + "编辑变量": "Edit Variable", + "编辑应用": "Edit Application", + "编辑视图": "Edit View", + "编辑订阅": "Edit Subscription", + "置顶": "Top", + "群晖chat": "Synology Chat", + "群聊": "Group Chat", + "脚本": "Script", + "脚本执行时的工作目录,留空则自动检测。相对路径基于 scripts 目录,也支持绝对路径": "Working directory for script execution. Leave blank for auto-detection. Relative paths are based on the scripts directory. Absolute paths are also supported.", + "脚本文件": "Script files", + "脚本管理": "Script Management", + "自动删除任务": "Automatically Delete Tasks", + "自动拆分": "Auto Split", + "自动添加任务": "Automatically Add Tasks", + "自动生成": "Auto-generated", + "自定义日志文件夹名称,用于区分不同任务的日志,留空则自动生成": "Custom log folder name to distinguish logs from different tasks. Leave blank to auto-generate", + "自定义日志文件夹名称,用于区分不同任务的日志,留空则自动生成。支持 /dev/null 丢弃日志,其他绝对路径必须在日志目录内": "Custom log folder name to distinguish logs from different tasks. Leave blank to auto-generate. Supports /dev/null to discard logs, other absolute paths must be within log directory", + "自定义日志文件夹名称,用于区分不同任务的日志,留空则自动生成。支持绝对路径如 /dev/null": "Custom log folder name to distinguish logs from different tasks. Leave blank to auto-generate. Supports absolute paths like /dev/null", + "自定义通知": "Custom Notification", + "自建的PushMeServer消息接口地址,例如:http://127.0.0.1:3010,不填则使用官方消息接口": "The self built PushMeServer message interface address, for example: http://127.0.0.1:3010 If left blank, use the official message interface", + "要发送的用户昵称或群名,如果目标是群,需要填群名,如果目标是好友,需要填好友昵称": "Enter the recipient's nickname if it's a friend or the group name if it's a group", + "视图名称": "View Name", + "视图管理": "View Management", + "订阅": "Subscription", + "订阅管理": "Subscription Management", + "设置": "Settings", + "访问密钥": "Access Key", + "语言": "Language", + "请": "Please", + "请先按如下方式修复:": "Please fix it as follows:", + "请求体格式key1: value1,多个换行分割。url或者body中必须包含$title,$content可选,对应api内容的位置": "Request body format: key1: value1 (separate multiple keys with line breaks). URL or body must contain $title, $content is optional and corresponds to the API content position.", + "请求头Content-Type": "Request Header Content-Type", + "请求头格式Custom-Header1: Header1,多个换行分割": "Request header format: Custom-Header1: Header1 (separate multiple headers with line breaks)", + "请求方法": "Request Method", + "请求链接以http或者https开头。url或者body中必须包含$title,$content可选,对应api内容的位置": "Request URL should start with http or https. URL or body must contain $title, $content is optional and corresponds to the API content position.", + "请至少输入一个标签": "Please enter at least one tag", + "请输入": "Please input", "请输入SSH密钥别名": "Please enter SSH key alias", "请输入SSH私钥": "Please enter SSH private key", "请输入SSH私钥内容(以 -----BEGIN 开头)": "Please enter SSH private key content (starts with -----BEGIN)", - "确认删除SSH密钥": "Confirm to delete SSH key", - "批量": "Batch", - "全局SSH私钥": "Global SSH Private Key", - "用于访问所有私有仓库的全局SSH私钥": "Global SSH private key for accessing all private repositories", + "请输入任务名称": "Please enter the task name", + "请输入依赖名称": "Please enter the dependency name", + "请输入依赖名称,支持指定版本": "Please enter the dependency name, version specification is supported", + "请输入保存目录,默认scripts目录": "Please enter the save directory, default is 'scripts'", + "请输入内容": "Please enter the content", + "请输入分支": "Please enter the branch", + "请输入名称": "Please enter a name", + "请输入名称/值/备注": "Please enter name/value/remarks", + "请输入名称或者关键词": "Please enter a name or keyword", + "请输入备注": "Please enter remarks", "请输入完整的SSH私钥内容": "Please enter the complete SSH private key content", - "仪表盘": "Dashboard", - "总任务": "Total Tasks", - "今日执行": "Today Runs", - "今日成功": "Success", - "今日失败": "Failed", - "成功率": "Success Rate", - "平均耗时": "Avg Time", - "近 7 日趋势": "7-Day Trend", - "今日耗时 Top 5": "Top 5 by Time", - "今日执行次数 Top 5": "Top 5 by Runs", - "实时运行态": "Runtime", - "系统资源": "System", - "排队中": "Queued", - "暂无运行中任务": "No running tasks", - "暂无数据": "No data", - "总执行": "Total", - "次数": "Runs", - "最长单次": "Max Time", - "已运行": "Elapsed", - "系统运行": "System Uptime", - "内存使用": "Memory", - "堆内存": "Heap", - "CPU 核心": "CPU Cores", + "请输入密码或者Token": "Please enter the password or Token", + "请输入应用名称": "Please enter the application name", + "请输入文件名": "Please enter the file name", + "请输入文件后缀": "Please enter the file extension", + "请输入文件夹名": "Please enter the folder name", + "请输入新名称": "Please enter a new name", + "请输入新的环境变量名称": "Please enter the new environment variable name", + "请输入日志名": "Please enter the log name", + "请输入环境变量值": "Please enter the environment variable value", + "请输入环境变量名称": "Please enter the environment variable name", + "请输入私钥": "Please enter the private key", + "请输入脚本依赖文件关键词,多个关键词竖线分割": "Please enter script dependency file keywords, multiple keywords separated by vertical lines (|)", + "请输入脚本名": "Please enter the script name", + "请输入脚本筛选白名单关键词,多个关键词竖线分割": "Please enter script filtering whitelist keywords, multiple keywords separated by vertical lines (|)", + "请输入脚本筛选黑名单关键词,多个关键词竖线分割": "Please enter script filtering blacklist keywords, multiple keywords separated by vertical lines (|)", + "请输入自定义日志文件夹名称": "Please enter a custom log folder name", + "请输入自定义日志文件夹名称或 /dev/null": "Please enter a custom log folder name or /dev/null", + "请输入自定义日志文件夹名称或绝对路径": "Please enter a custom log folder name or absolute path", + "请输入要发送的目标": "Please enter the recipient's name (group or friend)", + "请输入视图名称": "Please enter the view name", + "请输入订阅链接": "Please enter the subscription link", + "请输入认证用户名": "Please enter the authentication username", + "请输入运行任务前要执行的命令,不能包含 task 命令": "Please enter the command to run before executing the task, cannot contain task commands", + "请输入运行任务后要执行的命令,不能包含 task 命令": "Please enter the command to run after executing the task, cannot contain task commands", + "请输入运行订阅前要执行的命令": "Please enter the command to run before executing the subscription", + "请输入运行订阅后要执行的命令": "Please enter the command to run after executing the subscription", + "请选择": "Please select", + "请选择实例模式": "Please select instance mode", + "请选择操作符": "Please select operator", + "请选择日志": "Please select a log", + "请选择日志文件": "Please select a log file", + "请选择模块权限": "Please select module permissions", + "请选择父目录": "Please select a parent directory", + "请选择脚本": "Please select a script", + "请选择脚本文件": "Please select a script file", + "请选择通知方式": "Please select a notification method", + "调用版本;专业版填写pro,个人版填写personal,为空默认使用专业版": "Version, you can specify 'pro' for the Professional version and 'personal' for the Personal version. If left blank, it will default to the Professional version.", + "调试": "Debug", "负载 1m": "Load 1m", - "平台": "Platform", - "24小时未运行": "Idle 24h+", - "标签统计": "Label Stats", - "任务数": "Tasks", - "内存": "Memory" + "账户设置": "Account Settings", + "跟随系统": "Follow System", + "跳过": "Skip", + "输入后回车增加自定义选项": "Press Enter to add custom options", + "输入手机应用上的6位数字": "Enter the 6-digit code from the mobile app", + "运行": "Run", + "运行中": "Running", + "运行任务前执行的命令,比如 cp/mv/python3 xxx.py/node xxx.js": "Run commands before executing the task, e.g., cp/mv/python3 xxx.py/node xxx.js", + "运行任务后执行的命令,比如 cp/mv/python3 xxx.py/node xxx.js": "Run commands after executing the task, e.g., cp/mv/python3 xxx.py/node xxx.js", + "运行实例": "Running Instances", + "运行订阅前执行的命令,比如 cp/mv/python3 xxx.py/node xxx.js": "Run commands before executing the subscription, e.g., cp/mv/python3 xxx.py/node xxx.js", + "运行订阅后执行的命令,比如 cp/mv/python3 xxx.py/node xxx.js": "Run commands after executing the subscription, e.g., cp/mv/python3 xxx.py/node xxx.js", + "运行设置": "Run Settings", + "近 7 日趋势": "7-Day Trend", + "返回首页": "Return to Home", + "还原数据": "Restore Data", + "远程仓库缓存": "Remote repository cache", + "远程脚本缓存": "Remote script cache", + "退出": "Exit", + "退出登录": "Logout", + "退出编辑": "Exit Editing", + "选中的变量吗": "selected variables?", + "选中的定时任务吗": "selected scheduled tasks?", + "选择备份模块": "Select backup module", + "通知关闭成功": "Notification closed successfully", + "通知发送成功": "Notification sent successfully", + "通知方式": "Notification Method", + "通知设置": "Notification Settings", + "邮箱": "Email", + "邮箱地址": "Email Address", + "邮箱服务名称,比如126、163、Gmail、QQ等,支持列表https://github.com/nodemailer/nodemailer/blob/master/lib/well-known/services.json": "Email service name, e.g., 126, 163, Gmail, QQ, etc. Supported list: https://github.com/nodemailer/nodemailer/blob/master/lib/well-known/services.json", + "配置文件": "Configuration Files", + "重启": "Restart", + "重命名": "Rename", + "重新下载": "Redownload", + "重新启动": "Reboot", + "重新安装": "Reinstall", + "重置Secret会让当前应用所有token失效": "Resetting the Secret will invalidate all tokens for the current application", + "重置secret": "Reset secret", + "重置成功": "Reset successful", + "钉钉机器人": "DingTalk Bot", + "钉钉机器人webhook token,例如:5a544165465465645d0f31dca676e7bd07415asdasd": "DingTalk Bot webhook token, e.g., 5a544165465465645d0f31dca676e7bd07415asdasd", + "链接": "Link", + "错误": "Error", + "错误日志": "Error Log", + "队列中": "In Queue", + "青龙": "Qinglong", + "项": "items", + "顺序": "Order", + "飞书机器人": "Feishu Bot", + "飞书群组机器人加签密钥,安全设置中开启签名校验后获得": "Feishu group bot signature secret, obtained after enabling signature verification in security settings", + "飞书群组机器人:https://www.feishu.cn/hc/zh-CN/articles/360024984973": "Feishu group bot: https://www.feishu.cn/hc/zh-CN/articles/360024984973", + "验证": "Verify", + "验证失败": "Validation failed", + "验证码": "Verification Code", + "验证码为6位数字": "Verification code is a 6-digit number", + "黑名单": "Blacklist", + "默认为 CPU 个数": "Default is the number of CPUs", + ",保存后不可恢复": ", it can't be recovered after saving.", + ",删除后不可恢复": ", it can't be recovered after deletion" } diff --git a/src/locales/zh-CN.json b/src/locales/zh-CN.json index 5ac2a89c..14b03eee 100644 --- a/src/locales/zh-CN.json +++ b/src/locales/zh-CN.json @@ -1,592 +1,598 @@ { - "复制成功": "复制成功", - "复制": "复制", - "新建": "新建", - "登录": "登录", - "初始化": "初始化", - "错误": "错误", - "定时任务": "定时任务", - "订阅管理": "订阅管理", - "环境变量": "环境变量", - "配置文件": "配置文件", - "脚本管理": "脚本管理", - "依赖管理": "依赖管理", - "日志管理": "日志管理", - "对比工具": "对比工具", - "系统设置": "系统设置", - "退出登录": "退出登录", - "青龙": "青龙", - "返回首页": "返回首页", - "保存": "保存", - "日志": "日志", - "脚本": "脚本", - "确认保存文件": "确认保存文件", - ",保存后不可恢复": ",保存后不可恢复", - "确认运行": "确认运行", - "确认运行定时任务": "确认运行定时任务", - "吗": "吗", - "确认停止": "确认停止", - "确认停止定时任务": "确认停止定时任务", - "确认": "确认", - "任务": "任务", - "状态": "状态", - "空闲中": "空闲中", - "运行中": "运行中", - "队列中": "队列中", - "已禁用": "已禁用", - "定时": "定时", - "最后运行时间": "最后运行时间", - "最后运行时长": "最后运行时长", - "下次运行时间": "下次运行时间", - "名称": "名称", - "命令/脚本": "命令/脚本", - "定时规则": "定时规则", - "操作": "操作", - "确认删除": "确认删除", - "确认删除定时任务": "确认删除定时任务", - "编辑": "编辑", - "删除": "删除", - "确认删除选中的定时任务吗": "确认删除选中的定时任务吗", - "选中的定时任务吗": "选中的定时任务吗", - "创建视图": "创建视图", - "视图管理": "视图管理", - "请输入名称或者关键词": "请输入名称或者关键词", - "创建任务": "创建任务", - "更多": "更多", - "批量删除": "批量删除", - "批量启用": "批量启用", - "批量禁用": "批量禁用", - "批量运行": "批量运行", - "批量停止": "批量停止", - "批量置顶": "批量置顶", - "批量取消置顶": "批量取消置顶", - "批量修改标签": "批量修改标签", - "已选择": "已选择", - "项": "项", - "知道了": "知道了", - "请输入任务名称": "请输入任务名称", - "支持输入脚本路径/任意系统可执行命令/task 脚本路径": "支持输入脚本路径/任意系统可执行命令/task 脚本路径", - "秒(可选) 分 时 天 月 周": "秒(可选) 分 时 天 月 周", - "标签": "标签", - "取消": "取消", - "添加": "添加", - "启用": "启用", - "禁用": "禁用", - "运行": "运行", - "停止": "停止", - "置顶": "置顶", - "取消置顶": "取消置顶", - "命令": "命令", - "包含": "包含", - "不包含": "不包含", - "属于": "属于", - "不属于": "不属于", - "顺序": "顺序", - "倒序": "倒序", - "且": "且", - "或": "或", - "输入后回车增加自定义选项": "输入后回车增加自定义选项", - "视图名称": "视图名称", - "请输入视图名称": "请输入视图名称", - "请输入内容": "请输入内容", - "新增筛选条件": "新增筛选条件", - "新增排序方式": "新增排序方式", - "类型": "类型", - "显示": "显示", - "确认删除视图": "确认删除视图", - "安装中": "安装中", - "已安装": "已安装", - "安装失败": "安装失败", - "删除中": "删除中", - "已删除": "已删除", - "删除失败": "删除失败", - "已取消": "已取消", - "序号": "序号", - "备注": "备注", - "更新时间": "更新时间", - "创建时间": "创建时间", - "确认删除依赖": "确认删除依赖", - "确认重新安装": "确认重新安装", - "确认取消安装": "确认取消安装", - "确认删除选中的依赖吗": "确认删除选中的依赖吗", - "确认重新安装选中的依赖吗": "确认重新安装选中的依赖吗", - "请输入名称": "请输入名称", - "创建依赖": "创建依赖", - "批量安装": "批量安装", - "批量强制删除": "批量强制删除", - "日志 -": "日志 -", - "依赖类型": "依赖类型", - "自动拆分": "自动拆分", - "多个依赖是否换行分割": "多个依赖是否换行分割", - "是": "是", - "否": "否", - "请输入依赖名称,支持指定版本": "请输入依赖名称,支持指定版本", - "请输入依赖名称": "请输入依赖名称", - "请输入备注": "请输入备注", - "源文件": "源文件", - "当前文件": "当前文件", - "修改环境变量名称": "修改环境变量名称", - "请输入新的环境变量名称": "请输入新的环境变量名称", - "已启用": "已启用", - "值": "值", - "确认删除变量": "确认删除变量", - "确认删除选中的变量吗": "确认删除选中的变量吗", - "选中的变量吗": "选中的变量吗", - "请输入名称/值/备注": "请输入名称/值/备注", - "导入": "导入", - "创建变量": "创建变量", - "批量修改变量名称": "批量修改变量名称", - "批量导出": "批量导出", - "请输入环境变量名称": "请输入环境变量名称", - "只能输入字母数字下划线,且不能以数字开头": "只能输入字母数字下划线,且不能以数字开头", - "请输入环境变量值": "请输入环境变量值", - "服务启动超时": "服务启动超时", - "请先按如下方式修复:": "请先按如下方式修复:", "1. 宿主机执行 docker run --rm -v\n /var/run/docker.sock:/var/run/docker.sock\n containrrr/watchtower -cR <容器名>": "1. 宿主机执行 docker run --rm -v\n /var/run/docker.sock:/var/run/docker.sock\n containrrr/watchtower -cR <容器名>", "2. 容器内执行 ql check、ql update": "2. 容器内执行 ql check、ql update", + "24小时未运行": "24小时未运行", "3. 如果无法解决,容器内执行 pm2 logs,拷贝执行结果": "3. 如果无法解决,容器内执行 pm2 logs,拷贝执行结果", - "提交 issue": "提交 issue", - "启动中,请稍后...": "启动中,请稍后...", - "欢迎使用": "欢迎使用", - "欢迎使用青龙": "欢迎使用青龙", - "支持python3、javascript、shell、typescript 的定时任务管理面板": "支持python3、javascript、shell、typescript 的定时任务管理面板", - "开始安装": "开始安装", - "账户设置": "账户设置", - "用户名": "用户名", - "密码": "密码", - "密码不能为admin": "密码不能为admin", - "确认密码": "确认密码", - "您输入的两个密码不匹配!": "您输入的两个密码不匹配!", - "提交": "提交", - "通知设置": "通知设置", - "通知方式": "通知方式", - "请选择通知方式": "请选择通知方式", - "跳过": "跳过", - "完成安装": "完成安装", - "恭喜安装完成!": "恭喜安装完成!", - "Telegram频道": "Telegram频道", - "去登录": "去登录", - "初始化配置": "初始化配置", - "文件": "文件", - ",删除后不可恢复": ",删除后不可恢复", - "请选择日志": "请选择日志", - "请输入日志名": "请输入日志名", - "暂无日志": "暂无日志", - "登录成功!": "登录成功!", - "上次登录时间:": "上次登录时间:", - "上次登录地点:": "上次登录地点:", - "上次登录IP:": "上次登录IP:", - "上次登录设备:": "上次登录设备:", - "上次登录状态:": "上次登录状态:", - "验证码": "验证码", - "验证码为6位数字": "验证码为6位数字", "6位数字": "6位数字", - "验证": "验证", - "请": "请", - "秒后重试": "秒后重试", - "在您的设备上打开两步验证应用程序以查看您的身份验证代码并验证您的身份。": "在您的设备上打开两步验证应用程序以查看您的身份验证代码并验证您的身份。", - "请选择脚本文件": "请选择脚本文件", - "当前文件不支持预览": "当前文件不支持预览", - "清空日志": "清空日志", - "设置": "设置", - "退出": "退出", - "空文件": "空文件", - "本地文件": "本地文件", - "文件夹": "文件夹", - "文件名": "文件名", - "请输入文件名": "请输入文件名", - "文件名不能包含斜杠": "文件名不能包含斜杠", - "文件夹名": "文件夹名", - "请输入文件夹名": "请输入文件夹名", - "父目录": "父目录", - "请选择父目录": "请选择父目录", - "点击或者拖拽文件到此区域上传": "点击或者拖拽文件到此区域上传", - "当前修改未保存,确定离开吗": "当前修改未保存,确定离开吗", - "退出编辑": "退出编辑", - "重命名": "重命名", - "请选择脚本": "请选择脚本", - "调试": "调试", - "请输入脚本名": "请输入脚本名", - "暂无脚本": "暂无脚本", - "请输入新名称": "请输入新名称", - "保存文件": "保存文件", - "保存目录": "保存目录", - "请输入保存目录,默认scripts目录": "请输入保存目录,默认scripts目录", - "运行设置": "运行设置", - "待开发": "待开发", - "开发版": "开发版", - "正式版": "正式版", - "版本": "版本", - "更新日志": "更新日志", - "查看": "查看", - "提交BUG": "提交BUG", - "名称不能为保留关键字": "名称不能为保留关键字", - "请输入应用名称": "请输入应用名称", - "权限": "权限", - "请选择模块权限": "请选择模块权限", - "更新": "更新", - "已经是最新版了!": "已经是最新版了!", - "是目前检测到的最新可用版本了。": "是目前检测到的最新可用版本了。", - "重新下载": "重新下载", - "更新可用": "更新可用", - "新版本": "新版本", - "可用,你使用的版本为": "可用,你使用的版本为", - "下载更新": "下载更新", - "以后再说": "以后再说", - "下载更新中...": "下载更新中...", - "确认重启": "确认重启", - "系统安装包下载成功,确认重启": "系统安装包下载成功,确认重启", - "重启": "重启", - "系统将在": "系统将在", - "秒后自动刷新": "秒后自动刷新", - "检查更新": "检查更新", - "重新启动": "重新启动", - "确认删除应用": "确认删除应用", - "确认重置": "确认重置", - "确认重置应用": "确认重置应用", - "的Secret吗": "的Secret吗", - "重置Secret会让当前应用所有token失效": "重置Secret会让当前应用所有token失效", - "创建应用": "创建应用", - "安全设置": "安全设置", - "应用设置": "应用设置", - "登录日志": "登录日志", - "其他设置": "其他设置", - "关于": "关于", - "成功": "成功", - "失败": "失败", - "登录时间": "登录时间", - "登录地址": "登录地址", - "登录IP": "登录IP", - "登录设备": "登录设备", - "登录状态": "登录状态", - "亮色": "亮色", - "暗色": "暗色", - "跟随系统": "跟随系统", - "备份数据上传成功,确认覆盖数据": "备份数据上传成功,确认覆盖数据", - "主题设置": "主题设置", - "日志删除频率": "日志删除频率", - "每x天自动删除x天以前的日志": "每x天自动删除x天以前的日志", - "每": "每", - "天": "天", - "定时任务并发数": "定时任务并发数", - "数据备份还原": "数据备份还原", - "还原数据": "还原数据", - "第一步": "第一步", - "下载两步验证手机应用,比如 Google Authenticator 、": "下载两步验证手机应用,比如 Google Authenticator 、", - "第二步": "第二步", - "使用手机应用扫描二维码,或者输入秘钥": "使用手机应用扫描二维码,或者输入秘钥", - "第三步": "第三步", - "输入手机应用上的6位数字": "输入手机应用上的6位数字", - "完成设置": "完成设置", - "修改用户名密码": "修改用户名密码", - "两步验证": "两步验证", - "头像": "头像", - "更换头像": "更换头像", - "时": "时", - "分": "分", - "秒": "秒", - "私有仓库": "私有仓库", - "公开仓库": "公开仓库", - "单文件": "单文件", - "链接": "链接", - "分支": "分支", - "确认删除定时订阅": "确认删除定时订阅", - "定时订阅": "定时订阅", - "创建订阅": "创建订阅", - "私钥": "私钥", - "请输入私钥": "请输入私钥", - "请输入认证用户名": "请输入认证用户名", - "Github已不支持密码认证,请使用Token方式": "Github已不支持密码认证,请使用Token方式", - "密码/Token": "密码/Token", - "请输入密码或者Token": "请输入密码或者Token", - "支持拷贝 ql repo/raw 命令,粘贴导入": "支持拷贝 ql repo/raw 命令,粘贴导入", - "请输入订阅链接": "请输入订阅链接", - "请输入分支": "请输入分支", - "唯一值": "唯一值", - "唯一值用于日志目录和私钥别名": "唯一值用于日志目录和私钥别名", - "自动生成": "自动生成", - "拉取方式": "拉取方式", - "用户名密码/Token": "用户名密码/Token", - "定时类型": "定时类型", - "白名单": "白名单", - "多个关键词竖线分割,支持正则表达式": "多个关键词竖线分割,支持正则表达式", - "请输入脚本筛选白名单关键词,多个关键词竖线分割": "请输入脚本筛选白名单关键词,多个关键词竖线分割", - "黑名单": "黑名单", - "请输入脚本筛选黑名单关键词,多个关键词竖线分割": "请输入脚本筛选黑名单关键词,多个关键词竖线分割", - "依赖文件": "依赖文件", - "请输入脚本依赖文件关键词,多个关键词竖线分割": "请输入脚本依赖文件关键词,多个关键词竖线分割", - "文件后缀": "文件后缀", - "仓库需要拉取的文件后缀,多个后缀空格分隔,默认使用配置文件中的RepoFileExtensions": "仓库需要拉取的文件后缀,多个后缀空格分隔,默认使用配置文件中的RepoFileExtensions", - "请输入文件后缀": "请输入文件后缀", - "执行前": "执行前", - "运行订阅前执行的命令,比如 cp/mv/python3 xxx.py/node xxx.js": "运行订阅前执行的命令,比如 cp/mv/python3 xxx.py/node xxx.js", - "请输入运行订阅前要执行的命令": "请输入运行订阅前要执行的命令", - "执行后": "执行后", - "运行订阅后执行的命令,比如 cp/mv/python3 xxx.py/node xxx.js": "运行订阅后执行的命令,比如 cp/mv/python3 xxx.py/node xxx.js", - "请输入运行订阅后要执行的命令": "请输入运行订阅后要执行的命令", - "代理": "代理", - "公开仓库支持HTTP/SOCK5代理,私有仓库支持SOCK5代理": "公开仓库支持HTTP/SOCK5代理,私有仓库支持SOCK5代理", - "自动添加任务": "自动添加任务", - "自动删除任务": "自动删除任务", - "中文": "中文", - "系统信息": "系统信息", - "Server酱": "Server酱", - "Telegram机器人": "Telegram机器人", - "钉钉机器人": "钉钉机器人", - "企业微信机器人": "企业微信机器人", - "企业微信应用": "企业微信应用", - "智能微秘书": "智能微秘书", - "群晖chat": "群晖chat", - "微加机器人": "微加机器人", - "邮箱": "邮箱", - "飞书机器人": "飞书机器人", - "自定义通知": "自定义通知", - "已关闭": "已关闭", - "gotify的url地址,例如 https://push.example.de:8080": "gotify的url地址,例如 https://push.example.de:8080", - "gotify的消息应用token码": "gotify的消息应用token码", - "推送消息的优先级": "推送消息的优先级", - "synologyChat的url地址": "synologyChat的webhook url地址", - "chat的token码": "chat的token码", - "推送到个人QQ: http://127.0.0.1/send_private_msg,群:http://127.0.0.1/send_group_msg": "推送到个人QQ: http://127.0.0.1/send_private_msg,群:http://127.0.0.1/send_group_msg", - "访问密钥": "访问密钥", - "如果GOBOT_URL设置 /send_private_msg 则需要填入 user_id=个人QQ 相反如果是 /send_group_msg 则需要填入 group_id=QQ群": "如果GOBOT_URL设置 /send_private_msg 则需要填入 user_id=个人QQ 相反如果是 /send_group_msg 则需要填入 group_id=QQ群", - "Server酱SENDKEY": "Server 酱 SENDKEY,https://sct.ftqq.com/r/13363", - "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", - "Bark的信息IP/设备码,例如:https://api.day.app/XXXXXXXX": "Bark的信息IP/设备码,例如:https://api.day.app/XXXXXXXX", "BARK推送图标,自定义推送图标 (需iOS15或以上才能显示)": "BARK推送图标,自定义推送图标 (需iOS15或以上才能显示)", - "BARK推送铃声,铃声列表去APP查看复制填写": "BARK推送铃声,铃声列表去APP查看复制填写", "BARK推送消息的分组,默认为qinglong": "BARK推送消息的分组,默认为qinglong", "BARK推送消息的时效性,默认为active": "BARK推送消息的时效性,默认为active", "BARK推送消息的跳转URL": "BARK推送消息的跳转URL", + "BARK推送铃声,铃声列表去APP查看复制填写": "BARK推送铃声,铃声列表去APP查看复制填写", "BARK是否保存推送消息": "BARK是否保存推送消息", + "Bark的信息IP/设备码,例如:https://api.day.app/XXXXXXXX": "Bark的信息IP/设备码,例如:https://api.day.app/XXXXXXXX", + "CPU 核心": "CPU 核心", + "Chronocat Red 服务的连接地址 https://chronocat.vercel.app/install/docker/official/": "Chronocat Red 服务的连接地址 https://chronocat.vercel.app/install/docker/official/", + "Cron表达式格式有误": "Cron表达式格式有误", + "Github已不支持密码认证,请使用Token方式": "Github已不支持密码认证,请使用Token方式", + "Linux 软件包镜像源": "Linux 软件包镜像源", + "NPM 镜像源": "NPM 镜像源", + "Node 软件包镜像源": "Node 软件包镜像源", + "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", + "PushMe的Key,https://push.i-i.me/": "PushMe的Key,https://push.i-i.me/", + "PyPI 镜像源": "PyPI 镜像源", + "Python 软件包镜像源": "Python 软件包镜像源", + "SMTP 登录密码,也可能为特殊口令,视具体邮件服务商说明而定": "SMTP 登录密码,也可能为特殊口令,视具体邮件服务商说明而定", + "SSH 文件缓存": "SSH 文件缓存", + "SSH密钥": "SSH密钥", + "Server酱": "Server酱", + "Server酱SENDKEY": "Server 酱 SENDKEY,https://sct.ftqq.com/r/13363", + "Subscription表达式格式有误": "Subscription表达式格式有误", + "Telegram机器人": "Telegram机器人", + "Telegram频道": "Telegram频道", + "alpine linux 镜像源": "alpine linux 镜像源", + "chat的token码": "chat的token码", + "corpid、corpsecret、touser(注:多个成员ID使用|隔开)、agentid、消息类型(选填,不填默认文本消息类型) 注意用,号隔开(英文输入法的逗号),例如:wwcfrs,B-76WERQ,qinglong,1000001,2COat": "corpid,corpsecret,touser(注:多个成员ID使用|隔开),agentid,消息类型(选填,不填默认文本消息类型) 注意用,号隔开(英文输入法的逗号),例如:wwcfrs,B-76WERQ,qinglong,1000001,2COat", + "docker安装在持久化config目录下的chronocat.yml文件可找到": "docker安装在持久化config目录下的chronocat.yml文件可找到", + "gotify的url地址,例如 https://push.example.de:8080": "gotify的url地址,例如 https://push.example.de:8080", + "gotify的消息应用token码": "gotify的消息应用token码", + "iGot的信息推送key,例如:https://push.hellyw.com/XXXXXXXX": "iGot的信息推送key,例如:https://push.hellyw.com/XXXXXXXX", + "ntfy应用token": "ntfy应用token,参考 https://docs.ntfy.sh/config/#access-tokens", + "ntfy应用topic": "ntfy应用topic", + "ntfy应用密码": "ntfy应用密码,参考 https://docs.ntfy.sh/config/#users-and-roles", + "ntfy应用用户名": "ntfy应用用户名,参考 https://docs.ntfy.sh/config/#users-and-roles", + "ntfy用户动作": "ntfy用户动作,最多三个动作,参考 https://docs.ntfy.sh/publish/?h=actions#action-buttons", + "ntfy的url地址,例如 https://ntfy.sh": "ntfy的url地址,例如 https://ntfy.sh", + "synologyChat的url地址": "synologyChat的webhook url地址", + "telegram api自建的反向代理地址,默认tg官方api": "telegram api自建的反向代理地址,默认tg官方api", + "telegram代理配置认证参数,用户名与密码用英文冒号连接 user:password": "telegram代理配置认证参数, 用户名与密码用英文冒号连接 user:password", "telegram机器人的token,例如:1077xxx4424:AAFjv0FcqxxxxxxgEMGfi22B4yh15R5uw": "telegram机器人的token,例如:1077xxx4424:AAFjv0FcqxxxxxxgEMGfi22B4yh15R5uw", "telegram用户的id,例如:129xxx206": "telegram用户的id,例如:129xxx206", - "代理IP": "代理IP", - "代理端口": "代理端口", - "telegram代理配置认证参数,用户名与密码用英文冒号连接 user:password": "telegram代理配置认证参数, 用户名与密码用英文冒号连接 user:password", - "telegram api自建的反向代理地址,默认tg官方api": "telegram api自建的反向代理地址,默认tg官方api", - "钉钉机器人webhook token,例如:5a544165465465645d0f31dca676e7bd07415asdasd": "钉钉机器人webhook token,例如:5a544165465465645d0f31dca676e7bd07415asdasd", - "密钥,机器人安全设置页面,加签一栏下面显示的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", - "企业微信代理地址": "企业微信代理地址", - "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", - "发送的目标,群组或者好友": "发送的目标,群组或者好友", - "请输入要发送的目标": "请输入要发送的目标", - "群聊": "群聊", - "好友": "好友", - "要发送的用户昵称或群名,如果目标是群,需要填群名,如果目标是好友,需要填好友昵称": "要发送的用户昵称或群名,如果目标是群,需要填群名,如果目标是好友,需要填好友昵称", - "iGot的信息推送key,例如:https://push.hellyw.com/XXXXXXXX": "iGot的信息推送key,例如:https://push.hellyw.com/XXXXXXXX", - "微信扫码登录后一对一推送或一对多推送下面的token(您的Token),不提供PUSH_PLUS_USER则默认为一对一推送,参考 https://www.pushplus.plus/": "微信扫码登录后一对一推送或一对多推送下面的token(你的Token),不提供PUSH_PLUS_USER则默认为一对一推送,参考 https://www.pushplus.plus/", - "一对多推送的“群组编码”(一对多推送下面->您的群组(如无则创建)->群组编码,如果您是创建群组人。也需点击“查看二维码”扫描绑定,否则不能接受群组消息推送)": "一对多推送的“群组编码”(一对多推送下面->您的群组(如无则创建)->群组编码,如果您是创建群组人。也需点击“查看二维码”扫描绑定,否则不能接受群组消息推送)", - "发送模板": "发送模板,支持html,txt,json,markdown,cloudMonitor,jenkins,route,pay", - "发送渠道": "发送渠道,支持wechat,webhook,cp,mail,sms", "webhook编码": "webhook编码,可在pushplus公众号上扩展配置出更多渠道", - "发送结果回调地址": "发送结果回调地址,会把推送最终结果通知到这个地址上", - "好友令牌": "好友令牌,微信公众号渠道填写好友令牌,企业微信渠道填写企业微信用户id", - "用户令牌,扫描登录后 我的—>设置->令牌 中获取,参考 https://www.weplusbot.com/": "用户令牌,扫描登录后 我的—>设置->令牌 中获取,参考 https://www.weplusbot.com/", - "消息接收人": "消息接收人", - "调用版本;专业版填写pro,个人版填写personal,为空默认使用专业版": "调用版本;专业版填写pro,个人版填写personal,为空默认使用专业版", - "飞书群组机器人:https://www.feishu.cn/hc/zh-CN/articles/360024984973": "飞书群组机器人:https://www.feishu.cn/hc/zh-CN/articles/360024984973", - "飞书群组机器人加签密钥,安全设置中开启签名校验后获得": "飞书群组机器人加签密钥,安全设置中开启签名校验后获得", - "邮箱服务名称,比如126、163、Gmail、QQ等,支持列表https://github.com/nodemailer/nodemailer/blob/master/lib/well-known/services.json": "邮箱服务名称,比如126、163、Gmail、QQ等,支持列表https://github.com/nodemailer/nodemailer/blob/master/lib/well-known/services.json", - "邮箱地址": "邮箱地址", - "SMTP 登录密码,也可能为特殊口令,视具体邮件服务商说明而定": "SMTP 登录密码,也可能为特殊口令,视具体邮件服务商说明而定", - "PushMe的Key,https://push.i-i.me/": "PushMe的Key,https://push.i-i.me/", - "自建的PushMeServer消息接口地址,例如:http://127.0.0.1:3010,不填则使用官方消息接口": "自建的PushMeServer消息接口地址,例如:http://127.0.0.1:3010,不填则使用官方消息接口", - "ntfy的url地址,例如 https://ntfy.sh": "ntfy的url地址,例如 https://ntfy.sh", - "ntfy应用topic": "ntfy应用topic", - "ntfy应用token": "ntfy应用token,参考 https://docs.ntfy.sh/config/#access-tokens", - "ntfy应用用户名": "ntfy应用用户名,参考 https://docs.ntfy.sh/config/#users-and-roles", - "ntfy应用密码": "ntfy应用密码,参考 https://docs.ntfy.sh/config/#users-and-roles", - "ntfy用户动作": "ntfy用户动作,最多三个动作,参考 https://docs.ntfy.sh/publish/?h=actions#action-buttons", "wxPusherBot的appToken": "wxPusherBot的appToken, 按照文档获取 https://wxpusher.zjiecode.com/docs/", "wxPusherBot的topicIds": "wxPusherBot的topicIds, topicIds 和 uids 至少配置一个才行", "wxPusherBot的uids": "wxPusherBot的uids, topicIds 和 uids 至少配置一个才行", - "请求方法": "请求方法", - "请求头Content-Type": "请求头Content-Type", - "请求链接以http或者https开头。url或者body中必须包含$title,$content可选,对应api内容的位置": "请求链接以http或者https开头。url或者body中必须包含$title,$content可选,对应api内容的位置", - "请求头格式Custom-Header1: Header1,多个换行分割": "请求头格式Custom-Header1: Header1,多个换行分割", - "请求体格式key1: value1,多个换行分割。url或者body中必须包含$title,$content可选,对应api内容的位置": "请求体格式key1: value1,多个换行分割。url或者body中必须包含$title,$content可选,对应api内容的位置", - "错误日志": "错误日志", - "执行结束": "执行结束", - "备份": "备份", - "生成数据中...": "生成数据中...", - "请选择日志文件": "请选择日志文件", - "筛选条件": "筛选条件", - "系统": "系统", - "个人": "个人", - "重新安装": "重新安装", - "取消安装": "取消安装", - "强制删除": "强制删除", - "全部任务": "全部任务", - "关联订阅": "关联订阅", - "订阅": "订阅", - "创建": "创建", - "同时删除关联任务和脚本": "同时删除关联任务和脚本", - "未找到": "未找到", - "保存成功": "保存成功", - "删除成功": "删除成功", - "批量删除成功": "批量删除成功", - "启动中...": "启动中...", - "任务未运行": "任务未运行", - "更新任务成功": "更新任务成功", - "创建任务成功": "创建任务成功", - "编辑任务": "编辑任务", - "Cron表达式格式有误": "Cron表达式格式有误", - "添加Labels成功": "添加Labels成功", - "删除Labels成功": "删除Labels成功", - "添加标签成功": "添加标签成功", - "删除标签成功": "删除标签成功", - "请至少输入一个标签": "请至少输入一个标签", - "编辑视图": "编辑视图", - "排序方式": "排序方式", - "开始时间": "开始时间", - "安装": "安装", - "结束时间": "结束时间", - "编辑依赖": "编辑依赖", - "更新环境变量名称成功": "更新环境变量名称成功", - "更新变量成功": "更新变量成功", - "创建变量成功": "创建变量成功", - "编辑变量": "编辑变量", - "加载中...": "加载中...", - "夹下所有日志": "夹下所有日志", - "创建文件夹成功": "创建文件夹成功", - "创建文件成功": "创建文件成功", - "夹及其子文件": "夹及其子文件", - "更新名称成功": "更新名称成功", - "保存文件成功": "保存文件成功", - "更新应用成功": "更新应用成功", - "创建应用成功": "创建应用成功", - "编辑应用": "编辑应用", - "检查更新中...": "检查更新中...", - "失败,请检查": "失败,请检查", - "更新失败,请检查网络及日志或稍后再试": "更新失败,请检查网络及日志或稍后再试", - "更新包下载成功": "更新包下载成功", - "重置secret": "重置secret", - "重置成功": "重置成功", - "通知发送成功": "通知发送成功", - "通知关闭成功": "通知关闭成功", - "测试中...": "测试中...", - "上传": "上传", - "下载": "下载", - "更新成功": "更新成功", - "激活成功": "激活成功", - "验证失败": "验证失败", - "更新订阅成功": "更新订阅成功", - "创建订阅成功": "创建订阅成功", - "编辑订阅": "编辑订阅", - "Subscription表达式格式有误": "Subscription表达式格式有误", + "一对多推送的“群组编码”(一对多推送下面->您的群组(如无则创建)->群组编码,如果您是创建群组人。也需点击“查看二维码”扫描绑定,否则不能接受群组消息推送)": "一对多推送的“群组编码”(一对多推送下面->您的群组(如无则创建)->群组编码,如果您是创建群组人。也需点击“查看二维码”扫描绑定,否则不能接受群组消息推送)", "一对多推送的“群组编码”(一对多推送下面->您的群组(如无则新建)->群组编码,如果您是创建群组人。也需点击“查看二维码”扫描绑定,否则不能接受群组消息推送)": "一对多推送的“群组编码”(一对多推送下面->您的群组(如无则新建)->群组编码,如果您是创建群组人。也需点击“查看二维码”扫描绑定,否则不能接受群组消息推送)", - "登录已过期,请重新登录": "登录已过期,请重新登录", - "系统日志": "系统日志", - "主题": "主题", - "语言": "语言", - "中...": "中...", - "请选择操作符": "请选择操作符", - "新增定时规则": "新增定时规则", - "运行任务前执行的命令,比如 cp/mv/python3 xxx.py/node xxx.js": "运行任务前执行的命令,比如 cp/mv/python3 xxx.py/node xxx.js", - "运行任务后执行的命令,比如 cp/mv/python3 xxx.py/node xxx.js": "运行任务后执行的命令,比如 cp/mv/python3 xxx.py/node xxx.js", - "请输入运行任务前要执行的命令,不能包含 task 命令": "请输入运行任务前要执行的命令,不能包含 task 命令", - "请输入运行任务后要执行的命令,不能包含 task 命令": "请输入运行任务后要执行的命令,不能包含 task 命令", + "上传": "上传", + "上次登录IP:": "上次登录IP:", + "上次登录地点:": "上次登录地点:", + "上次登录时间:": "上次登录时间:", + "上次登录状态:": "上次登录状态:", + "上次登录设备:": "上次登录设备:", + "下次运行时间": "下次运行时间", + "下载": "下载", + "下载两步验证手机应用,比如 Google Authenticator 、": "下载两步验证手机应用,比如 Google Authenticator 、", + "下载更新": "下载更新", + "下载更新中...": "下载更新中...", + "不包含": "不包含", + "不属于": "不属于", "不能包含 task 命令": "不能包含 task 命令", - "工作目录": "工作目录", - "脚本执行时的工作目录,留空则自动检测。相对路径基于 scripts 目录,也支持绝对路径": "脚本执行时的工作目录,留空则自动检测。相对路径基于 scripts 目录,也支持绝对路径", - "留空自动检测,或输入相对/绝对路径": "留空自动检测,或输入相对/绝对路径", - "Chronocat Red 服务的连接地址 https://chronocat.vercel.app/install/docker/official/": "Chronocat Red 服务的连接地址 https://chronocat.vercel.app/install/docker/official/", + "且": "且", + "两步验证": "两步验证", + "个人": "个人", "个人:user_id=个人QQ 群则填入group_id=QQ群 多个用英文;隔开同时支持个人和群 如:user_id=xxx;group_id=xxxx;group_id=xxxxx": "个人:user_id=个人QQ 群则填入group_id=QQ群 多个用英文;隔开同时支持个人和群 如:user_id=xxx;group_id=xxxx;group_id=xxxxx", - "docker安装在持久化config目录下的chronocat.yml文件可找到": "docker安装在持久化config目录下的chronocat.yml文件可找到", - "请选择": "请选择", - "请输入": "请输入", - "依赖设置": "依赖设置", - "Node 软件包镜像源": "Node 软件包镜像源", - "Python 软件包镜像源": "Python 软件包镜像源", - "Linux 软件包镜像源": "Linux 软件包镜像源", + "中...": "中...", + "中文": "中文", + "主题": "主题", + "主题设置": "主题设置", + "亮色": "亮色", + "今日失败": "今日失败", + "今日成功": "今日成功", + "今日执行": "今日执行", + "今日执行次数 Top 5": "今日执行次数 Top 5", + "今日耗时 Top 5": "今日耗时 Top 5", + "仓库需要拉取的文件后缀,多个后缀空格分隔,默认使用配置文件中的RepoFileExtensions": "仓库需要拉取的文件后缀,多个后缀空格分隔,默认使用配置文件中的RepoFileExtensions", + "代理": "代理", + "代理IP": "代理IP", "代理与镜像源二选一即可": "代理与镜像源二选一即可", "代理地址, 支持HTTP(S)/SOCK5": "代理地址, 支持HTTP(S)/SOCK5", - "NPM 镜像源": "NPM 镜像源", - "PyPI 镜像源": "PyPI 镜像源", - "alpine linux 镜像源": "alpine linux 镜像源", + "代理端口": "代理端口", + "以后再说": "以后再说", + "仪表盘": "仪表盘", + "任务": "任务", + "任务数": "任务数", + "任务未运行": "任务未运行", + "企业微信代理地址": "企业微信代理地址", + "企业微信应用": "企业微信应用", + "企业微信机器人": "企业微信机器人", + "企业微信机器人的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", + "使用手机应用扫描二维码,或者输入秘钥": "使用手机应用扫描二维码,或者输入秘钥", + "依赖文件": "依赖文件", + "依赖管理": "依赖管理", + "依赖类型": "依赖类型", + "依赖缓存": "依赖缓存", + "依赖设置": "依赖设置", + "保存": "保存", + "保存成功": "保存成功", + "保存文件": "保存文件", + "保存文件成功": "保存文件成功", + "保存目录": "保存目录", + "修改环境变量名称": "修改环境变量名称", + "修改用户名密码": "修改用户名密码", + "倒序": "倒序", + "值": "值", + "停止": "停止", + "全局SSH私钥": "全局SSH私钥", + "全部任务": "全部任务", + "公开仓库": "公开仓库", + "公开仓库支持HTTP/SOCK5代理,私有仓库支持SOCK5代理": "公开仓库支持HTTP/SOCK5代理,私有仓库支持SOCK5代理", + "关于": "关于", + "关联订阅": "关联订阅", + "其他设置": "其他设置", + "内存": "内存", + "内存使用": "内存使用", + "分": "分", + "分支": "分支", + "创建": "创建", + "创建SSH密钥": "创建SSH密钥", + "创建SSH密钥成功": "创建SSH密钥成功", + "创建任务": "创建任务", + "创建任务成功": "创建任务成功", + "创建依赖": "创建依赖", + "创建变量": "创建变量", + "创建变量成功": "创建变量成功", + "创建应用": "创建应用", + "创建应用成功": "创建应用成功", + "创建文件夹成功": "创建文件夹成功", + "创建文件成功": "创建文件成功", + "创建时间": "创建时间", + "创建视图": "创建视图", + "创建订阅": "创建订阅", + "创建订阅成功": "创建订阅成功", + "初始化": "初始化", + "初始化配置": "初始化配置", + "删除": "删除", + "删除Labels成功": "删除Labels成功", + "删除中": "删除中", + "删除失败": "删除失败", + "删除成功": "删除成功", + "删除标签成功": "删除标签成功", + "别名": "别名", + "加载中...": "加载中...", + "包含": "包含", + "单实例": "单实例", + "单实例模式:定时启动新任务前会自动停止旧任务;多实例模式:允许同时运行多个任务实例": "单实例模式:定时启动新任务前会自动停止旧任务;多实例模式:允许同时运行多个任务实例", + "单文件": "单文件", + "去登录": "去登录", + "发送模板": "发送模板,支持html,txt,json,markdown,cloudMonitor,jenkins,route,pay", + "发送渠道": "发送渠道,支持wechat,webhook,cp,mail,sms", + "发送的目标,群组或者好友": "发送的目标,群组或者好友", + "发送结果回调地址": "发送结果回调地址,会把推送最终结果通知到这个地址上", + "取消": "取消", + "取消安装": "取消安装", + "取消置顶": "取消置顶", + "只能输入字母数字下划线,且不能以数字开头": "只能输入字母数字下划线,且不能以数字开头", + "可用,你使用的版本为": "可用,你使用的版本为", + "同时删除关联任务和脚本": "同时删除关联任务和脚本", + "名称": "名称", + "名称不能为保留关键字": "名称不能为保留关键字", + "吗": "吗", + "否": "否", + "启动": "启动", + "启动中...": "启动中...", + "启动中,请稍后...": "启动中,请稍后...", + "启用": "启用", + "命令": "命令", + "命令/脚本": "命令/脚本", + "唯一值": "唯一值", + "唯一值用于日志目录和私钥别名": "唯一值用于日志目录和私钥别名", + "在您的设备上打开两步验证应用程序以查看您的身份验证代码并验证您的身份。": "在您的设备上打开两步验证应用程序以查看您的身份验证代码并验证您的身份。", + "基础数据": "基础数据", + "堆内存": "堆内存", + "备份": "备份", + "备份数据上传成功,确认覆盖数据": "备份数据上传成功,确认覆盖数据", + "备注": "备注", + "复制": "复制", + "复制成功": "复制成功", + "多个依赖是否换行分割": "多个依赖是否换行分割", + "多个关键词竖线分割,支持正则表达式": "多个关键词竖线分割,支持正则表达式", + "多实例": "多实例", + "天": "天", + "失败": "失败", + "失败,请检查": "失败,请检查", + "头像": "头像", + "夹下所有日志": "夹下所有日志", + "夹及其子文件": "夹及其子文件", + "好友": "好友", + "好友令牌": "好友令牌,微信公众号渠道填写好友令牌,企业微信渠道填写企业微信用户id", + "如果GOBOT_URL设置 /send_private_msg 则需要填入 user_id=个人QQ 相反如果是 /send_group_msg 则需要填入 group_id=QQ群": "如果GOBOT_URL设置 /send_private_msg 则需要填入 user_id=个人QQ 相反如果是 /send_group_msg 则需要填入 group_id=QQ群", "如果恢复失败,可进入容器执行": "如果恢复失败,可进入容器执行", + "安全设置": "安全设置", + "安装": "安装", + "安装中": "安装中", + "安装失败": "安装失败", + "完成安装": "完成安装", + "完成设置": "完成设置", + "定时": "定时", + "定时任务": "定时任务", + "定时任务并发数": "定时任务并发数", + "定时类型": "定时类型", + "定时规则": "定时规则", + "定时订阅": "定时订阅", + "实例模式": "实例模式", + "实时运行态": "实时运行态", + "密码": "密码", + "密码/Token": "密码/Token", + "密码不能为admin": "密码不能为admin", + "密钥key,智能微秘书个人中心获取apikey,申请地址:https://wechat.aibotk.com/signup?from=ql": "密钥key,智能微秘书个人中心获取apikey,申请地址:https://wechat.aibotk.com/signup?from=ql", + "密钥,机器人安全设置页面,加签一栏下面显示的SEC开头的字符串": "密钥,机器人安全设置页面,加签一栏下面显示的SEC开头的字符串", + "对比工具": "对比工具", + "导入": "导入", + "属于": "属于", + "工作目录": "工作目录", + "已关闭": "已关闭", + "已删除": "已删除", + "已取消": "已取消", + "已启用": "已启用", + "已安装": "已安装", + "已禁用": "已禁用", + "实例已停止": "实例已停止", + "已经是最新版了!": "已经是最新版了!", + "已运行": "已运行", + "已选择": "已选择", "常规定时": "常规定时", - "手动运行": "手动运行", + "平台": "平台", + "平均耗时": "平均耗时", + "序号": "序号", + "应用设置": "应用设置", + "开发版": "开发版", + "开始备份": "开始备份", + "开始安装": "开始安装", + "开始时间": "开始时间", "开机运行": "开机运行", - "时区": "时区", + "强制删除": "强制删除", "强制打开": "强制打开", "强制打开可能会导致编辑器显示异常": "强制打开可能会导致编辑器显示异常", - "确认离开": "确认离开", + "当前修改未保存,确定离开吗": "当前修改未保存,确定离开吗", + "当前文件": "当前文件", + "当前文件不支持预览": "当前文件不支持预览", "当前文件未保存,确认离开吗": "当前文件未保存,确认离开吗", + "待开发": "待开发", + "微信扫码登录后一对一推送或一对多推送下面的token(您的Token),不提供PUSH_PLUS_USER则默认为一对一推送,参考 https://www.pushplus.plus/": "微信扫码登录后一对一推送或一对多推送下面的token(你的Token),不提供PUSH_PLUS_USER则默认为一对一推送,参考 https://www.pushplus.plus/", + "微加机器人": "微加机器人", + "总任务": "总任务", + "总执行": "总执行", + "恭喜安装完成!": "恭喜安装完成!", + "您输入的两个密码不匹配!": "您输入的两个密码不匹配!", + "成功": "成功", + "成功率": "成功率", + "或": "或", + "手动运行": "手动运行", + "执行前": "执行前", + "执行后": "执行后", + "执行结束": "执行结束", + "批量": "批量", + "批量修改变量名称": "批量修改变量名称", + "批量修改标签": "批量修改标签", + "批量停止": "批量停止", + "批量删除": "批量删除", + "批量删除成功": "批量删除成功", + "批量取消置顶": "批量取消置顶", + "批量启用": "批量启用", + "批量安装": "批量安装", + "批量导出": "批量导出", + "批量强制删除": "批量强制删除", + "批量禁用": "批量禁用", + "批量置顶": "批量置顶", + "批量运行": "批量运行", + "拉取方式": "拉取方式", + "排序方式": "排序方式", + "排队中": "排队中", + "推送到个人QQ: http://127.0.0.1/send_private_msg,群:http://127.0.0.1/send_group_msg": "推送到个人QQ: http://127.0.0.1/send_private_msg,群:http://127.0.0.1/send_group_msg", + "推送消息的优先级": "推送消息的优先级", + "提交": "提交", + "提交 issue": "提交 issue", + "提交BUG": "提交BUG", + "操作": "操作", + "支持python3、javascript、shell、typescript 的定时任务管理面板": "支持python3、javascript、shell、typescript 的定时任务管理面板", + "支持拷贝 ql repo/raw 命令,粘贴导入": "支持拷贝 ql repo/raw 命令,粘贴导入", + "支持输入脚本路径/任意系统可执行命令/task 脚本路径": "支持输入脚本路径/任意系统可执行命令/task 脚本路径", "收件邮箱地址,多个分号分隔,默认发送给发件邮箱地址": "收件邮箱地址,多个分号分隔,默认发送给发件邮箱地址", - "选择备份模块": "选择备份模块", - "开始备份": "开始备份", - "基础数据": "基础数据", - "脚本文件": "脚本文件", + "数据备份还原": "数据备份还原", + "文件": "文件", + "文件名": "文件名", + "文件名不能包含斜杠": "文件名不能包含斜杠", + "文件后缀": "文件后缀", + "文件夹": "文件夹", + "文件夹名": "文件夹名", + "新增定时规则": "新增定时规则", + "新增排序方式": "新增排序方式", + "新增筛选条件": "新增筛选条件", + "新建": "新建", + "新版本": "新版本", + "日志": "日志", + "日志 -": "日志 -", + "日志删除频率": "日志删除频率", + "日志名称": "日志名称", + "日志名称不能超过100个字符": "日志名称不能超过100个字符", + "日志名称只能包含字母、数字、下划线和连字符": "日志名称只能包含字母、数字、下划线和连字符", "日志文件": "日志文件", - "依赖缓存": "依赖缓存", - "远程脚本缓存": "远程脚本缓存", - "远程仓库缓存": "远程仓库缓存", - "SSH 文件缓存": "SSH 文件缓存", + "日志管理": "日志管理", + "时": "时", + "时区": "时区", + "是": "是", + "是目前检测到的最新可用版本了。": "是目前检测到的最新可用版本了。", + "显示": "显示", + "智能微秘书": "智能微秘书", + "暂无数据": "暂无数据", + "暂无日志": "暂无日志", + "暂无脚本": "暂无脚本", + "暂无运行中任务": "暂无运行中任务", + "暗色": "暗色", + "更多": "更多", + "更换头像": "更换头像", + "更新": "更新", + "更新SSH密钥成功": "更新SSH密钥成功", + "更新任务成功": "更新任务成功", + "更新包下载成功": "更新包下载成功", + "更新变量成功": "更新变量成功", + "更新可用": "更新可用", + "更新名称成功": "更新名称成功", + "更新失败,请检查网络及日志或稍后再试": "更新失败,请检查网络及日志或稍后再试", + "更新应用成功": "更新应用成功", + "更新成功": "更新成功", + "更新日志": "更新日志", + "更新时间": "更新时间", + "更新环境变量名称成功": "更新环境变量名称成功", + "更新订阅成功": "更新订阅成功", + "最后运行时长": "最后运行时长", + "最后运行时间": "最后运行时间", + "最小是 4": "最小是 4", + "最长单次": "最长单次", + "服务启动超时": "服务启动超时", + "未启用": "未启用", + "未找到": "未找到", + "本地文件": "本地文件", + "权限": "权限", + "查看": "查看", + "查看日志": "查看日志", + "标签": "标签", + "标签统计": "标签统计", + "检查更新": "检查更新", + "检查更新中...": "检查更新中...", + "次数": "次数", + "欢迎使用": "欢迎使用", + "欢迎使用青龙": "欢迎使用青龙", + "正式版": "正式版", + "每": "每", + "每x天自动删除x天以前的日志": "每x天自动删除x天以前的日志", + "测试中...": "测试中...", + "消息接收人": "消息接收人", + "添加": "添加", + "添加Labels成功": "添加Labels成功", + "添加标签成功": "添加标签成功", + "清空日志": "清空日志", "清除依赖缓存": "清除依赖缓存", "清除成功": "清除成功", - "日志名称": "日志名称", - "自定义日志文件夹名称,用于区分不同任务的日志,留空则自动生成": "自定义日志文件夹名称,用于区分不同任务的日志,留空则自动生成", - "自定义日志文件夹名称,用于区分不同任务的日志,留空则自动生成。支持绝对路径如 /dev/null": "自定义日志文件夹名称,用于区分不同任务的日志,留空则自动生成。支持绝对路径如 /dev/null", - "自定义日志文件夹名称,用于区分不同任务的日志,留空则自动生成。支持 /dev/null 丢弃日志,其他绝对路径必须在日志目录内": "自定义日志文件夹名称,用于区分不同任务的日志,留空则自动生成。支持 /dev/null 丢弃日志,其他绝对路径必须在日志目录内", - "请输入自定义日志文件夹名称": "请输入自定义日志文件夹名称", - "请输入自定义日志文件夹名称或绝对路径": "请输入自定义日志文件夹名称或绝对路径", - "请输入自定义日志文件夹名称或 /dev/null": "请输入自定义日志文件夹名称或 /dev/null", - "日志名称只能包含字母、数字、下划线和连字符": "日志名称只能包含字母、数字、下划线和连字符", - "日志名称不能超过100个字符": "日志名称不能超过100个字符", - "未启用": "未启用", - "默认为 CPU 个数": "默认为 CPU 个数", - "最小是 4": "最小是 4", - "实例模式": "实例模式", - "单实例模式:定时启动新任务前会自动停止旧任务;多实例模式:允许同时运行多个任务实例": "单实例模式:定时启动新任务前会自动停止旧任务;多实例模式:允许同时运行多个任务实例", - "请选择实例模式": "请选择实例模式", - "单实例": "单实例", - "多实例": "多实例", - "SSH密钥": "SSH密钥", - "别名": "别名", + "源文件": "源文件", + "激活成功": "激活成功", + "点击或者拖拽文件到此区域上传": "点击或者拖拽文件到此区域上传", + "父目录": "父目录", + "版本": "版本", + "状态": "状态", + "环境变量": "环境变量", + "生成数据中...": "生成数据中...", + "用于访问所有私有仓库的全局SSH私钥": "用于访问所有私有仓库的全局SSH私钥", + "用户令牌,扫描登录后 我的—>设置->令牌 中获取,参考 https://www.weplusbot.com/": "用户令牌,扫描登录后 我的—>设置->令牌 中获取,参考 https://www.weplusbot.com/", + "用户名": "用户名", + "用户名密码/Token": "用户名密码/Token", + "留空自动检测,或输入相对/绝对路径": "留空自动检测,或输入相对/绝对路径", + "登录": "登录", + "登录IP": "登录IP", + "登录地址": "登录地址", + "登录已过期,请重新登录": "登录已过期,请重新登录", + "登录成功!": "登录成功!", + "登录日志": "登录日志", + "登录时间": "登录时间", + "登录状态": "登录状态", + "登录设备": "登录设备", + "白名单": "白名单", + "的Secret吗": "的Secret吗", + "知道了": "知道了", + "确认": "确认", + "确认保存文件": "确认保存文件", + "确认停止": "确认停止", + "确认停止定时任务": "确认停止定时任务", + "确认停止实例": "确认停止实例", + "确认停止运行实例": "确认停止运行实例", + "确认删除": "确认删除", + "确认删除SSH密钥": "确认删除SSH密钥", + "确认删除依赖": "确认删除依赖", + "确认删除变量": "确认删除变量", + "确认删除定时任务": "确认删除定时任务", + "确认删除定时订阅": "确认删除定时订阅", + "确认删除应用": "确认删除应用", + "确认删除视图": "确认删除视图", + "确认删除选中的依赖吗": "确认删除选中的依赖吗", + "确认删除选中的变量吗": "确认删除选中的变量吗", + "确认删除选中的定时任务吗": "确认删除选中的定时任务吗", + "确认取消安装": "确认取消安装", + "确认密码": "确认密码", + "确认离开": "确认离开", + "确认运行": "确认运行", + "确认运行定时任务": "确认运行定时任务", + "确认重启": "确认重启", + "确认重新安装": "确认重新安装", + "确认重新安装选中的依赖吗": "确认重新安装选中的依赖吗", + "确认重置": "确认重置", + "确认重置应用": "确认重置应用", + "禁用": "禁用", + "私有仓库": "私有仓库", + "私钥": "私钥", + "秒": "秒", + "秒(可选) 分 时 天 月 周": "秒(可选) 分 时 天 月 周", + "秒后自动刷新": "秒后自动刷新", + "秒后重试": "秒后重试", + "空文件": "空文件", + "空闲中": "空闲中", + "第一步": "第一步", + "第三步": "第三步", + "第二步": "第二步", + "筛选条件": "筛选条件", + "类型": "类型", + "系统": "系统", + "系统信息": "系统信息", + "系统安装包下载成功,确认重启": "系统安装包下载成功,确认重启", + "系统将在": "系统将在", + "系统日志": "系统日志", + "系统设置": "系统设置", + "系统资源": "系统资源", + "系统运行": "系统运行", + "结束时间": "结束时间", + "编辑": "编辑", "编辑SSH密钥": "编辑SSH密钥", - "创建SSH密钥": "创建SSH密钥", - "更新SSH密钥成功": "更新SSH密钥成功", - "创建SSH密钥成功": "创建SSH密钥成功", + "编辑任务": "编辑任务", + "编辑依赖": "编辑依赖", + "编辑变量": "编辑变量", + "编辑应用": "编辑应用", + "编辑视图": "编辑视图", + "编辑订阅": "编辑订阅", + "置顶": "置顶", + "群晖chat": "群晖chat", + "群聊": "群聊", + "脚本": "脚本", + "脚本执行时的工作目录,留空则自动检测。相对路径基于 scripts 目录,也支持绝对路径": "脚本执行时的工作目录,留空则自动检测。相对路径基于 scripts 目录,也支持绝对路径", + "脚本文件": "脚本文件", + "脚本管理": "脚本管理", + "自动删除任务": "自动删除任务", + "自动拆分": "自动拆分", + "自动添加任务": "自动添加任务", + "自动生成": "自动生成", + "自定义日志文件夹名称,用于区分不同任务的日志,留空则自动生成": "自定义日志文件夹名称,用于区分不同任务的日志,留空则自动生成", + "自定义日志文件夹名称,用于区分不同任务的日志,留空则自动生成。支持 /dev/null 丢弃日志,其他绝对路径必须在日志目录内": "自定义日志文件夹名称,用于区分不同任务的日志,留空则自动生成。支持 /dev/null 丢弃日志,其他绝对路径必须在日志目录内", + "自定义日志文件夹名称,用于区分不同任务的日志,留空则自动生成。支持绝对路径如 /dev/null": "自定义日志文件夹名称,用于区分不同任务的日志,留空则自动生成。支持绝对路径如 /dev/null", + "自定义通知": "自定义通知", + "自建的PushMeServer消息接口地址,例如:http://127.0.0.1:3010,不填则使用官方消息接口": "自建的PushMeServer消息接口地址,例如:http://127.0.0.1:3010,不填则使用官方消息接口", + "要发送的用户昵称或群名,如果目标是群,需要填群名,如果目标是好友,需要填好友昵称": "要发送的用户昵称或群名,如果目标是群,需要填群名,如果目标是好友,需要填好友昵称", + "视图名称": "视图名称", + "视图管理": "视图管理", + "订阅": "订阅", + "订阅管理": "订阅管理", + "设置": "设置", + "访问密钥": "访问密钥", + "语言": "语言", + "请": "请", + "请先按如下方式修复:": "请先按如下方式修复:", + "请求体格式key1: value1,多个换行分割。url或者body中必须包含$title,$content可选,对应api内容的位置": "请求体格式key1: value1,多个换行分割。url或者body中必须包含$title,$content可选,对应api内容的位置", + "请求头Content-Type": "请求头Content-Type", + "请求头格式Custom-Header1: Header1,多个换行分割": "请求头格式Custom-Header1: Header1,多个换行分割", + "请求方法": "请求方法", + "请求链接以http或者https开头。url或者body中必须包含$title,$content可选,对应api内容的位置": "请求链接以http或者https开头。url或者body中必须包含$title,$content可选,对应api内容的位置", + "请至少输入一个标签": "请至少输入一个标签", + "请输入": "请输入", "请输入SSH密钥别名": "请输入SSH密钥别名", "请输入SSH私钥": "请输入SSH私钥", "请输入SSH私钥内容(以 -----BEGIN 开头)": "请输入SSH私钥内容(以 -----BEGIN 开头)", - "确认删除SSH密钥": "确认删除SSH密钥", - "批量": "批量", - "全局SSH私钥": "全局SSH私钥", - "用于访问所有私有仓库的全局SSH私钥": "用于访问所有私有仓库的全局SSH私钥", + "请输入任务名称": "请输入任务名称", + "请输入依赖名称": "请输入依赖名称", + "请输入依赖名称,支持指定版本": "请输入依赖名称,支持指定版本", + "请输入保存目录,默认scripts目录": "请输入保存目录,默认scripts目录", + "请输入内容": "请输入内容", + "请输入分支": "请输入分支", + "请输入名称": "请输入名称", + "请输入名称/值/备注": "请输入名称/值/备注", + "请输入名称或者关键词": "请输入名称或者关键词", + "请输入备注": "请输入备注", "请输入完整的SSH私钥内容": "请输入完整的SSH私钥内容", - "仪表盘": "仪表盘", - "总任务": "总任务", - "今日执行": "今日执行", - "今日成功": "今日成功", - "今日失败": "今日失败", - "成功率": "成功率", - "平均耗时": "平均耗时", - "近 7 日趋势": "近 7 日趋势", - "今日耗时 Top 5": "今日耗时 Top 5", - "今日执行次数 Top 5": "今日执行次数 Top 5", - "实时运行态": "实时运行态", - "系统资源": "系统资源", - "排队中": "排队中", - "暂无运行中任务": "暂无运行中任务", - "暂无数据": "暂无数据", - "总执行": "总执行", - "次数": "次数", - "最长单次": "最长单次", - "已运行": "已运行", - "系统运行": "系统运行", - "内存使用": "内存使用", - "堆内存": "堆内存", - "CPU 核心": "CPU 核心", + "请输入密码或者Token": "请输入密码或者Token", + "请输入应用名称": "请输入应用名称", + "请输入文件名": "请输入文件名", + "请输入文件后缀": "请输入文件后缀", + "请输入文件夹名": "请输入文件夹名", + "请输入新名称": "请输入新名称", + "请输入新的环境变量名称": "请输入新的环境变量名称", + "请输入日志名": "请输入日志名", + "请输入环境变量值": "请输入环境变量值", + "请输入环境变量名称": "请输入环境变量名称", + "请输入私钥": "请输入私钥", + "请输入脚本依赖文件关键词,多个关键词竖线分割": "请输入脚本依赖文件关键词,多个关键词竖线分割", + "请输入脚本名": "请输入脚本名", + "请输入脚本筛选白名单关键词,多个关键词竖线分割": "请输入脚本筛选白名单关键词,多个关键词竖线分割", + "请输入脚本筛选黑名单关键词,多个关键词竖线分割": "请输入脚本筛选黑名单关键词,多个关键词竖线分割", + "请输入自定义日志文件夹名称": "请输入自定义日志文件夹名称", + "请输入自定义日志文件夹名称或 /dev/null": "请输入自定义日志文件夹名称或 /dev/null", + "请输入自定义日志文件夹名称或绝对路径": "请输入自定义日志文件夹名称或绝对路径", + "请输入要发送的目标": "请输入要发送的目标", + "请输入视图名称": "请输入视图名称", + "请输入订阅链接": "请输入订阅链接", + "请输入认证用户名": "请输入认证用户名", + "请输入运行任务前要执行的命令,不能包含 task 命令": "请输入运行任务前要执行的命令,不能包含 task 命令", + "请输入运行任务后要执行的命令,不能包含 task 命令": "请输入运行任务后要执行的命令,不能包含 task 命令", + "请输入运行订阅前要执行的命令": "请输入运行订阅前要执行的命令", + "请输入运行订阅后要执行的命令": "请输入运行订阅后要执行的命令", + "请选择": "请选择", + "请选择实例模式": "请选择实例模式", + "请选择操作符": "请选择操作符", + "请选择日志": "请选择日志", + "请选择日志文件": "请选择日志文件", + "请选择模块权限": "请选择模块权限", + "请选择父目录": "请选择父目录", + "请选择脚本": "请选择脚本", + "请选择脚本文件": "请选择脚本文件", + "请选择通知方式": "请选择通知方式", + "调用版本;专业版填写pro,个人版填写personal,为空默认使用专业版": "调用版本;专业版填写pro,个人版填写personal,为空默认使用专业版", + "调试": "调试", "负载 1m": "负载 1m", - "平台": "平台", - "24小时未运行": "24小时未运行", - "标签统计": "标签统计", - "任务数": "任务数", - "内存": "内存" + "账户设置": "账户设置", + "跟随系统": "跟随系统", + "跳过": "跳过", + "输入后回车增加自定义选项": "输入后回车增加自定义选项", + "输入手机应用上的6位数字": "输入手机应用上的6位数字", + "运行": "运行", + "运行中": "运行中", + "运行任务前执行的命令,比如 cp/mv/python3 xxx.py/node xxx.js": "运行任务前执行的命令,比如 cp/mv/python3 xxx.py/node xxx.js", + "运行任务后执行的命令,比如 cp/mv/python3 xxx.py/node xxx.js": "运行任务后执行的命令,比如 cp/mv/python3 xxx.py/node xxx.js", + "运行实例": "运行实例", + "运行订阅前执行的命令,比如 cp/mv/python3 xxx.py/node xxx.js": "运行订阅前执行的命令,比如 cp/mv/python3 xxx.py/node xxx.js", + "运行订阅后执行的命令,比如 cp/mv/python3 xxx.py/node xxx.js": "运行订阅后执行的命令,比如 cp/mv/python3 xxx.py/node xxx.js", + "运行设置": "运行设置", + "近 7 日趋势": "近 7 日趋势", + "返回首页": "返回首页", + "还原数据": "还原数据", + "远程仓库缓存": "远程仓库缓存", + "远程脚本缓存": "远程脚本缓存", + "退出": "退出", + "退出登录": "退出登录", + "退出编辑": "退出编辑", + "选中的变量吗": "选中的变量吗", + "选中的定时任务吗": "选中的定时任务吗", + "选择备份模块": "选择备份模块", + "通知关闭成功": "通知关闭成功", + "通知发送成功": "通知发送成功", + "通知方式": "通知方式", + "通知设置": "通知设置", + "邮箱": "邮箱", + "邮箱地址": "邮箱地址", + "邮箱服务名称,比如126、163、Gmail、QQ等,支持列表https://github.com/nodemailer/nodemailer/blob/master/lib/well-known/services.json": "邮箱服务名称,比如126、163、Gmail、QQ等,支持列表https://github.com/nodemailer/nodemailer/blob/master/lib/well-known/services.json", + "配置文件": "配置文件", + "重启": "重启", + "重命名": "重命名", + "重新下载": "重新下载", + "重新启动": "重新启动", + "重新安装": "重新安装", + "重置Secret会让当前应用所有token失效": "重置Secret会让当前应用所有token失效", + "重置secret": "重置secret", + "重置成功": "重置成功", + "钉钉机器人": "钉钉机器人", + "钉钉机器人webhook token,例如:5a544165465465645d0f31dca676e7bd07415asdasd": "钉钉机器人webhook token,例如:5a544165465465645d0f31dca676e7bd07415asdasd", + "链接": "链接", + "错误": "错误", + "错误日志": "错误日志", + "队列中": "队列中", + "青龙": "青龙", + "项": "项", + "顺序": "顺序", + "飞书机器人": "飞书机器人", + "飞书群组机器人加签密钥,安全设置中开启签名校验后获得": "飞书群组机器人加签密钥,安全设置中开启签名校验后获得", + "飞书群组机器人:https://www.feishu.cn/hc/zh-CN/articles/360024984973": "飞书群组机器人:https://www.feishu.cn/hc/zh-CN/articles/360024984973", + "验证": "验证", + "验证失败": "验证失败", + "验证码": "验证码", + "验证码为6位数字": "验证码为6位数字", + "黑名单": "黑名单", + "默认为 CPU 个数": "默认为 CPU 个数", + ",保存后不可恢复": ",保存后不可恢复", + ",删除后不可恢复": ",删除后不可恢复" } diff --git a/src/pages/crontab/detail.tsx b/src/pages/crontab/detail.tsx index 42dd4d8f..880180da 100644 --- a/src/pages/crontab/detail.tsx +++ b/src/pages/crontab/detail.tsx @@ -22,6 +22,7 @@ import { PlayCircleOutlined, PauseCircleOutlined, FullscreenOutlined, + StopOutlined, } from '@ant-design/icons'; import { CrontabStatus } from './type'; import { diffTime } from '@/utils/date'; @@ -46,6 +47,10 @@ const tabList = [ key: 'script', tab: intl.get('脚本'), }, + { + key: 'runningInstance', + tab: intl.get('运行实例'), + }, ]; interface LogItem { @@ -77,6 +82,36 @@ const CronDetailModal = ({ const [currentCron, setCurrentCron] = useState({}); const listRef = useRef(null); const tableScrollHeight = useScrollHeight(listRef); + const [runningInstances, setRunningInstances] = useState([]); + const needRefreshRef = useRef(false); + + const fetchRunningInstances = async () => { + if (!cron.id) return Promise.resolve(); + return request + .get(`${config.apiPrefix}crons/${cron.id}/instances`) + .then(({ code, data }) => { + if (code === 200 && data) { + setRunningInstances(data); + } + }) + .catch(() => { }); + }; + + useEffect(() => { + fetchRunningInstances(); + let timer: ReturnType; + let cancelled = false; + const poll = async () => { + await fetchRunningInstances(); + if (cancelled) return; + timer = setTimeout(poll, 10000); + }; + poll(); + return () => { + cancelled = true; + clearTimeout(timer); + }; + }, [cron.id]); const contentList: any = { log: ( @@ -115,12 +150,107 @@ const CronDetailModal = ({ }} /> ), + runningInstance: ( +
+ + + {(item) => ( + +
+ ), + }; + + const stopRunningInstance = (instance: any) => { + Modal.confirm({ + title: intl.get('确认停止实例'), + content: ( + <> + {intl.get('确认停止运行实例')} PID: {instance.pid}{' '} + {intl.get('吗')} + + ), + onOk() { + request + .post(`${config.apiPrefix}crons/${cron.id}/instances/${instance.id}/stop`) + .then(({ code }) => { + if (code === 200) { + message.success(intl.get('实例已停止')); + needRefreshRef.current = true; + fetchRunningInstances(); + setTimeout(() => getLogs(), 1000); + } + }); + }, + }); + }; + + const viewInstanceLog = (instance: any) => { + if (!instance.log_path) return; + const parts = instance.log_path.split('/'); + const filename = parts.pop() || ''; + const directory = parts.join('/'); + const url = `${config.apiPrefix}logs/detail?file=${filename}&path=${directory}`; + localStorage.setItem('logCron', url); + setLogUrl(url); + request.get(url).then(({ code, data }) => { + if (code === 200) { + setLog(data); + setIsLogModalVisible(true); + } + }); }; const onClickItem = (item: LogItem) => { - const url = `${config.apiPrefix}logs/detail?file=${item.filename}&path=${ - item.directory || '' - }`; + const url = `${config.apiPrefix}logs/detail?file=${item.filename}&path=${item.directory || '' + }`; localStorage.setItem('logCron', url); setLogUrl(url); request.get(url).then(({ code, data }) => { @@ -256,9 +386,8 @@ const CronDetailModal = ({ const enabledOrDisabledCron = () => { Modal.confirm({ - title: `确认${ - currentCron.isDisabled === 1 ? intl.get('启用') : intl.get('禁用') - }`, + title: `确认${currentCron.isDisabled === 1 ? intl.get('启用') : intl.get('禁用') + }`, content: ( <> {intl.get('确认')} @@ -273,8 +402,7 @@ const CronDetailModal = ({ onOk() { request .put( - `${config.apiPrefix}crons/${ - currentCron.isDisabled === 1 ? 'enable' : 'disable' + `${config.apiPrefix}crons/${currentCron.isDisabled === 1 ? 'enable' : 'disable' }`, [currentCron.id], ) @@ -292,9 +420,8 @@ const CronDetailModal = ({ const pinOrUnPinCron = () => { Modal.confirm({ - title: `确认${ - currentCron.isPinned === 1 ? intl.get('取消置顶') : intl.get('置顶') - }`, + title: `确认${currentCron.isPinned === 1 ? intl.get('取消置顶') : intl.get('置顶') + }`, content: ( <> {intl.get('确认')} @@ -309,8 +436,7 @@ const CronDetailModal = ({ onOk() { request .put( - `${config.apiPrefix}crons/${ - currentCron.isPinned === 1 ? 'unpin' : 'pin' + `${config.apiPrefix}crons/${currentCron.isPinned === 1 ? 'unpin' : 'pin' }`, [currentCron.id], ) @@ -441,7 +567,7 @@ const CronDetailModal = ({ open={true} forceRender footer={false} - onCancel={() => handleCancel()} + onCancel={() => handleCancel(needRefreshRef.current)} wrapClassName="crontab-detail" width={!isPhone ? '80vw' : ''} > @@ -458,27 +584,27 @@ const CronDetailModal = ({
{(!currentCron.isDisabled || currentCron.status !== CrontabStatus.idle) && ( - <> - {currentCron.status === CrontabStatus.idle && ( - } color="default"> - {intl.get('空闲中')} - - )} - {currentCron.status === CrontabStatus.running && ( - } - color="processing" - > - {intl.get('运行中')} - - )} - {currentCron.status === CrontabStatus.queued && ( - } color="default"> - {intl.get('队列中')} - - )} - - )} + <> + {currentCron.status === CrontabStatus.idle && ( + } color="default"> + {intl.get('空闲中')} + + )} + {currentCron.status === CrontabStatus.running && ( + } + color="processing" + > + {intl.get('运行中')} + + )} + {currentCron.status === CrontabStatus.queued && ( + } color="default"> + {intl.get('队列中')} + + )} + + )} {currentCron.isDisabled === 1 && currentCron.status === CrontabStatus.idle && ( } color="error"> @@ -503,8 +629,8 @@ const CronDetailModal = ({
{currentCron.last_execution_time ? dayjs(currentCron.last_execution_time * 1000).format( - 'YYYY-MM-DD HH:mm:ss', - ) + 'YYYY-MM-DD HH:mm:ss', + ) : '-'}
diff --git a/src/pages/crontab/index.tsx b/src/pages/crontab/index.tsx index 68aa7280..3269ecd4 100644 --- a/src/pages/crontab/index.tsx +++ b/src/pages/crontab/index.tsx @@ -365,8 +365,8 @@ const Crontab = () => { } }; - const getCrons = () => { - setLoading(true); + const getCrons = async (silent?: boolean) => { + if (!silent) setLoading(true); const { page, size, sorter, filters } = pageConf; let url = `${config.apiPrefix }crons?searchValue=${searchText}&page=${page}&size=${size}&filters=${JSON.stringify( @@ -385,7 +385,7 @@ const Crontab = () => { filterRelation: viewConf.filterRelation || 'and', })}`; } - request + return request .get(url) .then(async ({ code, data: _data }) => { if (code === 200) { @@ -419,9 +419,24 @@ const Crontab = () => { setTotal(total); } }) - .finally(() => setLoading(false)); + .finally(() => !silent && setLoading(false)); }; + useEffect(() => { + let timer: ReturnType; + let cancelled = false; + const poll = async () => { + await getCrons(true); + if (cancelled) return; + timer = setTimeout(poll, 10000); + }; + poll(); + return () => { + cancelled = true; + clearTimeout(timer); + }; + }, [pageConf, viewConf, searchText]); + const addCron = () => { setEditedCron(null as any); setIsModalVisible(true); @@ -809,7 +824,7 @@ const Crontab = () => { setAllSubscriptions(data || []); } }) - .catch(() => {}); + .catch(() => { }); }; useEffect(() => { @@ -1077,8 +1092,11 @@ const Crontab = () => { )} {isDetailModalVisible && ( { + handleCancel={(needUpdate?: boolean) => { setIsDetailModalVisible(false); + if (needUpdate) { + getCrons(); + } }} cron={detailCron} theme={theme} diff --git a/src/pages/dashboard/index.tsx b/src/pages/dashboard/index.tsx index f2aa9afe..6c16d84c 100644 --- a/src/pages/dashboard/index.tsx +++ b/src/pages/dashboard/index.tsx @@ -46,7 +46,7 @@ interface TopItem { interface Runtime { runningCount: number; queuedCount: number; - running: Array<{ id: number; name: string; pid: number; elapsed: number; logPath: string }>; + running: Array<{ instanceId: number; id: number; name: string; pid: number; elapsed: number; logPath: string }>; idleTasks: Array<{ id: number; name: string; lastRun: string }>; } @@ -282,12 +282,15 @@ const Dashboard = () => { > 5 ? runtimePagination : false} size="small" locale={{ emptyText: }} columns={[ - { title: intl.get('定时任务'), dataIndex: 'name', ellipsis: true }, + { title: intl.get('定时任务'), dataIndex: 'name', ellipsis: true, render: (name: string, record) => { + const sameTaskCount = (runtime?.running || []).filter(r => r.id === record.id).length; + return sameTaskCount > 1 ? {name} ×{sameTaskCount} : name; + } }, { title: 'PID', dataIndex: 'pid', width: 80 }, { title: intl.get('已运行'), dataIndex: 'elapsed', width: 100, render: (v: number) => v ? formatSeconds(v) : '-' }, { title: intl.get('日志'), dataIndex: 'id', width: 60, render: (id, record) => { localStorage.setItem('logCron', String(id)); setLogCron({ id, name: record.name }); }}>{intl.get('查看')} },