第十四届蓝桥杯(web应用开发) 模拟赛2期 -大学组

时间:2022-11-25 08:54:22

凭空消失的TA

题解

加入第二行代码即可,没有使用elementUI提供的js文件,所以说提供的所有文件都是有用的呀~

 <!-- 引入 element-ui 样式 -->
    <link rel="stylesheet" href="./element-ui-2.15.10/index.css" />
    <script src="./element-ui-2.15.10/index.js"></script>

用户名片

题解

核心就是让整个卡片无论在什么时候都是页面居中,就是无论你缩放页面总是居中。这里就必须用到最后的center样式

* {
  margin: 0;
  padding: 0;
}
html,
body {
  background: #fceeb5;
  height: 100%;
  overflow: hidden;
}

html,
body {
  background: #fceeb5;
}
.card {
  width: 450px;
  height: 250px;
  background: #fff;
  box-shadow: 0 8px 16px -8px rgba(0, 0, 0, 0.4);
  border-radius: 6px;
  overflow: hidden;
  position: absolute;
  margin: auto;
  left: 0px;
  bottom: 0;
  top: 0;
  right: 0;
}
.card h1 {
  text-align: center;
}

.card img {
  width: 110px;
  height: 110px;
  border-radius: 50%;
}
.additional {
  position: absolute;
  height: 100%;
  background: #92bca6;
  z-index: 2;
}

.user-card {
  width: 150px;
  height: 100%;
  position: relative;
  float: left;
}
.user-card .points {
  top: 85%;
}
.general {
  width: 300px;
  height: 100%;
  position: absolute;
  top: 0;
  right: 0;
  z-index: 1;
  box-sizing: border-box;
  padding: 12px;
  padding-top: 0;
  display: flex;
  flex-flow: column;
  justify-content: space-around;
}
.more{
  display: block;
  text-align: right;
}
/* level 和  points 定位位置 */
.level,
.points {
  width: 72px;
  text-align: center;
  position: absolute;
  color: #fff;
  font-size: 12px;
  font-weight: bold;
  background: rgba(0, 0, 0, 0.15);
  padding: 2px 0;
  border-radius: 100px;
  white-space: nowrap;
  /*这里改了一下*/
  bottom: 5% !important;
}

/*  level 位置这里也改了一下 */
.level {
  top: -68% !important;
    height: 15px;
}

/* TODO 待补充代码 居中样式*/
.center{
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  margin: auto;
}

芝麻开门

题解

需要注意的是得把点击确定按钮的事件放在promise中,以至于最终返回的是mPrompt()的状态,不然放在外面返回的就是点击事件的状态了。我就是犯了这个错误,然后答案一直不对。然后点击事件用了.onclick和addEventListener事件监听器,因为开始不太熟悉还是什么都要多用用

const incantations = "芝麻开门";
function init(el) {
  document.querySelector(".wrapper .btn").addEventListener("click", () => {
    mPrompt()
      .then((res) => {
        console.log("@@@@@@@@@@" + res);
        if (res === incantations) {
          document
            .querySelectorAll("#door .doors")[0]
            .classList.add("door-left");
          document
            .querySelectorAll("#door .doors")[1]
            .classList.add("door-right");
        }
      })
      .catch((err) => {
        console.log(err);
      });
  });
}
/**
 * @description: 调用函数,开启弹窗,记录输入框的内容,并通过 promise 异步返回输入框中的内容
 * @return {Promise}
 */
