feat: add customer travel records and browse history

This commit is contained in:
duanshuwen
2026-08-27 14:19:03 +08:00
parent 0139fe6382
commit 6d9a546918
79 changed files with 12362 additions and 112 deletions

View File

@@ -0,0 +1,64 @@
import { afterEach, describe, expect, it, vi } from "vitest";
import * as api from "@/lib/api";
const customerRecordsApi = api as typeof api & {
createCustomerBrowseHistory: (payload: { itemType: string; itemId: string }, token: string) => Promise<unknown>;
fetchCustomerBrowseHistory: (token: string, pageNum: number, pageSize: number) => Promise<unknown>;
fetchCustomerVehicleDemand: (leadId: string, token: string) => Promise<unknown>;
fetchCustomerVehicleDemands: (token: string, pageNum: number, pageSize: number) => Promise<unknown>;
};
describe("customer records API client", () => {
afterEach(() => vi.unstubAllGlobals());
function requestPath(url: string) {
return url.startsWith("http") ? new URL(url).pathname : url;
}
it("requests the authenticated vehicle demand page and detail", async () => {
const request = vi.fn()
.mockImplementationOnce((options) => options.success({
statusCode: 200,
data: { code: 200, msg: "success", data: { items: [], total: 0, pageNum: 2, pageSize: 20 } },
}))
.mockImplementationOnce((options) => options.success({
statusCode: 200,
data: { code: 200, msg: "success", data: { id: "lead-1" } },
}));
vi.stubGlobal("uni", { request });
expect(typeof customerRecordsApi.fetchCustomerVehicleDemands).toBe("function");
expect(typeof customerRecordsApi.fetchCustomerVehicleDemand).toBe("function");
await customerRecordsApi.fetchCustomerVehicleDemands("customer-token", 2, 20);
await customerRecordsApi.fetchCustomerVehicleDemand("lead-1", "customer-token");
expect(request.mock.calls.map(([options]) => [requestPath(options.url), options.method, options.data, options.header.Authorization])).toEqual([
["/api/public/customer/vehicle-demands", "GET", { pageNum: 2, pageSize: 20 }, "Bearer customer-token"],
["/api/public/customer/vehicle-demands/lead-1", "GET", undefined, "Bearer customer-token"],
]);
});
it("requests browse history pages and records a viewed item with the customer token", async () => {
const request = vi.fn()
.mockImplementationOnce((options) => options.success({
statusCode: 200,
data: { code: 200, msg: "success", data: { items: [], total: 0, pageNum: 1, pageSize: 20 } },
}))
.mockImplementationOnce((options) => options.success({
statusCode: 201,
data: { code: 201, msg: "success", data: { itemId: "family-water" } },
}));
vi.stubGlobal("uni", { request });
expect(typeof customerRecordsApi.fetchCustomerBrowseHistory).toBe("function");
expect(typeof customerRecordsApi.createCustomerBrowseHistory).toBe("function");
await customerRecordsApi.fetchCustomerBrowseHistory("customer-token", 1, 20);
await customerRecordsApi.createCustomerBrowseHistory({ itemType: "wanfa-route", itemId: "family-water" }, "customer-token");
expect(request.mock.calls.map(([options]) => [requestPath(options.url), options.method, options.data, options.header.Authorization])).toEqual([
["/api/public/customer/browse-history", "GET", { pageNum: 1, pageSize: 20 }, "Bearer customer-token"],
["/api/public/customer/browse-history", "POST", { itemType: "wanfa-route", itemId: "family-water" }, "Bearer customer-token"],
]);
});
});

View File

