/** * Command: create-account — 一键创建账号 * * 创建目录结构 → 复制参考图 → 上传 OSS → 生成 account.json + 风格骨架 */ const fs = require('fs') const path = require('path') const { ensureDir, log, ACCOUNTS_DIR } = require('./pipeline-utils') async function createAccount(args) { const { id, name, desc, format, imageModel, videoModel, references } = args if (!id) { console.error('错误: 必须指定 --id <账号ID>'); process.exit(1) } if (!/^[a-z0-9_-]+$/.test(id)) { console.error('错误: id 只允许小写字母/数字/短横线/下划线'); process.exit(1) } if (!name) { console.error('错误: 必须指定 --name <账号名>'); process.exit(1) } const accountDir = path.join(ACCOUNTS_DIR, id) if (fs.existsSync(accountDir)) { console.error(`错误: 账号已存在: ${accountDir}`); process.exit(1) } ensureDir(accountDir) ensureDir(path.join(accountDir, 'prompts')) ensureDir(path.join(accountDir, 'references')) ensureDir(path.join(accountDir, 'styles')) // 复制参考图到 references/ 并上传 OSS const refs = (references || '').split(',').filter(Boolean) const uploadedRefs = [] if (refs.length > 0) { const { uploadFile } = require('../oss-upload') for (const refPath of refs) { const absPath = path.resolve(refPath) if (!fs.existsSync(absPath)) { console.error(`参考图不存在: ${absPath}`); continue } const fileName = path.basename(absPath) const destPath = path.join(accountDir, 'references', fileName) fs.copyFileSync(absPath, destPath) try { const { url } = await uploadFile(destPath) uploadedRefs.push({ file: fileName, url }) log('account', `参考图 ${fileName} → OK`) } catch (err) { uploadedRefs.push({ file: fileName }) log('account', `参考图 ${fileName} 上传失败: ${err.message}(仅保存本地)`) } } } // 生成 account.json const styleName = args.style || id const accountConfig = { id, name, description: desc || '', defaultFormat: format || '9:16', imageModel: imageModel || 'gemini', videoModel: videoModel || '', batchSize: 30, storyboardPrompt: 'prompts/分镜.md', imageStylePrompt: 'prompts/图片提示词.md', videoStylePrompt: 'prompts/视频提示词.md', capcut: { effects: [], filter: '', subtitleStyle: { fontSize: 36, color: '#FFFFFF', highlightColor: '#FF6B35', bold: true, }, defaultBGM: '', }, } if (uploadedRefs.length > 0) { accountConfig.styles = { [styleName]: { references: uploadedRefs }, } } const accountPath = path.join(accountDir, 'account.json') fs.writeFileSync(accountPath, JSON.stringify(accountConfig, null, 2), 'utf-8') // 生成默认风格骨架 const stylePath = path.join(accountDir, 'styles', `${styleName}.md`) const styleContent = [ `# ${styleName}`, '', `${desc || name} 的视觉风格。`, '', '---', '', '## 图片提示词', '', '### 核心视觉要素', '', '(待填充:描述关键视觉元素)', '', '### 色调方案', '', '(待填充)', '', '### 图片 Prompt 模板', '', '(待填充)', '', '### 图片禁止项', '', '- 文字水印', '- 字幕覆盖', '', '---', '', '## 视频提示词', '', '### 运镜规则', '', '(待填充)', '', '### 视频 Prompt 模板', '', '(待填充)', '', ].join('\n') fs.writeFileSync(stylePath, styleContent, 'utf-8') console.log(`\n账号已创建: ${accountDir}`) console.log(` ID: ${id}`) console.log(` 名称: ${name}`) console.log(` 模型: ${accountConfig.imageModel} + ${accountConfig.videoModel || '(未指定)'}`) console.log(` 参考图: ${uploadedRefs.length} 张(${uploadedRefs.filter(r => r.url).length} 已上传)`) console.log(` 风格: ${styleName}`) console.log(`\n下一步: 编辑 ${stylePath} 完善提示词策略\n`) return accountPath } module.exports = { createAccount }