ui: login & register

This commit is contained in:
CrescentLeaf
2025-09-08 03:09:05 +08:00
parent 0e14bb9a45
commit 3a7e4970d4
3 changed files with 127 additions and 40 deletions

View File

@@ -9,11 +9,11 @@ import User from "../api/client_data/User.ts"
import RecentChat from "../api/client_data/RecentChat.ts" import RecentChat from "../api/client_data/RecentChat.ts"
import * as React from 'react' import * as React from 'react'
import * as CryptoES from 'crypto-es'
import { Button, Dialog, NavigationRail, TextField } from "mdui" import { Button, Dialog, NavigationRail, TextField } from "mdui"
import Split from 'split.js' import Split from 'split.js'
import 'mdui/jsx.zh-cn.d.ts' import 'mdui/jsx.zh-cn.d.ts'
import { checkApiSuccessOrSncakbar } from "./snackbar.ts"; import { checkApiSuccessOrSncakbar } from "./snackbar.ts";
import RegisterDialog from "./dialog/RegisterDialog.tsx";
declare global { declare global {
namespace React { namespace React {
@@ -27,7 +27,7 @@ declare global {
export default function App() { export default function App() {
const [recentsList, setRecentsList] = React.useState([ const [recentsList, setRecentsList] = React.useState([
{ {
id: '0', id: '0',
avatar: "https://www.court-records.net/mugshot/aa6-004-maya.png", avatar: "https://www.court-records.net/mugshot/aa6-004-maya.png",
title: "麻油衣酱", title: "麻油衣酱",
@@ -38,11 +38,11 @@ export default function App() {
avatar: "https://www.court-records.net/mugshot/aa6-004-maya.png", avatar: "https://www.court-records.net/mugshot/aa6-004-maya.png",
title: "Maya Fey", title: "Maya Fey",
content: "我是绫里真宵, 是一名灵媒师~" content: "我是绫里真宵, 是一名灵媒师~"
}, },
] as RecentChat[]) ] as RecentChat[])
const [contactsMap, setContactsMap] = React.useState({ const [contactsMap, setContactsMap] = React.useState({
: [ : [
{ {
id: '0', id: '0',
avatar: "https://www.court-records.net/mugshot/aa6-004-maya.png", avatar: "https://www.court-records.net/mugshot/aa6-004-maya.png",
nickname: "麻油衣酱", nickname: "麻油衣酱",
@@ -51,7 +51,7 @@ export default function App() {
id: '0', id: '0',
avatar: "https://www.court-records.net/mugshot/aa6-004-maya.png", avatar: "https://www.court-records.net/mugshot/aa6-004-maya.png",
nickname: "Maya Fey", nickname: "Maya Fey",
}, },
], ],
} as unknown as { [key: string]: User[] }) } as unknown as { [key: string]: User[] })
const [navigationItemSelected, setNavigationItemSelected] = React.useState('Recents') const [navigationItemSelected, setNavigationItemSelected] = React.useState('Recents')
@@ -62,25 +62,16 @@ export default function App() {
}) })
const loginDialogRef: React.MutableRefObject<Dialog | null> = React.useRef(null) const loginDialogRef: React.MutableRefObject<Dialog | null> = React.useRef(null)
const inputAccountRef: React.MutableRefObject<TextField | null> = React.useRef(null) const loginInputAccountRef: React.MutableRefObject<TextField | null> = React.useRef(null)
const inputPasswordRef: React.MutableRefObject<TextField | null> = React.useRef(null) const loginInputPasswordRef: React.MutableRefObject<TextField | null> = React.useRef(null)
const registerButtonRef: React.MutableRefObject<Button | null> = React.useRef(null)
const loginButtonRef: React.MutableRefObject<Button | null> = React.useRef(null)
useEventListener(loginButtonRef as React.MutableRefObject<Button>, 'click', async () => { const registerDialogRef: React.MutableRefObject<Dialog | null> = React.useRef(null)
const account = inputAccountRef.current!.value const registerInputUserNameRef: React.MutableRefObject<TextField | null> = React.useRef(null)
const password = inputPasswordRef.current!.value const registerInputNickNameRef: React.MutableRefObject<TextField | null> = React.useRef(null)
const registerInputPasswordRef: React.MutableRefObject<TextField | null> = React.useRef(null)
const re = await Client.invoke("User.login", {
account: account,
password: CryptoES.SHA256(password),
})
if (checkApiSuccessOrSncakbar(re, "登錄失敗")) return
})
React.useEffect(() => { React.useEffect(() => {
;(async () => { ; (async () => {
Split(['#SideBar', '#ChatFragment'], { Split(['#SideBar', '#ChatFragment'], {
sizes: [25, 75], sizes: [25, 75],
minSize: [200, 400], minSize: [200, 400],
@@ -89,7 +80,7 @@ export default function App() {
Client.connect() Client.connect()
const re = await Client.invoke("User.auth", { const re = await Client.invoke("User.auth", {
access_token: data.access_token, access_token: data.access_token || '',
}) })
if (re.code == 401) if (re.code == 401)
loginDialogRef.current!.open = true loginDialogRef.current!.open = true
@@ -107,10 +98,18 @@ export default function App() {
}}> }}>
<LoginDialog <LoginDialog
loginDialogRef={loginDialogRef} loginDialogRef={loginDialogRef}
inputAccountRef={inputAccountRef} loginInputAccountRef={loginInputAccountRef}
inputPasswordRef={inputPasswordRef} loginInputPasswordRef={loginInputPasswordRef}
registerButtonRef={registerButtonRef} registerDialogRef={registerDialogRef} />
loginButtonRef={loginButtonRef} />
<RegisterDialog
registerDialogRef={registerDialogRef}
registerInputUserNameRef={registerInputUserNameRef}
registerInputNickNameRef={registerInputNickNameRef}
registerInputPasswordRef={registerInputPasswordRef}
loginInputAccountRef={loginInputAccountRef}
loginInputPasswordRef={loginInputPasswordRef} />
<mdui-navigation-rail contained value="Recents" ref={navigationRailRef}> <mdui-navigation-rail contained value="Recents" ref={navigationRailRef}>
<mdui-button-icon icon="menu" slot="top"></mdui-button-icon> <mdui-button-icon icon="menu" slot="top"></mdui-button-icon>

View File

@@ -1,29 +1,50 @@
import * as React from 'react' import * as React from 'react'
import { Button, Dialog, TextField } from "mdui"; import { Button, Dialog, TextField } from "mdui"
import useEventListener from "../useEventListener.ts"
import { checkApiSuccessOrSncakbar } from "../snackbar.ts"
import Client from "../../api/Client.ts"
import * as CryptoES from 'crypto-es'
import data from "../../Data.ts";
interface Refs { interface Refs {
inputAccountRef: React.MutableRefObject<TextField | null> loginInputAccountRef: React.MutableRefObject<TextField | null>
inputPasswordRef: React.MutableRefObject<TextField | null> loginInputPasswordRef: React.MutableRefObject<TextField | null>
registerButtonRef: React.MutableRefObject<Button | null>
loginButtonRef: React.MutableRefObject<Button | null>
loginDialogRef: React.MutableRefObject<Dialog | null> loginDialogRef: React.MutableRefObject<Dialog | null>
registerDialogRef: React.MutableRefObject<Dialog | null>
} }
export default function LoginDialog({ export default function LoginDialog({
inputAccountRef, loginInputAccountRef,
inputPasswordRef, loginInputPasswordRef,
registerButtonRef, loginDialogRef,
loginButtonRef, registerDialogRef
loginDialogRef
}: Refs) { }: Refs) {
return ( const loginButtonRef: React.MutableRefObject<Button | null> = React.useRef(null)
<mdui-dialog headline="登录" ref={loginDialogRef}> const registerButtonRef: React.MutableRefObject<Button | null> = React.useRef(null)
useEventListener(registerButtonRef, 'click', () => registerDialogRef.current!.open = true)
useEventListener(loginButtonRef, 'click', async () => {
const account = loginInputAccountRef.current!.value
const password = loginInputPasswordRef.current!.value
<mdui-text-field label="账号" ref={inputAccountRef}></mdui-text-field> const re = await Client.invoke("User.login", {
account: account,
password: CryptoES.SHA256(password).toString(CryptoES.Hex),
})
if (checkApiSuccessOrSncakbar(re, "登錄失敗")) return
data.access_token = re.data!.access_token as string
location.reload()
})
return (
<mdui-dialog headline="登錄" ref={loginDialogRef}>
<mdui-text-field label="用戶 ID / 用戶名" ref={loginInputAccountRef}></mdui-text-field>
<div style={{ <div style={{
height: "10px", height: "10px",
}}></div> }}></div>
<mdui-text-field label="密" ref={inputPasswordRef}></mdui-text-field> <mdui-text-field label="密" type="password" toggle-password ref={loginInputPasswordRef}></mdui-text-field>
<mdui-button slot="action" variant="text" ref={registerButtonRef}></mdui-button> <mdui-button slot="action" variant="text" ref={registerButtonRef}></mdui-button>
<mdui-button slot="action" variant="text" ref={loginButtonRef}></mdui-button> <mdui-button slot="action" variant="text" ref={loginButtonRef}></mdui-button>

View File

@@ -0,0 +1,67 @@
import * as React from 'react'
import { Button, Dialog, TextField } from "mdui";
import useEventListener from "../useEventListener.ts";
import Client from "../../api/Client.ts";
import { checkApiSuccessOrSncakbar, snackbar } from "../snackbar.ts";
import * as CryptoES from 'crypto-es'
interface Refs {
loginInputAccountRef: React.MutableRefObject<TextField | null>
loginInputPasswordRef: React.MutableRefObject<TextField | null>
registerInputUserNameRef: React.MutableRefObject<TextField | null>
registerInputNickNameRef: React.MutableRefObject<TextField | null>
registerInputPasswordRef: React.MutableRefObject<TextField | null>
registerDialogRef: React.MutableRefObject<Dialog | null>
}
export default function RegisterDialog({
loginInputAccountRef,
loginInputPasswordRef,
registerInputUserNameRef,
registerInputNickNameRef,
registerInputPasswordRef,
registerDialogRef
}: Refs) {
const registerBackButtonRef: React.MutableRefObject<Button | null> = React.useRef(null)
const doRegisterButtonRef: React.MutableRefObject<Button | null> = React.useRef(null)
useEventListener(registerBackButtonRef, 'click', () => registerDialogRef.current!.open = false)
useEventListener(doRegisterButtonRef, 'click', async () => {
const username = registerInputUserNameRef.current!.value
const re = await Client.invoke("User.register", {
username: username,
nickname: registerInputNickNameRef.current!.value,
password: CryptoES.SHA256(registerInputPasswordRef.current!.value).toString(CryptoES.Hex),
})
if (checkApiSuccessOrSncakbar(re, "注冊失敗")) return
loginInputAccountRef.current!.value = username == "" ? re.data!.userid as string : username
loginInputPasswordRef.current!.value = registerInputPasswordRef.current!.value
registerInputUserNameRef.current!.value = ""
registerInputNickNameRef.current!.value = ""
registerInputPasswordRef.current!.value = ""
registerDialogRef.current!.open = false
snackbar({
message: "注冊成功!",
placement: "top",
})
})
return (
<mdui-dialog headline="注冊" ref={registerDialogRef}>
<mdui-text-field label="用戶名 (可選)" ref={registerInputUserNameRef}></mdui-text-field>
<div style={{
height: "10px",
}}></div>
<mdui-text-field label="昵稱" ref={registerInputNickNameRef}></mdui-text-field>
<div style={{
height: "10px",
}}></div>
<mdui-text-field label="密码" type="password" toggle-password ref={registerInputPasswordRef}></mdui-text-field>
<mdui-button slot="action" variant="text" ref={registerBackButtonRef}></mdui-button>
<mdui-button slot="action" variant="text" ref={doRegisterButtonRef}></mdui-button>
</mdui-dialog>
)
}