<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-cn"><generator uri="https://gohugo.io/" version="0.147.7">Hugo</generator><title type="html">有呀</title><link href="https://nuoea.com/categories/%E6%8A%98%E8%85%BE/" rel="alternate" type="text/html" title="html"/><link href="https://nuoea.com/categories/%E6%8A%98%E8%85%BE/index.xml" rel="alternate" type="application/rss+xml" title="rss"/><updated>2026-07-07T04:03:54+00:00</updated><id>https://nuoea.com/categories/%E6%8A%98%E8%85%BE/</id><entry><title type="html">部署轻量友链朋友圈</title><link href="https://nuoea.com/friend-circle-lite/" rel="alternate" type="text/html"/><id>https://nuoea.com/friend-circle-lite/</id><published>2024-12-11T20:17:21+08:00</published><updated>2024-12-11T20:17:21+08:00</updated><content type="html"><![CDATA[<h2 id="前言">前言</h2>
<p>这两天突然发现，之前使用极简模式部署好的友链朋友圈没法获取到数据了。看了Github仓库才知道原项目已经停止支持了，取而代之的就是这个轻量友链朋友圈。</p>
<p>不知道是不是因为这个项目是为了 <code>hexo</code> 打造的原因，项目看了很久，愣是没看明白。直到把详细文档研究了一通，才大概明白了运行的原理。</p>
<p>其实严格来讲，该项目主要分为三个步骤：</p>
<ul>
<li>获取朋友圈JSON</li>
<li>配置 Github Action</li>
<li>拿到朋友圈文章列表JSON</li>
</ul>
<h2 id="获取朋友圈json">获取朋友圈JSON</h2>
<p>顾名思义，该步骤通过以下代码，将指定页面上的友链信息，直接转换成为一个 <code>friend.json</code> 。</p>
<p>原代码如下：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-JavaScript" data-lang="JavaScript"><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">YML</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">require</span>(<span style="color:#e6db74">&#39;yamljs&#39;</span>)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">fs</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">require</span>(<span style="color:#e6db74">&#39;fs&#39;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">friends</span> <span style="color:#f92672">=</span> [],
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">data_f</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">YML</span>.<span style="color:#a6e22e">parse</span>(<span style="color:#a6e22e">fs</span>.<span style="color:#a6e22e">readFileSync</span>(<span style="color:#e6db74">&#39;source/_data/link.yml&#39;</span>).<span style="color:#a6e22e">toString</span>().<span style="color:#a6e22e">replace</span>(<span style="color:#e6db74">/(?&lt;=rss:)\s*\n/g</span>, <span style="color:#e6db74">&#39; &#34;&#34;\n&#39;</span>));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">data_f</span>.<span style="color:#a6e22e">forEach</span>((<span style="color:#a6e22e">entry</span>, <span style="color:#a6e22e">index</span>) =&gt; {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">let</span> <span style="color:#a6e22e">lastIndex</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">2</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">index</span> <span style="color:#f92672">&lt;</span> <span style="color:#a6e22e">lastIndex</span>) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">filteredLinkList</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">entry</span>.<span style="color:#a6e22e">link_list</span>.<span style="color:#a6e22e">filter</span>(<span style="color:#a6e22e">linkItem</span> =&gt; <span style="color:#f92672">!</span><span style="color:#a6e22e">blacklist</span>.<span style="color:#a6e22e">includes</span>(<span style="color:#a6e22e">linkItem</span>.<span style="color:#a6e22e">name</span>));
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">friends</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">friends</span>.<span style="color:#a6e22e">concat</span>(<span style="color:#a6e22e">filteredLinkList</span>);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>});
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// 根据规定的格式构建 JSON 数据
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">friendData</span> <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">friends</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">friends</span>.<span style="color:#a6e22e">map</span>(<span style="color:#a6e22e">item</span> =&gt; {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> [<span style="color:#a6e22e">item</span>.<span style="color:#a6e22e">name</span>, <span style="color:#a6e22e">item</span>.<span style="color:#a6e22e">link</span>, <span style="color:#a6e22e">item</span>.<span style="color:#a6e22e">avatar</span>];
</span></span><span style="display:flex;"><span>    })
</span></span><span style="display:flex;"><span>};
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// 将 JSON 对象转换为字符串
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">friendJSON</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">JSON</span>.<span style="color:#a6e22e">stringify</span>(<span style="color:#a6e22e">friendData</span>, <span style="color:#66d9ef">null</span>, <span style="color:#ae81ff">2</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// 写入 friend.json 文件
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#a6e22e">fs</span>.<span style="color:#a6e22e">writeFileSync</span>(<span style="color:#e6db74">&#39;./source/friend.json&#39;</span>, <span style="color:#a6e22e">friendJSON</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#e6db74">&#39;friend.json 文件已生成。&#39;</span>);
</span></span></code></pre></div><p>比较遗憾的是，该代码仅适用于 <code>HEXO</code> 博客程序，如果想要用在<code>HUGO</code>中，需要做如下修改：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-JavaScript" data-lang="JavaScript"><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">cheerio</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">require</span>(<span style="color:#e6db74">&#39;cheerio&#39;</span>);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">fs</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">require</span>(<span style="color:#e6db74">&#39;fs&#39;</span>);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">path</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">require</span>(<span style="color:#e6db74">&#39;path&#39;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// 获取项目根目录的路径
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">projectRoot</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">process</span>.<span style="color:#a6e22e">cwd</span>();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// 读取 HTML 文件内容
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">htmlFilePath</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">path</span>.<span style="color:#a6e22e">join</span>(<span style="color:#a6e22e">projectRoot</span>, <span style="color:#e6db74">&#39;public&#39;</span>, <span style="color:#e6db74">&#39;links&#39;</span>, <span style="color:#e6db74">&#39;index.html&#39;</span>);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">htmlContent</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">fs</span>.<span style="color:#a6e22e">readFileSync</span>(<span style="color:#a6e22e">htmlFilePath</span>).<span style="color:#a6e22e">toString</span>();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// 使用 cheerio 解析 HTML
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">$</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">cheerio</span>.<span style="color:#a6e22e">load</span>(<span style="color:#a6e22e">htmlContent</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// 创建一个空的 friends 数组
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">friends</span> <span style="color:#f92672">=</span> [];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// 假设在 HTML 中每个好友信息存储在 &lt;div class=&#34;friend-item&#34;&gt; 中，
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">// 并且每个条目包含 &lt;a class=&#34;username&#34;&gt;、&lt;img class=&#34;avatar&#34;&gt; 和 &lt;a class=&#34;link&#34;&gt;
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#a6e22e">$</span>(<span style="color:#e6db74">&#39;.friend-item&#39;</span>).<span style="color:#a6e22e">each</span>((<span style="color:#a6e22e">index</span>, <span style="color:#a6e22e">element</span>) =&gt; {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">username</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">$</span>(<span style="color:#a6e22e">element</span>).<span style="color:#a6e22e">find</span>(<span style="color:#e6db74">&#39;.username&#39;</span>).<span style="color:#a6e22e">text</span>().<span style="color:#a6e22e">trim</span>();  <span style="color:#75715e">// 提取用户名
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">link</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">$</span>(<span style="color:#a6e22e">element</span>).<span style="color:#a6e22e">find</span>(<span style="color:#e6db74">&#39;.link&#39;</span>).<span style="color:#a6e22e">attr</span>(<span style="color:#e6db74">&#39;href&#39;</span>);  <span style="color:#75715e">// 提取链接
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">avatar</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">$</span>(<span style="color:#a6e22e">element</span>).<span style="color:#a6e22e">find</span>(<span style="color:#e6db74">&#39;.avatar&#39;</span>).<span style="color:#a6e22e">attr</span>(<span style="color:#e6db74">&#39;src&#39;</span>);  <span style="color:#75715e">// 提取头像
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// 如果都存在，添加到 friends 数组
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">username</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#a6e22e">link</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#a6e22e">avatar</span>) {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">friends</span>.<span style="color:#a6e22e">push</span>({
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">name</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">username</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">link</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">link</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">avatar</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">avatar</span>
</span></span><span style="display:flex;"><span>        });
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>});
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// 根据规定的格式构建 JSON 数据
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">friendData</span> <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">friends</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">friends</span>.<span style="color:#a6e22e">map</span>(<span style="color:#a6e22e">item</span> =&gt; {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> [<span style="color:#a6e22e">item</span>.<span style="color:#a6e22e">name</span>, <span style="color:#a6e22e">item</span>.<span style="color:#a6e22e">link</span>, <span style="color:#a6e22e">item</span>.<span style="color:#a6e22e">avatar</span>];
</span></span><span style="display:flex;"><span>    })
</span></span><span style="display:flex;"><span>};
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// 将 JSON 对象转换为字符串
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">friendJSON</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">JSON</span>.<span style="color:#a6e22e">stringify</span>(<span style="color:#a6e22e">friendData</span>, <span style="color:#66d9ef">null</span>, <span style="color:#ae81ff">2</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// 写入 friend.json 文件到根目录
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#a6e22e">fs</span>.<span style="color:#a6e22e">writeFileSync</span>(<span style="color:#a6e22e">path</span>.<span style="color:#a6e22e">join</span>(<span style="color:#a6e22e">__dirname</span>, <span style="color:#e6db74">&#39;friend.json&#39;</span>), <span style="color:#a6e22e">friendJSON</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#e6db74">&#39;friend.json 文件已生成。&#39;</span>);
</span></span></code></pre></div><p>将该代码文件保存在根目录Link.js文件中。运行：</p>
<pre tabindex="0"><code>node link.js
</code></pre><p>就可以得到 <code>friend.json</code> 文件。</p>
<p>需要注意的是，这里需要用到 <code>cheerio</code> 解析 HTML。所以在运行前，需要：</p>
<pre tabindex="0"><code>npm install cheerio
</code></pre><p>以下就是JSON格式文件示例：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-JSON" data-lang="JSON"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;friends&#34;</span>: [
</span></span><span style="display:flex;"><span>    [
</span></span><span style="display:flex;"><span>	    <span style="color:#e6db74">&#34;林木木&#34;</span>,
</span></span><span style="display:flex;"><span>	    <span style="color:#e6db74">&#34;https://immmmm.com&#34;</span>,
</span></span><span style="display:flex;"><span>	    <span style="color:#e6db74">&#34;https://cravatar.cn/avatar/ba83fa02fc4b2ba621514941307e21be.jpeg?s=400&#34;</span>
</span></span><span style="display:flex;"><span>    ],
</span></span><span style="display:flex;"><span>    [
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;山卜方&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;https://novcu.com&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;https://cravatar.cn/avatar/6ebab96f3131621c51c08370d3c996f0.jpeg?s=400&#34;</span>
</span></span><span style="display:flex;"><span>    ],
</span></span><span style="display:flex;"><span>    [
</span></span><span style="display:flex;"><span>		<span style="color:#e6db74">&#34;大大的小蜗牛&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;https://eallion.com&#34;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;https://cravatar.cn/avatar/171e4c30959e8c077a6c58b958624b31.jpeg?s=400&#34;</span>
</span></span><span style="display:flex;"><span>    ]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">}</span> 
</span></span></code></pre></div><h2 id="配置-github-action">配置 Github Action</h2>
<p>在 fork 了仓库：<a href="https://github.com/willow-god/Friend-Circle-Lite">Friend-Circle-Lite</a> 之后，只需要修改仓库中的 <code>config.yaml</code> 文件</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-YAML" data-lang="YAML"><span style="display:flex;"><span><span style="color:#f92672">spider_settings</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">enable</span>: <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">json_url</span>: <span style="color:#e6db74">&#34;https://&lt;你的地址&gt;/friend.json&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">article_count</span>: <span style="color:#ae81ff">5</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">merge_result</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">enable</span>: <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">merge_json_url</span>: <span style="color:#e6db74">&#34;&lt;你的地址&gt;&#34;</span>
</span></span></code></pre></div><p>如果需要邮件推送功能的，跟随官方文档完成相应配置即可。</p>
<h2 id="拿到朋友圈文章列表json">拿到朋友圈文章列表JSON</h2>
<p>在完成所有配置后，就可以手动或者自动的运行 <code>Github Action</code> ，该Action就会根据我们提供的 <code>friend.json</code> 拿到友链中所有朋友更新的文章啦。最后会在page分支中，生成一个 <code>all.json</code> ，通过调用这个文件，就可以做前端渲染了。</p>
<p>大功告成。</p>]]></content><category scheme="https://nuoea.com/categories/%E6%8A%98%E8%85%BE" term="%E6%8A%98%E8%85%BE" label="折腾"/><category scheme="https://nuoea.com/tags/%E6%9C%8B%E5%8F%8B%E5%9C%88" term="%E6%9C%8B%E5%8F%8B%E5%9C%88" label="朋友圈"/><category scheme="https://nuoea.com/tags/%E8%BF%9E%E6%8E%A5" term="%E8%BF%9E%E6%8E%A5" label="连接"/></entry><entry><title type="html">给Memos页面增加编辑、归档及删除功能</title><link href="https://nuoea.com/memos-add-edit-and-archive/" rel="alternate" type="text/html"/><id>https://nuoea.com/memos-add-edit-and-archive/</id><published>2023-07-19T14:44:15+08:00</published><updated>2023-07-19T14:44:15+08:00</updated><content type="html"><![CDATA[<h2 id="更新">更新</h2>
<ul>
<li>2023-07-19 新增删除功能；</li>
</ul>
<h2 id="前言">前言</h2>
<p>书接上回，继续完善<code>Memos</code>页面。这次给页面增加<code>编辑</code>和<code>归档</code>功能，让我们的<code>Memos</code>页面使用起来更加的方便。</p>
<h2 id="说明">说明</h2>
<p>值得一提的是，两个功能都需要Memos发布框的支持。还没有折腾的同学看这里：<a href="https://nuoea.com/add-memos-editor/"> Memos页面添加发布框 </a></p>
<h2 id="编辑">编辑</h2>
<ul>
<li>首先，给你的每一条Memos 增加一个按钮，并绑定一个点击事件:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-html" data-lang="html"><span style="display:flex;"><span>&lt;<span style="color:#f92672">button</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;edit-btn&#34;</span> <span style="color:#a6e22e">onclick</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;editMemo(&#39;+JSON.stringify(data[i]).replace(/&#34;</span><span style="color:#960050;background-color:#1e0010">/</span><span style="color:#a6e22e">g</span><span style="color:#960050;background-color:#1e0010">,</span> <span style="color:#960050;background-color:#1e0010">&#39;&amp;</span><span style="color:#a6e22e">quot</span><span style="color:#960050;background-color:#1e0010">;&#39;)+&#39;)&#34;</span>&gt;编辑&lt;/<span style="color:#f92672">button</span>&gt;
</span></span></code></pre></div><ul>
<li>添加点击事件</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">editMemo</span>(<span style="color:#a6e22e">e</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">memoContent</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">e</span>.<span style="color:#a6e22e">content</span>,<span style="color:#a6e22e">memoId</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">e</span>.<span style="color:#a6e22e">id</span>,<span style="color:#a6e22e">memoRelationList</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">e</span>.<span style="color:#a6e22e">relationList</span>,<span style="color:#a6e22e">memoResourceList</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">e</span>.<span style="color:#a6e22e">resourceList</span>,<span style="color:#a6e22e">memoVisibility</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">e</span>.<span style="color:#a6e22e">visibility</span>;
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">getEditor</span> <span style="color:#f92672">=</span> window.<span style="color:#a6e22e">localStorage</span> <span style="color:#f92672">&amp;&amp;</span> window.<span style="color:#a6e22e">localStorage</span>.<span style="color:#a6e22e">getItem</span>(<span style="color:#e6db74">&#34;memos-editor-display&#34;</span>),
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">memosOpenId</span> <span style="color:#f92672">=</span> window.<span style="color:#a6e22e">localStorage</span> <span style="color:#f92672">&amp;&amp;</span> window.<span style="color:#a6e22e">localStorage</span>.<span style="color:#a6e22e">getItem</span>(<span style="color:#e6db74">&#34;memos-access-token&#34;</span>);
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span>(<span style="color:#a6e22e">memosOpenId</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#a6e22e">getEditor</span> <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;show&#34;</span>){
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">memosTextarea</span>.<span style="color:#a6e22e">value</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">memoContent</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">memosTextarea</span>.<span style="color:#a6e22e">style</span>.<span style="color:#a6e22e">height</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">memosTextarea</span>.<span style="color:#a6e22e">scrollHeight</span> <span style="color:#f92672">+</span> <span style="color:#e6db74">&#39;px&#39;</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">submitMemoBtn</span>.<span style="color:#a6e22e">classList</span>.<span style="color:#a6e22e">add</span>(<span style="color:#e6db74">&#34;d-none&#34;</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">editMemoDom</span>.<span style="color:#a6e22e">classList</span>.<span style="color:#a6e22e">remove</span>(<span style="color:#e6db74">&#34;d-none&#34;</span>);
</span></span><span style="display:flex;"><span>    document.<span style="color:#a6e22e">body</span>.<span style="color:#a6e22e">scrollIntoView</span>({<span style="color:#a6e22e">behavior</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;smooth&#39;</span>});
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">editMemoBtn</span>.<span style="color:#a6e22e">addEventListener</span>(<span style="color:#e6db74">&#34;click&#34;</span>, <span style="color:#66d9ef">function</span> () {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">memosOpenId</span> <span style="color:#f92672">=</span> window.<span style="color:#a6e22e">localStorage</span> <span style="color:#f92672">&amp;&amp;</span> window.<span style="color:#a6e22e">localStorage</span>.<span style="color:#a6e22e">getItem</span>(<span style="color:#e6db74">&#34;memos-access-token&#34;</span>),
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">memoContent</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">memosTextarea</span>.<span style="color:#a6e22e">value</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">memoResourceList</span> <span style="color:#f92672">=</span> window.<span style="color:#a6e22e">localStorage</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#a6e22e">JSON</span>.<span style="color:#a6e22e">parse</span>(window.<span style="color:#a6e22e">localStorage</span>.<span style="color:#a6e22e">getItem</span>(<span style="color:#e6db74">&#34;memos-resource-list&#34;</span>)) <span style="color:#f92672">?</span> window.<span style="color:#a6e22e">localStorage</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#a6e22e">JSON</span>.<span style="color:#a6e22e">parse</span>(window.<span style="color:#a6e22e">localStorage</span>.<span style="color:#a6e22e">getItem</span>(<span style="color:#e6db74">&#34;memos-resource-list&#34;</span>)) <span style="color:#f92672">:</span> <span style="color:#a6e22e">e</span>.<span style="color:#a6e22e">resourceList</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">memoVisibility</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">memosVisibilitySelect</span>.<span style="color:#a6e22e">value</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">let</span> <span style="color:#a6e22e">TAG_REG</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">/(?&lt;=#)([^#\s!.,;:?&#34;&#39;()]+)(?= )/g</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">let</span> <span style="color:#a6e22e">memosTag</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">memoContent</span>.<span style="color:#a6e22e">match</span>(<span style="color:#a6e22e">TAG_REG</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">let</span> <span style="color:#a6e22e">hasContent</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">memoContent</span>.<span style="color:#a6e22e">length</span> <span style="color:#f92672">!==</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">hasContent</span>) {
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">memoUrl</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">memosPath</span><span style="color:#f92672">+</span><span style="color:#e6db74">&#34;/api/v1/memo/&#34;</span><span style="color:#f92672">+</span><span style="color:#a6e22e">memoId</span><span style="color:#f92672">+</span><span style="color:#e6db74">&#34;?openId=&#34;</span><span style="color:#f92672">+</span><span style="color:#a6e22e">memosOpenId</span>;
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">memoBody</span> <span style="color:#f92672">=</span> {<span style="color:#a6e22e">content</span><span style="color:#f92672">:</span><span style="color:#a6e22e">memoContent</span>,<span style="color:#a6e22e">id</span><span style="color:#f92672">:</span><span style="color:#a6e22e">memoId</span>,<span style="color:#a6e22e">relationList</span><span style="color:#f92672">:</span><span style="color:#a6e22e">memoRelationList</span>,<span style="color:#a6e22e">resourceList</span><span style="color:#f92672">:</span><span style="color:#a6e22e">memoResourceList</span>,<span style="color:#a6e22e">visibility</span><span style="color:#f92672">:</span><span style="color:#a6e22e">memoVisibility</span>}
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">fetch</span>(<span style="color:#a6e22e">memoUrl</span>, {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">method</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;PATCH&#39;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">body</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">JSON</span>.<span style="color:#a6e22e">stringify</span>(<span style="color:#a6e22e">memoBody</span>),
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">headers</span><span style="color:#f92672">:</span> {
</span></span><span style="display:flex;"><span>          <span style="color:#e6db74">&#39;Content-Type&#39;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;application/json&#39;</span>
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>      }).<span style="color:#a6e22e">then</span>(<span style="color:#66d9ef">function</span>(<span style="color:#a6e22e">res</span>) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">res</span>.<span style="color:#a6e22e">status</span> <span style="color:#f92672">==</span> <span style="color:#ae81ff">200</span>) {
</span></span><span style="display:flex;"><span>          <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">memosTag</span> <span style="color:#f92672">!==</span> <span style="color:#66d9ef">null</span>) {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">memoTagUrl</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">memosPath</span> <span style="color:#f92672">+</span> <span style="color:#e6db74">&#34;/api/v1/tag?openId=&#34;</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">memosOpenId</span>;
</span></span><span style="display:flex;"><span>            (<span style="color:#66d9ef">async</span> () =&gt; {
</span></span><span style="display:flex;"><span>              <span style="color:#66d9ef">for</span> <span style="color:#66d9ef">await</span> (<span style="color:#66d9ef">const</span> <span style="color:#a6e22e">i</span> <span style="color:#66d9ef">of</span> <span style="color:#a6e22e">memosTag</span>) {
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">response</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">await</span> <span style="color:#a6e22e">fetch</span>(<span style="color:#a6e22e">memoTagUrl</span>, {
</span></span><span style="display:flex;"><span>                  <span style="color:#a6e22e">method</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;POST&#39;</span>,
</span></span><span style="display:flex;"><span>                  <span style="color:#a6e22e">headers</span><span style="color:#f92672">:</span> {
</span></span><span style="display:flex;"><span>                    <span style="color:#e6db74">&#39;Content-Type&#39;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;application/json&#39;</span>
</span></span><span style="display:flex;"><span>                  },
</span></span><span style="display:flex;"><span>                  <span style="color:#a6e22e">body</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">JSON</span>.<span style="color:#a6e22e">stringify</span>({
</span></span><span style="display:flex;"><span>                    <span style="color:#a6e22e">name</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">i</span>
</span></span><span style="display:flex;"><span>                  })
</span></span><span style="display:flex;"><span>                });
</span></span><span style="display:flex;"><span>              }
</span></span><span style="display:flex;"><span>            })();
</span></span><span style="display:flex;"><span>          }
</span></span><span style="display:flex;"><span>          <span style="color:#a6e22e">cocoMessage</span>.<span style="color:#a6e22e">success</span>(
</span></span><span style="display:flex;"><span>          <span style="color:#e6db74">&#39;保存成功&#39;</span>,
</span></span><span style="display:flex;"><span>          ()=&gt;{
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">submitMemoBtn</span>.<span style="color:#a6e22e">classList</span>.<span style="color:#a6e22e">remove</span>(<span style="color:#e6db74">&#34;d-none&#34;</span>);
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">editMemoDom</span>.<span style="color:#a6e22e">classList</span>.<span style="color:#a6e22e">add</span>(<span style="color:#e6db74">&#34;d-none&#34;</span>);
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">location</span>.<span style="color:#a6e22e">reload</span>();
</span></span><span style="display:flex;"><span>          })
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>      })
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  })
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">cancelEditBtn</span>.<span style="color:#a6e22e">addEventListener</span>(<span style="color:#e6db74">&#34;click&#34;</span>, <span style="color:#66d9ef">function</span> () {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span><span style="color:#a6e22e">editMemoDom</span>.<span style="color:#a6e22e">classList</span>.<span style="color:#a6e22e">contains</span>(<span style="color:#e6db74">&#34;d-none&#34;</span>)) {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">memosTextarea</span>.<span style="color:#a6e22e">value</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;&#39;</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">memosTextarea</span>.<span style="color:#a6e22e">style</span>.<span style="color:#a6e22e">height</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;inherit&#39;</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">editMemoDom</span>.<span style="color:#a6e22e">classList</span>.<span style="color:#a6e22e">add</span>(<span style="color:#e6db74">&#34;d-none&#34;</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">submitMemoBtn</span>.<span style="color:#a6e22e">classList</span>.<span style="color:#a6e22e">remove</span>(<span style="color:#e6db74">&#34;d-none&#34;</span>);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>})
</span></span></code></pre></div><h2 id="归档">归档</h2>
<ul>
<li>首先，还是给你的每一条Memos 增加一个按钮，并绑定一个点击事件:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-html" data-lang="html"><span style="display:flex;"><span>&lt;<span style="color:#f92672">button</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;archive-btn&#34;</span> <span style="color:#a6e22e">onclick</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;archiveMemo(\&#39;&#39;+data[i].id+&#39;\&#39;)&#34;</span>&gt;归档&lt;/<span style="color:#f92672">button</span>&gt;
</span></span></code></pre></div><ul>
<li>然后，添加点击事件</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">archiveMemo</span>(<span style="color:#a6e22e">memoId</span>) { <span style="color:#75715e">//获取Memos的ID值
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>  <span style="color:#a6e22e">memosOpenId</span> <span style="color:#f92672">=</span> window.<span style="color:#a6e22e">localStorage</span> <span style="color:#f92672">&amp;&amp;</span> window.<span style="color:#a6e22e">localStorage</span>.<span style="color:#a6e22e">getItem</span>(<span style="color:#e6db74">&#34;memos-access-token&#34;</span>); <span style="color:#75715e">//登录信息
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>  <span style="color:#66d9ef">if</span>(<span style="color:#a6e22e">memosOpenId</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#a6e22e">memoId</span>){ <span style="color:#75715e">//判断是否登录以及获取到Memos的ID值
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">memoUrl</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">memosPath</span><span style="color:#f92672">+</span><span style="color:#e6db74">&#34;/api/v1/memo/&#34;</span><span style="color:#f92672">+</span><span style="color:#a6e22e">memoId</span><span style="color:#f92672">+</span><span style="color:#e6db74">&#34;?openId=&#34;</span><span style="color:#f92672">+</span><span style="color:#a6e22e">memosOpenId</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">memoBody</span> <span style="color:#f92672">=</span> {<span style="color:#a6e22e">id</span><span style="color:#f92672">:</span><span style="color:#a6e22e">memoId</span>,<span style="color:#a6e22e">rowStatus</span><span style="color:#f92672">:</span><span style="color:#e6db74">&#34;ARCHIVED&#34;</span>};
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">fetch</span>(<span style="color:#a6e22e">memoUrl</span>, {
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">method</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;PATCH&#39;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">body</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">JSON</span>.<span style="color:#a6e22e">stringify</span>(<span style="color:#a6e22e">memoBody</span>),
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">headers</span><span style="color:#f92672">:</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#39;Content-Type&#39;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;application/json&#39;</span>
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>    }).<span style="color:#a6e22e">then</span>(<span style="color:#66d9ef">function</span>(<span style="color:#a6e22e">res</span>) {
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">res</span>.<span style="color:#a6e22e">status</span> <span style="color:#f92672">==</span> <span style="color:#ae81ff">200</span>) {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">cocoMessage</span>.<span style="color:#a6e22e">success</span>(
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#39;归档成功&#39;</span>,
</span></span><span style="display:flex;"><span>        ()=&gt;{
</span></span><span style="display:flex;"><span>          <span style="color:#a6e22e">location</span>.<span style="color:#a6e22e">reload</span>();
</span></span><span style="display:flex;"><span>        })
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>    })
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="删除">删除</h2>
<ul>
<li>首先，还是给你的每一条Memos 增加一个按钮，并绑定一个点击事件:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-html" data-lang="html"><span style="display:flex;"><span>&lt;<span style="color:#f92672">button</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;delete-btn&#34;</span> <span style="color:#a6e22e">onclick</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;deleteMemo(\&#39;&#39;+data[i].id+&#39;\&#39;)&#34;</span>&gt;删除&lt;/<span style="color:#f92672">button</span>&gt;
</span></span></code></pre></div><ul>
<li>然后，添加点击事件</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">deleteMemo</span>(<span style="color:#a6e22e">memoId</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">memosOpenId</span> <span style="color:#f92672">=</span> window.<span style="color:#a6e22e">localStorage</span> <span style="color:#f92672">&amp;&amp;</span> window.<span style="color:#a6e22e">localStorage</span>.<span style="color:#a6e22e">getItem</span>(<span style="color:#e6db74">&#34;memos-access-token&#34;</span>);
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span>(<span style="color:#a6e22e">memosOpenId</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#a6e22e">memoId</span>){
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">memoUrl</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">memosPath</span><span style="color:#f92672">+</span><span style="color:#e6db74">&#34;/api/v1/memo/&#34;</span><span style="color:#f92672">+</span><span style="color:#a6e22e">memoId</span><span style="color:#f92672">+</span><span style="color:#e6db74">&#34;?openId=&#34;</span><span style="color:#f92672">+</span><span style="color:#a6e22e">memosOpenId</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">fetch</span>(<span style="color:#a6e22e">memoUrl</span>, {
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">method</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;DELETE&#39;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">headers</span><span style="color:#f92672">:</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#39;Content-Type&#39;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;application/json&#39;</span>
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>    }).<span style="color:#a6e22e">then</span>(<span style="color:#66d9ef">function</span>(<span style="color:#a6e22e">res</span>) {
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">res</span>.<span style="color:#a6e22e">status</span> <span style="color:#f92672">==</span> <span style="color:#ae81ff">200</span>) {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">cocoMessage</span>.<span style="color:#a6e22e">success</span>(
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#39;删除成功&#39;</span>,
</span></span><span style="display:flex;"><span>        ()=&gt;{
</span></span><span style="display:flex;"><span>          <span style="color:#a6e22e">location</span>.<span style="color:#a6e22e">reload</span>();
</span></span><span style="display:flex;"><span>        })
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>    }).<span style="color:#66d9ef">catch</span>(<span style="color:#a6e22e">err</span> =&gt; {
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">cocoMessage</span>.<span style="color:#a6e22e">error</span>(<span style="color:#e6db74">&#39;出错了，再检查一下吧&#39;</span>)
</span></span><span style="display:flex;"><span>    })
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content><category scheme="https://nuoea.com/categories/%E6%8A%98%E8%85%BE" term="%E6%8A%98%E8%85%BE" label="折腾"/><category scheme="https://nuoea.com/tags/memos" term="memos" label="Memos"/><category scheme="https://nuoea.com/tags/%E6%8A%98%E8%85%BE" term="%E6%8A%98%E8%85%BE" label="折腾"/></entry><entry><title type="html">开始连接，给Memos页面增加转发功能</title><link href="https://nuoea.com/memos-link-owner/" rel="alternate" type="text/html"/><id>https://nuoea.com/memos-link-owner/</id><published>2023-07-06T20:30:23+08:00</published><updated>2023-07-06T20:30:23+08:00</updated><content type="html"><![CDATA[<h2 id="前言">前言</h2>
<p>其实这个想法来自于 <a href="https://dongjunke.cn/">@小饿</a> 同学。在Memos页面拥有了发布框之后，我也一直在想，除了方便快捷之外，怎么可以让发布框更好用。转发功能的概念，让我眼前一亮。</p>
<blockquote>
<p>小饿： 转发功能，其实就是复制好友说说再评论，就更加接近微博了，信息连接效率会指数级提升。</p></blockquote>
<p>Memos诞生很长时间以来，很多人都是当个笔记应用，记录生活。后来因为[@林木木] 开始折腾。有了各种API，开始出现单独的Memos页面，也有了浏览器插件，各种手机APP。生态圈一下子就建立起来了。再到后来，木木兄为Memos开发了广场页面，尽可能多的将大家的信息聚合起来，自此，Memos开启了社交时代。</p>
<p>木木的<a href="https://immmmm.com/bbs/">「广场」</a>页面，其实已经非常趋近于微博。发布框加上后，功能已经非常完整了。所以当你拥有了一个Memos广场页面，并且加上了发布框。这个转发的功能，也可以折腾起来了。</p>
<p><img class="lozad" data-src="https://i.nuoea.com/img/2023/07/06/1688646868.jpg" alt=""  /></p>
<h2 id="部署">部署</h2>
<ul>
<li>首先，给你的每一条Memos 增加一个转发按钮，并绑定一个点击事件。</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-html" data-lang="html"><span style="display:flex;"><span>&lt;<span style="color:#f92672">a</span> <span style="color:#a6e22e">onclick</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;transPond(&#39;+JSON.stringify(memosForm)+&#39;)&#34;</span>&gt;&lt;/<span style="color:#f92672">a</span>&gt;
</span></span></code></pre></div><ul>
<li>然后，定义转发的内容。</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">memosForm</span> <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">creatorName</span><span style="color:#f92672">:</span><span style="color:#a6e22e">creatorName</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">content</span><span style="color:#f92672">:</span><span style="color:#a6e22e">transData</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">url</span><span style="color:#f92672">:</span><span style="color:#a6e22e">memosLink</span>
</span></span><span style="display:flex;"><span>};
</span></span></code></pre></div><ul>
<li>再然后，需要找到你页面中的发布框以及当前登录信息。</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">memosOpenId</span> <span style="color:#f92672">=</span> window.<span style="color:#a6e22e">localStorage</span> <span style="color:#f92672">&amp;&amp;</span> window.<span style="color:#a6e22e">localStorage</span>.<span style="color:#a6e22e">getItem</span>(<span style="color:#e6db74">&#34;memos-access-token&#34;</span>);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">memosPath</span> <span style="color:#f92672">=</span> window.<span style="color:#a6e22e">localStorage</span> <span style="color:#f92672">&amp;&amp;</span> window.<span style="color:#a6e22e">localStorage</span>.<span style="color:#a6e22e">getItem</span>(<span style="color:#e6db74">&#34;memos-access-path&#34;</span>);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">getEditor</span> <span style="color:#f92672">=</span> window.<span style="color:#a6e22e">localStorage</span> <span style="color:#f92672">&amp;&amp;</span> window.<span style="color:#a6e22e">localStorage</span>.<span style="color:#a6e22e">getItem</span>(<span style="color:#e6db74">&#34;memos-editor-display&#34;</span>);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">memosTextarea</span> <span style="color:#f92672">=</span> document.<span style="color:#a6e22e">querySelector</span>(<span style="color:#e6db74">&#34;.memos-editor-textarea&#34;</span>);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">memosVisibilitySelect</span> <span style="color:#f92672">=</span> document.<span style="color:#a6e22e">querySelector</span>(<span style="color:#e6db74">&#34;.select-memos-value&#34;</span>);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">submitMemoBtn</span> <span style="color:#f92672">=</span> document.<span style="color:#a6e22e">querySelector</span>(<span style="color:#e6db74">&#34;.submit-memos-btn&#34;</span>);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">editMemoDom</span> <span style="color:#f92672">=</span> document.<span style="color:#a6e22e">querySelector</span>(<span style="color:#e6db74">&#34;.edit-memos&#34;</span>);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">editMemoBtn</span> <span style="color:#f92672">=</span> document.<span style="color:#a6e22e">querySelector</span>(<span style="color:#e6db74">&#34;.edit-memos-btn&#34;</span>);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">cancelEditBtn</span> <span style="color:#f92672">=</span> document.<span style="color:#a6e22e">querySelector</span>(<span style="color:#e6db74">&#34;.cancel-edit-btn&#34;</span>);
</span></span></code></pre></div><ul>
<li>最后，给发布框中，添加转发内容。</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">transRes</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;[@&#39;</span><span style="color:#f92672">+</span> <span style="color:#a6e22e">a</span>.<span style="color:#a6e22e">creatorName</span><span style="color:#f92672">+</span><span style="color:#e6db74">&#39;](&#39;</span><span style="color:#f92672">+</span><span style="color:#a6e22e">a</span>.<span style="color:#a6e22e">url</span><span style="color:#f92672">+</span><span style="color:#e6db74">&#39;) \n\n&gt; &#39;</span><span style="color:#f92672">+</span><span style="color:#a6e22e">a</span>.<span style="color:#a6e22e">creatorName</span><span style="color:#f92672">+</span><span style="color:#e6db74">&#39;: &#39;</span><span style="color:#f92672">+</span><span style="color:#a6e22e">a</span>.<span style="color:#a6e22e">content</span>;
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">memosTextarea</span>.<span style="color:#a6e22e">value</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">transRes</span>;
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">memosTextarea</span>.<span style="color:#a6e22e">style</span>.<span style="color:#a6e22e">height</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">memosTextarea</span>.<span style="color:#a6e22e">scrollHeight</span> <span style="color:#f92672">+</span> <span style="color:#e6db74">&#39;px&#39;</span>;
</span></span><span style="display:flex;"><span>document.<span style="color:#a6e22e">body</span>.<span style="color:#a6e22e">scrollIntoView</span>({<span style="color:#a6e22e">behavior</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;smooth&#39;</span>})
</span></span></code></pre></div><p>完整点击事件代码如下：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#75715e">//转发
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">transPond</span>(<span style="color:#a6e22e">a</span>){
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">memosTextarea</span> <span style="color:#f92672">=</span> document.<span style="color:#a6e22e">querySelector</span>(<span style="color:#e6db74">&#34;.memos-editor-textarea&#34;</span>);
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">getEditor</span> <span style="color:#f92672">=</span> window.<span style="color:#a6e22e">localStorage</span> <span style="color:#f92672">&amp;&amp;</span> window.<span style="color:#a6e22e">localStorage</span>.<span style="color:#a6e22e">getItem</span>(<span style="color:#e6db74">&#34;memos-editor-display&#34;</span>);
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">memosOpenId</span> <span style="color:#f92672">=</span> window.<span style="color:#a6e22e">localStorage</span> <span style="color:#f92672">&amp;&amp;</span> window.<span style="color:#a6e22e">localStorage</span>.<span style="color:#a6e22e">getItem</span>(<span style="color:#e6db74">&#34;memos-access-token&#34;</span>);
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span>(<span style="color:#a6e22e">memosOpenId</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#a6e22e">getEditor</span> <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;show&#34;</span>){
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">transRes</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;[@&#39;</span><span style="color:#f92672">+</span> <span style="color:#a6e22e">a</span>.<span style="color:#a6e22e">creatorName</span><span style="color:#f92672">+</span><span style="color:#e6db74">&#39;](&#39;</span><span style="color:#f92672">+</span><span style="color:#a6e22e">a</span>.<span style="color:#a6e22e">url</span><span style="color:#f92672">+</span><span style="color:#e6db74">&#39;) \n\n&gt; &#39;</span><span style="color:#f92672">+</span><span style="color:#a6e22e">a</span>.<span style="color:#a6e22e">creatorName</span><span style="color:#f92672">+</span><span style="color:#e6db74">&#39;: &#39;</span><span style="color:#f92672">+</span><span style="color:#a6e22e">a</span>.<span style="color:#a6e22e">content</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">memosTextarea</span>.<span style="color:#a6e22e">value</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">transRes</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">memosTextarea</span>.<span style="color:#a6e22e">style</span>.<span style="color:#a6e22e">height</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">memosTextarea</span>.<span style="color:#a6e22e">scrollHeight</span> <span style="color:#f92672">+</span> <span style="color:#e6db74">&#39;px&#39;</span>;
</span></span><span style="display:flex;"><span>    document.<span style="color:#a6e22e">body</span>.<span style="color:#a6e22e">scrollIntoView</span>({<span style="color:#a6e22e">behavior</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;smooth&#39;</span>})
</span></span><span style="display:flex;"><span>  }<span style="color:#66d9ef">else</span>{
</span></span><span style="display:flex;"><span>    window.<span style="color:#a6e22e">open</span>(<span style="color:#a6e22e">a</span>.<span style="color:#a6e22e">url</span>);<span style="color:#75715e">//如果没登录，则不转发直接跳转。
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="最后">最后</h2>
<p>效果如下：</p>
<p><img class="lozad" data-src="https://i.nuoea.com/img/2023/07/06/1688649915.jpg" alt=""  /></p>
<p><img class="lozad" data-src="https://i.nuoea.com/img/2023/07/06/1688649318.jpg" alt=""  /></p>]]></content><category scheme="https://nuoea.com/categories/%E6%8A%98%E8%85%BE" term="%E6%8A%98%E8%85%BE" label="折腾"/><category scheme="https://nuoea.com/tags/memos" term="memos" label="Memos"/><category scheme="https://nuoea.com/tags/%E6%8A%98%E8%85%BE" term="%E6%8A%98%E8%85%BE" label="折腾"/></entry><entry><title type="html">给Memos页面添加发布框</title><link href="https://nuoea.com/add-memos-editor/" rel="alternate" type="text/html"/><id>https://nuoea.com/add-memos-editor/</id><published>2023-07-01T21:39:02+08:00</published><updated>2023-07-01T21:39:02+08:00</updated><content type="html"><![CDATA[<h2 id="起因">起因</h2>
<p>最开始是看到 <code>@林木木</code> 发的一条哔哔。说是想要在Memos页面内嵌入哔哔单页，从而可以实现在一个页面内发布哔哔以及浏览哔哔。寻思这样一来，体验确实是可以好很多，不需要切来切去，更有沉浸感。</p>
<h2 id="部署代码">部署代码</h2>
<ul>
<li>HTML</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-html" data-lang="html"><span style="display:flex;"><span>&lt;<span style="color:#f92672">div</span> <span style="color:#a6e22e">id</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;memos&#34;</span>&gt;&lt;/<span style="color:#f92672">div</span>&gt;
</span></span></code></pre></div><ul>
<li>CSS</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-css" data-lang="css"><span style="display:flex;"><span>.<span style="color:#a6e22e">load-memos-editor</span>{<span style="color:#66d9ef">position</span>:<span style="color:#66d9ef">fixed</span>;<span style="color:#66d9ef">right</span>:<span style="color:#ae81ff">1</span><span style="color:#66d9ef">rem</span>;<span style="color:#66d9ef">bottom</span>:<span style="color:#ae81ff">1</span><span style="color:#66d9ef">rem</span>;<span style="color:#66d9ef">background-color</span>:<span style="color:#ae81ff">#ebeced</span>;}
</span></span><span style="display:flex;"><span>.<span style="color:#a6e22e">memos-editor-body</span>{<span style="color:#66d9ef">display</span>:<span style="color:#66d9ef">flex</span>;<span style="color:#66d9ef">border-radius</span>:<span style="color:#ae81ff">.33</span><span style="color:#66d9ef">rem</span>;<span style="color:#66d9ef">background-color</span>:<span style="color:#a6e22e">var</span>(<span style="color:#f92672">--</span>light<span style="color:#f92672">-</span>background<span style="color:#f92672">-</span>secondary);<span style="color:#66d9ef">flex-direction</span>:<span style="color:#66d9ef">column</span>}
</span></span><span style="display:flex;"><span>.<span style="color:#a6e22e">dark</span> .<span style="color:#a6e22e">memos-editor-body</span> {<span style="color:#66d9ef">background-color</span>: <span style="color:#a6e22e">var</span>(<span style="color:#f92672">--</span>dark<span style="color:#f92672">-</span>background<span style="color:#f92672">-</span>secondary);}
</span></span><span style="display:flex;"><span>.<span style="color:#a6e22e">memos-editor-content</span><span style="color:#f92672">,</span>.<span style="color:#a6e22e">memos-editor-footer</span><span style="color:#f92672">,</span>.<span style="color:#a6e22e">memos-editor-option</span>{<span style="color:#66d9ef">display</span>: <span style="color:#66d9ef">flex</span>;}
</span></span><span style="display:flex;"><span>.<span style="color:#a6e22e">memos-editor-content</span> .<span style="color:#a6e22e">memos-editor-inputer</span>{<span style="color:#66d9ef">overflow-x</span>:<span style="color:#66d9ef">hidden</span>;<span style="color:#66d9ef">overflow-y</span>:<span style="color:#66d9ef">clip</span>;<span style="color:#66d9ef">padding</span>:<span style="color:#ae81ff">0</span>;<span style="color:#66d9ef">width</span>:<span style="color:#ae81ff">100</span><span style="color:#66d9ef">%</span>;<span style="color:#66d9ef">max-height</span>:<span style="color:#ae81ff">160</span><span style="color:#66d9ef">px</span>;<span style="color:#66d9ef">outline</span>:<span style="color:#ae81ff">2</span><span style="color:#66d9ef">px</span> <span style="color:#66d9ef">solid</span> <span style="color:#66d9ef">transparent</span>;<span style="color:#66d9ef">outline-offset</span>:<span style="color:#ae81ff">2</span><span style="color:#66d9ef">px</span>;<span style="color:#66d9ef">background-color</span>:<span style="color:#66d9ef">transparent</span>;<span style="color:#66d9ef">white-space</span>:<span style="color:#66d9ef">pre-wrap</span>;<span style="color:#66d9ef">line-height</span>:<span style="color:#ae81ff">2</span><span style="color:#66d9ef">rem</span>;<span style="color:#66d9ef">resize</span>:<span style="color:#66d9ef">none</span>;<span style="color:#66d9ef">overflow-wrap</span>:anywhere;<span style="color:#66d9ef">word-break</span>:<span style="color:#66d9ef">normal</span>}
</span></span><span style="display:flex;"><span>.<span style="color:#a6e22e">memos-editor-tools</span>{<span style="color:#66d9ef">display</span>: <span style="color:#66d9ef">flex</span>;<span style="color:#66d9ef">flex-direction</span>: <span style="color:#66d9ef">column</span>;}
</span></span><span style="display:flex;"><span>.<span style="color:#a6e22e">memos-editor-tools</span> .<span style="color:#a6e22e">action-btn</span> {<span style="color:#66d9ef">padding</span>: <span style="color:#ae81ff">.25</span><span style="color:#66d9ef">rem</span>;}
</span></span><span style="display:flex;"><span>.<span style="color:#a6e22e">memos-editor-tools</span> .<span style="color:#a6e22e">memos-tag-list</span> {<span style="color:#66d9ef">display</span>:<span style="color:#66d9ef">flex</span>;<span style="color:#66d9ef">flex-wrap</span>:<span style="color:#66d9ef">wrap</span>;<span style="color:#66d9ef">align-items</span>:<span style="color:#66d9ef">center</span>;<span style="color:#66d9ef">line-height</span>:<span style="color:#ae81ff">2</span>;}
</span></span><span style="display:flex;"><span>.<span style="color:#a6e22e">memos-editor-tools</span> .<span style="color:#a6e22e">memos-tag</span> {<span style="color:#66d9ef">position</span>:<span style="color:#66d9ef">relative</span>;}
</span></span><span style="display:flex;"><span>.<span style="color:#a6e22e">memos-editor-tools</span> .<span style="color:#a6e22e">memos-tag</span> <span style="color:#f92672">a</span> {<span style="color:#66d9ef">flex</span>:<span style="color:#ae81ff">1</span>}
</span></span></code></pre></div><ul>
<li>JS</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#f92672">&lt;</span><span style="color:#a6e22e">script</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">memosData</span> <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">dom</span><span style="color:#f92672">:</span><span style="color:#e6db74">&#39;#memos&#39;</span>,
</span></span><span style="display:flex;"><span>};
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;</span><span style="color:#960050;background-color:#1e0010">/script&gt;</span>
</span></span></code></pre></div><ul>
<li>页面布局</li>
</ul>
<blockquote>
<p><a href="https://github.com/insdram/hugo/blob/main/static/css/grid.css">grid.css</a></p></blockquote>
<ul>
<li>字体图标</li>
</ul>
<blockquote>
<p><a href="https://github.com/insdram/hugo/blob/main/static/css/iconfont.css">iconfont.css</a></p></blockquote>
<ul>
<li>Javascript</li>
</ul>
<blockquote>
<p><a href="https://github.com/insdram/hugo/blob/main/static/js/memos-editor.js">memos-editor.js</a></p></blockquote>
<ul>
<li>消息提醒弹窗</li>
</ul>
<pre tabindex="0"><code>https://github.com/TheWindRises-2/coco-message
</code></pre><ul>
<li>Animate.css</li>
</ul>
<pre tabindex="0"><code>https://animate.style/
</code></pre><h2 id="使用说明">使用说明</h2>
<ul>
<li>填入 <code>Memos Open API</code> ，格式如下：</li>
</ul>
<pre tabindex="0"><code>https://memos.example.com/api/memo?openId=&lt;Memos Open API&gt;
</code></pre><ul>
<li>开始哔哔吧</li>
</ul>
<h2 id="在线围观">在线围观</h2>
<p>围观地址：https://nuoea.com/memos</p>
<p><img class="lozad" data-src="https://i.nuoea.com/img/2023/06/30/1688138493.jpg" alt=""  /></p>
<h2 id="致谢">致谢</h2>
<ul>
<li><a href="https://immmmm.com/chrome-extensions-memos-bber/">Memos 单页及浏览器扩展：：木木木木木</a></li>
<li><a href="https://immmmm.com/memos-api-description/">Memos API 非官方不完全说明：：木木木木木</a></li>
</ul>
<h2 id="更新日志">更新日志</h2>
<ul>
<li><strong>2023-07-01</strong> 正式上线</li>
<li><strong>2023-07-02</strong> 新增：上传图片</li>
<li><strong>2023-07-02</strong> 修复：API地址多出<code>/</code>导致“Memos Open API 有误，请重新输入!”的问题</li>
<li><strong>2023-07-03</strong> 新增：随机回顾一条 Memos</li>
<li><strong>2023-07-04</strong> 新增：切换当前 Memos Open API</li>
<li><strong>2023-07-09</strong> 新增：光标自动定位（感谢 <a href="https://koobai.com/">@空白生活</a> ）</li>
<li><strong>2023-07-09</strong> 修复：随机Memos中最多只能显示1个标签的问题（感谢 <a href="https://koobai.com/">@空白生活</a> ）</li>
<li><strong>2023-07-18</strong> 新增：适配 <code>0.14.0</code> 版本API</li>
<li><strong>2023-07-19</strong> 新增：资源库图片删除</li>
<li><strong>2023-07-19</strong> 新增：编辑按钮</li>
<li><strong>2023-07-19</strong> 修复：无法新增TAG标签的问题</li>
</ul>]]></content><category scheme="https://nuoea.com/categories/%E6%8A%98%E8%85%BE" term="%E6%8A%98%E8%85%BE" label="折腾"/><category scheme="https://nuoea.com/tags/memos" term="memos" label="Memos"/><category scheme="https://nuoea.com/tags/%E6%95%99%E7%A8%8B" term="%E6%95%99%E7%A8%8B" label="教程"/></entry><entry><title type="html">使用 Umami Api 实现点赞统计</title><link href="https://nuoea.com/use-umami-like/" rel="alternate" type="text/html"/><id>https://nuoea.com/use-umami-like/</id><published>2023-06-14T22:11:46+08:00</published><updated>2023-06-14T22:11:46+08:00</updated><content type="html"><![CDATA[<h2 id="前言">前言</h2>
<p>在写完上篇<a href="https://nuoea.com/use-umami-api">《使用 Umami Api 显示统计数据》</a>之后，越发的觉得Umami非常有意思。于是就继续看了看官方API，一番了解下来之后，发现通过 <code>Track events</code> 可以实现自定义的页面事件统计。灵光一闪，觉得可以用这玩意做个点赞统计。</p>
<h2 id="使用">使用</h2>
<p>使用起来非常简单，只需要在触发事件的元素中加上：</p>
<pre tabindex="0"><code>data-umami-event=&#34;{event-name}&#34;
</code></pre><p>例如：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-html" data-lang="html"><span style="display:flex;"><span>&lt;<span style="color:#f92672">button</span> <span style="color:#a6e22e">id</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;Like-button&#34;</span> <span style="color:#a6e22e">data-umami-event</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;Like button&#34;</span>&gt;点赞&lt;/<span style="color:#f92672">button</span>&gt;
</span></span></code></pre></div><p>当然，也可以使用 Javascript</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">button</span> <span style="color:#f92672">=</span> document.<span style="color:#a6e22e">getElementById</span>(<span style="color:#e6db74">&#39;Like-button&#39;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">button</span>.<span style="color:#a6e22e">onclick</span> <span style="color:#f92672">=</span> () =&gt; <span style="color:#a6e22e">umami</span>.<span style="color:#a6e22e">track</span>(<span style="color:#e6db74">&#39;Like button&#39;</span>);
</span></span></code></pre></div><p>如此一来，Umami就会统计到一个名为 <code>Like button</code> 的事件信息，并为触发次数进行统计。</p>
<h2 id="接口">接口</h2>
<p>已经有了统计的信息，下面只需要通过官方的API接口就能获取到统计的数据了。</p>
<pre tabindex="0"><code>GET /api/websites/{websiteId}/events
</code></pre><p>该接口需要5个参数，分别是：</p>
<ul>
<li>startAt: 起始时间.</li>
<li>endAt: 终止时间.</li>
<li>unit: 时间单位 (year | month | hour | day).</li>
<li>timezone: 时区 (ex. Asia/Shanghai).</li>
<li>url: 连接.</li>
</ul>
<p>请求代码如下：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">umiTime</span> <span style="color:#f92672">=</span> Date.<span style="color:#a6e22e">parse</span>(<span style="color:#66d9ef">new</span> Date()); <span style="color:#75715e">//获取当前时间戳
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">pathurl</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">indow</span>.<span style="color:#a6e22e">location</span>.<span style="color:#a6e22e">pathname</span>; <span style="color:#75715e">// 获取当前URL路径
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">umiUrl</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;https://umami.mydomain.com/api/websites/&#34;</span> <span style="color:#f92672">+</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">websiteId</span><span style="color:#f92672">&gt;</span> <span style="color:#f92672">+</span> <span style="color:#e6db74">&#34;/events?startAt=0&amp;endAt=&#34;</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">umiTime</span> <span style="color:#f92672">+</span> <span style="color:#e6db74">&#34;&amp;unit=hour&amp;url=&#34;</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">pathurl</span> <span style="color:#f92672">+</span><span style="color:#e6db74">&#34;&amp;timezone=Asia/Shanghai&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">fetch</span>(<span style="color:#a6e22e">umiUrl</span>,{
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">method</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;GET&#39;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">mode</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;cors&#39;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">cache</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;default&#39;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">headers</span><span style="color:#f92672">:</span> {
</span></span><span style="display:flex;"><span>      <span style="color:#e6db74">&#39;Authorization&#39;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;Bearer &#39;</span> <span style="color:#f92672">+</span> <span style="color:#f92672">&lt;</span><span style="color:#a6e22e">Token</span><span style="color:#f92672">&gt;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#e6db74">&#39;Content-Type&#39;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;application/json&#39;</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  })
</span></span><span style="display:flex;"><span>  .<span style="color:#a6e22e">then</span>(<span style="color:#a6e22e">res</span> =&gt; <span style="color:#a6e22e">res</span>.<span style="color:#a6e22e">json</span>()).<span style="color:#a6e22e">then</span>(<span style="color:#a6e22e">resdata</span> =&gt; {});
</span></span></code></pre></div><p>请求成功后，获取到的数据如下：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>[
</span></span><span style="display:flex;"><span>  { <span style="color:#f92672">&#34;x&#34;</span>: <span style="color:#e6db74">&#34;Like button&#34;</span>, <span style="color:#f92672">&#34;t&#34;</span>: <span style="color:#e6db74">&#34;2023-04-12 22:00:00&#34;</span>, <span style="color:#f92672">&#34;y&#34;</span>: <span style="color:#ae81ff">1</span> },
</span></span><span style="display:flex;"><span>  { <span style="color:#f92672">&#34;x&#34;</span>: <span style="color:#e6db74">&#34;Like button&#34;</span>, <span style="color:#f92672">&#34;t&#34;</span>: <span style="color:#e6db74">&#34;2023-04-12 22:00:00&#34;</span>, <span style="color:#f92672">&#34;y&#34;</span>: <span style="color:#ae81ff">5</span> },
</span></span><span style="display:flex;"><span>  { <span style="color:#f92672">&#34;x&#34;</span>: <span style="color:#e6db74">&#34;Like button&#34;</span>, <span style="color:#f92672">&#34;t&#34;</span>: <span style="color:#e6db74">&#34;2023-04-12 23:00:00&#34;</span>, <span style="color:#f92672">&#34;y&#34;</span>: <span style="color:#ae81ff">4</span> },
</span></span><span style="display:flex;"><span>  { <span style="color:#f92672">&#34;x&#34;</span>: <span style="color:#e6db74">&#34;Like button&#34;</span>, <span style="color:#f92672">&#34;t&#34;</span>: <span style="color:#e6db74">&#34;2023-04-12 23:00:00&#34;</span>, <span style="color:#f92672">&#34;y&#34;</span>: <span style="color:#ae81ff">4</span> },
</span></span><span style="display:flex;"><span>  { <span style="color:#f92672">&#34;x&#34;</span>: <span style="color:#e6db74">&#34;Like button&#34;</span>, <span style="color:#f92672">&#34;t&#34;</span>: <span style="color:#e6db74">&#34;2023-04-13 00:00:00&#34;</span>, <span style="color:#f92672">&#34;y&#34;</span>: <span style="color:#ae81ff">1</span> }
</span></span><span style="display:flex;"><span>]
</span></span></code></pre></div><h2 id="最后">最后</h2>
<p>获取到的数据其实是请求的<code>Url</code>页面中，该事件以时间单位统计的一个数组，如果在参数中选择<code>unit</code>为<code>hour</code>,那么数据将会以小时为单位来分割，每小时的数据为一个对象，以此类推。而我们需要将所有的数据求和来得到我们最终的统计结果。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">groupBy</span>(<span style="color:#a6e22e">arr</span>, <span style="color:#a6e22e">by</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">arr</span>.<span style="color:#a6e22e">reduce</span>((<span style="color:#a6e22e">groups</span>, <span style="color:#a6e22e">item</span>) =&gt; {
</span></span><span style="display:flex;"><span>      <span style="color:#75715e">// 获取 item 的分组的 key
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>      <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">key</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">by</span>(<span style="color:#a6e22e">item</span>);
</span></span><span style="display:flex;"><span>      <span style="color:#75715e">// 看看这个组是不是已经存在
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>      <span style="color:#66d9ef">let</span> <span style="color:#a6e22e">group</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">groups</span>.<span style="color:#a6e22e">find</span>(<span style="color:#a6e22e">g</span> =&gt; <span style="color:#a6e22e">g</span>.<span style="color:#a6e22e">key</span> <span style="color:#f92672">===</span> <span style="color:#a6e22e">key</span>);
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">if</span>(<span style="color:#f92672">!</span><span style="color:#a6e22e">group</span>) {
</span></span><span style="display:flex;"><span>          <span style="color:#75715e">// 不存在就创建一个新组
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>          <span style="color:#a6e22e">group</span> <span style="color:#f92672">=</span> {<span style="color:#a6e22e">key</span>, <span style="color:#a6e22e">items</span><span style="color:#f92672">:</span> []};
</span></span><span style="display:flex;"><span>          <span style="color:#a6e22e">groups</span>.<span style="color:#a6e22e">push</span>(<span style="color:#a6e22e">group</span>);
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>      <span style="color:#75715e">// item 放入组中
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>      <span style="color:#a6e22e">group</span>.<span style="color:#a6e22e">items</span>.<span style="color:#a6e22e">push</span>(<span style="color:#a6e22e">item</span>);
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">groups</span>;
</span></span><span style="display:flex;"><span>  }, []);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">data</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">groupBy</span>(<span style="color:#a6e22e">res</span>, <span style="color:#a6e22e">item</span> =&gt; <span style="color:#a6e22e">item</span>.<span style="color:#a6e22e">x</span>)
</span></span><span style="display:flex;"><span>  .<span style="color:#a6e22e">map</span>(<span style="color:#a6e22e">g</span> =&gt; ({
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">x</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">g</span>.<span style="color:#a6e22e">key</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">t</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">g</span>.<span style="color:#a6e22e">items</span>.<span style="color:#a6e22e">map</span>(<span style="color:#a6e22e">item</span> =&gt; <span style="color:#a6e22e">item</span>.<span style="color:#a6e22e">t</span>),
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">y</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">g</span>.<span style="color:#a6e22e">items</span>.<span style="color:#a6e22e">reduce</span>((<span style="color:#a6e22e">sum</span>, <span style="color:#a6e22e">item</span>) =&gt; <span style="color:#a6e22e">sum</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">item</span>.<span style="color:#a6e22e">y</span>, <span style="color:#ae81ff">0</span>)
</span></span><span style="display:flex;"><span>  }));
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#a6e22e">data</span>);
</span></span></code></pre></div><p>以上。</p>]]></content><category scheme="https://nuoea.com/categories/%E6%8A%98%E8%85%BE" term="%E6%8A%98%E8%85%BE" label="折腾"/><category scheme="https://nuoea.com/tags/umami" term="umami" label="umami"/><category scheme="https://nuoea.com/tags/api" term="api" label="API"/></entry><entry><title type="html">极简模式部署友链朋友圈</title><link href="https://nuoea.com/hi-circle-of-friends/" rel="alternate" type="text/html"/><id>https://nuoea.com/hi-circle-of-friends/</id><published>2023-06-11T15:50:37+08:00</published><updated>2023-06-11T15:50:37+08:00</updated><content type="html"><![CDATA[<h2 id="前言">前言</h2>
<p>曾经我常常感觉到，每一个独立的博客都像是一座彼此独立的孤岛。所以现在，有了越来越多的工具，把大家连接起来，像Memos、Twikoo等等。而<code>友链朋友圈</code>也是如此。你可以随时获取朋友网站的更新内容，并了解朋友的活跃情况，以此来将大家紧密的连接起来。</p>
<h2 id="页面适配">页面适配</h2>
<p>首先，友链页的抓取是通过css选择器进行的，所以我们需要将友链页按照友链朋友圈提供的规则进行修改。如果与对应规则不匹配，可能会遇到获取文章为0、管理面板出现status code 500、start error等错误。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yml" data-lang="yml"><span style="display:flex;"><span><span style="color:#ae81ff">/* 规则一（common1）：*/</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">/*  avatar </span>: <span style="color:#e6db74">&#39;.cf-friends img::attr(src)&#39;</span>  <span style="color:#75715e">*/</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">/*  link </span>: <span style="color:#e6db74">&#39;.cf-friends a::attr(href)&#39;</span>  <span style="color:#75715e">*/</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">/*  name </span>: <span style="color:#e6db74">&#39;.cf-friends a::text&#39;</span>  <span style="color:#75715e">*/</span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">/* 规则二（common2）：*/</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">/*  avatar </span>: <span style="color:#e6db74">&#39;img.cf-friends-avatar&#39;</span>  <span style="color:#75715e">*/</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">/*  link </span>: <span style="color:#e6db74">&#39;a.cf-friends-link&#39;</span>  <span style="color:#75715e">*/</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">/*  name </span>: <span style="color:#e6db74">&#39;.cf-friends-name&#39;</span>  <span style="color:#75715e">*/</span>
</span></span></code></pre></div><p>只要上述css选择器能够匹配到，就完成了适配。根据规则，你编写的友链页面的友链部分可以是这样：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-html" data-lang="html"><span style="display:flex;"><span> &lt;<span style="color:#f92672">div</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;cf-friends&#34;</span>&gt;
</span></span><span style="display:flex;"><span>   &lt;<span style="color:#f92672">div</span>&gt;
</span></span><span style="display:flex;"><span>     &lt;<span style="color:#f92672">img</span> <span style="color:#a6e22e">src</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;https://www.baidu.com&#34;</span> <span style="color:#a6e22e">alt</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;&#34;</span>&gt; <span style="color:#75715e">&lt;!-- 头像 --&gt;</span>
</span></span><span style="display:flex;"><span>     &lt;<span style="color:#f92672">a</span> <span style="color:#a6e22e">href</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;https://www.baidu.com&#34;</span>&gt;xxxx的博客&lt;/<span style="color:#f92672">a</span>&gt; <span style="color:#75715e">&lt;!-- 链接 --&gt;</span>
</span></span><span style="display:flex;"><span>   &lt;/<span style="color:#f92672">div</span>&gt;
</span></span><span style="display:flex;"><span>   &lt;<span style="color:#f92672">div</span>&gt;
</span></span><span style="display:flex;"><span>     &lt;<span style="color:#f92672">img</span> <span style="color:#a6e22e">src</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;https://www.baidu.com&#34;</span> <span style="color:#a6e22e">alt</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;&#34;</span>&gt;
</span></span><span style="display:flex;"><span>     &lt;<span style="color:#f92672">a</span> <span style="color:#a6e22e">href</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;https://www.baidu.com&#34;</span>&gt;xxxx的博客&lt;/<span style="color:#f92672">a</span>&gt;
</span></span><span style="display:flex;"><span>   &lt;/<span style="color:#f92672">div</span>&gt;
</span></span><span style="display:flex;"><span>   &lt;<span style="color:#f92672">div</span>&gt;
</span></span><span style="display:flex;"><span>     &lt;<span style="color:#f92672">img</span> <span style="color:#a6e22e">src</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;https://www.baidu.com&#34;</span> <span style="color:#a6e22e">alt</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;&#34;</span>&gt;
</span></span><span style="display:flex;"><span>     &lt;<span style="color:#f92672">a</span> <span style="color:#a6e22e">href</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;https://www.baidu.com&#34;</span>&gt;xxxx的博客&lt;/<span style="color:#f92672">a</span>&gt;
</span></span><span style="display:flex;"><span>   &lt;/<span style="color:#f92672">div</span>&gt;
</span></span><span style="display:flex;"><span>   &lt;<span style="color:#f92672">div</span>&gt;
</span></span><span style="display:flex;"><span>     &lt;<span style="color:#f92672">img</span> <span style="color:#a6e22e">src</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;https://www.baidu.com&#34;</span> <span style="color:#a6e22e">alt</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;&#34;</span>&gt;
</span></span><span style="display:flex;"><span>     &lt;<span style="color:#f92672">a</span> <span style="color:#a6e22e">href</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;https://www.baidu.com&#34;</span>&gt;xxxx的博客&lt;/<span style="color:#f92672">a</span>&gt;
</span></span><span style="display:flex;"><span>   &lt;/<span style="color:#f92672">div</span>&gt;
</span></span><span style="display:flex;"><span> &lt;/<span style="color:#f92672">div</span>&gt;
</span></span></code></pre></div><p>也可以是：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-html" data-lang="html"><span style="display:flex;"><span>  &lt;<span style="color:#f92672">a</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;cf-friends-link&#34;</span> <span style="color:#a6e22e">href</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;https://www.baidu.com&#34;</span>&gt;
</span></span><span style="display:flex;"><span>    &lt;<span style="color:#f92672">img</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;cf-friends-avatar&#34;</span> <span style="color:#a6e22e">src</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;https://www.baidu.com&#34;</span> <span style="color:#a6e22e">alt</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;&#34;</span>&gt;
</span></span><span style="display:flex;"><span>    &lt;<span style="color:#f92672">span</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;cf-friends-name&#34;</span>&gt; xxxx的博客&lt;/<span style="color:#f92672">span</span>&gt;
</span></span><span style="display:flex;"><span>  &lt;/<span style="color:#f92672">a</span>&gt;
</span></span></code></pre></div><p>使用时，只需要在fc_settings.yaml配置文件中配置为common1或者common2即可。</p>
<h2 id="部署">部署</h2>
<p>友链朋友圈提供了非常多的部署方式，可以根据自己的习惯选择自己喜欢的方式部署，让我觉得十分的贴心。而我选择了极简模式。</p>
<blockquote>
<p>极简模式旨在最简程度运行程序，并输出最简化结果。</p></blockquote>
<p>在极简模式下，友链朋友圈会使用 Github Action 抓取友链页中的连接，并将连接RSS中的文章输出为一个Data.json文件存放在Github仓库中。而我们只需要调用这个文件，做前端渲染就行了。</p>
<blockquote>
<p><a href="https://hexo-circle-of-friends-doc.vercel.app/#/simplemode">极简模式部署</a></p></blockquote>
<p>如果担心 <code>data.json</code>  放在Github仓库访问不稳定，也可以通过 <code>up to aliyun oss</code> 等Github Action 将文件推送到国内的CDN上进行访问。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yml" data-lang="yml"><span style="display:flex;"><span>- <span style="color:#f92672">name</span>: <span style="color:#ae81ff">Setup aliyun oss</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">uses</span>: <span style="color:#ae81ff">manyuanrong/setup-ossutil@master</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">with</span>:
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">endpoint</span>: <span style="color:#ae81ff">oss-cn-hangzhou.aliyuncs.com</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">access-key-id</span>: <span style="color:#ae81ff">${{ secrets.ACCESS_KEY_ID }}</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">access-key-secret</span>: <span style="color:#ae81ff">${{ secrets.ACCESS_KEY_SECRET }}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>- <span style="color:#f92672">name</span>: <span style="color:#ae81ff">To aliyun</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">run</span>: <span style="color:#ae81ff">ossutil cp -rf data.json oss://${{ secrets.BUCKET }}/</span>
</span></span></code></pre></div><p>需要在仓库的setting&ndash;&gt;Secrets and variables&ndash;&gt;Actions&ndash;&gt;New repository secret</p>
<p>配置好Action所需要的变量。</p>
<h2 id="渲染">渲染</h2>
<p>部署成功后，应该就可以在你 <code>fork</code> 的仓库中看到 <code>data.json</code> 文件了。那么接下来，就是在前端渲染了。</p>
<p>直接上代码：</p>
<ul>
<li>HTML</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-html" data-lang="html"><span style="display:flex;"><span>&lt;<span style="color:#f92672">div</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;links&#34;</span>&gt;&lt;/<span style="color:#f92672">div</span>&gt;
</span></span></code></pre></div><ul>
<li>JS</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">linksUrl</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;https://&lt;你的Github仓库地址&gt;/data.json&#39;</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">linksDom</span> <span style="color:#f92672">=</span> document.<span style="color:#a6e22e">querySelector</span>(<span style="color:#e6db74">&#39;.links&#39;</span>);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">linksDom</span>) {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">getLinks</span>()
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">getLinks</span>() {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">fetch</span>(<span style="color:#a6e22e">linksUrl</span>).<span style="color:#a6e22e">then</span>(<span style="color:#a6e22e">res</span> =&gt; <span style="color:#a6e22e">res</span>.<span style="color:#a6e22e">json</span>()).<span style="color:#a6e22e">then</span>(<span style="color:#a6e22e">resdata</span> =&gt; {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">updateHtml</span>(<span style="color:#a6e22e">resdata</span>.<span style="color:#a6e22e">article_data</span>);
</span></span><span style="display:flex;"><span>  });
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">updateHtml</span>(<span style="color:#a6e22e">data</span>){
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">result</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">resultAll</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;&#34;</span>;
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">i</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">i</span> <span style="color:#f92672">&lt;</span> <span style="color:#a6e22e">data</span>.<span style="color:#a6e22e">length</span>; <span style="color:#a6e22e">i</span><span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">let</span> <span style="color:#a6e22e">author</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">data</span>[<span style="color:#a6e22e">i</span>].<span style="color:#a6e22e">author</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">avatar</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">data</span>[<span style="color:#a6e22e">i</span>].<span style="color:#a6e22e">avatar</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">title</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">data</span>[<span style="color:#a6e22e">i</span>].<span style="color:#a6e22e">title</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">link</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">data</span>[<span style="color:#a6e22e">i</span>].<span style="color:#a6e22e">link</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">floor</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">data</span>[<span style="color:#a6e22e">i</span>].<span style="color:#a6e22e">floor</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">created</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">data</span>[<span style="color:#a6e22e">i</span>].<span style="color:#a6e22e">created</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">result</span> <span style="color:#f92672">+=</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#39;&lt;div class=&#34;col-12 mt-3&#34;&gt;&lt;div class=&#34;item-body flex-fill p-3&#34;&gt;&lt;div class=&#34;item-header d-flex mb-3&#34;&gt;&lt;div class=&#34;item-avatar mr-3&#34; style=&#34;background-image:url(&#39;</span><span style="color:#f92672">+</span> <span style="color:#a6e22e">avatar</span> <span style="color:#f92672">+</span><span style="color:#e6db74">&#39;)&#34;&gt;&lt;/div&gt;&lt;div class=&#34;item-sub&#34;&gt;&lt;div class=&#34;item-creator&#34;&gt;&#39;</span><span style="color:#f92672">+</span> <span style="color:#a6e22e">author</span> <span style="color:#f92672">+</span><span style="color:#e6db74">&#39;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class =&#34;item-content d-flex flex-fill flex-column&#34;&gt;&lt;div class=&#34;item-inner flex-fill my-2&#34;&gt;&lt;a href=&#34;&#39;</span><span style="color:#f92672">+</span><span style="color:#a6e22e">link</span><span style="color:#f92672">+</span><span style="color:#e6db74">&#39;&#34; target=&#34;_blank&#34;&gt;&#39;</span><span style="color:#f92672">+</span> <span style="color:#a6e22e">title</span><span style="color:#f92672">+</span><span style="color:#e6db74">&#39;&lt;/a&gt;&lt;/div&gt;&lt;div class=&#34;item-footer d-flex mt-2&#34;&gt;&lt;div class=&#34;item-time item-tag d-flex align-items-center px-2 text-xs&#34;&gt;&#39;</span><span style="color:#f92672">+</span><span style="color:#a6e22e">created</span><span style="color:#f92672">+</span><span style="color:#e6db74">&#39;&lt;/div&gt;&lt;div class=&#34;d-flex flex-fill justify-content-end&#34;&gt;&lt;div class=&#34;item d-flex align-items-center&#34;&gt;&lt;i class=&#34;iconfont iconthunderbolt&#34;&gt;&lt;/i&gt;&lt;span class=&#34;ml-1&#34;&gt;&#39;</span><span style="color:#f92672">+</span><span style="color:#a6e22e">floor</span><span style="color:#f92672">+</span><span style="color:#e6db74">&#39;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&#39;</span>;
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">resultAll</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">result</span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">linksDom</span>.<span style="color:#a6e22e">insertAdjacentHTML</span>(<span style="color:#e6db74">&#39;beforeend&#39;</span>, <span style="color:#a6e22e">resultAll</span>);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>其中<code>result</code> 内的HTML结构请根据主题自行修改。</p>
<p>搞定收工～</p>]]></content><category scheme="https://nuoea.com/categories/%E6%8A%98%E8%85%BE" term="%E6%8A%98%E8%85%BE" label="折腾"/><category scheme="https://nuoea.com/tags/%E8%BF%9E%E6%8E%A5" term="%E8%BF%9E%E6%8E%A5" label="连接"/><category scheme="https://nuoea.com/tags/%E6%9C%8B%E5%8F%8B%E5%9C%88" term="%E6%9C%8B%E5%8F%8B%E5%9C%88" label="朋友圈"/></entry><entry><title type="html">使用 Umami Api 显示统计数据</title><link href="https://nuoea.com/use-umami-api/" rel="alternate" type="text/html"/><id>https://nuoea.com/use-umami-api/</id><published>2023-06-08T11:25:34+08:00</published><updated>2023-06-08T11:25:34+08:00</updated><content type="html"><![CDATA[<h2 id="前言">前言</h2>
<p>最近在大家的疯狂安利下，捣鼓上了这样一款可以部署在Docker上的前端统计应用。特别是木木老师，更是直接放出了<a href="https://immmmm.com/hi-umami-api/"> 《前端调用 Umami API 数据》 </a> 。不得不说，这个应用的可玩性成功的吸引了我的注意。</p>
<p>通过阅读官方的API文档，一番折腾下来，也是成功的在Memos页面中调用了umami统计的浏览数据。于是做个记录。</p>
<h2 id="认证">认证</h2>
<p>如果想要获取Umami的数据，首先需要身份鉴权。</p>
<pre tabindex="0"><code>POST https://umami.mydomain.com/api/auth/login
</code></pre><p>通过上述接口，请求到一个TOKEN。获取任何数据都需要在请求的头部带上这个TOKEN，完成身份的认证。</p>
<p>这一步我的建议是通过API在线请求调试工具去完成，像 <code>POSTMAN</code>、<code>hoppscotch</code></p>
<blockquote>
<p><a href="https://hoppscotch.io/">Hoppscotch</a></p></blockquote>
<p><img class="lozad" data-src="https://i.nuoea.com/img/2023/06/08/1686197391.jpg" alt=""  /></p>
<p>如果请求成功，会返回一个JSON</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-JSON" data-lang="JSON"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;token&#34;</span>: <span style="color:#e6db74">&#34;eyTMjU2IiwiY...4Q0JDLUhWxnIjoiUE_A&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;user&#34;</span>: {
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;id&#34;</span>: <span style="color:#e6db74">&#34;cd33a605-d785-42a1-9365-d6cad3b7befd&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;username&#34;</span>: <span style="color:#e6db74">&#34;your-username&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&#34;createdAt&#34;</span>: <span style="color:#e6db74">&#34;2020-04-20 01:00:00&#34;</span>
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>如此一来，就请求到了TOKEN，建议将TOKEN存入 HUGO 里面的 <code>config</code>中，方便后面调用。</p>
<pre tabindex="0"><code>[params.umami]
    url = &#39;https://umami.mydomain.com&#39;
    token = &#39;eyTMjU2IiwiY...4Q0JDLUhWxnIjoiUE_A&#39;
</code></pre><h2 id="浏览数据">浏览数据</h2>
<p>获取文章的阅读数据，可以使用下面的这个API：</p>
<pre tabindex="0"><code>GET https://umami.mydomain.com/api/websites/{websiteId}/metrics
</code></pre><p>参数如下：</p>
<ul>
<li>startAt: 起始时间</li>
<li>endAt: 终止时间</li>
<li>type: url</li>
</ul>
<p>请求代码如下：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">umiTime</span> <span style="color:#f92672">=</span> Date.<span style="color:#a6e22e">parse</span>(<span style="color:#66d9ef">new</span> Date()); <span style="color:#75715e">//获取当前时间戳
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">umiUrl</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;https://umami.mydomain.com/api/websites/&#34;</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">bbMemo</span>.<span style="color:#a6e22e">umiId</span> <span style="color:#f92672">+</span> <span style="color:#e6db74">&#34;/metrics?startAt=0&amp;endAt=&#34;</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">umiTime</span> <span style="color:#f92672">+</span> <span style="color:#e6db74">&#34;&amp;type=url&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">fetch</span>(<span style="color:#a6e22e">umiUrl</span>,{
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">method</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;GET&#39;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">mode</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;cors&#39;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">cache</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;default&#39;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">headers</span><span style="color:#f92672">:</span> {
</span></span><span style="display:flex;"><span>      <span style="color:#e6db74">&#39;Authorization&#39;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;Bearer &#39;</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">umami</span>.<span style="color:#a6e22e">token</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#e6db74">&#39;Content-Type&#39;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;application/json&#39;</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  })
</span></span><span style="display:flex;"><span>  .<span style="color:#a6e22e">then</span>(<span style="color:#a6e22e">res</span> =&gt; <span style="color:#a6e22e">res</span>.<span style="color:#a6e22e">json</span>()).<span style="color:#a6e22e">then</span>(<span style="color:#a6e22e">resdata</span> =&gt; {});
</span></span></code></pre></div><p>请求成功后，获取到的数据如下：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-JSON" data-lang="JSON"><span style="display:flex;"><span>[
</span></span><span style="display:flex;"><span>    {<span style="color:#f92672">&#34;x&#34;</span>: <span style="color:#e6db74">&#34;/&#34;</span>, <span style="color:#f92672">&#34;y&#34;</span>: <span style="color:#ae81ff">46</span>}
</span></span><span style="display:flex;"><span>    {<span style="color:#f92672">&#34;x&#34;</span>: <span style="color:#e6db74">&#34;/docs&#34;</span>, <span style="color:#f92672">&#34;y&#34;</span>: <span style="color:#ae81ff">17</span>}
</span></span><span style="display:flex;"><span>    {<span style="color:#f92672">&#34;x&#34;</span>: <span style="color:#e6db74">&#34;/download&#34;</span>, <span style="color:#f92672">&#34;y&#34;</span>: <span style="color:#ae81ff">14</span>}
</span></span><span style="display:flex;"><span>]
</span></span></code></pre></div><p>最后，通过遍历对比JSON中的地址与当前文章的URL地址，就可以获取到对应的浏览数据了。</p>
<h2 id="最后">最后</h2>
<p>官方的API文档里面还有非常多的接口，大家可以根据自己的需求，按照上面的方法去获取自己想要的统计数据，就酱。</p>]]></content><category scheme="https://nuoea.com/categories/%E6%8A%98%E8%85%BE" term="%E6%8A%98%E8%85%BE" label="折腾"/><category scheme="https://nuoea.com/tags/umami" term="umami" label="umami"/><category scheme="https://nuoea.com/tags/api" term="api" label="API"/></entry><entry><title type="html">Memos页面添加Twikoo评论系统</title><link href="https://nuoea.com/memos-twikoo/" rel="alternate" type="text/html"/><id>https://nuoea.com/memos-twikoo/</id><published>2023-06-05T21:56:31+08:00</published><updated>2023-06-05T21:56:31+08:00</updated><content type="html"><![CDATA[<h2 id="写在前面">写在前面</h2>
<p>如果没有木木老师的<a href="https://immmmm.com/memos-with-twikoo/">《Memos x Twikoo》</a>我是根本不会把这两个毫不相干的系统联系起来的，在给Memos添加了Twikoo评论系统之后，因为增加了社交属性，所以BB的时候，都更带劲了。</p>
<p>而美中不足的就是如果需要评论，需要跳转到Memos的页面内，这对于用户体验来说，还是略有不足的。而就在前不久，拾月老师的一篇<a href="https://www.skyue.com/23051422.html">《单页 Memos 添加 Artalk 评论，无限接近微博》</a>让评论系统嵌入Memos页面内，从而可以沉浸式边BB边吐槽，让Momos从一个记录工具成功变身微博、朋友圈，可玩性大增。只不过我看教程用的都是<code>Artalk</code>这个评论工具，作为用着<code>Twikoo</code>很顺手，并不想更换的我来说，只能自己根据大佬们提供的思路，自行折腾了。</p>
<h2 id="评论数量">评论数量</h2>
<p>关于Memos页面的搭建，直接用木木老师的就好。木木老师开发的版本，代码逻辑清晰，功能完善，开箱即用。Twikoo评论数量的实现在官网有相应API。</p>
<blockquote>
<p>批量获取文章评论数</p></blockquote>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#a6e22e">twikoo</span>.<span style="color:#a6e22e">getCommentsCount</span>({
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">envId</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;您的环境id&#39;</span>, <span style="color:#75715e">// 环境 ID
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>  <span style="color:#75715e">// region: &#39;ap-guangzhou&#39;, // 环境地域，默认为 ap-shanghai，如果您的环境地域不是上海，需传此参数
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>  <span style="color:#a6e22e">urls</span><span style="color:#f92672">:</span> [ <span style="color:#75715e">// 不包含协议、域名、参数的文章路径列表，必传参数
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#e6db74">&#39;/2020/10/post-1.html&#39;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#39;/2020/11/post-2.html&#39;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#39;/2020/12/post-3.html&#39;</span>
</span></span><span style="display:flex;"><span>  ],
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">includeReply</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">false</span> <span style="color:#75715e">// 评论数是否包括回复，默认：false
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>}).<span style="color:#a6e22e">then</span>(<span style="color:#66d9ef">function</span> (<span style="color:#a6e22e">res</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#a6e22e">res</span>);
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">// 返回示例: [
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>  <span style="color:#75715e">//   { url: &#39;/2020/10/post-1.html&#39;, count: 10 },
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>  <span style="color:#75715e">//   { url: &#39;/2020/11/post-2.html&#39;, count: 0 },
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>  <span style="color:#75715e">//   { url: &#39;/2020/12/post-3.html&#39;, count: 20 }
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>  <span style="color:#75715e">// ]
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>}).<span style="color:#66d9ef">catch</span>(<span style="color:#66d9ef">function</span> (<span style="color:#a6e22e">err</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">// 发生错误
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>  <span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">error</span>(<span style="color:#a6e22e">err</span>);
</span></span><span style="display:flex;"><span>});
</span></span></code></pre></div><p>请求中，需要一个评论URL的数组，所以我的思路是先通过Api获取Memos的数据。在遍历获取到的数据之后，拿到我所希望的由URL组成的数组。</p>
<p>直接在 getFirstList（） 方法中增加一个方法 updateTiwkoo()，并传值。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">getFirstList</span>() {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">bbUrl</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">memos</span> <span style="color:#f92672">+</span> <span style="color:#e6db74">&#34;api/memo?creatorId=&#34;</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">bbMemo</span>.<span style="color:#a6e22e">creatorId</span> <span style="color:#f92672">+</span> <span style="color:#e6db74">&#34;&amp;rowStatus=NORMAL&amp;limit=&#34;</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">limit</span>;
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">fetch</span>(<span style="color:#a6e22e">bbUrl</span>).<span style="color:#a6e22e">then</span>(<span style="color:#a6e22e">res</span> =&gt; <span style="color:#a6e22e">res</span>.<span style="color:#a6e22e">json</span>()).<span style="color:#a6e22e">then</span>(<span style="color:#a6e22e">resdata</span> =&gt; {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">updateTiwkoo</span>(<span style="color:#a6e22e">resdata</span>.<span style="color:#a6e22e">data</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">nowLength</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">resdata</span>.<span style="color:#a6e22e">data</span>.<span style="color:#a6e22e">length</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">nowLength</span> <span style="color:#f92672">&lt;</span> <span style="color:#a6e22e">limit</span>) { <span style="color:#75715e">//返回数据条数小于 limit 则直接移除“加载更多”按钮，中断预加载
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>      document.<span style="color:#a6e22e">querySelector</span>(<span style="color:#e6db74">&#34;button.button-load&#34;</span>).<span style="color:#a6e22e">remove</span>()
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">return</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">page</span><span style="color:#f92672">++</span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">offset</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">limit</span> <span style="color:#f92672">*</span> (<span style="color:#a6e22e">page</span> <span style="color:#f92672">-</span> <span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">getNextList</span>()
</span></span><span style="display:flex;"><span>  });
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">updateTiwkoo</span>(<span style="color:#a6e22e">data</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">twiID</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">data</span>.<span style="color:#a6e22e">map</span>((<span style="color:#a6e22e">item</span>) =&gt; <span style="color:#a6e22e">memos</span> <span style="color:#f92672">+</span> <span style="color:#e6db74">&#34;m/&#34;</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">item</span>.<span style="color:#a6e22e">id</span>);
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">twikoo</span>.<span style="color:#a6e22e">getCommentsCount</span>({
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">envId</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">envId</span>, <span style="color:#75715e">// 环境 ID
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    <span style="color:#a6e22e">urls</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">twiID</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">includeReply</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">true</span> <span style="color:#75715e">// 评论数是否包括回复，默认：false
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>  }).<span style="color:#a6e22e">then</span>(<span style="color:#66d9ef">function</span> (<span style="color:#a6e22e">res</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">updateCount</span>(<span style="color:#a6e22e">res</span>)
</span></span><span style="display:flex;"><span>  }).<span style="color:#66d9ef">catch</span>(<span style="color:#66d9ef">function</span> (<span style="color:#a6e22e">err</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">error</span>(<span style="color:#a6e22e">err</span>);
</span></span><span style="display:flex;"><span>  });
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">updateCount</span>(<span style="color:#a6e22e">res</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">twiCount</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">res</span>.<span style="color:#a6e22e">map</span>((<span style="color:#a6e22e">item</span>) =&gt; {
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">return</span> Object.<span style="color:#a6e22e">assign</span>({},{<span style="color:#e6db74">&#39;count&#39;</span><span style="color:#f92672">:</span><span style="color:#a6e22e">item</span>.<span style="color:#a6e22e">count</span>})
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">bbTwikoo</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">data</span>.<span style="color:#a6e22e">map</span>((<span style="color:#a6e22e">item</span>,<span style="color:#a6e22e">index</span>) =&gt; {
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">return</span> {...<span style="color:#a6e22e">item</span>, ...<span style="color:#a6e22e">twiCount</span>[<span style="color:#a6e22e">index</span>]};
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">updateHTMl</span>(<span style="color:#a6e22e">bbTwikoo</span>)
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>在获取到评论数的数据后，直接将两个数组合并。形成一个包含有评论数的新数组。</p>
<h2 id="评论内容">评论内容</h2>
<p>主要是在 <code>Memos</code> 页面内增加一个 供 <code>Twikoo</code> 初始化的容器。并通过一系列触发操作显示渲染。详细如下：</p>
<p>首先，我们需要在页面内增加一个按钮，通过点击来触发评论加载。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-html" data-lang="html"><span style="display:flex;"><span>&lt;<span style="color:#f92672">a</span> <span style="color:#a6e22e">onclick</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#39;loadTwikoo(memosId)&#39;</span>&gt;&lt;/<span style="color:#f92672">a</span>&gt;
</span></span></code></pre></div><p>其次，我们需要一个容纳 <code>Twikoo</code> 评论的容器，未触发时该容器隐藏。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-html" data-lang="html"><span style="display:flex;"><span>&lt;<span style="color:#f92672">div</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#39;twikoo-body twikoo-memosId d-none&#39;</span>&gt;&lt;/<span style="color:#f92672">div</span>&gt;
</span></span></code></pre></div><p>最后，我们需要一个点击事件，将评论初始化。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">loadTwikoo</span>(<span style="color:#a6e22e">memosId</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">twikooDom</span> <span style="color:#f92672">=</span> document.<span style="color:#a6e22e">querySelector</span>(<span style="color:#e6db74">&#39;.twikoo-memosId&#39;</span>);
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">var</span> <span style="color:#a6e22e">twikooCon</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;&lt;div id=&#39;twikoo&#39;&gt;&lt;/div&gt;&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">twikooDom</span>.<span style="color:#a6e22e">classList</span>.<span style="color:#a6e22e">contains</span>(<span style="color:#e6db74">&#39;d-none&#39;</span>)) {
</span></span><span style="display:flex;"><span>    document.<span style="color:#a6e22e">querySelectorAll</span>(<span style="color:#e6db74">&#39;.twikoo-body&#39;</span>).<span style="color:#a6e22e">forEach</span>((<span style="color:#a6e22e">item</span>) =&gt; {<span style="color:#a6e22e">item</span>.<span style="color:#a6e22e">classList</span>.<span style="color:#a6e22e">add</span>(<span style="color:#e6db74">&#39;d-none&#39;</span>);})
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span>(document.<span style="color:#a6e22e">getElementById</span>(<span style="color:#e6db74">&#34;twikoo&#34;</span>)){
</span></span><span style="display:flex;"><span>      document.<span style="color:#a6e22e">getElementById</span>(<span style="color:#e6db74">&#34;twikoo&#34;</span>).<span style="color:#a6e22e">remove</span>() <span style="color:#75715e">//如果页面中已经有其他Twikoo初始化，则移除。
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">twikooDom</span>.<span style="color:#a6e22e">insertAdjacentHTML</span>(<span style="color:#e6db74">&#39;beforeend&#39;</span>, <span style="color:#a6e22e">twikooCon</span>); 
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">twikooDom</span>.<span style="color:#a6e22e">classList</span>.<span style="color:#a6e22e">remove</span>(<span style="color:#e6db74">&#39;d-none&#39;</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">twikoo</span>.<span style="color:#a6e22e">init</span>({
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">envId</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">envId</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">el</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;#twikoo&#39;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">path</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">memosPath</span> <span style="color:#f92672">+</span> <span style="color:#e6db74">&#34;/m/&#34;</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">memosId</span> 
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>  }<span style="color:#66d9ef">else</span>{
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">twikooDom</span>.<span style="color:#a6e22e">classList</span>.<span style="color:#a6e22e">add</span>(<span style="color:#e6db74">&#39;d-none&#39;</span>);
</span></span><span style="display:flex;"><span>    document.<span style="color:#a6e22e">getElementById</span>(<span style="color:#e6db74">&#34;twikoo&#34;</span>).<span style="color:#a6e22e">remove</span>()
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>值得一提的是，需要将该 <code>Twikoo</code> 的ID值传给触发的方法。</p>
<h2 id="最终效果">最终效果</h2>
<p>效果如下</p>
<p><img class="lozad" data-src="https://i.nuoea.com/img/2023/06/05/1685976063.jpg" alt=""  /></p>]]></content><category scheme="https://nuoea.com/categories/%E6%8A%98%E8%85%BE" term="%E6%8A%98%E8%85%BE" label="折腾"/><category scheme="https://nuoea.com/tags/memos" term="memos" label="Memos"/><category scheme="https://nuoea.com/tags/twikoo" term="twikoo" label="Twikoo"/></entry><entry><title type="html">制作Big Sur风格的 icon</title><link href="https://nuoea.com/big-sur-icns/" rel="alternate" type="text/html"/><id>https://nuoea.com/big-sur-icns/</id><published>2021-06-27T16:30:37+08:00</published><updated>2021-06-27T16:30:37+08:00</updated><content type="html"><![CDATA[<h2 id="什么是-icns">什么是 icns</h2>
<p>icns 是 Apple 的 macOS 操作系统的 App 图标文件的扩展名，你在 macOS 的「 Desktop 桌面」、「Finder 访达」、「Dock 程序坞」等看到应用程序的外观就是由一个内置在此 App 内部的扩展名为.icns的文件实现的。</p>
<p>你可以通过鼠标“右键”点击 App - “显示包内容” - 进入 “Contents” 目录 - 进入“Resources”目录，然后在目录下可以找到名为Appicon.icns或其他后缀为.icns的一个图标文件。</p>
<p>要创建一个.icns图标文件，需要准备以下 10 种不同大小的.png图片文件</p>
<table>
  <thead>
      <tr>
          <th>图片名称</th>
          <th>图片大小</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>icon_16x16.png</td>
          <td>16x16</td>
      </tr>
      <tr>
          <td><a href="mailto:icon_16x16@2x.png">icon_16x16@2x.png</a></td>
          <td>32x32</td>
      </tr>
      <tr>
          <td>icon_32x32.png</td>
          <td>32x32</td>
      </tr>
      <tr>
          <td><a href="mailto:icon_32x32@2x.png">icon_32x32@2x.png</a></td>
          <td>64x64</td>
      </tr>
      <tr>
          <td>icon_128x128.png</td>
          <td>128x128</td>
      </tr>
      <tr>
          <td><a href="mailto:icon_128x128@2x.png">icon_128x128@2x.png</a></td>
          <td>256x256</td>
      </tr>
      <tr>
          <td>icon_256x256.png</td>
          <td>256x256</td>
      </tr>
      <tr>
          <td><a href="mailto:icon_256x256@2x.png">icon_256x256@2x.png</a></td>
          <td>512x512</td>
      </tr>
      <tr>
          <td>icon_512x512.png</td>
          <td>512x512</td>
      </tr>
      <tr>
          <td><a href="mailto:icon_512x512@2x.png">icon_512x512@2x.png</a></td>
          <td>1024x1024</td>
      </tr>
  </tbody>
</table>
<h2 id="big-sur">Big Sur</h2>
<p>在发布会上，Craig提及了macOS全新的拟物化设计。类似IOS的图标风格，加速了苹果全终端融合的进程。</p>
<p>但是因为时间的关系，很多第三方的APP暂时还没有适配这种风格的图标。所以，作为一名深度强迫症患者。自己去制作相关的ICNS就是唯一的出路了。</p>
<p><img class="lozad" data-src="https://i.nuoea.com/img/2021/20210627170052.jpg" alt=""  /></p>
<h2 id="制作过程">制作过程</h2>
<ul>
<li>准备最大尺寸 1024x1024 图片一张，重命名为icon.png，其他大小尺寸可以通过终端命令生成；</li>
</ul>
<p>最好是能根据Apple的设计规范，制作统一视觉效果的图标。如果会使用设计工具。如：PS、Sketch、Figma等。可以使用相关工具的模版自动生成。</p>
<blockquote>
<p><a href="https://github.com/elrumo/macOS_Big_Sur_icons_replacements/raw/master/design/Template-Icon-App.sketch">Sketch图标模版</a></p></blockquote>
<ul>
<li>通过鼠标右键或者命令，创建一个名为icons.iconset的文件夹；</li>
</ul>
<pre tabindex="0"><code> mkdir icons.iconset
</code></pre><ul>
<li>通过终端来快速创建各种不同尺寸要求的图片文件;</li>
</ul>
<pre tabindex="0"><code>sips -z 16 16 icon.png -o icons.iconset/icon_16x16.png
sips -z 32 32 icon.png -o icons.iconset/icon_16x16@2x.png
sips -z 32 32 icon.png -o icons.iconset/icon_32x32.png
sips -z 64 64 icon.png -o icons.iconset/icon_32x32@2x.png
sips -z 128 128 icon.png -o icons.iconset/icon_128x128.png
sips -z 256 256 icon.png -o icons.iconset/icon_128x128@2x.png
sips -z 256 256 icon.png -o icons.iconset/icon_256x256.png
sips -z 512 512 icon.png -o icons.iconset/icon_256x256@2x.png
sips -z 512 512 icon.png -o icons.iconset/icon_512x512.png
sips -z 1024 1024 icon.png -o icons.iconset/icon_512x512@2x.png
</code></pre><ul>
<li>最后，终端中运行下面的命令，就可以获得名为icon.icns的图标文件了;</li>
</ul>
<pre tabindex="0"><code>iconutil -c icns icons.iconset -o icon.icns
</code></pre><p><strong>注意 : icon.png图片文件和icons.iconset文件夹要保存在同一级目录下，终端启动后切换到该目录。</strong></p>
<div class="row">
  
  
  
  
</div>


]]></content><category scheme="https://nuoea.com/categories/%E6%8A%98%E8%85%BE" term="%E6%8A%98%E8%85%BE" label="折腾"/><category scheme="https://nuoea.com/tags/mac" term="mac" label="Mac"/><category scheme="https://nuoea.com/tags/%E6%95%99%E7%A8%8B" term="%E6%95%99%E7%A8%8B" label="教程"/></entry><entry><title type="html">Hi，Hugo</title><link href="https://nuoea.com/hi-hugo/" rel="alternate" type="text/html"/><id>https://nuoea.com/hi-hugo/</id><published>2020-07-18T16:39:16+08:00</published><updated>2020-07-18T16:39:16+08:00</updated><content type="html"><![CDATA[<h2 id="写在前面">写在前面</h2>
<p>一场突如其来的疫情，打乱了所有的计划和安排。可能是身处武汉的原因，可能焦虑的情绪会更多一些。</p>
<p>自四月八日武汉解封以来，武汉的一切似乎都在好转，但疫情之后的武汉又似乎和以往不那么一样。可能是更多的人不放心公共交通，选择自己开车，导致的交通大拥堵。让这个城市看起来，似乎恢复了往日的繁华和热闹。只是临街商铺萧索的生意告诉我们，这一场浩劫所带来的影响，还远远没有结束。只是我们，是时候继续往前走，向前看了。</p>
<h2 id="关于">关于</h2>
<p>生活重新回到正轨，新的工作也趋于稳定。到几个朋友的网站一看，发现好多都在折腾新的工具，就是这个 GO 语言编写的 Hugo 。</p>
<p>本着大家都推荐那就去看看的原则，就到 Hugo 的官方去看了下文档。看了之后吧，其实还是一脸懵逼，对于一个已经使用了 Gridea 很久，什么功能都使用的很贴心的懒人来说。文章主题等等需要重新折腾一遍，我的内心是拒绝的。而且部署的方式看起来也没有 Gridea 那么方便。所以看来看去。还是提不起对 Hugo 的兴趣。直到 木木 也开始搞这个东西。并推出了相当详细的折腾文档。才开始动心起来。</p>
<h2 id="折腾">折腾</h2>
<p>按照木木的教程一路走下来吧，其实还蛮有意思。折腾下来，就是没有找到比较好看的主题，当然收费的确实有喜欢的，只不过不想花这个冤枉钱。看来看去，觉得要用的话那还是自己弄吧。反正都是折腾，自然是怎么开心怎么来。</p>
<p>Go语言是一窍不通的。但是木木贴出了常用代码。所以改个主题的难度倒也能接受。慢慢的有了现在的样子，以后再慢慢完善吧。</p>]]></content><category scheme="https://nuoea.com/categories/%E6%8A%98%E8%85%BE" term="%E6%8A%98%E8%85%BE" label="折腾"/><category scheme="https://nuoea.com/tags/hugo" term="hugo" label="Hugo"/></entry><entry><title type="html">换了新主题</title><link href="https://nuoea.com/change-theme-vant/" rel="alternate" type="text/html"/><id>https://nuoea.com/change-theme-vant/</id><published>2019-12-18T13:39:23+00:00</published><updated>2019-12-18T13:39:23+00:00</updated><content type="html"><![CDATA[<p>感觉自己还是一个视觉动物。看一个东西久了吧，总是会生出喜新厌旧的情绪。最近工作之余看之前的那套主题越看越觉得不够精致。于是就有想要换掉的冲动。直到最近两天才得了时间，可以落实这个事情。</p>
<h2 id="第一版">第一版</h2>
<p>关于这套主题，最开始设计的时候还是用的阿里的那套 <code>Ant design</code> 的视觉框架。只是在配色细节上根据略有调整。整体还是依托于那套成熟的视觉效果。</p>
<p><img class="lozad" data-src="https://i.nuoea.com/img/2019/12/18/1.jpg" alt=""  /></p>
<h2 id="第二版">第二版</h2>
<p>因为在使用的过程中可能觉得布局方面还是有些痛点，觉得侧边栏的左右布局不太合适，对于排版方面的可定制程度不够灵活。所以有了这个版本。</p>
<p><img class="lozad" data-src="https://i.nuoea.com/img/2019/12/18/2.png" alt=""  /></p>
<p>在这套主题里面采用了 swiper 控件，流式布局。看起来还是挺大气美观的。只是后来越发的觉得臃肿。毕竟不是做什么资讯站，访问速度也是问题。</p>
<h2 id="第三版">第三版</h2>
<p>感觉最近还蛮喜欢这种小而美的精致范儿。每个像素每个线条每个颜色都重做了。首页的样式也根据不同的文章类型做了定制区分。整体展示效果应该更好吧。交互方面对移动端的样式做了比较大的修改，增加了可触控的区域，体验方面比之前应该也会更好。</p>
<p><img class="lozad" data-src="https://i.nuoea.com/img/2019/12/18/3.png" alt=""  /></p>
<h2 id="最后">最后</h2>
<p>这段时间一直没怎么更新，感觉又快一个月了吧。因为毕竟年底了么。也在整理简历啊，工作啊乱七八糟一堆事情。
最开始的时候，是想用Gridea 做一个展示个人设计作品的站，方便换工作的时候用。最近整理简历，也就顺手把这个站给做了。话说 Gridea 支持上传到自己主机的新版快点上线吧。</p>]]></content><category scheme="https://nuoea.com/categories/%E6%8A%98%E8%85%BE" term="%E6%8A%98%E8%85%BE" label="折腾"/><category scheme="https://nuoea.com/tags/theme" term="theme" label="Theme"/></entry><entry><title type="html">Hackintosh 安装全攻略</title><link href="https://nuoea.com/hackintosh-install-strategy/" rel="alternate" type="text/html"/><id>https://nuoea.com/hackintosh-install-strategy/</id><published>2019-11-21T23:15:16+00:00</published><updated>2019-11-21T23:15:16+00:00</updated><content type="html"><![CDATA[<h2 id="写在前面">写在前面</h2>
<p>感觉现在已经离不开 macOS 了。因为手里的这台15款的Macbook Pro 什么都好，就是性能已经慢慢的跟不上我的要求，所以折腾了一台 Hackintosh ，配置之前也发出来了&ndash;<a href="https://nuoea.com/asrock-itx-hackintosh/">我的配置</a>。然后就有小伙伴要求写个教程。我就想整理一下，尽可能全面的从硬件的选购到整个装机点亮的过程都记录下来。希望可以给想折腾的小伙伴一点参考。</p>
<h2 id="硬件指南">硬件指南</h2>
<p>选对的合适的硬件，那么 <code>Hackintosh</code> 就已经成功了90%以上。选对硬件，意味着安装时可以少走弯路，新手也能很轻松的折腾，不仅可以节省大量的时间成本，而且在使用的过程中也可以获得更加完整、稳定的体验。升级起来，也不需要每次都费劲功夫的折腾驱动，非常省心。</p>
<p>就目前而言，能够比较稳定使用的配置是：</p>
<ul>
<li>Intel 1151针的 第八代、第九代酷睿处理器。<code>免驱</code></li>
<li>市面上主流的华硕、技嘉、华擎、微星主板。<code>缩水版除外</code></li>
<li>AMD 的Radeon VII系列、Vega系列、RX系列显卡。<code>免驱</code></li>
<li>主流 M.2接口支持NVME协议的固态硬盘。<code>免驱</code></li>
<li>4k分辨率、5k分辨率的显示器。<code>体验最好</code></li>
<li>苹果Mac拆机或者同款的蓝牙WiFi二合一无线网卡。<code>免驱</code></li>
<li>主流的DDR4内存条。<code>越大越好</code></li>
<li>电源机箱别贪便宜，特别是电源千万不能缩水。<code>功率要足</code></li>
</ul>
<p>基本上 Hackintosh 的配置就从上面的选购指南中挑选就行了，只要不买一些冷门小众的品牌，不会有太大的问题。当然也会有人说，我不喜欢AMD的显卡，我就想用英伟达的显卡做双系统可不可以。答案是可以。但是英伟达的显卡目前不支持升级到 <code>MacOS Mojave 10.14.0</code>以上。只能停留在 <code>10.13.6</code> 这个版本。所以不介意自己不能使用最新版的同学可以选择N卡。</p>
<h2 id="前期准备">前期准备</h2>
<ul>
<li>进入主板BIOS设置，将”安全启动”关闭,将”传统模式”打开。</li>
<li>一个空白的U盘，8G以上的容量。</li>
<li>一个已经制作好带CLover引导工具的安全镜像（.dmg格式）。这里提供一个10.14.6的镜像&ndash;<a href="https://pan.baidu.com/s/1yx7A_wlfepp6ybTCRcz4cg">下载提取码：qrwt</a></li>
<li>Win 平台需要镜像写入软件：TransMac。</li>
<li>Mac 平台需要镜像写入软件：Etcher。</li>
</ul>
<h2 id="写入镜像">写入镜像</h2>
<h3 id="win-平台">Win 平台</h3>
<p><img class="lozad" data-src="https://i.nuoea.com/img/2019/11/21/2.jpg" alt=""  /></p>
<p>写入镜像</p>
<ul>
<li>打开 <code>TransMac</code> 软件，插入空白U盘。</li>
<li>右键单击U盘 选 <code>Format Disk For Mac</code> 格式化U盘。</li>
<li>然后再次右键单击U盘，选中 <code>Restore with Disk Image</code> ，然后选择下载好的安装镜像写入U盘。</li>
</ul>
<h3 id="mac-平台">Mac 平台</h3>
<p><img class="lozad" data-src="https://i.nuoea.com/img/2019/11/21/3.png" alt=""  /></p>
<p>写入镜像</p>
<ul>
<li>打开 <code>Etcher</code> 软件。插入空白U盘。</li>
<li>在 <code>Etcher</code> 中选中自动识别出来的U盘，点击 <code>Flash</code> 即可。</li>
</ul>
<p>制作好了安装U盘之后，就可以开始正式安装了。</p>
<p><img class="lozad" data-src="https://i.nuoea.com/img/2019/11/21/4.png" alt=""  /></p>
<p>clover 引导工具界面</p>
<ul>
<li>首先重启电脑。</li>
<li>插入已经写好镜像的U盘。开机选择从U盘启动。这个时候我们会进入到 <code>clover</code> 的引导界面。</li>
<li>移动光标到 <code>Boot OS X Install</code> 安装盘。然后敲击 <code>空格键</code> 。</li>
<li>用方向键与回车选中 <code>Verbose(-v)</code> 。</li>
<li>再用方向键和回车选择 <code>Boot macOS with selected options</code> 。</li>
<li>等待进入安装界面。</li>
</ul>
<h2 id="安装详细">安装详细</h2>
<p><img class="lozad" data-src="https://i.nuoea.com/img/2019/11/21/5.png" alt=""  /></p>
<p>语言选择</p>
<p><img class="lozad" data-src="https://i.nuoea.com/img/2019/11/21/6.png" alt=""  /></p>
<p>出现macOS实用工具界面,选择磁盘工具</p>
<p><img class="lozad" data-src="https://i.nuoea.com/img/2019/11/21/7.png" alt=""  /></p>
<p>选择 <code>SSD</code>,点击抹掉按钮,选择默认的 <code>Mac OS扩展(日志型)</code> ,将名称修改为 <code>Macintosh HD</code> ,点击 <code>抹掉</code> 按钮</p>
<p><img class="lozad" data-src="https://i.nuoea.com/img/2019/11/21/8.png" alt=""  /></p>
<p>抹盘成功后,它会自动生成一个200MB的EFI分区，用来存放我们的引导文件</p>
<p><img class="lozad" data-src="https://i.nuoea.com/img/2019/11/21/9.png" alt=""  /></p>
<p>到这里,磁盘工具的动作就已经结束了.退出磁盘工具进入安装界面,进行系统的安装了</p>
<p><img class="lozad" data-src="https://i.nuoea.com/img/2019/11/21/10.png" alt=""  /></p>
<p>进入安装界面</p>
<p><img class="lozad" data-src="https://i.nuoea.com/img/2019/11/21/11.png" alt=""  /></p>
<p>选择继续</p>
<p><img class="lozad" data-src="https://i.nuoea.com/img/2019/11/21/12.png" alt=""  /></p>
<p>点击同意,选择Macintosh HD</p>
<p><img class="lozad" data-src="https://i.nuoea.com/img/2019/11/21/13.png" alt=""  /></p>
<p>等它装完，期间会自动重启几次。在重启的时候还是要选择从U盘开机。选择继续安装。</p>
<p><img class="lozad" data-src="https://i.nuoea.com/img/2019/11/21/15.png" alt=""  /></p>
<p>大功告成！</p>
<p><img class="lozad" data-src="https://i.nuoea.com/img/2019/11/21/14.png" alt=""  /></p>
<h2 id="性能优化">性能优化</h2>
<p>安装好了镜像，成功进入mac界面并不是结束。这个时候我们还需要替换适合自己硬件的EFI引导文件到系统的EFI分区，来驱动我们的硬件。</p>
<p>这里有一份 Hackintosh 长期维护的机型名单，可以在上面找到适合自己的 EFI 文件夹。</p>
<blockquote>
<p><a href="https://github.com/daliansky/Hackintosh">长期维护名单</a></p></blockquote>
<p>打开终端,输入命令: <code>diskutil list</code> ,它会显示类似的信息:</p>
<pre tabindex="0"><code class="language-code" data-lang="code">/dev/disk4 (disk image):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      GUID_partition_scheme                        +8.0 GB     disk4
   1:                        EFI EFI                     209.7 MB   disk4s1
   2:                  Apple_HFS XiaoMiPro 10131         7.7 GB     disk4s2

