1
0
mirror of https://github.com/zclzone/vue-naive-admin.git synced 2025-12-28 12:10:20 +08:00

13 Commits

Author SHA1 Message Date
张传龙
9c5f4eaa3d chore: 依赖更新 2022-04-02 09:39:16 +08:00
张传龙
361fb52345 mod: 修改配置,打包默认不生成CNAME文件 2022-04-01 17:59:04 +08:00
张传龙
5993e8d7d0 refactor: 全局规范化调整文件夹和文件命名(代码无改动) 2022-04-01 17:41:07 +08:00
张传龙
8648f16ed8 mod: remove router.isReady 2022-04-01 16:39:26 +08:00
张传龙
33aaadba60 fix: 修复挂载路由时使用$loadingBar出错问题 2022-03-29 09:28:36 +08:00
张传龙
437d87f19e mod: 调整setupApp相关写法 2022-03-28 18:31:32 +08:00
张传龙
dfcc8c2158 mod: 修改失效图片链接 2022-03-26 17:50:29 +08:00
张传龙
51a583fc1e feat: 添加pageTitle路由守卫,支持动态修改页面title 2022-03-24 20:47:05 +08:00
张传龙
396428104a mod: 修改并完善首页 2022-03-20 18:59:20 +08:00
张传龙
ff2c25ff75 style: 调整测试页面和组件示例页面样式 2022-03-20 17:33:07 +08:00
张传龙
4f78bcb77c style: 调整app-main样式 2022-03-20 17:00:47 +08:00
张传龙
f62f59720d style: 调整header样式 2022-03-20 14:45:36 +08:00
张传龙
f296490569 docs: update readme 2022-03-19 19:13:07 +08:00
26 changed files with 560 additions and 496 deletions

2
.env
View File

@@ -3,4 +3,4 @@ VITE_APP_TITLE = 'Vue Naive Admin'
VITE_PORT = 3100 VITE_PORT = 3100
# 打包时自动生成CNAME文件用于配置github pages自定义域名如不需要可注释或者直接删除 # 打包时自动生成CNAME文件用于配置github pages自定义域名如不需要可注释或者直接删除
VITE_APP_GLOB_CNAME = 'template.qszone.com' # VITE_APP_GLOB_CNAME = 'template.qszone.com'

View File

@@ -76,3 +76,20 @@ npm run lint:fix
# 预览发布包效果(需先执行构建指令) # 预览发布包效果(需先执行构建指令)
npm run preview npm run preview
``` ```
## Git 提交规范
- `feat` 增加新功能
- `fix` 修复问题/BUG
- `style` 代码风格相关无影响运行结果的
- `perf` 优化/性能提升
- `refactor` 重构
- `revert` 撤销修改
- `test` 测试相关
- `docs` 文档/注释
- `chore` 依赖更新/脚手架配置修改等
- `workflow` 工作流改进
- `ci` 持续集成
- `types` 类型定义文件更改
- `wip` 开发中
- `mod` 不确定分类的修改

View File

@@ -7,7 +7,7 @@ export function configMockPlugin(isBuild) {
localEnabled: !isBuild, localEnabled: !isBuild,
prodEnabled: isBuild, prodEnabled: isBuild,
injectCode: ` injectCode: `
import { setupProdMockServer } from '../mock/_createProdServer'; import { setupProdMockServer } from '../mock/_create-prod-server';
setupProdMockServer(); setupProdMockServer();
`, `,
}) })

View File

@@ -4,21 +4,21 @@ const users = {
admin: { admin: {
id: 1, id: 1,
name: '大脸怪(admin)', name: '大脸怪(admin)',
avatar: 'https://gitee.com/zclzone/res/raw/master/qs-zone/blob/img/lADPDiQ3QDTwsz3NAarNAaw_428_426.jpg', avatar: 'https://assets.qszone.com/images/avatar.jpg',
email: 'Ronnie@123.com', email: 'Ronnie@123.com',
role: ['admin'], role: ['admin'],
}, },
editor: { editor: {
id: 2, id: 2,
name: '大脸怪(editor)', name: '大脸怪(editor)',
avatar: 'https://gitee.com/zclzone/res/raw/master/qs-zone/blob/img/lADPDiQ3QDTwsz3NAarNAaw_428_426.jpg', avatar: 'https://assets.qszone.com/images/avatar.jpg',
email: 'Ronnie@123.com', email: 'Ronnie@123.com',
role: ['editor'], role: ['editor'],
}, },
guest: { guest: {
id: 3, id: 3,
name: '访客(guest)', name: '访客(guest)',
avatar: 'https://gitee.com/zclzone/res/raw/master/qs-zone/blob/img/lADPDiQ3QDTwsz3NAarNAaw_428_426.jpg', avatar: 'https://assets.qszone.com/images/avatar.jpg',
role: [], role: [],
}, },
} }

