本地静态模版转为wangmarket的模版

本文是 WangMarket MCP 模板建站流程的执行规范。除明确标注为固定枚举或固定语法外,文中 HTML、文案、URL、栏目名、codeName、ID、账号、QQ、图片地址和返回 info 均为示例或占位值,不得直接写入生产站点。

版本基准:本文所有”已确认”的模板标签、URL 生成规则、templatePath 行为等结论,均基于 WangMarket 6.1 源码(依赖 wangmarket-6.1.jar)反编译核对。目标站点运行版本不是 6.1 时,标注”6.1 已确认”的项仍须按第 11 章实测确认;标注”跨版本注意”的项尤其需要验证。

执行前置条件:目标站点已开通且已明确;登录凭据有效;运行时工具列表至少包含本次分支所需的 loginsave_template_varsave_site_columnsave_template_pagesave_template_page_textgenerate_site,并按页面类型提供 save_news(信息列表内容)或 save_alone_page_content(独立页面内容);只有实际使用全局变量时才需要 save_site_var/save_site_var_value,只有绑定缺失且获授权修复时才需要 save_template。各工具 schema 必须与本文调用相符;站点是否已有同名对象已确认;预览所需的真实站点基础 URL 已由用户、宿主或后台提供。当前工具集没有站点 URL/生成结果查询工具,也没有”按栏目创建独立页面内容”的工具:真实页面 URL 必须外部提供,独立页面内容若未自动创建必须人工在后台添加后 AI 才能更新。任一当前分支必需条件缺失时必须先报告并停止,不得猜测或开始写入。

⚠️ 静态资源上传前置检查(必须在第 1 章之前完成)

开始读取和制作模板之前,必须先检查用户上传的 HTML 模板包中是否引用了本地静态资源文件,包括但不限于:

资源类型常见引用方式常见扩展名
样式表<link rel="stylesheet" href="...">@import.css
脚本<script src="...">.js
图片<img src="...">background-image: url(...)<source srcset="...">.jpg.jpeg.png.gif.webp.svg.ico
字体@font-face { src: url(...) }.woff.woff2.ttf.eot.otf
视频/音频<video src="..."><audio src="..."><source src="...">.mp4.webm.mp3.ogg
其他<iframe src="...">fetch("...")ajax 请求的本地 JSON.json.html

检查与处理流程

  1. 扫描模板:读取所有 HTML 文件,提取上述引用路径,区分绝对 URLhttp://https:// 开头,可直接使用)与相对/本地路径./..//、纯文件名开头,需要上传)。
  2. 统计清单:列出所有需要上传的本地静态资源文件路径、数量、总大小,向用户报告。
  3. 提醒上传:如果存在本地静态资源,必须暂停模板制作流程,提醒用户将这些资源上传到线上可访问的存储服务,可选方式包括:
    • 阿里云 OSS / 腾讯云 COS / 七牛云等对象存储
    • 公司 FTP 服务器 / 静态资源 CDN
    • 网市场后台的附件上传功能(如有)
    • 其他可公网访问的 HTTP/HTTPS 静态文件服务
  4. 配置访问域名:资源上传完成后,必须为存储服务配置一个可公网访问的域名,注意事项:
    • 不得直接使用存储服务的临时域名、内网地址或 IP 地址(如 https://bucket.oss-cn-hangzhou.aliyuncs.com/ 临时域名可能有访问次数限制或随时失效)
    • 必须使用用户自己的已备案域名(如 https://cdn.example.com/https://static.example.com/),并完成 DNS 解析(CNAME 指向存储服务)
    • 域名必须已完成 ICP 备案(中国大陆服务器要求),未备案域名无法正常访问
    • 建议配置 HTTPS 证书,确保资源通过 https:// 访问,避免混合内容问题(站点如果是 HTTPS,HTTP 资源会被浏览器拦截)
    • 配置完成后,需验证域名可正常解析且资源可通过该域名访问(如 https://cdn.example.com/css/style.css 返回 200)
  5. 获取 URL:域名配置并验证通过后,要求用户提供每个资源对应的线上可访问 URL(或一个统一的基础 URL 前缀 + 相对路径映射规则,如基础前缀 https://cdn.example.com/ + 相对路径 css/style.css)。
  6. 验证可访问:对每个线上 URL 进行可访问性验证(HTTP 状态码 200、Content-Type 正确、非空响应体),图片资源建议验证可正常渲染。
  7. 替换路径:验证通过后,将模板 HTML 中所有本地静态资源路径统一替换为对应的线上 URL。
  8. 继续流程:完成上述步骤后,才能进入第 1 章开始正常的模板制作流程。

禁止行为

例外情况:如果模板中所有静态资源均已使用绝对 URL(如 https://cdn.example.com/css/style.css),且验证可访问,则无需上传,可直接进入第 1 章。


目录

阅读指南

读者类型建议阅读路径
人工后台操作第 1→2→4→5→6→7→8 章,跳过 MCP 工具调用细节,关注后台操作步骤
AI / MCP 自动执行前置规则 → 第 3 章工具 schema → 第 9 章标签白名单 → 文末「AI 自动执行的唯一闭环」
排查问题「常见问题与避坑指南」→ 第 10 章「仍需确认的执行边界」→ 对应章节
模板标签参考第 9 章全部,重点 9.6(首页)、9.7(列表页)、9.8(详情页)、9.12(分页)

本文档版本:基于 WangMarket 6.1 核对版本编写。不同版本的标签适用性、URL 生成规则和字段行为可能存在差异,执行前必须按第 11 章「运行时确认操作指南」核对目标运行时。


AI 执行前置规则:来源优先级、版本边界与禁止猜测

本文档供 AI 读取并执行模板建站,但只把有当前运行时或明确源码依据的规则标为可执行。文档中的示例和历史说明不自动成为参数默认值。执行时必须遵守以下规则:

  1. 实际运行时 MCP 工具的 inputSchema / enum / 返回结果决定“接口能否接受某个参数”;源码和本文档决定“当前业务是否应该使用该参数”。“schema 仍兼容”不等于“AI 可以继续新建时使用历史废弃值”。
  2. 父级源码和帮助页只用于解释已核对的当前语义;存在版本差异时必须保留“待确认”状态。
  3. /templateTag/*.do 帮助页用于核对标签名称、适用页面、循环上下文和调用语法,但帮助页版本必须与目标运行时一致。
  4. 本地未渲染 Markdown 是本文的 canonical 文本。在线 CMS 页面可能执行花括号标签或破坏转义,不能在未验证原样发布前作为机器执行依据。
  5. 遇到本文档写为“源码未定义”“无完整技术规范”或“需确认”的内容时,必须停止并请求依据,不得由 AI 自行补全。
  6. 禁止按照其他 CMS、Jinja、Django、Vue、WordPress 等系统经验推导网市场不存在的标签、枚举、输入模型代码或 DOM 协议。
  7. 本文自动执行入口是 MCP。authHandle 只能原样使用 login.result=1 时返回的值,并显式传给每个业务工具;不得用用户名、密码、上游 token、session 或 iwSID 替代。
  8. 每次响应先检查 MCP/传输错误,再检查业务 result。出现 mcpErrorisError=true、超时、连接中断或 result != 1 时停止当前依赖链;result=2 时重新登录后只重试刚才失败的步骤。提交状态不明时不得盲目重试写操作。
  9. 只有接口定义明确说明为 ID 的真实成功返回值才能传给后续 ID 参数。非数字信息、示例值、名称、codeName 或根据 URL 猜出的数字都不是 ID;当前 MCP 无查询能力且上下文没有真实值时必须暂停。
  10. 模板标签唯一确认规则:只有目标运行时帮助页或一次真实生成结果确认某个标签及其上下文可用,AI 才能把它写入模板;帮助资料冲突且无法确认时必须暂停,不得回退、混用或猜测。WangMarket 6.1 例外{news.*}{siteColumn.*}{page.*}{templatePath} 已通过源码反编译确认可用(见第 10 章已确认表),6.1 版本可直接使用;动态调用标记(SiteColumn_Start/EndList_Start/EndSubColumnList_Start/End)内部字段及非 6.1 版本仍按本规则确认。
  11. 上游 URL、application/x-www-form-urlencodedtokeniwSID Cookie 只属于 MCP Server 与 WangMarket 之间的实现核对信息,不是 AI 的执行步骤。AI 只调用 MCP 工具;不得直接请求上游 URL,也不得自行构造 tokeniwSID 或 Cookie 去替代 authHandle
  12. 本文所有可执行 JSON / HTML 示例中的 URL、文案、联系方式、账号、codeName、ID、图片地址都是示例或占位值,不得原样提交到生产站点;必须先替换为用户、宿主或后台提供的真实值。
  13. 静态资源强制检查规则:开始制作模板前,必须扫描用户上传的 HTML 模板中引用的所有本地静态资源(CSS、JS、图片、字体、视频等),如存在相对路径或本地路径引用,必须暂停流程,提醒用户上传到线上云存储或 FTP 并提供可访问 URL,验证 URL 可访问后替换模板中的本地路径为线上 URL,验证通过后方可继续。禁止将本地相对路径直接写入模板页面或模板变量(详见文首「静态资源上传前置检查」)。

原样发布要求:本文中的 {...}、HTML 和 JSON 示例必须使用 CMS 提供的原样代码保护方式,或在发布前实体编码。发布后必须重新抓取验证:代码块中的标签仍为字面文本,JSON 可独立解析,没有整篇正文嵌入、重复章节或丢失反斜杠。无法保证原样发布时,在线页面不得作为 AI 执行依据。

当前最重要的版本结论:

  1. TemplatePage.type
  2. 0 = TYPE_ELSE / 其他;只有历史常量,无明确标准业务生成、绑定、预览路径;MCP 不使用
  3. 1 = 首页模板;当前使用
  4. 2 = 文章列表模板;当前使用
  5. 3 = 文章详情模板;当前使用;关于我们等单页面也并入该模板类型
  6. 6 = TYPE_ALONEPAGE / 旧独立页面模板;已废弃并入 type=3MCP 不使用
  7. SiteColumn.type
  8. 1 = TYPE_NEWS / 新闻信息;CMS 已废弃
  9. 2 = TYPE_IMAGENEWS / 图文信息;CMS 已废弃
  10. 3 = TYPE_PAGE / 旧版独立页面;仅历史兼容
  11. 4 = TYPE_LEAVEWORD / 留言板;CMS 已废弃
  12. 5 = TYPE_HREF / 超链接;CMS 已废弃
  13. 6 = TYPE_TEXT / 纯文字栏目;CMS 已废弃
  14. 7 = TYPE_LIST / 信息列表;当前 CMS 使用
  15. 8 = TYPE_ALONEPAGE / 独立页面;当前 CMS 使用

当前 AI/MCP 新建栏目只按业务使用:

  1. 新闻资讯等列表栏目 SiteColumn.type = 7
  2. 关于我们等独立页面栏目 SiteColumn.type = 8

因此“关于我们”的当前执行关系示例为:

  1. TemplatePage.type = 3
  2. +
  3. SiteColumn.type = 8
  4. +
  5. SiteColumn.templatePageViewName = about
  6. +
  7. SiteColumn.editMode = 0(通过内容管理维护正文时)

特别注意:TemplatePage.type=3SiteColumn.type=3 不是同一含义。前者是当前详情页模板,后者只是旧版独立页面栏目兼容值;若目标运行时版本不同,必须以运行时 schema 和实际结果为准。

1. 相关资料

教程中的 HTML 原始模板

现有 HTML 模板共有三个页面:首页、关于我们、新闻列表。
这里,来演示将此 HTML 模板制作成网市场云建站系统所用模板的步骤。
为了方便 AI 直接读取、分析并根据本文档进行模板制作,本教程不再要求另外下载附件,下面直接提供原始模板中的三个 HTML 文件完整源代码:

⚠️ 第 1 章三段源码不可直接提交:仅作视觉与结构参考

下面三段是第三方原始模板的完整源码,其中的开发者姓名、QQ、微信、微信公众号、官网、GitHub、开源中国地址、交流 QQ 群号以及全部宣传文案,都是原模板自带的内容,不是本次建站的目标数据

执行型 AI 不得把它们原样复制到生产站点:制作模板时只保留结构与样式,把文案、联系方式、链接全部替换为用户提供的真实值。第 2 章之后的每个可执行 JSON / HTML 示例同样如此(前置规则第 12 条)。

1.1 index.html 首页源代码

  1. <!DOCTYPE HTML>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>网·市场</title>
  6. </head>
  7. <body>
  8. <!-- 每个页面都有的头部导航 -->
  9. <nav style="text-align:center; font-size:26px;">
  10. <a href="index.html">首页</a>
  11. <a href="about.html">关于我们</a>
  12. <a href="news.html">新闻列表</a>
  13. <hr/>
  14. </nav>
  15. <div>
  16. <h2>hi,这是首页</h2>
  17. </div>
  18. <div> 网市场云建站系统,系统成熟、流程完善、细节精致、使用简单。极低的成本投入,30秒安装部署,选好模版一键导入。最快出网站,最快赚到钱。网市场云建站系统,历经8年,不断完善,拒绝半成品!
  19. 注重实际业务应用,一切以建站公司的利益为主。
  20. </div>
  21. <div>
  22. <h3>交流反馈:</h3>
  23. 开发者姓名:管雷鸣<br/>
  24. 开发者QQ:921153866<br/>
  25. 开发者微信:xnx3com<br/>
  26. 开发者微信公众号:wangmarket<br/>
  27. 交流QQ群:472328584<br/>
  28. 官方网站:www.wang.market<br/>
  29. GitHub:github.com/xnx3/wangmarket<br/>
  30. 开源中国:gitee.com/mail_osc/wangmarket<br/>
  31. </div>
  32. <!-- 每个页面都有的尾部 -->
  33. <footer style="text-align:center; padding-top:30px;">
  34. <hr/>
  35. power by: wang.market
  36. author: 管雷鸣
  37. QQ群:472328584
  38. </footer>
  39. </body>
  40. </html>

1.2 about.html 关于我们源代码

  1. <!DOCTYPE HTML>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>网·市场</title>
  6. </head>
  7. <body>
  8. <!-- 每个页面都有的头部导航 -->
  9. <nav style="text-align:center; font-size:26px;">
  10. <a href="index.html">首页</a>
  11. <a href="about.html">关于我们</a>
  12. <a href="news.html">新闻列表</a>
  13. <hr/>
  14. </nav>
  15. <h1>关于我们</h1>
  16. <div>
  17. 网市场云建站系统,于09年开发wap系统建站。之后在xnx3、iw等基础上开发而来。
  18. 于15年重新启动,<br/>
  19. 16年开始试运行<br/>
  20. 17年底正式开源发布!<br/>
  21. 截止17年底:<br/> 共建立网站服务客户一千余个,经过市场及客户验证。而非一时兴起作出来扔网上开源后就不管的<br/>
  22. 截止17年中旬,svn版本更新迭代837次、版本功能性升级57次!
  23. </div>
  24. <!-- 每个页面都有的尾部 -->
  25. <footer style="text-align:center; padding-top:30px;">
  26. <hr/>
  27. power by: wang.market
  28. author: 管雷鸣
  29. QQ群:472328584
  30. </footer>
  31. </body>
  32. </html>

1.3 news.html 新闻列表源代码

  1. <!DOCTYPE HTML>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>网·市场</title>
  6. </head>
  7. <body>
  8. <!-- 每个页面都有的头部导航 -->
  9. <nav style="text-align:center; font-size:26px;">
  10. <a href="index.html">首页</a>
  11. <a href="about.html">关于我们</a>
  12. <a href="news.html">新闻列表</a>
  13. <hr/>
  14. </nav>
  15. <h1>新闻列表</h1>
  16. <ul>
  17. <li><a href="about.html">v4.0升级了!</a></li>
  18. <li><a href="about.html">v3.9升级了!</a></li>
  19. <li><a href="about.html">v3.8.1升级了!</a></li>
  20. <li><a href="about.html">v3.8升级了!</a></li>
  21. <li><a href="about.html">v4.0升级了!</a></li>
  22. <li><a href="about.html">v3.9升级了!</a></li>
  23. <li><a href="about.html">v3.8.1升级了!</a></li>
  24. <li><a href="about.html">v3.8升级了!</a></li>
  25. <li><a href="about.html">v4.0升级了!</a></li>
  26. <li><a href="about.html">v3.9升级了!</a></li>
  27. </ul>
  28. <div>
  29. <!--这是分页-->
  30. <a href="">首页</a>
  31. <a href="">上一页</a>
  32. <a href="">下一页</a>
  33. <a href="">尾页</a>
  34. </div>
  35. <!-- 每个页面都有的尾部 -->
  36. <footer style="text-align:center; padding-top:30px;">
  37. <hr/>
  38. power by: wang.market
  39. author: 管雷鸣
  40. QQ群:472328584
  41. </footer>
  42. </body>
  43. </html>

2. 抽取,创建模板变量

创建模板变量的目的,如:
很多页面中都有头部导航,如果导航中要增加一项,那么有导航的每个页面也要挨个改过来,页面很多,太麻烦。而做成模板变量,可以只需要改动模板变量即可。
页面中都是调用模板变量,也就不用再每个页面都去改了。

2.1 查看 HTML 模板源代码

查看上面提供的 about.htmlindex.htmlnews.html 三个模板页面源代码,找到三个模板页面中都共同有的头部、尾部。
当然,这里不一定非得头部、尾部,这里只是把相同的地方找出来
根据上面三个 HTML 文件,可以直接确认共同的头部导航代码为:

  1. <!-- 每个页面都有的头部导航 -->
  2. <nav style="text-align:center; font-size:26px;">
  3. <a href="index.html">首页</a>
  4. <a href="about.html">关于我们</a>
  5. <a href="news.html">新闻列表</a>
  6. <hr/>
  7. </nav>

共同的尾部代码为:

  1. <!-- 每个页面都有的尾部 -->
  2. <footer style="text-align:center; padding-top:30px;">
  3. <hr/>
  4. power by: wang.market
  5. author: 管雷鸣
  6. QQ群:472328584
  7. </footer>

2.2 创建模板变量

将上面找到的相同的两处,分别保存成网市场云建站系统的模板变量。
登录当前网站的管理后台后,在左侧菜单中依次进入:

  1. 模板管理
  2. 模板变量

其中:


2.2.1 使用 MCP 创建模板变量

最新 MCP 文档已经定义:

  1. save_template_var

用于创建或更新当前登录站点的公共模板变量。
因此,原来需要通过后台原生模板变量保存接口完成的 navfooter 创建,现在如果 AI 已经连接网市场 MCP Server,可以直接调用 save_template_var 完成。
MCP 对应的上游接口为(仅作实现核对信息,不是 AI 的执行步骤;AI 只调用 MCP 工具):

  1. POST /plugin/adminapi/site/saveTemplateVar.json

对应的 MCP 工具名称为:

  1. save_template_var

调用 save_template_var 前,必须先通过:

  1. login

登录成功,并取得有效:

  1. authHandle

如果前面还没有登录,则先执行:

  1. login
  2. result = 1
  3. 获取 authHandle

然后再创建模板变量。本文只讨论 MCP 调用;传统 HTTP 的 token 仅属于上游请求层,不得代替 authHandle

2.2.2 save_template_var 参数说明

save_template_var 支持以下参数:
| 参数 | 是否必填 | 类型 | 含义 |
|—-|—-|—-|—-|
| authHandle | 是 | string | login 成功返回的不透明认证句柄 |
| varName | 是 | string | 模板变量代码,例如 navfooter |
| id | 否 | integer/null | 省略、null0 表示创建;大于 0 表示更新已有变量 |
| remark | 否 | string/null | 模板变量备注,仅用于后台管理和识别 |
| text | 协议可选;本流程必填 | string | 模板变量的完整 HTML 内容;每次调用会覆盖该变量原内容。创建页面会引用的变量时必须显式传入非空完整 HTML;省略会保存空内容。 |
其中最关键的是:

  1. varName

它就是页面中:

  1. {include=变量名}

所使用的变量代码。
例如:

  1. varName = nav
  2. 页面中使用 {include=nav}
  3. varName = footer
  4. 页面中使用 {include=footer}

text 则是实际需要被替换进去的完整 HTML。

2.2.3 通过 MCP 创建 nav

创建 nav 时调用:

  1. save_template_var

⚠️ 不可直接提交:以下示例仅用于说明 JSON 结构。其中 index.htmlabout.htmlnews.html 是原始模板自带的相对链接,不是最终地址;文案、链接、数量都必须替换为用户提供的真实内容,最终导航须按第 7 章用真实 URL 重写。HTML 字符串必须由 JSON 编码器正确转义。

传参示例:

  1. {
  2. "authHandle": "<login 返回的有效 authHandle>",
  3. "varName": "nav",
  4. "remark": "通用头部导航",
  5. "text": "<nav style="text-align:center; font-size:26px;">n<a href="<真实首页 URL>">首页</a>n<a href="<真实关于我们 URL>">关于我们</a>n<a href="<真实新闻列表 URL>">新闻列表</a>n<hr/>n</nav>"
  6. }

若此时尚未取得真实 URL,可按文末闭环第 3 步先保存不含猜测链接的最小导航,待第 8 步拿到真实 URL 后再按真实变量 ID 更新;不得用 about.htmlnews.html 等示例路径充数。最小指导航仅保留结构、不含任何 <a href> 链接项,例如:

  1. <nav style="text-align:center; font-size:26px;">
  2. <hr/>
  3. </nav>

它保证页面有完整 nav 结构但不输出错误链接;取得真实 URL 后必须按真实变量 ID 替换为完整导航。
参数对应关系:

  1. authHandle
  2. login 成功后返回的认证句柄
  3. varName = nav
  4. 模板变量名称
  5. remark = 通用头部导航
  6. 后台备注
  7. text
  8. nav 的完整 HTML 代码

如果是新建变量:

  1. id

可以省略,也可以传:

  1. 0

不需要自行传:

  1. userid
  2. siteid
  3. templateName

这些信息由当前登录站点状态自动确定。
正确返回结果应满足:

  1. {
  2. "result": 1,
  3. "info": "123"
  4. }

其中:

  1. result = 1
  2. 模板变量保存成功
  3. info = "123"
  4. 示例中的模板变量 ID

实际 ID 必须以接口真实返回值为准;只有 info 能严格解析为大于 0 的模板变量 ID 时才保存,用于后续更新。若 result=1info 为空或为非数字成功文本,变量可能已保存但当前 MCP 无法定位它,必须停止后续覆盖操作并由后台确认,不能猜 ID 或用 id=0“更新”。
结果判断:
| 返回情况 | 是否正确 | 处理 |
|—-|—-|—-|
| result = 1info 为已确认的正整数 ID | 正确 | nav 创建成功,保存真实 ID 后继续创建 footer |
| result = 1info 不是有效 ID | 不完整 | 停止依赖该 ID 的更新操作,要求后台确认,避免重复创建 |
| result = 0 | 不正确 | 模板变量保存业务失败,应查看 info |
| result = 2 | 不正确 | 未登录或 authHandle 已失效,需要重新 login |
| 返回 mcpError | 不正确 | MCP 适配器发生传输、协议、序列化或参数转换错误 |
创建成功后:

  1. {include=nav}

即可用于模板页面中引用该变量。

nav 保存成功以后,再次调用:

  1. save_template_var

创建 footer

⚠️ 不可直接提交:原始模板里的 wang.market、作者名、QQ 群号等都是原模板自带内容;下面已统一改成占位符,执行前必须替换为用户提供的真实署名与联系方式(QQ 群号后续会按第 8 章改成 {var.qq})。

传参示例:

  1. {
  2. "authHandle": "<login 返回的有效 authHandle>",
  3. "varName": "footer",
  4. "remark": "通用页面底部",
  5. "text": "<footer style="text-align:center; padding-top:30px;">n<hr/>npower by: <用户提供的真实署名> &nbsp;nauthor: <用户提供的真实作者名> &nbsp;nQQ群:<用户提供的真实 QQ 群号> n</footer>"
  6. }

参数对应关系:

  1. authHandle
  2. 与前面创建 nav 时使用同一个仍然有效的 authHandle
  3. varName = footer
  4. 模板变量名称
  5. remark = 通用页面底部
  6. 后台备注
  7. text
  8. footer 的完整 HTML 代码

正确返回结果同样应满足:

  1. {
  2. "result": 1,
  3. "info": "124"
  4. }

其中:

  1. result = 1
  2. footer 保存成功
  3. info = "124"
  4. 示例中的模板变量 ID

实际 ID 以真实接口返回值为准;只有正整数 info 才能作为后续更新 id
保存成功以后:

  1. {include=footer}

即可在模板页面中调用该变量。

2.2.5 模板变量 MCP 调用的正确顺序

本流程要求:在调用 save_template_page_text 保存包含 {include=...} 的页面 HTML 之前,先创建对应模板变量并确认保存成功。 这是为了保证生成时有可替换内容;不要把“协议层 text 可选”理解成可以创建空变量继续流程。
因此,本教程正确的 MCP 顺序应为:

  1. login
  2. 确认 result = 1
  3. 获得 authHandle
  4. save_template_var
  5. varName = nav
  6. text = nav 完整 HTML
  7. 确认 result = 1
  8. save_template_var
  9. varName = footer
  10. text = footer 完整 HTML
  11. 确认 result = 1
  12. 之后才能:
  13. save_template_page
  14. save_template_page_text

也就是说,不能先保存:

  1. {include=nav}
  2. {include=footer}

到模板页面,再去创建变量。
正确顺序必须是:

  1. 先创建 navfooter
  2. 确认两个 save_template_var result = 1
  3. 再保存引用它们的 index.html / about.html / news.html

如果页面引用的变量不存在或内容为空,生成结果可能保留占位符或输出空内容;必须在生成前检查变量已成功保存。
generate_site 在生成网站时,会从当前站点模板变量缓存中读取与变量代码匹配的 text,再用实际 HTML 替换:

  1. {include=nav}
  2. {include=footer}

因此:

  1. save_template_var

不仅是在后台创建一条变量记录,同时还会:

  1. 写入 template_var
  2. 写入 template_var_data
  3. 刷新模板变量缓存
  4. 记录操作日志

这一步必须在模板页面引用变量之前完成。

2.2.6 模板变量命名、嵌套、保留名与命名空间

父级源码确认模板变量本质上保存于:

  1. template_var.var_name

引用格式固定为:

  1. {include=变量名}

当前可以确定的规则:

AI 必须严格区分以下命名空间:

语法数据/机制典型用途
{include=xxx}template_var 模板变量公共 HTML 片段,如导航、页脚
{var.xxx}网站全局变量文本、图片 URL、下拉选择值等单项可维护数据
{site.xxx}网站通用标签网站名称、联系人等站点属性
{siteColumn.xxx}栏目标签当前栏目或动态调用栏目属性
{news.xxx}文章/内容标签详情内容或文章循环项
{page.xxx}分页标签列表页分页

因此不得把 site.*siteColumn.*news.*page.* 当成模板变量去创建,也不得把 {var.logo} 改写成 {include=logo}


2.3 改动模板页面

上一步我们创建了两个模板变量 navfooter,接下来,就可以将模板页面中的这两处改成动态调用模板变量。
将原来的公共头部导航代码替换为:

  1. {include=nav}

将原来的公共尾部代码替换为:

  1. {include=footer}

三个页面都同样如此。
修改后的 index.html

  1. <!DOCTYPE HTML>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>网·市场</title>
  6. </head>
  7. <body>
  8. {include=nav}
  9. <div>
  10. <h2>hi,这是首页</h2>
  11. </div>
  12. <div> 网市场云建站系统,系统成熟、流程完善、细节精致、使用简单。极低的成本投入,30秒安装部署,选好模版一键导入。最快出网站,最快赚到钱。网市场云建站系统,历经8年,不断完善,拒绝半成品!
  13. 注重实际业务应用,一切以建站公司的利益为主。
  14. </div>
  15. <div>
  16. <h3>交流反馈:</h3>
  17. 开发者姓名:管雷鸣<br/>
  18. 开发者QQ:921153866<br/>
  19. 开发者微信:xnx3com<br/>
  20. 开发者微信公众号:wangmarket<br/>
  21. 交流QQ群:472328584<br/>
  22. 官方网站:www.wang.market<br/>
  23. GitHub:github.com/xnx3/wangmarket<br/>
  24. 开源中国:gitee.com/mail_osc/wangmarket<br/>
  25. </div>
  26. {include=footer}
  27. </body>
  28. </html>

修改后的 about.html

  1. <!DOCTYPE HTML>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>网·市场</title>
  6. </head>
  7. <body>
  8. {include=nav}
  9. <h1>关于我们</h1>
  10. <div>
  11. 网市场云建站系统,于09年开发wap系统建站。之后在xnx3、iw等基础上开发而来。
  12. 于15年重新启动,<br/>
  13. 16年开始试运行<br/>
  14. 17年底正式开源发布!<br/>
  15. 截止17年底:<br/> 共建立网站服务客户一千余个,经过市场及客户验证。而非一时兴起作出来扔网上开源后就不管的<br/>
  16. 截止17年中旬,svn版本更新迭代837次、版本功能性升级57次!
  17. </div>
  18. {include=footer}
  19. </body>
  20. </html>

修改后的 news.html

  1. <!DOCTYPE HTML>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>网·市场</title>
  6. </head>
  7. <body>
  8. {include=nav}
  9. <h1>新闻列表</h1>
  10. <ul>
  11. <li><a href="about.html">v4.0升级了!</a></li>
  12. <li><a href="about.html">v3.9升级了!</a></li>
  13. <li><a href="about.html">v3.8.1升级了!</a></li>
  14. <li><a href="about.html">v3.8升级了!</a></li>
  15. <li><a href="about.html">v4.0升级了!</a></li>
  16. <li><a href="about.html">v3.9升级了!</a></li>
  17. <li><a href="about.html">v3.8.1升级了!</a></li>
  18. <li><a href="about.html">v3.8升级了!</a></li>
  19. <li><a href="about.html">v4.0升级了!</a></li>
  20. <li><a href="about.html">v3.9升级了!</a></li>
  21. </ul>
  22. <div>
  23. <!--这是分页-->
  24. <a href="">首页</a>
  25. <a href="">上一页</a>
  26. <a href="">下一页</a>
  27. <a href="">尾页</a>
  28. </div>
  29. {include=footer}
  30. </body>
  31. </html>

以上三段是中间处理稿,不是可直接提交生产站点的最终 HTML。news.html 中的固定文章、about.html 链接和空分页链接只用于展示原始模板;保存到 MCP 前必须按第 6.1 节改为文章循环、真实 {news.url} 和分页 URL。about.html 也必须按第 5.1 节替换为详情模板标签。任何未完成这些转换的源码不得直接调用 save_template_page_text

⚠️ 重要提醒:模板页面必须保留完整 HTML 结构(含 <meta charset="utf-8">

在将原始 HTML 改造成模板页面时,必须保留完整的 HTML 文档结构,包括 <!DOCTYPE html><html><head><meta charset="utf-8"><title><body> 等标签。

如果只保留 body 内部内容(如只写 {include=nav} + 内容 + {include=footer}),生成的静态 HTML 文件将缺少 <head> 中的编码声明,浏览器会使用默认编码解析,导致中文乱码

正确的模板页面结构示例:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>页面标题</title>
  6. </head>
  7. <body>
  8. {include=nav}
  9. ...页面内容...
  10. {include=footer}
  11. </body>
  12. </html>

详见本文档末尾「常见问题与避坑指南」中的问题2。

3. MCP 接口

本节 JSON 只是某一版本的 tools/list 定义快照,不是可直接发送的 MCP 请求,也不保证代表当前运行时。执行前必须重新读取运行时 tools/list;只使用实际返回且 schema 匹配的工具和字段。缺少当前分支必需的工具或字段时必须停止,不得按快照补造;未使用的可选工具不构成阻断。

上游 HTTP 层信息只作实现核对(前置规则第 11 条):本文任何位置出现的上游 URL、application/x-www-form-urlencodedtokeniwSID CookiePOST /plugin/... 都只是 MCP Server 与 WangMarket 之间的实现说明,不是 AI 的执行步骤。除非用户明确要求传统 HTTP 调用,AI 只调用 MCP 工具,不得直接请求这些 URL,也不得自行构造 tokeniwSID 或 Cookie 去替代 authHandle

  1. {
  2. "jsonrpc": "2.0",
  3. "id": "<echo-request-id>",
  4. "result": {
  5. "resultType": "complete",
  6. "ttlMs": 0,
  7. "cacheScope": "private",
  8. "tools": [
  9. {
  10. "name": "login",
  11. "title": "登录网市场站点",
  12. "description": "使用用户名或邮箱与密码建立 WangMarket 上游应用认证状态。成功后返回 authHandle;后续每一个 WangMarket 业务工具调用都必须显式传入该 authHandle。MCP Server 通过 authHandle 从内部私有认证存储中解析上游 iwSID Cookie 并转发给 WangMarket,绝不向 MCP Client 暴露 iwSID Cookie 或上游 token。",
  13. "inputSchema": {
  14. "type": "object",
  15. "required": ["username", "password"],
  16. "additionalProperties": false,
  17. "properties": {
  18. "username": {
  19. "type": "string",
  20. "minLength": 1,
  21. "description": "登录用户名或邮箱。MCP HTTP 适配器必须将其编码为上游表单字段 username。"
  22. },
  23. "password": {
  24. "type": "string",
  25. "minLength": 1,
  26. "description": "登录密码。MCP Client 和 Server 不得在日志、工具摘要或普通文本回复中泄露该值。MCP HTTP 适配器必须将其编码为上游表单字段 password。"
  27. }
  28. }
  29. },
  30. "outputSchema": {
  31. "type": "object",
  32. "required": ["result", "info"],
  33. "additionalProperties": true,
  34. "properties": {
  35. "result": {
  36. "type": "integer",
  37. "enum": [0, 1, 2],
  38. "description": "上游 LoginVO/BaseVO 状态码。1=登录成功,0=登录业务失败,2=未登录或 WangMarket 上游应用认证状态无效。"
  39. },
  40. "info": {
  41. "type": "string",
  42. "description": "上游登录结果说明。失败时可以直接作为面向用户的错误文本。"
  43. },
  44. "authHandle": {
  45. "type": ["string", "null"],
  46. "description": "仅 result=1 时返回的不透明认证句柄。后续每一个业务工具 save_template_var、save_site_column、save_news、save_alone_page_content、save_template_page、save_template_page_text、save_template、save_site_var、save_site_var_value、generate_site 都必须原样传入此值。它不是 iwSID、上游 token、用户名或密码;不得尝试解析、修改或记录其完整值。"
  47. },
  48. "user": {
  49. "type": ["object", "null"],
  50. "description": "登录用户信息。服务端已过滤密码等敏感字段;字段集合可能随服务端版本变化。"
  51. },
  52. "parentAgency": {
  53. "type": ["object", "null"],
  54. "description": "当前用户的上级代理信息;没有上级代理时可能为空。"
  55. },
  56. "mcpError": {
  57. "type": ["object", "null"],
  58. "description": "仅 MCP 适配器自身失败时出现,不是上游 LoginVO 字段。",
  59. "properties": {
  60. "kind": {"type": "string", "enum": ["transport", "protocol", "serialization", "adapter"]},
  61. "message": {"type": "string"}
  62. }
  63. }
  64. }
  65. }
  66. },
  67. {
  68. "name": "save_template_var",
  69. "title": "保存模板变量",
  70. "description": "创建或更新当前登录站点的公共模板变量。变量由 varName 和 text 组成:varName 是页面 HTML 中 {include=变量名} 的引用名,text 是生成整站时替换该占位符的完整 HTML。必须先成功保存变量,才保存引用它的页面 HTML。常见变量为 nav(导航)和 footer(页脚),但它们只是推荐名称,不是系统保留字。",
  71. "inputSchema": {
  72. "type": "object",
  73. "required": ["authHandle", "varName"],
  74. "additionalProperties": false,
  75. "properties": {
  76. "authHandle": {
  77. "type": "string",
  78. "minLength": 1,
  79. "description": "login 成功返回的不透明认证句柄。每次调用都必须显式传入;MCP Server 用它解析内部保存的 WangMarket iwSID Cookie,不会将此字段发送给上游接口。"
  80. },
  81. "id": {
  82. "type": ["integer", "null"],
  83. "default": 0,
  84. "description": "模板变量主键。缺省、null 或 0 表示创建;大于 0 表示更新。更新时 ID 对应变量必须属于当前登录站点。"
  85. },
  86. "varName": {
  87. "type": "string",
  88. "minLength": 1,
  89. "maxLength": 20,
  90. "description": "模板变量代码,例如 nav 或 footer。页面中必须通过完全相同的 {include=varName} 占位符引用,例如 {include=nav}。父级会对该值执行安全过滤。"
  91. },
  92. "remark": {
  93. "type": ["string", "null"],
  94. "maxLength": 30,
  95. "description": "变量备注,仅用于管理和识别;不会作为页面内容输出。父级会对该值执行安全过滤。"
  96. },
  97. "text": {
  98. "type": "string",
  99. "default": "",
  100. "description": "变量的完整 HTML 内容。每次调用都会覆盖该变量原内容;例如 nav 的导航片段或 footer 的页脚片段。"
  101. }
  102. }
  103. },
  104. "outputSchema": {
  105. "type": "object",
  106. "required": ["result", "info"],
  107. "additionalProperties": true,
  108. "properties": {
  109. "result": {"type": "integer", "enum": [0, 1, 2], "description": "1=保存成功,0=业务失败,2=未登录或 authHandle 无效。"},
  110. "info": {"type": "string", "description": "保存成功时为模板变量 ID;失败时为父级返回的原因。"},
  111. "mcpError": {
  112. "type": ["object", "null"],
  113. "description": "仅 MCP 适配器发生 HTTP、协议、序列化或参数转换失败时出现。"
  114. }
  115. }
  116. }
  117. },
  118. {
  119. "name": "save_site_column",
  120. "title": "创建或更新网站栏目",
  121. "description": "使用同一个工具创建或更新网站栏目并绑定模板页面。父级历史常量:1=新闻信息(已废弃),2=图文信息(已废弃),3=旧版独立页面兼容,4=留言板(已废弃),5=超链接(已废弃),6=纯文字栏目(已废弃),7=信息列表(当前),8=独立页面(当前)。当前 MCP 新建业务只使用 7 或 8;schema 中若仍兼容 1/2/3,不代表 AI 应继续新建时使用。列表栏目填写 templatePageListName,独立页面填写 templatePageViewName。TemplatePage.type 与 SiteColumn.type 是不同字段。",
  122. "inputSchema": {
  123. "type": "object",
  124. "required": ["authHandle", "name", "type"],
  125. "additionalProperties": false,
  126. "properties": {
  127. "authHandle": {"type": "string", "minLength": 1, "description": "login 返回的不透明认证句柄。"},
  128. "id": {"type": ["integer", "null"], "default": 0, "description": "栏目 ID;缺省或 0 创建,大于 0 更新。"},
  129. "name": {"type": "string", "minLength": 1, "description": "栏目名称,例如 新闻动态、关于我们。"},
  130. "type": {"type": "integer", "enum": [1, 2, 3, 7, 8], "description": "当前接口兼容的 SiteColumn 类型值。1=新闻信息(历史废弃),2=图文信息(历史废弃),3=旧版独立页面兼容值,7=信息列表(当前使用),8=独立页面(当前使用)。父级历史 4=留言板、5=超链接、6=纯文字,但不在当前 MCP schema 中。AI 新建栏目只使用 7 或 8。"},
  131. "url": {"type": ["string", "null"], "description": "历史兼容 URL 字段,通常省略。"},
  132. "icon": {"type": ["string", "null"], "description": "栏目图标 URL,可选。"},
  133. "templatePageListName": {"type": ["string", "null"], "description": "列表栏目绑定的模板页面名称。"},
  134. "templatePageViewName": {"type": ["string", "null"], "description": "详情或独立页面栏目绑定的模板页面名称;关于我们应填写此前创建的详情模板(模板页面 type=3)。"},
  135. "codeName": {"type": ["string", "null"], "description": "CMS 栏目代码。需要按代码生成页面时显式传入真实值;它不是 URL。只有已确认目标站点 generateUrlRule=code 时,才能按当前运行时规则推导文件名;否则必须使用真实返回或后台确认的栏目 URL。"},
  136. "parentCodeName": {"type": ["string", "null"], "description": "CMS 父栏目代码,可选。"},
  137. "listNum": {"type": ["integer", "null"], "default": 10, "minimum": 1, "description": "信息列表每页条数。"},
  138. "inputModelCodeName": {"type": ["string", "null"], "description": "输入模型代码。省略、null、空字符串或字符串 "0" 表示不指定自定义模型;其他值必须是当前网站真实存在的 input_model.code_name。当前 MCP 没有输入模型查询工具,不得猜测 product、news、article 等代码,也不得把源码文件路径当作参数值。"},
  139. "editMode": {"type": ["integer", "null"], "enum": [0, 1, null], "default": 0, "description": "独立页面内容编辑方式;0=内容管理 UEditor 富文本,1=直接编辑模板。省略时插件接口对 type=8/3 默认按 0 处理;要修改父级自动创建的 News 内容必须使用 0。"},
  140. "listRank": {"type": ["integer", "null"], "enum": [1, 2, null], "default": 1, "description": "列表排序:1 发布时间倒序,2 发布时间正序。"},
  141. "editUseTitlepic": {"type": ["integer", "null"], "enum": [0, 1, null], "description": "内容管理是否显示标题图片/列表图上传区域;1=显示,0=隐藏。信息列表栏目(type=7)省略时默认为0,建议显式传1;独立页面(type=8)省略时插件默认补为1。"},
  142. "editUseIntro": {"type": ["integer", "null"], "enum": [0, 1, null], "description": "内容管理是否显示简介输入区域;1=显示,0=隐藏。信息列表栏目(type=7)省略时默认为0,建议显式传1;独立页面(type=8)省略时插件默认补为1。"},
  143. "editUseText": {"type": ["integer", "null"], "enum": [0, 1, null], "description": "内容管理是否显示正文输入;1=显示 UEditor 富文本区域,0=隐藏。**信息列表栏目(type=7)省略时默认为0,必须显式传1才能看到正文文本域**;独立页面(type=8)省略时插件接口默认补为1,显式传0才会隐藏。"},
  144. "editUseExtendPhotos": {"type": ["integer", "null"], "enum": [0, 1, null], "description": "内容管理是否显示图集输入。"},
  145. "useGenerateView": {"type": ["integer", "null"], "enum": [0, 1, null], "default": 1, "description": "是否生成内容页面,默认 1。"},
  146. "templateCodeColumnUsed": {"type": ["integer", "null"], "enum": [0, 1, null], "default": 1, "description": "模板栏目调用中是否显示,默认 1。"},
  147. "adminNewsUsed": {"type": ["integer", "null"], "enum": [0, 1, null], "default": 1, "description": "内容管理中是否显示该栏目,默认 1。"},
  148. "used": {"type": ["integer", "null"], "enum": [0, 1, null], "default": 1, "description": "栏目是否启用。"},
  149. "keywords": {"type": ["string", "null"], "description": "SEO 关键词,可选。"},
  150. "description": {"type": ["string", "null"], "description": "SEO 描述,可选。"}
  151. }
  152. },
  153. "outputSchema": {"type": "object", "required": ["result", "info"], "additionalProperties": true, "properties": {"result": {"type": "integer", "enum": [0, 1, 2]}, "info": {"type": "string"}, "mcpError": {"type": ["object", "null"]}}}
  154. },
  155. {
  156. "name": "save_news",
  157. "title": "创建或更新新闻资讯内容",
  158. "description": "使用同一个工具创建或更新信息列表栏目的新闻内容。创建时省略 id 或传 0;更新时传入已有 News.id。当前 MCP schema 在两种操作中都要求 cid,它必须是已确认属于当前站点的真实栏目 ID。保存成功后必须调用 generate_site;预览地址只能使用真实返回、已知上下文或后台确认的 URL。",
  159. "inputSchema": {
  160. "type": "object",
  161. "required": ["authHandle", "cid", "title", "text"],
  162. "additionalProperties": false,
  163. "properties": {
  164. "authHandle": {"type": "string", "minLength": 1, "description": "login 返回的不透明认证句柄。"},
  165. "id": {"type": ["integer", "null"], "default": 0, "description": "News.id;省略或 0 表示创建,大于 0 表示更新。"},
  166. "cid": {"type": "integer", "minimum": 1, "description": "新闻所属栏目 SiteColumn.id。仅当 save_site_column 的 result=1 且 info 可严格解析为已确认属于当前站点的大于 0 的栏目 ID 时使用;不能传非数字 info、栏目代码或模板页面 ID。"},
  167. "title": {"type": "string", "minLength": 1, "description": "新闻标题。"},
  168. "titlepic": {"type": "string", "default": "", "description": "标题图片 URL,可选。"},
  169. "intro": {"type": "string", "default": "", "description": "新闻简介,可选。"},
  170. "text": {"type": "string", "description": "新闻正文的完整 HTML。"}
  171. }
  172. },
  173. "outputSchema": {"type": "object", "required": ["result", "info"], "additionalProperties": true, "properties": {"result": {"type": "integer", "enum": [0, 1, 2]}, "info": {"type": "string"}, "mcpError": {"type": ["object", "null"]}}}
  174. },
  175. {
  176. "name": "save_alone_page_content",
  177. "title": "保存独立页面栏目内容",
  178. "description": "修改独立页面栏目自动创建的内容。仅当 cid 已确认属于当前站点、栏目类型为当前独立页面 type=8(或已确认兼容的历史 type=3)、SiteColumn.editMode=0,且该栏目确实只有一条目标内容时使用。底层按 cid 查询单条 News;若历史数据存在多条同 cid 记录,目标记录不确定,必须停止并由后台确认。保存后必须调用 generate_site,再使用真实 URL 预览。",
  179. "inputSchema": {"type": "object", "required": ["authHandle", "cid", "title", "text"], "additionalProperties": false, "properties": {"authHandle": {"type": "string", "minLength": 1, "description": "login 返回的不透明认证句柄。"}, "cid": {"type": "integer", "minimum": 1, "description": "已确认属于当前站点的独立页面栏目 ID;仅接受 save_site_column 的 result=1 且 info 可严格解析为大于 0 的真实 ID。"}, "title": {"type": "string", "minLength": 1, "description": "内容标题,关于我们通常填写 关于我们。"}, "text": {"type": "string", "description": "要保存的完整正文 HTML。"}, "intro": {"type": "string", "default": "", "description": "内容简介;为空时父级从正文自动截取。"}, "titlepic": {"type": "string", "default": "", "description": "标题图片 URL,可选。"}, "htmlName": {"type": "string", "default": "", "description": "自定义静态 HTML 文件名,不含扩展名可选;不能据此推导预览 URL。"}, "reserve1": {"type": "string", "default": "", "maxLength": 10, "description": "输入模型预留字段 1,可选。"}, "reserve2": {"type": "string", "default": "", "maxLength": 10, "description": "输入模型预留字段 2,可选。"}}},
  180. "outputSchema": {"type": "object", "required": ["result", "info"], "additionalProperties": true, "properties": {"result": {"type": "integer", "enum": [0, 1, 2]}, "info": {"type": "string"}, "mcpError": {"type": ["object", "null"]}}}
  181. },
  182. {
  183. "name": "save_template_page",
  184. "title": "保存模板页面基本信息",
  185. "description": "创建或更新当前登录站点的 TemplatePage 元数据。该工具不保存 HTML 正文;需要保存正文时,必须在页面存在后调用 save_template_page_text。MCP 接口只支持首页、列表页和详情页三种类型;关于我们等单页面使用详情页 type=3。",
  186. "inputSchema": {
  187. "type": "object",
  188. "required": ["authHandle", "name", "type"],
  189. "additionalProperties": false,
  190. "properties": {
  191. "authHandle": {
  192. "type": "string",
  193. "minLength": 1,
  194. "description": "login 成功返回的不透明认证句柄。每次调用都必须显式传入。MCP Server 使用它解析内部保存的 WangMarket iwSID Cookie;不会将该字段发送给上游 saveTemplatePage 接口。"
  195. },
  196. "id": {
  197. "type": ["integer", "null"],
  198. "default": 0,
  199. "description": "模板页面主键。缺省、null 或 0 表示创建;大于 0 表示更新。更新时该 ID 对应的页面必须存在且属于当前站点。"
  200. },
  201. "name": {
  202. "type": "string",
  203. "minLength": 1,
  204. "maxLength": 20,
  205. "description": "模板页面名称,也是 save_template_page_text 的 pageName 定位键,例如 index 或 about。父级会安全过滤该值;同一站点、同一模板下名称不可重复。"
  206. },
  207. "type": {
  208. "type": "integer",
  209. "enum": [1, 2, 3],
  210. "description": "MCP 接口允许的 TemplatePage 类型:1=首页,2=新闻列表,3=新闻详情。关于我们等单页面统一使用 3。类型 1 在同一站点只能存在一个;0 和 6 不属于本 MCP 接口支持范围。"
  211. },
  212. "templateName": {
  213. "type": ["string", "null"],
  214. "description": "页面所属模板名称。创建时父级会无条件改为当前站点 site.templateName;更新时父级不会修改它。普通 AI 调用应省略该参数。"
  215. },
  216. "remark": {
  217. "type": ["string", "null"],
  218. "maxLength": 30,
  219. "description": "页面备注,建议填写便于后台识别,如'网站首页'、'关于我们独立页面'、'新闻列表页'。省略时后台备注列为空。父级会对该值执行安全过滤。"
  220. },
  221. "editMode": {
  222. "type": ["integer", "null"],
  223. "enum": [1, 2, null],
  224. "default": 2,
  225. "description": "TemplatePage 编辑模式:1=智能/可视化模式,2=代码模式。父级源码已标记可视化模式即将废弃、不建议使用;当前仅确认 iframe 编辑、在 </head> 前注入 htmledit.js、注入 htmledit_upload_url、保存时清理 XNX3HTMLEDIT 标记区和编辑器附加资源/属性。没有完整 DOM/API 规范,因此 AI/MCP 默认必须显式传 2。"
  226. }
  227. }
  228. },
  229. "outputSchema": {
  230. "type": "object",
  231. "required": ["result", "info"],
  232. "additionalProperties": true,
  233. "properties": {
  234. "result": {"type": "integer", "enum": [0, 1, 2], "description": "1=保存成功,0=业务失败,2=未登录。"},
  235. "info": {"type": "string", "description": "保存成功时为模板页面 ID;失败时为父级返回的原因。"},
  236. "mcpError": {
  237. "type": ["object", "null"],
  238. "description": "仅适配器发生 HTTP、协议、序列化或参数转换失败时出现。"
  239. }
  240. }
  241. }
  242. },
  243. {
  244. "name": "save_template_page_text",
  245. "title": "保存模板页面 HTML 内容",
  246. "description": "按照 pageName 完全覆盖当前登录站点指定模板页面的 HTML 内容。必须先通过 save_template_page 创建页面,或确认目标页面已存在。",
  247. "inputSchema": {
  248. "type": "object",
  249. "required": ["authHandle", "pageName", "html"],
  250. "additionalProperties": false,
  251. "properties": {
  252. "authHandle": {
  253. "type": "string",
  254. "minLength": 1,
  255. "description": "login 成功返回的不透明认证句柄。每次调用都必须显式传入。MCP Server 用它解析 WangMarket 上游认证状态;不会将该字段发送给上游 saveTemplatePageText 接口。"
  256. },
  257. "pageName": {
  258. "type": "string",
  259. "minLength": 1,
  260. "description": "目标页面名称,对应 template_page.name,不是页面 ID。父级会安全过滤此值;它必须与已保存的页面名称一致。"
  261. },
  262. "html": {
  263. "type": "string",
  264. "description": "完整 HTML 源码。每次保存会覆盖原内容。模板自带 CSS、JS、图片等资源必须使用 {templatePath}/相对路径引用,不得写死本地或云端模板域名。代码模式基本直接保存;可视化模式会清理编辑器标记区、编辑器附加资源及部分编辑属性,并按父级流程处理模板内容。"
  265. }
  266. }
  267. },
  268. "outputSchema": {
  269. "type": "object",
  270. "required": ["result", "info"],
  271. "additionalProperties": true,
  272. "properties": {
  273. "result": {"type": "integer", "enum": [0, 1, 2], "description": "1=保存成功,0=业务失败,2=未登录。"},
  274. "info": {"type": "string", "description": "成功时通常为成功消息;失败时为页面不存在、变量不存在或其他父级错误原因。"},
  275. "mcpError": {
  276. "type": ["object", "null"],
  277. "description": "仅适配器失败时出现。"
  278. }
  279. }
  280. }
  281. },
  282. {
  283. "name": "generate_site",
  284. "title": "生成整站 HTML",
  285. "description": "根据当前登录站点的模板页面、模板变量、栏目和内容生成整站 HTML。工具没有业务输入参数。父级仅返回 BaseVO,不会返回 previewUrl;MCP Client 或 Host 如需预览,必须从已知站点上下文获取地址,不能编造返回字段。",
  286. "inputSchema": {
  287. "type": "object",
  288. "required": ["authHandle"],
  289. "additionalProperties": false,
  290. "properties": {
  291. "authHandle": {
  292. "type": "string",
  293. "minLength": 1,
  294. "description": "login 成功返回的不透明认证句柄。每次调用都必须显式传入。MCP Server 用它解析 WangMarket 上游认证状态;不会将该字段发送给上游 generate 接口。"
  295. }
  296. }
  297. },
  298. "outputSchema": {
  299. "type": "object",
  300. "required": ["result", "info"],
  301. "additionalProperties": true,
  302. "properties": {
  303. "result": {"type": "integer", "enum": [0, 1, 2], "description": "1=生成成功,0=业务失败,2=未登录。"},
  304. "info": {"type": "string", "description": "生成结果说明或失败原因。此字段不是预览 URL。"},
  305. "mcpError": {
  306. "type": ["object", "null"],
  307. "description": "仅适配器失败时出现。"
  308. }
  309. }
  310. }
  311. },
  312. {
  313. "name": "save_site_var",
  314. "title": "创建或更新网站全局变量",
  315. "description": "创建或更新当前网站的全局变量。全局变量在模板页面或模板变量中通过 {var.变量名} 引用,例如 {var.qq}。它与用于整段 HTML 的 {include=变量名} 模板变量完全不同,不能混用。QQ群号等普通文本使用 type=text;图片使用 type=image;固定选项使用 type=select。",
  316. "inputSchema": {
  317. "type": "object",
  318. "required": ["authHandle", "name"],
  319. "additionalProperties": false,
  320. "properties": {
  321. "authHandle": {"type": "string", "minLength": 1, "description": "login 成功返回的不透明认证句柄。MCP Server 用它解析 WangMarket 上游 iwSID 状态,不会将该字段写入 site_var。"},
  322. "updateName": {"type": "string", "default": "", "description": "修改前的变量名。新建时留空;同名修改时可与 name 相同;重命名时填写旧名称,name 填新名称。"},
  323. "name": {"type": "string", "minLength": 1, "description": "变量代码,只使用稳定简短的英文或数字,例如 qq、logo。模板引用格式为 {var.name}。"},
  324. "description": {"type": "string", "default": "", "description": "给非技术用户看的详细填写说明。应注明用途、建议字数、图片尺寸、文件格式或下拉选项含义,例如“QQ群号,只填写数字,不要填写QQ群:前缀”。"},
  325. "value": {"type": "string", "default": "", "description": "变量初始值。text 为普通文本,image 为图片 URL,select 为 valueItems 中某个选项的值。"},
  326. "type": {"type": "string", "enum": ["text", "image", "select"], "default": "text", "description": "录入类型:text 文本、image 单图片、select 下拉选择。"},
  327. "title": {"type": "string", "default": "", "description": "后台全局变量管理页面显示的标题。"},
  328. "valueItems": {"type": "string", "default": "", "description": "type=select 时的完整选项定义;当前 6.1 后台解析格式为每行 值:显示文本。非 select 类型留空。若目标运行时版本不同,必须先在后台确认格式,不能改用猜测的分隔符。"}
  329. }
  330. },
  331. "outputSchema": {
  332. "type": "object",
  333. "required": ["result", "info"],
  334. "additionalProperties": true,
  335. "properties": {
  336. "result": {"type": "integer", "enum": [0, 1, 2], "description": "1=保存成功,0=业务失败,2=未登录或认证状态无效。"},
  337. "info": {"type": "string", "description": "父级保存结果说明。"},
  338. "mcpError": {"type": ["object", "null"], "description": "仅 MCP 适配器自身失败时出现。"}
  339. }
  340. }
  341. },
  342. {
  343. "name": "save_site_var_value",
  344. "title": "修改网站全局变量值",
  345. "description": "仅修改已存在网站全局变量的值,不改变变量名称、类型、标题、说明或下拉选项。适合后续修改QQ群号、联系电话等内容;变量不存在时必须先调用 save_site_var 创建。修改后仍需调用 generate_site 发布静态页面。",
  346. "inputSchema": {
  347. "type": "object",
  348. "required": ["authHandle", "name", "value"],
  349. "additionalProperties": false,
  350. "properties": {
  351. "authHandle": {"type": "string", "minLength": 1, "description": "login 成功返回的不透明认证句柄。"},
  352. "name": {"type": "string", "minLength": 1, "description": "已存在的全局变量代码,例如 qq;必须与模板中的 {var.qq} 保持一致。"},
  353. "value": {"type": "string", "description": "新的变量值。image 类型填写图片 URL,select 类型填写已配置选项的值。"}
  354. }
  355. },
  356. "outputSchema": {
  357. "type": "object",
  358. "required": ["result", "info"],
  359. "additionalProperties": true,
  360. "properties": {
  361. "result": {"type": "integer", "enum": [0, 1, 2]},
  362. "info": {"type": "string"},
  363. "mcpError": {"type": ["object", "null"]}
  364. }
  365. }
  366. },
  367. {
  368. "name": "save_template",
  369. "title": "创建或绑定网站模板",
  370. "description": "尝试补齐当前网站 site.template_id 对应的 template 记录。该实现可能在 template_id 无效时使用 ID 1,可能创建或修改既有模板,且 template_id 已指向现存记录时不会重新绑定到其它模板。result=1 只表示本次接口执行成功,不证明模板页面归属、后台生成按钮或最终预览已经正确;调用前必须确认允许其影响现有模板,调用后仍需生成和真实预览验证。",
  371. "inputSchema": {
  372. "type": "object",
  373. "required": ["authHandle"],
  374. "additionalProperties": false,
  375. "properties": {
  376. "authHandle": {"type": "string", "minLength": 1, "description": "login 成功返回的不透明认证句柄。每次调用都必须显式传入。MCP Server 用它解析 WangMarket 上游认证状态;不会将该字段发送给上游 saveTemplate 接口。"},
  377. "name": {"type": "string", "default": "自定义模板", "description": "模板名称,可选,默认「自定义模板」。当模板不存在需要创建时使用此名称;模板已存在时,若传入非默认值则更新名称。"},
  378. "remark": {"type": "string", "default": "", "description": "模板备注,可选,默认空字符串。当模板不存在需要创建时使用此备注;模板已存在时,若传入非空值则更新备注。"}
  379. }
  380. },
  381. "outputSchema": {
  382. "type": "object",
  383. "required": ["result", "info"],
  384. "additionalProperties": true,
  385. "properties": {
  386. "result": {"type": "integer", "enum": [0, 1, 2], "description": "1=保存成功,0=业务失败,2=未登录或认证状态无效。"},
  387. "info": {"type": "string", "description": "成功时为模板 ID;失败时为错误原因。"},
  388. "mcpError": {"type": ["object", "null"], "description": "仅 MCP 适配器自身失败时出现。"}
  389. }
  390. }
  391. }
  392. ]
  393. }
  394. }

4. 创建首页

4.1 创建首页的模板页面

网市场云建站系统中,新建一个模板页面,然后将上面已经改成 {include=nav}{include=footer} 调用方式的 index.html 源代码直接复制到新建立的首页模板页面中,保存即可。
操作过程可以理解为:

  1. 模板管理
  2. 模板页面
  3. 新建模板页面
  4. 创建首页模板页面
  5. 粘贴修改后的 index.html 源代码
  6. 保存

人工后台操作和 MCP 自动操作是两条互斥路径。使用 MCP 时只调用工具,不模拟后台点击;使用人工路径时按后台页面操作,不把点击结果当作 MCP 返回值。
如果当前 AI 已连接 MCP Server,则创建首页模板页面可以按照下面的 MCP 调用顺序执行。

4.1.1 第一步:调用 login 登录网市场站点

在没有有效 authHandle 的情况下,必须先调用:

  1. login

需要传入两个参数:
| 参数 | 是否必填 | 类型 | 含义 | 首页创建时如何传 |
|—-|—-|—-|—-|—-|
| username | 是 | string | 网市场登录用户名或邮箱 | 传用户实际登录用户名或邮箱 |
| password | 是 | string | 网市场登录密码 | 传用户实际登录密码 |
传参示例:

  1. {
  2. "username": "user@example.com",
  3. "password": "<用户实际登录密码>"
  4. }

这里的密码只作为 MCP 工具调用参数使用,不能输出到普通回复、日志、工具摘要或其他持久文本中。
login 调用完成后,重点检查返回结果中的:

  1. result
  2. info
  3. authHandle

正确结果应满足:

  1. {
  2. "result": 1,
  3. "info": "<登录成功信息>",
  4. "authHandle": "<MCP Server 返回的不透明认证句柄>"
  5. }

判断规则:
| 返回情况 | 是否正确 | 后续处理 |
|—-|—-|—-|
| result = 1,且返回有效 authHandle | 正确 | 可以继续调用 save_template_page |
| result = 0 | 不正确 | 登录业务失败,停止后续操作,并查看 info |
| result = 2 | 不正确 | 未登录或上游认证状态无效,需要重新登录 |
| 返回 mcpError | 不正确 | 属于 MCP 传输、协议、序列化或适配器错误,应先处理该错误 |

4.1.2 第二步:调用 save_template_page 创建首页模板页面

登录成功并取得有效 authHandle 后,调用:

  1. save_template_page

创建首页模板页面。
首页创建时推荐传入:
| 参数 | 是否必填 | 类型 | 首页示例值 | 含义 |
|—-|—-|—-|—-|—-|
| authHandle | 是 | string | <login 返回的 authHandle> | 当前登录认证句柄 |
| name | 是 | string | index | 模板页面名称,后续保存 HTML 时 pageName 必须与此一致 |
| type | 是 | integer | 1 | 模板页面类型,1 表示首页 |
| id | 否 | integer/null | 省略或 0 | 省略、null 或 0 表示创建;大于 0 表示更新 |
| remark | 否 | string/null | 首页模板 | 页面备注,最大 30 个字符 |
| editMode | 本流程必填 | integer/null | 2 | 编辑模式;本教程每次显式传 2,不能依赖 schema 的 default |
| templateName | 否 | string/null | 普通 AI 调用应省略 | 创建时系统会自动使用当前站点的模板名称 |
完整传参示例:

  1. {
  2. "authHandle": "<login 返回的 authHandle>",
  3. "name": "index",
  4. "type": 1,
  5. "remark": "首页模板",
  6. "editMode": 2
  7. }

这里没有传:

  1. id
  2. templateName
  3. siteid
  4. userid

原因是:

  1. id 省略
  2. 表示新建页面
  3. templateName
  4. 普通 AI 创建时应省略,由当前站点自动确定
  5. siteiduserid
  6. 当前 MCP 工具参数中没有这两个字段,不能自行添加

其中:

  1. type = 1

明确表示首页。同一站点只能存在一个首页模板,因此如果当前站点已经存在首页模板,再次创建可能返回业务失败。

这里同时记录父级 TemplatePage 的完整历史常量边界,避免 AI 以后看到 06 时自行猜测:

type父级常量/含义当前结论AI/MCP 规则
0TYPE_ELSE / 其他源码只标注“其他”;保存方法没有专门业务处理,标准生成服务也没有明确的生成、绑定、预览路径禁止用于当前 MCP 建站
1首页模板当前标准模板类型使用
2文章列表模板当前标准模板类型使用
3文章详情模板当前标准模板类型;单页面已并入详情模板使用
6TYPE_ALONEPAGE / 独立页面模板父级注释:单页面如关于我们,废弃,并入详情页模板禁止新建;改用 type=3

type=0 的正确文档结论不是为它臆造一个业务场景,而是:历史上它表示“其他”,当前没有标准业务路径,MCP 不使用。
调用成功时,正确结果应类似:

  1. {
  2. "result": 1,
  3. "info": "123"
  4. }

其中:

  1. result = 1
  2. 保存成功
  3. info = "123"
  4. 示例中的模板页面 ID

这里的 123 只是示例,实际页面 ID 以接口真实返回值为准;该 ID 仅用于记录或后续明确的更新调用,不传给 save_template_page_text
结果判断:
| 返回情况 | 是否正确 | 含义与处理 |
|—-|—-|—-|
| result = 1 | 正确 | 首页模板页面基本信息创建成功;创建时 info 为页面 ID |
| result = 0 | 不正确 | 业务失败,应直接查看 info,可能是页面名称重复、已有首页模板、保存失败等 |
| result = 2 | 不正确 | 登录状态失效,不能继续,需要重新 login 获取新的 authHandle |
| 返回 mcpError | 不正确 | MCP 适配器自身发生错误 |

需要注意:save_template_page 只保存模板页面的基本信息,不会把第 2.3 节中的完整 index.html 正文保存进去。因此创建页面成功以后,还必须继续调用 save_template_page_text

4.1.3 第三步:调用 save_template_page_text 保存首页 HTML

首页模板页面已经通过 save_template_page 创建成功后,再调用:

  1. save_template_page_text

保存首页完整 HTML。
需要传入:
| 参数 | 是否必填 | 类型 | 首页示例值 | 含义 |
|—-|—-|—-|—-|—-|
| authHandle | 是 | string | <login 返回的 authHandle> | 当前有效认证句柄 |
| pageName | 是 | string | index | 目标模板页面名称,必须与前面 save_template_page.name 完全一致 |
| html | 是 | string | 第 2.3 节修改后的完整 index.html | 要保存的完整 HTML 源码 |
传参结构示例(占位符不能原样提交):

  1. {
  2. "authHandle": "<login 返回的 authHandle>",
  3. "pageName": "index",
  4. "html": "<这里必须传入第 2.3 节修改后的 index.html 完整源码>"
  5. }

实际调用时,html 不能只传上面的占位说明,而应把第 2.3 节中已经完成:

  1. {include=nav}
  2. {include=footer}

替换后的 完整 index.html 源码 作为字符串传入。
pageName 必须为:

  1. index

因为前一步创建页面时使用的是:

  1. {
  2. "name": "index"
  3. }

两者对应关系:

  1. save_template_page.name = index
  2. save_template_page_text.pageName = index

调用成功时,正确结果应满足:

  1. {
  2. "result": 1,
  3. "info": "<保存成功信息>"
  4. }

结果判断:
| 返回情况 | 是否正确 | 含义与处理 |
|—-|—-|—-|
| result = 1 | 正确 | index 模板页面 HTML 已保存成功 |
| result = 0 | 不正确 | 业务失败,检查 info;可能是页面不存在、模板变量不存在或模板内容保存失败 |
| result = 2 | 不正确 | 认证状态失效,需要重新 login |
| 返回 mcpError | 不正确 | MCP 适配器自身错误 |
需要特别注意:

  1. save_template_page_text

每次保存都会完整覆盖目标模板页面原有 HTML,不是追加。
同时,该工具不会自动创建页面。如果:

  1. pageName = index

对应的模板页面不存在,则保存会失败。
因此首页创建的正确 MCP 顺序是:

  1. login
  2. 获得 authHandle
  3. save_template_page
  4. 创建 name=indextype=1 的首页模板页面
  5. save_template_page_text
  6. pageName=index 写入完整 index.html

4.2 生成整站,预览成果

人工路径可以点击 生成整站 并在后台预览。MCP 路径只调用工具,生成和预览必须分开确认。
人工操作顺序:

  1. 保存首页模板页面
  2. 生成整站
  3. 生成网站静态 HTML 页面
  4. 预览网站

如果使用 MCP,在 save_template_page_text 返回成功后,先确认当前站点是否已经绑定有效 template。只有绑定缺失且用户已授权其潜在副作用时,才调用 save_template;确认绑定有效时不要重复调用。之后才能调用:

  1. generate_site

生成整站。

重要提醒:首次生成整站前只有在模板绑定缺失时才考虑调用 save_template;调用成功不等于绑定状态已经验证。

后台点击「生成整站」时,系统会校验当前网站是否已绑定有效模板(site.template_id 对应 template 表中存在记录)。如果 template 表为空或 site.template_id 指向不存在的模板,会提示:

  1. 当前网站尚未选择/导入/增加模版,生成失败!网站有模版后才能根据模版生成整站!

注意:通过 MCP 接口 generate_site(对应上游 /template/refreshForTemplate.do)生成时,可能不校验 template 表绑定,直接根据站点的模板页面生成,因此可能出现”MCP 能生成但后台按钮不能生成”的情况。

处理方式:MCP 当前没有查询模板绑定的工具;只有用户、宿主或后台提供了绑定状态,才能判断是否缺失。确认绑定缺失且用户授权其副作用后,调用 MCP 工具 save_template(对应上游 /plugin/adminapi/site/saveTemplate.json);确认 result=1 后仍需后台复核,再生成。该工具的边界和副作用见 FAQ;不得仅凭 result=1 宣称站点绑定已验证。

调用示例:

  1. {
  2. "authHandle": "<login 返回的有效 authHandle>"
  3. }

正确返回:

  1. {
  2. "result": 1,
  3. "info": "1"
  4. }

其中 info 的具体含义以当前运行时 schema 为准;不要把它当作已经验证的站点绑定证明。

调用成功后仍需按当前运行时或后台确认模板绑定;不能保证后台按钮在所有已有数据状态下都正常工作。

详见本文档末尾「常见问题与避坑指南」中的问题1。

4.2.1 generate_site 传参

当前 MCP 文档中,generate_site 只需要一个业务参数:
| 参数 | 是否必填 | 类型 | 示例值 | 含义 |
|—-|—-|—-|—-|—-|
| authHandle | 是 | string | <login 返回的 authHandle> | 当前有效登录认证句柄 |
传参示例:

  1. {
  2. "authHandle": "<login 返回的 authHandle>"
  3. }

调用关系:

  1. login
  2. authHandle
  3. save_template_page
  4. result = 1
  5. save_template_page_text
  6. result = 1
  7. 确认模板绑定;仅在绑定缺失且已获授权时调用 save_template
  8. result = 1 后仍需后台复核
  9. generate_site
  10. 使用同一个仍然有效的 authHandle
4.2.2 generate_site 正确结果与错误结果

生成成功时,正确结果应满足:

  1. {
  2. "result": 1,
  3. "info": "<生成结果说明>"
  4. }

判断规则:
| 返回情况 | 是否正确 | 结果 |
|—-|—-|—-|
| result = 1 | 正确 | 生成调用返回成功;页面内容和可访问性仍需用真实 URL 验证 |
| result = 0 | 不正确 | 生成业务失败,应查看 info;可能是模板或内容不完整、生成整站失败或生成前插件钩子失败 |
| result = 2 | 不正确 | 当前认证状态失效,必须重新调用 login 获取新的 authHandle 后再生成 |
| 返回 mcpError | 不正确 | MCP HTTP、协议、序列化或适配器发生错误 |

⚠️ result=1 的终点边界:返回 1 只表示生成调用已完成,不代表静态文件已立即可访问。必须按宿主提供的真实 URL 做一次 HTTP 与内容验收(可访问、UTF-8 中文正常、无残留模板标签)。

若验收出现 404、超时,且当前没有官方提供的轮询或生成状态查询工具,不得无限重试 generate_site,也不得猜测 URL;应记录真实错误信息并停止,等待后台确认。重复调用生成不能替代排查。
特别注意:generate_site 不会返回 previewUrl
因此下面这种假设是不正确的:

  1. {
  2. "result": 1,
  3. "previewUrl": "https://example.com/index.html"
  4. }

当前 MCP 文档明确说明,生成整站的返回结果中没有 previewUrl 字段。
因此:

  1. generate_site 返回 result = 1
  2. 只能确认生成调用返回成功
  3. 需要预览网站
  4. 必须从已知站点上下文取得网站实际访问地址
  5. 不能由 AI 根据 generate_site 返回值自行编造预览网址

使用 MCP 完成首页创建与生成整站后,保存/生成状态流程为:

  1. login
  2. result = 1
  3. 获得 authHandle
  4. save_template_page
  5. name = index
  6. type = 1
  7. result = 1
  8. save_template_page_text
  9. pageName = index
  10. html = 完整 index.html
  11. result = 1
  12. 确认绑定状态;必要且获授权时调用 save_template
  13. result = 1 后仍需绑定复核
  14. generate_site
  15. authHandle
  16. result = 1
  17. 最终结果
  18. 首页模板页面已经创建
  19. 首页 HTML 已写入
  20. 生成调用返回成功
  21. 预览仍需使用真实站点基础 URL 另行验证

5. 创建关于我们页面

5.1 创建关于我们的模板页面

关于我们页面,是一个内容展示性页面,向访客展示关于我们的图文内容。
因此,在添加模板页面时,选择 详情页模板
关于我们的模板页面,主要是标题、正文的显示。
创建一个”关于我们”模板页面,并以经过第 2 步处理后的 about.html 页面结构作为基础。
关于我们属于 详情页模板。本教程示例用文章信息标签调出当前详情页内容,但详情标签的可用性必须以目标运行时帮助页或真实生成结果为准;资料不一致且无法确认时先暂停。

关于我们详情页的文章信息标签(需运行时确认)

适用范围:
| 功能模块分类 | 是否适用 |
|—-|—-|
| 模板页面 → 详情页 | √ |
标签列表:
| 标签 | 说明 | 类型 | 示例 |
|—-|—-|—-|—-|
| {news.id} | 文章编号 | 整数 | 1 |
| {news.title} | 文章的标题 | 字符串 | 产品周边 |
| {news.titlepic} | 文章的列表图 | URL | <用户提供的真实图片 URL> |
| {news.intro} | 文章的简介 | 字符串 | 这是产品周边 |
| {news.url} | 该文章页面的链接地址 | URL | <运行时生成的真实详情 URL> |
| {news.cid} | 该文章所属栏目的编号 | 整数 | 1 |
| {news.text} | 文章内容 | HTML | 当前文章的内容详情 |
| {news.extend.photos} | 文章图集 | 字符串 | JSON 格式字符串,需要前端 JS 自行解析 |
| {news.extend.???} | 自定义扩展标签 | 不限 | 根据实际扩展字段使用 |
| {news.addtime} | 发布时间 | 字符串 | 2019-09-09 |
| {news.addtime.year} | 发布时间-年 | 整数 | 2019 |
| {news.addtime.month} | 发布时间-月 | 整数/字符串 | <运行时返回值;是否补零需确认> |
| {news.addtime.day} | 发布时间-日 | 整数/字符串 | <运行时返回值;是否补零需确认> |
| {news.addtime.hour} | 发布时间-时 | 整数 | 10 |
| {news.addtime.minute} | 发布时间-分 | 整数 | 23 |
对于”关于我们”页面,最核心的两个标签是:

  1. {news.title}
  2. 调出当前关于我们内容的标题
  3. {news.text}
  4. 调出当前关于我们内容的正文 HTML

因此,原始 about.html 中原本写死的:

  1. <h1>关于我们</h1>
  2. <div>
  3. 网市场云建站系统,于09年开发wap系统建站。之后在xnx3、iw等基础上开发而来。
  4. 于15年重新启动,<br/>
  5. 16年开始试运行<br/>
  6. 17年底正式开源发布!<br/>
  7. 截止17年底:<br/> 共建立网站服务客户一千余个,经过市场及客户验证。而非一时兴起作出来扔网上开源后就不管的<br/>
  8. 截止17年中旬,svn版本更新迭代837次、版本功能性升级57次!
  9. </div>

可以在制作详情页模板时改成:

  1. <h1>{news.title}</h1>
  2. <div>
  3. {news.text}
  4. </div>

如果页面还需要显示简介、列表图、发布时间等信息,也可以继续使用(字段必须由当前帮助页/运行时确认):

  1. {news.intro}
  2. {news.titlepic}
  3. {news.addtime}

或更细的时间标签:

  1. {news.addtime.year}
  2. {news.addtime.month}
  3. {news.addtime.day}
  4. {news.addtime.hour}
  5. {news.addtime.minute}

如果后续使用自定义扩展字段,则使用:

  1. {news.extend.???}

其中 ??? 应替换为实际已经存在的扩展字段名,不能凭空编造字段名。
{news.extend.photos} 也不是每篇内容都必然存在;只有当前站点的真实输入模型和内容记录已经定义并填充该字段时才能使用。当前 save_news 工具没有 photos 参数,不得据此编造上传或扩展字段接口。月份、日期是否补前导零同样以当前运行时实测为准,需要固定两位时由模板或前端格式化。
如果使用当前 MCP 接口,可以通过:

  1. save_template_page
  2. save_template_page_text

完成”关于我们”模板页面本身的创建和 HTML 保存。
如果前面创建首页时取得的 authHandle 仍然有效,可以继续使用,不需要重复登录;如果任何业务工具返回:

  1. result = 2

则说明认证状态已经无效,需要重新调用 login 获取新的 authHandle

5.1.1 调用 save_template_page 创建关于我们模板页面

最新 MCP 文档已经明确:

  1. MCP 接口只支持首页、列表页和详情页三种类型

其中:

  1. type = 1
  2. 首页
  3. type = 2
  4. 新闻列表
  5. type = 3
  6. 详情页

并且最新 MCP 文档明确规定:

  1. 关于我们等单页面统一使用 type = 3

因此,”关于我们”通过 MCP 创建模板页面时,必须使用:

  1. type = 3

不能再使用旧版本中的:

  1. type = 6

父级源码已经把 TYPE_ALONEPAGE = 6 标记为:

  1. 单页面如关于我们,废弃,并入详情页模板

因此这里不是“暂时不推荐 6”,而是当前模型层已经把独立页面模板职责并入 type=3。最新 MCP 接口的 type 参数只允许:

  1. 1
  2. 2
  3. 3

06 均不属于当前 MCP 接口支持范围。
关于我们页面推荐传入以下参数:
| 参数 | 是否必填 | 类型 | 关于我们示例值 | 含义 |
|—-|—-|—-|—-|—-|
| authHandle | 是 | string | <有效 authHandle> | 当前登录认证句柄 |
| name | 是 | string | about | 模板页面名称,也是后续保存 HTML 时的定位名称 |
| type | 是 | integer | 3 | 详情页类型;关于我们等单页面统一使用该类型 |
| id | 否 | integer/null | 省略或 0 | 表示创建新页面;大于 0 表示更新已有页面 |
| remark | 否 | string/null | 关于我们 | 页面备注,最大 30 个字符 |
| editMode | 本流程必填 | integer/null | 2 | 代码模式;每次显式传 2,不依赖省略默认 |
| templateName | 否 | string/null | 省略 | 普通 AI 创建时不应自行设置,由当前站点自动确定 |
传参示例:

  1. {
  2. "authHandle": "<有效 authHandle>",
  3. "name": "about",
  4. "type": 3,
  5. "remark": "关于我们",
  6. "editMode": 2
  7. }

各参数对应关系:

  1. authHandle
  2. 使用 login 成功后返回的认证句柄
  3. name = about
  4. 将当前模板页面命名为 about
  5. 后续 save_template_page_text.pageName 也必须传 about
  6. type = 3
  7. 当前 MCP 定义的详情页类型
  8. 关于我们等单页面统一使用该值
  9. remark = 关于我们
  10. 只是页面备注,用于后台识别
  11. editMode = 2
  12. 使用代码模式保存页面

普通创建时不要额外传:

  1. siteid
  2. userid
  3. templateName

其中 siteiduserid 由当前登录状态自动确定;templateName 在普通 AI 调用时应省略。
创建成功时,正确结果应类似:

  1. {
  2. "result": 1,
  3. "info": "456"
  4. }

其中:

  1. result = 1
  2. 模板页面基本信息保存成功
  3. info = "456"
  4. 示例中的模板页面 ID

这里的 456 只是示例,实际模板页面 ID 必须以 MCP 接口真实返回值为准;保存正文时仍使用精确 pageName=about,不能把该 ID 传给 save_template_page_text
结果判断:
| 返回情况 | 是否正确 | 处理 |
|—-|—-|—-|
| result = 1 | 正确 | 关于我们模板页面基本信息创建成功,可以继续保存 about.html |
| result = 0 | 不正确 | 业务失败,直接查看 info;可能是页面名称重复、保存失败等 |
| result = 2 | 不正确 | 当前认证状态失效,停止后续调用并重新执行 login |
| 返回 mcpError | 不正确 | MCP 适配器自身发生传输、协议、序列化或参数转换错误 |
因此这一阶段正确的调用关系是:

  1. save_template_page
  2. authHandle = 有效认证句柄
  3. name = about
  4. type = 3
  5. remark = 关于我们
  6. editMode = 2
  7. result = 1
  8. 取得 info 中返回的模板页面 ID
  9. 继续保存 HTML 正文

5.1.2 调用 save_template_page_text 保存 about.html

关于我们模板页面创建成功后,调用:

  1. save_template_page_text

参数为:
| 参数 | 是否必填 | 类型 | 关于我们示例值 | 含义 |
|—-|—-|—-|—-|—-|
| authHandle | 是 | string | <有效 authHandle> | 当前认证句柄 |
| pageName | 是 | string | about | 必须与前一步 name=about 完全一致 |
| html | 是 | string | 第 2.3 节修改后的完整 about.html | 关于我们页面完整 HTML |
传参示例:

  1. {
  2. "authHandle": "<有效 authHandle>",
  3. "pageName": "about",
  4. "html": "<这里必须传入第 2.3 节修改后的 about.html 完整源码>"
  5. }

实际调用时:

  1. html

应传入已经完成详情页模板化处理后的完整 about.html 源码(WangMarket 6.1 已确认详情页 {news.*} 可用,源码 replaceNewsTag() 主动替换)。其中应包含:

  1. {include=nav}
  2. {news.title}
  3. {news.text}
  4. {include=footer}

跨版本注意:6.1 版本详情页 {news.title}/{news.text} 已确认可用。若目标版本不是 6.1,帮助页 details.jsp 表格的”不可用”标注可能生效,应按 11.1 实测确认。
也就是说,除了将公共头尾改成:

  1. {include=nav}
  2. {include=footer}

之外,还应将原本写死的”关于我们”标题和正文分别替换为:

  1. {news.title}
  2. {news.text}

然后再把这份完整 about.html 作为 html 参数传入。
对应关系必须保持:

  1. save_template_page.name = about
  2. save_template_page_text.pageName = about

也就是说,不能创建时使用:

  1. name = about

保存 HTML 时却改成其他:

  1. pageName

否则系统无法正确找到目标模板页面。
保存成功时,正确结果应满足:

  1. {
  2. "result": 1,
  3. "info": "<保存成功信息>"
  4. }

判断规则:
| 返回情况 | 是否正确 | 处理 |
|—-|—-|—-|
| result = 1 | 正确 | 关于我们模板页面 HTML 保存成功 |
| result = 0 | 不正确 | 检查 info;可能是页面不存在、变量不存在或模板内容保存失败 |
| result = 2 | 不正确 | 认证状态失效,需要重新执行 login |
| 返回 mcpError | 不正确 | 先处理 MCP 适配器错误 |
完成以后,MCP 能确认的结果是:

  1. name = about
  2. type = 3
  3. 的详情页模板页面已经创建
  4. +
  5. about.html 完整模板 HTML 已保存

因此,关于我们模板页面这一阶段完整 MCP 调用流程为:

  1. 已有有效 authHandle
  2. save_template_page
  3. name = about
  4. type = 3
  5. remark = 关于我们
  6. editMode = 2
  7. 确认 result = 1
  8. save_template_page_text
  9. pageName = about
  10. html = 完整 about.html
  11. 确认 result = 1

当前完整 MCP 已经定义:

  1. save_site_column
  2. save_alone_page_content

因此后续 5.2 可以通过 save_site_column 创建并绑定“关于我们”独立页面栏目;只有当前实现已由后台/运行时确认自动生成且唯一的目标内容时,5.3 才能通过 save_alone_page_content 修改它。若实际连接到的 MCP Server 缺少这些工具,则以运行时工具列表为准,不得自行虚构调用。

5.2 创建”关于我们”栏目

创建一个栏目,栏目名为”关于我们”,并给此栏目选上刚创建的”关于我们”详情页模板页面。
后台操作关系:

  1. 创建"关于我们"详情页模板
  2. 创建"关于我们"栏目
  3. 栏目类型选择独立页面
  4. 给栏目选择刚创建的 about 详情页模板
  5. 保存

如果当前 AI 已连接最新 MCP Server,则可以直接调用:

  1. save_site_column

创建”关于我们”栏目,并绑定前面已经创建好的 about 详情页模板。

5.2.1 save_site_column 参数说明与 SiteColumn.type 完整历史定义

父级 SiteColumn.java 已给出栏目类型的完整历史定义。这里必须把“历史常量”和“当前 AI 应使用的值”分开理解:

type常量准确含义当前状态AI/MCP 新建规则
1TYPE_NEWS新闻信息CMS 已废弃不使用
2TYPE_IMAGENEWS图文信息CMS 已废弃不使用
3TYPE_PAGE独立页面旧版本兼容不作为新建首选
4TYPE_LEAVEWORD留言板CMS 已废弃当前 MCP 不使用
5TYPE_HREF超链接CMS 已废弃当前 MCP 不使用
6TYPE_TEXT纯文字栏目CMS 已废弃当前 MCP 不使用
7TYPE_LIST信息列表当前 CMS 使用新闻、产品、案例等列表栏目使用
8TYPE_ALONEPAGE独立页面当前 CMS 使用关于我们、联系我们等单页面栏目使用

因此当前 MCP 新建业务固定按下列规则:

  1. 新闻资讯等信息列表栏目 SiteColumn.type = 7
  2. 关于我们等独立页面栏目 SiteColumn.type = 8

即使运行时 schema 仍兼容 123,也只表示历史兼容能力,不能据此让 AI 在新站点继续使用废弃栏目类型4/5/6 属于父级历史常量,但不在当前 MCP schema 中,更不得传入。

创建“关于我们”时的主要参数如下:

参数是否必填类型关于我们示例值含义
authHandlestring<有效 authHandle>login 成功返回的认证句柄
namestring关于我们栏目名称
typeinteger8当前独立页面栏目
idinteger/null省略或 0创建新栏目;大于 0 表示更新
templatePageViewName本流程必填string/nullabout必须与已成功保存 HTML 的详情模板页面名称完全一致
codeName条件必填string/nullabout栏目代码示例,不是预览 URL;仅在需要动态栏目调用或目标运行时要求按代码生成时才传入,且值必须是当前站点已确认存在的栏目代码;仅创建栏目且无上述需求时可按 schema 省略,省略后不得自行推导栏目 URL
inputModelCodeNamestring/null省略不指定自定义输入模型;若传其它值,必须先确认当前站点存在该 input_model.code_name
editMode本流程必填integer/null0必须为内容管理模式,供 save_alone_page_content 更新正文
editUseTextinteger/null1内容管理中显示正文输入
usedinteger/null1启用栏目
adminNewsUsedinteger/null1在内容管理中显示该栏目
useGenerateViewinteger/null1生成内容页面

codeName 的统一使用规则(适用本教程所有 save_site_column 调用,含 5.2 与 6.2)codeName 在需要动态栏目调用或目标运行时要求代码生成时才传入;值必须是当前站点已确认存在的栏目代码。仅创建栏目且没有上述需求时可按 schema 省略;省略后不得自行推导栏目 URL。本教程中的 aboutnews 仅为栏目代码格式示例;执行时必须替换为目标站点真实存在且已确认的 codeName,不得直接使用示例值。

其中最关键的对应关系为:

  1. TemplatePage.name = about
  2. TemplatePage.type = 3
  3. 详情页模板
  4. SiteColumn.name = 关于我们
  5. SiteColumn.type = 8
  6. SiteColumn.templatePageViewName = about
  7. SiteColumn.editMode = 0
  8. 当前独立页面栏目,通过内容管理维护唯一内容

不要混淆:

  1. TemplatePage.type = 3
  2. 当前文章详情模板
  3. SiteColumn.type = 3
  4. 旧版独立页面栏目兼容值

两个 type 来自不同数据对象,数字相同不代表语义相同。

关于 inputModelCodeName:省略、null、空字符串或字符串 "0" 表示不指定自定义输入模型;其它值必须是当前网站真实存在的 input_model.code_name。当前 MCP 没有输入模型查询工具,因此没有后台或已有上下文依据时只能省略,不得猜测 productnewsarticle,也不得把源码资源路径当成参数值。

5.2.2 创建”关于我们”栏目的 MCP 传参实例

推荐传参:

  1. {
  2. "authHandle": "<有效 authHandle>",
  3. "name": "关于我们",
  4. "type": 8,
  5. "templatePageViewName": "about",
  6. "codeName": "about",
  7. "editMode": 0,
  8. "editUseText": 1,
  9. "used": 1,
  10. "adminNewsUsed": 1,
  11. "useGenerateView": 1
  12. }

最新 MCP 对 save_site_column 还明确规定了上游请求编码方式(仅作实现核对信息;AI 只调用 MCP 工具,不直接发 HTTP 请求):

  1. POST /plugin/adminapi/site/column/save.json
  2. Content-Type: application/x-www-form-urlencoded

这里要区分 MCP 工具调用参数MCP Server 转发给 WangMarket 上游的 HTTP 请求

  1. AI / MCP Client
  2. 正常向 save_site_column 传结构化 arguments
  3. MCP Server
  4. arguments 转换为表单字段
  5. 使用 application/x-www-form-urlencoded 提交给 WangMarket
  6. WangMarket 上游
  7. 接收 SiteColumn 对应的表单字段

因此,AI 调用 MCP 工具时仍然可以按照上面的结构化参数传值;但 MCP Server 不能把整个参数对象直接作为 application/json 转发给上游接口
另外:

  1. authHandle

只用于 MCP 认证层,不会映射为 SiteColumn 业务字段,也不能被当作栏目字段提交给 WangMarket。
参数解释:

  1. name = 关于我们
  2. 后台栏目名称
  3. type = 8
  4. 独立页面栏目
  5. templatePageViewName = about
  6. 绑定前面创建好的 about 详情页模板
  7. codeName = about
  8. 栏目代码,仅为格式示例,执行时必须替换为目标站点真实存在且已确认的值
  9. 不是栏目网址;预览地址取决于当前站点生成 URL 规则
  10. 若本栏目不需要动态调用且目标运行时不要求按代码生成,可按 schema 省略;省略后不得推导 URL
  11. editMode = 0
  12. 内容通过内容管理中的 UEditor 富文本方式编辑
  13. 独立页面省略时,插件默认按 0 处理
  14. 要修改系统自动创建的唯一 News 内容必须使用 0
  15. 为避免歧义,建议 MCP 调用始终显式传 0
  16. editUseText = 1
  17. 内容管理中显示正文输入 / UEditor 富文本区域
  18. 独立页面省略时,插件默认补为 1
  19. 为避免歧义,建议 MCP 调用始终显式传 1
  20. used = 1
  21. 启用栏目
  22. useGenerateView = 1
  23. 允许生成内容页面
  24. type=7 信息列表栏目,控制是否为每篇新闻生成详情页
  25. type=8 独立页面栏目,当前资料未给出独立于列表栏目的特殊语义;插件接口在该字段为 null 时默认补为 1,本教程显式传 1 以保持行为明确

栏目接口默认回退(仅作实现说明,不替代显式传参):当前插件在创建栏目时,对 editMode=null 补为 0editUseText=null 补为 1useGenerateView=null 补为 1。这只能保证栏目参数有合理默认值,不能解决 M3 所述的内容记录缺失问题——内容记录是否自动创建取决于独立页面栏目的底层逻辑,与这些默认回退无关。为避免版本差异,本教程仍建议显式传入这些字段。

普通 AI 调用不要自行提交:

  1. siteid
  2. userid
  3. parentid
  4. rank

这些属于服务端控制字段。

5.2.3 正确返回结果

创建成功时,应满足:

  1. {
  2. "result": 1,
  3. "info": "789"
  4. }

其中:

  1. result = 1
  2. 栏目创建成功
  3. info = "789"
  4. 示例中的栏目 ID

info = "789" 只是示例。只有 info 能严格解析为大于 0 的整数,并且该值确实来自本次目标站点的栏目保存结果时,才能把它当作栏目 ID。当前上游在部分版本中可能返回 "成功" 等文字;此时即使 result=1 也没有得到 ID,当前 MCP 又没有栏目查询工具,必须停止并要求后台确认栏目 ID 或补充查询接口,不得继续猜测。

取得真实栏目 ID 后,下一步:

  1. save_alone_page_content

需要把它作为:

  1. cid

传入。
结果判断:
| 返回情况 | 是否正确 | 后续处理 |
|—-|—-|—-|
| result = 1info 为已确认的大于 0 的栏目 ID | 正确 | 保存该真实 ID,继续 5.3 |
| result = 1info 为空、为“成功”等非数字文本 | 不完整 | 栏目可能已保存,但缺少可用 ID;停止写入并由后台确认,避免重复创建 |
| result = 0 | 不正确 | 查看 info;可能是栏目名称为空、模板页面不存在、栏目保存失败等 |
| result = 2 | 不正确 | 认证失效,重新执行 login |
| 返回 mcpError | 不正确 | 先处理 MCP 适配器错误 |
本流程只有在 type=8editMode=0 且后台确认系统已自动创建唯一内容记录时,才进入下一步:

  1. save_site_column
  2. 创建"关于我们"栏目
  3. 当前实现尝试自动生成内容;后台确认已存在且唯一
  4. 下一步使用 save_alone_page_content 修改这条内容

5.3 修改”关于我们”的内容,预览

在当前父级实现中,创建 SiteColumn.type=8SiteColumn.editMode=0 的独立页面栏目时会尝试自动创建一条 News 内容;是否已创建成功、是否确实只有一条,必须由后台或当前运行时的真实结果确认,不能仅凭栏目接口返回成功或 info 数字推断。

这是实现边界,不是可承诺的行为save_alone_page_content 底层按 cid 查询 News,源码中的查询未显式带 siteid 条件;遇到历史重复 cid 记录或跨站数据时,被更新的目标记录可能不确定。因此本文只能把它写成“需后台确认的实现边界”,不能无条件承诺“当前站点唯一、已自动创建内容”。调用前必须由后台确认该 cid 在当前站点下确有且仅有一条目标内容。

内容不存在时的硬缺口与唯一回退路径save_alone_page_content 底层先执行 SELECT * FROM news WHERE cid = ?,查询为空时立即返回错误,不会创建内容记录。当前 MCP 工具集中没有”按栏目创建独立页面内容”的替代工具(save_news 仅用于 type=7 信息列表栏目,不适用于 type=8 独立页面)。因此,如果后台确认该栏目下没有自动创建的内容记录,AI 无法仅靠现有 MCP 接口修复——必须由人工在后台”内容管理”中为该栏目手动添加一条内容,之后 AI 才能用 save_alone_page_content 更新它。在此之前,关于我们页面的 {news.title}/{news.text} 无数据来源,不得宣称该页面已完成。

后台人工操作时:

  1. 内容管理
  2. 选择"关于我们"栏目
  3. 编辑自动创建的内容
  4. 保存
  5. 生成整站
  6. 预览

注意:save_alone_page_content 不是通用的按栏目更新接口。调用前必须确认栏目属于当前站点、类型为当前独立页面 type=8(或目标版本已确认兼容的历史 type=3)、editMode=0,并且该栏目只有一条应被更新的内容。历史数据若有多条同 cid 记录,底层单条查询的目标不确定,必须停止并由后台处理。
如果使用最新 MCP,则调用:

  1. save_alone_page_content

修改已由后台/运行时确认存在且唯一的目标内容;不能仅凭栏目创建成功推断内容已经生成。

5.3.1 save_alone_page_content 参数说明

主要参数:
| 参数 | 是否必填 | 类型 | 关于我们示例值 | 含义 |
|—-|—-|—-|—-|—-|
| authHandle | 是 | string | <有效 authHandle> | 当前认证句柄 |
| cid | 是 | integer | <5.2 返回的已确认栏目 ID> | “关于我们”栏目 ID;仅接受 result=1info 能严格解析为已确认属于当前站点的大于 0 的真实 ID |
| title | 是 | string | 关于我们 | 内容标题 |
| text | 是 | string | <关于我们的完整正文 HTML> | 内容正文 HTML |
| intro | 否 | string | 省略或空字符串 | 内容简介;为空时父级可从正文自动截取 |
| titlepic | 否 | string | 省略或空字符串 | 标题图片 URL |
| htmlName | 否 | string | 省略或空字符串 | 传给内容记录的自定义文件名;当前资料未证明 6.1 生成器会采用它,不能据此推导预览 URL |
| reserve1 | 否 | string | 省略 | 输入模型预留字段 1 |
| reserve2 | 否 | string | 省略 | 输入模型预留字段 2 |
最关键的是:

  1. cid

它不是模板页面 ID,也不是文章 ID,而是:

  1. 5.2 save_site_column 创建"关于我们"栏目成功后
  2. info 返回的栏目 ID

infocid 的唯一可用条件:仅当 result=1info 能严格解析为已确认属于当前站点的大于 0 的真实 ID 时,才可把它传给 cid;空值、成功 等文字、示例数字均不能使用。这一规则同样适用于本文所有把 info 当作 ID 继续传递的地方。

对应关系:

  1. save_site_column
  2. result = 1
  3. info 为可确认的正整数栏目 ID
  4. save_alone_page_content
  5. cid = 上面这个真实栏目 ID
5.3.2 MCP 传参实例

例如 5.2 创建栏目后实际返回:

  1. {
  2. "result": 1,
  3. "info": "789"
  4. }

则:

  1. cid = 789

保存”关于我们”内容时:

  1. {
  2. "authHandle": "<有效 authHandle>",
  3. "cid": 789,
  4. "title": "关于我们",
  5. "text": "<p>这里填写关于我们的实际正文 HTML</p>"
  6. }

注意:
这里的 text网站后台实际文章内容,不是 about.html 模板源码。
二者必须区分:

  1. save_template_page_text html 参数
  2. 保存 about.html 详情页模板代码
  3. 模板中使用 {news.title}、{news.text}
  4. save_alone_page_content.text
  5. 保存"关于我们"这篇实际内容的正文 HTML
  6. 生成网站时会由 {news.text} 调出

因此完整关系为:

  1. about.html 模板:
  2. <h1>{news.title}</h1>
  3. <div>{news.text}</div>
  4. 后台实际内容:
  5. title = 关于我们
  6. text = <p>这里是关于我们的实际介绍……</p>
  7. 生成整站后:
  8. {news.title}
  9. 被替换为"关于我们"
  10. {news.text}
  11. 被替换为实际正文 HTML
5.3.3 正确返回结果

保存成功时,应满足:

  1. {
  2. "result": 1,
  3. "info": "<保存成功信息>"
  4. }

结果判断:
| 返回情况 | 是否正确 | 处理 |
|—-|—-|—-|
| result = 1 | 正确 | 关于我们实际内容已更新,可以继续生成整站 |
| result = 0 | 不正确 | 查看 info;可能是栏目不存在、未找到自动创建内容、内容保存失败 |
| result = 2 | 不正确 | 认证失效,重新 login |
| 返回 mcpError | 不正确 | MCP 适配器错误 |
该工具自身不会创建第二条内容,而是按 cid 查询一条已有内容再更新。调用前必须满足本节开头的类型、编辑模式、站点归属和唯一记录条件;不能把“按单条查询”误写成数据库已强制保证唯一。

执行关系:

  1. 根据 cid
  2. 找到已由后台/运行时确认存在且唯一的目标内容
  3. 更新这条内容
5.3.4 保存内容后生成整站

save_alone_page_content 返回:

  1. result = 1

以后,还必须继续调用:

  1. generate_site

传参:

  1. {
  2. "authHandle": "<同一个仍然有效的 authHandle>"
  3. }

正确结果:

  1. {
  2. "result": 1,
  3. "info": "<生成成功说明>"
  4. }

最终正确流程:

  1. save_site_column
  2. 创建关于我们栏目
  3. result = 1
  4. 仅当 info 是已确认的正整数栏目 ID 时保存并继续;否则停止
  5. save_alone_page_content
  6. cid = 栏目 ID
  7. title = 关于我们
  8. text = 实际正文 HTML
  9. result = 1
  10. generate_site
  11. result = 1
  12. generate_site.result = 1
  13. 只确认生成调用成功
  14. 使用用户、宿主或后台提供的真实 URL 发起 HTTP 预览
  15. HTTP 可访问、中文正常、没有残留模板标签,才确认关于我们页面成功

5.4 独立页面当前底层实现:为什么不再使用 TemplatePage.type=6

这一点用于回答“独立页面模板 type=6 和详情页模板 type=3 到底有什么深层区别”。父级源码已经明确:旧 TemplatePage.TYPE_ALONEPAGE = 6 的单页面模板类型已废弃,并入详情页模板。因此当前系统把“模板渲染类型”和“栏目业务类型”拆开处理。

当前关于我们页面的底层关系是:

  1. TemplatePage.type = 3
  2. 提供详情页 HTML 渲染结构
  3. 模板使用 {news.title}、{news.text} 等内容标签
  4. SiteColumn.type = 8
  5. 表示这是当前 CMS 的独立页面栏目
  6. 绑定 templatePageViewName = about
  7. 当前父级会尝试自动产生该独立页面对应的 News 内容;是否存在且唯一必须由后台/运行时确认
  8. save_alone_page_content(cid=栏目ID)
  9. 按栏目定位已确认存在且唯一的目标内容
  10. 委托内容保存逻辑更新它
  11. 不创建第二条内容
  12. generate_site
  13. 使用 type=3 详情模板 + 已确认存在的独立页面内容生成静态页面

所以当前“独立页面”不是靠 TemplatePage.type=6 来区分,而是靠:

  1. 详情模板 TemplatePage.type=3
  2. +
  3. 独立页面栏目 SiteColumn.type=8
  4. +
  5. 该栏目的已确认目标内容记录

共同实现。

这也是为什么 AI 创建“关于我们”时必须使用:

  1. TemplatePage.type = 3
  2. SiteColumn.type = 8
  3. SiteColumn.editMode = 0 # 需要通过内容管理维护正文时

而不是重新启用已经废弃的 TemplatePage.type=6


6. 创建新闻列表页面

6.1 创建”新闻列表”的模板页面

列表页模板类型的模板页面,在一个网站中可存在零个或多个。
例如:

  1. 产品列表
  2. 新闻列表
  3. 案例列表

不同的列表展示形式,可以分别使用不同的列表页模板。
本教程使用前面经过第 2 步处理后的:

  1. news.html

作为”新闻列表”模板页面的基础。

6.1.1 列表页模板可用标签范围

WangMarket 6.1 源码已确认TemplateCMS.replaceListPageTag() 主动替换 {siteColumn.*} 和全部 {page.*}replaceNewsTag() 在列表循环内逐篇替换 {news.*}。帮助页 list.jsp 表格中标注的”不可用”为过时标注,与 6.1 实际代码不符。6.1 版本可直接使用以下标签;目标版本不是 6.1 时仍须按 11.1 实测确认。

列表页(TemplatePage.type=2)可用标签:

标签/能力6.1 是否可用使用边界
模板变量 {include=...}可用页面公共片段
网站全局变量 {var.xxx}可用单项可维护数据
通用标签 {site.*}{templatePath}可用可直接使用;{templatePath} 末尾带斜杠,见 11.6
栏目标签 {siteColumn.*}6.1 可用列表页当前栏目属性;文章循环中表示当前文章关联栏目
分页标签 {page.*}6.1 可用仅用于列表页,11 个字段见 6.1.4 / 9.12
文章信息标签 {news.*}6.1 可用(仅循环内)普通位置没有”当前文章”上下文,不得直接使用;必须在 TemplateListItemStart...End 循环内
动态栏目调用可用可额外调取其它栏目、子栏目或文章列表

因此,列表页普通位置可以写当前栏目名称:

  1. <h1>{siteColumn.name}</h1>

但列表页普通位置没有”当前某一篇文章”这一上下文,所以不要直接写:

  1. {news.title}
  2. {news.url}

去假设系统会自动选择一篇文章。文章标签需要进入明确的文章循环上下文。


6.1.2 列表页文章列表调取规则

将列表页面需要展示的文章列表调取出来时,使用(6.1 已确认可用):

  1. <!--TemplateListItemStart-->
  2. 这里面可使用文章信息标签、栏目标签
  3. <a href="{news.url}">{news.title}</a>
  4. <!--TemplateListItemEnd-->

其中:

  1. <!--TemplateListItemStart-->
  2. → 一条列表项模板的开始
  3. <!--TemplateListItemEnd-->
  4. → 一条列表项模板的结束
  5. {news.url}
  6. → 当前这一条文章的详情页链接
  7. {news.title}
  8. → 当前这一条文章的标题

生成网站时,系统会根据栏目中的实际文章重复生成这段 HTML。
例如模板中:

  1. <!--TemplateListItemStart-->
  2. <a href="{news.url}">{news.title}</a>
  3. <!--TemplateListItemEnd-->

如果当前栏目中有 5 篇文章,生成后的列表页 HTML 可以类似(仅示意替换结果;数字和地址不是固定值):

  1. <a href="451.html">网站正常运行1</a>
  2. <a href="452.html">网站正常运行2</a>
  3. <a href="453.html">网站正常运行3</a>
  4. <a href="454.html">网站正常运行4</a>
  5. <a href="455.html">网站正常运行5</a>

这些 451.html455.html 只是演示用的文章链接,不能当作固定 News.id、真实详情 URL 或下一次调用的参数;实际地址必须使用运行时生成的 {news.url} 或用户/后台提供的真实 URL。
如果目标版本已确认循环和栏目标签均可用,在 TemplateListItemStartTemplateListItemEnd 内部使用栏目标签,调出的才是当前这一篇文章所属栏目的信息。

例如当前循环到的文章属于一个二级栏目,那么在该循环区域中使用栏目标签,调出的就是这个二级栏目的属性信息。

6.1.3 将原始 news.html 改造成列表页模板

原始 news.html 中的静态文章列表:

  1. <ul>
  2. <li><a href="about.html">v4.0升级了!</a></li>
  3. <li><a href="about.html">v3.9升级了!</a></li>
  4. <li><a href="about.html">v3.8.1升级了!</a></li>
  5. <li><a href="about.html">v3.8升级了!</a></li>
  6. ...
  7. </ul>

不能继续作为固定新闻数据使用。
应改造成:

  1. <ul>
  2. <!--TemplateListItemStart-->
  3. <li><a href="{news.url}">{news.title}</a></li>
  4. <!--TemplateListItemEnd-->
  5. </ul>

因此,新闻列表模板的核心结构可以写成:

  1. <!DOCTYPE HTML>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>网·市场</title>
  6. </head>
  7. <body>
  8. {include=nav}
  9. <h1>{siteColumn.name}</h1>
  10. <ul>
  11. <!--TemplateListItemStart-->
  12. <li><a href="{news.url}">{news.title}</a></li>
  13. <!--TemplateListItemEnd-->
  14. </ul>
  15. <div class="pagination">
  16. <a href="{page.firstPage}">首页</a>
  17. <a href="{page.upPage}">上一页</a>
  18. {page.upList}
  19. {page.nextList}
  20. <a href="{page.nextPage}">下一页</a>
  21. <a href="{page.lastPage}">末页</a>
  22. </div>
  23. {include=footer}
  24. </body>
  25. </html>

原始 news.html 中写死的分页链接不应继续保留为空链接。WangMarket 6.1 源码已确认 {page.*} 分页标签和 {siteColumn.name} 栏目标签在列表页可用(replaceListPageTag() 主动替换),可直接将分页区域改造成动态分页。帮助页 list.jsp 的”不可用”标记为过时标注。完整字段和 URL 规则见下一节。跨版本注意:目标版本不是 6.1 时按 11.1 实测确认。


6.1.4 列表页分页标签完整字段与生成规则

父级官方页面:

  1. src/main/webapp/WEB-INF/view/templateTag/page.jsp

源码核对版本列出 11 个分页字段;公开列表帮助页的适用性标记存在冲突,使用前仍必须按目标运行时确认:

标签含义AI 使用说明
{page.allRecordNumber}总记录数目标版本确认支持后可用于显示“共 N 条”
{page.currentPageNumber}当前页码目标版本确认支持后输出当前页数字
{page.lastPageNumber}总页数目标版本确认支持后输出最后一页页码/总页数
{page.firstPage}首页 URL目标版本确认支持后只输出地址,必须放入 href 等 URL 上下文
{page.upPage}上一页 URL目标版本确认支持后只输出地址,必须放入 href 等 URL 上下文
{page.nextPage}下一页 URL目标版本确认支持后只输出地址,必须放入 href 等 URL 上下文
{page.lastPage}尾页 URL目标版本确认支持后只输出地址,必须放入 href 等 URL 上下文
{page.haveUpPage}是否存在上一页当前核对版本若启用该标签则输出小写 true / false;跨版本需实测,不会自动禁用 DOM
{page.haveNextPage}是否存在下一页当前核对版本若启用该标签则输出小写 true / false;跨版本需实测,不会自动禁用 DOM
{page.upList}前几页页码 HTML目标版本确认支持后会生成多个 <li>
{page.nextList}后几页页码 HTML目标版本确认支持后会生成多个 <li>

如果目标版本启用这组标签,它们只适用于列表页;首页和详情页不要使用 {page.*}。公开列表帮助页标为“不可用”时,必须以该版本帮助或真实生成结果为准并暂停未确认用法。

父级生成代码确认:仅当目标站点实际使用 generateUrlRule=code,列表页静态文件规则为:

  1. 第一页:codeName.html
  2. 后续分页:codeName_页码.html

例如栏目代码为示例值 news

  1. news.html
  2. news_2.html
  3. news_3.html
  4. ...

目标版本确认支持时,{page.upList}{page.nextList} 输出页码列表 HTML,并且会产生多个 <li>;不要把它们当作单纯数字变量再机械包成一个 <li>,也不要当成 URL 放进 href

上述 code 规则只在后台确认目标站点 generateUrlRule=code 时成立。源码中另外存在 lc<ID>_<page>.htmlc<ID>.html<News.id>.html 等按 ID 组合的条件形态,但它们没有稳定公开契约,仅作当前核对版本的条件示例;自动流程一律要求真实 URL,禁止由 codeName、栏目 ID 或 News.id 推导(详见 9.12)。

在目标版本确认支持后,一个保守的分页区域可以按实际样式组合这些系统输出,例如:

  1. <div class="pagination">
  2. <span>共 {page.allRecordNumber} 条,第 {page.currentPageNumber}/{page.lastPageNumber} 页</span>
  3. <a href="{page.firstPage}">首页</a>
  4. <a href="{page.upPage}">上一页</a>
  5. <ul>
  6. {page.upList}
  7. {page.nextList}
  8. </ul>
  9. <a href="{page.nextPage}">下一页</a>
  10. <a href="{page.lastPage}">末页</a>
  11. </div>

具体 CSS 可以由模板自行控制,但 AI 不得改写或发明不存在的 {page.xxx} 字段。


6.1.5 MCP 与列表页模板标签的职责边界

最新 MCP 文档中的新闻列表模板流程明确的是:

  1. 准备 news.html
  2. save_template_page 创建 type=2 的新闻列表模板页面
  3. save_template_page_text 保存完整 news.html
  4. 后续 save_site_column 通过 templatePageListName 绑定该模板

这里的 MCP 只负责:

  1. 创建模板页面
  2. 保存完整 HTML
  3. 后续绑定模板页面名称
  4. 生成整站

MCP 本身不定义列表页内部的标签语法
因此,本文档前面已经根据列表页模板规则确定的:

  1. <!--TemplateListItemStart-->
  2. <li><a href="{news.url}">{news.title}</a></li>
  3. <!--TemplateListItemEnd-->

仍然必须保留。
也就是说:

  1. 列表页模板标签文档
  2. 决定 news.html 如何从静态列表改造成动态文章循环
  3. MCP
  4. 保存已经处理完成的最终 news.html

最新 MCP 中”保存 news.html 的完整内容”,应理解为保存完成模板化处理后的完整 HTML,不是把动态列表再改回固定静态文章。
最终通过 save_template_page_texthtml 参数保存的 news.html 应同时保留:

  1. 完整页面结构
  2. {include=nav}
  3. {include=footer}
  4. TemplateListItemStart / TemplateListItemEnd
  5. 循环区域中的 {news.url}、{news.title}
6.1.6 使用 MCP 创建”新闻列表”模板页面

如果已经存在有效 authHandle,调用:

  1. save_template_page

创建新闻列表模板页面。
最新 MCP 中:

  1. type = 2
  2. 新闻列表

推荐参数:
| 参数 | 是否必填 | 类型 | 新闻列表示例值 | 含义 |
|—-|—-|—-|—-|—-|
| authHandle | 是 | string | <有效 authHandle> | 当前认证句柄 |
| name | 是 | string | news | 模板页面名称 |
| type | 是 | integer | 2 | 新闻列表模板 |
| id | 否 | integer/null | 省略或 0 | 创建新模板页面 |
| remark | 否 | string/null | 新闻列表 | 页面备注 |
| editMode | 本流程必填 | integer/null | 2 | 每次显式传数字 2 使用代码模式;schema 可选不代表本流程可以省略 |
传参示例:

  1. {
  2. "authHandle": "<有效 authHandle>",
  3. "name": "news",
  4. "type": 2,
  5. "remark": "新闻列表",
  6. "editMode": 2
  7. }

正确结果应满足:

  1. {
  2. "result": 1,
  3. "info": "901"
  4. }

其中:

  1. result = 1
  2. 新闻列表模板页面创建成功
  3. info = "901"
  4. 示例中的模板页面 ID

实际 ID 以真实返回值为准。

6.1.7 保存新闻列表模板 HTML

模板页面创建成功以后,再调用:

  1. save_template_page_text

传入:

  1. {
  2. "authHandle": "<有效 authHandle>",
  3. "pageName": "news",
  4. "html": "<已经完成列表页模板化处理后的完整 news.html>"
  5. }

其中:

  1. pageName = news

必须与前一步:

  1. save_template_page.name = news

完全一致。
实际传入的 html 中应包含(WangMarket 6.1 已确认全部可用):

  1. 完整页面结构(含 <!DOCTYPE>、<head>、<meta charset="utf-8">、<body>)
  2. {include=nav}
  3. <h1>{siteColumn.name}</h1>
  4. <!--TemplateListItemStart-->
  5. {news.url}
  6. {news.title}
  7. <!--TemplateListItemEnd-->
  8. <a href="{page.firstPage}">首页</a>
  9. <a href="{page.upPage}">上一页</a>
  10. {page.upList}
  11. {page.nextList}
  12. <a href="{page.nextPage}">下一页</a>
  13. <a href="{page.lastPage}">末页</a>
  14. {include=footer}

跨版本注意:以上标签在 6.1 源码中已确认可用(replaceListPageTag + replaceNewsTag)。若目标版本不是 6.1,{siteColumn.name}{page.*} 可能不被解析,应按 11.1 实测确认后再使用;未确认时可用静态标题和空分页占位替代。
例如:

  1. <!DOCTYPE HTML>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>网·市场</title>
  6. </head>
  7. <body>
  8. {include=nav}
  9. <h1>{siteColumn.name}</h1>
  10. <ul>
  11. <!--TemplateListItemStart-->
  12. <li><a href="{news.url}">{news.title}</a></li>
  13. <!--TemplateListItemEnd-->
  14. </ul>
  15. <div class="pagination">
  16. <a href="{page.firstPage}">首页</a>
  17. <a href="{page.upPage}">上一页</a>
  18. {page.upList}
  19. {page.nextList}
  20. <a href="{page.nextPage}">下一页</a>
  21. <a href="{page.lastPage}">末页</a>
  22. </div>
  23. {include=footer}
  24. </body>
  25. </html>

保存成功时:

  1. {
  2. "result": 1,
  3. "info": "<保存成功信息>"
  4. }

结果判断:
| 返回情况 | 是否正确 | 处理 |
|—-|—-|—-|
| result = 1 | 正确 | 新闻列表模板 HTML 保存成功 |
| result = 0 | 不正确 | 检查 info;可能是模板页面不存在、模板变量不存在或保存失败 |
| result = 2 | 不正确 | 认证失效,重新 login |
| 返回 mcpError | 不正确 | 先处理 MCP 适配器错误 |
因此 6.1 的正确 MCP 顺序为:

  1. 前提:
  2. navfooter 模板变量已经存在
  3. save_template_page
  4. name = news
  5. type = 2
  6. editMode = 2
  7. 确认 result = 1
  8. save_template_page_text
  9. pageName = news
  10. html = 完整新闻列表模板 HTML
  11. 确认 result = 1
  12. 新闻列表模板页面创建完成
  13. 后续创建"新闻资讯"信息列表栏目时:
  14. save_site_column.templatePageListName = news
6.1.8 创建并保存新闻详情模板 newsView

新闻栏目同时依赖列表模板和详情模板。只有 news 列表模板保存成功还不能绑定栏目;必须先创建并保存本节的 newsViewnewsView 是本教程的示例名称,可替换,但创建时的 name、保存 HTML 时的 pageName 和栏目绑定时的 templatePageViewName 必须完全一致。

多个 type=3 详情模板允许共存:与 TemplatePage.type=1(首页,全站只能有一个)不同,type=3 详情模板可存在多个,每个栏目通过 templatePageViewName 绑定各自的详情模板。本教程中 about(关于我们独立页面)和 newsView(新闻详情)就是两个独立的 type=3 模板,分别绑定不同栏目。

第一步,创建详情模板元数据:

  1. {
  2. "authHandle": "<login 成功返回的真实 authHandle>",
  3. "name": "newsView",
  4. "type": 3,
  5. "remark": "新闻详情",
  6. "editMode": 2
  7. }

调用 save_template_page 后,只有 result=1 才继续。返回的 info 是页面 ID,不传给下一步。

第二步,准备完整详情页 HTML:

  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="utf-8">
  5. <title>{news.title}</title>
  6. </head>
  7. <body>
  8. {include=nav}
  9. <main>
  10. <article>
  11. <h1>{news.title}</h1>
  12. <div>{news.text}</div>
  13. </article>
  14. </main>
  15. {include=footer}
  16. </body>
  17. </html>

将上面的完整源码作为 html 调用 save_template_page_text

  1. {
  2. "authHandle": "<同一有效 authHandle>",
  3. "pageName": "newsView",
  4. "html": "<上面的完整新闻详情页 HTML>"
  5. }

只有第二步也返回 result=1,才允许在后续栏目参数中使用 templatePageViewName=newsView。当前 MCP 没有模板页面查询工具;任何一步失败或提交状态不明时必须停止,不得仅凭名称假定模板已存在,也不得盲目重试创建。

6.2 添加”新闻资讯”栏目

创建”新闻资讯”栏目,并给此栏目选择刚创建的新闻列表模板页面。
后台人工操作关系:

  1. 创建新闻列表模板页面
  2. 创建"新闻资讯"栏目
  3. 栏目类型选择信息列表
  4. 给栏目选择 news 新闻列表模板页面
  5. 设置栏目代码
  6. 保存

如果使用最新完整 MCP,可以直接调用:

  1. save_site_column

创建”新闻资讯”信息列表栏目。

6.2.1 新闻资讯栏目与新闻列表模板的对应关系

前面第 6.1 步已经创建:

  1. TemplatePage.name = news
  2. TemplatePage.type = 2

表示一个名为 news 的新闻列表模板页面。
现在创建的是:

  1. SiteColumn

网站栏目。
最新 MCP 明确规定:

  1. SiteColumn.type = 7
  2. 信息列表栏目

因此:

  1. 新闻列表模板页面
  2. save_template_page
  3. name = news
  4. type = 2
  5. 新闻资讯栏目
  6. save_site_column
  7. name = 新闻资讯
  8. type = 7
  9. templatePageListName = news

这里的两个 type 仍属于不同对象:

  1. TemplatePage.type = 2
  2. 模板页面类型:新闻列表
  3. SiteColumn.type = 7
  4. 网站栏目类型:信息列表

不能混淆。

6.2.2 save_site_column 主要参数

创建”新闻资讯”栏目时,建议使用:
| 参数 | 是否必填 | 类型 | 本教程示例值 | 含义 |
|—-|—-|—-|—-|—-|
| authHandle | 是 | string | <有效 authHandle> | 当前登录认证句柄 |
| name | 是 | string | 新闻资讯 | 栏目名称 |
| type | 是 | integer | 7 | 信息列表栏目 |
| id | 否 | integer/null | 省略或 0 | 创建新栏目;大于 0 表示更新 |
| templatePageListName | 本流程必填 | string/null | news | 必须绑定第 6.1 已成功保存的列表模板 |
| templatePageViewName | 本流程必填 | string/null | newsView | 必须绑定第 6.1.8 已成功保存的详情模板 |
| codeName | 条件必填 | string/null | news | CMS 栏目代码示例,不是 URL;传入条件与限制见 5.2.1 的统一规则:只在需要动态栏目调用或目标运行时要求代码生成时才传,且必须是当前站点已确认存在的栏目代码;可省略,但省略后不得由它推导 URL |
| listNum | 否 | integer/null | 10 | 每页文章数量 |
| listRank | 否 | integer/null | 1 | 按发布时间倒序 |
| used | 否 | integer/null | 1 | 启用栏目 |
| adminNewsUsed | 否 | integer/null | 1 | 在内容管理中显示该栏目 |
| editMode | 本流程显式传入 | integer/null | 0 | 内容管理模式;与模板页面的 editMode 不同 |
| useGenerateView | 本流程显式传入 | integer/null | 1 | 允许生成新闻详情页 |
本教程显式传入示例栏目代码:

  1. codeName = news

这里的 news 仅为栏目代码格式示例,执行时必须替换为目标站点真实存在且已确认的 codeName(传入条件见 5.2.1 的统一规则)。它不能单独证明栏目地址是 news.html。只有后台确认当前站点 generateUrlRule=code 时才能按代码规则组合文件名;其它规则可能使用栏目 ID。当前 MCP 没有站点 URL 规则或栏目查询工具,必须使用用户、宿主、真实标签输出或后台提供的 URL。

6.2.3 创建新闻资讯栏目的 MCP 传参实例
  1. {
  2. "authHandle": "<有效 authHandle>",
  3. "name": "新闻资讯",
  4. "type": 7,
  5. "templatePageListName": "news",
  6. "templatePageViewName": "newsView",
  7. "codeName": "news",
  8. "listNum": 10,
  9. "listRank": 1,
  10. "used": 1,
  11. "adminNewsUsed": 1,
  12. "editMode": 0,
  13. "useGenerateView": 1,
  14. "editUseText": 1,
  15. "editUseTitlepic": 1,
  16. "editUseIntro": 1
  17. }

参数解释:

  1. name = 新闻资讯
  2. 栏目后台显示名称
  3. type = 7
  4. 信息列表栏目
  5. templatePageListName = news
  6. 使用第 6.1 创建的 news 列表模板
  7. templatePageViewName = newsView
  8. 使用新闻详情模板(type=3),用于文章详情页
  9. codeName = news
  10. 本教程的栏目代码示例;不能直接当作预览 URL
  11. listNum = 10
  12. 每页显示 10 条内容
  13. listRank = 1
  14. 按发布时间倒序
  15. used = 1
  16. 启用栏目
  17. adminNewsUsed = 1
  18. 内容管理中显示该栏目
  19. editMode = 0
  20. 使用内容管理模式;这是 SiteColumn 字段,不是 TemplatePage.editMode
  21. useGenerateView = 1
  22. 允许为新闻内容生成详情页
  23. editUseText = 1
  24. 内容管理中显示正文富文本编辑区域(信息列表栏目省略时默认为0,必须显式传1
  25. editUseTitlepic = 1
  26. 内容管理中显示标题图片/列表图上传区域
  27. editUseIntro = 1
  28. 内容管理中显示简介输入区域

editUseTexteditUseTitlepiceditUseIntro 控制内容管理中的相应输入区域。本流程需要正文、列表图和简介,所以三者都显式传 1;若实际页面不使用列表图或简介,可在需求明确后传 0。不要依赖不同版本的省略默认值。
普通 AI 调用不要自行提交:

  1. siteid
  2. userid
  3. parentid
  4. rank

这些属于服务端控制字段。
上游接口仍然使用(仅作实现核对信息,见前置规则第 11 条):

  1. application/x-www-form-urlencoded
6.2.4 正确返回结果

栏目创建成功时,应满足:

  1. {
  2. "result": 1,
  3. "info": "1001"
  4. }

其中:

  1. result = 1
  2. 新闻资讯栏目创建成功
  3. info = "1001"
  4. 示例中的 SiteColumn.id,即栏目 ID

这里的 1001 只是示例。只有本次返回的 info 能严格解析为大于 0 的整数,并已确认是当前站点的 SiteColumn.id 时才能继续。result=1info"成功"、空值或其它非数字文本时,栏目可能已经保存,但当前 MCP 无法查询其 ID;必须停止并由后台确认,不能重试创建或猜测 ID。
因为下一步:

  1. save_news.cid

必须使用这个栏目 ID。
infocid 的唯一可用条件(与 5.3.1 同一条规则):仅当 result=1info 能严格解析为已确认属于当前站点的大于 0 的真实 ID 时,才可把它传给后续 cid;空值、成功 等文字、示例数字均不能使用。

正确对应关系:

  1. save_site_column
  2. result = 1
  3. info 为可确认的正整数栏目 ID
  4. save_news
  5. cid = 上面这个真实栏目 ID

不能把下面这些值错误地传给 cid

  1. news
  2. 新闻资讯
  3. 模板页面 ID
  4. 模板页面 name
  5. codeName

结果判断:
| 返回情况 | 是否正确 | 处理 |
|—-|—-|—-|
| result = 1info 为已确认的大于 0 的栏目 ID | 正确 | 保存真实 ID,继续 6.3 |
| result = 1info 不是有效数字 ID | 不完整 | 停止写入并由后台确认 ID,避免重复创建 |
| result = 0 | 不正确 | 查看 info;可能是栏目名称为空、模板页面不存在或保存失败 |
| result = 2 | 不正确 | 登录认证失效,重新执行 login |
| 返回 mcpError | 不正确 | 先处理 MCP 适配器错误 |
至此完成:

  1. 新闻列表模板 news
  2. +
  3. 新闻资讯栏目
  4. +
  5. templatePageListName = news
  6. +
  7. codeName = news

6.3 添加新闻资讯内容,并预览本栏目

后台人工操作时:

  1. 内容管理
  2. 新闻资讯
  3. 添加新闻内容
  4. 填写标题、正文等内容
  5. 保存
  6. 生成整站
  7. 使用后台或已有上下文提供的真实栏目 URL 预览

最新完整 MCP 已经提供:

  1. save_news

用于创建或更新信息列表栏目的新闻内容。

6.3.1 save_news 参数说明

创建新闻资讯时主要使用:
| 参数 | 是否必填 | 类型 | 本教程示例 | 含义 |
|—-|—-|—-|—-|—-|
| authHandle | 是 | string | <有效 authHandle> | 当前认证句柄 |
| cid | 是 | integer | <6.2 返回的栏目 ID> | 新闻所属 SiteColumn.id |
| title | 是 | string | v4.0升级了! | 新闻标题 |
| text | 是 | string | <p>新闻正文...</p> | 新闻正文完整 HTML |
| id | 否 | integer/null | 省略或 0 | 创建新闻;大于 0 更新已有新闻 |
| titlepic | 否 | string | <用户提供的真实图片 URL> | 标题图片;传空字符串不等于真实素材,边界见 6.3.2 |
| intro | 否 | string | 新闻简介 | 内容简介 |
其中最重要的是:

  1. cid

必须使用:

  1. 6.2 save_site_column 返回 result=1,且 info 可严格解析为已确认的正整数栏目 ID

最新 MCP 明确禁止使用:

  1. 栏目代码
  2. 模板页面 ID
  3. 模板页面名称

代替 cid

6.3.2 新增第一篇新闻的 MCP 实例

假设 6.2 创建”新闻资讯”栏目后真实返回:

  1. {
  2. "result": 1,
  3. "info": "1001"
  4. }

则:

  1. cid = 1001

新增新闻:

  1. {
  2. "authHandle": "<有效 authHandle>",
  3. "cid": 1001,
  4. "title": "v4.0升级了!",
  5. "text": "<p>这里是 v4.0 升级新闻的正文内容。</p>"
  6. }

也可以显式传:

  1. {
  2. "authHandle": "<有效 authHandle>",
  3. "id": 0,
  4. "cid": 1001,
  5. "title": "v4.0升级了!",
  6. "intro": "v4.0 版本升级说明",
  7. "titlepic": "",
  8. "text": "<p>这里是 v4.0 升级新闻的正文内容。</p>"
  9. }

其中:

  1. id 省略或 id = 0
  2. 创建新新闻
  3. id > 0
  4. 更新已有 News.id 对应的新闻

当前 MCP schema 在创建和更新时都要求 cid;更新时除了真实 News.id,仍必须传该新闻所属的真实栏目 ID。不得因上游旧说明称更新可省略 cid 而违反运行时 schema。

titlepic 空值的执行边界:示例中的 titlepic: "" 只表示“本次不设置标题图”,它不等于一张真实素材。当前核对版本在标题图为 null 时可能回退到系统默认图,空字符串的处理也需按目标版本确认,因此“页面上出现了图片”不能证明素材已上传。

关键视觉(列表图、轮播图、题图)必须使用用户或后台提供的真实图片 URL,并在 generate_site 之后用真实页面 URL 检查实际的 src:图片可访问、内容确为目标素材。没有真实图片时,不得宣称轮播或题图已经完成,也不能编造上传接口或图片地址。

6.3.3 添加多条新闻

如果要把原始 news.html 示例中的多条固定新闻变成真实后台内容,则应重复调用:

  1. save_news

例如:

  1. 1
  2. title = v4.0升级了!
  3. 2
  4. title = v3.9升级了!
  5. 3
  6. title = v3.8.1升级了!
  7. 4
  8. title = v3.8升级了!

每一次创建时都使用同一个:

  1. cid = 新闻资讯栏目 ID

同时:

  1. id 省略
  2. id = 0

每次成功都确认:

  1. result = 1

再继续下一条。

6.3.4 save_news 返回结果如何判断

正确结果必须至少满足:

  1. {
  2. "result": 1,
  3. "info": "<保存成功信息>"
  4. }

判断规则:
| 返回情况 | 是否正确 | 处理 |
|—-|—-|—-|
| result = 1 | 正确 | 新闻保存成功 |
| result = 0 | 不正确 | 查看 info;可能是栏目不存在、标题为空、内容保存失败等 |
| result = 2 | 不正确 | 认证失效,重新 login |
| 返回 mcpError | 不正确 | MCP 适配器错误 |
注意:当前完整 MCP 文档没有明确声明 save_news 成功时的 info 一定就是 News.id
因此本文档不能把:

  1. save_news.info

直接当作新闻 ID 使用。
如果以后需要通过 MCP 更新已有新闻:

  1. save_news.id = 已知 News.id

必须使用真实已知的 News.id

如果需要 AI 自动查询某篇新闻的 News.id,当前这份 MCP 文档没有提供新闻列表/查询工具,需要后续增加对应接口,不能自行猜测 ID。

6.3.5 保存新闻后生成整站

新闻内容保存完成后必须调用:

  1. generate_site

传参:

  1. {
  2. "authHandle": "<同一个仍然有效的 authHandle>"
  3. }

正确结果:

  1. {
  2. "result": 1,
  3. "info": "<生成成功说明>"
  4. }

只有:

  1. result = 1

才能确认本次生成调用返回成功;不能据此确认页面可访问或内容正确。
最新 MCP 不会返回:

  1. previewUrl

因此栏目预览地址不能从 generate_site 的返回字段中编造。
预览必须使用用户、宿主、后台或真实页面标签提供的 URL。只有已确认目标站点使用 generateUrlRule=code 时,本教程的示例 codeName=news 才可能按对应规则生成 news.html;否则不得推导。
完整 MCP 流程:

  1. save_site_column
  2. name = 新闻资讯
  3. type = 7
  4. codeName = news
  5. templatePageListName = news
  6. templatePageViewName = newsView
  7. result = 1
  8. 仅当 info 是已确认的正整数栏目 ID 时保存并继续;否则停止
  9. save_news
  10. cid = 栏目 ID
  11. title = 新闻标题
  12. text = 新闻正文 HTML
  13. result = 1
  14. 如有更多新闻:
  15. 继续调用 save_news
  16. 每条都确认 result = 1
  17. generate_site
  18. result = 1
  19. 使用真实栏目 URL 和至少一篇真实详情 URL 进行 HTTP 预览
  20. 列表、详情均可访问,中文正常,链接可用,且无未解析模板标签
  21. 新闻列表与详情流程才算成功

7. 修改导航栏菜单的链接网址

网站建立好后,导航栏必须使用当前网站的真实页面 URL。codeName 是栏目代码,不是 URL;只有后台确认当前站点 generateUrlRule=code 时,才可按该版本的代码规则生成 codeName.html。其它规则可能使用栏目 ID,当前 MCP 又没有站点 URL 规则或栏目查询工具,因此不能自行拼接。

本教程中的:

  1. 关于我们栏目:
  2. codeName = about
  3. 新闻资讯栏目:
  4. codeName = news

均为示例代码。下面只展示导航结构,三个占位值必须在调用前替换为用户、宿主、后台或已验证页面提供的真实 URL,不能原样提交:

  1. <nav style="text-align:center; font-size:26px;">
  2. <a href="<真实首页 URL>">首页</a>
  3. <a href="<真实关于我们 URL>">关于我们</a>
  4. <a href="<真实新闻列表 URL>">新闻列表</a>
  5. <hr/>
  6. </nav>

若无法取得任一真实 URL,停止更新 nav 并要求后台确认;不得用示例 about.htmlnews.html 或猜测的数字路径代替。

7.1 使用 MCP 修改 nav 模板变量

由于本教程的所有页面都通过:

  1. {include=nav}

调用公共导航,所以应优先更新:

  1. nav 模板变量

而不是逐个修改 index.htmlabout.htmlnews.html
使用:

  1. save_template_var

更新。

7.2 更新已有 nav 时必须使用模板变量 ID

save_template_var 的接口规则是:

  1. id 省略、null 0
  2. 创建新模板变量
  3. id > 0
  4. 更新已有模板变量

因此这里如果是修改已经存在的 nav,必须使用第 2.2 创建 nav 时:

  1. save_template_var
  2. result = 1
  3. info 返回的模板变量 ID

假设第 2.2 创建 nav 时返回:

  1. {
  2. "result": 1,
  3. "info": "201"
  4. }

则:

  1. nav 模板变量 ID = 201

更新时传:

  1. {
  2. "authHandle": "<有效 authHandle>",
  3. "id": 201,
  4. "varName": "nav",
  5. "remark": "通用头部导航",
  6. "text": "<nav style="text-align:center; font-size:26px;">n<a href="<真实首页 URL>">首页</a>n<a href="<真实关于我们 URL>">关于我们</a>n<a href="<真实新闻列表 URL>">新闻列表</a>n<hr/>n</nav>"
  7. }

上例中的 201 和三个 URL 都是占位示例;调用前必须分别换成创建 nav 时真实返回的模板变量 ID 和已确认 URL。
正确结果:

  1. {
  2. "result": 1,
  3. "info": "<模板变量保存成功信息或 ID>"
  4. }

然后继续:

  1. generate_site

7.3 如果没有保存 nav 的模板变量 ID

当前完整 MCP 文档没有提供:

  1. varName 查询模板变量
  2. 列出模板变量
  3. 获取 nav ID

这类工具。
因此如果前面创建 nav 时没有保存:

  1. info 返回的模板变量 ID

则不能:

  1. 猜一个 id

也不能为了”更新”而直接:

  1. id = 0

因为:

  1. id = 0
  2. 创建

不是更新。
这种情况下应:

  1. 优先从当前 AI / MCP 会话前面保存的执行结果中取回 nav ID

如果执行上下文中也没有,则需要:

  1. 进入后台确认 nav 模板变量 ID

或以后补充一个:

  1. 查询模板变量 / varName 获取模板变量

的 MCP 工具。

在没有真实 ID 的情况下,不应自行猜测。

7.4 导航修改后的完整 MCP 流程

  1. 取得并验证首页、关于我们、新闻列表的真实 URL
  2. 不能从 codeName ID 猜测
  3. 取得 nav 已有模板变量 ID
  4. save_template_var
  5. id = nav 模板变量 ID
  6. varName = nav
  7. text = 修改后的完整导航 HTML
  8. 确认 result = 1
  9. generate_site
  10. 确认 result = 1(只表示生成调用成功)
  11. 使用真实站点 URL 检查三个导航链接

即使实际栏目代码为 companyarticle,也只能在已确认 generateUrlRule=code 时使用相应 .html 路径;否则仍以真实 URL 为准。

7.5 如果网站没有使用 {include=nav}

最新 MCP 工作流说明:

  1. 如果导航没有使用 {include=nav}

才需要调用:

  1. save_template_page_text

逐个修改包含导航的模板页面完整 HTML。
但本教程已经在第 2 步统一抽取了:

  1. {include=nav}

因此本教程应优先:

  1. 只更新 nav 模板变量

再:

  1. generate_site

即可。

8. 设置全局变量

比如页面底部的 QQ 群号,如果实际使用模板的人想修改 QQ 群号,但又不懂 HTML,就不适合要求用户每次进入 footer 模板变量的 HTML 中手工查找数字。
这里使用:

  1. 全局变量

解决。
全局变量可以在:

  1. 模板页面
  2. 模板变量

中通过:

  1. {var.变量名}

调用。
例如:

  1. {var.qq}

8.1 后台人工创建全局变量

后台菜单:

  1. 模板管理
  2. 全局变量

点击:

  1. 添加全局变量

本教程以 QQ 群号为例。
原始 footer:

  1. <footer style="text-align:center; padding-top:30px;">
  2. <hr/>
  3. power by: wang.market
  4. author: 管雷鸣
  5. QQ群:472328584
  6. </footer>

其中:

  1. 472328584

适合转换成全局变量。

这里的 472328584 是原模板自带的示例 QQ 群号,不是本次建站要发布的真实号码;实际创建时必须填用户提供的真实值。
创建变量名:

  1. qq

以后 footer 中使用:

  1. QQ群:{var.qq}

8.2 使用 MCP 创建 QQ 群全局变量

最新完整 MCP 已定义:

  1. save_site_var

用于创建或更新网站全局变量。
它和:

  1. save_template_var

不是同一种变量。
区别:

  1. save_template_var
  2. 模板变量
  3. 保存整段 HTML
  4. 页面通过 {include=nav}、{include=footer} 引用
  5. save_site_var
  6. 网站全局变量
  7. 保存文本、图片、下拉值等单项数据
  8. 页面通过 {var.qq}、{var.logo} 引用

不能混用。

8.3 save_site_var 参数说明

save_site_var 保存名称、说明、值、类型、标题和选项等完整定义,不是 PATCH。新建时按本节提供完整定义;更新或重命名已有变量时,只有已从真实上下文取得并确认全部现有字段后才能调用,否则省略字段可能被保存为空。当前 MCP 没有全局变量查询工具;若只是修改一个已确认存在的变量值,应使用 8.8 的 save_site_var_value

主要参数:
| 参数 | 是否必填 | 类型 | QQ 群示例 | 含义 |
|—-|—-|—-|—-|—-|
| authHandle | 是 | string | <有效 authHandle> | 当前认证句柄 |
| name | 是 | string | qq | 全局变量代码 |
| updateName | 否 | string | 新建时省略或空 | 更新/重命名时用于定位旧变量名 |
| description | 否 | string | QQ群号,只填写数字,不要填写"QQ群:"前缀 | 给非技术用户看的填写说明 |
| value | 否 | string | <用户提供的真实 QQ 群号> | 变量初始值 |
| type | 否 | string | text | text / image / select |
| title | 否 | string | QQ群号 | 后台显示标题 |
| valueItems | 否 | string | 空 | select 类型时定义选项 |
本教程 QQ 群号使用:

  1. type = text

8.4 创建 qq 全局变量的 MCP 实例

⚠️ 不可直接提交value 必须用用户提供的真实 QQ 群号,不能沿用原模板的 472328584

  1. {
  2. "authHandle": "<有效 authHandle>",
  3. "name": "qq",
  4. "title": "QQ群号",
  5. "description": "QQ群号,只填写数字,不要填写“QQ群:”前缀",
  6. "value": "<用户提供的真实 QQ 群号>",
  7. "type": "text"
  8. }

新建时:

  1. updateName

可以省略或保持为空。
正确结果应满足:

  1. {
  2. "result": 1,
  3. "info": "<保存结果说明>"
  4. }

结果判断:
| 返回情况 | 是否正确 | 处理 |
|—-|—-|—-|
| result = 1 | 正确 | 全局变量定义保存成功 |
| result = 0 | 不正确 | 查看 info;可能是变量名不合法、类型不合法或保存失败 |
| result = 2 | 不正确 | 认证失效,重新 login |
| 返回 mcpError | 不正确 | MCP 适配器错误 |
当前接口没有说明:

  1. save_site_var.info

一定是变量 ID,所以本文档不把它当作 ID 使用。

创建全局变量还不够。
还必须把:

  1. QQ群:472328584

改为:

  1. QQ群:{var.qq}

修改后的 footer(署名与站点名必须替换为用户提供的真实值,不可直接提交):

  1. <footer style="text-align:center; padding-top:30px;">
  2. <hr/>
  3. power by: <用户提供的真实署名>
  4. author: <用户提供的真实作者名>
  5. QQ群:{var.qq}
  6. </footer>

本教程的 footer 是通过:

  1. save_template_var

创建的模板变量。
因此这里应该更新已有:

  1. footer

模板变量。

与更新 nav 一样,更新已有 footer 必须使用其真实模板变量 ID。
假设第 2.2 创建 footer 时返回:

  1. {
  2. "result": 1,
  3. "info": "202"
  4. }

则:

  1. footer 模板变量 ID = 202

⚠️ 不可直接提交202 是占位示例,必须换成第 2.2 步真实返回的 footer 模板变量 ID;text 里的署名、作者名也必须替换为用户提供的真实值。

更新:

  1. {
  2. "authHandle": "<有效 authHandle>",
  3. "id": 202,
  4. "varName": "footer",
  5. "remark": "通用页面底部",
  6. "text": "<footer style="text-align:center; padding-top:30px;">n<hr/>npower by: <用户提供的真实署名> &nbsp;nauthor: <用户提供的真实作者名> &nbsp;nQQ群:{var.qq}n</footer>"
  7. }

必须确认:

  1. result = 1

以后再生成整站。
如果 footer 的真实模板变量 ID 没有保存,则与第 7 章 nav 相同:

  1. 当前 MCP 没有模板变量查询工具

不能自行猜测 ID。

8.7 创建全局变量后的完整流程

  1. save_site_var
  2. name = qq
  3. type = text
  4. value = <用户提供的真实 QQ 群号>
  5. 确认 result = 1
  6. 取得 footer 已有模板变量 ID
  7. save_template_var
  8. id = footer ID
  9. varName = footer
  10. text = 包含 {var.qq} 的完整 footer HTML
  11. 确认 result = 1
  12. generate_site
  13. 确认 result = 1
  14. 最终结果:
  15. footer {var.qq}
  16. 生成时被替换为当前 qq 全局变量的值

仅执行:

  1. save_site_var

但不修改 footer 引用,也不会让原本写死的:

  1. 472328584

自动变成动态变量。
同样,仅修改全局变量后如果不:

  1. generate_site

已经生成的静态 HTML 也不会立即变化。

8.8 后续只修改 QQ 群号

只有已由本次创建结果、已有执行上下文或后台确认:

  1. qq

变量确实存在,并且以后只想修改值时,才使用:
使用:

  1. save_site_var_value

⚠️ 不可直接提交value 必须是用户提供的真实 QQ 群号,不能沿用或改写原模板示例号码。

参数:

  1. {
  2. "authHandle": "<有效 authHandle>",
  3. "name": "qq",
  4. "value": "新的QQ群号"
  5. }

例如:

  1. {
  2. "authHandle": "<有效 authHandle>",
  3. "name": "qq",
  4. "value": "<用户提供的真实 QQ 群号>"
  5. }

正确结果:

  1. result = 1

然后必须继续:

  1. generate_site

完整顺序:

  1. save_site_var_value
  2. name = qq
  3. value = 新值
  4. result = 1
  5. generate_site
  6. result = 1
  7. 重新访问受影响页面

这里不需要:

  1. 重新创建 qq
  2. 修改 type
  3. 重新编辑 footer

因为 footer 已经引用:

  1. {var.qq}

8.9 图片、下拉类型全局变量

当前 MCP 的 save_site_var.type schema 暴露:

  1. text
  2. image
  3. select

三种录入类型。这里不能据此断言 WangMarket 所有版本只支持这三种类型;自动执行只能传运行时 schema 允许的值。三种类型在模板端的引用语法相同,统一使用 {var.变量名};类型只决定后台如何录入及 value 如何解释。

8.9.1 image 类型

例如创建网站 LOGO:

  1. {
  2. "authHandle": "<有效 authHandle>",
  3. "name": "logo",
  4. "title": "网站LOGO",
  5. "description": "上传网站LOGO,建议尺寸 320×240,请保持清晰。",
  6. "value": "<用户提供或后台已有的真实图片 URL>",
  7. "type": "image"
  8. }

上例 URL 是占位符,不能原样提交。当前 MCP 工具列表没有图片上传工具;必须使用用户提供或后台已确认的真实图片 URL,否则停止创建该变量,不得编造上传接口或 URL。value 保存图片 URL,模板中直接引用:

  1. <img src="{var.logo}" alt="网站LOGO">

不要把图片类型写成 {include=logo},也不要假设 {var.logo} 会自动生成 <img>;它输出的是当前变量值,HTML 标签由模板自己写。

8.9.2 select 类型

select 使用 valueItems 定义完整选项。当前 6.1 后台解析器确认的格式是每行一个:

  1. 值:显示文本

例如:

  1. {
  2. "authHandle": "<有效 authHandle>",
  3. "name": "theme",
  4. "title": "页面风格",
  5. "description": "选择网站前台使用的页面风格",
  6. "value": "light",
  7. "type": "select",
  8. "valueItems": "light:浅色ndark:深色"
  9. }

模板中仍然使用:

  1. {var.theme}

输出当前保存的选项值,例如 lightselect 是后台录入控件类型,不会在前台自动生成 <select> 元素

若目标 WangMarket 版本不是已核对的 6.1,必须先在后台确认 valueItems 解析格式;不得自行改成 =、JSON、逗号分隔或其它格式。

后续只改图片 URL 或下拉当前值时,可以使用 save_site_var_value,修改后仍需 generate_site 才会重新生成静态页面。

9. 模板标签公开基线白名单与上下文规则

本节只列出已核对、允许本教程使用的公开基线,不宣称覆盖 WangMarket 的全部内部标签或扩展钩子。AI 制作模板时只使用本节明确列出的合同;未列出的字段必须由目标运行时帮助页、源码或后台确认,不得根据名字自行猜测。

9.1 模板变量 {include=...}

后台模板变量界面已经明确展示:

调用代码备注说明
{include=footer}通用页脚
{include=nav}通用头部导航

模板变量的一般调用格式为:

  1. {include=变量名}

变量名规则:仅使用英文、数字、下划线 _;MCP save_template_var.varName 最大长度为 20。

AI 执行规则:本流程不依赖模板变量嵌套,并禁止循环引用。 例如:

  1. 模板页面 {include=a}
  2. 模板变量 a 内部 {include=b}

不同版本对上例是否继续展开存在资料冲突,不能把任一行为当作跨版本保证。需要两个模板变量时,在模板页面中分别写:

  1. {include=a}
  2. {include=b}

模板变量和网站全局变量不是一回事。官方基础教程明确允许模板变量中使用 {var.xxx};后台标签帮助页也把“通用标签”和“动态栏目调用”标记为可用于模板变量。非循环嵌套的实际行为仍需按目标版本实测;任何直接或间接循环引用都禁止。

父级源码没有发现固定的模板变量系统保留名清单,也没有发现 navfooter 被强制保留。因此当前准确结论是:源码未定义固定保留名;nav/footer 只是推荐名称。 AI 不得反过来伪造一份“系统保留变量列表”。同时,site.*siteColumn.*news.*page.* 属于其它模板标签命名空间,不应被当作模板变量名称使用。


9.2 通用标签

后台帮助页:/templateTag/common.do

适用范围明确包括:

  1. 首页
  2. 列表页
  3. 详情页
  4. 模板变量

当前已确认的通用标签如下:

标签/固定值含义类型/说明
{site.name}网站名称字符串
{site.id}网站编号整数
{site.domain}帮助页定义的网站域名前缀值字符串;不是 MCP 预览地址来源
{site.username}网站联系人姓名字符串
{site.phone}网站联系人手机数字/字符串形式输出
{site.qq}网站联系人 QQ数字/字符串形式输出
{site.address}当前网站联系人办公地址字符串
{site.companyName}当前网站公司名字符串
{linuxTime}当前 10 位 Unix 时间戳整数
index.html帮助页给出的首页相对文件名不是花括号标签,也不是包含域名的预览 URL
{masterSiteUrl}帮助页定义的主站/管理后台 URL 值URL 标签;不是目标站点预览地址来源
{templatePath}模板 CSS、JS、图片等资源 URL 前缀URL

{site.domain}{masterSiteUrl}{templatePath} 是生成模板时使用的标签或值,不是 MCP 返回的站点预览地址。AI 不能在工具调用前把它们展开,也不能据此拼接生产 URL;预览基础 URL 仍必须来自真实上下文或后台。

模板资源必须按照当前 MCP 要求使用:

  1. {templatePath}/相对路径

例如:

  1. <link rel="stylesheet" href="{templatePath}/css/style.css">
  2. <script src="{templatePath}/js/main.js"></script>
  3. <img src="{templatePath}/images/logo.png" alt="logo">

⚠️ {templatePath} 尾斜杠未统一,必须实测后固定一种写法:现有资料对该前缀本身是否已带尾斜杠 / 没有一致结论——若前缀已含 /,上面这种 {templatePath}/css/... 就会生成 // 双斜杠。不要把双斜杠当作通用可接受行为。

落地做法:在目标版本上先生成一次,查看生成页中实际的 href / src,确认前缀是否带尾斜杠,然后整份模板统一采用一种写法(例如确认前缀带 / 时统一写 {templatePath}css/style.css)。未实测前不得批量写入模板。

不要把本地开发机地址、临时 CDN 地址或 localhost 资源地址硬编码进最终模板。


9.3 栏目标签 {siteColumn.*}

后台帮助页:/templateTag/column.do

正确命名空间是 {siteColumn.*},不是 {column.*} 当前栏目帮助页列出的字段如下;但 .taglist.html 对列表页的适用性标为“不可用”,与其它资料冲突。

前置规则第 10 条,下表字段名称只是候选语法:只有目标运行时帮助页或一次真实生成结果确认该字段及其页面上下文可用,AI 才能写入模板;冲突且无法确认时暂停,不得回退、混用或猜测。

标签含义类型/特殊说明
{siteColumn.id}栏目 ID整数
{siteColumn.name}栏目名称字符串
{siteColumn.url}栏目链接地址URL
{siteColumn.type}栏目类型整数;不要据此反推未说明枚举的含义
{siteColumn.used}栏目是否启用/显示整数
{siteColumn.codeName}栏目代码字符串/字母
{siteColumn.parentCodeName}当前栏目的父栏目代码若当前栏目已经是顶级栏目,帮助页说明这里返回当前栏目代码
{siteColumn.icon}栏目图片/图标URL
{siteColumn.keywords}SEO 关键字字符串
{siteColumn.description}SEO 描述字符串

9.3.1 列表页中的栏目标签使用上下文

部分帮助页把栏目标签的适用范围标为列表页,但公开列表索引又标为“不可用”。只有目标运行时确认后,列表页才可以直接使用当前栏目的 {siteColumn.*} 属性,例如:

  1. <h1>{siteColumn.name}</h1>
  2. <a href="{siteColumn.url}">{siteColumn.name}</a>

在目标版本确认栏目标签可用后,还可区分以下两个上下文:

  1. TemplateListItemStart ... TemplateListItemEnd
  2. 若该循环被目标版本启用,栏目标签表示当前循环文章关联的栏目
  3. SiteColumn_Start / SubColumnList_Start 动态调用上下文
  4. 若相应字段被目标版本启用,栏目标签表示当前被动态调取的栏目/子栏目

因此 AI 必须根据上下文理解 {siteColumn.*} 所指向的栏目对象,不要把动态调用中的栏目、列表页当前栏目和文章关联栏目混成同一个固定对象。


9.4 文章信息标签 {news.*}

后台文章信息标签帮助页展示以下字段;列表/详情适用性在不同资料中存在冲突,本文示例使用这些字段不等于目标运行时必然支持。

前置规则第 10 条:只有目标运行时帮助页或一次真实生成结果确认该字段及其上下文可用,AI 才能写入模板;冲突且无法确认时必须暂停,不得回退为写死内容、不得混用两套规则、不得猜测其它字段。

标签含义类型/说明
{news.id}文章编号整数
{news.title}文章标题字符串
{news.titlepic}文章列表图/标题图URL
{news.intro}文章简介字符串
{news.url}文章页面链接地址URL
{news.cid}文章所属栏目编号整数
{news.text}文章正文HTML
{news.extend.photos}文章图集JSON 格式字符串,需要前端 JS 自行解析
{news.extend.???}自定义扩展字段??? 必须替换为真实已存在字段名,禁止编造
{news.addtime}发布时间字符串日期
{news.addtime.year}发布时间-年整数/字符串输出
{news.addtime.month}发布时间-月运行时输出;是否补前导零未确认
{news.addtime.day}发布时间-日运行时输出;是否补前导零未确认
{news.addtime.hour}发布时间-时示例 10
{news.addtime.minute}发布时间-分示例 23

在目标运行时确认文章标签可用后,两个典型上下文是:

  1. 详情页:用于当前文章/当前独立页面内容,例如 {news.title}、{news.text}
  2. 列表循环:用于当前循环项,例如 {news.url}、{news.title}、{news.titlepic}

不要在不存在“当前文章”或“当前循环项”的普通模板位置随意写 {news.*} 并假设系统知道你要哪一篇文章。


9.5 动态栏目调用

后台帮助页:/templateTag/dynamic.do

动态栏目调用的明确用途:

  1. 调取当前生成上下文中可用于模板调用且未被禁用/隐藏的一级栏目;
  2. 调取某个指定栏目下可用于模板调用且未被禁用/隐藏的子栏目;
  3. 根据栏目代码调取该栏目属性,以及该栏目下文章列表。

帮助页标记的适用范围包括:首页、列表页、详情页、模板变量。

SiteColumn_Start / SiteColumn_EndSubColumnList_Start / SubColumnList_EndList_Start / List_End 以及列表模板的 TemplateListItemStart / TemplateListItemEnd 都是区分大小写的精确标记。不得添加空格、改连字符、翻译或改写名称。生成后若仍残留这些标记或 {news.*}{siteColumn.*} 等标签,视为生成失败,必须停止交付。

标记与字段要分开判断(前置规则第 10 条):上面这些动态调用标记本身已确认可用;但标记内部使用的 {siteColumn.*}{news.*}{page.*} 字段仍必须按同一确认规则,经目标运行时帮助页或一次真实生成结果确认后才可写入。也就是说,可以写 <!--SiteColumn_Start-->...<!--SiteColumn_End-->,但不等于可以无条件在里面写 {siteColumn.url}{news.url}

9.5.1 基本结构与 codeName

  1. <!--SiteColumn_Start-->
  2. <!--codeName=xinwenzixun-->
  3. ...
  4. <!--SiteColumn_End-->

codeName 是栏目代码,必须使用真实已存在的栏目代码。不要把栏目名称、栏目 ID 或模板页面名称误当成 codeName

本节代码中的 xinwenzixungongsidongtaidocnews 都只是示例 codeName,执行时必须替换为目标站点真实存在的值。当前 MCP 没有按代码查询栏目的工具,缺少该值时不得执行动态调用模板保存。

帮助页还明确支持在栏目/详情相关模板上下文中动态引用当前栏目代码:

  1. <!--codeName={siteColumn.codeName}-->

只有在当前上下文本身存在有效 siteColumn 时才可以这样使用;不要在无栏目上下文的地方凭空使用。

9.5.2 调取指定栏目名称和 URL

  1. <!--SiteColumn_Start-->
  2. <!--codeName=xinwenzixun-->
  3. <a href="{siteColumn.url}">{siteColumn.name}</a>
  4. <!--SiteColumn_End-->

9.5.3 调取指定栏目文章列表

动态模板注释中的 number 用于控制本次动态调用的文章条数;未设置时,当前帮助页说明默认显示 6 条。它不是 save_site_column.listNum:后者控制栏目列表页的每页条数,两个同为数量字段但属于不同对象,不能互相替代或同步推导。

  1. <!--SiteColumn_Start-->
  2. <!--codeName=gongsidongtai-->
  3. <div>
  4. <a href="{siteColumn.url}" title="{siteColumn.name}">{siteColumn.name}</a>
  5. <ul>
  6. <!--number=6-->
  7. <!--List_Start-->
  8. <li><a href="{news.url}">{news.title}</a></li>
  9. <!--List_End-->
  10. </ul>
  11. </div>
  12. <!--SiteColumn_End-->

在目标运行时确认动态列表字段后,List_Start ... List_End 内部才可使用文章信息标签。

源码与动态帮助示例表明:首页可以通过动态栏目调用尝试调取新闻/文章列表,但这不替目标运行时解决列表标签冲突;只有相关标签和循环均经确认时才可依赖该结果。

关于“轮播图”:当前资料没有提供一个专用的“轮播图标签”。如果设计要求轮播,可以在动态文章列表中使用已经存在的 {news.titlepic}{news.url} 等字段,再由模板自身 HTML/CSS/JS 实现轮播效果;当前核对版本在 titlepicnull 时可能回退到系统默认图,空字符串的处理也需按目标版本确认。非空输出不证明素材已上传,验收时必须检查图片 URL 可访问且内容确为目标素材。AI 不得编造诸如 {slider.xxx}{banner.xxx} 之类未在文档出现的 CMS 标签


9.5.4 调取指定父栏目下的子栏目

  1. <!--SiteColumn_Start-->
  2. <!--codeName=xinwenzixun-->
  3. <h2>{siteColumn.name}</h2>
  4. <!--SubColumnList_Start-->
  5. <a href="{siteColumn.url}">{siteColumn.name}</a>
  6. <!--SubColumnList_End-->
  7. <!--SiteColumn_End-->

在目标运行时确认栏目字段后,SubColumnList_Start ... SubColumnList_End 内部才可使用栏目标签。


9.5.5 调取当前网站可用于模板调用的顶级栏目

不写 codeName

  1. <!--SiteColumn_Start-->
  2. <!--SubColumnList_Start-->
  3. <a href="{siteColumn.url}">{siteColumn.name}</a>
  4. <!--SubColumnList_End-->
  5. <!--SiteColumn_End-->

去掉具体栏目代码后,调取当前生成上下文中可用于模板代码调用且未被禁用/隐藏的顶级栏目;不能据此假设后台所有栏目都会输出。


9.5.6 父栏目 → 子栏目 → 每个子栏目的文章列表

  1. <!--SiteColumn_Start-->
  2. <!--codeName=doc-->
  3. <!--SubColumnList_Start-->
  4. <h2>{siteColumn.name}</h2>
  5. <!--number=30-->
  6. <!--List_Start-->
  7. <li><a href="{news.url}">{news.title}</a></li>
  8. <!--List_End-->
  9. <!--SubColumnList_End-->
  10. <!--SiteColumn_End-->

该结构说明动态栏目调用可以嵌套“子栏目循环 + 当前子栏目文章循环”。这里属于动态栏目语法自身的嵌套,不等于模板变量 {include=...} 的嵌套,不要混淆两个规则。


9.6 首页模板 TemplatePage.type=1 的完整当前标签边界

根据通用标签帮助页、动态栏目调用帮助页和当前模板机制,首页的标签边界如下。表中标为“可用”的能力可直接写入;凡涉及 {siteColumn.*}{news.*} 的字段,仍按前置规则第 10 条经目标运行时确认后才可写入:

能力/标签首页结论
模板变量 {include=...}可用
网站全局变量 {var.xxx}可用
通用标签 {site.*}{linuxTime}{masterSiteUrl}{templatePath}可用
动态栏目调用 SiteColumn_Start...End标记可用;内部 {siteColumn.*} 字段须按前置规则第 10 条确认
动态调取指定栏目文章列表 List_Start...End标记可用;内部 {news.*} 字段须按前置规则第 10 条确认
动态调取顶级栏目/子栏目 SubColumnList_Start...End标记可用;内部 {siteColumn.*} 字段须按前置规则第 10 条确认
{siteColumn.*} 作为首页“当前栏目”直接使用首页本身没有当前栏目上下文,不这样使用;进入动态栏目上下文且该字段已确认后才可用
{news.*} 作为首页“当前文章”直接使用不可直接使用;进入动态 List_Start...End 且该字段已确认后才可用于当前循环文章
{page.*} 分页标签不用于首页
专用轮播图 CMS 标签当前资料没有;不得编造

因此首页内容可以由三层组成:

  1. 固定布局 HTML
  2. +
  3. 可后台维护的全局数据 {var.xxx}
  4. +
  5. 栏目/文章动态数据 <!--SiteColumn_Start--> ...

例如首页调“新闻资讯”最新 6 篇(其中 news 是本教程示例 codeName{news.url}{news.title} 须先按前置规则第 10 条确认;不可直接提交):

  1. <!--SiteColumn_Start-->
  2. <!--codeName=news-->
  3. <!--number=6-->
  4. <!--List_Start-->
  5. <a href="{news.url}">{news.title}</a>
  6. <!--List_End-->
  7. <!--SiteColumn_End-->

如果首页需要轮播,可以把动态文章列表中的 {news.titlepic}{news.url} 等已有字段交给模板自己的 HTML/CSS/JS 组成轮播效果;这不是一个新的 CMS 轮播标签。当前核对版本在 titlepicnull 时可能回退到系统默认图,空字符串的处理也不能跨版本假定;因此输出非空不证明素材已上传,验收时必须检查图片 URL 可访问且内容确为目标素材。禁止编造 {slider.*}{banner.*} 等本文档不存在的标签。


9.7 列表页模板 TemplatePage.type=2 的完整标签上下文矩阵

列表页通常包含“当前栏目 + 文章列表 + 分页”,但公开列表帮助页与源码/示例对标签可用性存在冲突。

下表只是目标运行时确认后的候选上下文,不是跨版本保证。按前置规则第 10 条:表中所有“需确认”项,只有目标运行时帮助页或一次真实生成结果确认后才可写入模板;帮助资料冲突且无法确认时必须暂停,不得回退、混用或猜测。

上下文{include=...}{var.*}通用标签{siteColumn.*}{news.*}{page.*}动态栏目调用
列表页普通位置可用可用可用需确认,若支持则表示当前列表栏目不作为当前文章直接使用需确认可用
TemplateListItemStart ... End可用可用可用需确认,若支持则表示当前循环文章关联栏目需确认,若支持则表示当前循环文章通常放循环外,仍需确认可用但通常无需嵌入单项
SiteColumn_Start ... End可用可用可用需确认,若支持则表示动态指定栏目进入 List_Start...End 后才可用,需确认页面分页仍属于当前列表页,不要与动态文章列表混为一套分页可用
SubColumnList_Start ... End可用可用可用需确认,若支持则表示当前子栏目若再进入 List_Start...End 且目标版本支持才可用动态调用内部

在目标运行时确认上述条件后,列表页最典型的结构:

  1. <h1>{siteColumn.name}</h1>
  2. <ul>
  3. <!--TemplateListItemStart-->
  4. <li><a href="{news.url}">{news.title}</a></li>
  5. <!--TemplateListItemEnd-->
  6. </ul>
  7. <div class="pagination">
  8. <a href="{page.firstPage}">首页</a>
  9. <a href="{page.upPage}">上一页</a>
  10. <a href="{page.nextPage}">下一页</a>
  11. <a href="{page.lastPage}">末页</a>
  12. </div>

分页完整 11 个字段和 URL 生成规则见 9.12。


9.8 详情页模板 TemplatePage.type=3

基础教程明确“关于我们”添加模板页面时选择详情页模板;当前 MCP 文档进一步规定关于我们等单页面通过 MCP 创建模板页面时使用 TemplatePage.type=3

本教程详情示例使用以下核心标签。WangMarket 6.1 源码已确认可用replaceNewsTag() 主动替换);目标版本不是 6.1 时按 11.1 实测确认:

  1. {news.title}
  2. {news.text}

详情页还有以下独有标签:

标签说明类型
返回列表上一篇文章;没有上一篇时返回列表页面HTML
制作本地静态模版下一篇文章;没有下一篇时按系统规则返回列表页面HTML
ai-template.html上一篇文章链接地址URL
45919.html下一篇文章链接地址URL
本文是 WangMarket MCP 模板建站流程的执行规范。除明确标注为固定枚举或固定语法外,文中 HTML、文案、URL、栏目名、`codeName`、ID、账号、QQ、图片地址和返回 `info` 均为示例或占位值,不得直接写入生产站点。 **版本基准**:本文所有"已确认"的模板标签、URL 生成规则、`templatePath` 行为等结论,均基于 **WangMarket 6.1** 源码(依赖 `wangmarket-6.1.jar`)反编译核对。目标站点运行版本不是 6.1 时,标注"6.1 已确认"的项仍须按第 11 章实测确认;标注"跨版本注意"的项尤其需要验证。 **执行前置条件**:目标站点已开通且已明确;登录凭据有效;运行时工具列表至少包含本次分支所需的 `login`、`save_template_var`、`save_site_column`、`save_template_page`、`save_template_page_text`、`generate_site`,并按页面类型提供 `save_news`(信息列表内容)或 `save_alone_page_content`(独立页面内容);只有实际使用全局变量时才需要 `save_site_var`/`save_site_var_value`,只有绑定缺失且获授权修复时才需要 `save_template`。各工具 schema 必须与本文调用相符;站点是否已有同名对象已确认;预览所需的真实站点基础 URL 已由用户、宿主或后台提供。**当前工具集没有站点 URL/生成结果查询工具,也没有"按栏目创建独立页面内容"的工具**:真实页面 URL 必须外部提供,独立页面内容若未自动创建必须人工在后台添加后 AI 才能更新。任一当前分支必需条件缺失时必须先报告并停止,不得猜测或开始写入。 **⚠️ 静态资源上传前置检查(必须在第 1 章之前完成)**: 开始读取和制作模板之前,必须先检查用户上传的 HTML 模板包中是否引用了**本地静态资源文件**,包括但不限于: | 资源类型 | 常见引用方式 | 常见扩展名 | |---------|------------|----------| | 样式表 | ``、`@import` | `.css` | | 脚本 | ` logo ``` > **⚠️ `{templatePath}` 尾斜杠未统一,必须实测后固定一种写法**:现有资料对该前缀本身是否已带尾斜杠 `/` 没有一致结论——若前缀已含 `/`,上面这种 `{templatePath}/css/...` 就会生成 `//` 双斜杠。**不要把双斜杠当作通用可接受行为。** > > 落地做法:在目标版本上先生成一次,查看生成页中实际的 `href` / `src`,确认前缀是否带尾斜杠,然后整份模板统一采用一种写法(例如确认前缀带 `/` 时统一写 `{templatePath}css/style.css`)。未实测前不得批量写入模板。 不要把本地开发机地址、临时 CDN 地址或 `localhost` 资源地址硬编码进最终模板。 --- ### 9.3 栏目标签 `{siteColumn.*}` 后台帮助页:`/templateTag/column.do` **正确命名空间是 `{siteColumn.*}`,不是 `{column.*}`。** 当前栏目帮助页列出的字段如下;但 `.taglist.html` 对列表页的适用性标为“不可用”,与其它资料冲突。 按**前置规则第 10 条**,下表字段名称只是候选语法:只有目标运行时帮助页或一次真实生成结果确认该字段及其页面上下文可用,AI 才能写入模板;冲突且无法确认时暂停,不得回退、混用或猜测。 | 标签 | 含义 | 类型/特殊说明 | |---|---|---| | `{siteColumn.id}` | 栏目 ID | 整数 | | `{siteColumn.name}` | 栏目名称 | 字符串 | | `{siteColumn.url}` | 栏目链接地址 | URL | | `{siteColumn.type}` | 栏目类型 | 整数;不要据此反推未说明枚举的含义 | | `{siteColumn.used}` | 栏目是否启用/显示 | 整数 | | `{siteColumn.codeName}` | 栏目代码 | 字符串/字母 | | `{siteColumn.parentCodeName}` | 当前栏目的父栏目代码 | 若当前栏目已经是顶级栏目,帮助页说明这里返回当前栏目代码 | | `{siteColumn.icon}` | 栏目图片/图标 | URL | | `{siteColumn.keywords}` | SEO 关键字 | 字符串 | | `{siteColumn.description}` | SEO 描述 | 字符串 | #### 9.3.1 列表页中的栏目标签使用上下文 部分帮助页把栏目标签的适用范围标为**列表页**,但公开列表索引又标为“不可用”。只有目标运行时确认后,列表页才可以直接使用当前栏目的 `{siteColumn.*}` 属性,例如: ```html

{siteColumn.name}

{siteColumn.name} ``` 在目标版本确认栏目标签可用后,还可区分以下两个上下文: ```text TemplateListItemStart ... TemplateListItemEnd → 若该循环被目标版本启用,栏目标签表示当前循环文章关联的栏目 SiteColumn_Start / SubColumnList_Start 动态调用上下文 → 若相应字段被目标版本启用,栏目标签表示当前被动态调取的栏目/子栏目 ``` 因此 AI 必须根据上下文理解 `{siteColumn.*}` 所指向的栏目对象,不要把动态调用中的栏目、列表页当前栏目和文章关联栏目混成同一个固定对象。 --- ### 9.4 文章信息标签 `{news.*}` 后台文章信息标签帮助页展示以下字段;列表/详情适用性在不同资料中存在冲突,本文示例使用这些字段不等于目标运行时必然支持。 按**前置规则第 10 条**:只有目标运行时帮助页或一次真实生成结果确认该字段及其上下文可用,AI 才能写入模板;冲突且无法确认时必须暂停,不得回退为写死内容、不得混用两套规则、不得猜测其它字段。 | 标签 | 含义 | 类型/说明 | |---|---|---| | `{news.id}` | 文章编号 | 整数 | | `{news.title}` | 文章标题 | 字符串 | | `{news.titlepic}` | 文章列表图/标题图 | URL | | `{news.intro}` | 文章简介 | 字符串 | | `{news.url}` | 文章页面链接地址 | URL | | `{news.cid}` | 文章所属栏目编号 | 整数 | | `{news.text}` | 文章正文 | HTML | | `{news.extend.photos}` | 文章图集 | JSON 格式字符串,需要前端 JS 自行解析 | | `{news.extend.???}` | 自定义扩展字段 | `???` 必须替换为真实已存在字段名,禁止编造 | | `{news.addtime}` | 发布时间 | 字符串日期 | | `{news.addtime.year}` | 发布时间-年 | 整数/字符串输出 | | `{news.addtime.month}` | 发布时间-月 | 运行时输出;是否补前导零未确认 | | `{news.addtime.day}` | 发布时间-日 | 运行时输出;是否补前导零未确认 | | `{news.addtime.hour}` | 发布时间-时 | 示例 `10` | | `{news.addtime.minute}` | 发布时间-分 | 示例 `23` | 在目标运行时确认文章标签可用后,两个典型上下文是: ```text 详情页:用于当前文章/当前独立页面内容,例如 {news.title}、{news.text} 列表循环:用于当前循环项,例如 {news.url}、{news.title}、{news.titlepic} ``` 不要在不存在“当前文章”或“当前循环项”的普通模板位置随意写 `{news.*}` 并假设系统知道你要哪一篇文章。 --- ### 9.5 动态栏目调用 后台帮助页:`/templateTag/dynamic.do` 动态栏目调用的明确用途: 1. 调取当前生成上下文中可用于模板调用且未被禁用/隐藏的一级栏目; 2. 调取某个指定栏目下可用于模板调用且未被禁用/隐藏的子栏目; 3. 根据栏目代码调取该栏目属性,以及该栏目下文章列表。 帮助页标记的适用范围包括:首页、列表页、详情页、模板变量。 `SiteColumn_Start` / `SiteColumn_End`、`SubColumnList_Start` / `SubColumnList_End`、`List_Start` / `List_End` 以及列表模板的 `TemplateListItemStart` / `TemplateListItemEnd` 都是区分大小写的精确标记。不得添加空格、改连字符、翻译或改写名称。生成后若仍残留这些标记或 `{news.*}`、`{siteColumn.*}` 等标签,视为生成失败,必须停止交付。 > **标记与字段要分开判断(前置规则第 10 条)**:上面这些**动态调用标记本身已确认可用**;但标记内部使用的 `{siteColumn.*}`、`{news.*}`、`{page.*}` 字段仍必须按同一确认规则,经目标运行时帮助页或一次真实生成结果确认后才可写入。也就是说,可以写 `...`,但不等于可以无条件在里面写 `{siteColumn.url}` 或 `{news.url}`。 #### 9.5.1 基本结构与 `codeName` ```html ... ``` `codeName` 是栏目代码,必须使用真实已存在的栏目代码。不要把栏目名称、栏目 ID 或模板页面名称误当成 `codeName`。 本节代码中的 `xinwenzixun`、`gongsidongtai`、`doc` 和 `news` 都只是示例 `codeName`,执行时必须替换为目标站点真实存在的值。当前 MCP 没有按代码查询栏目的工具,缺少该值时不得执行动态调用模板保存。 帮助页还明确支持在栏目/详情相关模板上下文中动态引用当前栏目代码: ```html ``` 只有在当前上下文本身存在有效 `siteColumn` 时才可以这样使用;不要在无栏目上下文的地方凭空使用。 #### 9.5.2 调取指定栏目名称和 URL ```html {siteColumn.name} ``` --- #### 9.5.3 调取指定栏目文章列表 动态模板注释中的 `number` 用于控制本次动态调用的文章条数;未设置时,当前帮助页说明默认显示 6 条。它不是 `save_site_column.listNum`:后者控制栏目列表页的每页条数,两个同为数量字段但属于不同对象,不能互相替代或同步推导。 ```html ``` 在目标运行时确认动态列表字段后,`List_Start ... List_End` 内部才可使用文章信息标签。 源码与动态帮助示例表明:首页可以通过动态栏目调用尝试调取新闻/文章列表,但这不替目标运行时解决列表标签冲突;只有相关标签和循环均经确认时才可依赖该结果。 关于“轮播图”:当前资料**没有提供一个专用的“轮播图标签”**。如果设计要求轮播,可以在动态文章列表中使用已经存在的 `{news.titlepic}`、`{news.url}` 等字段,再由模板自身 HTML/CSS/JS 实现轮播效果;当前核对版本在 `titlepic` 为 `null` 时可能回退到系统默认图,空字符串的处理也需按目标版本确认。非空输出不证明素材已上传,验收时必须检查图片 URL 可访问且内容确为目标素材。AI **不得编造诸如 `{slider.xxx}`、`{banner.xxx}` 之类未在文档出现的 CMS 标签**。 --- #### 9.5.4 调取指定父栏目下的子栏目 ```html

{siteColumn.name}

{siteColumn.name} ``` 在目标运行时确认栏目字段后,`SubColumnList_Start ... SubColumnList_End` 内部才可使用栏目标签。 --- #### 9.5.5 调取当前网站可用于模板调用的顶级栏目 不写 `codeName`: ```html {siteColumn.name} ``` 去掉具体栏目代码后,调取当前生成上下文中可用于模板代码调用且未被禁用/隐藏的顶级栏目;不能据此假设后台所有栏目都会输出。 --- #### 9.5.6 父栏目 → 子栏目 → 每个子栏目的文章列表 ```html

{siteColumn.name}

  • {news.title}
  • ``` 该结构说明动态栏目调用可以嵌套“子栏目循环 + 当前子栏目文章循环”。这里属于动态栏目语法自身的嵌套,**不等于模板变量 `{include=...}` 的嵌套**,不要混淆两个规则。 --- ### 9.6 首页模板 `TemplatePage.type=1` 的完整当前标签边界 根据通用标签帮助页、动态栏目调用帮助页和当前模板机制,首页的标签边界如下。表中标为“可用”的能力可直接写入;凡涉及 `{siteColumn.*}`、`{news.*}` 的字段,仍按**前置规则第 10 条**经目标运行时确认后才可写入: | 能力/标签 | 首页结论 | |---|---| | 模板变量 `{include=...}` | 可用 | | 网站全局变量 `{var.xxx}` | 可用 | | 通用标签 `{site.*}`、`{linuxTime}`、`{masterSiteUrl}`、`{templatePath}` 等 | 可用 | | 动态栏目调用 `SiteColumn_Start...End` | 标记可用;内部 `{siteColumn.*}` 字段须按前置规则第 10 条确认 | | 动态调取指定栏目文章列表 `List_Start...End` | 标记可用;内部 `{news.*}` 字段须按前置规则第 10 条确认 | | 动态调取顶级栏目/子栏目 `SubColumnList_Start...End` | 标记可用;内部 `{siteColumn.*}` 字段须按前置规则第 10 条确认 | | `{siteColumn.*}` 作为首页“当前栏目”直接使用 | 首页本身没有当前栏目上下文,不这样使用;进入动态栏目上下文且该字段已确认后才可用 | | `{news.*}` 作为首页“当前文章”直接使用 | 不可直接使用;进入动态 `List_Start...End` 且该字段已确认后才可用于当前循环文章 | | `{page.*}` 分页标签 | 不用于首页 | | 专用轮播图 CMS 标签 | 当前资料没有;不得编造 | 因此首页内容可以由三层组成: ```text 固定布局 HTML + 可后台维护的全局数据 {var.xxx} + 栏目/文章动态数据 ... ``` 例如首页调“新闻资讯”最新 6 篇(其中 `news` 是本教程示例 `codeName`,`{news.url}`、`{news.title}` 须先按前置规则第 10 条确认;不可直接提交): ```html {news.title} ``` 如果首页需要轮播,可以把动态文章列表中的 `{news.titlepic}`、`{news.url}` 等已有字段交给模板自己的 HTML/CSS/JS 组成轮播效果;这不是一个新的 CMS 轮播标签。当前核对版本在 `titlepic` 为 `null` 时可能回退到系统默认图,空字符串的处理也不能跨版本假定;因此输出非空不证明素材已上传,验收时必须检查图片 URL 可访问且内容确为目标素材。禁止编造 `{slider.*}`、`{banner.*}` 等本文档不存在的标签。 --- ### 9.7 列表页模板 `TemplatePage.type=2` 的完整标签上下文矩阵 列表页通常包含“当前栏目 + 文章列表 + 分页”,但公开列表帮助页与源码/示例对标签可用性存在冲突。 下表只是**目标运行时确认后的候选上下文**,不是跨版本保证。按**前置规则第 10 条**:表中所有“需确认”项,只有目标运行时帮助页或一次真实生成结果确认后才可写入模板;帮助资料冲突且无法确认时必须暂停,不得回退、混用或猜测。 | 上下文 | `{include=...}` | `{var.*}` | 通用标签 | `{siteColumn.*}` | `{news.*}` | `{page.*}` | 动态栏目调用 | |---|---|---|---|---|---|---|---| | 列表页普通位置 | 可用 | 可用 | 可用 | **需确认,若支持则表示当前列表栏目** | 不作为当前文章直接使用 | **需确认** | 可用 | | `TemplateListItemStart ... End` | 可用 | 可用 | 可用 | 需确认,若支持则表示当前循环文章关联栏目 | **需确认,若支持则表示当前循环文章** | 通常放循环外,仍需确认 | 可用但通常无需嵌入单项 | | `SiteColumn_Start ... End` | 可用 | 可用 | 可用 | 需确认,若支持则表示动态指定栏目 | 进入 `List_Start...End` 后才可用,需确认 | 页面分页仍属于当前列表页,不要与动态文章列表混为一套分页 | 可用 | | `SubColumnList_Start ... End` | 可用 | 可用 | 可用 | **需确认,若支持则表示当前子栏目** | 若再进入 `List_Start...End` 且目标版本支持才可用 | — | 动态调用内部 | 在目标运行时确认上述条件后,列表页最典型的结构: ```html

    {siteColumn.name}

    ``` 分页完整 11 个字段和 URL 生成规则见 9.12。 --- ### 9.8 详情页模板 `TemplatePage.type=3` 基础教程明确“关于我们”添加模板页面时选择**详情页模板**;当前 MCP 文档进一步规定关于我们等单页面通过 MCP 创建模板页面时使用 `TemplatePage.type=3`。 本教程详情示例使用以下核心标签。**WangMarket 6.1 源码已确认可用**(`replaceNewsTag()` 主动替换);目标版本不是 6.1 时按 11.1 实测确认: ```text {news.title} {news.text} ``` 详情页还有以下独有标签: | 标签 | 说明 | 类型 | |---|---|---| | `返回列表` | 上一篇文章;没有上一篇时返回列表页面 | HTML | | `制作本地静态模版` | 下一篇文章;没有下一篇时按系统规则返回列表页面 | HTML | | `ai-template.html` | 上一篇文章链接地址 | URL | | `45919.html` | 下一篇文章链接地址 | URL | | `{text}` | 历史正文标签 | 旧模板兼容行为需按目标运行时验证;新模板不使用 | 新建详情模板统一使用 `{news.text}`。只有迁移已有旧模板且目标运行时已实测支持时,才保留裸 `{text}`;不得同时插入两种正文标签,否则可能重复输出正文。 `返回列表`、`制作本地静态模版` 输出完整 ``;当前核对版本在没有相邻文章时回到栏目列表。`ai-template.html`、`45919.html` 只输出 URL。独立页面虽然也使用 `type=3` 模板,但不得把这些标签解释成"上一独立页/下一独立页"。详情页普通位置的 `{siteColumn.*}` 在 6.1 源码中由 `replaceSiteColumnTag()` 替换,已确认可用;目标版本不是 6.1 时按 11.1 确认。 #### 9.8.1 关于旧帮助页"文章信息标签不可用"的说明 **WangMarket 6.1 源码已确认**:详情页 `{news.*}` 由 `TemplateCMS.replaceNewsTag()` 主动替换,含 `{news.title}`、`{news.text}`、`{news.url}` 等全部字段。帮助页 `details.jsp` 表格中的"文章信息标签:不可用"标注为**过时/错误**,与 6.1 实际代码不符。6.1 版本可直接使用 `{news.*}`,无需运行时确认。 跨版本注意:若目标 WangMarket 版本不是 6.1,该标注可能生效,应按 11.1 做一次最小化真实生成测试确认。 --- ### 9.9 网站全局变量 `text / image / select` 全局变量统一通过: ```text {var.变量名} ``` 引用。当前 MCP 暴露的 `text`、`image`、`select` 三种类型引用语法相同,区别在后台录入方式和 `value` 的含义;这不代表所有 WangMarket 版本只存在三种类型。 #### text 示例 ```text name = qq type = text value = <用户提供的真实 QQ 群号> 模板:{var.qq} ``` #### image 示例 ```json { "authHandle": "<有效 authHandle>", "name": "logo", "title": "网站LOGO", "description": "上传网站LOGO,并在备注中写明建议尺寸和格式", "value": "<用户提供或后台已有的真实图片 URL>", "type": "image" } ``` 模板仍然写: ```html 网站LOGO ``` #### select 示例 当前 6.1 后台解析器要求 `valueItems` 每行使用: ```text 值:显示文本 ``` 例如: ```text valueItems: light:浅色 dark:深色 value = light ``` 模板: ```text {var.theme} ``` 输出的是当前保存的变量值。AI 不得把 `select` 自动解释成会生成 ``;HTML 由模板自己写 | | 11 | 独立页面模板 `type=6` 与详情页 `type=3` | `TemplatePage.TYPE_ALONEPAGE=6` 已废弃并入详情页;当前关于我们使用 `TemplatePage.type=3 + SiteColumn.type=8` | **不得再创建 TemplatePage.type=6** | | 12 | `codeName` 是否必填 | 条件必填:仅在需要动态栏目调用或目标运行时要求按代码生成时才传入;值必须是当前站点已确认存在的栏目代码;仅创建栏目且无上述需求时可按 schema 省略 | 省略后不得由 `codeName` 推导栏目 URL;`about`、`news` 仅为栏目代码格式示例,执行时必须替换为真实存在的值 | | 13 | 列表页/详情页标签适用性 | **WangMarket 6.1 源码已确认可用**:`TemplateCMS.replaceListPageTag()` 主动替换 `{siteColumn.*}` 和全部 11 个 `{page.*}`;`replaceNewsTag()` 主动替换 `{news.*}`(含 `{news.url}`);列表页循环内逐篇调用 `replaceNewsTag()`。帮助页 list.jsp/details.jsp 表格中标注的"不可用"为过时标注,与 6.1 实际代码不符 | 6.1 版本可直接使用 `{siteColumn.*}`、`{page.*}`(列表页)、`{news.*}`(详情页及列表循环内);目标版本不是 6.1 时仍须按 11.1 实测确认 | | 14 | 分页标签与列表 URL 形态 | 11 个 `{page.*}` 字段来自源码核对版本;`codeName.html` / `codeName_页码.html` 仅在 `generateUrlRule=code` 时成立 | 分页只用于列表页;`upList`/`nextList` 输出页码列表 HTML,不包成单个数字或 URL;`lc_.html` 等 ID 形态无公开契约,禁止推导 | | 15 | `{templatePath}` 尾斜杠 | **WangMarket 6.1 源码已确认末尾带斜杠**:`getTemplatePath()` = 路径前缀 + `site.templateName` + `"/"`(字节码显式 append `/`)。私有模板前缀 = `ATTACHMENT_FILE_URL + websiteTemplate/`,云模板前缀 = `//cloudtemplate.weiunity.com/websiteTemplate/`,两者本身也以 `/` 结尾 | 6.1 版本模板中统一写 `{templatePath}css/style.css`(**不加**额外斜杠);写 `{templatePath}/css/style.css` 会产生双斜杠 `//` | | 16 | `generateUrlRule` 判定逻辑 | **WangMarket 6.1 源码已确认**:默认 `"int"`;`templateCMS()` 中判定——系统属性 `MASTER_SITE_URL` 为 null 或不等于 `"http://wang.market/"` 时 → `"code"`;等于官方云地址时,`site.id > 255` 或 `site.id == 218` → `"code"`,其余老站点 → `"int"` | 自部署/非官方环境几乎一定是 `"code"`;官方云老站点(id≤255 且 ≠218)才是 `"int"`。具体值可通过部署环境或站点 ID 判定,或从已生成页面 URL 反推;MCP 无查询接口 | 以下事项仍缺少当前 MCP 的查询能力或统一运行时依据,**不得标成已解决,更不得由 AI 补全**: | 待确认事项 | 当前可执行边界 | |---|---| | 站点基础 URL(域名/访问路径) | 由用户、宿主或后台提供;MCP 无查询接口 | | 栏目、模板变量、新闻、全局变量的查询 | 当前工具集没有查询工具;缺少真实 ID/存在性时停止 | | `save_site_column.info` 为非数字文本 | 不把"成功"当 ID;停止后由后台确认,避免重复创建 | | `save_template` 的目标模板与副作用 | 调用前确认允许影响现有模板;`result=1` 后仍以生成和预览验证 | | `generate_site` 之后文件的可访问性 | `result=1` 只表示调用完成;必须用真实 URL 做 HTTP 与内容验收;404/超时且无轮询工具时停止等待后台确认,不无限重试、不猜 URL | | 独立页面内容的"当前站点唯一" | 属实现边界(底层按 `cid` 查询 News 且未显式带 `siteid`);不得无条件承诺,必须后台确认后再更新 | | 独立页面内容记录未自动创建时的回退 | `save_alone_page_content` 只查询不创建,当前 MCP 无替代工具;必须由人工在后台"内容管理"手动添加一条后 AI 才能更新;在此之前关于我们页面无内容来源(见 5.3) | | `News.htmlName` 在当前 6.1 生成器中的效果 | 不用它推导详情 URL | | `editMode=1` 的完整可视化协议 | 当前 MCP 不使用,统一显式传 `TemplatePage.editMode=2` | | 非 6.1 版本的标签适用性、`valueItems`、日期补零、模板变量嵌套等细节 | 目标版本不是 6.1 时按 11.1-11.9 实测确认;6.1 版本以上述已确认表为准 | --- ## 11. 运行时确认操作指南 本章针对第 10 章「仍需确认的执行边界」中列出的事项,给出**具体的确认方法和操作步骤**。AI 不得自行决定这些技术参数,但可以按本章指引从目标运行时、后台或用户处取得确认依据。确认结果应记录版本号和证据,后续执行时引用。 ### 11.1 列表/详情页标签适用性(6.1 已确认) **WangMarket 6.1 结论**:`{siteColumn.*}`、`{news.*}`、`{page.*}` 在列表页和详情页**均可用**,源码中有对应的替换方法并被生成流程实际调用: - `replaceListPageTag()` → 替换 `{siteColumn.*}` 和全部 11 个 `{page.*}` - `replaceNewsTag()` → 替换 `{news.*}`(含 `{news.url}`),列表页循环内逐篇调用 帮助页 `list.jsp`/`details.jsp` 表格中标注的"不可用"为**过时标注**,与 6.1 实际代码不符。6.1 版本可直接使用这些标签,无需运行时测试。 **跨版本注意**:若目标 WangMarket 版本不是 6.1,仍须做一次最小化真实生成测试确认: 1. 在列表模板中写入 `{siteColumn.name}`、`{news.title}`、`{page.firstPage}`; 2. 在详情模板中写入 `{news.title}`、`{news.text}`; 3. 调用 `generate_site` 后查看源码,标签原样残留则该版本不支持。 ### 11.2 站点基础 URL 与 `generateUrlRule`(6.1 判定逻辑已确认) **WangMarket 6.1 源码已确认 `generateUrlRule` 判定逻辑**(`TemplateCMS.templateCMS()`): | 部署环境 | 判定条件 | generateUrlRule | |---|---|---| | 自部署/非官方 | `MASTER_SITE_URL` 系统属性为 null,或不等于 `"http://wang.market/"` | `"code"` | | 官方云(wang.market) | `site.id > 255` 或 `site.id == 218` | `"code"` | | 官方云(wang.market) | `site.id ≤ 255` 且 `site.id ≠ 218`(老站点) | `"int"`(默认值) | **实际操作**: 1. **自部署环境**:可直接判定为 `code` 规则,列表页 URL = `codeName.html`,独立页面 URL = `codeName.html`,新闻详情 URL = `News.id.html`。 2. **官方云/不确定环境**: - 从用户/宿主取得站点 ID,按上表判定;或 - 后台查看站点设置;或 - 从已生成页面 URL 反推:`news.html`/`news_2.html` → `code`;`lc1001_1.html`/`451.html` → `int`。 3. **站点基础 URL(域名/访问路径)**:仍须由用户、宿主或后台提供,MCP 无查询接口。 4. **独立页面(type=8)的 URL**:`code` 规则下 = `codeName.html`(源码 `generateNewsPageHtmlName()` 已确认);`int` 规则下须由后台确认,不得推导(见 9.12.1)。 ### 11.3 栏目/模板变量/新闻的已有状态与真实 ID 确认 **待确认内容**:目标站点是否已存在同名栏目、模板变量、模板页面或新闻,以及它们的真实 ID。 **确认方法**: 1. **后台查看**: - 栏目:后台「栏目管理」列表,记录栏目名称、ID、`codeName`、类型; - 模板变量:后台「模板管理 → 模板变量」,记录 `varName` 和 ID; - 模板页面:后台「模板管理 → 模板页面」,记录 `name`、`type` 和 ID; - 新闻:后台「内容管理」,按栏目筛选,记录文章 ID。 2. **从本次会话上下文取得**:若前面的工具调用已返回 `info` 中的正整数 ID,直接使用该值。 3. **当前 MCP 限制**:没有按名称/代码查询的工具,缺少 ID 时必须停止并请求后台确认,不得猜测或用 `id=0` 假装更新。 ### 11.4 `save_template` 目标模板与副作用确认 **待确认内容**:当前站点 `site.template_id` 是否指向有效模板;调用 `save_template` 是否会修改已有模板。 **确认方法**: 1. **后台查看模板绑定**:在后台「模板管理」中查看当前站点是否已选择/导入模板,以及模板名称。 2. **评估副作用**:`save_template` 的实现可能在 `template_id` 无效时使用 ID 1,可能创建或修改既有模板。调用前必须由用户确认允许该操作影响现有模板。 3. **调用后验证**:`result=1` 后仍需后台复核绑定状态,并执行 `generate_site` + 真实 URL 验收,不能仅凭返回值宣称绑定成功。 ### 11.5 `save_site_column.info` 非数字文本的落库状态确认 **待确认内容**:`result=1` 但 `info` 返回 `"成功"` 等非数字文本时,栏目是否实际落库、ID 是多少。 **确认方法**: 1. **停止后续写入**,不要重复调用 `save_site_column`(可能创建重复栏目)。 2. **后台栏目管理**:按栏目名称和创建时间找到刚创建的栏目,记录其真实 ID。 3. **若存在多个同名栏目**:通过绑定的模板页面名称(`templatePageListName` / `templatePageViewName`)和创建时间区分,确认哪一个是本次创建的。 4. **使用后台确认的真实 ID** 继续后续 `save_news` / `save_alone_page_content`。 ### 11.6 `{templatePath}` 前缀尾斜杠(6.1 已确认) **WangMarket 6.1 源码已确认**:`{templatePath}` 输出**末尾一定带斜杠 `/`**。 `getTemplatePath()` 实现:路径前缀 + `site.templateName` + `"/"`(字节码显式 append `/`)。路径前缀本身也以 `/` 结尾: - 私有模板:`ATTACHMENT_FILE_URL` + `websiteTemplate/` - 云模板:`//cloudtemplate.weiunity.com/websiteTemplate/` **6.1 版本确定写法**:模板中统一写 `{templatePath}css/style.css`(**不加**额外斜杠)。 **禁止写法**:`{templatePath}/css/style.css` 会产生双斜杠 `//`(如 `https://example.com/template/default//css/style.css`),部分浏览器/CDN 可能无法正确解析。 **跨版本注意**:目标版本不是 6.1 时,生成一次后查看实际 `href` 确认;确认后整份模板统一一种写法。 ### 11.7 `generate_site` 后静态文件可访问性确认 **待确认内容**:`generate_site` 返回 `result=1` 后,静态文件是否真实可访问。 **确认方法**: 1. **使用真实 URL 做 HTTP 验收**:用浏览器或 `curl` 访问首页、列表页、详情页,检查 HTTP 状态码。 2. **检查内容**:页面中文正常、无未解析标签、无残留动态标记、CSS/JS/图片可加载。 3. **404/超时处理**: - 不要无限重试 `generate_site`; - 检查宿主 Web 服务器根目录配置、CDN 缓存; - 后台文件管理中确认静态文件是否实际生成及文件名; - 无轮询工具时停止并等待后台确认。 ### 11.8 独立页面内容唯一性与存在性确认 **待确认内容**:`save_alone_page_content` 按 `cid` 查询的 News 记录在当前站点下是否存在且唯一。 **确认方法**: 1. **后台内容管理**:进入该独立页面栏目,首先确认是否存在内容记录。 - **若不存在任何内容记录**:当前 MCP 无法创建(`save_alone_page_content` 只查询不创建,`save_news` 不适用于 type=8),必须由人工在后台"内容管理"中为该栏目手动添加一条内容,之后 AI 才能用 `save_alone_page_content` 更新。在此之前不得宣称关于我们页面已完成。 - **若存在且仅有一条**:继续下一步。 2. **若存在多条同 `cid` 记录**:底层查询目标不确定,必须停止,由后台清理重复数据后再执行 `save_alone_page_content`。 3. **实现边界说明**:底层查询未显式带 `siteid` 条件,跨站数据可能干扰;不得无条件承诺「当前站点唯一」。 ### 11.9 非 6.1 版本的 `valueItems`、日期格式与嵌套行为确认 **待确认内容**:目标 WangMarket 版本不是已核对的 6.1 时,`select` 类型全局变量的 `valueItems` 格式、`{news.addtime.month}` 是否补前导零、模板变量非循环嵌套是否生效。 **确认方法**: 1. **确认版本号**:在后台关于页面或页脚查看 WangMarket 版本号。 2. **`valueItems` 格式**:在后台创建一个 `select` 类型全局变量,保存后查看选项是否正确解析;若 `值:显示文本` 格式不生效,尝试后台文档说明的格式。 3. **日期格式**:在详情模板中写入 `{news.addtime.month}`,生成后查看输出是 `3` 还是 `03`;需要固定两位时由模板前端 JS 格式化,不依赖 CMS 输出。 4. **模板变量嵌套**:创建变量 A 引用变量 B,生成后查看是否展开;若不生效,改为在模板页面中分别直接引用。 ### 11.10 `News.htmlName` 对详情 URL 的影响确认 **待确认内容**:`save_alone_page_content` 的 `htmlName` 参数是否影响当前生成器的详情页 URL。 **确认方法**: 1. **创建测试内容**时设置 `htmlName=test-page`,生成后查看详情页实际 URL。 2. **若 URL 未使用 `test-page.html`**:说明当前版本生成器不采用 `htmlName`,不得用它推导预览 URL。 3. **统一规则**:详情页 URL 始终使用真实生成结果或后台确认的地址,不得由 `htmlName`、`News.id` 或 `codeName` 推导。 ### 11.11 确认结果记录模板 每次完成上述确认后,应按以下格式记录,供后续执行引用: ```text 确认项:<对应 11.1-11.10 的编号> 目标运行时版本:<版本号> 确认方法:<帮助页 / 真实生成 / 后台查看> 确认结果:<可用 / 不可用 / 具体参数值> 证据:<帮助页截图描述 / 生成页面 URL / 后台路径> 确认时间: ``` 未完成确认的事项,在执行时必须按第 10 章的「当前可执行边界」停止并报告,不得跳过。 --- ## 常见问题与避坑指南 在实际操作过程中,以下常见问题容易导致生成失败或页面显示异常,在此特别说明,避免后续踩坑。 ### 问题1:后台点击「生成整站」提示"当前网站尚未选择/导入/增加模版,生成失败!" #### 现象描述 在网站管理后台左侧菜单点击「生成整站」按钮时,弹出错误提示: ``` 当前网站尚未选择/导入/增加模版,生成失败!网站有模版后才能根据模版生成整站! ``` 但奇怪的是,已经创建了模板页面(index、about、news)和模板变量(nav、footer),为什么还提示没有模板? #### 原因分析 网市场系统的模板体系分为两层: | 层级 | 数据表 | 说明 | |---|---|---| | 模板(Template) | `template` | 模板的基本信息,一个模板包含多个模板页面 | | 模板页面(TemplatePage) | `template_page` + `template_page_data` | 具体的页面模板(首页、列表页、详情页) | 网站表 `site` 中有一个字段 `template_id`,指向 `template` 表中的模板记录。 后台「生成整站」按钮在执行生成前,会校验: ```text site.template_id → template 表中是否存在对应记录 ``` 如果 `template` 表为空,或者 `site.template_id` 指向了一个不存在的模板 ID,校验就会失败,提示"当前网站尚未选择/导入/增加模版"。 而通过 MCP 接口 `generate_site`(对应上游接口 `/template/refreshForTemplate.do`)生成时,可能不执行同一项绑定校验,因此“生成调用返回成功”和“后台模板绑定有效”必须分别验证。 #### 解决方案 **方案一:在确认允许影响当前模板后调用 `save_template`** 本文档已新增 MCP 工具 `save_template`,对应上游接口: ```text POST /plugin/adminapi/site/saveTemplate.json ``` 当前实现的真实边界: 1. 读取当前网站的 `site.template_id`;为空或不大于 0 时把候选 ID 设为 `1`。 2. 候选 ID 不存在时,尝试按该 ID 新建模板记录,并把网站指向它。 3. 候选 ID 已存在时,不会重新绑定到其它模板;传入非默认名称或非空备注还可能修改该既有模板。 4. 若网站原本没有有效 `template_id` 而模板 ID 1 已存在,当前代码可能返回成功但没有把网站重新绑定到 1。 5. 接口没有验证新建/既有模板是否与已创建的模板页面正确归属,也不能保证后台按钮随后一定成功。 因此调用前必须由用户或后台确认允许该操作影响现有模板。无法确认当前绑定状态时,不得把此工具描述为无副作用的“确保绑定”。为降低误改风险,默认只传 `authHandle`;只有用户明确要求修改模板名称/备注时才传对应字段。 调用示例: ```json { "authHandle": "" } ``` 参数说明: | 参数 | 是否必填 | 类型 | 说明 | |---|---|---|---| | `authHandle` | 是 | string | `login` 成功返回的认证句柄 | | `name` | 否 | string | 模板名称,默认"自定义模板" | | `remark` | 否 | string | 模板备注,默认空字符串 | 返回示例: ```json { "result": 1, "info": "1" } ``` 其中 `info = "1"` 只是示例模板 ID。`result=1` 只表示本接口完成,不能宣称绑定、后台生成或预览已成功;仍须执行本节验证方法。 **方案二:由获授权的数据库管理员修复** 数据库写入不属于本文 MCP/AI 自动建站流程。只有获授权管理员在确认目标站点 ID、当前用户、目标模板 ID、数据归属并完成备份后,才能按实际数据库版本修复;不得把示例 ID `1` 当成固定值,也不得让 AI 执行未经限定站点的 `INSERT` 或 `UPDATE`。 #### 验证方法 依次验证:后台确认目标站点指向预期模板;后台「生成整站」不再出现该错误;`generate_site` 返回 `result=1`;最后用真实站点 URL 检查首页、列表页和详情页。四项都通过后才算解决。 --- ### 问题2:生成的网站中文乱码(UTF-8 编码问题) #### 现象描述 生成整站后,访问生成的静态 HTML 页面,中文显示为乱码(如"棣栭〉"、"鏂伴椈鍒楄〃"等),但英文和数字显示正常。 查看生成的 HTML 文件源码,发现文件中没有 `` 标签。 #### 原因分析 在创建模板页面时,如果只保留了 body 内部的内容,例如: ```html {include=nav}

    hi,这是首页

    {include=footer} ``` 而**没有保留完整的 HTML 文档结构**(缺少 ``、``、``、``、`` 等标签),那么系统生成静态 HTML 时,会直接将模板内容输出到文件中,不会自动添加 `` 和编码声明。 浏览器在解析没有编码声明的 HTML 文件时,会使用系统默认编码(在中文 Windows 上通常是 GBK/GB2312),而文件实际是 UTF-8 编码保存的,编码不匹配就会导致中文乱码。 #### 解决方案 **在创建/修改模板页面时,必须保留完整的 HTML 文档结构,包含 ``。** 正确的首页模板示例: ```html 首页 - 网站名称 {include=nav}

    hi,这是首页

    网站介绍内容...
    {include=footer} ``` 正确的详情页(关于我们)模板示例: ```html {news.title} - 网站名称 {include=nav}

    {news.title}

    {news.text}
    {include=footer} ``` 正确的列表页(新闻列表)模板示例: ```html 新闻列表 - 网站名称 {include=nav}

    新闻列表

    {include=footer} ``` #### 如果已有模板缺少编码声明,如何修复? 先从后台取得当前模板页面的完整源码,整理成**唯一一套** `doctype/html/head/body` 结构并保留原正文,再通过后台或 `save_template_page_text` 整体覆盖。不要在未知原文前后盲目追加标签,否则可能生成嵌套或重复的 ``、``、``。当前 MCP 没有读取模板页面源码的工具;若手头没有可信的完整原文,必须停止并要求后台导出,不能凭空重建后覆盖。 保存后重新生成整站,并用真实 URL 检查响应内容与浏览器显示。 #### 验证方法 生成整站后,查看生成的 HTML 文件源码,确认文件开头包含: ```html ``` 在浏览器中打开页面,中文应正常显示,不再出现乱码。 --- ### 问题3:`save_site_column` 返回 `result=1` 但 `info` 是"成功"等非数字文本 #### 现象描述 调用 `save_site_column` 创建栏目后,返回: ```json { "result": 1, "info": "成功" } ``` `info` 不是数字,无法取得栏目 ID,后续 `save_news` 或 `save_alone_page_content` 的 `cid` 参数无法填写。 #### 原因分析 不同版本的 WangMarket 上游接口在 `save_site_column` 成功时,`info` 字段的返回值不一致: - 部分版本返回栏目 ID(如 `"789"`); - 部分版本返回固定成功文本(如 `"成功"`)。 当前 MCP 没有栏目查询工具,无法通过 `codeName` 或栏目名称反查 ID。 #### 解决方案 1. **停止后续写入操作**,不要猜测栏目 ID,也不要用 `codeName`、栏目名称或模板页面 ID 代替 `cid`。 2. **进入后台确认**:在后台「栏目管理」中找到刚创建的栏目,记录其真实 ID。 3. **使用后台确认的真实 ID** 继续调用 `save_news` 或 `save_alone_page_content`。 4. 若后台中存在多个同名栏目,必须确认哪一个是本次创建的(可通过创建时间、绑定的模板页面名称区分),避免更新错误栏目。 5. 不要因为 `result=1` 就重复调用 `save_site_column`,否则可能创建重复栏目。 #### 验证方法 后台栏目列表中能看到本次创建的栏目;使用后台确认的真实 ID 调用后续工具返回 `result=1`;生成后页面内容属于目标栏目。 --- ### 问题4:页面中 `{include=nav}`、`{var.qq}`、`{news.title}` 等标签没有被解析,原样显示在生成的 HTML 中 #### 现象描述 生成整站后,查看页面源码,发现 `{include=nav}`、`{var.qq}`、`{news.title}`、`{siteColumn.name}` 等花括号标签没有被替换,原样出现在 HTML 中。 #### 原因分析 按标签类型分别排查: | 标签类型 | 常见原因 | |---|---| | `{include=xxx}` | 模板变量不存在、`varName` 拼写不一致、变量 `text` 为空、保存变量在保存页面之后 | | `{var.xxx}` | 全局变量不存在、变量名拼写不一致、变量未设置 `value` | | `{news.*}` / `{siteColumn.*}` / `{page.*}` | 当前页面没有对应上下文(如首页直接写 `{news.title}`)、目标运行时不支持该标签、标签在错误的循环位置使用 | | 动态标记 `` 等 | 标记拼写错误(区分大小写)、`codeName` 不存在、标记未正确闭合 | #### 解决方案 1. **`{include=xxx}` 未解析**: - 确认模板变量已通过 `save_template_var` 创建且 `result=1`; - 确认页面中 `{include=nav}` 的 `nav` 与 `save_template_var.varName` 完全一致(大小写敏感); - 确认变量 `text` 不为空; - 确认创建变量在保存页面 HTML 之前执行(见 2.2.5 顺序规则)。 2. **`{var.xxx}` 未解析**: - 确认全局变量已通过 `save_site_var` 创建; - 确认变量名与 `{var.qq}` 中的 `qq` 完全一致; - 确认变量已设置 `value`。 3. **`{news.*}` / `{siteColumn.*}` / `{page.*}` 未解析**: - 按前置规则第 10 条,先确认目标运行时是否支持该标签及上下文; - 确认标签使用在正确的上下文中:`{news.*}` 必须在详情页或文章循环内,`{page.*}` 仅用于列表页,首页不能直接写 `{news.title}`; - 确认动态标记 `` / `` 等拼写正确且已闭合。 4. **动态标记残留**: - 检查标记是否精确匹配(区分大小写,无多余空格):``、``、``、``、``、``、``、``; - 确认 `codeName` 指向的栏目真实存在且已启用。 #### 验证方法 重新生成整站后,页面源码中不再出现未解析的花括号标签和动态标记;页面内容正确显示为后台数据。 --- ### 问题5:`generate_site` 返回 `result=1` 但访问页面 404 或超时 #### 现象描述 `generate_site` 返回 `result=1`,但使用预期 URL 访问页面时返回 404 或连接超时。 #### 原因分析 `result=1` 只表示生成调用已完成,不代表: - 静态文件已写入到可访问的目录; - 宿主 Web 服务器已配置正确的站点根目录; - 预期 URL 与实际生成的文件名一致; - 生成过程中没有静默跳过某些页面。 常见具体原因: 1. **URL 猜测错误**:由 `codeName` 或栏目 ID 拼接的 URL 与实际 `generateUrlRule` 不符; 2. **宿主环境延迟**:静态文件生成后,CDN 或 Web 服务器需要时间刷新; 3. **站点未绑定有效模板**:见问题1; 4. **栏目未启用或 `useGenerateView=0`**:详情页不会生成。 #### 解决方案 1. **不要无限重试 `generate_site`**,也不要猜测 URL。记录真实的 404/超时错误信息。 2. **确认真实站点基础 URL**:从用户、宿主或后台取得,不要由 `codeName` 或 ID 推导。 3. **确认 `generateUrlRule`**:只有后台确认使用 `code` 规则时,`codeName.html` 才可能成立;其它规则可能使用栏目 ID 路径。 4. **确认栏目状态**:栏目 `used=1`、信息列表栏目 `useGenerateView=1`(需要详情页时)。 5. **后台确认生成结果**:在后台文件管理或 FTP 中查看静态文件是否实际生成、文件名是什么。 6. 若宿主有轮询或生成状态查询工具,使用它确认生成完成;没有则等待后台确认。 #### 验证方法 使用后台确认的真实 URL 访问,返回 HTTP 200;页面内容正确;中文正常;无未解析标签。 --- ### 问题6:更新已有模板变量/栏目时,应该传 `id` 还是省略? #### 现象描述 需要修改已存在的 `nav` 模板变量或已创建的栏目,不确定是否应该传 `id` 参数。 #### 原因分析 `save_template_var`、`save_template_page`、`save_site_column` 的 `id` 参数行为一致: - `id` 省略、`null` 或 `0` → **创建新对象**,不会按名称覆盖已有对象; - `id > 0` → **更新已有对象**。 如果省略 `id` 去"更新"已有变量,实际会创建一个同名新变量,导致重复。 #### 解决方案 按文末闭环开头的**创建/更新判定规则**执行: | 情况 | 处理方式 | |---|---| | 已存在,且有已确认的真实 ID | **更新**:显式传入该真实 ID | | 已确认不存在 | **创建**:省略 `id`,或传 `0` / `null` | | 状态不明,或没有真实 ID | **停止**:由后台确认,不得猜 ID、不得重复创建 | 具体操作: 1. 从本次会话前面的工具返回结果中查找 `info` 字段中的真实 ID; 2. 若上下文中没有,进入后台确认对象 ID; 3. 当前 MCP 没有按名称查询模板变量/栏目/新闻的工具,不能用 `varName`、`name` 或 `codeName` 代替 ID。 #### 验证方法 更新后后台只有一个目标对象(无重复);对象内容为更新后的值;生成页面反映更新内容。 --- ### 问题7:`{templatePath}` 生成的 CSS/JS/图片路径出现双斜杠 `//` #### 现象描述 生成页面后,查看资源引用,发现路径如 `https://example.com/template//css/style.css`,中间有双斜杠。 #### 原因分析 **WangMarket 6.1 源码已确认**:`{templatePath}` 输出末尾**一定带斜杠 `/`**(`getTemplatePath()` = 路径前缀 + templateName + `"/"`)。如果模板中写 `{templatePath}/css/style.css`,变量本身已带 `/`,就会生成 `//`。 #### 解决方案 1. **6.1 版本确定写法**:模板中统一写 `{templatePath}css/style.css`(**不加**额外斜杠); 2. **不要把双斜杠当作通用可接受行为**,部分浏览器/CDN 可能无法正确解析; 3. 修改后重新生成整站,检查所有资源引用。 #### 验证方法 生成页面中所有 `{templatePath}` 引用的资源路径无重复斜杠;CSS/JS/图片均可正常加载(HTTP 200)。 > **跨版本注意**:目标版本不是 6.1 时,生成一次后查看实际 `href` 确认前缀是否带斜杠,再统一写法。 --- ### 问题8:`save_alone_page_content` 返回内容不存在或栏目下没有内容记录 #### 现象描述 创建"关于我们"独立页面栏目(`type=8`、`editMode=0`)后,调用 `save_alone_page_content` 更新内容时返回 `result=0`,`info` 提示未找到内容记录;或在后台"内容管理"中进入该栏目发现没有任何内容。 #### 原因分析 `save_alone_page_content` 底层先执行 `SELECT * FROM news WHERE cid = ?`,查询为空时立即返回错误,**不会创建内容记录**。虽然创建 `type=8` 栏目时系统可能尝试自动生成一条内容,但这不是保证行为——部分版本、部分数据状态下可能未生成。 当前 MCP 工具集中没有"按栏目创建独立页面内容"的替代工具: - `save_news` 仅用于 `type=7` 信息列表栏目,不适用于 `type=8` 独立页面; - `save_alone_page_content` 只更新不创建。 #### 解决方案 1. **停止 MCP 操作**,不要重试 `save_alone_page_content`(不会因为重试而创建内容),也不要改用 `save_news`(栏目类型不匹配)。 2. **由人工在后台"内容管理"中为该栏目手动添加一条内容**:进入内容管理 → 选择"关于我们"栏目 → 添加内容 → 填写标题和正文 → 保存。 3. 后台确认内容已存在且唯一后,AI 再使用 `save_alone_page_content(cid=栏目ID)` 更新该内容。 4. 在此之前,关于我们页面的 `{news.title}`/`{news.text}` 无数据来源,**不得宣称该页面已完成**。 #### 验证方法 后台内容管理中该栏目下有且仅有一条内容记录;`save_alone_page_content` 返回 `result=1`;`generate_site` 后关于我们页面正确显示标题和正文。 --- ## AI 自动执行的唯一闭环 > **能力边界声明**:本节是 MCP 工具集支持范围内的唯一执行顺序,但**不构成"AI 全自动闭环"**。当前 MCP 缺少站点 URL/生成结果查询工具和独立页面内容创建工具,因此以下步骤中,真实页面 URL 必须由用户、宿主或后台外部提供;独立页面内容记录若未自动创建,必须由人工在后台添加后 AI 才能更新。缺少这些外部输入时,流程必须在对应步骤暂停并报告缺口,不得猜测或降级。 本节是全文的最终顺序;前文各章用于准备参数和 HTML,不得另行拼接出不同流程。示例 `index`、`about`、`news`、`newsView` 可以按需求改名,但同一对象在创建、保存和绑定处必须一致。 > **创建 / 更新判定规则(适用于每一个对象:模板变量、模板页面、栏目、新闻)** > > 执行前先对对象做三选一判定,再决定怎么调用: > > | 判定结果 | 处理方式 | > |---|---| > | 已存在,且有已确认的真实 ID | **更新**:显式传入该真实 ID | > | 已确认不存在 | **创建**:省略 `id`,或传 `0` / `null` | > | 状态不明,或没有真实 ID | **停止**:由后台确认,不得猜 ID、不得重复创建、不得用 `id=0` 假装更新 | > > 三条容易出错的边界: > > - `save_template_var` 的 `id` 省略、`null` 或 `0` 一律按**新建**处理,**不会按 `varName` 覆盖已有变量**;已有同名变量必须先取得真实 ID。 > - `save_template_page`、`save_site_column` 同理:已存在时必须用已确认的真实 ID 更新;确认不存在时才省略 ID 或传 `0`。 > - `save_news` 更新时必须**同时**提供真实 `News.id` 和真实 `cid`。 1. **准备并校验输入**:确认目标站点、运行时工具 schema、**本次要走哪些业务分支**(首页 / 独立页面 / 信息列表并启用详情)、每个对象的创建或更新状态与真实 ID、完整 HTML、文案、真实图片 URL、允许的模板绑定方案,以及真实站点基础 URL。需要更新的对象必须有真实 ID;需要自定义输入模型、栏目代码或图片 URL 时必须有后台依据。任一缺失即停止,不开始写入。 2. **登录**:调用 `login`。仅 `result=1` 且返回非空真实 `authHandle` 时继续,后续每个业务工具均原样传入它。 3. **先保存被引用的数据**:模板若使用 `{var.xxx}`,先用 `save_site_var` 创建完整定义;只改已确认存在的值才用 `save_site_var_value`。然后按本节开头的**创建/更新判定规则**处理 `nav`、`footer` 模板变量——已存在且有真实 ID 就按 ID 更新,已确认不存在才创建,不明则停止,并保存真实变量 ID。若真实导航 URL 尚未取得,可先保存不含猜测链接的最小导航,待第 8 步取得 URL 后按真实 ID 更新。 4. **按业务分支创建并保存模板页面**:先按第 1 步确定的分支列出本轮真正需要的页面,再对每个页面调用 `save_template_page(editMode=2)`,成功后**立即用相同名称**调用 `save_template_page_text` 保存完整 HTML。只有元数据和 HTML 两次调用都成功才算就绪;返回的页面 ID 不传给 `pageName`。 - **首页分支** → 需要 `index`(`TemplatePage.type=1`); - **独立页面分支** → 需要 `about` 等 `type=3` 页面; - **信息列表分支** → 需要 `news`(`type=2`);**只有启用详情生成(`useGenerateView=1`)时**才还需要 `newsView`(`type=3`)。 未选择的分支不创建、不绑定、不在第 10 步虚构预览页面;页面已存在时按判定规则用真实 ID 更新。 5. **处理模板绑定**:若后台已确认当前网站绑定有效模板,不调用 `save_template`。若尚未绑定,只有用户已授权其潜在副作用时才调用;`result=1` 后仍须后台复核绑定。未授权或无法确认时停止,不能宣称已确保绑定。 6. **创建或更新关于我们业务数据**(仅当选择独立页面分支时执行):按判定规则处理后,用 `save_site_column(type=8, templatePageViewName=about, editMode=0)` 写入栏目。只有 `result=1` 且 `info` 可严格解析为已确认属于当前站点的大于 0 的真实栏目 ID 时,才把它传给 `save_alone_page_content.cid`;`info` 为 `成功`、空值或其它非数字文本时停止并由后台确认。调用前还必须按 5.3 确认系统已创建且唯一的目标内容;存在多条同 `cid` 历史记录时停止。**若后台确认该栏目下没有内容记录,当前 MCP 无法创建——必须由人工在后台"内容管理"中手动添加一条后,才能继续 `save_alone_page_content`;在此之前不得宣称关于我们页面已完成。** 7. **创建或更新新闻业务数据**(仅当选择信息列表分支时执行):确认 `news`(启用详情生成时还包括 `newsView`)均已完整保存后,按判定规则处理栏目,再用 `save_site_column(type=7, templatePageListName=news, templatePageViewName=newsView)` 写入,并显式传本流程需要的编辑字段;更新已存在栏目时必须使用已确认的真实 ID。仍仅接受可确认的正整数栏目 ID,然后把该真实 ID 作为 `save_news.cid`。**更新新闻时必须同时提供真实 `News.id` 和真实 `cid`**。 8. **预生成并补齐真实导航**:先调用一次 `generate_site` 使本轮页面落库(`result=1` 仅表示调用完成,不返回任何 URL)。**当前 MCP 没有站点 URL、栏目或生成结果查询工具**,预生成后 AI 仍不能从返回值取得页面地址——必须由用户、宿主或后台提供本轮实际页面的真实 URL(首页、独立页面、列表页;启用详情生成时还需至少一篇详情页)。未知 `generateUrlRule` 时不得由 `codeName` 或栏目 ID 拼接。取得全部 URL 后,使用第 3 步保存的真实 `nav` 模板变量 ID 更新完整导航。缺少 nav ID 或任一页面 URL 时,保留第 3 步的最小导航并报告缺口,不得猜测 URL 或用 `about.html`/`news.html` 等示例路径充数。 9. **最终生成**:导航更新后再次调用 `generate_site`,使导航变更反映到静态页面。`result=1` **只表示生成调用已完成**,不等于静态文件已可访问或内容正确。必须按宿主提供的真实 URL 做一次 HTTP 与内容验收;若出现 404、超时且没有官方轮询/查询工具,**不得无限重试生成、不得猜 URL**,应记录真实错误并停止等待后台确认。 10. **真实预览验收**:使用可信 URL 分别访问**本轮实际选择的分支**生成的页面——首页分支访问首页;独立页面分支访问该独立页面;信息列表分支访问列表页;启用详情生成时再访问至少一篇详情页。**未选择的业务分支不创建、不绑定、也不虚构预览页面。** 全部满足以下条件才算建站成功:HTTP 响应可访问;UTF-8 中文正常;页面结构、导航、分页、详情链接及模板实际引用的图片/资源可用(题图/轮播必须确认是用户提供的真实素材,不能只凭 `titlepic` 非空);内容属于目标站点;源码中没有未解析的 `{include=...}`、`{var.*}`、`{news.*}`、`{siteColumn.*}`、`{page.*}`,也没有残留的精确动态标记 ``、``、``、``、``、``、`` 或 ``。 全局失败规则:先判断 MCP/传输错误,再判断业务 `result`。`result=0`、`mcpError`、`isError=true` 或验收失败时停止当前依赖链并报告真实错误;`result=2` 时重新登录,只重试刚失败的一步。超时、断线或其它无法判断写入是否落库的情况禁止盲目重试创建/覆盖操作,必须先由后台确认实际状态,否则可能产生重复对象或覆盖正确内容。 当前 MCP 没有站点 URL规则、栏目、模板页面、模板变量、新闻、输入模型、全局变量或上传结果的通用查询工具。缺少真实上下文时,结论只能是“需要后台确认或补充查询接口”,不能借用其它 CMS 经验、示例值、名称、`codeName`、URL 数字或历史默认值进行推断。
    历史正文标签旧模板兼容行为需按目标运行时验证;新模板不使用

    新建详情模板统一使用 {news.text}。只有迁移已有旧模板且目标运行时已实测支持时,才保留裸 本文是 WangMarket MCP 模板建站流程的执行规范。除明确标注为固定枚举或固定语法外,文中 HTML、文案、URL、栏目名、`codeName`、ID、账号、QQ、图片地址和返回 `info` 均为示例或占位值,不得直接写入生产站点。 **版本基准**:本文所有"已确认"的模板标签、URL 生成规则、`templatePath` 行为等结论,均基于 **WangMarket 6.1** 源码(依赖 `wangmarket-6.1.jar`)反编译核对。目标站点运行版本不是 6.1 时,标注"6.1 已确认"的项仍须按第 11 章实测确认;标注"跨版本注意"的项尤其需要验证。 **执行前置条件**:目标站点已开通且已明确;登录凭据有效;运行时工具列表至少包含本次分支所需的 `login`、`save_template_var`、`save_site_column`、`save_template_page`、`save_template_page_text`、`generate_site`,并按页面类型提供 `save_news`(信息列表内容)或 `save_alone_page_content`(独立页面内容);只有实际使用全局变量时才需要 `save_site_var`/`save_site_var_value`,只有绑定缺失且获授权修复时才需要 `save_template`。各工具 schema 必须与本文调用相符;站点是否已有同名对象已确认;预览所需的真实站点基础 URL 已由用户、宿主或后台提供。**当前工具集没有站点 URL/生成结果查询工具,也没有"按栏目创建独立页面内容"的工具**:真实页面 URL 必须外部提供,独立页面内容若未自动创建必须人工在后台添加后 AI 才能更新。任一当前分支必需条件缺失时必须先报告并停止,不得猜测或开始写入。 **⚠️ 静态资源上传前置检查(必须在第 1 章之前完成)**: 开始读取和制作模板之前,必须先检查用户上传的 HTML 模板包中是否引用了**本地静态资源文件**,包括但不限于: | 资源类型 | 常见引用方式 | 常见扩展名 | |---------|------------|----------| | 样式表 | ``、`@import` | `.css` | | 脚本 | ` logo ``` > **⚠️ `{templatePath}` 尾斜杠未统一,必须实测后固定一种写法**:现有资料对该前缀本身是否已带尾斜杠 `/` 没有一致结论——若前缀已含 `/`,上面这种 `{templatePath}/css/...` 就会生成 `//` 双斜杠。**不要把双斜杠当作通用可接受行为。** > > 落地做法:在目标版本上先生成一次,查看生成页中实际的 `href` / `src`,确认前缀是否带尾斜杠,然后整份模板统一采用一种写法(例如确认前缀带 `/` 时统一写 `{templatePath}css/style.css`)。未实测前不得批量写入模板。 不要把本地开发机地址、临时 CDN 地址或 `localhost` 资源地址硬编码进最终模板。 --- ### 9.3 栏目标签 `{siteColumn.*}` 后台帮助页:`/templateTag/column.do` **正确命名空间是 `{siteColumn.*}`,不是 `{column.*}`。** 当前栏目帮助页列出的字段如下;但 `.taglist.html` 对列表页的适用性标为“不可用”,与其它资料冲突。 按**前置规则第 10 条**,下表字段名称只是候选语法:只有目标运行时帮助页或一次真实生成结果确认该字段及其页面上下文可用,AI 才能写入模板;冲突且无法确认时暂停,不得回退、混用或猜测。 | 标签 | 含义 | 类型/特殊说明 | |---|---|---| | `{siteColumn.id}` | 栏目 ID | 整数 | | `{siteColumn.name}` | 栏目名称 | 字符串 | | `{siteColumn.url}` | 栏目链接地址 | URL | | `{siteColumn.type}` | 栏目类型 | 整数;不要据此反推未说明枚举的含义 | | `{siteColumn.used}` | 栏目是否启用/显示 | 整数 | | `{siteColumn.codeName}` | 栏目代码 | 字符串/字母 | | `{siteColumn.parentCodeName}` | 当前栏目的父栏目代码 | 若当前栏目已经是顶级栏目,帮助页说明这里返回当前栏目代码 | | `{siteColumn.icon}` | 栏目图片/图标 | URL | | `{siteColumn.keywords}` | SEO 关键字 | 字符串 | | `{siteColumn.description}` | SEO 描述 | 字符串 | #### 9.3.1 列表页中的栏目标签使用上下文 部分帮助页把栏目标签的适用范围标为**列表页**,但公开列表索引又标为“不可用”。只有目标运行时确认后,列表页才可以直接使用当前栏目的 `{siteColumn.*}` 属性,例如: ```html

    {siteColumn.name}

    {siteColumn.name} ``` 在目标版本确认栏目标签可用后,还可区分以下两个上下文: ```text TemplateListItemStart ... TemplateListItemEnd → 若该循环被目标版本启用,栏目标签表示当前循环文章关联的栏目 SiteColumn_Start / SubColumnList_Start 动态调用上下文 → 若相应字段被目标版本启用,栏目标签表示当前被动态调取的栏目/子栏目 ``` 因此 AI 必须根据上下文理解 `{siteColumn.*}` 所指向的栏目对象,不要把动态调用中的栏目、列表页当前栏目和文章关联栏目混成同一个固定对象。 --- ### 9.4 文章信息标签 `{news.*}` 后台文章信息标签帮助页展示以下字段;列表/详情适用性在不同资料中存在冲突,本文示例使用这些字段不等于目标运行时必然支持。 按**前置规则第 10 条**:只有目标运行时帮助页或一次真实生成结果确认该字段及其上下文可用,AI 才能写入模板;冲突且无法确认时必须暂停,不得回退为写死内容、不得混用两套规则、不得猜测其它字段。 | 标签 | 含义 | 类型/说明 | |---|---|---| | `{news.id}` | 文章编号 | 整数 | | `{news.title}` | 文章标题 | 字符串 | | `{news.titlepic}` | 文章列表图/标题图 | URL | | `{news.intro}` | 文章简介 | 字符串 | | `{news.url}` | 文章页面链接地址 | URL | | `{news.cid}` | 文章所属栏目编号 | 整数 | | `{news.text}` | 文章正文 | HTML | | `{news.extend.photos}` | 文章图集 | JSON 格式字符串,需要前端 JS 自行解析 | | `{news.extend.???}` | 自定义扩展字段 | `???` 必须替换为真实已存在字段名,禁止编造 | | `{news.addtime}` | 发布时间 | 字符串日期 | | `{news.addtime.year}` | 发布时间-年 | 整数/字符串输出 | | `{news.addtime.month}` | 发布时间-月 | 运行时输出;是否补前导零未确认 | | `{news.addtime.day}` | 发布时间-日 | 运行时输出;是否补前导零未确认 | | `{news.addtime.hour}` | 发布时间-时 | 示例 `10` | | `{news.addtime.minute}` | 发布时间-分 | 示例 `23` | 在目标运行时确认文章标签可用后,两个典型上下文是: ```text 详情页:用于当前文章/当前独立页面内容,例如 {news.title}、{news.text} 列表循环:用于当前循环项,例如 {news.url}、{news.title}、{news.titlepic} ``` 不要在不存在“当前文章”或“当前循环项”的普通模板位置随意写 `{news.*}` 并假设系统知道你要哪一篇文章。 --- ### 9.5 动态栏目调用 后台帮助页:`/templateTag/dynamic.do` 动态栏目调用的明确用途: 1. 调取当前生成上下文中可用于模板调用且未被禁用/隐藏的一级栏目; 2. 调取某个指定栏目下可用于模板调用且未被禁用/隐藏的子栏目; 3. 根据栏目代码调取该栏目属性,以及该栏目下文章列表。 帮助页标记的适用范围包括:首页、列表页、详情页、模板变量。 `SiteColumn_Start` / `SiteColumn_End`、`SubColumnList_Start` / `SubColumnList_End`、`List_Start` / `List_End` 以及列表模板的 `TemplateListItemStart` / `TemplateListItemEnd` 都是区分大小写的精确标记。不得添加空格、改连字符、翻译或改写名称。生成后若仍残留这些标记或 `{news.*}`、`{siteColumn.*}` 等标签,视为生成失败,必须停止交付。 > **标记与字段要分开判断(前置规则第 10 条)**:上面这些**动态调用标记本身已确认可用**;但标记内部使用的 `{siteColumn.*}`、`{news.*}`、`{page.*}` 字段仍必须按同一确认规则,经目标运行时帮助页或一次真实生成结果确认后才可写入。也就是说,可以写 `...`,但不等于可以无条件在里面写 `{siteColumn.url}` 或 `{news.url}`。 #### 9.5.1 基本结构与 `codeName` ```html ... ``` `codeName` 是栏目代码,必须使用真实已存在的栏目代码。不要把栏目名称、栏目 ID 或模板页面名称误当成 `codeName`。 本节代码中的 `xinwenzixun`、`gongsidongtai`、`doc` 和 `news` 都只是示例 `codeName`,执行时必须替换为目标站点真实存在的值。当前 MCP 没有按代码查询栏目的工具,缺少该值时不得执行动态调用模板保存。 帮助页还明确支持在栏目/详情相关模板上下文中动态引用当前栏目代码: ```html ``` 只有在当前上下文本身存在有效 `siteColumn` 时才可以这样使用;不要在无栏目上下文的地方凭空使用。 #### 9.5.2 调取指定栏目名称和 URL ```html {siteColumn.name} ``` --- #### 9.5.3 调取指定栏目文章列表 动态模板注释中的 `number` 用于控制本次动态调用的文章条数;未设置时,当前帮助页说明默认显示 6 条。它不是 `save_site_column.listNum`:后者控制栏目列表页的每页条数,两个同为数量字段但属于不同对象,不能互相替代或同步推导。 ```html
    {siteColumn.name}
    ``` 在目标运行时确认动态列表字段后,`List_Start ... List_End` 内部才可使用文章信息标签。 源码与动态帮助示例表明:首页可以通过动态栏目调用尝试调取新闻/文章列表,但这不替目标运行时解决列表标签冲突;只有相关标签和循环均经确认时才可依赖该结果。 关于“轮播图”:当前资料**没有提供一个专用的“轮播图标签”**。如果设计要求轮播,可以在动态文章列表中使用已经存在的 `{news.titlepic}`、`{news.url}` 等字段,再由模板自身 HTML/CSS/JS 实现轮播效果;当前核对版本在 `titlepic` 为 `null` 时可能回退到系统默认图,空字符串的处理也需按目标版本确认。非空输出不证明素材已上传,验收时必须检查图片 URL 可访问且内容确为目标素材。AI **不得编造诸如 `{slider.xxx}`、`{banner.xxx}` 之类未在文档出现的 CMS 标签**。 --- #### 9.5.4 调取指定父栏目下的子栏目 ```html

    {siteColumn.name}

    {siteColumn.name} ``` 在目标运行时确认栏目字段后,`SubColumnList_Start ... SubColumnList_End` 内部才可使用栏目标签。 --- #### 9.5.5 调取当前网站可用于模板调用的顶级栏目 不写 `codeName`: ```html {siteColumn.name} ``` 去掉具体栏目代码后,调取当前生成上下文中可用于模板代码调用且未被禁用/隐藏的顶级栏目;不能据此假设后台所有栏目都会输出。 --- #### 9.5.6 父栏目 → 子栏目 → 每个子栏目的文章列表 ```html

    {siteColumn.name}

  • {news.title}
  • ``` 该结构说明动态栏目调用可以嵌套“子栏目循环 + 当前子栏目文章循环”。这里属于动态栏目语法自身的嵌套,**不等于模板变量 `{include=...}` 的嵌套**,不要混淆两个规则。 --- ### 9.6 首页模板 `TemplatePage.type=1` 的完整当前标签边界 根据通用标签帮助页、动态栏目调用帮助页和当前模板机制,首页的标签边界如下。表中标为“可用”的能力可直接写入;凡涉及 `{siteColumn.*}`、`{news.*}` 的字段,仍按**前置规则第 10 条**经目标运行时确认后才可写入: | 能力/标签 | 首页结论 | |---|---| | 模板变量 `{include=...}` | 可用 | | 网站全局变量 `{var.xxx}` | 可用 | | 通用标签 `{site.*}`、`{linuxTime}`、`{masterSiteUrl}`、`{templatePath}` 等 | 可用 | | 动态栏目调用 `SiteColumn_Start...End` | 标记可用;内部 `{siteColumn.*}` 字段须按前置规则第 10 条确认 | | 动态调取指定栏目文章列表 `List_Start...End` | 标记可用;内部 `{news.*}` 字段须按前置规则第 10 条确认 | | 动态调取顶级栏目/子栏目 `SubColumnList_Start...End` | 标记可用;内部 `{siteColumn.*}` 字段须按前置规则第 10 条确认 | | `{siteColumn.*}` 作为首页“当前栏目”直接使用 | 首页本身没有当前栏目上下文,不这样使用;进入动态栏目上下文且该字段已确认后才可用 | | `{news.*}` 作为首页“当前文章”直接使用 | 不可直接使用;进入动态 `List_Start...End` 且该字段已确认后才可用于当前循环文章 | | `{page.*}` 分页标签 | 不用于首页 | | 专用轮播图 CMS 标签 | 当前资料没有;不得编造 | 因此首页内容可以由三层组成: ```text 固定布局 HTML + 可后台维护的全局数据 {var.xxx} + 栏目/文章动态数据 ... ``` 例如首页调“新闻资讯”最新 6 篇(其中 `news` 是本教程示例 `codeName`,`{news.url}`、`{news.title}` 须先按前置规则第 10 条确认;不可直接提交): ```html {news.title} ``` 如果首页需要轮播,可以把动态文章列表中的 `{news.titlepic}`、`{news.url}` 等已有字段交给模板自己的 HTML/CSS/JS 组成轮播效果;这不是一个新的 CMS 轮播标签。当前核对版本在 `titlepic` 为 `null` 时可能回退到系统默认图,空字符串的处理也不能跨版本假定;因此输出非空不证明素材已上传,验收时必须检查图片 URL 可访问且内容确为目标素材。禁止编造 `{slider.*}`、`{banner.*}` 等本文档不存在的标签。 --- ### 9.7 列表页模板 `TemplatePage.type=2` 的完整标签上下文矩阵 列表页通常包含“当前栏目 + 文章列表 + 分页”,但公开列表帮助页与源码/示例对标签可用性存在冲突。 下表只是**目标运行时确认后的候选上下文**,不是跨版本保证。按**前置规则第 10 条**:表中所有“需确认”项,只有目标运行时帮助页或一次真实生成结果确认后才可写入模板;帮助资料冲突且无法确认时必须暂停,不得回退、混用或猜测。 | 上下文 | `{include=...}` | `{var.*}` | 通用标签 | `{siteColumn.*}` | `{news.*}` | `{page.*}` | 动态栏目调用 | |---|---|---|---|---|---|---|---| | 列表页普通位置 | 可用 | 可用 | 可用 | **需确认,若支持则表示当前列表栏目** | 不作为当前文章直接使用 | **需确认** | 可用 | | `TemplateListItemStart ... End` | 可用 | 可用 | 可用 | 需确认,若支持则表示当前循环文章关联栏目 | **需确认,若支持则表示当前循环文章** | 通常放循环外,仍需确认 | 可用但通常无需嵌入单项 | | `SiteColumn_Start ... End` | 可用 | 可用 | 可用 | 需确认,若支持则表示动态指定栏目 | 进入 `List_Start...End` 后才可用,需确认 | 页面分页仍属于当前列表页,不要与动态文章列表混为一套分页 | 可用 | | `SubColumnList_Start ... End` | 可用 | 可用 | 可用 | **需确认,若支持则表示当前子栏目** | 若再进入 `List_Start...End` 且目标版本支持才可用 | — | 动态调用内部 | 在目标运行时确认上述条件后,列表页最典型的结构: ```html

    {siteColumn.name}

    ``` 分页完整 11 个字段和 URL 生成规则见 9.12。 --- ### 9.8 详情页模板 `TemplatePage.type=3` 基础教程明确“关于我们”添加模板页面时选择**详情页模板**;当前 MCP 文档进一步规定关于我们等单页面通过 MCP 创建模板页面时使用 `TemplatePage.type=3`。 本教程详情示例使用以下核心标签。**WangMarket 6.1 源码已确认可用**(`replaceNewsTag()` 主动替换);目标版本不是 6.1 时按 11.1 实测确认: ```text {news.title} {news.text} ``` 详情页还有以下独有标签: | 标签 | 说明 | 类型 | |---|---|---| | `返回列表` | 上一篇文章;没有上一篇时返回列表页面 | HTML | | `制作本地静态模版` | 下一篇文章;没有下一篇时按系统规则返回列表页面 | HTML | | `ai-template.html` | 上一篇文章链接地址 | URL | | `45919.html` | 下一篇文章链接地址 | URL | | `{text}` | 历史正文标签 | 旧模板兼容行为需按目标运行时验证;新模板不使用 | 新建详情模板统一使用 `{news.text}`。只有迁移已有旧模板且目标运行时已实测支持时,才保留裸 `{text}`;不得同时插入两种正文标签,否则可能重复输出正文。 `返回列表`、`制作本地静态模版` 输出完整 ``;当前核对版本在没有相邻文章时回到栏目列表。`ai-template.html`、`45919.html` 只输出 URL。独立页面虽然也使用 `type=3` 模板,但不得把这些标签解释成"上一独立页/下一独立页"。详情页普通位置的 `{siteColumn.*}` 在 6.1 源码中由 `replaceSiteColumnTag()` 替换,已确认可用;目标版本不是 6.1 时按 11.1 确认。 #### 9.8.1 关于旧帮助页"文章信息标签不可用"的说明 **WangMarket 6.1 源码已确认**:详情页 `{news.*}` 由 `TemplateCMS.replaceNewsTag()` 主动替换,含 `{news.title}`、`{news.text}`、`{news.url}` 等全部字段。帮助页 `details.jsp` 表格中的"文章信息标签:不可用"标注为**过时/错误**,与 6.1 实际代码不符。6.1 版本可直接使用 `{news.*}`,无需运行时确认。 跨版本注意:若目标 WangMarket 版本不是 6.1,该标注可能生效,应按 11.1 做一次最小化真实生成测试确认。 --- ### 9.9 网站全局变量 `text / image / select` 全局变量统一通过: ```text {var.变量名} ``` 引用。当前 MCP 暴露的 `text`、`image`、`select` 三种类型引用语法相同,区别在后台录入方式和 `value` 的含义;这不代表所有 WangMarket 版本只存在三种类型。 #### text 示例 ```text name = qq type = text value = <用户提供的真实 QQ 群号> 模板:{var.qq} ``` #### image 示例 ```json { "authHandle": "<有效 authHandle>", "name": "logo", "title": "网站LOGO", "description": "上传网站LOGO,并在备注中写明建议尺寸和格式", "value": "<用户提供或后台已有的真实图片 URL>", "type": "image" } ``` 模板仍然写: ```html 网站LOGO ``` #### select 示例 当前 6.1 后台解析器要求 `valueItems` 每行使用: ```text 值:显示文本 ``` 例如: ```text valueItems: light:浅色 dark:深色 value = light ``` 模板: ```text {var.theme} ``` 输出的是当前保存的变量值。AI 不得把 `select` 自动解释成会生成 ``;HTML 由模板自己写 | | 11 | 独立页面模板 `type=6` 与详情页 `type=3` | `TemplatePage.TYPE_ALONEPAGE=6` 已废弃并入详情页;当前关于我们使用 `TemplatePage.type=3 + SiteColumn.type=8` | **不得再创建 TemplatePage.type=6** | | 12 | `codeName` 是否必填 | 条件必填:仅在需要动态栏目调用或目标运行时要求按代码生成时才传入;值必须是当前站点已确认存在的栏目代码;仅创建栏目且无上述需求时可按 schema 省略 | 省略后不得由 `codeName` 推导栏目 URL;`about`、`news` 仅为栏目代码格式示例,执行时必须替换为真实存在的值 | | 13 | 列表页/详情页标签适用性 | **WangMarket 6.1 源码已确认可用**:`TemplateCMS.replaceListPageTag()` 主动替换 `{siteColumn.*}` 和全部 11 个 `{page.*}`;`replaceNewsTag()` 主动替换 `{news.*}`(含 `{news.url}`);列表页循环内逐篇调用 `replaceNewsTag()`。帮助页 list.jsp/details.jsp 表格中标注的"不可用"为过时标注,与 6.1 实际代码不符 | 6.1 版本可直接使用 `{siteColumn.*}`、`{page.*}`(列表页)、`{news.*}`(详情页及列表循环内);目标版本不是 6.1 时仍须按 11.1 实测确认 | | 14 | 分页标签与列表 URL 形态 | 11 个 `{page.*}` 字段来自源码核对版本;`codeName.html` / `codeName_页码.html` 仅在 `generateUrlRule=code` 时成立 | 分页只用于列表页;`upList`/`nextList` 输出页码列表 HTML,不包成单个数字或 URL;`lc_.html` 等 ID 形态无公开契约,禁止推导 | | 15 | `{templatePath}` 尾斜杠 | **WangMarket 6.1 源码已确认末尾带斜杠**:`getTemplatePath()` = 路径前缀 + `site.templateName` + `"/"`(字节码显式 append `/`)。私有模板前缀 = `ATTACHMENT_FILE_URL + websiteTemplate/`,云模板前缀 = `//cloudtemplate.weiunity.com/websiteTemplate/`,两者本身也以 `/` 结尾 | 6.1 版本模板中统一写 `{templatePath}css/style.css`(**不加**额外斜杠);写 `{templatePath}/css/style.css` 会产生双斜杠 `//` | | 16 | `generateUrlRule` 判定逻辑 | **WangMarket 6.1 源码已确认**:默认 `"int"`;`templateCMS()` 中判定——系统属性 `MASTER_SITE_URL` 为 null 或不等于 `"http://wang.market/"` 时 → `"code"`;等于官方云地址时,`site.id > 255` 或 `site.id == 218` → `"code"`,其余老站点 → `"int"` | 自部署/非官方环境几乎一定是 `"code"`;官方云老站点(id≤255 且 ≠218)才是 `"int"`。具体值可通过部署环境或站点 ID 判定,或从已生成页面 URL 反推;MCP 无查询接口 | 以下事项仍缺少当前 MCP 的查询能力或统一运行时依据,**不得标成已解决,更不得由 AI 补全**: | 待确认事项 | 当前可执行边界 | |---|---| | 站点基础 URL(域名/访问路径) | 由用户、宿主或后台提供;MCP 无查询接口 | | 栏目、模板变量、新闻、全局变量的查询 | 当前工具集没有查询工具;缺少真实 ID/存在性时停止 | | `save_site_column.info` 为非数字文本 | 不把"成功"当 ID;停止后由后台确认,避免重复创建 | | `save_template` 的目标模板与副作用 | 调用前确认允许影响现有模板;`result=1` 后仍以生成和预览验证 | | `generate_site` 之后文件的可访问性 | `result=1` 只表示调用完成;必须用真实 URL 做 HTTP 与内容验收;404/超时且无轮询工具时停止等待后台确认,不无限重试、不猜 URL | | 独立页面内容的"当前站点唯一" | 属实现边界(底层按 `cid` 查询 News 且未显式带 `siteid`);不得无条件承诺,必须后台确认后再更新 | | 独立页面内容记录未自动创建时的回退 | `save_alone_page_content` 只查询不创建,当前 MCP 无替代工具;必须由人工在后台"内容管理"手动添加一条后 AI 才能更新;在此之前关于我们页面无内容来源(见 5.3) | | `News.htmlName` 在当前 6.1 生成器中的效果 | 不用它推导详情 URL | | `editMode=1` 的完整可视化协议 | 当前 MCP 不使用,统一显式传 `TemplatePage.editMode=2` | | 非 6.1 版本的标签适用性、`valueItems`、日期补零、模板变量嵌套等细节 | 目标版本不是 6.1 时按 11.1-11.9 实测确认;6.1 版本以上述已确认表为准 | --- ## 11. 运行时确认操作指南 本章针对第 10 章「仍需确认的执行边界」中列出的事项,给出**具体的确认方法和操作步骤**。AI 不得自行决定这些技术参数,但可以按本章指引从目标运行时、后台或用户处取得确认依据。确认结果应记录版本号和证据,后续执行时引用。 ### 11.1 列表/详情页标签适用性(6.1 已确认) **WangMarket 6.1 结论**:`{siteColumn.*}`、`{news.*}`、`{page.*}` 在列表页和详情页**均可用**,源码中有对应的替换方法并被生成流程实际调用: - `replaceListPageTag()` → 替换 `{siteColumn.*}` 和全部 11 个 `{page.*}` - `replaceNewsTag()` → 替换 `{news.*}`(含 `{news.url}`),列表页循环内逐篇调用 帮助页 `list.jsp`/`details.jsp` 表格中标注的"不可用"为**过时标注**,与 6.1 实际代码不符。6.1 版本可直接使用这些标签,无需运行时测试。 **跨版本注意**:若目标 WangMarket 版本不是 6.1,仍须做一次最小化真实生成测试确认: 1. 在列表模板中写入 `{siteColumn.name}`、`{news.title}`、`{page.firstPage}`; 2. 在详情模板中写入 `{news.title}`、`{news.text}`; 3. 调用 `generate_site` 后查看源码,标签原样残留则该版本不支持。 ### 11.2 站点基础 URL 与 `generateUrlRule`(6.1 判定逻辑已确认) **WangMarket 6.1 源码已确认 `generateUrlRule` 判定逻辑**(`TemplateCMS.templateCMS()`): | 部署环境 | 判定条件 | generateUrlRule | |---|---|---| | 自部署/非官方 | `MASTER_SITE_URL` 系统属性为 null,或不等于 `"http://wang.market/"` | `"code"` | | 官方云(wang.market) | `site.id > 255` 或 `site.id == 218` | `"code"` | | 官方云(wang.market) | `site.id ≤ 255` 且 `site.id ≠ 218`(老站点) | `"int"`(默认值) | **实际操作**: 1. **自部署环境**:可直接判定为 `code` 规则,列表页 URL = `codeName.html`,独立页面 URL = `codeName.html`,新闻详情 URL = `News.id.html`。 2. **官方云/不确定环境**: - 从用户/宿主取得站点 ID,按上表判定;或 - 后台查看站点设置;或 - 从已生成页面 URL 反推:`news.html`/`news_2.html` → `code`;`lc1001_1.html`/`451.html` → `int`。 3. **站点基础 URL(域名/访问路径)**:仍须由用户、宿主或后台提供,MCP 无查询接口。 4. **独立页面(type=8)的 URL**:`code` 规则下 = `codeName.html`(源码 `generateNewsPageHtmlName()` 已确认);`int` 规则下须由后台确认,不得推导(见 9.12.1)。 ### 11.3 栏目/模板变量/新闻的已有状态与真实 ID 确认 **待确认内容**:目标站点是否已存在同名栏目、模板变量、模板页面或新闻,以及它们的真实 ID。 **确认方法**: 1. **后台查看**: - 栏目:后台「栏目管理」列表,记录栏目名称、ID、`codeName`、类型; - 模板变量:后台「模板管理 → 模板变量」,记录 `varName` 和 ID; - 模板页面:后台「模板管理 → 模板页面」,记录 `name`、`type` 和 ID; - 新闻:后台「内容管理」,按栏目筛选,记录文章 ID。 2. **从本次会话上下文取得**:若前面的工具调用已返回 `info` 中的正整数 ID,直接使用该值。 3. **当前 MCP 限制**:没有按名称/代码查询的工具,缺少 ID 时必须停止并请求后台确认,不得猜测或用 `id=0` 假装更新。 ### 11.4 `save_template` 目标模板与副作用确认 **待确认内容**:当前站点 `site.template_id` 是否指向有效模板;调用 `save_template` 是否会修改已有模板。 **确认方法**: 1. **后台查看模板绑定**:在后台「模板管理」中查看当前站点是否已选择/导入模板,以及模板名称。 2. **评估副作用**:`save_template` 的实现可能在 `template_id` 无效时使用 ID 1,可能创建或修改既有模板。调用前必须由用户确认允许该操作影响现有模板。 3. **调用后验证**:`result=1` 后仍需后台复核绑定状态,并执行 `generate_site` + 真实 URL 验收,不能仅凭返回值宣称绑定成功。 ### 11.5 `save_site_column.info` 非数字文本的落库状态确认 **待确认内容**:`result=1` 但 `info` 返回 `"成功"` 等非数字文本时,栏目是否实际落库、ID 是多少。 **确认方法**: 1. **停止后续写入**,不要重复调用 `save_site_column`(可能创建重复栏目)。 2. **后台栏目管理**:按栏目名称和创建时间找到刚创建的栏目,记录其真实 ID。 3. **若存在多个同名栏目**:通过绑定的模板页面名称(`templatePageListName` / `templatePageViewName`)和创建时间区分,确认哪一个是本次创建的。 4. **使用后台确认的真实 ID** 继续后续 `save_news` / `save_alone_page_content`。 ### 11.6 `{templatePath}` 前缀尾斜杠(6.1 已确认) **WangMarket 6.1 源码已确认**:`{templatePath}` 输出**末尾一定带斜杠 `/`**。 `getTemplatePath()` 实现:路径前缀 + `site.templateName` + `"/"`(字节码显式 append `/`)。路径前缀本身也以 `/` 结尾: - 私有模板:`ATTACHMENT_FILE_URL` + `websiteTemplate/` - 云模板:`//cloudtemplate.weiunity.com/websiteTemplate/` **6.1 版本确定写法**:模板中统一写 `{templatePath}css/style.css`(**不加**额外斜杠)。 **禁止写法**:`{templatePath}/css/style.css` 会产生双斜杠 `//`(如 `https://example.com/template/default//css/style.css`),部分浏览器/CDN 可能无法正确解析。 **跨版本注意**:目标版本不是 6.1 时,生成一次后查看实际 `href` 确认;确认后整份模板统一一种写法。 ### 11.7 `generate_site` 后静态文件可访问性确认 **待确认内容**:`generate_site` 返回 `result=1` 后,静态文件是否真实可访问。 **确认方法**: 1. **使用真实 URL 做 HTTP 验收**:用浏览器或 `curl` 访问首页、列表页、详情页,检查 HTTP 状态码。 2. **检查内容**:页面中文正常、无未解析标签、无残留动态标记、CSS/JS/图片可加载。 3. **404/超时处理**: - 不要无限重试 `generate_site`; - 检查宿主 Web 服务器根目录配置、CDN 缓存; - 后台文件管理中确认静态文件是否实际生成及文件名; - 无轮询工具时停止并等待后台确认。 ### 11.8 独立页面内容唯一性与存在性确认 **待确认内容**:`save_alone_page_content` 按 `cid` 查询的 News 记录在当前站点下是否存在且唯一。 **确认方法**: 1. **后台内容管理**:进入该独立页面栏目,首先确认是否存在内容记录。 - **若不存在任何内容记录**:当前 MCP 无法创建(`save_alone_page_content` 只查询不创建,`save_news` 不适用于 type=8),必须由人工在后台"内容管理"中为该栏目手动添加一条内容,之后 AI 才能用 `save_alone_page_content` 更新。在此之前不得宣称关于我们页面已完成。 - **若存在且仅有一条**:继续下一步。 2. **若存在多条同 `cid` 记录**:底层查询目标不确定,必须停止,由后台清理重复数据后再执行 `save_alone_page_content`。 3. **实现边界说明**:底层查询未显式带 `siteid` 条件,跨站数据可能干扰;不得无条件承诺「当前站点唯一」。 ### 11.9 非 6.1 版本的 `valueItems`、日期格式与嵌套行为确认 **待确认内容**:目标 WangMarket 版本不是已核对的 6.1 时,`select` 类型全局变量的 `valueItems` 格式、`{news.addtime.month}` 是否补前导零、模板变量非循环嵌套是否生效。 **确认方法**: 1. **确认版本号**:在后台关于页面或页脚查看 WangMarket 版本号。 2. **`valueItems` 格式**:在后台创建一个 `select` 类型全局变量,保存后查看选项是否正确解析;若 `值:显示文本` 格式不生效,尝试后台文档说明的格式。 3. **日期格式**:在详情模板中写入 `{news.addtime.month}`,生成后查看输出是 `3` 还是 `03`;需要固定两位时由模板前端 JS 格式化,不依赖 CMS 输出。 4. **模板变量嵌套**:创建变量 A 引用变量 B,生成后查看是否展开;若不生效,改为在模板页面中分别直接引用。 ### 11.10 `News.htmlName` 对详情 URL 的影响确认 **待确认内容**:`save_alone_page_content` 的 `htmlName` 参数是否影响当前生成器的详情页 URL。 **确认方法**: 1. **创建测试内容**时设置 `htmlName=test-page`,生成后查看详情页实际 URL。 2. **若 URL 未使用 `test-page.html`**:说明当前版本生成器不采用 `htmlName`,不得用它推导预览 URL。 3. **统一规则**:详情页 URL 始终使用真实生成结果或后台确认的地址,不得由 `htmlName`、`News.id` 或 `codeName` 推导。 ### 11.11 确认结果记录模板 每次完成上述确认后,应按以下格式记录,供后续执行引用: ```text 确认项:<对应 11.1-11.10 的编号> 目标运行时版本:<版本号> 确认方法:<帮助页 / 真实生成 / 后台查看> 确认结果:<可用 / 不可用 / 具体参数值> 证据:<帮助页截图描述 / 生成页面 URL / 后台路径> 确认时间: ``` 未完成确认的事项,在执行时必须按第 10 章的「当前可执行边界」停止并报告,不得跳过。 --- ## 常见问题与避坑指南 在实际操作过程中,以下常见问题容易导致生成失败或页面显示异常,在此特别说明,避免后续踩坑。 ### 问题1:后台点击「生成整站」提示"当前网站尚未选择/导入/增加模版,生成失败!" #### 现象描述 在网站管理后台左侧菜单点击「生成整站」按钮时,弹出错误提示: ``` 当前网站尚未选择/导入/增加模版,生成失败!网站有模版后才能根据模版生成整站! ``` 但奇怪的是,已经创建了模板页面(index、about、news)和模板变量(nav、footer),为什么还提示没有模板? #### 原因分析 网市场系统的模板体系分为两层: | 层级 | 数据表 | 说明 | |---|---|---| | 模板(Template) | `template` | 模板的基本信息,一个模板包含多个模板页面 | | 模板页面(TemplatePage) | `template_page` + `template_page_data` | 具体的页面模板(首页、列表页、详情页) | 网站表 `site` 中有一个字段 `template_id`,指向 `template` 表中的模板记录。 后台「生成整站」按钮在执行生成前,会校验: ```text site.template_id → template 表中是否存在对应记录 ``` 如果 `template` 表为空,或者 `site.template_id` 指向了一个不存在的模板 ID,校验就会失败,提示"当前网站尚未选择/导入/增加模版"。 而通过 MCP 接口 `generate_site`(对应上游接口 `/template/refreshForTemplate.do`)生成时,可能不执行同一项绑定校验,因此“生成调用返回成功”和“后台模板绑定有效”必须分别验证。 #### 解决方案 **方案一:在确认允许影响当前模板后调用 `save_template`** 本文档已新增 MCP 工具 `save_template`,对应上游接口: ```text POST /plugin/adminapi/site/saveTemplate.json ``` 当前实现的真实边界: 1. 读取当前网站的 `site.template_id`;为空或不大于 0 时把候选 ID 设为 `1`。 2. 候选 ID 不存在时,尝试按该 ID 新建模板记录,并把网站指向它。 3. 候选 ID 已存在时,不会重新绑定到其它模板;传入非默认名称或非空备注还可能修改该既有模板。 4. 若网站原本没有有效 `template_id` 而模板 ID 1 已存在,当前代码可能返回成功但没有把网站重新绑定到 1。 5. 接口没有验证新建/既有模板是否与已创建的模板页面正确归属,也不能保证后台按钮随后一定成功。 因此调用前必须由用户或后台确认允许该操作影响现有模板。无法确认当前绑定状态时,不得把此工具描述为无副作用的“确保绑定”。为降低误改风险,默认只传 `authHandle`;只有用户明确要求修改模板名称/备注时才传对应字段。 调用示例: ```json { "authHandle": "" } ``` 参数说明: | 参数 | 是否必填 | 类型 | 说明 | |---|---|---|---| | `authHandle` | 是 | string | `login` 成功返回的认证句柄 | | `name` | 否 | string | 模板名称,默认"自定义模板" | | `remark` | 否 | string | 模板备注,默认空字符串 | 返回示例: ```json { "result": 1, "info": "1" } ``` 其中 `info = "1"` 只是示例模板 ID。`result=1` 只表示本接口完成,不能宣称绑定、后台生成或预览已成功;仍须执行本节验证方法。 **方案二:由获授权的数据库管理员修复** 数据库写入不属于本文 MCP/AI 自动建站流程。只有获授权管理员在确认目标站点 ID、当前用户、目标模板 ID、数据归属并完成备份后,才能按实际数据库版本修复;不得把示例 ID `1` 当成固定值,也不得让 AI 执行未经限定站点的 `INSERT` 或 `UPDATE`。 #### 验证方法 依次验证:后台确认目标站点指向预期模板;后台「生成整站」不再出现该错误;`generate_site` 返回 `result=1`;最后用真实站点 URL 检查首页、列表页和详情页。四项都通过后才算解决。 --- ### 问题2:生成的网站中文乱码(UTF-8 编码问题) #### 现象描述 生成整站后,访问生成的静态 HTML 页面,中文显示为乱码(如"棣栭〉"、"鏂伴椈鍒楄〃"等),但英文和数字显示正常。 查看生成的 HTML 文件源码,发现文件中没有 `` 标签。 #### 原因分析 在创建模板页面时,如果只保留了 body 内部的内容,例如: ```html {include=nav}

    hi,这是首页

    {include=footer} ``` 而**没有保留完整的 HTML 文档结构**(缺少 ``、``、``、``、`` 等标签),那么系统生成静态 HTML 时,会直接将模板内容输出到文件中,不会自动添加 `` 和编码声明。 浏览器在解析没有编码声明的 HTML 文件时,会使用系统默认编码(在中文 Windows 上通常是 GBK/GB2312),而文件实际是 UTF-8 编码保存的,编码不匹配就会导致中文乱码。 #### 解决方案 **在创建/修改模板页面时,必须保留完整的 HTML 文档结构,包含 ``。** 正确的首页模板示例: ```html 首页 - 网站名称 {include=nav}

    hi,这是首页

    网站介绍内容...
    {include=footer} ``` 正确的详情页(关于我们)模板示例: ```html {news.title} - 网站名称 {include=nav}

    {news.title}

    {news.text}
    {include=footer} ``` 正确的列表页(新闻列表)模板示例: ```html 新闻列表 - 网站名称 {include=nav}

    新闻列表

    {include=footer} ``` #### 如果已有模板缺少编码声明,如何修复? 先从后台取得当前模板页面的完整源码,整理成**唯一一套** `doctype/html/head/body` 结构并保留原正文,再通过后台或 `save_template_page_text` 整体覆盖。不要在未知原文前后盲目追加标签,否则可能生成嵌套或重复的 ``、``、``。当前 MCP 没有读取模板页面源码的工具;若手头没有可信的完整原文,必须停止并要求后台导出,不能凭空重建后覆盖。 保存后重新生成整站,并用真实 URL 检查响应内容与浏览器显示。 #### 验证方法 生成整站后,查看生成的 HTML 文件源码,确认文件开头包含: ```html ``` 在浏览器中打开页面,中文应正常显示,不再出现乱码。 --- ### 问题3:`save_site_column` 返回 `result=1` 但 `info` 是"成功"等非数字文本 #### 现象描述 调用 `save_site_column` 创建栏目后,返回: ```json { "result": 1, "info": "成功" } ``` `info` 不是数字,无法取得栏目 ID,后续 `save_news` 或 `save_alone_page_content` 的 `cid` 参数无法填写。 #### 原因分析 不同版本的 WangMarket 上游接口在 `save_site_column` 成功时,`info` 字段的返回值不一致: - 部分版本返回栏目 ID(如 `"789"`); - 部分版本返回固定成功文本(如 `"成功"`)。 当前 MCP 没有栏目查询工具,无法通过 `codeName` 或栏目名称反查 ID。 #### 解决方案 1. **停止后续写入操作**,不要猜测栏目 ID,也不要用 `codeName`、栏目名称或模板页面 ID 代替 `cid`。 2. **进入后台确认**:在后台「栏目管理」中找到刚创建的栏目,记录其真实 ID。 3. **使用后台确认的真实 ID** 继续调用 `save_news` 或 `save_alone_page_content`。 4. 若后台中存在多个同名栏目,必须确认哪一个是本次创建的(可通过创建时间、绑定的模板页面名称区分),避免更新错误栏目。 5. 不要因为 `result=1` 就重复调用 `save_site_column`,否则可能创建重复栏目。 #### 验证方法 后台栏目列表中能看到本次创建的栏目;使用后台确认的真实 ID 调用后续工具返回 `result=1`;生成后页面内容属于目标栏目。 --- ### 问题4:页面中 `{include=nav}`、`{var.qq}`、`{news.title}` 等标签没有被解析,原样显示在生成的 HTML 中 #### 现象描述 生成整站后,查看页面源码,发现 `{include=nav}`、`{var.qq}`、`{news.title}`、`{siteColumn.name}` 等花括号标签没有被替换,原样出现在 HTML 中。 #### 原因分析 按标签类型分别排查: | 标签类型 | 常见原因 | |---|---| | `{include=xxx}` | 模板变量不存在、`varName` 拼写不一致、变量 `text` 为空、保存变量在保存页面之后 | | `{var.xxx}` | 全局变量不存在、变量名拼写不一致、变量未设置 `value` | | `{news.*}` / `{siteColumn.*}` / `{page.*}` | 当前页面没有对应上下文(如首页直接写 `{news.title}`)、目标运行时不支持该标签、标签在错误的循环位置使用 | | 动态标记 `` 等 | 标记拼写错误(区分大小写)、`codeName` 不存在、标记未正确闭合 | #### 解决方案 1. **`{include=xxx}` 未解析**: - 确认模板变量已通过 `save_template_var` 创建且 `result=1`; - 确认页面中 `{include=nav}` 的 `nav` 与 `save_template_var.varName` 完全一致(大小写敏感); - 确认变量 `text` 不为空; - 确认创建变量在保存页面 HTML 之前执行(见 2.2.5 顺序规则)。 2. **`{var.xxx}` 未解析**: - 确认全局变量已通过 `save_site_var` 创建; - 确认变量名与 `{var.qq}` 中的 `qq` 完全一致; - 确认变量已设置 `value`。 3. **`{news.*}` / `{siteColumn.*}` / `{page.*}` 未解析**: - 按前置规则第 10 条,先确认目标运行时是否支持该标签及上下文; - 确认标签使用在正确的上下文中:`{news.*}` 必须在详情页或文章循环内,`{page.*}` 仅用于列表页,首页不能直接写 `{news.title}`; - 确认动态标记 `` / `` 等拼写正确且已闭合。 4. **动态标记残留**: - 检查标记是否精确匹配(区分大小写,无多余空格):``、``、``、``、``、``、``、``; - 确认 `codeName` 指向的栏目真实存在且已启用。 #### 验证方法 重新生成整站后,页面源码中不再出现未解析的花括号标签和动态标记;页面内容正确显示为后台数据。 --- ### 问题5:`generate_site` 返回 `result=1` 但访问页面 404 或超时 #### 现象描述 `generate_site` 返回 `result=1`,但使用预期 URL 访问页面时返回 404 或连接超时。 #### 原因分析 `result=1` 只表示生成调用已完成,不代表: - 静态文件已写入到可访问的目录; - 宿主 Web 服务器已配置正确的站点根目录; - 预期 URL 与实际生成的文件名一致; - 生成过程中没有静默跳过某些页面。 常见具体原因: 1. **URL 猜测错误**:由 `codeName` 或栏目 ID 拼接的 URL 与实际 `generateUrlRule` 不符; 2. **宿主环境延迟**:静态文件生成后,CDN 或 Web 服务器需要时间刷新; 3. **站点未绑定有效模板**:见问题1; 4. **栏目未启用或 `useGenerateView=0`**:详情页不会生成。 #### 解决方案 1. **不要无限重试 `generate_site`**,也不要猜测 URL。记录真实的 404/超时错误信息。 2. **确认真实站点基础 URL**:从用户、宿主或后台取得,不要由 `codeName` 或 ID 推导。 3. **确认 `generateUrlRule`**:只有后台确认使用 `code` 规则时,`codeName.html` 才可能成立;其它规则可能使用栏目 ID 路径。 4. **确认栏目状态**:栏目 `used=1`、信息列表栏目 `useGenerateView=1`(需要详情页时)。 5. **后台确认生成结果**:在后台文件管理或 FTP 中查看静态文件是否实际生成、文件名是什么。 6. 若宿主有轮询或生成状态查询工具,使用它确认生成完成;没有则等待后台确认。 #### 验证方法 使用后台确认的真实 URL 访问,返回 HTTP 200;页面内容正确;中文正常;无未解析标签。 --- ### 问题6:更新已有模板变量/栏目时,应该传 `id` 还是省略? #### 现象描述 需要修改已存在的 `nav` 模板变量或已创建的栏目,不确定是否应该传 `id` 参数。 #### 原因分析 `save_template_var`、`save_template_page`、`save_site_column` 的 `id` 参数行为一致: - `id` 省略、`null` 或 `0` → **创建新对象**,不会按名称覆盖已有对象; - `id > 0` → **更新已有对象**。 如果省略 `id` 去"更新"已有变量,实际会创建一个同名新变量,导致重复。 #### 解决方案 按文末闭环开头的**创建/更新判定规则**执行: | 情况 | 处理方式 | |---|---| | 已存在,且有已确认的真实 ID | **更新**:显式传入该真实 ID | | 已确认不存在 | **创建**:省略 `id`,或传 `0` / `null` | | 状态不明,或没有真实 ID | **停止**:由后台确认,不得猜 ID、不得重复创建 | 具体操作: 1. 从本次会话前面的工具返回结果中查找 `info` 字段中的真实 ID; 2. 若上下文中没有,进入后台确认对象 ID; 3. 当前 MCP 没有按名称查询模板变量/栏目/新闻的工具,不能用 `varName`、`name` 或 `codeName` 代替 ID。 #### 验证方法 更新后后台只有一个目标对象(无重复);对象内容为更新后的值;生成页面反映更新内容。 --- ### 问题7:`{templatePath}` 生成的 CSS/JS/图片路径出现双斜杠 `//` #### 现象描述 生成页面后,查看资源引用,发现路径如 `https://example.com/template//css/style.css`,中间有双斜杠。 #### 原因分析 **WangMarket 6.1 源码已确认**:`{templatePath}` 输出末尾**一定带斜杠 `/`**(`getTemplatePath()` = 路径前缀 + templateName + `"/"`)。如果模板中写 `{templatePath}/css/style.css`,变量本身已带 `/`,就会生成 `//`。 #### 解决方案 1. **6.1 版本确定写法**:模板中统一写 `{templatePath}css/style.css`(**不加**额外斜杠); 2. **不要把双斜杠当作通用可接受行为**,部分浏览器/CDN 可能无法正确解析; 3. 修改后重新生成整站,检查所有资源引用。 #### 验证方法 生成页面中所有 `{templatePath}` 引用的资源路径无重复斜杠;CSS/JS/图片均可正常加载(HTTP 200)。 > **跨版本注意**:目标版本不是 6.1 时,生成一次后查看实际 `href` 确认前缀是否带斜杠,再统一写法。 --- ### 问题8:`save_alone_page_content` 返回内容不存在或栏目下没有内容记录 #### 现象描述 创建"关于我们"独立页面栏目(`type=8`、`editMode=0`)后,调用 `save_alone_page_content` 更新内容时返回 `result=0`,`info` 提示未找到内容记录;或在后台"内容管理"中进入该栏目发现没有任何内容。 #### 原因分析 `save_alone_page_content` 底层先执行 `SELECT * FROM news WHERE cid = ?`,查询为空时立即返回错误,**不会创建内容记录**。虽然创建 `type=8` 栏目时系统可能尝试自动生成一条内容,但这不是保证行为——部分版本、部分数据状态下可能未生成。 当前 MCP 工具集中没有"按栏目创建独立页面内容"的替代工具: - `save_news` 仅用于 `type=7` 信息列表栏目,不适用于 `type=8` 独立页面; - `save_alone_page_content` 只更新不创建。 #### 解决方案 1. **停止 MCP 操作**,不要重试 `save_alone_page_content`(不会因为重试而创建内容),也不要改用 `save_news`(栏目类型不匹配)。 2. **由人工在后台"内容管理"中为该栏目手动添加一条内容**:进入内容管理 → 选择"关于我们"栏目 → 添加内容 → 填写标题和正文 → 保存。 3. 后台确认内容已存在且唯一后,AI 再使用 `save_alone_page_content(cid=栏目ID)` 更新该内容。 4. 在此之前,关于我们页面的 `{news.title}`/`{news.text}` 无数据来源,**不得宣称该页面已完成**。 #### 验证方法 后台内容管理中该栏目下有且仅有一条内容记录;`save_alone_page_content` 返回 `result=1`;`generate_site` 后关于我们页面正确显示标题和正文。 --- ## AI 自动执行的唯一闭环 > **能力边界声明**:本节是 MCP 工具集支持范围内的唯一执行顺序,但**不构成"AI 全自动闭环"**。当前 MCP 缺少站点 URL/生成结果查询工具和独立页面内容创建工具,因此以下步骤中,真实页面 URL 必须由用户、宿主或后台外部提供;独立页面内容记录若未自动创建,必须由人工在后台添加后 AI 才能更新。缺少这些外部输入时,流程必须在对应步骤暂停并报告缺口,不得猜测或降级。 本节是全文的最终顺序;前文各章用于准备参数和 HTML,不得另行拼接出不同流程。示例 `index`、`about`、`news`、`newsView` 可以按需求改名,但同一对象在创建、保存和绑定处必须一致。 > **创建 / 更新判定规则(适用于每一个对象:模板变量、模板页面、栏目、新闻)** > > 执行前先对对象做三选一判定,再决定怎么调用: > > | 判定结果 | 处理方式 | > |---|---| > | 已存在,且有已确认的真实 ID | **更新**:显式传入该真实 ID | > | 已确认不存在 | **创建**:省略 `id`,或传 `0` / `null` | > | 状态不明,或没有真实 ID | **停止**:由后台确认,不得猜 ID、不得重复创建、不得用 `id=0` 假装更新 | > > 三条容易出错的边界: > > - `save_template_var` 的 `id` 省略、`null` 或 `0` 一律按**新建**处理,**不会按 `varName` 覆盖已有变量**;已有同名变量必须先取得真实 ID。 > - `save_template_page`、`save_site_column` 同理:已存在时必须用已确认的真实 ID 更新;确认不存在时才省略 ID 或传 `0`。 > - `save_news` 更新时必须**同时**提供真实 `News.id` 和真实 `cid`。 1. **准备并校验输入**:确认目标站点、运行时工具 schema、**本次要走哪些业务分支**(首页 / 独立页面 / 信息列表并启用详情)、每个对象的创建或更新状态与真实 ID、完整 HTML、文案、真实图片 URL、允许的模板绑定方案,以及真实站点基础 URL。需要更新的对象必须有真实 ID;需要自定义输入模型、栏目代码或图片 URL 时必须有后台依据。任一缺失即停止,不开始写入。 2. **登录**:调用 `login`。仅 `result=1` 且返回非空真实 `authHandle` 时继续,后续每个业务工具均原样传入它。 3. **先保存被引用的数据**:模板若使用 `{var.xxx}`,先用 `save_site_var` 创建完整定义;只改已确认存在的值才用 `save_site_var_value`。然后按本节开头的**创建/更新判定规则**处理 `nav`、`footer` 模板变量——已存在且有真实 ID 就按 ID 更新,已确认不存在才创建,不明则停止,并保存真实变量 ID。若真实导航 URL 尚未取得,可先保存不含猜测链接的最小导航,待第 8 步取得 URL 后按真实 ID 更新。 4. **按业务分支创建并保存模板页面**:先按第 1 步确定的分支列出本轮真正需要的页面,再对每个页面调用 `save_template_page(editMode=2)`,成功后**立即用相同名称**调用 `save_template_page_text` 保存完整 HTML。只有元数据和 HTML 两次调用都成功才算就绪;返回的页面 ID 不传给 `pageName`。 - **首页分支** → 需要 `index`(`TemplatePage.type=1`); - **独立页面分支** → 需要 `about` 等 `type=3` 页面; - **信息列表分支** → 需要 `news`(`type=2`);**只有启用详情生成(`useGenerateView=1`)时**才还需要 `newsView`(`type=3`)。 未选择的分支不创建、不绑定、不在第 10 步虚构预览页面;页面已存在时按判定规则用真实 ID 更新。 5. **处理模板绑定**:若后台已确认当前网站绑定有效模板,不调用 `save_template`。若尚未绑定,只有用户已授权其潜在副作用时才调用;`result=1` 后仍须后台复核绑定。未授权或无法确认时停止,不能宣称已确保绑定。 6. **创建或更新关于我们业务数据**(仅当选择独立页面分支时执行):按判定规则处理后,用 `save_site_column(type=8, templatePageViewName=about, editMode=0)` 写入栏目。只有 `result=1` 且 `info` 可严格解析为已确认属于当前站点的大于 0 的真实栏目 ID 时,才把它传给 `save_alone_page_content.cid`;`info` 为 `成功`、空值或其它非数字文本时停止并由后台确认。调用前还必须按 5.3 确认系统已创建且唯一的目标内容;存在多条同 `cid` 历史记录时停止。**若后台确认该栏目下没有内容记录,当前 MCP 无法创建——必须由人工在后台"内容管理"中手动添加一条后,才能继续 `save_alone_page_content`;在此之前不得宣称关于我们页面已完成。** 7. **创建或更新新闻业务数据**(仅当选择信息列表分支时执行):确认 `news`(启用详情生成时还包括 `newsView`)均已完整保存后,按判定规则处理栏目,再用 `save_site_column(type=7, templatePageListName=news, templatePageViewName=newsView)` 写入,并显式传本流程需要的编辑字段;更新已存在栏目时必须使用已确认的真实 ID。仍仅接受可确认的正整数栏目 ID,然后把该真实 ID 作为 `save_news.cid`。**更新新闻时必须同时提供真实 `News.id` 和真实 `cid`**。 8. **预生成并补齐真实导航**:先调用一次 `generate_site` 使本轮页面落库(`result=1` 仅表示调用完成,不返回任何 URL)。**当前 MCP 没有站点 URL、栏目或生成结果查询工具**,预生成后 AI 仍不能从返回值取得页面地址——必须由用户、宿主或后台提供本轮实际页面的真实 URL(首页、独立页面、列表页;启用详情生成时还需至少一篇详情页)。未知 `generateUrlRule` 时不得由 `codeName` 或栏目 ID 拼接。取得全部 URL 后,使用第 3 步保存的真实 `nav` 模板变量 ID 更新完整导航。缺少 nav ID 或任一页面 URL 时,保留第 3 步的最小导航并报告缺口,不得猜测 URL 或用 `about.html`/`news.html` 等示例路径充数。 9. **最终生成**:导航更新后再次调用 `generate_site`,使导航变更反映到静态页面。`result=1` **只表示生成调用已完成**,不等于静态文件已可访问或内容正确。必须按宿主提供的真实 URL 做一次 HTTP 与内容验收;若出现 404、超时且没有官方轮询/查询工具,**不得无限重试生成、不得猜 URL**,应记录真实错误并停止等待后台确认。 10. **真实预览验收**:使用可信 URL 分别访问**本轮实际选择的分支**生成的页面——首页分支访问首页;独立页面分支访问该独立页面;信息列表分支访问列表页;启用详情生成时再访问至少一篇详情页。**未选择的业务分支不创建、不绑定、也不虚构预览页面。** 全部满足以下条件才算建站成功:HTTP 响应可访问;UTF-8 中文正常;页面结构、导航、分页、详情链接及模板实际引用的图片/资源可用(题图/轮播必须确认是用户提供的真实素材,不能只凭 `titlepic` 非空);内容属于目标站点;源码中没有未解析的 `{include=...}`、`{var.*}`、`{news.*}`、`{siteColumn.*}`、`{page.*}`,也没有残留的精确动态标记 ``、``、``、``、``、``、`` 或 ``。 全局失败规则:先判断 MCP/传输错误,再判断业务 `result`。`result=0`、`mcpError`、`isError=true` 或验收失败时停止当前依赖链并报告真实错误;`result=2` 时重新登录,只重试刚失败的一步。超时、断线或其它无法判断写入是否落库的情况禁止盲目重试创建/覆盖操作,必须先由后台确认实际状态,否则可能产生重复对象或覆盖正确内容。 当前 MCP 没有站点 URL规则、栏目、模板页面、模板变量、新闻、输入模型、全局变量或上传结果的通用查询工具。缺少真实上下文时,结论只能是“需要后台确认或补充查询接口”,不能借用其它 CMS 经验、示例值、名称、`codeName`、URL 数字或历史默认值进行推断。
    ;不得同时插入两种正文标签,否则可能重复输出正文。

    返回列表制作本地静态模版 输出完整 <a>;当前核对版本在没有相邻文章时回到栏目列表。ai-template.html45919.html 只输出 URL。独立页面虽然也使用 type=3 模板,但不得把这些标签解释成”上一独立页/下一独立页”。详情页普通位置的 {siteColumn.*} 在 6.1 源码中由 replaceSiteColumnTag() 替换,已确认可用;目标版本不是 6.1 时按 11.1 确认。

    9.8.1 关于旧帮助页”文章信息标签不可用”的说明

    WangMarket 6.1 源码已确认:详情页 {news.*}TemplateCMS.replaceNewsTag() 主动替换,含 {news.title}{news.text}{news.url} 等全部字段。帮助页 details.jsp 表格中的”文章信息标签:不可用”标注为过时/错误,与 6.1 实际代码不符。6.1 版本可直接使用 {news.*},无需运行时确认。

    跨版本注意:若目标 WangMarket 版本不是 6.1,该标注可能生效,应按 11.1 做一次最小化真实生成测试确认。


    9.9 网站全局变量 text / image / select

    全局变量统一通过:

    1. {var.变量名}

    引用。当前 MCP 暴露的 textimageselect 三种类型引用语法相同,区别在后台录入方式和 value 的含义;这不代表所有 WangMarket 版本只存在三种类型。

    text 示例

    1. name = qq
    2. type = text
    3. value = <用户提供的真实 QQ 群号>
    4. 模板:{var.qq}

    image 示例

    1. {
    2. "authHandle": "<有效 authHandle>",
    3. "name": "logo",
    4. "title": "网站LOGO",
    5. "description": "上传网站LOGO,并在备注中写明建议尺寸和格式",
    6. "value": "<用户提供或后台已有的真实图片 URL>",
    7. "type": "image"
    8. }

    模板仍然写:

    1. <img src="{var.logo}" alt="网站LOGO">

    select 示例

    当前 6.1 后台解析器要求 valueItems 每行使用:

    1. 值:显示文本

    例如:

    1. valueItems:
    2. light:浅色
    3. dark:深色
    4. value = light

    模板:

    1. {var.theme}

    输出的是当前保存的变量值。AI 不得把 select 自动解释成会生成 <select> HTML;它只是后台的录入类型,模板端仍然通过 {var.xxx} 读取当前值。


    9.10 TemplatePage.editModeSiteColumn.editMode 必须分开

    这是两个完全不同的数据对象和枚举,禁止因为字段同名而混用。

    9.10.1 TemplatePage.editMode

    1. 1 = 智能 / 可视化模式
    2. 2 = 代码模式

    父级源码已经把可视化模式标记为“即将废弃,不建议用”。当前 TemplateController 只确认以下行为:

    当前工程没有找到完整的 htmledit.js DOM/API 规范,也没有完整定义:

    1. 可编辑区域标记标准
    2. 图片上传返回结构
    3. 元素选择规则
    4. 禁止编辑区域约定
    5. 可视化保存兼容 HTML 规范

    因此这项问题的最终执行结论是:

    1. AI / MCP 创建 TemplatePage
    2. 默认并显式使用 editMode = 2
    3. 不主动使用 editMode = 1

    “没有完整可视化协议”不再是需要 AI 自己补齐的缺口,而是禁止 AI 使用该模式的依据。除非以后官方重新提供完整规范,否则不得臆造 DOM 标记或上传协议。

    9.10.2 SiteColumn.editMode

    1. 0 = 内容管理 UEditor 富文本
    2. 1 = 直接编辑模板

    不是“0=输入模型,1=模板模式”。inputModelCodeName 是另一个独立字段。

    关于我们等独立页面希望通过 save_alone_page_content / 内容管理维护系统自动创建的唯一 News 内容时,应使用:

    1. SiteColumn.type = 8
    2. SiteColumn.editMode = 0

    9.11 输入模型 inputModelCodeName

    当前已核对资料中没有 productnewsarticle 等可假设为系统内置的固定模型代码列表

    默认逻辑:

    1. inputModelCodeName = null / 空字符串 / "0"
    2. 不指定自定义输入模型,由当前运行时处理默认输入模型

    自定义逻辑:

    1. inputModelCodeName = 其它代码
    2. 从数据库 input_model 中按 code_name 读取
    3. 该代码由网站管理员自行创建
    4. 每个网站可不同

    因此 AI 的固定执行规则为:

    1. 用户没有明确要求自定义输入模型时,省略 inputModelCodeName;如需显式空值,只使用运行时 schema 接受的 null、空字符串或字符串 "0"
    2. 用户明确要求某个自定义模型时,必须先确认当前网站确实存在对应 input_model.code_name
    3. 不得因为栏目叫“产品”“新闻”就自动传 productnewsarticle。这些字符串只有在当前网站真实存在同名自定义模型时才能使用。
    4. 输入模型与 SiteColumn.editMode 是两个独立概念,不得互相推导。

    9.12 分页标签 {page.*}

    分页标签来自父级官方页面:

    1. src/main/webapp/WEB-INF/view/templateTag/page.jsp

    WangMarket 6.1 源码已确认:这组标签只用于列表页(不用于首页和详情页),由 TemplateCMS.replaceListPageTag() 主动替换全部 11 个字段。帮助页 list.jsp 的”不可用”标记为过时标注。6.1 版本可直接使用;目标版本不是 6.1 时按 11.1 实测确认。源码核对版本列出 11 个字段:

    标签含义说明
    {page.allRecordNumber}总记录数6.1 已确认:输出当前列表栏目全部记录数量
    {page.currentPageNumber}当前页码6.1 已确认:输出当前静态分页页码
    {page.lastPageNumber}总页数6.1 已确认:输出最后一页页码/总页数
    {page.firstPage}首页 URL6.1 已确认:只输出地址,放入 href 等 URL 上下文
    {page.upPage}上一页 URL6.1 已确认:只输出地址,放入 href 等 URL 上下文
    {page.nextPage}下一页 URL6.1 已确认:只输出地址,放入 href 等 URL 上下文
    {page.lastPage}尾页 URL6.1 已确认:只输出地址,放入 href 等 URL 上下文
    {page.haveUpPage}是否存在上一页6.1 输出小写 true / false;跨版本需实测
    {page.haveNextPage}是否存在下一页6.1 输出小写 true / false;跨版本需实测
    {page.upList}前几页页码 HTML6.1 已确认:生成多个 <li>
    {page.nextList}后几页页码 HTML6.1 已确认:生成多个 <li>

    父级生成代码确认:仅在目标站点实际使用 generateUrlRule=code 时,列表页面文件名为:

    1. 第一页:codeName.html
    2. 2 页及以后:codeName_页码.html

    以下只是 codeName=news 的示例相对文件名,不含真实站点基础 URL:

    1. news.html
    2. news_2.html
    3. news_3.html

    {page.upList}{page.nextList} 按源码输出页码列表 HTML 并生成多个 <li>;它们输出的是一段页码列表 HTML,不是单个数字也不是单个 URL,因此不要把它们再机械包进一个 <li>href 中。

    code 规则的 URL 形态不得推导:源码中还可以看到 lc<ID>_<page>.htmlc<ID>.html<News.id>.html 等按 ID 组合的条件形式,但这些形态没有稳定公开契约,只能作为当前核对版本的条件示例来理解。自动流程统一要求使用用户、宿主、后台或真实页面标签输出的 URL;禁止由 codeName、栏目 ID、News.idhtmlName 或历史路径拼出预览地址。

    9.12.1 独立页面(SiteColumn.type=8)的 URL 规则

    WangMarket 6.1 源码已确认TemplateCMS.generateNewsPageHtmlName()):

    因此:


    10. 已确认规则与仍需确认的执行边界

    下表汇总有当前资料依据的规则。表中的“禁止使用/禁止猜测”也是执行结论,但不代表相关底层行为已经得到完整规范。

    序号原问题最终结论AI 强制执行规则
    1TemplatePage.type=0 使用场景TYPE_ELSE=0 仅标注“其他”;无明确标准生成、绑定、预览业务路径;普通保存也不会使其成为标准业务页面当前 MCP 不使用 0;不得自行定义用途
    2SiteColumn.type 1/2/3/4/5/6完整历史定义已确认:1新闻信息、2图文信息、3旧版独立页、4留言板、5超链接、6纯文字;7当前信息列表、8当前独立页新建只使用 7/8;3仅历史兼容;1/2/4/5/6 不用于当前新建
    3首页 type=1 标签和内容管理首页可用模板变量、全局变量、通用标签、动态栏目调用;可动态调文章/栏目列表;首页本身无当前文章/分页上下文新闻列表/轮播数据通过动态栏目调用;不得直接把 {news.*} 当首页当前文章,不得编造轮播 CMS 标签
    4列表页 type=2 除循环外全局标签可用模板变量、全局变量、通用标签、当前栏目 {siteColumn.*}、分页 {page.*}、动态栏目调用;文章 {news.*} 进入文章循环后使用使用 9.7 的上下文矩阵;分页仅列表页
    5栏目标签公开基线当前资料确认 {siteColumn.id/name/url/type/used/codeName/parentCodeName/icon/keywords/description}仅使用已确认字段;不得写成 {column.*} 或扩展未确认字段
    6TemplatePage.editMode=1 可视化模式父级标记即将废弃、不建议;只确认 iframe、htmledit.js、上传地址注入及保存清理逻辑;无完整 DOM/API 规范AI/MCP 默认 editMode=2;不使用、不臆造 editMode=1 协议
    7SiteColumn.editMode0=内容管理 UEditor1=直接编辑模板;与 TemplatePage.editMode 和输入模型都不同独立页面通过内容管理维护正文时使用 SiteColumn.editMode=0
    8inputModelCodeName省略、null、空字符串或字符串 "0" 表示不指定自定义模型;其它代码来自当前网站 input_model.code_name;没有固定 product/news/article 内置列表没有明确自定义模型时省略;其它代码必须先确认存在
    9模板变量命名、嵌套、保留名名称限英文/数字/下划线;非循环嵌套存在版本资料冲突;nav/footer 非保留;源码未定义固定保留名清单;各标签命名空间独立本流程在页面直接引用各变量;禁止循环引用;不伪造保留名或混用命名空间
    10全局变量 image/selecttext/image/select 都通过 {var.xxx} 引用;image value=图片 URL;select 用 valueItems 定义选项、value 保存当前值不把 image 自动当 <img>、不把 select 自动当 <select>;HTML 由模板自己写
    11独立页面模板 type=6 与详情页 type=3TemplatePage.TYPE_ALONEPAGE=6 已废弃并入详情页;当前关于我们使用 TemplatePage.type=3 + SiteColumn.type=8不得再创建 TemplatePage.type=6
    12codeName 是否必填条件必填:仅在需要动态栏目调用或目标运行时要求按代码生成时才传入;值必须是当前站点已确认存在的栏目代码;仅创建栏目且无上述需求时可按 schema 省略省略后不得由 codeName 推导栏目 URL;aboutnews 仅为栏目代码格式示例,执行时必须替换为真实存在的值
    13列表页/详情页标签适用性WangMarket 6.1 源码已确认可用TemplateCMS.replaceListPageTag() 主动替换 {siteColumn.*} 和全部 11 个 {page.*}replaceNewsTag() 主动替换 {news.*}(含 {news.url});列表页循环内逐篇调用 replaceNewsTag()。帮助页 list.jsp/details.jsp 表格中标注的”不可用”为过时标注,与 6.1 实际代码不符6.1 版本可直接使用 {siteColumn.*}{page.*}(列表页)、{news.*}(详情页及列表循环内);目标版本不是 6.1 时仍须按 11.1 实测确认
    14分页标签与列表 URL 形态11 个 {page.*} 字段来自源码核对版本;codeName.html / codeName_页码.html 仅在 generateUrlRule=code 时成立分页只用于列表页;upList/nextList 输出页码列表 HTML,不包成单个数字或 URL;lc<ID>_<page>.html 等 ID 形态无公开契约,禁止推导
    15{templatePath} 尾斜杠WangMarket 6.1 源码已确认末尾带斜杠getTemplatePath() = 路径前缀 + site.templateName + "/"(字节码显式 append /)。私有模板前缀 = ATTACHMENT_FILE_URL + websiteTemplate/,云模板前缀 = //cloudtemplate.weiunity.com/websiteTemplate/,两者本身也以 / 结尾6.1 版本模板中统一写 {templatePath}css/style.css不加额外斜杠);写 {templatePath}/css/style.css 会产生双斜杠 //
    16generateUrlRule 判定逻辑WangMarket 6.1 源码已确认:默认 "int"templateCMS() 中判定——系统属性 MASTER_SITE_URL 为 null 或不等于 "http://wang.market/" 时 → "code";等于官方云地址时,site.id > 255site.id == 218"code",其余老站点 → "int"自部署/非官方环境几乎一定是 "code";官方云老站点(id≤255 且 ≠218)才是 "int"。具体值可通过部署环境或站点 ID 判定,或从已生成页面 URL 反推;MCP 无查询接口

    以下事项仍缺少当前 MCP 的查询能力或统一运行时依据,不得标成已解决,更不得由 AI 补全

    待确认事项当前可执行边界
    站点基础 URL(域名/访问路径)由用户、宿主或后台提供;MCP 无查询接口
    栏目、模板变量、新闻、全局变量的查询当前工具集没有查询工具;缺少真实 ID/存在性时停止
    save_site_column.info 为非数字文本不把”成功”当 ID;停止后由后台确认,避免重复创建
    save_template 的目标模板与副作用调用前确认允许影响现有模板;result=1 后仍以生成和预览验证
    generate_site 之后文件的可访问性result=1 只表示调用完成;必须用真实 URL 做 HTTP 与内容验收;404/超时且无轮询工具时停止等待后台确认,不无限重试、不猜 URL
    独立页面内容的”当前站点唯一”属实现边界(底层按 cid 查询 News 且未显式带 siteid);不得无条件承诺,必须后台确认后再更新
    独立页面内容记录未自动创建时的回退save_alone_page_content 只查询不创建,当前 MCP 无替代工具;必须由人工在后台”内容管理”手动添加一条后 AI 才能更新;在此之前关于我们页面无内容来源(见 5.3)
    News.htmlName 在当前 6.1 生成器中的效果不用它推导详情 URL
    editMode=1 的完整可视化协议当前 MCP 不使用,统一显式传 TemplatePage.editMode=2
    非 6.1 版本的标签适用性、valueItems、日期补零、模板变量嵌套等细节目标版本不是 6.1 时按 11.1-11.9 实测确认;6.1 版本以上述已确认表为准

    11. 运行时确认操作指南

    本章针对第 10 章「仍需确认的执行边界」中列出的事项,给出具体的确认方法和操作步骤。AI 不得自行决定这些技术参数,但可以按本章指引从目标运行时、后台或用户处取得确认依据。确认结果应记录版本号和证据,后续执行时引用。

    11.1 列表/详情页标签适用性(6.1 已确认)

    WangMarket 6.1 结论{siteColumn.*}{news.*}{page.*} 在列表页和详情页均可用,源码中有对应的替换方法并被生成流程实际调用:

    帮助页 list.jsp/details.jsp 表格中标注的”不可用”为过时标注,与 6.1 实际代码不符。6.1 版本可直接使用这些标签,无需运行时测试。

    跨版本注意:若目标 WangMarket 版本不是 6.1,仍须做一次最小化真实生成测试确认:

    1. 在列表模板中写入 {siteColumn.name}<!--TemplateListItemStart-->{news.title}<!--TemplateListItemEnd-->{page.firstPage}
    2. 在详情模板中写入 {news.title}{news.text}
    3. 调用 generate_site 后查看源码,标签原样残留则该版本不支持。

    11.2 站点基础 URL 与 generateUrlRule(6.1 判定逻辑已确认)

    WangMarket 6.1 源码已确认 generateUrlRule 判定逻辑TemplateCMS.templateCMS()):

    部署环境判定条件generateUrlRule
    自部署/非官方MASTER_SITE_URL 系统属性为 null,或不等于 "http://wang.market/""code"
    官方云(wang.market)site.id > 255site.id == 218"code"
    官方云(wang.market)site.id ≤ 255site.id ≠ 218(老站点)"int"(默认值)

    实际操作

    1. 自部署环境:可直接判定为 code 规则,列表页 URL = codeName.html,独立页面 URL = codeName.html,新闻详情 URL = News.id.html
    2. 官方云/不确定环境
      • 从用户/宿主取得站点 ID,按上表判定;或
      • 后台查看站点设置;或
      • 从已生成页面 URL 反推:news.html/news_2.htmlcodelc1001_1.html/451.htmlint
    3. 站点基础 URL(域名/访问路径):仍须由用户、宿主或后台提供,MCP 无查询接口。
    4. 独立页面(type=8)的 URLcode 规则下 = codeName.html(源码 generateNewsPageHtmlName() 已确认);int 规则下须由后台确认,不得推导(见 9.12.1)。

    11.3 栏目/模板变量/新闻的已有状态与真实 ID 确认

    待确认内容:目标站点是否已存在同名栏目、模板变量、模板页面或新闻,以及它们的真实 ID。

    确认方法

    1. 后台查看
      • 栏目:后台「栏目管理」列表,记录栏目名称、ID、codeName、类型;
      • 模板变量:后台「模板管理 → 模板变量」,记录 varName 和 ID;
      • 模板页面:后台「模板管理 → 模板页面」,记录 nametype 和 ID;
      • 新闻:后台「内容管理」,按栏目筛选,记录文章 ID。
    2. 从本次会话上下文取得:若前面的工具调用已返回 info 中的正整数 ID,直接使用该值。
    3. 当前 MCP 限制:没有按名称/代码查询的工具,缺少 ID 时必须停止并请求后台确认,不得猜测或用 id=0 假装更新。

    11.4 save_template 目标模板与副作用确认

    待确认内容:当前站点 site.template_id 是否指向有效模板;调用 save_template 是否会修改已有模板。

    确认方法

    1. 后台查看模板绑定:在后台「模板管理」中查看当前站点是否已选择/导入模板,以及模板名称。
    2. 评估副作用save_template 的实现可能在 template_id 无效时使用 ID 1,可能创建或修改既有模板。调用前必须由用户确认允许该操作影响现有模板。
    3. 调用后验证result=1 后仍需后台复核绑定状态,并执行 generate_site + 真实 URL 验收,不能仅凭返回值宣称绑定成功。

    11.5 save_site_column.info 非数字文本的落库状态确认

    待确认内容result=1info 返回 "成功" 等非数字文本时,栏目是否实际落库、ID 是多少。

    确认方法

    1. 停止后续写入,不要重复调用 save_site_column(可能创建重复栏目)。
    2. 后台栏目管理:按栏目名称和创建时间找到刚创建的栏目,记录其真实 ID。
    3. 若存在多个同名栏目:通过绑定的模板页面名称(templatePageListName / templatePageViewName)和创建时间区分,确认哪一个是本次创建的。
    4. 使用后台确认的真实 ID 继续后续 save_news / save_alone_page_content

    11.6 {templatePath} 前缀尾斜杠(6.1 已确认)

    WangMarket 6.1 源码已确认{templatePath} 输出末尾一定带斜杠 /

    getTemplatePath() 实现:路径前缀 + site.templateName + "/"(字节码显式 append /)。路径前缀本身也以 / 结尾:

    6.1 版本确定写法:模板中统一写 {templatePath}css/style.css不加额外斜杠)。

    禁止写法{templatePath}/css/style.css 会产生双斜杠 //(如 https://example.com/template/default//css/style.css),部分浏览器/CDN 可能无法正确解析。

    跨版本注意:目标版本不是 6.1 时,生成一次后查看实际 href 确认;确认后整份模板统一一种写法。

    11.7 generate_site 后静态文件可访问性确认

    待确认内容generate_site 返回 result=1 后,静态文件是否真实可访问。

    确认方法

    1. 使用真实 URL 做 HTTP 验收:用浏览器或 curl 访问首页、列表页、详情页,检查 HTTP 状态码。
    2. 检查内容:页面中文正常、无未解析标签、无残留动态标记、CSS/JS/图片可加载。
    3. 404/超时处理
      • 不要无限重试 generate_site
      • 检查宿主 Web 服务器根目录配置、CDN 缓存;
      • 后台文件管理中确认静态文件是否实际生成及文件名;
      • 无轮询工具时停止并等待后台确认。

    11.8 独立页面内容唯一性与存在性确认

    待确认内容save_alone_page_contentcid 查询的 News 记录在当前站点下是否存在且唯一。

    确认方法

    1. 后台内容管理:进入该独立页面栏目,首先确认是否存在内容记录。
      • 若不存在任何内容记录:当前 MCP 无法创建(save_alone_page_content 只查询不创建,save_news 不适用于 type=8),必须由人工在后台”内容管理”中为该栏目手动添加一条内容,之后 AI 才能用 save_alone_page_content 更新。在此之前不得宣称关于我们页面已完成。
      • 若存在且仅有一条:继续下一步。
    2. 若存在多条同 cid 记录:底层查询目标不确定,必须停止,由后台清理重复数据后再执行 save_alone_page_content
    3. 实现边界说明:底层查询未显式带 siteid 条件,跨站数据可能干扰;不得无条件承诺「当前站点唯一」。

    11.9 非 6.1 版本的 valueItems、日期格式与嵌套行为确认

    待确认内容:目标 WangMarket 版本不是已核对的 6.1 时,select 类型全局变量的 valueItems 格式、{news.addtime.month} 是否补前导零、模板变量非循环嵌套是否生效。

    确认方法

    1. 确认版本号:在后台关于页面或页脚查看 WangMarket 版本号。
    2. valueItems 格式:在后台创建一个 select 类型全局变量,保存后查看选项是否正确解析;若 值:显示文本 格式不生效,尝试后台文档说明的格式。
    3. 日期格式:在详情模板中写入 {news.addtime.month},生成后查看输出是 3 还是 03;需要固定两位时由模板前端 JS 格式化,不依赖 CMS 输出。
    4. 模板变量嵌套:创建变量 A 引用变量 B,生成后查看是否展开;若不生效,改为在模板页面中分别直接引用。

    11.10 News.htmlName 对详情 URL 的影响确认

    待确认内容save_alone_page_contenthtmlName 参数是否影响当前生成器的详情页 URL。

    确认方法

    1. 创建测试内容时设置 htmlName=test-page,生成后查看详情页实际 URL。
    2. 若 URL 未使用 test-page.html:说明当前版本生成器不采用 htmlName,不得用它推导预览 URL。
    3. 统一规则:详情页 URL 始终使用真实生成结果或后台确认的地址,不得由 htmlNameNews.idcodeName 推导。

    11.11 确认结果记录模板

    每次完成上述确认后,应按以下格式记录,供后续执行引用:

    1. 确认项:<对应 11.1-11.10 的编号>
    2. 目标运行时版本:<版本号>
    3. 确认方法:<帮助页 / 真实生成 / 后台查看>
    4. 确认结果:<可用 / 不可用 / 具体参数值>
    5. 证据:<帮助页截图描述 / 生成页面 URL / 后台路径>
    6. 确认时间:<YYYY-MM-DD>

    未完成确认的事项,在执行时必须按第 10 章的「当前可执行边界」停止并报告,不得跳过。


    常见问题与避坑指南

    在实际操作过程中,以下常见问题容易导致生成失败或页面显示异常,在此特别说明,避免后续踩坑。

    问题1:后台点击「生成整站」提示”当前网站尚未选择/导入/增加模版,生成失败!”

    现象描述

    在网站管理后台左侧菜单点击「生成整站」按钮时,弹出错误提示:

    1. 当前网站尚未选择/导入/增加模版,生成失败!网站有模版后才能根据模版生成整站!

    但奇怪的是,已经创建了模板页面(index、about、news)和模板变量(nav、footer),为什么还提示没有模板?

    原因分析

    网市场系统的模板体系分为两层:

    层级数据表说明
    模板(Template)template模板的基本信息,一个模板包含多个模板页面
    模板页面(TemplatePage)template_page + template_page_data具体的页面模板(首页、列表页、详情页)

    网站表 site 中有一个字段 template_id,指向 template 表中的模板记录。

    后台「生成整站」按钮在执行生成前,会校验:

    1. site.template_id template 表中是否存在对应记录

    如果 template 表为空,或者 site.template_id 指向了一个不存在的模板 ID,校验就会失败,提示”当前网站尚未选择/导入/增加模版”。

    而通过 MCP 接口 generate_site(对应上游接口 /template/refreshForTemplate.do)生成时,可能不执行同一项绑定校验,因此“生成调用返回成功”和“后台模板绑定有效”必须分别验证。

    解决方案

    方案一:在确认允许影响当前模板后调用 save_template

    本文档已新增 MCP 工具 save_template,对应上游接口:

    1. POST /plugin/adminapi/site/saveTemplate.json

    当前实现的真实边界:

    1. 读取当前网站的 site.template_id;为空或不大于 0 时把候选 ID 设为 1
    2. 候选 ID 不存在时,尝试按该 ID 新建模板记录,并把网站指向它。
    3. 候选 ID 已存在时,不会重新绑定到其它模板;传入非默认名称或非空备注还可能修改该既有模板。
    4. 若网站原本没有有效 template_id 而模板 ID 1 已存在,当前代码可能返回成功但没有把网站重新绑定到 1。
    5. 接口没有验证新建/既有模板是否与已创建的模板页面正确归属,也不能保证后台按钮随后一定成功。

    因此调用前必须由用户或后台确认允许该操作影响现有模板。无法确认当前绑定状态时,不得把此工具描述为无副作用的“确保绑定”。为降低误改风险,默认只传 authHandle;只有用户明确要求修改模板名称/备注时才传对应字段。

    调用示例:

    1. {
    2. "authHandle": "<login 返回的有效 authHandle>"
    3. }

    参数说明:
    | 参数 | 是否必填 | 类型 | 说明 |
    |—-|—-|—-|—-|
    | authHandle | 是 | string | login 成功返回的认证句柄 |
    | name | 否 | string | 模板名称,默认”自定义模板” |
    | remark | 否 | string | 模板备注,默认空字符串 |

    返回示例:

    1. {
    2. "result": 1,
    3. "info": "1"
    4. }

    其中 info = "1" 只是示例模板 ID。result=1 只表示本接口完成,不能宣称绑定、后台生成或预览已成功;仍须执行本节验证方法。

    方案二:由获授权的数据库管理员修复

    数据库写入不属于本文 MCP/AI 自动建站流程。只有获授权管理员在确认目标站点 ID、当前用户、目标模板 ID、数据归属并完成备份后,才能按实际数据库版本修复;不得把示例 ID 1 当成固定值,也不得让 AI 执行未经限定站点的 INSERTUPDATE

    验证方法

    依次验证:后台确认目标站点指向预期模板;后台「生成整站」不再出现该错误;generate_site 返回 result=1;最后用真实站点 URL 检查首页、列表页和详情页。四项都通过后才算解决。


    问题2:生成的网站中文乱码(UTF-8 编码问题)

    现象描述

    生成整站后,访问生成的静态 HTML 页面,中文显示为乱码(如”棣栭〉”、”鏂伴椈鍒楄〃”等),但英文和数字显示正常。

    查看生成的 HTML 文件源码,发现文件中没有 <meta charset="utf-8"> 标签。

    原因分析

    在创建模板页面时,如果只保留了 body 内部的内容,例如:

    1. {include=nav}
    2. <div>
    3. <h2>hi,这是首页</h2>
    4. </div>
    5. {include=footer}

    没有保留完整的 HTML 文档结构(缺少 <!DOCTYPE html><html><head><meta charset="utf-8"><body> 等标签),那么系统生成静态 HTML 时,会直接将模板内容输出到文件中,不会自动添加 <head> 和编码声明。

    浏览器在解析没有编码声明的 HTML 文件时,会使用系统默认编码(在中文 Windows 上通常是 GBK/GB2312),而文件实际是 UTF-8 编码保存的,编码不匹配就会导致中文乱码。

    解决方案

    在创建/修改模板页面时,必须保留完整的 HTML 文档结构,包含 <meta charset="utf-8">

    正确的首页模板示例:

    1. <!DOCTYPE html>
    2. <html>
    3. <head>
    4. <meta charset="utf-8">
    5. <title>首页 - 网站名称</title>
    6. </head>
    7. <body>
    8. {include=nav}
    9. <div>
    10. <h2>hi,这是首页</h2>
    11. </div>
    12. <div>
    13. 网站介绍内容...
    14. </div>
    15. {include=footer}
    16. </body>
    17. </html>

    正确的详情页(关于我们)模板示例:

    1. <!DOCTYPE html>
    2. <html>
    3. <head>
    4. <meta charset="utf-8">
    5. <title>{news.title} - 网站名称</title>
    6. </head>
    7. <body>
    8. {include=nav}
    9. <h1>{news.title}</h1>
    10. <div>
    11. {news.text}
    12. </div>
    13. {include=footer}
    14. </body>
    15. </html>

    正确的列表页(新闻列表)模板示例:

    1. <!DOCTYPE html>
    2. <html>
    3. <head>
    4. <meta charset="utf-8">
    5. <title>新闻列表 - 网站名称</title>
    6. </head>
    7. <body>
    8. {include=nav}
    9. <h1>新闻列表</h1>
    10. <ul>
    11. <!--TemplateListItemStart-->
    12. <li><a href="{news.url}">{news.title}</a></li>
    13. <!--TemplateListItemEnd-->
    14. </ul>
    15. {include=footer}
    16. </body>
    17. </html>

    如果已有模板缺少编码声明,如何修复?

    先从后台取得当前模板页面的完整源码,整理成唯一一套 doctype/html/head/body 结构并保留原正文,再通过后台或 save_template_page_text 整体覆盖。不要在未知原文前后盲目追加标签,否则可能生成嵌套或重复的 <html><head><body>。当前 MCP 没有读取模板页面源码的工具;若手头没有可信的完整原文,必须停止并要求后台导出,不能凭空重建后覆盖。

    保存后重新生成整站,并用真实 URL 检查响应内容与浏览器显示。

    验证方法

    生成整站后,查看生成的 HTML 文件源码,确认文件开头包含:

    1. <!DOCTYPE html>
    2. <html>
    3. <head>
    4. <meta charset="utf-8">

    在浏览器中打开页面,中文应正常显示,不再出现乱码。


    问题3:save_site_column 返回 result=1info 是”成功”等非数字文本

    现象描述

    调用 save_site_column 创建栏目后,返回:

    1. {
    2. "result": 1,
    3. "info": "成功"
    4. }

    info 不是数字,无法取得栏目 ID,后续 save_newssave_alone_page_contentcid 参数无法填写。

    原因分析

    不同版本的 WangMarket 上游接口在 save_site_column 成功时,info 字段的返回值不一致:

    当前 MCP 没有栏目查询工具,无法通过 codeName 或栏目名称反查 ID。

    解决方案

    1. 停止后续写入操作,不要猜测栏目 ID,也不要用 codeName、栏目名称或模板页面 ID 代替 cid
    2. 进入后台确认:在后台「栏目管理」中找到刚创建的栏目,记录其真实 ID。
    3. 使用后台确认的真实 ID 继续调用 save_newssave_alone_page_content
    4. 若后台中存在多个同名栏目,必须确认哪一个是本次创建的(可通过创建时间、绑定的模板页面名称区分),避免更新错误栏目。
    5. 不要因为 result=1 就重复调用 save_site_column,否则可能创建重复栏目。

    验证方法

    后台栏目列表中能看到本次创建的栏目;使用后台确认的真实 ID 调用后续工具返回 result=1;生成后页面内容属于目标栏目。


    问题4:页面中 {include=nav}{var.qq}{news.title} 等标签没有被解析,原样显示在生成的 HTML 中

    现象描述

    生成整站后,查看页面源码,发现 {include=nav}{var.qq}{news.title}{siteColumn.name} 等花括号标签没有被替换,原样出现在 HTML 中。

    原因分析

    按标签类型分别排查:

    标签类型常见原因
    {include=xxx}模板变量不存在、varName 拼写不一致、变量 text 为空、保存变量在保存页面之后
    {var.xxx}全局变量不存在、变量名拼写不一致、变量未设置 value
    {news.*} / {siteColumn.*} / {page.*}当前页面没有对应上下文(如首页直接写 {news.title})、目标运行时不支持该标签、标签在错误的循环位置使用
    动态标记 <!--SiteColumn_Start-->标记拼写错误(区分大小写)、codeName 不存在、标记未正确闭合

    解决方案

    1. {include=xxx} 未解析

      • 确认模板变量已通过 save_template_var 创建且 result=1
      • 确认页面中 {include=nav}navsave_template_var.varName 完全一致(大小写敏感);
      • 确认变量 text 不为空;
      • 确认创建变量在保存页面 HTML 之前执行(见 2.2.5 顺序规则)。
    2. {var.xxx} 未解析

      • 确认全局变量已通过 save_site_var 创建;
      • 确认变量名与 {var.qq} 中的 qq 完全一致;
      • 确认变量已设置 value
    3. {news.*} / {siteColumn.*} / {page.*} 未解析

      • 按前置规则第 10 条,先确认目标运行时是否支持该标签及上下文;
      • 确认标签使用在正确的上下文中:{news.*} 必须在详情页或文章循环内,{page.*} 仅用于列表页,首页不能直接写 {news.title}
      • 确认动态标记 <!--TemplateListItemStart--> / <!--List_Start--> 等拼写正确且已闭合。
    4. 动态标记残留

      • 检查标记是否精确匹配(区分大小写,无多余空格):<!--SiteColumn_Start--><!--SiteColumn_End--><!--List_Start--><!--List_End--><!--SubColumnList_Start--><!--SubColumnList_End--><!--TemplateListItemStart--><!--TemplateListItemEnd-->
      • 确认 codeName 指向的栏目真实存在且已启用。

    验证方法

    重新生成整站后,页面源码中不再出现未解析的花括号标签和动态标记;页面内容正确显示为后台数据。


    问题5:generate_site 返回 result=1 但访问页面 404 或超时

    现象描述

    generate_site 返回 result=1,但使用预期 URL 访问页面时返回 404 或连接超时。

    原因分析

    result=1 只表示生成调用已完成,不代表:

    常见具体原因:

    1. URL 猜测错误:由 codeName 或栏目 ID 拼接的 URL 与实际 generateUrlRule 不符;
    2. 宿主环境延迟:静态文件生成后,CDN 或 Web 服务器需要时间刷新;
    3. 站点未绑定有效模板:见问题1;
    4. 栏目未启用或 useGenerateView=0:详情页不会生成。

    解决方案

    1. 不要无限重试 generate_site,也不要猜测 URL。记录真实的 404/超时错误信息。
    2. 确认真实站点基础 URL:从用户、宿主或后台取得,不要由 codeName 或 ID 推导。
    3. 确认 generateUrlRule:只有后台确认使用 code 规则时,codeName.html 才可能成立;其它规则可能使用栏目 ID 路径。
    4. 确认栏目状态:栏目 used=1、信息列表栏目 useGenerateView=1(需要详情页时)。
    5. 后台确认生成结果:在后台文件管理或 FTP 中查看静态文件是否实际生成、文件名是什么。
    6. 若宿主有轮询或生成状态查询工具,使用它确认生成完成;没有则等待后台确认。

    验证方法

    使用后台确认的真实 URL 访问,返回 HTTP 200;页面内容正确;中文正常;无未解析标签。


    问题6:更新已有模板变量/栏目时,应该传 id 还是省略?

    现象描述

    需要修改已存在的 nav 模板变量或已创建的栏目,不确定是否应该传 id 参数。

    原因分析

    save_template_varsave_template_pagesave_site_columnid 参数行为一致:

    如果省略 id 去”更新”已有变量,实际会创建一个同名新变量,导致重复。

    解决方案

    按文末闭环开头的创建/更新判定规则执行:

    情况处理方式
    已存在,且有已确认的真实 ID更新:显式传入该真实 ID
    已确认不存在创建:省略 id,或传 0 / null
    状态不明,或没有真实 ID停止:由后台确认,不得猜 ID、不得重复创建

    具体操作:

    1. 从本次会话前面的工具返回结果中查找 info 字段中的真实 ID;
    2. 若上下文中没有,进入后台确认对象 ID;
    3. 当前 MCP 没有按名称查询模板变量/栏目/新闻的工具,不能用 varNamenamecodeName 代替 ID。

    验证方法

    更新后后台只有一个目标对象(无重复);对象内容为更新后的值;生成页面反映更新内容。


    问题7:{templatePath} 生成的 CSS/JS/图片路径出现双斜杠 //

    现象描述

    生成页面后,查看资源引用,发现路径如 https://example.com/template//css/style.css,中间有双斜杠。

    原因分析

    WangMarket 6.1 源码已确认{templatePath} 输出末尾一定带斜杠 /getTemplatePath() = 路径前缀 + templateName + "/")。如果模板中写 {templatePath}/css/style.css,变量本身已带 /,就会生成 //

    解决方案

    1. 6.1 版本确定写法:模板中统一写 {templatePath}css/style.css不加额外斜杠);
    2. 不要把双斜杠当作通用可接受行为,部分浏览器/CDN 可能无法正确解析;
    3. 修改后重新生成整站,检查所有资源引用。

    验证方法

    生成页面中所有 {templatePath} 引用的资源路径无重复斜杠;CSS/JS/图片均可正常加载(HTTP 200)。

    跨版本注意:目标版本不是 6.1 时,生成一次后查看实际 href 确认前缀是否带斜杠,再统一写法。


    问题8:save_alone_page_content 返回内容不存在或栏目下没有内容记录

    现象描述

    创建”关于我们”独立页面栏目(type=8editMode=0)后,调用 save_alone_page_content 更新内容时返回 result=0info 提示未找到内容记录;或在后台”内容管理”中进入该栏目发现没有任何内容。

    原因分析

    save_alone_page_content 底层先执行 SELECT * FROM news WHERE cid = ?,查询为空时立即返回错误,不会创建内容记录。虽然创建 type=8 栏目时系统可能尝试自动生成一条内容,但这不是保证行为——部分版本、部分数据状态下可能未生成。

    当前 MCP 工具集中没有”按栏目创建独立页面内容”的替代工具:

    解决方案

    1. 停止 MCP 操作,不要重试 save_alone_page_content(不会因为重试而创建内容),也不要改用 save_news(栏目类型不匹配)。
    2. 由人工在后台”内容管理”中为该栏目手动添加一条内容:进入内容管理 → 选择”关于我们”栏目 → 添加内容 → 填写标题和正文 → 保存。
    3. 后台确认内容已存在且唯一后,AI 再使用 save_alone_page_content(cid=栏目ID) 更新该内容。
    4. 在此之前,关于我们页面的 {news.title}/{news.text} 无数据来源,不得宣称该页面已完成

    验证方法

    后台内容管理中该栏目下有且仅有一条内容记录;save_alone_page_content 返回 result=1generate_site 后关于我们页面正确显示标题和正文。


    AI 自动执行的唯一闭环

    能力边界声明:本节是 MCP 工具集支持范围内的唯一执行顺序,但不构成”AI 全自动闭环”。当前 MCP 缺少站点 URL/生成结果查询工具和独立页面内容创建工具,因此以下步骤中,真实页面 URL 必须由用户、宿主或后台外部提供;独立页面内容记录若未自动创建,必须由人工在后台添加后 AI 才能更新。缺少这些外部输入时,流程必须在对应步骤暂停并报告缺口,不得猜测或降级。

    本节是全文的最终顺序;前文各章用于准备参数和 HTML,不得另行拼接出不同流程。示例 indexaboutnewsnewsView 可以按需求改名,但同一对象在创建、保存和绑定处必须一致。

    创建 / 更新判定规则(适用于每一个对象:模板变量、模板页面、栏目、新闻)

    执行前先对对象做三选一判定,再决定怎么调用:

    判定结果处理方式
    已存在,且有已确认的真实 ID更新:显式传入该真实 ID
    已确认不存在创建:省略 id,或传 0 / null
    状态不明,或没有真实 ID停止:由后台确认,不得猜 ID、不得重复创建、不得用 id=0 假装更新

    三条容易出错的边界:

    • save_template_varid 省略、null0 一律按新建处理,不会按 varName 覆盖已有变量;已有同名变量必须先取得真实 ID。
    • save_template_pagesave_site_column 同理:已存在时必须用已确认的真实 ID 更新;确认不存在时才省略 ID 或传 0
    • save_news 更新时必须同时提供真实 News.id 和真实 cid
    1. 准备并校验输入:确认目标站点、运行时工具 schema、本次要走哪些业务分支(首页 / 独立页面 / 信息列表并启用详情)、每个对象的创建或更新状态与真实 ID、完整 HTML、文案、真实图片 URL、允许的模板绑定方案,以及真实站点基础 URL。需要更新的对象必须有真实 ID;需要自定义输入模型、栏目代码或图片 URL 时必须有后台依据。任一缺失即停止,不开始写入。
    2. 登录:调用 login。仅 result=1 且返回非空真实 authHandle 时继续,后续每个业务工具均原样传入它。
    3. 先保存被引用的数据:模板若使用 {var.xxx},先用 save_site_var 创建完整定义;只改已确认存在的值才用 save_site_var_value。然后按本节开头的创建/更新判定规则处理 navfooter 模板变量——已存在且有真实 ID 就按 ID 更新,已确认不存在才创建,不明则停止,并保存真实变量 ID。若真实导航 URL 尚未取得,可先保存不含猜测链接的最小导航,待第 8 步取得 URL 后按真实 ID 更新。
    4. 按业务分支创建并保存模板页面:先按第 1 步确定的分支列出本轮真正需要的页面,再对每个页面调用 save_template_page(editMode=2),成功后立即用相同名称调用 save_template_page_text 保存完整 HTML。只有元数据和 HTML 两次调用都成功才算就绪;返回的页面 ID 不传给 pageName
      • 首页分支 → 需要 indexTemplatePage.type=1);
      • 独立页面分支 → 需要 abouttype=3 页面;
      • 信息列表分支 → 需要 newstype=2);只有启用详情生成(useGenerateView=1)时才还需要 newsViewtype=3)。
        未选择的分支不创建、不绑定、不在第 10 步虚构预览页面;页面已存在时按判定规则用真实 ID 更新。
    5. 处理模板绑定:若后台已确认当前网站绑定有效模板,不调用 save_template。若尚未绑定,只有用户已授权其潜在副作用时才调用;result=1 后仍须后台复核绑定。未授权或无法确认时停止,不能宣称已确保绑定。
    6. 创建或更新关于我们业务数据(仅当选择独立页面分支时执行):按判定规则处理后,用 save_site_column(type=8, templatePageViewName=about, editMode=0) 写入栏目。只有 result=1info 可严格解析为已确认属于当前站点的大于 0 的真实栏目 ID 时,才把它传给 save_alone_page_content.cidinfo成功、空值或其它非数字文本时停止并由后台确认。调用前还必须按 5.3 确认系统已创建且唯一的目标内容;存在多条同 cid 历史记录时停止。若后台确认该栏目下没有内容记录,当前 MCP 无法创建——必须由人工在后台”内容管理”中手动添加一条后,才能继续 save_alone_page_content;在此之前不得宣称关于我们页面已完成。
    7. 创建或更新新闻业务数据(仅当选择信息列表分支时执行):确认 news(启用详情生成时还包括 newsView)均已完整保存后,按判定规则处理栏目,再用 save_site_column(type=7, templatePageListName=news, templatePageViewName=newsView) 写入,并显式传本流程需要的编辑字段;更新已存在栏目时必须使用已确认的真实 ID。仍仅接受可确认的正整数栏目 ID,然后把该真实 ID 作为 save_news.cid更新新闻时必须同时提供真实 News.id 和真实 cid
    8. 预生成并补齐真实导航:先调用一次 generate_site 使本轮页面落库(result=1 仅表示调用完成,不返回任何 URL)。当前 MCP 没有站点 URL、栏目或生成结果查询工具,预生成后 AI 仍不能从返回值取得页面地址——必须由用户、宿主或后台提供本轮实际页面的真实 URL(首页、独立页面、列表页;启用详情生成时还需至少一篇详情页)。未知 generateUrlRule 时不得由 codeName 或栏目 ID 拼接。取得全部 URL 后,使用第 3 步保存的真实 nav 模板变量 ID 更新完整导航。缺少 nav ID 或任一页面 URL 时,保留第 3 步的最小导航并报告缺口,不得猜测 URL 或用 about.html/news.html 等示例路径充数。
    9. 最终生成:导航更新后再次调用 generate_site,使导航变更反映到静态页面。result=1 只表示生成调用已完成,不等于静态文件已可访问或内容正确。必须按宿主提供的真实 URL 做一次 HTTP 与内容验收;若出现 404、超时且没有官方轮询/查询工具,不得无限重试生成、不得猜 URL,应记录真实错误并停止等待后台确认。
    10. 真实预览验收:使用可信 URL 分别访问本轮实际选择的分支生成的页面——首页分支访问首页;独立页面分支访问该独立页面;信息列表分支访问列表页;启用详情生成时再访问至少一篇详情页。未选择的业务分支不创建、不绑定、也不虚构预览页面。 全部满足以下条件才算建站成功:HTTP 响应可访问;UTF-8 中文正常;页面结构、导航、分页、详情链接及模板实际引用的图片/资源可用(题图/轮播必须确认是用户提供的真实素材,不能只凭 titlepic 非空);内容属于目标站点;源码中没有未解析的 {include=...}{var.*}{news.*}{siteColumn.*}{page.*},也没有残留的精确动态标记 <!--TemplateListItemStart--><!--TemplateListItemEnd--><!--SiteColumn_Start--><!--SiteColumn_End--><!--SubColumnList_Start--><!--SubColumnList_End--><!--List_Start--><!--List_End-->

    全局失败规则:先判断 MCP/传输错误,再判断业务 resultresult=0mcpErrorisError=true 或验收失败时停止当前依赖链并报告真实错误;result=2 时重新登录,只重试刚失败的一步。超时、断线或其它无法判断写入是否落库的情况禁止盲目重试创建/覆盖操作,必须先由后台确认实际状态,否则可能产生重复对象或覆盖正确内容。

    当前 MCP 没有站点 URL规则、栏目、模板页面、模板变量、新闻、输入模型、全局变量或上传结果的通用查询工具。缺少真实上下文时,结论只能是“需要后台确认或补充查询接口”,不能借用其它 CMS 经验、示例值、名称、codeName、URL 数字或历史默认值进行推断。