diff --git a/.superpowers/brainstorm/team-building-20260819-visual/state/server-info b/.superpowers/brainstorm/team-building-20260819-visual/state/server-info deleted file mode 100644 index 496ad36..0000000 --- a/.superpowers/brainstorm/team-building-20260819-visual/state/server-info +++ /dev/null @@ -1 +0,0 @@ -{"type":"server-started","port":63862,"host":"0.0.0.0","url_host":"127.0.0.1","url":"http://127.0.0.1:63862","screen_dir":"D:\\www\\znkj\\WonderQ-Project\\.superpowers\\brainstorm\\team-building-20260819-visual\\content","state_dir":"D:\\www\\znkj\\WonderQ-Project\\.superpowers\\brainstorm\\team-building-20260819-visual\\state"} diff --git a/.superpowers/brainstorm/team-building-20260819-visual/state/server-stopped b/.superpowers/brainstorm/team-building-20260819-visual/state/server-stopped new file mode 100644 index 0000000..c0242e3 --- /dev/null +++ b/.superpowers/brainstorm/team-building-20260819-visual/state/server-stopped @@ -0,0 +1 @@ +{"reason":"idle timeout","timestamp":1787142361651} diff --git a/WonderQ-Admin-UI/src/api.ts b/WonderQ-Admin-UI/src/api.ts index ab49cd5..0dbbd7d 100644 --- a/WonderQ-Admin-UI/src/api.ts +++ b/WonderQ-Admin-UI/src/api.ts @@ -120,6 +120,31 @@ export type WanfaRouteCreate = { export type WanfaRoutePatch = Partial; +export type DetailRecord = { + id: string; + key: string; + eyebrow: string; + duration: string; + title: string; + subtitle: string; + intro: string; + highlights: string[]; + included: string[]; + excluded: string[]; + notes: string[]; + gallery: string[]; + isActive: boolean; + sortOrder: number; + createdAt?: string; + updatedAt?: string; +}; + +export type DetailCreate = Omit & { + sortOrder?: number; +}; + +export type DetailPatch = Partial; + export type ConciergeDetail = { icon: string; label: string; @@ -391,6 +416,39 @@ export async function reorderWanfaRoutes(categoryId: string, itemIds: string[]) }); } +export async function getDetails() { + return request<{ details: DetailRecord[] }>("/api/admin/details"); +} + +export async function getDetail(detailId: string) { + return request(`/api/admin/details/${detailId}`); +} + +export async function createDetail(input: DetailCreate) { + return request("/api/admin/details", { + method: "POST", + body: JSON.stringify(input), + }); +} + +export async function updateDetail(detailId: string, input: DetailPatch) { + return request(`/api/admin/details/${detailId}`, { + method: "PATCH", + body: JSON.stringify(input), + }); +} + +export async function deleteDetail(detailId: string) { + return request<{ id: string }>(`/api/admin/details/${detailId}`, { method: "DELETE" }); +} + +export async function reorderDetails(itemIds: string[]) { + return request<{ items: DetailRecord[] }>("/api/admin/details/reorder", { + method: "PATCH", + body: JSON.stringify({ itemIds }), + }); +} + export async function getConciergeAdvisors() { return request<{ advisors: ConciergeAdvisor[] }>('/api/admin/concierge/advisors'); } diff --git a/WonderQ-Admin-UI/src/components/admin/WanfaRouteDetailFields.tsx b/WonderQ-Admin-UI/src/components/admin/WanfaRouteDetailFields.tsx new file mode 100644 index 0000000..56ed514 --- /dev/null +++ b/WonderQ-Admin-UI/src/components/admin/WanfaRouteDetailFields.tsx @@ -0,0 +1,121 @@ +import type { DetailCreate } from "@/api"; +import { Input } from "@/components/ui/input"; +import { Textarea } from "@/components/ui/textarea"; + +const detailArrayFields = [ + ["highlights", "行程亮点", "每行填写一项亮点"], + ["included", "费用包含", "每行填写一项包含内容"], + ["excluded", "费用不含", "每行填写一项不包含内容"], + ["notes", "注意事项", "每行填写一项注意事项"], + ["gallery", "详情图片画廊", "每行填写一个 http(s) 图片地址"], +] as const; + +type DetailArrayField = (typeof detailArrayFields)[number][0]; + +export function WanfaRouteDetailFields({ + detail, + onChange, +}: { + detail: DetailCreate; + onChange: (key: K, value: DetailCreate[K]) => void; +}) { + const updateLines = (key: DetailArrayField, value: string) => { + onChange( + key, + value + .split("\n") + .map((item) => item.trim()) + .filter(Boolean), + ); + }; + + return ( +
+
+

路线详情

+

+ 详情内容由独立详情接口维护,数组字段按每行一项保存。 +

+
+
+ + + +