Skip to content

15届蓝桥省赛

作者:江月迟迟
发表于:2024-12-10
字数统计:4411 字
预计阅读15分钟
css
.cars {
  position: absolute;
  z-index: 2;
  width: 600px;
  height: 600px;
  display: flex;
  flex-direction: column;  /* 排成列*/
  /* TODO: 请为下方属性填空,不要更改其他选择器里的代码 */
  flex-wrap: wrap; 
  align-content: space-between;
  justify-content: space-between;

}
js
  // TODO:待补充代码
        console.log(option);
        layoutOptions.forEach(item => item.classList.remove('active'))
        option.classList.add('active')
         // TODO:END
js
/**
 * @param {*} initialValue 初始值
 * @param {Array} sequence 由普通函数或 Promise 函数组成的数组
 * @return {Promise}
 */

const pipeline = (initialValue, sequence) => {
  // TODO: 待补充代码
  return sequence.reduce((acc, fn) => acc.then(fn), Promise.resolve(initialValue));
};
js
<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <title>多表单验证</title>
  <link rel="stylesheet" href="./css/style.css">
  <link rel="stylesheet" href="./css/element-plus.css">
  <script src="./lib/vue.global.prod.js"></script>
  <script src="./lib/index.full.js"></script>
</head>

<body>
  <div id="app">
    <div id="func">{{ submitForm }}</div>
    <el-tabs type="border-card" v-model="activeName">
      <el-tab-pane label="基本信息" name="user">
        <el-form id="form1" label-width="120px" v-model:model="form" ref="form1Ref" :rules="rules">
          <el-form-item label="姓名:" prop="name">
            <el-input v-model="form.name" id="input1" />
          </el-form-item>
          <el-form-item label="性别:" prop="sex"> 
            <el-radio-group v-model="form.sex" class="ml-4">
              <el-radio label="男" size="large" @click.prevent.native="onClickRadio('sex','男')">男</el-radio>
              <el-radio label="女" size="large" @click.prevent.native="onClickRadio('sex','女')">女</el-radio>
            </el-radio-group>
          </el-form-item>
          <el-form-item label="年龄:" prop="age">
            <el-input v-model="form.age" id="input3" />
          </el-form-item>
        </el-form>
      </el-tab-pane>
      <el-tab-pane label="附加信息" name="place">
        <el-form id="form2" label-width="200px" v-model:model="form" ref="form2Ref" :rules="rules">
          <el-form-item label="是否参加过编程比赛:" prop="isCompetition">
            <el-radio-group v-model="form.isCompetition" class="ml-4" id="input4">
              <el-radio label="1" size="large" @click.prevent.native="onClickRadio('isCompetition','1')">是</el-radio>
              <el-radio label="0" size="large" @click.prevent.native="onClickRadio('isCompetition','0')">否</el-radio>
            </el-radio-group>
          </el-form-item>
          <el-form-item label="是否有过创业经历:" prop="isEntrepreneurship">
            <el-radio-group v-model="form.isEntrepreneurship" class="ml-4" id="input5">
              <el-radio label="1" size="large"
                @click.prevent.native="onClickRadio('isEntrepreneurship','1')">是</el-radio>
              <el-radio label="0" size="large"
                @click.prevent.native="onClickRadio('isEntrepreneurship','0')">否</el-radio>
            </el-radio-group>
          </el-form-item>
          <el-form-item label="补充说明:" prop="footnote">
            <el-input type="textarea" style="width: 200px;" v-model="form.footnote" />
          </el-form-item>
        </el-form>
      </el-tab-pane>
    </el-tabs>

    <el-row>
      <el-button id="submit" type="primary" size="large" class="btn-submit" @click="submitForm">提交</el-button>
    </el-row>
  </div>

  <script>
    const { createApp, reactive, toRefs, ref, onMounted } = Vue;
    const { ElMessage } = ElementPlus

    const app = Vue.createApp({
      setup() {

        const activeName = ref('user')
        const onClickRadio = (key, val) => {
          form[key] = form[key] == val ? '' : val
        }
        const form = reactive({
          name: '',
          sex: '',
          age: '',
          isCompetition: '',
          isEntrepreneurship: '',
          footnote: ''
        })

        // TODO:待补充代码

        const validateName = (rule, value, callback) => {
                let testValue = value.replace(/[^\u4e00-\u9fa5]/g, '')
                console.log(value);
                if(testValue !== value) {
                  callback(new Error("只能输⼊汉字"));
                }
                else {
                  callback()
                }
          }

        const rules = reactive({
          name: [
            {
              required: true,
              message: '请输⼊姓名',
              trigger: 'blur'
            },
            {
              validator: validateName,
              trigger: 'blur'
            }
          ],
          sex: [
            {
              required: true,
              message: '请选择性别',
              trigger: 'change'
            }
          ],
          age: [
            {
              required: true,
              message: '请输⼊年龄',
              trigger: 'blur'
            }
          ],
          isCompetition: [
            {
              required: true,
              message: '请选择是否参加过编程⽐赛',
              trigger: 'change'
            }
          ],
          isEntrepreneurship: [
            {
              required: true,
              message: '请选择是否有过创业经历',
              trigger: 'change'
            }
          ]
        })

        const form1Ref = ref(null)
        const form2Ref = ref(null)
        var msg
        const submitForm = async () => {
          msg && msg.close()
          let res1 = await form1Ref.value.validate();
          let res2 = await form2Ref.value.validate()
          // console.log(res1, res2);
          if (res1 && res2) {
            msg = ElMessage({
              message: "提交成功",
              type: "success",
            });
          }
        }

        return {
          activeName,
          form,
          rules,
          form1Ref,
          form2Ref,
          submitForm,
          onClickRadio
        }
      }
    });

    app.use(ElementPlus).mount('#app');
  </script>
