first commit

This commit is contained in:
rjb
2025-12-20 23:19:19 +08:00
parent 4129d63afc
commit b728d729e6
14 changed files with 2850 additions and 2101 deletions

View File

@@ -1900,3 +1900,239 @@ werkzeug.routing.exceptions.BuildError: Could not build url for endpoint 'meal_p
2025-10-17 23:09:02,391 INFO: 应用启动 [in /home/renjianbo/aitsc/config/base.py:82]
2025-10-17 23:11:02,368 INFO: 应用启动 [in /home/renjianbo/aitsc/config/base.py:82]
2025-10-17 23:17:26,078 INFO: 应用启动 [in /home/renjianbo/aitsc/config/base.py:82]
2025-10-18 08:48:09,480 WARNING: 慢查询检测: 1.75s - SELECT admin_user.id AS admin_user_id, admin_user.username AS admin_user_username, admin_user.passwo... [in /home/renjianbo/aitsc/src/flask_prompt_master/utils/performance_monitor.py:35]
2025-10-27 11:27:36,580 ERROR: LLM API调用失败 (尝试 1/3): [Errno 5] Input/output error [in /home/renjianbo/aitsc/src/flask_prompt_master/routes/routes.py:100]
2025-10-27 11:27:45,432 ERROR: LLM API调用失败 (尝试 2/3): [Errno 5] Input/output error [in /home/renjianbo/aitsc/src/flask_prompt_master/routes/routes.py:100]
2025-10-27 11:27:56,356 ERROR: LLM API调用失败 (尝试 3/3): [Errno 5] Input/output error [in /home/renjianbo/aitsc/src/flask_prompt_master/routes/routes.py:100]
2025-10-27 11:27:56,361 ERROR: Exception on / [POST] [in /home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/flask/app.py:1414]
Traceback (most recent call last):
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/pymysql/connections.py", line 644, in connect
sock = socket.create_connection(
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/socket.py", line 865, in create_connection
raise exceptions[0]
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/socket.py", line 850, in create_connection
sock.connect(sa)
ConnectionRefusedError: [Errno 111] Connection refused
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/renjianbo/aitsc/src/flask_prompt_master/routes/routes.py", line 208, in index
conn = pymysql.connect(
^^^^^^^^^^^^^^^^
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/pymysql/connections.py", line 358, in __init__
self.connect()
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/pymysql/connections.py", line 711, in connect
raise exc
pymysql.err.OperationalError: (2003, "Can't connect to MySQL server on 'localhost' ([Errno 111] Connection refused)")
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/flask/app.py", line 2190, in wsgi_app
response = self.full_dispatch_request()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/flask/app.py", line 1486, in full_dispatch_request
rv = self.handle_user_exception(e)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/flask_cors/extension.py", line 176, in wrapped_function
return cors_after_request(app.make_response(f(*args, **kwargs)))
^^^^^^^^^^^^^^^^^^
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/flask/app.py", line 1484, in full_dispatch_request
rv = self.dispatch_request()
^^^^^^^^^^^^^^^^^^^^^^^
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/flask/app.py", line 1469, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/renjianbo/aitsc/src/flask_prompt_master/routes/routes.py", line 225, in index
print(f"获取用户ID失败: {str(e)}")
OSError: [Errno 5] Input/output error
2025-10-27 11:28:15,195 ERROR: LLM API调用失败 (尝试 1/3): [Errno 5] Input/output error [in /home/renjianbo/aitsc/src/flask_prompt_master/routes/routes.py:100]
2025-10-27 11:28:24,273 ERROR: LLM API调用失败 (尝试 2/3): [Errno 5] Input/output error [in /home/renjianbo/aitsc/src/flask_prompt_master/routes/routes.py:100]
2025-10-27 11:28:37,182 ERROR: LLM API调用失败 (尝试 3/3): [Errno 5] Input/output error [in /home/renjianbo/aitsc/src/flask_prompt_master/routes/routes.py:100]
2025-10-27 11:28:37,184 ERROR: Exception on / [POST] [in /home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/flask/app.py:1414]
Traceback (most recent call last):
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/pymysql/connections.py", line 644, in connect
sock = socket.create_connection(
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/socket.py", line 865, in create_connection
raise exceptions[0]
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/socket.py", line 850, in create_connection
sock.connect(sa)
ConnectionRefusedError: [Errno 111] Connection refused
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/renjianbo/aitsc/src/flask_prompt_master/routes/routes.py", line 208, in index
conn = pymysql.connect(
^^^^^^^^^^^^^^^^
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/pymysql/connections.py", line 358, in __init__
self.connect()
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/pymysql/connections.py", line 711, in connect
raise exc
pymysql.err.OperationalError: (2003, "Can't connect to MySQL server on 'localhost' ([Errno 111] Connection refused)")
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/flask/app.py", line 2190, in wsgi_app
response = self.full_dispatch_request()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/flask/app.py", line 1486, in full_dispatch_request
rv = self.handle_user_exception(e)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/flask_cors/extension.py", line 176, in wrapped_function
return cors_after_request(app.make_response(f(*args, **kwargs)))
^^^^^^^^^^^^^^^^^^
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/flask/app.py", line 1484, in full_dispatch_request
rv = self.dispatch_request()
^^^^^^^^^^^^^^^^^^^^^^^
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/flask/app.py", line 1469, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/renjianbo/aitsc/src/flask_prompt_master/routes/routes.py", line 225, in index
print(f"获取用户ID失败: {str(e)}")
OSError: [Errno 5] Input/output error
2025-10-28 07:52:24,409 ERROR: LLM API调用失败 (尝试 1/3): [Errno 5] Input/output error [in /home/renjianbo/aitsc/src/flask_prompt_master/routes/routes.py:100]
2025-10-28 07:52:39,998 ERROR: LLM API调用失败 (尝试 2/3): [Errno 5] Input/output error [in /home/renjianbo/aitsc/src/flask_prompt_master/routes/routes.py:100]
2025-10-28 07:52:55,022 ERROR: LLM API调用失败 (尝试 3/3): [Errno 5] Input/output error [in /home/renjianbo/aitsc/src/flask_prompt_master/routes/routes.py:100]
2025-10-28 07:52:55,024 ERROR: Exception on / [POST] [in /home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/flask/app.py:1414]
Traceback (most recent call last):
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/pymysql/connections.py", line 644, in connect
sock = socket.create_connection(
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/socket.py", line 865, in create_connection
raise exceptions[0]
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/socket.py", line 850, in create_connection
sock.connect(sa)
ConnectionRefusedError: [Errno 111] Connection refused
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/renjianbo/aitsc/src/flask_prompt_master/routes/routes.py", line 208, in index
conn = pymysql.connect(
^^^^^^^^^^^^^^^^
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/pymysql/connections.py", line 358, in __init__
self.connect()
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/pymysql/connections.py", line 711, in connect
raise exc
pymysql.err.OperationalError: (2003, "Can't connect to MySQL server on 'localhost' ([Errno 111] Connection refused)")
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/flask/app.py", line 2190, in wsgi_app
response = self.full_dispatch_request()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/flask/app.py", line 1486, in full_dispatch_request
rv = self.handle_user_exception(e)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/flask_cors/extension.py", line 176, in wrapped_function
return cors_after_request(app.make_response(f(*args, **kwargs)))
^^^^^^^^^^^^^^^^^^
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/flask/app.py", line 1484, in full_dispatch_request
rv = self.dispatch_request()
^^^^^^^^^^^^^^^^^^^^^^^
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/flask/app.py", line 1469, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/renjianbo/aitsc/src/flask_prompt_master/routes/routes.py", line 225, in index
print(f"获取用户ID失败: {str(e)}")
OSError: [Errno 5] Input/output error
2025-10-28 08:00:33,784 ERROR: LLM API调用失败 (尝试 1/3): [Errno 5] Input/output error [in /home/renjianbo/aitsc/src/flask_prompt_master/routes/routes.py:100]
2025-10-28 08:00:54,337 ERROR: LLM API调用失败 (尝试 2/3): [Errno 5] Input/output error [in /home/renjianbo/aitsc/src/flask_prompt_master/routes/routes.py:100]
2025-10-28 08:01:15,922 ERROR: LLM API调用失败 (尝试 3/3): [Errno 5] Input/output error [in /home/renjianbo/aitsc/src/flask_prompt_master/routes/routes.py:100]
2025-10-28 08:01:58,631 ERROR: LLM API调用失败 (尝试 1/3): [Errno 5] Input/output error [in /home/renjianbo/aitsc/src/flask_prompt_master/routes/routes.py:100]
2025-10-28 08:02:10,952 ERROR: LLM API调用失败 (尝试 2/3): [Errno 5] Input/output error [in /home/renjianbo/aitsc/src/flask_prompt_master/routes/routes.py:100]
2025-10-28 08:02:19,800 ERROR: LLM API调用失败 (尝试 1/3): [Errno 5] Input/output error [in /home/renjianbo/aitsc/src/flask_prompt_master/routes/routes.py:100]
2025-10-28 08:02:30,316 ERROR: LLM API调用失败 (尝试 3/3): [Errno 5] Input/output error [in /home/renjianbo/aitsc/src/flask_prompt_master/routes/routes.py:100]
2025-10-28 08:02:30,319 ERROR: Exception on / [POST] [in /home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/flask/app.py:1414]
Traceback (most recent call last):
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/pymysql/connections.py", line 644, in connect
sock = socket.create_connection(
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/socket.py", line 865, in create_connection
raise exceptions[0]
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/socket.py", line 850, in create_connection
sock.connect(sa)
ConnectionRefusedError: [Errno 111] Connection refused
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/renjianbo/aitsc/src/flask_prompt_master/routes/routes.py", line 208, in index
get_template_icon=get_template_icon, industries=industries,
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/pymysql/connections.py", line 358, in __init__
self.connect()
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/pymysql/connections.py", line 711, in connect
raise exc
pymysql.err.OperationalError: (2003, "Can't connect to MySQL server on 'localhost' ([Errno 111] Connection refused)")
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/flask/app.py", line 2190, in wsgi_app
response = self.full_dispatch_request()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/flask/app.py", line 1486, in full_dispatch_request
rv = self.handle_user_exception(e)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/flask_cors/extension.py", line 176, in wrapped_function
return cors_after_request(app.make_response(f(*args, **kwargs)))
^^^^^^^^^^^^^^^^^^
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/flask/app.py", line 1484, in full_dispatch_request
rv = self.dispatch_request()
^^^^^^^^^^^^^^^^^^^^^^^
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/flask/app.py", line 1469, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/renjianbo/aitsc/src/flask_prompt_master/routes/routes.py", line 225, in index
OSError: [Errno 5] Input/output error
2025-10-28 08:02:33,775 ERROR: LLM API调用失败 (尝试 2/3): [Errno 5] Input/output error [in /home/renjianbo/aitsc/src/flask_prompt_master/routes/routes.py:100]
2025-10-28 08:02:46,133 ERROR: LLM API调用失败 (尝试 3/3): [Errno 5] Input/output error [in /home/renjianbo/aitsc/src/flask_prompt_master/routes/routes.py:100]
2025-10-28 08:02:46,135 ERROR: Exception on / [POST] [in /home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/flask/app.py:1414]
Traceback (most recent call last):
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/pymysql/connections.py", line 644, in connect
sock = socket.create_connection(
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/socket.py", line 865, in create_connection
raise exceptions[0]
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/socket.py", line 850, in create_connection
sock.connect(sa)
ConnectionRefusedError: [Errno 111] Connection refused
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/renjianbo/aitsc/src/flask_prompt_master/routes/routes.py", line 208, in index
get_template_icon=get_template_icon, industries=industries,
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/pymysql/connections.py", line 358, in __init__
self.connect()
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/pymysql/connections.py", line 711, in connect
raise exc
pymysql.err.OperationalError: (2003, "Can't connect to MySQL server on 'localhost' ([Errno 111] Connection refused)")
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/flask/app.py", line 2190, in wsgi_app
response = self.full_dispatch_request()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/flask/app.py", line 1486, in full_dispatch_request
rv = self.handle_user_exception(e)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/flask_cors/extension.py", line 176, in wrapped_function
return cors_after_request(app.make_response(f(*args, **kwargs)))
^^^^^^^^^^^^^^^^^^
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/flask/app.py", line 1484, in full_dispatch_request
rv = self.dispatch_request()
^^^^^^^^^^^^^^^^^^^^^^^
File "/home/renjianbo/miniconda3/envs/myenv/lib/python3.12/site-packages/flask/app.py", line 1469, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/renjianbo/aitsc/src/flask_prompt_master/routes/routes.py", line 225, in index
OSError: [Errno 5] Input/output error
2025-10-28 08:04:36,598 INFO: 应用启动 [in /home/renjianbo/aitsc/config/base.py:82]

View File

@@ -1 +1 @@
11425
24197

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,463 +0,0 @@
"""
优化历史功能API接口
使用腾讯云prompt表
"""
from flask import Blueprint, request, jsonify, current_app, render_template
from flask_login import login_required, current_user
from datetime import datetime, date, timedelta
from sqlalchemy import func, desc, or_
import time
import pymysql
# 导入数据库模型
from ..models.models import db, Prompt, User, WxUser
# 创建蓝图
optimization_history_bp = Blueprint('optimization_history', __name__)
def get_current_user_id():
"""获取当前用户ID如果没有登录用户则返回默认用户ID"""
try:
return current_user.id if current_user.is_authenticated else 1
except:
return 1
def get_tencent_db_connection():
"""获取腾讯云数据库连接"""
try:
conn = pymysql.connect(
host='gz-cynosdbmysql-grp-d26pzce5.sql.tencentcdb.com',
port=24936,
user='root',
password='!Rjb12191',
database='pro_db',
charset='utf8mb4'
)
return conn
except Exception as e:
current_app.logger.error(f"连接腾讯云数据库失败: {str(e)}")
return None
@optimization_history_bp.route('/optimization-history')
# @login_required # 暂时注释掉登录要求,用于测试
def optimization_history_page():
"""优化历史页面"""
return render_template('optimization_history.html')
@optimization_history_bp.route('/api/optimization-history', methods=['GET'])
# @login_required # 暂时注释掉登录要求,用于测试
def get_optimization_history():
"""获取用户优化历史记录 - 使用腾讯云prompt表"""
try:
page = request.args.get('page', 1, type=int)
per_page = request.args.get('per_page', 20, type=int)
search = request.args.get('search', '')
date_filter = request.args.get('date_filter', '')
# 获取腾讯云数据库连接
conn = get_tencent_db_connection()
if not conn:
return jsonify({
'success': False,
'message': '数据库连接失败'
}), 500
cursor = conn.cursor()
# 构建查询条件
where_conditions = []
params = []
# 用户ID条件
user_id = get_current_user_id()
where_conditions.append("(user_id = %s OR wx_user_id = %s)")
params.extend([user_id, user_id])
# 搜索条件
if search:
where_conditions.append("(input_text LIKE %s OR generated_text LIKE %s)")
search_param = f"%{search}%"
params.extend([search_param, search_param])
# 日期过滤
if date_filter:
if date_filter == 'today':
where_conditions.append("DATE(created_at) = CURDATE()")
elif date_filter == 'week':
where_conditions.append("created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY)")
elif date_filter == 'month':
where_conditions.append("created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY)")
# 构建完整查询
where_clause = " AND ".join(where_conditions) if where_conditions else "1=1"
# 获取总数
count_sql = f"SELECT COUNT(*) FROM prompt WHERE {where_clause}"
cursor.execute(count_sql, params)
total = cursor.fetchone()[0]
# 计算分页
offset = (page - 1) * per_page
total_pages = (total + per_page - 1) // per_page
# 获取数据
data_sql = f"""
SELECT id, input_text, generated_text, created_at, user_id, wx_user_id
FROM prompt
WHERE {where_clause}
ORDER BY created_at DESC
LIMIT %s OFFSET %s
"""
cursor.execute(data_sql, params + [per_page, offset])
results = cursor.fetchall()
# 格式化数据
history_list = []
for row in results:
history_dict = {
'id': row[0],
'original_text': row[1],
'optimized_text': row[2],
'created_at': row[3].strftime('%Y-%m-%d %H:%M:%S') if row[3] else None,
'user_id': row[4],
'wx_user_id': row[5],
'optimization_type': '提示词优化',
'satisfaction_rating': None,
'is_favorite': False
}
history_list.append(history_dict)
cursor.close()
conn.close()
return jsonify({
'success': True,
'data': {
'history': history_list,
'pagination': {
'page': page,
'per_page': per_page,
'total': total,
'pages': total_pages,
'has_next': page < total_pages,
'has_prev': page > 1
}
}
})
except Exception as e:
current_app.logger.error(f"获取优化历史失败: {str(e)}")
return jsonify({
'success': False,
'message': '获取历史记录失败'
}), 500
@optimization_history_bp.route('/api/optimization-history', methods=['POST'])
# @login_required # 暂时注释掉登录要求,用于测试
def add_optimization_history():
"""添加优化历史记录 - 使用腾讯云prompt表"""
try:
data = request.get_json()
# 验证必需字段
required_fields = ['original_text', 'optimized_text']
for field in required_fields:
if field not in data or not data[field]:
return jsonify({
'success': False,
'message': f'缺少必需字段: {field}'
}), 400
# 获取腾讯云数据库连接
conn = get_tencent_db_connection()
if not conn:
return jsonify({
'success': False,
'message': '数据库连接失败'
}), 500
cursor = conn.cursor()
# 获取用户ID
user_id = get_current_user_id()
# 插入数据到prompt表
insert_sql = """
INSERT INTO prompt (input_text, generated_text, user_id, wx_user_id, created_at)
VALUES (%s, %s, %s, %s, NOW())
"""
cursor.execute(insert_sql, [
data['original_text'],
data['optimized_text'],
user_id,
data.get('wx_user_id', user_id) # 如果有微信用户ID则使用否则使用普通用户ID
])
# 获取插入的记录ID
prompt_id = cursor.lastrowid
conn.commit()
cursor.close()
conn.close()
# 返回结果
result_data = {
'id': prompt_id,
'original_text': data['original_text'],
'optimized_text': data['optimized_text'],
'user_id': user_id,
'wx_user_id': data.get('wx_user_id', user_id),
'created_at': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
'optimization_type': '提示词优化',
'satisfaction_rating': None,
'is_favorite': False
}
return jsonify({
'success': True,
'data': result_data,
'message': '历史记录添加成功'
})
except Exception as e:
import traceback
current_app.logger.error(f"添加优化历史失败: {str(e)}")
current_app.logger.error(f"错误堆栈: {traceback.format_exc()}")
return jsonify({
'success': False,
'message': f'添加历史记录失败: {str(e)}'
}), 500
@optimization_history_bp.route('/api/optimization-history/<int:history_id>/rating', methods=['PUT'])
# @login_required # 暂时注释掉登录要求,用于测试
def update_rating(history_id):
"""更新满意度评分 - 简化版本,仅返回成功"""
try:
data = request.get_json()
rating = data.get('rating')
if not rating or not isinstance(rating, int) or rating < 1 or rating > 5:
return jsonify({
'success': False,
'message': '评分必须在1-5之间'
}), 400
# 由于prompt表没有评分字段这里仅返回成功
# 在实际应用中可以考虑添加评分字段到prompt表
return jsonify({
'success': True,
'message': '评分记录成功(注意:当前版本暂不支持评分存储)'
})
except Exception as e:
current_app.logger.error(f"更新评分失败: {str(e)}")
return jsonify({
'success': False,
'message': '更新评分失败'
}), 500
@optimization_history_bp.route('/api/optimization-history/<int:history_id>', methods=['DELETE'])
# @login_required # 暂时注释掉登录要求,用于测试
def delete_optimization_history(history_id):
"""删除优化历史记录 - 使用腾讯云prompt表"""
try:
# 获取腾讯云数据库连接
conn = get_tencent_db_connection()
if not conn:
return jsonify({
'success': False,
'message': '数据库连接失败'
}), 500
cursor = conn.cursor()
# 检查记录是否存在
check_sql = "SELECT id FROM prompt WHERE id = %s"
cursor.execute(check_sql, [history_id])
if not cursor.fetchone():
cursor.close()
conn.close()
return jsonify({
'success': False,
'message': '历史记录不存在'
}), 404
# 删除记录
delete_sql = "DELETE FROM prompt WHERE id = %s"
cursor.execute(delete_sql, [history_id])
conn.commit()
cursor.close()
conn.close()
return jsonify({
'success': True,
'message': '历史记录删除成功'
})
except Exception as e:
current_app.logger.error(f"删除优化历史失败: {str(e)}")
return jsonify({
'success': False,
'message': '删除历史记录失败'
}), 500
@optimization_history_bp.route('/api/optimization-history/clear', methods=['DELETE'])
# @login_required # 暂时注释掉登录要求,用于测试
def clear_optimization_history():
"""清空用户优化历史记录 - 使用腾讯云prompt表"""
try:
# 获取腾讯云数据库连接
conn = get_tencent_db_connection()
if not conn:
return jsonify({
'success': False,
'message': '数据库连接失败'
}), 500
cursor = conn.cursor()
# 获取用户ID
user_id = get_current_user_id()
# 删除用户的所有记录
delete_sql = "DELETE FROM prompt WHERE user_id = %s OR wx_user_id = %s"
cursor.execute(delete_sql, [user_id, user_id])
deleted_count = cursor.rowcount
conn.commit()
cursor.close()
conn.close()
return jsonify({
'success': True,
'message': f'历史记录清空成功,共删除 {deleted_count} 条记录'
})
except Exception as e:
current_app.logger.error(f"清空优化历史失败: {str(e)}")
return jsonify({
'success': False,
'message': '清空历史记录失败'
}), 500
@optimization_history_bp.route('/api/optimization-history/stats', methods=['GET'])
# @login_required # 暂时注释掉登录要求,用于测试
def get_user_stats():
"""获取用户使用统计 - 简化版本"""
try:
# 获取腾讯云数据库连接
conn = get_tencent_db_connection()
if not conn:
return jsonify({
'success': False,
'message': '数据库连接失败'
}), 500
cursor = conn.cursor()
user_id = get_current_user_id()
# 获取基本统计信息
stats_sql = """
SELECT
COUNT(*) as total_count,
COUNT(CASE WHEN DATE(created_at) = CURDATE() THEN 1 END) as today_count,
COUNT(CASE WHEN created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY) THEN 1 END) as week_count,
COUNT(CASE WHEN created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY) THEN 1 END) as month_count
FROM prompt
WHERE user_id = %s OR wx_user_id = %s
"""
cursor.execute(stats_sql, [user_id, user_id])
stats = cursor.fetchone()
cursor.close()
conn.close()
return jsonify({
'success': True,
'data': {
'total_count': stats[0] or 0,
'today_count': stats[1] or 0,
'week_count': stats[2] or 0,
'month_count': stats[3] or 0
}
})
except Exception as e:
current_app.logger.error(f"获取用户统计失败: {str(e)}")
return jsonify({
'success': False,
'message': '获取统计信息失败'
}), 500
@optimization_history_bp.route('/api/optimization-history/export', methods=['GET'])
# @login_required # 暂时注释掉登录要求,用于测试
def export_history():
"""导出历史记录 - 使用腾讯云prompt表"""
try:
format_type = request.args.get('format', 'json')
# 获取腾讯云数据库连接
conn = get_tencent_db_connection()
if not conn:
return jsonify({
'success': False,
'message': '数据库连接失败'
}), 500
cursor = conn.cursor()
user_id = get_current_user_id()
# 获取所有历史记录
export_sql = """
SELECT id, input_text, generated_text, created_at, user_id, wx_user_id
FROM prompt
WHERE user_id = %s OR wx_user_id = %s
ORDER BY created_at DESC
"""
cursor.execute(export_sql, [user_id, user_id])
results = cursor.fetchall()
# 格式化数据
history_list = []
for row in results:
history_dict = {
'id': row[0],
'original_text': row[1],
'optimized_text': row[2],
'created_at': row[3].strftime('%Y-%m-%d %H:%M:%S') if row[3] else None,
'user_id': row[4],
'wx_user_id': row[5],
'optimization_type': '提示词优化'
}
history_list.append(history_dict)
cursor.close()
conn.close()
if format_type == 'json':
return jsonify({
'success': True,
'data': history_list,
'count': len(history_list)
})
else:
return jsonify({
'success': False,
'message': '不支持的导出格式'
}), 400
except Exception as e:
current_app.logger.error(f"导出历史记录失败: {str(e)}")
return jsonify({
'success': False,
'message': '导出历史记录失败'
}), 500

View File

@@ -56,11 +56,11 @@ def generate_with_llm(input_text, template_id=None, max_retries=3):
start_time = time.time() # 记录开始时间
# 记录参数到日志
logger.info("=== API 调用参数 ===")
logger.info(f"模板ID: {template_id}")
logger.info(f"输入文本: {input_text}")
logger.info(f"系统提示: {system_prompt}")
logger.info("==================")
current_app.logger.info("=== API 调用参数 ===")
current_app.logger.info(f"模板ID: {template_id}")
current_app.logger.info(f"输入文本: {input_text}")
current_app.logger.info(f"系统提示: {system_prompt}")
current_app.logger.info("==================")
for attempt in range(max_retries):
try:
@@ -80,10 +80,10 @@ def generate_with_llm(input_text, template_id=None, max_retries=3):
# 打印响应
generated_text = response.choices[0].message.content.strip()
print("\n=== API 响应结果 ===")
print(f"生成的提示词: {generated_text}")
print(f"生成耗时: {generation_time}ms")
print("==================\n")
current_app.logger.info("=== API 响应结果 ===")
current_app.logger.info(f"生成的提示词: {generated_text}")
current_app.logger.info(f"生成耗时: {generation_time}ms")
current_app.logger.info("==================")
# 保存到历史记录
save_to_history(
@@ -197,46 +197,69 @@ def index():
sub_categories = sorted(set(t.sub_category for t in all_templates if t.sub_category))
if form.validate_on_submit():
template_id = request.form.get('template_id')
generated_text = generate_with_llm(form.input_text.data, template_id)
# 获取搜索状态
search_state = request.form.get('search_state', '')
# 获取默认用户的 uid
try:
conn = pymysql.connect(
host='localhost',
user='root',
password='123456',
database='pro_db',
charset='utf8mb4'
template_id = request.form.get('template_id')
input_text = form.input_text.data.strip()
# 验证输入
if not input_text:
flash('请输入您的需求描述', 'error')
return render_template('generate.html', form=form, prompt=None, templates=templates,
get_template_icon=get_template_icon, industries=industries,
professions=professions, categories=categories,
sub_categories=sub_categories)
# 调用LLM生成提示词
generated_text = generate_with_llm(input_text, template_id)
# 检查生成结果
if not generated_text or generated_text.startswith("提示词生成失败"):
flash(f'生成失败: {generated_text}', 'error')
return render_template('generate.html', form=form, prompt=None, templates=templates,
get_template_icon=get_template_icon, industries=industries,
professions=professions, categories=categories,
sub_categories=sub_categories)
# 获取搜索状态
search_state = request.form.get('search_state', '')
# 获取默认用户的 uid - 使用SQLAlchemy而不是直接连接
try:
# 尝试从现有用户表中获取admin用户
admin_user = User.query.filter_by(login_name='admin').first()
if admin_user:
user_id = admin_user.uid
else:
# 如果没有admin用户使用默认值
user_id = 1
except Exception as e:
current_app.logger.warning(f"获取用户ID失败: {str(e)}")
user_id = 1 # 如果查询失败,使用默认值
# 保存到数据库
prompt = Prompt(
input_text=input_text,
generated_text=generated_text,
user_id=user_id
)
cursor = conn.cursor()
cursor.execute("SELECT uid FROM user WHERE login_name = 'admin' LIMIT 1")
result = cursor.fetchone()
if result:
user_id = result[0]
else:
user_id = 1 # 如果没有找到用户,使用默认值
cursor.close()
conn.close()
db.session.add(prompt)
db.session.commit()
flash('提示词生成成功!', 'success')
return render_template('generate.html', form=form, prompt=prompt, templates=templates,
get_template_icon=get_template_icon, industries=industries,
professions=professions, categories=categories,
sub_categories=sub_categories, selected_template_id=template_id,
search_state=search_state)
except Exception as e:
print(f"获取用户ID失败: {str(e)}")
user_id = 1 # 如果查询失败,使用默认值
prompt = Prompt(
input_text=form.input_text.data,
generated_text=generated_text,
user_id=user_id # 使用查询到的用户ID
)
db.session.add(prompt)
db.session.commit()
return render_template('generate.html', form=form, prompt=prompt, templates=templates,
get_template_icon=get_template_icon, industries=industries,
professions=professions, categories=categories,
sub_categories=sub_categories, selected_template_id=template_id,
search_state=search_state)
current_app.logger.error(f"生成提示词时发生错误: {str(e)}")
db.session.rollback()
flash(f'生成提示词时发生错误: {str(e)}', 'error')
return render_template('generate.html', form=form, prompt=None, templates=templates,
get_template_icon=get_template_icon, industries=industries,
professions=professions, categories=categories,
sub_categories=sub_categories)
return render_template('generate.html', form=form, prompt=None, templates=templates,
get_template_icon=get_template_icon, industries=industries,
professions=professions, categories=categories,

View File

@@ -1,846 +0,0 @@
{% extends "base.html" %}
{% block title %}优化历史 - AI应用{% endblock %}
{% block extra_css %}
<style>
/* 优化历史页面样式 - 参考收藏页面设计 */
.history-container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
background: linear-gradient(135deg, #1E3A8A 0%, #3B82F6 100%);
min-height: 100vh;
}
.history-header {
text-align: center;
color: white;
margin-bottom: 40px;
}
.history-header h1 {
font-size: 2.5rem;
margin-bottom: 10px;
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
font-family: 'Inter', sans-serif;
font-weight: 700;
}
.history-header p {
font-size: 1.2rem;
opacity: 0.9;
font-family: 'Inter', sans-serif;
}
.history-content {
background: white;
border-radius: 20px;
padding: 40px;
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
}
/* 搜索和筛选区域 */
.search-filters {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
margin-bottom: 30px;
padding: 20px;
background: #f8f9fa;
border-radius: 15px;
}
.search-filters input,
.search-filters select {
padding: 12px 16px;
border: 2px solid #e1e5e9;
border-radius: 10px;
font-size: 1rem;
transition: all 0.3s ease;
font-family: 'Inter', sans-serif;
}
.search-filters input:focus,
.search-filters select:focus {
outline: none;
border-color: #3B82F6;
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}
.search-btn {
background: linear-gradient(135deg, #3B82F6, #1E3A8A);
color: white;
border: none;
padding: 12px 24px;
border-radius: 10px;
font-weight: 600;
transition: all 0.3s ease;
cursor: pointer;
}
.search-btn:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(59, 130, 246, 0.3);
}
/* 历史记录列表 */
.history-list {
display: grid;
gap: 20px;
}
.history-item {
background: #f8f9fa;
border: 2px solid #e1e5e9;
border-radius: 15px;
padding: 25px;
transition: all 0.3s ease;
position: relative;
}
.history-item:hover {
border-color: #3B82F6;
box-shadow: 0 5px 15px rgba(59, 130, 246, 0.1);
transform: translateY(-2px);
}
.history-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 15px;
}
.history-title {
font-size: 1.3rem;
font-weight: 700;
color: #333;
margin-bottom: 5px;
font-family: 'Inter', sans-serif;
}
.history-type {
color: #3B82F6;
font-size: 1rem;
font-weight: 600;
background: rgba(59, 130, 246, 0.1);
padding: 4px 12px;
border-radius: 20px;
}
.history-meta {
display: flex;
gap: 15px;
align-items: center;
margin-bottom: 15px;
flex-wrap: wrap;
}
.history-time {
color: #666;
font-size: 0.9rem;
display: flex;
align-items: center;
gap: 5px;
}
.history-industry {
background: #e3f2fd;
color: #1976d2;
padding: 4px 8px;
border-radius: 12px;
font-size: 0.8rem;
font-weight: 500;
}
.history-profession {
background: #f3e5f5;
color: #7b1fa2;
padding: 4px 8px;
border-radius: 12px;
font-size: 0.8rem;
font-weight: 500;
}
.history-content {
margin-bottom: 15px;
}
.history-original,
.history-optimized {
margin-bottom: 15px;
}
.history-original h4,
.history-optimized h4 {
font-size: 1rem;
font-weight: 600;
color: #333;
margin-bottom: 8px;
display: flex;
align-items: center;
gap: 8px;
}
.history-original h4::before {
content: "📝";
font-size: 1.2rem;
}
.history-optimized h4::before {
content: "✨";
font-size: 1.2rem;
}
.history-original p,
.history-optimized p {
color: #666;
line-height: 1.6;
margin: 0;
background: white;
padding: 12px;
border-radius: 8px;
border-left: 4px solid #e1e5e9;
}
.history-optimized p {
border-left-color: #3B82F6;
background: #f8faff;
}
/* 标签区域 */
.history-tags {
display: flex;
gap: 8px;
margin-bottom: 15px;
flex-wrap: wrap;
}
.tag {
background: linear-gradient(135deg, #6366F1, #8B5CF6);
color: white;
padding: 4px 12px;
border-radius: 20px;
font-size: 0.8rem;
font-weight: 500;
}
/* 评分区域 */
.history-rating {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 15px;
}
.stars {
display: flex;
gap: 2px;
}
.stars i {
color: #ddd;
font-size: 1.1rem;
transition: color 0.2s ease;
}
.stars i.active {
color: #ffc107;
}
/* 操作按钮 */
.history-actions {
display: flex;
gap: 10px;
justify-content: flex-end;
flex-wrap: wrap;
}
.action-btn {
padding: 8px 16px;
border: none;
border-radius: 8px;
font-size: 0.9rem;
font-weight: 500;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
gap: 6px;
}
.copy-btn {
background: #10B981;
color: white;
}
.copy-btn:hover {
background: #059669;
transform: translateY(-1px);
}
.favorite-btn {
background: #EF4444;
color: white;
}
.favorite-btn:hover {
background: #DC2626;
transform: translateY(-1px);
}
.favorite-btn.favorited {
background: #F59E0B;
}
.favorite-btn.favorited:hover {
background: #D97706;
}
.delete-btn {
background: #6B7280;
color: white;
}
.delete-btn:hover {
background: #4B5563;
transform: translateY(-1px);
}
/* 分页 */
.pagination {
display: flex;
justify-content: center;
gap: 10px;
margin-top: 30px;
flex-wrap: wrap;
}
.pagination button {
padding: 10px 16px;
border: 2px solid #e1e5e9;
background: white;
color: #333;
border-radius: 8px;
cursor: pointer;
transition: all 0.3s ease;
font-weight: 500;
}
.pagination button:hover {
border-color: #3B82F6;
color: #3B82F6;
}
.pagination button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.pagination .current-page {
background: #3B82F6;
color: white;
border-color: #3B82F6;
}
/* 加载状态 */
.loading {
text-align: center;
padding: 40px;
color: #666;
}
.loading-spinner {
display: inline-block;
width: 40px;
height: 40px;
border: 4px solid #f3f3f3;
border-top: 4px solid #3B82F6;
border-radius: 50%;
animation: spin 1s linear infinite;
margin-bottom: 20px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* 空状态 */
.no-history {
text-align: center;
padding: 60px 20px;
color: #666;
}
.no-history i {
font-size: 4rem;
color: #ddd;
margin-bottom: 20px;
}
.no-history h3 {
font-size: 1.5rem;
margin-bottom: 10px;
color: #333;
}
.no-history p {
font-size: 1rem;
color: #666;
}
/* 统计卡片 */
.stats-cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
margin-bottom: 30px;
}
.stat-card {
background: linear-gradient(135deg, #3B82F6, #1E3A8A);
color: white;
padding: 20px;
border-radius: 15px;
text-align: center;
box-shadow: 0 5px 15px rgba(59, 130, 246, 0.2);
}
.stat-card h3 {
font-size: 2rem;
margin-bottom: 5px;
font-weight: 700;
}
.stat-card p {
font-size: 0.9rem;
opacity: 0.9;
margin: 0;
}
/* 响应式设计 */
@media (max-width: 768px) {
.history-container {
padding: 10px;
}
.history-content {
padding: 20px;
}
.search-filters {
grid-template-columns: 1fr;
}
.history-header {
flex-direction: column;
gap: 10px;
}
.history-meta {
flex-direction: column;
align-items: flex-start;
gap: 8px;
}
.history-actions {
justify-content: flex-start;
}
.stats-cards {
grid-template-columns: repeat(2, 1fr);
}
}
@media (max-width: 480px) {
.stats-cards {
grid-template-columns: 1fr;
}
.history-actions {
flex-direction: column;
}
.action-btn {
justify-content: center;
}
}
</style>
{% endblock %}
{% block content %}
<div class="history-container">
<div class="history-header">
<h1><i class="fas fa-history"></i> 优化历史</h1>
<p>查看和管理您的AI优化历史记录随时回顾精彩内容</p>
</div>
<div class="history-content">
<!-- 统计卡片 -->
<div class="stats-cards" id="statsCards">
<div class="stat-card">
<h3 id="totalCount">0</h3>
<p>总记录数</p>
</div>
<div class="stat-card">
<h3 id="todayCount">0</h3>
<p>今日生成</p>
</div>
<div class="stat-card">
<h3 id="avgRating">0</h3>
<p>平均评分</p>
</div>
<div class="stat-card">
<h3 id="timeSaved">0</h3>
<p>节省时间(分钟)</p>
</div>
</div>
<!-- 搜索和筛选 -->
<div class="search-filters">
<input type="text" id="searchInput" placeholder="搜索历史记录...">
<select id="typeFilter">
<option value="">所有类型</option>
<option value="提示词优化">提示词优化</option>
<option value="产品文案">产品文案</option>
<option value="商务邮件">商务邮件</option>
<option value="技术文档">技术文档</option>
<option value="营销文案">营销文案</option>
</select>
<select id="dateFilter">
<option value="">所有时间</option>
<option value="today">今天</option>
<option value="week">本周</option>
<option value="month">本月</option>
</select>
<select id="ratingFilter">
<option value="">所有评分</option>
<option value="5">5星</option>
<option value="4">4星</option>
<option value="3">3星</option>
<option value="2">2星</option>
<option value="1">1星</option>
</select>
<button id="searchBtn" class="search-btn">
<i class="fas fa-search"></i> 搜索
</button>
</div>
<!-- 历史记录列表 -->
<div id="historyList" class="history-list">
<div class="loading">
<div class="loading-spinner"></div>
<p>正在加载历史记录...</p>
</div>
</div>
<!-- 分页 -->
<div id="pagination" class="pagination" style="display: none;">
<!-- 分页内容 -->
</div>
</div>
</div>
<!-- 历史记录详情模态框 -->
<div class="modal fade" id="historyDetailModal" tabindex="-1">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">
<i class="fas fa-history"></i> 历史记录详情
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div id="history-detail-content">
<!-- 详情内容 -->
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
<button type="button" class="btn btn-primary" id="copy-detail-btn">
<i class="fas fa-copy"></i> 复制结果
</button>
<button type="button" class="btn btn-warning" id="rate-detail-btn">
<i class="fas fa-star"></i> 评分
</button>
<button type="button" class="btn btn-danger" id="delete-detail-btn">
<i class="fas fa-trash"></i> 删除
</button>
</div>
</div>
</div>
</div>
<!-- 评分模态框 -->
<div class="modal fade" id="ratingModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">
<i class="fas fa-star"></i> 满意度评分
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="text-center">
<p class="mb-3">请为这次优化结果评分:</p>
<div class="rating-stars" id="ratingStars">
<i class="fas fa-star" data-rating="1"></i>
<i class="fas fa-star" data-rating="2"></i>
<i class="fas fa-star" data-rating="3"></i>
<i class="fas fa-star" data-rating="4"></i>
<i class="fas fa-star" data-rating="5"></i>
</div>
<p class="mt-3 text-muted" id="ratingText">点击星星进行评分</p>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary" id="save-rating-btn" disabled>保存评分</button>
</div>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script src="{{ url_for('static', filename='js/optimization_history_db.js') }}"></script>
<script>
let currentPage = 1;
let currentHistoryId = null;
let currentRating = 0;
// 页面加载完成后执行
document.addEventListener('DOMContentLoaded', function() {
console.log('🚀 优化历史页面开始初始化...');
try {
// 初始化优化历史数据库对象
window.optimizationHistoryDB = new OptimizationHistoryDB();
console.log('✅ OptimizationHistoryDB对象创建成功');
loadStats();
console.log('✅ 统计信息加载完成');
loadHistory();
console.log('✅ 历史记录加载完成');
} catch (error) {
console.error('❌ 初始化失败:', error);
document.getElementById('historyList').innerHTML = `
<div class="error-message">
<h3>初始化失败</h3>
<p>错误信息: ${error.message}</p>
</div>
`;
}
// 搜索按钮点击事件
document.getElementById('searchBtn').addEventListener('click', function() {
currentPage = 1;
loadHistory();
});
// 回车搜索
document.getElementById('searchInput').addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
currentPage = 1;
loadHistory();
}
});
// 筛选器变化
['typeFilter', 'dateFilter', 'ratingFilter'].forEach(id => {
document.getElementById(id).addEventListener('change', function() {
currentPage = 1;
loadHistory();
});
});
// 评分星星点击事件
document.querySelectorAll('#ratingStars i').forEach(star => {
star.addEventListener('click', function() {
currentRating = parseInt(this.dataset.rating);
updateRatingDisplay();
});
star.addEventListener('mouseenter', function() {
const rating = parseInt(this.dataset.rating);
highlightStars(rating);
});
});
document.getElementById('ratingStars').addEventListener('mouseleave', function() {
highlightStars(currentRating);
});
// 保存评分
document.getElementById('save-rating-btn').addEventListener('click', function() {
if (currentRating > 0 && currentHistoryId) {
optimizationHistoryDB.updateRating(currentHistoryId, currentRating)
.then(success => {
if (success) {
$('#ratingModal').modal('hide');
loadHistory();
loadStats();
}
});
}
});
// 复制详情
document.getElementById('copy-detail-btn').addEventListener('click', function() {
const optimizedText = document.querySelector('#history-detail-content .optimized-text').textContent;
navigator.clipboard.writeText(optimizedText).then(() => {
showToast('内容已复制到剪贴板', 'success');
});
});
// 删除详情
document.getElementById('delete-detail-btn').addEventListener('click', function() {
if (confirm('确定要删除这条历史记录吗?')) {
optimizationHistoryDB.deleteHistory(currentHistoryId)
.then(success => {
if (success) {
$('#historyDetailModal').modal('hide');
loadHistory();
loadStats();
}
});
}
});
});
// 加载统计信息
function loadStats() {
optimizationHistoryDB.getUserStats(30).then(stats => {
if (stats) {
document.getElementById('totalCount').textContent = stats.period.total_generations || 0;
document.getElementById('todayCount').textContent = stats.today.generation_count || 0;
document.getElementById('avgRating').textContent = stats.period.avg_rating || 0;
document.getElementById('timeSaved').textContent = stats.period.total_time_saved || 0;
}
});
}
// 加载历史记录
function loadHistory() {
console.log('🔄 开始加载历史记录...');
const search = document.getElementById('searchInput').value;
const typeFilter = document.getElementById('typeFilter').value;
const dateFilter = document.getElementById('dateFilter').value;
const ratingFilter = document.getElementById('ratingFilter').value;
console.log('📋 搜索参数:', { search, typeFilter, dateFilter, ratingFilter });
optimizationHistoryDB.getHistory({
page: currentPage,
search: search,
typeFilter: typeFilter,
dateFilter: dateFilter,
ratingFilter: ratingFilter
});
}
// 查看详情
function viewDetail(historyId) {
currentHistoryId = historyId;
// 这里需要从当前显示的历史记录中获取数据
// 实际实现中应该通过API获取完整数据
const historyItem = document.querySelector(`[data-id="${historyId}"]`);
if (historyItem) {
const originalText = historyItem.querySelector('.history-original p').textContent;
const optimizedText = historyItem.querySelector('.history-optimized p').textContent;
const type = historyItem.querySelector('.history-type').textContent;
const time = historyItem.querySelector('.history-time').textContent;
let html = `
<div class="row">
<div class="col-md-6">
<h6><i class="fas fa-edit"></i> 原始输入</h6>
<div class="border rounded p-3 bg-light original-text">
${escapeHtml(originalText)}
</div>
</div>
<div class="col-md-6">
<h6><i class="fas fa-magic"></i> 优化结果</h6>
<div class="border rounded p-3 bg-light optimized-text">
<pre class="mb-0">${escapeHtml(optimizedText)}</pre>
</div>
</div>
</div>
<div class="row mt-3">
<div class="col-md-6">
<strong>类型:</strong> ${type}
</div>
<div class="col-md-6">
<strong>时间:</strong> ${time}
</div>
</div>
`;
document.getElementById('history-detail-content').innerHTML = html;
$('#historyDetailModal').modal('show');
}
}
// 评分功能
function rateHistory(historyId) {
currentHistoryId = historyId;
currentRating = 0;
updateRatingDisplay();
$('#ratingModal').modal('show');
}
// 更新评分显示
function updateRatingDisplay() {
highlightStars(currentRating);
document.getElementById('save-rating-btn').disabled = currentRating === 0;
const texts = ['', '很差', '一般', '还行', '很好', '优秀'];
document.getElementById('ratingText').textContent = texts[currentRating] || '点击星星进行评分';
}
// 高亮星星
function highlightStars(rating) {
document.querySelectorAll('#ratingStars i').forEach((star, index) => {
if (index < rating) {
star.classList.add('active');
} else {
star.classList.remove('active');
}
});
}
// 跳转到指定页面
function goToPage(page) {
currentPage = page;
loadHistory();
}
// 工具函数
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
function showToast(message, type) {
// 使用优化历史DB类中的消息显示功能
if (window.optimizationHistoryDB) {
if (type === 'success') {
window.optimizationHistoryDB.showSuccess(message);
} else {
window.optimizationHistoryDB.showError(message);
}
} else {
alert(message);
}
}
</script>
{% endblock %}

View File

@@ -193,3 +193,4 @@ if __name__ == "__main__":

125
test_prompt_generation.py Normal file
View File

@@ -0,0 +1,125 @@
#!/usr/bin/env python3
"""
测试提示词生成功能的脚本
"""
import requests
import json
import time
def test_prompt_generation():
"""测试提示词生成功能"""
base_url = "http://localhost:5002"
# 测试数据
test_data = {
"input_text": "帮我写一个关于人工智能的演讲稿",
"template_id": "1"
}
print("🧪 开始测试提示词生成功能...")
print(f"测试URL: {base_url}")
print(f"测试数据: {test_data}")
print("-" * 50)
try:
# 发送POST请求
response = requests.post(
base_url,
data=test_data,
timeout=120, # 2分钟超时
headers={
'Content-Type': 'application/x-www-form-urlencoded',
'User-Agent': 'TestScript/1.0'
}
)
print(f"📊 响应状态码: {response.status_code}")
print(f"📊 响应头: {dict(response.headers)}")
if response.status_code == 200:
print("✅ 请求成功!")
# 检查响应内容
if "生成的提示词" in response.text or "提示词生成成功" in response.text:
print("✅ 提示词生成功能正常!")
elif "提示词生成失败" in response.text:
print("❌ 提示词生成失败")
print(f"错误信息: {response.text[:500]}...")
else:
print("⚠️ 响应内容异常")
print(f"响应内容: {response.text[:500]}...")
elif response.status_code == 500:
print("❌ 服务器内部错误")
print(f"错误信息: {response.text[:500]}...")
else:
print(f"❌ 请求失败,状态码: {response.status_code}")
print(f"响应内容: {response.text[:500]}...")
except requests.exceptions.Timeout:
print("❌ 请求超时")
except requests.exceptions.ConnectionError:
print("❌ 连接失败,请检查服务器是否运行")
except Exception as e:
print(f"❌ 测试过程中发生错误: {str(e)}")
print("-" * 50)
print("🏁 测试完成")
def test_api_endpoint():
"""测试API端点"""
base_url = "http://localhost:5002"
print("🧪 测试API端点...")
# 测试GET请求
try:
response = requests.get(base_url, timeout=30)
if response.status_code == 200:
print("✅ GET请求正常")
else:
print(f"❌ GET请求失败: {response.status_code}")
except Exception as e:
print(f"❌ GET请求错误: {str(e)}")
# 测试微信API端点
wx_url = f"{base_url}/api/wx/generate"
wx_data = {
"input_text": "测试微信API",
"uid": 1
}
try:
response = requests.post(
wx_url,
json=wx_data,
timeout=60,
headers={'Content-Type': 'application/json'}
)
print(f"📊 微信API响应: {response.status_code}")
if response.status_code == 200:
print("✅ 微信API正常")
else:
print(f"❌ 微信API失败: {response.text[:200]}...")
except Exception as e:
print(f"❌ 微信API错误: {str(e)}")
if __name__ == "__main__":
print("🚀 启动提示词生成系统测试")
print("=" * 60)
# 测试API端点
test_api_endpoint()
print()
# 测试提示词生成
test_prompt_generation()
print("=" * 60)
print("📋 测试总结:")
print("1. 检查服务器是否运行在 localhost:5002")
print("2. 检查数据库连接是否正常")
print("3. 检查LLM API配置是否正确")
print("4. 查看日志文件获取详细错误信息")

View File

@@ -170,3 +170,4 @@ if __name__ == "__main__":

View File

@@ -1,162 +0,0 @@
# 提示词大师项目 - 服务器启动和停止指南
## 🚀 **启动服务器**
### 方法一:使用完整命令启动
```bash
# 进入项目目录
cd /home/renjianbo/aitsc
# 激活conda环境并启动服务
eval "$(/home/renjianbo/miniconda3/bin/conda shell.bash hook)" && conda activate myenv && gunicorn -c gunicorn.conf.py run_dev:app
```
### 方法二:分步启动
```bash
# 1. 进入项目目录
cd /home/renjianbo/aitsc
# 2. 激活conda环境
eval "$(/home/renjianbo/miniconda3/bin/conda shell.bash hook)"
conda activate myenv
# 3. 启动Gunicorn服务
gunicorn -c gunicorn.conf.py run_dev:app
```
### 方法三:后台启动
```bash
# 后台启动服务
nohup gunicorn -c gunicorn.conf.py run_dev:app > logs/gunicorn.log 2>&1 &
```
## 🛑 **停止服务器**
### 方法一使用PID文件停止
```bash
# 停止服务如果存在PID文件
kill -TERM $(cat logs/gunicorn.pid)
```
### 方法二强制停止所有Gunicorn进程
```bash
# 强制停止所有gunicorn进程
pkill -9 -f gunicorn
```
### 方法三:停止特定项目进程
```bash
# 停止run_dev:app相关进程
pkill -f "run_dev:app"
```
## 🔍 **检查服务状态**
### 检查进程状态
```bash
# 查看Gunicorn进程
ps aux | grep "run_dev:app" | grep -v grep
# 查看所有Gunicorn进程
ps aux | grep gunicorn | grep -v grep
```
### 检查端口状态
```bash
# 检查5002端口是否被监听
ss -tlnp | grep :5002
# 或者使用netstat
netstat -tlnp | grep :5002
```
### 检查服务响应
```bash
# 测试服务是否正常响应
curl -s http://localhost:5002/ | head -10
# 测试特定页面
curl -s -o /dev/null -w "%{http_code}" http://localhost:5002/admin/analytics_admin/
```
## 📊 **查看日志**
### 查看错误日志
```bash
# 查看最新的错误日志
tail -f logs/gunicorn_error.log
# 查看应用日志
tail -f logs/app.log
```
### 查看访问日志
```bash
# 查看访问日志
tail -f logs/gunicorn_access.log
```
## 🔧 **故障排除**
### 清理和重启
```bash
# 1. 停止所有相关进程
pkill -f gunicorn
# 2. 删除PID文件
rm -f logs/gunicorn.pid
# 3. 重新启动
eval "$(/home/renjianbo/miniconda3/bin/conda shell.bash hook)" && conda activate myenv && gunicorn -c gunicorn.conf.py run_dev:app
```
### 检查依赖
```bash
# 检查Python环境
which python
python --version
# 检查已安装的包
pip list | grep -E "(flask|gunicorn|openai)"
```
## 🌐 **访问地址**
启动成功后,可以访问以下地址:
- **主页**`http://101.43.95.130:5002/`
- **饭菜规划**`http://101.43.95.130:5002/meal-planning`
- **古诗词解析**`http://101.43.95.130:5002/poetry/`
- **古诗词示例**`http://101.43.95.130:5002/poetry/examples`
- **后台管理**`http://101.43.95.130:5002/admin`
- **数据分析**`http://101.43.95.130:5002/admin/analytics_admin/`
## ✅ **启动成功的标志**
看到以下信息表示启动成功:
- `[INFO] 应用启动`
- `[INFO] 工作进程 X 已启动`
- `[INFO] 工作进程 X 初始化完成`
- 端口5002开始监听
## 📝 **项目信息**
- **项目名称**:提示词大师
- **功能描述**:智能生成高质量提示词,提升您的工作效率
- **技术栈**Python 3.12 + Flask + Gunicorn + MySQL
- **端口**5002
- **环境**conda myenv
- **配置文件**gunicorn.conf.py
- **启动文件**run_dev.py
## 🚨 **注意事项**
1. 确保conda环境已正确激活
2. 确保所有依赖包已安装
3. 确保数据库连接正常
4. 确保5002端口未被占用
5. 定期检查日志文件大小,避免磁盘空间不足
---
*最后更新2025-09-14*
*维护人员:系统管理员*

View File

@@ -1,79 +0,0 @@
# 模板初始化快速参考
## 🚀 快速开始
### 一键初始化腾讯云数据库
```bash
python direct_insert_templates.py
```
### 选择数据库类型初始化
```bash
python init_tencent_db.py
```
## 📊 当前状态
-**腾讯云数据库**: 176个模板已成功插入
-**数据完整性**: 验证通过
-**连接状态**: 正常
## 🔧 常用命令
```bash
# 强制重新插入所有模板
python direct_insert_templates.py
# 初始化本地数据库
python init_tencent_db.py local
# 初始化腾讯云数据库
python init_tencent_db.py tencent
# 验证数据库连接
python -c "
import pymysql
conn = pymysql.connect(
host='gz-cynosdbmysql-grp-d26pzce5.sql.tencentcdb.com',
port=24936, user='root', password='!Rjb12191',
database='pro_db', charset='utf8mb4'
)
cursor = conn.cursor()
cursor.execute('SELECT COUNT(*) FROM prompt_template')
print(f'模板总数: {cursor.fetchone()[0]}')
conn.close()
"
```
## 📋 数据库配置
### 腾讯云数据库
- **主机**: gz-cynosdbmysql-grp-d26pzce5.sql.tencentcdb.com:24936
- **用户**: root
- **密码**: !Rjb12191
- **数据库**: pro_db
### 本地数据库
- **主机**: localhost:3306
- **用户**: root
- **密码**: 123456
- **数据库**: pro_db
## 🛠️ 故障排除
| 问题 | 解决方案 |
|------|----------|
| 连接失败 | 检查网络和防火墙设置 |
| 权限错误 | 验证数据库用户权限 |
| 数据不完整 | 使用 `direct_insert_templates.py` 重新初始化 |
| 模块导入错误 | 确保在项目根目录运行脚本 |
## 📁 相关文件
- `direct_insert_templates.py` - 推荐使用
- `init_tencent_db.py` - 通用初始化
- `src/flask_prompt_master/promptsTemplates.py` - 模板源文件
- `模板初始化完整文档.md` - 详细文档
---
**最后更新**: 2025年1月6日

View File

@@ -1,504 +0,0 @@
# 🎯 生成专业提示词代码逻辑分析
## 📋 系统概述
生成专业提示词系统是一个基于Flask的Web应用采用前后端分离架构集成了DeepSeek LLM API实现了智能化的提示词生成功能。
## 🏗️ 系统架构
### 1. 技术栈
- **后端**: Flask + SQLAlchemy + PyMySQL
- **前端**: HTML5 + CSS3 + JavaScript + Bootstrap
- **数据库**: MySQL (本地 + 腾讯云)
- **LLM API**: DeepSeek Chat API
- **部署**: Gunicorn + Nginx
### 2. 核心组件
- **路由层**: Flask Blueprint路由管理
- **模型层**: SQLAlchemy ORM模型
- **服务层**: LLM API集成服务
- **视图层**: Jinja2模板渲染
- **静态资源**: CSS/JS资源管理
## 🔄 完整生成流程
### 第一阶段:用户交互层
#### 1.1 前端界面 (`generate.html`)
```html
<!-- 模板选择区域 -->
<div class="template-grid">
{% for template in templates %}
<div class="template-card" data-template-id="{{ template.id }}">
<input type="radio" name="template_id" value="{{ template.id }}">
<label>{{ template.name }}</label>
</div>
{% endfor %}
</div>
<!-- 需求输入区域 -->
<div class="input-section">
<textarea name="input_text" placeholder="请详细描述您的需求..."></textarea>
</div>
<!-- 生成按钮 -->
<button type="submit" class="btn-generate">生成专业提示词</button>
```
#### 1.2 JavaScript交互逻辑
```javascript
// 模板选择处理
function handleTemplateSelection(radio) {
const card = radio.closest('.template-card');
const templateId = card.dataset.templateId;
// 添加选择动画
card.classList.add('selecting');
// 更新选择状态
updateSelectionStatus();
// 添加到选择历史
addToSelectionHistory(templateId, templateName);
}
// 表单提交处理
document.getElementById('promptForm').addEventListener('submit', function(e) {
e.preventDefault();
const formData = new FormData(this);
const templateId = formData.get('template_id');
const inputText = formData.get('input_text');
// 发送AJAX请求
fetch('/', {
method: 'POST',
body: formData
})
.then(response => response.text())
.then(html => {
// 更新页面内容
document.body.innerHTML = html;
});
});
```
### 第二阶段:后端处理层
#### 2.1 路由处理 (`routes.py`)
```python
@main_bp.route('/', methods=['GET', 'POST'])
def index():
form = PromptForm()
templates = PromptTemplate.query.all()
if form.validate_on_submit():
# 获取用户输入和模板ID
template_id = request.form.get('template_id')
input_text = form.input_text.data
# 调用LLM生成提示词
generated_text = generate_with_llm(input_text, template_id)
# 保存到数据库
prompt = Prompt(
input_text=input_text,
generated_text=generated_text,
user_id=get_user_id()
)
db.session.add(prompt)
db.session.commit()
# 返回结果页面
return render_template('generate.html',
form=form,
prompt=prompt,
templates=templates)
return render_template('generate.html',
form=form,
templates=templates)
```
#### 2.2 模板系统逻辑
```python
def get_system_prompt(template_id=None):
"""获取系统提示词模板"""
if template_id:
# 根据模板ID获取特定模板
template = PromptTemplate.query.get(template_id)
if template:
return template.system_prompt
# 获取默认模板
default_template = PromptTemplate.query.filter_by(is_default=True).first()
if default_template:
return default_template.system_prompt
# 硬编码默认模板
return """你是一个专业的提示词工程师,擅长将普通的描述转换为结构化、专业的 Prompt。
你需要:
1. 分析用户的需求和意图
2. 将其转换为清晰、详细的提示词
3. 添加必要的上下文和约束条件
4. 使用专业的术语和格式
5. 确保生成的提示词能够获得最佳的 AI 响应
请直接返回优化后的提示词,不要添加任何解释或其他内容。"""
```
### 第三阶段LLM集成层
#### 3.1 API配置
```python
# OpenAI兼容客户端配置
client = OpenAI(
api_key='sk-fdf7cc1c73504e628ec0119b7e11b8cc',
base_url='https://api.deepseek.com/v1'
)
```
#### 3.2 LLM调用逻辑
```python
def generate_with_llm(input_text, template_id=None, max_retries=3):
"""调用大模型API生成提示词带重试机制"""
system_prompt = get_system_prompt(template_id)
for attempt in range(max_retries):
try:
response = client.chat.completions.create(
model="deepseek-chat",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": input_text}
],
temperature=0.7,
max_tokens=500,
timeout=60
)
generated_text = response.choices[0].message.content.strip()
return generated_text
except Exception as e:
if attempt == max_retries - 1:
current_app.logger.error(f'LLM API调用失败: {str(e)}')
return "提示词生成失败,请稍后重试"
time.sleep(2 ** attempt) # 指数退避
```
### 第四阶段:专家模式生成
#### 4.1 两阶段专家系统
```python
@main_bp.route('/api/wx/generate/expert', methods=['POST'])
def wx_generate_expert_prompt():
"""两阶段专家提示词生成系统"""
# 第一阶段:意图识别专家
intent_analyst_prompt = """你是一位资深的意图分析专家,请分析用户输入的意图和需求。
你必须严格按照以下JSON格式返回
{
"core_intent": "技术", // 技术、创意、分析、咨询
"domain": "web开发", // 具体的专业领域
"key_requirements": [ // 2-4个关键需求
"需求1", "需求2"
],
"expected_output": "期望输出的具体形式",
"constraints": [ // 1-3个主要约束
"约束1", "约束2"
],
"keywords": [ // 2-4个关键词
"关键词1", "关键词2"
]
}"""
# 获取意图分析结果
intent_response = client.chat.completions.create(
model="deepseek-chat",
messages=[
{"role": "system", "content": intent_analyst_prompt},
{"role": "user", "content": user_input}
],
temperature=0.1
)
intent_analysis = json.loads(intent_response.choices[0].message.content.strip())
# 第二阶段:领域专家提示生成
domain_expert_templates = {
"技术": """你是一位专业的技术领域提示工程师。基于以下意图分析,生成一个专业的技术任务提示词:
意图分析:{analysis}
请生成的提示词包含:
1. 明确的技术背景和上下文
2. 具体的技术要求和规范
3. 性能和质量标准
4. 技术约束条件
5. 预期交付成果
6. 评估标准
使用专业技术术语,确保提示词的可执行性和可验证性。""",
"创意": """你是一位专业的创意领域提示工程师。基于以下意图分析,生成一个创意设计提示词:
意图分析:{analysis}
请生成的提示词包含:
1. 创意方向和灵感来源
2. 风格和氛围要求
3. 目标受众定义
4. 设计元素规范
5. 创意表现形式
6. 评估标准
使用专业创意术语,确保提示词的创新性和可执行性。"""
}
# 选择领域专家模板
expert_prompt = domain_expert_templates.get(
intent_analysis['core_intent'],
default_template
)
# 生成最终提示词
final_response = client.chat.completions.create(
model="deepseek-chat",
messages=[
{"role": "system", "content": expert_prompt.format(
analysis=json.dumps(intent_analysis, ensure_ascii=False, indent=2)
)},
{"role": "user", "content": user_input}
],
temperature=0.7
)
generated_prompt = final_response.choices[0].message.content.strip()
return jsonify({
'code': 200,
'data': {
'intent_analysis': intent_analysis,
'generated_prompt': generated_prompt
}
})
```
## 🗄️ 数据库设计
### 1. 核心表结构
#### Prompt表 (主要数据表)
```sql
CREATE TABLE prompt (
id INT PRIMARY KEY AUTO_INCREMENT,
input_text TEXT NOT NULL,
generated_text TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
user_id INT,
wx_user_id INT,
FOREIGN KEY (user_id) REFERENCES user(uid),
FOREIGN KEY (wx_user_id) REFERENCES wx_user(id)
);
```
#### PromptTemplate表 (模板管理)
```sql
CREATE TABLE prompt_template (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
description TEXT,
category VARCHAR(50),
industry VARCHAR(50),
profession VARCHAR(50),
sub_category VARCHAR(50),
system_prompt TEXT NOT NULL,
is_default BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
```
### 2. 数据流转
```
用户输入 → 模板选择 → LLM处理 → 结果生成 → 数据库存储 → 页面展示
```
## 🎨 前端交互逻辑
### 1. 模板选择系统
```javascript
// 模板筛选逻辑
function performSearchAndFilter() {
const searchTerm = document.getElementById('templateSearch').value.toLowerCase();
const selectedCategory = document.querySelector('.filter-tab.active')?.dataset.category;
document.querySelectorAll('.template-card').forEach(card => {
const templateName = card.querySelector('h3').textContent.toLowerCase();
const templateCategory = card.dataset.category;
const matchesSearch = templateName.includes(searchTerm);
const matchesCategory = !selectedCategory || templateCategory === selectedCategory;
card.style.display = (matchesSearch && matchesCategory) ? 'block' : 'none';
});
}
// 选择状态管理
function updateSelectionStatus() {
const selectedTemplates = document.querySelectorAll('input[name="template_id"]:checked');
const selectedCount = selectedTemplates.length;
document.getElementById('selectedCount').textContent = selectedCount;
document.getElementById('selectionStatus').style.display = selectedCount > 0 ? 'block' : 'none';
}
```
### 2. 用户体验优化
```javascript
// 现代交互功能
function initializeModernInteractions() {
// 平滑滚动
initializeSmoothScroll();
// 焦点管理
initializeFocusManagement();
// 悬停效果
initializeHoverEffects();
// 键盘导航
initializeKeyboardNavigation();
// 性能优化
initializePerformanceOptimizations();
}
// 防抖搜索
let searchTimeout;
document.getElementById('templateSearch').addEventListener('input', function() {
clearTimeout(searchTimeout);
searchTimeout = setTimeout(() => {
performSearchAndFilter();
}, 300);
});
```
## ⚙️ 配置管理
### 1. 环境配置
```python
class Config:
# 数据库配置
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:123456@localhost:3306/pro_db?charset=utf8mb4'
TENCENT_SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:!Rjb12191@gz-cynosdbmysql-grp-d26pzce5.sql.tencentcdb.com:24936/pro_db?charset=utf8mb4'
# LLM API配置
LLM_API_URL = 'https://api.deepseek.com/v1'
LLM_API_KEY = 'sk-fdf7cc1c73504e628ec0119b7e11b8cc'
# 微信小程序配置
WX_APPID = 'wx2c65877d37fc29bf'
WX_SECRET = '89aa97dda3c1347c6ae3d6ab4627f1f4'
```
### 2. 部署配置
```python
# Gunicorn配置 (gunicorn.conf.py)
bind = "0.0.0.0:5002"
workers = multiprocessing.cpu_count() * 2 + 1
worker_class = "sync"
timeout = 120
accesslog = "logs/gunicorn_access.log"
errorlog = "logs/gunicorn_error.log"
```
## 🔧 核心功能实现
### 1. 模板管理系统
- **模板分类**: 按行业、职业、领域分类
- **模板选择**: 单选模式,支持默认模板
- **模板搜索**: 实时搜索和筛选
- **模板历史**: 记录用户选择历史
### 2. 生成引擎
- **普通模式**: 单次LLM调用
- **专家模式**: 两阶段专家系统
- **重试机制**: 指数退避重试
- **错误处理**: 完善的异常处理
### 3. 数据管理
- **用户数据**: 支持普通用户和微信用户
- **历史记录**: 完整的生成历史管理
- **数据导出**: 支持JSON格式导出
- **统计分析**: 使用统计和分析
## 🚀 性能优化
### 1. 前端优化
- **懒加载**: 图片和资源懒加载
- **防抖搜索**: 减少API调用频率
- **缓存策略**: 模板数据缓存
- **响应式设计**: 移动端适配
### 2. 后端优化
- **连接池**: 数据库连接池管理
- **重试机制**: LLM API调用重试
- **日志记录**: 详细的日志追踪
- **错误处理**: 优雅的错误处理
### 3. 数据库优化
- **索引优化**: 关键字段索引
- **查询优化**: 减少N+1查询
- **分页查询**: 大数据量分页
- **连接管理**: 连接池和超时设置
## 📊 监控和日志
### 1. 日志系统
```python
# 配置日志
logger = logging.getLogger(__name__)
# API调用日志
logger.info("=== API 调用参数 ===")
logger.info(f"模板ID: {template_id}")
logger.info(f"输入文本: {input_text}")
logger.info(f"系统提示: {system_prompt}")
# 错误日志
current_app.logger.error(f'LLM API调用失败: {str(e)}')
```
### 2. 性能监控
- **响应时间**: API调用响应时间
- **成功率**: 生成成功率统计
- **错误率**: 错误类型和频率
- **用户行为**: 用户使用模式分析
## 🎯 总结
生成专业提示词系统采用了现代化的架构设计,具有以下特点:
### 优势
1. **架构清晰**: 前后端分离,职责明确
2. **功能完整**: 支持多种生成模式
3. **用户体验**: 现代化的交互设计
4. **扩展性强**: 支持模板和功能扩展
5. **性能优化**: 多层次的性能优化
### 技术亮点
1. **两阶段专家系统**: 意图识别 + 领域专家
2. **智能模板选择**: 基于用户行为的推荐
3. **多数据库支持**: 本地 + 腾讯云
4. **完善的错误处理**: 重试机制和降级策略
5. **现代化前端**: 响应式设计和交互优化
这个系统为用户提供了专业、高效的提示词生成服务通过智能化的模板选择和专家级的生成逻辑帮助用户快速生成高质量的AI提示词。
---
*分析完成时间2025年1月*
*系统版本v1.0*
*维护人员:系统管理员*