v2.8.2
2026-10-12 · 7天前
更新与更新日志页面以访问者的语言显示
修复内容
- •更新程序错误:文件和
version.json 写入失败、不支持补丁和变更预览、无法访问仓库以及连接成功。
- •更新页面:服务器响应错误、“N 个文件变更 · N 次提交”、完成、应用中、任务已登记、超时和回滚完成。
- •任务登记提示:更新、补丁或回滚任务已登记的消息。
- •权限工作进程(cron)留下的进度消息以及完成、失败通知,现在也使用正确的语言。
更新日志页面(`/changelog`)
- •“5 months ago”这类相对时间原来只有韩语和英语两种,现在支持 13 种语言。
空列表提示、“AI 翻译”标记、“没有翻译 — 以 KO 显示”提示和“仅显示最新 N 条”也一并翻译。
- •页面语言现在取网站实际使用的语言,而不只是会话值(
?lang=、会话、Cookie、默认语言)。
以前首次访问会退回韩语,导致日语和英语网站里混入韩语标注。
- •过长的标识符和路径(不含空格的文字)不再溢出卡片,也不会被压到右侧的安装提示按钮下面。
需要了解
- •权限工作进程没有登录用户,因此没有语言。它以网站的默认语言留下消息。
(以前它没有启动翻译系统,所以 updater.write_failed 这样的翻译键可能原样显示出来。现在工作进程会启动翻译。)
- •服务器日志(
error_log)和开发用调试日志是由运维人员阅读的,因此保持不变。
- •对于已安装的网站,执行更新的是已经安装的旧版更新程序,所以这些改进要在升级到 2.8.2 之后的更新中才会生效。
多语言
- •“添加到主屏幕”和安装提示中的应用名称与说明以访问者的语言显示。以前直接显示设置值(例如日语)。
翻译放在 rzx_translations 中类似 pwa.front.name 的键下。manifest.php 现在只负责转交给正式的输出。
- •结构化数据(JSON-LD):优先查看设置值的翻译。修复了面包屑第二项里还带有网站名称的问题,以及“Home”在所有语言里都显示为英语的问题。
- •统计组件:数字和单位(
suffix)也像标签一样接受各语言的值。单一值的行为与以前完全相同。
- •离线页面和 Service Worker 的最后提示文案提供了韩语、日语、英语三种语言。
Service Worker 的缓存版本从 v5 升到 v6,已安装的设备也会收到新页面。
- •消息搜索里写死为韩语的“没有搜索结果”,现在支持 13 种语言。
搜索引擎与 AI
- •输出
<meta property="og:locale"> 和备用语言(og:locale:alternate)。在社交媒体分享时,可以传达该页面使用的语言。
- •由代码绘制的公开系统页面也会收录到
sitemap.xml(之前遗漏了)。
- •
llms.txt 的第一行(网站说明)以访问者的语言显示。
- •每个页面的 robots 设置(管理页面里有输入框,但没有任何地方读取)现在真正生效。
修复的问题
- •
?lang= 的值只有在与支持的语言列表核对后才会被接受。以前不支持的值会在 Cookie 中保留一年,
之后打开该语言时,可能违背访问者本人的意愿跳转到那个页面。语言选择器也遵循同样的规则。
- •组件构建器:页面上没有输入框的语言,其翻译在每次保存时都会被删除的问题。
- •社区消息搜索:姓名以加密方式保存,导致输入任何姓名都是 0 条结果的问题。现在先解密再匹配。
更新时保护网站自行修改的核心文件
- •在
storage/custom/update-preserve.txt 中每行写一个路径(# 为注释,也可以写文件夹),更新就不会覆盖这些文件。
用于保护直接写入核心文件的内容,例如网站专用的登录规则。不接受绝对路径和 ..,
即使读取不到该文件,更新也不会中断,而是按默认保留列表继续进行。
- •需要了解:执行更新的一方必须已经具备这个功能才有效。它从升级到 2.8.1 之后的更新开始生效。
有什么变化
支付模块原本每个服务商就有各自的文件,但“有哪些服务商”被写在了代码的多个地方。
要加入新的服务商,必须同时修改支付管理代码、设置页面和 Webhook。
- •把文件夹(
gateway.json 加实现文件)放进 rzxlib/Modules/Payment/Gateways/,核心会自动识别。
管理设置页面里的服务商选择、密钥输入框和 Webhook 地址都由该规格文件生成。
- •网站仍然在设置页面中选择一个服务商(与以前相同)。这不是同时使用多个服务商的功能。
- •添加方法整理在
docs/PAYMENT_GATEWAYS.md 中。
Square
- •支持银行卡支付、退款、查询、已保存银行卡(用于定期扣款)和 Webhook(含签名验证)。
- •银行卡输入表单会进行持卡人认证(SCA),失败时在页面上说明原因。支持 13 种语言。
- •管理设置页面新增了“连接测试”按钮。在测试模式下执行小额支付 → 查询 → 退款,
用来确认密钥设置是否正确。不会有真实资金流动,在正式(live)模式下也不会运行。
- •在选择 Square 之前,对任何网站都没有影响。
现有服务商(PAY.JP·Stripe)保持不变
- •这两个服务商的实现文件没有改动。旧设置(单一密钥、v2、v3)仍然照常读取。
- •即使出现无法读取规格文件的情况,也设置了保护措施,使 PAY.JP 和 Stripe 按原来的方式创建。
- •我们用运营网站的真实设置和多种形式的合成设置,对比了旧代码和新代码,确认它们选择相同的服务商、相同的模式、相同的密钥
(scripts/test-payment-parity.php)。
按网站读取支付设置
当同一个数据库中为每个网站分别保存了支付设置时,支付模块现在读取自己网站的设置。
以前并没有规定会选中哪个网站的设置。如果该网站没有自己的设置,则与以前一样运行。
需要了解
- •新增了共用的 Webhook 地址(
/api/webhook-payment.php?gateway=…)。现有 PAY.JP 和 Stripe 的 Webhook 地址不变。
- •设置页面的服务商列表保持原来的顺序,通过规格文件加入的服务商排在后面。
v2.7.17
2026-09-21 · 28天前
插件内容现在能被搜索和 AI 引擎看到
问题是什么
站点地图(sitemap.xml)和 AI 说明文件(llms.txt)只收录了核心已知的内容。
插件要加入自己的页面,只能直接修改核心文件,而这种修改
每次更新都会消失。此外,核心是靠猜测来读取插件列表的,所以有些地方悄悄地出现了偏差。
- •房产信息只在单独的地址(
/properties-sitemap.xml)输出,如果没有任何地方指向该地址,
搜索引擎就找不到它。
- •市场商品因为查询语句去找一个根本不存在的字段,从来没有出现在站点地图里。
错误被直接吞掉,所以没有人发现。
- •有些网站把店铺地址写成了错误的形式,导致搜索引擎收录了打开后根本没有页面的地址。
插件自己输出自己的页面
- •在插件的
plugin.json 中写上 seo,核心就会读取并合并进站点地图和 AI 说明文件。
方式与组件、布局和内网模块相同,地址冲突时以核心为准。
- •多语言地址和语言标记由核心自动添加。插件只需要给出地址。
- •某个插件出错也不会让整个站点地图失效,只会少掉那个插件的部分。
- •已停用插件的地址会自动被排除——停用插件的页面本来就打不开。
中文备用地址被忽略的问题
站点地图把语言标记写成了 zh_CN,而标准写法是 zh-CN,所以谷歌整行忽略了它。
页面本身写得是正确的,因此同一个网站在两个地方说着不一样的话。
现在简体和繁体中文的备用地址都能被正确识别。
按语言提供 AI 说明文件
- •
llms.txt 以前只有默认语言一份。现在可以输出 ?lang=en 这样的语言版本。
商品名称和说明会以该语言输出,说明文件的开头会写明是哪个语言版本。
- •在多语言网站上,AI 回答引擎就能向各语言地区的用户介绍这个网站。
员工可以查看自己的人事卡(内网)
- •原来只有人事负责人才能看的人事卡,现在本人也可以查看。从顶部的个人资料菜单进入。
- •只能查看。如果有需要修改的内容,申请后由人事负责人批准的流程正在准备中。
- •评价对本人不可见。奖惩也一样。附件文件只显示列表。
- •无法通过修改地址栏来打开别人的卡片——是谁的卡片只由登录信息决定。
- •本人也可以查看是谁查阅了自己的人事信息。
v2.7.16
2026-09-21 · 28天前
论坛链接基准地址与插件布局
让论坛页面能在其他外壳中使用
论坛页面里的所有链接都由同一个值($boardUrl)生成,但核心总是无条件覆盖这个值。
因此像内网这样在管理页面内使用论坛的一方,不得不对已经渲染好的页面逐字进行替换。
只要核心稍微改动链接的形式,就会悄悄出现偏差。
- •如果调用方事先指定了基准地址,就使用该值。如果没有指定,则与以前完全一样。
- •齿轮(论坛设置)链接也在一处统一决定。以前列表、FAQ、问答和链接皮肤这四处各自生成。
布局可以放在插件里
- •查找布局时先找核心的
skins/layouts/,没有再找插件的 plugins/{id}/skins/layouts/。
规则与组件和内网模块相同,同名时以核心为准。
- •管理页面的布局选择器中也会同时显示插件布局。
- •到目前为止,插件专用布局必须放在核心文件夹里。更新不会删除它,
但之后如果核心推出同名布局就会被覆盖,而且把插件迁到其他网站时还得手动带上这个文件夹。
v2.7.15
2026-09-21 · 28天前
插件声明内网模块 · 日期输入支持日本年号
插件自己声明内网模块
内网页面(左侧菜单和入口路径)的列表,以前只存在于核心的一个设置文件中。
插件要加入自己的模块,必须修改核心文件,而更新后这些内容就会消失。
- •在插件的
plugin.json 中写上 intranet_module,核心就会读取并合并。方式与菜单和系统页面相同。
- •值可以直接写数组,也可以像
"data/intranet-module.php" 这样写文件路径。
- •同名时以核心为准。插件无法劫持核心模块来改变其默认行为。
- •核心中读取这个列表的 5 个位置全部改成了新方式。即使更新覆盖了设置文件,插件模块也会保留。
日期输入支持日本年号(和历)
- •在日语页面的日期输入框中,选择年号(令和、平成、昭和、大正、明治)并输入年数,公历年份会自动填入。
像出生日期这样习惯用年号记忆的值,不必每次都换算。
论坛布局设置没有反映到页面的问题
- •在管理页面中为每个论坛选择了布局,页面上显示的却是网站的默认布局。
保存的位置和读取的位置不一致。
已有的论坛在重新保存之前外观保持不变(外观不会突然改变)。
v2.7.14
2026-09-20 · 29天前
论坛发帖与搜索恢复正常
发帖后没有保存的问题
- •保存帖子时漏掉了标题字段,所以在仍保留该字段的网站上保存会失败。
页面上只显示“Unexpected end of JSON input”。
- •修复:如果该字段仍存在,也会同时填写它。已删除该字段的网站与以前一样运行。
论坛搜索
- •搜索在查找旧字段,所以在已删除该字段的网站上,一输入搜索词,整个列表就打不开了。
- •保留该字段的网站也有问题。修改帖子后该字段不会更新,所以只能搜到修改前的内容。
- •修复:改为在翻译表中搜索。现在可以搜到当前浏览的语言以及已翻译的内容。
列表、组件和个人中心里看不到帖子的问题
- •业务领域标签组件和论坛网格组件一直显示空列表(错误在内部被吞掉了)。
- •个人中心的“我的评论”里完全缺少论坛评论。
- •链接论坛皮肤的标题始终为空。
- •修复:全部改为从翻译表读取标题和正文。缩略图也会重新从正文中找出来。
AI 翻译与全新安装
- •修复了帖子 AI 翻译在读取原文时失败、导致翻译任务全部失败的问题。
- •修复了全新安装时加入的示例帖子原始语言的标题和正文没有写入翻译表,导致标题看起来为空的问题。
其他
- •修复了论坛排序设为“按推荐”时列表打不开的问题(引用了不存在的字段)。
v2.7.13
2026-09-20 · 29天前
管理提示框更安全 · 多语言
提示框直接嵌入他人输入的文字
管理界面的通用提示框(结果弹窗)会把菜单名称、皮肤名称、服务器返回的文案原样贴到页面上。
只要在名称里写入 <script> 之类的内容,其他管理员打开该页面时就可能被执行(存储型 XSS)。
- •修复:提示框中的所有文案(标题、正文、按钮、确认语)先转换为纯文字显示再插入。
- •数据库连接失败时的提示语也改用译文,并经过同样的转换。
提示框按钮在任何语言下都显示韩文
- •「确认」「取消」被硬编码在 JavaScript 里。现在按当前浏览的语言显示。
由服务器提供当前语言的文案,脚本读取该值。
管理界面文案支持 13 种语言
将设计(皮肤)、菜单、页面设置界面中硬编码的韩文提示改为翻译键,并补齐 13 种语言。
- •皮肤:重命名、复制、删除的结果;「皮肤文件与设置将被永久删除」确认语;图片上传结果
- •菜单:系统页面仅从菜单移除的说明;「关联页面(版块)也会一并删除」确认语
- •页面设置:文件格式、保存失败、URL 重复的提示
v2.7.12
2026-09-19 · 1个月前
私密文章保护 · 首屏显示提速
私密文章在列表中泄露
设为私密的文章,列表里仍然显示标题、封面图和摘要,被隐藏的只有正文。
- •修复:列表中也只有作者、管理员或输入了密码的人才能看到标题与预览。
- •同时堵上了通过附件地址窥视内容的口子,附件采用同样的判断。
- •阅读页面的上一篇・下一篇标题也会隐藏。
- •读取列表的挂件(版块卡片、网格、标签页等)在查询时就排除私密文章。
首屏迟迟不显示
手机上第一个字出现得很慢,原因是字体。
- •字体 CSS(Google Fonts 152KB + Pretendard 29KB)挡住了绘制。
现在先用系统字体绘制,网页字体下载完成后再替换。
- •Pretendard 只在韩文界面加载。 日文界面优先使用日文字体,此前只是下载碎片后丢弃。
- •两个小样式表(文字大小、版块正文)改为直接写入页面,不再单独请求文件。
- •首次访问时因页面缓存(Service Worker)重复读取文档的问题已消除。
- •横向滚动菜单的宽度计算推迟到页面加载完成之后(此前会卡住 0.5 秒)。
让搜索机器人与 AI 能跟踪各语言页面
- •语言切换链接改为真实网址(
?lang=…)。此前是 JavaScript 链接,机器人无法跟踪。
管理界面
- •页面列表中同一页面按语言数量重复多行,现已合并为一行。
- •仅修改菜单标题时其他语言译文被清空的问题已修复。只有更换链接页面时才会清理。
- •博客预约发布填入过去时间时会照样保存,现在会提示并保持原状态(13 种语言)。
通知与文案
- •社区私信通知的标题固定为韩文,现按收件人的语言发送。
- •Cookie 提示条的链接文字过暗,已调亮。
内部整理
- •删除了误复制成两份的管理界面目录(
admin/site/site、admin/components/components)。
实际使用的是原目录。发行版构建也会排除这些目录。
v2.7.11
2026-09-13 · 1个月前
站点地图排除私密版块 · 提升邮件送达率
站点地图中收录了私密版块
连只有管理员才能看到的版块(如咨询受理箱等)的地址也被收录进了站点地图。
搜索引擎机器人在这些地址上只能得到 403(禁止访问),而且私密版块的存在也暴露了出来。
- •修正:只收录非会员可以查看的版块。以列表和帖子阅读权限设为「全部」的版块为准。
- •秘密帖子,以及在版块设置中设为不被搜索收录(noindex)的版块,也会被排除。
- •与版块同名的页面以版块为准进行判断,因为地址会先被版块占用。
- •多语言页面也会收录到站点地图中。
- •不希望在某个网站收录的页面,可以写在设置
sitemap_exclude 中。llms.txt 也遵循同一设置。
发出的邮件进入垃圾箱或被退回
- •邮件中缺少发送时间(Date)和邮件唯一编号(Message-ID),因此收件方很容易将其判为垃圾邮件。
现在两者都会加上,正文以 base64 发送。同时也防止长行被截断,以及行首的「.」导致正文中断的问题。
- •当收件地址与发件地址属于同一域名时(例如发到公司邮箱的副本),该域名的邮箱会将其视为冒充而拒收。
仅在这种情况下,改为从 SMTP 账户地址发送,回复仍发往原来的地址。
加强 SEO 与 AI 搜索设置
- •在管理后台的 SEO 设置中新增了运营者信息(结构化数据 Organization)输入栏。没有填写值的项目不会输出。
- •真正使用每个页面的 SEO 设置;同一内容可通过多个地址访问时,会确定一个规范地址(canonical)。
- •新增了必应(Bing)网站验证码输入栏。ChatGPT 的搜索使用必应的索引。
- •描述文字会按搜索结果的显示宽度截取,并在句末而不是句子中间截断。
整理语言显示
- •404 页面一直以韩语显示。现在会以正在浏览的语言显示(日语、韩语或英语,其他语言显示英语)。
- •修正了通知铃中写死为韩语的「刚刚」。
- •日语页面优先使用日语字体。按语言选择字体的辅助函数会始终加载,因此不经过布局的页面(如分享页面)也不会再因字体而中断。
- •整理了「我的页面」中「首选语言」连没有文案的语言也一并列出的问题。
- •注册会员时,会把当时浏览页面的语言保存为首选语言(此前一直为空)。重置密码的邮件也以该语言发送。
输入与登录
- •出生日期等日期改为用年、月、日 3 个输入框填写。以前显示方式会随浏览器语言而变化。
- •修正了部分皮肤在登录和找回密码时漏掉 reCAPTCHA 验证的问题。
支付
- •按支付服务商(PG)分别保存测试密钥和正式密钥。测试模式只需选择即可,切换时不会再弄丢密钥。
小组件
- •主视觉(hero)小组件的按钮现在可以在新窗口中打开。
- •小组件构建器中的重复项目也可以按语言分别填写(地球仪按钮)。
构建
- •配置文件(.env)及其备份,无论名称如何,都不会放进发行版。
- •编辑时留下的备份文件(
.bak,包括名称后带日期的)也不会放进去。
- •仅用于总部运营的脚本(网站同步、主机托管、邮件服务器、条款更新等),以及只被发行版中没有的插件使用的定时任务(cron),已从发行版中移除。客户网站需要的更新、安装、翻译工作进程等脚本仍然包含在内。
- •生成 zip 后会再检查一次,如果其中含有配置文件或备份文件,就停止发布。
- •测试脚本不再把密码写在文件里,而是从设置中读取。
v2.7.10
2026-08-23 · 2个月前
更新后版本名称仍是旧的问题
更新后版本名称和发布日期没有变化
只有编号升上去了,标题仍然是上一个版本的。
管理界面里显示成“2.7.9 · 日语字体 · 合同续约提醒…”这样,编号和名称对不上。
光看界面,无法知道收到的到底是什么。
- •原因:
version.json 是为了保护每位客户各自的设置而 特意不覆盖 的文件。
所以由更新程序自己来填写,但它 只换了编号和时间,标题和发布日期原样保留。
- •修复:新版本的标题和发布日期现在 从收到的安装包中读取,一并写入。
对没有安装包的部分更新,则从发行清单(manifest.json)中读取。
每位客户各自的设置(github 等)保持不变。
注意 — 即使升级到这个版本,界面上显示的可能仍是旧名称。 因为执行更新的是
当前已安装 版本的更新程序。从收到 2.7.10 之后的下一个版本起才会正确显示。
构建检查
2.7.8 中构建器失灵的问题(在 2.7.9 修复)原样通过了回归测试。
因为原有的检查只看“文件是否存在 · 是否包含某个字符串”。
- •现在会对放入构建器的脚本 真正生成并做语法检查(
node --check)。
- •如果有代码把多行文件原样放进 JS 字符串,会 指出行号 并阻止构建。
- •我们用重现 2.7.8 的文件做了试验,确认该检查确实能拦截。
v2.7.9
2026-08-23 · 2个月前
小部件构建器失灵的问题(2.7.8 的回归)
症状
- •面板中 一个小部件都看不到
- •已经放置的小部件 没有绘制到画布上 — 放入的视频、图片等看起来像是消失了
- •无法保存
原因
2.7.8 中我们把字体声明集中到了 partials/fonts.php 这一处。但生成构建器预览的位置
位于 JS 字符串的一行之内, 33 行的字体声明被原样塞了进去。
一换行,字符串就被截断,整个构建器脚本在被读取之前就崩溃了。
由于是整个文件崩溃的类型,表现不是“部分功能异常”,而是 构建器什么都不做。
2.7.5 及以下版本没有这个问题。
修复方法
字体定义仍然保持在 fonts.php 这一处,只在放进构建器时把输出折成一行并处理引号。
需要修改字体的位置依然只有一个。
v2.7.8
2026-08-22 · 2个月前
日语字体 · 合同续约提醒 · 3-D 安全验证
默认字体改为以日语为基准
此前默认字体以韩语为基准。主要用户在日本, 画面却显得别扭,
而且切换语言字体也不变,日语文章被排成了韩语字体。
- •默认值改为 标题用明朝体,正文用 Pretendard JP。
- •在语言设置界面可以 为每种语言单独指定字体。 不指定时,会套用适合该语言的默认值。
- •管理员、会员、前台的全部界面以及所有皮肤(default、modern、minimal、shop)都适用同一规则。
合同续约与免费期结束提醒
过去有时 过期之后 才发现合同到期。现在临近续约日时会提前通知。
- •将在 日期到来之前 以通知形式提示即将续约和免费期结束。
- •通过一行 cron(
cron.d-voscms-contract-notice)运行,安装说明中已加入注册方法。
银行卡支付
通过日本发卡机构验证(3-D 安全验证)的支付,出现了 验证通过但扣款被拒绝 的问题。
- •PAY.jp 会阻止直接使用为验证而生成的令牌。验证通过后,服务器必须再发起一次收尾调用,
之后才能用于扣款,而这一步被漏掉了。
- •我们还开通了 提前确认 客户信息是否仍保留在支付公司一侧的途径 — 防止用已被删除的客户去尝试扣款而失败。
通知铃与退款规定文案多语言化
- •页眉通知铃中“没有通知”“几分钟前”等 写死为韩语的文案,现已改为按语言显示。
- •整理了退款规定说明中残留的固定文案。
会计
日本法人的账簿中 混入了韩元交易,导致合计对不上。
- •与账簿币种(日元)不同币种的凭证 不生成分录。 记录会保留,但不会进入账簿。
发行版整理
- •编辑过程中产生的 备份文件被带进了发行版(形如
文件名.php.bak.数字)。
排除规则只过滤了 .bak,漏掉了带数字的名称。现已连同 .bak.、.orig、*~ 一并拦截。
- •将 THEVOS AI 服务的 销售资料(价目表、套餐计算、支付对账 cron)从发行版中移除。
读取它们的一侧早已全部移除,所以在发行版中是没有人使用的文件。
v2.7.7
2026-08-10 · 2个月前
全新安装时出现的两个警告
“需要 DB 迁移”
039_ai_knowledge_base 用于创建 NaitoWork X 门店咨询 AI 的表,
却原封不动地随发行版发布了。而且该文件的 最后一行 是
ALTER TABLE rzx_shop_inquiries ADD COLUMN IF NOT EXISTS ai_meta ...
rzx_shop_inquiries 是 由 vos-store 插件创建的表。
发行版中没有 vos-store — 核心试图修改一个并不存在的插件的表。
于是每个新安装都是:创建了 4 张表,在最后一行失败 → 没有执行到最后,
所以不会记录为“已应用” → 横幅永久显示,点击后又在同一个地方失败。
现已把 AI 咨询(RAG)从发行版中整体移除:
039 · rzxlib/Core/AI/{Knowledge,Embedding,Generate} ·
scripts/{ai-kb-ingest,ai-rag-test,cron-ai-consult,hanesbot-ingest}.php
AI 翻译(rzxlib/Core/AI/Translation)予以保留。 它是付费插件 vos-ai 的
引擎,与会计、托管一样,遵循“引擎放在核心,功能由插件开启”的规则。
“1 个插件未认证(vos
核心持有一份 “无需许可证即可使用的随附插件” 清单,而这份清单已经过时。
代码以为的随附 | vos-autoinstall · vos-marketplace |
实际发布的随附 | vos-autoinstall · vos-community |
vos-marketplace 已从发行版中移除,由 vos-community 取而代之,
但 只有这份清单没有改。 明明随附了,却不知道是随附的,于是弹出警告。
防止再次发生
原因在于 随附清单写在两个地方 —
构建脚本的排除清单和 LicenseStatus::BUNDLE_PLUGINS。
我们在构建中加入了 核对步骤。 两者不一致时不生成 zip,直接停止。
这不应该靠人去记。
v2.7.6
2026-08-10 · 2个月前
留言板发帖按钮 · 多语言标题 · 安装时的迁移
留言板上看不到发帖按钮
在 Q&A 和 FAQ 中,连有权发帖的人也没有按钮。 原因有两个。
- •管理员被挡住了 — 检查发帖权限时,先判断是不是会员,之后才看管理员。
管理员不在 users 中,所以在第一道关卡就被拦下。现在调整了顺序,让管理员先通过。
- •一篇帖子都没有时,按钮也跟着消失 — 按钮位于列表内部,
一旦页面切换到“暂无帖子”的画面,按钮也一起没了。第一个发帖的人反而没法发帖。
现已把按钮移到列表之外。
- •FAQ 甚至直接查看
admin_id — 无视了留言板设置中的发帖权限。
留言板的标题和副标题以其他语言显示
中文界面里只有副标题显示成日语的问题。
- •根本没有读取翻译。 标题和副标题在皮肤设置中以 单个字符串 保存,
而翻译另外存放在 rzx_translations 中。界面只是原样输出保存的字符串。
- •没有区分留言板。 翻译键是
skin_config.subtitle_text,所以 Q&A 和 FAQ
共用同一个位置。 改了其中一个,另一个也跟着变。
现已拆分为 board.{留言板编号}.{项目}。
- •在语言确定之前就渲染了正文。 核心先生成正文,再附上页眉,
而语言是在页眉中确定的。现已改为在正文一侧先确定。
安装时漏掉了核心迁移
install-core.php 完全没有查看 database/migrations。
新安装的站点从一开始就缺少几张表,之后启用相应功能时就会崩溃。
迁移被悄悄跳过的问题(接 2.7.4)
2.7.4 处理了单行注释(--),但 多行注释(/ /)仍然存在。
该代码块中的分号使文件被合成一整块,一行也没有执行,
却被记录为“已应用”。我们确认了实际损失 — 有的安装缺少整整 9 张表。
字符串中的 -- 或 /* 不是注释。现在一边统计引号一边去除注释。
其他
- •购物页眉 — 在分类下拉菜单的最上方加入了“全部分类”。
想进去逛一逛的人原来无处可去。
- •小部件构建器 — 将重复项(
repeater)的编辑拆分到单独的文件。
- •内部网侧边栏 — 会计文案在三条分支(沙龙、购物商城、一般企业)中都会查找。
以前只看其中一个,所以使用其他会计时菜单会直接显示原始键名。
- •我的页面 — 整理了仪表盘。
- •付费插件报告 — 许可检查时会一并发送 已启用的付费插件。
只安装、没有启用的不会发送 — 费用只与启用的插件挂钩。
v2.7.5
2026-08-05 · 3个月前
从发行版中移除总部专用的系统页面
总部专用的页面被带进了发行版
config/system-pages.php 被整个放进了发行版,导致客户安装的管理员“系统页面”中,
出现了六个可以点击却什么都没有的菜单。
📥 downloads | 发行版下载 — 只有总部发布 |
📋 changelog | 这是总部的产品历史 |
📧 contact | 客户用组件自己制作(它不是系统页面) |
💼 recruit · 💃 casts | 仅限夜间业务门户(NaitoWork X)使用 |
🎟 coupons | 由应用市场的插件提供 |
- •新增了构建步骤
[4e/8](strip-system-pages.php)。删除之后用 php -l 检查语法 —
如果这个文件损坏,整个管理页面就会瘫痪。
- •发行版中保留的系统页面有八个:home · terms · privacy · data-policy ·
refund-policy · hosting-terms · tokushoho · funds-settlement
插件系统页面
- •在 13 种语言中加入了
site.pages.blog 文案。
即使插件注册了系统页面,如果核心中没有对应文案,屏幕上就会原样显示 site.pages.blog。
- •(对
vos-blog 自身 plugin.json 的修改通过应用市场发布 — 这是一个不在发行版中的插件)
已经安装的网站
如果管理员“系统页面”中出现不使用的项目,把 config/system-pages.php 中对应的块删除即可。
页面内容(rzx_page_contents)不会被删除 — 只是从列表中消失。
v2.7.4
2026-08-05 · 3个月前
迁移被悄悄跳过的问题
① 以注释开头的迁移被整个跳过
- •
DatabaseMigrator::splitSql() 的注释写着“去除注释后再分割”,但
实际上只是按分号分割。
- •如果 SQL 文件的第一行是
-- 说明,整个文件就成了一个片段,
被执行部分的 str_starts_with($stmt, '--') 拦住,一条语句也没有执行。
- •执行为 0 条,错误也是 0 条,所以被当作
success 处理,并记录为已应用。
一旦有记录就不会再次执行,所以表会一直缺失、永久固定下来。
- •受影响的范围是所有以
-- 开头的文件。实测:9 个中有 6 个执行了 0 条,2 个只执行了一部分。
- •现在会先去除
--、# 行注释和 / / 块,然后再分割。
字符串里的 -- 不会动(如果 'a -- b' 这样的值被截断,数据就会损坏)。
② 全新安装根本没有运行增量迁移
- •安装脚本只执行了
migrations/core 和 migrations/migrations,
漏掉了最上层的 database/migrations/*.sql。 而更新程序恰恰相反,只跟踪最上层。
- •因此全新安装时 034~042 从一开始就不存在,直到下一个版本到来之前都是空的。
- •现在安装时也会执行最上层,并记录为已应用(避免第一次更新又把同样的内容再运行一遍)。
已经安装的网站
请在管理员 → 设置 → 更新中点击一次运行迁移。
被错误记录的内容不会再次运行,所以如果表是空的,可以用下面的方式确认。
SELECT migration FROM rzx_migrations; -- 记录
SHOW TABLES LIKE 'rzx_home_notices'; -- 实际
v2.7.3
2026-08-05 · 3个月前
发行版插件整理 · 购物页眉 · 个人中心余额
从发行版中去掉的内容
- •
vos-cp(服务控制面板)和 vos-shopping(网上商城)一直夹带在发行版里。
这两个都是新做的插件,只是还没有列入排除名单而已。
- •
vos-cp 是 THEVOS 自家服务使用的面板。没有理由出现在客户的安装中
- •
vos-shopping 仍在开发中(v0.1.0),而且原则是插件要在应用市场购买
- •
vos-review 也去掉了 — 理由相同(店主的指示)。
- •发行版中包含的插件只有两个:
vos-community、vos-autoinstall。
其余全部从应用市场获取。
加入核心的内容
- •商城两层页眉(
skins/layouts/shop) — 全部分类下拉菜单、搜索、购物车预览、
登录后的头像菜单。在分类下拉菜单的最上方放了“全部分类”,让人有路可以返回
- •在个人中心显示积分、储值金和会员等级。名称直接使用所设置的值
- •支持插件组件 — 插件只要放了
widgets/,核心构建器就会自动识别
- •邮政编码地址搜索公共组件 — 订单页和会员信息使用同一个组件
- •管理员顶栏的通知铃铛
- •整理了管理控制台菜单分组(
config/intranet-modules.php)
- •支持组件构建器的重复字段(repeater)
修复的内容
- •多语言输入字段覆盖原始数据的问题
- •储值金账本记录的错误
- •发行版更新会让托管页面变成 404 的问题
在已安装的版本上需要确认的事
对于用旧发行版安装、之后只接收更新的网站,会留下不使用的插件文件夹
(更新不会删除插件文件夹)。在管理员 → 插件中显示为未安装的,
可以连同文件夹一起从 plugins/ 中删除。
v2.7.2
2026-07-26 · 3个月前
服务申请路由整理(核心重新构建)
Changed
- •服务申请 URL 的统一路由 —
/service/hosting、/service/mail、/service/domain → 以 302 连接到 /service/order(在专用申请页面准备好之前,引导到整合申请页面,以后可以替换为专用页面)。
Notes
- •2.7.1 的核心修复(多语言 hreflang、防止更新程序静默失败、把价格
/pricing 合并到 /service/order)已经正常包含在 2.7.1 的软件包中。2.7.2 是在此基础上增加服务申请路由整理的重新构建。
- •发行版原则上只包含纯核心(排除付费和垂直行业插件)。总部网站(voscms.com、thevos.jp)不是发行版自动更新的对象,而是通过源码/git 部署。
SEO
- •多语言 hreflang — 每个页面自引用 canonical + 自动生成所支持语言的 hreflang,通过
?lang=xx 按语言建立索引,把默认语言的 ?lang 以 301 规范化为不带参数的 URL,并扩展了 sitemap。
Fixed
- •修复更新程序的静默失败 — 把核心文件或 version.json 的写入失败作为异常处理。因权限不足等原因导致应用失败时,不再误报“SUCCESS”,而是给出明确的错误并自动回滚。
- •防止了价格页面中多语言字段以数组形式传给 htmlspecialchars 而导致 500 崩溃的问题。
Changed
- •扩展了 reCAPTCHA v3 按表单设置的开关(blog_comment 等)。
- •设置中的“店主控制台通知”标签页仅在 vos-store 启用时显示。
- •把价格页面
/pricing 合并到 /service/order(301),“系统无限”套餐仅限管理员。
v2.7.0
2026-06-27 · 4个月前
发行版核心精简化 + 组件与设置大幅增强
发行构成
- •发行版精简为纯核心 — 只附带 3 个核心插件(
vos-autoinstall、vos-community、vos-review)。垂直行业(夜间业务/沙龙/POS)的插件、组件和皮肤(story)全部排除。年龄验证、Cookie 横幅等通用功能属于核心(rzxlib),因此包含在内。
Added/Changed (核心组件)
- •location-map — 支持无密钥嵌入(
map_embed),消除了对 API 密钥的依赖,并使地图语言与区域设置联动
- •practice-tabs(业务领域标签页) — 新的内置组件
- •全局页面宽度设置(
widget_page_width) — 统一组件/文档页面的宽度
未内置(bundled:false)的网站专用组件(hero-slideshow、overlap-cards、office-intro、page-hero、content-head、consult-cta、board-grid、clients-logos、board 的个人资料皮肤)不包含在核心发行版中。
Removed
- •预付组件(
prepaid-charge、prepaid-pass、prepaid-purchase) — 由于 vos-prepaid 未内置,从发行版中排除
Added (设置与核心)
- •把年龄验证关卡提升为核心的常规设置
- •Cookie 同意横幅的背景透明度调节
- •按语言设置的徽标图片
- •在企业信息中加入银行账户信息 + 银行转账说明
- •支付页面的“可使用的银行卡”说明(品牌图标) + 管理员设置
Fixed
- •页面标题和副标题的多语言本地化(page-scoped db_trans),并修复 content_width 未生效的问题
- •修复了组件/管理页面/页面中的大量错误,并补充了 13 种语言
v2.6.24
2026-06-02 · 5个月前
更新时自动清理 orphan(已删除的源文件)
Added
- •自动清理 obsolete 文件 — 用完整包 zip 覆盖的更新无法删除源中已移除的文件,因此发行版中留下了残留文件(orphan)(例如在重构中被拆分并删除的整体式
settings.php 仍留在旧的安装中)。我们新增了一个基于明确列表的机制来清理它们。
- •
config/obsolete-files.php — 待删除路径的累积列表(跳过了多个版本的安装也能一次性清理)。
- •在更新程序的
applyUpdate() 之后,cleanupObsoleteFiles() 会安全地 unlink 列表中的文件。绝不会触碰保留对象(.env、storage 等)、路径逃逸和目录。
- •首次登记:
resources/views/admin/settings.php。
v2.6.23
2026-06-02 · 5个月前
更正仪表盘“系统设置”链接
Fixed
- •仪表盘“系统设置”链接 — 快捷操作中的链接指向已被拆分并删除的旧路径
/settings,导致跳转到错误的(回退)页面。现已更正为设置的默认入口 /settings/general。(2.6.22 构建之后遗漏的部分)
v2.6.22
2026-06-02 · 5个月前
修复运行迁移时的 CSRF 和记录错误
Fixed
- •仪表盘“需要 DB 迁移”横幅 — CSRF token invalid — 重试按钮没有向
/update-api.php(run_migrations)发送 CSRF 令牌,因此被以 419 拒绝。现已确保 $_SESSION['csrf_token'] 存在,并通过请求头和请求体发送。
- •执行迁移后横幅依然不消失 —
DatabaseMigrator::recordMigration 假定存在 batch 列和 patch_ 前缀,导致在安装型结构(migration/version/executed_at)上记录 INSERT 失败,而且前缀还使文件名匹配出现偏差。现已改为按实际列、原样记录文件名。(这是 2.6.20 更新时迁移只留下“OK”日志却没有应用的原因)
Fixed
- •管理员权限管理等核心页面侧边栏的原始键 — 由于仅凭
config/intranet-modules.php 的 route_prefixes 就启用内网 layout,在没有对应插件的网站(例如未安装 vos-salon)上,核心页面 /staff/admins 会以 salon 内网侧边栏渲染,导致 salon.intranet.、salon.section. 键以原始文本暴露。现已修复。
- •新增公共辅助函数
resolve_intranet_module() — 只有模块的 lang 资源(插件)确实已安装时才启用内网,未安装时回退到核心的 admin-sidebar。
- •把
_head.php / admin-sidebar.php 中重复的检测逻辑统一到辅助函数中。已安装插件的网站(salon、store 等)行为不变。
v2.6.20
2026-06-02 · 5个月前
积分/等级/分组结构一致化(解决等级保存错误)
Fixed
- •积分等级保存错误 — 修复了在管理员积分模块中保存等级时因
Unknown column 'group_id' 错误而失败的问题。原因是 core/004 与 migrations/019(v190) 在 point_levels/member_points 结构上的冲突(019 中的 CREATE TABLE IF NOT EXISTS 无法给已有的表添加新列)。
- •migration
034_point_system_schema_reconcile(最上层,更新时自动应用):
- •
point_levels — 新增 group_id,为 name 设置默认值,为 level 建立唯一索引(使 upsert 生效)。
- •
member_points — 新增 point/balance/total_accumulated/level。
- •全部为 additive(无数据丢失),不影响已有的列和使用方(vos-prepaid 等)。
Added
- •3 个购买组件 — 整合型(
prepaid-purchase,可选择显示全部/仅充值/仅次卡) + 仅充值(prepaid-charge) + 仅次卡(prepaid-pass)。用一个公共组件 purchase-widget.php 驱动 3 个组件(零重复),通过 $ppOnly 过滤器分支。
- •商品背景图片 — 在管理员的商品添加/编辑弹窗中加入拖放上传(同时支持点击上传),并把背景应用到个人中心和组件卡片。migration 003
image_url。
- •商品名称多语言输入 + AI 翻译 — 复用公共的
multilang-modal(地球按钮),基于 rzx_translations 保存,并通过 prepaid_name() 以访问者的语言显示。AI 翻译复用核心的 /api/translations 端点。
- •在支付表单中新增持卡人姓名输入栏(传给 PAY.jp 的
createToken)。
- •手动充值时选择客户 — 从直接输入 user_id 改为按姓名/电话/邮箱搜索的自动补全(
customer_search 操作)。客户状况列表也显示客户姓名 + 邮箱,而不是 user_id 哈希。
- •启用开关 — 把商品启用复选框改为开关。
Changed
- •购买框改为 4 列 — 商品卡片网格改为 2→3→4 响应式(
lg:grid-cols-4),并移除组件宽度 max-w-3xl 的固定值 → 适应放置容器的宽度。
Fixed
- •组件构建器调色板·大型菜单高度 — 把构建器的行高确定为
calc(100vh - 88px),使左侧分类和弹出菜单自动占满屏幕高度,并解决了大型菜单项目重叠的问题。
v2.6.18
2026-05-31 · 5个月前
公告发送表单的 URL 校验 + 友好的输入体验
Added
- •
api/broadcast.php 的 link 校验 — 缺少协议时自动在前面补上 https://(example.com → https://example.com),如果未通过 filter_var FILTER_VALIDATE_URL,就返回 400 + field: 'link' 错误,超过 500 个字符则拒绝。
- •客户端实时校验 —
type="url"、inputmode="url",输入时立即:
- •缺少协议 → emerald 外框 + ✓ + “发送时将自动补全:…”提示
- •主机中没有点(.)或格式不对 → red 外框 + ⚠ + “不是正确的 URL 格式”
- •正常 → emerald 外框 + ✓ + “是有效的 URL”
- •客户端也会先补全再发送 → 保证预览与实际发送的正文一致。
Added
- •区块标题:✉ 撰写消息 / 📡 发送渠道 — 视觉分组 + 说明文字。
- •字数计数器(标题
0/255,正文 0/2000) — 达到 70% 以上自动变为 amber,达到 90% 以上变为 red。
- •消息预览框(点线边框) — 实时渲染标题、正文和链接合在一起后在 LINE 中的显示效果 + 总字数
n/5000 计数器(超过 4500 变为 red)。
- •每个字段的 helper text:
- •标题:“会同时显示在会员消息箱和 LINE 通知中”
- •正文:“在正文中写入 URL,会自动缩短并进行点击追踪”
- •链接:“会空一行自动添加到正文末尾。如果正文中也写了,会显示两次,请注意”
- •链接输入框右侧的状态图标(
absolute) — 立即显示 ✓ / ⚠。
Added
🔗 URL 校验规则(新增第 5 个区块):
- •需要以
http:// / https:// 开头 → 转换为点击追踪令牌
- •缺少协议时自动补全
- •拒绝主机中没有点或格式不对的情况
- •500 个字符的限制
- •示例框:
✓ https://voscms.com/event / ✓ example.com/page → 自动补全 / ✗ asdfasdf (主机中没有点)
Notes
- •正式站(
voscms-com)和 salon 已同步完成。API/UI/i18n 全部立即生效。
- •13 种语言 i18n:
community.broadcast.guide_url_、section_message、section_channels*、subject_hint、body_hint、link_hint、link_{invalid,autofixed,valid}、preview_{title,empty}。
v2.6.17
2026-05-30 · 5个月前
在公告发送页面右侧加入预约发送指南框
Added
- •
/theadmin/community/broadcast 布局变更 — 把原来的单张卡片拆分为 lg:grid-cols-3。主发送表单占左侧 2 列(lg:col-span-2),右侧 1 列新增指南框(<aside>、sticky top-4)。
- •6 个部分的指南内容:
1. 📅 什么是预约发送? — 在未来的时间自动发送,可用于夜间/周末/活动
2. 🛠 使用方法 — 4 个步骤(选择对象 → 勾选 LINE → 勾选预约 → 发送),带编号徽章的 UI
3. ⏱ 发送精度 — 5 分钟间隔 cron 的说明 + 示例框(10:00 → 10:00~10:05)
4. 🆚 立即发送与预约发送的比较 — 以卡片形式展示两种模式的行为差异
5. 📋 查看队列等待 — 指向 /history?status=queued 的快捷按钮
6. ⚠ 注意事项 — 必须是 30 秒以上的未来时间、应用内/推送不能预约、没有 cron 的托管环境无法运行、暂不支持在 UI 中取消
- •靛蓝渐变背景(
from-indigo-50 to-blue-50) — 指南框在视觉上与主卡片区分开,同时柔和地融为一体。
- •13 种语言 i18n — 约 20 个
community.broadcast.guide_* 键(ko/en/ja/de/es/fr/id/mn/ru/tr/vi/zh_CN/zh_TW)。
Added
- •在
/mypage/settings 中新增“偏好语言”卡片 — 14 个选项的 select(自动/13 种语言)。保存时 UPDATE rzx_users.locale,并立即应用到 $_SESSION['locale']。
- •Auth::loginUser hook — 登录时如果存在
$user['locale'] 且会话 locale 为空,就自动填入。如果用户在会话期间手动更改过,则优先保留该值。
- •13 种语言 i18n —
auth.settings.language.{title,description,label,auto,hint,save,success,error_invalid,error_save}(ko/en/ja/de/es/fr/id/mn/ru/tr/vi/zh_CN/zh_TW)。
- •更改后,从下一个页面开始 UI 就以会员的语言显示;如果管理员在自动发送规则中设置了
messages_by_locale,就会通过 LINE 向该会员发送匹配的正文。
Added
在 /theadmin/community/broadcast/history 顶部新增 3 张卡片(排在原有的 4 张卡片之后):
1. 整体点击率(CTR) — SUM(rzx_broadcast_clicks.click_count) / SUM(rzx_line_broadcasts.recipient_count WHERE status='sent') × 100。大号字体的 emerald。
2. A/B 测试(最近 30 天) — 对 variant IS NOT NULL 的发送,按 variant 汇总接收、点击和 CTR。CTR 更高的 variant 用 emerald 突出显示。
3. 按 locale 的分布(最近 30 天) — 仅限 source='auto_rule' AND messages_by_locale IS NOT NULL 的发送,通过比较规则的 messages_by_locale JSON 的键与 broadcast 正文的前 30 个字符来匹配 locale → 按 locale 汇总接收/点击/CTR。用 ksort 排序。
- •13 种语言 i18n:
community.broadcast.stat_{ctr_title,ctr_breakdown,variant_title,variant_hint,locale_title,locale_hint,empty}。
Notes
- •
voscms-com 和 salon 的目录树已同步完成。没有新增数据库列(都已包含在 Step 4 的 migration 008/009/010 中)。
- •locale 匹配逻辑比较正文的前 30 个字符 — 变量替换后的正文一致,就计入同一个 locale 分组。如果正文太短,或者完全由变量替换填满,匹配率可能会下降(将来可以直接在 broadcast 行中添加 locale 列)。
Added
- •migration 010 —
rzx_auto_broadcast_rules.messages_by_locale JSON NULL + rzx_users.locale VARCHAR(10) NULL + idx_locale 索引。
- •AutoBroadcaster::lineUserIdsWithLocale — 查询 LINE userId 与会员 locale 的配对。没有
users.locale 列的环境会回退到 lineUserIds。
- •AutoBroadcaster::pickLocaleMessage — 优先级:会员的 user.locale → 网站默认 locale(rzx_settings.locale) → JSON 的第一个键(全部未命中则为 null → 回退到 A 正文)。
- •AutoBroadcaster::fire — 如果有
messages_by_locale,就为每个会员使用与 locale 匹配的正文;没有则使用 A/B variant;再没有则使用单一的 A。当 locale、variant 和 default 得到相同的正文时,会合并为同一组进行 multicast(提高效率)。
- •管理员规则弹窗 — 通过
<details> 展开“启用多语言路由”和直接输入 JSON。以 pretty-print 方式显示。invalid_locale_json 校验。
- •13 种语言 i18n —
community.automation.locale_{toggle,placeholder,hint} + fields.messages_by_locale + error.invalid_locale_json(ko/en/ja/de/es/fr/id/mn/ru/tr/vi/zh_CN/zh_TW)。
Notes
- •Step 1~4 的 LINE 发送基础设施已完成(2.6.9~2.6.15):
1. Step 1 — CTA · utility stack · 手动发送 · 按等级的 audience · 多选(7872c4b, 7c94a55, c4a3325)
2. Step 2 — 会员分组自动分类(b24979c)
3. Step 3 — 事件自动发送规则(60d47cd)+ 预约发送 cron(8cf02ad)
4. Step 4 — 点击追踪(79c99a84)+ A/B 测试(86e19b0b)+ 多语言路由(本次)
- •正式站(
voscms.com)已应用 migration 010。users.locale 是新增的列 — 所有现有会员为 NULL(使用网站默认 locale → 与以前行为相同)。
- •让会员在个人中心直接设置自己偏好 locale 的 UI 是下一个里程碑。
- •建议注册的 cron:
/5 /usr/bin/php8.3 /var/www/voscms-com/scripts/process-scheduled-broadcasts.php、0 3 /usr/bin/php8.3 /var/www/voscms-com/scripts/recalculate-member-grades.php。
v2.6.14
2026-05-30 · 5个月前
A/B 测试(Step 4-B)
Added
- •migration 009 —
rzx_auto_broadcast_rules.message_template_b TEXT NULL、rzx_line_broadcasts.variant CHAR(1) NULL、rzx_broadcast_clicks.variant CHAR(1) NULL + 索引 (source_rule_id, variant)。
- •AutoBroadcaster::fire — 如果
message_template_b 不为空,就用 crc32 mod 2 把 LINE userId 按 50:50 分成 A/B。按 variant 预先 INSERT 发送历史(logQueued) → 令牌 wrap → multicast → finalize。同一用户在重复发送时始终收到同一个 variant(哈希一致性)。
- •管理员规则弹窗 — 通过
<details> 展开“启用 A/B 测试”选项和 variant B 输入。默认是简单的单一发送,A/B 需要明确选择开启。
- •ClickTracker — 传递 variant 元信息。如果存在 broadcast_clicks.variant 列,就在 INSERT 时填入。没有则回退(兼容尚未应用 migration 009 的环境)。
- •logQueued 回退 — 在没有 variant 列的环境(未应用 migration 009 时)也能运行。
- •13 种语言 i18n —
community.automation.ab_{toggle,placeholder,hint}(ko/en/ja/de/es/fr/id/mn/ru/tr/vi/zh_CN/zh_TW)。
Notes
- •在正式站(
voscms.com)上分开执行了 migration 009 的 3 个 ALTER。已有规则的 message_template_b=NULL(保持单一发送的行为)。
- •编辑规则 → 在“启用 A/B 测试”展开区输入 variant B → 只要保存,从下一次触发开始就会自动进行 A/B 分配。
Added
- •migration 008(
rzx_broadcast_clicks) — token(8 位 base62,UNIQUE)、broadcast_id、source_rule_id、original_url(2048)、click_count、last_clicked_at、last_user_agent。相同的(broadcast_id, original_url)组合会复用令牌。
- •
ClickTracker 类 — wrap($pdo, $siteId, $body, $meta) 用正则表达式提取正文中的 http/https URL → INSERT 或复用 → 替换为 /t/{token}。consume($pdo, $token, $ua) 把令牌转换为原始 URL 并增加 click_count。
- •路由
/t/{token}(index.php:330) — 进入正则路由器。ClickTracker::consume → 302 重定向到原始 URL,没有则返回 404。URL 令牌校验([A-Za-z0-9]{4,16})。
- •与自动发送规则整合 —
AutoBroadcaster::fire() 在发送之前按 logQueued → 获取 broadcast_id → ClickTracker::wrap → multicast → finalizeBroadcast 的顺序运行。保证令牌与 broadcast_id 的关联。
- •与手动发送整合 — 在
api/broadcast.php 拼接好立即发送的文本之后立刻 wrap。在 scripts/process-scheduled-broadcasts.php 的队列发送之前也进行 wrap(已知 broadcast_id)。
- •追踪域名设置 — 优先使用
rzx_settings.click_track_domain,没有则使用 APP_URL。也可以使用短域名(例如 s.voscms.com)。
Notes
- •正式站(
voscms.com)已应用迁移 008。
- •wrap/consume 整合测试:正文中的 2 个 URL → INSERT 了 2 个 8 位令牌 → 调用 consume 时返回原始 URL,click_count 正常增加。
Added
- •migration 007(
rzx_line_broadcasts):新增 scheduled_at DATETIME NULL、processed_at DATETIME NULL 两列 + (status, scheduled_at) 索引。scheduled_at NULL = 立即发送(与以前相同),未来的时间 = 进入队列。
- •
scripts/process-scheduled-broadcasts.php — cron 入口。取出 50 条满足 status='queued' AND scheduled_at <= NOW() AND processed_at IS NULL 的项目 → 用 processed_at = NOW() 立即加锁(事务) → 解析 audience(all / grade_N,与 broadcast.php 相同) → LineMessenger 以 500 人为单位 multicast → 按结果更新 status。建议的 cron 周期:/5 *。
- •broadcast.php UI:
[预约发送] 复选框 + datetime-local 输入。勾选后默认值为当前时间 + 1 小时(用户本地时间)。未勾选/留空则与以前一样立即发送。只有 LINE 渠道可以预约(应用内和推送仍保持立即发送)。
- •api/broadcast.php:处理
scheduled_at POST 参数。对于未来的时间(> NOW + 30s)且 send_line 的情况,不调用 LINE API,只 INSERT rzx_line_broadcasts (status='queued', scheduled_at),并在响应中返回 scheduled: true, scheduled_at。
- •13 种语言 i18n:
community.broadcast.schedule_{label,enable,hint,success}(ko/en/ja/de/es/fr/id/mn/ru/tr/vi/zh_CN/zh_TW)。
Fixed
- •按
rzx_line_broadcasts 的实际结构(title、body、audience varchar(20)、recipient_count、status enum(queued|sent|failed))更正了 INSERT 的列。此前使用了并不存在的列名(message_text、recipients_count、sent_count、failed_count、audience_value、partial)来尝试 INSERT,连回退也失败,导致自动发送的历史缺失。
Notes
- •正式站(
voscms.com)已应用迁移 007。通过 dry-run 确认 pickup 为 0 条。
- •正式站(
voscms-com)和 salon 的目录树已同步完成。已排除 .env。
- •cron 的登记由托管运维方决定(如有需要,
/5 * /usr/bin/php8.3 /var/www/voscms-com/scripts/process-scheduled-broadcasts.php)。
Added
- •自动发送规则表(
rzx_auto_broadcast_rules) — migration 005_auto_broadcast_rules.sql。规则按 site_id 隔离,包含 trigger_type / trigger_filter(JSON)/ audience(all|grade_X|custom)/ message_template / is_enabled / fired_count / last_fired_at 各列。
- •AutoBroadcaster 调度器(
rzxlib/Core/Notification/AutoBroadcaster.php) — 静态入口 AutoBroadcaster::fire($triggerType, $ctx)。匹配已启用的规则 → 替换模板变量({{title}}, {{url}}, {{author}}, {{board_name}}, {{site_name}}) → 解析 audience(与 broadcast.php 逻辑相同,is_default 等级会自动包含 NULL 会员) → 通过 rzx_user_social_accounts 查询 LINE userId → 以 500 人为单位 multicast → 在 rzx_line_broadcasts 中记录历史 → 更新规则统计。
- •论坛新帖自动发送 hook(api-posts.php:184) — 帖子 INSERT 之后立即(不含私密帖)调用
AutoBroadcaster::fire('board_post', [post_id, board_id, title, url, author, board_name])。即使发送失败,也不影响帖子的响应。
- •管理员规则管理页面(
/theadmin/community/automation) — 卡片网格 UI。规则的 CRUD + 开/关切换 + 按触发器区分的颜色徽章(board_post=blue, review_created=amber, reservation_created=green)。在弹窗中编辑触发器 / 过滤器(JSON)/ 目标等级 / 消息模板。
- •rzx_line_broadcasts 的来源追踪列 — migration
006_line_broadcasts_add_source.sql。source('manual' | 'auto_rule')+ source_rule_id(INT)+ 索引。自动发送的历史可以与手动发送在同一张表中区分开。
- •plugin.json 路由与迁移登记 —
community/automation 路由,并在 003 之后写明 004/005/006 迁移。
- •13 种语言 i18n — 全部
community.automation.* 键(ko/en/ja/de/es/fr/id/mn/ru/tr/vi/zh_CN/zh_TW)。触发器标签、字段、提示、成功/错误消息、默认模板。
Notes
- •正式站(
voscms.com)已应用 005/006 迁移。规则处于未登记状态。
- •正式站(
voscms-com)和 salon 的目录树已同步完成。已排除 .env。
- •Step 3-B(预约发送
scheduled_at + cron)是下一个里程碑。
Added
- •注册时自动分配 default 等级(
rzxlib/Core/Auth/Auth.php::register()) — 会员注册后立即在 rzx_member_grades 中查询 is_default=1 的等级,并立刻填入新会员的 grade_id。在没有 member_grades 表的网站(旧版或未配置)上,通过 try-catch 静默跳过。已有的 NULL 会员由单独的重新计算脚本或按钮来填充。
- •CLI 等级重新计算脚本(
scripts/recalculate-member-grades.php) — 以 rzx_payments 的支付合计 + rzx_reservations 的预约数(仅当表存在时)为依据,按 sort_order DESC 依次遍历,匹配能够满足的最高等级。未设置规则的等级(min_spent=0 AND min_reservations=0)会自动跳过 — 只有设置了明确规则的等级才是晋级候选。不满足条件的会员回退到 default。
- •选项:
--dry-run(不实际 UPDATE,仅模拟)、--user-id=UUID(仅限特定会员)。
- •cron 示例:
0 3 * /usr/bin/php8.3 /var/www/voscms/scripts/recalculate-member-grades.php
- •管理员“立即重新计算”按钮(
/theadmin/members/groups) — 在操作栏中新增翡翠绿色调的按钮。点击后依次为确认弹窗 → AJAX action=recalculate_grades → 结果(对象/晋级/降级/新增)通知 → 自动刷新。由于内联包含了与脚本相同的逻辑,在没有 PHP CLI 权限的环境中也能运行。
- •13 种语言 i18n — 新增
members.groups.recalculate* 键(ko/en/ja/de/es/fr/id/mn/ru/tr/vi/zh_CN/zh_TW):recalculate、recalculate_hint、confirm_recalculate、recalculate_stat.{total,upgraded,downgraded,fallback}、success.recalculated、error.{no_grades,no_default_grade}。
Notes
- •在正式站(
voscms.com)上验证了 --dry-run → 实际执行 → 补充规则后重新执行。grade_id NULL 的 5 名会员全部被正确分配为 Normal(default)。VIP/Gold/Silver 因未设置规则,在添加规则之前保持 0 人(符合预期)。
- •正式站(
voscms-com)和 salon 的目录树已同步完成。已排除 .env。
Added
- •面向会员的 LINE 添加好友 CTA 组件(
resources/views/components/line-friend-cta.php) — 5 种 variant(card / button / bar / side-tab / bubble)× 6 个 position(bottom-right/bottom-left/bottom-center/top-right/middle-right/middle-left)× 3 种 size,自定义颜色、显示延迟,以及 24 小时“记住已关闭”(localStorage)。
- •可更改的设置 UI — 在
/theadmin/settings/message-api 的 LINE 渠道卡片下方新增“LINE 添加好友 CTA”区块。包括 Basic ID、启用开关、variant 单选、position 下拉、size、颜色选择器和 delay 输入。
- •自动显示在 5 个布局中 — 从
skins/layouts/{default,modern,minimal,modern-copy-260413}/footer.php 自动 include。在支付、服务申请和安装流程页面会自动跳过。
Added
- •新增组件
resources/views/components/utility-floating-stack.php — 采用 thevos.jp 的 cameron_plugin 设计模式(右侧边缘 80×80 方形 stack + 1px 间隔 + 每个图标各自的强调色)。位置、大小和颜色可由运营者调整。
- •两种模式并存 —
utility_stack_mode = separate(默认,各个 CTA 单独显示) / unified(PWA + LINE 合并为一个 stack 显示)。在整合模式下,LINE CTA 5 种 variant 的自动显示被停用,PWA 安装弹窗的自动触发(setTimeout/DOMContentLoaded 横幅)也被停用,只有点击 stack 中的 PWA 图标才会打开弹窗。
- •未来的自然扩展 — 借助项目注册模式,其他内容(Kakao 渠道、WhatsApp、订阅简报、深色模式切换等)只需添加设置键就能加入 stack。
- •保证自动换行 — 内联 CSS
word-break: break-all; overflow-wrap: anywhere; max-width: 72px 绕过 Tailwind flex 子元素的宽度限制。CJK 标签也能在框内自然换行。
- •13 种语言 i18n — 在
resources/lang/{13 locale}/messaging.php 中加入 line_cta. 组(22 个键)和 utility_stack. 组(12 个键)。日语和中文用语义单位的空格(如“アプリとして インストール”)保证自然换行位置。
Added
- •
LineMessenger::broadcast(messages) + broadcastText(text) — 向全部好友批量发送(最多 5 个消息对象,LINE 发送额度按接收人数 × 消息数扣除)。
- •
LineMessenger::multicast(userIds[], messages) — 向指定的最多 500 个 userId 发送(按群组发送的基础设施)。
- •
/theadmin/community/broadcast UI 增强 — 新增“同时发送给 LINE 好友”复选框(绿色横幅)。独立于推送发送,自动对 LINE 好友进行 multicast/broadcast 发送。
- •按会员等级发送 — 动态加载
rzx_member_grades,自动显示每个等级的单选项(颜色圆点 + slug + 实时计数)。audience 的格式为 grade_<id>。
- •
is_default=1 等级自动包含 grade_id IS NULL 的会员 — 即使在注册时不会自动分配等级的网站上,default 等级的计数和发送中也自然包含 NULL 会员。
- •
rzx_line_broadcasts 发送记录表 — site_id 隔离、method(broadcast/multicast)、audience、title/body、recipient_count、line_request_id、api_status/error、status。发送时自动 INSERT。
- •
audience=all 时自动选择 broadcast,其他情况选择 multicast — 收集目标用户中 user_social_accounts.line_friend=1 的 LINE userId,以每次 500 个为一组分批发送。
- •统一宽度 — broadcast.php 的
max-w-3xl → max-w-7xl(与其他管理页面一致)。
- •13 种语言 i18n — 新增
send_line_label/desc、audience_grade_group 键。
Changed
- •
resources/views/admin/dashboard.php — 页眉注释 / pageTitle 回退 / RezlyX v... 更新通知横幅全部更正为“VosCMS”。
- •
resources/views/admin/partials/admin-topbar.php — 更正页眉注释。
Fixed
- •
storage/.update_cache 保留着旧的 current: "2.6.4" 缓存,导致更新到 v2.6.8 之后,仪表盘仍显示“有新更新”的横幅 — 删除缓存后,会在下一次请求时自动重新计算。
- •dev → 正式站累积的变更没有同步 — 除了本次会话之外,install-core.php(#1~#7 缺陷补丁)和 version.json 等大量文件也都没有同步到正式站的遗留问题。通过 rsync 把 dev 一次性同步到正式站(342 个文件变更 + 196 个新增,6.3MB,不含用户数据、
.env、storage/、uploads/、vendor/、.git/)。
Documentation
- •
docs/LINE_FRIEND_CTA_DESIGN_GUIDE.md — 新增 Part 3(整合 Utility Floating Stack 的实际实现)、Part 4(Phase 1 发送运营的实际实现)、Part 5(外部用户场景 — 多选发送的价值分析)、Part 6(Phase 2~4 后续路线图)。从约 631 行增加到 920 行。
Regression Test
- •验证
utility-floating-stack.php 和 5 个 line-friend-cta variant partial 文件是否存在。
- •验证
LineMessenger::broadcast/multicast 方法是否存在。
- •验证
plugins/vos-community/migrations/004_line_broadcasts.sql 迁移文件是否存在。
- •验证 13 种语言的
messaging.utility_stack. + community.broadcast.send_line_ 键是否存在。
- •自动验证 dashboard.php / admin-topbar.php 中没有 RezlyX 残留。
Fixed
- •vos-market 许可证表合并 — 6 个 API 文件查询了错误的
{$pfx}vos_licenses 表,导致每次支付都出现 500 "Server error"。所有许可证验证现在都路由到单一主表 vcs_licenses(由 vos-license-server 管理)。
- •
sync.php 删除未验证主表注册的安全漏洞 — 之前的代码在不验证 vos_key 的情况下 UPSERT 到 vos_licenses,允许任何人通过简单的 POST 自动将任意许可证密钥注册到主表。跟踪现在由现有的 rzx_mkt_sync_reports(按项目)处理。
- •
migrations/007 弃用 — 设计错误的迁移现在是 no-op (SELECT 1),原因和变更历史记录在注释中。
Added
- •4 个统计卡片 — 已追踪站点 / 需要关注的站点 / 多域名许可证 / 未同步 30+ 天。
- •违规选项卡(项目级行显示) — 一目了然地查看哪个付费小部件在哪个域名上未授权安装。显示价格、版本、vos_key 和上次见过的时间。
- •多域名选项卡 — 单个许可证密钥从多个域名报告的情况。
- •未同步选项卡 — 30+ 天没有同步信号的站点。
- •细化的违规定义 — 排除
unknown_product 和免费项目。仅市场注册的付费项目处于未授权状态的才算违规。
- •所有者域名白名单 — 存储在
settings.mkt_owner_domains JSON 数组中的运营商自有域名自动从计数中排除。
- •13 种语言 i18n — 侧边栏、卡片、选项卡和帮助文本均已正式翻译。
Changed
- •
settings/system/updates — 已安装版本和最新版本卡片更正为 "VosCMS vX.Y.Z"。
- •
updates/ajax.php — 数据库名称回退和 User-Agent 已更正。
Regression Test
- •自动验证 vos-market 6 个文件中没有
vos_licenses SQL 残留
- •检测
sync.php 中 INSERT 安全漏洞的回归
- •验证
migrations/007 的 no-op 状态得到维护
- •自动验证更新画面 3 个文件中没有 RezlyX 残留
v2.6.7
2026-05-29 · 5个月前
install 向导安全化与引入自动回归测试
Fixed
- •自动写入
site_url — install 向导只把用户输入的 siteUrl 写入了 .env 的 APP_URL,没有写入数据库的 rzx_settings.site_url,导致新安装网站里所有依赖 site_url 的功能(自动安装、SEO、邮件链接等)失效。现已在 install-core.php 的 $settings 数组中加入 site_url 解决。
- •自动登记
rzx_site_domains — install 向导没有把当前安装的域名自动添加到 site_domains 表,导致 SiteRouter 无法识别该域名。现在会把安装的域名作为 site_id=1 的 primary 自动 INSERT。
- •自动写入
.env 中的 MARKET_API_URL — 全新安装时 .env 中没有应用市场 API 地址,InstallerService 找不到调用目标。现在会自动写入默认值 https://market.voscms.com/api/market(许可证单一主库运营)。
- •应用市场 install API 的表名拼写错误 —
vos-market/views/api/item/install.php 在验证许可证时查询了不存在的 rzx_vos_licenses 表,导致所有自动安装都返回“Server error”的 500 响应。已改为真实的表 vcs_licenses(许可证主库,固定不带前缀)。
- •自动设置 widgets/plugins/themes 目录权限 — install 之后 PHP-FPM 用户无法写入这些目录,自动安装悄无声息地失败。现在 install 向导会自动授予 setgid 和组写入权限(自动检测 PHP 运行组,以适应各种外部环境)。
- •
install-handler.php 的多重回退 — 在多站点环境中,site_url 的查询没有 site_id 过滤、只用 LIMIT 1,结果不稳定。现在通过 SiteRouter → site_id=1 回退 → $_SERVER['HTTP_HOST'] 这三级回退,保证在任何环境下都能识别域名。
Added
- •
InstallerService::installTheme() — 读取 type=theme 商品的 theme.json,递归安装 requires 中的 plugin/widget/skin。保证 13 种语言校验和幂等性(已安装的项目会跳过)。
- •
runPostInstall — 主题安装完成后立即自动执行 post_install/settings.json / boards.json / pages.json 的种子数据,页面 + 组件布置 + 默认设置一次性全部自动配置完成。
- •强制 13 种语言(
REQUIRED_LOCALES) — 多语言对象(name、description、页面 title、组件 config.title 等)必须包含全部 13 个键才能正式通过。缺少的语言会给出警告。
- •统一
vcs_licenses 主库 — 所有许可证的签发和验证都通过正式的应用市场(market.voscms.com)管理。dev/test 环境也使用同一个主库。
Added
- •自动验证这 6 个缺陷 — 共 13 项,包括 install 向导的种子逻辑 + 目录权限 + 应用市场 API + 许可证服务器可达性 + InstallerService 的 theme 分支 + install-handler 的多重回退等。
- •build-voscms.sh 自动执行钩子 — 构建结束时自动调用。只要出现 1 个 FAIL,退出码就不为 0,阻止发布。即使同样的缺陷在之后的构建中再次出现,也会被立即发现。
Documentation
- •
docs/theme-package/THEME_PACKAGE_SPEC.md — 定义了 VosCMS 主题包标准(theme.json)。写明了沙龙整合主题示例 + post_install 详细结构 + 13 种语言规则。
v2.6.6
2026-05-27 · 5个月前
防止更新备份重复
Fixed
- •更新备份每个版本只保留一份 —
Backup::createFull() 现在会在创建备份之前先删除同一版本的已有备份。解决了在同一版本上反复更新或回滚时,备份列表中堆积同一版本重复项的问题(只保留更新前的最新状态)。
v2.6.5
2026-05-27 · 5个月前
更新系统整顿(单一入口、会话/权限、发行版修复)
Fixed
- •恢复发行版中缺失的
update-api.php — 构建脚本把更新后端 update-api.php 误判为“dev 文件”,从发行版中删除了它。结果所有已安装发行版的更新标签页都无法使用,显示“File not found”。现已从构建排除项中移除,发行版正常包含它。
- •修复登录会话无法识别(Unauthorized) —
update-api.php 原来查看默认的会话保存路径(/var/lib/php/sessions),现已改为与 index.php 相同的 storage/sessions。解决了以管理员身份登录后仍出现 Unauthorized 的问题。
Changed
- •Core 更新只使用自有发行 manifest 这一个入口 — 移除了
update-api.php 中 GitHub 标签/令牌/诊断的残留代码(阻断了 check 用 GitHub 标签覆盖 manifest 结果的路径)。应用市场中没有 Core(仅限插件)。
- •安全加固 — 为
update-api.php 增加了 CSRF 验证和主账号(所有者)权限检查。
- •整理更新保留列表 — 把
skins 和 config 从保留列表中移除。由于 applyUpdate 只做复制,发行 zip 中的核心皮肤和 config 会被更新,而 zip 中没有的客户自定义文件会被保留。
Changed
- •移除了重复的“检查更新”按钮 — 进入页面时自动检查最新版本。
- •修复了临时出错时备份列表消失的问题 → 保留该区块并显示为空状态。
- •出错时不再显示
Unauthorized 之类的原始消息,而是显示“当前使用的已是最新版本”的提示。
Added
- •新增 13 种语言的
um 区块 — vos-community/lang/{locale}.php 全部语言 (ko·en·ja·de·es·fr·id·mn·ru·tr·vi·zh_CN·zh_TW):follow·following·message·block·unblock·report·report_about·report_reason/detail/placeholder·reason_spam/harassment/inappropriate/other·report_submit/sent/failed·msg_title/placeholder/send/sent/failed·block/unblock_confirm·block/unblock_done·cancel·failed·network_error
- •
user-mention-menu.php 全面 i18n — PHP HTML 中硬编码的韩文全部替换为 __('community.um.*');JS 运行时字符串通过 UM_LANG = <?= json_encode(...) ?> 以 PHP 对象形式输出,并由 umT(key, name) 辅助函数替换 :name 占位符
- •允许未登录用户使用提及菜单 — 重构
community-overlays.php 的守卫结构:管理员/API 路径全面拦截,而 user-mention-menu 即使未登录也包含(关注·举报引导登录);页面操作与 username 守卫仍仅限登录用户
Changed
- •新增
boardPreloadUsers(array $rows) 函数 (board/_init.php) — 用单次 IN 查询批量加载 user_id 列表,通过 $GLOBALS['_boardUserCache'] 共享缓存
- •扩展
boardAuthorMention() — 新增 data-user-username·data-user-avatar 属性(精确关联故事 URL /story/{username},显示头像图片)。优先命中预加载缓存,未命中时进行 lazy 单条查询
- •
board/list.php·board/read.php·skins/board/qna/_list-full.php — 渲染前调用 boardPreloadUsers() 以防止 N+1 查询
Fixed
- •扩展显示解析器 (
resources/views/system/changelog/index.php) — 新增对代码栅栏 (``)、表格 (|...|)、markdown 链接 (text)、#### 小标题和水平线 (---`) 的渲染。解决了使用此语法的早期版本 (2.4.1·2.3.8·2.3.7 等) 以原始 markdown 显示的问题
- •按版本的 locale 回退 — 由按单一语言一次性取整个列表改为按版本 (
当前 locale → en → ko)。现在任何语言都能完整显示所有版本,尚未翻译的版本会显示回退语言徽章
- •块边界对齐 (
rzxlib/Core/Changelog/ChangelogParser.php) — 通过在每个 ## [ 处分割块,防止无日期的 ## [Unreleased] 标题被并入前一版本(如 1.5.0)
v2.6.3
2026-05-25 · 5个月前
发行版下载统计·英雄组件拆分·拖放构建器
Added
- •迁移 056
dist_downloads 表 (site_id·version·ip·user_agent·referrer·utm_*·is_bot·created_at)
- •下载端点
api/dist-download.php — 不再使用静态 /download/*.zip 直链,而是经由该端点统计按版本/按日/来源(referrer·UTM)后再 302 重定向。机器人 UA 单独统计;版本白名单(防路径穿越)
- •管理员统计页
resources/views/admin/dist-downloads.php (仅限主管理员,13 种语言) — 摘要卡片(总计/今日/7天/30天)·按版本柱状图·每日趋势(30天)·来源 Top10·UTM。自带 SVG/CSS 图表(无外部库)
- •将
download-hero 组件的下载链接改为计数端点
- •新增「下载统计」管理菜单 (config/admin-menu.php,仅限主管理员)
Added
- •
hero-cta-text — 顶部文本(打字)区域。默认值与线上 hero-cta2 内容一致(13 种语言),用户设置优先
- •
hero-cta-button — 下载按钮(自动检测最新版本+统计下载次数,无需配置) + 可选的市场按钮(留空则只有一个按钮)
- •设置表单的标签与默认值支持13 种语言(构建器
getLabel 对象支持)
- •下载按钮的颜色/背景与 hero-cta2 统一(#2563eb)
Added
- •将面板卡片拖到画布即可添加组件(SortableJS
pull:'clone' 组 + 画布 onAdd 中替换为真实区块)。与原有的点击添加、↑↓/手柄排序并存
- •拖动时浮层保持打开 + 画布投放区高亮(
wb-drop-active)
Changed
- •移除组件之间的页面包装间距(
type-widget.php py-2 → 0)
- •稳定评论 AI 翻译的同步处理 — nginx
fastcgi_read_timeout 150s(论坛 vhost)·PHP-FPM request_terminate_timeout 150·set_time_limit 150,OllamaProvider keep_alive 30 分钟(模型常驻,消除冷加载)
- •在消息 API 与社交登录选项卡新增 Webhook URL、Redirect URI 的复制按钮(13 种语言,含非安全上下文回退)
v2.6.2
2026-05-14 · 5个月前
结算税务自动化、注册表单分支与系统页面 SSOT
Added
- •迁移 036 — 在
partner_earnings / payouts 中新增 withholding_tax · consumption_tax · tax_basis 列
- •迁移 037 — 在
payouts 中新增 fx_rate · fx_amount · fx_currency 列(记录换算为 USD 的汇款信息)
- •迁移 038 — 新增
vcs_developers.paypal_email 列
- •Helper
rzxlib/Core/Helpers/MarketTax::calculate() — 日本标准扣税模型
· 销售价格含税(税込);平台直接向 NTA 缴纳消费税
· freelance → 扣除 10.21% 预扣税 / invoice_eligible → 进项税抵扣 / no_invoice → 不缴纳消费税
· 未分类或未填写 → 强制设为 freelance(保守策略:少付可退,多付难追)
- •补填脚本
scripts/market-tax-backfill.php — 重新计算现有 earnings/payouts(保护 status='paid',支持 --dry-run)
- •五部分结算展示:收入 → 手续费 → 消费税扣除 → 预扣税(freelance)→ 实付金额
- •
rzx_mkt_settings 新增键值:min_payout_amount · consumption_tax_rate · default_commission_rate(全局优先使用 settings,移除硬编码 fallback)
Added
- •
/theadmin/market/partners/payouts 结算弹窗 — prompt() × 2 + alert() → 统一弹窗
· JOIN vcs_developers 自动预填银行/支行/户主/账号/企业类型/T号(prefill;PII enc:自动解密)
· 自动计算五部分 + 日本法律依据标签(freelance_withholding 等)+ 条文引用(§204,发票制度)
· 页内 toast 通知;关闭弹窗后自动刷新
· Frankfurter API 自动汇率(storage 缓存 TTL 24 小时)+ 管理员手动覆盖(银行 TTS)
· 自动选择 method=paypal
· 境外开发者:隐藏银行账户卡片,显示 PayPal 邮箱卡片(bank_country == site_country)
- •开发者自行指定结算金额(
/mypage/developer/earnings)
· 全额余额 → 金额输入框 + 全额按钮 + 最低金额校验
· 销售记录五列展示,结算说明框(按企业类型显示适用税法)
- •付款记录中展示 USD 换算与汇率辅助信息(管理员及开发者两端均显示)
- •销售趋势图改为 SVG 条形图(解决 div 条形在部分环境中近乎不可见的问题)
Added
- •基于
tax_review_status 的锁定策略(开发者资料)
· not_submitted / rejected → 可编辑
· pending / approved → 编辑锁定(挂锁 + 说明)
· rejected → 可编辑 + 提示"保存后将进入重新审核队列"
· 服务端防御:HTTP 423 Locked(阻止绕过界面操作)
- •
update.php 部分更新安全化 — 仅对已提交字段执行动态 UPDATE(旧逻辑:全量覆盖,未提交字段有被置 NULL 的风险)
- •官方验证网站链接(管理员验证页面 + 开发者资料)
· 🇯🇵 NTA 法人番号公示サイト(https://www.houjin-bangou.nta.go.jp/)
· 🇯🇵 NTA 适格发票发行人公示网站(https://www.invoice-kohyo.nta.go.jp/regno-search/)
· 🇰🇷 韩国 Hometax 企业注册状态查询
· 企业编号/T号旁添加一键复制按钮
Added
- •新注册(
/mypage/developer)— 国籍选择移至表单最顶部,提供与运营国的对比说明
· country == site_country → 🏠 本国表单(企业类型 / 银行账户)
· country != site_country → 🌐 境外表单(自动 freelance + PayPal 邮箱必填)
· Alpine.js isDomestic getter,全局常量 OPERATING_COUNTRY
- •资料编辑(
/mypage/developer/profile)— 相同结构([feedback_admin_user_parity] 规则)
· 境外开发者:隐藏企业信息区块;结算信息仅保留 PayPal 邮箱
· 国籍字段锁定(如需变更请联系管理员),顶部显示模式标签
- •注册 API 服务端强制校验 — 境外开发者必须填写 PayPal 邮箱,强制设为 freelance,企业/账户输入值一律忽略
Added
- •
page.php Token 自动替换 — 统一应用于所有系统页面
· {{COMPANY_NAME}} {{COMPANY_ADDRESS}} {{COMPANY_PHONE}} {{COMPANY_EMAIL}} {{COMPANY_REG_NUMBER}} {{COMPANY_REPRESENTATIVE}}
· {{SITE_NAME}} {{SITE_URL}} {{DOMAIN}}
· 自动映射管理后台 business_ 或 site_ settings 值
· 自定义 page_title / page_subtitle 同样经过 Token 替换
- •
{{DOMAIN}} 优先级 — official_domain(条款/政策专用官方域名)→ site_url 的 host
· 即便在开发服务器 vos.21ces.com 上,条款正文中依然显示 voscms.com
Added
- •
rzx_page_contents 中 terms / privacy(各 13 行)全面替换 — RezlyX 预约平台条款 → VosCMS 免费软件条款
- •服务条款 18 条:目的 · 定义 · 公告与修订 · 补充规则 · 合同成立 · 隐私 · 通知 · 公司义务 · 用户义务 · 服务提供 · 变更 · 使用限制 · 许可(免费使用授权)· 数据所有权与保留 · 帖子版权 · 免责声明(AS-IS)· 损害赔偿 · 争议解决
- •隐私政策 10 条:处理目的 · 类别 · 保留期限 · 向第三方提供与委托 · 数据主体权利 · 安全措施 · Cookie · 保护负责人 · 侵权救济(PPC)· 变更
- •适用日本法律 + 福冈地方裁判所专属管辖,引用 APPI §33·§34·§35
- •公司信息使用 Token → 在管理后台修改一次,条款与政策自动同步
- •以日文版为正本,13 种语言均使用各自母语进行正式翻译
- •公司信息卡片 — 仅含 3 项:法定名称、地址及电话(删除代表人/姓名,避免因注册变更引发条款修订)
- •保存脚本:
scripts/voscms-terms-update.php · scripts/voscms-privacy-update.php
Fixed
- •
/theadmin/site/menus 中的 menus-api.php 落后 vos 99 行,导致保存/编辑菜单时遗漏验证与翻译
- •将 menus-api.php 从 vos 同步至 market:
· mn_link_target_exists() — 快捷方式(链接)菜单只有在目标页面(系统页面 · rzx_page_contents)存在后才允许保存
· 防止菜单 ID 复用 — 新 ID 的陈旧 rzx_translations.menu_item.{id}.* 自动清理
· 翻译 INSERT 方式:INSERT IGNORE → INSERT … ON DUPLICATE KEY UPDATE(允许覆盖)
· 修改 title·url 时:清除旧翻译 + 与系统页面匹配(config/system-pages.php)时自动重新注册翻译
- •在
sync-to-market.sh 的 INCLUDES 中新增 4 个 admin/site/menus*.php 文件
Fixed
- •
rzx_contact_messages 表缺失 → 新增迁移 041_create_contact_messages.sql(IF NOT EXISTS,对已有的 vos 无影响)
- •
contact-messages.php 双重布局问题 — _head.php 已输出 sidebar+topbar,但 view 再次直接 include,导致 <body> 重复和 main 嵌套。按 vos 模式整理(头部 = _head 1 次,尾部 = _foot 1 次)
Added
- •迁移 040
040_create_developer_platform.sql — 批量创建 7 张表:vcs_developers + vcs_developer_earnings/payouts/activity/notes + vcs_review_queue + rzx_mp_items(IF NOT EXISTS,应用 ALTER 030~038 后的最终表结构)
· vos.21ces.com 的 vcs_developers 仅存在于 dump 中,无 CREATE TABLE 迁移 — 修复后续站点 ALTER 030 失败的问题
- •同步
mypage/profile-sidebar.php — 旧 rzx_mkt_partners 查询 → 新 vcs_developers 查询(在个人中心中整合开发者活动)
- •market
index.php 路由补丁(手动,避免全量同步):
· /developer/ → /mypage/developer/ 301 重定向(login/dashboard/my-items/submit/earnings/profile/logout 映射)
· mypage/developer/{register|items|items/new|earnings|profile} + mypage/developer/items/{N} + mypage/developer/items/{N}/edit 路由
- •在
sync-to-market.sh 的 INCLUDES 中新增迁移 040 + profile-sidebar.php
- •应用迁移 040 前自动备份 market DB(
storage/backups/market-YYYYMMDD-HHMMSS/market_vos.sql)
Added
- •market.21ces.com 条款采用第三方运营市场模式,与 VosCMS 免费软件条款分别制定
- •18 条条款(反映市场运营规则):
· 第 8 条:买卖合同在买家与开发者之间成立;公司作为支付与交付中介
· 第 9 条:数字商品退款的 4 种例外(下载前 · 说明不符 7 日 · 恶意软件确认 · 系统错误)— 符合日本《特定商取引法》§15-2 的披露要求
· 第 10 条:不明示佣金比例(引用"另行公告的费率",可在无需修订条款的情况下调整比率)
· 第 10 条:依《所得税法》§204 预扣税 10.21%;持有 T 号者的消费税由平台直接缴纳给 NTA;运营国以外账户 → 以 USD 通过 PayPal 汇款
· 第 14 条:开发者个人条款优先适用 — 平台运营事项(支付、结算、退款流程)除外
· 第 17 条:损害赔偿上限:前 6 个月手续费/结算款总额
· 第 18 条:适用日本法律 + 福冈地方裁判所专属管辖
· 数据类别 — 通用 / 买家 / 开发者(通用)/ 日本居民 / 海外居民 / 配送:共 6 类
· 保留期限 — 会员 1 年 · 交易 7 年 · 结算/预扣税 7 年 · 身份核验 5 年 · 日志 6 个月 · 咨询 3 年
· 数据处理受托方 — 明确列出 Stripe · KOMOJU · PayPal · Frankfurter · SendGrid · NTA
· 境外传输 — 明确列出美国(PayPal/Stripe/SendGrid)· 欧盟(汇率)· 其他国家(当地支付网关/银行)
- •脚本:
scripts/market-terms-update.php · scripts/market-privacy-update.php(UPSERT — 先 UPDATE;无记录则 INSERT)
- •market DB 已更新(terms/privacy,rzx_page_contents 各 13 行),page-i18n 多语言标题与副标题同步应用
Added
- •修复 skin 设置值(
page_title · page_subtitle)映射缺失 — 设置页面输入的值未在页面中显示
- •新建缺失的
_page-title-bg.php partial(解决 nginx error log 中的 include 警告)
- •在
title_bg_type 中新增 color 选项 + title_bg_color 字段 — 图片/视频为空时自动 fallback 为纯色
- •移除
content_bg=transparent 时的白色卡片 fallback(修复 max-w-5xl 内容在卡片内显得过窄的问题)
- •自动输出
--page-content-width CSS 变量 — "关于本页面"操作栏(vos-community)等外部自动 include 的组件将与页面 content_width 保持同等宽度
Fixed
- •结算页面 PDOException — 移除对
rzx_mkt_partners 中不存在的 p.currency 列的引用
- •销售趋势图不显示 — div 条形的百分比高度在部分环境中几乎为 0px → 替换为基于 SVG viewBox 的图表(保证最低 4px 可见高度)
Added
- •开发者我的页面条目详情界面(
/mypage/developer/items/{id})— 统计数据、发布历史、下载趋势
- •开发者条目编辑界面(
/mypage/developer/items/{id}/edit)— 与 items-new 相同的3标签页 UI,自动填充现有值,新 ZIP 上传采用独立流程
- •新 API:
/api/developer/item-update — 更新 name(JSON)、short/desc(JSON)、tags(JSON)、price、license、repo/demo URL、依赖项、最低版本、icon、screenshots
- •新 API:
/api/developer/request-payout — 申请结算
- •新 API:
/api/developer/update-bank — 更新本人结算账户
- •新 API:
/api/developer/issue-reply — 发布 Q&A 回复(开发者自己的回复渠道)
- •管理员开发者详情界面(
/theadmin/developers/show)— 企业/账户/文件卡片 + 文件审核(批准/拒绝)模式
- •注册与登录的邮件验证(
/verify-email)增强 + Auth::register 中保存 company 字段
- •新增13种语言正式翻译键(
show_edit_btn、items_edit_*、items_back_detail、api_updated 等)
Added
- •在小组件中直接展示评论、问题和 Q&A 提交表单(无需跳转独立页面)
- •仅购买者可提交 — 未购买者可看到表单,但提交时会收到提示信息
- •Q&A 回复支持嵌套(对回复的回复)— DB 迁移 035(
parent_reply_id)
- •新 API:
/plugins/vos-market/views/api/item/post-issue.php、post-reply.php、post-review.php
- •核心
rzxlib/Core/Helpers/Notifications.php — 通知辅助函数(与 DB 迁移 034 配套)
Added
- •对所有界面全面应用13种语言支持:
/theadmin/market/licenses、sync、orders、settings、submissions、partners/payouts、items
- •市场设置界面 — "合作伙伴"标签统一改为"开发者"(仅显示文本;变量名为兼容性保留不变)
- •市场条目名称输入使用公用多语言输入弹窗 —
name_json 可同时以13种语言编辑
- •
plugins/vos-market/lang/* — 插件级新语言资源池
- •
resources/lang/*/marketplace.php — 13种语言全部以本国语言翻译(符合多语言完整翻译规则)
Added
- •
033_developer_notes_activity.sql — 按开发者记录的备注和活动日志
- •
034_notifications.sql — rzx_notifications 表(用户通知)
- •
035_issue_reply_thread.sql — 新增 rzx_mkt_issue_replies.parent_reply_id 字段(嵌套回复)
Fixed
- •
/Market?item={slug} 缺少 slug — 在 items-show 中通过专用单列查询进行修正
- •条目更新 API 中的
icon_url 字段名修正为实际字段名 icon
- •市场设置页面空白 — 应用
rzx_mkt_settings 缺失的迁移 005
Added
- •VARCHAR(12)
users.username + UsernameValidator(至少 6 个字符,特殊字符限制)
- •登录后首次进入时显示门控弹窗(AJAX
/api/username-set)
- •13 种语言的正式翻译(移除英语 fallback)
Added
- •
/profile/{uuid} → /story/{username} 301 跳转
- •右键菜单标签从"查看个人主页"改为"查看动态"
Added
- •从核心分离的 vos-story 插件 — 专属
/story/{username}
- •Facebook 风格页头 + 5 个固定标签页(全部 / 简介 / 照片 / 粉丝 / 关注)
- •帖子 CRUD + SNS 动态(
vos_story_posts,body_format = text/html)
- •TEXT/EDIT 切换 + Summernote 集成
- •图片附件(多张)+ 照片标签页网格
- •点赞 + 评论系统
- •Story 皮肤系统(
skins/story/default)+ 用户独立令牌(/mypage/story)
- •管理员运营政策页面(
/admin/vos-story/policy)
- •页面操作栏:i18n + 位置(主内容末尾)+ 内容宽度令牌
- •2:1 网格(仅内容区域)— 右侧:广告 + 好友(粉丝/关注标签页)
- •页头操作按钮 — 纯图标([我的 Story 设置] / [编辑个人资料] / [关注])
Added
- •D-1:4 菜单侧边栏(仪表板 / 动态 / 账户信息 / 消息)
- •D-2-A:新仪表板 — 8 个状态卡片 + 8 标签页导航 + 账户信息标签页
- •D-2-B:收藏夹 / 收件箱 / 好友标签页(各含"查看全部"链接)
- •D-2-C:已保存 / 我的帖子 / 我的评论标签页(板块 + Story + 页面统一)
- •D-2-D:自动登录(remember tokens)管理
Added
- •公共辅助函数
rzx_mirror_external_images() — cURL + SSRF 防护 + GD 图片缩放
- •E-1:收藏快照截取 + 外部图片吸收
- •E-2:发布 Story 时吸收(story_attachments source 列)
- •E-3:发布板块帖子时吸收
- •E-4:创建页面内容时吸收
- •图片标记:
data-source-original、data-source-mirrored
Added
- •托管管理侧边栏末尾的 [设置] — 进入服务申请页面的 4 个标签页(general/domain/hosting/addons)
- •退款政策 → 系统设置 → 通用 → 独立卡片 分离(与税务设置隔离)
- •
rzx_settings.refund_policy 单键存储
- •13 种语言的
settings.refund.* 键
Added
- •迁移 009:
page_contents.created_by / updated_by 列
- •在所有页面编辑界面(admin/customer/system)自动记录
Added
- •帖子计数 — 识别板块帖子的独立
rzx_translations 结构(board_post.{id}.title)
Added
- •管理员设置中支持按托管配置存储配额 / 警告阈值 / 策略(block/notify/none)
- •我的页面使用量甜甜圈图表
- •
scripts/db-quota-monitor.php 后台监控程序
Added
- •VosCMS 重新安装按钮 — 管理员托管标签页
- •托管 [状态] 变更操作 + 日志
- •删除"服务器连接信息设置"编辑表单(防止不必要的信息暴露)
Fixed
- •收藏
add_scrap 网络错误 — vos-story API 文件 require 冲突
- •收藏卡片 — 轮廓 + 删除/编辑图标(垃圾桶)
- •帖子计数与列表不一致(缺少状态筛选条件)
- •移除 nick_name 匹配(防止将 user_id 为 NULL 的种子数据误识别)
- •我的页面 Story 菜单位置 — top → main(插件自动识别)
- •Story 菜单图标使用核心格式(完整
<path> 标签)
- •附加服务标签页 settings SELECT 缺少 key 列(导致两个区块隐藏)
- •hosting_status 操作 500 — 辅助函数定义位置
- •页面操作栏 — 内容宽度令牌已应用
- •发布新帖子时现有帖子消失的 bug(动态即时刷新)
Added
- •托管详情 → 域名选项卡 →
+ 添加域名 按钮 → 弹窗
- •选项:免费子域名 / 新注册 / 连接现有域名
- •WHOIS查询(
/api/domain-check.php 复用)+ 按TLD显示价格
- •付款:已保存的卡(复用托管PAY.JP客户)或新卡(PAY.JP Elements)
- •自动分离10%消费税(小计 / 税额 / 合计)
- •付款完成时追加到托管sub的
metadata.added_domains[](不另创建sub)
- •自动退款安全网 — DB处理失败时PAY.JP扣款自动退还
Added
- •开始日期~到期日期 + 检查按钮(DNS A/CNAME → 匹配我们的区域或Cloudflare IP段)
- •自动续期开关 + 续期申请按钮(按域名)
- •registrar_pending / manual_attach_pending时检查按钮 → "处理中"徽章
- •"附加域名"紫色徽章
Added
- •托管管理侧边栏:新增第2项
- •统一列表:type='domain' sub + 托管sub.added_domains[] 全部按时间顺序显示
- •统计卡片(全部/处理中/已完成)+ 筛选(状态/选项/搜索)
- •操作:[标记为已注册] / [处理取消](取消时:PAY.JP退款 + INSERT退款行)
- •用户名自动解密
Added
- •托管管理侧边栏:新增第3项
- •基于
rzx_payments 的交易账本 — 收入/退款/净收入/税额统计卡片
- •日本消费税申报用金额自动计算(含税价格 → 本体 = total × 100/110,税额 = total × 10/110)
- •近12个月走势表 + 交易账本表格 + 筛选/分页
Added
- •我的页面附加服务选项卡:"可申请"区域(商务邮件自动排除)
- •按价格的操作:
- •免费(安装支持):管理员通知 + order_logs
- •报价(定制开发):"申请报价"
- •固定定期价格(1年技术支持):卡片支付弹窗(
_addon-pay-modal.php)
- •付款完成时自动创建addon sub + payments凭证
- •已激活sub标签匹配时申请按钮自动禁用
- •install_info行右侧:[前往管理后台 / 前往首页] 按钮
Added
- •DB架构:
uk_payment_order UNIQUE移除 → uk_payment_key(charge_id)UNIQUE替代
- •允许一个订单有多行支付记录(托管+域名+附加服务累积)
- •退款时:paid行不变,单独INSERT退款行(status='refund',会计完整性)
- •满足日本7年保存义务 + PAY.JP商户纠纷处理标准
Added
- •composer require minishlink/web-push
- •基于VAPID的admin/supervisor推送发送助手
- •已过期endpoint自动清理 + rzx_push_messages自动记录
- •调用点:pay_domain(域名付款完成)、service-order(域名注册申请)、request_addon
Added
- •我们区域的子域名自动匹配(识别wildcard CNAME)
- •Cloudflare IPv4 15个CIDR段匹配(代理响应时)
- •"already_refunded"响应视为成功处理(PAY.JP已退款时)
Added
- •子查询汇总
rzx_payments 合计(paid − refunded)
- •托管基础付款 + 域名添加 + 附加服务付款累积显示
Added
- •
admin_cancel_addon — sub status='cancelled' + PG退款 + INSERT退款行
- •PG路由:基于支付行的
gateway 列(PG变更后也安全)
Removed
- •根据日本7年保存义务 + PAY.JP纠纷处理政策,管理员UI中的所有"删除"按钮已全部移除
- •垃圾桶图标 + adminDeleteAddon JS + admin_delete_addon API + 13种语言4个标签全部移除
- •仅使用"取消" — 数据行绝不执行DELETE
Fixed
- •Translator占位符冒号前缀冲突 —
[':count' => N] → ['count' => N] 批量修正
- •PayjpGateway::refund()的
metadata[refund_reason] 被PAY.JP拒绝 → 更改为 refund_reason
- •service-manage.php管理员权限检查 —
role === 'admin' → role IN ('admin','supervisor') 5个操作统一修正
- •服务订单域名选项卡:退款后会计卡片显示负数 → SQL逻辑修正(status='paid' / 'refund'分离汇总)
Added
- •ssh.21ces.com Cloudflare Tunnel注册(Public Hostname: SSH → localhost:22)
- •外部电脑:
cloudflared access ssh --hostname ssh.21ces.com 或~/.ssh/config中的ProxyCommand
- •服务器端:PermitRootLogin no,thevos密钥已注册
Added
HostingProvisioner.php installVoscms() 在 zip 部署后按顺序调用 install-core.php step 3 → step 4(此前仅 step 2):
- •新增
runInstallCoreSteps() — 利用 _db POST 回退绕过 Session + 验证 .installed 标记
- •新增
callInstallCore() — HTTP loopback(端口 80,借助 Cloudflare edge SSL;限速时处理 origin 证书缺失)
- •新增
appendHostingEnv() — install-core.php 覆写 .env 后重新注入 HOSTING_* 变量
- •安装完成后自动删除 welcome.html(使 VosCMS index.php 优先加载)
- •支付流程 service-order.php:567-576 — 安装成功时自动将
install_completed_at、install_admin_url 写入 addon 元数据(触发我的页面选项卡显示)
Added
admin/service-orders/detail.php:175-260 + partials/addon.php:
- •附加服务选项卡的"安装支持"addon 中新增两个按钮:
- •安装 VosCMS(紫色)— 存在
install_info 且尚无 install_completed_at 时显示
- •管理员页面(绿色)— 安装完成后在新窗口打开 admin URL
- •API 操作
admin_run_voscms_install — 直接调用 HostingProvisioner.installVoscms(),DB 凭据从 metadata.server.db 或客户 .env 回退
- •成功时:写入 addon 元数据 +
voscms_installed order_log 记录
Added
customer/mypage/service-partials/hosting.php:
- •🟢 站点备份按钮 —
service-manage.php?action=request_backup(新增)
- •mysqldump → DB 导出 + zip 打包(public_html、.env、sql)
- •签名下载 URL(HMAC,10 分钟有效)— api/backup-download.php 新增
- •自动清理 7 天前的旧备份
- •🟣 打开 phpMyAdmin —
https://pma.voscms.com/?lang=<user_locale> 新窗口
- •nginx vhost:pma.voscms.com.conf 新增(通过 Cloudflare Tunnel
*.voscms.com 通配符自动路由)
- •使用用户自己的 DB 凭据登录
- •显示 DB 连接信息(主机 / 数据库名 / 用户 / 密码切换)
- •13 种语言 i18n:
btn_site_backup、btn_open_phpmyadmin、confirm_site_backup、backup_in_progress、backup_ready、f_password、password_notice、f_protocol
Added
customer/mypage/service-partials/_setup-monitor.php:
- •分离步骤:托管配置 → VosCMS 自动安装
- •
system_imported 订单(管理员自行注册的系统托管,如 vos.21ces.com)立即激活 — 不显示监控框
- •新增 13 种语言 i18n:
setup_step_voscms_install
Changed
rsync 排除项新增:
- •5 个内部插件(不应部署到托管客户站点):
- •
vos-developer、vos-hosting、vos-license-server、vos-market、vos-salon
- •7 个 reservation 迁移 SQL(托管客户不安装预约系统):
- •
001_create_reservation_tables.sql、011_seed_service_translations.sql、012_seed_service_translations_p2.sql、013_add_source_to_reservations.sql、014_add_payment_status_to_reservations.sql、015_create_reservation_core.sql(新增)、016_alter_reservation_services.sql、024_reservations_bundle_columns.sql
dev 文件删除新增:
- •
admin/ 目录(offline.html 残留)— 空目录导致 nginx 目录索引 403,仅 root /offline.html 被 sw.js 引用
- •基础编码 →
obfuscate.php(旧版 ionCube EVAL 运行时挂起;仅在 USE_IONCUBE=1 时使用 ionCube)
Changed
将 001_create_base_tables.sql 原本在单文件中同时创建 base 和 reservation 表的结构拆分:
- •已修改:
001_create_base_tables.sql — 仅包含 5 个核心表(rzx_admins、rzx_users、rzx_member_grades、rzx_settings、rzx_migrations)+ 核心种子(member_grades 默认值、settings 默认值)
- •新增:
015_create_reservation_core.sql — 9 个预约表(rzx_categories、rzx_services、rzx_service_options、rzx_reservations、rzx_payments、rzx_point_transactions、rzx_business_hours、rzx_holidays、rzx_staff_positions、rzx_staff)+ 预约种子(business_hours、point_*)
托管分发版构建时排除 015 → 不创建 rzx_reservations → admin/dashboard.php:25-27 中 $hasReservations = false → 日历不自动显示。
使用预约系统的站点(voscms.com、RezlyX 等)同时应用两个 SQL 文件 → 无变化。
Changed
config/templates/nginx-vhost.conf.tpl + HostingProvisioner addHttpsToVhost():
- •原来:80 端口(HTTPS 重定向)+ 443 端口(实际内容)→ Cloudflare Tunnel + 80→443 重定向形成无限循环
- •现在:80/443 统一单个 server 块,提供相同内容,无重定向
- •
fastcgi_read_timeout 60s → 300s(防止大批量 INSERT 时 nginx 超时)
Changed
- •
provision-hosting.php(CLI 回填工具):自动更新托管订阅元数据(hosting_provisioned、server.{ftp,db,env})— 以前仅执行 service-order.php 的 _autoProvisionHosting
- •自动删除 5 个内部插件 + admin/ 目录
Added
新增 scripts/install-cli.php:
- •托管配置后自动调用 install-core.php 的回填
- •DB 凭据:优先使用 subscription 元数据,若无则回退到客户 docroot 的
.env
- •用法:
sudo -u www-data php scripts/install-cli.php --order=<ORDER>
- •成功时:自动将
install_completed_at 写入 addon 元数据 + 在 order_logs 中记录 voscms_installed 操作
Fixed
- •信用卡支付分支缺少
_autoProvisionHosting() 调用 — 已补充
- •支付元数据中
install_info.admin_pw 明文暴露 → 统一我的页面和管理员两侧的切换(👁)展示模式
Migration Notes
- •外部托管客户:无需额外操作。
voscms-2.4.3.zip 构建使用干净的 zip。
- •本站(voscms.com):无变化(两个 reservation SQL 文件均已应用)。
- •现有托管客户(dwhahn 等):建议 deprovision + reprovision 进行干净重装(拆分后应用新 zip)。
- •手动清理:
/etc/nginx/sites-available/pma.voscms.com.conf 已新增 — 直接部署到本站系统(rsync 之外)。
v2.4.2
2026-04-29 · 6个月前
托管自动化支付 Hook + 活动日志 i18n
Added
在 service-order.php 中支付完成后立即调用:
- •新函数
_autoProvisionHosting($pdo, $prefix, $orderId, $orderNumber) — 在支付事务外部执行(DB 完整性隔离;即使失败也不影响订单本身)
- •仅
domain_option = 'free' 立即完成设置(Cloudflare 子域名 — DNS 自动注册已完成,可立即使用)
- •
new(购买域名后等待 NS 更改)/ existing(已有域名等待 NS 更改)处于 deferred 状态 — 管理员在域名激活时单独触发
- •如果 'install' 插件有
install_info,则部署 voscms 文件并自动生成 .env(install-core.php 的分步会话流程(步骤 2–5)自动化需要重新设计整个 voscms 安装流水线,是项大工程,推迟至第 5 阶段;用户支付完成后访问 https://<域名>/install.php → 按向导操作,DB 信息已预注入 .env)
- •ftp/db/env 信息自动保存到托管订阅的
metadata.server → 在我的页面托管标签页中自动显示(无需 UI 修改)
- •order_logs 操作:
hosting_provisioned / hosting_provision_skipped / hosting_provision_deferred / hosting_provision_failed
调用顺序:支付提交 → _autoProvisionHosting() → _autoProvisionMailDomain()
Added
管理员服务订单详情页面(detail.php:498-528)的 $actionLabels 从 8 个扩展至 31 个。修复了活动日志中直接显示原始代码(如 mail_account_added)的问题。
新增的操作映射:
- •邮件:
mail_account_added/deleted、mail_address_changed、mail_provisioned/_skipped/_failed、mail_domain_migrated/activated、bizmail_upgrade_request
- •托管:
hosting_provisioned、hosting_provision_skipped/deferred/failed、hosting_deprovisioned
- •附加服务:
admin_add_storage_addon、admin_delete_addon、storage_addon_paid/requested
- •系统:
customer_notified、setup_email_sent、server_info_updated、bulk_extended、manual_capacity_period_fix
各操作颜色含义:green(完成/正向)、amber(待处理/警告)、red(失败/删除)、blue(信息/通知)、violet(管理员/特殊)、zinc(中性)。
23 个 i18n 键 — services.admin_orders.act_* — 已为 ko/ja/en 三种语言添加(运营页面)。其余 10 种语言回退至英文。
Changed
托管自动 Provisioning 时,VosCMS 自动安装仅执行文件部署 + .env 自动生成。install-core.php 的分步会话流程(步骤 2–5)自动化需要重新设计整个 voscms 安装流水线,工程量较大,推迟至第 5 阶段。用户支付完成后访问 https://<域名>/install.php → 按向导操作(DB 信息已预注入 .env)。
installVoscms() 返回值已变更 — 现在返回 install_url + note 提示信息。
v2.4.1
2026-04-29 · 6个月前
托管虚拟化自动配置(阶段1–3)
Added
HostingProvisioner.php — 托管订购时自动配置的主类。9步事务(失败时按逆序回滚):
- •Linux用户创建(
vos_<order_number>,在32字符限制内,保留大小写)
- •目录结构:
/var/www/customers/<order>/{public_html,logs,tmp}(chmod 750/2775/750/1770)
- •磁盘配额(
setquota -u <user> <soft> <hard>,hard = soft × 1.1)
- •目录冲突检测:与现有nginx vhost /
reserved_subdomains 冲突时拒绝
- •1.9TB SSD
/var/www 挂载(ext4 + noatime + usrquota,grpquota)
- •集中sudoers(
/etc/sudoers.d/voscms-hosting-provisioner)— www-data以NOPASSWD运行root命令(useradd/setquota/nginx等)
- •按命令限制参数模式(
vos_、/var/www/customers/、*.conf)— 通过visudo验证
CLI工具 scripts/provision-hosting.php:
php provision-hosting.php SVC260428AE7476 hotel.com 1GB
php provision-hosting.php --order SVC260428AE7476 # 自动DB查询
php provision-hosting.php --deprovision SVC260428AE7476 hotel.com
php provision-hosting.php --install-voscms <order> <domain> <capacity>
模板 config/templates/:
- •
nginx-vhost.conf.tpl — HTTP + ACME挑战位置 + 每用户FPM socket
- •
welcome.html.tpl — 激活欢迎页面
Added
每个托管在自己用户权限下运行PHP(防止跨站攻击)+ 即使在Cloudflare代理后面也能自动颁发SSL。
config/templates/php-fpm-pool.conf.tpl:
- •
user = vos_<order> / group = www-data — UID隔离
- •
listen = /var/run/php/<order>.sock — 每用户socket
- •
pm = ondemand — 低流量托管的内存效率
- •
php_admin_value[open_basedir] — 访问限制为站点目录 + /tmp + /usr/share/php
- •
disable_functions — exec, passthru, shell_exec, system, proc_open, popen, pcntl_exec
- •
session.save_path / upload_tmp_dir — 隔离到用户目录
- •env: HOSTING_ORDER / HOSTING_USER / HOSTING_DOMAIN
Let's Encrypt SSL — Cloudflare DNS-01挑战:
- •
python3-certbot-dns-cloudflare 插件
- •
/etc/letsencrypt/cloudflare/credentials.ini(root 0600,.env中的CLOUDFLARE_API_TOKEN)
- •无论Cloudflare代理 / 外部可达性均可颁发
- •HTTPS服务器块自动添加(TLS 1.2/1.3,强密码,HSTS,X-Frame-Options,X-Content-Type-Options)
- •HTTP → HTTPS 301自动重定向
- •
certbot.timer 每天自动续期两次(已激活)
Added
每个托管订单的DB + 用户隔离。
- •
hosting_admin MySQL账户(创建一次,ALL PRIVILEGES + GRANT OPTION)— 仅用于DB管理
- •DB名/用户 =
vos_<order>(与Linux用户名相同)
- •密码:32位hex随机(
bin2hex(random_bytes(16)))
- •
GRANT ALL PRIVILEGES ON vos_<order>.* TO vos_<order>@localhost — 仅访问自己的DB
- •隔离验证:访问其他托管DB / voscms_prod返回Access denied 1044
VosCMS自动安装(installVoscms() — 由--install-voscms或addon有install_info时触发):
- •解压最新
voscms-dist/voscms-X.Y.Z.zip → public_html
- •自动生成
.env:APP_KEY=base64:<32字节> / DB信息 / HOSTING_ORDER注入
- •权限:vos_:www-data,.env chmod 640
- •无界面调用
install-core.php(当前存在301重定向问题,将在阶段4解决)
Verified
provision DEMO260429FULL demo07.21ces.com 1GB --install-voscms:
- •✅ 用户
vos_DEMO260429FULL(UID隔离,www-data组)
- •✅ 磁盘配额1GB soft / 1.05GB hard
- •✅ PHP-FPM pool 独立socket
- •✅ nginx vhost(HTTP + HTTPS,HSTS)
- •✅ Let's Encrypt SSL(
/etc/letsencrypt/live/demo07.21ces.com/)
- •✅ MySQL DB
vos_DEMO260429FULL + 用户(隔离已验证)
- •✅ VosCMS 2.3.9文件 + .env已部署
deprovision:所有资源已清理(用户/home/DB/FPM pool/nginx/SSL)。
Added
不再使用行业标准的周年纪念计费方式(从注册日起至一年后的同一天),改为按日历月末截止(从次月1日到到期月最后一天)。同月注册的用户到期日相同,简化了 cron 批处理和会计结账。遵循日本主机标准(月末締め翌月1日請求)模式。
- •数据库:新增
rzx_subscriptions.billing_start DATETIME NULL 列(正常计费开始日)
- •Helper 函数:
_proratedFirstAmount(月单价 ÷ 30 × 剩余天数)、_calendarBillingStart(次月1日)、_calendarExpires(最后一天 23:59:59)
- •订单表单:自动在主机付款项目中添加
hosting_prorated(例如:4/2 注册 12 个月 ¥1,000/月 → 首月 ¥967 + 正常 12 个月 ¥12,000 = ¥12,967)
- •域名保持周年纪念计费(1 年注册周期);主机、邮件、维护和附加服务使用日历计费
- •service-order.php 中的
-1 second → -1 day 处理也统一
- •附加服务(额外 web 存储)同样使用相同的按天计费 + 正常 N 个月合计,自动与主机到期日同步
Added
在 ConoHa VPS (133.117.72.149) 上部署 Postfix + Dovecot + Rspamd + Roundcube + OpenDKIM + Let's Encrypt。mail-tester 10/10,FCRDNS 已验证。下单时自动配置域名。
- •自动 DNS 注册(
CloudflareDns.php)— A / MX / SPF / DKIM / DMARC 5 种记录一次性添加
- •DKIM 密钥生成 — mx1 SSH
rspamadm dkim_keygen(专用 ed25519 密钥 storage/keys/mailsync_ed25519,www-data 所有,0700)
- •3 模式配置(
MailDomainProvisioner.php):free(子域名即时)/ new(购买域名,管理员激活)/ existing(NS 变更指南)。状态机:existing_pending / new_pending / active
- •密码:SHA512-CRYPT(
{SHA512-CRYPT}$6$...)— Dovecot 兼容的单向哈希。旧 enc:(encrypt 函数)密码迁移脚本:scripts/migrate-mail-passwords.php
- •mx1 同步 cron(
scripts/mail-sync-to-mx1.php)— voscms_prod → mx1 mail_lookup virtual_users 每 5 分钟同步一次。邮件操作后即时触发后台同步的即时触发器(triggerMailSyncToMx1())也已添加
- •cron 自动注册:
/etc/cron.d/voscms-mail-sync
- •通知:管理员(需要配置)/ 客户(邮件可用)HTML 邮件模板(
MailNotifier.php)
Added
基础邮件 / 商务邮件与主机捆绑管理。修复了同一地址同时保存在邮件订阅和主机元数据中导致界面重复显示的问题(单一数据来源:邮件订阅)。
- •网页邮件按钮 — Roundcube
?_user=地址 GET 参数自动填充用户名,target="_blank"。URL 优先级:metadata.mail_server.webmail_url → WEBMAIL_URL env → 默认 https://mail.voscms.com/
- •邮箱更改按钮 — 用于更正拼写错误。域名固定,仅更改本地部分。同一订单的所有邮件 + 主机元数据均同步
- •去重逻辑(
mail.php)— _seenAddresses 每个地址只显示一次,邮件订阅优先
- •service-detail.php 中的虚拟 hosting → mail 转换仅在没有真实邮件订阅时生效(旧数据兼容)
- •service-order.php 新注册时不再保存 hosting metadata.mail_accounts(邮件订阅为唯一来源)
Added
在个人中心附加服务标签页购买额外主机存储。PAY.JP 客户注册 + chargeCustomer。
- •弹窗:选择容量(1 GB / 3 GB / 5 GB)+ 输入卡片信息(payjp.js v2 Elements)
- •注册卡片 / 用其他卡片支付 / 返回已注册卡片 — 切换
- •自动检测过期/被拒绝的卡片(
expired_card、card_declined、invalid_* 等 PAY.JP 错误代码)→ 卡片表单自动展开 + 提示横幅
- •新增持卡人姓名输入字段(
addon-card-holder)— 存为客户元数据,不传入 token(PAY.JP v2 Elements 不支持 name 选项)
- •Portal 模式:
document.body.appendChild() 脱离带 transform 的容器,覆盖整个 viewport(z-[9999])
- •创建新客户后扣费失败时:自动退款 + 删除客户(防止孤儿记录)
- •hosting metadata.extra_storage[] 累积,主机标签页存储指示器显示合计值
Added
参考 StarServer 等日本主机服务商的标准条款,构建 14 个条款(定义、申请、费用、自动续费、取消、服务、备份、禁止行为、暂停、维护、隐私、免责、变更、管辖)。明确注明按日历计费方式 + 首月按日计算 + 取消时退还未使用月份费用的政策。
- •系统页面注册:
config/system-pages.php hosting-terms slug,🖥️ 靛蓝
- •页面编辑器映射:
pages-document.php — pageMetaMap['hosting-terms']
- •数据库填充:ja(主)/ ko / en — 3 种语言(rzx_page_contents)
- •i18n:
site.pages.hosting_terms + hosting_terms_edit(editor_title/desc)
Added
- •4 个标签页始终可见(detail.php)— hosting/domain/mail/addon。无数据时显示空状态消息(empty_*)
- •附加服务标签页 —
+ 添加存储 按钮(管理员免费授予弹窗,选择容量后立即创建 active addon subscription,billing_amount=0,expires=主机到期日)+ 各项的垃圾桶/删除按钮(软删除 status=cancelled,从 hosting metadata.extra_storage[] 中移除)
- •列表 — 申请人显示改善(index.php)—
supervisor/admin 角色的系统管理员订单显示为 user.name + 紫色副标题 超级管理员: [email protected] 格式(绕过旧加密 applicant_name 如 FKzGx9SE7xG/2 的解密失败)
- •创建订单按钮(
+ New Order)— 仅 UI,功能待实现
- •i18n 13 种语言:
role_supervisor、role_admin、btn_create_order、empty_、btn_add_storage_addon、btn_delete_addon、modal_add_storage_、confirm_、alert_ 等 20 余个键
Added
- •
subdomain-check.php — DB(reserved_subdomains)优先 + Cloudflare API 降级。JS checkSubdomain() 调用服务器并反映结果
- •service-order.php 在付款前进行服务端再验证 — 防止客户端绕过
- •
reserved_subdomains 自动导入 — Cloudflare 区域中的 11 条现有记录(vos/bestatech/bt/dev/ec430/ec431/salon/ssh/test/thevos/ai.21ces.com)
- •菜单 INSERT IGNORE 错误修复(menus-api.php):
- •
add_menu_item:INSERT 后立即清理过时翻译 + 用 INSERT ... ON DUPLICATE KEY UPDATE 覆写
- •
update_menu_item:检测到 title/url 变化时删除全部 13 条旧翻译 + 若为系统页面则重新注册
- •
rename_menu_item:标题变更时清理旧翻译
- •修复旧菜单(id=38,"VosCMS 介绍")的多语言翻译指向新主机服务条款菜单的回归问题
Added
完整流程构建:服务申请 → 付款完成 → 自动邮件域名配置 → 客户通知。
- •在 service-order.php 中添加
_autoProvisionMailDomain() 调用 — 在付款事务之外执行(隔离数据库完整性)
- •数据库:
rzx_reserved_subdomains(zone、subdomain、record_type、reserved_by、reason)— 可用性缓存
- •DKIM 密钥自动生成,以 mode/origin/domain/zone/subdomain/provisioned_at 格式保存至 metadata.mail_provision
- •按配置模式分支 UI(service-detail.php):
pending / new_pending / existing_pending — 隐藏标签页,仅显示监控(_setup-monitor.php);仅在 active 状态时显示标签页
Fixed
PHP 的 $arr['key'] ?? [] 返回临时值,因此 &$ref 不影响原始数组。change_mail_password / change_mail_address 返回了成功响应,但 metadata UPDATE 无效 — 密码和地址更改均静默失败。
- •改为基于索引的直接更新模式:
foreach ($arr as $i => $item) { $arr[$i]['k'] = ... }
- •service-order.php 中新邮件密码存储也从
encrypt()(双向)改为 mail_password_hash()(SHA512-CRYPT)
Fixed
- •付款摘要荧光亮绿色 → 更清晰的颜色:
text-green-400 → text-green-600 dark:text-green-400(7 处)
- •子域名可用性响应消息缺少 i18n 键(
order.php 中 PHP→JS i18n 映射 + :fqdn 占位符统一)
- •到期日计算精确化:
+N months -1 second(同一天)→ +N months -1 day(恰好提前 1 天)→ 最终统一为日历方式
Database
- •新增
rzx_subscriptions.billing_start DATETIME NULL(dev + prod)
- •
rzx_reserved_subdomains 表(Cloudflare 区域冲突缓存)
- •
rzx_page_contents 填充 hosting-terms(ja/ko/en)
v2.3.9
2026-04-27 · 6个月前
服务订单多语言化 + 三区域菜单系统
Added
域名、主机、附加项、申请人、支付、摘要共6个区域及支付完成页面的所有文本已翻译成13种语言。客户端的 alert/modal 文本通过 PHP 以 var I18N = {...} + t(key, replace) 模式注入。
- •位置:plugins/vos-hosting/lang/{13 locales}/services.php —
services.order.* 200+个键
- •我的页面服务详情:
services.detail.* 70+个键,service-detail.php
- •管理员订单管理:
services.admin_orders.* 115+个键,admin/service-orders/
- •存储在 DB 中的韩语标签(主机套餐、维护、附加项)通过
_localizeLabel($sub) 闭包按设置 ID 映射后应用 db_trans() → 我的页面和管理端处理一致
Added
点击支付按钮时,验证订单详情(域名/套餐/附加项/申请人/条款)后显示摘要弹窗 → 用户确认 → 进行支付。防止注册空子域名等误操作。
- •order.js —
showOrderConfirmModal(), closeOrderConfirmModal(), confirmAndPay()
- •加强支付完成后残留弹窗层的移除(DOM 删除 + body/documentElement overflow 重置)
Added
在附加项中勾选"安装支持"(_id='install')时,显示管理员 ID/邮箱/密码/站点名称输入表单。密码带遮罩 + 眼睛图标切换 + "安装后请更改"提示。输入值以 install_info 存储在订阅元数据中,在我的页面和管理端均可查看。
- •输入:_addons.php
- •显示:我的页面/管理端 partials/addon.php(蓝色背景框 + 密码切换)
Added
将附加项标签页中的备注改为订单(rzx_orders.admin_notes)级别。无论附加项是否存在,始终在右侧活动日志上方以7行文本框形式显示。新增 AJAX update_order_memo 操作。
Added
引入 section 字段(top/main/bottom,默认 main),用于在视觉上区分核心菜单和插件菜单。区域之间自动插入分隔线;若某区域无可显示菜单,则包括分隔线在内整体跳过。
管理员侧边栏:
- •top:控制台 / 会员管理 / 站点管理 / 自动安装(
vos-autoinstall)
- •main:VosCMS 授权(
vos-license-manager)/ 主机管理(vos-hosting)
- •bottom:插件 / 设置
- •变更:config/admin-menu.php, admin-sidebar.php
我的页面侧边栏:
- •top:控制台 / 个人资料 / 消息
- •main:服务(
vos-hosting 自动添加)— 其他插件添加条目时自动累积
- •bottom:设置 / 密码 / 注销账户 / 退出登录
- •变更:config/mypage-menu.php, mypage-sidebar.php
插件菜单注册:plugin.json 的 menus.admin / menus.mypage 条目中的 section + position 字段指定区域。services 菜单已从核心 mypage-menu.php → vos-hosting/plugin.json 迁移(自动注册)。
Added
许可证验证 API 和开发者门户 API 位于核心中,部署到所有 voscms 站点时将对外暴露。两个 API 已分离为新的仅限总部使用的插件。
- •
vos-license-server(scope: hq_only):迁移7个许可证端点(check, register, verify, stats, updates, register-plugin, _init)
- •
vos-developer(scope: hq_only):迁移7个开发者门户端点(register, login, submit, my-items, earnings, update-version, _init)
- •
api/_plugin_dispatch.php — 核心封装器在 dispatch 前检查 rzx_plugins.is_active,未激活时返回 404
- •核心
/api/license/.php、/api/developer/.php 仅保留封装器(维持外部兼容性)
- •
/api/notices.php 新增 HQ_HOSTS env 白名单(仅从总部 voscms.com 域名响应)
- •构建脚本(
build-voscms.sh)已排除 api/license、api/developer、api/notices.php、vos-license-manager
Fixed
- •主机合同到期日 +1 天 bug(
+12 months → +12 months -1 second)— 应用于4处:subscription/free/paid/bank
- •企业邮箱无法添加2个及以上(选择器误捕获了 X 按钮)
- •订单摘要中附加存储未汇总(storage select 缺少
name 属性)
- •主机套餐标签未多语言化 — 通过
service_hosting_plans._id 与 db_trans() 匹配解决
v2.3.8
2026-04-25 · 6个月前
版块多语言完善 + FAQ/Q&A 皮肤
Added
_init.php 现在直接从 rzx_translations 查询 board.{id}.{title|description|header_content|footer_content|seo_keywords|seo_description}(当前语言 → en → 源语言)。在 list/read/write/settings 任意页面,$board[$field] 均自动填入翻译值。版块设置页面的"← 返回"按钮也通过相同机制自动翻译。
为问题反馈版块(id=6)的 title + header_content 提供 13 语言种子数据——保留 HTML 结构,仅翻译文本,处理阶段徽章也各语言显示。种子脚本:scripts/seed_issue_i18n.php + scripts/seed_issue_i18n_data.php。
Added
将 rzx_board_extra_vars 的定义(标签/描述/选项/默认值)翻译为 13 种语言。4 个字段 × 13 = 52 行。
- •
ExtraVarRenderer::renderAll($vars, $values, $mode, $boardId) — 新增 boardId 参数,applyDefTranslations() 单次查询批量加载所有变量翻译。
- •
ExtraVarRenderer::getOptionLabel($boardId, $varName, $value) — 列表视图用单个选项翻译标签查询(静态缓存)。
- •
renderStatusBadge($value, $size, $displayLabel = null) — 颜色保留源(ko)映射,仅翻译文本 → 各语言颜色一致(已接收=玫瑰色,已解决=翠绿色)。
- •select/radio/checkbox:
value=源值 / label=翻译 模式。保存文章时始终存储源值,确保数据兼容性。
- •调用方更新:
read.php、write.php、_list-row.php、默认皮肤的 _list-card/_list-webzine/_list-gallery。
问题版块 status 扩展变量 13 语言种子:scripts/seed_ev_status_i18n.php。
Added
extra_var_get API 通过 db_trans() 以 localized 对象形式返回当前语言的翻译值。JS 弹窗优先显示 localized.title || ev.title → 日语模式下打开弹窗时自动显示"処理ステージ"。
extra_var_update 按语言分支:
- •源语言(ko)→ 更新整个源行(现有行为)
- •非源语言(ja/en/…)→ 仅将元数据(
var_type/权限/3 个复选框)保存至源行;4 个翻译字段(title/description/options/default_value)以当前语言保存至 rzx_translations → 源数据完整性保证
扩展变量列表的显示名称也应用 db_trans('board_ev.{boardId}.{varName}.title')。
Added
扩展变量编辑弹窗中的"编辑权限"区域(标签/下拉选项/帮助文本)拆分为 13 语言 lang 文件。新键:site.boards.ev_permission、ev_perm_all、ev_perm_member、ev_perm_admin、ev_permission_help。
Added
扩展变量编辑弹窗中"选项"字段的双向规范化:
- •弹窗加载:将 DB JSON 数组(
["a","b","c"])转换为换行格式显示在 textarea 中(与说明一致)
- •保存 API:
ev_normalize_options() 助手同时接受换行或 JSON 输入,并统一以 JSON 数组保存。修复了换行输入此前被存为 NULL 的问题。
Added
两款针对问题/公告以外新内容模式的皮肤。
FAQ (skins/board/faq/) — 文章=问题,正文=答案。包含搜索栏、分类筛选和分页。标题区显示开关、标题/副标题多语言、背景(图片/视频/无)支持、遮罩透明度调节。v1.0.1。
Q&A (skins/board/qna/) — 文章=问题(标题+正文),评论=回答。未回复徽章,首个条目自动展开,树形排序(parent_id/depth)评论显示。回复的回复缩进 + "↳ 回复"标签(顶层为"A.")。内联编辑/回复表单(仅作者/管理员可编辑,perm_comment 权限者可回复)。v1.0.0。
两款皮肤共同特性:管理员设置齿轮图标置于搜索栏右下方(与标题区分离)。boardSkinFile() 以 _list-full.php 优先运行。
Added
api-comments.php 新增 update 操作。仅 comment.user_id == 当前用户 或管理员可编辑。字符数验证后更新 content + updated_at。
Added
版面设置 copyright 字段中的 {year} 标记在渲染时自动替换为当前年份。DB 保留原始内容(含 {year}),无需每年手动更新。适用于:default/minimal/modern/base-footer.php。4 个 layout.json 的版权说明扩展至 13 种语言,并以各自母语显示 {year} 使用说明。
同时修复了 default/minimal 页脚忽略 $_lc['copyright'] 的问题——版面设置值现在真正被渲染。
Added
menu_item.38.title 13 语言种子(VosCMS 介绍 / About VosCMS / VosCMSについて / Über VosCMS / Acerca de VosCMS / À propos de VosCMS / Tentang VosCMS / VosCMS-ийн тухай / О VosCMS / VosCMS Hakkında / Giới thiệu VosCMS / 关于 VosCMS / 關於 VosCMS)。
Added
每个处理阶段各一个样本 + 1 个已解决的现有样本 = 共 4 个。每篇文章的标题/内容翻译为 13 种语言(104 行)。
| 阶段 | 标题(ko) | 状态 |
|---|
| 已接收 | [Bug] 移动端汉堡菜单 X 按钮无法点击 | 新增 |
| 确认中 | [功能请求] 评论时向文章作者发送邮件通知 | 新增 |
| 进行中 | [性能] 改善市场详情页首次加载速度 | 新增 |
| 已解决 | 版块中附加的图片插入到正文… | 现有 |
删除现有 post 34(积累 Tailwind 内联样式的测试文章)。
Fixed
customer/board/list.php 在第 167 行 require 了 rzx_admin_icons 助手,但第 161 行的皮肤文件 include 通过 return 提前退出——导致 FAQ/Q&A 皮肤中调用 rzx_admin_icons() 时出现 500 错误。已将 require_once 移至皮肤 include 之前。
Changed
删除残留的旧名称 /marketplace 引用。修复搜索表单通过GET提交到 /marketplace 导致跳转至仪表板的问题(搜索/排序/筛选变更时页面离开)。将 browse.php、item-detail.php、item-submit.php、purchases.php、assets/js/marketplace.js 全部统一到 /autoinstall。
Added
在 install.php 第4步管理员路径输入框下方添加黄色提示 + URL实时预览 + 可展开的"为什么需要更改?"说明。以普通人能理解的语言提供3个理由:自动化入侵尝试(暴力破解)、漏洞扫描、强密码的局限性。已应用至全部13种语言。
Added
在 install.php 安装完成步骤中,自动注册并激活 vos-autoinstall 插件(直接调用 PluginManager::install())。用户进入管理员界面后无需单独安装即可立即使用市场。
Added
为 market.21ces.com/api/market/catalog 和 /item 添加 ?locale=xx 参数支持。name、description、short_description、cat_name 的多语言JSON由服务器端以单一字符串返回(回退:请求的locale → en → 第一个值)。删除VosCMS端所有重复的 json_decode + locale回退 逻辑(browse.php、item-detail.php、_components/item-card.php)。
Added
将文件缓存市场API响应的TTL统一整合到PluginManager设置中管理。硬编码30分钟 → 默认5分钟,提供1/5/10/30/60分钟选项。https://vos.21ces.com/theadmin/settings/general 市场缓存区域与 /theadmin/autoinstall/settings 读写同一设置,自动同步。在自动安装页面右上角和通用设置页面均添加立即刷新缓存按钮。更改TTL时自动使现有缓存失效。
Added
在页头之后立即显示与市场管理员相同的资料类型 / 简介 / Slug / Product Key / 最低VosCMS和PHP版本 / 合作伙伴 / 价格 / 许可证表格。将内容区域左:右比例从2:1调整为3:1以扩大内容区域。
Added
在详情页面评论选项卡右上角添加"写评论"按钮。星级/昵称/正文输入弹窗 → VosCMS API → 转发至市场 POST /api/market/item/review。自动附上VosCMS许可证密钥 + 域名,同一域名仅限提交一次,购买者自动设置 is_verified=1。评论以 status='pending' 状态存储到市场数据库(rzx_mkt_reviews),运营者审批后公开。新建 GET /api/market/item/reviews?slug=... 端点仅返回已审批的评论。域名进行部分遮蔽显示(mys***.com)。
Added
将原来的 仅免费 复选框 → 扩展为 全部 / 免费 / 付费 三向切换。向市场目录API添加 paid=1 参数(i.price>0)。从搜索栏分离并移至视图切换区域前方,与排序下拉框一起整合为标题工具栏。
Changed
搜索输入框边框 border-2 border-emerald-300,左侧搜索图标添加绿色背景框,搜索按钮 bg-emerald-500。仅保留关键词输入,将排序和筛选功能移至内容标题区,简化搜索栏。
Changed
| 状态 | 显示 |
|---|
| 免费 | 安装 + 下载 |
| 付费(未购买) | 购买(市场PAY.JP付款弹窗) |
| 付费(已购买) | 安装 + 下载 |
| 已安装 | "已安装" |
相同分支应用于列表页面的4种视图(列表/杂志/卡片/网格)。进入页面时一次性查询已购买的slug集合并重复使用。付款由市场 POST /api/market/item/purchase 处理,执行PAY.JP扣款 + 许可证签发。
Changed
- •视图样式切换:移除文字标签 → 仅图标 +
title / aria-label(保持可访问性)
- •类型徽章:
bg-<color>-100 浅色背景 → bg-zinc-900/85 backdrop-blur-sm 深色半透明 + 彩色文字(提升图片上的可读性)
- •截图区域:从标题后立即显示 → 移至标签页内容下方,像市场一样显示
(数量) 计数
- •详情页
dark:prose-invert 不生效 → 在CDN Tailwind中添加typography插件
- •详情页描述区域:采用与市场管理员相同的方式,仅移除
<script>/<iframe>/<style>/onXX 等危险元素,HTML标记原样渲染
Fixed
- •PAY.JP卡片表单无法输入:在隐藏状态下提前挂载导致iframe以0px渲染。通过懒加载初始化 +
requestAnimationFrame 挂载解决
- •小部件缩略图缺失:市场数据库已注册28个小部件,但
/var/www/market/widgets/ 中仅复制了12个免费小部件。同步了14个缺失的小部件。在catalog/item API中为 screenshots 添加绝对URL转换 + 不存在文件的自动过滤
- •Bundle插件未授权警告:
vos-autoinstall 被识别为 unauthorizedPlugins。向 LicenseStatus.php 添加 BUNDLE_PLUGINS = ['vos-autoinstall', 'vos-marketplace'] 常量,在 active()/fromCache()/canUsePlugin() 全部应用过滤。许可证服务器 verify.php 也进行了相同处理
- •小部件可能重复添加:
install.php 的seeding只使用了 INSERT IGNORE,但 rzx_page_widgets 没有UNIQUE约束,因此可能出现重复。改为在INSERT前执行 DELETE FROM page_widgets WHERE page_slug='home'(由于存在版块小部件等需要故意重复的情况,不添加DB UNIQUE约束)
Migration Notes
- •
vos-autoinstall 插件的菜单/路由/迁移在全新安装时自动激活(现有安装需在管理员面板手动激活一次)
- •市场API缓存默认TTL:30分钟 → 5分钟(使价格/内容变更更快生效)
- •
vos-autoinstall.cache_ttl 插件设置为新增
v2.3.6
2026-04-21 · 6个月前
市场 API 实时对接
Changed
- •
browse.php:从本地 DB 查询切换为调用 market.21ces.com/api/market/catalog 实时 API
- •
item-detail.php:从本地 DB 切换为调用 /api/market/item 和 /api/market/item/versions API
- •
CatalogClient.php:API 基础 URL 从 /api/v1 → /api/market,响应字段 items[] → data[] 对齐
Fixed
问题: market.21ces.com/index.php 中布局应用块未处理 $__noLayout = true 情况,导致所有插件 API 路由(api/market/*)返回 HTTP 200 + 空响应。
修复: 在 index.php 末尾添加 elseif ($__pageFile && $__noLayout) { include $__pageFile; }。api/market/catalog、api/market/item、api/market/updates/check 等已恢复正常。
Added
为 plugins/vos-market/views/api/catalog.php 添加 sort、free、featured 参数,并扩展响应字段(sale_price、rating_avg、is_featured 等)。
Added
mpApiFetch() 辅助函数:通过 30 分钟 TTL 文件缓存将对市场服务器的请求降至最低。API 响应失败时显示错误提示横幅。
v2.3.5
2026-04-21 · 6个月前
自动许可证注册逻辑完成
Fixed
问题: 在 AdminRouter 中,创建 $licenseClient = new LicenseClient() 实例并尝试自动注册后,$_ENV['LICENSE_KEY'] 的更新未反映到实例内部的 $this->licenseKey 中——导致同一请求中调用 check() 时仍返回 unregistered。
Changed
- •进入
check() 时,若 $this->licenseKey 为空,立即调用 /api/license/register
- •成功时:更新
$this->licenseKey + 更新 $_ENV['LICENSE_KEY'] + 保存 .env 文件,然后继续 verify 步骤
- •仅在失败时(服务器无响应)返回
unregistered
- •新增
saveKeyToEnv() 方法:将空的 LICENSE_KEY= 行(install.php 失败情形)替换为实际密钥;若已存在有效密钥则跳过
效果
- •未经 install.php 手动安装的用户 → 首次进入管理后台时自动注册许可证
- •从旧版本升级的用户(无 LICENSE_KEY)→ 升级后首次进入管理后台时自动注册
- •仪表板的"许可证未注册"提示现在仅在许可证服务器本身无法访问时才显示
v2.3.4
2026-04-20 · 6个月前
内容污染清理 + 卡片式 CSS 移除
Fixed
database/seeds/legal_pages.php 种子文件中,Tailwind CSS 变量(--tw-scale-x、--tw-pan-x 等,400 余个)被内联嵌入每个 <h1>/<h2>/<p> 标签的 style="" 属性中。每次安装都将这些污染传播到数据库,导致 terms 和 privacy 页面急剧膨胀(尤其是 privacy/ko 达到 128KB,正常应为 2KB)。
- •
database/seeds/legal_pages.php:442KB → 131KB(减少 70%,语法有效)
- •清理开发数据库中已污染的 26 行:1.04MB → 56KB(移除 988KB,−95%)
- •新增
scripts/clean-inline-styles.php — style="... --tw-* ..." 批量清理工具(如问题复发可重复使用)
Changed
.board-content CSS 包含将每个文档页面强制转换的规则,将"h2 视为卡片标题,h2+p 视为卡片内容"。这破坏了直接用 Tailwind 设计的页面(如 Brand)的 hero 结构。
- •删除 103 行卡片式块规则(149 → 45 行)
- •保留的规则:基础排版(p/h·/blockquote/code/ul/ol/table)、OG 链接卡片、深色模式文本覆盖
- •结果:
Brand 页面原始设计恢复(左侧蓝线 h2、居中 hero 等)
- •法律文档(terms/privacy 等)使用标准
<h1><h2><p> 排版已足够 — 卡片样式是过度装饰
v2.3.3
2026-04-20 · 6个月前
页面翻译结构回滚(回归单表)
Changed
决策背景:2.3.1 中将页面内容拆分为韩语原文的 rzx_page_contents 和非韩语的 rzx_translations,2.3.2 中在编辑器添加了独立保存路径。然而,设计重审后发现两个表的实际结构完全相同(slug/key + locale + content),却带来了以下额外成本:
- •韩语原文在两个表中重复存储(用于 db_trans fallback 链镜像)
- •编辑器保存逻辑需要对 ko vs. 非 ko 进行分支处理
- •在页面管理界面显示 locale 状态时需要对两个表进行 JOIN
- •最初的理由("AI 翻译流水线统一队列")实际价值有限——长页面正文 HTML(10KB)与短 UI 字符串(20字节)需要不同的工作流(分片切割、标签保留等),统一意义不大
恢复的结构:单一 rzx_page_contents 表,每个 locale 一行(原始设计)
Migration
- •
rzx_translations.page.{slug}.title/content × 7 个 slug × 12 个非 ko locale(168 行)→ 恢复到 rzx_page_contents
- •从
rzx_translations 中删除所有 page.* 键(234 行)
- •目标:Brand、terms、privacy、refund-policy、tokushoho、funds-settlement、data-policy
- •同时应用于开发数据库和生产数据库
Changed
- •
resources/views/admin/site/pages-edit-content.php — 移除 ko/非ko 分支,改为简单 UPSERT
- •
resources/views/admin/site/pages-document.php — 同上
- •
resources/views/customer/page.php — 移除 db_trans('page.*.title/content'),直接读取 page_contents(保留 fallback 链 locale → en → ko)
- •
resources/views/admin/site/pages.php — 页面列表标题也直接从 page_contents.title 读取
Kept
rzx_translations 本身保留 — 继续用于以下场景:
- •论坛(
board_post.{id}.title/content)
- •UI 字符串(
menu.*、设置标签)
- •页面 SEO 元数据(
page.{slug}.browser_title|meta_keywords|meta_description)— 字符串较短,存放此处合适
原则:短 UI/元数据字符串 → rzx_translations;长页面正文内容 → rzx_page_contents,根据数据特性分开存储。
v2.3.2
2026-04-20 · 6个月前
页面编辑器翻译 DB 保存逻辑对齐
Changed
2.3.1 将页面内容保存结构迁移到原始 ko(rzx_page_contents)+ 翻译 DB(rzx_translations)之后,管理员编辑器仍仅向 rzx_page_contents 进行 INSERT/UPDATE——导致与迁移格式不一致,渲染端 db_trans() 查询失败。本版本修复此问题。
分支规则(源语言环境 = $_ENV['DEFAULT_LOCALE'] ?? 'ko'):
| locale | 保存路径 |
|---|
ko(源) | rzx_page_contents + 镜像至 rzx_translations(db_trans() 兜底用) |
en/ja/zh_CN/... | 仅 rzx_translations(page.{slug}.title、page.{slug}.content) |
保存非源语言环境时,若 rzx_page_contents 中无源行,自动创建 stub 行(保留菜单/设置连接)。is_active 统一应用于源行。
Changed
打开非源语言环境编辑页面时:
1. 先从 rzx_translations 查询 page.{slug}.title/content + locale
2. 未找到则回退到旧版 rzx_page_contents 行(兼容迁移遗漏的页面)
源语言环境仍与以往相同,只用 rzx_page_contents。
Changed
- •页面删除:同时删除
rzx_translations WHERE lang_key LIKE 'page.{slug}.%'
- •slug 变更:批量 UPDATE
rzx_translations.lang_key 中 page.{old_slug}. → page.{new_slug}.
Changed
以往在 rzx_page_contents 中按 locale 分别存储完整内容行的方式,已统一为 原始 ko + 翻译数据库(rzx_translations) 方案。与版块(board_post.*)的存储结构保持一致。
目标7个页面:Brand, terms, privacy, refund-policy, tokushoho, funds-settlement, data-policy
Before:
rzx_page_contents
├── Brand / ko (完整内容)
├── Brand / en (完整内容)
├── ... (13个 locale 行)
After:
rzx_page_contents
└── Brand / ko (原始 1 行)
rzx_translations
├── page.Brand.title × 13 locale (含 ko)
└── page.Brand.content × 13 locale
迁移结果:
- •
rzx_page_contents:7个slug × 12条非ko行 = 84行已删除
- •
rzx_translations:7个slug × 13个locale × (title + content) = 182行已迁移
- •已应用于开发和生产数据库,渲染验证通过(ko/en等各locale均正常显示)
Changed
- •移除"新建页面"标头按钮 — 原本是不可用的占位符。页面由菜单管理创建,是唯一的数据来源。
- •移除垃圾桶🗑图标 + AJAX处理程序 +
deleteUserPage() JS — 删除菜单时会一起清理页面,因此不需要独立的页面删除路径。防止因误删导致菜单损坏。
- •保留:设置 ⚙ · 编辑 ✏ · 预览 👁 图标
Fixed
- •
设置 > 网站 > Logo图片 上传失败:因缺少 storage/logos/ 子目录导致 move_uploaded_file() 静默失败。在上传处理器中添加子目录自动创建,并在开发和生产服务器上创建目录(www-data:www-data,775)。
- •恢复布局Logo优先级:曾短暂改为"网站设置优先",后根据"各布局使用专属Logo"的需求恢复为 布局 > 网站回退。布局未设置Logo时自动使用网站Logo。
- •涉及:
skins/layouts/{default, minimal, modern, modern-copy-260413}/header.php 及 footer.php
Fixed
- •保留
bi-guide / logo-guide slug 重复行中最早创建的一条(id=186, 187),删除重复的 id=193, 194
- •已应用于开发和生产环境。菜单API的重复INSERT问题已在v2.3.0中修复
Added
在 /var/www/_upload/ 创建了Logo资产 — 按需上传到生产环境:
图标(仅标志)
- •
voscms-logo-color-{256,512,1024}.png · 彩色(deep·ocean·sky·ocean + 中心deep)
- •
voscms-logo-mono-{256,512,1024}.png · sky纯色 + 透明度 1/0.7/0.48/0.7 渐变
横向字标(用于页头)— 820×256 比例
- •
voscms-wordmark-{128h,256h,512h}.png · 浅色(Vos deep + CMS灰色)
- •
voscms-wordmark-dark-{128h,256h,512h}.png · 深色(Vos sky + CMS slate-300)
纵向字标(用于应用图标 / OG图片)— 360×420 比例
- •
voscms-stacked-light-{256h,512h,1024h}.png
- •
voscms-stacked-dark-{256h,512h,1024h}.png
所有SVG原件均已保留。已安装 librsvg2-bin,提供 rsvg-convert CLI。OKLCH颜色支持问题通过十六进制转换版(voscms-logo-mono-hex.svg)解决。
v2.3.0
2026-04-20 · 6个月前
页面设置标签页重构 + Changelog 系统
Added
- •DB 表
rzx_changelog 新增 — 按版本 × locale 独立存储记录,追踪 translation_source(original/ai/manual)+ source_hash
- •解析器
RzxLib\Core\Changelog\ChangelogParser — Keep a Changelog 标准 + 内部区块白名单(Infrastructure/Internal/Refactor/Chore/Docs/Test 为私有)
- •导入器
ChangelogImporter — 幂等合并,保护手动翻译,通过 content_hash 仅检测变更
- •CLI 脚本
scripts/import-changelog.php — --file --locale --dry-run --silent 选项,支持 SemVer 预发布版本(2.1.1-hotfix)
- •翻译接口
RzxLib\Core\Translate\{TranslatorInterface, NullTranslator, TranslatorFactory} — Gemma 4(ai.21ces.com)GPU 就绪后,只需修改 config/translator.php 的 driver 即可激活
- •系统页面
/changelog 已注册(config/system-pages.php),前端视图 resources/views/system/changelog/index.php
- •专属皮肤
skins/page/changelog/skin.json — 卡片样式(filled/outlined/flat)、按区块配色、版本徽章、日期格式、相对时间显示、内部区块可见性开关
- •编辑页面
/changelog/edit 独立拆分 — MD 上传预览、多语言覆盖矩阵、按版本切换/删除、AI 翻译按钮(即将推出)
- •部署自动化 —
deploy-voscms.sh 新增 1.5/5 Changelog import 步骤:自动检测并合并 ko + 12 个 locale 的 .md 文件
- •翻译键
site.pages.changelog 已为 13 个 locale 添加
Changed
- •标签页顺序调整:
[基本信息] [权限] [高级设置] [皮肤] — 系统页面可在末尾追加自己的标签页
- •引入
settings_tabs 架构(config/system-pages.php)— 系统页面声明顶级标签页数组,各条目通过 key/label/icon/view 动态渲染。移除原有 settings_view 底部 include 遗留代码
- •原则确立:设置 = 外观 + 功能 / 编辑 = 数据 — 上传、版本、翻译等数据管理界面统一迁至
/changelog/edit
- •MERGE 保存策略 —
save_settings 处理器与现有设置合并,即使标签页拆分也不会清除其他标签页的数据
- •
saveSettings() JS — 仅提交 DOM 中存在的字段,在部分字段未渲染的分离标签页环境中安全可靠
- •布局/皮肤卡片位置 — 回归基本信息标签页(依据用户反馈),皮肤标签页专属负责 skin.json 变量
- •去除页面宽度重复 — 基本信息标签页中删除
page_width 字段(合并到皮肤的 content_width)
- •service/order 二级子标签平铺 —
config/service-settings-tabs.php 中的 general/domain/hosting/addons 迁移至 settings_tabs,提升为顶级标签页
Changed
- •
/{slug}/settings 和 /{slug}/edit 现已识别 config/system-pages.php — 此前仅查询 rzx_page_contents DB,导致系统页面返回 404。现按 DB → config 顺序查询
- •新增
edit_view 字段 — 直接指定系统页面专属编辑视图的文件路径。点击 /{slug}/edit 时直接 include 对应视图(移除管理员重定向跳转)
- •pages-settings.php 回退机制 — 无 DB 记录的系统页面也从 config 构建
$pageData,防止跳转到页面管理列表
- •管理员图标 URL 统一 —
/{slug}/settings、/{slug}/edit 使用前端标准 URL
Fixed
- •
menus-api.php:修复 external 页面类型 INSERT 前缺少重复检查 — 防止菜单保存两次时 rzx_page_contents 产生重复行
- •修复删除菜单时 external 类型 + widget 的
page_contents 清理遗漏 — 防止产生孤立记录
Fixed
- •标题背景(
title_bg_type、title_bg_image、title_bg_video、title_bg_overlay、title_text_color)、show_title、show_breadcrumb、custom_css、custom_header_html、custom_footer_html — 所有标准页面皮肤变量现已反映至公开视图
- •
_page-title-bg.php partial 现接受 $_contentWidth 变量 — 标题区域跟随内容宽度
- •管理员图标与标题分离 — 独立置于内容区域右上角;即使
show_title=0 也始终显示
- •标题区域上方新增 20px 间距(背景布局均衡)
Added
- •
site.pages.contact 翻译键已为 13 个 locale 添加(ko/en/ja/zh_CN/zh_TW/de/es/fr/id/mn/ru/tr/vi)— 解决原先遗漏
- •页面管理系统指南
docs/PAGE_ADMIN_GUIDE.md 新增 — 整理标签页结构、架构、路由、权限及扩展方式
v2.2.2
2026-04-19 · 6个月前
统计小组件改进 + 管理员顶栏修复
Added
- •每个条目的数字、后缀、标签(多语言)、图标和颜色字段
- •管理员小组件构建器支持条目的添加/编辑/删除(新增
stat_items 类型编辑界面)
- •16 种图标(users, chart, star, heart, check-circle, clock, calendar, globe, shield, lightning, trophy, cart, dollar, building, chat)+ 10 种颜色选项
- •进入视口时的数字滚动动画 — IntersectionObserver + easeOutCubic 1.4s
- •仅对数值进行计数(
24/7 等字符串原样显示),保留逗号格式和小数点
- •
widget.json v1.1.0 → v1.2.0
Fixed
- •修复
admin_name 以 enc: 前缀存储且未解密直接显示的问题
- •修复头像查询错误地 LEFT JOIN 不存在的
staff 表的问题 — 现根据 admin_id = users.id 统一结构直接查询 rzx_users.profile_image
- •自动为相对路径头像添加 baseUrl 前缀
v2.2.1
2026-04-19 · 6个月前
URL 截图(缩略图 / 全页截图)
Added
- •所有板块的每个
<input type="url"> 字段(包括扩展变量 url 类型)旁边自动插入 [获取缩略图] [获取截图] 按钮
- •缩略图:原生渲染 1280×960 → 800×600 输出(首屏视口)
- •截图:原生渲染 1280×全页 → 800×缩放 输出(完整滚动页面,使用实际页面高度)
- •分步进度条界面 —
连接服务器 → 加载页面 → 截取屏幕 → 生成图片 → 保存文件 → 等待响应
- •自动将截取的缩略图设为封面图 — 标记为
board_files.is_primary=1,board-showcase 小组件优先使用
- •新路由
/board/api/url-capture?type={thumbnail|screenshot}&url=... + api-url-capture.php 代理
- •向
/board/api/files 添加 set_primary 操作 — 将现有附件之一指定为封面图
Changed
- •附件图片查询
ORDER BY is_primary DESC, id ASC — 截取的缩略图优先显示
- •创建文章时通过
primary_file_pos 参数向服务器传递封面文件索引
v2.2.0
2026-04-18 · 6个月前
Marketplace 分离
Changed
- •Marketplace 产品分离:
plugins/vos-marketplace/ 插件原本共享的功能被拆分为独立产品 → github.com/THEVOSjp/Marketplace 新仓库,在 market.21ces.com 独立部署
- •插件仅保留"面向客户的 UI(浏览、购买、安装、授权)"——数据、卖家和结算由 marketplace 服务器专责处理
- •Core 侧 API 集成点已更新
Added
- •选择语言后显示模态框 — 提示需要备份
.env + 数据库 + storage/uploads/,以及 APP_KEY 丢失后无法解密的警告
- •两步确认:复选框 + 确认按钮(禁止无条件安装)
- •为所有 13 种语言添加完整翻译(
backup_title/body/item_env/db/uploads/warn/check/confirm/cancel)
Added
- •
scripts/register-widgets-to-marketplace.php — 将 28 个基于文件的 widget 批量注册到 rzx_mp_items
Changed
- •
plugins/vos-marketplace/src/CatalogClient.php — 默认 API URL 改为 https://market.21ces.com/api/v1,fetchItem() 路径更新,checkUpdates() 查询格式更新
- •
plugins/vos-marketplace/plugin.json — marketplace_api_url 默认值更新
- •
rzxlib/Core/Modules/WidgetLoader.php — 缩略图 URL 现在包含缓存破坏参数 ?v={mtime}(应对 Cloudflare immutable 缓存)
Fixed
- •
widgets/feature-tour/widget.json — 字段整理
- •部分 widget 缩略图已更新(staff、testimonials、feature-tour、shop-map、shop-ranking、stylebook)
Added
- •contact-info (v0.1.0) — 联系卡(地址/电话/邮箱/营业时间 + 图片 + 小地图)
- •location-map (v0.1.0) — 横向地图(Google Maps + 下方3列信息,可调整宽度)
Added
- •项目提交页面全面重构 — 3个标签页(基本信息 / 发布 / 销售)
- •许可证(GPL/LGPL/BSD/MIT/CC/PD/商业)、仓库URL、演示URL、依赖插件、横幅图片
- •发布历史、销售信息(公开/付费切换、折扣价/截止日期)、UX改进
Added
- •开发者菜单(ID:20)支持13种语言,Hero CTA的description/typing_words补充12种语言
Changed
- •明确小部件名称区分(地图 / 联系卡),
page.php 添加fullWidthTypes
- •contact-form分类 → 仅标签(删除代码,小部件设置可编辑)
Fixed
- •board-contents/board-showcase: file_type → mime_type
- •boards-api: 缺少is_shown_in_list + options JSON约束
- •contact-form POST: 完全清空ob缓冲区
- •Hero CTA: typing_words/description的
\n 双重转义
DB Changes
- •rzx_mp_items: 新增license, repo_url, demo_url
- •rzx_board_extra_vars: 新增is_shown_in_list
- •rzx_contact_messages: 新表
Added
- •download-hero 小工具 — 软件下载页面(实时与 version.json 联动,内置 4 种语言,主要功能 / 系统要求 / 版本历史)
- •/downloads 页面 — widget 类型系统页面,13 种语言菜单翻译,
is_system=1
- •contact-form 小工具(v0.1.0)— 私密 1:1 咨询表单小工具(支持访客提交,分类选择,蜜罐防垃圾邮件,AJAX 提交)
- •contact-info 小工具 — 联系信息展示小工具
- •location-map 小工具 — 位置地图小工具
- •rzx_send_mail() 公共辅助函数 — 在
rzxlib/Core/Helpers/mail.php 中新增 SMTP 邮件发送函数
- •rzx_contact_messages 表 — 用于存储咨询内容的数据库表
- •/contact 页面 — widget 类型系统页面,13 种语言菜单翻译
Fixed
- •系统页面删除保护 — 从菜单中删除系统页面时,保留页面内容/小工具(仅移除菜单条目)
- •
menus-api.php:通过 DB is_system + config/system-pages.php slug 双重验证
- •
menus-js.php:删除系统页面时显示"仅从菜单中移除"的提示
- •系统页面菜单多语言 — 将系统页面添加到菜单时,自动从
site.pages.* 翻译键注册 13 种语言标签
- •下载页面翻译 — 新增
site.pages.downloads 的 13 种语言翻译
Changed
- •首页 Hero — 下载按钮 → 直接下载
/download/voscms-latest.zip,版本更新至 v2.1.1
- •Auth.php — 优先调用公共辅助函数
rzx_send_mail(),保留 sendSmtpMail 作为回退
- •index.php — 添加
mail.php 辅助函数的自动加载
Changed
- •主机托管标签页 — 概要卡片 + 用量进度条 + FTP/数据库连接信息表(管理员配置后自动显示)
- •域名标签页 — 域名卡片 + 主设置 + 域名服务器信息表(管理员配置后自动显示)
- •邮件标签页 — 邮件服务器信息(IMAP/SMTP)+ 按账户卡片 + 内嵌密码修改
- •维护标签页 — 信息卡片 + 计划日期 + 工作历史(管理员记录后自动显示)
- •附加服务标签页 — 统一卡片布局
- •与管理员 partial 统一为相同的信息结构(管理员在 metadata 中录入 → 自动同步到我的页面)
Changed
- •活动日志区域从 1/3 缩小至 1/5 比例
- •移除管理员域名标签页中 NS 默认值的硬编码(为 Cloudflare API 集成做准备)
Changed
- •配置工作流全面改版:子域名优先 → 购买域名随后连接
- •配置 ID 规则:子域名名称或购买域名的 SLD
- •利用 Cloudflare 通配符隧道(无需添加子域名 A 记录)
- •服务器 2 磁盘配置变更:NVMe 256 GB + SSD 2 TB + HDD 8 TB 三盘体制
Added
- •服务分类体系 — 新增
service_class 字段(recurring/one_time/free),completed_at 一次性服务完成日期
- •我的页面服务详情 —
/mypage/services/{order} 按类型管理标签页(主机/域名/邮件/维护/增值服务)
- •服务管理 API —
api/service-manage.php(自动续期开关、续期申请、主域名设置、邮件密码修改)
- •管理员订单管理 —
/admin/service-orders 订单列表 + 详情页,一次性状态弹窗(已接收/处理中/暂挂/已取消/已完成)
- •管理员菜单 — 侧边栏新增"服务订单"菜单(position: 65)
Added
- •phone-display — 电话号码显示组件(服务端
format_phone() 助手),无 JS 依赖
- •format_phone() — PHP 国际电话号码格式化函数(韩国/日本/美国/中国/英国/法国/德国/澳大利亚等)
- •免费域名设置 — 在管理员设置中管理免费子域名列表(
service_free_domains),支持多域名选择
Fixed
- •免费服务订阅缺失 — 免费订单未为域名/增值/维护等创建订阅记录 → 重构为批量创建所有服务
- •付款区域条款同意 — 免费订单时条款复选框随付款区域一起隐藏 → 分离至区域外部
- •updateSubmitButton isFree 判断 —
btn.closest('form') NULL → 用 document.querySelector 修复
- •管理员侧边栏活动指示 —
$adminPath 未定义导致所有菜单不活动 → 添加变量声明
- •我的页面头像 — services.php/service-detail.php 中缺少
use Auth + $user = Auth::user()
- •增值服务一次性检查 — 管理员设置中的
one_time 标志现在在下单时正确反映到 service_class
- •一次性服务初始状态 — 改为创建时状态为
pending(已接收)而非 active
Changed
- •订单 API 重构 — 将 3 种付款路径(免费/刷卡/转账)的订阅创建代码整合为共同函数
$subscriptionData + _insertSubscriptions()
- •服务列表 UI — 内联展开 → 卡片链接 + 独立详情页
- •电话号码显示 — 在个人资料/会员列表/员工列表中应用
format_phone()
- •免费域名动态化 —
.21ces.net 硬编码 → 引用管理员设置值
v2.1.1-hotfix
2026-04-16 · 6个月前
Fixed
- •页脚菜单 404 错误 —
rzx_page_contents 表中缺少法律文档页面数据(terms、privacy、refund-policy、data-policy、tokushoho、funds-settlement)→ 从测试数据库恢复
- •Widget 构建器图片/视频上传失败 — 修复前端包装器(
page-widget-builder.php)的 FormData POST 未传递给 AJAX 处理器的问题(添加文件上传条件 + ob_end_clean/exit 处理)
- •上传目录权限 — 将
storage/uploads/widgets/ 的所有者改为 www-data,以授予 PHP-FPM 写入权限
Added
- •服务申请菜单多语言 — 在
rzx_translations 表中添加 menu_item.19.title 的 13 种语言翻译
- •Hero CTA Widget 多语言 — 为 Dev 页面 Hero 横幅的 title、subtitle 和 button text 应用 13 种语言翻译
- •上传状态预览 — 图片/视频上传时添加可视化反馈:处理中(加载动画)、成功(对勾)和失败(错误消息)
Added
- •第0步语言选择界面 — 安装开始前从13种语言中选择;此后整个UI以所选语言显示
- •安装翻译文件分离 —
resources/lang/install.php(13种语言 × 45个字符串)
- •会员等级多语言 — Normal/Silver/Gold/VIP自动生成13种语言翻译
Added
- •config/admin-menu.php — 核心管理员菜单分离到配置文件(Core更新时保留)
- •admin-sidebar.php 重构 — 731行硬编码 → ~200行动态渲染器(基于config + plugin.json)
- •vos-shop plugin.json — 硬编码菜单迁移到
menus.admin 格式
Added
- •侧滑菜单 — 移动端:头像+姓名切换栏 → 左侧滑入遮罩(300ms ease-out)
- •渐隐暗化背景 — 点击背景或X按钮关闭;body滚动锁定
Added
- •force_locale — 强制应用默认语言(
?lang=xx 参数允许用户更改)
- •default_language — install.php ↔ Translator配置键统一
- •URL参数 —
?lang=xx 优先检测,保存到会话/Cookie
Fixed
- •FAQ皮肤未应用 — 迁移SQL在install.php之前对默认版块执行了裸
INSERT,导致INSERT IGNORE被静默忽略;已修复
- •translations表缺少source_locale — 核心迁移缺少列 → db_trans()完全失败 → 用户信息/菜单/多语言不显示;已修复
- •设置标签侧边栏活动指示 — 添加
route_prefix属性,使设置菜单在所有设置子路由中保持活动状态
- •安装会话残留错误 — 没有.env的全新安装中,残留的PHP会话导致第0步被跳过;已修复
- •nginx 403 — admin/物理目录与路由的冲突已修复(移除
try_files $uri/)
- •混淆脚本版本硬编码 — obfuscate.php现在从version.json动态读取版本
Changed
- •网格/board-contents小部件多语言视图 — 添加rzx_translations查询(当前语言环境 → 英语回退)
- •站点行业分类 — 从15个扩展到26个(新增:企业、购物中心、法律、会计、IT、媒体等;13种语言)
- •网格小部件设置 — grid-section的render.php更改为原生单元格类型(
board-list);13种语言标题
- •第4步语言选择 — 从5种扩展到13种语言;以安装语言预填充
- •时区选择 — 扩展到涵盖13语言用户地区的12个时区
v1.26.0
2026-04-01 · 7个月前
Added
- •服务选择页面顶部以3列展示套餐(组合)服务 — 用琥珀色主题与单项服务进行视觉区分
- •SET 徽章、活动折扣标签、包含的服务名称、套餐价格、原价划线、折扣率显示
- •选择套餐后自动选中所有包含的服务(价格按套餐价计算)
- •套餐中包含的服务不可单独切换(防止错误价格计算)
- •指定模式:通过
rzx_staff_bundles 表按员工过滤套餐
- •将
bundles 参数传递至确认页面
- •多语言支持:已为13种语言添加与套餐相关的自助终端翻译键
Added
- •视图切换按钮 — 顶部栏的
[月] [周] [日] 切换(激活状态:蓝色)
- •周视图 — 左侧纵轴 = 星期,顶部横轴 = 时间轴
- •水平滚动,预约块以时间条形式显示
- •泳道算法:检测时间重叠后自动向下排列,行高可变
- •左侧边栏 ↔ 表格垂直滚动同步
- •日视图 — 横向 = 时间轴,纵向 = 泳道(与周视图相同方法)
- •基于营业时间的时间范围 — 依据
business_hour_start/business_hour_end 设置;范围外的预约自动扩展
- •点击空白格传递时间 — 在周/日视图中:点击 X 坐标 → 以15分钟为单位计算时间 → 自动填入预约弹窗开始时间
- •顶部导航栏固定 — 应用
overflow-x-hidden + sticky;水平滚动时保持在视口内
Added
- •管理员 > 设置 > 通用 — 新增营业开始/结束时间设置界面
- •
business_hour_start, business_hour_end DB 设置键
- •应用于日历周/日视图的默认时间范围
Fixed
- •POS
add-service 缺失字段 — 新增 start_time、end_time、staff_id、designation_fee、notes 的传递(原先:服务器端时间硬编码,员工/备注缺失)
- •防止 end_time 跨越午夜 — 在
ReservationHelper、start-service API 及预约表单 calcEnd() 中均应用 % 24 → min(23:59) 上限
- •POS 使用中判断的跨午夜处理 —
CustomerBasedAdapter 中将 end_time < start_time 作为跨午夜处理
- •预约套餐验证 — 修复仅选择套餐(不选单项服务)时也能创建预约的问题
Changed
- •选项卡名称变更:接待 / 接待名单 / 预约人
- •接待名单:
walk_in、pos、kiosk、admin 来源 — 显示所有状态
- •预约人:
phone、online 来源 — 显示所有状态
- •排序顺序:等待 → 已确认 → 使用中 → 已完成 → 未出现 → 已取消;同一状态内按时间排序
- •已完成/已取消/未出现行:以
opacity-50 显示为半透明,显示未分配徽章
Changed
- •已完成徽章:由灰色改为绿色
- •已添加已取消/未出现徽章(数量为0时隐藏)
Added
- •卡片底部:等待状态卡片新增未出现按钮(禁止图标),取消按钮改为红色
- •详情弹窗:
pending 和 confirmed 状态均显示未出现操作按钮
- •分组批量未出现:新增
POS.noShowAllServices() 函数
Fixed
- •预约详情返回导航 —
<a href="/reservations"> → history.back(),返回上一页
- •多语言:已为13种语言添加日历视图切换(月/周/日)、套餐、营业时间相关键
v1.25.0
2026-04-01 · 7个月前
Architecture
- •POS 拆分为独立插件结构
- •
resources/views/admin/reservations/pos-*.php → 移至 resources/views/admin/pos/ 目录
- •根据
pos/ 目录是否存在自动启用/禁用 POS 功能(is_dir() 检测)
- •侧边栏菜单:
pos/ 目录不存在时自动隐藏 POS 菜单
- •
index.php 路由:pos/ 目录不存在时禁用 POS 路由
- •
pos/_init.php → 委托给预约公共 _init.php(共享 DB、认证、多语言)
- •API 端点保留在
reservations/_api.php(向后兼容性有保障)
Added
- •统一支付弹窗 — 积分 + 现金 + 刷卡同时使用(组合支付)
- •积分:查询余额,手动输入或全额使用
- •现金:输入金额
- •刷卡:输入金额 + "使用全部余额"自动填写按钮
- •分期:一次性付款 / 选择 2–12 期
- •实时自动计算合计、找零和不足金额
- •Stripe 刷卡支付时,现金/积分仅在刷卡成功后处理(取消时安全)
- •服务详情弹窗 — 积分显示
- •会员积分余额始终显示在标题区域(即使余额为 0 也显示)
- •服务详情弹窗 — 员工徽章改进
- •已分配/指定徽章显示在员工姓名前(之前:姓名下方)
- •收据/打印按钮位置调整
- •移至客户详情上方,收据(左)+ 打印(右)布局
- •打印功能改进
- •打印当前服务详情弹窗内容,而非打开外部页面
Changed
- •卡片布局 — 基于 grid → 基于 flex-wrap 的固定尺寸卡片
- •固定卡片尺寸:默认 320×240px(small:260×200,large:380×280)
- •卡片尺寸不随屏幕宽度变化,自动换行
- •刷卡支付弹窗 — 扩大至宽 1030px、高 800px
Fixed
- •API 跨域错误已解决
- •
$baseUrl 被硬编码为 .env 中的 APP_URL,导致从其他主机/HTTPS 访问时 fetch 失败
- •控制面板:fetch URL 改为相对路径(
/update-api.php)
- •预约
_init.php:$baseUrl 改为空字符串,使所有 fetch 使用相对路径
- •彻底解决 Cloudflare HTTPS 代理环境下的混合内容问题
- •DB 迁移执行错误 — 解决 "Failed to fetch"(跨域问题)
- •Stripe 组合支付取消时现金预先扣除 Bug
- •之前:先处理现金 → 取消刷卡时现金已被处理
- •之后:仅在 Stripe 刷卡支付成功后才处理现金/积分
i18n
- •
pos_pay_after_points — 积分抵扣后的金额
- •
pos_pay_proceed — 继续支付
- •
pos_pay_remainder — 使用全部余额
- •
pos_pay_installment — 分期付款
- •
pos_pay_lump_sum — 一次性付款
- •
pos_pay_months — 期
- •
pos_pay_total_pay — 合计
- •
pos_pay_short — 不足
- •
show_receipt — 收据
- •
show_print — 打印
v1.18.0
2026-03-29 · 7个月前
Added
- •多语言日期格式化函数 —
formatReservationDate($dateString, $locale)
- •支持 13 种语言 (ko, en, ja, zh_CN, zh_TW, de, es, fr, id, mn, ru, tr, vi)
- •在预约详情页自动本地化日期和星期
- •回退:不支持的 locale → 英语格式
Changed
- •预约详情页多语言处理
- •服务名称、员工姓名和套餐名称已本地化(基于 DB 的 translations 表)
- •集成日期格式化函数
- •支付状态标签本地化(payment_status 字段)
- •支付状态多语言支持
- •向所有语言文件(11 种语言)添加
payment 部分
- •翻译项:未支付、已支付、部分支付、已退款
Fixed
- •预约详情页:之前未本地化的员工姓名和服务名称现已正确显示
- •支付状态标签:修复了仅以韩语显示的问题
- •统一为基于
_tr() 函数的多语言处理方式
Layout & UI
- •页面宽度统一 (max-w-5xl → max-w-7xl)
- •版块页面(列表、阅读、撰写):max-w-5xl → max-w-7xl
- •外部页面(page.php):更新默认值及 DB 配置值
- •预约详情 / 预约查询 / 员工页面:更新 DB 配置值
- •结果:所有页面宽度现与预约页保持一致
Documentation
- •在 COMPONENT_MANUAL.md 中添加
formatReservationDate() 的详细文档
- •支持的语言及格式表
- •使用示例和内部结构
- •注意事项及相关函数
v1.16.0
2026-03-23 · 7个月前
Added
- •移动端底部菜单栏 — 员工 / 预约 / 首页 / 登录(或我的)/ 注册 / 更多,当前页面高亮显示
- •移动端"更多"面板 — 主菜单 + 我的页面 / 退出登录
- •布局/皮肤设置实际生效 — site_layout、site_page_skin、site_board_skin、site_member_skin → 反映至渲染
- •no_layout 参数 — 无布局纯内容模式(用于预览)
- •新增翻译键 — common.nav.staff、common.nav.more(13种语言)
Fixed
- •将布局应用于会员页面(login/register/forgot/reset):通过提取皮肤
<main> 消除重复的页面头部
- •修复会员皮肤中 ImageCropper/ProfilePhotoCropper 重复声明的错误
- •修复菜单加载器 include_once 问题:在皮肤 closure 中优先加载时 base-header 菜单缺失的问题
- •
apple-mobile-web-app-capable 已弃用 → mobile-web-app-capable(8个文件)
- •在移动端隐藏页头的登录/注册按钮(由底部菜单栏替代)
- •底部菜单栏支持 iOS safe-area
Changed
- •将会员页面从独立布局合并至默认布局(login/register/forgot/reset)
- •移除页脚底部外边距(移动端菜单栏使用固定定位)
v1.15.3
2026-03-22 · 7个月前
Added
- •布局详细设置面板 — 基于 SkinConfigRenderer 的设置表单 AJAX 加载
- •布局菜单设置 — layout.json 的 menus 部分 → 自动生成 DB sitemaps 下拉列表
- •SkinConfigRenderer 标签页支持 — 在 vars 中添加
tab 属性后自动生成标签页 UI
- •SkinConfigRenderer 重构 — 统一为
renderVar() 单一方法,分离 renderFormFlat/renderFormWithTabs,renderDependsOnJs 公共化
- •layout.json 扩展 — menus(GNB/FNB)、14 个 vars(页眉/Logo/颜色/页脚/自定义)、13 种语言
- •布局预览联动 — 选择"禁用"时以 ?no_layout=1 显示无布局预览
Fixed
- •布局管理菜单查询:
rzx_menus → rzx_sitemaps 表名修正
- •中央面板宽度调整 + 操作链接 whitespace-nowrap
Pending
- •将布局/皮肤设置值应用于实际页面渲染(下一个会话)
v1.15.2
2026-03-22 · 7个月前
Added
- •布局管理页面 — 3面板结构:左侧预览+菜单、右侧皮肤列表、详细设置面板
- •每个皮肤条目:缩略图 + 详细设置/创建副本/删除操作链接
- •"禁用" / "安装其他皮肤" 选项
- •4分类保存:布局、页面、版块、会员(
site_layout、site_page_skin、site_board_skin、site_member_skin)
Changed
- •"设计管理" → 更名为 "布局管理"(13种语言:admin.php + site.php)
v1.15.1
2026-03-22 · 7个月前
Changed
- •网站管理的15个页面 → 应用共享头部
_head.php
- •论坛: boards, boards-create, boards-edit, boards-trash
- •菜单: menus
- •设计: design
- •页面: pages, pages-settings, pages-edit-content, pages-document, pages-compliance, pages-widget-builder
- •小部件: widgets, widgets-create, widgets-marketplace
- •嵌入模式页面(boards-edit, pages-settings, pages-edit-content)仅在非嵌入模式下应用
_head.php
- •所有管理员页面的头部/布局统一工作全部完成
v1.15.0
2026-03-22 · 7个月前
Added
- •系统小部件模块 — 4个小部件:staff(员工介绍)、booking(预约)、lookup(预约查询)、cta001(预约行动召唤横幅)
- •系统页面 — staff、booking、lookup 注册到数据库(is_system=1)+ 路由(
/staff、/booking、/lookup)
- •基于小部件的页面渲染 — staff/booking/lookup 页面在放置小部件时渲染小部件,未放置时回退到原有渲染
- •小部件自动注册到数据库 — 调用
syncToDatabase() 在添加小部件目录时自动注册
- •小部件分类
system — 翻译为13种语言(widgets.categories + widget_builder.cat)
- •页面列表统一 — 系统页面循环渲染 + 统一的齿轮/编辑/预览图标组
- •管理员页面标题统一 —
$pageSubTitle + $pageSubDesc(通过 _head.php 公共输出)
- •翻译键新增 — staff.admins、staff.attendance.report/stats、points.description 等
Fixed
- •小部件构建器中
page_slug = 'home' 硬编码 → 动态处理 $_GET['slug']
- •小部件构建器 AJAX save/preview 中
home 硬编码 → 动态 $pageSlug
- •小部件构建器预览 URL → 动态
$pageSlug(首页固定 → 各页面)
- •修复小部件 preview_widget 中缺少 WidgetLoader require
- •服务卡片视图图片路径(
/storage/ 前缀)
- •自助终端设置宽度
max-w-3xl → 统一为 100%
- •POS 标题"预约管理"→ 改为"POS"
Changed
- •员工管理10个页面 + 会员管理4个页面 → 应用公共
_head.php 标题
- •自助终端/套餐页面应用
_head.php
- •自助终端语言设置 grid → flex-wrap 响应式
- •页面列表中系统页面通过数据驱动循环渲染
v1.14.1
2026-03-22 · 7个月前
Added
- •页面皮肤标签页 — 皮肤基本信息 + 扩展变量设置(基于SkinConfigRenderer)
- •皮肤应用于所有页面类型 — 皮肤设置同样适用于document/widget/external
- •标题背景系统 — 图片/视频背景 + 叠加层 + 文字颜色(通用局部视图
_page-title-bg.php)
- •depends_on系统 — 在skin.json中声明式定义字段间依赖关系,渲染器自动生成JS(支持checkbox/radio)
- •皮肤文件上传 — 通过multipart上传图片/视频(
storage/skins/page/{skin}/)
- •卡片式布局/皮肤选择器 — 在模块信息标签页改为缩略图卡片UI
- •SEO系统 — SEO助手、标题模板、OG/Twitter元标签、内容提取
- •OG Image上传 — URL输入 + 文件上传 + 预览
- •通用结果弹窗 — 统一的保存成功/失败弹窗UI(支持13种语言)
- •服务卡片视图 — 全背景图片卡片 + 表格/卡片切换按钮
- •服务拖拽排序 — 在两种视图中更改顺序并保存到数据库
- •预约员工分配/指定 — 预约详情中有分配/指定2个按钮
- •预约来源UI — 电话预约/现场到访/在线选择
- •电话预约设置 — 在服务基本设置中启用/禁用开关
- •安全标头 — X-Frame-Options + CSP frame-ancestors
- •PAGE_SYSTEM.md — 页面系统开发文档
- •PRD_OrderSystem.md — 桌台点餐系统规划文档
- •PRD_KioskSystem.md — 自助终端系统规划文档
Fixed
- •应用数据库中的favicon设置(前端 / 管理员 / 皮肤布局 — 4处)
- •仪表板迁移URL
window.location.origin → $baseUrl(子目录环境)
- •页面设置嵌入模式API URL → 直接指定admin路径
- •结果弹窗i18n:页面渲染时使用locale消息,而非API响应
- •皮肤标签页空皮肤值回退(
"" → default)
- •解决
pages-settings.php 中 php://input 重复消费问题
Changed
- •自助终端 / 自助终端设置 / bundle页面 → 应用共享头部
_head.php
- •皮肤设置保存JSON → FormData(multipart)传输(支持文件上传)
- •向SkinConfigRenderer添加
$baseUrl 参数(图片/视频预览)
- •13种语言皮肤翻译(skin.json + site.php + common.php)
v1.13.0
2026-03-21 · 7个月前
Added
- •页面系统完成 — 从菜单创建文档/小部件/外部页面时自动创建页面
- •动态页面渲染器 —
page.php(文档→HTML,小部件→WidgetRenderer,外部→iframe/include)
- •页面环境设置 — 3个标签页(基本 / 布局与皮肤 / SEO),保存为
page_config_{slug} JSON
- •页面内容编辑 — 按语言编辑标题与内容、更改slug、更改类型、删除
- •动态页面管理列表 — 从数据库自动加载用户页面,按类型显示图标与徽章
- •前端管理员图标 — 齿轮(设置)+ 编辑(内容)分开显示
- •外部页面iframe — 加载失败时显示"在新窗口中打开"提示
- •内部PHP/HTML文件 — 通过include在RezlyX布局内渲染
Fixed
- •菜单快捷URL
#menu_{id} → 保存实际菜单URL
- •菜单编辑显示与创建时相同的快捷UI结构
- •菜单保存时反映快捷URL(
formMenuType → 面板可见性依据)
- •为13种语言新增菜单翻译(12个菜单项 × 13种语言)
- •修正页面文档编辑器翻译键路径(
admin.site.pages. → site.pages.)
Changed
- •向DB
rzx_page_contents 添加 page_type 列(document/widget/external)
- •删除菜单时同时删除关联页面 + 翻译数据
v1.12.5
2026-03-21 · 7个月前
Fixed
- •修复菜单快捷方式 URL — 现在保存实际菜单 URL,而非
#menu_{id}
v1.12.4
2026-03-21 · 7个月前
Fixed
- •皮肤设置列表类型未生效 — 修复了 localStorage 缓存覆盖皮肤设置的问题
- •禁止切换样式时仅使用皮肤设置,允许时 localStorage 优先
- •移除 checkbox 隐藏字段的重复提交(未选中状态现在由 JS 处理)
v1.12.3
2026-03-20 · 7个月前
Fixed
- •修复英语/日语缺失的板块翻译键(source_locale、reply、style、board_settings 等)
- •对分类名称应用多语言 fallback(locale → en → 原文)
- •板块列表正文支持多语言(网络杂志/卡片/图库预览)
v1.12.2
2026-03-20 · 7个月前
Fixed
- •板块列表正文多语言回退 — 将翻译正文应用于网刊/卡片/图库预览(语言环境 → en → 原文)
- •生产环境皮肤文件缺失 — 通过 FTP 创建
skins/default/board/ 目录并上传 skin.json/缩略图
v1.12.1
2026-03-20 · 7个月前
Fixed
- •生产环境皮肤设置不显示 — 全文件同步重新整理
- •CLAUDE.md + BOARD_SYSTEM.md 文件结构全面更新
v1.12.0
2026-03-20 · 7个月前
Added
- •皮肤设置系统完成 — 基于 skin.json 动态生成表单 + 应用于实际版块
- •分区分组(基本 / 列表 / 链接 / 设计 / 标题背景 / 自定义)
- •新增 radio 和 video 输入类型
- •图片/视频文件上传(FormData multipart)
- •图片/视频删除功能
- •皮肤基本信息表(作者 / URL / 邮箱 / 日期 / 版本 / 缩略图)
- •标题背景图片/视频 — 背景类型、高度、遮罩层透明度及文字颜色设置
- •4 种列表布局样式 — 列表式 / 网络杂志式 / 画廊式 / 卡片式;皮肤文件分离 + 支持覆盖
- •画廊式:全图 cover + 鼠标悬停时的滑动动画
- •网络杂志式:缩略图 + 标题 + 预览 + 元信息卡片
- •公告帖分离至顶部列表(_list-notices.php)
- •皮肤设置生效 — primary_color, border_radius, posts_per_row, allow_style_switch, show_category, 关联版块, Font Awesome, 自定义 CSS/HTML
- •skin.json 默认值自动合并 — 即使未保存到 DB 也会应用 skin.json 的默认值
Fixed
- •skin_config 未保存到 DB(boards-api.php 的 update 操作缺少 skin_config)
- •皮肤保存从 URLSearchParams → FormData(multipart)变更,以支持文件上传
- •支持自动解析
$_POST['skin_config'] 数组
v1.11.3
2026-03-20 · 7个月前
Fixed
- •在文章详情页的上一篇/下一篇标题中应用多语言 fallback(locale → en → 原文)
v1.11.2
2026-03-20 · 7个月前
Fixed
- •板块列表标题多语言回退 — 在所有语言环境中查询翻译(移除仅限韩语的限制),基于源语言的英语回退
v1.11.1
2026-03-20 · 7个月前
Fixed
- •改进 OG 卡片的独立 URL 判断逻辑 — 现在会向上追溯至块级父元素,确保包裹在
<font> / <span> 等内联标签内的 URL 也能被正确处理
v1.11.0
2026-03-20 · 7个月前
Added
- •URL 自动链接 — 自动检测版块帖子正文/编辑器中的 URL → 转换为
<a> 标签
- •OG 链接预览卡片 — 自动生成 SNS 横幅格式(缩略图 + 标题 + 描述 + 域名)的卡片
- •编辑器:输入/粘贴 URL + 回车 → 调用 OG API → 插入卡片
- •正文:独立 URL 链接 → 自动转换为 OG 卡片
- •OgFetcher 模块 — OG/Twitter Card 元数据提取、favicon、自动处理编码
- •OG API —
/board/api/og 端点
- •board-autolink.js — 自动链接 + OG 卡片统一 JS(从 base-header 全局加载)
v1.10.2
2026-03-20 · 7个月前
Fixed
- •编辑器/正文图片对齐 — 覆盖 Tailwind preflight 的
img { display: block }
- •创建
board-content.css 公共 CSS(统一编辑器 + 正文显示)
- •从
base-header.php 全局加载(所有前端页面)
- •在
multilang-modal.php 中添加全局编辑器样式(管理端所有 Summernote 实例)
- •移除版块正文中的
prose 类;编辑器内联样式现可 100% 保留
Changed
- •在 CLAUDE.md 中明确版块正文样式规则(
board-content 类为必填项)
v1.10.1
2026-03-20 · 7个月前
Fixed
- •修复添加版块分类时,多语言弹窗加载上一个分类数据的错误(生成唯一的临时 langKey)
- •在迁移 021 中为
comment_max_depth 添加默认值 3
v1.10.0
2026-03-20 · 7个月前
Added
- •版块扩展变量 — ExtraVarRenderer 组件模块(15种类型:按类型渲染 input/display)
- •扩展变量多语言 — 按语言独立存储扩展变量值(rzx_translations 集成,降级链)
- •版块帖子多语言分离存储 — 以原文语言编辑时直接保存到 board_posts;其他语言将翻译保存到 rzx_translations
- •版块帖子读取降级链 — 按顺序显示标题/正文/扩展变量:当前 locale → en → 原文
- •嵌套回复 — 支持3级深度嵌套评论,递归树排序,内联回复表单
- •评论点赞/踩 — 每条评论的点赞按钮 + API
- •版块设置前端访问 — 管理员齿轮图标 → /board/{slug}/settings 前端布局
- •版块管理标题链接 — 在管理员版块列表中点击标题跳转到对应版块
Fixed
- •版块 API 管理员权限检查:
$currentUser['role'] → $_SESSION['admin_id'](更新4个文件)
- •原文语言提示仅向作者/管理员显示
- •版块设置嵌入模式标签链接支持前端 URL
Changed
- •向数据库
rzx_board_posts 添加 extra_vars JSON 列
- •
comment_max_depth 默认值从 0 → 3
- •统一评论操作栏(点赞/踩/回复/删除图标)
Added
- •默认版块数据 — 公告板、问答、常见问题、自由讨论板迁移(020_default_boards_v193.sql)
Added
- •会员组重置 — 使用默认数据(7个组 + 13种语言翻译)进行初始化
- •积分设置重置 — 将配置值/等级积分/组关联恢复为默认值(不影响会员余额)
- •会员组多语言 — 在组名/权益描述中应用
rzx_multilang_input() 公共组件
- •会员组拖放排序 — SortableJS 卡片排序 + 自动保存
Fixed
- •按语言显示会员组卡片翻译(卡片视图 + 编辑模态框)
- •修复会员组多语言翻译数据乱码(PHP UTF-8 重新保存)
- •修正积分模块设置看板列名(board_name → title)
- •解决积分会员列表排序规则冲突(统一为 utf8mb4_unicode_ci)
- •生产数据库迁移(019_point_system_v190.sql)
Added
- •积分(余额)管理系统 — 三标签结构(基本设置 / 模块设置 / 会员积分列表)
- •积分三字段结构 — point(活动积分)、balance(支付余额)、total_accumulated(累计积分,等级计算基准)
- •累计积分权重 — 支付权重 / 活动权重分离,付费用户优先升级
- •积分兑换 — 积分 → 余额转换(比例、单位、最低积分可配置)
- •17个积分授予/扣除项目 — 与 Rhymix 相同结构(删除时收回、有效期限制、排除公告)
- •模块设置 — 每个板块 15 个积分项目独立配置
- •会员积分列表 — 4列(积分/余额/累计/等级)、搜索、单独编辑
- •等级积分 — 公式计算、最高等级动态调整、关联群组
- •积分系统文档 — POINT_SYSTEM.md 详细设计文档
- •会员群组拖拽排序 — 使用 SortableJS 变更卡片顺序 + 自动保存
- •会员群组多语言 — 群组名称/权益说明应用
rzx_multilang_input() 通用组件
- •会员群组种子数据 — 7个群组 × 13种语言的多语言翻译数据
Changed
- •向 DB
rzx_member_points 添加 balance、total_accumulated 字段
- •DB
rzx_point_levels.group_id 从 INT 改为 CHAR(36)(兼容 UUID)
- •统一
rzx_point_levels、rzx_member_points 排序规则为 utf8mb4_unicode_ci
- •更新捆绑页面布局(
sidebar-main-content → flex-1 ml-64 仪表盘模式)
- •修正捆绑页面货币单位
$config['currency'] → $siteSettings['service_currency']
- •服务时长从 select 改为 input number + datalist
- •在 CLAUDE.md 中明确多语言输入 UI 规范(强制使用 rzx_multilang_input)
Added
- •套餐详细管理页面 — 编辑单个套餐基本信息、上传封面图片、编辑服务组合、关联员工、切换启用/禁用
- •活动折扣 — 每个套餐的活动价格、时间段(开始/结束)、标签设置;在时间段内自动激活
- •套餐列表卡片设计 — 网格卡片布局、图片标题、活动/折扣徽章、底部固定操作栏
- •推荐套餐背景图片 — 客户员工详情页套餐卡片上的封面图片背景 + 渐变遮罩
- •服务时长直接输入 — select → 数字输入(5–480分钟,5分钟为步长)+ datalist 推荐列表
Changed
- •DB
rzx_service_bundles 新增列:event_price、event_start、event_end、event_label
- •套餐列表API新增
total_duration 和活动相关列
- •翻译文件(ko、en、ja):新增套餐详细管理 + 活动折扣键
Added
- •POS设置页面 — 卡片大小、图片/价格/电话显示、透明度、默认标签、自动刷新、提示音、员工分配必须、自动分配
- •POS设置已应用 — 卡片大小/图片/价格/电话/透明度/自动刷新/默认标签全部反映到POS
- •员工自动分配 — 在POS设置中启用时,自助终端签到时自动分配(可提供服务+当日预约最少)
- •POS卡片员工徽章 — 已分配/未分配指示;未分配时禁用继续按钮
- •POS服务图片背景 — 服务详情弹窗的标题+客户区域显示代表服务图片背景
- •员工 is_visible — 控制列表可见性;隐藏员工从预约/POS/自助终端中排除
- •员工卡片横幅 — 管理员员工卡片上的横幅图片+状态徽章
- •自助终端自动分配 — 以 staff_id=NULL 签到;由管理员在POS中分配
Fixed
- •POS员工分配:分配后立即刷新服务列表(防止缓存)
- •员工分配API参数修正(reservation_id → reservation_ids[])
- •修复生产环境中多个缺失的表/列(迁移018加强)
- •添加管理员退出登录路由
- •自助终端预认证路由位置
Added
- •基础布局系统 —
layouts/base-header.php + base-footer.php,在 index.php 中自动应用 ob_start,所有客户页面共用页眉/页脚
- •公告板前端 — 列表、详情、写作/编辑页面,Summernote 编辑器,拖放文件附件
- •公告板短链接 — 无需
/board/ 前缀即可访问 /free、/notice/3 等;自动匹配数据库 slug
- •预约查询页面 — 短链接
/lookup,按预约号 / 邮箱 / 电话搜索
- •预约详情页面 —
/booking/detail/{编号},员工问候气泡,服务/付款/取消信息
- •预约取消页面 —
/booking/cancel/{编号},取消原因输入
- •个人中心预约详情 —
/mypage/reservations/{id},侧边栏 + 详细信息
- •公告板多语言 —
original_locale(首稿语言)+ source_locale(当前内容语言),回退链(source → en → original)
- •员工问候语 —
greeting_before(服务前)+ greeting_after(服务后),多语言,根据预约状态显示
- •管理员资料下拉菜单 — 头像/首字母 + 姓名 + 主页/个人中心/退出链接
- •客户页眉管理员链接 — 以管理员身份登录时,下拉菜单显示管理后台链接
Changed
- •统一所有客户页面的布局(移除各自的 HTML 结构,LayoutManager 自动应用)
- •公告板分类显示条件从
show_category 改为 hide_categories
- •公告板 URL 从
/board/free 改为短链接 /free(默认)
- •管理员顶部栏的"Admin"改为实际登录名 + 头像
Fixed
- •
rzx_users.role 列不存在 → 管理员识别改为基于 $_SESSION['admin_id']
- •
rzx_users.nick_name 列不存在 → 使用 name + Encryption 解密
- •
rzx_staff.profile_image → 修正为列名 avatar
- •Service 模型
category_id int→string 类型转换
- •预约按邮箱/电话查询使用明文搜索(数据未加密)
Added
- •6 个版块管理标签页 — 基本设置、分类管理、扩展变量、权限设置、附加设置、皮肤
- •基本设置标签页整合 — 基本信息 + SEO + 版面选择 + 皮肤选择 + 显示 + 列表 + 高级(可折叠/展开)
- •公共组件 — 8 个
components/board/section-*.php 文件(basic, seo, layout-select, skin-select, display, list, advanced, js),可在创建/编辑页面复用
- •多语言输入组件 —
rzx_multilang_input() 函数,文本/编辑器模式,内联地球仪按钮
- •分类管理增强 — 树形结构(parent_id)、编辑弹窗(名称/字体颜色/描述/允许的组/展开/默认分类)、SortableJS 拖拽排序、从 DB 动态加载会员等级
- •扩展变量标签页 —
rzx_board_extra_vars 表,15 种输入类型(包含 text_multilang、textarea_multilang、textarea_editor),支持多语言,拖拽排序
- •权限设置标签页 — 访问权限(all/member/grade:*/admin_staff/admin)、模块管理员(公共用户搜索、头像、权限范围)、通知邮件说明
- •附加设置标签页 — 集成版块、文档(历史/推荐/举报)、评论(数量/深度/审核/推荐/举报)、WYSIWYG 编辑器(权限矩阵)、文件(下载组)、Feed(RSS 公开/版权)
- •皮肤系统 —
skin.json 格式、SkinConfigRenderer、"multilang": true 支持、皮肤信息卡片
- •版面系统 —
layout.json 格式,基本设置中以卡片形式选择
- •公共用户搜索 —
user-search.php 组件,加密/解密,头像,随处可复用
- •模块管理员 —
rzx_board_admins 表,帖子/评论/设置权限,通知订阅
- •高级设置扩展 — 将管理员排除在匿名之外、Data URL 限制、Unicode 滥用、帖子/评论保护(评论数/回复数/期限)、超级管理员保护、发件人邮箱地址
- •切换开关 UI — 所有是/否项目转换为切换开关(基本 + 附加设置)
- •翻译键 — 约 300 个键,13 种语言
Fixed
- •回收站 SQL 错误 —
LIMIT ? 绑定字符串 → 整数字面量
- •Summernote 未渲染 — 加载 jQuery/Summernote JS + 模态框显示后初始化
- •排序规则错误 — JOIN board_admins 时显式指定 COLLATE utf8mb4_unicode_ci
- •折叠/展开不工作 —
toggleSection 函数先在 <head> 中定义
Changed
- •独立标签页(列表/高级)→ 合并至基本设置标签页并带折叠/展开
- •皮肤选择 → 移至基本设置标签页;皮肤标签页仅显示设置
- •管理员邮箱 → 改为高级设置中的"发件人邮箱地址"
- •模块管理员 → 移至权限设置标签页
- •"在列表中显示分类" → 从分类设置中移除,委托给各皮肤设置
- •"在列表中显示分类" → 从分类设置中移除,委托给各皮肤设置
- •允许发帖的组 → 从
rzx_member_grades 表动态加载,不再硬编码
Added
- •多语言回退系统:
db_trans() 函数内置回退链(配置语言 → en → 默认语言 → source_locale → 任意翻译)
- •版块设置多语言按钮:在基本设置标签页的6个字段中添加多语言(地球)按钮
- •版块前端视图多语言回退:在
_init.php 中应用标题、描述、SEO、页头/页脚多语言
- •小部件多语言回退:改进
WidgetRenderer::t()、tBtn() 对空字符串的处理
- •新增PWA翻译键(13种语言:
admin.pwa.update_available、update、later)
Fixed
- •Features小部件空卡片问题:
?? 运算符将空字符串 "" 视为有效值 → 改用基于 !empty() 的回退
- •生产环境Mixed Content错误:
APP_URL http→https 已修复 + JS协议自动修正
Added
- •从 POS 服务记录中删除服务的功能(删除按钮 + API + 即时刷新 DOM)
- •为 13 种语言新增服务删除相关翻译键
Added
- •自助终端接待系统:服务确认 → 客户信息 → 创建预约 → 发放排队号
- •员工可用状态徽章:在自助终端选择员工时实时显示忙碌/可用
- •国际电话号码模块:在自助终端接待表单中应用 phone-input 组件
- •预约示例数据种子:
database/seed_reservations.php(POS/自助终端/在线 共10条)
- •拆分自助终端公共文件(
_styles.php、_bg.php、_scripts.php)
- •为13种语言新增11个自助终端翻译键
Changed
- •自助终端服务选择:基于员工技能的筛选(指定模式)
- •自助终端分类标签居中对齐
Fixed
- •生产环境管理员无法登录(密码哈希损坏——bash 的
$ 变量替换问题)
- •更新系统稳定化:扩展保留列表、健康检查、数据库版本同步
- •统一版本单一来源(
version.json → index.php,数据库自动同步)