</body>

</html>
js
/**
 * 定义一个可重置的一次性函数
 * @param {func} fn 要作用的函数
 * @returns {object} {runOnce:func, reset:func } 
 */

let flag = false
let result = ''
let prevFunName = ''

function resetableOnce(fn) {
    // TODO: 待补充代码
    if (fn !== prevFunName) {
        flag = false
    }
    function runOnce(...args) {
       if (!flag) {
        flag = true
        result = fn(...args)
        return result
       } else {
        return result
       }
    }
    function reset() {
       flag = false
       result = ''
       return 
    }  
    // TODO: END
    return { runOnce, reset};
}
js
const fs = require('fs');
const path = require('path');

// 生成文件树
function generateTree(dirPath) {
  // TODO:待补充代码
  if (!dirPath) {
    return []
  }
  if (!isDir(dirPath)) {
    return []
  }
  // is Dir
  let result = []
  const fileInDir = fs.readdirSync(dirPath)
  // console.log(fileInDir);
  // console.log(fs.readdirSync(path.resolve(dirPath, fileInDir[1])));
  fileInDir.forEach((item, index) => {
    // dfs loading
    // not a dir
    result.push(dfs(item, dirPath))
  })
  return result                                                                          
}

function dfs(fileName, dirPath) {
  if (!isDir(path.resolve(dirPath, fileName))) {
    return { name: fileName }
  } else {
    // dfs
    // dirPath + fileName is Dir, need a itearate
    const childPath = path.resolve(dirPath, fileName)
    const fileInDir = fs.readdirSync(childPath)
    let result = {}
    fileInDir.forEach((item, index) => {
        result.name = fileName
        result.children ? result.children.push(dfs(item, childPath)) : result.children = [dfs(item, childPath)]
    })
    console.log(result);
    return result
  }
}

function isDir(dirPath) {
  return fs.statSync(dirPath).isDirectory()
}




// 根据数据生成 tree 命令
function generateDirectoryStructure(data, indent = "") {
  let result = "";
  if(!Array.isArray(data)) throw Error('返回的数据不是数组');
  for (let i = 0; i < data.length; i++) {
    const item = data[i];
    const name = item.name;
    const isLast = i === data.length - 1;

    result += `${indent}${isLast ? "└──" : "├──"} ${name}\n`;

    if (item.children) {
      const childIndent = indent + (isLast ? "    " : "│   ");
      result += generateDirectoryStructure(item.children, childIndent);
    }
  }

  return result;
}