/dev/disk5 (disk image):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      GUID_partition_scheme                        +7.0 GB     disk5
   1:                        EFI EFI                     209.7 MB   disk5s1
   2:                  Apple_HFS XiaoMiPro 10131         6.7 GB     disk5s2
</code></pre><p>挂载EFI分区</p>
<p>我们使用diskutil命令挂载EFI分区，例如这里是：<code>sudo diskutil mount disk5s1</code></p>
<p>复制/替换EFI</p>
<p>将下载好的EFI复制到系统SSD的EFI分区下即可。</p>
<h2 id="最后">最后</h2>
<p><img class="lozad" data-src="https://i.nuoea.com/img/2019/11/21/16.jpg" alt=""  /></p>
<p>EFI目录的结构就是如此。主要的配置项都在 config.plist 文件中。kexts 目录存放的是驱动文件。如果按照给出的标准硬件去配置着台机器的话，其实绝大部分硬件都免驱了，我们只需要几个核心的驱动文件就可以了。</p>
<ul>
<li>Clover &ndash; 引导工具 <a href="https://github.com/Dids/clover-builder/releases">下载地址</a></li>
<li>Lilu &ndash; 核心驱动 <a href="https://github.com/acidanthera/Lilu">下载地址</a></li>
<li>WhateverGreen &ndash; 显卡相关 <a href="https://github.com/acidanthera/WhateverGreen">下载地址</a></li>
<li>AppleALC  &ndash; 声卡相关 <a href="https://github.com/acidanthera/AppleALC/tree/master/">下载地址</a></li>
<li>VirtualSMC  &ndash; 核心驱动 <a href="https://github.com/acidanthera/VirtualSMC/releases">下载地址</a></li>
</ul>
<p>当然，如果已经在上面的 <code>长期维护的机型名单</code>中，找到了自己的配置。那么就不需要自己再去折腾这些了， 直接下载下来替换就能起飞了。就写到这里吧。</p>]]></content><category scheme="https://nuoea.com/categories/%E6%8A%98%E8%85%BE" term="%E6%8A%98%E8%85%BE" label="折腾"/><category scheme="https://nuoea.com/tags/hackintosh" term="hackintosh" label="Hackintosh"/><category scheme="https://nuoea.com/tags/%E6%95%99%E7%A8%8B" term="%E6%95%99%E7%A8%8B" label="教程"/></entry><entry><title type="html">Gridea主题：Mao</title><link href="https://nuoea.com/gridea-theme-mao/" rel="alternate" type="text/html"/><id>https://nuoea.com/gridea-theme-mao/</id><published>2019-11-18T13:04:49+00:00</published><updated>2019-11-18T13:04:49+00:00</updated><content type="html"><![CDATA[<h2 id="关于">关于</h2>
<p>这是给一个朋友定制的主题。朋友提了一些需求，做完原型和飞机稿，看到效果感觉还挺满意的吧。想到最近折腾的 <code>Gridea</code> 非常好用，就用它实现了。后期应该还会继续优化。</p>
<p><img class="lozad" data-src="https://i.nuoea.com/img/2019/11/18/6.jpg" alt=""  /></p>
<hr>
<p><img class="lozad" data-src="https://i.nuoea.com/img/2019/11/18/5.jpg" alt=""  /></p>
<h2 id="设计">设计</h2>
<p><img class="lozad" data-src="https://i.nuoea.com/img/2019/11/18/4.jpg" alt=""  /></p>
<p>给的需求关键词是<code>活泼</code>。就用这组清新的水果绿做了整个视觉的搭配。整体的代入感让人可以有一种回到夏天的清爽感。</p>
<p><img class="lozad" data-src="https://i.nuoea.com/img/2019/11/18/1.png" alt=""  /></p>
<hr>
<p><img class="lozad" data-src="https://i.nuoea.com/img/2019/11/18/2.png" alt=""  /></p>
<hr>
<p><img class="lozad" data-src="https://i.nuoea.com/img/2019/11/18/3.png" alt=""  /></p>
<h2 id="使用">使用</h2>
<ul>
<li>首页展示图片可以自定义，在主题自定义配置中可以配置图片链接，以方便更换。</li>
<li>评论框使用的是 <code>valine</code> 。在主题的自定义配置项目中可以设置ID和KEY。特别感谢 <code>@林木木</code> 童鞋。</li>
<li>页脚置入社交链接。根据自己的需要可以在自定义配置项中定义。</li>
<li>less 所有颜色可自定义。</li>
<li>待完善</li>
</ul>
<h2 id="最后">最后</h2>
<p>希望 <code>Gridea</code> 越来越好～</p>]]></content><category scheme="https://nuoea.com/categories/%E6%8A%98%E8%85%BE" term="%E6%8A%98%E8%85%BE" label="折腾"/><category scheme="https://nuoea.com/tags/theme" term="theme" label="Theme"/></entry><entry><title type="html">Hi，Gridea</title><link href="https://nuoea.com/hi-gridea/" rel="alternate" type="text/html"/><id>https://nuoea.com/hi-gridea/</id><published>2019-11-15T09:32:33+00:00</published><updated>2019-11-15T09:32:33+00:00</updated><content type="html"><![CDATA[<h2 id="写在前面">写在前面</h2>
<p>耗时两天，从 Bitcron 搬到了 Gridea。</p>
<h2 id="关于">关于</h2>
<p>Gridea 是一个船新的静态博客写作客户端，前两天看到 <code>@林木木</code> 在推荐。就好奇去喵了一下。结果却看越喜欢。发现这货简直神器，不但解决了很多静态博客前辈们的痛点，而且自身的特性一大堆：</p>
<ul>
<li>支持 MarkDown</li>
<li>自定义标签</li>
<li>跨设备</li>
<li>多平台</li>
<li>不断完善。。。</li>
</ul>
<h2 id="踩坑">踩坑</h2>
<p>在折腾 Gridea 的这两天，还是遇到了不少的问题：</p>
<ul>
<li>导入之前的文章似乎有 <code>BUG</code> 。导入不识别的文章，会导致整个客户端刷不出数据，呈崩溃状态。</li>
<li>设置了 cname 域名之后，客户端中的访问域名没有改，导致所有 JS 资源全部 403</li>
<li>似乎现在还不能通过 ejs 生成 单独的页面</li>
<li>官方的文档资源还可以更多一点</li>
</ul>
<h2 id="最后">最后</h2>
<p>其实作为一个才起步的程序，其完整程度已经做的很好，该有的基本都有了。而支持 Github 和 Coding 两个平台确实很友好，我在使用的过程中才发现 <code>Coing</code> 已经全部迁移到了腾讯云。好坏都有吧，好的是速度更快，也更稳定了，坏的可能就是国内的一大堆政策吧。希望以后支持更多的资源，持续看好！</p>]]></content><category scheme="https://nuoea.com/categories/%E6%8A%98%E8%85%BE" term="%E6%8A%98%E8%85%BE" label="折腾"/><category scheme="https://nuoea.com/tags/theme" term="theme" label="Theme"/></entry><entry><title type="html">暴风播酷云黑群全攻略</title><link href="https://nuoea.com/baofeng-synology-note/" rel="alternate" type="text/html"/><id>https://nuoea.com/baofeng-synology-note/</id><published>2019-11-05T00:21:00+00:00</published><updated>2019-11-05T00:21:00+00:00</updated><content type="html"><![CDATA[<p>前段时间据说矿难，但具体有多惨我也不太清楚。只是闲鱼上多了很多所谓的矿机，真香的价格让我跟小伙伴们每人都入手了一台。</p>
<p>具体配置如下：</p>
<table>
  <thead>
      <tr>
          <th>名称</th>
          <th>品牌型号</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>CPU&amp;主板</td>
          <td>ASROCK J3455-ITX</td>
      </tr>
      <tr>
          <td>内存</td>
          <td>DDR3 8G</td>
      </tr>
      <tr>
          <td>SSD</td>
          <td>威刚 64G</td>
      </tr>
      <tr>
          <td>HDD</td>
          <td>WD40EJRX 西数4T X 2</td>
      </tr>
      <tr>
          <td>网络接口</td>
          <td>千兆以太网卡</td>
      </tr>
      <tr>
          <td>功耗</td>
          <td>约25W</td>
      </tr>
  </tbody>
