feat(edit): 编辑上报细节优化

This commit is contained in:
2026-10-06 18:30:05 +08:00
parent e20cd7547f
commit 79b310efe7
92 changed files with 2764 additions and 368 deletions
+10 -5
View File
@@ -1,10 +1,15 @@
import { getSession, login, openErp, submit } from '../lib/api.js';
import { backgroundError } from '../lib/request-errors.js';
export default defineBackground(() => {
browser.runtime.onMessage.addListener(async (message: { type?: string; payload?: unknown; path?: string }) => {
if (message?.type === 'atlas.session') return { session: await getSession() };
if (message?.type === 'atlas.login') return { session: await login() };
if (message?.type === 'atlas.collect') return { result: await submit(message.payload as import('@atlas/contracts').CollectedProductPayload) };
if (message?.type === 'atlas.open') { await openErp(message.path); return { ok: true }; }
return undefined;
try {
if (message?.type === 'atlas.session') return { session: await getSession() };
if (message?.type === 'atlas.login') return { session: await login() };
if (message?.type === 'atlas.collect') return { result: await submit(message.payload as import('@atlas/contracts').CollectedProductPayload) };
if (message?.type === 'atlas.open') { await openErp(message.path); return { ok: true }; }
return undefined;
} catch (error) {
return backgroundError(error);
}
});
});
+22 -18
View File
@@ -4,6 +4,8 @@ import {
} from '../lib/source-parsers.js';
import type { OzonPageJsonFetcher } from '../lib/ozon-parser.js';
import type { MarketplacePageStateFetcher } from '../lib/source-parsers.js';
import { renderCollectorPanel } from '../lib/collector-panel.js';
import { unwrapBackgroundResponse } from '../lib/request-errors.js';
export default defineContentScript({
matches: [
@@ -19,6 +21,7 @@ export default defineContentScript({
let mount: HTMLDivElement | null = null;
let shadow: ShadowRoot | null = null;
let observedUrl = location.href;
let minimized = false;
const render = async () => {
if (!supportedProductPlatform()) {
@@ -35,21 +38,17 @@ export default defineContentScript({
shadow = mount.attachShadow({ mode: 'open' });
}
const root = shadow!;
const session = await browser.runtime
.sendMessage({ type: 'atlas.session' })
const session = await sendBackgroundMessage<{ session?: unknown }>({ type: 'atlas.session' })
.then((value: { session?: unknown }) => value.session)
.catch(() => null);
root.innerHTML = `<style>:host{all:initial}.box{width:156px;padding:12px;background:#fff;border-radius:12px;box-shadow:0 8px 28px #0003;font:14px -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;color:#1f2937}.head{display:flex;justify-content:space-between;align-items:center;font-weight:700;margin-bottom:10px}.dot{width:9px;height:9px;border-radius:50%;background:#ffd43b;border:0}.btn{display:block;width:100%;border:0;border-radius:18px;padding:9px 8px;margin:7px 0;background:#2878f0;color:#fff;font-weight:600;cursor:pointer}.btn.primary{background:#ff5353}.link{display:block;width:100%;border:0;background:transparent;color:#1668dc;cursor:pointer;padding:5px}.hint{font-size:12px;color:#6b7280;text-align:center;margin-top:6px}</style><div class="box"><div class="head"><span>Atlas ERP</span><button class="dot" aria-label="收起"></button></div>${session ? '<button class="btn primary" data-action="edit">编辑上架</button><button class="btn" data-action="collect">采集商品</button><button class="link" data-action="erp">进入 ERP</button>' : '<button class="btn primary" data-action="login">登录 Atlas ERP</button>'}<div class="hint" data-hint></div></div>`;
root.querySelector('.dot')?.addEventListener('click', () => {
mount?.remove();
mount = null;
shadow = null;
});
root.querySelectorAll<HTMLButtonElement>('[data-action]').forEach(
(button) =>
button.addEventListener('click', () =>
void action(button.dataset.action ?? '', root),
),
renderCollectorPanel(
root,
Boolean(session),
minimized,
(next) => {
minimized = next;
},
(kind) => void action(kind, root),
);
};
@@ -58,12 +57,12 @@ export default defineContentScript({
try {
if (kind === 'login') {
hint.textContent = '正在登录…';
await browser.runtime.sendMessage({ type: 'atlas.login' });
await sendBackgroundMessage({ type: 'atlas.login' });
await render();
return;
}
if (kind === 'erp') {
await browser.runtime.sendMessage({ type: 'atlas.open', path: '/' });
await sendBackgroundMessage({ type: 'atlas.open', path: '/' });
return;
}
hint.textContent = '正在采集多 SKU…';
@@ -77,18 +76,19 @@ export default defineContentScript({
? requestMarketplacePageState
: undefined,
);
const response = await browser.runtime.sendMessage({
hint.textContent = `已解析 ${payload.variants.length || 1} 个 SKU,正在入库…`;
const response = await sendBackgroundMessage<{ result: { data: { editor_entry_path: string } } }>({
type: 'atlas.collect',
payload,
});
if (kind === 'edit') {
await browser.runtime.sendMessage({
await sendBackgroundMessage({
type: 'atlas.open',
path: response.result.data.editor_entry_path,
});
}
hint.textContent =
kind === 'edit' ? '已打开采集数据测试页' : '已进入采集箱';
`${kind === 'edit' ? '已打开商品编辑页' : '已进入采集箱'}(${payload.variants.length || 1} 个 SKU)`;
} catch (error) {
hint.textContent =
error instanceof Error ? error.message : '采集失败,请重试';
@@ -105,6 +105,10 @@ export default defineContentScript({
},
});
async function sendBackgroundMessage<T>(message: { type: string; payload?: unknown; path?: string }) {
return unwrapBackgroundResponse<T>(await browser.runtime.sendMessage(message));
}
const requestOzonPageJson: OzonPageJsonFetcher = ({ kind, sku }) =>
new Promise((resolve, reject) => {
const requestId = crypto.randomUUID();