0


第十五届蓝桥杯(Web 应用开发)模拟赛 3 期-大学组And职业组

1、创意广告牌 代码:

.billboard {
  position: relative;
  background-color: #8e6534;
  color: #fff;
  padding: 20px;
  box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.3);
  background-size: cover;
  border-radius: 10px; /* 设置圆角为 10px */
  background-image: url('../images/woodiness.jpg'); /* 设置背景图片为 woodiness.jpg */
}

.top-sign {
  position: relative;
  width: 200px;
  height: 100px;
  background-color: #a87f4a;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 1rem;
  border-top-left-radius: 15px; /* 设置上左角为圆角 15px */
  border-top-right-radius: 15px; /* 设置上右角为圆角 15px */
  transform: skewX(-20deg); /* 在 x 轴方向倾斜元素 20度 */
}

2、原子化CSS 的代码

直接在css下面加个flex弹性布局的操作,然后竖着。

/* TODO: 实现原子化 flex */
div {
  display: flex;
  flex-direction: column;
}

3、神秘咒语

简单的token操作,axios知识点,请求的时候在请求头带上token,就可以顺利请求访问到。

// TODO:新增或者修改以下代码
let token = '2b58f9a8-7d73-4a9c-b8a2-9f05d6e8e3c7';
key1Button.addEventListener('click', async () => {
    // 从后台请求钥匙1的咒语部分
    key1Button.disabled = true;
    let {data} =  await axios.get('/spellone', {headers: {'Authorization': token}})
    spell1.innerHTML = data;
    tryOpenTreasureBox();
});

key2Button.addEventListener('click', async () => {
    // 从后台请求钥匙2的咒语部分
    key2Button.disabled = true;
    let {data} =  await axios.get('/spelltwo', {headers: {'Authorization': token}})
    spell2.innerHTML = data;
    tryOpenTreasureBox();
});

4、朋友圈 代码:

防抖考了,会不会在真题的时候考节流。。。

JS练习题

document.addEventListener("DOMContentLoaded", function() {
  let textContent = localStorage.getItem('savedText');
  document.getElementById('text').value = textContent;
  show()
});

document.getElementById("text").addEventListener(
  "input",
  debounce(function() {
    document.getElementById("prompt").textContent = "正在保存中...";
    let textContent = document.getElementById('text').value;

    localStorage.setItem('savedText', textContent);

    show()
    setTimeout(function() {
      document.getElementById("prompt").textContent = "内容已保存";
    }, 750);
  }, 200)
);

document.getElementById("post").addEventListener("click", function() {
  const content = document.getElementById("text").value;
  // 假设 createContent 是一个已定义的函数,用于创建表示内容的DOM元素
  const element = createContent(content);
  document.querySelector(".contents").appendChild(element);
  document.getElementById("prompt").textContent = "发表成功!";
  document.getElementById("text").value = '';
  localStorage.removeItem('savedText');
  show()
});

// 防抖工具函数
/**
 * @param  {function} fn  - 回调函数
 * @param  {string} delay - 函数执行延迟,单位为ms
 */
function debounce(fn, delay) {
  // return fn; // 这一行是为了确保页面正常运行,可以去掉
  let timer = null;
  return function () {
    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(() => {
      fn();
    }, delay);
  }

  // TODO: 请实现函数防抖的功能
}

function show(){

  if (document.getElementById("text").value !== '') {
    document.getElementById("post").removeAttribute('disabled');
  } else {
    document.getElementById("post").setAttribute('disabled', 'disabled');
  }
}

// 用户点击“发表”后,创建一条新信息的DOM元素
function createContent(content) {
  const div = document.createElement("div");
  const d = new Date();
  const deleteBtn = document.createElement("button");
  deleteBtn.textContent = "删除";
  deleteBtn.addEventListener("click", function() {
    div.remove();
  });
  div.innerHTML = `<div><span class="content">${content}</span><span class="date">${d.toLocaleString()}</span></div>`;
  div.appendChild(deleteBtn);
  return div;
}

5、美食蛋白质揭秘 代码:

JS原生ajax请求 )xhr = new XMLHttpRequest();