</table>
<p>这个配置还是非常不错的，和群晖918+一样的配置让其拿来做黑群是非常不错的选择。所以机器到了之后，就折腾了一番，几个月用下来，感觉真的超值。</p>
<h2 id="前期准备">前期准备</h2>
<ul>
<li>安装黑群晖的主机一台</li>
<li>SSD固态硬盘一块</li>
<li>WinPE U盘一枚</li>
<li>黑群晖二合一安装文件</li>
<li>Roadkil&rsquo;s DiskImage 工具（用于写入系统镜像到硬盘）</li>
<li>DiskGenius 硬盘分区工具</li>
</ul>
<h2 id="安装">安装</h2>
<ul>
<li>清除固态硬盘所有分区</li>
</ul>
<p>进入WinPE之后，使用硬盘工具DiskGenius将目标固态硬盘所有分区删除然后保存。</p>
<p><img class="lozad" data-src="https://i.nuoea.com/img/2019/11/04/11.jpg" alt=""  /></p>
<ul>
<li>写入黑群晖二合一安装文件到固态硬盘</li>
</ul>
<p>打开Roadkil&rsquo;s DiskImage软件。选择下载好的安装文件和选择好硬盘。这里要注意一定不要写错了。</p>
<p><img class="lozad" data-src="https://i.nuoea.com/img/2019/11/04/10.jpg" alt=""  /></p>
<ul>
<li>使用</li>
</ul>
<p>接通电源开机，通过群晖助手或者浏览器输入http://find.synology.com查找群辉机器。就可以正常使用了。</p>
<p><img class="lozad" data-src="https://i.nuoea.com/img/2019/11/04/12.jpg" alt=""  /></p>
<h2 id="资源">资源</h2>
<blockquote>
<p><a href="https://pan.baidu.com/s/16NNJkV2zn_bS_qC80KcHbA">点我下载 ( 提取码：3bix )</a></p></blockquote>]]></content><category scheme="https://nuoea.com/categories/%E6%8A%98%E8%85%BE" term="%E6%8A%98%E8%85%BE" label="折腾"/><category scheme="https://nuoea.com/tags/%E6%95%99%E7%A8%8B" term="%E6%95%99%E7%A8%8B" label="教程"/></entry><entry><title type="html">组了一台 ITX 的黑苹果</title><link href="https://nuoea.com/asrock-itx-hackintosh/" rel="alternate" type="text/html"/><id>https://nuoea.com/asrock-itx-hackintosh/</id><published>2019-11-04T00:34:00+00:00</published><updated>2019-11-04T00:34:00+00:00</updated><content type="html"><![CDATA[<h2 id="hackintosh">Hackintosh</h2>
<p>其实攒这台机器的初心主要是手里的Macbook Pro 2015 性能越来越吃紧了。但是工作的需要，对于机器性能的需求却越来越多。看了下白果劝退的定价，果断还是选择 Hackintosh 了。</p>
<p>其实现在的 Hackintosh 早已不是以前的小众选择。正如知乎上的一位知友所说：</p>
<blockquote>
<p>如果你需要一台高性能的Mac，那么 Hackintosh 可能是现阶段最好的选择。</p></blockquote>
<p>对于从事开发和设计工作的人来说，Mac 流畅的体验和成熟的交互确实让人省心，作为长期使用Mac办公的人来说，这可能就是用了就回不去的一种体验。</p>
<h2 id="配置">配置</h2>
<table>
  <thead>
      <tr>
          <th>名称</th>
          <th>品牌型号</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>CPU</td>
          <td>Intel i7 8700</td>
      </tr>
      <tr>
          <td>主板</td>
          <td>华擎 Z390 Phantom Gaming itx/ac</td>
      </tr>
      <tr>
          <td>散热</td>
          <td>猫头鹰（NOCTUA）NH-L9i</td>
      </tr>
      <tr>
          <td>内存</td>
          <td>金士顿骇客神条 8G x 2</td>
      </tr>
      <tr>
          <td>SSD</td>
          <td>西部数据 SN500 500G</td>
      </tr>
      <tr>
          <td>机箱</td>
          <td>追风者 MG210 ITX 侧透 RGB</td>
      </tr>
      <tr>
          <td>电源</td>
          <td>海盗船 SF600 SFX</td>
      </tr>
      <tr>
          <td>无线/蓝牙</td>
          <td>博通 BCM94360CS2</td>
      </tr>
      <tr>
          <td>显卡</td>
          <td>蓝宝石 RX580 超白金</td>
      </tr>
      <tr>
          <td>显示器</td>
          <td>LG 27UL600 4k HDR400 IPS</td>
      </tr>
  </tbody>
