mirror of
https://github.com/fantastic-admin/basic.git
synced 2026-10-07 03:54:00 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ce099b3bea | ||
|
|
eff431a09d | ||
|
|
501a8955c3 | ||
|
|
f0a523f505 | ||
|
|
b2e33ca05f | ||
|
|
a401b1f5bf | ||
|
|
07a13b004e | ||
|
|
defd87869e | ||
|
|
051e6a99e1 | ||
|
|
5f3855cc82 | ||
|
|
6489e8b94a | ||
|
|
98ca00326a | ||
|
|
fc033c8693 | ||
|
|
57b18c2710 |
@@ -19,4 +19,69 @@ jobs:
|
||||
|
||||
- run: npx changelogithub # or changelogithub@0.12 if ensure the stable result
|
||||
env:
|
||||
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
||||
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
||||
|
||||
upload-archive:
|
||||
needs: release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Get Release
|
||||
id: last_release
|
||||
uses: joutvhu/get-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
latest: true
|
||||
|
||||
- name: Create Archive
|
||||
uses: thedoctor0/zip-release@main
|
||||
with:
|
||||
type: 'zip'
|
||||
filename: fantastic-admin.${{ steps.last_release.outputs.tag_name }}.zip
|
||||
exclusions: '/.git/* /.github/*'
|
||||
|
||||
- name: Upload Archive To Release
|
||||
uses: xresloader/upload-to-github-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
release_id: ${{ steps.last_release.outputs.id }}
|
||||
draft: false
|
||||
file: fantastic-admin.${{ steps.last_release.outputs.tag_name }}.zip
|
||||
|
||||
upload-archive-example:
|
||||
needs: release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: example
|
||||
|
||||
- name: Get Release
|
||||
id: last_release
|
||||
uses: joutvhu/get-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
latest: true
|
||||
|
||||
- name: Create Archive
|
||||
uses: thedoctor0/zip-release@main
|
||||
with:
|
||||
type: 'zip'
|
||||
filename: fantastic-admin.example.${{ steps.last_release.outputs.tag_name }}.zip
|
||||
exclusions: '/.git/* /.github/*'
|
||||
|
||||
- name: Upload Archive To Release
|
||||
uses: xresloader/upload-to-github-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
release_id: ${{ steps.last_release.outputs.id }}
|
||||
draft: false
|
||||
file: fantastic-admin.example.${{ steps.last_release.outputs.tag_name }}.zip
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
pnpm lint-staged
|
||||
+28
-25
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "2.1.0",
|
||||
"version": "2.2.0",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build:test": "vue-tsc --noEmit && vite build --mode test",
|
||||
@@ -12,65 +12,64 @@
|
||||
"lint:tsc": "vue-tsc --noEmit",
|
||||
"lint:eslint": "eslint src/**/*.{ts,tsx,vue} --cache --fix",
|
||||
"lint:stylelint": "stylelint src/**/*.{css,scss,vue} --cache --fix",
|
||||
"prepare": "husky install",
|
||||
"postinstall": "esno scripts/prepare.js",
|
||||
"postinstall": "simple-git-hooks && esno scripts/prepare.js",
|
||||
"preinstall": "npx only-allow pnpm",
|
||||
"commit": "git cz",
|
||||
"release": "bumpp"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tinymce/tinymce-vue": "^5.0.0",
|
||||
"@vueuse/core": "^9.4.0",
|
||||
"@vueuse/integrations": "^9.4.0",
|
||||
"axios": "^1.1.3",
|
||||
"@vueuse/core": "^9.6.0",
|
||||
"@vueuse/integrations": "^9.6.0",
|
||||
"axios": "^1.2.0",
|
||||
"dayjs": "^1.11.6",
|
||||
"element-plus": "^2.2.19",
|
||||
"hotkeys-js": "^3.10.0",
|
||||
"element-plus": "^2.2.25",
|
||||
"hotkeys-js": "^3.10.1",
|
||||
"lodash-es": "^4.17.21",
|
||||
"mitt": "^3.0.0",
|
||||
"mockjs": "^1.1.0",
|
||||
"nprogress": "^0.2.0",
|
||||
"path-browserify": "^1.0.1",
|
||||
"path-to-regexp": "^6.2.1",
|
||||
"pinia": "^2.0.23",
|
||||
"pinia": "^2.0.26",
|
||||
"qs": "^6.11.0",
|
||||
"tinymce": "^6.2.0",
|
||||
"vue": "^3.2.41",
|
||||
"tinymce": "^6.3.0",
|
||||
"vue": "^3.2.45",
|
||||
"vue-router": "^4.1.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config": "^0.27.0",
|
||||
"@antfu/eslint-config": "^0.31.0",
|
||||
"@iconify-json/ep": "^1.1.8",
|
||||
"@iconify/vue": "^4.0.0",
|
||||
"@types/nprogress": "^0.2.0",
|
||||
"@types/path-browserify": "^1.0.0",
|
||||
"@types/qs": "^6.9.7",
|
||||
"@vitejs/plugin-vue": "^3.2.0",
|
||||
"@vitejs/plugin-vue-jsx": "^2.1.0",
|
||||
"@vitejs/plugin-vue-jsx": "^2.1.1",
|
||||
"autoprefixer": "^10.4.13",
|
||||
"bumpp": "^8.2.1",
|
||||
"cz-git": "^1.3.12",
|
||||
"eslint": "^8.26.0",
|
||||
"eslint": "^8.28.0",
|
||||
"esno": "^0.16.3",
|
||||
"fs-extra": "^10.1.0",
|
||||
"http-server": "^14.1.1",
|
||||
"husky": "^8.0.1",
|
||||
"lint-staged": "^13.0.3",
|
||||
"lint-staged": "^13.0.4",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"plop": "^3.1.1",
|
||||
"postcss-html": "^1.5.0",
|
||||
"sass": "^1.55.0",
|
||||
"stylelint": "^14.14.0",
|
||||
"sass": "^1.56.1",
|
||||
"simple-git-hooks": "^2.8.1",
|
||||
"stylelint": "^14.15.0",
|
||||
"stylelint-config-standard": "^29.0.0",
|
||||
"stylelint-config-standard-scss": "^6.0.0",
|
||||
"stylelint-config-standard-scss": "^6.1.0",
|
||||
"stylelint-config-standard-vue": "^1.0.0",
|
||||
"stylelint-scss": "^4.3.0",
|
||||
"svgo": "^3.0.0",
|
||||
"typescript": "^4.8.4",
|
||||
"unplugin-auto-import": "^0.11.4",
|
||||
"unplugin-vue-components": "^0.22.9",
|
||||
"vite": "^3.2.1",
|
||||
"vite-plugin-banner": "^0.5.0",
|
||||
"svgo": "^3.0.2",
|
||||
"typescript": "^4.9.3",
|
||||
"unplugin-auto-import": "^0.12.0",
|
||||
"unplugin-vue-components": "^0.22.11",
|
||||
"vite": "^3.2.4",
|
||||
"vite-plugin-banner": "^0.6.1",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vite-plugin-html": "^3.2.0",
|
||||
"vite-plugin-mock": "^2.9.6",
|
||||
@@ -81,6 +80,10 @@
|
||||
"vite-plugin-vue-setup-extend": "^0.4.0",
|
||||
"vue-tsc": "^1.0.9"
|
||||
},
|
||||
"simple-git-hooks": {
|
||||
"pre-commit": "pnpm lint-staged",
|
||||
"preserveUnused": true
|
||||
},
|
||||
"config": {
|
||||
"commitizen": {
|
||||
"path": "node_modules/cz-git"
|
||||
|
||||
Generated
+627
-494
File diff suppressed because it is too large
Load Diff
@@ -9,6 +9,8 @@ defineProps({
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
|
||||
const slots = useSlots()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -23,7 +25,7 @@ defineProps({
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sub">
|
||||
<div v-if="slots.default" class="sub">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
@@ -65,4 +67,15 @@ defineProps({
|
||||
flex: none;
|
||||
}
|
||||
}
|
||||
|
||||
[data-mode="mobile"] {
|
||||
.header {
|
||||
flex-direction: column;
|
||||
|
||||
.main {
|
||||
margin-right: auto;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Vendored
+6
-6
@@ -52,15 +52,15 @@ declare namespace Settings {
|
||||
*/
|
||||
routeBaseOn?: 'frontend' | 'backend' | 'filesystem'
|
||||
}
|
||||
interface dashboard {
|
||||
interface home {
|
||||
/**
|
||||
* 是否开启控制台页面
|
||||
* 是否开启主页页面
|
||||
* @默认值 `true`
|
||||
*/
|
||||
enable?: boolean
|
||||
/**
|
||||
* 控制台名称
|
||||
* @默认值 `'控制台'`
|
||||
* 主页名称
|
||||
* @默认值 `'主页'`
|
||||
*/
|
||||
title?: string
|
||||
}
|
||||
@@ -189,8 +189,8 @@ declare namespace Settings {
|
||||
interface all {
|
||||
/** 应用设置 */
|
||||
app?: app
|
||||
/** 控制台设置 */
|
||||
dashboard?: dashboard
|
||||
/** 主页设置 */
|
||||
home?: home
|
||||
/** 布局设置 */
|
||||
layout?: layout
|
||||
/** 导航栏设置 */
|
||||
|
||||
@@ -226,23 +226,23 @@ function handleCopy() {
|
||||
</div>
|
||||
<el-input v-model="settingsStore.copyright.beian" size="small" :disabled="!settingsStore.copyright.enable" />
|
||||
</div>
|
||||
<el-divider>控制台</el-divider>
|
||||
<el-divider>主页</el-divider>
|
||||
<div class="setting-item">
|
||||
<div class="label">
|
||||
是否开启
|
||||
<el-tooltip content="该功能开启时,登录成功默认进入控制台页面,反之则默认进入导航栏里第一个导航页面" placement="top">
|
||||
<el-tooltip content="该功能开启时,登录成功默认进入主页,反之则默认进入导航栏里第一个导航页面" placement="top">
|
||||
<el-icon>
|
||||
<svg-icon name="ep:question-filled" />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<el-switch v-model="settingsStore.dashboard.enable" />
|
||||
<el-switch v-model="settingsStore.home.enable" />
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div class="label">
|
||||
控制台名称
|
||||
主页名称
|
||||
</div>
|
||||
<el-input v-model="settingsStore.dashboard.title" size="small" />
|
||||
<el-input v-model="settingsStore.home.title" size="small" />
|
||||
</div>
|
||||
<el-divider>其它</el-divider>
|
||||
<div class="setting-item">
|
||||
|
||||
@@ -22,15 +22,15 @@ const to = computed(() => {
|
||||
const rtn: {
|
||||
name?: string
|
||||
} = {}
|
||||
if (settingsStore.dashboard.enable) {
|
||||
rtn.name = 'dashboard'
|
||||
if (settingsStore.home.enable) {
|
||||
rtn.name = 'home'
|
||||
}
|
||||
return rtn
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<router-link :to="to" class="title" :class="{ 'is-link': settingsStore.dashboard.enable }" :title="title">
|
||||
<router-link :to="to" class="title" :class="{ 'is-link': settingsStore.home.enable }" :title="title">
|
||||
<img v-if="showLogo" :src="logo" class="logo">
|
||||
<span v-if="showTitle">{{ title }}</span>
|
||||
</router-link>
|
||||
@@ -58,6 +58,7 @@ const to = computed(() => {
|
||||
.logo {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
object-fit: contain;
|
||||
|
||||
& + span {
|
||||
margin-left: 10px;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts" setup name="SidebarItem">
|
||||
// import SidebarItem from './index.vue'
|
||||
import { isExternalLink, resolveRoutePath } from '@/utils'
|
||||
import useSettingsStore from '@/store/modules/settings'
|
||||
import type { Menu } from '@/global'
|
||||
|
||||
const props = defineProps({
|
||||
@@ -14,6 +15,8 @@ const props = defineProps({
|
||||
},
|
||||
})
|
||||
|
||||
const settingsStore = useSettingsStore()
|
||||
|
||||
const hasChildren = computed(() => {
|
||||
let flag = true
|
||||
if (props.item.children) {
|
||||
@@ -40,7 +43,7 @@ const hasChildren = computed(() => {
|
||||
</el-menu-item>
|
||||
</a>
|
||||
</router-link>
|
||||
<el-sub-menu v-else :title="item.meta.title" :index="resolveRoutePath(basePath, item.path || '')">
|
||||
<el-sub-menu v-else :title="item.meta.title" :index="settingsStore.app.routeBaseOn !== 'filesystem' ? resolveRoutePath(basePath, item.path || '') : JSON.stringify(item)">
|
||||
<template #title>
|
||||
<el-icon v-if="item.meta.icon" class="title-icon">
|
||||
<svg-icon :name="item.meta.icon" />
|
||||
|
||||
@@ -12,11 +12,11 @@ const userStore = useUserStore()
|
||||
const mainPage = useMainPage()
|
||||
const { isFullscreen, toggle } = useFullscreen()
|
||||
|
||||
function userCommand(command: 'dashboard' | 'setting' | 'hotkeys' | 'logout') {
|
||||
function userCommand(command: 'home' | 'setting' | 'hotkeys' | 'logout') {
|
||||
switch (command) {
|
||||
case 'dashboard':
|
||||
case 'home':
|
||||
router.push({
|
||||
name: 'dashboard',
|
||||
name: 'home',
|
||||
})
|
||||
break
|
||||
case 'setting':
|
||||
@@ -85,8 +85,8 @@ function pro() {
|
||||
</div>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu class="user-dropdown">
|
||||
<el-dropdown-item v-if="settingsStore.dashboard.enable" command="dashboard">
|
||||
控制台
|
||||
<el-dropdown-item v-if="settingsStore.home.enable" command="home">
|
||||
{{ settingsStore.home.title }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item command="setting">
|
||||
个人设置
|
||||
|
||||
@@ -16,10 +16,10 @@ const enableSubMenuCollapseButton = computed(() => {
|
||||
|
||||
const breadcrumbList = computed(() => {
|
||||
const breadcrumbList = []
|
||||
if (settingsStore.dashboard.enable) {
|
||||
if (settingsStore.home.enable) {
|
||||
breadcrumbList.push({
|
||||
path: '/dashboard',
|
||||
title: settingsStore.dashboard.title,
|
||||
path: '/',
|
||||
title: settingsStore.home.title,
|
||||
})
|
||||
}
|
||||
if (route.meta.breadcrumbNeste) {
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { Menu } from '@/global'
|
||||
const menus: Menu.recordRaw = {
|
||||
meta: {
|
||||
title: '多级导航',
|
||||
icon: 'heroicons-solid:menu-alt-3',
|
||||
icon: 'sidebar-menu',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
|
||||
+6
-6
@@ -30,22 +30,22 @@ router.beforeEach(async (to, from, next) => {
|
||||
if (routeStore.isGenerate) {
|
||||
// 导航栏如果不是 single 模式,则需要根据 path 定位主导航的选中状态
|
||||
settingsStore.menu.menuMode !== 'single' && menuStore.setActived(to.path)
|
||||
// 如果已登录状态下,进入登录页会强制跳转到控制台页面
|
||||
// 如果已登录状态下,进入登录页会强制跳转到主页
|
||||
if (to.name === 'login') {
|
||||
next({
|
||||
name: 'dashboard',
|
||||
name: 'home',
|
||||
replace: true,
|
||||
})
|
||||
}
|
||||
// 如果未开启控制台,但进入的是控制台页面,则会进入侧边栏导航第一个模块
|
||||
else if (!settingsStore.dashboard.enable && to.name === 'dashboard') {
|
||||
// 如果未开启主页,但进入的是主页,则会进入侧边栏导航第一个模块
|
||||
else if (!settingsStore.home.enable && to.name === 'home') {
|
||||
if (menuStore.sidebarMenus.length > 0) {
|
||||
next({
|
||||
path: menuStore.sidebarMenusFirstDeepestPath,
|
||||
replace: true,
|
||||
})
|
||||
}
|
||||
// 如果侧边栏导航第一个模块无法命中,则还是进入控制台页面
|
||||
// 如果侧边栏导航第一个模块无法命中,则还是进入主页
|
||||
else {
|
||||
next()
|
||||
}
|
||||
@@ -104,7 +104,7 @@ router.beforeEach(async (to, from, next) => {
|
||||
next({
|
||||
name: 'login',
|
||||
query: {
|
||||
redirect: to.fullPath,
|
||||
redirect: to.fullPath !== '/' ? to.fullPath : undefined,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
+13
-41
@@ -7,13 +7,6 @@ import useSettingsStore from '@/store/modules/settings'
|
||||
|
||||
// 固定路由(默认路由)
|
||||
const constantRoutes: Route.recordRaw[] = [
|
||||
{
|
||||
path: '/',
|
||||
redirect: '/dashboard',
|
||||
meta: {
|
||||
title: '',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: '/login',
|
||||
name: 'login',
|
||||
@@ -35,33 +28,31 @@ const constantRoutes: Route.recordRaw[] = [
|
||||
// 系统路由
|
||||
const systemRoutes: Route.recordRaw[] = [
|
||||
{
|
||||
path: '/dashboard',
|
||||
path: '/',
|
||||
component: () => import('@/layouts/index.vue'),
|
||||
meta: {
|
||||
title: () => useSettingsStore().dashboard.title,
|
||||
title: () => useSettingsStore().home.title,
|
||||
breadcrumb: false,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'dashboard',
|
||||
name: 'home',
|
||||
component: () => import('@/views/index.vue'),
|
||||
meta: {
|
||||
title: () => useSettingsStore().dashboard.title,
|
||||
title: () => useSettingsStore().home.title,
|
||||
breadcrumb: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'reload',
|
||||
name: 'reload',
|
||||
component: () => import('@/views/reload.vue'),
|
||||
meta: {
|
||||
title: '重新加载',
|
||||
breadcrumb: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/personal',
|
||||
component: () => import('@/layouts/index.vue'),
|
||||
redirect: '/personal/setting',
|
||||
meta: {
|
||||
title: '个人中心',
|
||||
breadcrumb: false,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'setting',
|
||||
name: 'personalSetting',
|
||||
@@ -81,25 +72,6 @@ const systemRoutes: Route.recordRaw[] = [
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/reload',
|
||||
component: () => import('@/layouts/index.vue'),
|
||||
meta: {
|
||||
title: '重新加载',
|
||||
breadcrumb: false,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'reload',
|
||||
component: () => import('@/views/reload.vue'),
|
||||
meta: {
|
||||
title: '重新加载',
|
||||
breadcrumb: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
// 动态路由(异步路由、导航栏路由)
|
||||
|
||||
@@ -12,9 +12,9 @@ const globalSettingsDefault: RecursiveRequired<Settings.all> = {
|
||||
enableDynamicTitle: false,
|
||||
routeBaseOn: 'frontend',
|
||||
},
|
||||
dashboard: {
|
||||
home: {
|
||||
enable: true,
|
||||
title: '控制台',
|
||||
title: '主页',
|
||||
},
|
||||
layout: {
|
||||
enableMobileAdaptation: false,
|
||||
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
<route lang="yaml">
|
||||
name: dashboard
|
||||
name: home
|
||||
meta:
|
||||
title: 控制台
|
||||
title: 主页
|
||||
</route>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@@ -60,7 +60,7 @@ const oneStepAdminInfo = ref({
|
||||
<div>注:在作者就职的公司,本框架已在电商、直播、OA、ERP等多个不同领域的中后台系统中应用并稳定运行</div>
|
||||
</div>
|
||||
</template>
|
||||
<el-button-group style="margin-right: 10px;">
|
||||
<el-button-group>
|
||||
<el-button type="success" size="large" plain @click="open('https://hooray.gitee.io/fantastic-admin/')">
|
||||
开发文档
|
||||
</el-button>
|
||||
|
||||
Reference in New Issue
Block a user