Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
76 changes: 75 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,75 @@
# Notes
# 网页版备忘录应用

这是一个使用Flask框架开发的网页版备忘录应用,支持添加、删除、修改备忘录,并具有优先级排序和完成状态管理功能。

## 功能特点

- ✅ 备忘录包含标题、详情、创建时间和预计完成时间
- ✅ 支持添加、删除、修改备忘录
- ✅ 可查看备忘录详情页面
- ✅ 自动获取创建时的本地时间
- ✅ 支持设置优先级(P0、P1、P2),并按优先级排序
- ✅ 支持标记完成状态,完成和未完成备忘录分组显示
- ✅ 响应式设计,适配不同设备屏幕
- ✅ 现代化UI设计,使用渐变色彩和卡片布局

## 技术栈

- **后端**: Python 3.x + Flask
- **数据库**: SQLite (使用SQLAlchemy ORM)
- **前端**: HTML5 + CSS3 + JavaScript
- **时区处理**: pytz

## 快速开始

### 1. 安装依赖

```bash
pip install -r requirements.txt
```

### 2. 运行应用

```bash
python app.py
```

### 3. 访问应用

在浏览器中打开:http://127.0.0.1:5000

## 项目结构

```
.
├── app.py # Flask应用主文件
├── requirements.txt # 项目依赖
├── templates/ # HTML模板文件夹
│ ├── base.html # 基础模板
│ ├── index.html # 首页 - 备忘录列表
│ ├── add_note.html # 添加备忘录页面
│ ├── view_note.html # 查看备忘录详情页面
│ └── edit_note.html # 编辑备忘录页面
└── README.md # 项目说明文档
```

## 优先级说明

- **P0**: 紧急重要 - 红色标签
- **P1**: 一般重要 - 橙色标签
- **P2**: 不太紧急 - 绿色标签

## 注意事项

1. 应用使用SQLite数据库,数据存储在项目根目录的notes.db文件中
2. 应用默认使用上海时区(Asia/Shanghai),可在app.py中修改local_tz变量
3. 开发环境中debug模式已开启,生产环境部署时请关闭
4. 表单提交时会进行简单的错误处理和消息提示

## 扩展建议

1. 添加用户认证功能,支持多用户使用
2. 添加备忘录搜索和过滤功能
3. 添加导出和导入功能
4. 实现数据备份和恢复功能
5. 集成提醒功能,在截止时间前发送通知
162 changes: 162 additions & 0 deletions app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
from flask import Flask, render_template, request, redirect, url_for, flash
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
import pytz

app = Flask(__name__)
app.config['SECRET_KEY'] = 'your-secret-key'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///notes.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)

# 获取本地时间
local_tz = pytz.timezone('Asia/Shanghai')

def get_local_time():
return datetime.now(local_tz)

# 备忘录模型
class Note(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False)
content = db.Column(db.Text, nullable=False)
created_at = db.Column(db.DateTime, default=get_local_time)
due_time = db.Column(db.DateTime, nullable=True)
priority = db.Column(db.String(2), default='P1') # P0, P1, P2
is_completed = db.Column(db.Boolean, default=False)

def __repr__(self):
return f'<Note {self.title}>'

# 初始化数据库
with app.app_context():
db.create_all()

# 首页 - 显示备忘录列表
@app.route('/')
def index():
# 按优先级和完成状态排序
# 未完成的按优先级排序,已完成的按完成时间排序
completed_notes = Note.query.filter_by(is_completed=True).order_by(Note.created_at.desc()).all()
incomplete_notes = Note.query.filter_by(is_completed=False).order_by(
db.case(
(Note.priority == 'P0', 0),
(Note.priority == 'P1', 1),
(Note.priority == 'P2', 2),
else_=3
)
).all()

return render_template('index.html', incomplete_notes=incomplete_notes, completed_notes=completed_notes)

# 添加备忘录
@app.route('/add', methods=['GET', 'POST'])
def add_note():
if request.method == 'POST':
title = request.form['title']
content = request.form['content']
priority = request.form['priority']

# 处理预计完成时间
due_time_str = request.form['due_time']
due_time = None
if due_time_str:
try:
due_time = datetime.strptime(due_time_str, '%Y-%m-%dT%H:%M')
due_time = local_tz.localize(due_time)
except ValueError:
flash('预计完成时间格式不正确')
return redirect(url_for('add_note'))

