v3.2.3 发布

This commit is contained in:
ray_wuhao 2023-05-31 15:35:57 +08:00
parent f69be958bd
commit d8bdfc1f66
23 changed files with 636 additions and 192 deletions

View File

@ -1,5 +1,20 @@
# CHANGE LOG
## 3.2.3
### 特征
- 新增锁屏功能(值得注意的是,锁屏解锁后会刷新当前 RouterView 区域,因为在处于锁屏状态时,会自动销毁所有的操作页面。可以理解为是一个 v-if 操作行为)
- 新增 dayjs hook支持国际化与切换
- 支持更多 appConfig 配置
- 调整 setupAppRoute 触发时机(现在会在 layout 渲染阶段触发)
- 补充了新的组件分包 AppComponents存放该系统的一些组件会与系统进行一些深度绑定例如 AppAvatar 组件依赖系统数据)
### 补充
- 锁屏功能的设计并不理想,后期会进行破坏性更新。锁屏触发条件与管理方式目前并不理想,管理有点混乱
- 后期会考虑补充 keepAlive 功能。目前没有实现是因为该功能实现的话,需要将所有路由提升为顶层路由(这是 KeepAlive 组件限制),目前并未实现该功能。后期会在权衡后增加该功能,实现时会在 RayTransitionComponent 进行拓展补充
## 3.2.2
### 特征

View File

