Files
medical-mall/services/admin/AdminUserService.uts
2026-02-05 10:11:09 +08:00

236 lines
7.7 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { supa } from '@/utils/supabaseService.uts'
import type { AkReqResponse } from '@/uni_modules/ak-req/interface.uts'
// Admin 用户管理相关类型定义
export type AdminUserItem = {
id: string
auth_id: string
username: string
email: string
role: string
profile_status?: number
real_name?: string
credit_score?: number
verification_status?: number
created_at: string
updated_at: string
balance: number // 固定 0
is_member: boolean
member_plan_name?: string
member_end_date?: string
}
export type AdminUserDetail = {
id: string
auth_id: string
username: string
email: string
role: string
profile_status?: number
real_name?: string
credit_score?: number
verification_status?: number
preferences?: UTSJSONObject
emergency_contact?: string
service_areas?: UTSJSONObject
created_at: string
updated_at: string
balance: number // 固定 0
is_member: boolean
member_info?: {
plan_name: string
plan_code: string
billing_period: string
price: number
features: UTSJSONObject
status: string
start_date: string
end_date?: string
next_billing_date?: string
auto_renew: boolean
}
addresses?: Array<{
id: string
receiver_name: string
receiver_phone: string
province: string
city: string
district: string
address_detail: string
postal_code?: string
is_default: boolean
label?: string
latitude?: number
longitude?: number
delivery_instructions?: string
business_hours?: string
status: number
created_at: string
updated_at: string
}>
}
export type AdminUserListParams = {
page?: number
limit?: number
search?: string
role?: string
status?: number
is_member?: boolean
}
export type AdminUserListResponse = {
total: number
page: number
limit: number
has_more: boolean
items: Array<AdminUserItem>
}
/**
* Admin 用户管理服务
* 封装对 admin 用户管理相关 RPC 的调用
* 符合项目规范:页面/组件不得直接访问 supabase client必须通过 services
*/
export class AdminUserService {
/**
* 获取用户列表(分页+筛选)
* @param params 查询参数
* @returns Promise<AdminUserListResponse>
*/
static async getUserList(params: AdminUserListParams = {}): Promise<AdminUserListResponse> {
try {
const rpcParams = {
p_page: params.page ?? 1,
p_limit: params.limit ?? 20,
p_search: params.search ?? null,
p_role: params.role ?? null,
p_status: params.status ?? null,
p_is_member: params.is_member ?? null
} as UTSJSONObject
const response = await supa.rpc('rpc_admin_user_list', rpcParams)
if (response.error != null) {
throw new Error(`RPC 调用失败: ${response.error.message}`)
}
const data = response.data as UTSJSONObject
return {
total: data.getNumber('total') ?? 0,
page: data.getNumber('page') ?? 1,
limit: data.getNumber('limit') ?? 20,
has_more: data.getBoolean('has_more') ?? false,
items: (data.getArray('items') as Array<UTSJSONObject>)?.map(item => ({
id: item.getString('id') ?? '',
auth_id: item.getString('auth_id') ?? '',
username: item.getString('username') ?? '',
email: item.getString('email') ?? '',
role: item.getString('role') ?? '',
profile_status: item.getNumber('profile_status'),
real_name: item.getString('real_name'),
credit_score: item.getNumber('credit_score'),
verification_status: item.getNumber('verification_status'),
created_at: item.getString('created_at') ?? '',
updated_at: item.getString('updated_at') ?? '',
balance: item.getNumber('balance') ?? 0,
is_member: item.getBoolean('is_member') ?? false,
member_plan_name: item.getString('member_plan_name'),
member_end_date: item.getString('member_end_date')
})) ?? []
}
} catch (error) {
console.error('[AdminUserService] getUserList error:', error)
throw error
}
}
/**
* 获取用户详情
* @param userId 用户IDak_users.id
* @returns Promise<AdminUserDetail | null>
*/
static async getUserDetail(userId: string): Promise<AdminUserDetail | null> {
try {
const response = await supa.rpc('rpc_admin_user_detail', { p_user_id: userId } as UTSJSONObject)
if (response.error != null) {
throw new Error(`RPC 调用失败: ${response.error.message}`)
}
const data = response.data as UTSJSONObject
if (data == null) {
return null
}
// 解析会员信息
let memberInfo: any = null
const memberInfoObj = data.getJSONObject('member_info')
if (memberInfoObj != null) {
memberInfo = {
plan_name: memberInfoObj.getString('plan_name') ?? '',
plan_code: memberInfoObj.getString('plan_code') ?? '',
billing_period: memberInfoObj.getString('billing_period') ?? '',
price: memberInfoObj.getNumber('price') ?? 0,
features: memberInfoObj.getJSONObject('features') ?? {},
status: memberInfoObj.getString('status') ?? '',
start_date: memberInfoObj.getString('start_date') ?? '',
end_date: memberInfoObj.getString('end_date'),
next_billing_date: memberInfoObj.getString('next_billing_date'),
auto_renew: memberInfoObj.getBoolean('auto_renew') ?? false
}
}
// 解析地址列表
let addresses: any[] = []
const addressesArray = data.getArray('addresses') as Array<UTSJSONObject>
if (addressesArray != null) {
addresses = addressesArray.map(addr => ({
id: addr.getString('id') ?? '',
receiver_name: addr.getString('receiver_name') ?? '',
receiver_phone: addr.getString('receiver_phone') ?? '',
province: addr.getString('province') ?? '',
city: addr.getString('city') ?? '',
district: addr.getString('district') ?? '',
address_detail: addr.getString('address_detail') ?? '',
postal_code: addr.getString('postal_code'),
is_default: addr.getBoolean('is_default') ?? false,
label: addr.getString('label'),
latitude: addr.getNumber('latitude'),
longitude: addr.getNumber('longitude'),
delivery_instructions: addr.getString('delivery_instructions'),
business_hours: addr.getString('business_hours'),
status: addr.getNumber('status') ?? 1,
created_at: addr.getString('created_at') ?? '',
updated_at: addr.getString('updated_at') ?? ''
}))
}
return {
id: data.getString('id') ?? '',
auth_id: data.getString('auth_id') ?? '',
username: data.getString('username') ?? '',
email: data.getString('email') ?? '',
role: data.getString('role') ?? '',
profile_status: data.getNumber('profile_status'),
real_name: data.getString('real_name'),
credit_score: data.getNumber('credit_score'),
verification_status: data.getNumber('verification_status'),
preferences: data.getJSONObject('preferences'),
emergency_contact: data.getString('emergency_contact'),
service_areas: data.getJSONObject('service_areas'),
created_at: data.getString('created_at') ?? '',
updated_at: data.getString('updated_at') ?? '',
balance: data.getNumber('balance') ?? 0,
is_member: data.getBoolean('is_member') ?? false,
member_info: memberInfo,
addresses: addresses
}
} catch (error) {
console.error('[AdminUserService] getUserDetail error:', error)
throw error
}
}
}
export default AdminUserService