homepage.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. /**
  2. * 首页数据接口服务
  3. *
  4. * 注意:目前使用模拟数据,后端接口开发完成后需要替换
  5. *
  6. * 替换步骤:
  7. * 1. 将 import 模拟数据改为真实的网络请求
  8. * 2. 修改返回的 Promise 为实际的 uni.request 调用
  9. * 3. 添加错误处理和网络异常处理
  10. * 4. 调整数据结构映射(如果后端返回结构与前端需要的不一致)
  11. */
  12. import {
  13. MOCK_HOMEPAGE_DATA,
  14. MOCK_BANNER_CONFIG,
  15. MOCK_CATEGORIES,
  16. MOCK_PRODUCTS,
  17. MOCK_ASSETS,
  18. API_ENDPOINTS
  19. } from '@/mock/mockData.js'
  20. /**
  21. * 获取首页数据
  22. * TODO: 替换为真实API调用
  23. *
  24. * 真实接口示例:
  25. * export const getHomepageData = () => {
  26. * return uni.request({
  27. * url: API_ENDPOINTS.HOMEPAGE,
  28. * method: 'GET',
  29. * header: {
  30. * 'Authorization': 'Bearer ' + getToken()
  31. * }
  32. * })
  33. * }
  34. */
  35. export const getHomepageData = () => {
  36. return new Promise((resolve) => {
  37. // 模拟网络延迟
  38. setTimeout(() => {
  39. console.log('📡 [API调用] 获取首页数据 - 当前为模拟数据')
  40. resolve(MOCK_HOMEPAGE_DATA)
  41. }, 300)
  42. })
  43. }
  44. /**
  45. * 获取轮播图配置
  46. * TODO: 替换为真实API调用
  47. */
  48. export const getBannerConfig = () => {
  49. return new Promise((resolve) => {
  50. setTimeout(() => {
  51. console.log('📡 [API调用] 获取轮播图配置 - 当前为模拟数据')
  52. // 组合轮播图数据和素材URL
  53. const banners = MOCK_BANNER_CONFIG.data.banners.map(banner => ({
  54. ...banner,
  55. imageUrl: MOCK_ASSETS.banners[banner.assetId]
  56. }))
  57. resolve({
  58. success: true,
  59. data: { banners }
  60. })
  61. }, 200)
  62. })
  63. }
  64. /**
  65. * 获取商品分类数据
  66. * TODO: 替换为真实API调用
  67. */
  68. export const getCategories = () => {
  69. return new Promise((resolve) => {
  70. setTimeout(() => {
  71. console.log('📡 [API调用] 获取商品分类 - 当前为模拟数据')
  72. resolve(MOCK_CATEGORIES)
  73. }, 150)
  74. })
  75. }
  76. /**
  77. * 获取分类下的商品列表
  78. * TODO: 替换为真实API调用
  79. *
  80. * @param {string} categoryId - 分类ID
  81. * @param {number} page - 页码
  82. * @param {number} limit - 每页数量
  83. */
  84. export const getCategoryProducts = (categoryId, page = 1, limit = 3) => {
  85. return new Promise((resolve) => {
  86. setTimeout(() => {
  87. console.log(`📡 [API调用] 获取分类商品 - categoryId: ${categoryId}, 当前为模拟数据`)
  88. // 过滤并组合商品数据
  89. const products = MOCK_PRODUCTS.data.products
  90. .filter(product => product.categoryId === categoryId && product.status === 1)
  91. .sort((a, b) => a.sort - b.sort)
  92. .slice((page - 1) * limit, page * limit)
  93. .map(product => ({
  94. ...product,
  95. imageUrl: MOCK_ASSETS.products[product.assetId]
  96. }))
  97. resolve({
  98. success: true,
  99. data: {
  100. products,
  101. pagination: {
  102. page,
  103. limit,
  104. total: MOCK_PRODUCTS.data.products.filter(p => p.categoryId === categoryId).length
  105. }
  106. }
  107. })
  108. }, 200)
  109. })
  110. }
  111. /**
  112. * 获取商品详情
  113. * TODO: 替换为真实API调用
  114. *
  115. * @param {string} productId - 商品ID
  116. */
  117. export const getProductDetail = (productId) => {
  118. return new Promise((resolve, reject) => {
  119. setTimeout(() => {
  120. console.log(`📡 [API调用] 获取商品详情 - productId: ${productId}, 当前为模拟数据`)
  121. const product = MOCK_PRODUCTS.data.products.find(p => p.id === productId)
  122. if (product) {
  123. resolve({
  124. success: true,
  125. data: {
  126. ...product,
  127. imageUrl: MOCK_ASSETS.products[product.assetId]
  128. }
  129. })
  130. } else {
  131. reject({
  132. success: false,
  133. message: '商品不存在'
  134. })
  135. }
  136. }, 250)
  137. })
  138. }
  139. /**
  140. * 获取素材资源URL
  141. * TODO: 替换为真实API调用
  142. *
  143. * @param {string} assetId - 素材ID
  144. * @param {string} type - 素材类型 banners/products
  145. */
  146. export const getAssetUrl = (assetId, type = 'products') => {
  147. return new Promise((resolve) => {
  148. setTimeout(() => {
  149. console.log(`📡 [API调用] 获取素材URL - assetId: ${assetId}, type: ${type}, 当前为模拟数据`)
  150. const url = MOCK_ASSETS[type] && MOCK_ASSETS[type][assetId]
  151. ? MOCK_ASSETS[type][assetId]
  152. : null
  153. resolve({
  154. success: !!url,
  155. data: { url }
  156. })
  157. }, 100)
  158. })
  159. }
  160. /**
  161. * 搜索商品
  162. * TODO: 替换为真实API调用
  163. *
  164. * @param {string} keyword - 搜索关键词
  165. * @param {number} page - 页码
  166. * @param {number} limit - 每页数量
  167. */
  168. export const searchProducts = (keyword, page = 1, limit = 10) => {
  169. return new Promise((resolve) => {
  170. setTimeout(() => {
  171. console.log(`📡 [API调用] 搜索商品 - keyword: ${keyword}, 当前为模拟数据`)
  172. // 模拟搜索逻辑
  173. const products = MOCK_PRODUCTS.data.products
  174. .filter(product =>
  175. product.status === 1 &&
  176. product.name.toLowerCase().includes(keyword.toLowerCase())
  177. )
  178. .slice((page - 1) * limit, page * limit)
  179. .map(product => ({
  180. ...product,
  181. imageUrl: MOCK_ASSETS.products[product.assetId]
  182. }))
  183. resolve({
  184. success: true,
  185. data: {
  186. products,
  187. keyword,
  188. pagination: {
  189. page,
  190. limit,
  191. total: MOCK_PRODUCTS.data.products.filter(p =>
  192. p.status === 1 && p.name.toLowerCase().includes(keyword.toLowerCase())
  193. ).length
  194. }
  195. }
  196. })
  197. }, 400)
  198. })
  199. }
  200. /**
  201. * 通用错误处理
  202. * TODO: 根据实际后端错误码进行调整
  203. */
  204. export const handleApiError = (error) => {
  205. console.error('API请求错误:', error)
  206. // 模拟错误处理逻辑
  207. if (error.statusCode) {
  208. switch (error.statusCode) {
  209. case 401:
  210. uni.showToast({ title: '请先登录', icon: 'none' })
  211. // 跳转到登录页
  212. break
  213. case 403:
  214. uni.showToast({ title: '权限不足', icon: 'none' })
  215. break
  216. case 404:
  217. uni.showToast({ title: '请求的资源不存在', icon: 'none' })
  218. break
  219. case 500:
  220. uni.showToast({ title: '服务器错误', icon: 'none' })
  221. break
  222. default:
  223. uni.showToast({ title: '网络错误,请稍后重试', icon: 'none' })
  224. }
  225. } else {
  226. uni.showToast({ title: '网络连接失败', icon: 'none' })
  227. }
  228. }