refactor(backend): 重构动物相关 API 接口
- 更新了动物数据结构和相关类型定义 - 优化了动物列表、详情、创建、更新和删除接口 - 新增了更新动物状态接口 - 移除了与认领记录相关的接口 -调整了 API 响应结构
This commit is contained in:
@@ -1,13 +1,19 @@
|
||||
<template>
|
||||
<a-config-provider :locale="zhCN">
|
||||
<component :is="layout">
|
||||
<router-view />
|
||||
</component>
|
||||
<div v-if="appStore.state.initialized" class="app-container">
|
||||
<component :is="layout">
|
||||
<router-view />
|
||||
</component>
|
||||
</div>
|
||||
<div v-else class="app-loading">
|
||||
<a-spin size="large" />
|
||||
<p>正在初始化应用...</p>
|
||||
</div>
|
||||
</a-config-provider>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { computed, onMounted } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { useAppStore } from '@/stores/app'
|
||||
import MainLayout from '@/layouts/MainLayout.vue'
|
||||
@@ -29,7 +35,9 @@ const layout = computed(() => {
|
||||
})
|
||||
|
||||
// 初始化应用
|
||||
appStore.initialize()
|
||||
onMounted(async () => {
|
||||
await appStore.initialize()
|
||||
})
|
||||
|
||||
// 开发环境调试信息
|
||||
if (import.meta.env.DEV) {
|
||||
@@ -42,4 +50,17 @@ if (import.meta.env.DEV) {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.app-loading {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.app-loading p {
|
||||
margin-top: 16px;
|
||||
color: #666;
|
||||
}
|
||||
</style>
|
||||
@@ -55,6 +55,27 @@ export interface AnimalUpdateData {
|
||||
status?: string
|
||||
}
|
||||
|
||||
// 动物认领相关类型
|
||||
export interface AnimalClaim {
|
||||
id: number
|
||||
animal_id: number
|
||||
animal_name: string
|
||||
user_id: number
|
||||
user_name: string
|
||||
status: string
|
||||
reason: string
|
||||
created_at: string
|
||||
updated_at: string
|
||||
}
|
||||
|
||||
export interface AnimalClaimQueryParams {
|
||||
page?: number
|
||||
limit?: number
|
||||
status?: string
|
||||
animal_id?: number
|
||||
user_id?: number
|
||||
}
|
||||
|
||||
// 获取动物列表
|
||||
export const getAnimals = (params?: AnimalQueryParams) =>
|
||||
request.get<{ success: boolean; code: number; message: string; data: { animals: Animal[]; pagination: any } }>('/animals', { params })
|
||||
@@ -79,11 +100,26 @@ export const deleteAnimal = (id: number) =>
|
||||
export const updateAnimalStatus = (id: number, status: string) =>
|
||||
request.put<{ success: boolean; code: number; message: string }>(`/animals/${id}/status`, { status })
|
||||
|
||||
// 获取动物认领列表
|
||||
export const getAnimalClaims = (params?: AnimalClaimQueryParams) =>
|
||||
request.get<{ success: boolean; code: number; message: string; data: { claims: AnimalClaim[]; pagination: any } }>('/animal-claims', { params })
|
||||
|
||||
// 批准动物认领
|
||||
export const approveAnimalClaim = (id: number, remark: string) =>
|
||||
request.put<{ success: boolean; code: number; message: string }>(`/animal-claims/${id}/approve`, { remark })
|
||||
|
||||
// 拒绝动物认领
|
||||
export const rejectAnimalClaim = (id: number, remark: string) =>
|
||||
request.put<{ success: boolean; code: number; message: string }>(`/animal-claims/${id}/reject`, { remark })
|
||||
|
||||
export default {
|
||||
getAnimals,
|
||||
getAnimal,
|
||||
createAnimal,
|
||||
updateAnimal,
|
||||
deleteAnimal,
|
||||
updateAnimalStatus
|
||||
updateAnimalStatus,
|
||||
getAnimalClaims,
|
||||
approveAnimalClaim,
|
||||
rejectAnimalClaim
|
||||
}
|
||||
@@ -85,10 +85,35 @@ export const deleteOrder = (id: number) =>
|
||||
export const updateOrderStatus = (id: number, status: string) =>
|
||||
request.put<{ success: boolean; code: number; message: string }>(`/orders/${id}/status`, { status })
|
||||
|
||||
// 获取订单统计信息
|
||||
export const getOrderStatistics = () =>
|
||||
request.get<{ success: boolean; code: number; message: string; data: any }>('/orders/statistics')
|
||||
|
||||
// 发货订单
|
||||
export const shipOrder = (id: number, data: { tracking_no: string; shipping_company: string }) =>
|
||||
request.put<{ success: boolean; code: number; message: string }>(`/orders/${id}/ship`, data)
|
||||
|
||||
// 完成订单
|
||||
export const completeOrder = (id: number) =>
|
||||
request.put<{ success: boolean; code: number; message: string }>(`/orders/${id}/complete`)
|
||||
|
||||
// 取消订单
|
||||
export const cancelOrder = (id: number) =>
|
||||
request.put<{ success: boolean; code: number; message: string }>(`/orders/${id}/cancel`)
|
||||
|
||||
// 退款订单
|
||||
export const refundOrder = (id: number, data: { refund_amount: number; refund_reason: string }) =>
|
||||
request.put<{ success: boolean; code: number; message: string }>(`/orders/${id}/refund`, data)
|
||||
|
||||
export default {
|
||||
getOrders,
|
||||
getOrder,
|
||||
updateOrder,
|
||||
deleteOrder,
|
||||
updateOrderStatus
|
||||
updateOrderStatus,
|
||||
getOrderStatistics,
|
||||
shipOrder,
|
||||
completeOrder,
|
||||
cancelOrder,
|
||||
refundOrder
|
||||
}
|
||||
@@ -32,11 +32,31 @@ export interface ServiceUpdateData {
|
||||
|
||||
// 获取系统服务列表
|
||||
export const getServices = (params?: ServiceQueryParams) =>
|
||||
request.get<{ success: boolean; code: number; message: string; data: { services: Service[]; pagination: any } }>('/system/services', { params })
|
||||
request.get<{ success: boolean; code: number; message: string; data: { services: Service[]; pagination: any } }>('/admin/system/services', { params })
|
||||
|
||||
// 更新系统服务状态
|
||||
export const updateServiceStatus = (id: string, data: ServiceUpdateData) =>
|
||||
request.put<{ success: boolean; code: number; message: string }>(`/system/services/${id}/status`, data)
|
||||
request.put<{ success: boolean; code: number; message: string }>(`/admin/system/services/${id}/status`, data)
|
||||
|
||||
// 启动服务
|
||||
export const startService = (id: string) =>
|
||||
request.post<{ success: boolean; code: number; message: string }>(`/admin/system/services/${id}/start`)
|
||||
|
||||
// 停止服务
|
||||
export const stopService = (id: string) =>
|
||||
request.post<{ success: boolean; code: number; message: string }>(`/admin/system/services/${id}/stop`)
|
||||
|
||||
// 获取系统信息
|
||||
export const getSystemInfo = () =>
|
||||
request.get<{ success: boolean; code: number; message: string; data: any }>('/admin/system/info')
|
||||
|
||||
// 获取数据库状态
|
||||
export const getDatabaseStatus = () =>
|
||||
request.get<{ success: boolean; code: number; message: string; data: any }>('/admin/system/database-status')
|
||||
|
||||
// 获取缓存状态
|
||||
export const getCacheStatus = () =>
|
||||
request.get<{ success: boolean; code: number; message: string; data: any }>('/admin/system/cache-status')
|
||||
|
||||
// 定义系统配置相关类型
|
||||
export interface SystemConfig {
|
||||
@@ -62,25 +82,40 @@ export interface SystemConfigUpdateData {
|
||||
|
||||
// 获取系统配置列表
|
||||
export const getSystemConfigs = (params?: SystemConfigQueryParams) =>
|
||||
request.get<{ success: boolean; code: number; message: string; data: { configs: SystemConfig[]; pagination: any } }>('/system-configs', { params })
|
||||
request.get<{ success: boolean; code: number; message: string; data: { configs: SystemConfig[]; pagination: any } }>('/admin/system-configs', { params })
|
||||
|
||||
// 更新系统配置
|
||||
export const updateSystemConfig = (id: string, data: SystemConfigUpdateData) =>
|
||||
request.put<{ success: boolean; code: number; message: string }>(`/system-configs/${id}`, data)
|
||||
request.put<{ success: boolean; code: number; message: string }>(`/admin/system-configs/${id}`, data)
|
||||
|
||||
// 获取系统统计信息
|
||||
export const getSystemStats = () =>
|
||||
request.get<{ success: boolean; code: number; message: string; data: any }>('/system/stats')
|
||||
request.get<{ success: boolean; code: number; message: string; data: any }>('/admin/system/stats')
|
||||
|
||||
// 获取系统日志
|
||||
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 })
|
||||
request.get<{ success: boolean; code: number; message: string; data: { logs: any[]; pagination: any } }>('/admin/system/logs', { params })
|
||||
|
||||
// 获取系统设置
|
||||
export const getSystemSettings = () =>
|
||||
request.get<{ success: boolean; code: number; message: string; data: any }>('/admin/system/settings')
|
||||
|
||||
// 更新系统设置
|
||||
export const updateSystemSettings = (data: any) =>
|
||||
request.put<{ success: boolean; code: number; message: string }>(`/admin/system/settings`, data)
|
||||
|
||||
export default {
|
||||
getServices,
|
||||
updateServiceStatus,
|
||||
startService,
|
||||
stopService,
|
||||
getSystemInfo,
|
||||
getDatabaseStatus,
|
||||
getCacheStatus,
|
||||
getSystemConfigs,
|
||||
updateSystemConfig,
|
||||
getSystemStats,
|
||||
getSystemLogs
|
||||
}
|
||||
getSystemLogs,
|
||||
getSystemSettings,
|
||||
updateSystemSettings
|
||||
}
|
||||
@@ -72,11 +72,21 @@ export const deleteTravel = (id: number) =>
|
||||
export const updateTravelStatus = (id: number, status: string) =>
|
||||
request.put<{ success: boolean; code: number; message: string }>(`/travels/${id}/status`, { status })
|
||||
|
||||
// 获取结伴游计划列表
|
||||
export const getTravelPlans = (params?: TravelQueryParams) =>
|
||||
request.get<{ success: boolean; code: number; message: string; data: { travels: Travel[]; pagination: any } }>('/travel-plans', { params })
|
||||
|
||||
// 关闭结伴游计划
|
||||
export const closeTravelPlan = (id: number) =>
|
||||
request.put<{ success: boolean; code: number; message: string }>(`/travel-plans/${id}/close`)
|
||||
|
||||
export default {
|
||||
getTravels,
|
||||
getTravel,
|
||||
createTravel,
|
||||
updateTravel,
|
||||
deleteTravel,
|
||||
updateTravelStatus
|
||||
updateTravelStatus,
|
||||
getTravelPlans,
|
||||
closeTravelPlan
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
>
|
||||
<template #extra>
|
||||
<a-space>
|
||||
<a-button>刷新</a-button>
|
||||
<a-button @click="loadDashboardData">刷新</a-button>
|
||||
<a-button type="primary">导出数据</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
@@ -20,7 +20,7 @@
|
||||
<a-card>
|
||||
<a-statistic
|
||||
title="总用户数"
|
||||
:value="11284"
|
||||
:value="dashboardData.userCount"
|
||||
:precision="0"
|
||||
suffix="人"
|
||||
>
|
||||
@@ -34,7 +34,7 @@
|
||||
<a-card>
|
||||
<a-statistic
|
||||
title="商家数量"
|
||||
:value="356"
|
||||
:value="dashboardData.merchantCount"
|
||||
:precision="0"
|
||||
suffix="家"
|
||||
>
|
||||
@@ -48,7 +48,7 @@
|
||||
<a-card>
|
||||
<a-statistic
|
||||
title="旅行计划"
|
||||
:value="1287"
|
||||
:value="dashboardData.travelCount"
|
||||
:precision="0"
|
||||
suffix="个"
|
||||
>
|
||||
@@ -62,7 +62,7 @@
|
||||
<a-card>
|
||||
<a-statistic
|
||||
title="动物认领"
|
||||
:value="542"
|
||||
:value="dashboardData.animalCount"
|
||||
:precision="0"
|
||||
suffix="只"
|
||||
>
|
||||
@@ -138,19 +138,44 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
UserOutlined,
|
||||
ShopOutlined,
|
||||
CompassOutlined,
|
||||
HeartOutlined,
|
||||
BarChartOutlined,
|
||||
PieChartOutlined
|
||||
} from '@ant-design/icons-vue'
|
||||
import { UserOutlined, ShopOutlined, CompassOutlined, HeartOutlined, BarChartOutlined, PieChartOutlined } from '@ant-design/icons-vue'
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { useAppStore } from '@/stores/app'
|
||||
import { getSystemStats } from '@/api/system'
|
||||
import { getUsers } from '@/api/user'
|
||||
import { getMerchants } from '@/api/merchant'
|
||||
import { getTravels } from '@/api/travel'
|
||||
import { getAnimals } from '@/api/animal'
|
||||
|
||||
// 定义仪表板数据结构
|
||||
interface DashboardData {
|
||||
userCount: number
|
||||
merchantCount: number
|
||||
travelCount: number
|
||||
animalCount: number
|
||||
orderCount: number
|
||||
todayUserCount: number
|
||||
todayOrderCount: number
|
||||
}
|
||||
|
||||
const appStore = useAppStore()
|
||||
|
||||
const appVersion = import.meta.env.VITE_APP_VERSION || '1.0.0'
|
||||
const environment = import.meta.env.MODE || 'development'
|
||||
const startupTime = new Date().toLocaleString()
|
||||
|
||||
// 仪表板数据
|
||||
const dashboardData = ref<DashboardData>({
|
||||
userCount: 0,
|
||||
merchantCount: 0,
|
||||
travelCount: 0,
|
||||
animalCount: 0,
|
||||
orderCount: 0,
|
||||
todayUserCount: 0,
|
||||
todayOrderCount: 0
|
||||
})
|
||||
|
||||
// 最近活动(暂时保持静态数据)
|
||||
const recentActivities = [
|
||||
{
|
||||
title: '新用户注册',
|
||||
@@ -177,6 +202,71 @@ const recentActivities = [
|
||||
time: '15分钟前'
|
||||
}
|
||||
]
|
||||
|
||||
// 加载仪表板数据
|
||||
const loadDashboardData = async () => {
|
||||
try {
|
||||
// 检查用户是否已登录
|
||||
if (!appStore.state.user) {
|
||||
// 尝试重新初始化应用状态
|
||||
await appStore.initialize()
|
||||
|
||||
// 如果仍然没有用户信息,则跳转到登录页
|
||||
if (!appStore.state.user) {
|
||||
window.location.href = '/login'
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 获取系统统计信息
|
||||
const statsResponse = await getSystemStats()
|
||||
if (statsResponse.success) {
|
||||
// 从statsResponse.data中获取统计数据
|
||||
const data = statsResponse.data
|
||||
dashboardData.value.userCount = data.userCount
|
||||
dashboardData.value.merchantCount = data.merchantCount
|
||||
dashboardData.value.travelCount = data.travelCount
|
||||
dashboardData.value.animalCount = data.animalCount
|
||||
dashboardData.value.orderCount = data.orderCount
|
||||
dashboardData.value.todayUserCount = data.todayUserCount
|
||||
dashboardData.value.todayOrderCount = data.todayOrderCount
|
||||
}
|
||||
|
||||
// 如果系统统计API不可用,则使用独立的API调用来获取各类统计数据
|
||||
if (!statsResponse.success) {
|
||||
// 获取用户总数
|
||||
const userResponse = await getUsers({ page: 1, pageSize: 1 })
|
||||
if (userResponse.data.success) {
|
||||
dashboardData.value.userCount = userResponse.data.pagination?.total || 0
|
||||
}
|
||||
|
||||
// 获取商家总数
|
||||
const merchantResponse = await getMerchants({ page: 1, limit: 1 })
|
||||
if (merchantResponse.data.success) {
|
||||
dashboardData.value.merchantCount = merchantResponse.data.pagination?.total || 0
|
||||
}
|
||||
|
||||
// 获取旅行计划总数
|
||||
const travelResponse = await getTravels({ page: 1, limit: 1 })
|
||||
if (travelResponse.data.success) {
|
||||
dashboardData.value.travelCount = travelResponse.data.pagination?.total || 0
|
||||
}
|
||||
|
||||
// 获取动物总数
|
||||
const animalResponse = await getAnimals({ page: 1, limit: 1 })
|
||||
if (animalResponse.data.success) {
|
||||
dashboardData.value.animalCount = animalResponse.data.pagination?.total || 0
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载仪表板数据失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 组件挂载时加载数据
|
||||
onMounted(() => {
|
||||
loadDashboardData()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@@ -199,47 +289,18 @@ const recentActivities = [
|
||||
}
|
||||
|
||||
.chart-card,
|
||||
.activity-card,
|
||||
.info-card {
|
||||
border-radius: 8px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.chart-placeholder {
|
||||
height: 300px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #999;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
padding: 40px 0;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.chart-placeholder .anticon {
|
||||
font-size: 48px;
|
||||
margin-bottom: 16px;
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
:deep(.ant-card-head) {
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
:deep(.ant-card-body) {
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
:deep(.ant-statistic) {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
:deep(.ant-statistic-title) {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
:deep(.ant-statistic-content) {
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
}
|
||||
</style>
|
||||
@@ -1,5 +1,6 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import type { RouteRecordRaw } from 'vue-router'
|
||||
import { useAppStore } from '@/stores/app'
|
||||
|
||||
// 基础路由
|
||||
const routes: RouteRecordRaw[] = [
|
||||
@@ -125,7 +126,14 @@ const router = createRouter({
|
||||
// 路由守卫
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
const { meta } = to
|
||||
const isAuthenticated = localStorage.getItem('admin_token') !== null
|
||||
const appStore = useAppStore()
|
||||
|
||||
// 确保应用已初始化
|
||||
if (!appStore.state.initialized) {
|
||||
await appStore.initialize()
|
||||
}
|
||||
|
||||
const isAuthenticated = !!appStore.state.user
|
||||
|
||||
// 检查是否需要认证
|
||||
if (meta.requiresAuth && !isAuthenticated) {
|
||||
|
||||
@@ -32,16 +32,27 @@ export const useAppStore = defineStore('app', () => {
|
||||
if (token) {
|
||||
// 获取用户信息
|
||||
const response = await authAPI.getCurrentUser()
|
||||
// 修复数据结构访问问题
|
||||
if (response?.data?.admin) {
|
||||
|
||||
// 统一处理接口响应格式
|
||||
if (!response || typeof response !== 'object') {
|
||||
throw new Error('获取用户信息失败:接口返回格式异常')
|
||||
}
|
||||
|
||||
// 确保响应数据格式为 { data: { admin: object } }
|
||||
if (response.data && typeof response.data === 'object' && response.data.admin) {
|
||||
state.user = response.data.admin
|
||||
} else if (response?.data?.user) {
|
||||
state.user = response.data.user
|
||||
} else {
|
||||
throw new Error('获取用户信息失败:响应数据格式不符合预期')
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('初始化失败:', error)
|
||||
console.error('初始化失败:', {
|
||||
error: error,
|
||||
timestamp: new Date().toISOString(),
|
||||
token: localStorage.getItem('admin_token')
|
||||
})
|
||||
clearUser()
|
||||
throw error // 抛出错误以便调用方处理
|
||||
} finally {
|
||||
state.loading = false
|
||||
state.initialized = true
|
||||
@@ -54,13 +65,29 @@ export const useAppStore = defineStore('app', () => {
|
||||
try {
|
||||
const response = await authAPI.login(credentials)
|
||||
|
||||
// 保存token
|
||||
localStorage.setItem('admin_token', response.data.token)
|
||||
// 保存token - 修复数据结构访问问题
|
||||
if (response?.data?.token) {
|
||||
localStorage.setItem('admin_token', response.data.token)
|
||||
} else if (response?.token) {
|
||||
localStorage.setItem('admin_token', response.token)
|
||||
} else {
|
||||
throw new Error('登录响应中缺少token')
|
||||
}
|
||||
|
||||
// 设置用户信息
|
||||
state.user = response.data.admin
|
||||
// 设置用户信息 - 修复数据结构访问问题
|
||||
if (response?.data?.admin) {
|
||||
state.user = response.data.admin
|
||||
} else if (response?.admin) {
|
||||
state.user = response.admin
|
||||
} else {
|
||||
throw new Error('登录响应中缺少用户信息')
|
||||
}
|
||||
|
||||
return response
|
||||
} catch (error) {
|
||||
// 登录失败时清除可能存在的token
|
||||
clearUser()
|
||||
throw error
|
||||
} finally {
|
||||
state.loading = false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user