This commit is contained in:
“shengyudong”
2026-01-06 14:18:39 +08:00
commit 5a384b694e
10345 changed files with 2050918 additions and 0 deletions

298
release/32/auth_routes.py Normal file
View File

@@ -0,0 +1,298 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
认证接口
"""
from flask import Blueprint, request, jsonify
import logging
from datetime import datetime
from auth_utils import AuthUtils
from database_config import get_db_manager, format_datetime_fields
from log_utils import log_create, log_update, log_delete, log_error, log_operation
logger = logging.getLogger('article_server')
# 创建蓝图
auth_bp = Blueprint('auth', __name__, url_prefix='/api/auth')
@auth_bp.route('/login', methods=['POST'])
def login():
"""统一登录接口(支持企业主和员工)"""
client_ip = request.environ.get('HTTP_X_FORWARDED_FOR', request.environ.get('REMOTE_ADDR', '未知'))
logger.info(f"[用户登录] 开始处理登录请求, IP: {client_ip}")
try:
data = request.get_json()
if not data:
logger.warning(f"[用户登录] 请求参数为空, IP: {client_ip}")
return jsonify({
'code': 400,
'message': '请求参数错误',
'data': None
}), 400
# 支持手机号或用户名登录
phone = data.get('phone')
username = data.get('username')
password = data.get('password')
login_account = phone or username
logger.info(f"[用户登录] 收到登录请求, 账号: {login_account}, IP: {client_ip}")
if not login_account or not password:
logger.warning(f"[用户登录] 账号或密码为空, 账号: {login_account}, IP: {client_ip}")
return jsonify({
'code': 400,
'message': '账号和密码不能为空',
'data': None
}), 400
# 第一步:先在 ai_users 表查询用户
# 从ai_authors表获取xhs_account字段以优化性能
logger.info(f"[用户登录] 开始在ai_users表查询用户, 账号: {login_account}")
db_manager = get_db_manager()
# 支持手机号或用户名登录
sql = """
SELECT u.id, u.enterprise_id, u.enterprise_name, u.username, u.phone, u.password,
u.real_name, u.role, u.status, u.is_bound_xhs, a.xhs_account
FROM ai_users u
LEFT JOIN ai_authors a ON u.id = a.created_user_id AND a.status = 'active'
WHERE (u.phone = %s OR u.username = %s) AND u.status = 'active'
"""
result = db_manager.execute_query(sql, (login_account, login_account))
if not result:
logger.warning(f"[用户登录失败] 用户不存在或已禁用: {login_account}, IP: {client_ip}")
return jsonify({
'code': 401,
'message': '账号或密码错误',
'data': None
}), 401
user = result[0]
logger.info(f"[用户登录] 查询到用户信息, 用户名: {user['username']}, 角色: {user['role']}, 企业: {user['enterprise_name']}, 企业ID: {user['enterprise_id']}")
# 验证密码
logger.info(f"[用户登录] 开始验证密码, 账号: {login_account}")
if not AuthUtils.verify_password(password, user['password']):
logger.warning(f"[用户登录失败] 密码错误: {login_account}, 用户名: {user['username']}, IP: {client_ip}")
return jsonify({
'code': 401,
'message': '账号或密码错误',
'data': None
}), 401
logger.info(f"[用户登录] 密码验证成功, 用户名: {user['username']}, 角色: {user['role']}")
# 如果是企业角色,获取企业详细信息
enterprise_info = None
if user['role'] == 'enterprise' and user['enterprise_id']:
logger.info(f"[用户登录] 检测到企业角色, 开始获取企业详细信息, 企业ID: {user['enterprise_id']}")
enterprise_sql = """
SELECT id, enterprise_ID, name, short_name, phone, email, status,
users_total, products_total, articles_total, published_total
FROM ai_enterprises
WHERE id = %s AND status = 'active'
"""
enterprise_result = db_manager.execute_query(enterprise_sql, (user['enterprise_id'],))
if enterprise_result:
enterprise_info = enterprise_result[0]
logger.info(f"[用户登录] 获取企业信息成功, 企业名称: {enterprise_info['name']}, 企业编号: {enterprise_info['enterprise_ID']}")
else:
logger.warning(f"[用户登录] 企业信息不存在或已禁用, 企业ID: {user['enterprise_id']}")
# 生成token
logger.info(f"[用户登录] 开始生成token, 用户ID: {user['id']}, 角色: {user['role']}")
token = AuthUtils.generate_token(
user['id'],
user['phone'] or user['username'],
user['role'],
user['enterprise_id']
)
# 构造返回数据
user_info = {
'id': user['id'],
'name': user['real_name'] or user['username'],
'username': user['username'],
'phone': user['phone'],
'role': user['role'],
'enterpriseId': user['enterprise_id'],
'enterpriseName': user['enterprise_name'],
'isBoundXHS': bool(user.get('is_bound_xhs', 0)),
'xhsAccount': user.get('xhs_account', '')
}
# 如果是企业角色且有企业信息,添加企业详细信息
if enterprise_info:
user_info.update({
'enterpriseCode': enterprise_info['enterprise_ID'],
'enterpriseShortName': enterprise_info['short_name'],
'enterpriseEmail': enterprise_info['email'],
'enterprisePhone': enterprise_info['phone'],
'usersTotal': enterprise_info['users_total'],
'productsTotal': enterprise_info['products_total'],
'articlesTotal': enterprise_info['articles_total'],
'publishedTotal': enterprise_info['published_total']
})
logger.info(f"[用户登录成功] Token生成成功, 用户: {user['username']}, 角色: {user['role']}, 企业: {user['enterprise_name']}, IP: {client_ip}")
# 返回用户信息和token
return jsonify({
'code': 200,
'message': '登录成功',
'data': {
'token': token,
'userInfo': user_info
},
'timestamp': int(datetime.now().timestamp() * 1000)
})
except Exception as e:
logger.error(f"[用户登录处理] 处理请求时发生错误: {str(e)}", exc_info=True)
return jsonify({
'code': 500,
'message': '服务器内部错误',
'data': None
}), 500
@auth_bp.route('/employee/login', methods=['POST'])
def employee_login():
"""员工登录"""
client_ip = request.environ.get('HTTP_X_FORWARDED_FOR', request.environ.get('REMOTE_ADDR', '未知'))
logger.info(f"[员工登录] 开始处理员工登录请求, IP: {client_ip}")
try:
data = request.get_json()
if not data:
logger.warning(f"[员工登录] 请求参数为空, IP: {client_ip}")
return jsonify({
'code': 400,
'message': '请求参数错误',
'data': None
}), 400
phone = data.get('phone')
password = data.get('password')
logger.info(f"[员工登录] 收到登录请求, 手机号: {phone}, IP: {client_ip}")
if not phone or not password:
logger.warning(f"[员工登录] 手机号或密码为空, 手机号: {phone}, IP: {client_ip}")
return jsonify({
'code': 400,
'message': '手机号和密码不能为空',
'data': None
}), 400
# 查询员工用户
# 从ai_authors表获取xhs_account字段以优化性能
logger.info(f"[员工登录] 开始查询员工信息, 手机号: {phone}")
db_manager = get_db_manager()
sql = """
SELECT u.id, u.enterprise_id, u.real_name, u.phone, u.password, u.role, u.status,
u.is_bound_xhs, a.xhs_account,
e.name as enterprise_name
FROM ai_users u
LEFT JOIN ai_enterprises e ON u.enterprise_id = e.id
LEFT JOIN ai_authors a ON u.id = a.created_user_id AND a.status = 'active'
WHERE u.phone = %s
"""
result = db_manager.execute_query(sql, (phone,))
if not result:
logger.warning(f"[员工登录失败] 用户不存在: {phone}, IP: {client_ip}")
return jsonify({
'code': 401,
'message': '手机号或密码错误',
'data': None
}), 401
user = result[0]
logger.info(f"[员工登录] 查询到员工信息, 姓名: {user['real_name']}, 角色: {user['role']}, 企业: {user['enterprise_name']}, 状态: {user['status']}, 绑定小红书: {user.get('is_bound_xhs', 0)}")
# 检查用户状态
if user['status'] != 'active':
logger.warning(f"[员工登录失败] 用户状态异常: {phone}, 状态: {user['status']}, 姓名: {user['real_name']}, IP: {client_ip}")
return jsonify({
'code': 403,
'message': '用户已被禁用',
'data': None
}), 403
# 验证密码
logger.info(f"[员工登录] 开始验证密码, 手机号: {phone}, 姓名: {user['real_name']}")
if not AuthUtils.verify_password(password, user['password']):
logger.warning(f"[员工登录失败] 密码错误: {phone}, 姓名: {user['real_name']}, IP: {client_ip}")
return jsonify({
'code': 401,
'message': '手机号或密码错误',
'data': None
}), 401
# 生成token
logger.info(f"[员工登录] 密码验证成功, 开始生成token, 姓名: {user['real_name']}, 角色: {user['role']}, 企业: {user['enterprise_name']}")
token = AuthUtils.generate_token(user['id'], phone, user['role'], user['enterprise_id'])
logger.info(f"[员工登录成功] Token生成成功, 姓名: {user['real_name']}, 手机号: {phone}, 角色: {user['role']}, 企业: {user['enterprise_name']}, IP: {client_ip}")
# 返回用户信息和token
return jsonify({
'code': 200,
'message': '登录成功',
'data': {
'token': token,
'userInfo': {
'id': user['id'],
'name': user['real_name'],
'phone': user['phone'],
'role': user['role'],
'enterpriseId': user['enterprise_id'],
'enterpriseName': user['enterprise_name'],
'isBoundXHS': bool(user.get('is_bound_xhs', 0)),
'xhsAccount': user.get('xhs_account', '')
}
},
'timestamp': int(datetime.now().timestamp() * 1000)
})
except Exception as e:
logger.error(f"[员工登录处理] 处理请求时发生错误: {str(e)}", exc_info=True)
return jsonify({
'code': 500,
'message': '服务器内部错误',
'data': None
}), 500
@auth_bp.route('/logout', methods=['POST'])
def logout():
"""用户登出"""
try:
# 记录登出日志
auth_header = request.headers.get('Authorization')
if auth_header:
parts = auth_header.split()
if len(parts) == 2:
token = parts[1]
payload = AuthUtils.verify_token(token)
if payload:
logger.info(f"[登出成功] 用户ID: {payload.get('user_id')}")
return jsonify({
'code': 200,
'message': '退出成功',
'data': None,
'timestamp': int(datetime.now().timestamp() * 1000)
})
except Exception as e:
logger.error(f"[登出处理] 处理请求时发生错误: {str(e)}", exc_info=True)
return jsonify({
'code': 500,
'message': '服务器内部错误',
'data': None
}), 500

View File

@@ -0,0 +1,311 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
员工管理接口
"""
from flask import Blueprint, request, jsonify
import logging
from datetime import datetime
from auth_utils import require_auth, require_role, AuthUtils
from database_config import get_db_manager, format_datetime_fields
from log_utils import log_create, log_update, log_delete, log_error, log_operation
logger = logging.getLogger('article_server')
# 创建蓝图
employee_bp = Blueprint('employee', __name__, url_prefix='/api/employees')
@employee_bp.route('/list', methods=['GET'])
@require_auth
def get_employees_list():
"""获取员工列表"""
try:
current_user = AuthUtils.get_current_user()
enterprise_id = current_user.get('enterprise_id')
if not enterprise_id:
return jsonify({
'code': 400,
'message': '无法获取企业ID',
'data': None
}), 400
# 获取查询参数
page = int(request.args.get('page', 1))
page_size = int(request.args.get('pageSize', 20))
keyword = request.args.get('keyword', '').strip()
status = request.args.get('status', '').strip()
is_bound_xhs = request.args.get('isBoundXHS', '').strip()
# 构建查询条件(使用表别名以避免字段歧义)
where_conditions = ["u.enterprise_id = %s", "u.status != 'deleted'"]
params = [enterprise_id]
if keyword:
where_conditions.append("(u.real_name LIKE %s OR u.username LIKE %s OR u.phone LIKE %s)")
keyword_pattern = f"%{keyword}%"
params.extend([keyword_pattern, keyword_pattern, keyword_pattern])
if status:
where_conditions.append("u.status = %s")
params.append(status)
if is_bound_xhs:
bound_value = 1 if is_bound_xhs.lower() == 'true' else 0
where_conditions.append("u.is_bound_xhs = %s")
params.append(bound_value)
where_clause = " AND ".join(where_conditions)
# 计算偏移量
offset = (page - 1) * page_size
db_manager = get_db_manager()
# 查询总数
count_sql = f"SELECT COUNT(*) as total FROM ai_users u WHERE {where_clause}"
count_result = db_manager.execute_query(count_sql, params)
total = count_result[0]['total']
# 查询员工列表
# 从ai_authors表获取xhs_account字段以优化性能
sql = f"""
SELECT u.id, u.enterprise_id, u.real_name as name, u.username, u.phone, u.role, u.department,
u.is_bound_xhs, a.xhs_account, u.status, u.created_at, u.updated_at
FROM ai_users u
LEFT JOIN ai_authors a ON u.id = a.created_user_id AND a.status = 'active'
WHERE {where_clause}
ORDER BY u.created_at DESC
LIMIT %s OFFSET %s
"""
params.extend([page_size, offset])
employees = db_manager.execute_query(sql, params)
# 转换布尔值
for emp in employees:
emp['is_bound_xhs'] = bool(emp.get('is_bound_xhs', 0))
# 格式化日期时间字段
employees = format_datetime_fields(employees)
logger.info(f"获取员工列表成功,总数: {total}")
return jsonify({
'code': 200,
'message': 'success',
'data': {
'total': total,
'list': employees
},
'timestamp': int(datetime.now().timestamp() * 1000)
})
except Exception as e:
logger.error(f"[获取员工列表] 处理请求时发生错误: {str(e)}", exc_info=True)
return jsonify({
'code': 500,
'message': '服务器内部错误',
'data': None
}), 500
@employee_bp.route('/add', methods=['POST'])
@require_auth
@require_role('enterprise')
def add_employee():
"""添加员工"""
try:
current_user = AuthUtils.get_current_user()
enterprise_id = current_user.get('enterprise_id')
if not enterprise_id:
return jsonify({
'code': 400,
'message': '无法获取企业ID',
'data': None
}), 400
data = request.get_json()
if not data:
return jsonify({
'code': 400,
'message': '请求参数错误',
'data': None
}), 400
# 验证必需字段
required_fields = ['name', 'phone', 'password', 'role']
for field in required_fields:
if not data.get(field):
return jsonify({
'code': 400,
'message': f'缺少必需字段: {field}',
'data': None
}), 400
# 验证角色
valid_roles = ['editor', 'reviewer', 'publisher', 'each_title_reviewer']
if data['role'] not in valid_roles:
return jsonify({
'code': 400,
'message': '无效的角色',
'data': None
}), 400
# 检查手机号是否已存在
db_manager = get_db_manager()
check_sql = "SELECT id FROM ai_users WHERE phone = %s AND enterprise_id = %s"
existing = db_manager.execute_query(check_sql, (data['phone'], enterprise_id))
if existing:
return jsonify({
'code': 409,
'message': '手机号已被使用',
'data': None
}), 409
# 创建员工
# xhs_phone, xhs_account, bound_at字段已迁移到ai_authors表不再在ai_users表中存储
sql = """
INSERT INTO ai_users
(enterprise_id, enterprise_name, username, real_name, phone, password, role, department, status, is_bound_xhs)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
"""
hashed_password = AuthUtils.hash_password(data['password'])
# 获取企业名称
ent_sql = "SELECT name FROM ai_enterprises WHERE id = %s"
ent_result = db_manager.execute_query(ent_sql, (enterprise_id,))
enterprise_name = ent_result[0]['name'] if ent_result else ''
user_id = db_manager.execute_insert(sql, (
enterprise_id,
enterprise_name,
data['phone'], # 使用手机号作为username
data['name'], # real_name
data['phone'],
hashed_password,
data['role'],
data.get('department', ''),
'active',
0 # is_bound_xhs
))
# 更新企业员工总数
update_sql = "UPDATE ai_enterprises SET users_total = users_total + 1 WHERE id = %s"
db_manager.execute_update(update_sql, (enterprise_id,))
logger.info(f"添加员工成功: {data['name']}, ID: {user_id}")
return jsonify({
'code': 200,
'message': '添加成功',
'data': {'id': user_id},
'timestamp': int(datetime.now().timestamp() * 1000)
})
except Exception as e:
logger.error(f"[添加员工] 处理请求时发生错误: {str(e)}", exc_info=True)
return jsonify({
'code': 500,
'message': '服务器内部错误',
'data': None
}), 500
@employee_bp.route('/<int:employee_id>', methods=['DELETE'])
@require_auth
@require_role('enterprise')
def delete_employee(employee_id):
"""删除员工"""
try:
current_user = AuthUtils.get_current_user()
enterprise_id = current_user.get('enterprise_id')
if not enterprise_id:
return jsonify({
'code': 400,
'message': '无法获取企业ID',
'data': None
}), 400
db_manager = get_db_manager()
# 检查员工是否存在且属于当前企业
check_sql = "SELECT id, real_name FROM ai_users WHERE id = %s AND enterprise_id = %s AND status != 'deleted'"
existing = db_manager.execute_query(check_sql, (employee_id, enterprise_id))
if not existing:
return jsonify({
'code': 404,
'message': '员工不存在',
'data': None
}), 404
# 软删除员工
sql = "UPDATE ai_users SET status = 'deleted', updated_at = NOW() WHERE id = %s"
db_manager.execute_update(sql, (employee_id,))
# 更新企业员工总数
update_sql = "UPDATE ai_enterprises SET users_total = users_total - 1 WHERE id = %s"
db_manager.execute_update(update_sql, (enterprise_id,))
logger.info(f"删除员工成功: {existing[0]['real_name']}")
return jsonify({
'code': 200,
'message': '删除成功',
'data': None,
'timestamp': int(datetime.now().timestamp() * 1000)
})
except Exception as e:
logger.error(f"[删除员工] 处理请求时发生错误: {str(e)}", exc_info=True)
return jsonify({
'code': 500,
'message': '服务器内部错误',
'data': None
}), 500
@employee_bp.route('/stats', methods=['GET'])
@require_auth
def get_employees_stats():
"""获取员工统计"""
try:
current_user = AuthUtils.get_current_user()
enterprise_id = current_user.get('enterprise_id')
if not enterprise_id:
return jsonify({
'code': 400,
'message': '无法获取企业ID',
'data': None
}), 400
db_manager = get_db_manager()
sql = """
SELECT
COUNT(*) as total_count,
SUM(CASE WHEN status = 'active' THEN 1 ELSE 0 END) as active_count,
SUM(CASE WHEN is_bound_xhs = 1 THEN 1 ELSE 0 END) as bound_xhs_count
FROM ai_users
WHERE enterprise_id = %s AND status != 'deleted'
"""
result = db_manager.execute_query(sql, (enterprise_id,))
stats = result[0] if result else {}
logger.info("获取员工统计成功")
return jsonify({
'code': 200,
'message': 'success',
'data': stats,
'timestamp': int(datetime.now().timestamp() * 1000)
})
except Exception as e:
logger.error(f"[获取员工统计] 处理请求时发生错误: {str(e)}", exc_info=True)
return jsonify({
'code': 500,
'message': '服务器内部错误',
'data': None
}), 500

