first commit
This commit is contained in:
Binary file not shown.
@@ -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
|
||||
@@ -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,
|
||||
|
||||
@@ -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 %}
|
||||
Reference in New Issue
Block a user