Update admin UI overhaul, scores , tooltip/version fixes

This commit is contained in:
2026-05-13 19:16:34 +08:00
parent ab9749a111
commit aeb360bc8a
6 changed files with 307 additions and 68 deletions
@@ -55,6 +55,7 @@ public class AdminSystemController extends BaseController {
private final UpgradeLogRepository upgradeLogRepository; private final UpgradeLogRepository upgradeLogRepository;
private final AuditLogRepository auditLogRepository; private final AuditLogRepository auditLogRepository;
private final AuditLogService auditLogService; private final AuditLogService auditLogService;
private final com.yaoyuan.jiscuss.service.IScoreService scoreService;
public AdminSystemController( public AdminSystemController(
UsersRepository usersRepository, UsersRepository usersRepository,
@@ -65,7 +66,8 @@ public class AdminSystemController extends BaseController {
UserRoleRepository userRoleRepository, UserRoleRepository userRoleRepository,
UpgradeLogRepository upgradeLogRepository, UpgradeLogRepository upgradeLogRepository,
AuditLogRepository auditLogRepository, AuditLogRepository auditLogRepository,
AuditLogService auditLogService) { AuditLogService auditLogService,
com.yaoyuan.jiscuss.service.IScoreService scoreService) {
this.usersRepository = usersRepository; this.usersRepository = usersRepository;
this.discussionsRepository = discussionsRepository; this.discussionsRepository = discussionsRepository;
this.postsRepository = postsRepository; this.postsRepository = postsRepository;
@@ -75,6 +77,7 @@ public class AdminSystemController extends BaseController {
this.upgradeLogRepository = upgradeLogRepository; this.upgradeLogRepository = upgradeLogRepository;
this.auditLogRepository = auditLogRepository; this.auditLogRepository = auditLogRepository;
this.auditLogService = auditLogService; this.auditLogService = auditLogService;
this.scoreService = scoreService;
} }
@GetMapping("/admin/home") @GetMapping("/admin/home")
@@ -294,6 +297,27 @@ public class AdminSystemController extends BaseController {
return "admin/themes"; return "admin/themes";
} }
/** 积分管理 — list all users sorted by score desc. */
@GetMapping("/admin/scores")
public String scores(HttpServletRequest request, ModelMap map) {
fillCommon(request, map, "scores");
List<User> users = usersRepository.findAll(Sort.by(Sort.Direction.DESC, "score"));
map.put("users", users);
return "admin/scores";
}
/** Manually adjust a user's score (admin operation). */
@PostMapping("/admin/scores/{id}/adjust")
public String adjustScore(@PathVariable Integer id,
@RequestParam int delta,
HttpServletRequest request) {
UserInfo operator = getUserInfo(request);
scoreService.addScore(id, delta);
auditLogService.log(operator, "score_adjust", "user", id,
"score " + (delta >= 0 ? "+" : "") + delta);
return "redirect:/admin/scores";
}
private void fillCommon(HttpServletRequest request, ModelMap map, String active) { private void fillCommon(HttpServletRequest request, ModelMap map, String active) {
UserInfo user = getUserInfo(request); UserInfo user = getUserInfo(request);
map.put("adminName", user == null ? "admin" : user.getUsername()); map.put("adminName", user == null ? "admin" : user.getUsername());
@@ -327,13 +351,30 @@ public class AdminSystemController extends BaseController {
result.put("java", System.getProperty("java.version")); result.put("java", System.getProperty("java.version"));
result.put("spring", implVersion("org.springframework.core.SpringVersion")); result.put("spring", implVersion("org.springframework.core.SpringVersion"));
result.put("hibernate", implVersion("org.hibernate.Version")); result.put("hibernate", implVersion("org.hibernate.Version"));
result.put("flyway", implVersion("org.flywaydb.core.Flyway")); result.put("flyway", mavenVersion("org.flywaydb", "flyway-core",
result.put("druid", implVersion("com.alibaba.druid.pool.DruidDataSource")); implVersion("org.flywaydb.core.Flyway")));
result.put("druid", mavenVersion("com.alibaba", "druid-spring-boot-3-starter",
mavenVersion("com.alibaba", "druid",
implVersion("com.alibaba.druid.pool.DruidDataSource"))));
result.put("ehcache", implVersion("org.ehcache.CacheManager")); result.put("ehcache", implVersion("org.ehcache.CacheManager"));
result.put("springdoc", implVersion("org.springdoc.core.configuration.SpringDocConfiguration")); result.put("springdoc", implVersion("org.springdoc.core.configuration.SpringDocConfiguration"));
return result; return result;
} }
/** Read version from META-INF/maven pom.properties (works in fat JARs). Falls back to {@code fallback}. */
private String mavenVersion(String groupId, String artifactId, String fallback) {
String path = "/META-INF/maven/" + groupId + "/" + artifactId + "/pom.properties";
try (java.io.InputStream is = getClass().getResourceAsStream(path)) {
if (is != null) {
java.util.Properties props = new java.util.Properties();
props.load(is);
String v = props.getProperty("version");
if (v != null && !v.isBlank()) return v;
}
} catch (Exception ignored) {}
return fallback;
}
private String implVersion(String className) { private String implVersion(String className) {
try { try {
Class<?> clazz = Class.forName(className); Class<?> clazz = Class.forName(className);
@@ -1,6 +1,6 @@
-- V10: Add score column for the points/level system. -- V10: Add score column for the points/level system.
-- score: cumulative activity points (default 0). -- score: cumulative activity points (default 0).
-- level is already present; it will be recomputed by ScoreServiceImpl whenever score changes. -- level is recomputed by ScoreServiceImpl whenever score changes.
ALTER TABLE user ADD COLUMN score INTEGER NOT NULL DEFAULT 0; ALTER TABLE user ADD COLUMN score INTEGER NOT NULL DEFAULT 0;
-- Back-fill an initial score for existing users based on their activity counts. -- Back-fill an initial score for existing users based on their activity counts.
@@ -8,9 +8,10 @@ ALTER TABLE user ADD COLUMN score INTEGER NOT NULL DEFAULT 0;
UPDATE user UPDATE user
SET score = COALESCE(discussions_count, 0) * 10 + COALESCE(comments_count, 0) * 5; SET score = COALESCE(discussions_count, 0) * 10 + COALESCE(comments_count, 0) * 5;
-- Recompute level for all users based on back-filled score. -- Recompute level for ALL users based on back-filled score.
-- Thresholds: 0=新手(<50), 1=学徒(50-199), 2=熟手(200-499), -- Thresholds: 0=新手(<50), 1=学徒(50-199), 2=熟手(200-499),
-- 3=达人(500-999), 4=专家(1000-1999), 5=大神(>=2000) -- 3=达人(500-999), 4=专家(1000-1999), 5=大神(>=2000)
-- Note: admin access is now RBAC-based; level is purely cosmetic.
UPDATE user SET level = UPDATE user SET level =
CASE CASE
WHEN score >= 2000 THEN 5 WHEN score >= 2000 THEN 5
@@ -19,5 +20,4 @@ UPDATE user SET level =
WHEN score >= 200 THEN 2 WHEN score >= 200 THEN 2
WHEN score >= 50 THEN 1 WHEN score >= 50 THEN 1
ELSE 0 ELSE 0
END END;
WHERE level = 0 OR level IS NULL;
@@ -9,46 +9,146 @@
<title>${title}</title> <title>${title}</title>
<#include "admin/admin-commjs.ftl"/> <#include "admin/admin-commjs.ftl"/>
<style> <style>
body { background: #f6f7fb; } body { background: #f6f7fb; margin: 0; font-family: 'Lato', 'Helvetica Neue', Arial, sans-serif; }
.admin-header { background: #1f2937; color: #fff; padding: 12px 18px; }
.admin-grid { display: grid; grid-template-columns: 230px 1fr; gap: 16px; padding: 16px; } /* ── Top navigation bar (matches main site style) ── */
.admin-sidebar { background: #fff; border-radius: 8px; padding: 8px; box-shadow: 0 1px 3px rgba(0,0,0,.08); } .admin-topbar {
.admin-main { background: #fff; border-radius: 8px; padding: 16px; box-shadow: 0 1px 3px rgba(0,0,0,.08); } background: #1b1c1d;
.admin-sidebar a.item.active { background: #1d4ed8 !important; color: #fff !important; border-radius: 6px; } color: #fff;
.metric-card { border: 1px solid #e5e7eb; border-radius: 8px; padding: 12px; } padding: 0 20px;
.small-muted { color: #6b7280; font-size: 12px; } height: 50px;
@media (max-width: 900px) { display: flex;
.admin-grid { grid-template-columns: 1fr; } align-items: center;
justify-content: space-between;
box-shadow: 0 2px 4px rgba(0,0,0,.2);
position: sticky;
top: 0;
z-index: 100;
} }
.admin-topbar .brand { font-size: 1.05em; font-weight: 700; display: flex; align-items: center; gap: 8px; }
.admin-topbar .brand img { height: 24px; }
.admin-topbar .nav-right { display: flex; align-items: center; gap: 18px; font-size: .88em; }
.admin-topbar .nav-right a { color: #93c5fd; text-decoration: none; }
.admin-topbar .nav-right a:hover { color: #fff; }
.admin-topbar .nav-right .admin-name { color: #d1d5db; }
/* ── Layout ── */
.admin-layout { display: grid; grid-template-columns: 220px 1fr; min-height: calc(100vh - 50px - 60px); gap: 0; }
@media (max-width: 900px) { .admin-layout { grid-template-columns: 1fr; } }
/* ── Sidebar ── */
.admin-sidebar {
background: #fff;
border-right: 1px solid #e5e7eb;
padding: 12px 8px;
}
.admin-sidebar .section-label {
font-size: .72em; font-weight: 700; color: #9ca3af;
text-transform: uppercase; letter-spacing: .06em;
padding: 8px 12px 4px;
}
.admin-sidebar a.item {
display: flex; align-items: center; gap: 8px;
padding: 9px 14px; border-radius: 7px;
color: #374151; font-size: .91em;
text-decoration: none; margin: 1px 0;
transition: background .15s, color .15s;
}
.admin-sidebar a.item:hover { background: #f3f4f6; color: #111; }
.admin-sidebar a.item.active { background: #1d4ed8; color: #fff; font-weight: 600; }
.admin-sidebar a.item.active:hover { background: #1e40af; }
.admin-sidebar .divider { border-top: 1px solid #e5e7eb; margin: 8px 0; }
/* ── Main content ── */
.admin-main { padding: 24px; }
.admin-main .page-card {
background: #fff; border-radius: 10px;
box-shadow: 0 1px 4px rgba(0,0,0,.07);
padding: 24px;
}
/* ── Footer ── */
.admin-footer {
background: #fff;
border-top: 1px solid #e5e7eb;
padding: 14px 24px;
display: flex;
align-items: center;
justify-content: space-between;
font-size: .82em;
color: #9ca3af;
}
.admin-footer a { color: #6b7280; text-decoration: none; }
.admin-footer a:hover { color: #2185d0; }
</style> </style>
</head> </head>
<body> <body>
<div class="admin-header">
<div class="ui grid"> <div class="admin-topbar">
<div class="ten wide column">Jiscuss 后台管理</div> <div class="brand">
<div class="six wide right aligned column">当前管理员: ${adminName} | <a style="color:#93c5fd" href="/swagger-ui.html" target="_blank">接口文档</a> | <a style="color:#93c5fd" href="/">前台首页</a></div> <img src="/static/assets/images/logo.png" alt="logo">
Jiscuss 后台管理
</div>
<div class="nav-right">
<span class="admin-name"><i class="user circle icon"></i> ${adminName}</span>
<a href="/swagger-ui.html" target="_blank"><i class="book icon"></i> 接口文档</a>
<a href="/"><i class="home icon"></i> 前台首页</a>
</div> </div>
</div> </div>
<div class="admin-grid"> <div class="admin-layout">
<div class="admin-sidebar"> <div class="admin-sidebar">
<div class="ui vertical fluid menu"> <div class="section-label">概览</div>
<a class="item <#if active=='home'>active</#if>" href="/admin/home">总览与运维</a> <a class="item <#if active=='home'>active</#if>" href="/admin/home">
<a class="item <#if active=='users'>active</#if>" href="/admin/users">用户与角色</a> <i class="tachometer alternate icon"></i>总览与运维
<a class="item <#if active=='discussions'>active</#if>" href="/admin/discussions">文章管理</a> </a>
<a class="item <#if active=='posts'>active</#if>" href="/admin/posts">评论管理</a> <div class="divider"></div>
<a class="item <#if active=='upgradeLogs'>active</#if>" href="/admin/upgrade-logs">版本升级日志</a> <div class="section-label">内容管理</div>
<a class="item <#if active=='auditLogs'>active</#if>" href="/admin/audit-logs">操作审计日志</a> <a class="item <#if active=='discussions'>active</#if>" href="/admin/discussions">
<div class="item small-muted">预留扩展</div> <i class="list alternate outline icon"></i>文章管理
<a class="item <#if active=='plugins'>active</#if>" href="/admin/plugins">插件管理(预留)</a> </a>
<a class="item <#if active=='themes'>active</#if>" href="/admin/themes">主题管理(预留)</a> <a class="item <#if active=='posts'>active</#if>" href="/admin/posts">
</div> <i class="comments outline icon"></i>评论管理
</a>
<div class="divider"></div>
<div class="section-label">用户管理</div>
<a class="item <#if active=='users'>active</#if>" href="/admin/users">
<i class="users icon"></i>用户与角色
</a>
<a class="item <#if active=='scores'>active</#if>" href="/admin/scores">
<i class="trophy icon"></i>积分管理
</a>
<div class="divider"></div>
<div class="section-label">系统</div>
<a class="item <#if active=='upgradeLogs'>active</#if>" href="/admin/upgrade-logs">
<i class="history icon"></i>升级日志
</a>
<a class="item <#if active=='auditLogs'>active</#if>" href="/admin/audit-logs">
<i class="shield alternate icon"></i>操作审计
</a>
<div class="divider"></div>
<div class="section-label">预留</div>
<a class="item <#if active=='plugins'>active</#if>" href="/admin/plugins">
<i class="plug icon"></i>插件管理
</a>
<a class="item <#if active=='themes'>active</#if>" href="/admin/themes">
<i class="paint brush icon"></i>主题管理
</a>
</div> </div>
<div class="admin-main"> <div class="admin-main">
<div class="page-card">
<#nested> <#nested>
</div> </div>
</div> </div>
</div>
<div class="admin-footer">
<span>Jiscuss 后台管理系统 &copy; 2019-2026</span>
<span>Powered by <strong>Jiscuss V2.0</strong> &nbsp;|&nbsp; <a href="/">返回前台</a></span>
</div>
</body> </body>
</html> </html>
</#macro> </#macro>
+60 -35
View File
@@ -1,50 +1,75 @@
<#import "admin/admin-shell.ftl" as shell> <#import "admin/admin-shell.ftl" as shell>
<@shell.page title="后台管理 - 总览" active=active adminName=adminName> <@shell.page title="后台管理 - 总览" active=active adminName=adminName>
<h2 class="ui header">系统总览</h2> <h2 class="ui header" style="margin-bottom:1.2em;"><i class="tachometer alternate icon"></i>系统总览</h2>
<div class="ui four stackable cards"> <div class="ui four stackable cards" style="margin-bottom:1.5em;">
<div class="card"><div class="content"><div class="header">用户总数</div><div class="description">${userCount}</div></div></div> <div class="card" style="border-radius:8px; box-shadow:0 1px 4px rgba(0,0,0,.08);">
<div class="card"><div class="content"><div class="header">文章总数</div><div class="description">${discussionCount}</div></div></div>
<div class="card"><div class="content"><div class="header">评论总数</div><div class="description">${postCount}</div></div></div>
<div class="card"><div class="content"><div class="header">角色总数</div><div class="description">${roleCount}</div></div></div>
</div>
<h3 class="ui dividing header">服务器与运行时</h3>
<div class="ui two stackable cards">
<div class="card">
<div class="content"> <div class="content">
<div class="header">CPU / 内存</div> <div class="header" style="font-size:1em; color:#6b7280;">用户总数</div>
<div class="description"> <div class="description" style="font-size:2em; font-weight:700; color:#2185d0;">${userCount}</div>
<p>CPU 负载: ${sys.cpuLoad}</p>
<p>JVM 已用内存: ${sys.usedMb} MB / ${sys.totalMb} MB</p>
<p>JVM 最大内存: ${sys.maxMb} MB</p>
<p>Heap 已用: ${sys.heapUsedMb} MB</p>
<p>应用运行时长: ${sys.uptimeMs} ms</p>
</div> </div>
</div> </div>
</div> <div class="card" style="border-radius:8px; box-shadow:0 1px 4px rgba(0,0,0,.08);">
<div class="card">
<div class="content"> <div class="content">
<div class="header">关键依赖版本</div> <div class="header" style="font-size:1em; color:#6b7280;">文章总数</div>
<div class="description" style="font-size:2em; font-weight:700; color:#21ba45;">${discussionCount}</div>
</div>
</div>
<div class="card" style="border-radius:8px; box-shadow:0 1px 4px rgba(0,0,0,.08);">
<div class="content">
<div class="header" style="font-size:1em; color:#6b7280;">评论总数</div>
<div class="description" style="font-size:2em; font-weight:700; color:#f2711c;">${postCount}</div>
</div>
</div>
<div class="card" style="border-radius:8px; box-shadow:0 1px 4px rgba(0,0,0,.08);">
<div class="content">
<div class="header" style="font-size:1em; color:#6b7280;">角色总数</div>
<div class="description" style="font-size:2em; font-weight:700; color:#a333c8;">${roleCount}</div>
</div>
</div>
</div>
<h3 class="ui dividing header"><i class="server icon"></i>服务器与运行时</h3>
<div class="ui two stackable cards" style="margin-bottom:1.5em;">
<div class="card" style="border-radius:8px; box-shadow:0 1px 4px rgba(0,0,0,.08);">
<div class="content">
<div class="header" style="font-size:1em; color:#374151; margin-bottom:.6em;"><i class="microchip icon"></i>CPU / 内存</div>
<div class="description"> <div class="description">
<p>Spring Boot: ${deps.springBoot}</p> <p><span style="color:#888;">CPU 负载</span>&nbsp;&nbsp;<b>${sys.cpuLoad}</b></p>
<p>Java: ${deps.java}</p> <p><span style="color:#888;">JVM 已用</span>&nbsp;&nbsp;<b>${sys.usedMb} MB</b> / ${sys.totalMb} MB</p>
<p>Spring: ${deps.spring}</p> <p><span style="color:#888;">JVM 最大</span>&nbsp;&nbsp;<b>${sys.maxMb} MB</b></p>
<p>Hibernate: ${deps.hibernate}</p> <p><span style="color:#888;">Heap 已用</span>&nbsp;&nbsp;<b>${sys.heapUsedMb} MB</b></p>
<p>Flyway: ${deps.flyway}</p> <p><span style="color:#888;">运行时长</span>&nbsp;&nbsp;<b>${sys.uptimeMs} ms</b></p>
<p>Druid: ${deps.druid}</p> </div>
<p>Ehcache: ${deps.ehcache}</p> </div>
<p>SpringDoc: ${deps.springdoc}</p> </div>
<div class="card" style="border-radius:8px; box-shadow:0 1px 4px rgba(0,0,0,.08);">
<div class="content">
<div class="header" style="font-size:1em; color:#374151; margin-bottom:.6em;"><i class="code branch icon"></i>关键依赖版本</div>
<div class="description">
<table style="width:100%; border-collapse:collapse; font-size:.9em;">
<tr><td style="color:#888; padding:2px 0;">Spring Boot</td><td><b>${deps.springBoot}</b></td></tr>
<tr><td style="color:#888; padding:2px 0;">Java</td><td><b>${deps.java}</b></td></tr>
<tr><td style="color:#888; padding:2px 0;">Spring</td><td><b>${deps.spring}</b></td></tr>
<tr><td style="color:#888; padding:2px 0;">Hibernate</td><td><b>${deps.hibernate}</b></td></tr>
<tr><td style="color:#888; padding:2px 0;">Flyway</td><td><b>${deps.flyway}</b></td></tr>
<tr><td style="color:#888; padding:2px 0;">Druid</td><td><b>${deps.druid}</b></td></tr>
<tr><td style="color:#888; padding:2px 0;">Ehcache</td><td><b>${deps.ehcache}</b></td></tr>
<tr><td style="color:#888; padding:2px 0;">SpringDoc</td><td><b>${deps.springdoc}</b></td></tr>
</table>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<h3 class="ui dividing header">快捷入口</h3> <h3 class="ui dividing header"><i class="lightning icon"></i>快捷入口</h3>
<div class="ui buttons"> <div style="display:flex; flex-wrap:wrap; gap:10px;">
<a class="ui primary button" href="/admin/users">用户与角色</a> <a class="ui primary button" href="/admin/users"><i class="users icon"></i>用户与角色</a>
<a class="ui button" href="/admin/discussions">文章管理</a> <a class="ui teal button" href="/admin/scores"><i class="trophy icon"></i>积分管理</a>
<a class="ui button" href="/admin/posts">评论管理</a> <a class="ui button" href="/admin/discussions"><i class="list alternate outline icon"></i>文章管理</a>
<a class="ui button" href="/swagger-ui.html" target="_blank">接口文档</a> <a class="ui button" href="/admin/posts"><i class="comments outline icon"></i>评论管理</a>
<a class="ui button" href="/admin/audit-logs"><i class="shield alternate icon"></i>审计日志</a>
<a class="ui button" href="/swagger-ui.html" target="_blank"><i class="book icon"></i>接口文档</a>
</div> </div>
</@shell.page> </@shell.page>
@@ -0,0 +1,75 @@
<#import "admin/admin-shell.ftl" as shell>
<@shell.page title="后台管理 - 积分管理" active=active adminName=adminName>
<div style="display:flex; align-items:center; justify-content:space-between; margin-bottom:1.2em;">
<h2 class="ui header" style="margin:0;"><i class="trophy icon"></i>积分管理</h2>
<span style="color:#888; font-size:.9em;">共 ${users?size} 位用户</span>
</div>
<#assign lvlNames = ["新手","学徒","熟手","达人","专家","大神"]>
<#assign lvlColors = ["#95a5a6","#27ae60","#2980b9","#8e44ad","#e67e22","#e74c3c"]>
<div class="ui segments" style="margin-bottom:1.5em; background:#f8f9ff; border-radius:8px; padding:12px 16px;">
<div style="font-size:.9em; color:#555;">
<b>等级阈值:</b>
<#list 0..5 as i>
<span style="display:inline-block; margin-right:10px;">
<span style="display:inline-block; padding:1px 8px; border-radius:10px;
background:${lvlColors[i]}; color:#fff; font-size:.82em; font-weight:bold;">
Lv.${i} ${lvlNames[i]}
</span>
<span style="color:#888;">
<#if i==0>&lt;50<#elseif i==1>50199<#elseif i==2>200499
<#elseif i==3>500999<#elseif i==4>10001999<#else>≥2000</#if>
</span>
</span>
</#list>
</div>
</div>
<table class="ui celled striped table" style="font-size:.93em;">
<thead>
<tr>
<th style="width:50px;">ID</th>
<th>用户名</th>
<th>真实姓名</th>
<th style="width:90px; text-align:center;">等级</th>
<th style="width:80px; text-align:center;">积分</th>
<th style="width:70px; text-align:center;">发帖</th>
<th style="width:70px; text-align:center;">回复</th>
<th style="width:180px; text-align:center;">手动调整积分</th>
</tr>
</thead>
<tbody>
<#list users as u>
<#assign lvl = (u.level)!0>
<#assign lvlIdx = lvl?int>
<#if lvlIdx < 0><#assign lvlIdx = 0></#if>
<#if lvlIdx > 5><#assign lvlIdx = 5></#if>
<tr>
<td>${u.id}</td>
<td><a href="/profile?uid=${u.id}" target="_blank">${u.username!}</a></td>
<td style="color:#666;">${u.realname!'-'}</td>
<td style="text-align:center;">
<span style="display:inline-block; padding:2px 10px; border-radius:12px;
background:${lvlColors[lvlIdx]}; color:#fff; font-size:.82em; font-weight:bold;">
Lv.${lvl} ${lvlNames[lvlIdx]}
</span>
</td>
<td style="text-align:center; font-weight:bold; color:#2185d0;">${(u.score)!0}</td>
<td style="text-align:center;">${(u.discussionsCount)!0}</td>
<td style="text-align:center;">${(u.commentsCount)!0}</td>
<td style="text-align:center;">
<form method="post" action="/admin/scores/${u.id}/adjust"
style="display:flex; align-items:center; gap:4px; justify-content:center;">
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
<input type="number" name="delta" value="0"
style="width:70px; text-align:center; border:1px solid #ddd; border-radius:4px; padding:3px 6px;"
min="-9999" max="9999">
<button type="submit" class="ui mini primary button" style="margin:0;">确定</button>
</form>
</td>
</tr>
</#list>
</tbody>
</table>
</@shell.page>
+1 -3
View File
@@ -333,9 +333,7 @@
</div> </div>
<div class="meta"> <div class="meta">
<div class=" description "><i class="edit icon"></i> <div class=" description "><i class="edit icon"></i>
<a class="user-card-trigger" data-user-id="${discussions.startUserId!''}" <a class="user-card-trigger" data-user-id="${discussions.startUserId!''}"><b>${discussions.username}</b></a>&nbsp;&nbsp;•&nbsp;&nbsp;
data-tooltip="${discussions.username}"
data-position="top center"><b>${discussions.username}</b></a>&nbsp;&nbsp;•&nbsp;&nbsp;
<i class="reply icon"></i>最后由 <a><b>${discussions.usernameLast}</b></a> <i class="reply icon"></i>最后由 <a><b>${discussions.usernameLast}</b></a>
回复于${discussions.lastTime}. 回复于${discussions.lastTime}.
</div> </div>