open("请求方式","请求路径“);

用onload加载一次就行了,补充一个就是

  • onreadystatechange
  • 当 readyState 属性发生变化时,调用的事件处理器。
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>不同食物的蛋白质占比</title>
    <script src="./lib/vue3.global.js"></script>
    <script src="./lib/echarts.min.js"></script>
    <link rel="stylesheet" href="css/style.css" />
  </head>
  <body>
    <div id="app">
      <h2>不同食物的蛋白质占比</h2>
      <div class="protein-container">
        <!-- TODO:待补充代码,渲染获取的数据 -->
      </div>
      <div class="echarts" id="main"></div>
    </div>
    <script>
      const { ref, onMounted } = Vue;
      const MockURL = "./mock/data.json";
      const app = {
        setup() {
          function echartsInit(data) {
            const main = document.getElementById("main");
            const myChart = echarts.init(main);
            myChart.setOption({
              legend: {
                data: data,
                orient: "vertical",
                top: "26%",
                right: "2%",
                icon: "circle",
                textStyle: {
                  fontSize: 20,
                  rich: {
                    one: {
                      width: 80,
                    },
                    two: {
                      width: 80,
                    },
                    three: {
                      width: 80,
                    },
                  },
                },
                formatter: (name) => {
                  var total = 0;
                  var target;
                  let formateData = data;
                  for (var i = 0; i < formateData.length; i++) {
                    if (formateData[i].value) {
                      total += formateData[i].value;
                      if (formateData[i].name === name) {
                        target = formateData[i].value;
                      }
                    }
                  }
                  var v = ((target / total) * 100).toFixed(2);
                  let row;
                  if (name === "表头") row = `食物      含量       占比`;
                  else row = `{one|${name}} {two|${target}} {three|${v}%}`;
                  return row;
                },
              },
              color: ["#baf", "#bfa", "#cde", "#f90", "#0c9"],
              series: [
                {
                  type: "pie",
                  radius: ["30%", "50%"],
                  center: ["32%", "40%"],
                  data: data,
                },
              ],
            });
          }

          async function fetchData() {
            // TODO:待补充代码
            let FoodArray = [];
            let xhr = new XMLHttpRequest();

            xhr.open("GET", MockURL);

            xhr.onload = function () {
              if (this.status == 200) {
                FoodArray = JSON.parse(this.responseText); //这个需要转换一下 因为是JSON格式转换为js对象
                let NewFoodArray = [
                    { name: "表头", icon: "none" },
                ]
                for (const item of FoodArray) {
                    NewFoodArray.push(item)
                }
                // console.log(NewFoodArray);
                echartsInit(NewFoodArray) //直接在里面调用就行了
                for (const item of FoodArray) {
                  let div = document.createElement("div");
                  div.innerHTML = `${item.name} ${item.value}`;
                  div.className= 'protein-item'
                  let content =
                  document.getElementsByClassName("protein-container")[0];
                  content.appendChild(div);
                }
              } else {
                console.log("请求失败:" + this.status);
              }
            };
            xhr.send();
          }
          fetchData();
          return {
            echartsInit,
          };
        },
      };
      const vm = Vue.createApp(app);
      const mountedApp = vm.mount("#app");
    </script>
  </body>
</html>

6、营业状态切换

其实就是 自定义一个东西 只不过这里的返回是需要对应上,要记得;

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>营业状态切换</title>
    <script src="./lib/vue.global.js"></script>
    <!-- 引入Vue.js库 -->
    <link rel="stylesheet" href="./css/style.css" />
    <!-- 引入样式表 -->
  </head>

  <body>
    <div id="app">
      <div class="header">
        <h1>营业状态切换</h1>
        <!-- 页面标题 -->
      </div>
      <!-- 显示店铺状态 -->
      <p>当前店铺状况: {{ isWorking ? '营业中' : '已打烊' }}</p>
      <!-- 根据状态显示相应的图片 -->
      <img :src="isWorking ? workImage : restImage" alt="Status Image" />
      <!-- 切换店铺状态的开关按钮 -->
      <div
        class="switch"
        @click="toggleWorking"
        :class="{ 'switch-on': isWorking }"
      >
        <span class="switch-inner"></span>
      </div>
    </div>
    <script setup>
      const { ref } = Vue; // 引入Vue中的ref函数

      function useToggle(state) {
        // TODO:待补充代码
        let s1 = ref(state);
        function s2() {
          //调用这里的函数 返回 isWorking 为true 就得到workImage
          s1.value = !s1.value;
        }

        return [s1, s2]; //如果报错 那么就是返回值的问题了
      }

      const app = Vue.createApp({
        setup() {
          const [isWorking, toggleWorking] = useToggle(false); // 使用自定义的useToggle函数创建状态和切换函数
          const workImage = "./images/open.jpg"; // 营业状态的图片路径
          const restImage = "./images/close.jpg"; // 打烊状态的图片路径
          return {
            isWorking,
            toggleWorking,
            workImage,
            restImage,
          };
        },
      });

      app.mount("#app"); // 将Vue应用挂载到id为app的元素上
    </script>
  </body>
</html>

7、嘟嘟购物 :

这里就是vue3的练习,职业组的一道题,大学组的是一道node题。

就是Pinia和vue3。WatchEffect监听 只要里面的响应式发生变化就会调用一次,还有在页面开始也会调用一次,至于Pinia,直接调用就行了,这里是非工程文件,已经有script引入了Pinia

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="./css/[email protected]/index.css" />
    <link rel="stylesheet" href="./css/index.css" />
    <script src="./lib/vue.min.js"></script>
    <script src="./css/[email protected]/index.full.js"></script>
    <script src="./lib/axios.js"></script>
    <script src="./lib/vueDemi.js"></script>
    <script src="./lib/pinia.min.js"></script>
    <script src="./js/store.js"></script>
    <title>嘟嘟购物</title>
  </head>
  <body>
    <div id="app">
      <div class="c-container">
        <div class="w">
          <div class="cart-filter-bar">
            <em>全部商品</em>
          </div>
          <!-- 购物车主要核心区域 -->
          <div class="cart-warp">
            <div class="cart-thead">
              <div class="t-checkbox"></div>
              <div class="t-goods">商品</div>
              <div class="t-price">单价</div>
              <div class="t-num">数量</div>
              <div class="t-sum">小计</div>
              <div class="t-action">操作</div>
            </div>
            <!-- 商品详细模块 -->
            <div class="cart-item-list">
              <div
                class="cart-item check-cart-item"
                v-for="(item,index) in goodsArray"
                :key="item.id"
              >
                <div class="p-checkbox">
                  <input
                    type="checkbox"
                    name=""
                    id=""
                    class="j-checkbox"
                    @change="updateCheckedState($event,index)"
                  />
                </div>
                <div class="p-goods">
                  <div class="p-img">
                    <img :src="item.image" alt="" />
                  </div>
                  <div class="p-msg">{{item.name}}</div>
                </div>
                <div class="p-price">{{item.price}}</div>
                <div class="p-num">
                  <div class="quantity-form">
                    <a
                      href="javascript:;"
                      class="decrement"
                      @click="decrement(index)"
                      >-</a
                    >
                    <input type="text" class="itxt" :value="item.priceCount" />
                    <a href="javascript:;" class="increment" @click="add(index)"
                      >+</a
                    >
                  </div>
                </div>
                <div class="p-sum">
                  {{(item.price * item.priceCount).toFixed(2)}}
                </div>
                <div class="p-action"><a href="javascript:;">删除</a></div>
              </div>
            </div>
            <!-- 结算模块 -->
            <div class="cart-floatbar">
              <div class="select-all"></div>
              <div class="toolbar-right">
                <div class="amount-sum">
                  已经选<em>{{ selectdItemCount }}</em>件商品
                </div>
                <div class="price-sum">
                  总价: <em>¥{{ totalItemPrice }}</em>
                </div>
                <div class="btn-area" @click="submit">去结算</div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </body>
  <script type="module">
    const { createApp, onMounted, watchEffect } = Vue;
    const { createPinia } = Pinia;
    const { ElMessage, ElNotification } = ElementPlus;
    const app = Vue.createApp({
      setup() {
        // TODO:补充代码,实现目标效果
        const goodsStock = Array.from(useGoodsStore().store);
        const goodId = [];
        const goodsArray = ref([]);
        const priceCount = ref(1);
        for (const item of goodsStock) {
          //这个是判断有没有货的操作
          if (item.stock !== 0) {
            goodId.push(item.id);
          } else {
            goodId.push(-1);
          }
        }

        const getGoods = () => {
          axios.get("./js/goods.json").then((res) => {
            const tempArray = [];
            // console.log(goodId); //有货的id 没货的id为 -1
            for (let i = 0; i < res.data.length; i++) {
              if (res.data[i].id === goodId[i]) {
                tempArray.push(res.data[i]);
              }
            }
            goodsArray.value = tempArray;
            for (const item of goodsArray.value) {
              item.priceCount = 1; //默认为1
              item.checked = false; //checked按钮默认为false
            }
            
            console.log(goodsArray.value);
          });
        };

        const add = (index) => {
          goodsArray.value[index].priceCount++;
        };
        const decrement = (index) => {
          if (goodsArray.value[index].priceCount === 1) {
            return;
          }
          goodsArray.value[index].priceCount--;
        };

        const updateCheckedState = (event, index) => {
          //给到响应式数组里面
          goodsArray.value[index].checked = event.target.checked;
        };

        const selectdItemCount = ref(0);
        const totalItemPrice = ref(0);
        watchEffect(() => {
          //就是这里面的响应式发生变化 就会触发watchEffect()
          selectdItemCount.value = 0;
          totalItemPrice.value = 0;
          for (const item of goodsArray.value) {
            if (item.checked === true) {
              selectdItemCount.value += item.priceCount;
              totalItemPrice.value += item.priceCount * item.price;
            }
          }
          totalItemPrice.value = totalItemPrice.value.toFixed(2);
        });

        //若没有选择商品
        const shopNoSelect = () => {
          for (const item of goodsArray.value) {
            if (item.checked === true) {
              return true;
            }
          }
          return false; //如果没有一个true就返回false
        };

        const submit = async () => {
          //提交结算
          try {
            if (!shopNoSelect()) {
              //则提示警告信息:
              ElMessage({
                message: "请至少选择一件商品",
                type: "warning",
              });
            }
            for (const item of goodsArray.value) {
              console.log(item.priceCount);
              if (item.checked === true) {
                let goodsNamePriceCount = await useGoodsStore().fetchInventory(
                  item.name
                );
                console.log(goodsNamePriceCount);

                if (item.priceCount > goodsNamePriceCount) {
                  ElMessage.error(`结算失败,${item.name}库存不足`);
                  return;
                }
              }
            }
            ElMessage({
              message: "结算成功",
              type: "success",
            });
          } catch (error) {
            ElMessage.error(`结算失败,${请求返回的错误信息}`);
          }
        };

        onMounted(() => {
          //页面渲染之后,直接调用
          getGoods(); //调用
        });
        return {
          //在这个非工程文件当中的vue3 都是需要return一下的
          goodsArray,
          priceCount,
          add,
          decrement,
          selectdItemCount,
          totalItemPrice,
          updateCheckedState,
          submit,
        };
        // TODOEnd
      },
    });
    app.use(ElementPlus);
    app.use(createPinia());
    app.mount("#app");
  </script>
</html>

8、冰岛人:

我这种方法是比较简单的 其实还可以用map集合或者 递归 他这里说五代人 并不包含第五代人。

/**
 * @description 通过输入的两个人的姓名返回相应的字符串
 * @param {array} data 当地的人口信息
 * @param {string} name1 要查询的两人名字之一
 * @param {string} name2 要查询的两人名字之一
 * @return {string} 根据被查询两人的名字返回对应的字符串
 * */
function marry(data, name1, name2) {
  // TODO:补充代码,实现目标效果
  console.log(data); //和NameAll是对应的
  let data2 = deepCopy(data);
  console.log(data2);

  const NameAll = [];
  for (let i = 0; i < data2.length; i++) {
    NameAll.push(`${data2[i].givenName} ${removeSuffix(data2[i].familyName)}`);
  }

  console.log(NameAll); // 和data是对应,就是去掉了后面的尾缀
  //查询其中一人是否在名单中
  const person1 = NameAll.findIndex((name) => name == name1);
  const person2 = NameAll.findIndex((name) => name == name2);
  console.log(person1);
  console.log(person2);
  if (person1 == -1 || person2 == -1) {
    return "NA";
  }
  //直接判断性别
  const gender1 = getGender(data2[person1].familyName);
  const gender2 = getGender(data2[person2].familyName);
  if (gender1 === gender2) {
    return "Whatever";
  }

  let nameObj1 = data2[person1];
  let nameObj2 = data2[person2];
  //前面的代码都已经拦截完毕了,现在开始直接进入查找就行了

  //april mikesdottir 和 steve billsson 是no
  //april mike 和 steve bill 是 no
  if (hasCommonAncestor(data2, nameObj1, nameObj2)) {
    return "No";
  } else {
    return "Yes";
  }
}

//深拷贝
function deepCopy(obj) {
  if (typeof obj !== 'object' || obj === null) {
    return obj;
  }
  
  let copy = Array.isArray(obj) ? [] : {};
  
  for (let key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key)) {
      copy[key] = deepCopy(obj[key]);
    }
  }
  
  return copy;
}

