Compare commits

..

No commits in common. "44ebd5f19ea1501b20110e4af17f89eb23fefc29" and "a5c3697a6b46d3c9c4ed6aaea54cf5ca78f283dc" have entirely different histories.

15 changed files with 33 additions and 47 deletions

View File

@ -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)

View File

@ -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)压缩包

View File

@ -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"
}
}

View File

@ -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
}

View File

@ -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',
})

View File

@ -38,4 +38,4 @@ const emit = defineEmits<{
</button>
</div>
</n-el>
</template>
</template>

View File

@ -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 })
}

View File

@ -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,

View File

@ -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

View File

@ -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>({

View File

@ -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 = [

View File

@ -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>

View File

@ -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: {

View File

@ -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'
//

View File

@ -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 }}