{"meta":{"title":"CCR39のLazyNest","subtitle":"QAQ","description":"交流学习用","author":"ccr39","url":"http://ccr39.github.io"},"pages":[{"title":"client","date":"2018-12-20T15:13:35.000Z","updated":"2021-11-09T14:13:18.000Z","comments":false,"path":"client/index.html","permalink":"http://ccr39.github.io/client/","excerpt":"","keywords":null,"text":"直接下载 or 扫码下载:","raw":null,"content":null},{"title":"bangumi","date":"2019-02-10T13:32:48.000Z","updated":"2023-01-20T12:20:52.575Z","comments":false,"path":"bangumi/index.html","permalink":"http://ccr39.github.io/bangumi/","excerpt":"","keywords":null,"text":"","raw":null,"content":null},{"title":"comment","date":"2018-12-20T15:13:48.000Z","updated":"2024-12-13T05:58:37.503Z","comments":true,"path":"comment/index.html","permalink":"http://ccr39.github.io/comment/","excerpt":"","keywords":null,"text":"念两句诗 前方还有很长的路要走,我们都加油吧,一言为定。 ——《CLANNAD》 import { init } from 'https://unpkg.com/@waline/client@v2/dist/waline.mjs'; init({ el: '#waline', serverURL: 'https://waline-ccr39.netlify.app/.netlify/functions/comment', reaction: [ 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_heart_eyes.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_joy.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_consider.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_sob.png', ], emoji: [ '//unpkg.com/@waline/emojis@1.1.0/bilibili', '//unpkg.com/@waline/emojis@1.1.0/weibo', '//unpkg.com/@waline/emojis@1.1.0/qq', ] });","raw":null,"content":null},{"title":"links","date":"2018-12-19T15:11:06.000Z","updated":"2023-01-07T03:52:52.178Z","comments":true,"path":"links/index.html","permalink":"http://ccr39.github.io/links/","excerpt":"","keywords":null,"text":"","raw":null,"content":null},{"title":"about","date":"2018-12-12T14:14:36.000Z","updated":"2023-01-07T02:17:57.992Z","comments":false,"path":"about/index.html","permalink":"http://ccr39.github.io/about/","excerpt":"","keywords":null,"text":"[CCR39のLazyNest] 与  CCR39  ( ccr ミク ) 对话中... bot_ui_ini()","raw":null,"content":null},{"title":"donate","date":"2018-12-20T15:13:05.000Z","updated":"2023-01-07T02:19:11.355Z","comments":false,"path":"donate/index.html","permalink":"http://ccr39.github.io/donate/","excerpt":"","keywords":null,"text":"","raw":null,"content":null},{"title":"lab","date":"2019-01-05T13:47:59.000Z","updated":"2021-11-09T14:13:18.000Z","comments":false,"path":"lab/index.html","permalink":"http://ccr39.github.io/lab/","excerpt":"","keywords":null,"text":"sakura主题balabala","raw":null,"content":null},{"title":"music","date":"2018-12-20T15:14:28.000Z","updated":"2023-04-01T14:19:57.703Z","comments":false,"path":"music/index.html","permalink":"http://ccr39.github.io/music/","excerpt":"","keywords":null,"text":"","raw":null,"content":null},{"title":"rss","date":"2018-12-20T15:09:03.000Z","updated":"2022-12-09T13:40:31.610Z","comments":true,"path":"rss/index.html","permalink":"http://ccr39.github.io/rss/","excerpt":"","keywords":null,"text":"","raw":null,"content":null},{"title":"tags","date":"2018-12-12T14:14:16.000Z","updated":"2023-01-07T02:19:57.757Z","comments":true,"path":"tags/index.html","permalink":"http://ccr39.github.io/tags/","excerpt":"","keywords":null,"text":"","raw":null,"content":null},{"title":"theme-sakura","date":"2019-01-04T14:53:25.000Z","updated":"2023-01-07T02:20:26.877Z","comments":false,"path":"theme-sakura/index.html","permalink":"http://ccr39.github.io/theme-sakura/","excerpt":"","keywords":null,"text":"Hexo主题Sakura修改自WordPress主题Sakura,感谢原作者Mashiro","raw":null,"content":null},{"title":"video","date":"2022-12-09T16:00:00.000Z","updated":"2022-12-10T14:05:37.014Z","comments":false,"path":"video/index.html","permalink":"http://ccr39.github.io/video/","excerpt":"","keywords":null,"text":"var videos = [ { img: 'https://lain.bgm.tv/pic/cover/l/0e/1e/218971_2y351.jpg', title: '朝花夕誓——于离别之朝束起约定之花', status: '已追完', progress: 100, jp: 'さよならの朝に約束の花をかざろう', time: '放送时间: 2018-02-24 SUN.', desc: ' 住在远离尘嚣的土地,一边将每天的事情编织成名为希比欧的布,一边静静生活的伊欧夫人民。在15岁左右外表就停止成长,拥有数百年寿命的他们,被称为“离别的一族”,并被视为活着的传说。没有双亲的伊欧夫少女玛奇亚,过着被伙伴包围的平稳日子,却总感觉“孤身一人”。他们的这种日常,一瞬间就崩溃消失。追求伊欧夫的长寿之血,梅萨蒂军乘坐着名为雷纳特的古代兽发动了进攻。在绝望与混乱之中,伊欧夫的第一美女蕾莉亚被梅萨蒂带走,而玛奇亚暗恋的少年克里姆也失踪了。玛奇亚虽然总算逃脱了,却失去了伙伴和归去之地……。' }, { img : 'https://lain.bgm.tv/pic/cover/l/0e/1e/218971_2y351.jpg', title: '朝花夕誓——于离别之朝束起约定之花', status: '已追完', progress: 100, jp: 'さよならの朝に約束の花をかざろう', time: '2018-02-24 SUN.', desc: ' 住在远离尘嚣的土地,一边将每天的事情编织成名为希比欧的布,一边静静生活的伊欧夫人民。在15岁左右外表就停止成长,拥有数百年寿命的他们,被称为“离别的一族”,并被视为活着的传说。没有双亲的伊欧夫少女玛奇亚,过着被伙伴包围的平稳日子,却总感觉“孤身一人”。他们的这种日常,一瞬间就崩溃消失。追求伊欧夫的长寿之血,梅萨蒂军乘坐着名为雷纳特的古代兽发动了进攻。在绝望与混乱之中,伊欧夫的第一美女蕾莉亚被梅萨蒂带走,而玛奇亚暗恋的少年克里姆也失踪了。玛奇亚虽然总算逃脱了,却失去了伙伴和归去之地……。' } ] .should-ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:95%;}.should-ellipsis-full{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:100%;}.should-ellipsis i{position:absolute;right:24px;}.grey-text{color:#9e9e9e !important}.grey-text.text-darken-4{color:#212121 !important}html{line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}img{border-style:none}progress{display:inline-block;vertical-align:baseline}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}html{-webkit-box-sizing:border-box;box-sizing:border-box}*,*:before,*:after{-webkit-box-sizing:inherit;box-sizing:inherit}ul:not(.browser-default){padding-left:0;list-style-type:none}ul:not(.browser-default)>li{list-style-type:none}.card{-webkit-box-shadow:0 2px 2px 0 rgba(0,0,0,0.14),0 3px 1px -2px rgba(0,0,0,0.12),0 1px 5px 0 rgba(0,0,0,0.2);box-shadow:0 2px 2px 0 rgba(0,0,0,0.14),0 3px 1px -2px rgba(0,0,0,0.12),0 1px 5px 0 rgba(0,0,0,0.2)}.hoverable{-webkit-transition:-webkit-box-shadow .25s;transition:-webkit-box-shadow .25s;transition:box-shadow .25s;transition:box-shadow .25s,-webkit-box-shadow .25s}.hoverable:hover{-webkit-box-shadow:0 8px 17px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19);box-shadow:0 8px 17px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19)}i{line-height:inherit}i.right{float:right;margin-left:15px}.bangumi .right{float:right !important}.material-icons{text-rendering:optimizeLegibility;-webkit-font-feature-settings:'liga';-moz-font-feature-settings:'liga';font-feature-settings:'liga'}.row{margin-left:auto;margin-right:auto;margin-bottom:20px}.row:after{content:\"\";display:table;clear:both}.row .col{float:left;-webkit-box-sizing:border-box;box-sizing:border-box;padding:0 .75rem;min-height:1px}.row .col.s12{width:100%;margin-left:auto;left:auto;right:auto}@media only screen and (min-width:601px){.row .col.m6{width:50%;margin-left:auto;left:auto;right:auto}}html{line-height:1.5;font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",Roboto,Oxygen-Sans,Ubuntu,Cantarell,\"Helvetica Neue\",sans-serif;font-weight:normal;color:rgba(0,0,0,0.87)}@media only screen and (min-width:0){html{font-size:14px}}@media only screen and (min-width:992px){html{font-size:14.5px}}@media only screen and (min-width:1200px){html{font-size:15px}}.card{position:relative;margin:.5rem 0 1rem 0;background-color:#fff;-webkit-transition:-webkit-box-shadow .25s;transition:-webkit-box-shadow .25s;transition:box-shadow .25s;transition:box-shadow .25s,-webkit-box-shadow .25s;border-radius:2px}.card .card-title{font-size:24px;font-weight:300}.card .card-title.activator{cursor:pointer}.card .card-image{position:relative}.card .card-image img{display:block;border-radius:2px 2px 0 0;position:relative;left:0;right:0;top:0;bottom:0;width:100%}.card .card-content{padding:24px;border-radius:0 0 2px 2px}.card .card-content p{margin:0}.card .card-content .card-title{display:block;line-height:32px;margin-bottom:8px}.card .card-content .card-title i{line-height:32px}.card .card-reveal{padding:24px;position:absolute;background-color:#fff;width:100%;overflow-y:auto;left:0;top:100%;height:100%;z-index:3;display:none}.card .card-reveal .card-title{cursor:pointer;display:block}.waves-effect{position:relative;cursor:pointer;display:inline-block;overflow:hidden;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;vertical-align:middle;z-index:1;-webkit-transition:.3s ease-out;transition:.3s ease-out}.waves-effect img{position:relative;z-index:-1}.waves-block{display:block}::-webkit-input-placeholder{color:#d1d1d1}::-moz-placeholder{color:#d1d1d1}:-ms-input-placeholder{color:#d1d1d1}::-ms-input-placeholder{color:#d1d1d1}[type=\"radio\"]:not(:checked){position:absolute;opacity:0;pointer-events:none}[type=\"radio\"]:not(:checked)+span{position:relative;padding-left:35px;cursor:pointer;display:inline-block;height:25px;line-height:25px;font-size:1rem;-webkit-transition:.28s ease;transition:.28s ease;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}[type=\"radio\"]:not(:checked)+span:before,[type=\"radio\"]:not(:checked)+span:after{border-radius:50%}[type=\"radio\"]:not(:checked)+span:before,[type=\"radio\"]:not(:checked)+span:after{border:2px solid #5a5a5a}[type=\"radio\"]:not(:checked)+span:after{-webkit-transform:scale(0);transform:scale(0)}[type=\"checkbox\"]:not(:checked){position:absolute;opacity:0;pointer-events:none}[type=\"checkbox\"]:not(:checked):disabled+span:not(.lever):before{border:none;background-color:rgba(0,0,0,0.42)}[type=\"checkbox\"].filled-in:not(:checked)+span:not(.lever):before{width:0;height:0;border:3px solid transparent;left:6px;top:10px;-webkit-transform:rotateZ(37deg);transform:rotateZ(37deg);-webkit-transform-origin:100% 100%;transform-origin:100% 100%}[type=\"checkbox\"].filled-in:not(:checked)+span:not(.lever):after{height:20px;width:20px;background-color:transparent;border:2px solid #5a5a5a;top:0px;z-index:0}input[type=checkbox]:not(:disabled) ~ .lever:active:before,input[type=checkbox]:not(:disabled).tabbed:focus ~ .lever::before{-webkit-transform:scale(2.4);transform:scale(2.4);background-color:rgba(0,0,0,0.08)}input[type=range].focused:focus:not(.active)::-webkit-slider-thumb{-webkit-box-shadow:0 0 0 10px rgba(38,166,154,0.26);box-shadow:0 0 0 10px rgba(38,166,154,0.26)}input[type=range].focused:focus:not(.active)::-moz-range-thumb{box-shadow:0 0 0 10px rgba(38,166,154,0.26)}input[type=range].focused:focus:not(.active)::-ms-thumb{box-shadow:0 0 0 10px rgba(38,166,154,0.26)} 番组计划 这里将是永远的回忆 window.onload = function(){ videos.forEach(function(video, i){ $('#rootRow').append(` ${video.title} ${video.jp} ${video.status} ${video.title} ${video.jp} 放送时间: ${video.time} ${video.desc} ${video.status} `) }) }","raw":null,"content":null},{"title":"","date":"2022-12-10T12:48:36.726Z","updated":"2022-12-10T12:48:36.726Z","comments":true,"path":"live2dw/assets/index.json","permalink":"http://ccr39.github.io/live2dw/assets/index.json","excerpt":"","keywords":null,"text":"{\"version\":\"1.0.0\",\"model\":\"model.moc\",\"textures\":[\"textures/animal-costume-racoon.png\"],\"layout\":{\"center_x\":0,\"center_y\":-0.05,\"width\":2},\"hit_areas_custom\":{\"head_x\":[-0.35,0.6],\"head_y\":[0.19,-0.2],\"body_x\":[-0.3,-0.25],\"body_y\":[0.3,-0.9]},\"motions\":{\"idle\":[{\"file\":\"motions/Breath1.mtn\"},{\"file\":\"motions/Breath2.mtn\"},{\"file\":\"motions/Breath3.mtn\"},{\"file\":\"motions/Breath5.mtn\"},{\"file\":\"motions/Breath7.mtn\"},{\"file\":\"motions/Breath8.mtn\"}],\"sleepy\":[{\"file\":\"motions/Sleeping.mtn\"}],\"flick_head\":[{\"file\":\"motions/Touch Dere1.mtn\"},{\"file\":\"motions/Touch Dere2.mtn\"},{\"file\":\"motions/Touch Dere3.mtn\"},{\"file\":\"motions/Touch Dere4.mtn\"},{\"file\":\"motions/Touch Dere5.mtn\"},{\"file\":\"motions/Touch Dere6.mtn\"}],\"tap_body\":[{\"file\":\"motions/Sukebei1.mtn\"},{\"file\":\"motions/Sukebei2.mtn\"},{\"file\":\"motions/Sukebei3.mtn\"},{\"file\":\"motions/Touch1.mtn\"},{\"file\":\"motions/Touch2.mtn\"},{\"file\":\"motions/Touch3.mtn\"},{\"file\":\"motions/Touch4.mtn\"},{\"file\":\"motions/Touch5.mtn\"},{\"file\":\"motions/Touch6.mtn\"}]}}","raw":null,"content":null}],"posts":[{"title":"学校机房无法访问互联网之联网教程","slug":"LW","date":"2025-02-06T08:06:45.000Z","updated":"2025-02-06T06:37:16.264Z","comments":true,"path":"资源/LW/","link":"","permalink":"http://ccr39.github.io/%E8%B5%84%E6%BA%90/LW/","excerpt":"","keywords":null,"text":"机房联网教程 ——By ccr39 由于学校机房可能会阻止机房电脑访问互联网,此篇教程旨在利用局域网代理来使机房电脑连接到互联网。 请现在校园网下可以访问互联网的设备(如教室多媒体)下使用本教程搭建代理服务,再在机房计算机内配置代理。 请事先查询电脑操作系统是64位还是32位:右击此电脑->点击属性->系统类型 一、原理使用局域网代理的方式,通过设置内网服务器,并提供网络代理服务,并最终访问互联网。 二、使用工具Clash for Windows: 32 位电脑下载;64 位电脑下载);备用1;备用2;备用3; 三、快速开始1、服务端设置代理请在多媒体上进行以下操作 ①下载Clash for Windows并安装 32 位电脑下载;64 位电脑下载 因为多媒体每次重启会重置C盘,因此建议将默认下载地址改为D盘,并且记住下载目录。 若出现下载慢、安装失败、版本不对请使用备用下载链接。 ②查询本机内网ip与端口(如果界面为英文,请按照对应位置进行操作) 先记录下端口号,如果为空,可以点击并更改,建议改为方便记忆的端口号。 再点击“允许互联网连接”后面的图标,记录地址后面的ip地址 ③开启”允许局域网连接” 确保这一项打开即可,其他不用管,以上即为全部操作,请保持此电脑开启 2、代理端设置请在机房内以下操作 ①打开控制面板 ②点击“网络和 Internet”。进入网络设置。 ③点击“网络和共享中心”,点击左下角的“Internet选项”进入Internet属性设置。 ④选择“连接”,然后进入“高级设置”。 ⑤勾选”为LAN使用代理服务器”,填写IP地址和端口号信息。 这里把之前记录的地址和端口填入,点击确定即可完成。 3、完成祝大家爽玩 4、翻墙操作(不想翻墙可以不看,看不懂可以不看)由于在机房电脑设置了局域网代理,因此不能再次设置互联网代理,想要使用梯子,必须在多媒体的Clas上配置。 在“配置”里输入订阅连接点击下载即可,并在“常规”中启动系统代理。 这样就可以为所有使用此服务器的客户端都使用VPN进行代理 免费放一个订阅链接(不嫌麻烦顺手导入就可以): https://36ba8c72.ghelper.me/subs/clash/53b94da436ba8c72acbd137a45cd6003 免费机场: 登录 — iKuuu VPN 付费机场: XSUS import { init } from 'https://unpkg.com/@waline/client@v2/dist/waline.mjs'; init({ el: '#waline', serverURL: 'https://waline-ccr39.netlify.app/.netlify/functions/comment', reaction: [ 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_heart_eyes.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_joy.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_consider.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_sob.png', ], emoji: [ '//unpkg.com/@waline/emojis@1.1.0/bilibili', '//unpkg.com/@waline/emojis@1.1.0/weibo', '//unpkg.com/@waline/emojis@1.1.0/qq', ] });","raw":null,"content":null,"categories":[{"name":"资源","slug":"资源","permalink":"http://ccr39.github.io/categories/%E8%B5%84%E6%BA%90/"}],"tags":[{"name":"技术","slug":"技术","permalink":"http://ccr39.github.io/tags/%E6%8A%80%E6%9C%AF/"}]},{"title":"从零开始编写一个浏览器笔记脚本","slug":"nicoNote","date":"2024-12-14T13:34:20.000Z","updated":"2024-12-19T08:00:01.069Z","comments":true,"path":"技术/nicoNote/","link":"","permalink":"http://ccr39.github.io/%E6%8A%80%E6%9C%AF/nicoNote/","excerpt":"","keywords":null,"text":"项目地址:ccr39/NicoNote: 从零开始编写的浏览器笔记脚本 故事的开始: 在浏览器上学习时时常要记笔记。 在预览网络上已有的各类插件后本人发现,这类插件往往已经长时间失去维护,或需要付费使用。 为什么不自己制作一个有类似功能的脚本呢? 在几乎没有任何理论知识的前提下本人决定实施这个构想。 一、开始前的准备希望实现的功能基本功能: 能够在网页上编写笔记,并保存在本地。可以在打开网页后显示对应笔记。 能够使用 Markdown 语法并实现实时渲染 $\\LaTeX$ 。 能够导出与导入 Markdown 笔记。 能够调整笔记框的大小。 进阶功能: 美化笔记框背景。 可以根据网页中的某条内容链接到笔记的某一部分。 可以根据视频的进度链接到笔记。 自定义笔记框。 (待思考) 实现方案1、使用 Tampermonkey 编写基本主体脚本。这需要学习一部分网页前端知识。 2、使用开源的纯前端 Markdown 文字编辑器。 3、利用 Git 进行版本控制与脚本的发布。 二、让我们开始吧尝试了解 Tampermonkey,发现官方文档没有进行汉化,因此翻阅了中文的油猴开发指南。 1、对头部元数据的理解 元数据 值 @name( :zh-CN :zh-TW :en ) 脚本的名字(简中,繁中,英文)。 @namespace 一般为一个 URL 或自定义的内容,用于脚本管理器在@name相同的情况下识别唯一的脚本 @version 脚本的版本。 @author 脚本作者。 @description( :zh-CN :zh-YW :en ) 脚本的描述(简中,繁中,英文)。 @include 脚本应该运行的页面, 可以使用通配符, 允许多个标签。 @match 与@include相似,区别是不可以用通配符,更精确因此更为常用,允许多个标签。 @exclude 排除URL,即使它们包含在@include或@match中 ,允许多个标签。 @icon @iconURL @defaulticon 脚本的图标的 URL,会在脚本管理列表上显示。 @icon64 @icon64URL 64*64 的图标文件的 URL ,可能会在选项中缩放。 @updateURL 更新脚本的地址,该URL应该指向一个脚本文件,只需要定期更新该文件即可实现对脚本的更新。注意:只有存在@version标签才会去更新。 @downloadURL 定义脚本的下载地址(一般指的是手动安装脚本时的文件)通常和 @updateURL 指向同一文件较常见。 @license 用于声明脚本的许可证类型。许可证定义了其他人如何使用、修改和分发你的脚本。 @grant 声明脚本会用到的特殊权限或功能。它决定了脚本是否可以使用某些特定的 API,或者是否可以访问用户脚本管理器提供的功能。可以存在多条 @require 指向一个脚本文件,会在本脚本运行前加载并执行 @run-at 定义脚本被注入的时间,与其他脚本处理相反,@run-at 定义了脚本要运行的第一可能时间。这意味着,使用@require标记的脚本可能会在文档已加载后执行,因为获取所需脚本花费了很长时间。 @supportURL 插件个人支持的地址,用于提交 issue 。 @homepage @homepageURL @website @source 在“选项”页上用于从脚本名链接到给定页的作者主页。请注意,如果@namespace标记以“http://”开头,则其内容也将用于此操作。 @connect 用于声明可以与那些外部的域名进行跨域通信,未声明的域名在脚本中将被禁止访问,允许多个标签。可以使用@connect *允许所有域名(不推荐,可能带来安全风险)。 部分元数据的常用值 ①关于@license常见的许可证类型: 许可证 作用/特点 MIT 允许几乎任何使用,包括修改、分发和商业用途,只需保留原作者声明。 GNU GPL-3.0 允许修改和分发,但要求开源修改后的版本,适合需要保持自由传播的软件。 Apache-2.0 类似于 MIT,但要求保留通知文件,并保护专利权。 CC-BY-4.0 允许分享和修改,只需署名原作者,常用于非软件内容。 Unlicense 放弃所有版权,允许任何用途。 WTFPL Do What The Fuck You Want To Public License中文译:你他妈的想干嘛就干嘛公共许可证。是一种不太常用的、极度放任的自由软件许可证。它的条款基本等同于贡献到公有领域。 Custom 自定义声明,允许作者明确指定特殊的版权声明,例如:仅供个人使用,禁止修改传播。 ②@grant 的常用值 @grant 值 描述 none 不授予任何特殊权限,脚本与页面共享相同的全局作用域。 GM_addStyle 向页面动态添加 CSS 样式。 GM_getValue 从脚本的本地存储中获取数据。 GM_setValue 将数据存储到脚本的本地存储中。 GM_deleteValue 删除脚本本地存储中的数据。 GM_listValues 获取所有存储值的键名列表。 GM_xmlhttpRequest 发起跨域的 HTTP 请求(比原生的 XMLHttpRequest 更强大)。 GM_download 下载文件到本地。 GM_notification 在桌面弹出通知。 GM_openInTab 在新标签页中打开一个链接。 GM_registerMenuCommand 向用户脚本菜单添加自定义选项。 GM_unregisterMenuCommand 删除自定义的菜单选项。 GM_setClipboard 将内容复制到系统剪贴板。 GM_info 提供有关用户脚本的信息(只读)。 ③@run-at的常用值 @run-at 值 描述 document-start 脚本会被尽可能快地注入 document-body 当body元素存在是被注入 document-end 当 DOMContentLoaded 事件被触发时或者之后注入 document-idle 当 DOMContentLoaded 事件被触发后被注入 如果没有@run-at标签也是在此时注入 2、目前产生的问题(ChatGPT 解答)Q.1:@downloadURL和@updateURL的区别 在编写油猴(Tampermonkey 或 Greasemonkey)脚本时,@include 和 @match 是用来定义脚本作用范围的元数据注释。它们的作用类似,但有一些关键区别: @include 用途:匹配指定的 URL 模式,让脚本在符合模式的页面上运行。 语法:支持通配符(*),简单易用。 *:匹配任意字符。 示例: // 脚本会在所有以 "https://example.com/" 开头的页面上运行 @include https://example.com/* 匹配示例: https://example.com/* 可以匹配: https://example.com/page1 https://example.com/page2 通配符 *也可以放在中间或末尾,如: https://*.example.com/* 匹配所有子域名。 @match 用途:更严格地匹配 URL 模式,符合 URL 模式规范。 语法:不支持简单的 * 通配符定义所有,而是更精确的匹配规则。 但可以使用通配符 * 匹配子域名或协议。 示例: javascript复制代码// 脚本会在 https://example.com 的所有页面运行 @match https://example.com/* 匹配示例: https://*.example.com/* 可以匹配: https://sub.example.com/page https://another.example.com/page 但不会匹配: http://example.com(因为协议不同)。 关键区别 特性 @include @match 灵活性 支持简单通配符,较宽松 严格匹配 URL,符合标准规范 安全性 容易出现误匹配 更严格,减少误匹配的风险 协议要求 可以省略协议 必须指定协议(http:// 或 https://) 兼容性 旧版脚本可能使用更多 推荐使用,符合现代浏览器扩展规范 使用建议 如果需要快速定义作用域,且 URL 规则较简单,可以使用 @include。 如果需要更安全、更准确的匹配,建议使用 @match,特别是在现代浏览器扩展环境下。 现代浏览器和 Tampermonkey 都更推荐使用 @match,因为它的匹配规则符合浏览器扩展的标准。 个人总结 两者用来将脚本应用到所有的页面,应分别如下写: @match *://*/* @include * Q.2:什么是 DOMContentLoaded 事件? DOMContentLoaded 是一个常见的 JavaScript 事件,用于监听 HTML 文档的加载状态。当浏览器解析完所有的 HTML 并构建完成 DOM 树时,就会触发 DOMContentLoaded 事件,而无需等待其他资源(如图片、样式表和脚本文件)的加载完成。 特点 触发时机:当 HTML 文档被完全加载和解析完成时(即 DOM 树构建完成)。 不等待其他资源:与 window.onload 不同,DOMContentLoaded 不需要等待图片、样式表、iframe 等资源加载完成后才触发。 适用于操作 DOM:在该事件触发时,DOM 已经可用,因此适合初始化页面内容或操作 DOM 元素。 用法 监听 DOMContentLoaded 的方法有以下几种: 1. 使用 addEventListener document.addEventListener("DOMContentLoaded", function() { console.log("DOM 已完全加载并解析"); // 可以安全地操作 DOM 元素 document.body.style.backgroundColor = "lightblue"; }); 2. 使用旧的 onreadystatechange 早期浏览器中,可以通过 readyState 属性判断文档是否加载完成: document.onreadystatechange = function() { if (document.readyState === "interactive") { console.log("DOM 已完全加载并解析"); } }; 3. 直接在脚本末尾执行 如果你的脚本放在文档的底部(</body>标签之前),可以不显式监听 DOMContentLoaded,因为此时 DOM 已经解析完成: <!DOCTYPE html> <html> <head> <title>Example</title> </head> <body> <h1>Hello, World!</h1> <script> console.log(document.querySelector("h1").textContent); // "Hello, World!" </script> </body> </html> DOMContentLoaded 和 window.onload 的区别 特性 DOMContentLoaded window.onload 触发时机 DOM 树构建完成(HTML 已加载并解析)。 页面所有资源(包括图片、样式等)加载完成。 是否等待外部资源 不等待外部资源加载完成。 等待所有外部资源加载完成。 使用场景 初始化 DOM 操作或页面功能。 确保所有资源可用(如图片尺寸)。 示例:两者对比 document.addEventListener("DOMContentLoaded", function() { console.log("DOM 已加载完成,但图片可能还在加载中"); }); window.addEventListener("load", function() { console.log("页面所有资源加载完成,包括图片和样式"); }); 浏览器支持 DOMContentLoaded 是一个标准事件,现代浏览器(包括 IE9+)都完全支持。 使用建议 推荐场景:如果你的脚本只需要操作 DOM 元素(如添加事件监听器或修改内容),优先使用 DOMContentLoaded,因为它比 window.onload 更早触发。 性能优化:通过监听 DOMContentLoaded,可以更快地响应用户交互,而无需等待所有资源加载完成。 Q.3:什么是DOM树?DOM 树(Document Object Model Tree)是浏览器在加载和解析 HTML 文档时,根据 HTML 的层级结构生成的一种树形数据结构。它表示了文档的结构以及每个节点之间的关系,使得 JavaScript 可以通过 DOM API 操作页面内容和结构。 DOM 树的组成 DOM 树由以下几种节点组成,每个节点代表 HTML 文档的一部分: 文档节点(Document Node): 表示整个 HTML 文档的根节点。 通过 JavaScript 的 document 对象访问。 元素节点(Element Nodes): 表示 HTML 的元素标签,例如 <div>、<p>。 元素节点可以嵌套形成层级结构。 属性节点(Attribute Nodes): 表示 HTML 元素的属性,例如 id="example"。 属性是元素节点的一部分,但在 DOM 树中不是子节点,而是直接附属于对应的元素节点。 文本节点(Text Nodes): 表示元素或属性中的文本内容。 文本节点始终是叶节点,没有子节点。 注释节点(Comment Nodes): 表示 HTML 文档中的注释内容。 DOM 树的结构 以以下 HTML 代码为例: <!DOCTYPE html> <html> <head> <title>Example</title> </head> <body> <h1 id="header">Hello, World!</h1> <p>Welcome to DOM.</p> </body> </html> 对应的 DOM 树结构如下: Document └── html ├── head │ └── title │ └── "Example" └── body ├── h1 │ ├── Attribute: id="header" │ └── "Hello, World!" └── p └── "Welcome to DOM." DOM 树的特点 层级关系: HTML 文档的嵌套结构会在 DOM 树中反映为父子关系。 每个 HTML 元素是一个节点,嵌套关系形成了树状层级。 节点类型: 可以通过 nodeType 属性查看节点类型,例如: 1:元素节点 3:文本节点 8:注释节点 可遍历: DOM 树中的节点可以通过 JavaScript 遍历,例如 parentNode、childNodes、nextSibling 等。 常见操作 获取节点: const header = document.getElementById("header"); // 获取 h1 元素 const paragraphs = document.getElementsByTagName("p"); // 获取所有 <p> 元素 2. **修改节点内容**: ```javascript const header = document.getElementById("header"); header.textContent = "Hello, DOM!"; 添加新节点: const newDiv = document.createElement("div"); newDiv.textContent = "This is a new div."; document.body.appendChild(newDiv); 删除节点: const header = document.getElementById("header"); header.remove(); **DOM 树的作用** 1. **页面动态交互**:通过操作 DOM 树,可以动态修改页面的结构和内容。 2. **事件绑定**:JavaScript 事件处理器通过 DOM 树关联 HTML 元素。 3. **样式动态调整**:通过修改 DOM 节点的样式属性实现动态效果。 **总结** DOM 树是 HTML 文档在浏览器中的表示形式,它将 HTML 结构化为可以用 JavaScript 操作的对象模型。熟练掌握 DOM 树和相关操作是前端开发的基础。 2024/12/8 3、Hello World在头部元数据下方标注了书写代码的地方。 (function() { 'use strict'; // Your code here... })(); 根据文档描述,脚本的书写应该使用JavaScript。 利用alert()弹出一个对话框,并输出 HelloWorld,并使用@include *将其应用到所有页面。 // ==UserScript== //@name a_simple_test //@include * // ==/UserScript== (function() { 'use strict'; alert('HelloWorld') // Your code here... })(); 这样,在打开任意网站后,都会弹出一个 HelloWorld 的对话框。 4、熟悉 JavaScript 的语法在JavaScript 用法 | 菜鸟教程中了解JS的基本用法。 在此出现的问题: Q.4:之前 HelloWorld 脚本中的alert('HelloWorld')末尾没有分号,这种写法是否合法? 是合法的!在 JavaScript 中,分号(;)是可选的,因为 JavaScript 有一个自动分号插入(Automatic Semicolon Insertion, ASI)的机制。在大多数情况下,即使你省略了分号,JavaScript 引擎也会根据上下文自动插入。 解释代码中的 alert('HelloWorld') 在以下代码中: alert('HelloWorld') 即使没有写分号,JavaScript 引擎仍然能正确解析,因为: alert('HelloWorld') 是一个独立的语句。 ASI 机制会在行末自动插入分号,等效于: alert('HelloWorld'); 因此,这种省略分号的写法是合法的。 什么时候分号是必要的? 尽管 ASI 机制可以避免大部分语法错误,但在某些特定情况下,省略分号可能导致意外行为。例如: 情况 1:行首是 [ 或 ( 的表达式 let a = 5 [1, 2, 3].forEach(x => console.log(x)) 在这种情况下,JavaScript 会将 [1, 2, 3] 视为数组访问器,而不是独立的数组字面量。 解决方法: let a = 5; [1, 2, 3].forEach(x => console.log(x)); 情况 2:返回值与表达式在不同行 function test() { return { value: 42 } } console.log(test()) // undefined 在这种情况下,return 语句后自动插入了分号,因此实际返回的是 undefined。 解决方法: function test() { return { value: 42 }; } 建议 始终使用分号:虽然 JavaScript 的 ASI 机制可以省略分号,但为了代码的可读性和避免潜在的错误,建议显式添加分号。 遵循团队规范:如果项目使用了某种代码风格(如 Airbnb 或 Standard),遵循其规范(例如 Standard JS 就不使用分号)。 工具辅助:使用代码检查工具(如 ESLint)和格式化工具(如 Prettier)来统一代码风格。 结论 在你的脚本中,省略 alert('HelloWorld') 的分号是合法的,且能正确运行。不过,养成显式添加分号的习惯会更安全、更规范。 5、(番外)为插件创作一个图标使用 ChatGPT 绘制一个笔记本的图标,将其转换为64*64大小。 使用 SVG 在线编辑器 | 菜鸟工具 将其转化为矢量图形,并使其可以用代码表示出来。 发现 ChatGPT 绘制的图形不是纯色图形,会导致代码过长,故放弃使用 ChatGPT 绘制的图形,转而使用网络上公开的资源,使用 SVG 工具将其稍加修改。 接下来,将其转换为可以直接在@icon后使用的格式,即 Data URI 格式。使用在线工具在线SVG转DataURL - UU在线工具自动转化。 6、创建一个唤出笔记本的标识我们需要一个拥有以下功能的标识: 在浏览器页面的边框处,并始终位于页面最上方。 点击后会唤出笔记本。 拥有一些简单的动画效果。 随页面滚动时不改变标识的位置。 首先要知道如何使用 JavaScript 创建并插入 HTML 元素。 查阅了HTML DOM insertAdjacentHTML() 方法 - 菜鸟教程,HTML DOM querySelector() 方法 | 菜鸟教程。 document.querySelector("body").insertAdjacentHTML("afterend", "<div><p>Hello world</p></div>"); //表示在<body>元素后插入<div>元素。先用querySelector()获取<body>元素的document,再用insertAdjacentHTML(,)插入元素。 现在我们要将这个元素置于我们希望它存在的位置,为此,我们需要了解如何利用脚本改变元素的 CSS 样式,以及如何书写 CSS。 设置位置查阅的资料:CSS position 属性 | 菜鸟教程、CSS bottom 属性 | 菜鸟教程、使用css,如何把div设置为圆形-百度经验、CSS border 属性 | 菜鸟教程 document.querySelector("body").insertAdjacentHTML("afterbegin",'<div id="nicoBt"><p>helloworld</></div>'); //表示在<body>元素后插入<div>元素 var nicoButton = document.getElementById("nicoBt"); //var 表示定义变量,根据getElementById()利用id找到<div>元素 var nicoButtonStyle = "\\ position: fixed;\\ right: 1%;\\ bottom:80%;\\ width: 44px;\\ height: 44px;\\ border: 2px solid #D3D3D3;\\ border-radius: 50%;\\ background: rgb(0, 127, 255);\\ z-index: 2147483647;\\ "; //第一句表示依照浏览器边框定位,right与bottom定义位置,width与height定义长宽,border用于定义边框,border-radius用于实现圆形效果,z-index定义了元素的图层高度,设置一个很大的数字可以保证其置于其他图像上方。 //定义<div>元素的CSS样式,输入字符串时进行换行操作,在每行末尾加上\\ //末尾的;可加可不加 nicoButton.setAttribute("style",nicoButtonStyle); //setAttribute(,)可以改变元素属性,用来改变nicoButton的CSS样式 现在我们把这个元素改写为一个按钮,把图标插入进去。 var htmlNicoButton = '\\ <div id="nicoBt">\\ <img src="图标URL">\\ </div>\\ '; document.querySelector("body").insertAdjacentHTML("afterbegin",htmlNicoButton); //以下略 2024/12/9 position: absolute;/*使用相对位置*/ top: 50%;/*竖直方向上一半*/ left: 50%;/*水平方向上一半*/ transform: translate(-50%, -50%);/*x,y方向上均往回移动自身的一般*/ 使用上面的方法把图像居中,参考:CSS3 transform 属性 | 菜鸟教程 发现存在<iframe>时会添加很多的标识,希望只在主页面添加,加上判断: if (window.self === window.top) { document.querySelector("body").insertAdjacentHTML("afterend",htmlNicoButton); } 参考了JavaScript 比较和逻辑运算符 | 菜鸟教程、Window self 属性 | 菜鸟教程 下面我们要让鼠标悬停在标识上方时有一定的反馈效果,这里利用了addEventListener()设置两个效果,参考了HTML DOM addEventListener() 方法 | 菜鸟教程。 nicoButton.addEventListener("mouseover", function () { //光标移动到图标上,执行函数 nicoButton.style.width = "55px"; nicoButton.style.height = "55px"; //大小改变 nicoButton.style.cursor = "pointer"; //鼠标光标从箭头改编为小手 }); nicoButton.addEventListener("mouseout", function () { //光标移开 nicoButton.style.width = "48px"; nicoButton.style.height = "48px"; nicoButton.style.cursor = ""; //变回 }); 7、创建一个容器创建一个作为我们的笔记本的容器: var nicoNoteDiv = document.createElement("div");//这里用document.creatElement()创建元素。ps.比最开始进步了 nicoNoteDiv.setAttribute("id","nicoNoteDiv"); 用点击事件呼出编辑框,并让图标不透明度降低(参考css中让元素消失的方法_transition visibility 无效-CSDN博客): nicoButton.addEventListener("click", function () { document.querySelector("html").appendChild(nicoNoteDiv);//用点击事件呼出编辑框,添加在 nicoBt 后面 nicoButton.style.opacity="0.3"; //图标不透明度降低 }); //这里用 elementA.appendChild(elemenetB):表明在A内最后添加B元素 下面我们来设计这个nicoNoteDiv除了最基本的长宽位置之外,我们希望它可以允许自己通过拖拽调节大小和位置(似乎略有些麻烦)。 2024/12/10 2024/12/11 去医院了,还被坑了,详情请见:只身陷入心理治疗骗局!!深扒“SCIO全科生物反馈测疗仪”与“心理AI智能检测”底裤。 - 知乎 ①拖拽调节位置为了使其可以调节自身位置和大小,我们应该从两方考虑: CSS 角度,在鼠标靠近边缘时,光标应该发生变化。 JS 角度,根据鼠标光标的坐标改变的大小。 为了实现上述操作,我们考虑把存放笔记本主体的和调整大小的分开,外层仅仅实现拖拽功能,内层为主体。 Q.5:在查询资料时发现的() => {}是什么意思? (e) => {} 是 JavaScript 中的箭头函数语法,是定义函数的一种简洁方式。它可以用来代替传统的 function 声明。 语法 (param1, param2, ...) => { // 函数体 } 分解理解 (e) => {} 箭头函数: => 是箭头函数的核心,表示这是一个函数。 **参数 (e)**: e 是箭头函数的参数。它通常代表事件对象,尤其是在事件处理程序中,比如 addEventListener。 **函数体 {}**: {} 包含函数执行的代码。 完整例子 以下是一个常见的使用场景: 传统函数写法 document.addEventListener("click", function(e) { console.log("鼠标点击了页面", e); }); 箭头函数写法 document.addEventListener("click", (e) => { console.log("鼠标点击了页面", e); }); 简化规则 参数简写: 如果只有一个参数,可以省略括号 () e => console.log(e); 如果没有参数或有多个参数,则必须使用括号。 () => console.log("无参数"); (x, y) => console.log(x + y); 函数体简写: 如果函数体只有一行代码,且直接返回值,可以省略 {} 和 return x => x * x; // 返回 x 的平方 优势 简洁:语法更短,易读。 自动绑定上下文:箭头函数不会创建自己的 this,而是继承自外层作用域。 例子:箭头函数绑定上下文 function Example() { this.name = "箭头函数示例"; document.addEventListener("click", () => { console.log(this.name); // 指向 Example 实例 }); } new Example(); 对比传统函数 特性 箭头函数 普通函数 语法简洁 是 否 this 指向 继承外层作用域 动态绑定,取决于调用位置 使用场景 回调函数、简单逻辑 需要动态绑定 this 的复杂场景 箭头函数非常适合在事件处理、数组操作等回调中使用,但如果需要灵活绑定 this,普通函数可能更适合。 先实现较简单的拖拽: 首先我们应该想办法获取鼠标的光标坐标,可以利用addEventListener监听mousemove事件,再将生成的MouseEvent 对象传入参数,提取clientX 和 clientY的信息。 关于这一过程的具体原理 Chat GPT 回答如下: 在以下代码中: document.addEventListener('mousemove', (event) => { const { clientX, clientY } = event; console.log(`鼠标X坐标: ${clientX}, 鼠标Y坐标: ${clientY}`);//console.log()用于把信息输出到工作台。${}表示在字符串中插入函数或变量。 }); 事件参数 event 的捕捉和传递机制: 事件监听器的注册: document.addEventListener('mousemove', callback) 将事件监听器绑定到 document 上,用于监听 mousemove 事件。 当用户移动鼠标时,浏览器会触发 mousemove 事件。 事件对象的生成: 浏览器在触发事件时,会生成一个 Event 对象。对于 mousemove 事件,生成的对象是一个 MouseEvent 实例,它继承了 Event 的所有属性和方法,同时还包含鼠标相关的属性,比如 clientX 和 clientY。 事件对象的传递: 当事件触发时,浏览器会将生成的 MouseEvent 对象作为参数传递给监听器中定义的回调函数 (event) => { ... }。 解构赋值: 在回调函数中,通过 const { clientX, clientY } = event; 使用了解构赋值,从 event 对象中提取 clientX 和 clientY 属性值,代表鼠标指针相对于视口左上角的 X 和 Y 坐标。 输出结果: 提取到的坐标值会被插入到字符串中,并通过 console.log 输出到控制台。 总结: 浏览器自动生成事件对象并将其作为参数传递给事件回调函数。你只需定义回调函数的参数名称(这里是 event),浏览器会负责传递这个对象。 MouseEvent实例中还有那些属性? MouseEvent 是由浏览器生成的事件对象,专门用于表示与鼠标操作相关的事件(例如 click、mousemove、mousedown 等)。它继承自 UIEvent,并进一步继承自 Event。MouseEvent 实例包含许多有用的属性,用于描述鼠标事件的详细信息。 以下是 MouseEvent 的主要属性: 鼠标位置信息 **clientX**:鼠标指针相对于浏览器视口(窗口)左边缘的 X 坐标。 **clientY**:鼠标指针相对于浏览器视口(窗口)顶部的 Y 坐标。 **screenX**:鼠标指针相对于屏幕左边缘的 X 坐标。 **screenY**:鼠标指针相对于屏幕顶部的 Y 坐标。 **pageX**:鼠标指针相对于整个文档左边缘的 X 坐标(包括页面滚动距离)。 **pageY**:鼠标指针相对于整个文档顶部的 Y 坐标(包括页面滚动距离)。 **offsetX**:鼠标指针相对于事件目标元素左边缘的 X 坐标。 **offsetY**:鼠标指针相对于事件目标元素顶部的 Y 坐标。 鼠标按键信息 button: 触发事件的鼠标按键的代码: 0:主按钮(通常是左键) 1:中间按钮(滚轮) 2:次按钮(通常是右键) buttons: 一个按位标记的数字,表示当前按下的鼠标按钮: 1:左键 2:右键 4:中键 (可以组合,如同时按下左键和右键时值为 3) 键盘修饰键状态 这些属性表示事件发生时是否按下了修饰键: **altKey**:true 表示 Alt 键被按下。 **ctrlKey**:true 表示 Ctrl 键被按下。 **metaKey**:true 表示 Meta 键被按下(Mac 上为 Command 键)。 **shiftKey**:true 表示 Shift 键被按下。 拖放和相关元素 relatedTarget: 对于某些事件(如 mouseover 和 mouseout),表示鼠标从哪个元素移入/移出。 target: 事件的目标元素。 currentTarget: 当前正在处理事件的元素。 其他信息 **movementX**:自上一次 mousemove 事件以来,鼠标指针在 X 轴上的移动距离。 **movementY**:自上一次 mousemove 事件以来,鼠标指针在 Y 轴上的移动距离。 **detail**:事件的点击次数(适用于 click 和 dblclick 等事件)。 方法 getModifierState(key):检查指定的修饰键(如 Alt、Shift)是否被按下。 继承自 UIEvent 和 Event 的属性 **type**:事件类型(如 "click"、"mousemove")。 **target**:事件触发的目标元素。 **bubbles**:true 表示事件会冒泡。 **cancelable**:true 表示事件可以被取消。 **defaultPrevented**:true 表示默认操作已被阻止。 **timeStamp**:事件触发时的时间戳。 示例 document.addEventListener('mousemove', (event) => { console.log('clientX:', event.clientX); console.log('clientY:', event.clientY); console.log('screenX:', event.screenX); console.log('button:', event.button); console.log('altKey pressed:', event.altKey); }); 这些属性可以帮助开发者获取鼠标的位置信息、按键状态和修饰键等详细信息,以便实现复杂的鼠标交互功能。 Q.6:什么是解构赋值? 在 const { clientX } = event; 和 const clientX = event.clientX; 中,**clientX** 最终的效果是等价的,它们都会从 event 对象中提取 clientX 的值并赋值给一个同名变量。 但它们的语法和解构方式不同,具体区别如下: 解构赋值 (const { clientX } = event;) 这是 ES6 解构赋值 的语法,用于从对象中提取属性并赋值给同名变量。 const { clientX } = event; 等价于: const clientX = event.clientX; 优点: 可以同时提取多个属性: const { clientX, clientY } = event; 上述写法相当于: const clientX = event.clientX; const clientY = event.clientY; 语法更加简洁,适合处理多个属性时使用。 普通赋值 (const clientX = event.clientX;) 这是更传统的方式,逐个访问对象属性并赋值。 const clientX = event.clientX; 优点: 更直观,适合只提取单个属性时。 总结 两种写法最终效果是等价的,区别在于语法形式和适用场景: 如果只需要提取单个属性,使用 const clientX = event.clientX; 和 const { clientX } = event; 都可以。 如果需要提取多个属性,解构赋值更简洁且可读性更好。 例如: // 解构赋值 const { clientX, clientY } = event; // 传统方式 const clientX = event.clientX; const clientY = event.clientY; 这里遇到了新的问题,最初设置依靠的是百分比作为位置信息,在js操作中利用的是px,导致操作繁琐。 现在尝试把之前的代码进行一定的修改,在一番折腾后写出了以下代码: let offsetX = 0; let offsetY = 0; let nicoDivX =0; let nicoDivY =0; let ifDragging = false; //充当一个布尔变量,用于判断是否在抓取移动状态,let为局部变量 nicoNoteDiv.addEventListener("mousedown",(e) => {//"mousedown"即监测鼠标点下的事件。 ifDragging = true; nicoNoteDiv.style.cursor = "move"; offsetX = e.clientX; offsetY = e.clientY; //记录初始鼠标坐标(相对于左上角) nicoDivY = parseInt(nicoNoteDiv.style.top); nicoDivX = parseInt(nicoNoteDiv.style.right); //获取div的位置parseInt()会将字符串转化为数字(忽略最后的非数字部分) e.preventDefault(); //用来禁止鼠标拖拽时选中的功能 nicoNoteDiv.addEventListener('mousemove',(e)=>{if (ifDragging){nicoDragging(e)}}); //通过检测是否拖拽来启用拖拽函数 }); function nicoDragging(e) {//定义一个Dragging函数 语法:function 函数名(参数) {} const { clientX, clientY } = e; //获取当前鼠标坐标 nicoNoteDiv.style.top = `${nicoDivY+clientY-offsetY}px`; //${}表示在字符串中插入函数或变量,但要确保使用反引号`Code` nicoNoteDiv.addEventListener("mouseup",() =>{ifDragging = false;}); //松开鼠标,停止拖拽 }; 但是事情并没有那么简单,在松开鼠标后这个玩意还在动,原因如下: JavaScript 中,监听器(事件监听器)只要没有被明确移除或停止,就会一直监听事件。 当你使用诸如 addEventListener 方法在 DOM 元素上绑定一个事件监听器时,这个监听器会一直处于活动状态,直到满足以下条件之一: 手动移除监听器:可以使用 removeEventListener 方法来移除监听器。例如: const button = document.getElementById('myButton'); function handleClick(event) { console.log('Button clicked!'); } // 添加监听器 button.addEventListener('click', handleClick); // 移除监听器 button.removeEventListener('click', handleClick); 元素被移除:如果绑定了监听器的 DOM 元素被从 DOM 中移除,监听器也会随之停止。 一次性监听器:如果在添加监听器时指定了 { once: true },监听器会在首次触发后自动移除。例如: button.addEventListener('click', handleClick, { once: true }); 父监听器与子监听器的关系 如果你指的是在父元素上添加的事件监听器(比如通过事件冒泡机制监听子元素的事件),这种父监听器也会一直监听,除非明确移除。事件冒泡意味着子元素触发的事件会逐层向上传递到父元素,因此父监听器会接收到事件。比如: const parent = document.getElementById('parent'); // 父元素监听器 parent.addEventListener('click', (event) => { console.log('Parent clicked!', event.target); }); 无论是直接点击父元素,还是点击子元素,父元素的监听器都会被触发,除非: 你使用 stopPropagation() 来阻止冒泡; 或者通过 removeEventListener 手动移除父监听器。 总结 监听器会持续监听事件,直到手动移除或绑定的 DOM 元素被移除。 如果没有停止或移除,父监听器会一直监听其范围内的事件冒泡。 也就是说,由于mousemove在mousedown内导致mousedmove一直没法停止。把: nicoNoteDiv.addEventListener('mousemove',(e)=>{if (ifDragging){nicoDragging(e)}}); nicoNoteDiv.addEventListener("mouseup",() =>{ifDragging = false;}); 插在外面就行了。 最终成品: let offsetX = 0; let offsetY = 0; let nicoDivX =0; let nicoDivY =0; let ifDragging = false; //充当一个布尔变量,用于判断是否在抓取移动状态,let为局部变量 nicoNoteDiv.addEventListener("mousedown",(e) => {//"mousedown"即监测鼠标点下的事件。 ifDragging = true; offsetX = e.clientX; offsetY = e.clientY; //记录初始鼠标坐标(相对于左上角) nicoDivY = parseInt(nicoNoteDiv.style.top); nicoDivX = parseInt(nicoNoteDiv.style.right); //获取div的位置parseInt()会将字符串转化为数字(忽略最后的非数字部分) e.preventDefault(); //用来禁止鼠标拖拽时选中的功能 }); nicoNoteDiv.addEventListener('mousemove',(e)=>{ if(ifDragging){ const { clientX, clientY } = e; //获取当前鼠标坐标 nicoNoteDiv.style.top = `${nicoDivY+clientY-offsetY}px`; nicoNoteDiv.style.right = `${nicoDivX-clientX+offsetX}px`; //${}表示在字符串中插入函数或变量,但要确保使用反引号`Code ` } }); nicoNoteDiv.addEventListener("mouseup",() =>{ifDragging = false;}); //松开鼠标,停止拖拽 考虑到这个玩意可以应用到之前那个图标上,我们把它封装成一个函数。 由于光标太快会划出element,有时候mousedown事件会停止监听,改变策略把mousemove和mouseup监听对象改为document,即: document.addEventListener()。 这里有个新问题: Q.7如何在拖拽的同时不触发点击? 方法一:通过 mousemove 判断是否发生拖拽 可以在 mousedown 和 mousemove 中记录鼠标的移动距离,并在 mouseup 时判断是否是一次有效的拖拽操作。如果移动的距离超过一定阈值,就认为是拖拽而非点击。 let isDragging = false; const element = document.querySelector("#draggable"); element.addEventListener("mousedown", (e) => { isDragging = false; // 重置拖拽状态 const startX = e.clientX; const startY = e.clientY; const onMouseMove = (e) => { if (Math.abs(e.clientX - startX) > 5 || Math.abs(e.clientY - startY) > 5) { isDragging = true; } }; const onMouseUp = () => { document.removeEventListener("mousemove", onMouseMove); document.removeEventListener("mouseup", onMouseUp); }; document.addEventListener("mousemove", onMouseMove); document.addEventListener("mouseup", onMouseUp); }); element.addEventListener("click", (e) => { if (isDragging) { e.preventDefault(); // 如果是拖拽,不触发点击 } }); 方法二:使用 drag 和 dragstart 事件 如果使用 HTML5 的拖放 API,可以利用 drag 和 dragstart 来区分拖拽和点击。 let isDragging = false; const element = document.querySelector("#draggable"); element.addEventListener("dragstart", () => { isDragging = true; // 标记为拖拽 }); element.addEventListener("click", (e) => { if (isDragging) { e.preventDefault(); // 阻止点击事件 isDragging = false; // 重置状态 } }); 方法三:直接在 click 中判断拖拽状态 如果你的拖拽实现中没有其他复杂的状态,也可以简单地在 click 事件中检查。 let isDragging = false; element.addEventListener("mousedown", () => { isDragging = false; }); element.addEventListener("mousemove", () => { isDragging = true; // 如果发生移动,标记为拖拽 }); element.addEventListener("mouseup", () => { setTimeout(() => (isDragging = false), 0); // 延迟重置状态 }); element.addEventListener("click", (e) => { if (isDragging) { e.preventDefault(); } }); 方法四:CSS pointer-events 阻止点击 如果拖拽操作是通过 CSS 结合 JavaScript 实现,可以在拖拽时临时禁用 pointer-events。 const element = document.querySelector("#draggable"); element.addEventListener("mousedown", () => { element.style.pointerEvents = "none"; // 禁止点击 }); element.addEventListener("mouseup", () => { setTimeout(() => { element.style.pointerEvents = "auto"; // 恢复点击 }, 0); }); 总结 最推荐的方法是 方法一,结合鼠标的移动距离判断是否是拖拽,因为它适用于大多数拖拽实现场景,且与 HTML5 拖放 API 或 CSS 的依赖性较低。 这里采用方法四,而 mouseup 的监听对象一定为 document 才有效,最后将right改为更易操作的的left,封装后的函数如下: function letWeDrag(dragDiv){ let offsetX = 0; let offsetY = 0; let nicoDivX =0; let nicoDivY =0; let ifDragging = false; //充当一个布尔变量,用于判断是否在抓取移动状态,let为局部变量 dragDiv.addEventListener("mousedown",(e) => {//"mousedown"即监测鼠标点下的事件。 ifDragging = true; offsetX = e.clientX; offsetY = e.clientY; //记录初始鼠标坐标(相对于左上角) nicoDivY = parseInt(dragDiv.style.top); nicoDivX = parseInt(dragDiv.style.left); //获取div的位置parseInt()会将字符串转化为数字(忽略最后的非数字部分) e.preventDefault(); //用来禁止鼠标拖拽时选中的功能 }); document.addEventListener('mousemove',(e)=>{ if(ifDragging){ const { clientX, clientY } = e; //获取当前鼠标坐标 dragDiv.style.top = `${nicoDivY+clientY-offsetY}px`; dragDiv.style.left = `${nicoDivX+clientX-offsetX}px`; //${}表示在字符串中插入函数或变量,但要确保使用反引号`Code` dragDiv.style.pointerEvents = "none"; //禁止单击,防止拖拽同时点击。 } }); document.addEventListener("mouseup",() =>{ ifDragging = false; dragDiv.style.pointerEvents = "auto"; // 恢复点击 }); //松开鼠标,停止拖拽 } 由于将right换用left,为了使图标继续在右侧,我们应该获取屏幕的宽度。 Q.8:如何获取屏幕的宽度?在 JavaScript 中,可以使用以下方法获取屏幕的 像素信息: 1. 获取屏幕的宽度和高度(window.screen) 通过 window.screen 对象,可以获取屏幕的物理分辨率: console.log("屏幕宽度:" + window.screen.width + "px"); console.log("屏幕高度:" + window.screen.height + "px"); window.screen.width:屏幕的宽度(像素)。 window.screen.height:屏幕的高度(像素)。 2. 获取可用工作区域的尺寸 window.screen.availWidth 和 window.screen.availHeight 用于获取屏幕除去任务栏或工具栏后的可用尺寸: javascript复制代码console.log("可用宽度:" + window.screen.availWidth + "px"); console.log("可用高度:" + window.screen.availHeight + "px"); 3. 获取浏览器窗口的尺寸 通过 window.innerWidth 和 window.innerHeight 可以获取浏览器窗口的内容区域大小(不包含工具栏或边框): javascript复制代码console.log("窗口宽度:" + window.innerWidth + "px"); console.log("窗口高度:" + window.innerHeight + "px"); 4. 获取设备像素比(devicePixelRatio) window.devicePixelRatio 返回设备像素比(DPR),表示物理像素与 CSS 像素的比值: console.log("设备像素比:" + window.devicePixelRatio); 例如: 如果 devicePixelRatio = 2,表示 1 个 CSS 像素对应 2 个物理像素。 通常高分辨率设备(如 Retina 屏幕)会有较高的 DPR 值。 5. 获取页面滚动的像素位置 通过 window.scrollX 和 window.scrollY 可以获取页面的水平和垂直滚动位置: console.log("水平滚动位置:" + window.scrollX + "px"); console.log("垂直滚动位置:" + window.scrollY + "px"); 6. 获取元素的大小和位置 如果要获取某个 HTML 元素的宽度和高度,可以使用 getBoundingClientRect(): const element = document.querySelector("#myElement"); const rect = element.getBoundingClientRect(); console.log(`元素宽度:${rect.width}px, 高度:${rect.height}px`); console.log(`元素位置:左=${rect.left}px, 上=${rect.top}px`); 总结 屏幕尺寸:window.screen.width 和 window.screen.height 可用区域:window.screen.availWidth 和 window.screen.availHeight 浏览器窗口:window.innerWidth 和 window.innerHeight DPR:window.devicePixelRatio 滚动位置:window.scrollX 和 window.scrollY 这里我们用到window.innerWidth就可以了。 这里我们还要保证窗口调节时,它的位置能一同调节,用以下函数,达到这一效果: window.top.addEventListener('resize', () => {//监听顶层窗口调节大小事件 const element = document.getElementById("nicoBt"); const elementWidth = element.offsetWidth; const viewportWidth = window.innerWidth; element.style.left = (viewportWidth - elementWidth-10) + "px"; nicoNoteDiv.style.top = `${parseInt(nicoButton.style.top)}px`; nicoNoteDiv.style.left = `${parseInt(nicoButton.style.left)-parseInt(nicoNoteDiv.style.width)}px`; }); 2024/12/12 ②拖拽调节大小只需要在CSS中添加: resize: both;/*允许元素在x、y两个方向上调整大小*/ overflow: auto;/*显示滚动条*/ 就可以实现简单的调整大小,参考css resize-CSDN博客。 注意的是,能正常调整的条件是:CSS样式中,元素的位置描述使用 top 与 left。 但是我们要让它有最大最小的限制,思路是通过监听鼠标,通过JS来限制大小。 document.addEventListener("mouseup",()=>{ if(parseInt(nicoNoteDiv.style.width)<200){ nicoNoteDiv.style.width="200px";}; if(parseInt(nicoNoteDiv.style.height)<40){ nicoNoteDiv.style.height="40px";} }); ③组合起来!由于这两者判定位置重合,因此我们应该使用一定的嵌套。 这时我们就要对 UI 进行一定的规划:也就是流出上方一条允许拖拽,其余部分无法拖拽。 让外层元素调节大小,内层元素负责拖动,这样一个东西就做好了! 8、引入 VditorJS 与 CSS 的引入终于捣鼓完这个框框了,接下来我们要在这个容器中引入文本编辑器。 使用开源项目 Vditor 来作为文本编辑器 ,根据开发者文档尝试在 HTML 中引入 vditor 的 JS 与 CSS 。 <!-- ⚠️生产环境请指定版本号,如 https://unpkg.com/vditor@x.x.x/dist... --> <link rel="stylesheet" href="https://unpkg.com/vditor/dist/index.css" /> <script src="https://unpkg.com/vditor/dist/index.min.js"></script> 把这行代码写入中: document.querySelector("head").insertAdjacentHTML("afterbegin",headVditorCode); Q.9:之前讲过用@require加载脚本,这里可以那样做吗? 可以,且更推荐使用@require的方式,因为如果你在插入资源后立即使用 Vditor,可能会因为资源未加载完成而报错,并且动态插入 HTML 字符串不够直观,可能会增加代码阅读和维护的难度。 但是**@require只能用来加载 JS 而不能用于 CSS **使用GM_addStyle可以解决这一问题。 // ==UserScript== // @name Vditor Integration with CSS // @namespace http://tampermonkey.net/ // @version 1.0 // @description Integrate Vditor // @author Your Name // @match *://*/* // @require https://cdn.jsdelivr.net/npm/vditor/dist/index.min.js // @grant GM_addStyle // ==/UserScript== // 使用 GM_addStyle 插入 CSS 样式 GM_addStyle(` @import url('https://cdn.jsdelivr.net/npm/vditor/dist/index.css'); `); 如果你坚持使用动态插入方式,建议优化为分步加载,避免时序问题: // 动态加载 CSS var link = document.createElement('link'); link.rel = 'stylesheet'; link.href = 'https://unpkg.com/vditor/dist/index.css'; document.head.appendChild(link); // 动态加载 JS var script = document.createElement('script'); script.src = 'https://unpkg.com/vditor/dist/index.min.js'; script.onload = function () { // 确保 Vditor 加载完成后再初始化 new Vditor('editor', { height: 300, placeholder: 'Write something...', }); }; document.head.appendChild(script); 这种方式更易维护,且避免 HTML 字符串操作的潜在问题。 Vditor 的初始化为了理解如何引入 Vditor ,我需要花一点时间来对文档进行理解: 首先,Vditor 定义了一个名为 Vditor 的类。 这个类包含若干属性,最主要的是 id 和 options。 我们首先要创建一个这个”类“的”实例“,可以理解为所谓”实例“就是一个这个”类“的变量。 创建实例的语法为: new 类名(参数1,参数2。。。) 在这个Vditor就应该写成:new Vditor(id,options,....) 这个id是一个字符串,而这个 options 里面包含了许多属性,我们把这些属性用大括号括起来。 另外 options 还有诸如 options.toolbar options.counter 的子属性他们的书写方式文档中也有写。 此外,我们这个类中还有一些”方法“methods供我们操作这些实例。 第一次尝试引入: const vditor = new Vditor("nicoVditor",{ placeholder: 'Write something here...', toolbar: ['emoji', 'headings', 'bold', 'italic', 'strike', 'link', 'list'], }) 显示 nicoVditor Not found ,推断是初始化代码在 nicoVditor 被添加之前就已经运行,通过调整代码逻辑,成功解决该问题。 再次运行显示:GET https://unpkg.com/vditor@3.10.8/dist/js/i18n/zh_CN.js net::ERR_ABORTED 404 (Not Found) 怀疑是脚本无权访问此文件,在元属性中添加// @require https://unpkg.com/vditor@3.10.8/dist/js/i18n/zh_CN.js成功运行。 接下来就是简单的调试一下! 2024/12/13 9、尝试与修复 CDN 被 CSP 拦截的问题(待解决)发现无法在 Github 中初始化,询问AI后得到以下解答: 这个错误消息表示,浏览器拒绝加载样式表 https://cdn.jsdelivr.net/npm/vditor/dist/index.css,因为它违反了当前页面的内容安全策略(Content Security Policy,CSP)指令。具体来说,CSP 指令 style-src 'unsafe-inline' github.githubassets.com 限制了可以加载样式表的来源,而 jsdelivr.net 不在允许的来源列表中。 可能导致该错误的原因 严格的内容安全策略:GitHub 页面设置了严格的 CSP,限制了可以加载样式表的来源,以提高安全性。 外部样式表来源不被允许:当前 CSP 只允许从 github.githubassets.com 加载样式表,而不允许从 jsdelivr.net 加载。 搜索方案,发现某些项目可以绕过这一限制:guansss/webpack-monkey:一个 webpack 插件,用于使用现代工作流程开发您的用户脚本,具有 HMR、元生成等功能。 使用 webpack-monkey用 npm 或 yarn(install 替换为 add) 均可。(超时挂梯子,给命令台走代理) 对该项目进行安装与初始化:npm init -y npm install webpack webpack-cli webpack-dev-server webpack-monkey --save-dev 创建以下目录:. ├── dist │ └── hello.user.js ├── src │ ├── index.js │ └── meta.js ├── webpack.config.js └── package.json 编写脚本: 在 src/index.js 中编写脚本逻辑(不包含元数据) GM_log("Hello world!"); if (module.hot) { module.hot.monkeyReload(); } 在 src/meta.js 中定义脚本的元数据 module.exports = { name: "Hello world", version: "1.0.0", match: ["*://example.com/"], }; 在 webpack.config.js 中配置 webpack-monkey const path = require("path") const { monkey } = require("webpack-monkey") // module.exports = monkey({ entry: './src/index.js',//输入文件 output: { path: path.resolve(__dirname, "dist"),//输出目录 }, }) 配置构建脚本在 package.json 中添加构建脚本,相当于添加了命令台指令: { "scripts": { "dev": "webpack serve --mode development",//调试工具 "build": "webpack --mode production"//生成工具 } } 生成用户脚本npm build 会在 dist 中生成用户脚本。 尝试绕过CSPwebpack-monkey 的原理是:通过将需要外部加载的脚本与CSS样表与油猴脚本一起打包到一个文件,从而解决了 CSP 的问题。 首先,安装用于打包 CSS 与 JS 的 loader: npm install css-loader style-loader --save-dev#用于加载CSS npm install script-loader --save-dev#用于加载JS 在 Webpack 配置中,添加相关配置: const path = require("path"); const { monkey } = require("webpack-monkey"); const TerserPlugin = require("terser-webpack-plugin"); // 引入 terser-webpack-plugin module.exports = monkey({ entry: './src/index.js',//输入文件 output: { path: path.resolve(__dirname, "dist"),//输出目录 }, module: { rules: [ { test: /\\.css$/i, // 匹配所有 .css 文件 use: ["style-loader", "css-loader"], // 使用 style-loader 和 css-loader 处理 }, { test: /external-script\\.js$/, // 匹配外部 JS 脚本 use: "script-loader", // 使用 script-loader 打包 }, ], }, }); 将脚本和CSS下载到本地后,在 index.js 文件中引入本地的脚本: import "./CSS/index.css"; import "./JS/index.min.js"; 运行后生成了打包后的脚本,但无法运行,反思后认为原因如下: webpack打包的js中又通过字符串操作引用了新的URL,而新的URL仍然不能绕过CSP。 并且不同的 JS 之间的相互依赖限制了运行顺序,运行顺序不当也会出现这种情况。 替代的解决方案 手动追踪所有的URL将他们修改并打包。缺点是耗时长且可维护性极低。(不可行) 使用拓展程序来手动禁用 CSP。 无法加载的其他未知原因与局限性分析在某些页面不是因为 CSP 而无法初始化 Vditor (经过测试,所有搜索引擎的“搜索结果”页面都不能正常载入)原因暂时未知。 这类问题暴露出了油猴作为脚本运行器的局限性,或许我们可以开发浏览器插件,而不是油猴脚本。 总结就是,关于这个问题: 失敗した失敗した失敗した失敗した失敗した 失敗した失敗した失敗した失敗した失敗した 失敗した失敗した失敗した失敗した失敗した 失敗した失敗した失敗した失敗した失敗した 失敗した失敗した失敗した失敗した失敗した あたしは失敗した失敗した失敗した失敗した 失敗した失敗した失敗した失敗した失敗した 失敗した失敗した失敗した失敗した失敗した 2024/12/13 10、储存编辑的文本参考:HTML5 Web IndexedDB 数据库 | 菜鸟教程 Vditor 提供了把文件导出到本地的功能,但不能实现将笔记保存在当前网页的功能。 由于浏览器的网页存在严格的沙箱机制,因此我们无法利用浏览器脚本操作本地文件,自然也就不能利用脚本把文件保存在本地。 但是浏览器提供了 IndexedDB 这一机制,允许我们储大量结构化数据。它是异步的,可以存储较大的数据对象,适合需要存储大量数据或进行复杂查询的场景。因此我们甚至可以实现自动保存,历史版本管理的功能。 获取文本内容Vditor 提供的工具中为我们提供了获取文本内容的 API: 方法 说明 exportJSON(markdown: string) 根据 Markdown 获取对应 JSON getValue() 获取 Markdown 内容 getHTML() 获取 HTML 内容 创建 IndexedDBconst request = indexedDB.open("VditorHistoryDB", 1);//创建版本号为1的IndexedDB let db; 初始化: request.onupgradeneeded = e => { db = e.target.result; //表示成功打开的数据库实例。 if (!db.objectStoreNames.contains("history")) { db.createObjectStore("history", { keyPath: "id" }); //如果没有创建对象储存,则创建一个"history"对象储存。 //而每一条主字段的标识为id,也就是我们可以在之后给每个字段添加id,作为标识。IndexedDB 会根据这个属性对记录进行索引。 } }; 这里的onupgradeneeded代表数据库初次创建或版本号更新时执行函数。 **db.objectStoreNames**:一个类似数组的对象,列出了当前数据库中所有已存在的对象存储(表)。 而**contains("history")**:检查是否已存在名为 "history" 的对象存储。 如果数据库已经创建了,则: request.onsuccess = e => { db = e.target.result; }; onsuccess表示成功加载执行函数。 出现的问题:onsuccess无法正确触发 既不出发onsuccess也不触发onerror,只能触发onupgradeneeded,且控制台没有输出,原因暂时未知,所以无法修复。 这里采用替代方案每次进入都改变版本号来触发onupgradeneeded。 将内容保存至数据库这里使用数据库实例的 transaction() 方法创建一个事务: const transaction = db.transaction(storeNames, mode); **storeNames**: 可以是一个字符串(单个对象存储的名称)或数组(多个对象存储的名称)。 决定事务可以操作哪些对象存储。例如,"history" 表示事务将操作名为 "history" 的存储。 **mode**: 事务的模式,定义了可以执行的操作: "readonly":只读事务,只允许读取数据。 "readwrite":读写事务,允许读取和修改数据。 通过 transaction.objectStore() 获取特定的存储,操作其中的数据。 function saveContent() { const content = nicoVditor.getValue();//获取 Markdown 内容 const timestamp = Date.now(); // 时间戳作为 ID const transaction = db.transaction("history", "readwrite");//创建一个操作 "history" 存储的读写事务。 const store = transaction.objectStore("history");// 获取 "history" 对象存储 store.put({ id: timestamp, content: content, savedAt: new Date().toLocaleString() }); //向"history" 存储中放入一个id为时间戳,内容为 Markdown 内容,保存的时间为当前时间的内容。 //savedAt 是一个字段,用于记录保存的时间。而new Date().toLocaleString() 是 JavaScript 的方法,返回当前时间的本地化格式(例如 2024/12/15 10:30:45) transaction.oncomplete = () => { alert("内容已保存!"); }; transaction.onerror = (event) => { console.error("保存失败", event.target.error); }; } 最后在工具栏插入一个按钮: { name: 'nicoSave', tipPosition: 's', tip: '保存到浏览器', className: 'right', icon: ``, click () {saveContent()},} 出现的问题:getValue()未定义(已解决) 原因是无法引入method脚本文件,引入后问题依旧存在,替代方案: document.querySelector("#nicoVditor > div.vditor-content > div.vditor-ir").innerHTML;//获取 HTML 内容 出错原因:在 saveContent() 函数中 Vditor 未被定义 解决方法:将 Vditor 作为参数传入函数中 返回历史版本 function showHistory(ifFirst) { const transaction = db.transaction("history", "readonly");//创建读取事务的实例 const store = transaction.objectStore("history");//获取对象储存的实例 const request = store.getAll(); request.onsuccess = (event) => { const history = event.target.result; // 确保在请求成功后访问 result 属性 }; history.sort((a, b) => b.id - a.id);// 按 ID(即时间戳)降序排序 if(ifFirst){document.querySelector("#nicoVditor > div.vditor-content > div.vditor-ir").innerHTML = history[0].content;ifFirst=true;} else{return history;} } 这里直接使用修改.innerHTML导致返回保存后无法被继续编辑,改用setValue()重构代码 点击之后呼出弹窗 function showHistoryDialog(history) { // 如果已有弹窗,先移除 //const existingDialog = document.querySelector("#history-dialog"); //if (existingDialog) existingDialog.remove(); // 创建弹窗容器 const dialog = document.createElement("div"); dialog.id = "history-dialog"; dialog.style.position = "fixed"; dialog.style.top = "50%"; dialog.style.left = "50%"; dialog.style.transform = "translate(-50%, -50%)"; dialog.style.background = "#fff"; dialog.style.border = "1px solid #ddd"; dialog.style.padding = "15px"; dialog.style.boxShadow = "0px 2px 10px rgba(0, 0, 0, 0.3)"; dialog.style.zIndex = "1000"; dialog.style.maxHeight = "300px"; dialog.style.overflowY = "auto"; // 弹窗标题 const title = document.createElement("h3"); title.innerText = "历史记录"; title.style.marginTop = "0"; dialog.appendChild(title); // 遍历历史记录,添加按钮 history.forEach((item, index) => { const button = document.createElement("button"); button.innerText = `${index + 1}. ${item.savedAt}`; button.style.display = "block"; button.style.marginBottom = "10px"; button.style.width = "100%"; // 点击按钮时写入内容 button.onclick = () => { document.querySelector("#nicoVditor > div.vditor-content > div.vditor-ir").innerHTML = item.content; console.log(`已恢复历史记录: ${item.savedAt}`); dialog.remove(); // 关闭弹窗 }; dialog.appendChild(button); }); // 关闭按钮 const closeButton = document.createElement("button"); closeButton.innerText = "关闭"; closeButton.style.marginTop = "10px"; closeButton.style.width = "100%"; closeButton.onclick = () => dialog.remove(); dialog.appendChild(closeButton); // 将弹窗插入到页面 document.body.appendChild(dialog); } 但是因为 showHistory 函数是异步(允许它之后的代码先运行)的,而你在调用 showHistory 函数时期望立即获得结果。你需要确保在 request.onsuccess 事件处理程序中处理结果。 Q10.异步执行的函数如何获取返回值? 在 JavaScript 中,异步函数的返回值无法直接通过同步方式获取,因为异步操作(如网络请求、定时器等)需要时间完成。因此,需要通过以下几种方法来获取异步函数的返回值: Promise 和 then() 当异步函数返回一个 Promise 对象时,可以通过 .then() 方法来处理返回值。 示例代码 function asyncFunction() { return new Promise((resolve) => { setTimeout(() => { resolve("异步返回值"); }, 1000); // 模拟异步操作,1秒后返回 }); } // 使用 then() 获取返回值 asyncFunction().then((result) => { console.log("获取到的返回值:", result); }); async/await async/await 是对 Promise 的语法糖,使得异步代码更像同步代码,更易于理解和编写。 示例代码 async function asyncFunction() { return new Promise((resolve) => { setTimeout(() => { resolve("异步返回值"); }, 1000); // 模拟异步操作 }); } // 使用 async/await 获取返回值 async function getValue() { const result = await asyncFunction(); console.log("获取到的返回值:", result); } getValue(); 注意: await 只能在 async 函数 中使用。 await 会暂停当前 async 函数的执行,直到异步操作完成。 回调函数 将一个回调函数作为参数传入异步函数,在异步操作完成后调用该回调函数并传入返回值。 示例代码 function asyncFunction(callback) { setTimeout(() => { const value = "异步返回值"; callback(value); // 调用回调函数,传入返回值 }, 1000); } // 使用回调函数获取返回值 asyncFunction((result) => { console.log("获取到的返回值:", result); }); 结合 async/await 和 Promise 的例子 当你调用一个异步函数,返回的是 Promise,你可以用 async/await 来等待它的完成。 示例代码 function fetchData() { return new Promise((resolve) => { setTimeout(() => resolve("返回数据成功"), 1000); }); } async function getData() { const result = await fetchData(); console.log("最终获取的数据:", result); } getData(); 立即执行异步函数 (IIFE) 有时你需要在代码块内立即调用 async 函数,可以使用 **立即执行函数表达式 (IIFE)**。 示例代码 (async () => { const result = await asyncFunction(); console.log("立即执行异步函数的返回值:", result); })(); 删除历史记录使用 delate 方法删除历史记录: const request = indexedDB.open("VditorHistoryDB", dbVersion); request.onsuccess = (event) => { const db = event.target.result; const transaction = db.transaction("history", "readwrite"); const store = transaction.objectStore("history"); const deleteRequest = store.delete(recordId); // 替换 recordId 为你要删除的记录的 ID deleteRequest.onsuccess = () => { console.log("记录已删除"); }; deleteRequest.onerror = (event) => { console.error("删除记录失败", event.target.error); }; }; 2024/12/19 三、完成大概耗时十天时间,我们从无到有完成了这个脚本的编写。 事实上,我认为这次尝试,是利用 AI 进行学习的一种方式。 过去人们大部分情况下只能从前到后,一步步到达想要的结果,但是 AI 让我们可以从后向前,并且在这个过程中一点点弄清楚这个东西的原理,这一点是以往人所达不到的。 最后我希望我自己可以继续维护这个脚本,不断为其添加新的功能。 import { init } from 'https://unpkg.com/@waline/client@v2/dist/waline.mjs'; init({ el: '#waline', serverURL: 'https://waline-ccr39.netlify.app/.netlify/functions/comment', reaction: [ 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_heart_eyes.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_joy.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_consider.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_sob.png', ], emoji: [ '//unpkg.com/@waline/emojis@1.1.0/bilibili', '//unpkg.com/@waline/emojis@1.1.0/weibo', '//unpkg.com/@waline/emojis@1.1.0/qq', ] });","raw":null,"content":null,"categories":[{"name":"技术","slug":"技术","permalink":"http://ccr39.github.io/categories/%E6%8A%80%E6%9C%AF/"}],"tags":[{"name":"编程","slug":"编程","permalink":"http://ccr39.github.io/tags/%E7%BC%96%E7%A8%8B/"},{"name":"Web","slug":"Web","permalink":"http://ccr39.github.io/tags/Web/"},{"name":"脚本","slug":"脚本","permalink":"http://ccr39.github.io/tags/%E8%84%9A%E6%9C%AC/"}]},{"title":"Git入门(三)提交到远程库","slug":"git-3","date":"2024-12-13T07:38:00.000Z","updated":"2024-12-13T08:01:45.682Z","comments":true,"path":"技术/git-3/","link":"","permalink":"http://ccr39.github.io/%E6%8A%80%E6%9C%AF/git-3/","excerpt":"","keywords":null,"text":"往期文章:Git 的入门(一):Git 的基本概念以及 Git 命令行的使用、Git 的入门(二):Git 的常用命令 | CCR39のLazyNest 1、在 Github 上创建一个远程仓库 点击 New 创建,之后取个名字。拉到最下方直接创建。 2、在本地关联到远程仓库保证本地 git 已经配置好,在已经初始化的本地文件夹的命令台输入: git remote add origin git@github.com:远程仓库目录.git 这里的远程仓库目录就是用户名/仓库名 例如: git remote add origin git@github.com:ccr39/NicoNote.git 3、把本地仓库提交到远程仓库先把所有文件提交到本地库: git add . git commit -m "注释" 再提交到远程仓库: git push -u origin 分支名 默认分支一般为master或main。 上面的 origin 就是远程仓库的意思。 4、其他指令 将远程仓库的文件拷贝到本地文件夹 git clone 仓库地址 从远程获取最新版本到本地 git fetch origin 分支名 import { init } from 'https://unpkg.com/@waline/client@v2/dist/waline.mjs'; init({ el: '#waline', serverURL: 'https://waline-ccr39.netlify.app/.netlify/functions/comment', reaction: [ 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_heart_eyes.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_joy.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_consider.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_sob.png', ], emoji: [ '//unpkg.com/@waline/emojis@1.1.0/bilibili', '//unpkg.com/@waline/emojis@1.1.0/weibo', '//unpkg.com/@waline/emojis@1.1.0/qq', ] });","raw":null,"content":null,"categories":[{"name":"技术","slug":"技术","permalink":"http://ccr39.github.io/categories/%E6%8A%80%E6%9C%AF/"}],"tags":[{"name":"工具","slug":"工具","permalink":"http://ccr39.github.io/tags/%E5%B7%A5%E5%85%B7/"},{"name":"编程","slug":"编程","permalink":"http://ccr39.github.io/tags/%E7%BC%96%E7%A8%8B/"}]},{"title":"只身陷入心理治疗骗局!!深扒“SCIO全科生物反馈测疗仪”与“心理AI智能检测”底裤。","slug":"SCIO","date":"2024-12-13T07:14:00.000Z","updated":"2024-12-13T07:15:20.658Z","comments":true,"path":"生活/SCIO/","link":"","permalink":"http://ccr39.github.io/%E7%94%9F%E6%B4%BB/SCIO/","excerpt":"","keywords":null,"text":"转载于本人知乎:只身陷入心理治疗骗局!!深扒“SCIO全科生物反馈测疗仪”与“心理AI智能检测”底裤。 - 知乎 故事的开始: 本人去往医院作心理治疗,主治医生拿出一个小条,在”AI 心理治疗-情绪“上画上一个勾勾。我心想:AI 治疗?现在都这么高级了吗?随后便被告知要治疗780元的诊断费用。。。。算了,尝试高科技治病,能治好不嫌贵。开始治疗时,医生在我四肢和头部处绑上检测用的软环,在一旁躺下,接下来就开始不断点击电脑。由于没有任何感觉,我甚至不知道治疗在什么时候开始的,本人早上起的很早,于是直接睡下了。大概四十分钟后,大夫告诉说可以起来了,我还心想,这到底是发生了什么,完全没有感觉就完成治疗了。 大概就长这个样子,旁边有个供躺着的沙发,另外软环用线连接着仪器 等到打印报告时直接让我傻眼了:报告上赫然写着“SCIO 数字治疗”结果单底下不光列出了“情绪心理指数”、“第一次治疗记录”最逆天的是包括72项“情绪与心理反应性细项”,它明确的列出了72项有关心理的指标,并对每一项指标进行了定量化与说明。由于是在专业医院做的专业检测,我也没有多想什么,把报告给大夫看了看,大夫根据报告中的内容对我进行了诊断。 诸如此类项目,每一个都有明确的指标 揭穿” AI智能检测 “的真像等回到家我才意识到问题的不对: 首先,无论是检测还是治疗,都需要一定介质来采集生物信息,之前经颅磁利用的是磁场,而这个“AI治疗”只使用几个环,它是通过什么采集信息,还能保证信息如此精确。(既分类、又定量) 其次,在网络上搜索“AI治疗”出现的信息均为使用大预言模型进行治疗,这个“AI治疗”到底哪里用到AI了。 然后,大夫根据报告给出的治疗咨询疑似利用了巴纳姆效应(Barnum effect),说白了就是得出的结论很笼统,类似算命师傅解卦。 于是,我在网络上查询 SCIO 相关字样,但是几乎没有得到任何相关的信息。换用“SCIO生物反馈仪”作为关键词在中文互联网上搜索,终于查询到了知乎上的一篇文章,请先阅读该文章: 号称不采一滴血就能检测上万种指标的“SCIO生物反馈仪”,到底是啥货? 除此之外,只有寥寥无几的几篇关于这个仪器的信息。 有趣的是,当我在知乎、抖音上输入SCIO生物反馈仪时,搜索框中的相关搜索选项中出现了: “SCIO生物反馈仪 智商税 ”“ SCIO生物反馈仪 有用吗”相关字样。(看来被坑的不止我一个) 总结上述文章与已知消息我们得到以下真相: 首先,在官网上对 SCIO 全科生物反馈测疗仪的描述是: 依据量子物理学和拓扑学的原理,通过非侵入性的无痛、无副作用的电化学极谱分析和测量,通过计时电势分析法等运算方法,检测身体11000多项指标,从而获得早期风险提示,是一种集健康监测与干预调理为一体的具有国际先进水平的医疗器械,仪器具有极高的灵敏度,能检测到0.2µV极其微弱的人体生物能变化,从而精确的捕捉到任何早期疾病风险,提早预防。20多年来获得欧盟,美国,澳大利亚,加拿大,韩国等众多国家食药局的认证,为很多国际知名人士指定专项健康管理系统,2008年奥运会指定合作项目,为奥运冠军保驾护航。 事实上,这个 SCIO 全科生物反馈测疗仪,是由一个名为Willian C. Nelson的美国人发明的机器,最初发明该机器时涉及虚假宣传 ,使其本人遭受逮捕,被迫逃往匈牙利(记住这个,后面要考)。之后由于FDA通过医疗器械调整法案,大大降低注册难度,SCIO 成功注册,但之后,有微软软件工程师在查看其后台数据库后,指出其检查结果是随机给出的。(关于详情信息及来源,在上述文章中有提到) 国外的版本 而国内的 SCIO 全科生物反馈测疗仪,是在外国版本中发展而来,但是国内的炒作鬼才将其包装成了现在更加高大上的样子,并且卖出高价。 我们找到了这个机器的[注册号:国械注进20162093114](https://zhuanlan.zhihu.com/p/12090143389/。发现该器械最初应该在2016年注册,而在2022年进行了批准。我们可以看到,注册人为**匈牙利某公司人员,印证了国内外SCIO为同源。** 产品的注册信息,注册号:国械注进20162093114 但事实上,这个在这之前这个产品还有另一个注册号:国食药监械(进)字2012第2213148号(产品最早在2012年引入,08年奥运会一事显然不合理)再变更信息中,代理人名称变更为北京瑞蜜达国际生物科技有限公司。这样,两者就基本可以对上来了。 国食药监械(进)字2012第2213148号 反思与总结在查询资料过程中我们可以发现一个有意思的事情:那就是”国械注进20162093114“应该是16年九月份就发布了注册申请,而直到22年才再次被批准,这是为什么? 直到我看到,一个名为犀贝众齿联的公司(SCIO国内的新代理商)发布的文章: SCiO这款产品真的有他们自己说的这么强大么? 里面提到: 犀贝,作为一直以助力大健康行业的发展为理念,这次与山西省合作的「SCIO无创生物反馈人体检测」项目,就是人工智能与医疗深度融合的一项。 再结合我自己的经历才终于明白:合着是把好几年前的冷饭顺着AI的东风再炒起来,所以归根到底这个系统根本与AI毫无关系。而为了获批,这之中的利益关系我们又不得而知。 但是,仅仅是运用在心理治疗上也就没什么了,最令人害怕的事情是:本人再抖音上看到了癌症将患者使用该仪器的视频,深感痛心。 总的来说,本人算是交了次智商税。而和我去同一门诊的人不在少数。很难想象这种在网上都很难查到资料的器械被我碰到了。。。写这篇文章只希望能为中文互联网增加一点资料,至少不是什么都查不到了。。。 import { init } from 'https://unpkg.com/@waline/client@v2/dist/waline.mjs'; init({ el: '#waline', serverURL: 'https://waline-ccr39.netlify.app/.netlify/functions/comment', reaction: [ 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_heart_eyes.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_joy.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_consider.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_sob.png', ], emoji: [ '//unpkg.com/@waline/emojis@1.1.0/bilibili', '//unpkg.com/@waline/emojis@1.1.0/weibo', '//unpkg.com/@waline/emojis@1.1.0/qq', ] });","raw":null,"content":null,"categories":[{"name":"生活","slug":"生活","permalink":"http://ccr39.github.io/categories/%E7%94%9F%E6%B4%BB/"}],"tags":[{"name":"杂谈","slug":"杂谈","permalink":"http://ccr39.github.io/tags/%E6%9D%82%E8%B0%88/"}]},{"title":"Restart:My Blog","slug":"2024-12-13","date":"2024-12-13T06:19:00.000Z","updated":"2024-12-13T07:11:02.286Z","comments":true,"path":"生活/2024-12-13/","link":"","permalink":"http://ccr39.github.io/%E7%94%9F%E6%B4%BB/2024-12-13/","excerpt":"","keywords":null,"text":"有关为什么很久没有维护博客: 学业需要,没有时间来进行维护。 域名过期,续费域名需要一定费用。 原来的本地环境丢失,需要重新搭建环境。 懒。 有关博客有那些功能失修: 域名无法使用,因此沿用 Github 静态代理的网址:https://ccr39.github.io/ 部分图片失效。 部分内容或资源失效。 静态代理网络原因可能导致卡顿或部分时间上不去。 听歌系统有时抽风显示不出来。 有关博客的维修: 使用科学上网可以得到最佳的体验。 评论系统由于部署在 vercel 上,而 vercel 被墙,因此重新部署至 netlify 目前已经可以正常使用。 重新替代了部分图片。 目前大部分功能已经恢复。 import { init } from 'https://unpkg.com/@waline/client@v2/dist/waline.mjs'; init({ el: '#waline', serverURL: 'https://waline-ccr39.netlify.app/.netlify/functions/comment', reaction: [ 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_heart_eyes.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_joy.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_consider.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_sob.png', ], emoji: [ '//unpkg.com/@waline/emojis@1.1.0/bilibili', '//unpkg.com/@waline/emojis@1.1.0/weibo', '//unpkg.com/@waline/emojis@1.1.0/qq', ] });","raw":null,"content":null,"categories":[{"name":"生活","slug":"生活","permalink":"http://ccr39.github.io/categories/%E7%94%9F%E6%B4%BB/"}],"tags":[{"name":"杂谈","slug":"杂谈","permalink":"http://ccr39.github.io/tags/%E6%9D%82%E8%B0%88/"}]},{"title":"图床的使用与推荐","slug":"picbed","date":"2023-01-20T12:21:32.000Z","updated":"2024-12-13T05:57:34.291Z","comments":true,"path":"技术/picbed/","link":"","permalink":"http://ccr39.github.io/%E6%8A%80%E6%9C%AF/picbed/","excerpt":"","keywords":null,"text":"一、了解图床引用百度的话: 图床就是专门用来存放图片,同时允许你把图片对外连接的网上空间。 简单来说,我们在网上看到的所有的信息都是要储存在服务器里面的,那么允许我们上传图片,并且生成网上链接供给他人观看此图片的空间,就叫做图床。 图床分为很多种,你可以把图片放在自己的服务器/云服务器中,并生成链接。也可以使用他人提供的服务器生成的链接,服务器的不同也会造成图片的访问速度不同,同时可能还存在一些大小限制。 二、使用图床图床有什么用?要知道,有的时候部分网页时不支持上传图片的,如某些论坛,他们不支持图片上传,因此你需要预先将图片上传到其他服务器,并生成图床链接。 还有的时候,如你在写 web 脚本,博客,此时的图片信息一般也使用图床。 下面我将演示图片的上传,以及生成相应链接。 1、首先,我们打开提供图片上传的网站(图床网站,这里以 sm.ms 为例) 2、按照提示注册账号3、上传图片直接将图片拖动到页面中,或预览文件,并选择图片。 接下来点击上传。 4、获取图片链接上传成功后在下方点击复制链接即可。 这里大家如果不明白复制哪一个,就先点击上面的 Image URL 再复制出现的链接即可。 这只是 sm.ms 的用法,其他的图床网站均类似,最后均选择复制图片URL。 三、图床网站的推荐注意,这里只涉及提供图床网站的推荐,并不包含自建图床,对于图床的一些进阶使用,我会再写一篇文章进行叙述。 在上面提到过图片的加载速度与图床有关,因此使用一个好的图床实分重要,同时,你上传的的图片有可能被删除,图床网站也有可能跑路,因此图床的稳定性也很重要。 这里提醒大家:不要上传违法照片 下面我推荐两个网站: 1、 sm.ms这是上面提到的网站,服务器在国外,之前被国内墙过,被墙的图床生成的图片在国内也无法显示。 其使用了新网站Image Upload - SM.MS - Simple Free Image Hosting (smms.app),新网站解决了被墙的问题。 新用户注册免费使用 5GB 的空间,每张图片最大 5MB ,每次最多上传十张图片。 由于在国外,其图片加载速度一般,因此如果加载大量图片不建议使用,但是十分稳定,在少量使用时成为首选。 如果想要追求更高速度可以继续阅读下文第四章。 2、路过图床这是国内的网站,最大单张支持10 MB,在国内加载速度良好。 但是路过图床不允许上传二次元图片,并且会对上传的违法图片进行删除。 3、图床 imgloc.com最大 6 MB 图片大小,在国内的速度同样良好。 相比于路过图床,支持上传二次元图片,但是也会对违法图片进行删除。 四、使用 wsrv.nl 对图片访问加速1、介绍werv.nl 是一个十分强大的提供图像缓存和调整大小服务的工具。 他会先把图片进行缓存,同时你可以使用它对图片进行编辑与操作。 因为他的CDN由Cloudflare提供,而Cloudflare会对全球访问进行加速,因此我们可以用 werv.nl 对图片进行缓存,从而进行加速的效果。 利用这一方法,我们可以解决图床被墙,访问慢,甚至防盗链等问题。 2、使用详细使用已经编辑图像请阅读官方文档,我们只介绍缓存图片的方法。 在原来的图片链接前加上: https://images.weserv.nl/?url= 即可完成缓存,接下来只要使用组合成的新链接即可。 import { init } from 'https://unpkg.com/@waline/client@v2/dist/waline.mjs'; init({ el: '#waline', serverURL: 'https://waline-ccr39.netlify.app/.netlify/functions/comment', reaction: [ 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_heart_eyes.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_joy.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_consider.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_sob.png', ], emoji: [ '//unpkg.com/@waline/emojis@1.1.0/bilibili', '//unpkg.com/@waline/emojis@1.1.0/weibo', '//unpkg.com/@waline/emojis@1.1.0/qq', ] });","raw":null,"content":null,"categories":[{"name":"技术","slug":"技术","permalink":"http://ccr39.github.io/categories/%E6%8A%80%E6%9C%AF/"}],"tags":[{"name":"工具","slug":"工具","permalink":"http://ccr39.github.io/tags/%E5%B7%A5%E5%85%B7/"}]},{"title":"Git 的入门(二):Git 的常用命令","slug":"git-2","date":"2023-01-20T08:23:34.000Z","updated":"2024-12-13T06:07:22.145Z","comments":true,"path":"技术/git-2/","link":"","permalink":"http://ccr39.github.io/%E6%8A%80%E6%9C%AF/git-2/","excerpt":"","keywords":null,"text":"一、设置用户签名当我们使用 Git 前,首先要设置自己的用户签名。 1、基本语法在任意控制台下输入: git config --global user.name 用户名 git config --global user.email 邮箱 注意,在此处设置的邮箱并不一定为真实邮箱, Git 也并不会验证其真实性。 同时,此邮箱与将来使用的 GitHub 没有关系。 但是最好用自己创建 GitHub 的邮箱,不然提交代码没有小绿点! 2、用户签名所在位置在 Git 设置的用户签名会保存在C:\\Users\\你当前使用的用户\\.gitconfig 当我们尝试打开此文件可以看到 [user] name = 用户名 email = 邮箱 二、初始化本地库1、基本语法git init 2、具体用法在我们的工作区文件夹下打开 Git,并执行代码进行初始化本地库。 如果文件夹没有进行初始化,那么 Git 将没有权限修改文件。 执行完毕后,Git 将在文件夹下生成名为.git的文件夹(如果没有,是因为此文件夹被系统自动隐藏,请开启查看隐藏的文件) 三、将文件添加/删除到暂存区1、基本语法添加命令: git add . git add 文件名 删除命令: git rm --cached 文件名 rm .git/index 2、具体用法添加命令:将工作区的文件添加到暂存区,其中第一行指令为将工作区所有文件添加到暂存区,第二行指令为将指定文件添加到暂存区。 删除命令:第一行为将某文件从暂存区移除,暂存区实质是.git目录下的index文件,只要将此文件删除,那么就可以认为暂存区被清空(即第二行代码)。 四、提交到本地库1、基本语法提交暂存区到本地仓库中: git commit -m [message] [message] 可以是一些备注信息。 提交暂存区的指定文件到仓库区: $ git commit [file1] [file2] ... -m [message] -a 参数设置修改文件后不需要执行 git add 命令,直接来提交 $ git commit -a 2、具体用法使用提交命令提交到本地库中的文件不能再次删除。 五、查看本地库状态1、基本语法git status 2、具体用法当工作区文件没有在暂存区找到时,会提示: $ git status On branch master Untracked files: (use "git add <file>..." to include in what will be committed) new3.txt 当我们使用命令将文件添加到暂存区,提示: $ git status On branch master Changes to be committed: (use "git restore --staged <file>..." to unstage) new file: new3.txt 代表我们还未将文件提交本地库,再次执行提交本地库的命令,会提示: $ git status On branch master nothing to commit, working tree clean 表明文件已经全部提交到本地库。 六、查看历史版本1、基本语法git reflog 查看精简版本信息 git log 查看版本信息 2、具体用法使用git reflog可以查看本地库中的各个版本号前七位,以及该版本的备注信息,以及当前版本指向的本地库中的版本。 使用git log咳哟看到本地库中各版本完整的版本号,提交者及邮箱,提交日期以及备注信息。 如: $ git log commit c1c925dffc5b57bdb82b22d0d9ae18c8d5cf141f (HEAD -> master) Author: ccr39 <1632145835@qq.com> Date: Fri Jan 20 15:44:41 2023 +0800 测试版本 commit 后的就是版本号。 七、进行版本穿梭1、基本语法git reset --hard 版本号/版本号前七位 2、具体用法使用版本穿梭命令进行版本穿梭。我们可以再次使用git reflog查看版本信息。 观察到新生成了一个日志信息,以及当前指针已经指向穿梭到的版本号。 $ git reflog c845da5 (HEAD -> master) HEAD@{0}: reset: moving to c845da5 新生成的版本信息 c1c925d HEAD@{1}: commit: 测试版本 4738829 HEAD@{2}: commit: second c845da5 (HEAD -> master) HEAD@{3}: commit (initial): first 当前指针指向的版本 我们可以再次验证本地库的文件状态,发现本地库中的文件已经回到原来版本的状态。 实际上,指针先指向了 master 分支,再指向了我们的相应版本。 我们可以在.\\.git\\HEAD看到: ref: refs/heads/master 表明指针在指向 master。 再次打开.\\.git\\refs\\heads\\master,可以看到,在 master 文件中正保存了当前的版本号。表明 master 版本指向了我们当前的版本。 实际上,Git 切换版本的实质是移动 HEAD 指针。 在刚刚的案例中:HEAD -> master(分支)-> 版本。通过移动指针指向不同的分支与版本,即可完成版本控制。 import { init } from 'https://unpkg.com/@waline/client@v2/dist/waline.mjs'; init({ el: '#waline', serverURL: 'https://waline-ccr39.netlify.app/.netlify/functions/comment', reaction: [ 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_heart_eyes.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_joy.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_consider.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_sob.png', ], emoji: [ '//unpkg.com/@waline/emojis@1.1.0/bilibili', '//unpkg.com/@waline/emojis@1.1.0/weibo', '//unpkg.com/@waline/emojis@1.1.0/qq', ] });","raw":null,"content":null,"categories":[{"name":"技术","slug":"技术","permalink":"http://ccr39.github.io/categories/%E6%8A%80%E6%9C%AF/"}],"tags":[{"name":"工具","slug":"工具","permalink":"http://ccr39.github.io/tags/%E5%B7%A5%E5%85%B7/"},{"name":"编程","slug":"编程","permalink":"http://ccr39.github.io/tags/%E7%BC%96%E7%A8%8B/"}]},{"title":"Git 的入门(一):Git 的基本概念以及 Git 命令行的使用","slug":"git-1","date":"2023-01-09T02:35:27.000Z","updated":"2024-12-13T06:07:12.809Z","comments":true,"path":"技术/git-1/","link":"","permalink":"http://ccr39.github.io/%E6%8A%80%E6%9C%AF/git-1/","excerpt":"","keywords":null,"text":"Git 是 Linux 之父 Linus 为维护 Linux 社区所开发的一款分布式版本控制工具。 学会使用 Git 能够为我们带来很大的帮助,接下来我就来简单带大家了解 Git 这个工具。 一、版本控制工具刚才我们说过:“Git 是一款分布式代码版本控制工具” 因此,让我们先来了解代码版本控制工具是什么。 我们想象以下场景: 如果你在写一篇文章,在写完后你又经过了多次的修改,此时我们就习惯于把每个版本都复制下来,保存副本,这样当我们文章出现问题时,就可以对比以前的版本查找问题所在。 在上面的的情景中,我们对文章不同版本的拷贝就可以看作是对这篇文章进行了版本控制,但是大家也能轻而易举的发现这样的问题所在,也就是这种版本控制的方法过于繁琐,完全不优雅,而且在实际中,协同工作十分常见,这时就需要大家同时对一个项目进行版本控制。 因此,版本控制工具就孕育而生。 集中式版本控制工具在对我们的主人公 Git 所属于的分布式版本控制工具介绍之前,请先让我们了解集中式版本控制工具(例如 CVS 及 SVN)。 我们来看看集中式的版本控制工具是如何进行协同工作的版本控制的: 集中式的版本控制系统,所有的版本库是放在中央服务器中的,也就是说我们每一次的修改上传都是保存在中央服务器中的。中央服务器就是个大仓库,大家把产品都堆里面,每一次需要改进和完善的时候,需要去仓库里面把文件给提出来,然后再操作。 这种做法也存在弊端,如:当中央服务器,或网络出现故障时,大家就无法再对我们的代码进行版本控制,因此导致他们在故障的这段时间,谁都无法继续进行工作。 分布式版本控制工具为了解决集中式版本控制工具的种种弊端,分布式版本控制工具孕育而生。所谓分布,就是把版本库整个克隆到本地,让每台计算机上都还有一个完整的版本库。这样,即使在断网的环境下,我们也可以进行工作。 这时,如果我们想进行协同工作时,仅需要把最新的版本库共享给对方就能保证每个人的版本保持最新。 但是这里面有个问题,就是一个团队很大的情况下,大家都去修改,到底找谁同步版本库,不乱套了嘛。而且,大的开发项目也不是简单的两台计算机之间的版本互推就可以得到完整的版本库的。所以,分布式版本控制系统中通常也会有一台充当“中央服务器”的计算机,被称为远程库(如:GitHub、码云)。 读到这,您可能觉得,又绕回到集中式版本管理系统了。但其实,两者间存在着本质区别,即集中式版本工具必须在中央服务器内才能进行版本控制,而分布式版本控制工具不然。而且,分布式版本控制依靠的远程库,一般来说几乎不可能出现故障。 二、Git 的基本原理 Git 的使用流程是:工作区>>暂存区>>本地仓库>>远程仓库 工作区:即我们在电脑里储存项目的目录。 暂存区:准备进行版本保存的文件列表。 本地仓库:在本地保存的版本控制后的文件列表。 远程仓库:基于网络服务器的远程代码仓库(代码托管平台)。 局域网中的远程仓库 GitLab:在局域网(如:校园网)中搭建的远程库。 互联网中的远程仓库 GitHub:Git 官方的搭建远程仓库。 Gitee:国内版的 GitHub。 三、Git 的安装进入 Git 官网,根据不同操作系统进行下载。(建议下载最新版) 安装选项在这里进行跳过,我的建议是:如果你不知道选项对应的是什么意思请直接选择使用默认设置。 详细的安装选项解释视频参考:尚硅谷 Git 安装和客户端的使用_哔哩哔哩 四、Git 命令行的基本使用在完成安装 Git 后,在任意文件夹内右键,点击 Git Bash Here 以打开命令行。 进入到 Git 的命令行,由于 Git 与 Linux 是创作者是以为,所以,Git 支持几乎所有的 Linux 的指令,下面我简单列举常用的 Linux 指令。 指令 功能 cd 路径 进入对应路径,支持输入相对路径 ls 输出当前目录下的所有文件 touch 文件名 在当前目录创建文件 cat 文件名 显示当前目录中的文件的内容 vim 文件名 使用 vim 对当前目录下的文件进行编辑 cp 文件1 文件2 创建名为文件2的文件1副本 rm 文件名 删除文件 mkdir 文件夹名 创建文件夹 接下来介绍在 Git 命令行中的复制粘贴快捷按键 快捷键 功能 Ctrl + Insert 复制 ShIft + Insert 粘贴 如果你不习惯使用此指令,可以使用以下方法把复制/粘贴的快捷键改为Ctrl+Shift+C/V 首先打开Git Bash界面,右键单击标题栏,可以看到option...这个选项,点进去(如下图)。在keys标签下面的ShortCuts中,第一个复选框前面的对勾去掉并点击Apply+Save,即可不使用Ctrl/Shift+Insert复制粘贴了,之后勾选 Ctrl+Shift+letter shortCuts ,就可以使用Bash终端常用的复制粘贴快捷键Ctrl+Shift+C/V。 import { init } from 'https://unpkg.com/@waline/client@v2/dist/waline.mjs'; init({ el: '#waline', serverURL: 'https://waline-ccr39.netlify.app/.netlify/functions/comment', reaction: [ 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_heart_eyes.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_joy.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_consider.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_sob.png', ], emoji: [ '//unpkg.com/@waline/emojis@1.1.0/bilibili', '//unpkg.com/@waline/emojis@1.1.0/weibo', '//unpkg.com/@waline/emojis@1.1.0/qq', ] });","raw":null,"content":null,"categories":[{"name":"技术","slug":"技术","permalink":"http://ccr39.github.io/categories/%E6%8A%80%E6%9C%AF/"}],"tags":[{"name":"工具","slug":"工具","permalink":"http://ccr39.github.io/tags/%E5%B7%A5%E5%85%B7/"},{"name":"编程","slug":"编程","permalink":"http://ccr39.github.io/tags/%E7%BC%96%E7%A8%8B/"}]},{"title":"【Galgame】【PC/安卓直装】亚托莉—我挚爱的时光/ATRI -MY DEAR MOMENTS","slug":"Gal-Atri","date":"2023-01-08T07:59:33.000Z","updated":"2024-12-13T05:56:24.521Z","comments":true,"path":"资源/Gal-Atri/","link":"","permalink":"http://ccr39.github.io/%E8%B5%84%E6%BA%90/Gal-Atri/","excerpt":"","keywords":null,"text":"一、游戏介绍《ATRI -My Dear Moments-》是由 ANIPLEX.EXE 和 Frontwing、枕社(The pillow) 共同制作,并由 ANIPLEX.EXE 发行的一部视觉小说游戏。 二、剧情介绍在不远的未来,海平面原因不明地急速上升,导致了地表多数都沉入海中。 小时候因为事故而失去一条腿的少年・斑鸠夏生,厌倦了都市的生活,移居到了海边的乡村小镇。曾经身为海洋地质学家的祖母留给他的、就只有船、潜水艇还有债务。夏生为了取回“失去的未来”,与迷之讨债人凯瑟琳一起,潜海前往据说保存着祖母遗产的海底仓库。在那里,他遇到了一位沉睡在如同棺材一般装置中不可思议的少女“亚托莉”。她是一位构造精密到与人类别无二致,而又丰富感情的机器人。从海底被打捞起来的亚托莉如是说到。“我想完成主人留给我的最后的命令。在此之前,我会成为夏生先生的腿!”在一个逐渐沉入海中的平和小镇,少年和机器人少女的难忘夏日就这么开始了。 三、游戏CG 四、游戏攻略(谨慎观看)游戏共有三个选择支,分别为: 「成为你的右腿!」一章,第一次带阿托莉去市场时,凯瑟琳要求让阿托莉跟着她(把亚托莉交出去 \\ 亚托莉先放我这)。 「日志」一章,晚上从学校返回船上时选择 是否对亚托莉动手动脚 (静静地看着她 \\ 吻她)。 「被占据的学校」一章,从船上赶去学校时,选择(捡起鞋子 \\ 放着不管)。 三个选择支分别选 「 亚托莉先放我这」「 吻她」「 捡起鞋子」 可达成HE。 任一选择支选错即为BE (BE结局很短)。 HE与BE均达成后解锁TE。 五、资源分享请先观看:【索引】下载 Galgame 资源须知 请直接点击代码框右上角的图标进行复制,复制后的文本如果带有: 著作权归作者所有。 商业转载请联系作者获得授权,非商业转载请注明出处。 作者: ccr39 链接:ccr39.love 来源:CCR39のLazyNest 请先将这段文字删去,仅保留剩下的文字。 解压密码已经在文件名中标出,但解压密码不包含文件后缀,如.rar .zip,等。 PC 秒传链接: dd0869c481c2f5bf64f948911bf31ab0#3795797161#ATRI-PC密码 穹妹的黑兔布偶.rar 安卓直装 秒传链接: 5706f609b6b91861f2ac2c1333379836#996952426#亚托莉—我挚爱的时光.apk import { init } from 'https://unpkg.com/@waline/client@v2/dist/waline.mjs'; init({ el: '#waline', serverURL: 'https://waline-ccr39.netlify.app/.netlify/functions/comment', reaction: [ 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_heart_eyes.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_joy.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_consider.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_sob.png', ], emoji: [ '//unpkg.com/@waline/emojis@1.1.0/bilibili', '//unpkg.com/@waline/emojis@1.1.0/weibo', '//unpkg.com/@waline/emojis@1.1.0/qq', ] });","raw":null,"content":null,"categories":[{"name":"资源","slug":"资源","permalink":"http://ccr39.github.io/categories/%E8%B5%84%E6%BA%90/"}],"tags":[{"name":"Galgame","slug":"Galgame","permalink":"http://ccr39.github.io/tags/Galgame/"},{"name":"PC","slug":"PC","permalink":"http://ccr39.github.io/tags/PC/"},{"name":"安卓直装","slug":"安卓直装","permalink":"http://ccr39.github.io/tags/%E5%AE%89%E5%8D%93%E7%9B%B4%E8%A3%85/"}]},{"title":"【Galgame】【PC/KRKR】纸上魔法使","slug":"Gal-zsmfs","date":"2023-01-08T07:45:22.000Z","updated":"2024-12-13T05:56:40.933Z","comments":true,"path":"资源/Gal-zsmfs/","link":"","permalink":"http://ccr39.github.io/%E8%B5%84%E6%BA%90/Gal-zsmfs/","excerpt":"","keywords":null,"text":"一、游戏介绍《纸上的魔法使》(日语:紙の上の魔法使い)是由ウグイスカグラ开发,并于2014年12月19日发售的一部GalGame,也是该社的处女作。该作由ルクル负责剧本,桐葉负责原画,讲述了一个略带奇幻色彩的恋爱故事。 二、剧情介绍在某个岛上有一座规模略小的图书馆。这座图书馆是专门为了某个少女而建造的,游行寺家的私人图书馆。这座图书馆里有很多的罕见的书物,如果是书虫的话,那就绝对不会存在比这里还要爱不释手的地方。而,在这般首屈一指的私人图书馆里,住着几位出众且愉快的住人。 热爱图书的尼特少女·游行寺夜子。毒舌,冷淡的妹妹·月社妃。借住于图书馆的天然少女·伏见理央。还有一位被这背后的秘密而吸引过来的侦探少女·日向彼方。 他们就宛如被什么而引导着一样,互相邂逅——随后又以“喜爱书”这一点为契机,开始了属于他们的青春。一开始的图书馆虽然寂寞单调,可自主人公一行人住进来之后这座图书馆就变得渐渐热闹了起来。在不知不觉中——他们之间的关系变的亲密起来,达到了所谓青梅竹马的程度。 时光飞逝,2年后。因家庭原因,主人公离开了这座岛屿。而这次,主人公久违的回到了那座图书馆。 与6年前相同这里还和以前一样,无论是图书馆还是亲爱的青梅竹马们都没有发生太大的变化。可是,那在6年前未曾得知的“图书馆的秘密”这次却等待着主人公去揭晓它。 「——出现在书中之事,会在现世中再现。无论那是何等荒谬之事」「——出现在书中之事,会在现世中再现。无论那是何等荒谬之事」 如果是酸酸甜甜的恋爱系小说的话,那就会发生宛如飘渺的爱情罗曼史。又假如那是惊讶重重的幻想系小说的话,到了明天就会有吸血鬼出现在你的面前。而碰到了略惊悚的恐怖系物语的话,你的身后就会有幽灵在向你招手。 「这就是所谓的「这就是所谓的“魔法之书”“魔法之书”」」 这是一个被小清新的青春与苦闷焦躁的感情所动摇的,某个小小图书馆的物语…… 游行寺夜子的逞强,月社妃的可爱,伏见理央的坚强,日向彼方的耀眼感……准备好——来一场你与“书”的恋爱吧。 三、游戏CG 四、游戏攻略注:全部角色(克丽索贝莉露?)攻略完毕后才能激活预约特典补丁。 游行寺夜子◆SAVE01对钟爱朋友的,极致的友谊◆SAVE02可最讨厌你◆SAVE03为了夜子,返还撕掉的书页夜子 END 伏见理央◆SAVE01开始对钟爱少女的,极致的爱意理央 END 月社妃◆SAVE02开始可最喜欢你妃 END 克丽索贝莉露◆SAVE03开始为了自己,阅读撕掉的书页◆SAVE04不撕毁魔法之书克丽索贝莉露 END ◆SAVE04开始撕毁魔法之书普通 END(彼方) 五、资源分享请先观看:【索引】下载 Galgame 资源须知 请直接点击代码框右上角的图标进行复制,复制后的文本如果带有: 著作权归作者所有。 商业转载请联系作者获得授权,非商业转载请注明出处。 作者: ccr39 链接:ccr39.love 来源:CCR39のLazyNest 请先将这段文字删去,仅保留剩下的文字。 解压密码已经在文件名中标出,但解压密码不包含文件后缀,如.rar .zip,等。 PC 秒传链接: 4ed25fa122220cd0189dfe35f991841e#2777077378#PC 密码 acgngame.7z KRKR 秒传链接: 76ea3b5f9e0f6b9bbd59ad464212106d#945523634#KRKR 密码 acgngame.7z import { init } from 'https://unpkg.com/@waline/client@v2/dist/waline.mjs'; init({ el: '#waline', serverURL: 'https://waline-ccr39.netlify.app/.netlify/functions/comment', reaction: [ 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_heart_eyes.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_joy.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_consider.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_sob.png', ], emoji: [ '//unpkg.com/@waline/emojis@1.1.0/bilibili', '//unpkg.com/@waline/emojis@1.1.0/weibo', '//unpkg.com/@waline/emojis@1.1.0/qq', ] });","raw":null,"content":null,"categories":[{"name":"资源","slug":"资源","permalink":"http://ccr39.github.io/categories/%E8%B5%84%E6%BA%90/"}],"tags":[{"name":"Galgame","slug":"Galgame","permalink":"http://ccr39.github.io/tags/Galgame/"},{"name":"PC","slug":"PC","permalink":"http://ccr39.github.io/tags/PC/"},{"name":"KRKR","slug":"KRKR","permalink":"http://ccr39.github.io/tags/KRKR/"}]},{"title":"【Galgame】【PC/ONS】悠之空","slug":"Gal-you","date":"2023-01-08T07:39:53.000Z","updated":"2024-12-13T05:56:36.150Z","comments":true,"path":"资源/Gal-you/","link":"","permalink":"http://ccr39.github.io/%E8%B5%84%E6%BA%90/Gal-you/","excerpt":"","keywords":null,"text":"一、游戏介绍《悠之空》(ハルカナソラ)是日本游戏社Sphere研发的一款单机游戏,于2009年发行,应用于PC平台。是前作游戏《缘之空》的后续作品。 二、剧情介绍游戏主要讲述了主人公春日野悠与双胞胎妹妹春日野穹(主要路线)的故事。以及天女目瑛、渚一叶、乃木坂初佳、依媛奈绪和中里亮平的故事,同时扩充了前作中没有的仓永梢与伊福部八寻路线(次要线路)。还增加了壁纸,剧场版(人物)的插件,并带有特典。主要还是以穹妹线为主,继续讲述悠与穹的爱情故事,以及穹与悠从山上下来到去北欧(赫尔辛基)旅游之间的故事,并有到北欧后的生活片段。 三、游戏CG 四、资源分享请先观看:【索引】下载 Galgame 资源须知 请直接点击代码框右上角的图标进行复制,复制后的文本如果带有: 著作权归作者所有。 商业转载请联系作者获得授权,非商业转载请注明出处。 作者: ccr39 链接:ccr39.love 来源:CCR39のLazyNest 请先将这段文字删去,仅保留剩下的文字。 解压密码已经在文件名中标出,但解压密码不包含文件后缀,如.rar .zip,等。 PC 秒传链接: f5a42414bf9b59c80234ed26cfb64016#1304749401#悠之空PC 解压密码acgmg.rar ONS 秒传链接: 54305a79febfeb8c983b98aace8bb9b9#598145499#001 【ONS】悠之空 密码:qingju.7z import { init } from 'https://unpkg.com/@waline/client@v2/dist/waline.mjs'; init({ el: '#waline', serverURL: 'https://waline-ccr39.netlify.app/.netlify/functions/comment', reaction: [ 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_heart_eyes.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_joy.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_consider.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_sob.png', ], emoji: [ '//unpkg.com/@waline/emojis@1.1.0/bilibili', '//unpkg.com/@waline/emojis@1.1.0/weibo', '//unpkg.com/@waline/emojis@1.1.0/qq', ] });","raw":null,"content":null,"categories":[{"name":"资源","slug":"资源","permalink":"http://ccr39.github.io/categories/%E8%B5%84%E6%BA%90/"}],"tags":[{"name":"Galgame","slug":"Galgame","permalink":"http://ccr39.github.io/tags/Galgame/"},{"name":"PC","slug":"PC","permalink":"http://ccr39.github.io/tags/PC/"},{"name":"ONS","slug":"ONS","permalink":"http://ccr39.github.io/tags/ONS/"}]},{"title":"【Galgame】【PC/ONS】缘之空","slug":"Gal-sora","date":"2023-01-08T07:28:41.000Z","updated":"2024-12-13T05:56:29.775Z","comments":true,"path":"资源/Gal-sora/","link":"","permalink":"http://ccr39.github.io/%E8%B5%84%E6%BA%90/Gal-sora/","excerpt":"","keywords":null,"text":"一、游戏介绍《缘之空》(日语:ヨスガノソラ,英语:Yosuga no Sora)是 Sphere 于2008年12月5日发售的恋爱文字冒险游戏,也是 Sphere 的第一部作品,以“双胞胎兄妹恋”为主题,并因此引发大量争议。亦有漫画、动画、Fandisk、广播剧等衍生作品,其主线讲述了一对双胞胎兄妹摆脱世俗观念的束缚、坚持找寻心中的真爱的故事。 二、剧情介绍春日野悠和他的双胞胎妹妹春日野穹在父母死于车祸之后,来到了远离都市的田园小镇奥木染的祖父家中,在那里开始新的生活。一边和不习惯的家务苦战,一边还要照顾平时足不出户、什么事情都不会做的妹妹穹,悠的生活变得异常艰辛。与此同时悠也受到了曾经一同玩耍的邻家大姐姐依媛奈绪、刚转校便结识了的中里亮平、神社的巫女兼管理人天女目瑛、以及她的朋友渚一叶和乃木坂初佳等人的热情欢迎。同儿时的印象几乎没有变化的村镇和人们,那让人怀念的回忆和温馨的环境,治愈着悠心中的伤痕。就在这样的过程中,慢慢地发生了一些变化。儿时所定下的只属于两个人的秘密的约定,以及所失去的重要东西的下落。还有定下了这个地方的真正理由。作为回忆铭刻在心之时,也已经悄悄开始。就这样悠的新生活展开了。在安稳的日子里,很快悠注意到了对自己来说谁是最重要的存在……面对伤痕累累,一路蹒跚走过的“她”,悠又会如何面对呢?阳光愈发灿烂的初夏的天空下,故事就这样开始了…… 三、游戏CG 四、游戏攻略(谨慎观看)注:穹线二周目才会开启(通完任意一人的结局后从最初开始)标有◆号的选项为二周目出现的选项,初次游戏时不出现,无视即可。 穹线敲门(2周目)别看我这样,我也是成长了不少了哦?从今往后也能和和乐乐的当朋友吗捉弄过头的话,是不是不大好啊穹妹 END 奈绪线今天这先这样吧◆今后也要麻烦你了。从今往后也能和和乐乐的当朋友吗捉弄过头的话,是不是不大好啊奈绪 END 瑛线◆今天这先这样吧别看我这样,我也是成长了不少了哦?我想了解一下天女目的事情……捉弄过头的话,是不是不大好啊瑛 END 一叶线◆今天这先这样吧别看我这样,我也是成长了不少了哦?从今往后也能和和乐乐的当朋友吗不过,我觉得这就是有意思的地方一叶 END 初佳线◆今天这先这样吧别看我这样,我也是成长了不少了哦?从今往后也能和和乐乐的当朋友吗捉弄过头的话,是不是不大好啊初佳 END 五、资源分享请先观看:【索引】下载 Galgame 资源须知 请直接点击代码框右上角的图标进行复制,复制后的文本如果带有: 著作权归作者所有。 商业转载请联系作者获得授权,非商业转载请注明出处。 作者: ccr39 链接:ccr39.love 来源:CCR39のLazyNest 请先将这段文字删去,仅保留剩下的文字。 解压密码已经在文件名中标出,但解压密码不包含文件后缀,如.rar .zip,等。 PC 秒传链接: f9e8bb23a25233fc4e9b699f6ddf8a71#1873592191#缘之空PC 解压密码acgmg.rar ONS 秒传链接: d34915fa632ffae0064419242a2729f4#1432325083#004 [ONS]缘X之X空 密码:qingju.7z import { init } from 'https://unpkg.com/@waline/client@v2/dist/waline.mjs'; init({ el: '#waline', serverURL: 'https://waline-ccr39.netlify.app/.netlify/functions/comment', reaction: [ 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_heart_eyes.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_joy.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_consider.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_sob.png', ], emoji: [ '//unpkg.com/@waline/emojis@1.1.0/bilibili', '//unpkg.com/@waline/emojis@1.1.0/weibo', '//unpkg.com/@waline/emojis@1.1.0/qq', ] });","raw":null,"content":null,"categories":[{"name":"资源","slug":"资源","permalink":"http://ccr39.github.io/categories/%E8%B5%84%E6%BA%90/"}],"tags":[{"name":"Galgame","slug":"Galgame","permalink":"http://ccr39.github.io/tags/Galgame/"},{"name":"PC","slug":"PC","permalink":"http://ccr39.github.io/tags/PC/"},{"name":"ONS","slug":"ONS","permalink":"http://ccr39.github.io/tags/ONS/"}]},{"title":"2023新年的第一份二次元美图","slug":"pic-2023-1","date":"2023-01-08T06:34:00.000Z","updated":"2024-12-13T05:57:27.863Z","comments":true,"path":"转载/pic-2023-1/","link":"","permalink":"http://ccr39.github.io/%E8%BD%AC%E8%BD%BD/pic-2023-1/","excerpt":"","keywords":null,"text":"END import { init } from 'https://unpkg.com/@waline/client@v2/dist/waline.mjs'; init({ el: '#waline', serverURL: 'https://waline-ccr39.netlify.app/.netlify/functions/comment', reaction: [ 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_heart_eyes.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_joy.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_consider.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_sob.png', ], emoji: [ '//unpkg.com/@waline/emojis@1.1.0/bilibili', '//unpkg.com/@waline/emojis@1.1.0/weibo', '//unpkg.com/@waline/emojis@1.1.0/qq', ] });","raw":null,"content":null,"categories":[{"name":"转载","slug":"转载","permalink":"http://ccr39.github.io/categories/%E8%BD%AC%E8%BD%BD/"}],"tags":[{"name":"图集","slug":"图集","permalink":"http://ccr39.github.io/tags/%E5%9B%BE%E9%9B%86/"}]},{"title":"【索引】下载 Galgame 资源须知 + 超详细的 Galgame 各种模拟器及工具使用教程","slug":"galgame","date":"2023-01-07T08:06:45.000Z","updated":"2024-12-13T05:56:45.507Z","comments":true,"path":"资源/galgame/","link":"","permalink":"http://ccr39.github.io/%E8%B5%84%E6%BA%90/galgame/","excerpt":"","keywords":null,"text":"一、关于资源的下载本人会不定期把一些 Galgame 的资源分享到博客上,资源一律采用百度网盘的秒传链接,不使用其他的链接。 关于秒传链接的提取,可以阅读 这篇文章 的第五节。你也可以阅读整篇文章,了解百度网盘不限速下载的方法。 二、资源的使用下载完毕后请解压压缩包,所有的压缩包密码,全部在压缩包名上,请大家留意。 分享的所有资源仅提供 Windows 与安卓,至于 IOS 的游戏资源以及使用,暂不提供。 如果你使用的是安卓手机端,建议下载以下工具。 工具名称 作用描述 MT管理器 强大的文件管理器,方便你找到文件。 ZArchiver 简称ZA,强大的解压工具。支持中文密码,也可以在 Google Play 下载正版。 WINRAR 同样强大的解压工具,支持中文密码,同时可以修复.RAR格式的压缩包。 可能会遇到压缩包为分卷压缩的情况,即同一文件使用多部份压缩,请确保全部的压缩包在同一目录下,并仅对某一压缩包进行解压即可。 下面我们分别讲解不同资源的用法: 1、PC 资源①在 PC 上的使用在电脑上使用 PC 资源的使用一般较为方便,在我们将资源成功解压后,一般直接打开游戏目录中的 .exe 文件,打开即可运行。 ②在安卓端的使用我们可以用一些模拟器,在安卓上运行部分 PC 游戏的资源,并不是所有游戏都能被模拟器运行,所以可以多次尝试。 JoiPlay 模拟器 安装:参考视频手把手教你安装joiplay模拟器 使用:参考视频Joiplay安卓模拟器使用教程 ExaGear模拟器 教程:参考视频ExaGear模拟器的使用方法 2、KRKR 资源KRKR 资源是为 KRKR2 模拟器使用的资源,KRKR2 是专门面向于安卓的手机 Galgame 模拟器,也是最常用的手机模拟器之一。 由于最新版的 Tyranor 模拟器增加了对 KRKR 的支持,因此,我们还可以用 Tyranor 模拟器运行 KRKR 资源。 使用 KRKR2 模拟器①安装下载链接: KRKR2 模拟器 ②使用打开 KRKR2 模拟器,找到资源解压后的目录,找到目录中的 .xp3 文件,点击即可运行。 使用 Tyranor 模拟器①安装下载链接:Tyranor模拟器 ②使用打开 Tyranor 模拟器,在 “添加” 页面点击最右上角的图标选择路径。 点击右侧图标进行预览。 在进入游戏的根目录时点击右下角对勾,即可添加游戏。 添加完成后,直接点击运行即可运行游戏。 3、ONS 资源ONS 资源可以在 ONS 模拟器使用,ONS 的一大优势是,它可以在大部分平台中运行,你可以在官方网站中了解。 这里我们讲的是 Windows 和安卓的使用。 ①在 PC 上运行 ONS 游戏下载 PC ONS 启动器,并解压。 打开游戏目录,并直接将刚才的解压的所有文件放入游戏目录。 在游戏目录中点击 ONScripter-Jh.exe 即可运行。 ②在手机运行 ONS 游戏使用 ONS-JH 模拟器在此下载 ONS-JH 模拟器,如果有能力,建议去 Google Play 下载正版。 打开 ONS-JH 模拟器,并在模拟器中直接打开游戏所在目录,即可使用。 使用 Mine 模拟器Mine 基于 ONS 模拟器制作的,功能跟 ONS 模拟器大致相同。 同时,Mine 还可能支持其他游戏,具体可自行探索。 下载 Mine 模拟器 使用教程参考视频:【MINE模拟器】使用教程 4、安卓直装资源即以安卓 app 安卓包形式存在的资源,文件后缀为.apk,此类资源在安卓手机直接下载后直接安装就可以使用。 5、Tyranor 资源Tyranor 可以运行 Artemis 引擎制作的游戏,比如富婆妹。 使用方法和下载在上面的 KRKR 资源中已经说过,这里就不说了。 6、Pymo 资源pymo 是一个手机上的 Galgame 引擎,其运行依赖于 pymo 模拟器。 下载: Pymo 模拟器 在手机上打开 pymo,选择游戏所在的文件夹就会开始游戏。 7、maldives 资源Maldives 模拟器可以在手机上运行近几年RPG的游戏(特点是有www文件夹) 下载:MaldiVes模拟器 使用方法与之前几个大体相似。 import { init } from 'https://unpkg.com/@waline/client@v2/dist/waline.mjs'; init({ el: '#waline', serverURL: 'https://waline-ccr39.netlify.app/.netlify/functions/comment', reaction: [ 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_heart_eyes.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_joy.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_consider.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_sob.png', ], emoji: [ '//unpkg.com/@waline/emojis@1.1.0/bilibili', '//unpkg.com/@waline/emojis@1.1.0/weibo', '//unpkg.com/@waline/emojis@1.1.0/qq', ] });","raw":null,"content":null,"categories":[{"name":"资源","slug":"资源","permalink":"http://ccr39.github.io/categories/%E8%B5%84%E6%BA%90/"}],"tags":[{"name":"Galgame","slug":"Galgame","permalink":"http://ccr39.github.io/tags/Galgame/"},{"name":"索引","slug":"索引","permalink":"http://ccr39.github.io/tags/%E7%B4%A2%E5%BC%95/"}]},{"title":"Clash 的安装与详细的使用","slug":"clash","date":"2023-01-06T08:47:35.000Z","updated":"2024-12-13T05:56:08.360Z","comments":true,"path":"技术/clash/","link":"","permalink":"http://ccr39.github.io/%E6%8A%80%E6%9C%AF/clash/","excerpt":"","keywords":null,"text":"由于时效性,本文章可能随时进行更新,文章内容可能会有误,我会在评论区修正,请谅解。 科学上网可以说是网上冲浪的必备技能了,相信大家也接触过不少科学上网的工具。 这里我们介绍一个最常用的科学上网工具之一: Clash 与 Clash 同样常用且强大的工具是V2ray,两者均可在各大系统操作系统中有相应客户端,以下我们主要介绍 Clash 在Windows上和在 Android上的使用,如果想为 IOS 配置 Clash 代理可以参考下文第四节的内容,其他系统的使用方法可以自行搜索。如果你想要了解更高级的使用方法,可以阅读官方文档以了解更多。 一、购买节点并获取订阅链接首先我们要去机场购买节点,所谓机场就是提供代理服务的网站。我们可以在机场购买订阅并获取订阅链接来使用网络代理服务。 机场提供的服务并不一定是稳定,高速,安全的。所以需要进行一定斟酌后再选用机场。而且由于再大陆内,提供代理网络服务并不合法,所以机场也有可能随时跑路,所以在购买节点时不建议长期订阅。 机场的价格往往与速度,稳定性挂钩,但是机场的价格普遍并不高。 博主使用的机场在这里,最便宜的价格的话是一个月一元100G,最高速度可以顶满带宽,完全足够个人使用。注册时记得输入邀请码:AtpsDqhe。 同时,机场一般也会提供使用方法和客户端资源,你可以参考机场上的方法来配置Clash。 二、Clash的基本使用1、Clash for Windows①下载客户端国内镜像下载、官方Github发布页(若国内无法访问官方发布页,请使用国内镜像) 云盘中的不一定为最新版,最新版可在官方发布页下载。 使用汉化包前往:官方发布页无法访问时请在此进行下载 如下图,将app.asar直接放入 resources 文件夹中,并进行替换。 再次启动汉化成功。 ②导入配置文件首次启动 Clash for Windows 后会出现下图所示界面代表启动成功: 导入配置文件有如下两个途径: URL 导入 本地文件拖拽导入 你可以在机场中复制订阅地址来获得URL。 URL 导入点击界面左侧菜单 Profiles(即:配置),在顶部输入框填入 URL 并点击 Download 下载即可,下载完成后点击对应的配置文件即可载入 本地文件拖拽导入如果无法通过 URL 下载配置文件,则可以尝试在浏览器中下载配置文件后通过拖拽方式导入 ③打开系统代理返回 General 常规中,打开System Proxy系统代理即可,如果你希望开机自启,也可以勾选 Start with Windows开机自启。 System Proxy:设置系统代理 Start with Windows: 设置开机自启 2、Clash for Android①下载客户端云盘 提取码:1og4,Github 官方(若国内无法访问官方发布页,请使用国内镜像),Google Play(没有代理无法访问) 云盘中的不一定为最新版,最新版可在官方发布页下载。 ②添加订阅面板是有一键订阅的,直接点击就好,手动如下步骤 打开 Clash for Android ,依次进入 配置 > 新配置 > URL 。 在 URL 一栏中粘贴 Clash 配置订阅链接;自动更新 (分钟) 推荐填写 1440 ,即每 24 小时自动从链接中更新配置文件。 完成后点击右上角的保存按钮,Clash for Android 将下载配置文件,请点击选中添加的配置文件。 ③开启代理返回软件首页。点击开关,即可进行代理。会提示是否同意创建VPN,请点击允许。 点开 “代理”,可以策略组进行选择。 三、其他基本功能1、代理模式①代理模式的区别Clash 提供了 全局、规则、直连、脚本 四种代理模式。 全局:设备上所有支持代理协议的浏览器、程序的 IP 均使用代理,换句通俗的话说,就是整个设备都通过代理来访问外部网络。 规则:使用 Clash 的规则文件进行上网流量分流,比如让国内IP、域名的流量直连,让国外的IP、域名通过代理连接。 直连:意思是直接连接,不使用代理上网。 脚本:利用用户自己写的脚本文件进行流量分流,需要配置脚本文件使用 ②设置代理模式在 Windows 端的 代理 的上方,从左到右依次为 全局 、规则 、直连 、脚本 在安卓端的 代理 中,点击右上角三个点,在弹出的框中的 模式 里可以设置代理模式,但仅在此次有效,下次启动会重新使用默认设置 你也可以在设置中更改默认模式:点击 设置 >> 覆写 >> 模式 2、设置终端代理在 Windows 端,可以直接为控制终端设置代理,来解决在终端中安装超时的问题。 3、打开 Clash 的 Web 控制台点击 Clash 核心后面的那行字。 此时我们就可以进入控制台 四、使用 Clash 为局域网中的其他设备配置代理使用 Clash 的 “允许局域网连接” 功能可以为 Clash 为局域网内的其他设备进行代理。 利用这个方法,我们可以解决在 IOS 端,配置 Clash 困难,复杂的问题。 1、配置 Windows 端①打开 ”允许局域网连接” ②点击 “允许局域网连接” 后方的图标,查看网络接口 ③点击 “端口” 后方的数字,设置端口,端口号的范围应在 0 到 1023 ,你也可以使用默认的端口号不去设置。 2、配置其他客户端这里拿 IOS 举例,安卓或其他客户端大体相似,具体可自行查询 。 首先保证 PC 与手机在同一局域网下。 ①打开手机设置: ②打开 WiFi 设置; ③向下滑动,找到HTTP设置——配置代理; ④将配置代理的关闭勾选为手动; ⑤将刚才查看的网络接口地址,和端口号分别填入服务器和端口中。 保存之后即可生效,其代理模式和 PC 端保持一致。 如果你不在想用代理,重新把配置代理关闭即可。 五、完毕到此,一些关于 Clash 的基本使用技巧已经简单概述,如果您还需要更多进阶技巧,可从此文档中获取。 import { init } from 'https://unpkg.com/@waline/client@v2/dist/waline.mjs'; init({ el: '#waline', serverURL: 'https://waline-ccr39.netlify.app/.netlify/functions/comment', reaction: [ 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_heart_eyes.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_joy.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_consider.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_sob.png', ], emoji: [ '//unpkg.com/@waline/emojis@1.1.0/bilibili', '//unpkg.com/@waline/emojis@1.1.0/weibo', '//unpkg.com/@waline/emojis@1.1.0/qq', ] });","raw":null,"content":null,"categories":[{"name":"技术","slug":"技术","permalink":"http://ccr39.github.io/categories/%E6%8A%80%E6%9C%AF/"}],"tags":[{"name":"工具","slug":"工具","permalink":"http://ccr39.github.io/tags/%E5%B7%A5%E5%85%B7/"}]},{"title":"vim的安装以及基础使用","slug":"vim","date":"2023-01-05T13:24:00.000Z","updated":"2024-12-13T05:57:50.932Z","comments":true,"path":"技术/vim/","link":"","permalink":"http://ccr39.github.io/%E6%8A%80%E6%9C%AF/vim/","excerpt":"","keywords":null,"text":"Vim 是从 Vi 发展出来的一个文本编辑器,也是所有的 Unix Like 内置的文本编辑器。其拥有强大的对代码的处理功能,因此成为了许多大佬写代码的首选。 这里要说明, Vim 不是 IDE 他可以在任何的平台中使用,也没有对语言的限制。 可以说,学好对 Vim ,可以让你的手几乎不会离开键盘的主操作区,对我们有着极大的帮助。 一、Vim 在 Windows 上的安装1、直接安装 Vim 本体在官网中直接下载 Gvim 的安装包,根据提示进行安装。 安装完成之后,即可以从目录中启动 Vim ,或者,你可以在控制台中输入 Vim 进行使用。(当然要保证已经为 Vim 配置了环境变量) 2、在 VS Code 中使用 Vim直接在 VS Code 的拓展中搜索 Vim 即可让 VS Code 的文本编译方式转为和 Vim 相同。 二、Vim 的学习和使用如果你是安装的 Gvim 本体的话,你可以直接在控制台输入 vimtutor使用 Vim 自带的学习文档进行学习。 下面将在这里介绍 Vim 的基本使用。 如下图,Vim 为我们编辑文本提供了三种方式:命令模式、输入模式、底线命令模式。 当我们打开 Vim 默认的模式即为命令模式,在命令模式下,我们不能完成文本的输入等操作,但是我们可以通过键盘上的按键来操作并编辑文本。 当我们在命令模式下输入 : 时,会进入底线命令模式,这个时候,光标会在左下角出现,我们可以输入相应的指令并按回车执行指令。 在命令模式下,当我们输入 i a o 三个键时,即可进入输入模式,在输入模式下,我们可以正常的输入文字,如果想要切换回命令模式,需要按 esc 键。 下面是 vi/vim 的键盘图 Vim 的指令十分强大,需要一段时间的学习和适应,在熟悉按键之后,即可达到非常强大的效果。 import { init } from 'https://unpkg.com/@waline/client@v2/dist/waline.mjs'; init({ el: '#waline', serverURL: 'https://waline-ccr39.netlify.app/.netlify/functions/comment', reaction: [ 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_heart_eyes.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_joy.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_consider.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_sob.png', ], emoji: [ '//unpkg.com/@waline/emojis@1.1.0/bilibili', '//unpkg.com/@waline/emojis@1.1.0/weibo', '//unpkg.com/@waline/emojis@1.1.0/qq', ] });","raw":null,"content":null,"categories":[{"name":"技术","slug":"技术","permalink":"http://ccr39.github.io/categories/%E6%8A%80%E6%9C%AF/"}],"tags":[{"name":"工具","slug":"工具","permalink":"http://ccr39.github.io/tags/%E5%B7%A5%E5%85%B7/"},{"name":"编程","slug":"编程","permalink":"http://ccr39.github.io/tags/%E7%BC%96%E7%A8%8B/"}]},{"title":"BOCCHI THE ROCK!","slug":"bochinorock","date":"2022-12-20T14:23:43.000Z","updated":"2024-12-13T05:56:01.848Z","comments":true,"path":"转载/bochinorock/","link":"","permalink":"http://ccr39.github.io/%E8%BD%AC%E8%BD%BD/bochinorock/","excerpt":"","keywords":null,"text":"图片均来自于pixiv BOCHI 虹夏 喜多 凉 END import { init } from 'https://unpkg.com/@waline/client@v2/dist/waline.mjs'; init({ el: '#waline', serverURL: 'https://waline-ccr39.netlify.app/.netlify/functions/comment', reaction: [ 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_heart_eyes.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_joy.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_consider.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_sob.png', ], emoji: [ '//unpkg.com/@waline/emojis@1.1.0/bilibili', '//unpkg.com/@waline/emojis@1.1.0/weibo', '//unpkg.com/@waline/emojis@1.1.0/qq', ] });","raw":null,"content":null,"categories":[{"name":"转载","slug":"转载","permalink":"http://ccr39.github.io/categories/%E8%BD%AC%E8%BD%BD/"}],"tags":[{"name":"图集","slug":"图集","permalink":"http://ccr39.github.io/tags/%E5%9B%BE%E9%9B%86/"}]},{"title":"从零开始速通百度云网盘","slug":"panbaidu","date":"2022-12-18T06:20:37.000Z","updated":"2024-12-13T05:57:16.216Z","comments":true,"path":"资源/panbaidu/","link":"","permalink":"http://ccr39.github.io/%E8%B5%84%E6%BA%90/panbaidu/","excerpt":"","keywords":null,"text":"由于时效性,本文章可能随时进行更新,文章内容可能会有误,我会在评论区修正,请谅解。 相信大家在网上冲浪时时常会下载一些资源、软件,如果你需要下载别人分享的资源时,就需要用到网盘。 百度云网盘由于早期在国内占据了一定规模的市场,拥有大量的资源与链接,直至目前,百度云网盘仍是被使用最多的网盘。但是百度的不当人做法,让百度云网盘的限速到达了堪称恐怖的境界,但另一方面,坐拥大量资源的百度云网盘让我们不得不通过它进行资源的传输。所以不少人选择了向百度屈服,充了百度的SVIP,但就算是SVIP仍然逃不过限速的命运。 还有这样一种情况,就是我们经常会看到一些资源分享链接,结果还没有来得及下载,链接就失效了。 直链下载和秒传链接就能帮助我们解决上述两个问题。 今天,由我为大家带来,从零开始速通百度云网盘,把带宽顶满,生成永久有效的秒链,从此告别限速与分享无效。 全文提供安卓和 Windows 两种方案,前面先讲的直链,秒链在最后面。 如果大家之前接触过安卓端使用ES文件管理器加ADM的方法,本人实测该方法已失效,所以请使用本文提供的方法。 一、准备工作:科学上网(可自行跳过)科学上网可以说是网上冲浪的必备技能了,相信大家也接触过不少科学上网的工具。 这里我们介绍一个最常用的科学上网工具之一: Clash 与 Clash 同样常用且强大的工具是V2ray,两者均可在各大系统操作系统中有相应客户端,以下我们主要介绍 Clash 在Windows上和在 Android上的使用,其他系统的使用方法可以自行搜索。如果你想要了解更高级的使用方法,可以阅读官方文档以了解更多。 1、购买节点并获取订阅链接首先我们要去机场购买节点,所谓机场就是提供代理服务的网站。我们可以在机场购买订阅并获取订阅链接来使用网络代理服务。 机场提供的服务并不一定是稳定,高速,安全的。所以需要进行一定斟酌后再选用机场。而且由于再大陆内,提供代理网络服务并不合法,所以机场也有可能随时跑路,所以在购买节点时不建议长期订阅。 机场的价格往往与速度,稳定性挂钩,但是机场的价格普遍并不高。 博主使用的机场在这里,最便宜的价格的话是一个月一元100G,最高速度可以顶满带宽,完全足够个人使用。注册时记得输入邀请码:AtpsDqhe。 同时,机场一般也会提供使用方法和客户端资源,你可以参考机场上的方法来配置Clash。 2、Clash for Windows①下载客户端国内镜像下载、官方Github发布页(若国内无法访问官方发布页,请使用国内镜像) 云盘中的不一定为最新版,最新版可在官方发布页下载。 首次启动 Clash for Windows 后会出现下图所示界面代表启动成功: ②导入配置文件导入配置文件有如下两个途径: URL 导入 本地文件拖拽导入 你可以在机场中复制订阅地址来获得URL。 URL 导入点击界面左侧菜单 Profiles,在顶部输入框填入 URL 并点击 Download 即可,下载完成后点击对应的配置文件即可载入 本地文件拖拽导入如果无法通过 URL 下载配置文件,则可以尝试在浏览器中下载配置文件后通过拖拽方式导入 ③打开系统代理返回 General 中,打开System Proxy即可,如果你希望开机自启,也可以勾选 Start with Windows。 System Proxy:设置系统代理 Start with Windows: 设置开机自启 3、Clash for Android①下载客户端云盘 提取码:1og4,Github 官方(若国内无法访问官方发布页,请使用国内镜像),Google Play(没有代理无法访问) 云盘中的不一定为最新版,最新版可在官方发布页下载。 ②添加订阅面板是有一键订阅的,直接点击就好,手动如下步骤 打开 Clash for Android ,依次进入 配置 > 新配置 > URL 。 在 URL 一栏中粘贴 Clash 配置订阅链接;自动更新 (分钟) 推荐填写 1440 ,即每 24 小时自动从链接中更新配置文件。 完成后点击右上角的保存按钮,Clash for Android 将下载配置文件,请点击选中添加的配置文件。 ③开启代理返回软件首页。点击开关,即可进行代理。会提示是否同意创建VPN,请点击允许。 点开 “代理”,可以策略组进行选择。 二、tampermonkeytampermonkey(油猴)是一个强大的浏览器插件,他为脚本在浏览器内运行提供了一个环境。 通过油猴我们可以使用脚本来做到许多神奇的操作,接下来我来带大家使用tampermonkey。 1、浏览器的使用Windows说到浏览器插件,首先就要说浏览器了,首推浏览器现在是Edge,适配绝大部分插件。 如果你有谷歌账号还熟练科学上网,推荐Chrome。 实际上,常见的几乎所有国产浏览器,甚至手机的APP,以及Edge使用的是都是开源的chromemiu内核。 但其实Edge最初是自己制作内核,但是微软的工程师最后屈服于谷歌了。 所以Edge可以适配谷歌的所有插件,甚至可以一建导入,而且Edge在国内没被墙以及还有许多其他功能(Win10以上自带),所以在国内掀起了一波推崇热潮。 本人因为不想再下chrome用了自带的Edge,但实际体验极差,经常会卡顿,无响应。 所以我的推荐是,如果你会用Chrome还是不要用Edge了。 其次的推荐Firefox、Opera。 Android在安卓平台,首推kiwi浏览器,可以适用谷歌的所有插件,你可以再Google play上直接搜索下载,如果你不会使用Google play可以在此(百度网盘)或在此(推荐)本地安装包。 你还可以在Kiwi浏览器中文网,获取更多的下载方式和详细的使用方法。 2、安装tampermonkeyWindows①插件商店安装以Edge为例,找到右上角三个点,点击>拓展>获取 Microsoft Edge 扩展>搜索tampermonkey点击获取 这里注意,不建议安装tampermonkey Beta因为Beta版本的某些功能并不稳定。 如果你使用的是Chrome浏览器,那么想要用谷歌的扩展商店需要科学上网,如果无法科学上网可以使用本地安装的方法。 ②本地安装你还可以选择在这里(百度云)或这里(蓝奏云)下载本地文件,完毕后打开浏览器,这里还是以Edge为例。 右上角三个点,点击>扩展>打开“开发者模式”>打开之后把下载好的本地文件直接拖入即可安装。 如果显示出错无法安装右击文件,把文件后缀 .crx 改为 .zip 把文件解压,然后再次来到扩展页面,保证开发者模式打开,点击”加载解压缩的扩展”,进入到刚才解压好的文件夹的根目录,点击选择文件夹即可。 这时可能会发生显示出错的情况,如: 这种情况不用在意,可以正常使用。 Android①插件商店安装Kiwi浏览器的商店依赖的时谷歌插件商店,因此需要科学上网。 打开Kiwi浏览器,先新建标签页,点击右上角三个点 > 扩展程序 > +(from store) > 搜索 tampermonkey > 添加到Chrome 同样,不建议安装tampermonkey Beta,因为Beta版本的某些功能并不稳定。 ②本地安装在这里(百度云)或这里(蓝奏云)下载本地文件,完毕后要注意文件被下载到的位置,不同手机浏览器的文件位置可能不一样,所以可以自行搜索并查找。 打开Kiwi浏览器,先新建标签页,点击右上角三个点 > 扩展程序 > +(from .zip/.crx/.user.js) 这时候在出现的文件管理器中找到刚才下载的文件,点击添加即可。 3、安装脚本确保安装完成tampermonkey后再次确保tampermonkey打开。 在浏览器内点击这里,点击安装此脚本以安装脚本。 安装成功后进入插件的管理面板,在电脑端浏览器,点击右上角拼图样式的图标>点击tampermonkey>管理面板。 在手机端中点击三个点,下滑到最后,找到tampermonkey,点击后再点击管理面板。 进入管理面板可以看到: 确保脚本打开,至此插件脚本安装成功。 三、下载器的安装及配置Windows端:IDM下载器安装在这里下载IDM破解版,然后解压。 配置UA我提供的IDM是绿色版本,解压后,执行“!)绿化.bat”,就可以正常使用了。IDM配置:修改UA为 netdisk;PC Android端:ADM下载器安装:蓝奏云,密码:2z6b 百度云 [Google Play](Advanced Download Manager - Google Play 上的应用) 配置UA进入ADM,点击设置>下载中,滑倒最下方找到浏览器标识。选择最下方的自定义,然后再最下方的自定义设置中输入netdisk;PC。保存 四、获取直链并下载将百度网盘中你想下载的文件转存如自己的网盘中。 如果是安卓端,需要在Kiwi浏览器右上角三个点勾选桌面版网站来访问电脑版网站。 同时,因为在手机端打开网页会自动跳转,请保证在勾选桌面版网站之后访问百度网盘网页端。 打开浏览器,进入百度网盘网页端,找到刚才转存的文件。 勾选,并点击简易下载助手。 点击获取直链地址,如果需要验证码可以根据提示,关注公众号,获取验证码,填写完毕后再次点击获取直链地址。 完成后点击复制直链地址,这里也要注意,关注下方的公告,我们已经把UA改为目前可用的UA,但不排除更换的可能性,如果需要更换UA,请根据下方公告填写。 Windows接下来打开IDM,点击新建任务。 将刚才的直链地址复制进去点击确定,开始下载。 可以看到,我们的带宽已经跑满。 Android进入ADM,点击下方加号把刚才的直链复制进去。 展开高级选项,在下方的浏览器标识中选择”自定义”,接下来点击开始进行下载。 网速也是跑满了带宽: 常见问题无权限下载这是因为UA设置错误导致的,请查看是否有新的UA,然后再按上面的方法重新配置UA。 在ADM中,一定要保证在下载时的浏览器表示中使用自定义。 下载过慢/网速不正常这可能与你的线程设置有关系,ADM和IDM的默认线程数为8线程,而脚本要求的线程数是4线程。 常规来说,在带宽顶满之前,线程数越多下载速度越快,但是过多的线程数可能会引起系统异常,从而停止对你的文件传输。 实际使用来说,使用8线程一般不会造成问题,但也存在例外。 因此,如果下载速度异常,请先尝试将最大线程数调到4线程,如果无效,可以尝试配置更多的线程观察是否对下载速度有一定帮助。 下面介绍修改最大线程数的方法。 IDM: ADM:在添加下载任务>高级选项中 五、秒传链接的使用秒传链接实现了分享网盘资源永久分享。 接下来介绍秒传链接的使用方法。 Windows在安装完Tampermonkey的浏览器中点击这个链接。 点击安装后点击安装此脚本,进行安装。 完成后进入到网页版百度网盘,选择需要传输的文件,点击生成秒传。 接下来点击复制秒传代码即可生成。 想要导入秒传文件,则点击秒传,并将秒传链接复制在其中。 Android在安卓端,你可以参考上面的方法在Kiwi浏览器中打开这个,下载脚本。 并打开桌面版网站,进入百度云网盘,和上面Windows端使用同样的方法进行秒传。 这里我们介绍另一种方法,依靠的是手机的客户端导入秒传文件(仅支持导入,想要生成还是用上面的办法)。 首先下载狐悠(百度网盘、蓝奏云 提取码:2mu9) 进入APP,然后登陆百度网盘,直接将秒传链接复制进去即可导入秒传文件。 完成至此,你已经学会了如何以正确姿势使用百度网盘了,请记住,白嫖是有代价的,不爱折腾不可能得到良好的体验。 只有能折腾,才能获得更好的体验,所以不要犯懒,经过上述方法,你一定能完美使用百度网盘 import { init } from 'https://unpkg.com/@waline/client@v2/dist/waline.mjs'; init({ el: '#waline', serverURL: 'https://waline-ccr39.netlify.app/.netlify/functions/comment', reaction: [ 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_heart_eyes.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_joy.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_consider.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_sob.png', ], emoji: [ '//unpkg.com/@waline/emojis@1.1.0/bilibili', '//unpkg.com/@waline/emojis@1.1.0/weibo', '//unpkg.com/@waline/emojis@1.1.0/qq', ] });","raw":null,"content":null,"categories":[{"name":"资源","slug":"资源","permalink":"http://ccr39.github.io/categories/%E8%B5%84%E6%BA%90/"}],"tags":[{"name":"软件","slug":"软件","permalink":"http://ccr39.github.io/tags/%E8%BD%AF%E4%BB%B6/"}]},{"title":"编程环境的搭建与scoop的使用","slug":"scoop","date":"2022-12-16T14:46:00.000Z","updated":"2024-12-13T05:57:42.398Z","comments":true,"path":"技术/scoop/","link":"","permalink":"http://ccr39.github.io/%E6%8A%80%E6%9C%AF/scoop/","excerpt":"","keywords":null,"text":"学习计算机编程语言,想必第一件事情就是搭建所需的环境,但往往环境的搭建是非常折磨人的。 你是否曾自己一人,抱着满腔热血,试图学习某门语言,但却因为 IDE 或编译器无法运行而在各个网页间来回穿梭? 你是否在想要使用别人的项目时,却面对这琳琅满目的报错中独自发愁。 鲁迅曾经说过“我刚开始学编程,最痛苦的一件事就是搭建环境。”那么今天我就为大家来避避踩过的坑。 一、何为环境? 编程环境的方面包括很多,简单来说,编程环境指的是能供让代码或程序正常运行的环境。 那么需要哪些条件呢? 拿C++举例,首先你要有一个IDE,用来编写代码。其次你要有一个编译器,来编译代码。 那么这一套用来编译,并运行的条件就是C++的运行环境。(最简单的i 二、系统环境变量环境变量的使用是避坑的第一个环节。 记得学OI那会,第一次使用VS Code,闹腾半天愣是不知道如何添加环境变量,现在回想下来,其实原因就在于没有理解环境变量究竟是什么。 当你在控制台输入一些程序( 比如Windows自带的cmd时 ),你可能会看到这句话: Microsoft Windows [版本 10.0.22621.819](c) Microsoft Corporation。保留所有权利。 这句话中包含了cmd的版本信息。 但是你是否想过,我们分明没有输入cmd的路径,但是系统是如何找到cmd的所在位置呢? 如果在最初搭建环境踩过坑的人,可能会联想到另外一种情况,就比如说,你在控制台输入$ python index.py时可能会报出出的错误: ‘python’ 不是内部或外部命令,也不是可运行的程序或批处理文件。 想必聪明的读者一定能想得到,在这里系统并没有找到python的位置。 可能是两种情况: 电脑中不存在python。 电脑中存在python但是不能被系统像找到cmd那样找到。 那么现在就可以回答上面那个问题:系统是如何找到cmd的所在位置呢? 答案就是环境变量。 在你的系统中,环境变量是用来储存一些程序的位置的东西,有了它系统就能知道程序的路径在哪里,所以想要解决上面的问题,我们就要知道如何去通过修改环境变量来使系统能够找到程序。 在Windows操作系统下,右击桌面上的此电脑,点击属性>>高级系统设置>>高级>>环境变量。即可修改环境变量。 而我们一般把值储存在Path变量中,值的格式就是你的程序的目录的路径,多个路径之间用逗号相隔。(在Win10以及以上版本中,你只点击编辑环境变量>>新建,就能够添加新的地址,而在其他版本中,则需要在整个变量最后添加逗号,再输入新的路径) 在这里,Windows还提供了两类环境变量,一个是用户变量,储存的变量是储存在用户中的,另外一个是系统变量,储存在系统中。如果不太了解什么意思,其实无论存在系统还是用户中都可以正常使用。 当我们用安装包安装的时候,环境变量一般会自动添加到系统中,但也不乏一些个例,从而可能会引起上述报错。还有人因为挪动了根目录的位置从而报错,原因也不难猜了,只需要把原来的环境变量修改为根目录就行了。 现在我们就可以理解上面的报错了,我们只需要把python的目录复制,添加到环境变量的Path变量中,就可以解决问题。还有、其他问题,比如报错说存在多个程序,那么就可能是由于电脑中的多个同名程序都被识别找到,但是系统不知道打开哪一个,这时候你可以用$ where 程序名来获取程序地址,再去环境变量中找到多余的某个路径,删去就可以。 简单来说,了解环境变量的本质之后,就能很大程度上手动解决许多问题。 再举一个解决实际问题的例子: 假如说我们再使用指令$ pip install XXX时报错pip 不是内部或外部命令,也不是可运行的程序或批处理文件。我们就可以进行推测,首先我们知道pip时python自带的安装依赖包的程序,那么有可能是这个程序的目录没有在环境变量中,这时,我们可以查询pip在python目录的哪个地方,再把pip的路径复制,放到环境变量中即可。如果你发现自己的python没有自带pip,我们就可以用python的命令(或其他方法)安装pip,再把路径加入环境变量,即可解决 三、Scoop的使用在 Windows 下,搭建开发环境一直是一个复杂且困难的问题。由于没有一个统一的标准,导致各种开发环境的安装方式差异巨大,需要付出很多不必要的时间成本。而 Scoop 可以帮助你统一安装并管理常见的开发软件,省去了手动下载安装,配置环境变量等繁琐步骤。 例如安装 python 和 nodejs 只需要执行: scoop install python scoop install nodejs 1、安装scoop的安装依靠PoweShell,如果你使用的是 Windows 7 系统,那么PowerShell的版本可能过于陈旧。你可以手动安装新版的PowerShell。 安装命令:在PowerShell中输入 Set-ExecutionPolicy RemoteSigned -scope CurrentUser irm get.scoop.sh -outfile 'install.ps1' .\\install.ps1 -ScoopDir 'C:\\Scoop' 2、使用如: scoop install python 即可直接下载,并搭建python的环境。 详情可见官方文档。 import { init } from 'https://unpkg.com/@waline/client@v2/dist/waline.mjs'; init({ el: '#waline', serverURL: 'https://waline-ccr39.netlify.app/.netlify/functions/comment', reaction: [ 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_heart_eyes.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_joy.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_consider.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_sob.png', ], emoji: [ '//unpkg.com/@waline/emojis@1.1.0/bilibili', '//unpkg.com/@waline/emojis@1.1.0/weibo', '//unpkg.com/@waline/emojis@1.1.0/qq', ] });","raw":null,"content":null,"categories":[{"name":"技术","slug":"技术","permalink":"http://ccr39.github.io/categories/%E6%8A%80%E6%9C%AF/"}],"tags":[{"name":"编程","slug":"编程","permalink":"http://ccr39.github.io/tags/%E7%BC%96%E7%A8%8B/"}]},{"title":"基础动态规划","slug":"baseDP","date":"2022-12-16T08:59:00.000Z","updated":"2024-12-13T05:55:53.849Z","comments":true,"path":"转载/baseDP/","link":"","permalink":"http://ccr39.github.io/%E8%BD%AC%E8%BD%BD/baseDP/","excerpt":"","keywords":null,"text":"原文链接 一、基本概念与定义1、动态规划的概念对于某些问题,我们可以将其分成若干个互相联系的阶段,并在每个阶段做出决策,从而达到最优解。 这种通过状态来影响决策,在经由决策引起状态转移的动态过程被称作动态规划(简称DP) 动态规划(DP)不是某种具体算法,而是一种思想。 核心在于:把大问题转化为小问题,利用小问题的解,推断出大问题的解。 2、状态当我们把大问题化成小问题时,只有大问题和小问题拥有相同的形式,才能考虑拆分子问题。 如果满足这个要求,那么我们遇到的每个子问题,都可以通过某种简洁的形式来 表达。 我们把可能遇到的每种“局面”称为状态。 设计完状态之后,只要能利用小状态的解求出大状态的解,就可以动手把题目做 出来! 3、转移当我们设计好状态,我们需要用小状态推出大状态。 从一个状态的解,得知另一个状态的解,我们称之为“状态转移”。这个转移式子 称为“状态转移方程”。 4、Dp的基本原则(1)最优子结构:大问题的最优解,一定是从小问题的最优解推出来的。 (2)无后效性:无后效性 现在的决策,只与过去的结果有关,而与过去的决策无关。 5、DP与记忆化搜索(1)记忆化搜索在经$dfs$搜索过程中,会产生许许多多的子序列,对于每个序列,可能会产生重复的元素。 例如: 求99!,100!,101! 一般思路,分别从1开始乘 但显然,对于这道题我们只需要算出99!,就不需要再从头计算了,因为100!即是99! * 100,而101 ! 即是 100 ! * 101 ! 所以说,我们只需要在阶乘的过程中将 99 ! 的得数存到数组a[99]中,等到下次再调到用时,就可以直接访问a[99],从而省去不必要的时间。 一般情况下,可以将O($2^n$)的时间复杂度优化为O($n^2$)的复杂度。 (2)DP对于同样的问题,我们并不考虑如何直接去求 99 ! ,而去考虑如何可以将 99 ! 分成若干个子问题。 显然 99 ! = 98 ! * 99; 而 98 ! = 97! * 98; 以此类推,我们可以等到: 1 ! = 1 可以看出,对于所有的阶乘问题,我们都可以从 2的阶乘开始计算,最后一步步到达想要的结果,这就是DP。 同时,对于这道题,状态转移方程为:a[N] = a[N - 1] * N;且a[0]=1 6、DP与递推从上面我们的探究可以看出,对于同一个问题,DP的做法是,从最初结点开始遍历,在过程中,我们不考虑之前的值是否存在,也不考虑当决策是否对之后产生影响,只是根据状态转移方程,一步步选择,从而得到结果。 我们可发现,DP其实运用了递推的思想。 我们可以把状态转移方程看成递推公式,把初始值看做递推边界。 对于上题,我们同样可以写成递推公式 $F_n=F_{n-1}*n$;$F_0=1$ 同时,我们可以把记忆化搜索看成递归的思想 在搜索过程中沿着某一个答案前进,在过程中调用之前所储存的答案。 所以,记忆化搜索和递推也常被当做DP的一种实现方式。 二、DP程序的设计1、转移方式(1)backward 型转移:我从哪里来?这是一种常见的思路:对于一个没有求出解的状态,利用能走到它的状态,来得出它的解。 同时它也是记忆化搜索的方式 (2)forward 型转移:考虑我到哪里去对于一个已经求好了解的状态,拿去更新它能走 到的状态。 2、DP三连 我是谁? (设计状态) 我从哪里来 (backward 型转移) 我到那里去 (forward 型转移) (两种转移方式中,只需要选择一个来设计转移即可。) import { init } from 'https://unpkg.com/@waline/client@v2/dist/waline.mjs'; init({ el: '#waline', serverURL: 'https://waline-ccr39.netlify.app/.netlify/functions/comment', reaction: [ 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_heart_eyes.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_joy.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_consider.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_sob.png', ], emoji: [ '//unpkg.com/@waline/emojis@1.1.0/bilibili', '//unpkg.com/@waline/emojis@1.1.0/weibo', '//unpkg.com/@waline/emojis@1.1.0/qq', ] });","raw":null,"content":null,"categories":[{"name":"转载","slug":"转载","permalink":"http://ccr39.github.io/categories/%E8%BD%AC%E8%BD%BD/"}],"tags":[{"name":"算法","slug":"算法","permalink":"http://ccr39.github.io/tags/%E7%AE%97%E6%B3%95/"}]},{"title":"线性DP","slug":"线性DP","date":"2022-12-16T08:59:00.000Z","updated":"2024-12-13T05:54:05.964Z","comments":true,"path":"转载/线性DP/","link":"","permalink":"http://ccr39.github.io/%E8%BD%AC%E8%BD%BD/%E7%BA%BF%E6%80%A7DP/","excerpt":"","keywords":null,"text":"文章原链接: 【笔记】线性DP - OIer:ccr39の博客 - 洛谷博客 (luogu.com.cn) 一、定义线性$DP$,指利用线性结构对问题进行求解的一种常见的动态规划类型。 对于线性$DP$ ,一般没有固定的模板,需要根据题意与状态进行逐步求解。 线性动态规划的目标函数为特定变量的线性函数,约束是这些变量的线性不等式或等式,目的是求目标函数的最大值或最小值。 因此,除了少量问题(如:LIS、LCS、LCIS等)有固定的模板外,大部分都要根据实际问题来推导得出答案。 二、常见问题对于线性$DP$一般有以下常见模板题型: 1、最长单调上升子序列(洛谷AT2827 LIS)(1)题目 给定一个长为$n$ 的序列 $a_i$,求这个序列的单调上升子序列长度。 $1 \\le a_i \\le n \\le10^5$。 (2)做法$solution~1:O(n^2)$线性$DP$,根据我们之前介绍过得$DP$三连可以得到以下思路。 我是谁?(设计状态) 我们考虑使用$DP[i]$来表示第以i位结尾的最长的单调上升子序列长度。 即:我是第i位之前的最长单调上升子序列的长度。 我从何而来 (backward 型转移) 我将到何方 (forward 型转移) 对于本题来说,我们采用第一种转移方式,考虑我是如何求得。 我们可以发现,对于任何一个点$dp_i$来说,以它为结尾的最长单调上升子序列的长度就是在它之前的,元素值小于它的所有点的最大值+1。 即对于一个点$a_j(0\\le j< i)$若$a_j<a_i$且在所有满足条件的j中,$dp_j$的值最大,那么,$dp_i=dp_j+1$。 把写出它的状态转移方程: $dp_i=max(dp_j)+1(0\\le j< i,a_j<a_i );dp_0=0$这样,我们就能求出每个阶段下最长的单调上升序列,再存储其最大值即可。 时间复杂度$O(n^2)$ $code~1:$#include<bits/stdc++.h> #define re register #define rint re int const int MAXN=1e5+5; int n,ans,a[MAXN],dp[MAXN]; signed main() { scanf("%d",&n); for(rint i=1;i<=n;i++) scanf("%d",&a[i]); for(rint i=1;i<=n;i++) { for(rint j=1;j<i;j++) if(a[j]<a[i]) dp[i]=max(dp[i],dp[j]); ans=max(ans,++dp[i]); } printf("%d",ans); return 0; } $solution~2:O(nlogn)$利用二分的思想,去维护一个单调递增的序列。 对于每一次的元素的插入,都利用二分查找其位置。 时间复杂度$O(nlogn)$ $code$ $2:$#include<bits/stdc++.h> #define re register #define rint re int const int MAXN=1e5+5; int n,a[MAXN],f[MAXN],p=1; signed main() { scanf("%d",&n); for(rint i=1;i<=n;i++) scanf("%d",&a[i]); f[p]=a[1];//把a[1]先放入数组中 for(rint i=2;i<=n;i++) if(a[i]>f[p]) f[++p]=a[i];//如果a[i]>s[p]也就是比现有元素都大,就直接将其插入到数组最后 else f[lower_bound(f+1,f+p+1,a[i])-f]=a[i];//在f中查找正好大于或等于a[i]的位置,并将其替换。lower_bound查找大于等于,upper_bound查找大于,两者初始仅可以在单调递增的序列中查询。 printf("%d",p); return 0; } $solution$ $3:$树形数组,对$DP$的一种优化方式,时间复杂度$O(nlogn)$,但常数比第二种方法大。 详解可见此。(@星爵$dalao$) (3)同类题型:P1020导弹拦截、P1091合唱队形。 2、最长公共子序列$LCS$(P1439)(1)题目 给定两个长为$n$ 的序列$P_1$ 和 $P_2$ ,求它们的最长公共子序列。 $1 \\le n \\le10^5$。 (2)做法$solution1:O(n^2)$线性$DP$,我们继续按照之前做题的思路,使用$DP$三连分析问题。 我是谁?(设计状态) 我们考虑使用$DP[i][j]$来表示$a_{1∼i},b_{1∼j}$的LCS长度。 即:我是第$a$的第i位之前,和b的第$j$位前,$a,b$的最长公共子序列。 我从何而来 (backward 型转移) 我将到何方 (forward 型转移) 这里我们依旧选择第二种转移方式解决此题。 我们来思考,当$a[i]=b[j]$时,那么就表示有新的公共元素,那么 $dp[i][j]=dp[i-1][j-1]+1$ 如果没有新的公共元素,那么就要继承之前的值 $dp[i][j]=max(dp[i−1][j],dp[i][j−1])$ 那么我们就可以写出来它的状态转移方程。 $code~1:$#include<iostream> using namespace std; int dp[1001][1001],a[2001],b[2001],n,m; int main() { cin>>n; for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int i=1;i<=n;i++)scanf("%d",&b[i]); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(a[i]==b[j]) dp[i][j]=dp[i-1][j-1]+1; else dp[i][j]=max(dp[i-1][j],dp[i][j-1]); cout<<dp[n][n]; } $solution~2:O(nlogn)$将问题转化成$LIS$,将$a$序列映射进一个数组里,数组下标代表a序列的数,而数组的值表示其下标在$a$数组的位置。 即若 $a_1=3,a_2=2,a_3=1,a_4=4,a_5=5$ 那么$map_1=3,map_2=2,map_3=1,map_4=4,map_5=5$ 那么在根据$b$数组在$map$数组中的相对位置做$LIS$。 得到的就是他们的$LCS$。 换句话说,只要$b$中某个子序列在$a$中的相对位置单调递增,那么它就是$a$的子序列。 当$b_1=1,b_2=2,b_3=3,b_4=4,b_5=5$时 $b_1$的位置在$a$中排第3位,$b_2$的的位置在$a$中排第2位,$b_3$的位置在$a$中排第1位,$b_4$的位置在$a$中排第4位,$b_5$的位置在$a$中排第5位。 (也可以写成$map_{b_1}=3,map_{b_2}=2,map_{b_3}=1,map_{b_4}=4,map_{b_5}=5$) 在此之中,最长单调上升子序列为$1,4,5$,那么相对应的,$b$与$a$的$LCS$就是$b_3,b_4,b_5$。 时间复杂度$O(nlogn)$,但仅限于全排列数组。 $code~2:$#include<bits/stdc++.h> #define re register #define rint re int using namespace std; const int MAXN=1e6+5; int a,b[MAXN],Map[MAXN],dp[MAXN]; int main() { rint n,len=0; scanf("%d",&n); for(rint i=1;i<=n;i++) scanf("%d",&a),Map[a]=i; for(rint i=1;i<=n;i++) scanf("%d",&b[i]),dp[i]=0x7fffffff;//因为要查找位置,所以dp要赋极大值 for(rint i=1;i<=n;i++) if(Map[b[i]]>dp[len]) dp[++len]=Map[b[i]];//如果可以直接满足递增,则直接插入尾部 else { rint k=lower_bound(dp+1,dp+len+1,Map[b[i]])-dp; dp[k]=Map[b[i]];//如果不行,则插入到第一个大于等于本身的地方 } printf("%d",len); return 0; } (3)同类题目:AT4527 LCS 3、最长公共子上升序列(CF10D LCIS)(1)题目 给定两个长分别为$n、m$ 的序列$P_1$ 和 $P_2$ ,求它们的最长公共上升子序列。 $1 \\le n,m \\le500$。 (2)做法待补充(鸽了) import { init } from 'https://unpkg.com/@waline/client@v2/dist/waline.mjs'; init({ el: '#waline', serverURL: 'https://waline-ccr39.netlify.app/.netlify/functions/comment', reaction: [ 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_heart_eyes.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_joy.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_consider.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_sob.png', ], emoji: [ '//unpkg.com/@waline/emojis@1.1.0/bilibili', '//unpkg.com/@waline/emojis@1.1.0/weibo', '//unpkg.com/@waline/emojis@1.1.0/qq', ] });","raw":null,"content":null,"categories":[{"name":"转载","slug":"转载","permalink":"http://ccr39.github.io/categories/%E8%BD%AC%E8%BD%BD/"}],"tags":[{"name":"算法","slug":"算法","permalink":"http://ccr39.github.io/tags/%E7%AE%97%E6%B3%95/"}]},{"title":"进制与位运算","slug":"进制与位运算","date":"2022-12-16T00:53:00.000Z","updated":"2024-12-13T05:53:57.614Z","comments":true,"path":"转载/进制与位运算/","link":"","permalink":"http://ccr39.github.io/%E8%BD%AC%E8%BD%BD/%E8%BF%9B%E5%88%B6%E4%B8%8E%E4%BD%8D%E8%BF%90%E7%AE%97/","excerpt":"","keywords":null,"text":"原文链接 一、进制(1)概念几进制指的是几进一,日常生活中常常使用十进制,在计算机语言中,2进制最常见。 同时,还有8进制,16进制等进制。 (2)进制的表示:①二进制:用前缀 $0b$ 表示;或用后缀 $B$ 表示,如:$01101001B$。 ②八进制:用前缀 $0o$ 表示,如 $0o76$ ;或用后缀 $O$ 表示,如:$257O$。 ③十进制:用前缀 $0d$ 表示,或用后缀 $D$ 表示。 ④十六进制:用前缀 $0x$ 表示,或用后缀 $H$ 表示。 在表示9以上的数时使用用$A、B、C、D、E、F$。 (3)进制的转换①n进制转10进制思路:将第a位数字乘以$n^{a-1}$,再作和。 代码: #include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <iomanip> using namespace std; int n,b; string a; int main() { cin>>n>>a; int l=a.size(); for(int i=1;i<=l;i++) { if (a[l-i]>='0'&&a[l-i-1]<='9') a[l-i]-='0'; if ( a[l-i]>='A' && a[l-i]<='F' ) { a[l-i]-='A'; a[l-i]+=10; } b+=a[l-i]*pow(n,i-1); } cout<<b; return 0; } 也可以用C++库函数实现,用到函数strtol()。 用法strtol( 字符串(char*型) , NULL,n ) 代码 #include<bits/stdc++.h> using namespace std; int n; char a[1000]; int main() { cin>>n>>a; cout<<strtol(a,NULL,n); return 0; } ②10进制转n进制思路:模n取余法,将十进制数向n取余,记录余数,知道十进制数为零,反向书写余数,即为n进制数。 代码: #include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <iomanip> using namespace std; int n,b,i,ans[10000]; int main() { cin>>n>>b; while(b>0) { ans[i++]=b%n; b/=n; } for ( int q=i-1 ; q>=0 ; q-- ) if(ans[q]>=10&&ans[q]<16 ) cout<<char(ans[q]+55); else cout<<ans[q]; return 0; } ③二进制转十六进制。思路:一个有趣的性质 1位十六进制数码对应 4 位数的二进制数码。 所以将十六进制和二进制之间相互转换时并不需要以 10 进制为中间跳板,直接进行翻译即可。 例如二进制数 1010110111 经过分组可以变为 0010 1011 0111,直接查表(或者口算)可以翻译为 2B7。 反过来也是一样的。 ④n进制转m进制思路:先将n进制转10进制,再将10进制转m进制。 代码: #include<bits/stdc++.h> using namespace std; string a; int c[10000000],d,e,f,g,sum,ans; int main() { scanf("%d",&d); cin>>a; scanf("%d",&f); for(int x=0;x<a.size();x++){ if(a[x]<'A'){ e=pow(d,a.size()-x-1); e*=(a[x]-'0'); sum+=e; } else{ e=pow(d,a.size()-1-x); e*=(a[x]-'A'+10); sum+=e; } } while(sum>0){ c[g++]=sum%f; sum/=f; } for(int x=g-1;x>=0;x--){ if(c[x]>=10)printf("%c",c[x]+'A'-10); else printf("%d",c[x]); } return 0; } ⑤浮点数的进制转换思路:先转换整形,再将浮点数部分乘n取整。 (4) 二进制的深入探究在二进制中一个 0 或 1 的数码被称为一位。一个内存地址对应的 8 位,被称为一字节( Byte )。 一个 int 类型或 float 类型的变量占用 32 位空间。 而一个 char 的变量占用 8 位。 有些变量类型也有无符号数,例如 unsigned int 类型。 这个类型占用和 int 类型一样,为 32 位,但是以放弃存储正负符号为代价,可以储存比 int 多一倍的整数值(0 到$2^{32}$−1,接近4.3×$10^9$ )。 计算机中还有其他的表示数据大小的单位,比如 1 KB 是 $2^{10}$ =1024 字节(大约一千),1 MB 是 $2^{20}$ 字节(大约一百万), 1 GB 是 $2^{30}$ 字节。 在带符号整数的情况下,$-57$ 如何被表示成负数呢?在计算机中又是如何计算 $66-57$ 呢? 我们用 8 位的 $signed$ $char$ 类型来举例 $57$ 用二进制表示为 $0011$ $1001$(补足 8 位)。 如何表示一个负数? 可以占用最高位的一位来表示正负,0 表示非负,1 表示负数。 然后再经过以下方法处理 用除了第一位的数字表示这个负数的绝对值,第一位变成 1。这样的话 $-57$ 表示为 $1011$ $1001$。 这种表示方式称为原码。不过计算机不使用这种方式来表示负数。 将这个负数的绝对值的数全部取反,由 1 变为 0,0 变为 1。这样的话 $-57$ 表示为 $1100$ $0110$。这种表示方式成为反码。 使用反码有一个问题,对于$0$,既可以表示为$0000$ $0000$也可以表示为$1111$ $1111$,所以也不常用。 先计算这个负数的反码,然后加 1。这样的话 $-57$ 表示为 $1100$ $0111$。 这是计算机使用的表示数的方法,被称为补码。这种表达方式下,零只有 1 个,而$1111$ $1111$则代表 -1。 二、位运算(1)定义直接对整数在内存中的二进制位进行按位操作。 (2)运算符位运算包括与、或、非、异或等操作。 ①与运算:$A∧B$(在$C$语言写作”A&B”)A与B全为真时,得数为真。(即: 1&1 = 1 ; 1&0 = 0 ; 0&0 = 0) ②或运算:$A∨B$(在$C$语言写作” A|B”)A或B中有一个为真是,得数为真。(即:$1|1=1$ ; $1|0=1$ ; $0|0=0$) ③非运算:$¬A$(在$C$语言写作” ~A “)进行取反操作。(即:~1=0 ; ~0=1) ④异或运算:$A⊕B$(在$C$语言写作” $A$^$B$ “ )只有当两个值一假一真时,得数为真,等效于 “ ( A & ~B ) | (~A & B) “ (即:除$1$^$0$得数位1外,得数均为零) 性质1:任何数与 0 异或即为本身。 性质2:任何偶数个相同的数异或后结果为 0。 性质3:任何数异或偶数次另一个数结果不变。 ⑤左移:$A<<B$ 将A的二进制向左移B位,空位用 0 补齐。 ⑥右移:$A>>B$ 将A的二进制向右移B位,非正数位删去。 import { init } from 'https://unpkg.com/@waline/client@v2/dist/waline.mjs'; init({ el: '#waline', serverURL: 'https://waline-ccr39.netlify.app/.netlify/functions/comment', reaction: [ 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_heart_eyes.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_joy.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_consider.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_sob.png', ], emoji: [ '//unpkg.com/@waline/emojis@1.1.0/bilibili', '//unpkg.com/@waline/emojis@1.1.0/weibo', '//unpkg.com/@waline/emojis@1.1.0/qq', ] });","raw":null,"content":null,"categories":[{"name":"转载","slug":"转载","permalink":"http://ccr39.github.io/categories/%E8%BD%AC%E8%BD%BD/"}],"tags":[{"name":"算法","slug":"算法","permalink":"http://ccr39.github.io/tags/%E7%AE%97%E6%B3%95/"}]},{"title":"解决电脑钉钉视频会议无法旋转屏幕的问题","slug":"DingScreen","date":"2022-12-13T09:28:23.000Z","updated":"2024-12-13T05:56:19.083Z","comments":true,"path":"技术/DingScreen/","link":"","permalink":"http://ccr39.github.io/%E6%8A%80%E6%9C%AF/DingScreen/","excerpt":"","keywords":null,"text":"观前注意:如果第一次打开,请耐心加载,这个过程大约需要一分钟甚至更长,若长时间未反应,请尝试刷新。 最近一直在上网课,有一些同学反应,老师的手机因位置无法正向摆放导致画面反转,而且使用电脑的时候钉钉视频会议的屏幕无法旋转,导致极其别扭。本来我感觉并没有必要专门写一篇文章来说明这件事情,但介于博客建立不久,可以趁机宣传装逼一波,所以写一篇博客,来讨论一下关于此问题的方法。其中关于电脑屏幕旋转的问题可以适用于所有电脑窗口。 注意:本文章全片讨论钉钉视频会议,不是视频直播!!! 一、关于视频发起者(老师)钉钉的视频会议发起有两种模式:屏幕共享和摄像头。 1、PC(电脑)端老师上课用电脑,一般是使用ppt,所以是直接屏幕共享,如果对写字有特别要求的老师,也可能选择使用数位板,或者使用触屏设备。 使用屏幕共享的好处是,屏幕一般不可能发生显示翻转的问题。但是如果用摄像头就可能有例外的发生。我们可以在视频会议的页面来解决这个问题。 具体操作: 每点击一下这个按钮,自己的画面就会旋转90°。 2、手机端比起电脑,更多的老师也会选择手机端进行上课。 ①屏幕共享相关问题一般老师会在以下情景使用屏幕共享:第一,在需要使用ppt,或其他文件时。第二,老师通过屏幕共享加手机系统自带的摄像头进行直播。 手机进行屏幕共享,方向是不会出问题的,但是使用系统摄像头时摄像头现实的画面却和手机方向有关系。 你可能会问,为什么老师不用钉钉的摄像头反而要用手机自带的摄像头呢? 实际上,使用手机自带摄像头的好处是:由于手机自带摄像头的算法优化比钉钉更好,已经使用钉钉摄像头,画面清晰度会被压缩导致降低(受网络影响十分明显),所以使用手机系统摄像头加屏幕共享往往会获得更清晰的画面,但是也存在一定弊端。 使用钉钉摄像头可以在钉钉页面实时观察学生状态,而屏幕共享后因为需要切屏所以并不能这样做(当然你可以使用小窗) 就是上述所说的,系统摄像头的显示时根据手机摆放位置决定的,而屏幕共享的显示方向时和手机系统的方向一致的,所以会造成显示画面翻转的问题。 解决方法使用屏幕共享加系统摄像头导致屏幕翻转的问题解决方法很少,如果你爱捣鼓,你当然可以找一个摄像机app然后翻转画面,当然这很麻烦,也很粗暴。其他的方法(不如说建议): 老师可以先把题的解析写下,然后拍成照片,然后开启屏幕共享利用图片讲(当然这效果很不好,相当于一种妥协) 用一个手机支架或者找一些刁钻的物品做一个支撑平台,正着放置手机。 除了上述方法这个时候老师就没有其他办法了,但是参会者(学生)可以用其他方法自行解决这个问题。 ②使用钉钉视频会议自带摄像机的问题使用钉钉会议自带摄像机,屏幕的方向和手机的显示方向一致。所以,手机因摆放和显示方向不一致导致屏幕显示方向的问题是存在的。这个问题可以通过修改钉钉手机设置来解决,步骤如下: 手机钉钉主页面,点击头像 这个方法可以把竖向画面变成横向,但具体效果本人没有测试过,所以并不保证有效。 二、参会者(同学)可以采取的措施 (强烈建议老师观看此篇直接跳转第四条)因为手机屏幕可以随意翻转,所以当然不存在屏幕会倒着的问题,所以这里只讨论电脑端的操作方法。 注:以下方法适用于所有电脑软件的屏幕旋转问题。 1、利用系统旋转首先我们介绍一个最简单的也是最普遍的方法,使用Windows自带的屏幕旋转功能(什么,你告诉我你电脑不是windows系统?大佬另请高门吧) ①快捷键:Ctrl + Alt + 任意箭头键(四个快箭头分别代表四个方向)因电脑系统版本问题,可能存在快捷键无法使用的问题,我们可以用另外一种方法达到相似的效果。 ②右键点击桌面 因为系统版本问题,页面显示可能有所不同,请找到”显示方向”选择相应方向即可更改。 2、利用显卡或显示器旋转这个根据显卡不同,和显示器不同,是否支持和具体方法也不尽相同,由于上一个方法已经足够适用,故在此不赘述这个方法,有兴趣可自行百度。 3、利用屏幕录制工具进行旋转呢(不爱折腾的可以不用)听了上述方法,可能有人觉得这种方法并不优雅,因为其并不能实现单独窗口的旋转。那么是否可以达到这种效果? 在查阅的部分博客后,我发现Windows是自带屏幕旋转的API的,包括python也有Screen Rotate的库,如果有大佬可以做一个软件那就太感谢了,但是对于向我这样的小白来说,采取了一种更为傻瓜式的做法,那就是利用窗口录制软件进行实时录制,然后再将录制的画面进行旋转即可,这里我们用到软件OBS Studio来演示。(当然这意味着你的电脑不能太卡) 当然你也可以用其他相似功能的软件,但是我强烈推荐OBS,免费还好用,关于OBS的使用教程点击这里对于本次使用的功能,你并不需要完全了解所有功能仅需了解基本安装以及初次使用的配置即可,当然你也可以在百度上搜索其他教程。 我们打开OBS,初次使用建议选择”仅使用虚拟摄像机” 点击”来源”中的加号,选择窗口采集。 点击确定 点击采集方式,如果此时你已经进入了视频会议,就会显示出钉钉会议。 点击之后点击确定,发现在”来源”里多出一个东西。 右击他,点击变换,就可以看到旋转多少度了。 之后可以在上面调整大小即可。 但是这个方法存在一个弊端,那就是钉钉的视频会议窗口如果被切屏,就会自动变成小窗,这时候屏幕采集就会卡住,也就是说你要保证没有页面处于全屏状态以保证钉钉没有启动小窗。 (如下图,第一张图显示的是正常状态,窗口并没有全屏,钉钉视频会议的窗口在右侧。第二张是窗口全屏后,发现小窗被启用,窗口采集无法正常适用) 4、利用工具人完成上述操作如果你是老师,您并不想麻烦自己,但是又想给同学一个良好的学习环境,你可以让某个同学利用OBS的虚拟摄像机功能达到一人配置,造福全班的效果。 首先你要找一个同学(电脑好用一点的同学),让他完成”3”中的操作。 当某人完成”3”中的所有操作后,点击右下角”控件”中的启动虚拟摄像机。 打开钉钉视频会议页面,点击设置,然后点击视频,继续点击摄像头,选择”OBS”开头的。 之后我们让其他同学都看这位同学的屏幕,我们就可以看到翻转过来的老师的画面了。(当然你要让这位同学仔细阅读上文,不要切全屏,以保证所有同学的观看体验) 如果有老师需要技术支持,也欢迎到博客首页获取我的联系方式,以联系我。(博客初次访问速度可能较慢,请大家耐心等待,长时间无反应可以刷新重试) 至此,我已经讲完了,欢迎大家阅读我的其他文章,也欢迎大家转发这篇博客给老师。如果有什么其他的好方法或者出现的问题,也可以在下方留言。(评论区的加载需要一段时间,如果你没有看到评论区,请稍等或刷新) import { init } from 'https://unpkg.com/@waline/client@v2/dist/waline.mjs'; init({ el: '#waline', serverURL: 'https://waline-ccr39.netlify.app/.netlify/functions/comment', reaction: [ 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_heart_eyes.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_joy.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_consider.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_sob.png', ], emoji: [ '//unpkg.com/@waline/emojis@1.1.0/bilibili', '//unpkg.com/@waline/emojis@1.1.0/weibo', '//unpkg.com/@waline/emojis@1.1.0/qq', ] });","raw":null,"content":null,"categories":[{"name":"技术","slug":"技术","permalink":"http://ccr39.github.io/categories/%E6%8A%80%E6%9C%AF/"}],"tags":[{"name":"杂谈","slug":"杂谈","permalink":"http://ccr39.github.io/tags/%E6%9D%82%E8%B0%88/"}]},{"title":"浅谈我的学校","slug":"about_school","date":"2022-12-11T08:23:32.000Z","updated":"2024-12-13T06:08:33.368Z","comments":true,"path":"生活/about_school/","link":"","permalink":"http://ccr39.github.io/%E7%94%9F%E6%B4%BB/about_school/","excerpt":"","keywords":null,"text":"我?本人就读衡水志臻清河校区(衡水二中的分校)。 其他内容省略 如何评价衡水志臻RT请在评论留言 相关链接清河志臻吧清河志臻二次元同学群小游戏:吃掉衡水志臻 import { init } from 'https://unpkg.com/@waline/client@v2/dist/waline.mjs'; init({ el: '#waline', serverURL: 'https://waline-ccr39.netlify.app/.netlify/functions/comment', reaction: [ 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_heart_eyes.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_joy.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_consider.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_sob.png', ], emoji: [ '//unpkg.com/@waline/emojis@1.1.0/bilibili', '//unpkg.com/@waline/emojis@1.1.0/weibo', '//unpkg.com/@waline/emojis@1.1.0/qq', ] });","raw":null,"content":null,"categories":[{"name":"生活","slug":"生活","permalink":"http://ccr39.github.io/categories/%E7%94%9F%E6%B4%BB/"}],"tags":[{"name":"杂谈","slug":"杂谈","permalink":"http://ccr39.github.io/tags/%E6%9D%82%E8%B0%88/"}]},{"title":"ACGN插画(一)","slug":"ACGN插画(一)","date":"2022-12-11T04:56:00.000Z","updated":"2024-12-13T05:55:47.322Z","comments":true,"path":"资源/ACGN插画(一)/","link":"","permalink":"http://ccr39.github.io/%E8%B5%84%E6%BA%90/ACGN%E6%8F%92%E7%94%BB(%E4%B8%80)/","excerpt":"","keywords":null,"text":"import { init } from 'https://unpkg.com/@waline/client@v2/dist/waline.mjs'; init({ el: '#waline', serverURL: 'https://waline-ccr39.netlify.app/.netlify/functions/comment', reaction: [ 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_heart_eyes.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_joy.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_consider.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_sob.png', ], emoji: [ '//unpkg.com/@waline/emojis@1.1.0/bilibili', '//unpkg.com/@waline/emojis@1.1.0/weibo', '//unpkg.com/@waline/emojis@1.1.0/qq', ] });","raw":null,"content":null,"categories":[{"name":"资源","slug":"资源","permalink":"http://ccr39.github.io/categories/%E8%B5%84%E6%BA%90/"}],"tags":[{"name":"图集","slug":"图集","permalink":"http://ccr39.github.io/tags/%E5%9B%BE%E9%9B%86/"}]},{"title":"基础计数原理与排列组合","slug":"基础计数原理与排列组合","date":"2022-12-10T16:00:00.000Z","updated":"2024-12-13T05:53:50.840Z","comments":true,"path":"转载/基础计数原理与排列组合/","link":"","permalink":"http://ccr39.github.io/%E8%BD%AC%E8%BD%BD/%E5%9F%BA%E7%A1%80%E8%AE%A1%E6%95%B0%E5%8E%9F%E7%90%86%E4%B8%8E%E6%8E%92%E5%88%97%E7%BB%84%E5%90%88/","excerpt":"","keywords":null,"text":"一、加法原理和乘法原理1、定义:①加法原理:加法原理是分类计数原理,常用于排列组合中,具体是指:做一件事情,完成它有N类方式,第一类方式有$M_1$种方法,第二类方式有$M_2$种方法,……,第n类方式有Mn种方法,那么完成这件事情共有$M_1+M_2+……+M_n$种方法。 口诀:类类独立 ②乘法原理:做一件事,完成它需要分成N个步骤,做第一步有$M_1$种不同的方法,做第二步有$M_2$种不同的方法,……,做第n步有$M_n$种不同的方法。那么完成这件事共有 $N=M_1×M_2×M_3×…×M_n$ 种不同的方法。 口诀:步步相关 2、例:(1)某中学八年级一班有12名男生,16名女生;二班有9名男生,17名女生。 问: 从这两个班的同学中,选择 1 名男生、1 名女生作为主持人。有几种选法? 利用乘法原理,总方案数等于 总男生数 * 总女生数 $ (12+9)* (16+17)= 693 $ 3、模运算在得数较大时,要每进行一步计算就取余。 模运算符合以下规律 (1)$$ (a-b)\\%p=(a\\%p-b\\%p)\\%p$$ (2)$$ (a + b)\\%p=(a\\%p+b\\% p)\\%p$$ (3)$$(a*b)\\%p=(a\\%p*b\\%p)\\%p$$ (4)$$(a^b)\\%p=((a\\%p)^b)\\%p$$ 二、排列与组合1、排列数定义:从 n 个人里面选出 m 个人站成一排,方案数是: n ⋅ (n − 1) ⋯ (n − m + 1) = $ \\frac{ n ! }{ (n-m)! } $。我们将它称为排列数。 排列数用 $A^m_n$ 表示“从 n 个元素里面取 m 个元素,排成一排的方案数”,也就是$ A^m_n $ = $ \\frac{ n ! }{ (n-m)! } $。 2、组合数(1) 定义:用 $C^m_n$ 表示“从 n 个元素里面选出 m 个元素”的方案数,我们将它称为组合数。 (2) 公式:组合数的递推公式,称为帕斯卡公式。 $C^m_n$ = $C^{m-1}_{n-1}$ + $C^{m-1}_n$ $C^n_0$=1 ; $C^n_n$=1 ; $C^0_0$=1组合数的通项公式 $C^m_n$ = $\\frac{A_n^m}{A_m^m}$ = $\\frac{n\\cdot(n-1)\\cdot\\cdot\\cdot(n-m+1)}{m(m-1)\\cdot\\cdot\\cdot2\\cdot1}$ = $\\frac{n!}{m!\\cdot(n-m)!}$互补性质 $C_n^m=C^{n-m}_n$ (3) 代码实现①通项公式 long long fac(int n) { long long f=1; for(int i=n;i>0;i--) f *= i; return f; }//求阶乘 long long C(int n, int m) { return fac(n)/(fac(n - m)*fac(m)); } ②递归公式 for (int i=0;i<=21;i++) { C[i][0] = C[i][i] = 1; for (int j=1;j<i;j++) C[i][j]=C[i-1][j]+C[i-1][j-1] ; //递推 } 文章转载于本人原博客 import { init } from 'https://unpkg.com/@waline/client@v2/dist/waline.mjs'; init({ el: '#waline', serverURL: 'https://waline-ccr39.netlify.app/.netlify/functions/comment', reaction: [ 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_heart_eyes.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_joy.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_consider.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_sob.png', ], emoji: [ '//unpkg.com/@waline/emojis@1.1.0/bilibili', '//unpkg.com/@waline/emojis@1.1.0/weibo', '//unpkg.com/@waline/emojis@1.1.0/qq', ] });","raw":null,"content":null,"categories":[{"name":"转载","slug":"转载","permalink":"http://ccr39.github.io/categories/%E8%BD%AC%E8%BD%BD/"}],"tags":[{"name":"算法","slug":"算法","permalink":"http://ccr39.github.io/tags/%E7%AE%97%E6%B3%95/"},{"name":"数学","slug":"数学","permalink":"http://ccr39.github.io/tags/%E6%95%B0%E5%AD%A6/"}]},{"title":"hellow world","slug":"hellow-world","date":"2022-12-10T09:13:34.374Z","updated":"2024-12-13T05:57:04.408Z","comments":true,"path":"技术/hellow-world/","link":"","permalink":"http://ccr39.github.io/%E6%8A%80%E6%9C%AF/hellow-world/","excerpt":"","keywords":null,"text":"一、博客介绍经历了大概一个星期的搭建,本博客正式建立于2022/12/11。 博客采用的时hexo的框架以及Sakura的主题,感谢主题原作者以及修改者。 博客采用的是静态搭建,代码托管于github上。(这也直接导致了不进行代理时打开速度极慢) 至于为什么不用服务器并购买域名,你看我有这个钱吗。 未来预计会在gitee上进行镜像同步部署,以此来解决国内访问的问题。 二、捣鼓博客的经历关于博客的搭建,走的过的坑可太多了。 最开始环境的配置一番风顺。 第一个踩坑的环节就是git的push超时的问题,经历一晚上的斗争,发现无论是是否使用代理,push总是超时,结果等到第二天,居然直接成功push。(所以说这既是玄学吗) 第二个环节就是主题的配置,Sakura主题原本是一个WordPress主题,最初创建的时间大概是2017年(甚至更早),hojun大佬把主题移植到hexo上,也是2018年的事情了,而且主题最后的维护在2019年,换句话说,我手上的主题,就是一个烂摊子,需要各种调试。于是我就开始来回穿梭于目录下的js文件,试图修改各种东西。 第三个环节就是自己新添加的功能上,添加评论区的过程比较顺利,就不提了,但是添加看板娘可太不容易了。首先第一个问题,就是垃圾的npm,使用npm下载资源包,疯狂报错,用修复指令修复,居然给我来了诋毁连环报错(是的,就是修完了他又让你修,循环下去)。最后我发现了利器yarn,先用npm install -g yarn安装,然后再用yarn add来下载资源包,彻底解决了报错的问题。 可这还没完,很快我就又发现了一个问题,就是在静态页面上不能直接链接到已有的文件。什么意思,打个比方,假如我有一个图片存在.\\img目录中,当我在index.html中配置src=".\\img\\图片.png"时无法加载。调用f12控制台,打开源码,可以发现目录下方并不存在图片,打开github的仓库,又发现文件存在于目录中,这个问题,至今未得到解决。最后我想到了用外链的方法,既然文件确实存在于github中,那么可以用https://raw.githubusercontent.com/UeserID/仓库ID/master/img/图片.png的方式调用(ps.如果你想问为什么不用图床,我想书评图片指的是一个例子,实际上是一个json文件)。但是这样调用的速度,只能说dddd了。 有别的方法吗,我尝试在gitee上用同样的方法,调用gitee的文件,但是令我没想到的是,居然毫无卵用。最后我发现能用cdn的方法加速,但是用jsdeliver有一个弊端,那就是有500mb的限制,不能直接在原仓库使用,最后我选择新建了一个仓库,至此终于结束。 最后就是图床的问题,我使用了sm.ms的api和picgo+typora的配置(至于为什么不用gitee图床,因为稳定性问题) 三、总结总之虽然经历了很多东西,但是博客也算是建好了,也学到了不少东西,总的来说:值! import { init } from 'https://unpkg.com/@waline/client@v2/dist/waline.mjs'; init({ el: '#waline', serverURL: 'https://waline-ccr39.netlify.app/.netlify/functions/comment', reaction: [ 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_heart_eyes.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_joy.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_dog_consider.png', 'https://unpkg.com/@waline/emojis@1.1.0/weibo/weibo_sob.png', ], emoji: [ '//unpkg.com/@waline/emojis@1.1.0/bilibili', '//unpkg.com/@waline/emojis@1.1.0/weibo', '//unpkg.com/@waline/emojis@1.1.0/qq', ] });","raw":null,"content":null,"categories":[{"name":"技术","slug":"技术","permalink":"http://ccr39.github.io/categories/%E6%8A%80%E6%9C%AF/"}],"tags":[{"name":"悦读","slug":"悦读","permalink":"http://ccr39.github.io/tags/%E6%82%A6%E8%AF%BB/"}]}]}