mirror of
https://gitee.com/wanwujie/sub2api
synced 2026-05-05 13:40:44 +08:00
fix: close admin settings review gaps
This commit is contained in:
@@ -318,6 +318,7 @@ const pagination = reactive({
|
||||
pageSize: 20,
|
||||
total: 0,
|
||||
})
|
||||
const knownReportTypes = ref<string[]>([])
|
||||
|
||||
const columns: Column[] = [
|
||||
{ key: 'status', label: text('状态', 'Status') },
|
||||
@@ -330,12 +331,16 @@ const columns: Column[] = [
|
||||
]
|
||||
|
||||
const reportTypeOptions = computed(() =>
|
||||
Object.entries(summary.value.by_type)
|
||||
.sort(([left], [right]) => left.localeCompare(right))
|
||||
.map(([value, count]) => ({
|
||||
value,
|
||||
label: `${value} (${count})`,
|
||||
}))
|
||||
knownReportTypes.value
|
||||
.slice()
|
||||
.sort((left, right) => left.localeCompare(right))
|
||||
.map((value) => {
|
||||
const count = summary.value.by_type[value]
|
||||
return {
|
||||
value,
|
||||
label: count === undefined ? value : `${value} (${count})`,
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
const canResolve = computed(() =>
|
||||
@@ -347,10 +352,22 @@ const canResolve = computed(() =>
|
||||
)
|
||||
)
|
||||
|
||||
const mergeKnownReportTypes = (...values: Array<string | null | undefined>) => {
|
||||
const merged = new Set(knownReportTypes.value)
|
||||
for (const value of values) {
|
||||
const normalized = value?.trim()
|
||||
if (normalized) {
|
||||
merged.add(normalized)
|
||||
}
|
||||
}
|
||||
knownReportTypes.value = Array.from(merged)
|
||||
}
|
||||
|
||||
const loadSummary = async () => {
|
||||
summaryLoading.value = true
|
||||
try {
|
||||
summary.value = await adminAPI.users.getAuthIdentityMigrationReportSummary()
|
||||
mergeKnownReportTypes(...Object.keys(summary.value.by_type))
|
||||
} catch (error) {
|
||||
console.error('Failed to load auth identity migration report summary:', error)
|
||||
appStore.showError(text('加载 migration reports 汇总失败', 'Failed to load migration report summary'))
|
||||
@@ -370,6 +387,7 @@ const loadReports = async () => {
|
||||
|
||||
reports.value = response.items
|
||||
pagination.total = response.total
|
||||
mergeKnownReportTypes(filters.reportType, ...response.items.map((report) => report.report_type))
|
||||
|
||||
if (selectedReport.value) {
|
||||
const refreshed = response.items.find((report) => report.id === selectedReport.value?.id) ?? null
|
||||
|
||||
@@ -2728,8 +2728,8 @@
|
||||
<p class="mt-1.5 text-xs text-gray-400">
|
||||
{{
|
||||
localText(
|
||||
'留空表示自动路由;仅允许当前系统支持的官方或易支付来源。',
|
||||
'Leave blank for automatic routing. Only supported official or EasyPay sources are allowed.'
|
||||
'启用后必须明确选择一个来源;未配置状态不会对外展示该支付方式。',
|
||||
'Choose an explicit source before enabling the method. Not configured methods are not exposed.'
|
||||
)
|
||||
}}
|
||||
</p>
|
||||
@@ -3450,6 +3450,28 @@ function setPaymentVisibleMethodSource(
|
||||
form.payment_visible_method_wxpay_source = normalized
|
||||
}
|
||||
|
||||
function validatePaymentVisibleMethodSelections(): boolean {
|
||||
for (const visibleMethod of paymentVisibleMethodCards.value) {
|
||||
if (!getPaymentVisibleMethodEnabled(visibleMethod.key)) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (getPaymentVisibleMethodSource(visibleMethod.key)) {
|
||||
continue
|
||||
}
|
||||
|
||||
appStore.showError(
|
||||
localText(
|
||||
`${visibleMethod.title} 已启用,请先选择支付来源`,
|
||||
`Select a payment source before enabling ${visibleMethod.title}`
|
||||
)
|
||||
)
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Proxies for web search emulation ProxySelector
|
||||
const webSearchProxies = ref<Proxy[]>([])
|
||||
|
||||
@@ -3979,6 +4001,10 @@ async function saveSettings() {
|
||||
}
|
||||
}
|
||||
|
||||
if (!validatePaymentVisibleMethodSelections()) {
|
||||
return
|
||||
}
|
||||
|
||||
// Validate URL fields — novalidate disables browser-native checks, so we validate here
|
||||
const isValidHttpUrl = (url: string): boolean => {
|
||||
if (!url) return true
|
||||
|
||||
@@ -240,4 +240,21 @@ describe('AuthIdentityMigrationReportsView', () => {
|
||||
reportType: '',
|
||||
})
|
||||
})
|
||||
|
||||
it('keeps report type filter options available from list data when summary fails', async () => {
|
||||
getAuthIdentityMigrationReportSummary.mockRejectedValueOnce(new Error('summary failed'))
|
||||
listAuthIdentityMigrationReports.mockResolvedValueOnce(listResponse)
|
||||
|
||||
const wrapper = mountView()
|
||||
|
||||
await flushPromises()
|
||||
|
||||
const options = wrapper
|
||||
.get('[data-test="report-type-filter"]')
|
||||
.findAll('option')
|
||||
.map((node) => node.element.value)
|
||||
|
||||
expect(showError).toHaveBeenCalled()
|
||||
expect(options).toContain('oidc_synthetic_email_requires_manual_recovery')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -449,4 +449,27 @@ describe('admin SettingsView payment visible method controls', () => {
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it('blocks saving when a visible payment method is enabled without a source', async () => {
|
||||
const wrapper = mountView()
|
||||
|
||||
await flushPromises()
|
||||
await openPaymentTab(wrapper)
|
||||
|
||||
const paymentSourceSelects = wrapper
|
||||
.findAll('select.select-stub')
|
||||
.filter((node) => ['alipay', 'wxpay'].includes(node.attributes('data-placeholder')))
|
||||
|
||||
const alipaySelect = paymentSourceSelects.find(
|
||||
(node) => node.attributes('data-placeholder') === 'alipay'
|
||||
)
|
||||
|
||||
await alipaySelect?.setValue('')
|
||||
await wrapper.find('form').trigger('submit.prevent')
|
||||
await flushPromises()
|
||||
|
||||
expect(updateSettings).not.toHaveBeenCalled()
|
||||
expect(showError).toHaveBeenCalled()
|
||||
expect(String(showError.mock.calls.at(-1)?.[0] ?? '')).toContain('支付来源')
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user