| <template> |
| <div class="section-page"> |
| <div class="page-container"> |
| <!-- 面包屑导航 --> |
| <div class="breadcrumb"> |
| <el-breadcrumb separator="/"> |
| <el-breadcrumb-item :to="{ path: '/forum' }">论坛首页</el-breadcrumb-item> |
| <el-breadcrumb-item>{{ sectionInfo.name }}</el-breadcrumb-item> |
| </el-breadcrumb> |
| </div> |
| |
| <!-- 版块信息 --> |
| <div class="section-header"> |
| <div class="section-info"> |
| <div class="section-icon"> |
| <el-icon size="48" :color="sectionInfo.color"> |
| <component :is="sectionInfo.icon" /> |
| </el-icon> |
| </div> |
| <div class="section-details"> |
| <h1 class="section-name">{{ sectionInfo.name }}</h1> |
| <p class="section-description">{{ sectionInfo.description }}</p> |
| <div class="section-stats"> |
| <div class="stat-item"> |
| <el-icon><ChatDotRound /></el-icon> |
| <span>{{ sectionInfo.topics }} 主题</span> |
| </div> |
| <div class="stat-item"> |
| <el-icon><Comment /></el-icon> |
| <span>{{ sectionInfo.replies }} 回复</span> |
| </div> |
| <div class="stat-item"> |
| <el-icon><User /></el-icon> |
| <span>{{ sectionInfo.members }} 成员</span> |
| </div> |
| </div> |
| </div> |
| </div> |
| |
| <div class="section-actions"> |
| <el-button type="primary" :icon="Edit" @click="showNewTopicDialog = true"> |
| 发布新主题 |
| </el-button> |
| </div> |
| </div> |
| |
| <!-- 筛选和搜索 --> |
| <div class="filter-section"> |
| <div class="filter-left"> |
| <el-input |
| v-model="searchQuery" |
| placeholder="搜索主题..." |
| :prefix-icon="Search" |
| @keyup.enter="handleSearch" |
| clearable |
| style="width: 300px;" |
| /> |
| <el-button type="primary" @click="handleSearch">搜索</el-button> |
| </div> |
| |
| <div class="filter-right"> |
| <el-select v-model="sortBy" placeholder="排序方式" @change="handleFilter"> |
| <el-option label="最新回复" value="last_reply" /> |
| <el-option label="发布时间" value="create_time" /> |
| <el-option label="回复数量" value="replies" /> |
| <el-option label="浏览次数" value="views" /> |
| </el-select> |
| |
| <el-select v-model="filterType" placeholder="主题类型" @change="handleFilter"> |
| <el-option label="全部主题" value="" /> |
| <el-option label="置顶主题" value="pinned" /> |
| <el-option label="热门主题" value="hot" /> |
| <el-option label="精华主题" value="featured" /> |
| </el-select> |
| </div> |
| </div> |
| |
| <!-- 置顶主题 --> |
| <div v-if="pinnedTopics.length > 0" class="pinned-topics"> |
| <h3 class="section-title">置顶主题</h3> |
| <div class="topics-list"> |
| <div |
| v-for="topic in pinnedTopics" |
| :key="topic.id" |
| class="topic-item pinned" |
| @click="navigateToTopic(topic.id)" |
| > |
| <div class="topic-status"> |
| <el-icon class="pin-icon"><Top /></el-icon> |
| </div> |
| |
| <div class="topic-content"> |
| <div class="topic-header"> |
| <h4 class="topic-title">{{ topic.title }}</h4> |
| <div class="topic-tags"> |
| <el-tag type="warning" size="small">置顶</el-tag> |
| <el-tag v-if="topic.hot" type="danger" size="small">热门</el-tag> |
| <el-tag v-if="topic.featured" type="success" size="small">精华</el-tag> |
| </div> |
| </div> |
| |
| <div class="topic-meta"> |
| <div class="author-info"> |
| <el-avatar :size="24">{{ topic.author.charAt(0) }}</el-avatar> |
| <span class="author-name">{{ topic.author }}</span> |
| <span class="create-time">{{ formatTime(topic.createTime) }}</span> |
| </div> |
| |
| <div class="topic-stats"> |
| <span class="stat-item"> |
| <el-icon><View /></el-icon> |
| {{ topic.views }} |
| </span> |
| <span class="stat-item"> |
| <el-icon><Comment /></el-icon> |
| {{ topic.replies }} |
| </span> |
| </div> |
| </div> |
| </div> |
| |
| <div class="last-reply"> |
| <div v-if="topic.lastReply" class="reply-info"> |
| <div class="reply-author">{{ topic.lastReply.author }}</div> |
| <div class="reply-time">{{ formatTime(topic.lastReply.time) }}</div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| |
| <!-- 普通主题列表 --> |
| <div class="normal-topics"> |
| <div class="section-header"> |
| <h3 class="section-title">主题列表</h3> |
| <div class="results-info"> |
| 共 {{ totalTopics }} 个主题 |
| </div> |
| </div> |
| |
| <div class="topics-list" v-loading="loading"> |
| <div |
| v-for="topic in topics" |
| :key="topic.id" |
| class="topic-item" |
| @click="navigateToTopic(topic.id)" |
| > |
| <div class="topic-status"> |
| <el-icon v-if="topic.hasNewReplies" class="new-icon" color="#f56c6c"> |
| <ChatDotRound /> |
| </el-icon> |
| <el-icon v-else class="normal-icon" color="#909399"> |
| <ChatLineRound /> |
| </el-icon> |
| </div> |
| |
| <div class="topic-content"> |
| <div class="topic-header"> |
| <h4 class="topic-title">{{ topic.title }}</h4> |
| <div class="topic-tags"> |
| <el-tag v-if="topic.hot" type="danger" size="small">热门</el-tag> |
| <el-tag v-if="topic.featured" type="success" size="small">精华</el-tag> |
| <el-tag v-if="topic.closed" type="info" size="small">已关闭</el-tag> |
| </div> |
| </div> |
| |
| <div class="topic-meta"> |
| <div class="author-info"> |
| <el-avatar :size="24">{{ topic.author.charAt(0) }}</el-avatar> |
| <span class="author-name">{{ topic.author }}</span> |
| <span class="create-time">{{ formatTime(topic.createTime) }}</span> |
| </div> |
| |
| <div class="topic-stats"> |
| <span class="stat-item"> |
| <el-icon><View /></el-icon> |
| {{ topic.views }} |
| </span> |
| <span class="stat-item"> |
| <el-icon><Comment /></el-icon> |
| {{ topic.replies }} |
| </span> |
| </div> |
| </div> |
| </div> |
| |
| <div class="last-reply"> |
| <div v-if="topic.lastReply" class="reply-info"> |
| <div class="reply-author">{{ topic.lastReply.author }}</div> |
| <div class="reply-time">{{ formatTime(topic.lastReply.time) }}</div> |
| </div> |
| <div v-else class="no-reply">暂无回复</div> |
| </div> |
| </div> |
| |
| <div v-if="topics.length === 0 && !loading" class="no-topics"> |
| 暂无主题,快来发布第一个主题吧! |
| </div> |
| </div> |
| |
| <!-- 分页 --> |
| <div class="pagination-wrapper"> |
| <el-pagination |
| v-model:current-page="currentPage" |
| v-model:page-size="pageSize" |
| :page-sizes="[20, 50, 100]" |
| :total="totalTopics" |
| layout="total, sizes, prev, pager, next, jumper" |
| @size-change="handleSizeChange" |
| @current-change="handleCurrentChange" |
| /> |
| </div> |
| </div> |
| </div> |
| |
| <!-- 发布新主题对话框 --> |
| <el-dialog |
| v-model="showNewTopicDialog" |
| title="发布新主题" |
| width="600px" |
| :before-close="handleCloseDialog" |
| > |
| <el-form |
| ref="topicFormRef" |
| :model="newTopic" |
| :rules="topicRules" |
| label-width="80px" |
| > |
| <el-form-item label="主题标题" prop="title"> |
| <el-input |
| v-model="newTopic.title" |
| placeholder="请输入主题标题" |
| maxlength="100" |
| show-word-limit |
| /> |
| </el-form-item> |
| |
| <el-form-item label="主题标签"> |
| <div class="tags-input"> |
| <el-tag |
| v-for="tag in newTopic.tags" |
| :key="tag" |
| closable |
| @close="removeTopicTag(tag)" |
| > |
| {{ tag }} |
| </el-tag> |
| <el-input |
| v-if="tagInputVisible" |
| ref="tagInputRef" |
| v-model="tagInputValue" |
| size="small" |
| @keyup.enter="addTopicTag" |
| @blur="addTopicTag" |
| style="width: 100px;" |
| /> |
| <el-button |
| v-else |
| size="small" |
| @click="showTagInput" |
| > |
| + 添加标签 |
| </el-button> |
| </div> |
| </el-form-item> |
| |
| <el-form-item label="主题内容" prop="content"> |
| <el-input |
| v-model="newTopic.content" |
| type="textarea" |
| :rows="8" |
| placeholder="请输入主题内容..." |
| maxlength="5000" |
| show-word-limit |
| /> |
| </el-form-item> |
| |
| <el-form-item label="主题选项"> |
| <el-checkbox-group v-model="newTopic.options"> |
| <el-checkbox label="hot">申请热门</el-checkbox> |
| <el-checkbox label="featured">申请精华</el-checkbox> |
| </el-checkbox-group> |
| </el-form-item> |
| </el-form> |
| |
| <template #footer> |
| <el-button @click="handleCloseDialog">取消</el-button> |
| <el-button type="primary" @click="submitNewTopic" :loading="submitting"> |
| 发布主题 |
| </el-button> |
| </template> |
| </el-dialog> |
| </div> |
| </template> |
| |
| <script> |
| import { ref, reactive, onMounted, nextTick } from 'vue' |
| import { useRoute, useRouter } from 'vue-router' |
| import { ElMessage, ElMessageBox } from 'element-plus' |
| import { |
| Edit, |
| Search, |
| ChatDotRound, |
| Comment, |
| User, |
| View, |
| Top, |
| ChatLineRound, |
| Film, |
| Headphones, |
| Monitor, |
| GamePad, |
| Bell, |
| QuestionFilled |
| } from '@element-plus/icons-vue' |
| |
| export default { |
| name: 'ForumSectionView', |
| setup() { |
| const route = useRoute() |
| const router = useRouter() |
| const topicFormRef = ref(null) |
| const tagInputRef = ref(null) |
| |
| const loading = ref(false) |
| const showNewTopicDialog = ref(false) |
| const submitting = ref(false) |
| const tagInputVisible = ref(false) |
| const tagInputValue = ref('') |
| |
| const searchQuery = ref('') |
| const sortBy = ref('last_reply') |
| const filterType = ref('') |
| const currentPage = ref(1) |
| const pageSize = ref(20) |
| const totalTopics = ref(0) |
| |
| const sectionInfo = ref({ |
| id: 1, |
| name: '电影讨论', |
| description: '分享和讨论电影资源,交流观影心得', |
| icon: 'Film', |
| color: '#409eff', |
| topics: 3256, |
| replies: 18934, |
| members: 1234 |
| }) |
| |
| const newTopic = reactive({ |
| title: '', |
| content: '', |
| tags: [], |
| options: [] |
| }) |
| |
| const topicRules = { |
| title: [ |
| { required: true, message: '请输入标题', trigger: 'blur' }, |
| { min: 5, max: 100, message: '标题长度在 5 到 100 个字符', trigger: 'blur' } |
| ], |
| content: [ |
| { required: true, message: '请输入内容', trigger: 'blur' }, |
| { min: 10, max: 5000, message: '内容长度在 10 到 5000 个字符', trigger: 'blur' } |
| ] |
| } |
| |
| const pinnedTopics = ref([ |
| { |
| id: 1, |
| title: '【公告】本版块发帖规则和注意事项', |
| author: 'Admin', |
| createTime: '2025-05-01T10:00:00', |
| views: 5678, |
| replies: 23, |
| hot: false, |
| featured: true, |
| lastReply: { |
| author: 'User123', |
| time: '2025-06-02T15:30:00' |
| } |
| } |
| ]) |
| |
| const topics = ref([ |
| { |
| id: 2, |
| title: '2024年度最佳科幻电影推荐榜单', |
| author: 'SciFiFan', |
| createTime: '2025-06-03T10:30:00', |
| views: 1234, |
| replies: 45, |
| hot: true, |
| featured: false, |
| closed: false, |
| hasNewReplies: true, |
| lastReply: { |
| author: 'MovieLover', |
| time: '2025-06-03T14:25:00' |
| } |
| }, |
| { |
| id: 3, |
| title: '阿凡达2:水之道 观影感受分享', |
| author: 'Avatar2Fan', |
| createTime: '2025-06-02T16:45:00', |
| views: 892, |
| replies: 67, |
| hot: false, |
| featured: true, |
| closed: false, |
| hasNewReplies: false, |
| lastReply: { |
| author: 'CinemaExpert', |
| time: '2025-06-03T12:10:00' |
| } |
| }, |
| { |
| id: 4, |
| title: '求推荐几部好看的悬疑电影', |
| author: 'SuspenseLover', |
| createTime: '2025-06-01T09:20:00', |
| views: 456, |
| replies: 23, |
| hot: false, |
| featured: false, |
| closed: false, |
| hasNewReplies: true, |
| lastReply: { |
| author: 'ThrillerFan', |
| time: '2025-06-03T11:45:00' |
| } |
| } |
| ]) |
| |
| onMounted(() => { |
| const sectionId = route.params.id |
| fetchSectionData(sectionId) |
| }) |
| |
| const fetchSectionData = async (id) => { |
| loading.value = true |
| try { |
| // 模拟API调用 |
| console.log('获取版块数据:', id) |
| |
| // 根据版块ID设置不同的版块信息 |
| const sections = { |
| 1: { name: '电影讨论', description: '分享和讨论电影资源,交流观影心得', icon: 'Film', color: '#409eff' }, |
| 2: { name: '音乐分享', description: '音乐资源分享,音乐制作技术交流', icon: 'Headphones', color: '#67c23a' }, |
| 3: { name: '软件技术', description: '软件资源分享,技术问题讨论', icon: 'Monitor', color: '#e6a23c' }, |
| 4: { name: '游戏天地', description: '游戏资源分享,游戏攻略讨论', icon: 'GamePad', color: '#f56c6c' }, |
| 5: { name: '站务公告', description: '网站公告,规则说明,意见建议', icon: 'Bell', color: '#909399' }, |
| 6: { name: '新手求助', description: '新手问题解答,使用教程分享', icon: 'QuestionFilled', color: '#606266' } |
| } |
| |
| const sectionData = sections[id] || sections[1] |
| sectionInfo.value = { |
| id: parseInt(id), |
| ...sectionData, |
| topics: 3256, |
| replies: 18934, |
| members: 1234 |
| } |
| |
| totalTopics.value = 156 |
| |
| } catch (error) { |
| ElMessage.error('获取版块数据失败') |
| } finally { |
| loading.value = false |
| } |
| } |
| |
| const formatTime = (timeString) => { |
| const date = new Date(timeString) |
| const now = new Date() |
| const diff = now - date |
| const hours = Math.floor(diff / (1000 * 60 * 60)) |
| |
| if (hours < 1) return '刚刚' |
| if (hours < 24) return `${hours}小时前` |
| const days = Math.floor(hours / 24) |
| if (days < 7) return `${days}天前` |
| |
| return date.toLocaleDateString('zh-CN', { |
| month: '2-digit', |
| day: '2-digit', |
| hour: '2-digit', |
| minute: '2-digit' |
| }) |
| } |
| |
| const navigateToTopic = (topicId) => { |
| router.push(`/forum/topic/${topicId}`) |
| } |
| |
| const handleSearch = () => { |
| currentPage.value = 1 |
| fetchTopics() |
| } |
| |
| const handleFilter = () => { |
| currentPage.value = 1 |
| fetchTopics() |
| } |
| |
| const fetchTopics = async () => { |
| loading.value = true |
| try { |
| // 模拟API调用 |
| await new Promise(resolve => setTimeout(resolve, 500)) |
| console.log('获取主题列表:', { searchQuery: searchQuery.value, sortBy: sortBy.value, filterType: filterType.value }) |
| } catch (error) { |
| ElMessage.error('获取主题列表失败') |
| } finally { |
| loading.value = false |
| } |
| } |
| |
| const handleSizeChange = (size) => { |
| pageSize.value = size |
| currentPage.value = 1 |
| fetchTopics() |
| } |
| |
| const handleCurrentChange = (page) => { |
| currentPage.value = page |
| fetchTopics() |
| } |
| |
| const showTagInput = () => { |
| tagInputVisible.value = true |
| nextTick(() => { |
| tagInputRef.value?.focus() |
| }) |
| } |
| |
| const addTopicTag = () => { |
| const tag = tagInputValue.value.trim() |
| if (tag && !newTopic.tags.includes(tag)) { |
| newTopic.tags.push(tag) |
| } |
| tagInputVisible.value = false |
| tagInputValue.value = '' |
| } |
| |
| const removeTopicTag = (tag) => { |
| const index = newTopic.tags.indexOf(tag) |
| if (index > -1) { |
| newTopic.tags.splice(index, 1) |
| } |
| } |
| |
| const handleCloseDialog = () => { |
| if (newTopic.title || newTopic.content) { |
| ElMessageBox.confirm( |
| '确定要关闭吗?未保存的内容将会丢失。', |
| '提示', |
| { |
| confirmButtonText: '确定', |
| cancelButtonText: '取消', |
| type: 'warning' |
| } |
| ).then(() => { |
| resetForm() |
| showNewTopicDialog.value = false |
| }).catch(() => { |
| // 用户取消 |
| }) |
| } else { |
| resetForm() |
| showNewTopicDialog.value = false |
| } |
| } |
| |
| const submitNewTopic = async () => { |
| try { |
| await topicFormRef.value?.validate() |
| |
| submitting.value = true |
| |
| // 模拟提交过程 |
| await new Promise(resolve => setTimeout(resolve, 1500)) |
| |
| ElMessage.success('主题发布成功!') |
| resetForm() |
| showNewTopicDialog.value = false |
| |
| // 刷新主题列表 |
| fetchTopics() |
| |
| } catch (error) { |
| console.error('表单验证失败:', error) |
| } finally { |
| submitting.value = false |
| } |
| } |
| |
| const resetForm = () => { |
| topicFormRef.value?.resetFields() |
| newTopic.title = '' |
| newTopic.content = '' |
| newTopic.tags = [] |
| newTopic.options = [] |
| } |
| |
| return { |
| loading, |
| showNewTopicDialog, |
| submitting, |
| tagInputVisible, |
| tagInputValue, |
| searchQuery, |
| sortBy, |
| filterType, |
| currentPage, |
| pageSize, |
| totalTopics, |
| sectionInfo, |
| pinnedTopics, |
| topics, |
| newTopic, |
| topicRules, |
| topicFormRef, |
| tagInputRef, |
| formatTime, |
| navigateToTopic, |
| handleSearch, |
| handleFilter, |
| handleSizeChange, |
| handleCurrentChange, |
| showTagInput, |
| addTopicTag, |
| removeTopicTag, |
| handleCloseDialog, |
| submitNewTopic, |
| Edit, |
| Search, |
| ChatDotRound, |
| Comment, |
| User, |
| View, |
| Top, |
| ChatLineRound, |
| Film, |
| Headphones, |
| Monitor, |
| GamePad, |
| Bell, |
| QuestionFilled |
| } |
| } |
| } |
| </script> |
| |
| <style lang="scss" scoped> |
| .section-page { |
| max-width: 1200px; |
| margin: 0 auto; |
| padding: 24px; |
| background: #f5f5f5; |
| min-height: 100vh; |
| } |
| |
| .breadcrumb { |
| margin-bottom: 16px; |
| } |
| |
| .section-header { |
| background: #fff; |
| border-radius: 12px; |
| padding: 32px; |
| margin-bottom: 24px; |
| box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05); |
| |
| display: flex; |
| justify-content: space-between; |
| align-items: center; |
| gap: 24px; |
| |
| .section-info { |
| display: flex; |
| align-items: center; |
| gap: 20px; |
| flex: 1; |
| |
| .section-details { |
| .section-name { |
| font-size: 28px; |
| font-weight: 600; |
| color: #2c3e50; |
| margin: 0 0 8px 0; |
| } |
| |
| .section-description { |
| font-size: 16px; |
| color: #7f8c8d; |
| margin: 0 0 16px 0; |
| } |
| |
| .section-stats { |
| display: flex; |
| gap: 24px; |
| |
| .stat-item { |
| display: flex; |
| align-items: center; |
| gap: 8px; |
| font-size: 14px; |
| color: #606266; |
| } |
| } |
| } |
| } |
| |
| .section-actions { |
| flex-shrink: 0; |
| } |
| } |
| |
| .filter-section { |
| background: #fff; |
| border-radius: 12px; |
| padding: 20px 24px; |
| margin-bottom: 24px; |
| box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05); |
| |
| display: flex; |
| justify-content: space-between; |
| align-items: center; |
| gap: 20px; |
| |
| .filter-left { |
| display: flex; |
| align-items: center; |
| gap: 12px; |
| } |
| |
| .filter-right { |
| display: flex; |
| align-items: center; |
| gap: 12px; |
| |
| .el-select { |
| width: 120px; |
| } |
| } |
| } |
| |
| .pinned-topics, .normal-topics { |
| background: #fff; |
| border-radius: 12px; |
| padding: 24px; |
| margin-bottom: 24px; |
| box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05); |
| |
| .section-header { |
| display: flex; |
| justify-content: space-between; |
| align-items: center; |
| margin-bottom: 20px; |
| background: none; |
| padding: 0; |
| box-shadow: none; |
| |
| .section-title { |
| font-size: 18px; |
| font-weight: 600; |
| color: #2c3e50; |
| margin: 0; |
| } |
| |
| .results-info { |
| font-size: 14px; |
| color: #909399; |
| } |
| } |
| } |
| |
| .topics-list { |
| .topic-item { |
| display: flex; |
| align-items: center; |
| gap: 16px; |
| padding: 16px; |
| border: 1px solid #f0f0f0; |
| border-radius: 8px; |
| margin-bottom: 12px; |
| cursor: pointer; |
| transition: all 0.3s ease; |
| |
| &:hover { |
| background: #f8f9fa; |
| border-color: #409eff; |
| transform: translateX(2px); |
| } |
| |
| &.pinned { |
| background: linear-gradient(90deg, #fff7e6 0%, #fff 100%); |
| border-color: #e6a23c; |
| } |
| |
| .topic-status { |
| width: 32px; |
| text-align: center; |
| |
| .pin-icon { |
| color: #e6a23c; |
| } |
| |
| .new-icon { |
| animation: pulse 2s infinite; |
| } |
| } |
| |
| .topic-content { |
| flex: 1; |
| |
| .topic-header { |
| display: flex; |
| align-items: center; |
| gap: 12px; |
| margin-bottom: 8px; |
| |
| .topic-title { |
| font-size: 16px; |
| font-weight: 500; |
| color: #2c3e50; |
| margin: 0; |
| flex: 1; |
| |
| &:hover { |
| color: #409eff; |
| } |
| } |
| |
| .topic-tags { |
| .el-tag { |
| margin-left: 4px; |
| } |
| } |
| } |
| |
| .topic-meta { |
| display: flex; |
| justify-content: space-between; |
| align-items: center; |
| |
| .author-info { |
| display: flex; |
| align-items: center; |
| gap: 8px; |
| |
| .author-name { |
| font-size: 14px; |
| font-weight: 500; |
| color: #606266; |
| } |
| |
| .create-time { |
| font-size: 12px; |
| color: #909399; |
| } |
| } |
| |
| .topic-stats { |
| display: flex; |
| gap: 16px; |
| |
| .stat-item { |
| display: flex; |
| align-items: center; |
| gap: 4px; |
| font-size: 12px; |
| color: #909399; |
| } |
| } |
| } |
| } |
| |
| .last-reply { |
| width: 150px; |
| text-align: right; |
| |
| .reply-info { |
| .reply-author { |
| font-size: 14px; |
| font-weight: 500; |
| color: #606266; |
| margin-bottom: 4px; |
| } |
| |
| .reply-time { |
| font-size: 12px; |
| color: #909399; |
| } |
| } |
| |
| .no-reply { |
| font-size: 12px; |
| color: #c0c4cc; |
| } |
| } |
| } |
| |
| .no-topics { |
| text-align: center; |
| color: #909399; |
| padding: 60px 0; |
| font-size: 16px; |
| } |
| } |
| |
| .pagination-wrapper { |
| margin-top: 24px; |
| text-align: center; |
| } |
| |
| .tags-input { |
| display: flex; |
| flex-wrap: wrap; |
| gap: 8px; |
| align-items: center; |
| |
| .el-tag { |
| margin: 0; |
| } |
| } |
| |
| @keyframes pulse { |
| 0% { |
| transform: scale(1); |
| } |
| 50% { |
| transform: scale(1.1); |
| } |
| 100% { |
| transform: scale(1); |
| } |
| } |
| |
| @media (max-width: 768px) { |
| .section-page { |
| padding: 16px; |
| } |
| |
| .section-header { |
| flex-direction: column; |
| align-items: flex-start; |
| gap: 16px; |
| |
| .section-info { |
| flex-direction: column; |
| text-align: center; |
| |
| .section-stats { |
| justify-content: center; |
| } |
| } |
| |
| .section-actions { |
| width: 100%; |
| text-align: center; |
| } |
| } |
| |
| .filter-section { |
| flex-direction: column; |
| gap: 16px; |
| |
| .filter-left, .filter-right { |
| width: 100%; |
| justify-content: center; |
| } |
| |
| .filter-right { |
| .el-select { |
| width: 140px; |
| } |
| } |
| } |
| |
| .topic-item { |
| flex-direction: column; |
| align-items: flex-start; |
| gap: 12px; |
| |
| .topic-status { |
| align-self: flex-start; |
| } |
| |
| .topic-content { |
| width: 100%; |
| |
| .topic-meta { |
| flex-direction: column; |
| align-items: flex-start; |
| gap: 8px; |
| } |
| } |
| |
| .last-reply { |
| width: 100%; |
| text-align: left; |
| } |
| } |
| } |
| </style> |