<!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>
* {
box-sizing: border-box;
font-family: "Microsoft YaHei", sans-serif;
}
body {
margin: 0;
padding: 20px;
background-color: #f5f5f5;
color: #333;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
header {
text-align: center;
margin-bottom: 30px;
}
h1 {
color: #8B4513;
margin-bottom: 10px;
}
.tabs {
display: flex;
justify-content: center;
margin-bottom: 20px;
}
.tab {
padding: 10px 20px;
margin: 0 5px;
background-color: #e0e0e0;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
}
.tab.active {
background-color: #8B4513;
color: white;
}
.content {
display: none;
}
.content.active {
display: block;
}
.cards-container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 20px;
}
.card {
background-color: white;
border-radius: 10px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
overflow: hidden;
}
.card-header {
padding: 15px;
background-color: #f9f9f9;
border-bottom: 1px solid #eee;
}
.card-nickname {
font-size: 18px;
font-weight: bold;
color: #8B4513;
margin: 0;
}
.card-avatar {
width: 60px;
height: 60px;
border-radius: 50%;
object-fit: cover;
margin-right: 10px;
vertical-align: middle;
}
.card-content {
padding: 15px;
}
.card-dynamic {
margin-bottom: 15px;
}
.card-location {
color: #666;
font-size: 14px;
margin-bottom: 15px;
}
.card-image {
width: 100%;
height: 200px;
object-fit: cover;
border-radius: 5px;
margin-bottom: 15px;
}
.card-interaction {
margin-top: 15px;
}
.interaction-item {
margin-bottom: 10px;
padding-left: 10px;
border-left: 3px solid #8B4513;
}
.interaction-author {
font-weight: bold;
}
.card-notes {
margin-top: 15px;
padding: 10px;
background-color: #f9f9f9;
border-radius: 5px;
font-style: italic;
}
.admin-panel {
background-color: white;
border-radius: 10px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
padding: 20px;
}
.form-group {
margin-bottom: 15px;
}
label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
input, textarea, select {
width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
}
textarea {
height: 100px;
}
.button-group {
display: flex;
gap: 10px;
margin-top: 20px;
}
button {
padding: 10px 15px;
background-color: #8B4513;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background-color: #6e3500;
}
.edit-buttons {
display: flex;
gap: 5px;
margin-top: 10px;
}
.edit-btn, .delete-btn {
padding: 5px 10px;
font-size: 14px;
}
.edit-btn {
background-color: #ffc107;
color: #333;
}
.delete-btn {
background-color: #dc3545;
color: white;
}
.hidden {
display: none;
}
</style>
</head>
<body>
<div class="container">
<header>
<h1>李白朋友圈史料卡</h1>
</header>
<div class="tabs">
<button class="tab active" data-tab="view">浏览史料卡</button>
<button class="tab" data-tab="admin">后台管理</button>
</div>
<div id="view" class="content active">
<div class="cards-container" id="cards-container">
<!-- 卡片将通过JavaScript动态生成 -->
</div>
</div>
<div id="admin" class="content">
<div class="admin-panel">
<h2>添加/编辑史料卡</h2>
<form id="card-form">
<input type="hidden" id="edit-id">
<div class="form-group">
<label for="nickname">昵称</label>
<input type="text" id="nickname" required>
</div>
<div class="form-group">
<label for="avatar">头像URL</label>
<input type="text" id="avatar" placeholder="https://example.com/avatar.jpg">
</div>
<div class="form-group">
<label for="dynamic">动态</label>
<textarea id="dynamic" required></textarea>
</div>
<div class="form-group">
<label for="location">定位</label>
<input type="text" id="location">
</div>
<div class="form-group">
<label for="image">配图URL</label>
<input type="text" id="image" placeholder="https://example.com/image.jpg">
</div>
<div class="form-group">
<label for="interaction">互动内容 (每行一个,格式:姓名:内容)</label>
<textarea id="interaction"></textarea>
</div>
<div class="form-group">
<label for="notes">史料备注</label>
<textarea id="notes"></textarea>
</div>
<div class="button-group">
<button type="submit" id="save-btn">保存</button>
<button type="button" id="cancel-btn" class="edit-btn hidden">取消</button>
</div>
</form>
<h2>史料卡列表</h2>
<div id="cards-list">
<!-- 列表将通过JavaScript动态生成 -->
</div>
</div>
</div>
</div>
<script>
// 初始数据
const initialCards = [
{
id: 1,
nickname: "青莲酒剑仙",
avatar: "醉卧云间挥毫图",
dynamic: "📜「岑夫子!丹丘生!将进酒,杯莫停!三百杯不够,今夜再战敬亭山!」",
location: "嵩山颍阳山居·元丹丘家后院",
image: "歪斜的酒坛、泼墨诗稿《将进酒》残页",
interaction: [
{ name: "玉真公主", content: "酒虽好,莫贪杯。明日来观中煮茶论道?" },
{ name: "岑夫子", content: "你写诗倒是痛快,我家的马都被你押去换酒了!😤" },
{ name: "丹丘生", content: "下次炼丹炉旁摆酒局,仙丹配烈酒,长生加倍!" }
],
notes: "李白与岑勋、元丹丘因酒结缘,仕途失意后常聚饮抒怀,《将进酒》即诞生于三人狂饮之夜。诗中\"天生我材必有用\"既是自勉,亦暗含对玉真公主举荐的感激。"
},
{
id: 2,
nickname: "上真·道观在逃公主",
avatar: "手持拂尘倚青松",
dynamic: "🏯「青灯黄卷三十载,今日观中梨花落,忽忆故人诗一句:『若非群玉山头见,会向瑶台月下逢』。」",
location: "敬亭山清虚观",
image: "满树梨花、石案上摊开的李白诗卷",
interaction: [
{ name: "李白", content: "公主仙姿,当入《清平调》续篇!" },
{ name: "王维", content: "新谱一曲《郁轮袍》,盼公主雅赏。" }
],
notes: "玉真公主为唐玄宗胞妹,修道后广交文人,曾向玄宗力荐李白。李白多次为其作诗,赞其\"气韵如仙\",两人以道法为纽带保持精神知己关系,未涉俗世情爱。"
},
{
id: 3,
nickname: "大唐酒局赞助商",
avatar: "手捧金樽仰天笑",
dynamic: "🍶「谁能想到?千年前某夜蹭了顿酒,竟被@青莲酒剑仙 写进诗里名垂青史……这波血赚!」",
location: "鸣皋山隐居草堂",
image: "泛黄的《将进酒》手抄本、墙角空酒坛堆",
interaction: [
{ name: "丹丘生", content: "下次酒钱你出,我负责炼丹醒酒。" },
{ name: "元稹", content: "实名羡慕!求带飞文学史!" }
],
notes: "岑勋出身名门(或附会岑参家族),与李白、元丹丘组成\"贪杯三人组\"。《将进酒》中\"岑夫子,丹丘生\"一句使其意外成为文化符号,生平虽鲜见史载,却因诗不朽。"
},
{
id: 4,
nickname: "炼丹·交友·催酒三栖达人",
avatar: "八卦炉前举药杵",
dynamic: "⚗️「新丹方:朱砂三钱,晨露半盏,佐以@青莲酒剑仙 诗稿灰烬,服之可增诗胆!」",
location: "嵩山炼丹洞",
image: "丹炉紫烟缭绕、李白醉题石壁",
interaction: [
{ name: "李白", content: "丹成之日,速唤我来试药——以酒送服!" },
{ name: "司马承祯", content: "道友跨界创新,道法诗酒两开花🌼" }
],
notes: "元丹丘为李白挚友兼修道导师,二人相识二十余年,李白为其作诗11首远超杜甫。他组局促成《将进酒》,堪称李白\"酒灵感\"背后的男人。"
},
{
id: 5,
nickname: "诗佛·佛系点赞党",
avatar: "竹里馆抚琴剪影",
dynamic: "🎼「新作《辋川集》付梓,诸君可至蓝田别业品茗共赏——@上真·道观在逃公主 特留雅座。」",
location: "辋川别墅",
image: "精装诗集、玉真公主赠的翡翠茶盏",
interaction: [
{ name: "玉真公主", content: "雪日煎茶,静候君至。" },
{ name: "裴迪", content: "摩诘兄雅致,弟已备好松柴煮泉!" }
],
notes: "王维早年受玉真公主提携中举,后因娶妻与其疏远。虽与李白同代且共友,史料未见二人直接交集,疑似因公主\"朋友圈\"微妙避嫌。"
}
];
// 当前卡片数据
let cards = JSON.parse(localStorage.getItem('cards')) || initialCards;
// DOM元素
const viewTab = document.querySelector('.tab[data-tab="view"]');
const adminTab = document.querySelector('.tab[data-tab="admin"]');
const viewContent = document.getElementById('view');
const adminContent = document.getElementById('admin');
const cardsContainer = document.getElementById('cards-container');
const cardForm = document.getElementById('card-form');
const editIdInput = document.getElementById('edit-id');
const nicknameInput = document.getElementById('nickname');
const avatarInput = document.getElementById('avatar');
const dynamicInput = document.getElementById('dynamic');
const locationInput = document.getElementById('location');
const imageInput = document.getElementById('image');
const interactionInput = document.getElementById('interaction');
const notesInput = document.getElementById('notes');
const saveBtn = document.getElementById('save-btn');
const cancelBtn = document.getElementById('cancel-btn');
const cardsList = document.getElementById('cards-list');
// 切换标签页
viewTab.addEventListener('click', () => {
viewTab.classList.add('active');
adminTab.classList.remove('active');
viewContent.classList.add('active');
adminContent.classList.remove('active');
});
adminTab.addEventListener('click', () => {
viewTab.classList.remove('active');
adminTab.classList.add('active');
viewContent.classList.remove('active');
adminContent.classList.add('active');
renderCardsList();
});
// 渲染卡片
function renderCards() {
cardsContainer.innerHTML = '';
cards.forEach(card => {
const cardElement = document.createElement('div');
cardElement.className = 'card';
// 格式化互动内容
let interactionHTML = '';
if (card.interaction && card.interaction.length > 0) {
card.interaction.forEach(item => {
interactionHTML += `
<div class="interaction-item">
<span class="interaction-author">${item.name}</span>: ${item.content}
</div>
`;
});
}
cardElement.innerHTML = `
<div class="card-header">
<h3 class="card-nickname">${card.nickname}</h3>
</div>
<div class="card-content">
<div class="card-dynamic">${card.dynamic}</div>
<div class="card-location">${card.location || ''}</div>
<img src="${card.image || 'https://via.placeholder.com/300x200?text=无图片'}" alt="${card.nickname}" class="card-image">
<div class="card-interaction">
${interactionHTML}
</div>
<div class="card-notes">${card.notes || ''}</div>
</div>
<div class="edit-buttons">
<button class="edit-btn" data-id="${card.id}">编辑</button>
</div>
`;
cardsContainer.appendChild(cardElement);
});
// 添加编辑按钮事件
document.querySelectorAll('.edit-btn').forEach(btn => {
btn.addEventListener('click', (e) => {
const id = parseInt(e.target.getAttribute('data-id'));
editCard(id);
});
});
}
// 渲染卡片列表(用于后台)
function renderCardsList() {
cardsList.innerHTML = '';
cards.forEach(card => {
const cardItem = document.createElement('div');
cardItem.className = 'card';
cardItem.innerHTML = `
<div class="card-header">
<h3 class="card-nickname">${card.nickname}</h3>
</div>
<div class="card-content">
<div class="card-dynamic">${card.dynamic}</div>
</div>
`;
cardsList.appendChild(cardItem);
});
}
// 编辑卡片
function editCard(id) {
const card = cards.find(c => c.id === id);
if (card) {
editIdInput.value = card.id;
nicknameInput.value = card.nickname;
avatarInput.value = card.avatar;
dynamicInput.value = card.dynamic;
locationInput.value = card.location || '';
imageInput.value = card.image || '';
// 格式化互动内容
if (card.interaction && card.interaction.length > 0) {
interactionInput.value = card.interaction.map(item => `${item.name}:${item.content}`).join('\n');
} else {
interactionInput.value = '';
}
notesInput.value = card.notes || '';
saveBtn.textContent = '更新';
cancelBtn.classList.remove('hidden');
}
}
// 保存卡片(新增或更新)
cardForm.addEventListener('submit', (e) => {
e.preventDefault();
const id = editIdInput.value ? parseInt(editIdInput.value) : null;
const newCard = {
nickname: nicknameInput.value,
avatar: avatarInput.value,
dynamic: dynamicInput.value,
location: locationInput.value,
image: imageInput.value,
interaction: interactionInput.value.split('\n').map(line => {
const [name, content] = line.split(':');
return { name: name.trim(), content: content ? content.trim() : '' };
}),
notes: notesInput.value
};
if (id) {
// 更新现有卡片
const index = cards.findIndex(c => c.id === id);
if (index !== -1) {
newCard.id = id;
cards[index] = newCard;
}
} else {
// 添加新卡片
newCard.id = Date.now(); // 使用时间戳作为ID
cards.push(newCard);
}
// 保存到本地存储
localStorage.setItem('cards', JSON.stringify(cards));
// 重置表单
cardForm.reset();
editIdInput.value = '';
saveBtn.textContent = '保存';
cancelBtn.classList.add('hidden');
// 重新渲染卡片
renderCards();
});
// 取消编辑
cancelBtn.addEventListener('click', () => {
cardForm.reset();
editIdInput.value = '';
saveBtn.textContent = '保存';
cancelBtn.classList.add('hidden');
});
// 初始渲染
renderCards();
</script>
</body>
</html>
index.html
index.html