@microi.net/cli 5.5.2 → 5.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,7 +9,21 @@ description: Microi AI 引擎、MiniMax 图片/音乐/视频生成与预览、
9
9
 
10
10
  平台媒体生成的受控 HTTP 入口包括 `/api/Ai/GenerateMiniMaxImage`、`/api/Ai/GenerateMiniMaxMusic`、`/api/Ai/CreateMiniMaxVideo`、`/api/Ai/GetMiniMaxVideoTask`、`/api/Ai/GetMiniMaxVideoFile`、`/api/Ai/PersistMiniMaxVideoFile`;AI 工作流统一调用 Managed 接口引擎 `/apiengine/platform-ai-workflow`,通过 `Action` 选择概览、节点详情、生成、列表、读取、保存或删除。调用方只提交业务参数和模型选择,供应商密钥、租户配额、任务归属和文件读取权限由服务端判定。生成结果必须先进入当前租户 HDFS 或受控临时句柄,浏览器不接触供应商密钥、图片 Base64、音频十六进制或原始视频任务 Id。`PersistMiniMaxVideoFile` 只能转存当前登录用户所属且已完成的任务,禁止作为任意 URL 搬运器。
11
11
 
12
- ## 能力
12
+ ## 能力
13
+
14
+ ### 媒体模型目录与中转(2026-09)
15
+
16
+ - 媒体选择以当前租户 `mic_ai.Id` 和实际媒体 `Model` 为准,图片、音乐、视频及配音请求携带 `AiModelId`。显式记录不可用时不得静默切换其它账号、主租户密钥或聊天模型。
17
+ - `MediaProtocol` 与 `MediaModels` 由 AI助手应用包交付。目录项为 `{ Id, Name, Capability, Protocol }`,能力支持 `image/music/video/speech`;协议与模型名称分离,未知协议明确不可选。新增供应商协议仍须真实后端适配器和契约测试,不能只改模型名称。
18
+ - `/api/Ai/GetMediaModels` 返回当前登录租户的可选目录,官方中转 `/v1/microi/media_models` 只返回安全投影,不含 Key、Endpoint 或供应商记录 Id。中转接收端按本机 `IsRelayModel=1` 的供应商目录选实际模型,不接受外部租户记录 Id。
19
+ - 图片生成继续使用持久任务;等待中转结果与执行供应商请求的 Worker 必须分开调度并预留执行容量,避免同节点循环等待。中断后查询原 TaskId,不能把 HTTP 524、Uncertain 或 Token Plan 使用状态猜测为关键词违规或扣费。
20
+ - 必须区分 MiniMax 开放平台 `image-01` 的 `subject_reference` 人物参考协议、MiniMax Code 的 `connector__matrix__generate_image` / `input_urls` 图像编辑工具,以及 OpenAI Images edits 协议。某个接口编辑失败,不能推断整个 MiniMax Code 不支持编辑;聊天界面选择 M3 也不证明实际图像工具的底层模型就是 M3。验收须看输出原图。
21
+ - MiniMax Code 图像编辑使用独立 `mic_ai` 行:`MediaProtocol=minimax-connector-image`,逻辑模型 `minimax-code-image`,Endpoint 为官方 `https://agent.minimaxi.com` 或 `https://agent.minimax.io`。工具未开放底层 model 字段,不能伪造。只接受服务器发现的固定图像/上传/文件 URL 工具,不增加任意工具执行入口。
22
+ - Connector 使用独立 OAuth 授权,不能复用 Token Plan API Key,也不能复制桌面 `electron` 登录态的 refresh_token。管理员通过连接账户或导入独立授权绑定引擎;凭据按租户和记录加密,续期使用共享锁与 CAS,目录、日志和响应不含 Token。应用包只扩展协议选项和凭据字段容量,不复制账号。
23
+ - 原图先通过当前租户私有 HDFS 校验,再取得供应商临时上传凭证。Multipart 文件分段须先写 Content-Disposition 再写 Content-Type,避免供应商 OSS 返回 MalformedPOSTRequest。生成结果先保存 node_id 回执,再调用 get_asset_url 并转存 HDFS;已有节点时只恢复下载,不重新生成。临时 URL 不作为永久结果,也不携带 OAuth 头访问文件域名。失败状态提供 CanRecoverResult 时,可通过 RecoverMiniMaxImageTask 或中转任务 recover 入口显式恢复原 TaskId;恢复 Worker 必须再次检查节点,节点失效时禁止重新生图。4K 图片下载允许最大 64 MiB,并继续执行租户存储限额。每次工具调用前重新取得当前连接授权;明确 401 才可刷新后重试一次,超时不重发生成。
24
+ - 升级要求包括 AI助手 v7.6.9、平台后端 v8.1.11 或更高版本、平台前端和中转节点程序;应用包只升级字段/受管资源,不复制租户密钥或替换运行二进制。媒体存储必须保留真实用户的上传开关、载荷和配额检查,仅可信后端能授权固定的私有参考图与公有生成结果目录,不能放宽普通用户上传策略。
25
+ - MiniMax 参考图以已校验原始字节的 data URI 发送,仍须先执行租户私有 HDFS 上传与配额检查;参考图请求关闭 prompt_optimizer。人物主体参考重绘不能等同局部精确编辑,验收必须同时检查任务结果和图片实际内容。
26
+ - 图片工具须按操作匹配模型能力:MiniMax 人物参考最多一张,不得用于消除、扩图、线稿还原、多图合成等结构编辑;前端过滤与后端校验必须一致。兼容媒体协议的型号由当前租户 mic_ai 目录验证,参数规范层不得再次把音乐、视频、配音固定为单一历史型号;未实现的供应商协议仍明确标为不可用。
13
27
 
14
28
  平台 AI 包含聊天/流式聊天、模型代理、模型路由、订阅配额、NL2SQL、NL2V8、数据库 Schema 关键词检索、可选向量融合和 V8 Skill 文档检索。AI 输出是建议,不是授权;执行 SQL、V8 或 MCP 写入前仍走平台权限与确认。
15
29
 
