爱简收旧衣按件回收前端代码仓库
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.

1447 lines
46 KiB

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