function hasCommonAncestor(data, name1, name2) {
  const ancestors1 = computeAncestors(data, name1);
  const ancestors2 = computeAncestors(data, name2);

  if (ancestors1 == ancestors2) {
    return true;
  }
  return false;
}
//找到最后的祖先
function computeAncestors(data, name) {
  //先切割掉 sson和sdottir 不要割掉 m 和 f 知道是祖宗
  for (let i = 0; i < data.length; i++) {
    data[i].familyName = removeSuffix2(data[i].familyName);
  }

  let ancestor = null; //设置祖先变量

// console.log(name.familyName == data[7].givenName);

  for (let i = 0; i < data.length; i++) {
    if (data[i].givenName == name.familyName) {
      if (data[i].familyName.charAt(data[i].familyName.length - 1) == 'm') {
        ancestor = data[i].givenName;
        break;
      }
      for (let j = 0; j < data.length; j++) {
        if (data[j].givenName == data[i].familyName) {
          if (data[j].familyName.charAt(data[j].familyName.length - 1) == 'm') {
            ancestor = data[j].givenName;
            break;
          }
          for (let k = 0; k < data.length; k++) {
            if (data[k].givenName == data[j].familyName) {
                  ancestor = data[k].givenName;
            }
          }
        }
      }
    }
  }
  console.log(ancestor);
  return ancestor
}