View File

@@ -0,0 +1,693 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
企业管理接口
"""
from flask import Blueprint, request, jsonify
import logging
from datetime import datetime
from auth_utils import require_auth, require_role, AuthUtils
from database_config import get_db_manager, format_datetime_fields
from log_utils import log_create, log_update, log_delete, log_error
import uuid
logger = logging.getLogger('article_server')
# 创建蓝图
enterprise_bp = Blueprint('enterprise', __name__, url_prefix='/api/enterprises')
@enterprise_bp.route('/list', methods=['GET'])
@require_auth
@require_role('admin', 'enterprise')
def get_enterprises_list():
"""获取企业列表(平台管理员)"""
client_ip = request.environ.get('HTTP_X_FORWARDED_FOR', request.environ.get('REMOTE_ADDR', '未知'))
logger.info(f"[获取企业列表] 开始处理请求, IP: {client_ip}")
try:
# 获取查询参数
page = int(request.args.get('page', 1))
page_size = int(request.args.get('pageSize', 20))
keyword = request.args.get('keyword', '').strip()
status = request.args.get('status', '').strip()
logger.info(f"[获取企业列表] 查询参数: page={page}, pageSize={page_size}, keyword={keyword}, status={status}, IP: {client_ip}")
# 构建查询条件
where_conditions = ["1=1"]
params = []
if keyword:
where_conditions.append("(name LIKE %s OR short_name LIKE %s OR phone LIKE %s)")
keyword_pattern = f"%{keyword}%"
params.extend([keyword_pattern, keyword_pattern, keyword_pattern])
if status:
where_conditions.append("status = %s")
params.append(status)
where_clause = " AND ".join(where_conditions)
# 计算偏移量
offset = (page - 1) * page_size
db_manager = get_db_manager()
# 查询总数
count_sql = f"SELECT COUNT(*) as total FROM ai_enterprises WHERE {where_clause}"
count_result = db_manager.execute_query(count_sql, params)
total = count_result[0]['total']
# 查询企业列表
sql = f"""
SELECT id, enterprise_ID, name, short_name, phone, email, status,
users_total, products_total, articles_total, published_total,
created_at, updated_at
FROM ai_enterprises
WHERE {where_clause}
ORDER BY created_at DESC
LIMIT %s OFFSET %s
"""
params.extend([page_size, offset])
enterprises = db_manager.execute_query(sql, params)
# 格式化日期时间字段
enterprises = format_datetime_fields(enterprises)
logger.info(f"[获取企业列表] 查询成功, 总数: {total}, 当前页: {page}, 每页: {page_size}, 返回数量: {len(enterprises)}, IP: {client_ip}")
return jsonify({
'code': 200,
'message': 'success',
'data': {
'total': total,
'list': enterprises
},
'timestamp': int(datetime.now().timestamp() * 1000)
})
except Exception as e:
logger.error(f"[获取企业列表] 处理请求时发生错误: {str(e)}", exc_info=True)
return jsonify({
'code': 500,
'message': '服务器内部错误',
'data': None
}), 500
@enterprise_bp.route('/create', methods=['POST'])
@require_auth
@require_role('admin', 'enterprise')
def create_enterprise():
"""创建企业(平台管理员)"""
client_ip = request.environ.get('HTTP_X_FORWARDED_FOR', request.environ.get('REMOTE_ADDR', '未知'))
logger.info(f"[创建企业] 开始处理创建企业请求, IP: {client_ip}")
try:
data = request.get_json()
if not data:
logger.warning(f"[创建企业] 请求参数为空, IP: {client_ip}")
return jsonify({
'code': 400,
'message': '请求参数错误',
'data': None
}), 400
logger.info(f"[创建企业] 收到创建请求, 企业名称: {data.get('name')}, 简称: {data.get('short_name')}, 手机号: {data.get('phone')}, IP: {client_ip}")
# 验证必需字段
required_fields = ['name', 'short_name', 'phone', 'password']
for field in required_fields:
if not data.get(field):
logger.warning(f"[创建企业] 缺少必需字段: {field}, IP: {client_ip}")
return jsonify({
'code': 400,
'message': f'缺少必需字段: {field}',
'data': None
}), 400
db_manager = get_db_manager()
# ✅ 检查手机号是否已存在ai_enterprises表
logger.info(f"[创建企业] 检查ai_enterprises表手机号是否已存在: {data['phone']}")
check_enterprise_sql = "SELECT id FROM ai_enterprises WHERE phone = %s"
existing_enterprise = db_manager.execute_query(check_enterprise_sql, (data['phone'],))
if existing_enterprise:
logger.warning(f"[创建企业] ai_enterprises表中手机号已存在: {data['phone']}, IP: {client_ip}")
return jsonify({
'code': 409,
'message': '手机号已被使用',
'data': None
}), 409
# ✅ 检查手机号是否已存在ai_users表
logger.info(f"[创建企业] 检查ai_users表手机号是否已存在: {data['phone']}")
check_user_sql = "SELECT id FROM ai_users WHERE phone = %s"
existing_user = db_manager.execute_query(check_user_sql, (data['phone'],))
if existing_user:
logger.warning(f"[创建企业] ai_users表中手机号已存在: {data['phone']}, IP: {client_ip}")
return jsonify({
'code': 409,
'message': '手机号已被使用',
'data': None
}), 409
# 生成企业唯一标识
enterprise_id_str = f"ENT-{datetime.now().strftime('%Y%m%d')}-{str(uuid.uuid4())[:8].upper()}"
logger.info(f"[创建企业] 生成企业ID: {enterprise_id_str}, 企业名称: {data['name']}")
# 加密密码
from auth_utils import AuthUtils
hashed_password = AuthUtils.hash_password(data['password'])
# ✅ 1创建企业ai_enterprises表
logger.info(f"[创建企业] 开始插入ai_enterprises表, 企业ID: {enterprise_id_str}, 名称: {data['name']}")
enterprise_sql = """
INSERT INTO ai_enterprises
(enterprise_ID, name, short_name, icon, phone, email, website, address, status,
users_total, products_total, published_total, articles_total, released_month_total, linked_to_xhs_num)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
"""
enterprise_db_id = db_manager.execute_insert(enterprise_sql, (
enterprise_id_str,
data['name'],
data['short_name'],
data.get('icon', ''),
data['phone'],
data.get('email', ''),
data.get('website', ''),
data.get('address', ''),
'active',
0, 0, 0, 0, 0, 0
))
logger.info(f"[创建企业] ai_enterprises表插入成功, 数据库ID: {enterprise_db_id}, 企业ID: {enterprise_id_str}")
# ✅ 2创建企业管理员用户ai_users表
logger.info(f"[创建企业] 开始创建企业管理员用户, 手机号: {data['phone']}, 角色: enterprise")
user_sql = """
INSERT INTO ai_users
(enterprise_id, enterprise_name, username, password, real_name, email, phone,
department, role, status)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
"""
# 用户名使用手机号
username = data['phone']
user_db_id = db_manager.execute_insert(user_sql, (
enterprise_db_id, # enterprise_id
data['name'], # enterprise_name
username, # username (使用手机号)
hashed_password, # password (使用传入的密码)
data.get('real_name', data['short_name']), # real_name
data.get('email', ''), # email
data['phone'], # phone
data.get('department', ''), # department
'enterprise', # role (✅ 角色为enterprise)
'active' # status
))
logger.info(f"[创建企业] ai_users表插入成功, 用户ID: {user_db_id}, 用户名: {username}, 角色: enterprise")
logger.info(f"[创建企业] 企业创建成功, 企业DB_ID: {enterprise_db_id}, 企业ID: {enterprise_id_str}, 名称: {data['name']}, 管理员用户ID: {user_db_id}, IP: {client_ip}")
# 记录业务日志
log_create(
target_type='enterprise',
target_id=enterprise_db_id,
description=f"创建企业: {data['name']}, 同时创建企业管理员用户",
request_data={**data, 'password': '***'}, # 隐藏密码
response_data={'enterprise_id': enterprise_db_id, 'enterprise_ID': enterprise_id_str, 'user_id': user_db_id}
)
return jsonify({
'code': 200,
'message': '创建成功',
'data': {
'id': enterprise_db_id,
'enterprise_ID': enterprise_id_str,
'name': data['name'],
'user_id': user_db_id,
'username': username
},
'timestamp': int(datetime.now().timestamp() * 1000)
})
except Exception as e:
logger.error(f"[创建企业] 处理请求时发生错误: {str(e)}", exc_info=True)
return jsonify({
'code': 500,
'message': '服务器内部错误',
'data': None
}), 500
@enterprise_bp.route('/<int:enterprise_id>', methods=['PUT'])
@require_auth
@require_role('admin', 'enterprise')
def update_enterprise(enterprise_id):
"""更新企业信息(平台管理员)"""
try:
data = request.get_json()
if not data:
return jsonify({
'code': 400,
'message': '请求参数错误',
'data': None
}), 400
# 检查企业是否存在
db_manager = get_db_manager()
check_sql = "SELECT id FROM ai_enterprises WHERE id = %s"
existing = db_manager.execute_query(check_sql, (enterprise_id,))
if not existing:
return jsonify({
'code': 404,
'message': '企业不存在',
'data': None
}), 404
# 构建更新字段
update_fields = []
params = []
if 'name' in data:
update_fields.append("name = %s")
params.append(data['name'])
if 'short_name' in data:
update_fields.append("short_name = %s")
params.append(data['short_name'])
if 'email' in data:
update_fields.append("email = %s")
params.append(data['email'])
if 'password' in data:
from auth_utils import AuthUtils
update_fields.append("password = %s")
params.append(AuthUtils.hash_password(data['password']))
if not update_fields:
return jsonify({
'code': 400,
'message': '没有要更新的字段',
'data': None
}), 400
# 执行更新
params.append(enterprise_id)
sql = f"UPDATE ai_enterprises SET {', '.join(update_fields)}, updated_at = NOW() WHERE id = %s"
db_manager.execute_update(sql, params)
logger.info(f"更新企业成功: ID {enterprise_id}")
# 记录业务日志
log_update(
target_type='enterprise',
target_id=enterprise_id,
description=f"更新企业信息",
request_data=data
)
return jsonify({
'code': 200,
'message': '更新成功',
'data': None,
'timestamp': int(datetime.now().timestamp() * 1000)
})
except Exception as e:
logger.error(f"[更新企业] 处理请求时发生错误: {str(e)}", exc_info=True)
return jsonify({
'code': 500,
'message': '服务器内部错误',
'data': None
}), 500
@enterprise_bp.route('/<int:enterprise_id>/status', methods=['PUT'])
@require_auth
@require_role('admin', 'enterprise')
def toggle_enterprise_status(enterprise_id):
"""切换企业状态(平台管理员)"""
try:
data = request.get_json()
if not data or 'status' not in data:
return jsonify({
'code': 400,
'message': '缺少status参数',
'data': None
}), 400
status = data['status']
if status not in ['active', 'disabled']:
return jsonify({
'code': 400,
'message': '状态值无效',
'data': None
}), 400
db_manager = get_db_manager()
sql = "UPDATE ai_enterprises SET status = %s, updated_at = NOW() WHERE id = %s"
affected = db_manager.execute_update(sql, (status, enterprise_id))
if affected == 0:
return jsonify({
'code': 404,
'message': '企业不存在',
'data': None
}), 404
logger.info(f"切换企业状态成功: ID {enterprise_id}, 状态: {status}")
# 记录业务日志
log_update(
target_type='enterprise',
target_id=enterprise_id,
description=f"切换企业状态: {status}",
request_data=data
)
return jsonify({
'code': 200,
'message': '操作成功',
'data': None,
'timestamp': int(datetime.now().timestamp() * 1000)
})
except Exception as e:
logger.error(f"[切换企业状态] 处理请求时发生错误: {str(e)}", exc_info=True)
return jsonify({
'code': 500,
'message': '服务器内部错误',
'data': None
}), 500
@enterprise_bp.route('/<int:enterprise_id>', methods=['DELETE'])
@require_auth
@require_role('admin', 'enterprise')
def delete_enterprise(enterprise_id):
"""删除企业(平台管理员)"""
try:
db_manager = get_db_manager()
# 检查企业是否存在
check_sql = "SELECT id, name FROM ai_enterprises WHERE id = %s"
existing = db_manager.execute_query(check_sql, (enterprise_id,))
if not existing:
return jsonify({
'code': 404,
'message': '企业不存在',
'data': None
}), 404
# 物理删除企业API文档要求
sql = "DELETE FROM ai_enterprises WHERE id = %s"
db_manager.execute_update(sql, (enterprise_id,))
logger.info(f"删除企业成功: {existing[0]['name']}")
# 记录业务日志
log_delete(
target_type='enterprise',
target_id=enterprise_id,
description=f"删除企业: {existing[0]['name']}"
)
return jsonify({
'code': 200,
'message': '删除成功',
'data': None,
'timestamp': int(datetime.now().timestamp() * 1000)
})
except Exception as e:
logger.error(f"[删除企业] 处理请求时发生错误: {str(e)}", exc_info=True)
return jsonify({
'code': 500,
'message': '服务器内部错误',
'data': None
}), 500
@enterprise_bp.route('/stats', methods=['GET'])
@require_auth
@require_role('admin', 'enterprise')
def get_enterprises_stats():
"""获取企业统计(平台管理员)"""
try:
db_manager = get_db_manager()
sql = """
SELECT
COUNT(*) as total_count,
SUM(CASE WHEN status = 'active' THEN 1 ELSE 0 END) as active_count,
SUM(CASE WHEN status = 'disabled' THEN 1 ELSE 0 END) as disabled_count,
SUM(users_total) as total_users,
SUM(products_total) as total_products,
SUM(articles_total) as total_articles,
SUM(published_total) as total_published
FROM ai_enterprises
WHERE status != 'deleted'
"""
result = db_manager.execute_query(sql)
stats = result[0] if result else {}
logger.info("获取企业统计成功")
return jsonify({
'code': 200,
'message': 'success',
'data': stats,
'timestamp': int(datetime.now().timestamp() * 1000)
})
except Exception as e:
logger.error(f"[获取企业统计] 处理请求时发生错误: {str(e)}", exc_info=True)
return jsonify({
'code': 500,
'message': '服务器内部错误',
'data': None
}), 500
# 企业管理员接口
@enterprise_bp.route('/info', methods=['GET'])
@require_auth
@require_role('enterprise')
def get_enterprise_info():
"""获取企业信息(企业管理员,包含密码字段)"""
try:
current_user = AuthUtils.get_current_user()
enterprise_id = current_user.get('enterprise_id')
user_id = current_user.get('user_id')
if not enterprise_id:
return jsonify({
'code': 400,
'message': '无法获取企业ID',
'data': None
}), 400
db_manager = get_db_manager()
# 查询企业信息
enterprise_sql = """
SELECT id, enterprise_ID, name, short_name, phone, email, status,
users_total, products_total, articles_total, published_total,
created_at, updated_at
FROM ai_enterprises
WHERE id = %s
"""
enterprise_result = db_manager.execute_query(enterprise_sql, (enterprise_id,))
if not enterprise_result:
return jsonify({
'code': 404,
'message': '企业不存在',
'data': None
}), 404
# 格式化日期时间字段
enterprise_info = format_datetime_fields(enterprise_result[0])
logger.info(f"获取企业信息成功(含密码): ID {enterprise_id}")
return jsonify({
'code': 200,
'message': 'success',
'data': enterprise_info,
'timestamp': int(datetime.now().timestamp() * 1000)
})
except Exception as e:
logger.error(f"[获取企业信息] 处理请求时发生错误: {str(e)}", exc_info=True)
return jsonify({
'code': 500,
'message': '服务器内部错误',
'data': None
}), 500
@enterprise_bp.route('/info', methods=['PUT'])
@require_auth
@require_role('enterprise')
def update_enterprise_info():
"""更新企业信息(企业管理员)"""
try:
current_user = AuthUtils.get_current_user()
enterprise_id = current_user.get('enterprise_id')
if not enterprise_id:
return jsonify({
'code': 400,
'message': '无法获取企业ID',
'data': None
}), 400
data = request.get_json()
if not data:
return jsonify({
'code': 400,
'message': '请求参数错误',
'data': None
}), 400
# 构建更新字段(企业管理员只能更新部分字段)
update_fields = []
params = []
if 'short_name' in data:
update_fields.append("short_name = %s")
params.append(data['short_name'])
if 'email' in data:
update_fields.append("email = %s")
params.append(data['email'])
if not update_fields:
return jsonify({
'code': 400,
'message': '没有要更新的字段',
'data': None
}), 400
db_manager = get_db_manager()
params.append(enterprise_id)
sql = f"UPDATE ai_enterprises SET {', '.join(update_fields)}, updated_at = NOW() WHERE id = %s"
db_manager.execute_update(sql, params)
logger.info(f"企业管理员更新企业信息成功: ID {enterprise_id}")
# 记录业务日志
log_update(
target_type='enterprise',
target_id=enterprise_id,
description=f"更新企业信息(企业管理员)",
request_data=data
)
return jsonify({
'code': 200,
'message': '更新成功',
'data': None,
'timestamp': int(datetime.now().timestamp() * 1000)
})
except Exception as e:
logger.error(f"[更新企业信息] 处理请求时发生错误: {str(e)}", exc_info=True)
return jsonify({
'code': 500,
'message': '服务器内部错误',
'data': None
}), 500
@enterprise_bp.route('/change-password', methods=['PUT'])
@require_auth
@require_role('enterprise')
def change_password():
"""修改企业密码(企业管理员)"""
try:
current_user = AuthUtils.get_current_user()
enterprise_id = current_user.get('enterprise_id')
if not enterprise_id:
return jsonify({
'code': 400,
'message': '无法获取企业ID',
'data': None
}), 400
data = request.get_json()
if not data:
return jsonify({
'code': 400,
'message': '请求参数错误',
'data': None
}), 400
old_password = data.get('old_password')
new_password = data.get('new_password')
if not old_password or not new_password:
return jsonify({
'code': 400,
'message': '旧密码和新密码不能为空',
'data': None
}), 400
# 获取当前密码从ai_users表查询企业管理员账号
db_manager = get_db_manager()
user_id = current_user.get('user_id')
sql = "SELECT password FROM ai_users WHERE id = %s AND role = 'enterprise'"
result = db_manager.execute_query(sql, (user_id,))
if not result:
return jsonify({
'code': 404,
'message': '用户不存在',
'data': None
}), 404
current_password = result[0]['password']
# 验证旧密码
if not AuthUtils.verify_password(old_password, current_password):
logger.warning(f"企业修改密码失败 - 旧密码错误: 企业ID {enterprise_id}")
return jsonify({
'code': 401,
'message': '旧密码错误',
'data': None
}), 401
# 更新密码更新ai_users表中的企业管理员密码
hashed_new_password = AuthUtils.hash_password(new_password)
update_sql = "UPDATE ai_users SET password = %s, updated_at = NOW() WHERE id = %s AND role = 'enterprise'"
db_manager.execute_update(update_sql, (hashed_new_password, user_id))
logger.info(f"企业修改密码成功: ID {enterprise_id}")
# 记录业务日志
log_update(
target_type='enterprise',
target_id=enterprise_id,
description=f"修改企业密码",
request_data={'old_password': '***', 'new_password': '***'} # 隐藏密码
)
return jsonify({
'code': 200,
'message': '密码修改成功',
'data': None,
'timestamp': int(datetime.now().timestamp() * 1000)
})
except Exception as e:
logger.error(f"[修改密码] 处理请求时发生错误: {str(e)}", exc_info=True)
return jsonify({
'code': 500,
'message': '服务器内部错误',
'data': None
}), 500

1297
release/32/product_routes.py Normal file

File diff suppressed because it is too large Load Diff

788
release/32/prompt_routes.py Normal file
View File

@@ -0,0 +1,788 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
提示词管理接口
"""
from flask import Blueprint, request, jsonify
import logging
from datetime import datetime
from auth_utils import require_auth, AuthUtils
from database_config import get_db_manager, format_datetime_fields
from log_utils import log_create, log_update, log_delete, log_error, log_operation
logger = logging.getLogger('article_server')
# 创建蓝图
prompt_bp = Blueprint('prompt', __name__, url_prefix='/api/prompts')
@prompt_bp.route('/list_info', methods=['GET'])
@require_auth
def get_prompts_list_info():
"""获取提示词列表简化版仅返回4个字段"""
client_ip = request.environ.get('HTTP_X_FORWARDED_FOR', request.environ.get('REMOTE_ADDR', '未知'))
logger.info(f"[获取提示词列表简化版] 开始处理请求, IP: {client_ip}")
try:
current_user = AuthUtils.get_current_user()
enterprise_id = current_user.get('enterprise_id')
logger.info(f"[获取提示词列表简化版] 用户信息 - 用户ID: {current_user.get('user_id')}, 企业ID: {enterprise_id}, IP: {client_ip}")
if not enterprise_id:
logger.warning(f"[获取提示词列表简化版] 无法获取企业ID, IP: {client_ip}")
return jsonify({
'code': 400,
'message': '无法获取企业ID',
'data': None
}), 400
db_manager = get_db_manager()
# 查询提示词列表仅返回4个字段优化性能
sql = """
SELECT id, prompt_workflow_name, created_at, updated_at
FROM ai_prompt_workflow
WHERE enterprise_id = %s
ORDER BY created_at DESC
"""
prompts = db_manager.execute_query(sql, (enterprise_id,))
# 格式化日期时间字段
prompts = format_datetime_fields(prompts)
logger.info(f"[获取提示词列表简化版] 查询成功, 返回数量: {len(prompts)}, 企业ID: {enterprise_id}, IP: {client_ip}")
return jsonify({
'code': 200,
'message': 'success',
'data': {
'list': prompts
},
'timestamp': int(datetime.now().timestamp() * 1000)
})
except Exception as e:
logger.error(f"[获取提示词列表简化版] 处理请求时发生错误: {str(e)}", exc_info=True)
return jsonify({
'code': 500,
'message': '服务器内部错误',
'data': None
}), 500
@prompt_bp.route('/list', methods=['GET'])
@require_auth
def get_prompts_list():
"""获取提示词列表"""
client_ip = request.environ.get('HTTP_X_FORWARDED_FOR', request.environ.get('REMOTE_ADDR', '未知'))
logger.info(f"[获取提示词列表] 开始处理请求, IP: {client_ip}")
try:
current_user = AuthUtils.get_current_user()
enterprise_id = current_user.get('enterprise_id')
user_id = current_user.get('user_id')
logger.info(f"[获取提示词列表] 用户信息 - 用户ID: {user_id}, 企业ID: {enterprise_id}, IP: {client_ip}")
if not enterprise_id:
return jsonify({
'code': 400,
'message': '无法获取企业ID',
'data': None
}), 400
# 获取查询参数
page = int(request.args.get('page', 1))
page_size = int(request.args.get('pageSize', 20))
# 计算偏移量
offset = (page - 1) * page_size
db_manager = get_db_manager()
# 查询总数
count_sql = "SELECT COUNT(*) as total FROM ai_prompt_workflow WHERE enterprise_id = %s"
count_result = db_manager.execute_query(count_sql, (enterprise_id,))
total = count_result[0]['total']
# 查询提示词列表
sql = """
SELECT id, prompt_workflow_name, workflow_id, content, usage_count, created_at, updated_at
FROM ai_prompt_workflow
WHERE enterprise_id = %s
ORDER BY created_at DESC
LIMIT %s OFFSET %s
"""
prompts = db_manager.execute_query(sql, (enterprise_id, page_size, offset))
# 查询每个提示词的标签
for prompt in prompts:
tag_sql = """
SELECT t.id, t.tag_name
FROM ai_prompt_tags t
INNER JOIN ai_prompt_tags_relation r ON t.id = r.tag_id
WHERE r.prompt_workflow_id = %s
"""
tags = db_manager.execute_query(tag_sql, (prompt['id'],))
prompt['tags'] = [tag['tag_name'] for tag in tags]
# 格式化日期时间字段
prompts = format_datetime_fields(prompts)
logger.info(f"[获取提示词列表] 查询成功, 总数: {total}, 企业ID: {enterprise_id}, IP: {client_ip}")
return jsonify({
'code': 200,
'message': 'success',
'data': {
'total': total,
'list': prompts
},
'timestamp': int(datetime.now().timestamp() * 1000)
})
except Exception as e:
logger.error(f"[获取提示词列表] 处理请求时发生错误: {str(e)}", exc_info=True)
return jsonify({
'code': 500,
'message': '服务器内部错误',
'data': None
}), 500
@prompt_bp.route('/create', methods=['POST'])
@require_auth
def create_prompt():
"""创建提示词"""
client_ip = request.environ.get('HTTP_X_FORWARDED_FOR', request.environ.get('REMOTE_ADDR', '未知'))
logger.info(f"[创建提示词] 开始处理请求, IP: {client_ip}")
try:
current_user = AuthUtils.get_current_user()
enterprise_id = current_user.get('enterprise_id')
user_id = current_user.get('user_id')
logger.info(f"[创建提示词] 用户信息 - 用户ID: {user_id}, 企业ID: {enterprise_id}, IP: {client_ip}")
if not enterprise_id:
return jsonify({
'code': 400,
'message': '无法获取企业ID',
'data': None
}), 400
data = request.get_json()
if not data:
return jsonify({
'code': 400,
'message': '请求参数错误',
'data': None
}), 400
# 验证必需字段
required_fields = ['prompt_workflow_name', 'content']
for field in required_fields:
if not data.get(field):
return jsonify({
'code': 400,
'message': f'缺少必需字段: {field}',
'data': None
}), 400
db_manager = get_db_manager()
# 生成workflow_id
import uuid
workflow_id = f"WF-{str(uuid.uuid4())[:8].upper()}"
# 创建提示词
sql = """
INSERT INTO ai_prompt_workflow
(enterprise_id, prompt_workflow_name, workflow_id, content, usage_count)
VALUES (%s, %s, %s, %s, %s)
"""
prompt_id = db_manager.execute_insert(sql, (
enterprise_id,
data['prompt_workflow_name'],
workflow_id,
data['content'],
0
))
# 记录SQL操作日志
log_create(
target_type='prompt_workflow',
target_id=prompt_id,
description=f"创建提示词: {data['prompt_workflow_name']}"
)
# 添加标签关联
if data.get('tags'):
# ✅ 去重处理,避免重复标签导致唯一索引冲突
unique_tags = list(set(data['tags'])) # 去除重复标签
processed_tag_ids = set() # 记录已处理的 tag_id
for tag_name in unique_tags:
if not tag_name or not tag_name.strip(): # 跳过空标签
continue
tag_name = tag_name.strip()
# ✅ 查找或创建标签(基于 enterprise_id 隔离)
tag_sql = "SELECT id FROM ai_prompt_tags WHERE enterprise_id = %s AND tag_name = %s"
tag_result = db_manager.execute_query(tag_sql, (enterprise_id, tag_name))
if tag_result:
tag_id = tag_result[0]['id']
else:
tag_insert_sql = "INSERT INTO ai_prompt_tags (enterprise_id, tag_name, created_user_id) VALUES (%s, %s, %s)"
tag_id = db_manager.execute_insert(tag_insert_sql, (enterprise_id, tag_name, current_user.get('user_id', 0)))
# ✅ 检查是否已经处理过该 tag_id避免重复插入
if tag_id in processed_tag_ids:
continue
processed_tag_ids.add(tag_id)
# ✅ 创建关联(添加 enterprise_id
try:
rel_sql = "INSERT INTO ai_prompt_tags_relation (enterprise_id, prompt_workflow_id, prompt_workflow_name, tag_id, tag_name, created_user_id) VALUES (%s, %s, %s, %s, %s, %s)"
db_manager.execute_insert(rel_sql, (enterprise_id, prompt_id, data['prompt_workflow_name'], tag_id, tag_name, current_user.get('user_id', 0)))
except Exception as rel_error:
# 如果关联已存在,跳过
logger.warning(f"标签关联已存在: prompt_id={prompt_id}, tag_id={tag_id}, error={str(rel_error)}")
continue
logger.info(f"[创建提示词] 创建成功, ID: {prompt_id}, 名称: {data['prompt_workflow_name']}, 企业ID: {enterprise_id}, IP: {client_ip}")
return jsonify({
'code': 200,
'message': '创建成功',
'data': {
'id': prompt_id,
'prompt_workflow_name': data['prompt_workflow_name']
},
'timestamp': int(datetime.now().timestamp() * 1000)
})
except Exception as e:
logger.error(f"[创建提示词] 处理请求时发生错误: {str(e)}", exc_info=True)
return jsonify({
'code': 500,
'message': '服务器内部错误',
'data': None
}), 500
@prompt_bp.route('/<int:prompt_id>', methods=['PUT'])
@require_auth
def update_prompt(prompt_id):
"""更新提示词"""
client_ip = request.environ.get('HTTP_X_FORWARDED_FOR', request.environ.get('REMOTE_ADDR', '未知'))
logger.info(f"[更新提示词] 开始处理请求, ID: {prompt_id}, IP: {client_ip}")
try:
current_user = AuthUtils.get_current_user()
enterprise_id = current_user.get('enterprise_id')
user_id = current_user.get('user_id')
logger.info(f"[更新提示词] 用户信息 - 用户ID: {user_id}, 企业ID: {enterprise_id}, IP: {client_ip}")
if not enterprise_id:
return jsonify({
'code': 400,
'message': '无法获取企业ID',
'data': None
}), 400
data = request.get_json()
if not data:
return jsonify({
'code': 400,
'message': '请求参数错误',
'data': None
}), 400
db_manager = get_db_manager()
# 检查提示词是否存在且属于当前企业
check_sql = "SELECT id FROM ai_prompt_workflow WHERE id = %s AND enterprise_id = %s"
existing = db_manager.execute_query(check_sql, (prompt_id, enterprise_id))
if not existing:
return jsonify({
'code': 404,
'message': '提示词不存在',
'data': None
}), 404
# 构建更新字段
update_fields = []
params = []
if 'prompt_workflow_name' in data:
update_fields.append("prompt_workflow_name = %s")
params.append(data['prompt_workflow_name'])
if 'content' in data:
update_fields.append("content = %s")
params.append(data['content'])
if update_fields:
params.append(prompt_id)
sql = f"UPDATE ai_prompt_workflow SET {', '.join(update_fields)}, updated_at = NOW() WHERE id = %s"
db_manager.execute_update(sql, params)
# 记录SQL操作日志
log_update(
target_type='prompt_workflow',
target_id=prompt_id,
description=f"更新提示词字段: {', '.join(update_fields)}"
)
# 更新标签关联
if 'tags' in data:
# 删除旧标签关联
del_sql = "DELETE FROM ai_prompt_tags_relation WHERE prompt_workflow_id = %s"
db_manager.execute_update(del_sql, (prompt_id,))
# ✅ 去重处理,避免重复标签导致唯一索引冲突
unique_tags = list(set(data['tags'])) # 去除重复标签
processed_tag_ids = set() # 记录已处理的 tag_id
# 查询prompt_workflow_name
prompt_info = db_manager.execute_query("SELECT prompt_workflow_name FROM ai_prompt_workflow WHERE id = %s", (prompt_id,))
prompt_workflow_name = prompt_info[0]['prompt_workflow_name'] if prompt_info else ''
# 添加新标签
for tag_name in unique_tags:
if not tag_name or not tag_name.strip(): # 跳过空标签
continue
tag_name = tag_name.strip()
# ✅ 查找或创建标签(基于 enterprise_id 隔离)
tag_sql = "SELECT id FROM ai_prompt_tags WHERE enterprise_id = %s AND tag_name = %s"
tag_result = db_manager.execute_query(tag_sql, (enterprise_id, tag_name))
if tag_result:
tag_id = tag_result[0]['id']
else:
tag_insert_sql = "INSERT INTO ai_prompt_tags (enterprise_id, tag_name, created_user_id) VALUES (%s, %s, %s)"
tag_id = db_manager.execute_insert(tag_insert_sql, (enterprise_id, tag_name, current_user.get('user_id', 0)))
# ✅ 检查是否已经处理过该 tag_id避免重复插入
if tag_id in processed_tag_ids:
continue
processed_tag_ids.add(tag_id)
# ✅ 创建关联(添加 enterprise_id
try:
rel_sql = "INSERT INTO ai_prompt_tags_relation (enterprise_id, prompt_workflow_id, prompt_workflow_name, tag_id, tag_name, created_user_id) VALUES (%s, %s, %s, %s, %s, %s)"
db_manager.execute_insert(rel_sql, (enterprise_id, prompt_id, prompt_workflow_name, tag_id, tag_name, current_user.get('user_id', 0)))
except Exception as rel_error:
# 如果关联已存在,跳过
logger.warning(f"标签关联已存在: prompt_id={prompt_id}, tag_id={tag_id}, error={str(rel_error)}")
continue
logger.info(f"[更新提示词] 更新成功, ID: {prompt_id}, 企业ID: {enterprise_id}, IP: {client_ip}")
return jsonify({
'code': 200,
'message': '更新成功',
'data': None,
'timestamp': int(datetime.now().timestamp() * 1000)
})
except Exception as e:
logger.error(f"[更新提示词] 处理请求时发生错误: {str(e)}", exc_info=True)
return jsonify({
'code': 500,
'message': '服务器内部错误',
'data': None
}), 500
@prompt_bp.route('/<int:prompt_id>', methods=['DELETE'])
@require_auth
def delete_prompt(prompt_id):
"""删除提示词"""
client_ip = request.environ.get('HTTP_X_FORWARDED_FOR', request.environ.get('REMOTE_ADDR', '未知'))
logger.info(f"[删除提示词] 开始处理请求, ID: {prompt_id}, IP: {client_ip}")
try:
current_user = AuthUtils.get_current_user()
enterprise_id = current_user.get('enterprise_id')
user_id = current_user.get('user_id')
logger.info(f"[删除提示词] 用户信息 - 用户ID: {user_id}, 企业ID: {enterprise_id}, IP: {client_ip}")
if not enterprise_id:
return jsonify({
'code': 400,
'message': '无法获取企业ID',
'data': None
}), 400
db_manager = get_db_manager()
# 检查提示词是否存在且属于当前企业
check_sql = "SELECT id, prompt_workflow_name FROM ai_prompt_workflow WHERE id = %s AND enterprise_id = %s"
existing = db_manager.execute_query(check_sql, (prompt_id, enterprise_id))
if not existing:
return jsonify({
'code': 404,
'message': '提示词不存在',
'data': None
}), 404
# 删除标签关联
del_rel_sql = "DELETE FROM ai_prompt_tags_relation WHERE prompt_workflow_id = %s"
db_manager.execute_update(del_rel_sql, (prompt_id,))
# 删除提示词
sql = "DELETE FROM ai_prompt_workflow WHERE id = %s"
db_manager.execute_update(sql, (prompt_id,))
# 记录SQL操作日志
log_delete(
target_type='prompt_workflow',
target_id=prompt_id,
description=f"删除提示词: {existing[0]['prompt_workflow_name']}"
)
logger.info(f"[删除提示词] 删除成功, ID: {prompt_id}, 名称: {existing[0]['prompt_workflow_name']}, 企业ID: {enterprise_id}, IP: {client_ip}")
return jsonify({
'code': 200,
'message': '删除成功',
'data': None,
'timestamp': int(datetime.now().timestamp() * 1000)
})
except Exception as e:
logger.error(f"[删除提示词] 处理请求时发生错误: {str(e)}", exc_info=True)
return jsonify({
'code': 500,
'message': '服务器内部错误',
'data': None
}), 500
# ==================== 提示词标签管理 (ai_prompt_tags) ====================
@prompt_bp.route('/tags/list', methods=['GET'])
@require_auth
def get_tags_list():
"""获取标签列表"""
client_ip = request.environ.get('HTTP_X_FORWARDED_FOR', request.environ.get('REMOTE_ADDR', '未知'))
logger.info(f"[获取标签列表] 开始处理请求, IP: {client_ip}")
try:
current_user = AuthUtils.get_current_user()
enterprise_id = current_user.get('enterprise_id')
user_id = current_user.get('user_id')
logger.info(f"[获取标签列表] 用户信息 - 用户ID: {user_id}, 企业ID: {enterprise_id}, IP: {client_ip}")
if not enterprise_id:
return jsonify({
'code': 400,
'message': '无法获取企业ID',
'data': None
}), 400
# 获取查询参数
page = int(request.args.get('page', 1))
page_size = int(request.args.get('pageSize', 20))
keyword = request.args.get('keyword', '').strip()
# 计算偏移量
offset = (page - 1) * page_size
db_manager = get_db_manager()
# ✅ 构建查询条件(基于 enterprise_id 隔离)
where_conditions = ["enterprise_id = %s"]
params = [enterprise_id]
if keyword:
where_conditions.append("tag_name LIKE %s")
params.append(f"%{keyword}%")
where_clause = " WHERE " + " AND ".join(where_conditions)
# 查询总数
count_sql = f"SELECT COUNT(*) as total FROM ai_prompt_tags{where_clause}"
count_result = db_manager.execute_query(count_sql, params)
total = count_result[0]['total']
# 查询标签列表
sql = f"""
SELECT id, tag_name, created_user_id, created_at, updated_at
FROM ai_prompt_tags
{where_clause}
ORDER BY created_at DESC
LIMIT %s OFFSET %s
"""
params.extend([page_size, offset])
tags = db_manager.execute_query(sql, params)
# 格式化日期时间字段
tags = format_datetime_fields(tags)
logger.info(f"[获取标签列表] 查询成功, 总数: {total}, 企业ID: {enterprise_id}, IP: {client_ip}")
return jsonify({
'code': 200,
'message': 'success',
'data': {
'total': total,
'list': tags
},
'timestamp': int(datetime.now().timestamp() * 1000)
})
except Exception as e:
logger.error(f"[获取标签列表] 处理请求时发生错误: {str(e)}", exc_info=True)
return jsonify({
'code': 500,
'message': '服务器内部错误',
'data': None
}), 500
@prompt_bp.route('/tags/create', methods=['POST'])
@require_auth
def create_tag():
"""创建标签"""
client_ip = request.environ.get('HTTP_X_FORWARDED_FOR', request.environ.get('REMOTE_ADDR', '未知'))
logger.info(f"[创建标签] 开始处理请求, IP: {client_ip}")
try:
current_user = AuthUtils.get_current_user()
enterprise_id = current_user.get('enterprise_id')
user_id = current_user.get('user_id', 0)
logger.info(f"[创建标签] 用户信息 - 用户ID: {user_id}, 企业ID: {enterprise_id}, IP: {client_ip}")
if not enterprise_id:
return jsonify({
'code': 400,
'message': '无法获取企业ID',
'data': None
}), 400
data = request.get_json()
if not data or not data.get('tag_name'):
return jsonify({
'code': 400,
'message': '标签名称不能为空',
'data': None
}), 400
db_manager = get_db_manager()
# ✅ 检查标签是否已存在(基于 enterprise_id 隔离)
check_sql = "SELECT id FROM ai_prompt_tags WHERE enterprise_id = %s AND tag_name = %s"
existing = db_manager.execute_query(check_sql, (enterprise_id, data['tag_name']))
if existing:
return jsonify({
'code': 409,
'message': '标签名称已存在',
'data': None
}), 409
# ✅ 创建标签(添加 enterprise_id
sql = """
INSERT INTO ai_prompt_tags (enterprise_id, tag_name, created_user_id)
VALUES (%s, %s, %s)
"""
tag_id = db_manager.execute_insert(sql, (enterprise_id, data['tag_name'], user_id))
# 记录SQL操作日志
log_create(
target_type='prompt_tag',
target_id=tag_id,
description=f"创建标签: {data['tag_name']}"
)
logger.info(f"[创建标签] 创建成功, ID: {tag_id}, 名称: {data['tag_name']}, 企业ID: {enterprise_id}, IP: {client_ip}")
return jsonify({
'code': 200,
'message': '创建成功',
'data': {
'id': tag_id,
'tag_name': data['tag_name']
},
'timestamp': int(datetime.now().timestamp() * 1000)
})
except Exception as e:
logger.error(f"[创建标签] 处理请求时发生错误: {str(e)}", exc_info=True)
return jsonify({
'code': 500,
'message': '服务器内部错误',
'data': None
}), 500
@prompt_bp.route('/tags/<int:tag_id>', methods=['PUT'])
@require_auth
def update_tag(tag_id):
"""更新标签"""
client_ip = request.environ.get('HTTP_X_FORWARDED_FOR', request.environ.get('REMOTE_ADDR', '未知'))
logger.info(f"[更新标签] 开始处理请求, ID: {tag_id}, IP: {client_ip}")
try:
current_user = AuthUtils.get_current_user()
enterprise_id = current_user.get('enterprise_id')
user_id = current_user.get('user_id')
logger.info(f"[更新标签] 用户信息 - 用户ID: {user_id}, 企业ID: {enterprise_id}, IP: {client_ip}")
if not enterprise_id:
return jsonify({
'code': 400,
'message': '无法获取企业ID',
'data': None
}), 400
data = request.get_json()
if not data or not data.get('tag_name'):
return jsonify({
'code': 400,
'message': '标签名称不能为空',
'data': None
}), 400
db_manager = get_db_manager()
# ✅ 检查标签是否存在(基于 enterprise_id 隔离)
check_sql = "SELECT id FROM ai_prompt_tags WHERE id = %s AND enterprise_id = %s"
existing = db_manager.execute_query(check_sql, (tag_id, enterprise_id))
if not existing:
return jsonify({
'code': 404,
'message': '标签不存在',
'data': None
}), 404
# ✅ 检查新名称是否与其他标签重复(基于 enterprise_id 隔离)
dup_sql = "SELECT id FROM ai_prompt_tags WHERE enterprise_id = %s AND tag_name = %s AND id != %s"
duplicate = db_manager.execute_query(dup_sql, (enterprise_id, data['tag_name'], tag_id))
if duplicate:
return jsonify({
'code': 409,
'message': '标签名称已存在',
'data': None
}), 409
# 更新标签
sql = "UPDATE ai_prompt_tags SET tag_name = %s, updated_at = NOW() WHERE id = %s"
db_manager.execute_update(sql, (data['tag_name'], tag_id))
# 同步更新关系表中的标签名称
rel_sql = "UPDATE ai_prompt_tags_relation SET tag_name = %s WHERE tag_id = %s"
db_manager.execute_update(rel_sql, (data['tag_name'], tag_id))
# 记录SQL操作日志
log_update(
target_type='prompt_tag',
target_id=tag_id,
description=f"更新标签: {data['tag_name']}"
)
logger.info(f"[更新标签] 更新成功, ID: {tag_id}, 名称: {data['tag_name']}, 企业ID: {enterprise_id}, IP: {client_ip}")
return jsonify({
'code': 200,
'message': '更新成功',
'data': None,
'timestamp': int(datetime.now().timestamp() * 1000)
})
except Exception as e:
logger.error(f"[更新标签] 处理请求时发生错误: {str(e)}", exc_info=True)
return jsonify({
'code': 500,
'message': '服务器内部错误',
'data': None
}), 500
@prompt_bp.route('/tags/<int:tag_id>', methods=['DELETE'])
@require_auth
def delete_tag(tag_id):
"""删除标签"""
client_ip = request.environ.get('HTTP_X_FORWARDED_FOR', request.environ.get('REMOTE_ADDR', '未知'))
logger.info(f"[删除标签] 开始处理请求, ID: {tag_id}, IP: {client_ip}")
try:
current_user = AuthUtils.get_current_user()
enterprise_id = current_user.get('enterprise_id')
user_id = current_user.get('user_id')
logger.info(f"[删除标签] 用户信息 - 用户ID: {user_id}, 企业ID: {enterprise_id}, IP: {client_ip}")
if not enterprise_id:
return jsonify({
'code': 400,
'message': '无法获取企业ID',
'data': None
}), 400
db_manager = get_db_manager()
# ✅ 检查标签是否存在(基于 enterprise_id 隔离)
check_sql = "SELECT id, tag_name FROM ai_prompt_tags WHERE id = %s AND enterprise_id = %s"
existing = db_manager.execute_query(check_sql, (tag_id, enterprise_id))
if not existing:
return jsonify({
'code': 404,
'message': '标签不存在',
'data': None
}), 404
# 检查是否有提示词正在使用该标签
rel_sql = "SELECT COUNT(*) as count FROM ai_prompt_tags_relation WHERE tag_id = %s"
rel_result = db_manager.execute_query(rel_sql, (tag_id,))
if rel_result[0]['count'] > 0:
return jsonify({
'code': 409,
'message': '该标签正在被使用,无法删除',
'data': None
}), 409
# 删除标签
sql = "DELETE FROM ai_prompt_tags WHERE id = %s"
db_manager.execute_update(sql, (tag_id,))
# 记录SQL操作日志
log_delete(
target_type='prompt_tag',
target_id=tag_id,
description=f"删除标签: {existing[0]['tag_name']}"
)
logger.info(f"[删除标签] 删除成功, ID: {tag_id}, 名称: {existing[0]['tag_name']}, 企业ID: {enterprise_id}, IP: {client_ip}")
return jsonify({
'code': 200,
'message': '删除成功',
'data': None,
'timestamp': int(datetime.now().timestamp() * 1000)
})
except Exception as e:
logger.error(f"[删除标签] 处理请求时发生错误: {str(e)}", exc_info=True)
return jsonify({
'code': 500,
'message': '服务器内部错误',
'data': None
}), 500

