feat: add environment variable labels

This commit is contained in:
whyour
2026-05-23 23:21:38 +08:00
parent 7a8917f8e4
commit 8bc0906949
10 changed files with 792 additions and 9 deletions
+1 -3
View File
@@ -66,9 +66,7 @@ const EditableTagGroup = ({
}, [inputVisible]);
useEffect(() => {
if (value) {
setTags(value);
}
setTags(value || []);
}, [value]);
return (
+3
View File
@@ -437,6 +437,9 @@
"Cron表达式格式有误": "Incorrect Cron Expression Format",
"添加Labels成功": "Labels added successfully",
"删除Labels成功": "Labels deleted successfully",
"添加标签成功": "Tags added successfully",
"删除标签成功": "Tags deleted successfully",
"请至少输入一个标签": "Please enter at least one tag",
"编辑视图": "Edit View",
"排序方式": "Sort Order",
"开始时间": "Start Time",
+3
View File
@@ -437,6 +437,9 @@
"Cron表达式格式有误": "Cron表达式格式有误",
"添加Labels成功": "添加Labels成功",
"删除Labels成功": "删除Labels成功",
"添加标签成功": "添加标签成功",
"删除标签成功": "删除标签成功",
"请至少输入一个标签": "请至少输入一个标签",
"编辑视图": "编辑视图",
"排序方式": "排序方式",
"开始时间": "开始时间",
+51 -2
View File
@@ -36,7 +36,7 @@ import { useVT } from 'virtualizedtableforantd4';
import Copy from '../../components/copy';
import EditNameModal from './editNameModal';
import './index.less';
import EnvModal from './modal';
import EnvModal, { EnvLabelModal } from './modal';
const { Paragraph } = Typography;
const { Search } = Input;
@@ -121,6 +121,25 @@ const Env = () => {
);
},
},
{
title: intl.get('标签'),
dataIndex: 'labels',
key: 'labels',
render: (labels: string[] | null) => {
const envLabels = Array.isArray(labels) ? labels : [];
return (
<Space size={[0, 4]} wrap>
{envLabels
.filter((label) => label)
.map((label) => (
<Tag key={label} color="blue">
{label}
</Tag>
))}
</Space>
);
},
},
{
title: intl.get('更新时间'),
dataIndex: 'timestamp',
@@ -238,6 +257,7 @@ const Env = () => {
const [loading, setLoading] = useState(true);
const [isModalVisible, setIsModalVisible] = useState(false);
const [isEditNameModalVisible, setIsEditNameModalVisible] = useState(false);
const [isLabelModalVisible, setIsLabelModalVisible] = useState(false);
const [editedEnv, setEditedEnv] = useState();
const [selectedRowIds, setSelectedRowIds] = useState<string[]>([]);
const [searchText, setSearchText] = useState('');
@@ -408,6 +428,13 @@ const Env = () => {
getEnvs();
};
const handleLabelCancel = (needUpdate?: boolean) => {
setIsLabelModalVisible(false);
if (needUpdate) {
getEnvs();
}
};
const [vt, setVT] = useVT(
() => ({ scroll: { y: tableScrollHeight } }),
[tableScrollHeight],
@@ -542,7 +569,12 @@ const Env = () => {
const exportEnvs = () => {
const envs = value
.filter((x) => selectedRowIds.includes(x.id))
.map((x) => ({ value: x.value, name: x.name, remarks: x.remarks }));
.map((x) => ({
value: x.value,
name: x.name,
remarks: x.remarks,
labels: x.labels,
}));
exportJson('env.json', JSON.stringify(envs));
};
@@ -550,6 +582,10 @@ const Env = () => {
setIsEditNameModalVisible(true);
};
const modifyLabels = () => {
setIsLabelModalVisible(true);
};
const onSearch = (value: string) => {
setSearchText(value.trim());
};
@@ -622,6 +658,13 @@ const Env = () => {
>
{intl.get('批量修改变量名称')}
</Button>
<Button
type="primary"
style={{ marginBottom: 5, marginLeft: 8 }}
onClick={modifyLabels}
>
{intl.get('批量修改标签')}
</Button>
<Button
type="primary"
style={{ marginBottom: 5, marginLeft: 8 }}
@@ -700,6 +743,12 @@ const Env = () => {
ids={selectedRowIds}
/>
)}
{isLabelModalVisible && (
<EnvLabelModal
handleCancel={handleLabelCancel}
ids={selectedRowIds}
/>
)}
</PageContainer>
);
};
+97 -4
View File
@@ -1,8 +1,9 @@
import intl from 'react-intl-universal';
import React, { useEffect, useState } from 'react';
import { Modal, message, Input, Form, Radio } from 'antd';
import { Modal, message, Input, Form, Radio, Button } from 'antd';
import { request } from '@/utils/http';
import config from '@/utils/config';
import EditableTagGroup from '@/components/tag';
const EnvModal = ({
env,
@@ -16,7 +17,7 @@ const EnvModal = ({
const handleOk = async (values: any) => {
setLoading(true);
const { value, split, name, remarks } = values;
const { value, split, name, remarks, labels } = values;
const method = env ? 'put' : 'post';
let payload;
if (!env) {
@@ -27,10 +28,11 @@ const EnvModal = ({
name: name,
value: x,
remarks: remarks,
labels: labels || [],
};
});
} else {
payload = [{ value, name, remarks }];
payload = [{ value, name, remarks, labels: labels || [] }];
}
} else {
payload = { ...values, id: env.id };
@@ -123,9 +125,100 @@ const EnvModal = ({
<Form.Item name="remarks" label={intl.get('备注')}>
<Input placeholder={intl.get('请输入备注')} />
</Form.Item>
<Form.Item name="labels" label={intl.get('标签')}>
<EditableTagGroup />
</Form.Item>
</Form>
</Modal>
);
};
export default EnvModal;
export { EnvModal as default };
export const EnvLabelModal = ({
ids,
handleCancel,
}: {
ids: string[];
handleCancel: (needUpdate?: boolean) => void;
}) => {
const [form] = Form.useForm();
const [loading, setLoading] = useState(false);
const update = async (action: 'add' | 'delete') => {
try {
const values = await form.validateFields();
const payload = { ids, labels: values.labels };
setLoading(true);
const { code } =
action === 'add'
? await request.post(`${config.apiPrefix}envs/labels`, payload)
: await request.delete(`${config.apiPrefix}envs/labels`, {
data: payload,
});
if (code === 200) {
message.success(
action === 'add'
? intl.get('添加标签成功')
: intl.get('删除标签成功'),
);
handleCancel(true);
}
} catch (error: any) {
if (error?.errorFields) {
return;
}
} finally {
setLoading(false);
}
};
return (
<Modal
title={intl.get('批量修改标签')}
open={true}
footer={[
<Button key="cancel" onClick={() => handleCancel(false)}>
{intl.get('取消')}
</Button>,
<Button
key="delete"
type="primary"
danger
loading={loading}
onClick={() => update('delete')}
>
{intl.get('删除')}
</Button>,
<Button
key="add"
type="primary"
loading={loading}
onClick={() => update('add')}
>
{intl.get('添加')}
</Button>,
]}
centered
maskClosable={false}
forceRender
onCancel={() => handleCancel(false)}
>
<Form form={form} layout="vertical" name="env_label_modal">
<Form.Item
name="labels"
label={intl.get('标签')}
rules={[
{
required: true,
message: intl.get('请至少输入一个标签'),
},
]}
>
<EditableTagGroup />
</Form.Item>
</Form>
</Modal>
);
};