diff --git a/back/api/cron.ts b/back/api/cron.ts index 562a4275..7b69b005 100644 --- a/back/api/cron.ts +++ b/back/api/cron.ts @@ -100,6 +100,40 @@ export default (app: Router) => { }, ); + route.put( + '/views/disable', + celebrate({ + body: Joi.array().items(Joi.number().required()), + }), + async (req: Request, res: Response, next: NextFunction) => { + const logger: Logger = Container.get('logger'); + try { + const cronViewService = Container.get(CronViewService); + const data = await cronViewService.disabled(req.body); + return res.send({ code: 200, data }); + } catch (e) { + return next(e); + } + }, + ); + + route.put( + '/views/enable', + celebrate({ + body: Joi.array().items(Joi.number().required()), + }), + async (req: Request, res: Response, next: NextFunction) => { + const logger: Logger = Container.get('logger'); + try { + const cronViewService = Container.get(CronViewService); + const data = await cronViewService.enabled(req.body); + return res.send({ code: 200, data }); + } catch (e) { + return next(e); + } + }, + ); + route.get('/', async (req: Request, res: Response, next: NextFunction) => { const logger: Logger = Container.get('logger'); try { diff --git a/back/services/cron.ts b/back/services/cron.ts index 10abb155..1e2eeb27 100644 --- a/back/services/cron.ts +++ b/back/services/cron.ts @@ -14,7 +14,7 @@ import dayjs from 'dayjs'; @Service() export default class CronService { - constructor(@Inject('logger') private logger: winston.Logger) { } + constructor(@Inject('logger') private logger: winston.Logger) {} private isSixCron(cron: Crontab) { const { schedule } = cron; @@ -122,9 +122,31 @@ export default class CronService { case 'Reg': operate = Op.like; break; - case 'Reg': + case 'NotReg': operate = Op.notLike; break; + case 'In': + query[Op.or] = [ + { + [property]: value, + }, + property === 'status' && value.includes(2) + ? { isDisabled: 1 } + : {}, + ]; + break; + case 'Nin': + query[Op.and] = [ + { + [property]: { + [Op.notIn]: value, + }, + }, + property === 'status' && value.includes(2) + ? { isDisabled: { [Op.ne]: 1 } } + : {}, + ]; + break; default: break; } @@ -134,13 +156,13 @@ export default class CronService { { [operate]: `%${value}%` }, { [operate]: `%${encodeURIComponent(value)}%` }, ], - } + }; } } } } - private formatSearchText(query: any, searchText: string | undefined) { + private formatSearchText(query: any, searchText: string | undefined) { if (searchText) { const textArray = searchText.split(':'); switch (textArray[0]) { @@ -216,7 +238,7 @@ export default class CronService { ['status', 'ASC'], ['createdAt', 'DESC'], ]; - + this.formatViewQuery(query, viewQuery); this.formatSearchText(query, searchText); this.formatViewSort(order, viewQuery); @@ -274,9 +296,9 @@ export default class CronService { const endTime = dayjs(); const diffTimeStr = doc.last_execution_time ? `,耗时 ${endTime.diff( - dayjs(doc.last_execution_time * 1000), - 'second', - )}` + dayjs(doc.last_execution_time * 1000), + 'second', + )}` : ''; if (logFileExist) { const str = err ? `\n${err}` : ''; diff --git a/src/pages/crontab/index.tsx b/src/pages/crontab/index.tsx index a934aecc..179823ae 100644 --- a/src/pages/crontab/index.tsx +++ b/src/pages/crontab/index.tsx @@ -369,6 +369,7 @@ const Crontab = ({ headerStyle, isPhone, theme }: any) => { const [isViewManageModalVisible, setIsViewManageModalVisible] = useState(false); const [cronViews, setCronViews] = useState([]); + const [enabledCronViews, setEnabledCronViews] = useState([]); const goToScriptManager = (record: any) => { const cmd = record.command.split(' ') as string[]; @@ -960,7 +961,7 @@ const Crontab = ({ headerStyle, isPhone, theme }: any) => { viewAction(key); }} items={[ - ...[...cronViews].slice(2).map((x) => ({ + ...[...enabledCronViews].slice(2).map((x) => ({ label: x.name, key: x.id, icon: , @@ -988,6 +989,7 @@ const Crontab = ({ headerStyle, isPhone, theme }: any) => { .get(`${config.apiPrefix}crons/views`) .then((data: any) => { setCronViews(data.data); + setEnabledCronViews(data.data.filter((x) => !x.isDisabled)); }) .finally(() => { setLoading(false); @@ -995,9 +997,9 @@ const Crontab = ({ headerStyle, isPhone, theme }: any) => { }; const tabClick = (key: string) => { - const view = cronViews.find(x => x.id == key); + const view = enabledCronViews.find((x) => x.id == key); setViewConf(view ? view : null); - } + }; return ( { tabPosition="top" className="crontab-view" tabBarExtraContent={ - +
更多 @@ -1043,7 +1049,7 @@ const Crontab = ({ headerStyle, isPhone, theme }: any) => { {panelContent} - {[...cronViews].slice(0, 2).map((x) => ( + {[...enabledCronViews].slice(0, 2).map((x) => ( {panelContent} @@ -1083,9 +1089,12 @@ const Crontab = ({ headerStyle, isPhone, theme }: any) => { /> { - getCronViews(); + handleCancel={(data) => { setIsCreateViewModalVisible(false); + getCronViews(); + if (data && data.id === viewConf.id) { + setViewConf({ ...viewConf, ...data }); + } }} /> { handleCancel={() => { setIsViewManageModalVisible(false); }} - cronViewChange={() => { + cronViewChange={(data) => { getCronViews(); + if (data && data.id === viewConf.id) { + setViewConf({ ...viewConf, ...data }); + } }} /> diff --git a/src/pages/crontab/viewCreateModal.tsx b/src/pages/crontab/viewCreateModal.tsx index c43e38e8..77294ddf 100644 --- a/src/pages/crontab/viewCreateModal.tsx +++ b/src/pages/crontab/viewCreateModal.tsx @@ -17,19 +17,31 @@ const PROPERTIES = [ { name: '命令', value: 'command' }, { name: '名称', value: 'name' }, { name: '定时规则', value: 'schedule' }, + { name: '状态', value: 'status' }, ]; const OPERATIONS = [ { name: '包含', value: 'Reg' }, { name: '不包含', value: 'NotReg' }, - // { name: '属于', value: 'In' }, - // { name: '不属于', value: 'Nin' }, + { name: '属于', value: 'In' }, + { name: '不属于', value: 'Nin' }, // { name: '等于', value: 'Eq' }, // { name: '不等于', value: 'Ne' }, // { name: '为空', value: 'IsNull' }, // { name: '不为空', value: 'NotNull' }, ]; +const SORTTYPES = [ + { name: '顺序', value: 'ASC' }, + { name: '倒序', value: 'DESC' }, +]; + +const STATUS = [ + { name: '运行中', value: 0 }, + { name: '空闲中', value: 1 }, + { name: '已禁用', value: 2 }, +]; + const ViewCreateModal = ({ view, handleCancel, @@ -37,10 +49,11 @@ const ViewCreateModal = ({ }: { view?: any; visible: boolean; - handleCancel: (param?: string) => void; + handleCancel: (param?: any) => void; }) => { const [form] = Form.useForm(); const [loading, setLoading] = useState(false); + const [operationMap, setOperationMap] = useState(); const handleOk = async (values: any) => { setLoading(true); @@ -49,7 +62,7 @@ const ViewCreateModal = ({ const { code, data } = await request[method]( `${config.apiPrefix}crons/views`, { - data: values, + data: view ? { ...values, id: view.id } : values, }, ); if (code !== 200) { @@ -63,14 +76,19 @@ const ViewCreateModal = ({ }; useEffect(() => { - form.resetFields(); - form.setFieldsValue({ - filters: [{ property: 'command', operation: 'Reg' }], - }); + form.setFieldsValue(view || {}); + if (!view) { + form.resetFields(); + } }, [view, visible]); const operationElement = ( - { + setOperationMap({}); + }} + > {OPERATIONS.map((x) => ( {x.name} @@ -79,9 +97,31 @@ const ViewCreateModal = ({ ); - const propertyElement = ( - + {props.map((x) => ( + + {x.name} + + ))} + + ); + }; + + const typeElement = ( + + ); + + const statusElement = ( + + {['In', 'Nin'].includes( + form.getFieldValue(['filters', index, 'operation']), + ) ? ( + statusElement + ) : ( + + )} {index !== 0 && ( remove(name)} /> @@ -159,9 +205,7 @@ const ViewCreateModal = ({ - add({ property: 'command', operation: 'Reg' }) - } + onClick={() => add({ property: 'command', operation: 'Reg' })} > 新增筛选条件 @@ -170,6 +214,49 @@ const ViewCreateModal = ({ )} + + {(fields, { add, remove }) => ( + <> + {fields.map(({ key, name, ...restField }, index) => ( + + + + {propertyElement(PROPERTIES)} + + + {typeElement} + + {index !== 0 && ( + remove(name)} /> + )} + + + ))} + + add({ property: 'command', operation: 'ASC' })} + > + + 新增排序方式 + + + + )} + ); diff --git a/src/pages/crontab/viewManageModal.tsx b/src/pages/crontab/viewManageModal.tsx index 33d7fad4..a0f9b61e 100644 --- a/src/pages/crontab/viewManageModal.tsx +++ b/src/pages/crontab/viewManageModal.tsx @@ -1,5 +1,14 @@ import React, { useCallback, useEffect, useRef, useState } from 'react'; -import { Modal, message, Space, Table, Tag, Typography, Button } from 'antd'; +import { + Modal, + message, + Space, + Table, + Tag, + Typography, + Button, + Switch, +} from 'antd'; import { request } from '@/utils/http'; import config from '@/utils/config'; import { DeleteOutlined, EditOutlined } from '@ant-design/icons'; @@ -59,12 +68,12 @@ const ViewManageModal = ({ cronViews, handleCancel, visible, - cronViewChange + cronViewChange, }: { cronViews: any[]; visible: boolean; handleCancel: () => void; - cronViewChange: () => void; + cronViewChange: (data?: any) => void; }) => { const columns: any = [ { @@ -72,22 +81,26 @@ const ViewManageModal = ({ dataIndex: 'name', key: 'name', align: 'center' as const, - width: 70, }, - // { - // title: '显示', - // key: 'isDisabled', - // dataIndex: 'isDisabled', - // align: 'center' as const, - // width: 70, - // render: (text: string, record: any, index: number) => { - // return ; - // }, - // }, + { + title: '显示', + key: 'isDisabled', + dataIndex: 'isDisabled', + align: 'center' as const, + width: 100, + render: (text: string, record: any, index: number) => { + return ( + onShowChange(checked, record, index)} + /> + ); + }, + }, { title: '操作', key: 'action', - width: 120, + width: 140, align: 'center' as const, render: (text: string, record: any, index: number) => { return ( @@ -106,10 +119,11 @@ const ViewManageModal = ({ const [list, setList] = useState([]); const [isCreateViewModalVisible, setIsCreateViewModalVisible] = useState(false); + const [editedView, setEditedView] = useState(null); const editView = (record: any, index: number) => { - // setEditedEnv(record); - // setIsModalVisible(true); + setEditedView(record); + setIsCreateViewModalVisible(true); }; const deleteView = (record: any, index: number) => { @@ -142,6 +156,24 @@ const ViewManageModal = ({ }); }; + const onShowChange = (checked: boolean, record: any, index: number) => { + console.log(checked); + request + .put(`${config.apiPrefix}crons/views/${checked ? 'enable' : 'disable'}`, { + data: [record.id], + }) + .then((data: any) => { + if (data.code === 200) { + const _list = [...list]; + _list.splice(index, 1, { ...list[index], isDisabled: !checked }); + setList(_list); + cronViewChange(); + } else { + message.error(data); + } + }); + }; + const components = { body: { row: DragableBodyRow, @@ -188,7 +220,13 @@ const ViewManageModal = ({ footer={false} maskClosable={false} > - +