feat(home): 联调首页接口并适配真实数据结构
- 更新首页 API 地址及 mock 处理器,对齐 Apifox 接口规范 - 重构首页页面,消费 `volunteer_top_banner`、`volunteer_bottom_banner`、`volunteer_home_icon` 字段 - 为顶部 banner 添加 Swiper 轮播支持,单图保持现状,多图自动切换 - 在 mock 环境下添加状态提示,便于后续真实数据联调 - 调整全局配置,移除默认 `f` 参数,改为各接口单独传递 - 更新组件类型声明,引入 NutUI Swiper 组件 - 同步更新 TODO 清单,标记已完成项并细化后续任务
Showing
7 changed files
with
220 additions
and
100 deletions
| 1 | # TODO 清单 | 1 | # TODO 清单 |
| 2 | 2 | ||
| 3 | -## 未实现与待联调功能 | 3 | +## 首页与内容接口 |
| 4 | - | 4 | + |
| 5 | -1. 首页当前使用的还是假数据,还缺一个首页内容接口,需要替换成真实返回的 banner、导航和图片入口数据。 | 5 | +- [x] 首页页面已按 Apifox“首页”接口结构改造,当前消费 `volunteer_top_banner`、`volunteer_bottom_banner`、`volunteer_home_icon` 三组字段。 |
| 6 | -2. 底部导航栏的显示还需要联调,还缺一个底部导航配置接口,用来确认各 tab 的标题、显隐、跳转页和 WebView 地址。 | 6 | +- [x] 首页 mock 已按真实接口字段结构补齐,当前图片和图标先复用现有页面假数据,避免真实接口到位后再次大范围改页面。 |
| 7 | -3. 资讯页面还需要一个接口获取资讯信息列表,后续要和详情页、已读状态这条链路一起确认真实字段。 | 7 | +- [x] 首页页面已增加“当前为 mock 接口结构”的状态提示,后续真实接口出数后可直接去掉该提示。 |
| 8 | -4. “应用”和“我的”页面还缺 2 个 WebView URL,需要分别提供可用地址后再完成联调。 | 8 | +- [ ] 首页真实接口还没有返回业务数据,后续需要把 mock 环境切到真实返回值联调。 |
| 9 | -5. 授权功能还没有联调,需要确认静默授权、授权失败跳转、授权成功回跳这条链路是否正常。 | 9 | +- [ ] 首页接口正式 `client_id` 还未确认,当前继续沿用全局默认请求参数,待后端给出正式值后补配置。 |
| 10 | -6. 支付确认页还没有联调,需要确认页面入参、金额展示、点击支付和状态提示是否正常。 | 10 | +- [ ] 继续确认 `volunteer_top_banner` 实际返回是一组还是多组;当前页面已兼容“单图保持现状,多图自动切 Swiper 轮播”。 |
| 11 | -7. 支付功能还没有联调,需要确认支付参数获取、小程序拉起支付、支付结果返回和回跳流程是否正常。 | 11 | +- [ ] 确认首页接口里的 `title`、`color` 后续是否启用;当前已保留字段但页面暂未消费。 |
| 12 | + | ||
| 13 | +## 底部导航与 WebView | ||
| 14 | + | ||
| 15 | +- [ ] 底部导航栏还需要联调真实配置接口,继续确认各 tab 的标题、显隐、跳转页和 WebView 地址。 | ||
| 16 | +- [ ] “应用”和“我的”页面还缺 2 个可用 WebView URL,提供后再完成联调。 | ||
| 17 | + | ||
| 18 | +## 资讯链路 | ||
| 19 | + | ||
| 20 | +- [ ] 资讯页面还需要真实接口获取列表数据,后续要和详情页、已读状态链路一起确认真实字段。 | ||
| 21 | + | ||
| 22 | +## 授权与支付 | ||
| 23 | + | ||
| 24 | +- [ ] 授权功能还没有完整联调,需要确认静默授权、授权失败跳转、授权成功回跳这条链路是否正常。 | ||
| 25 | +- [ ] 支付确认页还没有联调,需要确认页面入参、金额展示、点击支付和状态提示是否正常。 | ||
| 26 | +- [ ] 支付功能还没有联调,需要确认支付参数获取、小程序拉起支付、支付结果返回和回跳流程是否正常。 | ... | ... |
| ... | @@ -9,6 +9,8 @@ declare module 'vue' { | ... | @@ -9,6 +9,8 @@ declare module 'vue' { |
| 9 | export interface GlobalComponents { | 9 | export interface GlobalComponents { |
| 10 | AppTabbar: typeof import('./src/components/AppTabbar.vue')['default'] | 10 | AppTabbar: typeof import('./src/components/AppTabbar.vue')['default'] |
| 11 | IndexNav: typeof import('./src/components/indexNav.vue')['default'] | 11 | IndexNav: typeof import('./src/components/indexNav.vue')['default'] |
| 12 | + NutSwiper: typeof import('@nutui/nutui-taro')['Swiper'] | ||
| 13 | + NutSwiperItem: typeof import('@nutui/nutui-taro')['SwiperItem'] | ||
| 12 | Picker: typeof import('./src/components/time-picker-data/picker.vue')['default'] | 14 | Picker: typeof import('./src/components/time-picker-data/picker.vue')['default'] |
| 13 | PosterBuilder: typeof import('./src/components/PosterBuilder/index.vue')['default'] | 15 | PosterBuilder: typeof import('./src/components/PosterBuilder/index.vue')['default'] |
| 14 | QrCode: typeof import('./src/components/qrCode.vue')['default'] | 16 | QrCode: typeof import('./src/components/qrCode.vue')['default'] | ... | ... |
| 1 | import { fn, fetch } from './fn' | 1 | import { fn, fetch } from './fn' |
| 2 | 2 | ||
| 3 | const Api = { | 3 | const Api = { |
| 4 | - HOME_CONTENT: '/srv/?a=home&t=content', | 4 | + HOME_CONTENT: '/srv/?a=app_list&t=volunteer&f=customize', |
| 5 | PAY_TEST: '/srv/?a=pay', | 5 | PAY_TEST: '/srv/?a=pay', |
| 6 | } | 6 | } |
| 7 | 7 | ||
| 8 | +/** | ||
| 9 | + * @description 获取首页内容 | ||
| 10 | + * - 当前先按 Apifox 首页接口结构联调 | ||
| 11 | + * - client_id 继续走全局默认参数,正式值待后端确认 | ||
| 12 | + */ | ||
| 8 | export const getHomeContentAPI = () => fn(fetch.get(Api.HOME_CONTENT)) | 13 | export const getHomeContentAPI = () => fn(fetch.get(Api.HOME_CONTENT)) |
| 9 | 14 | ||
| 10 | /** | 15 | /** | ... | ... |
| 1 | -const banner_image = 'https://cdn.ipadbiz.cn/jls_weapp/images/banner01@2x.png' | 1 | +const top_banner_image = 'https://cdn.ipadbiz.cn/jls_weapp/images/banner01@2x.png' |
| 2 | -const activity_image_01 = 'https://cdn.ipadbiz.cn/jls_weapp/images/banner02@2x.png' | 2 | +const top_banner_image_02 = 'https://cdn.ipadbiz.cn/jls_weapp/images/banner02@2x.png' |
| 3 | -const activity_image_02 = 'https://cdn.ipadbiz.cn/jls_weapp/images/banner03@2x.png' | 3 | +const top_banner_image_03 = 'https://cdn.ipadbiz.cn/jls_weapp/images/banner03@2x.png' |
| 4 | +const bottom_banner_image_01 = 'https://cdn.ipadbiz.cn/jls_weapp/images/banner02@2x.png' | ||
| 5 | +const bottom_banner_image_02 = 'https://cdn.ipadbiz.cn/jls_weapp/images/banner03@2x.png' | ||
| 4 | 6 | ||
| 7 | +/** | ||
| 8 | + * @description 首页接口 mock 样本 | ||
| 9 | + * - 字段结构对齐 Apifox“首页”接口 | ||
| 10 | + * - 当前图片与图标先复用现有首页假数据,等真实接口出数后可直接替换 | ||
| 11 | + */ | ||
| 5 | export const getHomeContentFixture = () => ({ | 12 | export const getHomeContentFixture = () => ({ |
| 6 | - banner: { | 13 | + volunteer_top_banner: [ |
| 7 | - id: 'home-banner-01', | 14 | + { |
| 8 | - image_url: banner_image, | 15 | + id: 2770328, |
| 9 | title: '苏州觉林寺', | 16 | title: '苏州觉林寺', |
| 10 | - link_url: 'https://oa-dev.onwall.cn/f/futian_home/?f=f&p=futian_list', | 17 | + link: top_banner_image, |
| 11 | - link_title: '苏州觉林寺', | 18 | + value: 'https://oa-dev.onwall.cn/f/futian_home/?f=f&p=futian_list', |
| 19 | + }, | ||
| 20 | + { | ||
| 21 | + id: 2770329, | ||
| 22 | + title: '法讯动态', | ||
| 23 | + link: top_banner_image_02, | ||
| 24 | + value: 'https://oa-dev.onwall.cn/f/futian_home/?f=f&p=news_list', | ||
| 25 | + }, | ||
| 26 | + { | ||
| 27 | + id: 2770331, | ||
| 28 | + title: '共修活动', | ||
| 29 | + link: top_banner_image_03, | ||
| 30 | + value: 'https://oa-dev.onwall.cn/f/futian_home/?f=f&p=practice', | ||
| 31 | + }, | ||
| 32 | + ], | ||
| 33 | + volunteer_bottom_banner: [ | ||
| 34 | + { | ||
| 35 | + id: 2770330, | ||
| 36 | + title: '新春祈福法会', | ||
| 37 | + link: bottom_banner_image_01, | ||
| 38 | + value: 'https://oa-dev.onwall.cn/f/futian_home/?f=f&p=activity_spring', | ||
| 39 | + }, | ||
| 40 | + { | ||
| 41 | + id: 2770332, | ||
| 42 | + title: '中秋月光茶会', | ||
| 43 | + link: bottom_banner_image_02, | ||
| 44 | + value: 'https://oa-dev.onwall.cn/f/futian_home/?f=f&p=activity_moon', | ||
| 45 | + }, | ||
| 46 | + { | ||
| 47 | + id: 2770333, | ||
| 48 | + title: '禅修静心体验', | ||
| 49 | + link: bottom_banner_image_01, | ||
| 50 | + value: 'https://oa-dev.onwall.cn/f/futian_home/?f=f&p=activity_meditation', | ||
| 51 | + }, | ||
| 52 | + { | ||
| 53 | + id: 2770334, | ||
| 54 | + title: '法物流通', | ||
| 55 | + link: bottom_banner_image_02, | ||
| 56 | + value: '', | ||
| 12 | }, | 57 | }, |
| 13 | - nav_list: [ | 58 | + ], |
| 59 | + volunteer_home_icon: [ | ||
| 14 | { | 60 | { |
| 15 | - id: 'map-guide', | 61 | + id: 2770335, |
| 16 | title: '地图导览', | 62 | title: '地图导览', |
| 63 | + link: '/pages/map-guide/index', | ||
| 17 | icon: 'fa-odnoklassniki-square', | 64 | icon: 'fa-odnoklassniki-square', |
| 18 | - link_url: '', | ||
| 19 | - page_url: '/pages/map-guide/index', | ||
| 20 | }, | 65 | }, |
| 21 | { | 66 | { |
| 22 | - id: 'news', | 67 | + id: 2770336, |
| 23 | title: '法讯-最新动态', | 68 | title: '法讯-最新动态', |
| 69 | + link: 'https://oa-dev.onwall.cn/f/futian_home/?f=f&p=news_list', | ||
| 24 | icon: 'icon-jingxiuying', | 70 | icon: 'icon-jingxiuying', |
| 25 | - link_url: 'https://oa-dev.onwall.cn/f/futian_home/?f=f&p=news_list', | ||
| 26 | - link_title: '法讯-最新动态', | ||
| 27 | }, | 71 | }, |
| 28 | { | 72 | { |
| 29 | - id: 'intro', | 73 | + id: 2770337, |
| 30 | title: '寺院介绍', | 74 | title: '寺院介绍', |
| 75 | + link: 'https://oa-dev.onwall.cn/f/futian_home/?f=f&p=temple_intro', | ||
| 31 | icon: 'icon-jingxiuying', | 76 | icon: 'icon-jingxiuying', |
| 32 | - link_url: 'https://oa-dev.onwall.cn/f/futian_home/?f=f&p=temple_intro', | ||
| 33 | - link_title: '寺院介绍', | ||
| 34 | }, | 77 | }, |
| 35 | { | 78 | { |
| 36 | - id: 'practice', | 79 | + id: 2770338, |
| 37 | title: '共修活动', | 80 | title: '共修活动', |
| 81 | + link: 'https://oa-dev.onwall.cn/f/futian_home/?f=f&p=practice', | ||
| 38 | icon: 'icon-jingxiuying', | 82 | icon: 'icon-jingxiuying', |
| 39 | - link_url: 'https://oa-dev.onwall.cn/f/futian_home/?f=f&p=practice', | ||
| 40 | - link_title: '共修活动', | ||
| 41 | }, | 83 | }, |
| 42 | { | 84 | { |
| 43 | - id: 'volunteer', | 85 | + id: 2770339, |
| 44 | title: '义工报名', | 86 | title: '义工报名', |
| 87 | + link: 'https://oa-dev.onwall.cn/f/futian_home/?f=f&p=volunteer', | ||
| 45 | icon: 'icon-jingxiuying', | 88 | icon: 'icon-jingxiuying', |
| 46 | - link_url: 'https://oa-dev.onwall.cn/f/futian_home/?f=f&p=volunteer', | ||
| 47 | - link_title: '义工报名', | ||
| 48 | }, | 89 | }, |
| 49 | { | 90 | { |
| 50 | - id: 'contact', | 91 | + id: 2770340, |
| 51 | title: '联系我们', | 92 | title: '联系我们', |
| 93 | + link: '', | ||
| 52 | icon: 'icon-jingxiuying', | 94 | icon: 'icon-jingxiuying', |
| 53 | - link_url: '', | ||
| 54 | - }, | ||
| 55 | - ], | ||
| 56 | - image_links: [ | ||
| 57 | - { | ||
| 58 | - id: 'activity-01', | ||
| 59 | - title: '新春祈福法会', | ||
| 60 | - tag: '活动报名', | ||
| 61 | - image_url: activity_image_01, | ||
| 62 | - link_url: 'https://oa-dev.onwall.cn/f/futian_home/?f=f&p=activity_spring', | ||
| 63 | - link_title: '新春祈福法会', | ||
| 64 | - }, | ||
| 65 | - { | ||
| 66 | - id: 'activity-02', | ||
| 67 | - title: '中秋月光茶会', | ||
| 68 | - tag: '活动报名', | ||
| 69 | - image_url: activity_image_02, | ||
| 70 | - link_url: 'https://oa-dev.onwall.cn/f/futian_home/?f=f&p=activity_moon', | ||
| 71 | - link_title: '中秋月光茶会', | ||
| 72 | - }, | ||
| 73 | - { | ||
| 74 | - id: 'activity-03', | ||
| 75 | - title: '禅修静心体验', | ||
| 76 | - tag: '预约参加', | ||
| 77 | - image_url: activity_image_01, | ||
| 78 | - link_url: 'https://oa-dev.onwall.cn/f/futian_home/?f=f&p=activity_meditation', | ||
| 79 | - link_title: '禅修静心体验', | ||
| 80 | - }, | ||
| 81 | - { | ||
| 82 | - id: 'activity-04', | ||
| 83 | - title: '法物流通', | ||
| 84 | - tag: '查看详情', | ||
| 85 | - image_url: activity_image_02, | ||
| 86 | - link_url: '', | ||
| 87 | }, | 95 | }, |
| 88 | ], | 96 | ], |
| 97 | + title: '苏州觉林寺', | ||
| 98 | + color: '#d75b5b', | ||
| 89 | }) | 99 | }) | ... | ... |
| ... | @@ -3,9 +3,9 @@ import { buildMockSuccess } from '../shared/response' | ... | @@ -3,9 +3,9 @@ import { buildMockSuccess } from '../shared/response' |
| 3 | 3 | ||
| 4 | export const homeMockHandlers = [ | 4 | export const homeMockHandlers = [ |
| 5 | { | 5 | { |
| 6 | - action: 'home', | 6 | + action: 'app_list', |
| 7 | - type: 'content', | 7 | + type: 'volunteer', |
| 8 | method: 'GET', | 8 | method: 'GET', |
| 9 | - handle: () => buildMockSuccess(getHomeContentFixture(), '首页内容获取成功 (mock)'), | 9 | + handle: () => buildMockSuccess(getHomeContentFixture(), '首页内容获取成功(当前为 mock 结构)'), |
| 10 | }, | 10 | }, |
| 11 | ] | 11 | ] | ... | ... |
| 1 | <template> | 1 | <template> |
| 2 | <view class="index-page"> | 2 | <view class="index-page"> |
| 3 | <view class="page-content"> | 3 | <view class="page-content"> |
| 4 | + <view v-if="hasTopBanner" class="home-top-banner"> | ||
| 5 | + <view v-if="isMockHomeData" class="mock-state-badge"> | ||
| 6 | + mock | ||
| 7 | + </view> | ||
| 8 | + | ||
| 9 | + <nut-swiper | ||
| 10 | + v-if="shouldUseTopBannerSwiper" | ||
| 11 | + :auto-play="3000" | ||
| 12 | + :loop="true" | ||
| 13 | + :pagination-visible="true" | ||
| 14 | + pagination-color="#ffffff" | ||
| 15 | + pagination-unselected-color="rgba(255, 255, 255, 0.45)" | ||
| 16 | + height="210" | ||
| 17 | + > | ||
| 18 | + <nut-swiper-item | ||
| 19 | + v-for="item in topBanners" | ||
| 20 | + :key="item.id" | ||
| 21 | + > | ||
| 4 | <view | 22 | <view |
| 5 | - v-if="banner.image_url" | ||
| 6 | class="home-banner" | 23 | class="home-banner" |
| 7 | - :class="{ clickable: hasLink(banner) }" | 24 | + :class="{ clickable: hasLink(item) }" |
| 8 | - @tap="handleLinkedItemTap(banner)" | 25 | + @tap="handleLinkedItemTap(item)" |
| 9 | > | 26 | > |
| 10 | - <image class="home-banner__image" :src="banner.image_url" mode="aspectFill" /> | 27 | + <image class="home-banner__image" :src="item.image_url" mode="aspectFill" /> |
| 28 | + </view> | ||
| 29 | + </nut-swiper-item> | ||
| 30 | + </nut-swiper> | ||
| 31 | + | ||
| 32 | + <view | ||
| 33 | + v-else | ||
| 34 | + class="home-banner" | ||
| 35 | + :class="{ clickable: hasLink(topBanners[0]) }" | ||
| 36 | + @tap="handleLinkedItemTap(topBanners[0])" | ||
| 37 | + > | ||
| 38 | + <image class="home-banner__image" :src="topBanners[0].image_url" mode="aspectFill" /> | ||
| 39 | + </view> | ||
| 11 | </view> | 40 | </view> |
| 12 | 41 | ||
| 13 | <view class="nav-panel"> | 42 | <view class="nav-panel"> |
| 14 | <view | 43 | <view |
| 15 | - v-for="item in nav_list" | 44 | + v-for="item in homeIcons" |
| 16 | :key="item.id" | 45 | :key="item.id" |
| 17 | class="nav-entry" | 46 | class="nav-entry" |
| 18 | :class="{ clickable: hasLink(item) }" | 47 | :class="{ clickable: hasLink(item) }" |
| ... | @@ -30,7 +59,7 @@ | ... | @@ -30,7 +59,7 @@ |
| 30 | 59 | ||
| 31 | <view class="image-link-list"> | 60 | <view class="image-link-list"> |
| 32 | <view | 61 | <view |
| 33 | - v-for="item in image_links" | 62 | + v-for="item in bottomBanners" |
| 34 | :key="item.id" | 63 | :key="item.id" |
| 35 | class="image-link-card" | 64 | class="image-link-card" |
| 36 | :class="{ clickable: hasLink(item) }" | 65 | :class="{ clickable: hasLink(item) }" |
| ... | @@ -46,42 +75,83 @@ | ... | @@ -46,42 +75,83 @@ |
| 46 | </template> | 75 | </template> |
| 47 | 76 | ||
| 48 | <script setup> | 77 | <script setup> |
| 49 | -import { ref } from 'vue' | 78 | +import { computed, ref } from 'vue' |
| 50 | import Taro, { useLoad } from '@tarojs/taro' | 79 | import Taro, { useLoad } from '@tarojs/taro' |
| 51 | import AppTabbar from '@/components/AppTabbar.vue' | 80 | import AppTabbar from '@/components/AppTabbar.vue' |
| 52 | import { getHomeContentAPI } from '@/api' | 81 | import { getHomeContentAPI } from '@/api' |
| 53 | import { buildWebviewPreviewUrl } from '@/utils/webview' | 82 | import { buildWebviewPreviewUrl } from '@/utils/webview' |
| 83 | +import { isMockEnabled } from '@/utils/config' | ||
| 84 | + | ||
| 85 | +const defaultIcon = 'icon-jingxiuying' | ||
| 86 | +const homeContent = ref({ | ||
| 87 | + volunteer_top_banner: [], | ||
| 88 | + volunteer_bottom_banner: [], | ||
| 89 | + volunteer_home_icon: [], | ||
| 90 | + title: '', | ||
| 91 | + color: '', | ||
| 92 | +}) | ||
| 54 | 93 | ||
| 55 | -const default_icon = 'icon-jingxiuying' | 94 | +const topBanners = computed(() => homeContent.value.volunteer_top_banner || []) |
| 56 | -const banner = ref({}) | 95 | +const bottomBanners = computed(() => homeContent.value.volunteer_bottom_banner || []) |
| 57 | -const nav_list = ref([]) | 96 | +const homeIcons = computed(() => homeContent.value.volunteer_home_icon || []) |
| 58 | -const image_links = ref([]) | 97 | +const hasTopBanner = computed(() => topBanners.value.some((item) => item?.image_url)) |
| 98 | +const shouldUseTopBannerSwiper = computed(() => topBanners.value.filter((item) => item?.image_url).length > 1) | ||
| 99 | +const isMockHomeData = computed(() => isMockEnabled()) | ||
| 59 | 100 | ||
| 60 | -const hasLink = (item) => !!(item?.page_url || item?.link_url) | 101 | +const getItemTargetUrl = (item) => String(item?.target_url || '').trim() |
| 102 | + | ||
| 103 | +const hasLink = (item) => !!getItemTargetUrl(item) | ||
| 104 | + | ||
| 105 | +const isInternalMiniProgramPath = (url) => String(url || '').startsWith('/pages/') | ||
| 61 | 106 | ||
| 62 | const getIconClass = (item) => { | 107 | const getIconClass = (item) => { |
| 63 | - const icon = item?.icon || default_icon | 108 | + const icon = item?.icon || defaultIcon |
| 64 | - const font_class = icon.startsWith('fa-') ? 'fa' : 'iconfont' | 109 | + const fontClass = icon.startsWith('fa-') ? 'fa' : 'iconfont' |
| 65 | - return [font_class, icon] | 110 | + return [fontClass, icon] |
| 66 | } | 111 | } |
| 67 | 112 | ||
| 68 | const handleLinkedItemTap = (item) => { | 113 | const handleLinkedItemTap = (item) => { |
| 69 | - if (!item) return | 114 | + if (!item || !hasLink(item)) return |
| 70 | 115 | ||
| 71 | - if (item.page_url) { | 116 | + const targetUrl = getItemTargetUrl(item) |
| 117 | + | ||
| 118 | + if (isInternalMiniProgramPath(targetUrl)) { | ||
| 72 | Taro.navigateTo({ | 119 | Taro.navigateTo({ |
| 73 | - url: item.page_url, | 120 | + url: targetUrl, |
| 74 | }) | 121 | }) |
| 75 | return | 122 | return |
| 76 | } | 123 | } |
| 77 | 124 | ||
| 78 | - if (item.link_url) { | ||
| 79 | Taro.navigateTo({ | 125 | Taro.navigateTo({ |
| 80 | - url: buildWebviewPreviewUrl(item.link_url, item.link_title || item.title || ''), | 126 | + url: buildWebviewPreviewUrl(targetUrl, item?.title || ''), |
| 81 | }) | 127 | }) |
| 82 | - } | ||
| 83 | } | 128 | } |
| 84 | 129 | ||
| 130 | +const normalizeHomeContent = (data = {}) => ({ | ||
| 131 | + volunteer_top_banner: Array.isArray(data.volunteer_top_banner) | ||
| 132 | + ? data.volunteer_top_banner.map((item) => ({ | ||
| 133 | + ...item, | ||
| 134 | + image_url: item?.link || '', | ||
| 135 | + target_url: item?.value || '', | ||
| 136 | + })) | ||
| 137 | + : [], | ||
| 138 | + volunteer_bottom_banner: Array.isArray(data.volunteer_bottom_banner) | ||
| 139 | + ? data.volunteer_bottom_banner.map((item) => ({ | ||
| 140 | + ...item, | ||
| 141 | + image_url: item?.link || '', | ||
| 142 | + target_url: item?.value || '', | ||
| 143 | + })) | ||
| 144 | + : [], | ||
| 145 | + volunteer_home_icon: Array.isArray(data.volunteer_home_icon) | ||
| 146 | + ? data.volunteer_home_icon.map((item) => ({ | ||
| 147 | + ...item, | ||
| 148 | + target_url: item?.link || '', | ||
| 149 | + })) | ||
| 150 | + : [], | ||
| 151 | + title: data.title || '', | ||
| 152 | + color: data.color || '', | ||
| 153 | +}) | ||
| 154 | + | ||
| 85 | const fetchHomeContent = async () => { | 155 | const fetchHomeContent = async () => { |
| 86 | const response = await getHomeContentAPI() | 156 | const response = await getHomeContentAPI() |
| 87 | 157 | ||
| ... | @@ -93,10 +163,7 @@ const fetchHomeContent = async () => { | ... | @@ -93,10 +163,7 @@ const fetchHomeContent = async () => { |
| 93 | return | 163 | return |
| 94 | } | 164 | } |
| 95 | 165 | ||
| 96 | - const data = response?.data || {} | 166 | + homeContent.value = normalizeHomeContent(response?.data) |
| 97 | - banner.value = data.banner || {} | ||
| 98 | - nav_list.value = data.nav_list || [] | ||
| 99 | - image_links.value = data.image_links || [] | ||
| 100 | } | 167 | } |
| 101 | 168 | ||
| 102 | useLoad(() => { | 169 | useLoad(() => { |
| ... | @@ -114,8 +181,28 @@ useLoad(() => { | ... | @@ -114,8 +181,28 @@ useLoad(() => { |
| 114 | box-sizing: border-box; | 181 | box-sizing: border-box; |
| 115 | } | 182 | } |
| 116 | 183 | ||
| 117 | - .home-banner { | 184 | + .home-top-banner { |
| 185 | + position: relative; | ||
| 118 | margin: -32rpx -32rpx 0; | 186 | margin: -32rpx -32rpx 0; |
| 187 | + } | ||
| 188 | + | ||
| 189 | + .mock-state-badge { | ||
| 190 | + position: absolute; | ||
| 191 | + top: 20rpx; | ||
| 192 | + right: 20rpx; | ||
| 193 | + z-index: 3; | ||
| 194 | + padding: 8rpx 16rpx; | ||
| 195 | + border-radius: 999rpx; | ||
| 196 | + background: rgba(0, 0, 0, 0.42); | ||
| 197 | + font-size: 20rpx; | ||
| 198 | + line-height: 1; | ||
| 199 | + color: #ffffff; | ||
| 200 | + letter-spacing: 1rpx; | ||
| 201 | + text-transform: uppercase; | ||
| 202 | + pointer-events: none; | ||
| 203 | + } | ||
| 204 | + | ||
| 205 | + .home-banner { | ||
| 119 | height: 420rpx; | 206 | height: 420rpx; |
| 120 | overflow: hidden; | 207 | overflow: hidden; |
| 121 | background: #e5e7eb; | 208 | background: #e5e7eb; | ... | ... |
| 1 | /* | 1 | /* |
| 2 | * @Description: API 环境配置 | 2 | * @Description: API 环境配置 |
| 3 | + * 现在接口有的没有 f, 有的 f 不一样, 每个接口单独传 f 参数 | ||
| 3 | * @Note: 当前环境只由构建配置控制;本地开发默认 mock,生产构建默认正式环境 | 4 | * @Note: 当前环境只由构建配置控制;本地开发默认 mock,生产构建默认正式环境 |
| 4 | */ | 5 | */ |
| 5 | 6 | ||
| ... | @@ -9,7 +10,7 @@ export const API_ENVIRONMENTS = { | ... | @@ -9,7 +10,7 @@ export const API_ENVIRONMENTS = { |
| 9 | label: '正式环境', | 10 | label: '正式环境', |
| 10 | baseURL: 'https://oa.onwall.cn', | 11 | baseURL: 'https://oa.onwall.cn', |
| 11 | requestDefaultParams: { | 12 | requestDefaultParams: { |
| 12 | - f: 'room', | 13 | + // f: 'room', |
| 13 | client_id: '772428', | 14 | client_id: '772428', |
| 14 | }, | 15 | }, |
| 15 | useMock: false, | 16 | useMock: false, |
| ... | @@ -19,7 +20,7 @@ export const API_ENVIRONMENTS = { | ... | @@ -19,7 +20,7 @@ export const API_ENVIRONMENTS = { |
| 19 | label: '本地 Mock 环境', | 20 | label: '本地 Mock 环境', |
| 20 | baseURL: 'https://oa.onwall.cn', | 21 | baseURL: 'https://oa.onwall.cn', |
| 21 | requestDefaultParams: { | 22 | requestDefaultParams: { |
| 22 | - f: 'room', | 23 | + // f: 'room', |
| 23 | client_id: '772428', | 24 | client_id: '772428', |
| 24 | }, | 25 | }, |
| 25 | useMock: true, | 26 | useMock: true, | ... | ... |
-
Please register or login to post a comment