💻 源码本地运行
在本地环境中运行 Microi吾码源码(前端 + 后端)
🎥 视频教程
- 待重新录制上传
- 历史视频教程:https://net.itdos.net:999/sharing/ZBN5cLPKa
一、后端运行
📦 下载源码与 .NET 环境
🛠️ 使用 VS Code 打开解决方案(Mac 推荐)
- 下载并安装 VS Code
- 安装插件:C# Dev Kit
- 打开
/Microi.Server目录,稍等几秒会自动出现【解决方案资源管理器】,等待自动还原 NuGet 库 - 必须配置
/Microi.net.Api/appsettings.json文件
"AppSettings": {
"OsClient": "iTdos",//【必须】自定义SaaS引擎Key,与数据库【sys_osclients】表的【OsClient】字段值对应
"OsClientType": "Product",//【必须】自定义程序运行环境,如:Product(正式环境)、Dev(测试环境)等
"OsClientNetwork": "Internet",//【必须】自定义网络类型,如:Internet(公网)、Internal(内网)等
"OsClientDbType": "MySql",//默认MySql,可选SqlServer、Oracle
//【必须】数据库连接字符串,建议使用源码提供的MySql。同时支持SqlServer、Oracle
"OsClientDbConn": "Data Source=192.168.31.1;Database=microi_empty;User Id=roo;Password=password123456;Port=3306;Convert Zero Datetime=True;Allow Zero Datetime=True;Charset=utf8mb4;Max Pool Size=500;Min Pool Size=5;Connection Lifetime=300;Connection Timeout=30;Pooling=true;sslmode=None;",
//SqlServer连接字符串示例:Server=192.168.31.1,1434;Database=microi_empty;User Id=sa;Password=password123456;
//Oracle连接字符串示例:User Id=MICROI;Password=password123456;Data Source=192.168.31.1:1521/xe;
//Tips:若【OsClient + OsClientType + OsClientNetwork】在【sys_osclients】表中能匹配到数据,且数据中有Redis相关配置,则可以省略以下Redis配置
"OsClientRedisHost" : "",//Redis Host,如:119.31.116.88
"OsClientRedisPort" : "",//Redis端口,如:6379
"OsClientRedisPwd" : "",//Redis密码,如:123456
"OsClientRedisDataBase" : ""//Redis库,如:0、5
//其余配置分布式存储(如阿里云OSS、MinIO)、MQ消息队列、ES搜索引擎等,均在平台【SaaS引擎】中动态配置
},本地与存量部署的 CORS 在未配置来源时默认允许任意来源;只有在 SaaS 引擎主租户的 CorsAllowOrigins 中填写来源后才收紧。严格 SSRF 模式同样默认关闭,并由主租户 SsrfProtectionEnabled 控制。不要为了本地调试删除登录 RSA 历史兼容密钥或私有授权密钥;完整规则见 平台安全与兼容基线。
注意事项
- 公开源码使用
Microi.Server/Microi.net.sln;五个闭源库由Directory.Build.props指定的同平台版本 NuGet 提供,不要单独替换其中一个 DLL。 - 还原失败时先查看第一条错误;项目未加载、方案缺项和 SDK/IDE 不兼容与网络故障应分别排查,步骤见下方。
- 右键
Microi.net.Api项目 → 调试 → 启动新实例 - 访问地址:
https://localhost:7266(端口在/Microi.net.Api/Properties/launchSettings.json配置)
🖥️ 使用 Visual Studio 2026 打开解决方案(Windows 推荐)
- 安装 Visual Studio 2026 及“ASP.NET 和 Web 开发”工作负载,使用其配套 .NET 10 SDK。
- 打开仓库中的
Microi.Server/Microi.net.sln,等待全部项目加载,右键解决方案执行“还原 NuGet 程序包”。Microi.Anderson.sln是创建人完整源码入口,不适用于公开源码。 - 确认
Dependencies与Tests/Fixtures内的项目没有被卸载;还原成功后,将Microi.net.Api设为启动项目并生成。 - 必须配置
Microi.Server/Microi.net.Api/appsettings.json,说明同上。
.NET 10 与 IDE 版本
.NET 10 SDK 10.0.1xx 至少需要 Visual Studio 2026 18.0;后续 SDK 功能带应搭配对应更新的 IDE。Visual Studio 2022 17.14 不支持以 net10.0 为目标,即使另外安装 .NET 10 SDK 仍会出现 NETSDK1233。可升级 IDE,或使用 .NET CLI / VS Code。详见 Microsoft SDK 与 Visual Studio 版本矩阵。
拉取源码后出现 NU1105 / NETSDK1004
NU1105 的“找不到项目的信息”不一定是 NuGet 服务器故障。Visual Studio 还原需要解决方案完整列出项目引用链;仅有磁盘上的 .csproj 不够。NETSDK1004 表示对应项目的 obj/project.assets.json 尚未生成,应先修复还原错误。
- 更新并重新加载
Microi.Server/Microi.net.sln。方案包含 MongoDB 驱动、NPOI 及其四个子项目、Panel、MemoryDiagnostics 和两个独立测试夹具;这些都是公开项目,不需要获取闭源仓库。 - 若文件不存在,核对拉取的提交、稀疏检出配置或 ZIP 解压是否完整;若文件存在,检查是否仍打开旧方案或卸载了项目。不要删除项目引用、关闭诊断功能或复制他人的
obj来绕过还原。 - 在仓库根执行以下命令。还原报错时先处理该错误,再重新生成;命令行通过后仍须使用受支持的 IDE 加载方案。
dotnet --version
dotnet restore Microi.Server/Microi.net.sln
dotnet build Microi.Server/Microi.net.sln -c Debug --no-restore⚙️ 配置必须参数
最低要求
要使项目跑起来,至少需要 数据库 + Redis 两个环境,缺一不可。
独立端口复现历史 SQL Server 数据库
多人共用工作区时,可使用独立的 appsettings.SqlServerLocal.json、编译配置和端口,避免修改其它进程正在使用的 .microi-local。该文件按现有本地配置规则忽略,数据库凭据不得提交到仓库;AppSettings 仍只配置上文的租户、数据库、Redis、MongoDB 十项基础连接参数。测试副本应使用独立数据库与缓存,避免与同名正式租户共享会话和升级锁。
以下 PowerShell 命令在 Microi.Server/Microi.net.Api 目录执行,先确认端口未被占用:
$env:ASPNETCORE_ENVIRONMENT = 'SqlServerLocal'
$env:DOTNET_ENVIRONMENT = 'SqlServerLocal'
dotnet build -c SqlServerLocal -m:1 -p:UseSharedCompilation=false
& './bin/SqlServerLocal/net10.0/Microi.net.Api.exe' --urls 'https://localhost:61631'SQL Server 的 15.0.2000.5 对应 SQL Server 2019 RTM。还原脚本前应区分 .bak 备份与 SQL 导出脚本,并检查后者是否包含 INSERT 数据;只有 CREATE TABLE/ALTER TABLE 的脚本不能恢复客户账号、配置或业务记录。为这种脚本补入的测试账号和数据必须在验收报告中单独标明。
升级时先修复登录和接口执行所需的核心物理列与自描述元数据,再通过当前基础应用包交付表、字段、接口和运行资产。SaaS 包提供应用文件、版本和微服务页面结构,必须先于商城资产安装。旧版 MySQL 专用升级 SQL 不再直接重放到 SQL Server;任何 DDL 或应用安装失败都停止并保留原 ServerVersion。排查时记录首个失败阶段,修复后重复执行并回读字段、应用版本和业务数据,不能通过手工提高版本号跳过错误。
SQL Server 的宿主配置建议使用 OsClientDbType=SqlServer。历史名称 SqlServer9、mssql 及其大小写变体会在主租户配置重投影、子租户运行模型和共享缓存快照中统一为 SqlServer,底层连接仍使用支持现代分页的 Provider。排查 Upgrade21-持久后台任务 报“创建或接管后仍无法读取 diy_table 元数据”时,也应核对进程环境变量中的 OsClientDbType:它优先于本地 JSON,旧代码可能在重读配置时把历史别名写回运行模型。使用修复后的后端可保留原配置并从失败位置重启;尚未更新时,可先统一为 SqlServer 后重启。兼容验收需要覆盖公开源码加 NuGet 的实际交付方式、旧版本号、升级失败后的原库与旧缓存,不能只验证完整源码下的全新初始化。
已有列还必须满足启动协议的最小容量。旧 SQL Server 导出中的 sys_menu.SelectApi/ExportApi 可能只有 nvarchar(50),ImportApi/ImportProgressApi 可能只有 250 字符;后端会在登录前物理门禁及旧 DiyConfig 回填前检查并扩容到既有协议要求的 255 字符,已达到当前数据库版本的主租户也会经过这个小范围门禁。扩容保留原 varchar/nvarchar 类型、排序规则、默认值和可空属性,不收缩更宽的列或 MAX/text/ntext。普通非分区筛选索引阻止扩容时,在同一事务内保留并重建其定义、包含列、排序和存储选项;DDL 失败则回滚并阻止升级成功。验收必须同时检查列存在性、字符容量以及旧 DiyConfig 中超过 50/250 字符地址的完整回填,不能用无数据的结构导出代替历史内容验证。
SQL Server 验收还应覆盖 Unicode 文本、带单引号的创建人姓名和原生日期字段清空。表单引擎参数化写入创建人身份;新建文本列使用 Unicode 类型,原生日期的空输入保存为 NULL。应用文件唯一索引只约束非空 VersionId 的发布文件,允许不同应用保留同名的当前源码;已到达当前数据库版本的租户也会在分布式租约内修复旧的未过滤索引,继续跳过历史迁移链。
已有 varchar 列还受 SQL Server 排序规则的字符集限制。SaaS 包在 diy_lang 的物理文本列上声明 SQLSERVER_UNICODE: true,由商城导入器转换为足够宽的 Unicode 类型,保留目标排序规则、可空性、默认值和普通索引;引用表或未声明的业务列不执行这种转换。字符已经变成问号时,原文无法由类型转换恢复,需要从可靠备份或已知的系统元数据重新生成,不能猜测覆盖客户词条。原始数据库重放验收应同时检查物理类型和中文实际回读。
📝 环境配置注意事项
| 环境 | 影响功能 |
|---|---|
| 无 MongoDB | 系统日志暂存到后端 spool,MongoDB 恢复后自动重放;持续不可用时无法在系统日志页查询 |
| 无 MinIO / 阿里云 OSS | 无法使用文件/图片上传 |
| 无 RabbitMQ | 无法使用消息队列 |
| 无 Elasticsearch | 无法使用搜索引擎 |
系统日志 spool
生产/容器环境请将后端固定目录 logs/syslog-spool 挂载到持久卷。该目录用于 MongoDB 故障和服务正常重启时的日志重放,不应放在容器临时层。节点标识由平台根据当前节点自动生成,不需要增加环境变量;所有节点连接同一 MongoDB 时按全局 EventId 幂等写入。
🧪 后端自动化测试与发布门禁
测试与发布会自动回收自己新建的临时文件。Full 保留测试报告和 artifact-cleanup.json,删除本轮 .net-artifacts;一键发布将构建、pack、冒烟日志及 NuGet 替换临时目录统一放入结果目录的唯一 release-scratch-*,退出后保留同级 .cleanup.json 小回执。已有目录、其它任务工作区和未提交源码不会因本轮使用而取得删除权。
API 发行冒烟临时使用所选本地配置的十个基础设施 AppSettings 字段,不复制 DevLoginBypass,也不修改源配置。退出时先恢复公共配置原始字节,再回收临时文件;恢复失败会停止发布并保留证据。产物复用、Docker 构建及上传前还会检查公共模板的字节与哈希,拒绝环境配置或冒烟备份进入发行包;镜像配置只按不可变 imageId 静态读取,不启动测试容器。
Windows 清理采用普通 PowerShell 删除,先检查真实路径、祖先链接、Git 标记、受保护属性和文件占用,不默认使用 -Force。清理失败保留归属清单及错误,不升级为强删;发布原失败码保留,原成功但清理失败则返回非零。blocked by policy 若发生在 shell 启动前,脚本内检查与收尾均未执行,应先定位当前执行器和拒绝阶段;不要改 ACL、清除属性或换工具绕过。硬杀或掉电后需按归属清单重新核验并补清,不能整体清空共享 .tmp。
后端测试统一位于 /Microi.Server/Microi.Tests。它合并了历史 Dos.Common.Tests、Dos.ORM.Tests,并在私有源码存在时条件纳入 AI、 FormEngine、ApiEngine、安全与多租户边界测试。
日常开发先运行不连接服务器、不会写数据库的 Quick 门禁:
.\Microi.Server\Microi.Tests\run-tests.ps1 -Mode Quick吾码完整正式发布默认执行 Microi一键编译发布.sh --platform-release(菜单默认完整选项):版本号按原规则 +1 一次,发布 NuGet、API Docker、PC Docker 和官方网站文档/Docker。完整入口通过 PlatformRelease 执行常规 Microi.Tests(平台单元/组件,不自动追加 Full 专项)、吾码前端通用 Node 测试、真实接口检查与最终加密产物启动/运行冒烟;扩展浏览器验收仅在显式传入 --platform-frontend-tests 时追加。真实付费 AI、鸿地/JUNCHI、XJY 等指定客户数据专项和 SQL Server 等独立提供商专项默认不纳入,不再逐次询问;只有用户另行明确要求专项时才执行,回执逐项列为“不适用/未执行”,不能冒充通过。常规门禁通过后完成 Release 编译、闭源 DLL 加密、最终产物冒烟与各渠道回读。默认从 .microi-local 选择项目配置并复用已有 MySQL、Redis、MongoDB、MinIO/OSS,使用本机程序验证,不另建 Docker 测试依赖或临时官网运行容器;既有测试授权保护仍有效,缺前置条件不能静默跳过。整体以 30 分钟为耗时目标,超出时记录瓶颈并继续推进至成功,真实错误、取消及单操作超时仍保留。不混入 Microi Code/Agent 独立产品测试,不新建租户、不安装聊天应用。源码拉取、合并、冲突解决和提交推送按需补齐;仅明确要求局部发布时才缩小渠道。
完整入口自动复用本机持久的已授权测试配置,默认位置为工作区 .microi-e2e/platform-release/profile.json。该目录必须被 Git 忽略,并限制为当前用户和系统可读写;首次准备只从 .microi-local 对应的既有项目配置和明确的测试授权范围保存配置、归属及端口,不复制旧 Token,不创建租户、数据库、容器或应用。凭据只留私有文件,不写命令参数、源码或日志。隔离候选可通过发行进程变量 MICROI_PLATFORM_RELEASE_PROFILE 指向同一份稳定配置,不依赖历史 .tmp。
脚本在同一轮计时内管理原生转发和本轮实际构建的 API/Vite,测试子进程自动读取私有环境。浏览器测试结束后停止自有 API/Vite,依赖转发继续供最终加密产物冒烟使用,完整脚本退出时再收尾;已有外部监督进程通过 MICROI_PLATFORM_RUNTIME_CONTROL 显式复用,局部前端/仅官网入口不会因此要求写库凭据或启动 API。
可先只读验证持久配置与既有测试归属,不启动服务或写入测试数据:
node Microi.Server/tools/platform-release-runtime.mjs dry-preflight <工作区绝对路径> [profile绝对路径]新完整发布仍默认递增版本一次。中断后按脚本给出的会话路径恢复:
PlatformRelease 先执行 C# 编译和组件测试,再执行四组平台 Node 回归;编译失败会在 启动耗时 Node 组之前返回。所选用例、零跳过要求和最终产物门禁保持完整。
bash Microi一键编译发布.sh --platform-release
# 修复失败步骤后,使用本轮提示的原会话文件:
bash Microi一键编译发布.sh --resume=<本轮session文件的绝对路径>恢复会话沿用版本、渠道、冻结候选、原始测试和累计起点。脚本重新核验 TRX/TAP、制品字节与远端镜像摘要,只上传未完成的包或标签;已完成官网构建也可复用。源码、配置、渠道或证据变化会明确拒绝复用,不自动重测或覆盖已发布内容。--release-version=x.y.z 只指定版本,本身不复用执行结果;禁止截取脚本尾部续发。官方资源 HTTP 524 先回读再补差异,不能因此重新执行整套测试。配置或归属缺失按实际错误修复,不能把启动配置自动解释为业务写入授权。
若测试失败后必须修复源码,且本会话尚无任何成功测试、构建或渠道回执,可显式重新冻结:
bash Microi一键编译发布.sh --resume=<原session绝对路径> --refreeze-unaccepted-candidate原入口先检查旧候选证据和阶段状态,保留旧候选与原始 TRX/TAP,在同一会话记录历史指纹, 沿用原版本、渠道与累计起点,重新运行完整门禁。有任一成功阶段时拒绝此开关;默认续发 仍拒绝源码漂移,不把失败用例或旧候选结果换签为通过。Windows 会话原子替换遇到短暂 文件占用时只作有界重试,不删除目标会话或降级覆盖。
只有明确选择 Full 深度测试时,才对隔离测试租户和专用测试表运行下列独立入口;它不属于普通发布前置条件:
$env:MICROI_TEST_API_BASE = "http://127.0.0.1:1052/"
$env:MICROI_TEST_OSCLIENT = "integration-test"
$env:MICROI_TEST_TOKEN = "<测试租户超级管理员Token>"
$env:MICROI_TEST_FORM_ENGINE_KEY = "mci_release_gate"
$env:MICROI_TEST_API_ENGINE_KEY = "release_gate_echo"
$env:MICROI_TEST_CHILD_OSCLIENT = "integration-child"
$env:MICROI_TEST_CHILD_TOKEN = "<子租户测试管理员Token>"
$env:MICROI_TEST_FRONTEND_BASE = "http://localhost:61500"
$env:MICROI_TEST_ACCOUNT = "<主租户测试账号>"
$env:MICROI_TEST_PASSWORD = "<主租户测试密码>"
$env:MICROI_TEST_CHILD_ACCOUNT = "<子租户测试账号>"
$env:MICROI_TEST_CHILD_PASSWORD = "<子租户测试密码>"
$env:MICROI_UPGRADE_TEST_CONN = "<127.0.0.1:62606 上 upgrade_fixture 独立 MySQL 测试库连接>"
$env:MICROI_UPGRADE_SQLSERVER_TEST_CONN = "<127.0.0.1,62616 上 upgrade_fixture 独立 SQL Server 测试库连接>"
$env:MICROI_TEST_ALLOW_WRITES = "YES"
.\Microi.Server\Microi.Tests\run-tests.ps1 -Mode FullFull(显式深度测试)会依次执行:
- Release 恢复与编译、全部 Quick 单元/组件回归。
- FormEngine 单条、批量、按条件新增/查询/计数/修改/删除的真实 HTTP 闭环。
- ApiEngine 的 GET、JSON POST 调用。
- 以唯一前缀清理本次测试数据,并输出 TRX/覆盖率结果。
- MySQL/SQL Server 结构升级、主租户指定子租户的平台应用维护、子租户安装/更新全部平台应用、幂等重复提交和
Succeeded/100%终态;再次执行时应为Planned=0。 - 在独立浏览器 Context 中使用真实账号密码登录,验证通知中心按钮和后台任务完成;官方 iTdos 发布源应隐藏给自身安装应用的按钮。
- NuGet 易受攻击包和弃用包审计。
一键编译发布脚本在后端发布、前端构建和“仅推送镜像”模式使用 PlatformRelease;所选项缺少必需输入、零用例、失败、取消、跳过或待办均停止发布。取得所选产品发布锁后准备本次版本并冻结候选,复用已验证构建产物,续发同一候选不重复升版。显式 Full 的真实依赖、租户维护和浏览器深度测试单独运行,不能自动加入普通发布;Microi Code/Agent 与 VS Code 扩展使用独立产品入口。文档专用选项 6 不触发后端业务测试。实际进入后端镜像的 MCP 运行包仍须通过 TypeScript 编译、生产依赖裁剪和自包含包检查。
macOS 可使用 bash Microi一键编译发布.sh 的选项 6 发布官网。Docker 与端口探针优先使用 timeout / gtimeout,系统未安装时自动使用仓库内的 Node 时限工具,避免将正常 Docker 误判为启动超时。该模式只构建和推送官网镜像,不发布 DLL 或 NuGet;后端发布仍须通过原有加密和冒烟门禁。
搜索标签的真实浏览器验收默认覆盖 1366px 和 1920px 常规桌面。只有测试进程显式设置 MICROI_TEST_BROWSER_4K=1 时才追加 3840px;所选宽度冻结进显式 Full 或浏览器专项回执,所有所选用例均须通过且不得跳过。该变量仅控制测试,不是生产 API 配置。正式发布和同版本 Docker 热修复都拒绝历史 --skip-tests / SmokeOnly 路径,最终产物冒烟仍是 PlatformRelease 编译与平台自动化之后的独立必需检查。
后端 DLL 加密在 macOS/Linux 使用原生绝对路径;仅 Git Bash、MSYS 或 Cygwin 转换 Windows 路径,优先使用 cygpath,避免把 /Users、/usr 误识别为盘符。路径修复应先在隔离构建副本上验证五个 DLL 的实际加密和指纹,然后重新执行一键脚本的 PlatformRelease、加密及最终产物冒烟。
加密脚本被 source 引入以测试路径函数时不执行发行入口。SQLite 回归使用真实解释器及隔离标准库:Windows 选择 python,避免 python3 命中商店占位程序;其它系统使用 python3。包投影和 Manifest 内联源码使用 Git 指定的 LF 字节;官方资源目录中全部 JavaScript 接口、表事件和 Hook 模板也按 LF 检出,保持与包正文及声明摘要完全一致,不修改断言来忽略换行差异。缺少已发布的运行产物时,可以从相同版本的包正文按大小与 SHA-256 恢复制品,但恢复记录不能替代源码构建证据。
在线 AI 使用的 MCP 按依赖锁干净安装、编译和裁剪,再完整复制生产运行目录。生产命令的链接解析为真实文件并保留执行权限,使临时目录清理后命令仍可运行;损坏、越界和循环链接提前拒绝,重新打包不保留旧依赖。制品门禁继续拒绝符号链接,不能通过放宽门禁解决打包错误。
平台内置微服务的 Vue 生产样式标识和源码清单都依赖原始文件字节。其唯一源码目录通过 Git 属性禁用自动换行转换,按提交记录原样检出;不要按操作系统把整份源码改写为 CRLF 或 LF。新工作树需从锁定依赖真实构建 dist,再同时核对内嵌运行文件和源码清单。运行文件完全相同而源码清单漂移时,仍须用原始打包器修复清单并重新验收,不能删除校验或把旧包还原当作本轮构建通过。打包器写入完整包后自动刷新最小启动恢复投影,继续使用原生成器白名单;--verify-only 同时校验恢复 JSON 与导入脚本,漂移时拒绝且不改写文件。完整包、恢复投影和源码清单一致后再冻结 Full 候选。 前端构建在 macOS 使用有界 vm_stat 探针,按当前页大小统计空闲页与可回收文件页,不把文件缓存误判为构建占用,也不叠加匿名非活动页、压缩页或已包含的预读页。探针失败或格式未知时回退到原生空闲内存;Windows/Linux 保持原统计方式。可回收页的口径参考 Apple 内核内存说明。
吾码 PC 默认现代构建保留 6144 MiB Node 堆,按 5632 MiB(5.5 GiB)进程树预算加 max(1 GiB, 物理内存 3%) 系统余量准入:32 GiB 主机约需 6.5 GiB 空闲,64 GiB 主机约需 7.42 GiB。全机占用达到 97% 时暂停本轮构建进程树,降至 95% 以内并连续稳定五秒后恢复,正式发布继续执行这项保护。
低于 8 GiB 的宿主仍至少保留 1.5 GiB 系统余量;宿主限制或自定义设置改变堆大小时,改按实际堆与有界原生开销保守估算。串行压缩和 legacy 阶段也使用堆加原生开销,保留 768 MiB 原生下限,不叠加顺序阶段峰值;32 GiB 主机上两阶段启动目标分别约 3.25/3.75 GiB,堆仍为 1536/2048 MiB。
每个新增或修复都要补回归测试:C# 测试进入 Microi.Server/Microi.Tests;该入口自动发现测试项目、应用包 Resource 与前端 Microi.Client/tests 的确定性 Node 用例。真实浏览器和数据库仍使用 Full 的隔离环境入口,不能把 skipped 当作通过。
通过测试的候选源码和 Docker 构建上下文都会保存内容哈希回执,每次推送前重新校验。仅推送时没有回执或发现源码/产物变化会拒绝上传,必须重建重测,防止“当前源码测试通过、上传的却是旧 DLL/dist”。
后台发行需要静态组合私有原生规则时,不能依赖根公开仓的文件清单覆盖被忽略的应用源码。发布进程设置 MICROI_RELEASE_COMPOSITION_FILE 指向工作区内的受控 JSON 契约,格式为 schema:1,包含 properties、files、directories、artifacts。properties 必须固定 CustomAfterMicrosoftCommonTargets、PrivateRulesProject、ApprovedRulesBootstrapSource、MicroiCoreProject 四个文件路径,并与同一发布进程传给 MSBuild 的实际环境属性一致;这些文件必须同时进入 files 或 directories。
files 列出项目、组合 targets、静态审批代码等文件;directories 列出应用自己的规则源码目录。契约原始正文和这些输入逐文件加入发布候选,新增、删除或修改均触发重新验收;禁止越界路径和符号链接,bin/obj/dist 等生成目录不作为源码。artifacts 使用 { "path":"publish/ApprovedRules.dll", "sha256":"<后台审批的实际DLL哈希>" } 描述获批制品,最终 API 发布目录必须逐项匹配,缺失或不同均阻止捕获和推送。普通无私有组合的发布和 PC 制品沿用既有门禁。这些变量只供构建,不是生产 API 设置,也不授予 V8/MCP/HTTP 任意加载代码的权限。
发行组合的进程环境只绑定工具所在的工作区。临时测试仓库或其它源码根须显式传递自己的环境,不能继承另一发行任务的私有路径;显式配置错误仍立即失败。
Skills 的渐进披露清单校验原始 UTF-8 字节。根 .gitattributes 固定 microi.skills Markdown 与清单为 LF,避免 Windows checkout 改变摘要。拉取后运行 node microi.skills/scripts/validate-progressive-disclosure.mjs 验证完整正文;确实修改规则时,仅对已审阅的 Skill 使用 refresh-progressive-disclosure.mjs <名称> 更新清单,再同步插件与后端知识快照。不要用批量重签摘要掩盖未审阅的正文变化。
私有原生规则的依赖审批必须核对实际目标 Linux CLR 中的完整程序集引用链,不能用 Windows 框架文件或“某次业务调用未使用”代替。发行缺少、身份冲突或哈希不匹配时,保持失败关闭并修复依赖交付。例如 Oracle Core 23.26.300 声明引用 Azure、Kerberos、OCI、ConfigFile、AWS、GCP 六个扩展,Dos.ORM 同时引用六份同版本官方包,由 NuGet 交付它们及其传递依赖;ProviderDependencyDeliveryTests 只验证真实 CLR 装载,不连接 Oracle 或云服务。修复后重新运行目标运行时依赖验证、Full 及最终镜像回读,不在 V8 或生产配置中提供任意 DLL 装载入口。包说明见 Oracle Azure 扩展 和 Oracle OCI 扩展。
依赖统一也要覆盖存量模块:MongoDB 兼容构建与 NuGet 包声明共同使用 DnsClient 1.7.0,以满足 Azure 配置提供者的版本下界;MongoDB 3.6/7 的真实验收仍由 Full 执行。OCI 带有独立强名称的旧密码学程序集,微信支付继续使用 BouncyCastle.Cryptography 2.6.2;测试通过显式程序集别名断言原来的认证标签篡改异常,避免同名类型导致编译歧义,不改变运行时密码学协议。
Oracle AWS 扩展的实际程序集还引用 SQS,尽管其 NuGet 清单只列出 S3、SecretsManager。Dos.ORM 显式交付 AWSSDK.SQS 4.0.100.15,HDFS 的 AWS Core 引用同步至其下界 4.0.102.8,避免旧直接引用触发包降级。Oracle 回归递归验证完整扩展引用链并保留 512 个程序集预算;不访问 AWS 或申请凭据。
System.Drawing.Common 的 .NET 10 支持程序集还引用 System.Formats.Nrbf;该文件不在 ASP.NET Core 共享框架内,Dos.Common 显式交付同版本官方 NuGet 包,并由上述回归验证引用与文件。Windows GDI 的运行平台限制不变;Linux 图像处理继续使用 SkiaSharp。依赖可解析不等于在 Linux 执行 Windows 绘图 API。
共享源码持续变化时,可将完整候选源码及依赖保存到独立发布目录,在那里运行同一 PlatformRelease 和一键发布脚本。专用测试服务使用独立端口,并通过发布脚本变量 MICROI_RELEASE_BACKEND_PORT、MICROI_RELEASE_FRONTEND_PORT 指定收尾端口,默认仍为 61501、61500。进程管理器继续检查 PID、命令行和工作区归属;原工作区服务不受影响。这两个变量仅用于发布脚本,不是生产 API 配置。
Windows Git Bash 的 MSYS PID 与 Windows 原生 PID 不同。一键发布先用真实 ps 的 WINPID 映射登记 API、PC、官网或 Agent 发布锁,退出时用同一个原生 PID 和令牌释放。映射缺失、重复或进程已退出均停止发布;不借用其它存活进程。旧 API 热修复归属检查以 UTF-8 读取中文入口,并核对实际工作区路径,不仅依赖锁中的标签。
进程管理器在 PowerShell 5 和 7 中显式设置 UTF-8 控制台与管道输出,避免 Git Bash 继承 Windows 旧代码页后出现中文诊断乱码。编码不影响锁校验和停止范围;修复后仍须 通过真实 PowerShell、Git Bash 回归及完整 Full,不能通过忽略错误文字来放行。 API、PC 框架、官网和 Microi Agent 各自使用 .tmp/microi-process-state/ 下的 api-release.lock、pc-release.lock、website-release.lock、agent-release.lock,可以同时发布;同类发布互斥。合并发布只取得所选产品的锁,部分取得失败会撤回本次已取得的锁。API 服务启动前执行 node Microi.Server/tools/release-lock.mjs assert api <工作区根>,PC 使用 assert pc,或通过进程管理器 AssertServiceStart -ReleaseScope api|pc|all 检查。Windows 发布准备按相同范围清理:API 处理后端及 Release DLL,PC 处理 Vite,官网不停止二者。
PC/API 普通发布使用 PlatformRelease,Full 保留为显式深度测试;两者的 .NET restore、build、test 与依赖审计使用本次结果目录的 .net-artifacts,并行发布使用独立结果目录和本轮所需服务/端口,普通发布不创建租户。官网的全部源码、主题、测试和依赖由官网发布验收,不影响 PC/API 的候选一致性;共享 SDK、Skills、MCP 与发布工具仍受候选保护。共享版本和跨产品改动应先准备并冻结,再并行发布。资源排队按实际并行阶段预算之和与系统余量判断,不再因无关产品占用一个全局窗口而等待。 macOS/Linux 的进程管理器同时识别项目 bin/ 和当前工作区 .tmp/microi-release-gate/日期-时间-PID/.net-artifacts/bin/Microi.net.Api/debug|release/ 下的规范 API apphost;后者仍要求 API 项目 CWD 精确一致,其它工作区、任意输出目录、路径越界或无法回读身份均拒绝停止。
旧 platform-release.lock 或 release.lock 仅在 PID 的真实命令入口和共享状态目录证明属于 API 热修复或 Agent 时缩小阻塞范围;未知归属继续保守保护。原进程和唯一令牌释放自身锁,不能删除其它正在运行的发布锁。
进程管理器也支持通过 PowerShell 7 检查 macOS/Linux 的真实监听进程、命令行和工作目录;路径按大小写精确匹配,结束前再次核对启动时间,拒绝 PID 复用。dotnet run 启动的无扩展名 Microi.net.Api apphost 还必须使用规范绝对路径,位于所选 API 项目的 bin/ 下,且工作目录精确等于该项目;相同名称、其它目录、路径中的 ./.. 或无法读取启动时间都不能作为可停止的身份。只能停止已证明属于所选工作区的 API/Vite 及其后代,无法读取身份时停止操作。一键脚本仅处理所选发布范围的共享开发服务;跨平台回归使用独立目录和端口,不以模拟对象代替真实进程。
主、子租户必须在同一维护控制面的有效租户目录中;必要时用 MICROI_TEST_CONTROL_API_BASE、MICROI_TEST_CHILD_API_BASE 指定各自入口。详细变量和测试边界见源码 Microi.Server/Microi.Tests/README.md,报告应区分本地候选与已部署远端的结果。
这里的主、子租户仅用于显式 Full 深度测试,普通 PlatformRelease 不创建租户或安装聊天应用。官方应用发布与升级仅验收 https://api.microi.net 的主租户 iTdos(microi_itdos);线上子租户的安装版本、升级成功与否不属于平台发布完成条件,不因正式发布批量升级线上子租户。通过 AI 提示词或直接运行 Microi一键编译发布.sh 均遵守这一边界;普通用户只在自身授权范围执行,脚本不会授予官方母版写入或客户自动部署权限。
测试表至少包含一个可写短文本字段(默认 Name,其它名称可通过 MICROI_TEST_NAME_FIELD 指定)。MICROI_TEST_ALLOW_WRITES=YES 是强制保护, 禁止对生产租户设置。测试通过能显著降低发布风险,但不等于证明所有客户 V8、第三方接口、生产数据和基础设施绝对无误;正式发布还要用两个 API/Worker 节点连接同一 Redis/数据库,覆盖重复投递、锁持有者退出、依赖短暂故障、 响应前重启和滚动升级。
🐳 本地编译发布到 Docker 镜像
- 安装 Docker Desktop
- 在
Microi.net.Api项目目录下执行:
dotnet clean && dotnet publish -c Release -o ./bin/Release/publish- 进入
./bin/Release/目录,执行publish-demo.sh脚本(记得先修改里面的配置)
二、前端运行
📦 下载源码与开发工具
# 记住安装路径,一路往下安装即可
# 打开 nvm安装路径(我的是【D:\Users\Administrator\AppData\Local\nvm】),找到 settings.txt 文件,新增2行配置
node_mirror: https://npmmirror.com/mirrors/node/
npm_mirror: https://npmmirror.com/mirrors/npm/
# 打开cmd窗口,执行
nvm list available
nvm install 18
nvm install 14
# 常用命令
nvm ls
nvm use 18
node -v▶️ 运行前端源码
- 在 VS Code 打开
/Microi.Client/文件夹 - 查看
/Microi.Client/README.md,执行以下命令:
nvm use 20
nrm use taobao
npm install
npm run dev指定或切换 ApiBase 与 OsClient
Microi.Client/src/config.json 的 ApiBaseDev 是本地 Vite 的默认 API 地址。开发服务器默认使用 http://localhost:61500,可在主框架 URL 的 # 之前临时指定目标租户和 API:
http://localhost:61500/?OsClient=iTdos&ApiBase=https%3A%2F%2Fapi.example.com#/首页或菜单路由ApiBase 建议用 encodeURIComponent 编码。ApiBase 可以包含路径,例如 https://api.example.com/v2;只允许完整的 http:// 或 https:// 地址,不能包含账号密码、额外 query 或 hash。OsClient 与 ApiBase 都不是登录凭据,Token、密码和访问密钥禁止放进 URL。
运行时取值顺序如下:
| 优先级 | ApiBase | OsClient |
|---|---|---|
| 1(最高) | 当前 URL 的 ApiBase | 当前 URL 的 OsClient |
| 2 | index.html 的 window.ApiBase | index.html 的 window.OsClient |
| 3 | src/config.json 的 ApiBaseDev | 按当前域名向 API 解析,成功后更新状态 |
| 4 | 当前 Pinia/localStorage 状态;最后回落同源 | 域名解析失败时显示错误,不使用默认租户继续启动 |
URL 参数决定当前页面的运行目标,不需要反复改 config.json。平台初始化和登录仍会把运行状态 写入当前浏览器的同源持久化存储,因此并行租户仍必须按下文隔离浏览器。跨域连接远端 API 时, 目标租户还必须允许 http://localhost:61500 的 CORS;否则参数已正确生效,浏览器请求仍会被 CORS 拦截。
页面完成租户初始化后会公开一个不含 Token 的只读诊断对象,AI 和测试脚本可直接读取:
window.__MICROI_RUNTIME_ENDPOINT__
// {
// protocol: 'microi.runtime-endpoint.v1',
// apiBase: 'https://api.example.com',
// osClient: 'iTdos',
// source: { apiBase: 'url-query', osClient: 'url-query' }
// }后端健康但页面提示导航中止
Navigation aborted ... via a navigation guard 表示前端守卫取消了导航,并不能直接证明后端断网。 先确认上面的实际 ApiBase/OsClient,再检查浏览器网络面板中的当前用户与菜单接口响应。
若 /apiengine/platform-current-user 返回“无法确认接口配置”,还要检查旧登录态: 同源浏览器缓存可能保留其它租户的 Token。页面 URL 写了 OsClient=iTdos,不代表每个 API 请求 已经携带这个值。更新后的请求层会给当前 API 的请求补齐 osclient 请求头,同时保留请求本身 显式指定的其它租户,避免路由阶段按旧 Token 选择错误租户。旧会话无效时正常进入登录页, 重新登录后继续原链接,无需清空整个浏览器缓存。
首次域名解析尚未确定租户,因此匿名发现请求不会自动携带 iTdos 或旧缓存租户; 由当前 API 的主租户解析站点域名。没有 URL 或部署配置指定租户时,每次启动重新解析域名, 可自动修复此前失败写入的租户缓存。配置返回业务错误时保留具体提示,不因健康检查正常而循环刷新。 登录后保留完整深链接的查询参数和锚点,包含微服务页面的记录 Id、编号等。
更新后的前端会对身份和菜单初始化的短暂读取失败最多尝试三次,间隔 300/1000ms。 登录失效会返回登录页并保留原链接中的记录参数;权限拒绝与已经耗尽的菜单依赖重试不会重复请求。 持续失败时,启动页显示具体的身份或菜单错误,可修复对应配置后点击“刷新重试”。 启动身份确认只由守卫统一处理,后台用户刷新等待首次导航完成;重试不再堆叠全局错误弹窗。 本地开发复用 Vite 热更新即可,已有错误页请刷新;正式环境需部署包含此修复的前端产物。
如果出现“后端 API 服务暂时不可用”页面,前端每轮检测结束 5 秒后会自动重试固定健康接口。 服务恢复后,启动失败的页面自动重新进入原地址;已打开的业务页面撤掉异常层并保留输入。 “重新连接”可立即检测,之前失败的保存、打印等业务请求不会自动重复提交。
多租户并行测试必须隔离浏览器存储
同一浏览器配置文件下,相同 http://localhost:61500 源的 Tab 和窗口共享 localStorage、Pinia 持久化数据、Token、CurrentUser、ApiBase 和 OsClient。A 窗口登录租户 A 后,再让 B 窗口切换到 租户 B,A 窗口可能被新 Token/用户状态污染,表现为自动切租户、身份失效、请求发往错误服务器或 页面白屏。URL 参数优先级不能隔离共享的登录态。
并行测试规则
- 人工测试第二个不同
ApiBase + OsClient时,至少使用无痕/隐私窗口;更稳妥的是独立浏览器 Profile 或独立--user-data-dir。 - 同一 Chrome 进程中的多个无痕窗口可能共享同一个临时无痕会话。三个以上并行租户不要只开多个 无痕窗口,应为每组目标使用独立 Profile/浏览器进程。
- Codex、Playwright 等自动化必须为每个
ApiBase + OsClient创建独立browser.newContext(),不得在同一个 context 中用多个 Page 混测不同租户;结束后只关闭自己 创建的 context/browser。
AI 从线上页面识别目标后在本地复现
AI 收到一个已部署吾码页面地址时,应先在一次性独立浏览器上下文打开线上页面,等主框架完成 初始化,再读取 window.__MICROI_RUNTIME_ENDPOINT__。旧版本尚未提供该对象时,按顺序读取 URL 参数、window.ApiBase/window.OsClient、同源 localStorage 的 microi.net.ApiBase/OsClient;若 OsClient 仍为空,再以线上域名调用平台租户解析接口或从已成功的平台请求中确认,不能猜租户。
确认目标后,使用新的独立浏览器上下文打开本地源码:
const localUrl = `http://localhost:61500/?OsClient=${encodeURIComponent(osClient)}`
+ `&ApiBase=${encodeURIComponent(apiBase)}#/目标路由`;
const context = await browser.newContext();
const page = await context.newPage();
await page.goto(localUrl);远端识别、本地源码构建、浏览器页面验收和生产部署是不同证据层;本地参数切换成功不表示线上已 部署新源码。
- 常见问题
npm : 无法加载文件 d:\nvm4w\nodejs\npm.ps1,因为在此系统上禁止运行脚本。有关详细信息,请参阅 https:/go.microsoft.com/fwlink/?LinkID
=135170 中的 about_Execution_Policies。
所在位置 行:1 字符: 1
+ npm -v
+ ~~~
+ CategoryInfo : SecurityError: (:) [],PSSecurityException
+ FullyQualifiedErrorId : UnauthorizedAccess
//解决方案:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser🐳 本地编译发布到 Docker 镜像
- 安装 Docker Desktop
- 执行
npm run build打包现代版(Chrome / Edge 107+、Firefox 104+、Safari 16+,默认推荐) - 进入
bin/Release/目录,执行publish-demo.sh脚本(记得先修改里面的配置)
只有已明确约定继续支持 Chrome 49 的存量客户,才使用 npm run build:legacy 同时生成 legacy 包。该命令会额外执行旧语法转换、polyfill 和完整校验,明显增加构建时间与产物体积。由于 Vue 3、Element Plus 等当前依赖已不再官方支持 Chrome 49,这一产物属于尽力兼容层,正式交付前仍需在客户真实旧浏览器上验证实际使用功能。