Files
aitsc/优化历史功能设计方案.md
2025-10-10 23:39:54 +08:00

1054 lines
37 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 📚 优化历史功能设计方案
## 🎯 功能概述
基于现有的生成专业提示词系统,开发一个完整的优化历史功能,让用户可以:
- 查看自己生成的所有提示词历史
- 搜索和筛选历史记录
- 重新使用历史提示词
- 收藏重要的提示词
- 导出历史数据
## 🏗️ 系统架构设计
### 1. 数据模型设计
#### 1.1 历史记录表 (prompt_history)
```sql
CREATE TABLE prompt_history (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL,
wx_user_id INT,
original_input TEXT NOT NULL COMMENT '原始输入',
generated_prompt TEXT NOT NULL COMMENT '生成的提示词',
template_id INT COMMENT '使用的模板ID',
template_name VARCHAR(100) COMMENT '模板名称',
generation_time INT COMMENT '生成耗时(毫秒)',
satisfaction_rating TINYINT COMMENT '满意度评分(1-5)',
tags JSON COMMENT '标签列表',
is_favorite BOOLEAN DEFAULT FALSE COMMENT '是否收藏',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_user_id (user_id),
INDEX idx_wx_user_id (wx_user_id),
INDEX idx_created_at (created_at),
INDEX idx_template_id (template_id),
INDEX idx_is_favorite (is_favorite)
);
```
#### 1.2 历史标签表 (history_tags)
```sql
CREATE TABLE history_tags (
id INT PRIMARY KEY AUTO_INCREMENT,
history_id INT NOT NULL,
tag_name VARCHAR(50) NOT NULL,
tag_type VARCHAR(20) DEFAULT 'custom',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (history_id) REFERENCES prompt_history(id) ON DELETE CASCADE,
INDEX idx_history_id (history_id),
INDEX idx_tag_name (tag_name)
);
```
#### 1.3 用户统计表 (user_statistics)
```sql
CREATE TABLE user_statistics (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL,
total_generations INT DEFAULT 0,
favorite_count INT DEFAULT 0,
avg_rating DECIMAL(3,2) DEFAULT 0.00,
last_generation_at TIMESTAMP NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY uk_user_id (user_id)
);
```
### 2. API接口设计
#### 2.1 获取历史记录列表
```http
GET /api/history
:
- page: (1)
- per_page: (20)
- search:
- template_id:
- date_from:
- date_to:
- is_favorite:
- sort: (created_at, rating, generation_time)
```
#### 2.2 获取单个历史记录
```http
GET /api/history/{id}
```
#### 2.3 更新历史记录
```http
PUT /api/history/{id}
:
- satisfaction_rating:
- tags:
- is_favorite:
```
#### 2.4 删除历史记录
```http
DELETE /api/history/{id}
```
#### 2.5 批量操作
```http
POST /api/history/batch
:
- delete:
- favorite:
- unfavorite:
```
#### 2.6 导出历史记录
```http
GET /api/history/export
:
- format: (json, csv, txt)
- date_from:
- date_to:
```
### 3. 前端页面设计
#### 3.1 历史记录列表页面
- **搜索栏**: 支持关键词搜索
- **筛选器**: 按模板、日期、评分筛选
- **排序选项**: 按时间、评分、生成时间排序
- **列表展示**: 卡片式展示历史记录
- **分页导航**: 支持分页浏览
#### 3.2 历史记录详情页面
- **完整展示**: 原始输入和生成结果
- **操作按钮**: 复制、收藏、评分、删除
- **相关信息**: 生成时间、使用模板、耗时等
#### 3.3 统计面板
- **总生成数**: 历史生成总数
- **收藏数量**: 收藏的提示词数量
- **平均评分**: 用户满意度统计
- **使用趋势**: 生成时间趋势图
## 🔧 技术实现方案
### 1. 后端实现
#### 1.1 数据模型 (models.py)
```python
class PromptHistory(db.Model):
__tablename__ = 'prompt_history'
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, nullable=False)
wx_user_id = db.Column(db.Integer)
original_input = db.Column(db.Text, nullable=False)
generated_prompt = db.Column(db.Text, nullable=False)
template_id = db.Column(db.Integer)
template_name = db.Column(db.String(100))
generation_time = db.Column(db.Integer)
satisfaction_rating = db.Column(db.SmallInteger)
tags = db.Column(db.JSON)
is_favorite = db.Column(db.Boolean, default=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
# 关联关系
template = db.relationship('PromptTemplate', backref='histories')
history_tags = db.relationship('HistoryTag', backref='history', lazy='dynamic', cascade='all, delete-orphan')
def to_dict(self):
return {
'id': self.id,
'original_input': self.original_input,
'generated_prompt': self.generated_prompt,
'template_id': self.template_id,
'template_name': self.template_name,
'generation_time': self.generation_time,
'satisfaction_rating': self.satisfaction_rating,
'tags': self.tags or [],
'is_favorite': self.is_favorite,
'created_at': self.created_at.isoformat() if self.created_at else None,
'updated_at': self.updated_at.isoformat() if self.updated_at else None
}
class HistoryTag(db.Model):
__tablename__ = 'history_tags'
id = db.Column(db.Integer, primary_key=True)
history_id = db.Column(db.Integer, db.ForeignKey('prompt_history.id'), nullable=False)
tag_name = db.Column(db.String(50), nullable=False)
tag_type = db.Column(db.String(20), default='custom')
created_at = db.Column(db.DateTime, default=datetime.utcnow)
class UserStatistics(db.Model):
__tablename__ = 'user_statistics'
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, unique=True, nullable=False)
total_generations = db.Column(db.Integer, default=0)
favorite_count = db.Column(db.Integer, default=0)
avg_rating = db.Column(db.Numeric(3, 2), default=0.00)
last_generation_at = db.Column(db.DateTime)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
```
#### 1.2 API路由 (history_routes.py)
```python
from flask import Blueprint, request, jsonify, current_app
from sqlalchemy import desc, asc, and_, or_
from datetime import datetime, timedelta
import json
history_bp = Blueprint('history', __name__)
@history_bp.route('/api/history', methods=['GET'])
def get_history_list():
"""获取历史记录列表"""
try:
# 获取参数
page = request.args.get('page', 1, type=int)
per_page = min(request.args.get('per_page', 20, type=int), 100)
search = request.args.get('search', '').strip()
template_id = request.args.get('template_id', type=int)
date_from = request.args.get('date_from')
date_to = request.args.get('date_to')
is_favorite = request.args.get('is_favorite', type=bool)
sort = request.args.get('sort', 'created_at')
# 获取用户ID
user_id = get_current_user_id()
# 构建查询
query = PromptHistory.query.filter(
or_(PromptHistory.user_id == user_id, PromptHistory.wx_user_id == user_id)
)
# 搜索条件
if search:
query = query.filter(
or_(
PromptHistory.original_input.contains(search),
PromptHistory.generated_prompt.contains(search)
)
)
# 模板筛选
if template_id:
query = query.filter(PromptHistory.template_id == template_id)
# 日期筛选
if date_from:
query = query.filter(PromptHistory.created_at >= datetime.fromisoformat(date_from))
if date_to:
query = query.filter(PromptHistory.created_at <= datetime.fromisoformat(date_to))
# 收藏筛选
if is_favorite is not None:
query = query.filter(PromptHistory.is_favorite == is_favorite)
# 排序
if sort == 'rating':
query = query.order_by(desc(PromptHistory.satisfaction_rating))
elif sort == 'generation_time':
query = query.order_by(asc(PromptHistory.generation_time))
else:
query = query.order_by(desc(PromptHistory.created_at))
# 分页
pagination = query.paginate(page=page, per_page=per_page, error_out=False)
# 格式化结果
history_list = [history.to_dict() for history in pagination.items]
return jsonify({
'success': True,
'data': {
'history': history_list,
'pagination': {
'page': pagination.page,
'per_page': pagination.per_page,
'total': pagination.total,
'pages': pagination.pages,
'has_next': pagination.has_next,
'has_prev': pagination.has_prev
}
}
})
except Exception as e:
current_app.logger.error(f"获取历史记录失败: {str(e)}")
return jsonify({
'success': False,
'message': '获取历史记录失败'
}), 500
@history_bp.route('/api/history/<int:history_id>', methods=['GET'])
def get_history_detail(history_id):
"""获取单个历史记录详情"""
try:
user_id = get_current_user_id()
history = PromptHistory.query.filter(
PromptHistory.id == history_id,
or_(PromptHistory.user_id == user_id, PromptHistory.wx_user_id == user_id)
).first()
if not history:
return jsonify({
'success': False,
'message': '历史记录不存在'
}), 404
return jsonify({
'success': True,
'data': history.to_dict()
})
except Exception as e:
current_app.logger.error(f"获取历史记录详情失败: {str(e)}")
return jsonify({
'success': False,
'message': '获取历史记录详情失败'
}), 500
@history_bp.route('/api/history/<int:history_id>', methods=['PUT'])
def update_history(history_id):
"""更新历史记录"""
try:
user_id = get_current_user_id()
history = PromptHistory.query.filter(
PromptHistory.id == history_id,
or_(PromptHistory.user_id == user_id, PromptHistory.wx_user_id == user_id)
).first()
if not history:
return jsonify({
'success': False,
'message': '历史记录不存在'
}), 404
data = request.get_json()
# 更新字段
if 'satisfaction_rating' in data:
history.satisfaction_rating = data['satisfaction_rating']
if 'tags' in data:
history.tags = data['tags']
if 'is_favorite' in data:
history.is_favorite = data['is_favorite']
history.updated_at = datetime.utcnow()
db.session.commit()
# 更新用户统计
update_user_statistics(user_id)
return jsonify({
'success': True,
'data': history.to_dict(),
'message': '更新成功'
})
except Exception as e:
current_app.logger.error(f"更新历史记录失败: {str(e)}")
return jsonify({
'success': False,
'message': '更新历史记录失败'
}), 500
@history_bp.route('/api/history/<int:history_id>', methods=['DELETE'])
def delete_history(history_id):
"""删除历史记录"""
try:
user_id = get_current_user_id()
history = PromptHistory.query.filter(
PromptHistory.id == history_id,
or_(PromptHistory.user_id == user_id, PromptHistory.wx_user_id == user_id)
).first()
if not history:
return jsonify({
'success': False,
'message': '历史记录不存在'
}), 404
db.session.delete(history)
db.session.commit()
# 更新用户统计
update_user_statistics(user_id)
return jsonify({
'success': True,
'message': '删除成功'
})
except Exception as e:
current_app.logger.error(f"删除历史记录失败: {str(e)}")
return jsonify({
'success': False,
'message': '删除历史记录失败'
}), 500
@history_bp.route('/api/history/export', methods=['GET'])
def export_history():
"""导出历史记录"""
try:
user_id = get_current_user_id()
format_type = request.args.get('format', 'json')
date_from = request.args.get('date_from')
date_to = request.args.get('date_to')
# 构建查询
query = PromptHistory.query.filter(
or_(PromptHistory.user_id == user_id, PromptHistory.wx_user_id == user_id)
)
if date_from:
query = query.filter(PromptHistory.created_at >= datetime.fromisoformat(date_from))
if date_to:
query = query.filter(PromptHistory.created_at <= datetime.fromisoformat(date_to))
histories = query.order_by(desc(PromptHistory.created_at)).all()
if format_type == 'json':
data = [history.to_dict() for history in histories]
return jsonify({
'success': True,
'data': data,
'count': len(data)
})
elif format_type == 'csv':
# 实现CSV导出
pass
else:
return jsonify({
'success': False,
'message': '不支持的导出格式'
}), 400
except Exception as e:
current_app.logger.error(f"导出历史记录失败: {str(e)}")
return jsonify({
'success': False,
'message': '导出历史记录失败'
}), 500
def get_current_user_id():
"""获取当前用户ID"""
# 实现用户ID获取逻辑
return 1 # 临时返回默认用户ID
def update_user_statistics(user_id):
"""更新用户统计信息"""
try:
# 获取用户历史统计
total_generations = PromptHistory.query.filter(
or_(PromptHistory.user_id == user_id, PromptHistory.wx_user_id == user_id)
).count()
favorite_count = PromptHistory.query.filter(
or_(PromptHistory.user_id == user_id, PromptHistory.wx_user_id == user_id),
PromptHistory.is_favorite == True
).count()
# 计算平均评分
avg_rating_result = db.session.query(db.func.avg(PromptHistory.satisfaction_rating)).filter(
or_(PromptHistory.user_id == user_id, PromptHistory.wx_user_id == user_id),
PromptHistory.satisfaction_rating.isnot(None)
).scalar()
avg_rating = float(avg_rating_result) if avg_rating_result else 0.0
# 获取最后生成时间
last_generation = PromptHistory.query.filter(
or_(PromptHistory.user_id == user_id, PromptHistory.wx_user_id == user_id)
).order_by(desc(PromptHistory.created_at)).first()
last_generation_at = last_generation.created_at if last_generation else None
# 更新或创建统计记录
stats = UserStatistics.query.filter_by(user_id=user_id).first()
if not stats:
stats = UserStatistics(user_id=user_id)
db.session.add(stats)
stats.total_generations = total_generations
stats.favorite_count = favorite_count
stats.avg_rating = avg_rating
stats.last_generation_at = last_generation_at
stats.updated_at = datetime.utcnow()
db.session.commit()
except Exception as e:
current_app.logger.error(f"更新用户统计失败: {str(e)}")
db.session.rollback()
```
### 2. 前端实现
#### 2.1 历史记录页面 (history.html)
```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>优化历史 - AI提示词生成器</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
<style>
.history-card {
border: 1px solid #e0e0e0;
border-radius: 8px;
padding: 20px;
margin-bottom: 20px;
transition: all 0.3s ease;
}
.history-card:hover {
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
transform: translateY(-2px);
}
.history-card.favorite {
border-color: #ff6b6b;
background-color: #fff5f5;
}
.search-section {
background: #f8f9fa;
padding: 20px;
border-radius: 8px;
margin-bottom: 30px;
}
.stats-card {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border-radius: 10px;
padding: 20px;
margin-bottom: 20px;
}
.tag {
display: inline-block;
background: #e3f2fd;
color: #1976d2;
padding: 4px 8px;
border-radius: 12px;
font-size: 12px;
margin: 2px;
}
.rating-stars {
color: #ffc107;
}
</style>
</head>
<body>
<div class="container-fluid">
<div class="row">
<!-- 侧边栏 -->
<div class="col-md-3">
<div class="search-section">
<h5><i class="fas fa-search"></i> 搜索和筛选</h5>
<div class="mb-3">
<input type="text" class="form-control" id="searchInput" placeholder="搜索历史记录...">
</div>
<div class="mb-3">
<select class="form-select" id="templateFilter">
<option value="">所有模板</option>
</select>
</div>
<div class="mb-3">
<select class="form-select" id="dateFilter">
<option value="">所有时间</option>
<option value="today">今天</option>
<option value="week">本周</option>
<option value="month">本月</option>
</select>
</div>
<div class="mb-3">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="favoriteFilter">
<label class="form-check-label" for="favoriteFilter">
只显示收藏
</label>
</div>
</div>
<div class="mb-3">
<select class="form-select" id="sortSelect">
<option value="created_at">按时间排序</option>
<option value="rating">按评分排序</option>
<option value="generation_time">按生成时间排序</option>
</select>
</div>
<button class="btn btn-primary w-100" onclick="searchHistory()">
<i class="fas fa-search"></i> 搜索
</button>
</div>
<!-- 统计信息 -->
<div class="stats-card">
<h6><i class="fas fa-chart-bar"></i> 统计信息</h6>
<div class="row text-center">
<div class="col-6">
<div class="h4" id="totalGenerations">0</div>
<small>总生成数</small>
</div>
<div class="col-6">
<div class="h4" id="favoriteCount">0</div>
<small>收藏数</small>
</div>
</div>
<div class="mt-3">
<small>平均评分: <span id="avgRating">0.0</span></small>
</div>
</div>
</div>
<!-- 主内容区 -->
<div class="col-md-9">
<div class="d-flex justify-content-between align-items-center mb-4">
<h2><i class="fas fa-history"></i> 优化历史</h2>
<div>
<button class="btn btn-outline-primary" onclick="exportHistory()">
<i class="fas fa-download"></i> 导出
</button>
<button class="btn btn-primary" onclick="refreshHistory()">
<i class="fas fa-refresh"></i> 刷新
</button>
</div>
</div>
<!-- 历史记录列表 -->
<div id="historyList">
<!-- 动态加载内容 -->
</div>
<!-- 分页 -->
<nav aria-label="历史记录分页">
<ul class="pagination justify-content-center" id="pagination">
<!-- 动态生成分页 -->
</ul>
</nav>
</div>
</div>
</div>
<!-- 历史记录详情模态框 -->
<div class="modal fade" id="historyModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">历史记录详情</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label class="form-label">原始输入:</label>
<div class="border p-3 rounded" id="modalOriginalInput"></div>
</div>
<div class="mb-3">
<label class="form-label">生成的提示词:</label>
<div class="border p-3 rounded" id="modalGeneratedPrompt"></div>
</div>
<div class="row">
<div class="col-md-6">
<label class="form-label">模板:</label>
<span id="modalTemplateName"></span>
</div>
<div class="col-md-6">
<label class="form-label">生成时间:</label>
<span id="modalCreatedAt"></span>
</div>
</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" onclick="copyPrompt()">
<i class="fas fa-copy"></i> 复制
</button>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
<script>
let currentPage = 1;
let currentFilters = {};
// 页面加载完成后初始化
document.addEventListener('DOMContentLoaded', function() {
loadHistory();
loadTemplates();
loadStatistics();
});
// 加载历史记录
function loadHistory(page = 1) {
const params = new URLSearchParams({
page: page,
per_page: 20,
...currentFilters
});
fetch(`/api/history?${params}`)
.then(response => response.json())
.then(data => {
if (data.success) {
displayHistory(data.data.history);
displayPagination(data.data.pagination);
currentPage = page;
} else {
alert('加载历史记录失败: ' + data.message);
}
})
.catch(error => {
console.error('Error:', error);
alert('加载历史记录失败');
});
}
// 显示历史记录
function displayHistory(historyList) {
const container = document.getElementById('historyList');
if (historyList.length === 0) {
container.innerHTML = `
<div class="text-center py-5">
<i class="fas fa-history fa-3x text-muted mb-3"></i>
<h5 class="text-muted">暂无历史记录</h5>
<p class="text-muted">开始生成您的第一个提示词吧!</p>
</div>
`;
return;
}
container.innerHTML = historyList.map(history => `
<div class="history-card ${history.is_favorite ? 'favorite' : ''}" data-id="${history.id}">
<div class="row">
<div class="col-md-8">
<h6 class="mb-2">
${history.template_name || '默认模板'}
${history.is_favorite ? '<i class="fas fa-heart text-danger ms-2"></i>' : ''}
</h6>
<p class="text-muted mb-2">${history.original_input.substring(0, 100)}${history.original_input.length > 100 ? '...' : ''}</p>
<div class="mb-2">
${history.tags ? history.tags.map(tag => `<span class="tag">${tag}</span>`).join('') : ''}
</div>
<small class="text-muted">
<i class="fas fa-clock"></i> ${formatDate(history.created_at)}
${history.generation_time ? ` | <i class="fas fa-stopwatch"></i> ${history.generation_time}ms` : ''}
</small>
</div>
<div class="col-md-4 text-end">
<div class="mb-2">
${history.satisfaction_rating ? generateStars(history.satisfaction_rating) : ''}
</div>
<div class="btn-group">
<button class="btn btn-sm btn-outline-primary" onclick="viewHistory(${history.id})">
<i class="fas fa-eye"></i>
</button>
<button class="btn btn-sm btn-outline-success" onclick="copyPrompt('${history.generated_prompt.replace(/'/g, "\\'")}')">
<i class="fas fa-copy"></i>
</button>
<button class="btn btn-sm ${history.is_favorite ? 'btn-warning' : 'btn-outline-warning'}" onclick="toggleFavorite(${history.id})">
<i class="fas fa-heart"></i>
</button>
<button class="btn btn-sm btn-outline-danger" onclick="deleteHistory(${history.id})">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
</div>
</div>
`).join('');
}
// 搜索历史记录
function searchHistory() {
currentFilters = {
search: document.getElementById('searchInput').value,
template_id: document.getElementById('templateFilter').value,
date_filter: document.getElementById('dateFilter').value,
is_favorite: document.getElementById('favoriteFilter').checked,
sort: document.getElementById('sortSelect').value
};
loadHistory(1);
}
// 查看历史记录详情
function viewHistory(historyId) {
fetch(`/api/history/${historyId}`)
.then(response => response.json())
.then(data => {
if (data.success) {
const history = data.data;
document.getElementById('modalOriginalInput').textContent = history.original_input;
document.getElementById('modalGeneratedPrompt').textContent = history.generated_prompt;
document.getElementById('modalTemplateName').textContent = history.template_name || '默认模板';
document.getElementById('modalCreatedAt').textContent = formatDate(history.created_at);
const modal = new bootstrap.Modal(document.getElementById('historyModal'));
modal.show();
} else {
alert('获取历史记录详情失败: ' + data.message);
}
})
.catch(error => {
console.error('Error:', error);
alert('获取历史记录详情失败');
});
}
// 复制提示词
function copyPrompt(text) {
if (text) {
navigator.clipboard.writeText(text).then(() => {
alert('提示词已复制到剪贴板');
});
}
}
// 切换收藏状态
function toggleFavorite(historyId) {
fetch(`/api/history/${historyId}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
is_favorite: !document.querySelector(`[data-id="${historyId}"]`).classList.contains('favorite')
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
loadHistory(currentPage);
loadStatistics();
} else {
alert('操作失败: ' + data.message);
}
})
.catch(error => {
console.error('Error:', error);
alert('操作失败');
});
}
// 删除历史记录
function deleteHistory(historyId) {
if (confirm('确定要删除这条历史记录吗?')) {
fetch(`/api/history/${historyId}`, {
method: 'DELETE'
})
.then(response => response.json())
.then(data => {
if (data.success) {
loadHistory(currentPage);
loadStatistics();
} else {
alert('删除失败: ' + data.message);
}
})
.catch(error => {
console.error('Error:', error);
alert('删除失败');
});
}
}
// 导出历史记录
function exportHistory() {
const params = new URLSearchParams({
format: 'json',
...currentFilters
});
window.open(`/api/history/export?${params}`, '_blank');
}
// 刷新历史记录
function refreshHistory() {
loadHistory(currentPage);
loadStatistics();
}
// 加载模板列表
function loadTemplates() {
fetch('/api/templates')
.then(response => response.json())
.then(data => {
if (data.success) {
const select = document.getElementById('templateFilter');
select.innerHTML = '<option value="">所有模板</option>' +
data.data.templates.map(template =>
`<option value="${template.id}">${template.name}</option>`
).join('');
}
});
}
// 加载统计信息
function loadStatistics() {
fetch('/api/history/statistics')
.then(response => response.json())
.then(data => {
if (data.success) {
document.getElementById('totalGenerations').textContent = data.data.total_generations;
document.getElementById('favoriteCount').textContent = data.data.favorite_count;
document.getElementById('avgRating').textContent = data.data.avg_rating.toFixed(1);
}
});
}
// 工具函数
function formatDate(dateString) {
const date = new Date(dateString);
return date.toLocaleString('zh-CN');
}
function generateStars(rating) {
return '★'.repeat(rating) + '☆'.repeat(5 - rating);
}
</script>
</body>
</html>
```
### 3. 集成到现有系统
#### 3.1 修改生成逻辑
在现有的生成提示词逻辑中添加历史记录保存:
```python
def save_to_history(user_input, generated_text, template_id=None, generation_time=None):
"""保存到历史记录"""
try:
user_id = get_current_user_id()
template = PromptTemplate.query.get(template_id) if template_id else None
history = PromptHistory(
user_id=user_id,
original_input=user_input,
generated_prompt=generated_text,
template_id=template_id,
template_name=template.name if template else None,
generation_time=generation_time
)
db.session.add(history)
db.session.commit()
# 更新用户统计
update_user_statistics(user_id)
return history.id
except Exception as e:
current_app.logger.error(f"保存历史记录失败: {str(e)}")
db.session.rollback()
return None
```
#### 3.2 修改路由注册
在应用初始化时注册历史记录蓝图:
```python
from src.flask_prompt_master.routes.history_routes import history_bp
def create_app():
app = Flask(__name__)
# 注册蓝图
app.register_blueprint(main_bp)
app.register_blueprint(history_bp) # 新增历史记录蓝图
return app
```
## 🎯 功能特性
### 1. 核心功能
-**历史记录管理**: 完整的CRUD操作
-**搜索和筛选**: 多维度搜索和筛选
-**收藏功能**: 重要提示词收藏管理
-**评分系统**: 用户满意度评分
-**标签系统**: 自定义标签管理
-**数据导出**: 支持多种格式导出
### 2. 用户体验
-**响应式设计**: 移动端适配
-**实时搜索**: 防抖搜索优化
-**分页浏览**: 大数据量分页处理
-**统计面板**: 使用统计和趋势分析
-**批量操作**: 批量删除和收藏
### 3. 性能优化
-**数据库索引**: 关键字段索引优化
-**分页查询**: 减少数据传输量
-**缓存策略**: 模板和统计数据缓存
-**异步加载**: 前端异步数据加载
## 📊 数据统计
### 1. 用户统计
- 总生成数量
- 收藏数量
- 平均满意度评分
- 最后生成时间
### 2. 使用趋势
- 每日生成数量
- 模板使用频率
- 用户活跃度分析
## 🚀 部署说明
### 1. 数据库迁移
```sql
-- 执行SQL脚本创建表结构
-- 运行数据库迁移脚本
```
### 2. 配置更新
```python
# 在配置文件中添加历史记录相关配置
HISTORY_PAGE_SIZE = 20
HISTORY_MAX_EXPORT = 1000
```
### 3. 前端资源
- 将历史记录页面添加到路由
- 更新导航菜单
- 添加相关静态资源
## 🎉 总结
这个优化历史功能设计完整,具有以下特点:
1. **功能完整**: 涵盖历史记录的完整生命周期管理
2. **用户体验**: 现代化的界面设计和交互体验
3. **性能优化**: 多层次的性能优化策略
4. **扩展性强**: 支持功能扩展和定制
5. **集成简单**: 与现有系统无缝集成
通过这个功能,用户可以更好地管理和回顾自己的提示词生成历史,提升使用体验和工作效率。
---
*设计完成时间2025年1月*
*功能版本v1.0*
*维护人员:系统管理员*