Files
m2pool_web_frontend/mining-pool/src/views/announcements/index.vue

1032 lines
24 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="announcements-container" >
<!-- 主要内容区域 -->
<div class="main-content" v-loading="announcementsLoading">
<!-- 页面标题 -->
<div class="page-header">
<div class="header-left">
<h1 class="page-title">{{ $t('home.announcements') || '公告中心' }}</h1>
</div>
</div>
<!-- Markdown 使用规则指南 -->
<div class="markdown-guide-section" v-if="showMarkdownGuide">
<!-- 可展开的使用规则内容 -->
<transition name="slide-fade">
<div v-show="showMarkdownGuide" class="markdown-guide-content">
<div class="guide-container">
<h3 class="guide-title">📝 Markdown 语法规则详解</h3>
<!-- 标题语法 -->
<div class="guide-section">
<h4>1. 标题语法 (#符号)</h4>
<div class="example-container">
<div class="syntax-example">
<pre><code># 一级标题 (最大)
## 二级标题
### 三级标题
#### 四级标题
##### 五级标题
###### 六级标题 (最小)</code></pre>
</div>
<div class="result-preview">
<h1 style="font-size: 24px; margin: 8px 0;">一级标题</h1>
<h2 style="font-size: 20px; margin: 6px 0;">二级标题</h2>
<h3 style="font-size: 16px; margin: 4px 0;">三级标题</h3>
</div>
</div>
</div>
<!-- 文本格式化 -->
<div class="guide-section">
<h4>2. 文本格式化</h4>
<div class="example-container">
<div class="syntax-example">
<pre><code>**粗体文本**
*斜体文本*
***粗斜体***
~~删除线~~
`行内代码`</code></pre>
</div>
<div class="result-preview">
<p><strong>粗体文本</strong></p>
<p><em>斜体文本</em></p>
<p><strong><em>粗斜体</em></strong></p>
<p><del>删除线</del></p>
<p><code>行内代码</code></p>
</div>
</div>
</div>
<!-- 列表语法 -->
<div class="guide-section">
<h4>3. 列表语法</h4>
<div class="example-container">
<div class="syntax-example">
<pre><code>- 无序列表项 1
- 无序列表项 2
- 子列表项 2.1
- 子列表项 2.2
1. 有序列表项 1
2. 有序列表项 2
3. 有序列表项 3</code></pre>
</div>
<div class="result-preview">
<ul>
<li>无序列表项 1</li>
<li>无序列表项 2
<ul>
<li>子列表项 2.1</li>
<li>子列表项 2.2</li>
</ul>
</li>
</ul>
<ol>
<li>有序列表项 1</li>
<li>有序列表项 2</li>
<li>有序列表项 3</li>
</ol>
</div>
</div>
</div>
<!-- 链接和图片 -->
<div class="guide-section">
<h4>4. 链接和图片</h4>
<div class="example-container">
<div class="syntax-example">
<pre><code>[链接文本](https://example.com)
![图片描述](https://example.com/image.png)
参考式链接
[链接文本][1]
[1]: https://example.com</code></pre>
</div>
<div class="result-preview">
<p><a href="#" style="color: #5721E4;">链接文本</a></p>
<p>📷 图片会在这里显示</p>
<p><a href="#" style="color: #5721E4;">参考式链接</a></p>
</div>
</div>
</div>
<!-- 代码块 -->
<div class="guide-section">
<h4>5. 代码块</h4>
<div class="example-container">
<div class="syntax-example">
<pre><code>```javascript
function hello() {
console.log("Hello World!");
}
```
```python
def hello():
print("Hello World!")
```</code></pre>
</div>
<div class="result-preview">
<pre style="background: #f8f9fa; padding: 12px; border-radius: 4px;"><code>function hello() {
console.log("Hello World!");
}</code></pre>
</div>
</div>
</div>
<!-- 表格 -->
<div class="guide-section">
<h4>6. 表格语法</h4>
<div class="example-container">
<div class="syntax-example">
<pre><code>| 列标题1 | 列标题2 | 列标题3 |
|---------|---------|---------|
| 单元格1 | 单元格2 | 单元格3 |
| 数据A | 数据B | 数据C |
对齐方式
| 左对齐 | 居中对齐 | 右对齐 |
|:-------|:--------:|-------:|
| | | |</code></pre>
</div>
<div class="result-preview">
<table style="border-collapse: collapse; width: 100%;">
<thead>
<tr style="background: #f8f9fa;">
<th style="border: 1px solid #ddd; padding: 8px;">列标题1</th>
<th style="border: 1px solid #ddd; padding: 8px;">列标题2</th>
<th style="border: 1px solid #ddd; padding: 8px;">列标题3</th>
</tr>
</thead>
<tbody>
<tr>
<td style="border: 1px solid #ddd; padding: 8px;">单元格1</td>
<td style="border: 1px solid #ddd; padding: 8px;">单元格2</td>
<td style="border: 1px solid #ddd; padding: 8px;">单元格3</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!-- 引用 -->
<div class="guide-section">
<h4>7. 引用语法</h4>
<div class="example-container">
<div class="syntax-example">
<pre><code>> 这是一个引用块
> 可以包含多行内容
>
> > 嵌套引用
> > 可以多层嵌套</code></pre>
</div>
<div class="result-preview">
<blockquote style="border-left: 4px solid #5721E4; padding-left: 16px; margin: 16px 0; color: #666;">
<p>这是一个引用块<br>可以包含多行内容</p>
<blockquote style="border-left: 4px solid #ccc; padding-left: 16px;">
<p>嵌套引用<br>可以多层嵌套</p>
</blockquote>
</blockquote>
</div>
</div>
</div>
<!-- 分隔线 -->
<div class="guide-section">
<h4>8. 分隔线</h4>
<div class="example-container">
<div class="syntax-example">
<pre><code>--- (三个或更多短横线)
*** (三个或更多星号)
___ (三个或更多下划线)</code></pre>
</div>
<div class="result-preview">
<hr style="border: none; border-top: 1px solid #ddd; margin: 16px 0;">
</div>
</div>
</div>
<!-- 任务列表 -->
<div class="guide-section">
<h4>9. 任务列表</h4>
<div class="example-container">
<div class="syntax-example">
<pre><code>- [x] 已完成任务
- [ ] 待完成任务
- [x] 另一个已完成任务</code></pre>
</div>
<div class="result-preview">
<ul style="list-style: none; padding-left: 0;">
<li> 已完成任务</li>
<li> 待完成任务</li>
<li> 另一个已完成任务</li>
</ul>
</div>
</div>
</div>
<!-- 转义字符 -->
<div class="guide-section">
<h4>10. 转义字符</h4>
<div class="example-container">
<div class="syntax-example">
<pre><code>\* 显示星号而不是斜体
\# 显示井号而不是标题
\` 显示反引号
\\ 显示反斜杠</code></pre>
</div>
<div class="result-preview">
<p>* 显示星号而不是斜体</p>
<p># 显示井号而不是标题</p>
<p>` 显示反引号</p>
<p>\ 显示反斜杠</p>
</div>
</div>
</div>
<!-- 快捷提示 -->
<div class="guide-section tips-section">
<h4>💡 实用提示</h4>
<div class="tips-grid">
<div class="tip-item">
<strong>标题层级</strong>按逻辑顺序使用不跳级
</div>
<div class="tip-item">
<strong>空行</strong>在不同元素之间添加空行提高可读性
</div>
<div class="tip-item">
<strong>列表缩进</strong>子列表用2个空格缩进
</div>
<div class="tip-item">
<strong>代码语言</strong>指定代码块语言以获得语法高亮
</div>
<div class="tip-item">
<strong>表格对齐</strong>保持表格列的对齐美观
</div>
<div class="tip-item">
<strong>链接描述</strong>使用有意义的链接文本
</div>
</div>
</div>
<!-- 常用快捷键 -->
<div class="guide-section">
<h4> 编辑器快捷键</h4>
<div class="shortcuts-grid">
<div class="shortcut-item">
<kbd>Ctrl</kbd> + <kbd>B</kbd> 粗体
</div>
<div class="shortcut-item">
<kbd>Ctrl</kbd> + <kbd>I</kbd> 斜体
</div>
<div class="shortcut-item">
<kbd>Ctrl</kbd> + <kbd>K</kbd> 插入链接
</div>
<div class="shortcut-item">
<kbd>Ctrl</kbd> + <kbd>`</kbd> → 行内代码
</div>
<div class="shortcut-item">
<kbd>Ctrl</kbd> + <kbd>1-6</kbd> → 标题
</div>
<div class="shortcut-item">
<kbd>Ctrl</kbd> + <kbd>Z</kbd> → 撤销
</div>
</div>
</div>
</div>
</div>
</transition>
</div>
<!-- 最新公告标题 -->
<div class="latest-section">
<h2 class="section-title">{{ $t('home.latestTitle') || '最新公告' }}</h2>
</div>
<!-- 公告列表 -->
<div class="announcement-list" v-if="!loading && announcements.length > 0">
<div
v-for="announcement in announcements"
:key="announcement.id"
class="announcement-item"
@click="handleAnnouncementClick(announcement)"
>
<div class="announcement-content">
<h3 class="announcement-title">{{ announcement.title }}</h3>
<div class="announcement-meta">
<span class="announcement-date">{{ formatDate(announcement.createTime) }}</span>
<span class="announcement-type" v-if="announcement.type">{{handelType(announcement.type) }}</span>
</div>
<p class="announcement-summary" v-if="announcement.summary">
{{ announcement.summary }}
</p>
</div>
<div class="announcement-arrow">
<i class="el-icon-arrow-right"></i>
</div>
</div>
</div>
<!-- 空状态 -->
<div v-else-if="!loading && announcements.length === 0" class="empty-state">
<div class="empty-content">
<i class="el-icon-document"></i>
<p>{{ $t('home.noData') || '暂无公告' }}</p>
</div>
</div>
<!-- 分页信息和查看更多 -->
<div class="pagination-section" v-if="announcements.length > 0">
<!-- <div class="view-all-button">
<el-button
type="text"
class="view-all-link"
@click="handleViewAll"
>
{{ $t('home.viewAll') || '查看所有' }} {{ totalCount }} {{ $t('home.articles') || '篇文章' }}
</el-button>
</div> -->
<!-- 分页组件 -->
<el-pagination
@current-change="handleCurrentChange"
@size-change="handleSizeChange"
:current-page="currentPage"
:page-sizes="[10, 50, 100, 400]"
:total="totalCount"
layout="total, sizes, prev, pager, next, jumper"
class="pagination"
/>
</div>
</div>
</div>
</template>
<script>
/**
* 公告中心页面组件
* 提供公告列表展示、搜索、分页等功能
*/
import Index from './index.js'
export default {
name: 'Announcements',
mixins:[Index],
}
</script>
<style lang="scss" scoped>
/**
* 公告中心页面样式
*/
.announcements-container {
min-height: 100vh;
background-color: #f8f9fa;
padding: 20px;
}
/* 面包屑导航区域 */
.breadcrumb-section {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30px;
background: white;
padding: 16px 24px;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
}
.breadcrumb {
font-size: 14px;
.breadcrumb-item {
color: #666;
cursor: pointer;
transition: color 0.3s ease;
&:hover {
color: #5721E4;
}
}
}
.search-section {
.search-input {
width: 300px;
}
}
/* 主要内容区域 */
.main-content {
max-width: 1200px;
margin: 0 auto;
background: white;
border-radius: 12px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
overflow: hidden;
margin-top: 60px;
}
/* 页面标题 */
.page-header {
padding: 40px 40px 20px;
border-bottom: 1px solid #f0f0f0;
text-align: center;
}
.page-title {
font-size: 32px;
font-weight: 600;
color: #2c3e50;
margin: 0;
}
/* Markdown 使用规则指南 */
.markdown-guide-section {
padding: 30px 40px 20px;
border-bottom: 1px solid #f0f0f0;
}
.guide-header {
display: flex;
justify-content: flex-start;
margin-bottom: 20px;
}
.guide-toggle-btn {
font-size: 14px;
color: #5721E4;
text-decoration: none;
transition: color 0.3s ease;
&:hover {
color: #5721E4;
text-decoration: underline;
}
}
.markdown-guide-content {
background: #f8f9ff;
border-radius: 8px;
padding: 20px;
border: 1px solid #e0e0e0;
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05);
}
.guide-container {
max-height: 0;
overflow: hidden;
transition: max-height 0.3s ease-in-out;
}
.guide-container.show {
max-height: 1000px; /* 足够大的高度,确保所有内容都可见 */
}
.guide-title {
font-size: 20px;
font-weight: 600;
color: #34495e;
margin-bottom: 20px;
border-bottom: 1px solid #f0f0f0;
padding-bottom: 10px;
}
.guide-section {
margin-bottom: 25px;
padding-bottom: 20px;
border-bottom: 1px dashed #eee;
&:last-child {
border-bottom: none;
padding-bottom: 0;
}
}
.guide-section h4 {
font-size: 16px;
font-weight: 500;
color: #4a4a4a;
margin-bottom: 15px;
position: relative;
padding-left: 15px;
&::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 4px;
height: 15px;
background: #5721E4;
border-radius: 2px;
}
}
.example-container {
display: flex;
gap: 20px;
margin-bottom: 15px;
}
.syntax-example {
flex: 1;
background: #f0f0f0;
border-radius: 4px;
padding: 10px;
overflow-x: auto;
font-size: 14px;
color: #333;
line-height: 1.6;
white-space: pre-wrap;
word-break: break-all;
border: 1px solid #ccc;
}
.result-preview {
flex: 1;
padding: 10px;
background: #fff;
border-radius: 4px;
border: 1px solid #eee;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
min-height: 100px; /* Ensure some height for preview */
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
font-size: 14px;
color: #555;
line-height: 1.8;
}
.tips-section {
margin-top: 20px;
padding-top: 20px;
border-top: 1px dashed #eee;
}
.tips-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 15px;
margin-top: 15px;
}
.tip-item {
background: #f0edff;
padding: 10px 15px;
border-radius: 6px;
font-size: 13px;
color: #5721E4;
font-weight: 500;
display: flex;
align-items: center;
gap: 8px;
}
.shortcuts-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 10px;
margin-top: 15px;
}
.shortcut-item {
background: #f0edff;
padding: 8px 12px;
border-radius: 6px;
font-size: 13px;
color: #5721E4;
font-weight: 500;
display: flex;
align-items: center;
gap: 8px;
}
.shortcut-item kbd {
background-color: #e0e0e0;
border-radius: 4px;
padding: 2px 4px;
font-size: 12px;
font-family: monospace;
color: #333;
box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.2);
}
/* 最新公告标题 */
.latest-section {
padding: 30px 40px 20px;
}
.section-title {
font-size: 20px;
font-weight: 600;
color: #34495e;
margin: 0;
position: relative;
&::before {
content: '';
position: absolute;
left: -20px;
top: 50%;
transform: translateY(-50%);
width: 4px;
height: 20px;
background: #5721E4;
border-radius: 2px;
}
}
/* 公告列表 */
.announcement-list {
padding: 0 40px 20px;
}
.announcement-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 20px 0;
border-bottom: 1px solid #f5f5f5;
cursor: pointer;
transition: all 0.3s ease;
&:hover {
background-color: #f8f9ff;
transform: translateX(5px);
}
&:last-child {
border-bottom: none;
}
}
.announcement-content {
flex: 1;
}
.announcement-title {
font-size: 16px;
font-weight: 500;
color: #2c3e50;
margin: 0 0 8px;
line-height: 1.4;
transition: color 0.3s ease;
.announcement-item:hover & {
color: #5721E4;
}
}
.announcement-meta {
display: flex;
align-items: center;
gap: 16px;
margin-bottom: 8px;
}
.announcement-date {
font-size: 12px;
color: #999;
}
.announcement-type {
font-size: 12px;
color: #5721E4;
background: #f0edff;
padding: 2px 8px;
border-radius: 12px;
}
.announcement-summary {
font-size: 14px;
color: #666;
line-height: 1.5;
margin: 0;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.announcement-arrow {
color: #ccc;
transition: color 0.3s ease;
.announcement-item:hover & {
color: #5721E4;
}
}
/* 空状态 */
.empty-state {
text-align: center;
padding: 80px 40px;
}
.empty-content {
i {
font-size: 64px;
color: #ddd;
margin-bottom: 20px;
}
p {
font-size: 16px;
color: #999;
margin: 0;
}
}
/* 分页区域 */
.pagination-section {
padding: 30px 40px 40px;
text-align: center;
border-top: 1px solid #f0f0f0;
}
.view-all-button {
margin-bottom: 20px;
display: flex;
justify-content: center;
align-items: center;
gap: 16px;
flex-wrap: wrap;
}
.view-all-link {
font-size: 14px;
color: #5721E4;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
/* Markdown指南按钮样式 */
.markdown-guide-btn {
font-size: 14px;
color: #5721E4 !important;
font-weight: 500;
transition: all 0.3s ease;
border: 1px solid #5721E4;
border-radius: 4px;
padding: 8px 16px;
&:hover {
color: #fff !important;
background-color: #5721E4 !important;
transform: translateY(-1px);
box-shadow: 0 4px 8px rgba(87, 33, 228, 0.3);
}
}
.pagination {
justify-content: center;
:deep(.el-pager li) {
background-color: transparent;
color: #666;
&.active {
background-color: #5721E4;
color: white;
}
&:hover:not(.active) {
background-color: #f0edff;
color: #5721E4;
}
}
:deep(.btn-prev),
:deep(.btn-next) {
background-color: transparent;
color: #666;
&:hover {
background-color: #f0edff;
color: #5721E4;
}
}
}
/* 移动端适配 */
@media screen and (max-width: 768px) {
.announcements-container {
padding: 10px;
}
.breadcrumb-section {
flex-direction: column;
gap: 16px;
align-items: stretch;
padding: 16px;
}
.search-section .search-input {
width: 100%;
}
.main-content {
border-radius: 8px;
}
.markdown-guide-section {
padding: 15px 20px;
}
.guide-header {
justify-content: center;
}
.guide-toggle-btn {
font-size: 13px;
}
.markdown-guide-content {
padding: 10px;
}
.guide-container {
max-height: none; /* Allow content to wrap */
}
.guide-container.show {
max-height: none;
}
.example-container {
flex-direction: column;
gap: 10px;
}
.syntax-example,
.result-preview {
width: 100%;
}
.tips-grid,
.shortcuts-grid {
grid-template-columns: 1fr;
}
.tip-item,
.shortcut-item {
justify-content: flex-start;
padding-left: 15px;
}
.shortcut-item kbd {
font-size: 11px;
}
.page-header,
.latest-section,
.announcement-list,
.pagination-section {
padding-left: 20px;
padding-right: 20px;
}
.page-title {
font-size: 24px;
}
.section-title {
font-size: 18px;
&::before {
left: -16px;
}
}
.announcement-item {
padding: 16px 0;
}
.announcement-title {
font-size: 15px;
}
.announcement-meta {
flex-direction: column;
align-items: flex-start;
gap: 4px;
}
/* 移动端按钮样式调整 */
.view-all-button {
flex-direction: column;
gap: 12px;
}
.markdown-guide-btn {
font-size: 13px;
padding: 6px 12px;
}
}
/* 深色模式适配 */
@media (prefers-color-scheme: dark) {
.announcements-container {
background-color: #1a1a1a;
}
.breadcrumb-section,
.main-content {
background: #2d2d2d;
color: #fff;
}
.markdown-guide-section {
background: #2d2d2d;
border-color: #3a3a3a;
}
.guide-title,
.guide-section h4 {
color: #fff;
}
.syntax-example {
background: #3a3a3a;
border-color: #555;
color: #ccc;
}
.result-preview {
background: #333;
border-color: #555;
color: #bbb;
}
.tips-section {
border-top-color: #3a3a3a;
}
.tip-item {
background: #3a3a3a;
color: #888;
}
.shortcut-item {
background: #3a3a3a;
color: #888;
}
.shortcut-item kbd {
background-color: #444;
color: #eee;
box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3);
}
.page-title,
.section-title,
.announcement-title {
color: #fff;
}
.announcement-item:hover {
background-color: #3a3a3a;
}
.announcement-summary {
color: #ccc;
}
.announcement-date {
color: #999;
}
}
/* 展开/收起动画 */
.slide-fade-enter-active {
transition: all 0.3s ease;
}
.slide-fade-leave-active {
transition: all 0.3s ease;
}
.slide-fade-enter,
.slide-fade-leave-to {
transform: translateY(-10px);
opacity: 0;
}
</style>