- 新增客片案例全流程功能,包含前台页面、管理端配置、后端API、数据库迁移与文档 - 新增团队共创详情页面与对应接口 - 重构玩法模块:将静态playData替换为动态API获取,拆分类型定义到playTypes.ts - 优化vite构建配置与环境变量处理,调整详情页操作栏文案 - 更新全量相关文档与配图,新增客片案例、团队共创API文档 - 新增测试用例,完善数据归一化逻辑 - 调整路由配置与环境变量示例文件
80 lines
3.2 KiB
Vue
80 lines
3.2 KiB
Vue
<template>
|
|
<view class="wq-page">
|
|
<view class="wq-phone">
|
|
<scroll-view scroll-y class="h-screen bg-white no-scrollbar" :show-scrollbar="false">
|
|
<view v-if="loading" class="flex min-h-[360px] items-center justify-center text-[13px] text-[#aaa3a0]">
|
|
<text>正在加载团队共创详情</text>
|
|
</view>
|
|
<view v-else-if="!detail" class="flex min-h-[360px] flex-col items-center justify-center px-5 text-center">
|
|
<text class="text-[14px] font-medium text-[#151515]">暂时找不到这个团队共创</text>
|
|
<button class="mt-4 rounded-[8px] bg-[#008577] px-4 py-2 text-[13px] text-white"
|
|
@click="goBack()">返回首页</button>
|
|
</view>
|
|
<view v-else class="pb-10">
|
|
<view class="relative h-[280px] overflow-hidden bg-[#1f302d]">
|
|
<image class="h-full w-full" :src="detail.image" mode="aspectFill" />
|
|
<view
|
|
class="absolute inset-x-0 bottom-0 bg-gradient-to-t from-black/75 via-black/35 to-transparent px-5 pb-6 pt-16 text-white">
|
|
<text class="block text-[10px] uppercase tracking-[0.3em] text-white/75">{{ detail.tag }}</text>
|
|
<text class="mt-2 block text-[30px] font-semibold leading-[1.15] tracking-[0.04em]">{{ detail.title
|
|
}}</text>
|
|
<text class="mt-2 block text-[14px] leading-5 text-white/85">{{ detail.detailSubtitle }}</text>
|
|
</view>
|
|
</view>
|
|
<view v-if="fallbackNotice"
|
|
class="mx-5 mt-5 rounded-[8px] bg-[#fff8ed] px-3 py-2 text-[12px] leading-5 text-[#a67842]">
|
|
{{ fallbackNotice }}
|
|
</view>
|
|
<view class="space-y-6 px-5 py-8">
|
|
<text v-for="(paragraph, index) in detail.detailParagraphs" :key="`${detail.id}-${index}`"
|
|
class="block text-[15px] leading-8 tracking-[0.03em] text-[#34302d]">
|
|
{{ paragraph }}
|
|
</text>
|
|
</view>
|
|
</view>
|
|
</scroll-view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref } from "vue";
|
|
import { onLoad } from "@dcloudio/uni-app";
|
|
import { fetchPublicTeamBuildingDetail } from "@/lib/api";
|
|
import { goBack } from "@/lib/navigation";
|
|
import {
|
|
homeTeamBuildingFallback,
|
|
normalizeHomeTeamBuildingDetail,
|
|
type HomeTeamBuilding,
|
|
} from "@/pages/home/components/homeTeamBuildingData";
|
|
|
|
const detail = ref<HomeTeamBuilding | null>(null);
|
|
const loading = ref(true);
|
|
const fallbackNotice = ref("");
|
|
|
|
async function loadDetail(teamBuildingId: string) {
|
|
loading.value = true;
|
|
fallbackNotice.value = "";
|
|
try {
|
|
const response = await fetchPublicTeamBuildingDetail(teamBuildingId);
|
|
detail.value = normalizeHomeTeamBuildingDetail(response);
|
|
} catch {
|
|
const fallback = homeTeamBuildingFallback.find((item) => item.id === teamBuildingId);
|
|
detail.value = fallback ? { ...fallback, detailParagraphs: [...fallback.detailParagraphs] } : null;
|
|
if (detail.value) fallbackNotice.value = "接口暂不可用,当前展示模拟数据";
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
}
|
|
|
|
onLoad((query) => {
|
|
const teamBuildingId = typeof query?.id === "string" ? query.id : "";
|
|
if (!teamBuildingId) {
|
|
detail.value = null;
|
|
loading.value = false;
|
|
return;
|
|
}
|
|
void loadDetail(teamBuildingId);
|
|
});
|
|
</script>
|