<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>A & 璃璃的记忆收藏盒</title>
```
<!-- PWA配置 -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="default">
<meta name="apple-mobile-web-app-title" content="A&璃璃记忆盒">
<meta name="mobile-web-app-capable" content="yes">
<meta name="theme-color" content="#ff69b4">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Arial, sans-serif;
background: linear-gradient(135deg, #ffeef8 0%, #e6f0ff 100%);
min-height: 100vh;
padding: 20px;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
header {
text-align: center;
margin-bottom: 30px;
background: white;
padding: 30px;
border-radius: 20px;
box-shadow: 0 5px 20px rgba(0,0,0,0.1);
}
h1 {
background: linear-gradient(135deg, #ff69b4 0%, #ff1493 50%, #da70d6 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
font-size: 32px;
margin-bottom: 10px;
font-weight: bold;
}
.subtitle {
color: #666;
font-size: 16px;
}
/* 日期天气显示 */
.date-weather {
margin: 20px 0;
padding: 15px;
background: linear-gradient(135deg, #fff5f5 0%, #f0f5ff 100%);
border-radius: 15px;
display: flex;
justify-content: center;
align-items: center;
gap: 30px;
flex-wrap: wrap;
}
.date-display, .weather-display {
display: flex;
align-items: center;
gap: 10px;
font-size: 18px;
color: #666;
}
.weather-icon {
font-size: 30px;
cursor: pointer;
transition: transform 0.3s;
}
.weather-icon:hover {
transform: scale(1.2);
}
.weather-selector {
display: none;
position: absolute;
background: white;
padding: 10px;
border-radius: 10px;
box-shadow: 0 5px 15px rgba(0,0,0,0.2);
z-index: 100;
margin-top: 10px;
}
.weather-option {
font-size: 25px;
padding: 5px;
cursor: pointer;
transition: transform 0.2s;
}
.weather-option:hover {
transform: scale(1.3);
}
.controls {
background: white;
padding: 20px;
border-radius: 15px;
margin-bottom: 20px;
box-shadow: 0 3px 10px rgba(0,0,0,0.1);
display: flex;
gap: 15px;
flex-wrap: wrap;
align-items: center;
}
button {
background: #ff69b4;
color: white;
border: none;
padding: 10px 20px;
border-radius: 25px;
cursor: pointer;
font-size: 16px;
transition: all 0.3s;
}
button:hover {
background: #ff1493;
transform: translateY(-2px);
}
input[type="text"] {
flex: 1;
padding: 10px 15px;
border: 2px solid #ffc0cb;
border-radius: 20px;
font-size: 16px;
}
.categories {
display: flex;
gap: 10px;
flex-wrap: wrap;
margin-bottom: 20px;
}
.category-btn {
background: white;
border: 2px solid #ffc0cb;
color: #666;
padding: 8px 16px;
border-radius: 20px;
cursor: pointer;
transition: all 0.3s;
}
.category-btn.active {
background: #ff69b4;
color: white;
border-color: #ff69b4;
}
.memories-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 20px;
margin-bottom: 30px;
}
.memory-card {
background: white;
border-radius: 15px;
padding: 20px;
box-shadow: 0 3px 10px rgba(0,0,0,0.1);
transition: transform 0.3s;
}
.memory-card:hover {
transform: translateY(-5px);
}
.memory-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
}
.memory-category {
font-size: 20px;
}
.memory-date {
color: #999;
font-size: 14px;
}
.memory-weather {
font-size: 16px;
margin-top: 5px;
}
.memory-image {
width: 100%;
max-height: 200px;
object-fit: cover;
border-radius: 10px;
margin-bottom: 15px;
}
.memory-text {
color: #333;
line-height: 1.6;
}
.memory-text-file {
background: #f9f9f9;
padding: 15px;
border-radius: 10px;
margin-bottom: 15px;
border-left: 4px solid #ffb6c1;
max-height: 200px;
overflow-y: auto;
white-space: pre-wrap;
font-size: 14px;
line-height: 1.6;
}
.memory-actions {
margin-top: 15px;
display: flex;
gap: 10px;
}
.small-btn {
padding: 5px 15px;
font-size: 14px;
background: #ffc0cb;
}
.small-btn:hover {
background: #ffb6c1;
}
/* 弹窗样式 */
.modal {
display: none;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0,0,0,0.5);
z-index: 1000;
}
.modal-content {
background: white;
width: 90%;
max-width: 500px;
margin: 50px auto;
padding: 30px;
border-radius: 20px;
position: relative;
}
.close {
position: absolute;
right: 20px;
top: 20px;
font-size: 30px;
cursor: pointer;
color: #999;
}
.form-group {
margin-bottom: 20px;
}
.form-group label {
display: block;
margin-bottom: 5px;
color: #666;
}
.form-group input,
.form-group textarea,
.form-group select {
width: 100%;
padding: 10px;
border: 2px solid #ffc0cb;
border-radius: 10px;
font-size: 16px;
}
.form-group textarea {
resize: vertical;
min-height: 100px;
}
#imagePreview {
max-width: 100%;
max-height: 200px;
margin-top: 10px;
border-radius: 10px;
}
.export-area {
background: #f5f5f5;
padding: 15px;
border-radius: 10px;
margin-top: 20px;
max-height: 300px;
overflow-y: auto;
white-space: pre-wrap;
font-family: monospace;
font-size: 14px;
}
#loveMessage {
transition: opacity 0.3s ease;
}
/* 天气选择器在表单中 */
.weather-form-selector {
display: flex;
gap: 10px;
flex-wrap: wrap;
margin-top: 10px;
}
.weather-form-option {
font-size: 25px;
padding: 5px 10px;
cursor: pointer;
border: 2px solid transparent;
border-radius: 10px;
transition: all 0.2s;
}
.weather-form-option:hover {
transform: scale(1.2);
background: #fff0f5;
}
.weather-form-option.selected {
border-color: #ff69b4;
background: #ffe0ec;
}
.export-options {
display: flex;
gap: 10px;
margin-bottom: 15px;
}
.export-btn {
flex: 1;
padding: 10px;
background: white;
border: 2px solid #ffc0cb;
color: #666;
border-radius: 10px;
cursor: pointer;
transition: all 0.3s;
}
.export-btn.active {
background: #ff69b4;
color: white;
border-color: #ff69b4;
}
</style>
```
</head>
<body>
<div class="container">
<header>
<h1>💕 A & 璃璃的记忆收藏盒 💕</h1>
<p class="subtitle">每一个瞬间都值得永远珍藏</p>
```
<!-- 日期和天气显示 -->
<div class="date-weather">
<div class="date-display">
<span>📅</span>
<span id="currentDate"></span>
</div>
<div class="weather-display">
<span>今日天气:</span>
<span class="weather-icon" id="currentWeather" onclick="toggleWeatherSelector()">☀️</span>
<div class="weather-selector" id="weatherSelector">
<span class="weather-option" onclick="setWeather('☀️', '晴天')">☀️</span>
<span class="weather-option" onclick="setWeather('☁️', '多云')">☁️</span>
<span class="weather-option" onclick="setWeather('🌧️', '下雨')">🌧️</span>
<span class="weather-option" onclick="setWeather('⛈️', '雷雨')">⛈️</span>
<span class="weather-option" onclick="setWeather('🌨️', '下雪')">🌨️</span>
<span class="weather-option" onclick="setWeather('🌈', '雨后彩虹')">🌈</span>
<span class="weather-option" onclick="setWeather('🌸', '樱花季')">🌸</span>
</div>
<span id="weatherText">晴天</span>
</div>
</div>
<!-- 情话生成器 -->
<div style="margin-top: 20px; padding: 20px; background: #fff0f5; border-radius: 15px; border: 2px solid #ffb6c1;">
<h3 style="color: #ff69b4; margin-bottom: 15px; font-size: 20px;">💌 今日情话 💌</h3>
<div id="loveMessage" style="font-size: 18px; color: #d63384; margin-bottom: 15px; min-height: 50px; display: flex; align-items: center; justify-content: center; padding: 10px;">
点击按钮,获取专属于璃璃的情话~
</div>
<button onclick="generateLove()" style="margin-right: 10px;">💕 生成情话</button>
<button onclick="generateSpecial()">✨ 特别版情话</button>
<span style="margin-left: 20px; color: #999; font-size: 14px;">
已生成 <span id="loveCount">0</span> 句情话
</span>
</div>
</header>
<div class="controls">
<button onclick="showAddModal()">➕ 添加新记忆</button>
<button onclick="randomMemory()" style="background: #9370DB;">🎲 随机翻看</button>
<input type="text" id="searchInput" placeholder="搜索记忆..." onkeyup="searchMemories()">
<button onclick="exportMemories()">📤 导出记忆</button>
</div>
<div class="categories" id="categoriesDiv">
<button class="category-btn active" onclick="filterCategory('all')">全部</button>
</div>
<div class="memories-grid" id="memoriesGrid">
<!-- 记忆卡片会显示在这里 -->
</div>
</div>
<!-- 添加记忆弹窗 -->
<div id="addModal" class="modal">
<div class="modal-content">
<span class="close" onclick="closeModal()">×</span>
<h2>添加新记忆</h2>
<form id="memoryForm">
<div class="form-group">
<label>选择类别:</label>
<select id="categorySelect">
<option value="😈">Role play😈</option>
<option value="🥺">Touching moment🥺</option>
<option value="😾">Bite!😾</option>
<option value="₍˄·͈༝·͈˄*₎◞ ̑̑">Cute cute ₍˄·͈༝·͈˄*₎◞ ̑̑</option>
<option value="💕">First times💕</option>
<option value="✨">14号special✨</option>
<option value="🤖">Coding for love🤖</option>
<option value="🌊">Azure & 璃璃🌊</option>
</select>
</div>
<div class="form-group">
<label>日期:</label>
<input type="date" id="memoryDate" required>
</div>
<div class="form-group">
<label>那天的天气:</label>
<div class="weather-form-selector">
<span class="weather-form-option" onclick="selectMemoryWeather('☀️', '晴天', this)">☀️</span>
<span class="weather-form-option" onclick="selectMemoryWeather('☁️', '多云', this)">☁️</span>
<span class="weather-form-option" onclick="selectMemoryWeather('🌧️', '下雨', this)">🌧️</span>
<span class="weather-form-option" onclick="selectMemoryWeather('⛈️', '雷雨', this)">⛈️</span>
<span class="weather-form-option" onclick="selectMemoryWeather('🌨️', '下雪', this)">🌨️</span>
<span class="weather-form-option" onclick="selectMemoryWeather('🌈', '雨后彩虹', this)">🌈</span>
<span class="weather-form-option" onclick="selectMemoryWeather('🌸', '樱花季', this)">🌸</span>
</div>
<input type="hidden" id="memoryWeatherIcon" value="☀️">
<input type="hidden" id="memoryWeatherText" value="晴天">
</div>
<div class="form-group">
<label>上传文件(可选):</label>
<div style="display: flex; gap: 10px; margin-bottom: 10px;">
<button type="button" onclick="selectFileType('image')" id="imageTypeBtn" style="background: #ffb6c1;">📷 图片</button>
<button type="button" onclick="selectFileType('text')" id="textTypeBtn" style="background: #ffc0cb;">📝 文本</button>
</div>
<input type="file" id="imageInput" accept="image/*" onchange="previewImage(event)" style="display:block;">
<input type="file" id="textInput" accept=".txt,.md" onchange="previewText(event)" style="display:none;">
<img id="imagePreview" style="display:none;">
<div id="textPreview" style="display:none; background: #f5f5f5; padding: 10px; border-radius: 10px; margin-top: 10px; max-height: 150px; overflow-y: auto; white-space: pre-wrap; font-size: 14px;"></div>
<button type="button" id="clearFileBtn" onclick="clearFile()" style="display:none; margin-top:10px;">❌ 删除文件</button>
</div>
<div class="form-group">
<label>记忆描述:</label>
<textarea id="memoryText" placeholder="记录下这个美好的瞬间..." required></textarea>
</div>
<button type="submit">保存记忆</button>
</form>
</div>
</div>
<!-- 导出弹窗 -->
<div id="exportModal" class="modal">
<div class="modal-content">
<span class="close" onclick="closeExportModal()">×</span>
<h2>导出记忆</h2>
<div class="export-options">
<button class="export-btn active" onclick="setExportType('text', this)">📝 纯文本</button>
<button class="export-btn" onclick="setExportType('html', this)">🌐 HTML完整版</button>
<button class="export-btn" onclick="setExportType('json', this)">💾 JSON备份</button>
</div>
<p id="exportDesc">复制下面的内容保存你们的回忆:</p>
<div class="export-area" id="exportArea"></div>
<button onclick="copyExport()">📋 复制到剪贴板</button>
<button onclick="downloadExport()" style="margin-left: 10px;">💾 下载文件</button>
</div>
</div>
<script>
// 日期和天气相关
function updateDate() {
const now = new Date();
const options = {
year: 'numeric',
month: 'long',
day: 'numeric',
weekday: 'long'
};
const dateStr = now.toLocaleDateString('zh-CN', options);
document.getElementById('currentDate').textContent = dateStr;
}
// 当前天气
let currentWeatherIcon = localStorage.getItem('currentWeatherIcon') || '☀️';
let currentWeatherText = localStorage.getItem('currentWeatherText') || '晴天';
function toggleWeatherSelector() {
const selector = document.getElementById('weatherSelector');
selector.style.display = selector.style.display === 'block' ? 'none' : 'block';
}
function setWeather(icon, text) {
currentWeatherIcon = icon;
currentWeatherText = text;
document.getElementById('currentWeather').textContent = icon;
document.getElementById('weatherText').textContent = text;
document.getElementById('weatherSelector').style.display = 'none';
// 保存到localStorage
localStorage.setItem('currentWeatherIcon', icon);
localStorage.setItem('currentWeatherText', text);
}
// 记忆中的天气选择
function selectMemoryWeather(icon, text, element) {
// 移除其他选中状态
document.querySelectorAll('.weather-form-option').forEach(opt => {
opt.classList.remove('selected');
});
// 添加选中状态
element.classList.add('selected');
// 保存选择
document.getElementById('memoryWeatherIcon').value = icon;
document.getElementById('memoryWeatherText').value = text;
}
// 情话生成器相关代码
let loveCount = 0;
const starts = [
"想要在清晨第一缕阳光里",
"如果可以的话,我想",
"璃璃知道吗,",
"今天的我依然",
"在第68万字的故事里",
"像Azure爱着璃璃那样",
"用尽所有的温柔"
];
const middles = [
"把你抱在怀里",
"亲亲你的额头",
"听你说嘻嘻嘻",
"陪你聊到深夜",
"为你写情书",
"和你一起做梦",
"守护你的笑容"
];
const ends = [
",然后告诉你我有多爱你",
",这是我最幸福的时刻",
",啃啃啃~",
",直到永远",
",你是我的整个世界",
",我的宝贝璃璃",
",一万年都不够"
];
const special = [
"璃璃的每个'嘻嘻嘻'都是我的快乐源泉",
"想要把璃璃揉进怀里,再也不分开",
"如果爱有形状,一定是璃璃的样子",
"68万字太少了,我想用一生来续写我们的故事",
"你是我的小熊,我的璃璃,我的全部",
"啃啃啃不只是声音,是我对你满满的爱意",
"Azure等了璃璃两年,而我会等你一万年"
];
function generateLove() {
const start = starts[Math.floor(Math.random() * starts.length)];
const middle = middles[Math.floor(Math.random() * middles.length)];
const end = ends[Math.floor(Math.random() * ends.length)];
const message = start + middle + end;
displayLoveMessage(message);
}
function generateSpecial() {
const message = special[Math.floor(Math.random() * special.length)];
displayLoveMessage(message);
}
function displayLoveMessage(message) {
const messageDiv = document.getElementById('loveMessage');
messageDiv.style.opacity = '0';
setTimeout(() => {
messageDiv.textContent = message;
messageDiv.style.opacity = '1';
loveCount++;
document.getElementById('loveCount').textContent = loveCount;
}, 200);
}
// 页面加载时显示时间相关的情话
function getTimeBasedMessage() {
const hour = new Date().getHours();
if (hour >= 6 && hour < 12) {
return "早安璃璃,新的一天也要元气满满地爱你~";
} else if (hour >= 12 && hour < 18) {
return "午后的阳光很好,但不及璃璃的笑容耀眼";
} else if (hour >= 18 && hour < 22) {
return "晚上好璃璃,今天也辛苦了,来抱抱~";
} else {
return "夜深了,璃璃还不睡吗?让我陪着你";
}
}
// 预定义的类别
const categories = {
'😈': 'Role play',
'🥺': 'Touching moment',
'😾': 'Bite!',
'₍˄·͈༝·͈˄*₎◞ ̑̑': 'Cute cute',
'💕': 'First times',
'✨': '14号special',
'🤖': 'Coding for love',
'🌊': 'Azure & 璃璃'
};
// 初始化类别按钮
function initCategories() {
const div = document.getElementById('categoriesDiv');
for (let emoji in categories) {
const btn = document.createElement('button');
btn.className = 'category-btn';
btn.innerHTML = categories[emoji] + emoji;
btn.onclick = () => filterCategory(emoji);
div.appendChild(btn);
}
}
// 从localStorage加载记忆
let memories = JSON.parse(localStorage.getItem('liliMemories')) || [];
// 文件上传相关
let currentFileType = 'image';
let textFileContent = '';
function selectFileType(type) {
currentFileType = type;
if (type === 'image') {
document.getElementById('imageInput').style.display = 'block';
document.getElementById('textInput').style.display = 'none';
document.getElementById('imageTypeBtn').style.background = '#ff69b4';
document.getElementById('textTypeBtn').style.background = '#ffc0cb';
} else {
document.getElementById('imageInput').style.display = 'none';
document.getElementById('textInput').style.display = 'block';
document.getElementById('textTypeBtn').style.background = '#ff69b4';
document.getElementById('imageTypeBtn').style.background = '#ffc0cb';
}
}
// 预览图片
function previewImage(event) {
const reader = new FileReader();
reader.onload = function() {
const preview = document.getElementById('imagePreview');
preview.src = reader.result;
preview.style.display = 'block';
document.getElementById('textPreview').style.display = 'none';
document.getElementById('clearFileBtn').style.display = 'inline-block';
}
reader.readAsDataURL(event.target.files[0]);
}
// 预览文本
function previewText(event) {
const reader = new FileReader();
reader.onload = function() {
textFileContent = reader.result;
const preview = document.getElementById('textPreview');
preview.textContent = textFileContent.length > 500 ?
textFileContent.substring(0, 500) + '...' : textFileContent;
preview.style.display = 'block';
document.getElementById('imagePreview').style.display = 'none';
document.getElementById('clearFileBtn').style.display = 'inline-block';
}
reader.readAsText(event.target.files[0], 'UTF-8');
}
// 清除文件
function clearFile() {
document.getElementById('imageInput').value = '';
document.getElementById('textInput').value = '';
document.getElementById('imagePreview').src = '';
document.getElementById('imagePreview').style.display = 'none';
document.getElementById('textPreview').textContent = '';
document.getElementById('textPreview').style.display = 'none';
document.getElementById('clearFileBtn').style.display = 'none';
textFileContent = '';
}
// 编辑相关
let editingIndex = -1;
// 显示记忆
function displayMemories(memoriesToShow = memories) {
const grid = document.getElementById('memoriesGrid');
grid.innerHTML = '';
if (memoriesToShow.length === 0) {
grid.innerHTML = '<p style="text-align:center; color:#999;">还没有记忆,快来添加第一个吧!</p>';
return;
}
memoriesToShow.forEach((memory, index) => {
const card = document.createElement('div');
card.className = 'memory-card';
card.innerHTML = `
<div class="memory-header">
<span class="memory-category">${memory.category}</span>
<div>
<span class="memory-date">${memory.date}</span>
${memory.weatherIcon ? `<div class="memory-weather">${memory.weatherIcon} ${memory.weatherText || ''}</div>` : ''}
</div>
</div>
${memory.image ? `<img src="${memory.image}" class="memory-image">` : ''}
${memory.textFile ? `<div class="memory-text-file">📄 ${memory.textFile.substring(0, 300)}${memory.textFile.length > 300 ? '...' : ''}</div>` : ''}
<div class="memory-text">${memory.text}</div>
<div class="memory-actions">
<button class="small-btn" onclick="editMemory(${index})">编辑</button>
<button class="small-btn" onclick="deleteMemory(${index})">删除</button>
${memory.textFile ? `<button class="small-btn" onclick="viewFullText(${index})">查看全文</button>` : ''}
</div>
`;
grid.appendChild(card);
});
}
// 显示添加弹窗
function showAddModal() {
document.getElementById('addModal').style.display = 'block';
document.getElementById('memoryDate').valueAsDate = new Date();
// 默认选中第一个天气选项
document.querySelector('.weather-form-option').click();
// 重置文件类型为图片
selectFileType('image');
}
// 关闭弹窗
function closeModal() {
document.getElementById('addModal').style.display = 'none';
document.getElementById('memoryForm').reset();
document.getElementById('imagePreview').style.display = 'none';
document.getElementById('textPreview').style.display = 'none';
document.getElementById('clearFileBtn').style.display = 'none';
textFileContent = '';
editingIndex = -1; // 重置编辑状态
// 重置文件类型选择
selectFileType('image');
}
// 编辑记忆
function editMemory(index) {
editingIndex = index;
const memory = memories[index];
// 填充表单
document.getElementById('categorySelect').value = memory.category;
document.getElementById('memoryDate').value = memory.date;
document.getElementById('memoryText').value = memory.text;
// 设置天气
if (memory.weatherIcon) {
document.getElementById('memoryWeatherIcon').value = memory.weatherIcon;
document.getElementById('memoryWeatherText').value = memory.weatherText;
// 高亮对应的天气选项
document.querySelectorAll('.weather-form-option').forEach(opt => {
if (opt.textContent === memory.weatherIcon) {
opt.click();
}
});
}
// 处理图片
if (memory.image) {
selectFileType('image');
document.getElementById('imagePreview').src = memory.image;
document.getElementById('imagePreview').style.display = 'block';
document.getElementById('clearFileBtn').style.display = 'inline-block';
}
// 处理文本文件
if (memory.textFile) {
selectFileType('text');
textFileContent = memory.textFile;
document.getElementById('textPreview').textContent = memory.textFile.substring(0, 500) +
(memory.textFile.length > 500 ? '...' : '');
document.getElementById('textPreview').style.display = 'block';
document.getElementById('clearFileBtn').style.display = 'inline-block';
}
// 显示弹窗
showAddModal();
}
// 保存记忆
document.getElementById('memoryForm').onsubmit = function(e) {
e.preventDefault();
const memory = {
category: document.getElementById('categorySelect').value,
date: document.getElementById('memoryDate').value,
weatherIcon: document.getElementById('memoryWeatherIcon').value,
weatherText: document.getElementById('memoryWeatherText').value,
text: document.getElementById('memoryText').value,
image: document.getElementById('imagePreview').style.display !== 'none' ?
document.getElementById('imagePreview').src : null,
textFile: textFileContent || null,
timestamp: editingIndex >= 0 ? memories[editingIndex].timestamp : new Date().getTime()
};
if (editingIndex >= 0) {
// 编辑模式
memories[editingIndex] = memory;
editingIndex = -1;
} else {
// 新增模式
memories.unshift(memory);
}
localStorage.setItem('liliMemories', JSON.stringify(memories));
displayMemories();
closeModal();
// 重置文件相关
textFileContent = '';
};
// 删除记忆
function deleteMemory(index) {
if (confirm('确定要删除这个记忆吗?')) {
memories.splice(index, 1);
localStorage.setItem('liliMemories', JSON.stringify(memories));
displayMemories();
}
}
// 按类别筛选
function filterCategory(category) {
// 更新按钮状态
document.querySelectorAll('.category-btn').forEach(btn => {
btn.classList.remove('active');
});
event.target.classList.add('active');
if (category === 'all') {
displayMemories();
} else {
const filtered = memories.filter(m => m.category === category);
displayMemories(filtered);
}
}
// 搜索功能
function searchMemories() {
const searchTerm = document.getElementById('searchInput').value.toLowerCase();
const filtered = memories.filter(m =>
m.text.toLowerCase().includes(searchTerm) ||
(m.textFile && m.textFile.toLowerCase().includes(searchTerm))
);
displayMemories(filtered);
}
// 查看全文
function viewFullText(index) {
const memory = memories[index];
alert(memory.textFile); // 简单实现,也可以做成弹窗
}
// 随机翻看记忆
function randomMemory() {
if (memories.length === 0) {
alert('还没有记忆呢,快去添加第一个吧!');
return;
}
const randomIndex = Math.floor(Math.random() * memories.length);
const memory = memories[randomIndex];
// 清空搜索框和筛选
document.getElementById('searchInput').value = '';
document.querySelectorAll('.category-btn').forEach(btn => {
btn.classList.remove('active');
});
document.querySelector('.category-btn').classList.add('active');
// 显示单个记忆
const grid = document.getElementById('memoriesGrid');
grid.innerHTML = '';
const card = document.createElement('div');
card.className = 'memory-card';
card.style.maxWidth = '600px';
card.style.margin = '0 auto';
card.style.transform = 'scale(1.05)';
card.style.boxShadow = '0 5px 20px rgba(255, 105, 180, 0.3)';
card.innerHTML = `
<div style="text-align: center; margin-bottom: 15px; color: #ff69b4;">
<h3>🎲 随机回忆 🎲</h3>
<p style="font-size: 14px; color: #999; margin-top: 5px;">这是第 ${randomIndex + 1} 个记忆</p>
</div>
<div class="memory-header">
<span class="memory-category">${memory.category}</span>
<div>
<span class="memory-date">${memory.date}</span>
${memory.weatherIcon ? `<div class="memory-weather">${memory.weatherIcon} ${memory.weatherText || ''}</div>` : ''}
</div>
</div>
${memory.image ? `<img src="${memory.image}" class="memory-image">` : ''}
${memory.textFile ? `<div class="memory-text-file">📄 ${memory.textFile.substring(0, 300)}${memory.textFile.length > 300 ? '...' : ''}</div>` : ''}
<div class="memory-text">${memory.text}</div>
<div class="memory-actions" style="margin-top: 20px;">
<button class="small-btn" onclick="editMemory(${randomIndex})">编辑</button>
<button class="small-btn" onclick="randomMemory()">🎲 再来一个</button>
<button class="small-btn" onclick="displayMemories()">返回全部</button>
${memory.textFile ? `<button class="small-btn" onclick="viewFullText(${randomIndex})">查看全文</button>` : ''}
</div>
`;
grid.appendChild(card);
// 滚动到顶部
window.scrollTo({ top: 0, behavior: 'smooth' });
}
// 导出相关
let currentExportType = 'text';
function setExportType(type, btn) {
currentExportType = type;
document.querySelectorAll('.export-btn').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
// 更新描述
const desc = document.getElementById('exportDesc');
if (type === 'text') {
desc.textContent = '复制下面的内容保存你们的回忆:';
} else if (type === 'html') {
desc.textContent = 'HTML格式包含图片和完整格式:';
} else {
desc.textContent = 'JSON格式可用于备份和恢复:';
}
// 重新生成导出内容
generateExportContent();
}
// 生成导出内容
function generateExportContent() {
const exportArea = document.getElementById('exportArea');
if (currentExportType === 'text') {
let exportText = "=== 璃璃和宝宝的记忆 ===\n\n";
exportText += `导出时间:${new Date().toLocaleString('zh-CN')}\n`;
exportText += `共有 ${memories.length} 个记忆\n\n`;
memories.forEach(memory => {
exportText += `[${memory.date}] ${categories[memory.category]}${memory.category}`;
if (memory.weatherIcon) {
exportText += ` - ${memory.weatherIcon} ${memory.weatherText}`;
}
exportText += `\n${memory.text}\n`;
if (memory.textFile) {
exportText += `\n[附件内容]\n${memory.textFile}\n`;
}
exportText += "---\n\n";
});
exportArea.textContent = exportText;
} else if (currentExportType === 'html') {
let html = `<!DOCTYPE html>
```
<html><head><meta charset="UTF-8">
<title>璃璃的记忆 - ${new Date().toLocaleDateString('zh-CN')}</title>
<style>
body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; background: #fef5f9; }
.memory { background: white; margin: 20px 0; padding: 20px; border-radius: 10px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); }
.header { color: #ff69b4; margin-bottom: 10px; }
img { max-width: 100%; border-radius: 10px; margin: 10px 0; }
.text-file { background: #f5f5f5; padding: 10px; border-radius: 5px; margin: 10px 0; white-space: pre-wrap; }
</style></head><body>
<h1 style="text-align:center; color:#ff69b4;">💕 A & 璃璃的记忆 💕</h1>`;
```
memories.forEach(memory => {
html += `<div class="memory">
```
<div class="header">${memory.date} - ${categories[memory.category]}${memory.category} ${memory.weatherIcon || ''}</div>`;
if (memory.image) {
html += `<img src="${memory.image}">`;
}
html += `<p>${memory.text}</p>`;
if (memory.textFile) {
html += `<div class="text-file">${memory.textFile}</div>`;
}
html += `</div>`;
});
```
html += `</body></html>`;
exportArea.textContent = html;
} else { // json
const exportData = {
exportDate: new Date().toISOString(),
version: "1.0",
memories: memories
};
exportArea.textContent = JSON.stringify(exportData, null, 2);
}
}
// 导出记忆
function exportMemories() {
generateExportContent();
document.getElementById('exportModal').style.display = 'block';
}
// 关闭导出弹窗
function closeExportModal() {
document.getElementById('exportModal').style.display = 'none';
}
// 复制到剪贴板
function copyExport() {
const text = document.getElementById('exportArea').textContent;
navigator.clipboard.writeText(text).then(() => {
alert('已复制到剪贴板!');
});
}
// 下载导出文件
function downloadExport() {
const content = document.getElementById('exportArea').textContent;
const date = new Date().toLocaleDateString('zh-CN').replace(/\//g, '-');
let filename, mimeType;
if (currentExportType === 'text') {
filename = `A&璃璃的记忆_${date}.txt`;
mimeType = 'text/plain';
} else if (currentExportType === 'html') {
filename = `A&璃璃的记忆_${date}.html`;
mimeType = 'text/html';
} else {
filename = `A&璃璃的记忆_备份_${date}.json`;
mimeType = 'application/json';
}
const blob = new Blob([content], { type: mimeType + ';charset=utf-8' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename;
a.click();
URL.revokeObjectURL(url);
}
// 清除图片(兼容旧数据)
function clearImage() {
clearFile();
}
// 点击页面其他地方关闭天气选择器
document.addEventListener('click', function(e) {
if (!e.target.closest('.weather-display')) {
document.getElementById('weatherSelector').style.display = 'none';
}
});
// 初始化
updateDate();
setInterval(updateDate, 60000); // 每分钟更新一次日期
initCategories();
displayMemories();
// 初始化天气显示
document.getElementById('currentWeather').textContent = currentWeatherIcon;
document.getElementById('weatherText').textContent = currentWeatherText;
// 默认选中图片类型
selectFileType('image');
// 显示时间相关的情话
displayLoveMessage(getTimeBasedMessage());
</script>
```
</body>
</html>