507
release/32/user_routes.py Normal file
View File

@@ -0,0 +1,507 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
用户管理接口
"""
from flask import Blueprint, request, jsonify
import logging
from datetime import datetime
from auth_utils import require_auth, require_role, AuthUtils
from database_config import get_db_manager, format_datetime_fields
from log_utils import log_create, log_update, log_delete, log_error, log_operation
logger = logging.getLogger('article_server')
# 创建蓝图
user_bp = Blueprint('user', __name__, url_prefix='/api/users')
@user_bp.route('', methods=['GET'])
@require_auth
def get_users():
"""获取用户列表"""
try:
# 获取查询参数
page = int(request.args.get('page', 1))
size = int(request.args.get('size', 10))
role = request.args.get('role')
status = request.args.get('status')
# 构建查询条件
where_conditions = ["1=1"]
params = []
if role:
where_conditions.append("role = %s")
params.append(role)
if status:
where_conditions.append("status = %s")
params.append(status)
where_clause = " AND ".join(where_conditions)
# 计算偏移量
offset = (page - 1) * size
db_manager = get_db_manager()
# 查询总数
count_sql = f"SELECT COUNT(*) as total FROM wht_admin_users WHERE {where_clause}"
count_result = db_manager.execute_query(count_sql, params)
total = count_result[0]['total']
# 查询用户列表
sql = f"""
SELECT id, username, real_name, email, phone, role, status, created_at, updated_at
FROM wht_admin_users
WHERE {where_clause}
ORDER BY created_at DESC
LIMIT %s OFFSET %s
"""
params.extend([size, offset])
users = db_manager.execute_query(sql, params)
# 格式化日期时间字段
users = format_datetime_fields(users)
# 记录操作日志
current_user = AuthUtils.get_current_user()
log_sql = """
INSERT INTO wht_logs (user_id, action, description, ip_address, user_agent, status)
VALUES (%s, %s, %s, %s, %s, %s)
"""
client_ip = request.environ.get('HTTP_X_FORWARDED_FOR', request.environ.get('REMOTE_ADDR', '未知'))
user_agent = request.headers.get('User-Agent', '未知')
db_manager.execute_insert(log_sql, (
current_user['user_id'],
'get_users',
f'获取用户列表,总数: {total}',
client_ip,
user_agent,
'success'
))
logger.info(f"获取用户列表成功,总数: {total}")
return jsonify({
'code': 200,
'message': '获取成功',
'data': {
'list': users,
'total': total,
'page': page,
'size': size
},
'timestamp': int(datetime.now().timestamp() * 1000)
})
except Exception as e:
logger.error(f"[获取用户列表] 处理请求时发生错误: {str(e)}", exc_info=True)
return jsonify({
'code': 500,
'message': '服务器内部错误',
'data': None
}), 500
@user_bp.route('/<int:user_id>', methods=['GET'])
@require_auth
def get_user(user_id):
"""获取特定用户"""
try:
db_manager = get_db_manager()
sql = """
SELECT id, username, real_name, email, phone, role, status, created_at, updated_at
FROM wht_admin_users
WHERE id = %s AND status != 'deleted'
"""
result = db_manager.execute_query(sql, (user_id,))
logger.info(f"SQL查询结果: {result}")
if not result:
return jsonify({
'code': 404,
'message': '用户不存在',
'data': None
}), 404
user_data = result[0]
# 格式化日期时间字段
user_data = format_datetime_fields(user_data)
# 记录操作日志
current_user = AuthUtils.get_current_user()
log_sql = """
INSERT INTO wht_logs (user_id, action, target_type, target_id, description, ip_address, user_agent, status)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
"""
client_ip = request.environ.get('HTTP_X_FORWARDED_FOR', request.environ.get('REMOTE_ADDR', '未知'))
user_agent = request.headers.get('User-Agent', '未知')
db_manager.execute_insert(log_sql, (
current_user['user_id'],
'get_user',
'user',
user_id,
f'获取用户信息: {user_data["username"]}',
client_ip,
user_agent,
'success'
))
logger.info(f"获取用户信息成功: {user_data['username']}")
return jsonify({
'code': 200,
'message': '获取成功',
'data': user_data,
'timestamp': int(datetime.now().timestamp() * 1000)
})
except Exception as e:
logger.error(f"[获取用户信息] 处理请求时发生错误: {str(e)}", exc_info=True)
return jsonify({
'code': 500,
'message': '服务器内部错误',
'data': None
}), 500
@user_bp.route('', methods=['POST'])
@require_auth
@require_role('admin')
def create_user():
"""创建用户"""
try:
data = request.get_json()
if not data:
return jsonify({
'code': 400,
'message': '请求参数错误',
'data': None
}), 400
# 验证必需字段
required_fields = ['username', 'password', 'real_name', 'role']
for field in required_fields:
if not data.get(field):
return jsonify({
'code': 400,
'message': f'缺少必需字段: {field}',
'data': None
}), 400
# 数据验证
import re
# 验证用户名长度
if len(data['username']) > 50:
return jsonify({
'code': 400,
'message': '用户名长度不能超过50个字符',
'data': None
}), 400
# 验证密码长度
if len(data['password']) < 6:
return jsonify({
'code': 400,
'message': '密码长度不能少于6个字符',
'data': None
}), 400
# 验证邮箱格式
if data.get('email'):
email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
if not re.match(email_pattern, data['email']):
return jsonify({
'code': 400,
'message': '邮箱格式不正确',
'data': None
}), 400
# 验证角色
valid_roles = ['admin', 'editor', 'reviewer', 'publisher']
if data['role'] not in valid_roles:
return jsonify({
'code': 400,
'message': '无效的用户角色',
'data': None
}), 400
# 检查用户名是否已存在
db_manager = get_db_manager()
check_sql = "SELECT id FROM wht_admin_users WHERE username = %s"
existing_user = db_manager.execute_query(check_sql, (data['username'],))
if existing_user:
return jsonify({
'code': 409,
'message': '用户名已存在',
'data': None
}), 409
# 创建用户
sql = """
INSERT INTO wht_admin_users (username, password, real_name, email, phone, role, status)
VALUES (%s, %s, %s, %s, %s, %s, %s)
"""
hashed_password = AuthUtils.hash_password(data['password'])
user_id = db_manager.execute_insert(sql, (
data['username'],
hashed_password,
data['real_name'],
data.get('email'),
data.get('phone'),
data['role'],
'active'
))
# 记录操作日志
current_user = AuthUtils.get_current_user()
log_sql = """
INSERT INTO wht_logs (user_id, action, target_type, target_id, description, ip_address, user_agent, status)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
"""
client_ip = request.environ.get('HTTP_X_FORWARDED_FOR', request.environ.get('REMOTE_ADDR', '未知'))
user_agent = request.headers.get('User-Agent', '未知')
db_manager.execute_insert(log_sql, (
current_user['user_id'],
'create_user',
'user',
user_id,
f'创建用户: {data["username"]}',
client_ip,
user_agent,
'success'
))
logger.info(f"创建用户成功: {data['username']}, ID: {user_id}")
return jsonify({
'code': 200,
'message': '创建成功',
'data': {'id': user_id},
'timestamp': int(datetime.now().timestamp() * 1000)
})
except Exception as e:
logger.error(f"[创建用户] 处理请求时发生错误: {str(e)}", exc_info=True)
return jsonify({
'code': 500,
'message': '服务器内部错误',
'data': None
}), 500
@user_bp.route('/<int:user_id>', methods=['PUT'])
@require_auth
@require_role('admin')
def update_user(user_id):
"""更新用户"""
try:
data = request.get_json()
if not data:
return jsonify({
'code': 400,
'message': '请求参数错误',
'data': None
}), 400
# 检查用户是否存在
db_manager = get_db_manager()
check_sql = "SELECT id, username FROM wht_admin_users WHERE id = %s"
existing_user = db_manager.execute_query(check_sql, (user_id,))
if not existing_user:
return jsonify({
'code': 404,
'message': '用户不存在',
'data': None
}), 404
# 构建更新字段
update_fields = []
params = []
if 'real_name' in data:
update_fields.append("real_name = %s")
params.append(data['real_name'])
if 'email' in data:
update_fields.append("email = %s")
params.append(data['email'])
if 'phone' in data:
update_fields.append("phone = %s")
params.append(data['phone'])
if 'role' in data:
update_fields.append("role = %s")
params.append(data['role'])
if 'status' in data:
update_fields.append("status = %s")
params.append(data['status'])
if not update_fields:
return jsonify({
'code': 400,
'message': '没有要更新的字段',
'data': None
}), 400
# 执行更新
params.append(user_id)
sql = f"UPDATE wht_admin_users SET {', '.join(update_fields)} WHERE id = %s"
affected_rows = db_manager.execute_update(sql, params)
# 记录操作日志
current_user = AuthUtils.get_current_user()
log_sql = """
INSERT INTO wht_logs (user_id, action, target_type, target_id, description, ip_address, user_agent, status)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
"""
client_ip = request.environ.get('HTTP_X_FORWARDED_FOR', request.environ.get('REMOTE_ADDR', '未知'))
user_agent = request.headers.get('User-Agent', '未知')
db_manager.execute_insert(log_sql, (
current_user['user_id'],
'update_user',
'user',
user_id,
f'更新用户: {existing_user[0]["username"]}',
client_ip,
user_agent,
'success'
))
logger.info(f"更新用户成功: {existing_user[0]['username']}, 影响行数: {affected_rows}")
return jsonify({
'code': 200,
'message': '更新成功',
'data': None,
'timestamp': int(datetime.now().timestamp() * 1000)
})
except Exception as e:
logger.error(f"[更新用户] 处理请求时发生错误: {str(e)}", exc_info=True)
return jsonify({
'code': 500,
'message': '服务器内部错误',
'data': None
}), 500
@user_bp.route('/<int:user_id>', methods=['DELETE'])
@require_auth
@require_role('admin')
def delete_user(user_id):
"""删除用户"""
try:
# 检查用户是否存在
db_manager = get_db_manager()
check_sql = "SELECT id, username FROM wht_admin_users WHERE id = %s"
existing_user = db_manager.execute_query(check_sql, (user_id,))
if not existing_user:
return jsonify({
'code': 404,
'message': '用户不存在',
'data': None
}), 404
# 软删除用户设置状态为deleted
sql = "UPDATE wht_admin_users SET status = 'deleted' WHERE id = %s"
affected_rows = db_manager.execute_update(sql, (user_id,))
# 记录操作日志
current_user = AuthUtils.get_current_user()
log_sql = """
INSERT INTO wht_logs (user_id, action, target_type, target_id, description, ip_address, user_agent, status)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
"""
client_ip = request.environ.get('HTTP_X_FORWARDED_FOR', request.environ.get('REMOTE_ADDR', '未知'))
user_agent = request.headers.get('User-Agent', '未知')
db_manager.execute_insert(log_sql, (
current_user['user_id'],
'delete_user',
'user',
user_id,
f'删除用户: {existing_user[0]["username"]}',
client_ip,
user_agent,
'success'
))
logger.info(f"删除用户成功: {existing_user[0]['username']}, 影响行数: {affected_rows}")
return jsonify({
'code': 200,
'message': '删除成功',
'data': None,
'timestamp': int(datetime.now().timestamp() * 1000)
})
except Exception as e:
logger.error(f"[删除用户] 处理请求时发生错误: {str(e)}", exc_info=True)
return jsonify({
'code': 500,
'message': '服务器内部错误',
'data': None
}), 500
@user_bp.route('/info', methods=['GET'])
@require_auth
def get_user_info():
"""获取当前用户信息默认不包含password企业主可通过action=need_password获取"""
client_ip = request.environ.get('HTTP_X_FORWARDED_FOR', request.environ.get('REMOTE_ADDR', '未知'))
logger.info(f"[获取用户信息] 开始处理请求, IP: {client_ip}")
try:
current_user = AuthUtils.get_current_user()
user_id = current_user.get('user_id')
if not user_id:
logger.warning(f"[获取用户信息] 无法获取用户ID, IP: {client_ip}")
return jsonify({'code': 400, 'message': '无法获取用户ID', 'data': None}), 400
# 获取action参数
action = request.args.get('action', '').strip()
logger.info(f"[获取用户信息] 用户ID: {user_id}, action: {action}, IP: {client_ip}")
db_manager = get_db_manager()
# 查询用户信息
# 从ai_authors表获取xhs_cookie, xhs_phone, xhs_account, bound_at字段以优化性能
sql = """
SELECT id, enterprise_id, enterprise_name, username, real_name, email, phone,
wechat_openid, wechat_unionid, password,
is_bound_xhs, department, role, status, created_at, updated_at
FROM ai_users u
WHERE id = %s AND status != 'deleted'
"""
result = db_manager.execute_query(sql, (user_id,))
if not result:
logger.warning(f"[获取用户信息] 用户不存在, ID: {user_id}, IP: {client_ip}")
return jsonify({'code': 404, 'message': '用户不存在', 'data': None}), 404
user_info = result[0]
# 记录操作日志
log_operation(
action='get_user_info',
target_type='user',
target_id=user_id,
description=f"查询用户信息: {user_info.get('username')}, action={action}"
)
return jsonify({
'code': 200,
'message': 'success',
'data': user_info,
'timestamp': int(datetime.now().timestamp() * 1000)
})
except Exception as e:
logger.error(f"[获取用户信息] 错误: {str(e)}", exc_info=True)
return jsonify({'code': 500, 'message': '服务器内部错误', 'data': None}), 500