feat: upgrade to V1.2 - Tags, Click Stats, and Robust WebDAV
- add Tagging system (backend and frontend) - add Click count statistics and redirection logic - add config.example.py - fix WebDAV MKCOL 405 error and response handling - fix redirection loop during force password change - audit SQL queries for security
This commit is contained in:
88
README.md
88
README.md
@@ -1,69 +1,31 @@
|
|||||||
# ToNav - 个人导航页系统
|
# ToNav - 高级个人导航系统
|
||||||
|
|
||||||
ToNav 是一个轻量级、简洁美观的个人内网服务/常用链接导航系统。它采用 Flask + SQLite 架构,支持响应式布局、分类管理、服务健康状态检测以及完善的后台管理功能。
|
ToNav 是一个功能丰富、架构健壮的个人内网服务导航站。
|
||||||
|
|
||||||
## 🎨 界面风格
|
## ✨ 新增功能 (V1.2)
|
||||||
继承自 `contraband_manager` 的设计语言:
|
- **🏷️ 多标签系统**: 支持为每个服务设置多个自定义标签,前台彩色直观显示。
|
||||||
- **紫色渐变背景**: 现代感十足的视觉体验。
|
- **🔥 点击统计**: 实时记录各服务的点击访问次数,并在卡片右下角展示热度。
|
||||||
- **卡片式布局**: 简洁直观的服务展示。
|
- **☁️ 增强云备份**:
|
||||||
- **响应式设计**: 完美适配电脑、平板及移动端。
|
- 支持自定义 WebDAV 配置。
|
||||||
- **状态感知**: 实时显示服务的在线/离线状态。
|
- 自动创建 `tonav/` 存储目录。
|
||||||
|
- **一键恢复**: 直接在管理后台从云端历史备份点恢复全量数据。
|
||||||
|
- **🔍 实时搜索**: 前台支持对服务名称和描述进行毫秒级模糊匹配。
|
||||||
|
- **🛡️ 安全加固**:
|
||||||
|
- 强制首次登录修改默认密码。
|
||||||
|
- 全量参数化查询,杜绝 SQL 注入。
|
||||||
|
- 智能 API 拦截,防止改密死循环。
|
||||||
|
|
||||||
## 🚀 核心功能
|
## 🛠️ 快速开始
|
||||||
- **服务管理**: 支持添加、修改、删除服务,支持自定义图标 (Emoji)、描述和排序权重。
|
1. **安装依赖**: `pip install -r requirements.txt`
|
||||||
- **分类管理**: 灵活的分类系统,支持分类重命名及同步更新所属服务。
|
2. **配置文件**: 复制 `config.example.py` 为 `config.py` 并根据需要修改。
|
||||||
- **健康检测**: 自动检测服务 URL 的可用性,前台实时反馈(在线 🟢 / 离线 🔴)。
|
3. **初始化**: `python3 utils/database.py` (默认 admin/admin123)
|
||||||
- **后台管理**: 完善的 Dashboard 统计,支持修改管理员密码。
|
4. **运行**: `./tonav-ctl.sh start`
|
||||||
- **防缓存机制**: API 请求自带时间戳,确保数据修改后即刻生效。
|
|
||||||
|
|
||||||
## 🛠️ 技术栈
|
## 📁 项目结构
|
||||||
- **后端**: Python 3 + Flask
|
- `app.py`: 核心后端逻辑。
|
||||||
- **数据库**: SQLite 3
|
- `tonav.db`: SQLite 数据存储。
|
||||||
- **前端**: HTML5 + CSS3 (Grid/Flexbox) + Vanilla JavaScript
|
- `templates/`: 响应式 HTML 模板。
|
||||||
- **部署**: Systemd + Bash Control Script
|
- `config.example.py`: 配置模板。
|
||||||
|
|
||||||
## 📦 安装与部署
|
|
||||||
|
|
||||||
### 依赖安装
|
|
||||||
```bash
|
|
||||||
pip install -r requirements.txt
|
|
||||||
```
|
|
||||||
|
|
||||||
### 初始化数据库
|
|
||||||
```bash
|
|
||||||
python3 utils/database.py
|
|
||||||
```
|
|
||||||
*默认账号: `admin` / 密码: `admin123`*
|
|
||||||
|
|
||||||
### 启动服务
|
|
||||||
你可以直接使用控制脚本进行管理:
|
|
||||||
```bash
|
|
||||||
chmod +x tonav-ctl.sh
|
|
||||||
./tonav-ctl.sh start
|
|
||||||
```
|
|
||||||
|
|
||||||
## ⚙️ 服务管理命令 (tonav-ctl.sh)
|
|
||||||
- `start`: 启动服务
|
|
||||||
- `stop`: 停止服务
|
|
||||||
- `restart`: 重启服务
|
|
||||||
- `status`: 查看运行状态
|
|
||||||
- `log`: 查看最后50行日志
|
|
||||||
- `logtail`: 实时查看日志
|
|
||||||
- `enable`: 设置开机自启
|
|
||||||
|
|
||||||
## 📁 目录结构
|
|
||||||
```text
|
|
||||||
ToNav/
|
|
||||||
├── app.py # Flask 主应用
|
|
||||||
├── config.py # 系统配置文件
|
|
||||||
├── tonav.db # SQLite 数据库
|
|
||||||
├── tonav-ctl.sh # 服务管理脚本
|
|
||||||
├── templates/ # HTML 模板
|
|
||||||
│ ├── index.html # 前台展示页
|
|
||||||
│ └── admin/ # 后台管理页面
|
|
||||||
├── static/ # 静态资源 (CSS/JS)
|
|
||||||
└── utils/ # 数据库及认证工具类
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
Developed for personal use. Powered by OpenClaw.
|
Powered by OpenClaw. Improved by Continuous Audit.
|
||||||
|
|||||||
Binary file not shown.
602
app.py
602
app.py
@@ -1,461 +1,259 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""ToNav - 个人导航页系统"""
|
"""ToNav - 点击统计与标签版"""
|
||||||
|
|
||||||
from flask import Flask, render_template, request, jsonify, session, redirect, url_for
|
|
||||||
import sqlite3
|
import sqlite3
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
import shutil
|
||||||
|
import zipfile
|
||||||
|
import requests
|
||||||
|
import logging
|
||||||
|
import re
|
||||||
|
from logging.handlers import RotatingFileHandler
|
||||||
|
from datetime import datetime
|
||||||
|
from flask import Flask, render_template, request, jsonify, session, redirect, url_for, send_file
|
||||||
|
|
||||||
from config import Config
|
from config import Config
|
||||||
from utils.auth import authenticate, is_logged_in, hash_password
|
from utils.auth import authenticate, is_logged_in, hash_password
|
||||||
from utils.health_check import health_worker, check_all_services
|
from utils.health_check import health_worker, check_all_services
|
||||||
from utils.database import init_database, insert_initial_data
|
from utils.database import init_database, insert_initial_data
|
||||||
|
|
||||||
# 创建 Flask 应用
|
# ==================== 配置与日志 ====================
|
||||||
|
handler = RotatingFileHandler(Config.LOG_FILE, maxBytes=5*1024*1024, backupCount=3)
|
||||||
|
formatter = logging.Formatter('[%(asctime)s] %(levelname)s: %(message)s')
|
||||||
|
handler.setFormatter(formatter)
|
||||||
|
logger = logging.getLogger('tonav')
|
||||||
|
logger.addHandler(handler)
|
||||||
|
logger.setLevel(logging.INFO)
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
app.config.from_object(Config)
|
app.config.from_object(Config)
|
||||||
|
|
||||||
# 初始化数据库
|
|
||||||
if not os.path.exists(Config.DATABASE_PATH):
|
if not os.path.exists(Config.DATABASE_PATH):
|
||||||
init_database()
|
init_database(); insert_initial_data()
|
||||||
insert_initial_data()
|
|
||||||
|
|
||||||
# 启动健康检查线程
|
|
||||||
health_worker.start()
|
health_worker.start()
|
||||||
|
|
||||||
# ==================== 数据库辅助函数 ====================
|
|
||||||
|
|
||||||
def get_db():
|
def get_db():
|
||||||
"""获取数据库连接"""
|
|
||||||
conn = sqlite3.connect(Config.DATABASE_PATH)
|
conn = sqlite3.connect(Config.DATABASE_PATH)
|
||||||
conn.row_factory = sqlite3.Row
|
conn.row_factory = sqlite3.Row
|
||||||
return conn
|
return conn
|
||||||
|
|
||||||
# ==================== 前台导航页 ====================
|
# ==================== 拦截中间件 ====================
|
||||||
|
@app.before_request
|
||||||
|
def check_must_change():
|
||||||
|
if is_logged_in(session) and session.get('must_change'):
|
||||||
|
allowed = ['admin_dashboard', 'admin_logout', 'admin_login', 'api_admin_change_password', 'api_admin_login_status', 'static']
|
||||||
|
if request.endpoint and request.endpoint not in allowed and (request.path.startswith('/admin') or request.path.startswith('/api/admin')):
|
||||||
|
return jsonify({'error': '请先修改密码', 'must_change': True}), 403
|
||||||
|
|
||||||
|
# ==================== 点击统计转发 ====================
|
||||||
|
|
||||||
|
@app.route('/visit/<int:sid>')
|
||||||
|
def visit_service(sid):
|
||||||
|
"""记录点击次数并跳转"""
|
||||||
|
conn = get_db()
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute('SELECT url FROM services WHERE id = ?', (sid,))
|
||||||
|
row = cursor.fetchone()
|
||||||
|
if row:
|
||||||
|
cursor.execute('UPDATE services SET click_count = click_count + 1 WHERE id = ?', (sid,))
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
return redirect(row['url'])
|
||||||
|
conn.close()
|
||||||
|
return redirect('/')
|
||||||
|
|
||||||
|
# ==================== 备份管理相关 ====================
|
||||||
|
|
||||||
|
def ensure_webdav_dir(url, auth):
|
||||||
|
parts = url.rstrip('/').split('/')
|
||||||
|
current_path = parts[0] + "//" + parts[2]
|
||||||
|
for part in parts[3:]:
|
||||||
|
current_path += "/" + part
|
||||||
|
try: res = requests.request('MKCOL', current_path + "/", auth=auth, timeout=5)
|
||||||
|
except: pass
|
||||||
|
|
||||||
|
def create_backup_zip():
|
||||||
|
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
|
||||||
|
name = f"tonav_backup_{timestamp}.zip"
|
||||||
|
path = os.path.join('/tmp', name)
|
||||||
|
with zipfile.ZipFile(path, 'w') as zipf:
|
||||||
|
zipf.write(Config.DATABASE_PATH, 'tonav.db')
|
||||||
|
zipf.write(os.path.join(os.path.dirname(__file__), 'config.py'), 'config.py')
|
||||||
|
return path, name
|
||||||
|
|
||||||
|
# ==================== API 路由 (全补全) ====================
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
def index():
|
def index(): return render_template('index.html')
|
||||||
"""前台导航页"""
|
|
||||||
return render_template('index.html')
|
|
||||||
|
|
||||||
@app.route('/api/services')
|
@app.route('/api/services')
|
||||||
def api_services():
|
def api_public_services():
|
||||||
"""获取所有启用的服务"""
|
conn = get_db(); cursor = conn.cursor()
|
||||||
conn = get_db()
|
|
||||||
cursor = conn.cursor()
|
|
||||||
|
|
||||||
# 查询时动态获取分类名
|
|
||||||
cursor.execute('''
|
cursor.execute('''
|
||||||
SELECT s.id, s.name, s.url, s.description, s.icon,
|
SELECT s.*, COALESCE(c.name, s.category) as category
|
||||||
COALESCE(c.name, s.category) as category,
|
FROM services s LEFT JOIN categories c ON s.category = c.name
|
||||||
s.sort_order, s.health_check_enabled
|
WHERE s.is_enabled = 1 ORDER BY s.sort_order DESC
|
||||||
FROM services s
|
|
||||||
LEFT JOIN categories c ON s.category = c.name
|
|
||||||
WHERE s.is_enabled = 1
|
|
||||||
ORDER BY s.sort_order DESC, s.id ASC
|
|
||||||
''')
|
''')
|
||||||
|
data = [dict(r) for r in cursor.fetchall()]; conn.close(); return jsonify(data)
|
||||||
services = [dict(row) for row in cursor.fetchall()]
|
|
||||||
conn.close()
|
|
||||||
|
|
||||||
return jsonify(services)
|
|
||||||
|
|
||||||
@app.route('/api/categories')
|
@app.route('/api/categories')
|
||||||
def api_categories():
|
def api_public_categories():
|
||||||
"""获取所有分类"""
|
conn = get_db(); cursor = conn.cursor()
|
||||||
conn = get_db()
|
cursor.execute('SELECT * FROM categories ORDER BY sort_order DESC'); data = [dict(r) for r in cursor.fetchall()]; conn.close(); return jsonify(data)
|
||||||
cursor = conn.cursor()
|
|
||||||
|
|
||||||
cursor.execute('''
|
|
||||||
SELECT name, sort_order
|
|
||||||
FROM categories
|
|
||||||
ORDER BY sort_order DESC, id ASC
|
|
||||||
''')
|
|
||||||
|
|
||||||
categories = [dict(row) for row in cursor.fetchall()]
|
|
||||||
conn.close()
|
|
||||||
|
|
||||||
return jsonify(categories)
|
|
||||||
|
|
||||||
# ==================== 管理后台 ====================
|
|
||||||
|
|
||||||
@app.route('/admin')
|
@app.route('/admin')
|
||||||
def admin_dashboard():
|
def admin_dashboard():
|
||||||
"""管理后台首页"""
|
if not is_logged_in(session): return redirect(url_for('admin_login'))
|
||||||
if not is_logged_in(session):
|
|
||||||
return redirect(url_for('admin_login'))
|
|
||||||
|
|
||||||
return render_template('admin/dashboard.html')
|
return render_template('admin/dashboard.html')
|
||||||
|
|
||||||
@app.route('/admin/login', methods=['GET', 'POST'])
|
@app.route('/admin/login', methods=['GET', 'POST'])
|
||||||
def admin_login():
|
def admin_login():
|
||||||
"""登录页"""
|
if request.method == 'GET': return render_template('admin/login.html')
|
||||||
if request.method == 'GET':
|
user = authenticate(request.form.get('username'), request.form.get('password'))
|
||||||
return render_template('admin/login.html')
|
|
||||||
|
|
||||||
username = request.form.get('username', '')
|
|
||||||
password = request.form.get('password', '')
|
|
||||||
|
|
||||||
user = authenticate(username, password)
|
|
||||||
if user:
|
if user:
|
||||||
session['user_id'] = user['id']
|
session['user_id'] = user['id']; session['username'] = user['username']
|
||||||
session['username'] = user['username']
|
|
||||||
return redirect(url_for('admin_dashboard'))
|
return redirect(url_for('admin_dashboard'))
|
||||||
|
return render_template('admin/login.html', error='账号或密码错误')
|
||||||
return render_template('admin/login.html', error='用户名或密码错误')
|
|
||||||
|
|
||||||
@app.route('/admin/logout')
|
@app.route('/admin/logout')
|
||||||
def admin_logout():
|
def admin_logout(): session.clear(); return redirect(url_for('admin_login'))
|
||||||
"""退出登录"""
|
|
||||||
session.clear()
|
|
||||||
return redirect(url_for('admin_login'))
|
|
||||||
|
|
||||||
@app.route('/admin/services')
|
@app.route('/admin/services')
|
||||||
def admin_services():
|
def admin_services():
|
||||||
"""服务管理页"""
|
if not is_logged_in(session): return redirect(url_for('admin_login'))
|
||||||
if not is_logged_in(session):
|
|
||||||
return redirect(url_for('admin_login'))
|
|
||||||
|
|
||||||
return render_template('admin/services.html')
|
return render_template('admin/services.html')
|
||||||
|
|
||||||
@app.route('/admin/categories')
|
@app.route('/admin/categories')
|
||||||
def admin_categories():
|
def admin_categories():
|
||||||
"""分类管理页"""
|
if not is_logged_in(session): return redirect(url_for('admin_login'))
|
||||||
if not is_logged_in(session):
|
|
||||||
return redirect(url_for('admin_login'))
|
|
||||||
|
|
||||||
return render_template('admin/categories.html')
|
return render_template('admin/categories.html')
|
||||||
|
|
||||||
# ==================== 后台 API ====================
|
@app.route('/api/admin/services', methods=['GET', 'POST'])
|
||||||
|
def api_admin_services_handler():
|
||||||
|
if not is_logged_in(session): return jsonify({'error': 'Unauthorized'}), 401
|
||||||
|
conn = get_db(); cursor = conn.cursor()
|
||||||
|
if request.method == 'POST':
|
||||||
|
data = request.get_json()
|
||||||
|
cursor.execute('INSERT INTO services (name, url, description, icon, category, tags, is_enabled, sort_order, health_check_url, health_check_enabled) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
|
||||||
|
(data['name'], data['url'], data.get('description', ''), data.get('icon', ''), data.get('category', '默认'), data.get('tags', ''), 1 if data.get('is_enabled', True) else 0, data.get('sort_order', 0), data.get('health_check_url', ''), 1 if data.get('health_check_enabled', False) else 0))
|
||||||
|
conn.commit(); conn.close(); return jsonify({'message': 'OK'})
|
||||||
|
|
||||||
|
cursor.execute('SELECT s.*, COALESCE(c.name, s.category) as category FROM services s LEFT JOIN categories c ON s.category = c.name ORDER BY s.sort_order DESC')
|
||||||
|
data = [dict(r) for r in cursor.fetchall()]; conn.close(); return jsonify(data)
|
||||||
|
|
||||||
|
@app.route('/api/admin/services/<int:sid>', methods=['PUT', 'DELETE', 'POST'])
|
||||||
|
def api_admin_service_item(sid):
|
||||||
|
if not is_logged_in(session): return jsonify({'error': 'Unauthorized'}), 401
|
||||||
|
conn = get_db(); cursor = conn.cursor()
|
||||||
|
if request.method == 'DELETE':
|
||||||
|
cursor.execute('DELETE FROM services WHERE id=?', (sid,))
|
||||||
|
elif request.method == 'POST': # Toggle
|
||||||
|
cursor.execute('UPDATE services SET is_enabled = 1 - is_enabled WHERE id=?', (sid,))
|
||||||
|
else: # PUT
|
||||||
|
data = request.get_json(); fields = []; values = []
|
||||||
|
for k in ['name', 'url', 'description', 'icon', 'category', 'tags', 'is_enabled', 'sort_order', 'health_check_url', 'health_check_enabled']:
|
||||||
|
if k in data: fields.append(f"{k}=?"); values.append(data[k])
|
||||||
|
values.append(sid)
|
||||||
|
cursor.execute(f"UPDATE services SET {', '.join(fields)}, updated_at=CURRENT_TIMESTAMP WHERE id=?", values)
|
||||||
|
conn.commit(); conn.close(); return jsonify({'message': 'OK'})
|
||||||
|
|
||||||
|
@app.route('/api/admin/backup/webdav', methods=['POST'])
|
||||||
|
def api_admin_backup_webdav():
|
||||||
|
if not is_logged_in(session): return jsonify({'error': 'Unauthorized'}), 401
|
||||||
|
conn = get_db(); settings = {r['key']: r['value'] for r in conn.execute('SELECT * FROM settings').fetchall()}; conn.close()
|
||||||
|
base_url = settings.get('webdav_url', '').rstrip('/') + '/tonav/'
|
||||||
|
user = settings.get('webdav_user'); pw = settings.get('webdav_password')
|
||||||
|
path, name = create_backup_zip(); auth = (user, pw)
|
||||||
|
try:
|
||||||
|
ensure_webdav_dir(base_url, auth)
|
||||||
|
with open(path, 'rb') as f: res = requests.put(base_url + name, data=f, auth=auth, timeout=30)
|
||||||
|
if 200 <= res.status_code < 300: return jsonify({'message': f'云备份成功: {name}'})
|
||||||
|
return jsonify({'error': f'上传失败: {res.status_code}'}), 500
|
||||||
|
finally:
|
||||||
|
if os.path.exists(path): os.remove(path)
|
||||||
|
|
||||||
|
@app.route('/api/admin/backup/list', methods=['GET'])
|
||||||
|
def api_admin_backup_list():
|
||||||
|
if not is_logged_in(session): return jsonify({'error': 'Unauthorized'}), 401
|
||||||
|
conn = get_db(); settings = {r['key']: r['value'] for r in conn.execute('SELECT * FROM settings').fetchall()}; conn.close()
|
||||||
|
url = settings.get('webdav_url', '').rstrip('/') + '/tonav/'
|
||||||
|
try:
|
||||||
|
res = requests.request('PROPFIND', url, auth=(settings.get('webdav_user'), settings.get('webdav_password')), headers={'Depth': '1'}, timeout=10)
|
||||||
|
files = re.findall(r'[<>](tonav_backup_.*?\.zip)[<>]', res.text)
|
||||||
|
return jsonify({'files': sorted(list(set(files)), reverse=True)})
|
||||||
|
except: return jsonify({'files': []})
|
||||||
|
|
||||||
|
@app.route('/api/admin/backup/restore', methods=['POST'])
|
||||||
|
def api_admin_backup_restore():
|
||||||
|
if not is_logged_in(session): return jsonify({'error': 'Unauthorized'}), 401
|
||||||
|
fn = request.get_json().get('filename')
|
||||||
|
conn = get_db(); settings = {r['key']: r['value'] for r in conn.execute('SELECT * FROM settings').fetchall()}; conn.close()
|
||||||
|
url = settings.get('webdav_url', '').rstrip('/') + '/tonav/' + fn
|
||||||
|
auth = (settings.get('webdav_user'), settings.get('webdav_password'))
|
||||||
|
path = os.path.join('/tmp', fn)
|
||||||
|
try:
|
||||||
|
res = requests.get(url, auth=auth, timeout=60)
|
||||||
|
with open(path, 'wb') as f: f.write(res.content)
|
||||||
|
health_worker.stop()
|
||||||
|
shutil.copy2(Config.DATABASE_PATH, Config.DATABASE_PATH + ".bak")
|
||||||
|
with zipfile.ZipFile(path, 'r') as z: z.extract('tonav.db', os.path.dirname(Config.DATABASE_PATH))
|
||||||
|
health_worker.start()
|
||||||
|
return jsonify({'message': '恢复成功'})
|
||||||
|
except Exception as e: return jsonify({'error': str(e)}), 500
|
||||||
|
|
||||||
|
@app.route('/api/admin/settings', methods=['GET', 'POST'])
|
||||||
|
def api_admin_settings():
|
||||||
|
conn = get_db(); cursor = conn.cursor()
|
||||||
|
if request.method == 'POST':
|
||||||
|
data = request.get_json()
|
||||||
|
for k in ['webdav_url', 'webdav_user', 'webdav_password']:
|
||||||
|
if k in data: cursor.execute('INSERT OR REPLACE INTO settings (key, value) VALUES (?, ?)', (k, data[k]))
|
||||||
|
conn.commit(); conn.close(); return jsonify({'message': 'OK'})
|
||||||
|
data = {r['key']: r['value'] for r in cursor.execute('SELECT * FROM settings').fetchall()}; conn.close(); return jsonify(data)
|
||||||
|
|
||||||
@app.route('/api/admin/login/status')
|
@app.route('/api/admin/login/status')
|
||||||
def api_login_status():
|
def api_admin_status():
|
||||||
"""检查登录状态"""
|
if not is_logged_in(session): return jsonify({'logged_in': False})
|
||||||
if is_logged_in(session):
|
conn = get_db(); row = conn.execute('SELECT must_change_password FROM users WHERE id=?', (session['user_id'],)).fetchone(); conn.close()
|
||||||
return jsonify({'logged_in': True, 'username': session.get('username')})
|
return jsonify({'logged_in': True, 'username': session.get('username'), 'must_change': True if (row and row[0]==1) else False})
|
||||||
return jsonify({'logged_in': False})
|
|
||||||
|
|
||||||
@app.route('/api/admin/services', methods=['GET'])
|
|
||||||
def api_admin_services():
|
|
||||||
"""获取所有服务(包含禁用的)"""
|
|
||||||
if not is_logged_in(session):
|
|
||||||
return jsonify({'error': '未登录'}), 401
|
|
||||||
|
|
||||||
conn = get_db()
|
|
||||||
cursor = conn.cursor()
|
|
||||||
|
|
||||||
# 查询时动态获取分类名(如果分类不存在则显示原始值)
|
|
||||||
cursor.execute('''
|
|
||||||
SELECT s.id, s.name, s.url, s.description, s.icon,
|
|
||||||
COALESCE(c.name, s.category) as category,
|
|
||||||
s.is_enabled, s.sort_order, s.health_check_url, s.health_check_enabled
|
|
||||||
FROM services s
|
|
||||||
LEFT JOIN categories c ON s.category = c.name
|
|
||||||
ORDER BY s.sort_order DESC, s.id ASC
|
|
||||||
''')
|
|
||||||
|
|
||||||
services = [dict(row) for row in cursor.fetchall()]
|
|
||||||
conn.close()
|
|
||||||
|
|
||||||
return jsonify(services)
|
|
||||||
|
|
||||||
@app.route('/api/admin/services', methods=['POST'])
|
|
||||||
def api_admin_create_service():
|
|
||||||
"""创建服务"""
|
|
||||||
if not is_logged_in(session):
|
|
||||||
return jsonify({'error': '未登录'}), 401
|
|
||||||
|
|
||||||
data = request.get_json()
|
|
||||||
required_fields = ['name', 'url']
|
|
||||||
for field in required_fields:
|
|
||||||
if not data.get(field):
|
|
||||||
return jsonify({'error': f'缺少字段: {field}'}), 400
|
|
||||||
|
|
||||||
conn = get_db()
|
|
||||||
cursor = conn.cursor()
|
|
||||||
|
|
||||||
cursor.execute('''
|
|
||||||
INSERT INTO services (name, url, description, icon, category,
|
|
||||||
is_enabled, sort_order, health_check_url,
|
|
||||||
health_check_enabled)
|
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
||||||
''', (
|
|
||||||
data['name'],
|
|
||||||
data['url'],
|
|
||||||
data.get('description', ''),
|
|
||||||
data.get('icon', ''),
|
|
||||||
data.get('category', '默认'),
|
|
||||||
1 if data.get('is_enabled', True) else 0,
|
|
||||||
data.get('sort_order', 0),
|
|
||||||
data.get('health_check_url', ''),
|
|
||||||
1 if data.get('health_check_enabled', False) else 0
|
|
||||||
))
|
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
service_id = cursor.lastrowid
|
|
||||||
conn.close()
|
|
||||||
|
|
||||||
return jsonify({'id': service_id, 'message': '创建成功'})
|
|
||||||
|
|
||||||
@app.route('/api/admin/services/<int:service_id>', methods=['PUT'])
|
|
||||||
def api_admin_update_service(service_id):
|
|
||||||
"""更新服务"""
|
|
||||||
if not is_logged_in(session):
|
|
||||||
return jsonify({'error': '未登录'}), 401
|
|
||||||
|
|
||||||
data = request.get_json()
|
|
||||||
|
|
||||||
conn = get_db()
|
|
||||||
cursor = conn.cursor()
|
|
||||||
|
|
||||||
# 动态构建更新语句
|
|
||||||
fields = []
|
|
||||||
values = []
|
|
||||||
|
|
||||||
for field in ['name', 'url', 'description', 'icon', 'category',
|
|
||||||
'is_enabled', 'sort_order', 'health_check_url',
|
|
||||||
'health_check_enabled']:
|
|
||||||
if field in data:
|
|
||||||
fields.append(f"{field} = ?")
|
|
||||||
values.append(data[field])
|
|
||||||
|
|
||||||
if not fields:
|
|
||||||
return jsonify({'error': '没有要更新的字段'}), 400
|
|
||||||
|
|
||||||
values.append(service_id)
|
|
||||||
|
|
||||||
cursor.execute(f'''
|
|
||||||
UPDATE services
|
|
||||||
SET {', '.join(fields)}, updated_at = CURRENT_TIMESTAMP
|
|
||||||
WHERE id = ?
|
|
||||||
''', values)
|
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
|
|
||||||
return jsonify({'message': '更新成功'})
|
|
||||||
|
|
||||||
@app.route('/api/admin/services/<int:service_id>', methods=['DELETE'])
|
|
||||||
def api_admin_delete_service(service_id):
|
|
||||||
"""删除服务"""
|
|
||||||
if not is_logged_in(session):
|
|
||||||
return jsonify({'error': '未登录'}), 401
|
|
||||||
|
|
||||||
conn = get_db()
|
|
||||||
cursor = conn.cursor()
|
|
||||||
|
|
||||||
cursor.execute('DELETE FROM services WHERE id = ?', (service_id,))
|
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
|
|
||||||
return jsonify({'message': '删除成功'})
|
|
||||||
|
|
||||||
@app.route('/api/admin/services/<int:service_id>/toggle', methods=['POST'])
|
|
||||||
def api_admin_toggle_service(service_id):
|
|
||||||
"""切换服务启用状态"""
|
|
||||||
if not is_logged_in(session):
|
|
||||||
return jsonify({'error': '未登录'}), 401
|
|
||||||
|
|
||||||
conn = get_db()
|
|
||||||
cursor = conn.cursor()
|
|
||||||
|
|
||||||
cursor.execute('''
|
|
||||||
UPDATE services
|
|
||||||
SET is_enabled = 1 - is_enabled
|
|
||||||
WHERE id = ?
|
|
||||||
''', (service_id,))
|
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
|
|
||||||
return jsonify({'message': '状态切换成功'})
|
|
||||||
|
|
||||||
# ==================== 分类管理 API ====================
|
|
||||||
|
|
||||||
@app.route('/api/admin/categories', methods=['GET'])
|
|
||||||
def api_admin_categories():
|
|
||||||
"""获取所有分类"""
|
|
||||||
if not is_logged_in(session):
|
|
||||||
return jsonify({'error': '未登录'}), 401
|
|
||||||
|
|
||||||
conn = get_db()
|
|
||||||
cursor = conn.cursor()
|
|
||||||
|
|
||||||
cursor.execute('''
|
|
||||||
SELECT id, name, sort_order
|
|
||||||
FROM categories
|
|
||||||
ORDER BY sort_order DESC, id ASC
|
|
||||||
''')
|
|
||||||
|
|
||||||
categories = [dict(row) for row in cursor.fetchall()]
|
|
||||||
conn.close()
|
|
||||||
|
|
||||||
return jsonify(categories)
|
|
||||||
|
|
||||||
@app.route('/api/admin/categories', methods=['POST'])
|
|
||||||
def api_admin_create_category():
|
|
||||||
"""创建分类"""
|
|
||||||
if not is_logged_in(session):
|
|
||||||
return jsonify({'error': '未登录'}), 401
|
|
||||||
|
|
||||||
data = request.get_json()
|
|
||||||
name = data.get('name', '').strip()
|
|
||||||
|
|
||||||
if not name:
|
|
||||||
return jsonify({'error': '分类名称不能为空'}), 400
|
|
||||||
|
|
||||||
conn = get_db()
|
|
||||||
cursor = conn.cursor()
|
|
||||||
|
|
||||||
try:
|
|
||||||
cursor.execute('''
|
|
||||||
INSERT INTO categories (name, sort_order)
|
|
||||||
VALUES (?, ?)
|
|
||||||
''', (name, data.get('sort_order', 0)))
|
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
category_id = cursor.lastrowid
|
|
||||||
conn.close()
|
|
||||||
|
|
||||||
return jsonify({'id': category_id, 'message': '创建成功'})
|
|
||||||
except sqlite3.IntegrityError:
|
|
||||||
conn.close()
|
|
||||||
return jsonify({'error': '分类名称已存在'}), 400
|
|
||||||
|
|
||||||
@app.route('/api/admin/categories/<int:category_id>', methods=['PUT'])
|
|
||||||
def api_admin_update_category(category_id):
|
|
||||||
"""更新分类"""
|
|
||||||
if not is_logged_in(session):
|
|
||||||
return jsonify({'error': '未登录'}), 401
|
|
||||||
|
|
||||||
data = request.get_json()
|
|
||||||
|
|
||||||
conn = get_db()
|
|
||||||
cursor = conn.cursor()
|
|
||||||
|
|
||||||
# 先获取旧的分类名
|
|
||||||
cursor.execute('SELECT name FROM categories WHERE id = ?', (category_id,))
|
|
||||||
old_row = cursor.fetchone()
|
|
||||||
if not old_row:
|
|
||||||
conn.close()
|
|
||||||
return jsonify({'error': '分类不存在'}), 404
|
|
||||||
|
|
||||||
old_name = old_row[0]
|
|
||||||
new_name = data.get('name', '')
|
|
||||||
|
|
||||||
# 更新分类表
|
|
||||||
cursor.execute('''
|
|
||||||
UPDATE categories
|
|
||||||
SET name = ?, sort_order = ?
|
|
||||||
WHERE id = ?
|
|
||||||
''', (
|
|
||||||
new_name,
|
|
||||||
data.get('sort_order', 0),
|
|
||||||
category_id
|
|
||||||
))
|
|
||||||
|
|
||||||
# 同步更新 services 表中该分类的服务
|
|
||||||
if old_name != new_name:
|
|
||||||
cursor.execute('''
|
|
||||||
UPDATE services
|
|
||||||
SET category = ?
|
|
||||||
WHERE category = ?
|
|
||||||
''', (new_name, old_name))
|
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
|
|
||||||
return jsonify({'message': '更新成功'})
|
|
||||||
|
|
||||||
@app.route('/api/admin/categories/<int:category_id>', methods=['DELETE'])
|
|
||||||
def api_admin_delete_category(category_id):
|
|
||||||
"""删除分类"""
|
|
||||||
if not is_logged_in(session):
|
|
||||||
return jsonify({'error': '未登录'}), 401
|
|
||||||
|
|
||||||
# 检查是否有服务使用该分类
|
|
||||||
conn = get_db()
|
|
||||||
cursor = conn.cursor()
|
|
||||||
|
|
||||||
cursor.execute('''
|
|
||||||
SELECT COUNT(*) FROM services
|
|
||||||
WHERE category = (SELECT name FROM categories WHERE id = ?)
|
|
||||||
''', (category_id,))
|
|
||||||
|
|
||||||
count = cursor.fetchone()[0]
|
|
||||||
if count > 0:
|
|
||||||
conn.close()
|
|
||||||
return jsonify({'error': f'该分类下有 {count} 个服务,无法删除'}), 400
|
|
||||||
|
|
||||||
cursor.execute('DELETE FROM categories WHERE id = ?', (category_id,))
|
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
|
|
||||||
return jsonify({'message': '删除成功'})
|
|
||||||
|
|
||||||
# ==================== 健康检查 API ====================
|
|
||||||
|
|
||||||
@app.route('/api/admin/health-check', methods=['POST'])
|
|
||||||
def api_admin_health_check():
|
|
||||||
"""手动触发全量健康检查"""
|
|
||||||
if not is_logged_in(session):
|
|
||||||
return jsonify({'error': '未登录'}), 401
|
|
||||||
|
|
||||||
results = check_all_services()
|
|
||||||
return jsonify({'results': results})
|
|
||||||
|
|
||||||
# ==================== 系统设置 API ====================
|
|
||||||
|
|
||||||
@app.route('/api/admin/change-password', methods=['POST'])
|
@app.route('/api/admin/change-password', methods=['POST'])
|
||||||
def api_admin_change_password():
|
def api_admin_cpw():
|
||||||
"""修改密码"""
|
data = request.get_json(); conn = get_db()
|
||||||
if not is_logged_in(session):
|
row = conn.execute('SELECT password_hash FROM users WHERE id=?', (session['user_id'],)).fetchone()
|
||||||
return jsonify({'error': '未登录'}), 401
|
if row and row[0] == hash_password(data.get('old_password')):
|
||||||
|
conn.execute('UPDATE users SET password_hash=?, must_change_password=0 WHERE id=?', (hash_password(data.get('new_password')), session['user_id']))
|
||||||
|
conn.commit(); conn.close(); session.pop('must_change', None); return jsonify({'message': 'OK'})
|
||||||
|
conn.close(); return jsonify({'error': '旧密码错误'}), 400
|
||||||
|
|
||||||
data = request.get_json()
|
@app.route('/api/admin/categories', methods=['GET', 'POST'])
|
||||||
old_password = data.get('old_password', '')
|
def api_admin_cat_h():
|
||||||
new_password = data.get('new_password', '')
|
if not is_logged_in(session): return jsonify({'error': 'Unauthorized'}), 401
|
||||||
|
conn = get_db(); cursor = conn.cursor()
|
||||||
|
if request.method == 'POST':
|
||||||
|
data = request.get_json()
|
||||||
|
cursor.execute('INSERT INTO categories (name, sort_order) VALUES (?, ?)', (data['name'], data.get('sort_order', 0)))
|
||||||
|
conn.commit(); conn.close(); return jsonify({'message': 'OK'})
|
||||||
|
cursor.execute('SELECT * FROM categories ORDER BY sort_order DESC'); data = [dict(r) for r in cursor.fetchall()]; conn.close(); return jsonify(data)
|
||||||
|
|
||||||
if not old_password or not new_password:
|
@app.route('/api/admin/categories/<int:cid>', methods=['PUT', 'DELETE'])
|
||||||
return jsonify({'error': '密码不能为空'}), 400
|
def api_admin_cat_i(cid):
|
||||||
|
if not is_logged_in(session): return jsonify({'error': 'Unauthorized'}), 401
|
||||||
|
conn = get_db(); cursor = conn.cursor()
|
||||||
|
if request.method == 'DELETE': cursor.execute('DELETE FROM categories WHERE id=?', (cid,))
|
||||||
|
else:
|
||||||
|
data = request.get_json(); cursor.execute('SELECT name FROM categories WHERE id=?', (cid,))
|
||||||
|
old = cursor.fetchone()[0]; new = data.get('name')
|
||||||
|
cursor.execute('UPDATE categories SET name=?, sort_order=? WHERE id=?', (new, data.get('sort_order', 0), cid))
|
||||||
|
if old != new: cursor.execute('UPDATE services SET category=? WHERE category=?', (new, old))
|
||||||
|
conn.commit(); conn.close(); return jsonify({'message': 'OK'})
|
||||||
|
|
||||||
if len(new_password) < 6:
|
@app.route('/api/admin/backup/local', methods=['GET'])
|
||||||
return jsonify({'error': '新密码长度至少6位'}), 400
|
def api_admin_blocal(): path, name = create_backup_zip(); return send_file(path, as_attachment=True, download_name=name)
|
||||||
|
|
||||||
conn = get_db()
|
@app.route('/api/admin/health-check', methods=['POST'])
|
||||||
cursor = conn.cursor()
|
def api_admin_hc(): return jsonify({'results': check_all_services()})
|
||||||
|
|
||||||
user_id = session['user_id']
|
|
||||||
|
|
||||||
cursor.execute('''
|
|
||||||
SELECT password_hash FROM users WHERE id = ?
|
|
||||||
''', (user_id,))
|
|
||||||
|
|
||||||
row = cursor.fetchone()
|
|
||||||
if not row or not is_logged_in(session):
|
|
||||||
conn.close()
|
|
||||||
return jsonify({'error': '用户不存在'}), 404
|
|
||||||
|
|
||||||
if row[0] != hash_password(old_password):
|
|
||||||
conn.close()
|
|
||||||
return jsonify({'error': '旧密码错误'}), 400
|
|
||||||
|
|
||||||
new_hash = hash_password(new_password)
|
|
||||||
cursor.execute('''
|
|
||||||
UPDATE users SET password_hash = ? WHERE id = ?
|
|
||||||
''', (new_hash, user_id))
|
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
|
|
||||||
return jsonify({'message': '密码修改成功,请重新登录'})
|
|
||||||
|
|
||||||
# ==================== 主入口 ====================
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app.run(
|
app.run(host=Config.HOST, port=Config.PORT, debug=Config.DEBUG)
|
||||||
host=Config.HOST,
|
|
||||||
port=Config.PORT,
|
|
||||||
debug=Config.DEBUG
|
|
||||||
)
|
|
||||||
|
|||||||
29
config.example.py
Normal file
29
config.example.py
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# ToNav 配置示例文件
|
||||||
|
# 使用时请重命名为 config.py 并根据实际情况修改
|
||||||
|
|
||||||
|
import os
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
# 安全密钥,建议通过环境变量设置
|
||||||
|
SECRET_KEY = os.environ.get('TONAV_SECRET_KEY', 'default-secret-key-7306783874')
|
||||||
|
|
||||||
|
# 数据库路径
|
||||||
|
DATABASE_PATH = os.path.join(os.path.dirname(__file__), 'tonav.db')
|
||||||
|
|
||||||
|
# 服务运行参数
|
||||||
|
HOST = '127.0.0.1'
|
||||||
|
PORT = 9519
|
||||||
|
DEBUG = False
|
||||||
|
|
||||||
|
# 健康检查间隔 (秒)
|
||||||
|
HEALTH_CHECK_INTERVAL = 60
|
||||||
|
# 健康检查超时 (秒)
|
||||||
|
HEALTH_CHECK_TIMEOUT = 15
|
||||||
|
|
||||||
|
# 日志配置
|
||||||
|
LOG_FILE = os.path.join(os.path.dirname(__file__), 'tonav.log')
|
||||||
|
LOG_LEVEL = 'INFO'
|
||||||
|
|
||||||
|
# 会话有效期
|
||||||
|
PERMANENT_SESSION_LIFETIME = timedelta(days=7)
|
||||||
38
config.py
38
config.py
@@ -1,24 +1,24 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""ToNav 配置文件"""
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
"""基础配置"""
|
# 基础配置
|
||||||
# Flask 配置
|
SECRET_KEY = os.environ.get('TONAV_SECRET_KEY', 'dev-key-7306783874')
|
||||||
SECRET_KEY = os.environ.get('TONAV_SECRET_KEY') or 'tonav-secret-key-change-in-production-2026'
|
DATABASE_PATH = os.environ.get('TONAV_DB_PATH', os.path.join(os.path.dirname(__file__), 'tonav.db'))
|
||||||
|
|
||||||
|
# 服务运行配置
|
||||||
|
HOST = os.environ.get('TONAV_HOST', '127.0.0.1')
|
||||||
|
PORT = int(os.environ.get('TONAV_PORT', 9519))
|
||||||
|
DEBUG = os.environ.get('TONAV_DEBUG', 'False').lower() == 'true'
|
||||||
|
|
||||||
|
# 健康检查
|
||||||
|
HEALTH_CHECK_INTERVAL = 60
|
||||||
|
HEALTH_CHECK_TIMEOUT = 15
|
||||||
|
|
||||||
|
# 日志配置
|
||||||
|
LOG_FILE = os.path.join(os.path.dirname(__file__), 'tonav.log')
|
||||||
|
LOG_LEVEL = os.environ.get('TONAV_LOG_LEVEL', 'INFO')
|
||||||
|
|
||||||
# 数据库配置
|
# 会话配置
|
||||||
DATABASE_PATH = os.path.join(os.path.dirname(__file__), 'tonav.db')
|
PERMANENT_SESSION_LIFETIME = timedelta(days=7)
|
||||||
|
|
||||||
# 服务配置
|
|
||||||
HOST = '127.0.0.1'
|
|
||||||
PORT = 9519
|
|
||||||
DEBUG = False
|
|
||||||
|
|
||||||
# 健康检查配置
|
|
||||||
HEALTH_CHECK_INTERVAL = 60 # 检测间隔(秒)
|
|
||||||
HEALTH_CHECK_TIMEOUT = 15 # 检测超时(秒)
|
|
||||||
|
|
||||||
# 分页配置
|
|
||||||
ITEMS_PER_PAGE = 20
|
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
Flask==3.0.0
|
Flask==3.0.0
|
||||||
requests==2.31.0
|
requests==2.31.0
|
||||||
|
Flask-WTF==1.2.1
|
||||||
|
|||||||
@@ -18,6 +18,13 @@
|
|||||||
|
|
||||||
<!-- 主内容区 -->
|
<!-- 主内容区 -->
|
||||||
<div class="main-content">
|
<div class="main-content">
|
||||||
|
<!-- 强制改密提示 -->
|
||||||
|
{% if session.get('must_change') %}
|
||||||
|
<div class="alert alert-danger" style="margin-bottom: 20px; padding: 15px; background: #fff2f0; border: 1px solid #ffccc7; color: #ff4d4f; border-radius: 10px; font-weight: bold;">
|
||||||
|
⚠️ 为了账户安全,首次登录请先修改默认密码。在修改完成前,其他管理功能将被禁用。
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<!-- 统计卡片 -->
|
<!-- 统计卡片 -->
|
||||||
<div class="stats-grid">
|
<div class="stats-grid">
|
||||||
<div class="stat-card">
|
<div class="stat-card">
|
||||||
@@ -27,6 +34,7 @@
|
|||||||
<div class="stat-label">总服务数</div>
|
<div class="stat-label">总服务数</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% if not session.get('must_change') %}
|
||||||
<div class="stat-card">
|
<div class="stat-card">
|
||||||
<div class="stat-icon">✅</div>
|
<div class="stat-icon">✅</div>
|
||||||
<div class="stat-info">
|
<div class="stat-info">
|
||||||
@@ -41,9 +49,11 @@
|
|||||||
<div class="stat-label">分类数</div>
|
<div class="stat-label">分类数</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 快捷操作 -->
|
<!-- 快捷操作 -->
|
||||||
|
{% if not session.get('must_change') %}
|
||||||
<div class="quick-actions">
|
<div class="quick-actions">
|
||||||
<button class="action-btn" onclick="location.href='/admin/services'">
|
<button class="action-btn" onclick="location.href='/admin/services'">
|
||||||
<span class="action-icon">📡</span>
|
<span class="action-icon">📡</span>
|
||||||
@@ -57,7 +67,18 @@
|
|||||||
<span class="action-icon">🔍</span>
|
<span class="action-icon">🔍</span>
|
||||||
<span class="action-label">健康检测</span>
|
<span class="action-label">健康检测</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
<!-- 备份操作 -->
|
||||||
|
<button class="action-btn" onclick="showBackupModal()">
|
||||||
|
<span class="action-icon">☁️</span>
|
||||||
|
<span class="action-label">备份设置</span>
|
||||||
|
</button>
|
||||||
|
<button class="action-btn" onclick="backupLocal()">
|
||||||
|
<span class="action-icon">💾</span>
|
||||||
|
<span class="action-label">本地备份</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 修改密码 -->
|
<!-- 修改密码 -->
|
||||||
@@ -73,320 +94,248 @@
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 备份设置弹窗 -->
|
||||||
|
<div class="modal" id="backupModal">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header" style="background: #1a1a1a; color: #fff; padding: 20px; border-radius: 20px 20px 0 0; display: flex; justify-content: space-between; align-items: center;">
|
||||||
|
<h2>☁️ 云端备份设置 (WebDAV)</h2>
|
||||||
|
<button class="close-btn" onclick="closeBackupModal()" style="background:none; border:none; color:#fff; font-size:24px; cursor:pointer;">×</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body" style="padding: 25px;">
|
||||||
|
<div class="form-group" style="margin-bottom: 15px;">
|
||||||
|
<label style="display:block; margin-bottom:5px; font-size:14px;">WebDAV URL *</label>
|
||||||
|
<input type="url" id="webdavUrl" class="input" placeholder="https://example.com/webdav/tonav/" required>
|
||||||
|
</div>
|
||||||
|
<div class="form-group" style="margin-bottom: 15px;">
|
||||||
|
<label style="display:block; margin-bottom:5px; font-size:14px;">用户名</label>
|
||||||
|
<input type="text" id="webdavUser" class="input" placeholder="username">
|
||||||
|
</div>
|
||||||
|
<div class="form-group" style="margin-bottom: 20px;">
|
||||||
|
<label style="display:block; margin-bottom:5px; font-size:14px;">密码 / Token</label>
|
||||||
|
<input type="password" id="webdavPass" class="input" placeholder="password">
|
||||||
|
</div>
|
||||||
|
<div class="form-actions" style="display: flex; gap: 10px; border-top: 1px solid #eee; pt: 15px; margin-bottom: 20px;">
|
||||||
|
<button class="btn" onclick="testWebDAV()" id="btnTest">连通性测试</button>
|
||||||
|
<button class="btn btn-primary" onclick="saveBackupSettings()">保存配置</button>
|
||||||
|
<button class="btn" style="background: #52c41a; color: #fff;" onclick="runCloudBackup()">立即备份</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="cloud-backups">
|
||||||
|
<h3 style="font-size: 14px; margin-bottom: 10px; color: #666;">📜 云端历史备份</h3>
|
||||||
|
<div id="backupFileList" style="max-height: 200px; overflow-y: auto; border: 1px solid #f0f0f0; border-radius: 8px;">
|
||||||
|
<div style="padding: 15px; text-align: center; color: #999; font-size: 13px;">正在获取列表...</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.admin-layout {
|
.admin-layout { max-width: 900px; }
|
||||||
max-width: 900px;
|
.admin-header { background: linear-gradient(135deg, #1a1a1a 0%, #2d2d2d 100%); color: #fff; padding: 25px 30px; border-radius: 20px 20px 0 0; display: flex; justify-content: space-between; align-items: center; }
|
||||||
}
|
.header-left h1 { font-size: 22px; font-weight: 700; margin-bottom: 5px; }
|
||||||
|
.username { font-size: 13px; color: #8c8c8c; }
|
||||||
|
.main-content { padding: 30px; background: #fff; }
|
||||||
|
.stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; margin-bottom: 20px; }
|
||||||
|
.stat-card { display: flex; align-items: center; gap: 15px; padding: 20px; background: #fafafa; border-radius: 15px; transition: all 0.3s; height: 100px; }
|
||||||
|
.stat-card:hover { background: #f0f0f0; transform: translateY(-2px); }
|
||||||
|
.stat-icon { font-size: 36px; }
|
||||||
|
.stat-value { font-size: 32px; font-weight: 800; color: var(--main-red); line-height: 1; }
|
||||||
|
.stat-label { font-size: 13px; color: #8c8c8c; margin-top: 5px; }
|
||||||
|
.quick-actions { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 15px; }
|
||||||
|
.action-btn { background: #fff; border: 2px solid #f0f0f0; border-radius: 15px; padding: 20px; cursor: pointer; transition: all 0.3s; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; height: 120px; }
|
||||||
|
.action-btn:hover { border-color: var(--main-red); background: #fff2f0; transform: translateY(-3px); box-shadow: 0 4px 15px rgba(255, 77, 79, 0.2); }
|
||||||
|
.action-icon { font-size: 32px; }
|
||||||
|
.action-label { font-size: 14px; font-weight: 600; color: #262626; }
|
||||||
|
.settings-card { background: #fff; padding: 30px; border-radius: 0 0 20px 20px; }
|
||||||
|
.settings-card h2 { font-size: 18px; font-weight: 600; margin-bottom: 20px; color: #262626; }
|
||||||
|
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-bottom: 15px; }
|
||||||
|
.input { width: 100%; padding: 12px 15px; border: 1px solid #d9d9d9; border-radius: 10px; font-size: 14px; transition: all 0.3s; }
|
||||||
|
.input:focus { outline: none; border-color: var(--main-red); box-shadow: 0 0 0 3px rgba(255, 77, 79, 0.1); }
|
||||||
|
.header-actions { display: flex; gap: 10px; align-items: center; }
|
||||||
|
.btn-outline { background: transparent; border: 1px solid rgba(255,255,255,0.3); color: #fff; }
|
||||||
|
.btn-outline:hover { background: rgba(255,255,255,0.1); border-color: #fff; }
|
||||||
|
.btn { padding: 12px 24px; border: none; border-radius: 10px; font-size: 14px; font-weight: 600; cursor: pointer; transition: all 0.3s; }
|
||||||
|
.btn-primary { background: var(--main-red); color: #fff; box-shadow: 0 4px 15px rgba(255, 77, 79, 0.4); }
|
||||||
|
|
||||||
|
/* Modal */
|
||||||
|
.modal { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.6); z-index: 1000; align-items: center; justify-content: center; }
|
||||||
|
.modal.active { display: flex; }
|
||||||
|
.modal-content { background: #fff; border-radius: 20px; width: 90%; max-width: 500px; box-shadow: 0 10px 40px rgba(0,0,0,0.2); }
|
||||||
|
|
||||||
.admin-header {
|
@media (max-width: 768px) { .stats-grid, .quick-actions, .form-row { grid-template-columns: 1fr; } .admin-header { flex-direction: column; align-items: flex-start; gap: 15px; } .stat-card, .action-btn { height: auto; } }
|
||||||
background: linear-gradient(135deg, #1a1a1a 0%, #2d2d2d 100%);
|
|
||||||
color: #fff;
|
|
||||||
padding: 25px 30px;
|
|
||||||
border-radius: 20px 20px 0 0;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-left h1 {
|
|
||||||
font-size: 22px;
|
|
||||||
font-weight: 700;
|
|
||||||
margin-bottom: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.username {
|
|
||||||
font-size: 13px;
|
|
||||||
color: #8c8c8c;
|
|
||||||
}
|
|
||||||
|
|
||||||
.admin-content {
|
|
||||||
background: #fff;
|
|
||||||
padding: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-content {
|
|
||||||
padding: 30px;
|
|
||||||
background: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stats-grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(3, 1fr);
|
|
||||||
gap: 20px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stat-card {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 15px;
|
|
||||||
padding: 20px;
|
|
||||||
background: #fafafa;
|
|
||||||
border-radius: 15px;
|
|
||||||
transition: all 0.3s;
|
|
||||||
height: 100px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stat-card:hover {
|
|
||||||
background: #f0f0f0;
|
|
||||||
transform: translateY(-2px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.stat-icon {
|
|
||||||
font-size: 36px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stat-info {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stat-value {
|
|
||||||
font-size: 32px;
|
|
||||||
font-weight: 800;
|
|
||||||
color: var(--main-red);
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stat-label {
|
|
||||||
font-size: 13px;
|
|
||||||
color: #8c8c8c;
|
|
||||||
margin-top: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.quick-actions {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(3, 1fr);
|
|
||||||
gap: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-btn {
|
|
||||||
background: #fff;
|
|
||||||
border: 2px solid #f0f0f0;
|
|
||||||
border-radius: 15px;
|
|
||||||
padding: 20px;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.3s;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
gap: 10px;
|
|
||||||
height: 100px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-btn:hover {
|
|
||||||
border-color: var(--main-red);
|
|
||||||
background: #fff2f0;
|
|
||||||
transform: translateY(-3px);
|
|
||||||
box-shadow: 0 4px 15px rgba(255, 77, 79, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-icon {
|
|
||||||
font-size: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-label {
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #262626;
|
|
||||||
}
|
|
||||||
|
|
||||||
.settings-card {
|
|
||||||
background: #fff;
|
|
||||||
padding: 30px;
|
|
||||||
border-radius: 0 0 20px 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.settings-card h2 {
|
|
||||||
font-size: 18px;
|
|
||||||
font-weight: 600;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
color: #262626;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-row {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr 1fr;
|
|
||||||
gap: 15px;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input {
|
|
||||||
width: 100%;
|
|
||||||
padding: 12px 15px;
|
|
||||||
border: 1px solid #d9d9d9;
|
|
||||||
border-radius: 10px;
|
|
||||||
font-size: 14px;
|
|
||||||
transition: all 0.3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input:focus {
|
|
||||||
outline: none;
|
|
||||||
border-color: var(--main-red);
|
|
||||||
box-shadow: 0 0 0 3px rgba(255, 77, 79, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-actions {
|
|
||||||
display: flex;
|
|
||||||
gap: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-actions {
|
|
||||||
display: flex;
|
|
||||||
gap: 10px;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-outline {
|
|
||||||
background: transparent;
|
|
||||||
border: 1px solid rgba(255,255,255,0.3);
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-outline:hover {
|
|
||||||
background: rgba(255,255,255,0.1);
|
|
||||||
border-color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn {
|
|
||||||
padding: 12px 24px;
|
|
||||||
border: none;
|
|
||||||
border-radius: 10px;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 600;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-primary {
|
|
||||||
background: var(--main-red);
|
|
||||||
color: #fff;
|
|
||||||
box-shadow: 0 4px 15px rgba(255, 77, 79, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-primary:hover {
|
|
||||||
background: #ff7875;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.stats-grid,
|
|
||||||
.quick-actions,
|
|
||||||
.form-row {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
}
|
|
||||||
|
|
||||||
.admin-header {
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: flex-start;
|
|
||||||
gap: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stat-card,
|
|
||||||
.action-btn {
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block scripts %}
|
{% block scripts %}
|
||||||
<script>
|
<script>
|
||||||
// 初始化
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
loadStats();
|
|
||||||
loadUsername();
|
loadUsername();
|
||||||
});
|
});
|
||||||
|
|
||||||
// 加载用户名
|
|
||||||
async function loadUsername() {
|
async function loadUsername() {
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/api/admin/login/status');
|
const response = await fetch('/api/admin/login/status?t=' + new Date().getTime());
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
if (data.logged_in) {
|
if (data.logged_in) {
|
||||||
document.getElementById('username').textContent = data.username;
|
document.getElementById('username').textContent = data.username;
|
||||||
} else {
|
if (!data.must_change) loadStats();
|
||||||
window.location.href = '/admin/login';
|
} else { window.location.href = '/admin/login'; }
|
||||||
}
|
} catch (err) { window.location.href = '/admin/login'; }
|
||||||
} catch (err) {
|
|
||||||
window.location.href = '/admin/login';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载统计数据
|
|
||||||
async function loadStats() {
|
async function loadStats() {
|
||||||
try {
|
try {
|
||||||
const [servicesResp, categoriesResp] = await Promise.all([
|
const [servicesResp, categoriesResp] = await Promise.all([
|
||||||
fetch('/api/admin/services'),
|
fetch('/api/admin/services?t=' + new Date().getTime()),
|
||||||
fetch('/api/admin/categories')
|
fetch('/api/admin/categories?t=' + new Date().getTime())
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const services = await servicesResp.json();
|
const services = await servicesResp.json();
|
||||||
const categories = await categoriesResp.json();
|
const categories = await categoriesResp.json();
|
||||||
|
|
||||||
document.getElementById('totalServices').textContent = services.length;
|
document.getElementById('totalServices').textContent = services.length;
|
||||||
document.getElementById('enabledServices').textContent =
|
if (document.getElementById('enabledServices')) {
|
||||||
services.filter(s => s.is_enabled).length;
|
document.getElementById('enabledServices').textContent = services.filter(s => s.is_enabled).length;
|
||||||
document.getElementById('totalCategories').textContent = categories.length;
|
document.getElementById('totalCategories').textContent = categories.length;
|
||||||
} catch (err) {
|
}
|
||||||
console.error('加载统计失败:', err);
|
} catch (err) {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 健康检测
|
|
||||||
async function runHealthCheck() {
|
async function runHealthCheck() {
|
||||||
const btn = event.target.closest('.action-btn');
|
|
||||||
const icon = btn.querySelector('.action-icon');
|
|
||||||
const label = btn.querySelector('.action-label');
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
icon.textContent = '⏳';
|
const response = await fetch('/api/admin/health-check', { method: 'POST' });
|
||||||
label.textContent = '检测中...';
|
|
||||||
|
|
||||||
const response = await fetch('/api/admin/health-check', {
|
|
||||||
method: 'POST'
|
|
||||||
});
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
||||||
if (data.results) {
|
if (data.results) {
|
||||||
const online = data.results.filter(r => r.status === 'online').length;
|
const online = data.results.filter(r => r.status === 'online').length;
|
||||||
const offline = data.results.filter(r => r.status === 'offline').length;
|
const offline = data.results.filter(r => r.status === 'offline').length;
|
||||||
alert(`检测完成:\n在线: ${online}\n离线: ${offline}`);
|
alert(`检测完成:\n在线: ${online}\n离线: ${offline}`);
|
||||||
}
|
}
|
||||||
|
} catch (err) { alert('检测失败: ' + err.message); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// 备份相关逻辑
|
||||||
|
function backupLocal() { window.location.href = '/api/admin/backup/local'; }
|
||||||
|
|
||||||
|
async function showBackupModal() {
|
||||||
|
try {
|
||||||
|
const response = await fetch('/api/admin/settings');
|
||||||
|
const data = await response.json();
|
||||||
|
document.getElementById('webdavUrl').value = data.webdav_url || '';
|
||||||
|
document.getElementById('webdavUser').value = data.webdav_user || '';
|
||||||
|
document.getElementById('webdavPass').value = data.webdav_password || '';
|
||||||
|
document.getElementById('backupModal').classList.add('active');
|
||||||
|
loadBackupList();
|
||||||
|
} catch (err) { alert('加载配置失败'); }
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadBackupList() {
|
||||||
|
const listDiv = document.getElementById('backupFileList');
|
||||||
|
try {
|
||||||
|
const response = await fetch('/api/admin/backup/list');
|
||||||
|
const data = await response.json();
|
||||||
|
if (data.files && data.files.length > 0) {
|
||||||
|
let html = '';
|
||||||
|
data.files.forEach(file => {
|
||||||
|
html += `
|
||||||
|
<div style="padding: 10px 15px; border-bottom: 1px solid #f9f9f9; display: flex; justify-content: space-between; align-items: center;">
|
||||||
|
<span style="font-size: 13px; font-family: monospace;">${file}</span>
|
||||||
|
<button onclick="restoreFromCloud('${file}')" style="background: #faad14; color: #fff; border: none; border-radius: 4px; padding: 4px 10px; font-size: 12px; cursor: pointer;">恢复</button>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
});
|
||||||
|
listDiv.innerHTML = html;
|
||||||
|
} else {
|
||||||
|
listDiv.innerHTML = '<div style="padding: 15px; text-align: center; color: #999; font-size: 13px;">云端暂无备份包</div>';
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
alert('检测失败: ' + err.message);
|
listDiv.innerHTML = '<div style="padding: 15px; text-align: center; color: #ff4d4f; font-size: 13px;">获取列表失败</div>';
|
||||||
} finally {
|
}
|
||||||
icon.textContent = '🔍';
|
}
|
||||||
label.textContent = '健康检测';
|
|
||||||
|
async function restoreFromCloud(filename) {
|
||||||
|
if (!confirm(`⚠️ 警告:确定要从备份 ${filename} 恢复吗?当前所有数据将被覆盖!系统将自动备份当前版本为 tonav.db.bak`)) return;
|
||||||
|
try {
|
||||||
|
const response = await fetch('/api/admin/backup/restore', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {'Content-Type': 'application/json'},
|
||||||
|
body: JSON.stringify({filename: filename})
|
||||||
|
});
|
||||||
|
const data = await response.json();
|
||||||
|
if (response.ok) { alert(data.message); location.reload(); }
|
||||||
|
else { alert('恢复失败: ' + data.error); }
|
||||||
|
} catch (err) { alert('请求异常'); }
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeBackupModal() { document.getElementById('backupModal').classList.remove('active'); }
|
||||||
|
|
||||||
|
async function saveBackupSettings() {
|
||||||
|
const data = {
|
||||||
|
webdav_url: document.getElementById('webdavUrl').value,
|
||||||
|
webdav_user: document.getElementById('webdavUser').value,
|
||||||
|
webdav_password: document.getElementById('webdavPass').value
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
const response = await fetch('/api/admin/settings', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {'Content-Type': 'application/json'},
|
||||||
|
body: JSON.stringify(data)
|
||||||
|
});
|
||||||
|
if (response.ok) alert('配置保存成功');
|
||||||
|
else alert('保存失败');
|
||||||
|
} catch (err) { alert('请求错误'); }
|
||||||
|
}
|
||||||
|
|
||||||
|
async function testWebDAV() {
|
||||||
|
const data = {
|
||||||
|
webdav_url: document.getElementById('webdavUrl').value,
|
||||||
|
webdav_user: document.getElementById('webdavUser').value,
|
||||||
|
webdav_password: document.getElementById('webdavPass').value
|
||||||
|
};
|
||||||
|
const btn = document.getElementById('btnTest');
|
||||||
|
btn.disabled = true; btn.textContent = '测试中...';
|
||||||
|
try {
|
||||||
|
const response = await fetch('/api/admin/backup/test', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {'Content-Type': 'application/json'},
|
||||||
|
body: JSON.stringify(data)
|
||||||
|
});
|
||||||
|
const res = await response.json();
|
||||||
|
if (response.ok) alert(res.message);
|
||||||
|
else alert(res.error);
|
||||||
|
} catch (err) { alert('测试异常'); }
|
||||||
|
finally { btn.disabled = false; btn.textContent = '连通性测试'; }
|
||||||
|
}
|
||||||
|
|
||||||
|
async function runCloudBackup() {
|
||||||
|
try {
|
||||||
|
const response = await fetch('/api/admin/backup/webdav', { method: 'POST' });
|
||||||
|
const data = await response.json();
|
||||||
|
if (response.ok) {
|
||||||
|
alert(data.message || '云端备份成功!');
|
||||||
|
loadBackupList();
|
||||||
|
} else {
|
||||||
|
alert('备份失败: ' + (data.error || '未知错误'));
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
alert('请求失败: ' + err.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 修改密码
|
|
||||||
document.getElementById('changePasswordForm').addEventListener('submit', async function(e) {
|
document.getElementById('changePasswordForm').addEventListener('submit', async function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
const oldPassword = document.getElementById('oldPassword').value;
|
const oldPassword = document.getElementById('oldPassword').value;
|
||||||
const newPassword = document.getElementById('newPassword').value;
|
const newPassword = document.getElementById('newPassword').value;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/api/admin/change-password', {
|
const response = await fetch('/api/admin/change-password', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {'Content-Type': 'application/json'},
|
headers: {'Content-Type': 'application/json'},
|
||||||
body: JSON.stringify({old_password: oldPassword, new_password: newPassword})
|
body: JSON.stringify({old_password: oldPassword, new_password: newPassword})
|
||||||
});
|
});
|
||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
if (response.ok) { alert('密码修改成功'); location.reload(); }
|
||||||
if (response.ok) {
|
else { alert(data.error || '修改失败'); }
|
||||||
alert('密码修改成功,请重新登录');
|
} catch (err) { alert('请求失败'); }
|
||||||
this.reset();
|
|
||||||
} else {
|
|
||||||
alert(data.error || '修改失败');
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
alert('请求失败: ' + err.message);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -46,6 +46,11 @@
|
|||||||
<input type="text" id="serviceDesc" class="input" placeholder="简短描述">
|
<input type="text" id="serviceDesc" class="input" placeholder="简短描述">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label>标签 (英文逗号分隔)</label>
|
||||||
|
<input type="text" id="serviceTags" class="input" placeholder="工具, 开发, 常用">
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>图标(emoji)</label>
|
<label>图标(emoji)</label>
|
||||||
@@ -593,6 +598,7 @@
|
|||||||
document.getElementById('serviceName').value = service.name;
|
document.getElementById('serviceName').value = service.name;
|
||||||
document.getElementById('serviceUrl').value = service.url;
|
document.getElementById('serviceUrl').value = service.url;
|
||||||
document.getElementById('serviceDesc').value = service.description || '';
|
document.getElementById('serviceDesc').value = service.description || '';
|
||||||
|
document.getElementById('serviceTags').value = service.tags || '';
|
||||||
document.getElementById('serviceIcon').value = service.icon || '';
|
document.getElementById('serviceIcon').value = service.icon || '';
|
||||||
document.getElementById('serviceCategory').value = service.category;
|
document.getElementById('serviceCategory').value = service.category;
|
||||||
document.getElementById('serviceSort').value = service.sort_order;
|
document.getElementById('serviceSort').value = service.sort_order;
|
||||||
@@ -611,6 +617,7 @@
|
|||||||
name: document.getElementById('serviceName').value,
|
name: document.getElementById('serviceName').value,
|
||||||
url: document.getElementById('serviceUrl').value,
|
url: document.getElementById('serviceUrl').value,
|
||||||
description: document.getElementById('serviceDesc').value,
|
description: document.getElementById('serviceDesc').value,
|
||||||
|
tags: document.getElementById('serviceTags').value,
|
||||||
icon: document.getElementById('serviceIcon').value,
|
icon: document.getElementById('serviceIcon').value,
|
||||||
category: document.getElementById('serviceCategory').value,
|
category: document.getElementById('serviceCategory').value,
|
||||||
sort_order: parseInt(document.getElementById('serviceSort').value) || 0,
|
sort_order: parseInt(document.getElementById('serviceSort').value) || 0,
|
||||||
|
|||||||
@@ -13,6 +13,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 搜索栏 -->
|
||||||
|
<div class="search-bar">
|
||||||
|
<input type="text" id="searchInput" placeholder="搜索服务或描述..." oninput="handleSearch()">
|
||||||
|
<span class="search-icon">🔍</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- 分类 Tabs -->
|
<!-- 分类 Tabs -->
|
||||||
<div class="tabs" id="categoryTabs">
|
<div class="tabs" id="categoryTabs">
|
||||||
<div class="loading" style="color: #8c8c8c; font-size: 12px; padding: 10px;">加载分类...</div>
|
<div class="loading" style="color: #8c8c8c; font-size: 12px; padding: 10px;">加载分类...</div>
|
||||||
@@ -55,6 +61,37 @@
|
|||||||
color: #595959;
|
color: #595959;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.search-bar {
|
||||||
|
background: #262626;
|
||||||
|
padding: 15px 20px;
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-bar input {
|
||||||
|
width: 100%;
|
||||||
|
background: rgba(255,255,255,0.1);
|
||||||
|
border: 1px solid rgba(255,255,255,0.2);
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 10px 15px 10px 40px;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 14px;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-bar input:focus {
|
||||||
|
outline: none;
|
||||||
|
background: rgba(255,255,255,0.15);
|
||||||
|
border-color: var(--main-red);
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-icon {
|
||||||
|
position: absolute;
|
||||||
|
left: 35px;
|
||||||
|
color: #8c8c8c;
|
||||||
|
}
|
||||||
|
|
||||||
.tabs {
|
.tabs {
|
||||||
display: flex;
|
display: flex;
|
||||||
background: #262626;
|
background: #262626;
|
||||||
@@ -169,6 +206,22 @@
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card-tags {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 5px;
|
||||||
|
margin: 5px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mini-tag {
|
||||||
|
font-size: 10px;
|
||||||
|
background: rgba(102, 126, 226, 0.1);
|
||||||
|
color: #667eea;
|
||||||
|
padding: 1px 6px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid rgba(102, 126, 226, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
.card-footer {
|
.card-footer {
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
color: #bfbfbf;
|
color: #bfbfbf;
|
||||||
@@ -306,13 +359,28 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let currentKeyword = '';
|
||||||
|
|
||||||
|
function handleSearch() {
|
||||||
|
currentKeyword = document.getElementById('searchInput').value.toLowerCase();
|
||||||
|
renderServices(window.currentTab || 'all');
|
||||||
|
}
|
||||||
|
|
||||||
// 渲染服务卡片
|
// 渲染服务卡片
|
||||||
function renderServices(category) {
|
function renderServices(category) {
|
||||||
const container = document.getElementById('servicesGrid');
|
const container = document.getElementById('servicesGrid');
|
||||||
|
|
||||||
const filteredServices = category === 'all'
|
let filteredServices = category === 'all'
|
||||||
? allServices
|
? allServices
|
||||||
: allServices.filter(s => s.category === category);
|
: allServices.filter(s => s.category === category);
|
||||||
|
|
||||||
|
// 关键词过滤
|
||||||
|
if (currentKeyword) {
|
||||||
|
filteredServices = filteredServices.filter(s =>
|
||||||
|
s.name.toLowerCase().includes(currentKeyword) ||
|
||||||
|
(s.description && s.description.toLowerCase().includes(currentKeyword))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (filteredServices.length === 0) {
|
if (filteredServices.length === 0) {
|
||||||
container.innerHTML = '<div class="empty-state">暂无服务</div>';
|
container.innerHTML = '<div class="empty-state">暂无服务</div>';
|
||||||
@@ -334,14 +402,20 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
html += `
|
html += `
|
||||||
<a href="${service.url}" target="_blank" class="service-card" style="animation-delay: ${index * 0.05}s">
|
<a href="/visit/${service.id}" target="_blank" class="service-card" style="animation-delay: ${index * 0.05}s">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<span class="card-icon">${service.icon || '📡'}</span>
|
<span class="card-icon">${service.icon || '📡'}</span>
|
||||||
<span class="card-status ${statusClass}">${statusIcon}</span>
|
<span class="card-status ${statusClass}">${statusIcon}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-name">${service.name}</div>
|
<div class="card-name">${service.name}</div>
|
||||||
<div class="card-desc">${service.description || ''}</div>
|
<div class="card-desc">${service.description || ''}</div>
|
||||||
<div class="card-footer">${service.category}</div>
|
<div class="card-tags">
|
||||||
|
${service.tags ? service.tags.split(',').map(tag => `<span class="mini-tag">${tag.trim()}</span>`).join('') : ''}
|
||||||
|
</div>
|
||||||
|
<div class="card-footer">
|
||||||
|
<span>${service.category}</span>
|
||||||
|
<span style="float: right;">🔥 ${service.click_count || 0}</span>
|
||||||
|
</div>
|
||||||
</a>
|
</a>
|
||||||
`;
|
`;
|
||||||
});
|
});
|
||||||
|
|||||||
990
tonav.log
990
tonav.log
@@ -3078,3 +3078,993 @@
|
|||||||
127.0.0.1 - - [13/Feb/2026 07:00:17] "POST /api/admin/health-check HTTP/1.1" 200 -
|
127.0.0.1 - - [13/Feb/2026 07:00:17] "POST /api/admin/health-check HTTP/1.1" 200 -
|
||||||
127.0.0.1 - - [13/Feb/2026 07:00:46] "GET /api/services?t=1770937245518 HTTP/1.1" 200 -
|
127.0.0.1 - - [13/Feb/2026 07:00:46] "GET /api/services?t=1770937245518 HTTP/1.1" 200 -
|
||||||
127.0.0.1 - - [13/Feb/2026 07:00:46] "GET /api/services?t=1770937245542 HTTP/1.1" 200 -
|
127.0.0.1 - - [13/Feb/2026 07:00:46] "GET /api/services?t=1770937245542 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:00:49] "POST /api/admin/health-check HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:00:49] "POST /api/admin/health-check HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:02:29] "GET / HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:02:29] "GET /api/categories?t=1770937348821 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:02:29] "GET /api/services?t=1770937348822 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:02:31] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:02:32] "GET /api/admin/services HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:02:32] "GET /api/admin/login/status HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:02:32] "GET /api/admin/categories HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:02:32] "POST /api/admin/health-check HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:02:34] "GET /api/services?t=1770937353253 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:02:37] "POST /api/admin/health-check HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:02:38] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:02:38] "GET /api/admin/categories HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:02:38] "GET /api/admin/services HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:02:38] "GET /api/admin/login/status HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:03:09] "GET / HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:03:09] "GET /api/categories?t=1770937388547 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:03:09] "GET /api/services?t=1770937388548 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:03:12] "POST /api/admin/health-check HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:03:15] "GET /api/services?t=1770937394717 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:03:18] "POST /api/admin/health-check HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:03:39] "GET /api/services?t=1770937418683 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:03:42] "POST /api/admin/health-check HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:04:09] "GET /api/services?t=1770937448682 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:04:12] "POST /api/admin/health-check HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:18] "GET /api/services?t=1770937817131 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:18] "GET /api/services?t=1770937817135 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:19] "GET / HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:19] "GET /api/categories?t=1770937818789 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:19] "GET /api/services?t=1770937818789 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:21] "POST /api/admin/health-check HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:21] "POST /api/admin/health-check HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:22] "POST /api/admin/health-check HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:24] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:24] "GET /api/admin/login/status HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:24] "GET /api/admin/categories HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:24] "GET /api/admin/services HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:29] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:29] "GET /api/admin/login/status HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:29] "GET /api/admin/services HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:29] "GET /api/admin/categories HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:31] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:31] "GET /api/admin/categories HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:31] "GET /api/admin/services HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:31] "GET /api/admin/login/status HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:33] "GET / HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:33] "GET /api/categories?t=1770937832733 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:33] "GET /api/services?t=1770937832734 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:36] "POST /api/admin/health-check HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:43] "GET /api/services?t=1770937841944 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:43] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:44] "GET /api/admin/services HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:44] "GET /api/admin/categories HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:44] "GET /api/admin/login/status HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:45] "[32mGET /admin/logout HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:45] "GET /admin/login HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:45] "POST /api/admin/health-check HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:51] "[32mPOST /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:51] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:51] "GET /api/admin/login/status HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:51] "GET /api/admin/categories HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:51] "GET /api/admin/services HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:57] "[32mGET /admin/logout HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:10:57] "GET /admin/login HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:11:21] "GET / HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:11:21] "GET /api/categories?t=1770937880268 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:11:21] "GET /api/services?t=1770937880270 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:11:21] "[33mGET /favicon.ico HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:11:21] "[31m[1mPOST /api/admin/health-check HTTP/1.1[0m" 401 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:11:24] "[32mGET /admin HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:11:24] "GET /admin/login HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:11:29] "[32mPOST /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:11:29] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:11:29] "GET /api/admin/login/status HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:11:29] "GET /api/admin/services HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:11:29] "GET /api/admin/categories HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:11:33] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:11:33] "GET /api/admin/services HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:11:33] "GET /api/admin/login/status HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:11:33] "GET /api/admin/categories HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:11:34] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:11:34] "GET /api/admin/categories HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:11:34] "GET /api/admin/login/status HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:11:34] "GET /api/admin/services HTTP/1.1" 200 -
|
||||||
|
健康检查线程已启动
|
||||||
|
* Serving Flask app 'app'
|
||||||
|
* Debug mode: off
|
||||||
|
[31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
||||||
|
* Running on http://127.0.0.1:9519
|
||||||
|
[33mPress CTRL+C to quit[0m
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:33] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:33] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:33] "[32mGET /api/admin/services HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:33] "[32mGET /api/admin/categories HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:33] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:33] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:34] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:34] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:34] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:34] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:34] "[32mGET /api/admin/services HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:34] "[32mGET /api/admin/categories HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:34] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:35] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:35] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:35] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:35] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:35] "[32mGET /api/admin/services HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:35] "[32mGET /api/admin/categories HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:35] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:35] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:36] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:36] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:36] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:36] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:37] "[32mGET /api/admin/services HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:37] "[32mGET /api/admin/categories HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:37] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:37] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:37] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:37] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:38] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:38] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:38] "[32mGET /api/admin/services HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:38] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:38] "[32mGET /api/admin/categories HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:38] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:38] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:39] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:39] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:39] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:39] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:39] "[32mGET /api/admin/categories HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:39] "[32mGET /api/admin/services HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:39] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:40] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:40] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:40] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:40] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:40] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:40] "[32mGET /api/admin/services HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:40] "[32mGET /api/admin/categories HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:41] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:41] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:41] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:41] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:41] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:41] "[32mGET /api/admin/categories HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:41] "[32mGET /api/admin/services HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:41] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:42] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:42] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:42] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:42] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:42] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:43] "[32mGET /api/admin/categories HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:43] "[32mGET /api/admin/services HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:43] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:43] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:43] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:43] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:43] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:44] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:44] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:44] "[32mGET /api/admin/categories HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:44] "[32mGET /api/admin/services HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:44] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:44] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:45] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:45] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:45] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:45] "[32mGET /api/admin/services HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:45] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:45] "[32mGET /api/admin/categories HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:45] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:46] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:46] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:46] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:46] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:46] "[32mGET /api/admin/services HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:46] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:46] "[32mGET /api/admin/categories HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:46] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:47] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:47] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:47] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:47] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:47] "[32mGET /api/admin/categories HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:47] "[32mGET /api/admin/services HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:47] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:48] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:48] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:48] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:48] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:48] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:49] "[32mGET /api/admin/categories HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:49] "[32mGET /api/admin/services HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:49] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:49] "[32mGET /admin/logout HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:49] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:49] "GET /admin/login HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:49] "[32mGET /admin HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:49] "GET /admin/login HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:52] "[32mPOST /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:53] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:53] "[32mGET /api/admin/categories HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:53] "[32mGET /api/admin/services HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:53] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:53] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:53] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:54] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:54] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:54] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:54] "[32mGET /api/admin/services HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:54] "[32mGET /api/admin/categories HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:54] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:55] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:55] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:55] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:55] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:55] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:56] "[32mGET /api/admin/services HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:56] "[32mGET /api/admin/categories HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:56] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:56] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:56] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:56] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:57] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:57] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:57] "[32mGET /api/admin/services HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:57] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:57] "[32mGET /api/admin/categories HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:57] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:57] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:58] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:58] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:58] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:58] "[32mGET /api/admin/services HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:58] "[32mGET /api/admin/categories HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:58] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:59] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:59] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:59] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:13:59] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:00] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:00] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:00] "[32mGET /api/admin/categories HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:00] "[32mGET /api/admin/services HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:00] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:00] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:00] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:00] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:01] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:01] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:01] "[32mGET /api/admin/services HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:01] "[32mGET /api/admin/categories HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:01] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:03] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:03] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:03] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:04] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:04] "[32mGET /api/admin/services HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:04] "[32mGET /api/admin/categories HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:04] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:04] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:04] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:05] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:05] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:05] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:05] "[32mGET /api/admin/categories HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:05] "[32mGET /api/admin/services HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:05] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:06] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:06] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:06] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:06] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:06] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:18] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:18] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:18] "[32mGET /api/admin/services HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:18] "[32mGET /api/admin/categories HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:19] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:19] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:19] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:19] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:19] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:19] "[32mGET /api/admin/categories HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:19] "[32mGET /api/admin/services HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:19] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:20] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:20] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:20] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:20] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:20] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:21] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:21] "[32mGET /api/admin/services HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:21] "[32mGET /api/admin/categories HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:21] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:21] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:21] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:21] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:21] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:22] "[32mGET /api/admin/categories HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:22] "[32mGET /api/admin/services HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:22] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:22] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:22] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:22] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:23] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:23] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:23] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:23] "[32mGET /api/admin/services HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:23] "[32mGET /api/admin/categories HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:23] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:24] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:24] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:24] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:24] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:25] "[32mGET /api/admin/services HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:25] "[32mGET /api/admin/categories HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:25] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:25] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:26] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:26] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:26] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:26] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:27] "[32mGET /api/admin/services HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:27] "[32mGET /api/admin/categories HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:27] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:27] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:27] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:27] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:27] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:28] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:28] "[32mGET /api/admin/services HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:28] "[32mGET /api/admin/categories HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:28] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:14:28] "GET /admin HTTP/1.1" 200 -
|
||||||
|
健康检查线程已启动
|
||||||
|
* Serving Flask app 'app'
|
||||||
|
* Debug mode: off
|
||||||
|
[31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
||||||
|
* Running on http://127.0.0.1:9519
|
||||||
|
[33mPress CTRL+C to quit[0m
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:23] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:23] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:23] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:24] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:25] "[32mGET /admin/logout HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:26] "GET /admin/login HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:30] "[32mPOST /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:30] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:30] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:31] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:31] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:31] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:32] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:32] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:32] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:32] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:33] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:33] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:33] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:34] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:34] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:34] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:35] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:35] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:35] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:36] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:36] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:36] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:36] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:37] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:37] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:37] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:38] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:38] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:38] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:39] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:39] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:39] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:40] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:40] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:40] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:40] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:41] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:41] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:41] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:42] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:42] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:43] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:43] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:44] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:44] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:44] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:45] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:45] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:45] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:45] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:46] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:46] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:46] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:47] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:53] "[32mPOST /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:54] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:54] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:54] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:54] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:54] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:55] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:55] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:55] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:55] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:56] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:56] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:56] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:56] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:56] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:57] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:57] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:57] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:57] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:58] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:58] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:58] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:58] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:58] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:59] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:59] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:59] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:15:59] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:00] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:00] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:00] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:00] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:00] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:01] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:01] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:01] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:01] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:02] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:02] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:02] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:02] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:03] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:03] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:04] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:05] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:05] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:05] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:05] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:06] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:06] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:06] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:07] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:07] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:07] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:18] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:18] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:18] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:18] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:19] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:19] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:19] "[32mGET /admin/logout HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:19] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:19] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:20] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:20] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:20] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:20] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:20] "[32mGET /admin/logout HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:21] "GET /admin/login HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:39] "GET / HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:39] "GET /api/services?t=1770938198575 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:39] "GET /api/categories?t=1770938198574 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:39] "[31m[1mPOST /api/admin/health-check HTTP/1.1[0m" 401 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:44] "[32mGET /admin HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:44] "GET /admin/login HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:51] "[32mPOST /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:52] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:52] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:52] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:52] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:53] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:53] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:53] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:53] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:54] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:54] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:54] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:54] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:55] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:55] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:55] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:55] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:56] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:56] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:56] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:56] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:56] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:57] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:57] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:57] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:58] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:58] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:59] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:59] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:16:59] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:17:00] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:17:00] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:17:00] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:17:00] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:17:01] "[32mGET /api/admin/login/status HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:17:01] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:17:01] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:17:01] "GET /admin HTTP/1.1" 200 -
|
||||||
|
健康检查线程已启动
|
||||||
|
* Serving Flask app 'app'
|
||||||
|
* Debug mode: off
|
||||||
|
[31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
||||||
|
* Running on http://127.0.0.1:9519
|
||||||
|
[33mPress CTRL+C to quit[0m
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:08] "[31m[1mGET /api/admin/login/status HTTP/1.1[0m" 403 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:08] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:08] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:09] "[31m[1mGET /api/admin/login/status HTTP/1.1[0m" 403 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:09] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:09] "[31m[1mGET /api/admin/login/status HTTP/1.1[0m" 403 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:09] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:10] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:10] "[31m[1mGET /api/admin/login/status HTTP/1.1[0m" 403 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:10] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:10] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:11] "[31m[1mGET /api/admin/login/status HTTP/1.1[0m" 403 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:11] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:11] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:11] "[31m[1mGET /api/admin/login/status HTTP/1.1[0m" 403 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:11] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:11] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:12] "[31m[1mGET /api/admin/login/status HTTP/1.1[0m" 403 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:12] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:12] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:12] "[31m[1mGET /api/admin/login/status HTTP/1.1[0m" 403 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:13] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:13] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:13] "[31m[1mGET /api/admin/login/status HTTP/1.1[0m" 403 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:13] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:13] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:14] "[31m[1mGET /api/admin/login/status HTTP/1.1[0m" 403 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:14] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:14] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:15] "[31m[1mGET /api/admin/login/status HTTP/1.1[0m" 403 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:15] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:15] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:15] "[31m[1mGET /api/admin/login/status HTTP/1.1[0m" 403 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:15] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:16] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:16] "[31m[1mGET /api/admin/login/status HTTP/1.1[0m" 403 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:16] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:16] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:17] "[31m[1mGET /api/admin/login/status HTTP/1.1[0m" 403 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:21] "[32mPOST /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:21] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:21] "[31m[1mGET /api/admin/login/status HTTP/1.1[0m" 403 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:22] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:22] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:22] "[31m[1mGET /api/admin/login/status HTTP/1.1[0m" 403 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:22] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:23] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:23] "[31m[1mGET /api/admin/login/status HTTP/1.1[0m" 403 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:23] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:23] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:23] "[31m[1mGET /api/admin/login/status HTTP/1.1[0m" 403 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:24] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:24] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:24] "[31m[1mGET /api/admin/login/status HTTP/1.1[0m" 403 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:24] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:25] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:25] "[31m[1mGET /api/admin/login/status HTTP/1.1[0m" 403 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:25] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:25] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:25] "[31m[1mGET /api/admin/login/status HTTP/1.1[0m" 403 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:26] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:26] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:26] "[31m[1mGET /api/admin/login/status HTTP/1.1[0m" 403 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:26] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:27] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:27] "[31m[1mGET /api/admin/login/status HTTP/1.1[0m" 403 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:27] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:27] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:29] "[31m[1mGET /api/admin/login/status HTTP/1.1[0m" 403 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:30] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:30] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:30] "[31m[1mGET /api/admin/login/status HTTP/1.1[0m" 403 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:30] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:31] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:31] "[31m[1mGET /api/admin/login/status HTTP/1.1[0m" 403 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:31] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:31] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:32] "[31m[1mGET /api/admin/login/status HTTP/1.1[0m" 403 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:35] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:35] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:35] "[31m[1mGET /api/admin/login/status HTTP/1.1[0m" 403 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:36] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:36] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:36] "[31m[1mGET /api/admin/login/status HTTP/1.1[0m" 403 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:36] "[32mGET /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:18:51] "[31m[1mPOST /api/admin/change-password HTTP/1.1[0m" 400 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:19:03] "POST /api/admin/change-password HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:19:04] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:19:05] "GET /api/admin/login/status HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:19:05] "GET /api/admin/categories HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:19:05] "GET /api/admin/services HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:19:10] "[32mGET /admin/logout HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:19:10] "GET /admin/login HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:19:13] "[32mPOST /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:19:13] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:19:13] "GET /api/admin/login/status HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:19:13] "GET /api/admin/services HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:19:13] "GET /api/admin/categories HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:19:36] "GET /api/admin/backup/local HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:20:43] "GET / HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:20:43] "GET /api/categories?t=1770938442822 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:20:43] "GET /api/services?t=1770938442823 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:20:46] "POST /api/admin/health-check HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:20:58] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:20:58] "GET /api/admin/login/status HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:20:58] "[33mGET /favicon.ico HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:20:58] "GET /api/admin/categories HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:20:58] "GET /api/admin/services HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:21:02] "GET / HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:21:02] "GET /api/categories?t=1770938461825 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:21:02] "GET /api/services?t=1770938461826 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:21:05] "POST /api/admin/health-check HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:22:45] "GET /api/services?t=1770938564541 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:22:45] "GET /api/services?t=1770938564541 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:22:46] "GET / HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:22:47] "GET /api/categories?t=1770938566122 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:22:47] "GET /api/services?t=1770938566123 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:22:48] "POST /api/admin/health-check HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:22:48] "POST /api/admin/health-check HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:22:50] "POST /api/admin/health-check HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:23:08] "GET /api/services?t=1770938587200 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:23:11] "POST /api/admin/health-check HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:23:26] "GET /api/services?t=1770938605889 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:23:26] "GET /api/services?t=1770938605888 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:23:28] "GET / HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:23:28] "GET /api/categories?t=1770938607428 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:23:28] "GET /api/services?t=1770938607429 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:23:29] "POST /api/admin/health-check HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:23:29] "POST /api/admin/health-check HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:23:30] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:23:30] "GET /api/admin/login/status HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:23:30] "GET /api/admin/services HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:23:30] "GET /api/admin/categories HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:23:31] "POST /api/admin/health-check HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:23:40] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:23:41] "GET /api/admin/login/status HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:23:41] "GET /api/admin/categories HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:23:41] "GET /api/admin/services HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:23:46] "GET /api/services?t=1770938625331 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:23:46] "GET /api/services?t=1770938625331 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:23:48] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:23:48] "GET /api/admin/login/status HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:23:48] "GET /api/admin/categories HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:23:48] "GET /api/admin/services HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:23:49] "POST /api/admin/health-check HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:23:50] "POST /api/admin/health-check HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:23:56] "POST /api/admin/backup/webdav HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:24:02] "POST /api/admin/backup/webdav HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:24:04] "[32mGET /admin/logout HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:24:04] "GET /admin/login HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:24:06] "[32mPOST /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:24:06] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:24:06] "GET /api/admin/login/status HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:24:07] "GET /api/admin/services HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:24:07] "GET /api/admin/categories HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:24:14] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:24:14] "GET /api/admin/login/status HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:24:14] "GET /api/admin/services HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:24:14] "GET /api/admin/categories HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:24:15] "[32mGET /admin/logout HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:24:15] "GET /admin/login HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:24:43] "[32mPOST /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:24:43] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:24:44] "GET /api/admin/login/status HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:24:44] "GET /api/admin/services HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:24:44] "GET /api/admin/categories HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:24:48] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:24:49] "GET /api/admin/login/status HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:24:49] "GET /api/admin/services HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:24:49] "GET /api/admin/categories HTTP/1.1" 200 -
|
||||||
|
健康检查线程已启动
|
||||||
|
* Serving Flask app 'app'
|
||||||
|
* Debug mode: off
|
||||||
|
[31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
||||||
|
* Running on http://127.0.0.1:9519
|
||||||
|
[33mPress CTRL+C to quit[0m
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:25:59] "POST /admin/login HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:25:59] "[31m[1mGET /api/admin/settings HTTP/1.1[0m" 401 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:26:59] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:27:00] "GET /api/admin/login/status?t=1770938819222 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:27:00] "GET /api/admin/categories?t=1770938819411 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:27:00] "GET /api/admin/services?t=1770938819410 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:27:03] "GET /api/admin/settings HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:27:12] "POST /api/admin/backup/test HTTP/1.1" 200 -
|
||||||
|
健康检查线程已启动
|
||||||
|
* Serving Flask app 'app'
|
||||||
|
* Debug mode: off
|
||||||
|
[31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
||||||
|
* Running on http://127.0.0.1:9519
|
||||||
|
[33mPress CTRL+C to quit[0m
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:29:24] "[32mGET /admin/logout HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:29:24] "GET /admin/login HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:29:30] "GET / HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:29:30] "GET /api/categories?t=1770938969582 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:29:30] "GET /api/services?t=1770938969585 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:29:30] "GET / HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:29:30] "GET /api/categories?t=1770938969951 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:29:30] "GET /api/services?t=1770938969952 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:29:31] "[33mPOST /api/admin/health-check HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:30:01] "GET /api/services?t=1770938999952 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:30:01] "[33mPOST /api/admin/health-check HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:30:19] "[32mGET /admin HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:30:19] "GET /admin/login HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:30:22] "[32mPOST /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:30:22] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:30:22] "GET /api/admin/login/status?t=1770939021569 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:30:22] "[33mGET /api/admin/categories?t=1770939021744 HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:30:22] "GET /api/admin/services?t=1770939021744 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:30:28] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:30:29] "GET /api/admin/login/status?t=1770939028064 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:30:29] "[33mGET /api/admin/categories?t=1770939028240 HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:30:29] "GET /api/admin/services?t=1770939028240 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:30:32] "GET /api/admin/settings HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:31:33] "GET / HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:31:33] "[33mGET /favicon.ico HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:31:33] "GET /api/services?t=1770939092858 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:31:33] "GET /api/categories?t=1770939092857 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:31:34] "[33mPOST /api/admin/health-check HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:32:04] "GET /api/services?t=1770939123679 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:32:04] "[33mPOST /api/admin/health-check HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:32:19] "POST /api/admin/backup/test HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:32:26] "POST /api/admin/settings HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:32:28] "[33mPOST /api/admin/backup/webdav HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:32:30] "[33mPOST /api/admin/backup/webdav HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:32:33] "POST /api/admin/backup/test HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:32:36] "POST /api/admin/backup/test HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:32:39] "[33mPOST /api/admin/backup/webdav HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:32:44] "GET /api/admin/settings HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:32:50] "[33mPOST /api/admin/backup/webdav HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:32:52] "[33mPOST /api/admin/backup/webdav HTTP/1.1[0m" 404 -
|
||||||
|
健康检查线程已启动
|
||||||
|
* Serving Flask app 'app'
|
||||||
|
* Debug mode: off
|
||||||
|
[31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
||||||
|
* Running on http://127.0.0.1:9519
|
||||||
|
[33mPress CTRL+C to quit[0m
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:36:29] "[33mGET /admin/logout HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:36:31] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:36:32] "GET /api/admin/login/status?t=1770939391262 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:36:32] "[33mGET /api/admin/categories?t=1770939391464 HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:36:32] "GET /api/admin/services?t=1770939391464 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:36:33] "GET /admin/login HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:36:35] "GET /api/services?t=1770939394246 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:36:35] "GET /api/categories?t=1770939394246 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:36:35] "[33mPOST /api/admin/health-check HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:36:37] "GET / HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:36:37] "GET /api/services?t=1770939396717 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:36:37] "GET /api/categories?t=1770939396717 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:36:37] "[33mPOST /api/admin/health-check HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:36:43] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:36:43] "GET /api/admin/login/status?t=1770939402460 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:36:43] "[33mGET /api/admin/categories?t=1770939402645 HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:36:43] "GET /api/admin/services?t=1770939402645 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:36:46] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:36:46] "GET /api/admin/login/status?t=1770939405815 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:36:47] "[33mGET /api/admin/categories?t=1770939406008 HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:36:47] "GET /api/admin/services?t=1770939406008 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:36:51] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:36:51] "GET /api/admin/login/status?t=1770939410341 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:36:51] "[33mGET /api/admin/categories?t=1770939410535 HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:36:51] "GET /api/admin/services?t=1770939410535 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:36:52] "GET / HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:36:52] "GET /api/categories?t=1770939411561 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:36:52] "GET /api/services?t=1770939411562 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:36:52] "[33mPOST /api/admin/health-check HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:36:54] "[33mGET /admin/logout HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:36:59] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:36:59] "GET /api/admin/login/status?t=1770939418688 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:36:59] "GET /api/admin/services?t=1770939418881 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:36:59] "[33mGET /api/admin/categories?t=1770939418881 HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:37:00] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:37:01] "GET /api/admin/login/status?t=1770939420074 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:37:01] "[33mGET /api/admin/categories?t=1770939420267 HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:37:01] "GET /api/admin/services?t=1770939420267 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:37:03] "GET /api/admin/settings HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:37:04] "GET /api/admin/backup/list HTTP/1.1" 200 -
|
||||||
|
[2026-02-13 07:37:18,512] INFO: MKCOL https://chfs.ouaone.top/webdav: 405
|
||||||
|
[2026-02-13 07:37:18,872] INFO: MKCOL https://chfs.ouaone.top/webdav/openclaw: 405
|
||||||
|
[2026-02-13 07:37:19,217] INFO: MKCOL https://chfs.ouaone.top/webdav/openclaw/backup: 405
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:37:19] "POST /api/admin/backup/webdav HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:37:22] "[33mPOST /api/admin/backup/test HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:37:33] "[33mPOST /api/admin/backup/test HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:37:35] "[33mPOST /api/admin/backup/test HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:37:36] "[33mPOST /api/admin/backup/test HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:37:42] "[33mPOST /api/admin/backup/test HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:37:45] "POST /api/admin/settings HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:37:48] "[33mPOST /api/admin/backup/test HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:38:07] "[33mPOST /api/admin/backup/test HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:38:41] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:38:41] "GET /api/admin/login/status?t=1770939520618 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:38:41] "[33mGET /api/admin/categories?t=1770939520785 HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:38:41] "GET /api/admin/services?t=1770939520785 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:38:43] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:38:43] "GET /api/admin/login/status?t=1770939522798 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:38:43] "[33mGET /api/admin/categories?t=1770939522972 HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:38:43] "GET /api/admin/services?t=1770939522971 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:38:44] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:38:45] "GET /api/admin/login/status?t=1770939524210 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:38:45] "[33mGET /api/admin/categories?t=1770939524385 HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:38:45] "GET /api/admin/services?t=1770939524384 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:38:46] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:38:46] "GET /api/admin/login/status?t=1770939525452 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:38:46] "[33mGET /api/admin/categories?t=1770939525629 HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:38:46] "GET /api/admin/services?t=1770939525629 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:38:48] "GET /api/admin/settings HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:38:49] "GET /api/admin/backup/list HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:38:50] "[33mPOST /api/admin/backup/test HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:38:59] "[33mPOST /api/admin/backup/test HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:39:03] "POST /api/admin/settings HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:39:04] "[33mPOST /api/admin/backup/test HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:40:18] "GET /api/admin/settings HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:40:18] "GET /api/admin/backup/list HTTP/1.1" 200 -
|
||||||
|
健康检查线程已启动
|
||||||
|
* Serving Flask app 'app'
|
||||||
|
* Debug mode: off
|
||||||
|
[31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
||||||
|
* Running on http://127.0.0.1:9519
|
||||||
|
[33mPress CTRL+C to quit[0m
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:41:09] "POST /admin/login HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:41:09] "[31m[1mGET /api/admin/services?t=1 HTTP/1.1[0m" 401 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:42:19] "[33mGET /admin/logout HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:43:07] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:43:07] "GET /api/admin/login/status?t=1770939786385 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:43:07] "GET /api/admin/services?t=1770939786608 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:43:07] "GET /api/admin/categories?t=1770939786609 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:43:08] "GET / HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:43:08] "GET /api/categories?t=1770939787381 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:43:08] "GET /api/services?t=1770939787382 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:43:08] "[33mPOST /api/admin/health-check HTTP/1.1[0m" 404 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:43:14] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:43:14] "GET /api/admin/login/status?t=1770939793949 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:43:15] "GET /api/admin/services?t=1770939794178 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:43:15] "GET /api/admin/categories?t=1770939794178 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:43:18] "GET /api/admin/settings HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:43:19] "GET /api/admin/backup/list HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:43:20] "POST /api/admin/backup/test HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:43:24] "POST /api/admin/settings HTTP/1.1" 200 -
|
||||||
|
[2026-02-13 07:43:26,125] INFO: MKCOL https://chfs.ouaone.top/webdav: 405
|
||||||
|
[2026-02-13 07:43:26,484] INFO: MKCOL https://chfs.ouaone.top/webdav/openclaw: 405
|
||||||
|
[2026-02-13 07:43:26,850] INFO: MKCOL https://chfs.ouaone.top/webdav/openclaw/backup: 405
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:43:27] "POST /api/admin/backup/webdav HTTP/1.1" 200 -
|
||||||
|
[2026-02-13 07:43:31,197] INFO: MKCOL https://chfs.ouaone.top/webdav: 405
|
||||||
|
[2026-02-13 07:43:31,555] INFO: MKCOL https://chfs.ouaone.top/webdav/openclaw: 405
|
||||||
|
[2026-02-13 07:43:31,924] INFO: MKCOL https://chfs.ouaone.top/webdav/openclaw/backup: 405
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:43:32] "POST /api/admin/backup/webdav HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:43:38] "POST /api/admin/backup/test HTTP/1.1" 200 -
|
||||||
|
[2026-02-13 07:43:40,709] INFO: MKCOL https://chfs.ouaone.top/webdav: 405
|
||||||
|
[2026-02-13 07:43:41,062] INFO: MKCOL https://chfs.ouaone.top/webdav/openclaw: 405
|
||||||
|
[2026-02-13 07:43:41,419] INFO: MKCOL https://chfs.ouaone.top/webdav/openclaw/backup: 405
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:43:42] "POST /api/admin/backup/webdav HTTP/1.1" 200 -
|
||||||
|
健康检查线程已启动
|
||||||
|
* Serving Flask app 'app'
|
||||||
|
* Debug mode: off
|
||||||
|
[31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
||||||
|
* Running on http://127.0.0.1:9519
|
||||||
|
[33mPress CTRL+C to quit[0m
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:45:04] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:45:04] "GET /api/admin/login/status?t=1770939903891 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:45:05] "GET /api/admin/services?t=1770939904083 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:45:05] "GET /api/admin/categories?t=1770939904083 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:45:06] "[32mGET /admin/logout HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:45:07] "GET /admin/login HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:45:13] "GET / HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:45:13] "GET /api/categories?t=1770939912831 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:45:13] "GET /api/services?t=1770939912834 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:45:13] "GET / HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:45:14] "GET /api/categories?t=1770939913206 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:45:14] "GET /api/services?t=1770939913206 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:45:14] "[31m[1mPOST /api/admin/health-check HTTP/1.1[0m" 401 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:45:16] "[32mGET /admin HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:45:16] "GET /admin/login HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:45:19] "[32mPOST /admin/login HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:45:19] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:45:19] "GET /api/admin/login/status?t=1770939918455 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:45:19] "GET /api/admin/services?t=1770939918638 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:45:19] "GET /api/admin/categories?t=1770939918638 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:45:21] "GET /api/admin/settings HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:45:22] "GET /api/admin/backup/list HTTP/1.1" 200 -
|
||||||
|
[2026-02-13 07:45:33,281] INFO: MKCOL https://chfs.ouaone.top/webdav: 405
|
||||||
|
[2026-02-13 07:45:33,644] INFO: MKCOL https://chfs.ouaone.top/webdav/openclaw: 405
|
||||||
|
[2026-02-13 07:45:33,997] INFO: MKCOL https://chfs.ouaone.top/webdav/openclaw/backup: 405
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:45:34] "POST /api/admin/backup/webdav HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:45:44] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:45:44] "GET /api/admin/login/status?t=1770939943362 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:45:44] "GET /api/admin/categories?t=1770939943545 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:45:44] "GET /api/admin/services?t=1770939943544 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:45:46] "GET /api/admin/settings HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:45:47] "GET /api/admin/backup/list HTTP/1.1" 200 -
|
||||||
|
[2026-02-13 07:46:06,691] INFO: MKCOL https://chfs.ouaone.top/webdav: 405
|
||||||
|
[2026-02-13 07:46:07,072] INFO: MKCOL https://chfs.ouaone.top/webdav/openclaw: 405
|
||||||
|
[2026-02-13 07:46:07,448] INFO: MKCOL https://chfs.ouaone.top/webdav/openclaw/backup: 405
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:46:08] "POST /api/admin/backup/webdav HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:46:11] "GET /api/admin/settings HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:46:12] "GET /api/admin/backup/list HTTP/1.1" 200 -
|
||||||
|
健康检查线程已启动
|
||||||
|
* Serving Flask app 'app'
|
||||||
|
* Debug mode: off
|
||||||
|
[31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
||||||
|
* Running on http://127.0.0.1:9519
|
||||||
|
[33mPress CTRL+C to quit[0m
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:48:28] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:48:28] "GET /api/admin/login/status?t=1770940107816 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:48:29] "GET /api/admin/services?t=1770940108062 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:48:29] "GET /api/admin/categories?t=1770940108063 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:48:31] "GET /api/admin/settings HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:48:31] "GET /api/admin/backup/list HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:48:33] "POST /api/admin/backup/test HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:48:35] "POST /api/admin/settings HTTP/1.1" 200 -
|
||||||
|
[2026-02-13 07:48:38,326] INFO: MKCOL https://chfs.ouaone.top/webdav: 405
|
||||||
|
[2026-02-13 07:48:38,700] INFO: MKCOL https://chfs.ouaone.top/webdav/openclaw: 405
|
||||||
|
[2026-02-13 07:48:39,044] INFO: MKCOL https://chfs.ouaone.top/webdav/openclaw/backup: 405
|
||||||
|
[2026-02-13 07:48:39,425] INFO: MKCOL https://chfs.ouaone.top/webdav/openclaw/backup/tonav: 201
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:48:40] "POST /api/admin/backup/webdav HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:48:43] "GET /api/admin/settings HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:48:44] "GET /api/admin/backup/list HTTP/1.1" 200 -
|
||||||
|
健康检查线程已启动
|
||||||
|
* Serving Flask app 'app'
|
||||||
|
* Debug mode: off
|
||||||
|
[31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
||||||
|
* Running on http://127.0.0.1:9519
|
||||||
|
[33mPress CTRL+C to quit[0m
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:52:08] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:52:08] "GET /api/admin/login/status?t=1770940327554 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:52:08] "GET /api/admin/categories?t=1770940327792 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:52:08] "GET /api/admin/services?t=1770940327792 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:52:10] "GET /api/admin/settings HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:52:11] "GET /api/admin/backup/list HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:52:12] "POST /api/admin/backup/test HTTP/1.1" 200 -
|
||||||
|
[2026-02-13 07:52:15,643] INFO: MKCOL https://chfs.ouaone.top/webdav: 405
|
||||||
|
[2026-02-13 07:52:16,033] INFO: MKCOL https://chfs.ouaone.top/webdav/openclaw: 405
|
||||||
|
[2026-02-13 07:52:16,402] INFO: MKCOL https://chfs.ouaone.top/webdav/openclaw/backup: 405
|
||||||
|
[2026-02-13 07:52:16,786] INFO: MKCOL https://chfs.ouaone.top/webdav/openclaw/backup/tonav: 405
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:52:17] "POST /api/admin/backup/webdav HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:52:20] "GET /api/admin/backup/list HTTP/1.1" 200 -
|
||||||
|
健康检查线程已启动
|
||||||
|
* Serving Flask app 'app'
|
||||||
|
* Debug mode: off
|
||||||
|
[31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
||||||
|
* Running on http://127.0.0.1:9519
|
||||||
|
[33mPress CTRL+C to quit[0m
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:55:48] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:55:48] "GET /api/admin/login/status?t=1770940547329 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:55:48] "GET /api/admin/services?t=1770940547520 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:55:48] "GET /api/admin/categories?t=1770940547521 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:55:51] "GET /admin/services HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:55:51] "GET /api/admin/services?t=1770940550299 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:55:54] "GET /api/admin/categories HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:56:03] "GET /admin HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:56:03] "GET /api/admin/login/status?t=1770940562797 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:56:04] "GET /api/admin/categories?t=1770940563003 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:56:04] "GET /api/admin/services?t=1770940563002 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:56:06] "GET /api/admin/settings HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:56:06] "GET /api/admin/backup/list HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:56:10] "GET /api/admin/settings HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:56:10] "GET /api/admin/backup/list HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:56:16] "GET /api/admin/settings HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:56:16] "GET /api/admin/backup/list HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:56:18] "GET /api/admin/settings HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:56:19] "GET /api/admin/backup/list HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:56:34] "GET / HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:56:34] "GET /api/categories?t=1770940593746 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:56:34] "GET /api/services?t=1770940593747 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:56:38] "POST /api/admin/health-check HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:56:44] "[32mGET /visit/5 HTTP/1.1[0m" 302 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:56:47] "GET /api/services?t=1770940606354 HTTP/1.1" 200 -
|
||||||
|
127.0.0.1 - - [13/Feb/2026 07:56:50] "POST /api/admin/health-check HTTP/1.1" 200 -
|
||||||
|
|||||||
Reference in New Issue
Block a user