mirror of
https://gitee.com/lakernote/easy-admin.git
synced 2026-09-03 05:33:47 +08:00
feature: add vue3
This commit is contained in:
2
easy-admin-client-vue3/.env.development
Normal file
2
easy-admin-client-vue3/.env.development
Normal file
@@ -0,0 +1,2 @@
|
||||
VITE_BASE_URL = 'http://localhost:8080'
|
||||
VITE_TIMEOUT = 5000
|
||||
2
easy-admin-client-vue3/.env.production
Normal file
2
easy-admin-client-vue3/.env.production
Normal file
@@ -0,0 +1,2 @@
|
||||
VITE_BASE_URL = 'http://example.com'
|
||||
VITE_TIMEOUT = 5000
|
||||
@@ -46,7 +46,8 @@ npm run dev
|
||||
npm create vue@latest
|
||||
```
|
||||
|
||||
这一指令将会安装并执行 [create-vue](https://github.com/vuejs/create-vue),它是 Vue 官方的项目脚手架工具。你将会看到一些诸如 TypeScript 和测试支持之类的可选功能提示
|
||||
这一指令将会安装并执行 [create-vue](https://github.com/vuejs/create-vue),它是 Vue 官方的项目脚手架工具。你将会看到一些诸如
|
||||
TypeScript 和测试支持之类的可选功能提示
|
||||
|
||||
如果不确定是否要开启某个功能,你可以**直接按下回车键选择** `No`。
|
||||
|
||||
@@ -91,7 +92,8 @@ my-vue3-project/
|
||||
|
||||
#### Element Plus
|
||||
|
||||
ElementPlus 是基于 Vue 3 开发的一套高质量、美观且功能丰富的 UI 组件库。它提供了众多常用的界面组件,例如按钮、输入框、表格、弹窗等,这些组件具有统一的设计风格,能够帮助开发者快速搭建出专业、美观且易用的用户界面。
|
||||
ElementPlus 是基于 Vue 3 开发的一套高质量、美观且功能丰富的 UI
|
||||
组件库。它提供了众多常用的界面组件,例如按钮、输入框、表格、弹窗等,这些组件具有统一的设计风格,能够帮助开发者快速搭建出专业、美观且易用的用户界面。
|
||||
|
||||
1.安装element-plus
|
||||
|
||||
@@ -136,7 +138,8 @@ export default {
|
||||
|
||||
#### Vue Router
|
||||
|
||||
Vue Router 是 Vue 官方的客户端路由解决方案,用于实现单页面应用(SPA)的路由功能。它允许开发者通过定义路由规则,将不同的 URL 路径映射到对应的 Vue 组件,从而实现页面的切换和导航。
|
||||
Vue Router 是 Vue 官方的客户端路由解决方案,用于实现单页面应用(SPA)的路由功能。它允许开发者通过定义路由规则,将不同的 URL
|
||||
路径映射到对应的 Vue 组件,从而实现页面的切换和导航。
|
||||
|
||||
1.安装
|
||||
|
||||
@@ -149,26 +152,26 @@ npm install vue-router@4
|
||||
在 `src` 目录下创建 `router` 文件夹,并在其中创建 `index.js` 文件,示例代码如下:
|
||||
|
||||
```javascript
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import {createRouter, createWebHistory} from 'vue-router'
|
||||
import Home from '../views/Home.vue'
|
||||
import About from '../views/About.vue'
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: '/',
|
||||
name: 'Home',
|
||||
component: Home
|
||||
},
|
||||
{
|
||||
path: '/about',
|
||||
name: 'About',
|
||||
component: About
|
||||
}
|
||||
{
|
||||
path: '/',
|
||||
name: 'Home',
|
||||
component: Home
|
||||
},
|
||||
{
|
||||
path: '/about',
|
||||
name: 'About',
|
||||
component: About
|
||||
}
|
||||
]
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
routes
|
||||
history: createWebHistory(),
|
||||
routes
|
||||
})
|
||||
|
||||
export default router
|
||||
@@ -180,7 +183,7 @@ export default router
|
||||
在 `src/main.js` 中引入并使用路由:
|
||||
|
||||
```javascript
|
||||
import { createApp } from 'vue'
|
||||
import {createApp} from 'vue'
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
|
||||
@@ -190,6 +193,7 @@ app.mount('#app')
|
||||
```
|
||||
|
||||
### 调试
|
||||
|
||||
1.代码中添加debugger;
|
||||
> 1.在代码中需要调试的地方添加 `debugger;` 语句。
|
||||
> 2.在浏览器中打开开发者工具,切换到 Sources 面板。
|
||||
@@ -197,3 +201,53 @@ app.mount('#app')
|
||||
2.使用浏览器调试:sourcemap需启用
|
||||
3.vs code 调试:先开启node服务,后启用vs code的调试模式
|
||||
|
||||
### 本地开发和生产环境配置
|
||||
|
||||
在项目根目录下创建不同的环境变量文件:
|
||||
.env.development:用于开发环境。
|
||||
.env.production:用于生产环境。
|
||||
|
||||
在 .env.development 文件中添加如下内容:
|
||||
|
||||
```plaintext
|
||||
VITE_BASE_URL = 'http://localhost:8080'
|
||||
VITE_TIMEOUT = 5000
|
||||
```
|
||||
|
||||
在 .env.production 文件中添加如下内容,假设生产环境的基础 URL 为 http://example.com:
|
||||
|
||||
```plaintext
|
||||
VITE_BASE_URL = 'http://example.com'
|
||||
VITE_TIMEOUT = 5000
|
||||
```
|
||||
|
||||
修改 main.js 文件,使用环境变量来设置 axios 的基础 URL 和超时时间。
|
||||
|
||||
```javascript
|
||||
// 使用环境变量设置 axios 的基础 URL
|
||||
axios.defaults.baseURL = import.meta.env.VITE_BASE_URL;
|
||||
// 使用环境变量设置 请求超时时间
|
||||
axios.defaults.timeout = parseInt(import.meta.env.VITE_TIMEOUT);
|
||||
```
|
||||
|
||||
运行 vite / npm run dev 启动开发服务器,Vite 会自动加载 .env.development 文件中的环境变量。可以在package.json找到
|
||||
|
||||
运行 vite build / npm run build 构建生产环境,Vite 会自动加载 .env.production 文件中的环境变量。可以在package.json找到
|
||||
|
||||
### 部署nginx
|
||||
|
||||
将 dist 文件夹中的所有文件上传到 Nginx 服务器的指定目录,例如 /var/www/html
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name your_domain_or_ip;
|
||||
|
||||
root /var/www/html;
|
||||
index index.html;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -1,9 +1,6 @@
|
||||
<template>
|
||||
<!-- 定义根组件模板,显示路由对应的视图 -->
|
||||
<div id="app">
|
||||
<!-- 路由视图,用于显示当前路由对应的组件 -->
|
||||
<router-view/>
|
||||
</div>
|
||||
<!-- 路由视图,用于显示当前路由对应的组件 -->
|
||||
<router-view/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
@@ -23,12 +20,9 @@ onMounted(() => {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
#app {
|
||||
font-family: Avenir, Helvetica, Arial, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-align: center;
|
||||
color: #2c3e50;
|
||||
margin-top: 60px;
|
||||
body{
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
92
easy-admin-client-vue3/src/components/Layout.vue
Normal file
92
easy-admin-client-vue3/src/components/Layout.vue
Normal file
@@ -0,0 +1,92 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-row class="tac">
|
||||
<el-col :span="4">
|
||||
<el-menu
|
||||
default-active="Home"
|
||||
class="el-menu-vertical-demo"
|
||||
@open="handleOpen"
|
||||
@close="handleClose"
|
||||
router
|
||||
>
|
||||
<template v-for="route in routes" :key="route.name">
|
||||
<el-sub-menu v-if="route.children" :index="route.name">
|
||||
<template #title>
|
||||
<el-icon><component :is="icons[route.meta.icon]" /></el-icon>
|
||||
<span>{{ route.meta.title }}</span>
|
||||
</template>
|
||||
<template v-for="child in route.children" :key="child.name">
|
||||
<el-menu-item :index="child.name">
|
||||
<el-icon><component :is="icons[child.meta.icon]" /></el-icon>
|
||||
<span>{{ child.meta.title }}</span>
|
||||
</el-menu-item>
|
||||
</template>
|
||||
</el-sub-menu>
|
||||
<el-menu-item v-else :index="route.name">
|
||||
<el-icon><component :is="icons[route.meta.icon]" /></el-icon>
|
||||
<span>{{ route.meta.title }}</span>
|
||||
</el-menu-item>
|
||||
</template>
|
||||
</el-menu>
|
||||
</el-col>
|
||||
<el-col :span="20">
|
||||
<el-breadcrumb separator="/">
|
||||
<el-breadcrumb-item :to="{ name: 'Home' }">首页</el-breadcrumb-item>
|
||||
<template v-for="(crumb, index) in breadcrumbList" :key="index">
|
||||
<el-breadcrumb-item :to="{ name: crumb.name }">{{ crumb.meta.title }}</el-breadcrumb-item>
|
||||
</template>
|
||||
</el-breadcrumb>
|
||||
<router-view />
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {ref, watch} from 'vue';
|
||||
import {useRoute, useRouter} from 'vue-router';
|
||||
import {House, List, Plus, User} from '@element-plus/icons-vue';
|
||||
import router from '../router';
|
||||
|
||||
const route = useRoute();
|
||||
const routerInstance = useRouter();
|
||||
const routes = router.getRoutes().filter(r => r.path.startsWith('/'));
|
||||
const icons = {
|
||||
House,
|
||||
User,
|
||||
List,
|
||||
Plus
|
||||
};
|
||||
|
||||
const breadcrumbList = ref([]);
|
||||
|
||||
const generateBreadcrumb = () => {
|
||||
const currentRoute = route.matched;
|
||||
const breadcrumbs = [];
|
||||
currentRoute.forEach(r => {
|
||||
if (r.name!== 'Home') {
|
||||
breadcrumbs.push(r);
|
||||
}
|
||||
});
|
||||
breadcrumbList.value = breadcrumbs;
|
||||
};
|
||||
|
||||
watch(
|
||||
() => route.name,
|
||||
() => {
|
||||
generateBreadcrumb();
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
const handleOpen = (key, keyPath) => {
|
||||
console.log(key, keyPath);
|
||||
};
|
||||
|
||||
const handleClose = (key, keyPath) => {
|
||||
console.log(key, keyPath);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
@@ -1,31 +0,0 @@
|
||||
<template>
|
||||
<el-menu :default-active="activeMenu" mode="horizontal" @select="handleMenuSelect">
|
||||
<el-menu-item index="/users">用户管理</el-menu-item>
|
||||
<el-menu-item index="logout">登出</el-menu-item>
|
||||
</el-menu>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {ref} from 'vue';
|
||||
import {useRouter} from 'vue-router';
|
||||
|
||||
const router = useRouter();
|
||||
const activeMenu = ref('');
|
||||
|
||||
const handleMenuSelect = (index: string) => {
|
||||
if (index === 'logout') {
|
||||
// 清除登录状态
|
||||
localStorage.removeItem('isLoggedIn');
|
||||
// 跳转到登录页面
|
||||
router.push('/login');
|
||||
} else {
|
||||
router.push(index);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.el-menu {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
</style>
|
||||
@@ -15,10 +15,12 @@ app.use(router);
|
||||
|
||||
// 可以将 axios 挂载到全局,方便在组件中使用
|
||||
app.config.globalProperties.$axios = axios;
|
||||
// 设置 axios 的基础 URL
|
||||
axios.defaults.baseURL = 'http://localhost:8080';
|
||||
// 设置 请求超时时间
|
||||
axios.defaults.timeout = 5000;
|
||||
|
||||
// 使用环境变量设置 axios 的基础 URL
|
||||
axios.defaults.baseURL = import.meta.env.VITE_BASE_URL;
|
||||
// 使用环境变量设置 请求超时时间
|
||||
axios.defaults.timeout = parseInt(import.meta.env.VITE_TIMEOUT);
|
||||
|
||||
// 设置请求拦截器
|
||||
axios.interceptors.request.use(
|
||||
config => {
|
||||
|
||||
@@ -1,23 +1,56 @@
|
||||
import {createRouter, createWebHistory} from 'vue-router';
|
||||
import Login from '../views/Login.vue';
|
||||
import Users from '../views/Users.vue';
|
||||
|
||||
import Layout from '../components/Layout.vue';
|
||||
import Users from "@/views/Users.vue";
|
||||
// 定义路由配置数组
|
||||
const routes = [
|
||||
{
|
||||
// 根路径重定向到登录页面
|
||||
path: '/',
|
||||
path: '/', // 根路径对应的路由配置
|
||||
component: Layout, // 该路由对应的组件为 Layout,通常 Layout 组件作为应用的整体布局,包含侧边栏、导航栏等
|
||||
// 子路由配置数组,这些子路由会在 Layout 组件的 <router-view> 中渲染
|
||||
children: [
|
||||
{
|
||||
// 子路由的路径为空字符串,表示当访问根路径时默认显示该子路由对应的组件
|
||||
path: '',
|
||||
// 该子路由的名称为 'Home',可用于路由导航时通过名称跳转
|
||||
name: 'Home',
|
||||
meta: { title: '首页', icon: 'House' },
|
||||
// 使用懒加载的方式引入 Home 组件,只有在访问该路由时才会加载对应的组件,提高应用性能
|
||||
// '@' 是项目中配置的别名,通常指向 src 目录
|
||||
component: () => import('@/views/Home.vue')
|
||||
},
|
||||
{
|
||||
// 用户管理页面的路由路径,当访问该路径时会显示对应的组件
|
||||
path: 'users1',
|
||||
meta: { title: '用户管理', icon: 'User' },
|
||||
// 该路由对应的组件为 Users,该组件负责展示用户管理相关的内容
|
||||
component: Users,
|
||||
children: [
|
||||
{
|
||||
path: 'users',
|
||||
name: 'users',
|
||||
meta: { title: '用户列表', icon: 'List' },
|
||||
component: () => import('@/views/Users.vue')
|
||||
},
|
||||
{
|
||||
path: 'add',
|
||||
name: 'UserAdd',
|
||||
meta: { title: '添加用户', icon: 'Plus' },
|
||||
component: () => import('@/views/Users.vue')
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
// 重定向到登录页面
|
||||
path: '/401',
|
||||
redirect: '/login'
|
||||
},
|
||||
{
|
||||
// 登录页面路由
|
||||
path: '/login',
|
||||
component: Login
|
||||
},
|
||||
{
|
||||
// 用户管理页面路由
|
||||
path: '/users',
|
||||
component: Users
|
||||
}
|
||||
];
|
||||
|
||||
@@ -28,7 +61,7 @@ const router = createRouter({
|
||||
routes
|
||||
});
|
||||
|
||||
// 全局前置守卫,在每次路由跳转前执行
|
||||
// 全局前置路由守卫,在每次路由跳转前执行 用于权限控制
|
||||
router.beforeEach((to, from, next) => {
|
||||
// 从本地存储中获取登录状态
|
||||
const isLoggedIn = localStorage.getItem('isLoggedIn');
|
||||
|
||||
89
easy-admin-client-vue3/src/views/Home.vue
Normal file
89
easy-admin-client-vue3/src/views/Home.vue
Normal file
@@ -0,0 +1,89 @@
|
||||
<template>
|
||||
<div class="dashboard">
|
||||
<!-- 数据统计卡片 -->
|
||||
<div class="statistic-cards">
|
||||
<el-card class="statistic-card">
|
||||
<template #header>
|
||||
<div class="card-header">用户总数</div>
|
||||
</template>
|
||||
<div class="card-content">1000</div>
|
||||
</el-card>
|
||||
<el-card class="statistic-card">
|
||||
<template #header>
|
||||
<div class="card-header">今日新增用户</div>
|
||||
</template>
|
||||
<div class="card-content">10</div>
|
||||
</el-card>
|
||||
<el-card class="statistic-card">
|
||||
<template #header>
|
||||
<div class="card-header">订单总数</div>
|
||||
</template>
|
||||
<div class="card-content">500</div>
|
||||
</el-card>
|
||||
<el-card class="statistic-card">
|
||||
<template #header>
|
||||
<div class="card-header">今日新增订单</div>
|
||||
</template>
|
||||
<div class="card-content">5</div>
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
<!-- 通知区域 -->
|
||||
<el-card class="notice-card">
|
||||
<template #header>
|
||||
<div class="card-header">系统通知</div>
|
||||
</template>
|
||||
<el-list :data="notices" :size="8">
|
||||
<template #item="{ item }">
|
||||
<el-list-item>
|
||||
{{ item }}
|
||||
</el-list-item>
|
||||
</template>
|
||||
</el-list>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {ref} from 'vue';
|
||||
|
||||
// 模拟通知数据
|
||||
const notices = ref([
|
||||
'系统将于今晚 12 点进行维护,请提前做好准备。',
|
||||
'新的功能模块已上线,欢迎体验。',
|
||||
'请及时更新您的个人信息。'
|
||||
]);
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.dashboard {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.statistic-cards {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.statistic-card {
|
||||
flex: 1 1 calc(25% - 20px);
|
||||
min-width: 200px;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.card-content {
|
||||
font-size: 24px;
|
||||
text-align: center;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.notice-card {
|
||||
height: 200px;
|
||||
}
|
||||
</style>
|
||||
@@ -110,7 +110,7 @@ const handleLogin = () => {
|
||||
// 这里可以存储 token 等信息
|
||||
localStorage.setItem('tokenName', response.data.tokenName);
|
||||
localStorage.setItem('tokenValue', response.data.tokenValue);
|
||||
router.push('/users');
|
||||
router.push('/');
|
||||
} else {
|
||||
ElMessage.error(response.data.message);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<template>
|
||||
<div>
|
||||
<Navbar/>
|
||||
<h1>用户管理</h1>
|
||||
<!-- 新增用户按钮,点击打开新增用户对话框 -->
|
||||
<el-button type="primary" @click="openCreateDialog">新增用户</el-button>
|
||||
@@ -63,7 +62,6 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import {ref} from 'vue';
|
||||
import Navbar from '../components/Nav.vue';
|
||||
|
||||
// 用户数据列表,初始包含两个示例用户
|
||||
const users = ref([
|
||||
|
||||
Reference in New Issue
Block a user