fix: 修复管理后台样式丢失 + CSP inline style 违规
- 评论管理页:创建 comments.css,controller 传递 ExtraCSS/ExtraJS,模板移除所有 inline style,JS 改用 CSS 类 - 修复 comments.js 加载顺序:通过 ExtraJS 在 common.js 之后加载,解决 api is not defined - base.html:SVG inline style 移至 common.css - dashboard/index.html:3 处 inline style 替换为 CSS 类 - audit/index.html:modal 移除冗余 style="display:none" - fund_logs/logs:label inline style 移至 energy.css - common.css 新增多个 CSS 规则 - energy.css 新增 .filter-bar label 规则
This commit is contained in:
@ -23,7 +23,9 @@ func NewAdminCommentController(cs adminCommentUseCase) *AdminCommentController {
|
||||
// CommentsPage SSR 页面
|
||||
func (ctrl *AdminCommentController) CommentsPage(c *gin.Context) {
|
||||
c.HTML(http.StatusOK, "admin/comments/index.html", common.BuildAdminPageData(c, gin.H{
|
||||
"Title": "评论管理",
|
||||
"Title": "评论管理",
|
||||
"ExtraCSS": "/admin/static/css/comments.css",
|
||||
"ExtraJS": "/admin/static/js/comments.js",
|
||||
}))
|
||||
}
|
||||
|
||||
|
||||
@ -86,7 +86,7 @@
|
||||
</div>
|
||||
|
||||
<!-- 拒绝理由弹窗 -->
|
||||
<div class="modal-overlay" id="rejectModal" style="display:none;">
|
||||
<div class="modal-overlay" id="rejectModal">
|
||||
<div class="modal-box">
|
||||
<h3>拒绝审核</h3>
|
||||
<p>请填写拒绝理由:</p>
|
||||
|
||||
@ -7,19 +7,19 @@
|
||||
<div class="admin-toolbar">
|
||||
<input type="text" id="commentSearch" class="admin-search-input" placeholder="搜索评论内容、作者或文章标题..." />
|
||||
<button id="commentSearchBtn" class="btn btn-secondary">搜索</button>
|
||||
<button id="commentClearBtn" class="btn btn-secondary" style="display:none">清除</button>
|
||||
<button id="commentClearBtn" class="btn btn-secondary admin-hidden">清除</button>
|
||||
</div>
|
||||
|
||||
<div class="admin-table-wrap" id="commentTableWrap">
|
||||
<table class="admin-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:60px">ID</th>
|
||||
<th style="width:100px">作者</th>
|
||||
<th class="th-id">ID</th>
|
||||
<th class="th-author">作者</th>
|
||||
<th>评论内容</th>
|
||||
<th style="width:160px">所属文章</th>
|
||||
<th style="width:140px">时间</th>
|
||||
<th style="width:100px">操作</th>
|
||||
<th class="th-post">所属文章</th>
|
||||
<th class="th-time">时间</th>
|
||||
<th class="th-actions">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="commentTableBody"></tbody>
|
||||
@ -27,7 +27,6 @@
|
||||
</div>
|
||||
|
||||
<div class="admin-pagination" id="commentPagination"></div>
|
||||
<div class="admin-loading" id="commentLoading" style="display:none">加载中...</div>
|
||||
<div class="admin-loading admin-hidden" id="commentLoading">加载中...</div>
|
||||
|
||||
{{template "admin/layout/footer.html" .}}
|
||||
<script src="/admin/static/js/comments.js?v={{assetV "/admin/static/js/comments.js"}}" nonce="{{.CSPNonce}}"></script>
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
<div class="stat-info">
|
||||
<div class="stat-label">帖子总数</div>
|
||||
<div class="stat-value">{{.PostTotal}}</div>
|
||||
<div class="stat-desc">已发布 {{.PostApproved}}<span class="stat-badge badge-warn" style="margin-left: 12px;">待审核 {{.PostPending}}</span></div>
|
||||
<div class="stat-desc">已发布 {{.PostApproved}}<span class="stat-badge badge-warn">待审核 {{.PostPending}}</span></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
@ -23,8 +23,8 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="stats-grid" style="margin-top: 1rem;">
|
||||
<div class="stat-card" style="grid-column: span 2;">
|
||||
<div class="stats-grid mt-grid">
|
||||
<div class="stat-card span-2">
|
||||
<div class="stat-icon {{if .StoreDegraded}}stat-red{{else if eq .StoreType "redis"}}stat-green{{else}}stat-blue{{end}}">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3"/><path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"/></svg>
|
||||
</div>
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
</div>
|
||||
|
||||
<div class="filter-bar">
|
||||
<label for="fund-log-type-filter" style="font-size:0.85rem;color:#4a5568;font-weight:500;">类型筛选:</label>
|
||||
<label for="fund-log-type-filter">类型筛选:</label>
|
||||
<select id="fund-log-type-filter">
|
||||
<option value="">全部类型</option>
|
||||
{{range $type, $name := .LogTypes}}<option value="{{$type}}">{{$name}}</option>{{end}}
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
</div>
|
||||
|
||||
<div class="filter-bar">
|
||||
<label for="log-type-filter" style="font-size:0.85rem;color:#4a5568;font-weight:500;">类型筛选:</label>
|
||||
<label for="log-type-filter">类型筛选:</label>
|
||||
<select id="log-type-filter">
|
||||
<option value="">全部类型</option>
|
||||
{{range $type, $name := .LogTypes}}<option value="{{$type}}">{{$name}}</option>{{end}}
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
<a href="/admin" class="admin-logo">MetaLab <span>管理面板</span></a>
|
||||
<div class="admin-header-right">
|
||||
<span class="admin-user">{{.Username}}</span>
|
||||
<a href="/" class="admin-back-btn"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="14" height="14" style="vertical-align:-2px;margin-right:3px;"><path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>返回前台</a>
|
||||
<a href="/" class="admin-back-btn"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="14" height="14"><path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>返回前台</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
144
templates/admin/static/css/comments.css
Normal file
144
templates/admin/static/css/comments.css
Normal file
@ -0,0 +1,144 @@
|
||||
/* ========== 管理后台评论管理 ========== */
|
||||
|
||||
/* --- 页面标题 --- */
|
||||
.admin-page-header {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
.admin-page-header h2 {
|
||||
font-size: 22px;
|
||||
font-weight: 600;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
/* --- 工具栏/搜索 --- */
|
||||
.admin-toolbar {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
margin-bottom: 16px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.admin-search-input {
|
||||
flex: 1;
|
||||
min-width: 200px;
|
||||
max-width: 400px;
|
||||
padding: 8px 12px;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
font-size: 13px;
|
||||
outline: none;
|
||||
transition: border-color 0.2s;
|
||||
}
|
||||
.admin-search-input:focus {
|
||||
border-color: var(--primary);
|
||||
}
|
||||
|
||||
/* --- 表格 --- */
|
||||
.admin-table-wrap {
|
||||
background: var(--bg-card);
|
||||
border-radius: var(--radius);
|
||||
box-shadow: var(--shadow);
|
||||
overflow-x: auto;
|
||||
}
|
||||
.admin-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
font-size: 13px;
|
||||
}
|
||||
.admin-table th {
|
||||
text-align: left;
|
||||
padding: 12px 16px;
|
||||
background: #f9fafb;
|
||||
color: var(--text-muted);
|
||||
font-weight: 600;
|
||||
font-size: 12px;
|
||||
border-bottom: 2px solid var(--border);
|
||||
white-space: nowrap;
|
||||
}
|
||||
.admin-table td {
|
||||
padding: 12px 16px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
font-size: 13px;
|
||||
color: #374151;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.admin-table tbody tr:hover {
|
||||
background: #f8f9ff;
|
||||
}
|
||||
|
||||
/* 列宽 */
|
||||
.th-id { width: 60px; }
|
||||
.th-author { width: 100px; }
|
||||
.th-post { width: 160px; }
|
||||
.th-time { width: 140px; }
|
||||
.th-actions { width: 100px; }
|
||||
|
||||
/* 表格空状态 / 加载失败 */
|
||||
.admin-table-empty {
|
||||
text-align: center;
|
||||
padding: 40px;
|
||||
color: #9ca3af;
|
||||
}
|
||||
.admin-table-error {
|
||||
text-align: center;
|
||||
padding: 40px;
|
||||
color: #dc2626;
|
||||
}
|
||||
|
||||
/* 评论内容列 */
|
||||
.comment-body-cell {
|
||||
max-width: 320px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* --- 分页 --- */
|
||||
.admin-pagination {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.admin-page-link {
|
||||
padding: 6px 14px;
|
||||
border: 1px solid var(--border);
|
||||
background: #fff;
|
||||
border-radius: 4px;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
color: var(--text);
|
||||
text-decoration: none;
|
||||
transition: all 0.15s;
|
||||
}
|
||||
.admin-page-link:hover {
|
||||
border-color: var(--primary);
|
||||
color: var(--primary);
|
||||
}
|
||||
.admin-page-info {
|
||||
padding: 6px 14px;
|
||||
font-size: 13px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
/* --- 加载状态 --- */
|
||||
.admin-loading {
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
color: var(--text-muted);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
/* --- 按钮适配 --- */
|
||||
.btn-secondary {
|
||||
background: #e5e7eb;
|
||||
color: #374151;
|
||||
}
|
||||
.btn-secondary:hover {
|
||||
background: #d1d5db;
|
||||
}
|
||||
|
||||
/* --- 工具类 --- */
|
||||
.admin-hidden {
|
||||
display: none;
|
||||
}
|
||||
@ -66,11 +66,12 @@ a:hover { color: var(--primary-hover); }
|
||||
display: flex; align-items: center; gap: 16px;
|
||||
}
|
||||
.admin-user { color: #dfe6e9; font-size: 13px; }
|
||||
.admin-back-btn {
|
||||
.admin-back-btn {
|
||||
font-size: 12px; color: #b2bec3;
|
||||
padding: 4px 10px; border: 1px solid #636e72;
|
||||
border-radius: 4px; transition: all 0.2s;
|
||||
}
|
||||
.admin-back-btn svg { vertical-align: -2px; margin-right: 3px; }
|
||||
.admin-back-btn:hover { color: #fff; border-color: #fff; }
|
||||
|
||||
/* --- 整体布局 --- */
|
||||
@ -123,6 +124,7 @@ a:hover { color: var(--primary-hover); }
|
||||
gap: 16px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
.stats-grid.mt-grid { margin-top: 1rem; }
|
||||
.stat-card {
|
||||
background: var(--bg-card);
|
||||
border-radius: var(--radius);
|
||||
@ -130,6 +132,7 @@ a:hover { color: var(--primary-hover); }
|
||||
box-shadow: var(--shadow);
|
||||
display: flex; align-items: center; gap: 16px;
|
||||
}
|
||||
.stat-card.span-2 { grid-column: span 2; }
|
||||
.stat-icon {
|
||||
width: 44px; height: 44px; border-radius: 10px;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
@ -142,7 +145,7 @@ a:hover { color: var(--primary-hover); }
|
||||
.stat-label { font-size: 12px; color: var(--text-muted); }
|
||||
.stat-value { font-size: 22px; font-weight: 600; color: var(--text); }
|
||||
.stat-desc { font-size: 12px; color: var(--text-muted); margin-top: 4px; }
|
||||
.stat-badge { display: inline-block; font-size: 11px; padding: 1px 8px; border-radius: 10px; margin-left: 8px; vertical-align: middle; }
|
||||
.stat-badge { display: inline-block; font-size: 11px; padding: 1px 8px; border-radius: 10px; margin-left: 12px; vertical-align: middle; }
|
||||
.badge-warn { background: #fff3e0; color: var(--warning); }
|
||||
|
||||
/* --- 信息卡片 --- */
|
||||
|
||||
@ -172,6 +172,12 @@
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.filter-bar label {
|
||||
font-size: 0.85rem;
|
||||
font-weight: 500;
|
||||
color: #4a5568;
|
||||
}
|
||||
|
||||
.filter-bar select {
|
||||
padding: 0.4rem 0.75rem;
|
||||
border: 1px solid #cbd5e0;
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
tbody.innerHTML = '';
|
||||
var items = d.data.items || [];
|
||||
if (items.length === 0) {
|
||||
tbody.innerHTML = '<tr><td colspan="6" style="text-align:center;padding:40px;color:#9ca3af">暂无评论</td></tr>';
|
||||
tbody.innerHTML = '<tr><td colspan="6" class="admin-table-empty">暂无评论</td></tr>';
|
||||
pagination.innerHTML = '';
|
||||
return;
|
||||
}
|
||||
@ -48,7 +48,7 @@
|
||||
}).catch(function() {
|
||||
loading.style.display = 'none';
|
||||
showToast('加载失败', 'error');
|
||||
tbody.innerHTML = '<tr><td colspan="6" style="text-align:center;padding:40px;color:#dc2626">加载失败</td></tr>';
|
||||
tbody.innerHTML = '<tr><td colspan="6" class="admin-table-error">加载失败</td></tr>';
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user