sql数据流,amdin业务逻辑接入
This commit is contained in:
@@ -197,3 +197,165 @@ export async function getPromoterList(params?: PromoterListParams): Promise<Prom
|
||||
}
|
||||
return (data ?? []) as Promoter[]
|
||||
}
|
||||
|
||||
/**
|
||||
* 事业部模型
|
||||
*/
|
||||
export type DistributionDivision = {
|
||||
id?: string
|
||||
merchant_id?: string
|
||||
uid: string
|
||||
name: string
|
||||
invite_code: string
|
||||
ratio: number
|
||||
agent_count: number
|
||||
end_time: string | null
|
||||
status: boolean
|
||||
created_at?: string
|
||||
updated_at?: string
|
||||
// 关联字段
|
||||
nickname?: string
|
||||
avatar_url?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* 代理商模型
|
||||
*/
|
||||
export type DistributionAgent = {
|
||||
id?: string
|
||||
merchant_id?: string
|
||||
uid: string
|
||||
division_id: string
|
||||
name: string
|
||||
status: boolean
|
||||
created_at?: string
|
||||
updated_at?: string
|
||||
// 关联字段
|
||||
nickname?: string
|
||||
avatar_url?: string
|
||||
division_name?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取事业部列表
|
||||
*/
|
||||
export async function fetchDivisions(query?: { search?: string, page?: number, pageSize?: number }): Promise<{ total: number, items: DistributionDivision[] }> {
|
||||
let q = supa.from('ak_distribution_divisions').select('*, ak_users!uid(username, avatar_url)', { count: 'exact' })
|
||||
|
||||
if (query?.search != null && query.search !== '') {
|
||||
q = q.or(`name.ilike.%${query.search}%,ak_users.username.ilike.%${query.search}%`)
|
||||
}
|
||||
|
||||
const p = query?.page ?? 1
|
||||
const ps = query?.pageSize ?? 20
|
||||
const from = (p - 1) * ps
|
||||
const to = from + ps - 1
|
||||
|
||||
const { data, error, count } = await q
|
||||
.order('created_at', { ascending: false })
|
||||
.range(from, to)
|
||||
.execute()
|
||||
|
||||
if (error != null) {
|
||||
console.error('获取事业部列表失败:', error)
|
||||
return { total: 0, items: [] as DistributionDivision[] }
|
||||
}
|
||||
|
||||
const items = (data ?? []).map((item: any): DistributionDivision => {
|
||||
return {
|
||||
...item,
|
||||
nickname: item.ak_users?.username,
|
||||
avatar_url: item.ak_users?.avatar_url
|
||||
} as DistributionDivision
|
||||
})
|
||||
|
||||
return { total: count ?? 0, items }
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存事业部(新增/更新)
|
||||
*/
|
||||
export async function saveDivision(division: DistributionDivision): Promise<boolean> {
|
||||
const session = supa.getSession()
|
||||
const mid = session?.user?.getString('id')
|
||||
if (mid == null) return false
|
||||
|
||||
const { error } = await supa
|
||||
.from('ak_distribution_divisions')
|
||||
.upsert({
|
||||
...division,
|
||||
merchant_id: mid,
|
||||
updated_at: new Date().toISOString()
|
||||
})
|
||||
.execute()
|
||||
|
||||
return error == null
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除事业部
|
||||
*/
|
||||
export async function deleteDivision(id: string): Promise<boolean> {
|
||||
const { error } = await supa.from('ak_distribution_divisions').delete().eq('id', id).execute()
|
||||
return error == null
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取代理商列表
|
||||
*/
|
||||
export async function fetchAgents(query?: { search?: string, divisionId?: string, page?: number, pageSize?: number }): Promise<{ total: number, items: DistributionAgent[] }> {
|
||||
let q = supa.from('ak_distribution_agents').select('*, ak_users!uid(username, avatar_url), ak_distribution_divisions!division_id(name)', { count: 'exact' })
|
||||
|
||||
if (query?.search != null && query.search !== '') {
|
||||
q = q.or(`name.ilike.%${query.search}%,ak_users.username.ilike.%${query.search}%`)
|
||||
}
|
||||
if (query?.divisionId != null) {
|
||||
q = q.eq('division_id', query.divisionId)
|
||||
}
|
||||
|
||||
const p = query?.page ?? 1
|
||||
const ps = query?.pageSize ?? 20
|
||||
const from = (p - 1) * ps
|
||||
const to = from + ps - 1
|
||||
|
||||
const { data, error, count } = await q
|
||||
.order('created_at', { ascending: false })
|
||||
.range(from, to)
|
||||
.execute()
|
||||
|
||||
if (error != null) {
|
||||
console.error('获取代理商列表失败:', error)
|
||||
return { total: 0, items: [] as DistributionAgent[] }
|
||||
}
|
||||
|
||||
const items = (data ?? []).map((item: any): DistributionAgent => {
|
||||
return {
|
||||
...item,
|
||||
nickname: item.ak_users?.username,
|
||||
avatar_url: item.ak_users?.avatar_url,
|
||||
division_name: item.ak_distribution_divisions?.name
|
||||
} as DistributionAgent
|
||||
})
|
||||
|
||||
return { total: count ?? 0, items }
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存代理商
|
||||
*/
|
||||
export async function saveAgent(agent: DistributionAgent): Promise<boolean> {
|
||||
const session = supa.getSession()
|
||||
const mid = session?.user?.getString('id')
|
||||
if (mid == null) return false
|
||||
|
||||
const { error } = await supa
|
||||
.from('ak_distribution_agents')
|
||||
.upsert({
|
||||
...agent,
|
||||
merchant_id: mid,
|
||||
updated_at: new Date().toISOString()
|
||||
})
|
||||
.execute()
|
||||
|
||||
return error == null
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,9 @@
|
||||
import supa from '@/components/supadb/aksupainstance.uts'
|
||||
import { rpcOrNull, rpcOrValue } from '@/services/analytics/rpc.uts'
|
||||
|
||||
/**
|
||||
* 商品主模型 (SPU)
|
||||
*/
|
||||
export type AdminProduct = {
|
||||
id: string
|
||||
name: string
|
||||
@@ -20,22 +23,95 @@ export type AdminProduct = {
|
||||
video_urls: string[] | null
|
||||
tags: string[] | null
|
||||
attributes: any | null
|
||||
// 扩展字段 (Step 3-6)
|
||||
shipping_template_id: string | null
|
||||
give_integral: number
|
||||
stock_warning: number
|
||||
virtual_sales: number
|
||||
sort_order: number
|
||||
}
|
||||
|
||||
/**
|
||||
* 商品 SKU 模型
|
||||
*/
|
||||
export type AdminProductSku = {
|
||||
id?: string
|
||||
product_id?: string
|
||||
sku_code: string
|
||||
specifications: any
|
||||
price: number
|
||||
stock: number
|
||||
status: number
|
||||
image_url: string | null
|
||||
id ?: string
|
||||
product_id ?: string
|
||||
sku_code : string
|
||||
specifications : any
|
||||
price : number
|
||||
stock : number
|
||||
status : number
|
||||
image_url : string | null
|
||||
}
|
||||
|
||||
/**
|
||||
* 运费模板模型
|
||||
*/
|
||||
export type ShippingTemplate = {
|
||||
id : string
|
||||
merchant_id ?: string
|
||||
name : string
|
||||
calc_method : string // piece, weight, volume
|
||||
is_free_shipping : boolean
|
||||
sort_order : number
|
||||
created_at ?: string
|
||||
updated_at ?: string
|
||||
}
|
||||
|
||||
export type ProductPageResult = {
|
||||
total: number
|
||||
items: Array<AdminProduct>
|
||||
total : number
|
||||
items : Array<AdminProduct>
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取运费模板列表
|
||||
*/
|
||||
export async function fetchShippingTemplates() : Promise<ShippingTemplate[]> {
|
||||
const { data, error } = await supa
|
||||
.from('ak_shipping_templates')
|
||||
.select('*')
|
||||
.order('sort_order', { ascending: true })
|
||||
.execute()
|
||||
|
||||
if (error != null) {
|
||||
console.error('获取运费模板失败:', error)
|
||||
return [] as ShippingTemplate[]
|
||||
}
|
||||
return (data ?? []) as ShippingTemplate[]
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存运费模板(新增/更新)
|
||||
*/
|
||||
export async function saveShippingTemplate(tpl : Partial<ShippingTemplate>) : Promise<boolean> {
|
||||
const session = supa.getSession()
|
||||
const uid = session?.user?.getString('id')
|
||||
if (uid == null) return false
|
||||
|
||||
const { error } = await supa
|
||||
.from('ak_shipping_templates')
|
||||
.upsert({
|
||||
...tpl,
|
||||
merchant_id: uid,
|
||||
updated_at: new Date().toISOString()
|
||||
})
|
||||
.execute()
|
||||
|
||||
return error == null
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除运费模板
|
||||
*/
|
||||
export async function deleteShippingTemplate(id : string) : Promise<boolean> {
|
||||
const { error } = await supa
|
||||
.from('ak_shipping_templates')
|
||||
.delete()
|
||||
.eq('id', id)
|
||||
.execute()
|
||||
|
||||
return error == null
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -131,8 +207,7 @@ export async function saveAdminProduct(product: Partial<AdminProduct>, skus: Adm
|
||||
|
||||
const savedProductId = (savedProduct as any).id as string
|
||||
|
||||
// 2. 保存 SKU(简单策略:先删除旧的再插入新的,或使用 upsert)
|
||||
// 注意:如果涉及订单关联,不能简单的物理删除旧 SKU
|
||||
// 2. 保存 SKU
|
||||
const skuPayload = skus.map(s => ({
|
||||
...s,
|
||||
product_id: savedProductId,
|
||||
|
||||
Reference in New Issue
Block a user