feat(system): 实现注册码功能并优化用户注册流程
- 新增注册码生成和验证功能- 实现系统设置管理,包括注册功能开关 - 更新前端界面,增加系统管理和注册码相关功能 - 修改数据库结构,添加系统设置和注册码表
This commit is contained in:
@@ -66,6 +66,7 @@ export const register = (data) => {
|
||||
const formData = new FormData()
|
||||
formData.append('username', data.username)
|
||||
formData.append('password', data.password)
|
||||
formData.append('registrationCode', data.registrationCode)
|
||||
return axiosApi.post('/api/user/register', formData, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
@@ -132,3 +133,20 @@ export const cleanTrash = () => axiosApi.delete('/api/trash/clean');
|
||||
|
||||
// 验证Token
|
||||
export const validateToken = () => axiosApi.post('/api/user/validate-token');
|
||||
|
||||
// System APIs
|
||||
export const getRegistrationStatus = () => {
|
||||
return axiosApi.get('/system/registration/status');
|
||||
};
|
||||
|
||||
export const toggleRegistration = (enabled) => {
|
||||
return axiosApi.post('/system/registration/toggle', enabled, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const generateRegistrationCode = () => {
|
||||
return axiosApi.post('/system/registration/generate-code');
|
||||
};
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
<div v-if="userStore.isLoggedIn" class="user-actions">
|
||||
<span class="welcome-text">欢迎, {{ userStore.userInfo?.username }}</span>
|
||||
<el-button type="danger" @click="handleLogout">退出</el-button>
|
||||
<el-button type="warning" @click="showSystemSettingsDialog = true">系统管理</el-button>
|
||||
<el-button type="primary" @click="showCreateNoteDialog = true">新建笔记</el-button>
|
||||
<el-upload
|
||||
class="upload-btn"
|
||||
@@ -203,6 +204,28 @@
|
||||
<el-button type="primary" @click="handleMoveNote">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 系统管理对话框 -->
|
||||
<el-dialog v-model="showSystemSettingsDialog" title="系统管理" width="500px">
|
||||
<el-form label-width="120px">
|
||||
<el-form-item label="开放注册">
|
||||
<el-switch v-model="isRegistrationEnabled" @change="handleToggleRegistration"></el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item label="生成注册码">
|
||||
<el-button type="primary" @click="handleGenerateCode">生成</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="generatedCode" label="新注册码">
|
||||
<el-input v-model="generatedCode" readonly>
|
||||
<template #append>
|
||||
<el-button @click="copyToClipboard(generatedCode)">复制</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="showSystemSettingsDialog = false">关闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</el-main>
|
||||
</el-container>
|
||||
</el-container>
|
||||
@@ -225,7 +248,10 @@ import {
|
||||
updateMarkdownTitle,
|
||||
deleteGrouping as apiDeleteGrouping,
|
||||
getRecentFiles,
|
||||
validateToken
|
||||
validateToken,
|
||||
getRegistrationStatus,
|
||||
toggleRegistration,
|
||||
generateRegistrationCode
|
||||
} from '@/api/CommonApi.js'
|
||||
import { Plus, Fold, Expand, Folder, Document, Search, Edit, Delete, ArrowDown, Clock } from "@element-plus/icons-vue";
|
||||
import { useUserStore } from '../stores/user';
|
||||
@@ -253,6 +279,9 @@ const fileToImport = ref(null);
|
||||
const showMoveNoteDialog = ref(false);
|
||||
const moveToGroupId = ref(null);
|
||||
const currentGroupName = ref('');
|
||||
const showSystemSettingsDialog = ref(false);
|
||||
const isRegistrationEnabled = ref(true);
|
||||
const generatedCode = ref('');
|
||||
|
||||
const groupFormRef = ref(null);
|
||||
const newGroupForm = ref({ name: '', parentId: null });
|
||||
@@ -921,6 +950,44 @@ watch(activeMenu, (newVal) => {
|
||||
resetToHomeView();
|
||||
}
|
||||
});
|
||||
|
||||
const handleToggleRegistration = async (value) => {
|
||||
try {
|
||||
await toggleRegistration(value);
|
||||
ElMessage.success(`注册功能已${value ? '开启' : '关闭'}`);
|
||||
} catch (error) {
|
||||
ElMessage.error('操作失败');
|
||||
isRegistrationEnabled.value = !value; // revert
|
||||
}
|
||||
};
|
||||
|
||||
const handleGenerateCode = async () => {
|
||||
try {
|
||||
const response = await generateRegistrationCode();
|
||||
generatedCode.value = response.data;
|
||||
ElMessage.success('注册码生成成功');
|
||||
} catch (error) {
|
||||
ElMessage.error('生成注册码失败');
|
||||
}
|
||||
};
|
||||
|
||||
const copyToClipboard = (text) => {
|
||||
navigator.clipboard.writeText(text).then(() => {
|
||||
ElMessage.success('已复制到剪贴板');
|
||||
}, () => {
|
||||
ElMessage.error('复制失败');
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
// ... existing onMounted logic
|
||||
try {
|
||||
const response = await getRegistrationStatus();
|
||||
isRegistrationEnabled.value = response.data;
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch registration status:", error);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<el-form-item>
|
||||
<div class="button-group">
|
||||
<el-button type="primary" @click="handleLogin" class="login-button">安全登录</el-button>
|
||||
<el-button @click="goToRegister" class="register-button">立即注册</el-button>
|
||||
<el-button v-if="isRegistrationEnabled" @click="goToRegister" class="register-button">立即注册</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
@@ -35,15 +35,17 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useUserStore } from '../stores/user';
|
||||
import { getRegistrationStatus } from '../api/CommonApi';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { User, Lock } from '@element-plus/icons-vue';
|
||||
|
||||
const router = useRouter();
|
||||
const userStore = useUserStore();
|
||||
const loginFormRef = ref(null);
|
||||
const isRegistrationEnabled = ref(true);
|
||||
|
||||
const loginForm = ref({
|
||||
username: '',
|
||||
@@ -75,6 +77,17 @@ const goToRegister = () => {
|
||||
const goToHome = () => {
|
||||
router.push('/home');
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
const response = await getRegistrationStatus();
|
||||
isRegistrationEnabled.value = response.data;
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch registration status:", error);
|
||||
// 保守起见,如果获取失败则禁用注册按钮
|
||||
isRegistrationEnabled.value = false;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -27,6 +27,13 @@
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="注册码" prop="registrationCode">
|
||||
<el-input v-model="registerForm.registrationCode" placeholder="请输入注册码" size="large">
|
||||
<template #prefix>
|
||||
<el-icon><Key /></el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<div class="button-group">
|
||||
<el-button type="primary" @click="handleRegister" class="register-button">立即注册</el-button>
|
||||
@@ -46,7 +53,7 @@ import { ref } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { register } from '../api/CommonApi';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { User, Lock, CircleCheck } from '@element-plus/icons-vue';
|
||||
import { User, Lock, CircleCheck, Key } from '@element-plus/icons-vue';
|
||||
|
||||
const router = useRouter();
|
||||
const registerFormRef = ref(null);
|
||||
@@ -55,6 +62,7 @@ const registerForm = ref({
|
||||
username: '',
|
||||
password: '',
|
||||
confirmPassword: '',
|
||||
registrationCode: '',
|
||||
});
|
||||
|
||||
const validatePass = (rule, value, callback) => {
|
||||
@@ -71,17 +79,18 @@ const registerRules = {
|
||||
username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
|
||||
password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
|
||||
confirmPassword: [{ validator: validatePass, trigger: 'blur' }],
|
||||
registrationCode: [{ required: true, message: '请输入注册码', trigger: 'blur' }],
|
||||
};
|
||||
|
||||
const handleRegister = async () => {
|
||||
const valid = await registerFormRef.value.validate();
|
||||
if (valid) {
|
||||
try {
|
||||
await register({ username: registerForm.value.username, password: registerForm.value.password });
|
||||
await register(registerForm.value);
|
||||
ElMessage.success('注册成功');
|
||||
router.push('/login');
|
||||
} catch (error) {
|
||||
ElMessage.error('注册失败,请稍后再试');
|
||||
ElMessage.error(error.response?.data?.msg || '注册失败,请稍后再试');
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -224,4 +233,4 @@ const goToHome = () => {
|
||||
:deep(.el-link:hover) {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user