mirror of
https://github.com/whyour/qinglong.git
synced 2025-05-23 23:06:06 +08:00
修改定时任务添加标签交互
This commit is contained in:
parent
5dbfc65e7f
commit
22d097aa08
|
@ -53,7 +53,7 @@
|
|||
"sequelize": "^6.17.0",
|
||||
"serve-handler": "^6.1.3",
|
||||
"sockjs": "^0.3.24",
|
||||
"sqlite3": "npm:@louislam/sqlite3@^6.0.1",
|
||||
"sqlite3": "npm:@louislam/sqlite3@^15.0.3",
|
||||
"toad-scheduler": "^1.6.0",
|
||||
"typedi": "^0.10.0",
|
||||
"uuid": "^8.3.2",
|
||||
|
|
110
src/components/tag.tsx
Normal file
110
src/components/tag.tsx
Normal file
|
@ -0,0 +1,110 @@
|
|||
import { Tag, Input } from 'antd';
|
||||
import { TweenOneGroup } from 'rc-tween-one';
|
||||
import { PlusOutlined } from '@ant-design/icons';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
|
||||
const EditableTagGroup = ({
|
||||
value,
|
||||
onChange,
|
||||
}: {
|
||||
value?: string[];
|
||||
onChange?: (tags: string[]) => void;
|
||||
}) => {
|
||||
const [inputValue, setInputValue] = useState('');
|
||||
const [inputVisible, setInputVisible] = useState(false);
|
||||
const [tags, setTags] = useState<string[]>([]);
|
||||
const saveInputRef = useRef<any>();
|
||||
|
||||
const handleClose = (removedTag: string) => {
|
||||
const _tags = tags.filter((tag) => tag !== removedTag);
|
||||
setTags(_tags);
|
||||
onChange?.(_tags);
|
||||
};
|
||||
|
||||
const showInput = () => {
|
||||
setInputVisible(true);
|
||||
};
|
||||
|
||||
const handleInputChange = (e) => {
|
||||
setInputValue(e.target.value);
|
||||
};
|
||||
|
||||
const handleInputConfirm = () => {
|
||||
if (inputValue && !tags.includes(inputValue)) {
|
||||
setTags([...tags, inputValue]);
|
||||
onChange?.([...tags, inputValue]);
|
||||
}
|
||||
setInputVisible(false);
|
||||
setInputValue('');
|
||||
};
|
||||
|
||||
const tagChild = tags.map((tag) => {
|
||||
const tagElem = (
|
||||
<Tag
|
||||
closable
|
||||
onClose={(e) => {
|
||||
e.preventDefault();
|
||||
handleClose(tag);
|
||||
}}
|
||||
>
|
||||
{tag}
|
||||
</Tag>
|
||||
);
|
||||
return (
|
||||
<span key={tag} style={{ display: 'inline-block', marginBottom: 8 }}>
|
||||
{tagElem}
|
||||
</span>
|
||||
);
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (inputVisible && saveInputRef) {
|
||||
saveInputRef.current.focus();
|
||||
}
|
||||
}, [inputVisible]);
|
||||
|
||||
useEffect(() => {
|
||||
if (value) {
|
||||
setTags(value);
|
||||
}
|
||||
}, [value]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<TweenOneGroup
|
||||
enter={{
|
||||
scale: 0.8,
|
||||
opacity: 0,
|
||||
type: 'from',
|
||||
duration: 100,
|
||||
}}
|
||||
leave={{ opacity: 0, width: 0, scale: 0, duration: 200 }}
|
||||
appear={false}
|
||||
>
|
||||
{tagChild}
|
||||
</TweenOneGroup>
|
||||
{inputVisible && (
|
||||
<Input
|
||||
ref={saveInputRef}
|
||||
type="text"
|
||||
size="small"
|
||||
style={{ width: 78 }}
|
||||
value={inputValue}
|
||||
onChange={handleInputChange}
|
||||
onBlur={handleInputConfirm}
|
||||
onPressEnter={handleInputConfirm}
|
||||
/>
|
||||
)}
|
||||
{!inputVisible && (
|
||||
<Tag
|
||||
onClick={showInput}
|
||||
style={{ borderStyle: 'dashed', cursor: 'pointer' }}
|
||||
>
|
||||
<PlusOutlined /> 新建
|
||||
</Tag>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default EditableTagGroup;
|
|
@ -3,6 +3,7 @@ import { Modal, message, Input, Form, Button } from 'antd';
|
|||
import { request } from '@/utils/http';
|
||||
import config from '@/utils/config';
|
||||
import cronParse from 'cron-parser';
|
||||
import EditableTagGroup from '@/components/tag';
|
||||
|
||||
const CronModal = ({
|
||||
cron,
|
||||
|
@ -20,11 +21,6 @@ const CronModal = ({
|
|||
setLoading(true);
|
||||
const method = cron ? 'put' : 'post';
|
||||
const payload = { ...values };
|
||||
if (typeof payload.labels === 'string') {
|
||||
payload.labels = values.labels.split(/,|,/);
|
||||
} else if (!payload.labels) {
|
||||
payload.labels = [];
|
||||
}
|
||||
if (cron) {
|
||||
payload.id = cron.id;
|
||||
}
|
||||
|
@ -93,7 +89,7 @@ const CronModal = ({
|
|||
{ required: true },
|
||||
{
|
||||
validator: (rule, value) => {
|
||||
if (cronParse.parseExpression(value).hasNext()) {
|
||||
if (!value || cronParse.parseExpression(value).hasNext()) {
|
||||
return Promise.resolve();
|
||||
} else {
|
||||
return Promise.reject('Cron表达式格式有误');
|
||||
|
@ -105,7 +101,7 @@ const CronModal = ({
|
|||
<Input placeholder="秒(可选) 分 时 天 月 周" />
|
||||
</Form.Item>
|
||||
<Form.Item name="labels" label="标签">
|
||||
<Input placeholder="请输入任务标签" />
|
||||
<EditableTagGroup />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
|
@ -128,9 +124,6 @@ const CronLabelModal = ({
|
|||
form
|
||||
.validateFields()
|
||||
.then(async (values) => {
|
||||
if (typeof values.labels === 'string') {
|
||||
values.labels = values.labels.split(/,|,/);
|
||||
}
|
||||
setLoading(true);
|
||||
const payload = { ids, labels: values.labels };
|
||||
const { code, data } = await request[action](
|
||||
|
@ -179,7 +172,7 @@ const CronLabelModal = ({
|
|||
>
|
||||
<Form form={form} layout="vertical" name="form_in_label_modal">
|
||||
<Form.Item name="labels" label="标签">
|
||||
<Input placeholder="请输入任务标签" />
|
||||
<EditableTagGroup />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
|
|
Loading…
Reference in New Issue
Block a user