"use strict"; const common_vendor = require("../../common/vendor.js"); const utils_request = require("../../utils/request.js"); const CACHE_KEY = "products_cache_v1"; const TTL_MS = 10 * 60 * 1e3; const _sfc_main = { __name: "index", setup(__props) { const products = common_vendor.ref([]); const columns = common_vendor.ref([[], []]); const colHeights = common_vendor.ref([0, 0]); const loading = common_vendor.ref(false); const keyword = common_vendor.ref(""); const minPrice = common_vendor.ref(""); const maxPrice = common_vendor.ref(""); const displayCount = common_vendor.computed(() => columns.value[0].length + columns.value[1].length); const loadedMap = common_vendor.ref({}); function getKey(p) { return String((p && p.id) ?? "") + "|" + String((p && p.image) ?? ""); } function unwrap(list) { if (Array.isArray(list)) return list; const obj = list || {}; const data = obj.data || {}; const arr = obj.list || obj.items || data.list || data.items || data; return Array.isArray(arr) ? arr : []; } function cleanUrl(u) { const s = String(u || "").trim(); const m = s.match(/https?:\/\/[^\s'"`]+/); if (m && m[0]) return m[0]; return s.replace(/[`'\"]/g, "").trim(); } function apiGet(url, data = {}) { const token = common_vendor.index.getStorageSync("token"); const fn = token ? utils_request.authRequest : utils_request.request; return fn({ url, method: "GET", data }); } function getCachedProducts() { try { const obj = common_vendor.index.getStorageSync(CACHE_KEY); if (obj && Array.isArray(obj.data) && typeof obj.ts === "number") { const fresh = Date.now() - obj.ts < TTL_MS; if (fresh) return obj.data; } } catch (_) { } return null; } function setCachedProducts(list) { try { common_vendor.index.setStorageSync(CACHE_KEY, { data: Array.isArray(list) ? list : [], ts: Date.now() }); } catch (_) { } } function estimateHeight(p) { const base = 220; const len = String(p.title || "").length; const lines = Math.min(2, Math.ceil(len / 12)); const titleH = lines * 36; const stockH = p.stock !== null && p.stock !== void 0 ? 34 : 0; const padding = 28; return base + titleH + stockH + padding; } function distributeToColumns(list) { const arr = Array.isArray(list) ? list : []; const cols = Array.from({ length: 2 }, () => []); const hs = [0, 0]; for (let i = 0; i < arr.length; i++) { const h = estimateHeight(arr[i]); const idx = hs[0] <= hs[1] ? 0 : 1; cols[idx].push(arr[i]); hs[idx] += h; } columns.value = cols; colHeights.value = hs; const presentKeys = new Set(arr.map(getKey)); const next = {}; const prev = loadedMap.value || {}; for (const k in prev) { if (presentKeys.has(k)) next[k] = prev[k]; } loadedMap.value = next; } function extractListAndTotal(payload) { if (Array.isArray(payload)) return { list: payload, total: payload.length }; const obj = payload || {}; const data = obj.data || {}; const list = obj.list || obj.items || data.list || data.items || []; const totalRaw = obj.total ?? data.total; const total = typeof totalRaw === "number" ? totalRaw : Array.isArray(list) ? list.length : 0; return { list: Array.isArray(list) ? list : [], total }; } function normalizeProducts(list) { const arr = unwrap(list); return arr.map((i, idx) => ({ id: i.id ?? i.productId ?? i._id ?? i.sku_id ?? String(idx), image: cleanUrl(i.main_image ?? i.imageUrl ?? i.image_url ?? i.image ?? i.img ?? i.pic ?? ""), title: i.title ?? i.name ?? i.product_name ?? i.sku_name ?? "", price: i.price_sale ?? i.price ?? i.price_min ?? i.amount ?? null, points: i.points_required ?? i.points ?? i.integral ?? null, stock: i.stock ?? i.inventory ?? i.quantity ?? null, link: cleanUrl(i.linkUrl ?? i.link_url ?? i.link ?? i.url ?? "") })).filter((i) => i.image || i.title); } function onProductTap(p) { const imgs = (Array.isArray(products.value) ? products.value : []).map((x) => x.image).filter(Boolean); const current = p && p.image; if (current) { common_vendor.index.previewImage({ urls: imgs.length ? imgs : [current], current }); return; } if (p.link && /^\/.+/.test(p.link)) { common_vendor.index.navigateTo({ url: p.link }); } } function applyFilters() { const k = String(keyword.value || "").trim().toLowerCase(); const min = Number(minPrice.value); const max = Number(maxPrice.value); const hasMin = !isNaN(min) && String(minPrice.value).trim() !== ""; const hasMax = !isNaN(max) && String(maxPrice.value).trim() !== ""; const list = Array.isArray(products.value) ? products.value : []; const filtered = list.filter((p) => { const title = String(p.title || "").toLowerCase(); if (k && !title.includes(k)) return false; const priceNum = typeof p.price === "number" ? p.price : Number(p.price); if (hasMin) { if (isNaN(priceNum)) return false; if (priceNum < min) return false; } if (hasMax) { if (isNaN(priceNum)) return false; if (priceNum > max) return false; } return true; }); distributeToColumns(filtered); } function onSearchConfirm() { applyFilters(); } function onApplyFilters() { applyFilters(); } async function loadProducts() { try { const cached = getCachedProducts(); if (cached) { products.value = cached; distributeToColumns(cached); return; } const first = await apiGet("/api/app/products", { page: 1 }); const { list: firstList, total } = extractListAndTotal(first); const pageSize = 20; const totalPages = Math.max(1, Math.ceil((typeof total === "number" ? total : 0) / pageSize)); if (totalPages <= 1) { const normalized2 = normalizeProducts(firstList); products.value = normalized2; distributeToColumns(normalized2); setCachedProducts(normalized2); return; } const tasks = []; for (let p = 2; p <= totalPages; p++) { tasks.push(apiGet("/api/app/products", { page: p })); } const results = await Promise.allSettled(tasks); const restLists = results.map((r) => { if (r.status === "fulfilled") { const { list } = extractListAndTotal(r.value); return Array.isArray(list) ? list : []; } return []; }); const merged = [firstList, ...restLists].flat(); const normalized = normalizeProducts(merged); products.value = normalized; distributeToColumns(normalized); setCachedProducts(normalized); } catch (e) { products.value = []; columns.value = [[], []]; colHeights.value = [0, 0]; const presentKeys = /* @__PURE__ */ new Set([]); const next = {}; const prev = loadedMap.value || {}; for (const k in prev) { if (presentKeys.has(k)) next[k] = prev[k]; } loadedMap.value = next; } } function isLoaded(p) { return !!(loadedMap.value && loadedMap.value[getKey(p)]); } function onImageLoad(p) { const k = getKey(p); if (!k) return; loadedMap.value = { ...loadedMap.value || {}, [k]: true }; } function onImageError(p) { const k = getKey(p); if (!k) return; const prev = { ...loadedMap.value || {} }; delete prev[k]; loadedMap.value = prev; } common_vendor.onShow(async () => { const token = common_vendor.index.getStorageSync("token"); const phoneBound = !!common_vendor.index.getStorageSync("phone_bound"); if (!token || !phoneBound) { common_vendor.index.showModal({ title: "提示", content: "请先登录并绑定手机号", confirmText: "去登录", success: (res) => { if (res.confirm) { common_vendor.index.navigateTo({ url: "/pages/login/index" }); } } }); return; } loading.value = true; await loadProducts(); loading.value = false; }); return (_ctx, _cache) => { return common_vendor.e({ a: loading.value }, loading.value ? {} : common_vendor.e({ b: common_vendor.o(onSearchConfirm), c: keyword.value, d: common_vendor.o(($event) => keyword.value = $event.detail.value), e: minPrice.value, f: common_vendor.o(($event) => minPrice.value = $event.detail.value), g: maxPrice.value, h: common_vendor.o(($event) => maxPrice.value = $event.detail.value), i: common_vendor.o(onApplyFilters), j: displayCount.value }, displayCount.value ? { k: common_vendor.f(columns.value, (col, ci, i0) => { return { a: common_vendor.f(col, (p, k1, i1) => { return common_vendor.e({ a: isLoaded(p) ? 1 : "", b: p.image, c: common_vendor.o(($event) => onImageLoad(p), p.id), d: common_vendor.o(($event) => onImageError(p), p.id), e: !isLoaded(p) }, !isLoaded(p) ? {} : {}, { f: p.price !== null }, p.price !== null ? { g: common_vendor.t(p.price) } : {}, { h: p.points !== null }, p.points !== null ? { i: common_vendor.t(p.points) } : {}, { j: common_vendor.t(p.title), k: p.stock !== null }, p.stock !== null ? { l: common_vendor.t(p.stock) } : {}, { m: p.id, n: common_vendor.o(($event) => onProductTap(p), p.id) }); }), b: ci }; }) } : {})); }; } }; const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["__scopeId", "data-v-7db6cc15"]]); wx.createPage(MiniProgramPage); //# sourceMappingURL=../../../.sourcemap/mp-weixin/pages/shop/index.js.map