// 读取指定文件夹,传递本题目文件夹
const directoryPath = __dirname;
const tree = generateTree(directoryPath);
const treem= generateDirectoryStructure(tree);
console.log(treem)

// 以下代码检测需要,请勿删除
module.exports = generateTree;
js
<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8" />
  <title>Github 明星项目统计</title>
  <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
  <link rel="stylesheet" type="text/css" href="css/style.css" />
  <script src="./lib/axios.js"></script>
  <script src="lib/vue.global.js"></script>
  <script src="lib/echarts.min.js"></script>
</head>
<body>
  <div id="app">
    <!-- 图表容器 -->
    <div id="chart" style="width: 100%; height: 500px;"></div>
    <div class="filters">
      <div>
        筛选语言
        <!-- TODO: 待补充代码 -->
        <select name="language" id="language" @change="changeHandle" v-model="language">
          <!-- <option value="All">All</option> -->
          <option :value="item" v-for="item in languages">{{ item }}</option>
        </select>
      </div>
      <div>展示第<input id="first" type="text" v-model="pageStart" @input="changeHandle">到第<input id="second" type="text"
        v-model="pageEnd" @input="changeHandle">位的项目</div>
    </div>
  </div>
</body>

<script>
  var xData;
  var yData;
  const app = Vue.createApp({
    setup() {
      // 定义响应式数据
      const chart = Vue.ref(null);
      const chartOptions = Vue.ref(null);
      const chartData = Vue.ref(null);
      xData = Vue.ref(null);
      yData = Vue.ref(null);
      const languages = Vue.ref(['All', 'JavaScript', 'TypeScript', 'Python', 'Shell', 'C++', 'C#', 'Go', 'Rust', 'Java']);
      const language = Vue.ref('All');
      const pageStart = Vue.ref(1);
      const pageEnd = Vue.ref(100);
      // 语言筛选改变时或页面数字输入框数字改变时的处理函数
      const changeHandle = () => {
        // TODO:待补充代码
        if (language.value === 'All') {
          console.log('1');
        }
        else {
          // JavaScript
          console.log(language.value);
          console.log(chartData.value);
          const temXData = []
          const temYData = []
          chartData.value.filter(item => {
            if (item.language === language.value) {
              console.log(item.name);
              temXData.push(item.name)
            }
          })
          xData.value = temXData.slice(pageStart.value - 1, pageEnd.value)
          chartData.value.filter(item => {
            if (item.language === language.value) {
              temYData.push(item.stars) 
            }
          })
          yData.value = temYData.slice(pageStart.value - 1, pageEnd.value)
        }
        console.log(xData.value);
        console.log(yData.value);
        initChart();
      };

      // 初始化图表
      const initChart = () => {
        chart.value = echarts.init(document.getElementById('chart'));
        chartOptions.value = {
          title: {
            text: 'Github 明星项目统计',
            x: 'center'
          },
          tooltip: {
            trigger: 'axis',
            axisPointer: {
              type: 'shadow',
              label: {
                show: true
              }
            }
          },
          xAxis: {
            data: xData.value,
          },
          yAxis: {
            type: 'value',
            label: 'star数量'
          },
          series: [
            {
              data: yData.value,
              type: 'bar',
            }
          ],
        };
        chart.value.setOption(chartOptions.value);
      };

      // 组件挂载时获取数据
      Vue.onMounted(() => {
        axios.get('./js/data.json').then(res => {
          chartData.value = res.data;
          let newData = chartData.value.slice(pageStart.value - 1, pageEnd.value);
          xData.value = chartData.value.map(item => item.name);
          yData.value = chartData.value.map(item => item.stars);
          console.log(xData.value);
          initChart();
        });
      });

      return {
        chart,
        chartOptions,
        chartData,
        xData,
        yData,
        languages,
        language,
        pageStart,
        pageEnd,
        initChart,
        changeHandle,
      };
    },
  });

  var vm = app.mount('#app');
</script>

