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 } /** * Admin 用户管理服务 * 封装对 admin 用户管理相关 RPC 的调用 * 符合项目规范:页面/组件不得直接访问 supabase client,必须通过 services */ export class AdminUserService { /** * 获取用户列表(分页+筛选) * @param params 查询参数 * @returns Promise */ static async getUserList(params: AdminUserListParams = {}): Promise { 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)?.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 用户ID(ak_users.id) * @returns Promise */ static async getUserDetail(userId: string): Promise { 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 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