个人分享小站，包含但不限于各种教程，资源分享，欢迎来看
前言[card title="什么是校园网……" color="info"]校园网是指在学校范围内建立的计算机网络系统，旨在为师生、教职员工提供高效、便捷的互联网服务和资源共享。校园网通常覆盖校园内的各个主要区域，包括教学楼、图书馆、宿舍区和科研楼等，形成一个高速稳定的网络环境。通过校园网，学生和教师可以轻松访问各类在线教育资源、电子图书馆、教学平台以及校内信息系统，极大地提升了学习和科研的效率。同时，校园网也支持各种应用，如在线课程、远程教学、学术交流和校园活动信息发布等，促进了校园内外的沟通与合作。此外，校园网的管理通常由学校的网络中心或信息技术部门负责，确保网络安全、数据保护和用户隐私。同时，许多校园网还提供无线网络覆盖，让师生可以在校园内随时随地接入网络，体验更灵活的学习和工作方式。总之，校园网作为现代校园信息化建设的重要组成部分，不仅丰富了校园生活，还推动了教育的数字化转型，为师生创造了一个更加智能、便捷的学习环境。[/card]正文在我们的光纤实验课中，发现其网址是一个ip，根据其业务特性，应该是在校园内网运行的，所以尝试连接校园网ping了一下网址ip 显而易见，直接连接校园网进就欧克了基本操作首先连接重庆移通学院的校园网，有线无线都可，不需要其具有宽带账号，也就是上网功能在浏览器输入以下网址（5GSPN网络） http://172.16.35.250/sw/spn 使用学号登陆即可当我们登陆进去，可能会出现这样的情况 解决方法很简单打开我们的开发者工具 打开之后调整窗口的比例即可，（快捷键，键盘的F12）调整完毕之后关闭即可
GetQzonehistory(获取qq发布的历史说说)[button color="info" url="https://github.com/LibraHp/GetQzonehistory" outline="default" target="_blank"]本文转载自此处[/button]免责声明【必读】本工具仅供学习和技术研究使用，不得用于任何商业或非法行为，否则后果自负。本工具的作者不对本工具的安全性、完整性、可靠性、有效性、正确性或适用性做任何明示或暗示的保证，也不对本工具的使用或滥用造成的任何直接或间接的损失、责任、索赔、要求或诉讼承担任何责任。本工具的作者保留随时修改、更新、删除或终止本工具的权利，无需事先通知或承担任何义务。本工具的使用者应遵守相关法律法规，尊重QQ的版权和隐私，不得侵犯QQ或其他第三方的合法权益，不得从事任何违法或不道德的行为。本工具的使用者在下载、安装、运行或使用本工具时，即表示已阅读并同意本免责声明。如有异议，请立即停止使用本工具，并删除所有相关文件。该项目通过获取QQ空间的历史消息列表来获取该账号下发布的所有说说（当然消息列表中没有的就获取不到，例如一些仅自己可见的说说）B站有详细食用教程主要实现还是通过模拟登录QQ空间来获取历史消息列表，然后进行数据分析，最后将爬取的说说存放到/resource/result目录下由于对python编程还不是很熟悉，所以代码有很多疏漏，可以通过自己的想法来完善代码目录结构project/ ├── resource/ # 资源目录 │ ├── config/ # 配置目录，文件保存位置配置 │ │ └── config.ini │ ├── result/ # 导出结果的目录，格式为“你的qq.xlsx” │ │ ├── ... │ │ └── ... │ ├── temp/ # 缓存目录 │ │ ├── ... │ │ └── ... │ ├── user/ # 用户信息 │ │ ├── ... │ │ └── ... ├── util/ # 单元工具目录 │ ├── ConfigUtil.py # 读取配置 │ ├── GetAllMomentsUtil.py # 获取未删除的所有说说 │ ├── LoginUtil.py # 登录相关 │ ├── RequestUtil.py # 请求数据相关 │ └── ToolsUtil.py # 工具 ├── main.py # 主程序入口 ├── fetch_all_message.py # 主程序入口 ├── README.md # 项目说明文件 ├── requirements.txt # 依赖项列表 └── LICENSE # 许可证文件安装使用虚拟环境（推荐）# 克隆储存库 git clone https://github.com/LibraHp/GetQzonehistory.git # 打开目录 cd GetQzonehistory # 创建名为 myenv 的虚拟环境 python -m venv myenv # 激活虚拟环境。在终端或命令提示符中运行以下命令： # 对于 Windows： myenv\Scripts\activate # 对于 macOS/Linux： source myenv/bin/activate # 安装依赖 pip install -i https://mirrors.aliyun.com/pypi/simple/ -r requirements.txt # 运行脚本 python main.py使用本机环境（不推荐）# 克隆储存库 git clone https://github.com/LibraHp/GetQzonehistory.git # 打开目录 cd GetQzonehistory # 安装依赖 pip install -i https://mirrors.aliyun.com/pypi/simple/ -r requirements.txt # 运行脚本 python main.py参考登录方法参考自python-QQ空间扫码登录懒人使用方法首先下载我们的程序[button color="success" url="https://wwby.lanzouo.com/irk1R2elf5kd" outline="default" target="_blank"]点击下载密码1b6f[/button] 解压运行软件，扫码登录 Github作者呢，也是考虑的非常周到，编译了windows电脑的exe版本以及mac的运行版本登录扫码登录后，程序自动获取我们的历史数据 [photos] [/photos]没了，开始欣赏黑历史这个项目的作者也是非常的贴心，小白教程[BiliVideo][/BiliVideo]
概述Docker 容器的部署有一种在手机上装 App 的感觉，但 Docker 容器并不会像手机 App 那样会自动更新，而如果我们需要更新容器一般需要以下四个步骤：停止容器： docker stop 删除容器： docker rm 更新镜像： docker pull 启动容器： docker run 停止容器这个步骤可以在删除容器时使用 -f 参数来代替，即使这样还是需要三个步骤。如果部署了大量的容器需要更新使用这种传统的方式工作量是巨大的。Watchtower[card title="介绍" color="info"]Watchtower 是一款实现 自动化更新 Docker 镜像 与容器的实用工具，它本身也是一个 Docker 镜像，主要用来监控运行中的 Docker 容器的镜像是否需要更新。当 Watchtower 检测到容器的镜像有更新时，它会发送 SIGTERM 信号优雅地结束正在运行的容器，然后根据设定的参数自动重新启动容器，包括使用相同的参数和配置。这个过程无需用户介入，可以自动完成，从而实现 Docker 容器的自动更新。Watchtower 的工作方式是定期轮询 Docker 守护进程，检查容器的镜像是否有新的版本可用。如果有新版本，Watchtower 将自动拉取新镜像，并根据需要重启容器。这个工具对于希望保持容器始终运行最新镜像的用户来说非常有用，特别是在需要持续集成和持续部署的环境中。[/card]官网地址一、基本使用1.更新宿主机的所有容器使用以下命令，更新宿主机的所有容器，也包括 Watch­tower 本身docker run -d \ --name watchtower \ --volume /var/run/docker.sock:/var/run/docker.sock \ containrrr/watchtower2.指定某个容器进行监视如果指向监视某一个容器进行自定更新，则在上述命令后面加上容器名即可docker run -d \ --name watchtower \ -v /var/run/docker.sock:/var/run/docker.sock \ containrrr/watchtower \ 容器名字3.更新容器的频率Watchtower 默认情况下 24 小时会检查一次镜像更新。设置 --interval 选项更新时间，默认单位秒。docker run -d \ --name watchtower \ -v /var/run/docker.sock:/var/run/docker.sock \ containrrr/watchtower \ --interval 6当然，也可以使用--schedule选项， 设定定时更新任务，定时任务为6 字段来表示执行时间，第一个字段表示秒。docker run -d \ --name watchtower \ -v /var/run/docker.sock:/var/run/docker.sock \ containrrr/watchtower \ --schedule "0 30 20 * * 5"4.自定清理旧镜像可以使用--cleanup选项，这样每次更新都会把旧的镜像清理掉。docker run -d \ --name watchtower \ -v /var/run/docker.sock:/var/run/docker.sock \ containrrr/watchtower \ --cleanup用于清理无用的Docker卷。它会删除所有没有关联到任何容器的卷，以释放磁盘空间。当然你手动也没问题5.配置更新频率Watchtower 默认每 24 小时轮询一次,可以使用以下参数配置更新的频率.--interval,-i配置更新周期,默认300秒.--schedule,-s配置定时更新,使用Cron表达式,例如"0 0 1 *".即每天凌晨1点更新.docker run -d \ --name watchtower \ --restart always \ -v /var/run/docker.sock:/var/run/docker.sock \ containrrr/watchtower \ --cleanup \ -i 7200每两小时更新一次，并且清理旧镜像docker run -d \ --name watchtower \ --restart always \ -e TZ=Asia/Shanghai \ -v /var/run/docker.sock:/var/run/docker.sock \ containrrr/watchtower \ --cleanup \ -s "0 0 3 * * *"每天凌晨3点更新6.手动更新使用手动更新的方式,运行一次Watch­tower容器来更新所需的容器,更新后会自动删除本次运行的Watch­tower容器.只需要加上--rm和--run-once参数即可.同时也可以配合以上指定容器或指定排除容器的参数来使用.更新所有容器docker run --rm \ -v /var/run/docker.sock:/var/run/docker.sock \ containrrr/watchtower \ --cleanup \ --run-once更新指定容器docker run --rm \ -v /var/run/docker.sock:/var/run/docker.sock \ containrrr/watchtower \ --cleanup \ --run-once \ nginx redis
使用Keil uvision 5新建一个项目的操作[video src="https://qny.ie.mba/bandicam%202024-09-25%2020-17-16-134.mp4" loop="loop" poster="" height="" width=""]
一个重庆高校在线开放课程平台工具
[card title="info" color="danger"]🥁 We don't need no education🎹 We don't need no thought control🎸 No dark sarcasm in the classroom🎙️ Teacher, leave those kids alone[/card]使用方法windows版本与macos版本下载地址 [file url="https://wwz.lanzouo.com/b007snaq3e"]密码:ht1x[/file]附小鱼重庆高校版本 小鱼官网帮助下载解压缩文件，运行程序输入账号密码登录，勾选课程点击右上角f**k 功能提醒[event finish='true']视频与PPT资源[/event][event finish='false']测验，答题[/event]常见问题我的用户名和密码没错，但我不能登录?这种情况可能的原因是，程序的登录请求被服务器拒绝。这种情况下，你需要在浏览器中打开重庆高校在线课程平台，手动完成一次登录，然后回到程序中，再尝试重新登录。跳过任务花费的时间特别长，这是为什么?这是因为重庆高校在线课程平台服务器的管控策略。短时间跳过太多任务，你可能会遭到网站临时屏蔽。屏蔽不会持续太久，不到一分钟就会解除。但为了保证所有任务都能成功跳过，程序设置跳过每个任务之间都会间隔一段时间，具体是30秒。项目原文地址[button color="info" url="https://github.com/Fatpandac/fuck_cqooc" outline="default" target="_blank"]Github[/button]
[card title="Loading..." color="danger"]此模板已经失效了，正在撰写新文章[/card] 对接网址 点击跳转 邀请码lastdance遇到问题可有偿支持[quote color="info"]> 搭建测试环境：宝塔 PHP7.4 MySQL8.0[/quote]一、宝塔添加网站，创建数据库二、点开网站设置，设置伪静态location / { try_files $uri $uri/ $uri.php$is_args$args; }三、进入网站目录上传解压源代码源码回复下载[hide][file url="https://wwz.lanzouo.com/iNdXA1z7i97i"]蓝奏云下载[/file][/hide]修改config并导入数据库先去目录里面修改数据库的相关配置cinfig/config.php [quote color="info"]导入源码里的数据库文件[/quote] [progress value="90" color="bg-info"] [/progress]四、进入网站首页[quote color="info"]默认账号密码123 管理密码1[/quote] 目前已知源码易支付充值回调有问题，网站开启验证码无法注册等问题其余不知道 :@(脸红)，总之源码还有很多不完善的地方，自己到手改改就行
蓝桥杯十五届省赛Web应用开发题目答案解析
[quote color="info"]> 本文转自 赵阿卷 [/quote]1.智能停车系统 ⭐️考点： flex 布局解题答案：.cars { position: absolute; z-index: 2; display: flex; width: 600px; height: 600px; flex-direction: column; /* TODO: 请在下方编写题目代码，不要更改其他选择器里的代码 */ flex-wrap: wrap; align-content:space-between; justify-content:space-between; }2.分享点滴 ⭐️考察：对象的遍历，字符串基本操作答案1：function appendParamsToURL(url, params) { // 创建一个空字符串来存储参数字符串 let str = ""; // 遍历参数对象中的每个键 for (const key in params) { // 将键值对追加到字符串中 str += `${key}=${params[key]}&`; } // 移除字符串末尾的 "&" 符号 str = str.slice(0, -1); // 判断是否原始 URL 已包含查询字符串（通过是否包含 "?" 符号来判断） // 如果已包含查询字符串，则设置 sym 变量为 "&"，用于以 "&" 作为分隔符追加参数 // 否则，设置 sym 变量为 "?"，作为查询字符串的起始符号 let sym = url.includes("?") ? "&" : "?"; // 连接原始 URL、sym 符号和参数字符串，并返回最终的 URL return `${url}${sym}${str}`; }答案2：function appendParamsToURL(url, params) { // 使用 Object.entries() 获取参数对象的所有键值对并按照规则拼接 const paramArray = Object.entries(params).map( ([key, value]) => `${key}=${value}` ); // 使用join方法拼接参数字符串 const paramString = paramArray.join("&"); // 判断URL中是否已包含参数 let sym = url.includes("?") ? "&" : "?"; // 返回拼接后的URL return `${url}${sym}${paramString}`; }3. 布局切换 ⭐️考察 DOM 操作、class 类名操作 option.addEventListener('click', function () { for (const otherOption of layoutOptions) { // 移除其他选项的 active 类 otherOption.classList.remove('active'); } // TODO：待补充代码 this.classList.add('active'); // 为当前选项添加active类 }4. 产品 360 度展示 ⭐️⭐️考察：Promise、循环答案1：const pipeline = async (initialValue, sequence) => { let res = initialValue; for (const fn of sequence) { res = await fn(res); } return res; };答案2：const pipeline = (initialValue, sequence) => { let res = Promise.resolve(initialValue); for (const fn of sequence) { res = res.then((result) => fn(result)); } return res; };5. 多表单验证 ⭐️考察element-plus组件的使用const validateName = (rule, value, callback) => { if (value === "") { callback(new Error("请输入姓名")); } else { const reg = /[^\u4e00-\u9fa5]/g; if (reg.test(value)) { callback(new Error("只能输入汉字")); } callback(); } }; // TODO-3：书写表单校验规则，并绑定到对应表单上 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" }, ], });6. 找回连接的奇幻之旅 ⭐️⭐️⭐️考察：函数封装、闭包function resetableOnce(fn) { let done = false; // 标记函数是否已执行 let result; // 保存函数执行的结果 /** * 保证只执行一次的函数 * @returns {Any} 返回函数fn的执行结果 */ function runOnce() { if (!done) { // 如果之前没有执行过，则执行函数fn，并保存结果 result = fn.apply(this, arguments); done = true; // 标记为已完成，确保之后不再执行 } // 返回之前执行的结果 return result; } /** * 重置函数的执行状态 */ function reset() { done = false; // 重置done为false，允许函数再次执行 } // 返回控制对象 return { runOnce, reset }; }7. 悠然画境 ⭐️⭐️考察数组操作、字符串操作function generateAndDisplayImages(imageCount, selectedText) { // TODO：待补充代码 根据数量和用户输入在页面上生成图片并显示到 .right-panel 元素中 let count = 0; artDataArray.forEach((el) => { let tags = el.tags.split("、"); tags.forEach((tag) => { if (selectedText.includes(tag)) { count++; } }); el["count"] = count; count = 0; }); artDataArray.sort((a, b) => { return b.count - a.count; // 从小到大 -> a.age - b.age }); let b = artDataArray.slice(0, imageCount); return b; }8. 简易 JSX 解析器 ⭐️⭐️考察 dom 操作、字符串方法/** * 将驼峰式命名转换为短横线命名 * @param {string} str - 驼峰式命名的字符串 * @returns {string} - 转换后的短横线命名字符串 */ function camelToDash(str) { let result = ""; let hasUppercase = false; // 标记字符串中是否包含大写字母 for (let i = 0; i < str.length; i++) { let char = str.charAt(i); // 检查当前字符是否为大写字母 if (char === char.toUpperCase()) { hasUppercase = true; if (i > 0) { result += "-"; // 在大写字母前添加短横线 } result += char.toLowerCase(); // 将大写字母转换为小写字母并添加到结果中 } else { result += char; // 如果不是大写字母，直接添加到结果中 } } // 如果字符串中没有大写字母，则直接返回原字符串 if (!hasUppercase) { return str; } return result; } const jsx = (type, config) => { /* TODO: 请完善 jsx 函数的代码实现 */ const dom = document.createElement(type); for (let key in config) { const prop = config[key]; if (key === "style") { // 处理样式 let styleStr = Object.entries(prop) .map((item) => { return `${camelToDash(item[0])}:${item[1]}`; }) .join(";"); dom.setAttribute("style", styleStr); } else if (typeof prop === "function") { dom[key] = prop; } else if (key === "children") { // 处理 children if (typeof prop === "string") { dom.appendChild(document.createTextNode(prop)); } else { prop.forEach((child) => typeof child === "string" ? dom.appendChild(document.createTextNode(child)) : dom.appendChild(child) ); } } else { // 处理其他属性 dom.setAttribute(key, prop); } } return dom; };9. tree 命令助手 ⭐️⭐️⭐️考察 fs、递归函数function generateTree(dirPath) { // 读取目录下的所有文件和文件夹 const files = fs.readdirSync(dirPath); const tree = []; files.forEach(file => { const filePath = path.join(dirPath, file); const isDirectory = fs.statSync(filePath).isDirectory(); if (isDirectory) { // 如果是目录，则递归生成子目录的文件树 const subtree = generateTree(filePath); tree.push({ name: file, children: subtree }); } else { // 如果是文件，则直接添加到文件树 tree.push({ name: file }); } }); return tree; }10. Github 明星项目统计 ⭐️⭐️⭐️考察 vue3 v-for、Echarts 数据处理 {{language}} 11. 小蓝驿站 ⭐️⭐️⭐️考察 vue3 v-for、ref、数据处理// 目标 1 0" class="contacts-group-title"> {{ group.letter }} {{ contact.name }} 删除 12. 商品浏览足迹 ⭐️⭐️⭐️考察 axios 请求、数据处理window.onload = async ()=> { const res = await axios("./js/data.json"); const newData = getData(res.data); showData(newData); }; /** * 将同一天浏览的相同商品去重并作为数组返回 * @param {Array} defaultData json 文件中读取到的原始数据 * @returns 去重后的数据，数据结构与 defaultData 相同 */ const removeDuplicates = defaultData => { let newData = []; // TODO：在下面补充代码，最终完成该函数封装 defaultData.forEach((defaultGoods) => { const defaultDate = new Date(defaultGoods.viewed_on); const dD = `${defaultDate.getFullYear()}-${ defaultDate.getMonth() + 1 }-${defaultDate.getDate()}`; defaultGoods.date = dD; let hadThisGoods = false; newData.forEach((tmpGoods) => { const tmpDate = new Date(tmpGoods.viewed_on); const tD = `${tmpDate.getFullYear()}-${ tmpDate.getMonth() + 1 }-${tmpDate.getDate()}`; if (tmpGoods.id == defaultGoods.id && tD == dD) { hadThisGoods = true; } }); if (!hadThisGoods) { newData.push(defaultGoods); } }); return newData; } /** * 将去重后的数据根据字段 viewed_on（格式化为 YYYY-MM-DD） 降序排序 * @param {*} defaultData 去重后的数据 * @returns 根据字段 viewed_on（格式化为 YYYY-MM-DD） 降序排序 */ const sortByDate = defaultData => { let newData = []; // TODO：在下面补充代码，最终完成该函数封装 function sortByProperty(property, asc) { return function (value1, value2) { let a = new Date(value1[property]); let b = new Date(value2[property]); // 默认升序 if (asc == undefined) { return a - b; } else { return asc ? a - b : b - a; } }; } newData = defaultData.sort(sortByProperty("date", false)); return newData; } /** * 将去重排序后的所有商品数据，作为一个对象存储并返回， * 该对象的所有 `key` 为浏览商品的当天日期（即，字段 viewed_on 格式化为 YYYY-MM-DD）， * `value` 为当天浏览的所有商品（以数组形式表现）。 * @param {Array} defaultData 重后的所有商品数据 * @returns */ const transformStructure = defaultData => { let newData = {}; // TODO：在下面补充代码，最终完成该函数封装 // 月份和日期 不足10的前面补0 defaultData.forEach(item=>{ let date=new Date(item.date) ; let y = date.getFullYear() let m = date.getMonth()+1 m=m<10?'0'+m:m let d = date.getDate(); d=d<10?'0'+d:d item.date=`${y}-${m}-${d}`; }) newData = defaultData.reduce((aD, item) => { console.log(item); if (!aD[item.date]) { aD[item.date] = []; aD[item.date].push(item); } else { if (!aD[item.date].includes(item.date)) { aD[item.date].push(item); } } return aD; }, {}); return newData; }13. 扫雷游戏 ⭐️⭐️⭐️⭐️考察二维数组操作、递归function mineSweeperAlgorithms(arr, { row, col }) { if (flagData[row][col]) return; flagData[row][col] = true; const { positionWithoutMineArr, count } = getAroundAndCount(arr, { row, col, }); if (count == 0) { // 如果当前格子周围没有地雷，递归执行扫雷算法 positionWithoutMineArr.forEach((around) => { mineSweeperAlgorithms(arr, around); }); } }14.NPM Download Simulator ⭐️⭐️⭐️⭐️考察：获取数据类型、 promise.racefunction myRace(iterable) { return new Promise((resolve, reject) => { if (!(Symbol.iterator in Object(iterable))) { reject( new TypeError( `${Object.prototype.toString .call({ iterable }) .slice(-8, -1) .toLocaleLowerCase()} is not iterable` ) ); return; } const promises = Array.from(iterable); let resolvedOrRejected = false; for (const promise of promises) { Promise.resolve(promise).then( (value) => { if (!resolvedOrRejected) { resolvedOrRejected = true; resolve(value); } }, (reason) => { if (!resolvedOrRejected) { resolvedOrRejected = true; reject(reason); } } ); } }); }