</html>
js
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>小蓝驿站</title>
    <!-- 链接外部样式表 -->
    <link rel="stylesheet" href="css/style.css" />
    <!-- 引入 Vue.js 框架 -->
    <script src="lib/vue.global.js"></script>
  </head>

  <body>
    <div id="app">
      <!-- 邮箱顶部标题和操作按钮 -->
      <div class="email-header">
        <!-- 邮箱标题 -->
        <div class="email-header-logo">
          <h1 class="email-header-title">小蓝驿站</h1>
        </div>
        <!-- 邮箱操作按钮,包括撰写邮件、设置和退出 -->
        <div class="email-header-actions">
          <button class="email-header-button">撰写邮件</button>
          <button class="email-header-button">设置</button>
          <button class="email-header-button">退出</button>
        </div>
      </div>

      <div class="container">
        <!-- 邮箱侧边栏 -->
        <div class="email-sidebar">
          <!-- 邮箱文件夹列表 -->
          <ul class="folder-list">
            <li class="folder-list-item">收件箱</li>
            <li class="folder-list-item">草稿箱</li>
            <li class="folder-list-item">已发送</li>
            <li class="folder-list-item">已删除</li>
            <li class="folder-list-item">垃圾邮件</li>
            <li class="folder-list-item">广告邮件</li>
          </ul>
        </div>
        <div>
          <!-- 通讯录标题 -->
          <div class="contacts-title">通讯录</div>
          <!-- 添加联系人区块 -->
          <div class="add-contacts">
            <!-- 添加联系人标题 -->
            <div class="contacts-group-title">添加联系人</div>
            <!-- 添加联系人表单 -->
            <div class="add-contact">
              <!-- 联系人输入框,使用 Vue 的 v-model 进行双向数据绑定 -->
              <input
                class="add-contact-input"
                v-model="newContact"
                placeholder="新联系人名字"
              />
              <!-- 添加按钮,点击后触发 addContact 方法 -->
              <button class="add-contact-button" @click="addContact">
                添加
              </button>
            </div>
          </div>
          <!-- 联系人列表 -->
          <ul class="contacts-list">
            <!-- TODO:待补充代码 目标 1  -->
            <!-- 以 A 为例 start -->
            <li class="contacts-group" v-for="item in sortedContacts" :key="item">
              <!-- 字⺟分组渲染 DOM 结构-->
              <div class="contacts-group-title">{{ item.letter }}</div>
              <!-- 分组的 字⺟名称 -->
              <ul>
                <li class="contact-item" v-for="child in item.contacts" :key="child">
                  <!-- contact-item ⼈名渲染 dom 结构-->
                  <span class="contact-name">{{ child.name }}</span>
                  <button class="del-contact-button">删除</button>
                </li>
              </ul>
            </li>
            <!-- 以 A 为例 end -->
          </ul>
        </div>
      </div>
    </div>

    <script>
      // 从 Vue 对象中解构出 reactive、computed 和 ref 等方法
      const { reactive, computed, ref, onMounted } = Vue;
      // 定义 Vue 应用
      const app = {
        setup() {
          // 定义并初始化联系人列表
          let list = ref([]);
          onMounted(async () => {
            const res = await fetch("./data.json")
              .then((res) => res.json())
              .then((data) => data);
            list.value = res;
          });

          // 定义并初始化新联系人名字
          const newContact = ref("");

          // 定义计算属性,对联系人列表进行排序
          const sortedContacts = computed(() => {
            return list.value.sort((a, b) => a.letter.localeCompare(b.letter));
          });
          // 定义添加联系人的方法
          const addContact = () => {
            // TODO:待补充代码 目标 2
            console.log(sortedContacts.value);
            console.log(newContact.value[0].toUpperCase());
            console.log(sortedContacts.value.map(item => item.letter));
            let firstWord = newContact.value[0].toUpperCase()
            let position = sortedContacts.value.map(item => item.letter).indexOf(firstWord)
            if (position !== -1) {
                // 有,新增
                console.log('yes');
                sortedContacts.value[position].contacts.push({
                    name: newContact.value,
                })
                // sort一下
                // sortedContacts.value[position].contacts.sort((a,b) => {
                //     console.log(a.name);
                //     console.log(b.name);
                //     a.name.localeCompare(b.name)
                // })

            } else {
                // 没有,创建并新增
                console.log('no');
                sortedContacts.value.push({
                    letter: firstWord,
                    contacts: [
                        {
                            name: newContact.value
                        }
                    ]
                })
            }
            // TODO:END
            // 添加完成清空联系人输入框
            newContact.value = "";
          };

          // 返回应用所需的数据和方法
          return {
            list,
            newContact,
            sortedContacts,
            addContact,
          };
        },
      };

      // 创建并挂载 Vue 应用
      Vue.createApp(app).mount("#app");
    </script>
  </body>
