131 lines
4.2 KiB
Python
131 lines
4.2 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""ziwei-power Flask 应用 — 磁场管理打卡系统"""
|
||
|
||
import os
|
||
from datetime import timedelta
|
||
from functools import wraps
|
||
from flask import Flask, render_template, request, jsonify, session, redirect, url_for
|
||
from werkzeug.security import generate_password_hash, check_password_hash
|
||
from database import init_db, get_checkin, save_checkin, delete_checkin, get_all_checkins
|
||
|
||
app = Flask(__name__)
|
||
app.secret_key = os.urandom(24)
|
||
|
||
# 会话持久化:30 天
|
||
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=30)
|
||
|
||
# ── 用户库 ────────────────────────────────────────────
|
||
|
||
USERS = {
|
||
'qiukai': {
|
||
'password_hash': generate_password_hash('AiAlex2018$'),
|
||
'name': '凯哥'
|
||
}
|
||
}
|
||
|
||
# ── 登录检查装饰器 ────────────────────────────────────
|
||
|
||
def login_required(f):
|
||
@wraps(f)
|
||
def decorated(*args, **kwargs):
|
||
if not session.get('logged_in'):
|
||
return redirect(url_for('login_page', next=request.path))
|
||
return f(*args, **kwargs)
|
||
return decorated
|
||
|
||
|
||
# ── 登录路由 ──────────────────────────────────────────
|
||
|
||
@app.route('/login', methods=['GET', 'POST'])
|
||
def login_page():
|
||
if request.method == 'POST':
|
||
username = request.form.get('username', '').strip()
|
||
password = request.form.get('password', '')
|
||
remember = request.form.get('remember') == 'on'
|
||
|
||
user = USERS.get(username)
|
||
if user and check_password_hash(user['password_hash'], password):
|
||
session.permanent = remember
|
||
session['logged_in'] = True
|
||
session['username'] = username
|
||
session['display_name'] = user['name']
|
||
next_url = request.args.get('next', '/')
|
||
return jsonify({'ok': True, 'next': next_url})
|
||
else:
|
||
return jsonify({'ok': False, 'error': '账号或密码错误'}), 401
|
||
|
||
# GET:如果已登录直接跳转
|
||
if session.get('logged_in'):
|
||
return redirect(url_for('index'))
|
||
return render_template('login.html')
|
||
|
||
|
||
@app.route('/logout')
|
||
def logout():
|
||
session.clear()
|
||
return redirect(url_for('login_page'))
|
||
|
||
|
||
# ── 主页 ──────────────────────────────────────────────
|
||
|
||
@app.route('/')
|
||
@login_required
|
||
def index():
|
||
return render_template('index.html',
|
||
username=session.get('display_name', session.get('username', '')))
|
||
|
||
|
||
# ── API ──────────────────────────────────────────────
|
||
|
||
@app.route('/api/checkin', methods=['GET'])
|
||
@login_required
|
||
def api_get_checkin():
|
||
date = request.args.get('date', '')
|
||
if not date:
|
||
return jsonify({'ok': False, 'error': '缺少 date 参数'}), 400
|
||
row = get_checkin(date)
|
||
return jsonify({'ok': True, 'data': row})
|
||
|
||
|
||
@app.route('/api/checkin', methods=['POST'])
|
||
@login_required
|
||
def api_save_checkin():
|
||
body = request.get_json(force=True)
|
||
date = body.get('date', '')
|
||
if not date:
|
||
return jsonify({'ok': False, 'error': '缺少 date 字段'}), 400
|
||
data = body.get('data', {})
|
||
save_checkin(date, data)
|
||
return jsonify({'ok': True})
|
||
|
||
|
||
@app.route('/api/checkin/<date>', methods=['DELETE'])
|
||
@login_required
|
||
def api_delete_checkin(date):
|
||
delete_checkin(date)
|
||
return jsonify({'ok': True})
|
||
|
||
|
||
@app.route('/api/history', methods=['GET'])
|
||
@login_required
|
||
def api_history():
|
||
rows = get_all_checkins()
|
||
return jsonify({'ok': True, 'data': rows})
|
||
|
||
|
||
@app.route('/api/user', methods=['GET'])
|
||
@login_required
|
||
def api_user():
|
||
return jsonify({
|
||
'ok': True,
|
||
'username': session.get('username'),
|
||
'display_name': session.get('display_name')
|
||
})
|
||
|
||
|
||
# ── 启动 ──────────────────────────────────────────────
|
||
|
||
if __name__ == '__main__':
|
||
init_db()
|
||
app.run(host='0.0.0.0', port=5053, debug=False)
|