feat(pickup): 店铺管理支持历史店铺可视化手动映射与一键批量清洗
- 数据库升级:新增 pickup_shop_mappings 映射别名表,并在 admin_pickups 增加 raw_shop_name 永久保留原始店铺录入值 - 后端映射能力:提供历史店铺聚合统计、单条/批量映射至目标标准店铺、映射规则撤销与提号单还原接口;新建提号时若录入已映射别名自动归一化 - 前端管理升级:PickupShopDialog 升级为双 Tab 结构,Tab 2「历史店铺映射与清洗」支持总览统计卡片、状态筛选、单条/批量映射清洗、一键设为标准店铺及撤销还原 - 验证方式:执行并通过全套代码门禁(scripts/check.sh:SQL约束、go vet/build/test、MySQL测试库覆盖率、vue大小、eslint、prettier、vue-tsc及vite构建)
This commit is contained in:
@@ -23,6 +23,7 @@ export interface AdminPickup {
|
||||
platform: string
|
||||
third_party_order_no: string
|
||||
shop_name: string
|
||||
raw_shop_name?: string
|
||||
account_source: PickupAccountSource
|
||||
source_channel: string
|
||||
settlement_mode: PickupSettlementMode
|
||||
@@ -194,6 +195,41 @@ export interface PickupShopQuery {
|
||||
status?: string
|
||||
}
|
||||
|
||||
export type PickupShopMappingStatus = 'standard' | 'mapped' | 'unmapped'
|
||||
|
||||
export interface PickupShopHistoricalItem {
|
||||
source_name: string
|
||||
count: number
|
||||
mapping_status: PickupShopMappingStatus
|
||||
target_shop_id?: number
|
||||
target_shop_name?: string
|
||||
remark?: string
|
||||
}
|
||||
|
||||
export interface PickupShopHistoricalStats {
|
||||
items: PickupShopHistoricalItem[]
|
||||
total_pickups: number
|
||||
total_shops: number
|
||||
standard_count: number
|
||||
mapped_count: number
|
||||
unmapped_count: number
|
||||
}
|
||||
|
||||
export interface MapHistoricalShopsRequest {
|
||||
from_shop_names: string[]
|
||||
target_shop_name: string
|
||||
create_target_missing?: boolean
|
||||
target_platform?: string
|
||||
remark?: string
|
||||
}
|
||||
|
||||
export interface MapHistoricalShopsResult {
|
||||
updated_pickups_count: number
|
||||
target_shop_name: string
|
||||
target_shop_id: number
|
||||
created_standard_shop: boolean
|
||||
}
|
||||
|
||||
function cleanParams(query: object) {
|
||||
return Object.fromEntries(
|
||||
Object.entries(query).filter(([, value]) => value !== '' && value !== undefined)
|
||||
@@ -339,3 +375,26 @@ export async function deletePickupShop(id: number) {
|
||||
)
|
||||
return data.data
|
||||
}
|
||||
|
||||
export async function fetchHistoricalShopStats() {
|
||||
const { data } = await apiClient.get<ApiResponse<PickupShopHistoricalStats>>(
|
||||
'/admin/pickups/shops/historical-stats'
|
||||
)
|
||||
return data.data
|
||||
}
|
||||
|
||||
export async function mapHistoricalShops(req: MapHistoricalShopsRequest) {
|
||||
const { data } = await apiClient.post<ApiResponse<MapHistoricalShopsResult>>(
|
||||
'/admin/pickups/shops/map-historical',
|
||||
req
|
||||
)
|
||||
return data.data
|
||||
}
|
||||
|
||||
export async function deleteShopMapping(sourceName: string) {
|
||||
const { data } = await apiClient.delete<ApiResponse<{ deleted: boolean }>>(
|
||||
'/admin/pickups/shops/mappings',
|
||||
{ params: { source_name: sourceName } }
|
||||
)
|
||||
return data.data
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user