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

524 lines
14 KiB

3 weeks ago
6 days ago
3 weeks ago
3 weeks ago
3 weeks ago
3 weeks ago
6 days ago
3 weeks ago
6 days ago
3 weeks ago
6 days ago
3 weeks ago
6 days ago
3 weeks ago
6 days ago
3 weeks ago
6 days ago
3 weeks ago
6 days ago
3 weeks ago
6 days ago
3 weeks ago
6 days ago
3 weeks ago
  1. <template>
  2. <view class="inspect-result-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="more" size="24" color="#222" />
  11. </view>
  12. </view>
  13. <view class="main-content">
  14. <!-- 合格产品卡片 -->
  15. <view class="result-card">
  16. <view class="card-title">合格产品</view>
  17. <view v-for="item in qualifiedList" :key="item.id" class="result-row">
  18. <view class="row-main">
  19. <text class="row-name">{{item.name}}</text>
  20. <text class="row-price">¥ {{item.price}} <text class="row-unit">/</text></text>
  21. <text class="row-count">x{{item.count}}</text>
  22. <text class="row-total">¥{{item.total}}</text>
  23. </view>
  24. <view class="row-reason">
  25. <text class="reason-label">理由填写</text>
  26. <input class="reason-input" v-model="item.reason" placeholder="请选择理由(选填)" />
  27. </view>
  28. </view>
  29. </view>
  30. <!-- 不合格产品卡片 -->
  31. <view class="result-card">
  32. <view class="card-title">不合格产品</view>
  33. <view v-for="group in unqualifiedGroups" :key="group.name" class="result-group">
  34. <view class="row-main">
  35. <text class="row-name">{{group.name}}</text>
  36. <text class="row-price">¥ {{group.price}} <text class="row-unit">/</text></text>
  37. <text class="row-total">¥{{group.total}}</text>
  38. </view>
  39. <view v-for="item in group.items" :key="item.id" class="row-reason">
  40. <text class="reason-label">{{item.name}}</text>
  41. <view class="reason-select" @tap="selectReason(item)">
  42. <text class="reason-placeholder">请选择理由</text>
  43. <uni-icons type="right" size="18" color="#bbb" />
  44. </view>
  45. </view>
  46. </view>
  47. </view>
  48. <!-- 不可回收产品卡片 -->
  49. <view class="result-card">
  50. <view class="card-title">不可回收产品</view>
  51. <view v-for="item in unrecyclableList" :key="item.id" class="result-row">
  52. <view class="row-main">
  53. <text class="row-name">{{item.name}}</text>
  54. <text class="row-price">¥ {{item.price || '—'}} <text class="row-unit">/</text></text>
  55. <text class="row-count">x{{item.count}}</text>
  56. <text class="row-total">¥{{item.total}}</text>
  57. </view>
  58. <view class="row-reason">
  59. <text class="reason-label">理由填写</text>
  60. <input class="reason-input" v-model="item.reason" placeholder="请选择理由(选填)" />
  61. </view>
  62. </view>
  63. </view>
  64. <!-- 回收信息卡片 -->
  65. <view class="result-card info-card">
  66. <view class="card-title-row">
  67. <text class="card-title">回收信息</text>
  68. <view class="status-tag">待质检</view>
  69. </view>
  70. <view class="info-row">
  71. <text class="info-label">订单编号</text>
  72. <text class="info-value copy-btn">RE82738127861525 复制</text>
  73. </view>
  74. <view class="info-row">
  75. <text class="info-label">取件时间</text>
  76. <text class="info-value">2025-03-20 11:00</text>
  77. </view>
  78. </view>
  79. </view>
  80. <!-- 底部操作按钮 -->
  81. <view class="footer-btns">
  82. <button class="btn-outline" @tap="goPrev">上一步</button>
  83. <button class="btn-main" @tap="finishInspect">完成质检</button>
  84. </view>
  85. <!-- 理由弹窗 -->
  86. <uni-popup ref="reasonPopup" type="bottom" :mask-click="false">
  87. <view class="reason-popup">
  88. <view class="popup-header">
  89. <text class="popup-close" @tap="closeReasonPopup">关闭</text>
  90. <text class="popup-title">{{ currentReasonTitle }}</text>
  91. </view>
  92. <view class="popup-section">
  93. <text class="section-label">上传图片</text>
  94. <view class="img-list">
  95. <view v-for="(img, idx) in reasonImages" :key="idx" class="img-item">
  96. <image :src="img" class="img" />
  97. <view class="img-del" @tap="removeReasonImg(idx)">×</view>
  98. </view>
  99. <view class="img-item add" @tap="addReasonImg">
  100. <uni-icons type="plusempty" size="40" color="#bbb" />
  101. </view>
  102. </view>
  103. </view>
  104. <view class="popup-section">
  105. <text class="section-label">选择理由</text>
  106. <view v-for="(item, idx) in reasonOptions" :key="item" class="reason-row" @tap="toggleReason(idx)">
  107. <view :class="['checkbox', {checked: reasonChecked[idx]}]" />
  108. <text class="reason-text">{{ item }}</text>
  109. </view>
  110. </view>
  111. <button class="popup-save-btn" @tap="saveReason">保存</button>
  112. </view>
  113. </uni-popup>
  114. </view>
  115. </template>
  116. <script>
  117. import pullRefreshMixin from '../mixins/pullRefreshMixin.js'
  118. export default {
  119. mixins: [pullRefreshMixin],
  120. data() {
  121. return {
  122. qualifiedList: [
  123. { id: 1, name: '羽绒服', price: 8, count: 8, total: 64, reason: '' }
  124. ],
  125. unqualifiedGroups: [
  126. {
  127. name: '羽绒服', price: 8, total: 0,
  128. items: [
  129. { id: 11, name: '羽绒服1', reason: '' },
  130. { id: 12, name: '羽绒服2', reason: '' },
  131. { id: 13, name: '羽绒服3', reason: '' },
  132. { id: 14, name: '羽绒服4', reason: '' },
  133. { id: 15, name: '羽绒服5', reason: '' },
  134. { id: 16, name: '羽绒服6', reason: '' },
  135. { id: 17, name: '羽绒服7', reason: '' },
  136. { id: 18, name: '羽绒服8', reason: '' }
  137. ]
  138. },
  139. {
  140. name: '品牌服饰', price: 8, total: 0,
  141. items: [
  142. { id: 21, name: '品牌服饰1', reason: '' }
  143. ]
  144. }
  145. ],
  146. unrecyclableList: [
  147. { id: 31, name: '毛衣', price: '', count: 8, total: 0, reason: '' }
  148. ],
  149. reasonPopupVisible: false,
  150. currentReasonTitle: '',
  151. reasonImages: [],
  152. reasonOptions: ['大面积破损', '不可回收', '顽固污渍', '污渍无法清除', '异味严重', '带有危险物品'],
  153. reasonChecked: [false, true, false, true, false, false],
  154. currentReasonItem: null
  155. }
  156. },
  157. methods: {
  158. goBack() {
  159. uni.navigateBack()
  160. },
  161. goPrev() {
  162. uni.navigateBack()
  163. },
  164. finishInspect() {
  165. uni.showToast({ title: '完成质检', icon: 'success' })
  166. },
  167. selectReason(item) {
  168. this.currentReasonItem = item
  169. this.currentReasonTitle = item.name
  170. this.reasonImages = item.images || []
  171. this.reasonChecked = item.reasons || Array(this.reasonOptions.length).fill(false)
  172. this.$refs.reasonPopup.open()
  173. },
  174. closeReasonPopup() {
  175. this.$refs.reasonPopup.close()
  176. },
  177. addReasonImg() {
  178. uni.chooseImage({
  179. count: 3 - this.reasonImages.length,
  180. success: res => {
  181. this.reasonImages = this.reasonImages.concat(res.tempFilePaths)
  182. }
  183. })
  184. },
  185. removeReasonImg(idx) {
  186. this.reasonImages.splice(idx, 1)
  187. },
  188. toggleReason(idx) {
  189. this.$set(this.reasonChecked, idx, !this.reasonChecked[idx])
  190. },
  191. saveReason() {
  192. // 保存到当前item
  193. if (this.currentReasonItem) {
  194. this.currentReasonItem.images = [...this.reasonImages]
  195. this.currentReasonItem.reasons = [...this.reasonChecked]
  196. }
  197. this.closeReasonPopup()
  198. },
  199. async onRefresh() {
  200. await this.refreshData && this.refreshData()
  201. },
  202. refreshData() {
  203. // 可根据实际需求刷新质检结果数据
  204. // 例如重新请求接口或重置数据
  205. }
  206. }
  207. }
  208. </script>
  209. <style lang="scss" scoped>
  210. .inspect-result-container {
  211. min-height: 100vh;
  212. background: #f8f8f8;
  213. display: flex;
  214. flex-direction: column;
  215. }
  216. .nav-bar {
  217. display: flex;
  218. align-items: center;
  219. height: calc(150rpx + var(--status-bar-height));
  220. padding: 0 32rpx;
  221. padding-top: var(--status-bar-height);
  222. background: #fff;
  223. position: fixed;
  224. top: 0;
  225. left: 0;
  226. right: 0;
  227. z-index: 999;
  228. box-sizing: border-box;
  229. box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.03);
  230. .back {
  231. padding: 20rpx;
  232. margin-left: -20rpx;
  233. }
  234. .nav-title {
  235. flex: 1;
  236. text-align: center;
  237. font-size: 32rpx;
  238. font-weight: 500;
  239. color: #222;
  240. }
  241. .nav-icons {
  242. display: flex;
  243. align-items: center;
  244. gap: 12px;
  245. }
  246. }
  247. .main-content {
  248. margin-top: calc(150rpx + var(--status-bar-height));
  249. display: flex;
  250. flex-direction: column;
  251. background: none;
  252. padding-bottom: 120px;
  253. }
  254. .result-card {
  255. background: #fff;
  256. border-radius: 24px;
  257. box-shadow: 0 4px 24px rgba(0,0,0,0.06);
  258. margin: 0 24px 24px 24px;
  259. padding: 24px 24px 0 24px;
  260. }
  261. .card-title {
  262. font-size: 18px;
  263. font-weight: bold;
  264. color: #222;
  265. margin-bottom: 18px;
  266. }
  267. .card-title-row {
  268. display: flex;
  269. align-items: center;
  270. justify-content: space-between;
  271. margin-bottom: 18px;
  272. }
  273. .status-tag {
  274. background: #fff7e6;
  275. color: #ffb400;
  276. font-size: 14px;
  277. border-radius: 12px;
  278. padding: 2px 14px;
  279. font-weight: 400;
  280. height: 22px;
  281. display: flex;
  282. align-items: center;
  283. }
  284. .result-row, .result-group {
  285. margin-bottom: 18px;
  286. }
  287. .row-main {
  288. display: flex;
  289. align-items: center;
  290. .row-name {
  291. font-size: 16px;
  292. font-weight: bold;
  293. color: #222;
  294. margin-right: 8px;
  295. }
  296. .row-price {
  297. font-size: 15px;
  298. color: #ffb400;
  299. font-weight: bold;
  300. margin-right: 8px;
  301. .row-unit {
  302. font-size: 13px;
  303. color: #bbb;
  304. }
  305. }
  306. .row-count {
  307. font-size: 15px;
  308. color: #888;
  309. margin-right: 8px;
  310. }
  311. .row-total {
  312. font-size: 16px;
  313. color: #222;
  314. font-weight: bold;
  315. margin-left: auto;
  316. }
  317. }
  318. .row-reason {
  319. display: flex;
  320. align-items: center;
  321. margin-top: 8px;
  322. .reason-label {
  323. font-size: 15px;
  324. color: #bbb;
  325. min-width: 80px;
  326. }
  327. .reason-input {
  328. flex: 1;
  329. height: 40px;
  330. border-radius: 12px;
  331. background: #f6f6f6;
  332. border: none;
  333. font-size: 16px;
  334. color: #222;
  335. padding-left: 12px;
  336. margin-left: 8px;
  337. }
  338. .reason-select {
  339. flex: 1;
  340. display: flex;
  341. align-items: center;
  342. height: 40px;
  343. border-radius: 12px;
  344. background: #f6f6f6;
  345. font-size: 16px;
  346. color: #bbb;
  347. padding-left: 12px;
  348. margin-left: 8px;
  349. justify-content: space-between;
  350. }
  351. .reason-placeholder {
  352. color: #bbb;
  353. font-size: 16px;
  354. }
  355. }
  356. .info-card {
  357. background: #fff;
  358. border-radius: 24px;
  359. box-shadow: 0 4px 24px rgba(0,0,0,0.06);
  360. margin: 0 24px 24px 24px;
  361. padding: 24px 24px 0 24px;
  362. }
  363. .info-row {
  364. display: flex;
  365. align-items: center;
  366. margin-bottom: 16px;
  367. .info-label {
  368. font-size: 15px;
  369. color: #bbb;
  370. min-width: 80px;
  371. }
  372. .info-value {
  373. font-size: 15px;
  374. color: #222;
  375. margin-left: 8px;
  376. }
  377. .copy-btn {
  378. color: #ffb400;
  379. margin-left: 8px;
  380. }
  381. }
  382. .footer-btns {
  383. position: fixed;
  384. left: 0;
  385. right: 0;
  386. bottom: 0;
  387. background: #fff;
  388. display: flex;
  389. gap: 16px;
  390. padding: 12px 16px 24px 16px;
  391. z-index: 101;
  392. .btn-outline {
  393. flex: 1;
  394. height: 40px;
  395. border-radius: 16px;
  396. border: 1px solid #ffe09a;
  397. color: #ffb400;
  398. background: #fff0d2;
  399. font-size: 15px;
  400. font-weight: 500;
  401. box-shadow: none;
  402. padding: 0 18px;
  403. }
  404. .btn-main {
  405. flex: 1;
  406. height: 40px;
  407. border-radius: 16px;
  408. background: linear-gradient(90deg, #ffd01e 0%, #ffac04 100%);
  409. color: #fff;
  410. border: none;
  411. font-size: 15px;
  412. font-weight: 500;
  413. box-shadow: none;
  414. padding: 0 18px;
  415. }
  416. }
  417. .reason-popup {
  418. background: #fff;
  419. border-radius: 32px 32px 0 0;
  420. padding: 0 0 24px 0;
  421. .popup-header {
  422. display: flex;
  423. align-items: center;
  424. justify-content: center;
  425. height: 56px;
  426. border-bottom: 1px solid #f5f5f5;
  427. position: relative;
  428. .popup-close {
  429. position: absolute;
  430. left: 24px;
  431. color: #888;
  432. font-size: 18px;
  433. }
  434. .popup-title {
  435. font-size: 20px;
  436. font-weight: bold;
  437. color: #222;
  438. }
  439. }
  440. .popup-section {
  441. padding: 24px 24px 0 24px;
  442. .section-label {
  443. font-size: 16px;
  444. color: #888;
  445. margin-bottom: 12px;
  446. display: block;
  447. }
  448. .img-list {
  449. display: flex;
  450. gap: 12px;
  451. margin-bottom: 16px;
  452. .img-item {
  453. width: 80px;
  454. height: 80px;
  455. border-radius: 16px;
  456. background: #f6f6f6;
  457. position: relative;
  458. .img {
  459. width: 100%;
  460. height: 100%;
  461. border-radius: 16px;
  462. }
  463. .img-del {
  464. position: absolute;
  465. top: 4px;
  466. right: 4px;
  467. width: 20px;
  468. height: 20px;
  469. background: rgba(0,0,0,0.3);
  470. color: #fff;
  471. border-radius: 50%;
  472. text-align: center;
  473. line-height: 20px;
  474. font-size: 16px;
  475. }
  476. &.add {
  477. display: flex;
  478. align-items: center;
  479. justify-content: center;
  480. background: #f6f6f6;
  481. color: #bbb;
  482. }
  483. }
  484. }
  485. .reason-row {
  486. display: flex;
  487. align-items: center;
  488. padding: 18px 0;
  489. border-bottom: 1px solid #f5f5f5;
  490. .checkbox {
  491. width: 22px;
  492. height: 22px;
  493. border-radius: 6px;
  494. border: 2px solid #ddd;
  495. margin-right: 16px;
  496. background: #fff;
  497. &.checked {
  498. border-color: #ffb400;
  499. background: #ffb400;
  500. }
  501. }
  502. .reason-text {
  503. font-size: 16px;
  504. color: #222;
  505. }
  506. }
  507. }
  508. .popup-save-btn {
  509. width: 90%;
  510. margin: 32px auto 0 auto;
  511. height: 52px;
  512. border-radius: 26px;
  513. background: linear-gradient(90deg, #ffd01e 0%, #ffac04 100%);
  514. color: #fff;
  515. font-size: 20px;
  516. font-weight: bold;
  517. border: none;
  518. display: flex;
  519. align-items: center;
  520. justify-content: center;
  521. }
  522. }
  523. </style>