From 2a54e989b4c033e41b469c2e7525b4483471922a Mon Sep 17 00:00:00 2001 From: HynoR <20227709+HynoR@users.noreply.github.com> Date: Sun, 21 Sep 2025 17:26:56 +0900 Subject: [PATCH] feat: add duplicate key removal function when edit or add new channel --- .../channels/modals/EditChannelModal.jsx | 120 ++++++++++++++---- 1 file changed, 97 insertions(+), 23 deletions(-) diff --git a/web/src/components/table/channels/modals/EditChannelModal.jsx b/web/src/components/table/channels/modals/EditChannelModal.jsx index c0a216246..03becc2f0 100644 --- a/web/src/components/table/channels/modals/EditChannelModal.jsx +++ b/web/src/components/table/channels/modals/EditChannelModal.jsx @@ -802,7 +802,9 @@ const EditChannelModal = (props) => { delete localInputs.key; } } else { - localInputs.key = batch ? JSON.stringify(keys) : JSON.stringify(keys[0]); + localInputs.key = batch + ? JSON.stringify(keys) + : JSON.stringify(keys[0]); } } } @@ -899,6 +901,56 @@ const EditChannelModal = (props) => { } }; + // 密钥去重函数 + const deduplicateKeys = () => { + const currentKey = formApiRef.current?.getValue('key') || inputs.key || ''; + + if (!currentKey.trim()) { + showInfo(t('请先输入密钥')); + return; + } + + // 按行分割密钥 + const keyLines = currentKey.split('\n'); + const beforeCount = keyLines.length; + + // 使用哈希表去重,保持原有顺序 + const keySet = new Set(); + const deduplicatedKeys = []; + + keyLines.forEach((line) => { + const trimmedLine = line.trim(); + if (trimmedLine && !keySet.has(trimmedLine)) { + keySet.add(trimmedLine); + deduplicatedKeys.push(trimmedLine); + } + }); + + const afterCount = deduplicatedKeys.length; + const deduplicatedKeyText = deduplicatedKeys.join('\n'); + + // 更新表单和状态 + if (formApiRef.current) { + formApiRef.current.setValue('key', deduplicatedKeyText); + } + handleInputChange('key', deduplicatedKeyText); + + // 显示去重结果 + const message = t( + '去重完成:去重前 {{before}} 个密钥,去重后 {{after}} 个密钥', + { + before: beforeCount, + after: afterCount, + }, + ); + + if (beforeCount === afterCount) { + showInfo(t('未发现重复密钥')); + } else { + showSuccess(message); + } + }; + const addCustomModels = () => { if (customModel.trim() === '') return; const modelArray = customModel.split(',').map((model) => model.trim()); @@ -994,24 +1046,41 @@ const EditChannelModal = (props) => { )} {batch && ( - { - setMultiToSingle((prev) => !prev); - setInputs((prev) => { - const newInputs = { ...prev }; - if (!multiToSingle) { - newInputs.multi_key_mode = multiKeyMode; - } else { - delete newInputs.multi_key_mode; - } - return newInputs; - }); - }} - > - {t('密钥聚合模式')} - + <> + { + setMultiToSingle((prev) => { + const nextValue = !prev; + setInputs((prevInputs) => { + const newInputs = { ...prevInputs }; + if (nextValue) { + newInputs.multi_key_mode = multiKeyMode; + } else { + delete newInputs.multi_key_mode; + } + return newInputs; + }); + return nextValue; + }); + }} + > + {t('密钥聚合模式')} + + + {inputs.type !== 41 && ( + + )} + )} ) : null; @@ -1198,7 +1267,10 @@ const EditChannelModal = (props) => { value={inputs.vertex_key_type || 'json'} onChange={(value) => { // 更新设置中的 vertex_key_type - handleChannelOtherSettingsChange('vertex_key_type', value); + handleChannelOtherSettingsChange( + 'vertex_key_type', + value, + ); // 切换为 api_key 时,关闭批量与手动/文件切换,并清理已选文件 if (value === 'api_key') { setBatch(false); @@ -1218,7 +1290,8 @@ const EditChannelModal = (props) => { /> )} {batch ? ( - inputs.type === 41 && (inputs.vertex_key_type || 'json') === 'json' ? ( + inputs.type === 41 && + (inputs.vertex_key_type || 'json') === 'json' ? ( { autoComplete='new-password' onChange={(value) => handleInputChange('key', value)} extraText={ -
+
{isEdit && isMultiKeyChannel && keyMode === 'append' && ( @@ -1282,7 +1355,8 @@ const EditChannelModal = (props) => { ) ) : ( <> - {inputs.type === 41 && (inputs.vertex_key_type || 'json') === 'json' ? ( + {inputs.type === 41 && + (inputs.vertex_key_type || 'json') === 'json' ? ( <> {!batch && (