巴青农资商城

cartDisplay.js 4.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. import { resolveFileUrl } from '@/utils/image'
  2. import { formatPrice } from '@/utils/format'
  3. import {
  4. CART_INVALID_NONE,
  5. CART_INVALID_OUT_OF_STOCK,
  6. CART_INVALID_OFF_SHELF,
  7. CART_INVALID_SHOP_CLOSED,
  8. CART_INVALID_CATEGORY_HIDDEN,
  9. CART_INVALID_GOODS_DELETED,
  10. CART_INVALID_SHOP_DELETED
  11. } from '@/constants/cart'
  12. import { SHOP_STATUS_CLOSED } from '@/constants/shop'
  13. import { parseCartSpecText } from '@/utils/cartSpec'
  14. const GOODS_PLACEHOLDER = '/static/logo.png'
  15. const INVALID_LABEL_MAP = {
  16. [CART_INVALID_OUT_OF_STOCK]: '缺货',
  17. [CART_INVALID_OFF_SHELF]: '已下架',
  18. [CART_INVALID_SHOP_CLOSED]: '休息中',
  19. [CART_INVALID_CATEGORY_HIDDEN]: '不可购买',
  20. [CART_INVALID_GOODS_DELETED]: '已失效',
  21. [CART_INVALID_SHOP_DELETED]: '店铺失效'
  22. }
  23. export function getCartInvalidLabel(invalidType, invalidMsg) {
  24. if (!invalidType || invalidType === CART_INVALID_NONE) return ''
  25. return invalidMsg || INVALID_LABEL_MAP[invalidType] || '不可购买'
  26. }
  27. function mapCartItem(row) {
  28. if (!row) return null
  29. const invalidType = row.invalidType || CART_INVALID_NONE
  30. const purchasable = !!row.purchasable && invalidType === CART_INVALID_NONE
  31. return {
  32. cartItemId: row.cartItemId,
  33. goodsId: row.goodsId,
  34. goodsName: row.goodsName || '',
  35. mainPic: row.mainPic || '',
  36. displayPic: resolveFileUrl(row.mainPic) || GOODS_PLACEHOLDER,
  37. specText: (row.specText || '').trim() || '默认',
  38. specList: parseCartSpecText(row.specText),
  39. salePrice: row.salePrice,
  40. priceText: formatPrice(row.salePrice),
  41. quantity: Number(row.quantity) || 1,
  42. subtotal: row.subtotal,
  43. subtotalText: formatPrice(row.subtotal),
  44. checked: !!row.checked,
  45. purchasable,
  46. invalidType,
  47. invalidMsg: row.invalidMsg || '',
  48. invalidLabel: getCartInvalidLabel(invalidType, row.invalidMsg)
  49. }
  50. }
  51. function mapShopGroup(group) {
  52. if (!group) return null
  53. return {
  54. shopId: group.shopId,
  55. shopName: group.shopName || '',
  56. shopStatus: group.shopStatus,
  57. isClosed: String(group.shopStatus) === SHOP_STATUS_CLOSED,
  58. items: (group.items || []).map(mapCartItem).filter(Boolean)
  59. }
  60. }
  61. function mapCheckedSummary(summary) {
  62. const s = summary || {}
  63. const amount = s.checkedAmount
  64. return {
  65. checkedCount: Number(s.checkedCount) || 0,
  66. checkedQuantity: Number(s.checkedQuantity) || 0,
  67. checkedAmount: amount,
  68. checkedAmountText: formatPrice(amount)
  69. }
  70. }
  71. /** 扁平 items[] 按店铺分组(保持接口 cart_item_id 倒序下的店组顺序) */
  72. function groupCartItemsByShop(flatItems) {
  73. const groups = []
  74. const groupIndex = new Map()
  75. for (const row of flatItems || []) {
  76. const item = mapCartItem(row)
  77. if (!item) continue
  78. const shopId = row.shopId
  79. let group
  80. if (groupIndex.has(shopId)) {
  81. group = groups[groupIndex.get(shopId)]
  82. } else {
  83. group = {
  84. shopId,
  85. shopName: row.shopName || '',
  86. shopStatus: row.shopStatus,
  87. isClosed: String(row.shopStatus) === SHOP_STATUS_CLOSED,
  88. items: []
  89. }
  90. groupIndex.set(shopId, groups.length)
  91. groups.push(group)
  92. }
  93. group.items.push(item)
  94. }
  95. return groups
  96. }
  97. /** 列表接口 data → 页面模型 */
  98. export function mapCartList(data) {
  99. if (!data) {
  100. return { groups: [], checkedSummary: mapCheckedSummary(null) }
  101. }
  102. const groups = Array.isArray(data.groups) && data.groups.length
  103. ? data.groups.map(mapShopGroup).filter(Boolean)
  104. : groupCartItemsByShop(data.items || [])
  105. return {
  106. groups,
  107. checkedSummary: mapCheckedSummary(data.checkedSummary)
  108. }
  109. }
  110. /** 是否存在失效行 */
  111. export function hasInvalidCartItems(groups) {
  112. return countInvalidCartItems(groups) > 0
  113. }
  114. /** 失效商品件数(清理失效前展示) */
  115. export function countInvalidCartItems(groups) {
  116. if (!Array.isArray(groups)) return 0
  117. let count = 0
  118. groups.forEach((g) => {
  119. ;(g.items || []).forEach((item) => {
  120. if (!item.purchasable) count += 1
  121. })
  122. })
  123. return count
  124. }
  125. /** 当前勾选的可购行 shopId 集合 */
  126. export function getCheckedShopIds(groups) {
  127. const ids = new Set()
  128. if (!Array.isArray(groups)) return ids
  129. groups.forEach((g) => {
  130. ;(g.items || []).forEach((item) => {
  131. if (item.checked && item.purchasable) {
  132. ids.add(g.shopId)
  133. }
  134. })
  135. })
  136. return ids
  137. }
  138. /** 已勾选且可购的 cartItemId */
  139. export function getCheckedPurchasableIds(groups) {
  140. const ids = []
  141. if (!Array.isArray(groups)) return ids
  142. groups.forEach((g) => {
  143. ;(g.items || []).forEach((item) => {
  144. if (item.checked && item.purchasable) {
  145. ids.push(item.cartItemId)
  146. }
  147. })
  148. })
  149. return ids
  150. }
  151. /** 全部可购行 */
  152. export function getAllPurchasableItems(groups) {
  153. const list = []
  154. if (!Array.isArray(groups)) return list
  155. groups.forEach((g) => {
  156. ;(g.items || []).forEach((item) => {
  157. if (item.purchasable) {
  158. list.push({ ...item, shopId: g.shopId })
  159. }
  160. })
  161. })
  162. return list
  163. }