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

3 months ago
3 months ago
3 months 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
3 months ago
3 months 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
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
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. <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>