View File

@@ -13,35 +13,35 @@
"dependencies": { "dependencies": {
"@vicons/fa": "^0.11.0", "@vicons/fa": "^0.11.0",
"axios": "^0.21.4", "axios": "^0.21.4",
"dayjs": "^1.10.7", "dayjs": "^1.11.0",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"md-editor-v3": "^1.10.2", "md-editor-v3": "^1.11.4",
"mockjs": "^1.1.0", "mockjs": "^1.1.0",
"pinia": "^2.0.11", "pinia": "^2.0.13",
"vue": "^3.2.30", "vue": "^3.2.31",
"vue-router": "^4.0.12" "vue-router": "^4.0.14"
}, },
"devDependencies": { "devDependencies": {
"@unocss/preset-attributify": "^0.16.4", "@unocss/preset-attributify": "^0.16.4",
"@unocss/preset-icons": "^0.16.4", "@unocss/preset-icons": "^0.16.4",
"@unocss/preset-uno": "^0.16.4", "@unocss/preset-uno": "^0.16.4",
"@vitejs/plugin-vue": "^1.10.2", "@vitejs/plugin-vue": "^1.10.2",
"@vue/compiler-sfc": "^3.2.30", "@vue/compiler-sfc": "^3.2.31",
"chalk": "^5.0.0", "chalk": "^5.0.1",
"dotenv": "^10.0.0", "dotenv": "^10.0.0",
"eslint": "^8.6.0", "eslint": "^8.12.0",
"eslint-config-prettier": "^8.3.0", "eslint-config-prettier": "^8.5.0",
"eslint-plugin-prettier": "^4.0.0", "eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-vue": "^8.2.0", "eslint-plugin-vue": "^8.5.0",
"esno": "^0.13.0", "esno": "^0.13.0",
"fs-extra": "^10.0.0", "fs-extra": "^10.0.1",
"naive-ui": "^2.25.2", "naive-ui": "^2.27.0",
"prettier": "^2.5.1", "prettier": "^2.6.1",
"sass": "^1.38.1", "sass": "^1.49.10",
"unocss": "^0.16.4", "unocss": "^0.16.4",
"unplugin-vue-components": "^0.17.18", "unplugin-vue-components": "^0.17.21",
"vite": "^2.8.0", "vite": "^2.9.1",
"vite-plugin-html": "^2.1.1", "vite-plugin-html": "^2.1.2",
"vite-plugin-mock": "^2.9.6", "vite-plugin-mock": "^2.9.6",
"vite-plugin-vue-setup-extend": "^0.3.0" "vite-plugin-vue-setup-extend": "^0.3.0"
} }

831
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 59 KiB

View File

@@ -40,21 +40,21 @@ function switchRole() {
{ {
id: 1, id: 1,
name: '大脸怪(admin)', name: '大脸怪(admin)',
avatar: 'https://gitee.com/zclzone/res/raw/master/qs-zone/blob/img/lADPDiQ3QDTwsz3NAarNAaw_428_426.jpg', avatar: 'https://assets.qszone.com/images/avatar.jpg',
email: 'Ronnie@123.com', email: 'Ronnie@123.com',
role: ['admin'], role: ['admin'],
}, },
{ {
id: 2, id: 2,
name: '大脸怪(editor)', name: '大脸怪(editor)',
avatar: 'https://gitee.com/zclzone/res/raw/master/qs-zone/blob/img/lADPDiQ3QDTwsz3NAarNAaw_428_426.jpg', avatar: 'https://assets.qszone.com/images/avatar.jpg',
email: 'Ronnie@123.com', email: 'Ronnie@123.com',
role: ['editor'], role: ['editor'],
}, },
{ {
id: 3, id: 3,
name: '访客(guest)', name: '访客(guest)',
avatar: 'https://gitee.com/zclzone/res/raw/master/qs-zone/blob/img/lADPDiQ3QDTwsz3NAarNAaw_428_426.jpg', avatar: 'https://assets.qszone.com/images/avatar.jpg',
role: [], role: [],
}, },
] ]

View File

