Skip to content

Commit 36bf5fd

Browse files
committed
Merge PR #18: overhaul registration flow with questionnaire enforcement, LLM scoring, bug fixes (v1.2.8)
2 parents 127e2fc + 55e55dd commit 36bf5fd

29 files changed

Lines changed: 2115 additions & 892 deletions

README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,30 @@
6666
2. Start the server to auto-generate config files, then edit `config.yml` as needed (see full example below).
6767
3. Restart the server and visit `http://your_server_ip:8080` to access the admin panel.
6868

69+
### ✅ Recommended Minimum Environment
70+
71+
- Java 17+
72+
- Bukkit/Spigot/Paper/Folia 1.20+
73+
- A public domain with HTTPS enabled (recommended for production)
74+
- SMTP mailbox account (required when using `email` verification)
75+
76+
### ⚡ 5-Minute Quick Start
77+
78+
1. Set `auth_methods: [captcha]` in `config.yml` (fastest setup, no SMTP required).
79+
2. Set `whitelist_mode: plugin` and `web_register_url: https://your-domain.com/`.
80+
3. Configure `admin.password` to a strong password.
81+
4. (Optional) Enable `register.auto_approve: true` for small private servers.
82+
5. Restart the server and open `http://your_server_ip:8080`.
83+
84+
### 🧪 Build from Source
85+
86+
```bash
87+
cd plugin
88+
mvn clean package
89+
```
90+
91+
Output jar: `plugin/target/verifymc-<version>.jar`
92+
6993
```yaml
7094
# ----------------------------------------
7195
# General Settings
@@ -269,6 +293,8 @@ questionnaire:
269293
pass_score: 60
270294
# Auto-approve users who pass the questionnaire
271295
auto_approve_on_pass: false
296+
# Whether users must pass questionnaire before registration is allowed
297+
require_pass_before_register: false
272298

273299
# ----------------------------------------
274300
# Discord Integration (OAuth2)

README_zh.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,30 @@
7272
2. 启动服务器自动生成配置文件,按需编辑 `config.yml`(见下方完整示例)。
7373
3. 重启服务器,访问 `http://你的服务器IP:8080` 进入管理后台。
7474