</html>
js
window.onload = async ()=> {
    const MockUrl =`./js/data.json`;// 请求地址
    let data=[];// 存储请求后的数据
    // TODO:待补充代码,目标 1
    const response = await axios.get(MockUrl)
    data = response.data
    console.log(data);
    // TODO:END
    // 请求完成后调用下面的代码
    const newData = getData(data);
    showData(newData);
};

/**
 * 将同一天浏览的相同商品去重并作为数组返回
 * @param {Array} defaultData json 文件中读取到的原始数据
 * @returns 去重后的数据,数据结构与 defaultData 相同
 */
const removeDuplicates = defaultData => {
  let newData = [];
  // TODO:待补充代码,目标 2
  const hashMap = {}
  for(let item of defaultData) {
    // 压根没出现
    if (!hashMap[item.id]) {
      hashMap[item.id] = item.viewed_on
      newData.push(item)
    } else {
      // 出现过,判断是不是同一天,如果是同一天就不加进去
      if (hashMap[item.id].slice(0,10) !== item.viewed_on.slice(0, 10)) {
        newData.push(item)
      }
    }
  }
  console.log(newData);
  return newData;
}

/**
 * 将去重后的数据根据字段 viewed_on(格式化为 YYYY-MM-DD) 降序排序
 * @param {*} defaultData 去重后的数据
 * @returns 根据字段 viewed_on(格式化为 YYYY-MM-DD) 降序排序
 */
const sortByDate = defaultData => {
  let newData = [];
  // TODO:待补充代码,目标 3
  const temDate = defaultData.map(item => item.viewed_on)
  defaultData.forEach(item => {
    item.viewed_on1 = item.viewed_on.replace(/^(\d\d\d\d)-(\d\d)-(\d\d)T.*$/, `$1$2$3`)
  })
  // sort
  defaultData.sort((a, b) => {
    console.log('2024-03-23' - '2024-03-22');
    return parseInt(b.viewed_on1) - parseInt(a.viewed_on1)
  })
  defaultData.forEach(item => {
    delete item.viewed_on1
  })
  console.log(defaultData);
  newData = defaultData
  return newData;
}
/**
 * 将去重排序后的所有商品数据,作为一个对象存储并返回
 * @param {Array} defaultData 重后的所有商品数据
 * @returns 
 */
const transformStructure = defaultData => {
  let newData = {};
  // TODO:待补充代码,目标 4
  console.log(defaultData);
  defaultData.forEach(item => {
    const forMat = item.viewed_on.slice(0, 10)
    console.log(forMat);
    if (!newData[forMat]) {
      newData[forMat] = []
      newData[forMat].push(item)
    } else {
      newData[forMat].push(item)

    }
  })
  console.log(newData);
  return newData;
}
const getData = (defaultData) => {
  let newData = removeDuplicates(defaultData);
  let sortData = sortByDate(newData);
  let objData = transformStructure(sortData);
  return objData;
};
const showData = (data) => {
  let str = ``;
  for (let k in data) {
    str += `<h3>${k}</h3>`;
    data[k].forEach((goods) => {
      str += `<div class="container">
      	<div class="image"></div>
      	<div class="details">
      		<h4>${goods.name}</h4>
      		<p>${goods.description}</p>
      		<p class="buy">
      		  <span class="price">¥${goods.price}</span>
      		  <img src="./images/cart.svg" alt="" srcset="">
      		</p>
      	</div>
      </div>`;
    });
  }
  document.querySelector("#goodsList").innerHTML = str;
};
js
/**
 * @param {iterable} iterable 可迭代对象
 * @return {promise}
 */
