乙巳马年春联生成终端代码实例:用户历史记录本地存储与隐私保护设计

张开发
2026/4/18 23:32:28 15 分钟阅读

分享文章

乙巳马年春联生成终端代码实例:用户历史记录本地存储与隐私保护设计
乙巳马年春联生成终端代码实例用户历史记录本地存储与隐私保护设计1. 引言当传统年俗遇见现代隐私每到新年贴春联是家家户户必不可少的仪式。如今借助AI技术我们动动手指就能生成一副文采斐然、寓意吉祥的专属春联。这听起来很酷但你想过吗你输入的每一个新年愿望词——“如意”、“飞跃”、“五福”——这些充满个人期许的文字在生成春联后去了哪里今天我们就来聊聊一个看似简单却至关重要的功能用户历史记录的本地存储与隐私保护。我们将以“乙巳马年·皇城大门春联生成终端”这个极具视觉冲击力的Web应用为例手把手带你实现一个既能让用户回顾美好祝愿又能确保数据不出用户设备的安全方案。读完本文你将掌握为什么要在浏览器端本地存储用户历史记录。如何使用现代Web APIIndexedDB安全地实现它。怎样在前端优雅地展示和管理这些历史记录。理解这套设计如何从根本上保护用户隐私。2. 为什么选择本地存储隐私保护是第一原则在开始写代码之前我们必须想清楚用户的历史生成记录到底应该存哪里2.1 传统云端存储的隐忧最简单的做法是把用户每次输入的“愿望词”和生成的“春联”都上传到服务器数据库。但这会带来几个问题隐私风险用户的个人愿望与服务器绑定存在潜在的泄露可能。数据负担你需要维护服务器、数据库处理扩容和安全防护。合规成本涉及用户数据存储可能需要考虑数据合规性要求。2.2 本地存储的优势相比之下将数据完全存储在用户的浏览器中本地存储优势明显绝对隐私数据从未离开用户的设备从源头上杜绝了隐私泄露风险。用户对自己的数据拥有完全的控制权。极速体验读取本地数据的速度远超网络请求历史记录的加载和展示可以做到瞬间完成。减轻负载应用服务器无需处理历史数据的存储和查询只专注于AI模型推理这一核心服务架构更简洁成本更低。离线可用即使在没有网络的环境下用户依然可以浏览自己曾经生成过的春联。对于“春联生成”这类轻量级、个人化的应用本地存储是兼顾体验、成本和隐私的最佳选择。3. 技术选型为何是IndexedDB浏览器提供了几种本地存储方案我们简单对比一下存储方案容量数据结构适用场景LocalStorage约5MB键值对字符串存储简单配置、令牌SessionStorage约5MB键值对字符串单标签页会话数据Cookies约4KB键值对字符串身份认证、服务器端状态IndexedDB大量通常250MB对象仓库支持复杂对象结构化数据、大量数据、需要查询结论很明显IndexedDB是我们的首选。容量足够春联文本数据很小但我们要为未来可能存储的图片、更多记录留足空间。结构友好一条历史记录通常包含id、timestamp时间戳、wish愿望词、couplet生成的对联文本等多个字段。IndexedDB可以轻松存储这种JavaScript对象。功能强大支持索引、事务方便我们实现按时间排序、搜索等高级功能。4. 实战构建本地历史记录模块现在让我们进入代码实战环节。我们将为“皇城大门春联生成终端”添加历史记录功能。假设你的前端基于Streamlit但核心的JavaScript逻辑是通用的。4.1 核心数据结构设计首先定义一条历史记录应该是什么样子// 一条历史记录的对象结构 const historyRecordSchema { id: unique_id_123, // 唯一标识可以用时间戳或UUID timestamp: 1739452800000, // 生成时间的时间戳 wish: 如意, // 用户输入的愿望词 couplet: { firstLine: 龙马精神开锦绣, // 上联 secondLine: 春风得意展宏图, // 下联 horizontalScroll: 马到成功 // 横批 } };4.2 初始化IndexedDB数据库我们需要一个函数来打开或创建数据库。// db.js - IndexedDB 封装工具类 class CoupletHistoryDB { constructor(dbName CoupletHistoryDB, version 1) { this.dbName dbName; this.version version; this.storeName history; this.db null; } // 打开或升级数据库 open() { return new Promise((resolve, reject) { const request indexedDB.open(this.dbName, this.version); request.onerror (event) { console.error(IndexedDB 打开失败:, event.target.error); reject(event.target.error); }; request.onsuccess (event) { this.db event.target.result; console.log(IndexedDB 连接成功); resolve(this.db); }; // 仅在首次创建或版本升级时触发 request.onupgradeneeded (event) { const db event.target.result; // 如果对象仓库不存在则创建 if (!db.objectStoreNames.contains(this.storeName)) { // 创建对象仓库指定主键为自增的 id const store db.createObjectStore(this.storeName, { keyPath: id, autoIncrement: true }); // 创建时间戳索引方便按时间倒序查询 store.createIndex(timestamp, timestamp, { unique: false }); console.log(对象仓库 ${this.storeName} 创建成功); } }; }); } // 添加一条记录 async addRecord(wish, couplet) { if (!this.db) await this.open(); return new Promise((resolve, reject) { const transaction this.db.transaction([this.storeName], readwrite); const store transaction.objectStore(this.storeName); const record { timestamp: Date.now(), // 使用当前时间戳 wish: wish, couplet: couplet }; const request store.add(record); request.onsuccess () { console.log(历史记录添加成功); resolve(request.result); // 返回新记录的id }; request.onerror (event) { console.error(添加记录失败:, event.target.error); reject(event.target.error); }; }); } // 获取所有记录按时间倒序 async getAllRecords() { if (!this.db) await this.open(); return new Promise((resolve, reject) { const transaction this.db.transaction([this.storeName], readonly); const store transaction.objectStore(this.storeName); const index store.index(timestamp); // 使用时间戳索引 // 使用游标逆序遍历实现倒序 const request index.openCursor(null, prev); const records []; request.onsuccess (event) { const cursor event.target.result; if (cursor) { records.push(cursor.value); cursor.continue(); } else { // 游标遍历完毕 resolve(records); } }; request.onerror (event) { console.error(获取记录失败:, event.target.error); reject(event.target.error); }; }); } // 根据ID删除一条记录 async deleteRecord(id) { if (!this.db) await this.open(); return new Promise((resolve, reject) { const transaction this.db.transaction([this.storeName], readwrite); const store transaction.objectStore(this.storeName); const request store.delete(id); request.onsuccess () { console.log(记录 ${id} 删除成功); resolve(true); }; request.onerror (event) { console.error(删除记录失败:, event.target.error); reject(event.target.error); }; }); } // 清空所有历史记录 async clearAll() { if (!this.db) await this.open(); return new Promise((resolve, reject) { const transaction this.db.transaction([this.storeName], readwrite); const store transaction.objectStore(this.storeName); const request store.clear(); request.onsuccess () { console.log(所有历史记录已清空); resolve(true); }; request.onerror (event) { console.error(清空记录失败:, event.target.error); reject(event.target.error); }; }); } } // 导出单例实例方便全局使用 export const historyDB new CoupletHistoryDB();4.3 与春联生成流程集成接下来我们需要在用户成功生成春联后自动调用addRecord方法保存记录。// generation.js - 春联生成逻辑 import { historyDB } from ./db.js; async function generateCouplet(wishText) { // 1. 调用后端AI模型生成春联假设返回格式如下 const response await fetch(/api/generate, { method: POST, headers: { Content-Type: application/json }, body: JSON.stringify({ wish: wishText }) }); const result await response.json(); // 假设返回数据结构 const generatedCouplet { firstLine: result.first_line, // 例如龙马精神开锦绣 secondLine: result.second_line, // 例如春风得意展宏图 horizontalScroll: result.horizontal_scroll // 例如马到成功 }; // 2. 将生成结果保存到本地历史数据库 try { const recordId await historyDB.addRecord(wishText, generatedCouplet); console.log(记录已保存ID: ${recordId}); } catch (error) { console.error(保存历史记录失败但春联生成成功:, error); // 这里可以选择优雅降级例如用更简单的localStorage做临时备份 } // 3. 更新UI显示新生成的春联 displayCouplet(generatedCouplet); // 4. 可选刷新历史记录列表 refreshHistoryList(); return generatedCouplet; }4.4 构建历史记录展示界面历史数据存好了我们还需要一个地方让用户查看和管理它们。我们可以在应用侧边栏或底部添加一个“历史宝库”区域。!-- 在Streamlit或你的Web应用HTML中插入以下结构 -- div idhistory-section stylemargin-top: 2rem; padding: 1rem; background: rgba(255, 255, 255, 0.05); border-radius: 8px; h3 stylecolor: #fbc02d; border-bottom: 1px solid #444; padding-bottom: 0.5rem; 历史宝库 /h3 div idhistory-list !-- 历史记录将通过JS动态插入到这里 -- p classempty-tip尚未生成任何春联快去写下你的愿望吧/p /div div stylemargin-top: 1rem; text-align: center; button idclear-history-btn stylebackground: transparent; color: #aaa; border: 1px solid #666; padding: 0.3rem 0.8rem; border-radius: 4px; font-size: 0.9rem; 清空历史 /button /div /div// ui.js - 负责渲染历史记录列表 import { historyDB } from ./db.js; const historyListEl document.getElementById(history-list); const clearHistoryBtn document.getElementById(clear-history-btn); // 渲染单条历史记录 function renderHistoryRecord(record) { const recordEl document.createElement(div); recordEl.className history-record; recordEl.style.cssText padding: 1rem; margin-bottom: 1rem; background: rgba(139, 0, 0, 0.2); border-left: 4px solid #fbc02d; border-radius: 4px; ; const dateStr new Date(record.timestamp).toLocaleString(zh-CN); recordEl.innerHTML div styledisplay: flex; justify-content: space-between; align-items: start; margin-bottom: 0.5rem; div strong stylecolor: #ffcc80;愿望/strong span stylecolor: #fff;${record.wish}/span /div div stylefont-size: 0.85rem; color: #aaa;${dateStr}/div /div div stylecolor: #ffeb3b; font-family: Ma Shan Zheng, serif; line-height: 1.6; div上联${record.couplet.firstLine}/div div下联${record.couplet.secondLine}/div div styletext-align: center; margin-top: 0.5rem;横批${record.couplet.horizontalScroll}/div /div div styletext-align: right; margin-top: 0.5rem; button classdelete-record-btn>// 一个简单的示例生产环境应使用更成熟的库如Web Crypto API function simpleEncrypt(text, key user_specific_salt) { // 这里仅作示意实际应使用AES等加密算法 let result ; for (let i 0; i text.length; i) { result String.fromCharCode(text.charCodeAt(i) ^ key.charCodeAt(i % key.length)); } return btoa(result); // 转为Base64 } function simpleDecrypt(encryptedText, key user_specific_salt) { const text atob(encryptedText); let result ; for (let i 0; i text.length; i) { result String.fromCharCode(text.charCodeAt(i) ^ key.charCodeAt(i % key.length)); } return result; } // 存储时加密愿望词 const recordToSave { timestamp: Date.now(), wish: simpleEncrypt(userWish), // 加密存储 couplet: generatedCouplet };5.2 数据生命周期管理自动清理可以增加逻辑自动删除超过一定时间如一年的旧记录避免数据无限膨胀。导出/导入提供将历史记录导出为JSON文件的功能以及从文件导入恢复的功能方便用户换设备时迁移数据。5.3 清晰的用户告知在应用内合适的位置如“历史宝库”标题旁添加一个简短的提示“温馨提示您的所有生成记录均仅保存在当前设备的浏览器中我们不会收集或上传任何数据。清理浏览器缓存可能导致记录丢失。”6. 总结通过以上步骤我们成功为“乙巳马年春联生成终端”实现了一个完全运行在客户端、尊重用户隐私的历史记录功能。让我们回顾一下关键点理念先行我们选择了本地存储作为技术方案的基石这从根本上确立了“用户数据所有权归用户”的隐私保护立场。技术选型IndexedDB因其大容量和结构化存储能力成为存储历史记录的最佳选择远超LocalStorage。完整实现我们构建了从数据库初始化、数据增删改查到前端界面渲染的完整闭环。代码模块清晰易于集成到现有项目中。体验与隐私兼顾用户可以在“历史宝库”中随时回顾、品味自己曾许下的新年愿望和生成的精美对联同时享有对数据的完全控制权查看、删除、清空。面向未来我们讨论了加密、生命周期管理等进阶话题为更高安全要求的场景提供了思路。这个设计模式不仅适用于春联生成器也可以被广泛应用于任何需要保存用户操作历史、同时又极度重视隐私的轻量级Web应用中例如笔记工具、本地计算器、个人规划应用等。技术最终服务于人。在享受AI带来的便捷与创意时通过精心的设计守护好用户的数据隐私是我们开发者能给予用户的一份珍贵的新年礼物。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。

更多文章