mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-06-07 22:36:02 +00:00
feat: 用户账户系统
This commit is contained in:
88
web/src/components/InitDialog.vue
Normal file
88
web/src/components/InitDialog.vue
Normal file
@@ -0,0 +1,88 @@
|
||||
<template>
|
||||
<v-dialog v-model="dialog" width="500" persistent>
|
||||
<v-card id="init-dialog">
|
||||
<v-card-title class="d-flex align-center" style="gap: 0.5rem;">
|
||||
<img src="@/assets/langbot-logo.png" height="32" width="32" />
|
||||
<span>系统初始化</span>
|
||||
</v-card-title>
|
||||
|
||||
<v-card-text>
|
||||
<p>请输入初始管理员邮箱和密码。</p>
|
||||
</v-card-text>
|
||||
|
||||
<v-card-text class="d-flex flex-column" style="gap: 0.5rem;">
|
||||
<v-text-field v-model="user" variant="outlined" label="管理员邮箱" :rules="[rules.required, rules.email]"
|
||||
clearable />
|
||||
<v-text-field v-model="password" variant="outlined" label="管理员密码" :rules="[rules.required]"
|
||||
type="password" clearable />
|
||||
</v-card-text>
|
||||
|
||||
<v-card-actions>
|
||||
<v-btn color="primary" variant="flat" @click="initialize" prepend-icon="mdi-check">初始化</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, inject, getCurrentInstance } from 'vue'
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
const emit = defineEmits(['error', 'success', 'checkSystemInitialized'])
|
||||
|
||||
const dialog = ref(true)
|
||||
|
||||
const user = ref('')
|
||||
const password = ref('')
|
||||
|
||||
const snackbar = inject('snackbar')
|
||||
|
||||
const rules = {
|
||||
required: value => !!value || '必填项',
|
||||
email: value => {
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
|
||||
return emailRegex.test(value) || '请输入有效的邮箱地址'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function checkEmailValid(email) {
|
||||
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
|
||||
return regex.test(email)
|
||||
}
|
||||
|
||||
const initialize = () => {
|
||||
// 检查邮箱和密码是否为空
|
||||
if (user.value == undefined || password.value == undefined) {
|
||||
emit('error', '邮箱和密码不能为空')
|
||||
return
|
||||
}
|
||||
|
||||
if (user.value == '' || password.value == '') {
|
||||
emit('error', '邮箱和密码不能为空')
|
||||
return
|
||||
}
|
||||
|
||||
if (!checkEmailValid(user.value)) {
|
||||
emit('error', '请输入有效的邮箱地址')
|
||||
return
|
||||
}
|
||||
|
||||
proxy.$axios.post('/user/init', {
|
||||
user: user.value,
|
||||
password: password.value
|
||||
}).then(res => {
|
||||
emit('success', '系统初始化成功')
|
||||
|
||||
emit('checkSystemInitialized')
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
#init-dialog {
|
||||
padding-top: 0.8rem;
|
||||
padding-inline: 0.5rem;
|
||||
}
|
||||
</style>
|
||||
72
web/src/components/LoginDialog.vue
Normal file
72
web/src/components/LoginDialog.vue
Normal file
@@ -0,0 +1,72 @@
|
||||
<template>
|
||||
<v-dialog v-model="dialog" width="350" persistent>
|
||||
<v-card id="login-dialog">
|
||||
<v-card-title class="d-flex align-center" style="gap: 0.5rem;">
|
||||
<img src="@/assets/langbot-logo.png" height="32" width="32" />
|
||||
<span>登录 LangBot</span>
|
||||
</v-card-title>
|
||||
|
||||
<v-card-text class="d-flex flex-column" style="gap: 0.5rem;margin-bottom: -2rem;margin-top: 1rem;">
|
||||
|
||||
<v-text-field v-model="user" variant="outlined" label="邮箱" :rules="[rules.required, rules.email]"
|
||||
clearable />
|
||||
<v-text-field v-model="password" variant="outlined" label="密码" :rules="[rules.required]"
|
||||
type="password" clearable />
|
||||
</v-card-text>
|
||||
|
||||
<v-card-actions>
|
||||
<v-btn color="primary" variant="flat" @click="login">登录</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, getCurrentInstance } from 'vue'
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
const emit = defineEmits(['error', 'success', 'checkToken'])
|
||||
|
||||
const dialog = ref(true)
|
||||
|
||||
const user = ref('')
|
||||
const password = ref('')
|
||||
|
||||
const rules = {
|
||||
required: value => !!value || '必填项',
|
||||
email: value => {
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
|
||||
return emailRegex.test(value) || '请输入有效的邮箱地址'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const login = () => {
|
||||
proxy.$axios.post('/user/auth', {
|
||||
user: user.value,
|
||||
password: password.value
|
||||
}).then(res => {
|
||||
if (res.data.data.token) {
|
||||
emit('success', '登录成功')
|
||||
localStorage.setItem('user-token', res.data.data.token)
|
||||
setTimeout(() => {
|
||||
location.reload()
|
||||
}, 1000)
|
||||
} else {
|
||||
emit('error', '登录失败')
|
||||
}
|
||||
}).catch(err => {
|
||||
emit('error', err.response.data.message)
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
#login-dialog {
|
||||
padding-top: 0.8rem;
|
||||
padding-bottom: 0.5rem;
|
||||
padding-inline: 0.5rem;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user