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

952 lines
22 KiB

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