new_note = Note(
title=title,
content=content,
due_time=due_time,
priority=priority
)

try:
db.session.add(new_note)
db.session.commit()
flash('备忘录添加成功!')
return redirect(url_for('index'))
except Exception as e:
db.session.rollback()
flash(f'添加备忘录失败: {str(e)}')

return render_template('add_note.html')

# 查看备忘录详情
@app.route('/note/<int:note_id>')
def view_note(note_id):
note = Note.query.get_or_404(note_id)
return render_template('view_note.html', note=note)

# 编辑备忘录
@app.route('/edit/<int:note_id>', methods=['GET', 'POST'])
def edit_note(note_id):
note = Note.query.get_or_404(note_id)

if request.method == 'POST':
note.title = request.form['title']
note.content = request.form['content']
note.priority = request.form['priority']
note.is_completed = 'is_completed' in request.form

# 处理预计完成时间
due_time_str = request.form['due_time']
if due_time_str:
try:
due_time = datetime.strptime(due_time_str, '%Y-%m-%dT%H:%M')
note.due_time = local_tz.localize(due_time)
except ValueError:
flash('预计完成时间格式不正确')
return redirect(url_for('edit_note', note_id=note_id))
else:
note.due_time = None

try:
db.session.commit()
flash('备忘录更新成功!')
return redirect(url_for('view_note', note_id=note_id))
except Exception as e:
db.session.rollback()
flash(f'更新备忘录失败: {str(e)}')

# 为表单准备时间格式
due_time_formatted = note.due_time.strftime('%Y-%m-%dT%H:%M') if note.due_time else ''

return render_template('edit_note.html', note=note, due_time_formatted=due_time_formatted)

# 删除备忘录
@app.route('/delete/<int:note_id>')
def delete_note(note_id):
note = Note.query.get_or_404(note_id)

try:
db.session.delete(note)
db.session.commit()
flash('备忘录删除成功!')
except Exception as e:
db.session.rollback()
flash(f'删除备忘录失败: {str(e)}')

return redirect(url_for('index'))

# 标记备忘录完成状态
@app.route('/toggle_completed/<int:note_id>')
def toggle_completed(note_id):
note = Note.query.get_or_404(note_id)
note.is_completed = not note.is_completed

try:
db.session.commit()
except Exception as e:
db.session.rollback()
flash(f'更新状态失败: {str(e)}')

return redirect(url_for('index'))

if __name__ == '__main__':
app.run(debug=True)
Binary file added instance/notes.db
Binary file not shown.
3 changes: 3 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
flask==3.0.0
flask-sqlalchemy==3.1.1
pytz==2023.3.post1
45 changes: 45 additions & 0 deletions templates/add_note.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{% extends 'base.html' %}

{% block content %}
<div class="card" style="max-width: 800px; margin: 0 auto;">
<h2 style="margin-bottom: 1.5rem; color: #2c3e50;">添加新备忘录</h2>

<form method="POST">
<div class="form-group">
<label for="title" class="form-label">标题 *</label>
<input type="text" id="title" name="title" class="form-control" required placeholder="请输入备忘录标题">
</div>

<div class="form-group">
<label for="content" class="form-label">详情 *</label>
<textarea id="content" name="content" class="form-control" required placeholder="请输入备忘录详情"></textarea>
</div>

<div class="form-group">
<label for="priority" class="form-label">优先级 *</label>
<select id="priority" name="priority" class="form-control" required>
<option value="P0">P0 - 紧急重要</option>
<option value="P1" selected>P1 - 一般重要</option>
<option value="P2">P2 - 不太紧急</option>
</select>
</div>

<div class="form-group">
<label for="due_time" class="form-label">预计完成时间 (可选)</label>
<input type="datetime-local" id="due_time" name="due_time" class="form-control">
<small style="color: #666; display: block; margin-top: 0.5rem;">
设置备忘录的预计完成时间,留空表示不设置截止时间
</small>
</div>

<div style="display: flex; gap: 1rem; margin-top: 2rem;">
<button type="submit" class="btn btn-primary" style="flex: 1;">
保存备忘录
</button>
<a href="{{ url_for('index') }}" class="btn btn-secondary">
取消
</a>
</div>
</form>
</div>
{% endblock %}
Loading