product.js 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. /**
  2. * 商品相关API服务
  3. * 模拟后台接口,便于未来替换为真实API
  4. */
  5. import { MOCK_PRODUCTS, MOCK_ASSETS } from '@/mock/mockData.js'
  6. // 模拟网络延迟
  7. const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms))
  8. /**
  9. * 获取商品详情
  10. * @param {string} productId 商品ID
  11. * @returns {Promise} 商品详情数据
  12. */
  13. export const getProductDetail = async (productId) => {
  14. await delay(600) // 模拟网络延迟
  15. console.log('模拟API: 获取商品详情', productId)
  16. try {
  17. // 从模拟数据中查找商品
  18. const product = MOCK_PRODUCTS.data.products.find(p => p.id === productId)
  19. if (!product) {
  20. return {
  21. success: false,
  22. message: '商品不存在',
  23. data: null
  24. }
  25. }
  26. // 构建商品详情数据
  27. const productDetail = {
  28. id: product.id,
  29. name: product.name,
  30. price: Math.floor(Math.random() * 1000) + 200, // 模拟价格 200-1200
  31. points: Math.floor(Math.random() * 500) + 100, // 模拟积分 100-600
  32. mainImage: MOCK_ASSETS.products[product.assetId] || '',
  33. packageImage: MOCK_ASSETS.products[product.assetId] || '', // 包装图片
  34. qualityImage: MOCK_ASSETS.products[product.assetId] || '', // 品质图片
  35. qualityDescription: '采用高温制曲、二次投料,一年为一个生产周期,具有独特的酿造工艺。',
  36. // 商品特点字段 - 从酒谷商品主数据表获取
  37. material: '水、高粱、小麦',
  38. alcohol: '53%vol.',
  39. origin: '贵州省仁怀市茅台镇',
  40. type: '酱香型白酒',
  41. capacity: '500ml',
  42. storage: '干燥、通风、阴凉的环境条件下存储',
  43. company: '贵州茅台酒股份有限公司'
  44. }
  45. return {
  46. success: true,
  47. message: '商品详情获取成功',
  48. data: productDetail
  49. }
  50. } catch (error) {
  51. console.error('获取商品详情失败:', error)
  52. return {
  53. success: false,
  54. message: '商品详情获取失败',
  55. data: null
  56. }
  57. }
  58. }
  59. /**
  60. * 获取商品图片
  61. * @param {string} productId 商品ID
  62. * @param {number} imageType 图片分类 (2=商品详情图片)
  63. * @returns {Promise} 商品图片数据
  64. */
  65. export const getProductImages = async (productId, imageType = 2) => {
  66. await delay(400) // 模拟网络延迟
  67. console.log('模拟API: 获取商品图片', { productId, imageType })
  68. try {
  69. // 模拟图片数据 - 根据图片分类==2获取
  70. const mockImages = [
  71. {
  72. id: `${productId}_img_001`,
  73. url: 'https://images.unsplash.com/photo-1470337458703-46ad1756a187?w=750&h=600&fit=crop',
  74. type: imageType,
  75. sort: 1
  76. },
  77. {
  78. id: `${productId}_img_002`,
  79. url: 'https://images.unsplash.com/photo-1569529465841-dfecdab7503b?w=750&h=600&fit=crop',
  80. type: imageType,
  81. sort: 2
  82. },
  83. {
  84. id: `${productId}_img_003`,
  85. url: 'https://images.unsplash.com/photo-1584464491033-06628f3a6b7b?w=750&h=600&fit=crop',
  86. type: imageType,
  87. sort: 3
  88. },
  89. {
  90. id: `${productId}_img_004`,
  91. url: 'https://images.unsplash.com/photo-1607622750671-6cd5a99ec572?w=750&h=600&fit=crop',
  92. type: imageType,
  93. sort: 4
  94. },
  95. {
  96. id: `${productId}_img_005`,
  97. url: 'https://images.unsplash.com/photo-1596040977107-3c27c6e95ac3?w=750&h=600&fit=crop',
  98. type: imageType,
  99. sort: 5
  100. },
  101. {
  102. id: `${productId}_img_006`,
  103. url: 'https://images.unsplash.com/photo-1558346648-9757f2fa4c64?w=750&h=600&fit=crop',
  104. type: imageType,
  105. sort: 6
  106. }
  107. ]
  108. // 根据图片分类筛选
  109. const filteredImages = mockImages.filter(img => img.type === imageType)
  110. return {
  111. success: true,
  112. message: '商品图片获取成功',
  113. data: {
  114. images: filteredImages,
  115. total: filteredImages.length
  116. }
  117. }
  118. } catch (error) {
  119. console.error('获取商品图片失败:', error)
  120. return {
  121. success: false,
  122. message: '商品图片获取失败',
  123. data: {
  124. images: [],
  125. total: 0
  126. }
  127. }
  128. }
  129. }
  130. /**
  131. * 搜索商品
  132. * @param {string} keyword 搜索关键词
  133. * @param {number} page 页码
  134. * @param {number} pageSize 每页数量
  135. * @returns {Promise} 搜索结果
  136. */
  137. export const searchProducts = async (keyword, page = 1, pageSize = 20) => {
  138. await delay(500) // 模拟网络延迟
  139. console.log('模拟API: 搜索商品', { keyword, page, pageSize })
  140. try {
  141. // 从模拟数据中搜索商品
  142. const allProducts = MOCK_PRODUCTS.data.products
  143. const filteredProducts = allProducts.filter(product =>
  144. product.name.toLowerCase().includes(keyword.toLowerCase())
  145. )
  146. // 分页处理
  147. const startIndex = (page - 1) * pageSize
  148. const endIndex = startIndex + pageSize
  149. const paginatedProducts = filteredProducts.slice(startIndex, endIndex)
  150. // 添加图片URL
  151. const productsWithImages = paginatedProducts.map(product => ({
  152. ...product,
  153. imageUrl: MOCK_ASSETS.products[product.assetId] || '',
  154. price: Math.floor(Math.random() * 1000) + 200, // 模拟价格
  155. points: Math.floor(Math.random() * 500) + 100 // 模拟积分
  156. }))
  157. return {
  158. success: true,
  159. message: '商品搜索成功',
  160. data: {
  161. products: productsWithImages,
  162. total: filteredProducts.length,
  163. page,
  164. pageSize,
  165. totalPages: Math.ceil(filteredProducts.length / pageSize)
  166. }
  167. }
  168. } catch (error) {
  169. console.error('搜索商品失败:', error)
  170. return {
  171. success: false,
  172. message: '商品搜索失败',
  173. data: {
  174. products: [],
  175. total: 0,
  176. page,
  177. pageSize,
  178. totalPages: 0
  179. }
  180. }
  181. }
  182. }
  183. /**
  184. * 获取商品分类
  185. * @param {string} categoryId 分类ID (可选)
  186. * @returns {Promise} 分类数据
  187. */
  188. export const getCategories = async (categoryId = null) => {
  189. await delay(300) // 模拟网络延迟
  190. console.log('模拟API: 获取商品分类', { categoryId })
  191. try {
  192. // 这里应该调用真实的分类API
  193. // 暂时返回模拟数据
  194. const categories = [
  195. {
  196. id: 'category_jiugu',
  197. name: '酒谷酒',
  198. description: '自主品牌酒谷系列',
  199. imageUrl: 'https://images.unsplash.com/photo-1470337458703-46ad1756a187?w=300&h=200&fit=crop'
  200. },
  201. {
  202. id: 'category_maotai',
  203. name: '茅台酒',
  204. description: '茅台系列白酒',
  205. imageUrl: 'https://images.unsplash.com/photo-1569529465841-dfecdab7503b?w=300&h=200&fit=crop'
  206. },
  207. {
  208. id: 'category_wine',
  209. name: '红酒',
  210. description: '进口和国产红酒',
  211. imageUrl: 'https://images.unsplash.com/photo-1584464491033-06628f3a6b7b?w=300&h=200&fit=crop'
  212. }
  213. ]
  214. const result = categoryId
  215. ? categories.find(c => c.id === categoryId)
  216. : categories
  217. return {
  218. success: true,
  219. message: '分类获取成功',
  220. data: result
  221. }
  222. } catch (error) {
  223. console.error('获取分类失败:', error)
  224. return {
  225. success: false,
  226. message: '分类获取失败',
  227. data: null
  228. }
  229. }
  230. }
  231. /**
  232. * 错误处理
  233. * @param {Error} error 错误对象
  234. */
  235. export const handleProductError = (error) => {
  236. console.error('商品API错误:', error)
  237. // 根据错误类型显示不同的提示
  238. if (error.message.includes('网络')) {
  239. uni.showToast({
  240. title: '网络连接失败,请检查网络设置',
  241. icon: 'none',
  242. duration: 3000
  243. })
  244. } else if (error.message.includes('超时')) {
  245. uni.showToast({
  246. title: '请求超时,请稍后重试',
  247. icon: 'none',
  248. duration: 2000
  249. })
  250. } else {
  251. uni.showToast({
  252. title: '操作失败,请稍后重试',
  253. icon: 'none',
  254. duration: 2000
  255. })
  256. }
  257. }