feat: load ticket home from scenic api
This commit is contained in:
@@ -1,31 +1,77 @@
|
||||
<template>
|
||||
<view class="h-screen min-w-0 overflow-hidden bg-[#f5f7fa] text-[#172033]">
|
||||
<TicketHome
|
||||
:scenic-spot="SCENIC_SPOT"
|
||||
:groups="visibleGroups"
|
||||
:products="ticketStore.products"
|
||||
v-if="homeData"
|
||||
:home-data="homeData"
|
||||
@back="goBack"
|
||||
@open-travelers="openTravelers"
|
||||
@open-orders="openOrders"
|
||||
@open-detail="openProductDetail"
|
||||
@buy="startBooking"
|
||||
/>
|
||||
|
||||
<view v-else class="flex h-full flex-col">
|
||||
<TopNavBar title="" @back="goBack" />
|
||||
<view
|
||||
v-if="loading"
|
||||
class="flex min-h-0 flex-1 items-center justify-center"
|
||||
>
|
||||
<text class="text-[14px] text-[#808997]">正在加载景区商品...</text>
|
||||
</view>
|
||||
<view
|
||||
v-else-if="errorMessage"
|
||||
class="flex min-h-0 flex-1 flex-col items-center justify-center px-[32px] text-center"
|
||||
>
|
||||
<text class="text-[14px] leading-[21px] text-[#808997]">
|
||||
{{ errorMessage }}
|
||||
</text>
|
||||
<view
|
||||
class="mt-[18px] flex h-[38px] items-center justify-center rounded-full bg-[#149474] px-[22px]"
|
||||
@click="loadTicketHome"
|
||||
>
|
||||
<text class="text-[13px] font-medium text-white">重新加载</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from "vue";
|
||||
import { onMounted, ref } from "vue";
|
||||
import TopNavBar from "@/components/TopNavBar/index.vue";
|
||||
import TicketHome from "./components/TicketHome.vue";
|
||||
import { GROUPS, SCENIC_SPOT } from "./data.js";
|
||||
import { useTicketStore } from "./store.js";
|
||||
import { scenicProductHome } from "./api/scenic.js";
|
||||
|
||||
const ticketStore = useTicketStore();
|
||||
const homeData = ref(null);
|
||||
const loading = ref(false);
|
||||
const errorMessage = ref("");
|
||||
|
||||
const loadTicketHome = async () => {
|
||||
loading.value = true;
|
||||
errorMessage.value = "";
|
||||
|
||||
try {
|
||||
const response = await scenicProductHome({ scenicId: 20260811 });
|
||||
const validData =
|
||||
response?.data &&
|
||||
typeof response.data === "object" &&
|
||||
!Array.isArray(response.data);
|
||||
|
||||
if (response?.code !== 0 || !validData) {
|
||||
throw new Error(response?.msg || "景区商品加载失败,请稍后重试");
|
||||
}
|
||||
|
||||
homeData.value = response.data;
|
||||
} catch (error) {
|
||||
homeData.value = null;
|
||||
errorMessage.value = error?.message || "景区商品加载失败,请稍后重试";
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(loadTicketHome);
|
||||
|
||||
const visibleGroups = computed(() =>
|
||||
[...GROUPS]
|
||||
.filter((group) => group.enabled)
|
||||
.sort((left, right) => left.sortOrder - right.sortOrder)
|
||||
);
|
||||
const goBack = () => uni.navigateBack();
|
||||
const openTravelers = () =>
|
||||
uni.navigateTo({ url: "/pages-service/tickets/travelers" });
|
||||
|
||||
@@ -63,6 +63,25 @@ test("storefront synchronizes the left category from right-column scrolling", as
|
||||
assert.match(source, /TopNavBar/);
|
||||
});
|
||||
|
||||
test("ticket storefront loads API home data without a static adapter", async () => {
|
||||
const source = await readTicketFile("index.vue");
|
||||
|
||||
assert.match(
|
||||
source,
|
||||
/import \{ scenicProductHome \} from "\.\/api\/scenic\.js"/
|
||||
);
|
||||
assert.match(source, /scenicProductHome\(\{ scenicId: 20260811 \}\)/);
|
||||
assert.match(source, /const homeData = ref\(null\)/);
|
||||
assert.match(source, /:home-data="homeData"/);
|
||||
assert.match(source, /v-if="loading"/);
|
||||
assert.match(source, /v-else-if="errorMessage"/);
|
||||
assert.match(source, /@click="loadTicketHome"/);
|
||||
assert.doesNotMatch(
|
||||
source,
|
||||
/SCENIC_SPOT|GROUPS|ticketStore\.products|visibleGroups/
|
||||
);
|
||||
});
|
||||
|
||||
test("product detail is an independent prototype-aligned page", async () => {
|
||||
const indexPage = await readTicketFile("index.vue");
|
||||
const detailPage = await readTicketFile("product-detail.vue");
|
||||
|
||||
Reference in New Issue
Block a user