chore: 初始化平台管理端

This commit is contained in:
msumshk
2026-01-29 04:21:09 +00:00
commit 914dcc4166
533 changed files with 104838 additions and 0 deletions

254
src/api/announcement.ts Normal file
View File

@@ -0,0 +1,254 @@
/**
* 文件用途:公告模块 API 封装
* 说明:统一对接平台/租户/应用端公告接口
* 日期2025-12-20
*/
import request from '@/utils/http'
import type {
AnnouncementCommand,
AnnouncementFormData,
AnnouncementQueryParams,
TenantAnnouncementDto
} from '@/types/announcement'
import type { PagedResult } from '@/types/common/response'
/** 发布/撤销命令体(仅包含 RowVersion */
type RowVersionCommand = Pick<AnnouncementCommand, 'rowVersion'>
const withTenantHeader = (tenantId: string) => ({
headers: {
'X-Tenant-Id': tenantId
}
})
const normalizeQueryParams = (params: AnnouncementQueryParams) => {
const { dateFrom, dateTo, ...rest } = params
return {
...rest,
effectiveFrom: params.effectiveFrom ?? dateFrom,
effectiveTo: params.effectiveTo ?? dateTo
}
}
/**
* 平台公告 API
* 路由前缀:/api/platform/announcements
*/
export const platformAnnouncementApi = {
/**
* 创建平台公告
* @param data 创建参数
*/
create: (data: AnnouncementFormData) => {
return request.post<TenantAnnouncementDto>({
url: '/api/platform/announcements',
data
})
},
/**
* 查询平台公告列表
* @param params 查询参数
*/
list: (params: AnnouncementQueryParams) => {
return request.get<PagedResult<TenantAnnouncementDto>>({
url: '/api/platform/announcements',
params: normalizeQueryParams(params)
})
},
/**
* 获取平台公告详情
* @param announcementId 公告ID
*/
detail: (announcementId: string) => {
return request.get<TenantAnnouncementDto>({
url: `/api/platform/announcements/${announcementId}`
})
},
/**
* 更新平台公告(仅草稿)
* @param announcementId 公告ID
* @param data 更新参数
*/
update: (announcementId: string, data: AnnouncementFormData) => {
return request.put<TenantAnnouncementDto>({
url: `/api/platform/announcements/${announcementId}`,
data
})
},
/**
* 发布平台公告
* @param announcementId 公告ID
* @param command 命令体(包含 rowVersion
*/
publish: (announcementId: string, command: RowVersionCommand) => {
return request.post<TenantAnnouncementDto>({
url: `/api/platform/announcements/${announcementId}/publish`,
data: command
})
},
/**
* 撤销平台公告
* @param announcementId 公告ID
* @param command 命令体(包含 rowVersion
*/
revoke: (announcementId: string, command: RowVersionCommand) => {
return request.post<TenantAnnouncementDto>({
url: `/api/platform/announcements/${announcementId}/revoke`,
data: command
})
}
}
/**
* 租户公告 API
* 路由前缀:/api/admin/v1/tenants/{tenantId}/announcements
*/
export const tenantAnnouncementApi = {
/**
* 分页查询租户公告
* @param tenantId 租户ID
* @param params 查询参数
*/
list: (tenantId: string, params: AnnouncementQueryParams) => {
return request.get<PagedResult<TenantAnnouncementDto>>({
url: `/api/admin/v1/tenants/${tenantId}/announcements`,
params: normalizeQueryParams(params),
...withTenantHeader(tenantId)
})
},
/**
* 获取租户公告详情
* @param tenantId 租户ID
* @param announcementId 公告ID
*/
detail: (tenantId: string, announcementId: string) => {
return request.get<TenantAnnouncementDto>({
url: `/api/admin/v1/tenants/${tenantId}/announcements/${announcementId}`,
...withTenantHeader(tenantId)
})
},
/**
* 创建租户公告
* @param tenantId 租户ID
* @param data 创建参数
*/
create: (tenantId: string, data: AnnouncementFormData) => {
return request.post<TenantAnnouncementDto>({
url: `/api/admin/v1/tenants/${tenantId}/announcements`,
data,
...withTenantHeader(tenantId)
})
},
/**
* 更新租户公告(仅草稿)
* @param tenantId 租户ID
* @param announcementId 公告ID
* @param data 更新参数
*/
update: (tenantId: string, announcementId: string, data: AnnouncementFormData) => {
return request.put<TenantAnnouncementDto>({
url: `/api/admin/v1/tenants/${tenantId}/announcements/${announcementId}`,
data,
...withTenantHeader(tenantId)
})
},
/**
* 发布租户公告
* @param tenantId 租户ID
* @param announcementId 公告ID
* @param command 命令体(包含 rowVersion
*/
publish: (tenantId: string, announcementId: string, command: RowVersionCommand) => {
return request.post<TenantAnnouncementDto>({
url: `/api/admin/v1/tenants/${tenantId}/announcements/${announcementId}/publish`,
data: command,
...withTenantHeader(tenantId)
})
},
/**
* 撤销租户公告
* @param tenantId 租户ID
* @param announcementId 公告ID
* @param command 命令体(包含 rowVersion
*/
revoke: (tenantId: string, announcementId: string, command: RowVersionCommand) => {
return request.post<TenantAnnouncementDto>({
url: `/api/admin/v1/tenants/${tenantId}/announcements/${announcementId}/revoke`,
data: command,
...withTenantHeader(tenantId)
})
},
/**
* 删除租户公告
* @param tenantId 租户ID
* @param announcementId 公告ID
*/
delete: (tenantId: string, announcementId: string) => {
return request.del<boolean>({
url: `/api/admin/v1/tenants/${tenantId}/announcements/${announcementId}`,
...withTenantHeader(tenantId)
})
},
/**
* 标记公告已读(兼容旧路径)
* @param tenantId 租户ID
* @param announcementId 公告ID
*/
markRead: (tenantId: string, announcementId: string) => {
return request.post<TenantAnnouncementDto>({
url: `/api/admin/v1/tenants/${tenantId}/announcements/${announcementId}/read`,
...withTenantHeader(tenantId)
})
}
}
/**
* 应用端公告 API
* 路由前缀:/api/app/announcements
*/
export const appAnnouncementApi = {
/**
* 获取可见公告列表(已发布且有效期内)
* @param params 查询参数
*/
list: (params: AnnouncementQueryParams) => {
return request.get<PagedResult<TenantAnnouncementDto>>({
url: '/api/app/announcements',
params: normalizeQueryParams(params)
})
},
/**
* 获取未读公告列表
* @param params 查询参数
*/
unread: (params: AnnouncementQueryParams) => {
return request.get<PagedResult<TenantAnnouncementDto>>({
url: '/api/app/announcements/unread',
params: normalizeQueryParams(params)
})
},
/**
* 标记公告已读
* @param announcementId 公告ID
*/
markRead: (announcementId: string) => {
return request.post<TenantAnnouncementDto>({
url: `/api/app/announcements/${announcementId}/mark-read`
})
}
}

71
src/api/auth.ts Normal file
View File

@@ -0,0 +1,71 @@
import request from '@/utils/http'
/**
* 登录
* @param params 登录参数
* @returns 登录响应
*/
export function fetchLogin(params: Api.Auth.LoginParams) {
return request.post<Api.Auth.LoginResponse>({
url: '/api/admin/v1/auth/login',
params
// showSuccessMessage: true // 显示成功消息
// showErrorMessage: false // 不显示错误消息
})
}
/**
* 免租户号登录(仅账号+密码)
*/
export function fetchLoginSimple(params: Api.Auth.LoginParams) {
return request.post<Api.Auth.LoginResponse>({
url: '/api/admin/v1/auth/login/simple',
params,
skipTenantHeader: true
})
}
/**
* 获取用户信息
* @returns 用户信息
*/
export function fetchGetUserInfo() {
return request.get<Api.Auth.UserInfo>({
url: '/api/admin/v1/auth/profile'
// 自定义请求头
// headers: {
// 'X-Custom-Header': 'your-custom-value'
// }
})
}
/**
* 获取用户菜单
* @returns 菜单列表
*/
export function fetchGetMenu() {
return request.get<Api.Auth.MenuListResponse>({
url: '/api/admin/v1/auth/menu'
})
}
/**
* 获取用户权限
* @param userId 用户ID
* @returns 用户权限信息
*/
export function fetchGetUserPermissions(userId: string) {
return request.get<Api.Auth.UserPermissionsResponse>({
url: `/api/admin/v1/auth/permissions/${userId}`
})
}
/**
* 通过重置链接令牌重置管理员密码
*/
export function fetchResetAdminPassword(data: Api.Auth.ResetAdminPasswordRequest) {
return request.post<void>({
url: '/api/admin/v1/auth/reset-password',
data
})
}

