Skip to content

每日一题:一起会议吧

作者:江月迟迟
发表于:2024-12-10
字数统计:1892 字
预计阅读7分钟

介绍

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

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

准备

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

txt
├── 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 文件。

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

bash
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

题解

js
<!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>