mirror of
https://github.com/Jerryplusy/AI-powered-switches.git
synced 2025-10-14 09:49:19 +00:00
修配置页面
This commit is contained in:
parent
a57e4d4b46
commit
c0bb0e6a29
@ -8,10 +8,12 @@ import {
|
||||
HStack,
|
||||
Portal,
|
||||
Select,
|
||||
Spinner,
|
||||
Text,
|
||||
Textarea,
|
||||
VStack,
|
||||
} from '@chakra-ui/react';
|
||||
|
||||
import DocumentTitle from '@/components/system/pages/DocumentTitle';
|
||||
import PageContainer from '@/components/system/PageContainer';
|
||||
import DashboardBackground from '@/components/system/pages/DashboardBackground';
|
||||
@ -32,6 +34,10 @@ const ConfigPage = () => {
|
||||
const [editableConfig, setEditableConfig] = useState('');
|
||||
const [applying, setApplying] = useState(false);
|
||||
const [hasParsed, setHasParsed] = useState(false);
|
||||
const [conmmand, setConmmand] = useState([]);
|
||||
const [isPeizhi, setisPeizhi] = useState(false);
|
||||
const [isApplying, setIsApplying] = useState(false);
|
||||
const [applyStatus, setApplyStatus] = useState([]);
|
||||
|
||||
const deviceCollection = createListCollection({
|
||||
items: devices.map((device) => ({
|
||||
@ -55,6 +61,13 @@ const ConfigPage = () => {
|
||||
}
|
||||
|
||||
try {
|
||||
/**
|
||||
const response = await api.parseCommand(inputText);
|
||||
if (response) {
|
||||
setParsedConfig(response);
|
||||
setEditableConfig(response);
|
||||
setHasParsed(true);
|
||||
}**/
|
||||
const performParse = async () => {
|
||||
if (testMode) {
|
||||
await Common.sleep(800 + Math.random() * 700);
|
||||
@ -79,12 +92,16 @@ const ConfigPage = () => {
|
||||
},
|
||||
});
|
||||
|
||||
const result = await resultWrapper.unwrap();
|
||||
|
||||
if (result?.config) {
|
||||
setParsedConfig(result.config);
|
||||
setEditableConfig(result.config);
|
||||
let result = await resultWrapper.unwrap();
|
||||
if (result?.data) {
|
||||
setParsedConfig(JSON.stringify(result.data));
|
||||
setEditableConfig(JSON.stringify(result.data));
|
||||
setHasParsed(true);
|
||||
result = result.data;
|
||||
if (result.config && Array.isArray(result.config.commands)) {
|
||||
setConmmand(result.config.commands);
|
||||
}
|
||||
setisPeizhi(true);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('配置解析异常:', error);
|
||||
@ -95,6 +112,37 @@ const ConfigPage = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const applyCommand = async (switch_ip, command, index) => {
|
||||
try {
|
||||
setApplyStatus((prevStatus) => {
|
||||
const updated = [...prevStatus];
|
||||
updated[index] = 'in-progress';
|
||||
return updated;
|
||||
});
|
||||
|
||||
const applyResult = testMode
|
||||
? await Common.sleep(1000)
|
||||
: await api.applyConfig(switch_ip, [command]);
|
||||
|
||||
if (applyResult?.data?.success) {
|
||||
setApplyStatus((prevStatus) => {
|
||||
const updated = [...prevStatus];
|
||||
updated[index] = 'success';
|
||||
return updated;
|
||||
});
|
||||
} else {
|
||||
Notification.error({ title: '命令应用失败', description: '请检查命令是否合法' });
|
||||
}
|
||||
} catch (error) {
|
||||
setApplyStatus((prevStatus) => {
|
||||
const updated = [...prevStatus];
|
||||
updated[index] = 'failed';
|
||||
return updated;
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
const handleApply = async () => {
|
||||
if (!editableConfig) {
|
||||
Notification.warn({
|
||||
@ -108,7 +156,7 @@ const ConfigPage = () => {
|
||||
try {
|
||||
const applyOperation = testMode
|
||||
? Common.sleep(1000).then(() => ({ success: true }))
|
||||
: await api.applyConfig(selectedDevice, editableConfig);
|
||||
: await api.applyConfig(selectedDevice, conmmand);
|
||||
|
||||
await Notification.promise({
|
||||
promise: applyOperation,
|
||||
@ -250,6 +298,143 @@ const ConfigPage = () => {
|
||||
</Box>
|
||||
</FadeInWrapper>
|
||||
)}
|
||||
{isPeizhi && parsedConfig && (
|
||||
<FadeInWrapper delay={0.2}>
|
||||
<VStack spacing={4} align={'stretch'}>
|
||||
{(() => {
|
||||
let parsed;
|
||||
try {
|
||||
parsed = JSON.parse(editableConfig);
|
||||
} catch (e) {
|
||||
return <Text color={'red.300'}>配置 JSON 格式错误,无法解析。</Text>;
|
||||
}
|
||||
|
||||
const config = parsed.config ? [parsed.config] : parsed;
|
||||
return config.map((cfg, idx) => (
|
||||
<Box
|
||||
key={idx}
|
||||
p={4}
|
||||
bg={'whiteAlpha.100'}
|
||||
borderRadius={'xl'}
|
||||
border={'1px solid'}
|
||||
borderColor={'whiteAlpha.300'}
|
||||
>
|
||||
<Text fontSize="lg" fontWeight="bold" mb={2}>
|
||||
配置类型: {cfg.type}
|
||||
</Text>
|
||||
|
||||
{Object.entries(cfg).map(([key, value]) => {
|
||||
if (key === 'type' || key === 'commands') return null;
|
||||
return (
|
||||
<Field.Root
|
||||
key={key}
|
||||
colorPalette={'teal'}
|
||||
orientation={'vertical'}
|
||||
mb={3}
|
||||
>
|
||||
<Field.Label fontSize={'sm'}>{key}</Field.Label>
|
||||
<Textarea
|
||||
size={'sm'}
|
||||
value={value}
|
||||
onChange={(e) => {
|
||||
const newVal = e.target.value;
|
||||
const updated = JSON.parse(editableConfig);
|
||||
updated.config[key] = newVal;
|
||||
setEditableConfig(JSON.stringify(updated, null, 2));
|
||||
}}
|
||||
/>
|
||||
<Field.HelperText>可编辑字段: {key}</Field.HelperText>
|
||||
</Field.Root>
|
||||
);
|
||||
})}
|
||||
|
||||
<Text fontWeight={'semibold'} mt={3} mb={2}>
|
||||
配置命令:
|
||||
</Text>
|
||||
{cfg.commands?.map((cmd, i) => (
|
||||
<Field.Root key={i} colorPalette={'teal'} orientation={'vertical'} mb={2}>
|
||||
<Field.Label fontSize="sm">命令 #{i + 1}</Field.Label>
|
||||
<Textarea
|
||||
size={'sm'}
|
||||
fontFamily={'monospace'}
|
||||
value={cmd}
|
||||
onChange={(e) => {
|
||||
const newCmd = e.target.value;
|
||||
const updated = JSON.parse(editableConfig);
|
||||
updated.config.commands[i] = newCmd;
|
||||
setEditableConfig(JSON.stringify(updated, null, 2));
|
||||
}}
|
||||
/>
|
||||
</Field.Root>
|
||||
))}
|
||||
|
||||
<Button
|
||||
size={'sm'}
|
||||
mt={3}
|
||||
colorScheme={'teal'}
|
||||
onClick={() => {
|
||||
Notification.success({
|
||||
title: `配置 ${cfg.type} 已保存`,
|
||||
description: '修改已同步至内存配置',
|
||||
});
|
||||
}}
|
||||
>
|
||||
保存当前配置
|
||||
</Button>
|
||||
</Box>
|
||||
));
|
||||
})()}
|
||||
{isApplying && (
|
||||
<FadeInWrapper delay={0.2}>
|
||||
<VStack spacing={4} align={'stretch'}>
|
||||
<Box
|
||||
p={4}
|
||||
bg={'whiteAlpha.100'}
|
||||
borderRadius={'xl'}
|
||||
border={'1px solid'}
|
||||
borderColor={'whiteAlpha.300'}
|
||||
>
|
||||
<Text fontSize={'lg'} fontWeight={'bold'} mb={2}>
|
||||
应用配置命令
|
||||
</Text>
|
||||
<Box>
|
||||
{conmmand.map((command, index) => (
|
||||
<HStack key={index} mb={2}>
|
||||
<Text fontSize={'sm'} flex={1}>
|
||||
{command}
|
||||
</Text>
|
||||
<Spinner
|
||||
size={'sm'}
|
||||
color={applyStatus[index] === 'success' ? 'green.500' : 'red.500'}
|
||||
display={
|
||||
applyStatus[index] === 'pending' ||
|
||||
applyStatus[index] === 'in-progress'
|
||||
? 'inline-block'
|
||||
: 'none'
|
||||
}
|
||||
/>
|
||||
<Text
|
||||
color={applyStatus[index] === 'success' ? 'green.500' : 'red.500'}
|
||||
ml={2}
|
||||
>
|
||||
{applyStatus[index] === 'success'
|
||||
? '成功'
|
||||
: applyStatus[index] === 'failed'
|
||||
? '失败'
|
||||
: applyStatus[index] === 'in-progress'
|
||||
? '正在应用'
|
||||
: ''}
|
||||
</Text>
|
||||
</HStack>
|
||||
))}
|
||||
</Box>
|
||||
</Box>
|
||||
</VStack>
|
||||
</FadeInWrapper>
|
||||
)}
|
||||
</VStack>
|
||||
</FadeInWrapper>
|
||||
)}
|
||||
</VStack>
|
||||
</FadeInWrapper>
|
||||
</PageContainer>
|
||||
|
@ -41,22 +41,16 @@ export const api = {
|
||||
* @param text 文本
|
||||
* @returns {Promise<axios.AxiosResponse<any>>}
|
||||
*/
|
||||
//parseCommand: async (text) => await axios.post(buildUrl('/api/parse_command'), { command: text }),
|
||||
async parseCommand(text) {
|
||||
const res = await axios.post(buildUrl('/api/parse_command', { command: text }));
|
||||
if (res) {
|
||||
return res;
|
||||
} else return null;
|
||||
},
|
||||
parseCommand: (text) => axios.post(buildUrl('/api/parse_command'), { command: text }),
|
||||
|
||||
/**
|
||||
* 应用配置
|
||||
* @param switch_ip 交换机ip
|
||||
* @param config 配置
|
||||
* @param commands 配置,为数组[]
|
||||
* @returns {Promise<axios.AxiosResponse<any>>}
|
||||
*/
|
||||
applyConfig: (switch_ip, config) =>
|
||||
axios.post(buildUrl('/api/apply_config'), { switch_ip, config }),
|
||||
applyConfig: (switch_ip, commands) =>
|
||||
axios.post(buildUrl('/api/execute_cli_commands'), { switch_ip, commands }),
|
||||
|
||||
/**
|
||||
* 更新基础URL
|
||||
|
Loading…
x
Reference in New Issue
Block a user