跳转至

24模拟赛3

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;
  /* TODO:待补充代码  设置圆角 10px,背景图片为woodiness.jpg  */
 border-radius: 10px;
 background-image: url('../images/woodiness.jpg');
}
.top-sign {
  position: relative;
  width: 200px;
  height: 100px;
  background-color: #a87f4a;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 1rem;
  /* TODO:待补充代码   上面两个角是圆角 15px,下面两个角是直角  元素 x 轴倾斜 20度*/
 border-radius: 15px 15px 0 0 ;
 transform: skewX(-20deg); 
}

2.原子化CSS

<div flex="~ col">
    <div red></div>
    <div yellow></div>
    <div blue></div>
</div>

div[flex="~ col"]{
  display: flex;
  flex-direction: column;
}

flex="~ col" ,其中 ~ 代表 flex 本身,表示使用 flex 布局,而 col 代表让 flex 纵向布局

3.神秘咒语

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

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

4. 朋友圈

const textArea = document.querySelector("#text");
const postBtn = document.querySelector("#post");
document.addEventListener("DOMContentLoaded", function () {
  // TODO: 请在此补充页面加载时缓存检查的代码
  const value = localStorage.getItem("savedText");
  if (value) {
    textArea.innerText = value;
  }else{
    // 不能用这个:
    // postBtn.disabled=true
    postBtn.setAttribute('disabled','disabled')
  }
});

// 当文本框输入内容改变时,动态地设置localStorage缓存,并根据有没有文本改变按钮状态
// 此处使用了防抖函数,避免太过频繁地更新缓存
document.getElementById("text").addEventListener(
  "input",
  debounce(function () {
    // 提示正在保存中
    document.getElementById("prompt").textContent = "正在保存中...";

    // TODO: 请在此补充用户输入时设置缓存和调整按钮状态的代码
    localStorage.setItem("savedText", textArea.value);
    if(textArea.value){
      // postBtn.disabled=false
      postBtn.removeAttribute('disabled')
    }else{
      postBtn.setAttribute('disabled','disabled')
    }

    // TODO-END

    // 过一段时间后提示保存完成,模拟上传数据至后台的效果
    setTimeout(function () {
      document.getElementById("prompt").textContent = "内容已保存";
    }, 750);
  }, 200)
);

document.getElementById("post").addEventListener("click", function () {
  const content = document.getElementById("text").value;
  const element = createContent(content);
  document.querySelector(".contents").appendChild(element);
  document.getElementById("prompt").textContent = "";

  // TODO: 请在此补充用户点击“发表”按钮时清空文本框和缓存的代码
  textArea.value=''
  localStorage.setItem('savedText', "")
  postBtn.setAttribute('disabled','disabled')
});

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

// 用户点击“发表”后,创建一条新信息的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 美食蛋白质揭秘

async function fetchData() {
    let res;
    // TODO:待补充代码
    await fetch(MockURL)
        .then((response) => response.json())
        .then((data) => {
        res = data;
    })
        .catch((error) => console.error("Error:", error));
    const container = document.querySelector(".protein-container");
    let cont = res.reduce(
        (prev, now) =>
        prev +
        `<div class="protein-item">${now.name} ${now.value}</div>`,
        ``
    );
    container.innerHTML = cont;
    // 记得echartsInit的第一个数据要是这个:
     res.unshift({ name: "表头", icon: "none" })
    echartsInit(res);
}
fetchData();

6 营业状态切换

function useToggle(state) {
    // TODO:待补充代码
    const isWorking=ref(state)
    const toggleWorking=()=>{
        isWorking.value=! isWorking.value
    }
    return [isWorking, toggleWorking]
}

7. 小说阅读器

// run/index.js
const fs = require("fs");
//读取txt小说文件
let readFilePath = "./run/book.txt";
let writeFilePath = "./run/book.json";
let options = "UTF-8";

//请按照要求修改一下两个函数内容。

// run/index.js

