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

510 lines
13 KiB

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