实现 P2 管理端:租户生命周期、套餐与运维真实 API

- 租户开通自动创建管理员账号与网页渠道,支持暂停/恢复/编辑
- 运营概览返回月收入估算、套餐分布与真实操作日志
- 套餐上下架/新建,公告与操作日志前后端打通
- 补充管理端生命周期集成测试
This commit is contained in:
yml2213
2026-07-15 11:22:37 +08:00
parent 65014d80de
commit b5203f7cbd
7 changed files with 1095 additions and 261 deletions
+56 -3
View File
@@ -42,8 +42,35 @@ export interface Channel {
}
export interface Tenant {
id: number; name: string; plan_id: number; seat_count: number; expire_at: string; status: string
id: number; name: string; plan_id: number | null; seat_count: number; expire_at: string; status: string
contact_name: string; contact_phone: string; contact_email: string
created_at?: string
}
export interface Plan {
id: number; name: string; price_monthly: number; seats: number; storage_days: number
kb_limit: number; features: string; status: string
}
export interface OperationLog {
id: number; operator_id: number; action: string; detail: string
target_type?: string; target_id?: number; ip?: string; created_at: string
}
export interface Announcement {
id: number; title: string; content: string; status: string
created_at: string; updated_at?: string
}
export interface AdminStats {
tenant_total: number
active_tenant: number
suspended_tenant?: number
expiring_tenant?: number
monthly_income: number
system_uptime: string
plan_distribution?: { plan_id: number; name: string; count: number }[]
recent_logs?: OperationLog[]
}
export interface StatisticsKpis {
@@ -123,11 +150,37 @@ export const getChannelDistribution = () => get<{ type: string; value: number }[
export const getAgentPerformance = () => get<{ name: string; conversations: number; avg_response: number; satisfaction: number }[]>('/statistics/performance')
// Admin
export const getTenants = (params?: { search?: string; status?: string; page?: number }) => {
export const getTenants = (params?: { search?: string; status?: string; page?: number; pageSize?: number }) => {
const search = new URLSearchParams()
if (params?.search) search.set('search', params.search)
if (params?.status) search.set('status', params.status)
if (params?.page) search.set('page', String(params.page || 1))
if (params?.pageSize) search.set('pageSize', String(params.pageSize))
return getList<Tenant>(`/admin/tenants?${search}`)
}
export const getAdminStats = () => get('/admin/stats')
export const getAdminStats = () => get<AdminStats>('/admin/stats')
export const createTenant = (data: {
name: string; contact_name: string; contact_phone: string; contact_email?: string
plan_id?: number; seat_count?: number; duration_months?: number
admin_username?: string; admin_password?: string
}) => post<{ tenant: Tenant; admin_username: string; admin_password: string }>('/admin/tenants', data)
export const updateTenant = (id: number, data: Partial<Tenant>) => put<Tenant>(`/admin/tenants/${id}`, data)
export const suspendTenant = (id: number) => post(`/admin/tenants/${id}/suspend`, {})
export const resumeTenant = (id: number) => post(`/admin/tenants/${id}/resume`, {})
export const getPlans = () => get<Plan[]>('/admin/plans')
export const createPlan = (data: Partial<Plan>) => post<Plan>('/admin/plans', data)
export const updatePlan = (id: number, data: Partial<Plan>) => put<Plan>(`/admin/plans/${id}`, data)
export const getAdminLogs = (params?: { page?: number; pageSize?: number }) => {
const search = new URLSearchParams()
if (params?.page) search.set('page', String(params.page || 1))
if (params?.pageSize) search.set('pageSize', String(params.pageSize || 10))
return getList<OperationLog>(`/admin/logs?${search}`)
}
export const getAnnouncements = () => get<Announcement[]>('/admin/announcements')
export const createAnnouncement = (data: { title: string; content: string; status?: string }) =>
post<Announcement>('/admin/announcements', data)
export const updateAnnouncement = (id: number, data: Partial<Announcement>) =>
put<Announcement>(`/admin/announcements/${id}`, data)
export const deleteAnnouncement = (id: number) => del(`/admin/announcements/${id}`)