</table>
<h2 id="兼容情况">兼容情况</h2>
<blockquote>
<p>使用完美</p></blockquote>
<pre tabindex="0"><code>- macOS 版本
    - 10.14.4
    - 10.14.5
    - 10.14.6
- 显卡（DisplayPort 接显示器）
    - Intel UHD630 核显
    - AMD RX580
- 声卡(Realtek ALC1220)
    - 主板后置
    - 机箱前置
    - DisplayPort 声音输出
- 睡眠/唤醒
- 有线网卡
- 无线WI-FI
- 蓝牙
    - 耳机
    - Trackpad 2
    - Airdrop
    - Handoff
- 所有 USB 插口
</code></pre><blockquote>
<p>使用不完美</p></blockquote>
<pre tabindex="0"><code>- 雷电 3 接口
</code></pre><p><img class="lozad" data-src="https://i.nuoea.com/img/2019/11/04/7.jpg" alt=""  /></p>]]></content><category scheme="https://nuoea.com/categories/%E6%8A%98%E8%85%BE" term="%E6%8A%98%E8%85%BE" label="折腾"/><category scheme="https://nuoea.com/tags/hackintosh" term="hackintosh" label="Hackintosh"/></entry><entry><title type="html">开启博客视觉系统升级计划</title><link href="https://nuoea.com/start-vision-plan/" rel="alternate" type="text/html"/><id>https://nuoea.com/start-vision-plan/</id><published>2018-10-29T12:16:03+00:00</published><updated>2018-10-29T12:16:03+00:00</updated><content type="html"><![CDATA[<p>搬到 Bitcron 来之后一切都很满意。全新的写作体验，真的可以让人找回一开始写博的那种状态。要说唯一的遗憾，可能就是 Bitcron 提供的主题模版太少了，不过也正如官方文档所说，现在折腾这种静态博客的人，大多数都是有一定动手能力的吧。所以当时就想，有时间就自己写一个吧，也不是什么大问题。恰好上个周末有空，就花了两天的时间，把这个设计落地了。</p>
<h2 id="初心">初心</h2>
<p>第一次尝试制作主题，是在16年的时候，那时使用的程序是Typecho。之后因为各种各样的问题，博客打理得少，更新的就更少了。所以博客的视觉系统就一直停留在那个时候。而这两年，出现了太多好的设计语言。所以在接触到 Bitcron 之后，就想要去尝试更好的视觉效果了。</p>
<p>所以，在熬过了最初的适应期之后，心思就开始活泛起来了。一点点的看官方的文档，同时一点点的开始画网页的原型。可能是因为工作的关系吧。最近因为公司的项目有了解到阿里的 <code>Ant Design</code> 这个项目。越是接触，这个项目就越是深得我心。觉得这套框架的交互做的实在是太棒了。以至于我常常在公司的时候都会想：</p>
<blockquote>
<p>如果这套框架拿来做个人主页，体验应该也很不错吧！</p></blockquote>
<p>当时只是灵光一闪。其实心里也明白这种类似后台 <code>Dashboard</code> 的框架拿来做前端展示，肯定有很多需要修改的结构。在画原型的过程中，也一度陷入僵局，多次打算放弃。所幸，还是坚持完成了。</p>
<h2 id="设计">设计</h2>
<p>我比较享受整个设计的过程。虽然水平有限，但还是乐在其中。虽然有着设计规范的约束，有着市场需求的压力。但是在天马行空的想象中，寻找到的最合适的设计，无不体现着设计师的智慧和关怀。这是我热爱它的原因。</p>
<h2 id="方案一">方案一</h2>
<p><img class="lozad" data-src="https://i.nuoea.com/img/2018/10/29/86761214.jpg" alt=""  /></p>
<hr>
<p><img class="lozad" data-src="https://i.nuoea.com/img/2018/10/29/87559289.jpg" alt=""  /></p>
<blockquote>
<p>设计稿持续更新</p></blockquote>]]></content><category scheme="https://nuoea.com/categories/%E6%8A%98%E8%85%BE" term="%E6%8A%98%E8%85%BE" label="折腾"/><category scheme="https://nuoea.com/tags/vi" term="vi" label="VI"/><category scheme="https://nuoea.com/tags/hugo" term="hugo" label="Hugo"/></entry><entry><title type="html">极路由B70刷老毛子Padavan固件全过程</title><link href="https://nuoea.com/hiwifi-b70-padavan/" rel="alternate" type="text/html"/><id>https://nuoea.com/hiwifi-b70-padavan/</id><published>2018-10-21T00:00:00+00:00</published><updated>2018-10-21T00:00:00+00:00</updated><content type="html"><![CDATA[<p>在折腾酸酸乳的时候，无意中看到的这个固件，说是可以用路由器直接挂载酸酸乳，比较感兴趣，就到恩山论坛注册了账号翻了翻帖子。因为手上在用的主路由是小米的PRO，偶尔会有不稳定，但也不是什么大事。比较不爽的是，总是会弹分享路由得金币乱七八糟的广告，所以寻思如果有固件，刷成第三方也蛮好的。只是比较遗憾的是，并没有找到这个路由器的固件，却看到荒野无灯出了极路由B70的padavan固件。想到正好有个B70在家吃灰。就翻出来折腾了。</p>
<p>整个折腾过程不算太难，搞过VPS的基本都能走下来。只是B70这个机器现在比较麻烦的是解锁的过程，很多的教程都失效了。我也是在不断的尝试中，找到了一个现在还能用的解锁方式。</p>
<h2 id="解锁">解锁</h2>
<p>现在官方最新的固件版本号是：1.4.8.20462s 。 这个版本是不能解锁SSH的。唯一的办法就是降级。现在降级的固件在网上也几乎找不到了。分享一下：</p>
<blockquote>
<p>下载 ：<a href="https://pan.nuoea.com/tools/padavan/b70/B70%E5%AE%98%E6%96%B9%E5%9B%BA%E4%BB%B6/2.142baf.zip">2.142baf</a></p></blockquote>
<p>降级过程：</p>
<ul>
<li>拔掉路由电源。</li>
<li>用网线将极路由 LAN 口与电脑网口相连，刷机路由器无需联网，有无线网卡的建议将电脑的无线禁用。</li>
<li>按住极路由 RESET 不放，然后插上电源。</li>
<li>5秒之后松开 RESET，等待本地连接自动获取IP，网关IP为变为192.168.2.1。</li>
<li>浏览器中输入 192.168.2.1 选择降级固件刷机。</li>
<li>刷机完成，网关变成192.168.199.1。</li>
</ul>
<p>到此降级成功。如果中途有地方卡住了，可以重新再来一次。<code>注意：刷机降级有风险，请谨慎操作！！！</code></p>
<h2 id="获取权限">获取权限</h2>
<p>这里需要用到的工具是 <code>WINSCP</code>。具体过程如下：</p>
<ul>
<li>在极路由官方云插件平台中，下载vsftpd插件， 并设置好。</li>
<li>WinSCP登录FTP, 密码为路由器后台密码。</li>
<li>把破解文件拖入上传。</li>
<li>在极路由官方云插件平台中，安装 定时重播 插件。当前已经下架, 可点击任意一个软件，然后在该软件的浏览器网址中找到sid号码，并把sid号码改成118284854安装。</li>
<li>在自定义规则中填入： *  * * * * sh /tmp/storage/2.sh ，并启动。</li>
<li>回到 WinSCP 软件，  过1分钟左右， 点击刷新按钮。</li>
<li>用putty或者xshell ssh登录。用户名：root ，密码：路由器后台密码，端口：22</li>
</ul>
<p>到此为止整个路由器的准备工作都完成了。剩下的就是刷固件了。</p>
<h2 id="备份固件">备份固件</h2>
<p>一定要记得备份，如果以后想要刷回官方固件，备份文件就特别重要了。关键的时候，还可以用来救砖。</p>
<pre tabindex="0"><code>root@Hiwifi:/tmp# cat /proc/mtd //命令说明：查看原固件分区信息
dev: size erasesize name
mtd0: 00080000 00020000 &#34;u-boot&#34;
mtd1: 00080000 00020000 &#34;debug&#34;
mtd2: 00040000 00020000 &#34;Factory&#34;
mtd3: 02000000 00020000&#34;firmware&#34;
mtd4: 00180000 00020000 &#34;kernel&#34;
mtd5: 01e80000 00020000 &#34;rootfs&#34;
mtd6: 00080000 00020000&#34;hw_panic&#34;
mtd7: 00080000 00020000 &#34;bdinfo&#34;
mtd8: 00080000 00020000 &#34;backup&#34;
mtd9: 01000000 00020000 &#34;overlay&#34;
mtd10: 02000000 00020000&#34;firmware_backup&#34;
mtd11: 00200000 00020000 &#34;oem&#34;
mtd12: 02ac0000 00020000 &#34;opt&#34;
root@Hiwifi:~# dd if=/dev/mtd0 of=/tmp/u-boot.bin //命令说明：备份打包mtd0为u-boot.bin文件到tmp目录下
1024+0 records in
1024+0 records out
root@Hiwifi:~# dd if=/dev/mtd2 of=/tmp/Factory.bin//命令说明：备份打包mtd2为Factory.bin文件到tmp目录下
512+0 records in
512+0 records out
root@Hiwifi:~# dd if=/dev/mtd3 of=/tmp/firmware.bin//命令说明：备份打包mtd3为firmware.bin文件到tmp目录下
65536+0 records in
65536+0 records out
root@Hiwifi:~#
</code></pre><p>其它mtd文件也可以全部备份到tmp目录下。使用winscp工具，scp连接路由器，192.168.199.1。用winscp工具把备份的/tmp/*.bin原厂固件下载到本地电脑备用。</p>
<h2 id="备份mac地址">备份MAC地址</h2>
<p>MAC地址规则及示例：</p>
<pre tabindex="0"><code>WAN MAC：在LAN的基础上最后一位加1，具体以固件内看到的为准。示例：D4:EE:07:32:84:23
LAN MAC：机器背面的MAC地址即LAN地址，也可以进官方固件查看。示例：D4:EE:07:32:84:22
2.4G MAC：同LAN MAC，也可以用WirelessMon软件查看。示例：D4:EE:07:32:84:22
5G MAC：可以用WirelessMon软件查看，与2.4GMAC区别是第二位不同。示例：D0:EE:07:32:84:22
</code></pre><h2 id="刷入-breed">刷入 breed</h2>
<p>breed 就类似于安卓手机上的 Recovery 。刷上了这个，之后路由器在想刷什么固件都不用担心变砖。</p>
<p>过程也是很简单。</p>
<ul>
<li>用 WINSCP 工具将 breed.bin 文件复制到路由tmp目录。</li>
<li>输入命令：root@Hiwifi:～# cd /tmp</li>
<li>输入命令：root@Hiwifi:/tmp# mtd breed.bin u-boot</li>
<li>输入命令：root@Hiwifi:/tmp#mtd erase firmware_backup</li>
<li>reboot</li>
</ul>
<h2 id="刷入-padavan">刷入 padavan</h2>
<p>最后就是刷固件了。</p>
<ul>
<li>路由器抜电源，长按复位键，不要松开。</li>
<li>插上电源，5秒后松开复位键，浏览器输入：192.168.1.1。</li>
<li>上传 padavan 固件，点恢复固件。</li>
</ul>
<h2 id="最后">最后</h2>
<p>刷好之后重启一次，就可以登录路由器了。登录之后别忘了还要双清一次。然后恢复MAC地址。之后就可以享受新固件带来的乐趣了。</p>]]></content><category scheme="https://nuoea.com/categories/%E6%8A%98%E8%85%BE" term="%E6%8A%98%E8%85%BE" label="折腾"/><category scheme="https://nuoea.com/tags/%E6%95%99%E7%A8%8B" term="%E6%95%99%E7%A8%8B" label="教程"/></entry><entry><title type="html">Bitcron 科学使用 Disqus</title><link href="https://nuoea.com/bitcron-use-disqus/" rel="alternate" type="text/html"/><id>https://nuoea.com/bitcron-use-disqus/</id><published>2018-10-17T00:00:00+00:00</published><updated>2018-10-17T00:00:00+00:00</updated><content type="html"><![CDATA[<h2 id="前言">前言</h2>
<p>其实说到评论，老实讲 Bitcron 自带的评论还算好用，简单明了，该有的功能也都有。访问速度也没有问题。只是对于 Bitcron 来讲，所有的评论都是以一个个单独的 csv 文件的形式存在，然后存放在一个叫做 -comment 的文件夹里。从别的地方导入进来吧，很容易。但是想导出去好像我还没有找到办法。</p>
<p>于是，思来想去就想换了。但是现在能用的不多，好用的插件，要么就关闭服务了，要么就被挡住了。直到昨天，逛到朋友的站，讲到了可以科学的使用Disqus，利用 API 可以愉快的在圈内玩耍。立马就被种草了。</p>
<h2 id="过程">过程</h2>
<p>翻了教程，整个项目跑下来其实不难，制作这个项目的大神在 Github 里面其实已经说的很详细了。我就记录一下在 Bitcron 中使用这个项目的关键点。</p>
<ul>
<li>因为 Bitcron 是静态托管服务，所以如果想使用这个项目，你需要一台支持 PHP 的境外主机，国内的不行。</li>
<li>对于主机的PHP版本有要求，不能低于 5.6+</li>
<li>因为 Bitcron 默认是开启 SSL 服务的。所以存放项目文件的链接也要开启 SSL 服务，不然会有跨域的报错问题。</li>
<li>Bitcron 预留了 第三方评论的设置接口。直接在  Dashboard - 呈现 中 粘贴前端代码就可以。</li>
</ul>
<h2 id="最后">最后</h2>
<p>贴上大神的网址：</p>
<blockquote>
<p><a href="https://blog.fooleap.org/">fooleap</a></p></blockquote>
<p>以及项目的 Githu 地址：</p>
<blockquote>
<p><a href="https://github.com/fooleap/disqus-php-api">Disqus-php-api</a></p></blockquote>
<p>有兴趣的小伙伴可以折腾一下。</p>]]></content><category scheme="https://nuoea.com/categories/%E6%8A%98%E8%85%BE" term="%E6%8A%98%E8%85%BE" label="折腾"/><category scheme="https://nuoea.com/tags/%E6%95%99%E7%A8%8B" term="%E6%95%99%E7%A8%8B" label="教程"/></entry><entry><title type="html">福特SYNC3系统升级记录</title><link href="https://nuoea.com/ford-sync-update/" rel="alternate" type="text/html"/><id>https://nuoea.com/ford-sync-update/</id><published>2018-09-30T00:00:00+00:00</published><updated>2018-09-30T00:00:00+00:00</updated><content type="html"><![CDATA[<p>这两年随着互联网的发展，我们能够看到的各块屏幕几乎都被占领了，车载导航的这块屏幕也不例外，各大互联网公司以及传统车企纷纷推出自己的车机系统，加强用户粘性。</p>
<p>当然这里面鱼龙混杂，有做的好的，也有用着扎心的，就不细说了。比较出名的其实说来说去也就两个产品。一个是苹果的<code>CarPlay</code>，还有一个就是谷歌推出的 <code>Andtoid auto</code>。</p>
<p>基于行业良好的口碑和对行业整体的掌控力，苹果在推广<code>CarPlay</code>方面可以说一直是顺风顺水。而跟IOS无缝对接的良好体验也是<code>CarPlay</code>非常迷人的地方。只是痛点一直都是第三方的APP支持的较少，可能也跟苹果早期开放的权限不足有关。好在IOS12之后，常用的APP都可以使用了。高德导航、网易云等等。</p>
<p>而 <code>Andtoid auto</code>的使用体验么，应该是不错的。只是因为大家都懂的原因，现在没法用，所以暂且不说。</p>
<p>除此之外，就是传统车企对自身旗下车型定制的车机系统了。这类产品多数都比较难用。只能说在产品设计之初，其设计初衷可能就背离了用户体验吧。</p>
<h2 id="说说-sync3">说说 SYNC3</h2>
<p>说到福特的这套<code>SYNC3</code>，其实还是觉得很神奇的。这套系统人性化的地方在于，好像是他们承认自己做的系统不好用，所以干脆就把市场上好的都集成到一起，然后统统塞给你一样。反正我是欣然接受了这种略微讨巧的做法。</p>
<p><code>SYNC3</code>集成了苹果的<code>CarPlay</code>和谷歌的<code>Android Auto</code> ，所以不管是处在什么生态圈，都可以拥有比较好的使用体验。最近也是听说，最新的系统支持了百度的<code>CarLife</code>。所以激起了升级的欲望。</p>
<h2 id="升级">升级</h2>
<p>升级过程还是略坑。有很多的细节在官方的升级文档中都没有注明。所以只能自己在无数次升级失败中摸索了。大致过程如下：</p>
<ul>
<li>
<p>福特官网找到相关的页面注册，邮箱收到链接，就可以直接下载。下载挺快，解压直接复制到U盘。</p>
</li>
<li>
<p>不用启动车，插到车里会提示系统正在升级，时间大概25分钟。之后提示第一阶段升级好，下次启动车辆第二段升级。（注意：不要拔下U盘，开门下车锁车，不然提示失败！）</p>
</li>
<li>
<p>再开门上车，启动车辆再次提示在升级中，耗时20分钟，建议跑短途时操作，耐心等待，提示拔掉U盘，下次启动时升级成功。</p>
</li>
</ul>
<p>然后就可以愉快的玩耍了。</p>]]></content><category scheme="https://nuoea.com/categories/%E6%8A%98%E8%85%BE" term="%E6%8A%98%E8%85%BE" label="折腾"/><category scheme="https://nuoea.com/tags/%E6%95%99%E7%A8%8B" term="%E6%95%99%E7%A8%8B" label="教程"/></entry></feed>