function mPrompt() {
  // 弹窗必须使用以下结构 template 保存的是弹窗的结构字符串,可以先转化为 DOM 再通过 appendChild 方式插入到 body 中
  const template = `
        <div class="modal">
            <div class="message-box">
                <div class="message-header">请输入咒语</div>
                <div class="message-body">
                    <input type="text">
                </div>
                <div class="message-footer">
                    <button class="btn btn-small" id='cancel'>取消</button>
                    <button class="btn btn-small btn-primary" id='confirm'>确定</button>
                </div>
            </div>
        </div>
    `;
  // 让对话框弹出,先创建子节点
  const dialogDiv = document.createElement("div");
  dialogDiv.innerHTML = template;
  // body元素最后追加一个div元素
  let body = document.querySelector('body');
  body.appendChild(dialogDiv);

  // 获取对话框的确定和取消按钮,通过这个来操作对话框的显示与隐藏
  let confirmBtn = document.getElementById("confirm");
  let cancelBtn = document.getElementById("cancel");
  let inputVal = "";

  // TODO:待补充代码
  return new Promise((resolve, reject) => {
    // 点击确定事件
    confirmBtn.onclick = function () {
      // 注意getElementsByTagName获取到的是数组,取第一个
      inputVal = document.getElementsByTagName("input")[0].value
      body.removeChild(dialogDiv)
      if (inputVal == "芝麻开门") {
        return resolve("芝麻开门")
      } else {
        return reject(false)
      }
    }

    // 取消事件
    cancelBtn.addEventListener("click", () => {
      body.removeChild(dialogDiv)
      reject(false)
    })

  })
}

宝贵的一票

总结

这个题还是比较简单的就是考察了简单点dom操作,但是犯了一点错误,就是最终一直没有评测成功,最后发现应该是我动了初始化函数initRender 最初的dom结构,我为了图方便直接在里面都加了那个叉号的dom,但是最后评测时是不能有叉号的dom元素存在的,虽然我使它的display为none了但是还是不能通过检测,提示只有第一次删除检测成功,后面的直到选项小于等于2时应该就失败了。因为它检测到了序列小于2时还存在删除按钮的dom结构。
写这些的目的就是告诉大家一定不要随便操作题目已经给出的dom结构,因为它的评判标准里面就应该会检测最终的dom结构。当然我这个也是有解决办法的,就是在最后判断选项长度小于等于2时直接把选项1和选项2的删除按钮的dom结构remove就ok啦~ 我是小辣鸡一起进步吧

题解

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <title>宝贵的一票</title>
  <script src="./js/jquery.min.js"></script>
  <link rel="stylesheet" href="./css/bootstrap.min.css" />
  <link rel="stylesheet" href="./css/style.css" />
</head>

<body>
  <div class="inner-container shadow">
    <div class="mb-3 row">
      <label class="col-sm-2 col-form-label">投票主题</label>
      <div class="col-sm-9">
        <input type="text" class="form-control" />
      </div>
    </div>
    <div class="list"></div>
    <div class="add">
      <div class="addtxt">
        <img src="./images/plus-square.svg" alt="加号图标" />
        添加选项
      </div>
    </div>
    <div class="form-check checkbox-one">
      <input class="form-check-input" type="checkbox" value="" />
      <label class="form-check-label" for="flexCheckDefault">
        支持多选
      </label>
    </div>
    <div class="form-check">
      <input class="form-check-input" type="checkbox" value="" />
      <label class="form-check-label" for="flexCheckDefault">
        公开投票结果
      </label>
    </div>

    <div class="row bottom">
      <div class="col">
        <a class="historytxt" href="javascript:void(0)">历史投票</a>
      </div>
      <div class="col"></div>
      <div class="col">
        <button type="button" class="btn btn-light">取消</button>
        <button type="button" class="btn btn-primary">发起投票</button>
      </div>
    </div>
  </div>

  <script>
    let initRender = (txt) => {
      return `<div class="mb-3 row" >
                <label class="col-sm-2 col-form-label txt">${txt}</label>
                <div class="col-sm-9">
                    <input type="text" class="form-control">
               </div>
               <div class="col-sm-1">
                 <!-- 删除图标 -->
            <img class="del-icon" src="./images/x.svg" alt="" style="display:none" />
            </div>    
            </div>`;
    };
    $(
      (function () {
        // 初始化的时候渲染两条数据,且不带删除符号
        for (let index = 0; index < 2; index++) {
          let initList = initRender(`选项${index + 1}`);
          $(".list").append(initList);
        }

        // 点击加号逻辑
        $(".add").click(function () {
          // TODO 待补充代码
          // 获取当前选项列表的长度,根据initRender函数中的模板字符串可得到灵感
          
          let listLength = $('.list .row').length;
          let initList = initRender(`选项${listLength + 1}`);
          $(".list").append(initList);
          console.log(listLength);
          if (listLength >= 2) {
            $('.del-icon').css("display", "block")
          }
        });
        // 点击 x 删除逻辑,列表小于 2 项时不显示删除图标
        $(document).on("click", ".del-icon", function () {
          // TODO 待补充代码
          // console.log($(this).parent().parent());等价于$(this).parents()[1]
          $(this).parents()[1].remove()     
           
          let listLength = $('.list .row').length;
          for (let index = 0; index < listLength; index++) {
            $('.txt')[index].innerHTML=`选项${index+1}`
          }
           console.log(listLength);
          if (listLength> 2) {
            $('.del-icon').css("display", "block")
          }else{
            $('.del-icon').css("display", "none")
            // 切记要删除这里呀,因为判题应该是根据dom结构来滴
            $('.list .col-sm-1').remove()
          }
        });
      })()
    );
  </script>
