(14)Element Plus项目综合案例
本系列教程目录:Vue3+Element Plus全套学习笔记-目录大纲
文章目录
- 第3章 综合案例
- 3.1 搭建项目
- 3.1.1 创建Vite工程
- 3.1.2 配置路由
- 3.2 登录模块页面
- 3.2.1 注册页面
- 3.2.2 登录页面
- 3.2.3 忘记密码页面
- 3.3 导航设置
- 3.3.1 头部
- 3.3.2 侧边栏与底部
- 1)头像部分
- 2)折叠效果
- 3)菜单列表
- 4)路由配置
- 3.4 仪表盘模块
- 1)主面板部分
- 2)图表部分
- 3.5 用户模块
- 3.5.1 用户列表
- 1)搜索表单
- 2)表格组件
- 3)分页组件
- 3.5.2 用户详情
- 1)用户详情对话框
- 2)绑定事件
- 3.5.3 用户关注列表
- 1)关注列表
- 2)分页
- 3.5.4 个人中心
- 3.6 文章模块
- 3.6.1 文章列表
- 1)搜索表单
- 2)表格组件
- 3)分页组件
- 3.6.2 发布文章
- 1)发布文章对话框
- 2)绑定事件
- 3.6.3 文章详情
- 1)文章详情对话框
- 2)绑定事件
- 3.6.4 我的收藏列表
- 3.7 部门模块
- 3.8 会议模块
- 3.8.1 会议列表
- 1)搜索表单
- 2)表格组件
- 3)分页组件
- 3.8.2 发布会议
- 1)发布会议对话框
- 2)绑定事件
- 3.8.2 会议详情对话框
- 1)会议详情对话框
第3章 综合案例
3.1 搭建项目
3.1.1 创建Vite工程
1)创建Vite工程,输入命令:
npm create vite进入项目npm install
2)安装element plus、element plus icon依赖,并配置相关信息:
npm install element-plus
npm install @element-plus/icons-vue
3)配置相关信息(打开main.js):
import { createApp } from 'vue'// 导入ElementPlus组件
import ElementPlus from 'element-plus'// 导入ElementPlus样式
import 'element-plus/dist/index.css'// 导入App组件
import App from './App.vue'// 导入ElementPlus图标
import * as ElementPlusIconsVue from '@element-plus/icons-vue'// 创建Vue实例
const app = createApp(App)
app.use(ElementPlus) // 使用ElementPlus组件
app.mount('#app')// 注册ElementPlus图标
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {app.component(key, component)
}
3.1.2 配置路由
1)安装路由依赖:
npm install vue-router
2)创建src/router/index.js,配置路由信息:
// 导入VueRouter中的createRouter和createWebHashHistory函数
import {createRouter, createWebHashHistory} from 'vue-router'// 定义路由表
const routes = [// 访问/login或者/都来到login.vue组件{path: '/login', component: () => import('../components/login.vue')},{path: '/', component: () => import('../components/login.vue')},
]// 创建路由实例
const router = createRouter({history: createWebHashHistory(),routes: routes
})// 导出路由
export default router
3)创建components/login.vue组件:
<script setup></script><template><div><h1>Login</h1></div></template><style scoped></style>
4)在main.js中配置路由:
...
// 导入路由
import router from './router/index.js'
// 创建Vue实例
const app = createApp(App)
app.use(router) // 注册路由
...
3.2 登录模块页面
登录模块包括登录页面、忘记密码页面、注册用户页面等三个页面。
3.2.1 注册页面
效果如下:
1)在router/index.js中定义注册组件路由:
{path: '/register',name: "register", component: () => import('../components/register.vue')}
2)编写components/register.vue组件:
<template><div class="body"><div class="container"><h2>新用户注册</h2><el-text>请输入您的信息</el-text><el-divider></el-divider><el-form ref="formRef" :model="form" :rules="rules" size="large"><el-form-item prop="email"><el-input v-model="form.email" placeholder="请输入邮箱" prefix-icon="Message"></el-input></el-form-item><el-form-item prop="username"><el-input v-model="form.username" placeholder="请输入用户名" prefix-icon="User"></el-input></el-form-item><el-form-item prop="password"><el-input type="password" v-model="form.password" placeholder="请输入密码" prefix-icon="Lock"></el-input></el-form-item><el-form-item prop="confirmPassword"><el-input type="password" v-model="form.confirmPassword" placeholder="请再次输入密码"prefix-icon="Lock"></el-input></el-form-item><el-form-item><el-button type="primary" @click="sendEmail" :disabled="isDisabled">{{ buttonText }}</el-button></el-form-item><el-form-item><el-button type="success" style="width: 100%" @click="register">注册</el-button></el-form-item><el-form-item><el-link type="primary" @click="$router.push('/login')">返回登录</el-link></el-form-item></el-form></div></div></template>
3)css:
.body {/*布局*/display: flex;/*水平居中*/justify-content: center;/*垂直居中*/align-items: center;/*高度为 100vh(视窗高度)*/height: 100vh;/* 背景颜色(渐变)*/background: linear-gradient(135deg, #74ebd5 0%, #ACB6E5 100%);
}.container {width: 600px;margin: 0 auto;padding: 20px;background-color: #fff;text-align: center;
}
4)script:
import {reactive} from 'vue'
import {ref, computed, onUnmounted} from 'vue'
import {ElMessage, ElMessageBox} from "element-plus";// 表单的引用对象
const formRef = ref();// 表单数据
const form = reactive({email: '',username: '',password: '',confirmPassword: '',
})// 响应式数据
const isDisabled = ref(false) // 按钮禁用状态
const remainingTime = ref(0) // 剩余时间(秒)
let timer = null // 定时器实例// 计算按钮显示文本
const buttonText = computed(() => {return isDisabled.value? `${remainingTime.value}秒后重试`: '发送邮箱'
})// 发送邮件处理
const sendEmail = () => {// 校验email字段formRef.value.validateField("email",(valid) => {if (valid) {// 表单验证通过,发送邮件// 显示成功提示ElMessage.success('邮箱已发送,请注意查收!')// 重置表单form.email = ''// 设置禁用状态和倒计时isDisabled.value = trueremainingTime.value = 60// 启动倒计时定时器timer = setInterval(() => {remainingTime.value -= 1// 倒计时结束后恢复按钮状态if (remainingTime.value <= 0) {clearInterval(timer)isDisabled.value = false}}, 1000)} else {// 表单验证失败,显示错误信息ElMessage.error('表单验证失败,请检查输入!')}})
}// 组件卸载时清除定时器(防止内存泄漏)
onUnmounted(() => {if (timer) clearInterval(timer)
})// 表单校验规则
const rules = {email: [{required: true, message: '请输入邮箱', trigger: 'blur'},{type: 'email', message: '请输入正确的邮箱格式', trigger: 'blur'}],username: [{required: true, message: '请输入用户名', trigger: 'blur'},{min: 3, max: 10, message: '用户名长度在 3 到 10 个字符', trigger: 'blur'}],password: [{required: true, message: '请输入密码', trigger: 'blur'},{min: 6, max: 16, message: '密码长度在 6 到 16 个字符', trigger: 'blur'}],confirmPassword: [{required: true, message: '请再次输入密码', trigger: 'blur'},{validator: (rule, value, callback) => {if (value !== form.password) {callback('两次输入的密码不一致!')} else {callback()}}, trigger: 'blur'}]
}// 注册事件
const register = () => {formRef.value.validate((valid) => {if (valid) {// 表单验证通过,发送注册请求// 注册成功提示ElMessage.success('注册成功!');} else {// 表单验证失败,显示错误信息ElMessage.error('表单验证失败,请检查输入!')}})
}
3.2.2 登录页面
效果如下:
1)在router/index.js中定义组件路由:
{path: '/login',name: "login", component: () => import('../components/login.vue')}
2)编写components/login.vue组件:
<template><div class="body"><div class="container"><h2>用户登录</h2><el-text>请输入您的信息</el-text><el-divider></el-divider><el-form ref="formRef" :model="form" :rules="rules" size="large"><el-form-item prop="username"><el-input v-model="form.username" placeholder="请输入用户名" prefix-icon="User"></el-input></el-form-item><el-form-item prop="password"><el-input v-model="form.password" placeholder="请输入密码" type="password" prefix-icon="Lock"></el-input></el-form-item><el-form-item prop="checkCode"><el-row gutter="20" style="width: 100%;"><el-col :span="16"><el-input v-model="form.checkCode" placeholder="请输入验证码" prefix-icon="Check"></el-input></el-col><el-col :span="6"><img src="../assets/checkCode.png" alt="" style="width: 100%;height: 40px "></el-col></el-row></el-form-item><el-form-item><el-checkbox v-model="form.remember">记住我</el-checkbox></el-form-item><el-form-item><el-button type="success" style="width: 100%" @click="login">登录</el-button></el-form-item><el-form-item><el-row :gutter="20" style="width: 100%;"><el-col :span="12" style="text-align: left;"><el-link type="primary" :underline="false" @click="$router.push('/forget')">忘记密码?</el-link></el-col><el-col :span="12" style="text-align: right;"><el-link type="primary" :underline="false" @click="$router.push('/register')">没有账号?</el-link></el-col></el-row></el-form-item></el-form></div></div></template>
3)css:
.body {/*布局*/display: flex;/*水平居中*/justify-content: center;/*垂直居中*/align-items: center;/*高度为 100vh(视窗高度)*/height: 100vh;/* 背景颜色(渐变)*/background: linear-gradient(135deg, #74ebd5 0%, #ACB6E5 100%);
}.container {width: 600px;margin: 0 auto;padding: 20px;background-color: #fff;text-align: center;
}
4)script:
import {ref, reactive} from 'vue';
import {ElMessage} from 'element-plus';
import {useRouter} from 'vue-router';// 初始化路由
const router = useRouter();// 表单的引用对象
const formRef = ref(null);// 表单数据对象
const form = reactive({username: '',password: '',checkCode: '',remember: '',
});// 表单验证规则
const rules = {username: [{required: true, message: '请输入用户名', trigger: 'blur'},{min: 3, max: 10, message: '用户名长度在 3 到 10 个字符', trigger: 'blur'},],password: [{required: true, message: '请输入密码', trigger: 'blur'},{min: 6, max: 16, message: '密码长度在 6 到 16 个字符', trigger: 'blur'},],checkCode: [{required: true, message: '请输入验证码', trigger: 'blur'},{min: 4, max: 4, message: '验证码长度为 4', trigger: 'blur'},],
};// 用户登录
const login = () => {// 登录formRef.value.validate((valid) => {if (valid) {// 登录成功ElMessage.success('登录成功');// 跳转到首页router.push({name: 'dashboard'});} else {ElMessage.error('登录失败,请检查输入');}});
};
3.2.3 忘记密码页面
效果如下:
1)在router/index.js中定义组件路由:
{path: '/forget', name: "forget", component: () => import('../components/forget.vue')}
2)编写components/forget.vue组件:
<template><div class="body"><div class="container"><h2>忘记密码</h2><el-text>请输入您的信息</el-text><el-divider></el-divider><el-form ref="formRef" :model="form" :rules="rules" size="large"><el-form-item prop="email"><el-input v-model="form.email" placeholder="请输入邮箱" prefix-icon="Email"></el-input></el-form-item><el-form-item><el-button type="primary" style="width: 40%" @click="sendCheckCode">获取验证码</el-button></el-form-item><el-form-item prop="checkCode"><el-input v-model="form.checkCode" placeholder="请输入验证码" prefix-icon="Check"></el-input></el-form-item><el-form-item prop="newPassword"><el-input v-model="form.newPassword" placeholder="请输入新密码" type="password" prefix-icon="Lock"></el-input></el-form-item><el-form-item><el-row :gutter="20"><el-col :span="11"><el-button type="success" @click="resetPassword">重置密码</el-button></el-col><el-col :span="11"><el-button @click="$router.push('/login')">返回登录</el-button></el-col></el-row></el-form-item></el-form></div></div></template>
3)css:
.body {/*布局*/display: flex;/*水平居中*/justify-content: center;/*垂直居中*/align-items: center;/*高度为 100vh(视窗高度)*/height: 100vh;/* 背景颜色(渐变)*/background: linear-gradient(135deg, #74ebd5 0%, #ACB6E5 100%);
}.container {width: 600px;margin: 0 auto;padding: 20px;background-color: #fff;text-align: center;
}
4)script:
import { ref, reactive } from 'vue';
import { ElMessage } from 'element-plus';
import { useRouter } from 'vue-router';// 初始化路由实例
const router = useRouter();// 表单验证
const formRef = ref(null);// 表单数据
const form = reactive({email: '',checkCode: '',newPassword: '',
});// 表单验证规则
const rules = {email: [{ required: true, message: '请输入邮箱', trigger: 'blur' },{ type: 'email', message: '请输入正确的邮箱格式', trigger: 'blur' },],checkCode: [{ required: true, message: '请输入验证码', trigger: 'blur' },{ min: 4, max: 4, message: '验证码长度为 4', trigger: 'blur' },],newPassword: [{ required: true, message: '请输入新密码', trigger: 'blur' },{ min: 6, max: 20, message: '密码长度为 6-20 位', trigger: 'blur' },],
};// 发送验证码
const sendCheckCode = () => {formRef.value.validateField('email', (valid) => {if (valid) {// 发送验证码ElMessage.success('验证码已发送,请注意查收');}});
};// 重置密码
const resetPassword = () => {formRef.value.validate((valid) => {if (valid) {// 重置密码ElMessage.success('密码重置成功,请重新登录');router.push("/login");}});
};
3.3 导航设置
3.3.1 头部
如图所示:
1)定义components/views/home.vue组件:
<template><el-container style="height: 100vh"><el-header style="background: #409EFF; color: white">Header</el-header><el-container><el-aside width="200px" style="background: #545c64; color: white">Aside</el-aside><el-main>Main Content</el-main></el-container><el-footer style="background: #909399; color: white">Footer</el-footer></el-container></template>
2)在router/index.js中添加路由:
{path: '/views/', name: "home", component: () => import('../components/views/home.vue')}
3)头部布局:
<!-- *************************************************头部布局************************************************* -->
<el-header><div class="el-header-box"><el-row style="width: 100%"><el-col :span="12" style="text-align: left"><el-link to="/views/home" :underline="false" @click="$router.push('/views/dashboard')">协同会议平台</el-link></el-col><el-col :span="12" style="text-align: right"><el-link to="/login" :underline="false" @click="$router.push('/login')">退出</el-link></el-col></el-row></div></el-header>
4)css:
.el-header-box {display: flex;align-items: center;height: 100%;border-bottom: 1px solid #eee;
}
3.3.2 侧边栏与底部
效果如下:
1)头像部分
效果如下:
1)布局代码:
<!-- *************************************************主体部分 ************************************************* -->
<el-container>
<!-- *************************************************主体-侧边栏部分 ************************************************* --><el-aside><el-menu default-active="/views/dashboard" mode="vertical" :router="true"><div class="el-aside-avatar"><!-- *************************************************头像部分 ************************************************* --><el-row style="width: 180px"><el-col :span="12"><router-link to="/views/user/update"><el-avatar src="/src/assets/avatar.jpg" style="width: 70px; height: 70px"></el-avatar></router-link></el-col><el-col :span="4" v-show="!isCollapse"><el-tag type="success" size="large">小灰</el-tag><el-tag type="primary" size="large" style="margin-top: 10px;">研发部</el-tag></el-col></el-row></div></el-menu></el-aside><!-- 主体中心部分 --><el-main><!-- 当点击菜单时,路由切换到对应的页面 --><h1>Dashboard</h1></el-main></el-container>
2)css:
.el-aside-avatar {padding: 10px;
}
2)折叠效果
效果如下:
1)布局代码:
<!-- *************************************************主体部分 ************************************************* -->
<el-container><!-- *************************************************主体-侧边栏部分 ************************************************* --><el-aside class="el-aside-demo"><!-- 折叠按钮 --><el-radio-group v-model="isCollapse" style="margin-bottom: 20px"><el-radio-button :value="true">隐藏</el-radio-button><el-radio-button :value="false">展开</el-radio-button></el-radio-group><el-menu default-active="/views/dashboard" :collapse="isCollapse"mode="vertical" :router="true"><div class="el-aside-avatar"><!-- *************************************************头像部分 ************************************************* --><el-row style="width: 180px" v-show="!isCollapse"><!-- 没折叠时显示的头像信息 --><el-col :span="12"><router-link to="/views/user/update"><el-avatar src="/src/assets/avatar.jpg" style="width: 70px; height: 70px"></el-avatar></router-link></el-col><el-col :span="4"><el-tag type="success" size="large">小灰</el-tag><el-tag type="primary" size="large" style="margin-top: 10px;">研发部</el-tag></el-col></el-row><el-row v-show="isCollapse"><!-- 折叠时显示的头像信息 --><el-col :span="24" style="text-align: center"><router-link to="/views/user/update"><el-avatar src="/src/assets/avatar.jpg" style="width: 100%; height: 100%"></el-avatar></router-link></el-col></el-row></div></el-menu></el-aside><!-- *************************************************主体-中心部分 ************************************************* --><el-main><!-- 当点击菜单时,路由切换到对应的页面 --><h1>Dashboard</h1></el-main></el-container>
2)css:
.el-aside-demo {/* 宽度自适应 */--el-aside-width: auto;
}
3)script:
// 控制侧边栏折叠是否折叠
const isCollapse = ref(false);
3)菜单列表
效果如下:
1)布局代码:
<!-- *************************************************菜单部分 ************************************************* -->
<el-menu-item index="/views/dashboard"><el-icon><location/></el-icon><span slot="title">主页</span></el-menu-item><el-sub-menu><template #title><el-icon><user/></el-icon><span>用户列表</span></template><el-menu-item index="/views/user">查看用户</el-menu-item><el-menu-item index="/views/user/my_user">我关注的用户</el-menu-item></el-sub-menu><el-sub-menu index="3"><template #title><el-icon><Document/></el-icon><span>文章管理</span></template><el-menu-item index="/views/article">文章列表</el-menu-item><el-menu-item index="/views/article/article_collect">我的收藏</el-menu-item></el-sub-menu><el-menu-item index="/views/department"><el-icon><OfficeBuilding/></el-icon><span slot="title">部门列表</span></el-menu-item><el-menu-item index="/views/meeting"><el-icon><Coordinate/></el-icon><span slot="title">会议系统</span></el-menu-item>
4)路由配置
当点击侧边栏的菜单项时,右边的主体部分内容需要切换到具体的路由。如图所示:
1)定义views/home组件的子路由:
{path: '/views/',name:"home", component: () => import('../components/views/home.vue'),children: [{path: 'dashboard',name:"dashboard", component: () => import('../components/views/dashboard/index.vue')},{path: 'article', name:"article", component: () => import('../components/views/article/index.vue')},{path: 'article/favorite',name:"articleFavorite", component: () => import('../components/views/article/article_favorite.vue')},{path: 'department', name:"department", component: () => import('../components/views/department/index.vue')},{path: 'meeting', name:"meeting", component: () => import('../components/views/meeting/index.vue')},{path: 'user',name:"user", component: () => import('../components/views/user/index.vue')},{path: 'user/follow', name:"userFollow", component: () => import('../components/views/user/user_follow.vue')},{path: 'user/update', name:"myUser", component: () => import('../components/views/user/user_update.vue')},]
},
2)定义组件:
3)在home.vue组件中的布局主体部分替换成路由组件:
<!-- 主体中心部分 -->
<el-main><!-- 当点击菜单时,路由切换到对应的页面 --><router-view />
</el-main>
3.4 仪表盘模块
效果如图:
1)主面板部分
效果如下:
1)布局代码:
<!-- *************************************************主面板************************************************* -->
<h2>主面板</h2><el-row :gutter="20"><el-col :xs="24" :sm="12" :md="8" :lg="6"><el-card class="card-item"><h3>新增用户</h3><el-progress :percentage="100" :format="format"/></el-card></el-col><el-col :xs="24" :sm="12" :md="8" :lg="6"><el-card class="card-item"><h3>新增文章</h3><el-progress :percentage="54" :format="format"/></el-card></el-col><el-col :xs="24" :sm="12" :md="8" :lg="6"><el-card class="card-item"><h3>新开会议</h3><el-progress :percentage="38" :format="format"/></el-card></el-col></el-row>
2)script:
// 格式化百分比
const format = (percentage) => (percentage === 100 ? '100+' : percentage)
2)图表部分
效果如下:
1)安装echarts依赖:
npm install echarts
2)布局代码:
<!-- *************************************************图标部分************************************************* -->
<div id="charts" class="charts"></div>
3)css:
.charts {width: 80%;height: 400px;margin-top: 20px
}
4)script:
// 导入echarts
import * as echarts from 'echarts'
import {ref, onMounted} from 'vue'// 计算近七日日期
var date = new Date();
var days = [];for (var i = -6; i <= 0; i++) {date.setDate(date.getDate() + i);var month = date.getMonth() + 1;var day = date.getDate();if (month < 10) month = "0" + month;if (day < 10) day = "0" + day;days.push(month + "." + day);date.setDate(date.getDate() - i);
}// 图表渲染数据
const option = ref({title: {text: '数据汇总'},tooltip: {trigger: 'axis', axisPointer: {type: 'cross', label: {backgroundColor: '#aaaaff'}}},legend: {data: ['新增用户', '新增文章', '新开会议']},toolbox: {feature: {saveAsImage: {}}},grid: {left: '3%', right: '4%', bottom: '3%', containLabel: true},xAxis: [{type: 'category', boundaryGap: false, data: days}],yAxis: [{type: 'value'}],series: [{name: '新增用户', type: 'line', stack: '总量', areaStyle: {}, data: [56, 21, 24, 34, 61, 54, 100]},{name: '新增文章', type: 'line', stack: '总量', areaStyle: {}, data: [29, 40, 89, 54, 42, 69, 54]},{name: '新开会议', type: 'line', stack: '总量', areaStyle: {}, data: [31, 28, 49, 61, 39, 72, 38]}]
})// 图表实例
let myChart = null// 图表渲染
onMounted(() => {const chartDom = document.getElementById('charts')if (!chartDom) return// 初始化图表myChart = echarts.init(chartDom)myChart.setOption(option.value)// 窗口变化时自适应window.addEventListener('resize', () => myChart?.resize())
})
3.5 用户模块
3.5.1 用户列表
1)搜索表单
效果如下:
1)布局代码如下:
<!-- *************************************************表单搜索************************************************* -->
<h3>用户列表</h3><el-row><el-col :span="15"><el-form inline size="large"><el-form-item label="用户名"><el-input v-model="searchFrom.username" placeholder="请输入搜索内容"></el-input></el-form-item><el-form-item><el-button type="primary" @click="search">搜索</el-button></el-form-item></el-form></el-col></el-row>
2)script:
import {reactive} from 'vue'
import {ElMessage, ElMessageBox} from 'element-plus'//****************************************搜索表单********************************************//
// 表单搜索条件
const searchFrom = reactive({username: ''
})// 表单搜索
const search = () => {ElMessage.success(`搜索条件${searchFrom.username}`)
}
2)表格组件
效果如下:
1)布局代码:
<!-- *************************************************数据展示部分************************************************* -->
<el-table :data="users" border style="width: 100%;height: 300px"><el-table-column prop="id" label="ID" width="50"></el-table-column><el-table-column prop="username" label="用户名" width="120"></el-table-column><el-table-column prop="realName" label="真实姓名" width="120"></el-table-column><el-table-column prop="sex" label="性别" width="80"><template #default="scope"><el-tag :type="scope.row.sex === '0'? 'success' : 'warning'">{{ scope.row.sex === '0' ? '男' : '女' }}</el-tag></template></el-table-column><el-table-column prop="age" label="年龄" width="80"></el-table-column><el-table-column prop="email" label="邮箱" width="200"></el-table-column><el-table-column prop="phone" label="手机号" width="150"></el-table-column><el-table-column prop="info" label="简介" width="300"></el-table-column><el-table-column prop="isFollowed" label="加关注" width="80" fixed="right"><template #default="scope"><el-switch v-model="scope.row.isFollowed" @click="addFollow(scope.row.id)" :active-value="1":inactive-value="0"></el-switch></template></el-table-column><el-table-column label="操作" width="150" fixed="right"><template #default="scope"><el-button type="text" @click="showDialog(scope.row)">查看详情</el-button></template></el-table-column></el-table>
2)script:
const users = reactive([{id: 1,username: 'admin',realName: '管理员',sex: '0',age: 30,email: 'admin@example.com',phone: '12345678901',info: '这是一段简介',isFollowed: 1},{id: 2,username: 'xiaohui',realName: '小灰',sex: '0',age: 22,email: 'xiaohui@example.com',phone: '12345678902',info: '这是一段简介',isFollowed: 0},{id: 3,username: 'xiaolan',realName: '小蓝',sex: '1',age: 20,email: 'xiaolan@example.com',phone: '12345678903',info: '这是一段简介',isFollowed: 1},{id: 4,username: '小绿',realName: 'xiaolv',sex: '1',age: 20,email: 'xiaolv@example.com',phone: '12345678903',info: '这是一段简介',isFollowed: 0},{id: 5,username: 'xiaoming',realName: '小明',sex: '0',age: 20,email: 'xiaoming@example.com',phone: '12345678903',info: '这是一段简介',isFollowed: 1}
])
// 编辑按钮
const showDialog = (scope) => {ElMessage.success(`查看【${scope.id}】`)// 显示编辑对话框detailDialogVisible.value = true
}// 删除按钮
const deleteRow = (id) => {ElMessageBox.confirm('确认删除该行吗?').then(() => {ElMessage.success(`删除成功【${id}】`)// console.log(row)}).catch(() => {// cancel})
}// 加关注
const addFollow = (id) => {ElMessage.success(`关注【${id}】`)
}
3)分页组件
效果如下:
1)布局代码:
<!-- *************************************************分页组件************************************************* -->
<div style="margin-top: 20px;display: flex;justify-content: center;"><el-paginationv-model:current-page="currentPage"v-model:page-size="pageSize":page-sizes="[3, 5, 10]"size="large"layout="total, sizes, prev, pager, next, jumper":total="400"@size-change="handleSizeChange"@current-change="handleCurrentChange"/>
</div>
2)script:
//****************************************分页组件********************************************//
// 当前页
const currentPage = ref(1)
// 页大小
const pageSize = ref(10)// 当页大小发生改变时执行
const handleSizeChange = (val) => {ElMessage.success(`每页显示:${val}条`)
}// 当当前页发生改变时执行
const handleCurrentChange = (val) => {ElMessage.success(`当前页码:${val}`)
}
3.5.2 用户详情
1)用户详情对话框
当点击某一行的“查看详情”按钮时应该弹出对话框,展示用户信息数据。
效果如下:
1)布局代码:
<el-dialog title="用户详情" v-model="detailDialogVisible" width="60%" top="0vh"><el-divider/><el-form :model="userForm" label-width="80px" :disabled="true"><el-form-item label="头像"><el-row style="width: 100%;"><el-col :span="6"><el-avatar :size="84" shape="square" :src="userForm.pic"></el-avatar></el-col><el-col :span="18"><el-row style="width: 100%;" gutter="20"><el-col :span="10"><el-text size="large">粉丝数:<el-tag type="danger">{{ userForm.fans }}</el-tag></el-text></el-col><el-col :span="10"><el-text><!-- 嵌入一个子form,否则该switch控件会被处于禁止状态--><el-form>加关注:<el-switch v-model="userForm.isFollowed" @click="addFollow(userForm.id)":active-value="1" :inactive-value="0"></el-switch></el-form></el-text></el-col></el-row><el-divider style="width: 60%;"/><el-row style="width: 100%;" gutter="20"><el-col :span="10"><el-text>关注数:<el-tag type="success">{{ userForm.follows }}</el-tag></el-text></el-col><el-col :span="10"><el-text>浏览量:<el-tag type="primary">{{ userForm.browseCount }}</el-tag></el-text></el-col></el-row></el-col></el-row></el-form-item><el-form-item label="用户名"><el-input v-model="userForm.username"></el-input></el-form-item><el-form-item label="真实姓名"><el-input v-model="userForm.realName"></el-input></el-form-item><el-form-item label="所在部门"><el-select v-model="userForm.deptName"><el-option :value="userForm.deptName">{{ userForm.deptName }}</el-option></el-select></el-form-item><el-form-item label="性别"><el-radio-group v-model="userForm.sex"><el-radio value="0">男</el-radio><el-radio value="1">女</el-radio></el-radio-group></el-form-item><el-form-item label="年龄"><el-input-number v-model="userForm.age"></el-input-number></el-form-item><el-form-item label="邮箱"><el-input v-model="userForm.email"></el-input></el-form-item><el-form-item label="手机号"><el-input v-model="userForm.phone"></el-input></el-form-item><el-form-item label="简介"><el-input type="textarea" v-model="userForm.info"></el-input></el-form-item><el-form-item label="注册时间"><el-input v-model="userForm.registerTime"></el-input></el-form-item><el-form-item label="登录时间"><el-input v-model="userForm.loginTime"></el-input></el-form-item><el-form-item label="是否私密"><el-switch v-model="userForm.isSecret" active-value="0" inactive-value="1"></el-switch></el-form-item></el-form><el-divider/><div style="text-align: center"><el-button :icon="CircleClose" @click="dialogVisible = false" type="danger">关闭窗口</el-button></div></el-dialog>
2)script:
//****************************************会议详情********************************************//
// 编辑对话框是否显示
const detailDialogVisible = ref(false)// 用户数据
const userForm = reactive({id: "1",username: 'xiaohui',realName: '小灰',sex: '0',age: '20',email: 'xiaohui@example.com',phone: '110',info: '我是大帅哥',pic: '/src/assets/avatar.jpg',registerTime: '2030-10-10 10:10:10',loginTime: '2030-10-10 10:10:10',isSecret: '0',deptName: "研发部",isFollowed: 1,fans: 798,follows: 148,browseCount: 102400
})// 编辑按钮
const showDialog = (scope) => {ElMessage.success(`查看【${scope.id}】`)// 显示编辑对话框detailDialogVisible.value = true
}// 加关注
const addFollow = (id) => {ElMessage.success(`关注【${id}】`)
}
2)绑定事件
给“编辑”按钮绑定点击事件:
<el-table-column label="操作" width="150" fixed="right"><template #default="scope"><el-button type="text" @click="showDialog(scope.row)">查看详情</el-button></template></el-table-column>
3.5.3 用户关注列表
1)关注列表
1)布局代码:
<!-- *************************************************用户列表************************************************* -->
<h3>我的关注列表</h3><el-table :data="tableData" style="width: 100%;height: 300px"><el-table-column prop="realName" label="姓名"></el-table-column><el-table-column label="操作" fixed="right" width="150"><template #default="scope"><el-button type="danger" @click="unFollow(scope.row.id)">取消关注</el-button></template></el-table-column></el-table>
2)script:
import {ElMessage, ElMessageBox} from "element-plus";
//****************************************用户列表********************************************//
const tableData = [{id: 1,realName: '小灰'},{id: 2,realName: '小蓝'},{id: 3,realName: '小绿'},{id: 4,realName: '小红'},{id: 5,realName: '小明'},{id: 6,realName: '小龙'}
]// 取消关注
const unFollow = (id) => {ElMessageBox.confirm('确定取消关注该用户吗?').then(() => {ElMessage.success(`取消关注成功【${id}】`)})
}
2)分页
1)布局代码:
<!-- *************************************************分页组件************************************************* -->
<div style="margin-top: 20px;display: flex;justify-content: center;"><el-paginationv-model:current-page="currentPage"v-model:page-size="pageSize":page-sizes="[3, 5, 10]"size="large"layout="total, sizes, prev, pager, next, jumper":total="400"@size-change="handleSizeChange"@current-change="handleCurrentChange"/>
</div>
2)script:
//****************************************分页组件********************************************//
// 当前页
const currentPage = ref(1)
// 页大小
const pageSize = ref(10)// 当页大小发生改变时执行
const handleSizeChange = (val) => {ElMessage.success(`每页显示:${val}条`)
}// 当当前页发生改变时执行
const handleCurrentChange = (val) => {ElMessage.success(`当前页码:${val}`)
}
3.5.4 个人中心
当点击侧边栏中的“头像”时,进入个人中心页面。
效果如下:
1)注意修改/src/components/home.vue组件中的头像路由地址:
2)在/src/router/index.js文件中的home组件中定义子路由:
{path: 'user/update', name:"userUpdate", component: () => import('../components/views/user/user_update.vue')}
3)定义/src/components/views/user/update.vue组件
<template><h3>个人中心</h3><el-form ref="form" :model="userForm" label-width="100px" style="width: 80%"><el-form-item label="头像"><el-row style="width: 100%;"><el-col :span="6"><el-upload action="http://localhost:3000/upload":on-success="handleAvatarSuccess"><img v-if="userForm.pic" :src="userForm.pic" width="70"/><el-icon v-else class="avatar-uploader-icon"><Plus/></el-icon></el-upload></el-col><el-col :span="18"><el-row style="width: 100%;" gutter="20"><el-col :span="8"><el-text size="large">粉丝数:<el-tag type="danger">{{ userForm.fans }}</el-tag></el-text></el-col><el-col :span="8"><el-text>关注数:<el-tag type="success">{{ userForm.follows }}</el-tag></el-text></el-col><el-col :span="8"><el-text>浏览量:<el-tag type="primary">{{ userForm.browseCount }}</el-tag></el-text></el-col></el-row><el-divider style="width: 90%;"/></el-col></el-row></el-form-item><el-form-item label="用户名"><el-input v-model="userForm.username"></el-input></el-form-item><el-form-item label="真实姓名"><el-input v-model="userForm.realName"></el-input></el-form-item><el-form-item label="部门名称"><el-select v-model="userForm.deptId" placeholder="请选择部门"><el-option v-for="item in deptList" :key="item.id" :label="item.name" :value="item.id"></el-option></el-select></el-form-item><el-form-item label="性别"><el-radio-group v-model="userForm.sex"><el-radio :value="0">男</el-radio><el-radio :value="1">女</el-radio></el-radio-group></el-form-item><el-form-item label="年龄"><el-input-number v-model="userForm.age"></el-input-number></el-form-item><el-form-item label="邮箱"><el-input v-model="userForm.email"></el-input></el-form-item><el-form-item label="手机号"><el-input v-model="userForm.phone"></el-input></el-form-item><el-form-item label="简介"><el-input type="textarea" v-model="userForm.info"></el-input></el-form-item><el-form-item label="注册时间"><el-input v-model="userForm.registerTime" disabled></el-input></el-form-item><el-form-item label="登录时间"><el-input v-model="userForm.loginTime" disabled></el-input></el-form-item><el-form-item label="是否私密"><el-switch v-model="userForm.isSecret" active-value="0" inactive-value="1"></el-switch></el-form-item><el-form-item><el-button type="primary" @click="update">保存</el-button></el-form-item></el-form></template>
2)script:
import {reactive} from 'vue'
import {Plus} from "@element-plus/icons-vue";
import {ElMessage} from "element-plus";
import { useRouter } from 'vue-router'
let router = useRouter(); // 创建路由实例// 定义用户信息表单
const userForm = reactive({username: 'xiaohui',realName: '小灰',deptId: 2,sex: 0,age: 20,email: 'xiaohui@example.com',phone: '13800138000',info: '大家好,我叫小灰,我今年20岁,欢迎来到我的空间,方便的话点个小爱心哦~',registerTime: '2021-01-01 00:00:00',loginTime: '2021-01-01 00:00:00',isSecret: 0,pic: '/src/assets/avatar.jpg',fans: 478,follows: 124,browseCount: 142714
})// 定义部门列表
const deptList = reactive([{id: 1,name: '开发部'},{id: 2,name: '测试部'},{id: 3,name: '运营部'}
])// 上传用户头像
const handleAvatarSuccess = (res) => {ElMessage.success('上传成功')
}// 保存用户信息
const update = () => {ElMessage.success(`保存成功${userForm.username}`)// 跳转到用户列表组件router.push({name: 'user'})
}
3.6 文章模块
3.6.1 文章列表
1)搜索表单
效果如下:
1)布局代码:
<!-- *************************************************条件搜索************************************************* -->
<h3>文章列表</h3><el-row style="width: 100%;"><el-col :span="12"><el-form inline size="large"><el-form-item label="文章标题"><el-input v-model="searchForm.title" placeholder="请输入搜索内容"></el-input></el-form-item><el-form-item><el-button type="primary" @click="search">搜索</el-button></el-form-item></el-form></el-col><el-col :span="12" style="text-align: right;"><el-button type="primary" @click="addDialogVisible = true" size="large">新增文章</el-button></el-col></el-row>
2)script:
//****************************************搜索表单********************************************//
// 搜索条件
const searchForm = reactive({title: ''
});// 搜索方法
const search = () => {ElMessage.success(`搜索成功${searchForm.title}`);
};
2)表格组件
效果如下:
1)布局代码:
<!-- 文章列表 -->
<div><el-card v-for="(article, index) in articles" :key="index" style="margin-bottom: 20px;"><el-link type="primary" :underline="false">如何成为一名Java工程师?</el-link><p><el-text tag="strong">作者:</el-text><el-tag>{{ article.publishUser }}</el-tag></p><p><el-text tag="strong">时间:</el-text><el-tag type="success">{{ article.publishDate }}</el-tag></p><el-text>{{article.content}}</el-text></el-card></div>
2)script:
//****************************************文章列表********************************************//
const articles = [{id: '1',title: '如何成为一名Java工程师?',publishUser: '小灰',publishDate: '2030-01-01 10:00:00',content: '文章内容'},{id: '2',title: '如何成为一名Java工程师?',publishUser: '小蓝',publishDate: '2030-01-01 10:00:00',content: '文章内容'}
];
3)分页组件
效果如下:
1)布局代码:
<!-- *************************************************分页组件************************************************* -->
<div style="margin-top: 20px;display: flex;justify-content: center;"><el-paginationv-model:current-page="currentPage"v-model:page-size="pageSize":page-sizes="[3, 5, 10]"size="large"layout="total, sizes, prev, pager, next, jumper":total="400"@size-change="handleSizeChange"@current-change="handleCurrentChange"/>
</div>
2)script:
//****************************************分页组件********************************************//
// 当前页
const currentPage = ref(1)
// 页大小
const pageSize = ref(10)// 当页大小发生改变时执行
const handleSizeChange = (val) => {ElMessage.success(`每页显示:${val}条`)
}// 当当前页发生改变时执行
const handleCurrentChange = (val) => {ElMessage.success(`当前页码:${val}`)
}
3.6.2 发布文章
1)发布文章对话框
当点击“发布文章”按钮时应该弹出对话框,让用户填写文章数据。
效果如下:
1)布局代码:
<!-- *************************************************新增文章弹窗************************************************* -->
<el-dialog title="发布文章" v-model="addDialogVisible" style="width: 60%;height: 50%;"><el-divider/><el-form ref="form" :model="articleForm" label-width="80px"><el-form-item label="文章标题"><el-input v-model="articleForm.title" placeholder="请输入文章标题"></el-input></el-form-item><el-form-item label="文章内容"><el-input type="textarea" :rows="5" v-model="articleForm.content" placeholder="请输入文章内容"></el-input></el-form-item></el-form><el-divider/><div slot="footer" class="dialog-footer"><el-button type="primary" @click="add">确 定</el-button><el-button @click="addDialogVisible = false">取 消</el-button></div></el-dialog>
2)script:
//****************************************发布文章********************************************//
// 新增文章弹窗是否显示
const addDialogVisible = ref(false);// 文章对象
const articleForm = reactive({title: '',content: ''
});// 新增文章方法
const add = () => {ElMessage.success(`新增文章成功:${JSON.stringify(articleForm)}`);addDialogVisible.value = false;console.log(articleForm);
};
2)绑定事件
给“新增文章”按钮绑定点击事件:
<el-button type="primary" @click="addDialogVisible = true" size="large">发布文章</el-button>
3.6.3 文章详情
1)文章详情对话框
当点击某篇文章时,查询文章详情。
效果如下:
1)布局代码:
<!-- *************************************************文章详情弹窗************************************************* -->
<el-dialog title="文章详情" v-model="detailDialogVisible" width="60%" top="5vh"><div style="position: relative"><h2 style="text-align: center">如何做一名合格的Java工程师</h2><el-button style="position: absolute;top:0;right: 10px;" type="success" @click="addFavorite(articleDetail.id)">收藏文章</el-button></div><el-divider/><el-card><el-row><el-col :span="3"><strong><el-icon><User/></el-icon>发布人:</strong></el-col><el-col :span="12">{{ articleDetail.publishUser }}</el-col></el-row><el-divider style="width:30%;margin: 10px 0"/><el-row><el-col :span="3"><strong><el-icon><Timer/></el-icon>发布时间:</strong></el-col><el-col :span="12">{{ articleDetail.publishDate }}</el-col></el-row><el-divider style="width:30%;margin: 10px 0"/><el-row><el-col :span="3"><strong><el-icon><Reading/></el-icon>浏览次数:</strong></el-col><el-col :span="12">{{ articleDetail.browseCount }}</el-col></el-row><el-divider style="width:30%;margin: 10px 0"/><el-row><el-col :span="3"><strong><el-icon><StarFilled/></el-icon>收藏次数:</strong></el-col><el-col :span="12">{{ articleDetail.favoriteCount }}</el-col></el-row><el-divider style="width:30%;margin: 10px 0"/><p><strong><el-icon><Document/></el-icon>文章内容:</strong></p><el-input type="textarea" :rows="10" v-model="articleDetail.content" disabled></el-input></el-card><el-divider/><div><p><strong><el-icon><UserFilled/></el-icon>您关注的用户也收藏过这篇文章:</strong></p><el-button v-for="(user, index) in articleDetail.favoriteList">{{ user.realName }}</el-button></div><el-divider/><div style="text-align: center"><el-button type="danger" @click="detailDialogVisible = false"><el-icon><Close/></el-icon>关闭窗口</el-button></div></el-dialog>
2)script:
//****************************************文章详情********************************************//
// 文章详情弹窗是否显示
const detailDialogVisible = ref(false);// 文章详情对话框显示
const showDetail = (id) => {ElMessage.success(`显示文章详情:${id}`);detailDialogVisible.value = true;
}// 文章详情
const articleDetail = reactive({id: 1,title: '如何成为一名Java工程师?',content: '如何成为一名Java工程师如何成为一名Java工程师如何成为一名Java工程师如何成为一名Java工程师',publishUser: '小灰',publishDate: '2030-01-01 10:00:00',collectors: ['小灰', '小蓝'],favoriteCount: 89,browseCount: 1246,favoriteList: [{id: "1", realName: '小灰'},{id: "2", realName: '小蓝'},{id: "3", realName: '小绿'},]
});// 添加/取消收藏
const addFavorite = (id) => {ElMessage.success(`收藏成功:${articleDetail.id}`);
};
2)绑定事件
在文章列表中,给文章标题添加点击事件:
<el-link type="primary" :underline="false" @click="showDetail(article.id)">如何成为一名Java工程师?</el-link>
3.6.4 我的收藏列表
我的收藏页面整体布局和文章列表页面一致,代码可以参考文章列表。
效果如下:
1)布局代码:
<template><!-- *************************************************条件搜索************************************************* --><h3>我收藏的文章</h3><el-row style="width: 100%;"><el-col :span="12"><el-form inline size="large"><el-form-item label="文章标题"><el-input v-model="searchForm.title" placeholder="请输入搜索内容"></el-input></el-form-item><el-form-item><el-button type="primary" @click="search">搜索</el-button></el-form-item></el-form></el-col></el-row><!-- *************************************************文章列表************************************************* --><div><el-card v-for="(article, index) in articles" :key="index" style="margin-bottom: 20px;"><el-link type="primary" :underline="false" @click="showDetail(article.id)">如何成为一名Java工程师?</el-link><p><el-text tag="strong"><el-icon><User/></el-icon>作者:</el-text><el-tag>{{ article.publishUser }}</el-tag></p><p><el-text tag="strong"><el-icon><Timer/></el-icon>发布时间:</el-text><el-tag type="success">{{ article.publishDate }}</el-tag></p><el-text>{{ article.content }}</el-text></el-card></div><!-- *************************************************分页组件************************************************* --><div style="margin-top: 20px;display: flex;justify-content: center;"><el-paginationv-model:current-page="currentPage"v-model:page-size="pageSize":page-sizes="[3, 5, 10]"size="large"layout="total, sizes, prev, pager, next, jumper":total="400"@size-change="handleSizeChange"@current-change="handleCurrentChange"/></div><!-- *************************************************文章详情弹窗************************************************* --><el-dialog title="文章详情" v-model="detailDialogVisible" width="60%" top="5vh"><div style="position: relative"><h2 style="text-align: center">如何做一名合格的Java工程师</h2><el-button style="position: absolute;top:0;right: 10px;" type="success" @click="addFavorite(articleDetail.id)">收藏文章</el-button></div><el-divider/><el-card><el-row><el-col :span="3"><strong><el-icon><User/></el-icon>发布人:</strong></el-col><el-col :span="12">{{ articleDetail.publishUser }}</el-col></el-row><el-divider style="width:30%;margin: 10px 0"/><el-row><el-col :span="3"><strong><el-icon><Timer/></el-icon>发布时间:</strong></el-col><el-col :span="12">{{ articleDetail.publishDate }}</el-col></el-row><el-divider style="width:30%;margin: 10px 0"/><el-row><el-col :span="3"><strong><el-icon><Reading/></el-icon>浏览次数:</strong></el-col><el-col :span="12">{{ articleDetail.browseCount }}</el-col></el-row><el-divider style="width:30%;margin: 10px 0"/><el-row><el-col :span="3"><strong><el-icon><StarFilled/></el-icon>收藏次数:</strong></el-col><el-col :span="12">{{ articleDetail.favoriteCount }}</el-col></el-row><el-divider style="width:30%;margin: 10px 0"/><p><strong><el-icon><Document/></el-icon>文章内容:</strong></p><el-input type="textarea" :rows="10" v-model="articleDetail.content" disabled></el-input></el-card><el-divider/><div><p><strong><el-icon><UserFilled/></el-icon>您关注的用户也收藏过这篇文章:</strong></p><el-button v-for="(user, index) in articleDetail.favoriteList">{{ user.realName }}</el-button></div><el-divider/><div style="text-align: center"><el-button type="danger" @click="detailDialogVisible = false"><el-icon><Close/></el-icon>关闭窗口</el-button></div></el-dialog></template>
2)script:
import {ElMessage} from "element-plus";
import {reactive, ref} from "vue";
import {useRouter} from "vue-router";
import {Close, Timer, User} from "@element-plus/icons-vue";
const router = useRouter(); // 创建路由实例//****************************************搜索表单********************************************//
// 搜索条件
const searchForm = reactive({title: ''
});// 搜索方法
const search = () => {ElMessage.success(`搜索成功${searchForm.title}`);
};//****************************************文章列表********************************************//
const articles = [{id: '1',title: '如何成为一名Java工程师?',publishUser: '小灰',publishDate: '2030-01-01 10:00:00',content: '文章内容'},{id: '2',title: '如何成为一名Java工程师?',publishUser: '小蓝',publishDate: '2030-01-01 10:00:00',content: '文章内容'}
];//****************************************分页组件********************************************//
// 当前页
const currentPage = ref(1)
// 页大小
const pageSize = ref(10)// 当页大小发生改变时执行
const handleSizeChange = (val) => {ElMessage.success(`每页显示:${val}条`)
}// 当当前页发生改变时执行
const handleCurrentChange = (val) => {ElMessage.success(`当前页码:${val}`)
}//****************************************文章详情********************************************//
// 查询文章详情
const showDetail = (id) => {ElMessage.success(`显示文章详情:${id}`);detailDialogVisible.value = true;
}// 文章详情弹窗是否显示
const detailDialogVisible = ref(false);// 文章详情
const articleDetail = reactive({id: 1,title: '如何成为一名Java工程师?',content: '如何成为一名Java工程师如何成为一名Java工程师如何成为一名Java工程师如何成为一名Java工程师',publishUser: '小灰',publishDate: '2030-01-01 10:00:00',collectors: ['小灰', '小蓝'],favoriteCount: 89,browseCount: 1246,favoriteList: [{id: "1", realName: '小灰'},{id: "2", realName: '小蓝'},{id: "3", realName: '小绿'},]
});// 添加/取消收藏
const addFavorite = (id) => {ElMessage.success(`收藏成功:${articleDetail.id}`);
};
3.7 部门模块
效果如下:
1)布局代码:
<template><!-- *************************************************条件搜索************************************************* --><h3>全部部门</h3><el-form inline><el-form-item><el-input v-model="searchText" placeholder="请输入关键字搜索"></el-input></el-form-item></el-form><!-- *************************************************树形组件************************************************* --><el-treeref="treeRef":data="data":default-expand-all="true":filter-node-method="filterNode"></el-tree></template>
2)script:
<script lang="ts" setup> // 注意是ts语法import {ref, watch} from 'vue'
import type {TreeInstance} from 'element-plus'// 树节点数据类型
interface Tree {[key: string]: any
}// 搜索框输入值
const searchText = ref('')// 树组件实例
const treeRef = ref<TreeInstance>()// 监听searchText变化,使用Tree的filter方法过滤树节点
watch(searchText, (val) => {treeRef.value!.filter(val)
})/*** :filter-node-method: 当调用了filter方法时,会触发该方法,该方法的返回值决定是否显示该节点* @param value: 调用filter方法时传入的参数* @param data: 树节点数据* @returns boolean: true表示显示该节点,false表示不显示该节点*/
const filterNode = (value: string, data: Tree) => {// 如果搜索框为空,则显示所有节点if (!value) return true// 如果搜索框不为空,则根据节点的label属性进行匹配return data.label.includes(value)
}// 树组件数据
const data = [{id: 1,label: '研发部',children: [{id: 1,label: '小灰'},{id: 2,label: '小蓝'},{id: 3,label: '小绿'}]},{id: 2,label: '财务部',children: [{id: 4,label: '小红'},{id: 5,label: '小明'}]},{id: 3,label: '人事部',children: [{id: 6,label: '小龙'},{id: 7,label: '小军'}]}
]</script>
3.8 会议模块
3.8.1 会议列表
1)搜索表单
效果如下:
1)布局代码:
<!-- *************************************************条件搜索************************************************* -->
<h3>会议列表</h3><el-row style="width: 100%;"><el-col :span="18"><el-form inline size="large"><el-form-item label="会议标题"><el-input v-model="searchForm.title" placeholder="请输入搜索内容"></el-input></el-form-item><el-form-item label="会议状态"><el-select v-model="searchForm.status" placeholder="请选择" style="width: 160px"><el-option label="全部" :value="-1"></el-option><el-option label="未开始" :value="0"></el-option><el-option label="进行中" :value="1"></el-option><el-option label="已结束" :value="2"></el-option></el-select></el-form-item><el-form-item><el-button type="primary" @click="search">搜索</el-button></el-form-item></el-form></el-col><el-col :span="6" style="text-align: right;"><el-button type="primary" @click="addDialogVisible = true" size="large">发布会议</el-button></el-col></el-row>
2)script:
//****************************************搜索表单********************************************//
// 搜索条件
const searchForm = reactive({title: '',status: -1
});// 搜索方法
const search = () => {ElMessage.success(`搜索成功: ${searchForm.title} - ${searchForm.status}`);
};
2)表格组件
效果如下:
1)布局代码:
<!-- *************************************************会议列表************************************************* -->
<div><el-card v-for="(meeting, index) in meetingList" :key="index" style="margin-bottom: 20px;"><el-link type="primary" :underline="false" @click="showDetail(meeting.id)">{{ meeting.title }}</el-link><p><el-text tag="strong"><el-icon><OfficeBuilding/></el-icon>部门:</el-text><el-tag>{{ meeting.deptName }}</el-tag></p><p><el-text tag="strong"><el-icon><Timer/></el-icon>发布时间:</el-text><el-tag type="success">{{ meeting.startTime }}</el-tag></p><el-text>{{ meeting.content }}</el-text></el-card></div>
2)script:
//****************************************会议列表********************************************//
const meetingList = [{id: '1',title: '关于《协同开发平台》项目部分模块升级的讨论',deptName: '研发部',startTime: '2030-01-01 10:00:00',content: '功能升级如下:支持微信登录、QQ登录,支持通讯录、群组、聊天室、会议室等功能。'},{id: '2',title: '关于《协同开发平台》项目部分模块升级的讨论',deptName: '研发部',startTime: '2030-01-01 10:00:00',content: '功能升级如下:支持微信登录、QQ登录,支持通讯录、群组、聊天室、会议室等功能。'}
];
3)分页组件
效果如下:
1)布局代码:
<!-- *************************************************分页组件************************************************* -->
<div style="margin-top: 20px;display: flex;justify-content: center;"><el-paginationv-model:current-page="currentPage"v-model:page-size="pageSize":page-sizes="[3, 5, 10]"size="large"layout="total, sizes, prev, pager, next, jumper":total="400"@size-change="handleSizeChange"@current-change="handleCurrentChange"/>
</div>
2)script:
//****************************************分页组件********************************************//
// 当前页
const currentPage = ref(1)
// 页大小
const pageSize = ref(10)// 当页大小发生改变时执行
const handleSizeChange = (val) => {ElMessage.success(`每页显示:${val}条`)
}// 当当前页发生改变时执行
const handleCurrentChange = (val) => {ElMessage.success(`当前页码:${val}`)
}
3.8.2 发布会议
1)发布会议对话框
当点击“发布会议”按钮时,应该弹出对话框。
1)布局代码:
<!-- *************************************************发布会议弹窗************************************************* -->
<el-dialog title="发布会议" v-model="addDialogVisible" style="width: 60%;"><el-divider/><el-form ref="form" :model="meetingForm" label-width="80px" size="large"><el-form-item label="文章标题"><el-input v-model="meetingForm.title" placeholder="请输入文章标题"></el-input></el-form-item><el-row><el-col :span="12"><el-form-item label="部门"><el-select v-model="meetingForm.deptId" placeholder="请选择"><el-option label="研发部" :value="1"></el-option><el-option label="产品部" :value="2"></el-option><el-option label="测试部" :value="3"></el-option></el-select></el-form-item></el-col><el-col :span="12"><el-form-item label="抄送人"><el-select v-model="meetingForm.makeUser" placeholder="请选择" multiple><el-option label="小灰" value="1"></el-option><el-option label="小蓝" value="2"></el-option><el-option label="小绿" value="3"></el-option></el-select></el-form-item></el-col></el-row><el-row><el-col :span="12"><el-form-item label="开始时间"><el-date-picker v-model="meetingForm.startTime" type="datetime"placeholder="请选择开始时间"></el-date-picker></el-form-item></el-col><el-col :span="12"><el-form-item label="结束时间"><el-date-picker v-model="meetingForm.endTime" type="datetime" placeholder="请选择结束时间"></el-date-picker></el-form-item></el-col></el-row><el-form-item label="文章内容"><el-input type="textarea" :rows="8" v-model="meetingForm.content" placeholder="请输入文章内容"></el-input></el-form-item></el-form><el-divider/><div slot="footer" class="dialog-footer"><el-button type="primary" @click="add">确 定</el-button><el-button @click="addDialogVisible = false">取 消</el-button></div></el-dialog>
2)script:
//****************************************发布会议********************************************//// 新增会议弹窗是否显示
const addDialogVisible = ref(false);// 会议对象
const meetingForm = reactive({id: '',title: '',content: '',deptId: 1,startTime: '',endTime: '',makeUser: []
});// 新增会议方法
const add = () => {ElMessage.success(`新增会议成功:${JSON.stringify(meetingForm)}`);addDialogVisible.value = false;console.log(meetingForm);
};
2)绑定事件
给“发布会议”按钮绑定事件:
<el-button type="primary" @click="addDialogVisible = true" size="large">发布会议</el-button>
3.8.2 会议详情对话框
1)会议详情对话框
当点击某个会议标题时,查询会议详情。
效果如下:
1)布局代码:
<!-- *************************************************会议详情弹窗************************************************* -->
<el-dialog title="会议详情" v-model="detailDialogVisible" width="60%" top="2vh"><div style="position: relative"><h2 style="text-align: center">{{ meetingDetail.title }}</h2><el-button style="position: absolute;top:0;right: 10px;" type="success" @click="joinMeeting(meetingDetail.id)">参加会议</el-button></div><el-divider/><el-card><el-row><el-col :span="3"><strong><el-icon><OfficeBuilding/></el-icon>部门:</strong></el-col><el-col :span="12">{{ meetingDetail.deptName }}</el-col></el-row><el-divider style="width:30%;margin: 10px 0"/><el-row><el-col :span="3"><strong><el-icon><Timer/></el-icon>发布时间:</strong></el-col><el-col :span="12">{{ meetingDetail.publishDate }}</el-col></el-row><el-divider style="width:30%;margin: 10px 0"/><el-row><el-col :span="3"><strong><el-icon><CirclePlusFilled/></el-icon>开始时间:</strong></el-col><el-col :span="12">{{ meetingDetail.startTime }}</el-col></el-row><el-divider style="width:30%;margin: 10px 0"/><el-row><el-col :span="3"><strong><el-icon><RemoveFilled/></el-icon>结束时间:</strong></el-col><el-col :span="12">{{ meetingDetail.endTime }}</el-col></el-row><el-divider style="width:30%;margin: 10px 0"/><el-row><el-col :span="3"><strong><el-icon><Promotion/></el-icon>应到人数:</strong></el-col><el-col :span="3"><el-tag type="primary"> {{ meetingDetail.joinCount }}</el-tag></el-col><el-col :span="3"><strong><el-icon><SuccessFilled/></el-icon>实到人数:</strong></el-col><el-col :span="3"><el-tag type="success"> {{ meetingDetail.realCount }}</el-tag></el-col><el-col :span="3"><strong><el-icon><RemoveFilled/></el-icon>未到人数:</strong></el-col><el-col :span="3"><el-tag type="danger"> {{ meetingDetail.noCount }}</el-tag></el-col></el-row><el-divider style="width:80%;margin: 10px 0"/><p><strong><el-icon><Document/></el-icon>会议内容:</strong></p><el-input type="textarea" :rows="10" v-model="meetingDetail.content" disabled></el-input></el-card><el-divider/><div><p><strong><el-icon><UserFilled/></el-icon>以下用户需要参加本次会议:</strong></p><el-button :type="user.joinMeeting ? 'primary' : 'danger'" disabledv-for="(user, index) in meetingDetail.makeUser">{{ user.realName }}</el-button></div><el-divider/><div style="text-align: center"><el-button type="danger" @click="detailDialogVisible = false"><el-icon><Close/></el-icon>关闭窗口</el-button></div></el-dialog>
2)script:
//****************************************会议详情********************************************//
// 会议详情弹窗是否显示
const detailDialogVisible = ref(false);// 查询会议详情
const showDetail = (id) => {ElMessage.success(`显示会议详情:${id}`);detailDialogVisible.value = true;
}// 会议详情
const meetingDetail = reactive({id: 1,title: '关于《协同开发平台》项目部分模块升级的讨论',content: '功能升级如下:支持微信登录、QQ登录,支持通讯录、群组、聊天室、会议室等功能。',deptName: '研发部',publishDate: '2030-01-01 10:00:00',startTime: '2030-01-01 10:00:00',endTime: '2050-01-01 10:00:00',joinCount: 4,realCount: 2,noCount: 2,makeUser: [{id: "1", realName: '小灰', joinMeeting: true},{id: "2", realName: '小蓝', joinMeeting: false},{id: "3", realName: '小绿', joinMeeting: true},{id: "4", realName: '小红', joinMeeting: false},]
});// 添加/取消收藏
const joinMeeting = (id) => {ElMessage.success(`参加成功:${meetingDetail.id}`);
};