Files
medical-mall/services/admin/distributionService.uts
2026-02-15 16:37:37 +08:00

362 lines
8.4 KiB
Plaintext

import supa from '@/components/supadb/aksupainstance.uts'
/**
* 分销配置模型 (与 ak_distribution_config 表对齐)
*/
export type DistributionConfig = {
id?: string
// 分销模式
is_enabled: boolean
extract_type: string
bind_type: string
store_brokerage_binding_status: string
brokerage_poster_status: string | null
brokerage_level: number
is_area_manager: boolean
is_agent_apply: boolean
is_commission_window: boolean
// 返佣设置
is_self_brokerage: boolean
is_member_brokerage: boolean
brokerage_type: string
is_promoter_brokerage: boolean
promoter_brokerage_price: number
promoter_brokerage_day_max: number
store_brokerage_ratio: number
store_brokerage_two_ratio: number
extract_frozen_time: number
// 提现设置
user_extract_min_price: number
extract_bank_list: string
extract_type_list: string[]
wechat_extract_type: string
alipay_extract_type: string
user_extract_fee: number
updated_at?: string
updated_by?: string
}
/**
* 推广员模型
*/
export type Promoter = {
id: string
nickname: string
name: string
phone: string
avatar_url: string
level: string
userCount: number
orderCount: number
orderAmount: number
commissionTotal: number
withdrawnAmount: number
withdrawCount: number
unwithdrawnAmount: number
}
/**
* 获取分销全局配置
*/
export async function getDistributionConfig(): Promise<DistributionConfig | null> {
const { data, error } = await supa
.from('ak_distribution_config')
.select('*')
.eq('id', 'global_config')
.single()
.execute()
if (error != null) {
console.error('获取分销配置失败:', error)
return null
}
return data as DistributionConfig | null
}
/**
* 保存分销全局配置
*/
export async function saveDistributionConfig(config: DistributionConfig): Promise<boolean> {
const { error } = await supa
.from('ak_distribution_config')
.upsert({
...config,
id: 'global_config',
updated_at: new Date().toISOString()
})
.execute()
if (error != null) {
console.error('保存分销配置失败:', error)
return false
}
return true
}
/**
* 分销等级模型
*/
export type DistributionLevel = {
id?: string
name: string
level: number
percent1: number
percent2: number
task_total: number
task_finish: number
is_visible: boolean
created_at?: string
updated_at?: string
}
/**
* 获取分销等级列表
*/
export async function getDistributionLevelList(): Promise<DistributionLevel[]> {
const { data, error } = await supa
.from('ak_distribution_level')
.select('*')
.order('level', { ascending: true })
.execute()
if (error != null) {
console.error('获取分销等级列表失败:', error)
return [] as DistributionLevel[]
}
return data as DistributionLevel[]
}
/**
* 保存/更新分销等级
*/
export async function saveDistributionLevel(level: DistributionLevel): Promise<boolean> {
const { error } = await supa
.from('ak_distribution_level')
.upsert({
...level,
updated_at: new Date().toISOString()
})
.execute()
if (error != null) {
console.error('保存分销等级失败:', error)
return false
}
return true
}
/**
* 删除分销等级
*/
export async function deleteDistributionLevel(id: string): Promise<boolean> {
const { error } = await supa
.from('ak_distribution_level')
.delete()
.eq('id', id)
.execute()
if (error != null) {
console.error('删除分销等级失败:', error)
return false
}
return true
}
/**
* 获取推广员列表
*/
export type PromoterListParams = {
search?: string | null
page?: number
pageSize?: number
startTime?: string | null
endTime?: string | null
}
/**
* 获取推广员列表(聚合统计)
*/
export async function getPromoterList(params?: PromoterListParams): Promise<Promoter[]> {
const payload = {
p_search: params?.search ?? null,
p_page: params?.page ?? 1,
p_page_size: params?.pageSize ?? 20,
p_start_time: params?.startTime ?? null,
p_end_time: params?.endTime ?? null
} as any
const { data, error } = await supa
.rpc('rpc_admin_get_promoter_list', payload as any)
if (error != null) {
console.error('获取推广员列表失败:', error)
return [] as Promoter[]
}
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
}