</body>

</html>

粒粒皆辛苦

思路:

  • 先直接看json文件中的数据格式,看到是一个对象中嵌套对象的格式。获取数据就好
  • 一般echarts题都有初始化渲染的例子,我们不要动,然后直接看它是怎么渲染的,照着写就行。
    获取到数据后对数据进行处理,我是直接使用for of 对对象进行遍历然后将里面不同类型的值进行分类
  • 直接修改 option.dataset.source中的值注意最前面要加上大豆,玉米啥的中文名。最后一定得调用渲染函数myChart.setOption(option);最终页面才会改变

题解

<!DOCTYPE html>
<html style="height: 100%">

<head>
  <meta charset="utf-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <title>粒粒皆辛苦</title>
  <script type="text/javascript" src="./js/echarts.min.js"></script>
  <script src="./js/axios.min.js"></script>
</head>

<body style="height: 100%; margin: 0; overflow: hidden">
  <div id="container" style="height: 80%; width: 80%; margin: 5% auto"></div>
  <script>
    var dom = document.getElementById("container");
    var option;
    var myChart = echarts.init(dom, null, {
      renderer: "canvas",
      useDirtyRect: false,
    });
    let initCharts = () => {
      option = {
        title: {
          text: "近五年 x 市粮食总产量分布以及 2022 年粮食产量比例",
          subtext: "单位(万吨)",
        },
        dataset: {
          //source -> 图表显示所需的数据格式(饼形图和折线图共用),请勿手动修改此行
          source: [
            ["全部", "2017", "2018", "2019", "2020", "2021", "2022"],
            ["小麦", 1, 1, 1, 1, 1, 1],
            ["大豆", 9, 9, 9, 9, 9, 9],
            ["马铃薯", 13, 13, 13, 13, 13, 13],
            ["玉米", 23, 23, 23, 23, 23, 23],
          ],
        },
        xAxis: { type: "category" },
        yAxis: { gridIndex: 0 },
        grid: { top: "55%" },
        series: [
          {
            type: "line",
            seriesLayoutBy: "row",
          },
          {
            type: "line",
            seriesLayoutBy: "row",
          },
          {
            type: "line",
            seriesLayoutBy: "row",
          },
          {
            type: "line",
            seriesLayoutBy: "row",
          },
          {
            type: "pie",
            id: "pie",
            radius: "30%",
            center: ["50%", "25%"],
            label: {
              // 2022 数据的百分比
              formatter: "{b} {@2022} ({d}%)",
            },
            encode: {
              itemName: "全部",
              value: "2022",
              tooltip: "2022",
            },
          },
        ],
      };
      if (option && typeof option === "object") {
        // myChart.setOption -> 设置 echarts 数据的方法
        myChart.setOption(option);
      }
      window.addEventListener("resize", myChart.resize);
    };
    initCharts();

    // TODO: 待补充代码
    var dataList = {}
    // 初始化四个数组
    var wheat = ["小麦"], soybean = ["大豆"], corn = ["玉米"], potato = ["马铃薯"]
    window.onload = function () {
      axios.get(' ./data.json')
        .then(res => {
          dataList = res.data.data;

          // 双重循环取对象值
          for (item in dataList) {
            //  console.log(dataList[item]);
            let value = dataList[item]
            for (subitem in value) {
              // console.log(value[subitem]);
              if (subitem === "wheat") {
                wheat.push(value[subitem])
              } else if (subitem === "soybean") {
                soybean.push(value[subitem])
              } else if (subitem === "corn") {
                corn.push(value[subitem])
              } else if (subitem === "potato") {
                potato.push(value[subitem])
              }
            }
          }
          option.dataset.source = [
            ["全部", "2017", "2018", "2019", "2020", "2021", "2022"],
            wheat,
            soybean,
            potato,
            corn,]
          
          myChart.setOption(option);
          console.log(option);
        })
    }

  </script>
