Files
Sansheng-Intelligence/public/assets/js/render-intelligence.js
T

204 lines
7.7 KiB
JavaScript
Raw Normal View History

import { state } from "./render-intelligence-state.js?v=20260814e";
import { TEXT, create, detectViewerCountry, currentTranslationProvider, formatVerified, sectionItems, matchesFilters, makeCard, renderCalendar } from "./render-intelligence-core.js?v=20260817a";
import { renderExhibitions, renderPolicies, renderStandards, renderTrendNews, renderTrendSearchHub, trendItems } from "./render-intelligence-scenes.js?v=20260814i";
import { renderActivities } from "./render-intelligence-activities.js?v=20260814h";
import { renderPlatforms } from "./render-intelligence-platforms.js?v=20260817a";
function renderStats(data, container) {
if (!container) return;
container.innerHTML = "";
const values = [
["新增权威源", `${data.source_success || 0}/${data.source_target || 0}`],
["总体源基线", data.total_source_baseline || 0],
["重点备货商机", data.summary?.calendar_featured || data.summary?.calendar_insights || 0],
["已核实展会", data.summary?.exhibitions || 0],
["政策与召回", data.summary?.policies || 0],
["重点销售平台", data.summary?.platforms || data.platforms?.length || 0],
["可参加活动", data.summary?.activities || data.activities?.length || 0],
];
values.forEach(([label, value]) => {
const node = create("div", "intelligence-stat");
node.append(create("span", "", label), create("strong", "", String(value)));
container.appendChild(node);
});
}
function renderTabs(data, container, render) {
if (!container) return;
container.innerHTML = "";
Object.entries(TEXT.tabs).forEach(([key, label]) => {
const button = create("button", `intelligence-tab${state.activeSection === key ? " active" : ""}`, label);
button.type = "button";
button.setAttribute("role", "tab");
button.setAttribute("aria-selected", String(state.activeSection === key));
button.setAttribute("aria-controls", "intelligenceList");
const count = key === "today"
? data.today?.length
: (key === "calendar"
? (data.calendar_insights?.length || data.calendar?.length)
: (key === "standards" ? ((data.standards?.length || 0) + trendItems(data).length) : data[key]?.length));
button.appendChild(create("span", "intelligence-tab-count", String(count || 0)));
button.addEventListener("click", () => {
state.activeSection = key;
render();
state.onStateChange?.();
});
container.appendChild(button);
});
}
function renderRegionOptions(data, select) {
if (!select) return;
const regionField = typeof select.closest === "function" ? select.closest("label") : null;
if (regionField) regionField.hidden = state.activeSection === "calendar";
const previous = state.region;
select.innerHTML = "";
if (state.activeSection === "calendar") {
state.region = "";
select.disabled = true;
const calendarOption = create("option", "", "使用下方日历市场筛选");
calendarOption.value = "";
select.appendChild(calendarOption);
return;
}
select.disabled = false;
const sourceItems = state.activeSection === "today" ? (data.today || []) : (data[state.activeSection] || []);
const regions = new Set(sourceItems.map((item) => item.region).filter(Boolean));
const all = create("option", "", TEXT.allRegions);
all.value = "";
select.appendChild(all);
[...regions].sort((a, b) => a.localeCompare(b, "zh-CN")).forEach((value) => {
const option = create("option", "", value);
option.value = value;
select.appendChild(option);
});
select.value = regions.has(previous) ? previous : "";
state.region = select.value;
}
function renderList(data, container) {
if (!container) return;
const filtered = sectionItems(data).filter(matchesFilters);
container.innerHTML = "";
["calendar", "exhibitions", "policies", "standards", "platforms", "activities"].forEach((section) => {
container.classList.toggle(`is-${section}`, state.activeSection === section);
});
container.classList.toggle("is-today", state.activeSection === "today");
if (!filtered.length) {
const empty = create("div", "intelligence-empty", TEXT.empty);
container.appendChild(empty);
return;
}
if (state.activeSection === "calendar") {
renderCalendar(data, container);
return;
}
if (state.activeSection === "today") {
const header = create("section", "today-briefing");
header.append(
create("strong", "", `今天有 ${filtered.length} 件值得处理的事`),
create("span", "", "按截止时间、经营相关性和风险动态排序;继续下滑可查看全部事项"),
);
container.appendChild(header);
}
if (state.activeSection === "exhibitions") {
renderExhibitions(data, container);
return;
}
if (state.activeSection === "policies") {
renderPolicies(data, container);
return;
}
if (state.activeSection === "standards") {
renderStandards(data, container);
return;
}
if (state.activeSection === "platforms") {
renderPlatforms(data, container);
return;
}
if (state.activeSection === "activities") {
renderActivities(data.activities || [], container, currentTranslationProvider());
return;
}
const visible = filtered;
visible.forEach((item) => container.appendChild(makeCard(item)));
}
export function setIntelligenceSection(value) {
if (value && Object.prototype.hasOwnProperty.call(TEXT.tabs, value)) state.activeSection = value;
}
export function getIntelligenceSection() {
return state.activeSection;
}
export function renderIntelligence(data, options = {}) {
state.currentData = data;
if (!state.calendarYear) {
state.calendarYear = Number(String(data.as_of_date || "").slice(0, 4));
state.calendarMonth = 0;
}
state.onStateChange = options.onStateChange || null;
const root = options.root || document.getElementById("intelligencePanel");
if (!root || !data) return;
const stats = root.querySelector("#intelligenceStats");
const tabs = root.querySelector("#intelligenceTabs");
const list = root.querySelector("#intelligenceList");
const search = root.querySelector("#intelligenceSearch");
const regionSelect = root.querySelector("#intelligenceRegion");
const updated = root.querySelector("#intelligenceUpdatedAt");
const rerender = () => {
renderTabs(state.currentData, tabs, rerender);
renderList(state.currentData, list);
};
state.activeIntelligenceRerender = rerender;
renderStats(data, stats);
renderRegionOptions(data, regionSelect);
renderTabs(data, tabs, rerender);
renderList(data, list);
if (updated) updated.textContent = `核验时间:${formatVerified(data.generated_at)}`;
if (search && !search.dataset.bound) {
search.dataset.bound = "1";
search.placeholder = TEXT.searchPlaceholder;
search.addEventListener("input", (event) => {
state.query = event.target.value;
renderList(state.currentData, list);
});
}
if (regionSelect && !regionSelect.dataset.bound) {
regionSelect.dataset.bound = "1";
regionSelect.addEventListener("change", (event) => {
state.region = event.target.value;
renderList(state.currentData, list);
});
}
detectViewerCountry();
}
export async function shareIntelligence() {
const shareData = {
title: "家纺跨境情报 · 每日机会与风险提醒",
text: "全球备货日历、家纺展会、跨境政策与趋势雷达",
url: window.location.href,
};
try {
if (navigator.share) {
await navigator.share(shareData);
return "已打开系统分享面板";
}
await navigator.clipboard.writeText(shareData.url);
return "分享链接已复制,可粘贴到微信或企业微信";
} catch (error) {
if (error?.name === "AbortError") return "已取消分享";
console.error("[家纺跨境情报] 分享失败:", error);
throw error;
}
}
state.renderList = renderList;