release: 0.2.0421.2

This commit is contained in:
2026-04-21 17:10:06 +08:00
parent 55324a5bb7
commit 968cc88c62
19 changed files with 2832 additions and 178 deletions
+148 -3
View File
@@ -1,3 +1,5 @@
import type { MarketExportScope, MarketExportTarget } from "./types";
export interface PluginToolbarHandlers {
onApplyFilter(): Promise<void> | void;
onApplySort(): Promise<void> | void;
@@ -6,6 +8,9 @@ export interface PluginToolbarHandlers {
export interface PluginToolbarDom {
exportButton: HTMLButtonElement;
exportCustomPagesInput: HTMLInputElement;
exportRangeSelect: HTMLSelectElement;
exportStatusText: HTMLElement;
filterApplyButton: HTMLButtonElement;
personalFilterInput: HTMLInputElement;
root: HTMLElement;
@@ -65,6 +70,25 @@ export function ensurePluginToolbar(
exportButton.dataset.pluginExport = "button";
exportButton.textContent = "导出CSV";
const exportRangeSelect = document.createElement("select");
exportRangeSelect.dataset.pluginExportRange = "select";
appendOption(exportRangeSelect, "current", "当前页");
appendOption(exportRangeSelect, "first-5", "前5页");
appendOption(exportRangeSelect, "first-10", "前10页");
appendOption(exportRangeSelect, "all", "全部");
appendOption(exportRangeSelect, "custom", "自定义");
exportRangeSelect.value = "first-5";
const exportCustomPagesInput = document.createElement("input");
exportCustomPagesInput.type = "number";
exportCustomPagesInput.min = "1";
exportCustomPagesInput.step = "1";
exportCustomPagesInput.hidden = true;
exportCustomPagesInput.dataset.pluginExportCustomPages = "input";
const exportStatusText = document.createElement("span");
exportStatusText.dataset.pluginExportStatus = "text";
root.append(
singleFilterInput,
personalFilterInput,
@@ -72,8 +96,11 @@ export function ensurePluginToolbar(
sortFieldSelect,
sortDirectionSelect,
sortApplyButton,
exportRangeSelect,
exportCustomPagesInput,
exportButton
);
root.append(exportStatusText);
document.body.prepend(root);
filterApplyButton.addEventListener("click", () => {
@@ -85,9 +112,27 @@ export function ensurePluginToolbar(
exportButton.addEventListener("click", () => {
void handlers.onExport();
});
exportRangeSelect.addEventListener("change", () => {
syncCustomPagesInputVisibility({
exportButton,
exportCustomPagesInput,
exportRangeSelect,
exportStatusText,
filterApplyButton,
personalFilterInput,
root,
singleFilterInput,
sortApplyButton,
sortDirectionSelect,
sortFieldSelect
});
});
return {
const toolbarDom = {
exportButton,
exportCustomPagesInput,
exportRangeSelect,
exportStatusText,
filterApplyButton,
personalFilterInput,
root,
@@ -95,7 +140,10 @@ export function ensurePluginToolbar(
sortApplyButton,
sortDirectionSelect,
sortFieldSelect
};
} satisfies PluginToolbarDom;
syncCustomPagesInputVisibility(toolbarDom);
return toolbarDom;
}
function appendOption(
@@ -110,10 +158,19 @@ function appendOption(
}
function readToolbarDom(root: HTMLElement): PluginToolbarDom {
return {
const toolbarDom = {
exportButton: root.querySelector(
'[data-plugin-export="button"]'
) as HTMLButtonElement,
exportCustomPagesInput: root.querySelector(
'[data-plugin-export-custom-pages="input"]'
) as HTMLInputElement,
exportRangeSelect: root.querySelector(
'[data-plugin-export-range="select"]'
) as HTMLSelectElement,
exportStatusText: root.querySelector(
'[data-plugin-export-status="text"]'
) as HTMLElement,
filterApplyButton: root.querySelector(
'[data-plugin-filter-apply="button"]'
) as HTMLButtonElement,
@@ -133,5 +190,93 @@ function readToolbarDom(root: HTMLElement): PluginToolbarDom {
sortFieldSelect: root.querySelector(
'[data-plugin-sort-field="select"]'
) as HTMLSelectElement
} satisfies PluginToolbarDom;
syncCustomPagesInputVisibility(toolbarDom);
return toolbarDom;
}
export function readToolbarExportTarget(
toolbar: PluginToolbarDom
): { error?: string; target?: MarketExportTarget } {
const scope = toolbar.exportRangeSelect.value as MarketExportScope;
if (scope === "all") {
return {
target: {
mode: "all"
}
};
}
if (scope === "current") {
return {
target: {
mode: "count",
pageCount: 1
}
};
}
if (scope === "first-5") {
return {
target: {
mode: "count",
pageCount: 5
}
};
}
if (scope === "first-10") {
return {
target: {
mode: "count",
pageCount: 10
}
};
}
const pageCount = Number(toolbar.exportCustomPagesInput.value);
if (!Number.isInteger(pageCount) || pageCount < 1) {
return {
error: "请输入有效页数"
};
}
return {
target: {
mode: "count",
pageCount
}
};
}
export function setToolbarBusyState(
toolbar: PluginToolbarDom,
isBusy: boolean
): void {
[
toolbar.exportButton,
toolbar.filterApplyButton,
toolbar.sortApplyButton,
toolbar.singleFilterInput,
toolbar.personalFilterInput,
toolbar.sortFieldSelect,
toolbar.sortDirectionSelect,
toolbar.exportRangeSelect,
toolbar.exportCustomPagesInput
].forEach((element) => {
element.disabled = isBusy;
});
}
export function setToolbarExportStatus(
toolbar: PluginToolbarDom,
text: string
): void {
toolbar.exportStatusText.textContent = text;
}
function syncCustomPagesInputVisibility(toolbar: PluginToolbarDom): void {
toolbar.exportCustomPagesInput.hidden =
toolbar.exportRangeSelect.value !== "custom";
}