222
src/api/billing.ts Normal file
View File

@@ -0,0 +1,222 @@
import request from '@/utils/http'
/**
* 账单接口基础路径
*
* 说明:后端路由为 /api/admin/v1/billings。
*/
const BILLING_BASE_URL = '/api/admin/v1/billings'
// ==================== 查询类 API ====================
/**
* 获取账单列表
* @param params 查询参数
*/
export function fetchBillingList(params?: Partial<Api.Billing.BillingListParams>) {
return request.get<Api.Billing.BillingListResponse>({
url: BILLING_BASE_URL,
params
})
}
/**
* 获取账单列表(导出用:自动分页拉取)
* @param params 查询参数(不含分页也可)
* @param options 导出拉取选项
*/
export async function fetchBillingListForExport(
params?: Partial<Api.Billing.BillingListParams>,
options?: {
/** 单页拉取条数(越大越快,但后端可能有限制) */
pageSize?: number
/** 最大导出条数(防止一次性导出过大) */
maxRows?: number
}
) {
// 1. 兜底配置
const pageSize = Math.min(Math.max(options?.pageSize ?? 200, 50), 2000)
const maxRows = Math.min(Math.max(options?.maxRows ?? 10000, 1), 100000)
// 2. 循环分页拉取(直到 totalPages 或达到 maxRows
const result: Api.Billing.BillingListDto[] = []
let pageNumber = 1
let totalPages = 1
while (pageNumber <= totalPages && result.length < maxRows) {
const res = await fetchBillingList({
...params,
PageNumber: pageNumber,
PageSize: pageSize
})
const items = res.items || []
result.push(...items)
totalPages = res.totalPages || 1
if (items.length === 0) break
pageNumber += 1
}
// 3. 截断到 maxRows避免极端情况内存爆炸
return result.slice(0, maxRows)
}
/**
* 获取账单详情
* @param id 账单 ID
*/
export function fetchBillingDetail(id: string) {
return request.get<Api.Billing.BillingDetailDto>({
url: `${BILLING_BASE_URL}/${id}`
})
}
/**
* 获取账单支付记录
* @param billingId 账单 ID
*/
export function fetchBillingPayments(billingId: string) {
return request.get<Api.Billing.PaymentRecordListResponse>({
url: `${BILLING_BASE_URL}/${billingId}/payments`
})
}
/**
* 获取账单统计数据
* @param params 统计查询参数
*/
export function fetchBillingStatistics(params: Api.Billing.BillingStatisticsParams) {
return request.get<Api.Billing.BillingStatisticsDto>({
url: `${BILLING_BASE_URL}/statistics`,
params
})
}
/**
* 获取逾期账单列表
* @param params 分页参数
*/
export function fetchOverdueBillings(params?: Partial<Api.Billing.BillingListParams>) {
return request.get<Api.Billing.BillingListResponse>({
url: `${BILLING_BASE_URL}/overdue`,
params
})
}
// ==================== 命令类 API ====================
/**
* 创建账单
* @param data 创建账单数据
*/
export function createBilling(data: Api.Billing.CreateBillingCommand) {
return request.post<Api.Billing.BillingDetailDto>({
url: BILLING_BASE_URL,
data
})
}
/**
* 更新账单状态
* @param id 账单 ID
* @param data 更新状态数据
*/
export function updateBillingStatus(id: string, data: Api.Billing.UpdateStatusCommand) {
return request.put<Api.Billing.BillingDetailDto>({
url: `${BILLING_BASE_URL}/${id}/status`,
data
})
}
/**
* 取消账单
* @param id 账单 ID
* @param data 取消原因
*/
export function cancelBilling(id: string, data: Api.Billing.CancelBillingCommand) {
return request.del<void>({
url: `${BILLING_BASE_URL}/${id}`,
data
})
}
/**
* 记录支付(仅创建待审核支付记录,不会立即更新账单状态)
* @param billingId 账单 ID
* @param data 支付记录数据
*/
export function recordPayment(billingId: string, data: Api.Billing.RecordPaymentCommand) {
return request.post<Api.Billing.PaymentRecordDto>({
url: `${BILLING_BASE_URL}/${billingId}/payments`,
data
})
}
/**
* 一键确认收款(记录支付 + 立即审核通过 + 同步更新账单状态)
* @param billingId 账单 ID
* @param data 支付记录数据
*/
export function confirmPayment(billingId: string, data: Api.Billing.RecordPaymentCommand) {
return request.post<Api.Billing.PaymentRecordDto>({
url: `${BILLING_BASE_URL}/${billingId}/payments/confirm`,
data
})
}
/**
* 审核支付记录
* @param paymentId 支付记录 ID
* @param data 审核数据
*/
export function verifyPayment(paymentId: string, data: Api.Billing.VerifyPaymentCommand) {
return request.put<Api.Billing.PaymentRecordDto>({
url: `${BILLING_BASE_URL}/payments/${paymentId}/verify`,
data
})
}
/**
* 批量更新账单状态
* @param data 批量更新数据
*/
export function batchUpdateStatus(data: Api.Billing.BatchUpdateStatusCommand) {
return request.post<void>({
url: `${BILLING_BASE_URL}/batch/status`,
data
})
}
/**
* 导出账单
* @param data 导出参数
* @returns Blob 对象(用于下载)
*/
export function exportBillings(data: Api.Billing.ExportParams) {
return request.post<Blob>({
url: `${BILLING_BASE_URL}/export`,
data,
responseType: 'blob'
})
}
// ==================== 兼容导出(适配现有页面命名) ====================
/** 获取账单列表(兼容旧命名) */
export const fetchGetBillList = fetchBillingList
/** 获取账单详情(兼容旧命名) */
export const fetchGetBillDetail = fetchBillingDetail
/** 获取账单列表(导出用,兼容旧命名) */
export const fetchGetBillListForExport = fetchBillingListForExport
/** 创建账单(兼容旧命名) */
export const fetchCreateBill = createBilling
/** 更新账单状态(兼容旧命名) */
export const fetchUpdateBillStatus = updateBillingStatus
/** 记录支付(兼容旧命名) */
export const fetchRecordPayment = recordPayment

View File

@@ -0,0 +1,70 @@
import request from '@/utils/http'
const GROUP_BASE_URL = '/api/admin/v1/dictionary/groups'
export function getGroups(params?: Api.Dictionary.DictionaryGroupQueryParams) {
return request.get<Api.Common.PageResult<Api.Dictionary.DictionaryGroupDto>>({
url: GROUP_BASE_URL,
params
})
}
export function getGroupById(groupId: string) {
return request.get<Api.Dictionary.DictionaryGroupDto>({
url: `${GROUP_BASE_URL}/${groupId}`
})
}
export function createGroup(data: Api.Dictionary.CreateDictionaryGroupRequest) {
return request.post<Api.Dictionary.DictionaryGroupDto>({
url: GROUP_BASE_URL,
data
})
}
export function updateGroup(groupId: string, data: Api.Dictionary.UpdateDictionaryGroupRequest) {
return request.put<Api.Dictionary.DictionaryGroupDto>({
url: `${GROUP_BASE_URL}/${groupId}`,
data
})
}
export function deleteGroup(groupId: string) {
return request.del<void>({
url: `${GROUP_BASE_URL}/${groupId}`
})
}
export function exportGroup(
groupId: string,
format: Api.Dictionary.DictionaryExportRequest['format']
) {
return request.post<Blob>({
url: `${GROUP_BASE_URL}/${groupId}/export`,
data: { format },
responseType: 'blob'
})
}
export function importGroup(
groupId: string,
payload: {
file: File
conflictMode?: Api.Dictionary.ConflictResolutionMode | string
format?: 'csv' | 'json'
}
) {
const formData = new FormData()
formData.append('File', payload.file)
if (payload.conflictMode) {
formData.append('ConflictMode', String(payload.conflictMode))
}
if (payload.format) {
formData.append('Format', payload.format)
}
return request.post<Api.Dictionary.DictionaryImportResultDto>({
url: `${GROUP_BASE_URL}/${groupId}/import`,
data: formData
})
}

View File