75+
### ✅ 建议最低环境
76+
77+
- Java 17+
78+
- Bukkit/Spigot/Paper/Folia 1.20+
79+
- 可公网访问并启用 HTTPS 的域名(生产环境强烈建议)
80+
- SMTP 邮箱账号(当使用 `email` 验证方式时必需)
81+
82+
### ⚡ 5 分钟快速开始
83+
84+
1.`config.yml` 中设置 `auth_methods: [captcha]`(最快启动方式,无需 SMTP)。
85+
2. 设置 `whitelist_mode: plugin``web_register_url: https://your-domain.com/`
86+
3.`admin.password` 修改为强密码。
87+
4. (可选)小型私服可开启 `register.auto_approve: true`
88+
5. 重启服务器并访问 `http://你的服务器IP:8080`
89+
90+
### 🧪 从源码构建
91+
92+
```bash
93+
cd plugin
94+
mvn clean package
95+
```
96+
97+
产物 jar:`plugin/target/verifymc-<version>.jar`
98+
7599
```yaml
76100
# ----------------------------------------
77101
# 全局设置

frontend/glassx/src/components/AdminReviewPanel.vue

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343
<th class="px-6 py-3 text-left text-xs font-medium text-gray-400 uppercase tracking-wider">{{ $t('admin.review.table.username') }}</th>
4444
<th class="px-6 py-3 text-left text-xs font-medium text-gray-400 uppercase tracking-wider">{{ $t('admin.review.table.email') }}</th>
4545
<th class="px-6 py-3 text-left text-xs font-medium text-gray-400 uppercase tracking-wider">{{ $t('admin.review.table.register_time') }}</th>
46+
<th class="px-6 py-3 text-left text-xs font-medium text-gray-400 uppercase tracking-wider">{{ $t('admin.review.table.questionnaire_score') }}</th>
47+
<th class="px-6 py-3 text-left text-xs font-medium text-gray-400 uppercase tracking-wider">{{ $t('admin.review.table.questionnaire_reason') }}</th>
4648
<th class="px-6 py-3 text-right text-xs font-medium text-gray-400 uppercase tracking-wider">{{ $t('admin.review.table.actions') }}</th>
4749
</tr>
4850
</thead>
@@ -63,7 +65,17 @@
6365
</td>
6466
<td class="px-6 py-4 whitespace-nowrap">
6567
<div class="text-sm text-gray-300">
66-
{{ formatDate(user.registerTime) }}
68+
{{ formatDate(user.regTime || user.registerTime) }}
69+
</div>
70+
</td>
71+
<td class="px-6 py-4 whitespace-nowrap">
72+
<div class="text-sm text-gray-300">
73+
{{ user.questionnaire_score ?? '-' }}
74+
</div>
75+
</td>
76+
<td class="px-6 py-4">
77+
<div class="text-sm text-gray-300 max-w-[360px] break-words">
78+
{{ user.questionnaire_review_summary || '-' }}
6779
</div>
6880
</td>
6981
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
@@ -168,7 +180,8 @@ const rejectModal = ref({
168180
processing: false
169181
})
170182
171-
const formatDate = (dateString: string) => {
183+
const formatDate = (dateString?: string | number | null) => {
184+
if (!dateString) return "-"
172185
return new Date(dateString).toLocaleString()
173186
}
174187

frontend/glassx/src/components/AnimatedMenuBar.vue

Lines changed: 46 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -81,36 +81,51 @@ const route = useRoute()
8181
const hoveredIndex = ref<number | null>(null)
8282
const isNavHovered = ref(false)
8383
84-
const menuItems = computed(() => [
85-
{
86-
icon: Home,
87-
label: t('nav.home'),
88-
href: '/',
89-
gradient: 'radial-gradient(circle, rgba(59,130,246,0.15) 0%, rgba(37,99,235,0.06) 50%, rgba(29,78,216,0) 100%)',
90-
iconColor: 'text-blue-500',
91-
},
92-
{
93-
icon: UserPlus,
94-
label: t('nav.register'),
95-
href: '/register',
96-
gradient: 'radial-gradient(circle, rgba(249,115,22,0.15) 0%, rgba(234,88,12,0.06) 50%, rgba(194,65,12,0) 100%)',
97-
iconColor: 'text-orange-500',
98-
},
99-
{
100-
icon: LogIn,
101-
label: t('nav.login'),
102-
href: '/login',
103-
gradient: 'radial-gradient(circle, rgba(34,197,94,0.15) 0%, rgba(22,163,74,0.06) 50%, rgba(21,128,61,0) 100%)',
104-
iconColor: 'text-green-500',
105-
},
106-
{
107-
icon: Settings,
108-
label: t('nav.admin'),
109-
href: '/admin',
110-
gradient: 'radial-gradient(circle, rgba(239,68,68,0.15) 0%, rgba(220,38,38,0.06) 50%, rgba(185,28,28,0) 100%)',
111-
iconColor: 'text-red-500',
112-
},
113-
])
84+
const isAdminLoggedIn = computed(() => {
85+
// 绑定路由,确保登录/跳转后菜单可及时响应
86+
route.fullPath
87+
return !!localStorage.getItem('admin_token')
88+
})
89+
90+
const menuItems = computed(() => {
91+
const items = [
92+
{
93+
icon: Home,
94+
label: t('nav.home'),
95+
href: '/',
96+
gradient: 'radial-gradient(circle, rgba(59,130,246,0.15) 0%, rgba(37,99,235,0.06) 50%, rgba(29,78,216,0) 100%)',
97+
iconColor: 'text-blue-500',
98+
},
99+
]
100+
101+
if (isAdminLoggedIn.value) {
102+
items.push({
103+
icon: Settings,
104+
label: t('nav.admin'),
105+
href: '/admin',
106+
gradient: 'radial-gradient(circle, rgba(239,68,68,0.15) 0%, rgba(220,38,38,0.06) 50%, rgba(185,28,28,0) 100%)',
107+
iconColor: 'text-red-500',
108+
})
109+
} else {
110+
items.push({
111+
icon: UserPlus,
112+
label: t('nav.register'),
113+
href: '/register',
114+
gradient: 'radial-gradient(circle, rgba(249,115,22,0.15) 0%, rgba(234,88,12,0.06) 50%, rgba(194,65,12,0) 100%)',
115+
iconColor: 'text-orange-500',
116+
})
117+
118+
items.push({
119+
icon: LogIn,
120+
label: t('nav.login'),
121+
href: '/login',
122+
gradient: 'radial-gradient(circle, rgba(34,197,94,0.15) 0%, rgba(22,163,74,0.06) 50%, rgba(21,128,61,0) 100%)',
123+
iconColor: 'text-green-500',
124+
})
125+
}
126+
127+
return items
128+
})
114129
115130
const isActive = (href: string) => {
116131
if (href === '/') {
@@ -321,4 +336,4 @@ const isActive = (href: string) => {
321336
display: none !important;
322337
}
323338
}
324-
</style>
339+
</style>

frontend/glassx/src/components/HeroGeometric.vue

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
<!-- Action buttons -->
6060
<div class="fade-up-item" style="--delay: 0.6s">
6161
<div class="flex flex-col sm:flex-row gap-4 justify-center items-center">
62-
<router-link to="/register" class="register-button group">
62+
<router-link v-if="!isAdminLoggedIn" to="/register" class="register-button group">
6363
<span class="button-glow"></span>
6464
<span class="button-content">
6565
<svg class="w-5 h-5 transition-transform duration-300 group-hover:scale-110" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@@ -71,15 +71,15 @@
7171
<span class="button-shine"></span>
7272
</router-link>
7373

74-
<router-link to="/admin" class="glass-button group">
74+
<router-link :to="secondaryAction.href" class="glass-button group">
7575
<svg class="w-5 h-5 transition-transform duration-300 group-hover:rotate-90" fill="none" stroke="currentColor" viewBox="0 0 24 24">
7676
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
7777
d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z">
7878
</path>
7979
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
8080
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
8181
</svg>
82-
<span>{{ $t('nav.admin') }}</span>
82+
<span>{{ secondaryAction.label }}</span>
8383
</router-link>
8484
</div>
8585
</div>
@@ -94,8 +94,10 @@
9494
<script setup lang="ts">
9595
import { inject, computed, watch } from 'vue'
9696
import { useI18n } from 'vue-i18n'
97+
import { useRoute } from 'vue-router'
9798
9899
const { t } = useI18n()
100+
const route = useRoute()
99101
const config = inject('config', { value: {} as any })
100102
101103
interface Props {
@@ -124,6 +126,25 @@ const announcement = computed(() => {
124126
return config.value?.frontend?.announcement || ''
125127
})
126128
129+
const isAdminLoggedIn = computed(() => {
130+
route.fullPath
131+
return !!localStorage.getItem('admin_token')
132+
})
133+
134+
const secondaryAction = computed(() => {
135+
if (isAdminLoggedIn.value) {
136+
return {
137+
href: '/admin',
138+
label: t('nav.admin')
139+
}
140+
}
141+
142+
return {
143+
href: '/login',
144+
label: t('nav.login')
145+
}
146+
})
147+
127148
// 监听配置变化
128149
watch(() => config.value?.frontend?.web_server_prefix, (newPrefix) => {
129150
if (newPrefix) {
@@ -374,4 +395,4 @@ watch(() => config.value?.frontend?.web_server_prefix, (newPrefix) => {
374395
min-height: -webkit-fill-available;
375396
}
376397
}
377-
</style>
398+
</style>

0 commit comments

Comments
 (0)