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

1033 lines
24 KiB

2 months ago
4 weeks ago
4 weeks ago
4 weeks ago
2 months ago
4 weeks ago
2 months ago
4 weeks ago
2 months ago
4 weeks ago
2 months ago
4 weeks ago
2 months ago
4 weeks ago
2 months ago
4 weeks ago
2 months ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
2 months ago
4 weeks ago
2 months ago
4 weeks ago
4 weeks ago
2 months ago
4 weeks ago
4 weeks ago
2 months ago
4 weeks ago
2 months ago
4 weeks ago
2 months ago
4 weeks ago
2 months ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
1 month ago
4 weeks ago
4 weeks ago
4 weeks ago
1 month ago
4 weeks ago
2 months ago
4 weeks ago
  1. <template>
  2. <view class="container safe-area">
  3. <!-- 顶部banner -->
  4. <view class="banner">
  5. <swiper :indicator-dots="false" :autoplay="true" :interval="3000" :duration="500" circular
  6. style="width: 100%; height: 400rpx;">
  7. <swiper-item v-for="(item, index) in bannerList" :key="item.id || index">
  8. <view v-if="item.type == 1" class="video-container" @click="playVideo(item, index)">
  9. <video
  10. :id="`video-${index}`"
  11. :src="item.voUrl"
  12. :autoplay="false"
  13. :muted="true"
  14. :loop="false"
  15. :controls="true"
  16. :show-play-btn="true"
  17. :show-center-play-btn="true"
  18. :show-fullscreen-btn="true"
  19. :enable-play-gesture="true"
  20. object-fit="cover"
  21. :poster="item.image || ''"
  22. style="width: 100%; height: 100%;"
  23. @fullscreenchange="onFullscreenChange"
  24. @play="onVideoPlay(index)"
  25. @pause="onVideoPause(index)"
  26. ></video>
  27. <view v-if="!videoPlayingStates[index]" class="video-overlay">
  28. <view class="play-button">
  29. <uni-icons type="play-filled" size="60" color="#fff"></uni-icons>
  30. </view>
  31. </view>
  32. </view>
  33. <image v-else :src="item.image" mode="aspectFill" style="width: 100%; height: 100%;" />
  34. </swiper-item>
  35. </swiper>
  36. </view>
  37. <view class="content">
  38. <!-- 回收流程 -->
  39. <view class="process-section">
  40. <view class="section-header">
  41. <text class="title">回收流程</text>
  42. </view>
  43. <view class="process-grid">
  44. <view class="process-item" v-for="(item, index) in processes" :key="index">
  45. <image :src="item.icon" mode="aspectFit" class="process-icon"></image>
  46. <text class="process-text">{{item.text}}</text>
  47. <!-- <text class="process-number">{{index + 1}}</text> -->
  48. </view>
  49. </view>
  50. <button class="submit-btn" hover-class="submit-btn-hover" @click="getPickupto">
  51. <text class="submit-btn-hearder">快速免费上门</text>
  52. <text class="btn-desc">点击开始预约</text>
  53. <image src="/static/home/1745478917401 3.png" mode="aspectFit" class="arrow-icon"></image>
  54. <image src="/static/home/1745478917401 4.png" mode="aspectFit" class="arrow-icon-left"></image>
  55. </button>
  56. </view>
  57. <uv-divider :dashed="true"></uv-divider>
  58. <!-- 服务城市 -->
  59. <view class="city-section" @click="goCity">
  60. <view class="city-header">
  61. <text>已开通包邮服务城市有哪些</text>
  62. <uni-icons type="right" size="16" color="#999"></uni-icons>
  63. </view>
  64. <text class="city-list">{{ cityListStr }}</text>
  65. </view>
  66. <view class="Xiadan-section">
  67. <image :src="addressCion" alt="" class="process-icon" />
  68. <text class="left-text">不会下单联系客服了解回收流程</text>
  69. <view class="right" @click="goService">
  70. <image src="/static/home/联系客服.png" mode=""></image>
  71. <text>联系客服</text>
  72. </view>
  73. </view>
  74. <!-- 关于我们 -->
  75. <view class="about-section">
  76. <view class="section-header">
  77. <text class="title">关于我们</text>
  78. </view>
  79. <view class="about-footer" @click="goAbout">
  80. <view class="about-header">
  81. <image :src="sbkCion" mode="aspectFit" class="logo"></image>
  82. <!-- <text class="about-title">关于我们</text> -->
  83. </view>
  84. <view class="about-content">
  85. <text>免费寄送件验秒到账助环保</text>
  86. <text class="about-desc">让二手交易更轻松让地球多一份绿意</text>
  87. </view>
  88. <uni-icons type="right" size="16" color="#999"></uni-icons>
  89. </view>
  90. </view>
  91. <!-- 价格概览 -->
  92. <view class="price-section">
  93. <view class="section-header" @click="getPickupto">
  94. <text class="title">价格概览</text>
  95. <view class="more">
  96. <uni-icons type="right" size="14" color="#999"></uni-icons>
  97. <text>查看更多</text>
  98. </view>
  99. </view>
  100. <view class="price-grid">
  101. <view class="price-item" v-for="(item, index) in priceList" :key="item.id || index"
  102. @tap="goToRecycleCategory(item.id)">
  103. <image v-if="item.icon" :src="item.icon" mode="aspectFit" class="item-icon"></image>
  104. <view v-else class="item-icon placeholder"></view>
  105. <text class="item-name">{{item.name}}</text>
  106. <text class="item-price">¥ {{item.price}}
  107. <text class="item-price-right">/{{item.unit}}</text>
  108. </text>
  109. </view>
  110. </view>
  111. </view>
  112. <!-- 最近回收 -->
  113. <view class="recent-section">
  114. <view class="section-header">
  115. <text class="title">最近回收</text>
  116. </view>
  117. <view class="records-grid">
  118. <view class="record-item" v-for="(item, index) in records" :key="index"
  119. @tap="goToInspectionReport(item)">
  120. <image :src="item.image" mode="aspectFill"></image>
  121. <text class="location">{{item.name}}</text>
  122. <text class="user-id">****{{item.phone ? item.phone.slice(-4) : ''}}</text>
  123. <text class="user-id-f">成功完成衣物回收已到账</text>
  124. <text class="amount">+ ¥{{item.price}}</text>
  125. </view>
  126. </view>
  127. </view>
  128. <!-- 回收去向 -->
  129. <view class="destination-section">
  130. <view class="section-header">
  131. <text class="title">回收去向</text>
  132. </view>
  133. <view class="destination-grid">
  134. <view class="destination-item "
  135. @click="$utils.navigateTo('/pages/mine/recyclingDestination?id=' + item.id)"
  136. :class="`destination-item${index + 1}`" v-for="(item, index) in destinations" :key="index">
  137. <image :src="item.icon" mode="aspectFit" class="dest-icon"></image>
  138. <view class="dest-info">
  139. <text class="dest-title">{{item.title}}</text>
  140. <text class="dest-desc">{{item.description}}</text>
  141. </view>
  142. </view>
  143. </view>
  144. </view>
  145. </view>
  146. <!-- 根据角色显示不同的导航栏 -->
  147. <uv-tabbar :value="value" :fixed="true" @change="changeTo">
  148. <uv-tabbar-item text="首页">
  149. <template v-slot:active-icon>
  150. <image class="icon" src="/static/home/首页-点击.png"></image>
  151. </template>
  152. <template v-slot:inactive-icon>
  153. <image class="icon" src="/static/home/首页-未点击.png"></image>
  154. </template>
  155. </uv-tabbar-item>
  156. <uv-tabbar-item text="回收">
  157. <template v-slot:active-icon>
  158. <image class="icon" src="/static/home/回收-点击.png"></image>
  159. </template>
  160. <template v-slot:inactive-icon>
  161. <image class="icon" src="/static/home/回收-未点击.png"></image>
  162. </template>
  163. </uv-tabbar-item>
  164. <uv-tabbar-item text="我的">
  165. <template v-slot:active-icon>
  166. <image class="icon" src="/static/home/我的-点击.png"></image>
  167. </template>
  168. <template v-slot:inactive-icon>
  169. <image class="icon" src="/static/home/我的-未点击.png"></image>
  170. </template>
  171. </uv-tabbar-item>
  172. </uv-tabbar>
  173. </view>
  174. </template>
  175. <script>
  176. import pullRefreshMixin from '../mixins/pullRefreshMixin.js'
  177. export default {
  178. mixins: [pullRefreshMixin],
  179. data() {
  180. return {
  181. value: 0,
  182. processes: [],
  183. priceList: [],
  184. records: [],
  185. videoPlayingStates: {}, // 记录每个视频的播放状态
  186. destinations: [
  187. // {
  188. // icon: '/static/home/爱心援乡.png',
  189. // title: '爱心援乡',
  190. // description: '精准帮扶贫困群体'
  191. // },
  192. // {
  193. // icon: '/static/home/回塑新源.png',
  194. // title: '回塑新源',
  195. // description: '塑料的第二次成型'
  196. // },
  197. // {
  198. // icon: '/static/home/织物出海.png',
  199. // title: '织物出海',
  200. // description: '分拣出最高价值'
  201. // },
  202. // {
  203. // icon: '/static/home/碳循再生.png',
  204. // title: '碳循再生',
  205. // description: '减碳从出发生系统'
  206. // }
  207. ],
  208. bannerList: [],
  209. pricePreviewList: [],
  210. cityList: [],
  211. addressCion: '',
  212. sbkCion: '',
  213. queryParams: {},
  214. }
  215. },
  216. computed: {
  217. cityListStr() {
  218. // 只取前8个城市,超出用...结尾
  219. const names = this.cityList.map(c => c.name)
  220. const max = 8
  221. if (names.length > max) {
  222. return names.slice(0, max).join('、') + '...'
  223. }
  224. return names.join('、')
  225. },
  226. address_cion() {
  227. console.log(getApp().globalData.configData, 'home-getApp().globalData.configData')
  228. const item = getApp().globalData.configData.find(i => i.keyName === 'address_cion')
  229. return item ? item.keyContent : ''
  230. },
  231. sbk_cion() {
  232. const item = getApp().globalData.configData.find(i => i.keyName === 'sbk_cion')
  233. return item ? item.keyContent : ''
  234. }
  235. },
  236. methods: {
  237. changeTo(e) {
  238. this.value = e
  239. console.log(e, '111')
  240. if (e == 1) {
  241. uni.reLaunch({
  242. url: '/pages/component/recycle'
  243. }, true);
  244. } else if (e == 2) {
  245. uni.reLaunch({
  246. url: '/pages/component/my'
  247. }, true);
  248. }
  249. },
  250. goAbout() {
  251. uni.navigateTo({
  252. url: '/pages/subcomponent/about'
  253. })
  254. },
  255. goCity() {
  256. uni.navigateTo({
  257. url: '/pages/baoyou-city/baoyou-city'
  258. })
  259. },
  260. getPickupto() {
  261. uni.switchTab({
  262. url: '/pages/component/recycle'
  263. })
  264. },
  265. async onRefresh() {
  266. await new Promise(resolve => setTimeout(resolve, 1000))
  267. },
  268. getAreaList() {
  269. this.$api('getAreaList', {}, (res) => {
  270. console.log(res, 'getAreaList');
  271. if (res.code == 200 && Array.isArray(res.result)) {
  272. // 按sort升序排序
  273. const sorted = res.result.slice().sort((a, b) => a.sort - b.sort)
  274. this.processes = sorted.map(item => ({
  275. // id: item.id,
  276. icon: item.image,
  277. text: item.title
  278. }))
  279. }
  280. })
  281. },
  282. goService() {
  283. uni.navigateTo({
  284. url: '/pages/subcomponent/admin_faq'
  285. })
  286. },
  287. goToRecycleCategory(id) {
  288. getApp().globalData.targetRecycleCategoryId = id
  289. console.log(getApp().globalData.targetRecycleCategoryId, 'getApp().globalData.targetRecycleCategoryId')
  290. uni.switchTab({
  291. url: '/pages/component/recycle'
  292. })
  293. },
  294. getPricePreview() {
  295. const resList = this.pricePreviewList || []
  296. if (Array.isArray(resList)) {
  297. // 只取一级分类,按sort升序
  298. const firstLevel = resList.filter(item => item.pid == '0').sort((a, b) => a.sort - b.sort)
  299. // console.log(firstLevel,'firstLevel');
  300. this.priceList = firstLevel.map(item => {
  301. // 从静态表中找图片和价格
  302. // const staticItem = this.priceListStatic.find(s => s.name.replace(/\s/g, '') === item.title.replace(/\s/g, ''))
  303. // console.log(item,'item');
  304. return {
  305. id: item.id, // 保证有id
  306. icon: item.icon ? item.icon : '',
  307. name: item.title,
  308. price: item.priceNo ? item.priceNo : '',
  309. unit: item.unit ? item.unit : ''
  310. }
  311. })
  312. }
  313. },
  314. getRecentGoods() {
  315. this.$api('getRecentGoodsList', {}, res => {
  316. if (res && res.code === 200 && Array.isArray(res.result) && res.result.length > 0) {
  317. this.records = res.result.map(item => ({
  318. id: item.id,
  319. image: item.image,
  320. name: item.name,
  321. orderId: item.orderId,
  322. phone: item.phone,
  323. price: item.price
  324. }))
  325. } else {
  326. this.records = []
  327. }
  328. })
  329. },
  330. getRecyclingDestination() {
  331. this.$api('getRecyclingDestination')
  332. .then(res => {
  333. this.destinations = res.result
  334. })
  335. },
  336. goToInspectionReport(item) {
  337. uni.navigateTo({
  338. url: `/pages/subcomponent/inspection-report?orderId=${item.orderId}`
  339. })
  340. },
  341. getFreeCityList() {
  342. this.$api('getFreeCityList', {}, res => {
  343. if (res && res.code === 200 && Array.isArray(res.result)) {
  344. // 只取一级城市(有children的name)
  345. this.cityList = res.result.map(item => ({
  346. name: item.name
  347. })).filter(item => item.name)
  348. } else {
  349. this.cityList = []
  350. }
  351. })
  352. },
  353. updateCionData() {
  354. const configData = getApp().globalData.configData || [];
  355. const address = configData.find(i => i.keyName === 'address_cion');
  356. const sbk = configData.find(i => i.keyName === 'sbk_cion');
  357. this.addressCion = address ? address.keyContent : '';
  358. this.sbkCion = sbk ? sbk.keyContent : '';
  359. },
  360. // 视频相关方法
  361. playVideo(item, index) {
  362. const videoContext = uni.createVideoContext(`video-${index}`, this);
  363. if (this.videoPlayingStates[index]) {
  364. // 如果正在播放,暂停视频
  365. videoContext.pause();
  366. } else {
  367. // 如果未播放,开始播放
  368. videoContext.play();
  369. }
  370. },
  371. onVideoPlay(index) {
  372. this.$set(this.videoPlayingStates, index, true);
  373. },
  374. onVideoPause(index) {
  375. this.$set(this.videoPlayingStates, index, false);
  376. },
  377. onFullscreenChange(e) {
  378. console.log('全屏状态改变:', e.detail);
  379. },
  380. // 初始化页面数据的方法
  381. initializePageData() {
  382. const query = this.queryParams || {}
  383. if (query.shareId) {
  384. uni.setStorageSync('shareId', query.shareId)
  385. }
  386. // 先设置数据,再调用处理方法
  387. this.pricePreviewList = getApp().globalData.pricePreviewList || []
  388. this.bannerList = getApp().globalData.bannerList || []
  389. this.getAreaList()
  390. this.getPricePreview()
  391. this.getRecentGoods()
  392. this.getFreeCityList()
  393. // 监听数据更新事件
  394. uni.$on('pricePreviewListUpdated', () => {
  395. this.pricePreviewList = getApp().globalData.pricePreviewList || []
  396. this.getPricePreview()
  397. })
  398. uni.$on('bannerListUpdated', () => {
  399. this.bannerList = getApp().globalData.bannerList || []
  400. })
  401. },
  402. },
  403. onLoad(query) {
  404. // 保存query参数
  405. this.queryParams = query
  406. // 检查App数据是否已经准备好
  407. if (!getApp().globalData.isAppDataReady) {
  408. // 显示加载状态
  409. uni.showLoading({
  410. title: '加载中...',
  411. mask: true
  412. })
  413. // 监听App数据准备完成事件
  414. uni.$on('appDataReady', () => {
  415. uni.hideLoading()
  416. this.initializePageData()
  417. })
  418. } else {
  419. // App数据已经准备好,直接初始化页面数据
  420. this.initializePageData()
  421. }
  422. },
  423. onUnload() {
  424. uni.$off('pricePreviewListUpdated')
  425. uni.$off('bannerListUpdated')
  426. uni.$off('configDataUpdated', this.updateCionData)
  427. },
  428. onShow() {
  429. this.updateCionData();
  430. // 监听全局数据更新
  431. uni.$on('configDataUpdated', this.updateCionData);
  432. this.getPricePreview();
  433. this.getRecyclingDestination()
  434. },
  435. }
  436. </script>
  437. <style lang="scss" scoped>
  438. .container {
  439. min-height: 100vh;
  440. background-color: #f8f8f8;
  441. display: flex;
  442. flex-direction: column;
  443. padding-bottom: calc(var(--window-bottom) + 70px);
  444. }
  445. .safe-area {
  446. padding-bottom: constant(safe-area-inset-bottom);
  447. padding-bottom: env(safe-area-inset-bottom);
  448. }
  449. .banner {
  450. width: 100%;
  451. height: 400rpx;
  452. position: relative;
  453. overflow: hidden;
  454. border-radius: 0 0 30rpx 30rpx;
  455. image {
  456. width: 100%;
  457. height: 100%;
  458. }
  459. .video-container {
  460. position: relative;
  461. width: 100%;
  462. height: 100%;
  463. .video-overlay {
  464. position: absolute;
  465. top: 0;
  466. left: 0;
  467. right: 0;
  468. bottom: 0;
  469. background: rgba(0, 0, 0, 0.3);
  470. display: flex;
  471. flex-direction: column;
  472. justify-content: center;
  473. align-items: center;
  474. z-index: 10;
  475. .play-button {
  476. width: 120rpx;
  477. height: 120rpx;
  478. background: rgba(0, 0, 0, 0.6);
  479. border-radius: 50%;
  480. display: flex;
  481. justify-content: center;
  482. align-items: center;
  483. backdrop-filter: blur(10rpx);
  484. }
  485. }
  486. }
  487. }
  488. .content {
  489. // flex: 1;
  490. width: 90%;
  491. margin: -80rpx auto 0;
  492. position: relative;
  493. z-index: 3;
  494. padding-bottom: 20rpx;
  495. }
  496. .Xiadan-section {
  497. display: flex;
  498. // justify-content: space-around;
  499. align-items: center;
  500. margin-bottom: 20rpx;
  501. background: linear-gradient(to bottom, #fff3db 0%, #fffefb 50%);
  502. image {
  503. width: 80rpx;
  504. height: 80rpx;
  505. }
  506. .left-text {
  507. font-family: PingFang SC;
  508. font-weight: 400;
  509. font-size: 12px;
  510. line-height: 140%;
  511. letter-spacing: 0%;
  512. }
  513. .right {
  514. display: flex;
  515. // flex-direction: row-reverse;
  516. box-sizing: border-box;
  517. align-items: center;
  518. justify-content: center;
  519. background-color: #fff0d2;
  520. color: #da7143;
  521. font-size: 24rpx;
  522. // flex-grow: 2;
  523. border: 1px solid #da7143;
  524. border-radius: 10rpx;
  525. width: 25%;
  526. image {
  527. width: 40rpx;
  528. height: 40rpx;
  529. }
  530. }
  531. }
  532. .section-header {
  533. display: flex;
  534. // justify-content: space-around;
  535. align-items: center;
  536. margin-bottom: 20rpx;
  537. .title {
  538. font-size: 32rpx;
  539. font-weight: bold;
  540. color: #333;
  541. }
  542. .more {
  543. // justify-content: right;
  544. display: flex;
  545. flex-direction: row-reverse;
  546. align-items: center;
  547. color: #999;
  548. font-size: 24rpx;
  549. flex-grow: 2;
  550. // width: 100%;
  551. // margin-right: 0 auto;
  552. }
  553. }
  554. .process-section {
  555. background: #fff;
  556. border-radius: 50rpx;
  557. padding: 30rpx;
  558. margin-bottom: 20rpx;
  559. background: linear-gradient(to bottom, #fff5e1 0%, #fffefb 30%);
  560. .contact-service {
  561. display: flex;
  562. align-items: center;
  563. font-size: 24rpx;
  564. color: #666;
  565. border: 1px solid #da7143;
  566. background-color: #fff0d2;
  567. .service-icon {
  568. width: 32rpx;
  569. height: 32rpx;
  570. margin-right: 8rpx;
  571. }
  572. }
  573. .process-grid {
  574. display: grid;
  575. grid-template-columns: repeat(4, 1fr);
  576. gap: 20rpx;
  577. margin: 30rpx 0;
  578. border: none;
  579. }
  580. .process-item {
  581. position: relative;
  582. display: flex;
  583. flex-direction: column;
  584. align-items: center;
  585. background-color: #fff8ea;
  586. // left: 0; right: 0;
  587. .process-icon {
  588. width: 80rpx;
  589. height: 80rpx;
  590. margin-bottom: 10rpx;
  591. }
  592. .process-text {
  593. font-size: 24rpx;
  594. color: #333;
  595. }
  596. .process-number {
  597. position: absolute;
  598. top: -10rpx;
  599. left: 50%;
  600. transform: translateX(-50%);
  601. font-size: 24rpx;
  602. color: #999;
  603. }
  604. }
  605. .submit-btn {
  606. background: linear-gradient(to right, #ffd01e, #ff8917);
  607. border-radius: 70rpx;
  608. padding: 20rpx;
  609. text-align: center;
  610. position: relative;
  611. border: none;
  612. display: flex;
  613. flex-direction: column;
  614. overflow: visible;
  615. text {
  616. color: #ffffff;
  617. font-size: 32rpx;
  618. font-weight: bold;
  619. line-height: 40rpx;
  620. // display: block;
  621. }
  622. .btn-desc {
  623. font-size: 24rpx;
  624. font-weight: normal;
  625. // margin-top: 4rpx;
  626. }
  627. .arrow-icon {
  628. position: absolute;
  629. right: 10rpx;
  630. top: 10%;
  631. transform: translateY(-50%);
  632. width: 40rpx;
  633. height: 40rpx;
  634. // z-index: 5;
  635. }
  636. .arrow-icon-left {
  637. position: absolute;
  638. left: 1rpx;
  639. top: 90%;
  640. transform: translateY(-50%);
  641. width: 40rpx;
  642. height: 40rpx;
  643. // z-index: 4;
  644. }
  645. }
  646. .submit-btn::after {
  647. border: none !important;
  648. }
  649. }
  650. .city-section {
  651. background: #fff;
  652. border-radius: 20rpx;
  653. padding: 30rpx;
  654. margin-bottom: 20rpx;
  655. .city-header {
  656. display: flex;
  657. justify-content: space-between;
  658. align-items: center;
  659. font-size: 28rpx;
  660. color: #333;
  661. margin-bottom: 10rpx;
  662. }
  663. .city-list {
  664. font-size: 24rpx;
  665. color: #999;
  666. }
  667. }
  668. .price-section {
  669. background: #f0f9eb;
  670. border-radius: 20rpx;
  671. padding: 30rpx;
  672. margin-bottom: 20rpx;
  673. background-color: #fffefb;
  674. background: linear-gradient(to bottom, #fff3db 0%, #fffefb 5%);
  675. .section-header {
  676. margin-bottom: 40rpx;
  677. }
  678. .price-grid {
  679. display: grid;
  680. grid-template-columns: repeat(2, 1fr);
  681. gap: 20rpx;
  682. }
  683. .price-item {
  684. display: flex;
  685. flex-direction: column;
  686. align-items: center;
  687. background: #fff;
  688. border-radius: 16rpx;
  689. padding: 30rpx;
  690. background-color: #fff8ea;
  691. .item-icon {
  692. width: 120rpx;
  693. height: 120rpx;
  694. margin-bottom: 12rpx;
  695. &.placeholder {
  696. width: 120rpx;
  697. height: 120rpx;
  698. margin-bottom: 12rpx;
  699. background: #f5f5f5;
  700. border-radius: 16rpx;
  701. }
  702. }
  703. .item-name {
  704. font-size: 30rpx;
  705. color: #333;
  706. margin-bottom: 8rpx;
  707. font-weight: 500;
  708. }
  709. .item-price {
  710. font-family: PingFang SC;
  711. font-weight: 600;
  712. font-size: 28rpx;
  713. line-height: 140%;
  714. letter-spacing: 0%;
  715. text-align: center;
  716. color: #181818;
  717. .item-price-right {
  718. text-align: center;
  719. font-size: 26rpx;
  720. color: #666;
  721. line-height: 140%;
  722. letter-spacing: 0%;
  723. font-weight: 400;
  724. }
  725. }
  726. }
  727. }
  728. .recent-section {
  729. background: #f0f9eb;
  730. border-radius: 20rpx;
  731. padding: 30rpx;
  732. margin-bottom: 20rpx;
  733. background-color: #fffefb;
  734. background: linear-gradient(to bottom, #e8ffe0 0%, #fffefb 15%);
  735. .records-grid {
  736. display: grid;
  737. grid-template-columns: repeat(3, 1fr);
  738. gap: 20rpx;
  739. }
  740. .record-item {
  741. display: flex;
  742. flex-direction: column;
  743. align-items: center;
  744. background: linear-gradient(to top, #e8ffe0 0%, #fffefb 100%);
  745. border-radius: 16rpx;
  746. padding: 10rpx;
  747. background-color: #fff8ea;
  748. image {
  749. width: 60rpx;
  750. height: 60rpx;
  751. border-radius: 50%;
  752. }
  753. .location {
  754. font-size: 28rpx;
  755. color: #333;
  756. font-weight: bold;
  757. }
  758. .amount {
  759. font-size: 30rpx;
  760. color: #13ac47;
  761. font-weight: bold;
  762. margin: 6rpx 0;
  763. }
  764. .user-id {
  765. font-family: PingFang SC;
  766. font-weight: 500;
  767. font-size: 24rpx;
  768. line-height: 140%;
  769. letter-spacing: 0%;
  770. text-align: center;
  771. color: #183c5c;
  772. }
  773. .user-id-f {
  774. font-family: PingFang SC;
  775. font-weight: 400;
  776. font-size: 22rpx;
  777. line-height: 140%;
  778. letter-spacing: 0%;
  779. text-align: center;
  780. color: #9b9b9b;
  781. }
  782. }
  783. }
  784. .destination-section {
  785. // background: #fff;
  786. border-radius: 20rpx;
  787. padding: 30rpx;
  788. margin-bottom: 20rpx;
  789. background: linear-gradient(to bottom, #f2f0fc 0%, #fffefb 10%);
  790. padding-bottom: calc(var(--window-bottom) + 60px);
  791. .destination-grid {
  792. display: grid;
  793. grid-template-columns: repeat(2, 1fr);
  794. gap: 20rpx;
  795. }
  796. .destination-item {
  797. display: flex;
  798. align-items: center;
  799. // background: #fff9f9;
  800. border-radius: 16rpx;
  801. padding: 20rpx;
  802. .dest-icon {
  803. width: 60rpx;
  804. height: 60rpx;
  805. margin-right: 16rpx;
  806. }
  807. .dest-info {
  808. flex: 1;
  809. .dest-title {
  810. font-size: 26rpx;
  811. color: #333;
  812. margin-bottom: 4rpx;
  813. }
  814. .dest-desc {
  815. font-size: 22rpx;
  816. color: #999;
  817. }
  818. }
  819. }
  820. }
  821. .destination-item1 {
  822. background: linear-gradient(to top, #ffebeb, #fffefb);
  823. }
  824. .destination-item2 {
  825. background: linear-gradient(to top, #ebf8ff, #fffefb);
  826. }
  827. .destination-item3 {
  828. background: linear-gradient(to top, #ebedff, #fffefb);
  829. }
  830. .destination-item4 {
  831. background: linear-gradient(to top, #ebfff2, #fffefb);
  832. }
  833. .about-section {
  834. background: linear-gradient(to bottom, #fff3db 0%, #fffefb 30%);
  835. border-radius: 20rpx;
  836. padding: 30rpx;
  837. display: flex;
  838. justify-content: space-between;
  839. flex-direction: column;
  840. .about-footer {
  841. display: flex;
  842. flex-direction: row;
  843. align-items: center;
  844. justify-content: center;
  845. }
  846. .about-header {
  847. display: flex;
  848. align-items: center;
  849. .logo {
  850. width: 60rpx;
  851. height: 60rpx;
  852. margin-right: 16rpx;
  853. }
  854. .about-title {
  855. font-size: 28rpx;
  856. color: #333;
  857. }
  858. }
  859. .about-content {
  860. flex: 1;
  861. margin-left: 20rpx;
  862. text {
  863. display: block;
  864. font-size: 26rpx;
  865. color: #333;
  866. }
  867. .about-desc {
  868. font-size: 22rpx;
  869. color: #999;
  870. margin-top: 4rpx;
  871. }
  872. }
  873. }
  874. .tab-bar {
  875. position: fixed;
  876. bottom: 0;
  877. left: 0;
  878. right: 0;
  879. height: 100rpx;
  880. background-color: #fff;
  881. display: flex;
  882. justify-content: space-around;
  883. align-items: center;
  884. border-top: 1rpx solid #f5f5f5;
  885. box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
  886. .tab-item {
  887. display: flex;
  888. flex-direction: column;
  889. align-items: center;
  890. padding: 10rpx 0;
  891. transition: all 0.3s ease;
  892. .tab-icon {
  893. width: 48rpx;
  894. height: 48rpx;
  895. margin-bottom: 6rpx;
  896. }
  897. text {
  898. font-size: 22rpx;
  899. color: #666;
  900. transition: color 0.3s ease;
  901. }
  902. &.active {
  903. text {
  904. color: #ff5e00;
  905. }
  906. }
  907. &:active {
  908. transform: scale(0.95);
  909. }
  910. }
  911. }
  912. @keyframes fadeInUp {
  913. from {
  914. opacity: 0;
  915. transform: translateY(20rpx);
  916. }
  917. to {
  918. opacity: 1;
  919. transform: translateY(0);
  920. }
  921. }
  922. @keyframes fadeInScale {
  923. from {
  924. opacity: 0;
  925. transform: scale(0.8);
  926. }
  927. to {
  928. opacity: 1;
  929. transform: scale(1);
  930. }
  931. }
  932. </style>