function myRace(iterable) {
    // TODO:待补充代码  
    return new Promise((resolve, reject) => {
        // not a iterable
        if (iterable == null || typeof iterable[Symbol.iterator] !== 'function') {
            reject(new TypeError(`${typeof iterable} is not iterable`));
            return;
        } else {
            // is a iterable
            for (const item of iterable) {
                Promise.resolve(item).then(resolve, reject);
              }
        }
    })
 }


 // 测试⽤例 1
myRace([1,2]) //返回 Promise {<fulfilled>: 1}
// 测试⽤例 2
myRace('hello') // 返回 Promise {<fulfilled>: 'h'}
// 测试⽤例 3
let promise1 = new Promise((resolve, reject)=> {
reject(1)
})
let promise2 = new Promise((resolve, reject) =>{
setTimeout(()=>{
resolve(2)
},1000)
})
myRace([promise1, promise2]).then(res => {
console.log(res)
},reason=>{
console.log(reason) // 输出 1
})

// // 1 执⾏代码
// myRace(1)
// // 控制台报错输出
// // Uncaught (in promise) TypeError: number is not iterable




// 以下代码不需要修改
const random = Math.random();
const output = document.getElementById("output"); // 下载输出
const startButton = document.getElementById("startButton"); // 下载按钮
let isDownloading = false; //是否已经开始下载
// 定义不同下载源的下载任务,链接仅为函数模拟使用,不存在联网情况 
const downloadTasks = [
    ()=> executeTask("quick", "https://quick.lanqiao.com/"),
    ()=>executeTask("learn", "https://learn.lanqiaoshiyan.com/"),
    ()=> executeTask("study", "https:/study.lanqiao.com/"),
 ];
// 下载进度
function simulateDownload(source, httpLink, result) {
    output.textContent = `The current download source ${source},npm http fetch GET 200  ${httpLink}/\n`;
    output.textContent += "Downloading packages...\n";

    setTimeout(() => {
        output.textContent += "Fetching package 1/5...\n";
    });

    setTimeout(() => {
        output.textContent += "Fetching package 2/5...\n";
    }, 500);

    setTimeout(() => {
        output.textContent += "Fetching package 3/5...\n";
    }, 1000);

    setTimeout(() => {
        output.textContent += "Fetching package 4/5...\n";
    },1500);

    setTimeout(() => {
        if (result == "complete") {
            output.textContent += "Fetching package 5/5...\n";
            output.textContent += `Download ${result}!\n`;
        } else {
            output.textContent += "Fetching package 4/5...\n";
            output.textContent += `Download ${result}!\n`;
        }
    }, 2000);
}

// 点击开始匹配最快的下载源进行下载,并拿到下载成功失败的结果
startButton.addEventListener("click", () => {
    startButton.style.display = 'none';
    myRace(downloadTasks).then(
        ({ source, httpLink }) => {
            isDownloading = true;
            simulateDownload(source, httpLink, "complete");
        },
        ({ source, httpLink }) => {
            isDownloading = true;
            simulateDownload(source, httpLink, "fail");
        }
    );

});

// 匹配最快的下载源进行下载
function executeTask(source, httpLink) {
    return new Promise((resolve, reject) => {
        //executionTime 定义不同下载源的下载速度
        const executionTime = Math.random() * 300 ;
        // 设置需要下载的进度 100%
        let downloadPercentage = 100;
        const decreaseAmount = 100 / executionTime;

        if (random < 0.5) {
            setTimeout(() => {
                reject({ source, httpLink }); //下载失败
            }, executionTime);
        }
        interval = setInterval(() => {
            if (isDownloading) return clearInterval(interval);
            downloadPercentage -= decreaseAmount;
            if (downloadPercentage <= 0) {
                clearInterval(interval);
                resolve({ source, httpLink }) //下载成功
            }

        }, 10);
    });
}