Revert unnecessary file changes - keep only multi-device login feature files

Co-authored-by: whyour <22700758+whyour@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2025-11-18 16:13:53 +00:00
parent 5e7e39753c
commit 9d0e64262a
34 changed files with 687 additions and 1425 deletions

View File

@ -11,11 +11,12 @@ export default (app: Router) => {
route.get(
'/',
celebrate({
query: Joi.object({
searchValue: Joi.string().optional().allow(''),
type: Joi.string().optional().allow(''),
status: Joi.string().optional().allow(''),
}),
query:
Joi.object({
searchValue: Joi.string().optional().allow(''),
type: Joi.string().optional().allow(''),
status: Joi.string().optional().allow(''),
}),
}),
async (req: Request, res: Response, next: NextFunction) => {
const logger: Logger = Container.get('logger');

View File

@ -71,8 +71,7 @@ export default (app: Router) => {
logger.error('🔥 error: %o', e);
return next(e);
}
},
);
});
route.get(
'/detail',
@ -86,7 +85,7 @@ export default (app: Router) => {
try {
const scriptService = Container.get(ScriptService);
const content = await scriptService.getFile(
(req.query?.path as string) || '',
req.query?.path as string || '',
req.query.file as string,
);
res.send({ code: 200, data: content });
@ -110,7 +109,7 @@ export default (app: Router) => {
try {
const scriptService = Container.get(ScriptService);
const content = await scriptService.getFile(
(req.query?.path as string) || '',
req.query?.path as string || '',
req.params.file,
);
res.send({ code: 200, data: content });

View File

@ -28,18 +28,12 @@ class Application {
constructor() {
this.app = express();
// 创建一个全局中间件删除查询参数中的t
this.app.use(
(
req: express.Request,
res: express.Response,
next: express.NextFunction,
) => {
if (req.query.t) {
delete req.query.t;
}
next();
},
);
this.app.use((req: express.Request, res: express.Response, next: express.NextFunction) => {
if (req.query.t) {
delete req.query.t;
}
next();
});
}
async start() {
@ -67,8 +61,7 @@ class Application {
if (metadata) {
if (!this.isShuttingDown) {
Logger.error(
`${metadata.serviceType} worker ${worker.process.pid} died (${
signal || code
`${metadata.serviceType} worker ${worker.process.pid} died (${signal || code
}). Restarting...`,
);
const newWorker = this.forkWorker(metadata.serviceType);
@ -103,11 +96,9 @@ class Application {
}
private setupMiddlewares() {
this.app.use(
helmet({
contentSecurityPolicy: false,
}),
);
this.app.use(helmet({
contentSecurityPolicy: false,
}));
this.app.use(cors(config.cors));
this.app.use(compression());
this.app.use(monitoringMiddleware);

View File

@ -81,4 +81,4 @@ export function createRandomString(min: number, max: number): string {
}
return newArr.join('');
}
}

View File

@ -55,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',

View File

@ -24,13 +24,7 @@ export interface AppToken {
expiration: number;
}
export type AppScope =
| 'envs'
| 'crons'
| 'configs'
| 'scripts'
| 'logs'
| 'system';
export type AppScope = 'envs' | 'crons' | 'configs' | 'scripts' | 'logs' | 'system';
export interface AppInstance extends Model<App, App>, App {}
export const AppModel = sequelize.define<AppInstance>('App', {

View File

@ -13,7 +13,7 @@ async function linkToNodeModule(src: string, dst?: string) {
if (!stats) {
await fs.symlink(source, target, 'dir');
}
} catch (error) {}
} catch (error) { }
}
async function linkCommand() {
@ -41,7 +41,7 @@ async function linkCommand() {
if (stats) {
await fs.unlink(tmpTarget);
}
} catch (error) {}
} catch (error) { }
await fs.symlink(source, tmpTarget);
await fs.rename(tmpTarget, target);
}

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,7 @@
// source: back/protos/cron.proto
/* eslint-disable */
import { BinaryReader, BinaryWriter } from '@bufbuild/protobuf/wire';
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
import {
type CallOptions,
ChannelCredentials,
@ -17,9 +17,9 @@ import {
Metadata,
type ServiceError,
type UntypedServiceImplementation,
} from '@grpc/grpc-js';
} from "@grpc/grpc-js";
export const protobufPackage = 'com.ql.cron';
export const protobufPackage = "com.ql.cron";
export interface ISchedule {
schedule: string;
@ -37,32 +37,30 @@ 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: '' };
return { schedule: "" };
}
export const ISchedule: MessageFns<ISchedule> = {
encode(
message: ISchedule,
writer: BinaryWriter = new BinaryWriter(),
): BinaryWriter {
if (message.schedule !== '') {
encode(message: ISchedule, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.schedule !== "") {
writer.uint32(10).string(message.schedule);
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): ISchedule {
const reader =
input instanceof BinaryReader ? input : new BinaryReader(input);
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
let end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseISchedule();
while (reader.pos < end) {
@ -86,16 +84,12 @@ export const ISchedule: MessageFns<ISchedule> = {
},
fromJSON(object: any): ISchedule {
return {
schedule: isSet(object.schedule)
? globalThis.String(object.schedule)
: '',
};
return { schedule: isSet(object.schedule) ? globalThis.String(object.schedule) : "" };
},
toJSON(message: ISchedule): unknown {
const obj: any = {};
if (message.schedule !== '') {
if (message.schedule !== "") {
obj.schedule = message.schedule;
}
return obj;
@ -104,45 +98,39 @@ export const ISchedule: MessageFns<ISchedule> = {
create<I extends Exact<DeepPartial<ISchedule>, I>>(base?: I): ISchedule {
return ISchedule.fromPartial(base ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<ISchedule>, I>>(
object: I,
): ISchedule {
fromPartial<I extends Exact<DeepPartial<ISchedule>, I>>(object: I): ISchedule {
const message = createBaseISchedule();
message.schedule = object.schedule ?? '';
message.schedule = object.schedule ?? "";
return message;
},
};
function createBaseICron(): ICron {
return { id: '', schedule: '', command: '', extra_schedules: [], name: '' };
return { id: "", schedule: "", command: "", extra_schedules: [], name: "" };
}
export const ICron: MessageFns<ICron> = {
encode(
message: ICron,
writer: BinaryWriter = new BinaryWriter(),
): BinaryWriter {
if (message.id !== '') {
encode(message: ICron, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
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.extra_schedules) {
ISchedule.encode(v!, writer.uint32(34).fork()).join();
}
if (message.name !== '') {
if (message.name !== "") {
writer.uint32(42).string(message.name);
}
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): ICron {
const reader =
input instanceof BinaryReader ? input : new BinaryReader(input);
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
let end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseICron();
while (reader.pos < end) {
@ -177,9 +165,7 @@ export const ICron: MessageFns<ICron> = {
break;
}
message.extra_schedules.push(
ISchedule.decode(reader, reader.uint32()),
);
message.extra_schedules.push(ISchedule.decode(reader, reader.uint32()));
continue;
}
case 5: {
@ -201,35 +187,31 @@ export const ICron: MessageFns<ICron> = {
fromJSON(object: any): ICron {
return {
id: isSet(object.id) ? globalThis.String(object.id) : '',
schedule: isSet(object.schedule)
? globalThis.String(object.schedule)
: '',
command: isSet(object.command) ? globalThis.String(object.command) : '',
id: isSet(object.id) ? globalThis.String(object.id) : "",
schedule: isSet(object.schedule) ? globalThis.String(object.schedule) : "",
command: isSet(object.command) ? globalThis.String(object.command) : "",
extra_schedules: globalThis.Array.isArray(object?.extra_schedules)
? object.extra_schedules.map((e: any) => ISchedule.fromJSON(e))
: [],
name: isSet(object.name) ? globalThis.String(object.name) : '',
name: isSet(object.name) ? globalThis.String(object.name) : "",
};
},
toJSON(message: ICron): unknown {
const obj: any = {};
if (message.id !== '') {
if (message.id !== "") {
obj.id = message.id;
}
if (message.schedule !== '') {
if (message.schedule !== "") {
obj.schedule = message.schedule;
}
if (message.command !== '') {
if (message.command !== "") {
obj.command = message.command;
}
if (message.extra_schedules?.length) {
obj.extra_schedules = message.extra_schedules.map((e) =>
ISchedule.toJSON(e),
);
obj.extra_schedules = message.extra_schedules.map((e) => ISchedule.toJSON(e));
}
if (message.name !== '') {
if (message.name !== "") {
obj.name = message.name;
}
return obj;
@ -240,12 +222,11 @@ export const ICron: MessageFns<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.extra_schedules =
object.extra_schedules?.map((e) => ISchedule.fromPartial(e)) || [];
message.name = object.name ?? '';
message.id = object.id ?? "";
message.schedule = object.schedule ?? "";
message.command = object.command ?? "";
message.extra_schedules = object.extra_schedules?.map((e) => ISchedule.fromPartial(e)) || [];
message.name = object.name ?? "";
return message;
},
};
@ -255,10 +236,7 @@ function createBaseAddCronRequest(): AddCronRequest {
}
export const AddCronRequest: MessageFns<AddCronRequest> = {
encode(
message: AddCronRequest,
writer: BinaryWriter = new BinaryWriter(),
): BinaryWriter {
encode(message: AddCronRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
for (const v of message.crons) {
ICron.encode(v!, writer.uint32(10).fork()).join();
}
@ -266,8 +244,7 @@ export const AddCronRequest: MessageFns<AddCronRequest> = {
},
decode(input: BinaryReader | Uint8Array, length?: number): AddCronRequest {
const reader =
input instanceof BinaryReader ? input : new BinaryReader(input);
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
let end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseAddCronRequest();
while (reader.pos < end) {
@ -291,11 +268,7 @@ export const AddCronRequest: MessageFns<AddCronRequest> = {
},
fromJSON(object: any): AddCronRequest {
return {
crons: globalThis.Array.isArray(object?.crons)
? object.crons.map((e: any) => ICron.fromJSON(e))
: [],
};
return { crons: globalThis.Array.isArray(object?.crons) ? object.crons.map((e: any) => ICron.fromJSON(e)) : [] };
},
toJSON(message: AddCronRequest): unknown {
@ -306,14 +279,10 @@ export const AddCronRequest: MessageFns<AddCronRequest> = {
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 ?? ({} as any));
},
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;
@ -325,16 +294,12 @@ function createBaseAddCronResponse(): AddCronResponse {
}
export const AddCronResponse: MessageFns<AddCronResponse> = {
encode(
_: AddCronResponse,
writer: BinaryWriter = new BinaryWriter(),
): BinaryWriter {
encode(_: AddCronResponse, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
return writer;
},
decode(input: BinaryReader | Uint8Array, length?: number): AddCronResponse {
const reader =
input instanceof BinaryReader ? input : new BinaryReader(input);
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
let end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseAddCronResponse();
while (reader.pos < end) {
@ -358,14 +323,10 @@ export const AddCronResponse: MessageFns<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 ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<AddCronResponse>, I>>(
_: I,
): AddCronResponse {
fromPartial<I extends Exact<DeepPartial<AddCronResponse>, I>>(_: I): AddCronResponse {
const message = createBaseAddCronResponse();
return message;
},
@ -376,10 +337,7 @@ function createBaseDeleteCronRequest(): DeleteCronRequest {
}
export const DeleteCronRequest: MessageFns<DeleteCronRequest> = {
encode(
message: DeleteCronRequest,
writer: BinaryWriter = new BinaryWriter(),
): BinaryWriter {
encode(message: DeleteCronRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
for (const v of message.ids) {
writer.uint32(10).string(v!);
}
@ -387,8 +345,7 @@ export const DeleteCronRequest: MessageFns<DeleteCronRequest> = {
},
decode(input: BinaryReader | Uint8Array, length?: number): DeleteCronRequest {
const reader =
input instanceof BinaryReader ? input : new BinaryReader(input);
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
let end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseDeleteCronRequest();
while (reader.pos < end) {
@ -412,11 +369,7 @@ export const DeleteCronRequest: MessageFns<DeleteCronRequest> = {
},
fromJSON(object: any): DeleteCronRequest {
return {
ids: globalThis.Array.isArray(object?.ids)
? object.ids.map((e: any) => globalThis.String(e))
: [],
};
return { ids: globalThis.Array.isArray(object?.ids) ? object.ids.map((e: any) => globalThis.String(e)) : [] };
},
toJSON(message: DeleteCronRequest): unknown {
@ -427,14 +380,10 @@ export const DeleteCronRequest: MessageFns<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 ?? ({} as any));
},
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;
@ -446,19 +395,12 @@ function createBaseDeleteCronResponse(): DeleteCronResponse {
}
export const DeleteCronResponse: MessageFns<DeleteCronResponse> = {
encode(
_: DeleteCronResponse,
writer: BinaryWriter = new BinaryWriter(),
): BinaryWriter {
encode(_: DeleteCronResponse, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
return writer;
},
decode(
input: BinaryReader | Uint8Array,
length?: number,
): DeleteCronResponse {
const reader =
input instanceof BinaryReader ? input : new BinaryReader(input);
decode(input: BinaryReader | Uint8Array, length?: number): DeleteCronResponse {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
let end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseDeleteCronResponse();
while (reader.pos < end) {
@ -482,14 +424,10 @@ export const DeleteCronResponse: MessageFns<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 ?? ({} as any));
},
fromPartial<I extends Exact<DeepPartial<DeleteCronResponse>, I>>(
_: I,
): DeleteCronResponse {
fromPartial<I extends Exact<DeepPartial<DeleteCronResponse>, I>>(_: I): DeleteCronResponse {
const message = createBaseDeleteCronResponse();
return message;
},
@ -498,25 +436,21 @@ export const DeleteCronResponse: MessageFns<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;
@ -544,68 +478,38 @@ 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;
serviceName: string;
};
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 globalThis.Array<infer U>
? globalThis.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 globalThis.Array<infer U> ? globalThis.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;

View File

@ -5,7 +5,7 @@
// source: back/protos/health.proto
/* eslint-disable */
import { BinaryReader, BinaryWriter } from '@bufbuild/protobuf/wire';
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
import {
type CallOptions,
ChannelCredentials,
@ -19,9 +19,9 @@ import {
Metadata,
type ServiceError,
type UntypedServiceImplementation,
} from '@grpc/grpc-js';
} from "@grpc/grpc-js";
export const protobufPackage = 'com.ql.health';
export const protobufPackage = "com.ql.health";
export interface HealthCheckRequest {
service: string;
@ -39,68 +39,57 @@ 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: MessageFns<HealthCheckRequest> = {
encode(
message: HealthCheckRequest,
writer: BinaryWriter = new BinaryWriter(),
): BinaryWriter {
if (message.service !== '') {
encode(message: HealthCheckRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.service !== "") {
writer.uint32(10).string(message.service);
}
return writer;
},
decode(
input: BinaryReader | Uint8Array,
length?: number,
): HealthCheckRequest {
const reader =
input instanceof BinaryReader ? input : new BinaryReader(input);
decode(input: BinaryReader | Uint8Array, length?: number): HealthCheckRequest {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
let end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseHealthCheckRequest();
while (reader.pos < end) {
@ -124,29 +113,23 @@ export const HealthCheckRequest: MessageFns<HealthCheckRequest> = {
},
fromJSON(object: any): HealthCheckRequest {
return {
service: isSet(object.service) ? globalThis.String(object.service) : '',
};
return { service: isSet(object.service) ? globalThis.String(object.service) : "" };
},
toJSON(message: HealthCheckRequest): unknown {
const obj: any = {};
if (message.service !== '') {
if (message.service !== "") {
obj.service = message.service;
}
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 ?? ({} as any));
},
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;
},
};
@ -156,22 +139,15 @@ function createBaseHealthCheckResponse(): HealthCheckResponse {
}
export const HealthCheckResponse: MessageFns<HealthCheckResponse> = {
encode(
message: HealthCheckResponse,
writer: BinaryWriter = new BinaryWriter(),
): BinaryWriter {
encode(message: HealthCheckResponse, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
if (message.status !== 0) {
writer.uint32(8).int32(message.status);
}
return writer;
},
decode(
input: BinaryReader | Uint8Array,
length?: number,
): HealthCheckResponse {
const reader =
input instanceof BinaryReader ? input : new BinaryReader(input);
decode(input: BinaryReader | Uint8Array, length?: number): HealthCheckResponse {
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
let end = length === undefined ? reader.len : reader.pos + length;
const message = createBaseHealthCheckResponse();
while (reader.pos < end) {
@ -195,11 +171,7 @@ export const HealthCheckResponse: MessageFns<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 {
@ -210,14 +182,10 @@ export const HealthCheckResponse: MessageFns<HealthCheckResponse> = {
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 ?? ({} as any));
},
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;
@ -227,25 +195,21 @@ export const HealthCheckResponse: MessageFns<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;
@ -258,32 +222,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,
@ -291,44 +243,23 @@ 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;
serviceName: string;
};
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 globalThis.Array<infer U>
? globalThis.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 globalThis.Array<infer U> ? globalThis.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;

View File

@ -231,8 +231,7 @@ export const systemNotify = async (
const data = await systemService.notify({
title: call.request.title,
content: call.request.content,
notificationInfo: call.request
.notificationInfo as unknown as NotificationInfo,
notificationInfo: call.request.notificationInfo as unknown as NotificationInfo,
});
callback(null, data);
} catch (e: any) {

View File

@ -9,8 +9,11 @@ const delCron = (
) => {
for (const id of call.request.ids) {
if (scheduleStacks.has(id)) {
Logger.info('[schedule][取消定时任务] 任务ID: %s', id);
scheduleStacks.get(id)?.forEach((x) => x.cancel());
Logger.info(
'[schedule][取消定时任务] 任务ID: %s',
id,
);
scheduleStacks.get(id)?.forEach(x => x.cancel());
scheduleStacks.delete(id);
}
}

View File

@ -24,9 +24,7 @@ const check = async (
`tail -n 300 ~/.pm2/logs/schedule-error.log`,
);
return callback(
new Error(
`${scheduleErrLog || ''}\n${panelErrLog || ''}\n${res}`.trim(),
),
new Error(`${scheduleErrLog || ''}\n${panelErrLog || ''}\n${res}`.trim()),
);
default:

View File

@ -28,7 +28,7 @@ export default class DependenceService {
constructor(
@Inject('logger') private logger: winston.Logger,
private sockService: SockService,
) {}
) { }
public async create(payloads: Dependence[]): Promise<Dependence[]> {
const tabs = payloads.map((x) => {

View File

@ -16,7 +16,7 @@ class MetricsService {
// 定期清理旧数据
setInterval(() => {
const oneHourAgo = Date.now() - 3600000;
this.metrics = this.metrics.filter((m) => m.timestamp > oneHourAgo);
this.metrics = this.metrics.filter(m => m.timestamp > oneHourAgo);
}, 60000);
}
@ -46,11 +46,7 @@ class MetricsService {
}
}
async measureAsync(
name: string,
fn: () => Promise<void>,
tags?: Record<string, string>,
) {
async measureAsync(name: string, fn: () => Promise<void>, tags?: Record<string, string>) {
const start = performance.now();
try {
await fn();
@ -62,26 +58,23 @@ class MetricsService {
getMetrics(name?: string, tags?: Record<string, string>) {
let filtered = this.metrics;
if (name) {
filtered = filtered.filter((m) => m.name === name);
filtered = filtered.filter(m => m.name === name);
}
if (tags) {
filtered = filtered.filter((m) => {
filtered = filtered.filter(m => {
if (!m.tags) return false;
return Object.entries(tags).every(
([key, value]) => m.tags![key] === value,
);
return Object.entries(tags).every(([key, value]) => m.tags![key] === value);
});
}
return {
count: filtered.length,
average:
filtered.reduce((acc, curr) => acc + curr.value, 0) / filtered.length,
min: Math.min(...filtered.map((m) => m.value)),
max: Math.max(...filtered.map((m) => m.value)),
average: filtered.reduce((acc, curr) => acc + curr.value, 0) / filtered.length,
min: Math.min(...filtered.map(m => m.value)),
max: Math.max(...filtered.map(m => m.value)),
metrics: filtered,
};
}
@ -96,4 +89,4 @@ class MetricsService {
}
}
export const metricsService = MetricsService.getInstance();
export const metricsService = MetricsService.getInstance();

View File

@ -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;

View File

@ -47,7 +47,7 @@ export default class SystemService {
@Inject('logger') private logger: winston.Logger,
private scheduleService: ScheduleService,
private sockService: SockService,
) {}
) { }
public async getSystemConfig() {
const doc = await this.getDb({ type: AuthDataType.systemConfig });
@ -287,7 +287,7 @@ export default class SystemService {
);
const text = await body.text();
lastVersionContent = parseContentVersion(text);
} catch (error) {}
} catch (error) { }
if (!lastVersionContent) {
lastVersionContent = currentVersionContent;
@ -401,23 +401,16 @@ export default class SystemService {
}
}
public async run(
{ command, logPath }: { command: string; logPath?: string },
callback: TaskCallbacks,
) {
public async run({ command, logPath }: { command: string; logPath?: string }, callback: TaskCallbacks) {
if (!command.startsWith(TASK_COMMAND)) {
command = `${TASK_COMMAND} ${command}`;
}
const logPathPrefix = logPath ? `real_log_path=${logPath}` : '';
this.scheduleService.runTask(
`${logPathPrefix} real_time=true ${command}`,
callback,
{
command,
id: command.replace(/ /g, '-'),
runOrigin: 'system',
},
);
const logPathPrefix = logPath ? `real_log_path=${logPath}` : ''
this.scheduleService.runTask(`${logPathPrefix} real_time=true ${command}`, callback, {
command,
id: command.replace(/ /g, '-'),
runOrigin: 'system',
});
}
public async stop({ command, pid }: { command: string; pid: number }) {
@ -450,8 +443,7 @@ export default class SystemService {
}
const dataPaths = dataDirs.map((dir) => `data/${dir}`);
await promiseExec(
`cd ${config.dataPath} && cd ../ && tar -zcvf ${
config.dataTgzFile
`cd ${config.dataPath} && cd ../ && tar -zcvf ${config.dataTgzFile
} ${dataPaths.join(' ')}`,
);
res.download(config.dataTgzFile);
@ -545,7 +537,7 @@ export default class SystemService {
try {
const finalPath = path.join(config.dependenceCachePath, type);
await fs.promises.rm(finalPath, { recursive: true });
} catch (error) {}
} catch (error) { }
return { code: 200 };
}
}

View File

@ -8,4 +8,4 @@ declare global {
platform: 'desktop' | 'mobile';
}
}
}
}

View File

@ -1,5 +1,8 @@
{
"watch": ["back", ".env"],
"watch": [
"back",
".env"
],
"ext": "js,ts,json",
"env": {
"NODE_ENV": "development",
@ -9,4 +12,4 @@
"execMap": {
"ts": "node --require ts-node/register"
}
}
}

View File

@ -1262,15 +1262,7 @@ function ntfyNotify(text, desp) {
}
return new Promise((resolve) => {
const {
NTFY_URL,
NTFY_TOPIC,
NTFY_PRIORITY,
NTFY_TOKEN,
NTFY_USERNAME,
NTFY_PASSWORD,
NTFY_ACTIONS,
} = push_config;
const { NTFY_URL, NTFY_TOPIC, NTFY_PRIORITY, NTFY_TOKEN, NTFY_USERNAME, NTFY_PASSWORD, NTFY_ACTIONS } = push_config;
if (NTFY_TOPIC) {
const options = {
url: `${NTFY_URL || 'https://ntfy.sh'}/${NTFY_TOPIC}`,
@ -1285,9 +1277,7 @@ function ntfyNotify(text, desp) {
if (NTFY_TOKEN) {
options.headers['Authorization'] = `Bearer ${NTFY_TOKEN}`;
} else if (NTFY_USERNAME && NTFY_PASSWORD) {
options.headers['Authorization'] = `Basic ${Buffer.from(
`${NTFY_USERNAME}:${NTFY_PASSWORD}`,
).toString('base64')}`;
options.headers['Authorization'] = `Basic ${Buffer.from(`${NTFY_USERNAME}:${NTFY_PASSWORD}`).toString('base64')}`;
}
if (NTFY_ACTIONS) {
options.headers['Actions'] = encodeRFC2047(NTFY_ACTIONS);

View File

@ -4,16 +4,14 @@ import intl from 'react-intl-universal';
export function rootContainer(container: any) {
const locales = {
en: require('./locales/en-US.json'),
zh: require('./locales/zh-CN.json'),
'en': require('./locales/en-US.json'),
'zh': require('./locales/zh-CN.json'),
};
let currentLocale = intl
.determineLocale({
urlLocaleKey: 'lang',
cookieLocaleKey: 'lang',
localStorageLocaleKey: 'lang',
})
.slice(0, 2);
let currentLocale = intl.determineLocale({
urlLocaleKey: 'lang',
cookieLocaleKey: 'lang',
localStorageLocaleKey: 'lang',
}).slice(0, 2);
if (!currentLocale || !Object.keys(locales).includes(currentLocale)) {
currentLocale = 'zh';

View File

@ -136,7 +136,7 @@ const Config = () => {
lineNumbersMinChars: 3,
folding: false,
glyphMargin: false,
accessibilitySupport: 'off',
accessibilitySupport: 'off'
}}
onMount={(editor) => {
editorRef.current = editor;

View File

@ -1,5 +1,5 @@
import intl from 'react-intl-universal';
import React, { useEffect, useRef, useState } from 'react';
import intl from "react-intl-universal";
import React, { useEffect, useRef, useState } from "react";
import {
Modal,
message,
@ -8,17 +8,17 @@ import {
Statistic,
Button,
Typography,
} from 'antd';
import { request } from '@/utils/http';
import config from '@/utils/config';
} from "antd";
import { request } from "@/utils/http";
import config from "@/utils/config";
import {
Loading3QuartersOutlined,
CheckCircleOutlined,
} from '@ant-design/icons';
import { PageLoading } from '@ant-design/pro-layout';
import { logEnded } from '@/utils';
import { CrontabStatus } from './type';
import Ansi from 'ansi-to-react';
} from "@ant-design/icons";
import { PageLoading } from "@ant-design/pro-layout";
import { logEnded } from "@/utils";
import { CrontabStatus } from "./type";
import Ansi from "ansi-to-react";
const { Countdown } = Statistic;
@ -33,7 +33,7 @@ const CronLogModal = ({
data?: string;
logUrl?: string;
}) => {
const [value, setValue] = useState<string>(intl.get('启动中...'));
const [value, setValue] = useState<string>(intl.get("启动中..."));
const [loading, setLoading] = useState<any>(true);
const [executing, setExecuting] = useState<any>(true);
const [isPhone, setIsPhone] = useState(false);
@ -49,15 +49,15 @@ const CronLogModal = ({
.then(({ code, data }) => {
if (
code === 200 &&
localStorage.getItem('logCron') === uniqPath &&
localStorage.getItem("logCron") === uniqPath &&
data !== value
) {
const log = data as string;
setValue(log || intl.get('暂无日志'));
setValue(log || intl.get("暂无日志"));
const hasNext = Boolean(
log && !logEnded(log) && !log.includes('日志不存在'),
log && !logEnded(log) && !log.includes("日志不存在"),
);
if (!hasNext && !logEnded(value) && value !== intl.get('启动中...')) {
if (!hasNext && !logEnded(value) && value !== intl.get("启动中...")) {
setTimeout(() => {
autoScroll();
});
@ -85,13 +85,13 @@ const CronLogModal = ({
setTimeout(() => {
document
.querySelector('#log-flag')
?.scrollIntoView({ behavior: 'smooth' });
.querySelector("#log-flag")
?.scrollIntoView({ behavior: "smooth" });
}, 600);
};
const cancel = () => {
localStorage.removeItem('logCron');
localStorage.removeItem("logCron");
handleCancel();
};
@ -107,7 +107,7 @@ const CronLogModal = ({
const titleElement = () => {
return (
<div style={{ display: 'flex', alignItems: 'center' }}>
<div style={{ display: "flex", alignItems: "center" }}>
{(executing || loading) && <Loading3QuartersOutlined spin />}
{!executing && !loading && <CheckCircleOutlined />}
<Typography.Text ellipsis={true} style={{ marginLeft: 5 }}>
@ -144,7 +144,7 @@ const CronLogModal = ({
onCancel={() => cancel()}
footer={[
<Button type="primary" onClick={() => cancel()}>
{intl.get('知道了')}
{intl.get("知道了")}
</Button>,
]}
>
@ -156,9 +156,9 @@ const CronLogModal = ({
style={
isPhone
? {
fontFamily: 'Source Code Pro',
zoom: 0.83,
}
fontFamily: "Source Code Pro",
zoom: 0.83,
}
: {}
}
>

View File

@ -312,3 +312,4 @@ const CronLabelModal = ({
};
export { CronLabelModal, CronModal as default };

View File

@ -18,4 +18,4 @@ export enum Status {
'删除失败',
'队列中',
'已取消',
}
}

View File

@ -26,9 +26,7 @@ const Diff = () => {
const getConfig = () => {
request
.get(
`${config.apiPrefix}configs/detail?path=${encodeURIComponent(current)}`,
)
.get(`${config.apiPrefix}configs/detail?path=${encodeURIComponent(current)}`)
.then(({ code, data }) => {
if (code === 200) {
setCurrentValue(data);
@ -38,9 +36,7 @@ const Diff = () => {
const getSample = () => {
request
.get(
`${config.apiPrefix}configs/detail?path=${encodeURIComponent(origin)}`,
)
.get(`${config.apiPrefix}configs/detail?path=${encodeURIComponent(origin)}`)
.then(({ code, data }) => {
if (code === 200) {
setOriginValue(data);

View File

@ -1,4 +1,4 @@
import intl from 'react-intl-universal';
import intl from 'react-intl-universal'
import React, { useEffect, useState } from 'react';
import { Modal, message, Input, Form } from 'antd';
import { request } from '@/utils/http';
@ -55,9 +55,7 @@ const EditNameModal = ({
<Form form={form} layout="vertical" name="edit_name_modal">
<Form.Item
name="name"
rules={[
{ required: true, message: intl.get('请输入新的环境变量名称') },
]}
rules={[{ required: true, message: intl.get('请输入新的环境变量名称') }]}
>
<Input placeholder={intl.get('请输入新的环境变量名称')} />
</Form.Item>

View File

@ -64,4 +64,4 @@
.warningIcon {
font-size: 14px;
color: #faad14;
}
}

View File

@ -17,10 +17,12 @@ const UnsupportedFilePreview: React.FC<UnsupportedFilePreviewProps> = ({
<div className={styles.iconWrapper}>
<FileUnknownOutlined className={styles.icon} />
</div>
<div className={styles.message}>{intl.get('当前文件不支持预览')}</div>
<div className={styles.message}>
{intl.get('当前文件不支持预览')}
</div>
<Space direction="vertical" size={8} className={styles.actionArea}>
<Button
type="primary"
<Button
type="primary"
onClick={onForceOpen}
className={styles.button}
>
@ -36,4 +38,4 @@ const UnsupportedFilePreview: React.FC<UnsupportedFilePreviewProps> = ({
);
};
export default UnsupportedFilePreview;
export default UnsupportedFilePreview;

View File

@ -1,23 +1,23 @@
import { disableBody } from '@/utils';
import config from '@/utils/config';
import { request } from '@/utils/http';
import WebSocketManager from '@/utils/websocket';
import Ansi from 'ansi-to-react';
import { Button, Modal, Statistic, message } from 'antd';
import { useCallback, useEffect, useRef, useState } from 'react';
import intl from 'react-intl-universal';
import { disableBody } from "@/utils";
import config from "@/utils/config";
import { request } from "@/utils/http";
import WebSocketManager from "@/utils/websocket";
import Ansi from "ansi-to-react";
import { Button, Modal, Statistic, message } from "antd";
import { useCallback, useEffect, useRef, useState } from "react";
import intl from "react-intl-universal";
const { Countdown } = Statistic;
const CheckUpdate = ({ systemInfo }: any) => {
const [updateLoading, setUpdateLoading] = useState(false);
const [value, setValue] = useState('');
const [value, setValue] = useState("");
const modalRef = useRef<any>();
const checkUpgrade = () => {
if (updateLoading) return;
setUpdateLoading(true);
message.loading(intl.get('检查更新中...'), 0);
message.loading(intl.get("检查更新中..."), 0);
request
.put(`${config.apiPrefix}system/update-check`)
.then(({ code, data }) => {
@ -42,22 +42,22 @@ const CheckUpdate = ({ systemInfo }: any) => {
const showForceUpdateModal = (data: any) => {
Modal.confirm({
width: 500,
title: intl.get('更新'),
title: intl.get("更新"),
content: (
<>
<div>{intl.get('已经是最新版了!')}</div>
<div>{intl.get("已经是最新版了!")}</div>
<div style={{ fontSize: 12, fontWeight: 400, marginTop: 5 }}>
{intl.get('青龙')} {data.lastVersion}{' '}
{intl.get('是目前检测到的最新可用版本了。')}
{intl.get("青龙")} {data.lastVersion}{" "}
{intl.get("是目前检测到的最新可用版本了。")}
</div>
</>
),
okText: intl.get('重新下载'),
okText: intl.get("重新下载"),
onOk() {
showUpdatingModal();
request
.put(`${config.apiPrefix}system/update`)
.then((_data: any) => {})
.then((_data: any) => { })
.catch((error: any) => {
console.log(error);
});
@ -71,10 +71,10 @@ const CheckUpdate = ({ systemInfo }: any) => {
width: 500,
title: (
<>
<div>{intl.get('更新可用')}</div>
<div>{intl.get("更新可用")}</div>
<div style={{ fontSize: 12, fontWeight: 400, marginTop: 5 }}>
{intl.get('新版本')} {lastVersion}{' '}
{intl.get('可用,你使用的版本为')} {systemInfo.version}
{intl.get("新版本")} {lastVersion}{" "}
{intl.get("可用,你使用的版本为")} {systemInfo.version}
</div>
</>
),
@ -83,13 +83,13 @@ const CheckUpdate = ({ systemInfo }: any) => {
<Ansi>{lastLog}</Ansi>
</pre>
),
okText: intl.get('下载更新'),
cancelText: intl.get('以后再说'),
okText: intl.get("下载更新"),
cancelText: intl.get("以后再说"),
onOk() {
showUpdatingModal();
request
.put(`${config.apiPrefix}system/update`)
.then((_data: any) => {})
.then((_data: any) => { })
.catch((error: any) => {
console.log(error);
});
@ -98,14 +98,14 @@ const CheckUpdate = ({ systemInfo }: any) => {
};
const showUpdatingModal = () => {
setValue('');
setValue("");
modalRef.current = Modal.info({
width: 600,
maskClosable: false,
closable: false,
keyboard: false,
okButtonProps: { disabled: true },
title: intl.get('下载更新中...'),
title: intl.get("下载更新中..."),
centered: true,
content: (
<pre>
@ -122,13 +122,13 @@ const CheckUpdate = ({ systemInfo }: any) => {
message.success({
content: (
<span>
{intl.get('系统将在')}
{intl.get("系统将在")}
<Countdown
className="inline-countdown"
format="ss"
value={Date.now() + 1000 * 30}
/>
{intl.get('秒后自动刷新')}
{intl.get("秒后自动刷新")}
</span>
),
duration: 30,
@ -147,12 +147,12 @@ const CheckUpdate = ({ systemInfo }: any) => {
Modal.confirm({
width: 600,
maskClosable: false,
title: intl.get('确认重启'),
title: intl.get("确认重启"),
centered: true,
content: intl.get('系统安装包下载成功,确认重启'),
okText: intl.get('重启'),
content: intl.get("系统安装包下载成功,确认重启"),
okText: intl.get("重启"),
onOk() {
reloadSystem('system');
reloadSystem("system");
},
onCancel() {
modalRef.current.update({
@ -166,7 +166,7 @@ const CheckUpdate = ({ systemInfo }: any) => {
useEffect(() => {
if (!value) return;
const updateFailed = value.includes('失败,请检查');
const updateFailed = value.includes("失败,请检查");
modalRef.current.update({
maskClosable: updateFailed,
@ -185,19 +185,19 @@ const CheckUpdate = ({ systemInfo }: any) => {
const handleMessage = useCallback((payload: any) => {
let { message: _message } = payload;
const updateFailed = _message.includes('失败,请检查');
const updateFailed = _message.includes("失败,请检查");
if (updateFailed) {
message.error(intl.get('更新失败,请检查网络及日志或稍后再试'));
message.error(intl.get("更新失败,请检查网络及日志或稍后再试"));
}
setTimeout(() => {
document
.querySelector('#log-identifier')
?.scrollIntoView({ behavior: 'smooth' });
.querySelector("#log-identifier")
?.scrollIntoView({ behavior: "smooth" });
}, 600);
if (_message.includes('更新包下载成功')) {
if (_message.includes("更新包下载成功")) {
setTimeout(() => {
showReloadModal();
}, 1000);
@ -208,24 +208,24 @@ const CheckUpdate = ({ systemInfo }: any) => {
useEffect(() => {
const ws = WebSocketManager.getInstance();
ws.subscribe('updateSystemVersion', handleMessage);
ws.subscribe("updateSystemVersion", handleMessage);
return () => {
ws.unsubscribe('updateSystemVersion', handleMessage);
ws.unsubscribe("updateSystemVersion", handleMessage);
};
}, []);
return (
<>
<Button type="primary" onClick={checkUpgrade}>
{intl.get('检查更新')}
{intl.get("检查更新")}
</Button>
<Button
type="primary"
onClick={() => reloadSystem('reload')}
onClick={() => reloadSystem("reload")}
style={{ marginLeft: 8 }}
>
{intl.get('重新启动')}
{intl.get("重新启动")}
</Button>
</>
);

View File

@ -76,9 +76,7 @@ const NotificationSetting = ({ data }: any) => {
>
{x.items ? (
<Select
placeholder={
x.placeholder || `${intl.get('请选择')} ${x.label}`
}
placeholder={x.placeholder || `${intl.get('请选择')} ${x.label}`}
disabled={loading}
>
{x.items.map((y) => (
@ -91,9 +89,7 @@ const NotificationSetting = ({ data }: any) => {
<Input.TextArea
disabled={loading}
autoSize={{ minRows: 1, maxRows: 5 }}
placeholder={
x.placeholder || `${intl.get('请输入')} ${x.label}`
}
placeholder={x.placeholder || `${intl.get('请输入')} ${x.label}`}
/>
)}
</Form.Item>

View File

@ -97,7 +97,9 @@ const SecuritySettings = ({ user, userChange }: any) => {
const onChange = (e) => {
if (e.file && e.file.response) {
setAvatar(`${config.apiPrefix}static/${e.file.response.data}`);
setAvatar(
`${config.apiPrefix}static/${e.file.response.data}`,
);
userChange();
}
};

View File

@ -1,11 +1,11 @@
import * as monaco from 'monaco-editor';
interface FileTypeConfig {
extensions?: string[]; // 文件扩展名
filenames?: string[]; // 完整文件名
patterns?: RegExp[]; // 文件名正则匹配
startsWith?: string[]; // 文件名前缀匹配
endsWith?: string[]; // 文件名后缀匹配
extensions?: string[]; // 文件扩展名
filenames?: string[]; // 完整文件名
patterns?: RegExp[]; // 文件名正则匹配
startsWith?: string[]; // 文件名前缀匹配
endsWith?: string[]; // 文件名后缀匹配
}
// 文件类型分类配置(只包含特殊文件类型)
@ -13,13 +13,13 @@ const fileTypeConfigs: Record<string, FileTypeConfig> = {
// 前端特殊文件
frontend: {
extensions: [
'.json5', // JSON5
'.vue', // Vue
'.svelte', // Svelte
'.astro', // Astro
'.wxss', // 微信小程序样式
'.pcss', // PostCSS
'.acss', // 支付宝小程序样式
'.json5', // JSON5
'.vue', // Vue
'.svelte', // Svelte
'.astro', // Astro
'.wxss', // 微信小程序样式
'.pcss', // PostCSS
'.acss', // 支付宝小程序样式
],
patterns: [
/\.env\.(local|development|production|test)$/,
@ -32,28 +32,28 @@ const fileTypeConfigs: Record<string, FileTypeConfig> = {
// 小程序相关
miniprogram: {
extensions: [
'.wxml', // 微信小程序
'.wxs', // 微信小程序
'.axml', // 支付宝小程序
'.sjs', // 支付宝小程序
'.swan', // 百度小程序
'.ttml', // 字节跳动小程序
'.ttss', // 字节跳动小程序
'.wxl', // 微信小程序语言包
'.qml', // QQ小程序
'.qss', // QQ小程序
'.ksml', // 快手小程序
'.kss', // 快手小程序
'.wxml', // 微信小程序
'.wxs', // 微信小程序
'.axml', // 支付宝小程序
'.sjs', // 支付宝小程序
'.swan', // 百度小程序
'.ttml', // 字节跳动小程序
'.ttss', // 字节跳动小程序
'.wxl', // 微信小程序语言包
'.qml', // QQ小程序
'.qss', // QQ小程序
'.ksml', // 快手小程序
'.kss', // 快手小程序
],
},
// 开发工具相关
devtools: {
extensions: [
'.prisma', // Prisma
'.mdx', // MDX
'.swagger', // Swagger
'.openapi', // OpenAPI
'.prisma', // Prisma
'.mdx', // MDX
'.swagger', // Swagger
'.openapi', // OpenAPI
],
},
@ -84,7 +84,9 @@ const fileTypeConfigs: Record<string, FileTypeConfig> = {
'.gcloudignore',
'.htaccess',
],
patterns: [/^\.env\./],
patterns: [
/^\.env\./,
],
},
// CI/CD 配置
@ -104,33 +106,28 @@ const fileTypeConfigs: Record<string, FileTypeConfig> = {
*/
export function canPreviewInMonaco(fileName: string): boolean {
if (!fileName) return false;
// 获取 Monaco 支持的语言
const supportedLanguages = monaco.languages.getLanguages();
const ext = fileName.slice(fileName.lastIndexOf('.')).toLowerCase();
const lowercaseFileName = fileName.toLowerCase();
// 检查 Monaco 原生支持
if (
supportedLanguages.some(
(lang) =>
lang.extensions?.includes(ext) ||
lang.filenames?.includes(lowercaseFileName),
)
) {
if (supportedLanguages.some((lang) =>
lang.extensions?.includes(ext) ||
(lang.filenames?.includes(lowercaseFileName))
)) {
return true;
}
// 检查额外支持的文件类型
return Object.values(fileTypeConfigs).some((config) => {
return Object.values(fileTypeConfigs).some(config => {
return (
config.extensions?.includes(ext) ||
config.filenames?.includes(lowercaseFileName) ||
config.patterns?.some((pattern) => pattern.test(lowercaseFileName)) ||
config.startsWith?.some((prefix) =>
lowercaseFileName.startsWith(prefix),
) ||
config.endsWith?.some((suffix) => lowercaseFileName.endsWith(suffix))
(config.extensions?.includes(ext)) ||
(config.filenames?.includes(lowercaseFileName)) ||
(config.patterns?.some(pattern => pattern.test(lowercaseFileName))) ||
(config.startsWith?.some(prefix => lowercaseFileName.startsWith(prefix))) ||
(config.endsWith?.some(suffix => lowercaseFileName.endsWith(suffix)))
);
});
}
@ -142,19 +139,17 @@ export function canPreviewInMonaco(fileName: string): boolean {
*/
export function getFileCategory(fileName: string): string {
if (!fileName) return 'unknown';
const lowercaseFileName = fileName.toLowerCase();
const ext = fileName.slice(fileName.lastIndexOf('.')).toLowerCase();
for (const [category, config] of Object.entries(fileTypeConfigs)) {
if (
config.extensions?.includes(ext) ||
config.filenames?.includes(lowercaseFileName) ||
config.patterns?.some((pattern) => pattern.test(lowercaseFileName)) ||
config.startsWith?.some((prefix) =>
lowercaseFileName.startsWith(prefix),
) ||
config.endsWith?.some((suffix) => lowercaseFileName.endsWith(suffix))
(config.extensions?.includes(ext)) ||
(config.filenames?.includes(lowercaseFileName)) ||
(config.patterns?.some(pattern => pattern.test(lowercaseFileName))) ||
(config.startsWith?.some(prefix => lowercaseFileName.startsWith(prefix))) ||
(config.endsWith?.some(suffix => lowercaseFileName.endsWith(suffix)))
) {
return category;
}
@ -162,13 +157,10 @@ export function getFileCategory(fileName: string): string {
// 检查 Monaco 原生支持
const supportedLanguages = monaco.languages.getLanguages();
if (
supportedLanguages.some(
(lang) =>
lang.extensions?.includes(ext) ||
lang.filenames?.includes(lowercaseFileName),
)
) {
if (supportedLanguages.some((lang) =>
lang.extensions?.includes(ext) ||
(lang.filenames?.includes(lowercaseFileName))
)) {
return 'monaco-native';
}

View File

@ -5,8 +5,7 @@ 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 subscriptions: Map<SockMessageType, Set<(p: any) => void>> = new Map();
private options: {
maxReconnectAttempts: number;
reconnectInterval: number;
@ -16,10 +15,7 @@ class WebSocketManager {
private heartbeatTimeout: NodeJS.Timeout | null = null;
private state: 'closed' | 'connecting' | 'open' = 'closed';
constructor(
url: string,
options: Partial<typeof WebSocketManager.prototype.options> = {},
) {
constructor(url: string, options: Partial<typeof WebSocketManager.prototype.options> = {}) {
this.url = url;
this.options = {
maxReconnectAttempts: options.maxReconnectAttempts || 5,
@ -30,10 +26,7 @@ class WebSocketManager {
this.init();
}
public static getInstance(
url: string = '',
options?: Partial<typeof WebSocketManager.prototype.options>,
): WebSocketManager {
public static getInstance(url: string = '', options?: Partial<typeof WebSocketManager.prototype.options>): WebSocketManager {
if (!WebSocketManager.instance) {
WebSocketManager.instance = new WebSocketManager(url, options);
}
@ -54,9 +47,7 @@ class WebSocketManager {
this.socket = null;
this.reconnectAttempts++;
await new Promise((resolve) =>
setTimeout(resolve, this.options.reconnectInterval),
);
await new Promise((resolve) => setTimeout(resolve, this.options.reconnectInterval));
}
} catch (error) {
this.handleError(error);