每日一题:一起会议吧
介绍
网络会议已经成为当下最流行的会议模式,为网络会议提供支持的当然是一些优秀的会议软件。
本题需要在已提供的基础项目中使用 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 文件中补全代码,最终实现网络会议中参会人员列表的几个展示效果。
具体需求如下:
- 实现异步数据读取和渲染功能。
- 使用 axios 异步获取
./js/userList.json 中的用户数据(注意:调试完成后请将请求地址写死为 ./js/userList.json),并显示在登录窗口及参会人员窗口中。效果如下:


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

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

- 实现参会列表中的首位用户始终为登录用户功能。

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


- 实现用户列表显示效果切换功能。
- 点击显示所有参会人员的按钮图标,图标变色(即
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"> <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"> 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>
|