755059807a
- 优化 AI 配置列表页面:重构统计卡片、搜索表单、表格列展示 - 修复 3 处 TypeScript TS6133 编译错误,恢复构建 - 新增管理员修改密码和重置密码功能 - 优化小程序多个页面样式和交互 - 人生事件模块完善 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
335 lines
24 KiB
JavaScript
335 lines
24 KiB
JavaScript
import { zodiacs, mbtis, hintWords, scriptStyles, scriptLengths, npcRoles, npcRelations } from './data.js';
|
|
|
|
export const RegistrationWizard = {
|
|
renderStep: (step, user) => {
|
|
const steps = [
|
|
`<div class="space-y-6">
|
|
<div class="space-y-2">
|
|
<h2 class="text-3xl font-light tracking-tight text-white">系统初始化</h2>
|
|
<p class="text-purple-400/60 text-sm italic">定义你在人生OS中的唯一代码</p>
|
|
</div>
|
|
<div class="space-y-4">
|
|
<input id="nickname" type="text" placeholder="你的昵称" class="w-full bg-transparent border-b border-purple-500/30 py-3 focus:border-purple-400 outline-none transition-all" value="${user.nickname}">
|
|
<div class="grid grid-cols-2 gap-4">
|
|
<select id="gender" class="bg-white/5 p-3 rounded-xl border border-white/10 outline-none text-purple-100">
|
|
<option value="">性别</option><option value="male" ${user.gender==='male'?'selected':''}>男性</option><option value="female" ${user.gender==='female'?'selected':''}>女性</option>
|
|
</select>
|
|
<select id="zodiac" class="bg-white/5 p-3 rounded-xl border border-white/10 outline-none text-purple-100">
|
|
<option value="">星座</option>
|
|
${zodiacs.map(z => `<option value="${z}" ${user.zodiac===z?'selected':''}>${z}</option>`).join('')}
|
|
</select>
|
|
</div>
|
|
<select id="mbti" class="w-full bg-white/5 p-3 rounded-xl border border-white/10 outline-none text-purple-100">
|
|
<option value="">MBTI人格</option>
|
|
${mbtis.map(m => `<option value="${m}" ${user.mbti===m?'selected':''}>${m}</option>`).join('')}
|
|
</select>
|
|
<input id="hobbies" type="text" placeholder="兴趣爱好 (逗号分隔)" class="w-full bg-transparent border-b border-purple-500/30 py-3 focus:border-purple-400 outline-none" value="${user.hobbies.join(', ')}">
|
|
</div>
|
|
</div>`,
|
|
|
|
`<div class="space-y-6">
|
|
<div class="space-y-2">
|
|
<h2 class="text-3xl font-light text-white">回溯起源</h2>
|
|
<p class="text-purple-400/60 text-sm">一段让你感到温暖的早期时光</p>
|
|
</div>
|
|
<div class="space-y-4">
|
|
<input type="date" id="childhood-date" value="${user.childhoodDate}" class="w-full bg-white/5 p-3 rounded-xl border border-white/10 text-sm text-purple-200">
|
|
<textarea id="childhood" placeholder="回忆一段具体且温暖的午后..." class="w-full h-32 bg-white/5 p-4 rounded-xl border border-white/10 outline-none resize-none">${user.childhood}</textarea>
|
|
<div class="hint-container">
|
|
<p class="text-[10px] text-purple-400/50 mb-3 px-1 flex items-center gap-2 uppercase tracking-widest">
|
|
<i data-lucide="sparkles" class="w-3 h-3"></i> 灵感气泡
|
|
</p>
|
|
<div class="flex flex-wrap gap-2">
|
|
${hintWords.childhood.map((h, i) => `<button class="hint-chip bubble-anim" style="--delay: ${i}" onclick="document.getElementById('childhood').value += '${h} '"><span>${h}</span></button>`).join('')}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>`,
|
|
|
|
`<div class="space-y-6">
|
|
<div class="space-y-2">
|
|
<h2 class="text-3xl font-light text-white">悦然时刻</h2>
|
|
<p class="text-purple-400/60 text-sm">一段感受到生命跃动的经历</p>
|
|
</div>
|
|
<div class="space-y-4">
|
|
<input type="date" id="happy-date" value="${user.happyDate}" class="w-full bg-white/5 p-3 rounded-xl border border-white/10 text-sm text-purple-200">
|
|
<textarea id="happy-moment" placeholder="想一个令你会心一笑的瞬间..." class="w-full h-32 bg-white/5 p-4 rounded-xl border border-white/10 outline-none resize-none">${user.happyMoment}</textarea>
|
|
<div class="hint-container">
|
|
<p class="text-[10px] text-purple-400/50 mb-3 px-1 flex items-center gap-2 uppercase tracking-widest">
|
|
<i data-lucide="sparkles" class="w-3 h-3"></i> 灵感气泡
|
|
</p>
|
|
<div class="flex flex-wrap gap-2">
|
|
${hintWords.happy.map((h, i) => `<button class="hint-chip bubble-anim" style="--delay: ${i}" onclick="document.getElementById('happy-moment').value += '${h} '"><span>${h}</span></button>`).join('')}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>`,
|
|
|
|
`<div class="space-y-6">
|
|
<div class="space-y-2">
|
|
<h2 class="text-3xl font-light text-white">破茧成蝶</h2>
|
|
<p class="text-purple-400/60 text-sm">在宁静中默默积蓄力量的日子</p>
|
|
</div>
|
|
<div class="space-y-4">
|
|
<input type="date" id="low-date" value="${user.lowDate}" class="w-full bg-white/5 p-3 rounded-xl border border-white/10 text-sm text-purple-200">
|
|
<textarea id="low-point" placeholder="描述那段有些艰难但让你成长的日子..." class="w-full h-32 bg-white/5 p-4 rounded-xl border border-white/10 outline-none resize-none">${user.lowPoint}</textarea>
|
|
<div class="hint-container">
|
|
<p class="text-[10px] text-purple-400/50 mb-3 px-1 flex items-center gap-2 uppercase tracking-widest">
|
|
<i data-lucide="sparkles" class="w-3 h-3"></i> 灵感气泡
|
|
</p>
|
|
<div class="flex flex-wrap gap-2">
|
|
${hintWords.low.map((h, i) => `<button class="hint-chip bubble-anim" style="--delay: ${i}" onclick="document.getElementById('low-point').value += '${h} '"><span>${h}</span></button>`).join('')}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>`,
|
|
|
|
`<div class="space-y-6">
|
|
<div class="space-y-2">
|
|
<h2 class="text-3xl font-light text-white">未来憧憬</h2>
|
|
<p class="text-purple-400/60 text-sm">对未来理想生活状态的预见</p>
|
|
</div>
|
|
<div class="space-y-4">
|
|
<textarea id="aspirations" placeholder="你想成为怎样的人?尝试描述那幅画面..." class="w-full h-48 bg-white/5 p-4 rounded-xl border border-white/10 outline-none resize-none">${user.aspirations}</textarea>
|
|
<div class="flex items-center gap-2 p-4 glass-gold rounded-xl border-purple-500/30">
|
|
<i data-lucide="sparkles" class="w-5 h-5 text-purple-400"></i>
|
|
<span class="text-xs text-purple-200/80 italic">“照见未来,便是创造的开始。”</span>
|
|
</div>
|
|
</div>
|
|
</div>`
|
|
];
|
|
return steps[step];
|
|
}
|
|
};
|
|
|
|
export const AppPages = {
|
|
record: (events) => `
|
|
<div class="space-y-6 pb-4">
|
|
<div class="glass p-5 rounded-3xl space-y-4 border-white/10">
|
|
<div class="flex items-center gap-2 mb-2">
|
|
<div class="w-2 h-2 rounded-full bg-purple-400"></div>
|
|
<span class="text-[10px] font-bold text-purple-400 uppercase tracking-widest">记叙当下</span>
|
|
</div>
|
|
<input id="event-title" type="text" placeholder="为这段记忆命名" class="w-full bg-transparent border-b border-white/10 py-2 outline-none text-purple-50">
|
|
<input id="event-time" type="date" class="bg-transparent text-sm text-purple-400/60 outline-none">
|
|
<textarea id="event-content" placeholder="此刻的心境或发生的事..." class="w-full bg-transparent h-20 outline-none resize-none text-sm text-white/80"></textarea>
|
|
<button id="save-event" class="w-full py-3.5 bg-gradient-to-r from-purple-600/40 to-purple-400/40 border border-purple-500/30 rounded-2xl text-white text-sm font-medium hover:from-purple-600/60 transition-all">镌刻至星海</button>
|
|
</div>
|
|
|
|
<div class="space-y-6" id="event-list">
|
|
${events.map(ev => `
|
|
<div class="glass p-5 rounded-3xl space-y-3 relative overflow-hidden group border-white/5">
|
|
<div class="flex justify-between items-start">
|
|
<h3 class="font-medium text-purple-100">${ev.title}</h3>
|
|
<span class="text-[10px] text-purple-400/50">${ev.time}</span>
|
|
</div>
|
|
<p class="text-sm text-white/70 leading-relaxed">${ev.content}</p>
|
|
<div class="pt-3 border-t border-white/5 space-y-2 ai-card-glow-gold rounded-2xl p-4 bg-purple-500/5">
|
|
<div class="flex items-center gap-2 text-[10px] text-purple-400 font-bold uppercase tracking-widest">
|
|
<i data-lucide="sparkle" class="w-3 h-3 text-purple-400"></i> Life Harmony AI
|
|
</div>
|
|
<p class="text-xs text-purple-100/80 italic leading-snug ${ev.isNew ? 'typing-text' : ''}">${ev.aiReply}</p>
|
|
</div>
|
|
</div>
|
|
`).join('')}
|
|
</div>
|
|
</div>
|
|
`,
|
|
script: (scripts, isGenerating, config, npc, user, customPersonas) => `
|
|
<div class="space-y-6">
|
|
<h2 class="text-xl font-light text-purple-100">剧本生成器</h2>
|
|
|
|
<!-- User Base Info Section -->
|
|
<div class="glass p-5 rounded-3xl border-purple-500/20 space-y-4">
|
|
<div class="flex items-center justify-between">
|
|
<span class="text-[10px] text-purple-400 uppercase tracking-wider font-bold">我的基础人设</span>
|
|
<span class="text-[8px] text-white/30 italic">可自由修改</span>
|
|
</div>
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<input id="edit-name" type="text" value="${user.nickname}" placeholder="姓名" class="bg-white/5 border border-white/10 rounded-xl p-3 text-[11px] outline-none text-white focus:border-purple-500/50">
|
|
<select id="edit-zodiac" class="bg-white/5 border border-white/10 rounded-xl p-3 text-[11px] outline-none text-white">
|
|
${zodiacs.map(z => `<option value="${z}" ${user.zodiac===z?'selected':''}>${z}</option>`).join('')}
|
|
</select>
|
|
<select id="edit-mbti" class="bg-white/5 border border-white/10 rounded-xl p-3 text-[11px] outline-none text-white">
|
|
${mbtis.map(m => `<option value="${m}" ${user.mbti===m?'selected':''}>${m}</option>`).join('')}
|
|
</select>
|
|
<input id="edit-job" type="text" value="${user.profession}" placeholder="职业" class="bg-white/5 border border-white/10 rounded-xl p-3 text-[11px] outline-none text-white focus:border-purple-500/50">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="glass p-6 rounded-[2rem] border-white/10 space-y-6">
|
|
<div class="space-y-2">
|
|
<label class="text-[10px] text-purple-400 uppercase tracking-wider font-bold">1. 剧本主题</label>
|
|
<input id="script-theme" type="text" placeholder="如:巅峰重现、治愈之旅、赛博觉醒..." class="w-full bg-white/5 border border-white/10 rounded-2xl p-4 text-sm outline-none focus:border-purple-400/50 transition-all">
|
|
</div>
|
|
|
|
<!-- NPC / Other Persona Setup -->
|
|
<div class="space-y-4">
|
|
<div class="flex items-center justify-between">
|
|
<label class="text-[10px] text-purple-400 uppercase tracking-wider font-bold">2. 关键配角/新的人设</label>
|
|
<button id="add-persona-btn" class="flex items-center gap-1 text-[9px] text-purple-400 border border-purple-400/30 px-2 py-1 rounded-lg hover:bg-purple-500/10 transition-all">
|
|
<i data-lucide="plus" class="w-3 h-3"></i> 添加
|
|
</button>
|
|
</div>
|
|
|
|
<div class="bg-white/5 border border-white/10 rounded-2xl p-4 space-y-4">
|
|
<div class="grid grid-cols-3 gap-2">
|
|
<input id="npc-name" type="text" placeholder="姓名" value="${npc.name}" class="bg-white/5 border border-white/10 rounded-xl p-3 text-[10px] outline-none text-white focus:border-purple-500/50">
|
|
<select id="npc-role" class="bg-white/5 border border-white/10 rounded-xl p-3 text-[10px] outline-none text-white">
|
|
${npcRoles.map(r => `<option value="${r}" ${npc.role===r?'selected':''}>${r}</option>`).join('')}
|
|
</select>
|
|
<select id="npc-relation" class="bg-white/5 border border-white/10 rounded-xl p-3 text-[10px] outline-none text-white">
|
|
${npcRelations.map(r => `<option value="${r}" ${npc.relation===r?'selected':''}>${r}</option>`).join('')}
|
|
</select>
|
|
</div>
|
|
<textarea id="npc-desc" placeholder="自由描述TA的人设特点或关键剧情点..." class="w-full h-16 bg-white/5 border border-white/10 rounded-xl p-3 text-[10px] outline-none resize-none text-white focus:border-purple-500/50">${npc.desc}</textarea>
|
|
</div>
|
|
|
|
<!-- Custom Personas List -->
|
|
<div class="flex flex-wrap gap-2">
|
|
${customPersonas.map((p, idx) => `
|
|
<div class="group relative px-3 py-1.5 bg-purple-500/10 border border-purple-500/30 rounded-full flex items-center gap-2">
|
|
<span class="text-[10px] text-purple-200">${p.name} (${p.role})</span>
|
|
<button class="delete-persona-btn opacity-40 hover:opacity-100 transition-opacity" data-idx="${idx}">
|
|
<i data-lucide="x" class="w-3 h-3"></i>
|
|
</button>
|
|
</div>
|
|
`).join('')}
|
|
</div>
|
|
</div>
|
|
|
|
<div class="space-y-2">
|
|
<label class="text-[10px] text-purple-400 uppercase tracking-wider font-bold">3. 核心参数</label>
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<div class="space-y-2">
|
|
<p class="text-[9px] text-white/40 ml-1">叙事风格</p>
|
|
<div class="flex flex-wrap gap-1.5">
|
|
${scriptStyles.map(s => `
|
|
<button data-val="${s}" class="style-btn px-3 py-1.5 rounded-xl text-[10px] border transition-all ${config.style === s ? 'bg-purple-400/20 border-purple-400 text-purple-300' : 'bg-white/5 border-white/5 text-white/40'}">${s}</button>
|
|
`).join('')}
|
|
</div>
|
|
</div>
|
|
<div class="space-y-2">
|
|
<p class="text-[9px] text-white/40 ml-1">故事篇幅</p>
|
|
<div class="flex flex-wrap gap-1.5">
|
|
${scriptLengths.map(l => `
|
|
<button data-val="${l}" class="length-btn px-3 py-1.5 rounded-xl text-[10px] border transition-all ${config.length === l ? 'bg-purple-400/20 border-purple-400 text-purple-300' : 'bg-white/5 border-white/5 text-white/40'}">${l}</button>
|
|
`).join('')}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<button id="gen-script" class="w-full py-4 mt-2 bg-gradient-to-r from-purple-500 to-violet-500 text-white rounded-2xl font-bold text-sm shadow-[0_8px_20px_rgba(168,85,247,0.3)] flex items-center justify-center gap-2 active:scale-95 transition-all">
|
|
${isGenerating ? '<div class="starlight-gathering-gold w-4 h-4"></div> 命运编织中...' : '生成平行人生剧本'}
|
|
</button>
|
|
</div>
|
|
|
|
${scripts.length === 0 && !isGenerating ? `
|
|
<div class="h-40 glass rounded-[2rem] flex flex-col items-center justify-center p-8 text-center space-y-4 opacity-40">
|
|
<i data-lucide="film" class="w-8 h-8 text-purple-500"></i>
|
|
<p class="text-[10px] text-white/60">尚未生成剧本,定义你的未来篇章</p>
|
|
</div>
|
|
` : ''}
|
|
|
|
${isGenerating ? `
|
|
<div class="glass p-10 rounded-[2rem] flex flex-col items-center gap-4 animate-pulse border-purple-500/30">
|
|
<div class="starlight-gathering-gold"></div>
|
|
<p class="text-xs text-purple-300/60 font-serif tracking-widest">正在采集星海中的深紫色碎屑...</p>
|
|
</div>
|
|
` : scripts.map(s => `
|
|
<div class="glass p-6 rounded-[2rem] space-y-4 border-l-4 border-purple-400 relative overflow-hidden group">
|
|
<div class="absolute top-0 right-0 p-3 opacity-10 group-hover:opacity-30 transition-opacity">
|
|
<i data-lucide="crown" class="w-12 h-12 text-purple-400"></i>
|
|
</div>
|
|
<h3 class="text-lg text-purple-100 font-medium">${s.title}</h3>
|
|
<p class="text-xs text-white/50 line-clamp-3 leading-relaxed">${s.summary}</p>
|
|
<div class="flex justify-between items-center pt-2">
|
|
<span class="px-3 py-1 bg-purple-400/10 text-purple-400 text-[10px] rounded-full border border-purple-400/20">${s.persona}</span>
|
|
<button class="text-xs text-purple-400 font-bold select-script flex items-center gap-1" data-id="${s.id}">
|
|
路径映射 <i data-lucide="arrow-right" class="w-3 h-3"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
`).join('')}
|
|
</div>
|
|
`,
|
|
path: (activePath) => `
|
|
<div class="space-y-6">
|
|
<h2 class="text-xl font-light text-purple-100">实现路径</h2>
|
|
${!activePath ? `
|
|
<div class="glass p-12 rounded-[2rem] text-center space-y-4 border-white/5">
|
|
<i data-lucide="milestone" class="mx-auto w-10 h-10 text-purple-500/20"></i>
|
|
<p class="text-xs text-purple-300/40 italic">“未来尚未写就,请先在剧本页选择一个目标。”</p>
|
|
</div>
|
|
` : `
|
|
<div class="space-y-6">
|
|
<div class="p-6 glass-gold rounded-[2rem] border-purple-400/30 mb-4">
|
|
<div class="text-[10px] uppercase tracking-widest text-purple-400 mb-2 font-bold">目标:${activePath.title}</div>
|
|
<div class="text-sm font-medium text-purple-100">${activePath.summary.slice(0, 80)}...</div>
|
|
</div>
|
|
<div class="relative pl-8 space-y-12">
|
|
<div class="absolute left-[15px] top-4 bottom-4 w-0.5 bg-gradient-to-b from-purple-400 via-purple-400/20 to-transparent opacity-30"></div>
|
|
${activePath.steps.map((step, i) => `
|
|
<div class="relative">
|
|
<div class="absolute -left-10 w-6 h-6 rounded-full border-2 border-purple-400 bg-[#080B12] flex items-center justify-center z-10 shadow-[0_0_15px_rgba(168,85,247,0.4)]">
|
|
<div class="w-2 h-2 rounded-full ${step.done ? 'bg-purple-400 animate-pulse' : 'bg-white/10'}"></div>
|
|
</div>
|
|
<div class="glass p-5 rounded-[1.5rem] ${step.done ? 'border-purple-400/30' : 'opacity-40'}">
|
|
<div class="text-[10px] text-purple-400 font-bold mb-1 uppercase tracking-tighter">节点 ${i+1}</div>
|
|
<h4 class="text-sm font-medium mb-1 text-white">${step.task}</h4>
|
|
<p class="text-[10px] text-white/50 leading-relaxed">${step.desc}</p>
|
|
</div>
|
|
</div>
|
|
`).join('')}
|
|
</div>
|
|
</div>
|
|
`}
|
|
</div>
|
|
`,
|
|
profile: (user) => `
|
|
<div class="space-y-8 pb-10">
|
|
<div class="flex flex-col items-center text-center space-y-4">
|
|
<div class="w-24 h-24 rounded-full border-2 border-purple-400/30 p-1 relative shadow-[0_0_40px_rgba(168,85,247,0.1)]">
|
|
<img src="https://api.dicebear.com/7.x/avataaars/svg?seed=${user.nickname || 'life'}&backgroundColor=A855F7" class="w-full h-full rounded-full bg-purple-900/10">
|
|
<div class="absolute bottom-1 right-1 w-6 h-6 bg-purple-500 rounded-full border-2 border-[#080B12] flex items-center justify-center">
|
|
<i data-lucide="shield-check" class="w-3 h-3 text-white"></i>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<h2 class="text-2xl font-light text-purple-50">${user.nickname || '未同步系统'}</h2>
|
|
<p class="text-[10px] text-purple-400 font-mono tracking-widest uppercase">${user.mbti || 'QUESTER'} · ${user.zodiac || 'STAR'} · ${user.profession || '星民'}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-2 gap-4">
|
|
<div class="glass p-5 rounded-[1.5rem] flex flex-col items-center gap-1">
|
|
<span class="text-[10px] text-white/30 uppercase tracking-widest">觉醒深度</span>
|
|
<span class="text-xl font-light text-purple-200">Lv.4</span>
|
|
</div>
|
|
<div class="glass p-5 rounded-[1.5rem] flex flex-col items-center gap-1">
|
|
<span class="text-[10px] text-white/30 uppercase tracking-widest">星历契合</span>
|
|
<span class="text-xl font-light text-purple-200">98%</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="space-y-3">
|
|
<button class="w-full glass p-5 rounded-[1.5rem] flex justify-between items-center text-sm hover:bg-white/5 transition-all">
|
|
<div class="flex items-center gap-4 text-white/80"><i data-lucide="user" class="w-5 h-5 text-purple-400"></i><span>个人档案设置</span></div>
|
|
<i data-lucide="chevron-right" class="w-4 h-4 opacity-30"></i>
|
|
</button>
|
|
<button class="w-full glass p-5 rounded-[1.5rem] flex justify-between items-center text-sm hover:bg-white/5 transition-all">
|
|
<div class="flex items-center gap-4 text-white/80"><i data-lucide="layers" class="w-5 h-5 text-purple-400"></i><span>多账号切换</span></div>
|
|
<i data-lucide="chevron-right" class="w-4 h-4 opacity-30"></i>
|
|
</button>
|
|
<button class="w-full glass p-5 rounded-[1.5rem] flex justify-between items-center text-sm hover:bg-white/5 transition-all">
|
|
<div class="flex items-center gap-4 text-white/80"><i data-lucide="mail" class="w-5 h-5 text-purple-400"></i><span>与开发者对话</span></div>
|
|
<i data-lucide="external-link" class="w-4 h-4 opacity-30"></i>
|
|
</button>
|
|
</div>
|
|
|
|
<button class="w-full py-4 text-[10px] text-white/20 font-bold tracking-[0.3em] uppercase hover:text-purple-500/50 transition-colors">Terminate Life Harmony</button>
|
|
</div>
|
|
`
|
|
};
|