From 18edbfbe7f62432a58278ff2ea56cce48d9cef19 Mon Sep 17 00:00:00 2001 From: sunlei Date: Sat, 25 Jul 2026 15:57:47 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E7=BB=9F=E4=B8=80=E6=B6=88=E6=81=AF?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E8=A1=A8=E5=8D=95=E4=B8=8E=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E6=A0=8F=E5=B8=83=E5=B1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- .../qqbot/account/components/AccountMessagePushModal.tsx | 2 +- .../qqbot/account/components/AccountMessagePushPanel.tsx | 1 - .../components/MessageSubscriptionModal.tsx | 2 +- .../src/views/qqbot/message-subscription/list.tsx | 1 - .../message-template/components/MessageTemplateModal.tsx | 2 +- .../src/views/qqbot/message-template/list.tsx | 1 - .../account/components/AccountMessagePushModal.spec.tsx | 8 ++++++++ .../account/components/AccountMessagePushPanel.spec.tsx | 1 + .../components/MessageSubscriptionModal.spec.tsx | 8 ++++++++ test/views/qqbot/message-subscription/list.spec.tsx | 1 + .../components/MessageTemplateModal.spec.tsx | 8 ++++++++ test/views/qqbot/message-template/list.spec.tsx | 1 + 13 files changed, 31 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index f9f372b..9973655 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ pnpm run build:antdv-next - 系统管理 / 网络管理使用 TSX、KtTable 与统一 Vben 表单维护 API 持久化的 TCP/UDP 单端口转发期望状态,并通过独立页签管理腾讯云云解析 DNS 的 A/AAAA 自动更新绑定。页面展示 Agent、路由同步、UDP Keeper、公网端点租约和 DDNS 同步状态,支持异步 CRUD、重试、Keeper 启停、立即 STUN 刷新及端点历史;A 只使用合格 UDP Keeper 的公网 IPv4,AAAA 只使用 Agent 全局 IPv6,DNS 值不包含端口。首屏读取一次 HTTP 快照,后续只按 API SSE 的资源来源刷新当前活动页签;心跳和其他页签事件不刷新,不使用定时轮询。`Page autoContentHeight` 中的 Tabs 与 KtTable 必须由满高纵向 flex 外壳承接,活动面板保持 `flex-1 min-h-0`,否则 KtTable 的百分比高度链会塌陷。Admin 不接触路由器、MQTT 或腾讯云凭据;当前已验证切片只执行 UDP 路由器写入,TCP 可保存 CRUD 期望但 Agent 会显示设备协议门禁失败,STUN 操作保持可见且禁用。 - Vue i18n 文案中的普通 `@` 必须写成字面量插值 `{'@'}`,否则生产消息编译器会把它识别为 linked message 语法。网络管理语言包由 `network-locale.spec.ts` 逐条通过实际 i18n runtime 校验,不能只依赖 JSON 解析或组件测试里的 `$t` mock。 - QQBot / 账号连接页拆分 OneBot 连接、QQ 登录、NapCat 运行和运行说明列;更新登录通过 SSE 展示 quick / password / captcha / new-device / qrcode 每步中文进度,密码登录触发 QQ 安全验证时在弹窗内完成腾讯验证码并回交 API,新设备验证二维码和腾讯验证码分开展示;行操作“运行态”打开只读抽屉,展示 NapCat runtime/protocol/session behavior profile、风险模式和登录事件证据。 -- QQBot / 消息订阅与消息模板是两个平级菜单;新建订阅和新建模板均不默认选择消息源。订阅选择来源后才按该来源的 `subscriptionFields` 动态生成字段并加载候选项,不把通用订阅表单绑定到 STUN;模板选择来源后才加载变量详情,输入 `$` 后通过 Mentions 候选精确插入 `${{变量}}`。账号配置第四页签用于为当前 QQBot 选择订阅、模板以及群聊/私聊目标,不提供跨账号选择,两个目标选择框固定填满横向表单宽度;上述消息推送表单的必填、格式和长度校验提示统一使用中文。三个入口只在首次进入、显式刷新或成功写操作后更新列表,不使用后台轮询;菜单、按钮与账号页签分别受 `QqBot:MessageSubscription:*`、`QqBot:MessageTemplate:*` 和 `QqBot:Account:MessagePush:*` 权限控制。 +- QQBot / 消息订阅与消息模板是两个平级菜单;新建订阅和新建模板均不默认选择消息源。订阅选择来源后才按该来源的 `subscriptionFields` 动态生成字段并加载候选项,不把通用订阅表单绑定到 STUN;模板选择来源后才加载变量详情,输入 `$` 后通过 Mentions 候选精确插入 `${{变量}}`。账号配置第四页签用于为当前 QQBot 选择订阅、模板以及群聊/私聊目标,不提供跨账号选择,两个目标选择框固定填满横向表单宽度;上述消息推送表单的标签使用统一单行宽度,必填、格式和长度校验提示统一使用中文。三个入口只在首次进入、显式刷新或成功写操作后更新列表,不使用后台轮询;表格操作栏沿用 KtTable 全局“一个内联操作,其余收进更多操作”规则,菜单、按钮与账号页签分别受 `QqBot:MessageSubscription:*`、`QqBot:MessageTemplate:*` 和 `QqBot:Account:MessagePush:*` 权限控制。 源码目录禁止同级存放单元测试或 `__tests__`;全部单元测试统一放在根目录单数 `test/`,应用测试直接使用 `test/api`、`test/components`、`test/router`、`test/store`、`test/views`,共享包与内部工具分别使用 `test/packages`、`test/internal`,结构门禁位于 `test/governance`。 diff --git a/apps/web-antdv-next/src/views/qqbot/account/components/AccountMessagePushModal.tsx b/apps/web-antdv-next/src/views/qqbot/account/components/AccountMessagePushModal.tsx index 9597fac..b19e416 100644 --- a/apps/web-antdv-next/src/views/qqbot/account/components/AccountMessagePushModal.tsx +++ b/apps/web-antdv-next/src/views/qqbot/account/components/AccountMessagePushModal.tsx @@ -72,7 +72,7 @@ export default defineComponent({ let sessionSelfId = ''; const [BindingForm, formApi] = useVbenForm({ commonConfig: { - labelClass: 'w-24', + labelClass: 'w-32 whitespace-nowrap', }, async handleValuesChange(values, fieldsChanged) { if (!fieldsChanged.includes('subscriptionId')) return; diff --git a/apps/web-antdv-next/src/views/qqbot/account/components/AccountMessagePushPanel.tsx b/apps/web-antdv-next/src/views/qqbot/account/components/AccountMessagePushPanel.tsx index c78d472..fea3798 100644 --- a/apps/web-antdv-next/src/views/qqbot/account/components/AccountMessagePushPanel.tsx +++ b/apps/web-antdv-next/src/views/qqbot/account/components/AccountMessagePushPanel.tsx @@ -189,7 +189,6 @@ export default defineComponent({ columns, immediate: false, rowActions, - rowActionVisibleCount: 3, rowKey: 'id', showDefaultButtons: false, showFooter: false, diff --git a/apps/web-antdv-next/src/views/qqbot/message-subscription/components/MessageSubscriptionModal.tsx b/apps/web-antdv-next/src/views/qqbot/message-subscription/components/MessageSubscriptionModal.tsx index 4212a82..cd97b46 100644 --- a/apps/web-antdv-next/src/views/qqbot/message-subscription/components/MessageSubscriptionModal.tsx +++ b/apps/web-antdv-next/src/views/qqbot/message-subscription/components/MessageSubscriptionModal.tsx @@ -95,7 +95,7 @@ export default defineComponent({ const [SubscriptionForm, formApi] = useVbenForm({ commonConfig: { - labelClass: 'w-24', + labelClass: 'w-32 whitespace-nowrap', }, handleValuesChange, layout: 'horizontal', diff --git a/apps/web-antdv-next/src/views/qqbot/message-subscription/list.tsx b/apps/web-antdv-next/src/views/qqbot/message-subscription/list.tsx index df8d57a..891137e 100644 --- a/apps/web-antdv-next/src/views/qqbot/message-subscription/list.tsx +++ b/apps/web-antdv-next/src/views/qqbot/message-subscription/list.tsx @@ -158,7 +158,6 @@ export default defineComponent({ }, immediate: false, rowActions, - rowActionVisibleCount: 3, rowKey: 'id', tableTitle: '消息订阅', }); diff --git a/apps/web-antdv-next/src/views/qqbot/message-template/components/MessageTemplateModal.tsx b/apps/web-antdv-next/src/views/qqbot/message-template/components/MessageTemplateModal.tsx index 3e66643..ac00abf 100644 --- a/apps/web-antdv-next/src/views/qqbot/message-template/components/MessageTemplateModal.tsx +++ b/apps/web-antdv-next/src/views/qqbot/message-template/components/MessageTemplateModal.tsx @@ -71,7 +71,7 @@ export default defineComponent({ let sessionRevision = 0; const [TemplateForm, formApi] = useVbenForm({ commonConfig: { - labelClass: 'w-24', + labelClass: 'w-32 whitespace-nowrap', }, async handleValuesChange(values, fieldsChanged) { if (fieldsChanged.includes('content')) clearPreview(); diff --git a/apps/web-antdv-next/src/views/qqbot/message-template/list.tsx b/apps/web-antdv-next/src/views/qqbot/message-template/list.tsx index f237882..19d653e 100644 --- a/apps/web-antdv-next/src/views/qqbot/message-template/list.tsx +++ b/apps/web-antdv-next/src/views/qqbot/message-template/list.tsx @@ -142,7 +142,6 @@ export default defineComponent({ }, immediate: false, rowActions, - rowActionVisibleCount: 3, rowKey: 'id', tableTitle: '消息模板', }); diff --git a/test/views/qqbot/account/components/AccountMessagePushModal.spec.tsx b/test/views/qqbot/account/components/AccountMessagePushModal.spec.tsx index cd9b56a..13867ef 100644 --- a/test/views/qqbot/account/components/AccountMessagePushModal.spec.tsx +++ b/test/views/qqbot/account/components/AccountMessagePushModal.spec.tsx @@ -371,6 +371,14 @@ describe('account message-push modal', () => { ]); }); + it('为消息推送表单标签预留统一单行宽度', () => { + mountModal(); + + expect(mocks.formOptions.commonConfig.labelClass).toBe( + 'w-32 whitespace-nowrap', + ); + }); + it('uses Chinese validation messages for subscription, template, and targets', () => { mountModal(); const fieldRule = (fieldName: string) => diff --git a/test/views/qqbot/account/components/AccountMessagePushPanel.spec.tsx b/test/views/qqbot/account/components/AccountMessagePushPanel.spec.tsx index 47011d3..21110e0 100644 --- a/test/views/qqbot/account/components/AccountMessagePushPanel.spec.tsx +++ b/test/views/qqbot/account/components/AccountMessagePushPanel.spec.tsx @@ -286,6 +286,7 @@ describe('account message-push panel', () => { showPagination: false, showTableSetting: false, }); + expect(mocks.tableOptions).not.toHaveProperty('rowActionVisibleCount'); expect(mocks.api.getBindings).toHaveBeenCalledOnce(); expect(mocks.api.getBindings).toHaveBeenCalledWith('10000000000000001'); expect(mocks.api.getSubscriptions).toHaveBeenCalledWith({ diff --git a/test/views/qqbot/message-subscription/components/MessageSubscriptionModal.spec.tsx b/test/views/qqbot/message-subscription/components/MessageSubscriptionModal.spec.tsx index ae1d359..39191a4 100644 --- a/test/views/qqbot/message-subscription/components/MessageSubscriptionModal.spec.tsx +++ b/test/views/qqbot/message-subscription/components/MessageSubscriptionModal.spec.tsx @@ -306,6 +306,14 @@ describe('message subscription modal', () => { expect(mocks.getOptions).not.toHaveBeenCalled(); }); + it('为动态长标签预留单行宽度', () => { + mountModal(); + + expect(mocks.formOptions.commonConfig.labelClass).toBe( + 'w-32 whitespace-nowrap', + ); + }); + it('订阅固定字段和消息源动态必填字段均使用中文校验文案', async () => { mountModal(); const fieldRule = (fieldName: string) => diff --git a/test/views/qqbot/message-subscription/list.spec.tsx b/test/views/qqbot/message-subscription/list.spec.tsx index 4a4bf09..ab1aade 100644 --- a/test/views/qqbot/message-subscription/list.spec.tsx +++ b/test/views/qqbot/message-subscription/list.spec.tsx @@ -211,6 +211,7 @@ describe('message subscription list', () => { ); expect(mocks.tableOptions.immediate).toBe(false); expect(mocks.tableOptions.rowKey).toBe('id'); + expect(mocks.tableOptions).not.toHaveProperty('rowActionVisibleCount'); expect(mocks.registerTable).toHaveBeenCalledOnce(); }); diff --git a/test/views/qqbot/message-template/components/MessageTemplateModal.spec.tsx b/test/views/qqbot/message-template/components/MessageTemplateModal.spec.tsx index 3d4afa8..084de99 100644 --- a/test/views/qqbot/message-template/components/MessageTemplateModal.spec.tsx +++ b/test/views/qqbot/message-template/components/MessageTemplateModal.spec.tsx @@ -198,6 +198,14 @@ describe('message template modal', () => { }); }); + it('为消息表单标签预留统一单行宽度', () => { + mountModal(); + + expect(mocks.formOptions.commonConfig.labelClass).toBe( + 'w-32 whitespace-nowrap', + ); + }); + it('registers the exact schema and actually renders the local Mentions form field', () => { const wrapper = mountModal(); const fields = mocks.formOptions.schema.map( diff --git a/test/views/qqbot/message-template/list.spec.tsx b/test/views/qqbot/message-template/list.spec.tsx index 77579b4..d07c759 100644 --- a/test/views/qqbot/message-template/list.spec.tsx +++ b/test/views/qqbot/message-template/list.spec.tsx @@ -220,6 +220,7 @@ describe('message template list', () => { expect(wrapper.find('[data-testid="template-table"]').exists()).toBe(true); expect(mocks.tableOptions.immediate).toBe(false); expect(mocks.tableOptions.rowKey).toBe('id'); + expect(mocks.tableOptions).not.toHaveProperty('rowActionVisibleCount'); expect(mocks.registerTable).toHaveBeenCalledOnce(); expect(mocks.api.getList).toHaveBeenCalledOnce(); });