Initial commit: OmniAI Web Frontend
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,203 @@
|
||||
import {
|
||||
ENTERPRISE_DEFAULT_VIDEO_MODEL,
|
||||
ENTERPRISE_DEFAULT_VIDEO_RESOLUTION,
|
||||
ENTERPRISE_VIDEO_MODEL_OPTIONS,
|
||||
ENTERPRISE_VIDEO_RESOLUTION_OPTIONS,
|
||||
} from "../../utils/enterpriseVideoPolicy";
|
||||
import type {
|
||||
CanvasNodeKind,
|
||||
CanvasNodeSize,
|
||||
CanvasOption,
|
||||
CanvasStylePickerTab,
|
||||
CanvasVideoMode,
|
||||
} from "./canvasTypes";
|
||||
|
||||
// --- Connector follow behavior ---
|
||||
export const connectorFollowRadius = 96;
|
||||
export const connectorFollowStrength = 1;
|
||||
export const connectorMaxFollowOffset = 62;
|
||||
export const connectorAnchorOutset = 9;
|
||||
|
||||
// --- Interaction thresholds ---
|
||||
export const canvasNodeClickMoveThreshold = 5;
|
||||
|
||||
// --- Auto-save timing ---
|
||||
export const canvasAutoSaveDebounceMs = 2_000;
|
||||
export const canvasAutoSaveIdleTimeoutMs = 800;
|
||||
|
||||
// --- Viewport zoom limits ---
|
||||
export const canvasViewportMinZoom = 0.25;
|
||||
export const canvasViewportMaxZoom = 2.6;
|
||||
|
||||
// --- Node sizes ---
|
||||
export const canvasNodeDefaultSizes: Record<CanvasNodeKind, CanvasNodeSize> = {
|
||||
text: { width: 380, height: 260 },
|
||||
image: { width: 460, height: 290 },
|
||||
video: { width: 560, height: 315 },
|
||||
};
|
||||
|
||||
export const canvasNodeMinSizes: Record<CanvasNodeKind, CanvasNodeSize> = {
|
||||
text: { width: 300, height: 220 },
|
||||
image: { width: 340, height: 220 },
|
||||
video: { width: 420, height: 236 },
|
||||
};
|
||||
|
||||
export const canvasNodeMaxSizes: Record<CanvasNodeKind, CanvasNodeSize> = {
|
||||
text: { width: 720, height: 520 },
|
||||
image: { width: 860, height: 620 },
|
||||
video: { width: 960, height: 540 },
|
||||
};
|
||||
|
||||
// --- Text model options ---
|
||||
export const textModelOptions = [
|
||||
{ id: "gemini-3.1-pro", label: "Gemini 3.1 Pro", description: "默认文本生成模型", speed: "20s" },
|
||||
{ id: "gemini-2.5-pro", label: "Gemini 2.5 Pro", description: "通用文本生成模型", speed: "20s" },
|
||||
{ id: "gpt-4o", label: "GPT-4o", description: "通用文本生成模型", speed: "20s" },
|
||||
];
|
||||
export const defaultTextModelId = textModelOptions[0].id;
|
||||
|
||||
// --- Image model options ---
|
||||
export const imageModelOptions: CanvasOption[] = [
|
||||
{ value: "wan2.7-image", label: "wan 2.7 · 0.20 积分" },
|
||||
{ value: "wan2.7-image-pro", label: "wan 2.7 Pro · 0.20 积分" },
|
||||
{ value: "gpt-image-2", label: "GPT-Image-2 · 0.20 积分" },
|
||||
{ value: "gpt-image-2-vip", label: "GPT-Image-2 VIP · 0.20 积分" },
|
||||
{ value: "nano-banana-pro", label: "Nano Banana Pro · 0.20 积分" },
|
||||
{ value: "nano-banana-2", label: "Nano Banana 2 · 0.20 积分" },
|
||||
{ value: "nano-banana-fast", label: "Nano Banana · 0.20 积分" },
|
||||
];
|
||||
|
||||
export const imageRatioOptions: CanvasOption[] = [
|
||||
{ value: "16:9", label: "16:9" },
|
||||
{ value: "9:16", label: "9:16" },
|
||||
{ value: "1:1", label: "1:1" },
|
||||
{ value: "4:3", label: "4:3" },
|
||||
{ value: "3:4", label: "3:4" },
|
||||
];
|
||||
|
||||
export const imageFocusRatioOptions: CanvasOption[] = [
|
||||
{ value: "16:9", label: "16:9" },
|
||||
{ value: "3:2", label: "3:2" },
|
||||
{ value: "4:3", label: "4:3" },
|
||||
{ value: "1:1", label: "1:1" },
|
||||
{ value: "3:4", label: "3:4" },
|
||||
{ value: "2:3", label: "2:3" },
|
||||
{ value: "9:16", label: "9:16" },
|
||||
];
|
||||
|
||||
export const imageQualityOptions: CanvasOption[] = [
|
||||
{ value: "1K", label: "1K" },
|
||||
{ value: "2K", label: "2K" },
|
||||
{ value: "4K", label: "4K" },
|
||||
];
|
||||
|
||||
// --- Style picker ---
|
||||
export const canvasStylePickerTabs: Array<{ key: CanvasStylePickerTab; label: string }> = [
|
||||
{ key: "square", label: "广场" },
|
||||
{ key: "favorites", label: "我的收藏" },
|
||||
{ key: "recent", label: "最近使用" },
|
||||
];
|
||||
|
||||
export const canvasStylePickerCategories = [
|
||||
"推荐",
|
||||
"摄影写真",
|
||||
"电商营销",
|
||||
"动漫游戏",
|
||||
"风格插画",
|
||||
"平面设计",
|
||||
"建筑及室内设计",
|
||||
"创意玩法",
|
||||
"文创周边",
|
||||
"小说推文",
|
||||
];
|
||||
|
||||
// --- 4K capable image models ---
|
||||
export const image4kCapableModels = new Set([
|
||||
"wan2.7-image-pro",
|
||||
"nano-banana-2",
|
||||
"nano-banana-pro",
|
||||
"nano-banana-pro-4k",
|
||||
"nano-banana-pro-4k-vip",
|
||||
"gpt-image-2-vip",
|
||||
]);
|
||||
|
||||
// --- Video model options ---
|
||||
export const videoModelOptions: CanvasOption[] = [
|
||||
...ENTERPRISE_VIDEO_MODEL_OPTIONS.map((option) => ({
|
||||
value: option.value,
|
||||
label: option.label,
|
||||
})),
|
||||
];
|
||||
|
||||
// --- Video ratio & duration options ---
|
||||
export const videoRatioOptions: CanvasOption[] = [
|
||||
{ value: "21:9", label: "21:9" },
|
||||
{ value: "16:9", label: "16:9" },
|
||||
{ value: "4:3", label: "4:3" },
|
||||
{ value: "1:1", label: "1:1" },
|
||||
{ value: "3:4", label: "3:4" },
|
||||
{ value: "9:16", label: "9:16" },
|
||||
];
|
||||
|
||||
export const videoDurationOptions: CanvasOption[] = [
|
||||
{ value: "4", label: "4s" },
|
||||
{ value: "5", label: "5s" },
|
||||
{ value: "6", label: "6s" },
|
||||
{ value: "7", label: "7s" },
|
||||
{ value: "8", label: "8s" },
|
||||
{ value: "9", label: "9s" },
|
||||
{ value: "10", label: "10s" },
|
||||
{ value: "11", label: "11s" },
|
||||
{ value: "12", label: "12s" },
|
||||
{ value: "13", label: "13s" },
|
||||
{ value: "14", label: "14s" },
|
||||
{ value: "15", label: "15s" },
|
||||
];
|
||||
|
||||
// --- Video quality & resolution by model ---
|
||||
export const fallbackVideoQualityOptions: CanvasOption[] = [
|
||||
...ENTERPRISE_VIDEO_RESOLUTION_OPTIONS.map((option) => ({
|
||||
value: option.value,
|
||||
label: option.label,
|
||||
})),
|
||||
];
|
||||
|
||||
export const videoResolutionByModel: Record<string, CanvasOption[]> = {
|
||||
...Object.fromEntries(ENTERPRISE_VIDEO_MODEL_OPTIONS.map((option) => [option.value, fallbackVideoQualityOptions])),
|
||||
};
|
||||
|
||||
export const videoDefaultQualityByModel: Record<string, string> = {
|
||||
...Object.fromEntries(ENTERPRISE_VIDEO_MODEL_OPTIONS.map((option) => [option.value, ENTERPRISE_DEFAULT_VIDEO_RESOLUTION])),
|
||||
};
|
||||
|
||||
// --- Defaults ---
|
||||
export const defaultImageModel = "nano-banana-pro";
|
||||
export const defaultVideoModel = ENTERPRISE_DEFAULT_VIDEO_MODEL;
|
||||
export const canvasVideoModes: CanvasVideoMode[] = ["text2video", "img2video", "firstlast"];
|
||||
|
||||
// --- Poll constants ---
|
||||
export const imageNodeTaskPollIntervalMs = 3000;
|
||||
export const imageNodeTaskPollAttempts = 180;
|
||||
export const videoNodeTaskPollIntervalMs = 5000;
|
||||
export const videoNodeTaskPollAttempts = 360;
|
||||
|
||||
// --- Asset library ---
|
||||
export const assetTypePromptLabel: Record<import("../assets/localAssetStore").AssetLibraryCategory, string> = {
|
||||
character: "角色主体",
|
||||
scene: "环境场景",
|
||||
prop: "关键道具",
|
||||
video: "动态镜头",
|
||||
image: "图片素材",
|
||||
asset: "通用素材",
|
||||
other: "其他素材",
|
||||
};
|
||||
|
||||
export const assetLibraryCategories = [
|
||||
{ key: "character", label: "人物" },
|
||||
{ key: "scene", label: "场景" },
|
||||
{ key: "prop", label: "物品" },
|
||||
{ key: "video", label: "视频" },
|
||||
{ key: "image", label: "图片" },
|
||||
{ key: "asset", label: "素材" },
|
||||
{ key: "other", label: "其他" },
|
||||
] satisfies Array<{ key: import("../assets/localAssetStore").AssetLibraryCategory; label: string }>;
|
||||
Reference in New Issue
Block a user