From 8e5295b572a98a57eea33cdc2bc6ffd89c59c09a Mon Sep 17 00:00:00 2001 From: ylweng Date: Sun, 31 Aug 2025 00:45:46 +0800 Subject: [PATCH] =?UTF-8?q?refactor(backend):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E5=8A=A8=E7=89=A9=E7=9B=B8=E5=85=B3=20API=20=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 更新了动物数据结构和相关类型定义 - 优化了动物列表、详情、创建、更新和删除接口 - 新增了更新动物状态接口 - 移除了与认领记录相关的接口 -调整了 API 响应结构 --- add_test_admin.js | 61 + admin-system/.env.development | 2 +- admin-system/index.html | 2 +- admin-system/src/App.vue | 2 +- admin-system/src/api/animal.ts | 135 +- admin-system/src/api/index.ts | 21 +- admin-system/src/api/merchant.ts | 113 +- admin-system/src/api/order.ts | 97 +- admin-system/src/api/promotion.ts | 80 +- admin-system/src/api/system.ts | 152 +- admin-system/src/api/travel.ts | 108 +- admin-system/src/api/user.ts | 124 +- admin-system/src/pages/Login.vue | 38 +- admin-system/src/pages/merchant/index.vue | 33 +- admin-system/src/pages/order/index.vue | 524 ++++-- admin-system/src/pages/user/index.vue | 51 +- admin-system/src/stores/app.ts | 153 +- admin-system/src/stores/index.ts | 16 +- admin-system/src/stores/modules/activity.ts | 249 +++ admin-system/src/stores/modules/animal.ts | 245 +++ admin-system/src/stores/modules/content.ts | 439 +++++ admin-system/src/stores/modules/merchant.ts | 232 +++ admin-system/src/stores/modules/order.ts | 223 +++ admin-system/src/stores/modules/permission.ts | 721 ++++++++ admin-system/src/stores/modules/stats.ts | 668 ++++++++ admin-system/src/stores/modules/user.ts | 162 ++ admin-system/src/types/activity.ts | 274 +++ admin-system/src/types/animal.ts | 231 +++ admin-system/src/types/content.ts | 313 ++++ admin-system/src/types/merchant.ts | 163 ++ admin-system/src/types/order.ts | 209 +++ admin-system/src/types/permission.ts | 402 +++++ admin-system/src/types/stats.ts | 488 ++++++ admin-system/src/types/user.ts | 130 ++ admin-system/vite.config.ts | 4 +- backend/.env | 8 +- backend/config/env.js | 6 +- backend/package-lock.json | 13 +- backend/package.json | 2 +- backend/src/app.js | 88 +- backend/src/config/database.js | 105 +- backend/src/controllers/admin/index.js | 225 +++ backend/src/controllers/animal/index.js | 166 ++ .../src/controllers/authControllerMySQL.js | 65 +- backend/src/controllers/order/index.js | 402 +++++ backend/src/controllers/travel/index.js | 152 ++ backend/src/controllers/user/index.js | 129 ++ backend/src/docs/swagger.js | 54 + backend/src/middleware/auth.js | 153 +- backend/src/models/UserMySQL.js | 70 +- backend/src/models/admin.js | 88 + backend/src/routes/admin.js | 327 ++++ backend/src/routes/animal.js | 533 ++++++ backend/src/routes/auth.js | 54 + backend/src/routes/order.js | 53 + backend/src/routes/travel.js | 434 +++++ backend/src/routes/user.js | 380 +++++ backend/src/server.js | 2 +- backend/src/services/admin/index.js | 158 ++ backend/src/services/animal/index.js | 262 +++ backend/src/services/order/index.js | 368 +++++ backend/src/services/travel/index.js | 206 +++ backend/src/services/user/index.js | 165 ++ check_table_structure.js | 60 + db_test.js | 137 ++ db_update.js | 85 + db_verify.js | 65 + docs/admin-design.md | 484 ++++++ docs/api-documentation.md | 1469 +++++++++++++++++ docs/architecture.md | 215 ++- docs/detailed_design.md | 160 ++ docs/development_plan.md | 56 +- docs/requirements.md | 159 +- init-database.js | 31 +- mini-program/api/config.js | 2 +- mini-program/pages/animal/detail.vue | 97 +- mini-program/pages/index/index.vue | 616 ++----- mini-program/pages/travel/detail.vue | 105 +- mini-program/pages/user/center.vue | 73 +- mini-program/pages/user/orders.vue | 444 ++--- .../.sourcemap/mp-weixin/api/config.js.map | 1 + .../.sourcemap/mp-weixin/api/request.js.map | 1 + .../.sourcemap/mp-weixin/api/services.js.map | 1 + .../dist/dev/mp-weixin/api/config.js | 78 + .../dist/dev/mp-weixin/api/request.js | 182 ++ .../dist/dev/mp-weixin/api/services.js | 18 + package-lock.json | 293 +++- package.json | 2 + test-mysql-connection.js | 112 +- test_admin_api.js | 77 + test_db_connection.js | 60 + website/about.html | 29 +- website/case.html | 27 +- website/contact.html | 23 +- website/css/style.css | 100 ++ website/images/ceo-avatar.svg | 11 + website/images/cmo-avatar.svg | 11 + website/images/coo-avatar.svg | 11 + website/images/cto-avatar.svg | 11 + website/images/farm-case.svg | 16 + website/images/flower-case.svg | 16 + website/images/merchant-avatar1.svg | 10 + website/images/team-photo.svg | 16 + website/images/travel-case.svg | 15 + website/images/user-avatar1.svg | 10 + website/images/user-avatar2.svg | 10 + website/index.html | 27 +- website/js/main.js | 237 +++ website/merchant/apply.html | 22 + website/merchant/index.html | 22 + website/merchant/policy.html | 22 + 111 files changed, 15290 insertions(+), 1972 deletions(-) create mode 100644 add_test_admin.js create mode 100644 admin-system/src/stores/modules/activity.ts create mode 100644 admin-system/src/stores/modules/animal.ts create mode 100644 admin-system/src/stores/modules/content.ts create mode 100644 admin-system/src/stores/modules/merchant.ts create mode 100644 admin-system/src/stores/modules/order.ts create mode 100644 admin-system/src/stores/modules/permission.ts create mode 100644 admin-system/src/stores/modules/stats.ts create mode 100644 admin-system/src/stores/modules/user.ts create mode 100644 admin-system/src/types/activity.ts create mode 100644 admin-system/src/types/animal.ts create mode 100644 admin-system/src/types/content.ts create mode 100644 admin-system/src/types/merchant.ts create mode 100644 admin-system/src/types/order.ts create mode 100644 admin-system/src/types/permission.ts create mode 100644 admin-system/src/types/stats.ts create mode 100644 admin-system/src/types/user.ts create mode 100644 backend/src/controllers/admin/index.js create mode 100644 backend/src/controllers/animal/index.js create mode 100644 backend/src/controllers/order/index.js create mode 100644 backend/src/controllers/travel/index.js create mode 100644 backend/src/controllers/user/index.js create mode 100644 backend/src/models/admin.js create mode 100644 backend/src/routes/admin.js create mode 100644 backend/src/routes/animal.js create mode 100644 backend/src/routes/order.js create mode 100644 backend/src/routes/travel.js create mode 100644 backend/src/routes/user.js create mode 100644 backend/src/services/admin/index.js create mode 100644 backend/src/services/animal/index.js create mode 100644 backend/src/services/order/index.js create mode 100644 backend/src/services/travel/index.js create mode 100644 backend/src/services/user/index.js create mode 100644 check_table_structure.js create mode 100644 db_test.js create mode 100644 db_update.js create mode 100644 db_verify.js create mode 100644 docs/admin-design.md create mode 100644 mini-program/unpackage/dist/dev/.sourcemap/mp-weixin/api/config.js.map create mode 100644 mini-program/unpackage/dist/dev/.sourcemap/mp-weixin/api/request.js.map create mode 100644 mini-program/unpackage/dist/dev/.sourcemap/mp-weixin/api/services.js.map create mode 100644 mini-program/unpackage/dist/dev/mp-weixin/api/config.js create mode 100644 mini-program/unpackage/dist/dev/mp-weixin/api/request.js create mode 100644 mini-program/unpackage/dist/dev/mp-weixin/api/services.js create mode 100644 test_admin_api.js create mode 100644 test_db_connection.js create mode 100644 website/images/ceo-avatar.svg create mode 100644 website/images/cmo-avatar.svg create mode 100644 website/images/coo-avatar.svg create mode 100644 website/images/cto-avatar.svg create mode 100644 website/images/farm-case.svg create mode 100644 website/images/flower-case.svg create mode 100644 website/images/merchant-avatar1.svg create mode 100644 website/images/team-photo.svg create mode 100644 website/images/travel-case.svg create mode 100644 website/images/user-avatar1.svg create mode 100644 website/images/user-avatar2.svg create mode 100644 website/js/main.js diff --git a/add_test_admin.js b/add_test_admin.js new file mode 100644 index 0000000..80148b1 --- /dev/null +++ b/add_test_admin.js @@ -0,0 +1,61 @@ +const bcrypt = require('bcryptjs'); +const { query } = require('./backend/src/config/database'); + +// 数据库配置 +const dbConfig = { + host: '129.211.213.226', + port: 9527, + user: 'root', + password: 'aiotAiot123!', + database: 'jiebandata' +}; + +async function addTestAdmin() { + try { + // 加密密码 + const saltRounds = 10; + const plainPassword = 'admin123'; + const hashedPassword = await bcrypt.hash(plainPassword, saltRounds); + + console.log('加密后的密码:', hashedPassword); + + // 插入测试管理员账户 + const insertSQL = ` + INSERT INTO admins (username, password, email, nickname, role) + VALUES (?, ?, ?, ?, ?) + ON DUPLICATE KEY UPDATE + password = VALUES(password), + email = VALUES(email), + nickname = VALUES(nickname), + role = VALUES(role) + `; + + const params = [ + 'testadmin', + hashedPassword, + 'testadmin@example.com', + '测试管理员', + 'admin' + ]; + + // 注意:这里我们需要直接使用mysql2连接数据库,因为backend/src/config/database可能依赖环境变量 + const mysql = require('mysql2/promise'); + const connection = await mysql.createConnection(dbConfig); + + const [result] = await connection.execute(insertSQL, params); + console.log('✅ 测试管理员账户创建/更新成功'); + console.log('受影响的行数:', result.affectedRows); + + // 验证插入的数据 + const [rows] = await connection.execute('SELECT * FROM admins WHERE username = ?', ['testadmin']); + console.log('\n插入的管理员信息:'); + console.log(rows[0]); + + await connection.end(); + } catch (error) { + console.error('❌ 创建测试管理员账户失败:', error.message); + console.error(error.stack); + } +} + +addTestAdmin(); \ No newline at end of file diff --git a/admin-system/.env.development b/admin-system/.env.development index eacef0f..a1b9d2a 100644 --- a/admin-system/.env.development +++ b/admin-system/.env.development @@ -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 # 功能开关 diff --git a/admin-system/index.html b/admin-system/index.html index 2dc8b3f..79e3534 100644 --- a/admin-system/index.html +++ b/admin-system/index.html @@ -15,7 +15,7 @@ - + diff --git a/admin-system/src/App.vue b/admin-system/src/App.vue index 262201f..bcfc90e 100644 --- a/admin-system/src/App.vue +++ b/admin-system/src/App.vue @@ -13,7 +13,7 @@ const appStore = useAppStore() onMounted(() => { // 初始化应用 - appStore.initializeApp() + appStore.initialize() // 开发环境调试信息 if (import.meta.env.DEV) { diff --git a/admin-system/src/api/animal.ts b/admin-system/src/api/animal.ts index 56852fe..4d7dc83 100644 --- a/admin-system/src/api/animal.ts +++ b/admin-system/src/api/animal.ts @@ -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 { - 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> => { - return request.get>('/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> => { - return request.get>(`/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): Promise> => { - return request.post>('/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): Promise> => { - return request.put>(`/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> => { - return request.delete>(`/animals/${id}`) -} +export const deleteAnimal = (id: number) => + request.delete<{ success: boolean; code: number; message: string }>(`/animals/${id}`) -// 获取认领记录列表 -export const getAnimalClaims = async (params?: ClaimQueryParams): Promise> => { - return request.get>('/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> => { - return request.post>(`/animals/claims/${id}/approve`) -} - -// 拒绝动物认领 -export const rejectAnimalClaim = async (id: number, reason: string): Promise> => { - return request.post>(`/animals/claims/${id}/reject`, { reason }) +export default { + getAnimals, + getAnimal, + createAnimal, + updateAnimal, + deleteAnimal, + updateAnimalStatus } \ No newline at end of file diff --git a/admin-system/src/api/index.ts b/admin-system/src/api/index.ts index ac4677e..5d05c18 100644 --- a/admin-system/src/api/index.ts +++ b/admin-system/src/api/index.ts @@ -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 \ No newline at end of file diff --git a/admin-system/src/api/merchant.ts b/admin-system/src/api/merchant.ts index c3865ad..43d37ed 100644 --- a/admin-system/src/api/merchant.ts +++ b/admin-system/src/api/merchant.ts @@ -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 { - 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> => { - return request.get>('/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> => { - return request.get>(`/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> => { - return request.post>(`/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> => { - return request.post>(`/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> => { - return request.post>(`/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> => { - return request.post>(`/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 } \ No newline at end of file diff --git a/admin-system/src/api/order.ts b/admin-system/src/api/order.ts index eb05929..cf79386 100644 --- a/admin-system/src/api/order.ts +++ b/admin-system/src/api/order.ts @@ -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 { } // 获取订单列表 -export const getOrders = async (params?: OrderQueryParams): Promise> => { - return request.get>('/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> => { - return request.get>(`/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> => { - return request.put>(`/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> => { - return request.post>(`/orders/${id}/ship`) -} - -// 完成订单 -export const completeOrder = async (id: number): Promise> => { - return request.post>(`/orders/${id}/complete`) -} - -// 取消订单 -export const cancelOrder = async (id: number): Promise> => { - return request.post>(`/orders/${id}/cancel`) -} - -// 退款 -export const refundOrder = async (id: number): Promise> => { - return request.post>(`/orders/${id}/refund`) -} - -// 获取订单统计数据 -export const getOrderStatistics = async (): Promise> => { - return request.get>('/orders/statistics') +export default { + getOrders, + getOrder, + updateOrder, + deleteOrder, + updateOrderStatus } \ No newline at end of file diff --git a/admin-system/src/api/promotion.ts b/admin-system/src/api/promotion.ts index cb16f62..818339c 100644 --- a/admin-system/src/api/promotion.ts +++ b/admin-system/src/api/promotion.ts @@ -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' diff --git a/admin-system/src/api/system.ts b/admin-system/src/api/system.ts index 4bd0571..6c14de9 100644 --- a/admin-system/src/api/system.ts +++ b/admin-system/src/api/system.ts @@ -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 { - success: boolean - code: number - message: string - data: T -} - // 获取系统服务列表 -export const getServices = async (): Promise> => { - return request.get>('/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> => { - return request.post>(`/system/services/${id}/start`) +export interface SystemConfigQueryParams { + page?: number + limit?: number + group?: string } -// 停止服务 -export const stopService = async (id: number): Promise> => { - return request.post>(`/system/services/${id}/stop`) +export interface SystemConfigUpdateData { + value: string } -// 获取系统信息 -export const getSystemInfo = async (): Promise> => { - return request.get>('/system/info') -} - -// 获取数据库状态 -export const getDatabaseStatus = async (): Promise> => { - return request.get>('/system/database') -} - -// 获取缓存状态 -export const getCacheStatus = async (): Promise> => { - return request.get>('/system/cache') -} - -// 获取系统配置 -export const getSystemSettings = async (): Promise> => { - return request.get>('/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> => { - return request.put>('/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> => { - return request.get>('/system/logs', { params }) -} +// 获取系统统计信息 +export const getSystemStats = () => + request.get<{ success: boolean; code: number; message: string; data: any }>('/system/stats') -// 清理缓存 -export const clearCache = async (): Promise> => { - return request.post>('/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> => { - return request.get>('/system/health') -} \ No newline at end of file +export default { + getServices, + updateServiceStatus, + getSystemConfigs, + updateSystemConfig, + getSystemStats, + getSystemLogs +} diff --git a/admin-system/src/api/travel.ts b/admin-system/src/api/travel.ts index 784116b..bfb4517 100644 --- a/admin-system/src/api/travel.ts +++ b/admin-system/src/api/travel.ts @@ -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 { - 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> => { - return request.get>('/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> => { - return request.get>(`/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> => { - return request.post>(`/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> => { - return request.post>(`/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> => { - return request.post>(`/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 } \ No newline at end of file diff --git a/admin-system/src/api/user.ts b/admin-system/src/api/user.ts index 3f6365f..080efdf 100644 --- a/admin-system/src/api/user.ts +++ b/admin-system/src/api/user.ts @@ -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 { +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 { success: boolean code: number message: string data: T - pagination?: { - current: number - pageSize: number - total: number - totalPages: number - } } // 获取用户列表 -export const getUsers = async (params?: UserQueryParams): Promise> => { - return request.get>('/users', { params }) -} +export const getUsers = (params?: UserQueryParams) => + request.get>('/users', { params }) // 获取用户详情 -export const getUser = async (id: number): Promise> => { - return request.get>(`/users/${id}`) -} +export const getUser = (id: number) => + request.get>(`/users/${id}`) // 创建用户 -export const createUser = async (userData: Partial): Promise> => { - return request.post>('/users', userData) -} +export const createUser = (data: UserCreateData) => + request.post>('/users', data) // 更新用户 -export const updateUser = async (id: number, userData: Partial): Promise> => { - return request.put>(`/users/${id}`, userData) -} +export const updateUser = (id: number, data: UserUpdateData) => + request.put>(`/users/${id}`, data) // 删除用户 -export const deleteUser = async (id: number): Promise> => { - return request.delete>(`/users/${id}`) -} +export const deleteUser = (id: number) => + request.delete>(`/users/${id}`) -// 批量操作用户 -export const batchUsers = async ( - ids: number[], - action: 'delete' | 'ban' | 'activate' -): Promise> => { - return request.post>('/users/batch', { ids, action }) +// 批量删除用户 +export const batchDeleteUsers = (ids: number[]) => + request.post>('/users/batch-delete', { ids }) + +// 更新用户状态 +export const updateUserStatus = (id: number, status: string) => + request.put>(`/users/${id}/status`, { status }) + +// 重置用户密码 +export const resetUserPassword = (id: number, password: string) => + request.put>(`/users/${id}/password`, { password }) + +export default { + getUsers, + getUser, + createUser, + updateUser, + deleteUser, + batchDeleteUsers, + updateUserStatus, + resetUserPassword } \ No newline at end of file diff --git a/admin-system/src/pages/Login.vue b/admin-system/src/pages/Login.vue index d307bcf..5052ece 100644 --- a/admin-system/src/pages/Login.vue +++ b/admin-system/src/pages/Login.vue @@ -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) { diff --git a/admin-system/src/pages/merchant/index.vue b/admin-system/src/pages/merchant/index.vue index 3c90228..97910e7 100644 --- a/admin-system/src/pages/merchant/index.vue +++ b/admin-system/src/pages/merchant/index.vue @@ -137,7 +137,7 @@ \ No newline at end of file diff --git a/admin-system/src/pages/user/index.vue b/admin-system/src/pages/user/index.vue index 9c4f0c3..89c9317 100644 --- a/admin-system/src/pages/user/index.vue +++ b/admin-system/src/pages/user/index.vue @@ -236,8 +236,8 @@ - \ No newline at end of file diff --git a/mini-program/pages/travel/detail.vue b/mini-program/pages/travel/detail.vue index 3767480..0b326ec 100644 --- a/mini-program/pages/travel/detail.vue +++ b/mini-program/pages/travel/detail.vue @@ -36,36 +36,69 @@ + + \ No newline at end of file diff --git a/website/case.html b/website/case.html index b525ff1..7fd1d9d 100644 --- a/website/case.html +++ b/website/case.html @@ -3,11 +3,17 @@ - 成功案例 - 结伴客 - + + + + + + + 成功案例 - 结伴客 -j + + @@ -63,7 +69,7 @@ j
- 用户案例1 + 旅行结伴案例
从陌生人到旅行伙伴
@@ -77,7 +83,7 @@ j
- 用户案例2 + 农场体验案例
难忘的农场体验
@@ -91,7 +97,7 @@ j
- 用户案例3 + 送花服务案例
浪漫的送花惊喜
@@ -283,6 +289,15 @@ j +
+ +
+
+ + + \ No newline at end of file diff --git a/website/contact.html b/website/contact.html index 7b1d1de..0bf8618 100644 --- a/website/contact.html +++ b/website/contact.html @@ -3,12 +3,18 @@ - 联系我们 - 结伴客 - - + + + + + + + 联系我们 - 结伴客 + - + + @@ -246,6 +252,15 @@
+ +
+
+ +
+
+ + + \ No newline at end of file diff --git a/website/css/style.css b/website/css/style.css index 0454eda..5ffff6a 100644 --- a/website/css/style.css +++ b/website/css/style.css @@ -838,6 +838,106 @@ body { color: white; } +/* 页面加载动画 */ +.page-loader { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: var(--primary-gradient); + display: flex; + align-items: center; + justify-content: center; + z-index: 9999; + transition: opacity 0.5s ease, visibility 0.5s ease; +} + +.page-loader.hidden { + opacity: 0; + visibility: hidden; +} + +.loader-spinner { + width: 80px; + height: 80px; + display: flex; + align-items: center; + justify-content: center; + background: rgba(255, 255, 255, 0.2); + border-radius: 50%; + animation: pulse 2s infinite; +} + +.loader-spinner i { + font-size: 2.5rem; + color: white; +} + +@keyframes pulse { + 0% { + transform: scale(1); + opacity: 1; + } + 50% { + transform: scale(1.1); + opacity: 0.8; + } + 100% { + transform: scale(1); + opacity: 1; + } +} + +/* 平滑滚动 */ +html { + scroll-behavior: smooth; +} + +/* 滚动进度条 */ +.scroll-progress { + position: fixed; + top: 0; + left: 0; + width: 0%; + height: 4px; + background: var(--primary-gradient); + z-index: 9998; + transition: width 0.3s ease; +} + +/* 返回顶部按钮 */ +.back-to-top { + position: fixed; + bottom: 30px; + right: 30px; + width: 50px; + height: 50px; + background: var(--primary-gradient); + color: white; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-size: 1.2rem; + cursor: pointer; + opacity: 0; + visibility: hidden; + transition: all 0.3s ease; + z-index: 9997; + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2); +} + +.back-to-top.visible { + opacity: 1; + visibility: visible; +} + +.back-to-top:hover { + transform: translateY(-5px); + box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3); +} + /* 响应式字体调整 */ @media (max-width: 768px) { .hero-section h1 { diff --git a/website/images/ceo-avatar.svg b/website/images/ceo-avatar.svg new file mode 100644 index 0000000..58de669 --- /dev/null +++ b/website/images/ceo-avatar.svg @@ -0,0 +1,11 @@ + + + + + + + + + + CEO + \ No newline at end of file diff --git a/website/images/cmo-avatar.svg b/website/images/cmo-avatar.svg new file mode 100644 index 0000000..e8911ff --- /dev/null +++ b/website/images/cmo-avatar.svg @@ -0,0 +1,11 @@ + + + + + + + + + + CMO + \ No newline at end of file diff --git a/website/images/coo-avatar.svg b/website/images/coo-avatar.svg new file mode 100644 index 0000000..3413e04 --- /dev/null +++ b/website/images/coo-avatar.svg @@ -0,0 +1,11 @@ + + + + + + + + + + COO + \ No newline at end of file diff --git a/website/images/cto-avatar.svg b/website/images/cto-avatar.svg new file mode 100644 index 0000000..052d8ee --- /dev/null +++ b/website/images/cto-avatar.svg @@ -0,0 +1,11 @@ + + + + + + + + + + CTO + \ No newline at end of file diff --git a/website/images/farm-case.svg b/website/images/farm-case.svg new file mode 100644 index 0000000..0943e46 --- /dev/null +++ b/website/images/farm-case.svg @@ -0,0 +1,16 @@ + + + + + + + + + + 农场体验 + 亲近自然,体验农耕 + + + + + \ No newline at end of file diff --git a/website/images/flower-case.svg b/website/images/flower-case.svg new file mode 100644 index 0000000..44ca40b --- /dev/null +++ b/website/images/flower-case.svg @@ -0,0 +1,16 @@ + + + + + + + + + + 送花服务 + 传递心意,送达祝福 + + + + + \ No newline at end of file diff --git a/website/images/merchant-avatar1.svg b/website/images/merchant-avatar1.svg new file mode 100644 index 0000000..c66a392 --- /dev/null +++ b/website/images/merchant-avatar1.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/website/images/team-photo.svg b/website/images/team-photo.svg new file mode 100644 index 0000000..766cac9 --- /dev/null +++ b/website/images/team-photo.svg @@ -0,0 +1,16 @@ + + + + + + + + + + 结伴客团队 + 让旅行不再孤单 + + + + + \ No newline at end of file diff --git a/website/images/travel-case.svg b/website/images/travel-case.svg new file mode 100644 index 0000000..ffa0b87 --- /dev/null +++ b/website/images/travel-case.svg @@ -0,0 +1,15 @@ + + + + + + + + + + 旅行结伴 + 探索世界,结识旅伴 + + + + \ No newline at end of file diff --git a/website/images/user-avatar1.svg b/website/images/user-avatar1.svg new file mode 100644 index 0000000..1cdac64 --- /dev/null +++ b/website/images/user-avatar1.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/website/images/user-avatar2.svg b/website/images/user-avatar2.svg new file mode 100644 index 0000000..6e13e66 --- /dev/null +++ b/website/images/user-avatar2.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/website/index.html b/website/index.html index 93bbdc9..30e609f 100644 --- a/website/index.html +++ b/website/index.html @@ -3,11 +3,17 @@ - 结伴客 - 旅行结伴与动物认领平台 - - + + + + + + + + 结伴客 - 旅行结伴平台 + @@ -112,7 +118,7 @@

通过结伴客,我找到了一起去西藏的伙伴,还认领了一只小羊,这是一次非常难忘的经历!

- 用户1 + 用户小李
小李
旅行爱好者 @@ -130,7 +136,7 @@

作为农场主,结伴客为我们带来了大量游客,动物认领业务增长了300%!

- 商家1 + 商家王老板
王老板
绿野农场 @@ -148,7 +154,7 @@

通过结伴客的送花服务,我给了她一个浪漫的惊喜,我们的关系更进一步了!

- 用户2 + 用户小张
小张
浪漫主义者 @@ -245,7 +251,16 @@
+ +
+
+ +
+
+ + + \ No newline at end of file diff --git a/website/js/main.js b/website/js/main.js new file mode 100644 index 0000000..4483c79 --- /dev/null +++ b/website/js/main.js @@ -0,0 +1,237 @@ +// 页面加载完成后执行 +document.addEventListener('DOMContentLoaded', function() { + // 初始化AOS动画库 + AOS.init({ + duration: 800, + easing: 'ease-in-out', + once: true, + offset: 100 + }); + + // 页面加载动画 + setTimeout(function() { + const loader = document.querySelector('.page-loader'); + if (loader) { + loader.classList.add('hidden'); + + // 动画完成后移除元素 + setTimeout(function() { + loader.style.display = 'none'; + }, 500); + } + }, 1500); + + // 创建滚动进度条 + createScrollProgress(); + + // 创建返回顶部按钮 + createBackToTopButton(); + + // 添加滚动事件监听 + window.addEventListener('scroll', handleScroll); + + // 初始化页面交互 + initPageInteractions(); +}); + +// 创建滚动进度条 +function createScrollProgress() { + const progressBar = document.createElement('div'); + progressBar.className = 'scroll-progress'; + document.body.appendChild(progressBar); +} + +// 创建返回顶部按钮 +function createBackToTopButton() { + const backToTopBtn = document.createElement('div'); + backToTopBtn.className = 'back-to-top'; + backToTopBtn.innerHTML = ''; + backToTopBtn.setAttribute('aria-label', '返回顶部'); + + backToTopBtn.addEventListener('click', function() { + window.scrollTo({ + top: 0, + behavior: 'smooth' + }); + }); + + document.body.appendChild(backToTopBtn); +} + +// 处理滚动事件 +function handleScroll() { + updateScrollProgress(); + toggleBackToTopButton(); +} + +// 更新滚动进度条 +function updateScrollProgress() { + const progressBar = document.querySelector('.scroll-progress'); + if (progressBar) { + const windowHeight = window.innerHeight; + const documentHeight = document.documentElement.scrollHeight - windowHeight; + const scrolled = (window.scrollY / documentHeight) * 100; + progressBar.style.width = scrolled + '%'; + } +} + +// 显示/隐藏返回顶部按钮 +function toggleBackToTopButton() { + const backToTopBtn = document.querySelector('.back-to-top'); + if (backToTopBtn) { + if (window.scrollY > 300) { + backToTopBtn.classList.add('visible'); + } else { + backToTopBtn.classList.remove('visible'); + } + } +} + +// 初始化页面交互 +function initPageInteractions() { + // 导航菜单点击效果 + initNavigation(); + + // 功能卡片悬停效果 + initFeatureCards(); + + // 用户评价卡片交互 + initTestimonialCards(); + + // 行动号召按钮点击效果 + initCallToAction(); +} + +// 导航菜单交互 +function initNavigation() { + const navLinks = document.querySelectorAll('.navbar-nav .nav-link'); + + navLinks.forEach(link => { + link.addEventListener('click', function(e) { + // 移除所有active类 + navLinks.forEach(l => l.classList.remove('active')); + + // 添加当前active类 + this.classList.add('active'); + + // 如果是锚点链接,平滑滚动 + const href = this.getAttribute('href'); + if (href && href.startsWith('#')) { + e.preventDefault(); + const target = document.querySelector(href); + if (target) { + target.scrollIntoView({ + behavior: 'smooth', + block: 'start' + }); + } + } + }); + }); +} + +// 功能卡片交互 +function initFeatureCards() { + const featureCards = document.querySelectorAll('.feature-box'); + + featureCards.forEach(card => { + card.addEventListener('mouseenter', function() { + this.style.transform = 'translateY(-10px)'; + this.style.boxShadow = '0 15px 30px rgba(0,0,0,0.15)'; + }); + + card.addEventListener('mouseleave', function() { + this.style.transform = 'translateY(0)'; + this.style.boxShadow = '0 5px 15px rgba(0,0,0,0.05)'; + }); + }); +} + +// 用户评价卡片交互 +function initTestimonialCards() { + const testimonialCards = document.querySelectorAll('.testimonial-card'); + + testimonialCards.forEach(card => { + card.addEventListener('mouseenter', function() { + this.style.transform = 'translateY(-5px)'; + this.style.boxShadow = '0 10px 25px rgba(0,0,0,0.1)'; + }); + + card.addEventListener('mouseleave', function() { + this.style.transform = 'translateY(0)'; + this.style.boxShadow = '0 5px 15px rgba(0,0,0,0.05)'; + }); + }); +} + +// 行动号召按钮交互 +function initCallToAction() { + const ctaButtons = document.querySelectorAll('.cta-section .btn, .hero-section .btn'); + + ctaButtons.forEach(btn => { + btn.addEventListener('mouseenter', function() { + this.style.transform = 'scale(1.05)'; + this.style.boxShadow = '0 8px 25px rgba(0,0,0,0.2)'; + }); + + btn.addEventListener('mouseleave', function() { + this.style.transform = 'scale(1)'; + this.style.boxShadow = 'none'; + }); + + btn.addEventListener('click', function(e) { + // 添加点击效果 + this.style.transform = 'scale(0.95)'; + setTimeout(() => { + this.style.transform = 'scale(1)'; + }, 150); + + // 如果是演示按钮,阻止默认行为 + if (this.getAttribute('href') === '#') { + e.preventDefault(); + alert('欢迎体验结伴客平台!此功能正在开发中,敬请期待。'); + } + }); + }); +} + +// 页面性能优化:图片懒加载 +function initLazyLoading() { + if ('IntersectionObserver' in window) { + const lazyImages = document.querySelectorAll('img[data-src]'); + + const imageObserver = new IntersectionObserver((entries, observer) => { + entries.forEach(entry => { + if (entry.isIntersecting) { + const img = entry.target; + img.src = img.getAttribute('data-src'); + img.removeAttribute('data-src'); + imageObserver.unobserve(img); + } + }); + }); + + lazyImages.forEach(img => { + imageObserver.observe(img); + }); + } +} + +// 页面可见性变化处理 +document.addEventListener('visibilitychange', function() { + if (document.hidden) { + console.log('页面被隐藏'); + } else { + console.log('页面恢复显示'); + } +}); + +// 错误处理 +window.addEventListener('error', function(e) { + console.error('页面错误:', e.error); +}); + +// 页面卸载前清理 +window.addEventListener('beforeunload', function() { + // 清理操作 +}); \ No newline at end of file diff --git a/website/merchant/apply.html b/website/merchant/apply.html index 58707f0..51cc2c2 100644 --- a/website/merchant/apply.html +++ b/website/merchant/apply.html @@ -6,11 +6,23 @@ 商家入驻申请 - 结伴客 + + + + + + + +
+
+ Loading... +
+
+ +
+ + + +
@@ -53,6 +73,8 @@
+ +
diff --git a/website/merchant/index.html b/website/merchant/index.html index 516677f..a914ebc 100644 --- a/website/merchant/index.html +++ b/website/merchant/index.html @@ -6,11 +6,23 @@ 商家合作 - 结伴客 + + + + + + + +
+
+ Loading... +
+
+ +
+ + + +
@@ -53,6 +73,8 @@
+ +
diff --git a/website/merchant/policy.html b/website/merchant/policy.html index 62be59e..6e72b53 100644 --- a/website/merchant/policy.html +++ b/website/merchant/policy.html @@ -6,11 +6,23 @@ 合作政策 - 结伴客 + + + + + + + +
+
+ Loading... +
+
+ +
+ + + +
@@ -155,6 +175,8 @@
+ +