@@ -54,12 +68,18 @@ AI 业务统一实现在 `Microi.Server/Microi.AI`。`Microi.Server/Microi.net.A
54
68
  - 9 张 `mic_sub_*` 订阅表与 `mci_ai_token_account`、`mci_ai_token_log` 由官方 `app.microi.ai-engine` 应用升级提供,必须同时声明 DDL、PhysicalColumns、DiyTables、DiyFields;`PromptPreview` 属于日志表正式字段。`mci_ai_token_recharge` 当前不在该运行时实体闭包内,禁止根据线上残留自行扩包。运行时发现缺失时失败关闭,禁止在请求路径自动建表、加列或修改业务 Schema。
55
69
  - `Sys_User.AiApiKey` 归官方 `app.microi.sys_user`,由系统账号包同时维护建表 DDL、PhysicalColumns 和隐藏只读 DiyField;AI助手包不得重复声明 `Sys_User`。缺列错误必须提示升级系统账号应用,不能误导用户升级 AI助手。
56
70
 
57
- ## 模型与密钥
58
-
71
+ ## 模型与密钥
72
+
73
+ 存量模型配置的兼容验收组合包括 `GenerateMiniMaxImage + image-01`、`GenerateMiniMaxMusic + music-2.6`。这些组合只适用于服务端已配置且供应商账号仍有权限的旧路由;新路由仍遵循下列实时能力选择规则。验收必须同时检查实际返回的模型标识、媒体类型与 HDFS 读取,不能仅凭兼容接口名称判断底层模型。
74
+
59
75
  - 模型 Provider、Endpoint、ApiKey、AuthPrefix 和上游模型 Id 只保存在服务端受保护配置。
60
76
  - 普通用户使用平台签发的受限 API Key/订阅身份,不能枚举或读取上游密钥。
61
- - MiniMax 对话媒体必须区分意图模型与生成模型:`MiniMax-M3` 只负责识别普通对话、绘图或音乐意图;生成式图片固定走 `GenerateMiniMaxImage + image-01`,纯音乐新路由优先走 `GenerateMiniMaxMusic + music-3.0`,并继续兼容已有供应商配置的 `GenerateMiniMaxMusic + music-2.6`。托管音乐只有明确返回 410 退役终态时才允许切到官方开源 `MiniMax-Music3`,不得把超时、5xx、额度不足等不确定状态当作回退条件;目标账号支持的实际模型必须在线校准。不得让文本模型用说明文字冒充媒体生成,也不得声称图片/音乐是 `MiniMax-M3` 原生输出。
62
- - `GenerateMiniMaxImage` 可接收最多 4 张 JPEG/PNG/WebP 主体参考图;参考图先写当前租户私有 HDFS,只将短时签名 URL 交给供应商,浏览器与响应均不得得到签名地址。图生图、重绘、扩图、消除、去水印、证件照、多图合成、上色、修复等当前属于参考图提示词重绘,不得冒充像素级蒙版工具。黑白、纯色背景抠除、缩放、裁剪、旋转、翻转、格式转换和拼图使用 `platform-ai-runtime/ProcessImage + V8.Image` 精确处理。
77
+ - MiniMax 对话媒体必须区分意图模型与生成工具:`MiniMax-M3` 是对话与工具编排模型;图片入口兼容名仍为 `GenerateMiniMaxImage`,实际模型由 `mic_ai.MediaProtocol / MediaModels` 与当前媒体选择决定,不能固定为 `image-01`。MiniMax Code 的 `generate_image + input_urls` 使用 `minimax-connector-image` 协议和逻辑路由 `minimax-code-image`;供应商未公开底层图像模型名,不得把界面选择的 M3 当成图片生成底模。纯音乐优先使用所配置且可用的 `music-3.0`,兼容 `music-2.6`;托管音乐只有明确返回 410 退役终态时才允许切到官方开源 `MiniMax-Music3`,不得把超时、5xx、额度不足当作回退条件。目标账号能力必须实时校准,不得用文本说明冒充生成产物。
78
+ - `GenerateMiniMaxImage` 使用稳定 `RequestId` 持久入队,返回 `Code=2 + Data.TaskId` 后只通过 `GET /api/Ai/GetMiniMaxImageTask?taskId=...` 查询。只有 `Code=1 + Images` 才表示原图已写入 HDFS;浏览器超时、刷新或停止等待不能取消后台生成,也不能换请求号自动重发。图片任务复用 `mci_background_task` 的租户/用户隔离、数据库唯一键、分布式租约和 fencing,原生 Worker Key 为 `__microi_native_ai_image__`,不可由租户 V8 覆盖。请求参数只保存在服务端私有任务列,状态接口不返回提示词或参考图。
79
+ - `GenerateMiniMaxImage` 可接收最多 4 张 JPEG/PNG/WebP 参考图;先写当前租户私有 HDFS,由可信适配器上传原图或提供短时签名 URL,浏览器与响应均不得得到供应商上传票据和签名地址。`image-01` 的 `subject_reference` 是人物参考重绘,不能据此声称所有 MiniMax 工具都不支持消除。消除、换背景等操作须选择目录中声明对应编辑能力的协议:MiniMax Code 使用 `input_urls`,OpenAI Images 兼容模型使用 edits;实际效果必须逐张检查,生成式身份保持、发丝边缘与像素不变不能仅凭接口成功判为通过。黑白、纯色背景抠除、缩放、裁剪、旋转、翻转、格式转换和拼图使用 `platform-ai-runtime/ProcessImage + V8.Image` 精确处理。
80
+ - MiniMax Code 媒体连接使用管理员独立 OAuth 授权,不读取或复用桌面客户端凭据。令牌在可信后端按租户及引擎记录绑定加密保存,刷新使用共享锁与旧值比较;明确 401 可刷新后重试一次,不确定生成请求不得重发。生成结果节点须先保存到共享存储;下载或 HDFS 失败且存在节点时,通过同一 TaskId 的 `RecoverMiniMaxImageTask` 或 `/v1/microi/image_tasks/{taskId}/recover` 恢复已有图片,不再次生成。目录只公开能力元数据。`MediaModels` 可扩展同协议模型;新的供应商协议仍需适配器、商城字段及真实中转验收,不能只填名称就宣称已接通。
81
+ - 吾码节点之间的图片中转使用 `POST /v1/microi/image_tasks` 与 `GET /v1/microi/image_tasks/{taskId}`,服务端平台 API Key 鉴权,提交必须有稳定 `Idempotency-Key`。查询不占用生成额度;接收节点只能使用已启用且公布的供应商媒体模型,禁止自调用中转环路。MiniMax 官方适配器调用同步 `/v1/image_generation`,其它供应商由对应协议适配器处理。消费者、官方中转节点和前端必须更新到同一持久任务协议;应用包更新不能代替平台二进制与前端更新。
82
+ - HTTP 524、连接取消或空响应仅说明传输状态不确定,不能断言提示词违规、Token Plan 不可用或已扣费。明确供应商拒绝保留 `UpstreamHttpStatus`、`UpstreamCode` 和错误消息;`Failed/Uncertain` 不能在回读时合并成“仍在生成”。MiniMax 同步接口没有本任务可用的结果查询号时,不得伪造回查成功或盲目重发;相同 RequestId 参数冲突必须拒绝。
63
83
  - 图片与音乐都使用稳定 `RequestId` 和共享幂等;相同参数回放、参数冲突拒绝,上游结果不确定时禁止换 Id 盲重试。音乐当前仅向平台管理员开放且固定无人声;托管结果为 MP3,开源回退为 32kHz 立体声 WAV、10~60 秒。成功内容由服务端校验后直接写入当前租户公有 HDFS。
64
84
  - 聊天附件的公有媒体 URL 优先按当前运行租户 `FileServer + FilePath` 解析,禁止写死域名或沿用其它租户的前缀。图片使用 Element Plus `el-image` 的 `preview-src-list` 原页放大,不能套 `target="_blank"`;音乐使用 `<audio controls preload="metadata">` 在线播放。媒体是结构化附件,文本才走安全 Markdown 渲染,禁止拼接任意 HTML 绕过 URL/类型校验。
65
85
  - MiniMax 自 2026-08-20 起不再向新用户开放付费 Music/Lyrics API,并停止旧免费 Music 模型。既有 `music-3.0` 账号仍可优先直连;官方开源 `MiniMax-Music3` Space 可作为明确 410 后的回退,但公开 ZeroGPU 配额不是生产 SLA。需要专属额度时只在既有服务端 `mic_ai` 模型路由中保存官方 Space Endpoint 与受保护 Hugging Face Token,不新增 API `AppSettings`、环境变量或前端密钥。Provider/中转账号未开通、额度不足或上游停用时必须返回可诊断失败,不生成占位音频、不伪报成功。图片、音乐和视频的真实可用性都需用目标租户登录态调用及媒体 GET/播放回读证明,源码存在或接口 HTTP 200 不能替代生成成功。
@@ -68,7 +88,7 @@ AI 业务统一实现在 `Microi.Server/Microi.AI`。`Microi.Server/Microi.net.A
68
88
  - 视频创建必须要求调用方稳定 `RequestId`,先在当前租户共享 Redis 以 `OsClient + 用户 + RequestId` 原子 `NX` 占位;Redis 不可用时失败关闭。相同 RequestId/参数回放返回原任务,不同参数冲突拒绝;上游 POST 超时或结果不确定时禁止自动换 RequestId 重试。查询不再次扣生成额度。
69
89
  - 原始 MiniMax `task_id`/`file_id` 不下发。服务端返回由供应商 Key 签名、绑定当前用户和用途的短句柄;查询/下载验签后才还原。Key 轮换会使旧句柄失效,应先完成或重新登记在途任务。
70
90
  - 当前官方模型边界必须实时校准:`MiniMax-Hailuo-2.3` 支持文生/图生,`MiniMax-Hailuo-2.3-Fast` 仅图生且必须有首帧,首尾帧使用 `MiniMax-Hailuo-02`。Hailuo 2.3 的画质优先上限与平台默认值是 6 秒 / 1080P,时长优先上限是 10 秒 / 768P,两者不能同时最大;API 不提供 fps 参数,必须用媒体探针记录真实帧率,禁止把插帧/画布规格冒充模型原生能力。当前 Token Plan 使用统一用量条、5 小时固定窗口和周窗口,控制台是剩余额度事实源,不再把固定“每天 N 条”写成官方配额。需要自动生成时,在 `Microi.AI` 增加只读、脱敏、管理员限定的 `https://www.minimaxi.com/v1/token_plan/remains` 安全原子能力;不得由浏览器或可编辑 V8 读取 Provider Key,也不得把客户端今日计数当成供应商权威额度。
71
- - MiniMax 视频任务返回静音画面。需要人物对白时,男/女语音必须通过 `Microi.AI` 的 `GenerateMiniMaxSpeech` 受保护原子能力生成:固定 `speech-2.8-hd`、固定男女系统音色、稳定 RequestId、共享 Redis 幂等,并直接转存租户 HDFS;再由可靠 Worker 按时间轴混音、加准确字幕。无法证明口型同步时使用画外音或反打镜头。背景音乐使用 `GenerateMiniMaxMusic` 并在人声下压低。运行节点尚未部署 Speech 能力、额度未核实或母版混音/探针证据缺失时失败关闭,禁止静音、仅配乐、浏览器直连供应商或伪称模型原生带声。
91
+ - 当前 Hailuo 2.3 视频适配器返回静音画面;其它视频协议是否含声以实际模型能力和音轨探针为准。需要人物对白时,男/女语音通过 `Microi.AI` 的 `GenerateMiniMaxSpeech` 受保护原子能力生成:由当前租户 mic_ai 选择 speech 模型与受支持音色,`speech-2.8-hd` 是现有默认值;保持稳定 RequestId、共享 Redis 幂等,并直接转存租户 HDFS;再由可靠 Worker 按时间轴混音、加准确字幕。无法证明口型同步时使用画外音或反打镜头。背景音乐使用 `GenerateMiniMaxMusic` 并在人声下压低。运行节点尚未部署 Speech 能力、额度未核实或母版混音/探针证据缺失时失败关闭,禁止静音、仅配乐、浏览器直连供应商或伪称模型原生带声。
72
92
  - 管理端【AI视频】应按 `TaskHandle` 轮询任务,成功后优先转存 HDFS,并用 `<video controls preload="metadata">` 原页预览和明确下载按钮消费同一个已校验地址。临时 URL、生成完成、HDFS 转存、媒体可播放和外部平台发布是五个不同事实,必须分别验收。
73
93
  - 使用 Microi.AI 中转站时,租户侧 AI Bootstrap 通过官方 `official_ai_relay_models` 发现可用运行模型。该接口是跨租户只读公共契约,必须保持启用、允许匿名 HTTP 调用,并且只返回模型标识、展示名等公开白名单字段,绝不能返回中转密钥或上游 Endpoint。消费者不得把 `NoAuth` 静默伪装为“没有配置模型”;应返回可诊断错误,同时前端显示明确空态。