//读取txt小说文件,并按对应数据格式返回。
const readFile = (file) => {
  //TODO:待补充代码
  try {
    const book = fs.readFileSync(file).toString()
    // 分割字符串 + 去掉两边空字符 + 移除空行
    const list = book.split(/\r\n/g).map(t => t.trim()).filter(t => !!t)

    const res = { name: list[0], data: []}

    const rollReg = /^---([^-]+?)---$/
    let i = 2

    while (i < list.length) {
      let s = list[i]
      if (rollReg.test(s)) { // 卷
        res.data.push({ isRoll: true, title: rollReg.exec(s)[1] })
      } else { // 章节
        const j = i + 1
        while (i < list.length && list[i] !== '------------') i++ 
        res.data.push({ title: s, content: list.slice(j, i) })
      }
      i++
    }

    let result = JSON.stringify(res);
    return result;
  } catch (err) {
    return null;
  }
};
//写入json文件中
const writeFile = (file, data) => {
  //TODO:待补充代码
  fs.writeFileSync(file, data)
};

//以下内容请勿修改,否则将影响结果
let data = readFile(readFilePath);
if (data != null) writeFile(writeFilePath, data);

module.exports = {
  writeFile,
  readFile,
};
//component
next(value) {
    // TODO:待补充代码
    let now = this.activeChapter + value;
    if(this.chapters[now].isRoll){
        now+=value
    }
    let rollCount = 0;
    this.chapters.forEach((element) => {
        if (element.isRoll) rollCount++;
    });
    // console.log(rollCount);
    if (now < 1 || now > this.chapters.length - rollCount) return;
    else this.activeChapter=now
},

    created() {
        // TODO:待补充代码
        axios("../run/book.json").then((data) => {
            // console.log(data);
            this.bookName = data.data.name;
            this.chapters = data.data.data;
        });
    },

8. 冰岛人

这个没问题,但是过不去

/**
 * @description 通过输入的两个人的姓名返回相应的字符串
 * @param {array} data 当地的人口信息
 * @param {string} name1 要查询的两人名字之一
 * @param {string} name2 要查询的两人名字之一
 * @return {string} 根据被查询两人的名字返回对应的字符串
 * */

function marry(data, name1, name2) {
  // TODO:补充代码,实现目标效果
  let [firstName1, lastName1] = name1.split(" ");
  let [firstName2, lastName2] = name2.split(" ");

  // 检查是否都在名单里
  const isExist = (name1, name2) => {
    for (const item of data) {
      if (item.givenName === name1 && item.familyName.indexOf(name2) === 0) {
        return true;
      }
    }
    return false;
  };

  if (!isExist(firstName1, lastName1) || !isExist(firstName2, lastName2)) {
    return "NA";
  }

  // 检查是否为同性 
  let genderValue = 0;
  const checkGender = (name1, name2) => {
    for (const item of data) {
      if (item.givenName === name1 && item.familyName.indexOf(name2) === 0) {
        let gender = item.familyName.slice(
          name2.length,
          item.familyName.length
        );
        if (gender === "sson") genderValue += 1;
        else if (gender === "sdottir") genderValue += 2;
      }
    }
  };
  checkGender(firstName1, lastName1)
  checkGender(firstName2, lastName2)

  if(genderValue != 3) return "Whatever" 


}

module.exports = marry;

这是大佬写的题解,可以过去

function marry(data, name1, name2) {
  let [na1, na2] = [name1.split(' '), name2.split(' ')];
  let givenArr = Array.from(data,({ givenName }) => givenName);
  if(!givenArr.includes(na1[0]) || !givenArr.includes(na2[0])) return 'NA'
  let {givenName:gn1, familyName:fn1} = data.find((a)=>a.givenName===na1[0])
  let {givenName:gn2, familyName:fn2} = data.find((a)=>a.givenName===na2[0])
  let g1 = fn1.endsWith('sson') || fn1.endsWith('m') ? 'M' : 'F',
      g2 = fn2.endsWith('sson') || fn2.endsWith('m') ? 'M' : 'F';
  if(g1 === g2) return 'Whatever';

  function findAncestor(g, f, generation, ance = []) {
    if (generation >= 3 || !g) return null; // 出口
    let parentName = f.replace(/sson|sdottir/, '');
    let {givenName:gn, familyName:fn} = data.find(p => p.givenName === parentName);
    if (gn) ance.push(gn+fn);
    return findAncestor(gn, fn, generation + 1, ance);
  }
   // 获取两个人的祖先列表
  let ancestors1 = [], ancestors2 = [];
  findAncestor(gn1, fn1, 0, ancestors1);
  findAncestor(gn2, fn2, 0, ancestors2);
   // 检查是否有共同的祖先
   console.log(ancestors1, ancestors2)
  let commonAncestor = ancestors1.some(ancestor => ancestors2.includes(ancestor));
  return commonAncestor ? 'No' : 'Yes';
}
module.exports = marry;

