目录
- 一、介绍
- 二、准备
- 三、目标
- 四、代码
- 五、完成
一、介绍
网络会议已经成为当下最流行的会议模式,为网络会议提供支持的当然是一些优秀的会议软件。
本题需要在已提供的基础项目中使用 Vue 2.x 知识完善代码,最终实现网络会议软件中,参会人员列表的几个展示效果。
二、准备
开始答题前,需要先打开本题的项目代码文件夹,目录结构如下:
├── effect.gif
├── index.html
├── css
├── images
└── js
├── axios.min.js
├── userList.json
└── vue.js
其中:
- effect.gif 是最终实现的效果图。
- index.html 是主页面。
- css 是样式文件夹。
- images 是图片文件夹。
- js/axios.min.js 是 axios 文件。
- js/userList.json 是需要请求的数据文件。
- js/vue.js 是 Vue 2.x 文件。
在浏览器中预览 index.html
页面,显示如下所示:
三、目标
请在 index.html 文件中补全代码,最终实现网络会议中参会人员列表的几个展示效果。
具体需求如下:
- 实现异步数据读取和渲染功能。
- 使用 axios 异步获取 ./js/userList.json 中的用户数据(注意:调试完成后请将请求地址写死为 ./js/userList.json),并显示在登录窗口及参会人员窗口中。效果如下:
- 实现登录、注销切换功能。
- 在登录窗口选取用户登录后,登录窗口切换为注销窗口,具体变化为:登录标题变为注销字样;选择用户下拉框变为显示当前登录用户名;登录按钮变为注销按钮。参会人员窗口显示,并默认只显示当前登录用户信息。效果如下:
在注销窗口点击注销按钮后,注销窗口切换为登录窗口,参会人员窗口消失。效果如下:
3. 实现参会列表中的首位用户始终为登录用户功能。
参会列表中的首位用户始终为登录用户。效果如下:
4. 实现用户窗口显隐切换功能。
通过点击隐藏参会用户窗口或显示参会用户窗口按钮图标,可切换参会人员窗口的显隐。效果如下:
5. 实现用户列表显示效果切换功能。
- 点击显示所有参会人员的按钮图标,图标变色(即 class=active**),参会人员窗口**内的人员列表显示所有参会人员信息。效果如下:
注意,参会人员列表中用户名称前面的黄色小图标,代表的是该成员为会议发起者,与当前登录用户无关。与之对应的 ./js/userList.json 中的字段为 isHost,其中 “isHost”: true 为会议发起人,“isHost”: false 为普通参会成员。
点击最左侧的不显示参会人员列表的按钮图标,图标变色(即 class=active**),参会人员窗口**内的人员列表隐藏。效果如下:
点击只显示当前登录用户的按钮图标,图标变色(即 class=active**),参会人员窗口**内的人员列表中只显示当前登录用户信息。效果如下:
最终完成图:
四、代码
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>一起会议吧</title>
<link rel="stylesheet" type="text/css" href="./css/index.css" />
<link rel="stylesheet" href="./css/iconfont/iconfont.css" />
</head>
<body>
<div id="app">
<!-- TODO:请在下面实现需求 -->
<!-- 登录/注销窗口 -->
<div class="login">
<div class="left-tools">
<a class="close-btn"></a>
<a class="shrink-btn"></a>
</div>
<h3>登录</h3>
<p>
选择用户:<select id="selectUser">
<option value="1">Tom</option>
</select>
</p>
<p>当前用户为:Tom</p>
<a class="login-btn">登录</a>
</div>
<!-- 右侧显示用户列表窗口按钮 -->
<button id="show" class="right-btn">
<span class="iconfont icon-left-arrow"></span>
</button>
<!-- 用户列表窗口 -->
<div class="user-dialog">
<!-- 用户列表窗口上侧工具栏 -->
<ul class="tools">
<li class="tools-left">
<button>
<span class="iconfont icon-close"></span>
</button>
<button>
<span class="iconfont icon-dialog"></span>
</button>
<button class="active">
<span class="iconfont icon-list"></span>
</button>
</li>
<li class="tools-right">
<button class="show-list">
<span class="iconfont icon-retract"></span>
</button>
</li>
</ul>
<!-- 用户列表 -->
<ul class="say-list">
<li>
<span class="iconfont icon-microphone"></span>
</li>
<li class="line"></li>
<li>正在讲话:Tom;</li>
</ul>
<ul class="user-list">
<li>
<img class="header" src="./images/header1.png" />
<div class="user-name">
<span class="iconfont icon-user header-icon"></span>
<span class="iconfont icon-microphone"></span>
Tom
</div>
</li>
<li>
<img class="header" src="./images/header2.png" />
<div class="user-name">
<span class="iconfont icon-microphone"></span>
Lily
</div>
</li>
</ul>
</div>
</div>
<script type="text/javascript" src="./js/vue.js"></script>
<script type="text/javascript" src="./js/axios.min.js"></script>
<script type="text/javascript">
// TODO:请在下面实现需求
new Vue({
el: "#app",
});
</script>
</body>
</html>
js/userList.json
[
{
"id": "1",
"name": "Tom",
"imgPath": "./images/header1.png",
"isHost": true
},
{
"id": "2",
"name": "Lily",
"imgPath": "./images/header2.png",
"isHost": false
}
]
css/index.css
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-size: 12px;
}
button {
background-color: transparent;
border: none;
color: white;
cursor: pointer;
}
ul {
list-style: none;
}
a {
cursor: pointer;
}
.login {
width: 360px;
font-size: 14px;
border-radius: 8px;
height: 500px;
position: absolute;
left: 50%;
top: 50px;
transform: translateX(-50%);
box-shadow: 5px 5px 10.1px #cbc7c7;
}
.login h3 {
text-align: center;
padding: 50px 0 60px 0;
}
.login select {
width: 70%;
height: 30px;
border: 1px solid #1579f7;
}
.login p {
padding: 10px;
text-align: center;
width: 76%;
margin: 0 auto;
display: flex;
align-items: center;
justify-content: space-between;
}
.login-btn {
display: flex;
align-items: center;
justify-content: center;
width: 76%;
height: 40px;
background-color: #1579f7;
color: white;
margin: 0px auto;
border-radius: 2px;
margin-top: 50px;
font-size: 16px;
}
.right-btn {
position: fixed;
top: 100px;
right: 0;
display: block;
width: 30px;
height: 36px;
background-color: #686767;
border-top-left-radius: 18px;
border-bottom-left-radius: 18px;
color: white;
display: flex;
align-items: center;
padding-left: 10px;
box-shadow: 5px 5px 10.1px #9e9696;
}
.user-dialog {
position: fixed;
z-index: 99;
right: 100px;
top: 100px;
width: 300px;
background-color: #333333;
border-radius: 6px;
color: white;
overflow: hidden;
box-shadow: 5px 5px 10.1px #9e9696;
}
.tools {
display: flex;
height: 44px;
justify-content: space-between;
padding: 0 15px;
align-items: center;
}
.tools-left {
width: 100px;
display: flex;
justify-content: space-between;
}
.say-list {
display: flex;
align-items: center;
height: 44px;
background-color: dimgrey;
}
.say-list > li:nth-child(1) {
min-width: 40px;
padding: 0 15px;
}
.line {
height: 30px;
width: 1px;
background-color: #333333;
margin-right: 10px;
}
.user-list {
width: 100%;
}
.user-list > li {
height: 130px;
background-color: dimgrey;
margin-top: 5px;
display: flex;
align-items: center;
justify-content: center;
position: relative;
}
.user-name {
position: absolute;
left: 0;
bottom: 0;
height: 30px;
background-color: #444444;
display: flex;
padding: 0 5px 0 2px;
align-items: center;
}
.header-icon {
width: 22px;
height: 22px;
background-color: orange;
display: flex;
align-items: center;
justify-content: center;
font-size: 18px !important;
}
.user-name span {
padding: 0 3px;
}
.header {
display: block;
width: 100px;
height: 100px;
border-radius: 50%;
}
.active {
color: #0077aa;
}
.left-tools {
padding-left: 15px;
height: 32px;
display: flex;
align-items: center;
}
.close-btn {
width: 14px;
height: 14px;
border-radius: 50%;
background: red;
}
.shrink-btn {
width: 14px;
height: 14px;
border-radius: 50%;
background: #ffa100;
margin-left: 8px;
}
五、完成
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>一起会议吧</title>
<link rel="stylesheet" type="text/css" href="./css/index.css" />
<link rel="stylesheet" href="./css/iconfont/iconfont.css" />
</head>
<body>
<div id="app">
<!-- TODO:请在下面实现需求 -->
<!-- 登录/注销窗口 -->
<div class="login">
<div class="left-tools">
<a class="close-btn"></a>
<a class="shrink-btn"></a>
</div>
<h3>{{loinOrlogout}}</h3>
<p v-if="!isShow">
选择用户:<select v-model="indexUser" id="selectUser">
<option v-for="item in list" :value="item.name">
{{item.name}}
</option>
</select>
</p>
<p v-else>当前用户为:Tom</p>
<a @click="login" class="login-btn">{{loinOrlogout}}</a>
</div>
<!-- 右侧显示用户列表窗口按钮 -->
<button v-if="isShow&&isShowRbtn" @click="showUserList" id="show" class="right-btn">
<span class="iconfont icon-left-arrow"></span>
</button>
<!-- 用户列表窗口 -->
<div v-if="isShowUserList&&isShow" class="user-dialog">
<!-- 用户列表窗口上侧工具栏 -->
<ul class="tools">
<li class="tools-left">
<button @click="changeBtnActive(false,false,1)" :class="{'active': buttonIndex==1 ? true : false}">
<span class="iconfont icon-close"></span>
</button>
<button @click="changeBtnActive(true,false,2)" :class="{'active': buttonIndex==2 ? true : false}">
<span class="iconfont icon-dialog"></span>
</button>
<button @click="changeBtnActive(true,true,3)" :class="{'active': buttonIndex==3 ? true : false}">
<span class="iconfont icon-list"></span>
</button>
</li>
<li @click="showUserList" class="tools-right">
<button class="show-list">
<span class="iconfont icon-retract"></span>
</button>
</li>
</ul>
<!-- 用户列表 -->
<ul class="say-list">
<li>
<span class="iconfont icon-microphone"></span>
</li>
<li class="line"></li>
<li>正在讲话:Tom;</li>
</ul>
<ul v-if="isShow" class="user-list">
<li v-if="isShowIndexUser">
<img class="header" :src="user.imgPath" />
<div class="user-name">
<span v-if="user.isHost" class="iconfont icon-user header-icon"></span>
<span class="iconfont icon-microphone"></span>
{{user.name}}
</div>
</li>
<li
v-for="item in list"
v-if="item.name!=user.name&&isShowOtherUser"
>
<img class="header" :src="item.imgPath" />
<div class="user-name">
<span v-if="item.isHost&&changeBtnActive" class="iconfont icon-user header-icon"></span>
<span class="iconfont icon-microphone"></span>
{{item.name}}
</div>
</li>
</ul>
</div>
</div>
<script type="text/javascript" src="./js/vue.js"></script>
<script type="text/javascript" src="./js/axios.min.js"></script>
<script type="text/javascript">
// TODO:请在下面实现需求
new Vue({
el: "#app",
data() {
return {
list: [],
indexUser: "Tom",
isShow: false,
isShowRbtn:false,
isShowUserList:true,
isShowOtherUser:false,
isShowIndexUser:true,
user: "",
buttonIndex:2
};
},
mounted() {
this.getData();
},
computed: {
loinOrlogout() {
return this.isShow ? "注销" : "登录";
},
},
methods: {
//异步获取数据
async getData() {
const res = await axios({ url: "./js/userList.json" });
this.list = res.data;
console.log(res.data);
},
changeBtnActive(userFlag,otherUserFlag,value){
this.isShowIndexUser=userFlag
this.isShowOtherUser=otherUserFlag
this.buttonIndex=value
},
showUserList(){
this.isShowUserList=!this.isShowUserList
this.showRbtn()
},
showRbtn(){
this.isShowRbtn=!this.isShowRbtn
},
//登录
login() {
this.isShow = !this.isShow;
this.user=this.list.find(item=>item.name==this.indexUser)
console.log(this.user);
},
},
});
</script>
</body>
</html>