feat: 实现首次登录功能,添加用户名和密码输入,更新状态管理
This commit is contained in:
@@ -1,22 +1,20 @@
|
|||||||
import { useEffect } from "react";
|
import { use, useEffect, useState } from "react";
|
||||||
import { Layout } from "./layout"
|
import { Layout } from "./layout"
|
||||||
import { useStore } from "./store";
|
import { useStore } from "./store";
|
||||||
export const FirstLogin = () => {
|
export const FirstLogin = () => {
|
||||||
const store = useStore();
|
const store = useStore();
|
||||||
|
const [username, setUsername] = useState('')
|
||||||
|
const [password, setPassword] = useState('')
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
store.initAdmin();
|
store.initAdmin();
|
||||||
}, []);
|
}, []);
|
||||||
const onClickLogin = async () => {
|
useEffect(() => {
|
||||||
const accountInput = document.getElementById('account') as HTMLInputElement;
|
if (store.username) {
|
||||||
const passwordInput = document.getElementById('password') as HTMLInputElement;
|
setUsername(store.username);
|
||||||
const username = accountInput.value;
|
|
||||||
const password = passwordInput.value;
|
|
||||||
const res = await store.login(username, password);
|
|
||||||
if (res.code === 200) {
|
|
||||||
window.location.reload();
|
|
||||||
} else {
|
|
||||||
alert(res.message || '登录失败');
|
|
||||||
}
|
}
|
||||||
|
}, [store.username]);
|
||||||
|
const onClickLogin = async () => {
|
||||||
|
await store.login(username, password);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<Layout>
|
||||||
@@ -27,12 +25,14 @@ export const FirstLogin = () => {
|
|||||||
第一次登录的<a className="text-gray-700 mx-1" href="https://kevisual.cn">kevisual</a> 用户为当前设备管理员。如果已经存在管理员账号,管理员可在"全局设置"中设置。
|
第一次登录的<a className="text-gray-700 mx-1" href="https://kevisual.cn">kevisual</a> 用户为当前设备管理员。如果已经存在管理员账号,管理员可在"全局设置"中设置。
|
||||||
<a className="text-gray-700 mx-1 underline" href="../docs/01-login-first/">文档</a>
|
<a className="text-gray-700 mx-1 underline" href="../docs/01-login-first/">文档</a>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
<div className='space-y-4 mt-8'>
|
<form className='space-y-4 mt-8'>
|
||||||
<div>
|
<div>
|
||||||
<label htmlFor='account' className='block text-sm font-medium text-gray-900 mb-2'> 账号 </label>
|
<label htmlFor='account' className='block text-sm font-medium text-gray-900 mb-2'> 账号 </label>
|
||||||
<input
|
<input
|
||||||
type='text'
|
type='text'
|
||||||
id='account'
|
id='account'
|
||||||
|
onChange={e => setUsername(e.target.value)}
|
||||||
|
value={username}
|
||||||
placeholder='请输入账号'
|
placeholder='请输入账号'
|
||||||
className='w-full px-4 py-2 border-2 border-black bg-white text-black placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-black focus:border-transparent'
|
className='w-full px-4 py-2 border-2 border-black bg-white text-black placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-black focus:border-transparent'
|
||||||
/>
|
/>
|
||||||
@@ -42,6 +42,8 @@ export const FirstLogin = () => {
|
|||||||
<input
|
<input
|
||||||
type='password'
|
type='password'
|
||||||
id='password'
|
id='password'
|
||||||
|
onChange={e => setPassword(e.target.value)}
|
||||||
|
value={password}
|
||||||
placeholder='请输入密码'
|
placeholder='请输入密码'
|
||||||
className='w-full px-4 py-2 border-2 border-black bg-white text-black placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-black focus:border-transparent'
|
className='w-full px-4 py-2 border-2 border-black bg-white text-black placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-black focus:border-transparent'
|
||||||
/>
|
/>
|
||||||
@@ -52,9 +54,25 @@ export const FirstLogin = () => {
|
|||||||
className='w-full px-4 py-2 bg-black text-white font-medium hover:bg-gray-800 active:bg-gray-900 transition-colors focus:outline-none focus:ring-2 focus:ring-black focus:ring-offset-2'>
|
className='w-full px-4 py-2 bg-black text-white font-medium hover:bg-gray-800 active:bg-gray-900 transition-colors focus:outline-none focus:ring-2 focus:ring-black focus:ring-offset-2'>
|
||||||
确定
|
确定
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Layout>
|
</Layout>
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Config = () => {
|
||||||
|
const store = useStore();
|
||||||
|
useEffect(() => {
|
||||||
|
store.initAdmin();
|
||||||
|
}, []);
|
||||||
|
return (
|
||||||
|
<Layout>
|
||||||
|
<div className="p-4">
|
||||||
|
<pre className="bg-gray-100 p-4 rounded-lg overflow-x-auto">
|
||||||
|
{JSON.stringify(store.config, null, 2)}
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
</Layout>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
@@ -1,31 +1,42 @@
|
|||||||
import { query } from '@/modules/query';
|
import { query, queryLogin } from '@/modules/query';
|
||||||
import { create } from 'zustand';
|
import { create } from 'zustand';
|
||||||
|
|
||||||
type SettingState = {
|
type SettingState = {
|
||||||
username?: string;
|
username?: string;
|
||||||
initAdmin: () => any;
|
initAdmin: () => any;
|
||||||
login: (username: string, password: string) => any;
|
login: (username: string, password: string) => any;
|
||||||
|
config?: any;
|
||||||
}
|
}
|
||||||
export const useStore = create<SettingState>((set => ({
|
export const useStore = create<SettingState>((set => ({
|
||||||
username: undefined,
|
username: undefined,
|
||||||
|
config: undefined,
|
||||||
initAdmin: async () => {
|
initAdmin: async () => {
|
||||||
const res = await query.post({
|
const res = await query.post({
|
||||||
path: 'config'
|
path: 'config'
|
||||||
})
|
})
|
||||||
console.log('initAdmin', res);
|
console.log('initAdmin', res);
|
||||||
|
if (res.code === 200) {
|
||||||
|
const auth = res.data.auth || {}
|
||||||
|
if (auth.username) {
|
||||||
|
set({ username: auth.username });
|
||||||
|
}
|
||||||
|
set({ config: res.data });
|
||||||
|
}
|
||||||
},
|
},
|
||||||
login: async (username: string, password: string) => {
|
login: async (username: string, password: string) => {
|
||||||
const res = await query.post({
|
const res = await query.post({
|
||||||
path: 'admin',
|
path: 'admin',
|
||||||
key: 'login',
|
key: 'login',
|
||||||
data: {
|
username,
|
||||||
username,
|
password
|
||||||
password
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
set({ username });
|
set({ username });
|
||||||
|
const setToken = await queryLogin.setLoginToken(res.data)
|
||||||
|
console.log('setToken', setToken);
|
||||||
}
|
}
|
||||||
|
console.log('login res', res);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
})));
|
})));
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Query } from '@kevisual/query'
|
import { QueryClient, Query } from '@kevisual/query'
|
||||||
|
import { QueryLoginBrowser } from '@kevisual/query-login'
|
||||||
const getUrl = () => {
|
const getUrl = () => {
|
||||||
const host = window.location.host
|
const host = window.location.host
|
||||||
const isKevisual = host.includes('kevisual');
|
const isKevisual = host.includes('kevisual');
|
||||||
@@ -10,6 +10,14 @@ const getUrl = () => {
|
|||||||
return '/client/router'
|
return '/client/router'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const query = new Query({
|
export const query = new QueryClient({
|
||||||
url: getUrl()
|
url: getUrl()
|
||||||
|
});
|
||||||
|
|
||||||
|
export const remoteQuery = new Query({
|
||||||
|
url: '/api/router'
|
||||||
|
});
|
||||||
|
|
||||||
|
export const queryLogin = new QueryLoginBrowser({
|
||||||
|
query: remoteQuery
|
||||||
});
|
});
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
---
|
---
|
||||||
import Html from '@/components/html.astro';
|
import Html from '@/components/html.astro';
|
||||||
import { FirstLogin } from '@/apps/setting/index.tsx';
|
import { Config } from '@/apps/setting/index.tsx';
|
||||||
---
|
---
|
||||||
|
|
||||||
<Html>
|
<Html>
|
||||||
<FirstLogin client:only />
|
<Config client:only />
|
||||||
</Html>
|
</Html>
|
||||||
|
|||||||
Reference in New Issue
Block a user