@@ -0,0 +1,33 @@
import request from '@/utils/http'
const GROUP_BASE_URL = '/api/admin/v1/dictionary/groups'
export function getItems(groupId: string) {
return request.get<Api.Dictionary.DictionaryItemDto[]>({
url: `${GROUP_BASE_URL}/${groupId}/items`
})
}
export function createItem(groupId: string, data: Api.Dictionary.CreateDictionaryItemRequest) {
return request.post<Api.Dictionary.DictionaryItemDto>({
url: `${GROUP_BASE_URL}/${groupId}/items`,
data
})
}
export function updateItem(
groupId: string,
itemId: string,
data: Api.Dictionary.UpdateDictionaryItemRequest
) {
return request.put<Api.Dictionary.DictionaryItemDto>({
url: `${GROUP_BASE_URL}/${groupId}/items/${itemId}`,
data
})
}
export function deleteItem(groupId: string, itemId: string) {
return request.del<void>({
url: `${GROUP_BASE_URL}/${groupId}/items/${itemId}`
})
}

View File

@@ -0,0 +1,70 @@
import request from '@/utils/http'
const LABEL_OVERRIDE_BASE_URL = '/api/admin/v1/dictionary/label-overrides'
// ==================== 租户端 API ====================
/**
* 获取当前租户的标签覆盖列表
*/
export function getTenantLabelOverrides() {
return request.get<Api.Dictionary.LabelOverrideDto[]>({
url: `${LABEL_OVERRIDE_BASE_URL}/tenant`
})
}
/**
* 租户创建/更新标签覆盖
*/
export function upsertTenantLabelOverride(data: Api.Dictionary.UpsertLabelOverrideRequest) {
return request.post<Api.Dictionary.LabelOverrideDto>({
url: `${LABEL_OVERRIDE_BASE_URL}/tenant`,
data
})
}
/**
* 租户删除标签覆盖
*/
export function deleteTenantLabelOverride(dictionaryItemId: string) {
return request.del<void>({
url: `${LABEL_OVERRIDE_BASE_URL}/tenant/${dictionaryItemId}`
})
}
// ==================== 平台端 API ====================
/**
* 获取指定租户的所有标签覆盖(平台管理员用)
*/
export function getPlatformLabelOverrides(
targetTenantId: string,
overrideType?: Api.Dictionary.OverrideType
) {
return request.get<Api.Dictionary.LabelOverrideDto[]>({
url: `${LABEL_OVERRIDE_BASE_URL}/platform/${targetTenantId}`,
params: { overrideType }
})
}
/**
* 平台强制覆盖租户字典项的标签
*/
export function upsertPlatformLabelOverride(
targetTenantId: string,
data: Api.Dictionary.UpsertLabelOverrideRequest
) {
return request.post<Api.Dictionary.LabelOverrideDto>({
url: `${LABEL_OVERRIDE_BASE_URL}/platform/${targetTenantId}`,
data
})
}
/**
* 平台删除对租户的强制覆盖
*/
export function deletePlatformLabelOverride(targetTenantId: string, dictionaryItemId: string) {
return request.del<void>({
url: `${LABEL_OVERRIDE_BASE_URL}/platform/${targetTenantId}/${dictionaryItemId}`
})
}

View File

@@ -0,0 +1,35 @@
import request from '@/utils/http'
const METRICS_BASE_URL = '/api/admin/v1/dictionary/metrics'
export function getCacheStats(timeRange: '1h' | '24h' | '7d' = '1h') {
return request.get<{
totalHits: number
totalMisses: number
hitRatio: number
hitsByLevel: { l1: number; l2: number }
missesByLevel: { l1: number; l2: number }
averageQueryDurationMs: number
topQueriedDictionaries: Array<{ code: string; queryCount: number }>
}>({
url: `${METRICS_BASE_URL}/cache-stats`,
params: { timeRange }
})
}
export function getInvalidationEvents(params: {
page: number
pageSize: number
startDate?: string
endDate?: string
}) {
return request.get<Api.Common.PageResult<Api.Dictionary.CacheInvalidationLogDto>>({
url: `${METRICS_BASE_URL}/invalidation-events`,
params: {
page: params.page,
pageSize: params.pageSize,
startDate: params.startDate,
endDate: params.endDate
}
})
}

View File

@@ -0,0 +1,49 @@
import request from '@/utils/http'
const OVERRIDE_BASE_URL = '/api/admin/v1/dictionary/overrides'
export function getOverrides() {
return request.get<Api.Dictionary.OverrideConfigDto[]>({
url: OVERRIDE_BASE_URL
})
}
export function getOverride(groupCode: string) {
return request.get<Api.Dictionary.OverrideConfigDto>({
url: `${OVERRIDE_BASE_URL}/${groupCode}`
})
}
export function enableOverride(groupCode: string) {
return request.post<Api.Dictionary.OverrideConfigDto>({
url: `${OVERRIDE_BASE_URL}/${groupCode}/enable`,
data: {}
})
}
export function disableOverride(groupCode: string) {
return request.post<void>({
url: `${OVERRIDE_BASE_URL}/${groupCode}/disable`,
data: {}
})
}
export function updateHiddenItems(
groupCode: string,
hiddenItemIds: Api.Dictionary.DictionaryOverrideHiddenItemsRequest['hiddenItemIds']
) {
return request.put<Api.Dictionary.OverrideConfigDto>({
url: `${OVERRIDE_BASE_URL}/${groupCode}/hidden-items`,
data: { hiddenItemIds }
})
}
export function updateSortOrder(
groupCode: string,
sortOrder: Api.Dictionary.DictionaryOverrideSortOrderRequest['sortOrder']
) {
return request.put<Api.Dictionary.OverrideConfigDto>({
url: `${OVERRIDE_BASE_URL}/${groupCode}/sort-order`,
data: { sortOrder }
})
}

View File

@@ -0,0 +1,27 @@
import request from '@/utils/http'
const QUERY_BASE_URL = '/api/admin/v1/dictionaries'
const normalizeCode = (code: string) => code.trim().toLowerCase()
export async function getDictionary(code: string) {
const result = await batchGetDictionaries([code])
return result[code] ?? []
}
export async function batchGetDictionaries(codes: string[]) {
if (!codes.length) return {}
const result = await request.post<Record<string, Api.Dictionary.DictionaryItemDto[]>>({
url: `${QUERY_BASE_URL}/batch`,
data: { codes }
})
const mapped: Record<string, Api.Dictionary.DictionaryItemDto[]> = {}
codes.forEach((code) => {
const key = normalizeCode(code)
mapped[code] = result[key] ?? result[code] ?? []
})
return mapped
}

22
src/api/files.ts Normal file
View File

@@ -0,0 +1,22 @@
import request from '@/utils/http'
/**
* 文件上传 API
*/
/**
* 上传图片或文件Admin
* @param file 上传的文件
* @param type 上传类型(可选)
*/
export function fetchUploadFile(file: File, type: Api.Files.UploadFileType = 'other') {
const formData = new FormData()
formData.append('File', file)
formData.append('Type', type)
return request.post<Api.Files.FileUploadResponse>({
url: '/api/admin/v1/files/upload',
// 重要:不要手动设置 Content-Type让浏览器自动带 boundary
data: formData
})
}

126
src/api/merchant.ts Normal file
View File

