refactor: 使用 ConfirmDialog 组件替代原生 confirm() 对话框
- EditAccountModal 和 CreateAccountModal 使用 ConfirmDialog 组件 - 保存 pending payload 供确认后重试 - 添加 mixedChannelWarningTitle 翻译 Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
This commit is contained in:
@@ -1615,6 +1615,18 @@
|
||||
</div>
|
||||
</template>
|
||||
</BaseDialog>
|
||||
|
||||
<!-- Mixed Channel Warning Dialog -->
|
||||
<ConfirmDialog
|
||||
:show="showMixedChannelWarning"
|
||||
:title="t('admin.accounts.mixedChannelWarningTitle')"
|
||||
:message="mixedChannelWarningDetails ? t('admin.accounts.mixedChannelWarning', mixedChannelWarningDetails) : ''"
|
||||
:confirm-text="t('common.confirm')"
|
||||
:cancel-text="t('common.cancel')"
|
||||
:danger="true"
|
||||
@confirm="handleMixedChannelConfirm"
|
||||
@cancel="handleMixedChannelCancel"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
@@ -1634,6 +1646,7 @@ import { useGeminiOAuth } from '@/composables/useGeminiOAuth'
|
||||
import { useAntigravityOAuth } from '@/composables/useAntigravityOAuth'
|
||||
import type { Proxy, Group, AccountPlatform, AccountType } from '@/types'
|
||||
import BaseDialog from '@/components/common/BaseDialog.vue'
|
||||
import ConfirmDialog from '@/components/common/ConfirmDialog.vue'
|
||||
import Icon from '@/components/icons/Icon.vue'
|
||||
import ProxySelector from '@/components/common/ProxySelector.vue'
|
||||
import GroupSelector from '@/components/common/GroupSelector.vue'
|
||||
@@ -1760,6 +1773,11 @@ const tempUnschedEnabled = ref(false)
|
||||
const tempUnschedRules = ref<TempUnschedRuleForm[]>([])
|
||||
const geminiOAuthType = ref<'code_assist' | 'google_one' | 'ai_studio'>('google_one')
|
||||
const geminiAIStudioOAuthEnabled = ref(false)
|
||||
|
||||
// Mixed channel warning dialog state
|
||||
const showMixedChannelWarning = ref(false)
|
||||
const mixedChannelWarningDetails = ref<{ groupName: string; currentPlatform: string; otherPlatform: string } | null>(null)
|
||||
const pendingCreatePayload = ref<any>(null)
|
||||
const showAdvancedOAuth = ref(false)
|
||||
const showGeminiHelpDialog = ref(false)
|
||||
|
||||
@@ -2158,11 +2176,7 @@ const handleClose = () => {
|
||||
}
|
||||
|
||||
// Helper function to create account with mixed channel warning handling
|
||||
const doCreateAccount = async (payload: any, confirmMixedChannelRisk = false) => {
|
||||
if (confirmMixedChannelRisk) {
|
||||
payload.confirm_mixed_channel_risk = true
|
||||
}
|
||||
|
||||
const doCreateAccount = async (payload: any) => {
|
||||
submitting.value = true
|
||||
try {
|
||||
await adminAPI.accounts.create(payload)
|
||||
@@ -2173,22 +2187,13 @@ const doCreateAccount = async (payload: any, confirmMixedChannelRisk = false) =>
|
||||
// Handle 409 mixed_channel_warning - show confirmation dialog
|
||||
if (error.response?.status === 409 && error.response?.data?.error === 'mixed_channel_warning') {
|
||||
const details = error.response.data.details || {}
|
||||
const groupName = details.group_name || 'Unknown'
|
||||
const currentPlatform = details.current_platform || 'Unknown'
|
||||
const otherPlatform = details.other_platform || 'Unknown'
|
||||
|
||||
const confirmMessage = t('admin.accounts.mixedChannelWarning', {
|
||||
groupName,
|
||||
currentPlatform,
|
||||
otherPlatform
|
||||
})
|
||||
|
||||
if (confirm(confirmMessage)) {
|
||||
// Retry with confirmation flag
|
||||
submitting.value = false
|
||||
await doCreateAccount(payload, true)
|
||||
return
|
||||
mixedChannelWarningDetails.value = {
|
||||
groupName: details.group_name || 'Unknown',
|
||||
currentPlatform: details.current_platform || 'Unknown',
|
||||
otherPlatform: details.other_platform || 'Unknown'
|
||||
}
|
||||
pendingCreatePayload.value = payload
|
||||
showMixedChannelWarning.value = true
|
||||
} else {
|
||||
appStore.showError(error.response?.data?.detail || t('admin.accounts.failedToCreate'))
|
||||
}
|
||||
@@ -2197,6 +2202,32 @@ const doCreateAccount = async (payload: any, confirmMixedChannelRisk = false) =>
|
||||
}
|
||||
}
|
||||
|
||||
// Handle mixed channel warning confirmation
|
||||
const handleMixedChannelConfirm = async () => {
|
||||
showMixedChannelWarning.value = false
|
||||
if (pendingCreatePayload.value) {
|
||||
pendingCreatePayload.value.confirm_mixed_channel_risk = true
|
||||
submitting.value = true
|
||||
try {
|
||||
await adminAPI.accounts.create(pendingCreatePayload.value)
|
||||
appStore.showSuccess(t('admin.accounts.accountCreated'))
|
||||
emit('created')
|
||||
handleClose()
|
||||
} catch (error: any) {
|
||||
appStore.showError(error.response?.data?.detail || t('admin.accounts.failedToCreate'))
|
||||
} finally {
|
||||
submitting.value = false
|
||||
pendingCreatePayload.value = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const handleMixedChannelCancel = () => {
|
||||
showMixedChannelWarning.value = false
|
||||
pendingCreatePayload.value = null
|
||||
mixedChannelWarningDetails.value = null
|
||||
}
|
||||
|
||||
const handleSubmit = async () => {
|
||||
// For OAuth-based type, handle OAuth flow (goes to step 2)
|
||||
if (isOAuthFlow.value) {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<form
|
||||
v-if="account"
|
||||
id="edit-account-form"
|
||||
@submit.prevent="() => handleSubmit()"
|
||||
@submit.prevent="handleSubmit"
|
||||
class="space-y-5"
|
||||
>
|
||||
<div>
|
||||
@@ -821,6 +821,18 @@
|
||||
</div>
|
||||
</template>
|
||||
</BaseDialog>
|
||||
|
||||
<!-- Mixed Channel Warning Dialog -->
|
||||
<ConfirmDialog
|
||||
:show="showMixedChannelWarning"
|
||||
:title="t('admin.accounts.mixedChannelWarningTitle')"
|
||||
:message="mixedChannelWarningDetails ? t('admin.accounts.mixedChannelWarning', mixedChannelWarningDetails) : ''"
|
||||
:confirm-text="t('common.confirm')"
|
||||
:cancel-text="t('common.cancel')"
|
||||
:danger="true"
|
||||
@confirm="handleMixedChannelConfirm"
|
||||
@cancel="handleMixedChannelCancel"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
@@ -831,6 +843,7 @@ import { useAuthStore } from '@/stores/auth'
|
||||
import { adminAPI } from '@/api/admin'
|
||||
import type { Account, Proxy, Group } from '@/types'
|
||||
import BaseDialog from '@/components/common/BaseDialog.vue'
|
||||
import ConfirmDialog from '@/components/common/ConfirmDialog.vue'
|
||||
import Select from '@/components/common/Select.vue'
|
||||
import Icon from '@/components/icons/Icon.vue'
|
||||
import ProxySelector from '@/components/common/ProxySelector.vue'
|
||||
@@ -897,6 +910,11 @@ const mixedScheduling = ref(false) // For antigravity accounts: enable mixed sch
|
||||
const tempUnschedEnabled = ref(false)
|
||||
const tempUnschedRules = ref<TempUnschedRuleForm[]>([])
|
||||
|
||||
// Mixed channel warning dialog state
|
||||
const showMixedChannelWarning = ref(false)
|
||||
const mixedChannelWarningDetails = ref<{ groupName: string; currentPlatform: string; otherPlatform: string } | null>(null)
|
||||
const pendingUpdatePayload = ref<Record<string, unknown> | null>(null)
|
||||
|
||||
// Quota control state (Anthropic OAuth/SetupToken only)
|
||||
const windowCostEnabled = ref(false)
|
||||
const windowCostLimit = ref<number | null>(null)
|
||||
@@ -1294,17 +1312,12 @@ const handleClose = () => {
|
||||
emit('close')
|
||||
}
|
||||
|
||||
const handleSubmit = async (confirmMixedChannelRisk = false) => {
|
||||
const handleSubmit = async () => {
|
||||
if (!props.account) return
|
||||
|
||||
submitting.value = true
|
||||
const updatePayload: Record<string, unknown> = { ...form }
|
||||
try {
|
||||
const updatePayload: Record<string, unknown> = { ...form }
|
||||
|
||||
// Add confirmation flag if user confirmed mixed channel risk
|
||||
if (confirmMixedChannelRisk) {
|
||||
updatePayload.confirm_mixed_channel_risk = true
|
||||
}
|
||||
// 后端期望 proxy_id: 0 表示清除代理,而不是 null
|
||||
if (updatePayload.proxy_id === null) {
|
||||
updatePayload.proxy_id = 0
|
||||
@@ -1423,22 +1436,13 @@ const handleSubmit = async (confirmMixedChannelRisk = false) => {
|
||||
// Handle 409 mixed_channel_warning - show confirmation dialog
|
||||
if (error.response?.status === 409 && error.response?.data?.error === 'mixed_channel_warning') {
|
||||
const details = error.response.data.details || {}
|
||||
const groupName = details.group_name || 'Unknown'
|
||||
const currentPlatform = details.current_platform || 'Unknown'
|
||||
const otherPlatform = details.other_platform || 'Unknown'
|
||||
|
||||
const confirmMessage = t('admin.accounts.mixedChannelWarning', {
|
||||
groupName,
|
||||
currentPlatform,
|
||||
otherPlatform
|
||||
})
|
||||
|
||||
if (confirm(confirmMessage)) {
|
||||
// Retry with confirmation flag
|
||||
submitting.value = false
|
||||
await handleSubmit(true)
|
||||
return
|
||||
mixedChannelWarningDetails.value = {
|
||||
groupName: details.group_name || 'Unknown',
|
||||
currentPlatform: details.current_platform || 'Unknown',
|
||||
otherPlatform: details.other_platform || 'Unknown'
|
||||
}
|
||||
pendingUpdatePayload.value = updatePayload
|
||||
showMixedChannelWarning.value = true
|
||||
} else {
|
||||
appStore.showError(error.response?.data?.message || error.response?.data?.detail || t('admin.accounts.failedToUpdate'))
|
||||
}
|
||||
@@ -1446,4 +1450,30 @@ const handleSubmit = async (confirmMixedChannelRisk = false) => {
|
||||
submitting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// Handle mixed channel warning confirmation
|
||||
const handleMixedChannelConfirm = async () => {
|
||||
showMixedChannelWarning.value = false
|
||||
if (pendingUpdatePayload.value && props.account) {
|
||||
pendingUpdatePayload.value.confirm_mixed_channel_risk = true
|
||||
submitting.value = true
|
||||
try {
|
||||
await adminAPI.accounts.update(props.account.id, pendingUpdatePayload.value)
|
||||
appStore.showSuccess(t('admin.accounts.accountUpdated'))
|
||||
emit('updated')
|
||||
handleClose()
|
||||
} catch (error: any) {
|
||||
appStore.showError(error.response?.data?.message || error.response?.data?.detail || t('admin.accounts.failedToUpdate'))
|
||||
} finally {
|
||||
submitting.value = false
|
||||
pendingUpdatePayload.value = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const handleMixedChannelCancel = () => {
|
||||
showMixedChannelWarning.value = false
|
||||
pendingUpdatePayload.value = null
|
||||
mixedChannelWarningDetails.value = null
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1306,6 +1306,7 @@ export default {
|
||||
accountUpdated: 'Account updated successfully',
|
||||
failedToCreate: 'Failed to create account',
|
||||
failedToUpdate: 'Failed to update account',
|
||||
mixedChannelWarningTitle: 'Mixed Channel Warning',
|
||||
mixedChannelWarning: 'Warning: Group "{groupName}" contains both {currentPlatform} and {otherPlatform} accounts. Mixing different channels may cause thinking block signature validation issues, which will fallback to non-thinking mode. Are you sure you want to continue?',
|
||||
pleaseEnterAccountName: 'Please enter account name',
|
||||
pleaseEnterApiKey: 'Please enter API Key',
|
||||
|
||||
@@ -1439,6 +1439,7 @@ export default {
|
||||
accountUpdated: '账号更新成功',
|
||||
failedToCreate: '创建账号失败',
|
||||
failedToUpdate: '更新账号失败',
|
||||
mixedChannelWarningTitle: '混合渠道警告',
|
||||
mixedChannelWarning: '警告:分组 "{groupName}" 中同时包含 {currentPlatform} 和 {otherPlatform} 账号。混合使用不同渠道可能导致 thinking block 签名验证问题,会自动回退到非 thinking 模式。确定要继续吗?',
|
||||
pleaseEnterAccountName: '请输入账号名称',
|
||||
pleaseEnterApiKey: '请输入 API Key',
|
||||
|
||||
Reference in New Issue
Block a user