# OIP-Web **Repository Path**: orginone/OIP-Web ## Basic Information - **Project Name**: OIP-Web - **Description**: OIP-Web 是奥集能 V6 架构 L6 人机交互客户端(HCI 端) 的 Web 实现 - **Primary Language**: TypeScript - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 3 - **Created**: 2026-09-25 - **Last Updated**: 2026-10-16 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # OIP-Web > **文档版本**:v1.2 | **更新**:2026-10-01 | **状态**:详细设计 OIP-Web 是奥集能 V6 架构 **L6 人机交互客户端(HCI 端)** 的 Web 实现,运行于浏览器,面向「 办事、沟通、任务」三类组织协作活动提供统一工作台。 客户端以 **OIP-GoInOne** 为唯一接入边界:Hub(WebSocket)承载实时方法与推送,REST 承载查询 与降级;不直连 OIP-Book / OIP-Data / OIP-Message / OIP-Agent 等后端模块,一律经 OIP-GoInOne 代理。 | 项 | 内容 | | -------- | -------------------------------------------------- | | 包名 | `oip-web`(`private`,版本 `0.1.0`) | | 模块名 | `OIP-Web` | | 架构层级 | L6 人机交互端(客户端,纯消费者,不对外暴露接口) | | 许可证 | MIT(见 `LICENSE`) | | 详细设计 | [OIP-Web-Design.md](../OIP/docs/OIP-Web-Design.md) | | 协作规范 | [AGENTS.md](AGENTS.md) | ## 技术栈 依赖清单与版本以 `package.json` 为准。 **运行时框架** | 依赖 | 版本 | 作用 | | --------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | | `react` / `react-dom` | ^19.3.0 | 视图层;入口 `src/index.tsx` 使用 `react-dom/client` 的 `createRoot`。React 19 下 antd v5 需 `@ant-design/v5-patch-for-react-19`(已在依赖里,入口引入) | | `react-router-dom` | ^6.26.2 | 客户端路由 | | `zustand` | ^5.0.0 | 视图状态容器(`src/stores/index.ts`) | **通信与协议** | 依赖 | 版本 | 作用 | | -------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------- | | `@microsoft/signalr` | ^7.0.12 | Hub 实时通道;自定义 Hub 协议位于 `src/ts/base/protocol/txtHubProtocol.ts`,连接门面位于 `src/ts/base/api/storehub.ts` | | `axios` | ^1.7.7 | REST 请求(`src/infra/http.ts`) | **公式与脚本引擎**(`src/ts/scripting/**`) | 依赖 | 版本 | | ------------------------------------------------------------------------------------------- | -------------------------------- | | `@babel/standalone` / `@babel/core` / `@babel/parser` / `@babel/generator` / `@babel/types` | ^7.25.6(`@babel/core` ^7.25.2) | | `fast-formula-parser` | ^1.0.19 | **数据与工具**:`lodash` ^4.17.21、`moment` ^2.30.1、`dayjs` ^1.11.13、`decimal.js` ^10.4.3、`crypto-js` ^4.2.0、`pako` ^2.1.0、`pinyin-pro` ^3.26.0、`ajv` ^8.17.1、`qrcode.react` ^3.2.0、`echarts` ^6.1.0、`handsontable` ^14.6.2、`@handsontable/react` ^14.6.2。 **构建与工程** | 依赖 | 版本 | 作用 | | ---------------------------------------------------------------------------------------------------------- | ------- | ------------------------------------------------ | | `vite` | ^5.4.5 | 开发服务器与构建(配置见 `vite.config.ts`) | | `@vitejs/plugin-react` | ^4.3.1 | React 插件 | | `typescript` | ~5.6.2 | 类型检查(`tsconfig.json`,`strict` + `noEmit`) | | `vitest` | ^2.1.9 | 单元测试(`vitest.config.ts`,环境 jsdom) | | `jsdom` | ^25.0.1 | vitest 的 DOM 环境 | | `eslint` | ^9.39.4 | Flat config(`eslint.config.js`) | | `typescript-eslint` | ^8.71.0 | TypeScript 规则 | | `eslint-plugin-react-hooks` | ^5.2.0 | Hooks 规则 | | `@types/react` / `@types/react-dom` / `@types/node` / `@types/crypto-js` / `@types/lodash` / `@types/pako` | — | 类型声明 | **启用特性**:TypeScript `strict`、`noUnusedLocals`、`noUnusedParameters`、`jsx: react-jsx`、`moduleResolution: Bundler`; 路径别名 `@/*`(指向 `src/`)与 `@cfg/*`,声明于 `tsconfig.json` 的 `paths` 与 `vite.config.ts` 的 `resolve.alias`。 ## 目录结构 ```text OIP-Web/ ├─ index.html # HTML 入口:注入 window.__OIP_CONFIG__、首帧配色防闪烁 ├─ package.json # 包描述与 scripts ├─ package-lock.json # npm 依赖锁 ├─ tsconfig.json # TypeScript 编译配置 ├─ vite.config.ts # 开发服务器与构建配置(端口 5273、/oip 与 /orginone 代理、vendor 分包) ├─ LICENSE # MIT 许可证 ├─ README.md # 本文件 ├─ AGENTS.md # 协作规范 ├─ .gitignore ├─ .env.development # Vite 环境变量(development) ├─ .env.production # Vite 环境变量(production / 默认构建) ├─ .env.release # Vite 环境变量(release) ├─ src/ │ ├─ index.tsx # 应用入口 │ ├─ app.tsx # 应用根组件 │ ├─ vite-env.d.ts │ ├─ domain/ # L1 位置域(Locus)与上下文四元组:locus.ts │ ├─ hooks/ # React 复用钩子:useOrgCtrl.ts(orgCtrl 反应式桥接)、 │ │ # useWorkspace.ts(工作空间作用域:URL scope + store 兜底) │ ├─ infra/ # L0 基础设施:config / logger / result / protocol-surface / http / │ │ # bootstrap / keystore / auth / hub / degrade / agent-console / qrauth │ ├─ orchestration/ # L4 编排:slots(槽位)、keymap(快捷键)、workspaces(工作区)、 │ │ # intentBus(命令总线)、intent-parser(意图解析)、commands(命令处理器) │ ├─ services/ # L2 服务:context.service / target.service / directory.service / │ │ # relation.service / workspace.service / standard.service / │ │ # workflow.service / plaza.service / platform.service(平台设置)/ │ │ # discovery.service(动态流)/ credential.service(凭证)/ │ │ # node-tree.service(节点树)/ work-runtime.service(办事运行态), │ │ # 统一出口 index.ts │ ├─ presentation/ # L5 表现层 │ │ ├─ tokens/ # 设计 token:tokens.css │ │ ├─ primitives/ # 基础组件与其样式:index.tsx、primitives.module.css │ │ ├─ shell/ # 外壳与工作台:AppFrame(三栏)、NavRail(八项一级导航)、 │ │ │ # Breadcrumb(路由派生面包屑)、Workbench(列表-详情分栏/全屏)、 │ │ │ # OnlinePanel(在线面板)、FilterBar(多维筛选写 URL query)、 │ │ │ # nav.ts(IA 单一真相源) │ │ ├─ pages/ # 路由页面:pages.tsx(首页/发现/沟通/办事/门户/关系/我的/VET)、 │ │ │ # NodePage.tsx / PlatformEntryPage.tsx / ProfileGroupPage.tsx / │ │ │ # RuntimePage.tsx、RelationGraph.tsx(零依赖 SVG 关系图) │ │ ├─ platform-toolbar/ # 平台工具栏复用件:IdentityScaleSwitcher(三尺度身份)、 │ │ │ # IntentInput(意图输入)、OperatesMenu(operates() 驱动的行内菜单) │ │ ├─ workspaces/ # 三工作区列表与主内容区:lists.tsx、ThreeColumnWorkbench.tsx、 │ │ │ # threeColumn.module.css、ChatContextPanel.tsx、agentTaskPoll.ts、 │ │ │ # standard/(无代码搭建)、plaza/(广场商城)、data/、design/、node/ │ │ ├─ dialogs/ # CommandPalette、DirectoryPickerDialog、PlazaColumnDialog.tsx、StartWorkDialog.tsx │ │ ├─ settings/ # SettingsPanels(个人设置 / 关系设置)、PlatformSettingsPanel(平台设置)、 │ │ │ # SubjectSubpages.tsx │ │ └─ auth/ # LoginView │ ├─ stores/ # 视图状态(zustand):布局 / 上下文 / 工作空间作用域 / 列表视图 / 主题 / 连接 │ ├─ ts/ # 同源继承的数据层(L0+L1),不得引入 UI 依赖 │ │ ├─ base/ # 通用基础:协议与 Hub 协议、格式化、加密、LINQ、规则、通用工具 │ │ ├─ controller/ # 控制器入口:index.ts │ │ ├─ core/ # 领域模型与对象方法:target / space / thing / work / mall / app / │ │ │ # iot / provider / public │ │ ├─ element/ # 元素模型与工厂:ElementFactory、ElementMeta、ElementTreeManager、 │ │ │ # PageElement、standard/document、standard/page │ │ └─ scripting/ # 公式与脚本引擎:core / excel / js │ └─ utils/ # 通用工具:array / date / number / object / string / tree / tools / │ # validation / work / message / other / index,以及 react/(fc、antd) └─ typings/ # 全局类型声明 ├─ globelType.d.ts ├─ typing.d.ts ├─ babel-standalone.d.ts └─ fast-formula-parser.d.ts ``` `node_modules/`(依赖)、`dist/`(构建产物)、`.npm-cache/`、`.verify/`(本地缓存与验证输 出)为运行期生成目录,通过 `.gitignore` 排除。 ## 信息架构与路由 导航以 **URL 路由**(`react-router-dom` v6,`src/app.tsx` 的 `` + ``)为唯一真相源;路径与 OIP-Desktop 共用一套命名。IA 定义集中在 `src/presentation/shell/nav.ts`(一级导航、面包屑派生、筛选维度)。 | 一级导航 | 路径 | 二级 / 可达子页(示例) | | -------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | 首页 | `/` | — | | 发现 | `/discover` | `/discover/plaza` 广场 · `/discover/mall` 商城 · `/discover/feed` 内容发现 | | 沟通 | `/chat` | — | | 办事 | `/work` | `/work/todo` 待办、`/work/done` 已办、`/work/cc` 抄送、`/work/applied` 发起、`/work/finished` 完结、`/work/draft` 草稿 | | 门户 | `/portal` | `/portal/messages` 消息、`/portal/apps` 应用、`/portal/tasks` 任务、`/portal/files` 文件、`/portal/standard` 数据标准、`/portal/agents` 智能体;数据标准内部三段 `/portal/standard/standard`、`/portal/standard/work`、`/portal/standard/apps` | | 数据 | `/data` | `/data/standard` 数据标准 · `/data/apply` 应用 · `/data/view` 视图 · `/data/file` 文件(三级 `?section=`) | | 关系 | `/relation` | `/relation/members` 成员、`/relation/authz` 权限、`/relation/identity` 身份、`/relation/graph` 关系图、`/relation/approval` 审批流、`/relation/detail/:did` 节点详情 | | 我的 | `/profile` | `/profile/personal` 个人、`/profile/security` 账号与安全、`/profile/settings` 设置(含 `/profile/settings/connections` 连接管理、`/profile/settings/bindings`、`/profile/settings/did`、`/profile/settings/credentials` 等分区)、`/profile/about` 关于、`/profile/vet/*` VET、`/profile/console/:panel` 控制台 | VET 工作台挂在「我的」之下(`/profile/vet`),`/vet` 为历史路径并重定向到 `/profile/vet`。 `/profile/*` 的历史路径(如 `/profile/info`、`/profile/connections`、`/profile/bindings`) 保留为重定向,指向上述规范结构。 - 「可达」与「登记」是两件事 :`/discover/plaza`、`/discover/mall`、`/portal/standard/*`、`/portal/agents`、`/portal/runtime`、`/relation/{members,authz,identity,graph,approval}`、`/relation/detail/:did/*`、`/data/:group`、`/node/:did/*`、`/profile/settings/vet/*`、`/profile/console/:panel` 都有路由与中文名登记,但不出现在一级/二级导航轨;导航轨只登记需要常驻入口的项。 约定: - 面包屑由路由派生(`breadcrumbFor`),末级不可点;`?section=` 等筛选参数以可读文本带出。 - 列表筛选态写入 URL query(`type` / `status` / `belong` / `time` / `q` / `scope`),可深 链、可刷新保持。 - 详情栏支持全屏(`useLayoutStore.detailFullscreen`,属**瞬时**视图状态、不持久化,刷新回 落非全屏,`Esc` 退出)。 - 开发服务器为 SPA 模式,非首页路径回落到 `index.html`(history fallback),故深链直开可用 。 ## 常用命令 命令与 `package.json` 的 `scripts` 一一对应。 | 命令 | 实际执行 | 说明 | | ---------------------------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ | | `npm run dev` | `vite --mode desktop` | 启动开发服务器(**桌面剖面,默认**;端口 `1420`,跟进 Tauri `devUrl`、`host: true`) | | `npm run dev:web` | `vite --mode web` | 启动开发服务器(浏览器剖面;端口 `5273`) | | `npm run build` | `vite build --mode desktop` | **桌面剖面**生产构建(默认),输出到 `dist-desktop/` | | `npm run build:web` | `vite build --mode web` | 浏览器剖面构建(过渡期并存),输出到 `dist/` | | `npm run build:beta` | `vite build --mode beta` | beta 构建(浏览器剖面) | | `npm run build:release` | `vite build --mode release` | release 构建(浏览器剖面) | | `npm run preview` | `vite preview` | 预览 `dist/` 构建产物 | | `npm run typecheck` | `tsc --noEmit` | 仅类型检查,不产出文件 | | `npm run test` | `vitest run` | 单元测试(配置见 `vitest.config.ts`,用例 `src/**/*.test.ts`) | | `npm run lint` | `eslint .` | ESLint 检查(规则集见 `eslint.config.js`) | | `npm run check:contracts` | `node scripts/check-contracts.mjs` | 契约单一来源检查:服务层不得硬编码集合名 | | `npm run check:script-exec` | `node scripts/check-script-exec.mjs` | 执行面纪律检查:求值只允许出现在唯一闸门内 | | `npm run check:profile` | `node scripts/check-profile.mjs` | 壳剖面结构门禁(**默认剖面 = web**;端口两侧齐平;两剖面注入层键集一致) | | `npm run check:entry-routes` | `node scripts/check-entry-routes.mjs` | 入口面路由门禁(`/login` `/register` `/forgot` 可深链) | | `npm run verify:profiles` | `npm run build:desktop && npm run build:web && node scripts/check-profile-artifacts.mjs` | 双剖面构建 + **产物**隔离断言(web 产物不得含 Tauri 桥) | | `npm run verify` | 上述门禁 + `prettier` + `eslint` + `tsc` + `vitest` + `vite build` | 一键门禁(提交前必须全绿) | 开发服务器的代理规则(`vite.config.ts`): | 前缀 | 目标 | 说明 | | ----------- | ---------------------------------------------------------------------------------------- | ------------------------------------------ | | `/oip` | `VITE_OIP_PROXY_TARGET`(优先取;dev 下由 `.env.development` 给 `https://dataexp.orginone.cn`) | 唯一接入边界;支持 WebSocket(`ws: true`) | | `/orginone` | 同上 | 遗留兼容命名空间(双挂载期) | 构建产物:**桌面剖面**落 `dist-desktop/`(默认)、**浏览器剖面**落 `dist/`(两目录并存,便 于 `frontendDist` 分别指向);静态资源布局 `static/js/[hash].js`、`static/[ext]/[hash].[ext]`;`manualChunks` 的分组纪律是**"只对确定 同进退的族设显式组名"**——现为 `vendor-babel` / `vendor-univer` / `vendor-handsontable` / `vendor-antv` / `vendor-antd` / `vendor-react` / `vendor-protocol` / `vendor-libs`,以及 `vendor-preload`(Vite 注入的动态导入预加载助手,模块 id `\0vite/preload-helper.js`,**必 须单独成块**);**其余依赖一律按包名各自成块**(`vendor-<包名>`),**不设兜底组**。其中 `vendor-libs` 只收**真正被首屏静态引用到**的基础库——只被惰性路径用到的 (`fast-formula-parser`、`pinyin-pro`)**不列入**:即便调用处已改成 `await import`,只要还 留在该组,词典仍会随首屏预加载。为什么:chunk 是**整块加载**的,兜底组会把"只被动态路径引 用"的传递依赖(如 Univer 的 `html2canvas`、`franc-min`)与首屏要用的包合并,于是整组被预加 载——2026-10-10 实测,仅此一项就白拉约 1 MB;把 `pinyin-pro` 移出则再省约 296 KB。块体积告 警门限为 2048 KB(`chunkSizeWarningLimit`),`reportCompressedSize: false`,`sourcemap` 关 闭。 ## 环境变量 `.env.development` / `.env.production` / `.env.release` 是 Vite 的环境文件,字段名遵循 OIP 协议配置注入层(`OIP-Protocol.md` §3.13.1)的 `VITE_*` 命名。这三个文件只承载公开配置,随 仓库纳入版本管理。 | 变量 | 用途 | development | production / release | | --------------------------- | -------------------------------------- | ------------------------------ | -------------------- | | `VITE_OIP_L3_ENDPOINT` | 接入节点(OIP-GoInOne)基地址 | `/` | `https://assetcloud.zj.gov.cn/`(部署可覆盖) | | `VITE_OIP_PROXY_TARGET` | 开发代理转发目标(OIP-GoInOne 基地址) | `https://dataexp.orginone.cn`(dev);未配置时 `vite.config.ts` 兜底 `https://assetcloud.zj.gov.cn` | —(仅开发期生效) | | `VITE_OIP_L3_HUB_PATH` | Hub 实时通道路径 | `/oip/v1/hub` | `/oip/v1/hub` | | `VITE_OIP_L3_DID` | 客户端所在节点的 DID | `did:oip:node:local` | 留空,由部署注入 | | `VITE_OIP_COMPLIANCE_LEVEL` | 合规等级 | `OIP-Core` | `OIP-Full` | 注入链路:Vite 在构建时把上述 `%VITE_*%` 占位符替换进 `index.html`,形成运行时的 `window.__OIP_CONFIG__`(字段名 `OIP_L3_ENDPOINT` / `OIP_L3_HUB_PATH` / `OIP_L3_DID` / `OIP_COMPLIANCE_LEVEL`)。部署方也可在运行时直接覆盖 `window.__OIP_CONFIG__`。配置读取与占 位符防御位于 `src/infra/config.ts`:未替换的 `%...%` 占位符与空串等价于「未配置」,此时应 用呈现可见的未配置节点状态,而非静默失败。 另有一个不在 `.env.*` 中的可选项:`OIP_AGENT_API`(OIP-Agent 管理面基地址,Hono REST `/api/*` 风格),由部署方通过 `window.__OIP_CONFIG__` 注入;缺省时按 `{L3}/oip/v1/agent/api` 推导,推导不可得时任务页呈现未接入原因(见 `src/infra/agent-console.ts`、`src/infra/config.ts`)。 本地覆盖写入 `.env.local`(以及 `.env.local.*`、`.env.*.local`),这些文件由 `.gitignore` 排除。 ## 与后端及其他仓库的关系 ```text L6 人机交互端 OIP-Web(本仓库) ────────────────────────────────────────────── 接入边界 /oip/v1/hub(SignalR)· /oip/v1/*(REST) ────────────────────────────────────────────── 统一接入底座 OIP-GoInOne ────────────────────────────────────────────── 后端模块 OIP-Book · OIP-Data · OIP-Message · OIP-Agent · OIP-IoT ``` | 关系 | 规则 | | --------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | OIP-Web ↔ `OIP-GoInOne` | 唯一接入通道;Hub 承载实时方法与推送,REST 承载查询与降级 | | OIP-Web ↔ `OIP-Book` / `OIP-Data` / `OIP-Message` / `OIP-Agent` | 不直连,一律经 OIP-GoInOne 代理(`Request` / `DataProxy` / `Auth` 投影) | | OIP-Web ↔ 本地文件系统 | 仅经浏览器文件选择器与 OIP-Data 的 FileStream 原语交互,不建立旁路通道 | | OIP-Web ↔ OIP-Agent 管理面 | 任务页经 `/api/tasks/*` 访问(`src/infra/agent-console.ts`),基地址由 `OIP_AGENT_API` 指定或按 L3 推导;管理面不在协议面内 | | OIP-Web ↔ 存量 Web 端 `oiocns-react` | 数据领域模型与对象方法同源继承(`src/ts/**`),领域语义等价;交互界面另行设计 | | OIP-Web ↔ `OIP-Desktop` | 二者由**同一 React 代码库的两个构建剖面**产出(判别标准见 [OIP-Deployment.md §2.2](../OIP/docs/OIP-Deployment.md),MUST NOT 分叉为两套代码) | | 同层其他端 | `OIP-Desktop`(PC 本地终端,同一代码库的另一构建剖面)、`OIP-Mobile`(Flutter)、`OIP-Lite`(微信小程序原生(WXML/WXSS + TypeScript));跨端契约以 [OIP-Frontend-Design.md](../OIP/docs/OIP-Frontend-Design.md) 为单一真相源 | ## 相关文档 | 文档 | 内容 | | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | | [OIP-Web-Design.md](../OIP/docs/OIP-Web-Design.md) | OIP-Web 详细设计(数据领域建模、对象方法契约、工作区上下文模型、交互界面) | | [OIP-Frontend-Design.md](../OIP/docs/OIP-Frontend-Design.md) | L6 跨端交互契约(多端一致性要求的单一真相源) | | [OIP-Protocol.md](../OIP/docs/OIP-Protocol.md) | OIP 协议规范(含配置注入层 §3.13.1) | | [OIP-GoInOne-Design.md](../OIP/docs/OIP-GoInOne-Design.md) | 统一接入底座设计 | | [OIP-Agent-Design.md](../OIP/docs/OIP-Agent-Design.md) | L5 智能体与任务设计 | | [OIP/AGENTS.md](../OIP/AGENTS.md) | 智能体协作规范(文档体系、命名、版本与质量门禁) | | [插件化重构与 Cordis 框架落地方案.md](docs/插件化重构与Cordis框架落地方案.md) | 以本仓为架构基座的重构方案:Cordis 机制落地(§8/§15)、`antd` 并库机制(§21)、九波迁移与六阶段路线图(§23–§24)、八道验收门禁(§25) | | [设计系统与前端规范.md](docs/设计系统与前端规范.md) | 设计系统与前端规范(信息架构、设计系统、前端规范、交付验收基线) | | [智能体交互落地实施方案.md](docs/智能体交互落地实施方案.md) | 三尺度身份与统一指挥中枢的落地方案 | | [AGENTS.md](AGENTS.md) | 本仓协作规范(关键入口、硬性约束、Git 与测试约定) |