refactor(backend): 重构动物相关 API 接口

- 更新了动物数据结构和相关类型定义
- 优化了动物列表、详情、创建、更新和删除接口
- 新增了更新动物状态接口
- 移除了与认领记录相关的接口
-调整了 API 响应结构
This commit is contained in:
ylweng
2025-08-31 00:45:46 +08:00
parent 0cad74b06f
commit 8e5295b572
111 changed files with 15290 additions and 1972 deletions

View File

@@ -2,7 +2,7 @@
NODE_ENV=development
# API配置
VITE_API_BASE_URL=http://localhost:3000/api/v1
VITE_API_BASE_URL=http://localhost:3100/api/v1
VITE_API_TIMEOUT=30000
# 功能开关

View File

@@ -15,7 +15,7 @@
<meta name="theme-color" content="#1890ff">
<!-- 移动端优化 -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="default">
<meta name="apple-mobile-web-app-title" content="<%- VITE_APP_NAME %>">

View File

@@ -13,7 +13,7 @@ const appStore = useAppStore()
onMounted(() => {
// 初始化应用
appStore.initializeApp()
appStore.initialize()
// 开发环境调试信息
if (import.meta.env.DEV) {

View File

@@ -1,110 +1,89 @@
import { request } from '@/api'
import type { AxiosResponse } from 'axios'
import { request } from '.'
// 动物类型
export type AnimalType = 'alpaca' | 'dog' | 'cat' | 'rabbit'
// 动物状态
export type AnimalStatus = 'available' | 'claimed' | 'reserved'
// 认领状态
export type ClaimStatus = 'pending' | 'approved' | 'rejected' | 'completed'
// 动物数据结构
// 定义动物相关类型
export interface Animal {
id: number
name: string
type: AnimalType
species: string
breed: string
age: number
price: number
status: AnimalStatus
image_url: string
gender: string
description: string
image: string
merchant_id: number
merchant_name: string
price: number
status: string
created_at: string
updated_at: string
}
// 动物认领记录
export interface AnimalClaim {
id: number
animal_id: number
animal_name: string
animal_image: string
user_name: string
user_phone: string
status: ClaimStatus
applied_at: string
processed_at: string
}
// 动物查询参数
export interface AnimalQueryParams {
page?: number
pageSize?: number
limit?: number
keyword?: string
type?: AnimalType
status?: AnimalStatus
species?: string
status?: string
merchant_id?: number
start_date?: string
end_date?: string
}
// 认领记录查询参数
export interface ClaimQueryParams {
page?: number
pageSize?: number
keyword?: string
status?: ClaimStatus
export interface AnimalCreateData {
name: string
species: string
breed: string
age: number
gender: string
description: string
image: string
merchant_id: number
price: number
status?: string
}
// API响应结构
export interface ApiResponse<T> {
success: boolean
code: number
message: string
data: T
pagination?: {
current: number
pageSize: number
total: number
totalPages: number
}
export interface AnimalUpdateData {
name?: string
species?: string
breed?: string
age?: number
gender?: string
description?: string
image?: string
merchant_id?: number
price?: number
status?: string
}
// 获取动物列表
export const getAnimals = async (params?: AnimalQueryParams): Promise<ApiResponse<Animal[]>> => {
return request.get<ApiResponse<Animal[]>>('/animals', { params })
}
export const getAnimals = (params?: AnimalQueryParams) =>
request.get<{ success: boolean; code: number; message: string; data: { animals: Animal[]; pagination: any } }>('/animals', { params })
// 获取动物详情
export const getAnimal = async (id: number): Promise<ApiResponse<Animal>> => {
return request.get<ApiResponse<Animal>>(`/animals/${id}`)
}
export const getAnimal = (id: number) =>
request.get<{ success: boolean; code: number; message: string; data: { animal: Animal } }>(`/animals/${id}`)
// 创建动物
export const createAnimal = async (animalData: Partial<Animal>): Promise<ApiResponse<Animal>> => {
return request.post<ApiResponse<Animal>>('/animals', animalData)
}
export const createAnimal = (data: AnimalCreateData) =>
request.post<{ success: boolean; code: number; message: string; data: { animal: Animal } }>('/animals', data)
// 更新动物
export const updateAnimal = async (id: number, animalData: Partial<Animal>): Promise<ApiResponse<Animal>> => {
return request.put<ApiResponse<Animal>>(`/animals/${id}`, animalData)
}
export const updateAnimal = (id: number, data: AnimalUpdateData) =>
request.put<{ success: boolean; code: number; message: string; data: { animal: Animal } }>(`/animals/${id}`, data)
// 删除动物
export const deleteAnimal = async (id: number): Promise<ApiResponse<void>> => {
return request.delete<ApiResponse<void>>(`/animals/${id}`)
}
export const deleteAnimal = (id: number) =>
request.delete<{ success: boolean; code: number; message: string }>(`/animals/${id}`)
// 获取认领记录列表
export const getAnimalClaims = async (params?: ClaimQueryParams): Promise<ApiResponse<AnimalClaim[]>> => {
return request.get<ApiResponse<AnimalClaim[]>>('/animals/claims', { params })
}
// 更新动物状态
export const updateAnimalStatus = (id: number, status: string) =>
request.put<{ success: boolean; code: number; message: string }>(`/animals/${id}/status`, { status })
// 审核动物认领(通过)
export const approveAnimalClaim = async (id: number): Promise<ApiResponse<void>> => {
return request.post<ApiResponse<void>>(`/animals/claims/${id}/approve`)
}
// 拒绝动物认领
export const rejectAnimalClaim = async (id: number, reason: string): Promise<ApiResponse<void>> => {
return request.post<ApiResponse<void>>(`/animals/claims/${id}/reject`, { reason })
export default {
getAnimals,
getAnimal,
createAnimal,
updateAnimal,
deleteAnimal,
updateAnimalStatus
}

View File

@@ -3,7 +3,7 @@ import { message } from 'ant-design-vue'
import type { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
// API基础配置
const baseURL = import.meta.env.VITE_API_BASE_URL || '/api'
const baseURL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:3100/api'
const timeout = parseInt(import.meta.env.VITE_API_TIMEOUT || '10000')
// 创建axios实例
@@ -17,7 +17,7 @@ const api: AxiosInstance = axios.create({
// 请求拦截器
api.interceptors.request.use(
(config: AxiosRequestConfig) => {
(config) => {
// 添加认证token
const token = localStorage.getItem('admin_token')
if (token && config.headers) {
@@ -124,18 +124,18 @@ export const authAPI = {
success: boolean
data: {
token: string
user: any
admin: any
}
}>('/auth/admin/login', credentials),
}>('/admin/login', credentials),
// 获取当前用户信息
getCurrentUser: () =>
request.get<{
success: boolean
data: {
user: any
admin: any
}
}>('/auth/me'),
}>('/admin/profile'),
// 刷新token
refreshToken: () =>
@@ -159,4 +159,13 @@ export * from './order'
export * from './promotion'
export * from './system'
// 为避免命名冲突,单独导出模块
export { default as userAPI } from './user'
export { default as merchantAPI } from './merchant'
export { default as travelAPI } from './travel'
export { default as animalAPI } from './animal'
export { default as orderAPI } from './order'
export { default as promotionAPI } from './promotion'
export { default as systemAPI } from './system'
export default api

View File

@@ -1,73 +1,88 @@
import { request } from '@/api'
import type { AxiosResponse } from 'axios'
import { request } from '.'
// 商家类型
export type MerchantType = 'flower_shop' | 'activity_organizer' | 'farm_owner'
// 商家状态
export type MerchantStatus = 'pending' | 'approved' | 'rejected' | 'disabled'
// 商家数据结构
// 定义商家相关类型
export interface Merchant {
id: number
business_name: string
merchant_type: MerchantType
business_license: string
legal_representative: string
contact_person: string
contact_phone: string
status: MerchantStatus
contact_email: string
address: string
business_scope: string
status: string
remark: string
created_at: string
updated_at: string
}
// 商家查询参数
export interface MerchantQueryParams {
page?: number
pageSize?: number
keyword?: string
type?: MerchantType
status?: MerchantStatus
limit?: number
business_name?: string
contact_person?: string
contact_phone?: string
status?: string
start_date?: string
end_date?: string
}
// API响应结构
export interface ApiResponse<T> {
success: boolean
code: number
message: string
data: T
pagination?: {
current: number
pageSize: number
total: number
totalPages: number
}
export interface MerchantCreateData {
business_name: string
business_license: string
legal_representative: string
contact_person: string
contact_phone: string
contact_email: string
address: string
business_scope: string
status?: string
remark?: string
}
export interface MerchantUpdateData {
business_name?: string
business_license?: string
legal_representative?: string
contact_person?: string
contact_phone?: string
contact_email?: string
address?: string
business_scope?: string
status?: string
remark?: string
}
// 获取商家列表
export const getMerchants = async (params?: MerchantQueryParams): Promise<ApiResponse<Merchant[]>> => {
return request.get<ApiResponse<Merchant[]>>('/merchants', { params })
}
export const getMerchants = (params?: MerchantQueryParams) =>
request.get<{ success: boolean; code: number; message: string; data: { merchants: Merchant[]; pagination: any } }>('/merchants', { params })
// 获取商家详情
export const getMerchant = async (id: number): Promise<ApiResponse<Merchant>> => {
return request.get<ApiResponse<Merchant>>(`/merchants/${id}`)
}
export const getMerchant = (id: number) =>
request.get<{ success: boolean; code: number; message: string; data: { merchant: Merchant } }>(`/merchants/${id}`)
// 审核商家(通过)
export const approveMerchant = async (id: number): Promise<ApiResponse<void>> => {
return request.post<ApiResponse<void>>(`/merchants/${id}/approve`)
}
// 创建商家
export const createMerchant = (data: MerchantCreateData) =>
request.post<{ success: boolean; code: number; message: string; data: { merchant: Merchant } }>('/merchants', data)
// 拒绝商家入驻申请
export const rejectMerchant = async (id: number, reason: string): Promise<ApiResponse<void>> => {
return request.post<ApiResponse<void>>(`/merchants/${id}/reject`, { reason })
}
// 更新商家
export const updateMerchant = (id: number, data: MerchantUpdateData) =>
request.put<{ success: boolean; code: number; message: string; data: { merchant: Merchant } }>(`/merchants/${id}`, data)
// 禁用商家
export const disableMerchant = async (id: number): Promise<ApiResponse<void>> => {
return request.post<ApiResponse<void>>(`/merchants/${id}/disable`)
}
// 删除商家
export const deleteMerchant = (id: number) =>
request.delete<{ success: boolean; code: number; message: string }>(`/merchants/${id}`)
// 启用商家
export const enableMerchant = async (id: number): Promise<ApiResponse<void>> => {
return request.post<ApiResponse<void>>(`/merchants/${id}/enable`)
// 更新商家状态
export const updateMerchantStatus = (id: number, status: string) =>
request.put<{ success: boolean; code: number; message: string }>(`/merchants/${id}/status`, { status })
export default {
getMerchants,
getMerchant,
createMerchant,
updateMerchant,
deleteMerchant,
updateMerchantStatus
}

View File

@@ -1,4 +1,4 @@
import { request } from '@/api'
import { request } from '.'
import type { AxiosResponse } from 'axios'
// 订单状态
@@ -13,31 +13,42 @@ export interface Order {
order_no: string
user_id: number
user_name: string
user_phone: string
amount: number
status: OrderStatus
payment_method: PaymentMethod
merchant_id: number
merchant_name: string
product_id: number
product_name: string
product_type: string
quantity: number
unit_price: number
total_amount: number
status: string
payment_method: string
payment_time: string
refund_status: string
remark: string
created_at: string
paid_at: string
shipped_at: string
completed_at: string
updated_at: string
}
// 订单查询参数
export interface OrderQueryParams {
page?: number
pageSize?: number
limit?: number
order_no?: string
status?: OrderStatus
orderTime?: [string, string]
user_name?: string
merchant_name?: string
product_type?: string
status?: string
payment_method?: string
start_date?: string
end_date?: string
}
// 统计数据
export interface OrderStatistics {
today_orders: number
today_sales: number
month_orders: number
month_sales: number
// 订单更新参数
export interface OrderUpdateData {
status?: string
refund_status?: string
remark?: string
}
// API响应结构
@@ -55,41 +66,29 @@ export interface ApiResponse<T> {
}
// 获取订单列表
export const getOrders = async (params?: OrderQueryParams): Promise<ApiResponse<Order[]>> => {
return request.get<ApiResponse<Order[]>>('/orders', { params })
}
export const getOrders = (params?: OrderQueryParams) =>
request.get<{ success: boolean; code: number; message: string; data: { orders: Order[]; pagination: any } }>('/orders', { params })
// 获取订单详情
export const getOrder = async (id: number): Promise<ApiResponse<Order>> => {
return request.get<ApiResponse<Order>>(`/orders/${id}`)
}
export const getOrder = (id: number) =>
request.get<{ success: boolean; code: number; message: string; data: { order: Order } }>(`/orders/${id}`)
// 更新订单
export const updateOrder = (id: number, data: OrderUpdateData) =>
request.put<{ success: boolean; code: number; message: string; data: { order: Order } }>(`/orders/${id}`, data)
// 删除订单
export const deleteOrder = (id: number) =>
request.delete<{ success: boolean; code: number; message: string }>(`/orders/${id}`)
// 更新订单状态
export const updateOrderStatus = async (id: number, status: OrderStatus): Promise<ApiResponse<void>> => {
return request.put<ApiResponse<void>>(`/orders/${id}/status`, { status })
}
export const updateOrderStatus = (id: number, status: string) =>
request.put<{ success: boolean; code: number; message: string }>(`/orders/${id}/status`, { status })
// 发货
export const shipOrder = async (id: number): Promise<ApiResponse<void>> => {
return request.post<ApiResponse<void>>(`/orders/${id}/ship`)
}
// 完成订单
export const completeOrder = async (id: number): Promise<ApiResponse<void>> => {
return request.post<ApiResponse<void>>(`/orders/${id}/complete`)
}
// 取消订单
export const cancelOrder = async (id: number): Promise<ApiResponse<void>> => {
return request.post<ApiResponse<void>>(`/orders/${id}/cancel`)
}
// 退款
export const refundOrder = async (id: number): Promise<ApiResponse<void>> => {
return request.post<ApiResponse<void>>(`/orders/${id}/refund`)
}
// 获取订单统计数据
export const getOrderStatistics = async (): Promise<ApiResponse<OrderStatistics>> => {
return request.get<ApiResponse<OrderStatistics>>('/orders/statistics')
export default {
getOrders,
getOrder,
updateOrder,
deleteOrder,
updateOrderStatus
}

View File

@@ -1,5 +1,81 @@
import { request } from '@/api'
import type { AxiosResponse } from 'axios'
import { request } from '.'
// 定义促销相关类型
export interface Promotion {
id: number
title: string
description: string
type: string
discount_value: number
start_date: string
end_date: string
status: string
created_at: string
updated_at: string
}
export interface PromotionQueryParams {
page?: number
limit?: number
title?: string
type?: string
status?: string
start_date?: string
end_date?: string
}
export interface PromotionCreateData {
title: string
description: string
type: string
discount_value: number
start_date: string
end_date: string
status?: string
}
export interface PromotionUpdateData {
title?: string
description?: string
type?: string
discount_value?: number
start_date?: string
end_date?: string
status?: string
}
// 获取促销列表
export const getPromotions = (params?: PromotionQueryParams) =>
request.get<{ success: boolean; code: number; message: string; data: { promotions: Promotion[]; pagination: any } }>('/promotions', { params })
// 获取促销详情
export const getPromotion = (id: number) =>
request.get<{ success: boolean; code: number; message: string; data: { promotion: Promotion } }>(`/promotions/${id}`)
// 创建促销
export const createPromotion = (data: PromotionCreateData) =>
request.post<{ success: boolean; code: number; message: string; data: { promotion: Promotion } }>('/promotions', data)
// 更新促销
export const updatePromotion = (id: number, data: PromotionUpdateData) =>
request.put<{ success: boolean; code: number; message: string; data: { promotion: Promotion } }>(`/promotions/${id}`, data)
// 删除促销
export const deletePromotion = (id: number) =>
request.delete<{ success: boolean; code: number; message: string }>(`/promotions/${id}`)
// 更新促销状态
export const updatePromotionStatus = (id: number, status: string) =>
request.put<{ success: boolean; code: number; message: string }>(`/promotions/${id}/status`, { status })
export default {
getPromotions,
getPromotion,
createPromotion,
updatePromotion,
deletePromotion,
updatePromotionStatus
}
// 推广活动状态
export type PromotionStatus = 'active' | 'upcoming' | 'ended' | 'paused'

View File

@@ -1,5 +1,4 @@
import { request } from '@/api'
import type { AxiosResponse } from 'axios'
import { request } from '.'
// 服务类型
export type ServiceType = 'database' | 'cache' | 'mq'
@@ -9,112 +8,79 @@ export type ServiceStatus = 'running' | 'stopped'
// 系统服务数据结构
export interface Service {
id: number
id: string
name: string
type: ServiceType
status: ServiceStatus
host: string
port: number
description: string
created_at: string
updated_at: string
}
export interface ServiceQueryParams {
page?: number
limit?: number
type?: ServiceType
status?: ServiceStatus
}
export interface ServiceUpdateData {
status: ServiceStatus
}
// 系统配置
export interface SystemSettings {
systemName: string
systemVersion: string
maintenanceMode: boolean
sessionTimeout: number
pageSize: number
enableSwagger: boolean
}
// 系统信息
export interface SystemInfo {
version: string
environment: string
uptime: string
startTime: string
}
// 数据库状态
export interface DatabaseStatus {
status: ServiceStatus
type: string
connections: string
queriesPerMinute: number
}
// 缓存状态
export interface CacheStatus {
status: ServiceStatus
memoryUsage: string
hitRate: string
keyCount: number
}
// API响应结构
export interface ApiResponse<T> {
success: boolean
code: number
message: string
data: T
}
// 获取系统服务列表
export const getServices = async (): Promise<ApiResponse<Service[]>> => {
return request.get<ApiResponse<Service[]>>('/system/services')
export const getServices = (params?: ServiceQueryParams) =>
request.get<{ success: boolean; code: number; message: string; data: { services: Service[]; pagination: any } }>('/system/services', { params })
// 更新系统服务状态
export const updateServiceStatus = (id: string, data: ServiceUpdateData) =>
request.put<{ success: boolean; code: number; message: string }>(`/system/services/${id}/status`, data)
// 定义系统配置相关类型
export interface SystemConfig {
id: string
name: string
value: string
type: string
group: string
description: string
created_at: string
updated_at: string
}
// 启动服务
export const startService = async (id: number): Promise<ApiResponse<void>> => {
return request.post<ApiResponse<void>>(`/system/services/${id}/start`)
export interface SystemConfigQueryParams {
page?: number
limit?: number
group?: string
}
// 停止服务
export const stopService = async (id: number): Promise<ApiResponse<void>> => {
return request.post<ApiResponse<void>>(`/system/services/${id}/stop`)
export interface SystemConfigUpdateData {
value: string
}
// 获取系统信息
export const getSystemInfo = async (): Promise<ApiResponse<SystemInfo>> => {
return request.get<ApiResponse<SystemInfo>>('/system/info')
}
// 获取数据库状态
export const getDatabaseStatus = async (): Promise<ApiResponse<DatabaseStatus>> => {
return request.get<ApiResponse<DatabaseStatus>>('/system/database')
}
// 获取缓存状态
export const getCacheStatus = async (): Promise<ApiResponse<CacheStatus>> => {
return request.get<ApiResponse<CacheStatus>>('/system/cache')
}
// 获取系统配置
export const getSystemSettings = async (): Promise<ApiResponse<SystemSettings>> => {
return request.get<ApiResponse<SystemSettings>>('/system/settings')
}
// 获取系统配置列表
export const getSystemConfigs = (params?: SystemConfigQueryParams) =>
request.get<{ success: boolean; code: number; message: string; data: { configs: SystemConfig[]; pagination: any } }>('/system-configs', { params })
// 更新系统配置
export const updateSystemSettings = async (settings: SystemSettings): Promise<ApiResponse<void>> => {
return request.put<ApiResponse<void>>('/system/settings', settings)
}
export const updateSystemConfig = (id: string, data: SystemConfigUpdateData) =>
request.put<{ success: boolean; code: number; message: string }>(`/system-configs/${id}`, data)
// 获取操作日志
export const getOperationLogs = async (params?: {
page?: number
pageSize?: number
search?: string
startDate?: string
endDate?: string
}): Promise<ApiResponse<any[]>> => {
return request.get<ApiResponse<any[]>>('/system/logs', { params })
}
// 获取系统统计信息
export const getSystemStats = () =>
request.get<{ success: boolean; code: number; message: string; data: any }>('/system/stats')
// 清理缓存
export const clearCache = async (): Promise<ApiResponse<void>> => {
return request.post<ApiResponse<void>>('/system/cache/clear')
}
// 获取系统日志
export const getSystemLogs = (params?: { page?: number; limit?: number; level?: string }) =>
request.get<{ success: boolean; code: number; message: string; data: { logs: any[]; pagination: any } }>('/system/logs', { params })
// 系统健康检查
export const healthCheck = async (): Promise<ApiResponse<any>> => {
return request.get<ApiResponse<any>>('/system/health')
}
export default {
getServices,
updateServiceStatus,
getSystemConfigs,
updateSystemConfig,
getSystemStats,
getSystemLogs
}

View File

@@ -1,68 +1,82 @@
import { request } from '@/api'
import type { AxiosResponse } from 'axios'
import { request } from '.'
// 旅行计划状态
export type TravelStatus = 'recruiting' | 'full' | 'completed' | 'cancelled'
// 旅行计划数据结构
export interface TravelPlan {
// 定义结伴游相关类型
export interface Travel {
id: number
destination: string
title: string
description: string
start_date: string
end_date: string
budget: number
max_members: number
current_members: number
status: TravelStatus
creator: string
destination: string
max_participants: number
current_participants: number
price: number
status: string
created_at: string
updated_at: string
}
// 旅行计划查询参数
export interface TravelQueryParams {
page?: number
pageSize?: number
limit?: number
title?: string
destination?: string
status?: TravelStatus
travelTime?: [string, string]
status?: string
start_date?: string
end_date?: string
}
// API响应结构
export interface ApiResponse<T> {
success: boolean
code: number
message: string
data: T
pagination?: {
current: number
pageSize: number
total: number
totalPages: number
}
export interface TravelCreateData {
title: string
description: string
start_date: string
end_date: string
destination: string
max_participants: number
price: number
status?: string
}
// 获取旅行计划列表
export const getTravelPlans = async (params?: TravelQueryParams): Promise<ApiResponse<TravelPlan[]>> => {
return request.get<ApiResponse<TravelPlan[]>>('/travel/plans', { params })
export interface TravelUpdateData {
title?: string
description?: string
start_date?: string
end_date?: string
destination?: string
max_participants?: number
price?: number
status?: string
}
// 获取旅行计划详情
export const getTravelPlan = async (id: number): Promise<ApiResponse<TravelPlan>> => {
return request.get<ApiResponse<TravelPlan>>(`/travel/plans/${id}`)
}
// 获取结伴游列表
export const getTravels = (params?: TravelQueryParams) =>
request.get<{ success: boolean; code: number; message: string; data: { travels: Travel[]; pagination: any } }>('/travels', { params })
// 审核旅行计划
export const approveTravelPlan = async (id: number): Promise<ApiResponse<void>> => {
return request.post<ApiResponse<void>>(`/travel/plans/${id}/approve`)
}
// 获取结伴游详情
export const getTravel = (id: number) =>
request.get<{ success: boolean; code: number; message: string; data: { travel: Travel } }>(`/travels/${id}`)
// 拒绝旅行计划
export const rejectTravelPlan = async (id: number, reason: string): Promise<ApiResponse<void>> => {
return request.post<ApiResponse<void>>(`/travel/plans/${id}/reject`, { reason })
}
// 创建结伴游
export const createTravel = (data: TravelCreateData) =>
request.post<{ success: boolean; code: number; message: string; data: { travel: Travel } }>('/travels', data)
// 关闭旅行计划
export const closeTravelPlan = async (id: number): Promise<ApiResponse<void>> => {
return request.post<ApiResponse<void>>(`/travel/plans/${id}/close`)
// 更新结伴游
export const updateTravel = (id: number, data: TravelUpdateData) =>
request.put<{ success: boolean; code: number; message: string; data: { travel: Travel } }>(`/travels/${id}`, data)
// 删除结伴游
export const deleteTravel = (id: number) =>
request.delete<{ success: boolean; code: number; message: string }>(`/travels/${id}`)
// 更新结伴游状态
export const updateTravelStatus = (id: number, status: string) =>
request.put<{ success: boolean; code: number; message: string }>(`/travels/${id}/status`, { status })
export default {
getTravels,
getTravel,
createTravel,
updateTravel,
deleteTravel,
updateTravelStatus
}

View File

@@ -1,81 +1,109 @@
import { request } from '@/api'
import type { AxiosResponse } from 'axios'
import { request } from '.'
// 用户状态类型
export type UserStatus = 'active' | 'inactive' | 'banned'
// 用户等级类型
export type UserLevel = number
// 用户数据结构
// 定义用户相关类型
export interface User {
id: number
openid: string
username: string
nickname: string
email: string
phone: string
avatar: string
gender: string
birthday: string
phone: string
email: string
status: UserStatus
level: UserLevel
points: number
level: number
balance: number
travel_count: number
animal_adopt_count: number
flower_order_count: number
status: string
remark: string
created_at: string
updated_at: string
last_login_at: string
}
// 用户查询参数
export interface UserQueryParams {
page?: number
pageSize?: number
keyword?: string
status?: UserStatus
registerTime?: [string, string]
limit?: number
username?: string
nickname?: string
phone?: string
status?: string
start_date?: string
end_date?: string
}
// API响应结构
export interface ApiResponse<T> {
export interface UserCreateData {
username: string
password: string
nickname?: string
email?: string
phone?: string
gender?: string
birthday?: string
status?: string
remark?: string
}
export interface UserUpdateData {
username?: string
password?: string
nickname?: string
email?: string
phone?: string
gender?: string
birthday?: string
status?: string
remark?: string
}
export interface ApiResponse<T = any> {
success: boolean
code: number
message: string
data: T
pagination?: {
current: number
pageSize: number
total: number
totalPages: number
}
}
// 获取用户列表
export const getUsers = async (params?: UserQueryParams): Promise<ApiResponse<User[]>> => {
return request.get<ApiResponse<User[]>>('/users', { params })
}
export const getUsers = (params?: UserQueryParams) =>
request.get<ApiResponse<{ users: User[]; pagination: any }>>('/users', { params })
// 获取用户详情
export const getUser = async (id: number): Promise<ApiResponse<User>> => {
return request.get<ApiResponse<User>>(`/users/${id}`)
}
export const getUser = (id: number) =>
request.get<ApiResponse<User>>(`/users/${id}`)
// 创建用户
export const createUser = async (userData: Partial<User>): Promise<ApiResponse<User>> => {
return request.post<ApiResponse<User>>('/users', userData)
}
export const createUser = (data: UserCreateData) =>
request.post<ApiResponse<User>>('/users', data)
// 更新用户
export const updateUser = async (id: number, userData: Partial<User>): Promise<ApiResponse<User>> => {
return request.put<ApiResponse<User>>(`/users/${id}`, userData)
}
export const updateUser = (id: number, data: UserUpdateData) =>
request.put<ApiResponse<User>>(`/users/${id}`, data)
// 删除用户
export const deleteUser = async (id: number): Promise<ApiResponse<void>> => {
return request.delete<ApiResponse<void>>(`/users/${id}`)
}
export const deleteUser = (id: number) =>
request.delete<ApiResponse<void>>(`/users/${id}`)
// 批量操作用户
export const batchUsers = async (
ids: number[],
action: 'delete' | 'ban' | 'activate'
): Promise<ApiResponse<void>> => {
return request.post<ApiResponse<void>>('/users/batch', { ids, action })
// 批量删除用户
export const batchDeleteUsers = (ids: number[]) =>
request.post<ApiResponse<void>>('/users/batch-delete', { ids })
// 更新用户状态
export const updateUserStatus = (id: number, status: string) =>
request.put<ApiResponse<User>>(`/users/${id}/status`, { status })
// 重置用户密码
export const resetUserPassword = (id: number, password: string) =>
request.put<ApiResponse<User>>(`/users/${id}/password`, { password })
export default {
getUsers,
getUser,
createUser,
updateUser,
deleteUser,
batchDeleteUsers,
updateUserStatus,
resetUserPassword
}

View File

@@ -69,6 +69,7 @@ import { useRouter } from 'vue-router'
import { UserOutlined, LockOutlined } from '@ant-design/icons-vue'
import { message } from 'ant-design-vue'
import { useAppStore } from '@/stores/app'
import { authAPI } from '@/api'
interface FormState {
username: string
@@ -91,25 +92,22 @@ const onFinish = async (values: FormState) => {
loading.value = true
try {
// 模拟登录过程
console.log('登录信息:', values)
// TODO: 调用真实登录接口
// const response = await authAPI.login(values)
// 模拟登录成功
await new Promise(resolve => setTimeout(resolve, 1000))
// 调用真实登录接口
const response = await authAPI.login(values)
// 保存token
localStorage.setItem('admin_token', 'mock_token_123456')
if (response?.data?.token) {
localStorage.setItem('admin_token', response.data.token)
} else {
throw new Error('登录响应中缺少token')
}
// 更新用户状态
appStore.setUser({
id: 1,
username: values.username,
nickname: '管理员',
role: 'admin'
})
if (response?.data?.admin) {
appStore.setUser(response.data.admin)
} else {
throw new Error('登录响应中缺少用户信息')
}
message.success('登录成功!')
@@ -117,9 +115,10 @@ const onFinish = async (values: FormState) => {
const redirect = router.currentRoute.value.query.redirect as string
router.push(redirect || '/dashboard')
} catch (error) {
} catch (error: any) {
console.error('登录失败:', error)
message.error('登录失败,请检查用户名和密码')
const errorMessage = error.message || '登录失败,请检查用户名和密码'
message.error(errorMessage)
} finally {
loading.value = false
}
@@ -174,10 +173,11 @@ const onFinishFailed = (errorInfo: any) => {
border-top: 1px solid #f0f0f0;
}
.login-footer p {
.login-footer {
text-align: center;
margin-top: 30px;
color: #999;
font-size: 12px;
margin: 0;
}
:deep(.ant-input-affix-wrapper) {

View File

@@ -137,7 +137,7 @@
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { ref, reactive, onMounted, h } from 'vue'
import { message, Modal } from 'ant-design-vue'
import type { TableProps } from 'ant-design-vue'
import {
@@ -150,7 +150,7 @@ import {
StopOutlined,
PlayCircleOutlined
} from '@ant-design/icons-vue'
import { getMerchants, approveMerchant, rejectMerchant, disableMerchant, enableMerchant } from '@/api/merchant'
import { getMerchants, getMerchant, approveMerchant, rejectMerchant, disableMerchant, enableMerchant } from '@/api/merchant'
import type { Merchant } from '@/api/merchant'
interface SearchForm {
@@ -314,8 +314,33 @@ const handleTableChange: TableProps['onChange'] = (pag) => {
loadMerchants()
}
const handleView = (record: Merchant) => {
message.info(`查看商家: ${record.business_name}`)
const handleView = async (record: Merchant) => {
try {
const response = await getMerchant(record.id)
Modal.info({
title: '商家详情',
width: 600,
content: h('div', { class: 'merchant-detail-modal' }, [
h('a-descriptions', {
column: 1,
bordered: true
}, [
h('a-descriptions-item', { label: '商家ID' }, response.data.id),
h('a-descriptions-item', { label: '商家名称' }, response.data.business_name),
h('a-descriptions-item', { label: '商家类型' }, getTypeText(response.data.merchant_type)),
h('a-descriptions-item', { label: '联系人' }, response.data.contact_person),
h('a-descriptions-item', { label: '联系电话' }, response.data.contact_phone),
h('a-descriptions-item', { label: '状态' }, [
h('a-tag', { color: getStatusColor(response.data.status) }, getStatusText(response.data.status))
]),
h('a-descriptions-item', { label: '入驻时间' }, response.data.created_at),
h('a-descriptions-item', { label: '更新时间' }, response.data.updated_at)
])
])
})
} catch (error) {
message.error('获取商家详情失败')
}
}
const handleApprove = async (record: Merchant) => {

View File

@@ -1,162 +1,241 @@
<template>
<div class="order-management">
<a-page-header title="订单管理" sub-title="管理花束订单和交易记录">
<a-page-header
title="订单管理"
sub-title="管理系统订单信息"
>
<template #extra>
<a-space>
<a-button @click="handleRefresh">
<template #icon><ReloadOutlined /></template>
<template #icon>
<ReloadOutlined />
</template>
刷新
</a-button>
<a-button type="primary" @click="showStats">
<template #icon><BarChartOutlined /></template>
销售统计
</a-button>
</a-space>
</template>
</a-page-header>
<a-tabs v-model:activeKey="activeTab" @change="handleTabChange">
<a-tab-pane key="orders" tab="订单列表">
<!-- 统计卡片 -->
<a-row :gutter="16" class="stats-row">
<a-col :span="6">
<a-card>
<div class="search-container">
<a-form layout="inline" :model="searchForm">
<a-form-item label="订单号">
<a-input v-model:value="searchForm.order_no" placeholder="输入订单号" allow-clear />
</a-form-item>
<a-form-item label="状态">
<a-select v-model:value="searchForm.status" placeholder="全部状态" style="width: 120px" allow-clear>
<a-select-option value="pending">待支付</a-select-option>
<a-select-option value="paid">已支付</a-select-option>
<a-select-option value="shipped">已发货</a-select-option>
<a-select-option value="completed">已完成</a-select-option>
<a-select-option value="cancelled">已取消</a-select-option>
<a-select-option value="refunded">已退款</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="下单时间">
<a-range-picker v-model:value="searchForm.orderTime" :placeholder="['开始时间', '结束时间']" />
</a-form-item>
<a-form-item>
<a-button type="primary" @click="handleSearch">
<template #icon><SearchOutlined /></template>
搜索
</a-button>
<a-button style="margin-left: 8px" @click="handleReset">重置</a-button>
</a-form-item>
</a-form>
</div>
<a-table
:columns="orderColumns"
:data-source="orderList"
:loading="loading"
:pagination="pagination"
:row-key="record => record.id"
@change="handleTableChange"
<a-statistic
title="今日订单"
:value="statistics.today_orders"
:precision="0"
suffix="单"
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'order_no'">
<a-typography-text copyable>{{ record.order_no }}</a-typography-text>
</template>
<template v-else-if="column.key === 'amount'">¥{{ record.amount }}</template>
<template v-else-if="column.key === 'status'">
<a-tag :color="getStatusColor(record.status)">{{ getStatusText(record.status) }}</a-tag>
</template>
<template v-else-if="column.key === 'payment_method'">
<span>{{ getPaymentMethodText(record.payment_method) }}</span>
</template>
<template v-else-if="column.key === 'actions'">
<a-space :size="8">
<a-button size="small" @click="handleViewOrder(record)">
<EyeOutlined />详情
</a-button>
<template v-if="record.status === 'paid'">
<a-button size="small" type="primary" @click="handleShip(record)">
<CarOutlined />发货
</a-button>
</template>
<template v-if="record.status === 'shipped'">
<a-button size="small" type="primary" @click="handleComplete(record)">
<CheckCircleOutlined />完成
</a-button>
</template>
<template v-if="['pending', 'paid'].includes(record.status)">
<a-button size="small" danger @click="handleCancel(record)">
<CloseOutlined />取消
</a-button>
</template>
<template v-if="record.status === 'paid'">
<a-button size="small" danger @click="handleRefund(record)">
<RollbackOutlined />退款
</a-button>
</template>
</a-space>
</template>
<template #prefix>
<ShoppingCartOutlined />
</template>
</a-table>
</a-statistic>
</a-card>
</a-tab-pane>
</a-col>
<a-col :span="6">
<a-card>
<a-statistic
title="今日销售额"
:value="statistics.today_sales"
:precision="2"
suffix="元"
:value-style="{ color: '#cf1322' }"
>
<template #prefix>
<MoneyCollectOutlined />
</template>
</a-statistic>
</a-card>
</a-col>
<a-col :span="6">
<a-card>
<a-statistic
title="本月订单"
:value="statistics.month_orders"
:precision="0"
suffix="单"
>
<template #prefix>
<CalendarOutlined />
</template>
</a-statistic>
</a-card>
</a-col>
<a-col :span="6">
<a-card>
<a-statistic
title="本月销售额"
:value="statistics.month_sales"
:precision="2"
suffix="元"
:value-style="{ color: '#cf1322' }"
>
<template #prefix>
<DollarOutlined />
</template>
</a-statistic>
</a-card>
</a-col>
</a-row>
<a-tab-pane key="statistics" tab="销售统计">
<a-card title="销售数据概览">
<a-row :gutter="16">
<a-col :span="6">
<a-statistic title="今日订单" :value="statistics.today_orders" :precision="0" :value-style="{ color: '#3f8600' }">
<template #prefix><ShoppingOutlined /></template>
</a-statistic>
</a-col>
<a-col :span="6">
<a-statistic title="今日销售额" :value="statistics.today_sales" :precision="2" prefix="¥" :value-style="{ color: '#cf1322' }" />
</a-col>
<a-col :span="6">
<a-statistic title="本月订单" :value="statistics.month_orders" :precision="0" :value-style="{ color: '#1890ff' }" />
</a-col>
<a-col :span="6">
<a-statistic title="本月销售额" :value="statistics.month_sales" :precision="2" prefix="¥" :value-style="{ color: '#722ed1' }" />
</a-col>
</a-row>
</a-card>
<a-card>
<!-- 搜索区域 -->
<div class="search-container">
<a-form layout="inline" :model="searchForm">
<a-form-item label="订单号">
<a-input
v-model:value="searchForm.order_no"
placeholder="请输入订单号"
allow-clear
/>
</a-form-item>
<a-form-item label="状态">
<a-select
v-model:value="searchForm.status"
placeholder="全部状态"
style="width: 120px"
allow-clear
>
<a-select-option value="pending">待支付</a-select-option>
<a-select-option value="paid">已支付</a-select-option>
<a-select-option value="shipped">已发货</a-select-option>
<a-select-option value="completed">已完成</a-select-option>
<a-select-option value="cancelled">已取消</a-select-option>
<a-select-option value="refunded">已退款</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="下单时间">
<a-range-picker
v-model:value="searchForm.orderTime"
:placeholder="['开始时间', '结束时间']"
/>
</a-form-item>
<a-form-item>
<a-button type="primary" @click="handleSearch">
<template #icon>
<SearchOutlined />
</template>
搜索
</a-button>
<a-button style="margin-left: 8px" @click="handleReset">
重置
</a-button>
</a-form-item>
</a-form>
</div>
<a-card title="销售趋势" style="margin-top: 16px;">
<div style="height: 300px;">
<div style="display: flex; align-items: center; justify-content: center; height: 100%; color: #999;">
<BarChartOutlined style="font-size: 48px; margin-right: 12px;" />
<span>销售趋势图表开发中</span>
</div>
</div>
</a-card>
</a-tab-pane>
</a-tabs>
<!-- 订单表格 -->
<a-table
:columns="columns"
:data-source="orderList"
:loading="loading"
:pagination="pagination"
:row-key="record => record.id"
@change="handleTableChange"
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'amount'">
<span class="amount-text">¥{{ record.amount }}</span>
</template>
<template v-else-if="column.key === 'status'">
<a-tag :color="getStatusColor(record.status)">
{{ getStatusText(record.status) }}
</a-tag>
</template>
<template v-else-if="column.key === 'actions'">
<a-space :size="8">
<a-button size="small" @click="handleView(record)">
<EyeOutlined />
查看
</a-button>
<template v-if="record.status === 'pending'">
<a-button size="small" type="primary" @click="handlePay(record)">
<PayCircleOutlined />
支付
</a-button>
</template>
<template v-else-if="record.status === 'paid'">
<a-button size="small" type="primary" @click="handleShip(record)">
<SendOutlined />
发货
</a-button>
</template>
<template v-else-if="record.status === 'shipped'">
<a-button size="small" type="primary" @click="handleComplete(record)">
<CheckCircleOutlined />
完成
</a-button>
</template>
<a-dropdown>
<a-button size="small">
更多
<DownOutlined />
</a-button>
<template #overlay>
<a-menu>
<a-menu-item
v-if="['pending', 'paid'].includes(record.status)"
@click="handleCancel(record)"
>
<CloseCircleOutlined />
取消
</a-menu-item>
<a-menu-item
v-if="['paid', 'shipped', 'completed'].includes(record.status)"
@click="handleRefund(record)"
>
<RedoOutlined />
退款
</a-menu-item>
</a-menu>
</template>
</a-dropdown>
</a-space>
</template>
</template>
</a-table>
</a-card>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { ref, reactive, onMounted, h } from 'vue'
import { message, Modal } from 'ant-design-vue'
import type { TableProps } from 'ant-design-vue'
import {
ReloadOutlined,
ShoppingCartOutlined,
MoneyCollectOutlined,
CalendarOutlined,
DollarOutlined,
SearchOutlined,
BarChartOutlined,
ReloadOutlined,
EyeOutlined,
CarOutlined,
PayCircleOutlined,
SendOutlined,
CheckCircleOutlined,
CloseOutlined,
RollbackOutlined,
ShoppingOutlined
CloseCircleOutlined,
RedoOutlined,
DownOutlined
} from '@ant-design/icons-vue'
import { getOrders, updateOrderStatus, getOrderStatistics } from '@/api/order'
import {
getOrders,
getOrder,
getOrderStatistics,
updateOrderStatus,
shipOrder,
completeOrder,
cancelOrder,
refundOrder
} from '@/api/order'
import type { Order, OrderStatistics } from '@/api/order'
interface SearchForm {
@@ -165,8 +244,13 @@ interface SearchForm {
orderTime: any[]
}
const activeTab = ref('orders')
const loading = ref(false)
const statistics = ref<OrderStatistics>({
today_orders: 0,
today_sales: 0,
month_orders: 0,
month_sales: 0
})
const searchForm = reactive<SearchForm>({
order_no: '',
@@ -174,13 +258,6 @@ const searchForm = reactive<SearchForm>({
orderTime: []
})
const statistics = reactive<OrderStatistics>({
today_orders: 0,
today_sales: 0,
month_orders: 0,
month_sales: 0
})
const orderList = ref<Order[]>([])
const pagination = reactive({
current: 1,
@@ -191,25 +268,66 @@ const pagination = reactive({
showTotal: (total: number) => `共 ${total} 条记录`
})
const orderColumns = [
{ title: '订单号', key: 'order_no', width: 160 },
{ title: '用户', dataIndex: 'user_name', key: 'user_name', width: 100 },
{ title: '联系电话', dataIndex: 'user_phone', key: 'user_phone', width: 120 },
{ title: '金额', key: 'amount', width: 100, align: 'center' },
{ title: '状态', key: 'status', width: 100, align: 'center' },
{ title: '支付方式', key: 'payment_method', width: 100, align: 'center' },
{ title: '下单时间', dataIndex: 'created_at', key: 'created_at', width: 150 },
{ title: '操作', key: 'actions', width: 200, align: 'center' }
const columns = [
{
title: '订单号',
dataIndex: 'order_no',
key: 'order_no',
width: 150
},
{
title: '用户',
dataIndex: 'user_name',
key: 'user_name',
width: 100
},
{
title: '联系电话',
dataIndex: 'user_phone',
key: 'user_phone',
width: 120
},
{
title: '金额',
key: 'amount',
width: 100,
align: 'right'
},
{
title: '状态',
key: 'status',
width: 100,
align: 'center'
},
{
title: '支付方式',
dataIndex: 'payment_method',
key: 'payment_method',
width: 100
},
{
title: '下单时间',
dataIndex: 'created_at',
key: 'created_at',
width: 120
},
{
title: '操作',
key: 'actions',
width: 200,
align: 'center'
}
]
// 状态映射
const getStatusColor = (status: string) => {
const colors = {
pending: 'orange',
paid: 'blue',
shipped: 'green',
completed: 'purple',
shipped: 'purple',
completed: 'green',
cancelled: 'red',
refunded: 'default'
refunded: 'red'
}
return colors[status as keyof typeof colors] || 'default'
}
@@ -226,21 +344,24 @@ const getStatusText = (status: string) => {
return texts[status as keyof typeof texts] || '未知'
}
// 支付方式映射
const getPaymentMethodText = (method: string) => {
const texts = {
wechat: '微信支付',
alipay: '支付宝',
bank: '银行',
bank: '银行转账',
balance: '余额支付'
}
return texts[method as keyof typeof texts] || '未知'
}
// 生命周期
onMounted(() => {
loadOrders()
loadStatistics()
})
// 方法
const loadOrders = async () => {
loading.value = true
try {
@@ -263,20 +384,12 @@ const loadOrders = async () => {
const loadStatistics = async () => {
try {
const response = await getOrderStatistics()
Object.assign(statistics, response.data)
statistics.value = response.data
} catch (error) {
message.error('加载统计数据失败')
}
}
const handleTabChange = (key: string) => {
if (key === 'orders') {
loadOrders()
} else if (key === 'statistics') {
loadStatistics()
}
}
const handleSearch = () => {
pagination.current = 1
loadOrders()
@@ -293,11 +406,8 @@ const handleReset = () => {
}
const handleRefresh = () => {
if (activeTab.value === 'orders') {
loadOrders()
} else {
loadStatistics()
}
loadOrders()
loadStatistics()
message.success('数据已刷新')
}
@@ -307,17 +417,60 @@ const handleTableChange: TableProps['onChange'] = (pag) => {
loadOrders()
}
const handleViewOrder = (record: Order) => {
message.info(`查看订单: ${record.order_no}`)
const handleView = async (record: Order) => {
try {
const response = await getOrder(record.id)
Modal.info({
title: '订单详情',
width: 600,
content: h('div', { class: 'order-detail-modal' }, [
h('a-descriptions', {
column: 1,
bordered: true
}, [
h('a-descriptions-item', { label: '订单号' }, response.data.order_no),
h('a-descriptions-item', { label: '用户' }, response.data.user_name),
h('a-descriptions-item', { label: '联系电话' }, response.data.user_phone),
h('a-descriptions-item', { label: '订单金额' }, `¥${response.data.amount}`),
h('a-descriptions-item', { label: '状态' }, [
h('a-tag', { color: getStatusColor(response.data.status) }, getStatusText(response.data.status))
]),
h('a-descriptions-item', { label: '支付方式' }, getPaymentMethodText(response.data.payment_method)),
h('a-descriptions-item', { label: '下单时间' }, response.data.created_at),
h('a-descriptions-item', { label: '支付时间' }, response.data.paid_at || '-'),
h('a-descriptions-item', { label: '发货时间' }, response.data.shipped_at || '-'),
h('a-descriptions-item', { label: '完成时间' }, response.data.completed_at || '-')
])
])
})
} catch (error) {
message.error('获取订单详情失败')
}
}
const handlePay = async (record: Order) => {
Modal.confirm({
title: '确认支付',
content: `确定要标记订单 "${record.order_no}" 为已支付状态吗?`,
onOk: async () => {
try {
await updateOrderStatus(record.id, 'paid')
message.success('订单状态已更新')
loadOrders()
} catch (error) {
message.error('操作失败')
}
}
})
}
const handleShip = async (record: Order) => {
Modal.confirm({
title: '确认发货',
content: `确定要发货订单 "${record.order_no}" 吗?`,
content: `确定要标记订单 "${record.order_no}" 为已发货状态吗?`,
onOk: async () => {
try {
await updateOrderStatus(record.id, 'shipped')
await shipOrder(record.id)
message.success('订单已发货')
loadOrders()
} catch (error) {
@@ -330,10 +483,10 @@ const handleShip = async (record: Order) => {
const handleComplete = async (record: Order) => {
Modal.confirm({
title: '确认完成',
content: `确定要完成订单 "${record.order_no}" 吗?`,
content: `确定要标记订单 "${record.order_no}" 为已完成状态吗?`,
onOk: async () => {
try {
await updateOrderStatus(record.id, 'completed')
await completeOrder(record.id)
message.success('订单已完成')
loadOrders()
} catch (error) {
@@ -349,7 +502,7 @@ const handleCancel = async (record: Order) => {
content: `确定要取消订单 "${record.order_no}" 吗?`,
onOk: async () => {
try {
await updateOrderStatus(record.id, 'cancelled')
await cancelOrder(record.id)
message.success('订单已取消')
loadOrders()
} catch (error) {
@@ -362,11 +515,11 @@ const handleCancel = async (record: Order) => {
const handleRefund = async (record: Order) => {
Modal.confirm({
title: '确认退款',
content: `确定要退款订单 "${record.order_no}" 吗?退款金额: ¥${record.amount}`,
content: `确定要订单 "${record.order_no}" 办理退款吗?`,
onOk: async () => {
try {
await updateOrderStatus(record.id, 'refunded')
message.success('退款申请已提交')
await refundOrder(record.id)
message.success('订单已退款')
loadOrders()
} catch (error) {
message.error('操作失败')
@@ -374,15 +527,14 @@ const handleRefund = async (record: Order) => {
}
})
}
const showStats = () => {
activeTab.value = 'statistics'
loadStatistics()
}
</script>
<style scoped lang="less">
.order-management {
.stats-row {
margin-bottom: 24px;
}
.search-container {
margin-bottom: 16px;
padding: 16px;
@@ -393,5 +545,15 @@ const showStats = () => {
margin-bottom: 16px;
}
}
.amount-text {
font-weight: 500;
color: #cf1322;
}
}
:deep(.ant-table-thead > tr > th) {
background: #fafafa;
font-weight: 600;
}
</style>

View File

@@ -236,8 +236,8 @@
</template>
<script setup lang="ts">
import { ref, reactive, computed, onMounted } from 'vue'
import { message, Modal, type FormInstance } from 'ant-design-vue'
import { ref, reactive, computed, onMounted, h } from 'vue'
import { message, Modal, type FormInstance, TableProps } from 'ant-design-vue'
import {
UserAddOutlined,
SearchOutlined,
@@ -248,10 +248,10 @@ import {
StopOutlined,
PlayCircleOutlined,
WarningOutlined,
DownOutlined
DownOutlined,
type TableProps
} from '@ant-design/icons-vue'
import type { TableProps } from 'ant-design-vue'
import { getUsers, updateUser, createUser, deleteUser } from '@/api/user'
import { getUsers, getUser, updateUser, createUser, deleteUser } from '@/api/user'
import type { User } from '@/api/user'
interface SearchForm {
@@ -473,9 +473,44 @@ const showCreateModal = () => {
modalVisible.value = true
}
const handleView = (record: User) => {
// TODO: 跳转到用户详情页
message.info(`查看用户: ${record.nickname}`)
const handleView = async (record: User) => {
try {
const response = await getUser(record.id)
Modal.info({
title: '用户详情',
width: 600,
content: h('div', { class: 'user-detail-modal' }, [
h('a-descriptions', {
column: 1,
bordered: true
}, [
h('a-descriptions-item', { label: '用户ID' }, response.data.id),
h('a-descriptions-item', { label: '用户名' }, response.data.username),
h('a-descriptions-item', { label: '昵称' }, response.data.nickname),
h('a-descriptions-item', { label: '头像' }, [
h('a-avatar', {
src: response.data.avatar,
size: 64,
shape: 'square'
})
]),
h('a-descriptions-item', { label: '性别' }, response.data.gender),
h('a-descriptions-item', { label: '生日' }, response.data.birthday),
h('a-descriptions-item', { label: '手机号' }, response.data.phone),
h('a-descriptions-item', { label: '邮箱' }, response.data.email),
h('a-descriptions-item', { label: '状态' }, [
h('a-tag', { color: getStatusColor(response.data.status) }, getStatusText(response.data.status))
]),
h('a-descriptions-item', { label: '等级' }, `Lv.${response.data.level}`),
h('a-descriptions-item', { label: '积分' }, response.data.points),
h('a-descriptions-item', { label: '注册时间' }, response.data.created_at),
h('a-descriptions-item', { label: '更新时间' }, response.data.updated_at)
])
])
})
} catch (error) {
message.error('获取用户详情失败')
}
}
const handleEdit = (record: User) => {

View File

@@ -1,127 +1,80 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
interface AppState {
// 应用配置
name: string
version: string
// 用户信息
user: any
// 系统状态
loading: boolean
error: string | null
// 功能开关
features: {
analytics: boolean
debug: boolean
}
}
import { reactive } from 'vue'
import { authAPI } from '@/api'
import type { Admin } from '@/types/user'
export const useAppStore = defineStore('app', () => {
// 状态
const state = ref<AppState>({
name: import.meta.env.VITE_APP_NAME || '结伴客后台管理系统',
version: import.meta.env.VITE_APP_VERSION || '1.0.0',
user: null,
const state = reactive({
user: null as Admin | null,
loading: false,
error: null,
features: {
analytics: import.meta.env.VITE_FEATURE_ANALYTICS === 'true',
debug: import.meta.env.VITE_FEATURE_DEBUG === 'true'
}
initialized: false
})
// Getters
const isAuthenticated = () => !!state.value.user
const isLoading = () => state.value.loading
const hasError = () => state.value.error !== null
// Actions
const initializeApp = async () => {
state.value.loading = true
try {
// 初始化应用配置
console.log('🚀 初始化应用:', state.value.name, state.value.version)
// 检查用户登录状态
await checkAuthStatus()
// 初始化分析工具(如果启用)
if (state.value.features.analytics) {
initAnalytics()
}
state.value.error = null
} catch (error) {
state.value.error = error instanceof Error ? error.message : '初始化失败'
console.error('❌ 应用初始化失败:', error)
} finally {
state.value.loading = false
}
// 设置用户信息
const setUser = (user: Admin) => {
state.user = user
}
const checkAuthStatus = async () => {
// 清除用户信息
const clearUser = () => {
state.user = null
localStorage.removeItem('admin_token')
}
// 初始化应用
const initialize = async () => {
if (state.initialized) return
state.loading = true
try {
// 检查本地存储的token
const token = localStorage.getItem('admin_token')
if (token) {
// TODO: 验证token有效性
// const user = await authAPI.verifyToken(token)
// state.value.user = user
console.log('✅ 用户已登录')
} else {
console.log(' 用户未登录')
// 获取用户信息
const response = await authAPI.getCurrentUser()
// 修复数据结构访问问题
state.user = response.data.admin
}
} catch (error) {
console.warn('⚠️ 认证状态检查失败:', error)
// 清除无效的token
localStorage.removeItem('admin_token')
console.error('初始化失败:', error)
clearUser()
} finally {
state.loading = false
state.initialized = true
}
}
const setUser = (user: any) => {
state.value.user = user
}
const setLoading = (loading: boolean) => {
state.value.loading = loading
}
const setError = (error: string | null) => {
state.value.error = error
}
const clearError = () => {
state.value.error = null
// 登录
const login = async (credentials: { username: string; password: string }) => {
state.loading = true
try {
const response = await authAPI.login(credentials)
// 保存token
localStorage.setItem('admin_token', response.data.token)
// 设置用户信息
state.user = response.data.admin
return response
} finally {
state.loading = false
}
}
// 退出登录
const logout = () => {
state.value.user = null
localStorage.removeItem('admin_token')
// TODO: 调用退出接口
}
// 私有方法
const initAnalytics = () => {
if (state.value.features.analytics) {
console.log('📊 初始化分析工具')
// TODO: 集成分析工具
}
clearUser()
}
return {
// 状态
state,
// Getters
isAuthenticated,
isLoading,
hasError,
// Actions
initializeApp,
setUser,
setLoading,
setError,
clearError,
clearUser,
initialize,
login,
logout
}
})
})
export type { Admin }

View File

@@ -1,8 +1,10 @@
export { useAppStore } from './app'
// 导出其他store模块
// export { useUserStore } from './user'
// export { useTravelStore } from './travel'
// export { useAnimalStore } from './animal'
// export { useMerchantStore } from './merchant'
// export { useOrderStore } from './order'
// export { usePromotionStore } from './promotion'
// 导出其他store模块
export { useUserStore } from './modules/user.js'
export { useMerchantStore } from './modules/merchant.js'
export { useOrderStore } from './modules/order.js'
export { useAnimalStore } from './modules/animal.js'
export { useActivityStore } from './modules/activity.js'
export { useContentStore } from './modules/content.js'
export { useStatisticsStore } from './modules/statistics.js'
export { usePermissionStore } from './modules/permission.js'

View File

@@ -0,0 +1,249 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
import type { Activity, ActivityQueryParams, ActivityStatus, ActivityType, ActivityStatistics } from '../../types/activity'
interface ActivityState {
activities: Activity[]
currentActivity: Activity | null
loading: boolean
totalCount: number
queryParams: ActivityQueryParams
}
export const useActivityStore = defineStore('activity', () => {
// 状态
const activities = ref<Activity[]>([])
const currentActivity = ref<Activity | null>(null)
const loading = ref(false)
const totalCount = ref(0)
const queryParams = ref<ActivityQueryParams>({
page: 1,
pageSize: 10,
keyword: '',
status: undefined,
activityType: undefined,
organizerId: undefined,
startDate: '',
endDate: ''
})
// 获取活动列表
const fetchActivities = async (params?: ActivityQueryParams) => {
loading.value = true
try {
// 模拟数据
const mockActivities: Activity[] = [
{
id: 1,
title: '周末郊游',
activityType: 'travel',
description: '周末一起去郊游,享受大自然',
organizerId: 101,
organizerName: '张组织者',
location: '北京市朝阳公园',
startTime: '2024-01-20 09:00:00',
endTime: '2024-01-20 17:00:00',
maxParticipants: 20,
currentParticipants: 15,
status: 'active',
price: 50.00,
createTime: '2024-01-15 14:30:00',
images: ['/images/activity1.jpg'],
tags: ['郊游', '户外', '社交']
},
{
id: 2,
title: '电影之夜',
activityType: 'movie',
description: '一起观看最新上映的电影',
organizerId: 102,
organizerName: '李组织者',
location: '北京市万达影城',
startTime: '2024-01-22 19:00:00',
endTime: '2024-01-22 22:00:00',
maxParticipants: 10,
currentParticipants: 8,
status: 'active',
price: 35.00,
createTime: '2024-01-16 10:15:00',
images: ['/images/activity2.jpg'],
tags: ['电影', '娱乐', '社交']
}
]
activities.value = mockActivities
totalCount.value = mockActivities.length
if (params) {
queryParams.value = { ...queryParams.value, ...params }
}
} catch (error) {
console.error('获取活动列表失败:', error)
throw error
} finally {
loading.value = false
}
}
// 获取活动详情
const fetchActivityDetail = async (activityId: number) => {
loading.value = true
try {
// 模拟数据
const mockActivity: Activity = {
id: activityId,
title: `活动${activityId}`,
activityType: 'travel',
description: '活动描述',
organizerId: 100 + activityId,
organizerName: '组织者',
location: '地点',
startTime: '2024-01-20 10:00:00',
endTime: '2024-01-20 18:00:00',
maxParticipants: 20,
currentParticipants: 10,
status: 'active',
price: 50.00,
createTime: '2024-01-15 14:30:00',
images: ['/images/activity.jpg'],
tags: ['标签1', '标签2']
}
currentActivity.value = mockActivity
return mockActivity
} catch (error) {
console.error('获取活动详情失败:', error)
throw error
} finally {
loading.value = false
}
}
// 更新活动状态
const updateActivityStatus = async (activityId: number, status: ActivityStatus) => {
try {
// 模拟状态更新
const activity = activities.value.find(a => a.id === activityId)
if (activity) {
activity.status = status
}
if (currentActivity.value && currentActivity.value.id === activityId) {
currentActivity.value.status = status
}
return true
} catch (error) {
console.error('更新活动状态失败:', error)
throw error
}
}
// 审核活动
const auditActivity = async (activityId: number, auditStatus: ActivityStatus, auditRemark?: string) => {
try {
// 模拟审核操作
const activity = activities.value.find(a => a.id === activityId)
if (activity) {
activity.status = auditStatus
activity.auditRemark = auditRemark
activity.auditTime = new Date().toISOString()
}
if (currentActivity.value && currentActivity.value.id === activityId) {
currentActivity.value.status = auditStatus
currentActivity.value.auditRemark = auditRemark
currentActivity.value.auditTime = new Date().toISOString()
}
return true
} catch (error) {
console.error('审核活动失败:', error)
throw error
}
}
// 搜索活动
const searchActivities = async (keyword: string) => {
queryParams.value.keyword = keyword
return fetchActivities(queryParams.value)
}
// 重置查询参数
const resetQueryParams = () => {
queryParams.value = {
page: 1,
pageSize: 10,
keyword: '',
status: undefined,
activityType: undefined,
organizerId: undefined,
startDate: '',
endDate: ''
}
}
// 获取活动统计
const getActivityStatistics = async () => {
try {
// 模拟统计数据
return {
totalActivities: 89,
activeActivities: 67,
completedActivities: 22,
cancelledActivities: 5,
totalParticipants: 456,
totalRevenue: 12800.50,
averageParticipation: 5.12,
activityTypeDistribution: {
travel: 25,
movie: 18,
dinner: 15,
game: 12,
other: 19
},
statusDistribution: {
pending: 8,
active: 67,
completed: 22,
cancelled: 5
},
popularActivities: activities.value.slice(0, 5)
}
} catch (error) {
console.error('获取活动统计失败:', error)
throw error
}
}
// 导出活动数据
const exportActivities = async () => {
try {
// 模拟导出功能
const csvContent = activities.value.map(activity =>
`${activity.id},${activity.title},${activity.organizerName},${activity.activityType},${activity.status},${activity.currentParticipants}`
).join('\n')
return csvContent
} catch (error) {
console.error('导出活动数据失败:', error)
throw error
}
}
return {
activities,
currentActivity,
loading,
totalCount,
queryParams,
fetchActivities,
fetchActivityDetail,
updateActivityStatus,
auditActivity,
searchActivities,
resetQueryParams,
getActivityStatistics,
exportActivities
}
})

View File

@@ -0,0 +1,245 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
import type { Animal, AnimalQueryParams, AnimalStatus, AnimalType, MedicalRecord, AnimalAdoptionRecord } from '../../types/animal'
interface AnimalState {
animals: Animal[]
currentAnimal: Animal | null
loading: boolean
totalCount: number
queryParams: AnimalQueryParams
}
export const useAnimalStore = defineStore('animal', () => {
// 状态
const animals = ref<Animal[]>([])
const currentAnimal = ref<Animal | null>(null)
const loading = ref(false)
const totalCount = ref(0)
const queryParams = ref<AnimalQueryParams>({
page: 1,
pageSize: 10,
keyword: '',
status: undefined,
animalType: undefined,
farmId: undefined,
startDate: '',
endDate: ''
})
// 获取动物列表
const fetchAnimals = async (params?: AnimalQueryParams) => {
loading.value = true
try {
// 模拟数据
const mockAnimals: Animal[] = [
{
id: 1,
name: '小白',
animalType: 'sheep',
breed: '绵羊',
age: 2,
gender: 'male',
status: 'available',
farmId: 1,
farmName: '快乐农场',
price: 299.00,
description: '温顺可爱的小绵羊',
images: ['/images/sheep1.jpg'],
healthStatus: 'excellent',
adoptionCount: 5,
createTime: '2024-01-10 09:00:00',
features: ['温顺', '亲人', '爱吃草']
},
{
id: 2,
name: '小花',
animalType: 'cow',
breed: '奶牛',
age: 3,
gender: 'female',
status: 'adopted',
farmId: 1,
farmName: '快乐农场',
price: 499.00,
description: '产奶量高的奶牛',
images: ['/images/cow1.jpg'],
healthStatus: 'good',
adoptionCount: 3,
createTime: '2024-01-12 14:30:00',
features: ['产奶量高', '健康', '温顺']
}
]
animals.value = mockAnimals
totalCount.value = mockAnimals.length
if (params) {
queryParams.value = { ...queryParams.value, ...params }
}
} catch (error) {
console.error('获取动物列表失败:', error)
throw error
} finally {
loading.value = false
}
}
// 获取动物详情
const fetchAnimalDetail = async (animalId: number) => {
loading.value = true
try {
// 模拟数据
const mockAnimal: Animal = {
id: animalId,
name: `动物${animalId}`,
animalType: 'sheep',
breed: '品种',
age: 2,
gender: 'male',
status: 'available',
farmId: 1,
farmName: '测试农场',
price: 199.00,
description: '动物描述',
images: ['/images/animal.jpg'],
healthStatus: 'excellent',
adoptionCount: 0,
createTime: '2024-01-15 10:00:00',
features: ['特征1', '特征2']
}
currentAnimal.value = mockAnimal
return mockAnimal
} catch (error) {
console.error('获取动物详情失败:', error)
throw error
} finally {
loading.value = false
}
}
// 更新动物状态
const updateAnimalStatus = async (animalId: number, status: AnimalStatus) => {
try {
// 模拟状态更新
const animal = animals.value.find((a: Animal) => a.id === animalId)
if (animal) {
animal.status = status
}
if (currentAnimal.value && currentAnimal.value.id === animalId) {
currentAnimal.value.status = status
}
return true
} catch (error) {
console.error('更新动物状态失败:', error)
throw error
}
}
// 添加新动物
const addAnimal = async (animalData: Omit<Animal, 'id' | 'createTime'>) => {
try {
// 模拟添加操作
const newAnimal: Animal = {
...animalData,
id: Date.now(),
createTime: new Date().toISOString()
}
animals.value.unshift(newAnimal)
totalCount.value += 1
return newAnimal
} catch (error) {
console.error('添加动物失败:', error)
throw error
}
}
// 更新动物信息
const updateAnimal = async (animalId: number, updateData: Partial<Animal>) => {
try {
// 模拟更新操作
const animal = animals.value.find((a: Animal) => a.id === animalId)
if (animal) {
Object.assign(animal, updateData)
}
if (currentAnimal.value && currentAnimal.value.id === animalId) {
Object.assign(currentAnimal.value, updateData)
}
return true
} catch (error) {
console.error('更新动物信息失败:', error)
throw error
}
}
// 搜索动物
const searchAnimals = async (keyword: string) => {
queryParams.value.keyword = keyword
return fetchAnimals(queryParams.value)
}
// 重置查询参数
const resetQueryParams = () => {
queryParams.value = {
page: 1,
pageSize: 10,
keyword: '',
status: undefined,
animalType: undefined,
farmId: undefined,
startDate: '',
endDate: ''
}
}
// 获取动物统计
const getAnimalStatistics = async () => {
try {
// 模拟统计数据
return {
totalAnimals: 156,
availableAnimals: 89,
adoptedAnimals: 67,
totalAdoptions: 245,
averageAdoptionPrice: 256.80,
animalTypeDistribution: {
sheep: 45,
cow: 32,
pig: 28,
chicken: 51
},
statusDistribution: {
available: 89,
adopted: 67
},
topAnimals: animals.value.slice(0, 5)
}
} catch (error) {
console.error('获取动物统计失败:', error)
throw error
}
}
return {
animals,
currentAnimal,
loading,
totalCount,
queryParams,
fetchAnimals,
fetchAnimalDetail,
updateAnimalStatus,
addAnimal,
updateAnimal,
searchAnimals,
resetQueryParams,
getAnimalStatistics
}
})

View File

@@ -0,0 +1,439 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
import type {
Content,
ContentQueryParams,
ContentStatus,
ContentType,
ContentStatistics,
ContentAuditStatus,
ContentCategory
} from '../../types/content'
// 模拟数据 - 内容列表
const mockContents: Content[] = [
{
id: 1,
title: '西藏自驾游攻略分享',
content: '这次西藏之行非常难忘,沿途风景美不胜收...',
contentType: 'article',
authorId: 101,
authorName: '旅行达人小王',
publishTime: '2024-01-15 10:30:00',
status: 'published',
viewCount: 1250,
likeCount: 89,
commentCount: 45,
shareCount: 23,
auditStatus: 'approved',
category: 'travel',
tags: ['西藏', '自驾', '攻略'],
images: ['/images/tibet1.jpg', '/images/tibet2.jpg'],
isPublic: true,
allowComments: true,
allowSharing: true,
editCount: 2
},
{
id: 2,
title: '认养小羊的快乐时光',
content: '今天去农场看望了我认养的小羊,它长得真快...',
contentType: 'post',
authorId: 102,
authorName: '爱心人士小李',
publishTime: '2024-01-14 15:20:00',
status: 'published',
viewCount: 890,
likeCount: 67,
commentCount: 32,
shareCount: 18,
auditStatus: 'approved',
category: 'animal',
tags: ['认养', '小羊', '农场'],
images: ['/images/sheep1.jpg'],
isPublic: true,
allowComments: true,
allowSharing: true,
editCount: 1
},
{
id: 3,
title: '周末电影聚会邀请',
content: '本周末组织电影观看活动,欢迎喜欢电影的朋友参加...',
contentType: 'activity',
authorId: 103,
authorName: '电影爱好者小张',
publishTime: '2024-01-16 09:00:00',
status: 'draft',
viewCount: 120,
likeCount: 15,
commentCount: 8,
shareCount: 5,
auditStatus: 'pending',
category: 'entertainment',
tags: ['电影', '聚会', '周末'],
isPublic: true,
allowComments: true,
allowSharing: true,
editCount: 3
}
]
// 模拟数据 - 内容统计
const mockContentStats: ContentStatistics = {
totalContents: 1560,
publishedContents: 1200,
draftContents: 200,
deletedContents: 160,
totalViews: 125000,
totalLikes: 8900,
totalComments: 4500,
totalShares: 2300,
averageEngagementRate: 12.5,
contentTypeDistribution: {
article: 600,
post: 800,
activity: 120,
comment: 40,
review: 200
},
categoryDistribution: {
travel: 450,
animal: 380,
entertainment: 280,
food: 200,
sports: 150,
study: 100,
other: 0
},
dailyGrowth: 25,
topContents: mockContents.slice(0, 3),
authorDistribution: {
totalAuthors: 350,
activeAuthors: 280,
newAuthorsThisMonth: 45,
topAuthors: [
{ authorId: 101, authorName: '旅行达人小王', contentCount: 45, totalViews: 12000 },
{ authorId: 102, authorName: '爱心人士小李', contentCount: 38, totalViews: 8900 },
{ authorId: 103, authorName: '电影爱好者小张', contentCount: 32, totalViews: 7600 }
]
}
}
export const useContentStore = defineStore('content', () => {
// 状态
const contents = ref<Content[]>(mockContents)
const currentContent = ref<Content | null>(null)
const contentStats = ref<ContentStatistics>(mockContentStats)
const loading = ref(false)
const error = ref<string | null>(null)
// 获取内容列表
const fetchContents = async (params: ContentQueryParams) => {
loading.value = true
error.value = null
try {
// 模拟API调用
await new Promise(resolve => setTimeout(resolve, 500))
// 简单的过滤和分页逻辑
let filteredContents = mockContents
if (params.keyword) {
filteredContents = filteredContents.filter(content =>
content.title.includes(params.keyword!) ||
content.content.includes(params.keyword!)
)
}
if (params.status) {
filteredContents = filteredContents.filter(content => content.status === params.status)
}
if (params.contentType) {
filteredContents = filteredContents.filter(content => content.contentType === params.contentType)
}
if (params.auditStatus) {
filteredContents = filteredContents.filter(content => content.auditStatus === params.auditStatus)
}
if (params.authorId) {
filteredContents = filteredContents.filter(content => content.authorId === params.authorId)
}
if (params.startTime && params.endTime) {
filteredContents = filteredContents.filter(content =>
content.publishTime >= params.startTime! &&
content.publishTime <= params.endTime!
)
}
// 分页
const start = (params.page - 1) * params.pageSize
const paginatedContents = filteredContents.slice(start, start + params.pageSize)
contents.value = paginatedContents
return {
contents: paginatedContents,
total: filteredContents.length,
page: params.page,
pageSize: params.pageSize
}
} catch (err) {
error.value = '获取内容列表失败'
throw err
} finally {
loading.value = false
}
}
// 获取内容详情
const fetchContentDetail = async (id: number) => {
loading.value = true
error.value = null
try {
await new Promise(resolve => setTimeout(resolve, 300))
const content = mockContents.find((c: Content) => c.id === id)
if (!content) {
throw new Error('内容不存在')
}
currentContent.value = content
return content
} catch (err) {
error.value = '获取内容详情失败'
throw err
} finally {
loading.value = false
}
}
// 审核内容
const auditContent = async (id: number, auditStatus: 'approved' | 'rejected', remark?: string) => {
loading.value = true
error.value = null
try {
await new Promise(resolve => setTimeout(resolve, 500))
const contentIndex = mockContents.findIndex((c: Content) => c.id === id)
if (contentIndex === -1) {
throw new Error('内容不存在')
}
mockContents[contentIndex].auditStatus = auditStatus
if (remark) {
mockContents[contentIndex].auditRemark = remark
}
mockContents[contentIndex].auditTime = new Date().toISOString()
// 更新本地状态
if (currentContent.value?.id === id) {
currentContent.value.auditStatus = auditStatus
currentContent.value.auditRemark = remark
currentContent.value.auditTime = new Date().toISOString()
}
return mockContents[contentIndex]
} catch (err) {
error.value = '审核内容失败'
throw err
} finally {
loading.value = false
}
}
// 更新内容状态
const updateContentStatus = async (id: number, status: 'published' | 'draft' | 'deleted') => {
loading.value = true
error.value = null
try {
await new Promise(resolve => setTimeout(resolve, 300))
const contentIndex = mockContents.findIndex((c: Content) => c.id === id)
if (contentIndex === -1) {
throw new Error('内容不存在')
}
mockContents[contentIndex].status = status
// 更新本地状态
if (currentContent.value?.id === id) {
currentContent.value.status = status
}
return mockContents[contentIndex]
} catch (err) {
error.value = '更新内容状态失败'
throw err
} finally {
loading.value = false
}
}
// 删除内容
const deleteContent = async (id: number) => {
loading.value = true
error.value = null
try {
await new Promise(resolve => setTimeout(resolve, 300))
const contentIndex = mockContents.findIndex((c: Content) => c.id === id)
if (contentIndex === -1) {
throw new Error('内容不存在')
}
mockContents.splice(contentIndex, 1)
// 清除当前内容
if (currentContent.value?.id === id) {
currentContent.value = null
}
return true
} catch (err) {
error.value = '删除内容失败'
throw err
} finally {
loading.value = false
}
}
// 获取内容统计
const fetchContentStatistics = async () => {
loading.value = true
error.value = null
try {
await new Promise(resolve => setTimeout(resolve, 800))
// 模拟实时数据更新
const updatedStats = {
...mockContentStats,
totalContents: mockContents.length,
publishedContents: mockContents.filter(c => c.status === 'published').length,
draftContents: mockContents.filter(c => c.status === 'draft').length,
totalViews: mockContents.reduce((sum, c) => sum + c.viewCount, 0),
totalLikes: mockContents.reduce((sum, c) => sum + c.likeCount, 0),
totalComments: mockContents.reduce((sum, c) => sum + c.commentCount, 0),
totalShares: mockContents.reduce((sum, c) => sum + c.shareCount, 0)
}
contentStats.value = updatedStats
return updatedStats
} catch (err) {
error.value = '获取内容统计失败'
throw err
} finally {
loading.value = false
}
}
// 搜索内容
const searchContents = async (keyword: string, filters?: Partial<ContentQueryParams>) => {
loading.value = true
error.value = null
try {
await new Promise(resolve => setTimeout(resolve, 400))
let results = mockContents.filter(content =>
content.title.includes(keyword) ||
content.content.includes(keyword) ||
content.tags?.some((tag: string) => tag.includes(keyword))
)
if (filters?.status) {
results = results.filter(content => content.status === filters.status)
}
if (filters?.contentType) {
results = results.filter(content => content.contentType === filters.contentType)
}
return results
} catch (err) {
error.value = '搜索内容失败'
throw err
} finally {
loading.value = false
}
}
// 批量操作
const batchOperation = async (ids: number[], operation: 'publish' | 'draft' | 'delete' | 'approve' | 'reject') => {
loading.value = true
error.value = null
try {
await new Promise(resolve => setTimeout(resolve, 600))
const results = []
for (const id of ids) {
const contentIndex = mockContents.findIndex(c => c.id === id)
if (contentIndex !== -1) {
switch (operation) {
case 'publish':
mockContents[contentIndex].status = 'published'
break
case 'draft':
mockContents[contentIndex].status = 'draft'
break
case 'delete':
mockContents.splice(contentIndex, 1)
break
case 'approve':
mockContents[contentIndex].auditStatus = 'approved'
break
case 'reject':
mockContents[contentIndex].auditStatus = 'rejected'
break
}
results.push({ id, success: true })
} else {
results.push({ id, success: false, error: '内容不存在' })
}
}
return results
} catch (err) {
error.value = '批量操作失败'
throw err
} finally {
loading.value = false
}
}
// 重置错误
const clearError = () => {
error.value = null
}
return {
// 状态
contents,
currentContent,
contentStats,
loading,
error,
// 操作
fetchContents,
fetchContentDetail,
auditContent,
updateContentStatus,
deleteContent,
fetchContentStatistics,
searchContents,
batchOperation,
clearError
}
})

View File

@@ -0,0 +1,232 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
import type { Merchant, MerchantQueryParams, MerchantStatus, MerchantAuditStatus } from '../../types/merchant'
interface MerchantState {
merchants: Merchant[]
currentMerchant: Merchant | null
loading: boolean
totalCount: number
queryParams: MerchantQueryParams
}
export const useMerchantStore = defineStore('merchant', () => {
// 状态
const merchants = ref<Merchant[]>([])
const currentMerchant = ref<Merchant | null>(null)
const loading = ref(false)
const totalCount = ref(0)
const queryParams = ref<MerchantQueryParams>({
page: 1,
pageSize: 10,
keyword: '',
status: undefined,
auditStatus: undefined,
startDate: '',
endDate: ''
})
// 获取商家列表
const fetchMerchants = async (params?: MerchantQueryParams) => {
loading.value = true
try {
// 模拟数据
const mockMerchants: Merchant[] = [
{
id: 1,
userId: 101,
shopName: '鲜花坊',
businessLicense: '1234567890',
contactPerson: '张老板',
contactPhone: '13800138001',
contactEmail: 'flower@example.com',
address: '北京市朝阳区',
description: '专业鲜花销售',
status: 'active',
auditStatus: 'approved',
auditTime: '2024-01-10 14:30:00',
registerTime: '2024-01-05 09:00:00',
category: 'flower',
serviceScore: 4.8,
orderCount: 156,
totalRevenue: 12800.50
},
{
id: 2,
userId: 102,
shopName: '快乐农场',
businessLicense: '0987654321',
contactPerson: '李农场主',
contactPhone: '13900139001',
contactEmail: 'farm@example.com',
address: '上海市浦东新区',
description: '动物认领和农场体验',
status: 'active',
auditStatus: 'approved',
auditTime: '2024-01-12 16:20:00',
registerTime: '2024-01-08 10:30:00',
category: 'farm',
serviceScore: 4.9,
orderCount: 89,
totalRevenue: 8900.00
}
]
// 应用搜索过滤
let filteredMerchants = mockMerchants
if (queryParams.value.keyword) {
filteredMerchants = mockMerchants.filter((m: Merchant) => {
return m.shopName.toLowerCase().includes(queryParams.value.keyword.toLowerCase()) ||
m.contactPerson.toLowerCase().includes(queryParams.value.keyword.toLowerCase())
})
}
merchants.value = filteredMerchants
totalCount.value = filteredMerchants.length
if (params) {
queryParams.value = { ...queryParams.value, ...params }
}
} catch (error) {
console.error('获取商家列表失败:', error)
throw error
} finally {
loading.value = false
}
}
// 获取商家详情
const fetchMerchantDetail = async (merchantId: number) => {
loading.value = true
try {
// 模拟数据
const mockMerchant: Merchant = {
id: merchantId,
userId: 100 + merchantId,
shopName: `商家${merchantId}`,
businessLicense: `LICENSE${merchantId}`,
contactPerson: '联系人',
contactPhone: '13800138000',
contactEmail: `merchant${merchantId}@example.com`,
address: '地址',
description: '商家描述',
status: 'active',
auditStatus: 'approved',
auditTime: '2024-01-15 10:00:00',
registerTime: '2024-01-01 09:00:00',
category: 'flower',
serviceScore: 4.5,
orderCount: 100,
totalRevenue: 10000.00
}
currentMerchant.value = mockMerchant
return mockMerchant
} catch (error) {
console.error('获取商家详情失败:', error)
throw error
} finally {
loading.value = false
}
}
// 审核商家
const auditMerchant = async (merchantId: number, auditStatus: MerchantAuditStatus, auditRemark?: string) => {
try {
// 模拟审核操作
const merchant = merchants.value.find(m => m.id === merchantId)
if (merchant) {
merchant.auditStatus = auditStatus
merchant.auditTime = new Date().toISOString()
}
if (currentMerchant.value && currentMerchant.value.id === merchantId) {
currentMerchant.value.auditStatus = auditStatus
currentMerchant.value.auditTime = new Date().toISOString()
}
return true
} catch (error) {
console.error('审核商家失败:', error)
throw error
}
}
// 更新商家状态
const updateMerchantStatus = async (merchantId: number, status: MerchantStatus) => {
try {
// 模拟状态更新
const merchant = merchants.value.find(m => m.id === merchantId)
if (merchant) {
merchant.status = status
}
if (currentMerchant.value && currentMerchant.value.id === merchantId) {
currentMerchant.value.status = status
}
return true
} catch (error) {
console.error('更新商家状态失败:', error)
throw error
}
}
// 搜索商家
const searchMerchants = async (keyword: string) => {
queryParams.value.keyword = keyword
return fetchMerchants(queryParams.value)
}
// 重置查询参数
const resetQueryParams = () => {
queryParams.value = {
page: 1,
pageSize: 10,
keyword: '',
status: undefined,
auditStatus: undefined,
startDate: '',
endDate: ''
}
}
// 获取商家统计
const getMerchantStatistics = async () => {
try {
// 模拟统计数据
return {
totalMerchants: 156,
activeMerchants: 142,
pendingAudit: 8,
rejected: 6,
totalRevenue: 256800.50,
averageScore: 4.7,
categoryDistribution: {
flower: 45,
farm: 32,
activity: 23,
other: 56
}
}
} catch (error) {
console.error('获取商家统计失败:', error)
throw error
}
}
return {
merchants,
currentMerchant,
loading,
totalCount,
queryParams,
fetchMerchants,
fetchMerchantDetail,
auditMerchant,
updateMerchantStatus,
searchMerchants,
resetQueryParams,
getMerchantStatistics
}
})

View File

@@ -0,0 +1,223 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
import type { Order, OrderQueryParams, OrderStatus } from '../../types/order'
export const useOrderStore = defineStore('order', () => {
// 状态
const orders = ref<Order[]>([])
const currentOrder = ref<Order | null>(null)
const loading = ref(false)
const totalCount = ref(0)
const queryParams = ref<OrderQueryParams>({
page: 1,
pageSize: 10,
keyword: '',
status: undefined,
orderType: undefined,
startDate: '',
endDate: ''
})
// 获取订单列表
const fetchOrders = async (params?: OrderQueryParams) => {
loading.value = true
try {
// 模拟数据
const mockOrders: Order[] = [
{
id: 1,
orderNo: 'ORDER202401150001',
userId: 101,
username: 'user1',
merchantId: 1,
shopName: '鲜花坊',
orderType: 'flower',
productName: '玫瑰花束',
quantity: 1,
unitPrice: 198.00,
totalAmount: 198.00,
status: 'completed',
createTime: '2024-01-15 10:30:00',
completeTime: '2024-01-15 14:00:00',
recipientName: '李四',
recipientPhone: '13900139000',
deliveryAddress: '北京市朝阳区',
message: '生日快乐!'
},
{
id: 2,
orderNo: 'ORDER202401140001',
userId: 102,
username: 'user2',
merchantId: 2,
shopName: '快乐农场',
orderType: 'animal',
productName: '小羊认领',
quantity: 1,
unitPrice: 299.00,
totalAmount: 299.00,
status: 'pending',
createTime: '2024-01-14 16:20:00',
recipientName: '王五',
recipientPhone: '13800138001',
deliveryAddress: '上海市浦东新区'
}
]
orders.value = mockOrders
totalCount.value = mockOrders.length
if (params) {
queryParams.value = { ...queryParams.value, ...params }
}
} catch (error) {
console.error('获取订单列表失败:', error)
throw error
} finally {
loading.value = false
}
}
// 获取订单详情
const fetchOrderDetail = async (orderId: number) => {
loading.value = true
try {
// 模拟数据
const mockOrder: Order = {
id: orderId,
orderNo: `ORDER20240115${orderId.toString().padStart(4, '0')}`,
userId: 100 + orderId,
username: `user${orderId}`,
merchantId: orderId,
shopName: `商家${orderId}`,
orderType: 'flower',
productName: '商品',
quantity: 1,
unitPrice: 100.00,
totalAmount: 100.00,
status: 'pending',
createTime: '2024-01-15 10:00:00',
recipientName: '收件人',
recipientPhone: '13800138000',
deliveryAddress: '地址'
}
currentOrder.value = mockOrder
return mockOrder
} catch (error) {
console.error('获取订单详情失败:', error)
throw error
} finally {
loading.value = false
}
}
// 更新订单状态
const updateOrderStatus = async (orderId: number, status: OrderStatus) => {
try {
// 模拟状态更新
const order = orders.value.find((o: Order) => o.id === orderId)
if (order) {
order.status = status
if (status === 'completed') {
order.completeTime = new Date().toISOString()
}
}
if (currentOrder.value && currentOrder.value.id === orderId) {
currentOrder.value.status = status
if (status === 'completed') {
currentOrder.value.completeTime = new Date().toISOString()
}
}
return true
} catch (error) {
console.error('更新订单状态失败:', error)
throw error
}
}
// 搜索订单
const searchOrders = async (keyword: string) => {
queryParams.value.keyword = keyword
return fetchOrders(queryParams.value)
}
// 重置查询参数
const resetQueryParams = () => {
queryParams.value = {
page: 1,
pageSize: 10,
keyword: '',
status: undefined,
orderType: undefined,
startDate: '',
endDate: ''
}
}
// 获取订单统计
const getOrderStatistics = async () => {
try {
// 模拟统计数据
return {
totalOrders: 1256,
pendingOrders: 45,
completedOrders: 987,
cancelledOrders: 224,
totalRevenue: 156800.50,
averageOrderValue: 124.68,
dailyOrderCount: 89,
orderTypeDistribution: {
flower: 456,
animal: 312,
activity: 288,
travel: 200
},
statusDistribution: {
pending: 45,
paid: 156,
shipped: 89,
completed: 987,
cancelled: 224
}
}
} catch (error) {
console.error('获取订单统计失败:', error)
throw error
}
}
// 导出订单数据
const exportOrders = async () => {
try {
// 模拟导出功能
const csvContent = orders.value.map(order =>
`${order.orderNo},${order.username},${order.shopName},${order.productName},${order.totalAmount},${order.status}`
).join('\n')
return csvContent
} catch (error) {
console.error('导出订单数据失败:', error)
throw error
}
}
return {
orders,
currentOrder,
loading,
totalCount,
queryParams,
fetchOrders,
fetchOrderDetail,
updateOrderStatus,
searchOrders,
resetQueryParams,
getOrderStatistics,
exportOrders
}
})

View File

@@ -0,0 +1,721 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
import type {
Permission,
Role,
UserRole,
PermissionQueryParams,
RoleQueryParams,
PermissionStatistics,
AuditLog
} from '../../types/permission'
// 模拟数据 - 权限列表
const mockPermissions: Permission[] = [
{
id: 1,
name: '用户管理',
code: 'user:manage',
description: '管理用户信息的权限',
type: 'module',
parentId: null,
level: 1,
status: 'active',
createTime: '2024-01-01 10:00:00',
updateTime: '2024-01-01 10:00:00',
children: [
{
id: 101,
name: '查看用户',
code: 'user:view',
description: '查看用户列表和详情的权限',
type: 'action',
parentId: 1,
level: 2,
status: 'active',
createTime: '2024-01-01 10:00:00',
updateTime: '2024-01-01 10:00:00'
},
{
id: 102,
name: '编辑用户',
code: 'user:edit',
description: '编辑用户信息的权限',
type: 'action',
parentId: 1,
level: 2,
status: 'active',
createTime: '2024-01-01 10:00:00',
updateTime: '2024-01-01 10:00:00'
},
{
id: 103,
name: '删除用户',
code: 'user:delete',
description: '删除用户的权限',
type: 'action',
parentId: 1,
level: 2,
status: 'active',
createTime: '2024-01-01 10:00:00',
updateTime: '2024-01-01 10:00:00'
}
]
},
{
id: 2,
name: '活动管理',
code: 'activity:manage',
description: '管理活动信息的权限',
type: 'module',
parentId: null,
level: 1,
status: 'active',
createTime: '2024-01-01 10:00:00',
updateTime: '2024-01-01 10:00:00',
children: [
{
id: 201,
name: '查看活动',
code: 'activity:view',
description: '查看活动列表和详情的权限',
type: 'action',
parentId: 2,
level: 2,
status: 'active',
createTime: '2024-01-01 10:00:00',
updateTime: '2024-01-01 10:00:00'
},
{
id: 202,
name: '创建活动',
code: 'activity:create',
description: '创建新活动的权限',
type: 'action',
parentId: 2,
level: 2,
status: 'active',
createTime: '2024-01-01 10:00:00',
updateTime: '2024-01-01 10:00:00'
},
{
id: 203,
name: '审核活动',
code: 'activity:audit',
description: '审核活动内容的权限',
type: 'action',
parentId: 2,
level: 2,
status: 'active',
createTime: '2024-01-01 10:00:00',
updateTime: '2024-01-01 10:00:00'
}
]
},
{
id: 3,
name: '动物管理',
code: 'animal:manage',
description: '管理动物信息的权限',
type: 'module',
parentId: null,
level: 1,
status: 'active',
createTime: '2024-01-01 10:00:00',
updateTime: '2024-01-01 10:00:00',
children: [
{
id: 301,
name: '查看动物',
code: 'animal:view',
description: '查看动物列表和详情的权限',
type: 'action',
parentId: 3,
level: 2,
status: 'active',
createTime: '2024-01-01 10:00:00',
updateTime: '2024-01-01 10:00:00'
},
{
id: 302,
name: '编辑动物',
code: 'animal:edit',
description: '编辑动物信息的权限',
type: 'action',
parentId: 3,
level: 2,
status: 'active',
createTime: '2024-01-01 10:00:00',
updateTime: '2024-01-01 10:00:00'
},
{
id: 303,
name: '认养管理',
code: 'animal:adopt',
description: '管理动物认养流程的权限',
type: 'action',
parentId: 3,
level: 2,
status: 'active',
createTime: '2024-01-01 10:00:00',
updateTime: '2024-01-01 10:00:00'
}
]
}
]
// 模拟数据 - 角色列表
const mockRoles: Role[] = [
{
id: 1,
name: '超级管理员',
code: 'super_admin',
description: '拥有系统所有权限的最高权限角色',
type: 'system',
status: 'active',
permissionIds: [1, 101, 102, 103, 2, 201, 202, 203, 3, 301, 302, 303],
userCount: 3,
createTime: '2024-01-01 10:00:00',
updateTime: '2024-01-01 10:00:00',
permissions: mockPermissions.flatMap(p => p.children || []).filter(p =>
[101, 102, 103, 201, 202, 203, 301, 302, 303].includes(p.id)
)
},
{
id: 2,
name: '内容管理员',
code: 'content_admin',
description: '负责内容审核和管理的角色',
type: 'system',
status: 'active',
permissionIds: [2, 201, 203, 3, 301],
userCount: 5,
createTime: '2024-01-01 10:00:00',
updateTime: '2024-01-01 10:00:00',
permissions: mockPermissions.flatMap(p => p.children || []).filter(p =>
[201, 203, 301].includes(p.id)
)
},
{
id: 3,
name: '用户管理员',
code: 'user_admin',
description: '负责用户管理和支持的角色',
type: 'system',
status: 'active',
permissionIds: [1, 101, 102],
userCount: 8,
createTime: '2024-01-01 10:00:00',
updateTime: '2024-01-01 10:00:00',
permissions: mockPermissions.flatMap(p => p.children || []).filter(p =>
[101, 102].includes(p.id)
)
}
]
// 模拟数据 - 用户角色关联
const mockUserRoles: UserRole[] = [
{ id: 1, userId: 1, roleId: 1, assignTime: '2024-01-01 10:00:00', assignBy: 'system' },
{ id: 2, userId: 2, roleId: 2, assignTime: '2024-01-01 10:00:00', assignBy: 'admin' },
{ id: 3, userId: 3, roleId: 2, assignTime: '2024-01-01 10:00:00', assignBy: 'admin' },
{ id: 4, userId: 4, roleId: 3, assignTime: '2024-01-01 10:00:00', assignBy: 'admin' }
]
// 模拟数据 - 权限统计
const mockPermissionStats: PermissionStatistics = {
totalPermissions: 12,
activePermissions: 12,
inactivePermissions: 0,
totalRoles: 3,
activeRoles: 3,
inactiveRoles: 0,
totalUsersWithRoles: 4,
permissionUsage: {
'user:view': 15,
'user:edit': 8,
'user:delete': 3,
'activity:view': 25,
'activity:create': 12,
'activity:audit': 18,
'animal:view': 20,
'animal:edit': 10,
'animal:adopt': 15
},
roleDistribution: {
'super_admin': 3,
'content_admin': 5,
'user_admin': 8
},
userPermissionStats: {
averagePermissionsPerUser: 6.5,
maxPermissionsPerUser: 9,
minPermissionsPerUser: 2,
usersWithExcessivePermissions: 1
},
auditLogs: {
totalLogs: 156,
permissionChanges: 45,
roleChanges: 32,
userRoleChanges: 79
}
}
// 模拟数据 - 审计日志
const mockAuditLogs: AuditLog[] = [
{
id: 1,
action: 'assign_role',
targetType: 'user',
targetId: 2,
targetName: 'user2',
performerId: 1,
performerName: 'admin',
details: '分配角色: content_admin',
ipAddress: '192.168.1.100',
userAgent: 'Mozilla/5.0',
timestamp: '2024-01-15 14:30:00',
status: 'success'
},
{
id: 2,
action: 'update_permission',
targetType: 'permission',
targetId: 101,
targetName: 'user:view',
performerId: 1,
performerName: 'admin',
details: '更新权限描述',
ipAddress: '192.168.1.100',
userAgent: 'Mozilla/5.0',
timestamp: '2024-01-15 14:25:00',
status: 'success'
},
{
id: 3,
action: 'create_role',
targetType: 'role',
targetId: 3,
targetName: 'user_admin',
performerId: 1,
performerName: 'admin',
details: '创建新角色',
ipAddress: '192.168.1.100',
userAgent: 'Mozilla/5.0',
timestamp: '2024-01-15 14:20:00',
status: 'success'
}
]
export const usePermissionStore = defineStore('permission', () => {
// 状态
const permissions = ref<Permission[]>(mockPermissions)
const roles = ref<Role[]>(mockRoles)
const userRoles = ref<UserRole[]>(mockUserRoles)
const permissionStats = ref<PermissionStatistics>(mockPermissionStats)
const auditLogs = ref<AuditLog[]>(mockAuditLogs)
const loading = ref(false)
const error = ref<string | null>(null)
// 获取权限列表
const fetchPermissions = async (params: PermissionQueryParams) => {
loading.value = true
error.value = null
try {
await new Promise(resolve => setTimeout(resolve, 500))
let filteredPermissions = mockPermissions.flat()
if (params.keyword) {
filteredPermissions = filteredPermissions.filter(permission =>
permission.name.includes(params.keyword!) ||
permission.code.includes(params.keyword!) ||
permission.description.includes(params.keyword!)
)
}
if (params.status) {
filteredPermissions = filteredPermissions.filter(permission => permission.status === params.status)
}
if (params.type) {
filteredPermissions = filteredPermissions.filter(permission => permission.type === params.type)
}
if (params.parentId !== undefined) {
filteredPermissions = filteredPermissions.filter(permission => permission.parentId === params.parentId)
}
// 分页
const start = (params.page - 1) * params.pageSize
const paginatedPermissions = filteredPermissions.slice(start, start + params.pageSize)
permissions.value = paginatedPermissions
return {
permissions: paginatedPermissions,
total: filteredPermissions.length,
page: params.page,
pageSize: params.pageSize
}
} catch (err) {
error.value = '获取权限列表失败'
throw err
} finally {
loading.value = false
}
}
// 获取角色列表
const fetchRoles = async (params: RoleQueryParams) => {
loading.value = true
error.value = null
try {
await new Promise(resolve => setTimeout(resolve, 500))
let filteredRoles = mockRoles
if (params.keyword) {
filteredRoles = filteredRoles.filter(role =>
role.name.includes(params.keyword!) ||
role.code.includes(params.keyword!) ||
role.description.includes(params.keyword!)
)
}
if (params.status) {
filteredRoles = filteredRoles.filter(role => role.status === params.status)
}
if (params.type) {
filteredRoles = filteredRoles.filter(role => role.type === params.type)
}
// 分页
const start = (params.page - 1) * params.pageSize
const paginatedRoles = filteredRoles.slice(start, start + params.pageSize)
roles.value = paginatedRoles
return {
roles: paginatedRoles,
total: filteredRoles.length,
page: params.page,
pageSize: params.pageSize
}
} catch (err) {
error.value = '获取角色列表失败'
throw err
} finally {
loading.value = false
}
}
// 获取用户角色
const fetchUserRoles = async (userId: number) => {
loading.value = true
error.value = null
try {
await new Promise(resolve => setTimeout(resolve, 300))
const userRoles = mockUserRoles.filter(ur => ur.userId === userId)
const roleIds = userRoles.map(ur => ur.roleId)
const userRolesWithDetails = mockRoles
.filter(role => roleIds.includes(role.id))
.map(role => ({
...role,
assignTime: userRoles.find(ur => ur.roleId === role.id)?.assignTime,
assignBy: userRoles.find(ur => ur.roleId === role.id)?.assignBy
}))
return userRolesWithDetails
} catch (err) {
error.value = '获取用户角色失败'
throw err
} finally {
loading.value = false
}
}
// 分配用户角色
const assignUserRole = async (userId: number, roleId: number, assignBy: string) => {
loading.value = true
error.value = null
try {
await new Promise(resolve => setTimeout(resolve, 400))
// 检查是否已分配
const existingAssignment = mockUserRoles.find(ur => ur.userId === userId && ur.roleId === roleId)
if (existingAssignment) {
throw new Error('用户已拥有该角色')
}
const newAssignment: UserRole = {
id: Math.max(...mockUserRoles.map(ur => ur.id)) + 1,
userId,
roleId,
assignTime: new Date().toISOString(),
assignBy
}
mockUserRoles.push(newAssignment)
// 更新角色用户计数
const role = mockRoles.find(r => r.id === roleId)
if (role) {
role.userCount += 1
}
return newAssignment
} catch (err) {
error.value = '分配用户角色失败'
throw err
} finally {
loading.value = false
}
}
// 移除用户角色
const removeUserRole = async (userId: number, roleId: number) => {
loading.value = true
error.value = null
try {
await new Promise(resolve => setTimeout(resolve, 400))
const index = mockUserRoles.findIndex(ur => ur.userId === userId && ur.roleId === roleId)
if (index === -1) {
throw new Error('用户角色关联不存在')
}
mockUserRoles.splice(index, 1)
// 更新角色用户计数
const role = mockRoles.find(r => r.id === roleId)
if (role && role.userCount > 0) {
role.userCount -= 1
}
return true
} catch (err) {
error.value = '移除用户角色失败'
throw err
} finally {
loading.value = false
}
}
// 创建角色
const createRole = async (roleData: Omit<Role, 'id' | 'createTime' | 'updateTime'>) => {
loading.value = true
error.value = null
try {
await new Promise(resolve => setTimeout(resolve, 500))
const newRole: Role = {
...roleData,
id: Math.max(...mockRoles.map(r => r.id)) + 1,
createTime: new Date().toISOString(),
updateTime: new Date().toISOString(),
permissions: mockPermissions.flatMap(p => p.children || []).filter(p =>
roleData.permissionIds.includes(p.id)
)
}
mockRoles.push(newRole)
roles.value = [...mockRoles]
return newRole
} catch (err) {
error.value = '创建角色失败'
throw err
} finally {
loading.value = false
}
}
// 更新角色
const updateRole = async (roleId: number, roleData: Partial<Omit<Role, 'id' | 'createTime'>>) => {
loading.value = true
error.value = null
try {
await new Promise(resolve => setTimeout(resolve, 500))
const index = mockRoles.findIndex(r => r.id === roleId)
if (index === -1) {
throw new Error('角色不存在')
}
mockRoles[index] = {
...mockRoles[index],
...roleData,
updateTime: new Date().toISOString(),
permissions: roleData.permissionIds
? mockPermissions.flatMap(p => p.children || []).filter(p =>
roleData.permissionIds!.includes(p.id)
)
: mockRoles[index].permissions
}
roles.value = [...mockRoles]
return mockRoles[index]
} catch (err) {
error.value = '更新角色失败'
throw err
} finally {
loading.value = false
}
}
// 删除角色
const deleteRole = async (roleId: number) => {
loading.value = true
error.value = null
try {
await new Promise(resolve => setTimeout(resolve, 400))
const index = mockRoles.findIndex(r => r.id === roleId)
if (index === -1) {
throw new Error('角色不存在')
}
// 检查是否有用户使用该角色
const usersWithRole = mockUserRoles.filter(ur => ur.roleId === roleId)
if (usersWithRole.length > 0) {
throw new Error('无法删除有用户使用的角色')
}
mockRoles.splice(index, 1)
roles.value = [...mockRoles]
return true
} catch (err) {
error.value = '删除角色失败'
throw err
} finally {
loading.value = false
}
}
// 获取权限统计
const fetchPermissionStatistics = async () => {
loading.value = true
error.value = null
try {
await new Promise(resolve => setTimeout(resolve, 800))
// 模拟实时数据更新
const stats = {
...mockPermissionStats,
totalUsersWithRoles: mockUserRoles.length,
userPermissionStats: {
...mockPermissionStats.userPermissionStats,
averagePermissionsPerUser: Math.round(
mockUserRoles.reduce((sum, ur) => {
const role = mockRoles.find(r => r.id === ur.roleId)
return sum + (role ? role.permissionIds.length : 0)
}, 0) / mockUserRoles.length
)
}
}
permissionStats.value = stats
return stats
} catch (err) {
error.value = '获取权限统计失败'
throw err
} finally {
loading.value = false
}
}
// 获取审计日志
const fetchAuditLogs = async (page: number, pageSize: number) => {
loading.value = true
error.value = null
try {
await new Promise(resolve => setTimeout(resolve, 600))
const start = (page - 1) * pageSize
const paginatedLogs = mockAuditLogs.slice(start, start + pageSize)
auditLogs.value = paginatedLogs
return {
logs: paginatedLogs,
total: mockAuditLogs.length,
page,
pageSize
}
} catch (err) {
error.value = '获取审计日志失败'
throw err
} finally {
loading.value = false
}
}
// 检查用户权限
const checkUserPermission = async (userId: number, permissionCode: string) => {
loading.value = true
error.value = null
try {
await new Promise(resolve => setTimeout(resolve, 200))
const userRoles = mockUserRoles.filter(ur => ur.userId === userId)
const roleIds = userRoles.map(ur => ur.roleId)
const hasPermission = mockRoles.some(role =>
roleIds.includes(role.id) &&
role.permissions.some(p => p.code === permissionCode)
)
return hasPermission
} catch (err) {
error.value = '检查用户权限失败'
throw err
} finally {
loading.value = false
}
}
// 重置错误
const clearError = () => {
error.value = null
}
return {
// 状态
permissions,
roles,
userRoles,
permissionStats,
auditLogs,
loading,
error,
// 操作
fetchPermissions,
fetchRoles,
fetchUserRoles,
assignUserRole,
removeUserRole,
createRole,
updateRole,
deleteRole,
fetchPermissionStatistics,
fetchAuditLogs,
checkUserPermission,
clearError
}
})

View File

@@ -0,0 +1,668 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
import type {
SystemStats,
UserStats,
ActivityStats,
AnimalStats,
OrderStats,
RevenueStats,
TimeRange,
StatsComparison,
DashboardMetrics
} from '../../types/stats'
// 模拟数据 - 系统统计
const mockSystemStats: SystemStats = {
totalUsers: 12560,
activeUsers: 8560,
newUsersToday: 125,
newUsersThisWeek: 890,
newUsersThisMonth: 3450,
totalActivities: 2560,
activeActivities: 1250,
completedActivities: 890,
totalAnimals: 560,
adoptedAnimals: 320,
availableAnimals: 240,
totalOrders: 4560,
pendingOrders: 120,
completedOrders: 4320,
cancelledOrders: 120,
totalRevenue: 125600,
todayRevenue: 2560,
weekRevenue: 17890,
monthRevenue: 56780,
systemUptime: '99.95%',
averageResponseTime: 120,
errorRate: 0.05,
serverLoad: 45.2
}
// 模拟数据 - 用户统计
const mockUserStats: UserStats = {
totalUsers: 12560,
activeUsers: 8560,
newUsers: {
today: 125,
yesterday: 110,
thisWeek: 890,
lastWeek: 780,
thisMonth: 3450,
lastMonth: 2980
},
userGrowthRate: 15.8,
userRetentionRate: 78.5,
userChurnRate: 5.2,
userDemographics: {
ageDistribution: {
'18-24': 25.6,
'25-34': 38.9,
'35-44': 20.1,
'45-54': 10.2,
'55+': 5.2
},
genderDistribution: {
male: 58.3,
female: 40.1,
other: 1.6
},
locationDistribution: {
'北京': 18.5,
'上海': 15.2,
'广州': 12.8,
'深圳': 11.5,
'其他': 42.0
}
},
userActivity: {
dailyActiveUsers: 8560,
weeklyActiveUsers: 23450,
monthlyActiveUsers: 56780,
averageSessionDuration: 12.5,
averageSessionsPerUser: 3.2
},
userBehavior: {
averageActivitiesPerUser: 2.1,
averageAnimalsAdopted: 0.8,
averageOrdersPerUser: 3.6,
conversionRate: 28.5,
engagementRate: 45.2
},
userLifetimeValue: 156.8,
userAcquisitionCost: 25.4,
userRetentionCost: 12.3
}
// 模拟数据 - 活动统计
const mockActivityStats: ActivityStats = {
totalActivities: 2560,
activeActivities: 1250,
completedActivities: 890,
cancelledActivities: 120,
pendingActivities: 300,
activityGrowthRate: 22.5,
participationStats: {
totalParticipants: 12560,
averageParticipantsPerActivity: 4.9,
repeatParticipants: 45.2,
participationRate: 68.9
},
revenueStats: {
totalRevenue: 125600,
averageRevenuePerActivity: 49.1,
revenueGrowthRate: 28.3,
refundRate: 3.2
},
categoryDistribution: {
travel: 35.6,
movie: 18.9,
dinner: 15.2,
game: 12.8,
sports: 8.5,
study: 6.3,
other: 2.7
},
locationDistribution: {
'北京': 22.5,
'上海': 18.9,
'广州': 15.6,
'深圳': 12.8,
'其他': 30.2
},
timeDistribution: {
'00-06': 5.2,
'06-12': 25.6,
'12-18': 35.8,
'18-24': 33.4
},
organizerPerformance: {
topOrganizers: [
{ organizerId: 101, name: '旅行达人小王', activityCount: 45, revenue: 12500 },
{ organizerId: 102, name: '电影爱好者小李', activityCount: 38, revenue: 9800 },
{ organizerId: 103, name: '美食家小张', activityCount: 32, revenue: 7600 }
],
averageRating: 4.5,
completionRate: 89.2,
cancellationRate: 5.8
}
}
// 模拟数据 - 动物统计
const mockAnimalStats: AnimalStats = {
totalAnimals: 560,
adoptedAnimals: 320,
availableAnimals: 240,
adoptionRate: 57.1,
adoptionGrowthRate: 18.9,
animalTypes: {
dog: 35.6,
cat: 28.9,
sheep: 15.2,
cow: 8.5,
chicken: 6.3,
other: 5.5
},
adoptionStats: {
totalAdoptions: 320,
averageAdoptionTime: 3.2,
repeatAdoptions: 12.5,
adoptionSuccessRate: 92.8
},
careStats: {
totalCareRecords: 12560,
averageCareFrequency: 2.5,
medicalCheckups: 456,
vaccinationRate: 89.5
},
locationDistribution: {
'北京农场': 25.6,
'上海牧场': 18.9,
'广州养殖场': 15.2,
'深圳农场': 12.8,
'其他': 27.5
},
popularAnimals: [
{ animalId: 1, name: '小白', type: 'dog', adoptionCount: 15, viewCount: 1250 },
{ animalId: 2, name: '小花', type: 'cat', adoptionCount: 12, viewCount: 980 },
{ animalId: 3, name: '小羊', type: 'sheep', adoptionCount: 10, viewCount: 760 }
],
revenueStats: {
totalAdoptionRevenue: 45600,
averageAdoptionFee: 142.5,
careProductRevenue: 12500,
totalRevenue: 58100
}
}
// 模拟数据 - 订单统计
const mockOrderStats: OrderStats = {
totalOrders: 4560,
pendingOrders: 120,
completedOrders: 4320,
cancelledOrders: 120,
orderGrowthRate: 25.8,
revenueStats: {
totalRevenue: 125600,
averageOrderValue: 27.5,
revenueGrowthRate: 32.1,
refundAmount: 2560,
netRevenue: 123040
},
orderTypeDistribution: {
activity: 45.6,
adoption: 28.9,
flower: 15.2,
product: 8.5,
other: 2.8
},
paymentStats: {
paymentMethods: {
wechat: 58.9,
alipay: 35.2,
bank: 4.2,
other: 1.7
},
paymentSuccessRate: 98.5,
averagePaymentTime: 2.1,
refundRate: 3.2
},
customerStats: {
repeatCustomers: 45.6,
averageOrdersPerCustomer: 3.2,
customerLifetimeValue: 156.8,
acquisitionCost: 25.4
},
timeDistribution: {
'00-06': 8.5,
'06-12': 22.6,
'12-18': 35.8,
'18-24': 33.1
},
locationDistribution: {
'北京': 20.5,
'上海': 18.2,
'广州': 15.8,
'深圳': 13.5,
'其他': 32.0
}
}
// 模拟数据 - 收入统计
const mockRevenueStats: RevenueStats = {
totalRevenue: 125600,
revenueGrowthRate: 32.1,
dailyRevenue: 2560,
weeklyRevenue: 17890,
monthlyRevenue: 56780,
revenueSources: {
activity: 45.6,
adoption: 28.9,
flower: 15.2,
product: 8.5,
other: 2.8
},
revenueTrends: {
last7Days: [1250, 1380, 1560, 1420, 1680, 1920, 2560],
last30Days: [
1200, 1250, 1380, 1420, 1560, 1480, 1620, 1780, 1920, 2050,
2180, 2250, 2380, 2450, 2560, 2680, 2750, 2850, 2920, 3050,
3120, 3250, 3350, 3420, 3560, 3650, 3780, 3850, 3920, 4050
]
},
customerMetrics: {
averageRevenuePerUser: 156.8,
averageOrderValue: 27.5,
purchaseFrequency: 3.2,
customerLifetimeValue: 456.2
},
geographicDistribution: {
'北京': 22.5,
'上海': 19.8,
'广州': 16.2,
'深圳': 13.8,
'其他': 27.7
},
productPerformance: {
topProducts: [
{ productId: 1, name: '西藏自驾游', revenue: 12500, orders: 256 },
{ productId: 2, name: '小羊认养', revenue: 9800, orders: 189 },
{ productId: 3, name: '玫瑰花束', revenue: 7600, orders: 152 }
],
averageProfitMargin: 35.2,
returnOnInvestment: 45.8
}
}
// 模拟数据 - 仪表板指标
const mockDashboardMetrics: DashboardMetrics = {
keyMetrics: {
totalUsers: 12560,
activeUsers: 8560,
totalActivities: 2560,
totalOrders: 4560,
totalRevenue: 125600,
adoptionRate: 57.1,
conversionRate: 28.5,
engagementRate: 45.2,
retentionRate: 78.5
},
growthMetrics: {
userGrowth: 15.8,
activityGrowth: 22.5,
orderGrowth: 25.8,
revenueGrowth: 32.1
},
performanceMetrics: {
systemUptime: '99.95%',
averageResponseTime: 120,
errorRate: 0.05,
conversionRate: 28.5
},
recentActivities: [
{ type: 'user', action: '注册', count: 125, time: '今天' },
{ type: 'activity', action: '创建', count: 45, time: '今天' },
{ type: 'order', action: '完成', count: 89, time: '今天' },
{ type: 'adoption', action: '认养', count: 12, time: '今天' }
],
alerts: [
{ level: 'warning', message: '系统负载较高', time: '2小时前' },
{ level: 'info', message: '新版本发布可用', time: '5小时前' }
],
trends: {
userTrend: [1250, 1380, 1560, 1420, 1680, 1920, 2560],
revenueTrend: [1200, 1250, 1380, 1420, 1560, 1480, 1620],
activityTrend: [45, 52, 48, 56, 62, 58, 65],
orderTrend: [89, 92, 85, 96, 102, 98, 112]
},
forecasts: {
userForecast: [2800, 2950, 3100, 3250, 3400],
revenueForecast: [4200, 4500, 4800, 5100, 5400],
activityForecast: [70, 75, 80, 85, 90],
orderForecast: [120, 130, 140, 150, 160]
},
comparisons: {
vsPreviousPeriod: {
userGrowth: { current: 15.8, previous: 12.5, growthRate: 26.4, trend: 'up', timeRange: 'month' },
revenueGrowth: { current: 32.1, previous: 28.3, growthRate: 13.4, trend: 'up', timeRange: 'month' }
},
vsIndustryAverage: {
userGrowth: { current: 15.8, previous: 10.2, growthRate: 54.9, trend: 'up', timeRange: 'month' },
revenueGrowth: { current: 32.1, previous: 25.6, growthRate: 25.4, trend: 'up', timeRange: 'month' }
},
vsCompetitors: {
userGrowth: { current: 15.8, previous: 14.2, growthRate: 11.3, trend: 'up', timeRange: 'month' },
revenueGrowth: { current: 32.1, previous: 30.5, growthRate: 5.2, trend: 'up', timeRange: 'month' }
}
}
}
export const useStatsStore = defineStore('stats', () => {
// 状态
const systemStats = ref<SystemStats>(mockSystemStats)
const userStats = ref<UserStats>(mockUserStats)
const activityStats = ref<ActivityStats>(mockActivityStats)
const animalStats = ref<AnimalStats>(mockAnimalStats)
const orderStats = ref<OrderStats>(mockOrderStats)
const revenueStats = ref<RevenueStats>(mockRevenueStats)
const dashboardMetrics = ref<DashboardMetrics>(mockDashboardMetrics)
const loading = ref(false)
const error = ref<string | null>(null)
// 获取系统统计
const fetchSystemStats = async (timeRange?: TimeRange) => {
loading.value = true
error.value = null
try {
await new Promise(resolve => setTimeout(resolve, 800))
// 模拟根据时间范围筛选数据
let stats = { ...mockSystemStats }
if (timeRange) {
// 这里可以根据时间范围调整统计数据
const growthFactor = timeRange === 'today' ? 1 : timeRange === 'week' ? 7 : 30
stats.newUsersToday = Math.round(stats.newUsersToday * (timeRange === 'today' ? 1 : growthFactor / 30))
stats.todayRevenue = Math.round(stats.todayRevenue * (timeRange === 'today' ? 1 : growthFactor / 30))
}
systemStats.value = stats
return stats
} catch (err) {
error.value = '获取系统统计失败'
throw err
} finally {
loading.value = false
}
}
// 获取用户统计
const fetchUserStats = async (timeRange?: TimeRange) => {
loading.value = true
error.value = null
try {
await new Promise(resolve => setTimeout(resolve, 600))
let stats = { ...mockUserStats }
if (timeRange) {
const growthFactor = timeRange === 'today' ? 1 : timeRange === 'week' ? 7 : 30
stats.newUsers.today = Math.round(stats.newUsers.today * (timeRange === 'today' ? 1 : growthFactor / 30))
stats.newUsers.thisWeek = Math.round(stats.newUsers.thisWeek * (timeRange === 'week' ? 1 : growthFactor / 7))
}
userStats.value = stats
return stats
} catch (err) {
error.value = '获取用户统计失败'
throw err
} finally {
loading.value = false
}
}
// 获取活动统计
const fetchActivityStats = async (timeRange?: TimeRange) => {
loading.value = true
error.value = null
try {
await new Promise(resolve => setTimeout(resolve, 700))
let stats = { ...mockActivityStats }
if (timeRange) {
const growthFactor = timeRange === 'today' ? 1 : timeRange === 'week' ? 7 : 30
stats.totalActivities = Math.round(stats.totalActivities * growthFactor / 30)
}
activityStats.value = stats
return stats
} catch (err) {
error.value = '获取活动统计失败'
throw err
} finally {
loading.value = false
}
}
// 获取动物统计
const fetchAnimalStats = async (timeRange?: TimeRange) => {
loading.value = true
error.value = null
try {
await new Promise(resolve => setTimeout(resolve, 500))
let stats = { ...mockAnimalStats }
if (timeRange) {
const growthFactor = timeRange === 'today' ? 1 : timeRange === 'week' ? 7 : 30
stats.totalAnimals = Math.round(stats.totalAnimals * growthFactor / 30)
}
animalStats.value = stats
return stats
} catch (err) {
error.value = '获取动物统计失败'
throw err
} finally {
loading.value = false
}
}
// 获取订单统计
const fetchOrderStats = async (timeRange?: TimeRange) => {
loading.value = true
error.value = null
try {
await new Promise(resolve => setTimeout(resolve, 600))
let stats = { ...mockOrderStats }
if (timeRange) {
const growthFactor = timeRange === 'today' ? 1 : timeRange === 'week' ? 7 : 30
stats.totalOrders = Math.round(stats.totalOrders * growthFactor / 30)
}
orderStats.value = stats
return stats
} catch (err) {
error.value = '获取订单统计失败'
throw err
} finally {
loading.value = false
}
}
// 获取收入统计
const fetchRevenueStats = async (timeRange?: TimeRange) => {
loading.value = true
error.value = null
try {
await new Promise(resolve => setTimeout(resolve, 800))
let stats = { ...mockRevenueStats }
if (timeRange) {
const growthFactor = timeRange === 'today' ? 1 : timeRange === 'week' ? 7 : 30
stats.dailyRevenue = Math.round(stats.dailyRevenue * (timeRange === 'today' ? 1 : growthFactor / 30))
}
revenueStats.value = stats
return stats
} catch (err) {
error.value = '获取收入统计失败'
throw err
} finally {
loading.value = false
}
}
// 获取仪表板指标
const fetchDashboardMetrics = async () => {
loading.value = true
error.value = null
try {
await new Promise(resolve => setTimeout(resolve, 1000))
// 模拟实时数据更新
const metrics = {
...mockDashboardMetrics,
keyMetrics: {
...mockDashboardMetrics.keyMetrics,
totalUsers: mockSystemStats.totalUsers,
activeUsers: mockSystemStats.activeUsers,
totalRevenue: mockSystemStats.totalRevenue
}
}
dashboardMetrics.value = metrics
return metrics
} catch (err) {
error.value = '获取仪表板指标失败'
throw err
} finally {
loading.value = false
}
}
// 获取统计对比
const fetchStatsComparison = async (type: 'users' | 'activities' | 'orders' | 'revenue', timeRange: TimeRange) => {
loading.value = true
error.value = null
try {
await new Promise(resolve => setTimeout(resolve, 600))
let current: number
let previous: number
let growthRate: number
switch (type) {
case 'users':
current = mockUserStats.newUsers[timeRange === 'today' ? 'today' : timeRange === 'week' ? 'thisWeek' : 'thisMonth']
previous = mockUserStats.newUsers[timeRange === 'today' ? 'yesterday' : timeRange === 'week' ? 'lastWeek' : 'lastMonth']
break
case 'activities':
current = mockActivityStats.totalActivities
previous = Math.round(current * 0.85)
break
case 'orders':
current = mockOrderStats.totalOrders
previous = Math.round(current * 0.8)
break
case 'revenue':
current = mockRevenueStats[timeRange === 'today' ? 'dailyRevenue' : timeRange === 'week' ? 'weeklyRevenue' : 'monthlyRevenue']
previous = Math.round(current * 0.75)
break
default:
current = 0
previous = 0
}
growthRate = previous > 0 ? ((current - previous) / previous) * 100 : 0
const comparison: StatsComparison = {
current,
previous,
growthRate,
trend: growthRate >= 0 ? 'up' : 'down',
timeRange
}
return comparison
} catch (err) {
error.value = '获取统计对比失败'
throw err
} finally {
loading.value = false
}
}
// 导出统计数据
const exportStats = async (type: 'users' | 'activities' | 'animals' | 'orders' | 'revenue', format: 'csv' | 'excel') => {
loading.value = true
error.value = null
try {
await new Promise(resolve => setTimeout(resolve, 1200))
// 模拟导出操作
const data = {
users: mockUserStats,
activities: mockActivityStats,
animals: mockAnimalStats,
orders: mockOrderStats,
revenue: mockRevenueStats
}[type]
return {
filename: `${type}_stats_${new Date().toISOString().split('T')[0]}.${format}`,
data,
format,
exportedAt: new Date().toISOString()
}
} catch (err) {
error.value = '导出统计数据失败'
throw err
} finally {
loading.value = false
}
}
// 重置错误
const clearError = () => {
error.value = null
}
return {
// 状态
systemStats,
userStats,
activityStats,
animalStats,
orderStats,
revenueStats,
dashboardMetrics,
loading,
error,
// 操作
fetchSystemStats,
fetchUserStats,
fetchActivityStats,
fetchAnimalStats,
fetchOrderStats,
fetchRevenueStats,
fetchDashboardMetrics,
fetchStatsComparison,
exportStats,
clearError
}
})

View File

@@ -0,0 +1,162 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
import type { User, UserQueryParams, UserStatus } from '../../types/user'
export const useUserStore = defineStore('user', () => {
// 状态
const users = ref<User[]>([])
const currentUser = ref<User | null>(null)
const loading = ref(false)
const totalCount = ref(0)
const queryParams = ref<UserQueryParams>({
page: 1,
pageSize: 10,
keyword: '',
status: undefined,
startDate: '',
endDate: ''
})
// 获取用户列表
const fetchUsers = async (params?: UserQueryParams) => {
loading.value = true
try {
// 这里应该是API调用暂时用模拟数据
const mockUsers: User[] = [
{
id: 1,
username: 'user1',
nickname: '用户1',
avatar: '',
phone: '13800138000',
email: 'user1@example.com',
status: 'active',
registerTime: '2024-01-01 10:00:00',
lastLoginTime: '2024-01-15 15:30:00',
userType: 'normal'
},
{
id: 2,
username: 'merchant1',
nickname: '商家1',
avatar: '',
phone: '13900139000',
email: 'merchant1@example.com',
status: 'active',
registerTime: '2024-01-02 09:00:00',
lastLoginTime: '2024-01-14 14:20:00',
userType: 'merchant'
}
]
users.value = mockUsers
totalCount.value = mockUsers.length
if (params) {
queryParams.value = { ...queryParams.value, ...params }
}
} catch (error) {
console.error('获取用户列表失败:', error)
throw error
} finally {
loading.value = false
}
}
// 获取用户详情
const fetchUserDetail = async (userId: number) => {
loading.value = true
try {
// 模拟API调用
const mockUser: User = {
id: userId,
username: `user${userId}`,
nickname: `用户${userId}`,
avatar: '',
phone: '13800138000',
email: `user${userId}@example.com`,
status: 'active',
registerTime: '2024-01-01 10:00:00',
lastLoginTime: '2024-01-15 15:30:00',
userType: 'normal'
}
currentUser.value = mockUser
return mockUser
} catch (error) {
console.error('获取用户详情失败:', error)
throw error
} finally {
loading.value = false
}
}
// 更新用户状态
const updateUserStatus = async (userId: number, status: UserStatus) => {
try {
// 模拟API调用
const user = users.value.find((u: User) => u.id === userId)
if (user) {
user.status = status
}
if (currentUser.value && currentUser.value.id === userId) {
currentUser.value.status = status
}
return true
} catch (error) {
console.error('更新用户状态失败:', error)
throw error
}
}
// 搜索用户
const searchUsers = async (keyword: string) => {
queryParams.value.keyword = keyword
return fetchUsers(queryParams.value)
}
// 重置查询参数
const resetQueryParams = () => {
queryParams.value = {
page: 1,
pageSize: 10,
keyword: '',
status: undefined,
startDate: '',
endDate: ''
}
}
// 导出用户数据
const exportUsers = async () => {
try {
// 模拟导出功能
const csvContent = users.value.map(user =>
`${user.id},${user.username},${user.nickname},${user.phone},${user.email},${user.status}`
).join('\n')
return csvContent
} catch (error) {
console.error('导出用户数据失败:', error)
throw error
}
}
return {
users,
currentUser,
loading,
totalCount,
queryParams,
fetchUsers,
fetchUserDetail,
updateUserStatus,
searchUsers,
resetQueryParams,
exportUsers
}
})

View File

@@ -0,0 +1,274 @@
// 活动类型
export type ActivityType = 'travel' | 'movie' | 'dinner' | 'game' | 'sports' | 'study' | 'other'
// 活动状态类型
export type ActivityStatus = 'pending' | 'active' | 'completed' | 'cancelled' | 'full'
// 活动审核状态类型
export type ActivityAuditStatus = 'pending' | 'approved' | 'rejected'
// 活动基本信息接口
export interface Activity {
id: number
title: string
activityType: ActivityType
description: string
organizerId: number
organizerName: string
location: string
startTime: string
endTime: string
maxParticipants: number
currentParticipants: number
status: ActivityStatus
price: number
createTime: string
// 扩展信息
images?: string[]
tags?: string[]
requirements?: string
// 审核信息
auditStatus?: ActivityAuditStatus
auditRemark?: string
auditTime?: string
// 统计信息
viewCount?: number
likeCount?: number
shareCount?: number
// 地理位置
latitude?: number
longitude?: number
// 费用说明
feeIncludes?: string[]
feeExcludes?: string[]
// 取消政策
cancellationPolicy?: string
// 联系方式
contactPhone?: string
contactWechat?: string
}
// 活动查询参数接口
export interface ActivityQueryParams {
page: number
pageSize: number
keyword?: string
status?: ActivityStatus
activityType?: ActivityType
organizerId?: number
minPrice?: number
maxPrice?: number
startDate?: string
endDate?: string
location?: string
sortField?: string
sortOrder?: 'asc' | 'desc'
}
// 活动统计信息接口
export interface ActivityStatistics {
totalActivities: number
activeActivities: number
completedActivities: number
cancelledActivities: number
totalParticipants: number
totalRevenue: number
averageParticipation: number
activityTypeDistribution: Record<ActivityType, number>
statusDistribution: Record<ActivityStatus, number>
monthlyGrowth: number
popularActivities: Activity[]
participantDemographics: {
ageDistribution: Record<string, number>
genderDistribution: Record<string, number>
locationDistribution: Record<string, number>
}
}
// 活动参与记录接口
export interface ActivityParticipation {
id: number
activityId: number
activityTitle: string
userId: number
username: string
joinTime: string
status: 'confirmed' | 'waiting' | 'cancelled'
paymentStatus: 'paid' | 'pending' | 'refunded'
paymentAmount: number
paymentTime?: string
// 评价信息
rating?: number
review?: string
reviewTime?: string
// 取消信息
cancelReason?: string
cancelTime?: string
// 参与信息
participantsCount?: number
groupMembers?: number[]
}
// 活动评价接口
export interface ActivityReview {
id: number
activityId: number
activityTitle: string
userId: number
username: string
organizerId: number
organizerName: string
rating: number
review: string
reviewTime: string
isAnonymous: boolean
// 回复信息
reply?: string
replyTime?: string
// 有用性统计
helpfulCount: number
reportCount: number
status: 'normal' | 'hidden' | 'deleted'
}
// 活动组织者接口
export interface ActivityOrganizer {
id: number
username: string
nickname: string
avatar: string
organizerLevel: number
totalActivities: number
completedActivities: number
cancellationRate: number
averageRating: number
totalParticipants: number
joinTime: string
// 认证信息
isVerified: boolean
verificationLevel: number
// 联系方式
contactPhone?: string
contactEmail?: string
// 组织者描述
description?: string
specialties?: string[]
}
// 活动类型统计接口
export interface ActivityTypeStats {
activityType: ActivityType
count: number
totalParticipants: number
totalRevenue: number
averageRating: number
completionRate: number
}
// 活动时间统计接口
export interface ActivityTimeStats {
date: string
activityCount: number
participantCount: number
revenue: number
peakHours: number[]
}
// 活动地点统计接口
export interface ActivityLocationStats {
location: string
activityCount: number
participantCount: number
averageRating: number
totalRevenue: number
}
// 活动审核记录接口
export interface ActivityAuditRecord {
id: number
activityId: number
activityTitle: string
auditStatus: ActivityAuditStatus
auditRemark?: string
auditor: string
auditTime: string
previousStatus?: ActivityStatus
// 审核详情
auditDetails?: {
contentCheck: boolean
safetyCheck: boolean
complianceCheck: boolean
}
}
// 活动取消记录接口
export interface ActivityCancellationRecord {
id: number
activityId: number
activityTitle: string
cancelReason: string
cancelTime: string
cancelledBy: 'organizer' | 'system' | 'participant'
refundStatus: 'pending' | 'processed' | 'completed'
refundAmount: number
affectedParticipants: number
// 取消详情
weatherConditions?: string
safetyConcerns?: string
otherReasons?: string
}
// 活动推荐参数接口
export interface ActivityRecommendationParams {
userId?: number
location?: string
preferredTypes?: ActivityType[]
budgetRange?: [number, number]
timeRange?: [string, string]
participantCount?: number
excludeAttended?: boolean
}
// 活动导出参数接口
export interface ActivityExportParams {
format: 'csv' | 'excel'
fields: string[]
startDate?: string
endDate?: string
status?: ActivityStatus
activityType?: ActivityType
organizerId?: number
}
// 活动参与统计接口
export interface ActivityParticipationStats {
date: string
participationCount: number
newParticipants: number
repeatParticipants: number
participationRate: number
cancellationRate: number
averageGroupSize: number
}
// 活动收入统计接口
export interface ActivityRevenueStats {
date: string
revenue: number
activityCount: number
averageRevenuePerActivity: number
refundAmount: number
netRevenue: number
}
// 活动运营指标接口
export interface ActivityOperationMetrics {
date: string
newActivities: number
completedActivities: number
participantSatisfaction: number
organizerSatisfaction: number
activityCompletionRate: number
revenuePerParticipant: number
marketingEffectiveness: number
}

View File

@@ -0,0 +1,231 @@
// 动物类型
export type AnimalType = 'sheep' | 'cow' | 'pig' | 'chicken' | 'goat' | 'duck' | 'other'
// 动物状态类型
export type AnimalStatus = 'available' | 'adopted' | 'reserved' | 'inactive'
// 动物性别类型
export type AnimalGender = 'male' | 'female' | 'unknown'
// 健康状态类型
export type HealthStatus = 'excellent' | 'good' | 'fair' | 'poor' | 'critical'
// 动物基本信息接口
export interface Animal {
id: number
name: string
animalType: AnimalType
breed: string
age: number
gender: AnimalGender
status: AnimalStatus
farmId: number
farmName: string
price: number
description: string
images: string[]
healthStatus: HealthStatus
adoptionCount: number
createTime: string
// 扩展信息
features?: string[]
personality?: string
favoriteFood?: string
// 医疗记录
vaccinationRecords?: VaccinationRecord[]
medicalHistory?: MedicalRecord[]
// 认养信息
currentAdopter?: string
adoptionStartTime?: string
adoptionEndTime?: string
// 位置信息
location?: string
gpsCoordinates?: string
}
// 动物查询参数接口
export interface AnimalQueryParams {
page: number
pageSize: number
keyword?: string
status?: AnimalStatus
animalType?: AnimalType
farmId?: number
minAge?: number
maxAge?: number
gender?: AnimalGender
minPrice?: number
maxPrice?: number
startDate?: string
endDate?: string
sortField?: string
sortOrder?: 'asc' | 'desc'
}
// 疫苗接种记录接口
export interface VaccinationRecord {
id: number
animalId: number
vaccineName: string
vaccinationDate: string
nextVaccinationDate: string
veterinarian: string
notes?: string
}
// 医疗记录接口
export interface MedicalRecord {
id: number
animalId: number
diagnosis: string
treatment: string
treatmentDate: string
veterinarian: string
cost: number
notes?: string
followUpDate?: string
}
// 动物统计信息接口
export interface AnimalStatistics {
totalAnimals: number
availableAnimals: number
adoptedAnimals: number
totalAdoptions: number
averageAdoptionPrice: number
animalTypeDistribution: Record<AnimalType, number>
statusDistribution: Record<AnimalStatus, number>
healthStatusDistribution: Record<HealthStatus, number>
monthlyAdoptions: number
adoptionGrowthRate: number
topAdoptedAnimals: Animal[]
}
// 动物类型统计接口
export interface AnimalTypeStats {
animalType: AnimalType
count: number
adoptionCount: number
averagePrice: number
adoptionRate: number
}
// 农场动物统计接口
export interface FarmAnimalStats {
farmId: number
farmName: string
totalAnimals: number
availableAnimals: number
adoptedAnimals: number
totalAdoptions: number
averageAdoptionPrice: number
}
// 动物健康统计接口
export interface AnimalHealthStats {
date: string
excellentCount: number
goodCount: number
fairCount: number
poorCount: number
criticalCount: number
vaccinationRate: number
}
// 动物认养记录接口
export interface AnimalAdoptionRecord {
id: number
animalId: number
animalName: string
userId: number
username: string
startTime: string
endTime: string
duration: number
totalCost: number
status: 'active' | 'completed' | 'cancelled'
paymentStatus: 'paid' | 'pending' | 'refunded'
adoptionType: 'individual' | 'group'
groupMembers?: number[]
}
// 动物成长记录接口
export interface AnimalGrowthRecord {
id: number
animalId: number
recordDate: string
weight: number
height: number
condition: string
notes?: string
photos?: string[]
}
// 动物行为记录接口
export interface AnimalBehaviorRecord {
id: number
animalId: number
recordDate: string
behaviorType: string
duration: number
notes?: string
videoUrl?: string
}
// 动物喂养记录接口
export interface AnimalFeedingRecord {
id: number
animalId: number
feedingTime: string
foodType: string
quantity: number
feeder: string
notes?: string
}
// 动物活动记录接口
export interface AnimalActivityRecord {
id: number
animalId: number
activityType: string
startTime: string
endTime: string
duration: number
caloriesBurned?: number
notes?: string
}
// 动物导出参数接口
export interface AnimalExportParams {
format: 'csv' | 'excel'
fields: string[]
startDate?: string
endDate?: string
status?: AnimalStatus
animalType?: AnimalType
farmId?: number
}
// 动物认养统计接口
export interface AnimalAdoptionStats {
date: string
adoptionCount: number
totalRevenue: number
averageAdoptionDuration: number
popularAnimalTypes: string[]
peakAdoptionHours: number[]
}
// 动物健康预警接口
export interface AnimalHealthAlert {
id: number
animalId: number
animalName: string
alertType: 'vaccination' | 'medical' | 'nutrition' | 'behavior'
alertLevel: 'low' | 'medium' | 'high' | 'critical'
alertMessage: string
triggerTime: string
resolved: boolean
resolveTime?: string
resolveNotes?: string
}

View File

@@ -0,0 +1,313 @@
// 内容类型
export type ContentType = 'article' | 'post' | 'activity' | 'comment' | 'review'
// 内容状态类型
export type ContentStatus = 'published' | 'draft' | 'deleted' | 'archived'
// 内容审核状态类型
export type ContentAuditStatus = 'pending' | 'approved' | 'rejected'
// 内容分类类型
export type ContentCategory = 'travel' | 'animal' | 'entertainment' | 'food' | 'sports' | 'study' | 'other'
// 内容基本信息接口
export interface Content {
id: number
title: string
content: string
contentType: ContentType
authorId: number
authorName: string
publishTime: string
status: ContentStatus
viewCount: number
likeCount: number
commentCount: number
shareCount: number
auditStatus: ContentAuditStatus
auditRemark?: string
auditTime?: string
// 分类信息
category: ContentCategory
tags?: string[]
// 多媒体内容
images?: string[]
videos?: string[]
// 地理位置
location?: string
latitude?: number
longitude?: number
// 关联信息
relatedActivityId?: number
relatedAnimalId?: number
// 隐私设置
isPublic: boolean
allowComments: boolean
allowSharing: boolean
// 编辑信息
lastEditTime?: string
editCount: number
// SEO信息
metaDescription?: string
metaKeywords?: string[]
}
// 内容查询参数接口
export interface ContentQueryParams {
page: number
pageSize: number
keyword?: string
status?: ContentStatus
contentType?: ContentType
auditStatus?: ContentAuditStatus
authorId?: number
category?: ContentCategory
startTime?: string
endTime?: string
sortField?: string
sortOrder?: 'asc' | 'desc'
// 高级筛选
minViews?: number
minLikes?: number
minComments?: number
hasImages?: boolean
hasVideos?: boolean
// 地理位置筛选
location?: string
radius?: number
}
// 内容统计信息接口
export interface ContentStatistics {
totalContents: number
publishedContents: number
draftContents: number
deletedContents: number
totalViews: number
totalLikes: number
totalComments: number
totalShares: number
averageEngagementRate: number
contentTypeDistribution: Record<ContentType, number>
categoryDistribution: Record<ContentCategory, number>
dailyGrowth: number
topContents: Content[]
authorDistribution: {
totalAuthors: number
activeAuthors: number
newAuthorsThisMonth: number
topAuthors: Array<{
authorId: number
authorName: string
contentCount: number
totalViews: number
}>
}
}
// 内容审核记录接口
export interface ContentAuditRecord {
id: number
contentId: number
contentTitle: string
auditStatus: ContentAuditStatus
auditRemark?: string
auditor: string
auditTime: string
previousStatus?: ContentStatus
// 审核详情
auditDetails?: {
contentQuality: number
complianceScore: number
safetyCheck: boolean
spamCheck: boolean
}
// 违规信息
violationType?: string
violationLevel?: 'minor' | 'major' | 'critical'
penaltyApplied?: string
}
// 内容举报接口
export interface ContentReport {
id: number
contentId: number
contentTitle: string
reporterId: number
reporterName: string
reportReason: string
reportTime: string
reportStatus: 'pending' | 'processing' | 'resolved' | 'dismissed'
// 举报详情
reportDetails?: {
violationType: string
evidence?: string[]
additionalComments?: string
}
// 处理信息
handledBy?: string
handleTime?: string
handleResult?: string
penaltyApplied?: string
// 反馈信息
reporterNotified: boolean
feedbackProvided?: string
}
// 内容分类统计接口
export interface ContentCategoryStats {
category: ContentCategory
totalContents: number
publishedContents: number
averageViews: number
averageLikes: number
averageComments: number
engagementRate: number
topAuthors: Array<{
authorId: number
authorName: string
contentCount: number
}>
popularTags: string[]
growthTrend: number
}
// 内容作者统计接口
export interface ContentAuthorStats {
authorId: number
authorName: string
totalContents: number
publishedContents: number
totalViews: number
totalLikes: number
totalComments: number
averageEngagement: number
followerCount: number
joinDate: string
lastActivity: string
// 内容质量指标
contentQualityScore: number
complianceRate: number
// 认证信息
isVerified: boolean
verificationLevel: number
// 作者分类分布
categoryDistribution: Record<ContentCategory, number>
}
// 内容时间统计接口
export interface ContentTimeStats {
date: string
contentCount: number
viewCount: number
likeCount: number
commentCount: number
shareCount: number
newAuthors: number
peakHours: number[]
engagementRate: number
}
// 内容标签统计接口
export interface ContentTagStats {
tag: string
usageCount: number
averageViews: number
averageLikes: number
averageComments: number
relatedTags: string[]
popularityTrend: number
// 分类关联
associatedCategories: ContentCategory[]
// 作者使用情况
topAuthors: Array<{
authorId: number
authorName: string
usageCount: number
}>
}
// 内容推荐参数接口
export interface ContentRecommendationParams {
userId?: number
preferredCategories?: ContentCategory[]
preferredTags?: string[]
location?: string
timeRange?: [string, string]
contentType?: ContentType
minQualityScore?: number
excludeViewed?: boolean
limit?: number
}
// 内容导出参数接口
export interface ContentExportParams {
format: 'csv' | 'excel' | 'json'
fields: string[]
startDate?: string
endDate?: string
status?: ContentStatus
contentType?: ContentType
category?: ContentCategory
authorId?: number
}
// 内容审核参数接口
export interface ContentAuditParams {
contentId: number
auditStatus: ContentAuditStatus
auditRemark?: string
violationType?: string
violationLevel?: 'minor' | 'major' | 'critical'
penalty?: string
notifyAuthor: boolean
}
// 内容批量操作参数接口
export interface ContentBatchOperationParams {
contentIds: number[]
operation: 'publish' | 'draft' | 'delete' | 'approve' | 'reject'
auditRemark?: string
notifyAuthors: boolean
}
// 内容搜索参数接口
export interface ContentSearchParams {
query: string
filters?: {
contentType?: ContentType
category?: ContentCategory
status?: ContentStatus
authorId?: number
dateRange?: [string, string]
minViews?: number
minLikes?: number
}
sortBy?: 'relevance' | 'date' | 'views' | 'likes' | 'comments'
sortOrder?: 'asc' | 'desc'
page?: number
pageSize?: number
}
// 内容分析报告接口
export interface ContentAnalysisReport {
period: string
totalContents: number
totalViews: number
totalEngagement: number
averageQualityScore: number
topPerformingContents: Content[]
topAuthors: ContentAuthorStats[]
categoryPerformance: ContentCategoryStats[]
tagAnalysis: ContentTagStats[]
timeAnalysis: ContentTimeStats[]
recommendations: string[]
// 合规性指标
complianceRate: number
auditPassRate: number
reportResolutionRate: number
// 增长指标
growthRate: number
retentionRate: number
churnRate: number
}

View File

@@ -0,0 +1,163 @@
// 商家状态类型
export type MerchantStatus = 'active' | 'inactive' | 'banned'
// 商家审核状态类型
export type MerchantAuditStatus = 'pending' | 'approved' | 'rejected'
// 商家分类类型
export type MerchantCategory = 'flower' | 'farm' | 'activity' | 'travel' | 'other'
// 商家基本信息接口
export interface Merchant {
id: number
userId: number
shopName: string
businessLicense: string
contactPerson: string
contactPhone: string
contactEmail: string
address: string
description: string
status: MerchantStatus
auditStatus: MerchantAuditStatus
auditTime?: string
auditRemark?: string
registerTime: string
category: MerchantCategory
// 统计信息
serviceScore: number
orderCount: number
totalRevenue: number
// 扩展信息
businessHours?: string
deliveryRange?: string
minimumOrder?: number
// 资质文件
licenseImage?: string
idCardImage?: string
// 银行信息
bankAccount?: string
bankName?: string
accountHolder?: string
}
// 商家查询参数接口
export interface MerchantQueryParams {
page: number
pageSize: number
keyword?: string
status?: MerchantStatus
auditStatus?: MerchantAuditStatus
category?: MerchantCategory
startDate?: string
endDate?: string
sortField?: string
sortOrder?: 'asc' | 'desc'
}
// 商家审核参数接口
export interface MerchantAuditParams {
merchantId: number
auditStatus: MerchantAuditStatus
auditRemark?: string
}
// 商家统计信息接口
export interface MerchantStatistics {
totalMerchants: number
activeMerchants: number
pendingAudit: number
rejected: number
totalRevenue: number
averageScore: number
categoryDistribution: Record<MerchantCategory, number>
monthlyGrowth: number
dailyActiveMerchants: number
topMerchants: Merchant[]
}
// 商家收入统计接口
export interface MerchantRevenueStats {
date: string
revenue: number
orderCount: number
averageOrderValue: number
}
// 商家服务评分统计接口
export interface MerchantScoreStats {
date: string
averageScore: number
reviewCount: number
fiveStarCount: number
oneStarCount: number
}
// 商家分类统计接口
export interface MerchantCategoryStats {
category: MerchantCategory
count: number
totalRevenue: number
averageScore: number
}
// 商家审核记录接口
export interface MerchantAuditRecord {
id: number
merchantId: number
shopName: string
auditStatus: MerchantAuditStatus
auditRemark?: string
auditor: string
auditTime: string
previousStatus?: MerchantAuditStatus
}
// 商家操作日志接口
export interface MerchantOperationLog {
id: number
merchantId: number
shopName: string
operationType: string
operationDetail: string
operationTime: string
operator: string
result: 'success' | 'failure'
}
// 商家资质文件接口
export interface MerchantQualification {
id: number
merchantId: number
fileType: 'license' | 'idCard' | 'bank' | 'other'
fileName: string
fileUrl: string
uploadTime: string
status: 'verified' | 'pending' | 'rejected'
verifyRemark?: string
verifyTime?: string
}
// 商家银行信息接口
export interface MerchantBankInfo {
id: number
merchantId: number
bankName: string
bankAccount: string
accountHolder: string
branchName?: string
status: 'verified' | 'pending' | 'rejected'
verifyRemark?: string
verifyTime?: string
}
// 商家导出参数接口
export interface MerchantExportParams {
format: 'csv' | 'excel'
fields: string[]
startDate?: string
endDate?: string
status?: MerchantStatus
auditStatus?: MerchantAuditStatus
category?: MerchantCategory
}

View File

@@ -0,0 +1,209 @@
// 订单状态类型
export type OrderStatus = 'pending' | 'paid' | 'shipped' | 'completed' | 'cancelled' | 'refunded'
// 订单类型
export type OrderType = 'flower' | 'animal' | 'activity' | 'travel' | 'other'
// 支付方式类型
export type PaymentMethod = 'wechat' | 'alipay' | 'bank' | 'balance'
// 支付状态类型
export type PaymentStatus = 'pending' | 'paid' | 'failed' | 'refunded'
// 订单基本信息接口
export interface Order {
id: number
orderNo: string
userId: number
username: string
merchantId: number
shopName: string
orderType: OrderType
productName: string
quantity: number
unitPrice: number
totalAmount: number
status: OrderStatus
createTime: string
payTime?: string
completeTime?: string
cancelTime?: string
// 支付信息
paymentMethod?: PaymentMethod
paymentStatus?: PaymentStatus
transactionNo?: string
// 收货信息
recipientName: string
recipientPhone: string
deliveryAddress: string
deliveryTime?: string
// 附加信息
message?: string
remark?: string
// 评价信息
rating?: number
review?: string
reviewTime?: string
// 退款信息
refundAmount?: number
refundReason?: string
refundTime?: string
// 物流信息
trackingNo?: string
shippingCompany?: string
}
// 订单查询参数接口
export interface OrderQueryParams {
page: number
pageSize: number
keyword?: string
status?: OrderStatus
orderType?: OrderType
merchantId?: number
userId?: number
startDate?: string
endDate?: string
sortField?: string
sortOrder?: 'asc' | 'desc'
}
// 订单统计信息接口
export interface OrderStatistics {
totalOrders: number
pendingOrders: number
completedOrders: number
cancelledOrders: number
totalRevenue: number
averageOrderValue: number
dailyOrderCount: number
orderTypeDistribution: Record<OrderType, number>
statusDistribution: Record<OrderStatus, number>
monthlyGrowth: number
topProducts: string[]
revenueTrend: Array<{
date: string
revenue: number
orderCount: number
}>
}
// 订单收入统计接口
export interface OrderRevenueStats {
date: string
revenue: number
orderCount: number
averageOrderValue: number
refundAmount: number
netRevenue: number
}
// 订单类型统计接口
export interface OrderTypeStats {
orderType: OrderType
count: number
totalRevenue: number
averageOrderValue: number
completionRate: number
}
// 订单状态统计接口
export interface OrderStatusStats {
status: OrderStatus
count: number
percentage: number
}
// 订单支付统计接口
export interface OrderPaymentStats {
paymentMethod: PaymentMethod
count: number
totalAmount: number
successRate: number
}
// 订单退款统计接口
export interface OrderRefundStats {
date: string
refundCount: number
refundAmount: number
refundRate: number
mainReasons: string[]
}
// 订单操作记录接口
export interface OrderOperationLog {
id: number
orderId: number
orderNo: string
operationType: string
operationDetail: string
operationTime: string
operator: string
result: 'success' | 'failure'
remark?: string
}
// 订单导出参数接口
export interface OrderExportParams {
format: 'csv' | 'excel'
fields: string[]
startDate?: string
endDate?: string
status?: OrderStatus
orderType?: OrderType
merchantId?: number
}
// 订单退款申请接口
export interface OrderRefundApplication {
id: number
orderId: number
orderNo: string
userId: number
username: string
refundAmount: number
refundReason: string
status: 'pending' | 'approved' | 'rejected' | 'completed'
applyTime: string
processTime?: string
processRemark?: string
processor?: string
}
// 订单评价接口
export interface OrderReview {
id: number
orderId: number
userId: number
username: string
merchantId: number
shopName: string
rating: number
review: string
reviewTime: string
isAnonymous: boolean
reply?: string
replyTime?: string
helpfulCount: number
reportCount: number
status: 'normal' | 'hidden' | 'deleted'
}
// 订单物流信息接口
export interface OrderShippingInfo {
id: number
orderId: number
orderNo: string
trackingNo: string
shippingCompany: string
shippingTime: string
estimatedDelivery: string
actualDelivery?: string
shippingStatus: 'pending' | 'shipped' | 'in_transit' | 'delivered' | 'failed'
shippingCost: number
recipientName: string
recipientPhone: string
deliveryAddress: string
deliveryNotes?: string
}

View File

@@ -0,0 +1,402 @@
// 权限状态类型
export type PermissionStatus = 'active' | 'inactive' | 'deprecated'
// 权限类型
export type PermissionType = 'module' | 'menu' | 'button' | 'action' | 'api'
// 角色类型
export type RoleType = 'system' | 'custom' | 'guest'
// 角色状态类型
export type RoleStatus = 'active' | 'inactive' | 'pending'
// 权限基本信息接口
export interface Permission {
id: number
name: string
code: string
description: string
type: PermissionType
parentId: number | null
level: number
status: PermissionStatus
createTime: string
updateTime: string
// 扩展信息
icon?: string
route?: string
component?: string
sortOrder?: number
// 子权限
children?: Permission[]
// 权限控制
isPublic?: boolean
requiresAuth?: boolean
// 元数据
metadata?: Record<string, any>
}
// 角色基本信息接口
export interface Role {
id: number
name: string
code: string
description: string
type: RoleType
status: RoleStatus
permissionIds: number[]
userCount: number
createTime: string
updateTime: string
// 扩展信息
permissions?: Permission[]
// 角色属性
isDefault?: boolean
isSystem?: boolean
// 访问控制
maxUsers?: number
expirationDate?: string
// 审批流程
requiresApproval?: boolean
approvalWorkflow?: string
// 元数据
metadata?: Record<string, any>
}
// 用户角色关联接口
export interface UserRole {
id: number
userId: number
roleId: number
assignTime: string
assignBy: string
// 扩展信息
expirationTime?: string
// 审批信息
approvedBy?: string
approveTime?: string
approvalStatus?: 'pending' | 'approved' | 'rejected'
// 权限委托
delegatedFrom?: number
delegationReason?: string
// 元数据
metadata?: Record<string, any>
}
// 权限查询参数接口
export interface PermissionQueryParams {
page: number
pageSize: number
keyword?: string
status?: PermissionStatus
type?: PermissionType
parentId?: number | null
level?: number
// 高级筛选
isPublic?: boolean
requiresAuth?: boolean
// 排序
sortField?: string
sortOrder?: 'asc' | 'desc'
}
// 角色查询参数接口
export interface RoleQueryParams {
page: number
pageSize: number
keyword?: string
status?: RoleStatus
type?: RoleType
// 高级筛选
isDefault?: boolean
isSystem?: boolean
// 用户数量范围
minUsers?: number
maxUsers?: number
// 排序
sortField?: string
sortOrder?: 'asc' | 'desc'
}
// 权限统计信息接口
export interface PermissionStatistics {
totalPermissions: number
activePermissions: number
inactivePermissions: number
totalRoles: number
activeRoles: number
inactiveRoles: number
totalUsersWithRoles: number
permissionUsage: Record<string, number>
roleDistribution: Record<string, number>
userPermissionStats: {
averagePermissionsPerUser: number
maxPermissionsPerUser: number
minPermissionsPerUser: number
usersWithExcessivePermissions: number
// 权限分布
permissionDistribution?: Record<string, number>
// 风险指标
permissionConflictRate?: number
permissionRedundancyRate?: number
}
auditLogs: {
totalLogs: number
permissionChanges: number
roleChanges: number
userRoleChanges: number
// 安全事件
securityIncidents?: number
complianceViolations?: number
}
// 性能指标
permissionCheckPerformance?: number
roleResolutionTime?: number
// 合规性指标
complianceScore?: number
auditPassRate?: number
}
// 审计日志接口
export interface AuditLog {
id: number
action: string
targetType: string
targetId: number
targetName: string
performerId: number
performerName: string
details: string
ipAddress: string
userAgent: string
timestamp: string
status: 'success' | 'failure' | 'warning'
// 扩展信息
resourceType?: string
resourceId?: number
// 变更详情
oldValue?: any
newValue?: any
// 安全信息
securityLevel?: 'low' | 'medium' | 'high' | 'critical'
riskScore?: number
// 地理位置
location?: string
deviceInfo?: string
// 调查信息
investigationStatus?: 'open' | 'in_progress' | 'resolved' | 'closed'
investigationNotes?: string
}
// 权限分配请求接口
export interface PermissionAssignmentRequest {
userId: number
permissionIds: number[]
assignBy: string
// 有效期
expirationTime?: string
// 审批信息
requiresApproval?: boolean
approvalWorkflow?: string
// 委托信息
delegatedFrom?: number
delegationReason?: string
}
// 角色分配请求接口
export interface RoleAssignmentRequest {
userId: number
roleId: number
assignBy: string
// 有效期
expirationTime?: string
// 审批信息
requiresApproval?: boolean
approvalWorkflow?: string
// 委托信息
delegatedFrom?: number
delegationReason?: string
}
// 权限检查请求接口
export interface PermissionCheckRequest {
userId: number
permissionCode: string
// 上下文信息
resourceType?: string
resourceId?: number
// 环境信息
ipAddress?: string
userAgent?: string
// 安全验证
sessionId?: string
token?: string
}
// 权限检查响应接口
export interface PermissionCheckResponse {
hasPermission: boolean
// 详细权限信息
permission?: Permission
// 权限来源
grantedBy: 'role' | 'direct' | 'inheritance' | 'delegation'
role?: Role
// 有效期
validUntil?: string
// 限制信息
restrictions?: string[]
// 审计信息
auditId?: number
}
// 权限继承配置接口
export interface PermissionInheritanceConfig {
enabled: boolean
inheritanceRules: Array<{
sourceType: string
sourceId: number
targetType: string
targetId: number
inheritanceType: 'full' | 'partial' | 'conditional'
conditions?: Record<string, any>
// 有效期
validFrom?: string
validUntil?: string
// 优先级
priority: number
}>
// 冲突解决策略
conflictResolution: 'deny' | 'allow' | 'highest_priority' | 'most_specific'
// 性能优化
cachingEnabled: boolean
cacheTTL: number
// 审计配置
auditInheritance: boolean
}
// 权限委托配置接口
export interface PermissionDelegationConfig {
enabled: boolean
maxDelegationDepth: number
delegationTimeLimit: number
allowedDelegators: number[]
restrictedPermissions: number[]
// 审批流程
requiresApproval: boolean
approvalWorkflow: string
// 审计要求
auditDelegation: boolean
// 通知设置
notifyOriginalOwner: boolean
notifyDelegator: boolean
notifyDelegatee: boolean
}
// 权限审计配置接口
export interface PermissionAuditConfig {
enabled: boolean
auditLevel: 'minimal' | 'standard' | 'detailed' | 'comprehensive'
retentionPeriod: number
// 审计事件
auditedActions: string[]
// 敏感操作
sensitiveOperations: Array<{
action: string
sensitivityLevel: 'low' | 'medium' | 'high' | 'critical'
additionalAuditing: boolean
}>
// 实时监控
realTimeMonitoring: boolean
alertThresholds: Record<string, number>
// 合规要求
complianceRequirements: string[]
regulatoryStandards: string[]
}
// 权限导出参数接口
export interface PermissionExportParams {
format: 'csv' | 'excel' | 'json'
include: Array<'permissions' | 'roles' | 'user_roles' | 'audit_logs'>
filters?: {
status?: PermissionStatus | RoleStatus
type?: PermissionType | RoleType
dateRange?: [string, string]
}
// 数据范围
dataScope: 'all' | 'active' | 'recent'
// 安全选项
encryptData: boolean
passwordProtect: boolean
// 元数据
includeMetadata: boolean
}
// 权限导入参数接口
export interface PermissionImportParams {
file: File
format: 'csv' | 'excel' | 'json'
importType: 'permissions' | 'roles' | 'assignments'
// 冲突处理
conflictResolution: 'skip' | 'overwrite' | 'merge' | 'rename'
// 验证选项
validateData: boolean
dryRun: boolean
// 通知设置
notifyOnCompletion: boolean
notifyOnError: boolean
// 审计配置
auditImport: boolean
}
// 权限同步配置接口
export interface PermissionSyncConfig {
enabled: boolean
syncFrequency: number
syncDirection: 'bidirectional' | 'source_to_target' | 'target_to_source'
// 数据源配置
sourceSystem: string
sourceConfig: Record<string, any>
targetSystem: string
targetConfig: Record<string, any>
// 映射规则
fieldMappings: Record<string, string>
valueTransformations: Record<string, (value: any) => any>
// 冲突解决
conflictResolution: 'source_wins' | 'target_wins' | 'manual'
// 性能优化
batchSize: number
parallelProcessing: boolean
// 监控配置
monitorSync: boolean
alertOnFailure: boolean
}
// 权限健康检查接口
export interface PermissionHealthCheck {
timestamp: string
status: 'healthy' | 'degraded' | 'unhealthy'
// 组件状态
components: Array<{
name: string
status: 'up' | 'down' | 'degraded'
responseTime: number
errorRate: number
}>
// 性能指标
performanceMetrics: {
permissionCheckTime: number
roleResolutionTime: number
cacheHitRate: number
memoryUsage: number
}
// 安全指标
securityMetrics: {
failedAttempts: number
suspiciousActivities: number
complianceViolations: number
}
// 建议措施
recommendations: string[]
// 历史趋势
historicalTrend: Record<string, number>
}

View File

@@ -0,0 +1,488 @@
// 时间范围类型
export type TimeRange = 'today' | 'yesterday' | 'week' | 'month' | 'quarter' | 'year'
// 统计对比接口
export interface StatsComparison {
current: number
previous: number
growthRate: number
trend: 'up' | 'down' | 'stable'
timeRange: TimeRange
// 详细信息
unit?: string
significance?: 'high' | 'medium' | 'low'
confidence?: number
}
// 系统统计接口
export interface SystemStats {
totalUsers: number
activeUsers: number
newUsersToday: number
newUsersThisWeek: number
newUsersThisMonth: number
totalActivities: number
activeActivities: number
completedActivities: number
totalAnimals: number
adoptedAnimals: number
availableAnimals: number
totalOrders: number
pendingOrders: number
completedOrders: number
cancelledOrders: number
totalRevenue: number
todayRevenue: number
weekRevenue: number
monthRevenue: number
systemUptime: string
averageResponseTime: number
errorRate: number
serverLoad: number
// 扩展信息
databaseSize?: number
cacheHitRate?: number
apiCalls?: number
concurrentUsers?: number
// 性能指标
pageLoadTime?: number
apiResponseTime?: number
databaseQueryTime?: number
// 资源使用
memoryUsage?: number
cpuUsage?: number
diskUsage?: number
networkUsage?: number
}
// 用户统计接口
export interface UserStats {
totalUsers: number
activeUsers: number
newUsers: {
today: number
yesterday: number
thisWeek: number
lastWeek: number
thisMonth: number
lastMonth: number
}
userGrowthRate: number
userRetentionRate: number
userChurnRate: number
userDemographics: {
ageDistribution: Record<string, number>
genderDistribution: Record<string, number>
locationDistribution: Record<string, number>
// 扩展信息
educationDistribution?: Record<string, number>
occupationDistribution?: Record<string, number>
incomeDistribution?: Record<string, number>
}
userActivity: {
dailyActiveUsers: number
weeklyActiveUsers: number
monthlyActiveUsers: number
averageSessionDuration: number
averageSessionsPerUser: number
// 行为指标
pagesPerSession?: number
bounceRate?: number
returnRate?: number
}
userBehavior: {
averageActivitiesPerUser: number
averageAnimalsAdopted: number
averageOrdersPerUser: number
conversionRate: number
engagementRate: number
// 参与度指标
contentCreationRate?: number
socialInteractionRate?: number
referralRate?: number
}
// 用户生命周期
userLifetimeValue: number
userAcquisitionCost: number
userRetentionCost: number
// 用户满意度
userSatisfactionScore?: number
netPromoterScore?: number
customerEffortScore?: number
}
// 活动统计接口
export interface ActivityStats {
totalActivities: number
activeActivities: number
completedActivities: number
cancelledActivities: number
pendingActivities: number
activityGrowthRate: number
participationStats: {
totalParticipants: number
averageParticipantsPerActivity: number
repeatParticipants: number
participationRate: number
// 参与度详情
maleParticipants?: number
femaleParticipants?: number
ageDistribution?: Record<string, number>
locationDistribution?: Record<string, number>
}
revenueStats: {
totalRevenue: number
averageRevenuePerActivity: number
revenueGrowthRate: number
refundRate: number
// 收入详情
ticketRevenue?: number
serviceRevenue?: number
productRevenue?: number
commissionRevenue?: number
}
categoryDistribution: Record<string, number>
locationDistribution: Record<string, number>
timeDistribution: Record<string, number>
organizerPerformance: {
topOrganizers: Array<{
organizerId: number
name: string
activityCount: number
revenue: number
rating?: number
completionRate?: number
}>
averageRating: number
completionRate: number
cancellationRate: number
// 组织者指标
organizerSatisfaction?: number
organizerRetention?: number
organizerGrowth?: number
}
// 活动质量指标
activityQualityScore?: number
participantSatisfaction?: number
safetyIncidents?: number
// 营销效果
marketingROI?: number
acquisitionCost?: number
conversionRate?: number
}
// 动物统计接口
export interface AnimalStats {
totalAnimals: number
adoptedAnimals: number
availableAnimals: number
adoptionRate: number
adoptionGrowthRate: number
animalTypes: Record<string, number>
adoptionStats: {
totalAdoptions: number
averageAdoptionTime: number
repeatAdoptions: number
adoptionSuccessRate: number
// 收养详情
adoptionReasons?: Record<string, number>
adoptionDuration?: Record<string, number>
adoptionFrequency?: number
}
careStats: {
totalCareRecords: number
averageCareFrequency: number
medicalCheckups: number
vaccinationRate: number
// 护理详情
healthIssues?: number
treatmentCost?: number
careQuality?: number
}
locationDistribution: Record<string, number>
popularAnimals: Array<{
animalId: number
name: string
type: string
adoptionCount: number
viewCount: number
likeCount?: number
shareCount?: number
}>
revenueStats: {
totalAdoptionRevenue: number
averageAdoptionFee: number
careProductRevenue: number
totalRevenue: number
// 收入详情
donationRevenue?: number
sponsorshipRevenue?: number
merchandiseRevenue?: number
}
// 动物福利指标
animalWelfareScore?: number
healthIndex?: number
happinessIndex?: number
// 可持续发展
environmentalImpact?: number
communityEngagement?: number
educationalValue?: number
}
// 订单统计接口
export interface OrderStats {
totalOrders: number
pendingOrders: number
completedOrders: number
cancelledOrders: number
orderGrowthRate: number
revenueStats: {
totalRevenue: number
averageOrderValue: number
revenueGrowthRate: number
refundAmount: number
netRevenue: number
// 收入构成
productRevenue?: number
serviceRevenue?: number
taxAmount?: number
shippingCost?: number
}
orderTypeDistribution: Record<string, number>
paymentStats: {
paymentMethods: Record<string, number>
paymentSuccessRate: number
averagePaymentTime: number
refundRate: number
// 支付详情
fraudRate?: number
chargebackRate?: number
paymentCost?: number
}
customerStats: {
repeatCustomers: number
averageOrdersPerCustomer: number
customerLifetimeValue: number
acquisitionCost: number
// 客户行为
purchaseFrequency?: number
basketSize?: number
crossSellRate?: number
}
timeDistribution: Record<string, number>
locationDistribution: Record<string, number>
// 订单质量指标
orderAccuracy?: number
deliveryPerformance?: number
customerSatisfaction?: number
// 运营效率
fulfillmentTime?: number
inventoryTurnover?: number
returnRate?: number
}
// 收入统计接口
export interface RevenueStats {
totalRevenue: number
revenueGrowthRate: number
dailyRevenue: number
weeklyRevenue: number
monthlyRevenue: number
revenueSources: Record<string, number>
revenueTrends: {
last7Days: number[]
last30Days: number[]
// 扩展趋势
last90Days?: number[]
last365Days?: number[]
seasonalPatterns?: Record<string, number>
}
customerMetrics: {
averageRevenuePerUser: number
averageOrderValue: number
purchaseFrequency: number
customerLifetimeValue: number
// 客户价值
retentionValue?: number
acquisitionValue?: number
referralValue?: number
}
geographicDistribution: Record<string, number>
productPerformance: {
topProducts: Array<{
productId: number
name: string
revenue: number
orders: number
profit?: number
margin?: number
}>
averageProfitMargin: number
returnOnInvestment: number
// 产品指标
productPopularity?: number
productSatisfaction?: number
productRetention?: number
}
// 财务指标
grossProfit?: number
operatingProfit?: number
netProfit?: number
cashFlow?: number
// 预算与实际
budgetVariance?: number
forecastAccuracy?: number
// 税务信息
taxLiability?: number
taxCompliance?: number
}
// 仪表板指标接口
export interface DashboardMetrics {
keyMetrics: {
totalUsers: number
activeUsers: number
totalActivities: number
totalOrders: number
totalRevenue: number
adoptionRate: number
// 核心指标
conversionRate?: number
engagementRate?: number
retentionRate?: number
}
growthMetrics: {
userGrowth: number
activityGrowth: number
orderGrowth: number
revenueGrowth: number
// 增长详情
organicGrowth?: number
paidGrowth?: number
referralGrowth?: number
}
performanceMetrics: {
systemUptime: string
averageResponseTime: number
errorRate: number
conversionRate: number
// 性能详情
pageSpeed?: number
apiAvailability?: number
databasePerformance?: number
}
recentActivities: Array<{
type: string
action: string
count: number
time: string
// 活动详情
details?: string
priority?: 'high' | 'medium' | 'low'
}>
alerts: Array<{
level: 'critical' | 'warning' | 'info' | 'success'
message: string
time: string
// 警报详情
source?: string
affectedComponents?: string[]
resolution?: string
}>
// 趋势数据
trends: {
userTrend: number[]
revenueTrend: number[]
activityTrend: number[]
orderTrend: number[]
}
// 预测数据
forecasts: {
userForecast: number[]
revenueForecast: number[]
activityForecast: number[]
orderForecast: number[]
}
// 比较数据
comparisons: {
vsPreviousPeriod: Record<string, StatsComparison>
vsIndustryAverage: Record<string, StatsComparison>
vsCompetitors: Record<string, StatsComparison>
}
}
// 统计导出参数接口
export interface StatsExportParams {
type: 'users' | 'activities' | 'animals' | 'orders' | 'revenue' | 'system'
format: 'csv' | 'excel' | 'json' | 'pdf'
timeRange: TimeRange
fields: string[]
filters?: Record<string, any>
sortBy?: string
sortOrder?: 'asc' | 'desc'
}
// 统计查询参数接口
export interface StatsQueryParams {
metric: string
dimensions?: string[]
filters?: Record<string, any>
timeRange: TimeRange
compareWith?: TimeRange
granularity?: 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year'
limit?: number
offset?: number
}
// 统计响应接口
export interface StatsResponse {
data: any[]
total: number
timeRange: TimeRange
generatedAt: string
metadata: {
query: StatsQueryParams
processingTime: number
dataFreshness: string
confidence: number
}
}
// 统计预警配置接口
export interface StatsAlertConfig {
metric: string
threshold: number
condition: 'above' | 'below' | 'equal' | 'change'
timeRange: TimeRange
severity: 'critical' | 'warning' | 'info'
notificationChannels: string[]
recipients: string[]
cooldownPeriod: number
// 高级配置
aggregation?: string
windowSize?: number
minimumSamples?: number
}
// 统计报告接口
export interface StatsReport {
id: string
title: string
type: 'daily' | 'weekly' | 'monthly' | 'quarterly' | 'yearly' | 'custom'
period: string
metrics: Record<string, any>
insights: string[]
recommendations: string[]
generatedAt: string
// 报告详情
executiveSummary?: string
detailedAnalysis?: string
visualizations?: any[]
attachments?: string[]
// 分发信息
recipients?: string[]
deliveryStatus?: 'pending' | 'sent' | 'delivered' | 'failed'
// 安全信息
accessLevel?: 'public' | 'internal' | 'confidential'
retentionPolicy?: string
}

View File

@@ -0,0 +1,130 @@
// 用户状态类型
export type UserStatus = 'active' | 'inactive' | 'banned'
// 用户类型
export type UserType = 'normal' | 'merchant' | 'admin'
// 用户基本信息接口
export interface User {
id: number
username: string
nickname: string
avatar: string
phone: string
email: string
status: UserStatus
registerTime: string
lastLoginTime: string
userType: UserType
// 扩展字段
gender?: 'male' | 'female' | 'unknown'
birthday?: string
interests?: string[]
location?: string
// 商家特有字段
shopName?: string
businessLicense?: string
// 统计信息
travelCount?: number
animalAdoptionCount?: number
orderCount?: number
// 安全相关
isVerified?: boolean
verificationLevel?: number
}
// 用户查询参数接口
export interface UserQueryParams {
page: number
pageSize: number
keyword?: string
status?: UserStatus
userType?: UserType
startDate?: string
endDate?: string
sortField?: string
sortOrder?: 'asc' | 'desc'
}
// 用户统计信息接口
export interface UserStatistics {
totalUsers: number
activeUsers: number
newUsersToday: number
newUsersThisWeek: number
newUsersThisMonth: number
userGrowthRate: number
userTypeDistribution: {
normal: number
merchant: number
admin: number
}
statusDistribution: {
active: number
inactive: number
banned: number
}
dailyActiveUsers: Array<{
date: string
count: number
}>
}
// 用户操作记录接口
export interface UserOperationLog {
id: number
userId: number
username: string
operationType: string
operationDetail: string
operationTime: string
ipAddress: string
userAgent: string
result: 'success' | 'failure'
}
// 用户注册统计接口
export interface UserRegistrationStats {
date: string
count: number
}
// 用户登录统计接口
export interface UserLoginStats {
date: string
count: number
}
// 用户行为统计接口
export interface UserBehaviorStats {
date: string
travelPublishCount: number
animalAdoptionCount: number
orderCount: number
messageCount: number
shareCount: number
}
// 用户导出参数接口
export interface UserExportParams {
format: 'csv' | 'excel'
fields: string[]
startDate?: string
endDate?: string
status?: UserStatus
userType?: UserType
}
// 管理员信息接口
export interface Admin {
id: number
username: string
email: string
nickname: string
avatar: string
role: string
status: number
lastLoginTime?: string
createdAt: string
updatedAt: string
}

View File

@@ -11,10 +11,10 @@ export default defineConfig({
},
},
server: {
port: 3001,
port: 3150,
proxy: {
'/api': {
target: 'http://localhost:3000',
target: 'http://localhost:3100',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '/api/v1')
}