diff --git a/packages/drawnix/src/components/ttd-dialog/ai-image-generation.tsx b/packages/drawnix/src/components/ttd-dialog/ai-image-generation.tsx index a1452373..40d38a4d 100644 --- a/packages/drawnix/src/components/ttd-dialog/ai-image-generation.tsx +++ b/packages/drawnix/src/components/ttd-dialog/ai-image-generation.tsx @@ -4,6 +4,7 @@ import './ai-image-generation.scss'; import { useDrawnix } from '../../hooks/use-drawnix'; import { useI18n } from '../../i18n'; import { useBoard } from '@plait-board/react-board'; +import { getImagePrompts, type Language } from '../../constants/prompts'; import { getSelectedElements, PlaitElement, getRectangleByElements, Point } from '@plait/core'; import { defaultGeminiClient, promptForApiKey } from '../../utils/gemini-api'; import { geminiSettings } from '../../utils/settings-manager'; @@ -387,26 +388,8 @@ const AIImageGeneration = ({ initialPrompt = '', initialImages = [], selectedEle // 获取合并的预设提示词(用户历史 + 默认预设) const getMergedPresetPrompts = () => { - // 默认预设提示词 - const defaultPrompts = language === 'zh' ? [ - '一只可爱的小猫坐在窗台上,阳光透过窗户洒在它的毛发上', - '美丽的山水风景,青山绿水,云雾缭绕', - '现代简约风格的室内设计,明亮宽敞', - '夜晚的城市天际线,霓虹灯闪烁', - '春天的樱花盛开,粉色花瓣飘落', - '科幻风格的太空站,星空背景', - '温馨的咖啡厅,暖色调灯光', - '抽象艺术风格,色彩丰富的几何图形' - ] : [ - 'A cute kitten sitting on a windowsill with sunlight streaming through', - 'Beautiful mountain landscape with green hills and misty clouds', - 'Modern minimalist interior design, bright and spacious', - 'City skyline at night with neon lights glowing', - 'Cherry blossoms in spring with pink petals falling', - 'Sci-fi space station with starry background', - 'Cozy coffee shop with warm ambient lighting', - 'Abstract art with colorful geometric shapes' - ]; + // 获取默认预设提示词 + const defaultPrompts = getImagePrompts(language as Language); // 使用工具函数提取用户历史提示词 const userPrompts = extractUserPromptsFromHistory(historyItems).slice(0, 8); diff --git a/packages/drawnix/src/components/ttd-dialog/ai-video-generation.tsx b/packages/drawnix/src/components/ttd-dialog/ai-video-generation.tsx index c31a5c46..922e9f14 100644 --- a/packages/drawnix/src/components/ttd-dialog/ai-video-generation.tsx +++ b/packages/drawnix/src/components/ttd-dialog/ai-video-generation.tsx @@ -4,6 +4,7 @@ import './ai-video-generation.scss'; import { useDrawnix } from '../../hooks/use-drawnix'; import { useI18n } from '../../i18n'; import { useBoard } from '@plait-board/react-board'; +import { getVideoPrompts, type Language } from '../../constants/prompts'; import { getSelectedElements, PlaitElement, getRectangleByElements, Point } from '@plait/core'; import { defaultGeminiClient, videoGeminiClient, promptForApiKey } from '../../utils/gemini-api'; import { geminiSettings } from '../../utils/settings-manager'; @@ -439,26 +440,8 @@ const AIVideoGeneration = ({ initialPrompt = '', initialImage }: AIVideoGenerati // 获取合并的预设提示词(用户历史 + 默认预设) const getMergedPresetPrompts = () => { - // 默认预设提示词(适用于无源图片场景) - const defaultPrompts = language === 'zh' ? [ - '生成一个美丽的日出场景,阳光从山峰后缓缓升起,云朵轻柔地飘动', - '创造一个森林中的场景,树叶在微风中轻轻摇摆,阳光斑驳', - '生成一个海边场景,海浪轻拍岸边,海鸟在空中盘旋', - '创建一个花园场景,花朵在微风中轻摆,蝴蝶翩翩起舞', - '生成一个雨后场景,水滴从树叶上缓缓滴落,彩虹出现在天空', - '创造一个雪花飘落的冬日场景,雪花轻柔地降落', - '生成一个星空场景,星星闪烁,云朵缓缓飘过月亮', - '创建一个溪流场景,清水在石头间潺潺流淌,鱼儿游过' - ] : [ - 'Generate a beautiful sunrise scene where the sun slowly rises from behind mountains with clouds gently floating', - 'Create a forest scene with leaves swaying gently in the breeze and dappled sunlight', - 'Generate a beach scene with waves gently lapping the shore and seagulls soaring overhead', - 'Create a garden scene with flowers swaying in the breeze and butterflies dancing', - 'Generate a post-rain scene with water drops slowly falling from leaves and a rainbow in the sky', - 'Create a winter scene with snowflakes gently falling from the sky', - 'Generate a starry night scene with twinkling stars and clouds slowly drifting past the moon', - 'Create a stream scene with clear water flowing gently between rocks and fish swimming by' - ]; + // 获取默认预设提示词 + const defaultPrompts = getVideoPrompts(language as Language); // 使用工具函数提取用户历史提示词 const userPrompts = extractUserPromptsFromHistory(historyItems).slice(0, 8); diff --git a/packages/drawnix/src/constants/prompts.ts b/packages/drawnix/src/constants/prompts.ts new file mode 100644 index 00000000..5e9be9f8 --- /dev/null +++ b/packages/drawnix/src/constants/prompts.ts @@ -0,0 +1,81 @@ +/** + * AI 生成的默认提示词常量 + */ + +// AI 图像生成默认提示词 +export const AI_IMAGE_PROMPTS = { + zh: [ + `一张写实的半身人像,一位身穿水蓝色连身裙的年轻韩国亚洲女人走进旅馆大厅,女人脸上带着温暖的微笑,左手拿着白色棒球帽,右手拉着黄色行李箱。 +场景在济州岛度假感的旅馆大厅里,柔和的光线从窗外洒入室内柔和的打在女人的身上,凸显了女人的脸部表情。 +使用 50mm 人像镜头拍摄,女人在画面中央,背景呈现柔和的模糊(散景)。 +氛围是日系杂志的色调并充满放松度假感。直式人像构图,比例1:1。`, + '一只可爱的小猫坐在窗台上,阳光透过窗户洒在它的毛发上', + '美丽的山水风景,青山绿水,云雾缭绕', + '现代简约风格的室内设计,明亮宽敞', + '夜晚的城市天际线,霓虹灯闪烁', + '春天的樱花盛开,粉色花瓣飘落', + '科幻风格的太空站,星空背景', + '温馨的咖啡厅,暖色调灯光', + '抽象艺术风格,色彩丰富的几何图形' + ], + en: [ + `young Korean woman in a light blue dress holding a white baseball cap and pulling a yellow suitcase, photography, +stylish modern hotel lobby, soft sunlight streaming through the window, pastel tones, relaxed vacation mood, +centered vertical portrait with bokeh background, medium shot.`, + 'A cute kitten sitting on a windowsill with sunlight streaming through', + 'Beautiful mountain landscape with green hills and misty clouds', + 'Modern minimalist interior design, bright and spacious', + 'City skyline at night with neon lights glowing', + 'Cherry blossoms in spring with pink petals falling', + 'Sci-fi space station with starry background', + 'Cozy coffee shop with warm ambient lighting', + 'Abstract art with colorful geometric shapes' + ] +} as const; + +// AI 视频生成默认提示词 +export const AI_VIDEO_PROMPTS = { + zh: [ + `场景:日落时分,一座宏伟的城堡庭院,金色的光线透过彩色玻璃窗,营造出温暖而充满希望的氛围。 +相机:对两位公主进行中特写跟踪拍摄,然后进行广角拉出,露出整个庭院,最后缓慢向上倾斜到天空。 +动作:公主们互相微笑,然后开始和谐地唱歌,然后在灯光亮起时向天空举手。 +音频:柔和的管弦乐,伴随着令人振奋的弦乐和合唱,沙沙作响的树叶和远处鸟儿的环绕声,对话:“我们相信明天会更加光明。” +风格:迪士尼风格的动画,鲜艳的色彩,梦幻般的灯光。`, + '生成一个美丽的日出场景,阳光从山峰后缓缓升起,云朵轻柔地飘动', + '创造一个森林中的场景,树叶在微风中轻轻摇摆,阳光斑驳', + '生成一个海边场景,海浪轻拍岸边,海鸟在空中盘旋', + '创建一个花园场景,花朵在微风中轻摆,蝴蝶翩翩起舞', + '生成一个雨后场景,水滴从树叶上缓缓滴落,彩虹出现在天空', + '创造一个雪花飘落的冬日场景,雪花轻柔地降落', + '生成一个星空场景,星星闪烁,云朵缓缓飘过月亮', + '创建一个溪流场景,清水在石头间潺潺流淌,鱼儿游过' + ], + en: [ + `Scene: A grand castle courtyard at sunset, golden light filtering through stained glass windows, creating a warm and hopeful atmosphere. +Camera: Medium close-up tracking shot of the two princesses, then a wide-angle pull-out to reveal the entire courtyard, ending with a slow upward tilt to the sky. +Action: The princesses smile at each other, then begin singing in harmony, then raise their hands toward the sky as the light brightens. +Audio: Soft orchestral music with uplifting strings and choir, ambient sounds of rustling leaves and distant birds, dialogue: "Together, we believe tomorrow will be brighter." +Style: Disney-style animation, vibrant colors, dreamy lighting.`, + 'Generate a beautiful sunrise scene where the sun slowly rises from behind mountains with clouds gently floating', + 'Create a forest scene with leaves gently swaying in the breeze and dappled sunlight', + 'Generate a seaside scene with waves gently lapping the shore and seagulls circling overhead', + 'Create a garden scene with flowers swaying in the breeze and butterflies dancing', + 'Generate a post-rain scene with water drops slowly dripping from leaves and a rainbow appearing in the sky', + 'Create a winter scene with snowflakes gently falling', + 'Generate a starry night scene with twinkling stars and clouds slowly drifting across the moon', + 'Create a stream scene with clear water flowing gently between stones and fish swimming by' + ] +} as const; + +// 类型定义 +export type Language = 'zh' | 'en'; + +// 获取图像生成提示词的辅助函数 +export const getImagePrompts = (language: Language): readonly string[] => { + return AI_IMAGE_PROMPTS[language]; +}; + +// 获取视频生成提示词的辅助函数 +export const getVideoPrompts = (language: Language): readonly string[] => { + return AI_VIDEO_PROMPTS[language]; +}; \ No newline at end of file diff --git a/packages/drawnix/src/utils/crypto-utils.ts b/packages/drawnix/src/utils/crypto-utils.ts index 279fd119..8ac2a5c2 100644 --- a/packages/drawnix/src/utils/crypto-utils.ts +++ b/packages/drawnix/src/utils/crypto-utils.ts @@ -84,21 +84,6 @@ export class CryptoUtils { return `drawnix-v2-${stableInfo}`; } - /** - * 生成旧版密码种子 (v1) - 用于向后兼容 - */ - private static generateLegacyPasswordSeed(): string { - const deviceId = this.getDeviceId(); - const stableInfo = [ - deviceId, - screen.width, - screen.height, - navigator.language || 'en-US', - Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC' - ].join('-'); - - return `drawnix-v1-${stableInfo}`; - } /** * 加密数据 @@ -149,38 +134,19 @@ export class CryptoUtils { const iv = this.base64ToArrayBuffer(parsed.iv); const salt = this.base64ToArrayBuffer(parsed.salt); - // 先尝试新版密钥 - try { - const password = this.generatePasswordSeed(); - const key = await this.deriveKey(password, new Uint8Array(salt)); - - const decrypted = await crypto.subtle.decrypt( - { name: ALGORITHM, iv: iv as BufferSource }, - key, - data - ); - - const decoder = new TextDecoder(); - return decoder.decode(decrypted); - } catch (newKeyError) { - // 新版密钥失败,尝试旧版密钥 - console.warn('New key failed, trying legacy key:', newKeyError); - - const legacyPassword = this.generateLegacyPasswordSeed(); - const legacyKey = await this.deriveKey(legacyPassword, new Uint8Array(salt)); - - const decrypted = await crypto.subtle.decrypt( - { name: ALGORITHM, iv: iv as BufferSource }, - legacyKey, - data - ); - - const decoder = new TextDecoder(); - const result = decoder.decode(decrypted); - - console.log('Successfully decrypted with legacy key, data needs migration'); - return result; - } + // 生成解密密钥 + const password = this.generatePasswordSeed(); + const key = await this.deriveKey(password, new Uint8Array(salt)); + + // 解密数据 + const decrypted = await crypto.subtle.decrypt( + { name: ALGORITHM, iv: iv as BufferSource }, + key, + data + ); + + const decoder = new TextDecoder(); + return decoder.decode(decrypted); } catch (error) { console.error('Decryption failed:', error); throw new Error('Failed to decrypt data'); diff --git a/packages/drawnix/src/utils/settings-manager.ts b/packages/drawnix/src/utils/settings-manager.ts index dc1416b6..15a2494e 100644 --- a/packages/drawnix/src/utils/settings-manager.ts +++ b/packages/drawnix/src/utils/settings-manager.ts @@ -68,7 +68,6 @@ class SettingsManager { private async initializeAsync(): Promise { try { await this.initializeCrypto(); - await this.migrateStoredData(); this.initializeFromUrl(); console.log('SettingsManager initialization completed'); } catch (error) { @@ -133,26 +132,6 @@ class SettingsManager { } } - /** - * 解密敏感数据 - */ - private async decryptSensitiveData(path: string, value: string): Promise { - if (!this.isSensitiveField(path) || !this.cryptoAvailable) { - return value; - } - - // 检查数据是否已加密 - if (!CryptoUtils.isEncrypted(value)) { - return value; - } - - try { - return await CryptoUtils.decrypt(value); - } catch (error) { - console.warn(`Failed to decrypt sensitive data for ${path}:`, error); - return value; // 解密失败时返回原值 - } - } /** * 从本地存储加载设置 @@ -177,36 +156,6 @@ class SettingsManager { return settings; } - /** - * 迁移已存储的数据(处理加密数据) - */ - private async migrateStoredData(): Promise { - let hasChanges = false; - - for (const fieldPath of SENSITIVE_FIELDS) { - const value = this.getSetting(fieldPath); - if (value && typeof value === 'string') { - try { - // 如果是已加密的数据,解密到内存中 - if (CryptoUtils.isEncrypted(value)) { - const decryptedValue = await this.decryptSensitiveData(fieldPath, value); - if (decryptedValue !== value) { - this.setNestedValue(this.settings, fieldPath, decryptedValue); - console.log(`Decrypted stored sensitive field: ${fieldPath}`); - hasChanges = true; - } - } - } catch (error) { - console.warn(`Failed to decrypt stored field ${fieldPath}:`, error); - } - } - } - - // 如果有解密操作,重新保存以确保数据一致性 - if (hasChanges) { - await this.saveToStorage(); - } - } /** * 设置嵌套对象的值