@@ -0,0 +1,126 @@
import api from '@/utils/http'
/**
* 获取商户列表
*/
export function fetchMerchantList(params?: Partial<Api.Merchant.MerchantListParams>) {
return api.get<Api.Merchant.MerchantListResponse>({
url: '/api/admin/v1/merchants',
params
})
}
/**
* 获取商户详情
*/
export function fetchMerchantDetail(merchantId: string, options?: { showErrorMessage?: boolean }) {
return api.get<Api.Merchant.MerchantDetail>({
url: `/api/admin/v1/merchants/${merchantId}`,
showErrorMessage: options?.showErrorMessage
})
}
/**
* 更新商户信息
*/
export function fetchUpdateMerchant(
merchantId: string,
data: Api.Merchant.UpdateMerchantRequest,
options?: { showErrorMessage?: boolean }
) {
return api.put<Api.Merchant.UpdateMerchantResult>({
url: `/api/admin/v1/merchants/${merchantId}`,
data,
showErrorMessage: options?.showErrorMessage
})
}
/**
* 获取商户审核历史
*/
export function fetchMerchantAuditHistory(merchantId: string) {
return api.get<Api.Merchant.MerchantAuditRecord[]>({
url: `/api/admin/v1/merchants/${merchantId}/audit-history`
})
}
/**
* 获取商户变更历史
*/
export function fetchMerchantChangeLogs(merchantId: string, params?: { fieldName?: string }) {
return api.get<Api.Merchant.MerchantChangeLogRecord[]>({
url: `/api/admin/v1/merchants/${merchantId}/change-history`,
params
})
}
/**
* 获取待审核商户列表
*/
export function fetchPendingReviewList(params?: Partial<Api.Merchant.MerchantListParams>) {
return api.get<Api.Merchant.MerchantReviewListResponse>({
url: '/api/admin/v1/merchants/pending-review',
params
})
}
/**
* 获取审核领取信息
*/
export function fetchMerchantReviewClaim(merchantId: string) {
return api.get<Api.Merchant.ClaimInfo | null>({
url: `/api/admin/v1/merchants/${merchantId}/review/claim`
})
}
/**
* 领取审核
*/
export function fetchClaimMerchantReview(merchantId: string) {
return api.post<Api.Merchant.ClaimInfo>({
url: `/api/admin/v1/merchants/${merchantId}/review/claim`,
data: {}
})
}
/**
* 释放审核
*/
export function fetchReleaseMerchantReview(merchantId: string) {
return api.del<Api.Merchant.ClaimInfo | null>({
url: `/api/admin/v1/merchants/${merchantId}/review/claim`
})
}
/**
* 执行审核
*/
export function fetchReviewMerchant(merchantId: string, data: Api.Merchant.ReviewMerchantRequest) {
return api.post<void>({
url: `/api/admin/v1/merchants/${merchantId}/review`,
data
})
}
/**
* 撤销审核
*/
export function fetchRevokeMerchantReview(
merchantId: string,
data: Api.Merchant.RevokeMerchantRequest
) {
return api.post<void>({
url: `/api/admin/v1/merchants/${merchantId}/review/revoke`,
data
})
}
/**
* 导出商户 PDF
*/
export function fetchExportMerchantPdf(merchantId: string) {
return api.get<Blob>({
url: `/api/admin/v1/merchants/${merchantId}/export-pdf`,
responseType: 'blob'
})
}

21
src/api/permission.ts Normal file
View File

@@ -0,0 +1,21 @@
import request from '@/utils/http'
/**
* 获取权限列表(分页)
* @param params 查询参数
*/
export function fetchGetPermissions(params?: Api.Permission.PermissionQueryParams) {
return request.get<Api.Permission.PermissionPageResult>({
url: '/api/admin/v1/permissions',
params
})
}
/**
* 获取权限树
*/
export function fetchGetPermissionTree() {
return request.get<Api.Permission.PermissionDto[]>({
url: '/api/admin/v1/permissions/tree'
})
}

100
src/api/quotaPackage.ts Normal file
View File

@@ -0,0 +1,100 @@
import request from '@/utils/http'
/**
* 配额包管理 API
*/
/**
* 获取配额包列表
*/
export function fetchQuotaPackageList(params?: {
quotaType?: number
isActive?: boolean
page?: number
pageSize?: number
}) {
return request.get<Api.Common.PageResult<Api.QuotaPackage.QuotaPackageListDto>>({
url: '/api/admin/v1/quota-packages',
params
})
}
/**
* 创建配额包
*/
export function fetchCreateQuotaPackage(data: Api.QuotaPackage.CreateQuotaPackageCommand) {
return request.post<Api.QuotaPackage.QuotaPackageDto>({
url: '/api/admin/v1/quota-packages',
data
})
}
/**
* 更新配额包
*/
export function fetchUpdateQuotaPackage(
quotaPackageId: string,
data: Api.QuotaPackage.UpdateQuotaPackageCommand
) {
return request.put<Api.QuotaPackage.QuotaPackageDto>({
url: `/api/admin/v1/quota-packages/${quotaPackageId}`,
data
})
}
/**
* 删除配额包(软删)
*/
export function fetchDeleteQuotaPackage(quotaPackageId: string) {
return request.del<boolean>({
url: `/api/admin/v1/quota-packages/${quotaPackageId}`
})
}
/**
* 更新配额包状态(上架/下架)
*/
export function fetchUpdateQuotaPackageStatus(quotaPackageId: string, isActive: boolean) {
return request.put<boolean>({
url: `/api/admin/v1/quota-packages/${quotaPackageId}/status`,
data: {
isActive
}
})
}
/**
* 为租户购买配额包
*/
export function fetchPurchaseQuotaPackage(
tenantId: string,
data: Api.QuotaPackage.PurchaseQuotaPackageCommand
) {
return request.post<Api.QuotaPackage.TenantQuotaPurchaseDto>({
url: `/api/admin/v1/tenants/${tenantId}/quota-packages`,
data
})
}
/**
* 获取租户配额使用情况
*/
export function fetchTenantQuotaUsage(tenantId: string, params?: { quotaType?: number }) {
return request.get<Api.QuotaPackage.TenantQuotaUsageDto[]>({
url: `/api/admin/v1/tenants/${tenantId}/quota-usage`,
params
})
}
/**
* 获取租户配额购买记录
*/
export function fetchTenantQuotaPurchases(
tenantId: string,
params?: { page?: number; pageSize?: number }
) {
return request.get<Api.Common.PageResult<Api.QuotaPackage.TenantQuotaPurchaseDto>>({
url: `/api/admin/v1/tenants/${tenantId}/quota-purchases`,
params
})
}

94
src/api/role-template.ts Normal file
View File

@@ -0,0 +1,94 @@
import request from '@/utils/http'
/**
* 获取角色模板列表
* @param params 查询参数
*/
export function fetchGetRoleTemplates(params?: any) {
return request.get<Api.RoleTemplate.RoleTemplateDto[]>({
url: '/api/admin/v1/role-templates',
params
})
}
/**
* 获取角色模板详情
* @param templateCode 模板编码
*/
export function fetchGetRoleTemplateDetail(templateCode: string) {
return request.get<Api.RoleTemplate.RoleTemplateDto>({
url: `/api/admin/v1/role-templates/${templateCode}`
})
}
/**
* 创建角色模板
* @param data 创建参数
*/
export function fetchCreateRoleTemplate(data: Api.RoleTemplate.CreateRoleTemplateCommand) {
return request.post<Api.RoleTemplate.RoleTemplateDto>({
url: '/api/admin/v1/role-templates',
data
})
}
/**
* 更新角色模板
* @param templateCode 模板编码
* @param data 更新参数
*/
export function fetchUpdateRoleTemplate(
templateCode: string,
data: Api.RoleTemplate.UpdateRoleTemplateCommand
) {
return request.put<Api.RoleTemplate.RoleTemplateDto>({
url: `/api/admin/v1/role-templates/${templateCode}`,
data
})
}
/**
* 删除角色模板
* @param templateCode 模板编码
*/
export function fetchDeleteRoleTemplate(templateCode: string) {
return request.del<boolean>({
url: `/api/admin/v1/role-templates/${templateCode}`
})
}
/**
* 克隆角色模板
* @param templateCode 源模板编码
* @param data 克隆参数
*/
export function fetchCloneRoleTemplate(
templateCode: string,
data: Api.RoleTemplate.CloneRoleTemplateCommand
) {
return request.post<Api.RoleTemplate.RoleTemplateDto>({
url: `/api/admin/v1/role-templates/${templateCode}/clone`,
data
})
}
/**
* 初始化角色模板
* @param templateCodes 模板编码列表
*/
export function fetchInitRoleTemplates(templateCodes: string[]) {
return request.post<any>({
url: '/api/admin/v1/role-templates/init',
data: { templateCodes }
})
}
/**
* 获取角色模板权限列表
* @param templateCode 模板编码
*/
export function fetchGetRoleTemplatePermissions(templateCode: string) {
return request.get<Api.RoleTemplate.PermissionTemplateDto[]>({
url: `/api/admin/v1/role-templates/${templateCode}/permissions`
})
}

47
src/api/statistics.ts Normal file
View File