@@ -0,0 +1,30 @@
import { describe, expect, it } from "vitest";
import mineRecentViewsSource from "@/pages/mine/components/MineRecentViews.vue?raw";
import vehicleSource from "@/pages/mine/vehicle-demands/index.vue?raw";
import historySource from "@/pages/mine/browse-history/index.vue?raw";
import routeDetailSource from "@/pages/detail/index.vue?raw";
import teamDetailSource from "@/pages/team-buildings/detail.vue?raw";
import wildDetailSource from "@/pages/wild-archives/detail.vue?raw";
describe("mine customer records pages", () => {
it("keeps MineRecentViews focused on the two record entries", () => {
expect(mineRecentViewsSource).toContain("用车提交记录");
expect(mineRecentViewsSource).toContain("历史浏览记录");
expect(mineRecentViewsSource).not.toContain("v-for=\"(item, index) in items\"");
expect(mineRecentViewsSource).not.toContain("暂无浏览记录");
});
it("uses z-paging query mode for both paginated lists", () => {
for (const source of [vehicleSource, historySource]) {
expect(source).toContain("<z-paging");
expect(source).toContain('@query="queryList"');
expect(source).toContain("completeByTotal");
}
});
it("syncs successful detail visits through the customer history API", () => {
for (const source of [routeDetailSource, teamDetailSource, wildDetailSource]) {
expect(source).toContain("syncRecentlyViewed");
}
});
});

View File

@@ -4,17 +4,20 @@ import mineRecentViewsSource from "@/pages/mine/components/MineRecentViews.vue?r
import minePageSource from "@/pages/mine/index.vue?raw";
describe("mine travel records integration contract", () => {
it("keeps vehicle demand and recent views in one list", () => {
it("keeps vehicle demands and browse history as two entries", () => {
expect(mineRecentViewsSource).toContain("我的出行记录");
expect(mineRecentViewsSource).toContain("用车需求与最近浏览集中在这里");
expect(mineRecentViewsSource).toContain("items.length + 1");
expect(mineRecentViewsSource).toContain("open-vehicle");
expect(mineRecentViewsSource).toContain("暂无浏览记录");
expect(mineRecentViewsSource).toContain("用车需求与历史浏览集中在这里");
expect(mineRecentViewsSource).toContain("用车提交记录");
expect(mineRecentViewsSource).toContain("历史浏览记录");
expect(mineRecentViewsSource).not.toContain("暂无浏览记录");
});
it("wires the vehicle demand action through MineMember to the existing page", () => {
expect(mineMemberSource).toContain('@open-vehicle="emit(\'open-vehicle\')"');
expect(minePageSource).toContain("goVehicleDemand");
expect(minePageSource).toContain('@open-vehicle="goVehicleDemand"');
it("wires both entries from MineMember to their list pages", () => {
expect(mineMemberSource).toContain('@open-vehicle-demands="emit(\'open-vehicle-demands\')"');
expect(mineMemberSource).toContain('@open-browse-history="emit(\'open-browse-history\')"');
expect(minePageSource).toContain("goCustomerVehicleDemands");
expect(minePageSource).toContain("goCustomerBrowseHistory");
expect(minePageSource).toContain('@open-vehicle-demands="goCustomerVehicleDemands"');
expect(minePageSource).toContain('@open-browse-history="goCustomerBrowseHistory"');
});
});

View File

@@ -1,6 +1,11 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
import { goWanfaRouteDetail } from "@/lib/navigation";
import {
goCustomerBrowseHistory,
goCustomerVehicleDemandDetail,
goCustomerVehicleDemands,
goWanfaRouteDetail,
} from "@/lib/navigation";
describe("wanfa route detail navigation", () => {
const navigateTo = vi.fn();
@@ -17,4 +22,20 @@ describe("wanfa route detail navigation", () => {
url: "/pages/detail/index?routeId=family%20water",
});
});
it("opens the two customer record entries and encodes detail ids", () => {
goCustomerVehicleDemands();
goCustomerBrowseHistory();
goCustomerVehicleDemandDetail("lead 1");
expect(navigateTo).toHaveBeenNthCalledWith(1, {
url: "/pages/mine/vehicle-demands/index",
});
expect(navigateTo).toHaveBeenNthCalledWith(2, {
url: "/pages/mine/browse-history/index",
});
expect(navigateTo).toHaveBeenNthCalledWith(3, {
url: "/pages/mine/vehicle-demand-detail?id=lead%201",
});
});
});