mirror of
https://github.com/chansee97/nova-admin.git
synced 2026-07-15 15:51:19 +08:00
Compare commits
No commits in common. "44ebd5f19ea1501b20110e4af17f89eb23fefc29" and "a5c3697a6b46d3c9c4ed6aaea54cf5ca78f283dc" have entirely different histories.
44ebd5f19e
...
a5c3697a6b
@ -24,7 +24,7 @@
|
||||
|
||||
## Features
|
||||
|
||||
- Developed based on the latest technology stack including Vue3, Vite6, TypeScript, NaiveUI, Unocss, etc.
|
||||
- Developed based on the latest technology stack including Vue3, Vite5, TypeScript, NaiveUI, Unocss, etc.
|
||||
- Based on [alova](https://alova.js.org/) encapsulation and configuration, providing unified response handling and multi-scenario capabilities.
|
||||
- Comprehensive front-end and back-end permission management solution.
|
||||
- Supports local static routes and dynamically generated routes from the back end, with easy route configuration.
|
||||
@ -55,7 +55,7 @@ This project uses ApiFox for interface mock, check the online documentation for
|
||||
|
||||
## Install and use
|
||||
|
||||
The local development environment is recommended to use pnpm 10.x, Node.js version 21.x.
|
||||
The local development environment is recommended to use pnpm 8.x, Node.js must be version 20.x.
|
||||
|
||||
It is recommended to directly download the compressed package from [Releases](https://github.com/chansee97/nova-admin/releases)
|
||||
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
|
||||
## 特性
|
||||
|
||||
- 基于Vue3、Vite6、TypeScript、NaiveUI、Unocss等最新技术栈开发
|
||||
- 基于Vue3、Vite5、TypeScript、NaiveUI、Unocss等最新技术栈开发
|
||||
- 基于[alova](https://alova.js.org/)封装和配置,提供统一的响应处理和多场景能力
|
||||
- 完善的前后端权限管理方案
|
||||
- 支持本地静态路由和后台返回动态路由,路由简单易配置
|
||||
@ -55,7 +55,7 @@
|
||||
|
||||
## 安装使用
|
||||
|
||||
本地开发环境建议使用 pnpm 10.x 、Node.js 21.x
|
||||
本地开发环境建议使用 pnpm 8.x 、Node.js 必须 20.x
|
||||
|
||||
推荐直接下载[Releases](https://github.com/chansee97/nova-admin/releases)压缩包
|
||||
|
||||
|
||||
21
package.json
21
package.json
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "nova-admin",
|
||||
"type": "module",
|
||||
"version": "0.9.13",
|
||||
"version": "0.9.12",
|
||||
"private": true,
|
||||
"description": "a clean and concise back-end management template based on Vue3, Vite5, Typescript, and Naive UI.",
|
||||
"author": {
|
||||
@ -50,29 +50,29 @@
|
||||
"sizecheck": "npx vite-bundle-visualizer"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vueuse/core": "^13.1.0",
|
||||
"@vueuse/core": "^13.0.0",
|
||||
"alova": "^3.2.10",
|
||||
"colord": "^2.9.3",
|
||||
"echarts": "^5.6.0",
|
||||
"md-editor-v3": "^5.4.5",
|
||||
"pinia": "^3.0.2",
|
||||
"pinia": "^3.0.1",
|
||||
"pinia-plugin-persistedstate": "^4.2.0",
|
||||
"quill": "^2.0.3",
|
||||
"radash": "^12.1.0",
|
||||
"vue": "^3.5.13",
|
||||
"vue-draggable-plus": "^0.6.0",
|
||||
"vue-i18n": "^11.1.3",
|
||||
"vue-i18n": "^11.1.2",
|
||||
"vue-router": "^4.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config": "^4.12.0",
|
||||
"@antfu/eslint-config": "^4.11.0",
|
||||
"@iconify-json/icon-park-outline": "^1.2.2",
|
||||
"@iconify/vue": "^4.3.0",
|
||||
"@types/node": "^22.14.1",
|
||||
"@types/node": "^22.14.0",
|
||||
"@vitejs/plugin-vue": "^5.2.3",
|
||||
"@vitejs/plugin-vue-jsx": "^4.1.2",
|
||||
"eslint": "^9.24.0",
|
||||
"lint-staged": "^15.5.1",
|
||||
"lint-staged": "^15.5.0",
|
||||
"naive-ui": "^2.41.0",
|
||||
"sass": "^1.86.3",
|
||||
"simple-git-hooks": "^2.12.1",
|
||||
@ -80,8 +80,8 @@
|
||||
"unocss": "^0.65.4",
|
||||
"unplugin-auto-import": "^19.1.2",
|
||||
"unplugin-icons": "^22.1.0",
|
||||
"unplugin-vue-components": "^28.5.0",
|
||||
"vite": "^6.2.6",
|
||||
"unplugin-vue-components": "^28.4.1",
|
||||
"vite": "^6.2.5",
|
||||
"vite-bundle-visualizer": "^1.2.1",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vite-plugin-vue-devtools": "7.7.2",
|
||||
@ -92,5 +92,8 @@
|
||||
},
|
||||
"lint-staged": {
|
||||
"*": "eslint --fix"
|
||||
},
|
||||
"volta": {
|
||||
"node": "20.12.2"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
import { useAuthStore } from '@/store'
|
||||
import { isArray, isString } from 'radash'
|
||||
|
||||
/** 权限判断 */
|
||||
export function usePermission() {
|
||||
const authStore = useAuthStore()
|
||||
|
||||
function hasPermission(
|
||||
permission?: Entity.RoleType | Entity.RoleType[],
|
||||
permission?: Entity.RoleType[],
|
||||
) {
|
||||
if (!permission)
|
||||
return true
|
||||
@ -15,16 +14,9 @@ export function usePermission() {
|
||||
return false
|
||||
const { role } = authStore.userInfo
|
||||
|
||||
// 角色为super可直接通过
|
||||
let has = role.includes('super')
|
||||
if (!has) {
|
||||
if (isArray(permission))
|
||||
// 角色为数组, 判断是否有交集
|
||||
has = permission.some(i => role.includes(i))
|
||||
|
||||
if (isString(permission))
|
||||
// 角色为字符串, 判断是否包含
|
||||
has = role.includes(permission)
|
||||
has = permission.every(i => role.includes(i))
|
||||
}
|
||||
return has
|
||||
}
|
||||
|
||||
@ -14,7 +14,6 @@ import Reload from './Reload.vue'
|
||||
import TabBarItem from './TabBarItem.vue'
|
||||
|
||||
const tabStore = useTabStore()
|
||||
const { tabs } = storeToRefs(useTabStore())
|
||||
const appStore = useAppStore()
|
||||
|
||||
const router = useRouter()
|
||||
@ -102,9 +101,11 @@ function onClickoutside() {
|
||||
showDropdown.value = false
|
||||
}
|
||||
|
||||
// const [DefineTabItem, ReuseTabItem] = createReusableTemplate<{ route: RouteLocationNormalized }>()
|
||||
|
||||
const el = ref()
|
||||
|
||||
useDraggable(el, tabs, {
|
||||
useDraggable(el, tabStore.tabs, {
|
||||
animation: 150,
|
||||
ghostClass: 'ghost',
|
||||
})
|
||||
|
||||
@ -38,4 +38,4 @@ const emit = defineEmits<{
|
||||
</button>
|
||||
</div>
|
||||
</n-el>
|
||||
</template>
|
||||
</template>
|
||||
@ -21,5 +21,5 @@ export function fetchUpdateToken(data: any) {
|
||||
}
|
||||
|
||||
export function fetchUserRoutes(params: { id: number }) {
|
||||
return request.Get<Service.ResponseResult<AppRoute.RowRoute[]>>('/getUserRoutes', { params })
|
||||
return request.Get<Service.ResponseResult<AppRoute.RowRoute[]> >('/getUserRoutes', { params })
|
||||
}
|
||||
|
||||
@ -2,8 +2,7 @@ import { local } from '@/utils'
|
||||
import { createAlova } from 'alova'
|
||||
import { createServerTokenAuthentication } from 'alova/client'
|
||||
import adapterFetch from 'alova/fetch'
|
||||
import VueHook from 'alova/vue'
|
||||
import type { VueHookType } from 'alova/vue'
|
||||
import VueHook, { type VueHookType } from 'alova/vue'
|
||||
import {
|
||||
DEFAULT_ALOVA_OPTIONS,
|
||||
DEFAULT_BACKEND_OPTIONS,
|
||||
|
||||
6
src/typings/global.d.ts
vendored
6
src/typings/global.d.ts
vendored
@ -28,12 +28,6 @@ declare namespace NaiveUI {
|
||||
type ThemeColor = 'default' | 'error' | 'primary' | 'info' | 'success' | 'warning'
|
||||
}
|
||||
|
||||
// 修复naive-ui的TabPane组件的slots类型 https://github.com/tusen-ai/naive-ui/issues/6779 ,但是直接这样会导致更多类型报错,也无法查看naive-ui的源码
|
||||
// declare module 'naive-ui' {
|
||||
// interface TabPaneSlots {
|
||||
// tab?: () => VNode[]
|
||||
// }
|
||||
// }
|
||||
declare namespace Storage {
|
||||
interface Session {
|
||||
dict: DictMap
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { useEcharts } from '@/hooks'
|
||||
import type { ECOption } from '@/hooks'
|
||||
import { type ECOption, useEcharts } from '@/hooks'
|
||||
import { graphic } from 'echarts'
|
||||
|
||||
const lineOptions = ref<ECOption>({
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { useEcharts } from '@/hooks'
|
||||
import type { ECOption } from '@/hooks'
|
||||
import { type ECOption, useEcharts } from '@/hooks'
|
||||
import { graphic } from 'echarts'
|
||||
|
||||
const chartData = [
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { useEcharts } from '@/hooks'
|
||||
import type { ECOption } from '@/hooks'
|
||||
import { type ECOption, useEcharts } from '@/hooks'
|
||||
|
||||
const option = ref<ECOption>({
|
||||
tooltip: {
|
||||
@ -48,7 +47,8 @@ const option = ref<ECOption>({
|
||||
name: '小红书',
|
||||
},
|
||||
],
|
||||
}],
|
||||
},
|
||||
],
|
||||
}) as Ref<ECOption>
|
||||
useEcharts('lineRef', option)
|
||||
</script>
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { useEcharts } from '@/hooks'
|
||||
import type { ECOption } from '@/hooks'
|
||||
import { type ECOption, useEcharts } from '@/hooks'
|
||||
// 折线图
|
||||
const lineOptions = ref<ECOption>({
|
||||
tooltip: {
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { useEcharts } from '@/hooks'
|
||||
import type { ECOption } from '@/hooks'
|
||||
import { type ECOption, useEcharts } from '@/hooks'
|
||||
import { graphic } from 'echarts'
|
||||
|
||||
// 饼状图
|
||||
|
||||
@ -4,6 +4,7 @@ import { useAuthStore } from '@/store'
|
||||
|
||||
const authStore = useAuthStore()
|
||||
const { hasPermission } = usePermission()
|
||||
const { role } = authStore.userInfo
|
||||
|
||||
const roleList: Entity.RoleType[] = ['super', 'admin', 'user']
|
||||
|
||||
@ -14,7 +15,7 @@ function toggleUserRole(role: Entity.RoleType) {
|
||||
|
||||
<template>
|
||||
<n-card title="权限示例">
|
||||
<n-h1> 当前权限:{{ authStore.userInfo!.role }}</n-h1>
|
||||
<n-h1> 当前权限:{{ role }}</n-h1>
|
||||
<n-button-group>
|
||||
<n-button v-for="item in roleList" :key="item" type="default" @click="toggleUserRole(item)">
|
||||
{{ item }}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user