refactor(frontend): UI/UX改进和组件优化

- DataTable组件操作列自适应
- 优化各种Modal弹窗
- 统一API调用方式(AbortSignal)
- 添加全局订阅状态管理
- 优化各管理视图的交互和布局
- 修复国际化翻译问题
This commit is contained in:
IanShaw027
2025-12-28 01:00:06 +08:00
parent 9bbe468c91
commit 506cb21cb1
46 changed files with 1582 additions and 644 deletions

View File

@@ -186,6 +186,7 @@
:total="pagination.total"
:page-size="pagination.page_size"
@update:page="handlePageChange"
@update:pageSize="handlePageSizeChange"
/>
<!-- Batch Actions -->
@@ -542,6 +543,8 @@ const pagination = reactive({
pages: 0
})
let abortController: AbortController | null = null
const showDeleteDialog = ref(false)
const showDeleteUnusedDialog = ref(false)
const deletingCode = ref<RedeemCode | null>(null)
@@ -556,21 +559,46 @@ const generateForm = reactive({
})
const loadCodes = async () => {
if (abortController) {
abortController.abort()
}
const currentController = new AbortController()
abortController = currentController
loading.value = true
try {
const response = await adminAPI.redeem.list(pagination.page, pagination.page_size, {
type: filters.type as RedeemCodeType,
status: filters.status as any,
search: searchQuery.value || undefined
})
const response = await adminAPI.redeem.list(
pagination.page,
pagination.page_size,
{
type: filters.type as RedeemCodeType,
status: filters.status as any,
search: searchQuery.value || undefined
},
{
signal: currentController.signal
}
)
if (currentController.signal.aborted) {
return
}
codes.value = response.items
pagination.total = response.total
pagination.pages = response.pages
} catch (error) {
} catch (error: any) {
if (
currentController.signal.aborted ||
error?.name === 'AbortError' ||
error?.code === 'ERR_CANCELED'
) {
return
}
appStore.showError(t('admin.redeem.failedToLoad'))
console.error('Error loading redeem codes:', error)
} finally {
loading.value = false
if (abortController === currentController && !currentController.signal.aborted) {
loading.value = false
abortController = null
}
}
}
@@ -588,6 +616,12 @@ const handlePageChange = (page: number) => {
loadCodes()
}
const handlePageSizeChange = (pageSize: number) => {
pagination.page_size = pageSize
pagination.page = 1
loadCodes()
}
const handleGenerateCodes = async () => {
// 订阅类型必须选择分组
if (generateForm.type === 'subscription' && !generateForm.group_id) {