@@ -0,0 +1,47 @@
import request from '@/utils/http'
/**
* 统计分析 API
*/
/**
* 获取订阅概览统计
*/
export function fetchSubscriptionOverview() {
return request.get<Api.Statistics.SubscriptionOverview>({
url: '/api/admin/v1/statistics/subscriptions/overview'
})
}
/**
* 获取配额使用排行
* @param params 查询参数
*/
export function fetchQuotaUsageRanking(params?: Api.Statistics.QuotaUsageRankingParams) {
return request.get<Api.Statistics.QuotaUsageRankingResponse>({
url: '/api/admin/v1/statistics/quota/ranking',
params
})
}
/**
* 获取收入统计
* @param params 查询参数
*/
export function fetchRevenueStatistics(params?: Api.Statistics.RevenueStatisticsParams) {
return request.get<Api.Statistics.RevenueStatisticsResponse>({
url: '/api/admin/v1/statistics/revenue',
params
})
}
/**
* 获取即将到期订阅列表
* @param params 查询参数
*/
export function fetchExpiringSubscriptions(params?: Api.Statistics.ExpiringSubscriptionsParams) {
return request.get<Api.Statistics.ExpiringSubscriptionsResponse>({
url: '/api/admin/v1/statistics/subscriptions/expiring',
params
})
}

309
src/api/store.ts Normal file
View File

@@ -0,0 +1,309 @@
import api from '@/utils/http'
interface StoreRequestOptions {
tenantId?: string
}
const buildTenantHeader = (options?: StoreRequestOptions) => {
// 1. 未提供租户ID时返回空配置
if (!options?.tenantId) {
return {}
}
// 2. 返回携带租户头的请求配置
return {
headers: {
'X-Tenant-Id': String(options.tenantId)
}
}
}
/**
* 获取门店列表
*/
export function fetchStoreList(params?: Partial<Api.Store.StoreListParams>) {
return api.get<Api.Store.StoreListResponse>({
url: '/api/admin/v1/stores',
params
})
}
/**
* 获取门店详情
*/
export function fetchStoreDetail(storeId: string, options?: { showErrorMessage?: boolean }) {
return api.get<Api.Store.StoreDto>({
url: `/api/admin/v1/stores/${storeId}`,
showErrorMessage: options?.showErrorMessage
})
}
/**
* 创建门店
*/
export function fetchCreateStore(data: Api.Store.CreateStoreRequest) {
return api.post<Api.Store.StoreDto>({
url: '/api/admin/v1/stores',
data
})
}
/**
* 更新门店
*/
export function fetchUpdateStore(storeId: string, data: Api.Store.UpdateStoreRequest) {
return api.put<Api.Store.StoreDto>({
url: `/api/admin/v1/stores/${storeId}`,
data
})
}
/**
* 删除门店
*/
export function fetchDeleteStore(storeId: string) {
return api.del<void>({
url: `/api/admin/v1/stores/${storeId}`
})
}
/**
* 提交门店审核
*/
export function fetchSubmitStoreAudit(storeId: string) {
return api.post<boolean>({
url: `/api/admin/v1/stores/${storeId}/submit`,
data: {}
})
}
/**
* 切换门店经营状态
*/
export function fetchToggleBusinessStatus(
storeId: string,
data: Api.Store.ToggleBusinessStatusRequest
) {
return api.post<Api.Store.StoreDto>({
url: `/api/admin/v1/stores/${storeId}/business-status`,
data
})
}
/**
* 获取门店资质列表
*/
export function fetchStoreQualifications(storeId: string, options?: StoreRequestOptions) {
return api.get<Api.Store.StoreQualificationDto[]>({
url: `/api/admin/v1/stores/${storeId}/qualifications`,
...buildTenantHeader(options)
})
}
/**
* 检查门店资质完整性
*/
export function fetchCheckStoreQualifications(storeId: string, options?: StoreRequestOptions) {
return api.get<Api.Store.StoreQualificationCheckResultDto>({
url: `/api/admin/v1/stores/${storeId}/qualifications/check`,
...buildTenantHeader(options)
})
}
/**
* 创建门店资质
*/
export function fetchCreateStoreQualification(
storeId: string,
data: Api.Store.CreateStoreQualificationRequest,
options?: StoreRequestOptions
) {
return api.post<Api.Store.StoreQualificationDto>({
url: `/api/admin/v1/stores/${storeId}/qualifications`,
data,
...buildTenantHeader(options)
})
}
/**
* 更新门店资质
*/
export function fetchUpdateStoreQualification(
storeId: string,
qualificationId: string,
data: Api.Store.UpdateStoreQualificationRequest,
options?: StoreRequestOptions
) {
return api.put<Api.Store.StoreQualificationDto>({
url: `/api/admin/v1/stores/${storeId}/qualifications/${qualificationId}`,
data,
...buildTenantHeader(options)
})
}
/**
* 删除门店资质
*/
export function fetchDeleteStoreQualification(
storeId: string,
qualificationId: string,
options?: StoreRequestOptions
) {
return api.del<boolean>({
url: `/api/admin/v1/stores/${storeId}/qualifications/${qualificationId}`,
...buildTenantHeader(options)
})
}
/**
* 获取门店营业时段
*/
export function fetchStoreBusinessHours(storeId: string) {
return api.get<Api.Store.StoreBusinessHourDto[]>({
url: `/api/admin/v1/stores/${storeId}/business-hours`
})
}
/**
* 批量更新门店营业时段
*/
export function fetchBatchUpdateBusinessHours(
storeId: string,
data: Api.Store.BatchUpdateBusinessHoursRequest
) {
return api.put<Api.Store.StoreBusinessHourDto[]>({
url: `/api/admin/v1/stores/${storeId}/business-hours/batch`,
data
})
}
/**
* 获取配送区域
*/
export function fetchStoreDeliveryZones(storeId: string) {
return api.get<Api.Store.StoreDeliveryZoneDto[]>({
url: `/api/admin/v1/stores/${storeId}/delivery-zones`
})
}
/**
* 创建配送区域
*/
export function fetchCreateStoreDeliveryZone(
storeId: string,
data: Api.Store.CreateStoreDeliveryZoneRequest
) {
return api.post<Api.Store.StoreDeliveryZoneDto>({
url: `/api/admin/v1/stores/${storeId}/delivery-zones`,
data
})
}
/**
* 更新配送区域
*/
export function fetchUpdateStoreDeliveryZone(
storeId: string,
deliveryZoneId: string,
data: Api.Store.UpdateStoreDeliveryZoneRequest
) {
return api.put<Api.Store.StoreDeliveryZoneDto>({
url: `/api/admin/v1/stores/${storeId}/delivery-zones/${deliveryZoneId}`,
data
})
}
/**
* 删除配送区域
*/
export function fetchDeleteStoreDeliveryZone(storeId: string, deliveryZoneId: string) {
return api.del<void>({
url: `/api/admin/v1/stores/${storeId}/delivery-zones/${deliveryZoneId}`
})
}
/**
* 配送范围检测
*/
export function fetchDeliveryZoneCheck(storeId: string, data: Api.Store.StoreDeliveryCheckRequest) {
return api.post<Api.Store.StoreDeliveryCheckResultDto>({
url: `/api/admin/v1/stores/${storeId}/delivery-check`,
data
})
}
/**
* 获取门店费用配置
*/
export function fetchStoreFee(storeId: string) {
return api.get<Api.Store.StoreFeeDto>({
url: `/api/admin/v1/stores/${storeId}/fee`
})
}
/**
* 更新门店费用配置
*/
export function fetchUpdateStoreFee(storeId: string, data: Api.Store.UpdateStoreFeeRequest) {
return api.put<Api.Store.StoreFeeDto>({
url: `/api/admin/v1/stores/${storeId}/fee`,
data
})
}
/**
* 门店费用预览
*/
export function fetchCalculateStoreFee(storeId: string, data: Api.Store.CalculateStoreFeeRequest) {
return api.post<Api.Store.StoreFeeCalculationResultDto>({
url: `/api/admin/v1/stores/${storeId}/fee/calculate`,
data
})
}
// ==================== 临时时段 API ====================
/**
* 获取门店临时时段列表
*/
export function fetchStoreHolidays(storeId: string) {
return api.get<Api.Store.StoreHolidayDto[]>({
url: `/api/admin/v1/stores/${storeId}/holidays`
})
}
/**
* 创建临时时段
*/
export function fetchCreateStoreHoliday(
storeId: string,
data: Api.Store.CreateStoreHolidayRequest
) {
return api.post<Api.Store.StoreHolidayDto>({
url: `/api/admin/v1/stores/${storeId}/holidays`,
data
})
}
/**
* 更新临时时段
*/
export function fetchUpdateStoreHoliday(
storeId: string,
holidayId: string,
data: Api.Store.UpdateStoreHolidayRequest
) {
return api.put<Api.Store.StoreHolidayDto>({
url: `/api/admin/v1/stores/${storeId}/holidays/${holidayId}`,
data
})
}
/**
* 删除临时时段
*/
export function fetchDeleteStoreHoliday(storeId: string, holidayId: string) {
return api.del<boolean>({
url: `/api/admin/v1/stores/${storeId}/holidays/${holidayId}`
})
}

