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

37 KiB
Raw Permalink Blame History

📚 优化历史功能设计方案

🎯 功能概述

基于现有的生成专业提示词系统,开发一个完整的优化历史功能,让用户可以:

  • 查看自己生成的所有提示词历史
  • 搜索和筛选历史记录
  • 重新使用历史提示词
  • 收藏重要的提示词
  • 导出历史数据

🏗️ 系统架构设计

1. 数据模型设计

1.1 历史记录表 (prompt_history)

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)

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)

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 获取历史记录列表

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 获取单个历史记录

GET /api/history/{id}

2.3 更新历史记录

PUT /api/history/{id}
数据:
- satisfaction_rating: 满意度评分
- tags: 标签列表
- is_favorite: 是否收藏

2.4 删除历史记录

DELETE /api/history/{id}

2.5 批量操作

POST /api/history/batch
操作:
- delete: 批量删除
- favorite: 批量收藏
- unfavorite: 批量取消收藏

2.6 导出历史记录

GET /api/history/export
参数:
- format: 导出格式 (json, csv, txt)
- date_from: 开始日期
- date_to: 结束日期

3. 前端页面设计

3.1 历史记录列表页面

  • 搜索栏: 支持关键词搜索
  • 筛选器: 按模板、日期、评分筛选
  • 排序选项: 按时间、评分、生成时间排序
  • 列表展示: 卡片式展示历史记录
  • 分页导航: 支持分页浏览

3.2 历史记录详情页面

  • 完整展示: 原始输入和生成结果
  • 操作按钮: 复制、收藏、评分、删除
  • 相关信息: 生成时间、使用模板、耗时等

3.3 统计面板

  • 总生成数: 历史生成总数
  • 收藏数量: 收藏的提示词数量
  • 平均评分: 用户满意度统计
  • 使用趋势: 生成时间趋势图

🔧 技术实现方案

1. 后端实现

1.1 数据模型 (models.py)

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)

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)

<!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 修改生成逻辑

在现有的生成提示词逻辑中添加历史记录保存:

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 修改路由注册

在应用初始化时注册历史记录蓝图:

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脚本创建表结构
-- 运行数据库迁移脚本

2. 配置更新

# 在配置文件中添加历史记录相关配置
HISTORY_PAGE_SIZE = 20
HISTORY_MAX_EXPORT = 1000

3. 前端资源

  • 将历史记录页面添加到路由
  • 更新导航菜单
  • 添加相关静态资源

🎉 总结

这个优化历史功能设计完整,具有以下特点:

  1. 功能完整: 涵盖历史记录的完整生命周期管理
  2. 用户体验: 现代化的界面设计和交互体验
  3. 性能优化: 多层次的性能优化策略
  4. 扩展性强: 支持功能扩展和定制
  5. 集成简单: 与现有系统无缝集成

通过这个功能,用户可以更好地管理和回顾自己的提示词生成历史,提升使用体验和工作效率。


设计完成时间2025年1月 功能版本v1.0 维护人员:系统管理员