感觉蓝桥杯的模拟赛一次比一次难了😑
制作不易,代码都是纯手敲,觉得有帮助的伙伴们记得点个赞评论一下,谢谢大家支持😍
话不多说直接上答案
目录
1、想不相等
2、三行情书
3、电影院在线订票
4、老虎机
5、星际通讯
6、蓝桥杯排位赛
7、拼出一个未来
8、超能英雄联盟
HeroList.js
TeamList.js
9、万能合成台
10、账户验证
1、想不相等
这里有个坑,题意说如果不符合要求要抛出错误'...',实际上只需要return即可,不需要用到throw语句,当时这里卡了有一会
javascript">/**
* @param {string} val
* @return {Object}
*/
var expectFn = function(val) {
// TODO
return{
toBe(_val){
return val === _val || 'Not Equal'
},
notToBe(_val){
return val !== _val || 'Equal'
}
}
};
// console.log(expectFn(5).toBe(5)); // true
// console.log(expectFn(5).notToBe(5)); // "Equal"
// 检测需要,请勿删除
module.exports = expectFn;
2、三行情书
这题要注意的是,span标签原本为行内元素,无法设置宽高,需要将span转换为块级元素
span {
font-size: 20px;
color: #837362;
/* TODO:补充下面的代码 */
display: block;
width: 100%;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
p {
color: #837362;
/* TODO:补充下面的代码 */
display: -webkit-box;
-webkit-box-orient: vertical;
text-overflow: ellipsis;
overflow: hidden;
-webkit-line-clamp: 3;
}
3、电影院在线订票
/* TODO:
1. 完成数据请求,生成电影名,价格以及座位情况
2. 绑定点击事件,实现订票功能
*/
// 获取座位区域节点
const seatAreaNode = document.getElementById("seat-area");
// 获取电影名节点
const movieNameNode = document.getElementById("movie-name");
// 获取电影票价节点
const moviePriceNode = document.getElementById("movie-price");
// 获取已订电影票数量节点
const count = document.getElementById("count");
// 获取已订电影票总价节点
const total = document.getElementById("total");
axios('./data.json').then(res=>{
let {data} = res
console.log(data);
movieNameNode.innerText = data.name
moviePriceNode.innerText = data.price
let tpl = ``
data.seats.map(item=>{
tpl+=`<div class="row">{{replace}}</div>`
let _tpl = ''
item.map(_item=>{
_tpl+=_item?`
<div class="seat o***upied"></div>
`:`<div class="seat"></div>`
})
tpl = tpl.replace('{{replace}}',_tpl)
})
seatAreaNode.innerhtml = tpl
;[...document.getElementsByClassName('seat')].map(node=>{
if(![...node.classList].includes('o***upied')){
node.onclick=function(){
if([...node.classList].includes('selected')){
node.classList.remove('selected')
count.innerHTML = parseInt(count.innerHTML) - 1
total.innerHTML = parseInt(total.innerHTML) - 20
}else{
node.classList.add('selected')
count.innerHTML = parseInt(count.innerHTML) + 1
total.innerHTML = parseInt(total.innerHTML) + 20
}
}
}
})
})
4、老虎机
这题如果读懂题意还是很简单的,要r1、r2和r3减1即可
// GetResult 中奖结果函数,r1,r2,r3 为最后图片停留位置,以第一列为例,最终显示的元素是 sevenFirst 下的第 r 个 li 元素。
GetResult(r1, r2, r3) {
// TODO 待补充代码
let o1 = document.getElementById('sevenFirst').getElementsByTagName('li'),
o2 = document.getElementById('sevenSecond').getElementsByTagName('li'),
o3 = document.getElementById('sevenThird').getElementsByTagName('li'),
oTip = document.getElementsByClassName('textPanel')[0]
if(o1[r1-1].dataset.point == o2[r2-1].dataset.point == o3[r3-1].dataset.point){
oTip.innerHTML ='恭喜你,中奖了'
}else{
oTip.innerHTML ='很遗憾,未中奖'
}
}
}
5、星际通讯
这题难度还是比较简单的,因为codonTable里的key都是三位数的
/**
* @param {string} alienMessage 外星人的密文
* @return {string} 翻译结果
*/
const translate = (alienMessage) => {
// TODO:待补充代码
if(!alienMessage)return ""
if(alienMessage.length%3!=0)return"无效密语"
let strArr = [],
_str = '',
result = ''
for(let strIdx in alienMessage){
_str+=alienMessage[strIdx]
if(_str == 'XXI')break
if(_str.length == 3){
strArr.push(_str)
_str = ''
}
}
result+=(strArr.map(item=>codonTable[item])+'').replaceAll(',','')
if(result=='undefined' || !result)return "无效密语"
return result
};
6、蓝桥杯排位赛
考察的是echart,直接上答案
const { createApp, ref, onMounted } = Vue;
const app = createApp({
setup() {
const chartsData = ref([]);
onMounted(() => {
// TODO:待补充代码 请求数据,并正确渲染柱形图和地图
fetch('./mock/map.json').then(res=>res.json()).then(res=>{
let schoolList = []
res.map(item=>{
item.school_power.map((item,idx)=>schoolList.push(item))
})
schoolList.sort((a,b)=>b.power-a.power)
schoolList.length = 10
showChartBar(schoolList);
showChinaMap(res);
})
});
// 展示柱状图
const showChartBar = (schoolList) => {
const myChart = echarts.init(document.getElementById('chart'));
let data = chartsData.value.map((item, index) => {
return item.school_power;
});
let result = data.flat(1).sort((a, z) => {
return z.power - a.power;
});
let arr = result.slice(0, 10);
let school = arr.map((item) => {
return item.name;
});
let power = arr.map((item) => {
return item.power;
});
// 指定配置和数据
const option = {
xAxis: {
type: 'category',
axisLabel: { interval: 0, rotate: 40 },
// TODO:待修改 柱状图 x 轴数据 -> 前 10 学校名称
data: schoolList.map(item=>item.name),
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true,
},
yAxis: {
type: 'value',
boundaryGap: [0, 0.01],
},
series: [
{
// TODO:待修改 柱状图 y 轴数据->学校战力值
data: schoolList.map(item=>item.power),
type: 'bar',
showBackground: true,
backgroundStyle: {
color: 'rgba(180, 180, 180, 0.2)',
},
itemStyle: {
color: '#8c7ae6',
},
},
],
};
// 把配置给实例对象
myChart.setOption(option);
// 根据浏览器大小切换图表尺寸
window.addEventListener('resize', function () {
myChart.resize();
});
};
// 展示地图
const showChinaMap = (data) => {
const chinaMap = echarts.init(document.getElementById('chinaMap'));
// 进行相关配置
const mapOption = {
tooltip: [
{
backgroundColor: '#fff',
subtext: 'aaa',
borderColor: '#***c',
padding: 15,
formatter: (params) => {
return (
params.name +
'热度值:' +
params.value +
'<br>' +
params.data.school_count +
'所学校已加入备赛'
);
},
textStyle: {
fontSize: 18,
fontWeight: 'bold',
color: '#464646',
},
subtextStyle: {
fontSize: 12,
color: '#6E7079',
},
},
],
geo: {
// 这个是重点配置区
map: 'china', // 表示中国地图
label: {
normal: {
show: false, // 是否显示对应地名
},
},
itemStyle: {
normal: {
borderColor: 'rgb(38,63,168)',
borderWidth: '0.4',
areaColor: '#fff',
},
emphasis: {
//鼠标移入的效果
areaColor: 'rgb(255,158,0)',
shadowOffsetX: 0,
shadowOffsetY: 0,
shadowBlur: 20,
borderWidth: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)',
},
},
},
visualMap: {
show: true,
left: 'center',
top: 'bottom',
type: 'piecewise',
align: 'bottom',
orient: 'horizontal',
pieces: [
{
gte: 80000,
color: 'rgb(140,122,230)',
},
{
min: 50000,
max: 79999,
color: 'rgba(140,122,230,.8)',
},
{
min: 30000,
max: 49999,
color: 'rgba(140,122,230,.6)',
},
{
min: 10000,
max: 29999,
color: 'rgba(140,122,230,.4)',
},
{
min: 1,
max: 9999,
color: 'rgba(140,122,230,.2)',
},
],
textStyle: {
color: '#000',
fontSize: '11px',
},
},
series: [
{
type: 'map',
geoIndex: 0,
// TODO:待修改 地图对应数据
data,
},
],
};
// 把配置给实例对象
chinaMap.setOption(mapOption);
};
return {
chartsData,
showChartBar,
showChinaMap,
};
},
});
app.mount('#app');
7、拼出一个未来
// 定义拖放事件的处理函数
function drop(event) {
// 检查是否拖动的拼图块不是当前目标拼图块
// draggedPiece 被拖动的拼图块元素。this 目标位置的拼图块元素。
if (draggedPiece !== this) {
// TODO:待补充代码
let saveArr = [
[draggedPiece.children[0].src,draggedPiece.children[0].dataset.id]
,[this.children[0].src,this.children[0].dataset.id]
]
draggedPiece.children[0].src = saveArr[1][0]
draggedPiece.children[0].dataset.id = saveArr[1][1]
this.children[0].src = saveArr[0][0]
this.children[0].dataset.id = saveArr[0][1]
let imgDataIdList = [...document.getElementById('puzzle-container').getElementsByTagName('img')].map(item=>item.dataset.id)
console.log(imgDataIdList);
if(imgDataIdList == '1,2,3,4,5,6,7,8,9'){
document.getElementById('su***ess-message').classList.remove('hide')
document.getElementById('su***ess-message').classList.add('show')
}else{
document.getElementById('su***ess-message').classList.remove('show')
document.getElementById('su***ess-message').classList.add('hide')
}
}
// 重置正在拖动的拼图块
draggedPiece = null;
}
8、超能英雄联盟
这里我只改动了两个地方
HeroList.js
// TODO:补全代码,实现目标效果
const HeroList = {
template: `
<div class="hero-list">
<h2>可选英雄</h2>
<ul>
<li class="hero-item" v-for="(item,idx) in list">
<span>{{item.name}}</span>
<span>{{item.ability}}</span>
<span>{{item.strength}}</span>
<button @click="clickEvent(idx)" disabled v-if="item.btnInfo.disabled">
{{item.btnInfo.text}}</button>
<button @click="clickEvent(idx)" v-else="item.btnInfo.disabled">
{{item.btnInfo.text}}</button>
</li>
</ul>
</div>
`,
setup() {
let store = useHeroStore(),
list = ref([])
axios('./js/heroes.json').then(({data})=>{
data.map(item=>{
item.btnInfo = {
text:'添加至队伍',
disabled:false
}
})
list.value = data
store.heroes = list.value
})
return{
list,
clickEvent(idx){
list.value[idx].btnInfo.text = '已添加'
list.value[idx].btnInfo.disabled = true
}
}
},
};
// TODOEnd
TeamList.js
// TODO:补全代码,实现目标效果
const TeamList = {
template: `
<div class="team-list">
<h2>我的队伍</h2>
<ul>
<li class="team-item" v-for="(item,idx) in list">
<span>{{item.name}}</span>
<span>{{item.strength}}</span>
<button @click="removeHero(item,idx)">移除</button>
</li>
</ul>
<button class="sort-button" @click="sortStrength">按实力排序</button>
<p class="total-strength">当前队伍战斗力:{{count}} </p>
</div>
`,
setup() {
let store = useHeroStore(),
list = Vue.ref([]),
count = Vue.ref(0)
Vue.watch(()=>store.heroes,nv=>{
count.value = 0
list.value = nv.filter(item=>{
if(item.btnInfo.disabled){
count.value += item.strength
return true
}
})
},{deep:true})
return {
list,
count,
removeHero(item,idx){
store.heroes[item.id-1].btnInfo.text = '添加至队伍里'
store.heroes[item.id-1].btnInfo.disabled = false
},
sortStrength(){
list.value.sort((a,b)=>b.strength - a.strength)
},
}
},
};
// TODOEnd
9、万能合成台
这题的含金量还是比较高,考察了很多方面的知识点
这题我选择用了字符串来解
// state 辅助记录当前合成栏内容的全局变量
let state = [
['', '', ''],
['', '', ''],
['', '', '']
];
let targetItemName = ''; //辅助记录当前合成栏的可能目标合成物品每次 onPickItem 执行后,前端界面会根据此全局变量的值更改图标
/** 检查当前的合成配方是否能够合成某个物品。如果配方合法,返回一个合成的目标物品名,否则返回一个空字符串。
* @param {*} map 为一个 3*3 的二维数组,第一维为物品的每一横行,第二维为每一横行物品下的每个纵列
*/
function checkRecipe(map) {
// TODO:待补充代码
let rule = structuredClone(window.recipes)
//用字符串来玩这道题
let rMap = map.map(item=>{
return (item+'').replaceAll(',',' ').trim()
}),
rRule = {},
result = ''
for (let key in rule) {
rRule[key] = []
for (let idx in rule[key]) {
rRule[key][idx] = rule[key][idx].map(item=>(item+'').replaceAll(',',' ').trim())
}
}
for(let key in rRule){
for (const item of rRule[key]) {
let _itemStr = ''
//判断纵向是否拥有空位
if((rMap+'')[0]==','){
_itemStr = ','+item
}else if((rMap+'')[(rMap+'').length-1]==','){
_itemStr = item+','
}else{
_itemStr = item+''
}
if(_itemStr == rMap)result = key
}
}
return result
}
/** 更新 state 中的物品位置
* @param {string} name 为此次修改为的物品,可能为空字符串(通过右下角清空),也可能为物品
* @param {Array<Number>} pos 为一个两个元素的数字数组,分别指示物品的所在横行与所在纵列
*/
function onPickItem(name, pos) {
// TODO:待补充代码
state[pos[0]-1][pos[1]-1] = name
targetItemName = checkRecipe(state) || '';
}
10、账户验证
这题有个坑,最后清空了输入框的值依旧不给过,然后换了一种思路就可以了,上代码:
<!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/element-plus@2.3.7/index.css">
<script src="./js/vue3.global.js"></script>
<script src="./css/element-plus@2.3.7/index.full.js"></script>
<script type="importmap">
{
"imports":{
"vue-demi":"./js/index.mjs",
"vue":"./js/vue.esm-browser.prod.js",
"pinia":"./js/pinia.esm-browser.js"
}
}
</script>
<script src="./js/pinia.esm-browser.js" type="module"></script>
</head>
<body>
<!-- app根组件开始 -->
<div id="app">
<div class="header">
<img class="back-btn" src="images/arrow.png" />
<span id="main_title">使用手机号登录</span>
<span class="blank"></span>
</div>
<***ponent :is="showName"></***ponent>
</div>
<!-- app根组件结束 -->
<!-- phone组件开始 -->
<template id="phone">
<div>
<ul class="phone">
<span>输入手机号码</span>
<li>
<input type="text" v-model="phoneVal" autofocus id="numberInput" />
</li>
<li>
<input type="checkbox" v-model="isSure" name="" id="checkbox" />
<span>已阅读并同意
<a href="javascript:;">服务协议</a>
和
<a href="javascript:;">隐私保护指引</a>
</span>
</li>
<button id="btn" @click="nextStep">下一步</button>
</ul>
</div>
</template>
<!-- phone组件结束 -->
<!-- check组件开始 -->
<template id="check">
<ul class="number">
<span>输入短信验证码</span>
<li class="hassend">已向
<i>{{handlePhoneVal}}</i>
发送验证码
</li>
<li class="code-container">
<input type="number" class="code" min="0" max="9" required>
<input type="number" class="code" min="0" max="9" required>
<input type="number" class="code" min="0" max="9" required>
<input type="number" class="code" min="0" max="9" required>
<input type="number" class="code" min="0" max="9" required>
<input type="number" class="code" min="0" max="9" required>
</li>
<a href="javascript:;" id="resend" @click="resentCode">重新发送</a>
</ul>
</template>
<!-- check组件结束 -->
<!-- su***ess组件开始 -->
<template id="su***ess">
<div class="su***ess">
<ul>
<div>验证成功!</div>
<div>5s后将自动跳转</div>
</ul>
</div>
</template>
<!-- su***ess组件结束 -->
</body>
<script type="module">
import { createPinia, defineStore } from 'pinia'
const { createApp, reactive, toRefs,provide,inject,ref,watch } = Vue
const { ElNotification } = ElementPlus
const app = createApp({
setup() {
let data = reactive({
showName: "phone"
})
// TODO:补全代码实现目标需求
//定义全局通信数据池
const code = ref([])
const phoneVal = ref('')
const createCode = function(){ //随机生成二维码
let res = ''
function *_create(){
let count = 0
while(++count <= 6){
yield Math.floor(Math.random()*10)
}
}
for (const iterator of _create()) {
res+=iterator
}
return res
}
const handlePhone = num =>{
let res = ''
for(let idx in num){
if(idx>2 && idx<num.length-2){
res+='*'
}else{
res+=num[idx]
}
}
return res
}
//将通信数据派发渗透到子组件树
provide('code',code)
provide('phoneVal',phoneVal)
provide('createCode',createCode)
provide('data',data)
provide('handlePhone',handlePhone)
return {
...toRefs(data)
}
}
})
app.use(ElementPlus)
app.use(createPinia())
app.***ponent("phone", {
template: "#phone",
setup() {
// TODO:补全代码实现目标需求
let isSure = ref('')
let phoneVal = inject('phoneVal')
let code = inject('code')
let createCode = inject('createCode')
let data = inject('data')
//验证手机
function verifyPhone(num){
if(num.length!=11)return false
return ((num[0]==1) && num[1]==8)
}
return {
isSure,
phoneVal,
nextStep(){
if(!isSure.value)
return ElNotification({
title: '发送失败',
message: '请先阅读并同意下方协议',
type: 'error',
})
if(!verifyPhone(phoneVal.value))
return ElNotification({
title: '发送失败',
message: '无效的手机号码',
type: 'error',
})
code.value = createCode()
ElNotification({
title: '发送成功',
message: '您在验证码为'+code.value,
type: 'su***ess',
})
data.showName = 'check'
}
}
}
})
app.***ponent("check", {
template: "#check",
setup() {
// TODO:补全代码实现目标需求
let phoneVal = inject('phoneVal'),
handlePhoneVal = inject('handlePhone')(phoneVal.value),
data = inject('data'),
code = inject('code'),
createCode = inject('createCode'),
rVal = ''
setTimeout(()=>{ //将代码放入宏队列以此获取dom,用onMounted也行
let oCodeIptList = [...document.getElementsByClassName('code')]
oCodeIptList[0].focus() //第一个默认聚焦
oCodeIptList.map(item=>{
item.oninput=function(){
if(item.value){ //如果输入了值就聚焦下一个,否则聚焦上一个
item?.nextElementSibling && item?.nextElementSibling.focus()
}else{
item?.previousElementSibling && item?.previousElementSibling.focus()
}
rVal = (oCodeIptList.map(item=>item.value)+'').replaceAll(',','') //这里很关键,之前我用了这种方式之后,清空六个输入框的检测就给通过了
trackVal(rVal)
}
})
function trackVal(val){
if(val.length>=6){
if(val == code.value){
ElNotification({
title: '验证成功',
message: "欢迎回来",
type: 'su***ess',
})
data.showName = 'su***ess'
}else{
ElNotification({
title: '验证失败',
message: "您输入的验证码有误",
type: 'error',
})
;[...document.getElementsByClassName('code')].map(item=>item.value = '') //清空输入框
;[...document.getElementsByClassName('code')][0].focus() //重新聚焦第一个
}
}
}
})
return {
handlePhoneVal,
resentCode(){
code.value = createCode()
ElNotification({
title: '发送成功',
message: '您在验证码为'+code.value,
type: 'su***ess',
})
}
}
}
})
app.***ponent("su***ess", {
template: "#su***ess"
})
app.mount('#app')
</script>
</html>