feat: 插件改为浮窗模式
This commit is contained in:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user