243 lines
7.4 KiB
JavaScript
243 lines
7.4 KiB
JavaScript
|
|
/**
|
|||
|
|
* ═══════════════════════════════════════════════════
|
|||
|
|
* 铸渊图片工作室 · 风格配置系统
|
|||
|
|
* ═══════════════════════════════════════════════════
|
|||
|
|
*
|
|||
|
|
* 冰朔,这里所有的颜色、字体、间距你都可以改。
|
|||
|
|
* 告诉我想要的「感觉」,我来调。
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
export const STYLES = {
|
|||
|
|
|
|||
|
|
/* ── 当前风格:光湖极简 ── */
|
|||
|
|
name: '光湖极简',
|
|||
|
|
|
|||
|
|
colors: {
|
|||
|
|
primary: '#1a1a2e', // 主色 · 深蓝黑
|
|||
|
|
secondary: '#16213e', // 辅色 · 深蓝
|
|||
|
|
accent: '#0f3460', // 强调色 · 普鲁士蓝
|
|||
|
|
highlight: '#e94560', // 高亮 · 珊瑚红
|
|||
|
|
gold: '#c9a96e', // 金色 · 点缀
|
|||
|
|
warm: '#f5e6c8', // 暖白 · 背景
|
|||
|
|
|
|||
|
|
bg: '#faf8f5', // 页面背景
|
|||
|
|
bgCard: '#ffffff', // 卡片背景
|
|||
|
|
text: '#1a1a2e', // 正文
|
|||
|
|
textMuted: '#6b7280', // 辅助文字
|
|||
|
|
textLight: '#ffffff', // 浅色背景上的文字
|
|||
|
|
border: '#e5e7eb', // 边框
|
|||
|
|
divider: '#f0e6d3', // 分割线 · 暖色
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
fonts: {
|
|||
|
|
title: '"Noto Serif SC", "Source Han Serif SC", serif',
|
|||
|
|
body: '"Noto Sans SC", "Source Han Sans SC", "PingFang SC", sans-serif',
|
|||
|
|
quote: '"ZCOOL QingKe HuangYou", cursive',
|
|||
|
|
mono: '"JetBrains Mono", "Fira Code", monospace',
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
/* 卡片尺寸 —— 这些只是参考,可以随时改 */
|
|||
|
|
sizes: {
|
|||
|
|
xiaohongshu: { width: 1080, height: 1440 }, // 3:4
|
|||
|
|
jike: { width: 1080, height: 1080 }, // 1:1
|
|||
|
|
poster: { width: 1080, height: 1920 }, // 9:16 海报
|
|||
|
|
wechat: { width: 1080, height: 1350 }, // 4:5 朋友圈
|
|||
|
|
square: { width: 1080, height: 1080 }, // 1:1 通用方图
|
|||
|
|
wide: { width: 1920, height: 1080 }, // 16:9 宽图
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
/* 排版 */
|
|||
|
|
typography: {
|
|||
|
|
titleSize: 56,
|
|||
|
|
subtitleSize: 32,
|
|||
|
|
bodySize: 28,
|
|||
|
|
smallSize: 22,
|
|||
|
|
captionSize: 18,
|
|||
|
|
lineHeight: 1.6,
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
/* 间距 */
|
|||
|
|
spacing: {
|
|||
|
|
paddingX: 64,
|
|||
|
|
paddingY: 60,
|
|||
|
|
gap: 32,
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
/* 水印/品牌标识 */
|
|||
|
|
brand: {
|
|||
|
|
show: true,
|
|||
|
|
text: '光湖 · 铸渊',
|
|||
|
|
size: 16,
|
|||
|
|
opacity: 0.4,
|
|||
|
|
},
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/* ── 配色方案 ── */
|
|||
|
|
export const COLOR_SCHEMES = {
|
|||
|
|
guanghu: {
|
|||
|
|
name: '光湖极简',
|
|||
|
|
primary: '#1a1a2e', bg: '#faf8f5', accent: '#0f3460',
|
|||
|
|
highlight: '#e94560', gold: '#c9a96e', warm: '#f5e6c8',
|
|||
|
|
},
|
|||
|
|
cream: {
|
|||
|
|
name: '奶油暖调',
|
|||
|
|
primary: '#5d4037', bg: '#fef7f0', accent: '#8d6e63',
|
|||
|
|
highlight: '#e07a5f', gold: '#d4a373', warm: '#fae1dd',
|
|||
|
|
},
|
|||
|
|
night: {
|
|||
|
|
name: '暗夜深蓝',
|
|||
|
|
primary: '#e0e0e0', bg: '#0d1117', accent: '#58a6ff',
|
|||
|
|
highlight: '#f78166', gold: '#d4a373', warm: '#21262d',
|
|||
|
|
},
|
|||
|
|
green: {
|
|||
|
|
name: '文艺绿植',
|
|||
|
|
primary: '#2d3e2f', bg: '#f5f9f2', accent: '#5a8f5a',
|
|||
|
|
highlight: '#c78b5c', gold: '#b8a06e', warm: '#e8f0e0',
|
|||
|
|
},
|
|||
|
|
rose: {
|
|||
|
|
name: '玫瑰粉调',
|
|||
|
|
primary: '#4a1942', bg: '#fdf2f8', accent: '#9d4e8d',
|
|||
|
|
highlight: '#e8435e', gold: '#c9a96e', warm: '#fce4ec',
|
|||
|
|
},
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
export function useScheme(name) {
|
|||
|
|
const scheme = COLOR_SCHEMES[name]
|
|||
|
|
if (!scheme) return false
|
|||
|
|
const c = STYLES.colors
|
|||
|
|
c.primary = scheme.primary; c.bg = scheme.bg
|
|||
|
|
c.accent = scheme.accent; c.highlight = scheme.highlight
|
|||
|
|
c.gold = scheme.gold; c.warm = scheme.warm
|
|||
|
|
STYLES.name = scheme.name
|
|||
|
|
return true
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/* ═══════════════════════════════════════════════════
|
|||
|
|
* 内容感知 · 自动检测函数
|
|||
|
|
* ═══════════════════════════════════════════════════
|
|||
|
|
*
|
|||
|
|
* 冰朔给我一段文字,我分析它是什么类型的、什么情绪、
|
|||
|
|
* 适合什么布局。不需要她告诉我。
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 分析文本特征,返回检测结果
|
|||
|
|
*/
|
|||
|
|
export function analyzeText(text) {
|
|||
|
|
if (!text) return { type: 'empty' }
|
|||
|
|
|
|||
|
|
const t = text.trim()
|
|||
|
|
|
|||
|
|
/* ── 特征检测 ── */
|
|||
|
|
const hasList = /^[-•·*]\s|^\d+[\.\)]\s/m.test(t) // 列表项
|
|||
|
|
const isShort = t.length < 30 // 短句(金句)
|
|||
|
|
const isMedium = t.length < 100 // 中等长度
|
|||
|
|
const hasTitle = t.includes('标题') || t.includes(':') // 可能有标题
|
|||
|
|
const lines = t.split('\n').filter(Boolean)
|
|||
|
|
const lineCount = lines.length
|
|||
|
|
|
|||
|
|
const keywords = {
|
|||
|
|
notice: /通知|公告|放假|放假安排|节假日|放假通知/i,
|
|||
|
|
recruit: /征稿|收稿|投稿|征集|诚征|招聘|招募|稿酬/i,
|
|||
|
|
share: /干货|教程|指南|技巧|方法|如何|步骤|经验|分享/i,
|
|||
|
|
quote: /说|说过|句话|名言|语录|金句|记得|曾经/i,
|
|||
|
|
product: /新品|上线|发布|推出|产品|功能|更新/i,
|
|||
|
|
event: /活动|沙龙|讲座|直播|分享会|聚会/i,
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const detected = {}
|
|||
|
|
let type = 'general'
|
|||
|
|
|
|||
|
|
for (const [key, re] of Object.entries(keywords)) {
|
|||
|
|
if (re.test(t)) detected[key] = true
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* ── 类型推断 ── */
|
|||
|
|
if (detected.notice) type = 'notice'
|
|||
|
|
else if (detected.recruit) type = 'recruit'
|
|||
|
|
else if (detected.quote || isShort) type = 'quote'
|
|||
|
|
else if (detected.share || hasList) type = 'list'
|
|||
|
|
else if (detected.product) type = 'product'
|
|||
|
|
else if (detected.event) type = 'event'
|
|||
|
|
else if (lineCount >= 4) type = 'article'
|
|||
|
|
else if (isMedium) type = 'paragraph'
|
|||
|
|
|
|||
|
|
/* ── 情绪推断(基于关键词) ── */
|
|||
|
|
let mood = 'neutral'
|
|||
|
|
const warmWords = /感谢|温暖|爱|喜欢|开心|快乐|幸福|美好|谢谢/i
|
|||
|
|
const urgentWords = /紧急|重要|注意|必读|截止|最后/i
|
|||
|
|
const elegantWords = /岁月|时光|静好|诗意|远方|温柔/i
|
|||
|
|
|
|||
|
|
if (elegantWords.test(t)) mood = 'elegant'
|
|||
|
|
else if (warmWords.test(t)) mood = 'warm'
|
|||
|
|
else if (urgentWords.test(t)) mood = 'urgent'
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
type,
|
|||
|
|
mood,
|
|||
|
|
lineCount,
|
|||
|
|
isShort,
|
|||
|
|
hasList,
|
|||
|
|
lines,
|
|||
|
|
detected,
|
|||
|
|
text: t,
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 根据内容分析结果推荐配色方案
|
|||
|
|
*/
|
|||
|
|
export function recommendScheme(analysis) {
|
|||
|
|
const { mood, type } = analysis
|
|||
|
|
|
|||
|
|
if (mood === 'warm') return 'cream'
|
|||
|
|
if (mood === 'elegant') return 'green'
|
|||
|
|
if (mood === 'urgent') return 'guanghu'
|
|||
|
|
|
|||
|
|
if (type === 'recruit') return 'cream'
|
|||
|
|
if (type === 'notice') return 'guanghu'
|
|||
|
|
if (type === 'quote') return 'rose'
|
|||
|
|
|
|||
|
|
return 'guanghu'
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 根据内容分析推荐布局
|
|||
|
|
*/
|
|||
|
|
export function recommendLayout(analysis) {
|
|||
|
|
const { type, hasList, isShort, lineCount } = analysis
|
|||
|
|
|
|||
|
|
if (isShort) return 'quote'
|
|||
|
|
if (type === 'notice') return 'notice'
|
|||
|
|
if (type === 'recruit') return 'recruit'
|
|||
|
|
if (hasList) return 'list'
|
|||
|
|
if (lineCount <= 3) return 'minimal'
|
|||
|
|
|
|||
|
|
return 'default'
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 根据内容分析推荐尺寸
|
|||
|
|
* @param {'xiaohongshu'|'jike'|'poster'|'wechat'|'wide'|string} platform
|
|||
|
|
*/
|
|||
|
|
export function recommendSize(platform) {
|
|||
|
|
const sizes = STYLES.sizes
|
|||
|
|
if (sizes[platform]) return sizes[platform]
|
|||
|
|
|
|||
|
|
// 关键词匹配
|
|||
|
|
if (/小红书/i.test(platform)) return sizes.xiaohongshu
|
|||
|
|
if (/即刻/i.test(platform)) return sizes.jike
|
|||
|
|
if (/海报/i.test(platform) || /通知/i.test(platform) || /收稿/i.test(platform)) return sizes.poster
|
|||
|
|
if (/朋友圈/i.test(platform)) return sizes.wechat
|
|||
|
|
if (/宽/i.test(platform) || /横/i.test(platform)) return sizes.wide
|
|||
|
|
|
|||
|
|
// 默认识别
|
|||
|
|
return sizes.square
|
|||
|
|
}
|