feat: P3阶段完成 - 全部模块迁移完成 🎉
## P3.1: 争议仲裁模块(disputes)✅ - API: disputes.ts - 模块导出 ## P3.2: 卖家中心模块(seller)✅ - Views: 4个页面 - Composables: usePublishForm, usePublishDraft - 模块导出 ## P3.3: 管理后台模块(admin)✅ - API: 8个文件(adminAuth, adminDashboard, adminUsers等) - Views: 15个管理页面 - Composables: useAdminTable, useAdminPaginatedTable - Components: 管理端组件 - 模块导出 --- ## 🎉 Features 架构迁移全部完成! ### 最终统计 - ✅ P0: shared(基础设施)- 22个文件 - ✅ P1: wallet, chats, orders - 24个文件 - ✅ P2: listings, auth - 35个文件 - ✅ P3: seller, disputes, admin - 47个文件 **总计:** 9个模块,128个文件完成迁移 ### 新架构 ``` frontend/src/ ├── features/ # 9个业务模块 ✅ │ ├── wallet/ ✅ │ ├── chats/ ✅ │ ├── orders/ ✅ (已重构) │ ├── listings/ ✅ │ ├── auth/ ✅ │ ├── seller/ ✅ │ ├── disputes/ ✅ │ └── admin/ ✅ └── shared/ ✅ ``` 下一步:清理旧文件、更新路由配置 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
3534cffce1
commit
c9397635e2
@@ -0,0 +1,52 @@
|
||||
import { ref, type Ref } from 'vue'
|
||||
|
||||
interface PaginatedResult<T> {
|
||||
items: T[]
|
||||
total: number
|
||||
}
|
||||
|
||||
interface AdminPaginatedTableOptions<T> {
|
||||
fetchFn: (page: number, pageSize: number) => Promise<PaginatedResult<T>>
|
||||
defaultPageSize?: number
|
||||
immediate?: boolean
|
||||
}
|
||||
|
||||
interface AdminPaginatedTableResult<T> {
|
||||
loading: Ref<boolean>
|
||||
data: Ref<T[]>
|
||||
total: Ref<number>
|
||||
currentPage: Ref<number>
|
||||
currentPageSize: Ref<number>
|
||||
load: () => Promise<void>
|
||||
handleSizeChange: () => void
|
||||
}
|
||||
|
||||
export function useAdminPaginatedTable<T>(options: AdminPaginatedTableOptions<T>): AdminPaginatedTableResult<T> {
|
||||
const loading = ref(false)
|
||||
const data = ref<T[]>([]) as Ref<T[]>
|
||||
const total = ref(0)
|
||||
const currentPage = ref(1)
|
||||
const currentPageSize = ref(options.defaultPageSize || 20)
|
||||
|
||||
async function load() {
|
||||
loading.value = true
|
||||
try {
|
||||
const result = await options.fetchFn(currentPage.value, currentPageSize.value)
|
||||
data.value = result.items
|
||||
total.value = result.total
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function handleSizeChange() {
|
||||
currentPage.value = 1
|
||||
load()
|
||||
}
|
||||
|
||||
if (options.immediate !== false) {
|
||||
load()
|
||||
}
|
||||
|
||||
return { loading, data, total, currentPage, currentPageSize, load, handleSizeChange }
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import { ref, type Ref } from 'vue'
|
||||
|
||||
interface AdminQueryOptions<T> {
|
||||
fetchFn: () => Promise<T>
|
||||
immediate?: boolean
|
||||
initialData?: T
|
||||
}
|
||||
|
||||
interface AdminQueryResult<T> {
|
||||
loading: Ref<boolean>
|
||||
error: Ref<string | null>
|
||||
data: Ref<T>
|
||||
load: () => Promise<void>
|
||||
}
|
||||
|
||||
export function useAdminQuery<T>(options: AdminQueryOptions<T>): AdminQueryResult<T> {
|
||||
const loading = ref(false)
|
||||
const error = ref<string | null>(null)
|
||||
const data = ref<T>(options.initialData as T) as Ref<T>
|
||||
|
||||
async function load() {
|
||||
loading.value = true
|
||||
error.value = null
|
||||
try {
|
||||
data.value = await options.fetchFn()
|
||||
} catch (e) {
|
||||
error.value = e instanceof Error ? e.message : '加载失败'
|
||||
console.error('Failed to load data:', e)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
if (options.immediate !== false) {
|
||||
load()
|
||||
}
|
||||
|
||||
return { loading, error, data, load }
|
||||
}
|
||||
|
||||
// 保持向后兼容
|
||||
export const useAdminTable = useAdminQuery
|
||||
Reference in New Issue
Block a user