9 这是一个“浏览器”

// 1.切换功能
toggleTab(that) {
    // TODO: 添加代码,点击标签页,切换到对应标签页的功能
    that.clearClass()
    this.classList.add("liactive");
    that.sections[this.index].classList.add("conactive");

    // console.log(this.index);
    // TODO结束
}
// 2.清空所有标签页及其内容页类名
clearClass() {
    for (var i = 0; i < this.lis.length; i++) {
        this.lis[i].className = "";
        this.sections[i].className = "";
    }
}
// 3.添加标签页
addTab(that) {
    // TODO:添加代码,当点击加号,添加新的标签页(对应的内容页也应一并添加)
    let newLi = document.createElement('li')
    newLi.innerHTML = `<span class="content">标签页${that.lis.length + 1}</span>
    <span class="iconfont icon-guanbi">
        <span class="glyphicon glyphicon-remove"></span>
    </span>`
    that.ul.appendChild(newLi)

    let newSection = document.createElement('section')
    newSection.innerText = `标签页${that.lis.length + 1}的内容`
    that.fsection.appendChild(newSection)
    that.init()
    that.clearClass()
    that.lis[that.lis.length - 1].classList.add('liactive')
    that.sections[that.lis.length - 1].classList.add('conactive')
    // TODO结束
}
// 4.删除功能
removeTab(that, e) {
    // 阻止冒泡,不然会触发toggleTab
    e.stopPropagation();
    let index = this.parentNode.index, flag = 0;
    if (that.lis[index].classList.value) {
        // 删除的标签页是当前选中的标签页
        if (index === that.lis.length - 1) {
            flag = -1
        } else {
            flag = 1
        }
        that.lis[index + flag].classList.add('liactive')
        that.sections[index + flag].classList.add('conactive')
    }
    that.lis[index].remove()
    that.sections[index].remove();
    that.init();

    for (let i = index; i < that.lis.length; i++) {
        that.lis[i].children[0].innerText = `标签页${i+1}`
        that.sections[i].innerText = `标签页${i+1}的内容`
        // console.log(that.lis[i].children[0].innerText);
    }
}
// 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:实现双击修改内容,当文本框失焦时,把修改的值赋给被双击的对象,并作上已修改的标记
    // console.log(this);
    input.addEventListener("blur", (e) => {
        this.innerHTML = input.value;
    });
    // TODO结束
}

10 趣味加密解密

/*
    加密函数 encryption 接受两个参数 plainText 和 codes ,能够实现对明文的加密,并返回加密后的密文字符串。
    函数参数 plainText 是用户输入的明文,类型为 String 字符串。
    函数参数 codes 是用户输入的密码表,类型也为 String 字符串,并且可能存在重复字符,需要进行去重
    若去重后 codes 长度小于 2 则应采用默认密码表 defaultCodes 。
*/
function encryption(plainText, codes) {
  //TODO
  let plainArray = string2Unit8Array(plainText);
  // 需要使用去重后的密钥
  console.log(plainArray);
  codes = [...new Set(codes)].join("");
  if (codes.length < 2) codes = defaultCodes;

  //   4. 单位长度:log length(code)(256)=2
  let len = Math.ceil(Math.log(256) / Math.log(codes.length));
  let dive = codes.length;

  let ans = [];
  for (let i = 0; i < plainArray.length; i++) {
    let stringTemp = "";
    for (let idx = 0; idx < len; idx++) {
      stringTemp = codes[plainArray[i] % dive] + stringTemp;
      plainArray[i] /= dive;
    }
    ans.push(stringTemp);
  }
  return ans.map((str) => str.split("").reverse().join("")).join("");
}

