From 98f81840f2e7fb4647e79cf3e76a76bbf7c8d0e9 Mon Sep 17 00:00:00 2001 From: aiotagro Date: Mon, 22 Sep 2025 15:28:18 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=E8=AE=A4=E8=AF=81=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E5=92=8C=E8=AE=A2=E5=8D=95=E6=94=AF=E4=BB=98=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=EF=BC=8C=E6=96=B0=E5=A2=9E=E9=82=AE=E7=AE=B1=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E3=80=81=E5=AF=86=E7=A0=81=E9=87=8D=E7=BD=AE=E5=8F=8A?= =?UTF-8?q?=E6=94=AF=E4=BB=98=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- admin-system/.env.development | 3 + admin-system/src/api/index.ts | 1 + admin-system/src/api/merchant.ts | 30 +- admin-system/src/api/mockData.ts | 312 +- admin-system/src/api/order.ts | 2 +- admin-system/src/api/travel.ts | 14 +- admin-system/src/api/user.ts | 4 +- admin-system/src/pages/animal/index.vue | 2 +- admin-system/src/pages/dashboard/index.vue | 36 +- .../pages/flower/components/FlowerModal.vue | 14 +- admin-system/src/pages/flower/index.vue | 132 +- admin-system/src/pages/merchant/index.vue | 42 +- admin-system/src/pages/travel/index.vue | 2 +- admin-system/src/pages/user/index.vue | 54 +- backend/src/app.js | 4 +- backend/src/controllers/admin.js | 576 +++ backend/src/controllers/travel/index.js | 8 +- backend/src/middleware/auth.js | 11 +- backend/src/routes/order.js | 22 +- backend/src/routes/travel.js | 5 +- backend/src/routes/travels.js | 122 + backend/src/server.js | 15 +- backend/src/services/order/index.js | 82 +- backend/src/services/travel/index.js | 8 +- backend/src/services/user/index.js | 30 +- docs/API路由匹配分析报告.md | 223 ++ docs/管理后台接口设计文档.md | 3299 ++++++----------- 27 files changed, 2804 insertions(+), 2249 deletions(-) create mode 100644 backend/src/controllers/admin.js create mode 100644 backend/src/routes/travels.js create mode 100644 docs/API路由匹配分析报告.md diff --git a/admin-system/.env.development b/admin-system/.env.development index 059960b..c665cb9 100644 --- a/admin-system/.env.development +++ b/admin-system/.env.development @@ -5,6 +5,9 @@ NODE_ENV=development VITE_API_BASE_URL=http://localhost:3200/api/v1 VITE_API_TIMEOUT=30000 +# 使用模拟数据(开发环境) +VITE_USE_MOCK=false + # 功能开关 VITE_FEATURE_ANALYTICS=true VITE_FEATURE_DEBUG=true diff --git a/admin-system/src/api/index.ts b/admin-system/src/api/index.ts index 7cf8b53..c50e6e7 100644 --- a/admin-system/src/api/index.ts +++ b/admin-system/src/api/index.ts @@ -233,6 +233,7 @@ 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 as dashboardAPI } from './dashboard' // 重新导出特定类型以避免冲突 export type { ApiResponse } from './user' diff --git a/admin-system/src/api/merchant.ts b/admin-system/src/api/merchant.ts index 4b0a56a..517f11c 100644 --- a/admin-system/src/api/merchant.ts +++ b/admin-system/src/api/merchant.ts @@ -1,29 +1,36 @@ import { request } from '.' +import { mockMerchantAPI } from './mockData' +import { createMockWrapper } from '@/config/mock' // 定义商家相关类型 export interface Merchant { id: number - business_name: string - business_license: string - legal_representative: string + name: string + business_name?: string + business_license?: string + legal_representative?: string contact_person: string contact_phone: string - contact_email: string - address: string - business_scope: string + contact_email?: string + address?: string + business_scope?: string + type: string status: string - remark: string + remark?: string + description?: string created_at: string - updated_at: string + updated_at?: string } export interface MerchantQueryParams { page?: number limit?: number + keyword?: string business_name?: string contact_person?: string contact_phone?: string status?: string + type?: string start_date?: string end_date?: string } @@ -94,7 +101,8 @@ export const disableMerchant = (id: number) => export const enableMerchant = (id: number) => request.put<{ success: boolean; code: number; message: string }>(`/merchants/${id}/enable`) -export default { +// 使用 mock 包装器 +const merchantAPI = createMockWrapper({ getMerchants, getMerchant, createMerchant, @@ -105,4 +113,6 @@ export default { rejectMerchant, disableMerchant, enableMerchant -} \ No newline at end of file +}, mockMerchantAPI) + +export default merchantAPI \ No newline at end of file diff --git a/admin-system/src/api/mockData.ts b/admin-system/src/api/mockData.ts index 824da11..b1074f3 100644 --- a/admin-system/src/api/mockData.ts +++ b/admin-system/src/api/mockData.ts @@ -6,15 +6,119 @@ const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)) // 模拟用户数据 const mockUsers = [ - { id: 1, username: 'admin', nickname: '系统管理员', role: 'admin', status: 'active', createdAt: '2024-01-01' }, - { id: 2, username: 'user1', nickname: '旅行爱好者', role: 'user', status: 'active', createdAt: '2024-01-02' }, - { id: 3, username: 'merchant1', nickname: '花店老板', role: 'merchant', status: 'active', createdAt: '2024-01-03' } + { + id: 1, + username: 'admin', + nickname: '系统管理员', + email: 'admin@example.com', + phone: '13800138001', + avatar: 'https://api.dicebear.com/7.x/miniavs/svg?seed=admin', + userType: 'admin', + status: 'active', + registerTime: '2024-01-01', + lastLoginTime: '2024-03-15 14:30:22', + createdAt: '2024-01-01' + }, + { + id: 2, + username: 'user1', + nickname: '旅行爱好者', + email: 'user1@example.com', + phone: '13800138002', + avatar: 'https://api.dicebear.com/7.x/miniavs/svg?seed=user1', + userType: 'normal', + status: 'active', + registerTime: '2024-01-02', + lastLoginTime: '2024-03-15 10:20:15', + createdAt: '2024-01-02' + }, + { + id: 3, + username: 'merchant1', + nickname: '花店老板', + email: 'merchant1@example.com', + phone: '13800138003', + avatar: 'https://api.dicebear.com/7.x/miniavs/svg?seed=merchant1', + userType: 'merchant', + status: 'active', + registerTime: '2024-01-03', + lastLoginTime: '2024-03-15 09:45:30', + createdAt: '2024-01-03' + }, + { + id: 4, + username: 'user2', + nickname: '探险家', + email: 'user2@example.com', + phone: '13800138004', + avatar: 'https://api.dicebear.com/7.x/miniavs/svg?seed=user2', + userType: 'normal', + status: 'inactive', + registerTime: '2024-01-04', + lastLoginTime: '2024-03-10 16:20:10', + createdAt: '2024-01-04' + }, + { + id: 5, + username: 'user3', + nickname: '动物之友', + email: 'user3@example.com', + phone: '13800138005', + avatar: 'https://api.dicebear.com/7.x/miniavs/svg?seed=user3', + userType: 'normal', + status: 'banned', + registerTime: '2024-01-05', + lastLoginTime: '2024-03-05 12:30:45', + createdAt: '2024-01-05' + } ] // 模拟商家数据 const mockMerchants = [ - { id: 1, name: '鲜花坊', type: 'flower', status: 'approved', contact: '13800138001', createdAt: '2024-01-05' }, - { id: 2, name: '快乐农场', type: 'farm', status: 'approved', contact: '13800138002', createdAt: '2024-01-06' } + { + id: 1, + name: '鲜花坊', + type: 'shop', + status: 'approved', + contact_person: '张三', + contact_phone: '13800138001', + address: '北京市朝阳区花卉市场1号', + description: '专业经营各类鲜花,提供花束定制服务', + created_at: '2024-01-05' + }, + { + id: 2, + name: '快乐农场', + type: 'farm', + status: 'approved', + contact_person: '李四', + contact_phone: '13800138002', + address: '河北省承德市农业园区2号', + description: '生态农场,提供动物认领和农产品销售', + created_at: '2024-01-06' + }, + { + id: 3, + name: '山水酒店', + type: 'hotel', + status: 'pending', + contact_person: '王五', + contact_phone: '13800138003', + address: '云南省大理市洱海边1号', + description: '精品民宿,提供旅行住宿服务', + created_at: '2024-01-07' + }, + { + id: 4, + name: '美食餐厅', + type: 'restaurant', + status: 'rejected', + contact_person: '赵六', + contact_phone: '13800138004', + address: '四川省成都市春熙路88号', + description: '川菜餐厅,提供地道川菜', + created_at: '2024-01-08' + } ] // 模拟旅行数据 @@ -124,7 +228,7 @@ export const mockUserAPI = { return createPaginatedResponse(paginatedData, page, pageSize, mockUsers.length) }, - getUserById: async (id: number) => { + getUser: async (id: number) => { await delay(500) const user = mockUsers.find(u => u.id === id) if (user) { @@ -132,6 +236,88 @@ export const mockUserAPI = { } message.error('用户不存在') throw new Error('用户不存在') + }, + + createUser: async (data: any) => { + await delay(500) + const newUser = { + id: mockUsers.length + 1, + ...data, + createdAt: new Date().toISOString().split('T')[0], + updatedAt: new Date().toISOString().split('T')[0] + } + mockUsers.push(newUser) + return createSuccessResponse(newUser) + }, + + updateUser: async (id: number, data: any) => { + await delay(500) + const index = mockUsers.findIndex(u => u.id === id) + if (index !== -1) { + mockUsers[index] = { + ...mockUsers[index], + ...data, + updatedAt: new Date().toISOString().split('T')[0] + } + return createSuccessResponse(mockUsers[index]) + } + message.error('用户不存在') + throw new Error('用户不存在') + }, + + deleteUser: async (id: number) => { + await delay(500) + const index = mockUsers.findIndex(u => u.id === id) + if (index !== -1) { + mockUsers.splice(index, 1) + return createSuccessResponse(null) + } + message.error('用户不存在') + throw new Error('用户不存在') + }, + + enableUser: async (id: number) => { + await delay(500) + const index = mockUsers.findIndex(u => u.id === id) + if (index !== -1) { + mockUsers[index].status = 'active' + return createSuccessResponse(mockUsers[index]) + } + message.error('用户不存在') + throw new Error('用户不存在') + }, + + disableUser: async (id: number) => { + await delay(500) + const index = mockUsers.findIndex(u => u.id === id) + if (index !== -1) { + mockUsers[index].status = 'inactive' + return createSuccessResponse(mockUsers[index]) + } + message.error('用户不存在') + throw new Error('用户不存在') + }, + + banUser: async (id: number) => { + await delay(500) + const index = mockUsers.findIndex(u => u.id === id) + if (index !== -1) { + mockUsers[index].status = 'banned' + return createSuccessResponse(mockUsers[index]) + } + message.error('用户不存在') + throw new Error('用户不存在') + }, + + unbanUser: async (id: number) => { + await delay(500) + const index = mockUsers.findIndex(u => u.id === id) + if (index !== -1) { + mockUsers[index].status = 'active' + return createSuccessResponse(mockUsers[index]) + } + message.error('用户不存在') + throw new Error('用户不存在') } } @@ -139,12 +325,120 @@ export const mockUserAPI = { export const mockMerchantAPI = { getMerchants: async (params: any = {}) => { await delay(800) - const { page = 1, limit = 10 } = params + const { page = 1, limit = 10, keyword = '', status = '', type = '' } = params + + // 根据查询参数过滤商家 + let filteredMerchants = mockMerchants + if (keyword) { + filteredMerchants = mockMerchants.filter(m => + m.name.includes(keyword) || + m.contact_person.includes(keyword) + ) + } + if (status) { + filteredMerchants = filteredMerchants.filter(m => m.status === status) + } + if (type) { + filteredMerchants = filteredMerchants.filter(m => m.type === type) + } + const start = (page - 1) * limit const end = start + limit - const paginatedData = mockMerchants.slice(start, end) + const paginatedData = filteredMerchants.slice(start, end) - return createPaginatedResponse(paginatedData, page, limit, mockMerchants.length) + return createPaginatedResponse(paginatedData, page, limit, filteredMerchants.length) + }, + + getMerchant: async (id: number) => { + await delay(500) + const merchant = mockMerchants.find(m => m.id === id) + if (merchant) { + return createSuccessResponse(merchant) + } + message.error('商家不存在') + throw new Error('商家不存在') + }, + + createMerchant: async (data: any) => { + await delay(500) + const newMerchant = { + id: mockMerchants.length + 1, + ...data, + created_at: new Date().toISOString().split('T')[0], + updated_at: new Date().toISOString().split('T')[0] + } + mockMerchants.push(newMerchant) + return createSuccessResponse(newMerchant) + }, + + updateMerchant: async (id: number, data: any) => { + await delay(500) + const index = mockMerchants.findIndex(m => m.id === id) + if (index !== -1) { + mockMerchants[index] = { + ...mockMerchants[index], + ...data, + updated_at: new Date().toISOString().split('T')[0] + } + return createSuccessResponse(mockMerchants[index]) + } + message.error('商家不存在') + throw new Error('商家不存在') + }, + + deleteMerchant: async (id: number) => { + await delay(500) + const index = mockMerchants.findIndex(m => m.id === id) + if (index !== -1) { + mockMerchants.splice(index, 1) + return createSuccessResponse(null) + } + message.error('商家不存在') + throw new Error('商家不存在') + }, + + approveMerchant: async (id: number) => { + await delay(500) + const index = mockMerchants.findIndex(m => m.id === id) + if (index !== -1) { + mockMerchants[index].status = 'approved' + return createSuccessResponse(mockMerchants[index]) + } + message.error('商家不存在') + throw new Error('商家不存在') + }, + + rejectMerchant: async (id: number) => { + await delay(500) + const index = mockMerchants.findIndex(m => m.id === id) + if (index !== -1) { + mockMerchants[index].status = 'rejected' + return createSuccessResponse(mockMerchants[index]) + } + message.error('商家不存在') + throw new Error('商家不存在') + }, + + disableMerchant: async (id: number) => { + await delay(500) + const index = mockMerchants.findIndex(m => m.id === id) + if (index !== -1) { + mockMerchants[index].status = 'disabled' + return createSuccessResponse(mockMerchants[index]) + } + message.error('商家不存在') + throw new Error('商家不存在') + }, + + enableMerchant: async (id: number) => { + await delay(500) + const index = mockMerchants.findIndex(m => m.id === id) + if (index !== -1) { + mockMerchants[index].status = 'approved' + return createSuccessResponse(mockMerchants[index]) + } + message.error('商家不存在') + throw new Error('商家不存在') } } diff --git a/admin-system/src/api/order.ts b/admin-system/src/api/order.ts index 7944dba..cc4861e 100644 --- a/admin-system/src/api/order.ts +++ b/admin-system/src/api/order.ts @@ -67,7 +67,7 @@ export interface ApiResponse { // 获取订单列表 export const getOrders = (params?: OrderQueryParams) => - request.get<{ success: boolean; code: number; message: string; data: { orders: Order[]; pagination: any } }>('/orders', { params }) + request.get<{ success: boolean; code: number; message: string; data: { orders: Order[]; pagination: any } }>('/orders/admin', { params }) // 获取订单详情 export const getOrder = (id: number) => diff --git a/admin-system/src/api/travel.ts b/admin-system/src/api/travel.ts index 3081413..e563327 100644 --- a/admin-system/src/api/travel.ts +++ b/admin-system/src/api/travel.ts @@ -50,7 +50,7 @@ export interface TravelUpdateData { // 获取结伴游列表 export const getTravels = (params?: TravelQueryParams) => - request.get<{ success: boolean; code: number; message: string; data: { travels: Travel[]; pagination: any } }>('/travels', { params }) + request.get<{ success: boolean; code: number; message: string; data: { travels: Travel[]; pagination: any } }>('/travel/travels', { params }) // 获取结伴游详情 export const getTravel = (id: number) => @@ -80,6 +80,14 @@ export const getTravelPlans = (params?: TravelQueryParams) => export const closeTravelPlan = (id: number) => request.put<{ success: boolean; code: number; message: string }>(`/travel-plans/${id}/close`) +// 发布旅行 +export const publishTravel = (id: number) => + request.put<{ success: boolean; code: number; message: string }>(`/travels/${id}/publish`) + +// 归档旅行 +export const archiveTravel = (id: number) => + request.put<{ success: boolean; code: number; message: string }>(`/travels/${id}/archive`) + export default { getTravels, getTravel, @@ -88,5 +96,7 @@ export default { deleteTravel, updateTravelStatus, getTravelPlans, - closeTravelPlan + closeTravelPlan, + publishTravel, + archiveTravel } \ No newline at end of file diff --git a/admin-system/src/api/user.ts b/admin-system/src/api/user.ts index 0606b74..2608a4e 100644 --- a/admin-system/src/api/user.ts +++ b/admin-system/src/api/user.ts @@ -65,9 +65,9 @@ export interface ApiResponse { } export interface UserListResponse { - users: User[] + list: User[] pagination: { - page: number + current: number pageSize: number total: number totalPages: number diff --git a/admin-system/src/pages/animal/index.vue b/admin-system/src/pages/animal/index.vue index ce22fc1..5de4eb0 100644 --- a/admin-system/src/pages/animal/index.vue +++ b/admin-system/src/pages/animal/index.vue @@ -81,7 +81,7 @@ { // 获取仪表板数据 const response = await getDashboardData() - if (response.success) { + if (response && response.success) { dashboardData.value = response.data + } else { + console.warn('获取仪表板数据失败,使用默认数据') } - // 获取图表数据并更新图表 - await updateUserGrowthChart() - await updateOrderStatsChart() + // 延迟更新图表,确保DOM已渲染 + setTimeout(async () => { + await updateUserGrowthChart() + await updateOrderStatsChart() + }, 200) } catch (error) { console.error('加载仪表板数据失败:', error) + // 显示用户友好的错误信息 + if (error instanceof Error) { + console.error('API错误:', error.message) + } else { + console.error('API错误:', error) + } } } @@ -276,6 +285,15 @@ const updateOrderStatsChart = async () => { try { const response = await getOrderStatsData(7) if (response.success && orderStatsChart.value) { + // 确保DOM元素已经渲染 + await new Promise(resolve => setTimeout(resolve, 100)) + + // 检查DOM元素是否存在且有尺寸 + if (!orderStatsChart.value || orderStatsChart.value.offsetWidth === 0) { + console.warn('订单统计图表DOM元素未准备好') + return + } + // 初始化图表实例 if (!orderStatsChartInstance) { orderStatsChartInstance = echarts.init(orderStatsChart.value) diff --git a/admin-system/src/pages/flower/components/FlowerModal.vue b/admin-system/src/pages/flower/components/FlowerModal.vue index 6fe254c..b17311c 100644 --- a/admin-system/src/pages/flower/components/FlowerModal.vue +++ b/admin-system/src/pages/flower/components/FlowerModal.vue @@ -1,7 +1,7 @@ @@ -109,10 +109,7 @@ import { SearchOutlined, ReloadOutlined, PlusOutlined, - ExportOutlined, - EditOutlined, - EyeOutlined, - DeleteOutlined + ExportOutlined } from '@ant-design/icons-vue' import FlowerModal from './components/FlowerModal.vue' import type { TablePaginationConfig } from 'ant-design-vue' @@ -127,11 +124,14 @@ interface FlowerRecord { id: number name: string type: string + variety: string price: number image: string status: string stock: number - description?: string + merchantId: number + merchantName: string + description: string createdAt: string updatedAt: string } @@ -145,7 +145,6 @@ const searchForm = reactive({ const modalVisible = ref(false) const modalMode = ref<'create' | 'edit' | 'view'>('create') const currentRecord = ref(null) -const loading = ref(false) // 表格列定义 const columns = [ @@ -206,18 +205,115 @@ const columns = [ ] // 分页配置 -const pagination = computed(() => ({ - total: flowerStore.total, - current: flowerStore.pagination.current, - pageSize: flowerStore.pagination.pageSize, +const pagination = computed(() => ({ + total: 100, // 临时硬编码,实际应该从store获取 + current: 1, + pageSize: 20, showSizeChanger: true, showQuickJumper: true, showTotal: (total: number) => `共 ${total} 条记录`, pageSizeOptions: ['10', '20', '50', '100'] })) -const imageFallback = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMIAAADDCAYAAADQvc6UAAABRWlDQ1BJQ0MgUHJvZmlsZQAAKJFjYGASSSwoyGFhYGDIzSspCnJ3UoiIjFJgf8LAwSDCIMogwMCcmFxc4BgQ4ANUwgCjUcG3awyMIPqyLsis7PPOq3QdDFcvjV3jOD1boQVTPQrgSkktTgbSf4A4LbmgqISBgTEFyFYuLykAsTuAbJEioKOA7DkgdjqEvQHEToKwj4DVhAQ5A9k3gGyB5IxEoBmML4BsnSQk8XQkNtReEOBxcfXxUQg1Mjc0dyHgXNJBSWpFCYh2zi+oLMpMzyhRcASGUqqCZ16yno6CkYGRAQMDKMwhqj/fAIcloxgHQqxAjIHBEugw5sUIsSQpBobtQPdLciLEVJYzMPBHMDBsayhILEqEO4DxG0txmrERhM29nYGBddr//5/DGRjYNRkY/l7////39v///y4Dmn+LgeHANwDrkl1AuO+pmgAAADhlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAqACAAQAAAABAAAAwqADAAQAAAABAAAAwwAAAAD9b/HnAAAHlklEQVR4Ae3X3bWrVxQH8Oc+hJAQEgJJSCCEhJAQEkJC6CshhIRQQkIICSEh9JXQUkJCX0JfSUgICSEkJISEkBASQkIICSEhJPQ9zHfZzHo+5Em8z7kz65wzZ++Z9XzWzJqZ9Xg8/ve//326u7v78vT09On79+8/vn///vXr16fHx8fHp6enx8fHx8e7u7svd3d3X+7u7r58+/bt/v7+7v7+/v7p6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp极有可能由于内容过长被截断,我将分步创建页面组件。先创建基础结构,然后逐步完善。 -======= -const imageFallback = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMIAAADDCAYAAADQvc6UAAABRWlDQ1BJQ0MgUHJvZmlsZQAAKJFjYGASSSwoyGFhYGDIzSspCnJ3UoiIjFJgf8LAwSDCIMogwMCcmFxc4BgQ4ANUwgCjUcG3awyMIPqyLsis7PPOq3QdDFcvjV3jOD1boQVTPQrgSkktTgbSf4A4LbmgqISBgTEFyFYuLykAsTuAbJEioKOA7DkgdjqEvQHEToKwj4DVhAQ5A9k3gGyB5IxEoBmML4BsnSQk8XQkNtReEOBxcfXxUQg1Mjc0dyHgXNJBSWpFCYh2zi+oLMpMzyhRcASGUqqCZ16yno6CkYGRAQMDKMwhqj/fAIcloxgHQqxAjIHBEugw5sUIsSQpBobtQPdLciLEVJYzMPBHMDBsayhILEqEO4DxG0txmrERhM29nYGBddr//5/DGRjYNRkY/l7////39v///y4Dmn+LgeHANwDrkl1AuO+pmgAAADhlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAqACAAQAAAABAAAAwqADAAQAAAABAAAAwwAAAAD9b/HnAAAHlklEQVR4Ae3X3bWrVxQH8Oc+hJAQEgJJSCCEhJAQEkJC6CshhIRQQkIICSEh9JXQUkJCX0JfSUgICSEkJISEkBASQkIICSEhJPQ9zHfZzHo+5Em8z7kz65wzZ++Z9XzWzJqZ9Xg8/ve//326u7v78vT09On79+8/vn///vXr16fHx8fHp6enx8fHx8e7u7svd3d3X+7u7r58+/bt/v7+7v7+/v7p6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp极有可能由于内容过长被截断,我将分步创建页面组件。先创建基础结构,然后逐步完善。 +const imageFallback = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjQiIGhlaWdodD0iNjQiIHZpZXdCb3g9IjAgMCA2NCA2NCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjY0IiBoZWlnaHQ9IjY0IiBmaWxsPSIjRjVGNUY1Ii8+CjxwYXRoIGQ9Ik0zMiAyMEM0MC44MzY2IDIwIDQ4IDI3LjE2MzQgNDggMzZDNDggNDQuODM2NiA0MC44MzY2IDUyIDMyIDUyQzIzLjE2MzQgNTIgMTYgNDQuODM2NiAxNiAzNkMxNiAyNy4xNjM0IDIzLjE2MzQgMjAgMzIgMjBaIiBmaWxsPSIjRDlEOUQ5Ii8+Cjx0ZXh0IHg9IjMyIiB5PSI0MCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZm9udC1mYW1pbHk9IkFyaWFsIiBmb250LXNpemU9IjEyIiBmaWxsPSIjOTk5OTk5Ij7lm77niYc8L3RleHQ+Cjwvc3ZnPgo=' -const imageFallback = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMIAAADDCAYAAADQvc6UAAABRWlDQ1BJQ0MgUHJvZmlsZQAAKJFjYGASSSwoyGFhYGDIzSspCnJ3UoiIjFJgf8LAwSDCIMogwMCcmFxc4BgQ4ANUwgCjUcG3awyMIPqyLsis7PPOq3QdDFcvjV3jOD1boQVTPQrgSkktTgbSf4A4LbmgqISBgTEFyFYuLykAsTuAbJEioKOA7DkgdjqEvQHEToKwj4DVhAQ5A9k3gGyB5IxEoBmML4BsnSQk8XQkNtReEOBxcfXxUQg1Mjc0dyHgXNJBSWpFCYh2zi+oLMpMzyhRcASGUqqCZ16yno6CkYGRAQMDKMwhqj/fAIcloxgHQqxAjIHBEugw5sUIsSQpBobtQPdLciLEVJYzMPBHMDBsayhILEqEO4DxG0txmrERhM29nYGBddr//5/DGRjYNRkY/l7////39v///y4Dmn+LgeHANwDrkl1AuO+pmgAAADhlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAqACAAQAAAABAAAAwqADAAQAAAABAAAAwwAAAAD9b/HnAAAHlklEQVR4Ae3X3bWrVxQH8Oc+hJAQEgJJSCCEhJAQEkJC6CshhIRQQkIICSEh9JXQUkJCX0JfSUgICSEkJISEkBASQkIICSEhJPQ9zHfZzHo+5Em8z7kz65wzZ++Z9XzWzJqZ9Xg8/ve//326u7v78vT09On79+8/vn///vXr16fHx8fHp6enx8fHx8e7u7svd3d3X+7u7r58+/bt/v7+7v7+/v7p6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp6enp极有可能由于内容过长被截断,我将分步创建页面组件。先创建基础结构,然后逐步完善。 \ No newline at end of file +// 事件处理方法 +const handleSearch = () => { + console.log('搜索花卉:', searchForm) + // TODO: 实现搜索逻辑 +} + +const handleReset = () => { + searchForm.keyword = '' + searchForm.type = '' + searchForm.status = '' + console.log('重置搜索条件') + // TODO: 重新加载数据 +} + +const handleCreate = () => { + modalMode.value = 'create' + currentRecord.value = null + modalVisible.value = true +} + +const handleEdit = (record: FlowerRecord) => { + modalMode.value = 'edit' + currentRecord.value = record + modalVisible.value = true +} + +const handleView = (record: FlowerRecord) => { + modalMode.value = 'view' + currentRecord.value = record + modalVisible.value = true +} + +const handleDelete = async (id: number) => { + try { + // TODO: 调用删除API + console.log('删除花卉:', id) + message.success('删除成功') + } catch (error) { + message.error('删除失败') + } +} + +const handleExport = () => { + console.log('导出花卉数据') + // TODO: 实现导出功能 + message.info('导出功能开发中...') +} + +const handleModalCancel = () => { + modalVisible.value = false + currentRecord.value = null +} + +const handleModalSubmit = async (data: any) => { + try { + if (modalMode.value === 'create') { + // TODO: 调用创建API + console.log('创建花卉:', data) + message.success('创建成功') + } else if (modalMode.value === 'edit') { + // TODO: 调用更新API + console.log('更新花卉:', data) + message.success('更新成功') + } + modalVisible.value = false + currentRecord.value = null + // TODO: 重新加载数据 + } catch (error) { + message.error('操作失败') + } +} + +// 组件挂载时加载数据 +onMounted(() => { + // TODO: 加载花卉数据 + console.log('加载花卉数据') +}) + + + \ No newline at end of file diff --git a/admin-system/src/pages/merchant/index.vue b/admin-system/src/pages/merchant/index.vue index 4774a67..1236674 100644 --- a/admin-system/src/pages/merchant/index.vue +++ b/admin-system/src/pages/merchant/index.vue @@ -217,7 +217,7 @@