修复sqlite数据操作类型

This commit is contained in:
whyour 2022-01-08 01:09:38 +08:00
parent 89ed8527d6
commit e75a683173
21 changed files with 199 additions and 217 deletions

View File

@ -84,19 +84,22 @@ export default (app: Router) => {
}, },
); );
route.put( route.delete(
'/removelabels', '/labels',
celebrate({ celebrate({
body: Joi.object({ body: Joi.object({
ids: Joi.array().items(Joi.number().required()), ids: Joi.array().items(Joi.number().required()),
labels: Joi.array().items(Joi.string().required()), labels: Joi.array().items(Joi.string().required()),
}) }),
}), }),
async (req: Request, res: Response, next: NextFunction) => { async (req: Request, res: Response, next: NextFunction) => {
const logger: Logger = Container.get('logger'); const logger: Logger = Container.get('logger');
try { try {
const cronService = Container.get(CronService); const cronService = Container.get(CronService);
const data = await cronService.removeLabels(req.body.ids,req.body.labels); const data = await cronService.removeLabels(
req.body.ids,
req.body.labels,
);
return res.send({ code: 200, data }); return res.send({ code: 200, data });
} catch (e) { } catch (e) {
logger.error('🔥 error: %o', e); logger.error('🔥 error: %o', e);
@ -105,13 +108,13 @@ export default (app: Router) => {
}, },
); );
route.put( route.post(
'/addlabels', '/labels',
celebrate({ celebrate({
body: Joi.object({ body: Joi.object({
ids: Joi.array().items(Joi.number().required()), ids: Joi.array().items(Joi.number().required()),
labels: Joi.array().items(Joi.string().required()), labels: Joi.array().items(Joi.string().required()),
}) }),
}), }),
async (req: Request, res: Response, next: NextFunction) => { async (req: Request, res: Response, next: NextFunction) => {
const logger: Logger = Container.get('logger'); const logger: Logger = Container.get('logger');
@ -293,7 +296,7 @@ export default (app: Router) => {
const logger: Logger = Container.get('logger'); const logger: Logger = Container.get('logger');
try { try {
const cronService = Container.get(CronService); const cronService = Container.get(CronService);
const data = await cronService.get(req.params.id); const data = await cronService.getDb({ id: req.params.id });
return res.send({ code: 200, data }); return res.send({ code: 200, data });
} catch (e) { } catch (e) {
logger.error('🔥 error: %o', e); logger.error('🔥 error: %o', e);

View File

@ -27,7 +27,7 @@ export default (app: Router) => {
Joi.object({ Joi.object({
name: Joi.string().required(), name: Joi.string().required(),
type: Joi.number().required(), type: Joi.number().required(),
remark: Joi.number().optional().allow(''), remark: Joi.string().optional().allow(''),
}), }),
), ),
}), }),
@ -49,9 +49,9 @@ export default (app: Router) => {
celebrate({ celebrate({
body: Joi.object({ body: Joi.object({
name: Joi.string().required(), name: Joi.string().required(),
id: Joi.string().required(), id: Joi.number().required(),
type: Joi.number().required(), type: Joi.number().required(),
remark: Joi.number().optional().allow(''), remark: Joi.string().optional().allow(''),
}), }),
}), }),
async (req: Request, res: Response, next: NextFunction) => { async (req: Request, res: Response, next: NextFunction) => {
@ -107,14 +107,14 @@ export default (app: Router) => {
'/:id', '/:id',
celebrate({ celebrate({
params: Joi.object({ params: Joi.object({
id: Joi.string().required(), id: Joi.number().required(),
}), }),
}), }),
async (req: Request<{ id: number }>, res: Response, next: NextFunction) => { async (req: Request<{ id: number }>, res: Response, next: NextFunction) => {
const logger: Logger = Container.get('logger'); const logger: Logger = Container.get('logger');
try { try {
const dependenceService = Container.get(DependenceService); const dependenceService = Container.get(DependenceService);
const data = await dependenceService.get(req.params.id); const data = await dependenceService.getDb({ id: req.params.id });
return res.send({ code: 200, data }); return res.send({ code: 200, data });
} catch (e) { } catch (e) {
logger.error('🔥 error: %o', e); logger.error('🔥 error: %o', e);

View File

@ -51,7 +51,7 @@ export default (app: Router) => {
value: Joi.string().required(), value: Joi.string().required(),
name: Joi.string().required(), name: Joi.string().required(),
remarks: Joi.string().optional().allow(''), remarks: Joi.string().optional().allow(''),
id: Joi.string().required(), id: Joi.number().required(),
}), }),
}), }),
async (req: Request, res: Response, next: NextFunction) => { async (req: Request, res: Response, next: NextFunction) => {
@ -89,7 +89,7 @@ export default (app: Router) => {
'/:id/move', '/:id/move',
celebrate({ celebrate({
params: Joi.object({ params: Joi.object({
id: Joi.string().required(), id: Joi.number().required(),
}), }),
body: Joi.object({ body: Joi.object({
fromIndex: Joi.number().required(), fromIndex: Joi.number().required(),
@ -170,7 +170,7 @@ export default (app: Router) => {
'/:id', '/:id',
celebrate({ celebrate({
params: Joi.object({ params: Joi.object({
id: Joi.string().required(), id: Joi.number().required(),
}), }),
}), }),
async (req: Request<{ id: number }>, res: Response, next: NextFunction) => { async (req: Request<{ id: number }>, res: Response, next: NextFunction) => {

View File

@ -49,7 +49,7 @@ export default (app: Router) => {
body: Joi.object({ body: Joi.object({
name: Joi.string().optional().allow(''), name: Joi.string().optional().allow(''),
scopes: Joi.array().items(Joi.string()), scopes: Joi.array().items(Joi.string()),
id: Joi.string().required(), id: Joi.number().required(),
}), }),
}), }),
async (req: Request, res: Response, next: NextFunction) => { async (req: Request, res: Response, next: NextFunction) => {
@ -87,7 +87,7 @@ export default (app: Router) => {
'/apps/:id/reset-secret', '/apps/:id/reset-secret',
celebrate({ celebrate({
params: Joi.object({ params: Joi.object({
id: Joi.string().required(), id: Joi.number().required(),
}), }),
}), }),
async (req: Request<{ id: number }>, res: Response, next: NextFunction) => { async (req: Request<{ id: number }>, res: Response, next: NextFunction) => {

View File

@ -14,7 +14,7 @@ export class Crontab {
isDisabled?: 1 | 0; isDisabled?: 1 | 0;
log_path?: string; log_path?: string;
isPinned?: 1 | 0; isPinned?: 1 | 0;
labels: Array<string>; labels?: string[];
last_running_time?: number; last_running_time?: number;
last_execution_time?: number; last_execution_time?: number;
@ -60,18 +60,7 @@ export const CrontabModel = sequelize.define<CronInstance>('Crontab', {
isDisabled: DataTypes.NUMBER, isDisabled: DataTypes.NUMBER,
isPinned: DataTypes.NUMBER, isPinned: DataTypes.NUMBER,
log_path: DataTypes.STRING, log_path: DataTypes.STRING,
labels: { labels: DataTypes.JSON,
type: DataTypes.STRING,
allowNull: false,
get() {
if (this.getDataValue('labels')) {
return this.getDataValue('labels').split(',')
}
},
set(value) {
this.setDataValue('labels', value.join(','));
},
},
last_running_time: DataTypes.NUMBER, last_running_time: DataTypes.NUMBER,
last_execution_time: DataTypes.NUMBER, last_execution_time: DataTypes.NUMBER,
}); });

View File

@ -55,9 +55,9 @@ export const DependenceModel = sequelize.define<DependenceInstance>(
'Dependence', 'Dependence',
{ {
name: DataTypes.STRING, name: DataTypes.STRING,
type: DataTypes.STRING, type: DataTypes.NUMBER,
timestamp: DataTypes.STRING, timestamp: DataTypes.STRING,
status: DataTypes.STRING, status: DataTypes.NUMBER,
log: DataTypes.JSON, log: DataTypes.JSON,
remark: DataTypes.STRING, remark: DataTypes.STRING,
}, },

View File

@ -60,7 +60,7 @@ export default async () => {
db.authDb.persistence.compactDatafile(); db.authDb.persistence.compactDatafile();
try { try {
await sequelize.sync(); await sequelize.sync({ alter: true });
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} }

View File

@ -31,25 +31,19 @@ export default class CronService {
} }
public async insert(payload: Crontab): Promise<Crontab> { public async insert(payload: Crontab): Promise<Crontab> {
return await CrontabModel.create(payload); return await CrontabModel.create(payload, { returning: true });
} }
public async update(payload: Crontab): Promise<Crontab> { public async update(payload: Crontab): Promise<Crontab> {
const { id, ...other } = payload; payload.saved = false;
const doc = await this.get(id as number); const newDoc = await this.updateDb(payload);
const tab = new Crontab({ ...doc, ...other });
tab.saved = false;
const newDoc = await this.updateDb(tab);
await this.set_crontab(this.isSixCron(newDoc)); await this.set_crontab(this.isSixCron(newDoc));
return newDoc; return newDoc;
} }
public async updateDb(payload: Crontab): Promise<Crontab> { public async updateDb(payload: Crontab): Promise<Crontab> {
const result = await CrontabModel.update( await CrontabModel.update(payload, { where: { id: payload.id } });
{ ...payload }, return await this.getDb({ id: payload.id });
{ where: { id: payload.id } },
);
return result[1][0];
} }
public async status({ public async status({
@ -96,40 +90,53 @@ export default class CronService {
public async addLabels(ids: string[], labels: string[]) { public async addLabels(ids: string[], labels: string[]) {
const docs = await CrontabModel.findAll({ where: { id: ids } }); const docs = await CrontabModel.findAll({ where: { id: ids } });
for (const doc of docs) { for (const doc of docs) {
await CrontabModel.update({ await CrontabModel.update(
labels: Array.from(new Set(doc.labels.concat(labels))) {
},{ where: {id:doc.id}}); labels: Array.from(new Set((doc.labels || []).concat(labels))),
},
{ where: { id: doc.id } },
);
} }
} }
public async removeLabels(ids: string[], labels: string[]) { public async removeLabels(ids: string[], labels: string[]) {
const docs = await CrontabModel.findAll({ where: { id: ids } }); const docs = await CrontabModel.findAll({ where: { id: ids } });
for (const doc of docs) { for (const doc of docs) {
await CrontabModel.update({ await CrontabModel.update(
labels: doc.labels.filter( label => !labels.includes(label) ) {
},{ where: {id:doc.id}}); labels: (doc.labels || []).filter((label) => !labels.includes(label)),
},
{ where: { id: doc.id } },
);
} }
} }
public async crontabs(searchText?: string): Promise<Crontab[]> { public async crontabs(searchText?: string): Promise<Crontab[]> {
let query = {}; let query = {};
if (searchText) { if (searchText) {
const textArray = searchText.split(":"); const textArray = searchText.split(':');
switch (textArray[0]) { switch (textArray[0]) {
case "name": case 'name':
query = {name:{[Op.or]:createRegexp(textArray[1])}}; case 'command':
break; case 'schedule':
case "command": case 'label':
query = {command:{[Op.or]:createRegexp(textArray[1])}}; const column = textArray[0] === 'label' ? 'labels' : textArray[0];
break; query = {
case "schedule": [column]: {
query = {schedule:{[Op.or]:createRegexp(textArray[1])}}; [Op.or]: [
break; { [Op.like]: `%${textArray[1]}%` },
case "label": { [Op.like]: `%${encodeURIComponent(textArray[1])}%` },
query = {labels:{[Op.or]:createRegexp(textArray[1])}}; ],
},
};
break; break;
default: default:
const reg = createRegexp(searchText); const reg = {
[Op.or]: [
{ [Op.like]: `%${searchText}%` },
{ [Op.like]: `%${encodeURIComponent(searchText)}%` },
],
};
query = { query = {
[Op.or]: [ [Op.or]: [
{ {
@ -155,19 +162,11 @@ export default class CronService {
} catch (error) { } catch (error) {
throw error; throw error;
} }
function createRegexp(text:string) {
return {
[Op.or]: [
{ [Op.like]: `%${text}%` },
{ [Op.like]: `%${encodeURIComponent(text)}%` },
],
};
}
} }
public async get(id: number): Promise<Crontab> { public async getDb(query: any): Promise<Crontab> {
const result = await CrontabModel.findAll({ where: { id } }); const doc: any = await CrontabModel.findOne({ where: { ...query } });
return result[0] as any; return doc && (doc.get({ plain: true }) as Crontab);
} }
public async run(ids: number[]) { public async run(ids: number[]) {
@ -243,7 +242,7 @@ export default class CronService {
private async runSingle(cronId: number): Promise<number> { private async runSingle(cronId: number): Promise<number> {
return new Promise(async (resolve: any) => { return new Promise(async (resolve: any) => {
const cron = await this.get(cronId); const cron = await this.getDb({ id: cronId });
if (cron.status !== CrontabStatus.queued) { if (cron.status !== CrontabStatus.queued) {
resolve(); resolve();
return; return;
@ -312,7 +311,7 @@ export default class CronService {
} }
public async log(id: number) { public async log(id: number) {
const doc = await this.get(id); const doc = await this.getDb({ id });
if (!doc) { if (!doc) {
return ''; return '';
} }

View File

@ -41,7 +41,7 @@ export default class DependenceService {
payload: Dependence & { id: string }, payload: Dependence & { id: string },
): Promise<Dependence> { ): Promise<Dependence> {
const { id, ...other } = payload; const { id, ...other } = payload;
const doc = await this.get(id); const doc = await this.getDb({ id });
const tab = new Dependence({ const tab = new Dependence({
...doc, ...doc,
...other, ...other,
@ -53,18 +53,16 @@ export default class DependenceService {
} }
private async updateDb(payload: Dependence): Promise<Dependence> { private async updateDb(payload: Dependence): Promise<Dependence> {
const [, docs] = await DependenceModel.update( await DependenceModel.update(payload, { where: { id: payload.id } });
{ ...payload }, return await this.getDb({ id: payload.id });
{ where: { id: payload.id } },
);
return docs[0];
} }
public async remove(ids: number[]) { public async remove(ids: number[]) {
const [, docs] = await DependenceModel.update( await DependenceModel.update(
{ status: DependenceStatus.removing, log: [] }, { status: DependenceStatus.removing, log: [] },
{ where: { id: ids } }, { where: { id: ids } },
); );
const docs = await DependenceModel.findAll({ where: { id: ids } });
this.installOrUninstallDependencies(docs, false); this.installOrUninstallDependencies(docs, false);
} }
@ -82,7 +80,7 @@ export default class DependenceService {
const encodeText = encodeURIComponent(searchValue); const encodeText = encodeURIComponent(searchValue);
const reg = { const reg = {
[Op.or]: [ [Op.or]: [
{ [Op.like]: `%${encodeText}&` }, { [Op.like]: `%${searchValue}&` },
{ [Op.like]: `%${encodeText}%` }, { [Op.like]: `%${encodeText}%` },
], ],
}; };
@ -101,10 +99,12 @@ export default class DependenceService {
} }
public async reInstall(ids: number[]): Promise<Dependence[]> { public async reInstall(ids: number[]): Promise<Dependence[]> {
const [, docs] = await DependenceModel.update( await DependenceModel.update(
{ status: DependenceStatus.installing, log: [] }, { status: DependenceStatus.installing, log: [] },
{ where: { id: ids } }, { where: { id: ids } },
); );
const docs = await DependenceModel.findAll({ where: { id: ids } });
await this.installOrUninstallDependencies(docs); await this.installOrUninstallDependencies(docs);
return docs; return docs;
} }
@ -114,25 +114,22 @@ export default class DependenceService {
return docs; return docs;
} }
public async get(id: number): Promise<Dependence> { public async getDb(query: any): Promise<Dependence> {
const docs = await DependenceModel.findAll({ where: { id } }); const doc: any = await DependenceModel.findOne({ where: { ...query } });
return docs[0]; return doc && (doc.get({ plain: true }) as Dependence);
} }
private async updateLog(ids: number[], log: string): Promise<void> { private async updateLog(ids: number[], log: string): Promise<void> {
const doc = await DependenceModel.findOne({ where: { id: ids } }); const doc = await DependenceModel.findOne({ where: { id: ids } });
const newLog = doc?.log ? [...doc.log, log] : [log]; const newLog = doc?.log ? [...doc.log, log] : [log];
const [, docs] = await DependenceModel.update( await DependenceModel.update({ log: newLog }, { where: { id: ids } });
{ status: DependenceStatus.installing, log: newLog },
{ where: { id: ids } },
);
} }
public installOrUninstallDependencies( public installOrUninstallDependencies(
dependencies: Dependence[], dependencies: Dependence[],
isInstall: boolean = true, isInstall: boolean = true,
) { ) {
return new Promise((resolve) => { return new Promise(async (resolve) => {
if (dependencies.length === 0) { if (dependencies.length === 0) {
resolve(null); resolve(null);
return; return;
@ -154,41 +151,41 @@ export default class DependenceService {
).toLocaleString()}`, ).toLocaleString()}`,
references: depIds, references: depIds,
}); });
this.updateLog( await this.updateLog(
depIds, depIds,
`开始${actionText}依赖 ${depNames},开始时间 ${new Date( `开始${actionText}依赖 ${depNames},开始时间 ${new Date(
startTime, startTime,
).toLocaleString()}\n`, ).toLocaleString()}\n`,
); );
cp.stdout.on('data', (data) => { cp.stdout.on('data', async (data) => {
this.sockService.sendMessage({ this.sockService.sendMessage({
type: 'installDependence', type: 'installDependence',
message: data.toString(), message: data.toString(),
references: depIds, references: depIds,
}); });
this.updateLog(depIds, data.toString()); await this.updateLog(depIds, data.toString());
}); });
cp.stderr.on('data', (data) => { cp.stderr.on('data', async (data) => {
this.sockService.sendMessage({ this.sockService.sendMessage({
type: 'installDependence', type: 'installDependence',
message: data.toString(), message: data.toString(),
references: depIds, references: depIds,
}); });
this.updateLog(depIds, data.toString()); await this.updateLog(depIds, data.toString());
}); });
cp.on('error', (err) => { cp.on('error', async (err) => {
this.sockService.sendMessage({ this.sockService.sendMessage({
type: 'installDependence', type: 'installDependence',
message: JSON.stringify(err), message: JSON.stringify(err),
references: depIds, references: depIds,
}); });
this.updateLog(depIds, JSON.stringify(err)); await this.updateLog(depIds, JSON.stringify(err));
resolve(null); resolve(null);
}); });
cp.on('close', (code) => { cp.on('close', async (code) => {
const endTime = Date.now(); const endTime = Date.now();
const isSucceed = code === 0; const isSucceed = code === 0;
const resultText = isSucceed ? '成功' : '失败'; const resultText = isSucceed ? '成功' : '失败';
@ -200,7 +197,7 @@ export default class DependenceService {
).toLocaleString()} ${(endTime - startTime) / 1000} `, ).toLocaleString()} ${(endTime - startTime) / 1000} `,
references: depIds, references: depIds,
}); });
this.updateLog( await this.updateLog(
depIds, depIds,
`依赖${actionText}${resultText},结束时间 ${new Date( `依赖${actionText}${resultText},结束时间 ${new Date(
endTime, endTime,
@ -217,8 +214,7 @@ export default class DependenceService {
? DependenceStatus.installFailed ? DependenceStatus.installFailed
: DependenceStatus.removeFailed; : DependenceStatus.removeFailed;
} }
await DependenceModel.update({ status }, { where: { id: depIds } });
DependenceModel.update({ status }, { where: { id: depIds } });
// 如果删除依赖成功3秒后删除数据库记录 // 如果删除依赖成功3秒后删除数据库记录
if (isSucceed && !isInstall) { if (isSucceed && !isInstall) {

View File

@ -34,20 +34,14 @@ export default class EnvService {
} }
public async update(payload: Env): Promise<Env> { public async update(payload: Env): Promise<Env> {
const { id, ...other } = payload; const newDoc = await this.updateDb(payload);
const doc = await this.get(id as number);
const tab = new Env({ ...doc, ...other });
const newDoc = await this.updateDb(tab);
await this.set_envs(); await this.set_envs();
return newDoc; return newDoc;
} }
private async updateDb(payload: Env): Promise<Env> { private async updateDb(payload: Env): Promise<Env> {
const [, docs] = await EnvModel.update( await EnvModel.update({ ...payload }, { where: { id: payload.id } });
{ ...payload }, return await this.getDb({ id: payload.id });
{ where: { id: payload.id } },
);
return docs[0];
} }
public async remove(ids: string[]) { public async remove(ids: string[]) {
@ -126,13 +120,13 @@ export default class EnvService {
return docs; return docs;
} }
public async get(id: number): Promise<Env> { public async getDb(query: any): Promise<Env> {
const docs = await EnvModel.findAll({ where: { id } }); const doc: any = await EnvModel.findOne({ where: { ...query } });
return docs[0]; return doc && (doc.get({ plain: true }) as Env);
} }
public async disabled(ids: string[]) { public async disabled(ids: string[]) {
const [, docs] = await EnvModel.update( await EnvModel.update(
{ status: EnvStatus.disabled }, { status: EnvStatus.disabled },
{ where: { id: ids } }, { where: { id: ids } },
); );
@ -140,15 +134,12 @@ export default class EnvService {
} }
public async enabled(ids: string[]) { public async enabled(ids: string[]) {
const [, docs] = await EnvModel.update( await EnvModel.update({ status: EnvStatus.normal }, { where: { id: ids } });
{ status: EnvStatus.normal },
{ where: { id: ids } },
);
await this.set_envs(); await this.set_envs();
} }
public async updateNames({ ids, name }: { ids: string[]; name: string }) { public async updateNames({ ids, name }: { ids: string[]; name: string }) {
const [, docs] = await EnvModel.update({ name }, { where: { id: ids } }); await EnvModel.update({ name }, { where: { id: ids } });
await this.set_envs(); await this.set_envs();
} }

View File

@ -12,7 +12,7 @@ export default class OpenService {
constructor(@Inject('logger') private logger: winston.Logger) {} constructor(@Inject('logger') private logger: winston.Logger) {}
public async findTokenByValue(token: string): Promise<App | null> { public async findTokenByValue(token: string): Promise<App | null> {
const doc = await AppModel.findOne({ const doc = await this.getDb({
where: sequelize.fn( where: sequelize.fn(
'JSON_CONTAINS', 'JSON_CONTAINS',
sequelize.col('tokens'), sequelize.col('tokens'),
@ -23,32 +23,35 @@ export default class OpenService {
} }
public async create(payload: App): Promise<App> { public async create(payload: App): Promise<App> {
const tab = new App({ ...payload }); const tab = { ...payload };
tab.client_id = createRandomString(12, 12); tab.client_id = createRandomString(12, 12);
tab.client_secret = createRandomString(24, 24); tab.client_secret = createRandomString(24, 24);
const docs = await this.insert([tab]); const doc = await this.insert(tab);
return { ...docs[0], tokens: [] }; return { ...doc, tokens: [] };
} }
public async insert(payloads: App[]): Promise<App[]> { public async insert(payloads: App): Promise<App> {
const docs = await AppModel.bulkCreate(payloads); const doc = await AppModel.create(payloads, { returning: true });
return docs; return doc.get({ plain: true }) as App;
} }
public async update(payload: App): Promise<App> { public async update(payload: App): Promise<App> {
const { id, client_id, client_secret, tokens, ...other } = payload; const newDoc = await this.updateDb({
const doc = await this.get(id); name: payload.name,
const tab = new App({ ...doc, ...other }); scopes: payload.scopes,
const newDoc = await this.updateDb(tab); id: payload.id,
} as any);
return { ...newDoc, tokens: [] }; return { ...newDoc, tokens: [] };
} }
private async updateDb(payload: App): Promise<App> { private async updateDb(payload: App): Promise<App> {
const [, docs] = await AppModel.update( await AppModel.update(payload, { where: { id: payload.id } });
{ ...payload }, return await this.getDb({ id: payload.id });
{ where: { id: payload.id } }, }
);
return docs[0]; public async getDb(query: any): Promise<App> {
const doc: any = await AppModel.findOne({ where: { ...query } });
return doc && (doc.get({ plain: true }) as App);
} }
public async remove(ids: number[]) { public async remove(ids: number[]) {
@ -56,10 +59,7 @@ export default class OpenService {
} }
public async resetSecret(id: number): Promise<App> { public async resetSecret(id: number): Promise<App> {
const doc = await this.get(id); const tab: any = { client_secret: createRandomString(24, 24), tokens: [] };
const tab = new App({ ...doc });
tab.client_secret = createRandomString(24, 24);
tab.tokens = [];
const newDoc = await this.updateDb(tab); const newDoc = await this.updateDb(tab);
return newDoc; return newDoc;
} }
@ -104,12 +104,7 @@ export default class OpenService {
private async find(query: any, sort?: any): Promise<App[]> { private async find(query: any, sort?: any): Promise<App[]> {
const docs = await AppModel.findAll({ where: { ...query } }); const docs = await AppModel.findAll({ where: { ...query } });
return docs; return docs.map((x) => x.get({ plain: true }));
}
public async get(id: number): Promise<App> {
const docs = await AppModel.findAll({ where: { id } });
return docs[0];
} }
public async authToken({ public async authToken({
@ -123,7 +118,7 @@ export default class OpenService {
const expiration = Math.round(Date.now() / 1000) + 2592000; // 2592000 30天 const expiration = Math.round(Date.now() / 1000) + 2592000; // 2592000 30天
const doc = await AppModel.findOne({ where: { client_id, client_secret } }); const doc = await AppModel.findOne({ where: { client_id, client_secret } });
if (doc) { if (doc) {
const [, docs] = await AppModel.update( await AppModel.update(
{ tokens: [...(doc.tokens || []), { value: token, expiration }] }, { tokens: [...(doc.tokens || []), { value: token, expiration }] },
{ where: { client_id, client_secret } }, { where: { client_id, client_secret } },
); );

View File

@ -24,18 +24,21 @@ export default class SystemService {
) {} ) {}
public async getLogRemoveFrequency() { public async getLogRemoveFrequency() {
const doc = await AuthModel.findOne({ const doc = await this.getDb({ type: AuthDataType.removeLogFrequency });
where: { type: AuthDataType.removeLogFrequency },
});
return (doc && doc.info) || {}; return (doc && doc.info) || {};
} }
private async updateAuthDb(payload: AuthInfo): Promise<any> { private async updateAuthDb(payload: AuthInfo): Promise<any> {
await AuthModel.upsert({ ...payload }); await AuthModel.upsert({ ...payload });
const doc = await AuthModel.findOne({ where: { type: payload.type } }); const doc = await this.getDb({ type: payload.type });
return doc; return doc;
} }
public async getDb(query: any): Promise<any> {
const doc: any = await AuthModel.findOne({ where: { ...query } });
return doc && (doc.get({ plain: true }) as any);
}
public async updateNotificationMode(notificationInfo: NotificationInfo) { public async updateNotificationMode(notificationInfo: NotificationInfo) {
const code = Math.random().toString().slice(-6); const code = Math.random().toString().slice(-6);
const isSuccess = await this.notificationService.testNotify( const isSuccess = await this.notificationService.testNotify(

View File

@ -303,25 +303,26 @@ export default class UserService {
} }
public async getNotificationMode(): Promise<NotificationInfo> { public async getNotificationMode(): Promise<NotificationInfo> {
const doc = await AuthModel.findOne({ const doc = await this.getDb({ type: AuthDataType.notification });
where: { type: AuthDataType.notification },
});
return (doc && doc.info) || {}; return (doc && doc.info) || {};
} }
public async getLogRemoveFrequency() { public async getLogRemoveFrequency() {
const doc = await AuthModel.findOne({ const doc = await this.getDb({ type: AuthDataType.removeLogFrequency });
where: { type: AuthDataType.removeLogFrequency },
});
return (doc && doc.info) || {}; return (doc && doc.info) || {};
} }
private async updateAuthDb(payload: AuthInfo): Promise<any> { private async updateAuthDb(payload: AuthInfo): Promise<any> {
await AuthModel.upsert({ ...payload }); await AuthModel.upsert({ ...payload });
const doc = await AuthModel.findOne({ where: { type: payload.type } }); const doc = await this.getDb({ type: payload.type });
return doc; return doc;
} }
public async getDb(query: any): Promise<any> {
const doc: any = await AuthModel.findOne({ where: { ...query } });
return doc && (doc.get({ plain: true }) as any);
}
public async updateNotificationMode(notificationInfo: NotificationInfo) { public async updateNotificationMode(notificationInfo: NotificationInfo) {
const code = Math.random().toString().slice(-6); const code = Math.random().toString().slice(-6);
const isSuccess = await this.notificationService.testNotify( const isSuccess = await this.notificationService.testNotify(

View File

@ -38,7 +38,7 @@ const CronLogModal = ({
request request
.get(`${config.apiPrefix}crons/${cron.id}/log`) .get(`${config.apiPrefix}crons/${cron.id}/log`)
.then((data: any) => { .then((data: any) => {
if (localStorage.getItem('logCron') === cron.id) { if (localStorage.getItem('logCron') === String(cron.id)) {
const log = data.data as string; const log = data.data as string;
setValue(log || '暂无日志'); setValue(log || '暂无日志');
setExecuting( setExecuting(

View File

@ -20,9 +20,13 @@ const CronModal = ({
setLoading(true); setLoading(true);
const method = cron ? 'put' : 'post'; const method = cron ? 'put' : 'post';
const payload = { ...values }; const payload = { ...values };
if (typeof payload.labels === 'string') {
payload.labels = values.labels.split(/,|/);
}
if (cron) { if (cron) {
payload.id = cron.id; payload.id = cron.id;
} }
try {
const { code, data } = await request[method](`${config.apiPrefix}crons`, { const { code, data } = await request[method](`${config.apiPrefix}crons`, {
data: payload, data: payload,
}); });
@ -33,6 +37,9 @@ const CronModal = ({
} }
setLoading(false); setLoading(false);
handleCancel(data); handleCancel(data);
} catch (error: any) {
setLoading(false);
}
}; };
useEffect(() => { useEffect(() => {
@ -41,16 +48,13 @@ const CronModal = ({
return ( return (
<Modal <Modal
title={cron ? '编辑定时' : '新建定时'} title={cron ? '编辑任务' : '新建任务'}
visible={visible} visible={visible}
forceRender forceRender
onOk={() => { onOk={() => {
form form
.validateFields() .validateFields()
.then((values) => { .then((values) => {
if (typeof values.labels === "string") {
values.labels = values.labels.split(/,|/);
}
handleOk(values); handleOk(values);
}) })
.catch((info) => { .catch((info) => {
@ -69,9 +73,6 @@ const CronModal = ({
<Form.Item name="name" label="名称"> <Form.Item name="name" label="名称">
<Input placeholder="请输入任务名称" /> <Input placeholder="请输入任务名称" />
</Form.Item> </Form.Item>
<Form.Item name="labels" label="标签">
<Input placeholder="请输入任务标签" />
</Form.Item>
<Form.Item <Form.Item
name="command" name="command"
label="命令" label="命令"
@ -101,6 +102,9 @@ const CronModal = ({
> >
<Input placeholder="秒(可选) 分 时 天 月 周" /> <Input placeholder="秒(可选) 分 时 天 月 周" />
</Form.Item> </Form.Item>
<Form.Item name="labels" label="标签">
<Input placeholder="请输入任务标签" />
</Form.Item>
</Form> </Form>
</Modal> </Modal>
); );
@ -118,20 +122,25 @@ const CronLabelModal = ({
const [form] = Form.useForm(); const [form] = Form.useForm();
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const update = async (action: string) => { const update = async (action: 'delete' | 'post') => {
form form
.validateFields() .validateFields()
.then(async (values) => { .then(async (values) => {
if (typeof values.labels === "string") { if (typeof values.labels === 'string') {
values.labels = values.labels.split(/,|/); values.labels = values.labels.split(/,|/);
} }
setLoading(true); setLoading(true);
const payload = { ids, labels: values.labels }; const payload = { ids, labels: values.labels };
const { code, data } = await request.put(`${config.apiPrefix}crons/${action}`, { const { code, data } = await request[action](
`${config.apiPrefix}crons/labels`,
{
data: payload, data: payload,
}); },
);
if (code === 200) { if (code === 200) {
message.success(action === 'addLabels' ? '添加Labels成功' : '删除Labels成功'); message.success(
action === 'post' ? '添加Labels成功' : '删除Labels成功',
);
} else { } else {
message.error(data); message.error(data);
} }
@ -141,38 +150,32 @@ const CronLabelModal = ({
.catch((info) => { .catch((info) => {
console.log('Validate Failed:', info); console.log('Validate Failed:', info);
}); });
} };
useEffect(() => { useEffect(() => {
form.resetFields(); form.resetFields();
}, [ids, visible]); }, [ids, visible]);
const buttons = [ const buttons = [
<Button onClick={() => handleCancel(false)} key="test"> <Button onClick={() => handleCancel(false)}></Button>,
<Button type="primary" danger onClick={() => update('delete')}>
</Button>,
<Button type="primary" danger onClick={() => update('removeLabels')}>
</Button>, </Button>,
<Button type="primary" onClick={() => update('addLabels')}> <Button type="primary" onClick={() => update('post')}>
</Button> </Button>,
]; ];
return ( return (
<Modal <Modal
title='批量修改标签' title="批量修改标签"
visible={visible} visible={visible}
footer={buttons} footer={buttons}
forceRender forceRender
onCancel={() => handleCancel(false)} onCancel={() => handleCancel(false)}
confirmLoading={loading} confirmLoading={loading}
> >
<Form <Form form={form} layout="vertical" name="form_in_label_modal">
form={form}
layout="vertical"
name="form_in_label_modal"
>
<Form.Item name="labels" label="标签"> <Form.Item name="labels" label="标签">
<Input placeholder="请输入任务标签" /> <Input placeholder="请输入任务标签" />
</Form.Item> </Form.Item>
@ -181,4 +184,4 @@ const CronLabelModal = ({
); );
}; };
export { CronModal as default, CronLabelModal } export { CronModal as default, CronLabelModal };

View File

@ -90,11 +90,11 @@ const Dependence = ({ headerStyle, isPhone, socketMessage }: any) => {
}, },
{ {
title: '创建时间', title: '创建时间',
key: 'created', key: 'timestamp',
dataIndex: 'created', dataIndex: 'timestamp',
align: 'center' as const, align: 'center' as const,
render: (text: string, record: any) => { render: (text: string, record: any) => {
return <span>{new Date(record.created).toLocaleString()}</span>; return <span>{new Date(record.timestamp).toLocaleString()}</span>;
}, },
}, },
{ {

View File

@ -48,8 +48,8 @@ const DependenceLogModal = ({
request request
.get(`${config.apiPrefix}dependencies/${dependence.id}`) .get(`${config.apiPrefix}dependencies/${dependence.id}`)
.then((data: any) => { .then((data: any) => {
if (localStorage.getItem('logDependence') === dependence.id) { if (localStorage.getItem('logDependence') === String(dependence.id)) {
const log = (data.data.log || []).join('\n') as string; const log = (data.data.log || []).join('') as string;
setValue(log); setValue(log);
setExecuting(!log.includes('结束时间')); setExecuting(!log.includes('结束时间'));
setIsRemoveFailed(log.includes('删除失败')); setIsRemoveFailed(log.includes('删除失败'));
@ -99,7 +99,7 @@ const DependenceLogModal = ({
setExecuting(false); setExecuting(false);
setIsRemoveFailed(message.includes('删除失败')); setIsRemoveFailed(message.includes('删除失败'));
} }
setValue(`${value} \n ${message}`); setValue(`${value}${message}`);
}, [socketMessage]); }, [socketMessage]);
useEffect(() => { useEffect(() => {

View File

@ -26,7 +26,7 @@ const DependenceModal = ({
const handleOk = async (values: any) => { const handleOk = async (values: any) => {
setLoading(true); setLoading(true);
const { name, split, type } = values; const { name, split, type, remark } = values;
const method = dependence ? 'put' : 'post'; const method = dependence ? 'put' : 'post';
let payload; let payload;
if (!dependence) { if (!dependence) {
@ -36,10 +36,11 @@ const DependenceModal = ({
return { return {
name: x, name: x,
type, type,
remark,
}; };
}); });
} else { } else {
payload = [{ name, type }]; payload = [{ name, type, remark }];
} }
} else { } else {
payload = { ...values, id: dependence.id }; payload = { ...values, id: dependence.id };

View File

@ -125,7 +125,6 @@ const Script = ({ headerStyle, isPhone, theme, socketMessage }: any) => {
setExpandedKeys([p]); setExpandedKeys([p]);
onTreeSelect([vkey], obj); onTreeSelect([vkey], obj);
} }
history.push('/script');
}; };
const onSelect = (value: any, node: any) => { const onSelect = (value: any, node: any) => {

View File

@ -139,7 +139,7 @@ const CheckUpdate = ({ socketMessage }: any) => {
return; return;
} }
const newMessage = `${value}\n${_message}`; const newMessage = `${value}${_message}`;
modalRef.current.update({ modalRef.current.update({
content: ( content: (
<div style={{ height: '60vh', overflowY: 'auto' }}> <div style={{ height: '60vh', overflowY: 'auto' }}>

View File

@ -70,6 +70,8 @@ export default {
configs: '配置文件', configs: '配置文件',
scripts: '脚本管理', scripts: '脚本管理',
logs: '任务日志', logs: '任务日志',
dependencies: '依赖管理',
system: '系统信息',
}, },
notificationModes: [ notificationModes: [
{ value: 'gotify', label: 'Gotify' }, { value: 'gotify', label: 'Gotify' },