<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
>
<channel>
<title><![CDATA[ZhiCms]]></title> 
<atom:link href="https://www.zhi.red/rss.do" rel="self" type="application/rss+xml" />
<description><![CDATA[ZhiCms值得买内容推荐导购系统]]></description>
<link>https://www.zhi.red/</link>
<language>zh-cn</language>

<item>
    <title>模板开发文档</title>
    <link>https://www.zhi.red/template_dev.do</link>
    <description><![CDATA[<h1>ZhiCms 模板开发文档</h1>
<p>ZhiCms 系统内置 <strong>双模板引擎</strong>，二者对外接口一致，可在后台「系统设置 → 模板引擎」随时切换：</p>
<table>
<thead>
<tr>
<th>引擎</th>
<th>标识</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>ZhiCms 自研引擎</strong>（默认）</td>
<td><code>legacy</code></td>
<td><code>ZhiCms\base\Template</code>，ZhiCms 自研原生标签语法</td>
</tr>
<tr>
<td><strong>ThinkTemplate</strong></td>
<td><code>think</code></td>
<td><code>ZhiCms\base\ThinkTemplate</code>，基于真·ThinkPHP 模板引擎（<code>think-template</code>），语法与 ThinkPHP 一致</td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>警告</strong>：当前主题模板按默认引擎（ZhiCms 自研引擎）语法编写。<strong>请勿随意切换引擎</strong>，否则前端很可能崩溃（空白页/语法错误/样式错乱）。仅当已用新引擎语法重写全部模板时才可切换。</p>
</blockquote>
<p>两种引擎都通过统一的 <code>assign()</code> / <code>display()</code> 接口工作，因此<strong>同一套控制器代码无需改动</strong>，只需保证模板语法与当前引擎兼容。</p>
<blockquote>
<p>切换引擎后请务必到「系统 → 缓存管理」清除模板编译缓存（或删除 <code>data/cache/tpl</code>、<code>data/cache/tpl_compile</code> 目录），否则可能命中旧编译结果。</p>
</blockquote>
<hr />
<h2>1. 模板目录结构</h2>
<p>前台模板位于 <code>app/{模块}/view/{控制器}/</code> 下，默认模块为 <code>index</code>。</p>
<pre><code>app/index/view/
├── public/                 # 公共片段（可被任意页面 include）
│   ├── header.html         # 页头：&lt;head&gt; + 顶部导航 + 头部公共变量
│   ├── footer.html         # 页脚：友情链接 + 版权
│   ├── sidebar.html        # 侧边栏：用户信息 / 登录 / 排行榜等
│   └── pagebar.html        # 分页条
├── index/
│   ├── index.html          # 首页
│   ├── list.html           # 列表页
│   └── view.html           # 文章详情
├── brand/  cheaps/  rank/  search/  m/  ucenter/  ...   # 各功能页面</code></pre>
<ul>
<li>模板文件默认后缀为 <code>.html</code>（由 <code>data/config/global.php</code> 中 <code>TPL.TPL_SUFFIX</code> 控制）。</li>
<li>路径约定：<code>display()</code> 为空时自动解析为 <code>app/{APP_NAME}/view/{controller}/{action}.html</code>。</li>
<li>控制器可通过 <code>$this-&gt;display('app/index/view/xxx/yyy')</code> 指定任意模板（<strong>推荐绝对路径</strong>，见「控制器渲染」）。</li>
</ul>
<h3>1.1 一个标准页面的骨架</h3>
<p>几乎所有前台页面都以 <code>header</code> / <code>footer</code> 公共片段开始与结束：</p>
<pre><code class="language-html">{include file="app/index/view/public/header"}

&lt;!-- 页面主体内容 --&gt;
&lt;div class="container"&gt;
    ...
&lt;/div&gt;

{include file="app/index/view/public/footer"}</code></pre>
<p><code>header.html</code> 负责输出 <code>&lt;!DOCTYPE html&gt;</code>、<code>&lt;head&gt;</code>（含 SEO 标题/关键词/描述）、顶部导航与全局 CSS/JS；<code>footer.html</code> 负责输出页脚、友情链接、版权与公共 JS。</p>
<hr />
<h2>2. 控制器与模板的交互</h2>
<h3>2.1 变量赋值 <code>assign()</code></h3>
<pre><code class="language-php">public function index(){
    $this-&gt;assign('newsList', $list);   // 数组
    $this-&gt;assign('title', '示例标题');  // 标量
    $this-&gt;display();                   // 渲染默认模板
}</code></pre>
<p><code>assign($name, $value)</code> 把数据注入模板，模板中直接以 <code>$name</code> 使用。</p>
<h3>2.2 渲染模板 <code>display()</code></h3>
<pre><code class="language-php">$this-&gt;display();                                    // 默认：app/index/view/{controller}/{action}.html
$this-&gt;display('app/index/view/index/index');        // 指定模板（推荐绝对路径，避免 TPL_PATH 为空时报错）
$this-&gt;display('', false, false);                    // $isTpl=false 时 $tpl 为模板字符串</code></pre>
<p><code>display()</code> 会自动把控制器<strong>所有 public 属性</strong>（<code>$this-&gt;xxx</code>）一并注入模板。因此前台控制器最常见的写法是直接给属性赋值，无需逐个 <code>assign()</code>：</p>
<pre><code class="language-php">public function view(){
    $this-&gt;view = $data;        // 详情数据
    $this-&gt;pageTitle = '标题';   // SEO 标题
    $this-&gt;canonicalUrl = url(...);
    $this-&gt;display();
}</code></pre>
<h3>2.3 布局（layout）</h3>
<p>控制器设置 <code>$this-&gt;layout</code> 后，页面内容会套用到该布局中：</p>
<pre><code class="language-php">public $layout = 'app/index/view/public/layout';     // 所有输出都进入该布局</code></pre>
<blockquote>
<p>ThinkTemplate 引擎还额外支持 <code>{extend name="base"}...{block}...{/block}</code> 继承语法。</p>
</blockquote>
<h3>2.4 控制器输出数据到模板（完整流程）</h3>
<p>一个「从数据库取数 → 赋值 → 模板渲染」的典型控制器方法：</p>
<pre><code class="language-php">public function list(){
    $where = array("1");                       // 查询条件（数组元素会以 AND 拼接）
    $where[] = "`status` = '1'";               // 追加条件

    // 分页：第 1 参每页条数，返回 ['list'=&gt;..,'count'=&gt;..,'page'=&gt;html]
    $page = obj("api/ApiData")-&gt;page("10", "yun_article", $where, "`id` DESC", $baseUrl);
    $this-&gt;page = $page;                       // 模板里用 $page['list'] 遍历，$page['page'] 输出分页

    $this-&gt;pageTitle   = '列表页 - ' . obj('base/Base')-&gt;SiteConfig('sitename');
    $this-&gt;pageKeywords = '关键词';
    $this-&gt;display();
}</code></pre>
<p>模板端对应输出：</p>
<pre><code class="language-html">{foreach $page['list'] as $item}
  &lt;a href="{$item['url']}"&gt;{$item['title']}&lt;/a&gt;
  &lt;span&gt;{$item['addtime']|date_format}&lt;/span&gt;
{/foreach}
{$page['page']}   &lt;!-- 分页条 --&gt;</code></pre>
<hr />
<h2>3. 双引擎通用能力</h2>
<p>以下语法在 <strong>ZhiCms 自研引擎 与 ThinkTemplate 两种引擎下都可用</strong>，是编写「可同时兼容两套引擎」模板的基础。</p>
<h3>3.1 变量输出</h3>
<pre><code class="language-html">{$name}              &lt;!-- 输出 $name --&gt;
{$user.name}         &lt;!-- 输出 $user['name'] --&gt;
{$user['name']}      &lt;!-- 数组下标写法，两引擎都支持 --&gt;
{$list[0].title}     &lt;!-- 多维访问 --&gt;</code></pre>
<h3>3.2 判断（if / elseif / else）</h3>
<pre><code class="language-html">{if $status == 1}
  启用
{elseif $status == 2}
  暂停
{else}
  未知
{/if}</code></pre>
<p>常用判断写法：<code>{if $x == 1}</code>、<code>{if $x != ''}</code>、<code>{if $x &gt; 3}</code>、<code>{if !empty($arr)}</code>、<code>{if isset($a) &amp;&amp; $a == 1}</code>。</p>
<h3>3.3 循环 <code>foreach</code></h3>
<pre><code class="language-html">{foreach $list as $item}
  &lt;a href="{$item.url}"&gt;{$item.title}&lt;/a&gt;
{/foreach}

{foreach $map as $key =&gt; $val}
  {$key}: {$val}
{/foreach}</code></pre>
<blockquote>
<p>ZhiCms 自研引擎会在循环内自动维护 <code>$n</code> 计数器（<code>$n</code> 从 1 开始）；ThinkTemplate 同样兼容 <code>{foreach}</code>。空数组时 <code>foreach</code> 不会执行，不会报错。</p>
</blockquote>
<h3>3.4 引入公共片段 <code>include</code></h3>
<pre><code class="language-html">{include file="app/index/view/public/header"}
{include file="app/index/view/public/footer"}
{include file="app/index/view/index/list_item"}   &lt;!-- 可复用列表项 --&gt;</code></pre>
<h3>3.5 函数调用输出</h3>
<pre><code class="language-html">{obj('base/Base')-&gt;SiteConfig('sitename')}   &lt;!-- 站点名 --&gt;
{obj('base/Base')-&gt;SEO('index_title')}        &lt;!-- SEO 标题 --&gt;
{date('Y-m-d H:i:s', $item['addtime'])}       &lt;!-- 时间格式化 --&gt;
{count($list)}                                 &lt;!-- 统计数量 --&gt;
{url('index/index/index')}                     &lt;!-- 生成路由 URL --&gt;</code></pre>
<blockquote>
<p>说明：自研引擎把 <code>{函数(...)}</code> 编译为 <code>&lt;?php echo 函数(...);?&gt;</code>；ThinkTemplate 中这类「函数直出」建议使用 <code>{:func()}</code> 写法（见 5.2）。</p>
</blockquote>
<h3>3.6 <code>isset</code> / <code>empty</code> 防空</h3>
<p>为避免变量未定义告警，判断前先用 <code>isset</code> / <code>empty</code> 防护：</p>
<pre><code class="language-html">{if isset($pageTitle) &amp;&amp; $pageTitle != ''}{$pageTitle}{else}默认标题{/if}
{if !empty($banners)} ...轮播... {/if}</code></pre>
<hr />
<h2>4. ZhiCms 自研引擎（默认）</h2>
<p>直接通过正则把 <code>{...}</code> 编译成 PHP，<strong>输出默认原样、不转义</strong>。</p>
<h3>4.1 支持的标签</h3>
<table>
<thead>
<tr>
<th>语法</th>
<th>编译结果</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>{$var}</code></td>
<td><code>&lt;?php echo $var;?&gt;</code></td>
<td>变量输出</td>
</tr>
<tr>
<td><code>{$a.b.c}</code></td>
<td><code>&lt;?php echo $a['b']['c'];?&gt;</code></td>
<td>点语法访问多维数组</td>
</tr>
<tr>
<td><code>{CONSTANT}</code></td>
<td><code>&lt;?php echo CONSTANT;?&gt;</code></td>
<td>常量输出（如 <code>{CONTROLLER_NAME}</code>、<code>{ACTION_NAME}</code>、<code>{APP_NAME}</code>、<code>{__PUBLIC__}</code>）</td>
</tr>
<tr>
<td><code>{if ...}{elseif ...}{else}{/if}</code></td>
<td><code>&lt;?php if... ?&gt;...</code></td>
<td>条件判断</td>
</tr>
<tr>
<td><code>{foreach $arr as $v}</code> / <code>{foreach $arr as $k =&gt; $v}</code></td>
<td><code>&lt;?php foreach... ?&gt;</code></td>
<td>循环</td>
</tr>
<tr>
<td><code>{for $i=0;$i&lt;10;$i++}</code> / <code>{/for}</code></td>
<td><code>&lt;?php for... ?&gt;</code></td>
<td>for 循环</td>
</tr>
<tr>
<td><code>{php ...}</code></td>
<td><code>&lt;?php ... ?&gt;</code></td>
<td>原生 PHP 块</td>
</tr>
<tr>
<td><code>{函数(...)}</code></td>
<td><code>&lt;?php echo 函数(...);?&gt;</code></td>
<td>函数输出</td>
</tr>
<tr>
<td><code>{include file="..."}</code></td>
<td><code>&lt;?php $__Template-&gt;display("...");?&gt;</code></td>
<td>引入片段</td>
</tr>
</tbody>
</table>
<h3>4.2 常见坑</h3>
<ul>
<li><strong>不要在页面文案里写裸的 <code>{中文}</code> / <code>{标签}</code> / <code>{示例}</code></strong>：会被引擎当成常量解析，报 <code>Undefined constant "xxx"</code> 导致整页中断。如需在页面展示模板标签示例，请用 HTML 实体：<code>&amp;#123;</code> = <code>{</code>，<code>&amp;#125;</code> = <code>}</code>。</li>
<li>输出<strong>用户提交的内容</strong>（评论、文章等）请自行 <code>htmlspecialchars($x, ENT_QUOTES)</code>，因为自研引擎默认不转义。</li>
</ul>
<hr />
<h2>5. ThinkTemplate（真·ThinkPHP 引擎）</h2>
<p>语法与 ThinkPHP 模板引擎一致，额外支持更丰富的写法。</p>
<h3>5.1 变量与函数</h3>
<ul>
<li>变量输出同样默认原样（本系统把 <code>default_filter</code> 设为 <code>tpl_raw</code>，<strong>不自动转义</strong>，与自研引擎保持一致）。</li>
<li><strong>函数 / 常量输出用 <code>{:}</code></strong>：
<pre><code class="language-html">{:date('Y-m-d')}                       &lt;!-- 函数输出 --&gt;
{:strtoupper($name)}                   &lt;!-- 函数带参 --&gt;
{__PUBLIC__}                           &lt;!-- 常量输出 --&gt;</code></pre></li>
</ul>
<h3>5.2 模板继承</h3>
<pre><code class="language-html">{extend name="app/index/view/public/base"}
{block name="content"}页面内容{/block}</code></pre>
<h3>5.3 更多标签</h3>
<p>支持 <code>{include file="..."}</code>、<code>{volist}</code>、<code>{switch}</code>、<code>{compare}</code> 等 ThinkPHP 标签。</p>
<blockquote>
<p>编写可同时兼容两套引擎的模板：尽量只用第 3 章的通用语法；如需函数直出，用 <code>{:func()}</code>（自研引擎也能正确输出），避免在文案中出现裸大括号。</p>
</blockquote>
<hr />
<h2>6. 常用框架对象与数据</h2>
<p>模板中常用 <code>obj()</code> 全局助手获取业务数据：</p>
<table>
<thead>
<tr>
<th>表达式</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>{obj('base/Base')-&gt;SiteConfig('sitename')}</code></td>
<td>站点名称</td>
</tr>
<tr>
<td><code>{obj('base/Base')-&gt;SiteConfig('hosturl')}</code></td>
<td>站点域名</td>
</tr>
<tr>
<td><code>{obj('base/Base')-&gt;SiteConfig('sitekeywords')}</code></td>
<td>关键词</td>
</tr>
<tr>
<td><code>{obj('base/Base')-&gt;SiteConfig('sitedescription')}</code></td>
<td>站点描述</td>
</tr>
<tr>
<td><code>{obj('base/Base')-&gt;SEO('index_title')}</code></td>
<td>SEO 标题</td>
</tr>
<tr>
<td><code>{obj('base/Base')-&gt;SEO('index_dec')}</code></td>
<td>SEO 描述</td>
</tr>
<tr>
<td><code>{url('index/index/index')}</code></td>
<td>生成路由 URL</td>
</tr>
<tr>
<td><code>{obj('api/ApiData')-&gt;...}</code></td>
<td>数据查询（一般由控制器封装后赋值）</td>
</tr>
</tbody>
</table>
<p>控制器 <code>assign()</code> 注入的变量在模板中直接以 <code>$变量名</code> 使用。</p>
<hr />
<h2>7. 常用模板变量（控制器注入）</h2>
<p>以下变量由各控制器在渲染前注入，模板可直接使用：</p>
<ul>
<li><strong>站点/SEO</strong>：见 <code>obj('base/Base')-&gt;SiteConfig(...)</code> 系列。</li>
<li><strong>SEO</strong>：<code>$pageTitle</code>、<code>$pageKeywords</code>、<code>$pageDescription</code>、<code>$canonicalUrl</code>、<code>$ogImage</code>。</li>
<li><strong>列表页</strong>：<code>$list</code> / <code>$pageList</code>、<code>$pagebar</code>（分页 HTML）、<code>$page</code>（分页数组，含 <code>page</code> 字段）。</li>
<li><strong>详情页</strong>：<code>$info</code> / <code>$item</code> / <code>$article</code>、<code>$prev</code>、<code>$next</code>。</li>
<li><strong>通用</strong>：<code>$loginUser</code>（当前登录用户）、<code>$categories</code>（分类）、<code>$navs</code>（导航）、<code>$banners</code>（幻灯/轮播）。</li>
</ul>
<blockquote>
<p>具体变量名以各控制器 <code>assign()</code> 注入为准；开发时可先在同页面控制器源码中查看注入了哪些变量。</p>
</blockquote>
<h3>7.1 分页输出</h3>
<p>分页条已由框架生成 HTML，直接输出即可：</p>
<pre><code class="language-html">{if isset($page) &amp;&amp; isset($page['page'])}
&lt;div class="pagination" style="margin-top:24px;"&gt;{$page['page']}&lt;/div&gt;
{/if}</code></pre>
<h3>7.2 URL 生成</h3>
<p>用 <code>{url(...)}</code> 生成带路由规则的地址，避免硬编码：</p>
<pre><code class="language-html">&lt;a href="{url('index/index/view', ['id' =&gt; $item['id']])}"&gt;{$item['title']}&lt;/a&gt;</code></pre>
<hr />
<h2>8. 数据库操作（控制器取数 / 增改删）</h2>
<p>控制器通过 <code>obj("api/ApiData")</code>（即 <code>app\api\model\ApiDataModel</code>）访问数据库。表名可带前缀 <code>{pre}</code>（自动替换为 <code>yun_</code>）或直接用真实表名 <code>yun_xxx</code>。</p>
<blockquote>
<p>所有表名前缀统一为 <code>yun_</code>（如文章表 <code>yun_article</code>、用户表 <code>yun_user</code>、评论表 <code>yun_comment</code>、轮播表 <code>yun_huan</code>、友链表 <code>yun_link</code>）。插件自定义表通常也用 <code>yun_</code> 前缀建表。</p>
</blockquote>
<h3>8.1 查询（查）</h3>
<p><strong>单条记录</strong>（无 <code>$order</code> 时内部走 <code>find()</code>，返回一维数组）：</p>
<pre><code class="language-php">$row = obj("api/ApiData")-&gt;dataSelect("yun_article", array("`id` = 123"));
// $row = ['id'=&gt;123, 'title'=&gt;'...', 'content'=&gt;'...']</code></pre>
<p><strong>多条记录</strong>（传 <code>$order</code> 走 <code>select()</code>，返回二维数组）：</p>
<pre><code class="language-php">$list = obj("api/ApiData")-&gt;dataSelect("yun_article", array("`status` = '1'"), "`id` DESC LIMIT 0, 10");
// $list = [ ['id'=&gt;..,'title'=&gt;..], ... ]</code></pre>
<p><strong>原生 SQL 查询</strong>（可带占位参数防注入）：</p>
<pre><code class="language-php">$rows = obj("api/ApiData")-&gt;thisQuery(
    "SELECT c.*, u.username FROM `{pre}comment` c LEFT JOIN `{pre}user` u ON u.id = c.uid WHERE c.mid = ? ORDER BY c.id DESC LIMIT 6",
    array($id)
);</code></pre>
<p><strong>计数</strong>：</p>
<pre><code class="language-php">$count = obj("api/ApiData")-&gt;dataCount("yun_comment", array("`mid` = 1 AND `hide` = 'n'"));</code></pre>
<p><strong>流式查询构造器</strong>（<code>table()-&gt;where()-&gt;order()-&gt;limit()-&gt;select()</code>）：</p>
<pre><code class="language-php">$rows = obj("api/ApiData")-&gt;table("yun_article", true)
    -&gt;where(array("`status` = '1'"))
    -&gt;order("`id` DESC")
    -&gt;limit("0, 20")
    -&gt;select();</code></pre>
<h3>8.2 新增（增）</h3>
<pre><code class="language-php">$newId = obj("api/ApiData")-&gt;insertData("yun_my_table", array(
    'title'   =&gt; $title,
    'content' =&gt; $content,
    'addtime' =&gt; time(),
));
// $newId 为自增主键 id</code></pre>
<p>批量插入（性能更高，一条多值 INSERT）：</p>
<pre><code class="language-php">$dataList = array(
    array('title' =&gt; 'a', 'content' =&gt; '...'),
    array('title' =&gt; 'b', 'content' =&gt; '...'),
);
$affected = obj("api/ApiData")-&gt;insertAllData("yun_my_table", $dataList);</code></pre>
<h3>8.3 更新（改）</h3>
<pre><code class="language-php">obj("api/ApiData")-&gt;dataUpdate("yun_my_table", array(
    'title' =&gt; $newTitle,
    'hits'  =&gt; $hits + 1,
), array("`id` = $id"));</code></pre>
<p>原生更新（支持参数化）：</p>
<pre><code class="language-php">obj("api/ApiData")-&gt;executeQuery(
    "UPDATE `{pre}article` SET `hits` = `hits` + 1 WHERE `id` = ?",
    array($id)
);</code></pre>
<h3>8.4 删除（删）</h3>
<pre><code class="language-php">// 简单按 id 删除（自动参数化）
obj("api/ApiData")-&gt;deleteThis("yun_my_table", "`id` = 123");

// 复杂条件删除（推荐参数化）
obj("api/ApiData")-&gt;deleteThis("yun_my_table", "`uid` = ? AND `model` = ?", array($uid, 'article'));

// 原生删除
obj("api/ApiData")-&gt;executeQuery("DELETE FROM `{pre}my_table` WHERE `id` = ?", array($id));</code></pre>
<h3>8.5 控制器中「取数 → 加工 → 赋值给模板」完整示例</h3>
<pre><code class="language-php">public function detail(){
    $id = (int)$this-&gt;arg('id');            // 接收 GET/POST 参数并转整型

    // 1) 查文章
    $view = obj("api/ApiData")-&gt;dataSelect("yun_article", array("`id` = $id"));
    if (empty($view)) { $this-&gt;alert('文章不存在'); }

    // 2) 加工：补字段 / 触发钩子让插件改写
    $view['cateName'] = \app\base\controller\BaseController::getNavName($view['navid'] ?? 0);
    \ZhiCms\base\Hook::listen('article_view', array(&amp;$view));

    // 3) 赋值（public 属性会被 display() 自动注入）
    $this-&gt;view = $view;
    $this-&gt;pageTitle = $view['title'] . ' - ' . obj('base/Base')-&gt;SiteConfig('sitename');
    $this-&gt;canonicalUrl = url('index/index/view/id=&lt;id&gt;', array('id' =&gt; $id));
    $this-&gt;display();
}</code></pre>
<h3>8.6 前端提交数据的写入（增删改示例）</h3>
<p>配合前端表单，控制器接收 <code>$_POST</code>（用 <code>$this-&gt;arg()</code> / <code>$this-&gt;Postarg()</code> 安全取值）后写入数据库：</p>
<pre><code class="language-php">public function add(){
    if (!$this-&gt;isPost()) { $this-&gt;alert('非法请求'); }

    $title = trim($this-&gt;Postarg('title'));       // 安全取 POST，已做 htmlspecialchars 过滤
    $content = $_POST['content'];                  // 富文本内容一般用原始值

    obj("api/ApiData")-&gt;insertData("yun_article", array(
        'title'   =&gt; $title,
        'content' =&gt; $content,
        'addtime' =&gt; time(),
    ));
    echo json_encode(array('info' =&gt; '添加成功', 'status' =&gt; 'y'));
}</code></pre>
<blockquote>
<p><code>arg()</code>：合并 <code>$_GET</code>+<code>$_POST</code>，会剥离 <code>&lt;script&gt;</code> 等并做 <code>htmlspecialchars</code>；<code>Postarg()</code> 只取 POST。需要原始值（如富文本/JSON）时直接用 <code>$_POST['xxx']</code>。</p>
</blockquote>
<hr />
<h2>9. 静态资源引入</h2>
<p>建议在 <code>public/web/</code> 下组织 CSS/JS，模板中通过 <code>{__PUBLIC__}</code> 常量引用：</p>
<pre><code class="language-html">&lt;link rel="stylesheet" href="{__PUBLIC__}web/css/blog.css?v=5.0.2"&gt;
&lt;script src="{__PUBLIC__}web/js/common.js?v=5.0.2"&gt;&lt;/script&gt;</code></pre>
<ul>
<li><code>?v=版本号</code> 用于缓存刷新，发布模板改动时请更新版本号。</li>
<li>CSS 优先在 <code>&lt;head&gt;</code> 引入（避免 FOUC，利于 SEO）；JS 建议在 <code>&lt;/body&gt;</code> 前引入（非阻塞渲染）。</li>
<li>页面特有样式可内联 <code>&lt;style&gt;</code>，但<strong>不要重复定义与公共 CSS 相同的类</strong>，以免样式冲突。</li>
</ul>
<hr />
<h2>10. 明暗主题适配</h2>
<p>系统支持 light/dark 双主题（<code>&lt;html data-theme="light|dark"&gt;</code>），主题变量定义在 <code>public/web/css/blog.css</code> / <code>common.css</code>：</p>
<ul>
<li>用 CSS 变量（<code>var(--fontColor)</code>、<code>var(--conBgcolor)</code>、<code>var(--aColor)</code> 等）替代硬编码颜色。</li>
<li>不要在模板内联 <code>style</code> 中写死深色背景上的浅色文字，否则 dark 模式下会看不清。</li>
<li>组件卡片背景用 <code>var(--conBgcolor)</code>，正文用 <code>var(--fontColor)</code>，链接用 <code>var(--aColor)</code>。</li>
<li>移动端用 <code>@media (max-width: 767px)</code> 适配（侧栏折叠、卡片纵向排列等），公共样式已内置大部分适配，页面特有部分自行补充。</li>
</ul>
<hr />
<h2>11. 常见问题排查</h2>
<table>
<thead>
<tr>
<th>现象</th>
<th>原因 / 处理</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>Template file ... not found</code></td>
<td>模板路径不对；<code>display()</code> 建议用绝对路径 <code>app/index/view/xxx</code>，且 <code>data/config/global.php</code> 中 <code>TPL_PATH</code> 为空时不能依赖相对路径</td>
</tr>
<tr>
<td><code>Undefined constant "xxx"</code></td>
<td>自研引擎把 <code>{中文}</code> / <code>{标签}</code> 当常量解析；将文案中的裸大括号转义为实体</td>
</tr>
<tr>
<td>页面空白 / 无输出</td>
<td>模板编译缓存旧版，删除 <code>data/cache/tpl*</code> 后重试</td>
</tr>
<tr>
<td><code>{:func()}</code> 不生效</td>
<td>当前为自研引擎；自研引擎用 <code>{func()}</code> 写法</td>
</tr>
<tr>
<td>切换引擎后样式错乱</td>
<td>引擎不同导致标签渲染差异，核对模板中使用了哪些语法，统一为通用语法</td>
</tr>
<tr>
<td>变量未定义告警</td>
<td>用 <code>isset</code> / <code>empty</code> 防空</td>
</tr>
<tr>
<td>页面显示 HTML 实体 <code>&amp;#123;</code></td>
<td>这是转义后的模板标签示例，属正常；如需真的 <code>{</code>，用 <code>&amp;#123;</code> 即可</td>
</tr>
<tr>
<td>背景 / 文字在 dark 下看不清</td>
<td>模板内联写死了深色文字；改用 <code>var(--fontColor)</code> 等主题变量</td>
</tr>
</tbody>
</table>
<hr />
<p><em>本文档基于 ZhiCms 双模板引擎实现编写，覆盖模板目录、页面骨架、变量注入、双引擎语法差异、公共片段、分页/URL、静态资源、明暗主题与常见问题等完整开发要点。</em></p>
<hr />
<h2>12. 插件模板化（模板与插件协作）</h2>
<p>当插件是「模板化插件」（<code>plugin.json</code> 的 <code>type=template</code> + <code>rewrite</code>，见 PLUGIN_DEV.do 第 7 章）时，它的前台页由<strong>插件自己的 <code>view/</code> 目录下的模板</strong>渲染，而不是 <code>app/index/view/</code>。模板编写的异同如下。</p>
<h3>12.1 模板位置与引擎</h3>
<table>
<thead>
<tr>
<th>项</th>
<th>前台主站模板</th>
<th>模板化插件模板</th>
</tr>
</thead>
<tbody>
<tr>
<td>目录</td>
<td><code>app/index/view/</code></td>
<td><code>plugins/{alias}/view/</code></td>
</tr>
<tr>
<td>渲染者</td>
<td>前台控制器 <code>display()</code></td>
<td>插件控制器基类 <code>display()</code>（<code>ZhiCms\base\ThinkTemplate</code>）</td>
</tr>
<tr>
<td>默认引擎</td>
<td>后台「模板引擎」可切 legacy/think</td>
<td><strong>默认 think-template</strong>（与 guangdiu/kiees 一致，建议保持）</td>
</tr>
<tr>
<td>变量来源</td>
<td>控制器 <code>assign()</code> / public 属性</td>
<td>插件控制器 <code>assign()</code> + <code>display()</code> 里统一注入的站点变量</td>
</tr>
</tbody>
</table>
<blockquote>
<p>插件模板语法遵循 think-template 引擎（见第 3 章通用语法 + 第 5 章），可用 <code>{foreach}</code> / <code>{$x.y}</code> / <code>{include}</code> / <code>{:func()}</code>。</p>
</blockquote>
<h3>12.2 插件模板里可用的变量</h3>
<p>插件控制器 <code>display()</code> 通常会统一注入以下变量（以 guangdiu 为参考，具体以你的控制器为准）：</p>
<table>
<thead>
<tr>
<th>变量</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>{$site_name}</code> / <code>{$site_logo}</code> / <code>{$copyright}</code> / <code>{$beian}</code></td>
<td>站点名称 / Logo / 版权 / 备案（来自 <code>SiteConfig</code>）</td>
</tr>
<tr>
<td><code>{$host_url}</code></td>
<td>站点域名</td>
</tr>
<tr>
<td><code>{$plug_static}</code></td>
<td>插件静态资源根目录（<code>/plugins/{alias}/static</code>）</td>
</tr>
<tr>
<td><code>{$plug_url}</code></td>
<td>插件首页链接（伪静态或动态）</td>
</tr>
<tr>
<td><code>{$plug_base}</code></td>
<td>插件链接前缀（如 <code>plug-guangdiu</code>）</td>
</tr>
<tr>
<td><code>{$is_mobile}</code></td>
<td>是否移动端（0/1）</td>
</tr>
<tr>
<td><code>{$show_sidebar}</code></td>
<td>是否显示侧栏（移动端常 0）</td>
</tr>
<tr>
<td><code>{$nav_index}</code> / <code>{$nav_cheaps}</code> / <code>{$nav_brand}</code> / <code>{$nav_rank}</code></td>
<td>各频道链接</td>
</tr>
<tr>
<td><code>{$hot}</code> / <code>{$list}</code> / <code>{$article}</code> / <code>{$page}</code></td>
<td>业务数据（控制器 <code>assign</code> 注入）</td>
</tr>
</tbody>
</table>
<h3>12.3 在插件模板里引用站点配置</h3>
<pre><code class="language-html">&lt;title&gt;{$site_name}&lt;/title&gt;
&lt;footer&gt;© {$copyright} {$beian}&lt;/footer&gt;
&lt;link rel="stylesheet" href="{$plug_static}/css/style.css?v=1.0.0"&gt;</code></pre>
<h3>12.4 插件模板 include 自己的片段</h3>
<pre><code class="language-html">{include file="plugins/guangdiu/view/header"}
{include file="plugins/guangdiu/view/sidebar"}
...页面主体...
{include file="plugins/guangdiu/view/footer"}</code></pre>
<blockquote>
<p>路径要写成<strong>插件根目录绝对路径</strong>（<code>plugins/guangdiu/view/header</code>），不要用主站 <code>app/index/view/public/header</code>，否则会混入主站布局（主站 header 含 <code>BaseController</code> 注入的变量，插件页没有）。</p>
</blockquote>
<h3>12.5 插件模板里的链接生成</h3>
<p>模板已注入 <code>{$plug_url}</code>，拼详情/频道链接：</p>
<pre><code class="language-html">&lt;a href="{$plug_url}-{$item.id}.html"&gt;{$item.title}&lt;/a&gt;      &lt;!-- 详情 --&gt;
&lt;a href="{$nav_cheaps}"&gt;优惠券&lt;/a&gt;                          &lt;!-- 频道 --&gt;</code></pre>
<p>若需动态生成（如翻页），可在模板里用：</p>
<pre><code class="language-html">&lt;a href="{:plugins\guangdiu\controller\SiteController::pageUrlHref(['page'=&gt;$page['next']])}"&gt;下一页&lt;/a&gt;</code></pre>
<blockquote>
<p>更推荐：控制器把分页 HTML 算好（如 <code>$this-&gt;assign('pagebar', $html)</code>）直接输出 <code>{$pagebar}</code>。</p>
</blockquote>
<h3>12.6 插件模板的缓存清理</h3>
<p>改了插件 <code>view/</code> 下模板后，若前台有模板编译缓存或静态缓存命中旧版，请清理：</p>
<ul>
<li><code>runtime/cache/tpl*</code> 与 <code>runtime/static_cache/</code></li>
<li>插件若有自己的 <code>view/data/cache/tpl_compile/</code>，也一并删除</li>
</ul>
<p>否则可能看到旧版模板。</p>
<h3>12.7 把插件设为整站首页</h3>
<p>后台「系统设置 → 站点设置 → 主页展示插件」选择该模板化插件后，访问 <code>/</code> 会渲染插件首页（URL 不变）。插件无需任何改动，框架 <code>App::applyHomePlug()</code> 自动把首页路由转给 <code>PlugController::view()</code> → <code>Plugin::displayPage()</code>。前提：插件已启用、<code>type=template</code>、<code>rewrite</code> 含 <code>plug-&lt;alias&gt;.html</code>。*</p>]]></description>
    <pubDate>Sat, 08 Aug 2026 21:05:05 +0800</pubDate>
    <dc:creator>ZhiCms</dc:creator>
    <guid>https://www.zhi.red/template_dev.do</guid>
</item>
<item>
    <title>插件开发文档</title>
    <link>https://www.zhi.red/plugin_dev.do</link>
    <description><![CDATA[<h1>ZhiCms 插件开发文档</h1>
<p>本指南介绍如何为 ZhiCms 开发<strong>标准（Native）格式插件</strong>。插件通过钩子（Hook）挂载到系统运行流程中，实现「不改动框架代码」地扩展功能。</p>
<blockquote>
<p>兼容性：ZhiCms 同时兼容 <strong>Z-Blog / WordPress / Emlog</strong> 三种历史格式插件（通过 <code>ZhiCms\base\compat\Compat</code> 兼容层），本文仅针对官方推荐的 <strong>Native 格式</strong>。</p>
</blockquote>
<hr />
<h2>0. 先选类型：你要写哪种插件？</h2>
<p>ZhiCms 的插件按「是否需要接管前台页面 / 是否依赖数据库」分为三大类，开发方式差异很大，请先对号入座：</p>
<table>
<thead>
<tr>
<th>类型</th>
<th>典型场景</th>
<th>依赖数据库</th>
<th>是否接管前台页</th>
<th>核心入口</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>A. 普通插件（不依赖数据库）</strong></td>
<td>页脚加公告、注入统计代码、改写已有模板内容、SEO 追加</td>
<td>否</td>
<td>否</td>
<td><code>register()</code> 挂钩子 / 过滤器</td>
</tr>
<tr>
<td><strong>B. 依赖数据库的插件</strong></td>
<td>留言板、访问日志、自定义表单、积分、独立数据表业务</td>
<td>是</td>
<td>否（或仅后台页）</td>
<td><code>install.sql</code> 建表 + <code>register()</code> 钩子 + <code>Setting.php</code></td>
</tr>
<tr>
<td><strong>C. 模板化插件（接管前台）</strong></td>
<td>导购站、论坛、商城风格整站、把插件设为站点首页</td>
<td>通常也依赖数据库</td>
<td>是</td>
<td><code>plugin.json</code> 的 <code>rewrite</code> + <code>Plugin::displayPage()</code> + 自有控制器/视图</td>
</tr>
</tbody>
</table>
<p>本文第 1–4 章讲<strong>通用结构</strong>（三类插件都要遵守），第 5–7 章分别用完整示例讲<strong>三类插件怎么写</strong>，第 8 章讲后台菜单 / 设置页 / 首页接管，第 9 章讲打包与安装，第 10 章讲注意事项。</p>
<hr />
<h2>1. 插件目录结构（通用约定）</h2>
<p>插件统一存放于 <strong>网站根目录 <code>plugins/{alias}/</code></strong>，别名（<code>alias</code>）即目录名，只能包含 <code>字母、数字、下划线、连字符</code>。</p>
<h3>1.1 最小结构（类型 A/B 够用）</h3>
<pre><code>plugins/
└── my_plugin/                # 插件目录（alias = my_plugin）
    ├── plugin.json           # 元信息（必需）
    ├── Plugin.php            # 插件入口类（必需，继承 BasePlugin）
    ├── Setting.php           # 设置组件（可选，hasSetting=true 时需要）
    ├── install.sql           # 安装时执行的建表 SQL（可选，类型 B 需要）
    ├── uninstall.sql         # 卸载时执行的 SQL（可选）
    └── view/                 # 插件私有视图（可选，后台设置页 / 片段）
        └── setting.php</code></pre>
<h3>1.2 模板化插件结构（类型 C 推荐）</h3>
<pre><code>plugins/
└── demo/                      # alias = demo
    ├── plugin.json            # 必须声明 type=template + rewrite 规则
    ├── Plugin.php             # 入口：displayPage() 调度到控制器
    ├── controller/
    │   ├── DemoController.php    # 插件控制器基类（assign/display/isMobile）
    │   └── SiteController.php    # 业务：index/detail/list... 真实写在哪
    ├── view/                  # 模板目录（与控制器里的 view_path 对应）
    │   ├── header.html        # 插件页头（复用或自建）
    │   ├── footer.html
    │   ├── sidebar.html
    │   ├── index.html         # 首页
    │   ├── detail.html        # 详情页
    │   ├── list.html
    │   └── ...
    ├── static/                # 插件自有静态资源
    │   ├── css/style.css
    │   └── js/main.js
    ├── install.sql            # 若插件自身有表（可选）
    └── Setting.php            # 可选后台设置</code></pre>
<blockquote>
<p>目录命名建议：<code>controller/</code>（业务控制器）、<code>view/</code>（模板）、<code>static/</code>（资源）是社区约定，框架本身不强制，只要 <code>Plugin.php</code> / <code>plugin.json</code> 在根目录即可。<strong>关键点</strong>：<code>view/</code> 必须是 <code>Plugin::displayPage()</code> 或控制器 <code>display()</code> 实际指向的模板根目录。</p>
</blockquote>
<hr />
<h2>2. plugin.json 元信息（三类插件通用）</h2>
<pre><code class="language-json">{
    "alias": "my_plugin",
    "name": "我的插件",
    "version": "1.0.0",
    "author": "你的名字",
    "description": "插件功能描述",
    "hasSetting": true,
    "type": "common",
    "menu": [
        { "title": "插件设置", "url": "index.php?r=manage/plugin/setting&amp;alias=my_plugin" }
    ],
    "requires": "5.0.0",
    "rewrite": {
        "plug-&lt;alias&gt;.html": "index/plug/view/alias=&lt;alias&gt;",
        "plug-&lt;alias&gt;-&lt;id&gt;.html": "index/plug/view/alias=&lt;alias&gt;/id=&lt;id&gt;"
    }
}</code></pre>
<p>字段说明：</p>
<table>
<thead>
<tr>
<th>字段</th>
<th>必填</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>alias</code></td>
<td>是</td>
<td>插件别名，<strong>必须与目录名一致</strong></td>
</tr>
<tr>
<td><code>name</code></td>
<td>是</td>
<td>插件显示名称</td>
</tr>
<tr>
<td><code>version</code></td>
<td>是</td>
<td>版本号</td>
</tr>
<tr>
<td><code>type</code></td>
<td>否</td>
<td><code>common</code>（默认，普通插件）/ <code>template</code>（模板化插件，可被设为站点首页）。<code>template</code> 同时需要 <code>rewrite</code> 里含 <code>plug-&lt;alias&gt;.html</code> 规则</td>
</tr>
<tr>
<td><code>hasSetting</code></td>
<td>否</td>
<td><code>true</code> 时后台出现「设置」入口，需提供 <code>Setting.php</code></td>
</tr>
<tr>
<td><code>menu</code></td>
<td>否</td>
<td>后台侧边栏「扩展功能」分组下注入的菜单项</td>
</tr>
<tr>
<td><code>rewrite</code></td>
<td>否</td>
<td>模板化插件必填。伪静态规则（见第 7 章）</td>
</tr>
<tr>
<td><code>requires</code></td>
<td>否</td>
<td>依赖的最低系统版本</td>
</tr>
</tbody>
</table>
<blockquote>
<p>模板化插件判定逻辑（源码 <code>PluginManager::getTemplatePlugins()</code>）：<code>rewrite</code> 中存在 <code>plug-&lt;alias&gt;.html</code> 且 <code>Plugin::displayPage()</code> 方法存在，即被视为可被设为主页的模板化插件。后台「系统设置 → 站点设置 → 主页展示插件」下拉里会列出这些插件。</p>
</blockquote>
<hr />
<h2>3. 插件入口类 Plugin.php（三类插件通用）</h2>
<p>入口类必须<strong>继承 <code>ZhiCms\base\plugin\BasePlugin</code></strong>，命名空间为 <code>plugins\{alias}</code>，类名固定为 <code>Plugin</code>：</p>
<pre><code class="language-php">&lt;?php
namespace plugins\my_plugin;

use ZhiCms\base\plugin\BasePlugin;
use ZhiCms\base\Hook;

class Plugin extends BasePlugin
{
    /**
     * 钩子注册：插件「已启用」时，每次请求都会调用。
     * 在此通过 Hook::add() 把回调挂到系统钩子上。
     */
    public function register()
    {
        Hook::add('appBegin', array($this, 'myHook'));
    }

    /** 前台展示页入口（仅模板化插件 C 需要覆写） */
    public function displayPage($params = array()) {}

    /** 首次安装：建目录 / 初始化数据（install.sql 已自动执行） */
    public function install() {}

    /** 卸载：清理数据 / 删除文件 */
    public function uninstall() {}

    /** 启用 / 停用 */
    public function enable() {}
    public function disable() {}
}</code></pre>
<h3>3.1 生命周期方法（BasePlugin 可覆写）</h3>
<table>
<thead>
<tr>
<th>方法</th>
<th>触发时机</th>
<th>典型用途</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>register()</code></td>
<td>每次请求，插件处于启用状态时</td>
<td>注册钩子（最重要）</td>
</tr>
<tr>
<td><code>install()</code></td>
<td>首次安装（<code>install.sql</code> 已执行后）</td>
<td>创建目录、初始化数据</td>
</tr>
<tr>
<td><code>uninstall()</code></td>
<td>卸载插件时</td>
<td>清理建的表 / 生成的文件</td>
</tr>
<tr>
<td><code>enable()</code></td>
<td>从停用变为启用时</td>
<td>恢复数据 / 建目录</td>
</tr>
<tr>
<td><code>disable()</code></td>
<td>从启用变为停用时</td>
<td>停用运行 / 暂停任务</td>
</tr>
<tr>
<td><code>displayPage($params)</code></td>
<td>访问 <code>plug-&lt;alias&gt;*.html</code> 或 <code>index.php?r=index/plug/view</code> 时</td>
<td>模板化插件输出前台页</td>
</tr>
</tbody>
</table>
<blockquote>
<p>注意：<code>BasePlugin</code> <strong>没有</strong> <code>boot()</code> 方法（历史文档里提到的 <code>boot()</code> 实际是 <code>register()</code> 的别名用途，请以 <code>register()</code> 为准）。系统启动时 <code>PluginManager::boot()</code> 负责合并插件 <code>rewrite</code> 规则并 <code>register()</code> 钩子，插件无需自己写 <code>boot()</code>。</p>
</blockquote>
<h3>3.2 BasePlugin 内置可用方法</h3>
<table>
<thead>
<tr>
<th>方法</th>
<th>可见性</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>getConfig()</code></td>
<td>protected</td>
<td>读插件配置（来自 <code>yun_plug.config</code> 的 JSON），返回数组</td>
</tr>
<tr>
<td><code>setConfig($data)</code></td>
<td>protected</td>
<td>保存插件配置（自动 JSON 化写入 <code>yun_plug.config</code>）</td>
</tr>
<tr>
<td><code>displayPage($params)</code></td>
<td>public</td>
<td>模板化插件前台页入口（见第 7 章）</td>
</tr>
<tr>
<td><code>pageUrl($params)</code></td>
<td>public</td>
<td>生成插件展示页链接（伪静态优先，动态兜底）</td>
</tr>
<tr>
<td><code>render($tpl, $vars)</code></td>
<td>protected</td>
<td>渲染插件私有模板 <code>plugins/{alias}/view/{tpl}.html</code>（复用 think-template 引擎，返回字符串）</td>
</tr>
</tbody>
</table>
<h3>3.3 使用框架能力（三类插件通用）</h3>
<pre><code class="language-php">use ZhiCms\base\Config;

// 读数据库（{pre} 自动替换为表前缀 yun_）
$rows = obj('api/ApiData')-&gt;thisQuery("SELECT * FROM {pre}my_table WHERE id = ?", array($id));

// 读站点配置
$siteName = obj('base/Base')-&gt;SiteConfig('sitename');
$cfg = \app\common\ConfigStore::load('site');        // 站点配置数组

// 写操作日志
\ZhiCms\ext\AdminLog::write('my_plugin', '做了某事');

// 读/写插件自身配置
$conf = $this-&gt;getConfig();
$this-&gt;setConfig(array_merge($conf, array('foo' =&gt; 'bar')));</code></pre>
<hr />
<h2>4. 钩子（Hook）系统（类型 A/B 的核心）</h2>
<h3>4.1 注册钩子</h3>
<pre><code class="language-php">Hook::add($tag, $callable, $priority = 10);</code></pre>
<ul>
<li><code>$tag</code>：钩子名（系统内置或业务自定义）</li>
<li><code>$callable</code>：回调，支持数组 <code>[$this,'method']</code>、字符串 <code>'Class::method'</code>、<code>'Class@method'</code>、普通函数名、闭包</li>
<li><code>$priority</code>：数值越小越先执行</li>
</ul>
<h3>4.2 系统内置钩子</h3>
<table>
<thead>
<tr>
<th>钩子名</th>
<th>触发时机</th>
<th>参数</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>appBegin</code></td>
<td>框架启动</td>
<td>（无）</td>
</tr>
<tr>
<td><code>appEnd</code></td>
<td>框架结束</td>
<td>（无）</td>
</tr>
<tr>
<td><code>appError</code></td>
<td>框架错误</td>
<td><code>$e</code></td>
</tr>
<tr>
<td><code>routeParseUrl</code></td>
<td>路由解析</td>
<td><code>$rewriteRule</code>, <code>$rewriteOn</code></td>
</tr>
<tr>
<td><code>actionBefore</code> / <code>actionAfter</code></td>
<td>控制器方法执行前后</td>
<td><code>$obj</code>, <code>$action</code></td>
</tr>
<tr>
<td><code>templateParse</code></td>
<td>模板编译前</td>
<td><code>$template</code>（模板内容，可改写）</td>
</tr>
<tr>
<td><code>dbQueryBegin</code> / <code>dbQueryEnd</code> / <code>dbExecuteBegin</code> / <code>dbExecuteEnd</code> / <code>dbException</code></td>
<td>SQL 执行前后</td>
<td><code>$sql</code>, <code>$params</code> / <code>$data</code> / <code>$affectedRows</code> / <code>$err</code></td>
</tr>
</tbody>
</table>
<p>业务代码也可通过 <code>Hook::listen($tag, $args)</code> 自定义触发任意钩子名，插件可自由挂载。</p>
<h3>4.3 过滤器（改写数据）</h3>
<pre><code class="language-php">// 插件注册过滤器
Hook::add('article_content', function ($content) {
    return $content . "\n&lt;!-- by plugin --&gt;";
});</code></pre>
<pre><code class="language-php">// 业务代码触发（返回值被依次改写）
$content = Hook::filter('article_content', $content, array($article));</code></pre>
<blockquote>
<p>全局助手 <code>do_action()</code> / <code>apply_filters()</code>（<code>ZhiCms/core.php</code>）分别对应 <code>Hook::listen()</code> / <code>Hook::filter()</code>。</p>
</blockquote>
<hr />
<h2>5. 类型 A：不依赖数据库的普通插件（示例：页脚公告 + 统计代码）</h2>
<p><strong>特征</strong>：只挂载钩子、注入 HTML、改写模板/内容，完全不碰数据库。</p>
<h3>5.1 目录</h3>
<pre><code>plugins/hello/
├── plugin.json
└── Plugin.php</code></pre>
<h3>5.2 plugin.json</h3>
<pre><code class="language-json">{
    "alias": "hello",
    "name": "Hello 公告插件",
    "version": "1.0.0",
    "author": "你",
    "description": "在页脚注入公告与统计代码（无数据库）",
    "hasSetting": true
}</code></pre>
<h3>5.3 Plugin.php</h3>
<pre><code class="language-php">&lt;?php
namespace plugins\hello;

use ZhiCms\base\plugin\BasePlugin;
use ZhiCms\base\Hook;

class Plugin extends BasePlugin
{
    public function register()
    {
        // 在 appEnd 钩子（框架输出结束前）注入页脚公告 + 统计代码
        Hook::add('appEnd', function () {
            $cfg = $this-&gt;getConfig();
            if (empty($cfg['enabled'])) return;

            $notice = $cfg['notice'] ?? '欢迎光临本站';
            echo '&lt;div class="hello-footer-notice" style="text-align:center;padding:10px;background:#f5f5f5"&gt;'
               . htmlspecialchars($notice, ENT_QUOTES) . '&lt;/div&gt;';

            if (!empty($cfg['stat_code'])) {
                echo $cfg['stat_code'];   // 统计代码一般是 &lt;script&gt;，不转义
            }
        });

        // 改写文章正文（追加署名）
        Hook::add('article_content', function ($content) {
            return $content . '&lt;p style="color:#999"&gt;—— 本文由 Hello 插件标记 ——&lt;/p&gt;';
        });
    }

    public function install() {}
    public function uninstall() {}
}</code></pre>
<h3>5.4 Setting.php（可选，用于后台配置公告内容/统计代码）</h3>
<pre><code class="language-php">&lt;?php
namespace plugins\hello;

class Setting
{
    protected $meta = array();
    public function __construct($meta = array()) { $this-&gt;meta = $meta; }

    public function view()
    {
        $config = \ZhiCms\base\PluginManager::getConfig('hello');
        $config = array_merge(array('enabled' =&gt; 0, 'notice' =&gt; '', 'stat_code' =&gt; ''), $config);
        ob_start();
        include __DIR__ . '/view/setting.php';
        return ob_get_clean();
    }

    public function save($data)
    {
        return array(
            'enabled'   =&gt; intval($data['enabled'] ?? 0),
            'notice'    =&gt; trim($data['notice'] ?? ''),
            'stat_code' =&gt; $data['stat_code'] ?? '',   // 原始值，不转义
        );
    }
}</code></pre>
<blockquote>
<p>后台访问 <code>index.php?r=manage/plugin/setting&amp;alias=hello</code>。<code>save()</code> 返回的数组由系统自动写入 <code>yun_plug.config</code>，无需手动 <code>setConfig()</code>。</p>
</blockquote>
<hr />
<h2>6. 类型 B：依赖数据库的插件（示例：访问日志）</h2>
<p><strong>特征</strong>：需要自己的数据表（<code>install.sql</code> 建表），在钩子里读写数据，可配合后台设置页。</p>
<h3>6.1 目录</h3>
<pre><code>plugins/visit_log/
├── plugin.json
├── Plugin.php
├── Setting.php
├── install.sql        # 建表
├── uninstall.sql      # 删表（可选，也可在 uninstall() 里 DROP）
└── view/setting.php</code></pre>
<h3>6.2 install.sql（{pre} 会自动替换为 yun_）</h3>
<pre><code class="language-sql">CREATE TABLE IF NOT EXISTS `{pre}visit_log` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `url` varchar(255) NOT NULL DEFAULT '',
  `ip` varchar(45) NOT NULL DEFAULT '',
  `ua` varchar(255) NOT NULL DEFAULT '',
  `addtime` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `url` (`url`(191))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;</code></pre>
<h3>6.3 Plugin.php</h3>
<pre><code class="language-php">&lt;?php
namespace plugins\visit_log;

use ZhiCms\base\plugin\BasePlugin;
use ZhiCms\base\Hook;

class Plugin extends BasePlugin
{
    public function register()
    {
        Hook::add('appEnd', function () {
            $cfg = $this-&gt;getConfig();
            if (empty($cfg['enabled'])) return;

            $url = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '/';
            $ip  = $_SERVER['REMOTE_ADDR'] ?? '';
            $ua  = $_SERVER['HTTP_USER_AGENT'] ?? '';

            // 写入插件自有表（参数化防注入）
            obj('api/ApiData')-&gt;insertData('yun_visit_log', array(
                'url'     =&gt; $url,
                'ip'      =&gt; $ip,
                'ua'      =&gt; $ua,
                'addtime' =&gt; time(),
            ));
        }, 999); // 优先级大，最后执行，避免影响主流程
    }

    /** 后台查看日志（可选）：配合菜单跳转或用 Setting 页输出列表 */
    public function uninstall()
    {
        // 卸载时删表（二选一：这里 DROP 或提供 uninstall.sql）
        try {
            obj('api/ApiData')-&gt;executeQuery("DROP TABLE IF EXISTS `{pre}visit_log`");
        } catch (\Throwable $e) {}
    }
}</code></pre>
<h3>6.4 数据库 CRUD 速查（类型 B 必读）</h3>
<p>表名统一 <code>yun_</code> 前缀，<code>{pre}</code> 在 SQL 中自动替换。推荐用封装方法：</p>
<pre><code class="language-php">// 增（返回自增 id）
$id = obj('api/ApiData')-&gt;insertData('yun_visit_log', array('url'=&gt;$url,'ip'=&gt;$ip,'addtime'=&gt;time()));

// 批量增
obj('api/ApiData')-&gt;insertAllData('yun_visit_log', $dataList);

// 查（单条，无 $order 走 find() 返回一维数组）
$row = obj('api/ApiData')-&gt;dataSelect('yun_visit_log', array("`id` = $id"));

// 查（多条，传 $order 走 select() 返回二维数组）
$list = obj('api/ApiData')-&gt;dataSelect('yun_visit_log', array("1"), '`id` DESC LIMIT 0,20');

// 原生查询（参数化）
$rows = obj('api/ApiData')-&gt;thisQuery(
    "SELECT * FROM {pre}visit_log WHERE `ip` = ? ORDER BY id DESC LIMIT 10", array($ip)
);

// 改（注意 SET 与 WHERE 占位符不要同名冲突，建议用 :__id）
obj('api/ApiData')-&gt;dataUpdate('yun_visit_log', array('url'=&gt;$newUrl), array("`id` = $id"));

// 删（参数化）
obj('api/ApiData')-&gt;deleteThis('yun_visit_log', "`id` = ?", array($id));</code></pre>
<blockquote>
<p><strong>auto_increment 注意</strong>：插入时<strong>不要手填自增 <code>id</code> 字段</strong>，否则 MySQL 严格模式下 <code>id</code> 重复/类型错误会报错。让数据库自增即可。</p>
</blockquote>
<hr />
<h2>7. 类型 C：模板化插件（接管前台页，可被设为站点首页）</h2>
<p><strong>特征</strong>：有自己的控制器 + 视图 + 静态资源，通过 <code>plugin.json</code> 的 <code>rewrite</code> 规则暴露前台页，可整站接管首页（<code>home_plug</code>）。</p>
<blockquote>
<p>本仓库 <code>plugins/guangdiu</code>、<code>plugins/kiees</code> 就是这种插件，下面以「极简导购插件 demo」为例，结构照搬它们。</p>
</blockquote>
<h3>7.1 plugin.json（必须 type=template + rewrite）</h3>
<pre><code class="language-json">{
    "alias": "demo",
    "type": "template",
    "name": "Demo 导购",
    "version": "1.0.0",
    "author": "你",
    "description": "模板化插件示例",
    "hasSetting": false,
    "rewrite": {
        "plug-&lt;alias&gt;-cheaps.html": "index/plug/view/alias=&lt;alias&gt;/mod=cheaps",
        "plug-&lt;alias&gt;-brand.html":  "index/plug/view/alias=&lt;alias&gt;/mod=brand",
        "plug-&lt;alias&gt;-&lt;id&gt;.html":   "index/plug/view/alias=&lt;alias&gt;/id=&lt;id&gt;",
        "plug-&lt;alias&gt;.html":        "index/plug/view/alias=&lt;alias&gt;"
    }
}</code></pre>
<h3>7.2 Plugin.php（displayPage 调度入口）</h3>
<pre><code class="language-php">&lt;?php
namespace plugins\demo;

use ZhiCms\base\plugin\BasePlugin;

class Plugin extends BasePlugin
{
    public function displayPage($params = array())
    {
        $controller = new \plugins\demo\controller\SiteController();
        $controller-&gt;run($params);   // run() 内部按 $params['mod'] 分发到 index/detail/...
        exit;                         // 必须 exit，避免框架再输出默认布局
    }
}</code></pre>
<blockquote>
<p>调度机制：框架 <code>app\index\controller\PlugController::view()</code> 收到请求后，把除 <code>alias</code>/<code>r</code> 外的所有参数（如 <code>mod</code>、<code>id</code>、<code>kw</code>、<code>page</code>）收集进 <code>$params</code>，调用 <code>Plugin::displayPage($params)</code>。插件自己决定怎么分发。</p>
</blockquote>
<h3>7.3 控制器基类（assign / display / isMobile）</h3>
<p>因为模板化插件不继承框架前台控制器，需要自建一个轻量基类，提供 <code>assign()</code> / <code>display()</code> / <code>isMobile()</code> 等能力。可照搬 guangdiu 的 <code>GuangdiuController</code>：</p>
<pre><code class="language-php">&lt;?php
namespace plugins\demo\controller;

use ZhiCms\base\ThinkTemplate;   // 注意：插件默认用 think-template 引擎渲染自有模板

class DemoController
{
    protected $vars = array();
    protected $alias = 'demo';
    protected $isMobile = null;

    protected function isMobile()
    {
        if ($this-&gt;isMobile !== null) return $this-&gt;isMobile;
        // 简化：直接用 UA 判断（可参考 guangdiu 支持 ?pc=1 / ?m=1 强制切换）
        $ua = strtolower($_SERVER['HTTP_USER_AGENT'] ?? '');
        $this-&gt;isMobile = (bool) preg_match('/iphone|android|mobile|micromessenger/i', $ua);
        return $this-&gt;isMobile;
    }

    protected function assign($name, $value = null)
    {
        if (is_array($name)) { foreach ($name as $k=&gt;$v) $this-&gt;vars[$k]=$v; }
        else { $this-&gt;vars[$name] = $value; }
        return $this;
    }

    /**
     * 渲染插件私有模板 plugins/demo/view/{tpl}.html
     * 注意：display() 内必须 exit，防止框架再输出。
     */
    protected function display($tpl = 'index', $extra = array())
    {
        $config = \ZhiCms\base\Config::get('TPL');
        $viewPath = \BASE_PATH . 'plugins/' . $this-&gt;alias . '/view/';

        $tplConfig = array_merge((array)$config, array(
            'TPL_PATH'     =&gt; $viewPath,
            'view_path'    =&gt; $viewPath,
            'TPL_SUFFIX'  =&gt; '.html',
            'view_suffix' =&gt; 'html',
        ));
        $engine = new ThinkTemplate($tplConfig);

        // 注入控制器 public 属性 + $this-&gt;vars + 公共站点变量
        foreach (get_object_vars($this) as $k =&gt; $v) {
            if ($k === 'vars') continue;
            $engine-&gt;assign($k, $v);
        }
        foreach ($this-&gt;vars as $k =&gt; $v) { $engine-&gt;assign($k, $v); }
        foreach ((array)$extra as $k =&gt; $v) { $engine-&gt;assign($k, $v); }

        // 注入常用站点变量，供模板使用
        $base = obj('base/Base');
        $engine-&gt;assign('site_name', $base-&gt;SiteConfig('sitename'));
        $engine-&gt;assign('copyright', $base-&gt;SiteConfig('banquan'));
        $engine-&gt;assign('plug_static', '/plugins/' . $this-&gt;alias . '/static');
        $engine-&gt;assign('is_mobile', $this-&gt;isMobile() ? 1 : 0);

        $engine-&gt;display($tpl);   // 渲染 plugins/demo/view/{tpl}.html
        exit;
    }

    protected function arg($name = null, $default = null)
    {
        static $args;
        if (!$args) { $args = array_merge((array)$_GET, (array)$_POST); }
        if ($name === null) return $args;
        if (!isset($args[$name])) return $default;
        $v = $args[$name];
        if (is_array($v)) { array_walk($v, function(&amp;$x){ $x=trim(htmlspecialchars($x, ENT_QUOTES)); }); return $v; }
        return trim(htmlspecialchars($v, ENT_QUOTES));
    }

    protected function db() { return obj('api/ApiData'); }
}</code></pre>
<h3>7.4 业务控制器 SiteController（真实逻辑写这）</h3>
<pre><code class="language-php">&lt;?php
namespace plugins\demo\controller;

class SiteController extends DemoController
{
    /** 统一入口：按 $params['mod'] 分发 */
    public function run($params)
    {
        $mod = isset($params['mod']) ? $params['mod'] : '';
        switch ($mod) {
            case 'detail': $this-&gt;detail($params); break;
            case 'cheaps': $this-&gt;cheaps(); break;
            case 'brand':  $this-&gt;brand(); break;
            default:       $this-&gt;index();
        }
    }

    public function index()
    {
        $list = $this-&gt;db()-&gt;dataSelect('yun_article', array("`status` = 1"), '`id` DESC LIMIT 0,20');
        $this-&gt;assign('list', $list ?: array());
        $this-&gt;assign('page_title', '首页 - Demo');
        $this-&gt;display('index');
    }

    public function detail($params)
    {
        $id = isset($params['id']) ? intval($params['id']) : 0;
        $row = $this-&gt;db()-&gt;dataSelect('yun_article', array("`id` = $id", "`status` = 1"));
        if (empty($row)) { header('HTTP/1.1 404 Not Found'); echo '内容不存在'; exit; }

        // 浏览量自增（访客去重）
        $vk = 'demo_view_' . $id;
        if (empty($_COOKIE[$vk])) {
            $this-&gt;db()-&gt;executeQuery("UPDATE `{pre}article` SET `view`=`view`+1 WHERE `id`=?", array($id));
            if (isset($row['view'])) $row['view'] = (int)$row['view'] + 1;
            setcookie($vk, '1', time()+3600, '/');
        }

        $this-&gt;assign('article', $row);
        $this-&gt;assign('page_title', $row['title']);
        $this-&gt;display('detail');
    }

    public function cheaps() { $this-&gt;assign('list', array()); $this-&gt;display('cheaps'); }
    public function brand()  { $this-&gt;assign('list', array()); $this-&gt;display('brand'); }
}</code></pre>
<h3>7.5 模板（plugins/demo/view/）</h3>
<p><code>index.html</code>：</p>
<pre><code class="language-html">{include file="plugins/demo/view/header"}
&lt;div class="container"&gt;
  {foreach $list as $item}
    &lt;div class="gd-post"&gt;
      &lt;a href="{plug_url}-{$item.id}.html"&gt;{$item.title}&lt;/a&gt;
      &lt;span&gt;人气：{$item.view}&lt;/span&gt;
    &lt;/div&gt;
  {/foreach}
&lt;/div&gt;
{include file="plugins/demo/view/footer"}</code></pre>
<blockquote>
<p>插件模板用 <strong>相对于插件根目录的 include 路径</strong>（<code>plugins/demo/view/header</code>），与框架前台模板 <code>app/index/view/public/header</code> 区分开。模板语法用 think-template 引擎（<code>{foreach}</code> / <code>{$x.y}</code> / <code>{include}</code>），与 TEMPLATE_DEV.md 第 3 章通用语法一致。</p>
</blockquote>
<h3>7.6 设为站点首页（home_plug）</h3>
<p>后台「系统设置 → 站点设置 → 主页展示插件」下拉选择 <code>demo</code> 后，系统把 <code>site.home_plug</code> 存为 <code>demo</code>。框架 <code>ZhiCms\base\App::applyHomePlug()</code> 在访问 <code>/</code>、<code>/index.php</code>、<code>/index.html</code> 时，自动把路由改写为 <code>index/plug/view/alias=demo</code>（<strong>URL 不变</strong>，用户看到的还是首页地址）。</p>
<p>前提：</p>
<ol>
<li><code>plugin.json</code> 的 <code>type=template</code> 且 <code>rewrite</code> 含 <code>plug-&lt;alias&gt;.html</code>。</li>
<li>插件已启用。</li>
<li>站点伪静态 <code>REWRITE_ON=1</code>（仅伪静态访问需要；动态 <code>index.php</code> 始终可走）。</li>
</ol>
<h3>7.7 伪静态规则注意</h3>
<ul>
<li><strong>占位符</strong>：规则里用 <code>&lt;key&gt;</code>，映射里对应 <code>key=&lt;key&gt;</code>。<code>&lt;id&gt;</code> 仅允许数字；其余 <code>[\w%-]+</code>。</li>
<li><strong>顺序</strong>：框架按「占位符越少越靠前」合并（具体见 <code>PluginManager::boot()</code>），<strong>字面量越具体的规则（占位符少的）排在前面</strong>。例如 <code>plug-&lt;alias&gt;-cheaps.html</code>（0 个动态占位符，cheaps 是字面量）必须排在 <code>plug-&lt;alias&gt;-&lt;id&gt;.html</code>（1 个占位符）之前，否则 <code>plug-demo-123.html</code> 会被 cheaps 规则误匹配。</li>
<li>修改 <code>rewrite</code> 后：<strong>停用再启用插件</strong>（触发 <code>PluginManager::clearBoot()</code> 重新合并规则），并清 <code>runtime/cache</code> + <code>runtime/static_cache</code>。</li>
</ul>
<h3>7.8 链接生成</h3>
<pre><code class="language-php">// 插件内
echo $this-&gt;pageUrl(array('id' =&gt; 123));   // plug-demo-123.html（伪静态开）/ index.php?r=index/plug/view&amp;alias=demo&amp;id=123
echo $this-&gt;pageUrl(array('mod' =&gt; 'cheaps')); // plug-demo-cheaps.html

// 模板里（已由 display() 注入 plug_url 变量）
&lt;a href="{$plug_url}-{$item.id}.html"&gt;详情&lt;/a&gt;</code></pre>
<hr />
<h2>8. 后台菜单 / 设置页 / 首页接管 汇总</h2>
<h3>8.1 后台菜单注入</h3>
<p><code>plugin.json</code> 的 <code>menu</code> 配置后，插件启用时菜单自动注入后台侧边栏「扩展功能」：</p>
<pre><code class="language-json">"menu": [ { "title": "插件设置", "url": "index.php?r=manage/plugin/setting&amp;alias=my_plugin" } ]</code></pre>
<h3>8.2 设置页（Setting.php）</h3>
<p><code>hasSetting: true</code> 时提供 <code>Setting.php</code>（<code>plugins\{alias}\Setting</code>），含 <code>view()</code>（返回 HTML 字符串）与 <code>save($data)</code>（返回要落库的数组）。系统自动把 <code>save()</code> 结果写入 <code>yun_plug.config</code>。</p>
<h3>8.3 首页接管（仅模板化）</h3>
<p>见第 7.6 节。</p>
<hr />
<h2>9. 打包与安装</h2>
<ol>
<li>将插件目录打成 <strong>ZIP</strong>，压缩包根目录应直接包含 <code>{alias}/</code> 文件夹（包内路径 <code>demo/plugin.json</code>）。</li>
<li>后台「系统 → 插件管理 → 上传插件」，选 ZIP。</li>
<li>上传后点「安装」：执行 <code>install.sql</code> → 调 <code>install()</code> → 写 <code>yun_plug</code> 注册表 → 启用。</li>
<li>可「启用 / 停用 / 卸载」（卸载可选删除文件）。</li>
</ol>
<blockquote>
<p>支持 <code>.zba</code>（Z-Blog 格式）与 <code>__MACOSX</code> 元目录自动排除。ZIP 多层嵌套会被规范化。</p>
</blockquote>
<h3>9.1 插件注册表</h3>
<p>插件信息存于 <code>{pre}plug</code> 表：</p>
<table>
<thead>
<tr>
<th>字段</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>alias</code></td>
<td>插件别名</td>
</tr>
<tr>
<td><code>name</code> / <code>version</code> / <code>author</code></td>
<td>元信息</td>
</tr>
<tr>
<td><code>status</code></td>
<td>1=启用 0=停用</td>
</tr>
<tr>
<td><code>installed</code></td>
<td>1=已安装</td>
</tr>
<tr>
<td><code>config</code></td>
<td>插件配置（JSON 文本，Setting::save 写入）</td>
</tr>
<tr>
<td><code>addtime</code></td>
<td>安装时间</td>
</tr>
</tbody>
</table>
<hr />
<h2>10. 开发建议与注意事项</h2>
<h3>10.1 通用</h3>
<ul>
<li><strong>不要改框架核心文件</strong>，只通过钩子/插件扩展，避免升级被覆盖。</li>
<li><strong>命名空间</strong>：入口 <code>plugins\{alias}\Plugin</code>、设置 <code>plugins\{alias}\Setting</code>，类名固定。</li>
<li><strong><code>register()</code> 每次请求执行</strong>，钩子注册要轻量，重活在回调里按需做。</li>
<li><strong><code>{pre}</code> 表前缀</strong>：SQL 里统一用 <code>{pre}</code>，不要写死 <code>yun_</code>。</li>
<li><strong>配置读写</strong>：用 <code>getConfig()/setConfig()</code>，不要直接改 <code>yun_plug</code> 表。</li>
<li><strong>出错防护</strong>：钩子回调里 try/catch，单插件错误不应拖垮整站。</li>
</ul>
<h3>10.2 模板化插件（类型 C）特有</h3>
<ul>
<li><strong><code>display()</code> 必须 <code>exit</code></strong>：否则框架会继续输出默认布局，导致页面重复/错乱。</li>
<li><strong>模板根目录</strong>：<code>display()</code> 里的 <code>TPL_PATH</code> 必须指向 <code>plugins/{alias}/view/</code>，否则找不到模板。</li>
<li><strong>include 路径</strong>：插件模板 include 插件自己的片段用 <code>plugins/demo/view/header</code>，与前台 <code>app/index/view/public/header</code> 区分。</li>
<li><strong>引擎选择</strong>：插件自有模板建议用 think-template 引擎（与 guangdiu/kiees 一致），语法见 TEMPLATE_DEV.md 第 3/5 章。</li>
<li><strong>移动端</strong>：<code>isMobile()</code> 自行实现（参考 guangdiu 支持 <code>?pc=1</code>/<code>?m=1</code> 强制切换 + cookie 记忆）。</li>
<li><strong>静态资源</strong>：用 <code>{plug_static}</code>（由 display 注入为 <code>/plugins/{alias}/static</code>）引用，避免硬编码。</li>
<li><strong>SEO / 版权</strong>：模板里用 <code>obj('base/Base')-&gt;SiteConfig('sitename'/'banquan'/'beian')</code> 取站点配置，保持与主站一致。</li>
</ul>
<h3>10.3 数据库插件（类型 B）特有</h3>
<ul>
<li>建表用 <code>install.sql</code>（<code>{pre}</code> 占位），卸载用 <code>uninstall()</code> 里 <code>DROP TABLE</code> 或 <code>uninstall.sql</code>。</li>
<li>表名 <code>yun_</code> 前缀，与框架一致。</li>
<li>用 <code>insertData/dataSelect/dataUpdate/deleteThis</code> 封装；复杂 SQL 用 <code>thisQuery/executeQuery</code> 并<strong>参数化</strong>。</li>
<li>大数据量用 <code>insertAllData()</code> 批量插；分页用 <code>dataCount()</code> + <code>page()</code>。</li>
</ul>
<h3>10.4 最小可运行插件清单</h3>
<ul>
<li>[ ] <code>plugin.json</code>（alias 与目录一致）</li>
<li>[ ] <code>Plugin.php</code>（继承 BasePlugin，必要逻辑在 <code>register()</code> 或 <code>displayPage()</code>）</li>
<li>[ ] 依赖 DB：补充 <code>install.sql</code> + CRUD</li>
<li>[ ] 模板化：补充 <code>rewrite</code> + 控制器 + <code>view/</code> 模板 + <code>display()</code> 内 <code>exit</code></li>
<li>[ ] 有设置：<code>Setting.php</code></li>
<li>[ ] 安装后清 <code>runtime/cache</code> + <code>runtime/static_cache</code> 验证</li>
</ul>
<hr />
<p><em>本文档基于 ZhiCms 插件系统实现（参考 <code>plugins/guangdiu</code>、<code>plugins/kiees</code> 真实代码）编写，覆盖三类插件（无数据库 / 依赖数据库 / 模板化接管前台）的目录结构、写法、伪静态、首页接管与打包安装。</em></p>]]></description>
    <pubDate>Sat, 08 Aug 2026 21:02:57 +0800</pubDate>
    <dc:creator>ZhiCms</dc:creator>
    <guid>https://www.zhi.red/plugin_dev.do</guid>
</item>
<item>
    <title>ZhiCms5.0.0-5.0.1-5.0.2</title>
    <link>https://www.zhi.red/zhicms502.do</link>
    <description><![CDATA[<blockquote>
<p>专业的电商导购 CMS 系统 · 自研 MVC 框架 · 开箱即用<br />
演示地址：<a href="http://v5.zhicms.cc">http://v5.zhicms.cc</a><br />
下载地址：<a href="https://www.zhi.red/d/zhicms.zip">https://www.zhi.red/d/zhicms.zip</a><br />
代码仓库：<a href="https://gitee.com/dazensun/zhicms">https://gitee.com/dazensun/zhicms</a><br />
版本：5.0.0-5.0.1-5.0.2<br />
升级方式：下载5.0.0_5.0.2压缩包，上传文件到网站根目录，运行 <code>5.0.0_5.0.2_update.php</code>（远程一键升级）或后台「在线升级」/「文件校对-在线升级」<br />
数据库：升级脚本会自动执行 <code>zhicms_update.sql</code>，需执行后到【文件校对】重建基线<br />
<a href="https://www.zhi.red/?resource_alias=bkrf1kOnaGDxqw2I&amp;resource_filename=1b2e1785741530">5.0.0_5.0.2_update.zip</a></p>
</blockquote>
<hr />
<h2>一、新增功能</h2>
<h3>1. 用户中心（扁平风格，全新）</h3>
<ul>
<li>新增 <code>app/index/controller/UcenterController.php</code> 与 <code>app/index/view/ucenter/index.html</code></li>
<li>左侧菜单 + 右侧内容的会员中心风格布局，含：
<ul>
<li><strong>我的收藏</strong>（社区帖子 / 文章，可切换）</li>
<li><strong>我的评论</strong></li>
<li><strong>我的帖子</strong></li>
<li><strong>个人资料</strong>（改昵称 / 邮箱）</li>
<li><strong>修改密码</strong>（验证原密码）</li>
<li><strong>退出登录</strong></li>
</ul></li>
<li>用户中心 5 个页面全部兼容 PC 与移动端</li>
</ul>
<h3>2. 用户系统完整化（注册/登录）</h3>
<ul>
<li>完善 <code>app/index/controller/LoginController.php</code> 与登录/注册页</li>
<li>登录页、注册页（含图形验证码）</li>
<li>前端显示登录用户信息（侧栏用户卡片）</li>
<li>游客/登录态切换、退出登录返回首页</li>
</ul>
<h3>3. AI 机器人登录态集成</h3>
<ul>
<li>AI 助手面板顶部新增「当前对话身份」状态条（方案 A）</li>
<li>登录用户历史归属（方案 B）：登录后 AI 历史延续到该用户</li>
<li>游客模式提示&quot;对话仅存于本机&quot;</li>
</ul>
<h3>4. 后台伪静态规则补充</h3>
<ul>
<li><code>data/config/rule.php</code> 新增规则：
<ul>
<li><code>login.html</code>、<code>register.html</code></li>
<li><code>ucenter.html</code>、<code>ucenter-comment.html</code>、<code>ucenter-forum.html</code>、<code>ucenter-profile.html</code>、<code>ucenter-pwd.html</code></li>
</ul></li>
<li>升级时<strong>保留用户伪静态开关设置</strong>（开/关不被覆盖），并合并新规则</li>
</ul>
<h3>5. 前端资源整合（精简）</h3>
<ul>
<li>新增 <code>public/web/css/common.css</code>（公共组件：表单/按钮/toast/用户中心）</li>
<li>新增 <code>public/web/css/forum.css</code>（论坛模块样式）</li>
<li>新增 <code>public/web/js/common.js</code>（userLogout/showToast 全局函数）</li>
<li>移除模板内联样式/脚本，改用外链可缓存文件</li>
<li>带版本参数 <code>?v=5.0.2</code> 便于缓存刷新</li>
</ul>
<hr />
<h2>二、Bug 修复</h2>
<h3>1. 后台相关</h3>
<ul>
<li><strong>添加分类&quot;请求异常&quot;</strong>：<code>FindController::addType/editType</code> 排序字段 <code>px</code> 空值触发 MySQL 严格模式报错，已修复并统一用 <code>exit+try/catch</code> 返回纯净 JSON</li>
<li><strong>商品采集 <code>date()</code> 报错</strong>：<code>ZhiCms/ext/Tjk/Hdk.php</code> 采集时把 API 返回的时间字符串直接传 <code>date()</code>，PHP8 报类型错误，新增 <code>safeTime()</code> 安全转换</li>
<li><strong>资讯采集&quot;入库 0 条&quot;</strong>：<code>newsCollect</code> 用 <code>arg()</code> 获取 JSON 被 htmlspecialchars 破坏，改用 <code>$_POST</code> 原始值 + html_entity_decode；map 为空时明确提示</li>
<li><strong>后台弹窗不显示</strong>：<code>.d-none</code>（display:none!important）无法被内联 display:flex 覆盖，打开弹窗时移除 <code>.d-none</code> 类</li>
<li><strong>后台缺失方法</strong>：<code>FindController::del</code>、<code>ManageController::edit/del/setpass</code> 补充</li>
<li><strong>Union 版块表不一致</strong>：<code>type</code> 列表查 <code>yun_bankuai</code> 但增删改操作 <code>yun_group</code>，统一改为 <code>yun_bankuai</code></li>
<li><strong>在线升级&quot;返回数据异常&quot;</strong>：改用 <code>Http::doGet</code> 稳健请求 + 容错 JSON 解析 + 防缓存</li>
<li><strong>升级脚本</strong>：增强重复列/索引错误容错，配置文件智能合并（保留用户设置）</li>
</ul>
<h3>2. 前端相关</h3>
<ul>
<li>登录后首页仍显示登录/注册：<code>resolveLoginUser</code> 用 <code>$rows[0]</code> 取错（dataSelect 无 order 返回单数组），已修复</li>
<li>登录/注册页 CSS 不生效：站点无 Bootstrap，补充 Bootstrap 兼容样式</li>
<li>登录成功提示在底部（JS 穿透）：改自定义 toast 弹窗</li>
<li>侧栏登录按钮悬停变橘色：<code>.btn-primary:hover</code> 明确 <code>color:#fff</code></li>
<li>退出登录不返回首页：改为跳转首页</li>
<li>用户中心底部友情链接/版权不输出：footer 直接查库 + 版权兜底</li>
</ul>
<h3>3. 深色模式</h3>
<ul>
<li>首页资讯标题 dark 下看不清：移除模板内联硬编码深色，改用 CSS 变量</li>
<li>右下角主题切换按钮 dark 下不可见：提亮背景/边框/阴影</li>
<li>common.css、forum.css 补充 <code>[data-theme="dark"]</code> 适配</li>
</ul>
<h3>4. 移动端</h3>
<ul>
<li>用户中心 <code>uc-layout</code> 移动端垂直排列（避免挤压）</li>
<li>确认首页/论坛/底部导航等移动端适配</li>
</ul>
<hr />
<h2>三、数据库变更（zhicms_update.sql）</h2>
<pre><code class="language-sql">-- yun_user 表新增用户系统字段
ALTER TABLE yun_user ADD COLUMN email/avatar/reg_time/reg_ip/login_ip/status;
-- yun_user 手机号唯一索引
ALTER TABLE yun_user ADD UNIQUE KEY uk_mobile (mobile);
-- yun_mall 新增所属联盟模型字段
ALTER TABLE yun_mall ADD COLUMN union_id;
-- yun_config 用户功能开关默认值
user_reg_captcha / user_email_verify / user_show_login
-- 版本号更新为 5.0.2</code></pre>
<blockquote>
<p>全新安装：<code>data/config/zhicms.sql</code> 已同步这些字段，安装即为 5.0.2</p>
</blockquote>
<hr />
<h2>四、更新机制保护</h2>
<ul>
<li>升级时<strong>不会覆盖</strong>用户设置：
<ul>
<li><code>db.php</code>（数据库配置）</li>
<li><code>siteconfig.php</code> / <code>seo.php</code> / <code>sms.php</code> / <code>apiset.php</code> / <code>global.php</code>（站点配置，用户设置优先）</li>
<li><code>rule.php</code>（伪静态开关 REWRITE_ON 保留用户开/关，规则合并）</li>
</ul></li>
<li>后台「一键恢复整站」同样保护上述配置</li>
</ul>
<hr />
<h2>五、升级包内容</h2>
<p><code>full_update_5.0.2.zip</code> 共 46 个文件，覆盖：</p>
<ul>
<li>前端：用户中心、AI、登录注册、公共模板/样式/脚本</li>
<li>后台：多个控制器与视图的修复</li>
<li>框架：<code>ZhiCms/core.php</code>（obj() 递归保护）、<code>Hdk.php</code>（date 修复）</li>
<li>数据库：<code>zhicms_update.sql</code>、<code>zhicms.sql</code></li>
<li>升级脚本：<code>5.0.0_5.0.2_update.php</code></li>
</ul>
<blockquote>
<p>升级后建议：清除浏览器缓存（Ctrl+F5，因 CSS/JS 带版本参数）、后台【文件校对】重建基线</p>
</blockquote>]]></description>
    <pubDate>Mon, 03 Aug 2026 15:12:36 +0800</pubDate>
    <dc:creator>ZhiCms</dc:creator>
    <guid>https://www.zhi.red/zhicms502.do</guid>
</item>
<item>
    <title>关于后台对接大模型和AI应用</title>
    <link>https://www.zhi.red/ai.do</link>
    <description><![CDATA[<h1>对接大模型和 AI 应用</h1>
<h2>配置 AI</h2>
<p>最新版的zhicms系统(包括emlog、zblog、wortdpress插件)支持配置AI大模型，可以方便的对接 DeepSeek、OpenAI 等大模型，后台点击左侧系统菜单 - 设置 - AI 完成添加 AI 大模型即可开始体验对话、文本生成、图像生成等AI功能。</p>
<h2>文本对话模型</h2>
<p>系统支持添加 OpenAI 协议的大模型，知名大模型配置示例如下：</p>
<h3>智谱AI</h3>
<p>有不少免费模型可以用，<a href="https://www.bigmodel.cn/invite?icode=2efLIVKGlErOqNC6g1qv0mczbXFgPRGIalpycrEwJ28%3D">注册</a>送 GLM-4-Air 模型 2000万Tokens</p>
<ul>
<li><strong>API URL</strong>: <code>https://open.bigmodel.cn/api/paas/v4/chat/completions</code></li>
<li><strong>API Key</strong>: <a href="https://bigmodel.cn/usercenter/proj-mgmt/apikeys">生成api key</a></li>
<li><strong>Model</strong>:
<ul>
<li><code>glm-5.1</code></li>
<li><code>glm-4.7</code></li>
<li><code>glm-4.6</code></li>
<li><code>glm-4.5</code></li>
<li><code>glm-4-flash</code></li>
<li><code>glm-4-plus</code></li>
</ul></li>
<li><strong>免费Model</strong>：
<ul>
<li><code>glm-4.7-flash</code></li>
<li><code>glm-z1-flash</code></li>
<li><code>glm-4-flash</code></li>
</ul></li>
<li><a href="https://bigmodel.cn/console/modelcenter/square">更多模型</a></li>
</ul>
<h3>DeepSeek</h3>
<ul>
<li><strong>API URL</strong>: <code>https://api.deepseek.com/v1/chat/completions</code></li>
<li><strong>API Key</strong>: <a href="https://platform.deepseek.com/api_keys">生成api key</a>，格式如：<code>sk-****</code></li>
<li><strong>Model</strong>:
<ul>
<li><code>deepseek-v4-flash</code></li>
<li><code>deepseek-v4-pro</code></li>
</ul></li>
</ul>
<h3>硅基流动</h3>
<ul>
<li><strong>API URL</strong>: <code>https://api.siliconflow.cn/v1/chat/completions</code></li>
<li><strong>API Key</strong>: <a href="https://cloud.siliconflow.cn/i/YVKAoi2o">生成api key</a>，登录后左侧菜单 - API密钥 - 新建密钥</li>
<li><strong>Model</strong>:
<ul>
<li><code>THUDM/GLM-4-32B-0414</code></li>
<li><code>THUDM/GLM-Z1-Air-0414</code></li>
<li><code>Qwen/Qwen2.5-VL-32B-Instruct</code></li>
<li><code>Qwen/Qwen3-8B</code></li>
<li><code>deepseek-ai/DeepSeek-V3</code></li>
<li><code>deepseek-ai/DeepSeek-R1</code></li>
<li><code>Qwen/Qwen2.5-72B-Instruct</code></li>
</ul></li>
<li><strong>免费Model</strong>：
<ul>
<li><code>THUDM/GLM-4-9B-0414</code></li>
<li><code>THUDM/GLM-Z1-9B-0414</code></li>
<li><code>Qwen/Qwen3-8B</code></li>
<li><code>Qwen/Qwen2.5-7B-Instruct</code></li>
<li><code>deepseek-ai/DeepSeek-R1-Distill-Qwen-7B</code></li>
</ul></li>
<li><a href="https://cloud.siliconflow.cn/i/YVKAoi2o">更多模型</a> - 登录后左侧菜单 - 模型广场，可以筛选免费模型。</li>
</ul>
<h3>派欧云</h3>
<p>比较小众但是非常棒的 DeepSeek 服务。<a href="https://ppio.com/user/register?invited_by=N9XAUB">点击注册</a>即送 500万 token ，几乎可以免费用相当长时间了。</p>
<ul>
<li><strong>API URL</strong>: <code>https://api.ppinfra.com/v3/openai/v1/chat/completions</code></li>
<li><strong>API Key</strong>: <a href="https://ppinfra.com/settings/key-management">生成api key</a>，格式如：<code>sk-****</code></li>
<li><strong>Model</strong>:
<ul>
<li><code>deepseek/deepseek-v3/community</code></li>
</ul></li>
<li><a href="https://ppio.com/ai-computing/llm-api">更多模型</a></li>
</ul>
<h3>OpenRouter</h3>
<p>可以直连，有不少免费的模型，包括免费的 deepseek 模型。<a href="https://openrouter.ai/models">模型列表</a> 可以在模型列表中搜索 free 找到免费模型</p>
<ul>
<li><strong>API URL</strong>: <code>https://openrouter.ai/api/v1/chat/completions</code></li>
<li><strong>API Key</strong>: <a href="https://openrouter.ai/settings/keys">生成api key</a>，格式如：<code>sk-****</code></li>
<li><strong>Model</strong>:
<ul>
<li><code>deepseek/deepseek-chat:free</code></li>
<li><code>deepseek/deepseek-r1:free</code></li>
</ul></li>
<li><strong>免费Model</strong>：
<ul>
<li><code>qwen/qwen3-8b:free</code></li>
<li><code>thudm/glm-4-32b:free</code></li>
<li><code>google/gemini-2.0-flash:free</code></li>
</ul></li>
</ul>
<h3>阿里百炼 - 通义大模型</h3>
<ul>
<li><strong>API URL</strong>: <code>https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions</code></li>
<li><strong>API Key</strong>: <a href="https://bailian.console.aliyun.com/?apiKey=1#/api-key">生成api key</a>，格式如：<code>sk-****</code></li>
<li><strong>Model</strong>:
<ul>
<li><code>qwen3.5-plus</code></li>
<li><code>qwen3.5-flash</code></li>
<li><code>qwen-max</code></li>
<li><code>qwen-plus</code></li>
<li><code>qwen-turbo</code></li>
<li><code>qwen2.5-vl-72b-instruct</code></li>
<li><code>deepseek-v3</code></li>
</ul></li>
<li><a href="https://bailian.console.aliyun.com/?tab=model#/model-market/all">更多模型</a></li>
</ul>
<h3>Kimi - moonshot</h3>
<ul>
<li><strong>API URL</strong>: <code>https://api.moonshot.cn/v1/chat/completions</code></li>
<li><strong>API Key</strong>: <a href="https://platform.moonshot.cn/console/api-keys">生成api key</a>，格式如：<code>sk-****</code></li>
<li><strong>Model</strong>:
<ul>
<li><code>kimi-k2.6</code></li>
<li><code>kimi-k2.5</code></li>
<li><code>moonshot-v1-8k</code></li>
<li><code>moonshot-v1-32k</code></li>
<li><code>moonshot-v1-128k</code></li>
</ul></li>
<li><a href="https://platform.moonshot.cn/docs">更多模型</a></li>
</ul>
<h3>百度智能云</h3>
<ul>
<li><strong>API URL</strong>: <code>https://qianfan.baidubce.com/v2/chat/completions</code></li>
<li><strong>API Key</strong>: <a href="https://console.bce.baidu.com/iam/#/iam/apikey/list">生成api key</a>，创建API Key，服务选择：千帆ModelBuilder，资源选择：所有资源</li>
<li><strong>Model</strong>:
<ul>
<li><code>deepseek-v3</code></li>
<li><code>deepseek-r1</code></li>
<li><code>ERNIE-4.0-8K</code></li>
<li><code>ERNIE-4.0-Turbo-8K</code></li>
<li><code>ERNIE-3.5-8K</code></li>
<li><a href="https://cloud.baidu.com/doc/WENXINWORKSHOP/s/Fm2vrveyu">更多模型</a></li>
</ul></li>
</ul>
<h3>火山引擎 - 火山方舟（豆包AI）</h3>
<ul>
<li><strong>API URL</strong>: <code>https://ark.cn-beijing.volces.com/api/v3/chat/completions</code></li>
<li><strong>API Key</strong>: <a href="https://console.volcengine.com/ark/region:ark+cn-beijing/apiKey?apikey=%7B%7D">生成api key</a></li>
<li><strong>Model</strong>:
<ul>
<li><code>doubao-1-5-pro-32k-250115</code></li>
<li><code>doubao-1-5-thinking-pro-250115</code></li>
<li><code>deepseek-v3-250324</code></li>
<li><code>deepseek-r1-250324</code></li>
<li><a href="https://www.volcengine.com/docs/82379/1330310">更多模型</a>，填写对应的模型 ID（Model ID），需要先<a href="https://console.volcengine.com/ark/region:ark+cn-beijing/openManagement">开通模型</a></li>
</ul></li>
</ul>
<h3>OpenAI ChatGPT</h3>
<ul>
<li><strong>API URL</strong>: <code>https://api.openai.com/v1/chat/completions</code></li>
<li><strong>API Key</strong>: <a href="https://platform.openai.com/account/api-keys">生成api key</a>，格式如：<code>sk-****</code></li>
<li><strong>Model</strong>:
<ul>
<li><code>gpt-5.4-2025-12-18</code></li>
<li><code>gpt-5.4-thinking-2025-12-18</code></li>
<li><code>gpt-5.2-2025-10-31</code></li>
<li><code>gpt-5.2-thinking-2025-10-31</code></li>
<li><code>gpt-4.1-2025-04-14</code></li>
<li><code>gpt-4o-2024-11-20</code></li>
<li><code>gpt-4o-mini</code></li>
<li><code>o3-2025-04-16</code></li>
<li><code>o4-mini-2025-04-16</code></li>
<li><a href="https://platform.openai.com/docs/models">全部模型</a></li>
</ul></li>
</ul>
<h3>Google Gemini</h3>
<ul>
<li><strong>API URL</strong>: <code>https://generativelanguage.googleapis.com/v1beta/openai/chat/completions</code></li>
<li><strong>API Key</strong>: <a href="https://aistudio.google.com/app/apikey">生成api key</a></li>
<li><strong>Model</strong>:
<ul>
<li><code>gemini-3.0-pro</code></li>
<li><code>gemini-3.0-flash</code></li>
<li><code>gemini-2.5-pro</code></li>
<li><code>gemini-2.5-pro-preview-06-05</code></li>
<li><code>gemini-2.0-flash</code></li>
<li><code>gemini-2.0-flash-thinking</code></li>
</ul></li>
</ul>
<h3>Claude</h3>
<ul>
<li><strong>API URL</strong>: <code>https://api.anthropic.com/v1/messages</code></li>
<li><strong>API Key</strong>: <a href="https://console.anthropic.com/settings/keys">生成api key</a></li>
<li><strong>Model</strong>:
<ul>
<li><code>claude-4.6-opus-20251101</code></li>
<li><code>claude-4.6-sonnet-20251030</code></li>
<li><code>claude-4.5-sonnet-20241022</code></li>
<li><code>claude-3-7-sonnet-20250219</code></li>
<li><code>claude-3-5-haiku-20241022</code></li>
</ul></li>
</ul>
<h3>Grok</h3>
<ul>
<li><strong>API URL</strong>: <code>https://api.x.ai/v1/chat/completions</code></li>
<li><strong>API Key</strong>: <a href="https://console.x.ai/">生成api key</a></li>
<li><strong>Model</strong>:
<ul>
<li><code>grok-4.1-2025-11-14</code></li>
<li><code>grok-4-0709</code></li>
<li><code>grok-3</code></li>
<li><code>grok-3-fast</code></li>
<li><code>grok-3-mini</code></li>
</ul></li>
</ul>
<h2>图像生成模型</h2>
<h3>硅基流动</h3>
<ul>
<li><strong>API URL</strong>: <code>https://api.siliconflow.cn/v1/images/generations</code></li>
<li><strong>API Key</strong>: <a href="https://cloud.siliconflow.cn/me/account/ak">生成api key</a>，登录后左侧菜单 - API密钥 - 新建密钥</li>
<li><strong>Model</strong>:
<ul>
<li><code>black-forest-labs/FLUX.1-schnell</code></li>
<li><code>black-forest-labs/FLUX.1-dev</code></li>
<li><code>black-forest-labs/FLUX.1-pro</code></li>
<li><code>Kwai-Kolors/Kolors</code></li>
<li><code>stabilityai/stable-diffusion-3.5-large</code></li>
<li><code>stabilityai/stable-diffusion-xl-base-1.0</code></li>
</ul></li>
</ul>
<h3>火山引擎 - 豆包AI</h3>
<ul>
<li><strong>API URL</strong>: <code>https://ark.cn-beijing.volces.com/api/v3/images/generations</code></li>
<li><strong>API Key</strong>: <a href="https://console.volcengine.com/ark/region:ark+cn-beijing/apiKey?apikey=%7B%7D">生成api key</a></li>
<li><strong>Model</strong>:
<ul>
<li><code>doubao-seedream-3-0-t2i-250415</code></li>
<li><code>doubao-3d-250615</code></li>
<li><code>doubao-xl-250615</code></li>
</ul></li>
</ul>
<h3>OpenAI DALL-E</h3>
<ul>
<li><strong>API URL</strong>: <code>https://api.openai.com/v1/images/generations</code></li>
<li><strong>API Key</strong>: <a href="https://platform.openai.com/account/api-keys">生成api key</a>，格式如：<code>sk-****</code></li>
<li><strong>Model</strong>:
<ul>
<li><code>dall-e-3</code></li>
<li><code>gpt-image-1</code></li>
<li><code>gpt-image-1.5</code></li>
<li><code>gpt-image-1-mini</code></li>
</ul></li>
</ul>
<h3>Stability AI</h3>
<ul>
<li><strong>API URL</strong>: <code>https://api.stability.ai/v1/generation/stable-diffusion-xl-1024-v1-0/text-to-image</code></li>
<li><strong>API Key</strong>: <a href="https://platform.stability.ai/">生成api key</a></li>
<li><strong>Model</strong>:
<ul>
<li><code>stable-diffusion-xl-1024-v1-0</code></li>
<li><code>stable-diffusion-v1-6</code></li>
<li><code>stable-diffusion-2-1</code></li>
</ul></li>
</ul>
<h3>Replicate</h3>
<ul>
<li><strong>API URL</strong>: <code>https://api.replicate.com/v1/predictions</code></li>
<li><strong>API Key</strong>: <a href="https://replicate.com/account/api-tokens">生成api key</a></li>
<li><strong>Model</strong>:
<ul>
<li><code>black-forest-labs/flux-schnell</code></li>
<li><code>black-forest-labs/flux-dev</code></li>
<li><code>black-forest-labs/flux-pro</code></li>
<li><code>stability-ai/sdxl</code></li>
<li><code>runwayml/stable-diffusion-v1-5</code></li>
</ul></li>
</ul>
<h3>Leonardo AI</h3>
<ul>
<li><strong>API URL</strong>: <code>https://cloud.leonardo.ai/api/rest/v1/generations</code></li>
<li><strong>API Key</strong>: <a href="https://leonardo.ai/">生成api key</a></li>
<li><strong>Model</strong>:
<ul>
<li><code>leonardo-diffusion-xl</code></li>
<li><code>leonardo-vision-xl</code></li>
<li><code>albedo-base-xl</code></li>
</ul></li>
</ul>
<h2>AI 功能</h2>
<p>配置好 AI 模型，就可以使用 zhicms 系统的 AI 功能了。</p>
<ul>
<li>后台AI对话功能：在后台右下角会出现AI 对话图标 ✨ 点击即可随时和AI对话。</li>
<li>AI生成个性签名：在个人资料页，修改个人描述时可以点击 ✨ 按钮，以让AI生成签名</li>
<li>AI回复评论，在回复评论界面可以点击 ✨ 按钮，以让AI回复评论</li>
</ul>
<h2>常见问题</h2>
<h3>AI 对话反应慢是什么原因？</h3>
<ol>
<li>可能是AI模型提供商的问题，可以尝试更换其他服务商的AI模型试试。</li>
<li>可能是服务器网络问题，AI接口要通过服务器中转请求，如果网络不稳定，会造成延迟。</li>
</ol>
<h3>后台AI对话如何开启打字机效果输出？</h3>
<p>检查修改以下 PHP 配置项（宝塔面板进入 PHP 管理 - 配置文件，搜索配置项）</p>
<ul>
<li><code>output_buffering = Off</code></li>
<li><code>zlib.output_compression = Off</code></li>
</ul>
<p>检查修改以下 nginx 配置项（宝塔面板进入 nginx 管理 - 配置修改，搜索配置项）</p>
<ul>
<li><code>fastcgi_keep_conn on;</code></li>
</ul>]]></description>
    <pubDate>Mon, 27 Jul 2026 19:58:13 +0800</pubDate>
    <dc:creator>ZhiCms</dc:creator>
    <guid>https://www.zhi.red/ai.do</guid>
</item>
<item>
    <title>zhicms插件wordpress安装和使用说明</title>
    <link>https://www.zhi.red/wordpress.do</link>
    <description><![CDATA[<h1>ZhiCms 产品库 — WordPress 版插件说明</h1>
<h2>一、插件简介</h2>
<p>ZhiCms 产品库是一款集<strong>联盟商品搜索、选品采集、商品卡片展示、AI 导购助手</strong>于一体的 WordPress 插件。支持对接大淘客和好单库两大联盟 API，覆盖淘宝/天猫、京东、拼多多、唯品会四大主流电商平台，帮助站长快速搭建好物推荐内容。</p>
<p>此外，插件内置 <strong>WordPress 性能优化模块</strong>，可自动移除多个无用功能，有效加速网站加载速度。</p>
<ul>
<li><strong>版本</strong>：1.0.0</li>
<li><strong>作者</strong>：ZhiCms</li>
<li><strong>许可</strong>：GPL v2 or later</li>
<li><strong>最低 PHP</strong>：5.6</li>
<li><strong>支持 PHP</strong>：5.6 ~ 8.4</li>
<li><strong>演示地址</strong>：<a href="http://wp.zhicms.cc">http://wp.zhicms.cc</a></li>
<li><strong>下载地址</strong>：<a href="https://www.zhicms.cc/d/wordpress/zhicms.zip">https://www.zhicms.cc/d/wordpress/zhicms.zip</a></li>
</ul>
<hr />
<h2>二、核心功能</h2>
<h3>1. 联盟库商品搜索</h3>
<p>接入大淘客 + 好单库双 API，支持跨平台搜索淘宝、京东、拼多多、唯品会商品。搜索结果自动合并去重，按销量排序。</p>
<h3>2. 选品采集入库</h3>
<ul>
<li><strong>单条采集</strong>：将联盟库商品一键收录到本地选品库</li>
<li><strong>批量采集</strong>：输入关键词，可选采集平台（全部/淘宝/京东/拼多多/唯品会）和数量（10/20/50 条）</li>
<li>弹窗式操作界面，实时反馈采集结果</li>
</ul>
<h3>3. 选品库管理</h3>
<p>进入后台 → 产品库，可管理本地商品库：</p>
<ul>
<li>表格化管理，显示商品图、标题、平台、价格、销量</li>
<li>关键词搜索</li>
<li>商品置顶 / 取消置顶</li>
<li>删除商品</li>
<li>一键复制短代码</li>
<li>清理过期优惠券商品</li>
<li>分页浏览</li>
<li>后台首页统计卡片（各平台商品数量可视化）</li>
</ul>
<h3>4. 商品卡片短代码</h3>
<p>两种短代码供灵活使用：</p>
<p><strong>商品卡片短代码</strong> — 在文章任意位置插入商品：</p>
<pre><code>[zhicmsurl id="商品ID" platform="taobao"]</code></pre>
<p>渲染为美观的商品卡片，含商品图、标题、价格、优惠券标签、销量、店铺名。</p>
<p><strong>产品库整页短代码</strong> — 在页面中嵌入完整产品库：</p>
<pre><code>[zhicms_page]</code></pre>
<p>适用于创建独立的好物推荐页面。</p>
<h3>5. 转链跳转</h3>
<p>用户点击商品卡片跳转到 <code>/zhicms/go/?id=xxx&amp;platform=xxx</code>，插件自动完成三级降级转链：</p>
<ol>
<li>通过转链接口获取推广链接（含淘口令）</li>
<li>兜底查询本地选品库</li>
<li>最后调用商品详情 API 获取链接</li>
</ol>
<h3>6. 前端产品库页面</h3>
<p>独立访问地址 <code>/zhicms/</code>（Rewrite Rule 虚拟页面），也可通过 <code>[zhicms_page]</code> 短代码嵌入任意页面。支持：</p>
<ul>
<li>淘宝 / 京东 / 拼多多 / 唯品会分平台筛选</li>
<li>关键词搜索</li>
<li>选品库（本地）/ 联盟库（实时）双数据源切换</li>
<li>REST API 驱动的异步加载</li>
</ul>
<h3>7. AI 导购助手</h3>
<p>启用后在所有页面右下角显示悬浮机器人按钮，用户点击即可对话：</p>
<ul>
<li><strong>购物咨询</strong>：智能识别购买意图，自动搜索商品并展示卡片</li>
<li><strong>闲聊模式</strong>：非购物类问题调用 AI 大模型回复，语气亲切</li>
<li><strong>商品推荐</strong>：先查选品库，再查联盟库，找不到才走 AI</li>
<li><strong>对话历史</strong>：按用户 Cookie 保存最近对话，下次访问自动恢复</li>
<li><strong>快捷问题</strong>：预设多组购物问题，点击即可快速提问，支持换一批</li>
<li><strong>移动端适配</strong>：响应式设计，手机端自动缩小面板尺寸</li>
</ul>
<h3>8. 编辑器按钮</h3>
<p>在文章编辑页面，编辑器上方出现「插入商品」按钮：</p>
<ul>
<li>支持 <strong>Gutenberg 块编辑器</strong>（自动插入 shortcode 块）</li>
<li>支持 <strong>Classic Editor 经典编辑器</strong>（TinyMCE 插入）</li>
<li>选品库 / 联盟库双 Tab 切换</li>
<li>一键插入短代码或采集商品</li>
</ul>
<h3>9. WordPress 性能优化（内置）</h3>
<p>插件激活后自动启用以下优化，无需额外配置：</p>
<ul>
<li>移除 CSS/JS 链接中的版本号参数（利于缓存）</li>
<li>移除 WordPress 版本号输出（安全加固）</li>
<li>移除 Emoji 脚本和样式（减少 HTTP 请求）</li>
<li>移除 RSS Feed 链接</li>
<li>移除 WLW Manifest / RSD / 短链接</li>
<li>移除 DNS Prefetch</li>
<li>限制文章修订版本数为 0（减少数据库膨胀）</li>
<li>禁用自动保存功能</li>
<li>上传文件自动随机重命名（防止中文文件名和路径猜测）</li>
<li>保留 REST API 核心功能（zhicms 前端搜品依赖）</li>
</ul>
<hr />
<h2>三、安装说明</h2>
<h3>方法一：后台上传</h3>
<ol>
<li>下载插件压缩包 <code>zhicms.zip</code></li>
<li>进入 WordPress 后台 → 插件 → 安装插件 → 上传插件</li>
<li>选择 zip 文件，点击「现在安装」</li>
<li>安装完成后点击「启用」</li>
</ol>
<h3>方法二：手动上传</h3>
<ol>
<li>将插件文件夹 <code>zhicms</code> 上传到 <code>/wp-content/plugins/</code> 目录</li>
<li>进入 WordPress 后台 → 插件，找到「ZhiCms 产品库」点击启用</li>
</ol>
<h3>首次激活</h3>
<p>插件激活时自动完成以下操作：</p>
<ul>
<li>创建商品数据表（<code>wp_zhicms_items</code>）</li>
<li>写入默认配置项</li>
<li>刷新固定链接（Rewrite Rules）</li>
</ul>
<h3>卸载</h3>
<p>停用插件后，如需完全卸载，删除插件文件夹即可。停用时会自动刷新固定链接。</p>
<hr />
<h2>四、插件设置</h2>
<p>进入后台 → 产品库 → 设置。</p>
<h3>API 密钥配置</h3>
<table>
<thead>
<tr>
<th>配置项</th>
<th>说明</th>
<th style="text-align: center;">必填</th>
</tr>
</thead>
<tbody>
<tr>
<td>大淘客 AppKey</td>
<td>大淘客开放平台的应用 Key</td>
<td style="text-align: center;">否*</td>
</tr>
<tr>
<td>大淘客 AppSecret</td>
<td>大淘客开放平台的应用 Secret</td>
<td style="text-align: center;">否*</td>
</tr>
<tr>
<td>大淘客 PID</td>
<td>淘宝联盟推广位 ID，用于佣金归属</td>
<td style="text-align: center;">否</td>
</tr>
<tr>
<td>好单库 API Key</td>
<td>好单库开放平台的 API 密钥</td>
<td style="text-align: center;">否*</td>
</tr>
</tbody>
</table>
<blockquote>
<p>* 至少配置大淘客 AppKey+AppSecret 或好单库 ApiKey 其中一组，否则无法使用联盟搜索和采集功能。</p>
</blockquote>
<h3>AI 导购配置</h3>
<table>
<thead>
<tr>
<th>配置项</th>
<th>说明</th>
<th style="text-align: center;">必填</th>
</tr>
</thead>
<tbody>
<tr>
<td>启用 AI 导购</td>
<td>勾选后，网站所有页面右下角显示悬浮导购按钮</td>
<td style="text-align: center;">否</td>
</tr>
<tr>
<td>AI 接口地址</td>
<td>OpenAI 兼容 API 地址，例如 <code>https://api.openai.com/v1/chat/completions</code></td>
<td style="text-align: center;">启用时必填</td>
</tr>
<tr>
<td>API Key</td>
<td>AI 服务的 API 密钥（密码框）</td>
<td style="text-align: center;">启用时必填</td>
</tr>
<tr>
<td>模型名称</td>
<td>使用的模型，默认 <code>gpt-3.5-turbo</code>，支持 <code>gpt-4</code>、<code>deepseek-chat</code> 等</td>
<td style="text-align: center;">启用时必填</td>
</tr>
<tr>
<td>系统提示词</td>
<td>自定义 AI 导购角色设定，留空使用默认提示词（推荐）</td>
<td style="text-align: center;">否</td>
</tr>
</tbody>
</table>
<h3>固定链接设置</h3>
<p>插件使用了自定义 Rewrite Rules（<code>/zhicms/</code> 和 <code>/zhicms/go/</code>），请确保 WordPress 固定链接设置为<strong>非「朴素」模式</strong>。如果访问 <code>/zhicms/</code> 404，进入设置 → 固定链接，点击「保存更改」即可刷新规则。</p>
<hr />
<h2>五、API 密钥获取</h2>
<h3>大淘客开放平台</h3>
<ol>
<li>访问 <a href="https://www.dataoke.com/">https://www.dataoke.com/</a> 注册账号</li>
<li>进入开放平台控制台 → 应用管理，创建应用</li>
<li>获取 AppKey 和 AppSecret 填入插件</li>
<li>（可选）在淘宝联盟后台获取 PID（推广位），填入插件用于佣金归属</li>
</ol>
<h3>好单库开放平台</h3>
<ol>
<li>访问 <a href="https://www.haodanku.com/">https://www.haodanku.com/</a> 注册账号</li>
<li>进入个人中心 → API 管理</li>
<li>获取 ApiKey 填入插件</li>
</ol>
<h3>AI 大模型 (OpenAI 兼容接口)</h3>
<ol>
<li><strong>OpenAI 官方</strong>：访问 <a href="https://platform.openai.com/">https://platform.openai.com/</a> 注册并获取 API Key</li>
<li><strong>国产模型</strong>：支持 DeepSeek、通义千问、智谱 GLM 等兼容 OpenAI 接口格式的服务</li>
<li>将 API 地址和 Key 填入插件设置即可</li>
</ol>
<hr />
<h2>六、REST API 接口</h2>
<p>插件提供 REST API 供前端页面调用（不影响已禁用的 WordPress 默认 REST 端点）。</p>
<h3>GET <code>/wp-json/zhicms/v1/products</code></h3>
<table>
<thead>
<tr>
<th>参数</th>
<th>类型</th>
<th>默认值</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>source</td>
<td>string</td>
<td>local</td>
<td>数据源：<code>local</code>（选品库）或 <code>api</code>（联盟库）</td>
</tr>
<tr>
<td>keyword</td>
<td>string</td>
<td>—</td>
<td>搜索关键词</td>
</tr>
<tr>
<td>page</td>
<td>int</td>
<td>1</td>
<td>页码</td>
</tr>
<tr>
<td>page_size</td>
<td>int</td>
<td>20</td>
<td>每页条数（最大 50）</td>
</tr>
<tr>
<td>platform</td>
<td>string</td>
<td>all</td>
<td>平台筛选：<code>all</code> / <code>taobao</code> / <code>jd</code> / <code>pdd</code> / <code>vip</code></td>
</tr>
</tbody>
</table>
<hr />
<h2>七、WordPress 性能优化说明</h2>
<p>插件内置 <code>ZhiCmsOptimize</code> 性能优化模块，激活后自动生效，移除以下 WordPress 默认功能以提升加载速度：</p>
<table>
<thead>
<tr>
<th>优化项</th>
<th>效果</th>
</tr>
</thead>
<tbody>
<tr>
<td>CSS/JS 版本号</td>
<td>移除 <code>?ver=x.x.x</code> 查询参数，利于浏览器和 CDN 缓存</td>
</tr>
<tr>
<td>版本 Generator</td>
<td>隐藏 WordPress 版本号，提升安全性</td>
</tr>
<tr>
<td>Emoji 脚本</td>
<td>减少 <code>wp-emoji-release.min.js</code> 等 2 个 HTTP 请求</td>
</tr>
<tr>
<td>Feed 链接</td>
<td>移除 head 中 RSS/Atom 订阅链接</td>
</tr>
<tr>
<td>WLW Manifest</td>
<td>移除 Windows Live Writer 支持链接</td>
</tr>
<tr>
<td>RSD 链接</td>
<td>移除 Really Simple Discovery 链接</td>
</tr>
<tr>
<td>短链接</td>
<td>移除 <code>wp_shortlink_wp_head</code></td>
</tr>
<tr>
<td>DNS Prefetch</td>
<td>移除 <code>wp_resource_hints</code> 的 dns-prefetch</td>
</tr>
<tr>
<td>文章修订</td>
<td>修订版本数设为 0，不保留历史修订</td>
</tr>
<tr>
<td>自动保存</td>
<td>取消自动保存脚本加载</td>
</tr>
<tr>
<td>上传重命名</td>
<td>文件自动 MD5 重命名，防中文路径</td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>注意</strong>：REST API 本身未被禁用（zhicms 前端搜品功能依赖 <code>/wp-json/zhicms/v1/products</code>），仅移除了 head 中的 REST API 链接标签。</p>
</blockquote>
<hr />
<h2>八、常见问题</h2>
<p><strong>Q：为什么搜索不到商品？</strong><br />
A：请先检查是否已配置大淘客或好单库的 API 密钥，两个 API 至少配一组。</p>
<p><strong>Q：访问 <code>/zhicms/</code> 页面 404？</strong><br />
A：进入 WordPress 后台 → 设置 → 固定链接，点击「保存更改」刷新 Rewrite Rules。确保固定链接模式非「朴素」。</p>
<p><strong>Q：商品卡片在文章中不显示？</strong><br />
A：检查短代码格式是否正确：<code>[zhicmsurl id="商品ID" platform="taobao"]</code>。确认商品已采集入库或联盟 API 可正常访问。</p>
<p><strong>Q：转链跳转提示链接获取失败？</strong><br />
A：检查大淘客 PID 是否填写正确。同时确认 API 密钥有效且调用额度未用完。</p>
<p><strong>Q：AI 导购不显示？</strong><br />
A：确认以下三项均已正确配置：</p>
<ol>
<li>AI 导购开关已勾选</li>
<li>AI 接口地址和 API Key 已填写</li>
<li>模型名称已填写</li>
</ol>
<p><strong>Q：AI 导购调用报错？</strong><br />
A：检查 API 地址能否从服务器正常访问（支持 cURL），确认 API Key 有效且有余额。</p>
<p><strong>Q：Gutenberg 编辑器无法插入短代码？</strong><br />
A：确认浏览器控制台无 JS 报错。插件使用 <code>wp.data.dispatch('core/block-editor')</code> 插入 shortcode 块，如使用自定义区块模板可能受影响，可切换到经典编辑器使用。</p>
<p><strong>Q：支持哪些 PHP 版本？</strong><br />
A：支持 PHP 5.6 至 PHP 8.4，已做全版本兼容适配（包括 PHP 8.0 嵌套三元运算符等兼容性修复）。</p>
<p><strong>Q：性能优化会和其他插件冲突吗？</strong><br />
A：已排除可能冲突的项（不禁用 REST API 本身）。如与其他优化插件重复设置，通常不会产生问题，多个 remove_action 调用是安全的。</p>]]></description>
    <pubDate>Mon, 27 Jul 2026 15:15:47 +0800</pubDate>
    <dc:creator>ZhiCms</dc:creator>
    <guid>https://www.zhi.red/wordpress.do</guid>
</item>
<item>
    <title>zhicms插件zblog安装和使用说明</title>
    <link>https://www.zhi.red/zblog.do</link>
    <description><![CDATA[<h1>ZhiCms 产品库 — ZBlog PHP 版插件说明</h1>
<h2>一、插件简介</h2>
<p>ZhiCms 产品库是一款集<strong>联盟商品搜索、选品采集、商品卡片展示、AI 导购助手</strong>于一体的 ZBlog PHP 插件。支持对接大淘客和好单库两大联盟 API，覆盖淘宝/天猫、京东、拼多多、唯品会四大主流电商平台，帮助站长快速搭建好物推荐内容。</p>
<ul>
<li><strong>版本</strong>：1.0.0</li>
<li><strong>作者</strong>：ZhiCms</li>
<li><strong>最低 PHP</strong>：5.6</li>
<li><strong>支持 PHP</strong>：5.6 ~ 8.4</li>
<li><strong>演示地址</strong>：<a href="http://zblog.zhicms.cc/zb_system/cmd.php?act=zhicms">http://zblog.zhicms.cc/zb_system/cmd.php?act=zhicms</a></li>
<li><strong>下载地址</strong>：<a href="https://www.zhi.red/d/zblog/zhicms.zip">https://www.zhi.red/d/zblog/zhicms.zip</a></li>
<li><strong>下载地址2</strong>：<a href="https://www.zhi.red/d/zblog/zhicms.zba">https://www.zhi.red/d/zblog/zhicms.zba</a></li>
</ul>
<hr />
<h2>二、核心功能</h2>
<h3>1. 联盟库商品搜索</h3>
<p>接入大淘客 + 好单库双 API，支持跨平台搜索淘宝、京东、拼多多、唯品会商品。搜索结果自动合并去重，按销量排序。</p>
<h3>2. 选品采集入库</h3>
<ul>
<li><strong>单条采集</strong>：将联盟库商品一键收录到本地选品库</li>
<li><strong>批量采集</strong>：输入关键词，一次采集多条商品</li>
<li>支持按平台筛选（全部 / 淘宝 / 京东 / 拼多多 / 唯品会）</li>
<li>后台实时反馈采集结果</li>
</ul>
<h3>3. 选品库管理</h3>
<p>后台表格化管理本地商品库，支持以下操作：</p>
<ul>
<li>关键词搜索商品</li>
<li>商品置顶 / 取消置顶（置顶有效期 7 天）</li>
<li>删除商品</li>
<li>清理过期优惠券商品</li>
</ul>
<h3>4. 商品卡片短代码</h3>
<p>在文章编辑器中点击「插入商品」按钮，选择商品即可插入短代码：</p>
<pre><code>[zhicmsurl id="商品ID" platform="taobao"]</code></pre>
<p>发布后自动渲染为美观的商品卡片，包含商品图、标题、价格、优惠券、销量、店铺等信息。同时支持在文章中直接手写短代码。</p>
<h3>5. 转链跳转</h3>
<p>用户点击商品卡片的「立即购买」按钮，插件自动通过联盟 API 完成转链，确保佣金归属。采用三层降级策略：</p>
<ol>
<li>通过转链接口获取推广链接</li>
<li>兜底查询本地选品库</li>
<li>最后调用商品详情 API 获取链接</li>
</ol>
<h3>6. 前端产品库展示页</h3>
<p>访问 <code>https://你的域名/zb_system/cmd.php?act=zhicms</code> 即可进入完整的产品库页面，支持：</p>
<ul>
<li>淘宝 / 京东 / 拼多多 / 唯品会分平台筛选</li>
<li>关键词搜索</li>
<li>选品库 / 联盟库双数据源切换</li>
<li>分页加载</li>
</ul>
<h3>7. AI 导购助手</h3>
<p>启用后，网站页面右下角会出现悬浮的 AI 导购按钮。用户点击可与 AI 对话：</p>
<ul>
<li>智能识别购物意图，自动搜索相关商品</li>
<li>支持闲聊（调用 AI 大模型回复）</li>
<li>搜索到的商品以卡片形式展示，一键跳转购买</li>
<li>对话历史保存在本地，下次访问自动读取</li>
</ul>
<h3>8. 编辑器集成</h3>
<p>在后台文章编辑页面，编辑器上方增加「插入商品」按钮，点击弹出商品选择弹窗，支持：</p>
<ul>
<li>选品库 / 联盟库双 Tab 切换</li>
<li>选品库已有商品的快速选择插入</li>
<li>联盟库关键词搜索后采集/插入</li>
<li>一键生成 <code>[zhicmsurl]</code> 短代码</li>
<li>兼容 UEditor / CodeMirror / 原生 textarea 编辑器</li>
</ul>
<hr />
<h2>三、安装说明</h2>
<h3>方法一：后台上传</h3>
<ol>
<li>下载插件压缩包 <code>zhicms.zip</code>或<code>zhicms.zba</code></li>
<li>进入 ZBlog 后台 → 插件管理 → 安装插件</li>
<li>上传 zip 文件，激活插件</li>
</ol>
<h3>方法二：手动上传</h3>
<ol>
<li>将插件文件夹 <code>zhicms</code> 上传到 <code>/zb_users/plugin/</code> 目录</li>
<li>进入 ZBlog 后台 → 插件管理，找到「ZhiCms 产品库」点击启用</li>
</ol>
<h3>卸载</h3>
<p>在后台插件管理中停用并删除插件，将自动清除插件创建的数据表和配置。</p>
<hr />
<h2>四、插件设置</h2>
<p>进入后台 → 插件管理 → ZhiCms 产品库右侧「设置」，或直接点击插件名称进入管理页。</p>
<h3>API 密钥配置</h3>
<table>
<thead>
<tr>
<th>配置项</th>
<th>说明</th>
<th style="text-align: center;">必填</th>
</tr>
</thead>
<tbody>
<tr>
<td>大淘客 AppKey</td>
<td>大淘客开放平台的应用 Key</td>
<td style="text-align: center;">否*</td>
</tr>
<tr>
<td>大淘客 AppSecret</td>
<td>大淘客开放平台的应用 Secret</td>
<td style="text-align: center;">否*</td>
</tr>
<tr>
<td>大淘客 PID</td>
<td>淘宝联盟推广位 ID，用于佣金归属</td>
<td style="text-align: center;">否</td>
</tr>
<tr>
<td>好单库 ApiKey</td>
<td>好单库开放平台的 API 密钥</td>
<td style="text-align: center;">否*</td>
</tr>
</tbody>
</table>
<blockquote>
<p>* 至少配置大淘客或好单库其中一项，否则无法使用联盟搜索和采集功能。</p>
</blockquote>
<h3>AI 导购配置</h3>
<table>
<thead>
<tr>
<th>配置项</th>
<th>说明</th>
<th style="text-align: center;">必填</th>
</tr>
</thead>
<tbody>
<tr>
<td>启用 AI 导购</td>
<td>开启后，网站页面右下角显示悬浮按钮</td>
<td style="text-align: center;">否</td>
</tr>
<tr>
<td>AI 接口地址</td>
<td>OpenAI 兼容 API 地址，如 <code>https://api.openai.com/v1/chat/completions</code></td>
<td style="text-align: center;">启用时必填</td>
</tr>
<tr>
<td>API Key</td>
<td>AI 服务的 API 密钥</td>
<td style="text-align: center;">启用时必填</td>
</tr>
<tr>
<td>模型名称</td>
<td>使用的模型，如 <code>gpt-3.5-turbo</code>、<code>deepseek-chat</code> 等</td>
<td style="text-align: center;">启用时必填</td>
</tr>
<tr>
<td>系统提示词</td>
<td>自定义 AI 导购角色设定，留空使用默认提示词</td>
<td style="text-align: center;">否</td>
</tr>
</tbody>
</table>
<hr />
<h2>五、API 密钥获取</h2>
<h3>大淘客开放平台</h3>
<ol>
<li>访问 <a href="https://www.dataoke.com/">https://www.dataoke.com/</a> 注册账号</li>
<li>进入控制台 → 应用管理，创建应用</li>
<li>获取 AppKey 和 AppSecret</li>
<li>（可选）在淘宝联盟获取 PID，填入插件</li>
</ol>
<h3>好单库开放平台</h3>
<ol>
<li>访问 <a href="https://www.haodanku.com/">https://www.haodanku.com/</a> 注册账号</li>
<li>进入个人中心 → API 管理</li>
<li>获取 ApiKey</li>
</ol>
<h3>AI 大模型 (OpenAI 兼容)</h3>
<ol>
<li>直接使用 OpenAI API：<a href="https://platform.openai.com/">https://platform.openai.com/</a></li>
<li>或使用国内代理/大模型服务：如 DeepSeek、通义千问、智谱等</li>
<li>获取 API 地址和 Key 填入设置</li>
</ol>
<hr />
<h2>六、前端展示页配置</h2>
<p>插件的前端产品库页面使用 ZBlog 主题的头部和底部，自动继承当前主题样式。</p>
<p>如需自定义展示页样式，可在主题中覆盖以下 CSS 类：</p>
<ul>
<li><code>.zc-page</code> — 页面容器</li>
<li><code>.zc-header</code> — 页面标题区</li>
<li><code>.zc-search</code> — 搜索栏</li>
<li><code>.zc-tabs</code> — 数据源切换标签</li>
<li><code>.zc-plats</code> — 平台筛选标签</li>
<li><code>.zc-list</code> — 商品列表</li>
<li><code>.zcard</code> — 商品卡片</li>
</ul>
<hr />
<h2>七、常见问题</h2>
<p><strong>Q：为什么搜索不到商品？</strong><br />
A：请先检查是否已配置大淘客或好单库的 API 密钥，两个 API 至少配一个。</p>
<p><strong>Q：商品卡片样式错乱？</strong><br />
A：编辑器插入的短代码确保在独立段落中，不要嵌套在其他标签内。</p>
<p><strong>Q：转链跳转提示链接获取失败？</strong><br />
A：检查 PID 是否填写正确。同时确认 API 密钥有效且额度未用完。</p>
<p><strong>Q：AI 导购不显示？</strong><br />
A：确认已开启 AI 导购开关，且 API 地址、Key、模型名称三个配置项均已填写。</p>
<p><strong>Q：启用 AI 导购后 API 调用失败？</strong><br />
A：检查 API 地址是否能正常访问，确认 Key 有效。插件使用 cURL 发送请求，请确保服务器支持 cURL。</p>
<p><strong>Q：支持哪些 PHP 版本？</strong><br />
A：支持 PHP 5.6 至 PHP 8.4，已做全版本兼容适配。</p>]]></description>
    <pubDate>Mon, 27 Jul 2026 15:11:49 +0800</pubDate>
    <dc:creator>ZhiCms</dc:creator>
    <guid>https://www.zhi.red/zblog.do</guid>
</item>
<item>
    <title>zhicms插件emlog安装和使用说明</title>
    <link>https://www.zhi.red/emlog.do</link>
    <description><![CDATA[<h1>ZhiCms 产品库 — emlog 版插件说明</h1>
<h2>一、插件简介</h2>
<p>ZhiCms 产品库是一款集<strong>联盟商品搜索、选品采集、商品卡片展示、AI 导购助手</strong>于一体的 emlog 插件。支持对接大淘客和好单库两大联盟 API，覆盖淘宝/天猫、京东、拼多多、唯品会四大主流电商平台，帮助站长快速搭建好物推荐内容。</p>
<ul>
<li><strong>版本</strong>：1.0.0</li>
<li><strong>作者</strong>：ZhiCms</li>
<li><strong>最低 PHP</strong>：5.6</li>
<li><strong>支持 PHP</strong>：5.6 ~ 8.4</li>
<li><strong>演示地址</strong>：<a href="https://www.zhi.red/?plugin=zhicms">https://www.zhi.red/?plugin=zhicms</a></li>
<li><strong>下载地址</strong>：<a href="https://www.zhi.red/d/emlog/zhicms.zip">https://www.zhi.red/d/emlog/zhicms.zip</a></li>
</ul>
<hr />
<h2>二、核心功能</h2>
<h3>1. 联盟库商品搜索</h3>
<p>接入大淘客 + 好单库双 API，支持跨平台搜索淘宝、京东、拼多多、唯品会商品。搜索结果自动合并去重，按销量排序。</p>
<h3>2. 选品采集入库</h3>
<ul>
<li><strong>单条采集</strong>：将联盟库商品一键收录到本地选品库</li>
<li><strong>批量采集</strong>：输入关键词，一次采集多条商品</li>
<li>支持按平台筛选（全部 / 淘宝 / 京东 / 拼多多 / 唯品会）</li>
</ul>
<h3>3. 选品库管理</h3>
<p>后台表格化管理本地商品库，支持以下操作：</p>
<ul>
<li>关键词搜索商品</li>
<li>商品置顶 / 取消置顶</li>
<li>删除商品</li>
<li>清理过期优惠券商品</li>
</ul>
<h3>4. 商品卡片短代码</h3>
<p>在文章编辑器中点击「插入商品卡片」按钮，选择商品即可插入短代码：</p>
<pre><code>[zhicmsurl id="商品ID" platform="taobao"]</code></pre>
<p>发布后自动渲染为美观的商品卡片，包含商品图、标题、价格、优惠券、销量、店铺等信息。</p>
<h3>5. 转链跳转</h3>
<p>用户点击商品卡片的「立即购买」按钮，插件自动通过联盟 API 完成转链，确保佣金归属。采用三层降级策略：</p>
<ol>
<li>通过转链接口获取推广链接</li>
<li>兜底查询本地选品库</li>
<li>最后调用商品详情 API 获取链接</li>
</ol>
<h3>6. 前端产品库展示页</h3>
<p>访问 <code>https://你的域名/?plugin=zhicms</code> 即可进入完整的产品库页面，支持：</p>
<ul>
<li>淘宝 / 京东 / 拼多多 / 唯品会分平台筛选</li>
<li>关键词搜索</li>
<li>选品库 / 联盟库双数据源切换</li>
</ul>
<h3>7. AI 导购助手</h3>
<p>启用后，网站页面右下角会出现悬浮的 AI 导购按钮。用户点击可与 AI 对话：</p>
<ul>
<li>智能识别购物意图，自动搜索相关商品</li>
<li>支持闲聊（调用 AI 大模型回复）</li>
<li>搜索到的商品以卡片形式展示，一键跳转购买</li>
<li>对话历史保存在本地，下次访问自动读取</li>
</ul>
<h3>8. 编辑器集成</h3>
<p>在后台文章编辑页面，编辑器上方增加「插入商品」按钮，点击弹出商品选择弹窗，支持：</p>
<ul>
<li>选品库已有商品的快速选择插入</li>
<li>联盟库关键词搜索后采集/插入</li>
<li>一键生成 <code>[zhicmsurl]</code> 短代码</li>
</ul>
<hr />
<h2>三、安装说明</h2>
<h3>方法一：后台上传</h3>
<ol>
<li>下载插件压缩包 <code>zhicms.zip</code></li>
<li>进入 emlog 后台 → 插件 → 安装插件</li>
<li>上传 zip 文件，自动安装并激活</li>
</ol>
<h3>方法二：手动上传</h3>
<ol>
<li>将插件文件夹 <code>zhicms</code> 上传到 <code>/content/plugins/</code> 目录</li>
<li>进入 emlog 后台 → 插件，找到「ZhiCms 产品库」点击激活</li>
</ol>
<h3>卸载</h3>
<p>在后台插件管理中停用并删除插件，将自动清除插件创建的数据表。</p>
<hr />
<h2>四、插件设置</h2>
<h3>API 密钥配置</h3>
<p>进入后台 → 插件 → ZhiCms 产品库 → 设置，填写以下信息：</p>
<table>
<thead>
<tr>
<th>配置项</th>
<th>说明</th>
<th style="text-align: center;">必填</th>
</tr>
</thead>
<tbody>
<tr>
<td>大淘客 AppKey</td>
<td>大淘客开放平台的应用 Key</td>
<td style="text-align: center;">否*</td>
</tr>
<tr>
<td>大淘客 AppSecret</td>
<td>大淘客开放平台的应用 Secret</td>
<td style="text-align: center;">否*</td>
</tr>
<tr>
<td>大淘客 PID</td>
<td>淘宝联盟推广位 ID，用于佣金归属</td>
<td style="text-align: center;">否</td>
</tr>
<tr>
<td>好单库 ApiKey</td>
<td>好单库开放平台的 API 密钥</td>
<td style="text-align: center;">否*</td>
</tr>
</tbody>
</table>
<blockquote>
<p>* 至少配置大淘客或好单库其中一项，否则无法使用联盟搜索和采集功能。</p>
</blockquote>
<h3>AI 导购配置</h3>
<blockquote>
<p>注意：emlog 版插件的 AI API 地址、API Key、模型名称由 emlog 系统级「设置 → AI 模型」统一管理。</p>
</blockquote>
<table>
<thead>
<tr>
<th>配置项</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>启用 AI 导购</td>
<td>开启后，网站页面右下角显示悬浮按钮</td>
</tr>
<tr>
<td>系统提示词</td>
<td>自定义 AI 导购的角色设定，留空使用默认提示词</td>
</tr>
</tbody>
</table>
<hr />
<h2>五、API 密钥获取</h2>
<h3>大淘客开放平台</h3>
<ol>
<li>访问 <a href="https://www.dataoke.com/">https://www.dataoke.com/</a> 注册账号</li>
<li>进入控制台 → 应用管理，创建应用</li>
<li>获取 AppKey 和 AppSecret</li>
<li>（可选）在淘宝联盟获取 PID，填入插件</li>
</ol>
<h3>好单库开放平台</h3>
<ol>
<li>访问 <a href="https://www.haodanku.com/">https://www.haodanku.com/</a> 注册账号</li>
<li>进入个人中心 → API 管理</li>
<li>获取 ApiKey</li>
</ol>
<hr />
<h2>六、常见问题</h2>
<p><strong>Q：为什么搜索不到商品？</strong><br />
A：请先检查是否已配置大淘客或好单库的 API 密钥，两个 API 至少配一个。</p>
<p><strong>Q：商品卡片样式错乱？</strong><br />
A：CSS 样式兼容主流 emlog 主题。如遇问题，可在插件设置中调整。</p>
<p><strong>Q：转链跳转提示「商品链接获取失败」？</strong><br />
A：检查 PID 是否填写正确。同时确认 API 密钥有效且额度未用完。</p>
<p><strong>Q：AI 导购不显示？</strong><br />
A：确认已开启 AI 导购开关，且在 emlog 系统设置中已配置 AI 模型（API 地址、Key、模型名称）。</p>
<p><strong>Q：支持哪些 PHP 版本？</strong><br />
A：支持 PHP 5.6 至 PHP 8.4，已做全版本兼容适配。</p>]]></description>
    <pubDate>Mon, 27 Jul 2026 14:56:28 +0800</pubDate>
    <dc:creator>ZhiCms</dc:creator>
    <guid>https://www.zhi.red/emlog.do</guid>
</item>
<item>
    <title>本届省政府质量奖名单中民企占八成 与质量死磕，才是成功正道</title>
    <link>https://www.zhi.red/vp0CKK.do</link>
    <description><![CDATA[<p>[zhicmsurl id=&quot;KnmARRbT3toJZRqjAbumVksJtW-26VpOQjCMMz4g0qmFv&quot; platform=&quot;taobao&quot;]</p>
<p>本届省政府质量奖名单中民企占八成 与质量死磕，才是成功正道</p><p><a href="https://mini.eastday.com/mobile/260724085254170123106.html" target="_blank" rel="nofollow">查看原文</a></p><p style="color:#999;font-size:12px;">来源：杭州网</p><p style="color:#999;font-size:12px;">时间：2026-07-24 08:52:00</p>]]></description>
    <pubDate>Sun, 26 Jul 2026 17:02:37 +0800</pubDate>
    <dc:creator>ZhiCms</dc:creator>
    <guid>https://www.zhi.red/vp0CKK.do</guid>
</item>
<item>
    <title>故宫博物院7月27日免费开放 需经小程序预约</title>
    <link>https://www.zhi.red/cpIdNl.do</link>
    <description><![CDATA[<p>故宫博物院7月27日免费开放 需经小程序预约</p><p><a href="https://mini.eastday.com/mobile/260724095627354502758.html" target="_blank" rel="nofollow">查看原文</a></p><p style="color:#999;font-size:12px;">来源：中国网</p><p style="color:#999;font-size:12px;">时间：2026-07-24 09:56:00</p>]]></description>
    <pubDate>Sun, 26 Jul 2026 17:02:37 +0800</pubDate>
    <dc:creator>ZhiCms</dc:creator>
    <guid>https://www.zhi.red/cpIdNl.do</guid>
</item>
<item>
    <title>张北大数据产业集群以共享模式激活数字产业新活力</title>
    <link>https://www.zhi.red/tvFwFB.do</link>
    <description><![CDATA[<p>张北大数据产业集群以共享模式激活数字产业新活力</p><p><a href="https://mini.eastday.com/mobile/260725222852370820480.html" target="_blank" rel="nofollow">查看原文</a></p><p style="color:#999;font-size:12px;">来源：河北新闻网</p><p style="color:#999;font-size:12px;">时间：2026-07-25 22:28:00</p>]]></description>
    <pubDate>Sun, 26 Jul 2026 17:02:37 +0800</pubDate>
    <dc:creator>ZhiCms</dc:creator>
    <guid>https://www.zhi.red/tvFwFB.do</guid>
</item>
</channel>
</rss>