9 Commits

Author SHA1 Message Date
stringadmin 3b72455062 Merge pull request 'feat: implement multi-turn conversation system for generation record detail with deduplication enhancement' (#18) from feat/ecommerce-record-detail-conversation-panel into main
Reviewed-on: #18
2026-06-16 05:07:49 +00:00
stringadmin 526ad490f7 Merge branch 'main' into feat/ecommerce-record-detail-conversation-panel 2026-06-16 05:07:45 +00:00
ludan 4993f6eeec feat: implement multi-turn conversation system for generation record detail with deduplication enhancement
- generationRecordClient.ts: Enhance save deduplication with payload signature — replace simple recordId-based dedup with stableJsonStringify-based signature comparison; same recordId + same signature skips save, changed payload proceeds; add buildSaveSignature covering tool/mode/title/status/prompt/taskIds/assets/config/result/metadata; store signature alongside savedAt in recentlySavedRecords map for per-turn save accuracy
- EcommercePage.tsx: Introduce EcommerceHistoryTurn interface and multi-turn conversation architecture —
  - Add EcommerceHistoryTurn with full generation context (status/output/platform/market/language/ratio/requirement/images/results/counts/modules/scenes/replicateLevel); EcommerceHistoryRecord gains status/errorMessage/turns[] fields
  - beginEcommerceHistoryTurn() — start a new generation turn, create or append to record, persist to localStorage immediately
  - updateLocalEcommerceHistoryTurn() — real-time turn status sync (generating→done/failed) with record summary mirroring via syncRecordSummaryWithTurn()
  - restoreHistoryTurnInputs() — one-click parameter restoration from failed turns for retry
  - upsertCanvasNode() — insert or update canvas node by ID (dedup by turnId), alternating row layout (x: index*420, y: 0 or 160)
  - Generate flow wired to turns: status callbacks update turn state; cancel sets turn to failed; results written to turn.results
  - Record detail conversation panel refactored from single-message to per-turn iteration — each turn renders user message (requirement + meta + assets) and assistant message (status-aware text + progress bar during generation + result thumbnails); failed turns show "恢复参数" retry button; generating turn shows EcommerceProgressBar
  - openEcommerceHistoryRecord() loads all turns as canvas nodes with distributed positions; preserves generating turn tracking via activeHistoryTurnIdRef
  - History list items display status label (生成中/失败/time)
  - Product set preview backdrop moved to createPortal(document.body) with z-index 4000
- pages/ecommerce.css: Bump product-set-preview-backdrop z-index from 100 to 4000 for Portal rendering layer
2026-06-16 13:02:11 +08:00
Codex 79f220dbbf feat: add responsive layouts for template cards and hot clone 2026-06-16 11:44:55 +08:00
Codex c1c7cb3cc7 fix ecommerce preview and module compatibility 2026-06-15 22:00:00 +08:00
Codex b67f2e7601 Merge branch 'main' of http://118.145.251.184:3000/OmniAI/omniai-ds-code-package into codex/main-latest-20260615-030000 2026-06-15 21:56:00 +08:00
stringadmin f929be30ed Merge pull request 'feat: 优化记录详情对话面板布局与视觉层次' (#17) from feat/ecommerce-chat-polish into main
Reviewed-on: #17
2026-06-15 10:24:35 +00:00
stringadmin a2875738ce Merge branch 'main' into feat/ecommerce-chat-polish 2026-06-15 10:24:30 +00:00
ludan 85adcdceef feat: 优化记录详情对话面板布局与视觉层次
本次修改聚焦于电商记录详情页的对话面板体验打磨:

一、对话顺序优化(EcommercePage.tsx):
- 将"新需求"跟进消息从AI回复之前移至AI回复之后
- 调整后的对话时间线:用户历史需求 → AI回复 → 用户新需求,逻辑更符合真实对话流程

二、对话面板视觉升级(ecommerce-standalone.css):
- 对话面板宽度采用CSS变量动态控制(408-440px),视觉更宽敞
- 消息气泡区分明确:
  · 用户消息:左侧缩进26-36px,蓝色调渐变背景,青色边框
  · AI消息:右侧缩进26-36px,蓝调边框,中性背景
  · 跟进消息:独特高亮样式,更强边框(0.24透明度)和投影
- 排版细节打磨:
  · 消息标签字号12px/权重820
  · 正文13px/行高1.64
  · 气泡内间距15px、圆角20px、投影加深
- 元信息标签(emo)精修:28px高度、圆角胶囊样式
- 素材缩略图:46x46px、圆角14px
- 响应式适配:≤900px面板收窄至92vw,≤480px去除消息缩进

变更文件:
- src/features/ecommerce/EcommercePage.tsx (+20/-20)
- src/styles/ecommerce-standalone.css (+121)
2026-06-15 18:23:36 +08:00
35 changed files with 983 additions and 186 deletions
+1
View File
@@ -0,0 +1 @@
export * from "./aiGenerationClient.ts";
+1
View File
@@ -0,0 +1 @@
export * from "./apiErrorUtils.ts";
+1
View File
@@ -0,0 +1 @@
export * from "./generationRecordClient.ts";
+38 -10
View File
@@ -43,15 +43,40 @@ export interface SaveGenerationRecordResult {
// 单个 poller 内也会重复触发。这里做客户端幂等:in-flight 合流 + 成功后短期拦截, // 单个 poller 内也会重复触发。这里做客户端幂等:in-flight 合流 + 成功后短期拦截,
// 避免后端在缺少去重时插入重复记录。 // 避免后端在缺少去重时插入重复记录。
const inFlightSaves = new Map<string, Promise<SaveGenerationRecordResult>>(); const inFlightSaves = new Map<string, Promise<SaveGenerationRecordResult>>();
const recentlySavedAt = new Map<string, number>(); const recentlySavedRecords = new Map<string, { savedAt: number; signature: string }>();
const SAVE_DEDUPE_WINDOW_MS = 60_000; const SAVE_DEDUPE_WINDOW_MS = 60_000;
function pruneRecentlySaved(now: number): void { function pruneRecentlySaved(now: number): void {
for (const [id, savedAt] of recentlySavedAt) { for (const [id, record] of recentlySavedRecords) {
if (now - savedAt > SAVE_DEDUPE_WINDOW_MS) recentlySavedAt.delete(id); if (now - record.savedAt > SAVE_DEDUPE_WINDOW_MS) recentlySavedRecords.delete(id);
} }
} }
function stableJsonStringify(value: unknown): string {
if (value === null || typeof value !== "object") return JSON.stringify(value);
if (Array.isArray(value)) return `[${value.map(stableJsonStringify).join(",")}]`;
const entries = Object.entries(value as Record<string, unknown>)
.filter(([, entryValue]) => entryValue !== undefined)
.sort(([a], [b]) => a.localeCompare(b));
return `{${entries.map(([key, entryValue]) => `${JSON.stringify(key)}:${stableJsonStringify(entryValue)}`).join(",")}}`;
}
function buildSaveSignature(input: SaveGenerationRecordInput): string {
return stableJsonStringify({
tool: input.tool,
mode: input.mode,
title: input.title,
status: input.status,
prompt: input.prompt,
taskIds: input.taskIds,
assets: input.assets,
config: input.config,
result: input.result,
metadata: input.metadata,
createdAt: input.createdAt,
});
}
function readPendingRecords(): SaveGenerationRecordInput[] { function readPendingRecords(): SaveGenerationRecordInput[] {
try { try {
const raw = window.localStorage.getItem(PENDING_RECORDS_KEY); const raw = window.localStorage.getItem(PENDING_RECORDS_KEY);
@@ -78,26 +103,29 @@ export async function saveGenerationRecord(input: SaveGenerationRecordInput): Pr
pruneRecentlySaved(now); pruneRecentlySaved(now);
const recordId = input.clientRecordId; const recordId = input.clientRecordId;
const signature = buildSaveSignature(input);
if (recordId) { if (recordId) {
const inFlight = inFlightSaves.get(recordId); const saveKey = `${recordId}:${signature}`;
const inFlight = inFlightSaves.get(saveKey);
if (inFlight) return inFlight; if (inFlight) return inFlight;
const savedAt = recentlySavedAt.get(recordId); const savedRecord = recentlySavedRecords.get(recordId);
if (savedAt !== undefined && now - savedAt <= SAVE_DEDUPE_WINDOW_MS) { if (savedRecord && savedRecord.signature === signature && now - savedRecord.savedAt <= SAVE_DEDUPE_WINDOW_MS) {
// 终态记录只需落库一次;窗口内的重复调用直接视为已保存。 // 相同 clientRecordId 且 payload 完全一致时才拦截;同一记录的多轮更新需要继续保存。
return { source: "server", id: recordId }; return { source: "server", id: recordId };
} }
} }
const promise = saveGenerationRecordInternal(input); const promise = saveGenerationRecordInternal(input);
if (recordId) { if (recordId) {
inFlightSaves.set(recordId, promise); const saveKey = `${recordId}:${signature}`;
inFlightSaves.set(saveKey, promise);
void promise void promise
.then((result) => { .then((result) => {
if (result.source === "server") recentlySavedAt.set(recordId, Date.now()); if (result.source === "server") recentlySavedRecords.set(recordId, { savedAt: Date.now(), signature });
}) })
.catch(() => undefined) .catch(() => undefined)
.finally(() => { .finally(() => {
inFlightSaves.delete(recordId); inFlightSaves.delete(saveKey);
}); });
} }
return promise; return promise;
+1
View File
@@ -0,0 +1 @@
export * from "./serverConnection.ts";
+1
View File
@@ -0,0 +1 @@
export * from "./taskSubscription.ts";
+1
View File
@@ -0,0 +1 @@
export * from "./webGenerationGateway.ts";
+1
View File
@@ -0,0 +1 @@
export * from "./toastStore.ts";
+1
View File
@@ -0,0 +1 @@
export * from "./ossAssets.ts";
+1
View File
@@ -0,0 +1 @@
export * from "./workflows.ts";
+2
View File
@@ -0,0 +1,2 @@
export { default } from "./EcommercePage.tsx";
export * from "./EcommercePage.tsx";
File diff suppressed because it is too large Load Diff
@@ -0,0 +1 @@
export * from "./ecommerceGenerationPersistence.ts";
@@ -0,0 +1 @@
export * from "./ecommerceImageValidation.ts";
@@ -0,0 +1 @@
export * from "./ecommerceTemplates.ts";
@@ -0,0 +1 @@
export * from "./workbenchDownload.ts";
+1
View File
@@ -0,0 +1 @@
export * from "./useGenerationTasks.ts";
+1
View File
@@ -0,0 +1 @@
export * from "./useTypewriter.ts";
+1
View File
@@ -0,0 +1 @@
export * from "./backgroundTaskRunner.ts";
+1
View File
@@ -0,0 +1 @@
export * from "./index.ts";
+1
View File
@@ -0,0 +1 @@
export * from "./useAppStore.ts";
+1
View File
@@ -0,0 +1 @@
export * from "./useGenerationStore.ts";
+1
View File
@@ -0,0 +1 @@
export * from "./useProjectStore.ts";
+1
View File
@@ -0,0 +1 @@
export * from "./useSessionStore.ts";
+1
View File
@@ -0,0 +1 @@
export * from "./useTaskStore.ts";
+234 -1
View File
@@ -2781,7 +2781,7 @@
position: absolute !important; position: absolute !important;
left: 50% !important; left: 50% !important;
z-index: 12 !important; z-index: 12 !important;
width: min(1036px, calc(100% - 56px)) !important; width: min(1220px, calc(100% - 40px)) !important;
margin-right: 0 !important; margin-right: 0 !important;
margin-left: 0 !important; margin-left: 0 !important;
; ;
@@ -9040,6 +9040,58 @@
z-index: 0 !important; z-index: 0 !important;
} }
.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-template-strip {
display: grid !important;
grid-template-columns: repeat(4, minmax(0, 1fr)) !important;
gap: 10px !important;
width: min(100%, 1088px) !important;
margin: 16px auto 12px !important;
box-sizing: border-box !important;
}
.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-template-card {
position: relative !important;
display: block !important;
width: 100% !important;
min-width: 0 !important;
aspect-ratio: 3.06 / 1 !important;
min-height: 100px !important;
padding: 0 !important;
border: 1px solid rgba(30, 189, 219, 0.18) !important;
border-radius: 14px !important;
background:
linear-gradient(180deg, rgba(255, 255, 255, 0.94), rgba(246, 251, 253, 0.98)),
#ffffff !important;
box-shadow:
0 16px 34px rgba(16, 115, 204, 0.08),
inset 0 1px 0 rgba(255, 255, 255, 0.94) !important;
overflow: hidden !important;
cursor: pointer !important;
transition: transform 180ms ease, border-color 180ms ease, box-shadow 180ms ease, background 180ms ease !important;
}
.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-template-card:hover {
transform: translateY(-1px) !important;
border-color: rgba(30, 189, 219, 0.34) !important;
box-shadow:
0 20px 42px rgba(16, 115, 204, 0.11),
0 0 0 1px rgba(30, 189, 219, 0.12) inset !important;
}
.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-template-card:focus-visible {
outline: none !important;
border-color: rgba(30, 189, 219, 0.48) !important;
box-shadow:
0 0 0 3px rgba(30, 189, 219, 0.15),
0 20px 42px rgba(16, 115, 204, 0.11) !important;
}
.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-template-card__blank {
display: block !important;
width: 100% !important;
height: 100% !important;
}
.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-preview { .ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-preview {
background: #f8f9fa !important; background: #f8f9fa !important;
transition: padding-top 520ms cubic-bezier(0.16, 1, 0.3, 1), transition: padding-top 520ms cubic-bezier(0.16, 1, 0.3, 1),
@@ -9258,6 +9310,10 @@
min-height: 224px !important; min-height: 224px !important;
} }
.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-template-strip {
grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
}
.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-quick-board button:not(:nth-child(6n + 1))::before { .ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-quick-board button:not(:nth-child(6n + 1))::before {
content: none !important; content: none !important;
} }
@@ -9288,6 +9344,18 @@
min-height: 60px !important; min-height: 60px !important;
} }
.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-template-strip {
grid-template-columns: minmax(0, 1fr) !important;
gap: 8px !important;
width: min(100%, 540px) !important;
margin: 12px auto 10px !important;
}
.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-template-card {
aspect-ratio: 2.9 / 1 !important;
min-height: 84px !important;
}
.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-preview { .ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-preview {
padding-inline: 18px !important; padding-inline: 18px !important;
} }
@@ -9324,6 +9392,50 @@
content: "" !important; content: "" !important;
background: rgba(30, 189, 219, 0.12) !important; background: rgba(30, 189, 219, 0.12) !important;
} }
html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-hot-clone-page .ecom-quick-hot-page .ecom-quick-set-upload.has-images,
html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-hot-clone-page .ecom-quick-hot-page .ecom-quick-hot-material.has-images {
gap: 8px !important;
padding: 8px !important;
}
html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-hot-clone-page .ecom-quick-hot-page .ecom-quick-set-upload.has-images .ecom-command-asset-thumb.ecom-quick-upload-thumb,
html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-hot-clone-page .ecom-quick-hot-page .ecom-quick-hot-material.has-images .ecom-command-asset-thumb.ecom-quick-upload-thumb,
html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-hot-clone-page .ecom-quick-hot-page .ecom-quick-set-upload.has-images .ecom-quick-hot-add-btn,
html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-hot-clone-page .ecom-quick-hot-page .ecom-quick-hot-material.has-images .ecom-quick-hot-add-btn {
width: 56px !important;
height: 56px !important;
min-width: 56px !important;
min-height: 56px !important;
flex-basis: 56px !important;
}
}
@media (max-width: 480px) {
.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-template-strip {
width: 100% !important;
}
.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-template-card {
min-height: 76px !important;
}
html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-hot-clone-page .ecom-quick-hot-page .ecom-quick-set-upload.has-images,
html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-hot-clone-page .ecom-quick-hot-page .ecom-quick-hot-material.has-images {
gap: 6px !important;
padding: 6px !important;
}
html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-hot-clone-page .ecom-quick-hot-page .ecom-quick-set-upload.has-images .ecom-command-asset-thumb.ecom-quick-upload-thumb,
html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-hot-clone-page .ecom-quick-hot-page .ecom-quick-hot-material.has-images .ecom-command-asset-thumb.ecom-quick-upload-thumb,
html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-hot-clone-page .ecom-quick-hot-page .ecom-quick-set-upload.has-images .ecom-quick-hot-add-btn,
html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-hot-clone-page .ecom-quick-hot-page .ecom-quick-hot-material.has-images .ecom-quick-hot-add-btn {
width: 50px !important;
height: 50px !important;
min-width: 50px !important;
min-height: 50px !important;
flex-basis: 50px !important;
}
} }
@keyframes ecommerce-soft-popover-out { @keyframes ecommerce-soft-popover-out {
@@ -17200,3 +17312,124 @@ html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[d
height: 38px !important; height: 38px !important;
} }
} }
/* Record detail chat polish: wider drawer and clearer turn-taking. */
html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-detail {
--clone-chat-width: clamp(408px, 30vw, 440px);
}
html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-detail .clone-ai-conversation-panel {
width: var(--clone-chat-width) !important;
min-width: var(--clone-chat-width) !important;
border-right-color: rgba(30, 189, 219, 0.18) !important;
box-shadow:
24px 0 58px rgba(16, 115, 204, 0.09),
inset -1px 0 0 rgba(255, 255, 255, 0.72) !important;
}
html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-detail.is-conversation-collapsed .clone-ai-conversation-panel {
transform: translateX(calc(-1 * var(--clone-chat-width))) !important;
}
html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-detail .clone-ai-conversation-toggle {
left: var(--clone-chat-width) !important;
}
html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-detail .clone-ai-conversation-head {
padding: 18px 18px 15px !important;
}
html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-detail .clone-ai-conversation-body {
gap: 16px !important;
padding-right: 18px !important;
padding-left: 18px !important;
scroll-padding-bottom: 124px !important;
}
html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-detail .clone-ai-chat-message {
gap: 10px !important;
padding: 15px 16px !important;
border-radius: 20px !important;
box-shadow:
0 14px 34px rgba(16, 115, 204, 0.075),
inset 0 1px 0 rgba(255, 255, 255, 0.92) !important;
}
html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-detail .clone-ai-chat-message--user {
margin-left: clamp(26px, 7%, 36px) !important;
border-color: rgba(30, 189, 219, 0.22) !important;
background:
linear-gradient(180deg, rgba(232, 249, 253, 0.96), rgba(255, 255, 255, 0.94)) !important;
}
html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-detail .clone-ai-chat-message--assistant {
margin-right: clamp(26px, 7%, 36px) !important;
border-color: rgba(16, 115, 204, 0.13) !important;
}
html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-detail .clone-ai-chat-message--followup {
margin-top: 2px !important;
border-color: rgba(30, 189, 219, 0.24) !important;
background:
linear-gradient(180deg, rgba(225, 248, 253, 0.92), rgba(255, 255, 255, 0.95)) !important;
box-shadow:
0 16px 38px rgba(30, 189, 219, 0.1),
inset 0 1px 0 rgba(255, 255, 255, 0.94) !important;
}
html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-detail .clone-ai-chat-message > span {
font-size: 12px !important;
font-weight: 820 !important;
}
html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-detail .clone-ai-chat-message p {
font-size: 13px !important;
line-height: 1.64 !important;
}
html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-detail .clone-ai-chat-meta {
gap: 8px !important;
margin-top: 10px !important;
}
html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-detail .clone-ai-chat-meta em {
min-height: 28px !important;
padding: 7px 11px !important;
border-color: rgba(30, 189, 219, 0.16) !important;
background: rgba(248, 253, 255, 0.98) !important;
}
html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-detail .clone-ai-chat-assets {
gap: 9px !important;
margin-top: 2px !important;
}
html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-detail .clone-ai-chat-assets img,
html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-detail .clone-ai-chat-assets em {
width: 46px !important;
height: 46px !important;
border-radius: 14px !important;
}
@media (max-width: 900px) {
html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-detail {
--clone-chat-width: min(92vw, 408px);
}
html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-detail .clone-ai-conversation-body {
padding-right: 14px !important;
padding-left: 14px !important;
}
}
@media (max-width: 480px) {
html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-detail {
--clone-chat-width: min(94vw, 364px);
}
html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-detail .clone-ai-chat-message--user,
html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-detail .clone-ai-chat-message--assistant {
margin-right: 0 !important;
margin-left: 0 !important;
}
}
+1 -1
View File
@@ -7861,7 +7861,7 @@
.product-set-preview-backdrop { .product-set-preview-backdrop {
position: fixed; position: fixed;
inset: 0; inset: 0;
z-index: 100; z-index: 4000;
display: grid; display: grid;
place-items: center; place-items: center;
background: rgb(17 24 39 / 58%); background: rgb(17 24 39 / 58%);
+1
View File
@@ -0,0 +1 @@
export * from "./types.ts";
+1
View File
@@ -0,0 +1 @@
export * from "./enterpriseVideoPolicy.ts";
+1
View File
@@ -0,0 +1 @@
export * from "./happyHorseRouting.ts";
+1
View File
@@ -0,0 +1 @@
export * from "./pixverseRouting.ts";
+1
View File
@@ -0,0 +1 @@
export * from "./resolveVideoModel.ts";
+1
View File
@@ -0,0 +1 @@
export * from "./taskLifecycle.ts";
+1
View File
@@ -0,0 +1 @@
export * from "./translateTaskError.ts";
+1
View File
@@ -0,0 +1 @@
export * from "./viduRouting.ts";