2024第十五届蓝桥杯第三次模拟赛web组题解

1. 创意广告牌

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
.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

1
2
3
4
5
6
7
8
9
10
11
<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.神秘咒语

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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. 朋友圈

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
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 美食蛋白质揭秘

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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 营业状态切换

1
2
3
4
5
6
7
8
function useToggle(state) {
// TODO:待补充代码
const isWorking=ref(state)
const toggleWorking=()=>{
isWorking.value=! isWorking.value
}
return [isWorking, toggleWorking]
}

7. 小说阅读器

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
// 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,
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//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. 冰岛人

这个没问题,但是过不去

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
/**
* @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;

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

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
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
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
"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");
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(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结束
}
}
var tab = new Tab("#tab");

10 趣味加密解密

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
/*
常量 defaultCodes 是默认密码表,当输入的密码表长度小于 2 时采用
请勿进行修改 ,否则可能造成考生提交的函数与检测用例所采用的默认密码表不一致,导致检测无法通过
*/
const defaultCodes = "这是十六位默认密码表请勿进行改动";

/*
函数 string2Unit8Array 接受一个参数 str ,能够返回 str 以 UTF8 格式解码后的 Unit8Array 数组。
参数 str 类型为 String 字符串。
*/
function string2Unit8Array(str) {
return new TextEncoder().encode(str);
}

/*
函数 uint8Array2String 接受一个参数 arr ,能够返回 arr 以 UTF8 格式编码之后的 String 字符串。
参数 arr 类型为 Array 数组。
*/
function uint8Array2String(arr) {
return new TextDecoder().decode(new Uint8Array(arr));
}

/*
加密函数 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 };


2024第十五届蓝桥杯第三次模拟赛web组题解
https://asxjdb.github.io/2024/03/16/2024第十五届蓝桥杯第三次模拟赛web组题解/
作者
Asxjdb
发布于
2024年3月16日
许可协议