feat(pugongying): 将可选字段分为"达人信息"和"粉丝画像"两组

在字段选择下拉列表中添加分组标题,将字段按"达人信息"和"粉丝画像"
两部分展示,搜索过滤时自动隐藏无匹配项的分组标题。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
wxs 2026-03-13 16:28:37 +08:00
parent 572ff95aa9
commit cce8f22e0f

View File

@ -55,6 +55,16 @@
const SELECTABLE_FIELD_PATHS = Object.keys(FIELD_LABEL_MAP).filter(
(path) => !(path in NAMESPACE_LABEL_MAP),
);
const FIELD_GROUPS = [
{
label: "达人信息",
fields: SELECTABLE_FIELD_PATHS.filter((p) => !p.startsWith("fansProfile.")),
},
{
label: "粉丝画像",
fields: SELECTABLE_FIELD_PATHS.filter((p) => p.startsWith("fansProfile.")),
},
];
const STORAGE_INPUT_KEY = "xhs-pgy-export:last-input";
const SCRIPT_FLAG = "__xhsPgyExportMounted__";
@ -896,6 +906,14 @@
padding: 2px;
}
.xhs-export-group-header {
font-size: 12px;
font-weight: 800;
color: #7a6152;
padding: 6px 4px 2px;
border-bottom: 1px solid rgba(141, 88, 51, 0.15);
}
.xhs-export-select-item {
display: grid;
gap: 4px;
@ -1196,24 +1214,36 @@
const search = wrapper.querySelector(".xhs-export-select-search");
const list = wrapper.querySelector(".xhs-export-select-list");
for (const field of fieldOptions) {
const labelText = field.label || field.path;
const item = root.document.createElement("label");
item.className = "xhs-export-select-item";
item.dataset.path = field.path;
item.dataset.label = labelText;
item.innerHTML = `
<div class="xhs-export-select-item-row">
<span class="xhs-export-checkbox">
<input class="xhs-export-checkbox-input" type="checkbox" value="${escapeXml(
field.path,
)}" ${selected.has(field.path) ? "checked" : ""}>
<span class="xhs-export-checkbox-box" aria-hidden="true"></span>
</span>
<span class="xhs-export-field-name">${escapeXml(labelText)}</span>
</div>
`;
list.appendChild(item);
const fieldByPath = new Map(fieldOptions.map((f) => [f.path, f]));
for (const group of FIELD_GROUPS) {
const groupFields = group.fields.filter((p) => fieldByPath.has(p));
if (!groupFields.length) continue;
const header = root.document.createElement("div");
header.className = "xhs-export-group-header";
header.textContent = group.label;
header.dataset.group = group.label;
list.appendChild(header);
for (const path of groupFields) {
const field = fieldByPath.get(path);
const labelText = field.label || field.path;
const item = root.document.createElement("label");
item.className = "xhs-export-select-item";
item.dataset.path = field.path;
item.dataset.label = labelText;
item.dataset.group = group.label;
item.innerHTML = `
<div class="xhs-export-select-item-row">
<span class="xhs-export-checkbox">
<input class="xhs-export-checkbox-input" type="checkbox" value="${escapeXml(
field.path,
)}" ${selected.has(field.path) ? "checked" : ""}>
<span class="xhs-export-checkbox-box" aria-hidden="true"></span>
</span>
<span class="xhs-export-field-name">${escapeXml(labelText)}</span>
</div>
`;
list.appendChild(item);
}
}
const setOpenState = (open) => {
@ -1240,6 +1270,13 @@
const path = String(item.dataset.path || "").toLowerCase();
item.hidden = q ? !(label.includes(q) || path.includes(q)) : false;
}
for (const header of list.querySelectorAll(".xhs-export-group-header")) {
const group = header.dataset.group;
const hasVisible = list.querySelector(
`.xhs-export-select-item[data-group="${group}"]:not([hidden])`,
);
header.hidden = !hasVisible;
}
});
}