每日一题:一起会议吧

介绍

网络会议已经成为当下最流行的会议模式,为网络会议提供支持的当然是一些优秀的会议软件。

本题需要在已提供的基础项目中使用 Vue 2.x 知识完善代码,最终实现网络会议软件中,参会人员列表的几个展示效果

准备

开始答题前,需要先打开本题的项目代码文件夹,目录结构如下:

1
2
3
4
5
6
7
8
├── 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 文件。

注意:打开环境后发现缺少项目代码,请手动键入下述命令进行下载:

1
2
cd /home/project
wget https://labfile.oss.aliyuncs.com/courses/9788/07.zip && unzip 07.zip && rm 07.zip

在浏览器中预览 index.html 页面,显示如下所示:

初始效果

目标

请在 index.html 文件中补全代码,最终实现网络会议中参会人员列表的几个展示效果

具体需求如下:

  1. 实现异步数据读取和渲染功能。
  • 使用 axios 异步获取 ./js/userList.json 中的用户数据(注意:调试完成后请将请求地址写死为 ./js/userList.json),并显示在登录窗口参会人员窗口中。效果如下:

登录窗口异步数据渲染效果

参会人员窗口异步数据渲染效果

  1. 实现登录、注销切换功能。
  • 在登录窗口选取用户登录后,登录窗口切换为注销窗口,具体变化为:登录标题变为注销字样;选择用户下拉框变为显示当前登录用户名登录按钮变为注销按钮。参会人员窗口显示,并默认只显示当前登录用户信息。效果如下:

登录后的效果

  • 在注销窗口点击注销按钮后,注销窗口切换为登录窗口,参会人员窗口消失。效果如下:

注销后的效果图

  1. 实现参会列表中的首位用户始终为登录用户功能。
  • 参会列表中的首位用户始终为登录用户。效果如下:

参会列表中的首位用户始终为登录用户

  1. 实现用户窗口显隐切换功能。
  • 通过点击隐藏参会用户窗口显示参会用户窗口按钮图标,可切换参会人员窗口的显隐。效果如下:

隐藏参会用户窗口按钮图标位置

显示参会用户窗口按钮图标位置

  1. 实现用户列表显示效果切换功能。
  • 点击显示所有参会人员的按钮图标,图标变色(即 class=active\),参会人员窗口内的人员列表显示所有参会人员信息。效果如下:

显示所有参会人员效果图

注意,参会人员列表中用户名称前面的黄色小图标,代表的是该成员为会议发起者,与当前登录用户无关。与之对应的 ./js/userList.json 中的字段为 isHost,其中 "isHost": true 为会议发起人,"isHost": false 为普通参会成员。

  • 点击最左侧的不显示参会人员列表的按钮图标,图标变色(即 class=active\),参会人员窗口内的人员列表隐藏。效果如下:

不显示参会人员列表效果图

  • 点击只显示当前登录用户的按钮图标,图标变色(即 class=active\),参会人员窗口内的人员列表中只显示当前登录用户信息。效果如下:

只显示当前登录用户效果图

完成后的效果见文件夹下面的 gif 图,图片名称为 effect.gif(提示:可以通过 VS Code 或者浏览器预览 gif 图片)。

注意:本题涉及到的登录/注销流程仅为当前题目需要而设计,非真实场景模拟。

规定

  • 请勿修改 index.html 文件外的任何内容。
  • 请严格按照上述要求来完成代码,页面中需要显示的文本内容,与具体说明里的内容保持一致,不要自定义,以免造成无法判题通过。
  • 请严格按照考试步骤操作,切勿修改考试默认提供项目中的文件名称、文件夹路径、class 名、id 名、图片名等,以免造成无法判题通过。

判分标准

  • 实现异步数据读取功能,得 5 分。
  • 实现登录、注销切换功能,得 4 分。
  • 实现参会列表首位用户始终为登录用户功能,得 3 分。
  • 实现用户窗口显隐切换功能,得 2 分。
  • 实现用户列表显示效果切换功能,得 6 分。

总通过次数: 214 | 总提交次数: 332 | 通过率: 64.5%

难度: 中等 标签: 2022, 国赛, Web 前端, Vue.js

题解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
<!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>{{ isLogin ? '注销' : '登录' }}</h3>
<p v-if="!isLogin">
选择用户:<select id="selectUser" @change="changeUser($event)" ref="selectUser">
<option :value="item.id" v-for="item in userList" :key="item.id">{{ item.name }}</option>
</select>
</p>
<p v-if="isLogin">当前用户为:{{ currentUser }}</p>

<a class="login-btn" @click="login" >{{ isLogin ? '注销' : '登录' }}</a>
</div>

<!-- 右侧显示用户列表窗口按钮 -->
<button id="show" class="right-btn" @click="isShow = true" v-if="!isShow && isLogin">
<span class="iconfont icon-left-arrow"></span>
</button>

<!-- 用户列表窗口 -->
<div class="user-dialog" v-if="isLogin && isShow">
<!-- 用户列表窗口上侧工具栏 -->
<ul class="tools">
<li class="tools-left">
<button :class="activeIndex === 0 ? 'active' : ''" @click="changeActiveIndex(0)">
<span class="iconfont icon-close" ></span>
</button>
<button :class="activeIndex === 1 ? 'active' : ''" @click="changeActiveIndex(1)">
<span class="iconfont icon-dialog"></span>
</button>
<button :class="activeIndex === 2 ? 'active' : ''" @click="changeActiveIndex(2)">
<span class="iconfont icon-list"></span>
</button>
</li>
<li class="tools-right" @click="isShow = !isShow">
<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" v-if="activeIndex !== 0">
<li v-for="item in sortList" :key="item.key">
<img class="header" :src="item.imgPath" />
<div class="user-name">
<span class="iconfont icon-user header-icon" v-if="item.isHost"></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: {
userList: [],
value: 1,
isLogin: false,
isShow: true,
activeIndex: 2
},
computed: {
currentUser() {
return this.userList.length > 0 ? this.userList[this.value - 1].name : 'Tom'
},
sortList() {
if (this.activeIndex === 1) {
return this.userList.filter(item => item.name === this.currentUser)
}
else {
const tmpList = [...this.userList]
const result = this.userList.length > 0 ? tmpList.sort((a,b) => {
if (a.name === this.currentUser) {
return -1
} else if (b.name === this.currentUser) {
return 1
} else return 0
}) : []
return result
}

}
},
mounted() {
axios.get('./js/userList.json').then(res => {
this.userList = res.data
})
},
methods: {
changeUser(event) {
this.value = event.target.value !== undefined ? event.target.value : 1
},
login() {
this.isLogin = !this.isLogin
if (!this.isLogin) {
this.value = 1
}
},
changeActiveIndex(val) {
this.activeIndex = val

}
}
});
</script>
</body>
</html>