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

812 lines
24 KiB

1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month 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. <view class="goods-list">
  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">¥ {{ item.price }} <text class="goods-unit">/</text></text>
  31. </view>
  32. <text class="goods-desc">{{ item.desc }}</text>
  33. <text v-if="item.brand" class="goods-brand">品牌{{ item.brand }}</text>
  34. <text v-if="item.originalNum" class="goods-limit">总数量{{ item.originalNum }}</text>
  35. </view>
  36. </view>
  37. <view class="goods-row">
  38. <text class="row-label">合格数量</text>
  39. <view class="num-ctrl">
  40. <button class="num-btn" @tap="changeNum(item, 'qualified', -1)">-</button>
  41. <text class="num">{{ item.qualified }}</text>
  42. <button class="num-btn" @tap="changeNum(item, 'qualified', 1)">+</button>
  43. </view>
  44. </view>
  45. <view class="goods-row">
  46. <text class="row-label">不合格数量</text>
  47. <view class="num-ctrl">
  48. <button class="num-btn" @tap="changeNum(item, 'unqualified', -1)">-</button>
  49. <text class="num">{{ item.unqualified }}</text>
  50. <button class="num-btn" @tap="changeNum(item, 'unqualified', 1)">+</button>
  51. </view>
  52. </view>
  53. <view class="goods-row">
  54. <text class="row-label">总金额</text>
  55. <input class="amount-input" :value="getInspectPrice(item)" @input="updateInspectPrice(item, $event)" placeholder="请输入金额" />
  56. </view>
  57. </view>
  58. </view>
  59. </view>
  60. <!-- 底部操作按钮 -->
  61. <view class="footer-btns">
  62. <button class="btn-outline" @tap="goBack">返回订单详情</button>
  63. <button class="btn-main" @tap="goNext">下一步</button>
  64. </view>
  65. </view>
  66. </template>
  67. <script>
  68. export default {
  69. data() {
  70. return {
  71. statusBarHeight: 0,
  72. currentCategory: 0,
  73. orderId: '',
  74. order: null, // 订单数据
  75. currentGoods: [], // 当前显示的商品列表
  76. inspectResult: {}, // 质检结果对象,按照新的数据格式
  77. }
  78. },
  79. computed: {
  80. categories() {
  81. const list = getApp().globalData.pricePreviewList || []
  82. let filteredCategories = []
  83. // 如果有订单数据,根据订单商品过滤分类
  84. if (this.order && this.order.commonOrderList) {
  85. // 获取订单中所有商品的分类ID(去重)
  86. const orderCategoryIds = new Set()
  87. this.order.commonOrderList.forEach(item => {
  88. // 如果有shopClass字段直接使用
  89. if (item.shopClass) {
  90. orderCategoryIds.add(item.shopClass)
  91. } else {
  92. // 如果没有shopClass,通过商品标题匹配分类
  93. const matchedCategory = list.find(cat =>
  94. cat.pid === '0' && item.title && item.title.includes(cat.title)
  95. )
  96. if (matchedCategory) {
  97. orderCategoryIds.add(matchedCategory.id)
  98. }
  99. }
  100. })
  101. // 过滤出订单中包含的分类
  102. filteredCategories = list.filter(item =>
  103. item.pid === '0' && orderCategoryIds.has(item.id)
  104. ).sort((a, b) => a.sort - b.sort)
  105. // 如果没有匹配到任何分类,显示所有分类
  106. if (filteredCategories.length === 0) {
  107. filteredCategories = list.filter(item => item.pid === '0').sort((a, b) => a.sort - b.sort)
  108. }
  109. } else {
  110. // 没有订单数据时显示所有分类
  111. filteredCategories = list.filter(item => item.pid === '0').sort((a, b) => a.sort - b.sort)
  112. }
  113. // 新增不可回收分类
  114. const extra = [{ id: 'unrecyclable', title: '不可回收' }]
  115. return [...filteredCategories, ...extra]
  116. }
  117. },
  118. methods: {
  119. initInspectResult() {
  120. if (!this.order || !this.order.commonOrderList) return
  121. this.inspectResult = {
  122. id: this.order.id,
  123. list: []
  124. }
  125. // 按照订单商品分组(按originalId分组)
  126. const groupedGoods = {}
  127. this.order.commonOrderList.forEach(item => {
  128. if (!groupedGoods[item.id]) {
  129. groupedGoods[item.id] = {
  130. id: item.id,
  131. price: '', // 初始为空字符串
  132. qualifiedNum: 0,
  133. noQualifiedNum: 0,
  134. unrecyclable: 0,
  135. commonOrderList: []
  136. }
  137. }
  138. console.log('groupedGoods', groupedGoods)
  139. // 为每个数量创建对应的质检项
  140. for (let i = 0; i < (item.num || 0); i++) {
  141. // console.log('groupedGoods[item.id]', groupedGoods[item.id])
  142. groupedGoods[item.id].commonOrderList.push({
  143. id: `${item.commonOrderList[i].id}`, // 生成唯一ID
  144. testingInstructions: '',
  145. testingImages: '',
  146. testingStatus: '' // 默认为空
  147. })
  148. }
  149. })
  150. // 添加不可回收分类 - 暂时注释掉
  151. // const totalOrderNum = this.order.commonOrderList.reduce((sum, item) => sum + (item.num || 0), 0)
  152. // groupedGoods['unrecyclable'] = {
  153. // id: 'unrecyclable',
  154. // price: '',
  155. // qualifiedNum: 0,
  156. // noQualifiedNum: 0,
  157. // unrecyclable: totalOrderNum, // 初始化时全部为不可回收状态
  158. // commonOrderList: []
  159. // }
  160. // // 为不可回收创建对应数量的质检项
  161. // for (let i = 0; i < totalOrderNum; i++) {
  162. // groupedGoods['unrecyclable'].commonOrderList.push({
  163. // id: `unrecyclable-${i}`,
  164. // testingInstructions: '',
  165. // testingImages: '',
  166. // testingStatus: 2 // 不可回收状态
  167. // })
  168. // }
  169. this.inspectResult.list = Object.values(groupedGoods)
  170. },
  171. updateCurrentGoods() {
  172. const currentCategoryId = this.categories[this.currentCategory]?.id
  173. const currentCategoryTitle = this.categories[this.currentCategory]?.title
  174. // 不可回收分类内容
  175. if (currentCategoryId === 'unrecyclable') {
  176. // 计算订单中所有商品的总数量作为不可回收的最大限制
  177. let totalOrderNum = 0
  178. if (this.order && this.order.commonOrderList) {
  179. totalOrderNum = this.order.commonOrderList.reduce((sum, item) => sum + (item.num || 0), 0)
  180. }
  181. this.currentGoods = [{
  182. id: 'unrecyclable-1',
  183. image: '/static/回收/衣物.png',
  184. name: '不可回收品类',
  185. price: '—',
  186. desc: '允许脏破烂,160码以上',
  187. qualified: 0,
  188. unqualified: 0,
  189. amount: '',
  190. originalNum: totalOrderNum // 设置最大数量为订单总数
  191. }]
  192. return
  193. }
  194. // 如果有订单数据,根据订单商品过滤当前分类的商品
  195. if (this.order && this.order.commonOrderList) {
  196. const orderGoods = this.order.commonOrderList.filter(item => {
  197. // 如果有shopClass字段,直接匹配
  198. if (item.shopClass) {
  199. return item.shopClass === currentCategoryId
  200. }
  201. // 如果没有shopClass,通过商品标题匹配分类
  202. return item.title && currentCategoryTitle && item.title.includes(currentCategoryTitle)
  203. })
  204. // 根据pinName展示不同品牌的商品,不进行去重
  205. const goodsList = orderGoods.map((item, index) => ({
  206. id: `${item.id}`,
  207. image: item.image || '/static/回收/衣物.png',
  208. name: item.title,
  209. brand: item.pinName || '未知品牌',
  210. price: item.onePrice || 0,
  211. desc: item.details || '',
  212. qualified: 0,
  213. unqualified: 0,
  214. amount: '',
  215. originalNum: item.num || 0,
  216. estimatedPrice: item.price || 0,
  217. originalId: item.id // 保存原始ID
  218. }))
  219. this.currentGoods = goodsList
  220. return
  221. }
  222. // 没有订单数据时返回空数组
  223. this.currentGoods = []
  224. },
  225. goBack() {
  226. uni.navigateBack()
  227. },
  228. goNext() {
  229. // 检测是否所有商品都已完成质检和填写价格
  230. const validationResult = this.validateInspectData()
  231. if (!validationResult.isValid) {
  232. uni.showToast({
  233. title: validationResult.message,
  234. icon: 'none',
  235. duration: 2000
  236. })
  237. return
  238. }
  239. // 构造传递给步骤二的完整数据
  240. const resultData = {
  241. inspectResult: this.inspectResult,
  242. order: this.order // 同时传递订单信息
  243. }
  244. const resultDataStr = encodeURIComponent(JSON.stringify(resultData))
  245. uni.navigateTo({
  246. url: `/pages/manager/inspect-result?resultData=${resultDataStr}`
  247. })
  248. },
  249. validateInspectData() {
  250. if (!this.inspectResult.list || this.inspectResult.list.length === 0) {
  251. return {
  252. isValid: false,
  253. message: '没有质检数据'
  254. }
  255. }
  256. for (const item of this.inspectResult.list) {
  257. // 跳过不可回收分类的检查
  258. if (item.id === 'unrecyclable') {
  259. continue
  260. }
  261. // 获取商品信息用于显示错误消息
  262. const orderItem = this.order.commonOrderList.find(orderGoods => orderGoods.id == item.id)
  263. const brandName = orderItem ? (orderItem.title+' '+orderItem.pinName || orderItem.title || '未知商品') : '未知商品'
  264. // 检查是否有空的testingStatus
  265. const hasEmptyStatus = item.commonOrderList.some(commonItem =>
  266. commonItem.testingStatus === '' || commonItem.testingStatus === null || commonItem.testingStatus === undefined
  267. )
  268. if (hasEmptyStatus) {
  269. return {
  270. isValid: false,
  271. message: `${brandName} 还未完成质检选择`
  272. }
  273. }
  274. // 检查价格是否为空
  275. if (!item.price || item.price === 0 || item.price === '') {
  276. return {
  277. isValid: false,
  278. message: `${brandName} 还未填写总金额`
  279. }
  280. }
  281. }
  282. return {
  283. isValid: true,
  284. message: ''
  285. }
  286. },
  287. switchCategory(idx) {
  288. this.currentCategory = idx
  289. this.updateCurrentGoods()
  290. },
  291. changeNum(item, key, delta) {
  292. const currentQualified = item.qualified || 0
  293. const currentUnqualified = item.unqualified || 0
  294. const maxNum = item.originalNum || 0
  295. if (key === 'qualified') {
  296. const newQualified = Math.max(0, currentQualified + delta)
  297. const totalAfterChange = newQualified + currentUnqualified
  298. // 检查总数是否超过原始数量
  299. if (totalAfterChange <= maxNum) {
  300. this.$set(item, 'qualified', newQualified)
  301. // 更新inspectResult对象
  302. this.updateInspectResult(item, 'qualified', delta)
  303. console.log('更新后的inspectResult:', JSON.stringify(this.inspectResult, null, 2))
  304. } else {
  305. uni.showToast({
  306. title: `总数不能超过${maxNum}`,
  307. icon: 'none',
  308. duration: 1500
  309. })
  310. }
  311. } else if (key === 'unqualified') {
  312. const newUnqualified = Math.max(0, currentUnqualified + delta)
  313. const totalAfterChange = currentQualified + newUnqualified
  314. // 检查总数是否超过原始数量
  315. if (totalAfterChange <= maxNum) {
  316. this.$set(item, 'unqualified', newUnqualified)
  317. // 更新inspectResult对象
  318. this.updateInspectResult(item, 'unqualified', delta)
  319. } else {
  320. uni.showToast({
  321. title: `总数不能超过${maxNum}`,
  322. icon: 'none',
  323. duration: 1500
  324. })
  325. }
  326. }
  327. },
  328. updateInspectResult(item, type, delta) {
  329. // 处理不可回收分类 - 暂时注释掉
  330. // if (item.id === 'unrecyclable-1') {
  331. // const unrecyclableItem = this.inspectResult.list.find(listItem => listItem.id === 'unrecyclable')
  332. // if (!unrecyclableItem) return
  333. // if (type === 'qualified' && delta > 0) {
  334. // // 增加合格数量:找到第一个不可回收状态的项改为合格
  335. // const targetItem = unrecyclableItem.commonOrderList.find(commonItem => commonItem.testingStatus === 2)
  336. // if (targetItem) {
  337. // targetItem.testingStatus = 0
  338. // unrecyclableItem.unrecyclable--
  339. // unrecyclableItem.qualifiedNum++
  340. // }
  341. // } else if (type === 'qualified' && delta < 0) {
  342. // // 减少合格数量:找到第一个合格状态的项改为不可回收
  343. // const targetItem = unrecyclableItem.commonOrderList.find(commonItem => commonItem.testingStatus === 0)
  344. // if (targetItem) {
  345. // targetItem.testingStatus = 2
  346. // unrecyclableItem.qualifiedNum--
  347. // unrecyclableItem.unrecyclable++
  348. // }
  349. // } else if (type === 'unqualified' && delta > 0) {
  350. // // 增加不合格数量:找到第一个不可回收状态的项改为质量问题
  351. // const targetItem = unrecyclableItem.commonOrderList.find(commonItem => commonItem.testingStatus === 2)
  352. // if (targetItem) {
  353. // targetItem.testingStatus = 1
  354. // unrecyclableItem.unrecyclable--
  355. // unrecyclableItem.noQualifiedNum++
  356. // }
  357. // } else if (type === 'unqualified' && delta < 0) {
  358. // // 减少不合格数量:找到第一个质量问题状态的项改为不可回收
  359. // const targetItem = unrecyclableItem.commonOrderList.find(commonItem => commonItem.testingStatus === 1)
  360. // if (targetItem) {
  361. // targetItem.testingStatus = 2
  362. // unrecyclableItem.noQualifiedNum--
  363. // unrecyclableItem.unrecyclable++
  364. // }
  365. // }
  366. // console.log('更新后的不可回收inspectResult:', JSON.stringify(unrecyclableItem, null, 2))
  367. // return
  368. // }
  369. // 找到对应的inspectResult项
  370. const originalId = item.originalId || item.id.split('-')[0]
  371. const inspectItem = this.inspectResult.list.find(listItem => listItem.id == originalId)
  372. if (!inspectItem) return
  373. if (type === 'qualified' && delta > 0) {
  374. // 增加合格数量:优先找空状态的项,其次找非合格状态的项
  375. let targetItem = inspectItem.commonOrderList.find(commonItem => commonItem.testingStatus === '')
  376. if (!targetItem) {
  377. targetItem = inspectItem.commonOrderList.find(commonItem =>
  378. commonItem.testingStatus === 1 || commonItem.testingStatus === 2
  379. )
  380. }
  381. if (targetItem) {
  382. const oldStatus = targetItem.testingStatus
  383. targetItem.testingStatus = 0
  384. inspectItem.qualifiedNum++
  385. if (oldStatus === 1) {
  386. inspectItem.noQualifiedNum--
  387. } else if (oldStatus === 2) {
  388. inspectItem.unrecyclable--
  389. }
  390. }
  391. } else if (type === 'qualified' && delta < 0) {
  392. // 减少合格数量:找到第一个合格状态的项改为空状态
  393. const targetItem = inspectItem.commonOrderList.find(commonItem => commonItem.testingStatus === 0)
  394. if (targetItem) {
  395. targetItem.testingStatus = ''
  396. inspectItem.qualifiedNum--
  397. }
  398. } else if (type === 'unqualified' && delta > 0) {
  399. // 增加不合格数量:优先找空状态的项,其次找合格状态的项
  400. let targetItem = inspectItem.commonOrderList.find(commonItem => commonItem.testingStatus === '')
  401. if (!targetItem) {
  402. targetItem = inspectItem.commonOrderList.find(commonItem => commonItem.testingStatus === 0)
  403. }
  404. if (targetItem) {
  405. const oldStatus = targetItem.testingStatus
  406. targetItem.testingStatus = 1
  407. inspectItem.noQualifiedNum++
  408. if (oldStatus === 0) {
  409. inspectItem.qualifiedNum--
  410. }
  411. }
  412. } else if (type === 'unqualified' && delta < 0) {
  413. // 减少不合格数量:找到第一个质量问题状态的项改为空状态
  414. const targetItem = inspectItem.commonOrderList.find(commonItem => commonItem.testingStatus === 1)
  415. if (targetItem) {
  416. targetItem.testingStatus = ''
  417. inspectItem.noQualifiedNum--
  418. }
  419. }
  420. console.log('更新后的inspectResult:', JSON.stringify(this.inspectResult, null, 2))
  421. },
  422. getInspectPrice(item) {
  423. // 获取inspectResult中对应商品的price
  424. if (item.id === 'unrecyclable-1') {
  425. return ''
  426. }
  427. const originalId = item.originalId || item.id.split('-')[0]
  428. const inspectItem = this.inspectResult.list?.find(listItem => listItem.id == originalId)
  429. return inspectItem ? inspectItem.price : ''
  430. },
  431. updateInspectPrice(item, event) {
  432. // 更新inspectResult中对应商品的price
  433. if (item.id === 'unrecyclable-1') {
  434. return
  435. }
  436. const originalId = item.originalId || item.id.split('-')[0]
  437. const inspectItem = this.inspectResult.list?.find(listItem => listItem.id == originalId)
  438. if (inspectItem) {
  439. const newPrice = parseFloat(event.detail.value) || 0
  440. inspectItem.price = newPrice
  441. console.log('更新价格:', originalId, newPrice)
  442. }
  443. },
  444. },
  445. created() {
  446. this.currentCategory = 0
  447. },
  448. onLoad(options) {
  449. // 接收订单数据
  450. if (options && options.orderData) {
  451. try {
  452. this.order = JSON.parse(decodeURIComponent(options.orderData))
  453. console.log('接收到的订单数据:', this.order)
  454. // 订单数据加载完成后更新商品列表和初始化质检结果
  455. this.$nextTick(() => {
  456. this.initInspectResult()
  457. this.updateCurrentGoods()
  458. })
  459. } catch (error) {
  460. console.error('解析订单数据失败:', error)
  461. }
  462. }
  463. if (options && options.orderId) {
  464. this.orderId = options.orderId
  465. }
  466. console.log(this.orderId, 'orderId')
  467. },
  468. }
  469. </script>
  470. <style lang="scss" scoped>
  471. .inspect-container {
  472. min-height: 100vh;
  473. background: #f8f8f8;
  474. display: flex;
  475. flex-direction: column;
  476. }
  477. .nav-bar {
  478. display: flex;
  479. align-items: center;
  480. height: calc(150rpx + var(--status-bar-height));
  481. padding: 0 32rpx;
  482. padding-top: var(--status-bar-height);
  483. background: #fff;
  484. position: fixed;
  485. top: 0;
  486. left: 0;
  487. right: 0;
  488. z-index: 999;
  489. box-sizing: border-box;
  490. box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.03);
  491. .back {
  492. padding: 20rpx;
  493. margin-left: -20rpx;
  494. }
  495. .nav-title {
  496. flex: 1;
  497. text-align: center;
  498. font-size: 32rpx;
  499. font-weight: 500;
  500. color: #222;
  501. }
  502. .nav-icons {
  503. display: flex;
  504. align-items: center;
  505. gap: 12px;
  506. }
  507. }
  508. .main-content {
  509. margin-top: calc(200rpx + var(--status-bar-height));
  510. display: flex;
  511. background: none;
  512. }
  513. .category-nav {
  514. width: 80px;
  515. background: #fff;
  516. border-radius: 24px 0 0 24px;
  517. padding: 24px 0;
  518. display: flex;
  519. flex-direction: column;
  520. align-items: center;
  521. box-shadow: 0 2px 8px rgba(0, 0, 0, 0.03);
  522. height: 100%;
  523. overflow-y: auto;
  524. position: relative;
  525. z-index: 2;
  526. .category-item {
  527. width: 64px;
  528. height: 44px;
  529. border-radius: 16px 0 0 16px;
  530. display: flex;
  531. align-items: center;
  532. justify-content: flex-start;
  533. font-size: 16px;
  534. color: #222;
  535. margin-bottom: 12px;
  536. background: #fff;
  537. position: relative;
  538. transition: background 0.2s, color 0.2s, font-weight 0.2s;
  539. padding-left: 12px;
  540. &.active {
  541. background: linear-gradient(90deg, #fff7e6 80%, #fff 100%);
  542. color: #ffb400;
  543. font-weight: bold;
  544. &::before {
  545. content: '';
  546. position: absolute;
  547. left: 0;
  548. top: 30%;
  549. height: 40%;
  550. width: 2px;
  551. border-radius: 4px;
  552. background: #ffb400;
  553. bottom: auto;
  554. }
  555. }
  556. .category-badge {
  557. position: absolute;
  558. top: 6px;
  559. right: 10px;
  560. background: #ff4d4f;
  561. color: #fff;
  562. font-size: 12px;
  563. border-radius: 50%;
  564. width: 18px;
  565. height: 18px;
  566. display: flex;
  567. align-items: center;
  568. justify-content: center;
  569. }
  570. }
  571. }
  572. .goods-list {
  573. flex: 1;
  574. height: calc(100vh - 110rpx - var(--status-bar-height) - 80px);
  575. padding: 0 0 0 16px;
  576. overflow-y: auto;
  577. background: none;
  578. }
  579. .goods-card {
  580. background: #fff;
  581. border-radius: 24px;
  582. box-shadow: 0 4px 24px rgba(0, 0, 0, 0.06);
  583. margin-bottom: 18px;
  584. padding: 18px 18px 9px 18px;
  585. }
  586. .goods-header {
  587. display: flex;
  588. align-items: center;
  589. margin-bottom: 12px;
  590. .goods-img {
  591. width: 56px;
  592. height: 56px;
  593. border-radius: 16px;
  594. margin-right: 12px;
  595. background: #f8f8f8;
  596. object-fit: contain;
  597. }
  598. .goods-info {
  599. flex: 1;
  600. display: flex;
  601. flex-direction: column;
  602. justify-content: center;
  603. min-width: 0;
  604. .goods-title-row {
  605. display: flex;
  606. align-items: baseline;
  607. .goods-name {
  608. font-size: 16px;
  609. font-weight: bold;
  610. color: #222;
  611. margin-right: 8px;
  612. }
  613. .goods-price {
  614. font-size: 15px;
  615. color: #ffb400;
  616. font-weight: bold;
  617. .goods-unit {
  618. font-size: 13px;
  619. color: #bbb;
  620. }
  621. }
  622. }
  623. .goods-desc {
  624. font-size: 13px;
  625. color: #999;
  626. margin-top: 4px;
  627. }
  628. }
  629. }
  630. .goods-row {
  631. display: flex;
  632. align-items: center;
  633. margin-bottom: 12px;
  634. .row-label {
  635. font-size: 14px;
  636. color: #888;
  637. width: 80px;
  638. flex-shrink: 0;
  639. }
  640. .num-ctrl {
  641. display: flex;
  642. align-items: center;
  643. .num-btn {
  644. width: 60rpx;
  645. height: 60rpx;
  646. padding: 0;
  647. margin: 0;
  648. display: flex;
  649. align-items: center;
  650. justify-content: center;
  651. font-size: 28rpx;
  652. color: #666;
  653. background: #ffffff;
  654. border: none;
  655. border-radius: 50%;
  656. &::after {
  657. border: none;
  658. }
  659. &:active {
  660. opacity: 0.8;
  661. }
  662. }
  663. .num {
  664. width: 80rpx;
  665. text-align: center;
  666. font-size: 32rpx;
  667. color: #333;
  668. }
  669. }
  670. .amount-input {
  671. flex: 1;
  672. height: 32px;
  673. border-radius: 12px;
  674. background: #f6f6f6;
  675. border: none;
  676. font-size: 15px;
  677. color: #222;
  678. padding-left: 10px;
  679. margin-left: 8px;
  680. }
  681. }
  682. .footer-btns {
  683. position: fixed;
  684. left: 0;
  685. right: 0;
  686. bottom: 0;
  687. background: #fff;
  688. display: flex;
  689. gap: 16px;
  690. padding: 12px 16px 24px 16px;
  691. z-index: 101;
  692. .btn-outline {
  693. flex: 1;
  694. height: 40px;
  695. border-radius: 16px;
  696. border: 1px solid #ffe09a;
  697. color: #ffb400;
  698. background: #fff0d2;
  699. font-size: 15px;
  700. font-weight: 500;
  701. box-shadow: none;
  702. padding: 0 18px;
  703. }
  704. .btn-main {
  705. flex: 1;
  706. height: 40px;
  707. border-radius: 16px;
  708. background: linear-gradient(90deg, #ffd01e 0%, #ffac04 100%);
  709. color: #fff;
  710. border: none;
  711. font-size: 15px;
  712. font-weight: 500;
  713. box-shadow: none;
  714. padding: 0 18px;
  715. }
  716. }
  717. .goods-brand {
  718. font-size: 12px;
  719. color: #ffb400;
  720. margin-top: 2px;
  721. font-weight: 500;
  722. }
  723. .goods-limit {
  724. font-size: 12px;
  725. color: #ffb400;
  726. margin-top: 2px;
  727. font-weight: 500;
  728. }
  729. </style>