|
|
@@ -438,13 +438,16 @@ const EditChannel = (props) => {
|
|
|
value={inputs.type}
|
|
|
onChange={(value) => handleInputChange('type', value)}
|
|
|
style={{ width: '50%' }}
|
|
|
+ filter
|
|
|
+ searchPosition='dropdown'
|
|
|
+ placeholder={t('请选择渠道类型')}
|
|
|
/>
|
|
|
{inputs.type === 3 && (
|
|
|
<>
|
|
|
<div style={{ marginTop: 10 }}>
|
|
|
<Banner
|
|
|
type={'warning'}
|
|
|
- description={t('注意,模型部署名称必须和模型名称保持一致,因为 One API 会把请求体中的 model 参数替换为你的部署名称(模型名称中的点会被剔除)')}
|
|
|
+ description={t('注意,模型部署名称必须和模型名称保持一致')}
|
|
|
></Banner>
|
|
|
</div>
|
|
|
<div style={{ marginTop: 10 }}>
|
|
|
@@ -501,6 +504,19 @@ const EditChannel = (props) => {
|
|
|
/>
|
|
|
</>
|
|
|
)}
|
|
|
+ <div style={{ marginTop: 10 }}>
|
|
|
+ <Typography.Text strong>{t('名称')}:</Typography.Text>
|
|
|
+ </div>
|
|
|
+ <Input
|
|
|
+ required
|
|
|
+ name="name"
|
|
|
+ placeholder={t('请为渠道命名')}
|
|
|
+ onChange={(value) => {
|
|
|
+ handleInputChange('name', value);
|
|
|
+ }}
|
|
|
+ value={inputs.name}
|
|
|
+ autoComplete="new-password"
|
|
|
+ />
|
|
|
{inputs.type !== 3 && inputs.type !== 8 && inputs.type !== 22 && inputs.type !== 36 && (
|
|
|
<>
|
|
|
<div style={{ marginTop: 10 }}>
|
|
|
@@ -518,6 +534,77 @@ const EditChannel = (props) => {
|
|
|
/>
|
|
|
</>
|
|
|
)}
|
|
|
+ <div style={{ marginTop: 10 }}>
|
|
|
+ <Typography.Text strong>{t('密钥')}:</Typography.Text>
|
|
|
+ </div>
|
|
|
+ {batch ? (
|
|
|
+ <TextArea
|
|
|
+ label={t('密钥')}
|
|
|
+ name="key"
|
|
|
+ required
|
|
|
+ placeholder={t('请输入密钥,一行一个')}
|
|
|
+ onChange={(value) => {
|
|
|
+ handleInputChange('key', value);
|
|
|
+ }}
|
|
|
+ value={inputs.key}
|
|
|
+ style={{ minHeight: 150, fontFamily: 'JetBrains Mono, Consolas' }}
|
|
|
+ autoComplete="new-password"
|
|
|
+ />
|
|
|
+ ) : (
|
|
|
+ <>
|
|
|
+ {inputs.type === 41 ? (
|
|
|
+ <TextArea
|
|
|
+ label={t('鉴权json')}
|
|
|
+ name="key"
|
|
|
+ required
|
|
|
+ placeholder={'{\n' +
|
|
|
+ ' "type": "service_account",\n' +
|
|
|
+ ' "project_id": "abc-bcd-123-456",\n' +
|
|
|
+ ' "private_key_id": "123xxxxx456",\n' +
|
|
|
+ ' "private_key": "-----BEGIN PRIVATE KEY-----xxxx\n' +
|
|
|
+ ' "client_email": "xxx@developer.gserviceaccount.com",\n' +
|
|
|
+ ' "client_id": "111222333",\n' +
|
|
|
+ ' "auth_uri": "https://accounts.google.com/o/oauth2/auth",\n' +
|
|
|
+ ' "token_uri": "https://oauth2.googleapis.com/token",\n' +
|
|
|
+ ' "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",\n' +
|
|
|
+ ' "client_x509_cert_url": "https://xxxxx.gserviceaccount.com",\n' +
|
|
|
+ ' "universe_domain": "googleapis.com"\n' +
|
|
|
+ '}'}
|
|
|
+ onChange={(value) => {
|
|
|
+ handleInputChange('key', value);
|
|
|
+ }}
|
|
|
+ autosize={{ minRows: 10 }}
|
|
|
+ value={inputs.key}
|
|
|
+ autoComplete="new-password"
|
|
|
+ />
|
|
|
+ ) : (
|
|
|
+ <Input
|
|
|
+ label={t('密钥')}
|
|
|
+ name="key"
|
|
|
+ required
|
|
|
+ placeholder={t(type2secretPrompt(inputs.type))}
|
|
|
+ onChange={(value) => {
|
|
|
+ handleInputChange('key', value);
|
|
|
+ }}
|
|
|
+ value={inputs.key}
|
|
|
+ autoComplete="new-password"
|
|
|
+ />
|
|
|
+ )}
|
|
|
+ </>
|
|
|
+ )}
|
|
|
+ {!isEdit && (
|
|
|
+ <div style={{ marginTop: 10, display: 'flex' }}>
|
|
|
+ <Space>
|
|
|
+ <Checkbox
|
|
|
+ checked={batch}
|
|
|
+ label={t('批量创建')}
|
|
|
+ name="batch"
|
|
|
+ onChange={() => setBatch(!batch)}
|
|
|
+ />
|
|
|
+ <Typography.Text strong>{t('批量创建')}</Typography.Text>
|
|
|
+ </Space>
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
{inputs.type === 22 && (
|
|
|
<>
|
|
|
<div style={{ marginTop: 10 }}>
|
|
|
@@ -552,19 +639,6 @@ const EditChannel = (props) => {
|
|
|
/>
|
|
|
</>
|
|
|
)}
|
|
|
- <div style={{ marginTop: 10 }}>
|
|
|
- <Typography.Text strong>{t('名称')}:</Typography.Text>
|
|
|
- </div>
|
|
|
- <Input
|
|
|
- required
|
|
|
- name="name"
|
|
|
- placeholder={t('请为渠道命名')}
|
|
|
- onChange={(value) => {
|
|
|
- handleInputChange('name', value);
|
|
|
- }}
|
|
|
- value={inputs.name}
|
|
|
- autoComplete="new-password"
|
|
|
- />
|
|
|
<div style={{ marginTop: 10 }}>
|
|
|
<Typography.Text strong>{t('分组')}:</Typography.Text>
|
|
|
</div>
|
|
|
@@ -640,7 +714,7 @@ const EditChannel = (props) => {
|
|
|
{inputs.type === 21 && (
|
|
|
<>
|
|
|
<div style={{ marginTop: 10 }}>
|
|
|
- <Typography.Text strong>��识库 ID:</Typography.Text>
|
|
|
+ <Typography.Text strong>知识库 ID:</Typography.Text>
|
|
|
</div>
|
|
|
<Input
|
|
|
label="知识库 ID"
|
|
|
@@ -768,149 +842,6 @@ const EditChannel = (props) => {
|
|
|
>
|
|
|
{t('填入模板')}
|
|
|
</Typography.Text>
|
|
|
- <div style={{ marginTop: 10 }}>
|
|
|
- <Typography.Text strong>{t('密钥')}:</Typography.Text>
|
|
|
- </div>
|
|
|
- {batch ? (
|
|
|
- <TextArea
|
|
|
- label={t('密钥')}
|
|
|
- name="key"
|
|
|
- required
|
|
|
- placeholder={t('请输入密钥,一行一个')}
|
|
|
- onChange={(value) => {
|
|
|
- handleInputChange('key', value);
|
|
|
- }}
|
|
|
- value={inputs.key}
|
|
|
- style={{ minHeight: 150, fontFamily: 'JetBrains Mono, Consolas' }}
|
|
|
- autoComplete="new-password"
|
|
|
- />
|
|
|
- ) : (
|
|
|
- <>
|
|
|
- {inputs.type === 41 ? (
|
|
|
- <TextArea
|
|
|
- label={t('鉴权json')}
|
|
|
- name="key"
|
|
|
- required
|
|
|
- placeholder={'{\n' +
|
|
|
- ' "type": "service_account",\n' +
|
|
|
- ' "project_id": "abc-bcd-123-456",\n' +
|
|
|
- ' "private_key_id": "123xxxxx456",\n' +
|
|
|
- ' "private_key": "-----BEGIN PRIVATE KEY-----xxxx\n' +
|
|
|
- ' "client_email": "xxx@developer.gserviceaccount.com",\n' +
|
|
|
- ' "client_id": "111222333",\n' +
|
|
|
- ' "auth_uri": "https://accounts.google.com/o/oauth2/auth",\n' +
|
|
|
- ' "token_uri": "https://oauth2.googleapis.com/token",\n' +
|
|
|
- ' "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",\n' +
|
|
|
- ' "client_x509_cert_url": "https://xxxxx.gserviceaccount.com",\n' +
|
|
|
- ' "universe_domain": "googleapis.com"\n' +
|
|
|
- '}'}
|
|
|
- onChange={(value) => {
|
|
|
- handleInputChange('key', value);
|
|
|
- }}
|
|
|
- autosize={{ minRows: 10 }}
|
|
|
- value={inputs.key}
|
|
|
- autoComplete="new-password"
|
|
|
- />
|
|
|
- ) : (
|
|
|
- <Input
|
|
|
- label={t('密钥')}
|
|
|
- name="key"
|
|
|
- required
|
|
|
- placeholder={t(type2secretPrompt(inputs.type))}
|
|
|
- onChange={(value) => {
|
|
|
- handleInputChange('key', value);
|
|
|
- }}
|
|
|
- value={inputs.key}
|
|
|
- autoComplete="new-password"
|
|
|
- />
|
|
|
- )}
|
|
|
- </>
|
|
|
- )}
|
|
|
- {!isEdit && (
|
|
|
- <div style={{ marginTop: 10, display: 'flex' }}>
|
|
|
- <Space>
|
|
|
- <Checkbox
|
|
|
- checked={batch}
|
|
|
- label={t('批量创建')}
|
|
|
- name="batch"
|
|
|
- onChange={() => setBatch(!batch)}
|
|
|
- />
|
|
|
- <Typography.Text strong>{t('批量创建')}</Typography.Text>
|
|
|
- </Space>
|
|
|
- </div>
|
|
|
- )}
|
|
|
- {inputs.type === 1 && (
|
|
|
- <>
|
|
|
- <div style={{ marginTop: 10 }}>
|
|
|
- <Typography.Text strong>{t('组织')}:</Typography.Text>
|
|
|
- </div>
|
|
|
- <Input
|
|
|
- label={t('组织,可选,不填则为默认组织')}
|
|
|
- name="openai_organization"
|
|
|
- placeholder={t('请输入组织org-xxx')}
|
|
|
- onChange={(value) => {
|
|
|
- handleInputChange('openai_organization', value);
|
|
|
- }}
|
|
|
- value={inputs.openai_organization}
|
|
|
- />
|
|
|
- </>
|
|
|
- )}
|
|
|
- <div style={{ marginTop: 10 }}>
|
|
|
- <Typography.Text strong>{t('默认测试模型')}:</Typography.Text>
|
|
|
- </div>
|
|
|
- <Input
|
|
|
- name="test_model"
|
|
|
- placeholder={t('不填则为模型列表第一个')}
|
|
|
- onChange={(value) => {
|
|
|
- handleInputChange('test_model', value);
|
|
|
- }}
|
|
|
- value={inputs.test_model}
|
|
|
- />
|
|
|
- <div style={{ marginTop: 10, display: 'flex' }}>
|
|
|
- <Space>
|
|
|
- <Checkbox
|
|
|
- name="auto_ban"
|
|
|
- checked={autoBan}
|
|
|
- onChange={() => {
|
|
|
- setAutoBan(!autoBan);
|
|
|
- }}
|
|
|
- />
|
|
|
- <Typography.Text strong>
|
|
|
- {t('是否自动禁用(仅当自动禁用开启时有效),关闭后不会自动禁用该渠道:')}
|
|
|
- </Typography.Text>
|
|
|
- </Space>
|
|
|
- </div>
|
|
|
- <div style={{ marginTop: 10 }}>
|
|
|
- <Typography.Text strong>
|
|
|
- {t('状态码复写(仅影响本地判断,不修改返回到上游的状态码)')}:
|
|
|
- </Typography.Text>
|
|
|
- </div>
|
|
|
- <TextArea
|
|
|
- placeholder={t('此项可选,用于复写返回的状态码,比如将claude渠道的400错误复写为500(用于重试),请勿滥用该功能,例如:') +
|
|
|
- '\n' + JSON.stringify(STATUS_CODE_MAPPING_EXAMPLE, null, 2)}
|
|
|
- name="status_code_mapping"
|
|
|
- onChange={(value) => {
|
|
|
- handleInputChange('status_code_mapping', value);
|
|
|
- }}
|
|
|
- autosize
|
|
|
- value={inputs.status_code_mapping}
|
|
|
- autoComplete="new-password"
|
|
|
- />
|
|
|
- <Typography.Text
|
|
|
- style={{
|
|
|
- color: 'rgba(var(--semi-blue-5), 1)',
|
|
|
- userSelect: 'none',
|
|
|
- cursor: 'pointer'
|
|
|
- }}
|
|
|
- onClick={() => {
|
|
|
- handleInputChange(
|
|
|
- 'status_code_mapping',
|
|
|
- JSON.stringify(STATUS_CODE_MAPPING_EXAMPLE, null, 2)
|
|
|
- );
|
|
|
- }}
|
|
|
- >
|
|
|
- {t('填入模板')}
|
|
|
- </Typography.Text>
|
|
|
<div style={{ marginTop: 10 }}>
|
|
|
<Typography.Text strong>
|
|
|
{t('渠道标签')}
|
|
|
@@ -1014,6 +945,78 @@ const EditChannel = (props) => {
|
|
|
</Typography.Text>
|
|
|
</Space>
|
|
|
</>
|
|
|
+ {inputs.type === 1 && (
|
|
|
+ <>
|
|
|
+ <div style={{ marginTop: 10 }}>
|
|
|
+ <Typography.Text strong>{t('组织')}:</Typography.Text>
|
|
|
+ </div>
|
|
|
+ <Input
|
|
|
+ label={t('组织,可选,不填则为默认组织')}
|
|
|
+ name="openai_organization"
|
|
|
+ placeholder={t('请输入组织org-xxx')}
|
|
|
+ onChange={(value) => {
|
|
|
+ handleInputChange('openai_organization', value);
|
|
|
+ }}
|
|
|
+ value={inputs.openai_organization}
|
|
|
+ />
|
|
|
+ </>
|
|
|
+ )}
|
|
|
+ <div style={{ marginTop: 10 }}>
|
|
|
+ <Typography.Text strong>{t('默认测试模型')}:</Typography.Text>
|
|
|
+ </div>
|
|
|
+ <Input
|
|
|
+ name="test_model"
|
|
|
+ placeholder={t('不填则为模型列表第一个')}
|
|
|
+ onChange={(value) => {
|
|
|
+ handleInputChange('test_model', value);
|
|
|
+ }}
|
|
|
+ value={inputs.test_model}
|
|
|
+ />
|
|
|
+ <div style={{ marginTop: 10, display: 'flex' }}>
|
|
|
+ <Space>
|
|
|
+ <Checkbox
|
|
|
+ name="auto_ban"
|
|
|
+ checked={autoBan}
|
|
|
+ onChange={() => {
|
|
|
+ setAutoBan(!autoBan);
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ <Typography.Text strong>
|
|
|
+ {t('是否自动禁用(仅当自动禁用开启时有效),关闭后不会自动禁用该渠道:')}
|
|
|
+ </Typography.Text>
|
|
|
+ </Space>
|
|
|
+ </div>
|
|
|
+ <div style={{ marginTop: 10 }}>
|
|
|
+ <Typography.Text strong>
|
|
|
+ {t('状态码复写(仅影响本地判断,不修改返回到上游的状态码)')}:
|
|
|
+ </Typography.Text>
|
|
|
+ </div>
|
|
|
+ <TextArea
|
|
|
+ placeholder={t('此项可选,用于复写返回的状态码,比如将claude渠道的400错误复写为500(用于重试),请勿滥用该功能,例如:') +
|
|
|
+ '\n' + JSON.stringify(STATUS_CODE_MAPPING_EXAMPLE, null, 2)}
|
|
|
+ name="status_code_mapping"
|
|
|
+ onChange={(value) => {
|
|
|
+ handleInputChange('status_code_mapping', value);
|
|
|
+ }}
|
|
|
+ autosize
|
|
|
+ value={inputs.status_code_mapping}
|
|
|
+ autoComplete="new-password"
|
|
|
+ />
|
|
|
+ <Typography.Text
|
|
|
+ style={{
|
|
|
+ color: 'rgba(var(--semi-blue-5), 1)',
|
|
|
+ userSelect: 'none',
|
|
|
+ cursor: 'pointer'
|
|
|
+ }}
|
|
|
+ onClick={() => {
|
|
|
+ handleInputChange(
|
|
|
+ 'status_code_mapping',
|
|
|
+ JSON.stringify(STATUS_CODE_MAPPING_EXAMPLE, null, 2)
|
|
|
+ );
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ {t('填入模板')}
|
|
|
+ </Typography.Text>
|
|
|
</Spin>
|
|
|
</SideSheet>
|
|
|
</>
|