mirror of
https://github.com/whyour/qinglong.git
synced 2026-08-05 16:25:04 +08:00
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 77a8e00b17 | |||
| 99281a061e | |||
| 22eedebf14 | |||
| d7e0531935 | |||
| 16734326cf | |||
| 956cfe18be | |||
| a864a56917 | |||
| ab3fc9b5f1 | |||
| 8d899f1a53 | |||
| a1eef2c644 | |||
| aab096843c | |||
| acc7443004 | |||
| 042d7d3b8e | |||
| 0511a4af0d | |||
| 748a099087 | |||
| 742d0b2135 | |||
| 2081364325 |
@@ -6,10 +6,9 @@ on:
|
||||
- 'master'
|
||||
- 'develop'
|
||||
tags:
|
||||
- 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
|
||||
- 'v*'
|
||||
schedule:
|
||||
# 参考 https://jasonet.co/posts/scheduled-actions/
|
||||
- cron: '00 14 * * *' # GMT 15:00 => 北京时间 23:00
|
||||
- cron: '00 20 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
@@ -87,14 +86,15 @@ jobs:
|
||||
build:
|
||||
needs: build-static
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
# 由于 ubuntu-latest 中使用 linux6.x 内核 linux/s390x npm 无法使用
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
permissions:
|
||||
packages: write
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: '8.3.1'
|
||||
@@ -108,13 +108,13 @@ jobs:
|
||||
timezone: Asia/Shanghai
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Login to GHCR
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
@@ -122,7 +122,7 @@ jobs:
|
||||
|
||||
- name: Extract metadata (tags, labels) for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@v4
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: |
|
||||
${{ github.repository }}
|
||||
@@ -142,14 +142,14 @@ jobs:
|
||||
type=semver,pattern={{major}}
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Build and push
|
||||
id: docker_build
|
||||
uses: docker/build-push-action@v3
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
build-args: |
|
||||
MAINTAINER=${{ github.repository_owner }}
|
||||
|
||||
@@ -61,7 +61,12 @@ npm i @whyour/qinglong
|
||||
# curl -sSL get.docker.com | sh
|
||||
docker run -dit \
|
||||
-v $PWD/ql/data:/ql/data \
|
||||
# The 5700 after the colon is the default port, if QlPort is set, it needs to be the same as QlPort.
|
||||
-p 5700:5700 \
|
||||
# Deployment paths are not required and begin and end with a slash, e.g. /test/.
|
||||
-e QlBaseUrl="/" \
|
||||
# Deployment port is not required, when using host mode, you can set the port after service startup, default 5700
|
||||
-e QlPort="5700" \
|
||||
--name qinglong \
|
||||
--hostname qinglong \
|
||||
--restart unless-stopped \
|
||||
@@ -88,7 +93,12 @@ docker-compose down
|
||||
podman run -dit \
|
||||
--network bridge \
|
||||
-v $PWD/ql/data:/ql/data \
|
||||
# The 5700 after the colon is the default port, if QlPort is set, it needs to be the same as QlPort.
|
||||
-p 5700:5700 \
|
||||
# Deployment paths are not required and begin and end with a slash, e.g. /test/.
|
||||
-e QlBaseUrl="/" \
|
||||
# Deployment port is not required, when using host mode, you can set the port after service startup, default 5700
|
||||
-e QlPort="5700" \
|
||||
--name qinglong \
|
||||
--hostname qinglong \
|
||||
docker.io/whyour/qinglong:latest
|
||||
|
||||
@@ -63,9 +63,12 @@ npm i @whyour/qinglong
|
||||
# curl -sSL get.docker.com | sh
|
||||
docker run -dit \
|
||||
-v $PWD/ql/data:/ql/data \
|
||||
# 冒号后面的 5700 为默认端口,如果设置了 QlPort, 需要跟 QlPort 保持一致
|
||||
-p 5700:5700 \
|
||||
# 部署路径非必须,以斜杠开头和结尾,比如 /test/
|
||||
-e QlBaseUrl="/" \
|
||||
# 部署端口非必须,当使用 host 模式时,可以设置服务启动后的端口,默认 5700
|
||||
-e QlPort="5700" \
|
||||
--name qinglong \
|
||||
--hostname qinglong \
|
||||
--restart unless-stopped \
|
||||
@@ -92,9 +95,12 @@ docker-compose down
|
||||
podman run -dit \
|
||||
--network bridge \
|
||||
-v $PWD/ql/data:/ql/data \
|
||||
# 冒号后面的 5700 为默认端口,如果设置了 QlPort, 需要跟 QlPort 保持一致
|
||||
-p 5700:5700 \
|
||||
# 部署路径非必须,以斜杠开头和结尾,比如 /test/
|
||||
-e QlBaseUrl="/" \
|
||||
# 部署端口非必须,当使用 host 模式时,可以设置服务启动后的端口,默认 5700
|
||||
-e QlPort="5700" \
|
||||
--name qinglong \
|
||||
--hostname qinglong \
|
||||
docker.io/whyour/qinglong:latest
|
||||
|
||||
@@ -176,6 +176,9 @@ export default (app: Router) => {
|
||||
name: Joi.string().optional(),
|
||||
labels: Joi.array().optional(),
|
||||
sub_id: Joi.number().optional().allow(null),
|
||||
extra_schedules: Joi.array().optional().allow(null),
|
||||
task_before: Joi.string().optional().allow('').allow(null),
|
||||
task_after: Joi.string().optional().allow('').allow(null),
|
||||
}),
|
||||
}),
|
||||
async (req: Request, res: Response, next: NextFunction) => {
|
||||
@@ -333,6 +336,9 @@ export default (app: Router) => {
|
||||
schedule: Joi.string().required(),
|
||||
name: Joi.string().optional().allow(null),
|
||||
sub_id: Joi.number().optional().allow(null),
|
||||
extra_schedules: Joi.array().optional().allow(null),
|
||||
task_before: Joi.string().optional().allow('').allow(null),
|
||||
task_after: Joi.string().optional().allow('').allow(null),
|
||||
id: Joi.number().required(),
|
||||
}),
|
||||
}),
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ export default (app: Router) => {
|
||||
const logger: Logger = Container.get('logger');
|
||||
try {
|
||||
let result = [];
|
||||
const blacklist = ['node_modules', '.git'];
|
||||
const blacklist = ['node_modules', '.git', '.pnpm'];
|
||||
if (req.query.path) {
|
||||
const targetPath = path.join(
|
||||
config.scriptPath,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Request, Response } from 'express';
|
||||
import { pick } from 'lodash';
|
||||
import pick from 'lodash/pick';
|
||||
|
||||
let pickedEnv: Record<string, string>;
|
||||
|
||||
|
||||
+10
-1
@@ -18,6 +18,9 @@ export class Crontab {
|
||||
last_running_time?: number;
|
||||
last_execution_time?: number;
|
||||
sub_id?: number;
|
||||
extra_schedules?: Array<{ schedule: string }>;
|
||||
task_before?: string;
|
||||
task_after?: string;
|
||||
|
||||
constructor(options: Crontab) {
|
||||
this.name = options.name;
|
||||
@@ -39,6 +42,9 @@ export class Crontab {
|
||||
this.last_running_time = options.last_running_time || 0;
|
||||
this.last_execution_time = options.last_execution_time || 0;
|
||||
this.sub_id = options.sub_id;
|
||||
this.extra_schedules = options.extra_schedules;
|
||||
this.task_before = options.task_before;
|
||||
this.task_after = options.task_after;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +55,7 @@ export enum CrontabStatus {
|
||||
'disabled',
|
||||
}
|
||||
|
||||
export interface CronInstance extends Model<Crontab, Crontab>, Crontab {}
|
||||
export interface CronInstance extends Model<Crontab, Crontab>, Crontab { }
|
||||
export const CrontabModel = sequelize.define<CronInstance>('Crontab', {
|
||||
name: {
|
||||
unique: 'compositeIndex',
|
||||
@@ -75,4 +81,7 @@ export const CrontabModel = sequelize.define<CronInstance>('Crontab', {
|
||||
last_running_time: DataTypes.NUMBER,
|
||||
last_execution_time: DataTypes.NUMBER,
|
||||
sub_id: { type: DataTypes.NUMBER, allowNull: true },
|
||||
extra_schedules: DataTypes.JSON,
|
||||
task_before: DataTypes.STRING,
|
||||
task_after: DataTypes.STRING,
|
||||
});
|
||||
|
||||
@@ -55,6 +55,8 @@ export class BarkNotification extends NotificationBaseInfo {
|
||||
public barkIcon = 'https://qn.whyour.cn/logo.png';
|
||||
public barkSound = '';
|
||||
public barkGroup = 'qinglong';
|
||||
public barkLevel = 'active';
|
||||
public barkUrl = '';
|
||||
}
|
||||
|
||||
export class TelegramBotNotification extends NotificationBaseInfo {
|
||||
|
||||
Vendored
+2
@@ -3,3 +3,5 @@ declare namespace Express {
|
||||
platform: 'desktop' | 'mobile';
|
||||
}
|
||||
}
|
||||
|
||||
declare module 'pstree.remy';
|
||||
|
||||
+10
-1
@@ -48,7 +48,16 @@ export default async () => {
|
||||
} catch (error) {}
|
||||
try {
|
||||
await sequelize.query('alter table Crontabs add column sub_id NUMBER');
|
||||
} catch (error) {}
|
||||
} catch (error) { }
|
||||
try {
|
||||
await sequelize.query('alter table Crontabs add column extra_schedules JSON');
|
||||
} catch (error) { }
|
||||
try {
|
||||
await sequelize.query('alter table Crontabs add column task_before TEXT');
|
||||
} catch (error) { }
|
||||
try {
|
||||
await sequelize.query('alter table Crontabs add column task_after TEXT');
|
||||
} catch (error) { }
|
||||
|
||||
// 2.10-2.11 升级
|
||||
const cronDbFile = path.join(config.rootPath, 'db/crontab.db');
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Container } from 'typedi';
|
||||
import SystemService from '../services/system';
|
||||
import ScheduleService from '../services/schedule';
|
||||
import ScheduleService, { ScheduleTaskType } from '../services/schedule';
|
||||
import SubscriptionService from '../services/subscription';
|
||||
import config from '../config';
|
||||
import { fileExist } from '../config/util';
|
||||
@@ -22,7 +22,7 @@ export default async () => {
|
||||
id: NaN,
|
||||
name: '生成token',
|
||||
command: tokenCommand,
|
||||
};
|
||||
} as ScheduleTaskType;
|
||||
await scheduleService.cancelIntervalTask(cron);
|
||||
scheduleService.createIntervalTask(cron, {
|
||||
days: 28,
|
||||
|
||||
@@ -7,10 +7,13 @@ service Cron {
|
||||
rpc delCron(DeleteCronRequest) returns (DeleteCronResponse);
|
||||
}
|
||||
|
||||
message ISchedule { string schedule = 1; }
|
||||
|
||||
message ICron {
|
||||
string id = 1;
|
||||
string schedule = 2;
|
||||
string command = 3;
|
||||
repeated ISchedule extra_schedules = 4;
|
||||
}
|
||||
|
||||
message AddCronRequest { repeated ICron crons = 1; }
|
||||
|
||||
+144
-138
@@ -10,78 +10,150 @@ import {
|
||||
Metadata,
|
||||
ServiceError,
|
||||
UntypedServiceImplementation,
|
||||
} from '@grpc/grpc-js';
|
||||
import _m0 from 'protobufjs/minimal';
|
||||
} from "@grpc/grpc-js";
|
||||
import _m0 from "protobufjs/minimal";
|
||||
|
||||
export const protobufPackage = 'com.ql.cron';
|
||||
export const protobufPackage = "com.ql.cron";
|
||||
|
||||
export interface ISchedule {
|
||||
schedule: string;
|
||||
}
|
||||
|
||||
export interface ICron {
|
||||
id: string;
|
||||
schedule: string;
|
||||
command: string;
|
||||
extraSchedules: ISchedule[];
|
||||
}
|
||||
|
||||
export interface AddCronRequest {
|
||||
crons: ICron[];
|
||||
}
|
||||
|
||||
export interface AddCronResponse {}
|
||||
export interface AddCronResponse {
|
||||
}
|
||||
|
||||
export interface DeleteCronRequest {
|
||||
ids: string[];
|
||||
}
|
||||
|
||||
export interface DeleteCronResponse {}
|
||||
export interface DeleteCronResponse {
|
||||
}
|
||||
|
||||
function createBaseISchedule(): ISchedule {
|
||||
return { schedule: "" };
|
||||
}
|
||||
|
||||
export const ISchedule = {
|
||||
encode(message: ISchedule, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
|
||||
if (message.schedule !== "") {
|
||||
writer.uint32(10).string(message.schedule);
|
||||
}
|
||||
return writer;
|
||||
},
|
||||
|
||||
decode(input: _m0.Reader | Uint8Array, length?: number): ISchedule {
|
||||
const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input);
|
||||
let end = length === undefined ? reader.len : reader.pos + length;
|
||||
const message = createBaseISchedule();
|
||||
while (reader.pos < end) {
|
||||
const tag = reader.uint32();
|
||||
switch (tag >>> 3) {
|
||||
case 1:
|
||||
if (tag !== 10) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.schedule = reader.string();
|
||||
continue;
|
||||
}
|
||||
if ((tag & 7) === 4 || tag === 0) {
|
||||
break;
|
||||
}
|
||||
reader.skipType(tag & 7);
|
||||
}
|
||||
return message;
|
||||
},
|
||||
|
||||
fromJSON(object: any): ISchedule {
|
||||
return { schedule: isSet(object.schedule) ? String(object.schedule) : "" };
|
||||
},
|
||||
|
||||
toJSON(message: ISchedule): unknown {
|
||||
const obj: any = {};
|
||||
message.schedule !== undefined && (obj.schedule = message.schedule);
|
||||
return obj;
|
||||
},
|
||||
|
||||
create<I extends Exact<DeepPartial<ISchedule>, I>>(base?: I): ISchedule {
|
||||
return ISchedule.fromPartial(base ?? {});
|
||||
},
|
||||
|
||||
fromPartial<I extends Exact<DeepPartial<ISchedule>, I>>(object: I): ISchedule {
|
||||
const message = createBaseISchedule();
|
||||
message.schedule = object.schedule ?? "";
|
||||
return message;
|
||||
},
|
||||
};
|
||||
|
||||
function createBaseICron(): ICron {
|
||||
return { id: '', schedule: '', command: '' };
|
||||
return { id: "", schedule: "", command: "", extraSchedules: [] };
|
||||
}
|
||||
|
||||
export const ICron = {
|
||||
encode(message: ICron, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
|
||||
if (message.id !== '') {
|
||||
if (message.id !== "") {
|
||||
writer.uint32(10).string(message.id);
|
||||
}
|
||||
if (message.schedule !== '') {
|
||||
if (message.schedule !== "") {
|
||||
writer.uint32(18).string(message.schedule);
|
||||
}
|
||||
if (message.command !== '') {
|
||||
if (message.command !== "") {
|
||||
writer.uint32(26).string(message.command);
|
||||
}
|
||||
for (const v of message.extraSchedules) {
|
||||
ISchedule.encode(v!, writer.uint32(34).fork()).ldelim();
|
||||
}
|
||||
return writer;
|
||||
},
|
||||
|
||||
decode(input: _m0.Reader | Uint8Array, length?: number): ICron {
|
||||
const reader =
|
||||
input instanceof _m0.Reader ? input : _m0.Reader.create(input);
|
||||
const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input);
|
||||
let end = length === undefined ? reader.len : reader.pos + length;
|
||||
const message = createBaseICron();
|
||||
while (reader.pos < end) {
|
||||
const tag = reader.uint32();
|
||||
switch (tag >>> 3) {
|
||||
case 1:
|
||||
if (tag != 10) {
|
||||
if (tag !== 10) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.id = reader.string();
|
||||
continue;
|
||||
case 2:
|
||||
if (tag != 18) {
|
||||
if (tag !== 18) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.schedule = reader.string();
|
||||
continue;
|
||||
case 3:
|
||||
if (tag != 26) {
|
||||
if (tag !== 26) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.command = reader.string();
|
||||
continue;
|
||||
case 4:
|
||||
if (tag !== 34) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.extraSchedules.push(ISchedule.decode(reader, reader.uint32()));
|
||||
continue;
|
||||
}
|
||||
if ((tag & 7) == 4 || tag == 0) {
|
||||
if ((tag & 7) === 4 || tag === 0) {
|
||||
break;
|
||||
}
|
||||
reader.skipType(tag & 7);
|
||||
@@ -91,9 +163,12 @@ export const ICron = {
|
||||
|
||||
fromJSON(object: any): ICron {
|
||||
return {
|
||||
id: isSet(object.id) ? String(object.id) : '',
|
||||
schedule: isSet(object.schedule) ? String(object.schedule) : '',
|
||||
command: isSet(object.command) ? String(object.command) : '',
|
||||
id: isSet(object.id) ? String(object.id) : "",
|
||||
schedule: isSet(object.schedule) ? String(object.schedule) : "",
|
||||
command: isSet(object.command) ? String(object.command) : "",
|
||||
extraSchedules: Array.isArray(object?.extraSchedules)
|
||||
? object.extraSchedules.map((e: any) => ISchedule.fromJSON(e))
|
||||
: [],
|
||||
};
|
||||
},
|
||||
|
||||
@@ -102,6 +177,11 @@ export const ICron = {
|
||||
message.id !== undefined && (obj.id = message.id);
|
||||
message.schedule !== undefined && (obj.schedule = message.schedule);
|
||||
message.command !== undefined && (obj.command = message.command);
|
||||
if (message.extraSchedules) {
|
||||
obj.extraSchedules = message.extraSchedules.map((e) => e ? ISchedule.toJSON(e) : undefined);
|
||||
} else {
|
||||
obj.extraSchedules = [];
|
||||
}
|
||||
return obj;
|
||||
},
|
||||
|
||||
@@ -111,9 +191,10 @@ export const ICron = {
|
||||
|
||||
fromPartial<I extends Exact<DeepPartial<ICron>, I>>(object: I): ICron {
|
||||
const message = createBaseICron();
|
||||
message.id = object.id ?? '';
|
||||
message.schedule = object.schedule ?? '';
|
||||
message.command = object.command ?? '';
|
||||
message.id = object.id ?? "";
|
||||
message.schedule = object.schedule ?? "";
|
||||
message.command = object.command ?? "";
|
||||
message.extraSchedules = object.extraSchedules?.map((e) => ISchedule.fromPartial(e)) || [];
|
||||
return message;
|
||||
},
|
||||
};
|
||||
@@ -123,10 +204,7 @@ function createBaseAddCronRequest(): AddCronRequest {
|
||||
}
|
||||
|
||||
export const AddCronRequest = {
|
||||
encode(
|
||||
message: AddCronRequest,
|
||||
writer: _m0.Writer = _m0.Writer.create(),
|
||||
): _m0.Writer {
|
||||
encode(message: AddCronRequest, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
|
||||
for (const v of message.crons) {
|
||||
ICron.encode(v!, writer.uint32(10).fork()).ldelim();
|
||||
}
|
||||
@@ -134,22 +212,21 @@ export const AddCronRequest = {
|
||||
},
|
||||
|
||||
decode(input: _m0.Reader | Uint8Array, length?: number): AddCronRequest {
|
||||
const reader =
|
||||
input instanceof _m0.Reader ? input : _m0.Reader.create(input);
|
||||
const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input);
|
||||
let end = length === undefined ? reader.len : reader.pos + length;
|
||||
const message = createBaseAddCronRequest();
|
||||
while (reader.pos < end) {
|
||||
const tag = reader.uint32();
|
||||
switch (tag >>> 3) {
|
||||
case 1:
|
||||
if (tag != 10) {
|
||||
if (tag !== 10) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.crons.push(ICron.decode(reader, reader.uint32()));
|
||||
continue;
|
||||
}
|
||||
if ((tag & 7) == 4 || tag == 0) {
|
||||
if ((tag & 7) === 4 || tag === 0) {
|
||||
break;
|
||||
}
|
||||
reader.skipType(tag & 7);
|
||||
@@ -158,32 +235,24 @@ export const AddCronRequest = {
|
||||
},
|
||||
|
||||
fromJSON(object: any): AddCronRequest {
|
||||
return {
|
||||
crons: Array.isArray(object?.crons)
|
||||
? object.crons.map((e: any) => ICron.fromJSON(e))
|
||||
: [],
|
||||
};
|
||||
return { crons: Array.isArray(object?.crons) ? object.crons.map((e: any) => ICron.fromJSON(e)) : [] };
|
||||
},
|
||||
|
||||
toJSON(message: AddCronRequest): unknown {
|
||||
const obj: any = {};
|
||||
if (message.crons) {
|
||||
obj.crons = message.crons.map((e) => (e ? ICron.toJSON(e) : undefined));
|
||||
obj.crons = message.crons.map((e) => e ? ICron.toJSON(e) : undefined);
|
||||
} else {
|
||||
obj.crons = [];
|
||||
}
|
||||
return obj;
|
||||
},
|
||||
|
||||
create<I extends Exact<DeepPartial<AddCronRequest>, I>>(
|
||||
base?: I,
|
||||
): AddCronRequest {
|
||||
create<I extends Exact<DeepPartial<AddCronRequest>, I>>(base?: I): AddCronRequest {
|
||||
return AddCronRequest.fromPartial(base ?? {});
|
||||
},
|
||||
|
||||
fromPartial<I extends Exact<DeepPartial<AddCronRequest>, I>>(
|
||||
object: I,
|
||||
): AddCronRequest {
|
||||
fromPartial<I extends Exact<DeepPartial<AddCronRequest>, I>>(object: I): AddCronRequest {
|
||||
const message = createBaseAddCronRequest();
|
||||
message.crons = object.crons?.map((e) => ICron.fromPartial(e)) || [];
|
||||
return message;
|
||||
@@ -195,23 +264,19 @@ function createBaseAddCronResponse(): AddCronResponse {
|
||||
}
|
||||
|
||||
export const AddCronResponse = {
|
||||
encode(
|
||||
_: AddCronResponse,
|
||||
writer: _m0.Writer = _m0.Writer.create(),
|
||||
): _m0.Writer {
|
||||
encode(_: AddCronResponse, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
|
||||
return writer;
|
||||
},
|
||||
|
||||
decode(input: _m0.Reader | Uint8Array, length?: number): AddCronResponse {
|
||||
const reader =
|
||||
input instanceof _m0.Reader ? input : _m0.Reader.create(input);
|
||||
const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input);
|
||||
let end = length === undefined ? reader.len : reader.pos + length;
|
||||
const message = createBaseAddCronResponse();
|
||||
while (reader.pos < end) {
|
||||
const tag = reader.uint32();
|
||||
switch (tag >>> 3) {
|
||||
}
|
||||
if ((tag & 7) == 4 || tag == 0) {
|
||||
if ((tag & 7) === 4 || tag === 0) {
|
||||
break;
|
||||
}
|
||||
reader.skipType(tag & 7);
|
||||
@@ -228,15 +293,11 @@ export const AddCronResponse = {
|
||||
return obj;
|
||||
},
|
||||
|
||||
create<I extends Exact<DeepPartial<AddCronResponse>, I>>(
|
||||
base?: I,
|
||||
): AddCronResponse {
|
||||
create<I extends Exact<DeepPartial<AddCronResponse>, I>>(base?: I): AddCronResponse {
|
||||
return AddCronResponse.fromPartial(base ?? {});
|
||||
},
|
||||
|
||||
fromPartial<I extends Exact<DeepPartial<AddCronResponse>, I>>(
|
||||
_: I,
|
||||
): AddCronResponse {
|
||||
fromPartial<I extends Exact<DeepPartial<AddCronResponse>, I>>(_: I): AddCronResponse {
|
||||
const message = createBaseAddCronResponse();
|
||||
return message;
|
||||
},
|
||||
@@ -247,10 +308,7 @@ function createBaseDeleteCronRequest(): DeleteCronRequest {
|
||||
}
|
||||
|
||||
export const DeleteCronRequest = {
|
||||
encode(
|
||||
message: DeleteCronRequest,
|
||||
writer: _m0.Writer = _m0.Writer.create(),
|
||||
): _m0.Writer {
|
||||
encode(message: DeleteCronRequest, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
|
||||
for (const v of message.ids) {
|
||||
writer.uint32(10).string(v!);
|
||||
}
|
||||
@@ -258,22 +316,21 @@ export const DeleteCronRequest = {
|
||||
},
|
||||
|
||||
decode(input: _m0.Reader | Uint8Array, length?: number): DeleteCronRequest {
|
||||
const reader =
|
||||
input instanceof _m0.Reader ? input : _m0.Reader.create(input);
|
||||
const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input);
|
||||
let end = length === undefined ? reader.len : reader.pos + length;
|
||||
const message = createBaseDeleteCronRequest();
|
||||
while (reader.pos < end) {
|
||||
const tag = reader.uint32();
|
||||
switch (tag >>> 3) {
|
||||
case 1:
|
||||
if (tag != 10) {
|
||||
if (tag !== 10) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.ids.push(reader.string());
|
||||
continue;
|
||||
}
|
||||
if ((tag & 7) == 4 || tag == 0) {
|
||||
if ((tag & 7) === 4 || tag === 0) {
|
||||
break;
|
||||
}
|
||||
reader.skipType(tag & 7);
|
||||
@@ -282,11 +339,7 @@ export const DeleteCronRequest = {
|
||||
},
|
||||
|
||||
fromJSON(object: any): DeleteCronRequest {
|
||||
return {
|
||||
ids: Array.isArray(object?.ids)
|
||||
? object.ids.map((e: any) => String(e))
|
||||
: [],
|
||||
};
|
||||
return { ids: Array.isArray(object?.ids) ? object.ids.map((e: any) => String(e)) : [] };
|
||||
},
|
||||
|
||||
toJSON(message: DeleteCronRequest): unknown {
|
||||
@@ -299,15 +352,11 @@ export const DeleteCronRequest = {
|
||||
return obj;
|
||||
},
|
||||
|
||||
create<I extends Exact<DeepPartial<DeleteCronRequest>, I>>(
|
||||
base?: I,
|
||||
): DeleteCronRequest {
|
||||
create<I extends Exact<DeepPartial<DeleteCronRequest>, I>>(base?: I): DeleteCronRequest {
|
||||
return DeleteCronRequest.fromPartial(base ?? {});
|
||||
},
|
||||
|
||||
fromPartial<I extends Exact<DeepPartial<DeleteCronRequest>, I>>(
|
||||
object: I,
|
||||
): DeleteCronRequest {
|
||||
fromPartial<I extends Exact<DeepPartial<DeleteCronRequest>, I>>(object: I): DeleteCronRequest {
|
||||
const message = createBaseDeleteCronRequest();
|
||||
message.ids = object.ids?.map((e) => e) || [];
|
||||
return message;
|
||||
@@ -319,23 +368,19 @@ function createBaseDeleteCronResponse(): DeleteCronResponse {
|
||||
}
|
||||
|
||||
export const DeleteCronResponse = {
|
||||
encode(
|
||||
_: DeleteCronResponse,
|
||||
writer: _m0.Writer = _m0.Writer.create(),
|
||||
): _m0.Writer {
|
||||
encode(_: DeleteCronResponse, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
|
||||
return writer;
|
||||
},
|
||||
|
||||
decode(input: _m0.Reader | Uint8Array, length?: number): DeleteCronResponse {
|
||||
const reader =
|
||||
input instanceof _m0.Reader ? input : _m0.Reader.create(input);
|
||||
const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input);
|
||||
let end = length === undefined ? reader.len : reader.pos + length;
|
||||
const message = createBaseDeleteCronResponse();
|
||||
while (reader.pos < end) {
|
||||
const tag = reader.uint32();
|
||||
switch (tag >>> 3) {
|
||||
}
|
||||
if ((tag & 7) == 4 || tag == 0) {
|
||||
if ((tag & 7) === 4 || tag === 0) {
|
||||
break;
|
||||
}
|
||||
reader.skipType(tag & 7);
|
||||
@@ -352,15 +397,11 @@ export const DeleteCronResponse = {
|
||||
return obj;
|
||||
},
|
||||
|
||||
create<I extends Exact<DeepPartial<DeleteCronResponse>, I>>(
|
||||
base?: I,
|
||||
): DeleteCronResponse {
|
||||
create<I extends Exact<DeepPartial<DeleteCronResponse>, I>>(base?: I): DeleteCronResponse {
|
||||
return DeleteCronResponse.fromPartial(base ?? {});
|
||||
},
|
||||
|
||||
fromPartial<I extends Exact<DeepPartial<DeleteCronResponse>, I>>(
|
||||
_: I,
|
||||
): DeleteCronResponse {
|
||||
fromPartial<I extends Exact<DeepPartial<DeleteCronResponse>, I>>(_: I): DeleteCronResponse {
|
||||
const message = createBaseDeleteCronResponse();
|
||||
return message;
|
||||
},
|
||||
@@ -369,25 +410,21 @@ export const DeleteCronResponse = {
|
||||
export type CronService = typeof CronService;
|
||||
export const CronService = {
|
||||
addCron: {
|
||||
path: '/com.ql.cron.Cron/addCron',
|
||||
path: "/com.ql.cron.Cron/addCron",
|
||||
requestStream: false,
|
||||
responseStream: false,
|
||||
requestSerialize: (value: AddCronRequest) =>
|
||||
Buffer.from(AddCronRequest.encode(value).finish()),
|
||||
requestSerialize: (value: AddCronRequest) => Buffer.from(AddCronRequest.encode(value).finish()),
|
||||
requestDeserialize: (value: Buffer) => AddCronRequest.decode(value),
|
||||
responseSerialize: (value: AddCronResponse) =>
|
||||
Buffer.from(AddCronResponse.encode(value).finish()),
|
||||
responseSerialize: (value: AddCronResponse) => Buffer.from(AddCronResponse.encode(value).finish()),
|
||||
responseDeserialize: (value: Buffer) => AddCronResponse.decode(value),
|
||||
},
|
||||
delCron: {
|
||||
path: '/com.ql.cron.Cron/delCron',
|
||||
path: "/com.ql.cron.Cron/delCron",
|
||||
requestStream: false,
|
||||
responseStream: false,
|
||||
requestSerialize: (value: DeleteCronRequest) =>
|
||||
Buffer.from(DeleteCronRequest.encode(value).finish()),
|
||||
requestSerialize: (value: DeleteCronRequest) => Buffer.from(DeleteCronRequest.encode(value).finish()),
|
||||
requestDeserialize: (value: Buffer) => DeleteCronRequest.decode(value),
|
||||
responseSerialize: (value: DeleteCronResponse) =>
|
||||
Buffer.from(DeleteCronResponse.encode(value).finish()),
|
||||
responseSerialize: (value: DeleteCronResponse) => Buffer.from(DeleteCronResponse.encode(value).finish()),
|
||||
responseDeserialize: (value: Buffer) => DeleteCronResponse.decode(value),
|
||||
},
|
||||
} as const;
|
||||
@@ -415,67 +452,36 @@ export interface CronClient extends Client {
|
||||
): ClientUnaryCall;
|
||||
delCron(
|
||||
request: DeleteCronRequest,
|
||||
callback: (
|
||||
error: ServiceError | null,
|
||||
response: DeleteCronResponse,
|
||||
) => void,
|
||||
callback: (error: ServiceError | null, response: DeleteCronResponse) => void,
|
||||
): ClientUnaryCall;
|
||||
delCron(
|
||||
request: DeleteCronRequest,
|
||||
metadata: Metadata,
|
||||
callback: (
|
||||
error: ServiceError | null,
|
||||
response: DeleteCronResponse,
|
||||
) => void,
|
||||
callback: (error: ServiceError | null, response: DeleteCronResponse) => void,
|
||||
): ClientUnaryCall;
|
||||
delCron(
|
||||
request: DeleteCronRequest,
|
||||
metadata: Metadata,
|
||||
options: Partial<CallOptions>,
|
||||
callback: (
|
||||
error: ServiceError | null,
|
||||
response: DeleteCronResponse,
|
||||
) => void,
|
||||
callback: (error: ServiceError | null, response: DeleteCronResponse) => void,
|
||||
): ClientUnaryCall;
|
||||
}
|
||||
|
||||
export const CronClient = makeGenericClientConstructor(
|
||||
CronService,
|
||||
'com.ql.cron.Cron',
|
||||
) as unknown as {
|
||||
new (
|
||||
address: string,
|
||||
credentials: ChannelCredentials,
|
||||
options?: Partial<ClientOptions>,
|
||||
): CronClient;
|
||||
export const CronClient = makeGenericClientConstructor(CronService, "com.ql.cron.Cron") as unknown as {
|
||||
new (address: string, credentials: ChannelCredentials, options?: Partial<ClientOptions>): CronClient;
|
||||
service: typeof CronService;
|
||||
};
|
||||
|
||||
type Builtin =
|
||||
| Date
|
||||
| Function
|
||||
| Uint8Array
|
||||
| string
|
||||
| number
|
||||
| boolean
|
||||
| undefined;
|
||||
type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined;
|
||||
|
||||
export type DeepPartial<T> = T extends Builtin
|
||||
? T
|
||||
: T extends Array<infer U>
|
||||
? Array<DeepPartial<U>>
|
||||
: T extends ReadonlyArray<infer U>
|
||||
? ReadonlyArray<DeepPartial<U>>
|
||||
: T extends {}
|
||||
? { [K in keyof T]?: DeepPartial<T[K]> }
|
||||
export type DeepPartial<T> = T extends Builtin ? T
|
||||
: T extends Array<infer U> ? Array<DeepPartial<U>> : T extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>>
|
||||
: T extends {} ? { [K in keyof T]?: DeepPartial<T[K]> }
|
||||
: Partial<T>;
|
||||
|
||||
type KeysOfUnion<T> = T extends T ? keyof T : never;
|
||||
export type Exact<P, I extends P> = P extends Builtin
|
||||
? P
|
||||
: P & { [K in keyof P]: Exact<P[K], I[K]> } & {
|
||||
[K in Exclude<keyof I, KeysOfUnion<P>>]: never;
|
||||
};
|
||||
export type Exact<P, I extends P> = P extends Builtin ? P
|
||||
: P & { [K in keyof P]: Exact<P[K], I[K]> } & { [K in Exclude<keyof I, KeysOfUnion<P>>]: never };
|
||||
|
||||
function isSet(value: any): boolean {
|
||||
return value !== null && value !== undefined;
|
||||
|
||||
+51
-114
@@ -12,10 +12,10 @@ import {
|
||||
Metadata,
|
||||
ServiceError,
|
||||
UntypedServiceImplementation,
|
||||
} from '@grpc/grpc-js';
|
||||
import _m0 from 'protobufjs/minimal';
|
||||
} from "@grpc/grpc-js";
|
||||
import _m0 from "protobufjs/minimal";
|
||||
|
||||
export const protobufPackage = 'com.ql.health';
|
||||
export const protobufPackage = "com.ql.health";
|
||||
|
||||
export interface HealthCheckRequest {
|
||||
service: string;
|
||||
@@ -33,79 +33,71 @@ export enum HealthCheckResponse_ServingStatus {
|
||||
UNRECOGNIZED = -1,
|
||||
}
|
||||
|
||||
export function healthCheckResponse_ServingStatusFromJSON(
|
||||
object: any,
|
||||
): HealthCheckResponse_ServingStatus {
|
||||
export function healthCheckResponse_ServingStatusFromJSON(object: any): HealthCheckResponse_ServingStatus {
|
||||
switch (object) {
|
||||
case 0:
|
||||
case 'UNKNOWN':
|
||||
case "UNKNOWN":
|
||||
return HealthCheckResponse_ServingStatus.UNKNOWN;
|
||||
case 1:
|
||||
case 'SERVING':
|
||||
case "SERVING":
|
||||
return HealthCheckResponse_ServingStatus.SERVING;
|
||||
case 2:
|
||||
case 'NOT_SERVING':
|
||||
case "NOT_SERVING":
|
||||
return HealthCheckResponse_ServingStatus.NOT_SERVING;
|
||||
case 3:
|
||||
case 'SERVICE_UNKNOWN':
|
||||
case "SERVICE_UNKNOWN":
|
||||
return HealthCheckResponse_ServingStatus.SERVICE_UNKNOWN;
|
||||
case -1:
|
||||
case 'UNRECOGNIZED':
|
||||
case "UNRECOGNIZED":
|
||||
default:
|
||||
return HealthCheckResponse_ServingStatus.UNRECOGNIZED;
|
||||
}
|
||||
}
|
||||
|
||||
export function healthCheckResponse_ServingStatusToJSON(
|
||||
object: HealthCheckResponse_ServingStatus,
|
||||
): string {
|
||||
export function healthCheckResponse_ServingStatusToJSON(object: HealthCheckResponse_ServingStatus): string {
|
||||
switch (object) {
|
||||
case HealthCheckResponse_ServingStatus.UNKNOWN:
|
||||
return 'UNKNOWN';
|
||||
return "UNKNOWN";
|
||||
case HealthCheckResponse_ServingStatus.SERVING:
|
||||
return 'SERVING';
|
||||
return "SERVING";
|
||||
case HealthCheckResponse_ServingStatus.NOT_SERVING:
|
||||
return 'NOT_SERVING';
|
||||
return "NOT_SERVING";
|
||||
case HealthCheckResponse_ServingStatus.SERVICE_UNKNOWN:
|
||||
return 'SERVICE_UNKNOWN';
|
||||
return "SERVICE_UNKNOWN";
|
||||
case HealthCheckResponse_ServingStatus.UNRECOGNIZED:
|
||||
default:
|
||||
return 'UNRECOGNIZED';
|
||||
return "UNRECOGNIZED";
|
||||
}
|
||||
}
|
||||
|
||||
function createBaseHealthCheckRequest(): HealthCheckRequest {
|
||||
return { service: '' };
|
||||
return { service: "" };
|
||||
}
|
||||
|
||||
export const HealthCheckRequest = {
|
||||
encode(
|
||||
message: HealthCheckRequest,
|
||||
writer: _m0.Writer = _m0.Writer.create(),
|
||||
): _m0.Writer {
|
||||
if (message.service !== '') {
|
||||
encode(message: HealthCheckRequest, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
|
||||
if (message.service !== "") {
|
||||
writer.uint32(10).string(message.service);
|
||||
}
|
||||
return writer;
|
||||
},
|
||||
|
||||
decode(input: _m0.Reader | Uint8Array, length?: number): HealthCheckRequest {
|
||||
const reader =
|
||||
input instanceof _m0.Reader ? input : _m0.Reader.create(input);
|
||||
const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input);
|
||||
let end = length === undefined ? reader.len : reader.pos + length;
|
||||
const message = createBaseHealthCheckRequest();
|
||||
while (reader.pos < end) {
|
||||
const tag = reader.uint32();
|
||||
switch (tag >>> 3) {
|
||||
case 1:
|
||||
if (tag != 10) {
|
||||
if (tag !== 10) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.service = reader.string();
|
||||
continue;
|
||||
}
|
||||
if ((tag & 7) == 4 || tag == 0) {
|
||||
if ((tag & 7) === 4 || tag === 0) {
|
||||
break;
|
||||
}
|
||||
reader.skipType(tag & 7);
|
||||
@@ -114,7 +106,7 @@ export const HealthCheckRequest = {
|
||||
},
|
||||
|
||||
fromJSON(object: any): HealthCheckRequest {
|
||||
return { service: isSet(object.service) ? String(object.service) : '' };
|
||||
return { service: isSet(object.service) ? String(object.service) : "" };
|
||||
},
|
||||
|
||||
toJSON(message: HealthCheckRequest): unknown {
|
||||
@@ -123,17 +115,13 @@ export const HealthCheckRequest = {
|
||||
return obj;
|
||||
},
|
||||
|
||||
create<I extends Exact<DeepPartial<HealthCheckRequest>, I>>(
|
||||
base?: I,
|
||||
): HealthCheckRequest {
|
||||
create<I extends Exact<DeepPartial<HealthCheckRequest>, I>>(base?: I): HealthCheckRequest {
|
||||
return HealthCheckRequest.fromPartial(base ?? {});
|
||||
},
|
||||
|
||||
fromPartial<I extends Exact<DeepPartial<HealthCheckRequest>, I>>(
|
||||
object: I,
|
||||
): HealthCheckRequest {
|
||||
fromPartial<I extends Exact<DeepPartial<HealthCheckRequest>, I>>(object: I): HealthCheckRequest {
|
||||
const message = createBaseHealthCheckRequest();
|
||||
message.service = object.service ?? '';
|
||||
message.service = object.service ?? "";
|
||||
return message;
|
||||
},
|
||||
};
|
||||
@@ -143,10 +131,7 @@ function createBaseHealthCheckResponse(): HealthCheckResponse {
|
||||
}
|
||||
|
||||
export const HealthCheckResponse = {
|
||||
encode(
|
||||
message: HealthCheckResponse,
|
||||
writer: _m0.Writer = _m0.Writer.create(),
|
||||
): _m0.Writer {
|
||||
encode(message: HealthCheckResponse, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
|
||||
if (message.status !== 0) {
|
||||
writer.uint32(8).int32(message.status);
|
||||
}
|
||||
@@ -154,22 +139,21 @@ export const HealthCheckResponse = {
|
||||
},
|
||||
|
||||
decode(input: _m0.Reader | Uint8Array, length?: number): HealthCheckResponse {
|
||||
const reader =
|
||||
input instanceof _m0.Reader ? input : _m0.Reader.create(input);
|
||||
const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input);
|
||||
let end = length === undefined ? reader.len : reader.pos + length;
|
||||
const message = createBaseHealthCheckResponse();
|
||||
while (reader.pos < end) {
|
||||
const tag = reader.uint32();
|
||||
switch (tag >>> 3) {
|
||||
case 1:
|
||||
if (tag != 8) {
|
||||
if (tag !== 8) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.status = reader.int32() as any;
|
||||
continue;
|
||||
}
|
||||
if ((tag & 7) == 4 || tag == 0) {
|
||||
if ((tag & 7) === 4 || tag === 0) {
|
||||
break;
|
||||
}
|
||||
reader.skipType(tag & 7);
|
||||
@@ -178,29 +162,20 @@ export const HealthCheckResponse = {
|
||||
},
|
||||
|
||||
fromJSON(object: any): HealthCheckResponse {
|
||||
return {
|
||||
status: isSet(object.status)
|
||||
? healthCheckResponse_ServingStatusFromJSON(object.status)
|
||||
: 0,
|
||||
};
|
||||
return { status: isSet(object.status) ? healthCheckResponse_ServingStatusFromJSON(object.status) : 0 };
|
||||
},
|
||||
|
||||
toJSON(message: HealthCheckResponse): unknown {
|
||||
const obj: any = {};
|
||||
message.status !== undefined &&
|
||||
(obj.status = healthCheckResponse_ServingStatusToJSON(message.status));
|
||||
message.status !== undefined && (obj.status = healthCheckResponse_ServingStatusToJSON(message.status));
|
||||
return obj;
|
||||
},
|
||||
|
||||
create<I extends Exact<DeepPartial<HealthCheckResponse>, I>>(
|
||||
base?: I,
|
||||
): HealthCheckResponse {
|
||||
create<I extends Exact<DeepPartial<HealthCheckResponse>, I>>(base?: I): HealthCheckResponse {
|
||||
return HealthCheckResponse.fromPartial(base ?? {});
|
||||
},
|
||||
|
||||
fromPartial<I extends Exact<DeepPartial<HealthCheckResponse>, I>>(
|
||||
object: I,
|
||||
): HealthCheckResponse {
|
||||
fromPartial<I extends Exact<DeepPartial<HealthCheckResponse>, I>>(object: I): HealthCheckResponse {
|
||||
const message = createBaseHealthCheckResponse();
|
||||
message.status = object.status ?? 0;
|
||||
return message;
|
||||
@@ -210,25 +185,21 @@ export const HealthCheckResponse = {
|
||||
export type HealthService = typeof HealthService;
|
||||
export const HealthService = {
|
||||
check: {
|
||||
path: '/com.ql.health.Health/Check',
|
||||
path: "/com.ql.health.Health/Check",
|
||||
requestStream: false,
|
||||
responseStream: false,
|
||||
requestSerialize: (value: HealthCheckRequest) =>
|
||||
Buffer.from(HealthCheckRequest.encode(value).finish()),
|
||||
requestSerialize: (value: HealthCheckRequest) => Buffer.from(HealthCheckRequest.encode(value).finish()),
|
||||
requestDeserialize: (value: Buffer) => HealthCheckRequest.decode(value),
|
||||
responseSerialize: (value: HealthCheckResponse) =>
|
||||
Buffer.from(HealthCheckResponse.encode(value).finish()),
|
||||
responseSerialize: (value: HealthCheckResponse) => Buffer.from(HealthCheckResponse.encode(value).finish()),
|
||||
responseDeserialize: (value: Buffer) => HealthCheckResponse.decode(value),
|
||||
},
|
||||
watch: {
|
||||
path: '/com.ql.health.Health/Watch',
|
||||
path: "/com.ql.health.Health/Watch",
|
||||
requestStream: false,
|
||||
responseStream: true,
|
||||
requestSerialize: (value: HealthCheckRequest) =>
|
||||
Buffer.from(HealthCheckRequest.encode(value).finish()),
|
||||
requestSerialize: (value: HealthCheckRequest) => Buffer.from(HealthCheckRequest.encode(value).finish()),
|
||||
requestDeserialize: (value: Buffer) => HealthCheckRequest.decode(value),
|
||||
responseSerialize: (value: HealthCheckResponse) =>
|
||||
Buffer.from(HealthCheckResponse.encode(value).finish()),
|
||||
responseSerialize: (value: HealthCheckResponse) => Buffer.from(HealthCheckResponse.encode(value).finish()),
|
||||
responseDeserialize: (value: Buffer) => HealthCheckResponse.decode(value),
|
||||
},
|
||||
} as const;
|
||||
@@ -241,32 +212,20 @@ export interface HealthServer extends UntypedServiceImplementation {
|
||||
export interface HealthClient extends Client {
|
||||
check(
|
||||
request: HealthCheckRequest,
|
||||
callback: (
|
||||
error: ServiceError | null,
|
||||
response: HealthCheckResponse,
|
||||
) => void,
|
||||
callback: (error: ServiceError | null, response: HealthCheckResponse) => void,
|
||||
): ClientUnaryCall;
|
||||
check(
|
||||
request: HealthCheckRequest,
|
||||
metadata: Metadata,
|
||||
callback: (
|
||||
error: ServiceError | null,
|
||||
response: HealthCheckResponse,
|
||||
) => void,
|
||||
callback: (error: ServiceError | null, response: HealthCheckResponse) => void,
|
||||
): ClientUnaryCall;
|
||||
check(
|
||||
request: HealthCheckRequest,
|
||||
metadata: Metadata,
|
||||
options: Partial<CallOptions>,
|
||||
callback: (
|
||||
error: ServiceError | null,
|
||||
response: HealthCheckResponse,
|
||||
) => void,
|
||||
callback: (error: ServiceError | null, response: HealthCheckResponse) => void,
|
||||
): ClientUnaryCall;
|
||||
watch(
|
||||
request: HealthCheckRequest,
|
||||
options?: Partial<CallOptions>,
|
||||
): ClientReadableStream<HealthCheckResponse>;
|
||||
watch(request: HealthCheckRequest, options?: Partial<CallOptions>): ClientReadableStream<HealthCheckResponse>;
|
||||
watch(
|
||||
request: HealthCheckRequest,
|
||||
metadata?: Metadata,
|
||||
@@ -274,43 +233,21 @@ export interface HealthClient extends Client {
|
||||
): ClientReadableStream<HealthCheckResponse>;
|
||||
}
|
||||
|
||||
export const HealthClient = makeGenericClientConstructor(
|
||||
HealthService,
|
||||
'com.ql.health.Health',
|
||||
) as unknown as {
|
||||
new (
|
||||
address: string,
|
||||
credentials: ChannelCredentials,
|
||||
options?: Partial<ClientOptions>,
|
||||
): HealthClient;
|
||||
export const HealthClient = makeGenericClientConstructor(HealthService, "com.ql.health.Health") as unknown as {
|
||||
new (address: string, credentials: ChannelCredentials, options?: Partial<ClientOptions>): HealthClient;
|
||||
service: typeof HealthService;
|
||||
};
|
||||
|
||||
type Builtin =
|
||||
| Date
|
||||
| Function
|
||||
| Uint8Array
|
||||
| string
|
||||
| number
|
||||
| boolean
|
||||
| undefined;
|
||||
type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined;
|
||||
|
||||
export type DeepPartial<T> = T extends Builtin
|
||||
? T
|
||||
: T extends Array<infer U>
|
||||
? Array<DeepPartial<U>>
|
||||
: T extends ReadonlyArray<infer U>
|
||||
? ReadonlyArray<DeepPartial<U>>
|
||||
: T extends {}
|
||||
? { [K in keyof T]?: DeepPartial<T[K]> }
|
||||
export type DeepPartial<T> = T extends Builtin ? T
|
||||
: T extends Array<infer U> ? Array<DeepPartial<U>> : T extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>>
|
||||
: T extends {} ? { [K in keyof T]?: DeepPartial<T[K]> }
|
||||
: Partial<T>;
|
||||
|
||||
type KeysOfUnion<T> = T extends T ? keyof T : never;
|
||||
export type Exact<P, I extends P> = P extends Builtin
|
||||
? P
|
||||
: P & { [K in keyof P]: Exact<P[K], I[K]> } & {
|
||||
[K in Exclude<keyof I, KeysOfUnion<P>>]: never;
|
||||
};
|
||||
export type Exact<P, I extends P> = P extends Builtin ? P
|
||||
: P & { [K in keyof P]: Exact<P[K], I[K]> } & { [K in Exclude<keyof I, KeysOfUnion<P>>]: never };
|
||||
|
||||
function isSet(value: any): boolean {
|
||||
return value !== null && value !== undefined;
|
||||
|
||||
+24
-14
@@ -5,21 +5,15 @@ import { scheduleStacks } from './data';
|
||||
import { runCron } from '../shared/runCron';
|
||||
import { QL_PREFIX, TASK_PREFIX } from '../config/const';
|
||||
import Logger from '../loaders/logger';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
const addCron = (
|
||||
call: ServerUnaryCall<AddCronRequest, AddCronResponse>,
|
||||
callback: sendUnaryData<AddCronResponse>,
|
||||
) => {
|
||||
for (const item of call.request.crons) {
|
||||
const { id, schedule, command } = item;
|
||||
const { id, schedule, command, extraSchedules } = item;
|
||||
if (scheduleStacks.has(id)) {
|
||||
scheduleStacks.get(id)?.cancel();
|
||||
}
|
||||
|
||||
let cmdStr = command.trim();
|
||||
if (!cmdStr.startsWith(TASK_PREFIX) && !cmdStr.startsWith(QL_PREFIX)) {
|
||||
cmdStr = `${TASK_PREFIX}${cmdStr}`;
|
||||
scheduleStacks.get(id)?.forEach((x) => x.cancel());
|
||||
}
|
||||
|
||||
Logger.info(
|
||||
@@ -29,15 +23,31 @@ const addCron = (
|
||||
command,
|
||||
);
|
||||
|
||||
scheduleStacks.set(
|
||||
id,
|
||||
nodeSchedule.scheduleJob(id, schedule, async () => {
|
||||
if (extraSchedules?.length) {
|
||||
extraSchedules.forEach(x => {
|
||||
Logger.info(
|
||||
`[schedule][准备运行任务] 命令: ${cmdStr}`,
|
||||
'[schedule][创建定时任务], 任务ID: %s, cron: %s, 执行命令: %s',
|
||||
id,
|
||||
x.schedule,
|
||||
command,
|
||||
);
|
||||
runCron(`ID=${id} ${cmdStr}`);
|
||||
})
|
||||
}
|
||||
|
||||
scheduleStacks.set(id, [
|
||||
nodeSchedule.scheduleJob(id, schedule, async () => {
|
||||
Logger.info(`[schedule][准备运行任务] 命令: ${command}`);
|
||||
runCron(command);
|
||||
}),
|
||||
);
|
||||
...(extraSchedules?.length
|
||||
? extraSchedules.map((x) =>
|
||||
nodeSchedule.scheduleJob(id, x.schedule, async () => {
|
||||
Logger.info(`[schedule][准备运行任务] 命令: ${command}`);
|
||||
runCron(command);
|
||||
}),
|
||||
)
|
||||
: []),
|
||||
]);
|
||||
}
|
||||
|
||||
callback(null, null);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import nodeSchedule from 'node-schedule';
|
||||
import { ToadScheduler } from 'toad-scheduler';
|
||||
|
||||
export const scheduleStacks = new Map<string, nodeSchedule.Job>();
|
||||
export const scheduleStacks = new Map<string, nodeSchedule.Job[]>();
|
||||
|
||||
export const intervalSchedule = new ToadScheduler();
|
||||
|
||||
@@ -13,7 +13,7 @@ const delCron = (
|
||||
'[schedule][取消定时任务], 任务ID: %s',
|
||||
id,
|
||||
);
|
||||
scheduleStacks.get(id)?.cancel();
|
||||
scheduleStacks.get(id)?.forEach(x => x.cancel());
|
||||
scheduleStacks.delete(id);
|
||||
}
|
||||
}
|
||||
|
||||
+27
-28
@@ -31,9 +31,9 @@ export default class CronService {
|
||||
const tab = new Crontab(payload);
|
||||
tab.saved = false;
|
||||
const doc = await this.insert(tab);
|
||||
if (this.isSixCron(doc)) {
|
||||
if (this.isSixCron(doc) || doc.extra_schedules?.length) {
|
||||
await cronClient.addCron([
|
||||
{ id: String(doc.id), schedule: doc.schedule!, command: doc.command },
|
||||
{ id: String(doc.id), schedule: doc.schedule!, command: this.makeCommand(doc), extraSchedules: doc.extra_schedules || [] },
|
||||
]);
|
||||
}
|
||||
await this.set_crontab();
|
||||
@@ -52,15 +52,16 @@ export default class CronService {
|
||||
if (doc.isDisabled === 1) {
|
||||
return newDoc;
|
||||
}
|
||||
if (this.isSixCron(doc)) {
|
||||
await cronClient.delCron([String(newDoc.id)]);
|
||||
if (this.isSixCron(doc) || doc.extra_schedules?.length) {
|
||||
await cronClient.delCron([String(doc.id)]);
|
||||
}
|
||||
if (this.isSixCron(newDoc)) {
|
||||
if (this.isSixCron(newDoc) || newDoc.extra_schedules?.length) {
|
||||
await cronClient.addCron([
|
||||
{
|
||||
id: String(newDoc.id),
|
||||
schedule: newDoc.schedule!,
|
||||
command: newDoc.command,
|
||||
command: this.makeCommand(newDoc),
|
||||
extraSchedules: newDoc.extra_schedules || []
|
||||
},
|
||||
]);
|
||||
}
|
||||
@@ -405,21 +406,7 @@ export default class CronService {
|
||||
this.logger.silly('ID: ' + id);
|
||||
this.logger.silly('Original command: ' + command);
|
||||
|
||||
let cmdStr = command;
|
||||
if (!cmdStr.startsWith(TASK_PREFIX) && !cmdStr.startsWith(QL_PREFIX)) {
|
||||
cmdStr = `${TASK_PREFIX}${cmdStr}`;
|
||||
}
|
||||
if (
|
||||
cmdStr.endsWith('.js') ||
|
||||
cmdStr.endsWith('.py') ||
|
||||
cmdStr.endsWith('.pyc') ||
|
||||
cmdStr.endsWith('.sh') ||
|
||||
cmdStr.endsWith('.ts')
|
||||
) {
|
||||
cmdStr = `${cmdStr} now`;
|
||||
}
|
||||
|
||||
const cp = spawn(`real_log_path=${logPath} ID=${id} ${cmdStr}`, { shell: '/bin/bash' });
|
||||
const cp = spawn(`real_log_path=${logPath} no_delay=true ${this.makeCommand(cron)}`, { shell: '/bin/bash' });
|
||||
|
||||
await CrontabModel.update(
|
||||
{ status: CrontabStatus.running, pid: cp.pid, log_path: logPath },
|
||||
@@ -462,7 +449,8 @@ export default class CronService {
|
||||
.map((doc) => ({
|
||||
id: String(doc.id),
|
||||
schedule: doc.schedule!,
|
||||
command: doc.command,
|
||||
command: this.makeCommand(doc),
|
||||
extraSchedules: doc.extra_schedules || []
|
||||
}));
|
||||
await cronClient.addCron(sixCron);
|
||||
await this.set_crontab();
|
||||
@@ -505,12 +493,22 @@ export default class CronService {
|
||||
}
|
||||
}
|
||||
|
||||
private make_command(tab: Crontab) {
|
||||
private makeCommand(tab: Crontab) {
|
||||
let command = tab.command.trim();
|
||||
if (!command.startsWith(TASK_PREFIX) && !command.startsWith(QL_PREFIX)) {
|
||||
command = `${TASK_PREFIX}${tab.command}`;
|
||||
}
|
||||
const crontab_job_string = `ID=${tab.id} ${command}`;
|
||||
let commandVariable = `ID=${tab.id} `
|
||||
if (tab.task_before) {
|
||||
commandVariable += `task_before='${tab.task_before.replace(/'/g, "'\\''")
|
||||
.trim()}' `;
|
||||
}
|
||||
if (tab.task_after) {
|
||||
commandVariable += `task_after='${tab.task_after.replace(/'/g, "'\\''")
|
||||
.trim()}' `;
|
||||
}
|
||||
|
||||
const crontab_job_string = `${commandVariable}${command}`;
|
||||
return crontab_job_string;
|
||||
}
|
||||
|
||||
@@ -519,16 +517,16 @@ export default class CronService {
|
||||
var crontab_string = '';
|
||||
tabs.data.forEach((tab) => {
|
||||
const _schedule = tab.schedule && tab.schedule.split(/ +/);
|
||||
if (tab.isDisabled === 1 || _schedule!.length !== 5) {
|
||||
if (tab.isDisabled === 1 || _schedule!.length !== 5 || tab.extra_schedules?.length) {
|
||||
crontab_string += '# ';
|
||||
crontab_string += tab.schedule;
|
||||
crontab_string += ' ';
|
||||
crontab_string += this.make_command(tab);
|
||||
crontab_string += this.makeCommand(tab);
|
||||
crontab_string += '\n';
|
||||
} else {
|
||||
crontab_string += tab.schedule;
|
||||
crontab_string += ' ';
|
||||
crontab_string += this.make_command(tab);
|
||||
crontab_string += this.makeCommand(tab);
|
||||
crontab_string += '\n';
|
||||
}
|
||||
});
|
||||
@@ -582,7 +580,8 @@ export default class CronService {
|
||||
.map((doc) => ({
|
||||
id: String(doc.id),
|
||||
schedule: doc.schedule!,
|
||||
command: doc.command,
|
||||
command: this.makeCommand(doc),
|
||||
extraSchedules: doc.extra_schedules || []
|
||||
}));
|
||||
await cronClient.addCron(sixCron);
|
||||
}
|
||||
|
||||
@@ -195,7 +195,7 @@ export default class NotificationService {
|
||||
}
|
||||
|
||||
private async bark() {
|
||||
let { barkPush, barkIcon, barkSound, barkGroup } = this.params;
|
||||
let { barkPush, barkIcon, barkSound, barkGroup, barkLevel, barkUrl } = this.params;
|
||||
if (!barkPush.startsWith('http')) {
|
||||
barkPush = `https://api.day.app/${barkPush}`;
|
||||
}
|
||||
@@ -203,7 +203,7 @@ export default class NotificationService {
|
||||
this.title,
|
||||
)}/${encodeURIComponent(
|
||||
this.content,
|
||||
)}?icon=${barkIcon}&sound=${barkSound}&group=${barkGroup}`;
|
||||
)}?icon=${barkIcon}&sound=${barkSound}&group=${barkGroup}&level=${barkLevel}&url=${barkUrl}`;
|
||||
|
||||
try {
|
||||
const res: any = await got
|
||||
|
||||
@@ -12,7 +12,7 @@ import dayjs from 'dayjs';
|
||||
import taskLimit from '../shared/pLimit';
|
||||
import { spawn } from 'cross-spawn';
|
||||
|
||||
interface ScheduleTaskType {
|
||||
export interface ScheduleTaskType {
|
||||
id: number;
|
||||
command: string;
|
||||
name?: string;
|
||||
|
||||
@@ -7,7 +7,7 @@ import { SockMessage } from '../data/sock';
|
||||
export default class SockService {
|
||||
private clients: Connection[] = [];
|
||||
|
||||
constructor(@Inject('logger') private logger: winston.Logger) {}
|
||||
constructor(@Inject('logger') private logger: winston.Logger) { }
|
||||
|
||||
public getClients() {
|
||||
return this.clients;
|
||||
|
||||
@@ -28,7 +28,7 @@ import taskLimit from '../shared/pLimit';
|
||||
import tar from 'tar';
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import { sum } from 'lodash';
|
||||
import sum from 'lodash/sum';
|
||||
|
||||
@Service()
|
||||
export default class SystemService {
|
||||
@@ -84,7 +84,7 @@ export default class SystemService {
|
||||
});
|
||||
if (info.logRemoveFrequency) {
|
||||
const cron = {
|
||||
id: result.id,
|
||||
id: result.id || NaN,
|
||||
name: '删除日志',
|
||||
command: `ql rmlog ${info.logRemoveFrequency}`,
|
||||
};
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ map $http_upgrade $connection_upgrade {
|
||||
}
|
||||
|
||||
server {
|
||||
listen 5700;
|
||||
IPV4_CONFIG
|
||||
IPV6_CONFIG
|
||||
ssl_session_timeout 5m;
|
||||
|
||||
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
{
|
||||
"watch": ["back", ".env"],
|
||||
"ext": "js,ts,json",
|
||||
"ignore": ["src/**/*.spec.ts"],
|
||||
"exec": "ts-node --transpile-only ./back/app.ts"
|
||||
"exec": "ts-node -P tsconfig.back.json ./back/app.ts"
|
||||
}
|
||||
|
||||
+5
-5
@@ -4,8 +4,8 @@
|
||||
"start": "concurrently -n w: npm:start:*",
|
||||
"start:front": "max dev",
|
||||
"start:back": "nodemon",
|
||||
"start:public": "ts-node --transpile-only ./back/public.ts",
|
||||
"start:rpc": "ts-node --transpile-only ./back/schedule/index.ts",
|
||||
"start:public": "ts-node -P tsconfig.back.json ./back/public.ts",
|
||||
"start:rpc": "ts-node -P tsconfig.back.json ./back/schedule/index.ts",
|
||||
"build:front": "max build",
|
||||
"build:back": "tsc -p tsconfig.back.json",
|
||||
"panel": "npm run build:back && node static/build/app.js",
|
||||
@@ -69,11 +69,11 @@
|
||||
"dotenv": "^16.0.0",
|
||||
"express": "^4.17.3",
|
||||
"express-jwt": "^6.1.1",
|
||||
"express-rate-limit": "^6.7.0",
|
||||
"express-rate-limit": "^7.0.0",
|
||||
"express-urlrewrite": "^1.4.0",
|
||||
"form-data": "^4.0.0",
|
||||
"got": "^11.8.2",
|
||||
"hpagent": "^0.1.2",
|
||||
"hpagent": "^1.2.0",
|
||||
"http-proxy-middleware": "^2.0.6",
|
||||
"iconv-lite": "^0.6.3",
|
||||
"js-yaml": "^4.1.0",
|
||||
@@ -162,7 +162,7 @@
|
||||
"ts-proto": "^1.146.0",
|
||||
"tslib": "^2.4.0",
|
||||
"tsx": "^3.12.3",
|
||||
"typescript": "4.8.4",
|
||||
"typescript": "5.2.2",
|
||||
"vh-check": "^2.0.5",
|
||||
"virtualizedtableforantd4": "1.3.0",
|
||||
"webpack": "^5.70.0",
|
||||
|
||||
Generated
+68
-67
@@ -44,8 +44,8 @@ dependencies:
|
||||
specifier: ^6.1.1
|
||||
version: 6.1.2
|
||||
express-rate-limit:
|
||||
specifier: ^6.7.0
|
||||
version: 6.7.0(express@4.18.2)
|
||||
specifier: ^7.0.0
|
||||
version: 7.0.0(express@4.18.2)
|
||||
express-urlrewrite:
|
||||
specifier: ^1.4.0
|
||||
version: 1.4.0
|
||||
@@ -56,8 +56,8 @@ dependencies:
|
||||
specifier: ^11.8.2
|
||||
version: 11.8.6
|
||||
hpagent:
|
||||
specifier: ^0.1.2
|
||||
version: 0.1.2
|
||||
specifier: ^1.2.0
|
||||
version: 1.2.0
|
||||
http-proxy-middleware:
|
||||
specifier: ^2.0.6
|
||||
version: 2.0.6(@types/express@4.17.17)
|
||||
@@ -224,7 +224,7 @@ devDependencies:
|
||||
version: 4.21.9(@babel/runtime@7.22.3)(@codemirror/autocomplete@6.9.0)(@codemirror/language@6.9.0)(@codemirror/lint@6.4.0)(@codemirror/search@6.5.1)(@codemirror/state@6.2.1)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.16.0)(codemirror@6.0.1)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@umijs/max':
|
||||
specifier: ^4.0.72
|
||||
version: 4.0.72(@types/node@17.0.45)(@types/react-dom@18.2.4)(@types/react@18.2.8)(prettier@2.8.8)(react-dom@18.2.0)(react@18.2.0)(sockjs-client@1.6.1)(typescript@4.8.4)(webpack@5.85.1)
|
||||
version: 4.0.72(@types/node@17.0.45)(@types/react-dom@18.2.4)(@types/react@18.2.8)(prettier@2.8.8)(react-dom@18.2.0)(react@18.2.0)(sockjs-client@1.6.1)(typescript@5.2.2)(webpack@5.85.1)
|
||||
'@umijs/ssr-darkreader':
|
||||
specifier: ^4.9.45
|
||||
version: 4.9.45
|
||||
@@ -308,7 +308,7 @@ devDependencies:
|
||||
version: 1.6.1
|
||||
ts-node:
|
||||
specifier: ^10.6.0
|
||||
version: 10.9.1(@types/node@17.0.45)(typescript@4.8.4)
|
||||
version: 10.9.1(@types/node@17.0.45)(typescript@5.2.2)
|
||||
ts-proto:
|
||||
specifier: ^1.146.0
|
||||
version: 1.148.2
|
||||
@@ -319,8 +319,8 @@ devDependencies:
|
||||
specifier: ^3.12.3
|
||||
version: 3.12.7
|
||||
typescript:
|
||||
specifier: 4.8.4
|
||||
version: 4.8.4
|
||||
specifier: 5.2.2
|
||||
version: 5.2.2
|
||||
vh-check:
|
||||
specifier: ^2.0.5
|
||||
version: 2.0.5
|
||||
@@ -5117,7 +5117,7 @@ packages:
|
||||
'@types/yargs-parser': 21.0.0
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/eslint-plugin@5.48.1(@typescript-eslint/parser@5.48.1)(eslint@8.35.0)(typescript@4.8.4):
|
||||
/@typescript-eslint/eslint-plugin@5.48.1(@typescript-eslint/parser@5.48.1)(eslint@8.35.0)(typescript@5.2.2):
|
||||
resolution: {integrity: sha512-9nY5K1Rp2ppmpb9s9S2aBiF3xo5uExCehMDmYmmFqqyxgenbHJ3qbarcLt4ITgaD6r/2ypdlcFRdcuVPnks+fQ==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
@@ -5130,23 +5130,23 @@ packages:
|
||||
typescript:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/parser': 5.48.1(eslint@8.35.0)(typescript@4.8.4)
|
||||
'@typescript-eslint/parser': 5.48.1(eslint@8.35.0)(typescript@5.2.2)
|
||||
'@typescript-eslint/scope-manager': 5.48.1
|
||||
'@typescript-eslint/type-utils': 5.48.1(eslint@8.35.0)(typescript@4.8.4)
|
||||
'@typescript-eslint/utils': 5.48.1(eslint@8.35.0)(typescript@4.8.4)
|
||||
'@typescript-eslint/type-utils': 5.48.1(eslint@8.35.0)(typescript@5.2.2)
|
||||
'@typescript-eslint/utils': 5.48.1(eslint@8.35.0)(typescript@5.2.2)
|
||||
debug: 4.3.4
|
||||
eslint: 8.35.0
|
||||
ignore: 5.2.4
|
||||
natural-compare-lite: 1.4.0
|
||||
regexpp: 3.2.0
|
||||
semver: 7.5.1
|
||||
tsutils: 3.21.0(typescript@4.8.4)
|
||||
typescript: 4.8.4
|
||||
tsutils: 3.21.0(typescript@5.2.2)
|
||||
typescript: 5.2.2
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/parser@5.48.1(eslint@8.35.0)(typescript@4.8.4):
|
||||
/@typescript-eslint/parser@5.48.1(eslint@8.35.0)(typescript@5.2.2):
|
||||
resolution: {integrity: sha512-4yg+FJR/V1M9Xoq56SF9Iygqm+r5LMXvheo6DQ7/yUWynQ4YfCRnsKuRgqH4EQ5Ya76rVwlEpw4Xu+TgWQUcdA==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
@@ -5160,10 +5160,10 @@ packages:
|
||||
dependencies:
|
||||
'@typescript-eslint/scope-manager': 5.48.1
|
||||
'@typescript-eslint/types': 5.48.1
|
||||
'@typescript-eslint/typescript-estree': 5.48.1(typescript@4.8.4)
|
||||
'@typescript-eslint/typescript-estree': 5.48.1(typescript@5.2.2)
|
||||
debug: 4.3.4
|
||||
eslint: 8.35.0
|
||||
typescript: 4.8.4
|
||||
typescript: 5.2.2
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
@@ -5184,7 +5184,7 @@ packages:
|
||||
'@typescript-eslint/visitor-keys': 5.59.9
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/type-utils@5.48.1(eslint@8.35.0)(typescript@4.8.4):
|
||||
/@typescript-eslint/type-utils@5.48.1(eslint@8.35.0)(typescript@5.2.2):
|
||||
resolution: {integrity: sha512-Hyr8HU8Alcuva1ppmqSYtM/Gp0q4JOp1F+/JH5D1IZm/bUBrV0edoewQZiEc1r6I8L4JL21broddxK8HAcZiqQ==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
@@ -5196,12 +5196,12 @@ packages:
|
||||
typescript:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/typescript-estree': 5.48.1(typescript@4.8.4)
|
||||
'@typescript-eslint/utils': 5.48.1(eslint@8.35.0)(typescript@4.8.4)
|
||||
'@typescript-eslint/typescript-estree': 5.48.1(typescript@5.2.2)
|
||||
'@typescript-eslint/utils': 5.48.1(eslint@8.35.0)(typescript@5.2.2)
|
||||
debug: 4.3.4
|
||||
eslint: 8.35.0
|
||||
tsutils: 3.21.0(typescript@4.8.4)
|
||||
typescript: 4.8.4
|
||||
tsutils: 3.21.0(typescript@5.2.2)
|
||||
typescript: 5.2.2
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
@@ -5216,7 +5216,7 @@ packages:
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/typescript-estree@5.48.1(typescript@4.8.4):
|
||||
/@typescript-eslint/typescript-estree@5.48.1(typescript@5.2.2):
|
||||
resolution: {integrity: sha512-Hut+Osk5FYr+sgFh8J/FHjqX6HFcDzTlWLrFqGoK5kVUN3VBHF/QzZmAsIXCQ8T/W9nQNBTqalxi1P3LSqWnRA==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
@@ -5231,13 +5231,13 @@ packages:
|
||||
globby: 11.1.0
|
||||
is-glob: 4.0.3
|
||||
semver: 7.5.1
|
||||
tsutils: 3.21.0(typescript@4.8.4)
|
||||
typescript: 4.8.4
|
||||
tsutils: 3.21.0(typescript@5.2.2)
|
||||
typescript: 5.2.2
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/typescript-estree@5.59.9(typescript@4.8.4):
|
||||
/@typescript-eslint/typescript-estree@5.59.9(typescript@5.2.2):
|
||||
resolution: {integrity: sha512-pmM0/VQ7kUhd1QyIxgS+aRvMgw+ZljB3eDb+jYyp6d2bC0mQWLzUDF+DLwCTkQ3tlNyVsvZRXjFyV0LkU/aXjA==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
@@ -5252,13 +5252,13 @@ packages:
|
||||
globby: 11.1.0
|
||||
is-glob: 4.0.3
|
||||
semver: 7.5.1
|
||||
tsutils: 3.21.0(typescript@4.8.4)
|
||||
typescript: 4.8.4
|
||||
tsutils: 3.21.0(typescript@5.2.2)
|
||||
typescript: 5.2.2
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/utils@5.48.1(eslint@8.35.0)(typescript@4.8.4):
|
||||
/@typescript-eslint/utils@5.48.1(eslint@8.35.0)(typescript@5.2.2):
|
||||
resolution: {integrity: sha512-SmQuSrCGUOdmGMwivW14Z0Lj8dxG1mOFZ7soeJ0TQZEJcs3n5Ndgkg0A4bcMFzBELqLJ6GTHnEU+iIoaD6hFGA==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
@@ -5271,7 +5271,7 @@ packages:
|
||||
'@types/semver': 7.5.0
|
||||
'@typescript-eslint/scope-manager': 5.48.1
|
||||
'@typescript-eslint/types': 5.48.1
|
||||
'@typescript-eslint/typescript-estree': 5.48.1(typescript@4.8.4)
|
||||
'@typescript-eslint/typescript-estree': 5.48.1(typescript@5.2.2)
|
||||
eslint: 8.35.0
|
||||
eslint-scope: 5.1.1
|
||||
eslint-utils: 3.0.0(eslint@8.35.0)
|
||||
@@ -5281,7 +5281,7 @@ packages:
|
||||
- typescript
|
||||
dev: true
|
||||
|
||||
/@typescript-eslint/utils@5.59.9(eslint@8.35.0)(typescript@4.8.4):
|
||||
/@typescript-eslint/utils@5.59.9(eslint@8.35.0)(typescript@5.2.2):
|
||||
resolution: {integrity: sha512-1PuMYsju/38I5Ggblaeb98TOoUvjhRvLpLa1DoTOFaLWqaXl/1iQ1eGurTXgBY58NUdtfTXKP5xBq7q9NDaLKg==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
@@ -5295,7 +5295,7 @@ packages:
|
||||
'@types/semver': 7.5.0
|
||||
'@typescript-eslint/scope-manager': 5.59.9
|
||||
'@typescript-eslint/types': 5.59.9
|
||||
'@typescript-eslint/typescript-estree': 5.59.9(typescript@4.8.4)
|
||||
'@typescript-eslint/typescript-estree': 5.59.9(typescript@5.2.2)
|
||||
eslint: 8.35.0
|
||||
eslint-scope: 5.1.1
|
||||
semver: 7.5.1
|
||||
@@ -5486,7 +5486,7 @@ packages:
|
||||
- terser
|
||||
dev: true
|
||||
|
||||
/@umijs/bundler-webpack@4.0.72(sockjs-client@1.6.1)(typescript@4.8.4)(webpack@5.85.1):
|
||||
/@umijs/bundler-webpack@4.0.72(sockjs-client@1.6.1)(typescript@5.2.2)(webpack@5.85.1):
|
||||
resolution: {integrity: sha512-0oTvna4AdMoSvRWeF0E8u8/aKASwll226DkLKvjYDs5FE9nhbxIHevsoSRX7TnlEDPNfV/a3kVRnRG1dR2oJnQ==}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
@@ -5503,7 +5503,7 @@ packages:
|
||||
cors: 2.8.5
|
||||
css-loader: 6.7.1(webpack@5.85.1)
|
||||
es5-imcompatible-versions: 0.1.83
|
||||
fork-ts-checker-webpack-plugin: 8.0.0(typescript@4.8.4)(webpack@5.85.1)
|
||||
fork-ts-checker-webpack-plugin: 8.0.0(typescript@5.2.2)(webpack@5.85.1)
|
||||
jest-worker: 29.4.3
|
||||
lightningcss: 1.19.0
|
||||
node-libs-browser: 2.2.1
|
||||
@@ -5648,16 +5648,16 @@ packages:
|
||||
query-string: 6.14.1
|
||||
dev: true
|
||||
|
||||
/@umijs/lint@4.0.72(eslint@8.35.0)(stylelint@14.8.2)(typescript@4.8.4):
|
||||
/@umijs/lint@4.0.72(eslint@8.35.0)(stylelint@14.8.2)(typescript@5.2.2):
|
||||
resolution: {integrity: sha512-kH3L81Rex+jj5WeyJjR2G6yI1/0KFpr91ZtXeMy9Iyd4G7mEUJl3Fl/9iUEwZ2sgUa7kEJ+28H43eER5W4A6bg==}
|
||||
dependencies:
|
||||
'@babel/core': 7.21.0
|
||||
'@babel/eslint-parser': 7.19.1(@babel/core@7.21.0)(eslint@8.35.0)
|
||||
'@stylelint/postcss-css-in-js': 0.38.0(postcss-syntax@0.36.2)(postcss@8.4.24)
|
||||
'@typescript-eslint/eslint-plugin': 5.48.1(@typescript-eslint/parser@5.48.1)(eslint@8.35.0)(typescript@4.8.4)
|
||||
'@typescript-eslint/parser': 5.48.1(eslint@8.35.0)(typescript@4.8.4)
|
||||
'@typescript-eslint/eslint-plugin': 5.48.1(@typescript-eslint/parser@5.48.1)(eslint@8.35.0)(typescript@5.2.2)
|
||||
'@typescript-eslint/parser': 5.48.1(eslint@8.35.0)(typescript@5.2.2)
|
||||
'@umijs/babel-preset-umi': 4.0.72
|
||||
eslint-plugin-jest: 27.2.1(@typescript-eslint/eslint-plugin@5.48.1)(eslint@8.35.0)(typescript@4.8.4)
|
||||
eslint-plugin-jest: 27.2.1(@typescript-eslint/eslint-plugin@5.48.1)(eslint@8.35.0)(typescript@5.2.2)
|
||||
eslint-plugin-react: 7.32.2(eslint@8.35.0)
|
||||
eslint-plugin-react-hooks: 4.6.0(eslint@8.35.0)
|
||||
postcss: 8.4.24
|
||||
@@ -5677,16 +5677,16 @@ packages:
|
||||
- typescript
|
||||
dev: true
|
||||
|
||||
/@umijs/max@4.0.72(@types/node@17.0.45)(@types/react-dom@18.2.4)(@types/react@18.2.8)(prettier@2.8.8)(react-dom@18.2.0)(react@18.2.0)(sockjs-client@1.6.1)(typescript@4.8.4)(webpack@5.85.1):
|
||||
/@umijs/max@4.0.72(@types/node@17.0.45)(@types/react-dom@18.2.4)(@types/react@18.2.8)(prettier@2.8.8)(react-dom@18.2.0)(react@18.2.0)(sockjs-client@1.6.1)(typescript@5.2.2)(webpack@5.85.1):
|
||||
resolution: {integrity: sha512-5e5BwaSBCdGWlj0PZ2I73+WLLe/8AibgDt2OtXc86YujRkhSKGY740pYgqy2PAszV8MjDMg8Sqs+gZG13C5z8w==}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
'@umijs/lint': 4.0.72(eslint@8.35.0)(stylelint@14.8.2)(typescript@4.8.4)
|
||||
'@umijs/lint': 4.0.72(eslint@8.35.0)(stylelint@14.8.2)(typescript@5.2.2)
|
||||
'@umijs/plugins': 4.0.72(@types/react-dom@18.2.4)(@types/react@18.2.8)(antd@4.24.10)(react-dom@18.2.0)(react@18.2.0)
|
||||
antd: 4.24.10(react-dom@18.2.0)(react@18.2.0)
|
||||
eslint: 8.35.0
|
||||
stylelint: 14.8.2
|
||||
umi: 4.0.72(@types/node@17.0.45)(@types/react@18.2.8)(eslint@8.35.0)(prettier@2.8.8)(react-dom@18.2.0)(react@18.2.0)(sockjs-client@1.6.1)(stylelint@14.8.2)(typescript@4.8.4)(webpack@5.85.1)
|
||||
umi: 4.0.72(@types/node@17.0.45)(@types/react@18.2.8)(eslint@8.35.0)(prettier@2.8.8)(react-dom@18.2.0)(react@18.2.0)(sockjs-client@1.6.1)(stylelint@14.8.2)(typescript@5.2.2)(webpack@5.85.1)
|
||||
transitivePeerDependencies:
|
||||
- '@babel/core'
|
||||
- '@reduxjs/toolkit'
|
||||
@@ -5794,7 +5794,7 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/@umijs/preset-umi@4.0.72(@types/node@17.0.45)(@types/react@18.2.8)(sockjs-client@1.6.1)(typescript@4.8.4)(webpack@5.85.1):
|
||||
/@umijs/preset-umi@4.0.72(@types/node@17.0.45)(@types/react@18.2.8)(sockjs-client@1.6.1)(typescript@5.2.2)(webpack@5.85.1):
|
||||
resolution: {integrity: sha512-DDRzPCyP2K667YrOHrexAPcEacTdA9/TBn73erwreZpi+c4qhFZ2eYQo27SAGAhfZlYDYthL8JAfbgfhYmLo1A==}
|
||||
dependencies:
|
||||
'@iconify/utils': 2.1.1
|
||||
@@ -5804,7 +5804,7 @@ packages:
|
||||
'@umijs/bundler-esbuild': 4.0.72
|
||||
'@umijs/bundler-utils': 4.0.72
|
||||
'@umijs/bundler-vite': 4.0.72(@types/node@17.0.45)
|
||||
'@umijs/bundler-webpack': 4.0.72(sockjs-client@1.6.1)(typescript@4.8.4)(webpack@5.85.1)
|
||||
'@umijs/bundler-webpack': 4.0.72(sockjs-client@1.6.1)(typescript@5.2.2)(webpack@5.85.1)
|
||||
'@umijs/core': 4.0.72
|
||||
'@umijs/did-you-know': 1.0.3
|
||||
'@umijs/es-module-parser': 0.0.7
|
||||
@@ -8437,7 +8437,7 @@ packages:
|
||||
source-map: 0.6.1
|
||||
dev: true
|
||||
|
||||
/eslint-plugin-jest@27.2.1(@typescript-eslint/eslint-plugin@5.48.1)(eslint@8.35.0)(typescript@4.8.4):
|
||||
/eslint-plugin-jest@27.2.1(@typescript-eslint/eslint-plugin@5.48.1)(eslint@8.35.0)(typescript@5.2.2):
|
||||
resolution: {integrity: sha512-l067Uxx7ZT8cO9NJuf+eJHvt6bqJyz2Z29wykyEdz/OtmcELQl2MQGQLX8J94O1cSJWAwUSEvCjwjA7KEK3Hmg==}
|
||||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
||||
peerDependencies:
|
||||
@@ -8452,8 +8452,8 @@ packages:
|
||||
jest:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@typescript-eslint/eslint-plugin': 5.48.1(@typescript-eslint/parser@5.48.1)(eslint@8.35.0)(typescript@4.8.4)
|
||||
'@typescript-eslint/utils': 5.59.9(eslint@8.35.0)(typescript@4.8.4)
|
||||
'@typescript-eslint/eslint-plugin': 5.48.1(@typescript-eslint/parser@5.48.1)(eslint@8.35.0)(typescript@5.2.2)
|
||||
'@typescript-eslint/utils': 5.59.9(eslint@8.35.0)(typescript@5.2.2)
|
||||
eslint: 8.35.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@@ -8724,9 +8724,9 @@ packages:
|
||||
lodash: 4.17.21
|
||||
dev: false
|
||||
|
||||
/express-rate-limit@6.7.0(express@4.18.2):
|
||||
resolution: {integrity: sha512-vhwIdRoqcYB/72TK3tRZI+0ttS8Ytrk24GfmsxDXK9o9IhHNO5bXRiXQSExPQ4GbaE5tvIS7j1SGrxsuWs+sGA==}
|
||||
engines: {node: '>= 12.9.0'}
|
||||
/express-rate-limit@7.0.0(express@4.18.2):
|
||||
resolution: {integrity: sha512-zKMQ9meikj7j3ILeVvHIaBejAYljgDBtGuCfbzNS2d0VCW4s68ONdtEhBJnOGW/Ty1wGeNXgC4m/C1bBUIX0LA==}
|
||||
engines: {node: '>= 16'}
|
||||
peerDependencies:
|
||||
express: ^4 || ^5
|
||||
dependencies:
|
||||
@@ -8986,7 +8986,7 @@ packages:
|
||||
is-callable: 1.2.7
|
||||
dev: true
|
||||
|
||||
/fork-ts-checker-webpack-plugin@8.0.0(typescript@4.8.4)(webpack@5.85.1):
|
||||
/fork-ts-checker-webpack-plugin@8.0.0(typescript@5.2.2)(webpack@5.85.1):
|
||||
resolution: {integrity: sha512-mX3qW3idpueT2klaQXBzrIM/pHw+T0B/V9KHEvNrqijTq9NFnMZU6oreVxDYcf33P8a5cW+67PjodNHthGnNVg==}
|
||||
engines: {node: '>=12.13.0', yarn: '>=1.0.0'}
|
||||
peerDependencies:
|
||||
@@ -9008,7 +9008,7 @@ packages:
|
||||
schema-utils: 3.1.2
|
||||
semver: 7.5.1
|
||||
tapable: 2.2.1
|
||||
typescript: 4.8.4
|
||||
typescript: 5.2.2
|
||||
webpack: 5.85.1
|
||||
dev: true
|
||||
|
||||
@@ -9468,8 +9468,9 @@ packages:
|
||||
wbuf: 1.7.3
|
||||
dev: true
|
||||
|
||||
/hpagent@0.1.2:
|
||||
resolution: {integrity: sha512-ePqFXHtSQWAFXYmj+JtOTHr84iNrII4/QRlAAPPE+zqnKy4xJo7Ie1Y4kC7AdB+LxLxSTTzBMASsEcy0q8YyvQ==}
|
||||
/hpagent@1.2.0:
|
||||
resolution: {integrity: sha512-A91dYTeIB6NoXG+PxTQpCCDDnfHsW9kc06Lvpu1TEe9gnd6ZFeiBoRO9JvzEv6xK7EX97/dUE8g/vBMTqTS3CA==}
|
||||
engines: {node: '>=14'}
|
||||
dev: false
|
||||
|
||||
/htm@3.1.1:
|
||||
@@ -12412,7 +12413,7 @@ packages:
|
||||
engines: {node: '>= 0.8.0'}
|
||||
dev: true
|
||||
|
||||
/prettier-plugin-organize-imports@3.2.2(prettier@2.8.8)(typescript@4.8.4):
|
||||
/prettier-plugin-organize-imports@3.2.2(prettier@2.8.8)(typescript@5.2.2):
|
||||
resolution: {integrity: sha512-e97lE6odGSiHonHJMTYC0q0iLXQyw0u5z/PJpvP/3vRy6/Zi9kLBwFAbEGjDzIowpjQv8b+J04PDamoUSQbzGA==}
|
||||
peerDependencies:
|
||||
'@volar/vue-language-plugin-pug': ^1.0.4
|
||||
@@ -12426,7 +12427,7 @@ packages:
|
||||
optional: true
|
||||
dependencies:
|
||||
prettier: 2.8.8
|
||||
typescript: 4.8.4
|
||||
typescript: 5.2.2
|
||||
dev: true
|
||||
|
||||
/prettier-plugin-packagejson@2.4.3(prettier@2.8.8):
|
||||
@@ -15338,7 +15339,7 @@ packages:
|
||||
resolution: {integrity: sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==}
|
||||
dev: false
|
||||
|
||||
/ts-node@10.9.1(@types/node@17.0.45)(typescript@4.8.4):
|
||||
/ts-node@10.9.1(@types/node@17.0.45)(typescript@5.2.2):
|
||||
resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
@@ -15364,7 +15365,7 @@ packages:
|
||||
create-require: 1.1.1
|
||||
diff: 4.0.2
|
||||
make-error: 1.3.6
|
||||
typescript: 4.8.4
|
||||
typescript: 5.2.2
|
||||
v8-compile-cache-lib: 3.0.1
|
||||
yn: 3.1.1
|
||||
dev: true
|
||||
@@ -15406,14 +15407,14 @@ packages:
|
||||
resolution: {integrity: sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==}
|
||||
dev: true
|
||||
|
||||
/tsutils@3.21.0(typescript@4.8.4):
|
||||
/tsutils@3.21.0(typescript@5.2.2):
|
||||
resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==}
|
||||
engines: {node: '>= 6'}
|
||||
peerDependencies:
|
||||
typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta'
|
||||
dependencies:
|
||||
tslib: 1.14.1
|
||||
typescript: 4.8.4
|
||||
typescript: 5.2.2
|
||||
dev: true
|
||||
|
||||
/tsx@3.12.7:
|
||||
@@ -15523,28 +15524,28 @@ packages:
|
||||
resolution: {integrity: sha512-v3UJF8xm68BBj6AF4oQML3ikrfK2c9EmZUyLOfShpJuItAqVBHWP/KtpGinkSsIiP6EZyyb6Z3NXyW9dgS9X1w==}
|
||||
dev: false
|
||||
|
||||
/typescript@4.8.4:
|
||||
resolution: {integrity: sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==}
|
||||
engines: {node: '>=4.2.0'}
|
||||
/typescript@5.2.2:
|
||||
resolution: {integrity: sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==}
|
||||
engines: {node: '>=14.17'}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/umi@4.0.72(@types/node@17.0.45)(@types/react@18.2.8)(eslint@8.35.0)(prettier@2.8.8)(react-dom@18.2.0)(react@18.2.0)(sockjs-client@1.6.1)(stylelint@14.8.2)(typescript@4.8.4)(webpack@5.85.1):
|
||||
/umi@4.0.72(@types/node@17.0.45)(@types/react@18.2.8)(eslint@8.35.0)(prettier@2.8.8)(react-dom@18.2.0)(react@18.2.0)(sockjs-client@1.6.1)(stylelint@14.8.2)(typescript@5.2.2)(webpack@5.85.1):
|
||||
resolution: {integrity: sha512-VXXwhHtZAApRR02c2F+uDv84m/Bf5g56pMKrArtIUFsrWM8hqS3f7whzgpdjzh0H8EFjpXwan0kJrkXFr6dAPg==}
|
||||
engines: {node: '>=14'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.21.0
|
||||
'@umijs/bundler-utils': 4.0.72
|
||||
'@umijs/bundler-webpack': 4.0.72(sockjs-client@1.6.1)(typescript@4.8.4)(webpack@5.85.1)
|
||||
'@umijs/bundler-webpack': 4.0.72(sockjs-client@1.6.1)(typescript@5.2.2)(webpack@5.85.1)
|
||||
'@umijs/core': 4.0.72
|
||||
'@umijs/lint': 4.0.72(eslint@8.35.0)(stylelint@14.8.2)(typescript@4.8.4)
|
||||
'@umijs/preset-umi': 4.0.72(@types/node@17.0.45)(@types/react@18.2.8)(sockjs-client@1.6.1)(typescript@4.8.4)(webpack@5.85.1)
|
||||
'@umijs/lint': 4.0.72(eslint@8.35.0)(stylelint@14.8.2)(typescript@5.2.2)
|
||||
'@umijs/preset-umi': 4.0.72(@types/node@17.0.45)(@types/react@18.2.8)(sockjs-client@1.6.1)(typescript@5.2.2)(webpack@5.85.1)
|
||||
'@umijs/renderer-react': 4.0.72(react-dom@18.2.0)(react@18.2.0)
|
||||
'@umijs/server': 4.0.72
|
||||
'@umijs/test': 4.0.72
|
||||
'@umijs/utils': 4.0.72
|
||||
prettier-plugin-organize-imports: 3.2.2(prettier@2.8.8)(typescript@4.8.4)
|
||||
prettier-plugin-organize-imports: 3.2.2(prettier@2.8.8)(typescript@5.2.2)
|
||||
prettier-plugin-packagejson: 2.4.3(prettier@2.8.8)
|
||||
transitivePeerDependencies:
|
||||
- '@babel/core'
|
||||
|
||||
+11
-1
@@ -55,6 +55,10 @@ let BARK_ICON = 'https://qn.whyour.cn/logo.png';
|
||||
let BARK_SOUND = '';
|
||||
//BARK app推送消息的分组, 默认为"QingLong"
|
||||
let BARK_GROUP = 'QingLong';
|
||||
//BARK app推送消息的时效性, 默认为"active"
|
||||
let BARK_LEVEL = 'active';
|
||||
//BARK app推送消息的跳转URL
|
||||
let BARK_URL = '';
|
||||
|
||||
// =======================================telegram机器人通知设置区域===========================================
|
||||
//此处填你telegram bot 的Token,telegram机器人通知推送必填项.例如:1077xxx4424:AAFjv0FcqxxxxxxgEMGfi22B4yh15R5uw
|
||||
@@ -211,6 +215,12 @@ if (process.env.BARK_PUSH) {
|
||||
if (process.env.BARK_GROUP) {
|
||||
BARK_GROUP = process.env.BARK_GROUP;
|
||||
}
|
||||
if (process.env.BARK_LEVEL) {
|
||||
BARK_LEVEL = process.env.BARK_LEVEL;
|
||||
}
|
||||
if (process.env.BARK_URL) {
|
||||
BARK_URL = process.env.BARK_URL;
|
||||
}
|
||||
} else {
|
||||
if (
|
||||
BARK_PUSH &&
|
||||
@@ -552,7 +562,7 @@ function BarkNotify(text, desp, params = {}) {
|
||||
const options = {
|
||||
url: `${BARK_PUSH}/${encodeURIComponent(text)}/${encodeURIComponent(
|
||||
desp,
|
||||
)}?icon=${BARK_ICON}&sound=${BARK_SOUND}&group=${BARK_GROUP}&${querystring.stringify(
|
||||
)}?icon=${BARK_ICON}&sound=${BARK_SOUND}&group=${BARK_GROUP}&level=${BARK_LEVEL}&url=${BARK_URL}&${querystring.stringify(
|
||||
params,
|
||||
)}`,
|
||||
headers: {
|
||||
|
||||
@@ -40,6 +40,8 @@ push_config = {
|
||||
'BARK_GROUP': '', # bark 推送分组
|
||||
'BARK_SOUND': '', # bark 推送声音
|
||||
'BARK_ICON': '', # bark 推送图标
|
||||
'BARK_LEVEL': '', # bark 推送时效性
|
||||
'BARK_URL': '', # bark 推送跳转URL
|
||||
|
||||
'CONSOLE': True, # 控制台输出
|
||||
|
||||
@@ -130,6 +132,8 @@ def bark(title: str, content: str) -> None:
|
||||
"BARK_GROUP": "group",
|
||||
"BARK_SOUND": "sound",
|
||||
"BARK_ICON": "icon",
|
||||
"BARK_LEVEL": "level",
|
||||
"BARK_URL": "url",
|
||||
}
|
||||
params = ""
|
||||
for pair in filter(
|
||||
|
||||
+1
-1
@@ -94,7 +94,7 @@ env_str_to_array() {
|
||||
## 正常运行单个脚本,$1:传入参数
|
||||
run_normal() {
|
||||
local file_param=$1
|
||||
if [[ $# -eq 1 ]] && [[ "$real_time" != "true" ]]; then
|
||||
if [[ $# -eq 1 ]] && [[ "$real_time" != "true" ]] && [[ "$no_delay" != "true" ]]; then
|
||||
random_delay "$file_param"
|
||||
fi
|
||||
|
||||
|
||||
+19
-3
@@ -69,6 +69,7 @@ import_config() {
|
||||
[[ -f $file_env ]] && . $file_env
|
||||
|
||||
ql_base_url=${QlBaseUrl:-"/"}
|
||||
ql_port=${QlPort:-"5700"}
|
||||
command_timeout_time=${CommandTimeoutTime:-""}
|
||||
proxy_url=${ProxyUrl:-""}
|
||||
file_extensions=${RepoFileExtensions:-"js py"}
|
||||
@@ -416,12 +417,15 @@ init_nginx() {
|
||||
sed -i "s,QL_BASE_URL_LOCATION,${location_url},g" /etc/nginx/conf.d/front.conf
|
||||
sed -i "s,QL_BASE_URL,${ql_base_url},g" /etc/nginx/conf.d/front.conf
|
||||
|
||||
ipv6=$(ip a | grep inet6)
|
||||
ipv6Str=""
|
||||
local ipv6=$(ip a | grep inet6)
|
||||
local ipv6Str=""
|
||||
if [[ $ipv6 ]]; then
|
||||
ipv6Str="listen [::]:5700 ipv6only=on;"
|
||||
ipv6Str="listen [::]:${ql_port} ipv6only=on;"
|
||||
fi
|
||||
|
||||
local ipv4Str="listen ${ql_port};"
|
||||
sed -i "s,IPV6_CONFIG,${ipv6Str},g" /etc/nginx/conf.d/front.conf
|
||||
sed -i "s,IPV4_CONFIG,${ipv4Str},g" /etc/nginx/conf.d/front.conf
|
||||
}
|
||||
|
||||
handle_task_before() {
|
||||
@@ -432,11 +436,23 @@ handle_task_before() {
|
||||
[[ $is_macos -eq 0 ]] && check_server
|
||||
|
||||
. $file_task_before "$@"
|
||||
|
||||
if [[ $task_before ]]; then
|
||||
echo -e "执行前置命令\n"
|
||||
eval "$task_before"
|
||||
echo -e "\n执行前置命令结束\n"
|
||||
fi
|
||||
}
|
||||
|
||||
handle_task_after() {
|
||||
. $file_task_after "$@"
|
||||
|
||||
if [[ $task_after ]]; then
|
||||
echo -e "\n执行后置命令\n"
|
||||
eval "$task_after"
|
||||
echo -e "\n执行后置命令结束"
|
||||
fi
|
||||
|
||||
local etime=$(date "+$time_format")
|
||||
local end_time=$(format_time "$time_format" "$etime")
|
||||
local end_timestamp=$(format_timestamp "$time_format" "$etime")
|
||||
|
||||
+7
-6
@@ -273,13 +273,13 @@ update_qinglong() {
|
||||
exit_status=$?
|
||||
|
||||
if [[ $exit_status -eq 0 ]]; then
|
||||
echo -e "\n更新青龙源文件成功...\n"
|
||||
echo -e "更新青龙源文件成功...\n"
|
||||
|
||||
unzip -oq ${dir_tmp}/ql.zip -d ${dir_tmp}
|
||||
|
||||
update_qinglong_static
|
||||
else
|
||||
echo -e "\n更新青龙源文件失败,请检查网络...\n"
|
||||
echo -e "更新青龙源文件失败,请检查网络...\n"
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -288,28 +288,29 @@ update_qinglong_static() {
|
||||
exit_status=$?
|
||||
|
||||
if [[ $exit_status -eq 0 ]]; then
|
||||
echo -e "\n更新青龙静态资源成功...\n"
|
||||
echo -e "更新青龙静态资源成功...\n"
|
||||
unzip -oq ${dir_tmp}/static.zip -d ${dir_tmp}
|
||||
|
||||
check_update_dep
|
||||
else
|
||||
echo -e "\n更新青龙静态资源失败,请检查网络...\n"
|
||||
echo -e "更新青龙静态资源失败,请检查网络...\n"
|
||||
fi
|
||||
}
|
||||
|
||||
check_update_dep() {
|
||||
echo -e "\n开始检测依赖...\n"
|
||||
if [[ $(diff $dir_sample/package.json $dir_scripts/package.json) ]]; then
|
||||
if [[ ! -s $dir_scripts/package.json ]] || [[ $(diff $dir_sample/package.json $dir_scripts/package.json) ]]; then
|
||||
cp -f $dir_sample/package.json $dir_scripts/package.json
|
||||
npm_install_2 $dir_scripts
|
||||
fi
|
||||
|
||||
if [[ $(diff $dir_root/package.json ${dir_tmp}/qinglong-${primary_branch}/package.json) ]]; then
|
||||
npm_install_2 "${dir_tmp}/qinglong-${primary_branch}"
|
||||
fi
|
||||
|
||||
if [[ $exit_status -eq 0 ]]; then
|
||||
echo -e "\n依赖检测安装成功...\n"
|
||||
echo -e "\n更新包下载成功...\n"
|
||||
echo -e "更新包下载成功..."
|
||||
|
||||
if [[ "$needRestart" == 'true' ]]; then
|
||||
cp -rf ${dir_tmp}/qinglong-${primary_branch}/* ${dir_root}/
|
||||
|
||||
@@ -451,3 +451,9 @@ body[data-mode='phone'] header {
|
||||
.ant-table.ant-table-middle tfoot > tr > td {
|
||||
padding: 12px 16px;
|
||||
}
|
||||
|
||||
body[data-dark='true'] {
|
||||
.ant-popover-arrow-content {
|
||||
--antd-arrow-background-color: rgb(24, 26, 27);
|
||||
}
|
||||
}
|
||||
|
||||
+4
-27
@@ -1,5 +1,5 @@
|
||||
import intl from 'react-intl-universal';
|
||||
import React, { useEffect, useState, useRef } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import ProLayout, { PageLoading } from '@ant-design/pro-layout';
|
||||
import * as DarkReader from '@umijs/ssr-darkreader';
|
||||
import defaultProps from './defaultProps';
|
||||
@@ -29,9 +29,9 @@ import {
|
||||
MenuProps,
|
||||
} from 'antd';
|
||||
// @ts-ignore
|
||||
import SockJS from 'sockjs-client';
|
||||
import * as Sentry from '@sentry/react';
|
||||
import { init } from '../utils/init';
|
||||
import WebSocketManager from '../utils/websocket';
|
||||
|
||||
export interface SharedContext {
|
||||
headerStyle: React.CSSProperties;
|
||||
@@ -40,7 +40,6 @@ export interface SharedContext {
|
||||
user: any;
|
||||
reloadUser: (needLoading?: boolean) => void;
|
||||
reloadTheme: () => void;
|
||||
socketMessage: any;
|
||||
systemInfo: TSystemInfo;
|
||||
}
|
||||
|
||||
@@ -60,8 +59,6 @@ export default function () {
|
||||
const [user, setUser] = useState<any>({});
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
const [systemInfo, setSystemInfo] = useState<TSystemInfo>();
|
||||
const ws = useRef<any>(null);
|
||||
const [socketMessage, setSocketMessage] = useState<any>();
|
||||
const [collapsed, setCollapsed] = useState(false);
|
||||
const [initLoading, setInitLoading] = useState<boolean>(true);
|
||||
const {
|
||||
@@ -180,32 +177,14 @@ export default function () {
|
||||
|
||||
useEffect(() => {
|
||||
if (!user || !user.username) return;
|
||||
ws.current = new SockJS(
|
||||
const ws = WebSocketManager.getInstance(
|
||||
`${window.location.origin}/api/ws?token=${localStorage.getItem(
|
||||
config.authKey,
|
||||
)}`,
|
||||
);
|
||||
|
||||
ws.current.onmessage = (e: any) => {
|
||||
try {
|
||||
const data = JSON.parse(e.data);
|
||||
if (data.type === 'ping') {
|
||||
if (data && data.message === 'hanhh') {
|
||||
console.log('WS connection succeeded !!!');
|
||||
} else {
|
||||
console.log('WS connection Failed !!!', e);
|
||||
}
|
||||
}
|
||||
setSocketMessage(data);
|
||||
} catch (error) {
|
||||
console.log('websocket连接失败', e);
|
||||
}
|
||||
};
|
||||
|
||||
const wsCurrent = ws.current;
|
||||
|
||||
return () => {
|
||||
wsCurrent.close();
|
||||
ws.close();
|
||||
};
|
||||
}, [user]);
|
||||
|
||||
@@ -246,7 +225,6 @@ export default function () {
|
||||
user,
|
||||
reloadUser,
|
||||
reloadTheme,
|
||||
ws: ws.current,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
@@ -387,7 +365,6 @@ export default function () {
|
||||
user,
|
||||
reloadUser,
|
||||
reloadTheme,
|
||||
socketMessage,
|
||||
systemInfo,
|
||||
}}
|
||||
/>
|
||||
|
||||
+10
-1
@@ -352,6 +352,8 @@
|
||||
"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 redirecting URL",
|
||||
"BARK推送消息的跳转URL": "BARK push message grouping, default is qinglong",
|
||||
"telegram机器人的token,例如:1077xxx4424:AAFjv0FcqxxxxxxgEMGfi22B4yh15R5uw": "Telegram Bot token, e.g., 1077xxx4424:AAFjv0FcqxxxxxxgEMGfi22B4yh15R5uw",
|
||||
"telegram用户的id,例如:129xxx206": "Telegram user ID, e.g., 129xxx206",
|
||||
"代理IP": "Proxy IP",
|
||||
@@ -451,5 +453,12 @@
|
||||
"登录已过期,请重新登录": "Login session has expired, please log in again",
|
||||
"系统日志": "System Logs",
|
||||
"主题": "Theme",
|
||||
"语言": "Language"
|
||||
"语言": "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",
|
||||
"请输入运行任务前要执行的命令": "Please enter the command to run before executing the task",
|
||||
"请输入运行任务后要执行的命令": "Please enter the command to run after executing the task"
|
||||
}
|
||||
|
||||
+10
-1
@@ -352,6 +352,8 @@
|
||||
"BARK推送图标,自定义推送图标 (需iOS15或以上才能显示)": "BARK推送图标,自定义推送图标 (需iOS15或以上才能显示)",
|
||||
"BARK推送铃声,铃声列表去APP查看复制填写": "BARK推送铃声,铃声列表去APP查看复制填写",
|
||||
"BARK推送消息的分组,默认为qinglong": "BARK推送消息的分组,默认为qinglong",
|
||||
"BARK推送消息的时效性,默认为active": "BARK推送消息的时效性,默认为active",
|
||||
"BARK推送消息的跳转URL": "BARK推送消息的跳转URL",
|
||||
"telegram机器人的token,例如:1077xxx4424:AAFjv0FcqxxxxxxgEMGfi22B4yh15R5uw": "telegram机器人的token,例如:1077xxx4424:AAFjv0FcqxxxxxxgEMGfi22B4yh15R5uw",
|
||||
"telegram用户的id,例如:129xxx206": "telegram用户的id,例如:129xxx206",
|
||||
"代理IP": "代理IP",
|
||||
@@ -451,5 +453,12 @@
|
||||
"登录已过期,请重新登录": "登录已过期,请重新登录",
|
||||
"系统日志": "系统日志",
|
||||
"主题": "主题",
|
||||
"语言": "语言"
|
||||
"语言": "语言",
|
||||
"中...": "中...",
|
||||
"请选择操作符": "请选择操作符",
|
||||
"新增定时规则": "新增定时规则",
|
||||
"运行任务前执行的命令,比如 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",
|
||||
"请输入运行任务前要执行的命令": "请输入运行任务前要执行的命令",
|
||||
"请输入运行任务后要执行的命令": "请输入运行任务后要执行的命令"
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
.log-item {
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background: #fafafa;
|
||||
background: #f2f2f2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,5 +195,5 @@ body[data-mode='desktop'] {
|
||||
}
|
||||
|
||||
.cron.pinned-cron > td {
|
||||
background: #fafafa;
|
||||
background: #f2f2f2;
|
||||
}
|
||||
@@ -43,7 +43,6 @@ import { request } from '@/utils/http';
|
||||
import CronModal, { CronLabelModal } from './modal';
|
||||
import CronLogModal from './logModal';
|
||||
import CronDetailModal from './detail';
|
||||
import cron_parser from 'cron-parser';
|
||||
import { diffTime } from '@/utils/date';
|
||||
import { history, useOutletContext } from '@umijs/max';
|
||||
import './index.less';
|
||||
@@ -183,6 +182,20 @@ const Crontab = () => {
|
||||
sorter: {
|
||||
compare: (a, b) => a.schedule.localeCompare(b.schedule),
|
||||
},
|
||||
render: (text, record) => {
|
||||
return record.extra_schedules?.length ? (
|
||||
<Popover
|
||||
placement="right"
|
||||
content={record.extra_schedules?.map((x) => (
|
||||
<div>{x.schedule}</div>
|
||||
))}
|
||||
>
|
||||
{text}
|
||||
</Popover>
|
||||
) : (
|
||||
text
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: intl.get('最后运行时长'),
|
||||
|
||||
@@ -82,12 +82,12 @@ const CronLogModal = ({
|
||||
handleCancel();
|
||||
};
|
||||
|
||||
const handleScroll = (e) => {
|
||||
const sTop = e.target.scrollTop;
|
||||
const handleScroll: React.UIEventHandler<HTMLDivElement> = (e) => {
|
||||
const sTop = (e.target as HTMLDivElement).scrollTop;
|
||||
if (scrollInfoRef.current.down) {
|
||||
scrollInfoRef.current = {
|
||||
value: sTop,
|
||||
down: sTop > scrollInfoRef.current.value,
|
||||
down: sTop > scrollInfoRef.current.value || !sTop,
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -105,6 +105,7 @@ const CronLogModal = ({
|
||||
useEffect(() => {
|
||||
if (cron && cron.id && visible) {
|
||||
getCronLog(true);
|
||||
scrollInfoRef.current.down = true;
|
||||
}
|
||||
}, [cron, visible]);
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import intl from 'react-intl-universal';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Modal, message, Input, Form, Button } from 'antd';
|
||||
import { Modal, message, Input, Form, Button, Space } from 'antd';
|
||||
import { request } from '@/utils/http';
|
||||
import config from '@/utils/config';
|
||||
import cronParse from 'cron-parser';
|
||||
import EditableTagGroup from '@/components/tag';
|
||||
import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons';
|
||||
|
||||
const CronModal = ({
|
||||
cron,
|
||||
@@ -107,9 +108,67 @@ const CronModal = ({
|
||||
>
|
||||
<Input placeholder={intl.get('秒(可选) 分 时 天 月 周')} />
|
||||
</Form.Item>
|
||||
<Form.List name="extra_schedules">
|
||||
{(fields, { add, remove }, { errors }) => (
|
||||
<>
|
||||
{fields.map(({ key, name, ...restField }) => (
|
||||
<Form.Item key={key} noStyle>
|
||||
<Space className="view-create-modal-sorts" align="baseline">
|
||||
<Form.Item
|
||||
{...restField}
|
||||
name={[name, 'schedule']}
|
||||
rules={[{ required: true }]}
|
||||
>
|
||||
<Input
|
||||
placeholder={intl.get('秒(可选) 分 时 天 月 周')}
|
||||
/>
|
||||
</Form.Item>
|
||||
<MinusCircleOutlined
|
||||
className="dynamic-delete-button"
|
||||
onClick={() => remove(name)}
|
||||
/>
|
||||
</Space>
|
||||
</Form.Item>
|
||||
))}
|
||||
<Form.Item>
|
||||
<a onClick={() => add({ schedule: '' })}>
|
||||
<PlusOutlined />
|
||||
{intl.get('新增定时规则')}
|
||||
</a>
|
||||
</Form.Item>
|
||||
<Form.ErrorList errors={errors} />
|
||||
</>
|
||||
)}
|
||||
</Form.List>
|
||||
<Form.Item name="labels" label={intl.get('标签')}>
|
||||
<EditableTagGroup />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="task_before"
|
||||
label={intl.get('执行前')}
|
||||
tooltip={intl.get(
|
||||
'运行任务前执行的命令,比如 cp/mv/python3 xxx.py/node xxx.js',
|
||||
)}
|
||||
>
|
||||
<Input.TextArea
|
||||
rows={4}
|
||||
autoSize={{ minRows: 1, maxRows: 5 }}
|
||||
placeholder={intl.get('请输入运行任务前要执行的命令')}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="task_after"
|
||||
label={intl.get('执行后')}
|
||||
tooltip={intl.get(
|
||||
'运行任务后执行的命令,比如 cp/mv/python3 xxx.py/node xxx.js',
|
||||
)}
|
||||
>
|
||||
<Input.TextArea
|
||||
rows={4}
|
||||
autoSize={{ minRows: 1, maxRows: 5 }}
|
||||
placeholder={intl.get('请输入运行任务后要执行的命令')}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
);
|
||||
|
||||
@@ -35,4 +35,6 @@ export interface ICrontab {
|
||||
last_running_time?: number;
|
||||
last_execution_time?: number;
|
||||
nextRunTime: Date;
|
||||
sub_id: number;
|
||||
extra_schedules?: Array<{ schedule: string; }>;
|
||||
}
|
||||
|
||||
@@ -107,20 +107,29 @@ const ViewCreateModal = ({
|
||||
}
|
||||
form.setFieldsValue(
|
||||
view || {
|
||||
filters: [{ property: 'command', operation: 'Reg' }],
|
||||
filters: [{ property: 'command' }],
|
||||
},
|
||||
);
|
||||
}, [view, visible]);
|
||||
|
||||
const operationElement = (
|
||||
<Select style={{ width: 120 }}>
|
||||
{OPERATIONS.map((x) => (
|
||||
<Select.Option key={x.name} value={x.value}>
|
||||
{x.name}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
);
|
||||
const OperationElement = ({ name, ...others }: { name: number }) => {
|
||||
const property = form.getFieldValue(['filters', name, 'property']);
|
||||
return (
|
||||
<Select
|
||||
style={{ width: 120 }}
|
||||
placeholder={intl.get('请选择操作符')}
|
||||
{...others}
|
||||
>
|
||||
{OPERATIONS.filter((x) =>
|
||||
STATUS_MAP[property as 'status' | 'sub_id'] ? x.type === 'select' : x,
|
||||
).map((x) => (
|
||||
<Select.Option key={x.name} value={x.value}>
|
||||
{x.name}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
);
|
||||
};
|
||||
|
||||
const propertyElement = (props: any, style: React.CSSProperties = {}) => {
|
||||
return (
|
||||
@@ -190,7 +199,7 @@ const ViewCreateModal = ({
|
||||
<Input placeholder={intl.get('请输入视图名称')} />
|
||||
</Form.Item>
|
||||
<Form.List name="filters">
|
||||
{(fields, { add, remove }) => (
|
||||
{(fields, { add, remove }, { errors }) => (
|
||||
<div
|
||||
style={{ position: 'relative' }}
|
||||
className={`view-filters-container ${
|
||||
@@ -256,9 +265,11 @@ const ViewCreateModal = ({
|
||||
<Form.Item
|
||||
{...restField}
|
||||
name={[name, 'operation']}
|
||||
rules={[{ required: true }]}
|
||||
rules={[
|
||||
{ required: true, message: intl.get('请选择操作符') },
|
||||
]}
|
||||
>
|
||||
{operationElement}
|
||||
<OperationElement name={name} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
{...restField}
|
||||
@@ -290,12 +301,13 @@ const ViewCreateModal = ({
|
||||
{intl.get('新增筛选条件')}
|
||||
</a>
|
||||
</Form.Item>
|
||||
<Form.ErrorList errors={errors} />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</Form.List>
|
||||
<Form.List name="sorts">
|
||||
{(fields, { add, remove }) => (
|
||||
{(fields, { add, remove }, { errors }) => (
|
||||
<div
|
||||
style={{ position: 'relative' }}
|
||||
className={`view-filters-container ${
|
||||
@@ -365,6 +377,7 @@ const ViewCreateModal = ({
|
||||
{intl.get('新增排序方式')}
|
||||
</a>
|
||||
</Form.Item>
|
||||
<Form.ErrorList errors={errors} />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -35,6 +35,7 @@ import { useOutletContext } from '@umijs/max';
|
||||
import { SharedContext } from '@/layouts';
|
||||
import useTableScrollHeight from '@/hooks/useTableScrollHeight';
|
||||
import dayjs from 'dayjs';
|
||||
import WebSocketManager from '@/utils/websocket';
|
||||
|
||||
const { Text } = Typography;
|
||||
const { Search } = Input;
|
||||
@@ -87,8 +88,7 @@ const StatusMap: Record<number, { icon: React.ReactNode; color: string }> = {
|
||||
};
|
||||
|
||||
const Dependence = () => {
|
||||
const { headerStyle, isPhone, socketMessage } =
|
||||
useOutletContext<SharedContext>();
|
||||
const { headerStyle, isPhone } = useOutletContext<SharedContext>();
|
||||
const columns: any = [
|
||||
{
|
||||
title: intl.get('序号'),
|
||||
@@ -100,7 +100,7 @@ const Dependence = () => {
|
||||
{
|
||||
title: intl.get('名称'),
|
||||
dataIndex: 'name',
|
||||
width: 120,
|
||||
width: 180,
|
||||
key: 'name',
|
||||
},
|
||||
{
|
||||
@@ -109,11 +109,12 @@ const Dependence = () => {
|
||||
width: 120,
|
||||
dataIndex: 'status',
|
||||
render: (text: string, record: any, index: number) => {
|
||||
console.log(record.status);
|
||||
return (
|
||||
<Space size="middle" style={{ cursor: 'text' }}>
|
||||
<Tag
|
||||
color={StatusMap[record.status].color}
|
||||
icon={StatusMap[record.status].icon}
|
||||
color={StatusMap[record.status]?.color}
|
||||
icon={StatusMap[record.status]?.icon}
|
||||
style={{ marginRight: 0 }}
|
||||
>
|
||||
{intl.get(Status[record.status])}
|
||||
@@ -125,7 +126,7 @@ const Dependence = () => {
|
||||
{
|
||||
title: intl.get('备注'),
|
||||
dataIndex: 'remark',
|
||||
width: 120,
|
||||
width: 100,
|
||||
key: 'remark',
|
||||
},
|
||||
{
|
||||
@@ -149,7 +150,7 @@ const Dependence = () => {
|
||||
{
|
||||
title: intl.get('操作'),
|
||||
key: 'action',
|
||||
width: 150,
|
||||
width: 140,
|
||||
render: (text: string, record: any, index: number) => {
|
||||
const isPc = !isPhone;
|
||||
return (
|
||||
@@ -395,63 +396,62 @@ const Dependence = () => {
|
||||
}
|
||||
}, [logDependence]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!socketMessage) return;
|
||||
const { type, message, references } = socketMessage;
|
||||
if (
|
||||
type === 'installDependence' &&
|
||||
message.includes('开始时间') &&
|
||||
references.length > 0
|
||||
) {
|
||||
const result = [...value];
|
||||
for (let i = 0; i < references.length; i++) {
|
||||
const index = value.findIndex((x) => x.id === references[i]);
|
||||
if (index !== -1) {
|
||||
result.splice(index, 1, {
|
||||
...value[index],
|
||||
status: message.includes('安装') ? Status.安装中 : Status.删除中,
|
||||
});
|
||||
}
|
||||
}
|
||||
setValue(result);
|
||||
const handleMessage = useCallback((payload: any) => {
|
||||
const { message, references } = payload;
|
||||
let status: number | undefined = undefined;
|
||||
if (message.includes('开始时间') && references.length > 0) {
|
||||
status = message.includes('安装') ? Status.安装中 : Status.删除中;
|
||||
}
|
||||
if (
|
||||
type === 'installDependence' &&
|
||||
message.includes('结束时间') &&
|
||||
references.length > 0
|
||||
) {
|
||||
let status;
|
||||
if (message.includes('结束时间') && references.length > 0) {
|
||||
if (message.includes('安装')) {
|
||||
status = message.includes('成功') ? Status.已安装 : Status.安装失败;
|
||||
} else {
|
||||
status = message.includes('成功') ? Status.已删除 : Status.删除失败;
|
||||
}
|
||||
const result = [...value];
|
||||
for (let i = 0; i < references.length; i++) {
|
||||
const index = value.findIndex((x) => x.id === references[i]);
|
||||
if (index !== -1) {
|
||||
result.splice(index, 1, {
|
||||
...value[index],
|
||||
status,
|
||||
});
|
||||
}
|
||||
}
|
||||
setValue(result);
|
||||
|
||||
if (status === Status.已删除) {
|
||||
setTimeout(() => {
|
||||
const _result = [...value];
|
||||
for (let i = 0; i < references.length; i++) {
|
||||
const index = value.findIndex((x) => x.id === references[i]);
|
||||
if (index !== -1) {
|
||||
_result.splice(index, 1);
|
||||
setValue((p) => {
|
||||
const _result = [...p];
|
||||
for (let i = 0; i < references.length; i++) {
|
||||
const index = p.findIndex((x) => x.id === references[i]);
|
||||
if (index !== -1) {
|
||||
_result.splice(index, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
setValue(_result);
|
||||
return _result;
|
||||
});
|
||||
}, 5000);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}, [socketMessage]);
|
||||
if (typeof status === 'number') {
|
||||
setValue((p) => {
|
||||
const result = [...p];
|
||||
for (let i = 0; i < references.length; i++) {
|
||||
const index = p.findIndex((x) => x.id === references[i]);
|
||||
if (index !== -1) {
|
||||
result.splice(index, 1, {
|
||||
...p[index],
|
||||
status,
|
||||
});
|
||||
}
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const ws = WebSocketManager.getInstance();
|
||||
ws.subscribe('installDependence', handleMessage);
|
||||
ws.subscribe('uninstallDependence', handleMessage);
|
||||
|
||||
return () => {
|
||||
ws.unsubscribe('installDependence', handleMessage);
|
||||
ws.unsubscribe('uninstallDependence', handleMessage);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const onTabChange = (activeKey: string) => {
|
||||
setSelectedRowIds([]);
|
||||
@@ -548,24 +548,25 @@ const Dependence = () => {
|
||||
dependence={editedDependence}
|
||||
defaultType={type}
|
||||
/>
|
||||
<DependenceLogModal
|
||||
visible={isLogModalVisible}
|
||||
handleCancel={(needRemove?: boolean) => {
|
||||
setIsLogModalVisible(false);
|
||||
if (needRemove) {
|
||||
const index = value.findIndex((x) => x.id === logDependence.id);
|
||||
const result = [...value];
|
||||
if (index !== -1) {
|
||||
result.splice(index, 1);
|
||||
setValue(result);
|
||||
{logDependence && (
|
||||
<DependenceLogModal
|
||||
visible={isLogModalVisible}
|
||||
handleCancel={(needRemove?: boolean) => {
|
||||
setIsLogModalVisible(false);
|
||||
if (needRemove) {
|
||||
const index = value.findIndex((x) => x.id === logDependence.id);
|
||||
const result = [...value];
|
||||
if (index !== -1) {
|
||||
result.splice(index, 1);
|
||||
setValue(result);
|
||||
}
|
||||
} else if ([...value].map((x) => x.id).includes(logDependence.id)) {
|
||||
getDependenceDetail(logDependence);
|
||||
}
|
||||
} else if ([...value].map((x) => x.id).includes(logDependence.id)) {
|
||||
getDependenceDetail(logDependence);
|
||||
}
|
||||
}}
|
||||
socketMessage={socketMessage}
|
||||
dependence={logDependence}
|
||||
/>
|
||||
}}
|
||||
dependence={logDependence}
|
||||
/>
|
||||
)}
|
||||
</PageContainer>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -9,17 +9,16 @@ import {
|
||||
} from '@ant-design/icons';
|
||||
import { PageLoading } from '@ant-design/pro-layout';
|
||||
import Ansi from 'ansi-to-react';
|
||||
import WebSocketManager from '@/utils/websocket';
|
||||
|
||||
const DependenceLogModal = ({
|
||||
dependence,
|
||||
handleCancel,
|
||||
visible,
|
||||
socketMessage,
|
||||
}: {
|
||||
dependence?: any;
|
||||
visible: boolean;
|
||||
handleCancel: (needRemove?: boolean) => void;
|
||||
socketMessage: any;
|
||||
}) => {
|
||||
const [value, setValue] = useState<string>('');
|
||||
const [executing, setExecuting] = useState<any>(true);
|
||||
@@ -54,7 +53,7 @@ const DependenceLogModal = ({
|
||||
code === 200 &&
|
||||
localStorage.getItem('logDependence') === String(dependence.id)
|
||||
) {
|
||||
const log = (data.log || []).join('') as string;
|
||||
const log = (data?.log || []).join('') as string;
|
||||
setValue(log);
|
||||
setExecuting(!log.includes('结束时间'));
|
||||
setIsRemoveFailed(log.includes('删除失败'));
|
||||
@@ -95,21 +94,25 @@ const DependenceLogModal = ({
|
||||
}
|
||||
}, [dependence]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!socketMessage || !dependence) return;
|
||||
const { type, message, references } = socketMessage;
|
||||
if (
|
||||
type === 'installDependence' &&
|
||||
references.length > 0 &&
|
||||
references.includes(dependence.id)
|
||||
) {
|
||||
const handleMessage = (payload: any) => {
|
||||
const { message, references } = payload;
|
||||
if (references.length > 0 && references.includes(dependence.id)) {
|
||||
if (message.includes('结束时间')) {
|
||||
setExecuting(false);
|
||||
setIsRemoveFailed(message.includes('删除失败'));
|
||||
}
|
||||
setValue(`${value}${message}`);
|
||||
setValue((p) => `${p}${message}`);
|
||||
}
|
||||
}, [socketMessage]);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const ws = WebSocketManager.getInstance();
|
||||
ws.subscribe('installDependence', handleMessage);
|
||||
|
||||
return () => {
|
||||
ws.unsubscribe('installDependence', handleMessage);
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setIsPhone(document.body.clientWidth < 768);
|
||||
|
||||
Vendored
+10
@@ -82,6 +82,16 @@ const Env = () => {
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
sorter: (a: any, b: any) => a.name.localeCompare(b.name),
|
||||
render: (text: string, record: any) => {
|
||||
return (
|
||||
<div style={{ display: 'flex', alignItems: 'center' }}>
|
||||
<Tooltip title={text} placement="topLeft">
|
||||
<div className="text-ellipsis">{text}</div>
|
||||
</Tooltip>
|
||||
<Copy text={text} />
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: intl.get('值'),
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
import intl from 'react-intl-universal';
|
||||
import React, { useEffect, useState, useRef } from 'react';
|
||||
import React, {
|
||||
useEffect,
|
||||
useState,
|
||||
useRef,
|
||||
useCallback,
|
||||
useReducer,
|
||||
} from 'react';
|
||||
import { Drawer, Button, Tabs, Badge, Select, TreeSelect } from 'antd';
|
||||
import { request } from '@/utils/http';
|
||||
import config from '@/utils/config';
|
||||
@@ -9,6 +15,7 @@ import SaveModal from './saveModal';
|
||||
import SettingModal from './setting';
|
||||
import { useTheme } from '@/utils/hooks';
|
||||
import { getEditorMode, logEnded } from '@/utils';
|
||||
import WebSocketManager from '@/utils/websocket';
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
@@ -18,12 +25,10 @@ const EditModal = ({
|
||||
content,
|
||||
handleCancel,
|
||||
visible,
|
||||
socketMessage,
|
||||
}: {
|
||||
treeData?: any;
|
||||
content?: string;
|
||||
visible: boolean;
|
||||
socketMessage: any;
|
||||
currentNode: any;
|
||||
handleCancel: () => void;
|
||||
}) => {
|
||||
@@ -34,12 +39,11 @@ const EditModal = ({
|
||||
const [saveModalVisible, setSaveModalVisible] = useState<boolean>(false);
|
||||
const [settingModalVisible, setSettingModalVisible] =
|
||||
useState<boolean>(false);
|
||||
const [log, setLog] = useState<string>('');
|
||||
const [log, setLog] = useState('');
|
||||
const { theme } = useTheme();
|
||||
const editorRef = useRef<any>(null);
|
||||
const [isRunning, setIsRunning] = useState(false);
|
||||
const [currentPid, setCurrentPid] = useState(null);
|
||||
|
||||
const cancel = () => {
|
||||
handleCancel();
|
||||
};
|
||||
@@ -104,28 +108,25 @@ const EditModal = ({
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!socketMessage) {
|
||||
return;
|
||||
}
|
||||
|
||||
let { type, message: _message, references } = socketMessage;
|
||||
|
||||
if (type !== 'manuallyRunScript') {
|
||||
return;
|
||||
}
|
||||
|
||||
const handleMessage = useCallback((payload: any) => {
|
||||
let { message: _message } = payload;
|
||||
if (logEnded(_message)) {
|
||||
setTimeout(() => {
|
||||
setIsRunning(false);
|
||||
}, 300);
|
||||
}
|
||||
|
||||
if (log) {
|
||||
_message = `\n${_message}`;
|
||||
}
|
||||
setLog(`${log}${_message}`);
|
||||
}, [socketMessage]);
|
||||
setLog(p=>`${p}${_message}`);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const ws = WebSocketManager.getInstance();
|
||||
ws.subscribe('manuallyRunScript', handleMessage);
|
||||
|
||||
return () => {
|
||||
ws.unsubscribe('manuallyRunScript', handleMessage);
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setLog('');
|
||||
|
||||
@@ -48,7 +48,7 @@ import { langs } from '@uiw/codemirror-extensions-langs';
|
||||
const { Text } = Typography;
|
||||
|
||||
const Script = () => {
|
||||
const { headerStyle, isPhone, theme, socketMessage } =
|
||||
const { headerStyle, isPhone, theme } =
|
||||
useOutletContext<SharedContext>();
|
||||
const [value, setValue] = useState(intl.get('请选择脚本文件'));
|
||||
const [select, setSelect] = useState<string>('');
|
||||
@@ -591,16 +591,15 @@ const Script = () => {
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<EditModal
|
||||
{isLogModalVisible && <EditModal
|
||||
visible={isLogModalVisible}
|
||||
treeData={data}
|
||||
currentNode={currentNode}
|
||||
content={value}
|
||||
socketMessage={socketMessage}
|
||||
handleCancel={() => {
|
||||
setIsLogModalVisible(false);
|
||||
}}
|
||||
/>
|
||||
/>}
|
||||
<EditScriptNameModal
|
||||
visible={isAddFileModalVisible}
|
||||
treeData={data}
|
||||
|
||||
@@ -7,12 +7,6 @@ import dayjs from 'dayjs';
|
||||
|
||||
const { Link } = Typography;
|
||||
|
||||
enum TVersion {
|
||||
'develop' = '开发版',
|
||||
'master' = '正式版',
|
||||
'debian' = '正式版'
|
||||
}
|
||||
|
||||
const About = ({ systemInfo }: { systemInfo: SharedContext['systemInfo'] }) => {
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
@@ -30,7 +24,10 @@ const About = ({ systemInfo }: { systemInfo: SharedContext['systemInfo'] }) => {
|
||||
</span>
|
||||
<Descriptions>
|
||||
<Descriptions.Item label={intl.get('版本')} span={3}>
|
||||
{intl.get(TVersion[systemInfo.branch])} v{systemInfo.version}
|
||||
{systemInfo?.branch === 'develop'
|
||||
? intl.get('开发版')
|
||||
: intl.get('正式版')}{' '}
|
||||
v{systemInfo.version}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label={intl.get('更新时间')} span={3}>
|
||||
{dayjs(systemInfo.publishTime * 1000).format('YYYY-MM-DD HH:mm')}
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
import intl from 'react-intl-universal';
|
||||
import React, { useEffect, useState, useRef } from 'react';
|
||||
import React, { useEffect, useState, useRef, useCallback } from 'react';
|
||||
import { Statistic, Modal, Tag, Button, Spin, message } from 'antd';
|
||||
import { request } from '@/utils/http';
|
||||
import config from '@/utils/config';
|
||||
import WebSocketManager from '@/utils/websocket';
|
||||
import Ansi from 'ansi-to-react';
|
||||
|
||||
const { Countdown } = Statistic;
|
||||
|
||||
const CheckUpdate = ({ socketMessage, systemInfo }: any) => {
|
||||
const CheckUpdate = ({ systemInfo }: any) => {
|
||||
const [updateLoading, setUpdateLoading] = useState(false);
|
||||
const [value, setValue] = useState('');
|
||||
const modalRef = useRef<any>();
|
||||
@@ -149,17 +151,8 @@ const CheckUpdate = ({ socketMessage, systemInfo }: any) => {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!modalRef.current || !socketMessage) {
|
||||
return;
|
||||
}
|
||||
const { type, message: _message, references } = socketMessage;
|
||||
|
||||
if (type !== 'updateSystemVersion') {
|
||||
return;
|
||||
}
|
||||
|
||||
const newMessage = `${value}${_message}`;
|
||||
const updateFailed = newMessage.includes('失败');
|
||||
if (!value) return;
|
||||
const updateFailed = value.includes('失败,请检查');
|
||||
|
||||
modalRef.current.update({
|
||||
maskClosable: updateFailed,
|
||||
@@ -167,29 +160,46 @@ const CheckUpdate = ({ socketMessage, systemInfo }: any) => {
|
||||
okButtonProps: { disabled: !updateFailed },
|
||||
content: (
|
||||
<>
|
||||
<pre>{newMessage}</pre>
|
||||
<pre>
|
||||
<Ansi>{value}</Ansi>
|
||||
</pre>
|
||||
<div id="log-identifier" style={{ paddingBottom: 5 }}></div>
|
||||
</>
|
||||
),
|
||||
});
|
||||
}, [value]);
|
||||
|
||||
if (updateFailed && !value.includes('失败,请检查')) {
|
||||
const handleMessage = useCallback((payload: any) => {
|
||||
let { message: _message } = payload;
|
||||
const updateFailed = _message.includes('失败,请检查');
|
||||
|
||||
if (updateFailed) {
|
||||
message.error(intl.get('更新失败,请检查网络及日志或稍后再试'));
|
||||
}
|
||||
|
||||
setValue(newMessage);
|
||||
|
||||
document.getElementById('log-identifier') &&
|
||||
setTimeout(() => {
|
||||
document
|
||||
.getElementById('log-identifier')!
|
||||
.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
||||
.querySelector('#log-identifier')!
|
||||
.scrollIntoView({ behavior: 'smooth' });
|
||||
}, 600);
|
||||
|
||||
if (_message.includes('更新包下载成功')) {
|
||||
setTimeout(() => {
|
||||
showReloadModal();
|
||||
}, 1000);
|
||||
}
|
||||
}, [socketMessage]);
|
||||
|
||||
setValue((p) => `${p}${_message}`);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const ws = WebSocketManager.getInstance();
|
||||
ws.subscribe('updateSystemVersion', handleMessage);
|
||||
|
||||
return () => {
|
||||
ws.unsubscribe('updateSystemVersion', handleMessage);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -46,7 +46,6 @@ const Setting = () => {
|
||||
theme,
|
||||
reloadUser,
|
||||
reloadTheme,
|
||||
socketMessage,
|
||||
systemInfo,
|
||||
} = useOutletContext<SharedContext>();
|
||||
const columns = [
|
||||
@@ -376,7 +375,6 @@ const Setting = () => {
|
||||
children: (
|
||||
<Other
|
||||
reloadTheme={reloadTheme}
|
||||
socketMessage={socketMessage}
|
||||
systemInfo={systemInfo}
|
||||
/>
|
||||
),
|
||||
|
||||
@@ -24,9 +24,8 @@ import useProgress from './progress';
|
||||
|
||||
const Other = ({
|
||||
systemInfo,
|
||||
socketMessage,
|
||||
reloadTheme,
|
||||
}: Pick<SharedContext, 'socketMessage' | 'reloadTheme' | 'systemInfo'>) => {
|
||||
}: Pick<SharedContext, 'reloadTheme' | 'systemInfo'>) => {
|
||||
const defaultTheme = localStorage.getItem('qinglong_dark_theme') || 'auto';
|
||||
const [systemConfig, setSystemConfig] = useState<{
|
||||
logRemoveFrequency?: number | null;
|
||||
@@ -274,7 +273,7 @@ const Other = ({
|
||||
</Upload>
|
||||
</Form.Item>
|
||||
<Form.Item label={intl.get('检查更新')} name="update">
|
||||
<CheckUpdate systemInfo={systemInfo} socketMessage={socketMessage} />
|
||||
<CheckUpdate systemInfo={systemInfo} />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import intl from 'react-intl-universal';
|
||||
import { Modal, Progress } from 'antd';
|
||||
import { useRef } from 'react';
|
||||
|
||||
@@ -15,14 +16,14 @@ export default function useProgress(title: string) {
|
||||
const showProgress = (percent: number) => {
|
||||
if (modalRef.current) {
|
||||
modalRef.current.update({
|
||||
title: `${title}${percent >= 100 ? '成功' : '中...'}`,
|
||||
title: `${title}${percent >= 100 ? intl.get('成功') : intl.get('中...')}`,
|
||||
content: <ProgressElement percent={percent} />,
|
||||
});
|
||||
} else {
|
||||
modalRef.current = Modal.info({
|
||||
width: 600,
|
||||
maskClosable: false,
|
||||
title: `${title}${percent >= 100 ? '成功' : '中...'}`,
|
||||
title: `${title}${percent >= 100 ? intl.get('成功') : intl.get('中...')}`,
|
||||
centered: true,
|
||||
content: <ProgressElement percent={percent} />,
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import intl from 'react-intl-universal';
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import React, { useState, useEffect, useRef, useCallback } from 'react';
|
||||
import {
|
||||
Button,
|
||||
message,
|
||||
@@ -36,6 +36,7 @@ import './index.less';
|
||||
import SubscriptionLogModal from './logModal';
|
||||
import { SharedContext } from '@/layouts';
|
||||
import useTableScrollHeight from '@/hooks/useTableScrollHeight';
|
||||
import WebSocketManager from '@/utils/websocket';
|
||||
|
||||
const { Text, Paragraph } = Typography;
|
||||
const { Search } = Input;
|
||||
@@ -61,8 +62,7 @@ export enum SubscriptionType {
|
||||
}
|
||||
|
||||
const Subscription = () => {
|
||||
const { headerStyle, isPhone, socketMessage } =
|
||||
useOutletContext<SharedContext>();
|
||||
const { headerStyle, isPhone } = useOutletContext<SharedContext>();
|
||||
|
||||
const columns: any = [
|
||||
{
|
||||
@@ -508,23 +508,31 @@ const Subscription = () => {
|
||||
: 'subscription';
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!socketMessage) return;
|
||||
const { type, message, references } = socketMessage;
|
||||
if (type === 'runSubscriptionEnd' && references.length > 0) {
|
||||
const result = [...value];
|
||||
const handleMessage = useCallback((payload: any) => {
|
||||
const { message, references } = payload;
|
||||
setValue((p) => {
|
||||
const result = [...p];
|
||||
for (let i = 0; i < references.length; i++) {
|
||||
const index = value.findIndex((x) => x.id === references[i]);
|
||||
const index = p.findIndex((x) => x.id === references[i]);
|
||||
if (index !== -1) {
|
||||
result.splice(index, 1, {
|
||||
...value[index],
|
||||
...p[index],
|
||||
status: SubscriptionStatus.idle,
|
||||
});
|
||||
}
|
||||
}
|
||||
setValue(result);
|
||||
}
|
||||
}, [socketMessage]);
|
||||
return result;
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const ws = WebSocketManager.getInstance();
|
||||
ws.subscribe('runSubscriptionEnd', handleMessage);
|
||||
|
||||
return () => {
|
||||
ws.unsubscribe('runSubscriptionEnd', handleMessage);
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (logSubscription) {
|
||||
|
||||
@@ -176,6 +176,14 @@ export default {
|
||||
label: 'barkGroup',
|
||||
tip: intl.get('BARK推送消息的分组,默认为qinglong'),
|
||||
},
|
||||
{
|
||||
label: 'barkLevel',
|
||||
tip: intl.get('BARK推送消息的时效性,默认为active'),
|
||||
},
|
||||
{
|
||||
label: 'barkUrl',
|
||||
tip: intl.get('BARK推送消息的跳转URL'),
|
||||
},
|
||||
],
|
||||
telegramBot: [
|
||||
{
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
export type SockMessageType =
|
||||
| 'ping'
|
||||
| 'installDependence'
|
||||
| 'uninstallDependence'
|
||||
| 'updateSystemVersion'
|
||||
| 'manuallyRunScript'
|
||||
| 'runSubscriptionEnd'
|
||||
| 'reloadSystem';
|
||||
@@ -0,0 +1,154 @@
|
||||
import SockJS from 'sockjs-client';
|
||||
import { SockMessageType } from './type';
|
||||
|
||||
class WebSocketManager {
|
||||
private static instance: WebSocketManager | null = null;
|
||||
private url: string;
|
||||
private socket: WebSocket | null = null;
|
||||
private subscriptions: Map<SockMessageType, Set<(p: any) => void>> = new Map();
|
||||
private options: {
|
||||
maxReconnectAttempts: number;
|
||||
reconnectInterval: number;
|
||||
heartbeatInterval: number;
|
||||
};
|
||||
private reconnectAttempts: number = 0;
|
||||
private heartbeatTimeout: NodeJS.Timeout | null = null;
|
||||
private state: 'closed' | 'connecting' | 'open' = 'closed';
|
||||
|
||||
constructor(url: string, options: Partial<typeof WebSocketManager.prototype.options> = {}) {
|
||||
this.url = url;
|
||||
this.options = {
|
||||
maxReconnectAttempts: options.maxReconnectAttempts || 5,
|
||||
reconnectInterval: options.reconnectInterval || 3000,
|
||||
heartbeatInterval: options.heartbeatInterval || 30000,
|
||||
};
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
public static getInstance(url: string = '', options?: Partial<typeof WebSocketManager.prototype.options>): WebSocketManager {
|
||||
if (!WebSocketManager.instance) {
|
||||
WebSocketManager.instance = new WebSocketManager(url, options);
|
||||
}
|
||||
return WebSocketManager.instance;
|
||||
}
|
||||
|
||||
private async init() {
|
||||
try {
|
||||
this.state = 'connecting';
|
||||
this.emit('connecting');
|
||||
|
||||
while (this.reconnectAttempts < this.options.maxReconnectAttempts) {
|
||||
this.socket = new SockJS(this.url);
|
||||
this.setupEventListeners();
|
||||
this.startHeartbeat();
|
||||
await this.waitForClose();
|
||||
this.stopHeartbeat();
|
||||
this.socket = null;
|
||||
this.reconnectAttempts++;
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, this.options.reconnectInterval));
|
||||
}
|
||||
} catch (error) {
|
||||
this.handleError(error);
|
||||
}
|
||||
}
|
||||
|
||||
private setupEventListeners() {
|
||||
if (!this.socket) return;
|
||||
|
||||
this.socket.onopen = () => {
|
||||
this.state = 'open';
|
||||
this.emit('open');
|
||||
};
|
||||
|
||||
this.socket.onmessage = (event) => {
|
||||
const message = JSON.parse(event.data);
|
||||
this.dispatchMessage(message);
|
||||
};
|
||||
|
||||
this.socket.onclose = () => {
|
||||
this.state = 'closed';
|
||||
this.emit('close');
|
||||
};
|
||||
}
|
||||
|
||||
private async waitForClose() {
|
||||
while (this.socket?.readyState !== SockJS.CLOSED) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
}
|
||||
}
|
||||
|
||||
public subscribe(topic: SockMessageType, callback: (v: any) => void) {
|
||||
const topicSubscriptions = this.subscriptions.get(topic) || new Set();
|
||||
|
||||
if (!topicSubscriptions.has(callback)) {
|
||||
topicSubscriptions.add(callback);
|
||||
this.subscriptions.set(topic, topicSubscriptions);
|
||||
|
||||
const subscriptionMessage = { action: 'subscribe', topic };
|
||||
this.send(subscriptionMessage);
|
||||
}
|
||||
}
|
||||
|
||||
public unsubscribe(topic: SockMessageType, callback: (v: any) => void) {
|
||||
const topicSubscriptions = this.subscriptions.get(topic) || new Set();
|
||||
if (topicSubscriptions.has(callback)) {
|
||||
topicSubscriptions.delete(callback);
|
||||
|
||||
const unsubscribeMessage = { action: 'unsubscribe', topic };
|
||||
this.send(unsubscribeMessage);
|
||||
}
|
||||
}
|
||||
|
||||
public send(message: any) {
|
||||
if (this.socket?.readyState === SockJS.OPEN) {
|
||||
this.socket.send(JSON.stringify(message));
|
||||
}
|
||||
}
|
||||
|
||||
private dispatchMessage(message: any) {
|
||||
const { type, ...others } = message;
|
||||
const topicSubscriptions = this.subscriptions.get(type) || new Set();
|
||||
|
||||
[...topicSubscriptions].forEach((callback) => callback(others));
|
||||
}
|
||||
|
||||
private startHeartbeat() {
|
||||
this.heartbeatTimeout = setInterval(() => {
|
||||
if (this.socket?.readyState === SockJS.OPEN) {
|
||||
this.socket.send(JSON.stringify({ type: 'heartbeat' }));
|
||||
}
|
||||
}, this.options.heartbeatInterval);
|
||||
}
|
||||
|
||||
private stopHeartbeat() {
|
||||
if (this.heartbeatTimeout) {
|
||||
clearInterval(this.heartbeatTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
public close() {
|
||||
if (this.socket) {
|
||||
this.state = 'closed';
|
||||
this.stopHeartbeat();
|
||||
this.socket.close();
|
||||
this.emit('close');
|
||||
}
|
||||
}
|
||||
|
||||
private handleError(error: any) {
|
||||
console.error('WebSocket错误:', error);
|
||||
this.emit('error', error);
|
||||
}
|
||||
|
||||
public on(event: string, listener: Function) {
|
||||
// this.addListener(event, listener);
|
||||
}
|
||||
|
||||
public emit(event: string, data?: any) {
|
||||
// this.listeners(event).forEach((listener) => listener(data));
|
||||
}
|
||||
}
|
||||
|
||||
export default WebSocketManager;
|
||||
+7
-8
@@ -1,19 +1,17 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2017",
|
||||
"lib": ["es2021", "esnext.asynciterable", "DOM"],
|
||||
"typeRoots": [
|
||||
"./node_modules/@types",
|
||||
"./src/types",
|
||||
"./node_modules/celebrate/lib/index.d.ts"
|
||||
],
|
||||
"lib": ["ESNext"],
|
||||
"typeRoots": ["./node_modules/celebrate/lib", "./node_modules/@types"],
|
||||
"paths": {
|
||||
"@/*": ["./back/*"],
|
||||
"@/*": ["./back/*"]
|
||||
},
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"moduleResolution": "node",
|
||||
"module": "commonjs",
|
||||
"pretty": true,
|
||||
@@ -24,5 +22,6 @@
|
||||
"esModuleInterop": true
|
||||
},
|
||||
"include": ["./back/**/*"],
|
||||
"exclude": ["node_modules", "tests"]
|
||||
"exclude": ["node_modules"],
|
||||
"files": ["./back/index.d.ts"]
|
||||
}
|
||||
|
||||
+3
-8
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2017",
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"target": "ESNext",
|
||||
"module": "ES2015",
|
||||
"moduleResolution": "Bundler",
|
||||
"importHelpers": true,
|
||||
"jsx": "react-jsx",
|
||||
"esModuleInterop": true,
|
||||
@@ -14,11 +14,6 @@
|
||||
"@@/*": ["src/.umi/*"]
|
||||
},
|
||||
"lib": ["dom", "es2021", "esnext.asynciterable"],
|
||||
"typeRoots": [
|
||||
"./node_modules/@types",
|
||||
"./back/types",
|
||||
"./node_modules/celebrate/lib/index.d.ts"
|
||||
],
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
|
||||
Vendored
-2
@@ -9,8 +9,6 @@ declare module '*.svg' {
|
||||
export default url;
|
||||
}
|
||||
|
||||
declare module 'pstree.remy';
|
||||
|
||||
interface Window {
|
||||
__ENV__QlBaseUrl: string;
|
||||
__ENV__DeployEnv: string;
|
||||
|
||||
+10
-9
@@ -1,10 +1,11 @@
|
||||
version: 2.16.1
|
||||
changeLogLink: https://t.me/jiao_long/392
|
||||
publishTime: 2023-08-21 23:00
|
||||
version: 2.16.3
|
||||
changeLogLink: https://t.me/jiao_long/394
|
||||
publishTime: 2023-09-23 12:00
|
||||
changeLog: |
|
||||
1. 系统设置增加系统日志,展示系统和任务运行日志
|
||||
2. 修复 python 企业微信推送
|
||||
3. 修复 debian 版本关于页面报错
|
||||
4. 修复添加订阅粘贴 ql 命令链接参数可能错误
|
||||
5. 修改日志弹框样式
|
||||
6. 其他 bug 修复
|
||||
1. 定时任务支持设置多定时规则、任务执行前和执行后命令
|
||||
2. 增加启动环境变量 QlPort, 支持修改 hosts 模式青龙启动端口
|
||||
3. 消息通知 Bark 增加额外参数: 时效性通知、跳转Url
|
||||
4. 修复调试脚本日志丢失
|
||||
5. 环境变量名称增加复制功能
|
||||
6. 修复系统设置展示版本失败
|
||||
7. 其他 bug 修复
|
||||
|
||||
Reference in New Issue
Block a user