103
src/api/storeAudit.ts Normal file
View File

@@ -0,0 +1,103 @@
import api from '@/utils/http'
/**
* 获取待审核门店列表
*/
export function fetchPendingStoreAudits(
params?: Partial<Api.StoreAudit.ListPendingStoreAuditsParams>
) {
return api.get<Api.StoreAudit.PendingStoreAuditResponse>({
url: '/api/admin/v1/platform/store-audits/pending',
params
})
}
/**
* 获取审核统计
*/
export function fetchStoreAuditStatistics(params?: Api.StoreAudit.StoreAuditStatisticsParams) {
return api.get<Api.StoreAudit.StoreAuditStatisticsDto>({
url: '/api/admin/v1/platform/store-audits/statistics',
params
})
}
/**
* 获取门店审核详情
*/
export function fetchStoreAuditDetail(storeId: string) {
return api.get<Api.StoreAudit.StoreAuditDetailDto>({
url: `/api/admin/v1/platform/store-audits/${storeId}`
})
}
/**
* 获取审核记录
*/
export function fetchStoreAuditRecords(
storeId: string,
params?: Api.StoreAudit.ListStoreAuditRecordsParams
) {
return api.get<Api.Common.PageResult<Api.StoreAudit.StoreAuditRecordDto>>({
url: `/api/admin/v1/platform/store-audits/${storeId}/records`,
params
})
}
/**
* 审核通过
*/
export function fetchApproveStoreAudit(
storeId: string,
data: Api.StoreAudit.ApproveStoreAuditRequest
) {
return api.post<Api.StoreAudit.StoreAuditActionResultDto>({
url: `/api/admin/v1/platform/store-audits/${storeId}/approve`,
data
})
}
/**
* 审核驳回
*/
export function fetchRejectStoreAudit(
storeId: string,
data: Api.StoreAudit.RejectStoreAuditRequest
) {
return api.post<Api.StoreAudit.StoreAuditActionResultDto>({
url: `/api/admin/v1/platform/store-audits/${storeId}/reject`,
data
})
}
/**
* 强制关闭门店
*/
export function fetchForceCloseStore(storeId: string, data: Api.StoreAudit.ForceCloseStoreRequest) {
return api.post<Api.StoreAudit.StoreAuditActionResultDto>({
url: `/api/admin/v1/platform/store-audits/${storeId}/force-close`,
data
})
}
/**
* 解除强制关闭
*/
export function fetchReopenStore(storeId: string, data: Api.StoreAudit.ReopenStoreRequest) {
return api.post<Api.StoreAudit.StoreAuditActionResultDto>({
url: `/api/admin/v1/platform/store-audits/${storeId}/reopen`,
data
})
}
/**
* 获取资质预警列表(平台)
*/
export function fetchQualificationAlerts(
params?: Partial<Api.Store.StoreQualificationAlertQueryParams>
) {
return api.get<Api.Store.StoreQualificationAlertResultDto>({
url: '/api/admin/v1/platform/store-qualifications/expiring',
params
})
}

134
src/api/subscription.ts Normal file
View File

@@ -0,0 +1,134 @@
import request from '@/utils/http'
/**
* 订阅管理 API
*/
/**
* 获取订阅列表
* @param params 查询参数
*/
export function getSubscriptionList(params?: Api.Subscription.SubscriptionListParams) {
return request.get<Api.Subscription.SubscriptionListResponse>({
url: '/api/admin/v1/subscriptions',
params
})
}
/**
* 获取订阅详情
* @param id 订阅ID
*/
export function getSubscriptionDetail(id: string) {
return request.get<Api.Subscription.SubscriptionDetailDto>({
url: `/api/admin/v1/subscriptions/${id}`
})
}
/**
* 更新订阅
* @param id 订阅ID
* @param data 更新数据
*/
export function updateSubscription(
id: string,
data: Omit<Api.Subscription.UpdateSubscriptionCommand, 'subscriptionId'>
) {
return request.put<Api.Subscription.SubscriptionDto>({
url: `/api/admin/v1/subscriptions/${id}`,
data: {
...data,
subscriptionId: id
}
})
}
/**
* 延期订阅
* @param id 订阅ID
* @param data 延期数据
*/
export function extendSubscription(
id: string,
data: Omit<Api.Subscription.ExtendSubscriptionCommand, 'subscriptionId'>
) {
return request.post<Api.Subscription.SubscriptionDto>({
url: `/api/admin/v1/subscriptions/${id}/extend`,
data: {
...data,
subscriptionId: id
}
})
}
/**
* 变更套餐
* @param id 订阅ID
* @param data 变更数据
*/
export function changeSubscriptionPlan(
id: string,
data: Omit<Api.Subscription.ChangePlanCommand, 'subscriptionId'>
) {
return request.post<Api.Subscription.SubscriptionDto>({
url: `/api/admin/v1/subscriptions/${id}/change-plan`,
data: {
...data,
subscriptionId: id
}
})
}
/**
* 变更订阅状态
* @param id 订阅ID
* @param data 状态数据
*/
export function updateSubscriptionStatus(
id: string,
data: Omit<Api.Subscription.UpdateStatusCommand, 'subscriptionId'>
) {
return request.post<Api.Subscription.SubscriptionDto>({
url: `/api/admin/v1/subscriptions/${id}/status`,
data: {
...data,
subscriptionId: id
}
})
}
/**
* 批量延期订阅
* @param data 批量延期数据
*/
export function batchExtendSubscriptions(data: {
subscriptionIds: string[]
durationDays: number
notes?: string
}) {
return request.post<{
successCount: number
failureCount: number
failures: Array<{ subscriptionId: string; reason: string }>
}>({
url: '/api/admin/v1/subscriptions/batch-extend',
data,
showSuccessMessage: true
})
}
/**
* 批量发送提醒
* @param data 批量提醒数据
*/
export function batchSendReminders(data: { subscriptionIds: string[]; reminderContent: string }) {
return request.post<{
successCount: number
failureCount: number
failures: Array<{ subscriptionId: string; reason: string }>
}>({
url: '/api/admin/v1/subscriptions/batch-remind',
data,
showSuccessMessage: true
})
}

86
src/api/system-manage.ts Normal file
View File

@@ -0,0 +1,86 @@
import api from '@/utils/http'
import type { AppRouteRecord } from '@/types/router'
// 1. 获取用户列表
export function fetchGetUserList(params: Api.SystemManage.UserSearchParams) {
return api.get<Api.SystemManage.UserListResponse>({
url: '/api/admin/v1/users',
params
})
}
// 2. 获取用户详情
export function fetchGetUserDetail(userId: string, includeDeleted?: boolean) {
return api.get<Api.SystemManage.UserDetailDto>({
url: `/api/admin/v1/users/${userId}`,
params: includeDeleted ? { includeDeleted } : undefined
})
}
// 3. 创建用户
export function fetchCreateUser(command: Api.SystemManage.CreateIdentityUserCommand) {
return api.post<Api.SystemManage.UserDetailDto>({
url: '/api/admin/v1/users',
data: command
})
}
// 4. 更新用户
export function fetchUpdateUser(
userId: string,
command: Api.SystemManage.UpdateIdentityUserCommand
) {
return api.put<Api.SystemManage.UserDetailDto>({
url: `/api/admin/v1/users/${userId}`,
data: command
})
}
// 5. 删除用户
export function fetchDeleteUser(userId: string) {
return api.del<boolean>({
url: `/api/admin/v1/users/${userId}`
})
}
// 6. 恢复用户
export function fetchRestoreUser(userId: string) {
return api.post<boolean>({
url: `/api/admin/v1/users/${userId}/restore`
})
}
// 7. 更新用户状态
export function fetchChangeUserStatus(
userId: string,
command: Api.SystemManage.ChangeIdentityUserStatusCommand
) {
return api.put<boolean>({
url: `/api/admin/v1/users/${userId}/status`,
data: command
})
}
// 8. 重置用户密码
export function fetchResetUserPassword(userId: string) {
return api.post<Api.SystemManage.ResetIdentityUserPasswordResult>({
url: `/api/admin/v1/users/${userId}/password-reset`
})
}
// 9. 批量用户操作
export function fetchBatchUserOperation(
command: Api.SystemManage.BatchIdentityUserOperationCommand
) {
return api.post<Api.SystemManage.BatchIdentityUserOperationResult>({
url: '/api/admin/v1/users/batch',
data: command
})
}
// 10. 获取菜单列表
export function fetchGetMenuList() {
return api.get<AppRouteRecord[]>({
url: '/api/v3/system/menus/simple'
})
}

