初始化参股
This commit is contained in:
57
前端/utils/api-test.uts
Normal file
57
前端/utils/api-test.uts
Normal file
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* API测试文件 - 测试前后端对接
|
||||
*/
|
||||
import { getCaseList, getBanners, getActiveServices } from '@/api/index.uts'
|
||||
|
||||
// 测试案例列表API
|
||||
export const testCaseListAPI = async () => {
|
||||
try {
|
||||
console.log('测试案例列表API...')
|
||||
const res = await getCaseList()
|
||||
console.log('案例列表API响应:', res)
|
||||
return res
|
||||
} catch (error) {
|
||||
console.error('案例列表API错误:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
// 测试轮播图API
|
||||
export const testBannersAPI = async () => {
|
||||
try {
|
||||
console.log('测试轮播图API...')
|
||||
const res = await getBanners()
|
||||
console.log('轮播图API响应:', res)
|
||||
return res
|
||||
} catch (error) {
|
||||
console.error('轮播图API错误:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
// 测试服务列表API
|
||||
export const testServicesAPI = async () => {
|
||||
try {
|
||||
console.log('测试服务列表API...')
|
||||
const res = await getActiveServices()
|
||||
console.log('服务列表API响应:', res)
|
||||
return res
|
||||
} catch (error) {
|
||||
console.error('服务列表API错误:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
// 运行所有测试
|
||||
export const runAllTests = async () => {
|
||||
console.log('开始API对接测试...')
|
||||
|
||||
try {
|
||||
await testBannersAPI()
|
||||
await testCaseListAPI()
|
||||
await testServicesAPI()
|
||||
console.log('所有API测试完成!')
|
||||
} catch (error) {
|
||||
console.error('API测试失败:', error)
|
||||
}
|
||||
}
|
||||
73
前端/utils/config.uts
Normal file
73
前端/utils/config.uts
Normal file
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* 项目配置文件
|
||||
*/
|
||||
|
||||
// 环境配置
|
||||
export const ENV = {
|
||||
// 开发环境
|
||||
development: {
|
||||
baseUrl: 'http://localhost:3000/api',
|
||||
imageBaseUrl: 'http://localhost:3000'
|
||||
},
|
||||
// 生产环境
|
||||
production: {
|
||||
baseUrl: 'https://api.youyijia.com/api',
|
||||
imageBaseUrl: 'https://api.youyijia.com'
|
||||
}
|
||||
}
|
||||
|
||||
// 当前环境 - 切换为 'production' 上线
|
||||
export const currentEnv = 'development'
|
||||
|
||||
// 获取当前环境配置
|
||||
export const getEnvConfig = () : UTSJSONObject => {
|
||||
if (currentEnv == 'production') {
|
||||
return {
|
||||
baseUrl: ENV.production.baseUrl,
|
||||
imageBaseUrl: ENV.production.imageBaseUrl
|
||||
} as UTSJSONObject
|
||||
}
|
||||
return {
|
||||
baseUrl: ENV.development.baseUrl,
|
||||
imageBaseUrl: ENV.development.imageBaseUrl
|
||||
} as UTSJSONObject
|
||||
}
|
||||
|
||||
// 是否使用Mock数据 - 已关闭,对接真实后端
|
||||
export const useMock = false
|
||||
|
||||
// 分页配置
|
||||
export const PAGE_SIZE = 10
|
||||
|
||||
// 图片上传配置
|
||||
export const UPLOAD_CONFIG = {
|
||||
maxSize: 5 * 1024 * 1024, // 5MB
|
||||
maxCount: 9,
|
||||
accept: ['image/jpeg', 'image/png', 'image/gif']
|
||||
}
|
||||
|
||||
// 缓存Key
|
||||
export const STORAGE_KEYS = {
|
||||
TOKEN: 'user_token',
|
||||
USER_INFO: 'user_info',
|
||||
FAVORITES: 'user_favorites',
|
||||
SEARCH_HISTORY: 'search_history'
|
||||
}
|
||||
|
||||
// 沙发分类
|
||||
export const SOFA_CATEGORIES = [
|
||||
{ id: 'all', name: '全部' },
|
||||
{ id: 'leather', name: '皮沙发' },
|
||||
{ id: 'fabric', name: '布艺沙发' },
|
||||
{ id: 'functional', name: '功能沙发' },
|
||||
{ id: 'antique', name: '古典沙发' },
|
||||
{ id: 'office', name: '办公沙发' }
|
||||
]
|
||||
|
||||
// 翻新服务类型
|
||||
export const SERVICE_TYPES = [
|
||||
{ id: 'repair', name: '局部修复', icon: '/static/icons/repair.png' },
|
||||
{ id: 'recolor', name: '改色翻新', icon: '/static/icons/recolor.png' },
|
||||
{ id: 'refurbish', name: '整体翻新', icon: '/static/icons/refurbish.png' },
|
||||
{ id: 'custom', name: '定制换皮', icon: '/static/icons/custom.png' }
|
||||
]
|
||||
249
前端/utils/mock.uts
Normal file
249
前端/utils/mock.uts
Normal file
@@ -0,0 +1,249 @@
|
||||
/**
|
||||
* Mock数据 - 开发阶段使用
|
||||
* 后端开发完成后可关闭
|
||||
*/
|
||||
|
||||
// 轮播图数据
|
||||
const bannerList = [
|
||||
{
|
||||
id: '1',
|
||||
image: '/static/mock/banner1.svg',
|
||||
title: '专业沙发翻新服务',
|
||||
link: '/pages/service/index'
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
image: '/static/mock/banner2.svg',
|
||||
title: '十年品质保证',
|
||||
link: '/pages/about/index'
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
image: '/static/mock/banner3.svg',
|
||||
title: '免费上门评估',
|
||||
link: '/pages/booking/index'
|
||||
}
|
||||
]
|
||||
|
||||
// 案例数据
|
||||
const caseList = [
|
||||
{
|
||||
id: '1',
|
||||
title: '欧式真皮沙发翻新',
|
||||
category: 'leather',
|
||||
categoryName: '皮沙发',
|
||||
beforeImages: ['/static/mock/case1-before.svg'],
|
||||
afterImages: ['/static/mock/case1-after.svg'],
|
||||
coverImage: '/static/mock/case1-after.svg',
|
||||
description: '这款欧式真皮沙发使用多年后出现皮面老化、褪色问题,经过我们专业的翻新处理,焕然一新。采用进口头层牛皮,色泽均匀,手感细腻。',
|
||||
material: '进口头层牛皮',
|
||||
duration: '7天',
|
||||
price: '¥3800',
|
||||
views: 1256,
|
||||
likes: 89,
|
||||
createTime: '2026-01-15'
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
title: '现代简约布艺沙发翻新',
|
||||
category: 'fabric',
|
||||
categoryName: '布艺沙发',
|
||||
beforeImages: ['/static/mock/case2-before.svg'],
|
||||
afterImages: ['/static/mock/case2-after.svg'],
|
||||
coverImage: '/static/mock/case2-after.svg',
|
||||
description: '布艺沙发使用时间长了容易脏污、起球,这款沙发经过整体换布处理,选用高品质科技布,防水防污,易于打理。',
|
||||
material: '高品质科技布',
|
||||
duration: '5天',
|
||||
price: '¥2200',
|
||||
views: 986,
|
||||
likes: 67,
|
||||
createTime: '2026-01-12'
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
title: '美式复古沙发改色翻新',
|
||||
category: 'leather',
|
||||
categoryName: '皮沙发',
|
||||
beforeImages: ['/static/mock/case3-before.svg'],
|
||||
afterImages: ['/static/mock/case3-after.svg'],
|
||||
coverImage: '/static/mock/case3-after.svg',
|
||||
description: '客户希望将原本深棕色的沙发改为更现代的米白色,我们采用专业改色工艺,色泽持久不脱落,触感保持柔软。',
|
||||
material: '专业皮革改色',
|
||||
duration: '6天',
|
||||
price: '¥2800',
|
||||
views: 756,
|
||||
likes: 45,
|
||||
createTime: '2026-01-10'
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
title: '功能沙发维修翻新',
|
||||
category: 'functional',
|
||||
categoryName: '功能沙发',
|
||||
beforeImages: ['/static/mock/case4-before.svg'],
|
||||
afterImages: ['/static/mock/case4-after.svg'],
|
||||
coverImage: '/static/mock/case4-after.svg',
|
||||
description: '功能沙发的电动机构出现故障,同时皮面也有磨损。我们更换了电机和控制系统,并对皮面进行了局部修复。',
|
||||
material: '原装配件+局部修复',
|
||||
duration: '4天',
|
||||
price: '¥1800',
|
||||
views: 623,
|
||||
likes: 38,
|
||||
createTime: '2026-01-08'
|
||||
},
|
||||
{
|
||||
id: '5',
|
||||
title: '中式红木沙发垫翻新',
|
||||
category: 'antique',
|
||||
categoryName: '古典沙发',
|
||||
beforeImages: ['/static/mock/case5-before.svg'],
|
||||
afterImages: ['/static/mock/case5-after.svg'],
|
||||
coverImage: '/static/mock/case5-after.svg',
|
||||
description: '红木沙发的坐垫和靠垫使用多年已经塌陷变形,我们重新填充高密度海绵,并更换了丝绸面料,古典韵味十足。',
|
||||
material: '高密度海绵+丝绸面料',
|
||||
duration: '5天',
|
||||
price: '¥2500',
|
||||
views: 512,
|
||||
likes: 32,
|
||||
createTime: '2026-01-05'
|
||||
},
|
||||
{
|
||||
id: '6',
|
||||
title: '办公室皮沙发组合翻新',
|
||||
category: 'office',
|
||||
categoryName: '办公沙发',
|
||||
beforeImages: ['/static/mock/case6-before.svg'],
|
||||
afterImages: ['/static/mock/case6-after.svg'],
|
||||
coverImage: '/static/mock/case6-after.svg',
|
||||
description: '企业办公室的沙发组合整体翻新,包括一套3+1+1沙发。采用耐磨商务皮革,简约大气,提升企业形象。',
|
||||
material: '商务耐磨皮革',
|
||||
duration: '10天',
|
||||
price: '¥8800',
|
||||
views: 445,
|
||||
likes: 28,
|
||||
createTime: '2026-01-02'
|
||||
}
|
||||
]
|
||||
|
||||
// 服务流程数据
|
||||
const serviceProcess = [
|
||||
{
|
||||
step: 1,
|
||||
title: '在线预约',
|
||||
description: '通过小程序或电话预约上门服务',
|
||||
icon: '/static/icons/step1.png'
|
||||
},
|
||||
{
|
||||
step: 2,
|
||||
title: '上门评估',
|
||||
description: '专业师傅免费上门查看沙发状况',
|
||||
icon: '/static/icons/step2.png'
|
||||
},
|
||||
{
|
||||
step: 3,
|
||||
title: '方案报价',
|
||||
description: '根据沙发情况提供翻新方案和报价',
|
||||
icon: '/static/icons/step3.png'
|
||||
},
|
||||
{
|
||||
step: 4,
|
||||
title: '确认订单',
|
||||
description: '确认方案后签订服务合同',
|
||||
icon: '/static/icons/step4.png'
|
||||
},
|
||||
{
|
||||
step: 5,
|
||||
title: '专业翻新',
|
||||
description: '工厂或上门进行专业翻新作业',
|
||||
icon: '/static/icons/step5.png'
|
||||
},
|
||||
{
|
||||
step: 6,
|
||||
title: '验收交付',
|
||||
description: '翻新完成后客户验收,满意付款',
|
||||
icon: '/static/icons/step6.png'
|
||||
}
|
||||
]
|
||||
|
||||
// 公司信息
|
||||
const companyInfo = {
|
||||
name: '优艺家沙发翻新',
|
||||
slogan: '让旧沙发焕发新生',
|
||||
description: '优艺家是一家专业从事沙发翻新、维修、改色的服务公司,拥有十余年行业经验。我们秉承"品质至上、客户第一"的服务理念,为千家万户提供专业的沙发翻新服务。',
|
||||
phone: '400-888-8888',
|
||||
wechat: 'youyijia2026',
|
||||
address: '上海市浦东新区张江高科技园区',
|
||||
workTime: '周一至周日 9:00-18:00',
|
||||
features: [
|
||||
{ title: '专业团队', desc: '10年+从业经验' },
|
||||
{ title: '品质保证', desc: '质保期内免费维护' },
|
||||
{ title: '上门服务', desc: '免费上门评估' },
|
||||
{ title: '价格透明', desc: '无隐形消费' }
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Mock数据
|
||||
*/
|
||||
export const getMockData = (url : string, method : string, params ?: UTSJSONObject | null) : any | null => {
|
||||
// 轮播图
|
||||
if (url == '/banners') {
|
||||
return bannerList
|
||||
}
|
||||
|
||||
// 案例列表
|
||||
if (url == '/cases' && method == 'GET') {
|
||||
const category = params?.['category'] as string | null
|
||||
const page = (params?.['page'] ?? 1) as number
|
||||
const pageSize = (params?.['pageSize'] ?? 10) as number
|
||||
|
||||
let filteredList = caseList
|
||||
if (category != null && category != '' && category != 'all') {
|
||||
filteredList = caseList.filter((item) : boolean => item.category == category)
|
||||
}
|
||||
|
||||
const start = (page - 1) * pageSize
|
||||
const end = start + pageSize
|
||||
const list = filteredList.slice(start, end)
|
||||
|
||||
return {
|
||||
list: list,
|
||||
total: filteredList.length,
|
||||
page: page,
|
||||
pageSize: pageSize
|
||||
}
|
||||
}
|
||||
|
||||
// 案例详情
|
||||
if (url.startsWith('/cases/') && method == 'GET') {
|
||||
const id = url.replace('/cases/', '')
|
||||
const caseItem = caseList.find((item) : boolean => item.id == id)
|
||||
return caseItem
|
||||
}
|
||||
|
||||
// 热门案例
|
||||
if (url == '/cases/hot') {
|
||||
return caseList.slice(0, 4)
|
||||
}
|
||||
|
||||
// 服务流程
|
||||
if (url == '/service/process') {
|
||||
return serviceProcess
|
||||
}
|
||||
|
||||
// 公司信息
|
||||
if (url == '/company/info') {
|
||||
return companyInfo
|
||||
}
|
||||
|
||||
// 提交预约
|
||||
if (url == '/booking' && method == 'POST') {
|
||||
return {
|
||||
bookingId: 'BK' + Date.now().toString(),
|
||||
status: 'pending',
|
||||
message: '预约成功,我们会尽快与您联系'
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
174
前端/utils/request.uts
Normal file
174
前端/utils/request.uts
Normal file
@@ -0,0 +1,174 @@
|
||||
/**
|
||||
* 网络请求封装
|
||||
* 预留后端接口对接
|
||||
*/
|
||||
import { getEnvConfig, useMock, STORAGE_KEYS } from './config.uts'
|
||||
import { getMockData } from './mock.uts'
|
||||
|
||||
// 请求配置类型
|
||||
type RequestOptions = {
|
||||
url : string
|
||||
method ?: 'GET' | 'POST' | 'PUT' | 'DELETE'
|
||||
data ?: UTSJSONObject | null
|
||||
header ?: UTSJSONObject | null
|
||||
showLoading ?: boolean
|
||||
loadingText ?: string
|
||||
}
|
||||
|
||||
// 响应数据类型
|
||||
type ResponseData = {
|
||||
code : number
|
||||
message : string
|
||||
data : any
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求拦截器
|
||||
*/
|
||||
const requestInterceptor = (options : RequestOptions) : RequestOptions => {
|
||||
// 添加token
|
||||
const token = uni.getStorageSync(STORAGE_KEYS.TOKEN) as string
|
||||
if (token != '') {
|
||||
if (options.header == null) {
|
||||
options.header = {} as UTSJSONObject
|
||||
}
|
||||
options.header!['Authorization'] = `Bearer ${token}`
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
/**
|
||||
* 响应拦截器
|
||||
*/
|
||||
const responseInterceptor = (response : UTSJSONObject) : ResponseData => {
|
||||
const statusCode = response['statusCode'] as number
|
||||
const data = response['data'] as UTSJSONObject
|
||||
|
||||
if (statusCode == 200) {
|
||||
const code = (data['code'] ?? 0) as number
|
||||
if (code == 0 || code == 200) {
|
||||
return {
|
||||
code: 0,
|
||||
message: 'success',
|
||||
data: data['data']
|
||||
} as ResponseData
|
||||
} else if (code == 401) {
|
||||
// token过期,跳转登录
|
||||
uni.removeStorageSync(STORAGE_KEYS.TOKEN)
|
||||
uni.showToast({
|
||||
title: '请重新登录',
|
||||
icon: 'none'
|
||||
})
|
||||
return {
|
||||
code: code,
|
||||
message: (data['message'] ?? '请重新登录') as string,
|
||||
data: null
|
||||
} as ResponseData
|
||||
} else {
|
||||
return {
|
||||
code: code,
|
||||
message: (data['message'] ?? '请求失败') as string,
|
||||
data: null
|
||||
} as ResponseData
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
code: statusCode,
|
||||
message: '网络请求失败',
|
||||
data: null
|
||||
} as ResponseData
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一请求方法
|
||||
*/
|
||||
export const request = (options : RequestOptions) : Promise<ResponseData> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
// 使用Mock数据
|
||||
if (useMock) {
|
||||
const mockData = getMockData(options.url, options.method ?? 'GET', options.data)
|
||||
if (mockData != null) {
|
||||
setTimeout(() => {
|
||||
resolve({
|
||||
code: 0,
|
||||
message: 'success',
|
||||
data: mockData
|
||||
} as ResponseData)
|
||||
}, 300) // 模拟网络延迟
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 请求拦截
|
||||
const finalOptions = requestInterceptor(options)
|
||||
|
||||
// 显示loading
|
||||
if (finalOptions.showLoading == true) {
|
||||
uni.showLoading({
|
||||
title: finalOptions.loadingText ?? '加载中...'
|
||||
})
|
||||
}
|
||||
|
||||
const config = getEnvConfig()
|
||||
const baseUrl = config['baseUrl'] as string
|
||||
|
||||
uni.request({
|
||||
url: baseUrl + finalOptions.url,
|
||||
method: finalOptions.method ?? 'GET',
|
||||
data: finalOptions.data as UTSJSONObject | null,
|
||||
header: finalOptions.header as UTSJSONObject | null,
|
||||
success: (res) => {
|
||||
if (finalOptions.showLoading == true) {
|
||||
uni.hideLoading()
|
||||
}
|
||||
const result = responseInterceptor(res as UTSJSONObject)
|
||||
if (result.code == 0) {
|
||||
resolve(result)
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: result.message,
|
||||
icon: 'none'
|
||||
})
|
||||
reject(result)
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
if (finalOptions.showLoading == true) {
|
||||
uni.hideLoading()
|
||||
}
|
||||
uni.showToast({
|
||||
title: '网络连接失败',
|
||||
icon: 'none'
|
||||
})
|
||||
reject({
|
||||
code: -1,
|
||||
message: '网络连接失败',
|
||||
data: null
|
||||
} as ResponseData)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* GET请求
|
||||
*/
|
||||
export const get = (url : string, data ?: UTSJSONObject | null) : Promise<ResponseData> => {
|
||||
return request({
|
||||
url: url,
|
||||
method: 'GET',
|
||||
data: data
|
||||
} as RequestOptions)
|
||||
}
|
||||
|
||||
/**
|
||||
* POST请求
|
||||
*/
|
||||
export const post = (url : string, data ?: UTSJSONObject | null) : Promise<ResponseData> => {
|
||||
return request({
|
||||
url: url,
|
||||
method: 'POST',
|
||||
data: data
|
||||
} as RequestOptions)
|
||||
}
|
||||
Reference in New Issue
Block a user