diff --git a/src/App.tsx b/src/App.tsx index 7a8e4ff..aae1cac 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,21 +1,37 @@ -import React from "react"; +import React, { useEffect } from "react"; import "./App.scss"; -import { Outlet } from "react-router"; +import { Outlet, useNavigate } from "react-router"; import { Layout } from "antd"; import { default as AppHeader } from "./components/Header"; import { default as AppFooter } from "./components/Footer"; import SideMenu from "./components/SideMenu"; import { createWebSocket, sharedWsUrl } from "./services/socket"; +import { useDispatch } from "react-redux"; +import { updateUser } from "./store/features/contextSlice"; const { Header, Footer, Sider, Content } = Layout; function App() { - console.log('app-------init--------') - //连接websocket - const wsClient = createWebSocket(sharedWsUrl); - wsClient.dataOb.subscribe(data => { - console.log('data---', data) - }) + const navigate = useNavigate(); + const dispatch = useDispatch(); + + useEffect(() => { + //连接websocket + const wsClient = createWebSocket(sharedWsUrl); + const subscription = wsClient.dataOb.subscribe(data => { + console.log("data---", data); + if (data.messageType === "DeviceContext") { + if (data.data.loginFlag) { + dispatch(updateUser(data.data)); + navigate("/measure/config"); + } else { + navigate("/login"); + } + } + }); + wsClient.connect(); + return () => subscription.unsubscribe(); + }); const headerStyle: React.CSSProperties = { height: 64, @@ -31,8 +47,6 @@ function App() { overflow: "hidden", }; - - return (
diff --git a/src/assets/icon_logout.svg b/src/assets/icon_logout.svg new file mode 100644 index 0000000..ddce64d --- /dev/null +++ b/src/assets/icon_logout.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/Header.tsx b/src/components/Header.tsx index 83b1c5e..3851ba6 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -1,11 +1,49 @@ +import { useSelector } from "react-redux"; import icon_avatar from "../assets/icon_avatar.svg"; +import icon_logout from "../assets/icon_logout.svg"; +import icon_pwd from "../assets/icon_pwd.svg"; + +import { Dropdown, MenuProps, message } from "antd"; +import { logout } from "../services/user/user"; + export default function Header() { + //@ts-ignore + const context = useSelector(store => store.context); + const [messageApi, contextHolder] = message.useMessage(); + + const items: MenuProps["items"] = [ + // { + // key: "1", + // label: "修改密码", + // icon: , + // onClick: () => { + // messageApi.info('ok') + // }, + // }, + { + key: "2", + label: "退出登录", + icon: icon, + onClick: () => { + logout({}).then(res => { + if (res.status !== 0) { + messageApi.error(res.data.info) + } + }) + } + }, + ]; return ( -
-
- -

Admin

-
-
+ <> + {contextHolder} +
+ +
+ +

{context.loginFlag ? context.loginUser.nickname : "未登录"}

+
+
+
+ ); } diff --git a/src/pages/login/Login.tsx b/src/pages/login/Login.tsx index 17ebce3..933a65c 100644 --- a/src/pages/login/Login.tsx +++ b/src/pages/login/Login.tsx @@ -1,22 +1,34 @@ -import { Button, Form, Input } from "antd"; +import { Button, Form, Input, message } from "antd"; import icon_user from "../../assets/icon_user.svg"; import icon_pwd from "../../assets/icon_pwd.svg"; import img_bg from "../../assets/img_bg.jpg"; import img_logo from "../../assets/icon_logo.png"; import { useNavigate } from "react-router"; +import { login } from "../../services/user/user"; export default function Login() { - const navigate = useNavigate(); + const navigate = useNavigate(); + const [messageApi, contextHolder] = message.useMessage(); const onFinish = (values: any) => { console.log("Received values of form: ", values); - navigate('/home'); + login({ account: values["username"], password: values["password"] }).then(res => { + if (res.status !== 0) { + messageApi.open({ + type: "error", + content: res.data.info, + }); + } else { + navigate("/measure/config"); + } + }); }; return (
+ {contextHolder}
- + - } placeholder="用户名" className="w-[280px]" /> + } + placeholder="用户名" + className="w-[280px]" + /> - + - } type="password" placeholder="密码" /> + } + type="password" + placeholder="密码" + /> @@ -39,7 +61,7 @@ export default function Login() { 登录 -

CHINA LOGISTICS

+

CHINA LOGISTICS

diff --git a/src/services/httpRequest.ts b/src/services/httpRequest.ts index 46ed9f7..919f7be 100644 --- a/src/services/httpRequest.ts +++ b/src/services/httpRequest.ts @@ -1,10 +1,8 @@ import { Subject } from "rxjs"; -export interface BaseResponse { - success: boolean; - code: string; - msg: string; +export interface BaseResponse { data: T; + status: number; } type HttpReqParam = { @@ -20,16 +18,6 @@ export type ApiException = "invalidToken" | "serverError"; const exceptionSub = new Subject(); export const exceptionOb = exceptionSub.asObservable(); -function extHandle(res: BaseResponse) { - if (res.code === "A0230") { - // 访问令牌无效或已过期 - exceptionSub.next("invalidToken"); - } - return { - ...res, - success: res.code === "00000", - }; -} export default async function httpRequest({ url, method = "GET", params = {}, encode = "json", headers = {} }: HttpReqParam) { const token = sessionStorage.getItem("token"); @@ -40,7 +28,7 @@ export default async function httpRequest({ url, method = "GET", params = {}, const query = urlEncode(params); const _url = query ? url + "?" + query : url; const res = await fetch(_url, { headers }); - return res.json().then(res => extHandle(res) as T); + return res.json() as T; } else { const body = encode === "json" ? JSON.stringify(params) : urlEncode(params); const _headers = @@ -48,7 +36,7 @@ export default async function httpRequest({ url, method = "GET", params = {}, ? { "Content-Type": "application/json; charset=utf-8", ...headers } : { "Content-Type": "application/x-www-form-urlencoded; charset=utf-8", ...headers }; const res = await fetch(url, { method, headers: _headers, body }); - return res.json().then(res => extHandle(res) as T); + return res.json() as T; } } export function urlEncode(params?: Record) { diff --git a/src/services/user/user.ts b/src/services/user/user.ts new file mode 100644 index 0000000..d0c6bc3 --- /dev/null +++ b/src/services/user/user.ts @@ -0,0 +1,17 @@ +import httpRequest, { BaseResponse } from "../httpRequest"; + +export function login(params: { account: string; password: string }) { + return httpRequest({ + url: "/auth/login", + params, + method: "POST", + }); +} + +export function logout(params: {}) { + return httpRequest({ + url: "/auth/logout", + params, + method: "POST", + }); +} diff --git a/src/services/wsTypes.ts b/src/services/wsTypes.ts index 7113fc9..45ebbcf 100644 --- a/src/services/wsTypes.ts +++ b/src/services/wsTypes.ts @@ -1,4 +1,4 @@ - // 开始、停止绘制 +// 开始、停止绘制 export type TaskState = { messageType: "EVENT"; data: { @@ -17,4 +17,20 @@ export type TrackRecordSig = { path: "/measurement-task/profile-record-ctrl-sig"; }; -export type Datagram = TrackRecordSig | TaskState; +export type ContextMessage = { + messageType: "DeviceContext"; + data: { + loginFlag: Boolean; + loginUser: Partial<{ + id: number; + account: string; + nickname: string; + password: string; + userRole: "Admin" | "User" | "Dev"; + isBuiltInUser: boolean; + }>; + }; + path: "/deviceContext"; +}; + +export type Datagram = TrackRecordSig | TaskState | ContextMessage; diff --git a/src/store/features/contextSlice.ts b/src/store/features/contextSlice.ts new file mode 100644 index 0000000..f93588b --- /dev/null +++ b/src/store/features/contextSlice.ts @@ -0,0 +1,28 @@ +// counterSlice.ts 文件 + +import { createSlice } from "@reduxjs/toolkit"; +import { ContextMessage } from "../../services/wsTypes"; + +const initialState: ContextMessage["data"] = { + loginFlag: false, + loginUser: {}, +}; + +// 创建一个 Slice +export const contextSlice = createSlice({ + name: "context", + initialState, + // 定义 reducers 并生成关联的操作 + reducers: { + // 定义一个加的方法 + updateUser: (state, { payload }) => { + state.loginFlag = payload.loginFlag; + state.loginUser = payload.loginUser; + }, + }, +}); +// 导出加减的方法 +export const { updateUser } = contextSlice.actions; + +// 默认导出 +export default contextSlice.reducer; diff --git a/src/store/index.ts b/src/store/index.ts index 9890dcc..b1bf104 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -2,12 +2,14 @@ import { configureStore } from "@reduxjs/toolkit"; import counterSlice from "./features/counterSlice"; +import contextSlice from "./features/contextSlice"; // configureStore创建一个redux数据 const store = configureStore({ // 合并多个Slice reducer: { counter: counterSlice, + context: contextSlice, }, });