View File

@@ -0,0 +1,99 @@
import request from '@/utils/http'
/**
* 自助注册租户
* @param data 自助注册参数
*/
export function fetchSelfRegisterTenant(data: Api.Tenant.SelfRegisterTenantCommand) {
return request.post<Api.Tenant.SelfRegisterResult>({
url: '/api/public/v1/tenants/self-register',
data
})
}
/**
* 查询租户入驻进度
* @param tenantId 租户ID
*/
export function fetchTenantProgress(tenantId: string) {
return request.get<Api.Tenant.TenantProgress>({
url: `/api/public/v1/tenants/${tenantId}/status`
})
}
/**
* 提交或更新租户实名信息
* @param tenantId 租户ID
* @param data 实名资料
*/
export function submitTenantVerification(
tenantId: string,
data: Api.Tenant.SubmitTenantVerificationCommand
) {
return request.post<Api.Tenant.TenantVerificationDto>({
url: `/api/public/v1/tenants/${tenantId}/verification`,
data: { ...data, tenantId }
})
}
/**
* 提交或更新租户实名信息(管理端)
* @param tenantId 租户ID
* @param data 实名资料
*/
export function submitTenantVerificationAdmin(
tenantId: string,
data: Api.Tenant.SubmitTenantVerificationCommand
) {
return request.post<Api.Tenant.TenantVerificationDto>({
url: `/api/admin/v1/tenants/${tenantId}/verification`,
data: { ...data, tenantId }
})
}
/**
* 创建租户订阅
* @param tenantId 租户ID
* @param data 订阅参数
*/
export function createTenantSubscription(
tenantId: string,
data: Api.Tenant.CreateTenantSubscriptionCommand
) {
return request.post<Api.Tenant.TenantSubscriptionDto>({
url: `/api/admin/v1/tenants/${tenantId}/subscriptions`,
data: { ...data, tenantId }
})
}
/**
* 初次绑定租户订阅(自助入驻)
* @param tenantId 租户ID
* @param data 初次绑定参数
*/
export function bindInitialTenantSubscription(
tenantId: string,
data: Api.Tenant.BindInitialTenantSubscriptionCommand
) {
return request.post<Api.Tenant.TenantSubscriptionDto>({
url: `/api/public/v1/tenants/${tenantId}/subscriptions/initial`,
data: { ...data, tenantId }
})
}
/**
* 升降配租户套餐
* @param tenantId 租户ID
* @param subscriptionId 订阅ID
* @param data 升降配参数
*/
export function changeTenantSubscriptionPlan(
tenantId: string,
subscriptionId: string,
data: Api.Tenant.ChangeTenantSubscriptionPlanCommand
) {
return request.put<Api.Tenant.TenantSubscriptionDto>({
url: `/api/admin/v1/tenants/${tenantId}/subscriptions/${subscriptionId}/plan`,
data: { ...data, tenantId, tenantSubscriptionId: subscriptionId }
})
}

103
src/api/tenant-package.ts Normal file
View File

@@ -0,0 +1,103 @@
import request from '@/utils/http'
/**
* 租户套餐管理 API
*/
/**
* 获取租户套餐分页列表
*/
export function fetchTenantPackageList(params?: Api.Tenant.TenantPackageQueryParams) {
return request.get<Api.Tenant.TenantPackageListResponse>({
url: '/api/admin/v1/tenant-packages',
params
})
}
/**
* 公共租户套餐列表(匿名可访问)
*/
export function fetchPublicTenantPackageList(params?: Api.Tenant.TenantPackageQueryParams) {
return request.get<Api.Tenant.PublicTenantPackageListResponse>({
url: '/api/public/v1/tenant-packages',
params
})
}
/**
* 获取租户套餐详情
*/
export function fetchTenantPackageDetail(tenantPackageId: string) {
return request.get<Api.Tenant.TenantPackageDto>({
url: `/api/admin/v1/tenant-packages/${tenantPackageId}`
})
}
/**
* 创建租户套餐
*/
export function fetchCreateTenantPackage(data: Api.Tenant.CreateTenantPackageCommand) {
return request.post<Api.Tenant.TenantPackageDto>({
url: '/api/admin/v1/tenant-packages',
data
})
}
/**
* 更新租户套餐
*/
export function fetchUpdateTenantPackage(
tenantPackageId: string,
data: Api.Tenant.UpdateTenantPackageCommand
) {
return request.put<Api.Tenant.TenantPackageDto>({
url: `/api/admin/v1/tenant-packages/${tenantPackageId}`,
data: {
...data,
tenantPackageId
}
})
}
/**
* 删除租户套餐(软删)
*/
export function fetchDeleteTenantPackage(tenantPackageId: string) {
return request.del<boolean>({
url: `/api/admin/v1/tenant-packages/${tenantPackageId}`
})
}
/**
* 查询套餐使用统计(订阅关联数量、使用租户数量)
*/
export function fetchTenantPackageUsages(tenantPackageIds?: string[]) {
const params = new URLSearchParams()
if (tenantPackageIds?.length) {
tenantPackageIds.forEach((id) => params.append('tenantPackageIds', id))
}
return request.get<Api.Tenant.TenantPackageUsageDto[]>({
url: '/api/admin/v1/tenant-packages/usages',
params,
showErrorMessage: false
})
}
/**
* 查询套餐当前使用租户列表(按有效订阅口径)
*/
export function fetchTenantPackageTenants(
tenantPackageId: string,
params: { keyword?: string; page?: number; pageSize?: number; expiringWithinDays?: number } = {}
) {
return request.get<Api.Common.PageResult<Api.Tenant.TenantPackageTenantDto>>({
url: `/api/admin/v1/tenant-packages/${tenantPackageId}/tenants`,
params: {
keyword: params.keyword || undefined,
expiringWithinDays: params.expiringWithinDays ?? undefined,
page: params.page ?? 1,
pageSize: params.pageSize ?? 20
}
})
}

98
src/api/tenant-role.ts Normal file
View File

@@ -0,0 +1,98 @@
import request from '@/utils/http'
/**
* 获取租户角色列表
* @param tenantId 租户ID
* @param params 查询参数
*/
export function fetchGetTenantRoles(
tenantId: number | string,
params?: Api.TenantRole.RoleQueryParams
) {
return request.get<Api.TenantRole.RoleDtoPagedResult>({
url: `/api/admin/v1/tenants/${tenantId}/roles`,
params
})
}
/**
* 获取租户角色详情
* @param tenantId 租户ID
* @param roleId 角色ID
*/
export function fetchGetTenantRoleDetail(tenantId: number | string, roleId: number | string) {
return request.get<Api.TenantRole.RoleDto>({
url: `/api/admin/v1/tenants/${tenantId}/roles/${roleId}`
})
}
/**
* 创建租户角色
* @param tenantId 租户ID
* @param data 创建参数
*/
export function fetchCreateTenantRole(
tenantId: number | string,
data: Api.TenantRole.CreateRoleCommand
) {
return request.post<Api.TenantRole.RoleDto>({
url: `/api/admin/v1/tenants/${tenantId}/roles`,
data
})
}
/**
* 更新租户角色
* @param tenantId 租户ID
* @param roleId 角色ID
* @param data 更新参数
*/
export function fetchUpdateTenantRole(
tenantId: number | string,
roleId: number | string,
data: Api.TenantRole.UpdateRoleCommand
) {
return request.put<Api.TenantRole.RoleDto>({
url: `/api/admin/v1/tenants/${tenantId}/roles/${roleId}`,
data
})
}
/**
* 删除租户角色
* @param tenantId 租户ID
* @param roleId 角色ID
*/
export function fetchDeleteTenantRole(tenantId: number | string, roleId: number | string) {
return request.del<boolean>({
url: `/api/admin/v1/tenants/${tenantId}/roles/${roleId}`
})
}
/**
* 获取租户角色权限
* @param tenantId 租户ID
* @param roleId 角色ID
*/
export function fetchGetTenantRolePermissions(tenantId: number | string, roleId: number | string) {
return request.get<string[]>({
url: `/api/admin/v1/tenants/${tenantId}/roles/${roleId}/permissions`
})
}
/**
* 更新租户角色权限
* @param tenantId 租户ID
* @param roleId 角色ID
* @param permissions 权限代码列表
*/
export function fetchUpdateTenantRolePermissions(
tenantId: number | string,
roleId: number | string,
permissionIds: string[]
) {
return request.put<boolean>({
url: `/api/admin/v1/tenants/${tenantId}/roles/${roleId}/permissions`,
data: { permissionIds }
})
}