</body>

</html>

618 活动

介绍

最近蓝桥准备了很多 618 优惠,今天我们将化身蓝桥前端小工,亲自动手制作一个 618 活动页面,快来一显身手吧。

后面补哈~~

资讯接口

题解

其实和模拟一的那个node题都是一样的原理

const http=require('http');

const server=http.createServer();
server.on('request',(req,res)=>{
    // 设置请求头
    res.setHeader("Content-type", "text/html;charset=utf8");
  if(req.url=="/news"){
    res.end(JSON.stringify(
        [
            {
              "channelId": "5572a108b3cdc86cf39001cd",
              "name": "国内焦点"
            },
            {
              "channelId": "5572a108b3cdc86cf39001ce",
              "name": "国际焦点"
            }
          ]
    ))
  }else{
    res.end("404")
  }
})

server.listen(8080,function(){
    console.log("8080端口启动成功");
})

绝美宋词

题解

思路:使用v-model实现双向绑定,最后使用watch监听words的变化,最后需要使用v-html指令在展示经过我们处理的字符串

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <title>绝美宋词</title>
  <link rel="stylesheet" href="css/style.css" />
  <script src="./js/vue.min.js"></script>
  <script src="./js/axios.min.js"></script>
</head>

<body>
  <div id="app">
    <h1 style="text-align: center">输入关键字,找一首词</h1>
    <!-- TODO:待补充代码 -->
    <div class="search-form">
      <input type="text" id="search" v-model="words" class="search" placeholder="词牌名 词句 词人" />
      <ul class="suggestions" v-if="">
        <li v-for="item in resultList" :key="item.title">
          <span class="poet" v-html="item.poetry_content"></span>
          <span class="title" v-html=`${item.title}-${item.author}`></span>
        </li>
      </ul>
    </div>
  </div>
  <script>
    let vm = new Vue({
      el: '#app',
      // TODO:待补充代码
      data() {
        return ({
          poetryList: [],//数据库数据
          resultList: [],//最终展示数据
          words: '' //关键字
        })
      },
      mounted() {
        axios.get('./data.json').then(res => {
          this.poetryList = res.data
        })
      },
      watch: {
        words(newVal, oldVal) {
          if (newVal === '') {
            //如果关键字为空不匹配,直接返回
            this.resultList = [];
            return;
          }
          console.log("newVal值", newVal);
          this.resultList = [];
          this.poetryList.forEach(item => {
            // 处理关键字,得到含有关键字的对象
            if (item.poetry_content.includes(newVal) || item.title.includes(newVal) || item.author.includes(newVal)) {
              // 注意这里得使用深拷贝,不然在下面重新赋值resultList时会改变原有的从JSON中的数据,
              // 导致最终只能匹配一个字符
              this.resultList.push(JSON.parse(JSON.stringify(item)))
            }
          })
          // 处理高亮,全部的
          let reg = new RegExp(newVal, 'g');
          this.resultList.forEach(ele => {
            // 关键字替换
            ele.poetry_content = ele.poetry_content.replace(reg, `<span class="highlight">${newVal}</span>`)
            ele.title = ele.title.replace(reg, `<span class="highlight">${newVal}</span>`)
            ele.author = ele.author.replace(reg, `<span class="highlight">${newVal}</span>`);
          })
        },
      }
    })
  </script>
</body>

</html>

平地起高楼

题解

这个题最开始我是想直接一遍又一片for循环的后来发现好像所有的流程都是一样的,就开始尝试使用递归,但是最开始的递归时所有的数据都是单独存在的,并没有什么联系,于是我就打开了控制台反复测试每一次递归的结果,发现的确每一次递归都是正确的,但是我设置的resultList.children=convertToTree(regions, item.id)并没有效果,导致所有的数据都无法关联,最后测试出了可以直接使用item.children,因为regions的数据是我们每一次递归都不会改变的,所以可以对其进行操作,保证最后的递归数据能够串联起来。

