智联笔记项目——251022登录注册、后端管理及内容类型处理优化

news/2025/10/22 18:53:25/文章来源:https://www.cnblogs.com/yuzuruandpupu/p/19158741

登录注册、后端管理及内容类型处理优化
在笔记系统的迭代中,基于原有代码,新增了登录注册功能、后端管理模块,并解决了 Markdown 与富文本内容混淆的问题。
本文将详细介绍这些功能的实现思路与代码修改细节,适合记录系统迭代过程。

功能背景与核心目标
原有系统局限
此前的系统(基于 share (4)、index (4)、app (4))存在以下关键问题:

  1. 无用户认证机制,所有用户共用同一权限,存在数据安全隐患
  2. 缺乏后端管理能力,无法对笔记、用户进行批量管理
  3. Markdown 与富文本内容渲染逻辑混乱(如富文本含 HTML 标签被误解析为 Markdown,或 Markdown 语法未正确转换)

一、登录注册功能实现

1. 后端用户模型与认证逻辑

数据模型修改
原有app中无用户模型,本次新增User表及认证相关字段:

点击查看代码
新增代码(app.py)
from flask_login import UserMixin
from werkzeug.security import generate_password_hash, check_password_hash# 原有app中仅包含Note、ShareLink模型,新增User模型
class User(UserMixin, db.Model):__tablename__ = 'user'id = db.Column(db.Integer, primary_key=True)username = db.Column(db.String(50), unique=True, nullable=False)  # 用户名password_hash = db.Column(db.String(128), nullable=False)  # 密码哈希email = db.Column(db.String(100), unique=True, nullable=False)role = db.Column(db.String(20), default='user')  # 角色:user/admincreated_at = db.Column(db.DateTime, default=datetime.now)# 密码加密存储def set_password(self, password):self.password_hash = generate_password_hash(password)# 密码验证def check_password(self, password):return check_password_hash(self.password_hash, password)# 关联用户与笔记(修改Note模型,app(4)中原Note无用户关联)
class Note(db.Model):__tablename__ = 'note'# ...原有字段(id、title、content、type等)user_id = db.Column(db.Integer, db.ForeignKey('user.id', ondelete="CASCADE"), nullable=False)  # 新增:关联用户user = db.relationship('User', backref='notes')  

新增:用户的笔记列表
认证接口实现
新增注册、登录、登出接口,基于 Flask-Login 管理用户会话:

点击查看代码
新增代码(app.py)
from flask_login import LoginManager, login_user, login_required, logout_user, current_user# 初始化登录管理器
login_manager = LoginManager(app)
login_manager.login_view = 'login'@login_manager.user_loader
def load_user(user_id):return User.query.get(int(user_id))# 注册接口
@app.route('/api/register', methods=['POST'])
def register():data = request.jsonusername = data.get('username')password = data.get('email')email = data.get('email')if User.query.filter_by(username=username).first():return jsonify({'error': '用户名已存在'}), 400user = User(username=username, email=email)user.set_password(password)db.session.add(user)db.session.commit()return jsonify({'message': '注册成功'}), 201# 登录接口
@app.route('/api/login', methods=['POST'])
def login():data = request.jsonuser = User.query.filter_by(username=data.get('username')).first()if not user or not user.check_password(data.get('password')):return jsonify({'error': '用户名或密码错误'}), 401login_user(user, remember=data.get('remember', False))  # 记住登录状态return jsonify({'message': '登录成功','user': {'id': user.id,'username': user.username,'role': user.role}})# 登出接口
@app.route('/api/logout', methods=['POST'])
@login_required
def logout():logout_user()return jsonify({'message': '登出成功'})

2. 前端登录注册页面

原有 index无用户界面,新增登录 / 注册弹窗及路由控制:

点击查看代码
<!-- 新增登录弹窗(index.html) -->
<div id="login-modal" class="modal"><div class="modal-content"><span class="close" data-modal="login-modal">&times;</span><h3>用户登录</h3><form id="login-form"><input type="text" name="username" placeholder="用户名" required><input type="password" name="password" placeholder="密码" required><label><input type="checkbox" name="remember"> 记住我</label><button type="submit">登录</button><p>还没有账号?<a href="#" data-toggle-modal="register-modal">注册</a></p></form></div>
</div><!-- 新增注册弹窗(index.html) -->
<div id="register-modal" class="modal"><div class="modal-content"><span class="close" data-modal="register-modal">&times;</span><h3>用户注册</h3><form id="register-form"><input type="text" name="username" placeholder="用户名" required><input type="email" name="email" placeholder="邮箱" required><input type="password" name="password" placeholder="密码" required><button type="submit">注册</button></form></div>
</div>

前端交互逻辑(处理表单提交与会话管理):

