feat:登录的也是mock接口对接

This commit is contained in:
zoujing
2026-09-17 16:24:02 +08:00
parent d723eb1232
commit d759d48e79
37 changed files with 1791 additions and 7498 deletions

View File

@@ -1,199 +0,0 @@
/**
* 一次性数据构建脚本:把 DuohuaDiscovery 的 miniprogram_data.json
* 拆成小程序运行期使用的 mock 数据(字段与未来接口同构)。
*
* 运行node scripts/build-mock.mjs
*/
import fs from "node:fs";
import path from "node:path";
const ROOT = path.resolve(import.meta.dirname, "..");
const SRC = "/Users/gleen/OneFeel/YGChatCS/src/pages/DuohuaDiscovery/data/miniprogram_data.json";
const OUT = path.join(ROOT, "src/mock");
const data = JSON.parse(fs.readFileSync(SRC, "utf8"));
const SECTION_DEFINITIONS = [
{
key: "tourism",
title: "龙里票根经济",
subtitle: "领取龙里旅游优惠",
coverImage:
"https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/longli/miniprogram/attractions/attraction-001/01.jpg",
collections: ["attractions", "attraction_subprojects"],
supportAssetIds: ["tourism-overview-map", "tourism-guide-qr"],
},
{
key: "lodging",
title: "旅居服务",
subtitle: "酒店 · 民宿别院 · 旅居公寓 · 露营基地",
collections: ["accommodations"],
supportAssetIds: ["lodging-location-schematic", "lodging-guide-qr"],
},
{
key: "food",
title: "全域美食",
subtitle: "特色菜肴 · 地方小吃 · 甜品饮品",
collections: ["foods"],
supportAssetIds: ["food-guide-qr"],
},
{
key: "specialties",
title: "龙里特产",
subtitle: "刺梨制品 · 地方食品 · 农产品",
collections: ["specialties"],
supportAssetIds: [],
},
];
const COLLECTIONS = [
{ key: "attractions", label: "景点" },
{ key: "attraction_subprojects", label: "游乐演艺" },
{ key: "accommodations", label: "旅居" },
{ key: "foods", label: "美食" },
{ key: "specialties", label: "特产" },
];
/** 一期 mock源数据无营业时间字段统一占位待运营方按商户补充 */
const MOCK_BUSINESS_HOURS = "09:0022:00";
const DROP_FIELDS = [
"issues",
"source",
"source_no",
"images",
"main_image_object_key",
"gallery_object_keys",
"local_relative_path",
"oss_object_key",
"sha256",
"source_file",
"source_page",
"pdf_image_name",
"pdf_x0",
"pdf_top",
"pdf_x1",
"pdf_bottom",
"conversion_note",
"color_mode",
];
const trim = (obj) => {
const out = {};
for (const [k, v] of Object.entries(obj)) {
if (DROP_FIELDS.includes(k)) continue;
if (v === null || v === undefined || v === "") continue;
out[k] = v;
}
return out;
};
/** 电话归一:源数据里分隔符混用「—」「–」「-」,统一成半角连字符;另给纯数字供 makePhoneCall */
const normalizeContact = (item) => {
const raw = item?.contact?.raw || "";
if (!raw) return null;
const display = raw.replace(/[—–-~\s]/g, "-").replace(/-+/g, "-").replace(/-$/, "");
const dial = display.replace(/\D/g, "");
return { raw, display, dial };
};
/** 地址归一:源数据 address 是对象(含经纬度为 null页面只用一个字符串无地址返回空串页面整行隐藏 */
const normalizeAddress = (item) => {
const addr = item?.address;
if (!addr) return "";
if (typeof addr === "string") return addr;
if (addr.raw || addr.normalized) return addr.raw || addr.normalized;
if (addr.township_or_street) {
return [addr.province, addr.prefecture, addr.county, addr.township_or_street].filter(Boolean).join("");
}
return "";
};
const items = {};
const counts = {};
for (const { key } of COLLECTIONS) {
const list = Array.isArray(data[key]) ? data[key] : [];
let n = 0;
for (const raw of list) {
// 硬约束:过滤 enabled === false
if (raw.enabled === false) continue;
const item = trim(raw);
delete item.enabled;
delete item.address;
item.collection = key;
item.business_hours = item.business_hours || MOCK_BUSINESS_HOURS;
item.contact = normalizeContact(raw);
item.address_text = normalizeAddress(raw);
item.badge = item.subtype || item.category || item.type || "";
items[raw.id] = item;
n += 1;
}
counts[key] = n;
}
/** 分组目录:过滤 enabled=false / 空分组,按 type_order -> sort_within_type 排序 */
const catalog = {};
for (const { key } of COLLECTIONS) {
const groups = Array.isArray(data?.catalog_by_type?.[key]) ? data.catalog_by_type[key] : [];
catalog[key] = groups
.map((group) => {
const ids = (group.items || [])
.filter((it) => items[it.id])
.sort((a, b) => (a.sort_within_type ?? 0) - (b.sort_within_type ?? 0))
.map((it) => it.id);
return {
collection: key,
type_code: group.type_code,
type: group.type,
type_order: group.type_order ?? 0,
item_count: ids.length,
item_ids: ids,
};
})
.filter((group) => group.item_count > 0)
.sort((a, b) => a.type_order - b.type_order);
}
const assets = (data.assets || []).map((a) => ({
asset_id: a.asset_id,
entity_type: a.entity_type,
entity_id: a.entity_id,
entity_name: a.entity_name,
role: a.role,
sort_order: a.sort_order ?? 0,
oss_url: a.oss_url,
width_px: a.width_px,
height_px: a.height_px,
content_type: a.content_type,
}));
const sections = SECTION_DEFINITIONS.map((def) => {
const groups = def.collections.flatMap((c) =>
catalog[c].map((g) => ({ ...g, groupId: `${c}-${g.type_code}` }))
);
const ids = groups.flatMap((g) => g.item_ids);
const first = items[ids[0]];
return {
...def,
group_count: groups.length,
item_count: ids.length,
group_ids: groups.map((g) => g.groupId),
};
});
const write = (name, payload) => {
const file = path.join(OUT, name);
fs.writeFileSync(file, JSON.stringify(payload, null, 0) + "\n", "utf8");
const kb = (fs.statSync(file).size / 1024).toFixed(1);
console.log(`${name.padEnd(16)} ${kb} KB`);
};
fs.mkdirSync(OUT, { recursive: true });
write("sections.json", sections);
write("catalog.json", catalog);
write("items.json", items);
write("assets.json", assets);
console.log("\n集合条数已过滤 enabled=false:", counts);
console.log("items 总数:", Object.keys(items).length);