feat: 插件改为浮窗模式

This commit is contained in:
R524809
2026-08-19 17:05:23 +08:00
parent 06b220ae8d
commit 82cb694837
11 changed files with 381 additions and 22 deletions
+24 -3
View File
@@ -11,7 +11,7 @@
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { createRoot } from 'react-dom/client';
import { App as AntApp, ConfigProvider, Popover, Progress, Select } from 'antd';
import { SettingOutlined, DownloadOutlined, ThunderboltOutlined, UploadOutlined } from '@ant-design/icons';
import { SettingOutlined, DownloadOutlined, ThunderboltOutlined, UploadOutlined, CloseOutlined } from '@ant-design/icons';
import type { ScanResult, ImageMaterial } from '../../src/collector/scan';
import {
buildGeneratePayload, suiteZipUrl, uploadImage,
@@ -40,6 +40,14 @@ const PLATFORM_LABELS: Record<string, string> = {
/** 支持的站点(用于判断刷新是否有意义) */
const SUPPORTED_URL_RE = /^https?:\/\/([a-z0-9-]+\.ozon\.(ru|kz|by)|detail\.1688\.com|item\.taobao\.com|detail\.tmall\.com)\//i;
/** 页内悬浮面板模式(作为 iframe 嵌在商品页里运行);独立 Side Panel 打开时为 false */
const IN_PAGE = window.self !== window.top;
/** 通知宿主页收起悬浮面板 */
function closePanel(): void {
window.parent.postMessage({ type: 'sc-panel-close' }, '*');
}
/** 在指定 tab 执行采集,返回结果或 null(未就绪/不支持) */
async function tryScan(tabId: number): Promise<ScanResult | null> {
const [res] = await chrome.scripting.executeScript({
@@ -133,8 +141,8 @@ const App: React.FC = () => {
// 出图方案
const [platform, setPlatform] = useState<'ozon' | 'wb' | 'cn'>('ozon');
const [styleSet, setStyleSet] = useState(1);
/** 生图模型(通义 DashScope,默认 wan2.7-image-pro,与后端 .env 默认一致 */
const [model, setModel] = useState<string>('wan2.7-image-pro');
/** 生图模型(默认 gpt-image-2,走 RightAPI provider */
const [model, setModel] = useState<string>('gpt-image-2');
/** 用户改写的风格提示词(按风格 id 存,切风格不丢) */
const [stylePrompts, setStylePrompts] = useState<Record<number, string>>({});
/** 生图要求(最高优先级,强制约束,覆盖其他设定) */
@@ -179,6 +187,16 @@ const App: React.FC = () => {
return () => window.removeEventListener('keydown', onKey);
}, [preview]);
// 页内面板模式:Esc 收起面板(预览打开时优先关预览,由上面的监听处理)
useEffect(() => {
if (!IN_PAGE) return;
const onKey = (e: KeyboardEvent) => {
if (e.key === 'Escape' && !preview) closePanel();
};
window.addEventListener('keydown', onKey);
return () => window.removeEventListener('keydown', onKey);
}, [preview]);
const brand = result?.texts.find(t => t.kind === 'brand')?.content ?? '';
const sales = result?.texts.find(t => t.kind === 'sales')?.content ?? '';
const shop = result?.texts.find(t => t.kind === 'shop')?.content ?? '';
@@ -500,6 +518,9 @@ const App: React.FC = () => {
<div className="page">
{/* ── 顶栏 ── */}
<div className="topbar">
{IN_PAGE && (
<button className="icon-btn" title="收起面板(Esc" onClick={closePanel}><CloseOutlined /></button>
)}
<div className="logo"></div>
<div>
<h1></h1>