From 9ed107980c7dcecf888c1e2bfa1ba1ba9de2c629 Mon Sep 17 00:00:00 2001 From: whyour Date: Mon, 6 Nov 2023 23:55:16 +0800 Subject: [PATCH] =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E8=AE=BE=E7=BD=AE=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E4=BE=9D=E8=B5=96=E4=BB=A3=E7=90=86=E5=92=8C=E9=95=9C?= =?UTF-8?q?=E5=83=8F=E6=BA=90=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/data/{auth.ts => system.ts} | 12 ++- back/loaders/db.ts | 8 +- back/services/system.ts | 21 +++-- back/services/user.ts | 22 ++--- back/shared/pLimit.ts | 6 +- sample/config.sample.sh | 15 +++- src/locales/en-US.json | 11 ++- src/locales/zh-CN.json | 11 ++- src/pages/setting/dependence.tsx | 139 +++++++++++++++++++++++++++++++ src/pages/setting/index.tsx | 6 ++ 10 files changed, 213 insertions(+), 38 deletions(-) rename back/data/{auth.ts => system.ts} (75%) create mode 100644 src/pages/setting/dependence.tsx diff --git a/back/data/auth.ts b/back/data/system.ts similarity index 75% rename from back/data/auth.ts rename to back/data/system.ts index 5f1dc6c3..cfac3956 100644 --- a/back/data/auth.ts +++ b/back/data/system.ts @@ -5,7 +5,7 @@ import { NotificationInfo } from './notify'; export class AuthInfo { ip?: string; type: AuthDataType; - info?: AuthModelInfo; + info?: SystemModelInfo; id?: number; constructor(options: AuthInfo) { @@ -32,6 +32,10 @@ export enum AuthDataType { export interface SystemConfigInfo { logRemoveFrequency?: number; cronConcurrency?: number; + dependenceProxy?: string; + nodeMirror?: string; + pythonMirror?: string; + linuxMirror?: string; } export interface LoginLogInfo { @@ -42,12 +46,12 @@ export interface LoginLogInfo { status?: LoginStatus; } -export type AuthModelInfo = SystemConfigInfo & +export type SystemModelInfo = SystemConfigInfo & Partial & LoginLogInfo; -export interface AuthInstance extends Model, AuthInfo {} -export const AuthModel = sequelize.define('Auth', { +export interface SystemInstance extends Model, AuthInfo { } +export const SystemModel = sequelize.define('Auth', { ip: DataTypes.STRING, type: DataTypes.STRING, info: { diff --git a/back/loaders/db.ts b/back/loaders/db.ts index c650d654..999ab43b 100644 --- a/back/loaders/db.ts +++ b/back/loaders/db.ts @@ -5,7 +5,7 @@ import { EnvModel } from '../data/env'; import { CrontabModel } from '../data/cron'; import { DependenceModel } from '../data/dependence'; import { AppModel } from '../data/open'; -import { AuthModel } from '../data/auth'; +import { SystemModel } from '../data/system'; import { fileExist } from '../config/util'; import { SubscriptionModel } from '../data/subscription'; import { CrontabViewModel } from '../data/cronView'; @@ -17,7 +17,7 @@ export default async () => { await CrontabModel.sync(); await DependenceModel.sync(); await AppModel.sync(); - await AuthModel.sync(); + await SystemModel.sync(); await EnvModel.sync(); await SubscriptionModel.sync(); await CrontabViewModel.sync(); @@ -75,7 +75,7 @@ export default async () => { const dependenceCount = await DependenceModel.count(); const envCount = await EnvModel.count(); const appCount = await AppModel.count(); - const authCount = await AuthModel.count(); + const authCount = await SystemModel.count(); if (crondbExist && cronCount === 0) { const cronDb = new DataStore({ filename: cronDbFile, @@ -127,7 +127,7 @@ export default async () => { }); authDb.persistence.compactDatafile(); authDb.find({}).exec(async (err, docs) => { - await AuthModel.bulkCreate(docs, { ignoreDuplicates: true }); + await SystemModel.bulkCreate(docs, { ignoreDuplicates: true }); }); } diff --git a/back/services/system.ts b/back/services/system.ts index 84012cb1..ad26a249 100644 --- a/back/services/system.ts +++ b/back/services/system.ts @@ -5,10 +5,10 @@ import config from '../config'; import { AuthDataType, AuthInfo, - AuthInstance, - AuthModel, - AuthModelInfo, -} from '../data/auth'; + SystemInstance, + SystemModel, + SystemModelInfo, +} from '../data/system'; import { NotificationInfo } from '../data/notify'; import NotificationService from './notify'; import ScheduleService, { TaskCallbacks } from './schedule'; @@ -43,17 +43,17 @@ export default class SystemService { public async getSystemConfig() { const doc = await this.getDb({ type: AuthDataType.systemConfig }); - return doc || ({} as AuthInstance); + return doc || ({} as SystemInstance); } - private async updateAuthDb(payload: AuthInfo): Promise { - await AuthModel.upsert({ ...payload }); + private async updateAuthDb(payload: AuthInfo): Promise { + await SystemModel.upsert({ ...payload }); const doc = await this.getDb({ type: payload.type }); return doc; } - public async getDb(query: any): Promise { - const doc: any = await AuthModel.findOne({ where: { ...query } }); + public async getDb(query: any): Promise { + const doc: any = await SystemModel.findOne({ where: { ...query } }); return doc && doc.get({ plain: true }); } @@ -75,11 +75,10 @@ export default class SystemService { } } - public async updateSystemConfig(info: AuthModelInfo) { + public async updateSystemConfig(info: SystemModelInfo) { const oDoc = await this.getSystemConfig(); const result = await this.updateAuthDb({ ...oDoc, - type: AuthDataType.systemConfig, info, }); if (info.logRemoveFrequency) { diff --git a/back/services/user.ts b/back/services/user.ts index 3ed9bd85..b2297081 100644 --- a/back/services/user.ts +++ b/back/services/user.ts @@ -14,10 +14,10 @@ import { authenticator } from '@otplib/preset-default'; import { AuthDataType, AuthInfo, - AuthModel, - AuthModelInfo, + SystemModel, + SystemModelInfo, LoginStatus, -} from '../data/auth'; +} from '../data/system'; import { NotificationInfo } from '../data/notify'; import NotificationService from './notify'; import { Request } from 'express'; @@ -195,8 +195,8 @@ export default class UserService { }); } - public async getLoginLog(): Promise> { - const docs = await AuthModel.findAll({ + public async getLoginLog(): Promise> { + const docs = await SystemModel.findAll({ where: { type: AuthDataType.loginLog }, }); if (docs && docs.length > 0) { @@ -204,7 +204,7 @@ export default class UserService { (a, b) => b.info!.timestamp! - a.info!.timestamp!, ); if (result.length > 100) { - await AuthModel.destroy({ + await SystemModel.destroy({ where: { id: result[result.length - 1].id }, }); } @@ -214,7 +214,7 @@ export default class UserService { } private async insertDb(payload: AuthInfo): Promise { - const doc = await AuthModel.create({ ...payload }, { returning: true }); + const doc = await SystemModel.create({ ...payload }, { returning: true }); return doc; } @@ -345,21 +345,21 @@ export default class UserService { } private async updateAuthDb(payload: AuthInfo): Promise { - let doc = await AuthModel.findOne({ type: payload.type }); + let doc = await SystemModel.findOne({ type: payload.type }); if (doc) { - const updateResult = await AuthModel.update(payload, { + const updateResult = await SystemModel.update(payload, { where: { id: doc.id }, returning: true, }); doc = updateResult[1][0]; } else { - doc = await AuthModel.create(payload, { returning: true }); + doc = await SystemModel.create(payload, { returning: true }); } return doc; } public async getDb(query: any): Promise { - const doc: any = await AuthModel.findOne({ where: { ...query } }); + const doc: any = await SystemModel.findOne({ where: { ...query } }); return doc && (doc.get({ plain: true }) as any); } diff --git a/back/shared/pLimit.ts b/back/shared/pLimit.ts index 13d15468..1aa84104 100644 --- a/back/shared/pLimit.ts +++ b/back/shared/pLimit.ts @@ -1,6 +1,6 @@ import PQueue, { QueueAddOptions } from 'p-queue-cjs'; import os from 'os'; -import { AuthDataType, AuthModel } from '../data/auth'; +import { AuthDataType, SystemModel } from '../data/system'; import Logger from '../loaders/logger'; class TaskLimit { @@ -59,8 +59,8 @@ class TaskLimit { this.cronLimit.concurrency = limit; return; } - await AuthModel.sync(); - const doc = await AuthModel.findOne({ + await SystemModel.sync(); + const doc = await SystemModel.findOne({ where: { type: AuthDataType.systemConfig }, }); if (doc?.info?.cronConcurrency) { diff --git a/sample/config.sample.sh b/sample/config.sample.sh index baa6d63a..6771b2c2 100644 --- a/sample/config.sample.sh +++ b/sample/config.sample.sh @@ -10,6 +10,9 @@ DefaultCronRule="" ## ql repo命令拉取脚本时需要拉取的文件后缀,直接写文件后缀名即可 RepoFileExtensions="js py" +## 代理地址,支持HTTP/SOCK5,例如 http://127.0.0.1:7890 +ProxyUrl="" + ## 资源告警阙值,默认CPU 80%、内存80%、磁盘90% CpuWarn=80 MemoryWarn=80 @@ -18,7 +21,7 @@ DiskWarn=90 ## 设置定时任务执行的超时时间,例如1h,后缀"s"代表秒(默认值), "m"代表分, "h"代表小时, "d"代表天 CommandTimeoutTime="" -## 在使用 task 命令执行 JavaScript 脚本1时,随机延迟启动任务的最大延迟时间 +## 在运行 task 命令时,随机延迟启动任务的最大延迟时间 ## 默认给javascript任务加随机延迟,如 RandomDelay="300" ,表示任务将在 1-300 秒内随机延迟一个秒数,然后再运行,取消延迟赋值为空 RandomDelay="" @@ -30,8 +33,8 @@ RandomDelayFileExtensions="" ## 默认是第0分钟和第30分钟,例如21:00或21:30分的任务将会准点运行。不需要准点运行赋值为空 RandomDelayIgnoredMinutes="" -## 如果你自己会写shell脚本,并且希望在每次容器启动时,额外运行你的 shell 脚本,请赋值为 "true",默认为true -EnableExtraShell="" +## 如果你自己会写shell脚本,并且希望在每次运行 ql update 命令时,额外运行你的 shell 脚本,请赋值为 "true",默认为true +EnableExtraShell="true" ## 是否自动启动bot,默认不启动,设置为true时自动启动,目前需要自行克隆bot仓库所需代码,存到ql/repo目录下,文件夹命名为dockerbot AutoStartBot="" @@ -39,6 +42,12 @@ AutoStartBot="" ## 是否使用第三方bot,默认不使用,使用时填入仓库地址,存到ql/repo目录下,文件夹命名为diybot BotRepoUrl="" +## 安装python依赖时指定pip源 +PipMirror="" + +## 安装node依赖时指定npm源 +NpmMirror="" + ## 通知环境变量 ## 1. Server酱 ## https://sct.ftqq.com diff --git a/src/locales/en-US.json b/src/locales/en-US.json index da780933..4a4670fa 100644 --- a/src/locales/en-US.json +++ b/src/locales/en-US.json @@ -466,5 +466,14 @@ "个人: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" + "请输入": "Please input", + "依赖设置": "Dependence Settings", + "Node 软件包镜像源": "Node Software Package Mirror Source", + "Python 软件包镜像源": "Python Software Package Mirror Source", + "Linux 软件包镜像源": "Linux Software Package Mirror Source", + "代理与镜像源二选一即可": "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" } diff --git a/src/locales/zh-CN.json b/src/locales/zh-CN.json index dca39205..cf7613db 100644 --- a/src/locales/zh-CN.json +++ b/src/locales/zh-CN.json @@ -466,5 +466,14 @@ "个人: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 软件包镜像源", + "代理与镜像源二选一即可": "代理与镜像源二选一即可", + "代理地址, 支持HTTP(S)/SOCK5": "代理地址, 支持HTTP(S)/SOCK5", + "NPM 镜像源": "NPM 镜像源", + "PyPI 镜像源": "PyPI 镜像源", + "alpine linux 镜像源": "alpine linux 镜像源" } diff --git a/src/pages/setting/dependence.tsx b/src/pages/setting/dependence.tsx new file mode 100644 index 00000000..c5defd25 --- /dev/null +++ b/src/pages/setting/dependence.tsx @@ -0,0 +1,139 @@ +import intl from 'react-intl-universal'; +import React, { useState, useEffect, useRef } from 'react'; +import { Button, InputNumber, Form, message, Input, Alert } from 'antd'; +import config from '@/utils/config'; +import { request } from '@/utils/http'; +import './index.less'; + +const Dependence = () => { + const [systemConfig, setSystemConfig] = useState<{ + dependenceProxy?: string; + nodeMirror?: string; + pythonMirror?: string; + linuxMirror?: string; + }>(); + const [form] = Form.useForm(); + + const getSystemConfig = () => { + request + .get(`${config.apiPrefix}system/config`) + .then(({ code, data }) => { + if (code === 200 && data.info) { + setSystemConfig(data.info); + } + }) + .catch((error: any) => { + console.log(error); + }); + }; + + const updateSystemConfig = () => { + request + .put(`${config.apiPrefix}system/config`, systemConfig) + .then(({ code, data }) => { + if (code === 200) { + message.success(intl.get('更新成功')); + } + }) + .catch((error: any) => { + console.log(error); + }); + }; + + useEffect(() => { + getSystemConfig(); + }, []); + + return ( +
+ + + { + setSystemConfig({ + ...systemConfig, + dependenceProxy: e.target.value, + }); + }} + /> + + + + + + { + setSystemConfig({ ...systemConfig, nodeMirror: e.target.value }); + }} + /> + + + + + + { + setSystemConfig({ + ...systemConfig, + pythonMirror: e.target.value, + }); + }} + /> + + + + + + { + setSystemConfig({ ...systemConfig, linuxMirror: e.target.value }); + }} + /> + + + +
+ ); +}; + +export default Dependence; diff --git a/src/pages/setting/index.tsx b/src/pages/setting/index.tsx index 9ba993d5..d5df629b 100644 --- a/src/pages/setting/index.tsx +++ b/src/pages/setting/index.tsx @@ -34,6 +34,7 @@ import { SharedContext } from '@/layouts'; import './index.less'; import useResizeObserver from '@react-hook/resize-observer'; import SystemLog from './systemLog'; +import Dependence from './dependence'; const { Text } = Typography; const isDemoEnv = window.__ENV__DeployEnv === 'demo'; @@ -354,6 +355,11 @@ const Setting = () => { label: intl.get('登录日志'), children: , }, + { + key: 'dependence', + label: intl.get('依赖设置'), + children: + }, { key: 'other', label: intl.get('其他设置'),