Merge remote-tracking branch 'origin/pr/605'

This commit is contained in:
elky
2026-06-03 00:16:22 +08:00
7 changed files with 924 additions and 9 deletions
@@ -82,6 +82,7 @@
:auto-delete-expired-keys="systemConfig.auto_delete_expired_keys"
:enable-format-conversion="systemConfig.enable_format_conversion"
:enable-openai-image-sync-heartbeat="systemConfig.enable_openai_image_sync_heartbeat"
:enable-standard-text-sync-heartbeat="systemConfig.enable_standard_text_sync_heartbeat"
:loading="systemConfigLoading || basicConfigLoading"
:has-changes="hasBasicConfigChanges"
@save="saveBasicConfig"
@@ -106,6 +107,7 @@
@update:auto-delete-expired-keys="systemConfig.auto_delete_expired_keys = $event"
@update:enable-format-conversion="systemConfig.enable_format_conversion = $event"
@update:enable-openai-image-sync-heartbeat="systemConfig.enable_openai_image_sync_heartbeat = $event"
@update:enable-standard-text-sync-heartbeat="systemConfig.enable_standard_text_sync_heartbeat = $event"
/>
<!-- 请求记录配置 -->
@@ -172,6 +172,27 @@
</div>
</div>
<div class="flex items-center h-full">
<div class="flex items-center space-x-2">
<Checkbox
id="enable-standard-text-sync-heartbeat"
:checked="enableStandardTextSyncHeartbeat"
@update:checked="$emit('update:enableStandardTextSyncHeartbeat', $event)"
/>
<div>
<Label
for="enable-standard-text-sync-heartbeat"
class="cursor-pointer"
>
标准文本非流式心跳
</Label>
<p class="text-xs text-muted-foreground">
开启后标准文本非流式接口外层 HTTP 状态固定为 200,上游失败需读取响应体 error.upstream_status
</p>
</div>
</div>
</div>
<div class="md:col-span-2 grid grid-cols-1 md:grid-cols-2 gap-4 border-t pt-5">
<div class="flex items-center h-full">
<div class="flex items-center space-x-2">
@@ -498,6 +519,7 @@ defineProps<{
autoDeleteExpiredKeys: boolean
enableFormatConversion: boolean
enableOpenaiImageSyncHeartbeat: boolean
enableStandardTextSyncHeartbeat: boolean
loading: boolean
hasChanges: boolean
}>()
@@ -525,5 +547,6 @@ defineEmits<{
'update:autoDeleteExpiredKeys': [value: boolean]
'update:enableFormatConversion': [value: boolean]
'update:enableOpenaiImageSyncHeartbeat': [value: boolean]
'update:enableStandardTextSyncHeartbeat': [value: boolean]
}>()
</script>
@@ -1,13 +1,14 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'
const { getSystemConfigMock } = vi.hoisted(() => ({
const { getSystemConfigMock, updateSystemConfigMock } = vi.hoisted(() => ({
getSystemConfigMock: vi.fn(),
updateSystemConfigMock: vi.fn(),
}))
vi.mock('@/api/admin', () => ({
adminApi: {
getSystemConfig: getSystemConfigMock,
updateSystemConfig: vi.fn(),
updateSystemConfig: updateSystemConfigMock,
getSystemVersion: vi.fn(),
},
}))
@@ -40,6 +41,7 @@ interface DeferredConfigResponse {
describe('useSystemConfig', () => {
beforeEach(() => {
getSystemConfigMock.mockReset()
updateSystemConfigMock.mockReset()
})
it('loads config keys in parallel and keeps change detection disabled until the baseline is ready', async () => {
@@ -53,6 +55,7 @@ describe('useSystemConfig', () => {
expect(getSystemConfigMock.mock.calls.map(([key]) => key)).toContain('request_record_level')
expect(getSystemConfigMock.mock.calls.map(([key]) => key)).toContain('proxy_node_metrics_cleanup_batch_size')
expect(getSystemConfigMock.mock.calls.map(([key]) => key)).toContain('enable_standard_text_sync_heartbeat')
state.systemConfig.value.request_record_level = 'headers'
expect(state.systemConfigLoading.value).toBe(true)
@@ -74,4 +77,29 @@ describe('useSystemConfig', () => {
state.systemConfig.value.request_record_level = 'full'
expect(state.hasLogConfigChanges.value).toBe(true)
})
it('loads and saves the standard text sync heartbeat flag as a basic config item', async () => {
getSystemConfigMock.mockImplementation(async (key: string) => ({
key,
value: key === 'enable_standard_text_sync_heartbeat' ? false : undefined,
is_set: key === 'enable_standard_text_sync_heartbeat',
}))
updateSystemConfigMock.mockResolvedValue({})
const state = useSystemConfig()
await state.loadSystemConfig()
expect(state.systemConfig.value.enable_standard_text_sync_heartbeat).toBe(false)
state.systemConfig.value.enable_standard_text_sync_heartbeat = true
expect(state.hasBasicConfigChanges.value).toBe(true)
await state.saveBasicConfig()
expect(updateSystemConfigMock).toHaveBeenCalledWith(
'enable_standard_text_sync_heartbeat',
true,
'标准文本非流式心跳开关:开启后外层 HTTP 状态固定为 200,上游失败写入响应体'
)
expect(state.hasBasicConfigChanges.value).toBe(false)
})
})
@@ -35,6 +35,8 @@ export interface SystemConfig {
enable_format_conversion: boolean
// 同步生图心跳
enable_openai_image_sync_heartbeat: boolean
// 标准文本非流式心跳
enable_standard_text_sync_heartbeat: boolean
// 请求记录
request_record_level: string
max_request_body_size: number
@@ -89,6 +91,8 @@ const CONFIG_KEYS = [
'enable_format_conversion',
// 同步生图心跳
'enable_openai_image_sync_heartbeat',
// 标准文本非流式心跳
'enable_standard_text_sync_heartbeat',
// 请求记录
'request_record_level',
'max_request_body_size',
@@ -145,6 +149,8 @@ function createDefaultConfig(): SystemConfig {
enable_format_conversion: false,
// 同步生图心跳
enable_openai_image_sync_heartbeat: false,
// 标准文本非流式心跳
enable_standard_text_sync_heartbeat: false,
// 请求记录
request_record_level: 'basic',
max_request_body_size: 1048576,
@@ -230,7 +236,10 @@ export function useSystemConfig() {
originalConfig.value.registration_privacy_policy_version ||
systemConfig.value.auto_delete_expired_keys !== originalConfig.value.auto_delete_expired_keys ||
systemConfig.value.enable_format_conversion !== originalConfig.value.enable_format_conversion ||
systemConfig.value.enable_openai_image_sync_heartbeat !== originalConfig.value.enable_openai_image_sync_heartbeat
systemConfig.value.enable_openai_image_sync_heartbeat !==
originalConfig.value.enable_openai_image_sync_heartbeat ||
systemConfig.value.enable_standard_text_sync_heartbeat !==
originalConfig.value.enable_standard_text_sync_heartbeat
)
})
@@ -513,6 +522,11 @@ export function useSystemConfig() {
value: systemConfig.value.enable_openai_image_sync_heartbeat,
description: '同步生图心跳开关:开启后外层 HTTP 状态固定为 200,上游失败写入响应体',
},
{
key: 'enable_standard_text_sync_heartbeat',
value: systemConfig.value.enable_standard_text_sync_heartbeat,
description: '标准文本非流式心跳开关:开启后外层 HTTP 状态固定为 200,上游失败写入响应体',
},
]
const turnstileSecret = systemConfig.value.turnstile_secret_key.trim()
if (turnstileSecret) {
@@ -565,6 +579,8 @@ export function useSystemConfig() {
systemConfig.value.enable_format_conversion
originalConfig.value.enable_openai_image_sync_heartbeat =
systemConfig.value.enable_openai_image_sync_heartbeat
originalConfig.value.enable_standard_text_sync_heartbeat =
systemConfig.value.enable_standard_text_sync_heartbeat
}
success('基础配置已保存')
} catch (err) {