bill 3 éve
szülő
commit
0b30eeb55a

+ 7 - 2
src/api/user.ts

@@ -1,5 +1,5 @@
-import { axios, setToken } from './instance'
-import { LOGIN } from 'constant'
+import { axios, delToken, setToken } from './instance'
+import { LOGIN, LOGOUT } from 'constant'
 import { encodePwd } from 'utils'
 
 export type User = {
@@ -19,4 +19,9 @@ export const login = async (data: LoginParams) => {
   )
   setToken(token)
   return user
+}
+
+export const logout = async () => {
+  await axios.post(LOGOUT, {})
+  delToken()
 }

+ 1 - 0
src/constant/api.ts

@@ -14,6 +14,7 @@ export const UPLOAD_HEADS = {
 
 
 export const LOGIN = `/fusion/fdLogin`
+export const LOGOUT = `/fusion/fdLogout`
 
 // 场景列表
 export const SCENE_LIST = `/fusion/scene/list`

+ 25 - 5
src/layout/header/index.tsx

@@ -1,18 +1,38 @@
-import { Avatar } from 'antd'
+import { Avatar, Menu, Dropdown } from 'antd'
+import { DownOutlined } from '@ant-design/icons'
 import style from './style.module.scss'
 import { title } from 'constant'
-import { useSelector } from 'store'
+import { useSelector, useDispatch, postLogout } from 'store'
+import { useNavigate, RoutePath } from 'router'
 
 
 export const HeaderContent = () => {
   const user = useSelector(store => store.user.value)
-  
+  const dispatch = useDispatch()
+  const navigate = useNavigate()
+  const logout = async () => {
+    await dispatch(postLogout()).unwrap()
+    navigate(RoutePath.login, { replace: true })
+  }
+
+  const items = [
+    {
+      key: '1',
+      label: <div onClick={logout} style={{textAlign: 'center'}}>退出</div>,
+    }
+  ]
+
   return (
     <>
       <h2 className={style.title}>{title}</h2>
       <div className={style.avatar}>
-        <Avatar src={user.head} />
-        <span className={style.username}>{user.nickName}</span>
+        <Dropdown overlay={<Menu items={items} />}>
+          <div>
+            <Avatar src={user.head} />
+            <span className={style.username}>{user.nickName}</span>
+            <DownOutlined />
+          </div>
+        </Dropdown>
       </div>
     </>
   )

+ 1 - 0
src/layout/header/style.module.scss

@@ -9,6 +9,7 @@
   color: #fff;
   display: flex;
   align-items: center;
+  cursor: pointer;
 
   .username {
     margin-left: 10px;

+ 7 - 2
src/store/user.ts

@@ -1,6 +1,6 @@
 import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'
 import { initialThukState, thunkStatusAutoSet } from './help'
-import { login } from 'api'
+import { login, logout } from 'api'
 
 import type { User } from 'api'
 import type { ThunkState } from './help'
@@ -43,6 +43,10 @@ const userSlice = createSlice({
         localStorage.setItem(userStoreKey, JSON.stringify(user))
       }
     )
+    builder.addCase(postLogout.fulfilled, (state) => {
+      localStorage.removeItem(userStoreKey)
+      state.value = getInitUser()
+    })
   },
 })
 
@@ -50,7 +54,8 @@ export const userName = userSlice.name
 export const userReducers = userSlice.reducer
 
 export const postLogin = createAsyncThunk('post/login', login)
+export const postLogout = createAsyncThunk('post/logout', logout)
 export type { LoginParams } from 'api'
 
 
-export const userSelector = (state: StoreState) => state.user.value
+export const userSelector = (state: StoreState) => state.user.value

+ 28 - 8
src/views/example/scene/list.tsx

@@ -1,10 +1,10 @@
-import { getExampleScenes } from 'api'
+import { getExampleScenes, SceneIdents } from 'api'
 import { useEffect, useState } from 'react'
 import { SceneTypeDesc } from 'constant';
 import { ActionsButton, Table } from 'components'
 import { Modal, Button } from 'antd'
 import { sceneTitleColumn, sceneTimeColumn, getSceneActions } from 'views/scene'
-import { getScenesIdents } from 'store'
+import { getSceneIdent, getScenesIdents } from 'store'
 import { SelectScenes } from './select'
 import style from '../style.module.scss'
 
@@ -34,7 +34,26 @@ export const ExampleScenes = (props: ExampleScenesProps) => {
       title: '操作',
       key: 'action',
       render: (_, record) => {
-        const actions = getSceneActions(record, true)
+        const actions = [
+          ...getSceneActions(record, true),
+          { 
+            text: '删除', 
+            action: () => {
+              const newIdents = idents.map(ident => {
+                if (ident.type === record.type) {
+                  const sceneIdent = getSceneIdent(record)
+                  return {
+                    ...ident,
+                    numList: ident.numList.filter(num => num !== sceneIdent)
+                  }
+                } else {
+                  return ident
+                }
+              })
+              selectChange(newIdents)
+            }
+          }
+        ]
         return <ActionsButton actions={actions} /> 
       }
     }
@@ -43,17 +62,18 @@ export const ExampleScenes = (props: ExampleScenesProps) => {
     getExampleScenes({ caseId: props.caseId })
       .then(setScenes)
   }
+  const selectChange = async (newIdents: SceneIdents) => {
+    await props.onChangeScenes(newIdents, idents)
+    await fetchExampleScenes()
+    setInSelectMode(false)
+  }
   useEffect(fetchExampleScenes, [props.caseId])
 
   const renderSelectMode = inSelectMode 
     && <SelectScenes 
         onClose={() => setInSelectMode(false)}
         sceneIdents={idents}
-        onSelect={async newIdents => {
-          await props.onChangeScenes(newIdents, idents)
-          await fetchExampleScenes()
-          setInSelectMode(false)
-        }}
+        onSelect={selectChange}
       />
   const renderSelf = (
     <Modal 

+ 0 - 1
src/views/example/scene/select.tsx

@@ -61,7 +61,6 @@ export const SelectScenes = ({ sceneIdents, ...props }: SelectScenesProps) => {
       }
     };
     
-    console.log(scenes)
     return (
       <div>
         <div className={style['model-header']}>