wip: 迁移 v3-admin v3.1.3 版本代码
This commit is contained in:
6
src/views/dashboard/admin/index.vue
Normal file
6
src/views/dashboard/admin/index.vue
Normal file
@@ -0,0 +1,6 @@
|
||||
<!-- admin 权限主页 -->
|
||||
<template>
|
||||
<div class="app-container">
|
||||
Admin 权限可见
|
||||
</div>
|
||||
</template>
|
||||
6
src/views/dashboard/editor/index.vue
Normal file
6
src/views/dashboard/editor/index.vue
Normal file
@@ -0,0 +1,6 @@
|
||||
<!-- editor 权限主页 -->
|
||||
<template>
|
||||
<div class="app-container">
|
||||
Editor 权限可见
|
||||
</div>
|
||||
</template>
|
||||
20
src/views/dashboard/index.vue
Normal file
20
src/views/dashboard/index.vue
Normal file
@@ -0,0 +1,20 @@
|
||||
<template>
|
||||
<component :is="currentRole === 'admin' ? AdminDashboard : EditorDashboard" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useUserStore } from '@/store/modules/user'
|
||||
import { computed, onBeforeMount, ref } from 'vue'
|
||||
import AdminDashboard from './admin/index.vue'
|
||||
import EditorDashboard from './editor/index.vue'
|
||||
|
||||
const currentRole = ref('admin')
|
||||
const roles = computed(() => {
|
||||
return useUserStore().roles
|
||||
})
|
||||
onBeforeMount(() => {
|
||||
if (!roles.value.includes('admin')) {
|
||||
currentRole.value = 'editor'
|
||||
}
|
||||
})
|
||||
</script>
|
||||
10
src/views/error-page/401.vue
Normal file
10
src/views/error-page/401.vue
Normal file
@@ -0,0 +1,10 @@
|
||||
<template>
|
||||
<div>
|
||||
<p style="text-align: center; font-size: 140px; margin-bottom: 50px">
|
||||
401
|
||||
</p>
|
||||
<p style="text-align: center; font-size: 40px">
|
||||
你没有权限去该页面
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
10
src/views/error-page/404.vue
Normal file
10
src/views/error-page/404.vue
Normal file
@@ -0,0 +1,10 @@
|
||||
<template>
|
||||
<div>
|
||||
<p style="text-align: center; font-size: 140px; margin-bottom: 50px">
|
||||
404
|
||||
</p>
|
||||
<p style="text-align: center; font-size: 40px">
|
||||
未找到你想要的页面
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
220
src/views/login/index.vue
Normal file
220
src/views/login/index.vue
Normal file
@@ -0,0 +1,220 @@
|
||||
<template>
|
||||
<div class="login-container">
|
||||
<ThemeSwitch class="theme-switch" />
|
||||
<div class="login-card">
|
||||
<div class="title">
|
||||
<img src="@/assets/layout/logo-text-2.png">
|
||||
</div>
|
||||
<div class="content">
|
||||
<el-form ref="loginFormDom" :model="loginForm" :rules="loginRules" @keyup.enter="handleLogin">
|
||||
<el-form-item prop="username">
|
||||
<el-input
|
||||
v-model="loginForm.username"
|
||||
placeholder="用户名"
|
||||
type="text"
|
||||
tabindex="1"
|
||||
:prefix-icon="User"
|
||||
size="large"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item prop="password">
|
||||
<el-input
|
||||
v-model="loginForm.password"
|
||||
placeholder="密码"
|
||||
type="password"
|
||||
tabindex="2"
|
||||
:prefix-icon="Lock"
|
||||
size="large"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item prop="code">
|
||||
<el-input
|
||||
v-model="loginForm.code"
|
||||
placeholder="验证码"
|
||||
type="text"
|
||||
tabindex="3"
|
||||
:prefix-icon="Key"
|
||||
maxlength="4"
|
||||
size="large"
|
||||
/>
|
||||
<span class="show-code">
|
||||
<img :src="codeUrl" @click="createCode">
|
||||
</span>
|
||||
</el-form-item>
|
||||
<el-button :loading="loading" type="primary" size="large" @click.prevent="handleLogin">
|
||||
登 录
|
||||
</el-button>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import { useUserStore } from '@/store/modules/user'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { User, Lock, Key } from '@element-plus/icons-vue'
|
||||
import ThemeSwitch from '@/components/ThemeSwitch/index.vue'
|
||||
|
||||
interface ILoginForm {
|
||||
/** admin 或 editor */
|
||||
username: string
|
||||
/** 密码 */
|
||||
password: string
|
||||
/** 验证码 */
|
||||
code: string
|
||||
/** 随机数 */
|
||||
codeToken: string
|
||||
}
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
const loading = ref<boolean>(false)
|
||||
const loginFormDom = ref<any>()
|
||||
const codeUrl = ref<string>('')
|
||||
const loginForm = reactive<ILoginForm>({
|
||||
username: 'admin',
|
||||
password: '123456',
|
||||
code: '1234',
|
||||
codeToken: ''
|
||||
})
|
||||
const loginRules = reactive({
|
||||
username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
|
||||
password: [
|
||||
{ required: true, message: '请输入密码', trigger: 'blur' },
|
||||
{ min: 6, max: 18, message: '长度在 6 到 18 个字符', trigger: 'blur' }
|
||||
],
|
||||
code: [{ required: true, message: '请输入验证码', trigger: 'blur' }]
|
||||
})
|
||||
const handleLogin = () => {
|
||||
loginFormDom.value.validate((valid: boolean) => {
|
||||
if (valid) {
|
||||
loading.value = true
|
||||
useUserStore()
|
||||
.login({
|
||||
username: loginForm.username,
|
||||
password: loginForm.password
|
||||
})
|
||||
.then(() => {
|
||||
loading.value = false
|
||||
router.push({ path: '/' }).catch((err) => {
|
||||
console.warn(err)
|
||||
})
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false
|
||||
createCode()
|
||||
})
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
})
|
||||
}
|
||||
/** 创建验证码 */
|
||||
const createCode: () => void = () => {
|
||||
// 先清空验证码的输入
|
||||
loginForm.code = ''
|
||||
let codeToken = ''
|
||||
const codeLength = 12
|
||||
// 随机数
|
||||
const random: Array<number | string> = [
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
'A',
|
||||
'B',
|
||||
'C',
|
||||
'D',
|
||||
'E',
|
||||
'F',
|
||||
'G',
|
||||
'H',
|
||||
'I',
|
||||
'J',
|
||||
'K',
|
||||
'L',
|
||||
'M',
|
||||
'N',
|
||||
'O',
|
||||
'P',
|
||||
'Q',
|
||||
'R',
|
||||
'S',
|
||||
'T',
|
||||
'U',
|
||||
'V',
|
||||
'W',
|
||||
'X',
|
||||
'Y',
|
||||
'Z'
|
||||
]
|
||||
for (let i = 0; i < codeLength; i++) {
|
||||
const index = Math.floor(Math.random() * 36)
|
||||
codeToken += random[index]
|
||||
}
|
||||
loginForm.codeToken = codeToken
|
||||
// 实际开发中,可替换成自己的地址,这里只是提供一个参考
|
||||
codeUrl.value = `/api/v1/login/authcode?token=${codeToken}`
|
||||
}
|
||||
// 需要验证码的时候,需打开下方注释
|
||||
// createCode()
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.login-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
min-height: 100%;
|
||||
.theme-switch {
|
||||
position: fixed;
|
||||
top: 5%;
|
||||
right: 5%;
|
||||
cursor: pointer;
|
||||
}
|
||||
.login-card {
|
||||
width: 480px;
|
||||
border-radius: 20px;
|
||||
box-shadow: 0 0 10px #dcdfe6;
|
||||
background-color: #fff;
|
||||
overflow: hidden;
|
||||
.title {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 150px;
|
||||
img {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.content {
|
||||
padding: 20px 50px 50px 50px;
|
||||
.show-code {
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
top: 0px;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
img {
|
||||
width: 100px;
|
||||
height: 40px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
.el-button {
|
||||
width: 100%;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
29
src/views/permission/components/switch-roles.vue
Normal file
29
src/views/permission/components/switch-roles.vue
Normal file
@@ -0,0 +1,29 @@
|
||||
<!-- 切换角色 -->
|
||||
<template>
|
||||
<div>
|
||||
<div style="margin-bottom: 15px">
|
||||
你的权限:{{ roles }}
|
||||
</div>
|
||||
<div style="display: flex; align-items: center">
|
||||
<span>切换权限:</span>
|
||||
<el-radio-group v-model="currentRole">
|
||||
<el-radio-button label="editor" />
|
||||
<el-radio-button label="admin" />
|
||||
</el-radio-group>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useUserStore } from '@/store/modules/user'
|
||||
import { computed, ref, watch } from 'vue'
|
||||
|
||||
const userStore = useUserStore()
|
||||
const emit = defineEmits(['change'])
|
||||
const roles = computed(() => userStore.roles)
|
||||
const currentRole = ref(roles.value[0])
|
||||
watch(currentRole, async(value) => {
|
||||
await userStore.changeRoles(value)
|
||||
emit('change')
|
||||
})
|
||||
</script>
|
||||
92
src/views/permission/directive.vue
Normal file
92
src/views/permission/directive.vue
Normal file
@@ -0,0 +1,92 @@
|
||||
<!-- 指令权限、权限判断函数的使用 -->
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<SwitchRoles @change="state.handleRolesChange" />
|
||||
<div :key="state.key" style="margin-top: 30px">
|
||||
<div>
|
||||
<span v-permission="['admin']" class="permission-alert">
|
||||
只有
|
||||
<el-tag>admin</el-tag>可以看见这个
|
||||
</span>
|
||||
<el-tag v-permission="['admin']" class="permission-sourceCode" type="info" size="large">
|
||||
v-permission="['admin']"
|
||||
</el-tag>
|
||||
</div>
|
||||
<div>
|
||||
<span v-permission="['editor']" class="permission-alert">
|
||||
只有
|
||||
<el-tag>editor</el-tag>可以看见这个
|
||||
</span>
|
||||
<el-tag v-permission="['editor']" class="permission-sourceCode" type="info" size="large">
|
||||
v-permission="['editor']"
|
||||
</el-tag>
|
||||
</div>
|
||||
<div>
|
||||
<span v-permission="['admin', 'editor']" class="permission-alert">
|
||||
两者
|
||||
<el-tag>admin</el-tag>和 <el-tag>editor</el-tag>都可以看见这个
|
||||
</span>
|
||||
<el-tag v-permission="['admin', 'editor']" class="permission-sourceCode" type="info" size="large">
|
||||
v-permission="['admin', 'editor']"
|
||||
</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
<div :key="'checkPermission' + state.key" style="margin-top: 60px">
|
||||
<el-tag type="info" size="large">
|
||||
在某些情况下,不适合使用 v-permission。例如:element-plus 的 el-tab 或 el-table-column 以及其它动态渲染 dom
|
||||
的场景。你只能通过手动设置 v-if 来实现。
|
||||
</el-tag>
|
||||
<el-tabs type="border-card" style="width: 550px; margin-top: 60px">
|
||||
<el-tab-pane v-if="checkPermission(['admin'])" label="admin">
|
||||
admin 可以看见这个
|
||||
<el-tag class="permission-sourceCode" type="info">
|
||||
v-if="checkPermission(['admin'])"
|
||||
</el-tag>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane v-if="checkPermission(['editor'])" label="editor">
|
||||
editor 可以看见这个
|
||||
<el-tag class="permission-sourceCode" type="info">
|
||||
v-if="checkPermission(['editor'])"
|
||||
</el-tag>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane v-if="checkPermission(['admin', 'editor'])" label="admin 和 editor">
|
||||
两者 admin 和 editor 都可以看见这个
|
||||
<el-tag class="permission-sourceCode" type="info">
|
||||
v-if="checkPermission(['admin', 'editor'])"
|
||||
</el-tag>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive } from 'vue'
|
||||
import { checkPermission } from '@/utils/permission' // 权限判断函数
|
||||
import SwitchRoles from './components/switch-roles.vue'
|
||||
|
||||
const state = reactive({
|
||||
key: 1,
|
||||
handleRolesChange: () => {
|
||||
state.key++
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.permission-alert {
|
||||
width: 320px;
|
||||
margin-top: 15px;
|
||||
background-color: #f0f9eb;
|
||||
color: #67c23a;
|
||||
padding: 8px 16px;
|
||||
border-radius: 4px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.permission-sourceCode {
|
||||
margin-left: 15px;
|
||||
}
|
||||
</style>
|
||||
21
src/views/permission/page.vue
Normal file
21
src/views/permission/page.vue
Normal file
@@ -0,0 +1,21 @@
|
||||
<!-- 页面权限测试页 -->
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-tag type="success" size="large" style="margin-bottom: 15px">
|
||||
当前页面只有 admin 权限可见
|
||||
</el-tag>
|
||||
<SwitchRoles @change="handleRolesChange" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useRouter } from 'vue-router'
|
||||
import SwitchRoles from './components/switch-roles.vue'
|
||||
|
||||
const router = useRouter()
|
||||
const handleRolesChange = () => {
|
||||
router.push({ path: '/401' }).catch((err) => {
|
||||
console.warn(err)
|
||||
})
|
||||
}
|
||||
</script>
|
||||
16
src/views/redirect/index.vue
Normal file
16
src/views/redirect/index.vue
Normal file
@@ -0,0 +1,16 @@
|
||||
<!-- 重定向 -->
|
||||
<template>
|
||||
<div />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
|
||||
const { params, query } = useRoute()
|
||||
const { path } = params
|
||||
useRouter()
|
||||
.replace({ path: '/' + path, query })
|
||||
.catch((err) => {
|
||||
console.warn(err)
|
||||
})
|
||||
</script>
|
||||
Reference in New Issue
Block a user