|
@@ -61,9 +61,11 @@ import OllamaModelModal from './OllamaModelModal';
|
|
|
import CodexOAuthModal from './CodexOAuthModal';
|
|
import CodexOAuthModal from './CodexOAuthModal';
|
|
|
import JSONEditor from '../../../common/ui/JSONEditor';
|
|
import JSONEditor from '../../../common/ui/JSONEditor';
|
|
|
import SecureVerificationModal from '../../../common/modals/SecureVerificationModal';
|
|
import SecureVerificationModal from '../../../common/modals/SecureVerificationModal';
|
|
|
|
|
+import StatusCodeRiskGuardModal from './StatusCodeRiskGuardModal';
|
|
|
import ChannelKeyDisplay from '../../../common/ui/ChannelKeyDisplay';
|
|
import ChannelKeyDisplay from '../../../common/ui/ChannelKeyDisplay';
|
|
|
import { useSecureVerification } from '../../../../hooks/common/useSecureVerification';
|
|
import { useSecureVerification } from '../../../../hooks/common/useSecureVerification';
|
|
|
import { createApiCalls } from '../../../../services/secureVerification';
|
|
import { createApiCalls } from '../../../../services/secureVerification';
|
|
|
|
|
+import { collectNewDisallowedStatusCodeRedirects } from './statusCodeRiskGuard';
|
|
|
import {
|
|
import {
|
|
|
IconSave,
|
|
IconSave,
|
|
|
IconClose,
|
|
IconClose,
|
|
@@ -255,6 +257,12 @@ const EditChannelModal = (props) => {
|
|
|
window.open(targetUrl, '_blank', 'noopener');
|
|
window.open(targetUrl, '_blank', 'noopener');
|
|
|
};
|
|
};
|
|
|
const [verifyLoading, setVerifyLoading] = useState(false);
|
|
const [verifyLoading, setVerifyLoading] = useState(false);
|
|
|
|
|
+ const statusCodeRiskConfirmResolverRef = useRef(null);
|
|
|
|
|
+ const [statusCodeRiskConfirmVisible, setStatusCodeRiskConfirmVisible] =
|
|
|
|
|
+ useState(false);
|
|
|
|
|
+ const [statusCodeRiskDetailItems, setStatusCodeRiskDetailItems] = useState(
|
|
|
|
|
+ [],
|
|
|
|
|
+ );
|
|
|
|
|
|
|
|
// 表单块导航相关状态
|
|
// 表单块导航相关状态
|
|
|
const formSectionRefs = useRef({
|
|
const formSectionRefs = useRef({
|
|
@@ -276,6 +284,7 @@ const EditChannelModal = (props) => {
|
|
|
const doubaoApiClickCountRef = useRef(0);
|
|
const doubaoApiClickCountRef = useRef(0);
|
|
|
const initialModelsRef = useRef([]);
|
|
const initialModelsRef = useRef([]);
|
|
|
const initialModelMappingRef = useRef('');
|
|
const initialModelMappingRef = useRef('');
|
|
|
|
|
+ const initialStatusCodeMappingRef = useRef('');
|
|
|
|
|
|
|
|
// 2FA状态更新辅助函数
|
|
// 2FA状态更新辅助函数
|
|
|
const updateTwoFAState = (updates) => {
|
|
const updateTwoFAState = (updates) => {
|
|
@@ -691,6 +700,7 @@ const EditChannelModal = (props) => {
|
|
|
.map((model) => (model || '').trim())
|
|
.map((model) => (model || '').trim())
|
|
|
.filter(Boolean);
|
|
.filter(Boolean);
|
|
|
initialModelMappingRef.current = data.model_mapping || '';
|
|
initialModelMappingRef.current = data.model_mapping || '';
|
|
|
|
|
+ initialStatusCodeMappingRef.current = data.status_code_mapping || '';
|
|
|
|
|
|
|
|
let parsedIonet = null;
|
|
let parsedIonet = null;
|
|
|
if (data.other_info) {
|
|
if (data.other_info) {
|
|
@@ -1017,11 +1027,22 @@ const EditChannelModal = (props) => {
|
|
|
if (!isEdit) {
|
|
if (!isEdit) {
|
|
|
initialModelsRef.current = [];
|
|
initialModelsRef.current = [];
|
|
|
initialModelMappingRef.current = '';
|
|
initialModelMappingRef.current = '';
|
|
|
|
|
+ initialStatusCodeMappingRef.current = '';
|
|
|
}
|
|
}
|
|
|
}, [isEdit, props.visible]);
|
|
}, [isEdit, props.visible]);
|
|
|
|
|
|
|
|
|
|
+ useEffect(() => {
|
|
|
|
|
+ return () => {
|
|
|
|
|
+ if (statusCodeRiskConfirmResolverRef.current) {
|
|
|
|
|
+ statusCodeRiskConfirmResolverRef.current(false);
|
|
|
|
|
+ statusCodeRiskConfirmResolverRef.current = null;
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+ }, []);
|
|
|
|
|
+
|
|
|
// 统一的模态框重置函数
|
|
// 统一的模态框重置函数
|
|
|
const resetModalState = () => {
|
|
const resetModalState = () => {
|
|
|
|
|
+ resolveStatusCodeRiskConfirm(false);
|
|
|
formApiRef.current?.reset();
|
|
formApiRef.current?.reset();
|
|
|
// 重置渠道设置状态
|
|
// 重置渠道设置状态
|
|
|
setChannelSettings({
|
|
setChannelSettings({
|
|
@@ -1151,6 +1172,22 @@ const EditChannelModal = (props) => {
|
|
|
});
|
|
});
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
|
|
+ const resolveStatusCodeRiskConfirm = (confirmed) => {
|
|
|
|
|
+ setStatusCodeRiskConfirmVisible(false);
|
|
|
|
|
+ setStatusCodeRiskDetailItems([]);
|
|
|
|
|
+ if (statusCodeRiskConfirmResolverRef.current) {
|
|
|
|
|
+ statusCodeRiskConfirmResolverRef.current(confirmed);
|
|
|
|
|
+ statusCodeRiskConfirmResolverRef.current = null;
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const confirmStatusCodeRisk = (detailItems) =>
|
|
|
|
|
+ new Promise((resolve) => {
|
|
|
|
|
+ statusCodeRiskConfirmResolverRef.current = resolve;
|
|
|
|
|
+ setStatusCodeRiskDetailItems(detailItems);
|
|
|
|
|
+ setStatusCodeRiskConfirmVisible(true);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
const hasModelConfigChanged = (normalizedModels, modelMappingStr) => {
|
|
const hasModelConfigChanged = (normalizedModels, modelMappingStr) => {
|
|
|
if (!isEdit) return true;
|
|
if (!isEdit) return true;
|
|
|
const initialModels = initialModelsRef.current;
|
|
const initialModels = initialModelsRef.current;
|
|
@@ -1340,6 +1377,17 @@ const EditChannelModal = (props) => {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ const riskyStatusCodeRedirects = collectNewDisallowedStatusCodeRedirects(
|
|
|
|
|
+ initialStatusCodeMappingRef.current,
|
|
|
|
|
+ localInputs.status_code_mapping,
|
|
|
|
|
+ );
|
|
|
|
|
+ if (riskyStatusCodeRedirects.length > 0) {
|
|
|
|
|
+ const confirmed = await confirmStatusCodeRisk(riskyStatusCodeRedirects);
|
|
|
|
|
+ if (!confirmed) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
if (localInputs.base_url && localInputs.base_url.endsWith('/')) {
|
|
if (localInputs.base_url && localInputs.base_url.endsWith('/')) {
|
|
|
localInputs.base_url = localInputs.base_url.slice(
|
|
localInputs.base_url = localInputs.base_url.slice(
|
|
|
0,
|
|
0,
|
|
@@ -3440,6 +3488,12 @@ const EditChannelModal = (props) => {
|
|
|
onVisibleChange={(visible) => setIsModalOpenurl(visible)}
|
|
onVisibleChange={(visible) => setIsModalOpenurl(visible)}
|
|
|
/>
|
|
/>
|
|
|
</SideSheet>
|
|
</SideSheet>
|
|
|
|
|
+ <StatusCodeRiskGuardModal
|
|
|
|
|
+ visible={statusCodeRiskConfirmVisible}
|
|
|
|
|
+ detailItems={statusCodeRiskDetailItems}
|
|
|
|
|
+ onCancel={() => resolveStatusCodeRiskConfirm(false)}
|
|
|
|
|
+ onConfirm={() => resolveStatusCodeRiskConfirm(true)}
|
|
|
|
|
+ />
|
|
|
{/* 使用通用安全验证模态框 */}
|
|
{/* 使用通用安全验证模态框 */}
|
|
|
<SecureVerificationModal
|
|
<SecureVerificationModal
|
|
|
visible={isModalVisible}
|
|
visible={isModalVisible}
|