74
94
  - PC、UniApp 和其它客户端通过 `POST /apiengine/{key}` 发送的 JSON Body 必须完整进入 `V8.Param`;兼容入口 `/api/ApiEngine/Run` 的 JSON Body 还必须包含 `ApiEngineKey`。API 层只负责请求绑定和清除客户端伪造的可信字段,模型选择、权限策略与对话逻辑仍全部位于 `Microi.AI` 或受控 AI 接口引擎中。
@@ -82,11 +102,24 @@ AI 业务统一实现在 `Microi.Server/Microi.AI`。`Microi.Server/Microi.net.A
82
102
  - 官方 AI助手应用归 `app.microi.ai-engine`。v6.3.6 的接口引擎必须严格只有 Managed `mci_ai_data_assistant`、Managed `platform-ai-account`、Managed `platform-ai-runtime` 和 CreateIfMissing `platform-ai-custom-hook` 四项,并声明 `V8.Method.ManageAiPlatform`、`V8.Method.RequireManagedProtocolContext` 与所需 `V8.AI` 能力;后端缺少任一能力时安装预检失败关闭。
83
103
  - `ai_app_list`、`ai_app_detail`、`ai_app_get_file`、`ai_app_save_file`、`ai_app_create`、`ai_app_build`、`ai_app_preview`、`ai_app_download_source_zip`、`ai_app_download_build_zip`、`ai_app_moveobject_probe`、`ai_app_moveobject_exec_probe`、`ai_app_publish_store` 这 12 个 `ai_app_*` 归 `app.microi.store` 维护。AI助手包移除它们的资源选择和所有权声明,但不会删除目标租户既有运行时接口记录;既有记录继续由应用商城包升级。
84
104
  - v6.3.6 还必须保持 AI助手包的 DDL、PhysicalColumns、DiyTables、DiyFields、DataSets 全层不再包含重复的 `mci_ai_app_version`、`mci_ai_app_file`、`sys_microistore`,这些表交回 Store/SaaS 既有平台包维护;当前仅 AI助手包拥有的 `app_mic_aiapp`、`mci_ai_app` 继续保留。
85
- - 普通角色必须匹配启用的 `mci_ai_role_policy`。只有后端可信的 `V8.CurrentUser.Level >= 9999` 可以在新安装租户缺少角色策略时获得安全兜底:从目标租户动态读取已启用业务域和模型,范围为 `All`,仍保持 `AllowRawSql=false`、敏感字段默认关闭。不得相信客户端提交的 Level、角色名或账号名。
86
- - 当租户要求“所有角色均可使用 AI 助手”时,必须为 `sys_role` 中每个目标角色建立显式启用策略;受限角色使用 `Self`/`Department` 与最小业务域,管理角色才可使用经确认的 `All`。禁止把“人人可打开助手”实现成普通角色默认全库可读。
87
- - `Sys_Config.DisableAiAssistant` 是负向开关:缺失、空值或 `0/false` 都显示 AI 助手,只有显式 `1/true` 才关闭图标。商城升级应复用旧 `IsShowAiAssistant` 的字段元数据 Id 就地改名;兼容读取可以保留旧物理列,但旧字段元数据必须在 PC 与移动端隐藏,禁止同时暴露正向、负向两个开关。关闭该开关前后都要做策略覆盖验收:回读 `sys_role` 与 `mci_ai_role_policy`,断言每个目标角色都有唯一启用策略,`AllowedDomains`、`AllowedModels` 均非空且模型仍处于启用状态;再至少用超级管理员、普通员工和客户身份分别调用 `Bootstrap`,确认 `Enabled=true` 且返回范围符合角色。仅看到入口图标不算可用。
88
- - 角色策略存在但 `AllowedModels` 为空时,客户端最终仍会得到无可用模型;不得把它误判为前端角色拦截。应补齐当前租户启用模型白名单并回读,而不是删除 `mci_ai_role_policy` 校验或在客户端强制把 `Enabled` 改成 `true`。
89
- - 商城包不能携带发布租户的角色 Id、模型 Id 或密钥;应携带业务域定义和接口引擎,由安装后的目标租户动态发现自己的启用模型。发布后回读 `sys_microistore.AppVersion/AppPakcet`,并真实执行 `Bootstrap` 验证超级管理员可用、模型非空、快捷问题存在。
105
+ - 普通角色读取业务数据必须匹配启用的 `mci_ai_role_policy`,这不是常规对话的前置条件。只有后端可信的 `V8.CurrentUser.Level >= 9999` 可以在新安装租户缺少角色策略时获得数据分析安全兜底:从目标租户动态读取已启用业务域和模型,范围为 `All`,仍保持 `AllowRawSql=false`、敏感字段默认关闭。不得相信客户端提交的 Level、角色名或账号名。
106
+ - 所有已登录账号默认可使用 AI 常规对话,包括未分配任何角色、未申请业务身份、没有数据域、策略禁用或原模型已失效的账号。官方 AI助手 v7.7.1 在 `mic_ai` 的“基础配置”提供 `AllowAllRolesChat`(所有角色可常规对话),默认 `1`;存量缺失/null/空值兼容开启,显式 `0/false/'0'/'false'` 关闭该模型的公共对话使用权,启用值兼容 `1/true/'1'/'true'`。此开关不授予业务数据、SQL、菜单或管理权限,也不绕过登录、供应商额度和模型启用状态。
107
+ - 历史“所有角色使用助手都必须逐个建策略”的经验只适用于授予这些角色业务分析权限,不再适用于打开助手或常规对话。需要分析数据的目标角色仍应有显式策略;受限角色使用 `Self`/`Department` 与最小业务域,管理角色才可使用经确认的 `All`。禁止把“人人可打开助手”实现成普通角色默认全库可读。
108
+ - `Sys_Config.DisableAiAssistant` 是负向开关:缺失、空值或 `0/false` 都显示 AI 助手,只有显式 `1/true` 才关闭图标。历史包曾复用旧 `IsShowAiAssistant` 的字段元数据 Id 就地改名;因此清理旧开关必须按当前表名和字段名回读定位,不能只按历史 Id 删除,避免误删已复用该 Id 的新开关。官方母版必须通过标准 MCP 删除旧字段元数据,不能仅隐藏;新版包的 DiyFields、PhysicalColumns、DDL 及生成器均不得重新创建旧开关。平台删除字段可保留存量物理列兼容,但新前端只读取 DisableAiAssistant,不得重建正向开关或改写租户现有配置值。关闭该开关前后都要做权限分层验收:回读 `sys_role` 与 `mci_ai_role_policy`,需要业务分析的角色应有明确启用策略,`AllowedDomains`、`AllowedModels` 有效且模型仍处于启用状态;无策略账号仍可常规对话。至少用无角色、超级管理员、普通员工和客户身份分别调用 `Bootstrap`,确认 `Enabled=true`,并独立验证 `CanQueryData` 与数据范围符合角色。仅看到入口图标不算可用。
109
+ - 提审要求关闭 AI 入口时,必须把“关闭AI助手图标”设为 `DisableAiAssistant=1`,从数据库、客户端实际配置接口和入口逐层验收,不能用旧正向字段为 `0` 代替。官方包发布与其他租户安装是两个独立动作;未执行目标租户安装或字段清理时,不得宣称全体存量租户已移除旧元数据。
110
+ - 角色策略存在但 `AllowedModels` 为空或只引用已删除模型时,业务分析不可用,常规对话仍动态使用当前租户启用且开放的对话模型。要恢复原业务分析能力,应经管理员授权补齐当前租户模型白名单并回读,保留原 `DataScope/AllowedDomains`,不能静默把任何新模型当作已获准接收业务数据。禁止删除角色策略校验或在客户端强制 `Enabled=true`。
111
+ - 商城包不能携带发布租户的角色 Id、模型 Id 或密钥;应携带业务域定义和接口引擎,由安装后的目标租户动态发现自己的启用模型。发布后回读 `sys_microistore.AppVersion/AppPakcet`,并真实执行 `Bootstrap` 验证超级管理员可用、模型非空、快捷问题存在。
112
+
113
+ ### 常规对话与业务数据权限分离(强制)
114
+
115
+ - `Bootstrap.Enabled` 表示登录账号可进入助手,`ChatEnabled` 表示存在可用对话模型,`CanQueryData` 独立表示可分析已授权业务数据。无数据权限时返回空 `AllowedDomains` 和“常规对话”;模型列表为空时返回 `MODEL_UNAVAILABLE`,客户端提示检查模型,不得再显示“当前角色未开通 AI助手”。入口的 `DisableAiAssistant`、模型的 `AllowAllRolesChat` 和业务数据策略是三种不同含义,不能互相替代。
116
+ - 多角色权限必须按“数据域 + 当前模型”分别合并。A 域的 `All` 不能提升 B 域的 `Self`,其它模型的白名单不能授权本轮模型读取数据。没有适用授权、范围无法落到固定业务字段、敏感字段未开放时,业务读取失败关闭。
117
+ - 普通问候、写作与知识问答不自动查询全部业务域。常规对话路径不查询业务表、不提供 Schema/SQL/工具,也不把历史数据模式消息重新送入无数据权限的模型上下文。客户端伪造 Mode、RoleIds、Level、AllowedDomains 或模型 Id 不能扩大范围。
118
+ - 对话模型发现必须按当前模型和媒体目录判断能力,纯图片/音乐/视频/配音型号不能成为默认文本模型;中转目录只暴露安全投影,不返回供应商 ApiKey 或 Endpoint。远端 HTTP 可能返回 Promise,必须等待真实模型结果,不能把 Promise 当字符串或用统计兜底冒充常规对话成功。
119
+ - 打开助手和身份变更时重新获取 Bootstrap;请求结果按用户与请求代次隔离,旧角色/旧账号请求不能覆盖新状态。模型缺失、网络失败、会话失效分别处理,并保留重试。
120
+ - 欢迎语、输入提示与等待状态也必须区分常规对话和业务分析;无数据权限时不得声称已连接业务数据、正在汇总业务记录。前端定时动画不能冒充服务端实际执行进度。
121
+ - 官方 AI助手 v7.7.2 的 `mci_ai_data_assistant.ApiRole` 显式使用平台支持的 `["$authenticated"]`,`AllowAnonymous=0`,让 `OnlyGet` 只读角色也能调用助手和保存自己的对话。不能通过清空角色 `BaseLimit`、给账号添加管理员角色或放开其它业务接口解决聊天入口受阻;必须用真实只读客户账号验证 Bootstrap、Chat、会话记录与原业务限制仍成立。
122
+ - 最低验收:无角色、客户、员工、管理、多角色账号分别执行 Bootstrap 和真实 Chat;确认无数据账号 `UsedAi=true/Mode=chat/Domains=[]`,有数据账号按本人/部门范围查询。测试禁用策略、旧模型、显式关闭公共对话模型、纯媒体模型、跨账号历史、伪造权限和模型故障。管理员单账号成功、仅图标截图或本地 mock 成功都不能代替普通账号真实验收。
90
123
 
91
124
  ## Schema 检索双模式
92
125
 
@@ -305,6 +305,8 @@ description: Microi 应用商城开发、打包、安装和升级规范。用于
305
305
 
306
306
  - 触发场景:同一轮主租户批量任务在不同子租户分别报“数据集目标表尚未创建”“接口引擎写入后 HTTP 状态不一致”“既有菜单 Url 唯一冲突”或“未找到 OsClient”;父任务若在目录阶段对全部目标做有副作用自举,还会让一个坏租户阻断其余已可执行租户。
307
307
  - 包结构闭包:任何 `DataSets.TableName` 都必须由同一包的 `DiyTables + DiyFields + DDLStatements + PhysicalColumns` 完整创建或由显式依赖声明保证先安装,不能只因为官方母库已有该表就省略。契约测试要逐个数据集反向验证目标表、主键、字段和物理 DDL,并在真实缺表旧租户执行首次安装与重复安装。
308
+ - 配置子表种子不能硬编码官方父记录 Id。`InsertIfMissing` 数据集可声明 `ParentBinding:{Field:'SysConfigId',TableName:'sys_config',MatchField:'IsEnable',MatchValue:1}`,仅在目标端查询恰好一条父记录 Id,先绑定外键再检查冲突。0 条、多条、查询失败或不安全标识立即失败;不能覆盖父配置值。导出器须保留该声明,旧导入器必须先升级,不能忽略绑定后按官方 Id 写入。
309
+ - 大表物理兼容必须覆盖全部 DDL 路径:`BIT` 不能落入 `varchar` 默认映射,整数显示宽度与纯标签/注释差异不能触发改列;同一个包的字段元数据变化交给物理列阶段统一比较,不能先改再改回。只有默认值变化时使用 `ALTER COLUMN ... SET/DROP DEFAULT`、强回读并禁止 COPY 回退,不能用完整 `MODIFY COLUMN` 重写类型/字符集/历史行;空字符串默认值不等同于无默认值。安装器时间辅助必须自包含,应用文件落库等新增分支也不得直接依赖租户的 DateNow。
308
310
  - 受管接口状态:旧库 `diy_field` 元数据可能落后于 `sys_apiengine` 物理列,导致 FormEngine 返回成功却忽略 `IsEnable/StopHttp`。仅对受信官方 `Managed` 接口的固定布尔控制列,允许在 FormEngine 写后不一致时按稳定 Id 参数化校准物理列、清理租户缓存并严格二次回读;源码、匿名权限、ApiAddress 和租户扩展不得借此绕过三方冲突或所有权保护,二次回读仍不一致必须整包失败。
309
311
  - 菜单与目录隔离:更新既有菜单发生 Url 唯一冲突时,优先保留目标租户当前唯一路由;确需新路由时使用有界、可回读的稳定后缀,不得字符串拼 SQL。子租户目录发现必须是无副作用读取;运行时缺失在单目标投递前按 `sys_osclients` 受控热加载并只记录该租户失败,已经排队的子任务继续监控到终态,禁止一个 `未找到OsClient` 提前终止整批。
310
312
  - 百租户并发边界:父协调任务继续使用集群级防重键;子安装任务必须使用固定商城工作器 `ConcurrencyKey` 在当前运行环境内串行。不能根据 `OsClient` 推断物理库隔离,因为多个子租户可能共享同一数据库;只有未来能由服务端权威连接指纹证明互不共享物理库并建立分组锁时,才允许在不同物理库组间并行。
@@ -1,181 +1,181 @@
1
- ---
2
- name: microi-mobile-app-quality
3
- description: Microi 移动端质量门禁,适用于 UniApp/H5/微信小程序。用于创建、重设计、修复、测试或交付任何 Microi 移动端项目,覆盖登录、底部导航、快捷入口、按钮、动效、菜单层级与移动端视觉验收。
4
- ---
5
-
6
- > **Codex 非阻塞自动更新:** 当前宿主为 Codex 时,吾码 CLI、Codex 插件与工作区 AI/MCP 由后台自动更新;需要诊断时读取 `../microi-codex-installer/SKILL.md`。更新失败、等待空闲或尚未重载均不得阻断当前、正在进行或新建任务。非 Codex 宿主跳过此项。
7
-
8
- # Microi 移动端质量门禁
9
-
10
- 每次交付 Microi UniApp/H5/微信小程序时都必须应用本 skill。这里记录的是移动端项目反复出现、必须避免的问题。
11
-
12
- 自动触发:只要任务涉及 Microi 移动端应用、H5、微信小程序、App 构建、uni-app 项目、登录页、tabbar、首页、我的页、工作台、报告页、视觉重设计或移动端验收,即使用户没有明确点名,也要应用本 skill。
13
-
14
- <!-- microi-progressive:begin -->
15
- <!-- microi-progressive:chunk id=microi-mobile-app-quality-000 sha256=9f83607349ba6e305c3d2993de8eeceab70c344557e5dfa2a5be964492ef4685 -->
16
- ## 1. 导航和快捷入口必须使用真实图标
17
-
18
- 底部导航、首页快捷入口、会员中心快捷项、九宫格操作和悬浮操作,必须在文字上方或旁边显示可识别的图标。
19
-
20
- 要求:
21
- - 使用 Microi.UI 图标、项目 `mci-icon-*` CSS 图标、iconfont 或稳定的本地图标组件。
22
- - 首页、订单、报告、报修、我的等底部导航项必须显示图标,不能用 `首` / `单` / `报` / `我` 这类单字代替。
23
- - 首页入口宫格和我的/个人中心快捷项同样适用。
24
- - 主题、租户、版本、账号、关于、客户绑定、服务入口等个人中心/设置/信息块必须使用真实图标,不能用 `租` / `版` / `客` 这类单字代替。
25
- - 图标必须是真实视觉符号,不能依赖远程占位图。
26
- - tabBar、返回、关闭等小型交互图标若使用 SVG 或图片,必须本地化、纳入版本管理并检查小程序打包结果;Hero、Banner、音视频、字体等大资源遵守 `microi-uniapp-frontend` 的租户 HDFS/CDN 规则,不得为“本地化”无边界增大主包。
27
- - 彩色圆形、胶囊、浮动快捷入口必须同时定义图标底色和内部图标色,不能只依赖继承。红、绿、灰等深色背景优先白色图标;黄色、浅色背景必须使用深色图标。
28
- - 如果基础样式里存在 `.entry:nth-child(n)`、`.mci-bubble:nth-child(n)` 等颜色规则,主题覆盖必须同时覆盖 `background` 和 `color`,避免只换圆底但图标仍沿用旧主题色。
29
- - 主题图标色覆盖必须具备不低于基础规则的 CSS 优先级;构建压缩后仍要检查产物。如果压缩器移除了同值 `color`,可对图标对比度兜底规则使用 `!important`,但只限这类可读性护栏。
30
-
31
- 禁止:
32
- - 纯文字导航图标。
33
- - 用单个汉字冒充图标。
34
- - 缺失图标占位、404 远程图标或只靠 emoji 的图标体系。
35
-
36
- 验收:
37
- - 截图检查每个底部导航、首页快捷入口和会员快捷入口。
38
- - 确认 H5、微信小程序和 App 构建目标中,图标加文字可见、对齐且可点击。
39
- - 主题切换后重新截图底部导航、首页快捷入口和个人中心快捷入口;任何一个图标在圆底上看不清,都算验收失败。
40
- - UniApp H5 桌面预览可以显示手机壳;真机和浏览器移动设备仿真必须自动去壳并铺满视口。自动化测试要分别断言桌面手机壳存在、移动端手机壳标题隐藏,同时检查所有底部菜单包含真实图标节点。
41
-
42
- <!-- /microi-progressive:chunk -->
43
- <!-- microi-progressive:chunk id=microi-mobile-app-quality-001 sha256=4e1b247852aa9f235a26f756d415ebb9fb922f2fea0569bda1bdc8e0b91c4d1c -->
44
- ## 1.1 包体资源必须按用途分层
45
-
46
- - 构建前扫描图片、音频、视频、字体和第三方资源;公开的大资源优先上传到当前租户 HDFS 公有桶并通过 `sys_config.FileServer`/CDN 引用,敏感资源使用私有桶。
47
- - 只保留小型交互图标和离线关键资源在主包。任何远程迁移都必须同步检查小程序下载域名、失败占位、缓存策略和弱网首屏。
48
- - 压缩以用户可感知质量为边界:图片检查文字与主体细节,音频抽听,视频抽播;禁止仅为满足扫描数字而过度压缩。
49
- - 验收必须同时给出包体扫描、CDN 匿名 `200`、正确媒体类型和多尺寸截图证据。缺任一层都不能宣称资源问题已通过。
50
- - 微信小程序上传前增加硬门禁:扫描 `dist/build/mp-weixin` 的真实文件;单个非关键静态资源超过 `256 KB`、主包静态资源达到 `1.5 MB`,或主包距微信当前硬上限不足 `300 KB` 时,发布步骤必须失败并列出最大文件,不能等开发者工具上传后才发现超限。
51
- - 迁移到 HDFS/CDN 后必须从构建产物确认原大文件已经消失,并从业务记录/配置回读相对 `Path`;页面要先加载当前租户 `SysConfig.FileServer`,不得以源码硬编码 CDN 域名替代运行期配置。远程资源加载失败时只能回退到轻量本地占位,不得把原大图重新塞回主包。
52
-
53
- <!-- /microi-progressive:chunk -->
54
- <!-- microi-progressive:chunk id=microi-mobile-app-quality-002 sha256=99bbb22068bb61d61a3fd20b1a21f421804857ce8da85a92390f64641e3f43fc -->
55
- ## 2. 不要猜测 Microi 前端 SDK 登录接口
56
-
57
- 编写登录代码前,先检查本地项目 SDK 封装,例如 `src/utils/microi.v8.js`、`src/utils/api.js`,或标准 `microi.uniapp` 登录实现。
58
-
59
- 要求:
60
- - 使用实际导出的接口。如果 SDK 暴露的是 `V8.Login(param)`,不要写 `V8.Login.Login(...)`。
61
- - 员工/账号登录应通过项目 SDK 封装调用平台登录端点,通常是 `/api/SysUser/Login` 或 `V8.Login(param)`。
62
- - Token 提取必须同时支持响应头和响应体兜底。
63
- - 登录成功必须同时满足 `Code=1`、已获取有效 token、已获取有效用户对象且存在 `Id`。任一条件缺失都必须清理 token、用户缓存和本地会话,并以失败处理;不能只因为接口返回成功或缓存了账号名就显示为半登录。
64
- - 会话恢复必须重新校验 token 和用户 `Id`。如果本地只有 `staffUser.Account/Name` 但没有 token,必须清空缓存,不能出现“姓名是 admin、状态是未登录”的矛盾界面。
65
- - 登录后所有页面的 `isLogin`、头像姓名、角色文本、未登录提示和可见按钮必须来自同一个 session store,不要让单页自己读取旧缓存。
66
- - 登录实现后的第一个测试必须包含真实点击登录按钮,并检查控制台和网络请求。
67
- - 登录必须传移动端 `_ClientType` 和稳定 `did`,并在 `App.onShow` 调用标准 SDK 的 `resumeAuthSession(false)`。系统休眠后不能只等定时器恢复。
68
- - 登录失效提示必须原样展示后端 `Msg`;如果 Token 已过期,显示过期分钟/小时/天,如果 Token 属于其它租户,显示 Token 租户与当前租户。详细协议读取 `microi-frontend-sdk/SKILL.md`。
69
-
70
- 禁止:
71
- - 凭空编造 SDK 子对象。
72
- - 把接口引擎登录和 `SysUser` 账号登录当作同一个契约。
73
- - 未测试真实按钮路径就交付登录页。
74
-
75
- 验收:
76
- - H5 路由 `/pages/login/login` 或项目登录路由打开时无控制台错误。
77
- - 点击账号登录不会抛出 `V8.Login.Login is not a function`。
78
- - 使用真实系统账号登录后,必须验证“我的”页显示已登录角色,首页/工单/报告不再出现未登录提示,刷新页面或切换底部导航后仍保持一致。
79
-
80
- <!-- /microi-progressive:chunk -->
81
- <!-- microi-progressive:chunk id=microi-mobile-app-quality-003 sha256=0a9274750cb6f507b87c417eb66e5f9aa60918c6ead87c7eb2855e209aa30e61 -->
82
- ## 2.1 登录验证码必须跟随 Sys_Config.EnableCaptcha
83
-
84
- PC 端、H5、App、微信小程序或任何自定义前端只要调用 `/api/SysUser/login`、`/api/SysUser/Login` 或 `V8.Login(param)`,都必须先读取 `Sys_Config` 的 `EnableCaptcha` 配置,并按配置决定是否展示和提交图形验证码。
85
-
86
- 要求:
87
- - 启动登录页时调用 `/apiengine/platform-sys-config` 或项目 SDK 的 `V8.GetSysConfig(true)`,读取当前租户启用状态;旧 Controller 路由只作兼容转发。
88
- - `EnableCaptcha` 可能是 `1`、`true`、`'1'`、`'true'`,也可能是大小写不同的字符串。必须使用统一的 `isEnabledFlag(value)` 或等价函数判断,不能直接 `!!value`,否则字符串 `'0'` 会被误判为开启。
89
- - 开启验证码时,登录表单必须显示验证码输入框和验证码图片;验证码图片通过 `GET /api/Captcha/GetCaptcha` 获取,读取响应头 `captchaid`,提交登录时附加 `_CaptchaId` 和 `_CaptchaValue`。
90
- - 登录失败、验证码错误、网络错误后必须刷新验证码并清空验证码输入;验证码未填写时前端直接阻止提交并提示用户。
91
- - 未开启验证码时不得显示验证码输入,也不得提交空 `_CaptchaId/_CaptchaValue` 影响正常登录。
92
- - 微信小程序默认手机号授权登录仍是主路径;账号/手机号 + 密码兜底入口如果调用 `SysUser/login`,同样要遵守验证码规则。
93
-
94
- 禁止:
95
- - 不读取 `Sys_Config.EnableCaptcha` 就直接调用账号登录。
96
- - 只在 PC 端做验证码,移动端缺失验证码。
97
- - 直接写 `if (SysConfig.EnableCaptcha)` 或 `!!cfg.EnableCaptcha`,没有兼容 `'0'`、`'1'`、`'true'` 等字符串。
98
- - 登录失败后继续使用旧 `captchaid` 和旧验证码值。
99
-
100
- 验收:
101
- - 人工或自动化把 `EnableCaptcha` 分别模拟为 `1`、`true`、`'1'`、`'true'`,确认验证码出现并随登录提交。
102
- - 模拟 `EnableCaptcha` 为 `0`、`false`、`'0'`、空值,确认验证码不出现且登录请求不带空验证码字段。
103
- - 检查网络请求:`/api/Captcha/GetCaptcha` 返回后已保存 `captchaid`;登录请求体包含 `_CaptchaId/_CaptchaValue`。
104
- - 参考标准实现:`microi.uniapp/src/pages/login/index.vue`。
105
-
106
- <!-- /microi-progressive:chunk -->
107
- <!-- microi-progressive:chunk id=microi-mobile-app-quality-004 sha256=22bdaf38588f251016e115f1ad15a433e827fb2191041d55ecad42cda94253d1 -->
108
- ## 3. OsClient 请求头不得重复
109
-
110
- Microi 请求只能发送一个不区分大小写的 OsClient 请求头。浏览器、代理或服务端运行时可能把 `OsClient` 和 `osclient` 这类大小写重复键合并成 `demo, demo`,导致租户识别失败。
111
-
112
- 要求:
113
- - 通过统一工具构建请求头,设置 `osclient` 前先删除已有的不区分大小写匹配项。标准 SDK 的 `buildHeaders` 必须使用单值写入函数,不得直接写 `headers.OsClient = ...`。
114
- - 优先使用一个标准键,通常是小写 `osclient`,并且只传一个运行期值,例如 `demo`。
115
- - `Authorization` / `authorization` 以及其它单值鉴权头也要做同样的大小写去重。
116
- - 当 Microi 端点契约需要时,请求体或查询参数可以包含 `OsClient`,但请求头仍只能包含一个 `osclient` 值。
117
-
118
- 禁止:
119
- - 同时设置 `headers.OsClient` 和 `headers.osclient`。
120
- - 同时设置 `headers.Authorization` 和 `headers.authorization`。
121
- - 网络面板里已经看到 `demo, demo` 仍然交付。
122
-
123
- 验收:
124
- - 在网络面板或请求适配器日志里检查登录请求。
125
- - 确认目标租户请求头正好是一个运行期值(例如 `osclient: demo`),没有被逗号合并。
126
- - 微信/支付宝/飞书/抖音等小程序授权登录接口也必须检查,例如 `/apiengine/miniprogram-login`,不得出现 `osclient: demo, demo` 这类合并值。
127
-
128
- <!-- /microi-progressive:chunk -->
129
- <!-- microi-progressive:chunk id=microi-mobile-app-quality-005 sha256=1394c7fb8e59b25553e2f9b71ab7f8cf03290b6930c8d8436123bc6048ad2435 -->
130
- ## 3.1 小程序授权登录必须可追踪、可读错误
131
-
132
- 微信开发者工具的模拟授权与体验版真机调用不是同一条真实链路。手机号授权登录接口必须按阶段诊断,不能只返回“手机号登录失败”。
133
-
134
- 要求:
135
- - 接口入口生成短追踪号,并在微信身份交换、AccessToken、手机号交换、账号匹配、用户更新/注册、兼容映射、系统 Token 签发前更新阶段名。
136
- - 每个失败出口和顶层 `catch` 都调用统一 `fail(stage, message, detail)`:写 `V8.Method.AddSysLog`,同时返回包含“阶段 + 原因 + 追踪号”的 `Msg`。系统日志使用独立 MongoDB 日志,不依赖业务事务提交。
137
- - 日志只记录 OsClient、AppId、阶段、微信 `errcode/errmsg`、是否收到授权码、脱敏手机号和必要业务 Id;严禁记录小程序 Secret、AccessToken、完整手机号、`detail.code`、`LoginCode`、OpenId 或请求头 Token。
138
- - 微信 `jscode2session`、AccessToken、`getuserphonenumber` 必须分别捕获 HTTP 异常与微信业务错误,保留官方 `errmsg`,不要用一个大 `catch` 抹掉失败位置。
139
- - 前端请求适配器必须把 `uni.request.fail.errMsg`、HTTP 状态、后端 `Msg` 归一化;手机号登录失败使用可完整阅读的模态框展示,不用会截断长文本的短 Toast。
140
- - 用户拒绝授权可以使用简短提示;非拒绝类授权错误、网络错误、后端错误必须显示真实原因和追踪号。
141
-
142
- 验收:
143
- - 用无效 `LoginCode` 和无效手机号授权码分别烟测,响应包含不同阶段和追踪号,并能在系统日志按追踪号查到对应记录。
144
- - 模拟 `uni.request` 域名未配置、超时、HTTP 500、接口 `Code=0`,前端均显示具体原因,loading 在 `finally` 中恢复。
145
- - 体验版真机复测授权登录;不能只以开发者工具模拟成功作为上线依据。
146
-
147
- <!-- /microi-progressive:chunk -->
148
- <!-- microi-progressive:chunk id=microi-mobile-app-quality-006 sha256=feb9ba3267bdf1f6394c425b45dd71e19ac4382ae05549d6e1b6b664c6517a19 -->
149
- ## 3.1.1 手机号快速验证前置页不得混淆腾讯官方
150
-
151
- - 调用手机号快速验证组件前展示的登录页、弹窗、按钮、说明、分享标题和失败提示中,禁止出现“微信”“微信官方”“微信登录”“一键登录”等可能让用户误认为腾讯官方功能或官方产品的文案。
152
- - 前置页不得使用微信官方 Logo、相似绿色气泡图标、仿官方按钮或其它腾讯官方视觉元素;只允许展示小程序自身主体名称、品牌 Logo 和通用手机/验证图标。
153
- - 推荐统一使用“手机号快捷登录”“手机号快速验证”“验证中”等中性文案。底层仍按平台要求保留 `open-type="getPhoneNumber"`、`provider:'weixin'` 等技术实现,不能为改文案破坏真实授权链路。
154
- - `build:mp-weixin` 后必须扫描登录页源码和 `dist/build/mp-weixin/pages/login/` 产物中的可见文案,并对手机号快速验证前置页截图;发现混淆词、官方 Logo 或近似元素时阻止上传和提审。
155
-
156
- <!-- /microi-progressive:chunk -->
157
- <!-- microi-progressive:chunk id=microi-mobile-app-quality-007 sha256=7598db1fdabfe127c2be7593b83dc3a246b1db852d9c0d4001f849d3e97aa273 -->
158
- ## 3.2 微信小程序每个页面默认支持分享
159
-
160
- 小程序项目必须默认支持转发给朋友和分享到朋友圈,不能只给首页或公开页添加分享。登录和权限控制属于访问阶段,不得用来隐藏分享能力。
161
-
162
- 要求:
163
- - 以 `pages.json` 为路由清单逐页接入 `onShareAppMessage` 与 `onShareTimeline`;Vue3 组合式 API 页面必须从 `@dcloudio/uni-app` 直接导入并注册两个生命周期,不能只写一个全局工具后假设编译器会自动发现。
164
- - 页面显示时确保微信分享菜单包含 `shareAppMessage`、`shareTimeline`;分享标题使用业务标题或稳定页面标题,资讯/报告等内容页优先带预览图。
165
- - 好友转发返回以 `/` 开头的完整 `path`;朋友圈返回当前页面业务 `query`。保留 `id`、分类、公开报告 ShareToken 等定位参数,剔除 Authorization、AccessToken、CustomerToken、手机号授权码、LoginCode、OpenId、验证码等敏感或一次性参数。
166
- - 需要登录或角色权限的页面仍允许分享原页面。接收者打开后再由页面鉴权提示登录/无权限,不能把所有受保护页面的分享地址强制改成首页。
167
- - 登录页本身也必须支持分享,避免接收者被鉴权重定向后失去转发入口。
168
-
169
- 验收:
170
- - 静态扫描 `pages.json` 与页面源码,页面总数必须等于同时注册两种分享生命周期的页面数。
171
- - 执行 `build:mp-weixin`,逐页检查编译后的页面 JS 存在 `onShareAppMessage`、`onShareTimeline`,不能只检查源码或只确认构建成功。
172
- - 在微信开发者工具和体验版各抽测公开页、登录页、一个需登录详情页:朋友转发和朋友圈入口都存在,接收者路径参数正确;未登录接收者看到登录提示而不是白屏或 404。
173
-
174
- <!-- /microi-progressive:chunk -->
175
- ## 详细参考路由(渐进披露)
176
-
177
- 仅在当前任务涉及对应主题时读取;下列文件合计保留了原 SKILL.md 的全部详细知识。
178
-
179
- - [references/progressive-01-4-重要按钮必须带图标.md](references/progressive-01-4-重要按钮必须带图标.md):4. 重要按钮必须带图标;4.1 模块列表优先使用声明式业务卡片;5. 首屏文字和浮层不得重叠;5.1 未登录/授权提示必须在可用内容区居中;5.2 自定义导航页面必须通过安全区与微信胶囊门禁;5.3 全屏工具页必须遵守返回状态栈;5.4 微信浮动入口必须通过真实事件桥门禁;6. 后台菜单必须规划为至少两级;7. 移动端页面需要动效,但动效必须有用;8. 登录页必须是直接登录界面
180
- - [references/progressive-02-9-主题切换必须真实且全局生效.md](references/progressive-02-9-主题切换必须真实且全局生效.md):9. 主题切换必须真实且全局生效;10. 报告/列表详情必须保留用户身份;11. 角色与权限必须基于 sys_user.RoleIds 建模;最终交付清单
181
- <!-- microi-progressive:end -->
1
+ ---
2
+ name: microi-mobile-app-quality
3
+ description: Microi 移动端质量门禁,适用于 UniApp/H5/微信小程序。用于创建、重设计、修复、测试或交付任何 Microi 移动端项目,覆盖登录、底部导航、快捷入口、按钮、动效、菜单层级与移动端视觉验收。
4
+ ---
5
+
6
+ > **Codex 非阻塞自动更新:** 当前宿主为 Codex 时,吾码 CLI、Codex 插件与工作区 AI/MCP 由后台自动更新;需要诊断时读取 `../microi-codex-installer/SKILL.md`。更新失败、等待空闲或尚未重载均不得阻断当前、正在进行或新建任务。非 Codex 宿主跳过此项。
7
+
8
+ # Microi 移动端质量门禁
9
+
10
+ 每次交付 Microi UniApp/H5/微信小程序时都必须应用本 skill。这里记录的是移动端项目反复出现、必须避免的问题。
11
+
12
+ 自动触发:只要任务涉及 Microi 移动端应用、H5、微信小程序、App 构建、uni-app 项目、登录页、tabbar、首页、我的页、工作台、报告页、视觉重设计或移动端验收,即使用户没有明确点名,也要应用本 skill。
13
+
14
+ <!-- microi-progressive:begin -->
15
+ <!-- microi-progressive:chunk id=microi-mobile-app-quality-000 sha256=9f83607349ba6e305c3d2993de8eeceab70c344557e5dfa2a5be964492ef4685 -->
16
+ ## 1. 导航和快捷入口必须使用真实图标
17
+
18
+ 底部导航、首页快捷入口、会员中心快捷项、九宫格操作和悬浮操作,必须在文字上方或旁边显示可识别的图标。
19
+
20
+ 要求:
21
+ - 使用 Microi.UI 图标、项目 `mci-icon-*` CSS 图标、iconfont 或稳定的本地图标组件。
22
+ - 首页、订单、报告、报修、我的等底部导航项必须显示图标,不能用 `首` / `单` / `报` / `我` 这类单字代替。
23
+ - 首页入口宫格和我的/个人中心快捷项同样适用。
24
+ - 主题、租户、版本、账号、关于、客户绑定、服务入口等个人中心/设置/信息块必须使用真实图标,不能用 `租` / `版` / `客` 这类单字代替。
25
+ - 图标必须是真实视觉符号,不能依赖远程占位图。
26
+ - tabBar、返回、关闭等小型交互图标若使用 SVG 或图片,必须本地化、纳入版本管理并检查小程序打包结果;Hero、Banner、音视频、字体等大资源遵守 `microi-uniapp-frontend` 的租户 HDFS/CDN 规则,不得为“本地化”无边界增大主包。
27
+ - 彩色圆形、胶囊、浮动快捷入口必须同时定义图标底色和内部图标色,不能只依赖继承。红、绿、灰等深色背景优先白色图标;黄色、浅色背景必须使用深色图标。
28
+ - 如果基础样式里存在 `.entry:nth-child(n)`、`.mci-bubble:nth-child(n)` 等颜色规则,主题覆盖必须同时覆盖 `background` 和 `color`,避免只换圆底但图标仍沿用旧主题色。
29
+ - 主题图标色覆盖必须具备不低于基础规则的 CSS 优先级;构建压缩后仍要检查产物。如果压缩器移除了同值 `color`,可对图标对比度兜底规则使用 `!important`,但只限这类可读性护栏。
30
+
31
+ 禁止:
32
+ - 纯文字导航图标。
33
+ - 用单个汉字冒充图标。
34
+ - 缺失图标占位、404 远程图标或只靠 emoji 的图标体系。
35
+
36
+ 验收:
37
+ - 截图检查每个底部导航、首页快捷入口和会员快捷入口。
38
+ - 确认 H5、微信小程序和 App 构建目标中,图标加文字可见、对齐且可点击。
39
+ - 主题切换后重新截图底部导航、首页快捷入口和个人中心快捷入口;任何一个图标在圆底上看不清,都算验收失败。
40
+ - UniApp H5 桌面预览可以显示手机壳;真机和浏览器移动设备仿真必须自动去壳并铺满视口。自动化测试要分别断言桌面手机壳存在、移动端手机壳标题隐藏,同时检查所有底部菜单包含真实图标节点。
41
+
42
+ <!-- /microi-progressive:chunk -->
43
+ <!-- microi-progressive:chunk id=microi-mobile-app-quality-001 sha256=4e1b247852aa9f235a26f756d415ebb9fb922f2fea0569bda1bdc8e0b91c4d1c -->
44
+ ## 1.1 包体资源必须按用途分层
45
+
46
+ - 构建前扫描图片、音频、视频、字体和第三方资源;公开的大资源优先上传到当前租户 HDFS 公有桶并通过 `sys_config.FileServer`/CDN 引用,敏感资源使用私有桶。
47
+ - 只保留小型交互图标和离线关键资源在主包。任何远程迁移都必须同步检查小程序下载域名、失败占位、缓存策略和弱网首屏。
48
+ - 压缩以用户可感知质量为边界:图片检查文字与主体细节,音频抽听,视频抽播;禁止仅为满足扫描数字而过度压缩。
49
+ - 验收必须同时给出包体扫描、CDN 匿名 `200`、正确媒体类型和多尺寸截图证据。缺任一层都不能宣称资源问题已通过。
50
+ - 微信小程序上传前增加硬门禁:扫描 `dist/build/mp-weixin` 的真实文件;单个非关键静态资源超过 `256 KB`、主包静态资源达到 `1.5 MB`,或主包距微信当前硬上限不足 `300 KB` 时,发布步骤必须失败并列出最大文件,不能等开发者工具上传后才发现超限。
51
+ - 迁移到 HDFS/CDN 后必须从构建产物确认原大文件已经消失,并从业务记录/配置回读相对 `Path`;页面要先加载当前租户 `SysConfig.FileServer`,不得以源码硬编码 CDN 域名替代运行期配置。远程资源加载失败时只能回退到轻量本地占位,不得把原大图重新塞回主包。
52
+
53
+ <!-- /microi-progressive:chunk -->
54
+ <!-- microi-progressive:chunk id=microi-mobile-app-quality-002 sha256=99bbb22068bb61d61a3fd20b1a21f421804857ce8da85a92390f64641e3f43fc -->
55
+ ## 2. 不要猜测 Microi 前端 SDK 登录接口
56
+
57
+ 编写登录代码前,先检查本地项目 SDK 封装,例如 `src/utils/microi.v8.js`、`src/utils/api.js`,或标准 `microi.uniapp` 登录实现。
58
+
59
+ 要求:
60
+ - 使用实际导出的接口。如果 SDK 暴露的是 `V8.Login(param)`,不要写 `V8.Login.Login(...)`。
61
+ - 员工/账号登录应通过项目 SDK 封装调用平台登录端点,通常是 `/api/SysUser/Login` 或 `V8.Login(param)`。
62
+ - Token 提取必须同时支持响应头和响应体兜底。
63
+ - 登录成功必须同时满足 `Code=1`、已获取有效 token、已获取有效用户对象且存在 `Id`。任一条件缺失都必须清理 token、用户缓存和本地会话,并以失败处理;不能只因为接口返回成功或缓存了账号名就显示为半登录。
64
+ - 会话恢复必须重新校验 token 和用户 `Id`。如果本地只有 `staffUser.Account/Name` 但没有 token,必须清空缓存,不能出现“姓名是 admin、状态是未登录”的矛盾界面。
65
+ - 登录后所有页面的 `isLogin`、头像姓名、角色文本、未登录提示和可见按钮必须来自同一个 session store,不要让单页自己读取旧缓存。
66
+ - 登录实现后的第一个测试必须包含真实点击登录按钮,并检查控制台和网络请求。
67
+ - 登录必须传移动端 `_ClientType` 和稳定 `did`,并在 `App.onShow` 调用标准 SDK 的 `resumeAuthSession(false)`。系统休眠后不能只等定时器恢复。
68
+ - 登录失效提示必须原样展示后端 `Msg`;如果 Token 已过期,显示过期分钟/小时/天,如果 Token 属于其它租户,显示 Token 租户与当前租户。详细协议读取 `microi-frontend-sdk/SKILL.md`。
69
+
70
+ 禁止:
71
+ - 凭空编造 SDK 子对象。
72
+ - 把接口引擎登录和 `SysUser` 账号登录当作同一个契约。
73
+ - 未测试真实按钮路径就交付登录页。
74
+
75
+ 验收:
76
+ - H5 路由 `/pages/login/login` 或项目登录路由打开时无控制台错误。
77
+ - 点击账号登录不会抛出 `V8.Login.Login is not a function`。
78
+ - 使用真实系统账号登录后,必须验证“我的”页显示已登录角色,首页/工单/报告不再出现未登录提示,刷新页面或切换底部导航后仍保持一致。
79
+
80
+ <!-- /microi-progressive:chunk -->
81
+ <!-- microi-progressive:chunk id=microi-mobile-app-quality-003 sha256=a35f20404acbf61814f9475610f881f7c60effc0ce3bb8797cee300cd3349ba7 -->
82
+ ## 2.1 登录验证码必须跟随 Sys_Config.EnableCaptcha
83
+
84
+ PC 端、H5、App、微信小程序或任何自定义前端只要调用 `/api/SysUser/login`、`/api/SysUser/Login` 或 `V8.Login(param)`,都必须先读取 `Sys_Config` 的 `EnableCaptcha` 配置,并按配置决定是否展示和提交图形验证码。
85
+
86
+ 要求:
87
+ - 启动登录页时调用 `/apiengine/platform-sys-config` 或项目 SDK 的 `V8.GetSysConfig(true)`,读取当前租户启用状态;旧 Controller 路由只作兼容转发。
88
+ - `EnableCaptcha` 可能是 `1`、`true`、`'1'`、`'true'`,也可能是大小写不同的字符串。必须使用统一的 `isEnabledFlag(value)` 或等价函数判断,不能直接 `!!value`,否则字符串 `'0'` 会被误判为开启。
89
+ - 开启验证码时,登录表单必须显示验证码输入框和验证码图片;验证码图片通过 `GET /api/Captcha/GetCaptcha` 获取,读取响应头 `captchaid`,提交登录时附加 `_CaptchaId` 和 `_CaptchaValue`。
90
+ - 登录失败、验证码错误、网络错误后必须刷新验证码并清空验证码输入;验证码未填写时前端直接阻止提交并提示用户。
91
+ - 未开启验证码时不得显示验证码输入,也不得提交空 `_CaptchaId/_CaptchaValue` 影响正常登录。
92
+ - 微信小程序默认手机号授权登录仍是主路径;账号/手机号 + 密码兜底入口如果调用 `SysUser/login`,同样要遵守验证码规则。
93
+
94
+ 禁止:
95
+ - 不读取 `Sys_Config.EnableCaptcha` 就直接调用账号登录。
96
+ - 只在 PC 端做验证码,移动端缺失验证码。
97
+ - 直接写 `if (SysConfig.EnableCaptcha)` 或 `!!cfg.EnableCaptcha`,没有兼容 `'0'`、`'1'`、`'true'` 等字符串。
98
+ - 登录失败后继续使用旧 `captchaid` 和旧验证码值。
99
+
100
+ 验收:
101
+ - 人工或自动化把 `EnableCaptcha` 分别模拟为 `1`、`true`、`'1'`、`'true'`,确认验证码出现并随登录提交。
102
+ - 模拟 `EnableCaptcha` 为 `0`、`false`、`'0'`、空值,确认验证码不出现且登录请求不带空验证码字段。
103
+ - 检查网络请求:`/api/Captcha/GetCaptcha` 返回后已保存 `captchaid`;登录请求体包含 `_CaptchaId/_CaptchaValue`。
104
+ - 参考标准实现:`microi.uniapp/src/pages/login/index.vue`。
105
+
106
+ <!-- /microi-progressive:chunk -->
107
+ <!-- microi-progressive:chunk id=microi-mobile-app-quality-004 sha256=22bdaf38588f251016e115f1ad15a433e827fb2191041d55ecad42cda94253d1 -->
108
+ ## 3. OsClient 请求头不得重复
109
+
110
+ Microi 请求只能发送一个不区分大小写的 OsClient 请求头。浏览器、代理或服务端运行时可能把 `OsClient` 和 `osclient` 这类大小写重复键合并成 `demo, demo`,导致租户识别失败。
111
+
112
+ 要求:
113
+ - 通过统一工具构建请求头,设置 `osclient` 前先删除已有的不区分大小写匹配项。标准 SDK 的 `buildHeaders` 必须使用单值写入函数,不得直接写 `headers.OsClient = ...`。
114
+ - 优先使用一个标准键,通常是小写 `osclient`,并且只传一个运行期值,例如 `demo`。
115
+ - `Authorization` / `authorization` 以及其它单值鉴权头也要做同样的大小写去重。
116
+ - 当 Microi 端点契约需要时,请求体或查询参数可以包含 `OsClient`,但请求头仍只能包含一个 `osclient` 值。
117
+
118
+ 禁止:
119
+ - 同时设置 `headers.OsClient` 和 `headers.osclient`。
120
+ - 同时设置 `headers.Authorization` 和 `headers.authorization`。
121
+ - 网络面板里已经看到 `demo, demo` 仍然交付。
122
+
123
+ 验收:
124
+ - 在网络面板或请求适配器日志里检查登录请求。
125
+ - 确认目标租户请求头正好是一个运行期值(例如 `osclient: demo`),没有被逗号合并。
126
+ - 微信/支付宝/飞书/抖音等小程序授权登录接口也必须检查,例如 `/apiengine/miniprogram-login`,不得出现 `osclient: demo, demo` 这类合并值。
127
+
128
+ <!-- /microi-progressive:chunk -->
129
+ <!-- microi-progressive:chunk id=microi-mobile-app-quality-005 sha256=1394c7fb8e59b25553e2f9b71ab7f8cf03290b6930c8d8436123bc6048ad2435 -->
130
+ ## 3.1 小程序授权登录必须可追踪、可读错误
131
+
132
+ 微信开发者工具的模拟授权与体验版真机调用不是同一条真实链路。手机号授权登录接口必须按阶段诊断,不能只返回“手机号登录失败”。
133
+
134
+ 要求:
135
+ - 接口入口生成短追踪号,并在微信身份交换、AccessToken、手机号交换、账号匹配、用户更新/注册、兼容映射、系统 Token 签发前更新阶段名。
136
+ - 每个失败出口和顶层 `catch` 都调用统一 `fail(stage, message, detail)`:写 `V8.Method.AddSysLog`,同时返回包含“阶段 + 原因 + 追踪号”的 `Msg`。系统日志使用独立 MongoDB 日志,不依赖业务事务提交。
137
+ - 日志只记录 OsClient、AppId、阶段、微信 `errcode/errmsg`、是否收到授权码、脱敏手机号和必要业务 Id;严禁记录小程序 Secret、AccessToken、完整手机号、`detail.code`、`LoginCode`、OpenId 或请求头 Token。
138
+ - 微信 `jscode2session`、AccessToken、`getuserphonenumber` 必须分别捕获 HTTP 异常与微信业务错误,保留官方 `errmsg`,不要用一个大 `catch` 抹掉失败位置。
139
+ - 前端请求适配器必须把 `uni.request.fail.errMsg`、HTTP 状态、后端 `Msg` 归一化;手机号登录失败使用可完整阅读的模态框展示,不用会截断长文本的短 Toast。
140
+ - 用户拒绝授权可以使用简短提示;非拒绝类授权错误、网络错误、后端错误必须显示真实原因和追踪号。
141
+
142
+ 验收:
143
+ - 用无效 `LoginCode` 和无效手机号授权码分别烟测,响应包含不同阶段和追踪号,并能在系统日志按追踪号查到对应记录。
144
+ - 模拟 `uni.request` 域名未配置、超时、HTTP 500、接口 `Code=0`,前端均显示具体原因,loading 在 `finally` 中恢复。
145
+ - 体验版真机复测授权登录;不能只以开发者工具模拟成功作为上线依据。
146
+
147
+ <!-- /microi-progressive:chunk -->
148
+ <!-- microi-progressive:chunk id=microi-mobile-app-quality-006 sha256=feb9ba3267bdf1f6394c425b45dd71e19ac4382ae05549d6e1b6b664c6517a19 -->
149
+ ## 3.1.1 手机号快速验证前置页不得混淆腾讯官方
150
+
151
+ - 调用手机号快速验证组件前展示的登录页、弹窗、按钮、说明、分享标题和失败提示中,禁止出现“微信”“微信官方”“微信登录”“一键登录”等可能让用户误认为腾讯官方功能或官方产品的文案。
152
+ - 前置页不得使用微信官方 Logo、相似绿色气泡图标、仿官方按钮或其它腾讯官方视觉元素;只允许展示小程序自身主体名称、品牌 Logo 和通用手机/验证图标。
153
+ - 推荐统一使用“手机号快捷登录”“手机号快速验证”“验证中”等中性文案。底层仍按平台要求保留 `open-type="getPhoneNumber"`、`provider:'weixin'` 等技术实现,不能为改文案破坏真实授权链路。
154
+ - `build:mp-weixin` 后必须扫描登录页源码和 `dist/build/mp-weixin/pages/login/` 产物中的可见文案,并对手机号快速验证前置页截图;发现混淆词、官方 Logo 或近似元素时阻止上传和提审。
155
+
156
+ <!-- /microi-progressive:chunk -->
157
+ <!-- microi-progressive:chunk id=microi-mobile-app-quality-007 sha256=7598db1fdabfe127c2be7593b83dc3a246b1db852d9c0d4001f849d3e97aa273 -->
158
+ ## 3.2 微信小程序每个页面默认支持分享
159
+
160
+ 小程序项目必须默认支持转发给朋友和分享到朋友圈,不能只给首页或公开页添加分享。登录和权限控制属于访问阶段,不得用来隐藏分享能力。
161
+
162
+ 要求:
163
+ - 以 `pages.json` 为路由清单逐页接入 `onShareAppMessage` 与 `onShareTimeline`;Vue3 组合式 API 页面必须从 `@dcloudio/uni-app` 直接导入并注册两个生命周期,不能只写一个全局工具后假设编译器会自动发现。
164
+ - 页面显示时确保微信分享菜单包含 `shareAppMessage`、`shareTimeline`;分享标题使用业务标题或稳定页面标题,资讯/报告等内容页优先带预览图。
165
+ - 好友转发返回以 `/` 开头的完整 `path`;朋友圈返回当前页面业务 `query`。保留 `id`、分类、公开报告 ShareToken 等定位参数,剔除 Authorization、AccessToken、CustomerToken、手机号授权码、LoginCode、OpenId、验证码等敏感或一次性参数。
166
+ - 需要登录或角色权限的页面仍允许分享原页面。接收者打开后再由页面鉴权提示登录/无权限,不能把所有受保护页面的分享地址强制改成首页。
167
+ - 登录页本身也必须支持分享,避免接收者被鉴权重定向后失去转发入口。
168
+
169
+ 验收:
170
+ - 静态扫描 `pages.json` 与页面源码,页面总数必须等于同时注册两种分享生命周期的页面数。
171
+ - 执行 `build:mp-weixin`,逐页检查编译后的页面 JS 存在 `onShareAppMessage`、`onShareTimeline`,不能只检查源码或只确认构建成功。
172
+ - 在微信开发者工具和体验版各抽测公开页、登录页、一个需登录详情页:朋友转发和朋友圈入口都存在,接收者路径参数正确;未登录接收者看到登录提示而不是白屏或 404。
173
+
174
+ <!-- /microi-progressive:chunk -->
175
+ ## 详细参考路由(渐进披露)
176
+
177
+ 仅在当前任务涉及对应主题时读取;下列文件合计保留了原 SKILL.md 的全部详细知识。
178
+
179
+ - [references/progressive-01-4-重要按钮必须带图标.md](references/progressive-01-4-重要按钮必须带图标.md):4. 重要按钮必须带图标;4.1 模块列表优先使用声明式业务卡片;5. 首屏文字和浮层不得重叠;5.1 未登录/授权提示必须在可用内容区居中;5.2 自定义导航页面必须通过安全区与微信胶囊门禁;5.3 全屏工具页必须遵守返回状态栈;5.4 微信浮动入口必须通过真实事件桥门禁;6. 后台菜单必须规划为至少两级;7. 移动端页面需要动效,但动效必须有用;8. 登录页必须是直接登录界面
180
+ - [references/progressive-02-9-主题切换必须真实且全局生效.md](references/progressive-02-9-主题切换必须真实且全局生效.md):9. 主题切换必须真实且全局生效;10. 报告/列表详情必须保留用户身份;11. 角色与权限必须基于 sys_user.RoleIds 建模;最终交付清单
181
+ <!-- microi-progressive:end -->