mirror of
https://github.com/whyour/qinglong.git
synced 2025-05-22 22:36:06 +08:00
任务视图增加状态筛选
This commit is contained in:
parent
2f05c95422
commit
9a3181bc44
|
@ -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 {
|
||||
|
|
|
@ -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}` : '';
|
||||
|
|
|
@ -369,6 +369,7 @@ const Crontab = ({ headerStyle, isPhone, theme }: any) => {
|
|||
const [isViewManageModalVisible, setIsViewManageModalVisible] =
|
||||
useState(false);
|
||||
const [cronViews, setCronViews] = useState<any[]>([]);
|
||||
const [enabledCronViews, setEnabledCronViews] = useState<any[]>([]);
|
||||
|
||||
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: <UnorderedListOutlined />,
|
||||
|
@ -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 (
|
||||
<PageContainer
|
||||
|
@ -1028,7 +1030,11 @@ const Crontab = ({ headerStyle, isPhone, theme }: any) => {
|
|||
tabPosition="top"
|
||||
className="crontab-view"
|
||||
tabBarExtraContent={
|
||||
<Dropdown overlay={menu} trigger={['click']} overlayStyle={{minWidth: 200}}>
|
||||
<Dropdown
|
||||
overlay={menu}
|
||||
trigger={['click']}
|
||||
overlayStyle={{ minWidth: 200 }}
|
||||
>
|
||||
<div className="view-more">
|
||||
<Space>
|
||||
更多
|
||||
|
@ -1043,7 +1049,7 @@ const Crontab = ({ headerStyle, isPhone, theme }: any) => {
|
|||
<Tabs.TabPane tab="全部任务" key="all">
|
||||
{panelContent}
|
||||
</Tabs.TabPane>
|
||||
{[...cronViews].slice(0, 2).map((x) => (
|
||||
{[...enabledCronViews].slice(0, 2).map((x) => (
|
||||
<Tabs.TabPane tab={x.name} key={x.id}>
|
||||
{panelContent}
|
||||
</Tabs.TabPane>
|
||||
|
@ -1083,9 +1089,12 @@ const Crontab = ({ headerStyle, isPhone, theme }: any) => {
|
|||
/>
|
||||
<ViewCreateModal
|
||||
visible={isCreateViewModalVisible}
|
||||
handleCancel={() => {
|
||||
getCronViews();
|
||||
handleCancel={(data) => {
|
||||
setIsCreateViewModalVisible(false);
|
||||
getCronViews();
|
||||
if (data && data.id === viewConf.id) {
|
||||
setViewConf({ ...viewConf, ...data });
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<ViewManageModal
|
||||
|
@ -1094,8 +1103,11 @@ const Crontab = ({ headerStyle, isPhone, theme }: any) => {
|
|||
handleCancel={() => {
|
||||
setIsViewManageModalVisible(false);
|
||||
}}
|
||||
cronViewChange={() => {
|
||||
cronViewChange={(data) => {
|
||||
getCronViews();
|
||||
if (data && data.id === viewConf.id) {
|
||||
setViewConf({ ...viewConf, ...data });
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</PageContainer>
|
||||
|
|
|
@ -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<any>();
|
||||
|
||||
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 = (
|
||||
<Select style={{ width: 80 }}>
|
||||
<Select
|
||||
style={{ width: 100 }}
|
||||
onChange={() => {
|
||||
setOperationMap({});
|
||||
}}
|
||||
>
|
||||
{OPERATIONS.map((x) => (
|
||||
<Select.Option key={x.name} value={x.value}>
|
||||
{x.name}
|
||||
|
@ -79,9 +97,31 @@ const ViewCreateModal = ({
|
|||
</Select>
|
||||
);
|
||||
|
||||
const propertyElement = (
|
||||
<Select style={{ width: 100 }}>
|
||||
{PROPERTIES.map((x) => (
|
||||
const propertyElement = (props: any) => {
|
||||
return (
|
||||
<Select style={{ width: 120 }}>
|
||||
{props.map((x) => (
|
||||
<Select.Option key={x.name} value={x.value}>
|
||||
{x.name}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
);
|
||||
};
|
||||
|
||||
const typeElement = (
|
||||
<Select style={{ width: 120 }}>
|
||||
{SORTTYPES.map((x) => (
|
||||
<Select.Option key={x.name} value={x.value}>
|
||||
{x.name}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
);
|
||||
|
||||
const statusElement = (
|
||||
<Select mode="multiple" allowClear placeholder="请选择状态">
|
||||
{STATUS.map((x) => (
|
||||
<Select.Option key={x.name} value={x.value}>
|
||||
{x.name}
|
||||
</Select.Option>
|
||||
|
@ -110,7 +150,7 @@ const ViewCreateModal = ({
|
|||
onCancel={() => handleCancel()}
|
||||
confirmLoading={loading}
|
||||
>
|
||||
<Form form={form} layout="vertical" name="env_modal" initialValues={view}>
|
||||
<Form form={form} layout="vertical" name="env_modal">
|
||||
<Form.Item
|
||||
name="name"
|
||||
label="视图名称"
|
||||
|
@ -134,7 +174,7 @@ const ViewCreateModal = ({
|
|||
name={[name, 'property']}
|
||||
rules={[{ required: true }]}
|
||||
>
|
||||
{propertyElement}
|
||||
{propertyElement(PROPERTIES)}
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
{...restField}
|
||||
|
@ -148,7 +188,13 @@ const ViewCreateModal = ({
|
|||
name={[name, 'value']}
|
||||
rules={[{ required: true, message: '请输入内容' }]}
|
||||
>
|
||||
<Input />
|
||||
{['In', 'Nin'].includes(
|
||||
form.getFieldValue(['filters', index, 'operation']),
|
||||
) ? (
|
||||
statusElement
|
||||
) : (
|
||||
<Input placeholder="请输入内容" />
|
||||
)}
|
||||
</Form.Item>
|
||||
{index !== 0 && (
|
||||
<MinusCircleOutlined onClick={() => remove(name)} />
|
||||
|
@ -159,9 +205,7 @@ const ViewCreateModal = ({
|
|||
<Form.Item>
|
||||
<a
|
||||
href="#"
|
||||
onClick={() =>
|
||||
add({ property: 'command', operation: 'Reg' })
|
||||
}
|
||||
onClick={() => add({ property: 'command', operation: 'Reg' })}
|
||||
>
|
||||
<PlusOutlined />
|
||||
新增筛选条件
|
||||
|
@ -170,6 +214,49 @@ const ViewCreateModal = ({
|
|||
</>
|
||||
)}
|
||||
</Form.List>
|
||||
<Form.List name="sorts">
|
||||
{(fields, { add, remove }) => (
|
||||
<>
|
||||
{fields.map(({ key, name, ...restField }, index) => (
|
||||
<Form.Item
|
||||
label={index === 0 ? '排序方式' : ''}
|
||||
required={true}
|
||||
key={key}
|
||||
style={{ marginBottom: 0 }}
|
||||
>
|
||||
<Space className="view-create-modal-filters" align="baseline">
|
||||
<Form.Item
|
||||
{...restField}
|
||||
name={[name, 'property']}
|
||||
rules={[{ required: true }]}
|
||||
>
|
||||
{propertyElement(PROPERTIES)}
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
{...restField}
|
||||
name={[name, 'type']}
|
||||
rules={[{ required: true }]}
|
||||
>
|
||||
{typeElement}
|
||||
</Form.Item>
|
||||
{index !== 0 && (
|
||||
<MinusCircleOutlined onClick={() => remove(name)} />
|
||||
)}
|
||||
</Space>
|
||||
</Form.Item>
|
||||
))}
|
||||
<Form.Item>
|
||||
<a
|
||||
href="#"
|
||||
onClick={() => add({ property: 'command', operation: 'ASC' })}
|
||||
>
|
||||
<PlusOutlined />
|
||||
新增排序方式
|
||||
</a>
|
||||
</Form.Item>
|
||||
</>
|
||||
)}
|
||||
</Form.List>
|
||||
</Form>
|
||||
</Modal>
|
||||
);
|
||||
|
|
|
@ -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 <Space size="middle" style={{ cursor: 'text' }}></Space>;
|
||||
// },
|
||||
// },
|
||||
{
|
||||
title: '显示',
|
||||
key: 'isDisabled',
|
||||
dataIndex: 'isDisabled',
|
||||
align: 'center' as const,
|
||||
width: 100,
|
||||
render: (text: string, record: any, index: number) => {
|
||||
return (
|
||||
<Switch
|
||||
checked={!record.isDisabled}
|
||||
onChange={(checked) => 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<any[]>([]);
|
||||
const [isCreateViewModalVisible, setIsCreateViewModalVisible] =
|
||||
useState<boolean>(false);
|
||||
const [editedView, setEditedView] = useState<any>(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}
|
||||
>
|
||||
<Space style={{ display: 'flex', justifyContent: 'flex-end', marginBottom: 10 }}>
|
||||
<Space
|
||||
style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'flex-end',
|
||||
marginBottom: 10,
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
key="2"
|
||||
type="primary"
|
||||
|
@ -216,9 +254,10 @@ const ViewManageModal = ({
|
|||
/>
|
||||
</DndProvider>
|
||||
<ViewCreateModal
|
||||
view={editedView}
|
||||
visible={isCreateViewModalVisible}
|
||||
handleCancel={() => {
|
||||
cronViewChange();
|
||||
handleCancel={(data) => {
|
||||
cronViewChange(data);
|
||||
setIsCreateViewModalVisible(false);
|
||||
}}
|
||||
/>
|
||||
|
|
Loading…
Reference in New Issue
Block a user