这里写目录标题
一、顶部盒子设计
1. 顶部盒子包含项目列表和添加项目、退出登录2个按钮
<template>
<!-- 项目列表页面 -->
<div class="pros_box">
<!-- 顶部的盒子 -->
<div class="top_box">
<span>项目列表</span>
<el-button icon="User" color="#00aa7f">退出登录</el-button>
<el-button icon="Plus" color="#00aa7f">添加项目</el-button>
</div
</div>
</template>
<script>
</script>
<style scoped>
/* 顶部内容 */
.top_box{
border-bottom:solid 5px #00aa7f;
height: 50px; 设置高度
font:bold 20px/40px '微软雅黑';
color: #00aa7f; 设置背景颜色
margin: 20px auto;
}
/* 大盒子 */
.pros_box{
margin: 30px auto;
max-width: 1400px;
}
/* 顶部按钮 */
.top_box .el-button{
float:right; 右浮动
margin: 10px;
}
</style>
二、项目列表盒子设计
项目列表页面(整个页面的大盒子)包含显示项目列表的区域(显示所有项目的盒子)包含单个项目(单个项目的盒子)包含图标、项目名称、负责人、2个按钮,共4个盒子
<template>
<!-- 项目列表页面 -->
<div class="pros_box">
<!-- 顶部的盒子 -->
<div class="top_box">
<span>项目列表</span>
<el-button icon="User" color="#00aa7f">退出登录</el-button>
<el-button icon="Plus" color="#00aa7f">添加项目</el-button>
</div>
<!-- 显示项目列表的区域 -->
<div class="pro_list">
<!-- 单个项目 -->
<el-card class="pro">
<!-- 图标 -->
<div class="pro_icon">
<el-icon><Platform /></el-icon>
</div>
<!-- 项目名称 -->
<div class="pro_name">
演示项目
</div>
<!-- 负责人 -->
<div class="leader">
负责人:kobe
</div>
<div class="btns">
<el-button size="small" icon="Edit" style="float:left;" color="#efefef">编辑</el-button>
<el-button size="small" icon="Delete" style="float:right;" color="#efefef">删除</el-button>
</div>
</el-card>
</div>
</div>
</template>
<script>
</script>
<style scoped>
/* 顶部内容 */
.top_box{
border-bottom:solid 5px #00aa7f;
height: 50px;
/* 设置字体加粗 宽度和高度 */
font:bold 20px/40px '微软雅黑';
/* 设置颜色 */
color: #00aa7f;
margin: 20px auto;
}
/* 大盒子 */
.pros_box{
margin: 30px auto;
/* 设置最大宽度 */
max-width: 1400px;
}
/* 顶部按钮 */
.top_box .el-button{
/* 右浮动 */
float:right;
margin: 10px;
}
/* 项目列表样式 */
.pro{
width:200px;
height: 250px;
float: left;
margin: 10px;
}
/* 项目中图标的样式 */
.pro .pro_icon{
width: 60px;
height: 60px;
border-radius: 30px;
/* 背景颜色 */
background: #e1ffed;
color: #00aa7f;
font: normal 30px/60px '微软雅黑';
/* 居中 */
text-align: center;
margin: 0 auto;
}
/* 项目名称的样式 */
.pro .pro_name{
text-align: center;
margin-top: 20px;
font: bold 18px/20px '微软雅黑';
}
/* 负责人 */
.pro .leader{
text-align: center;
color: rgb(55, 28, 206);
/* 设置:字体/行高 */
font: normal 15px/40px '微软雅黑';
/* margin-bottom: 10px; */
}
/* 按钮区域 */
.pro .btns{
margin-top: 50px;
text-align: center;
}
</style>
三、添加项目盒子设计
<template>
......
......
<!-- 添加项目的盒子 -->
<el-card class="pro">
<div class="add_box">
<el-icon :size="50" color="green"><Plus /></el-icon>
</div>
</el-card>
</template>
<style scoped>
......
/* 添加项目 */
.pro .add_box{
/* 水平居中 */
text-align: center;
/* 高度 */
/* height: 250px; */
/* 行高 */
line-height: 200px;
}
......
</style>
四、退出登录功能实现
<el-button @click="logout" icon='User' color='#00aa7f'>退出登录</el-button>
<script>
export default{
data(){
return{
}
},
methods:{
// 退出登录
logout(){
//清除token和用户名
window.sessionStorage.removeItem('token')
window.sessionStorage.removeItem('username')
//跳转到登录页面
this.$router.push({name:'login'})
}
}
}
</script>
五、路由导航守卫实现
添加路由导航守卫,控制前端页面访问的权限
router.beforeEach(async (to, from) => {
// 获取sessionStorage是否存在token,如果存在token视为已经登录
const isAuthenticated = window.sessionStorage.getItem('token')
if (
// 检查用户是否已登录
!isAuthenticated &&
// ❗️ 避免无限重定向
to.name !== 'login'
) {
// 将用户重定向到登录页面
return { name: 'login' }
}
})
六、展示项目信息
<script>
export default{
data(){
return{
//项目列表信息
projectList:[
]
}
},
methods:{
...
...
// 通过接口获取后端所有的项目
async getAllProject(){
const response= await this.$api.getAllProjects()
if(response.status===200){
console.log(response.data)
// 将获取到的项目信息保存到data中
this.projectList=response.data
}
}
},
// 钩子函数,最先执行的方法
created(){
this.getAllProject()
}
}
</script>
<!-- 显示项目列表的区域 -->
<div class="pro_list">
<!-- 单个项目显示在一个el-card -->
<el-card class="pro" v-for="pro in projectList" :key='pro.id'>
<!-- 图标 -->
<div class="pro_icon">
<el-icon><Platform /></el-icon>
</div>
<!-- 项目名称 -->
<div class="pro_name">
{{pro.name}}
</div>
<!-- 项目负责人 -->
<div class="pro_leader">
{{pro.leader}}
</div>
<!-- 按钮 -->
<div class="btns">
<el-button color="#d9d9d9" class="edit" size="small" icon="Edit">编辑</el-button>
<el-button color="#F5F5DC" class="del" size="small" icon="Delete">删除</el-button>
</div>
</el-card>
<!-- 添加项目的空盒子-->
<el-card class="pro">
<!-- 图标 -->
<div class="add_pro">
<el-icon :size=70>
<Plus/>
</el-icon>
</div>
</el-card>
</div>
七、bug修复
1、当项目名称太长或者项目负责人太长,需要一行展示,当超过8个字…展示
<!-- 项目名称 -->
<div class="pro_name">
<span v-if="pro.name.length<8">{{pro.name}}</span>
<el-tooltip v-else class="item" effect="dark" v-bind:content=pro.name placement="top-start">
{{pro.name.slice(0,8)}}...
</el-tooltip>
</div>
<!-- 项目负责人 -->
<div class="pro_leader">
<span v-if="pro.leader.length<8">{{pro.leader}}</span>
<el-tooltip v-else class="item" effect="dark" v-bind:content=pro.leader placement="top-start">
{{pro.leader.slice(0,8)}}...
</el-tooltip>
</div>
八、删除单个项目
index.js
export default{
// 登录接口
login(params){
return http.post('/login/',params)
},
// ---------------------------项目操作的api---------------------------
// 获取项目列表
getAllProjects(){
return http.get('/projects/')
},
// 删除项目的接口
delProject(id){
return http.delete(`/projects/${id}/`)
}
}
<div class="btns">
<el-button color="#d9d9d9" class="edit" size="small" icon="Edit">编辑</el-button>
<el-button color="#F5F5DC" class="del" size="small" icon="Delete" @click="clickDelete(pro.id)">删除</el-button>
</div>
<script>
import { ElMessage, ElMessageBox } from 'element-plus'
export default{
data(){
return{
//项目列表信息
projectList:[
]
}
},
methods:{
...
...
// 通过接口获取后端所有的项目
async getAllProject(){
const response= await this.$api.getAllProjects()
if(response.status===200){
console.log(response.data)
// 将获取到的项目信息保存到data中
this.projectList=response.data
}
},
// 调用接口删除项目
async deletePro(proId){
//发送接口请求
const response = await this.$api.delProject(proId)
if(response.status===204){
//更新页面的数据
this.getAllProject()
//提示删除成功
this.$message({
type: 'success',
message: '删除成功!'
})
}
},
// 点击删除项目
clickDelete(id){
this.$confirm('此操作不可恢复,确定要删除吗?', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
// 调用删除的接口
this.deletePro(id)
// 取消操作 -->
}).catch(() => {
this.$message({
type: 'info',
message: '已取消删除'
});
});
}
},
// 钩子函数,最先执行的方法
created(){
this.getAllProject()
}
}
</script>
九、添加项目功能
index.js
export default{
// 登录接口
login(params){
return http.post('/login/',params)
},
// ---------------------------项目操作的api---------------------------
// 获取项目列表
getAllProjects(){
return http.get('/projects/')
},
// 删除项目的接口
delProject(id){
return http.delete(`/projects/${id}/`)
},
//添加项目的接口
createProject(params){
return http.post('/projects/',params)
}
}
<!-- 顶部盒子 -->
<div class="top_box">
<span>项目列表</span>
<el-button @click="logout" icon='User' color='#00aa7f'>退出登录</el-button>
<el-button @click="addDlg=true" icon='Plus' color='#00aa7f'>添加项目</el-button>
</div>
<!-- 添加项目的空盒子-->
<el-card class="pro">
<!-- 图标 -->
<div class="add_pro" @click="addDlg=true">
<el-icon :size=70>
<Plus/>
</el-icon>
</div>
</el-card>
<!-- 添加项目的弹框 -->
<el-dialog v-model="addDlg" title="添加项目" >
<el-form :model="form">
<el-form-item label="项目名称">
<el-input v-model="addForm.name"></el-input>
</el-form-item>
<el-form-item label="负责人">
<el-input v-model="addForm.leader"></el-input>
</el-form-item>
</el-form>
<div class="dialog-footer">
<el-button @click="addDlg = false">取 消</el-button>
<el-button type="primary" @click="addPro">确 定</el-button>
</div>
</el-dialog>
<script>
import { ElMessage, ElMessageBox } from 'element-plus'
export default{
data(){
return{
//项目列表信息
projectList:[
],
// 添加项目的弹框是否显示
addDlg:false,
// 向表单中输入的文字
addForm:{
name:"",
leader:""
}
}
},
methods:{
...
...
...
// 添加项目
async addPro(){
// 发送请求
const response=await this.$api.createProject(this.addForm)
if(response.status===201){
//更新页面的数据
this.getAllProject()
// 关闭窗口
this.addDlg=false
this.$message({
type: 'success',
message: '添加成功!'
})
}
}
},
// 钩子函数,最先执行的方法
created(){
this.getAllProject()
}
}
</script>
十、编辑和添加使用同一个弹框
title:不写死
在data中设置dlgTitle为弹窗的标题
接着在显示title的地方,设置数据绑定
给编辑按钮添加一个事件clickEdit
修改点击添加的方法clickAdd
十一、编辑项目
index.js
export default{
// 登录接口
login(params){
return http.post('/login/',params)
},
// ---------------------------项目操作的api---------------------------
// 获取项目列表
getAllProjects(){
return http.get('/projects/')
},
// 删除项目的接口
delProject(id){
return http.delete(`/projects/${id}/`)
},
//添加项目的接口
createProject(params){
return http.post('/projects/',params)
},
// 修改项目
updateProject(id,params){
return http.patch(`/projects/${id}/`,params)
}
}
根据dlgTitle发送不同的接口
id怎么传?
this.addForm={…pro}:将项目信息赋值给addForm
十二、总体实现代码
<template>
<!-- 项目列表页面 -->
<div class="pros_box">
<!-- 顶部盒子 -->
<div class="top_box">
<span>项目列表</span>
<el-button @click="logout" icon='User' color='#00aa7f'>退出登录</el-button>
<el-button @click="clickAdd" icon='Plus' color='#00aa7f'>添加项目</el-button>
</div>
<!-- 显示项目列表的区域 -->
<div class="pro_list">
<!-- 单个项目显示在一个el-card -->
<el-card class="pro" v-for="pro in projectList" :key='pro.id'>
<div style="cursor: pointer;" @click="selectPro(pro)">
<!-- 图标 -->
<div class="pro_icon">
<el-icon><Platform /></el-icon>
</div>
<!-- 项目名称 -->
<div class="pro_name">
<span v-if="pro.name.length<8">{{pro.name}}</span>
<el-tooltip v-else class="item" effect="dark" v-bind:content=pro.name placement="top-start">
{{pro.name.slice(0,8)}}...
</el-tooltip>
</div>
<!-- 项目负责人 -->
<div class="pro_leader">
<span v-if="pro.leader.length<8">{{pro.leader}}</span>
<el-tooltip v-else class="item" effect="dark" v-bind:content=pro.leader placement="top-start">
{{pro.leader.slice(0,8)}}...
</el-tooltip>
</div>
</div>
<!-- 按钮 -->
<div class="btns">
<el-button @click="clickEdit(pro)" color="#d9d9d9" class="edit" size="small" icon="Edit">编辑</el-button>
<el-button color="#F5F5DC" class="del" size="small" icon="Delete" @click="clickDelete(pro.id)">删除</el-button>
</div>
</el-card>
<!-- 添加项目的空盒子-->
<el-card class="pro">
<!-- 图标 -->
<div class="add_pro" @click="clickAdd">
<el-icon :size=70>
<Plus/>
</el-icon>
</div>
</el-card>
</div>
</div>
<!-- 添加项目的弹框 -->
<!-- <el-dialog v-model="addDlg" title="添加项目" > -->
<!-- <el-form :model="form">
<el-form-item label="项目名称">
<el-input v-model="addForm.name"></el-input>
</el-form-item>
<el-form-item label="负责人">
<el-input v-model="addForm.leader"></el-input>
</el-form-item>
</el-form> -->
<!-- <div class="dialog-footer">
<el-button @click="addDlg = false">取 消</el-button>
<el-button type="primary" @click="addPro">确 定</el-button>
</div>
</el-dialog> -->
<!-- 添加和编辑项目的弹窗 -->
<el-dialog v-model="addDlg" :title="dlgTitle" >
<el-form :model="form">
<el-form-item label="项目名称">
<el-input v-model="addForm.name"></el-input>
</el-form-item>
<el-form-item label="负责人">
<el-input v-model="addForm.leader"></el-input>
</el-form-item>
</el-form>
<div class="dialog-footer">
<el-button @click="addDlg = false">取 消</el-button>
<!-- <el-button type="primary" @click="addPro">确 定</el-button> -->
<el-button v-if='(dlgTitle==="添加项目")' type="primary" @click="addPro">确 定</el-button>
<el-button v-else type="primary" @click="updatePro">提交修改</el-button>
</div>
</el-dialog>
</template>
<script>
import { ElMessage, ElMessageBox } from 'element-plus'
// 导入映射方法的函数mapActions
import { mapActions } from 'pinia'
import { userStore } from '../store/user.js'
export default{
data(){
return{
//项目列表信息
projectList:[
],
// 添加项目的弹框是否显示
addDlg:false,
addForm:{
name:"",
leader:""
},
// 弹框的标题
dlgTitle:"添加项目"
}
},
methods:{
// 退出登录
// logout(){
// //清除token和用户名
// window.sessionStorage.removeItem('token')
// window.sessionStorage.removeItem('username')
// //跳转到登录页面
// this.$router.push({name:'login'})
// },
// 将全局定义的logout方法,映射为当前组件的logout方法
...mapActions(userStore,['logout','savePro']),
// 通过接口获取后端所有的项目
async getAllProject(){
const response= await this.$api.getAllProjects()
if(response.status===200){
console.log(response.data)
// 将获取到的项目信息保存到data中
this.projectList=response.data
}
},
// 调用接口删除项目
async deletePro(proId){
//发送接口请求
const response = await this.$api.delProject(proId)
if(response.status===204){
//更新页面的数据
this.getAllProject()
//提示删除成功
this.$message({
type: 'success',
message: '删除成功!'
})
}
},
// 点击删除项目
clickDelete(id){
this.$confirm('此操作不可恢复,确定要删除吗?', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
// 调用删除的接口
this.deletePro(id)
// 取消操作 -->
}).catch(() => {
this.$message({
type: 'info',
message: '已取消删除'
});
});
},
// 添加项目
async addPro(){
// 发送请求
const response=await this.$api.createProject(this.addForm)
if(response.status===201){
//更新页面的数据
this.getAllProject()
// 关闭窗口
this.addDlg=false
this.$message({
type: 'success',
message: '添加成功!'
})
}
},
// 点击编辑执行 的方法
clickEdit(pro){
// 修改title
this.dlgTitle='编辑项目'
// 将项目信息赋值给addForm
this.addForm={...pro}
// 显示编辑框
this.addDlg=true
},
// 点击添加项目
clickAdd(){
this.dlgTitle='添加项目'
// 将项目信息addForm置空
this.addForm={
name:'',
leader:''
}
// 展示弹窗
this.addDlg=true
},
// 发送请求,修改编辑后的项目信息
async updatePro(){
const id=this.addForm.id
const params={
leader:this.addForm.leader,
name:this.addForm.name
}
const response=await this.$api.updateProject(id,params)
if(response.status===200){
//更新页面的数据
this.getAllProject()
// 提示
this.$message({
type: 'success',
message: '修改成功!'
})
}
// 关闭窗口
this.addDlg=false
},
// 选择进入的项目
selectPro(pro){
this.$router.push({name:"home"})
console.log(666)
// 将项目信息保存到vue的全局数据存储仓库
this.savePro(pro)
}
},
// 钩子函数,最先执行的方法
created(){
this.getAllProject()
}
}
</script>
<style scoped>
/* ----------------顶部样式--------------------- */
/* 整体盒子 */
.pros_box{
max-width: 1480px;
margin: 30px auto;
}
/* 顶部盒子 */
.top_box{
border-bottom: solid 5px green;
height: 40px;
font: bold 20px/40px '微软雅黑';
color: #00aa7f;
margin: 20px auto;
}
/* 顶部按钮 */
.top_box .el-button{
float: right;
margin-left: 10px;
}
/* ------------------项目列表样式-------------------------- */
.pro{
width: 200px;
height: 250px;
margin: 20px;
float: left;
}
/* 项目中图标样式 */
.pro .pro_icon{
width: 80px;
height: 80px;
border-radius: 40px;
background: #e1ffed;
color: #00aa7f;
font: normal 30px/60px '微软雅黑';
text-align: center;
margin: 0 auto;
}
/* 项目名称的样式 */
.pro .pro_name{
text-align: center;
margin-top: 20px;
font: bold 18px/40px '微软雅黑';
}
/* 负责人的样式 */
.pro .pro_leader{
text-align: center;
color: blue;
font: normal 12px/20px '微软雅黑';
}
/* 按钮区域的样式 */
.pro .btns{
margin-top: 30px;
}
.pro .btns .edit{
float: left;
}
.pro .btns .del{
float: right;
}
/*添加的盒子样式*/
.pro .add_pro{
text-align: center;
height: 250px;
line-height: 250px;
color: #d3d4d3;
}
</style>
index.js路由设置
const routes = [
{
path: '/',
name: 'index',
redirect:{name:"login"}
},
{
path: '/user/login',
name: 'login',
component: () => import('../views/Login.vue')
},
{
path: '/allProject',
name: 'allProject',
component: () => import('../views/AllProject.vue')
},
{
path: '/home',
name: 'home',
component: () => import('../views/Home.vue')
},
]
十三:鼠标放上指定的位置变成手,点击进入home页面
用大的div包起来
<!-- 单个项目显示在一个el-card -->
<el-card class="pro" v-for="pro in projectList" :key='pro.id'>
<div style="cursor: pointer;" @click="selectPro(pro)">
<!-- 图标 -->
<div class="pro_icon">
<el-icon><Platform /></el-icon>
</div>
<!-- 项目名称 -->
<div class="pro_name">
<span v-if="pro.name.length<8">{{pro.name}}</span>
<el-tooltip v-else class="item" effect="dark" v-bind:content=pro.name placement="top-start">
{{pro.name.slice(0,8)}}...
</el-tooltip>
</div>
<!-- 项目负责人 -->
<div class="pro_leader">
<span v-if="pro.leader.length<8">{{pro.leader}}</span>
<el-tooltip v-else class="item" effect="dark" v-bind:content=pro.leader placement="top-start">
{{pro.leader.slice(0,8)}}...
</el-tooltip>
</div>
</div>
<!-- 按钮 -->
<div class="btns">
<el-button @click="clickEdit(pro)" color="#d9d9d9" class="edit" size="small" icon="Edit">编辑</el-button>
<el-button color="#F5F5DC" class="del" size="small" icon="Delete" @click="clickDelete(pro.id)">删除</el-button>
</div>
</el-card>