@ -1,6 +1,7 @@
import RayGlobalProvider from '@/components/RayGlobalProvider/index'
import { RouterView } from 'vue-router'
import GlobalSpin from '@/spin/index'
import LockScreen from '@/components/AppComponents/AppLockScreen/index'
import { getCache } from '@/utils/cache'
import { get } from 'lodash-es'
@ -79,6 +80,8 @@ const App = defineComponent({
render() {
return (
<RayGlobalProvider>
<LockScreen />
<GlobalSpin>
{{
default: () => <RouterView />,

View File

@ -76,3 +76,19 @@ export const MENU_COLLAPSED_CONFIG: MenuCollapsedConfig = {
/** 是否启用菜单手风琴模式 */
export const MENU_ACCORDION = false
/**
*
* key
* , key
*
* :
* - signin: 登陆信息缓存 key
* - localeLanguage: 国际化默认缓存 key
* - token: token key
*/
export const APP_CATCH_KEY = {
signin: 'signin',
localeLanguage: 'localeLanguage',
token: 'token',
}

View File

@ -11,6 +11,8 @@
/** 国际化相关配置 */
import type { DayjsLocal, DayjsLocalMap } from '@/dayjs/type'
/**
*
* ,
@ -34,3 +36,24 @@ export const LOCAL_OPTIONS = [
* LOCAL_OPTIONS key
*/
export const SYSTEM_DEFAULT_LOCAL = 'zh-CN'
/**
*
* dayjs
* (en)
*
* (-)
*/
export const DEFAULT_DAYJS_LOCAL: DayjsLocal = 'zh-cn'
/**
*
* i18n dayjs
*
* key LOCAL_OPTIONS key
*
*/
export const DAYJS_LOCAL_MAP: DayjsLocalMap = {
'zh-CN': 'zh-cn',
'en-US': 'en',
}

View File

@ -0,0 +1,7 @@
.app-avatar {
cursor: var(--app-avatar-cursor);
& .app-avatar__name {
font-weight: 500;
}
}

View File

@ -0,0 +1,87 @@
/**
*
* @author Ray <https://github.com/XiaoDaiGua-Ray>
*
* @date 2023-05-31
*
* @workspace ray-template
*
* @remark
*/
/**
*
*
*
* naive ui Avatar ,
* session catch
*/
import './index.scss'
import { NAvatar, NSpace } from 'naive-ui'
import { avatarProps, spaceProps } from 'naive-ui'
import { APP_CATCH_KEY } from '@/appConfig/appConfig'
import { getCache } from '@/utils/cache'
import type { PropType } from 'vue'
import type { AvatarProps, SpaceProps } from 'naive-ui'
const AppAvatar = defineComponent({
name: 'AppAvatar',
props: {
...avatarProps,
...spaceProps,
cursor: {
type: String,
default: 'auto',
},
spaceSize: {
type: [String, Number] as PropType<SpaceProps['size']>,
default: 'medium',
},
avatarSize: {
type: [String, Number] as PropType<AvatarProps['size']>,
default: 'medium',
},
},
setup(props) {
const signin = getCache(APP_CATCH_KEY.signin)
const cssVars = computed(() => {
const vars = {
'--app-avatar-cursor': props.cursor,
}
return vars
})
return {
signin,
cssVars,
}
},
render() {
return (
<NSpace
class="app-avatar"
{...this.$props}
wrapItem={false}
style={this.cssVars}
size={this.spaceSize}
>
<NAvatar
// eslint-disable-next-line prettier/prettier, @typescript-eslint/no-explicit-any
{...(this.$props as any)}
src={this.signin.avatar}
objectFit="cover"
round
size={this.avatarSize}
/>
<div class="app-avatar__name">{this.signin.name}</div>
</NSpace>
)
},
})
export default AppAvatar

View File

@ -0,0 +1,63 @@
.lock-screen {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
background: black;
& .lock-screen__content {
position: relative;
width: 100%;
height: 100%;
@include flexCenter;
flex-direction: column;
& .lock-screen__content-bg {
position: absolute;
width: 100%;
height: 100%;
@include flexCenter;
font-size: 220px;
gap: 80px;
z-index: 0;
& .left,
& .right {
@include flexCenter;
border-radius: 30px;
background-color: #141313;
font-weight: 700;
padding: 80px;
filter: blur(4px);
}
}
& .lock-screen__content-avatar {
margin-top: 5px;
color: #bababa;
font-weight: 500;
z-index: 1;
}
& .lock-screen__content-input {
width: 260px;
z-index: 1;
}
& .lock-screen__content-date {
position: fixed;
width: 100%;
font-size: 3rem;
text-align: center;
font-weight: 500;
bottom: 24px;
z-index: 1;
& .current-year,
& .current-date span {
font-size: 1.5rem;
}
}
}
}

View File

@ -0,0 +1,250 @@
/**
*
* @author Ray <https://github.com/XiaoDaiGua-Ray>
*
* @date 2023-05-13
*
* @workspace ray-template
*
* @remark
*/
import './index.scss'
import { NModal, NInput, NForm, NFormItem, NButton, NSpace } from 'naive-ui'
import AppAvatar from '@/components/AppComponents/AppAvatar/index'
import { useSetting, useSignin } from '@/store'
import { getCache, setCache } from '@/utils/cache'
import dayjs from 'dayjs'
import { APP_CATCH_KEY } from '@/appConfig/appConfig'
import type { FormInst, InputInst } from 'naive-ui'
const LockScreen = defineComponent({
name: 'LockScreen',
setup() {
const formRef = ref<FormInst>()
const inputInstRef = ref<InputInst>()
const settingStore = useSetting()
const signinStore = useSignin()
/** lockScreenSwitch 检测是否激活锁屏弹窗 */
const { lockScreenSwitch, lockScreenInputSwitch } =
storeToRefs(settingStore)
const { changeSwitcher } = settingStore
const { logout } = signinStore
const TIME_FORMAT = 'HH:mm'
const AM_PM_FORMAT = 'A'
const YEAR_FORMAT = 'YY-MM-DD'
const DATE_FORMAT = 'dddd'
const state = reactive({
lockCondition: {
pwd: null,
},
time: dayjs().format(TIME_FORMAT),
second: dayjs().locale('en').format(AM_PM_FORMAT),
year: dayjs().format(YEAR_FORMAT),
date: dayjs().format(DATE_FORMAT),
})
const rules = {
pwd: {
required: true,
message: '请输入正确格式密码',
min: 6,
max: 12,
trigger: ['input', 'blur'],
},
}
/** 检测是否处于锁屏状态 */
const isLock = useStorage('isLockScreen', false, sessionStorage, {
mergeDefaults: true,
})
const signin = getCache(APP_CATCH_KEY.signin)
const handleLockScreen = () => {
formRef.value?.validate((error) => {
if (!error) {
isLock.value = true
state.lockCondition.pwd = null
setCache('lockScreenPassword', state.lockCondition.pwd)
changeSwitcher(true, 'lockScreenSwitch')
}
})
}
const dayInterval = setInterval(() => {
state.time = dayjs().format(TIME_FORMAT)
state.second = dayjs().format(AM_PM_FORMAT)
}, 60_000)
const yearInterval = setInterval(() => {
state.year = dayjs().format(YEAR_FORMAT)
state.date = dayjs().format(DATE_FORMAT)
}, 86_400_000)
const handleBackToSignin = () => {
window.$dialog.warning({
title: '警告',
content: '是否返回到登陆页?',
positiveText: '确定',
negativeText: '取消',
onPositiveClick: () => {
logout()
setTimeout(() => {
changeSwitcher(false, 'lockScreenSwitch')
})
},
})
}
const handleUnlockScreen = () => {
formRef.value?.validate((error) => {
if (!error) {
isLock.value = false
state.lockCondition.pwd = null
changeSwitcher(false, 'lockScreenSwitch')
}
})
}
/** 当弹窗出现后, 自动聚焦密码输入框 */
const handleModalUpdateShow = () => {
nextTick(() => {
inputInstRef.value?.focus()
})
}
onBeforeUnmount(() => {
clearInterval(dayInterval)
clearInterval(yearInterval)
})
return {
lockScreenSwitch,
lockScreenInputSwitch,
rules,
...toRefs(state),
isLock,
handleLockScreen,
formRef,
signin,
handleBackToSignin,
handleUnlockScreen,
inputInstRef,
handleModalUpdateShow,
}
},
render() {
return (
<NModal
v-model:show={this.lockScreenSwitch}
transform-origin="center"
show
maskClosable={false}
closeOnEsc={false}
preset={!this.isLock ? 'dialog' : undefined}
title="锁定屏幕"
onAfterEnter={this.handleModalUpdateShow.bind(this)}
>
{!this.isLock ? (
/** 输入界面 */
<div class="lock-screen__input">
<AppAvatar vertical align="center" avatarSize={52} />
<NForm
ref="formRef"
model={this.lockCondition}
rules={this.rules}
labelPlacement="left"
style={{
margin: '24px 0',
}}
>
<NFormItem path="pwd">
<NInput
v-model:value={this.lockCondition.pwd}
type="password"
placeholder="请输入锁屏密码"
clearable
minlength={6}
maxlength={12}
ref="inputInstRef"
/>
</NFormItem>
<NButton
type="primary"
onClick={this.handleLockScreen.bind(this)}
style={{
width: '100%',
}}
>
</NButton>
</NForm>
</div>
) : (
/** 锁屏界面 */
<div class="lock-screen">
<div class="lock-screen__content">
<div class="lock-screen__content-bg">
<div class="left">{this.time?.split(':')[0]}</div>
<div class="right">{this.time?.split(':')[1]}</div>
</div>
<div class="lock-screen__content-avatar">
<AppAvatar vertical align="center" avatarSize={52} />
</div>
<div class="lock-screen__content-input">
<NForm
ref="formRef"
model={this.lockCondition}
rules={this.rules}
>
<NFormItem path="pwd">
<NInput
v-model:value={this.lockCondition.pwd}
type="password"
placeholder="请输入解锁密码"
clearable
minlength={6}
maxlength={12}
ref="inputInstRef"
/>
</NFormItem>
<NSpace justify="space-between">
<NButton
type="primary"
text
onClick={this.handleBackToSignin.bind(this)}
>
</NButton>
<NButton
type="primary"
text
onClick={this.handleUnlockScreen.bind(this)}
>
</NButton>
</NSpace>
</NForm>
</div>
<div class="lock-screen__content-date">
<div class="current-date">
{this.time}&nbsp;<span>{this.second}</span>
</div>
<div class="current-year">
{this.year}&nbsp;{this.date}
</div>
</div>
</div>
</div>
)}
</NModal>
)
},
})
export default LockScreen

28
src/dayjs/index.ts Normal file
View File

@ -0,0 +1,28 @@
import dayjs from 'dayjs'
import { DEFAULT_DAYJS_LOCAL, DAYJS_LOCAL_MAP } from '@/appConfig/localConfig'
import 'dayjs/locale/zh-cn'
import type { DayjsLocal } from './type'
export const setupDayjs = () => {
dayjs.locale(DEFAULT_DAYJS_LOCAL)
}
/**
*
* dayjs hook
*
* :
* - locale: 切换 dayjs
*/
export const useDayjs = () => {
const locale = (key: DayjsLocal) => {
const mapkey = DAYJS_LOCAL_MAP[key]
mapkey ? dayjs.locale(mapkey) : dayjs.locale(DEFAULT_DAYJS_LOCAL)
}
return {
locale,
}
}

6
src/dayjs/type.ts Normal file
View File

@ -0,0 +1,6 @@
export type DayjsLocal = 'zh-cn' | 'en'
export interface DayjsLocalMap {
'zh-CN': 'zh-cn'
'en-US': 'en'
}

View File

@ -12,7 +12,7 @@ const LayoutMenu = defineComponent({
const menuStore = useMenu()
const router = useRouter()
const { menuModelValueChange, setupAppRoutes, collapsedMenu } = menuStore
const { menuModelValueChange, collapsedMenu } = menuStore
const modelMenuKey = computed({
get: () => menuStore.menuKey,
// eslint-disable-next-line @typescript-eslint/no-empty-function
@ -32,8 +32,6 @@ const LayoutMenu = defineComponent({
}
}
setupAppRoutes()
return {
modelMenuKey,
menuModelValueChange,

View File

@ -1,12 +0,0 @@
.lock-screen {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
& .lock-screen__content {
width: 100%;
height: 100%;
}
}

View File

@ -1,94 +0,0 @@
/**
*
* @author Ray <https://github.com/XiaoDaiGua-Ray>
*
* @date 2023-05-13
*
* @workspace ray-template
*
* @remark
*/
import './index.scss'
import { NModal, NInput, NForm, NFormItem, NButton } from 'naive-ui'
import { useSetting } from '@/store'
import { getCache, setCache } from '@/utils/cache'
import type { FormInst } from 'naive-ui'
const LockScreen = defineComponent({
name: 'LockScreen',
setup() {
const formRef = ref<FormInst>()
const settingStore = useSetting()
const { lockScreenSwitch, lockScreenInputSwitch } =
storeToRefs(settingStore)
const state = reactive({
lockCondition: {
pwd: null,
},
})
const rules = {
pwd: {},
}
const isLock =
getCache('isLockScreen') === 'no' ? false : getCache('isLockScreen')
return {
lockScreenSwitch,
lockScreenInputSwitch,
rules,
...toRefs(state),
isLock,
}
},
render() {
return (
<NModal
v-model:show={this.lockScreenSwitch}
transform-origin="center"
show
// closeOnEsc={false}
autoFocus={false}
maskClosable={false}
preset={!this.isLock ? 'dialog' : undefined}
title="锁定屏幕"
>
{!this.isLock ? (
/** 输入界面 */
<div class="lock-screen__input">
<NForm model={this.lockCondition} rules={this.rules} inline>
<NFormItem label="锁屏密码">
<NInput
v-model:value={this.lockCondition.pwd}
type="password"
/>
</NFormItem>
<NFormItem>
<NButton
type="primary"
onClick={() => {
window.$message.info('功能开发中...')
}}
>
</NButton>
</NFormItem>
</NForm>
</div>
) : (
/** 锁屏界面 */
<div class="lock-screen">
<div class="lock-screen__content"></div>
</div>
)}
</NModal>
)
},
})
export default LockScreen

View File

@ -1,8 +1,14 @@
import { useSetting, useSignin } from '@/store'
export const useAvatarOptions = () => [
{
key: 'person',
label: '个人信息',
},
{
key: 'lockScreen',
label: '锁定屏幕',
},
{
type: 'divider',
key: 'd1',
@ -12,3 +18,32 @@ export const useAvatarOptions = () => [
label: '退出登陆',
},
]
const avatarDropdownActionMap = {
logout: () => {
const signinStore = useSignin()
const { logout } = signinStore
window.$dialog.warning({
title: '提示',
content: '您确定要退出登录吗',
positiveText: '确定',
negativeText: '不确定',
onPositiveClick: () => {
logout()
},
})
},
lockScreen: () => {
const settingStore = useSetting()
const { changeSwitcher } = settingStore
changeSwitcher(true, 'lockScreenSwitch')
},
}
export const avatarDropdownClick = (key: string | number) => {
const action = avatarDropdownActionMap[key]
action ? action() : window.$message.info('这个人很懒, 没做这个功能~')
}

View File

@ -11,20 +11,21 @@
import './index.scss'
import { NLayoutHeader, NSpace, NTooltip, NDropdown, NTag } from 'naive-ui'
import { NLayoutHeader, NSpace, NTooltip, NDropdown } from 'naive-ui'
import RayIcon from '@/components/RayIcon/index'
import RayTooltipIcon from '@/components/RayTooltipIcon/index'
import SettingDrawer from './components/SettingDrawer/index'
import Breadcrumb from './components/Breadcrumb/index'
import GlobalSeach from './components/GlobalSeach/index'
import LockScreen from './components/LockScreen/index'
import AppAvatar from '@/components/AppComponents/AppAvatar/index'
import { useSetting, useSignin } from '@/store'
import { LOCAL_OPTIONS } from '@/appConfig/localConfig'
import { useAvatarOptions } from './hook'
import { useAvatarOptions, avatarDropdownClick } from './hook'
import { getCache } from '@/utils/cache'
import screenfull from 'screenfull'
import { useI18n } from '@/locales/useI18n'
import { APP_CATCH_KEY } from '@/appConfig/appConfig'
import type { IconEventMapOptions, IconEventMap } from './type'
@ -47,7 +48,7 @@ const SiderBar = defineComponent({
const { drawerPlacement, breadcrumbSwitch } = storeToRefs(settingStore)
const showSettings = ref(false)
const person = getCache('person')
const signin = getCache(APP_CATCH_KEY.signin)
const spaceItemStyle = {
display: 'flex',
}
@ -75,12 +76,6 @@ const SiderBar = defineComponent({
tooltip: t('headerTooltip.Search'),
eventKey: 'search',
},
{
name: 'lock',
size: 18,
tooltip: t('headerTooltip.Lock'),
eventKey: 'lock',
},
{
name: 'fullscreen',
size: 18,
@ -131,22 +126,6 @@ const SiderBar = defineComponent({
iconEventMap[key]?.()
}
const handlePersonSelect = (key: string | number) => {
if (key === 'logout') {
window.$dialog.warning({
title: '提示',
content: '您确定要退出登录吗',
positiveText: '确定',
negativeText: '不确定',
onPositiveClick: () => {
logout()
},
})
} else {
window.$message.info('这个人很懒, 没做这个功能~')
}
}
return {
leftIconOptions,
rightTooltipIconOptions,
@ -154,8 +133,7 @@ const SiderBar = defineComponent({
handleIconClick,
showSettings,
updateLocale,
handlePersonSelect,
person,
signin,
spaceItemStyle,
drawerPlacement,
breadcrumbSwitch,
@ -166,7 +144,6 @@ const SiderBar = defineComponent({
return (
<NLayoutHeader class="layout-header" bordered>
<GlobalSeach v-model:show={this.globalSearchShown} />
<LockScreen />
<NSpace
class="layout-header__method"
align="center"
@ -221,21 +198,10 @@ const SiderBar = defineComponent({
</NDropdown>
<NDropdown
options={useAvatarOptions()}
onSelect={this.handlePersonSelect.bind(this)}
onSelect={avatarDropdownClick.bind(this)}
trigger="click"
>
<NTag checkable size="large">
{{
icon: () => (
<RayIcon
customClassName="layout-header__method--icon"
name="ray"
size="18"
/>
),
default: () => this.person.name,
}}
</NTag>
<AppAvatar avatarSize="small" align="center" cursor="pointer" />
</NDropdown>
</NSpace>
</NSpace>

View File

@ -15,16 +15,18 @@ import MenuTag from './components/MenuTag/index'
import ContentWrapper from '@/layout/default/ContentWrapper'
import FooterWrapper from '@/layout/default/FooterWrapper'
import { useSetting } from '@/store'
import { useSetting, useMenu } from '@/store'
import { viewScrollContainerId } from '@/appConfig/routerConfig'
const Layout = defineComponent({
name: 'Layout',
setup() {
const settingStore = useSetting()
const menuStore = useMenu()
const { height: windowHeight } = useWindowSize()
const { menuTagSwitch: modelMenuTagSwitch } = storeToRefs(settingStore)
const { setupAppRoutes } = menuStore
const cssVarsRef = computed(() => {
let cssVar = {}
@ -40,11 +42,17 @@ const Layout = defineComponent({
return cssVar
})
const isLock = useStorage('isLockScreen', false, sessionStorage, {
mergeDefaults: true,
})
setupAppRoutes()
return {
windowHeight,
modelMenuTagSwitch,
cssVarsRef,
isLock,
}
},
render() {
@ -53,21 +61,25 @@ const Layout = defineComponent({
class={['layout']}
style={[`height: ${this.windowHeight}px`, this.cssVarsRef]}
>
<NLayout class="layout-full" hasSider>
<Menu />
<NLayout>
<SiderBar />
{this.modelMenuTagSwitch ? <MenuTag /> : ''}
<NLayoutContent
class="layout-content__router-view"
nativeScrollbar={false}
{...{ id: viewScrollContainerId }}
>
<ContentWrapper />
<FooterWrapper />
</NLayoutContent>
{!this.isLock ? (
<NLayout class="layout-full" hasSider>
<Menu />
<NLayout>
<SiderBar />
{this.modelMenuTagSwitch ? <MenuTag /> : ''}
<NLayoutContent
class="layout-content__router-view"
nativeScrollbar={false}
{...{ id: viewScrollContainerId }}
>
<ContentWrapper />
<FooterWrapper />
</NLayoutContent>
</NLayout>
</NLayout>
</NLayout>
) : (
''
)}
</div>
)
},

View File

@ -21,6 +21,7 @@ import { set } from 'lodash-es'
import { zhCN, dateZhCN } from 'naive-ui' // 导入 `naive ui` 中文包
import { getCache } from '@use-utils/cache'
import { SYSTEM_DEFAULT_LOCAL } from '@/appConfig/localConfig'
import { APP_CATCH_KEY } from '@/appConfig/appConfig'
import type { Recordable } from '@/types/type-utils'
@ -109,7 +110,7 @@ export const naiveLocales = (key: string) => {
* @remak , `main.ts` , `i18n`
*/
export const getDefaultLocal = () => {
const catchLanguage = getCache('localeLanguage', 'localStorage')
const catchLanguage = getCache(APP_CATCH_KEY.localeLanguage, 'localStorage')
const locale: string =
catchLanguage !== 'no' ? catchLanguage : SYSTEM_DEFAULT_LOCAL

View File

@ -5,6 +5,8 @@ import type { App as AppType } from 'vue'
import '@/styles/base.scss'
import 'virtual:svg-icons-register' // `vite-plugin-svg-icons` 脚本, 如果不使用此插件注释即可
import 'dayjs/locale/zh-cn'
import dayjs from 'dayjs'
import App from './App'
@ -33,6 +35,8 @@ const setupTemplate = async () => {
permissionRouter()
dayjs.locale('zh-cn')
app.mount('#app')
}
@ -57,6 +61,8 @@ const setupWujieTemplate = async () => {
permissionRouter()
dayjs.locale('zh-cn')
instance.mount('#app')
}

View File

@ -24,6 +24,7 @@
import { getCache, setCache } from '@/utils/cache'
import { useSignin } from '@/store'
import { APP_CATCH_KEY } from '@/appConfig/appConfig'
import type { Router, NavigationGuardNext } from 'vue-router'
@ -42,7 +43,7 @@ export const permissionRouter = (router: Router) => {
}
beforeEach((to, from, next) => {
const token = getCache('token')
const token = getCache(APP_CATCH_KEY.token)
const route = getCache('menuKey')
const { signinCallback } = storeToRefs(useSignin())
const role = computed(() => signinCallback.value.role)

View File

@ -4,9 +4,11 @@ import { set } from 'lodash-es'
import { addClass, removeClass, colorToRgba } from '@/utils/element'
import { useI18n } from '@/locales/useI18n'
import { APP_NAIVE_UI_THEME_OVERRIDES } from '@/appConfig/designConfig'
import { useDayjs } from '@/dayjs/index'
import type { ConditionalPick } from '@/types/type-utils'
import type { SettingState } from '@/store/modules/setting/type'
import type { DayjsLocal } from '@/dayjs/type'
export const useSetting = defineStore(
'setting',
@ -15,6 +17,7 @@ export const useSetting = defineStore(
appPrimaryColor: { primaryColor },
} = __APP_CFG__ // 默认主题色
const { t, locale } = useI18n()
const { locale: dayjsLocal } = useDayjs()
const settingState = reactive<SettingState>({
drawerPlacement: 'right' as NaiveDrawerPlacement,
@ -39,6 +42,7 @@ export const useSetting = defineStore(
/** 修改当前语言 */
const updateLocale = (key: string) => {
locale(key)
dayjsLocal(key as DayjsLocal)
settingState.localeLanguage = key

View File

@ -21,8 +21,13 @@
import { isEmpty } from 'lodash-es'
import { removeCache } from '@/utils/cache'
import { useMenu } from '@/store'
import type { SigninForm, SigninCallback } from '@/store/modules/signin/type'
import type {
SigninForm,
SigninCallback,
SigninResponse,
} from '@/store/modules/signin/type'
export const useSignin = defineStore(
'signin',
@ -43,17 +48,29 @@ export const useSignin = defineStore(
*
* @remark 0: 登陆成功, 1: 登陆失败
*/
const signin = (signinForm: SigninForm) => {
if (!isEmpty(signinForm)) {
state.signinCallback = {
role: 'admin',
name: signinForm.name,
}
const signin = (signinForm: SigninForm): Promise<SigninResponse> => {
return new Promise((resolve, reject) => {
if (!isEmpty(signinForm)) {
state.signinCallback = {
role: 'admin',
name: signinForm.name,
avatar:
'https://usc1.contabostorage.com/c2e495d7890844d392e8ec0c6e5d77eb:image/longmao.jpeg',
}
return 0
} else {
return 1
}
resolve({
code: 0,
message: '登陆成功',
data: state.signinCallback,
})
} else {
reject({
code: 1,
message: '登陆失败',
data: null,
})
}
})
}
/**
@ -65,7 +82,7 @@ export const useSignin = defineStore(
window.$message.info('账号退出中...')
removeCache('all-sessionStorage')
setTimeout(() => window.location.reload(), 300)
setTimeout(() => window.location.reload())
}
return {

View File

@ -6,4 +6,11 @@ export interface SigninForm extends IUnknownObjectKey {
export interface SigninCallback extends IUnknownObjectKey {
role: string
name: string
avatar?: string
}
export interface SigninResponse extends IUnknownObjectKey {
code: number
data: SigninCallback
message: string
}

View File

@ -4,6 +4,7 @@ import { setCache } from '@/utils/cache'
import { useSpin } from '@/spin'
import { useSignin } from '@/store'
import { useI18n } from '@/locales/useI18n'
import { APP_CATCH_KEY } from '@/appConfig/appConfig'
import type { FormInst } from 'naive-ui'
@ -21,7 +22,7 @@ const Signin = defineComponent({
} = __APP_CFG__
const useSigninForm = () => ({
name: 'ray',
name: 'Ray Admin',
pwd: '123456',
})
@ -47,20 +48,24 @@ const Signin = defineComponent({
if (!valid) {
useSpin(true)
if (signin(signinForm.value) === 0) {
setTimeout(() => {
useSpin(false)
signin(signinForm.value)
.then((res) => {
if (res.code === 0) {
setTimeout(() => {
useSpin(false)
window.$message.success(`欢迎${signinForm.value.name}登陆~`)
window.$message.success(`欢迎${signinForm.value.name}登陆~`)
setCache('token', 'tokenValue')
setCache('person', signinForm.value)
setCache(APP_CATCH_KEY.token, 'tokenValue')
setCache(APP_CATCH_KEY.signin, res.data)
router.push(path)
}, 2 * 1000)
}
} else {
window.$message.error('不可以这样哟, 不可以哟')
router.push(path)
}, 2 * 1000)
}
})
.catch(() => {
window.$message.error('不可以这样哟, 不可以哟')
})
}
})
}