@@ -12,7 +12,7 @@ import HeaderAction from './HeaderAction.vue'
<style lang="scss" scoped> <style lang="scss" scoped>
.header { .header {
padding: 0 35px; padding: 0 24px;
height: 100%; height: 100%;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;

View File

@@ -11,18 +11,22 @@ import AppMain from './components/AppMain.vue'
<side-menu /> <side-menu />
</n-layout-sider> </n-layout-sider>
<n-layout> <n-layout>
<n-layout-header style="height: 100px; background-color: #f5f6fb"> <n-layout-header>
<app-header /> <app-header />
</n-layout-header> </n-layout-header>
<n-layout <n-layout position="absolute" style="top: 60px; background-color: #f5f6fb" :native-scrollbar="false">
position="absolute"
content-style="padding: 0 35px 35px;height: 100%;"
style="top: 100px; background-color: #f5f6fb"
:native-scrollbar="false"
>
<app-main /> <app-main />
</n-layout> </n-layout>
</n-layout> </n-layout>
</n-layout> </n-layout>
</div> </div>
</template> </template>
<style lang="scss" scoped>
.n-layout-header {
height: 60px;
background-color: #fff;
border-bottom: 1px solid #eee;
border-left: 1px solid #eee;
}
</style>

View File

@@ -2,18 +2,18 @@ import '@/styles/index.scss'
import 'uno.css' import 'uno.css'
import { createApp } from 'vue' import { createApp } from 'vue'
import App from './App.vue'
import { setupRouter } from '@/router' import { setupRouter } from '@/router'
import { setupStore } from '@/store' import { setupStore } from '@/store'
import App from './App.vue'
async function bootstrap() { function setupApp() {
const app = createApp(App) const app = createApp(App)
setupStore(app) setupStore(app)
setupRouter(app) setupRouter(app)
app.mount('#app', true) app.mount('#app')
} }
bootstrap() setupApp()

View File

@@ -1,7 +1,9 @@
import { createPageLoadingGuard } from './pageLoadingGuard' import { createPageLoadingGuard } from './page-loading-guard'
import { createPermissionGuard } from './permissionGuard' import { createPageTitleGuard } from './page-title-guard'
import { createPermissionGuard } from './permission-guard'
export function setupRouterGuard(router) { export function setupRouterGuard(router) {
createPageLoadingGuard(router) createPageLoadingGuard(router)
createPermissionGuard(router) createPermissionGuard(router)
createPageTitleGuard(router)
} }

View File

@@ -1,15 +1,15 @@
export function createPageLoadingGuard(router) { export function createPageLoadingGuard(router) {
router.beforeEach(() => { router.beforeEach(() => {
$loadingBar.start() window.$loadingBar?.start()
}) })
router.afterEach(() => { router.afterEach(() => {
setTimeout(() => { setTimeout(() => {
$loadingBar.finish() window.$loadingBar?.finish()
}, 200) }, 200)
}) })
router.onError(() => { router.onError(() => {
$loadingBar.error() window.$loadingBar?.error()
}) })
} }

View File

@@ -0,0 +1,12 @@
const baseTitle = import.meta.env.VITE_APP_TITLE
export function createPageTitleGuard(router) {
router.afterEach((to) => {
const pageTitle = to.meta?.title
if (pageTitle) {
document.title = `${pageTitle} | ${baseTitle}`
} else {
document.title = baseTitle
}
})
}

View File

@@ -1,4 +1,4 @@
import { createWebStorage } from './webStorage' import { createWebStorage } from './web-storage'
export const createLocalStorage = function (option = {}) { export const createLocalStorage = function (option = {}) {
return createWebStorage({ prefixKey: option.prefixKey || '', storage: localStorage }) return createWebStorage({ prefixKey: option.prefixKey || '', storage: localStorage })

View File

@@ -1,3 +1,68 @@
<template> <template>
<h1>首页</h1> <div>
<n-card>
<div flex items-center>
<img width="60" style="border-radius: 50%" :src="userStore.avatar" />
<div ml20>
<p text-16>Hello, {{ userStore.name }}</p>
<p op80 text-12 mt5>今天又是元气满满的一天</p>
</div>
<div flex ml-auto>
<n-statistic label="待办" :value="4">
<template #suffix> / 10 </template>
</n-statistic>
<n-statistic ml80 label="Stars">
<n-number-animation ref="starsNumberRef" show-separator :from="0" :to="999" />
</n-statistic>
<n-statistic ml80 label="Forks">
<n-number-animation ref="starsNumberRef" show-separator :from="0" :to="299" />
</n-statistic>
</div>
</div>
</n-card>
<div p15 flex>
<n-card title="项目" size="small" :segmented="true">
<template #header-extra>
<n-button text type="primary">更多</n-button>
</template>
<div class="card-list">
<n-card v-for="i in 10" :key="i" title="Vue Naive Admin" size="small">
<p op60>一个基于 Vue3.0ViteNaive UI 的轻量级后台管理模板</p>
</n-card>
<div class="blank"></div>
<div class="blank"></div>
<div class="blank"></div>
<div class="blank"></div>
</div>
</n-card>
</div>
</div>
</template> </template>
<script setup>
import { useUserStore } from '@/store/modules/user'
const userStore = useUserStore()
</script>
<style lang="scss" scoped>
.card-list {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.n-card {
width: 300px;
flex-shrink: 0;
margin: 10px 0;
cursor: pointer;
&:hover {
box-shadow: 0 1px 2px -2px #00000029, 0 3px 6px #0000001f, 0 5px 12px 4px #00000017;
}
}
.blank {
width: 300px;
height: 0;
}
}
</style>

View File

@@ -7,10 +7,10 @@ const { replace } = useRouter()
<div class="page-404"> <div class="page-404">
<n-result status="404" description="抱歉,您访问的页面不存在。"> <n-result status="404" description="抱歉,您访问的页面不存在。">
<template #icon> <template #icon>
<img src="@/assets/imgs/404/404.png" width="500" /> <img src="@/assets/images/404.png" width="500" />
</template> </template>
<template #footer> <template #footer>
<n-button @click="replace('/')">返回首页</n-button> <n-button color="#002d6f" @click="replace('/')">返回首页</n-button>
</template> </template>
</n-result> </n-result>
</div> </div>
@@ -19,6 +19,7 @@ const { replace } = useRouter()
<style lang="scss" scoped> <style lang="scss" scoped>
.page-404 { .page-404 {
height: 100%; height: 100%;
min-height: calc(100vh - 60px);
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;

View File

@@ -1,5 +1,5 @@
<template> <template>
<div> <div p24>
<div class="action-btns"> <div class="action-btns">
<n-button size="small" type="primary" @click="handleCreate">新建文章</n-button> <n-button size="small" type="primary" @click="handleCreate">新建文章</n-button>
</div> </div>
@@ -11,7 +11,7 @@
:columns="columns" :columns="columns"
:pagination="pagination" :pagination="pagination"
:row-key="(row) => row.id" :row-key="(row) => row.id"
max-height="calc(100vh - 260px)" max-height="calc(100vh - 250px)"
@update:checked-row-keys="handleCheck" @update:checked-row-keys="handleCheck"
/> />
</div> </div>

View File

@@ -4,7 +4,7 @@
<input v-model="post.title" type="text" placeholder="输入文章标题..." class="title" /> <input v-model="post.title" type="text" placeholder="输入文章标题..." class="title" />
<n-button type="primary" style="width: 80px" :loading="btnLoading" @click="handleSavePost">保存</n-button> <n-button type="primary" style="width: 80px" :loading="btnLoading" @click="handleSavePost">保存</n-button>
</div> </div>
<md-editor v-model="post.content" style="height: calc(100vh - 180px)" /> <md-editor v-model="post.content" style="height: calc(100vh - 140px)" />
</div> </div>
</template> </template>

View File

@@ -13,5 +13,7 @@ const handleDelete = function () {
</script> </script>
<template> <template>
<n-button @click="handleDelete">删除</n-button> <div p24>
<n-button type="error" @click="handleDelete">删除</n-button>
</div>
</template> </template>

View File

@@ -16,5 +16,7 @@ onDeactivated(() => {
</script> </script>
<template> <template>
<div p24>
<n-gradient-text gradient="linear-gradient(90deg, red 0%, green 50%, blue 100%)"> 注意查看提示语 </n-gradient-text> <n-gradient-text gradient="linear-gradient(90deg, red 0%, green 50%, blue 100%)"> 注意查看提示语 </n-gradient-text>
</div>
</template> </template>

View File

@@ -12,5 +12,7 @@ function handleLogin() {
</script> </script>
<template> <template>
<n-button @click="handleLogin">点击登陆</n-button> <div p24>
<n-button type="primary" @click="handleLogin">点击登陆</n-button>
</div>
</template> </template>

View File

@@ -1,6 +1,6 @@
<template> <template>
<div> <div p24>
<div class="content-box"> <div p20 bg="#fff">
<p text-12>测试12px</p> <p text-12>测试12px</p>
<p text-13>测试13px</p> <p text-13>测试13px</p>
<p text-14>测试14px</p> <p text-14>测试14px</p>
@@ -13,11 +13,3 @@
</div> </div>
</div> </div>
</template> </template>
<style lang="scss" scoped>
.content-box {
background-color: #fff;
border-radius: 15px;
padding: 20px;
}
</style>