![]()
💬 开场白
“`html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>创世面板</title>
<style>
/* 引入华丽风格字体 */
@import url('https://fonts.googleapis.com/css2?family=Cinzel+Decorative:wght@700&family=Noto+Serif+SC:wght@400;600&display=swap');/* — 变量定义 — */
:root {
–bg-color: #0c0a1f; /* 深邃星空紫 */
–panel-bg: rgba(26, 20, 46, 0.6); /* 半透明面板背景 */
–border-color: rgba(255, 215, 0, 0.3); /* 金色微光边框 */
–glow-color: rgba(255, 215, 0, 0.8); /* 金色辉光 */
–text-color: #e0e6f0; /* 柔和星光白 */
–title-color: #FFD700; /* 华丽金色 */
–accent-color: #c5a6ff; /* 神秘紫罗兰 */
–font-title: 'Cinzel Decorative', cursive;
–font-body: 'Noto Serif SC', serif;
}/* — 整体布局 — */
.genesis-container {
width: 100%;
max-width: 800px;
margin: auto;
font-family: var(–font-body);
color: var(–text-color);
background: var(–bg-color);
border: 2px solid var(–border-color);
border-radius: 20px;
padding: 2.5rem;
box-shadow: 0 0 40px rgba(0, 0, 0, 0.5), 0 0 25px var(–glow-color) inset;
position: relative;
overflow: hidden;
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
}/* 动画背景 */
.genesis-container::before {
content: '';
position: absolute;
top: 0; left: 0;
width: 100%; height: 100%;
background: linear-gradient(45deg, rgba(197, 166, 255, 0.1), transparent, rgba(255, 215, 0, 0.1));
animation: gradient-flow 15s ease infinite;
z-index: -1;
background-size: 200% 200%;
}@keyframes gradient-flow {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}/* — 标题 — */
.genesis-title {
font-family: var(–font-title);
color: var(–title-color);
text-align: center;
font-size: 2.8em;
margin-bottom: 2rem;
text-shadow: 0 0 10px var(–glow-color), 0 0 20px var(–glow-color);
animation: pulse-glow 4s ease-in-out infinite;
}@keyframes pulse-glow {
0%, 100% { text-shadow: 0 0 10px var(–glow-color), 0 0 20px var(–glow-color); }
50% { text-shadow: 0 0 20px var(–glow-color), 0 0 40px var(–glow-color); }
}/* — 模式切换Tabs — */
.mode-switcher {
display: flex;
justify-content: center;
margin-bottom: 2rem;
border: 1px solid var(–border-color);
border-radius: 50px;
padding: 5px;
background: rgba(0,0,0,0.2);
}
.mode-tab {
flex: 1;
text-align: center;
padding: 12px 20px;
border-radius: 50px;
cursor: pointer;
transition: all 0.4s ease;
font-weight: 600;
}
.mode-tab.active {
background: linear-gradient(45deg, var(–accent-color), #8d62d9);
color: #fff;
box-shadow: 0 0 15px rgba(197, 166, 255, 0.6);
}/* — 内容面板 — */
.form-panel { display: none; }
.form-panel.active { display: block; animation: fadeIn 0.6s ease; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }/* — 步骤/字段组 — */
.step {
margin-bottom: 2rem;
padding: 1.5rem;
border: 1px solid var(–border-color);
border-radius: 15px;
background: var(–panel-bg);
}
.step-title {
font-size: 1.4em;
color: var(–accent-color);
margin-bottom: 1.2rem;
padding-bottom: 0.5rem;
border-bottom: 1px dashed var(–border-color);
}/* — 选项气泡 (模板模式) — */
.option-bubbles {
display: flex;
flex-wrap: wrap;
gap: 12px;
}
.bubble {
padding: 10px 20px;
border-radius: 30px;
border: 1px solid var(–border-color);
cursor: pointer;
transition: all 0.3s ease;
background: rgba(255,255,255,0.05);
position: relative; /* For tooltips */
}
.bubble:hover {
background: var(–accent-color);
border-color: var(–accent-color);
color: var(–bg-color);
box-shadow: 0 0 10px var(–accent-color);
transform: translateY(-3px);
}
.bubble.selected {
background: var(–title-color);
border-color: var(–title-color);
color: var(–bg-color);
font-weight: bold;
box-shadow: 0 0 15px var(–glow-color);
}
.bubble[data-tooltip]::after {
content: attr(data-tooltip);
position: absolute;
bottom: 110%;
left: 50%;
transform: translateX(-50%);
background-color: #333;
color: #fff;
padding: 5px 10px;
border-radius: 5px;
white-space: nowrap;
opacity: 0;
visibility: hidden;
transition: opacity 0.3s, visibility 0.3s;
font-size: 0.9em;
}
.bubble[data-tooltip]:hover::after {
opacity: 1;
visibility: visible;
}
.hidden-options { display: none; }/* — 输入框 (自由模式) — */
.form-group {
margin-bottom: 1.5rem;
}
.form-group label {
display: block;
margin-bottom: 0.5rem;
font-size: 1.1em;
font-weight: 600;
}
.form-group input, .form-group textarea {
width: 100%;
background: rgba(0,0,0,0.3);
border: 1px solid var(–border-color);
border-radius: 8px;
padding: 12px;
color: var(–text-color);
font-family: var(–font-body);
transition: all 0.3s ease;
}
.form-group input:focus, .form-group textarea:focus {
outline: none;
border-color: var(–title-color);
box-shadow: 0 0 10px var(–glow-color);
}
.form-group textarea {
min-height: 100px;
resize: vertical;
}/* — 最终按钮 — */
.submit-container {
text-align: center;
margin-top: 2rem;
}
.enter-world-btn {
padding: 15px 40px;
font-family: var(–font-title);
font-size: 1.5em;
color: var(–bg-color);
background: linear-gradient(45deg, var(–title-color), #f0c040);
border: none;
border-radius: 50px;
cursor: pointer;
transition: all 0.4s ease;
box-shadow: 0 5px 20px rgba(255, 215, 0, 0.4);
}
.enter-world-btn:hover {
transform: scale(1.05);
box-shadow: 0 8px 30px rgba(255, 215, 0, 0.6);
}
.enter-world-btn:active {
transform: scale(0.98);
box-shadow: 0 2px 10px rgba(255, 215, 0, 0.4);
}</style>
</head>
<body>
<div class="genesis-container">
<h1 class="genesis-title">创世面板</h1><div class="mode-switcher">
<div class="mode-tab active" data-mode="guided">模板创世</div>
<div class="mode-tab" data-mode="free">自由创世</div>
</div><!– 模板创世 –>
<div id="guided-panel" class="form-panel active">
<div id="guided-form">
<!– 步骤1: 选择大分类 –>
<div class="step">
<h2 class="step-title">第一步:选择世界基调</h2>
<div class="option-bubbles" id="category-selection">
<div class="bubble" data-value="男频">男频</div>
<div class="bubble" data-value="女频">女频</div>
</div>
</div>
<!– 步骤2: 选择类型 (动态加载) –>
<div class="step hidden-options" id="genre-step">
<h2 class="step-title">第二步:选择故事类型</h2>
<div class="option-bubbles" id="genre-selection"></div>
</div>
<!– 步骤3: 选择子类 (动态加载) –>
<div class="step hidden-options" id="subgenre-step">
<h2 class="step-title">第三步:选择核心设定</h2>
<div class="option-bubbles" id="subgenre-selection"></div>
</div>
<!– 步骤4: 选择附加元素 (动态加载) –>
<div class="step hidden-options" id="elements-step">
<h2 class="step-title">第四步:添加魅力元素 (可多选)</h2>
<div class="option-bubbles" id="elements-selection"></div>
</div>
</div>
</div><!– 自由创世 –>
<div id="free-panel" class="form-panel">
<form id="free-form">
<div class="form-group">
<label for="world-name">世界名称</label>
<input type="text" id="world-name" placeholder="例如:永黯星域、瓦尔德兰">
</div>
<div class="form-group">
<label for="free-genre">故事类型</label>
<input type="text" id="free-genre" placeholder="例如:赛博朋克、废土、克苏鲁神话">
</div>
<div class="form-group">
<label for="free-background">核心背景</label>
<textarea id="free-background" placeholder="描述世界的关键设定、历史、势力分布等。"></textarea>
</div>
<div class="form-group">
<label for="user-role">你的身份</label>
<textarea id="user-role" placeholder="描述你(user)的初始身份、目标或特长。"></textarea>
</div>
<div class="form-group">
<label for="plot-hook">情节引子</label>
<textarea id="plot-hook" placeholder="希望故事从哪里开始?例如:'我从一场爆炸中醒来,失去了记忆'"></textarea>
</div>
</form>
</div><div class="submit-container">
<button class="enter-world-btn" onclick="enterWorld()">进入世界</button>
</div>
</div><script>
// — 数据定义 —
const optionsData = {
"男频": {
genres: { "玄幻": "东方异世界,修炼升级", "都市": "现代背景,超凡力量", "仙侠": "求仙问道,斩妖除魔", "科幻": "星辰大海,未来科技", "历史": "架空古代,权谋争霸" },
subgenres: {
"玄幻": { "废柴逆袭": "主角从弱小崛起", "老爷爷流": "随身携带强大灵魂", "无敌流": "开局即巅峰", "退婚羞辱": "经典打脸剧情" },
"都市": { "兵王归来": "顶级特种兵回归都市", "神医/相师": "掌握绝世医术/相术", "神豪系统": "获得无限金钱", "都市修仙": "在现代社会修炼" },
"仙侠": { "凡人修仙": "无灵根凡人逆天改命", "师徒情缘": "感天动地的师徒恋", "剑修": "一剑破万法" },
"科幻": { "机甲浪潮": "驾驶巨型机甲战斗", "星际文明": "多文明间的战争与探索", "末世危机": "末日背景下的生存与重建" },
"历史": { "种田争霸": "攀科技树,发展势力", "权谋斗争": "朝堂之上的智力博弈", "寒门崛起": "平民主角逆袭之路" }
},
elements: [ "系统", "重生", "穿越", "扮猪吃虎", "后宫", "兄弟情" ]
},
"女频": {
genres: { "古代言情": "古代背景下的爱恨情仇", "现代言情": "都市生活中的浪漫故事", "幻想言情": "架空世界的奇幻爱恋" },
subgenres: {
"古代言情": { "宫斗/宅斗": "后院/深宫的智斗", "穿越/重生": "利用先知改变命运", "种田经商": "发家致富,温馨日常", "古风权谋": "女主投身朝堂纷争" },
"现代言情": { "豪门总裁": "霸总与平凡女主的纠葛", "娱乐圈": "明星事业与恋情", "校园": "纯真美好的青春悸动", "破镜重圆": "分手后的再次相爱" },
"幻想言情": { "快穿": "穿梭不同世界完成任务", "末世": "末日背景下的生存与情感", "西幻": "魔法与骑士的浪漫史诗", "仙侠虐恋": "几生几世的爱恨纠缠" }
},
elements: [ "甜宠", "虐恋", "女强", "打脸爽文", "追妻火葬场", "双向奔赴" ]
}
};// — DOM 元素获取 —
const modeTabs = document.querySelectorAll('.mode-tab');
const panels = document.querySelectorAll('.form-panel');
const categorySelection = document.getElementById('category-selection');const genreStep = document.getElementById('genre-step');
const genreSelection = document.getElementById('genre-selection');const subgenreStep = document.getElementById('subgenre-step');
const subgenreSelection = document.getElementById('subgenre-selection');const elementsStep = document.getElementById('elements-step');
const elementsSelection = document.getElementById('elements-selection');let selections = {};
// — 函数定义 —
// 模式切换
modeTabs.forEach(tab => {
tab.addEventListener('click', () => {
modeTabs.forEach(t => t.classList.remove('active'));
tab.classList.add('active');
panels.forEach(p => p.classList.remove('active'));
document.getElementById(`${tab.dataset.mode}-panel`).classList.add('active');
});
});// 更新选项气泡
function updateBubbles(container, options, allowMultiple = false) {
container.innerHTML = '';
for (const [key, value] of Object.entries(options)) {
const bubble = document.createElement('div');
bubble.className = 'bubble';
bubble.dataset.value = key;
bubble.textContent = key;
// Nếu value là string, dùng nó làm tooltip
if (typeof value === 'string') {
bubble.dataset.tooltip = value;
}
bubble.addEventListener('click', () => {
if (allowMultiple) {
bubble.classList.toggle('selected');
} else {
container.querySelectorAll('.bubble').forEach(b => b.classList.remove('selected'));
bubble.classList.add('selected');
}
handleSelection(bubble, allowMultiple);
});
container.appendChild(bubble);
}
}// 处理选择事件
function handleSelection(element, isMultiple) {
const step = element.closest('.step').id;
const parentId = element.parentElement.id;if (parentId === 'category-selection') {
selections = { category: element.dataset.value };
const genreOptions = optionsData[selections.category].genres;
updateBubbles(genreSelection, genreOptions);
genreStep.classList.remove('hidden-options');
subgenreStep.classList.add('hidden-options');
elementsStep.classList.add('hidden-options');
} else if (parentId === 'genre-selection') {
selections.genre = element.dataset.value;
const subgenreOptions = optionsData[selections.category].subgenres[selections.genre] || {};
updateBubbles(subgenreSelection, subgenreOptions);
subgenreStep.classList.remove('hidden-options');const elementOptions = {};
optionsData[selections.category].elements.forEach(el => elementOptions[el] = '');
updateBubbles(elementsSelection, elementOptions, true);
elementsStep.classList.remove('hidden-options');
} else if (parentId === 'subgenre-selection') {
selections.subgenre = element.dataset.value;
}
}// 初始化
function initialize() {
updateBubbles(categorySelection, { "男频": "", "女频": "" });
}// 最终提交
function enterWorld() {
let finalData = {};
const activeMode = document.querySelector('.mode-tab.active').dataset.mode;if (activeMode === 'guided') {
const selectedElements = Array.from(elementsSelection.querySelectorAll('.bubble.selected')).map(b => b.dataset.value);
finalData = {
mode: '模板',
category: selections.category,
genre: selections.genre,
subgenre: selections.subgenre,
elements: selectedElements
};
// 校验
if (!finalData.category || !finalData.genre || !finalData.subgenre) {
triggerSlash('/echo severity=error 请完成所有步骤的选择。');
return;
}
} else { // free mode
finalData = {
mode: '自由',
customData: {
worldName: document.getElementById('world-name').value,
genre: document.getElementById('free-genre').value,
background: document.getElementById('free-background').value,
userRole: document.getElementById('user-role').value,
plotHook: document.getElementById('plot-hook').value
}
};
// 校验
if (!finalData.customData.worldName || !finalData.customData.userRole) {
triggerSlash('/echo severity=error 世界名称和你的身份为必填项。');
return;
}
}const jsonData = JSON.stringify(finalData);
const command = `/echo 正在构筑世界,请稍候… | /send 开始故事:${jsonData} | /trigger`;if (typeof triggerSlash === 'function') {
triggerSlash(command);
} else {
alert('SillyTavern API 未找到。请在SillyTavern环境中使用。');
console.log(command);
}
}initialize();
</script>
</body>
</html>“`