feat: load ticket home from scenic api
This commit is contained in:
@@ -1,31 +1,77 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="h-screen min-w-0 overflow-hidden bg-[#f5f7fa] text-[#172033]">
|
<view class="h-screen min-w-0 overflow-hidden bg-[#f5f7fa] text-[#172033]">
|
||||||
<TicketHome
|
<TicketHome
|
||||||
:scenic-spot="SCENIC_SPOT"
|
v-if="homeData"
|
||||||
:groups="visibleGroups"
|
:home-data="homeData"
|
||||||
:products="ticketStore.products"
|
|
||||||
@back="goBack"
|
@back="goBack"
|
||||||
@open-travelers="openTravelers"
|
@open-travelers="openTravelers"
|
||||||
@open-orders="openOrders"
|
@open-orders="openOrders"
|
||||||
@open-detail="openProductDetail"
|
@open-detail="openProductDetail"
|
||||||
@buy="startBooking"
|
@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>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<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 TicketHome from "./components/TicketHome.vue";
|
||||||
import { GROUPS, SCENIC_SPOT } from "./data.js";
|
import { scenicProductHome } from "./api/scenic.js";
|
||||||
import { useTicketStore } from "./store.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 goBack = () => uni.navigateBack();
|
||||||
const openTravelers = () =>
|
const openTravelers = () =>
|
||||||
uni.navigateTo({ url: "/pages-service/tickets/travelers" });
|
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/);
|
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 () => {
|
test("product detail is an independent prototype-aligned page", async () => {
|
||||||
const indexPage = await readTicketFile("index.vue");
|
const indexPage = await readTicketFile("index.vue");
|
||||||
const detailPage = await readTicketFile("product-detail.vue");
|
const detailPage = await readTicketFile("product-detail.vue");
|
||||||
|
|||||||
Reference in New Issue
Block a user