点击查看代码
// 登录表单提交(index.html)
document.getElementById('login-form').addEventListener('submit', async (e) => {e.preventDefault();const formData = new FormData(e.target);const data = Object.fromEntries(formData.entries());try {const res = await fetch('/api/login', {method: 'POST',headers: { 'Content-Type': 'application/json' },body: JSON.stringify(data)});if (!res.ok) throw new Error('登录失败');const result = await res.json();// 保存用户信息到本地存储localStorage.setItem('user', JSON.stringify(result.user));// 刷新页面或跳转至首页window.location.reload();} catch (err) {alert(err.message);}
});

二、后端管理模块实现
1. 管理员权限控制
基于用户角色(role=admin)限制管理接口访问:

点击查看代码
# 新增代码(app.py)
from functools import wraps
from flask import abort# 管理员权限装饰器
def admin_required(f):@wraps(f)@login_requireddef decorated_function(*args, **kwargs):if current_user.role != 'admin':abort(403, description='无管理员权限')return f(*args, **kwargs)return decorated_function

2. 管理接口实现(笔记 / 用户管理)

点击查看代码
# 管理员获取所有用户(app.py)
@app.route('/api/admin/users')
@admin_required
def get_all_users():users = User.query.all()return jsonify([{'id': u.id,'username': u.username,'email': u.email,'role': u.role,'created_at': u.created_at.isoformat()} for u in users])# 管理员删除笔记(app.py)
@app.route('/api/admin/notes/<int:note_id>', methods=['DELETE'])
@admin_required
def delete_note_admin(note_id):note = Note.query.get_or_404(note_id)db.session.delete(note)db.session.commit()return jsonify({'message': '笔记已删除'})

3. 管理页面前端实现

新增admin.html页面,仅管理员可见:

点击查看代码
<!-- admin.html -->
<!DOCTYPE html>
<html>
<head><title>系统管理</title><!-- 复用index(4)中的基础样式 --><link rel="stylesheet" href="/static/css/base.css">
</head>
<body><div class="admin-container"><h1>系统管理</h1><div class="tabs"><button class="tab-btn active" data-tab="users">用户管理</button><button class="tab-btn" data-tab="notes">笔记管理</button></div><!-- 用户列表 --><div class="tab-content" id="users-tab"><table id="users-table"><thead><tr><th>ID</th><th>用户名</th><th>邮箱</th><th>角色</th><th>操作</th></tr></thead><tbody></tbody></table></div><!-- 笔记列表 --><div class="tab-content" id="notes-tab" style="display:none;"><table id="notes-table"><thead><tr><th>ID</th><th>标题</th><th>作者</th><th>类型</th><th>操作</th></tr></thead><tbody></tbody></table></div></div><script>// 加载用户列表async function loadUsers() {const res = await fetch('/api/admin/users', {headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` }});const users = await res.json();// 渲染表格...}// 页面加载时执行document.addEventListener('DOMContentLoaded', () => {// 验证管理员权限(前端判断)const user = JSON.parse(localStorage.getItem('user'));if (!user || user.role !== 'admin') {window.location.href = '/';}loadUsers();});</script>
</body>
</html>

三、Markdown 与富文本混淆问题处理
1. 问题分析
原有 share (4) 和 app (4) 中,笔记内容渲染存在两个问题:

  • 富文本包含的 HTML 标签被当作普通文本显示
  • Markdown 语法(如# 标题)未转换为 HTML,直接显示原始字符

2. 解决方案实现

后端类型标识强化
在app原有Note.type字段基础上,增加创建 / 编辑时的类型校验:

点击查看代码
# 修改代码(app.py,基于原来代码的Note模型)
@app.route('/api/notes', methods=['POST'])
@login_required
def create_note():data = request.jsonnote_type = data.get('type', 'richtext')# 校验类型合法性(仅允许richtext/markdown)if note_type not in ['richtext', 'markdown']:return jsonify({'error': '无效的笔记类型'}), 400note = Note(title=data.get('title'),content=data.get('content'),type=note_type,  # 明确存储类型user_id=current_user.id)db.session.add(note)db.session.commit()return jsonify({'id': note.id}), 201

前端渲染逻辑优化
在 share (4) 的分享详情页和笔记编辑页,根据类型切换渲染方式:

点击查看代码

<!-- 分享详情页渲染优化(share_detail.html,基于share(4)扩展) -->
<div class="note-content">{% if note.type == 'richtext' %}<!-- 富文本:保留HTML格式 -->{{ note.content|safe }}{% else %}<!-- Markdown:转换为HTML并高亮代码 -->{{ note.content|markdown }}{% endif %}
</div><!-- 编辑页编辑器切换(index.html) -->
<select id="note-type" onchange="switchEditor(this.value)"><option value="richtext">富文本</option><option value="markdown">Markdown</option>
</select><div id="richtext-editor" style="display:block;"><!-- 富文本编辑器(如TinyMCE) --><textarea id="richtext-content"></textarea>
</div><div id="markdown-editor" style="display:none;"><!-- Markdown编辑器(如SimpleMDE) --><textarea id="markdown-content"></textarea>
</div><script>// 切换编辑器显示function switchEditor(type) {document.getElementById('richtext-editor').style.display = type === 'richtext' ? 'block' : 'none';document.getElementById('markdown-editor').style.display = type === 'markdown' ? 'block' : 'none';}
</script>

功能效果与总结
核心功能效果

  • 登录注册:用户可创建账号并登录,系统基于用户身份隔离数据
  • 后端管理:管理员可查看所有用户 / 笔记,执行删除等操作,提升系统可控性
  • 内容渲染:富文本保留格式、Markdown 正确转换,解决此前混淆问题

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/943650.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JavaScript formatter插件的使用

第一步:在浏览器中发送请求 第二步:在fiddler中,右击“请求内容类型”,在弹出的菜单中单击“Search this column...”,在弹出的对话框中输入“JavaScript”单击“OK” 第三步:在左侧的“会话列表”中找到需要的数…

完整教程:基于WebAssembly的STEP文件3D在线查看器实现详解

完整教程:基于WebAssembly的STEP文件3D在线查看器实现详解pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consol…

20232407 2025-2026-1 《网络与系统攻防技术》 实验二实验报告

1.实验内容实验目标(1)使用netcat获取主机操作Shell,cron启动某项任务(任务自定)PS:cron是linux下用来周期性的执行某种任务或等待处理某些事件的一个守护进程 (2)使用socat获取主机操作Shell, 任务计划启动 (3)使…

uniapp+<script setup lang=“ts“>解析后端返回的图片流并将二维码展示在页面中 - 指南

uniapp+<script setup lang=“ts“>解析后端返回的图片流并将二维码展示在页面中 - 指南2025-10-22 18:44 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !importan…

10.21 CSP-S模拟36 改题记录

HZOJ 写在前面 大概就是切不了任何一道题,大概就是T4改了一辈子。大概就是个人感觉T2严格简单于T1,T3严格简单于T4。感觉好久没有模拟赛改完4道题了。时间貌似不多了,那还是速战速决吧。《Shopper》 아직도 난 我现…

20232406 2025-2026-1 《网络与系统攻防技术》实验二实验报告

一、实验内容及问题回答 1.1实验内容: (1)使用netcat获取主机操作Shell,cron启动。 (2)使用socat获取主机操作Shell, 任务计划启动。 (3)使用MSF meterpreter(或其他软件)生成可执行文件,利用ncat或socat传送到主…

程序员必备!5款小白也能秒上手的AI编程工具

解放双手,让代码自动生成 在传统的开发过程中,开发者常常陷入“想法与代码实现”的拉锯战:脑海中构思的交互效果,需通过逐行编写代码才能落地,调试、优化、兼容性测试……流程冗长且易偏离初衷。随着AI技术的快速…

Securing Your DevOps Pipelines -1

Securing Your DevOps PipelinesBackground on DevOps Security in DevOps or DevSecOps DevSecOps Tools Setting up a DevSecOps Pipeline Final Security ChecksBackground on DevOps 1.1 Understand where DevOps …

低代码软件开发平台介绍

一、低代码市场产品类型 1. 可视化编程 代表产品:OutSystems、牛刀、iVX等 核心特征:通过可视化操作生成代码,本质上是新一代的编程IDE 2. 表单驱动 代表产品:宜搭、氚云、简道云、轻流等 核心特征:以表单、流程、…

接口重试的7种常用方案! - 指南

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

这3种底层思维就是新老班主任的最大区别:不是经验,而

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

windows局域网,能够使用IP打开共享但无法通过机器名打开(0x80070035)

windows局域网,能够使用IP打开共享但无法通过机器名打开(0x80070035)在客户机上操作 组策略管理器-计算机配置-管理模板-网络-Lanman工作站 启用“启用不安全的来宾登录”骑着母猪去打猎的备忘录,如有侵权请联系本…

笔记本 copilot按键 PowerToys映射

有时候笔记本电脑重启后就不管用了,需要进到powertoys设置里边重新设置一下按键才管用

实用指南:86-python电网可视化项目-6

实用指南:86-python电网可视化项目-6pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Mona…

详细介绍:3.5mm耳机插座技术全解析:从镀层工艺到阻抗稳定性测试

详细介绍:3.5mm耳机插座技术全解析:从镀层工艺到阻抗稳定性测试pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "…

通过电脑调试 Android/iOS 手机端网页

通过电脑调试 Android/iOS 手机端网页教程1. Android 手机端需要先安装 Chrome 浏览器。 手机端需要开启 USB 调试功能。具体方法可以搜索,以小米手机为例,在【设置】【我的设备】【全部参数与信息】,连续点击【OS版…

java数据类型和转义字符

java数据类型和转义字符int i=0b10;//2进制0bint i2=010;//八进制0int i3=0x10;//十六进制0xfloat f=0.1f;double d=0.1;System.out.println(d);System.out.println(i2);System.out.println(i3);银行业务:BigDecimal数…

CMS垃圾回收器详解

CMS垃圾回收器详解🔴 CMS收集器概述 #JVM/垃圾回收 🔴 CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器,采用标记清除算法,实现了垃圾回收与用户线程的并发执行。 🟠 CMS核心特点…

网页自动转发替换图片

第一步:打开fiddler,在“工具”栏中单击“Remove all”,清除干扰项 第二步:在需要替换图片的网页发送请求(强制刷新 Ctrl+F5),下方状态栏闪烁,代表fiddler抓包成功 第三步:返回fiddler,在左侧的“会话列表”中…