/*
    加密函数 decryption 接受两个参数 cipherText 和 codes ,能够实现对密文的解密,并返回解密之后的明文字符串。
    函数参数 cipherText 是用户输入的密文,类型为 String 字符串。
    函数参数 codes 是用户输入的密码表,类型也为 String 字符串,并且可能存在重复字符,需要进行去重
    若去重后 codes 长度小于 2 则应采用默认密码表 defaultCodes 。
*/
function decryption(cipherText, codes) {
  //TODO
  codes = [...new Set(codes)].join("");
    if (codes.length < 2) codes = defaultCodes;
  let len = Math.ceil(Math.log(256) / Math.log(codes.length));
  let dive = codes.length;
  if (cipherText.length % len) return "ERROR";

  let cipherArray = [];
  for (let i = 0; i < cipherText.length; i+=len) {
    cipherArray.push(cipherText.slice(i,i+len).split('').join(''))
    // 不必加reverse,方便下面计算
    // cipherArray.push(cipherText.slice(i,i+len).split('').reverse().join(''))
  }
  console.log(cipherArray);

  let ans=[]
  cipherArray.forEach((item)=>{
    let ansTmp=0
    for (let idx = 0; idx < len; idx++) {
        ansTmp+=codes.indexOf(item[idx]) * dive**idx
        // debugger
    }
    ans.push(ansTmp)    
  })
  console.log(ans);
  return uint8Array2String(ans)
}

/*
    调用 encryption("你好,世界","0123456789ABCDEF") 方法,应当返回密文 "4EDB0A5E5ADBFECBC84E8B697E59C8" 。
    调用 decryption("4EDB0A5E5ADBFECBC84E8B697E59C8","0123456789ABCDEF") 方法,应当返回明文 "你好,世界" 。
*/

//以下代码请勿删除,否则可能导致检测不通过
export { defaultCodes, encryption, decryption };

11 嘟嘟购物

