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:
yml2213
2026-06-04 09:05:34 +08:00
co-authored by Claude Opus 4.7
parent 3534cffce1
commit c9397635e2
47 changed files with 9406 additions and 0 deletions
@@ -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