generated from dellevin/template
1.登录验证
2.自动打开默认浏览器
This commit is contained in:
@@ -7,9 +7,9 @@ import sys
|
|||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from flask import Flask, render_template, jsonify, g, request
|
from flask import Flask, render_template, jsonify, g, request, session, redirect
|
||||||
|
|
||||||
from config import PORT
|
from config import PORT, LOGIN_ENABLED, LOGIN_USERNAME, LOGIN_PASSWORD, SECRET_KEY
|
||||||
from blueprints import pin_tu_bp, base64_bp, down_video_bp, fen_ci_bp, content_tag_bp, chmod_calc_bp, json_format_bp, qr_code_bp, http_status_bp, url_parser_bp, token_gen_bp, sovits_tts_bp, stt_bp, ai_dubbing_bp, rvc_bp
|
from blueprints import pin_tu_bp, base64_bp, down_video_bp, fen_ci_bp, content_tag_bp, chmod_calc_bp, json_format_bp, qr_code_bp, http_status_bp, url_parser_bp, token_gen_bp, sovits_tts_bp, stt_bp, ai_dubbing_bp, rvc_bp
|
||||||
from utils.stats_db import init_db, record_call, get_total_count, get_avg_duration, get_daily_counts, get_monthly_counts, get_available_years, get_available_months, get_daily_counts_by_month, get_hourly_counts, get_endpoint_stats, get_today_count, get_yesterday_count, get_month_count, get_success_rate, get_duration_distribution, get_slowest_endpoints, get_week_compare, get_recent_calls, get_active_days
|
from utils.stats_db import init_db, record_call, get_total_count, get_avg_duration, get_daily_counts, get_monthly_counts, get_available_years, get_available_months, get_daily_counts_by_month, get_hourly_counts, get_endpoint_stats, get_today_count, get_yesterday_count, get_month_count, get_success_rate, get_duration_distribution, get_slowest_endpoints, get_week_compare, get_recent_calls, get_active_days
|
||||||
from utils.stats_db import ALLOWED_TABLES, get_table_info, get_table_rows, get_table_count, insert_row, update_row, delete_rows, clear_table
|
from utils.stats_db import ALLOWED_TABLES, get_table_info, get_table_rows, get_table_count, insert_row, update_row, delete_rows, clear_table
|
||||||
@@ -28,6 +28,24 @@ def create_app():
|
|||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
init_db()
|
init_db()
|
||||||
|
app.secret_key = SECRET_KEY
|
||||||
|
|
||||||
|
# 登录/登出
|
||||||
|
@app.route('/login', methods=['GET', 'POST'])
|
||||||
|
def login():
|
||||||
|
if not LOGIN_ENABLED:
|
||||||
|
return redirect('/')
|
||||||
|
if request.method == 'POST':
|
||||||
|
if request.form.get('username') == LOGIN_USERNAME and request.form.get('password') == LOGIN_PASSWORD:
|
||||||
|
session['logged_in'] = True
|
||||||
|
return redirect('/')
|
||||||
|
return render_template('login.html', error='用户名或密码错误')
|
||||||
|
return render_template('login.html')
|
||||||
|
|
||||||
|
@app.route('/logout')
|
||||||
|
def logout():
|
||||||
|
session.pop('logged_in', None)
|
||||||
|
return redirect('/login')
|
||||||
|
|
||||||
# 主页
|
# 主页
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
@@ -162,6 +180,19 @@ def create_app():
|
|||||||
deleted = clear_table(table)
|
deleted = clear_table(table)
|
||||||
return jsonify({'success': True, 'deleted': deleted})
|
return jsonify({'success': True, 'deleted': deleted})
|
||||||
|
|
||||||
|
# 登录验证
|
||||||
|
@app.before_request
|
||||||
|
def _check_auth():
|
||||||
|
if not LOGIN_ENABLED:
|
||||||
|
return
|
||||||
|
path = request.path
|
||||||
|
if path == '/login' or path.startswith('/static/'):
|
||||||
|
return
|
||||||
|
if not session.get('logged_in'):
|
||||||
|
if path.startswith('/api/'):
|
||||||
|
return jsonify({'error': '未登录'}), 401
|
||||||
|
return redirect('/login')
|
||||||
|
|
||||||
# 请求计时
|
# 请求计时
|
||||||
@app.before_request
|
@app.before_request
|
||||||
def _start_timer():
|
def _start_timer():
|
||||||
@@ -203,12 +234,19 @@ app = create_app()
|
|||||||
|
|
||||||
def start_flask():
|
def start_flask():
|
||||||
"""供桌面启动器调用,以非调试模式运行 Flask"""
|
"""供桌面启动器调用,以非调试模式运行 Flask"""
|
||||||
|
from config import AUTO_OPEN_BROWSER
|
||||||
|
if AUTO_OPEN_BROWSER:
|
||||||
|
import webbrowser
|
||||||
|
import threading as _t
|
||||||
|
_t.Timer(1, webbrowser.open, args=[f'http://127.0.0.1:{PORT}']).start()
|
||||||
a = create_app()
|
a = create_app()
|
||||||
a.run(host='127.0.0.1', port=PORT, use_reloader=False, threaded=True)
|
a.run(host='127.0.0.1', port=PORT, use_reloader=False, threaded=True)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
# import webbrowser
|
from config import AUTO_OPEN_BROWSER
|
||||||
# import threading as _t
|
if AUTO_OPEN_BROWSER:
|
||||||
# _t.Timer(1, webbrowser.open, args=[f'http://127.0.0.1:{PORT}']).start()
|
import webbrowser
|
||||||
|
import threading as _t
|
||||||
|
_t.Timer(1, webbrowser.open, args=[f'http://127.0.0.1:{PORT}']).start()
|
||||||
app.run(debug=True, host='0.0.0.0', port=PORT, threaded=True)
|
app.run(debug=True, host='0.0.0.0', port=PORT, threaded=True)
|
||||||
|
|||||||
@@ -3,10 +3,17 @@
|
|||||||
全局配置集中管理
|
全局配置集中管理
|
||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
|
|
||||||
# 基础目录
|
# 基础目录
|
||||||
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
# ==================== 是否自动打开浏览器 ====================
|
||||||
|
AUTO_OPEN_BROWSER = False
|
||||||
|
# AUTO_OPEN_BROWSER = True
|
||||||
|
# ==================== 登录设置 ====================
|
||||||
|
LOGIN_ENABLED = False
|
||||||
|
# LOGIN_ENABLED = True
|
||||||
|
LOGIN_USERNAME = 'admin'
|
||||||
|
LOGIN_PASSWORD = '123456'
|
||||||
|
SECRET_KEY = 'LQkCU9XfKjxOSfIFZP7kDhwS57o2bvI4qVwZWMet4l8X3RNKnl12bgxvAy1BaByV'
|
||||||
# ==================== down-video 视频下载 ====================
|
# ==================== down-video 视频下载 ====================
|
||||||
TWITTER_COOKIE = os.path.join(BASE_DIR, "config", "dv_cookies", "x.com_cookies.txt")
|
TWITTER_COOKIE = os.path.join(BASE_DIR, "config", "dv_cookies", "x.com_cookies.txt")
|
||||||
BILIBILI_COOKIE = os.path.join(BASE_DIR, "config", "dv_cookies", "bilibili.com_cookies.txt")
|
BILIBILI_COOKIE = os.path.join(BASE_DIR, "config", "dv_cookies", "bilibili.com_cookies.txt")
|
||||||
@@ -21,3 +28,4 @@ JIEBA_DICT_FILE = os.path.join(BASE_DIR, 'config', 'fen_ci', 'jieba.txt')
|
|||||||
TOKEN_FILE_PATH = os.path.join(BASE_DIR, 'config', 'fen_ci', 'usertoken.json')
|
TOKEN_FILE_PATH = os.path.join(BASE_DIR, 'config', 'fen_ci', 'usertoken.json')
|
||||||
# ==================== 服务端口 ====================
|
# ==================== 服务端口 ====================
|
||||||
PORT = 5000
|
PORT = 5000
|
||||||
|
|
||||||
|
|||||||
@@ -29,8 +29,6 @@ live.bilibili.com FALSE / FALSE 1782229863 GIFT_BLOCK_COOKIE GIFT_BLOCK_COOKIE
|
|||||||
.bilibili.com TRUE / FALSE 1816004451 buvid4 D3170BA8-2910-9D9B-A608-52B60F1437AB62978-025051010-2j8K1NCxW9nraGJ2vOJv2vg3LhbmydYJolrkxpng+JQJZmNXaAoya/H8tItJHUfy
|
.bilibili.com TRUE / FALSE 1816004451 buvid4 D3170BA8-2910-9D9B-A608-52B60F1437AB62978-025051010-2j8K1NCxW9nraGJ2vOJv2vg3LhbmydYJolrkxpng+JQJZmNXaAoya/H8tItJHUfy
|
||||||
.bilibili.com TRUE / FALSE 1812974025 home_feed_column 5
|
.bilibili.com TRUE / FALSE 1812974025 home_feed_column 5
|
||||||
.bilibili.com TRUE / FALSE 1812018942 CURRENT_QUALITY 64
|
.bilibili.com TRUE / FALSE 1812018942 CURRENT_QUALITY 64
|
||||||
.bilibili.com TRUE / FALSE 1781516479 bili_ticket eyJhbGciOiJIUzI1NiIsImtpZCI6InMwMyIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3ODE1MTY0ODIsImlhdCI6MTc4MTI1NzIyMiwicGx0IjotMX0.eEl-svs_DNL9hArempTC7OjEOmwU5zkzh4z5lvc2JGU
|
|
||||||
.bilibili.com TRUE / FALSE 1781516479 bili_ticket_expires 1781516422
|
|
||||||
.bilibili.com TRUE / TRUE 1796809280 SESSDATA e981c0f8%2C1796809283%2C53cbf%2A61CjDSekND1lFe5TiJgnRjBVV1dsBTaBY0JP5uDZhtM2bI4WZ9FnbNW1xAQXYO7eBAH7cSVk1jUG0zLU1SWUprSFZxb0VZNl9HM05WckVCZHpYRTVqM3dFUkMwbEVjai1DWF9MbERjUDZVVExzZ2JLMjBnbFhfSjA0MUZWTThBb2tRaDZDQ1d6UHpBIIEC
|
.bilibili.com TRUE / TRUE 1796809280 SESSDATA e981c0f8%2C1796809283%2C53cbf%2A61CjDSekND1lFe5TiJgnRjBVV1dsBTaBY0JP5uDZhtM2bI4WZ9FnbNW1xAQXYO7eBAH7cSVk1jUG0zLU1SWUprSFZxb0VZNl9HM05WckVCZHpYRTVqM3dFUkMwbEVjai1DWF9MbERjUDZVVExzZ2JLMjBnbFhfSjA0MUZWTThBb2tRaDZDQ1d6UHpBIIEC
|
||||||
.bilibili.com TRUE / TRUE 1796809280 bili_jct ef487b5774b781e6ab9c18d90213d327
|
.bilibili.com TRUE / TRUE 1796809280 bili_jct ef487b5774b781e6ab9c18d90213d327
|
||||||
.bilibili.com TRUE / FALSE 0 sid 8gro2gn0
|
.bilibili.com TRUE / FALSE 0 sid 8gro2gn0
|
||||||
|
|||||||
Binary file not shown.
75
flask-dev-api/templates/login.html
Normal file
75
flask-dev-api/templates/login.html
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static', filename='font-awesome.css') }}">
|
||||||
|
<title>登录</title>
|
||||||
|
<style>
|
||||||
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||||
|
body {
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||||
|
background: #f5f5f5; color: #333;
|
||||||
|
display: flex; align-items: center; justify-content: center;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
.login-card {
|
||||||
|
background: #fff; border-radius: 12px; padding: 40px 36px;
|
||||||
|
width: 380px; box-shadow: 0 4px 24px rgba(0,0,0,0.08);
|
||||||
|
}
|
||||||
|
.login-card h1 {
|
||||||
|
font-size: 20px; font-weight: 700; color: #1a1a1a;
|
||||||
|
text-align: center; margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
.login-card .subtitle {
|
||||||
|
text-align: center; font-size: 13px; color: #999; margin-bottom: 28px;
|
||||||
|
}
|
||||||
|
.input-group { margin-bottom: 16px; }
|
||||||
|
.input-group label {
|
||||||
|
display: block; font-size: 12px; font-weight: 600; color: #555; margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
.input-group input {
|
||||||
|
width: 100%; padding: 10px 12px; border: 1px solid #e0e0e0; border-radius: 8px;
|
||||||
|
font-size: 14px; outline: none; transition: border-color 0.15s;
|
||||||
|
}
|
||||||
|
.input-group input:focus { border-color: #0078d4; box-shadow: 0 0 0 2px rgba(0,120,212,0.06); }
|
||||||
|
.login-btn {
|
||||||
|
width: 100%; padding: 11px 0; margin-top: 8px;
|
||||||
|
background: linear-gradient(135deg, #0078d4, #005fa3);
|
||||||
|
color: #fff; border: none; border-radius: 8px;
|
||||||
|
font-size: 14px; font-weight: 600; cursor: pointer;
|
||||||
|
transition: all 0.15s;
|
||||||
|
}
|
||||||
|
.login-btn:hover {
|
||||||
|
background: linear-gradient(135deg, #006cbd, #004e8a);
|
||||||
|
box-shadow: 0 4px 12px rgba(0,120,212,0.25); transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
.login-btn:active { transform: translateY(0); }
|
||||||
|
.error-msg {
|
||||||
|
background: #fce4ec; color: #c62828; border: 1px solid #f8bbd0;
|
||||||
|
border-radius: 6px; padding: 8px 12px; font-size: 13px;
|
||||||
|
text-align: center; margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="login-card">
|
||||||
|
<h1><i class="fas fa-wrench" style="color:#0078d4; margin-right:6px;"></i>工具集管理后台</h1>
|
||||||
|
<p class="subtitle">请登录以继续使用</p>
|
||||||
|
{% if error %}
|
||||||
|
<div class="error-msg">{{ error }}</div>
|
||||||
|
{% endif %}
|
||||||
|
<form method="POST" action="/login">
|
||||||
|
<div class="input-group">
|
||||||
|
<label>用户名</label>
|
||||||
|
<input type="text" name="username" placeholder="请输入用户名" autofocus required>
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<label>密码</label>
|
||||||
|
<input type="password" name="password" placeholder="请输入密码" required>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="login-btn"><i class="fas fa-right-to-bracket"></i> 登 录</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user