Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 132 additions & 20 deletions web/src/components/table/channels/modals/EditChannelModal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ import {
IconCode,
IconGlobe,
IconBolt,
IconChevronUp,
IconChevronDown,
} from '@douyinfe/semi-icons';

const { Text, Title } = Typography;
Expand Down Expand Up @@ -206,6 +208,27 @@ const EditChannelModal = (props) => {
keyData: '',
});

// 专门的2FA验证状态(用于TwoFactorAuthModal)
const [show2FAVerifyModal, setShow2FAVerifyModal] = useState(false);
const [verifyCode, setVerifyCode] = useState('');
const [verifyLoading, setVerifyLoading] = useState(false);

// 表单块导航相关状态
const formSectionRefs = useRef({
basicInfo: null,
apiConfig: null,
modelConfig: null,
advancedSettings: null,
channelExtraSettings: null,
});
const [currentSectionIndex, setCurrentSectionIndex] = useState(0);
const formSections = ['basicInfo', 'apiConfig', 'modelConfig', 'advancedSettings', 'channelExtraSettings'];
const formContainerRef = useRef(null);

// 2FA状态更新辅助函数
const updateTwoFAState = (updates) => {
setTwoFAState((prev) => ({ ...prev, ...updates }));
};
// 使用通用安全验证 Hook
const {
isModalVisible,
Expand Down Expand Up @@ -245,6 +268,44 @@ const EditChannelModal = (props) => {
});
};

// 重置2FA验证状态
const reset2FAVerifyState = () => {
setShow2FAVerifyModal(false);
setVerifyCode('');
setVerifyLoading(false);
};

// 表单导航功能
const scrollToSection = (sectionKey) => {
const sectionElement = formSectionRefs.current[sectionKey];
if (sectionElement) {
sectionElement.scrollIntoView({
behavior: 'smooth',
block: 'start',
inline: 'nearest'
});
}
};

const navigateToSection = (direction) => {
const availableSections = formSections.filter(section => {
if (section === 'apiConfig') {
return showApiConfigCard;
}
return true;
});

let newIndex;
if (direction === 'up') {
newIndex = currentSectionIndex > 0 ? currentSectionIndex - 1 : availableSections.length - 1;
} else {
newIndex = currentSectionIndex < availableSections.length - 1 ? currentSectionIndex + 1 : 0;
}

setCurrentSectionIndex(newIndex);
scrollToSection(availableSections[newIndex]);
};
Comment on lines +290 to +307

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Fix navigation index when sections collapse.

When showApiConfigCard flips to false the buttons should skip the API block, but currentSectionIndex still points to the old slot from formSections. Pressing Down in that state jumps straight from “基本信息” to “高级设置”, because we increment a stale index. Same problem exists for the Up button.

Please normalise the current position against availableSections before advancing and then persist the canonical index (or switch to storing the section key). One way to address it:

-    let newIndex;
-    if (direction === 'up') {
-      newIndex = currentSectionIndex > 0 ? currentSectionIndex - 1 : availableSections.length - 1;
-    } else {
-      newIndex = currentSectionIndex < availableSections.length - 1 ? currentSectionIndex + 1 : 0;
-    }
-
-    setCurrentSectionIndex(newIndex);
-    scrollToSection(availableSections[newIndex]);
+    const currentKey = formSections[currentSectionIndex];
+    const normalizedIndex = Math.max(
+      availableSections.indexOf(currentKey),
+      0,
+    );
+
+    let newIndex;
+    if (direction === 'up') {
+      newIndex =
+        normalizedIndex > 0
+          ? normalizedIndex - 1
+          : availableSections.length - 1;
+    } else {
+      newIndex =
+        normalizedIndex < availableSections.length - 1
+          ? normalizedIndex + 1
+          : 0;
+    }
+
+    const targetKey = availableSections[newIndex] ?? availableSections[0];
+    if (!targetKey) {
+      return;
+    }
+    setCurrentSectionIndex(formSections.indexOf(targetKey));
+    scrollToSection(targetKey);

This keeps navigation aligned with the filtered list and prevents skipping sections.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const navigateToSection = (direction) => {
const availableSections = formSections.filter(section => {
if (section === 'apiConfig') {
return showApiConfigCard;
}
return true;
});
let newIndex;
if (direction === 'up') {
newIndex = currentSectionIndex > 0 ? currentSectionIndex - 1 : availableSections.length - 1;
} else {
newIndex = currentSectionIndex < availableSections.length - 1 ? currentSectionIndex + 1 : 0;
}
setCurrentSectionIndex(newIndex);
scrollToSection(availableSections[newIndex]);
};
const navigateToSection = (direction) => {
const availableSections = formSections.filter(section => {
if (section === 'apiConfig') {
return showApiConfigCard;
}
return true;
});
const currentKey = formSections[currentSectionIndex];
const normalizedIndex = Math.max(
availableSections.indexOf(currentKey),
0,
);
let newIndex;
if (direction === 'up') {
newIndex =
normalizedIndex > 0
? normalizedIndex - 1
: availableSections.length - 1;
} else {
newIndex =
normalizedIndex < availableSections.length - 1
? normalizedIndex + 1
: 0;
}
const targetKey = availableSections[newIndex] ?? availableSections[0];
if (!targetKey) {
return;
}
setCurrentSectionIndex(formSections.indexOf(targetKey));
scrollToSection(targetKey);
};
🤖 Prompt for AI Agents
In web/src/components/table/channels/modals/EditChannelModal.jsx around lines
256-273, the navigation uses a stale currentSectionIndex from the full
formSections list when showApiConfigCard toggles off, causing jumps; normalize
the current position against the filtered availableSections before advancing:
compute the current section key (e.g. formSections[currentSectionIndex]), find
its index in availableSections (fallback to 0 if missing), use that normalized
index to compute the up/down newIndex, then call
setCurrentSectionIndex(newIndex) and
scrollToSection(availableSections[newIndex]); alternatively persist section
selection by key instead of an index so toggling sections cannot leave an
invalid index.


