mirror of
https://github.com/XiaoDaiGua-Ray/ray-template.git
synced 2025-04-06 03:57:49 +08:00
v3.2.3 发布
This commit is contained in:
parent
f69be958bd
commit
d8bdfc1f66
15
CHANGELOG.md
15
CHANGELOG.md
@ -1,5 +1,20 @@
|
|||||||
# CHANGE LOG
|
# CHANGE LOG
|
||||||
|
|
||||||
|
## 3.2.3
|
||||||
|
|
||||||
|
### 特征
|
||||||
|
|
||||||
|
- 新增锁屏功能(值得注意的是,锁屏解锁后会刷新当前 RouterView 区域,因为在处于锁屏状态时,会自动销毁所有的操作页面。可以理解为是一个 v-if 操作行为)
|
||||||
|
- 新增 dayjs hook,支持国际化与切换
|
||||||
|
- 支持更多 appConfig 配置
|
||||||
|
- 调整 setupAppRoute 触发时机(现在会在 layout 渲染阶段触发)
|
||||||
|
- 补充了新的组件分包 AppComponents,存放该系统的一些组件(会与系统进行一些深度绑定,例如 AppAvatar 组件依赖系统数据)
|
||||||
|
|
||||||
|
### 补充
|
||||||
|
|
||||||
|
- 锁屏功能的设计并不理想,后期会进行破坏性更新。锁屏触发条件与管理方式目前并不理想,管理有点混乱
|
||||||
|
- 后期会考虑补充 keepAlive 功能。目前没有实现是因为该功能实现的话,需要将所有路由提升为顶层路由(这是 KeepAlive 组件限制),目前并未实现该功能。后期会在权衡后增加该功能,实现时会在 RayTransitionComponent 进行拓展补充
|
||||||
|
|
||||||
## 3.2.2
|
## 3.2.2
|
||||||
|
|
||||||
### 特征
|
### 特征
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import RayGlobalProvider from '@/components/RayGlobalProvider/index'
|
import RayGlobalProvider from '@/components/RayGlobalProvider/index'
|
||||||
import { RouterView } from 'vue-router'
|
import { RouterView } from 'vue-router'
|
||||||
import GlobalSpin from '@/spin/index'
|
import GlobalSpin from '@/spin/index'
|
||||||
|
import LockScreen from '@/components/AppComponents/AppLockScreen/index'
|
||||||
|
|
||||||
import { getCache } from '@/utils/cache'
|
import { getCache } from '@/utils/cache'
|
||||||
import { get } from 'lodash-es'
|
import { get } from 'lodash-es'
|
||||||
@ -79,6 +80,8 @@ const App = defineComponent({
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<RayGlobalProvider>
|
<RayGlobalProvider>
|
||||||
|
<LockScreen />
|
||||||
|
|
||||||
<GlobalSpin>
|
<GlobalSpin>
|
||||||
{{
|
{{
|
||||||
default: () => <RouterView />,
|
default: () => <RouterView />,
|
||||||
|
@ -76,3 +76,19 @@ export const MENU_COLLAPSED_CONFIG: MenuCollapsedConfig = {
|
|||||||
|
|
||||||
/** 是否启用菜单手风琴模式 */
|
/** 是否启用菜单手风琴模式 */
|
||||||
export const MENU_ACCORDION = false
|
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',
|
||||||
|
}
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
/** 国际化相关配置 */
|
/** 国际化相关配置 */
|
||||||
|
|
||||||
|
import type { DayjsLocal, DayjsLocalMap } from '@/dayjs/type'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* 语言包语种添加后, 需要在此文件配置语言包
|
* 语言包语种添加后, 需要在此文件配置语言包
|
||||||
@ -34,3 +36,24 @@ export const LOCAL_OPTIONS = [
|
|||||||
* 配置时应该与 LOCAL_OPTIONS 的 key 一致
|
* 配置时应该与 LOCAL_OPTIONS 的 key 一致
|
||||||
*/
|
*/
|
||||||
export const SYSTEM_DEFAULT_LOCAL = 'zh-CN'
|
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',
|
||||||
|
}
|
||||||
|
7
src/components/AppComponents/AppAvatar/index.scss
Normal file
7
src/components/AppComponents/AppAvatar/index.scss
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
.app-avatar {
|
||||||
|
cursor: var(--app-avatar-cursor);
|
||||||
|
|
||||||
|
& .app-avatar__name {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
87
src/components/AppComponents/AppAvatar/index.tsx
Normal file
87
src/components/AppComponents/AppAvatar/index.tsx
Normal 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
|
63
src/components/AppComponents/AppLockScreen/index.scss
Normal file
63
src/components/AppComponents/AppLockScreen/index.scss
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
250
src/components/AppComponents/AppLockScreen/index.tsx
Normal file
250
src/components/AppComponents/AppLockScreen/index.tsx
Normal 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} <span>{this.second}</span>
|
||||||
|
</div>
|
||||||
|
<div class="current-year">
|
||||||
|
{this.year} {this.date}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</NModal>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
export default LockScreen
|
28
src/dayjs/index.ts
Normal file
28
src/dayjs/index.ts
Normal 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
6
src/dayjs/type.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
export type DayjsLocal = 'zh-cn' | 'en'
|
||||||
|
|
||||||
|
export interface DayjsLocalMap {
|
||||||
|
'zh-CN': 'zh-cn'
|
||||||
|
'en-US': 'en'
|
||||||
|
}
|
@ -12,7 +12,7 @@ const LayoutMenu = defineComponent({
|
|||||||
const menuStore = useMenu()
|
const menuStore = useMenu()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
const { menuModelValueChange, setupAppRoutes, collapsedMenu } = menuStore
|
const { menuModelValueChange, collapsedMenu } = menuStore
|
||||||
const modelMenuKey = computed({
|
const modelMenuKey = computed({
|
||||||
get: () => menuStore.menuKey,
|
get: () => menuStore.menuKey,
|
||||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||||
@ -32,8 +32,6 @@ const LayoutMenu = defineComponent({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setupAppRoutes()
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
modelMenuKey,
|
modelMenuKey,
|
||||||
menuModelValueChange,
|
menuModelValueChange,
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
.lock-screen {
|
|
||||||
position: fixed;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
|
|
||||||
& .lock-screen__content {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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
|
|
@ -1,8 +1,14 @@
|
|||||||
|
import { useSetting, useSignin } from '@/store'
|
||||||
|
|
||||||
export const useAvatarOptions = () => [
|
export const useAvatarOptions = () => [
|
||||||
{
|
{
|
||||||
key: 'person',
|
key: 'person',
|
||||||
label: '个人信息',
|
label: '个人信息',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'lockScreen',
|
||||||
|
label: '锁定屏幕',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
type: 'divider',
|
type: 'divider',
|
||||||
key: 'd1',
|
key: 'd1',
|
||||||
@ -12,3 +18,32 @@ export const useAvatarOptions = () => [
|
|||||||
label: '退出登陆',
|
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('这个人很懒, 没做这个功能~')
|
||||||
|
}
|
||||||
|
@ -11,20 +11,21 @@
|
|||||||
|
|
||||||
import './index.scss'
|
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 RayIcon from '@/components/RayIcon/index'
|
||||||
import RayTooltipIcon from '@/components/RayTooltipIcon/index'
|
import RayTooltipIcon from '@/components/RayTooltipIcon/index'
|
||||||
import SettingDrawer from './components/SettingDrawer/index'
|
import SettingDrawer from './components/SettingDrawer/index'
|
||||||
import Breadcrumb from './components/Breadcrumb/index'
|
import Breadcrumb from './components/Breadcrumb/index'
|
||||||
import GlobalSeach from './components/GlobalSeach/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 { useSetting, useSignin } from '@/store'
|
||||||
import { LOCAL_OPTIONS } from '@/appConfig/localConfig'
|
import { LOCAL_OPTIONS } from '@/appConfig/localConfig'
|
||||||
import { useAvatarOptions } from './hook'
|
import { useAvatarOptions, avatarDropdownClick } from './hook'
|
||||||
import { getCache } from '@/utils/cache'
|
import { getCache } from '@/utils/cache'
|
||||||
import screenfull from 'screenfull'
|
import screenfull from 'screenfull'
|
||||||
import { useI18n } from '@/locales/useI18n'
|
import { useI18n } from '@/locales/useI18n'
|
||||||
|
import { APP_CATCH_KEY } from '@/appConfig/appConfig'
|
||||||
|
|
||||||
import type { IconEventMapOptions, IconEventMap } from './type'
|
import type { IconEventMapOptions, IconEventMap } from './type'
|
||||||
|
|
||||||
@ -47,7 +48,7 @@ const SiderBar = defineComponent({
|
|||||||
|
|
||||||
const { drawerPlacement, breadcrumbSwitch } = storeToRefs(settingStore)
|
const { drawerPlacement, breadcrumbSwitch } = storeToRefs(settingStore)
|
||||||
const showSettings = ref(false)
|
const showSettings = ref(false)
|
||||||
const person = getCache('person')
|
const signin = getCache(APP_CATCH_KEY.signin)
|
||||||
const spaceItemStyle = {
|
const spaceItemStyle = {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
}
|
}
|
||||||
@ -75,12 +76,6 @@ const SiderBar = defineComponent({
|
|||||||
tooltip: t('headerTooltip.Search'),
|
tooltip: t('headerTooltip.Search'),
|
||||||
eventKey: 'search',
|
eventKey: 'search',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: 'lock',
|
|
||||||
size: 18,
|
|
||||||
tooltip: t('headerTooltip.Lock'),
|
|
||||||
eventKey: 'lock',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'fullscreen',
|
name: 'fullscreen',
|
||||||
size: 18,
|
size: 18,
|
||||||
@ -131,22 +126,6 @@ const SiderBar = defineComponent({
|
|||||||
iconEventMap[key]?.()
|
iconEventMap[key]?.()
|
||||||
}
|
}
|
||||||
|
|
||||||
const handlePersonSelect = (key: string | number) => {
|
|
||||||
if (key === 'logout') {
|
|
||||||
window.$dialog.warning({
|
|
||||||
title: '提示',
|
|
||||||
content: '您确定要退出登录吗',
|
|
||||||
positiveText: '确定',
|
|
||||||
negativeText: '不确定',
|
|
||||||
onPositiveClick: () => {
|
|
||||||
logout()
|
|
||||||
},
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
window.$message.info('这个人很懒, 没做这个功能~')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
leftIconOptions,
|
leftIconOptions,
|
||||||
rightTooltipIconOptions,
|
rightTooltipIconOptions,
|
||||||
@ -154,8 +133,7 @@ const SiderBar = defineComponent({
|
|||||||
handleIconClick,
|
handleIconClick,
|
||||||
showSettings,
|
showSettings,
|
||||||
updateLocale,
|
updateLocale,
|
||||||
handlePersonSelect,
|
signin,
|
||||||
person,
|
|
||||||
spaceItemStyle,
|
spaceItemStyle,
|
||||||
drawerPlacement,
|
drawerPlacement,
|
||||||
breadcrumbSwitch,
|
breadcrumbSwitch,
|
||||||
@ -166,7 +144,6 @@ const SiderBar = defineComponent({
|
|||||||
return (
|
return (
|
||||||
<NLayoutHeader class="layout-header" bordered>
|
<NLayoutHeader class="layout-header" bordered>
|
||||||
<GlobalSeach v-model:show={this.globalSearchShown} />
|
<GlobalSeach v-model:show={this.globalSearchShown} />
|
||||||
<LockScreen />
|
|
||||||
<NSpace
|
<NSpace
|
||||||
class="layout-header__method"
|
class="layout-header__method"
|
||||||
align="center"
|
align="center"
|
||||||
@ -221,21 +198,10 @@ const SiderBar = defineComponent({
|
|||||||
</NDropdown>
|
</NDropdown>
|
||||||
<NDropdown
|
<NDropdown
|
||||||
options={useAvatarOptions()}
|
options={useAvatarOptions()}
|
||||||
onSelect={this.handlePersonSelect.bind(this)}
|
onSelect={avatarDropdownClick.bind(this)}
|
||||||
trigger="click"
|
trigger="click"
|
||||||
>
|
>
|
||||||
<NTag checkable size="large">
|
<AppAvatar avatarSize="small" align="center" cursor="pointer" />
|
||||||
{{
|
|
||||||
icon: () => (
|
|
||||||
<RayIcon
|
|
||||||
customClassName="layout-header__method--icon"
|
|
||||||
name="ray"
|
|
||||||
size="18"
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
default: () => this.person.name,
|
|
||||||
}}
|
|
||||||
</NTag>
|
|
||||||
</NDropdown>
|
</NDropdown>
|
||||||
</NSpace>
|
</NSpace>
|
||||||
</NSpace>
|
</NSpace>
|
||||||
|
@ -15,16 +15,18 @@ import MenuTag from './components/MenuTag/index'
|
|||||||
import ContentWrapper from '@/layout/default/ContentWrapper'
|
import ContentWrapper from '@/layout/default/ContentWrapper'
|
||||||
import FooterWrapper from '@/layout/default/FooterWrapper'
|
import FooterWrapper from '@/layout/default/FooterWrapper'
|
||||||
|
|
||||||
import { useSetting } from '@/store'
|
import { useSetting, useMenu } from '@/store'
|
||||||
import { viewScrollContainerId } from '@/appConfig/routerConfig'
|
import { viewScrollContainerId } from '@/appConfig/routerConfig'
|
||||||
|
|
||||||
const Layout = defineComponent({
|
const Layout = defineComponent({
|
||||||
name: 'Layout',
|
name: 'Layout',
|
||||||
setup() {
|
setup() {
|
||||||
const settingStore = useSetting()
|
const settingStore = useSetting()
|
||||||
|
const menuStore = useMenu()
|
||||||
|
|
||||||
const { height: windowHeight } = useWindowSize()
|
const { height: windowHeight } = useWindowSize()
|
||||||
const { menuTagSwitch: modelMenuTagSwitch } = storeToRefs(settingStore)
|
const { menuTagSwitch: modelMenuTagSwitch } = storeToRefs(settingStore)
|
||||||
|
const { setupAppRoutes } = menuStore
|
||||||
const cssVarsRef = computed(() => {
|
const cssVarsRef = computed(() => {
|
||||||
let cssVar = {}
|
let cssVar = {}
|
||||||
|
|
||||||
@ -40,11 +42,17 @@ const Layout = defineComponent({
|
|||||||
|
|
||||||
return cssVar
|
return cssVar
|
||||||
})
|
})
|
||||||
|
const isLock = useStorage('isLockScreen', false, sessionStorage, {
|
||||||
|
mergeDefaults: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
setupAppRoutes()
|
||||||
|
|
||||||
return {
|
return {
|
||||||
windowHeight,
|
windowHeight,
|
||||||
modelMenuTagSwitch,
|
modelMenuTagSwitch,
|
||||||
cssVarsRef,
|
cssVarsRef,
|
||||||
|
isLock,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
render() {
|
render() {
|
||||||
@ -53,21 +61,25 @@ const Layout = defineComponent({
|
|||||||
class={['layout']}
|
class={['layout']}
|
||||||
style={[`height: ${this.windowHeight}px`, this.cssVarsRef]}
|
style={[`height: ${this.windowHeight}px`, this.cssVarsRef]}
|
||||||
>
|
>
|
||||||
<NLayout class="layout-full" hasSider>
|
{!this.isLock ? (
|
||||||
<Menu />
|
<NLayout class="layout-full" hasSider>
|
||||||
<NLayout>
|
<Menu />
|
||||||
<SiderBar />
|
<NLayout>
|
||||||
{this.modelMenuTagSwitch ? <MenuTag /> : ''}
|
<SiderBar />
|
||||||
<NLayoutContent
|
{this.modelMenuTagSwitch ? <MenuTag /> : ''}
|
||||||
class="layout-content__router-view"
|
<NLayoutContent
|
||||||
nativeScrollbar={false}
|
class="layout-content__router-view"
|
||||||
{...{ id: viewScrollContainerId }}
|
nativeScrollbar={false}
|
||||||
>
|
{...{ id: viewScrollContainerId }}
|
||||||
<ContentWrapper />
|
>
|
||||||
<FooterWrapper />
|
<ContentWrapper />
|
||||||
</NLayoutContent>
|
<FooterWrapper />
|
||||||
|
</NLayoutContent>
|
||||||
|
</NLayout>
|
||||||
</NLayout>
|
</NLayout>
|
||||||
</NLayout>
|
) : (
|
||||||
|
''
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
@ -21,6 +21,7 @@ import { set } from 'lodash-es'
|
|||||||
import { zhCN, dateZhCN } from 'naive-ui' // 导入 `naive ui` 中文包
|
import { zhCN, dateZhCN } from 'naive-ui' // 导入 `naive ui` 中文包
|
||||||
import { getCache } from '@use-utils/cache'
|
import { getCache } from '@use-utils/cache'
|
||||||
import { SYSTEM_DEFAULT_LOCAL } from '@/appConfig/localConfig'
|
import { SYSTEM_DEFAULT_LOCAL } from '@/appConfig/localConfig'
|
||||||
|
import { APP_CATCH_KEY } from '@/appConfig/appConfig'
|
||||||
|
|
||||||
import type { Recordable } from '@/types/type-utils'
|
import type { Recordable } from '@/types/type-utils'
|
||||||
|
|
||||||
@ -109,7 +110,7 @@ export const naiveLocales = (key: string) => {
|
|||||||
* @remak 未避免出现加载语言错误问题, 故而在 `main.ts` 注册时, 应优先加载 `i18n` 避免出现该问题
|
* @remak 未避免出现加载语言错误问题, 故而在 `main.ts` 注册时, 应优先加载 `i18n` 避免出现该问题
|
||||||
*/
|
*/
|
||||||
export const getDefaultLocal = () => {
|
export const getDefaultLocal = () => {
|
||||||
const catchLanguage = getCache('localeLanguage', 'localStorage')
|
const catchLanguage = getCache(APP_CATCH_KEY.localeLanguage, 'localStorage')
|
||||||
|
|
||||||
const locale: string =
|
const locale: string =
|
||||||
catchLanguage !== 'no' ? catchLanguage : SYSTEM_DEFAULT_LOCAL
|
catchLanguage !== 'no' ? catchLanguage : SYSTEM_DEFAULT_LOCAL
|
||||||
|
@ -5,6 +5,8 @@ import type { App as AppType } from 'vue'
|
|||||||
import '@/styles/base.scss'
|
import '@/styles/base.scss'
|
||||||
|
|
||||||
import 'virtual:svg-icons-register' // `vite-plugin-svg-icons` 脚本, 如果不使用此插件注释即可
|
import 'virtual:svg-icons-register' // `vite-plugin-svg-icons` 脚本, 如果不使用此插件注释即可
|
||||||
|
import 'dayjs/locale/zh-cn'
|
||||||
|
import dayjs from 'dayjs'
|
||||||
|
|
||||||
import App from './App'
|
import App from './App'
|
||||||
|
|
||||||
@ -33,6 +35,8 @@ const setupTemplate = async () => {
|
|||||||
|
|
||||||
permissionRouter()
|
permissionRouter()
|
||||||
|
|
||||||
|
dayjs.locale('zh-cn')
|
||||||
|
|
||||||
app.mount('#app')
|
app.mount('#app')
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,6 +61,8 @@ const setupWujieTemplate = async () => {
|
|||||||
|
|
||||||
permissionRouter()
|
permissionRouter()
|
||||||
|
|
||||||
|
dayjs.locale('zh-cn')
|
||||||
|
|
||||||
instance.mount('#app')
|
instance.mount('#app')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
import { getCache, setCache } from '@/utils/cache'
|
import { getCache, setCache } from '@/utils/cache'
|
||||||
import { useSignin } from '@/store'
|
import { useSignin } from '@/store'
|
||||||
|
import { APP_CATCH_KEY } from '@/appConfig/appConfig'
|
||||||
|
|
||||||
import type { Router, NavigationGuardNext } from 'vue-router'
|
import type { Router, NavigationGuardNext } from 'vue-router'
|
||||||
|
|
||||||
@ -42,7 +43,7 @@ export const permissionRouter = (router: Router) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
beforeEach((to, from, next) => {
|
beforeEach((to, from, next) => {
|
||||||
const token = getCache('token')
|
const token = getCache(APP_CATCH_KEY.token)
|
||||||
const route = getCache('menuKey')
|
const route = getCache('menuKey')
|
||||||
const { signinCallback } = storeToRefs(useSignin())
|
const { signinCallback } = storeToRefs(useSignin())
|
||||||
const role = computed(() => signinCallback.value.role)
|
const role = computed(() => signinCallback.value.role)
|
||||||
|
@ -4,9 +4,11 @@ import { set } from 'lodash-es'
|
|||||||
import { addClass, removeClass, colorToRgba } from '@/utils/element'
|
import { addClass, removeClass, colorToRgba } from '@/utils/element'
|
||||||
import { useI18n } from '@/locales/useI18n'
|
import { useI18n } from '@/locales/useI18n'
|
||||||
import { APP_NAIVE_UI_THEME_OVERRIDES } from '@/appConfig/designConfig'
|
import { APP_NAIVE_UI_THEME_OVERRIDES } from '@/appConfig/designConfig'
|
||||||
|
import { useDayjs } from '@/dayjs/index'
|
||||||
|
|
||||||
import type { ConditionalPick } from '@/types/type-utils'
|
import type { ConditionalPick } from '@/types/type-utils'
|
||||||
import type { SettingState } from '@/store/modules/setting/type'
|
import type { SettingState } from '@/store/modules/setting/type'
|
||||||
|
import type { DayjsLocal } from '@/dayjs/type'
|
||||||
|
|
||||||
export const useSetting = defineStore(
|
export const useSetting = defineStore(
|
||||||
'setting',
|
'setting',
|
||||||
@ -15,6 +17,7 @@ export const useSetting = defineStore(
|
|||||||
appPrimaryColor: { primaryColor },
|
appPrimaryColor: { primaryColor },
|
||||||
} = __APP_CFG__ // 默认主题色
|
} = __APP_CFG__ // 默认主题色
|
||||||
const { t, locale } = useI18n()
|
const { t, locale } = useI18n()
|
||||||
|
const { locale: dayjsLocal } = useDayjs()
|
||||||
|
|
||||||
const settingState = reactive<SettingState>({
|
const settingState = reactive<SettingState>({
|
||||||
drawerPlacement: 'right' as NaiveDrawerPlacement,
|
drawerPlacement: 'right' as NaiveDrawerPlacement,
|
||||||
@ -39,6 +42,7 @@ export const useSetting = defineStore(
|
|||||||
/** 修改当前语言 */
|
/** 修改当前语言 */
|
||||||
const updateLocale = (key: string) => {
|
const updateLocale = (key: string) => {
|
||||||
locale(key)
|
locale(key)
|
||||||
|
dayjsLocal(key as DayjsLocal)
|
||||||
|
|
||||||
settingState.localeLanguage = key
|
settingState.localeLanguage = key
|
||||||
|
|
||||||
|
@ -21,8 +21,13 @@
|
|||||||
|
|
||||||
import { isEmpty } from 'lodash-es'
|
import { isEmpty } from 'lodash-es'
|
||||||
import { removeCache } from '@/utils/cache'
|
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(
|
export const useSignin = defineStore(
|
||||||
'signin',
|
'signin',
|
||||||
@ -43,17 +48,29 @@ export const useSignin = defineStore(
|
|||||||
*
|
*
|
||||||
* @remark 0: 登陆成功, 1: 登陆失败
|
* @remark 0: 登陆成功, 1: 登陆失败
|
||||||
*/
|
*/
|
||||||
const signin = (signinForm: SigninForm) => {
|
const signin = (signinForm: SigninForm): Promise<SigninResponse> => {
|
||||||
if (!isEmpty(signinForm)) {
|
return new Promise((resolve, reject) => {
|
||||||
state.signinCallback = {
|
if (!isEmpty(signinForm)) {
|
||||||
role: 'admin',
|
state.signinCallback = {
|
||||||
name: signinForm.name,
|
role: 'admin',
|
||||||
}
|
name: signinForm.name,
|
||||||
|
avatar:
|
||||||
|
'https://usc1.contabostorage.com/c2e495d7890844d392e8ec0c6e5d77eb:image/longmao.jpeg',
|
||||||
|
}
|
||||||
|
|
||||||
return 0
|
resolve({
|
||||||
} else {
|
code: 0,
|
||||||
return 1
|
message: '登陆成功',
|
||||||
}
|
data: state.signinCallback,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
reject({
|
||||||
|
code: 1,
|
||||||
|
message: '登陆失败',
|
||||||
|
data: null,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -65,7 +82,7 @@ export const useSignin = defineStore(
|
|||||||
window.$message.info('账号退出中...')
|
window.$message.info('账号退出中...')
|
||||||
removeCache('all-sessionStorage')
|
removeCache('all-sessionStorage')
|
||||||
|
|
||||||
setTimeout(() => window.location.reload(), 300)
|
setTimeout(() => window.location.reload())
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -6,4 +6,11 @@ export interface SigninForm extends IUnknownObjectKey {
|
|||||||
export interface SigninCallback extends IUnknownObjectKey {
|
export interface SigninCallback extends IUnknownObjectKey {
|
||||||
role: string
|
role: string
|
||||||
name: string
|
name: string
|
||||||
|
avatar?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SigninResponse extends IUnknownObjectKey {
|
||||||
|
code: number
|
||||||
|
data: SigninCallback
|
||||||
|
message: string
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import { setCache } from '@/utils/cache'
|
|||||||
import { useSpin } from '@/spin'
|
import { useSpin } from '@/spin'
|
||||||
import { useSignin } from '@/store'
|
import { useSignin } from '@/store'
|
||||||
import { useI18n } from '@/locales/useI18n'
|
import { useI18n } from '@/locales/useI18n'
|
||||||
|
import { APP_CATCH_KEY } from '@/appConfig/appConfig'
|
||||||
|
|
||||||
import type { FormInst } from 'naive-ui'
|
import type { FormInst } from 'naive-ui'
|
||||||
|
|
||||||
@ -21,7 +22,7 @@ const Signin = defineComponent({
|
|||||||
} = __APP_CFG__
|
} = __APP_CFG__
|
||||||
|
|
||||||
const useSigninForm = () => ({
|
const useSigninForm = () => ({
|
||||||
name: 'ray',
|
name: 'Ray Admin',
|
||||||
pwd: '123456',
|
pwd: '123456',
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -47,20 +48,24 @@ const Signin = defineComponent({
|
|||||||
if (!valid) {
|
if (!valid) {
|
||||||
useSpin(true)
|
useSpin(true)
|
||||||
|
|
||||||
if (signin(signinForm.value) === 0) {
|
signin(signinForm.value)
|
||||||
setTimeout(() => {
|
.then((res) => {
|
||||||
useSpin(false)
|
if (res.code === 0) {
|
||||||
|
setTimeout(() => {
|
||||||
|
useSpin(false)
|
||||||
|
|
||||||
window.$message.success(`欢迎${signinForm.value.name}登陆~`)
|
window.$message.success(`欢迎${signinForm.value.name}登陆~`)
|
||||||
|
|
||||||
setCache('token', 'tokenValue')
|
setCache(APP_CATCH_KEY.token, 'tokenValue')
|
||||||
setCache('person', signinForm.value)
|
setCache(APP_CATCH_KEY.signin, res.data)
|
||||||
|
|
||||||
router.push(path)
|
router.push(path)
|
||||||
}, 2 * 1000)
|
}, 2 * 1000)
|
||||||
}
|
}
|
||||||
} else {
|
})
|
||||||
window.$message.error('不可以这样哟, 不可以哟')
|
.catch(() => {
|
||||||
|
window.$message.error('不可以这样哟, 不可以哟')
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user