| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891 |
- <template>
- <div class="admin-container">
- <!-- 左侧边栏 -->
- <div class="sidebar">
- <!-- 顶部AI图标 -->
- <div class="sidebar-header">
- <img src="./assets/admin/1.png" alt="AI" class="ai-icon">
- <span class="ai-title">AI后台管理系统</span>
- </div>
-
- <!-- 导航菜单 -->
- <nav class="sidebar-nav">
- <div
- :class="['nav-item', { active: currentPage === 'chat' }]"
- @click="switchPage('chat')"
- >
- <img src="./assets/admin/2.png" alt="对话记录" class="nav-icon">
- <span class="nav-text">AI对话记录</span>
- </div>
- <div
- :class="['nav-item', { active: currentPage === 'data' }]"
- @click="switchPage('data')"
- >
- <img src="./assets/admin/3.png" alt="数据资源" class="nav-icon">
- <span class="nav-text">数据资源</span>
- </div>
- </nav>
-
- <!-- 底部用户信息 -->
- <div class="sidebar-footer">
- <div class="user-info">
- <img src="./assets/admin/4.png" alt="管理员" class="user-avatar">
- <div class="user-details">
- <span class="user-name">管理员</span>
- <span class="user-role">超级管理员</span>
- </div>
- </div>
- <button class="logout-btn" @click="handleLogout">
- <img src="./assets/admin/5.png" alt="退出" class="logout-icon">
- </button>
- </div>
- </div>
- <!-- 右侧表单区域 -->
- <div class="main-content1">
- <!-- AI对话记录页面 -->
- <div v-if="currentPage === 'chat'">
- <!-- 顶部标题和搜索 -->
- <div class="content-header">
- <div class="header-left">
- <h1 class="page-title">AI对话记录</h1>
- <p class="page-description">查看和管理所有用户与AI助手的对话历史记录</p>
- </div>
- <div class="search-box">
- <img src="./assets/admin/6.png" alt="搜索" class="search-icon">
- <input
- type="text"
- placeholder="搜索用户ID或问题内容"
- class="search-input"
- v-model="searchKeyword"
- >
- </div>
- </div>
- <!-- 数据表格 -->
- <div class="data-table">
- <table class="table">
- <thead>
- <tr>
- <th>序号</th>
- <th>用户ID</th>
- <th>提问内容</th>
- <th>回答内容</th>
- <th>提问时间</th>
- <th>状态</th>
- </tr>
- </thead>
- <tbody>
- <tr v-for="(record, index) in filteredRecords" :key="index">
- <td>{{ index + 1 }}</td>
- <td>{{ record.userId }}</td>
- <td class="content-cell">
- <div class="content-preview">{{ record.userMessage }}</div>
- </td>
- <td class="content-cell">
- <div class="content-preview">{{ record.aiReply }}</div>
- </td>
- <td>{{ record.timestamp }}</td>
- <td>
- <span :class="['status-badge', record.status]">
- {{ getStatusText(record.status) }}
- </span>
- </td>
- </tr>
- </tbody>
- </table>
- </div>
- <!-- 分页器 -->
- <div class="pagination">
- <button class="page-btn prev-btn" @click="prevPage">
- <span>‹</span>
- </button>
- <div class="page-numbers">
- <span
- v-for="page in visiblePages"
- :key="page"
- :class="['page-number', { active: page === chatCurrentPage }]"
- @click="goToPage(page)"
- >
- {{ page }}
- </span>
- </div>
- <button class="page-btn next-btn" @click="nextPage">
- <span>›</span>
- </button>
- <div class="page-info">
- 第{{ chatCurrentPage }}页,共{{ totalPages }}页
- </div>
- </div>
- </div>
- <!-- 数据资源页面 -->
- <div v-if="currentPage === 'data'">
- <!-- 顶部标题和搜索 -->
- <div class="content-header">
- <div class="header-left">
- <h1 class="page-title">数据资源</h1>
- <p class="page-description">查看和管理已标注的相关文档知识点</p>
- </div>
- <div class="search-box">
- <img src="./assets/admin/6.png" alt="搜索" class="search-icon">
- <input
- type="text"
- placeholder="搜索ID、知识点内容或标签"
- class="search-input"
- v-model="dataSearchKeyword"
- >
- </div>
- </div>
- <!-- 数据表格 -->
- <div class="data-table">
- <table class="table">
- <thead>
- <tr>
- <th>ID</th>
- <th>内容</th>
- <th>标签</th>
- <th>录入时间</th>
- <th>来源</th>
- </tr>
- </thead>
- <tbody>
- <tr v-for="(item, index) in filteredDataItems" :key="index">
- <td>{{ item.id }}</td>
- <td class="content-cell">
- <div class="content-preview">{{ item.content }}</div>
- </td>
- <td>
- <div class="tags-container">
- <span
- v-for="tag in item.tags"
- :key="tag"
- class="tag"
- >
- {{ tag }}
- </span>
- </div>
- </td>
- <td>{{ item.timestamp }}</td>
- <td class="content-cell">
- <div class="content-preview">{{ item.source }}</div>
- </td>
- </tr>
- </tbody>
- </table>
- </div>
- <!-- 分页器 -->
- <div class="pagination">
- <button class="page-btn prev-btn" @click="prevDataPage">
- <span>‹</span>
- </button>
- <div class="page-numbers">
- <span
- v-for="page in dataVisiblePages"
- :key="page"
- :class="['page-number', { active: page === dataCurrentPage }]"
- @click="goToDataPage(page)"
- >
- {{ page }}
- </span>
- </div>
- <button class="page-btn next-btn" @click="nextDataPage">
- <span>›</span>
- </button>
- <div class="page-info">
- 第{{ dataCurrentPage }}页,共{{ dataTotalPages }}页
- </div>
- </div>
- </div>
- </div>
- </div>
- </template>
- <script setup>
- import { ref, computed, onMounted } from 'vue'
- // 响应式数据
- const currentPage = ref('chat') // 当前页面:'chat' 或 'data'
- const searchKeyword = ref('')
- const chatCurrentPage = ref(1)
- const pageSize = ref(15)
- // 数据资源相关
- const dataSearchKeyword = ref('')
- const dataCurrentPage = ref(1)
- const dataPageSize = ref(15)
- // 模拟数据
- const records = ref([
- {
- userId: 'SD00125',
- userMessage: '施工现场照片如何识别脚手架搭设隐患?',
- aiReply: '脚手架搭设隐患识别可以通过以下几个关键点:1.检查连接件是否松动;2.立杆垂直度是否满足要求;3.横杆间距是否符合规范...',
- timestamp: '2023-10-15 14:32:45',
- status: 'liked'
- },
- {
- userId: 'SD00078',
- userMessage: '高性能混凝土在桥梁工程中的应用特点?',
- aiReply: '高性能混凝土在桥梁工程中的主要应用特点包括:1.具有更高的强度和耐久性;2.抗渗性能优异;3.施工性能良好...',
- timestamp: '2023-10-14 11:03:51',
- status: 'liked'
- },
- {
- userId: 'SD00234',
- userMessage: '桥梁健康监测系统如何设计?',
- aiReply: '桥梁健康监测系统设计需要考虑:1.传感器布置优化;2.数据采集与传输;3.健康状态评估算法;4.预警机制建立...',
- timestamp: '2023-10-13 16:45:22',
- status: 'liked'
- },
- {
- userId: 'SD00156',
- userMessage: '桥梁施工质量控制要点有哪些?',
- aiReply: '桥梁施工质量控制要点包括:1.原材料质量控制;2.施工工艺控制;3.质量检测与验收;4.质量记录管理...',
- timestamp: '2023-10-12 09:15:33',
- status: 'liked'
- },
- {
- userId: 'SD00345',
- userMessage: '桥梁抗震设计规范要求?',
- aiReply: '桥梁抗震设计规范要求:1.地震作用计算;2.结构抗震验算;3.构造措施要求;4.抗震性能目标...',
- timestamp: '2023-10-11 14:28:17',
- status: 'disliked'
- },
- {
- userId: 'SD00189',
- userMessage: '桥梁养护管理策略?',
- aiReply: '桥梁养护管理策略:1.定期检查制度;2.预防性养护;3.维修加固技术;4.养护资金管理...',
- timestamp: '2023-10-10 11:42:55',
- status: 'liked'
- },
- {
- userId: 'SD00456',
- userMessage: '桥梁施工安全管理措施?',
- aiReply: '桥梁施工安全管理措施:1.安全教育培训;2.安全防护设施;3.安全检查制度;4.应急预案制定...',
- timestamp: '2023-10-09 15:33:28',
- status: 'liked'
- },
- {
- userId: 'SD00278',
- userMessage: '桥梁设计荷载标准?',
- aiReply: '桥梁设计荷载标准:1.恒载计算;2.活载标准;3.风荷载;4.地震荷载;5.温度荷载...',
- timestamp: '2023-10-08 10:25:41',
- status: 'liked'
- },
- {
- userId: 'SD00567',
- userMessage: '桥梁施工进度控制方法?',
- aiReply: '桥梁施工进度控制方法:1.进度计划编制;2.进度监控;3.进度调整;4.进度报告制度...',
- timestamp: '2023-10-07 13:18:36',
- status: 'liked'
- },
- {
- userId: 'SD00321',
- userMessage: '桥梁检测技术发展现状?',
- aiReply: '桥梁检测技术发展现状:1.无损检测技术;2.智能检测设备;3.检测数据分析;4.检测标准完善...',
- timestamp: '2023-10-06 16:52:19',
- status: 'liked'
- },
- {
- userId: 'SD00678',
- userMessage: '桥梁施工环境保护要求?',
- aiReply: '桥梁施工环境保护要求:1.噪声控制;2.扬尘控制;3.废水处理;4.固体废物管理...',
- timestamp: '2023-10-05 09:41:27',
- status: 'liked'
- },
- {
- userId: 'SD00432',
- userMessage: '桥梁施工成本控制策略?',
- aiReply: '桥梁施工成本控制策略:1.成本计划编制;2.成本核算;3.成本分析;4.成本控制措施...',
- timestamp: '2023-10-04 14:15:33',
- status: 'liked'
- },
- {
- userId: 'SD00789',
- userMessage: '桥梁施工技术发展趋势?',
- aiReply: '桥梁施工技术发展趋势:1.智能化施工;2.绿色施工;3.装配式施工;4.信息化管理...',
- timestamp: '2023-10-03 11:28:45',
- status: 'liked'
- },
- {
- userId: 'SD00543',
- userMessage: '桥梁施工质量验收标准?',
- aiReply: '桥梁施工质量验收标准:1.验收程序;2.验收标准;3.验收方法;4.验收记录...',
- timestamp: '2023-10-02 15:37:12',
- status: 'liked'
- },
- {
- userId: 'SD00890',
- userMessage: '桥梁施工安全风险评估?',
- aiReply: '桥梁施工安全风险评估:1.风险识别;2.风险分析;3.风险评价;4.风险控制措施...',
- timestamp: '2023-10-01 10:52:38',
- status: 'liked'
- }
- ])
- // 数据资源模拟数据
- const dataItems = ref([
- {
- id: 'KB0012',
- content: '公路路基不均匀沉降处理方法:1.采用换填法处理软土地基;2.设置沉降缝和伸缩缝;3.加强路基压实度控制;4.采用预压法减少工后沉降。',
- tags: ['路基', '公路工程', '沉降处理'],
- timestamp: '2023-10-18 14:32:45',
- source: '《公路路基施工技术规范》(JTG F10-2006)'
- },
- {
- id: 'KB0007',
- content: '高性能混凝土在桥梁工程中的应用特点:1.具有更高的强度和耐久性;2.抗渗性能优异;3.施工性能良好;4.能够满足大跨度桥梁的承载要求。',
- tags: ['混凝土', '桥梁工程', '材料应用'],
- timestamp: '2023-10-17 11:03:51',
- source: '《公路桥涵施工技术规范》(JTG/T F50-2011)'
- },
- {
- id: 'KB0034',
- content: '大跨径桥梁施工技术要点:1.采用悬臂浇筑法施工;2.设置临时支撑体系;3.实施智能监测系统;4.严格控制施工精度和质量。',
- tags: ['大跨径桥梁', '施工技术', '智能监测'],
- timestamp: '2023-10-16 16:45:22',
- source: '《公路工程技术标准》(JTG B01-2014)'
- },
- {
- id: 'KB0015',
- content: '公路车道宽度设计标准:1.一级公路车道宽度为3.75m;2.二级公路车道宽度为3.5m;3.三级公路车道宽度为3.25m;4.四级公路车道宽度为3.0m。',
- tags: ['公路标准', '车道宽度', '设计规范'],
- timestamp: '2023-10-15 09:15:33',
- source: '《公路工程技术标准》(JTG B01-2014)'
- },
- {
- id: 'KB0029',
- content: '桥梁预应力张拉施工注意事项:1.张拉前检查锚具和钢绞线;2.控制张拉力和伸长量;3.实施对称张拉;4.做好张拉记录和检测。',
- tags: ['预应力', '桥梁施工', '张拉技术'],
- timestamp: '2023-10-14 14:28:17',
- source: '《公路桥涵施工技术规范》(JTG/T F50-2011)'
- },
- {
- id: 'KB0018',
- content: 'SMA与SUP沥青混合料区别:1.SMA具有更好的抗车辙性能;2.SUP具有更好的低温性能;3.施工工艺要求不同;4.适用场景有所差异。',
- tags: ['沥青混合料', '路面材料', 'SMA'],
- timestamp: '2023-10-13 11:42:55',
- source: '《公路沥青路面施工技术规范》(JTG F40-2004)'
- },
- {
- id: 'KB0005',
- content: '隧道突水突泥防治措施:1.超前地质预报;2.注浆加固围岩;3.设置排水系统;4.加强施工监测和预警。',
- tags: ['隧道施工', '安全防护', '突水防治'],
- timestamp: '2023-10-12 15:33:28',
- source: '《公路隧道施工技术规范》(JTG F60-2009)'
- },
- {
- id: 'KB0021',
- content: '脚手架搭设隐患识别要点:1.检查连接件是否松动;2.立杆垂直度是否满足要求;3.横杆间距是否符合规范;4.安全防护设施是否完善。',
- tags: ['脚手架', '施工安全', '隐患识别'],
- timestamp: '2023-10-11 10:25:41',
- source: '《建筑施工安全检查标准》(JGJ 59-2011)'
- },
- {
- id: 'KB0043',
- content: '高铁轨道精调技术要点:1.轨道几何状态检测;2.扣件调整和更换;3.轨道平顺性控制;4.精调后质量验收。',
- tags: ['高铁轨道', '精调技术', '质量控制'],
- timestamp: '2023-10-10 13:18:36',
- source: '《高速铁路轨道工程施工质量验收标准》(TB 10754-2010)'
- },
- {
- id: 'KB0038',
- content: '桥梁健康监测系统设计原则:1.传感器布置优化;2.数据采集与传输;3.健康状态评估算法;4.预警机制建立。',
- tags: ['桥梁监测', '健康评估', '智能系统'],
- timestamp: '2023-10-09 16:52:19',
- source: '《公路桥梁技术状况评定标准》(JTG/T H21-2011)'
- },
- {
- id: 'KB0025',
- content: '公路施工环境保护要求:1.噪声控制措施;2.扬尘控制技术;3.废水处理工艺;4.固体废物管理。',
- tags: ['环境保护', '施工管理', '绿色施工'],
- timestamp: '2023-10-08 09:41:27',
- source: '《公路工程施工环境保护技术规范》(JTG B06-2007)'
- },
- {
- id: 'KB0041',
- content: '桥梁抗震设计要点:1.地震作用计算;2.结构抗震验算;3.构造措施要求;4.抗震性能目标。',
- tags: ['桥梁抗震', '结构设计', '安全性能'],
- timestamp: '2023-10-07 14:15:33',
- source: '《公路桥梁抗震设计细则》(JTG/T B02-01-2008)'
- }
- ])
- // 计算属性
- const filteredRecords = computed(() => {
- if (!searchKeyword.value) return records.value
-
- return records.value.filter(record =>
- record.userId.includes(searchKeyword.value) ||
- record.userMessage.includes(searchKeyword.value) ||
- record.aiReply.includes(searchKeyword.value)
- )
- })
- const totalRecords = computed(() => filteredRecords.value.length)
- const totalPages = computed(() => Math.ceil(totalRecords.value / pageSize.value))
- const visiblePages = computed(() => {
- const pages = []
- const start = Math.max(1, chatCurrentPage.value - 2)
- const end = Math.min(totalPages.value, start + 4)
-
- for (let i = start; i <= end; i++) {
- pages.push(i)
- }
- return pages
- })
- // 数据资源计算属性
- const filteredDataItems = computed(() => {
- if (!dataSearchKeyword.value) return dataItems.value
-
- return dataItems.value.filter(item =>
- item.id.includes(dataSearchKeyword.value) ||
- item.content.includes(dataSearchKeyword.value) ||
- item.tags.some(tag => tag.includes(dataSearchKeyword.value)) ||
- item.source.includes(dataSearchKeyword.value)
- )
- })
- const dataTotalRecords = computed(() => filteredDataItems.value.length)
- const dataTotalPages = computed(() => Math.ceil(dataTotalRecords.value / dataPageSize.value))
- const dataVisiblePages = computed(() => {
- const pages = []
- const start = Math.max(1, dataCurrentPage.value - 2)
- const end = Math.min(dataTotalPages.value, start + 4)
-
- for (let i = start; i <= end; i++) {
- pages.push(i)
- }
- return pages
- })
- // 方法
- const switchPage = (page) => {
- currentPage.value = page
- }
- const getStatusText = (status) => {
- const statusMap = {
- 'liked': '已点赞',
- 'disliked': '踩',
- 'empty': ''
- }
- return statusMap[status] || ''
- }
- // AI对话记录分页方法
- const prevPage = () => {
- if (chatCurrentPage.value > 1) {
- chatCurrentPage.value--
- }
- }
- const nextPage = () => {
- if (chatCurrentPage.value < totalPages.value) {
- chatCurrentPage.value++
- }
- }
- const goToPage = (page) => {
- chatCurrentPage.value = page
- }
- // 数据资源分页方法
- const prevDataPage = () => {
- if (dataCurrentPage.value > 1) {
- dataCurrentPage.value--
- }
- }
- const nextDataPage = () => {
- if (dataCurrentPage.value < dataTotalPages.value) {
- dataCurrentPage.value++
- }
- }
- const goToDataPage = (page) => {
- dataCurrentPage.value = page
- }
- // 退出登录
- const handleLogout = () => {
- // 清除所有token和用户信息
- localStorage.removeItem('shudao_refresh_token')
- localStorage.removeItem('shudao_token_type')
- localStorage.removeItem('shudao_username')
- // 重定向到统一认证门户
- window.location.href = 'https://tyrz.scgsdsj.com/iga/login_sd.html'
- console.log('🚪 已退出登录,跳转到统一认证门户')
- }
- onMounted(() => {
- // 初始化数据
- })
- </script>
- <style lang="less" scoped>
- .admin-container {
- display: flex;
- height: 100vh;
- font-family: 'Alibaba PuHuiTi 3.0', sans-serif;
- }
- /* 左侧边栏 */
- .sidebar {
- width: 240px;
- background: url('./assets/admin/7.png') no-repeat;
- // background-size: 240px 100%;
- background-position: center;
- display: flex;
- flex-direction: column;
- color: white;
-
- .sidebar-header {
- padding: 24px 20px;
- border-bottom: 1px solid #DBEAFE50;
- display: flex;
- align-items: center;
- gap: 12px;
-
- .ai-icon {
- width: 40px;
- height: 40px;
- object-fit: contain;
- }
-
- .ai-title {
- font-size: 18px;
- font-weight: 600;
- color: #fff;
- }
- }
-
- .sidebar-nav {
- flex: 1;
- padding: 20px 0;
-
- .nav-item {
- display: flex;
- align-items: center;
- gap: 12px;
- padding: 16px 16px;
- cursor: pointer;
- transition: all 0.3s ease;
-
- &:hover {
- background: rgba(255, 255, 255, 0.1);
- }
-
- &.active {
- background: #3E7BFA;
- border-left: 4px solid #fff;
- }
-
- .nav-icon {
- width: 20px;
- height: 20px;
- object-fit: contain;
- }
-
- .nav-text {
- font-size: 14px;
- color: #fff;
- }
- }
- }
-
- .sidebar-footer {
- padding: 20px;
- border-top: 1px solid #333;
- display: flex;
- justify-content: space-between;
- align-items: center;
-
- .user-info {
- display: flex;
- align-items: center;
- gap: 12px;
-
- .user-avatar {
- width: 36px;
- height: 36px;
- object-fit: contain;
- border-radius: 50%;
- }
-
- .user-details {
- display: flex;
- flex-direction: column;
- gap: 2px;
-
- .user-name {
- font-size: 14px;
- color: #fff;
- font-weight: 500;
- }
-
- .user-role {
- font-size: 12px;
- color: #999;
- }
- }
- }
-
- .logout-btn {
- background: none;
- border: none;
- cursor: pointer;
- padding: 8px;
- border-radius: 4px;
- transition: all 0.3s ease;
-
- &:hover {
- background: rgba(255, 255, 255, 0.1);
- }
-
- .logout-icon {
- width: 18px;
- height: 18px;
- object-fit: contain;
- }
- }
- }
- }
- /* 右侧主内容区 */
- .main-content1 {
- flex: 1;
- // background: #f5f5f5;
- display: flex;
- flex-direction: column;
- overflow: hidden;
- }
- /* 内容头部 */
- .content-header {
- // background: white;
- padding: 24px 32px;
- // border-bottom: 1px solid #e5e5e5;
- display: flex;
- justify-content: space-between;
- align-items: flex-start;
-
- .header-left {
- .page-title {
- font-size: 24px;
- font-weight: 600;
- color: #333;
- margin: 0 0 8px 0;
- }
-
- .page-description {
- font-size: 14px;
- color: #666;
- margin: 0;
- }
- }
-
- .search-box {
- display: flex;
- align-items: center;
- gap: 12px;
- background: #f8f9fa;
- border: 1px solid #e5e5e5;
- border-radius: 8px;
- padding: 12px 16px;
- width: 300px;
- margin-right: 15px;
- margin-top: 8px;
-
- .search-icon {
- width: 16px;
- height: 16px;
- object-fit: contain;
- }
-
- .search-input {
- flex: 1;
- border: none;
- background: transparent;
- outline: none;
- font-size: 14px;
- color: #333;
-
- &::placeholder {
- color: #999;
- }
- }
- }
- }
- /* 数据表格 */
- .data-table {
- flex: 1;
- overflow: auto;
- padding: 0px 32px;
-
- .table {
- width: 100%;
- background: white;
- border-radius: 8px;
- border-collapse: collapse;
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
-
- th, td {
- padding: 16px;
- text-align: left;
- border-bottom: 1px solid #f0f0f0;
- }
-
- th {
- background: #f8f9fa;
- font-weight: 600;
- color: #333;
- font-size: 14px;
- }
-
- td {
- color: #666;
- font-size: 14px;
- }
-
- .content-cell {
- max-width: 300px;
-
- .content-preview {
- max-height: 60px;
- overflow: hidden;
- text-overflow: ellipsis;
- display: -webkit-box;
- -webkit-line-clamp: 1;
- -webkit-box-orient: vertical;
- line-height: 1.4;
- }
- }
-
- .status-badge {
- padding: 4px 12px;
- border-radius: 4px;
- font-size: 12px;
- font-weight: 500;
-
- &.liked {
- background: rgba(34, 197, 94, 0.1);
- color: #22c55e;
- }
-
- &.disliked {
- background: #f3f4f6;
- color: #6b7280;
- }
-
- &.empty {
- background: transparent;
- color: transparent;
- }
- }
-
- .tags-container {
- display: flex;
- flex-wrap: wrap;
- gap: 4px;
-
- .tag {
- background: rgba(59, 130, 246, 0.1);
- color: #3b82f6;
- padding: 2px 8px;
- border-radius: 4px;
- font-size: 12px;
- font-weight: 500;
- white-space: nowrap;
- }
- }
- }
- }
- /* 分页器 */
- .pagination {
- // background: white;
- padding: 20px 30px;
- // border-top: 1px solid #e5e5e5;
- display: flex;
- justify-content: center;
- align-items: center;
- gap: 10px;
-
- .page-btn {
- width: 32px;
- height: 32px;
- border: 1px solid #e5e5e5;
- background: white;
- color: #666;
- border-radius: 4px;
- cursor: pointer;
- transition: all 0.3s ease;
- display: flex;
- align-items: center;
- justify-content: center;
- font-size: 18px;
-
- &:hover:not(:disabled) {
- background: #f8f9fa;
- border-color: #3E7BFA;
- color: #3E7BFA;
- }
-
- &:disabled {
- opacity: 0.5;
- cursor: not-allowed;
- }
- }
-
- .page-numbers {
- display: flex;
- gap: 8px;
-
- .page-number {
- width: 32px;
- height: 32px;
- border: 1px solid #e5e5e5;
- background: white;
- color: #666;
- border-radius: 4px;
- cursor: pointer;
- transition: all 0.3s ease;
- display: flex;
- align-items: center;
- justify-content: center;
- font-size: 14px;
-
- &:hover {
- background: #f8f9fa;
- border-color: #3E7BFA;
- color: #3E7BFA;
- }
-
- &.active {
- background: #3E7BFA;
- color: white;
- border-color: #3E7BFA;
- }
- }
- }
-
- .page-info {
- color: #666;
- font-size: 14px;
- margin-left: 20px;
- }
- }
- </style>
|