前言
对于多个项目的使用,可能需要进行项目切换管理,所以这里创建一个项目管理页面,登录成功后跳转这个页面,进行选择项目,再进入Home页面展示对应项目的内容。
一、实现效果图预览
二、页面内容
功能1、项目列表展示
这里使用element-plus的走马灯效果来实现
elment-plus走马灯效果
走马灯数据从接口获取。有多少项目,就展示多少
1、封装接口
2、在setup中请求后端数据,并赋值
//首先获取项目数据,接口定义
<script setup>
import {ref} from 'vue'
import http from '@/api/index'
let proList = ref([])
console.log('1::',proList.value)
async function getProList(){
const resposne = await http.pro.getProListApi()
if(resposne.status == 200){
console.log(resposne.data)
proList.value = resposne.data
}
}
getProList()
</script>
3、通过循环展示
<template>
<el-carousel :interval="4000" type="card" height="200px" motion-blur>
<el-carousel-item v-for="item in proList" :key="item.id">
<h3 text="2xl" justify="center">{{ item.name }}</h3>
</el-carousel-item>
</el-carousel>
</template>
剩下的内容就是把这些换成自己喜欢的图片,再加亿点点css样式美化一下页面。
功能2、创建新项目
在右上角新增一个按钮,点击展示添加项目的表单界面,填写内容,再提交(注意封装api接口),提交完成后,再刷新一下列表数据,展示到页面。
1. 界面增加按钮和添加弹窗
<el-button icon="CirclePlus" size="small" @click='showDlg'>添加项目</el-button>
...
<!-- 添加项目的弹框 -->
<el-dialog v-model="isDlgShow" title="添加项目">
<el-form :model="fromData" label-width="80">
<el-form-item label="项目名称">
<el-input v-model="fromData.name" autocomplete="off" />
</el-form-item>
<el-form-item label="负责人">
<el-select v-model="fromData.leader" placeholder="选择负责人" >
<el-option v-for="item in users" :key="item.id" :value="item.id" :label="item.nickname">
</el-option>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="isDlgShow = false">取消</el-button>
<el-button type="primary" @click="creatPro">确认</el-button>
</span>
</template>
</el-dialog>
2. 添加函数功能
import {ref,reactive} from 'vue'
import {ElNotification} from 'element-plus'
import http from '@/api/index'
...
// ===================实现项目添加的功能=================
let isDlgShow = ref(false)
let users = ref([])
let fromData = reactive({
name: "",
leader: ""
})
// 加载用户
async function getUserList(){
const response = await http.user.getUserListApi()
users.value = response.data
console.log(users.value)
}
// 显示添加窗口
function showDlg() {
isDlgShow.value = true
}
// 发送请求添加项目
async function creatPro() {
const response = await api.createProApi(fromData)
if (response.status === 201) {
// 弹出提示
ElNotification({
title: '项目创建成功',
type: 'success',
})
// 关闭窗口
isDlgShow.value = false
// 刷新页面数据
getProList()
}
}
功能3、编辑和删除项目
再新增两个按钮,编辑和删除
<!-- 按钮 -->
<div class="btn_box1">
<el-button @click='clickEdit(item)' plain icon='Edit' type="primary" size="small"></el-button>
</div>
<div class="btn_box2">
<el-button @click='clickDelete(item.id)' plain icon='Delete' type="danger" size="small"></el-button>
</div>
编辑
// api/module/ProjectApi.js
editProApi(pro_id,data){
return request.patch(`/api/testPro/editProject/${pro_id}`,data)
}
// ProView.vue
// ===========实现项目修改的功能===================
let isUpdateDlgShow = ref(false)
let fromUpdateData = ref({
name: "",
leader: ""
})
// 点击编辑按钮时调用的方法
function clickEdit(pro) {
getUserList()
isUpdateDlgShow.value = true
fromUpdateData.value = { ...pro }
// console.log("edit::",pro,{ ...pro })
}
// 发送请求修改项目信息
async function updatePro() {
let pro_id = fromUpdateData.value.id
const response = await http.pro.editProApi(pro_id, fromUpdateData.value)
if (response.status === 200) {
ElNotification({
title: '项目修改成功',
type: 'success',
duration: 3000
})
// 关闭窗口
isUpdateDlgShow.value = false
// 刷新页面上的数据
getProList()
}
}
删除
// ==============实现项目删除的功能=====================
function clickDelete(pro_id) {
// 调用后端的接口进行删除
ElMessageBox.confirm(
'删除操作不可恢复,请确认是否要删除该项目?',
'提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(async () => {
// 调用接口进行删除
const response = await http.pro.deleteProApi(pro_id)
if (response.status === 204) {
ElMessage({
type: 'success',
message: '已成功删除该项目',
})
// 刷新页面数据
getProList()
}
})
.catch(() => {
ElMessage({
type: 'info',
message: '已取消删除操作',
})
})
}
功能4、进入Home页面
1.新建一个用于存储项目数据的pinia
// stores/moudel/ProStore.js
import {defineStore} from "pinia"
import http from '@/api/index'
export const ProjectStore = defineStore('proStore',{
state:() => {
return {
pro : {},
}
},
persist:{
enabled:true,
strategies:[
{
key:'proInfo',
storage:localStorage
}
]
}
})
2. 选择项目点击跳转到home页
同时将选择的项目信息持久化储存到pinia中,以便后续使用
// ===================点击进入选择的项目=================
function enterProject(pro){
console.log('enterclick')
const proStore = ProjectStore()
// 保存项目信息
proStore.pro = pro
router.push('home')
}
三、总结
- elment-plus走马灯数据展示
- el-select 下拉选择器
- ElNotification,ElMessage 消息反馈
- pinia持久化存储
部分页面代码
ProjectApi.js
import request from "@/api/request";
//导出请求方法
export default {
//获取项目列表
getProListApi(){
return request.get('/api/testPro/projects')
},
createProApi(data){
return request.post('/api/testPro/projects',data)
},
editProApi(pro_id,data){
return request.patch(`/api/testPro/editProject/${pro_id}`,data)
},
deleteProApi(pro_id){
return request.delete(`/api/testPro/Projects/${pro_id}`)
}
}
ProView.vue
<template>
<div class="pro_page">
<div class="pro_box">
<div class="welcome">
<span>欢迎使用自动化测试平台</span>
<el-button icon="CirclePlus" size="small" @click='showDlg'>添加项目</el-button>
</div>
<div class="pro_list">
<el-carousel :interval="4000" type="card" height="400px" motion-blur>
<el-carousel-item v-for="(item,index) in proList" :key="index">
<div class="pro">
<div @click='enterProject(item)'>
<!-- 图片 -->
<img src="@/assets/procard.jpg">
<!-- 名称 -->
<div class="name">
{{item.name}}
</div>
</div>
<!-- 按钮 -->
<div class="btn_box1">
<el-button @click='clickEdit(item)' plain icon='Edit' type="primary" size="small"></el-button>
</div>
<div class="btn_box2">
<el-button @click='clickDelete(item.id)' plain icon='Delete' type="danger" size="small"></el-button>
</div>
</div>
</el-carousel-item>
</el-carousel>
</div>
<div class="iod">
我觉得该写点什么,但是又不知道写点什么。
</div>
<div class="iod">
只是觉得这样看起来这里很空旷,随便写点东西占个位置
</div>
</div>
<!-- 添加项目的弹框 -->
<el-dialog v-model="isDlgShow" title="添加项目">
<el-form :model="fromData" label-width="80">
<el-form-item label="项目名称">
<el-input v-model="fromData.name" autocomplete="off" />
</el-form-item>
<el-form-item label="负责人">
<el-select v-model="fromData.leader" placeholder="选择负责人" >
<el-option v-for="item in users" :key="item.id" :value="item.id" :label="item.nickname"></el-option>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="isDlgShow = false">取消</el-button>
<el-button type="primary" @click="creatPro">确认</el-button>
</span>
</template>
</el-dialog>
<!-- 修改项目的弹框 -->
<el-dialog v-model="isUpdateDlgShow" title="编辑项目">
<el-form :model="fromUpdateData" label-width="80">
<el-form-item label="项目名称">
<el-input v-model="fromUpdateData.name" autocomplete="off" />
</el-form-item>
<el-form-item label="负责人">
<el-select v-model="fromUpdateData.leader" placeholder="选择负责人" >
<el-option v-for="item in users" :key="item.id" :value="item.nickname" :label="item.nickname"></el-option>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="isUpdateDlgShow = false">取消</el-button>
<el-button type="primary" @click="updatePro">确认</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup>
import {ref,reactive} from 'vue'
import {ElNotification,ElMessageBox,ElMessage} from 'element-plus'
import http from '@/api/index'
let proList = ref([])
async function getProList(){
const resposne = await http.pro.getProListApi()
if(resposne.status == 200){
// console.log(resposne.data)
proList.value = resposne.data
}
}
getProList()
// ===================实现项目添加的功能=================
let isDlgShow = ref(false)
let users = ref([])
let fromData = reactive({
name: "",
leader: ""
})
// 加载用户
async function getUserList(){
const response = await http.user.getUserListApi()
users.value = response.data
// console.log(users.value)
}
// 显示添加窗口
function showDlg() {
getUserList()
isDlgShow.value = true
}
// 发送请求添加项目
async function creatPro() {
const response = await http.pro.createProApi(fromData)
if (response.status === 201) {
// 弹出提示
ElNotification({
title: '项目创建成功',
type: 'success',
duration: 3000
})
// 关闭窗口
isDlgShow.value = false
// 刷新页面数据
getProList()
}
}
// ===========实现项目修改的功能===================
let isUpdateDlgShow = ref(false)
let fromUpdateData = ref({
name: "",
leader: ""
})
// 点击编辑按钮时调用的方法
function clickEdit(pro) {
getUserList()
isUpdateDlgShow.value = true
fromUpdateData.value = { ...pro }
// console.log("edit::",pro,{ ...pro })
}
// 发送请求修改项目信息
async function updatePro() {
let pro_id = fromUpdateData.value.id
const response = await http.pro.editProApi(pro_id, fromUpdateData.value)
if (response.status === 200) {
ElNotification({
title: '项目修改成功',
type: 'success',
duration: 3000
})
// 关闭窗口
isUpdateDlgShow.value = false
// 刷新页面上的数据
getProList()
}
}
// ==============实现项目删除的功能=====================
function clickDelete(pro_id) {
// 调用后端的接口进行删除
ElMessageBox.confirm(
'删除操作不可恢复,请确认是否要删除该项目?',
'提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(async () => {
// 调用后端接口进行删除
const response = await http.pro.deleteProApi(pro_id)
if (response.status === 204) {
ElMessage({
type: 'success',
message: '已成功删除该项目',
})
// 刷新页面数据
getProList()
}
})
.catch(() => {
ElMessage({
type: 'info',
message: '已取消删除操作',
})
})
}
</script>
<style lang='scss' scoped>
@use './pro.scss';
</style>
pro.scss
.pro_page{
background-color: aliceblue;
background-image:url('@/assets/bg.jpeg') ;
height: 100vh;
min-height: 700px;
background-size: cover;
.pro_box{
height: 94%;
width: 96%;
background-color: rgba(255, 255, 255, 0.8);
border-radius: 10px;
position: relative;
left: 2%;
top: 3%;
.el-button{
position: absolute; // 设置绝对定位
top: 10px;
right: 10px;
}
.iod{
margin-top: 20px;
display: flex; // 使用 Flexbox 布局
justify-content: center; // 水平居中
align-items: center; // 垂直居中
color: #2a2a2a;
font-size: 24px;
font-weight: bold;
height: 80px;
line-height: 80px;
}
// 顶部内容
.welcome{
display: flex; // 使用 Flexbox 布局
justify-content: center; // 水平居中
align-items: center; // 垂直居中
color: #2a2a2a;
font-size: 24px;
font-weight: bold;
height: 80px;
line-height: 80px;
}
// 项目卡片
.pro_list{
.pro{
position: relative;
height: 400px;
background: #00aaff;
text-align: center;
img{
height: 400px;
width: 100%; // 使图片宽度占满 .pro 容器
object-fit: cover; // 保持图片比例并裁剪以填满容器
}
.name {
position: absolute; // 设置绝对定位
top: 50%;
left: 50%;
transform: translate(-50%, -50%); // 将文字居中
color: #000; // 文字颜色
font: bold 28px/80px '微软雅黑';
background: rgba(0, 0, 0, 0.1); // 可选:背景色以提高可读性
padding: 10px; // 可选:内边距
border-radius: 5px; // 可选:圆角
}
.btn_box1{
position: absolute; // 设置绝对定位
left: 50%;
bottom: 20%;
transform: translate(-50%, -50%); // 将文字居中
bottom: 55px;
}
.btn_box2{
position: absolute; // 设置绝对定位
left: 56%;
bottom: 40px;
transform: translate(-50%, -50%); // 将文字居中
bottom: 55px;
}
}
}
}
}