//递归

/**
 * 查询冰岛人名的性别的函数
 * @param {String} name 传递进来的冰岛人名
 * @return {String} 返回男是 male 女的是female
 */
function getGender(name) {
  if (name.endsWith("sson") || name.endsWith("m")) {
    return "male"; //男
  } else if (name.endsWith("sdottir") || name.endsWith("f")) {
    return "female"; //女
  }
}
// 使用正则表达式匹配字符串结尾的 'sson'、'sdottir'、'm' 或 'f' 并替换为 ''
function removeSuffix(name) {
  return name.replace(/(sson|sdottir|m|f)$/, "");
}
// 使用正则表达式匹配字符串结尾的 'sson'、'sdottir'并替换为 ''
function removeSuffix2(name) {
  return name.replace(/(sson|sdottir)$/, "");
}

module.exports = marry;

9、这是一个“浏览器”

也是纯粹的JS题,功能是实现了,但是不知为啥过不了检测。

"use strict";
class Tab {
  // 构造方法
  constructor(id) {
    // 获取元素
    this.main = document.querySelector(id);
    this.add = this.main.querySelector(".tabadd");
    this.ul = this.main.querySelector(".fisrstnav ul");
    this.fsection = this.main.querySelector(".tabscon"); //content页面
    this.init();
  }
  // 初始化
  init() {
    this.updateNode();
    // init初始化操作让相关元素绑定事件
    
    this.add.onclick = this.addTab.bind(this.add, this);
    for (var i = 0; i < this.lis.length; i++) {
      this.lis[i].index = i;
      this.lis[i].onclick = this.toggleTab.bind(this.lis[i], this);
      this.remove[i].onclick = this.removeTab.bind(this.remove[i], this);
      this.spans[i].ondblclick = this.editTab;
      this.sections[i].ondblclick = this.editTab;
    }
  }
  // 更新所有的li和section
  updateNode() {
    this.lis = this.main.querySelectorAll("li");
    this.remove = this.main.querySelectorAll(".icon-guanbi");
    this.sections = this.main.querySelectorAll("section");
    this.spans = this.main.querySelectorAll(".content");
  }
  // 1.切换功能
  toggleTab(event) {
    // TODO: 添加代码,点击标签页,切换到对应标签页的功能
    var num = this.getAttribute("num");
    if (num != null && !(this.classList.contains("liactive"))) return; //阻止冒泡
    event.clearClass(); //this.clearClass不行 因为指向的是元素
    this.className = 'liactive'
    event.sections[this.index].className = 'conactive'
      // TODO结束
  }
  // 2.清空所有标签页及其内容页类名
  clearClass() {
    for (var i = 0; i < this.lis.length; i++) {
      this.lis[i].className = "";
      this.sections[i].className = "";
    }
  }
  // 3.添加标签页
  addTab(event) {
    // TODO:添加代码,当点击加号,添加新的标签页(对应的内容页也应一并添加)
    event.clearClass(); //清除一下
    let newTab = document.createElement('li');
    let lengthTab = event.lis.length + 1
    newTab.className = 'liactive'
    newTab.innerHTML = `<span class="content">标签页${lengthTab}</span>
    <span class="iconfont icon-guanbi">
        <span class="glyphicon glyphicon-remove">
        </span>
    </span>`
    event.ul.appendChild(newTab);
    //添加section内容
    let newTabScon = document.createElement('section');
    newTabScon.className = 'conactive';
    newTabScon.innerHTML = `标签页${lengthTab}的内容`;
    event.fsection.appendChild(newTabScon);
    event.updateNode(); //需要更新一下节点
    event.init();
    // TODO结束
  }
  // 4.删除功能
removeTab(event) {
  let index = Array.from(event.remove).indexOf(this); // 获取点击的删除按钮在数组中的索引
  var lis = document.getElementsByTagName("li");

  for (let index = 0; index < lis.length; index++) {
    if (lis[index] == this.parentElement) {
        this.parentElement.setAttribute('num', index);
    }
}

  if (event.lis[index].classList.contains('liactive')) { // 如果要删除的标签页是当前选中的标签页
      if (index < event.lis.length - 1) { // 不是最后一个标签页
          event.lis[index + 1].click(); // 选中临近的下一个标签页
      } else if (index > 0) { // 是最后一个标签页
          event.lis[index - 1].click(); // 选中临近的上一个标签页
      }
  }

  event.ul.removeChild(event.lis[index]); // 从页面中删除对应的标签页
  event.fsection.removeChild(event.sections[index]); // 从页面中删除对应的内容页
  event.updateNode(); // 更新节点
}

  // 5.修改功能
  editTab() {
    var str = this.innerHTML;
    window.getSelection
      ? window.getSelection().removeAllRanges()
      : document.Selection.empty();
    this.innerHTML = '<input type="text" />';
    var input = this.children[0];
    input.value = str;
    input.select(); //让文本框里的文字处于选定状态
    // TODO:实现双击修改内容,当文本框失焦时,把修改的值赋给被双击的对象,并作上已修改的标记
    let li = this;
    input.onblur = function () {
      li.innerHTML = this.value
    }
    // TODO结束
  }
}
var tab = new Tab("#tab");

本文转载自: https://blog.csdn.net/m0_56646930/article/details/136558163
版权归原作者 Stolen 遗憾 所有, 如有侵权,请联系我们删除。

“第十五届蓝桥杯(Web 应用开发)模拟赛 3 期-大学组And职业组”的评论:

还没有评论