mirror of
https://github.com/zhinianboke/xianyu-auto-reply.git
synced 2025-08-30 01:27:35 +08:00
优化结构
This commit is contained in:
parent
5b2a991f41
commit
a525675e73
200
.gitignore
vendored
200
.gitignore
vendored
@ -105,3 +105,203 @@ keywords_sample.xlsx
|
|||||||
*.tar.gz
|
*.tar.gz
|
||||||
*.rar
|
*.rar
|
||||||
*.7z
|
*.7z
|
||||||
|
|
||||||
|
# ==================== 新增忽略项 ====================
|
||||||
|
# Python 字节码和缓存
|
||||||
|
*.pyc
|
||||||
|
*.pyo
|
||||||
|
*.pyd
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# 分发/打包
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# 单元测试/覆盖率报告
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
.python-version
|
||||||
|
|
||||||
|
# pipenv
|
||||||
|
Pipfile.lock
|
||||||
|
|
||||||
|
# PEP 582
|
||||||
|
__pypackages__/
|
||||||
|
|
||||||
|
# Celery
|
||||||
|
celerybeat-schedule
|
||||||
|
celerybeat.pid
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
# Pyre type checker
|
||||||
|
.pyre/
|
||||||
|
|
||||||
|
# ==================== 项目特定新增 ====================
|
||||||
|
# 环境变量文件
|
||||||
|
.env.example
|
||||||
|
.env.*.example
|
||||||
|
|
||||||
|
# 数据库文件
|
||||||
|
*.db-journal
|
||||||
|
*.db-wal
|
||||||
|
*.db-shm
|
||||||
|
|
||||||
|
# 临时文件和缓存
|
||||||
|
*.cache
|
||||||
|
.cache/
|
||||||
|
cache/
|
||||||
|
|
||||||
|
# 编辑器临时文件
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*.tmp
|
||||||
|
*~
|
||||||
|
.#*
|
||||||
|
|
||||||
|
# 系统文件
|
||||||
|
.DS_Store
|
||||||
|
.DS_Store?
|
||||||
|
._*
|
||||||
|
.Spotlight-V100
|
||||||
|
.Trashes
|
||||||
|
ehthumbs.db
|
||||||
|
Thumbs.db
|
||||||
|
desktop.ini
|
||||||
|
|
||||||
|
# 文档生成
|
||||||
|
docs/_build/
|
||||||
|
docs/build/
|
||||||
|
|
||||||
|
# 密钥和证书
|
||||||
|
*.key
|
||||||
|
*.pem
|
||||||
|
*.crt
|
||||||
|
*.cert
|
||||||
|
*.p12
|
||||||
|
*.pfx
|
||||||
|
|
||||||
|
# 配置文件备份
|
||||||
|
*.conf.bak
|
||||||
|
*.config.bak
|
||||||
|
|
||||||
|
# 运行时文件
|
||||||
|
*.pid
|
||||||
|
*.sock
|
||||||
|
|
||||||
|
# 调试文件
|
||||||
|
debug.log
|
||||||
|
*.debug
|
||||||
|
|
||||||
|
# 性能分析文件
|
||||||
|
*.prof
|
||||||
|
|
||||||
|
# 本地开发文件
|
||||||
|
local/
|
||||||
|
.local/
|
||||||
|
|
||||||
|
# Docker相关
|
||||||
|
.dockerignore.bak
|
||||||
|
docker-compose.override.yml
|
||||||
|
|
||||||
|
# 版本控制
|
||||||
|
.svn/
|
||||||
|
.hg/
|
||||||
|
.bzr/
|
||||||
|
|
||||||
|
# 包管理器
|
||||||
|
node_modules/
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
package-lock.json
|
||||||
|
yarn.lock
|
||||||
|
|
||||||
|
# 前端构建
|
||||||
|
dist/
|
||||||
|
build/
|
||||||
|
.next/
|
||||||
|
.nuxt/
|
||||||
|
.vuepress/dist
|
||||||
|
|
||||||
|
# 移动端
|
||||||
|
*.apk
|
||||||
|
*.ipa
|
||||||
|
*.app
|
||||||
|
|
||||||
|
# 数据文件
|
||||||
|
*.csv.bak
|
||||||
|
*.json.bak
|
||||||
|
*.xml.bak
|
||||||
|
|
||||||
|
# 媒体文件缓存
|
||||||
|
*.mp4.cache
|
||||||
|
*.mp3.cache
|
||||||
|
*.wav.cache
|
||||||
|
*.avi.cache
|
||||||
|
|
||||||
|
# AI模型文件
|
||||||
|
*.model
|
||||||
|
*.weights
|
||||||
|
*.h5
|
||||||
|
*.pb
|
||||||
|
|
||||||
|
# 大文件
|
||||||
|
*.iso
|
||||||
|
*.dmg
|
||||||
|
*.img
|
48
README.md
48
README.md
@ -25,12 +25,13 @@
|
|||||||
|
|
||||||
### 🤖 智能回复系统
|
### 🤖 智能回复系统
|
||||||
- **关键词匹配** - 支持精确关键词匹配回复
|
- **关键词匹配** - 支持精确关键词匹配回复
|
||||||
- **商品专用回复** - 支持为特定商品设置专用关键词回复
|
- **指定商品回复** - 支持为特定商品设置专门的回复内容,优先级最高
|
||||||
|
- **商品专用关键词** - 支持为特定商品设置专用关键词回复
|
||||||
- **通用关键词** - 支持全局通用关键词,适用于所有商品
|
- **通用关键词** - 支持全局通用关键词,适用于所有商品
|
||||||
- **批量导入导出** - 支持Excel格式的关键词批量导入导出
|
- **批量导入导出** - 支持Excel格式的关键词批量导入导出
|
||||||
- **AI智能回复** - 集成OpenAI API,支持上下文理解
|
- **AI智能回复** - 集成OpenAI API,支持上下文理解
|
||||||
- **变量替换** - 回复内容支持动态变量(用户名、商品信息等)
|
- **变量替换** - 回复内容支持动态变量(用户名、商品信息、商品ID等)
|
||||||
- **优先级策略** - 商品专用关键词 > 通用关键词 > AI回复
|
- **优先级策略** - 指定商品回复 > 商品专用关键词 > 通用关键词 > 默认回复 > AI回复
|
||||||
|
|
||||||
### 🚚 自动发货功能
|
### 🚚 自动发货功能
|
||||||
- **智能匹配** - 基于商品信息自动匹配发货规则
|
- **智能匹配** - 基于商品信息自动匹配发货规则
|
||||||
@ -41,8 +42,9 @@
|
|||||||
- **防重复发货** - 智能防重复机制,避免重复发货
|
- **防重复发货** - 智能防重复机制,避免重复发货
|
||||||
- **多种发货方式** - 支持固定文字、批量数据、API调用、图片发货等方式
|
- **多种发货方式** - 支持固定文字、批量数据、API调用、图片发货等方式
|
||||||
- **图片发货** - 支持上传图片并自动发送给买家,图片自动上传到CDN
|
- **图片发货** - 支持上传图片并自动发送给买家,图片自动上传到CDN
|
||||||
- **自动确认发货** - 检测到付款后自动调用闲鱼API确认发货
|
- **自动确认发货** - 检测到付款后自动调用闲鱼API确认发货,支持锁机制防并发
|
||||||
- **防重复确认** - 智能防重复确认机制,避免重复API调用
|
- **防重复确认** - 智能防重复确认机制,避免重复API调用
|
||||||
|
- **订单详情缓存** - 订单详情获取支持数据库缓存,大幅提升性能
|
||||||
- **发货统计** - 完整的发货记录和统计功能
|
- **发货统计** - 完整的发货记录和统计功能
|
||||||
|
|
||||||
### 🛍️ 商品管理
|
### 🛍️ 商品管理
|
||||||
@ -359,31 +361,31 @@ python Start.py
|
|||||||
## 📁 核心文件功能说明
|
## 📁 核心文件功能说明
|
||||||
|
|
||||||
### 🚀 核心启动模块
|
### 🚀 核心启动模块
|
||||||
- **`Start.py`** - 项目启动入口,初始化CookieManager和FastAPI服务,从数据库加载账号任务并启动后台API服务
|
- **`Start.py`** - 项目启动入口,初始化CookieManager和FastAPI服务,从数据库加载账号任务并启动后台API服务,支持环境变量配置
|
||||||
- **`XianyuAutoAsync.py`** - 闲鱼WebSocket连接核心,处理消息收发、自动回复、自动发货、商品信息收集
|
- **`XianyuAutoAsync.py`** - 闲鱼WebSocket连接核心,处理消息收发、自动回复、指定商品回复、自动发货、商品信息收集、AI回复
|
||||||
- **`reply_server.py`** - FastAPI Web服务器,提供完整的管理界面和RESTful API接口,支持多用户系统
|
- **`reply_server.py`** - FastAPI Web服务器,提供完整的管理界面和RESTful API接口,支持多用户系统、JWT认证、权限管理
|
||||||
- **`cookie_manager.py`** - 多账号Cookie管理器,负责账号任务的启动、停止、状态管理和线程安全操作
|
- **`cookie_manager.py`** - 多账号Cookie管理器,负责账号任务的启动、停止、状态管理和线程安全操作,支持数据库持久化
|
||||||
|
|
||||||
### 🗄️ 数据和配置管理
|
### 🗄️ 数据和配置管理
|
||||||
- **`db_manager.py`** - SQLite数据库管理器,支持多用户数据隔离、自动迁移、版本管理、完整的CRUD操作
|
- **`db_manager.py`** - SQLite数据库管理器,支持多用户数据隔离、自动迁移、版本管理、完整的CRUD操作、邮箱验证、系统设置
|
||||||
- **`config.py`** - 全局配置文件管理器,加载YAML配置和环境变量,提供配置项访问接口
|
- **`config.py`** - 全局配置文件管理器,加载YAML配置和环境变量,提供配置项访问接口,支持动态配置更新
|
||||||
- **`global_config.yml`** - 全局配置文件,包含WebSocket、API、自动回复、AI等所有系统配置项
|
- **`global_config.yml`** - 全局配置文件,包含WebSocket、API、自动回复、AI、通知等所有系统配置项
|
||||||
|
|
||||||
### 🤖 智能功能模块
|
### 🤖 智能功能模块
|
||||||
- **`ai_reply_engine.py`** - AI智能回复引擎,支持OpenAI、通义千问等多种AI模型,意图识别和上下文管理
|
- **`ai_reply_engine.py`** - AI智能回复引擎,支持OpenAI、通义千问等多种AI模型,意图识别、上下文管理、个性化回复
|
||||||
- **`secure_confirm_ultra.py`** - 自动确认发货模块,采用多层加密保护,调用闲鱼API确认发货状态
|
- **`secure_confirm_ultra.py`** - 自动确认发货模块,采用多层加密保护,调用闲鱼API确认发货状态,支持锁机制防并发
|
||||||
- **`secure_freeshipping_ultra.py`** - 自动免拼发货模块,支持批量处理、异常恢复和智能匹配
|
- **`secure_freeshipping_ultra.py`** - 自动免拼发货模块,支持批量处理、异常恢复、智能匹配、规格识别
|
||||||
- **`file_log_collector.py`** - 实时日志收集器,提供Web界面日志查看、搜索和管理功能
|
- **`file_log_collector.py`** - 实时日志收集器,提供Web界面日志查看、搜索、过滤、下载和管理功能
|
||||||
|
|
||||||
### 🛠️ 工具模块 (`utils/`)
|
### 🛠️ 工具模块 (`utils/`)
|
||||||
- **`xianyu_utils.py`** - 闲鱼API核心工具,包含加密算法、签名生成、数据解析、Cookie处理
|
- **`xianyu_utils.py`** - 闲鱼API核心工具,包含加密算法、签名生成、数据解析、Cookie处理、请求封装
|
||||||
- **`message_utils.py`** - 消息处理工具,格式化消息内容、变量替换、内容过滤和模板渲染
|
- **`message_utils.py`** - 消息处理工具,格式化消息内容、变量替换、内容过滤、模板渲染、表情处理
|
||||||
- **`ws_utils.py`** - WebSocket客户端封装,处理连接管理、心跳检测、重连机制和消息队列
|
- **`ws_utils.py`** - WebSocket客户端封装,处理连接管理、心跳检测、重连机制、消息队列、异常恢复
|
||||||
- **`qr_login.py`** - 二维码登录功能,生成登录二维码、状态检测、Cookie获取和验证
|
- **`qr_login.py`** - 二维码登录功能,生成登录二维码、状态检测、Cookie获取、验证、自动刷新
|
||||||
- **`item_search.py`** - 商品搜索功能,基于Playwright获取真实闲鱼商品数据,支持分页和过滤
|
- **`item_search.py`** - 商品搜索功能,基于Playwright获取真实闲鱼商品数据,支持分页、过滤、排序
|
||||||
- **`order_detail_fetcher.py`** - 订单详情获取工具,解析订单信息、买家信息、SKU详情,支持缓存优化
|
- **`order_detail_fetcher.py`** - 订单详情获取工具,解析订单信息、买家信息、SKU详情,支持缓存优化、锁机制
|
||||||
- **`image_utils.py`** - 图片处理工具,支持压缩、格式转换、尺寸调整、水印添加
|
- **`image_utils.py`** - 图片处理工具,支持压缩、格式转换、尺寸调整、水印添加、质量优化
|
||||||
- **`image_uploader.py`** - 图片上传工具,支持多种CDN服务商,自动压缩和格式优化
|
- **`image_uploader.py`** - 图片上传工具,支持多种CDN服务商、自动压缩、格式优化、批量上传
|
||||||
|
|
||||||
### 🌐 前端界面 (`static/`)
|
### 🌐 前端界面 (`static/`)
|
||||||
- **`index.html`** - 主管理界面,包含账号管理、关键词管理、系统监控、实时状态显示
|
- **`index.html`** - 主管理界面,包含账号管理、关键词管理、系统监控、实时状态显示
|
||||||
|
@ -1,171 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
检查用户凭据
|
|
||||||
"""
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
import hashlib
|
|
||||||
|
|
||||||
# 添加项目根目录到路径
|
|
||||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
|
||||||
|
|
||||||
from db_manager import db_manager
|
|
||||||
|
|
||||||
|
|
||||||
def check_users():
|
|
||||||
"""检查用户表中的用户信息"""
|
|
||||||
print("🔍 检查用户表中的用户信息")
|
|
||||||
print("=" * 50)
|
|
||||||
|
|
||||||
try:
|
|
||||||
cursor = db_manager.conn.cursor()
|
|
||||||
cursor.execute("SELECT id, username, password_hash, is_admin FROM users")
|
|
||||||
users = cursor.fetchall()
|
|
||||||
|
|
||||||
print(f"用户表中共有 {len(users)} 个用户:")
|
|
||||||
for user in users:
|
|
||||||
print(f" - 用户ID: {user[0]}")
|
|
||||||
print(f" 用户名: {user[1]}")
|
|
||||||
print(f" 密码哈希: {user[2][:20]}..." if user[2] else " 密码哈希: None")
|
|
||||||
print(f" 是否管理员: {user[3]}")
|
|
||||||
print()
|
|
||||||
|
|
||||||
# 测试密码验证
|
|
||||||
if users:
|
|
||||||
test_user = users[0]
|
|
||||||
username = test_user[1]
|
|
||||||
stored_hash = test_user[2]
|
|
||||||
|
|
||||||
print(f"🔐 测试用户 '{username}' 的密码验证:")
|
|
||||||
|
|
||||||
# 测试常见密码
|
|
||||||
test_passwords = ["admin123", "admin", "123456", "password"]
|
|
||||||
|
|
||||||
for password in test_passwords:
|
|
||||||
# 计算密码哈希
|
|
||||||
password_hash = hashlib.sha256(password.encode()).hexdigest()
|
|
||||||
|
|
||||||
if password_hash == stored_hash:
|
|
||||||
print(f"✅ 密码 '{password}' 匹配!")
|
|
||||||
return username, password
|
|
||||||
else:
|
|
||||||
print(f"❌ 密码 '{password}' 不匹配")
|
|
||||||
print(f" 计算哈希: {password_hash[:20]}...")
|
|
||||||
print(f" 存储哈希: {stored_hash[:20]}...")
|
|
||||||
|
|
||||||
print("⚠️ 没有找到匹配的密码")
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"❌ 检查用户失败: {e}")
|
|
||||||
|
|
||||||
return None, None
|
|
||||||
|
|
||||||
|
|
||||||
def test_login_with_correct_credentials():
|
|
||||||
"""使用正确的凭据测试登录"""
|
|
||||||
username, password = check_users()
|
|
||||||
|
|
||||||
if username and password:
|
|
||||||
print(f"\n🌐 使用正确凭据测试登录")
|
|
||||||
print("=" * 50)
|
|
||||||
|
|
||||||
import requests
|
|
||||||
|
|
||||||
try:
|
|
||||||
login_data = {
|
|
||||||
"username": username,
|
|
||||||
"password": password
|
|
||||||
}
|
|
||||||
response = requests.post("http://localhost:8080/login", json=login_data, timeout=10)
|
|
||||||
print(f"登录状态码: {response.status_code}")
|
|
||||||
print(f"登录响应: {response.text}")
|
|
||||||
|
|
||||||
if response.status_code == 200:
|
|
||||||
data = response.json()
|
|
||||||
if data.get('success'):
|
|
||||||
token = data.get('token') or data.get('access_token')
|
|
||||||
print(f"✅ 登录成功!Token: {token[:20]}..." if token else "✅ 登录成功但没有token")
|
|
||||||
|
|
||||||
if token:
|
|
||||||
# 测试cookies/details接口
|
|
||||||
headers = {"Authorization": f"Bearer {token}"}
|
|
||||||
response = requests.get("http://localhost:8080/cookies/details", headers=headers, timeout=10)
|
|
||||||
print(f"cookies/details状态码: {response.status_code}")
|
|
||||||
|
|
||||||
if response.status_code == 200:
|
|
||||||
details = response.json()
|
|
||||||
print(f"✅ 获取到 {len(details)} 个账号详情")
|
|
||||||
for detail in details:
|
|
||||||
print(f" - {detail['id']}: {'启用' if detail['enabled'] else '禁用'}")
|
|
||||||
else:
|
|
||||||
print(f"❌ 获取账号详情失败: {response.text}")
|
|
||||||
else:
|
|
||||||
print(f"❌ 登录失败: {data.get('message', '未知错误')}")
|
|
||||||
else:
|
|
||||||
print(f"❌ 登录请求失败: {response.status_code}")
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"❌ 登录测试失败: {e}")
|
|
||||||
|
|
||||||
|
|
||||||
def create_test_user():
|
|
||||||
"""创建测试用户"""
|
|
||||||
print(f"\n🔧 创建测试用户")
|
|
||||||
print("=" * 50)
|
|
||||||
|
|
||||||
try:
|
|
||||||
# 创建一个新的测试用户
|
|
||||||
test_username = "testuser"
|
|
||||||
test_password = "test123"
|
|
||||||
password_hash = hashlib.sha256(test_password.encode()).hexdigest()
|
|
||||||
|
|
||||||
cursor = db_manager.conn.cursor()
|
|
||||||
cursor.execute("""
|
|
||||||
INSERT OR REPLACE INTO users (username, password_hash, is_admin)
|
|
||||||
VALUES (?, ?, ?)
|
|
||||||
""", (test_username, password_hash, 1))
|
|
||||||
db_manager.conn.commit()
|
|
||||||
|
|
||||||
print(f"✅ 创建测试用户成功:")
|
|
||||||
print(f" 用户名: {test_username}")
|
|
||||||
print(f" 密码: {test_password}")
|
|
||||||
print(f" 密码哈希: {password_hash[:20]}...")
|
|
||||||
|
|
||||||
return test_username, test_password
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"❌ 创建测试用户失败: {e}")
|
|
||||||
return None, None
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
print("🚀 检查用户凭据和登录问题")
|
|
||||||
print("=" * 60)
|
|
||||||
|
|
||||||
# 检查现有用户
|
|
||||||
username, password = check_users()
|
|
||||||
|
|
||||||
if not username:
|
|
||||||
# 如果没有找到有效用户,创建一个测试用户
|
|
||||||
print("\n没有找到有效的用户凭据,创建测试用户...")
|
|
||||||
username, password = create_test_user()
|
|
||||||
|
|
||||||
if username and password:
|
|
||||||
# 使用正确凭据测试登录
|
|
||||||
test_login_with_correct_credentials()
|
|
||||||
|
|
||||||
print("\n" + "=" * 60)
|
|
||||||
print("🎯 检查完成!")
|
|
||||||
print("\n📋 总结:")
|
|
||||||
print("1. 检查了用户表中的用户信息")
|
|
||||||
print("2. 验证了密码哈希")
|
|
||||||
print("3. 测试了登录功能")
|
|
||||||
print("4. 测试了cookies/details接口")
|
|
||||||
|
|
||||||
if username and password:
|
|
||||||
print(f"\n✅ 可用的登录凭据:")
|
|
||||||
print(f" 用户名: {username}")
|
|
||||||
print(f" 密码: {password}")
|
|
||||||
print(f"\n请使用这些凭据登录管理后台测试账号下拉框功能")
|
|
@ -1,192 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
检查用户表结构
|
|
||||||
"""
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
import hashlib
|
|
||||||
|
|
||||||
# 添加项目根目录到路径
|
|
||||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
|
||||||
|
|
||||||
from db_manager import db_manager
|
|
||||||
|
|
||||||
|
|
||||||
def check_user_table_structure():
|
|
||||||
"""检查用户表结构"""
|
|
||||||
print("🔍 检查用户表结构")
|
|
||||||
print("=" * 50)
|
|
||||||
|
|
||||||
try:
|
|
||||||
cursor = db_manager.conn.cursor()
|
|
||||||
|
|
||||||
# 检查用户表是否存在
|
|
||||||
cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='users'")
|
|
||||||
table_exists = cursor.fetchone()
|
|
||||||
|
|
||||||
if table_exists:
|
|
||||||
print("✅ users表存在")
|
|
||||||
|
|
||||||
# 检查表结构
|
|
||||||
cursor.execute("PRAGMA table_info(users)")
|
|
||||||
columns = cursor.fetchall()
|
|
||||||
print("users表结构:")
|
|
||||||
for col in columns:
|
|
||||||
print(f" - {col[1]} ({col[2]}) - {'NOT NULL' if col[3] else 'NULL'} - {'PRIMARY KEY' if col[5] else ''}")
|
|
||||||
|
|
||||||
# 查看表中的数据
|
|
||||||
cursor.execute("SELECT * FROM users")
|
|
||||||
users = cursor.fetchall()
|
|
||||||
print(f"\nusers表中共有 {len(users)} 条记录:")
|
|
||||||
for i, user in enumerate(users):
|
|
||||||
print(f" 记录{i+1}: {user}")
|
|
||||||
|
|
||||||
else:
|
|
||||||
print("❌ users表不存在")
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"❌ 检查用户表失败: {e}")
|
|
||||||
|
|
||||||
|
|
||||||
def fix_user_table():
|
|
||||||
"""修复用户表"""
|
|
||||||
print("\n🔧 修复用户表")
|
|
||||||
print("=" * 50)
|
|
||||||
|
|
||||||
try:
|
|
||||||
cursor = db_manager.conn.cursor()
|
|
||||||
|
|
||||||
# 检查是否有is_admin列
|
|
||||||
cursor.execute("PRAGMA table_info(users)")
|
|
||||||
columns = cursor.fetchall()
|
|
||||||
column_names = [col[1] for col in columns]
|
|
||||||
|
|
||||||
if 'is_admin' not in column_names:
|
|
||||||
print("添加is_admin列...")
|
|
||||||
cursor.execute("ALTER TABLE users ADD COLUMN is_admin INTEGER DEFAULT 1")
|
|
||||||
db_manager.conn.commit()
|
|
||||||
print("✅ 添加is_admin列成功")
|
|
||||||
|
|
||||||
# 检查是否有用户数据
|
|
||||||
cursor.execute("SELECT COUNT(*) FROM users")
|
|
||||||
user_count = cursor.fetchone()[0]
|
|
||||||
|
|
||||||
if user_count == 0:
|
|
||||||
print("创建默认管理员用户...")
|
|
||||||
username = "admin"
|
|
||||||
password = "admin123"
|
|
||||||
password_hash = hashlib.sha256(password.encode()).hexdigest()
|
|
||||||
|
|
||||||
cursor.execute("""
|
|
||||||
INSERT INTO users (username, password_hash, is_admin)
|
|
||||||
VALUES (?, ?, ?)
|
|
||||||
""", (username, password_hash, 1))
|
|
||||||
db_manager.conn.commit()
|
|
||||||
|
|
||||||
print(f"✅ 创建默认用户成功:")
|
|
||||||
print(f" 用户名: {username}")
|
|
||||||
print(f" 密码: {password}")
|
|
||||||
|
|
||||||
return username, password
|
|
||||||
else:
|
|
||||||
# 获取第一个用户并重置密码
|
|
||||||
cursor.execute("SELECT username FROM users LIMIT 1")
|
|
||||||
username = cursor.fetchone()[0]
|
|
||||||
password = "admin123"
|
|
||||||
password_hash = hashlib.sha256(password.encode()).hexdigest()
|
|
||||||
|
|
||||||
cursor.execute("""
|
|
||||||
UPDATE users SET password_hash = ?, is_admin = 1
|
|
||||||
WHERE username = ?
|
|
||||||
""", (password_hash, username))
|
|
||||||
db_manager.conn.commit()
|
|
||||||
|
|
||||||
print(f"✅ 重置用户密码成功:")
|
|
||||||
print(f" 用户名: {username}")
|
|
||||||
print(f" 密码: {password}")
|
|
||||||
|
|
||||||
return username, password
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"❌ 修复用户表失败: {e}")
|
|
||||||
return None, None
|
|
||||||
|
|
||||||
|
|
||||||
def test_login_after_fix():
|
|
||||||
"""修复后测试登录"""
|
|
||||||
username, password = fix_user_table()
|
|
||||||
|
|
||||||
if username and password:
|
|
||||||
print(f"\n🌐 测试修复后的登录")
|
|
||||||
print("=" * 50)
|
|
||||||
|
|
||||||
import requests
|
|
||||||
|
|
||||||
try:
|
|
||||||
login_data = {
|
|
||||||
"username": username,
|
|
||||||
"password": password
|
|
||||||
}
|
|
||||||
response = requests.post("http://localhost:8080/login", json=login_data, timeout=10)
|
|
||||||
print(f"登录状态码: {response.status_code}")
|
|
||||||
|
|
||||||
if response.status_code == 200:
|
|
||||||
data = response.json()
|
|
||||||
print(f"登录响应: {data}")
|
|
||||||
|
|
||||||
if data.get('success'):
|
|
||||||
token = data.get('token') or data.get('access_token')
|
|
||||||
print(f"✅ 登录成功!")
|
|
||||||
|
|
||||||
if token:
|
|
||||||
print(f"Token: {token[:20]}...")
|
|
||||||
|
|
||||||
# 测试cookies/details接口
|
|
||||||
headers = {"Authorization": f"Bearer {token}"}
|
|
||||||
response = requests.get("http://localhost:8080/cookies/details", headers=headers, timeout=10)
|
|
||||||
print(f"cookies/details状态码: {response.status_code}")
|
|
||||||
|
|
||||||
if response.status_code == 200:
|
|
||||||
details = response.json()
|
|
||||||
print(f"✅ 获取到 {len(details)} 个账号详情")
|
|
||||||
|
|
||||||
if len(details) > 0:
|
|
||||||
print("🎉 账号下拉框应该有数据了!")
|
|
||||||
print("账号列表:")
|
|
||||||
for detail in details:
|
|
||||||
status = "🟢" if detail['enabled'] else "🔴"
|
|
||||||
print(f" {status} {detail['id']}")
|
|
||||||
else:
|
|
||||||
print("⚠️ 账号列表为空,但API接口正常")
|
|
||||||
else:
|
|
||||||
print(f"❌ 获取账号详情失败: {response.text}")
|
|
||||||
else:
|
|
||||||
print("⚠️ 登录成功但没有获取到token")
|
|
||||||
else:
|
|
||||||
print(f"❌ 登录失败: {data.get('message', '未知错误')}")
|
|
||||||
else:
|
|
||||||
print(f"❌ 登录请求失败: {response.status_code} - {response.text}")
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"❌ 登录测试失败: {e}")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
print("🚀 检查和修复用户表")
|
|
||||||
print("=" * 60)
|
|
||||||
|
|
||||||
# 检查用户表结构
|
|
||||||
check_user_table_structure()
|
|
||||||
|
|
||||||
# 修复用户表并测试登录
|
|
||||||
test_login_after_fix()
|
|
||||||
|
|
||||||
print("\n" + "=" * 60)
|
|
||||||
print("🎯 修复完成!")
|
|
||||||
print("\n📋 现在可以:")
|
|
||||||
print("1. 使用 admin/admin123 登录管理后台")
|
|
||||||
print("2. 进入指定商品回复界面")
|
|
||||||
print("3. 检查账号下拉框是否有数据")
|
|
||||||
print("4. 如果仍然没有数据,请检查浏览器开发者工具")
|
|
@ -57,6 +57,9 @@ openpyxl>=3.1.0
|
|||||||
# ==================== 邮件发送 ====================
|
# ==================== 邮件发送 ====================
|
||||||
email-validator>=2.0.0
|
email-validator>=2.0.0
|
||||||
|
|
||||||
|
# ==================== 数据处理和验证 ====================
|
||||||
|
xlsxwriter>=3.1.0
|
||||||
|
|
||||||
# ==================== 说明 ====================
|
# ==================== 说明 ====================
|
||||||
# 以下模块是Python内置模块,无需安装:
|
# 以下模块是Python内置模块,无需安装:
|
||||||
# sqlite3, json, base64, hashlib, hmac, time, datetime, os, sys, re, urllib
|
# sqlite3, json, base64, hashlib, hmac, time, datetime, os, sys, re, urllib
|
||||||
@ -64,3 +67,4 @@ email-validator>=2.0.0
|
|||||||
# collections, itertools, functools, copy, pickle, gzip, zipfile, shutil
|
# collections, itertools, functools, copy, pickle, gzip, zipfile, shutil
|
||||||
# tempfile, io, csv, xml, html, http, socket, ssl, subprocess, signal
|
# tempfile, io, csv, xml, html, http, socket, ssl, subprocess, signal
|
||||||
# inspect, ast, enum, math, decimal, array, queue, contextlib, warnings
|
# inspect, ast, enum, math, decimal, array, queue, contextlib, warnings
|
||||||
|
# typing, dataclasses, weakref, gc, platform, stat, glob, fnmatch
|
Loading…
x
Reference in New Issue
Block a user