feat: 实现设置账号并发数功能(支持 bulk-update 与 fallback 逐个更新)

This commit is contained in:
liumangmang
2026-07-02 09:48:59 +08:00
parent a296525d4e
commit 608ef00920
7 changed files with 570 additions and 5 deletions
+11
View File
@@ -343,6 +343,15 @@ export interface CleanupInvalidAccountsItem {
message: string
}
export interface SetConcurrencyItem {
account_id: string
account_name: string | null
old_concurrency: number | null
target_concurrency: number
status: string
message: string
}
export const websitesApi = {
list: () => api.get<WebsiteData[]>('/api/websites'),
create: (data: WebsiteForm) => api.post<WebsiteData>('/api/websites', data),
@@ -374,6 +383,8 @@ export const websitesApi = {
api.post<{ success: boolean; message: string; items: CleanupInvalidAccountsItem[] }>(`/api/websites/${id}/accounts/cleanup-invalid/preview`),
cleanupExecute: (id: number) =>
api.post<{ success: boolean; message: string; items: CleanupInvalidAccountsItem[] }>(`/api/websites/${id}/accounts/cleanup-invalid/execute`),
setConcurrency: (id: number, data: { concurrency: number }) =>
api.post<{ success: boolean; message: string; items: SetConcurrencyItem[] }>(`/api/websites/${id}/accounts/set-concurrency`, data),
listBindings: () => api.get<GroupBindingData[]>('/api/group-bindings'),
createBinding: (data: GroupBindingForm) => api.post<GroupBindingData>('/api/group-bindings', data),
updateBinding: (id: number, data: Partial<GroupBindingForm>) => api.put<GroupBindingData>(`/api/group-bindings/${id}`, data),
+141 -2
View File
@@ -133,6 +133,15 @@
>
清理失效账号
</el-button>
<el-button
size="small"
text
:disabled="!selectedWebsite"
@click="openConcurrencyDialog"
title="一键设置当前网站已导入账号的并发数"
>
设置账号并发
</el-button>
<el-button size="small" text :disabled="websites.length === 0" @click="openBindingCreate(selectedWebsite || websites[0])">新增绑定</el-button>
</div>
<div class="binding-list" v-loading="bindingLoading">
@@ -841,6 +850,87 @@
</div>
</template>
</el-dialog>
<!-- 设置账号并发数弹窗 -->
<el-dialog
v-model="concurrencyDialog"
title="一键设置账号并发数"
width="850px"
destroy-on-close
>
<div v-if="!concurrencyHasExecuted">
<el-alert
title="功能说明"
type="warning"
show-icon
:closable="false"
style="margin-bottom: 15px;"
>
<div style="font-size: 13px; line-height: 1.5;">
该操作将<strong>仅修改由 SmartUp 导入并绑定到当前网站的账号并发数</strong>不会影响任何由目标站手工创建的其他账号<br />
如果目标站接口支持批量更新bulk-update系统将一次性批量设置否则将自动退回至逐个请求更新模式
</div>
</el-alert>
<el-form label-width="120px" style="margin-top: 20px;">
<el-form-item label="目标并发数">
<el-input-number
v-model="targetConcurrency"
:min="1"
:max="1000"
:step="10"
style="width: 200px;"
/>
<div style="font-size: 12px; color: var(--el-text-color-secondary); margin-top: 5px;">
请输入 1 1000 之间的并发值推荐设置为 100
</div>
</el-form-item>
</el-form>
</div>
<div v-else>
<div style="margin-bottom: 15px; font-weight: bold; color: var(--el-color-primary);">
{{ concurrencyMessage }}
</div>
<el-table :data="concurrencyResults" border stripe size="small" style="width: 100%; max-height: 400px; overflow-y: auto;">
<el-table-column prop="account_id" label="账号 ID" width="150" />
<el-table-column prop="account_name" label="账号名" min-width="180" show-overflow-tooltip />
<el-table-column prop="old_concurrency" label="当前并发" width="110" align="center">
<template #default="{ row }">
<span v-if="row.old_concurrency !== null">{{ row.old_concurrency }}</span>
<span v-else class="text-muted">-</span>
</template>
</el-table-column>
<el-table-column prop="target_concurrency" label="目标并发" width="110" align="center" />
<el-table-column prop="status" label="状态" width="100" align="center">
<template #default="{ row }">
<el-tag v-if="row.status === 'success'" type="success" size="small">成功</el-tag>
<el-tag v-else-if="row.status === 'skipped'" type="warning" size="small">跳过</el-tag>
<el-tag v-else-if="row.status === 'failed'" type="danger" size="small">失败</el-tag>
<el-tag v-else type="info" size="small">{{ row.status }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="message" label="说明/原因" min-width="150" show-overflow-tooltip />
</el-table>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="concurrencyDialog = false" :disabled="concurrencyExecuting">
{{ concurrencyHasExecuted ? '关闭' : '取消' }}
</el-button>
<el-button
v-if="!concurrencyHasExecuted"
type="primary"
:loading="concurrencyExecuting"
@click="submitSetConcurrency"
>
确认执行
</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
@@ -866,6 +956,7 @@ import {
type WebsiteSyncLog,
type OrganizeGroupsItem,
type CleanupInvalidAccountsItem,
type SetConcurrencyItem,
} from '@/api'
const websites = ref<(WebsiteData & { _testing?: boolean })[]>([])
@@ -1004,7 +1095,7 @@ const importAccountsForm = ref({
account_name_prefix: 'SmartUp',
default_platform: 'openai',
platform_mode: 'auto',
concurrency: 10,
concurrency: 100,
priority: 1,
auto_priority_by_rate: true,
})
@@ -1021,6 +1112,13 @@ const cleanupExecuting = ref(false)
const cleanupHasExecuted = ref(false)
const cleanupItems = ref<CleanupInvalidAccountsItem[]>([])
const concurrencyDialog = ref(false)
const concurrencyExecuting = ref(false)
const concurrencyHasExecuted = ref(false)
const targetConcurrency = ref(100)
const concurrencyMessage = ref('')
const concurrencyResults = ref<SetConcurrencyItem[]>([])
const upstreamGroupOptions = computed(() => {
const rows: Array<{ key: string; label: string; rate: string | number; source: BindingSourceGroup }> = []
for (const upstream of upstreams.value) {
@@ -1727,6 +1825,47 @@ async function executeCleanup() {
}
}
function openConcurrencyDialog() {
if (!selectedWebsite.value) return
targetConcurrency.value = 100
concurrencyHasExecuted.value = false
concurrencyResults.value = []
concurrencyMessage.value = ''
concurrencyDialog.value = true
}
async function submitSetConcurrency() {
if (!selectedWebsite.value) return
try {
await ElMessageBox.confirm(
`确认将当前网站中由 SmartUp 导入账号的并发数一键设置为 ${targetConcurrency.value}`,
'确认修改并发数',
{ type: 'warning' }
)
} catch {
return
}
concurrencyExecuting.value = true
try {
const res = await websitesApi.setConcurrency(selectedWebsite.value.id, {
concurrency: targetConcurrency.value
})
concurrencyMessage.value = res.data.message
concurrencyResults.value = res.data.items
concurrencyHasExecuted.value = true
if (res.data.success) {
ElMessage.success('设置完成')
} else {
ElMessage.warning(res.data.message || '部分账号设置并发失败')
}
} catch (e: any) {
ElMessage.error(e.response?.data?.detail || '设置并发失败')
} finally {
concurrencyExecuting.value = false
}
}
async function toggleBinding(row: GroupBindingData) {
try {
await websitesApi.updateBinding(row.id, { enabled: row.enabled })
@@ -1797,7 +1936,7 @@ async function openImportAccounts(site?: WebsiteData | null) {
account_name_prefix: 'SmartUp',
default_platform: 'openai',
platform_mode: 'auto',
concurrency: 10,
concurrency: 100,
priority: 1,
auto_priority_by_rate: true,
}