166 lines
5.4 KiB
JavaScript
166 lines
5.4 KiB
JavaScript
const { createApp, ref, provide, onMounted, onUnmounted } = Vue;
|
|
|
|
const app = createApp({
|
|
setup() {
|
|
const api = useApi();
|
|
const currentPage = ref('log');
|
|
const authReady = ref(false);
|
|
const authenticated = ref(false);
|
|
const authUser = ref('');
|
|
const loginLoading = ref(false);
|
|
const loginForm = ref({
|
|
username: '',
|
|
password: '',
|
|
});
|
|
|
|
provide('currentPage', currentPage);
|
|
|
|
async function refreshAuthState() {
|
|
const json = await api.getAuthStatus();
|
|
if (json) {
|
|
authenticated.value = !!json.authenticated;
|
|
authUser.value = json.username || '';
|
|
if (json.username && !loginForm.value.username) {
|
|
loginForm.value.username = json.username;
|
|
}
|
|
} else {
|
|
authenticated.value = false;
|
|
authUser.value = '';
|
|
}
|
|
authReady.value = true;
|
|
}
|
|
|
|
async function login() {
|
|
const username = (loginForm.value.username || '').trim();
|
|
const password = loginForm.value.password || '';
|
|
if (!username) {
|
|
ElementPlus.ElMessage.warning('请输入账号');
|
|
return;
|
|
}
|
|
if (!password) {
|
|
ElementPlus.ElMessage.warning('请输入密码');
|
|
return;
|
|
}
|
|
|
|
loginLoading.value = true;
|
|
const json = await api.login(username, password);
|
|
loginLoading.value = false;
|
|
if (!json) return;
|
|
|
|
authenticated.value = true;
|
|
authUser.value = json.username || username;
|
|
loginForm.value.password = '';
|
|
currentPage.value = 'log';
|
|
ElementPlus.ElMessage.success('登录成功');
|
|
}
|
|
|
|
async function logout() {
|
|
await api.logout();
|
|
authenticated.value = false;
|
|
loginForm.value.password = '';
|
|
currentPage.value = 'log';
|
|
}
|
|
|
|
function handleAuthExpired() {
|
|
const wasAuthenticated = authenticated.value;
|
|
authenticated.value = false;
|
|
loginForm.value.password = '';
|
|
currentPage.value = 'log';
|
|
if (wasAuthenticated) {
|
|
ElementPlus.ElMessage.warning('登录状态已失效,请重新登录');
|
|
}
|
|
}
|
|
|
|
function handleAuthUpdated(event) {
|
|
const username = event?.detail?.username;
|
|
if (username) {
|
|
authUser.value = username;
|
|
}
|
|
}
|
|
|
|
function handleLayoutAuthUpdated(username) {
|
|
if (username) {
|
|
authUser.value = username;
|
|
}
|
|
}
|
|
|
|
onMounted(() => {
|
|
window.addEventListener('webui-auth-required', handleAuthExpired);
|
|
window.addEventListener('webui-auth-updated', handleAuthUpdated);
|
|
refreshAuthState();
|
|
});
|
|
|
|
onUnmounted(() => {
|
|
window.removeEventListener('webui-auth-required', handleAuthExpired);
|
|
window.removeEventListener('webui-auth-updated', handleAuthUpdated);
|
|
});
|
|
|
|
return {
|
|
authReady,
|
|
authenticated,
|
|
authUser,
|
|
loginLoading,
|
|
loginForm,
|
|
login,
|
|
logout,
|
|
handleLayoutAuthUpdated,
|
|
};
|
|
},
|
|
template: `
|
|
<div v-if="authReady" class="app-root">
|
|
<div v-if="!authenticated"
|
|
class="login-page">
|
|
<el-card class="login-card">
|
|
<template #header>
|
|
<div class="login-title">WechatHookBot 控制台</div>
|
|
<div class="login-subtitle">Bright Tech UI · 安全登录</div>
|
|
</template>
|
|
<el-form label-position="top">
|
|
<el-form-item label="账号">
|
|
<el-input
|
|
v-model="loginForm.username"
|
|
autocomplete="username"
|
|
placeholder="请输入账号" />
|
|
</el-form-item>
|
|
<el-form-item label="密码">
|
|
<el-input
|
|
v-model="loginForm.password"
|
|
show-password
|
|
autocomplete="current-password"
|
|
placeholder="请输入密码"
|
|
@keyup.enter="login" />
|
|
</el-form-item>
|
|
<el-button type="primary" :loading="loginLoading" style="width:100%" @click="login">
|
|
登录
|
|
</el-button>
|
|
</el-form>
|
|
</el-card>
|
|
</div>
|
|
|
|
<AppLayout
|
|
v-else
|
|
:auth-user="authUser"
|
|
@logout="logout"
|
|
@auth-updated="handleLayoutAuthUpdated" />
|
|
</div>
|
|
`
|
|
});
|
|
|
|
app.use(ElementPlus, {
|
|
locale: ElementPlusLocaleZhCn,
|
|
});
|
|
|
|
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
|
app.component(key, component);
|
|
}
|
|
|
|
app.component('AppLayout', window.AppLayout);
|
|
app.component('LogViewer', window.LogViewer);
|
|
app.component('ConfigEditor', window.ConfigEditor);
|
|
app.component('ConfigSection', window.ConfigSection);
|
|
app.component('PluginList', window.PluginList);
|
|
app.component('PluginConfigDialog', window.PluginConfigDialog);
|
|
app.component('SecuritySettings', window.SecuritySettings);
|
|
|
|
app.mount('#app');
|