263
src/api/tenant.ts Normal file
View File

@@ -0,0 +1,263 @@
import api from '@/utils/http'
import { fetchTenantPackageList } from './tenant-package'
import type { QuotaUsageHistoryDto, UpdateTenantCommand } from '@/types/tenant'
/**
* 获取租户列表
* @param params 搜索参数
*/
export function fetchGetTenantList(params?: Partial<Api.Tenant.TenantListParams>) {
return api.get<Api.Tenant.TenantListResponse>({
url: '/api/admin/v1/tenants',
params
})
}
/**
* 注册租户
*/
export function fetchRegisterTenant(data: Api.Tenant.RegisterTenantCommand) {
return api.post<Api.Tenant.TenantDto>({
url: '/api/admin/v1/tenants',
data
})
}
/**
* 后台手动新增租户并直接入驻(创建租户 + 认证 + 订阅 + 管理员账号)
*/
export function fetchCreateTenantManually(data: Api.Tenant.CreateTenantManuallyCommand) {
return api.post<Api.Tenant.TenantDetailDto>({
url: '/api/admin/v1/tenants/manual',
data
})
}
/**
* 获取租户详情(包含认证信息、订阅信息)
*/
export function fetchGetTenantDetail(tenantId: string, options?: { showErrorMessage?: boolean }) {
return api.get<Api.Tenant.TenantDetailDto>({
url: `/api/admin/v1/tenants/${tenantId}`,
showErrorMessage: options?.showErrorMessage
})
}
/**
* 获取租户配额使用情况
*/
export function fetchGetTenantQuotaUsage(
tenantId: string,
options?: { showErrorMessage?: boolean }
) {
return api.get<Api.QuotaPackage.TenantQuotaUsageDto[]>({
url: `/api/admin/v1/tenants/${tenantId}/quota-usage`,
showErrorMessage: options?.showErrorMessage
})
}
/**
* 获取租户配额使用历史
* @param tenantId 租户ID
* @param params 分页参数
*/
export function fetchGetTenantQuotaUsageHistory(
tenantId: string,
params?: { Page?: number; PageSize?: number }
) {
return api.get<Api.Common.PageResult<QuotaUsageHistoryDto>>({
url: `/api/admin/v1/tenants/${tenantId}/quota-usage-history`,
params
})
}
/**
* 获取订阅信息(注意:该接口为 POST
*/
export function fetchGetTenantSubscriptions(
tenantId: string,
options?: { showErrorMessage?: boolean }
) {
return api.post<Api.Tenant.TenantSubscriptionDto>({
url: `/api/admin/v1/tenants/${tenantId}/subscriptions`,
data: {},
showErrorMessage: options?.showErrorMessage
})
}
/**
* 获取账单信息分页最近10条可传 Page=1 PageSize=10
*/
export function fetchGetTenantBillings(
tenantId: string,
params: { Page?: number; PageSize?: number } = {},
options?: { showErrorMessage?: boolean }
) {
return api.get<Api.Common.PageResult<Api.Billing.BillingListDto>>({
url: `/api/admin/v1/tenants/${tenantId}/billings`,
params,
showErrorMessage: options?.showErrorMessage
})
}
/**
* 更新租户信息TD-001待后端接口补充
* @param tenantId 租户IDSnowflake long → string
* @param data 更新数据tenantId 会以入参为准覆盖)
* @returns void后端 BaseResponse<void> 的 data 字段)
*
* 后端接口PUT /api/admin/v1/tenants/{tenantId}
* 预期响应BaseResponse<void>
* 预期错误码400参数错误、404租户不存在、409code 冲突)
* TODO(TD-001): Swagger 中缺失该端点(当前可能返回 404/405待后端补充后再联调验证
*/
export function fetchUpdateTenant(tenantId: string, data: UpdateTenantCommand) {
return api.put<void>({
url: `/api/admin/v1/tenants/${tenantId}`,
data: { ...data, tenantId },
showErrorMessage: false
})
}
/**
* 获取租户套餐列表(兼容旧调用)
*/
export const fetchGetTenantPackages = fetchTenantPackageList
/**
* 审核租户
*/
export function fetchReviewTenant(
tenantId: string,
data: Omit<Api.Tenant.ReviewTenantCommand, 'tenantId'>
) {
return api.post<Api.Tenant.TenantDto>({
url: `/api/admin/v1/tenants/${tenantId}/review`,
data: { ...data, tenantId }
})
}
/**
* 获取租户审核领取信息(未领取返回 null
*/
export function fetchGetTenantReviewClaim(tenantId: string) {
return api.get<Api.Tenant.TenantReviewClaimDto | null>({
url: `/api/admin/v1/tenants/${tenantId}/review/claim`
})
}
/**
* 领取租户审核
*/
export function fetchClaimTenantReview(tenantId: string) {
return api.post<Api.Tenant.TenantReviewClaimDto>({
url: `/api/admin/v1/tenants/${tenantId}/review/claim`
})
}
/**
* 强制接管租户审核(仅超级管理员)
*/
export function fetchForceClaimTenantReview(tenantId: string) {
return api.post<Api.Tenant.TenantReviewClaimDto>({
url: `/api/admin/v1/tenants/${tenantId}/review/force-claim`
})
}
/**
* 释放租户审核领取(仅领取人)
*/
export function fetchReleaseTenantReviewClaim(tenantId: string) {
return api.post<Api.Tenant.TenantReviewClaimDto | null>({
url: `/api/admin/v1/tenants/${tenantId}/review/release`
})
}
/**
* 查询租户审核日志
*/
export function fetchGetTenantAuditLogs(
tenantId: string,
params: { page?: number; pageSize?: number } = {}
) {
return api.get<Api.Tenant.TenantAuditLogListResponse>({
url: `/api/admin/v1/tenants/${tenantId}/audits`,
params: {
page: params.page ?? 1,
pageSize: params.pageSize ?? 20
}
})
}
/**
* 冻结租户(暂停服务)
*/
export function fetchFreezeTenant(
tenantId: string,
data: Omit<Api.Tenant.FreezeTenantCommand, 'tenantId'>
) {
return api.post<Api.Tenant.TenantDto>({
url: `/api/admin/v1/tenants/${tenantId}/freeze`,
data: { ...data, tenantId }
})
}
/**
* 解冻租户(恢复服务)
*/
export function fetchUnfreezeTenant(
tenantId: string,
data: Omit<Api.Tenant.UnfreezeTenantCommand, 'tenantId'> = {}
) {
return api.post<Api.Tenant.TenantDto>({
url: `/api/admin/v1/tenants/${tenantId}/unfreeze`,
data: { ...data, tenantId }
})
}
/**
* 延期/赠送租户订阅时长(按当前订阅套餐续费)
*/
export function fetchExtendTenantSubscription(
tenantId: string,
data: Omit<Api.Tenant.ExtendTenantSubscriptionCommand, 'tenantId'>
) {
return api.post<Api.Tenant.TenantSubscriptionDto>({
url: `/api/admin/v1/tenants/${tenantId}/subscriptions/extend`,
data: { ...data, tenantId }
})
}
/**
* 伪装登录租户(返回租户主管理员的 Token
*/
export function fetchImpersonateTenant(tenantId: string) {
return api.post<Api.Auth.TokenResponse>({
url: `/api/admin/v1/tenants/${tenantId}/impersonate`
})
}
/**
* 生成租户主管理员重置密码链接(仅展示一次)
*/
export function fetchCreateTenantAdminResetLink(tenantId: string) {
return api.post<string>({
url: `/api/admin/v1/tenants/${tenantId}/admin/reset-link`
})
}
/**
* 获取租户配额购买记录(分页)
*/
export function fetchGetTenantQuotaPurchases(
tenantId: string,
params: { Page?: number; PageSize?: number } = {}
) {
return api.get<Api.Common.PageResult<Api.QuotaPackage.TenantQuotaPurchaseDto>>({
url: `/api/admin/v1/tenants/${tenantId}/quota-purchases`,
params: {
Page: params.Page ?? 1,
PageSize: params.PageSize ?? 10
}
})
}