Commit 4298a4c4 authored by nick zheng's avatar nick zheng

feat: 模拟用户密码登录(非正式版)及调整布局

parent e874823d
import { request } from '@/utils/request'
export function fetchLogin<T>(payload: { loginChannel: string; account: string; password: string }) {
return request.post<T>(`/bizMemberInfoRest/doLogin.json`, payload)
}
export const BASE_URLS: Record<'DEV' | 'PROD', string> = {
DEV: '',
PROD: '',
DEV: 'https://poc-sit.gsstcloud.com',
PROD: 'https://poc.gsstcloud.com',
}
export const INDEX_URLS: Record<'DEV' | 'PROD', string> = {
DEV: 'https://poc-sit.gsstcloud.com/fe#/',
PROD: 'https://poc.gsstcloud.com/fe#/',
}
<script setup lang="ts">
import { useUserStore } from '@/store/modules/user'
import { readonly } from 'vue'
import { useRouter } from 'vue-router'
const defaultAvatar = 'https://mkp-dev.oss-cn-shenzhen.aliyuncs.com/game-template/20221018/1666079174947.png'
const userStore = useUserStore()
const router = useRouter()
const avatarOptions = readonly([
{
label: '退出登录',
key: 1,
},
])
function handleDropdownSelect(key: number) {
if (key === 1) {
userStore.logout().then(() => {
router.push({ name: 'Login' })
})
}
}
</script>
<template>
<div class="flex select-none items-center justify-between bg-white px-4 shadow-[inset_0_-1px_#e8e9eb]">
<div class="flex">APPBuilder</div>
<div class="flex cursor-pointer items-center px-2">
<NDropdown trigger="click" :options="avatarOptions" @select="handleDropdownSelect">
<div class="flex h-full items-center">
<NAvatar round :size="30" object-fit="cover" :src="userStore.userInfo.avatar || defaultAvatar" />
</div>
</NDropdown>
</div>
</div>
</template>
<script setup lang="ts">
import { h, readonly, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { sidebarMenus } from '@/router/index'
import { type MenuOption } from '@/router/utils'
import { useRoute, useRouter } from 'vue-router'
import { ref, watch } from 'vue'
import CustomIcon from '@/components/custom-icon/custom-icon.vue'
import { useUserStore } from '@/store/modules/user'
const currentRoute = useRoute()
const router = useRouter()
const userStore = useUserStore()
const menuValue = ref(currentRoute.meta.belong)
const defaultAvatar = 'https://gsst-poe-sit.gz.bcebos.com/data/20240910/1725952917468.png'
const avatarOptions = readonly([
// {
// label: '我的',
// key: 'My',
// icon: () => h(CustomIcon, { icon: 'bx:user' }),
// },
{
label: '退出登录',
key: 'logout',
icon: () => h(CustomIcon, { icon: 'teenyicons:logout-solid' }),
},
])
watch(
() => currentRoute.fullPath,
() => {
......@@ -24,27 +42,75 @@ function handleUpdateValue(_key: string, menuItemOption: MenuOption) {
// function handleToPersonAppSettingPage() {
// router.push({ name: 'PersonalAppSetting' })
// }
function handleDropdownSelect(key: string) {
if (key === 'logout') {
userStore.logout().then(() => {
router.push({ name: 'Login' })
})
return
}
router.replace({ name: key })
}
</script>
<template>
<!-- <button
class="mx-2 mb-[14px] flex h-[32px] w-[188px] items-center justify-center rounded-md bg-gradient-to-r from-[#005aff] to-[#60e0fd] text-white outline-none hover:opacity-80"
@click="handleToPersonAppSettingPage"
>
<CustomIcon icon="zondicons:add-solid" class="mr-1.5" />
<span>创建应用</span>
</button> -->
<ul>
<li
v-for="sidebarMenuItem in sidebarMenus"
:key="sidebarMenuItem.key"
class="my-1 flex h-10 cursor-pointer items-center rounded-md pl-3 hover:bg-[#f2f5f9]"
:class="[menuValue === sidebarMenuItem.routeName ? 'bg-[#f2f5f9] text-[#151b26]' : 'text-[#5c5f66]']"
@click="handleUpdateValue(sidebarMenuItem.routeName, sidebarMenuItem)"
>
<CustomIcon :icon="sidebarMenuItem.icon" class="mr-2 text-base" />
<span class="line-clamp-1 max-w-[150px]">{{ sidebarMenuItem.label }}</span>
</li>
</ul>
<div class="flex h-full flex-col justify-between px-3">
<div>
<div
class="mx-auto my-[14px] flex h-[23px] w-[90px] bg-[url('@/assets/images/page-logo.png')] bg-contain bg-center bg-no-repeat"
/>
<!-- <div class="py-5">
<button
class="bg-theme-color flex h-[40px] w-[203px] items-center justify-center rounded-md text-white outline-none hover:opacity-80"
@click="handleToPersonAppSettingPage"
>
<CustomIcon icon="ic:outline-add" class="mr-1 h-[18px] w-[18px]" />
<span>创建应用</span>
</button>
</div> -->
<ul>
<li
v-for="sidebarMenuItem in sidebarMenus"
:key="sidebarMenuItem.key"
class="my-1 flex h-10 cursor-pointer items-center rounded-md pl-3 hover:bg-[#f2f5f9]"
:class="[menuValue === sidebarMenuItem.routeName ? 'bg-[#f2f5f9] text-[#151b26]' : 'text-[#5c5f66]']"
@click="handleUpdateValue(sidebarMenuItem.routeName, sidebarMenuItem)"
>
<CustomIcon :icon="sidebarMenuItem.icon" class="mr-2 text-base" />
<span class="line-clamp-1 max-w-[150px]">{{ sidebarMenuItem.label }}</span>
</li>
</ul>
</div>
<div class="mb-7">
<NDropdown trigger="click" placement="top-start" :options="avatarOptions" @select="handleDropdownSelect">
<div class="flex h-full cursor-pointer items-center">
<NAvatar round :size="40" object-fit="cover" :src="userStore.userInfo.avatarUrl || defaultAvatar" />
<div class="ml-3 line-clamp-1 max-w-[140px] select-none break-all text-base">
{{ userStore.userInfo.nickName || '未登录' }}
</div>
</div>
</NDropdown>
</div>
</div>
</template>
<style lang="scss">
.v-binder-follower-container {
.n-dropdown-menu {
--n-border-radius: 10px !important;
--n-box-shadow: -3px 3px 4px 0px #f2f2f2 !important;
padding: 6px 0 !important;
}
.n-dropdown-menu .n-dropdown-option-body {
padding: 0 10px;
}
}
</style>
<script setup lang="ts">
import Sidebar from './components/sidebar/sidebar.vue'
import NavBar from './components/navbar/navbar.vue'
const layoutSideWidth = 221
const layoutSideWidth = 243
</script>
<template>
<NLayout content-class="layout-content" position="absolute">
<NLayoutHeader class="box-border h-[56px] flex-none">
<NavBar class="h-full" />
</NLayoutHeader>
<NLayout has-sider class="h-[calc(100%-56px)]">
<NLayoutSider
class="border-r border-[#e8e9eb] px-2 pt-4"
collapse-mode="width"
:collapsed-width="64"
:width="layoutSideWidth"
>
<Sidebar />
</NLayoutSider>
<NLayoutContent class="bg-[#f3f6f9]! flex-1">
<main class="box-border h-full px-6 py-4">
<RouterView v-slot="{ Component }">
<Transition appear name="fade-slide" mode="out-in">
<Component :is="Component" />
</Transition>
</RouterView>
</main>
</NLayoutContent>
</NLayout>
<NLayout has-sider class="h-full">
<NLayoutSider
class="border-r border-[#e8e9eb] px-2"
collapse-mode="width"
:collapsed-width="64"
:width="layoutSideWidth"
>
<Sidebar />
</NLayoutSider>
<NLayoutContent class="bg-[#f3f6f9]! flex-1">
<main class="box-border h-full px-6 py-4">
<RouterView v-slot="{ Component }">
<Transition appear name="fade-slide" mode="out-in">
<Component :is="Component" />
</Transition>
</RouterView>
</main>
</NLayoutContent>
</NLayout>
</template>
......
......@@ -34,7 +34,7 @@ const modules: Record<string, any> = import.meta.glob(['./modules/**/*.ts', '!./
export const sidebarMenus: any[] = menuFilterSort([...routes])
const router = createRouter({
export const router = createRouter({
history: getHistoryMode(import.meta.env.VITE_ROUTER_MODE),
routes: [...routes, ...baseRoutes],
strict: true,
......
......@@ -5,12 +5,10 @@ import type { UserState, UserInfo } from '../types/user'
function getDefaultUserInfo(): UserInfo {
return {
account: '',
userAccount: '',
userId: null,
userName: '用户',
createdTime: '',
avatar: '',
memberId: 0,
nickName: '',
mobilePhone: '',
avatarUrl: 'https://gsst-poe-sit.gz.bcebos.com/data/20240910/1725952917468.png',
}
}
......
export interface UserInfo {
account: string
userAccount: string
userId: null | number
userName: string
createdTime: string
avatar: string
memberId: number
nickName: string
avatarUrl: string
mobilePhone: string
}
export interface UserState {
......
......@@ -2,6 +2,7 @@ import axios, { type AxiosRequestConfig, type AxiosResponse } from 'axios'
import { BASE_URLS } from '@/config/base-url'
import { useUserStore } from '@/store/modules/user'
import { useRouter } from 'vue-router'
import { router } from '@/router'
interface PagingInfoParams {
pageNo: number
......@@ -18,15 +19,14 @@ export interface Response<T> {
const ENV = import.meta.env.VITE_APP_ENV
function handleLogout() {
const router = useRouter()
const currentRoute = router.currentRoute.value
router.replace({ name: 'Login', query: { redirect: encodeURIComponent(currentRoute.fullPath) } })
window.$message.warning('身份已过期,请重新登录')
}
const service = axios.create({
baseURL: `${BASE_URLS[ENV]}/api`,
baseURL: `${BASE_URLS[ENV]}/api/rest`,
timeout: 7000,
headers: {
'Content-Type': 'application/json',
......@@ -81,7 +81,7 @@ function http<T>(
handleLogout()
}
if (res.message) {
if (res.code === -1 && res.message) {
const msg = res.message.match(/\[(?<msg>[\s\S]+)\]/)?.groups?.msg
window.$message.error(msg || res.message)
}
......
......@@ -3,9 +3,8 @@ import { ref } from 'vue'
import { appConfig } from '@/config/app-config'
import CustomIcon from '@/components/custom-icon/custom-icon.vue'
import { FormInst } from 'naive-ui'
// import { fetchLogin } from '@/apis/user'
import { fetchLogin } from '@/apis/user'
import { useUserStore } from '@/store/modules/user'
// import type { UserInfo } from '@/store/types/user'
import { useRouter } from 'vue-router'
const userStore = useUserStore()
......@@ -26,73 +25,42 @@ const loginFormRules = {
function handleLogin(e: MouseEvent) {
e.preventDefault()
loginFormRef.value?.validate((errors) => {
loginFormRef.value?.validate(async (errors) => {
if (!errors) {
// loginBtnLoading.value = true
loginBtnLoading.value = true
userStore.updateIsLogin(true)
userStore.updateToken('')
const userInfoRes = {
account: 'account',
userAccount: 'userAccount',
userId: 134,
userName: 'userName',
createdTime: 'createdTime',
}
userStore.updateUserInfo({
account: userInfoRes.account,
userAccount: userInfoRes.userAccount,
userId: userInfoRes.userId,
userName: userInfoRes.userName,
createdTime: userInfoRes.createdTime,
avatar: '',
})
const currentRoute = router.currentRoute.value
const redirectUrl = decodeURIComponent((currentRoute.query.redirect as string) || '')
if (redirectUrl) {
router.replace({ path: redirectUrl })
return
}
const res = await fetchLogin<{
token: string
memberId: number
nickName: string
avatarUrl: string
mobilePhone: string
}>({
loginChannel: 'MEMBER_PLATFOMR_PW',
account: '15816736768',
password: '123456',
}).finally(() => (loginBtnLoading.value = false))
router.replace({ name: 'Root' })
if (res.code === 0) {
userStore.updateIsLogin(true)
userStore.updateToken(res.data.token)
userStore.updateUserInfo({
avatarUrl: res.data.avatarUrl,
memberId: res.data.memberId,
mobilePhone: res.data.mobilePhone,
nickName: res.data.nickName,
})
// fetchLogin<{ token: string; user: UserInfo }>(loginForm.value)
// .then((res) => {
// if (res.code !== null && res.code !== 0) {
// window.$message.error(res.message || '登录失败请重试')
// return
// }
const currentRoute = router.currentRoute.value
const redirectUrl = decodeURIComponent((currentRoute.query.redirect as string) || '')
// userStore.updateIsLogin(true)
// userStore.updateToken(res.data.token)
// const userInfoRes = res.data.user || {}
// userStore.updateUserInfo({
// account: userInfoRes.account,
// userAccount: userInfoRes.userAccount,
// userId: userInfoRes.userId,
// userName: userInfoRes.userName,
// createdTime: userInfoRes.createdTime,
// avatar: '',
// })
if (redirectUrl) {
router.replace({ path: redirectUrl })
return
}
// const currentRoute = router.currentRoute.value
// const redirectUrl = decodeURIComponent((currentRoute.query.redirect as string) || '')
// if (redirectUrl) {
// router.replace({ path: redirectUrl })
// return
// }
// router.replace({ name: 'Root' })
// })
// .catch((err) => {
// console.log(err)
// })
// .finally(() => {
// loginBtnLoading.value = false
// })
router.replace({ name: 'Root' })
}
}
})
}
......
......@@ -18,5 +18,9 @@ export default defineConfig({
colors: {
'theme-color': '#2468f2',
},
height: {
navbar: '56px',
content: 'calc(100% - 56px)',
},
},
})
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment