本地静态模版转为wangmarket的模版
本文是 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 模板包中是否引用了本地静态资源文件,包括但不限于:
| 资源类型 | 常见引用方式 | 常见扩展名 |
|---|---|---|
| 样式表 | <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 |
检查与处理流程:
- 扫描模板:读取所有 HTML 文件,提取上述引用路径,区分绝对 URL(
http://、https://开头,可直接使用)与相对/本地路径(./、../、/、纯文件名开头,需要上传)。 - 统计清单:列出所有需要上传的本地静态资源文件路径、数量、总大小,向用户报告。
- 提醒上传:如果存在本地静态资源,必须暂停模板制作流程,提醒用户将这些资源上传到线上可访问的存储服务,可选方式包括:
- 阿里云 OSS / 腾讯云 COS / 七牛云等对象存储
- 公司 FTP 服务器 / 静态资源 CDN
- 网市场后台的附件上传功能(如有)
- 其他可公网访问的 HTTP/HTTPS 静态文件服务
- 配置访问域名:资源上传完成后,必须为存储服务配置一个可公网访问的域名,注意事项:
- 不得直接使用存储服务的临时域名、内网地址或 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)
- 不得直接使用存储服务的临时域名、内网地址或 IP 地址(如
- 获取 URL:域名配置并验证通过后,要求用户提供每个资源对应的线上可访问 URL(或一个统一的基础 URL 前缀 + 相对路径映射规则,如基础前缀
https://cdn.example.com/+ 相对路径css/style.css)。 - 验证可访问:对每个线上 URL 进行可访问性验证(HTTP 状态码 200、Content-Type 正确、非空响应体),图片资源建议验证可正常渲染。
- 替换路径:验证通过后,将模板 HTML 中所有本地静态资源路径统一替换为对应的线上 URL。
- 继续流程:完成上述步骤后,才能进入第 1 章开始正常的模板制作流程。
禁止行为:
- ❌ 不得将本地相对路径(如
images/logo.png、css/style.css)直接写入模板页面或模板变量,否则生成的站点会出现图片不显示、样式丢失、脚本失效等问题。 - ❌ 不得使用
{templatePath}前缀指向本地资源目录——{templatePath}仅用于模板自带的示例资源路径,生产环境必须替换为真实可访问的线上 URL。 - ❌ 不得在未验证 URL 可访问的情况下继续流程,必须确认资源真实可访问后再替换。
- ❌ 不得使用存储服务的临时域名、内网地址或 IP 地址作为资源访问地址——临时域名可能有访问次数限制或随时失效,内网地址/IP 无法公网访问,必须使用用户自己的已备案域名并配置 HTTPS。
例外情况:如果模板中所有静态资源均已使用绝对 URL(如 https://cdn.example.com/css/style.css),且验证可访问,则无需上传,可直接进入第 1 章。
目录
- ⚠️ 静态资源上传前置检查
- 1. 相关资料
- 2. 抽取,创建模板变量
- 3. MCP 接口
- 4. 创建首页
- 5. 创建关于我们页面
- 6. 创建新闻列表页面
- 7. 修改导航栏菜单的链接网址
- 8. 设置全局变量
- 9. 模板标签公开基线白名单与上下文规则
- 10. 已确认规则与仍需确认的执行边界
- 11. 运行时确认操作指南
- 常见问题与避坑指南
- AI 自动执行的唯一闭环
阅读指南
| 读者类型 | 建议阅读路径 |
|---|---|
| 人工后台操作 | 第 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 读取并执行模板建站,但只把有当前运行时或明确源码依据的规则标为可执行。文档中的示例和历史说明不自动成为参数默认值。执行时必须遵守以下规则:
- 实际运行时 MCP 工具的
inputSchema/enum/ 返回结果决定“接口能否接受某个参数”;源码和本文档决定“当前业务是否应该使用该参数”。“schema 仍兼容”不等于“AI 可以继续新建时使用历史废弃值”。- 父级源码和帮助页只用于解释已核对的当前语义;存在版本差异时必须保留“待确认”状态。
/templateTag/*.do帮助页用于核对标签名称、适用页面、循环上下文和调用语法,但帮助页版本必须与目标运行时一致。- 本地未渲染 Markdown 是本文的 canonical 文本。在线 CMS 页面可能执行花括号标签或破坏转义,不能在未验证原样发布前作为机器执行依据。
- 遇到本文档写为“源码未定义”“无完整技术规范”或“需确认”的内容时,必须停止并请求依据,不得由 AI 自行补全。
- 禁止按照其他 CMS、Jinja、Django、Vue、WordPress 等系统经验推导网市场不存在的标签、枚举、输入模型代码或 DOM 协议。
- 本文自动执行入口是 MCP。
authHandle只能原样使用login.result=1时返回的值,并显式传给每个业务工具;不得用用户名、密码、上游token、session 或iwSID替代。- 每次响应先检查 MCP/传输错误,再检查业务
result。出现mcpError、isError=true、超时、连接中断或result != 1时停止当前依赖链;result=2时重新登录后只重试刚才失败的步骤。提交状态不明时不得盲目重试写操作。- 只有接口定义明确说明为 ID 的真实成功返回值才能传给后续 ID 参数。非数字信息、示例值、名称、
codeName或根据 URL 猜出的数字都不是 ID;当前 MCP 无查询能力且上下文没有真实值时必须暂停。- 模板标签唯一确认规则:只有目标运行时帮助页或一次真实生成结果确认某个标签及其上下文可用,AI 才能把它写入模板;帮助资料冲突且无法确认时必须暂停,不得回退、混用或猜测。WangMarket 6.1 例外:
{news.*}、{siteColumn.*}、{page.*}、{templatePath}已通过源码反编译确认可用(见第 10 章已确认表),6.1 版本可直接使用;动态调用标记(SiteColumn_Start/End、List_Start/End、SubColumnList_Start/End)内部字段及非 6.1 版本仍按本规则确认。- 上游 URL、
application/x-www-form-urlencoded、token、iwSID Cookie只属于 MCP Server 与 WangMarket 之间的实现核对信息,不是 AI 的执行步骤。AI 只调用 MCP 工具;不得直接请求上游 URL,也不得自行构造token、iwSID或 Cookie 去替代authHandle。- 本文所有可执行 JSON / HTML 示例中的 URL、文案、联系方式、账号、
codeName、ID、图片地址都是示例或占位值,不得原样提交到生产站点;必须先替换为用户、宿主或后台提供的真实值。- 静态资源强制检查规则:开始制作模板前,必须扫描用户上传的 HTML 模板中引用的所有本地静态资源(CSS、JS、图片、字体、视频等),如存在相对路径或本地路径引用,必须暂停流程,提醒用户上传到线上云存储或 FTP 并提供可访问 URL,验证 URL 可访问后替换模板中的本地路径为线上 URL,验证通过后方可继续。禁止将本地相对路径直接写入模板页面或模板变量(详见文首「静态资源上传前置检查」)。
原样发布要求:本文中的
{...}、HTML 和 JSON 示例必须使用 CMS 提供的原样代码保护方式,或在发布前实体编码。发布后必须重新抓取验证:代码块中的标签仍为字面文本,JSON 可独立解析,没有整篇正文嵌入、重复章节或丢失反斜杠。无法保证原样发布时,在线页面不得作为 AI 执行依据。当前最重要的版本结论:
TemplatePage.type0 = TYPE_ELSE / 其他;只有历史常量,无明确标准业务生成、绑定、预览路径;MCP 不使用1 = 首页模板;当前使用2 = 文章列表模板;当前使用3 = 文章详情模板;当前使用;关于我们等单页面也并入该模板类型6 = TYPE_ALONEPAGE / 旧独立页面模板;已废弃并入 type=3;MCP 不使用SiteColumn.type1 = TYPE_NEWS / 新闻信息;CMS 已废弃2 = TYPE_IMAGENEWS / 图文信息;CMS 已废弃3 = TYPE_PAGE / 旧版独立页面;仅历史兼容4 = TYPE_LEAVEWORD / 留言板;CMS 已废弃5 = TYPE_HREF / 超链接;CMS 已废弃6 = TYPE_TEXT / 纯文字栏目;CMS 已废弃7 = TYPE_LIST / 信息列表;当前 CMS 使用8 = TYPE_ALONEPAGE / 独立页面;当前 CMS 使用当前 AI/MCP 新建栏目只按业务使用:
新闻资讯等列表栏目 → SiteColumn.type = 7关于我们等独立页面栏目 → SiteColumn.type = 8因此“关于我们”的当前执行关系示例为:
TemplatePage.type = 3+SiteColumn.type = 8+SiteColumn.templatePageViewName = about+SiteColumn.editMode = 0(通过内容管理维护正文时)特别注意:
TemplatePage.type=3与SiteColumn.type=3不是同一含义。前者是当前详情页模板,后者只是旧版独立页面栏目兼容值;若目标运行时版本不同,必须以运行时 schema 和实际结果为准。
1. 相关资料
教程中的 HTML 原始模板
现有 HTML 模板共有三个页面:首页、关于我们、新闻列表。
这里,来演示将此 HTML 模板制作成网市场云建站系统所用模板的步骤。
为了方便 AI 直接读取、分析并根据本文档进行模板制作,本教程不再要求另外下载附件,下面直接提供原始模板中的三个 HTML 文件完整源代码:
index.html:首页about.html:关于我们news.html:新闻列表
⚠️ 第 1 章三段源码不可直接提交:仅作视觉与结构参考
下面三段是第三方原始模板的完整源码,其中的开发者姓名、QQ、微信、微信公众号、官网、GitHub、开源中国地址、交流 QQ 群号以及全部宣传文案,都是原模板自带的内容,不是本次建站的目标数据。
执行型 AI 不得把它们原样复制到生产站点:制作模板时只保留结构与样式,把文案、联系方式、链接全部替换为用户提供的真实值。第 2 章之后的每个可执行 JSON / HTML 示例同样如此(前置规则第 12 条)。
1.1 index.html 首页源代码
<!DOCTYPE HTML><html><head><meta charset="utf-8"><title>网·市场</title></head><body><!-- 每个页面都有的头部导航 --><nav style="text-align:center; font-size:26px;"><a href="index.html">首页</a><a href="about.html">关于我们</a><a href="news.html">新闻列表</a><hr/></nav><div><h2>hi,这是首页</h2></div><div> 网市场云建站系统,系统成熟、流程完善、细节精致、使用简单。极低的成本投入,30秒安装部署,选好模版一键导入。最快出网站,最快赚到钱。网市场云建站系统,历经8年,不断完善,拒绝半成品!注重实际业务应用,一切以建站公司的利益为主。</div><div><h3>交流反馈:</h3>开发者姓名:管雷鸣<br/>开发者QQ:921153866<br/>开发者微信:xnx3com<br/>开发者微信公众号:wangmarket<br/>交流QQ群:472328584<br/>官方网站:www.wang.market<br/>GitHub:github.com/xnx3/wangmarket<br/>开源中国:gitee.com/mail_osc/wangmarket<br/></div><!-- 每个页面都有的尾部 --><footer style="text-align:center; padding-top:30px;"><hr/>power by: wang.marketauthor: 管雷鸣QQ群:472328584</footer></body></html>
1.2 about.html 关于我们源代码
<!DOCTYPE HTML><html><head><meta charset="utf-8"><title>网·市场</title></head><body><!-- 每个页面都有的头部导航 --><nav style="text-align:center; font-size:26px;"><a href="index.html">首页</a><a href="about.html">关于我们</a><a href="news.html">新闻列表</a><hr/></nav><h1>关于我们</h1><div>网市场云建站系统,于09年开发wap系统建站。之后在xnx3、iw等基础上开发而来。于15年重新启动,<br/>16年开始试运行<br/>17年底正式开源发布!<br/>截止17年底:<br/> 共建立网站服务客户一千余个,经过市场及客户验证。而非一时兴起作出来扔网上开源后就不管的<br/>截止17年中旬,svn版本更新迭代837次、版本功能性升级57次!</div><!-- 每个页面都有的尾部 --><footer style="text-align:center; padding-top:30px;"><hr/>power by: wang.marketauthor: 管雷鸣QQ群:472328584</footer></body></html>
1.3 news.html 新闻列表源代码
<!DOCTYPE HTML><html><head><meta charset="utf-8"><title>网·市场</title></head><body><!-- 每个页面都有的头部导航 --><nav style="text-align:center; font-size:26px;"><a href="index.html">首页</a><a href="about.html">关于我们</a><a href="news.html">新闻列表</a><hr/></nav><h1>新闻列表</h1><ul><li><a href="about.html">v4.0升级了!</a></li><li><a href="about.html">v3.9升级了!</a></li><li><a href="about.html">v3.8.1升级了!</a></li><li><a href="about.html">v3.8升级了!</a></li><li><a href="about.html">v4.0升级了!</a></li><li><a href="about.html">v3.9升级了!</a></li><li><a href="about.html">v3.8.1升级了!</a></li><li><a href="about.html">v3.8升级了!</a></li><li><a href="about.html">v4.0升级了!</a></li><li><a href="about.html">v3.9升级了!</a></li></ul><div><!--这是分页--><a href="">首页</a><a href="">上一页</a><a href="">下一页</a><a href="">尾页</a></div><!-- 每个页面都有的尾部 --><footer style="text-align:center; padding-top:30px;"><hr/>power by: wang.marketauthor: 管雷鸣QQ群:472328584</footer></body></html>
2. 抽取,创建模板变量
创建模板变量的目的,如:
很多页面中都有头部导航,如果导航中要增加一项,那么有导航的每个页面也要挨个改过来,页面很多,太麻烦。而做成模板变量,可以只需要改动模板变量即可。
页面中都是调用模板变量,也就不用再每个页面都去改了。
2.1 查看 HTML 模板源代码
查看上面提供的 about.html、index.html、news.html 三个模板页面源代码,找到三个模板页面中都共同有的头部、尾部。
当然,这里不一定非得头部、尾部,这里只是把相同的地方找出来。
根据上面三个 HTML 文件,可以直接确认共同的头部导航代码为:
<!-- 每个页面都有的头部导航 --><nav style="text-align:center; font-size:26px;"><a href="index.html">首页</a><a href="about.html">关于我们</a><a href="news.html">新闻列表</a><hr/></nav>
共同的尾部代码为:
<!-- 每个页面都有的尾部 --><footer style="text-align:center; padding-top:30px;"><hr/>power by: wang.marketauthor: 管雷鸣QQ群:472328584</footer>
2.2 创建模板变量
将上面找到的相同的两处,分别保存成网市场云建站系统的模板变量。
登录当前网站的管理后台后,在左侧菜单中依次进入:
模板管理→ 模板变量
其中:
- 模板管理:左侧一级菜单;
- 模板变量:展开”模板管理”后显示的二级菜单。
点击”模板变量”后,即进入模板变量管理页面。
在创建或编辑模板变量时,页面中主要需要填写以下内容:
以头部导航为例,创建一个名为变量名备注模板变量代码
nav的模板变量。
填写方式:变量名:nav备注:通用头部导航模板变量代码:粘贴三个 HTML 页面中共同的头部导航代码
nav的模板变量代码为:
保存后,这段公共导航代码就成为一个名为<nav style="text-align:center; font-size:26px;"><a href="index.html">首页</a><a href="about.html">关于我们</a><a href="news.html">新闻列表</a><hr/></nav>
nav的模板变量。
同样的方法,再创建一个名为footer的模板变量。
填写方式:变量名:footer备注:通用页面底部模板变量代码:粘贴三个 HTML 页面中共同的尾部代码
footer的模板变量代码为:
保存后,共得到两个模板变量:<footer style="text-align:center; padding-top:30px;"><hr/>power by: wang.marketauthor: 管雷鸣QQ群:472328584</footer>
在模板变量页面中可以看到说明:模板页面中可以使用:navfooter
调用模板变量。{include=变量名}
因此,名为nav的模板变量,在模板页面中使用:
进行调用。{include=nav}
名为footer的模板变量,在模板页面中使用:
进行调用。{include=footer}
也就是说:
注:模板变量名字可以自己随便起名,限英文、数字、{include=nav}→ 调用上面保存的公共头部导航代码{include=footer}→ 调用上面保存的公共尾部代码
_(下划线)。
例如:
均符合命名要求。navfooterheadertop_navfooter_1
2.2.1 使用 MCP 创建模板变量
最新 MCP 文档已经定义:
save_template_var
用于创建或更新当前登录站点的公共模板变量。
因此,原来需要通过后台原生模板变量保存接口完成的 nav、footer 创建,现在如果 AI 已经连接网市场 MCP Server,可以直接调用 save_template_var 完成。
MCP 对应的上游接口为(仅作实现核对信息,不是 AI 的执行步骤;AI 只调用 MCP 工具):
POST /plugin/adminapi/site/saveTemplateVar.json
对应的 MCP 工具名称为:
save_template_var
调用 save_template_var 前,必须先通过:
login
登录成功,并取得有效:
authHandle
如果前面还没有登录,则先执行:
login→ result = 1→ 获取 authHandle
然后再创建模板变量。本文只讨论 MCP 调用;传统 HTTP 的 token 仅属于上游请求层,不得代替 authHandle。
2.2.2 save_template_var 参数说明
save_template_var 支持以下参数:
| 参数 | 是否必填 | 类型 | 含义 |
|—-|—-|—-|—-|
| authHandle | 是 | string | login 成功返回的不透明认证句柄 |
| varName | 是 | string | 模板变量代码,例如 nav、footer |
| id | 否 | integer/null | 省略、null 或 0 表示创建;大于 0 表示更新已有变量 |
| remark | 否 | string/null | 模板变量备注,仅用于后台管理和识别 |
| text | 协议可选;本流程必填 | string | 模板变量的完整 HTML 内容;每次调用会覆盖该变量原内容。创建页面会引用的变量时必须显式传入非空完整 HTML;省略会保存空内容。 |
其中最关键的是:
varName
它就是页面中:
{include=变量名}
所使用的变量代码。
例如:
varName = nav→ 页面中使用 {include=nav}varName = footer→ 页面中使用 {include=footer}
text 则是实际需要被替换进去的完整 HTML。
id 省略、传 null 或传 0 时接口按“新建”处理,不会按 varName 自动查找并覆盖已有变量。执行前必须确认 nav/footer 同名变量不存在;若已存在,只能取得并核验该变量的真实 ID 后按更新调用,ID 不明时停止,不得再次省略 id 创建副本。
2.2.3 通过 MCP 创建 nav
创建 nav 时调用:
save_template_var
⚠️ 不可直接提交:以下示例仅用于说明 JSON 结构。其中 index.html、about.html、news.html 是原始模板自带的相对链接,不是最终地址;文案、链接、数量都必须替换为用户提供的真实内容,最终导航须按第 7 章用真实 URL 重写。HTML 字符串必须由 JSON 编码器正确转义。
传参示例:
{"authHandle": "<login 返回的有效 authHandle>","varName": "nav","remark": "通用头部导航","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>"}
若此时尚未取得真实 URL,可按文末闭环第 3 步先保存不含猜测链接的最小导航,待第 8 步拿到真实 URL 后再按真实变量 ID 更新;不得用
about.html、news.html等示例路径充数。最小指导航仅保留结构、不含任何<a href>链接项,例如:
<nav style="text-align:center; font-size:26px;"><hr/></nav>它保证页面有完整 nav 结构但不输出错误链接;取得真实 URL 后必须按真实变量 ID 替换为完整导航。
参数对应关系:
authHandle→ login 成功后返回的认证句柄varName = nav→ 模板变量名称remark = 通用头部导航→ 后台备注text→ nav 的完整 HTML 代码如果是新建变量:
id可以省略,也可以传:
0不需要自行传:
useridsiteidtemplateName这些信息由当前登录站点状态自动确定。
正确返回结果应满足:
{"result": 1,"info": "123"}其中:
result = 1→ 模板变量保存成功info = "123"→ 示例中的模板变量 ID实际 ID 必须以接口真实返回值为准;只有
info能严格解析为大于 0 的模板变量 ID 时才保存,用于后续更新。若result=1但info为空或为非数字成功文本,变量可能已保存但当前 MCP 无法定位它,必须停止后续覆盖操作并由后台确认,不能猜 ID 或用id=0“更新”。
结果判断:
| 返回情况 | 是否正确 | 处理 |
|—-|—-|—-|
|result = 1且info为已确认的正整数 ID | 正确 |nav创建成功,保存真实 ID 后继续创建footer|
|result = 1但info不是有效 ID | 不完整 | 停止依赖该 ID 的更新操作,要求后台确认,避免重复创建 |
|result = 0| 不正确 | 模板变量保存业务失败,应查看info|
|result = 2| 不正确 | 未登录或authHandle已失效,需要重新login|
| 返回mcpError| 不正确 | MCP 适配器发生传输、协议、序列化或参数转换错误 |
创建成功后:
{include=nav}即可用于模板页面中引用该变量。
2.2.4 通过 MCP 创建
footer
nav保存成功以后,再次调用:
save_template_var创建
footer。
⚠️ 不可直接提交:原始模板里的 wang.market、作者名、QQ 群号等都是原模板自带内容;下面已统一改成占位符,执行前必须替换为用户提供的真实署名与联系方式(QQ 群号后续会按第 8 章改成 {var.qq})。
传参示例:
{"authHandle": "<login 返回的有效 authHandle>","varName": "footer","remark": "通用页面底部","text": "<footer style="text-align:center; padding-top:30px;">n<hr/>npower by: <用户提供的真实署名> nauthor: <用户提供的真实作者名> nQQ群:<用户提供的真实 QQ 群号> n</footer>"}
参数对应关系:
authHandle→ 与前面创建 nav 时使用同一个仍然有效的 authHandlevarName = footer→ 模板变量名称remark = 通用页面底部→ 后台备注text→ footer 的完整 HTML 代码
正确返回结果同样应满足:
{"result": 1,"info": "124"}
其中:
result = 1→ footer 保存成功info = "124"→ 示例中的模板变量 ID
实际 ID 以真实接口返回值为准;只有正整数 info 才能作为后续更新 id。
保存成功以后:
{include=footer}
即可在模板页面中调用该变量。
2.2.5 模板变量 MCP 调用的正确顺序
本流程要求:在调用 save_template_page_text 保存包含 {include=...} 的页面 HTML 之前,先创建对应模板变量并确认保存成功。 这是为了保证生成时有可替换内容;不要把“协议层 text 可选”理解成可以创建空变量继续流程。
因此,本教程正确的 MCP 顺序应为:
login↓确认 result = 1↓获得 authHandlesave_template_varvarName = navtext = nav 完整 HTML↓确认 result = 1save_template_varvarName = footertext = footer 完整 HTML↓确认 result = 1之后才能:save_template_page↓save_template_page_text
也就是说,不能先保存:
{include=nav}{include=footer}
到模板页面,再去创建变量。
正确顺序必须是:
先创建 nav、footer↓确认两个 save_template_var 都 result = 1↓再保存引用它们的 index.html / about.html / news.html
如果页面引用的变量不存在或内容为空,生成结果可能保留占位符或输出空内容;必须在生成前检查变量已成功保存。
而 generate_site 在生成网站时,会从当前站点模板变量缓存中读取与变量代码匹配的 text,再用实际 HTML 替换:
{include=nav}{include=footer}
因此:
save_template_var
不仅是在后台创建一条变量记录,同时还会:
写入 template_var写入 template_var_data刷新模板变量缓存记录操作日志
这一步必须在模板页面引用变量之前完成。
2.2.6 模板变量命名、嵌套、保留名与命名空间
父级源码确认模板变量本质上保存于:
template_var.var_name
引用格式固定为:
{include=变量名}
当前可以确定的规则:
- 模板变量名按本教程规则仅使用英文、数字、下划线
_;MCPvarName最大长度 20。 nav、footer只是推荐命名,不是系统强制保留名。- 当前父级源码中没有发现一份固定的模板变量系统保留名清单,因此不得伪造“保留变量列表”。
- 本自动流程不依赖模板变量嵌套。不同运行时可能循环展开
{include=...},旧资料又称嵌套不生效,行为存在版本冲突;需要多个公共片段时,统一在模板页面中分别调用。 - 严禁直接或间接循环引用(例如 A 引用 B、B 又引用 A),以免替换不终止或产生不可预测结果。模板变量内部是否支持非循环的
{include=...}必须按目标版本实测确认;{var.xxx}、通用标签和动态栏目调用仍按各自适用范围处理。
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 改动模板页面
上一步我们创建了两个模板变量 nav、footer,接下来,就可以将模板页面中的这两处改成动态调用模板变量。
将原来的公共头部导航代码替换为:
{include=nav}
将原来的公共尾部代码替换为:
{include=footer}
三个页面都同样如此。
修改后的 index.html:
<!DOCTYPE HTML><html><head><meta charset="utf-8"><title>网·市场</title></head><body>{include=nav}<div><h2>hi,这是首页</h2></div><div> 网市场云建站系统,系统成熟、流程完善、细节精致、使用简单。极低的成本投入,30秒安装部署,选好模版一键导入。最快出网站,最快赚到钱。网市场云建站系统,历经8年,不断完善,拒绝半成品!注重实际业务应用,一切以建站公司的利益为主。</div><div><h3>交流反馈:</h3>开发者姓名:管雷鸣<br/>开发者QQ:921153866<br/>开发者微信:xnx3com<br/>开发者微信公众号:wangmarket<br/>交流QQ群:472328584<br/>官方网站:www.wang.market<br/>GitHub:github.com/xnx3/wangmarket<br/>开源中国:gitee.com/mail_osc/wangmarket<br/></div>{include=footer}</body></html>
修改后的 about.html:
<!DOCTYPE HTML><html><head><meta charset="utf-8"><title>网·市场</title></head><body>{include=nav}<h1>关于我们</h1><div>网市场云建站系统,于09年开发wap系统建站。之后在xnx3、iw等基础上开发而来。于15年重新启动,<br/>16年开始试运行<br/>17年底正式开源发布!<br/>截止17年底:<br/> 共建立网站服务客户一千余个,经过市场及客户验证。而非一时兴起作出来扔网上开源后就不管的<br/>截止17年中旬,svn版本更新迭代837次、版本功能性升级57次!</div>{include=footer}</body></html>
修改后的 news.html:
<!DOCTYPE HTML><html><head><meta charset="utf-8"><title>网·市场</title></head><body>{include=nav}<h1>新闻列表</h1><ul><li><a href="about.html">v4.0升级了!</a></li><li><a href="about.html">v3.9升级了!</a></li><li><a href="about.html">v3.8.1升级了!</a></li><li><a href="about.html">v3.8升级了!</a></li><li><a href="about.html">v4.0升级了!</a></li><li><a href="about.html">v3.9升级了!</a></li><li><a href="about.html">v3.8.1升级了!</a></li><li><a href="about.html">v3.8升级了!</a></li><li><a href="about.html">v4.0升级了!</a></li><li><a href="about.html">v3.9升级了!</a></li></ul><div><!--这是分页--><a href="">首页</a><a href="">上一页</a><a href="">下一页</a><a href="">尾页</a></div>{include=footer}</body></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>中的编码声明,浏览器会使用默认编码解析,导致中文乱码。正确的模板页面结构示例:
<!DOCTYPE html><html><head><meta charset="utf-8"><title>页面标题</title></head><body>{include=nav}...页面内容...{include=footer}</body></html>详见本文档末尾「常见问题与避坑指南」中的问题2。
3. MCP 接口
本节 JSON 只是某一版本的 tools/list 定义快照,不是可直接发送的 MCP 请求,也不保证代表当前运行时。执行前必须重新读取运行时 tools/list;只使用实际返回且 schema 匹配的工具和字段。缺少当前分支必需的工具或字段时必须停止,不得按快照补造;未使用的可选工具不构成阻断。
上游 HTTP 层信息只作实现核对(前置规则第 11 条):本文任何位置出现的上游 URL、
application/x-www-form-urlencoded、token、iwSID Cookie、POST /plugin/...都只是 MCP Server 与 WangMarket 之间的实现说明,不是 AI 的执行步骤。除非用户明确要求传统 HTTP 调用,AI 只调用 MCP 工具,不得直接请求这些 URL,也不得自行构造token、iwSID或 Cookie 去替代authHandle。
{"jsonrpc": "2.0","id": "<echo-request-id>","result": {"resultType": "complete","ttlMs": 0,"cacheScope": "private","tools": [{"name": "login","title": "登录网市场站点","description": "使用用户名或邮箱与密码建立 WangMarket 上游应用认证状态。成功后返回 authHandle;后续每一个 WangMarket 业务工具调用都必须显式传入该 authHandle。MCP Server 通过 authHandle 从内部私有认证存储中解析上游 iwSID Cookie 并转发给 WangMarket,绝不向 MCP Client 暴露 iwSID Cookie 或上游 token。","inputSchema": {"type": "object","required": ["username", "password"],"additionalProperties": false,"properties": {"username": {"type": "string","minLength": 1,"description": "登录用户名或邮箱。MCP HTTP 适配器必须将其编码为上游表单字段 username。"},"password": {"type": "string","minLength": 1,"description": "登录密码。MCP Client 和 Server 不得在日志、工具摘要或普通文本回复中泄露该值。MCP HTTP 适配器必须将其编码为上游表单字段 password。"}}},"outputSchema": {"type": "object","required": ["result", "info"],"additionalProperties": true,"properties": {"result": {"type": "integer","enum": [0, 1, 2],"description": "上游 LoginVO/BaseVO 状态码。1=登录成功,0=登录业务失败,2=未登录或 WangMarket 上游应用认证状态无效。"},"info": {"type": "string","description": "上游登录结果说明。失败时可以直接作为面向用户的错误文本。"},"authHandle": {"type": ["string", "null"],"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、用户名或密码;不得尝试解析、修改或记录其完整值。"},"user": {"type": ["object", "null"],"description": "登录用户信息。服务端已过滤密码等敏感字段;字段集合可能随服务端版本变化。"},"parentAgency": {"type": ["object", "null"],"description": "当前用户的上级代理信息;没有上级代理时可能为空。"},"mcpError": {"type": ["object", "null"],"description": "仅 MCP 适配器自身失败时出现,不是上游 LoginVO 字段。","properties": {"kind": {"type": "string", "enum": ["transport", "protocol", "serialization", "adapter"]},"message": {"type": "string"}}}}}},{"name": "save_template_var","title": "保存模板变量","description": "创建或更新当前登录站点的公共模板变量。变量由 varName 和 text 组成:varName 是页面 HTML 中 {include=变量名} 的引用名,text 是生成整站时替换该占位符的完整 HTML。必须先成功保存变量,才保存引用它的页面 HTML。常见变量为 nav(导航)和 footer(页脚),但它们只是推荐名称,不是系统保留字。","inputSchema": {"type": "object","required": ["authHandle", "varName"],"additionalProperties": false,"properties": {"authHandle": {"type": "string","minLength": 1,"description": "login 成功返回的不透明认证句柄。每次调用都必须显式传入;MCP Server 用它解析内部保存的 WangMarket iwSID Cookie,不会将此字段发送给上游接口。"},"id": {"type": ["integer", "null"],"default": 0,"description": "模板变量主键。缺省、null 或 0 表示创建;大于 0 表示更新。更新时 ID 对应变量必须属于当前登录站点。"},"varName": {"type": "string","minLength": 1,"maxLength": 20,"description": "模板变量代码,例如 nav 或 footer。页面中必须通过完全相同的 {include=varName} 占位符引用,例如 {include=nav}。父级会对该值执行安全过滤。"},"remark": {"type": ["string", "null"],"maxLength": 30,"description": "变量备注,仅用于管理和识别;不会作为页面内容输出。父级会对该值执行安全过滤。"},"text": {"type": "string","default": "","description": "变量的完整 HTML 内容。每次调用都会覆盖该变量原内容;例如 nav 的导航片段或 footer 的页脚片段。"}}},"outputSchema": {"type": "object","required": ["result", "info"],"additionalProperties": true,"properties": {"result": {"type": "integer", "enum": [0, 1, 2], "description": "1=保存成功,0=业务失败,2=未登录或 authHandle 无效。"},"info": {"type": "string", "description": "保存成功时为模板变量 ID;失败时为父级返回的原因。"},"mcpError": {"type": ["object", "null"],"description": "仅 MCP 适配器发生 HTTP、协议、序列化或参数转换失败时出现。"}}}},{"name": "save_site_column","title": "创建或更新网站栏目","description": "使用同一个工具创建或更新网站栏目并绑定模板页面。父级历史常量:1=新闻信息(已废弃),2=图文信息(已废弃),3=旧版独立页面兼容,4=留言板(已废弃),5=超链接(已废弃),6=纯文字栏目(已废弃),7=信息列表(当前),8=独立页面(当前)。当前 MCP 新建业务只使用 7 或 8;schema 中若仍兼容 1/2/3,不代表 AI 应继续新建时使用。列表栏目填写 templatePageListName,独立页面填写 templatePageViewName。TemplatePage.type 与 SiteColumn.type 是不同字段。","inputSchema": {"type": "object","required": ["authHandle", "name", "type"],"additionalProperties": false,"properties": {"authHandle": {"type": "string", "minLength": 1, "description": "login 返回的不透明认证句柄。"},"id": {"type": ["integer", "null"], "default": 0, "description": "栏目 ID;缺省或 0 创建,大于 0 更新。"},"name": {"type": "string", "minLength": 1, "description": "栏目名称,例如 新闻动态、关于我们。"},"type": {"type": "integer", "enum": [1, 2, 3, 7, 8], "description": "当前接口兼容的 SiteColumn 类型值。1=新闻信息(历史废弃),2=图文信息(历史废弃),3=旧版独立页面兼容值,7=信息列表(当前使用),8=独立页面(当前使用)。父级历史 4=留言板、5=超链接、6=纯文字,但不在当前 MCP schema 中。AI 新建栏目只使用 7 或 8。"},"url": {"type": ["string", "null"], "description": "历史兼容 URL 字段,通常省略。"},"icon": {"type": ["string", "null"], "description": "栏目图标 URL,可选。"},"templatePageListName": {"type": ["string", "null"], "description": "列表栏目绑定的模板页面名称。"},"templatePageViewName": {"type": ["string", "null"], "description": "详情或独立页面栏目绑定的模板页面名称;关于我们应填写此前创建的详情模板(模板页面 type=3)。"},"codeName": {"type": ["string", "null"], "description": "CMS 栏目代码。需要按代码生成页面时显式传入真实值;它不是 URL。只有已确认目标站点 generateUrlRule=code 时,才能按当前运行时规则推导文件名;否则必须使用真实返回或后台确认的栏目 URL。"},"parentCodeName": {"type": ["string", "null"], "description": "CMS 父栏目代码,可选。"},"listNum": {"type": ["integer", "null"], "default": 10, "minimum": 1, "description": "信息列表每页条数。"},"inputModelCodeName": {"type": ["string", "null"], "description": "输入模型代码。省略、null、空字符串或字符串 "0" 表示不指定自定义模型;其他值必须是当前网站真实存在的 input_model.code_name。当前 MCP 没有输入模型查询工具,不得猜测 product、news、article 等代码,也不得把源码文件路径当作参数值。"},"editMode": {"type": ["integer", "null"], "enum": [0, 1, null], "default": 0, "description": "独立页面内容编辑方式;0=内容管理 UEditor 富文本,1=直接编辑模板。省略时插件接口对 type=8/3 默认按 0 处理;要修改父级自动创建的 News 内容必须使用 0。"},"listRank": {"type": ["integer", "null"], "enum": [1, 2, null], "default": 1, "description": "列表排序:1 发布时间倒序,2 发布时间正序。"},"editUseTitlepic": {"type": ["integer", "null"], "enum": [0, 1, null], "description": "内容管理是否显示标题图片/列表图上传区域;1=显示,0=隐藏。信息列表栏目(type=7)省略时默认为0,建议显式传1;独立页面(type=8)省略时插件默认补为1。"},"editUseIntro": {"type": ["integer", "null"], "enum": [0, 1, null], "description": "内容管理是否显示简介输入区域;1=显示,0=隐藏。信息列表栏目(type=7)省略时默认为0,建议显式传1;独立页面(type=8)省略时插件默认补为1。"},"editUseText": {"type": ["integer", "null"], "enum": [0, 1, null], "description": "内容管理是否显示正文输入;1=显示 UEditor 富文本区域,0=隐藏。**信息列表栏目(type=7)省略时默认为0,必须显式传1才能看到正文文本域**;独立页面(type=8)省略时插件接口默认补为1,显式传0才会隐藏。"},"editUseExtendPhotos": {"type": ["integer", "null"], "enum": [0, 1, null], "description": "内容管理是否显示图集输入。"},"useGenerateView": {"type": ["integer", "null"], "enum": [0, 1, null], "default": 1, "description": "是否生成内容页面,默认 1。"},"templateCodeColumnUsed": {"type": ["integer", "null"], "enum": [0, 1, null], "default": 1, "description": "模板栏目调用中是否显示,默认 1。"},"adminNewsUsed": {"type": ["integer", "null"], "enum": [0, 1, null], "default": 1, "description": "内容管理中是否显示该栏目,默认 1。"},"used": {"type": ["integer", "null"], "enum": [0, 1, null], "default": 1, "description": "栏目是否启用。"},"keywords": {"type": ["string", "null"], "description": "SEO 关键词,可选。"},"description": {"type": ["string", "null"], "description": "SEO 描述,可选。"}}},"outputSchema": {"type": "object", "required": ["result", "info"], "additionalProperties": true, "properties": {"result": {"type": "integer", "enum": [0, 1, 2]}, "info": {"type": "string"}, "mcpError": {"type": ["object", "null"]}}}},{"name": "save_news","title": "创建或更新新闻资讯内容","description": "使用同一个工具创建或更新信息列表栏目的新闻内容。创建时省略 id 或传 0;更新时传入已有 News.id。当前 MCP schema 在两种操作中都要求 cid,它必须是已确认属于当前站点的真实栏目 ID。保存成功后必须调用 generate_site;预览地址只能使用真实返回、已知上下文或后台确认的 URL。","inputSchema": {"type": "object","required": ["authHandle", "cid", "title", "text"],"additionalProperties": false,"properties": {"authHandle": {"type": "string", "minLength": 1, "description": "login 返回的不透明认证句柄。"},"id": {"type": ["integer", "null"], "default": 0, "description": "News.id;省略或 0 表示创建,大于 0 表示更新。"},"cid": {"type": "integer", "minimum": 1, "description": "新闻所属栏目 SiteColumn.id。仅当 save_site_column 的 result=1 且 info 可严格解析为已确认属于当前站点的大于 0 的栏目 ID 时使用;不能传非数字 info、栏目代码或模板页面 ID。"},"title": {"type": "string", "minLength": 1, "description": "新闻标题。"},"titlepic": {"type": "string", "default": "", "description": "标题图片 URL,可选。"},"intro": {"type": "string", "default": "", "description": "新闻简介,可选。"},"text": {"type": "string", "description": "新闻正文的完整 HTML。"}}},"outputSchema": {"type": "object", "required": ["result", "info"], "additionalProperties": true, "properties": {"result": {"type": "integer", "enum": [0, 1, 2]}, "info": {"type": "string"}, "mcpError": {"type": ["object", "null"]}}}},{"name": "save_alone_page_content","title": "保存独立页面栏目内容","description": "修改独立页面栏目自动创建的内容。仅当 cid 已确认属于当前站点、栏目类型为当前独立页面 type=8(或已确认兼容的历史 type=3)、SiteColumn.editMode=0,且该栏目确实只有一条目标内容时使用。底层按 cid 查询单条 News;若历史数据存在多条同 cid 记录,目标记录不确定,必须停止并由后台确认。保存后必须调用 generate_site,再使用真实 URL 预览。","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,可选。"}}},"outputSchema": {"type": "object", "required": ["result", "info"], "additionalProperties": true, "properties": {"result": {"type": "integer", "enum": [0, 1, 2]}, "info": {"type": "string"}, "mcpError": {"type": ["object", "null"]}}}},{"name": "save_template_page","title": "保存模板页面基本信息","description": "创建或更新当前登录站点的 TemplatePage 元数据。该工具不保存 HTML 正文;需要保存正文时,必须在页面存在后调用 save_template_page_text。MCP 接口只支持首页、列表页和详情页三种类型;关于我们等单页面使用详情页 type=3。","inputSchema": {"type": "object","required": ["authHandle", "name", "type"],"additionalProperties": false,"properties": {"authHandle": {"type": "string","minLength": 1,"description": "login 成功返回的不透明认证句柄。每次调用都必须显式传入。MCP Server 使用它解析内部保存的 WangMarket iwSID Cookie;不会将该字段发送给上游 saveTemplatePage 接口。"},"id": {"type": ["integer", "null"],"default": 0,"description": "模板页面主键。缺省、null 或 0 表示创建;大于 0 表示更新。更新时该 ID 对应的页面必须存在且属于当前站点。"},"name": {"type": "string","minLength": 1,"maxLength": 20,"description": "模板页面名称,也是 save_template_page_text 的 pageName 定位键,例如 index 或 about。父级会安全过滤该值;同一站点、同一模板下名称不可重复。"},"type": {"type": "integer","enum": [1, 2, 3],"description": "MCP 接口允许的 TemplatePage 类型:1=首页,2=新闻列表,3=新闻详情。关于我们等单页面统一使用 3。类型 1 在同一站点只能存在一个;0 和 6 不属于本 MCP 接口支持范围。"},"templateName": {"type": ["string", "null"],"description": "页面所属模板名称。创建时父级会无条件改为当前站点 site.templateName;更新时父级不会修改它。普通 AI 调用应省略该参数。"},"remark": {"type": ["string", "null"],"maxLength": 30,"description": "页面备注,建议填写便于后台识别,如'网站首页'、'关于我们独立页面'、'新闻列表页'。省略时后台备注列为空。父级会对该值执行安全过滤。"},"editMode": {"type": ["integer", "null"],"enum": [1, 2, null],"default": 2,"description": "TemplatePage 编辑模式:1=智能/可视化模式,2=代码模式。父级源码已标记可视化模式即将废弃、不建议使用;当前仅确认 iframe 编辑、在 </head> 前注入 htmledit.js、注入 htmledit_upload_url、保存时清理 XNX3HTMLEDIT 标记区和编辑器附加资源/属性。没有完整 DOM/API 规范,因此 AI/MCP 默认必须显式传 2。"}}},"outputSchema": {"type": "object","required": ["result", "info"],"additionalProperties": true,"properties": {"result": {"type": "integer", "enum": [0, 1, 2], "description": "1=保存成功,0=业务失败,2=未登录。"},"info": {"type": "string", "description": "保存成功时为模板页面 ID;失败时为父级返回的原因。"},"mcpError": {"type": ["object", "null"],"description": "仅适配器发生 HTTP、协议、序列化或参数转换失败时出现。"}}}},{"name": "save_template_page_text","title": "保存模板页面 HTML 内容","description": "按照 pageName 完全覆盖当前登录站点指定模板页面的 HTML 内容。必须先通过 save_template_page 创建页面,或确认目标页面已存在。","inputSchema": {"type": "object","required": ["authHandle", "pageName", "html"],"additionalProperties": false,"properties": {"authHandle": {"type": "string","minLength": 1,"description": "login 成功返回的不透明认证句柄。每次调用都必须显式传入。MCP Server 用它解析 WangMarket 上游认证状态;不会将该字段发送给上游 saveTemplatePageText 接口。"},"pageName": {"type": "string","minLength": 1,"description": "目标页面名称,对应 template_page.name,不是页面 ID。父级会安全过滤此值;它必须与已保存的页面名称一致。"},"html": {"type": "string","description": "完整 HTML 源码。每次保存会覆盖原内容。模板自带 CSS、JS、图片等资源必须使用 {templatePath}/相对路径引用,不得写死本地或云端模板域名。代码模式基本直接保存;可视化模式会清理编辑器标记区、编辑器附加资源及部分编辑属性,并按父级流程处理模板内容。"}}},"outputSchema": {"type": "object","required": ["result", "info"],"additionalProperties": true,"properties": {"result": {"type": "integer", "enum": [0, 1, 2], "description": "1=保存成功,0=业务失败,2=未登录。"},"info": {"type": "string", "description": "成功时通常为成功消息;失败时为页面不存在、变量不存在或其他父级错误原因。"},"mcpError": {"type": ["object", "null"],"description": "仅适配器失败时出现。"}}}},{"name": "generate_site","title": "生成整站 HTML","description": "根据当前登录站点的模板页面、模板变量、栏目和内容生成整站 HTML。工具没有业务输入参数。父级仅返回 BaseVO,不会返回 previewUrl;MCP Client 或 Host 如需预览,必须从已知站点上下文获取地址,不能编造返回字段。","inputSchema": {"type": "object","required": ["authHandle"],"additionalProperties": false,"properties": {"authHandle": {"type": "string","minLength": 1,"description": "login 成功返回的不透明认证句柄。每次调用都必须显式传入。MCP Server 用它解析 WangMarket 上游认证状态;不会将该字段发送给上游 generate 接口。"}}},"outputSchema": {"type": "object","required": ["result", "info"],"additionalProperties": true,"properties": {"result": {"type": "integer", "enum": [0, 1, 2], "description": "1=生成成功,0=业务失败,2=未登录。"},"info": {"type": "string", "description": "生成结果说明或失败原因。此字段不是预览 URL。"},"mcpError": {"type": ["object", "null"],"description": "仅适配器失败时出现。"}}}},{"name": "save_site_var","title": "创建或更新网站全局变量","description": "创建或更新当前网站的全局变量。全局变量在模板页面或模板变量中通过 {var.变量名} 引用,例如 {var.qq}。它与用于整段 HTML 的 {include=变量名} 模板变量完全不同,不能混用。QQ群号等普通文本使用 type=text;图片使用 type=image;固定选项使用 type=select。","inputSchema": {"type": "object","required": ["authHandle", "name"],"additionalProperties": false,"properties": {"authHandle": {"type": "string", "minLength": 1, "description": "login 成功返回的不透明认证句柄。MCP Server 用它解析 WangMarket 上游 iwSID 状态,不会将该字段写入 site_var。"},"updateName": {"type": "string", "default": "", "description": "修改前的变量名。新建时留空;同名修改时可与 name 相同;重命名时填写旧名称,name 填新名称。"},"name": {"type": "string", "minLength": 1, "description": "变量代码,只使用稳定简短的英文或数字,例如 qq、logo。模板引用格式为 {var.name}。"},"description": {"type": "string", "default": "", "description": "给非技术用户看的详细填写说明。应注明用途、建议字数、图片尺寸、文件格式或下拉选项含义,例如“QQ群号,只填写数字,不要填写QQ群:前缀”。"},"value": {"type": "string", "default": "", "description": "变量初始值。text 为普通文本,image 为图片 URL,select 为 valueItems 中某个选项的值。"},"type": {"type": "string", "enum": ["text", "image", "select"], "default": "text", "description": "录入类型:text 文本、image 单图片、select 下拉选择。"},"title": {"type": "string", "default": "", "description": "后台全局变量管理页面显示的标题。"},"valueItems": {"type": "string", "default": "", "description": "type=select 时的完整选项定义;当前 6.1 后台解析格式为每行 值:显示文本。非 select 类型留空。若目标运行时版本不同,必须先在后台确认格式,不能改用猜测的分隔符。"}}},"outputSchema": {"type": "object","required": ["result", "info"],"additionalProperties": true,"properties": {"result": {"type": "integer", "enum": [0, 1, 2], "description": "1=保存成功,0=业务失败,2=未登录或认证状态无效。"},"info": {"type": "string", "description": "父级保存结果说明。"},"mcpError": {"type": ["object", "null"], "description": "仅 MCP 适配器自身失败时出现。"}}}},{"name": "save_site_var_value","title": "修改网站全局变量值","description": "仅修改已存在网站全局变量的值,不改变变量名称、类型、标题、说明或下拉选项。适合后续修改QQ群号、联系电话等内容;变量不存在时必须先调用 save_site_var 创建。修改后仍需调用 generate_site 发布静态页面。","inputSchema": {"type": "object","required": ["authHandle", "name", "value"],"additionalProperties": false,"properties": {"authHandle": {"type": "string", "minLength": 1, "description": "login 成功返回的不透明认证句柄。"},"name": {"type": "string", "minLength": 1, "description": "已存在的全局变量代码,例如 qq;必须与模板中的 {var.qq} 保持一致。"},"value": {"type": "string", "description": "新的变量值。image 类型填写图片 URL,select 类型填写已配置选项的值。"}}},"outputSchema": {"type": "object","required": ["result", "info"],"additionalProperties": true,"properties": {"result": {"type": "integer", "enum": [0, 1, 2]},"info": {"type": "string"},"mcpError": {"type": ["object", "null"]}}}},{"name": "save_template","title": "创建或绑定网站模板","description": "尝试补齐当前网站 site.template_id 对应的 template 记录。该实现可能在 template_id 无效时使用 ID 1,可能创建或修改既有模板,且 template_id 已指向现存记录时不会重新绑定到其它模板。result=1 只表示本次接口执行成功,不证明模板页面归属、后台生成按钮或最终预览已经正确;调用前必须确认允许其影响现有模板,调用后仍需生成和真实预览验证。","inputSchema": {"type": "object","required": ["authHandle"],"additionalProperties": false,"properties": {"authHandle": {"type": "string", "minLength": 1, "description": "login 成功返回的不透明认证句柄。每次调用都必须显式传入。MCP Server 用它解析 WangMarket 上游认证状态;不会将该字段发送给上游 saveTemplate 接口。"},"name": {"type": "string", "default": "自定义模板", "description": "模板名称,可选,默认「自定义模板」。当模板不存在需要创建时使用此名称;模板已存在时,若传入非默认值则更新名称。"},"remark": {"type": "string", "default": "", "description": "模板备注,可选,默认空字符串。当模板不存在需要创建时使用此备注;模板已存在时,若传入非空值则更新备注。"}}},"outputSchema": {"type": "object","required": ["result", "info"],"additionalProperties": true,"properties": {"result": {"type": "integer", "enum": [0, 1, 2], "description": "1=保存成功,0=业务失败,2=未登录或认证状态无效。"},"info": {"type": "string", "description": "成功时为模板 ID;失败时为错误原因。"},"mcpError": {"type": ["object", "null"], "description": "仅 MCP 适配器自身失败时出现。"}}}}]}}
4. 创建首页
4.1 创建首页的模板页面
网市场云建站系统中,新建一个模板页面,然后将上面已经改成 {include=nav}、{include=footer} 调用方式的 index.html 源代码直接复制到新建立的首页模板页面中,保存即可。
操作过程可以理解为:
模板管理→ 模板页面→ 新建模板页面→ 创建首页模板页面→ 粘贴修改后的 index.html 源代码→ 保存
人工后台操作和 MCP 自动操作是两条互斥路径。使用 MCP 时只调用工具,不模拟后台点击;使用人工路径时按后台页面操作,不把点击结果当作 MCP 返回值。
如果当前 AI 已连接 MCP Server,则创建首页模板页面可以按照下面的 MCP 调用顺序执行。
4.1.1 第一步:调用 login 登录网市场站点
在没有有效 authHandle 的情况下,必须先调用:
login
需要传入两个参数:
| 参数 | 是否必填 | 类型 | 含义 | 首页创建时如何传 |
|—-|—-|—-|—-|—-|
| username | 是 | string | 网市场登录用户名或邮箱 | 传用户实际登录用户名或邮箱 |
| password | 是 | string | 网市场登录密码 | 传用户实际登录密码 |
传参示例:
{"username": "user@example.com","password": "<用户实际登录密码>"}
这里的密码只作为 MCP 工具调用参数使用,不能输出到普通回复、日志、工具摘要或其他持久文本中。login 调用完成后,重点检查返回结果中的:
resultinfoauthHandle
正确结果应满足:
{"result": 1,"info": "<登录成功信息>","authHandle": "<MCP Server 返回的不透明认证句柄>"}
判断规则:
| 返回情况 | 是否正确 | 后续处理 |
|—-|—-|—-|
| result = 1,且返回有效 authHandle | 正确 | 可以继续调用 save_template_page |
| result = 0 | 不正确 | 登录业务失败,停止后续操作,并查看 info |
| result = 2 | 不正确 | 未登录或上游认证状态无效,需要重新登录 |
| 返回 mcpError | 不正确 | 属于 MCP 传输、协议、序列化或适配器错误,应先处理该错误 |
authHandle 是后续业务调用必须使用的不透明认证句柄。MCP Client 不应获取或传递网市场上游的 iwSID Cookie,也不能使用用户名、密码或其他 token 代替 authHandle。
4.1.2 第二步:调用 save_template_page 创建首页模板页面
登录成功并取得有效 authHandle 后,调用:
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 调用应省略 | 创建时系统会自动使用当前站点的模板名称 |
完整传参示例:
{"authHandle": "<login 返回的 authHandle>","name": "index","type": 1,"remark": "首页模板","editMode": 2}
这里没有传:
idtemplateNamesiteiduserid
原因是:
id 省略→ 表示新建页面templateName→ 普通 AI 创建时应省略,由当前站点自动确定siteid、userid→ 当前 MCP 工具参数中没有这两个字段,不能自行添加
其中:
type = 1
明确表示首页。同一站点只能存在一个首页模板,因此如果当前站点已经存在首页模板,再次创建可能返回业务失败。
这里同时记录父级 TemplatePage 的完整历史常量边界,避免 AI 以后看到 0 或 6 时自行猜测:
| type | 父级常量/含义 | 当前结论 | AI/MCP 规则 |
|---|---|---|---|
0 | TYPE_ELSE / 其他 | 源码只标注“其他”;保存方法没有专门业务处理,标准生成服务也没有明确的生成、绑定、预览路径 | 禁止用于当前 MCP 建站 |
1 | 首页模板 | 当前标准模板类型 | 使用 |
2 | 文章列表模板 | 当前标准模板类型 | 使用 |
3 | 文章详情模板 | 当前标准模板类型;单页面已并入详情模板 | 使用 |
6 | TYPE_ALONEPAGE / 独立页面模板 | 父级注释:单页面如关于我们,废弃,并入详情页模板 | 禁止新建;改用 type=3 |
type=0 的正确文档结论不是为它臆造一个业务场景,而是:历史上它表示“其他”,当前没有标准业务路径,MCP 不使用。
调用成功时,正确结果应类似:
{"result": 1,"info": "123"}
其中:
result = 1→ 保存成功info = "123"→ 示例中的模板页面 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 创建成功后,再调用:
save_template_page_text
保存首页完整 HTML。
需要传入:
| 参数 | 是否必填 | 类型 | 首页示例值 | 含义 |
|—-|—-|—-|—-|—-|
| authHandle | 是 | string | <login 返回的 authHandle> | 当前有效认证句柄 |
| pageName | 是 | string | index | 目标模板页面名称,必须与前面 save_template_page.name 完全一致 |
| html | 是 | string | 第 2.3 节修改后的完整 index.html | 要保存的完整 HTML 源码 |
传参结构示例(占位符不能原样提交):
{"authHandle": "<login 返回的 authHandle>","pageName": "index","html": "<这里必须传入第 2.3 节修改后的 index.html 完整源码>"}
实际调用时,html 不能只传上面的占位说明,而应把第 2.3 节中已经完成:
{include=nav}{include=footer}
替换后的 完整 index.html 源码 作为字符串传入。pageName 必须为:
index
因为前一步创建页面时使用的是:
{"name": "index"}
两者对应关系:
save_template_page.name = index↓save_template_page_text.pageName = index
调用成功时,正确结果应满足:
{"result": 1,"info": "<保存成功信息>"}
结果判断:
| 返回情况 | 是否正确 | 含义与处理 |
|—-|—-|—-|
| result = 1 | 正确 | index 模板页面 HTML 已保存成功 |
| result = 0 | 不正确 | 业务失败,检查 info;可能是页面不存在、模板变量不存在或模板内容保存失败 |
| result = 2 | 不正确 | 认证状态失效,需要重新 login |
| 返回 mcpError | 不正确 | MCP 适配器自身错误 |
需要特别注意:
save_template_page_text
每次保存都会完整覆盖目标模板页面原有 HTML,不是追加。
同时,该工具不会自动创建页面。如果:
pageName = index
对应的模板页面不存在,则保存会失败。
因此首页创建的正确 MCP 顺序是:
login→ 获得 authHandle→ save_template_page→ 创建 name=index、type=1 的首页模板页面→ save_template_page_text→ 向 pageName=index 写入完整 index.html
4.2 生成整站,预览成果
人工路径可以点击 生成整站 并在后台预览。MCP 路径只调用工具,生成和预览必须分开确认。
人工操作顺序:
保存首页模板页面→ 生成整站→ 生成网站静态 HTML 页面→ 预览网站
如果使用 MCP,在 save_template_page_text 返回成功后,先确认当前站点是否已经绑定有效 template。只有绑定缺失且用户已授权其潜在副作用时,才调用 save_template;确认绑定有效时不要重复调用。之后才能调用:
generate_site
生成整站。
重要提醒:首次生成整站前只有在模板绑定缺失时才考虑调用 save_template;调用成功不等于绑定状态已经验证。
后台点击「生成整站」时,系统会校验当前网站是否已绑定有效模板(site.template_id 对应 template 表中存在记录)。如果 template 表为空或 site.template_id 指向不存在的模板,会提示:
当前网站尚未选择/导入/增加模版,生成失败!网站有模版后才能根据模版生成整站!
注意:通过 MCP 接口 generate_site(对应上游 /template/refreshForTemplate.do)生成时,可能不校验 template 表绑定,直接根据站点的模板页面生成,因此可能出现”MCP 能生成但后台按钮不能生成”的情况。
处理方式:MCP 当前没有查询模板绑定的工具;只有用户、宿主或后台提供了绑定状态,才能判断是否缺失。确认绑定缺失且用户授权其副作用后,调用 MCP 工具 save_template(对应上游 /plugin/adminapi/site/saveTemplate.json);确认 result=1 后仍需后台复核,再生成。该工具的边界和副作用见 FAQ;不得仅凭 result=1 宣称站点绑定已验证。
调用示例:
{"authHandle": "<login 返回的有效 authHandle>"}
正确返回:
{"result": 1,"info": "1"}
其中 info 的具体含义以当前运行时 schema 为准;不要把它当作已经验证的站点绑定证明。
调用成功后仍需按当前运行时或后台确认模板绑定;不能保证后台按钮在所有已有数据状态下都正常工作。
详见本文档末尾「常见问题与避坑指南」中的问题1。
4.2.1 generate_site 传参
当前 MCP 文档中,generate_site 只需要一个业务参数:
| 参数 | 是否必填 | 类型 | 示例值 | 含义 |
|—-|—-|—-|—-|—-|
| authHandle | 是 | string | <login 返回的 authHandle> | 当前有效登录认证句柄 |
传参示例:
{"authHandle": "<login 返回的 authHandle>"}
调用关系:
login→ authHandlesave_template_page→ result = 1save_template_page_text→ result = 1确认模板绑定;仅在绑定缺失且已获授权时调用 save_template→ result = 1 后仍需后台复核generate_site→ 使用同一个仍然有效的 authHandle
4.2.2 generate_site 正确结果与错误结果
生成成功时,正确结果应满足:
{"result": 1,"info": "<生成结果说明>"}
判断规则:
| 返回情况 | 是否正确 | 结果 |
|—-|—-|—-|
| 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。
因此下面这种假设是不正确的:
{"result": 1,"previewUrl": "https://example.com/index.html"}当前 MCP 文档明确说明,生成整站的返回结果中没有
previewUrl字段。
因此:
generate_site 返回 result = 1→ 只能确认生成调用返回成功需要预览网站→ 必须从已知站点上下文取得网站实际访问地址→ 不能由 AI 根据 generate_site 返回值自行编造预览网址使用 MCP 完成首页创建与生成整站后,保存/生成状态流程为:
login→ result = 1→ 获得 authHandlesave_template_page→ name = index→ type = 1→ result = 1save_template_page_text→ pageName = index→ html = 完整 index.html→ result = 1确认绑定状态;必要且获授权时调用 save_template→ result = 1 后仍需绑定复核generate_site→ authHandle→ result = 1最终结果→ 首页模板页面已经创建→ 首页 HTML 已写入→ 生成调用返回成功→ 预览仍需使用真实站点基础 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|
对于”关于我们”页面,最核心的两个标签是:
{news.title}→ 调出当前关于我们内容的标题{news.text}→ 调出当前关于我们内容的正文 HTML因此,原始
about.html中原本写死的:
<h1>关于我们</h1><div>网市场云建站系统,于09年开发wap系统建站。之后在xnx3、iw等基础上开发而来。于15年重新启动,<br/>16年开始试运行<br/>17年底正式开源发布!<br/>截止17年底:<br/> 共建立网站服务客户一千余个,经过市场及客户验证。而非一时兴起作出来扔网上开源后就不管的<br/>截止17年中旬,svn版本更新迭代837次、版本功能性升级57次!</div>可以在制作详情页模板时改成:
<h1>{news.title}</h1><div>{news.text}</div>如果页面还需要显示简介、列表图、发布时间等信息,也可以继续使用(字段必须由当前帮助页/运行时确认):
{news.intro}{news.titlepic}{news.addtime}或更细的时间标签:
{news.addtime.year}{news.addtime.month}{news.addtime.day}{news.addtime.hour}{news.addtime.minute}如果后续使用自定义扩展字段,则使用:
{news.extend.???}其中
???应替换为实际已经存在的扩展字段名,不能凭空编造字段名。{news.extend.photos}也不是每篇内容都必然存在;只有当前站点的真实输入模型和内容记录已经定义并填充该字段时才能使用。当前save_news工具没有photos参数,不得据此编造上传或扩展字段接口。月份、日期是否补前导零同样以当前运行时实测为准,需要固定两位时由模板或前端格式化。
如果使用当前 MCP 接口,可以通过:
save_template_page→ save_template_page_text完成”关于我们”模板页面本身的创建和 HTML 保存。
如果前面创建首页时取得的authHandle仍然有效,可以继续使用,不需要重复登录;如果任何业务工具返回:
result = 2则说明认证状态已经无效,需要重新调用
login获取新的authHandle。5.1.1 调用
save_template_page创建关于我们模板页面最新 MCP 文档已经明确:
MCP 接口只支持首页、列表页和详情页三种类型其中:
type = 1→ 首页type = 2→ 新闻列表type = 3→ 详情页并且最新 MCP 文档明确规定:
关于我们等单页面统一使用 type = 3因此,”关于我们”通过 MCP 创建模板页面时,必须使用:
type = 3不能再使用旧版本中的:
type = 6父级源码已经把
TYPE_ALONEPAGE = 6标记为:
单页面如关于我们,废弃,并入详情页模板
因此这里不是“暂时不推荐 6”,而是当前模型层已经把独立页面模板职责并入 type=3。最新 MCP 接口的 type 参数只允许:
123
0 和 6 均不属于当前 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 创建时不应自行设置,由当前站点自动确定 |
传参示例:
{"authHandle": "<有效 authHandle>","name": "about","type": 3,"remark": "关于我们","editMode": 2}
各参数对应关系:
authHandle→ 使用 login 成功后返回的认证句柄name = about→ 将当前模板页面命名为 about→ 后续 save_template_page_text.pageName 也必须传 abouttype = 3→ 当前 MCP 定义的详情页类型→ 关于我们等单页面统一使用该值remark = 关于我们→ 只是页面备注,用于后台识别editMode = 2→ 使用代码模式保存页面
普通创建时不要额外传:
siteiduseridtemplateName
其中 siteid、userid 由当前登录状态自动确定;templateName 在普通 AI 调用时应省略。
创建成功时,正确结果应类似:
{"result": 1,"info": "456"}
其中:
result = 1→ 模板页面基本信息保存成功info = "456"→ 示例中的模板页面 ID
这里的 456 只是示例,实际模板页面 ID 必须以 MCP 接口真实返回值为准;保存正文时仍使用精确 pageName=about,不能把该 ID 传给 save_template_page_text。
结果判断:
| 返回情况 | 是否正确 | 处理 |
|—-|—-|—-|
| result = 1 | 正确 | 关于我们模板页面基本信息创建成功,可以继续保存 about.html |
| result = 0 | 不正确 | 业务失败,直接查看 info;可能是页面名称重复、保存失败等 |
| result = 2 | 不正确 | 当前认证状态失效,停止后续调用并重新执行 login |
| 返回 mcpError | 不正确 | MCP 适配器自身发生传输、协议、序列化或参数转换错误 |
因此这一阶段正确的调用关系是:
save_template_pageauthHandle = 有效认证句柄name = abouttype = 3remark = 关于我们editMode = 2↓result = 1↓取得 info 中返回的模板页面 ID↓继续保存 HTML 正文
5.1.2 调用 save_template_page_text 保存 about.html
关于我们模板页面创建成功后,调用:
save_template_page_text
参数为:
| 参数 | 是否必填 | 类型 | 关于我们示例值 | 含义 |
|—-|—-|—-|—-|—-|
| authHandle | 是 | string | <有效 authHandle> | 当前认证句柄 |
| pageName | 是 | string | about | 必须与前一步 name=about 完全一致 |
| html | 是 | string | 第 2.3 节修改后的完整 about.html | 关于我们页面完整 HTML |
传参示例:
{"authHandle": "<有效 authHandle>","pageName": "about","html": "<这里必须传入第 2.3 节修改后的 about.html 完整源码>"}
实际调用时:
html
应传入已经完成详情页模板化处理后的完整 about.html 源码(WangMarket 6.1 已确认详情页 {news.*} 可用,源码 replaceNewsTag() 主动替换)。其中应包含:
{include=nav}{news.title}{news.text}{include=footer}
跨版本注意:6.1 版本详情页
{news.title}/{news.text}已确认可用。若目标版本不是 6.1,帮助页details.jsp表格的”不可用”标注可能生效,应按 11.1 实测确认。
也就是说,除了将公共头尾改成:
{include=nav}{include=footer}之外,还应将原本写死的”关于我们”标题和正文分别替换为:
{news.title}{news.text}然后再把这份完整
about.html作为html参数传入。
对应关系必须保持:
save_template_page.name = about↓save_template_page_text.pageName = about也就是说,不能创建时使用:
name = about保存 HTML 时却改成其他:
pageName否则系统无法正确找到目标模板页面。
保存成功时,正确结果应满足:
{"result": 1,"info": "<保存成功信息>"}判断规则:
| 返回情况 | 是否正确 | 处理 |
|—-|—-|—-|
|result = 1| 正确 | 关于我们模板页面 HTML 保存成功 |
|result = 0| 不正确 | 检查info;可能是页面不存在、变量不存在或模板内容保存失败 |
|result = 2| 不正确 | 认证状态失效,需要重新执行login|
| 返回mcpError| 不正确 | 先处理 MCP 适配器错误 |
完成以后,MCP 能确认的结果是:
name = abouttype = 3的详情页模板页面已经创建+about.html 完整模板 HTML 已保存因此,关于我们模板页面这一阶段完整 MCP 调用流程为:
已有有效 authHandle↓save_template_pagename = abouttype = 3remark = 关于我们editMode = 2↓确认 result = 1↓save_template_page_textpageName = abouthtml = 完整 about.html↓确认 result = 1当前完整 MCP 已经定义:
save_site_columnsave_alone_page_content因此后续 5.2 可以通过
save_site_column创建并绑定“关于我们”独立页面栏目;只有当前实现已由后台/运行时确认自动生成且唯一的目标内容时,5.3 才能通过save_alone_page_content修改它。若实际连接到的 MCP Server 缺少这些工具,则以运行时工具列表为准,不得自行虚构调用。5.2 创建”关于我们”栏目
创建一个栏目,栏目名为”关于我们”,并给此栏目选上刚创建的”关于我们”详情页模板页面。
后台操作关系:
创建"关于我们"详情页模板→ 创建"关于我们"栏目→ 栏目类型选择独立页面→ 给栏目选择刚创建的 about 详情页模板→ 保存如果当前 AI 已连接最新 MCP Server,则可以直接调用:
save_site_column创建”关于我们”栏目,并绑定前面已经创建好的
about详情页模板。5.2.1
save_site_column参数说明与SiteColumn.type完整历史定义
父级 SiteColumn.java 已给出栏目类型的完整历史定义。这里必须把“历史常量”和“当前 AI 应使用的值”分开理解:
| type | 常量 | 准确含义 | 当前状态 | AI/MCP 新建规则 |
|---|---|---|---|---|
1 | TYPE_NEWS | 新闻信息 | CMS 已废弃 | 不使用 |
2 | TYPE_IMAGENEWS | 图文信息 | CMS 已废弃 | 不使用 |
3 | TYPE_PAGE | 独立页面 | 旧版本兼容 | 不作为新建首选 |
4 | TYPE_LEAVEWORD | 留言板 | CMS 已废弃 | 当前 MCP 不使用 |
5 | TYPE_HREF | 超链接 | CMS 已废弃 | 当前 MCP 不使用 |
6 | TYPE_TEXT | 纯文字栏目 | CMS 已废弃 | 当前 MCP 不使用 |
7 | TYPE_LIST | 信息列表 | 当前 CMS 使用 | 新闻、产品、案例等列表栏目使用 |
8 | TYPE_ALONEPAGE | 独立页面 | 当前 CMS 使用 | 关于我们、联系我们等单页面栏目使用 |
因此当前 MCP 新建业务固定按下列规则:
新闻资讯等信息列表栏目 → SiteColumn.type = 7关于我们等独立页面栏目 → SiteColumn.type = 8
即使运行时 schema 仍兼容 1、2、3,也只表示历史兼容能力,不能据此让 AI 在新站点继续使用废弃栏目类型。4/5/6 属于父级历史常量,但不在当前 MCP schema 中,更不得传入。
创建“关于我们”时的主要参数如下:
| 参数 | 是否必填 | 类型 | 关于我们示例值 | 含义 |
|---|---|---|---|---|
authHandle | 是 | string | <有效 authHandle> | login 成功返回的认证句柄 |
name | 是 | string | 关于我们 | 栏目名称 |
type | 是 | integer | 8 | 当前独立页面栏目 |
id | 否 | integer/null | 省略或 0 | 创建新栏目;大于 0 表示更新 |
templatePageViewName | 本流程必填 | string/null | about | 必须与已成功保存 HTML 的详情模板页面名称完全一致 |
codeName | 条件必填 | string/null | about | 栏目代码示例,不是预览 URL;仅在需要动态栏目调用或目标运行时要求按代码生成时才传入,且值必须是当前站点已确认存在的栏目代码;仅创建栏目且无上述需求时可按 schema 省略,省略后不得自行推导栏目 URL |
inputModelCodeName | 否 | string/null | 省略 | 不指定自定义输入模型;若传其它值,必须先确认当前站点存在该 input_model.code_name |
editMode | 本流程必填 | integer/null | 0 | 必须为内容管理模式,供 save_alone_page_content 更新正文 |
editUseText | 否 | integer/null | 1 | 内容管理中显示正文输入 |
used | 否 | integer/null | 1 | 启用栏目 |
adminNewsUsed | 否 | integer/null | 1 | 在内容管理中显示该栏目 |
useGenerateView | 否 | integer/null | 1 | 生成内容页面 |
codeName的统一使用规则(适用本教程所有save_site_column调用,含 5.2 与 6.2):codeName在需要动态栏目调用或目标运行时要求代码生成时才传入;值必须是当前站点已确认存在的栏目代码。仅创建栏目且没有上述需求时可按 schema 省略;省略后不得自行推导栏目 URL。本教程中的about、news仅为栏目代码格式示例;执行时必须替换为目标站点真实存在且已确认的 codeName,不得直接使用示例值。
其中最关键的对应关系为:
TemplatePage.name = aboutTemplatePage.type = 3→ 详情页模板SiteColumn.name = 关于我们SiteColumn.type = 8SiteColumn.templatePageViewName = aboutSiteColumn.editMode = 0→ 当前独立页面栏目,通过内容管理维护唯一内容
不要混淆:
TemplatePage.type = 3→ 当前文章详情模板SiteColumn.type = 3→ 旧版独立页面栏目兼容值
两个 type 来自不同数据对象,数字相同不代表语义相同。
关于 inputModelCodeName:省略、null、空字符串或字符串 "0" 表示不指定自定义输入模型;其它值必须是当前网站真实存在的 input_model.code_name。当前 MCP 没有输入模型查询工具,因此没有后台或已有上下文依据时只能省略,不得猜测 product、news、article,也不得把源码资源路径当成参数值。
5.2.2 创建”关于我们”栏目的 MCP 传参实例
推荐传参:
{"authHandle": "<有效 authHandle>","name": "关于我们","type": 8,"templatePageViewName": "about","codeName": "about","editMode": 0,"editUseText": 1,"used": 1,"adminNewsUsed": 1,"useGenerateView": 1}
最新 MCP 对 save_site_column 还明确规定了上游请求编码方式(仅作实现核对信息;AI 只调用 MCP 工具,不直接发 HTTP 请求):
POST /plugin/adminapi/site/column/save.jsonContent-Type: application/x-www-form-urlencoded
这里要区分 MCP 工具调用参数 和 MCP Server 转发给 WangMarket 上游的 HTTP 请求:
AI / MCP Client→ 正常向 save_site_column 传结构化 argumentsMCP Server→ 将 arguments 转换为表单字段→ 使用 application/x-www-form-urlencoded 提交给 WangMarketWangMarket 上游→ 接收 SiteColumn 对应的表单字段
因此,AI 调用 MCP 工具时仍然可以按照上面的结构化参数传值;但 MCP Server 不能把整个参数对象直接作为 application/json 转发给上游接口。
另外:
authHandle
只用于 MCP 认证层,不会映射为 SiteColumn 业务字段,也不能被当作栏目字段提交给 WangMarket。
参数解释:
name = 关于我们→ 后台栏目名称type = 8→ 独立页面栏目templatePageViewName = about→ 绑定前面创建好的 about 详情页模板codeName = about→ 栏目代码,仅为格式示例,执行时必须替换为目标站点真实存在且已确认的值→ 不是栏目网址;预览地址取决于当前站点生成 URL 规则→ 若本栏目不需要动态调用且目标运行时不要求按代码生成,可按 schema 省略;省略后不得推导 URLeditMode = 0→ 内容通过内容管理中的 UEditor 富文本方式编辑→ 独立页面省略时,插件默认按 0 处理→ 要修改系统自动创建的唯一 News 内容必须使用 0→ 为避免歧义,建议 MCP 调用始终显式传 0editUseText = 1→ 内容管理中显示正文输入 / UEditor 富文本区域→ 独立页面省略时,插件默认补为 1→ 为避免歧义,建议 MCP 调用始终显式传 1used = 1→ 启用栏目useGenerateView = 1→ 允许生成内容页面→ 对 type=7 信息列表栏目,控制是否为每篇新闻生成详情页→ 对 type=8 独立页面栏目,当前资料未给出独立于列表栏目的特殊语义;插件接口在该字段为 null 时默认补为 1,本教程显式传 1 以保持行为明确
栏目接口默认回退(仅作实现说明,不替代显式传参):当前插件在创建栏目时,对
editMode=null补为0、editUseText=null补为1、useGenerateView=null补为1。这只能保证栏目参数有合理默认值,不能解决 M3 所述的内容记录缺失问题——内容记录是否自动创建取决于独立页面栏目的底层逻辑,与这些默认回退无关。为避免版本差异,本教程仍建议显式传入这些字段。
普通 AI 调用不要自行提交:
siteiduseridparentidrank
这些属于服务端控制字段。
5.2.3 正确返回结果
创建成功时,应满足:
{"result": 1,"info": "789"}
其中:
result = 1→ 栏目创建成功info = "789"→ 示例中的栏目 ID
info = "789" 只是示例。只有 info 能严格解析为大于 0 的整数,并且该值确实来自本次目标站点的栏目保存结果时,才能把它当作栏目 ID。当前上游在部分版本中可能返回 "成功" 等文字;此时即使 result=1 也没有得到 ID,当前 MCP 又没有栏目查询工具,必须停止并要求后台确认栏目 ID 或补充查询接口,不得继续猜测。
取得真实栏目 ID 后,下一步:
save_alone_page_content
需要把它作为:
cid
传入。
结果判断:
| 返回情况 | 是否正确 | 后续处理 |
|—-|—-|—-|
| result = 1 且 info 为已确认的大于 0 的栏目 ID | 正确 | 保存该真实 ID,继续 5.3 |
| result = 1 但 info 为空、为“成功”等非数字文本 | 不完整 | 栏目可能已保存,但缺少可用 ID;停止写入并由后台确认,避免重复创建 |
| result = 0 | 不正确 | 查看 info;可能是栏目名称为空、模板页面不存在、栏目保存失败等 |
| result = 2 | 不正确 | 认证失效,重新执行 login |
| 返回 mcpError | 不正确 | 先处理 MCP 适配器错误 |
本流程只有在 type=8、editMode=0 且后台确认系统已自动创建唯一内容记录时,才进入下一步:
save_site_column→ 创建"关于我们"栏目→ 当前实现尝试自动生成内容;后台确认已存在且唯一→ 下一步使用 save_alone_page_content 修改这条内容
5.3 修改”关于我们”的内容,预览
在当前父级实现中,创建 SiteColumn.type=8 且 SiteColumn.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}无数据来源,不得宣称该页面已完成。
后台人工操作时:
内容管理→ 选择"关于我们"栏目→ 编辑自动创建的内容→ 保存→ 生成整站→ 预览
注意:save_alone_page_content 不是通用的按栏目更新接口。调用前必须确认栏目属于当前站点、类型为当前独立页面 type=8(或目标版本已确认兼容的历史 type=3)、editMode=0,并且该栏目只有一条应被更新的内容。历史数据若有多条同 cid 记录,底层单条查询的目标不确定,必须停止并由后台处理。
如果使用最新 MCP,则调用:
save_alone_page_content
修改已由后台/运行时确认存在且唯一的目标内容;不能仅凭栏目创建成功推断内容已经生成。
5.3.1 save_alone_page_content 参数说明
主要参数:
| 参数 | 是否必填 | 类型 | 关于我们示例值 | 含义 |
|—-|—-|—-|—-|—-|
| authHandle | 是 | string | <有效 authHandle> | 当前认证句柄 |
| cid | 是 | integer | <5.2 返回的已确认栏目 ID> | “关于我们”栏目 ID;仅接受 result=1 且 info 能严格解析为已确认属于当前站点的大于 0 的真实 ID |
| title | 是 | string | 关于我们 | 内容标题 |
| text | 是 | string | <关于我们的完整正文 HTML> | 内容正文 HTML |
| intro | 否 | string | 省略或空字符串 | 内容简介;为空时父级可从正文自动截取 |
| titlepic | 否 | string | 省略或空字符串 | 标题图片 URL |
| htmlName | 否 | string | 省略或空字符串 | 传给内容记录的自定义文件名;当前资料未证明 6.1 生成器会采用它,不能据此推导预览 URL |
| reserve1 | 否 | string | 省略 | 输入模型预留字段 1 |
| reserve2 | 否 | string | 省略 | 输入模型预留字段 2 |
最关键的是:
cid
它不是模板页面 ID,也不是文章 ID,而是:
5.2 中 save_site_column 创建"关于我们"栏目成功后info 返回的栏目 ID
info 到 cid 的唯一可用条件:仅当 result=1 且 info 能严格解析为已确认属于当前站点的大于 0 的真实 ID 时,才可把它传给 cid;空值、成功 等文字、示例数字均不能使用。这一规则同样适用于本文所有把 info 当作 ID 继续传递的地方。
对应关系:
save_site_column→ result = 1→ info 为可确认的正整数栏目 IDsave_alone_page_content→ cid = 上面这个真实栏目 ID
5.3.2 MCP 传参实例
例如 5.2 创建栏目后实际返回:
{"result": 1,"info": "789"}
则:
cid = 789
保存”关于我们”内容时:
{"authHandle": "<有效 authHandle>","cid": 789,"title": "关于我们","text": "<p>这里填写关于我们的实际正文 HTML</p>"}
注意:
这里的 text 是网站后台实际文章内容,不是 about.html 模板源码。
二者必须区分:
save_template_page_text 的 html 参数→ 保存 about.html 详情页模板代码→ 模板中使用 {news.title}、{news.text}save_alone_page_content.text→ 保存"关于我们"这篇实际内容的正文 HTML→ 生成网站时会由 {news.text} 调出
因此完整关系为:
about.html 模板:<h1>{news.title}</h1><div>{news.text}</div>↓后台实际内容:title = 关于我们text = <p>这里是关于我们的实际介绍……</p>↓生成整站后:{news.title}→ 被替换为"关于我们"{news.text}→ 被替换为实际正文 HTML
5.3.3 正确返回结果
保存成功时,应满足:
{"result": 1,"info": "<保存成功信息>"}
结果判断:
| 返回情况 | 是否正确 | 处理 |
|—-|—-|—-|
| result = 1 | 正确 | 关于我们实际内容已更新,可以继续生成整站 |
| result = 0 | 不正确 | 查看 info;可能是栏目不存在、未找到自动创建内容、内容保存失败 |
| result = 2 | 不正确 | 认证失效,重新 login |
| 返回 mcpError | 不正确 | MCP 适配器错误 |
该工具自身不会创建第二条内容,而是按 cid 查询一条已有内容再更新。调用前必须满足本节开头的类型、编辑模式、站点归属和唯一记录条件;不能把“按单条查询”误写成数据库已强制保证唯一。
执行关系:
根据 cid→ 找到已由后台/运行时确认存在且唯一的目标内容→ 更新这条内容
5.3.4 保存内容后生成整站
save_alone_page_content 返回:
result = 1
以后,还必须继续调用:
generate_site
传参:
{"authHandle": "<同一个仍然有效的 authHandle>"}
正确结果:
{"result": 1,"info": "<生成成功说明>"}
最终正确流程:
save_site_column→ 创建关于我们栏目→ result = 1→ 仅当 info 是已确认的正整数栏目 ID 时保存并继续;否则停止save_alone_page_content→ cid = 栏目 ID→ title = 关于我们→ text = 实际正文 HTML→ result = 1generate_site→ result = 1generate_site.result = 1→ 只确认生成调用成功使用用户、宿主或后台提供的真实 URL 发起 HTTP 预览→ HTTP 可访问、中文正常、没有残留模板标签,才确认关于我们页面成功
5.4 独立页面当前底层实现:为什么不再使用 TemplatePage.type=6
这一点用于回答“独立页面模板 type=6 和详情页模板 type=3 到底有什么深层区别”。父级源码已经明确:旧 TemplatePage.TYPE_ALONEPAGE = 6 的单页面模板类型已废弃,并入详情页模板。因此当前系统把“模板渲染类型”和“栏目业务类型”拆开处理。
当前关于我们页面的底层关系是:
TemplatePage.type = 3→ 提供详情页 HTML 渲染结构→ 模板使用 {news.title}、{news.text} 等内容标签SiteColumn.type = 8→ 表示这是当前 CMS 的独立页面栏目→ 绑定 templatePageViewName = about→ 当前父级会尝试自动产生该独立页面对应的 News 内容;是否存在且唯一必须由后台/运行时确认save_alone_page_content(cid=栏目ID)→ 按栏目定位已确认存在且唯一的目标内容→ 委托内容保存逻辑更新它→ 不创建第二条内容generate_site→ 使用 type=3 详情模板 + 已确认存在的独立页面内容生成静态页面
所以当前“独立页面”不是靠 TemplatePage.type=6 来区分,而是靠:
详情模板 TemplatePage.type=3+独立页面栏目 SiteColumn.type=8+该栏目的已确认目标内容记录
共同实现。
这也是为什么 AI 创建“关于我们”时必须使用:
TemplatePage.type = 3SiteColumn.type = 8SiteColumn.editMode = 0 # 需要通过内容管理维护正文时
而不是重新启用已经废弃的 TemplatePage.type=6。
6. 创建新闻列表页面
6.1 创建”新闻列表”的模板页面
列表页模板类型的模板页面,在一个网站中可存在零个或多个。
例如:
产品列表新闻列表案例列表
不同的列表展示形式,可以分别使用不同的列表页模板。
本教程使用前面经过第 2 步处理后的:
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 循环内 |
| 动态栏目调用 | 可用 | 可额外调取其它栏目、子栏目或文章列表 |
因此,列表页普通位置可以写当前栏目名称:
<h1>{siteColumn.name}</h1>
但列表页普通位置没有”当前某一篇文章”这一上下文,所以不要直接写:
{news.title}{news.url}
去假设系统会自动选择一篇文章。文章标签需要进入明确的文章循环上下文。
6.1.2 列表页文章列表调取规则
将列表页面需要展示的文章列表调取出来时,使用(6.1 已确认可用):
<!--TemplateListItemStart-->这里面可使用文章信息标签、栏目标签<a href="{news.url}">{news.title}</a><!--TemplateListItemEnd-->
其中:
<!--TemplateListItemStart-->→ 一条列表项模板的开始<!--TemplateListItemEnd-->→ 一条列表项模板的结束{news.url}→ 当前这一条文章的详情页链接{news.title}→ 当前这一条文章的标题
生成网站时,系统会根据栏目中的实际文章重复生成这段 HTML。
例如模板中:
<!--TemplateListItemStart--><a href="{news.url}">{news.title}</a><!--TemplateListItemEnd-->
如果当前栏目中有 5 篇文章,生成后的列表页 HTML 可以类似(仅示意替换结果;数字和地址不是固定值):
<a href="451.html">网站正常运行1</a><a href="452.html">网站正常运行2</a><a href="453.html">网站正常运行3</a><a href="454.html">网站正常运行4</a><a href="455.html">网站正常运行5</a>
这些 451.html~455.html 只是演示用的文章链接,不能当作固定 News.id、真实详情 URL 或下一次调用的参数;实际地址必须使用运行时生成的 {news.url} 或用户/后台提供的真实 URL。
如果目标版本已确认循环和栏目标签均可用,在 TemplateListItemStart 与 TemplateListItemEnd 内部使用栏目标签,调出的才是当前这一篇文章所属栏目的信息。
例如当前循环到的文章属于一个二级栏目,那么在该循环区域中使用栏目标签,调出的就是这个二级栏目的属性信息。
6.1.3 将原始 news.html 改造成列表页模板
原始 news.html 中的静态文章列表:
<ul><li><a href="about.html">v4.0升级了!</a></li><li><a href="about.html">v3.9升级了!</a></li><li><a href="about.html">v3.8.1升级了!</a></li><li><a href="about.html">v3.8升级了!</a></li>...</ul>
不能继续作为固定新闻数据使用。
应改造成:
<ul><!--TemplateListItemStart--><li><a href="{news.url}">{news.title}</a></li><!--TemplateListItemEnd--></ul>
因此,新闻列表模板的核心结构可以写成:
<!DOCTYPE HTML><html><head><meta charset="utf-8"><title>网·市场</title></head><body>{include=nav}<h1>{siteColumn.name}</h1><ul><!--TemplateListItemStart--><li><a href="{news.url}">{news.title}</a></li><!--TemplateListItemEnd--></ul><div class="pagination"><a href="{page.firstPage}">首页</a><a href="{page.upPage}">上一页</a>{page.upList}{page.nextList}<a href="{page.nextPage}">下一页</a><a href="{page.lastPage}">末页</a></div>{include=footer}</body></html>
原始 news.html 中写死的分页链接不应继续保留为空链接。WangMarket 6.1 源码已确认 {page.*} 分页标签和 {siteColumn.name} 栏目标签在列表页可用(replaceListPageTag() 主动替换),可直接将分页区域改造成动态分页。帮助页 list.jsp 的”不可用”标记为过时标注。完整字段和 URL 规则见下一节。跨版本注意:目标版本不是 6.1 时按 11.1 实测确认。
6.1.4 列表页分页标签完整字段与生成规则
父级官方页面:
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 时,列表页静态文件规则为:
第一页:codeName.html后续分页:codeName_页码.html
例如栏目代码为示例值 news:
news.htmlnews_2.htmlnews_3.html...
目标版本确认支持时,{page.upList}、{page.nextList} 输出页码列表 HTML,并且会产生多个 <li>;不要把它们当作单纯数字变量再机械包成一个 <li>,也不要当成 URL 放进 href。
上述 code 规则只在后台确认目标站点 generateUrlRule=code 时成立。源码中另外存在 lc<ID>_<page>.html、c<ID>.html、<News.id>.html 等按 ID 组合的条件形态,但它们没有稳定公开契约,仅作当前核对版本的条件示例;自动流程一律要求真实 URL,禁止由 codeName、栏目 ID 或 News.id 推导(详见 9.12)。
在目标版本确认支持后,一个保守的分页区域可以按实际样式组合这些系统输出,例如:
<div class="pagination"><span>共 {page.allRecordNumber} 条,第 {page.currentPageNumber}/{page.lastPageNumber} 页</span><a href="{page.firstPage}">首页</a><a href="{page.upPage}">上一页</a><ul>{page.upList}{page.nextList}</ul><a href="{page.nextPage}">下一页</a><a href="{page.lastPage}">末页</a></div>
具体 CSS 可以由模板自行控制,但 AI 不得改写或发明不存在的 {page.xxx} 字段。
6.1.5 MCP 与列表页模板标签的职责边界
最新 MCP 文档中的新闻列表模板流程明确的是:
准备 news.html→ save_template_page 创建 type=2 的新闻列表模板页面→ save_template_page_text 保存完整 news.html→ 后续 save_site_column 通过 templatePageListName 绑定该模板
这里的 MCP 只负责:
创建模板页面保存完整 HTML后续绑定模板页面名称生成整站
MCP 本身不定义列表页内部的标签语法。
因此,本文档前面已经根据列表页模板规则确定的:
<!--TemplateListItemStart--><li><a href="{news.url}">{news.title}</a></li><!--TemplateListItemEnd-->
仍然必须保留。
也就是说:
列表页模板标签文档→ 决定 news.html 如何从静态列表改造成动态文章循环MCP→ 保存已经处理完成的最终 news.html
最新 MCP 中”保存 news.html 的完整内容”,应理解为保存完成模板化处理后的完整 HTML,不是把动态列表再改回固定静态文章。
最终通过 save_template_page_text 的 html 参数保存的 news.html 应同时保留:
完整页面结构{include=nav}{include=footer}TemplateListItemStart / TemplateListItemEnd循环区域中的 {news.url}、{news.title}
6.1.6 使用 MCP 创建”新闻列表”模板页面
如果已经存在有效 authHandle,调用:
save_template_page
创建新闻列表模板页面。
最新 MCP 中:
type = 2→ 新闻列表
推荐参数:
| 参数 | 是否必填 | 类型 | 新闻列表示例值 | 含义 |
|—-|—-|—-|—-|—-|
| authHandle | 是 | string | <有效 authHandle> | 当前认证句柄 |
| name | 是 | string | news | 模板页面名称 |
| type | 是 | integer | 2 | 新闻列表模板 |
| id | 否 | integer/null | 省略或 0 | 创建新模板页面 |
| remark | 否 | string/null | 新闻列表 | 页面备注 |
| editMode | 本流程必填 | integer/null | 2 | 每次显式传数字 2 使用代码模式;schema 可选不代表本流程可以省略 |
传参示例:
{"authHandle": "<有效 authHandle>","name": "news","type": 2,"remark": "新闻列表","editMode": 2}
正确结果应满足:
{"result": 1,"info": "901"}
其中:
result = 1→ 新闻列表模板页面创建成功info = "901"→ 示例中的模板页面 ID
实际 ID 以真实返回值为准。
6.1.7 保存新闻列表模板 HTML
模板页面创建成功以后,再调用:
save_template_page_text
传入:
{"authHandle": "<有效 authHandle>","pageName": "news","html": "<已经完成列表页模板化处理后的完整 news.html>"}
其中:
pageName = news
必须与前一步:
save_template_page.name = news
完全一致。
实际传入的 html 中应包含(WangMarket 6.1 已确认全部可用):
完整页面结构(含 <!DOCTYPE>、<head>、<meta charset="utf-8">、<body>){include=nav}<h1>{siteColumn.name}</h1><!--TemplateListItemStart-->{news.url}{news.title}<!--TemplateListItemEnd--><a href="{page.firstPage}">首页</a><a href="{page.upPage}">上一页</a>{page.upList}{page.nextList}<a href="{page.nextPage}">下一页</a><a href="{page.lastPage}">末页</a>{include=footer}
跨版本注意:以上标签在 6.1 源码中已确认可用(
replaceListPageTag+replaceNewsTag)。若目标版本不是 6.1,{siteColumn.name}和{page.*}可能不被解析,应按 11.1 实测确认后再使用;未确认时可用静态标题和空分页占位替代。
例如:
<!DOCTYPE HTML><html><head><meta charset="utf-8"><title>网·市场</title></head><body>{include=nav}<h1>{siteColumn.name}</h1><ul><!--TemplateListItemStart--><li><a href="{news.url}">{news.title}</a></li><!--TemplateListItemEnd--></ul><div class="pagination"><a href="{page.firstPage}">首页</a><a href="{page.upPage}">上一页</a>{page.upList}{page.nextList}<a href="{page.nextPage}">下一页</a><a href="{page.lastPage}">末页</a></div>{include=footer}</body></html>保存成功时:
{"result": 1,"info": "<保存成功信息>"}结果判断:
| 返回情况 | 是否正确 | 处理 |
|—-|—-|—-|
|result = 1| 正确 | 新闻列表模板 HTML 保存成功 |
|result = 0| 不正确 | 检查info;可能是模板页面不存在、模板变量不存在或保存失败 |
|result = 2| 不正确 | 认证失效,重新login|
| 返回mcpError| 不正确 | 先处理 MCP 适配器错误 |
因此 6.1 的正确 MCP 顺序为:
前提:nav、footer 模板变量已经存在↓save_template_pagename = newstype = 2editMode = 2↓确认 result = 1↓save_template_page_textpageName = newshtml = 完整新闻列表模板 HTML↓确认 result = 1↓新闻列表模板页面创建完成↓后续创建"新闻资讯"信息列表栏目时:save_site_column.templatePageListName = news
6.1.8 创建并保存新闻详情模板 newsView
新闻栏目同时依赖列表模板和详情模板。只有 news 列表模板保存成功还不能绑定栏目;必须先创建并保存本节的 newsView。newsView 是本教程的示例名称,可替换,但创建时的 name、保存 HTML 时的 pageName 和栏目绑定时的 templatePageViewName 必须完全一致。
多个 type=3 详情模板允许共存:与
TemplatePage.type=1(首页,全站只能有一个)不同,type=3详情模板可存在多个,每个栏目通过templatePageViewName绑定各自的详情模板。本教程中about(关于我们独立页面)和newsView(新闻详情)就是两个独立的 type=3 模板,分别绑定不同栏目。
第一步,创建详情模板元数据:
{"authHandle": "<login 成功返回的真实 authHandle>","name": "newsView","type": 3,"remark": "新闻详情","editMode": 2}
调用 save_template_page 后,只有 result=1 才继续。返回的 info 是页面 ID,不传给下一步。
第二步,准备完整详情页 HTML:
<!DOCTYPE html><html lang="zh-CN"><head><meta charset="utf-8"><title>{news.title}</title></head><body>{include=nav}<main><article><h1>{news.title}</h1><div>{news.text}</div></article></main>{include=footer}</body></html>
将上面的完整源码作为 html 调用 save_template_page_text:
{"authHandle": "<同一有效 authHandle>","pageName": "newsView","html": "<上面的完整新闻详情页 HTML>"}
只有第二步也返回 result=1,才允许在后续栏目参数中使用 templatePageViewName=newsView。当前 MCP 没有模板页面查询工具;任何一步失败或提交状态不明时必须停止,不得仅凭名称假定模板已存在,也不得盲目重试创建。
6.2 添加”新闻资讯”栏目
创建”新闻资讯”栏目,并给此栏目选择刚创建的新闻列表模板页面。
后台人工操作关系:
创建新闻列表模板页面→ 创建"新闻资讯"栏目→ 栏目类型选择信息列表→ 给栏目选择 news 新闻列表模板页面→ 设置栏目代码→ 保存
如果使用最新完整 MCP,可以直接调用:
save_site_column
创建”新闻资讯”信息列表栏目。
6.2.1 新闻资讯栏目与新闻列表模板的对应关系
前面第 6.1 步已经创建:
TemplatePage.name = newsTemplatePage.type = 2
表示一个名为 news 的新闻列表模板页面。
现在创建的是:
SiteColumn
网站栏目。
最新 MCP 明确规定:
SiteColumn.type = 7→ 信息列表栏目
因此:
新闻列表模板页面→ save_template_page→ name = news→ type = 2新闻资讯栏目→ save_site_column→ name = 新闻资讯→ type = 7→ templatePageListName = news
这里的两个 type 仍属于不同对象:
TemplatePage.type = 2→ 模板页面类型:新闻列表SiteColumn.type = 7→ 网站栏目类型:信息列表
不能混淆。
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 | 允许生成新闻详情页 |
本教程显式传入示例栏目代码:
codeName = news
这里的 news 仅为栏目代码格式示例,执行时必须替换为目标站点真实存在且已确认的 codeName(传入条件见 5.2.1 的统一规则)。它不能单独证明栏目地址是 news.html。只有后台确认当前站点 generateUrlRule=code 时才能按代码规则组合文件名;其它规则可能使用栏目 ID。当前 MCP 没有站点 URL 规则或栏目查询工具,必须使用用户、宿主、真实标签输出或后台提供的 URL。
6.2.3 创建新闻资讯栏目的 MCP 传参实例
{"authHandle": "<有效 authHandle>","name": "新闻资讯","type": 7,"templatePageListName": "news","templatePageViewName": "newsView","codeName": "news","listNum": 10,"listRank": 1,"used": 1,"adminNewsUsed": 1,"editMode": 0,"useGenerateView": 1,"editUseText": 1,"editUseTitlepic": 1,"editUseIntro": 1}
参数解释:
name = 新闻资讯→ 栏目后台显示名称type = 7→ 信息列表栏目templatePageListName = news→ 使用第 6.1 创建的 news 列表模板templatePageViewName = newsView→ 使用新闻详情模板(type=3),用于文章详情页codeName = news→ 本教程的栏目代码示例;不能直接当作预览 URLlistNum = 10→ 每页显示 10 条内容listRank = 1→ 按发布时间倒序used = 1→ 启用栏目adminNewsUsed = 1→ 内容管理中显示该栏目editMode = 0→ 使用内容管理模式;这是 SiteColumn 字段,不是 TemplatePage.editModeuseGenerateView = 1→ 允许为新闻内容生成详情页editUseText = 1→ 内容管理中显示正文富文本编辑区域(信息列表栏目省略时默认为0,必须显式传1)editUseTitlepic = 1→ 内容管理中显示标题图片/列表图上传区域editUseIntro = 1→ 内容管理中显示简介输入区域
editUseText、editUseTitlepic、editUseIntro控制内容管理中的相应输入区域。本流程需要正文、列表图和简介,所以三者都显式传1;若实际页面不使用列表图或简介,可在需求明确后传0。不要依赖不同版本的省略默认值。
普通 AI 调用不要自行提交:
siteiduseridparentidrank这些属于服务端控制字段。
上游接口仍然使用(仅作实现核对信息,见前置规则第 11 条):
application/x-www-form-urlencodedMCP Server 负责把 MCP arguments 转换成上游所需表单字段;AI 只需按结构化参数调用工具,不直接发 HTTP 请求,也不自行构造
token、iwSID或 Cookie。6.2.4 正确返回结果
栏目创建成功时,应满足:
{"result": 1,"info": "1001"}其中:
result = 1→ 新闻资讯栏目创建成功info = "1001"→ 示例中的 SiteColumn.id,即栏目 ID这里的
1001只是示例。只有本次返回的info能严格解析为大于 0 的整数,并已确认是当前站点的SiteColumn.id时才能继续。result=1但info为"成功"、空值或其它非数字文本时,栏目可能已经保存,但当前 MCP 无法查询其 ID;必须停止并由后台确认,不能重试创建或猜测 ID。
因为下一步:
save_news.cid必须使用这个栏目 ID。
info到cid的唯一可用条件(与 5.3.1 同一条规则):仅当result=1且info能严格解析为已确认属于当前站点的大于 0 的真实 ID 时,才可把它传给后续cid;空值、成功等文字、示例数字均不能使用。
正确对应关系:
save_site_column→ result = 1→ info 为可确认的正整数栏目 IDsave_news→ cid = 上面这个真实栏目 ID
不能把下面这些值错误地传给 cid:
news新闻资讯模板页面 ID模板页面 namecodeName
结果判断:
| 返回情况 | 是否正确 | 处理 |
|—-|—-|—-|
| result = 1 且 info 为已确认的大于 0 的栏目 ID | 正确 | 保存真实 ID,继续 6.3 |
| result = 1 但 info 不是有效数字 ID | 不完整 | 停止写入并由后台确认 ID,避免重复创建 |
| result = 0 | 不正确 | 查看 info;可能是栏目名称为空、模板页面不存在或保存失败 |
| result = 2 | 不正确 | 登录认证失效,重新执行 login |
| 返回 mcpError | 不正确 | 先处理 MCP 适配器错误 |
至此完成:
新闻列表模板 news+新闻资讯栏目+templatePageListName = news+codeName = news
6.3 添加新闻资讯内容,并预览本栏目
后台人工操作时:
内容管理→ 新闻资讯→ 添加新闻内容→ 填写标题、正文等内容→ 保存→ 生成整站→ 使用后台或已有上下文提供的真实栏目 URL 预览
最新完整 MCP 已经提供:
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 | 新闻简介 | 内容简介 |
其中最重要的是:
cid
必须使用:
6.2 save_site_column 返回 result=1,且 info 可严格解析为已确认的正整数栏目 ID
最新 MCP 明确禁止使用:
栏目代码模板页面 ID模板页面名称
代替 cid。
6.3.2 新增第一篇新闻的 MCP 实例
假设 6.2 创建”新闻资讯”栏目后真实返回:
{"result": 1,"info": "1001"}
则:
cid = 1001
新增新闻:
{"authHandle": "<有效 authHandle>","cid": 1001,"title": "v4.0升级了!","text": "<p>这里是 v4.0 升级新闻的正文内容。</p>"}
也可以显式传:
{"authHandle": "<有效 authHandle>","id": 0,"cid": 1001,"title": "v4.0升级了!","intro": "v4.0 版本升级说明","titlepic": "","text": "<p>这里是 v4.0 升级新闻的正文内容。</p>"}
其中:
id 省略或 id = 0→ 创建新新闻id > 0→ 更新已有 News.id 对应的新闻
当前 MCP schema 在创建和更新时都要求 cid;更新时除了真实 News.id,仍必须传该新闻所属的真实栏目 ID。不得因上游旧说明称更新可省略 cid 而违反运行时 schema。
titlepic空值的执行边界:示例中的titlepic: ""只表示“本次不设置标题图”,它不等于一张真实素材。当前核对版本在标题图为null时可能回退到系统默认图,空字符串的处理也需按目标版本确认,因此“页面上出现了图片”不能证明素材已上传。关键视觉(列表图、轮播图、题图)必须使用用户或后台提供的真实图片 URL,并在
generate_site之后用真实页面 URL 检查实际的src:图片可访问、内容确为目标素材。没有真实图片时,不得宣称轮播或题图已经完成,也不能编造上传接口或图片地址。6.3.3 添加多条新闻
如果要把原始
news.html示例中的多条固定新闻变成真实后台内容,则应重复调用:
save_news例如:
第 1 次title = v4.0升级了!第 2 次title = v3.9升级了!第 3 次title = v3.8.1升级了!第 4 次title = v3.8升级了!每一次创建时都使用同一个:
cid = 新闻资讯栏目 ID同时:
id 省略或id = 0每次成功都确认:
result = 1再继续下一条。
6.3.4
save_news返回结果如何判断正确结果必须至少满足:
{"result": 1,"info": "<保存成功信息>"}判断规则:
| 返回情况 | 是否正确 | 处理 |
|—-|—-|—-|
|result = 1| 正确 | 新闻保存成功 |
|result = 0| 不正确 | 查看info;可能是栏目不存在、标题为空、内容保存失败等 |
|result = 2| 不正确 | 认证失效,重新login|
| 返回mcpError| 不正确 | MCP 适配器错误 |
注意:当前完整 MCP 文档没有明确声明save_news成功时的info一定就是News.id。
因此本文档不能把:
save_news.info直接当作新闻 ID 使用。
如果以后需要通过 MCP 更新已有新闻:
save_news.id = 已知 News.id必须使用真实已知的
News.id。如果需要 AI 自动查询某篇新闻的
News.id,当前这份 MCP 文档没有提供新闻列表/查询工具,需要后续增加对应接口,不能自行猜测 ID。6.3.5 保存新闻后生成整站
新闻内容保存完成后必须调用:
generate_site传参:
{"authHandle": "<同一个仍然有效的 authHandle>"}正确结果:
{"result": 1,"info": "<生成成功说明>"}只有:
result = 1才能确认本次生成调用返回成功;不能据此确认页面可访问或内容正确。
最新 MCP 不会返回:
previewUrl因此栏目预览地址不能从
generate_site的返回字段中编造。
预览必须使用用户、宿主、后台或真实页面标签提供的 URL。只有已确认目标站点使用generateUrlRule=code时,本教程的示例codeName=news才可能按对应规则生成news.html;否则不得推导。
完整 MCP 流程:
save_site_columnname = 新闻资讯type = 7codeName = newstemplatePageListName = newstemplatePageViewName = newsView↓result = 1↓仅当 info 是已确认的正整数栏目 ID 时保存并继续;否则停止save_newscid = 栏目 IDtitle = 新闻标题text = 新闻正文 HTML↓result = 1如有更多新闻:继续调用 save_news↓每条都确认 result = 1generate_site↓result = 1使用真实栏目 URL 和至少一篇真实详情 URL 进行 HTTP 预览↓列表、详情均可访问,中文正常,链接可用,且无未解析模板标签↓新闻列表与详情流程才算成功7. 修改导航栏菜单的链接网址
网站建立好后,导航栏必须使用当前网站的真实页面 URL。
codeName是栏目代码,不是 URL;只有后台确认当前站点generateUrlRule=code时,才可按该版本的代码规则生成codeName.html。其它规则可能使用栏目 ID,当前 MCP 又没有站点 URL 规则或栏目查询工具,因此不能自行拼接。
本教程中的:
关于我们栏目:codeName = about新闻资讯栏目:codeName = news
均为示例代码。下面只展示导航结构,三个占位值必须在调用前替换为用户、宿主、后台或已验证页面提供的真实 URL,不能原样提交:
<nav style="text-align:center; font-size:26px;"><a href="<真实首页 URL>">首页</a><a href="<真实关于我们 URL>">关于我们</a><a href="<真实新闻列表 URL>">新闻列表</a><hr/></nav>
若无法取得任一真实 URL,停止更新 nav 并要求后台确认;不得用示例 about.html、news.html 或猜测的数字路径代替。
7.1 使用 MCP 修改 nav 模板变量
由于本教程的所有页面都通过:
{include=nav}
调用公共导航,所以应优先更新:
nav 模板变量
而不是逐个修改 index.html、about.html、news.html。
使用:
save_template_var
更新。
7.2 更新已有 nav 时必须使用模板变量 ID
save_template_var 的接口规则是:
id 省略、null 或 0→ 创建新模板变量id > 0→ 更新已有模板变量
因此这里如果是修改已经存在的 nav,必须使用第 2.2 创建 nav 时:
save_template_var→ result = 1→ info 返回的模板变量 ID
假设第 2.2 创建 nav 时返回:
{"result": 1,"info": "201"}
则:
nav 模板变量 ID = 201
更新时传:
{"authHandle": "<有效 authHandle>","id": 201,"varName": "nav","remark": "通用头部导航","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>"}
上例中的 201 和三个 URL 都是占位示例;调用前必须分别换成创建 nav 时真实返回的模板变量 ID 和已确认 URL。
正确结果:
{"result": 1,"info": "<模板变量保存成功信息或 ID>"}
然后继续:
generate_site
7.3 如果没有保存 nav 的模板变量 ID
当前完整 MCP 文档没有提供:
按 varName 查询模板变量列出模板变量获取 nav ID
这类工具。
因此如果前面创建 nav 时没有保存:
info 返回的模板变量 ID
则不能:
猜一个 id
也不能为了”更新”而直接:
id = 0
因为:
id = 0→ 创建
不是更新。
这种情况下应:
优先从当前 AI / MCP 会话前面保存的执行结果中取回 nav ID
如果执行上下文中也没有,则需要:
进入后台确认 nav 模板变量 ID
或以后补充一个:
查询模板变量 / 按 varName 获取模板变量
的 MCP 工具。
在没有真实 ID 的情况下,不应自行猜测。
7.4 导航修改后的完整 MCP 流程
取得并验证首页、关于我们、新闻列表的真实 URL→ 不能从 codeName 或 ID 猜测取得 nav 已有模板变量 ID↓save_template_varid = nav 模板变量 IDvarName = navtext = 修改后的完整导航 HTML↓确认 result = 1↓generate_site↓确认 result = 1(只表示生成调用成功)↓使用真实站点 URL 检查三个导航链接
即使实际栏目代码为 company、article,也只能在已确认 generateUrlRule=code 时使用相应 .html 路径;否则仍以真实 URL 为准。
7.5 如果网站没有使用 {include=nav}
最新 MCP 工作流说明:
如果导航没有使用 {include=nav}
才需要调用:
save_template_page_text
逐个修改包含导航的模板页面完整 HTML。
但本教程已经在第 2 步统一抽取了:
{include=nav}
因此本教程应优先:
只更新 nav 模板变量
再:
generate_site
即可。
8. 设置全局变量
比如页面底部的 QQ 群号,如果实际使用模板的人想修改 QQ 群号,但又不懂 HTML,就不适合要求用户每次进入 footer 模板变量的 HTML 中手工查找数字。
这里使用:
全局变量
解决。
全局变量可以在:
模板页面模板变量
中通过:
{var.变量名}
调用。
例如:
{var.qq}
8.1 后台人工创建全局变量
后台菜单:
模板管理→ 全局变量
点击:
添加全局变量
本教程以 QQ 群号为例。
原始 footer:
<footer style="text-align:center; padding-top:30px;"><hr/>power by: wang.marketauthor: 管雷鸣QQ群:472328584</footer>
其中:
472328584
适合转换成全局变量。
这里的
472328584是原模板自带的示例 QQ 群号,不是本次建站要发布的真实号码;实际创建时必须填用户提供的真实值。
创建变量名:
以后 footer 中使用:
QQ群:{var.qq}8.2 使用 MCP 创建 QQ 群全局变量
最新完整 MCP 已定义:
save_site_var用于创建或更新网站全局变量。
它和:
save_template_var不是同一种变量。
区别:
save_template_var→ 模板变量→ 保存整段 HTML→ 页面通过 {include=nav}、{include=footer} 引用save_site_var→ 网站全局变量→ 保存文本、图片、下拉值等单项数据→ 页面通过 {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 群号使用:
type = text
8.4 创建 qq 全局变量的 MCP 实例
⚠️ 不可直接提交:value 必须用用户提供的真实 QQ 群号,不能沿用原模板的 472328584。
{"authHandle": "<有效 authHandle>","name": "qq","title": "QQ群号","description": "QQ群号,只填写数字,不要填写“QQ群:”前缀","value": "<用户提供的真实 QQ 群号>","type": "text"}
新建时:
updateName
可以省略或保持为空。
正确结果应满足:
{"result": 1,"info": "<保存结果说明>"}
结果判断:
| 返回情况 | 是否正确 | 处理 |
|—-|—-|—-|
| result = 1 | 正确 | 全局变量定义保存成功 |
| result = 0 | 不正确 | 查看 info;可能是变量名不合法、类型不合法或保存失败 |
| result = 2 | 不正确 | 认证失效,重新 login |
| 返回 mcpError | 不正确 | MCP 适配器错误 |
当前接口没有说明:
save_site_var.info
一定是变量 ID,所以本文档不把它当作 ID 使用。
8.5 把 footer 中的固定 QQ 群号改成 {var.qq}
创建全局变量还不够。
还必须把:
QQ群:472328584
改为:
QQ群:{var.qq}
修改后的 footer(署名与站点名必须替换为用户提供的真实值,不可直接提交):
<footer style="text-align:center; padding-top:30px;"><hr/>power by: <用户提供的真实署名>author: <用户提供的真实作者名>QQ群:{var.qq}</footer>
本教程的 footer 是通过:
save_template_var
创建的模板变量。
因此这里应该更新已有:
footer
模板变量。
8.6 使用 MCP 更新 footer
与更新 nav 一样,更新已有 footer 必须使用其真实模板变量 ID。
假设第 2.2 创建 footer 时返回:
{"result": 1,"info": "202"}
则:
footer 模板变量 ID = 202
⚠️ 不可直接提交:202 是占位示例,必须换成第 2.2 步真实返回的 footer 模板变量 ID;text 里的署名、作者名也必须替换为用户提供的真实值。
更新:
{"authHandle": "<有效 authHandle>","id": 202,"varName": "footer","remark": "通用页面底部","text": "<footer style="text-align:center; padding-top:30px;">n<hr/>npower by: <用户提供的真实署名> nauthor: <用户提供的真实作者名> nQQ群:{var.qq}n</footer>"}
必须确认:
result = 1
以后再生成整站。
如果 footer 的真实模板变量 ID 没有保存,则与第 7 章 nav 相同:
当前 MCP 没有模板变量查询工具
不能自行猜测 ID。
8.7 创建全局变量后的完整流程
save_site_varname = qqtype = textvalue = <用户提供的真实 QQ 群号>↓确认 result = 1取得 footer 已有模板变量 ID↓save_template_varid = footer IDvarName = footertext = 包含 {var.qq} 的完整 footer HTML↓确认 result = 1generate_site↓确认 result = 1最终结果:footer 中 {var.qq}→ 生成时被替换为当前 qq 全局变量的值
仅执行:
save_site_var
但不修改 footer 引用,也不会让原本写死的:
472328584
自动变成动态变量。
同样,仅修改全局变量后如果不:
generate_site
已经生成的静态 HTML 也不会立即变化。
8.8 后续只修改 QQ 群号
只有已由本次创建结果、已有执行上下文或后台确认:
变量确实存在,并且以后只想修改值时,才使用:
使用:
save_site_var_value
⚠️ 不可直接提交:value 必须是用户提供的真实 QQ 群号,不能沿用或改写原模板示例号码。
参数:
{"authHandle": "<有效 authHandle>","name": "qq","value": "新的QQ群号"}
例如:
{"authHandle": "<有效 authHandle>","name": "qq","value": "<用户提供的真实 QQ 群号>"}
正确结果:
result = 1
然后必须继续:
generate_site
完整顺序:
save_site_var_valuename = qqvalue = 新值↓result = 1generate_site↓result = 1重新访问受影响页面
这里不需要:
重新创建 qq修改 type重新编辑 footer
因为 footer 已经引用:
{var.qq}
8.9 图片、下拉类型全局变量
当前 MCP 的 save_site_var.type schema 暴露:
textimageselect
三种录入类型。这里不能据此断言 WangMarket 所有版本只支持这三种类型;自动执行只能传运行时 schema 允许的值。三种类型在模板端的引用语法相同,统一使用 {var.变量名};类型只决定后台如何录入及 value 如何解释。
8.9.1 image 类型
例如创建网站 LOGO:
{"authHandle": "<有效 authHandle>","name": "logo","title": "网站LOGO","description": "上传网站LOGO,建议尺寸 320×240,请保持清晰。","value": "<用户提供或后台已有的真实图片 URL>","type": "image"}
上例 URL 是占位符,不能原样提交。当前 MCP 工具列表没有图片上传工具;必须使用用户提供或后台已确认的真实图片 URL,否则停止创建该变量,不得编造上传接口或 URL。value 保存图片 URL,模板中直接引用:
<img src="{var.logo}" alt="网站LOGO">
不要把图片类型写成 {include=logo},也不要假设 {var.logo} 会自动生成 <img>;它输出的是当前变量值,HTML 标签由模板自己写。
8.9.2 select 类型
select 使用 valueItems 定义完整选项。当前 6.1 后台解析器确认的格式是每行一个:
值:显示文本
例如:
{"authHandle": "<有效 authHandle>","name": "theme","title": "页面风格","description": "选择网站前台使用的页面风格","value": "light","type": "select","valueItems": "light:浅色ndark:深色"}
模板中仍然使用:
{var.theme}
输出当前保存的选项值,例如 light。select 是后台录入控件类型,不会在前台自动生成 <select> 元素。
若目标 WangMarket 版本不是已核对的 6.1,必须先在后台确认 valueItems 解析格式;不得自行改成 =、JSON、逗号分隔或其它格式。
后续只改图片 URL 或下拉当前值时,可以使用 save_site_var_value,修改后仍需 generate_site 才会重新生成静态页面。
9. 模板标签公开基线白名单与上下文规则
本节只列出已核对、允许本教程使用的公开基线,不宣称覆盖 WangMarket 的全部内部标签或扩展钩子。AI 制作模板时只使用本节明确列出的合同;未列出的字段必须由目标运行时帮助页、源码或后台确认,不得根据名字自行猜测。
9.1 模板变量 {include=...}
后台模板变量界面已经明确展示:
| 调用代码 | 备注说明 |
|---|---|
{include=footer} | 通用页脚 |
{include=nav} | 通用头部导航 |
模板变量的一般调用格式为:
{include=变量名}
变量名规则:仅使用英文、数字、下划线 _;MCP save_template_var.varName 最大长度为 20。
AI 执行规则:本流程不依赖模板变量嵌套,并禁止循环引用。 例如:
模板页面 → {include=a}模板变量 a 内部 → {include=b}
不同版本对上例是否继续展开存在资料冲突,不能把任一行为当作跨版本保证。需要两个模板变量时,在模板页面中分别写:
{include=a}{include=b}
模板变量和网站全局变量不是一回事。官方基础教程明确允许模板变量中使用 {var.xxx};后台标签帮助页也把“通用标签”和“动态栏目调用”标记为可用于模板变量。非循环嵌套的实际行为仍需按目标版本实测;任何直接或间接循环引用都禁止。
父级源码没有发现固定的模板变量系统保留名清单,也没有发现 nav、footer 被强制保留。因此当前准确结论是:源码未定义固定保留名;nav/footer 只是推荐名称。 AI 不得反过来伪造一份“系统保留变量列表”。同时,site.*、siteColumn.*、news.*、page.* 属于其它模板标签命名空间,不应被当作模板变量名称使用。
9.2 通用标签
后台帮助页:/templateTag/common.do
适用范围明确包括:
首页列表页详情页模板变量
当前已确认的通用标签如下:
| 标签/固定值 | 含义 | 类型/说明 |
|---|---|---|
{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 要求使用:
{templatePath}/相对路径
例如:
<link rel="stylesheet" href="{templatePath}/css/style.css"><script src="{templatePath}/js/main.js"></script><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.*} 属性,例如:
<h1>{siteColumn.name}</h1><a href="{siteColumn.url}">{siteColumn.name}</a>
在目标版本确认栏目标签可用后,还可区分以下两个上下文:
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 |
在目标运行时确认文章标签可用后,两个典型上下文是:
详情页:用于当前文章/当前独立页面内容,例如 {news.title}、{news.text}列表循环:用于当前循环项,例如 {news.url}、{news.title}、{news.titlepic}
不要在不存在“当前文章”或“当前循环项”的普通模板位置随意写 {news.*} 并假设系统知道你要哪一篇文章。
9.5 动态栏目调用
后台帮助页:/templateTag/dynamic.do
动态栏目调用的明确用途:
- 调取当前生成上下文中可用于模板调用且未被禁用/隐藏的一级栏目;
- 调取某个指定栏目下可用于模板调用且未被禁用/隐藏的子栏目;
- 根据栏目代码调取该栏目属性,以及该栏目下文章列表。
帮助页标记的适用范围包括:首页、列表页、详情页、模板变量。
SiteColumn_Start / SiteColumn_End、SubColumnList_Start / SubColumnList_End、List_Start / List_End 以及列表模板的 TemplateListItemStart / TemplateListItemEnd 都是区分大小写的精确标记。不得添加空格、改连字符、翻译或改写名称。生成后若仍残留这些标记或 {news.*}、{siteColumn.*} 等标签,视为生成失败,必须停止交付。
标记与字段要分开判断(前置规则第 10 条):上面这些动态调用标记本身已确认可用;但标记内部使用的
{siteColumn.*}、{news.*}、{page.*}字段仍必须按同一确认规则,经目标运行时帮助页或一次真实生成结果确认后才可写入。也就是说,可以写<!--SiteColumn_Start-->...<!--SiteColumn_End-->,但不等于可以无条件在里面写{siteColumn.url}或{news.url}。
9.5.1 基本结构与 codeName
<!--SiteColumn_Start--><!--codeName=xinwenzixun-->...<!--SiteColumn_End-->
codeName 是栏目代码,必须使用真实已存在的栏目代码。不要把栏目名称、栏目 ID 或模板页面名称误当成 codeName。
本节代码中的 xinwenzixun、gongsidongtai、doc 和 news 都只是示例 codeName,执行时必须替换为目标站点真实存在的值。当前 MCP 没有按代码查询栏目的工具,缺少该值时不得执行动态调用模板保存。
帮助页还明确支持在栏目/详情相关模板上下文中动态引用当前栏目代码:
<!--codeName={siteColumn.codeName}-->
只有在当前上下文本身存在有效 siteColumn 时才可以这样使用;不要在无栏目上下文的地方凭空使用。
9.5.2 调取指定栏目名称和 URL
<!--SiteColumn_Start--><!--codeName=xinwenzixun--><a href="{siteColumn.url}">{siteColumn.name}</a><!--SiteColumn_End-->
9.5.3 调取指定栏目文章列表
动态模板注释中的 number 用于控制本次动态调用的文章条数;未设置时,当前帮助页说明默认显示 6 条。它不是 save_site_column.listNum:后者控制栏目列表页的每页条数,两个同为数量字段但属于不同对象,不能互相替代或同步推导。
<!--SiteColumn_Start--><!--codeName=gongsidongtai--><div><a href="{siteColumn.url}" title="{siteColumn.name}">{siteColumn.name}</a><ul><!--number=6--><!--List_Start--><li><a href="{news.url}">{news.title}</a></li><!--List_End--></ul></div><!--SiteColumn_End-->
在目标运行时确认动态列表字段后,List_Start ... List_End 内部才可使用文章信息标签。
源码与动态帮助示例表明:首页可以通过动态栏目调用尝试调取新闻/文章列表,但这不替目标运行时解决列表标签冲突;只有相关标签和循环均经确认时才可依赖该结果。
关于“轮播图”:当前资料没有提供一个专用的“轮播图标签”。如果设计要求轮播,可以在动态文章列表中使用已经存在的 {news.titlepic}、{news.url} 等字段,再由模板自身 HTML/CSS/JS 实现轮播效果;当前核对版本在 titlepic 为 null 时可能回退到系统默认图,空字符串的处理也需按目标版本确认。非空输出不证明素材已上传,验收时必须检查图片 URL 可访问且内容确为目标素材。AI 不得编造诸如 {slider.xxx}、{banner.xxx} 之类未在文档出现的 CMS 标签。
9.5.4 调取指定父栏目下的子栏目
<!--SiteColumn_Start--><!--codeName=xinwenzixun--><h2>{siteColumn.name}</h2><!--SubColumnList_Start--><a href="{siteColumn.url}">{siteColumn.name}</a><!--SubColumnList_End--><!--SiteColumn_End-->
在目标运行时确认栏目字段后,SubColumnList_Start ... SubColumnList_End 内部才可使用栏目标签。
9.5.5 调取当前网站可用于模板调用的顶级栏目
不写 codeName:
<!--SiteColumn_Start--><!--SubColumnList_Start--><a href="{siteColumn.url}">{siteColumn.name}</a><!--SubColumnList_End--><!--SiteColumn_End-->
去掉具体栏目代码后,调取当前生成上下文中可用于模板代码调用且未被禁用/隐藏的顶级栏目;不能据此假设后台所有栏目都会输出。
9.5.6 父栏目 → 子栏目 → 每个子栏目的文章列表
<!--SiteColumn_Start--><!--codeName=doc--><!--SubColumnList_Start--><h2>{siteColumn.name}</h2><!--number=30--><!--List_Start--><li><a href="{news.url}">{news.title}</a></li><!--List_End--><!--SubColumnList_End--><!--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 标签 | 当前资料没有;不得编造 |
因此首页内容可以由三层组成:
固定布局 HTML+可后台维护的全局数据 {var.xxx}+栏目/文章动态数据 <!--SiteColumn_Start--> ...
例如首页调“新闻资讯”最新 6 篇(其中 news 是本教程示例 codeName,{news.url}、{news.title} 须先按前置规则第 10 条确认;不可直接提交):
<!--SiteColumn_Start--><!--codeName=news--><!--number=6--><!--List_Start--><a href="{news.url}">{news.title}</a><!--List_End--><!--SiteColumn_End-->
如果首页需要轮播,可以把动态文章列表中的 {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 且目标版本支持才可用 | — | 动态调用内部 |
在目标运行时确认上述条件后,列表页最典型的结构:
<h1>{siteColumn.name}</h1><ul><!--TemplateListItemStart--><li><a href="{news.url}">{news.title}</a></li><!--TemplateListItemEnd--></ul><div class="pagination"><a href="{page.firstPage}">首页</a><a href="{page.upPage}">上一页</a><a href="{page.nextPage}">下一页</a><a href="{page.lastPage}">末页</a></div>
分页完整 11 个字段和 URL 生成规则见 9.12。
9.8 详情页模板 TemplatePage.type=3
基础教程明确“关于我们”添加模板页面时选择详情页模板;当前 MCP 文档进一步规定关于我们等单页面通过 MCP 创建模板页面时使用 TemplatePage.type=3。
本教程详情示例使用以下核心标签。WangMarket 6.1 源码已确认可用(replaceNewsTag() 主动替换);目标版本不是 6.1 时按 11.1 实测确认:
{news.title}{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` |
| 脚本 | `
| 历史正文标签 | 旧模板兼容行为需按目标运行时验证;新模板不使用 |
新建详情模板统一使用 {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` |
| 脚本 | `
;不得同时插入两种正文标签,否则可能重复输出正文。
```
> **⚠️ `{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}
{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
```
#### select 示例
当前 6.1 后台解析器要求 `valueItems` 每行使用:
```text
值:显示文本
```
例如:
```text
valueItems:
light:浅色
dark:深色
value = light
```
模板:
```text
{var.theme}
```
输出的是当前保存的变量值。AI 不得把 `select` 自动解释成会生成 `
`、不把 select 自动当 `
hi,这是首页
hi,这是首页
{news.title}
新闻列表
{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.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
全局变量统一通过:
{var.变量名}
引用。当前 MCP 暴露的 text、image、select 三种类型引用语法相同,区别在后台录入方式和 value 的含义;这不代表所有 WangMarket 版本只存在三种类型。
text 示例
name = qqtype = textvalue = <用户提供的真实 QQ 群号>模板:{var.qq}
image 示例
{"authHandle": "<有效 authHandle>","name": "logo","title": "网站LOGO","description": "上传网站LOGO,并在备注中写明建议尺寸和格式","value": "<用户提供或后台已有的真实图片 URL>","type": "image"}
模板仍然写:
<img src="{var.logo}" alt="网站LOGO">
select 示例
当前 6.1 后台解析器要求 valueItems 每行使用:
值:显示文本
例如:
valueItems:light:浅色dark:深色value = light
模板:
{var.theme}
输出的是当前保存的变量值。AI 不得把 select 自动解释成会生成 <select> HTML;它只是后台的录入类型,模板端仍然通过 {var.xxx} 读取当前值。
9.10 TemplatePage.editMode 与 SiteColumn.editMode 必须分开
这是两个完全不同的数据对象和枚举,禁止因为字段同名而混用。
9.10.1 TemplatePage.editMode
1 = 智能 / 可视化模式2 = 代码模式
父级源码已经把可视化模式标记为“即将废弃,不建议用”。当前 TemplateController 只确认以下行为:
- 将模板页面放入 iframe 编辑;
- 在
</head>前注入htmledit.js; - 注入
htmledit_upload_url图片上传地址; - 保存时清理
<!--XNX3HTMLEDIT-->标记区; - 保存时清理编辑器附加资源以及部分编辑属性。
当前工程没有找到完整的 htmledit.js DOM/API 规范,也没有完整定义:
可编辑区域标记标准图片上传返回结构元素选择规则禁止编辑区域约定可视化保存兼容 HTML 规范
因此这项问题的最终执行结论是:
AI / MCP 创建 TemplatePage→ 默认并显式使用 editMode = 2→ 不主动使用 editMode = 1
“没有完整可视化协议”不再是需要 AI 自己补齐的缺口,而是禁止 AI 使用该模式的依据。除非以后官方重新提供完整规范,否则不得臆造 DOM 标记或上传协议。
9.10.2 SiteColumn.editMode
0 = 内容管理 UEditor 富文本1 = 直接编辑模板
它不是“0=输入模型,1=模板模式”。inputModelCodeName 是另一个独立字段。
关于我们等独立页面希望通过 save_alone_page_content / 内容管理维护系统自动创建的唯一 News 内容时,应使用:
SiteColumn.type = 8SiteColumn.editMode = 0
9.11 输入模型 inputModelCodeName
当前已核对资料中没有 product、news、article 等可假设为系统内置的固定模型代码列表。
默认逻辑:
inputModelCodeName = null / 空字符串 / "0"→ 不指定自定义输入模型,由当前运行时处理默认输入模型
自定义逻辑:
inputModelCodeName = 其它代码→ 从数据库 input_model 中按 code_name 读取→ 该代码由网站管理员自行创建→ 每个网站可不同
因此 AI 的固定执行规则为:
- 用户没有明确要求自定义输入模型时,省略
inputModelCodeName;如需显式空值,只使用运行时 schema 接受的null、空字符串或字符串"0"。 - 用户明确要求某个自定义模型时,必须先确认当前网站确实存在对应
input_model.code_name。 - 不得因为栏目叫“产品”“新闻”就自动传
product、news、article。这些字符串只有在当前网站真实存在同名自定义模型时才能使用。 - 输入模型与
SiteColumn.editMode是两个独立概念,不得互相推导。
9.12 分页标签 {page.*}
分页标签来自父级官方页面:
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} | 首页 URL | 6.1 已确认:只输出地址,放入 href 等 URL 上下文 |
{page.upPage} | 上一页 URL | 6.1 已确认:只输出地址,放入 href 等 URL 上下文 |
{page.nextPage} | 下一页 URL | 6.1 已确认:只输出地址,放入 href 等 URL 上下文 |
{page.lastPage} | 尾页 URL | 6.1 已确认:只输出地址,放入 href 等 URL 上下文 |
{page.haveUpPage} | 是否存在上一页 | 6.1 输出小写 true / false;跨版本需实测 |
{page.haveNextPage} | 是否存在下一页 | 6.1 输出小写 true / false;跨版本需实测 |
{page.upList} | 前几页页码 HTML | 6.1 已确认:生成多个 <li> |
{page.nextList} | 后几页页码 HTML | 6.1 已确认:生成多个 <li> |
父级生成代码确认:仅在目标站点实际使用 generateUrlRule=code 时,列表页面文件名为:
第一页:codeName.html第 2 页及以后:codeName_页码.html
以下只是 codeName=news 的示例相对文件名,不含真实站点基础 URL:
news.htmlnews_2.htmlnews_3.html
{page.upList} 和 {page.nextList} 按源码输出页码列表 HTML 并生成多个 <li>;它们输出的是一段页码列表 HTML,不是单个数字也不是单个 URL,因此不要把它们再机械包进一个 <li> 或 href 中。
非
code规则的 URL 形态不得推导:源码中还可以看到lc<ID>_<page>.html、c<ID>.html、<News.id>.html等按 ID 组合的条件形式,但这些形态没有稳定公开契约,只能作为当前核对版本的条件示例来理解。自动流程统一要求使用用户、宿主、后台或真实页面标签输出的 URL;禁止由codeName、栏目 ID、News.id、htmlName或历史路径拼出预览地址。
9.12.1 独立页面(SiteColumn.type=8)的 URL 规则
WangMarket 6.1 源码已确认(TemplateCMS.generateNewsPageHtmlName()):
generateUrlRule=code且栏目类型为type=8(独立页面)或type=3(页面)时,详情/独立页面文件名 = 栏目codeName(调用方追加.html),即codeName.html。generateUrlRule=code且栏目为普通新闻列表(type=7)时,详情页文件名 =News.id(如451.html),不是 codeName。generateUrlRule=int时,使用 ID 组合形态(如lc<栏目ID>_<页码>.html、<News.id>.html),具体形态见源码但无稳定公开契约。
因此:
- 自部署/非官方环境(
generateUrlRule几乎一定为code),独立页面设置了真实codeName后,URL 即为codeName.html,可按此规则构造导航链接。 - 官方云老站点(
generateUrlRule=int),独立页面 URL 须由后台或已生成页面确认,不得推导。 save_site_column.codeName本身不是 URL,但在code规则下可用于推导独立页面地址;普通新闻详情页 URL 始终是News.id.html,与 codeName 无关。save_alone_page_content.htmlName不用于推导预览地址(见 11.10)。
10. 已确认规则与仍需确认的执行边界
下表汇总有当前资料依据的规则。表中的“禁止使用/禁止猜测”也是执行结论,但不代表相关底层行为已经得到完整规范。
| 序号 | 原问题 | 最终结论 | AI 强制执行规则 |
|---|---|---|---|
| 1 | TemplatePage.type=0 使用场景 | TYPE_ELSE=0 仅标注“其他”;无明确标准生成、绑定、预览业务路径;普通保存也不会使其成为标准业务页面 | 当前 MCP 不使用 0;不得自行定义用途 |
| 2 | SiteColumn.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.*} 或扩展未确认字段 |
| 6 | TemplatePage.editMode=1 可视化模式 | 父级标记即将废弃、不建议;只确认 iframe、htmledit.js、上传地址注入及保存清理逻辑;无完整 DOM/API 规范 | AI/MCP 默认 editMode=2;不使用、不臆造 editMode=1 协议 |
| 7 | SiteColumn.editMode | 0=内容管理 UEditor,1=直接编辑模板;与 TemplatePage.editMode 和输入模型都不同 | 独立页面通过内容管理维护正文时使用 SiteColumn.editMode=0 |
| 8 | inputModelCodeName | 省略、null、空字符串或字符串 "0" 表示不指定自定义模型;其它代码来自当前网站 input_model.code_name;没有固定 product/news/article 内置列表 | 没有明确自定义模型时省略;其它代码必须先确认存在 |
| 9 | 模板变量命名、嵌套、保留名 | 名称限英文/数字/下划线;非循环嵌套存在版本资料冲突;nav/footer 非保留;源码未定义固定保留名清单;各标签命名空间独立 | 本流程在页面直接引用各变量;禁止循环引用;不伪造保留名或混用命名空间 |
| 10 | 全局变量 image/select | text/image/select 都通过 {var.xxx} 引用;image value=图片 URL;select 用 valueItems 定义选项、value 保存当前值 | 不把 image 自动当 <img>、不把 select 自动当 <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<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 会产生双斜杠 // |
| 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,仍须做一次最小化真实生成测试确认:
- 在列表模板中写入
{siteColumn.name}、<!--TemplateListItemStart-->{news.title}<!--TemplateListItemEnd-->、{page.firstPage}; - 在详情模板中写入
{news.title}、{news.text}; - 调用
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"(默认值) |
实际操作:
- 自部署环境:可直接判定为
code规则,列表页 URL =codeName.html,独立页面 URL =codeName.html,新闻详情 URL =News.id.html。 - 官方云/不确定环境:
- 从用户/宿主取得站点 ID,按上表判定;或
- 后台查看站点设置;或
- 从已生成页面 URL 反推:
news.html/news_2.html→code;lc1001_1.html/451.html→int。
- 站点基础 URL(域名/访问路径):仍须由用户、宿主或后台提供,MCP 无查询接口。
- 独立页面(type=8)的 URL:
code规则下 =codeName.html(源码generateNewsPageHtmlName()已确认);int规则下须由后台确认,不得推导(见 9.12.1)。
11.3 栏目/模板变量/新闻的已有状态与真实 ID 确认
待确认内容:目标站点是否已存在同名栏目、模板变量、模板页面或新闻,以及它们的真实 ID。
确认方法:
- 后台查看:
- 栏目:后台「栏目管理」列表,记录栏目名称、ID、
codeName、类型; - 模板变量:后台「模板管理 → 模板变量」,记录
varName和 ID; - 模板页面:后台「模板管理 → 模板页面」,记录
name、type和 ID; - 新闻:后台「内容管理」,按栏目筛选,记录文章 ID。
- 栏目:后台「栏目管理」列表,记录栏目名称、ID、
- 从本次会话上下文取得:若前面的工具调用已返回
info中的正整数 ID,直接使用该值。 - 当前 MCP 限制:没有按名称/代码查询的工具,缺少 ID 时必须停止并请求后台确认,不得猜测或用
id=0假装更新。
11.4 save_template 目标模板与副作用确认
待确认内容:当前站点 site.template_id 是否指向有效模板;调用 save_template 是否会修改已有模板。
确认方法:
- 后台查看模板绑定:在后台「模板管理」中查看当前站点是否已选择/导入模板,以及模板名称。
- 评估副作用:
save_template的实现可能在template_id无效时使用 ID 1,可能创建或修改既有模板。调用前必须由用户确认允许该操作影响现有模板。 - 调用后验证:
result=1后仍需后台复核绑定状态,并执行generate_site+ 真实 URL 验收,不能仅凭返回值宣称绑定成功。
11.5 save_site_column.info 非数字文本的落库状态确认
待确认内容:result=1 但 info 返回 "成功" 等非数字文本时,栏目是否实际落库、ID 是多少。
确认方法:
- 停止后续写入,不要重复调用
save_site_column(可能创建重复栏目)。 - 后台栏目管理:按栏目名称和创建时间找到刚创建的栏目,记录其真实 ID。
- 若存在多个同名栏目:通过绑定的模板页面名称(
templatePageListName/templatePageViewName)和创建时间区分,确认哪一个是本次创建的。 - 使用后台确认的真实 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 后,静态文件是否真实可访问。
确认方法:
- 使用真实 URL 做 HTTP 验收:用浏览器或
curl访问首页、列表页、详情页,检查 HTTP 状态码。 - 检查内容:页面中文正常、无未解析标签、无残留动态标记、CSS/JS/图片可加载。
- 404/超时处理:
- 不要无限重试
generate_site; - 检查宿主 Web 服务器根目录配置、CDN 缓存;
- 后台文件管理中确认静态文件是否实际生成及文件名;
- 无轮询工具时停止并等待后台确认。
- 不要无限重试
11.8 独立页面内容唯一性与存在性确认
待确认内容:save_alone_page_content 按 cid 查询的 News 记录在当前站点下是否存在且唯一。
确认方法:
- 后台内容管理:进入该独立页面栏目,首先确认是否存在内容记录。
- 若不存在任何内容记录:当前 MCP 无法创建(
save_alone_page_content只查询不创建,save_news不适用于 type=8),必须由人工在后台”内容管理”中为该栏目手动添加一条内容,之后 AI 才能用save_alone_page_content更新。在此之前不得宣称关于我们页面已完成。 - 若存在且仅有一条:继续下一步。
- 若不存在任何内容记录:当前 MCP 无法创建(
- 若存在多条同
cid记录:底层查询目标不确定,必须停止,由后台清理重复数据后再执行save_alone_page_content。 - 实现边界说明:底层查询未显式带
siteid条件,跨站数据可能干扰;不得无条件承诺「当前站点唯一」。
11.9 非 6.1 版本的 valueItems、日期格式与嵌套行为确认
待确认内容:目标 WangMarket 版本不是已核对的 6.1 时,select 类型全局变量的 valueItems 格式、{news.addtime.month} 是否补前导零、模板变量非循环嵌套是否生效。
确认方法:
- 确认版本号:在后台关于页面或页脚查看 WangMarket 版本号。
valueItems格式:在后台创建一个select类型全局变量,保存后查看选项是否正确解析;若值:显示文本格式不生效,尝试后台文档说明的格式。- 日期格式:在详情模板中写入
{news.addtime.month},生成后查看输出是3还是03;需要固定两位时由模板前端 JS 格式化,不依赖 CMS 输出。 - 模板变量嵌套:创建变量 A 引用变量 B,生成后查看是否展开;若不生效,改为在模板页面中分别直接引用。
11.10 News.htmlName 对详情 URL 的影响确认
待确认内容:save_alone_page_content 的 htmlName 参数是否影响当前生成器的详情页 URL。
确认方法:
- 创建测试内容时设置
htmlName=test-page,生成后查看详情页实际 URL。 - 若 URL 未使用
test-page.html:说明当前版本生成器不采用htmlName,不得用它推导预览 URL。 - 统一规则:详情页 URL 始终使用真实生成结果或后台确认的地址,不得由
htmlName、News.id或codeName推导。
11.11 确认结果记录模板
每次完成上述确认后,应按以下格式记录,供后续执行引用:
确认项:<对应 11.1-11.10 的编号>目标运行时版本:<版本号>确认方法:<帮助页 / 真实生成 / 后台查看>确认结果:<可用 / 不可用 / 具体参数值>证据:<帮助页截图描述 / 生成页面 URL / 后台路径>确认时间:<YYYY-MM-DD>
未完成确认的事项,在执行时必须按第 10 章的「当前可执行边界」停止并报告,不得跳过。
常见问题与避坑指南
在实际操作过程中,以下常见问题容易导致生成失败或页面显示异常,在此特别说明,避免后续踩坑。
问题1:后台点击「生成整站」提示”当前网站尚未选择/导入/增加模版,生成失败!”
现象描述
在网站管理后台左侧菜单点击「生成整站」按钮时,弹出错误提示:
当前网站尚未选择/导入/增加模版,生成失败!网站有模版后才能根据模版生成整站!
但奇怪的是,已经创建了模板页面(index、about、news)和模板变量(nav、footer),为什么还提示没有模板?
原因分析
网市场系统的模板体系分为两层:
| 层级 | 数据表 | 说明 |
|---|---|---|
| 模板(Template) | template | 模板的基本信息,一个模板包含多个模板页面 |
| 模板页面(TemplatePage) | template_page + template_page_data | 具体的页面模板(首页、列表页、详情页) |
网站表 site 中有一个字段 template_id,指向 template 表中的模板记录。
后台「生成整站」按钮在执行生成前,会校验:
site.template_id → template 表中是否存在对应记录
如果 template 表为空,或者 site.template_id 指向了一个不存在的模板 ID,校验就会失败,提示”当前网站尚未选择/导入/增加模版”。
而通过 MCP 接口 generate_site(对应上游接口 /template/refreshForTemplate.do)生成时,可能不执行同一项绑定校验,因此“生成调用返回成功”和“后台模板绑定有效”必须分别验证。
解决方案
方案一:在确认允许影响当前模板后调用 save_template
本文档已新增 MCP 工具 save_template,对应上游接口:
POST /plugin/adminapi/site/saveTemplate.json
当前实现的真实边界:
- 读取当前网站的
site.template_id;为空或不大于 0 时把候选 ID 设为1。 - 候选 ID 不存在时,尝试按该 ID 新建模板记录,并把网站指向它。
- 候选 ID 已存在时,不会重新绑定到其它模板;传入非默认名称或非空备注还可能修改该既有模板。
- 若网站原本没有有效
template_id而模板 ID 1 已存在,当前代码可能返回成功但没有把网站重新绑定到 1。 - 接口没有验证新建/既有模板是否与已创建的模板页面正确归属,也不能保证后台按钮随后一定成功。
因此调用前必须由用户或后台确认允许该操作影响现有模板。无法确认当前绑定状态时,不得把此工具描述为无副作用的“确保绑定”。为降低误改风险,默认只传 authHandle;只有用户明确要求修改模板名称/备注时才传对应字段。
调用示例:
{"authHandle": "<login 返回的有效 authHandle>"}
参数说明:
| 参数 | 是否必填 | 类型 | 说明 |
|—-|—-|—-|—-|
| authHandle | 是 | string | login 成功返回的认证句柄 |
| name | 否 | string | 模板名称,默认”自定义模板” |
| remark | 否 | string | 模板备注,默认空字符串 |
返回示例:
{"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 文件源码,发现文件中没有 <meta charset="utf-8"> 标签。
原因分析
在创建模板页面时,如果只保留了 body 内部的内容,例如:
{include=nav}<div><h2>hi,这是首页</h2></div>{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">。
正确的首页模板示例:
<!DOCTYPE html><html><head><meta charset="utf-8"><title>首页 - 网站名称</title></head><body>{include=nav}<div><h2>hi,这是首页</h2></div><div>网站介绍内容...</div>{include=footer}</body></html>
正确的详情页(关于我们)模板示例:
<!DOCTYPE html><html><head><meta charset="utf-8"><title>{news.title} - 网站名称</title></head><body>{include=nav}<h1>{news.title}</h1><div>{news.text}</div>{include=footer}</body></html>
正确的列表页(新闻列表)模板示例:
<!DOCTYPE html><html><head><meta charset="utf-8"><title>新闻列表 - 网站名称</title></head><body>{include=nav}<h1>新闻列表</h1><ul><!--TemplateListItemStart--><li><a href="{news.url}">{news.title}</a></li><!--TemplateListItemEnd--></ul>{include=footer}</body></html>
如果已有模板缺少编码声明,如何修复?
先从后台取得当前模板页面的完整源码,整理成唯一一套 doctype/html/head/body 结构并保留原正文,再通过后台或 save_template_page_text 整体覆盖。不要在未知原文前后盲目追加标签,否则可能生成嵌套或重复的 <html>、<head>、<body>。当前 MCP 没有读取模板页面源码的工具;若手头没有可信的完整原文,必须停止并要求后台导出,不能凭空重建后覆盖。
保存后重新生成整站,并用真实 URL 检查响应内容与浏览器显示。
验证方法
生成整站后,查看生成的 HTML 文件源码,确认文件开头包含:
<!DOCTYPE html><html><head><meta charset="utf-8">
在浏览器中打开页面,中文应正常显示,不再出现乱码。
问题3:save_site_column 返回 result=1 但 info 是”成功”等非数字文本
现象描述
调用 save_site_column 创建栏目后,返回:
{"result": 1,"info": "成功"}
info 不是数字,无法取得栏目 ID,后续 save_news 或 save_alone_page_content 的 cid 参数无法填写。
原因分析
不同版本的 WangMarket 上游接口在 save_site_column 成功时,info 字段的返回值不一致:
- 部分版本返回栏目 ID(如
"789"); - 部分版本返回固定成功文本(如
"成功")。
当前 MCP 没有栏目查询工具,无法通过 codeName 或栏目名称反查 ID。
解决方案
- 停止后续写入操作,不要猜测栏目 ID,也不要用
codeName、栏目名称或模板页面 ID 代替cid。 - 进入后台确认:在后台「栏目管理」中找到刚创建的栏目,记录其真实 ID。
- 使用后台确认的真实 ID 继续调用
save_news或save_alone_page_content。 - 若后台中存在多个同名栏目,必须确认哪一个是本次创建的(可通过创建时间、绑定的模板页面名称区分),避免更新错误栏目。
- 不要因为
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 不存在、标记未正确闭合 |
解决方案
{include=xxx}未解析:- 确认模板变量已通过
save_template_var创建且result=1; - 确认页面中
{include=nav}的nav与save_template_var.varName完全一致(大小写敏感); - 确认变量
text不为空; - 确认创建变量在保存页面 HTML 之前执行(见 2.2.5 顺序规则)。
- 确认模板变量已通过
{var.xxx}未解析:- 确认全局变量已通过
save_site_var创建; - 确认变量名与
{var.qq}中的qq完全一致; - 确认变量已设置
value。
- 确认全局变量已通过
{news.*}/{siteColumn.*}/{page.*}未解析:- 按前置规则第 10 条,先确认目标运行时是否支持该标签及上下文;
- 确认标签使用在正确的上下文中:
{news.*}必须在详情页或文章循环内,{page.*}仅用于列表页,首页不能直接写{news.title}; - 确认动态标记
<!--TemplateListItemStart-->/<!--List_Start-->等拼写正确且已闭合。
动态标记残留:
- 检查标记是否精确匹配(区分大小写,无多余空格):
<!--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 只表示生成调用已完成,不代表:
- 静态文件已写入到可访问的目录;
- 宿主 Web 服务器已配置正确的站点根目录;
- 预期 URL 与实际生成的文件名一致;
- 生成过程中没有静默跳过某些页面。
常见具体原因:
- URL 猜测错误:由
codeName或栏目 ID 拼接的 URL 与实际generateUrlRule不符; - 宿主环境延迟:静态文件生成后,CDN 或 Web 服务器需要时间刷新;
- 站点未绑定有效模板:见问题1;
- 栏目未启用或
useGenerateView=0:详情页不会生成。
解决方案
- 不要无限重试
generate_site,也不要猜测 URL。记录真实的 404/超时错误信息。 - 确认真实站点基础 URL:从用户、宿主或后台取得,不要由
codeName或 ID 推导。 - 确认
generateUrlRule:只有后台确认使用code规则时,codeName.html才可能成立;其它规则可能使用栏目 ID 路径。 - 确认栏目状态:栏目
used=1、信息列表栏目useGenerateView=1(需要详情页时)。 - 后台确认生成结果:在后台文件管理或 FTP 中查看静态文件是否实际生成、文件名是什么。
- 若宿主有轮询或生成状态查询工具,使用它确认生成完成;没有则等待后台确认。
验证方法
使用后台确认的真实 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、不得重复创建 |
具体操作:
- 从本次会话前面的工具返回结果中查找
info字段中的真实 ID; - 若上下文中没有,进入后台确认对象 ID;
- 当前 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,变量本身已带 /,就会生成 //。
解决方案
- 6.1 版本确定写法:模板中统一写
{templatePath}css/style.css(不加额外斜杠); - 不要把双斜杠当作通用可接受行为,部分浏览器/CDN 可能无法正确解析;
- 修改后重新生成整站,检查所有资源引用。
验证方法
生成页面中所有 {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只更新不创建。
解决方案
- 停止 MCP 操作,不要重试
save_alone_page_content(不会因为重试而创建内容),也不要改用save_news(栏目类型不匹配)。 - 由人工在后台”内容管理”中为该栏目手动添加一条内容:进入内容管理 → 选择”关于我们”栏目 → 添加内容 → 填写标题和正文 → 保存。
- 后台确认内容已存在且唯一后,AI 再使用
save_alone_page_content(cid=栏目ID)更新该内容。 - 在此之前,关于我们页面的
{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。
- 准备并校验输入:确认目标站点、运行时工具 schema、本次要走哪些业务分支(首页 / 独立页面 / 信息列表并启用详情)、每个对象的创建或更新状态与真实 ID、完整 HTML、文案、真实图片 URL、允许的模板绑定方案,以及真实站点基础 URL。需要更新的对象必须有真实 ID;需要自定义输入模型、栏目代码或图片 URL 时必须有后台依据。任一缺失即停止,不开始写入。
- 登录:调用
login。仅result=1且返回非空真实authHandle时继续,后续每个业务工具均原样传入它。 - 先保存被引用的数据:模板若使用
{var.xxx},先用save_site_var创建完整定义;只改已确认存在的值才用save_site_var_value。然后按本节开头的创建/更新判定规则处理nav、footer模板变量——已存在且有真实 ID 就按 ID 更新,已确认不存在才创建,不明则停止,并保存真实变量 ID。若真实导航 URL 尚未取得,可先保存不含猜测链接的最小导航,待第 8 步取得 URL 后按真实 ID 更新。 - 按业务分支创建并保存模板页面:先按第 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 更新。
- 首页分支 → 需要
- 处理模板绑定:若后台已确认当前网站绑定有效模板,不调用
save_template。若尚未绑定,只有用户已授权其潜在副作用时才调用;result=1后仍须后台复核绑定。未授权或无法确认时停止,不能宣称已确保绑定。 - 创建或更新关于我们业务数据(仅当选择独立页面分支时执行):按判定规则处理后,用
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;在此之前不得宣称关于我们页面已完成。 - 创建或更新新闻业务数据(仅当选择信息列表分支时执行):确认
news(启用详情生成时还包括newsView)均已完整保存后,按判定规则处理栏目,再用save_site_column(type=7, templatePageListName=news, templatePageViewName=newsView)写入,并显式传本流程需要的编辑字段;更新已存在栏目时必须使用已确认的真实 ID。仍仅接受可确认的正整数栏目 ID,然后把该真实 ID 作为save_news.cid。更新新闻时必须同时提供真实News.id和真实cid。 - 预生成并补齐真实导航:先调用一次
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等示例路径充数。 - 最终生成:导航更新后再次调用
generate_site,使导航变更反映到静态页面。result=1只表示生成调用已完成,不等于静态文件已可访问或内容正确。必须按宿主提供的真实 URL 做一次 HTTP 与内容验收;若出现 404、超时且没有官方轮询/查询工具,不得无限重试生成、不得猜 URL,应记录真实错误并停止等待后台确认。 - 真实预览验收:使用可信 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/传输错误,再判断业务 result。result=0、mcpError、isError=true 或验收失败时停止当前依赖链并报告真实错误;result=2 时重新登录,只重试刚失败的一步。超时、断线或其它无法判断写入是否落库的情况禁止盲目重试创建/覆盖操作,必须先由后台确认实际状态,否则可能产生重复对象或覆盖正确内容。
当前 MCP 没有站点 URL规则、栏目、模板页面、模板变量、新闻、输入模型、全局变量或上传结果的通用查询工具。缺少真实上下文时,结论只能是“需要后台确认或补充查询接口”,不能借用其它 CMS 经验、示例值、名称、codeName、URL 数字或历史默认值进行推断。