style: refine market toolbar layout
This commit is contained in:
@@ -162,10 +162,10 @@ export function ensurePluginToolbar(
|
||||
dataGroup.dataset.pluginToolbarGroup = "data";
|
||||
applyToolbarGroupStyles(dataGroup);
|
||||
dataGroup.append(
|
||||
createToolbarGroupTitle(document, "达人数据"),
|
||||
audienceProfileExportButton,
|
||||
audienceProfileByIdExportButton,
|
||||
audienceProfileFieldButton
|
||||
audienceProfileFieldButton,
|
||||
batchSubmitButton
|
||||
);
|
||||
|
||||
const videoGroup = document.createElement("div");
|
||||
@@ -181,30 +181,23 @@ export function ensurePluginToolbar(
|
||||
|
||||
const thresholdGroup = document.createElement("div");
|
||||
thresholdGroup.dataset.pluginToolbarGroup = "thresholds";
|
||||
applyToolbarGroupStyles(thresholdGroup);
|
||||
applyThresholdGroupStyles(thresholdGroup);
|
||||
thresholdGroup.append(
|
||||
createToolbarGroupTitle(document, "传播指标"),
|
||||
...Object.values(spreadThresholdInputs)
|
||||
...createSpreadThresholdControls(document, spreadThresholdInputs)
|
||||
);
|
||||
|
||||
const divider = document.createElement("span");
|
||||
applyToolbarDividerStyles(divider);
|
||||
const thresholdTitle = createToolbarGroupTitle(document, "传播指标筛选");
|
||||
const thresholdRule = createSpreadThresholdRule(document);
|
||||
|
||||
const actions = document.createElement("div");
|
||||
actions.dataset.pluginToolbarActions = "root";
|
||||
applyToolbarActionStyles(actions);
|
||||
actions.append(batchSubmitButton);
|
||||
|
||||
firstRow.append(dataGroup, divider, videoGroup, exportStatusText);
|
||||
secondRow.append(thresholdGroup);
|
||||
firstRow.append(dataGroup, videoGroup, exportStatusText);
|
||||
secondRow.append(thresholdTitle, thresholdRule, thresholdGroup);
|
||||
panel.append(firstRow, secondRow);
|
||||
|
||||
root.append(
|
||||
exportRangeSelect,
|
||||
exportCustomPagesInput,
|
||||
exportButton,
|
||||
panel,
|
||||
actions
|
||||
panel
|
||||
);
|
||||
|
||||
document.body.appendChild(root);
|
||||
@@ -220,7 +213,7 @@ export function ensurePluginToolbar(
|
||||
spreadFilterOnlyAssignSelect,
|
||||
spreadFilterRangeSelect,
|
||||
spreadFilterTypeSelect,
|
||||
...Object.values(spreadThresholdInputs)
|
||||
...spreadThresholdInputs
|
||||
});
|
||||
ensureToolbarMounted(root, document);
|
||||
|
||||
@@ -249,11 +242,19 @@ export function ensurePluginToolbar(
|
||||
exportCustomPagesInput,
|
||||
exportRangeSelect,
|
||||
exportStatusText,
|
||||
root
|
||||
root,
|
||||
spreadFilterFlowTypeSelect,
|
||||
spreadFilterOnlyAssignSelect,
|
||||
spreadFilterRangeSelect,
|
||||
spreadFilterTypeSelect,
|
||||
spreadThresholdInputs
|
||||
});
|
||||
});
|
||||
spreadFilterTypeSelect.addEventListener("change", () => {
|
||||
syncSpreadFilterControlState({
|
||||
audienceProfileByIdExportButton,
|
||||
audienceProfileExportButton,
|
||||
audienceProfileFieldButton,
|
||||
batchSubmitButton,
|
||||
exportButton,
|
||||
exportCustomPagesInput,
|
||||
@@ -345,6 +346,67 @@ function createSpreadThresholdInput(
|
||||
return input;
|
||||
}
|
||||
|
||||
function createSpreadThresholdControls(
|
||||
document: Document,
|
||||
inputs: Record<keyof SpreadThresholdFilter["thresholds"], HTMLInputElement>
|
||||
): HTMLElement[] {
|
||||
const controls: HTMLElement[] = [];
|
||||
const entries: Array<[string, HTMLInputElement]> = [
|
||||
["评论", inputs.averageCommentCount],
|
||||
["时长", inputs.averageDuration],
|
||||
["点赞", inputs.averageLikeCount],
|
||||
["转发", inputs.averageShareCount],
|
||||
["完播率", inputs.finishRate],
|
||||
["互动率", inputs.interactionRate],
|
||||
["播放中位数", inputs.playMedian]
|
||||
];
|
||||
|
||||
entries.forEach(([label, input], index) => {
|
||||
if (index > 0) {
|
||||
controls.push(createSpreadThresholdConjunction(document));
|
||||
}
|
||||
|
||||
const wrapper = document.createElement("label");
|
||||
wrapper.dataset.pluginSpreadThresholdControl = input.dataset.pluginSpreadThreshold;
|
||||
applySpreadThresholdControlStyles(wrapper);
|
||||
|
||||
const labelText = document.createElement("span");
|
||||
labelText.textContent = label;
|
||||
|
||||
const operator = document.createElement("b");
|
||||
operator.dataset.pluginSpreadThresholdOperator = "gte";
|
||||
operator.textContent = "≥";
|
||||
|
||||
wrapper.append(labelText, operator, input);
|
||||
controls.push(wrapper);
|
||||
});
|
||||
|
||||
return controls;
|
||||
}
|
||||
|
||||
function createSpreadThresholdConjunction(document: Document): HTMLElement {
|
||||
const conjunction = document.createElement("span");
|
||||
conjunction.dataset.pluginSpreadThresholdConjunction = "and";
|
||||
conjunction.textContent = "且";
|
||||
applySpreadThresholdConjunctionStyles(conjunction);
|
||||
return conjunction;
|
||||
}
|
||||
|
||||
function createSpreadThresholdRule(document: Document): HTMLElement {
|
||||
const rule = document.createElement("span");
|
||||
rule.dataset.pluginSpreadThresholdRule = "and-gte";
|
||||
applySpreadThresholdRuleStyles(rule);
|
||||
|
||||
const emphasis = document.createElement("strong");
|
||||
emphasis.textContent = "AND";
|
||||
|
||||
const detail = document.createElement("small");
|
||||
detail.textContent = "每项取值 >= 输入值";
|
||||
|
||||
rule.append("全部满足", emphasis, detail);
|
||||
return rule;
|
||||
}
|
||||
|
||||
function readSpreadThresholdInputs(
|
||||
root: HTMLElement
|
||||
): Record<keyof SpreadThresholdFilter["thresholds"], HTMLInputElement> {
|
||||
@@ -719,8 +781,8 @@ function findNativeActionButton(
|
||||
}
|
||||
|
||||
const candidates = Array.from(root.querySelectorAll("button")).filter(
|
||||
(element): element is HTMLElement =>
|
||||
element instanceof document.defaultView!.HTMLElement
|
||||
(element): element is HTMLButtonElement =>
|
||||
element instanceof document.defaultView!.HTMLButtonElement
|
||||
);
|
||||
return (
|
||||
candidates.find((element) => normalizeText(element.textContent) === text) ?? null
|
||||
@@ -739,12 +801,12 @@ function applyToolbarRootStyles(root: HTMLElement): void {
|
||||
function applyToolbarPanelStyles(panel: HTMLElement): void {
|
||||
panel.style.display = "flex";
|
||||
panel.style.flexDirection = "column";
|
||||
panel.style.alignItems = "stretch";
|
||||
panel.style.alignItems = "center";
|
||||
panel.style.gap = "6px";
|
||||
panel.style.flex = "1 1 auto";
|
||||
panel.style.minWidth = "0";
|
||||
panel.style.padding = "2px 0";
|
||||
panel.style.overflowX = "visible";
|
||||
panel.style.padding = "0";
|
||||
panel.style.overflowX = "hidden";
|
||||
panel.style.overflowY = "hidden";
|
||||
}
|
||||
|
||||
@@ -762,41 +824,42 @@ function applyToolbarRowStyles(row: HTMLElement): void {
|
||||
function applyToolbarGroupStyles(group: HTMLElement): void {
|
||||
group.style.display = "flex";
|
||||
group.style.alignItems = "center";
|
||||
group.style.gap = "6px";
|
||||
group.style.gap = "8px";
|
||||
group.style.minWidth = "0";
|
||||
group.style.flex = "0 0 auto";
|
||||
group.style.flexWrap = "nowrap";
|
||||
}
|
||||
|
||||
function applyThresholdGroupStyles(group: HTMLElement): void {
|
||||
group.style.display = "flex";
|
||||
group.style.alignItems = "center";
|
||||
group.style.gap = "7px";
|
||||
group.style.minWidth = "0";
|
||||
group.style.flex = "1 1 auto";
|
||||
group.style.flexWrap = "nowrap";
|
||||
group.style.overflowX = "auto";
|
||||
group.style.overflowY = "hidden";
|
||||
}
|
||||
|
||||
function createToolbarGroupTitle(document: Document, label: string): HTMLElement {
|
||||
const title = document.createElement("span");
|
||||
title.dataset.pluginToolbarTitle = label;
|
||||
title.textContent = label;
|
||||
title.style.color = "#64748b";
|
||||
title.style.display = "flex";
|
||||
title.style.alignItems = "center";
|
||||
title.style.height = "32px";
|
||||
title.style.padding = "0 10px";
|
||||
title.style.border = "1px solid #cfe0ff";
|
||||
title.style.borderRadius = "8px";
|
||||
title.style.background = "#eef5ff";
|
||||
title.style.color = "#2563eb";
|
||||
title.style.fontSize = "12px";
|
||||
title.style.fontWeight = "700";
|
||||
title.style.lineHeight = "32px";
|
||||
title.style.fontWeight = "900";
|
||||
title.style.flex = "0 0 auto";
|
||||
title.style.whiteSpace = "nowrap";
|
||||
return title;
|
||||
}
|
||||
|
||||
function applyToolbarDividerStyles(divider: HTMLElement): void {
|
||||
divider.style.width = "1px";
|
||||
divider.style.height = "24px";
|
||||
divider.style.background = "#e5e7eb";
|
||||
divider.style.flex = "0 0 auto";
|
||||
}
|
||||
|
||||
function applyToolbarActionStyles(actions: HTMLElement): void {
|
||||
actions.style.display = "flex";
|
||||
actions.style.alignItems = "center";
|
||||
actions.style.gap = "8px";
|
||||
actions.style.flex = "0 0 auto";
|
||||
actions.style.paddingLeft = "10px";
|
||||
actions.style.borderLeft = "1px solid #e5e7eb";
|
||||
}
|
||||
|
||||
function applyNativeControlStyles(
|
||||
document: Document,
|
||||
controls: {
|
||||
@@ -876,7 +939,14 @@ function applyNativeControlStyles(
|
||||
element.dataset.pluginSpreadThreshold
|
||||
) {
|
||||
element.style.width =
|
||||
element.dataset.pluginSpreadThreshold === "playMedian" ? "104px" : "78px";
|
||||
element.dataset.pluginSpreadThreshold === "playMedian" ? "82px" : "58px";
|
||||
element.style.minWidth = "0";
|
||||
element.style.height = "26px";
|
||||
element.style.border = "0";
|
||||
element.style.borderRadius = "0";
|
||||
element.style.padding = "0";
|
||||
element.style.outline = "0";
|
||||
element.style.fontWeight = "700";
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -896,11 +966,61 @@ function applyPrimaryButtonStyles(
|
||||
"background-color 0.16s ease, border-color 0.16s ease, box-shadow 0.16s ease, transform 0.16s ease";
|
||||
}
|
||||
|
||||
function applySpreadThresholdControlStyles(control: HTMLElement): void {
|
||||
control.style.display = "grid";
|
||||
control.style.gridTemplateColumns = "auto auto 1fr";
|
||||
control.style.alignItems = "center";
|
||||
control.style.gap = "6px";
|
||||
control.style.height = "32px";
|
||||
control.style.padding = "0 8px";
|
||||
control.style.border = "1px solid #dbe2ec";
|
||||
control.style.borderRadius = "8px";
|
||||
control.style.background = "#ffffff";
|
||||
control.style.flex = "0 0 auto";
|
||||
}
|
||||
|
||||
function applySpreadThresholdConjunctionStyles(conjunction: HTMLElement): void {
|
||||
conjunction.style.color = "#0f8a5f";
|
||||
conjunction.style.fontSize = "12px";
|
||||
conjunction.style.fontWeight = "900";
|
||||
conjunction.style.whiteSpace = "nowrap";
|
||||
conjunction.style.flex = "0 0 auto";
|
||||
}
|
||||
|
||||
function applySpreadThresholdRuleStyles(rule: HTMLElement): void {
|
||||
rule.style.display = "flex";
|
||||
rule.style.alignItems = "center";
|
||||
rule.style.height = "32px";
|
||||
rule.style.padding = "0 10px";
|
||||
rule.style.border = "1px solid #d9efe7";
|
||||
rule.style.borderRadius = "8px";
|
||||
rule.style.background = "#f0fbf6";
|
||||
rule.style.color = "#0f8a5f";
|
||||
rule.style.fontSize = "12px";
|
||||
rule.style.fontWeight = "900";
|
||||
rule.style.whiteSpace = "nowrap";
|
||||
rule.style.flex = "0 0 auto";
|
||||
|
||||
Array.from(rule.children).forEach((child) => {
|
||||
if (child instanceof rule.ownerDocument.defaultView!.HTMLElement) {
|
||||
child.style.marginLeft = child.tagName === "SMALL" ? "6px" : "3px";
|
||||
if (child.tagName === "SMALL") {
|
||||
child.style.color = "#64748b";
|
||||
child.style.fontSize = "12px";
|
||||
child.style.fontWeight = "700";
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function applyStatusStyles(statusText: HTMLElement): void {
|
||||
statusText.style.color = "#64748b";
|
||||
statusText.style.fontSize = "12px";
|
||||
statusText.style.lineHeight = "20px";
|
||||
statusText.style.marginLeft = "4px";
|
||||
statusText.style.marginLeft = "0";
|
||||
statusText.style.flex = "1 1 auto";
|
||||
statusText.style.minWidth = "120px";
|
||||
statusText.style.textAlign = "center";
|
||||
statusText.style.whiteSpace = "nowrap";
|
||||
}
|
||||
|
||||
@@ -949,6 +1069,19 @@ function ensurePluginActionButtonTheme(document: Document): void {
|
||||
transform: none !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
[data-plugin-spread-threshold-control] span,
|
||||
[data-plugin-spread-threshold-control] b {
|
||||
color: #667085 !important;
|
||||
font-size: 12px !important;
|
||||
font-weight: 700 !important;
|
||||
white-space: nowrap !important;
|
||||
}
|
||||
|
||||
[data-plugin-spread-threshold-control] b {
|
||||
color: #0f8a5f !important;
|
||||
font-weight: 900 !important;
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
@@ -967,8 +1100,8 @@ function findButtonContainingText(
|
||||
}
|
||||
|
||||
const candidates = Array.from(root.querySelectorAll("button")).filter(
|
||||
(element): element is HTMLElement =>
|
||||
element instanceof document.defaultView!.HTMLElement
|
||||
(element): element is HTMLButtonElement =>
|
||||
element instanceof document.defaultView!.HTMLButtonElement
|
||||
);
|
||||
|
||||
return candidates.find((element) => normalizeText(element.textContent).includes(text)) ?? null;
|
||||
|
||||
@@ -1 +1 @@
|
||||
export const DEFAULT_BATCH_SUBMIT_BASE_URL = "http://192.168.31.21:8083";
|
||||
export const DEFAULT_BATCH_SUBMIT_BASE_URL = "http://localhost:8083";
|
||||
|
||||
Reference in New Issue
Block a user