爱简收旧衣按件回收前端代码仓库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1484 lines
47 KiB

3 months ago
3 months ago
3 months ago
2 weeks ago
3 months ago
2 weeks ago
3 months ago
2 weeks ago
3 months ago
3 months ago
3 months ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
3 months ago
3 months ago
2 weeks ago
2 weeks ago
3 months ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
3 months ago
3 months ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
2 weeks ago
3 months ago
2 weeks ago
3 months ago
3 months ago
3 months ago
2 weeks ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
2 weeks ago
2 weeks ago
3 months ago
2 weeks ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
2 weeks ago
  1. <template>
  2. <view class="inspect-container">
  3. <!-- 顶部导航栏 -->
  4. <view class="nav-bar">
  5. <view class="back" @tap="goBack">
  6. <uni-icons type="left" size="20" color="#222" />
  7. </view>
  8. <text class="nav-title">步骤一数量确认</text>
  9. <view class="nav-icons">
  10. <uni-icons type="scan" size="24" color="#222" />
  11. </view>
  12. </view>
  13. <view class="main-content">
  14. <!-- 左侧分类导航 -->
  15. <view class="category-nav">
  16. <view v-for="(cat, idx) in categories" :key="cat.title"
  17. :class="['category-item', { active: idx === currentCategory }]" @tap="switchCategory(idx)">
  18. <text>{{ cat.title }}</text>
  19. <view v-if="cat.badge" class="category-badge">{{ cat.badge }}</view>
  20. </view>
  21. </view>
  22. <!-- 右侧商品卡片区 -->
  23. <scroll-view class="goods-list" scroll-y @scrolltolower="loadMoreGoods">
  24. <view v-for="(item, idx) in currentGoods" :key="item.id" class="goods-card">
  25. <view class="goods-header">
  26. <view class="goods-img-container">
  27. <image :src="item.image" class="goods-img" />
  28. <!-- 品牌标签 -->
  29. <view class="brand-tag" v-if="item.isPin === 'Y'">品牌</view>
  30. </view>
  31. <view class="goods-info">
  32. <view class="goods-title-row">
  33. <text class="goods-name">{{ item.name }}</text>
  34. <text class="goods-price">
  35. {{ formatPrice(item) }}
  36. <text class="goods-unit" v-if="item.unit">/{{item.unit}}</text>
  37. </text>
  38. </view>
  39. <text class="goods-desc">{{ item.desc }}</text>
  40. <!-- 显示已选择的品牌款式信息 -->
  41. <view v-if="getSelectedBrandStyles(item).length > 0" class="selected-styles">
  42. <view v-for="style in getSelectedBrandStyles(item)" :key="style.uniqueKey" class="style-item">
  43. <text class="style-text">{{ style.brandName }} - {{ style.styleName }} x{{ style.quantity }}</text>
  44. </view>
  45. </view>
  46. </view>
  47. </view>
  48. <view class="goods-row">
  49. <text class="row-label">合格数量</text>
  50. <view class="num-ctrl">
  51. <button class="num-btn" @tap="updateQuantity(idx, -1)">-</button>
  52. <text class="num">{{ getItemTotalQuantity(item) }}</text>
  53. <button class="num-btn" @tap="updateQuantity(idx, 1)">+</button>
  54. </view>
  55. </view>
  56. </view>
  57. <view v-if="loadingMore" class="loading-more">加载中...</view>
  58. <view v-else-if="finished" class="loading-more">没有更多了</view>
  59. </scroll-view>
  60. </view>
  61. <!-- 底部操作按钮 -->
  62. <view class="footer-btns">
  63. <button class="btn-outline" @tap="goBack">返回订单详情</button>
  64. <button class="btn-main" @tap="goNext">下一步</button>
  65. </view>
  66. <!-- 品牌选择组件 -->
  67. <brand-selector ref="brandSelector" @brand-confirm="onBrandConfirm" @reduce-select="onReduceSelect"
  68. @close="onBrandSelectorClose" @get-existing-quantities="getExistingQuantities"></brand-selector>
  69. </view>
  70. </template>
  71. <script>
  72. import brandSelector from '../../compoent/recycle/brand-selector.vue'
  73. export default {
  74. components: {
  75. brandSelector
  76. },
  77. data() {
  78. return {
  79. statusBarHeight: 0,
  80. currentCategory: 0,
  81. orderId: '',
  82. order: null, // 订单数据
  83. currentGoods: [], // 当前显示的商品列表
  84. inspectResult: {}, // 质检结果对象,按照新的数据格式
  85. allProducts: {}, // { [categoryId]: [商品数组] }
  86. allProductsPage: {}, // { [categoryId]: 当前已加载页码 }
  87. allProductsTotal: {}, // { [categoryId]: 总数 }
  88. pageSize: 10,
  89. loadingMore: false,
  90. finished: false,
  91. // 品牌选择相关
  92. pendingBrandIndex: null,
  93. reduceItem: null, // 待减少数量的商品
  94. brandStyleCache: {}, // 全局品牌款式缓存
  95. // brandIndexList 改为 computed
  96. }
  97. },
  98. computed: {
  99. categories() {
  100. const list = getApp().globalData.pricePreviewList || []
  101. console.log('categories计算 - pricePreviewList:', list.length)
  102. // 显示所有分类,不再根据订单数据筛选
  103. const allCategories = list.filter(item => item.pid === '0').sort((a, b) => a.sort - b.sort)
  104. console.log('categories计算 - allCategories:', allCategories.length)
  105. // 为每个分类计算数量
  106. const categoriesWithCount = allCategories.map(category => {
  107. const count = this.getCategoryItemCountDirect(category.id)
  108. return {
  109. ...category,
  110. badge: count > 0 ? count : null
  111. }
  112. })
  113. // 新增不可回收和质量问题分类
  114. const extra = [
  115. { id: 'unrecyclable', title: '不可回收', badge: this.getUnrecyclableCount() },
  116. { id: 'quality_issue', title: '质量问题', badge: this.getQualityIssueCount() }
  117. ]
  118. const result = [...categoriesWithCount, ...extra]
  119. console.log('categories计算 - 最终结果:', result.map(c => ({ id: c.id, title: c.title, badge: c.badge })))
  120. return result
  121. },
  122. },
  123. methods: {
  124. initInspectResult() {
  125. // 只初始化空的list
  126. this.inspectResult = {
  127. id: this.order ? this.order.id : '',
  128. list: []
  129. }
  130. },
  131. // 获取分类商品数量(直接方法,避免递归)
  132. getCategoryItemCountDirect(categoryId) {
  133. if (categoryId === 'unrecyclable') {
  134. return this.getUnrecyclableCount()
  135. }
  136. if (categoryId === 'quality_issue') {
  137. return this.getQualityIssueCount()
  138. }
  139. let totalCount = 0
  140. if (this.inspectResult.list && this.inspectResult.list.length > 0) {
  141. this.inspectResult.list.forEach(inspectItem => {
  142. if (inspectItem.categoryId === categoryId) {
  143. totalCount += inspectItem.qualifiedNum || 0
  144. }
  145. })
  146. }
  147. return totalCount
  148. },
  149. // 获取当前分类ID(避免递归)
  150. getCurrentCategoryId() {
  151. const list = getApp().globalData.pricePreviewList || []
  152. const allCategories = list.filter(item => item.pid === '0').sort((a, b) => a.sort - b.sort)
  153. const extra = [
  154. { id: 'unrecyclable', title: '不可回收' },
  155. { id: 'quality_issue', title: '质量问题' }
  156. ]
  157. const allCategoriesWithExtra = [...allCategories, ...extra]
  158. return allCategoriesWithExtra[this.currentCategory]?.id
  159. },
  160. // 获取分类商品数量(保持原有方法名兼容性)
  161. getCategoryItemCount(categoryId) {
  162. return this.getCategoryItemCountDirect(categoryId)
  163. },
  164. // 获取不可回收数量
  165. getUnrecyclableCount() {
  166. // 从inspectResult中获取不可回收的数量
  167. const unrecyclableItem = this.inspectResult.list?.find(item => item.id === 'unrecyclable')
  168. return unrecyclableItem ? unrecyclableItem.unrecyclable : 0
  169. },
  170. // 获取质量问题数量
  171. getQualityIssueCount() {
  172. // 从inspectResult中获取质量问题的数量
  173. const qualityIssueItem = this.inspectResult.list?.find(item => item.id === 'quality_issue')
  174. return qualityIssueItem ? qualityIssueItem.noQualifiedNum : 0
  175. },
  176. fetchGoodsList(categoryId, page = 1, callback) {
  177. this.$api('getClassGoodsList', {
  178. classId: categoryId,
  179. pageNo: page,
  180. pageSize: this.pageSize
  181. }, res => {
  182. if (res.code === 200 && res.result && Array.isArray(res.result.records)) {
  183. const oldList = this.allProducts[categoryId] || []
  184. const newList = page === 1 ? res.result.records : oldList.concat(res.result.records)
  185. this.$set(this.allProducts, categoryId, newList)
  186. this.$set(this.allProductsPage, categoryId, page)
  187. this.$set(this.allProductsTotal, categoryId, res.result.total)
  188. this.updateCurrentGoods()
  189. }
  190. if (callback) callback()
  191. })
  192. },
  193. updateCurrentGoods() {
  194. const currentCategoryId = this.categories[this.currentCategory]?.id
  195. // 不可回收分类内容
  196. if (currentCategoryId === 'unrecyclable') {
  197. // 从inspectResult中获取不可回收的数量
  198. const unrecyclableItem = this.inspectResult.list?.find(item => item.id === 'unrecyclable')
  199. const unrecyclableCount = unrecyclableItem ? unrecyclableItem.unrecyclable : 0
  200. this.currentGoods = [{
  201. id: 'unrecyclable-1',
  202. image: '/static/回收/衣物.png',
  203. name: '不可回收品类',
  204. price: '—',
  205. desc: '允许脏破烂,160码以上',
  206. qualified: unrecyclableCount,
  207. amount: '',
  208. originalNum: 0 // 不设置最大数量限制
  209. }]
  210. return
  211. }
  212. // 质量问题分类内容
  213. if (currentCategoryId === 'quality_issue') {
  214. // 从inspectResult中获取质量问题的数量
  215. const qualityIssueItem = this.inspectResult.list?.find(item => item.id === 'quality_issue')
  216. const qualityIssueCount = qualityIssueItem ? qualityIssueItem.noQualifiedNum : 0
  217. this.currentGoods = [{
  218. id: 'quality-issue-1',
  219. image: '/static/回收/衣物.png',
  220. name: '质量问题品类',
  221. price: '—',
  222. desc: '存在质量问题,无法正常回收',
  223. qualified: qualityIssueCount,
  224. amount: '',
  225. originalNum: 0 // 不设置最大数量限制
  226. }]
  227. return
  228. }
  229. // 从API获取的商品数据
  230. const categoryGoods = this.allProducts[currentCategoryId] || []
  231. // 将API商品数据转换为质检页面格式,并合并inspectResult.list中已选状态(shopId和id双向查找)
  232. const goodsList = categoryGoods.map((item, index) => {
  233. // 从订单数据中查找对应的商品
  234. const orderItem = this.getOrderItemByProductId(item.id)
  235. let itemId = item.id
  236. if (orderItem && orderItem.id) {
  237. itemId = orderItem.id
  238. }
  239. const inspectItem = this.inspectResult.list?.find(listItem =>
  240. listItem.shopId == item.id || listItem.shopId == itemId || listItem.id == item.id || listItem.id == itemId
  241. )
  242. // 恢复品牌款式数据 - 从所有分类的商品中查找
  243. const brandStyleQuantities = {}
  244. const styleCache = {}
  245. let totalQuantity = 0
  246. // 查找所有分类中是否有相同商品的品牌款式数据
  247. Object.values(this.allProducts).forEach(categoryProducts => {
  248. const existingProduct = categoryProducts.find(p => p.id === item.id)
  249. if (existingProduct && this.currentGoods) {
  250. const existingGoodsItem = this.currentGoods.find(g => g.id === item.id)
  251. if (existingGoodsItem && existingGoodsItem.brandStyleQuantities) {
  252. Object.assign(brandStyleQuantities, existingGoodsItem.brandStyleQuantities)
  253. Object.assign(styleCache, existingGoodsItem.styleCache)
  254. totalQuantity = Object.values(existingGoodsItem.brandStyleQuantities).reduce((sum, qty) => sum + qty, 0)
  255. }
  256. }
  257. })
  258. // 如果没有找到现有数据,尝试从全局状态中恢复
  259. if (totalQuantity === 0 && this.brandStyleCache && this.brandStyleCache[item.id]) {
  260. Object.assign(brandStyleQuantities, this.brandStyleCache[item.id].brandStyleQuantities || {})
  261. Object.assign(styleCache, this.brandStyleCache[item.id].styleCache || {})
  262. totalQuantity = Object.values(brandStyleQuantities).reduce((sum, qty) => sum + qty, 0)
  263. }
  264. // 如果没有品牌款式数据,使用普通数量
  265. const finalQuantity = totalQuantity > 0 ? 0 : (inspectItem ? inspectItem.qualifiedNum : 0)
  266. return {
  267. id: item.id,
  268. image: item.image || '/static/回收/衣物.png',
  269. name: item.name,
  270. price: item.price || 0,
  271. maxPrice: item.maxPrice || 0,
  272. desc: item.service || '允许脏破烂,160码以上',
  273. qualified: inspectItem ? inspectItem.qualifiedNum : 0,
  274. originalNum: 0,
  275. estimatedPrice: orderItem ? orderItem.estimatedPrice : 0,
  276. originalId: item.id,
  277. isPin: item.isPin || 'N',
  278. orderItem: orderItem,
  279. unit: item.unit || '件',
  280. // 品牌款式相关数据
  281. brandStyleQuantities: brandStyleQuantities,
  282. styleCache: styleCache,
  283. quantity: finalQuantity
  284. }
  285. })
  286. this.currentGoods = goodsList
  287. },
  288. // 根据商品ID从订单数据中查找对应商品
  289. getOrderItemByProductId(productId) {
  290. if (!this.order || !this.order.commonOrderList) {
  291. return null
  292. }
  293. // 支持id和shopId双向查找
  294. return this.order.commonOrderList.find(item => item.id == productId || item.shopId == productId)
  295. },
  296. goBack() {
  297. uni.navigateBack()
  298. },
  299. goNext() {
  300. // 检测是否所有商品都已完成质检和填写价格
  301. const validationResult = this.validateInspectData()
  302. if (!validationResult.isValid) {
  303. uni.showToast({
  304. title: validationResult.message,
  305. icon: 'none',
  306. duration: 2000
  307. })
  308. return
  309. }
  310. // 将品牌款式数据转换为独立的质检对象
  311. const processedInspectResult = this.processInspectResultForBrandStyles()
  312. // 构造传递给步骤二的完整数据
  313. const resultData = {
  314. inspectResult: processedInspectResult,
  315. order: this.order // 同时传递订单信息
  316. }
  317. console.log('resultDataStr:', resultData)
  318. const resultDataStr = encodeURIComponent(JSON.stringify(resultData))
  319. uni.navigateTo({
  320. url: `/pages/manager/inspect-result?resultData=${resultDataStr}`
  321. })
  322. },
  323. // 处理品牌款式数据,将每个品牌款式组合生成独立的质检对象
  324. processInspectResultForBrandStyles() {
  325. const processedList = []
  326. // 遍历当前的质检结果
  327. this.inspectResult.list.forEach(inspectItem => {
  328. // 不可回收和质量问题直接保留
  329. if (inspectItem.id === 'unrecyclable' || inspectItem.id === 'quality_issue') {
  330. processedList.push(inspectItem)
  331. return
  332. }
  333. // 从全局缓存中查找品牌款式数据
  334. const cachedBrandStyleData = this.findBrandStyleDataFromCache(inspectItem.shopId)
  335. if (cachedBrandStyleData && Object.keys(cachedBrandStyleData.brandStyleQuantities).length > 0) {
  336. // 如果有品牌款式数据,为每个品牌款式创建独立对象
  337. Object.entries(cachedBrandStyleData.brandStyleQuantities).forEach(([uniqueKey, quantity]) => {
  338. if (quantity > 0 && cachedBrandStyleData.styleCache && cachedBrandStyleData.styleCache[uniqueKey]) {
  339. const { brandInfo, styleInfo } = cachedBrandStyleData.styleCache[uniqueKey]
  340. // 为每个品牌款式组合创建独立的质检对象
  341. const brandStyleInspectItem = {
  342. ...inspectItem,
  343. qualifiedNum: quantity,
  344. shopId: inspectItem.shopId,
  345. pinId: brandInfo.id,
  346. styleId: styleInfo.id,
  347. brandName: brandInfo.name,
  348. styleName: styleInfo.name,
  349. brandImage: brandInfo.logo,
  350. styleImage: styleInfo.image,
  351. uniqueKey: uniqueKey,
  352. // 添加款式价格信息
  353. styleMinPrice: styleInfo.minPrice || 0,
  354. styleMaxPrice: styleInfo.maxPrice || styleInfo.minPrice || 0,
  355. commonOrderList: [{
  356. testingInstructions: '',
  357. testingImages: '',
  358. testingStatus: 0
  359. }]
  360. }
  361. processedList.push(brandStyleInspectItem)
  362. }
  363. })
  364. } else {
  365. // 没有品牌款式数据,保留原始对象并添加商品价格信息
  366. const productId = this.getProductIdFromShopId(inspectItem.shopId)
  367. const productInfo = this.findProductInfoById(productId)
  368. const enhancedInspectItem = {
  369. ...inspectItem,
  370. // 添加商品本身的价格信息
  371. productMinPrice: productInfo ? productInfo.price || 0 : 0,
  372. productMaxPrice: productInfo ? productInfo.maxPrice || productInfo.price || 0 : 0
  373. }
  374. processedList.push(enhancedInspectItem)
  375. }
  376. })
  377. return {
  378. id: this.inspectResult.id,
  379. list: processedList
  380. }
  381. },
  382. // 根据shopId查找当前商品
  383. findCurrentGoodsByShopId(shopId) {
  384. return this.currentGoods.find(item => {
  385. const orderItem = this.getOrderItemByProductId(item.id)
  386. const itemId = orderItem ? (orderItem.shopId || orderItem.id) : item.id
  387. return itemId == shopId
  388. })
  389. },
  390. // 从全局缓存和所有分类商品中查找品牌款式数据
  391. findBrandStyleDataFromCache(shopId) {
  392. // 首先从全局缓存中查找
  393. const productId = this.getProductIdFromShopId(shopId)
  394. if (productId && this.brandStyleCache[productId]) {
  395. return this.brandStyleCache[productId]
  396. }
  397. // 从所有分类的商品中查找
  398. for (const categoryId in this.allProducts) {
  399. const categoryProducts = this.allProducts[categoryId]
  400. for (const product of categoryProducts) {
  401. const orderItem = this.getOrderItemByProductId(product.id)
  402. const itemId = orderItem ? (orderItem.shopId || orderItem.id) : product.id
  403. if (itemId == shopId && this.brandStyleCache[product.id]) {
  404. return this.brandStyleCache[product.id]
  405. }
  406. }
  407. }
  408. return null
  409. },
  410. // 根据shopId获取productId
  411. getProductIdFromShopId(shopId) {
  412. // 从订单数据中查找
  413. if (this.order && this.order.commonOrderList) {
  414. const orderItem = this.order.commonOrderList.find(item =>
  415. item.shopId == shopId || item.id == shopId
  416. )
  417. if (orderItem) {
  418. return orderItem.shopId || orderItem.id
  419. }
  420. }
  421. // 从所有分类商品中查找
  422. for (const categoryId in this.allProducts) {
  423. const categoryProducts = this.allProducts[categoryId]
  424. const product = categoryProducts.find(p => {
  425. const orderItem = this.getOrderItemByProductId(p.id)
  426. const itemId = orderItem ? (orderItem.shopId || orderItem.id) : p.id
  427. return itemId == shopId
  428. })
  429. if (product) {
  430. return product.id
  431. }
  432. }
  433. return shopId
  434. },
  435. // 根据商品ID查找商品信息
  436. findProductInfoById(productId) {
  437. // 从所有分类商品中查找
  438. for (const categoryId in this.allProducts) {
  439. const categoryProducts = this.allProducts[categoryId]
  440. const product = categoryProducts.find(p => p.id == productId)
  441. if (product) {
  442. return product
  443. }
  444. }
  445. return null
  446. },
  447. validateInspectData() {
  448. if (!this.inspectResult.list || this.inspectResult.list.length === 0) {
  449. return {
  450. isValid: false,
  451. message: '没有质检数据'
  452. }
  453. }
  454. for (const item of this.inspectResult.list) {
  455. // 不可回收和质量问题不需要校验金额
  456. if (item.id === 'unrecyclable' || item.id === 'quality_issue') {
  457. continue
  458. }
  459. // 只判断是否填写了commonOrderList(即有质检结果)
  460. if (!item.commonOrderList || item.commonOrderList.length === 0) {
  461. return {
  462. isValid: false,
  463. message: '有商品未完成质检选择'
  464. }
  465. }
  466. // 检查是否有空的testingStatus
  467. const hasEmptyStatus = item.commonOrderList.some(commonItem =>
  468. commonItem.testingStatus === '' || commonItem.testingStatus === null || commonItem.testingStatus === undefined
  469. )
  470. if (hasEmptyStatus) {
  471. return {
  472. isValid: false,
  473. message: '有商品未完成质检选择'
  474. }
  475. }
  476. // 不再校验价格,价格将在下一步填写
  477. }
  478. return {
  479. isValid: true,
  480. message: ''
  481. }
  482. },
  483. switchCategory(idx) {
  484. this.currentCategory = idx
  485. this.loadingMore = false
  486. this.finished = false
  487. const categoryId = this.categories[idx]?.id
  488. if (categoryId === 'unrecyclable' || categoryId === 'quality_issue') {
  489. // 不可回收和质量问题分类直接更新商品列表
  490. this.updateCurrentGoods()
  491. return
  492. }
  493. // 如果该分类的商品还没有加载,调用API获取
  494. if (!this.allProducts[categoryId]) {
  495. this.fetchGoodsList(categoryId, 1)
  496. } else {
  497. // 已有数据,直接更新显示
  498. this.updateCurrentGoods()
  499. }
  500. },
  501. // 更新商品数量
  502. updateQuantity(index, delta) {
  503. const categoryId = this.categories[this.currentCategory]?.id
  504. const item = this.currentGoods[index]
  505. if (!item) return
  506. // 处理不可回收和质量问题
  507. if (item.id === 'unrecyclable-1' || item.id === 'quality-issue-1') {
  508. const newQualified = Math.max(0, (item.qualified || 0) + delta)
  509. this.$set(item, 'qualified', newQualified)
  510. this.updateInspectResult(item, 'qualified', delta, categoryId)
  511. // 更新商品列表以同步显示
  512. this.updateCurrentGoods()
  513. this.$forceUpdate()
  514. return
  515. }
  516. // 如果是减少数量且delta为负数
  517. if (delta < 0) {
  518. // 检查是否有多个品牌款式
  519. if (item.brandStyleQuantities && Object.keys(item.brandStyleQuantities).length > 1) {
  520. // 有多个品牌款式,显示选择弹窗
  521. this.reduceItem = { item, index, delta }
  522. const reduceStyleList = Object.entries(item.brandStyleQuantities)
  523. .filter(([uniqueKey, quantity]) => quantity > 0)
  524. .map(([uniqueKey, quantity]) => {
  525. const cacheInfo = item.styleCache[uniqueKey]
  526. return {
  527. uniqueKey,
  528. quantity,
  529. name: cacheInfo ? `${cacheInfo.brandInfo.name} - ${cacheInfo.styleInfo.name}` : '未知款式',
  530. logo: cacheInfo ? cacheInfo.brandInfo.logo : ''
  531. }
  532. })
  533. this.$refs.brandSelector.openReducePopup(reduceStyleList)
  534. return
  535. } else if (item.brandStyleQuantities && Object.keys(item.brandStyleQuantities).length === 1) {
  536. // 只有一个品牌款式,直接减少
  537. const uniqueKey = Object.keys(item.brandStyleQuantities)[0]
  538. const currentQty = item.brandStyleQuantities[uniqueKey] || 0
  539. const newQty = Math.max(0, currentQty + delta)
  540. this.$set(item.brandStyleQuantities, uniqueKey, newQty)
  541. // 如果数量为0,删除该品牌款式
  542. if (newQty === 0) {
  543. delete item.brandStyleQuantities[uniqueKey]
  544. if (item.styleCache && item.styleCache[uniqueKey]) {
  545. delete item.styleCache[uniqueKey]
  546. }
  547. }
  548. this.updateInspectResultFromBrandStyle(item)
  549. return
  550. } else {
  551. // 没有品牌数量,使用原来的逻辑
  552. let newQuantity = (item.quantity || 0) + delta
  553. if (newQuantity < 0) newQuantity = 0
  554. this.$set(item, 'quantity', newQuantity)
  555. this.updateInspectResultFromQuantity(item)
  556. return
  557. }
  558. }
  559. // 品牌商品且加一时,每次都重新选择品牌款式
  560. if (item.isPin === 'Y' && delta > 0) {
  561. this.pendingBrandIndex = index
  562. this.$refs.brandSelector.open(item.id)
  563. return
  564. }
  565. // 无品牌商品,直接加减数量
  566. if (item.isPin !== 'Y') {
  567. let newQuantity = (item.quantity || 0) + delta
  568. if (newQuantity < 0) newQuantity = 0
  569. this.$set(item, 'quantity', newQuantity)
  570. this.updateInspectResultFromQuantity(item)
  571. return
  572. }
  573. },
  574. // 获取商品的总数量(所有品牌款式)
  575. getItemTotalQuantity(item) {
  576. // 特殊处理不可回收和质量问题
  577. if (item.id === 'unrecyclable-1' || item.id === 'quality-issue-1') {
  578. return item.qualified || 0
  579. }
  580. if (item.brandStyleQuantities && Object.keys(item.brandStyleQuantities).length > 0) {
  581. return Object.values(item.brandStyleQuantities).reduce((sum, qty) => sum + qty, 0)
  582. }
  583. return item.quantity || 0
  584. },
  585. // 获取已选择的品牌款式信息
  586. getSelectedBrandStyles(item) {
  587. const styles = []
  588. if (item.brandStyleQuantities && item.styleCache) {
  589. Object.entries(item.brandStyleQuantities).forEach(([uniqueKey, quantity]) => {
  590. if (quantity > 0 && item.styleCache[uniqueKey]) {
  591. const { brandInfo, styleInfo } = item.styleCache[uniqueKey]
  592. styles.push({
  593. uniqueKey,
  594. quantity,
  595. brandName: brandInfo.name,
  596. styleName: styleInfo.name
  597. })
  598. }
  599. })
  600. }
  601. return styles
  602. },
  603. // 处理品牌确认事件
  604. onBrandConfirm(data) {
  605. if (this.pendingBrandIndex !== null) {
  606. const item = this.currentGoods[this.pendingBrandIndex]
  607. if (item && data.selectedStyles && data.selectedStyles.length > 0) {
  608. // 初始化品牌款式数量对象
  609. if (!item.brandStyleQuantities) {
  610. this.$set(item, 'brandStyleQuantities', {})
  611. }
  612. // 为每个选中的款式累加数量(不清理现有数据,而是累加)
  613. data.selectedStyles.forEach(style => {
  614. if (style.quantity > 0) {
  615. const uniqueKey = `${data.brandInfo.id}_${style.id}`
  616. const existingQty = item.brandStyleQuantities[uniqueKey] || 0
  617. this.$set(item.brandStyleQuantities, uniqueKey, existingQty + style.quantity)
  618. // 缓存款式信息用于后续显示
  619. if (!item.styleCache) {
  620. this.$set(item, 'styleCache', {})
  621. }
  622. this.$set(item.styleCache, uniqueKey, {
  623. brandInfo: data.brandInfo,
  624. styleInfo: style
  625. })
  626. }
  627. })
  628. // 清除原来的quantity
  629. if (item.quantity) {
  630. this.$set(item, 'quantity', 0)
  631. }
  632. // 更新质检结果
  633. this.updateInspectResultFromBrandStyle(item)
  634. // 保存到全局缓存
  635. this.$set(this.brandStyleCache, item.id, {
  636. brandStyleQuantities: { ...item.brandStyleQuantities },
  637. styleCache: { ...item.styleCache }
  638. })
  639. }
  640. this.pendingBrandIndex = null
  641. }
  642. },
  643. // 处理减少品牌选择事件
  644. onReduceSelect(selectInfo) {
  645. const { item, index, delta } = this.reduceItem
  646. if (selectInfo.uniqueKey) {
  647. // 品牌款式减少逻辑
  648. const currentQty = item.brandStyleQuantities[selectInfo.uniqueKey] || 0
  649. const newQty = Math.max(0, currentQty + delta)
  650. this.$set(item.brandStyleQuantities, selectInfo.uniqueKey, newQty)
  651. // 如果数量为0,删除该品牌款式
  652. if (newQty === 0) {
  653. delete item.brandStyleQuantities[selectInfo.uniqueKey]
  654. if (item.styleCache && item.styleCache[selectInfo.uniqueKey]) {
  655. delete item.styleCache[selectInfo.uniqueKey]
  656. }
  657. }
  658. this.updateInspectResultFromBrandStyle(item)
  659. // 更新全局缓存
  660. this.$set(this.brandStyleCache, item.id, {
  661. brandStyleQuantities: { ...item.brandStyleQuantities },
  662. styleCache: { ...item.styleCache }
  663. })
  664. }
  665. this.reduceItem = null
  666. },
  667. // 处理品牌选择器关闭事件
  668. onBrandSelectorClose() {
  669. this.pendingBrandIndex = null
  670. },
  671. // 获取已有的款式数量
  672. getExistingQuantities(brandId, callback) {
  673. if (this.pendingBrandIndex !== null) {
  674. const item = this.currentGoods[this.pendingBrandIndex]
  675. if (item && item.brandStyleQuantities) {
  676. // 过滤出当前品牌的款式数量
  677. const existingQuantities = {}
  678. Object.entries(item.brandStyleQuantities).forEach(([uniqueKey, quantity]) => {
  679. if (uniqueKey.startsWith(`${brandId}_`)) {
  680. existingQuantities[uniqueKey] = quantity
  681. }
  682. })
  683. callback(existingQuantities)
  684. } else {
  685. callback({})
  686. }
  687. } else {
  688. callback({})
  689. }
  690. },
  691. // 从品牌款式数据更新质检结果
  692. updateInspectResultFromBrandStyle(item) {
  693. const totalQuantity = this.getItemTotalQuantity(item)
  694. // 如果总数量为0,移除质检结果
  695. if (totalQuantity === 0) {
  696. this.removeInspectItem(item)
  697. return
  698. }
  699. // 更新或创建质检结果项
  700. const categoryId = this.categories[this.currentCategory]?.id
  701. const orderItem = this.getOrderItemByProductId(item.id)
  702. const itemId = orderItem ? (orderItem.shopId || orderItem.id) : item.id
  703. let inspectItem = this.inspectResult.list?.find(listItem => listItem.shopId == itemId)
  704. if (!inspectItem) {
  705. inspectItem = {
  706. price: 0,
  707. qualifiedNum: totalQuantity,
  708. noQualifiedNum: 0,
  709. unrecyclable: 0,
  710. shopId: itemId,
  711. pinId: '',
  712. categoryId: categoryId || '',
  713. commonOrderList: [{
  714. testingInstructions: '',
  715. testingImages: '',
  716. testingStatus: 0
  717. }]
  718. }
  719. this.inspectResult.list.push(inspectItem)
  720. } else {
  721. inspectItem.qualifiedNum = totalQuantity
  722. }
  723. },
  724. // 从普通数量更新质检结果
  725. updateInspectResultFromQuantity(item) {
  726. const quantity = item.quantity || 0
  727. // 如果数量为0,移除质检结果
  728. if (quantity === 0) {
  729. this.removeInspectItem(item)
  730. return
  731. }
  732. // 更新或创建质检结果项
  733. const categoryId = this.categories[this.currentCategory]?.id
  734. const orderItem = this.getOrderItemByProductId(item.id)
  735. const itemId = orderItem ? (orderItem.shopId || orderItem.id) : item.id
  736. let inspectItem = this.inspectResult.list?.find(listItem => listItem.shopId == itemId)
  737. if (!inspectItem) {
  738. inspectItem = {
  739. price: 0,
  740. qualifiedNum: quantity,
  741. noQualifiedNum: 0,
  742. unrecyclable: 0,
  743. shopId: itemId,
  744. pinId: '',
  745. categoryId: categoryId || '',
  746. commonOrderList: [{
  747. testingInstructions: '',
  748. testingImages: '',
  749. testingStatus: 0
  750. }]
  751. }
  752. this.inspectResult.list.push(inspectItem)
  753. } else {
  754. inspectItem.qualifiedNum = quantity
  755. }
  756. },
  757. // 修改:移除商品对象方法,支持不可回收和质量问题
  758. removeInspectItem(item) {
  759. // 判断不可回收和质量问题
  760. if (item.id === 'unrecyclable-1' || item.id === 'unrecyclable') {
  761. const idx = this.inspectResult.list.findIndex(listItem => listItem.id === 'unrecyclable')
  762. if (idx !== -1) {
  763. this.inspectResult.list.splice(idx, 1)
  764. }
  765. return
  766. }
  767. if (item.id === 'quality-issue-1' || item.id === 'quality_issue') {
  768. const idx = this.inspectResult.list.findIndex(listItem => listItem.id === 'quality_issue')
  769. if (idx !== -1) {
  770. this.inspectResult.list.splice(idx, 1)
  771. }
  772. return
  773. }
  774. let itemId = item.originalId || item.id
  775. const orderItem = this.getOrderItemByProductId(itemId)
  776. if (orderItem && orderItem.id) {
  777. itemId = orderItem.id
  778. }
  779. // shopId 匹配
  780. const idx = this.inspectResult.list.findIndex(listItem => listItem.shopId == (orderItem ? (orderItem.shopId || orderItem.id) : itemId))
  781. if (idx !== -1) {
  782. this.inspectResult.list.splice(idx, 1)
  783. }
  784. },
  785. updateInspectResult(item, type, delta, currentCategoryId) {
  786. // 处理不可回收分类
  787. if (item.id === 'unrecyclable-1') {
  788. let inspectItem = this.inspectResult.list.find(listItem => listItem.id === 'unrecyclable')
  789. if (!inspectItem && delta > 0) {
  790. inspectItem = {
  791. id: 'unrecyclable',
  792. price: 0,
  793. qualifiedNum: 0,
  794. noQualifiedNum: 0,
  795. unrecyclable: 0, // 初始值为0
  796. shopId: '',
  797. pinId: '',
  798. categoryId: '',
  799. commonOrderList: [] // 初始为空数组
  800. }
  801. this.inspectResult.list.push(inspectItem)
  802. }
  803. if (!inspectItem) return
  804. if (type === 'qualified' && delta > 0) {
  805. inspectItem.unrecyclable++
  806. // 增加一个commonOrderList对象
  807. inspectItem.commonOrderList.push({
  808. testingInstructions: '',
  809. testingImages: '',
  810. testingStatus: 2
  811. })
  812. } else if (type === 'qualified' && delta < 0) {
  813. inspectItem.unrecyclable = Math.max(0, inspectItem.unrecyclable - 1)
  814. // 减少一个commonOrderList对象
  815. if (inspectItem.commonOrderList.length > 0) {
  816. inspectItem.commonOrderList.pop()
  817. }
  818. // 新增:如果减到0,移除该对象
  819. if (inspectItem.unrecyclable === 0) {
  820. const idx = this.inspectResult.list.findIndex(listItem => listItem === inspectItem)
  821. if (idx !== -1) {
  822. this.inspectResult.list.splice(idx, 1)
  823. }
  824. return
  825. }
  826. }
  827. console.log('不可回收对象:', inspectItem)
  828. return
  829. }
  830. if (item.id === 'quality-issue-1') {
  831. let inspectItem = this.inspectResult.list.find(listItem => listItem.id === 'quality_issue')
  832. if (!inspectItem && delta > 0) {
  833. inspectItem = {
  834. id: 'quality_issue',
  835. price: 0,
  836. qualifiedNum: 0,
  837. noQualifiedNum: 0, // 初始值为0
  838. unrecyclable: 0,
  839. shopId: '',
  840. pinId: '',
  841. categoryId: '',
  842. commonOrderList: [] // 初始为空数组
  843. }
  844. this.inspectResult.list.push(inspectItem)
  845. }
  846. if (!inspectItem) return
  847. if (type === 'qualified' && delta > 0) {
  848. inspectItem.noQualifiedNum++
  849. // 增加一个commonOrderList对象
  850. inspectItem.commonOrderList.push({
  851. testingInstructions: '',
  852. testingImages: '',
  853. testingStatus: 1
  854. })
  855. } else if (type === 'qualified' && delta < 0) {
  856. inspectItem.noQualifiedNum = Math.max(0, inspectItem.noQualifiedNum - 1)
  857. // 减少一个commonOrderList对象
  858. if (inspectItem.commonOrderList.length > 0) {
  859. inspectItem.commonOrderList.pop()
  860. }
  861. // 新增:如果减到0,移除该对象
  862. if (inspectItem.noQualifiedNum === 0) {
  863. const idx = this.inspectResult.list.findIndex(listItem => listItem === inspectItem)
  864. if (idx !== -1) {
  865. this.inspectResult.list.splice(idx, 1)
  866. }
  867. return
  868. }
  869. }
  870. console.log('质量问题对象:', inspectItem)
  871. return
  872. }
  873. let itemId = item.originalId || item.id
  874. const orderItem = this.getOrderItemByProductId(itemId)
  875. if (orderItem && orderItem.id) {
  876. itemId = orderItem.id
  877. }
  878. let inspectItem = this.inspectResult.list.find(listItem => listItem.shopId == (orderItem ? (orderItem.shopId || orderItem.id) : itemId))
  879. if (!inspectItem && delta > 0) {
  880. inspectItem = {
  881. price: 0,
  882. qualifiedNum: 0,
  883. noQualifiedNum: 0,
  884. unrecyclable: 0,
  885. shopId: orderItem ? (orderItem.shopId || orderItem.id) : itemId,
  886. pinId: '',
  887. categoryId: currentCategoryId || '', // 直接用当前分类id
  888. commonOrderList: [{
  889. testingInstructions: '',
  890. testingImages: '',
  891. testingStatus: 0
  892. }] // 合格产品固定一个commonOrderList项
  893. }
  894. this.inspectResult.list.push(inspectItem)
  895. }
  896. if (!inspectItem) return
  897. if (type === 'qualified' && delta > 0) {
  898. inspectItem.qualifiedNum++
  899. // 合格产品不需要动态增加commonOrderList,保持固定一个
  900. } else if (type === 'qualified' && delta < 0) {
  901. inspectItem.qualifiedNum = Math.max(0, inspectItem.qualifiedNum - 1)
  902. // 合格产品不需要动态减少commonOrderList
  903. // 新增:如果减到0,移除该商品对象
  904. if (inspectItem.qualifiedNum === 0) {
  905. const idx = this.inspectResult.list.findIndex(listItem => listItem === inspectItem)
  906. if (idx !== -1) {
  907. this.inspectResult.list.splice(idx, 1)
  908. }
  909. return
  910. }
  911. }
  912. console.log('更新后的inspectResult:', JSON.stringify(this.inspectResult, null, 2))
  913. },
  914. loadMoreGoods() {
  915. const categoryId = this.categories[this.currentCategory]?.id
  916. // 不可回收和质量问题分类不支持加载更多
  917. if (categoryId === 'unrecyclable' || categoryId === 'quality_issue') {
  918. return
  919. }
  920. const page = (this.allProductsPage[categoryId] || 1) + 1
  921. const total = this.allProductsTotal[categoryId] || 0
  922. const loaded = (this.allProducts[categoryId] || []).length
  923. if (this.loadingMore || this.finished) return
  924. if (loaded < total) {
  925. this.loadingMore = true
  926. this.fetchGoodsList(categoryId, page, () => {
  927. this.loadingMore = false
  928. // 判断是否加载完
  929. const newLoaded = (this.allProducts[categoryId] || []).length
  930. this.finished = newLoaded >= (this.allProductsTotal[categoryId] || 0)
  931. })
  932. } else {
  933. this.finished = true
  934. }
  935. },
  936. // 格式化价格显示
  937. formatPrice(item) {
  938. const price = item.price
  939. const maxPrice = item.maxPrice
  940. // 如果两个价格都没有或都为0,显示占位符
  941. if ((!price || price === 0) && (!maxPrice || maxPrice === 0)) {
  942. return '¥ —'
  943. }
  944. // 如果只有一个价格有值
  945. if (price && (!maxPrice || maxPrice === 0)) {
  946. return `¥ ${price}`
  947. }
  948. if (maxPrice && (!price || price === 0)) {
  949. return `¥ ${maxPrice}`
  950. }
  951. // 如果两个价格都有值且不相等,显示价格范围
  952. if (price && maxPrice && price !== maxPrice) {
  953. const minPrice = Math.min(price, maxPrice)
  954. const maxPriceValue = Math.max(price, maxPrice)
  955. return `¥ ${minPrice} - ${maxPriceValue}`
  956. }
  957. // 如果两个价格相等,只显示一个
  958. return `¥ ${price || maxPrice}`
  959. },
  960. },
  961. created() {
  962. this.currentCategory = 0
  963. },
  964. onLoad(options) {
  965. // 接收订单数据
  966. if (options && options.orderData) {
  967. try {
  968. this.order = JSON.parse(decodeURIComponent(options.orderData))
  969. console.log('接收到的订单数据:', this.order)
  970. // 订单数据加载完成后初始化质检结果
  971. this.$nextTick(() => {
  972. this.initInspectResult()
  973. })
  974. } catch (error) {
  975. console.error('解析订单数据失败:', error)
  976. }
  977. }
  978. if (options && options.orderId) {
  979. this.orderId = options.orderId
  980. }
  981. // 初始化加载第一个分类的商品
  982. this.$nextTick(() => {
  983. // 确保categories已经计算完成
  984. if (this.categories.length > 0) {
  985. const firstCategoryId = this.categories[0]?.id
  986. console.log('第一个分类ID:', firstCategoryId, '所有分类:', this.categories.map(c => c.id))
  987. if (firstCategoryId && firstCategoryId !== 'unrecyclable' && firstCategoryId !== 'quality_issue') {
  988. this.fetchGoodsList(firstCategoryId, 1)
  989. } else if (firstCategoryId === 'unrecyclable' || firstCategoryId === 'quality_issue') {
  990. this.updateCurrentGoods()
  991. }
  992. } else {
  993. console.log('categories为空,等待数据加载')
  994. // 如果categories为空,等待一下再尝试
  995. setTimeout(() => {
  996. if (this.categories.length > 0) {
  997. const firstCategoryId = this.categories[0]?.id
  998. if (firstCategoryId && firstCategoryId !== 'unrecyclable' && firstCategoryId !== 'quality_issue') {
  999. this.fetchGoodsList(firstCategoryId, 1)
  1000. } else if (firstCategoryId === 'unrecyclable' || firstCategoryId === 'quality_issue') {
  1001. this.updateCurrentGoods()
  1002. }
  1003. }
  1004. }, 500)
  1005. }
  1006. })
  1007. console.log(this.orderId, 'orderId')
  1008. },
  1009. onShow() {
  1010. // 确保在页面显示时categories已经正确计算
  1011. console.log('onShow - categories:', this.categories.map(c => ({ id: c.id, title: c.title, badge: c.badge })))
  1012. // 强制更新视图,确保所有分类都显示
  1013. this.$nextTick(() => {
  1014. console.log('分类导航应该显示的分类数量:', this.categories.length)
  1015. this.categories.forEach((cat, index) => {
  1016. console.log(`分类 ${index}: ${cat.title} (${cat.id})`)
  1017. })
  1018. })
  1019. },
  1020. }
  1021. </script>
  1022. <style lang="scss" scoped>
  1023. .inspect-container {
  1024. min-height: 100vh;
  1025. background: #f8f8f8;
  1026. display: flex;
  1027. flex-direction: column;
  1028. }
  1029. .nav-bar {
  1030. display: flex;
  1031. align-items: center;
  1032. height: calc(150rpx + var(--status-bar-height));
  1033. padding: 0 32rpx;
  1034. padding-top: var(--status-bar-height);
  1035. background: #fff;
  1036. position: fixed;
  1037. top: 0;
  1038. left: 0;
  1039. right: 0;
  1040. z-index: 999;
  1041. box-sizing: border-box;
  1042. box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.03);
  1043. .back {
  1044. padding: 20rpx;
  1045. margin-left: -20rpx;
  1046. }
  1047. .nav-title {
  1048. flex: 1;
  1049. text-align: center;
  1050. font-size: 32rpx;
  1051. font-weight: 500;
  1052. color: #222;
  1053. }
  1054. .nav-icons {
  1055. display: flex;
  1056. align-items: center;
  1057. gap: 12px;
  1058. }
  1059. }
  1060. .main-content {
  1061. margin-top: calc(200rpx + var(--status-bar-height));
  1062. display: flex;
  1063. background: none;
  1064. height: calc(100vh - 200rpx - var(--status-bar-height));
  1065. min-height: calc(100vh - 200rpx - var(--status-bar-height));
  1066. }
  1067. .category-nav {
  1068. width: 160rpx;
  1069. background: #fff;
  1070. border-radius: 48rpx 0 0 48rpx;
  1071. // padding: 48rpx 0;
  1072. display: flex;
  1073. flex-direction: column;
  1074. align-items: center;
  1075. box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.03);
  1076. height: calc(100vh - 200rpx - var(--status-bar-height) - 160rpx);
  1077. max-height: calc(100vh - 200rpx - var(--status-bar-height) - 160rpx);
  1078. overflow-y: scroll;
  1079. overflow-x: hidden;
  1080. position: relative;
  1081. z-index: 2;
  1082. -webkit-overflow-scrolling: touch;
  1083. scrollbar-width: thin;
  1084. scrollbar-color: #ddd transparent;
  1085. &::-webkit-scrollbar {
  1086. width: 8rpx;
  1087. }
  1088. &::-webkit-scrollbar-track {
  1089. background: transparent;
  1090. }
  1091. &::-webkit-scrollbar-thumb {
  1092. background: #ddd;
  1093. border-radius: 4rpx;
  1094. }
  1095. &::-webkit-scrollbar-thumb:hover {
  1096. background: #ccc;
  1097. }
  1098. .category-item {
  1099. width: 128rpx;
  1100. height: 88rpx;
  1101. border-radius: 32rpx 0 0 32rpx;
  1102. display: flex;
  1103. align-items: center;
  1104. justify-content: flex-start;
  1105. font-size: 32rpx;
  1106. color: #222;
  1107. margin-bottom: 24rpx;
  1108. background: #fff;
  1109. position: relative;
  1110. transition: background 0.2s, color 0.2s, font-weight 0.2s;
  1111. padding-left: 24rpx;
  1112. &.active {
  1113. background: linear-gradient(90deg, #fff7e6 80%, #fff 100%);
  1114. color: #ffb400;
  1115. font-weight: bold;
  1116. &::before {
  1117. content: '';
  1118. position: absolute;
  1119. left: 0;
  1120. top: 30%;
  1121. height: 40%;
  1122. width: 4rpx;
  1123. border-radius: 8rpx;
  1124. background: #ffb400;
  1125. bottom: auto;
  1126. }
  1127. }
  1128. .category-badge {
  1129. position: absolute;
  1130. top: 12rpx;
  1131. right: 20rpx;
  1132. background: #ff4d4f;
  1133. color: #fff;
  1134. font-size: 24rpx;
  1135. border-radius: 50%;
  1136. width: 36rpx;
  1137. height: 36rpx;
  1138. display: flex;
  1139. align-items: center;
  1140. justify-content: center;
  1141. }
  1142. }
  1143. }
  1144. .goods-list {
  1145. flex: 1;
  1146. height: calc(100vh - 200rpx - var(--status-bar-height) - 160rpx);
  1147. padding: 0 0 0 32rpx;
  1148. overflow-y: auto;
  1149. background: none;
  1150. }
  1151. .goods-card {
  1152. background: #fff;
  1153. border-radius: 48rpx;
  1154. box-shadow: 0 8rpx 48rpx rgba(0, 0, 0, 0.06);
  1155. margin-bottom: 36rpx;
  1156. padding: 36rpx 36rpx 18rpx 36rpx;
  1157. }
  1158. .goods-header {
  1159. display: flex;
  1160. align-items: center;
  1161. margin-bottom: 24rpx;
  1162. .goods-img-container {
  1163. position: relative;
  1164. width: 112rpx;
  1165. height: 112rpx;
  1166. margin-right: 24rpx;
  1167. flex-shrink: 0;
  1168. }
  1169. .goods-img {
  1170. width: 100%;
  1171. height: 100%;
  1172. border-radius: 32rpx;
  1173. background: #f8f8f8;
  1174. object-fit: contain;
  1175. }
  1176. .brand-tag {
  1177. position: absolute;
  1178. top: 0rpx;
  1179. left: 0rpx;
  1180. background: rgba(0, 0, 0, 0.8);
  1181. color: #fff;
  1182. font-size: 20rpx;
  1183. padding: 4rpx 8rpx;
  1184. border-radius: 8rpx;
  1185. z-index: 2;
  1186. }
  1187. .goods-info {
  1188. flex: 1;
  1189. display: flex;
  1190. flex-direction: column;
  1191. justify-content: center;
  1192. min-width: 0;
  1193. .goods-title-row {
  1194. display: flex;
  1195. align-items: baseline;
  1196. justify-content: space-between;
  1197. .goods-name {
  1198. font-size: 28rpx;
  1199. font-weight: bold;
  1200. color: #222;
  1201. margin-right: 16rpx;
  1202. flex: 1;
  1203. overflow: hidden;
  1204. text-overflow: ellipsis;
  1205. white-space: nowrap;
  1206. }
  1207. .goods-price {
  1208. font-size: 30rpx;
  1209. color: #ffb400;
  1210. font-weight: bold;
  1211. white-space: nowrap;
  1212. flex-shrink: 0;
  1213. .goods-unit {
  1214. font-size: 26rpx;
  1215. color: #bbb;
  1216. }
  1217. }
  1218. }
  1219. .goods-desc {
  1220. font-size: 26rpx;
  1221. color: #999;
  1222. margin-top: 8rpx;
  1223. }
  1224. }
  1225. }
  1226. .goods-row {
  1227. display: flex;
  1228. align-items: center;
  1229. margin-bottom: 24rpx;
  1230. .row-label {
  1231. font-size: 28rpx;
  1232. color: #888;
  1233. width: 160rpx;
  1234. flex-shrink: 0;
  1235. }
  1236. .num-ctrl {
  1237. display: flex;
  1238. align-items: center;
  1239. .num-btn {
  1240. width: 60rpx;
  1241. height: 60rpx;
  1242. padding: 0;
  1243. margin: 0;
  1244. display: flex;
  1245. align-items: center;
  1246. justify-content: center;
  1247. font-size: 28rpx;
  1248. color: #666;
  1249. background: #ffffff;
  1250. border: none;
  1251. border-radius: 50%;
  1252. &::after {
  1253. border: none;
  1254. }
  1255. &:active {
  1256. opacity: 0.8;
  1257. }
  1258. }
  1259. .num {
  1260. width: 80rpx;
  1261. text-align: center;
  1262. font-size: 32rpx;
  1263. color: #333;
  1264. }
  1265. }
  1266. .amount-input {
  1267. flex: 1;
  1268. height: 64rpx;
  1269. border-radius: 24rpx;
  1270. background: #f6f6f6;
  1271. border: none;
  1272. font-size: 30rpx;
  1273. color: #222;
  1274. padding-left: 20rpx;
  1275. margin-left: 16rpx;
  1276. }
  1277. }
  1278. .footer-btns {
  1279. position: fixed;
  1280. left: 0;
  1281. right: 0;
  1282. bottom: 0;
  1283. background: #fff;
  1284. display: flex;
  1285. gap: 32rpx;
  1286. padding: 24rpx 32rpx 48rpx 32rpx;
  1287. z-index: 101;
  1288. .btn-outline {
  1289. flex: 1;
  1290. height: 80rpx;
  1291. border-radius: 32rpx;
  1292. border: 2rpx solid #ffe09a;
  1293. color: #ffb400;
  1294. background: #fff0d2;
  1295. font-size: 30rpx;
  1296. font-weight: 500;
  1297. box-shadow: none;
  1298. padding: 0 36rpx;
  1299. }
  1300. .btn-main {
  1301. flex: 1;
  1302. height: 80rpx;
  1303. border-radius: 32rpx;
  1304. background: linear-gradient(90deg, #ffd01e 0%, #ffac04 100%);
  1305. color: #fff;
  1306. border: none;
  1307. font-size: 30rpx;
  1308. font-weight: 500;
  1309. box-shadow: none;
  1310. padding: 0 36rpx;
  1311. }
  1312. }
  1313. .loading-more {
  1314. text-align: center;
  1315. color: #999;
  1316. padding: 20rpx 0;
  1317. font-size: 26rpx;
  1318. }
  1319. // 品牌款式显示样式
  1320. .selected-styles {
  1321. margin-top: 8rpx;
  1322. .style-item {
  1323. margin-bottom: 4rpx;
  1324. .style-text {
  1325. font-size: 22rpx;
  1326. color: #ff9c00;
  1327. background: #fff7e6;
  1328. padding: 2rpx 8rpx;
  1329. border-radius: 8rpx;
  1330. display: inline-block;
  1331. }
  1332. }
  1333. }
  1334. </style>