// 渠道额外设置状态
const [channelSettings, setChannelSettings] = useState({
force_format: false,
Expand Down Expand Up @@ -729,6 +790,8 @@ const EditChannelModal = (props) => {
fetchModelGroups();
// 重置手动输入模式状态
setUseManualInput(false);
// 重置导航状态
setCurrentSectionIndex(0);
} else {
// 统一的模态框关闭重置逻辑
resetModalState();
Expand Down Expand Up @@ -1270,7 +1333,41 @@ const EditChannelModal = (props) => {
visible={props.visible}
width={isMobile ? '100%' : 600}
footer={
<div className='flex justify-end bg-white'>
<div className='flex justify-between items-center bg-white'>
<div className='flex gap-2'>
<Button
size='small'
type='tertiary'
icon={<IconChevronUp />}
onClick={() => navigateToSection('up')}
style={{
borderRadius: '50%',
width: '32px',
height: '32px',
padding: 0,
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}}
title={t('上一个表单块')}
/>
<Button
size='small'
type='tertiary'
icon={<IconChevronDown />}
onClick={() => navigateToSection('down')}
style={{
borderRadius: '50%',
width: '32px',
height: '32px',
padding: 0,
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}}
title={t('下一个表单块')}
/>
</div>
<Space>
<Button
theme='solid'
Expand Down Expand Up @@ -1301,10 +1398,14 @@ const EditChannelModal = (props) => {
>
{() => (
<Spin spinning={loading}>
<div className='p-2'>
<Card className='!rounded-2xl shadow-sm border-0 mb-6'>
{/* Header: Basic Info */}
<div className='flex items-center mb-2'>
<div
className='p-2'
ref={formContainerRef}
>
<div ref={el => formSectionRefs.current.basicInfo = el}>
<Card className='!rounded-2xl shadow-sm border-0 mb-6'>
{/* Header: Basic Info */}
<div className='flex items-center mb-2'>
<Avatar
size='small'
color='blue'
Expand Down Expand Up @@ -1778,13 +1879,15 @@ const EditChannelModal = (props) => {
}
/>
)}
</Card>
</Card>
</div>

{/* API Configuration Card */}
{showApiConfigCard && (
<Card className='!rounded-2xl shadow-sm border-0 mb-6'>
{/* Header: API Config */}
<div className='flex items-center mb-2'>
<div ref={el => formSectionRefs.current.apiConfig = el}>
<Card className='!rounded-2xl shadow-sm border-0 mb-6'>
{/* Header: API Config */}
<div className='flex items-center mb-2'>
<Avatar
size='small'
color='green'
Expand Down Expand Up @@ -1995,13 +2098,15 @@ const EditChannelModal = (props) => {
/>
</div>
)}
</Card>
</Card>
</div>
)}

{/* Model Configuration Card */}
<Card className='!rounded-2xl shadow-sm border-0 mb-6'>
{/* Header: Model Config */}
<div className='flex items-center mb-2'>
<div ref={el => formSectionRefs.current.modelConfig = el}>
<Card className='!rounded-2xl shadow-sm border-0 mb-6'>
{/* Header: Model Config */}
<div className='flex items-center mb-2'>
<Avatar
size='small'
color='purple'
Expand Down Expand Up @@ -2196,12 +2301,14 @@ const EditChannelModal = (props) => {
formApi={formApiRef.current}
extraText={t('键为请求中的模型名称,值为要替换的模型名称')}
/>
</Card>
</Card>
</div>

{/* Advanced Settings Card */}
<Card className='!rounded-2xl shadow-sm border-0 mb-6'>
{/* Header: Advanced Settings */}
<div className='flex items-center mb-2'>
<div ref={el => formSectionRefs.current.advancedSettings = el}>
<Card className='!rounded-2xl shadow-sm border-0 mb-6'>
{/* Header: Advanced Settings */}
<div className='flex items-center mb-2'>
<Avatar
size='small'
color='orange'
Expand Down Expand Up @@ -2414,6 +2521,8 @@ const EditChannelModal = (props) => {
'键为原状态码,值为要复写的状态码,仅影响本地判断',
)}
/>
</Card>
</div>

{/* 字段透传控制 - OpenAI 渠道 */}
{inputs.type === 1 && (
Expand Down Expand Up @@ -2487,9 +2596,10 @@ const EditChannelModal = (props) => {
</Card>

{/* Channel Extra Settings Card */}
<Card className='!rounded-2xl shadow-sm border-0 mb-6'>
{/* Header: Channel Extra Settings */}
<div className='flex items-center mb-2'>
<div ref={el => formSectionRefs.current.channelExtraSettings = el}>
<Card className='!rounded-2xl shadow-sm border-0 mb-6'>
{/* Header: Channel Extra Settings */}
<div className='flex items-center mb-2'>
<Avatar
size='small'
color='violet'
Expand Down Expand Up @@ -2587,6 +2697,8 @@ const EditChannelModal = (props) => {
'如果用户请求中包含系统提示词,则使用此设置拼接到用户的系统提示词前面',
)}
/>
</Card>
</div>

</Card>
</div>
Expand Down