<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>微信 on MoeJueのブログ</title>
    <link>https://ja.moejue.cn/zh-hant/tags/%E5%BE%AE%E4%BF%A1/</link>
    <description>Recent content in 微信 on MoeJueのブログ</description>
    <generator>Hugo</generator>
    <language>zh-hant</language>
    <lastBuildDate>Fri, 17 May 2019 06:59:47 +0000</lastBuildDate>
    <atom:link href="https://ja.moejue.cn/zh-hant/tags/%E5%BE%AE%E4%BF%A1/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>小程序架構</title>
      <link>https://ja.moejue.cn/zh-hant/posts/92/</link>
      <pubDate>Fri, 17 May 2019 06:59:47 +0000</pubDate>
      <guid>https://ja.moejue.cn/zh-hant/posts/92/</guid>
      <description>&lt;p&gt;不知道大家們寫小程序是怎麼個寫法的，前幾個月在寫微信小程序，自己整理的一種架構，或者叫框架&#xA;微信原生的架構是這樣子&lt;/p&gt;&#xA;&lt;p&gt;├── app.js&#xA;├── app.json&#xA;├── app.wxss&#xA;├── pages&#xA;│   │── index&#xA;│   │   ├── index.wxml&#xA;│   │   ├── index.js&#xA;│   │   ├── index.json&#xA;│   │   └── index.wxss&#xA;│   └── logs&#xA;│       ├── logs.wxml&#xA;│       └── logs.js&#xA;└── utils&lt;/p&gt;&#xA;&lt;p&gt;為什麼不用微信原生的寫法呢？&#xA;小程序就類似手機APP，都會有一個tabBar欄對吧，微信官方的tabBar欄是在app.json中進行的全局配置。做一般的開發是沒有任何問題的，但涉及到一個複雜的tabBar欄時，使用官方原生的就無法實現，也無法動態載入，比如某影片app中間的拍照錄影功能&#xA;這意味著，我們不能使用官方給我們提供的tabBar欄，需要我們自己寫&#xA;最開始我的做法還是保持原生的結構，只是自己寫tabBar欄，所以頁面程式碼都寫在一個文件中，預設顯示第一屏，其他的都隱藏起來，切換頁面的時候再把相應的頁面顯示，其他的隱藏起來，並且動態渲染資料上去。但是有個問題是，如果是小專案倒沒什麼大問題，但是如果是大專案程式碼量非常龐大，都寫在一個文件中，後期難以維護，所以這個方法最後被pass掉&lt;/p&gt;&#xA;&lt;p&gt;再後來將切換頁面的方式改為跳轉（wx.switchTab等），把不同頁面的程式碼放到了不同的文件，但是還有一個問題，切換也會閃爍，每次切換頁面就等於重新打開一個網頁一樣，tabBar都被重新渲染，所以會閃爍。pass&lt;/p&gt;&#xA;&lt;p&gt;由此就有了現在的全新架構方式：&#xA;將/pages/index/下的文件全部定義為入口文件，js入口，css入口，視圖入口，不同頁面的文件還是放到不同的位置去，為了好管理，新建了一個template的資料夾，用於放不同頁面間的程式碼，結構和官方的單頁面結構是一樣的&#xA;根目錄下的app.js用於存放全域函數，其他頁面呼叫只需getApp()即可&#xA;js的入口文件&lt;/p&gt;&#xA;&lt;div&#xA;  class=&#34;code-block-container border-border bg-card my-6 overflow-hidden rounded-xl border shadow-sm transition-all duration-200 ease-out hover:-translate-y-0.5 hover:shadow-md&#34;&gt;&#xA;  &#xA;  &lt;div&#xA;    class=&#34;code-block-header bg-muted/30 border-border flex items-center justify-between border-b px-4 py-3&#34;&gt;&#xA;    &#xA;    &lt;div class=&#34;flex items-center gap-2&#34;&gt;&#xA;      &lt;div class=&#34;text-muted-foreground flex-shrink-0&#34;&gt;&#xA;        &#xA;  &lt;svg class=&#34;h-4 w-4&#34;&#xA;    fill=&#34;none&#34;&#xA;    stroke=&#34;currentColor&#34;&#xA;    viewBox=&#34;0 0 24 24&#34;&gt;&lt;path stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; stroke-width=&#34;2&#34; d=&#34;M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4&#34; /&gt;&#xA;&lt;/svg&gt;&#xA;      &lt;/div&gt;&#xA;      &lt;span class=&#34;text-muted-foreground text-sm font-medium&#34;&gt;&#xA;        JAVASCRIPT&#xA;      &lt;/span&gt;&#xA;    &lt;/div&gt;&#xA;&#xA;    &#xA;    &lt;div class=&#34;flex items-center gap-2&#34;&gt;&#xA;      &lt;button&#xA;          class=&#34;collapse-code-btn text-muted-foreground hover:text-primary hover:bg-primary/10 focus:ring-primary/20 flex items-center gap-1.5 rounded-md px-2 py-1 text-xs font-medium transition-all duration-200 ease-out focus:ring-2 focus:outline-none&#34;&#xA;          data-code-id=&#34;code-0&#34;&#xA;          data-default-state=&#34;expanded&#34;&#xA;          data-collapsed=&#34;false&#34;&#xA;          data-auto-collapse-lines=&#34;30&#34;&#xA;          data-auto-collapse-height=&#34;400&#34;&#xA;          data-collapsed-height=&#34;120&#34;&#xA;          title=&#34;折りたたむ&#34;&#xA;          aria-label=&#34;折りたたむ&#34;&gt;&#xA;          &lt;span class=&#34;collapse-icon&#34;&gt;&#xA;            &#xA;  &lt;svg class=&#34;h-3 w-3&#34;&#xA;    fill=&#34;none&#34;&#xA;    stroke=&#34;currentColor&#34;&#xA;    viewBox=&#34;0 0 24 24&#34;&gt;&lt;path fill=&#34;currentColor&#34; d=&#34;M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6l-6 6z&#34;/&gt;&lt;/svg&gt;&#xA;          &lt;/span&gt;&#xA;          &lt;span class=&#34;collapse-text hidden sm:inline&#34;&#xA;            &gt;折りたたむ&lt;/span&#xA;          &gt;&#xA;        &lt;/button&gt;&#xA;      &lt;button&#xA;        class=&#34;copy-code-btn text-muted-foreground hover:text-primary hover:bg-primary/10 focus:ring-primary/20 flex items-center gap-1.5 rounded-md px-2 py-1 text-xs font-medium transition-all duration-200 ease-out focus:ring-2 focus:outline-none&#34;&#xA;        data-code-id=&#34;code-0&#34;&#xA;        title=&#34;コピー&#34;&#xA;        aria-label=&#34;コピー&#34;&gt;&#xA;        &lt;span class=&#34;copy-icon&#34;&gt;&#xA;          &#xA;  &lt;svg class=&#34;h-3 w-3&#34;&#xA;    fill=&#34;none&#34;&#xA;    stroke=&#34;currentColor&#34;&#xA;    viewBox=&#34;0 0 24 24&#34;&gt;&lt;path stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; stroke-width=&#34;2&#34; d=&#34;M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z&#34; /&gt;&#xA;&lt;/svg&gt;&#xA;        &lt;/span&gt;&#xA;        &lt;span class=&#34;copy-text hidden sm:inline&#34;&#xA;          &gt;コピー&lt;/span&#xA;        &gt;&#xA;      &lt;/button&gt;&#xA;    &lt;/div&gt;&#xA;  &lt;/div&gt;&#xA;&#xA;  &#xA;  &lt;div class=&#34;code-block-content relative&#34; id=&#34;code-0&#34;&gt;&#xA;    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;app&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;getApp&lt;/span&gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;index&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;\&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;_js&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;require&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;../../template/index/index.js&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;types&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;\&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;_js&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;require&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;../../template/types/types.js&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Global&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;\&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;_Data&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;\&lt;/span&gt;[&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;\&lt;/span&gt;];&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Page&lt;/span&gt;({&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;data&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;active&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;show&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6e22e&#34;&gt;index&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6e22e&#34;&gt;types&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6e22e&#34;&gt;course&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6e22e&#34;&gt;user&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;onLoad&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;options&lt;/span&gt;) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;setData&lt;/span&gt;({&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6e22e&#34;&gt;Global&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;\&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;_Data&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;index&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;\&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;_js&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;getData&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        })&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 底部nav切换&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;tabbar&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;\&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;_onChange&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;event&lt;/span&gt;) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;key&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;data&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;show&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6e22e&#34;&gt;index&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6e22e&#34;&gt;types&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6e22e&#34;&gt;course&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6e22e&#34;&gt;user&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        };&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;console&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;log&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;event&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;switch&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;event&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;detail&lt;/span&gt;) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6e22e&#34;&gt;key&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;index&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6e22e&#34;&gt;Global&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;\&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;_Data&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;index&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;\&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;_js&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;getData&lt;/span&gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#66d9ef&#34;&gt;break&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6e22e&#34;&gt;key&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;types&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6e22e&#34;&gt;Global&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;\&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;_Data&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;types&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;\&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;_js&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;getData&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#66d9ef&#34;&gt;break&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6e22e&#34;&gt;key&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;course&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6e22e&#34;&gt;Global&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;\&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;_Data&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;index&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;\&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;_js&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;getData&lt;/span&gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#66d9ef&#34;&gt;break&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6e22e&#34;&gt;key&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;user&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6e22e&#34;&gt;Global&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;\&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;_Data&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;index&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;\&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;_js&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;getData&lt;/span&gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#66d9ef&#34;&gt;break&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;data&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;show&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;\&lt;/span&gt;[&lt;span style=&#34;color:#a6e22e&#34;&gt;key&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;\&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;console&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;log&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;Global&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;\&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;_Data&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;setData&lt;/span&gt;({&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6e22e&#34;&gt;show&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;data&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;show&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6e22e&#34;&gt;Global&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;\&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;_Data&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Global&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;\&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;_Data&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        })&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#xA;    &#xA;    &lt;div&#xA;      class=&#34;collapse-overlay to-card/90 pointer-events-none absolute inset-0 bg-gradient-to-b from-transparent via-transparent opacity-0 transition-opacity duration-300&#34;&gt;&#xA;      &lt;div&#xA;        class=&#34;text-muted-foreground bg-card/80 border-border/50 hover:bg-primary/10 hover:text-primary hover:border-primary/30 absolute bottom-4 left-1/2 -translate-x-1/2 cursor-pointer rounded-full border px-3 py-1.5 text-xs backdrop-blur-sm transition-all duration-200&#34;&gt;&#xA;        クリックして展開し、詳細を表示&#xA;      &lt;/div&gt;&#xA;    &lt;/div&gt;&#xA;  &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;script&gt;&#xA;(function() {&#xA;  const codeId = &#39;code-0&#39;;&#xA;  const copyBtn = document.querySelector(&#39;.copy-code-btn[data-code-id=&#34;&#39; + codeId + &#39;&#34;]&#39;);&#xA;  const collapseBtn = document.querySelector(&#39;.collapse-code-btn[data-code-id=&#34;&#39; + codeId + &#39;&#34;]&#39;);&#xA;  const codeContainer = document.getElementById(codeId);&#xA;&#xA;  if (!codeContainer) return;&#xA;&#xA;  &#xA;  if (copyBtn) {&#xA;    const copyIcon = copyBtn.querySelector(&#39;.copy-icon&#39;);&#xA;    const copyText = copyBtn.querySelector(&#39;.copy-text&#39;);&#xA;&#xA;    copyBtn.addEventListener(&#39;click&#39;, async function() {&#xA;      try {&#xA;        &#xA;        let codeText = &#39;&#39;;&#xA;&#xA;        &#xA;        const codeTableCell = codeContainer.querySelector(&#39;.lntd:last-child code&#39;);&#xA;        if (codeTableCell) {&#xA;          codeText = codeTableCell.textContent || codeTableCell.innerText;&#xA;        } else {&#xA;          &#xA;          const codeElement = codeContainer.querySelector(&#39;code&#39;);&#xA;          if (codeElement) {&#xA;            &#xA;            const hasInlineLineNumbers = codeElement.querySelector(&#39;.ln&#39;);&#xA;            if (hasInlineLineNumbers) {&#xA;              &#xA;              const codeLines = codeElement.querySelectorAll(&#39;.cl&#39;);&#xA;              if (codeLines.length &gt; 0) {&#xA;                codeText = Array.from(codeLines)&#xA;                  .map(line =&gt; {&#xA;                    const text = line.textContent || line.innerText;&#xA;                    &#xA;                    return text.replace(/\n+$/, &#39;&#39;);&#xA;                  })&#xA;                  .join(&#39;\n&#39;)&#xA;                  .replace(/\n+$/, &#39;&#39;); &#xA;              } else {&#xA;                &#xA;                const allText = codeElement.textContent || codeElement.innerText;&#xA;                codeText = allText.replace(/^\d+/gm, &#39;&#39;).replace(/^\s+/gm, &#39;&#39;);&#xA;              }&#xA;            } else {&#xA;              &#xA;              codeText = codeElement.textContent || codeElement.innerText;&#xA;            }&#xA;          } else {&#xA;            &#xA;            codeText = codeContainer.textContent || codeContainer.innerText;&#xA;          }&#xA;        }&#xA;&#xA;        &#xA;        codeText = codeText.trim();&#xA;&#xA;        &#xA;        await navigator.clipboard.writeText(codeText);&#xA;&#xA;        &#xA;        copyIcon.innerHTML = `\n  \u003csvg class=\u0022h-3 w-3\u0022\n    fill=\u0022none\u0022\n    stroke=\u0022currentColor\u0022\n    viewBox=\u00220 0 24 24\u0022\u003e\u003cpath stroke-linecap=\u0022round\u0022 stroke-linejoin=\u0022round\u0022 stroke-width=\u00222\u0022 d=\u0022M5 13l4 4L19 7\u0022 \/\u003e\n\u003c\/svg\u003e`;&#xA;        if (copyText) {&#xA;          copyText.textContent = &#39;コピーしました&#39;;&#xA;        }&#xA;        copyBtn.classList.add(&#39;text-green-600&#39;);&#xA;&#xA;        &#xA;        setTimeout(() =&gt; {&#xA;          copyIcon.innerHTML = `\n  \u003csvg class=\u0022h-3 w-3\u0022\n    fill=\u0022none\u0022\n    stroke=\u0022currentColor\u0022\n    viewBox=\u00220 0 24 24\u0022\u003e\u003cpath stroke-linecap=\u0022round\u0022 stroke-linejoin=\u0022round\u0022 stroke-width=\u00222\u0022 d=\u0022M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z\u0022 \/\u003e\n\u003c\/svg\u003e`;&#xA;          if (copyText) {&#xA;            copyText.textContent = &#39;コピー&#39;;&#xA;          }&#xA;          copyBtn.classList.remove(&#39;text-green-600&#39;);&#xA;        }, 2000);&#xA;&#xA;      } catch (err) {&#xA;        console.error(&#39;复制失败:&#39;, err);&#xA;&#xA;        &#xA;        const range = document.createRange();&#xA;        const codeElement = codeContainer.querySelector(&#39;code&#39;) || codeContainer;&#xA;        range.selectNodeContents(codeElement);&#xA;        const selection = window.getSelection();&#xA;        selection.removeAllRanges();&#xA;        selection.addRange(range);&#xA;&#xA;        &#xA;        if (copyText) {&#xA;          copyText.textContent = &#39;選択済み&#39;;&#xA;        }&#xA;&#xA;        setTimeout(() =&gt; {&#xA;          if (copyText) {&#xA;            copyText.textContent = &#39;コピー&#39;;&#xA;          }&#xA;          selection.removeAllRanges();&#xA;        }, 2000);&#xA;      }&#xA;    });&#xA;  }&#xA;&#xA;  &#xA;  if (collapseBtn) {&#xA;    const collapseIcon = collapseBtn.querySelector(&#39;.collapse-icon&#39;);&#xA;    const collapseText = collapseBtn.querySelector(&#39;.collapse-text&#39;);&#xA;    const collapseOverlay = codeContainer.querySelector(&#39;.collapse-overlay&#39;);&#xA;&#xA;    &#xA;    let codeElement = codeContainer.querySelector(&#39;pre.chroma&#39;);&#xA;    if (!codeElement) {&#xA;      codeElement = codeContainer.querySelector(&#39;pre&#39;);&#xA;    }&#xA;&#xA;    const defaultState = collapseBtn.dataset.defaultState || &#39;expanded&#39;;&#xA;    const isCollapsedAttr = collapseBtn.dataset.collapsed === &#39;true&#39;;&#xA;    const autoCollapseLines = parseInt(collapseBtn.dataset.autoCollapseLines) || 30;&#xA;    const autoCollapseHeight = parseInt(collapseBtn.dataset.autoCollapseHeight) || 400;&#xA;    const collapsedHeight = parseInt(collapseBtn.dataset.collapsedHeight) || 120;&#xA;&#xA;    let isCollapsed = false;&#xA;&#xA;    &#xA;    function initCollapse() {&#xA;      &#xA;      const shouldCollapse = isCollapsedAttr ||&#xA;                           defaultState === &#39;collapsed&#39; ||&#xA;                           shouldAutoCollapse();&#xA;&#xA;      if (shouldCollapse) {&#xA;        setCollapsed(true, false); &#xA;      }&#xA;    }&#xA;&#xA;    function shouldAutoCollapse() {&#xA;      &#xA;      if (codeElement) {&#xA;        const lines = codeElement.querySelectorAll(&#39;.line, .cl&#39;);&#xA;        const height = codeElement.offsetHeight;&#xA;        return lines.length &gt; autoCollapseLines || height &gt; autoCollapseHeight;&#xA;      }&#xA;&#xA;      &#xA;      const containerHeight = codeContainer.offsetHeight;&#xA;      if (containerHeight &gt; autoCollapseHeight) {&#xA;        return true;&#xA;      }&#xA;&#xA;      &#xA;      const textContent = codeContainer.textContent || codeContainer.innerText || &#39;&#39;;&#xA;      const estimatedLines = textContent.split(&#39;\n&#39;).length;&#xA;      return estimatedLines &gt; autoCollapseLines;&#xA;    }&#xA;&#xA;    function setCollapsed(collapsed, animate = true) {&#xA;      if (!collapseOverlay) return;&#xA;&#xA;      isCollapsed = collapsed;&#xA;&#xA;      if (collapsed) {&#xA;        &#xA;        codeContainer.style.maxHeight = collapsedHeight + &#39;px&#39;;&#xA;        codeContainer.style.overflow = &#39;hidden&#39;;&#xA;        collapseOverlay.style.opacity = &#39;1&#39;;&#xA;        collapseOverlay.style.pointerEvents = &#39;auto&#39;;&#xA;&#xA;        &#xA;        collapseIcon.innerHTML = `\n  \u003csvg class=\u0022h-3 w-3\u0022\n    fill=\u0022none\u0022\n    stroke=\u0022currentColor\u0022\n    viewBox=\u00220 0 24 24\u0022\u003e\u003cpath stroke-linecap=\u0022round\u0022 stroke-linejoin=\u0022round\u0022 stroke-width=\u00222\u0022 d=\u0022M19 9l-7 7-7-7\u0022 \/\u003e\n\u003c\/svg\u003e`;&#xA;        if (collapseText) {&#xA;          collapseText.textContent = &#39;展開&#39;;&#xA;        }&#xA;        collapseBtn.title = &#39;展開&#39;;&#xA;&#xA;      } else {&#xA;        &#xA;        codeContainer.style.maxHeight = &#39;&#39;;&#xA;        codeContainer.style.overflow = &#39;&#39;;&#xA;        collapseOverlay.style.opacity = &#39;0&#39;;&#xA;        collapseOverlay.style.pointerEvents = &#39;none&#39;;&#xA;&#xA;        &#xA;        collapseIcon.innerHTML = `\n  \u003csvg class=\u0022h-3 w-3\u0022\n    fill=\u0022none\u0022\n    stroke=\u0022currentColor\u0022\n    viewBox=\u00220 0 24 24\u0022\u003e\u003cpath fill=\u0022currentColor\u0022 d=\u0022M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6l-6 6z\u0022\/\u003e\u003c\/svg\u003e`;&#xA;        if (collapseText) {&#xA;          collapseText.textContent = &#39;折りたたむ&#39;;&#xA;        }&#xA;        collapseBtn.title = &#39;折りたたむ&#39;;&#xA;      }&#xA;&#xA;      &#xA;      if (animate) {&#xA;        codeContainer.style.transition = &#39;max-height 0.3s ease-out&#39;;&#xA;        setTimeout(() =&gt; {&#xA;          codeContainer.style.transition = &#39;&#39;;&#xA;        }, 300);&#xA;      }&#xA;    }&#xA;&#xA;    function toggleCollapse() {&#xA;      setCollapsed(!isCollapsed, true);&#xA;    }&#xA;&#xA;    &#xA;    collapseBtn.addEventListener(&#39;click&#39;, toggleCollapse);&#xA;&#xA;    &#xA;    if (collapseOverlay) {&#xA;      collapseOverlay.addEventListener(&#39;click&#39;, () =&gt; {&#xA;        if (isCollapsed) {&#xA;          setCollapsed(false, true);&#xA;        }&#xA;      });&#xA;    }&#xA;&#xA;    &#xA;    initCollapse();&#xA;  }&#xA;})();&#xA;&lt;/script&gt;&#xA;&lt;p&gt;wxml入口文件&lt;/p&gt;</description>
    </item>
    <item>
      <title>微信授權登入</title>
      <link>https://ja.moejue.cn/zh-hant/posts/88/</link>
      <pubDate>Fri, 05 Apr 2019 09:29:45 +0000</pubDate>
      <guid>https://ja.moejue.cn/zh-hant/posts/88/</guid>
      <description>&lt;p&gt;&#xA;&lt;figure class=&#34;image-figure not-prose my-8&#34; &#xA;        data-lightbox-enabled=&#34;false&#34;&#xA;        data-gallery-type=&#34;auto&#34;&gt;&#xA;  &lt;div class=&#34;image-container&#34;&gt;&#xA;    &lt;img&#xA;    src=&#34;https://res.wx.qq.com/mpres/htmledition/weui-desktopSkin/svg/buildless/bg_logo_primary4247a9.svg&#34;&#xA;    alt=&#34;&#34;&#xA;    &#xA;    &#xA;    loading=&#34;lazy&#34;&#xA;    decoding=&#34;async&#34;&#xA;    data-gallery-src=&#34;https://res.wx.qq.com/mpres/htmledition/weui-desktopSkin/svg/buildless/bg_logo_primary4247a9.svg&#34;&#xA;    data-gallery-alt=&#34;&#34;&#xA;    data-gallery-title=&#34;&#34; /&gt;&lt;/div&gt;&#xA;&#xA;  &lt;/figure&gt; 文件：&lt;a href=&#34;https://mp.weixin.qq.com/wiki?t=resource/res_main&amp;amp;id=mp1421135319&#34;target=&#34;_blank&#34;&#xA;  class=&#34;inline-flex items-center gap-1&#34;&#xA;&gt;https://mp.weixin.qq.com/wiki?t=resource/res_main&amp;amp;id=mp1421135319&#xA;  &lt;svg id=&#34;external-link&#34; class=&#34;h-3 w-3 flex-shrink-0&#34;&#xA;    fill=&#34;none&#34;&#xA;    stroke=&#34;currentColor&#34;&#xA;    viewBox=&#34;0 0 24 24&#34;&gt;&lt;path fill=&#34;none&#34; stroke=&#34;currentColor&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; stroke-width=&#34;2&#34; d=&#34;M15 3h6v6m-11 5L21 3m-3 10v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6&#34;/&gt;&lt;/svg&gt;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;微信的授權登入與QQ、新浪等平台的授權登入大同小異，均採用OauthOAuth2.0鑑權方式。&lt;br&gt;&#xA;微信授權分為兩種：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;靜默授權&lt;/li&gt;&#xA;&lt;li&gt;彈窗授權，需要用戶手動同意&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;兩種scope的區別說明&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;以snsapi_base為scope發起的網頁授權，是用來獲取進入頁面的用戶openid的，並且是靜默授權並自動跳轉到回調頁的。用戶感知的就是直接進入了回調頁（往往是業務頁面）&lt;/li&gt;&#xA;&lt;li&gt;以snsapi_userinfo為scope發起的網頁授權，是用來獲取用戶的基本資訊的。但這種授權需要用戶手動同意，並且由於用戶同意過，所以無須關注，就可在授權後獲取該用戶的基本資訊。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;用戶管理類介面中的「獲取用戶基本資訊介面」，是在用戶和公眾號產生訊息交互或關注後事件推送後，才能根據用戶OpenID來獲取用戶基本資訊。這個介面，包括其他微信介面，都是需要該用戶（即openid）關注了公眾號後，才能呼叫成功的。&lt;/p&gt;&#xA;&lt;p&gt;具體而言，網頁授權流程分為四步：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;引導用戶進入授權頁面同意授權，獲取code&lt;/li&gt;&#xA;&lt;li&gt;透過code換取網頁授權access_token（與基礎支援中的access_token不同）&lt;/li&gt;&#xA;&lt;li&gt;如果需要，開發者可以重新整理網頁授權access_token，避免過期&lt;/li&gt;&#xA;&lt;li&gt;透過網頁授權access_token和openid獲取用戶基本資訊（支援UnionID機制）&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;以下是封裝的微信操作類，需要用到兩個資料表，用於保存access_token、ticket，由於它們具有一定有效期，且每天請求數有上限，所以開發者需自行保存&lt;/p&gt;&#xA;&lt;?php&#xA;/\*\*&#xA;\*   微信操作表&#xA;\*   wxtoken 表結構&#xA;\*   id&#xA;\*   access\_token&#xA;\*   addtime&#xA;\*   wxticket 表結構&#xA;\*   id&#xA;\*   ticket&#xA;\*   addtime&#xA;\*/&#xA;class WX {&#xA;&#x9;private $appid;&#xA;&#x9;private $appserect;&#xA;&#x9;private $curl;&#xA;&#x9;private $msg;&#xA;&#x9;protected $errs = array(&#xA;&#x9;&#x9;&#39;-1&#39; =&gt; &#39;系統繁忙，此時請開發者稍候再試&#39;,&#xA;&#x9;&#x9;&#39;0&#39; =&gt; &#39;請求成功&#39;,&#xA;&#x9;&#x9;&#39;40001&#39; =&gt; &#39;AppSecret錯誤或者AppSecret不屬於這個公眾號，請開發者確認AppSecret的正確性&#39;,&#xA;&#x9;&#x9;&#39;40002&#39; =&gt; &#39;請確保grant\_type字段值為client\_credential&#39;,&#xA;&#x9;&#x9;&#39;40164&#39; =&gt; &#39;呼叫介面的IP地址不在白名單中，請在介面IP白名單中進行設定。&#39;,&#xA;&#x9;);&#xA;&#x9;function \_\_construct($appid, $appserect) {&#xA;&#x9;&#x9;$this-&gt;appid = $appid;&#xA;&#x9;&#x9;$this-&gt;appserect = $appserect;&#xA;&#x9;&#x9;$this-&gt;curl = new Curl();&#xA;&#x9;}&#xA;&#x9;/\*&#xA;&#x9;微信網頁授權登入  需要在公眾號設定 - 功能設定 - 網頁授權域名&#xA;&#x9;第一步：用戶同意授權，獲取code&#xA;&#x9;scope : snsapi\_base 只能獲取openid 直接跳轉&#xA;&#x9;snsapi\_userinfo&#xA;&#x9;\*/&#xA;&#x9;public function getCode($redirect\_uri, $scope = &#39;snsapi\_userinfo&#39;,$state = &#39;1&#39;) {&#xA;&#x9;&#x9;$url = &#34;https://open.weixin.qq.com/connect/oauth2/authorize?appid={$this-&gt;appid}&amp;redirect\_uri={$redirect\_uri}&amp;response\_type=code&amp;scope={$scope}&amp;state={$state}#wechat\_redirect&#34;;&#xA;&#x9;&#x9;header(&#34;Location:{$url}&#34;);&#xA;&#x9;&#x9;exit;&#xA;&#x9;}&#xA;&#x9;/\*&#xA;&#x9;第二步：透過code換取網頁授權access\_token&#xA;&#x9;\*/&#xA;&#x9;public function getAccessTokenByCode($code) {&#xA;&#x9;&#x9;$url = &#34;https://api.weixin.qq.com/sns/oauth2/access\_token?appid={$this-&gt;appid}&amp;secret={$this-&gt;appserect}&amp;code={$code}&amp;grant\_type=authorization\_code&#34;;&#xA;&#x9;&#x9;// exit($url);&#xA;&#x9;&#x9;// $curl = new Curl();&#xA;&#x9;&#x9;$result = $this-&gt;curl-&gt;doGet($url);&#xA;&#x9;&#x9;if (!$result) {&#xA;&#x9;&#x9;&#x9;// $this-&gt;curl-&gt;getError()&#xA;&#x9;&#x9;&#x9;$this-&gt;msg = &#34;獲取token失敗&#34;;&#xA;&#x9;&#x9;&#x9;return false;&#xA;&#x9;&#x9;}&#xA;&#x9;&#x9;$result = json\_decode($result, true);&#xA;&#x9;&#x9;if ($result\[&#39;errcode&#39;\]) {&#xA;&#x9;&#x9;&#x9;$this-&gt;msg = $result\[&#39;errmsg&#39;\];&#xA;&#x9;&#x9;&#x9;return false;&#xA;&#x9;&#x9;}&#xA;&#x9;&#x9;return $result;&#xA;&#x9;}&#xA;&#x9;// 第三步：重新整理access\_token（如果需要） 透過code 獲取openid $type 0靜默授權 1彈窗授權&#xA;&#x9;public function getUserInfo($code, $type = 0, $lang = &#39;zh\_CN &#39;) {&#xA;&#x9;&#x9;$result = $this-&gt;getAccessTokenByCode($code);&#xA;&#x9;&#x9;&#x9;if (!$result) {&#xA;&#x9;&#x9;&#x9;return false;&#xA;&#x9;&#x9;}&#xA;&#x9;&#x9;$member = C::t(PT\_USER)-&gt;getByOpenid($result\[&#39;openid&#39;\]);&#xA;&#x9;if ($member) {&#xA;&#x9;&#x9;return $member;&#xA;&#x9;} else {&#xA;&#x9;&#x9;if ($type) {&#xA;&#x9;&#x9;&#x9;$url = &#34;https://api.weixin.qq.com/sns/userinfo?access\_token={$result\[&#39;access\_token&#39;\]}&amp;openid={$result\[&#39;openid&#39;\]}&amp;lang={$lang}&#34;;&#xA;&#x9;&#x9;&#x9;// $return = $this-&gt;curl-&gt;doGet($url);&#xA;&#x9;&#x9;&#x9;// 這介面有病 強制顯示文件頭&#xA;&#x9;&#x9;&#x9;$return = file\_get\_contents($url);&#xA;&#x9;&#x9;&#x9;if (!$return) {&#xA;&#x9;&#x9;&#x9;&#x9;$this-&gt;msg = &#39;獲取用戶資訊失敗&#39;;&#xA;&#x9;&#x9;&#x9;&#x9;return false;&#xA;&#x9;&#x9;&#x9;}&#xA;&#x9;&#x9;&#x9;$return = json\_decode($return, true);&#xA;&#x9;&#x9;&#x9;if (!$return) {&#xA;&#x9;&#x9;&#x9;&#x9;$this-&gt;msg = &#39;獲取用戶資訊返回失敗&#39;;&#xA;&#x9;&#x9;&#x9;&#x9;return false;&#xA;&#x9;&#x9;&#x9;}&#xA;&#x9;&#x9;&#x9;// file\_put\_contents(&#39;ccc.txt&#39;,print\_r($return,true),FILE\_APPEND);&#xA;&#x9;&#x9;&#x9;$data = array(&#xA;&#x9;&#x9;&#x9;&#x9;&#39;openid&#39; =&gt; $return\[&#39;openid&#39;\],&#xA;&#x9;&#x9;&#x9;&#x9;&#39;name&#39; =&gt; $return\[&#39;nickname&#39;\],&#xA;&#x9;&#x9;&#x9;&#x9;&#39;sex&#39; =&gt; $return\[&#39;sex&#39;\],&#xA;&#x9;&#x9;&#x9;&#x9;&#39;province&#39; =&gt; $return\[&#39;province&#39;\],&#xA;&#x9;&#x9;&#x9;&#x9;&#39;city&#39; =&gt; $return\[&#39;city&#39;\],&#xA;&#x9;&#x9;&#x9;&#x9;&#39;country&#39; =&gt; $return\[&#39;country&#39;\],&#xA;&#x9;&#x9;&#x9;&#x9;&#39;img&#39; =&gt; $return\[&#39;headimgurl&#39;\],&#xA;&#x9;&#x9;&#x9;&#x9;&#39;bindtel&#39; =&gt; 0,&#xA;&#x9;&#x9;&#x9;);&#xA;&#x9;&#x9;} else {&#xA;&#x9;&#x9;&#x9;$data = array(&#xA;&#x9;&#x9;&#x9;&#x9;&#39;openid&#39; =&gt; $result\[&#39;openid&#39;\],&#xA;&#x9;&#x9;&#x9;&#x9;&#39;username&#39; =&gt; &#34;微信用戶\_&#34; . random(6,1)&#xA;&#x9;&#x9;&#x9;);&#xA;&#x9;&#x9;}&#xA;&#x9;&#x9;$name = rand(100000, 1000000000);&#xA;&#x9;&#x9;$e = $name . &#34;@qq.com&#34;;&#xA;&#x9;&#x9;$password = $e;&#xA;&#x9;&#x9;$id = UserAddEdit(0, $data\[&#39;username&#39;\], $password, $e,10,0,&#34;&#34;, $msg);&#xA;&#x9;&#x9;if ($id &lt;= 0) {&#xA;&#x9;&#x9;&#x9;$this-&gt;msg = $msg;&#xA;&#x9;&#x9;&#x9;return false;&#xA;&#x9;&#x9;}&#xA;&#x9;&#x9;C::t(PT\_USER)-&gt;update($data, $id);&#xA;&#x9;&#x9;$member = C::t(PT\_USER)-&gt;get($id);&#xA;&#x9;&#x9;return $member;&#xA;&#x9;&#x9;}&#xA;&#x9;}&#xA;&#x9;/\*&#xA;&#x9;公眾號 安全中心 設定IP白名單&#xA;&#x9;公眾號的全局唯一介面呼叫憑據，公眾號呼叫各介面時都需使用access\_token。開發者需要進行妥善保存。access\_token的儲存至少要保留512個字符空間。access\_token的有效期目前為2個小時，需定時重新整理，重複獲取將導致上次獲取的access\_token失效。&#xA;&#x9;\*/&#xA;&#x9;public function getAccessToken($type) {&#xA;&#x9;&#x9;$addtime = TIMESTAMP - 7200;&#xA;&#x9;&#x9;$url = &#34;https://api.weixin.qq.com/cgi-bin/token?grant\_type=client\_credential&amp;appid={$this-&gt;appid}&amp;secret={$this-&gt;appserect}&#34;;&#xA;&#x9;&#x9;$row = C::t(PT\_WXTOKEN)-&gt;getNew($addtime, $type);&#xA;&#x9;&#x9;if ($row) {&#xA;&#x9;&#x9;&#x9;return $row\[&#39;access\_token&#39;\];&#xA;&#x9;&#x9;} else {&#xA;&#x9;&#x9;&#x9;$result = $this-&gt;curl-&gt;doGet($url);&#xA;&#x9;&#x9;&#x9;if (!$result) {&#xA;&#x9;&#x9;&#x9;&#x9;$this-&gt;msg = &#34;無法獲取令牌內容&#34;;&#xA;&#x9;&#x9;&#x9;&#x9;return false;&#xA;&#x9;&#x9;&#x9;}&#xA;&#x9;&#x9;&#x9;$result = json\_decode($result, true);&#xA;&#x9;&#x9;&#x9;if (!$result) {&#xA;&#x9;&#x9;&#x9;&#x9;$this-&gt;msg = &#34;解析令牌內容失敗&#34;;&#xA;&#x9;&#x9;&#x9;&#x9;return false;&#xA;&#x9;&#x9;&#x9;}&#xA;&#x9;&#x9;&#x9;if ($result\[&#39;access\_token&#39;\]) {&#xA;&#x9;&#x9;&#x9;&#x9;C::t(PT\_WXTOKEN)-&gt;addToken($result\[&#39;access\_token&#39;\], $type);&#xA;&#x9;&#x9;&#x9;&#x9;return $result\[&#39;access\_token&#39;\];&#xA;&#x9;&#x9;&#x9;} else {&#xA;&#x9;&#x9;&#x9;&#x9;$this-&gt;msg = &#34;獲取令牌失敗&#34;;&#xA;&#x9;&#x9;&#x9;&#x9;return false;&#xA;&#x9;&#x9;&#x9;}&#xA;&#x9;&#x9;}&#xA;&#x9;}&#xA;&#x9;// 獲取js票據  需要在公眾號設定 - 功能設定 - JS介面安全域名設定&#xA;&#x9;public function getJsTicket() {&#xA;&#x9;&#x9;$addtime = TIMESTAMP - 7200;&#xA;&#x9;&#x9;$row = C::t(PT\_WXTICKET)-&gt;getNew($addtime);&#xA;&#x9;&#x9;if ($row) {&#xA;&#x9;&#x9;&#x9;return $row\[&#39;ticket&#39;\];&#xA;&#x9;&#x9;} else {&#xA;&#x9;&#x9;&#x9;$token = $this-&gt;getAccessToken();&#xA;&#x9;&#x9;&#x9;if (!$token) {&#xA;&#x9;&#x9;&#x9;&#x9;return false;&#xA;&#x9;&#x9;&#x9;}&#xA;&#x9;&#x9;&#x9;$url = &#34;https://api.weixin.qq.com/cgi-bin/ticket/getticket?access\_token={$token}&amp;type=jsapi&#34;;&#xA;&#x9;&#x9;&#x9;$result = $this-&gt;curl-&gt;doGet($url);&#xA;&#x9;&#x9;&#x9;if (!$result) {&#xA;&#x9;&#x9;&#x9;&#x9;$this-&gt;msg = &#34;無法獲取js票據&#34;;&#xA;&#x9;&#x9;&#x9;&#x9;return false;&#xA;&#x9;&#x9;&#x9;}&#xA;&#x9;&#x9;&#x9;$result = json\_decode($result, true);&#xA;&#x9;&#x9;&#x9;if (!$result) {&#xA;&#x9;&#x9;&#x9;&#x9;$this-&gt;msg = &#34;解析js票據內容失敗&#34;;&#xA;&#x9;&#x9;&#x9;&#x9;return false;&#xA;&#x9;&#x9;&#x9;}&#xA;&#x9;&#x9;&#x9;if ($result\[&#39;ticket&#39;\]) {&#xA;&#x9;&#x9;&#x9;&#x9;C::t(PT\_WXTICKET)-&gt;addTicket($result\[&#39;ticket&#39;\]);&#xA;&#x9;&#x9;&#x9;&#x9;return $result\[&#39;ticket&#39;\];&#xA;&#x9;&#x9;&#x9;} else {&#xA;&#x9;&#x9;&#x9;&#x9;$this-&gt;msg = &#34;獲取js票據失敗&#34;;&#xA;&#x9;&#x9;&#x9;&#x9;return false;&#xA;&#x9;&#x9;&#x9;}&#xA;&#x9;&#x9;}&#xA;&#x9;}&#xA;&#x9;// js sdk 票據簽名 當前網頁的URL，不包含#及其後面部分&#xA;&#x9;public function jsSign($data) {&#xA;&#x9;&#x9;// 1.所有待簽名參數按照字段名的ASCII 碼從小到大排序（字典序）&#xA;&#x9;&#x9;ksort($data);&#xA;&#x9;&#x9;// 2.URL鍵值對的格式（即key1=value1&amp;key2=value2…）拼接成字符串string1 採用原始值，不進行URL 轉義&#xA;&#x9;&#x9;$string1 = $this-&gt;ToUrlParams($data);&#xA;&#x9;&#x9;// echo &#34;string1:{$string1}&lt;br/&gt;&#34;;&#xA;&#x9;&#x9;// 3.對string1做sha1加密&#xA;&#x9;&#x9;$sign = sha1($string1);&#xA;&#x9;&#x9;// echo &#34;signature:{$sign}&lt;br/&gt;&#34;;&#xA;&#x9;&#x9;return $sign;&#xA;&#x9;}&#xA;&#x9;// 獲取訊息內容&#xA;&#x9;public function getMsg() {&#xA;&#x9;&#x9;return $this-&gt;msg;&#xA;&#x9;}&#xA;&#x9;/\*\*&#xA;&#x9;\* 格式化參數格式化成url參數&#xA;&#x9;\*/&#xA;&#x9;public function ToUrlParams($data) {&#xA;&#x9;&#x9;$buff = &#34;&#34;;&#xA;&#x9;&#x9;foreach ($data as $k =&gt; $v) {&#xA;&#x9;&#x9;&#x9;if ($k != &#34;sign&#34; &amp;&amp; $v != &#34;&#34; &amp;&amp; !is\_array($v)) {&#xA;&#x9;&#x9;&#x9;&#x9;$buff .= $k . &#34;=&#34; . $v . &#34;&amp;&#34;;&#xA;&#x9;&#x9;&#x9;}&#xA;&#x9;&#x9;}&#xA;&#x9;&#x9;$buff = trim($buff, &#34;&amp;&#34;);&#xA;&#x9;&#x9;return $buff;&#xA;&#x9;}&#xA;}&#xA;?&gt;&#xA;&lt;p&gt;// 微信登入&#xA;function wxlogin() {&#xA;global $_G,$identifier,$config,$wx;&#xA;if (!$_G[&amp;lsquo;uid&amp;rsquo;]) {&#xA;if ($_GET[&amp;lsquo;state&amp;rsquo;]) {&#xA;// 回調&#xA;$member = $wx-&amp;gt;getUserInfo($_GET[&amp;lsquo;code&amp;rsquo;]);&#xA;if (!$member) {&#xA;exit($wx-&amp;gt;getMsg());&#xA;}&#xA;if (!function_exists(&amp;ldquo;setloginstatus&amp;rdquo;)) {&#xA;include_once libfile(&amp;lsquo;function/member&amp;rsquo;);&#xA;}&#xA;// 設定登入狀態$wx&#xA;setloginstatus($member, 2592000);&#xA;checkfollowfeed();&#xA;$_G[&amp;lsquo;uid&amp;rsquo;] = $member[&amp;lsquo;uid&amp;rsquo;];&#xA;$_G[&amp;lsquo;member&amp;rsquo;] = $member;&#xA;} else {&#xA;// 請求授權 對參數編碼&#xA;$redirect = urlencode(getProtocol() . $_SERVER[&amp;lsquo;HTTP_HOST&amp;rsquo;] . $_SERVER[&amp;lsquo;REQUEST_URI&amp;rsquo;]);&#xA;$wx-&amp;gt;getCode($redirect, &amp;lsquo;snsapi_base&amp;rsquo;);&#xA;}&#xA;}&#xA;}&#xA;function getProtocol() {&#xA;return is_HTTPS() ? &amp;lsquo;https://&amp;rsquo; : &amp;lsquo;http://&amp;rsquo;;&#xA;}&#xA;function is_HTTPS() {  if ($_SERVER[&amp;lsquo;HTTPS&amp;rsquo;] === 1 || $_SERVER[&amp;lsquo;HTTPS&amp;rsquo;] === &amp;lsquo;on&amp;rsquo; || $_SERVER[&amp;lsquo;SERVER_PORT&amp;rsquo;] == 443) {&#xA;return true;&#xA;}&#xA;return false;&#xA;}&lt;/p&gt;</description>
    </item>
    <item>
      <title>微信JSAPI支付</title>
      <link>https://ja.moejue.cn/zh-hant/posts/89/</link>
      <pubDate>Sat, 30 Mar 2019 09:30:21 +0000</pubDate>
      <guid>https://ja.moejue.cn/zh-hant/posts/89/</guid>
      <description>&lt;p&gt;&#xA;&lt;figure class=&#34;image-figure not-prose my-8&#34; &#xA;        data-lightbox-enabled=&#34;false&#34;&#xA;        data-gallery-type=&#34;auto&#34;&gt;&#xA;  &lt;div class=&#34;image-container&#34;&gt;&#xA;    &lt;img&#xA;    src=&#34;https://image.baidu.com/search/down?url=https://tva1.sinaimg.cn//large/0072Vf1pgy1g1l3k211blj30ia04x74e.jpg&#34;&#xA;    alt=&#34;&#34;&#xA;    &#xA;    &#xA;    loading=&#34;lazy&#34;&#xA;    decoding=&#34;async&#34;&#xA;    data-gallery-src=&#34;https://image.baidu.com/search/down?url=https://tva1.sinaimg.cn//large/0072Vf1pgy1g1l3k211blj30ia04x74e.jpg&#34;&#xA;    data-gallery-alt=&#34;&#34;&#xA;    data-gallery-title=&#34;&#34; /&gt;&lt;/div&gt;&#xA;&#xA;  &lt;/figure&gt; 前陣子一直在做微信相關的業務，雖說不是什麼新技術，但之前一直沒有機會接觸到，然後踩了些坑，抽空整理記錄下。&#xA;微信支付一共分為7種，分別是：付款碼支付、JSAPI支付、Native支付、APP支付、H5支付、小程序支付、人臉支付。&#xA;此次業務中使用到的是微信JSAPI支付：用戶透過微信掃碼、關注公眾號等方式進入商家H5頁面，並在&lt;strong&gt;微信內&lt;/strong&gt;呼叫 JSSDK完成支付&lt;/p&gt;&#xA;&lt;p&gt;文件：&lt;a href=&#34;https://pay.weixin.qq.com/wiki/doc/api/index.html&#34;target=&#34;_blank&#34;&#xA;  class=&#34;inline-flex items-center gap-1&#34;&#xA;&gt;https://pay.weixin.qq.com/wiki/doc/api/index.html&#xA;  &lt;svg id=&#34;external-link&#34; class=&#34;h-3 w-3 flex-shrink-0&#34;&#xA;    fill=&#34;none&#34;&#xA;    stroke=&#34;currentColor&#34;&#xA;    viewBox=&#34;0 0 24 24&#34;&gt;&lt;path fill=&#34;none&#34; stroke=&#34;currentColor&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; stroke-width=&#34;2&#34; d=&#34;M15 3h6v6m-11 5L21 3m-3 10v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6&#34;/&gt;&lt;/svg&gt;&#xA;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;SDK：[https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=11_1&lt;/p&gt;&#xA;&lt;p&gt;](&lt;a href=&#34;https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=11_1%29JSAPI&#34;target=&#34;_blank&#34;&#xA;  class=&#34;inline-flex items-center gap-1&#34;&#xA;&gt;https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=11_1)JSAPI&#xA;  &lt;svg id=&#34;external-link&#34; class=&#34;h-3 w-3 flex-shrink-0&#34;&#xA;    fill=&#34;none&#34;&#xA;    stroke=&#34;currentColor&#34;&#xA;    viewBox=&#34;0 0 24 24&#34;&gt;&lt;path fill=&#34;none&#34; stroke=&#34;currentColor&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; stroke-width=&#34;2&#34; d=&#34;M15 3h6v6m-11 5L21 3m-3 10v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6&#34;/&gt;&lt;/svg&gt;&#xA;&lt;/a&gt;支付需要在微信中的瀏覽器打開才能喚起微信支付，效果如下圖&#xA;&#xA;&lt;figure class=&#34;image-figure not-prose my-8&#34; &#xA;        data-lightbox-enabled=&#34;false&#34;&#xA;        data-gallery-type=&#34;auto&#34;&gt;&#xA;  &lt;div class=&#34;image-container&#34;&gt;&#xA;    &lt;img&#xA;    src=&#34;https://image.baidu.com/search/down?url=https://tva1.sinaimg.cn//large/0072Vf1pgy1g1l36yn1sej30p91hc40b.jpg&#34;&#xA;    alt=&#34;&#34;&#xA;    &#xA;    &#xA;    loading=&#34;lazy&#34;&#xA;    decoding=&#34;async&#34;&#xA;    data-gallery-src=&#34;https://image.baidu.com/search/down?url=https://tva1.sinaimg.cn//large/0072Vf1pgy1g1l36yn1sej30p91hc40b.jpg&#34;&#xA;    data-gallery-alt=&#34;&#34;&#xA;    data-gallery-title=&#34;&#34; /&gt;&lt;/div&gt;&#xA;&#xA;  &lt;/figure&gt;&#xA;附上介面程式碼&#xA;程式碼中使用了模板引擎&#xA;html：&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
