feature: add vue3

This commit is contained in:
laker
2025-04-18 14:34:16 +08:00
parent 6b4833ac13
commit a4ba2afe1d
11 changed files with 312 additions and 77 deletions

View File

@@ -0,0 +1,2 @@
VITE_BASE_URL = 'http://localhost:8080'
VITE_TIMEOUT = 5000

View File

@@ -0,0 +1,2 @@
VITE_BASE_URL = 'http://example.com'
VITE_TIMEOUT = 5000

View File

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

View File

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

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

View File

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

View File

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

View File

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

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

View File

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

View File

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