<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>码农成长随笔</title>
        <link>https://upupup.top/</link>
        <description>Recent content on 码农成长随笔</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh-cn</language>
        <lastBuildDate>Sun, 05 Apr 2026 20:04:00 +0800</lastBuildDate><atom:link href="https://upupup.top/index.xml" rel="self" type="application/rss+xml" /><item>
            <title>Decap CMS接入Gitee简单方案</title>
            <link>https://upupup.top/posts/2026-04-05-decap-cms%E6%8E%A5%E5%85%A5gitee%E7%AE%80%E5%8D%95%E6%96%B9%E6%A1%88/</link>
            <pubDate>Sun, 05 Apr 2026 20:04:00 +0800</pubDate>
            <guid>https://upupup.top/posts/2026-04-05-decap-cms%E6%8E%A5%E5%85%A5gitee%E7%AE%80%E5%8D%95%E6%96%B9%E6%A1%88/</guid>
            <description>&lt;p&gt;decap cms不支持gitee的api&lt;/p&gt;&#xA;&lt;p&gt;gitee也不支持oauth pkce拓展，在不动代码的情况下是不可能直接使用的。&lt;/p&gt;&#xA;&lt;h2 id=&#34;第一步decap-cms编译&#34;&gt;第一步，decap cms编译&#xA;&lt;/h2&gt;&lt;p&gt;gitee地址 &lt;a class=&#34;link&#34; href=&#34;https://gitee.com/icelee123/decap-cms&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;decap-cms&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;github地址 &lt;a class=&#34;link&#34; href=&#34;https://github.com/icelee123/decap-cms&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;decap-cms&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;该项目实现了gitee的发布文章API, gitee的oauth2流程。&lt;/p&gt;&#xA;&lt;p&gt;代码由ai编写，人工测试，目前已测试登录发布文章相关功能。&lt;/p&gt;&#xA;&lt;p&gt;使用&lt;code&gt;npm run build&lt;/code&gt; 完成编译。&lt;/p&gt;&#xA;&lt;p&gt;在 packages/decap-cms/dist中可以找到编译后的decap-cms.js&lt;/p&gt;&#xA;&lt;h2 id=&#34;第二步decap-cms配置&#34;&gt;第二步，decap cms配置&#xA;&lt;/h2&gt;&lt;p&gt;Decap CMS 配置&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;&#xA;&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  backend:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  name: gitee&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  repo: &amp;lt;USER&amp;gt;/&amp;lt;REPO&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  branch: master&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  base_url: https://&amp;lt;YOUR_PROXY_HOST&amp;gt;/gitee-proxy/&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  api_root: https://gitee.com/api/v5&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  auth_type: pkce&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  app_id: &amp;lt;YOUR_APP_ID&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;index.html引用新生成的decap-cms.js&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;&#xA;&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;!DOCTYPE html&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;html&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;lt;head&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &amp;lt;meta charset=&amp;#34;utf-8&amp;#34; /&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &amp;lt;meta name=&amp;#34;viewport&amp;#34; content=&amp;#34;width=device-width, initial-scale=1.0&amp;#34; /&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &amp;lt;meta name=&amp;#34;robots&amp;#34; content=&amp;#34;noindex&amp;#34; /&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &amp;lt;title&amp;gt;Blog Manage&amp;lt;/title&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;lt;/head&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;lt;body&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &amp;lt;script src=&amp;#34;decap-cms.js&amp;#34;&amp;gt;&amp;lt;/script&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;lt;/body&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;lt;/html&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;h2 id=&#34;第三步oauth2的处理&#34;&gt;第三步，OAuth2的处理&#xA;&lt;/h2&gt;&lt;p&gt;OAuth应用的创建官方已经有详尽文档 &lt;a class=&#34;link&#34; href=&#34;https://gitee.com/api/v5/oauth_doc#/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;gitee oauth 文档&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;权限至少要选择： user_info projects pull_requests&lt;/p&gt;&#xA;&lt;p&gt;目前gitee不支持pkce, 仅支持授权码模式， decap-cms走pkce流程不通。&lt;/p&gt;&#xA;&lt;p&gt;但pkce本质是授权码模式的拓展，oauth前几步包含了授权码模式的所有参数， 只不过换token时需要client secret.&lt;/p&gt;&#xA;&lt;p&gt;因此这里做了一个简单的代理，核心逻辑就是 调用 oauth/token这一步时，将client secret一并送到gitee。&lt;/p&gt;&#xA;&lt;p&gt;相关代码在 tool/main.go 中。&lt;/p&gt;&#xA;&lt;h3 id=&#34;首先修改secretyour_client_secret填写自己的client-secret&#34;&gt;首先修改secret=&amp;ldquo;YOUR_CLIENT_SECRET&amp;rdquo;,填写自己的client secret.&#xA;&lt;/h3&gt;&lt;h3 id=&#34;使用-pathtogobingo-run-toolmaingo-运行代理服务&#34;&gt;使用 &lt;code&gt;/PATH/TO/GOBIN/go run tool/main.go&lt;/code&gt; 运行代理服务&#xA;&lt;/h3&gt;&lt;h3 id=&#34;最后创建一个入口nginx反向代理&#34;&gt;最后，创建一个入口nginx反向代理&#xA;&lt;/h3&gt;&lt;p&gt;decap cms的配置中，base_url 指向该nginx代理服务&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;&#xA;&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7&#xA;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; location /gitee-proxy/ {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    proxy_pass http://127.0.0.1:5000/;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    proxy_set_header Host gitee.com;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    proxy_set_header X-Real-IP $remote_addr;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    proxy_set_header X-Forwarded-Proto $scheme;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;h3 id=&#34;完成这些后即可运行&#34;&gt;完成这些后，即可运行&#xA;&lt;/h3&gt;&lt;p&gt;运行后，点击 login with gitee，即可跳转进gitee登录，登陆后回调到你的decap cms地址即可完成授权。&lt;/p&gt;&#xA;&lt;p&gt;授权后，会进入后台页面，你可以编写文章、上传图片资源等。&lt;/p&gt;&#xA;&lt;p&gt;再次强调，decap cms的config中base_url是你的nginx代理地址, oauth会通过base_url进行。&lt;/p&gt;&#xA;&lt;h2 id=&#34;未尽事宜&#34;&gt;未尽事宜&#xA;&lt;/h2&gt;&lt;p&gt;目前流程中，/gitee-proxy/oauth/token接口 无论何种请求，都会带上client secret, 可能存在安全隐患。&lt;/p&gt;&#xA;&lt;p&gt;任何人都可以通过前端拿到你的client key, 调用/gitee-proxy/oauth/token自动添加了client secret，等于说对任何人来讲，只需要一个授权码就可以拿到你的access token。&lt;/p&gt;&#xA;&lt;p&gt;不过换授权码这一步需要gitee登录，整个流程还有这一层保护。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Use at your own risk&lt;/strong&gt;&lt;/p&gt;&#xA;</description>
        </item><item>
            <title>hugo整合CMS时区设置方案</title>
            <link>https://upupup.top/posts/2026-04-01-sveltia-cms-%E6%97%B6%E5%8C%BA%E8%AE%BE%E7%BD%AE%E6%96%B9%E6%A1%88/</link>
            <pubDate>Wed, 01 Apr 2026 23:25:00 +0800</pubDate>
            <guid>https://upupup.top/posts/2026-04-01-sveltia-cms-%E6%97%B6%E5%8C%BA%E8%AE%BE%E7%BD%AE%E6%96%B9%E6%A1%88/</guid>
            <description>&lt;h2 id=&#34;问题&#34;&gt;问题&#xA;&lt;/h2&gt;&lt;p&gt;在hugo与Decap CMS / Sveltia CMS整合过程中，经常post无法生成的问题。&lt;/p&gt;&#xA;&lt;p&gt;一般情况下，这个是由于时区引起的。&#xA;Decap CMS 中，对于时间格式，有一个picker_utc 参数，表示是否使用UTC时间&lt;/p&gt;&#xA;&lt;p&gt;如果不设定，则使用本地时间，生成的时间内没有时区标识。&lt;/p&gt;&#xA;&lt;p&gt;如果设定为true, 则生成的时间里面带一个Z, 比如2026-04-01T17:44:00Z， 表示此时间为UTC时区&lt;/p&gt;&#xA;&lt;p&gt;理论上这里设计没有什么问题，但是对于hugo来讲，无论带Z与否，经过实测，都会按照UTC解析。这样一来，北京时间2026-04-01 17:44:00 就变成了UTC时间2026-04-01 17:44:00，这在此时是一个未来的时间，默认情况下，无法生成未来的post。&lt;/p&gt;&#xA;&lt;h2 id=&#34;解决方案在decapsveltia-cms中的时间串中增加明确的时区标识举例&#34;&gt;解决方案：在Decap/Sveltia CMS中的时间串中增加明确的时区标识，举例：&#xA;&lt;/h2&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;&#xA;&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1&#xA;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#xA;&lt;td class=&#34;lntd&#34;&gt;&#xA;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; - { label: &amp;#34;日期&amp;#34;, name: &amp;#34;date&amp;#34;, widget: &amp;#34;datetime&amp;#34;, format: &amp;#34;YYYY-MM-DDTHH:mm:ss.SSS+08:00&amp;#34;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#xA;&lt;/div&gt;&#xA;&lt;/div&gt;&lt;p&gt;picker_utc默认false, 取的是本地时间（北京时间），我们通过format强制增加了东八区标识，这样hugo不会再误认为是UTC。经测试，该格式可以由hugo正常识别。&lt;/p&gt;&#xA;&lt;p&gt;手工维护markdown文档也可以使用类似方法。&lt;/p&gt;&#xA;&lt;p&gt;（当然，也可以开启picker_utc，整个blog全部使用UTC，理论上也没有问题，post可以正常发布。就是时间显示成UTC对于我们并不友好，还是推荐使用format）&lt;/p&gt;&#xA;</description>
        </item></channel>
</rss>
