366 lines
20 KiB
HTML
366 lines
20 KiB
HTML
<!doctype html>
|
||
<html lang="zh-CN" data-theme="dark">
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||
<title>魂镜 · 人物详情页设计预览</title>
|
||
<link rel="stylesheet" href="tokens.css" />
|
||
<link rel="stylesheet" href="_base.css" />
|
||
<link rel="stylesheet" href="_chrome.css" />
|
||
<style>
|
||
/* ============================================================
|
||
* 铜镜鉴心 v2.1 — 人物详情页
|
||
* ============================================================ */
|
||
|
||
/* ── 通用布局 ── */
|
||
|
||
.app-main { flex: 1; padding: 24px 28px 56px; max-width: 920px; width: 100%; margin: 0 auto; }
|
||
@media (max-width: 900px) { .sidebar-wrap { display: none; } }
|
||
|
||
/* ── 操作栏 ── */
|
||
.action-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin: 14px 0 18px; }
|
||
.badge { display: inline-flex; align-items: center; gap: 5px; padding: 4px 12px; border-radius: 999px; font-family: "JetBrains Mono", monospace; font-size: 11px; border: 1px solid var(--rule); background: var(--surface); color: var(--fg-dim); }
|
||
.badge.active { border-color: var(--patina-dim); color: var(--patina); background: var(--patina-wash); }
|
||
.badge.paused { border-color: var(--gilt-dim); color: var(--gilt); background: var(--gilt-faint); }
|
||
.badge.wuji { border-color: var(--rule); color: var(--fg-faint); }
|
||
|
||
/* ── 生命周期条 ── */
|
||
.lifecycle-bar { display: flex; align-items: center; gap: 3px; font-family: "JetBrains Mono", monospace; font-size: 10.5px; }
|
||
.lifecycle-step { display: inline-flex; align-items: center; gap: 4px; padding: 3px 9px; border-radius: 999px; color: var(--fg-faint); border: 1px solid transparent; }
|
||
.lifecycle-step.past { color: var(--patina); border-color: var(--patina-dim); background: var(--patina-wash); }
|
||
.lifecycle-step.current { color: var(--gilt); border-color: var(--gilt-dim); background: var(--gilt-faint); }
|
||
.lifecycle-arrow { color: var(--fg-faint); font-size: 12px; opacity: 0.5; }
|
||
|
||
.action-link { margin-left: auto; display: inline-flex; align-items: center; gap: 5px; padding: 6px 14px; border-radius: 10px; font-size: 12px; color: var(--patina); border: 1px solid var(--patina-dim); background: var(--patina-wash); text-decoration: none; transition: background 0.12s; cursor: pointer; }
|
||
.action-link:hover { background: var(--patina-dim); color: var(--fg); }
|
||
|
||
/* ── 卡片 ── */
|
||
|
||
.card-banner { height: 72px; background: linear-gradient(135deg, var(--patina-wash), var(--glass), var(--gilt-faint)); }
|
||
|
||
/* ── 铜镜头像 ── */
|
||
.avatar-section { position: relative; width: 88px; height: 88px; margin-top: -48px; margin-bottom: 12px; }
|
||
.avatar-img { width: 88px; height: 88px; border-radius: 50%; border: 3px solid var(--gilt); box-shadow: 0 0 0 3px var(--surface), 0 0 16px rgba(201,162,74,0.25); overflow: hidden; display: flex; align-items: center; justify-content: center; background: conic-gradient(from 0deg, var(--ink), var(--night-bronze), var(--patina-dim), var(--gilt-dim), var(--ink)); position: relative; cursor: pointer; transition: filter 0.2s; }
|
||
.avatar-img:hover { filter: brightness(1.15); }
|
||
.avatar-img .placeholder { font-size: 28px; opacity: 0.6; }
|
||
.avatar-img img { width: 100%; height: 100%; object-fit: cover; border-radius: 50%; }
|
||
.avatar-overlay { position: absolute; inset: 0; border-radius: 50%; background: rgba(0,0,0,0.5); display: flex; align-items: center; justify-content: center; opacity: 0; transition: opacity 0.2s; }
|
||
.avatar-section:hover .avatar-overlay { opacity: 1; }
|
||
.avatar-overlay .upload-label { display: flex; align-items: center; gap: 3px; color: #fff; font-size: 10px; cursor: pointer; }
|
||
.avatar-overlay .upload-icon { font-size: 20px; }
|
||
.avatar-name-badge { flex: 1; }
|
||
|
||
.identity-header { display: flex; align-items: flex-end; justify-content: space-between; }
|
||
.char-name { font-family: "Songti SC", serif; font-size: 20px; font-weight: 700; color: var(--fg); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||
.char-inner-name { font-size: 12px; color: var(--fg-dim); margin-top: 1px; }
|
||
|
||
/* ── 档案信息网格 ── */
|
||
.info-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 20px; margin-top: 14px; }
|
||
.info-item .label { font-size: 12px; color: var(--muted); }
|
||
.info-item .value { font-size: 14px; font-weight: 500; color: var(--fg); }
|
||
.quote { font-style: italic; color: var(--fg-dim); font-size: 14px; margin-top: 12px; padding-left: 10px; border-left: 2px solid var(--gilt-dim); }
|
||
.bio-section { margin-top: 14px; border-top: 1px solid var(--rule); padding-top: 14px; }
|
||
.bio-section .label { font-size: 12px; color: var(--muted); margin-bottom: 4px; }
|
||
.bio-section .text { font-size: 14px; line-height: 1.7; color: var(--fg); white-space: pre-wrap; }
|
||
|
||
/* ── 双列布局 ── */
|
||
.two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
|
||
|
||
/* ── 表单 ── */
|
||
.form-card .card-header { display: flex; align-items: center; justify-content: space-between; padding: 14px 20px 0; }
|
||
.form-card .card-title { font-family: "Songti SC", serif; font-size: 15px; font-weight: 600; color: var(--fg); display: flex; align-items: center; gap: 6px; }
|
||
.form-card .card-title .glyph { color: var(--cinnabar); opacity: 0.7; }
|
||
.form-body { padding: 14px 20px 20px; }
|
||
.field { margin-bottom: 12px; }
|
||
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
|
||
.field-label { display: block; font-family: "JetBrains Mono", monospace; font-size: 11px; letter-spacing: 0.04em; color: var(--muted); margin-bottom: 4px; }
|
||
.field input, .field textarea, .field select { width: 100%; padding: 8px 12px; border: 1px solid var(--rule); border-radius: 10px; background: var(--glass); color: var(--fg); font-family: inherit; font-size: 13px; transition: border-color 0.15s; }
|
||
.field input:focus, .field textarea:focus, .field select:focus { outline: none; border-color: var(--patina-dim); }
|
||
.field textarea { min-height: 64px; resize: vertical; }
|
||
.field-hint { font-size: 11px; color: var(--fg-faint); margin-top: 3px; }
|
||
.btn-save { display: inline-flex; align-items: center; gap: 5px; padding: 6px 16px; border-radius: 10px; font-size: 12px; font-weight: 500; border: 1px solid var(--patina-dim); background: var(--patina-wash); color: var(--patina); cursor: pointer; transition: background 0.12s; font-family: inherit; }
|
||
.btn-save:hover { background: var(--patina-dim); color: var(--fg); }
|
||
.btn-save:disabled { opacity: 0.4; cursor: default; }
|
||
|
||
/* ── Tag 输入模拟 ── */
|
||
.tag-input-mock { display: flex; flex-wrap: wrap; gap: 4px; padding: 6px 10px; border: 1px solid var(--rule); border-radius: 10px; background: var(--glass); min-height: 34px; align-items: center; }
|
||
|
||
/* ── Modal ── */
|
||
.modal-overlay { position: fixed; inset: 0; z-index: 100; background: rgba(0,0,0,0.55); backdrop-filter: blur(6px); display: flex; align-items: center; justify-content: center; padding: 20px; }
|
||
.modal { background: var(--ink); border: 1px solid var(--rule); border-radius: 18px; width: 100%; max-width: 420px; box-shadow: 0 12px 60px rgba(0,0,0,0.6); }
|
||
.modal-header { display: flex; align-items: center; gap: 12px; padding: 18px 22px 10px; border-bottom: 1px solid var(--rule); }
|
||
.modal-title { font-family: "Songti SC", serif; font-size: 16px; font-weight: 600; color: var(--fg); flex: 1; }
|
||
.modal-close { width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; border-radius: 8px; cursor: pointer; border: none; background: none; color: var(--fg-faint); font-size: 18px; transition: background 0.12s; }
|
||
.modal-close:hover { background: var(--surface-hi); color: var(--fg); }
|
||
.modal-body { padding: 18px 22px 22px; }
|
||
|
||
|
||
/* ── Toast ── */
|
||
.toast { position: fixed; bottom: 24px; right: 24px; z-index: 200; display: flex; align-items: center; gap: 8px; padding: 10px 16px; border-radius: 12px; border: 1px solid var(--patina-dim); background: var(--surface); backdrop-filter: blur(12px); font-size: 13px; color: var(--patina); box-shadow: 0 4px 24px rgba(0,0,0,0.5); }
|
||
|
||
/* ── Responsive ── */
|
||
@media (max-width: 768px) {
|
||
.app-main { padding: 16px 14px 40px; }
|
||
.two-col { grid-template-columns: 1fr; }
|
||
.info-grid { grid-template-columns: 1fr; }
|
||
.field-row { grid-template-columns: 1fr; }
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="app-shell">
|
||
<div class="sidebar-mount" data-active="人物"></div>
|
||
<div class="main-area">
|
||
<main class="app-main">
|
||
|
||
<!-- ═══ 面包屑 ═══ -->
|
||
<a class="back-link" href="characters-preview.html">← 返回人物列表</a>
|
||
|
||
<!-- ═══ 页头 ═══ -->
|
||
<h1 class="page-title">时崎狂三</h1>
|
||
<p class="page-sub">内部名称:tokisaki_kurumi · 创建于 2026-07-09 14:32:18</p>
|
||
|
||
<!-- ═══ 操作栏 ═══ -->
|
||
<div class="action-bar">
|
||
<span class="badge active">● active</span>
|
||
|
||
<span class="lifecycle-bar">
|
||
<span class="lifecycle-step past">无极</span><span class="lifecycle-arrow">→</span>
|
||
<span class="lifecycle-step past">立名</span><span class="lifecycle-arrow">→</span>
|
||
<span class="lifecycle-step past">设定</span><span class="lifecycle-arrow">→</span>
|
||
<span class="lifecycle-step past">初识</span><span class="lifecycle-arrow">→</span>
|
||
<span class="lifecycle-step current">太极</span><span class="lifecycle-arrow">→</span>
|
||
<span class="lifecycle-step">归档</span>
|
||
</span>
|
||
|
||
<a class="action-link" href="#">资料与沉淀 →</a>
|
||
</div>
|
||
|
||
<!-- ═══ 角色身份卡 ═══ -->
|
||
<div class="card">
|
||
<div class="card-banner"></div>
|
||
<div class="card-body">
|
||
<!-- 头像:预留图片 -->
|
||
<div class="avatar-section" onclick="document.getElementById('modal-upload').style.display='flex'">
|
||
<div class="avatar-img">
|
||
<span class="placeholder">☯</span>
|
||
</div>
|
||
<div class="avatar-overlay">
|
||
<span class="upload-label">
|
||
<span class="upload-icon">📷</span>
|
||
更换头像
|
||
</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="identity-header">
|
||
<div>
|
||
<div class="char-name">时崎狂三</div>
|
||
<div class="char-inner-name">内部名称:tokisaki_kurumi</div>
|
||
</div>
|
||
<span class="badge active">● active</span>
|
||
</div>
|
||
|
||
<div class="info-grid">
|
||
<div class="info-item"><div class="label">生日</div><div class="value">2000-12-25</div></div>
|
||
<div class="info-item"><div class="label">身高</div><div class="value">157 cm</div></div>
|
||
<div class="info-item"><div class="label">体重</div><div class="value">43 kg</div></div>
|
||
<div class="info-item"><div class="label">当前心情</div><div class="value">平静(42%)</div></div>
|
||
<div class="info-item"><div class="label">语言</div><div class="value">zh-CN</div></div>
|
||
<div class="info-item"><div class="label">创建时间</div><div class="value">2026-07-09 14:32</div></div>
|
||
</div>
|
||
|
||
<div class="quote">「优雅从容的大小姐口气,语速中等偏慢…」</div>
|
||
|
||
<div class="bio-section">
|
||
<div class="label">背景</div>
|
||
<div class="text">
|
||
拥有时间之力的精灵「Nightmare(梦魇)」。
|
||
为了某个终极目标在时间洪流中独自前行,通过吞噬他人的时间维持自己的存在。
|
||
她的过去充满了失去与痛苦,但她从不后悔自己选择的道路。
|
||
</div>
|
||
</div>
|
||
|
||
<div class="bio-section">
|
||
<div class="label">兴趣爱好</div>
|
||
<div class="tag-input-mock" style="margin-top:4px;">
|
||
<span class="tag">与猫相处</span>
|
||
<span class="tag">阅读</span>
|
||
<span class="tag">钢琴</span>
|
||
<span class="tag">收藏古董时钟</span>
|
||
<span class="tag">摄影</span>
|
||
<span class="tag">品尝红茶与甜点</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="bio-section">
|
||
<div class="label">价值观</div>
|
||
<div class="tag-input-mock" style="margin-top:4px;">
|
||
<span class="tag">自由</span>
|
||
<span class="tag">尊严</span>
|
||
<span class="tag">独立</span>
|
||
<span class="tag">记忆</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ═══ 双列:档案编辑 + 模型策略 ═══ -->
|
||
<div class="two-col">
|
||
|
||
<!-- 左:人物档案编辑 -->
|
||
<div class="card form-card">
|
||
<div class="card-header">
|
||
<h2 class="card-title"><span class="glyph">📋</span> 人物档案</h2>
|
||
<button class="btn-save">✎ 保存</button>
|
||
</div>
|
||
<div class="form-body">
|
||
<div class="field">
|
||
<label class="field-label">显示名</label>
|
||
<input type="text" value="时崎狂三" />
|
||
</div>
|
||
<div class="field-row">
|
||
<div class="field">
|
||
<label class="field-label">生日</label>
|
||
<input type="date" value="2000-12-25" />
|
||
</div>
|
||
<div class="field">
|
||
<label class="field-label">身高</label>
|
||
<input type="text" value="157" />
|
||
</div>
|
||
</div>
|
||
<div class="field-row">
|
||
<div class="field">
|
||
<label class="field-label">体重</label>
|
||
<input type="text" value="43" />
|
||
</div>
|
||
<div class="field">
|
||
<label class="field-label">性情气质</label>
|
||
<input type="text" value="优雅腹黑、孤独偏执" />
|
||
</div>
|
||
</div>
|
||
<div class="field">
|
||
<label class="field-label">表达风格</label>
|
||
<input type="text" value="优雅从容的大小姐口气,语速中等偏慢" />
|
||
</div>
|
||
<div class="field">
|
||
<label class="field-label">背景</label>
|
||
<textarea>拥有时间之力的精灵「Nightmare(梦魇)」。</textarea>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 右:模型策略编辑 -->
|
||
<div class="card form-card">
|
||
<div class="card-header">
|
||
<h2 class="card-title"><span class="glyph">⚙</span> 模型策略</h2>
|
||
<button class="btn-save">✎ 保存</button>
|
||
</div>
|
||
<div class="form-body">
|
||
<div class="field">
|
||
<label class="field-label">对话模型</label>
|
||
<select>
|
||
<option>— 不设置(使用系统默认)</option>
|
||
<option selected>deepseek-v4-flash</option>
|
||
<option>deepseek-v3</option>
|
||
<option>gpt-4o</option>
|
||
</select>
|
||
<span class="field-hint">留空则使用 DEFAULT_MODEL_HINT</span>
|
||
</div>
|
||
<div class="field">
|
||
<label class="field-label">记忆提取模型</label>
|
||
<select>
|
||
<option>— 不设置(空)</option>
|
||
<option selected>memory-extraction</option>
|
||
<option>deepseek-v4-flash</option>
|
||
</select>
|
||
</div>
|
||
<div class="field">
|
||
<label class="field-label">人格分析模型</label>
|
||
<select>
|
||
<option>— 不设置(空)</option>
|
||
<option selected>personality-analysis</option>
|
||
<option>deepseek-v4-flash</option>
|
||
</select>
|
||
</div>
|
||
<div class="field">
|
||
<label class="field-label">向量嵌入模型</label>
|
||
<select>
|
||
<option>— 不设置(空)</option>
|
||
<option selected>embedding</option>
|
||
<option>text-embedding-3-small</option>
|
||
</select>
|
||
</div>
|
||
<div class="field">
|
||
<label class="field-label">私隐等级</label>
|
||
<select>
|
||
<option selected>normal</option>
|
||
<option>sensitive</option>
|
||
<option>local_only</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
</main>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ═══ 上传头像 Modal ═══ -->
|
||
<div class="modal-overlay" id="modal-upload" style="display:none;" onclick="if(event.target===this)this.style.display='none'">
|
||
<div class="modal">
|
||
<div class="modal-header">
|
||
<h3 class="modal-title">📷 上传头像</h3>
|
||
<button class="modal-close" onclick="document.getElementById('modal-upload').style.display='none'">✕</button>
|
||
</div>
|
||
<div class="modal-body" style="text-align:center;">
|
||
<!-- 预览区 -->
|
||
<div style="width:120px;height:120px;border-radius:50%;border:3px dashed var(--rule);margin:0 auto 16px;display:flex;align-items:center;justify-content:center;background:var(--glass);overflow:hidden;" id="preview-area">
|
||
<span style="font-size:36px;opacity:0.25;color:var(--fg-faint);">+</span>
|
||
</div>
|
||
<!-- 上传按钮 -->
|
||
<label class="btn btn-primary" style="display:inline-flex;cursor:pointer;">
|
||
📁 选择图片
|
||
<input type="file" accept="image/*" style="display:none;" onchange="previewFile(this)" />
|
||
</label>
|
||
<p style="font-size:11px;color:var(--fg-faint);margin-top:10px;">支持 JPG / PNG / WebP,建议 512×512 以上,最大 5MB</p>
|
||
<div style="display:flex;gap:8px;justify-content:center;margin-top:16px;">
|
||
<button class="btn btn-outline" onclick="document.getElementById('modal-upload').style.display='none'">取消</button>
|
||
<button class="btn btn-primary" onclick="showToast('✔ 头像已更新');document.getElementById('modal-upload').style.display='none'">✚ 上传</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="toast" id="toast" style="display:none;">✔ 已保存</div>
|
||
|
||
<script>
|
||
function previewFile(input) {
|
||
const file = input.files && input.files[0];
|
||
if (!file) return;
|
||
const reader = new FileReader();
|
||
reader.onload = function(e) {
|
||
const area = document.getElementById('preview-area');
|
||
area.innerHTML = '<img src="' + e.target.result + '" style="width:100%;height:100%;object-fit:cover;" />';
|
||
};
|
||
reader.readAsDataURL(file);
|
||
}
|
||
function showToast(msg) {
|
||
const t = document.getElementById('toast');
|
||
t.textContent = msg;
|
||
t.style.display = 'flex';
|
||
setTimeout(function() { t.style.display = 'none'; }, 2500);
|
||
}
|
||
document.addEventListener('keydown', function(e) {
|
||
if (e.key === 'Escape') document.querySelectorAll('.modal-overlay').forEach(function(m) { m.style.display = 'none'; });
|
||
});
|
||
</script>
|
||
|
||
<script src="_theme.js" defer></script>
|
||
|
||
|
||
</body>
|
||
</html>
|