function convertToTree(regions, rootId = "0") {
  // TODO: 在这里写入具体的实现逻辑
  // 将平铺的结构转化为树状结构,并将 rootId 下的所有子节点数组返回
  // 如果不存在 rootId 下的子节点,则返回一个空数组
  
  let resultList=[];
  // let testList=[]
  regions.forEach(item=>{
    // let testList=[];
    if(item.pid===rootId){
      // 符合结果就放进去,比如最先找到四川,然后就把四川
      //放进去,之后在把四川作为pid去查找下一个子代。之后在遍历子代
      resultList.push(item);
      // testList=resultList
      // 没用,因为每一次递归后的return的是resultList,所以最终会不断
      //的改变,所以得使用item.children,直接改变它的值
      //resultList.children=convertToTree(regions, item.id)
      // 为孩子做准备,题目也说了如果没有孩子就设置为空数组,不影响
      // item.children=[],这一次递归的结果就是找到这一轮符合要求的子代
      //这里把item.id作为pid继续查找子代
      item.children=convertToTree(regions, item.id)

      // console.log(convertToTree(regions, item.id));
      // resultList.children=convertToTree(regions, item.id); 
      
      // console.log(resultList);解开注释,观察递归效果
    }
  })
  return resultList;
}

module.exports = convertToTree; // 检测需要,请勿删除

收快递了

最初错误示例

function findRegion(regions, regionName) {
  // TODO: 在这里写入具体的实现逻辑
  // 需要从树状结构的行政信息中,遍历找到目标区域的行政信息,如输入:成都市,返回 [四川省,成都市]
  // 如果所输入的位置信息不存在,则返回 null
  let replceList=regions[0];
  // 省
  let resultArr=[regions[0].name];
  if(replceList.name===regionName){
    
    return resultArr;
  }

  var flag1=false;
  for(let i=0;i<replceList.children.length;i++){
    // 市级
    if(replceList.children[i].name===regionName){
      resultArr.push(regionName)
      flag1=true
      break;
    }else{
      // 区级
     replceList.children[i].children.forEach(item=>{
        if(item.name===regionName){
          flag1=true
          resultArr.push(replceList.children[i].name)
            resultArr.push(item.name)
        }
     })
      
    }
  }

  if(flag1){
    return resultArr;
  }else{
    return null;
  }
}
module.exports = findRegion; // 检测需要,请勿删除

题解

检测发现原来是我最初的时候就把省份定死啦,我以为最后测试的数据只有一个省原来不是!!!所以在加一层循环就好啦!!!但是这样真的很消耗时间哦,幸好不是算法竞赛,不然就给我TTL了,真给我写麻了。
需要注意的是只有for循环或者while等其他循环语句才可以使用break,所以当我使用forEach时是没有使用break跳出的。

function findRegion(regions, regionName) {
  // TODO: 在这里写入具体的实现逻辑
  // 需要从树状结构的行政信息中,遍历找到目标区域的行政信息,如输入:成都市,返回 [四川省,成都市]
  // 如果所输入的位置信息不存在,则返回 null
let resultArr=[]
  var flag1 = false;//最终返回条件
  for (let t = 0; t < regions.length; t++) {
    // 省
    if (regions[t].name === regionName) {
      resultArr.push(regions[t].name)
      flag1 = true;
      break
    } else {
      for (let i = 0; i < regions[t].children.length; i++) {
        // 市级
        if (regions[t].children[i].name === regionName) {
          resultArr.push(regions[t].name)
          resultArr.push(regionName)
          flag1 = true
          break;
        } else {
          // 区级
          regions[t].children[i].children.forEach(item => {
            if (item.name === regionName) {
              flag1 = true
              resultArr.push(regions[t].name)
              resultArr.push(regions[t].children[i].name)
              resultArr.push(item.name)
            }           
          })
        }
      }
    }
  }
  if (flag1) {
    return resultArr;
  } else {
    return null;
  }
}

module.exports = findRegion; // 检测需要,请勿删除