<!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/element-plus@2.3.7/index.css" />
    <link rel="stylesheet" href="./css/index.css" />
    <script src="./lib/vue.min.js"></script>
    <script src="./css/element-plus@2.3.7/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 in goodsCart">
                <div class="p-checkbox">
                  <input
                    type="checkbox"
                    v-model="item.checked"
                    :name="item.name"
                    :id="item.id"
                    class="j-checkbox"
                  />
                </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="edit(item.id,-1)"
                      >-</a
                    >
                    <input type="text" class="itxt" v-model="item.num" />
                    <a
                      href="javascript:;"
                      class="increment"
                      @click="edit(item.id,1)"
                      >+</a
                    >
                  </div>
                </div>
                <div class="p-sum">{{(item.num*item.price).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>{{total.number}}</em>件商品
                </div>
                <div class="price-sum">总价: <em>¥{{total.price}}</em></div>
                <div class="btn-area" @click="submit">去结算</div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </body>
  <script type="module">
    const { createApp, ref, onMounted, computed } = Vue;
    const { createPinia } = Pinia;
    const { ElMessage, ElNotification } = ElementPlus;

    const app = Vue.createApp({
      setup() {
        // TODO:补充代码,实现目标效果
        let goodsCart = ref([]);
        let detail = [];
        let goodsStore = useGoodsStore();

        const edit = (id, step) => {
          let target = goodsCart.value.find((item) => item.id === id);
          if (target.num === 1 && step === -1) return;
          target.num += step;
        };

        const total = computed(() => {
          const tmp = {
            number: 0,
            price: 0,
          };
          goodsCart.value.forEach((item) => {
            if (item.checked) {
              tmp.number += item.num;
              tmp.price += item.num * item.price;
            }
          });
          return tmp;
        });

        const submit = () => {
          if (goodsCart.value.every((item) => !item.checked)) {
            ElMessage({
              message: "请至少选择一件商品",
              type: "warning",
            });
            return;
          }

          // 模拟发送请求获取所有商品的库存:
          let stock = [];
          goodsCart.value.forEach((item) => {
            if (item.checked) {
              goodsStore
                .fetchInventory(item.name)
                .then((res) => {
                  console.log(res);
                  stock.push({
                    id: item.id,
                    stock: res,
                  });
                })
                .catch((res) => {
                  console.log(res);
                  ElMessage({
                    message: `结算失败,${res}`,
                    type: "error",
                  });
                });
            }
          });

          // 库存
          goodsCart.value
            .filter((item) => item.checked)
            .forEach((item) => {
              stock.forEach((store) => {
                if (store.id === item.id && store.stock < item.num) {
                  ElMessage({
                    message: `结算失败,${item.name}库存不足`,
                    type: "error",
                  });
                  return;
                }
              });
            });
            ElMessage({
                    message: `结算成功`,
                    type: "success",
                  });
          // 发送
        };

        const getAxios = async () => {
          await axios("./js/goods.json").then((res) => {
            detail = res.data;
          });

          goodsStore.store.forEach((item) => {
            if (item.stock) {
              goodsCart.value.push({
                id: item.id,
                name: item.name,
              });
            }
          });
          goodsCart.value.forEach((item) => {
            for (let priceImage of detail) {
              if (priceImage.id === item.id) {
                item.price = priceImage.price;
                item.image = priceImage.image;
                item.checked = false;
                item.num = 1;
              }
            }
          });
          // console.log(goodsCart.value);
        };
        onMounted(getAxios);

        return {
          goodsCart,
          edit,
          total,
          submit,
        };
        // TODOEnd
      },
    });
    app.use(ElementPlus);
    app.use(createPinia());
    app.mount("#app");
  </script>
</html>
<div v-for="item in carList" class="cart-item check-cart-item">
    <div class="p-checkbox">
        <input v-model="item.checked" type="checkbox" name="" id="" class="j-checkbox">
    </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:;" @click="Edit(item.id,0)" class="decrement" >-</a>
            <input type="text" v-model="item.num" class="itxt">
            <a href="javascript:;" @click="Edit(item.id,1)" class="increment" >+</a>
        </div>
    </div>
    <div class="p-sum">{{(item.num*item.price).toFixed(2)}}</div>
    <div class="p-action"><a href="javascript:;">删除</a></div>
</div>

<!-- 结算模块 -->
<div class="cart-floatbar">
    <div class="select-all">
    </div>
    <div class="toolbar-right">
        <div class="amount-sum">已经选<em>{{Total.select}}</em>件商品</div>
        <div class="price-sum">总价: <em>¥{{Total.price}}</em></div>
        <div class="btn-area" @click="comMit">去结算</div>
    </div>
</div>


<script type="module">

  const { createApp,reactive,onMounted,computed} = Vue
  const { createPinia } = Pinia
  const { ElMessage, ElNotification  } = ElementPlus
  const app = Vue.createApp({
    setup() {
      // TODO:补充代码,实现目标效果
      let store=useGoodsStore();
      let carList=reactive([])
      let Edit=(id,type)=>{
        carList.map(e=>{
          if(e.id==id){
            e.num=type==1?e.num+1:e.num-1
            e.num=e.num<1?1:e.num
          }
        })
      }
      let comMit=async()=>{
        let commit=carList.filter(s=>s.checked)
        if(commit==null || commit.length==0){
          ElMessage({
                message: `请至少选择一件商品`,
                type: 'warning',
              })
        }
        for (let index = 0; index < commit.length; index++) {
          const e = commit[index];
          let a= await store.fetchInventory(e.name)
          if(a<e.num){
              ElMessage({
                message: `结算失败,${e.name}库存不足`,
                type: 'error',
              })
            break;
          }else if(index==commit.length-1){
            ElMessage({
            message: `结算成功`,
            type: 'success',
            })
          }
        }
      }
      let Total= computed(()=>{
        return  {
          select:carList.reduce((pre,e)=>{return pre+(e.checked*e.num)},0),
          price:carList.reduce((pre,e)=>{return pre+(e.checked?e.price*e.num:0)},0).toFixed(2),

        }
      })
      onMounted(async()=>{
        axios.get('./js/goods.json')
        .then(r=>{
          let data=r.data
          data.forEach(element => {
           let stock= store.store.find(s=>s.id==element.id).stock
           element.num=1
           element.checked=false
            if(stock!=0){
              carList.push(element)
            }
          });
        })
      })
      return {
        store,
        carList,
        Total,
        Edit,
        comMit
      }
      // TODOEnd
    },
  });