|
@@ -0,0 +1,1378 @@
|
|
|
+<template>
|
|
|
+ <div class="history-container">
|
|
|
+ <!-- 顶部导航 -->
|
|
|
+ <div class="history-header">
|
|
|
+ <div class="header-content">
|
|
|
+ <div class="header-main">
|
|
|
+ <h1 class="history-title">📚 历史问题记录</h1>
|
|
|
+ <p class="history-subtitle">查看之前的提问和回答记录</p>
|
|
|
+ </div>
|
|
|
+ <div class="header-actions">
|
|
|
+ <el-button
|
|
|
+ class="back-btn"
|
|
|
+ @click="$router.push('/qanda')"
|
|
|
+ >
|
|
|
+ <span class="btn-icon">⬅️</span>
|
|
|
+ 返回问答
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="history-content">
|
|
|
+ <!-- 统计卡片 -->
|
|
|
+ <div class="stats-cards">
|
|
|
+ <div class="stat-card">
|
|
|
+ <div class="stat-icon">📝</div>
|
|
|
+ <div class="stat-info">
|
|
|
+ <div class="stat-number">{{ totalCount }}</div>
|
|
|
+ <div class="stat-label">总问题数</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="stat-card">
|
|
|
+ <div class="stat-icon">📄</div>
|
|
|
+ <div class="stat-info">
|
|
|
+ <div class="stat-number">{{ totalPages }}</div>
|
|
|
+ <div class="stat-label">总页数</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="stat-card">
|
|
|
+ <div class="stat-icon">🕒</div>
|
|
|
+ <div class="stat-info">
|
|
|
+ <div class="stat-number">{{ pageSize }}</div>
|
|
|
+ <div class="stat-label">每页数量</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 搜索和筛选 -->
|
|
|
+<!-- <div class="filter-section">-->
|
|
|
+<!-- <div class="search-input">-->
|
|
|
+<!-- <el-input-->
|
|
|
+<!-- v-model="searchQuery"-->
|
|
|
+<!-- placeholder="搜索问题内容..."-->
|
|
|
+<!-- size="large"-->
|
|
|
+<!-- clearable-->
|
|
|
+<!-- @input="handleSearch"-->
|
|
|
+<!-- >-->
|
|
|
+<!-- <template #prefix>-->
|
|
|
+<!-- <span class="search-icon">🔍</span>-->
|
|
|
+<!-- </template>-->
|
|
|
+<!-- </el-input>-->
|
|
|
+<!-- </div>-->
|
|
|
+<!-- <div class="filter-actions">-->
|
|
|
+<!-- <el-button-->
|
|
|
+<!-- class="refresh-btn"-->
|
|
|
+<!-- @click="refreshData"-->
|
|
|
+<!-- :loading="loading"-->
|
|
|
+<!-- >-->
|
|
|
+<!-- <span class="btn-icon">🔄</span>-->
|
|
|
+<!-- 刷新-->
|
|
|
+<!-- </el-button>-->
|
|
|
+<!-- </div>-->
|
|
|
+<!-- </div>-->
|
|
|
+
|
|
|
+ <!-- 加载状态 -->
|
|
|
+ <div v-if="loading" class="loading-section">
|
|
|
+ <div class="loading-content">
|
|
|
+ <div class="loading-spinner"></div>
|
|
|
+ <p>加载历史记录中...</p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 历史记录列表 -->
|
|
|
+ <div v-else class="history-list">
|
|
|
+ <div v-if="historyList.length === 0" class="empty-state">
|
|
|
+ <div class="empty-content">
|
|
|
+ <div class="empty-icon">📚</div>
|
|
|
+ <h3>暂无历史记录</h3>
|
|
|
+ <p>您还没有任何提问记录,快去首页提问吧!</p>
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ @click="$router.push('/')"
|
|
|
+ class="go-home-btn"
|
|
|
+ >
|
|
|
+ <span class="btn-icon">🚀</span>
|
|
|
+ 开始提问
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div v-else class="history-items">
|
|
|
+ <div
|
|
|
+ v-for="item in filteredHistory"
|
|
|
+ :key="item.create_time"
|
|
|
+ class="history-item"
|
|
|
+ >
|
|
|
+ <div class="item-header">
|
|
|
+ <div class="question-content">
|
|
|
+ <h3 class="question-title">{{ item.query }}</h3>
|
|
|
+ <div class="question-meta">
|
|
|
+ <span class="meta-item">
|
|
|
+ <span class="meta-icon">🕒</span>
|
|
|
+ {{ formatTime(item.create_time) }}
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="item-actions">
|
|
|
+ <el-button
|
|
|
+ class="detail-btn"
|
|
|
+ @click="toggleItemDetail(item)"
|
|
|
+ :class="{ active: expandedItems.includes(item.create_time) }"
|
|
|
+ >
|
|
|
+ <span class="btn-icon">
|
|
|
+ {{ expandedItems.includes(item.create_time) ? '📖' : '📄' }}
|
|
|
+ </span>
|
|
|
+ {{ expandedItems.includes(item.create_time) ? '收起详情' : '查看详情' }}
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 展开的详情 -->
|
|
|
+ <div
|
|
|
+ v-if="expandedItems.includes(item.create_time)"
|
|
|
+ class="item-detail"
|
|
|
+ >
|
|
|
+ <!-- 最终结果 -->
|
|
|
+ <div class="detail-section" v-if="item.final_result">
|
|
|
+ <div class="section-header">
|
|
|
+ <div class="section-icon">💡</div>
|
|
|
+ <h4>最终结果</h4>
|
|
|
+ </div>
|
|
|
+ <div class="section-content">
|
|
|
+ <div v-html="parseMarkdown(item.final_result)" class="content-text"></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- RAG搜索结果 -->
|
|
|
+ <div class="detail-section" v-if="item.chat_res">
|
|
|
+ <div class="section-header">
|
|
|
+ <div class="section-icon">🔍</div>
|
|
|
+ <h4>RAG搜索结果</h4>
|
|
|
+ </div>
|
|
|
+ <div class="section-content">
|
|
|
+ <div v-html="parseMarkdown(item.chat_res)" class="content-text"></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- LLM搜索结果 -->
|
|
|
+ <div class="detail-section" v-if="item.ai_answer">
|
|
|
+ <div class="section-header">
|
|
|
+ <div class="section-icon">🤖</div>
|
|
|
+ <h4>LLM搜索结果</h4>
|
|
|
+ </div>
|
|
|
+ <div class="section-content">
|
|
|
+ <div v-html="parseMarkdown(item.ai_answer)" class="content-text"></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 搜索结果统计 -->
|
|
|
+ <div class="detail-section" v-if="item.search_res">
|
|
|
+ <div class="section-header">
|
|
|
+ <div class="section-icon">📚</div>
|
|
|
+ <h4>参考内容</h4>
|
|
|
+ <span class="result-count">
|
|
|
+ {{ getSearchResults(item.search_res).length }} 条相关内容
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ <div class="search-results-preview">
|
|
|
+ <div
|
|
|
+ v-for="(result, index) in getDisplayedResults(item)"
|
|
|
+ :key="index"
|
|
|
+ class="result-preview"
|
|
|
+ @click="handleResultDetails(result)"
|
|
|
+ >
|
|
|
+ <div class="result-header">
|
|
|
+ <span class="result-index">#{{ index + 1 }}</span>
|
|
|
+ <span class="result-score" :class="getScoreClass(result.score)">
|
|
|
+ {{ (result.score * 100).toFixed(1) }}%
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ <p class="result-content">{{ result.contentSummary || result.content.substring(0, 120) }}...</p>
|
|
|
+ <span class="result-source">{{ result.datasetName }}</span>
|
|
|
+ <div class="result-footer">
|
|
|
+ <span class="view-details">
|
|
|
+ <span class="view-icon">🔍</span>
|
|
|
+ 查看详情
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 展开/收起按钮 -->
|
|
|
+ <div
|
|
|
+ v-if="getSearchResults(item.search_res).length > 3"
|
|
|
+ class="more-results"
|
|
|
+ >
|
|
|
+ <el-button
|
|
|
+ link
|
|
|
+ type="primary"
|
|
|
+ @click="toggleResultsExpansion(item)"
|
|
|
+ class="expand-btn"
|
|
|
+ >
|
|
|
+ <span class="btn-icon">
|
|
|
+ {{ item.isResultsExpanded ? '📂' : '📁' }}
|
|
|
+ </span>
|
|
|
+ {{ item.isResultsExpanded ? '收起' : `展开剩余 ${getSearchResults(item.search_res).length - 3} 条内容` }}
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 分页 -->
|
|
|
+ <div v-if="historyList.length > 0" class="pagination-section">
|
|
|
+ <el-pagination
|
|
|
+ v-model:current-page="currentPage"
|
|
|
+ v-model:page-size="pageSize"
|
|
|
+ :total="totalCount"
|
|
|
+ :page-sizes="[10, 20, 50, 100]"
|
|
|
+ layout="total, sizes, prev, pager, next, jumper"
|
|
|
+ @size-change="handleSizeChange"
|
|
|
+ @current-change="handleCurrentChange"
|
|
|
+ class="history-pagination"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 搜索结果详情弹窗 -->
|
|
|
+ <el-dialog
|
|
|
+ v-model="resultDialogVisible"
|
|
|
+ width="85%"
|
|
|
+ class="content-dialog"
|
|
|
+ :close-on-click-modal="false"
|
|
|
+ >
|
|
|
+ <template #header>
|
|
|
+ <div class="dialog-header">
|
|
|
+ <div class="dialog-title">
|
|
|
+ <div class="title-icon">📄</div>
|
|
|
+ <div class="title-content">
|
|
|
+ <h3>{{ selectedResult.contentSummary }}</h3>
|
|
|
+ <div class="title-meta">
|
|
|
+ <span class="meta-badge knowledge-badge">
|
|
|
+ <span class="badge-icon">📚</span>
|
|
|
+ {{ selectedResult.datasetName }}
|
|
|
+ </span>
|
|
|
+ <span class="meta-badge score-badge" :class="getScoreClass(selectedResult.score)">
|
|
|
+ <span class="badge-icon">🎯</span>
|
|
|
+ 相关度: {{ (selectedResult.score * 100).toFixed(1) }}%
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <div class="dialog-content">
|
|
|
+ <div class="content-tabs">
|
|
|
+ <div
|
|
|
+ class="tab-item"
|
|
|
+ :class="{ active: activeTab === 'summary' }"
|
|
|
+ @click="activeTab = 'summary'"
|
|
|
+ >
|
|
|
+ <span class="tab-icon">📝</span>
|
|
|
+ 摘要内容
|
|
|
+ </div>
|
|
|
+ <div
|
|
|
+ class="tab-item"
|
|
|
+ :class="{ active: activeTab === 'original' }"
|
|
|
+ @click="activeTab = 'original'"
|
|
|
+ >
|
|
|
+ <span class="tab-icon">📖</span>
|
|
|
+ 完整原文
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="tab-content">
|
|
|
+ <div v-show="activeTab === 'summary'" class="content-section summary-section">
|
|
|
+ <div class="section-header">
|
|
|
+ <h4>内容摘要</h4>
|
|
|
+ <el-button
|
|
|
+ text
|
|
|
+ class="copy-btn"
|
|
|
+ @click="copyToClipboard(selectedResult.content)"
|
|
|
+ >
|
|
|
+ 📋 复制内容
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ <div class="summary-content">
|
|
|
+ {{ selectedResult.content }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div v-show="activeTab === 'original'" class="content-section original-section">
|
|
|
+ <div class="section-header">
|
|
|
+ <h4>完整原文</h4>
|
|
|
+ <el-button
|
|
|
+ text
|
|
|
+ class="copy-btn"
|
|
|
+ @click="copyToClipboard(originalContent)"
|
|
|
+ >
|
|
|
+ 📋 复制原文
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ <div class="original-content">
|
|
|
+ <pre>{{ originalContent }}</pre>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <template #footer>
|
|
|
+ <div class="dialog-footer">
|
|
|
+ <div class="footer-actions">
|
|
|
+ <el-button
|
|
|
+ class="action-btn secondary"
|
|
|
+ @click="resultDialogVisible = false"
|
|
|
+ >
|
|
|
+ 取消
|
|
|
+ </el-button>
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ class="action-btn primary"
|
|
|
+ @click="resultDialogVisible = false"
|
|
|
+ >
|
|
|
+ 关闭
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { ref, onMounted, computed } from 'vue';
|
|
|
+import { ElMessage } from 'element-plus';
|
|
|
+import { marked } from 'marked';
|
|
|
+import { API_BASE_URL } from "@/config";
|
|
|
+import dayjs from 'dayjs';
|
|
|
+
|
|
|
+
|
|
|
+// 响应式数据
|
|
|
+const historyList = ref([]);
|
|
|
+const loading = ref(false);
|
|
|
+const currentPage = ref(1);
|
|
|
+const pageSize = ref(10);
|
|
|
+const totalCount = ref(0);
|
|
|
+const totalPages = ref(0);
|
|
|
+const searchQuery = ref('');
|
|
|
+const expandedItems = ref([]);
|
|
|
+const resultDialogVisible = ref(false);
|
|
|
+const selectedResult = ref({});
|
|
|
+const originalContent = ref('');
|
|
|
+const activeTab = ref('summary');
|
|
|
+
|
|
|
+// 计算属性
|
|
|
+const filteredHistory = computed(() => {
|
|
|
+ if (!searchQuery.value) {
|
|
|
+ return historyList.value;
|
|
|
+ }
|
|
|
+ const query = searchQuery.value.toLowerCase();
|
|
|
+ return historyList.value.filter(item =>
|
|
|
+ item.query.toLowerCase().includes(query) ||
|
|
|
+ (item.final_result && item.final_result.toLowerCase().includes(query)) ||
|
|
|
+ (item.chat_res && item.chat_res.toLowerCase().includes(query)) ||
|
|
|
+ (item.ai_answer && item.ai_answer.toLowerCase().includes(query))
|
|
|
+ );
|
|
|
+});
|
|
|
+
|
|
|
+// 方法
|
|
|
+const parseMarkdown = (content) => {
|
|
|
+ if (!content) return '';
|
|
|
+ const markdownSymbols = /[#*+\-`>!]/;
|
|
|
+ const isMarkdown = markdownSymbols.test(content);
|
|
|
+ return isMarkdown ? marked(content) : content;
|
|
|
+};
|
|
|
+
|
|
|
+const formatTime = (timeString) => {
|
|
|
+ try {
|
|
|
+ // 处理 GMT 时间格式 "Tue, 30 Sep 2025 14:02:21 GMT"
|
|
|
+ if (timeString.includes('GMT')) {
|
|
|
+ // 使用 UTC 方法获取时间组件,避免时区转换
|
|
|
+ const date = new Date(timeString);
|
|
|
+
|
|
|
+ if (!isNaN(date.getTime())) {
|
|
|
+ // 使用 UTC 相关的方法获取时间组件
|
|
|
+ const year = date.getUTCFullYear();
|
|
|
+ const month = String(date.getUTCMonth() + 1).padStart(2, '0');
|
|
|
+ const day = String(date.getUTCDate()).padStart(2, '0');
|
|
|
+ const hours = String(date.getUTCHours()).padStart(2, '0');
|
|
|
+ const minutes = String(date.getUTCMinutes()).padStart(2, '0');
|
|
|
+ const seconds = String(date.getUTCSeconds()).padStart(2, '0');
|
|
|
+
|
|
|
+ return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 对于其他格式,使用原来的逻辑
|
|
|
+ const date = new Date(timeString);
|
|
|
+ if (!isNaN(date.getTime())) {
|
|
|
+ return date.toLocaleString('zh-CN', {
|
|
|
+ year: 'numeric',
|
|
|
+ month: '2-digit',
|
|
|
+ day: '2-digit',
|
|
|
+ hour: '2-digit',
|
|
|
+ minute: '2-digit',
|
|
|
+ second: '2-digit'
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ console.warn('无法解析的时间格式:', timeString);
|
|
|
+ return timeString;
|
|
|
+
|
|
|
+ } catch (error) {
|
|
|
+ console.error('时间格式化错误:', error);
|
|
|
+ return timeString;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+const getScoreClass = (score) => {
|
|
|
+ if (score >= 0.8) return 'high';
|
|
|
+ if (score >= 0.6) return 'medium';
|
|
|
+ return 'low';
|
|
|
+};
|
|
|
+
|
|
|
+const getSearchResults = (searchRes) => {
|
|
|
+ try {
|
|
|
+ return JSON.parse(searchRes) || [];
|
|
|
+ } catch (error) {
|
|
|
+ console.error('解析search_res失败:', error);
|
|
|
+ return [];
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+const getDisplayedResults = (item) => {
|
|
|
+ const results = getSearchResults(item.search_res);
|
|
|
+ if (item.isResultsExpanded) {
|
|
|
+ return results;
|
|
|
+ }
|
|
|
+ return results.slice(0, 3);
|
|
|
+};
|
|
|
+
|
|
|
+const processHistoryItem = (item) => {
|
|
|
+ // 确保所有字段都有值,如果没有则从其他字段获取
|
|
|
+ return {
|
|
|
+ ...item,
|
|
|
+ final_result: item.final_result || item.chat_res || item.ai_answer || '',
|
|
|
+ chat_res: item.chat_res || '',
|
|
|
+ ai_answer: item.ai_answer || '',
|
|
|
+ // 添加展开状态
|
|
|
+ isResultsExpanded: false
|
|
|
+ };
|
|
|
+};
|
|
|
+
|
|
|
+const toggleItemDetail = (item) => {
|
|
|
+ const index = expandedItems.value.indexOf(item.create_time);
|
|
|
+ if (index === -1) {
|
|
|
+ expandedItems.value.push(item.create_time);
|
|
|
+ } else {
|
|
|
+ expandedItems.value.splice(index, 1);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+const toggleResultsExpansion = (item) => {
|
|
|
+ item.isResultsExpanded = !item.isResultsExpanded;
|
|
|
+};
|
|
|
+
|
|
|
+const handleResultDetails = async (result) => {
|
|
|
+ selectedResult.value = result;
|
|
|
+ resultDialogVisible.value = true;
|
|
|
+ activeTab.value = 'summary';
|
|
|
+
|
|
|
+ try {
|
|
|
+ const response = await fetch(`${API_BASE_URL}/content/get?docId=${result.docId}`);
|
|
|
+ const data = await response.json();
|
|
|
+ if (data.status_code === 200) {
|
|
|
+ originalContent.value = data.data.text;
|
|
|
+ } else {
|
|
|
+ ElMessage.error('获取原文内容失败');
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ ElMessage.error('请求原文内容失败');
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+const copyToClipboard = async (text) => {
|
|
|
+ try {
|
|
|
+ await navigator.clipboard.writeText(text);
|
|
|
+ ElMessage.success('已复制到剪贴板');
|
|
|
+ } catch (err) {
|
|
|
+ ElMessage.error('复制失败');
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+const handleSearch = () => {
|
|
|
+ currentPage.value = 1;
|
|
|
+};
|
|
|
+
|
|
|
+const handleSizeChange = (newSize) => {
|
|
|
+ pageSize.value = newSize;
|
|
|
+ currentPage.value = 1;
|
|
|
+ fetchHistory();
|
|
|
+};
|
|
|
+
|
|
|
+const handleCurrentChange = (newPage) => {
|
|
|
+ currentPage.value = newPage;
|
|
|
+ fetchHistory();
|
|
|
+};
|
|
|
+
|
|
|
+const refreshData = () => {
|
|
|
+ currentPage.value = 1;
|
|
|
+ fetchHistory();
|
|
|
+};
|
|
|
+
|
|
|
+const fetchHistory = async () => {
|
|
|
+ loading.value = true;
|
|
|
+ try {
|
|
|
+ const response = await fetch(
|
|
|
+ `${API_BASE_URL}/chat/history?page=${currentPage.value}&pageSize=${pageSize.value}`
|
|
|
+ );
|
|
|
+ const data = await response.json();
|
|
|
+
|
|
|
+ if (data.status_code === 200) {
|
|
|
+ // 处理每个历史记录项,确保字段正确
|
|
|
+ historyList.value = (data.data.entities || []).map(processHistoryItem);
|
|
|
+ totalCount.value = data.data.total_count || 0;
|
|
|
+ totalPages.value = data.data.total_pages || 0;
|
|
|
+ } else {
|
|
|
+ ElMessage.error('获取历史记录失败');
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ ElMessage.error('请求失败,请稍后重试');
|
|
|
+ console.error('Fetch history error:', error);
|
|
|
+ } finally {
|
|
|
+ loading.value = false;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 生命周期
|
|
|
+onMounted(() => {
|
|
|
+ fetchHistory();
|
|
|
+});
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+/* 保持原有的所有样式不变 */
|
|
|
+.history-container {
|
|
|
+ min-height: 100vh;
|
|
|
+ background: linear-gradient(135deg, rgba(102, 126, 234, 0.81) 0%, rgba(118, 75, 162, 0.77) 100%);
|
|
|
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
|
+}
|
|
|
+
|
|
|
+.history-header {
|
|
|
+ background: rgba(255, 255, 255, 0.1);
|
|
|
+ backdrop-filter: blur(20px);
|
|
|
+ padding: 20px 0;
|
|
|
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
|
|
+}
|
|
|
+
|
|
|
+.header-content {
|
|
|
+ max-width: 1200px;
|
|
|
+ margin: 0 auto;
|
|
|
+ padding: 0 24px;
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+}
|
|
|
+
|
|
|
+.header-main {
|
|
|
+ flex: 1;
|
|
|
+}
|
|
|
+
|
|
|
+.history-title {
|
|
|
+ color: white;
|
|
|
+ font-size: 2.25rem;
|
|
|
+ font-weight: 800;
|
|
|
+ margin: 0;
|
|
|
+ text-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
|
|
|
+ background: linear-gradient(135deg, #fff 0%, #e2e8f0 100%);
|
|
|
+ -webkit-background-clip: text;
|
|
|
+ -webkit-text-fill-color: transparent;
|
|
|
+ background-clip: text;
|
|
|
+}
|
|
|
+
|
|
|
+.history-subtitle {
|
|
|
+ color: rgba(255, 255, 255, 0.8);
|
|
|
+ font-size: 1rem;
|
|
|
+ margin: 8px 0 0 0;
|
|
|
+ font-weight: 500;
|
|
|
+}
|
|
|
+
|
|
|
+.header-actions {
|
|
|
+ display: flex;
|
|
|
+ gap: 12px;
|
|
|
+}
|
|
|
+
|
|
|
+.back-btn {
|
|
|
+ background: rgba(255, 255, 255, 0.2);
|
|
|
+ border: 1px solid rgba(255, 255, 255, 0.3);
|
|
|
+ color: white;
|
|
|
+ border-radius: 12px;
|
|
|
+ padding: 10px 20px;
|
|
|
+ font-weight: 600;
|
|
|
+ transition: all 0.3s ease;
|
|
|
+ backdrop-filter: blur(10px);
|
|
|
+}
|
|
|
+
|
|
|
+.back-btn:hover {
|
|
|
+ background: rgba(255, 255, 255, 0.3);
|
|
|
+ transform: translateY(-2px);
|
|
|
+ box-shadow: 0 8px 25px rgba(255, 255, 255, 0.2);
|
|
|
+}
|
|
|
+
|
|
|
+.history-content {
|
|
|
+ max-width: 1200px;
|
|
|
+ margin: 0 auto;
|
|
|
+ padding: 24px;
|
|
|
+}
|
|
|
+
|
|
|
+.stats-cards {
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
|
|
+ gap: 20px;
|
|
|
+ margin-bottom: 24px;
|
|
|
+}
|
|
|
+
|
|
|
+.stat-card {
|
|
|
+ background: white;
|
|
|
+ border-radius: 16px;
|
|
|
+ padding: 24px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 16px;
|
|
|
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
|
|
+ transition: transform 0.3s ease;
|
|
|
+}
|
|
|
+
|
|
|
+.stat-card:hover {
|
|
|
+ transform: translateY(-4px);
|
|
|
+}
|
|
|
+
|
|
|
+.stat-icon {
|
|
|
+ font-size: 2.5rem;
|
|
|
+ width: 60px;
|
|
|
+ height: 60px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
|
+ border-radius: 12px;
|
|
|
+ color: white;
|
|
|
+}
|
|
|
+
|
|
|
+.stat-info {
|
|
|
+ flex: 1;
|
|
|
+}
|
|
|
+
|
|
|
+.stat-number {
|
|
|
+ font-size: 2rem;
|
|
|
+ font-weight: 800;
|
|
|
+ color: #2d3748;
|
|
|
+ line-height: 1;
|
|
|
+ margin-bottom: 4px;
|
|
|
+}
|
|
|
+
|
|
|
+.stat-label {
|
|
|
+ color: #718096;
|
|
|
+ font-size: 0.9rem;
|
|
|
+ font-weight: 600;
|
|
|
+}
|
|
|
+
|
|
|
+.filter-section {
|
|
|
+ background: white;
|
|
|
+ border-radius: 16px;
|
|
|
+ padding: 20px;
|
|
|
+ margin-bottom: 24px;
|
|
|
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
|
|
+ display: flex;
|
|
|
+ gap: 16px;
|
|
|
+ align-items: center;
|
|
|
+}
|
|
|
+
|
|
|
+.search-input {
|
|
|
+ flex: 1;
|
|
|
+}
|
|
|
+
|
|
|
+.filter-actions {
|
|
|
+ display: flex;
|
|
|
+ gap: 12px;
|
|
|
+}
|
|
|
+
|
|
|
+.refresh-btn {
|
|
|
+ border-radius: 12px;
|
|
|
+ padding: 10px 20px;
|
|
|
+ font-weight: 600;
|
|
|
+}
|
|
|
+
|
|
|
+.loading-section {
|
|
|
+ background: white;
|
|
|
+ border-radius: 16px;
|
|
|
+ padding: 60px 32px;
|
|
|
+ text-align: center;
|
|
|
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
|
|
+}
|
|
|
+
|
|
|
+.loading-content {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ gap: 16px;
|
|
|
+}
|
|
|
+
|
|
|
+.loading-spinner {
|
|
|
+ width: 40px;
|
|
|
+ height: 40px;
|
|
|
+ border: 4px solid #e2e8f0;
|
|
|
+ border-top: 4px solid #4299e1;
|
|
|
+ border-radius: 50%;
|
|
|
+ animation: spin 1s linear infinite;
|
|
|
+}
|
|
|
+
|
|
|
+@keyframes spin {
|
|
|
+ 0% { transform: rotate(0deg); }
|
|
|
+ 100% { transform: rotate(360deg); }
|
|
|
+}
|
|
|
+
|
|
|
+.history-list {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 16px;
|
|
|
+}
|
|
|
+
|
|
|
+.empty-state {
|
|
|
+ background: white;
|
|
|
+ border-radius: 24px;
|
|
|
+ padding: 80px 32px;
|
|
|
+ text-align: center;
|
|
|
+ box-shadow: 0 12px 40px rgba(0, 0, 0, 0.12);
|
|
|
+}
|
|
|
+
|
|
|
+.empty-content {
|
|
|
+ max-width: 400px;
|
|
|
+ margin: 0 auto;
|
|
|
+}
|
|
|
+
|
|
|
+.empty-icon {
|
|
|
+ font-size: 4rem;
|
|
|
+ margin-bottom: 20px;
|
|
|
+}
|
|
|
+
|
|
|
+.empty-state h3 {
|
|
|
+ margin: 0 0 12px 0;
|
|
|
+ color: #2d3748;
|
|
|
+ font-size: 1.5rem;
|
|
|
+ font-weight: 700;
|
|
|
+}
|
|
|
+
|
|
|
+.empty-state p {
|
|
|
+ margin: 0 0 24px 0;
|
|
|
+ color: #718096;
|
|
|
+ font-size: 1rem;
|
|
|
+ line-height: 1.5;
|
|
|
+}
|
|
|
+
|
|
|
+.go-home-btn {
|
|
|
+ border-radius: 12px;
|
|
|
+ padding: 12px 24px;
|
|
|
+ font-weight: 600;
|
|
|
+}
|
|
|
+
|
|
|
+.history-items {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 16px;
|
|
|
+}
|
|
|
+
|
|
|
+.history-item {
|
|
|
+ background: white;
|
|
|
+ border-radius: 16px;
|
|
|
+ overflow: hidden;
|
|
|
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
|
|
|
+ transition: all 0.3s ease;
|
|
|
+ border: 1px solid #e2e8f0;
|
|
|
+}
|
|
|
+
|
|
|
+.history-item:hover {
|
|
|
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15);
|
|
|
+ transform: translateY(-2px);
|
|
|
+}
|
|
|
+
|
|
|
+.item-header {
|
|
|
+ padding: 24px;
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: flex-start;
|
|
|
+ gap: 16px;
|
|
|
+ cursor: pointer;
|
|
|
+}
|
|
|
+
|
|
|
+.question-content {
|
|
|
+ flex: 1;
|
|
|
+ min-width: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.question-title {
|
|
|
+ margin: 0 0 12px 0;
|
|
|
+ color: #2d3748;
|
|
|
+ font-size: 1.1rem;
|
|
|
+ font-weight: 600;
|
|
|
+ line-height: 1.4;
|
|
|
+ display: -webkit-box;
|
|
|
+ -webkit-line-clamp: 2;
|
|
|
+ -webkit-box-orient: vertical;
|
|
|
+ overflow: hidden;
|
|
|
+}
|
|
|
+
|
|
|
+.question-meta {
|
|
|
+ display: flex;
|
|
|
+ gap: 16px;
|
|
|
+ align-items: center;
|
|
|
+}
|
|
|
+
|
|
|
+.meta-item {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 6px;
|
|
|
+ color: #718096;
|
|
|
+ font-size: 0.85rem;
|
|
|
+}
|
|
|
+
|
|
|
+.meta-icon {
|
|
|
+ font-size: 0.8rem;
|
|
|
+}
|
|
|
+
|
|
|
+.item-actions {
|
|
|
+ flex-shrink: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.detail-btn {
|
|
|
+ border-radius: 12px;
|
|
|
+ padding: 8px 16px;
|
|
|
+ font-weight: 600;
|
|
|
+ transition: all 0.3s ease;
|
|
|
+}
|
|
|
+
|
|
|
+.detail-btn.active {
|
|
|
+ background: #4299e1;
|
|
|
+ color: white;
|
|
|
+}
|
|
|
+
|
|
|
+.item-detail {
|
|
|
+ border-top: 1px solid #e2e8f0;
|
|
|
+ padding: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.detail-section {
|
|
|
+ padding: 24px;
|
|
|
+ border-bottom: 1px solid #f7fafc;
|
|
|
+}
|
|
|
+
|
|
|
+.detail-section:last-child {
|
|
|
+ border-bottom: none;
|
|
|
+}
|
|
|
+
|
|
|
+.section-header {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 12px;
|
|
|
+ margin-bottom: 16px;
|
|
|
+}
|
|
|
+
|
|
|
+.section-icon {
|
|
|
+ font-size: 1.5rem;
|
|
|
+ width: 40px;
|
|
|
+ height: 40px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ background: #f7fafc;
|
|
|
+ border-radius: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.section-header h4 {
|
|
|
+ margin: 0;
|
|
|
+ color: #2d3748;
|
|
|
+ font-size: 1.1rem;
|
|
|
+ font-weight: 600;
|
|
|
+ flex: 1;
|
|
|
+}
|
|
|
+
|
|
|
+.result-count {
|
|
|
+ background: #4299e1;
|
|
|
+ color: white;
|
|
|
+ padding: 4px 10px;
|
|
|
+ border-radius: 12px;
|
|
|
+ font-size: 0.8rem;
|
|
|
+ font-weight: 600;
|
|
|
+}
|
|
|
+
|
|
|
+.section-content {
|
|
|
+ color: #4a5568;
|
|
|
+ line-height: 1.6;
|
|
|
+}
|
|
|
+
|
|
|
+.content-text {
|
|
|
+ line-height: 1.7;
|
|
|
+}
|
|
|
+
|
|
|
+.content-text :deep(h1),
|
|
|
+.content-text :deep(h2),
|
|
|
+.content-text :deep(h3) {
|
|
|
+ color: #2d3748;
|
|
|
+ margin-top: 1.5em;
|
|
|
+ margin-bottom: 0.5em;
|
|
|
+}
|
|
|
+
|
|
|
+.content-text :deep(p) {
|
|
|
+ margin-bottom: 1em;
|
|
|
+}
|
|
|
+
|
|
|
+.content-text :deep(ul),
|
|
|
+.content-text :deep(ol) {
|
|
|
+ margin: 1em 0;
|
|
|
+ padding-left: 1.5em;
|
|
|
+}
|
|
|
+
|
|
|
+.content-text :deep(li) {
|
|
|
+ margin-bottom: 0.5em;
|
|
|
+}
|
|
|
+
|
|
|
+.content-text :deep(code) {
|
|
|
+ background: #f7fafc;
|
|
|
+ padding: 2px 6px;
|
|
|
+ border-radius: 4px;
|
|
|
+ font-family: 'Monaco', 'Consolas', monospace;
|
|
|
+ color: #e53e3e;
|
|
|
+ font-size: 0.9em;
|
|
|
+}
|
|
|
+
|
|
|
+.content-text :deep(pre) {
|
|
|
+ background: #2d3748;
|
|
|
+ color: #e2e8f0;
|
|
|
+ padding: 16px;
|
|
|
+ border-radius: 8px;
|
|
|
+ overflow-x: auto;
|
|
|
+ margin: 1em 0;
|
|
|
+ font-size: 0.9em;
|
|
|
+}
|
|
|
+
|
|
|
+.search-results-preview {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 12px;
|
|
|
+}
|
|
|
+
|
|
|
+.result-preview {
|
|
|
+ background: #f7fafc;
|
|
|
+ border-radius: 12px;
|
|
|
+ padding: 16px;
|
|
|
+ border: 1px solid #e2e8f0;
|
|
|
+ cursor: pointer;
|
|
|
+ transition: all 0.3s ease;
|
|
|
+ position: relative;
|
|
|
+}
|
|
|
+
|
|
|
+.result-preview:hover {
|
|
|
+ transform: translateY(-2px);
|
|
|
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
|
|
|
+ border-color: #4299e1;
|
|
|
+}
|
|
|
+
|
|
|
+.result-header {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.result-index {
|
|
|
+ background: #4299e1;
|
|
|
+ color: white;
|
|
|
+ padding: 2px 8px;
|
|
|
+ border-radius: 8px;
|
|
|
+ font-size: 0.8rem;
|
|
|
+ font-weight: 700;
|
|
|
+}
|
|
|
+
|
|
|
+.result-score {
|
|
|
+ padding: 2px 8px;
|
|
|
+ border-radius: 8px;
|
|
|
+ font-size: 0.8rem;
|
|
|
+ font-weight: 700;
|
|
|
+ color: white;
|
|
|
+}
|
|
|
+
|
|
|
+.result-score.high {
|
|
|
+ background: #48bb78;
|
|
|
+}
|
|
|
+
|
|
|
+.result-score.medium {
|
|
|
+ background: #ed8936;
|
|
|
+}
|
|
|
+
|
|
|
+.result-score.low {
|
|
|
+ background: #e53e3e;
|
|
|
+}
|
|
|
+
|
|
|
+.result-content {
|
|
|
+ margin: 0 0 8px 0;
|
|
|
+ color: #4a5568;
|
|
|
+ font-size: 0.9rem;
|
|
|
+ line-height: 1.5;
|
|
|
+}
|
|
|
+
|
|
|
+.result-source {
|
|
|
+ background: #e2e8f0;
|
|
|
+ color: #4a5568;
|
|
|
+ padding: 2px 8px;
|
|
|
+ border-radius: 8px;
|
|
|
+ font-size: 0.8rem;
|
|
|
+ margin-bottom: 8px;
|
|
|
+ display: inline-block;
|
|
|
+}
|
|
|
+
|
|
|
+.result-footer {
|
|
|
+ display: flex;
|
|
|
+ justify-content: flex-end;
|
|
|
+ margin-top: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.view-details {
|
|
|
+ color: #4299e1;
|
|
|
+ font-weight: 600;
|
|
|
+ font-size: 0.9rem;
|
|
|
+ transition: color 0.3s ease;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 6px;
|
|
|
+}
|
|
|
+
|
|
|
+.view-icon {
|
|
|
+ font-size: 0.8rem;
|
|
|
+}
|
|
|
+
|
|
|
+.result-preview:hover .view-details {
|
|
|
+ color: #2b6cb0;
|
|
|
+}
|
|
|
+
|
|
|
+.more-results {
|
|
|
+ text-align: center;
|
|
|
+ padding: 12px;
|
|
|
+}
|
|
|
+
|
|
|
+.expand-btn {
|
|
|
+ font-weight: 600;
|
|
|
+ color: #4299e1;
|
|
|
+}
|
|
|
+
|
|
|
+.expand-btn:hover {
|
|
|
+ color: #2b6cb0;
|
|
|
+}
|
|
|
+
|
|
|
+.pagination-section {
|
|
|
+ background: white;
|
|
|
+ border-radius: 16px;
|
|
|
+ padding: 20px;
|
|
|
+ margin-top: 24px;
|
|
|
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+}
|
|
|
+
|
|
|
+.history-pagination {
|
|
|
+ margin: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.btn-icon {
|
|
|
+ margin-right: 6px;
|
|
|
+}
|
|
|
+
|
|
|
+/* 弹窗样式 - 从主页面复制并调整 */
|
|
|
+.content-dialog :deep(.el-dialog) {
|
|
|
+ border-radius: 24px;
|
|
|
+ overflow: hidden;
|
|
|
+ box-shadow: 0 25px 50px rgba(0, 0, 0, 0.2);
|
|
|
+}
|
|
|
+
|
|
|
+.content-dialog :deep(.el-dialog__header) {
|
|
|
+ padding: 0;
|
|
|
+ margin: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.content-dialog :deep(.el-dialog__headerbtn) {
|
|
|
+ top: 24px;
|
|
|
+ right: 24px;
|
|
|
+ width: 32px;
|
|
|
+ height: 32px;
|
|
|
+ border-radius: 8px;
|
|
|
+ background: #f7fafc;
|
|
|
+}
|
|
|
+
|
|
|
+.content-dialog :deep(.el-dialog__headerbtn:hover) {
|
|
|
+ background: #e2e8f0;
|
|
|
+}
|
|
|
+
|
|
|
+.dialog-header {
|
|
|
+ padding: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.dialog-title {
|
|
|
+ display: flex;
|
|
|
+ align-items: flex-start;
|
|
|
+ gap: 16px;
|
|
|
+ padding: 32px 32px 0;
|
|
|
+}
|
|
|
+
|
|
|
+.title-icon {
|
|
|
+ font-size: 2.5rem;
|
|
|
+ width: 60px;
|
|
|
+ height: 60px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
|
+ border-radius: 16px;
|
|
|
+ color: white;
|
|
|
+ flex-shrink: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.title-content {
|
|
|
+ flex: 1;
|
|
|
+ min-width: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.title-content h3 {
|
|
|
+ margin: 0 0 12px 0;
|
|
|
+ color: #2d3748;
|
|
|
+ font-size: 1.5rem;
|
|
|
+ font-weight: 700;
|
|
|
+ line-height: 1.4;
|
|
|
+}
|
|
|
+
|
|
|
+.title-meta {
|
|
|
+ display: flex;
|
|
|
+ gap: 12px;
|
|
|
+ flex-wrap: wrap;
|
|
|
+}
|
|
|
+
|
|
|
+.meta-badge {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 6px;
|
|
|
+ padding: 6px 12px;
|
|
|
+ border-radius: 12px;
|
|
|
+ font-size: 0.85rem;
|
|
|
+ font-weight: 500;
|
|
|
+}
|
|
|
+
|
|
|
+.knowledge-badge {
|
|
|
+ background: #ebf8ff;
|
|
|
+ color: #2b6cb0;
|
|
|
+ border: 1px solid #bee3f8;
|
|
|
+}
|
|
|
+
|
|
|
+.score-badge.high {
|
|
|
+ background: #f0fff4;
|
|
|
+ color: #2f855a;
|
|
|
+ border: 1px solid #c6f6d5;
|
|
|
+}
|
|
|
+
|
|
|
+.score-badge.medium {
|
|
|
+ background: #fffaf0;
|
|
|
+ color: #c05621;
|
|
|
+ border: 1px solid #feebc8;
|
|
|
+}
|
|
|
+
|
|
|
+.score-badge.low {
|
|
|
+ background: #fff5f5;
|
|
|
+ color: #c53030;
|
|
|
+ border: 1px solid #fed7d7;
|
|
|
+}
|
|
|
+
|
|
|
+.badge-icon {
|
|
|
+ font-size: 0.8rem;
|
|
|
+}
|
|
|
+
|
|
|
+.dialog-content {
|
|
|
+ padding: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.content-tabs {
|
|
|
+ display: flex;
|
|
|
+ padding: 0 32px;
|
|
|
+ border-bottom: 1px solid #e2e8f0;
|
|
|
+ margin-top: 24px;
|
|
|
+}
|
|
|
+
|
|
|
+.tab-item {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 8px;
|
|
|
+ padding: 12px 20px;
|
|
|
+ cursor: pointer;
|
|
|
+ border-bottom: 2px solid transparent;
|
|
|
+ color: #718096;
|
|
|
+ font-weight: 500;
|
|
|
+ transition: all 0.3s ease;
|
|
|
+}
|
|
|
+
|
|
|
+.tab-item:hover {
|
|
|
+ color: #4299e1;
|
|
|
+}
|
|
|
+
|
|
|
+.tab-item.active {
|
|
|
+ color: #4299e1;
|
|
|
+ border-bottom-color: #4299e1;
|
|
|
+}
|
|
|
+
|
|
|
+.tab-icon {
|
|
|
+ font-size: 1.1rem;
|
|
|
+}
|
|
|
+
|
|
|
+.tab-content {
|
|
|
+ padding: 0 32px 32px;
|
|
|
+}
|
|
|
+
|
|
|
+.content-section {
|
|
|
+ margin-top: 24px;
|
|
|
+}
|
|
|
+
|
|
|
+.section-header {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 16px;
|
|
|
+}
|
|
|
+
|
|
|
+.section-header h4 {
|
|
|
+ margin: 0;
|
|
|
+ color: #2d3748;
|
|
|
+ font-size: 1.2rem;
|
|
|
+ font-weight: 600;
|
|
|
+}
|
|
|
+
|
|
|
+.copy-btn {
|
|
|
+ font-size: 0.9rem;
|
|
|
+ padding: 6px 12px;
|
|
|
+ border-radius: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.summary-content {
|
|
|
+ background: #f7fafc;
|
|
|
+ padding: 20px;
|
|
|
+ border-radius: 12px;
|
|
|
+ color: #4a5568;
|
|
|
+ line-height: 1.6;
|
|
|
+ font-size: 0.95rem;
|
|
|
+ border: 1px solid #e2e8f0;
|
|
|
+}
|
|
|
+
|
|
|
+.original-content {
|
|
|
+ background: #f7fafc;
|
|
|
+ border-radius: 12px;
|
|
|
+ border: 1px solid #e2e8f0;
|
|
|
+ max-height: 500px;
|
|
|
+ overflow-y: auto;
|
|
|
+}
|
|
|
+
|
|
|
+.original-content pre {
|
|
|
+ margin: 0;
|
|
|
+ padding: 20px;
|
|
|
+ color: #4a5568;
|
|
|
+ line-height: 1.6;
|
|
|
+ font-size: 0.9rem;
|
|
|
+ white-space: pre-wrap;
|
|
|
+ word-wrap: break-word;
|
|
|
+}
|
|
|
+
|
|
|
+.dialog-footer {
|
|
|
+ padding: 0 32px 24px;
|
|
|
+}
|
|
|
+
|
|
|
+.footer-actions {
|
|
|
+ display: flex;
|
|
|
+ justify-content: flex-end;
|
|
|
+ gap: 12px;
|
|
|
+}
|
|
|
+
|
|
|
+.action-btn {
|
|
|
+ border-radius: 12px;
|
|
|
+ padding: 10px 24px;
|
|
|
+ font-weight: 500;
|
|
|
+ transition: all 0.3s ease;
|
|
|
+}
|
|
|
+
|
|
|
+.action-btn.secondary {
|
|
|
+ border: 1px solid #e2e8f0;
|
|
|
+ background: white;
|
|
|
+ color: #718096;
|
|
|
+}
|
|
|
+
|
|
|
+.action-btn.secondary:hover {
|
|
|
+ background: #f7fafc;
|
|
|
+ border-color: #cbd5e0;
|
|
|
+}
|
|
|
+
|
|
|
+.action-btn.primary {
|
|
|
+ background: #4299e1;
|
|
|
+ border: 1px solid #4299e1;
|
|
|
+ color: white;
|
|
|
+}
|
|
|
+
|
|
|
+.action-btn.primary:hover {
|
|
|
+ background: #3182ce;
|
|
|
+ border-color: #3182ce;
|
|
|
+ transform: translateY(-1px);
|
|
|
+ box-shadow: 0 4px 12px rgba(66, 153, 225, 0.3);
|
|
|
+}
|
|
|
+
|
|
|
+/* 响应式设计 */
|
|
|
+@media (max-width: 768px) {
|
|
|
+ .header-content {
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 16px;
|
|
|
+ text-align: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ .history-title {
|
|
|
+ font-size: 1.75rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .history-content {
|
|
|
+ padding: 16px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .stats-cards {
|
|
|
+ grid-template-columns: 1fr;
|
|
|
+ }
|
|
|
+
|
|
|
+ .filter-section {
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: stretch;
|
|
|
+ }
|
|
|
+
|
|
|
+ .item-header {
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: stretch;
|
|
|
+ gap: 12px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .item-actions {
|
|
|
+ align-self: flex-end;
|
|
|
+ }
|
|
|
+
|
|
|
+ .section-header {
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: flex-start;
|
|
|
+ gap: 8px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .content-dialog :deep(.el-dialog) {
|
|
|
+ width: 95% !important;
|
|
|
+ margin: 20px auto;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|