fix: finalize market alignment release

This commit is contained in:
admin123 2026-05-09 12:06:19 +08:00
parent a5aad4f165
commit 2e049ef718
5 changed files with 40 additions and 127 deletions

View File

@ -1354,20 +1354,34 @@
const templateCells = getDirectContentCells(templateColumn); const templateCells = getDirectContentCells(templateColumn);
for (let index = 0; index < rowCount; index += 1) { for (let index = 0; index < rowCount; index += 1) {
const existingCell = getDirectContentCells(column)[index] ?? null; const existingCell = getDirectContentCells(column)[index] ?? null;
const templateCell = templateCells[index] ?? templateCells[templateCells.length - 1] ?? null;
if (existingCell) { if (existingCell) {
existingCell.dataset.marketRowCell = field; existingCell.dataset.marketRowCell = field;
applyPluginContentCellStyles(existingCell); applyPluginContentCellStyles(existingCell);
syncContentCellHeight(existingCell, templateCell);
continue; continue;
} }
const templateCell = templateCells[index] ?? templateCells[templateCells.length - 1] ?? null;
const nextCell = field === SELECTION_COLUMN_KEY ? templateCell ? createSelectionContentCell(templateCell) : createBareContentCell(column.ownerDocument) : templateCell ? cloneElementShallow(templateCell) : createBareContentCell(column.ownerDocument); const nextCell = field === SELECTION_COLUMN_KEY ? templateCell ? createSelectionContentCell(templateCell) : createBareContentCell(column.ownerDocument) : templateCell ? cloneElementShallow(templateCell) : createBareContentCell(column.ownerDocument);
nextCell.dataset.marketRowCell = field; nextCell.dataset.marketRowCell = field;
applyColumnWidth(nextCell, field); applyColumnWidth(nextCell, field);
applyPluginContentCellStyles(nextCell); applyPluginContentCellStyles(nextCell);
syncContentCellHeight(nextCell, templateCell);
nextCell.textContent = ""; nextCell.textContent = "";
column.appendChild(nextCell); column.appendChild(nextCell);
} }
} }
function syncContentCellHeight(cell, templateCell) {
if (!templateCell) {
return;
}
const measuredHeight = Math.round(templateCell.getBoundingClientRect().height);
const nextHeight = measuredHeight > 0 ? `${measuredHeight}px` : templateCell.style.height;
if (nextHeight) {
cell.style.height = nextHeight;
} else {
cell.style.removeProperty("height");
}
}
function applyPluginHeaderCellStyles(cell) { function applyPluginHeaderCellStyles(cell) {
cell.style.display = "flex"; cell.style.display = "flex";
cell.style.alignItems = "center"; cell.style.alignItems = "center";

View File

@ -69,6 +69,16 @@ git clone https://git.internal.intelligrow.cn/wangshaoqing/star-chart-search-enh
--- ---
## 🆕 最近修复
当前版本已修复:
- 在星图搜索关键词后,左侧插件勾选框和右侧达人行可能逐行错位的问题
如果你之前已经装过旧版本,请务必按下面的“后续更新”步骤执行一次更新和重新加载。
---
## 🔄 后续更新 ## 🔄 后续更新
当我发布新版本时,你只需要: 当我发布新版本时,你只需要:
@ -81,6 +91,21 @@ npm run build:release
然后到 `chrome://extensions` 页面点击插件卡片的 **"重新加载"** 🔄 然后到 `chrome://extensions` 页面点击插件卡片的 **"重新加载"** 🔄
推荐完整更新顺序:
1. 先关闭星图页面标签页
2. 执行 `git pull`
3. 执行 `npm run build:release`
4. 到 `chrome://extensions` 点击插件卡片的 **"重新加载"**
5. 重新打开星图页面
如果你主要使用的是“达人市场”页面,更新后可以这样快速确认修复是否生效:
1. 打开 `https://xingtu.cn/ad/creator/market`
2. 在搜索框输入关键词,例如 `孕晚期`
3. 向下滚动到达人列表区域
4. 确认左侧勾选框和右侧达人行保持对齐
⚠️ **如果重新加载后还是旧版本** ⚠️ **如果重新加载后还是旧版本**
- 先点击插件卡片的 **"移除"** 删除旧版本 - 先点击插件卡片的 **"移除"** 删除旧版本
- 然后重新点击 **"加载已解压的扩展程序"** - 然后重新点击 **"加载已解压的扩展程序"**

View File

@ -99,39 +99,10 @@ export interface MarketTableDom {
rows: MarketRowDom[]; rows: MarketRowDom[];
} }
export interface MarketAlignmentDiagnostic {
authorId: string;
authorName: string;
checkboxTop: number;
rowTop: number;
topDelta: number;
}
export function syncMarketTable(root: ParentNode): MarketTableDom | null { export function syncMarketTable(root: ParentNode): MarketTableDom | null {
return syncSyntheticMarketTable(root) ?? syncDivGridMarketTable(root); return syncSyntheticMarketTable(root) ?? syncDivGridMarketTable(root);
} }
export function readMarketAlignmentDiagnostics(
table: MarketTableDom
): MarketAlignmentDiagnostic[] {
return table.rows.map((rowDom) => {
const selectionCell = rowDom.selectionCheckbox.parentElement;
const selectionRect = selectionCell?.getBoundingClientRect();
const rowRect = rowDom.row.getBoundingClientRect();
const checkboxTop = selectionRect?.top ?? Number.NaN;
const rowTop = rowRect.top ?? Number.NaN;
return {
authorId: rowDom.authorId,
authorName: rowDom.authorName,
checkboxTop,
rowTop,
topDelta: checkboxTop - rowTop
};
});
}
export function readMarketPageSignature(root: ParentNode): string { export function readMarketPageSignature(root: ParentNode): string {
const document = getOwnerDocument(root); const document = getOwnerDocument(root);
const explicitPageIndex = const explicitPageIndex =

View File

@ -4,7 +4,6 @@ import { createBatchPayload, type BatchPayload } from "./batch-payload";
import { import {
applyRowOrder, applyRowOrder,
applyRowVisibility, applyRowVisibility,
readMarketAlignmentDiagnostics,
readMarketPageSignature, readMarketPageSignature,
renderMarketRowState, renderMarketRowState,
syncPluginSortHeaders, syncPluginSortHeaders,
@ -397,7 +396,6 @@ export function createMarketController(options: CreateMarketControllerOptions) {
applyRowOrder(table, records.map((record) => record.authorId)); applyRowOrder(table, records.map((record) => record.authorId));
bindSelectionControls(table); bindSelectionControls(table);
syncMarketSelectionState(table, selectedAuthorIds); syncMarketSelectionState(table, selectedAuthorIds);
logMarketAlignmentDiagnosticsIfEnabled(options.window, table, "applyCurrentView");
lastKnownPageSignature = readMarketPageSignature(options.document); lastKnownPageSignature = readMarketPageSignature(options.document);
}); });
} }
@ -664,23 +662,12 @@ export function createMarketController(options: CreateMarketControllerOptions) {
} }
const step = Math.max(scrollContainer.clientHeight, 240); const step = Math.max(scrollContainer.clientHeight, 240);
logMarketScrollTraceIfEnabled(options.window, {
event: "start",
maxScrollTop,
originalScrollTop,
step
});
for ( for (
let nextScrollTop = Math.min(originalScrollTop + step, maxScrollTop); let nextScrollTop = Math.min(originalScrollTop + step, maxScrollTop);
nextScrollTop > originalScrollTop && nextScrollTop <= maxScrollTop; nextScrollTop > originalScrollTop && nextScrollTop <= maxScrollTop;
nextScrollTop = Math.min(nextScrollTop + step, maxScrollTop) nextScrollTop = Math.min(nextScrollTop + step, maxScrollTop)
) { ) {
setScrollTop(scrollContainer, nextScrollTop); setScrollTop(scrollContainer, nextScrollTop);
logMarketScrollTraceIfEnabled(options.window, {
event: "step",
nextScrollTop,
scrollTop: scrollContainer.scrollTop
});
hydrationSnapshot = await collectCurrentPageSnapshotsUntilSettled(); hydrationSnapshot = await collectCurrentPageSnapshotsUntilSettled();
if ( if (
hydrationSnapshot.missingDefaultFieldCount === 0 && hydrationSnapshot.missingDefaultFieldCount === 0 &&
@ -696,10 +683,6 @@ export function createMarketController(options: CreateMarketControllerOptions) {
if (scrollContainer.scrollTop !== originalScrollTop) { if (scrollContainer.scrollTop !== originalScrollTop) {
setScrollTop(scrollContainer, originalScrollTop); setScrollTop(scrollContainer, originalScrollTop);
logMarketScrollTraceIfEnabled(options.window, {
event: "restore",
restoredScrollTop: scrollContainer.scrollTop
});
} }
} }
@ -1026,45 +1009,6 @@ function setScrollTop(element: HTMLElement, top: number): void {
element.dispatchEvent(new Event("scroll")); element.dispatchEvent(new Event("scroll"));
} }
function logMarketAlignmentDiagnosticsIfEnabled(
window: Window,
table: ReturnType<typeof syncMarketTable>,
label: string
): void {
if (!isMarketDebugLoggingEnabled(window) || !table) {
return;
}
const diagnostics = readMarketAlignmentDiagnostics(table);
console.info(`[SCES debug] ${label} alignment`, diagnostics);
}
function logMarketScrollTraceIfEnabled(
window: Window,
payload: Record<string, unknown>
): void {
if (!isMarketDebugLoggingEnabled(window)) {
return;
}
console.info("[SCES debug] submit/export scroll", payload);
}
function isMarketDebugLoggingEnabled(window: Window): boolean {
try {
const searchParams = new URL(window.location.href).searchParams;
if (searchParams.get("scesDebug") === "1") {
return true;
}
} catch {}
try {
return window.localStorage.getItem("scesDebugMarket") === "1";
} catch {
return false;
}
}
function readCurrentPageRows(document: Document): MarketRowSnapshot[] { function readCurrentPageRows(document: Document): MarketRowSnapshot[] {
const table = syncMarketTable(document); const table = syncMarketTable(document);
if (!table) { if (!table) {

View File

@ -7,7 +7,6 @@ import {
applyRowVisibility, applyRowVisibility,
findNextPageControl, findNextPageControl,
isPageControlDisabled, isPageControlDisabled,
readMarketAlignmentDiagnostics,
readMarketPageSignature, readMarketPageSignature,
renderMarketRowState, renderMarketRowState,
syncMarketTable syncMarketTable
@ -354,46 +353,6 @@ describe("market-dom-sync", () => {
expect(readSelectionCellHeights()).toEqual(["152px", "152px"]); expect(readSelectionCellHeights()).toEqual(["152px", "152px"]);
}); });
test("reads alignment diagnostics for selection cells against native rows", () => {
document.body.innerHTML = buildRealMarketGridFixture();
const table = syncMarketTable(document);
if (!table) {
throw new Error("Expected market table");
}
const firstSelectionCell = table.rows[0].selectionCheckbox.parentElement as HTMLElement;
const secondSelectionCell = table.rows[1].selectionCheckbox.parentElement as HTMLElement;
vi.spyOn(firstSelectionCell, "getBoundingClientRect").mockReturnValue(
createRect({ height: 24, top: 100 })
);
vi.spyOn(table.rows[0].row, "getBoundingClientRect").mockReturnValue(
createRect({ height: 120, top: 120 })
);
vi.spyOn(secondSelectionCell, "getBoundingClientRect").mockReturnValue(
createRect({ height: 24, top: 260 })
);
vi.spyOn(table.rows[1].row, "getBoundingClientRect").mockReturnValue(
createRect({ height: 120, top: 250 })
);
expect(readMarketAlignmentDiagnostics(table)).toEqual([
expect.objectContaining({
authorId: "111",
checkboxTop: 100,
rowTop: 120,
topDelta: -20
}),
expect.objectContaining({
authorId: "222",
checkboxTop: 260,
rowTop: 250,
topDelta: 10
})
]);
});
test("uses native-like alignment styles for plugin cells", () => { test("uses native-like alignment styles for plugin cells", () => {
document.body.innerHTML = buildRealMarketGridFixtureWithScopedAttributes(); document.body.innerHTML = buildRealMarketGridFixtureWithScopedAttributes();