diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c63834..873020d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,346 +1,29 @@ -# XYOS 系统升级日志 +# openXYOS changelog -## V0.4.5.3 (2026-07-02) — 监理集团OA管控 · 工程管理框架 +Public community-edition notes only. This file is not a production-readiness claim. -代号:`SupervisionOA` | Build 453 +Commercial XYOS 4.x / 0.4.5.x upgrade notes are archived at [docs/archive/XYOS-CHANGELOG.md](docs/archive/XYOS-CHANGELOG.md). License, trademark, and patent boundary documents are unchanged. ---- +## 0.6.3 — 2026-09-17 -### 🆕 新增功能 +Community identity alignment for the public 12-module edition. -#### 1. 考勤管理系统(P26) -**路由**:`/attendance` +### Identity -| 功能 | API 端点 | 说明 | -|------|----------|------| -| 今日考勤 | `GET /api/attendance/today` | 当天打卡状态(签到/签退时间) | -| 签到 | `POST /api/attendance/check-in` | GPS 定位签到 | -| 签退 | `POST /api/attendance/check-out` | GPS 定位签退 | -| 考勤记录 | `GET /api/attendance/records` | 分页查询,支持日期/状态筛选 | -| 考勤统计 | `GET /api/attendance/stats` | 月度汇总(正常/迟到/早退/缺勤天数) | -| 补卡申请 | `GET/POST /api/attendance/supplements` | 发起补卡申请(关联workflow审批) | -| 补卡审批 | `PUT /api/attendance/supplements/:id/review` | 管理员审批,通过后自动创建考勤记录 | +- Runtime, health, and operator-facing version strings now read **openXYOS 0.6.3** from `package.json`. +- Removed leftover public 4.5.x, 0.4.5.3, and `0.50.0-dev` product versions. +- Footer and signed-in sidebar show the same community version. -**特性**:迟到检测(基于排班表 `flexible_minutes`)、排班管理(行政班/弹性研发班)、多租户隔离、唯一日期约束 +### Catalog and UI boundary -#### 2. 请假/报销/日报周报(P27) +- `/api/module-settings` and the signed-in client remain on the open 12-module catalog (`workspace`, `announcements`, `organization`, `employees`, `skills`, `chat`, `agents`, `tasks`, `knowledge`, `reflections`, `governance`, `settings`). +- The commercial tenant catalog and unused commercial pages were quarantined under `docs/archive/`. They are not imported by `OpenApp`. -| 模块 | 路由 | 核心功能 | -|------|------|---------| -| 请假管理 | `/api/leave` | 7种请假类型、日期校验、workflow审批关联 | -| 费用报销 | `/api/expense` | 8种报销类型、多发票明细、付款状态跟踪 | -| 日报周报 | `/api/daily-report` | 日报周报提交、重复提交更新、评论互动 | +### Docs -**特性**:全部复用现有 workflow 引擎,不重复造审批系统;审批完成后自动更新业务状态 +- `CONTRIBUTING.md` now says openXYOS. CLA completion and `Signed-off-by` rules are unchanged. +- Architecture notes describe `OpenApp.tsx` as the community router. -#### 3. 种子数据系统 -- 新增 `backend/seed-oa.ts`:为两个租户自动植入考勤/请假/报销/日报演示数据 -- 启动时自动运行,支持幂等(重复执行不重复插入) +## 0.6.0 — 2026-09-12 -#### 4. 数据库向后兼容迁移 -- `db.ts` 新增 `ensureTables()`:启动时自动检查并创建旧数据库缺失的表 -- 解决已有数据库文件缺少 `announcements`/`attendance_*`/`leave_requests`/`expense_*` 等新表的问题 - ---- - -### 🔧 改进与优化 - -- **侧边栏重构**:合并核心导航与管理导航为统一列表,移除分组折叠 -- **导航顺序优化**:工作台 → 通知公告 → 组织架构 → 员工管理 → 技能插件 → 沟通协作 → 任务管理 → 流程管理 → 合同管理 → 工程管理 → 资产管理 → 考勤管理 → 费用报销 → 工作记录 → 目标管理 → 预算管理 → 绩效评估 → 效能仪表板 → 反思引擎 → 知识库 -- **请假管理并入考勤管理**:移除独立 `/leave` 侧边栏入口 -- **工作日报 → 工作记录**:统一日报/周报/月报入口 -- **知识库提升**:从底部移动到主导航列表 - ---- - -### 📝 修改文件清单 - -``` -backend/db.ts +200行 (P25-P27数据表 + ensureTables迁移) -backend/seed-oa.ts 新增 (OA种子数据脚本) -backend/server.ts +3行 (注册OA路由 + seed导入 + 版本号) -backend/config/version.ts 版本号 4.5.2 → 0.4.5.3 -backend/routes/attendance.ts +363行 (新增) -backend/routes/leave.ts +184行 (新增) -backend/routes/expense.ts +218行 (新增) -backend/routes/daily-report.ts +263行 (新增) -frontend/src/pages/AttendancePage.tsx +514行 (新增) -frontend/src/pages/LeavePage.tsx 新增 -frontend/src/pages/ExpensePage.tsx 新增 -frontend/src/pages/DailyReportPage.tsx 新增 -frontend/src/App.tsx +6行 (注册4个新路由) -frontend/src/components/Sidebar.tsx 重构 (统一导航 + 顺序调整 + 版本号) -frontend/src/components/Header.tsx 版本号 4.5.2 → 0.4.5.3 -frontend/src/components/Footer.tsx 版本号 4.5.2 → 0.4.5.3 -frontend/src/pages/Dashboard.tsx 版本号 4.5.2 → 0.4.5.3 -frontend/src/pages/DemoPage.tsx 版本号 4.5.2 → 0.4.5.3 -entry/src/main/ets/pages/Index.ets 版本号 4.5.2 → 0.4.5.3 -docs/监理集团OA管控体系开发计划v2.md 新增 (Phase 1-3 规划文档) ---- - -## V4.5.2 (2026-06-28) — 资产管理 · 通知公告 · 群组重构 - -代号:`AssetHub` | Build 452 - ---- - -### 🆕 新增功能 - -#### 1. 超级管理员 — 数据库管理系统 -**位置**:系统设置 → 数据库管理(仅 `super_admin` 角色可见) - -| 功能 | API 端点 | 说明 | -|------|----------|------| -| 数据库概览 | `GET /api/settings/database/info` | 引擎类型、表数、行数、文件大小、备份统计 | -| 立即备份 | `POST /api/settings/database/backup` | 一键创建 `.db` 快照,自动保留最近 20 个 | -| 备份列表 | `GET /api/settings/database/backups` | 查看所有历史备份(大小、时间) | -| 恢复备份 | `POST /api/settings/database/restore` | 从指定备份恢复(自动创建安全回滚点) | -| 删除备份 | `DELETE /api/settings/database/backups/:filename` | 清理不需要的备份文件 | - -**安全机制**: -- 所有端点均需 `requireSuperAdmin` + JWT 双重校验 -- 文件名防路径穿越检查(禁止 `..` `/` `\`) -- **恢复前自动创建 `pre-recover-{timestamp}.bak` 安全快照** -- 二次确认对话框(前端删除/恢复操作) -- 自动清理旧备份(最多保留 20 个手动备份) - -#### 2. 前端源码完整同步 -从参考版本 `XYOSv4` 同步前端开发环境到主项目: - -| 同步项 | 目标路径 | 用途 | -|--------|----------|------| -| Vite 配置 | `vite.config.ts` | 前端构建工具配置 | -| TS 配置 | `tsconfig.json` | TypeScript 编译选项 | -| 前端源码 | `frontend/src/` (37 files) | React 组件、页面、API 层 | -| 入口 HTML | `frontend/index.html` | SPA 入口 | -| 样式资源 | `frontend/public/`, `src/index.css` | 静态资源、全局样式 | - -**影响范围**:26 页面 + 4 公共组件 + authFetch API 层 + Zustand 状态管理 - ---- - -### 🔧 改进与优化 - -- **构建流程规范化**:`npm run build` → `dist/assets/index-*.js`,支持热更新开发 (`npm run dev`) -- **多端兼容确认**:H5 前端通过 `window.__API_BASE__` 注入机制适配鸿蒙 WebView -- **备份策略**:手动备份命名格式 `xyos-YYYYMMDD-HHMMSS.db`,自动轮转保留最近 20 个 - ---- - -### 📝 修改文件清单 - -``` -backend/routes/settings.ts +200行 (数据库管理API) -frontend/src/pages/SettingsPage.tsx +180行 (DatabaseManagementTab组件) -vite.config.ts 新增 (Vite构建配置) -tsconfig.json 新增 (TS编译配置) -frontend/ 新增 (37个源码文件) -dist/ 重建 (新构建产物) -``` - ---- - -### 🔄 升级路径 - -**从 V4.5.0 升级:** -```bash -# 1. 前端源码已同步,无需额外操作 -# 2. 重启后端加载新的 settings 路由 -# 3. 浏览器访问:系统设置 → 数据库管理 -``` - -**破坏性变更:** 无(纯增量更新,不影响现有功能) - ---- - -## V4.5.2 (2026-06-27) — 集团管控 · 合同增强 - -代号:`BranchControl` | Build 452 - ---- - -## 一、集团化多分支驻外机构管控架构 全面升级 - -### 🏢 设计理念 - -面向集团型企业的多层级、多架构、跨地域管理需求,我们彻底重构了组织架构引擎。支持一家企业同时使用**多种组织形态共存**——总部职能制、事业部分权制、项目矩阵制、创业扁平化和驻外二级机构,在同一棵组织树中无缝融合。 - ---- - -### 📐 五大机构类型 · 一树兼容 - -| 机构类型 | 标识 | 适用场景 | 视觉特征 | -|----------|------|----------|----------| -| **职能制** | 🏢 `functional` | 总部职能部门(财务、HR、行政) | 7 级递进配色(靛蓝→天蓝→翠绿→琥珀→赤红→紫罗兰→品红) | -| **事业部制** | 🏭 `divisional` | 独立核算产品线/区域 | 同上层级配色体系 | -| **矩阵制** | 🔀 `matrix` | 跨部门项目组、临时攻坚团队 | 同上层级配色体系 | -| **扁平化** | ⚡ `flat` | 创业团队、创新孵化器、工作室 | 同上层级配色体系 | -| **外派机构** | 📍 `dispatched` | 驻外办事处、海外分支机构、二级管理单元 | **专属青蓝系配色**(Teal → Cyan → Sky → Indigo)**虚线边框** · **MapPin 定位图标** · **「外派」标签** | - -> 🎨 外派机构在组织图中一目了然:专属青蓝色调 + 虚线描边的卡片,一眼区分总部分支/驻外机构。 - ---- - -### 🏗️ 部门管控字段 - -每个部门节点附带完整管控元数据: - -| 字段 | 说明 | -|------|------| -| `department_code` | 部门编码(如 TECH、SALES、HW-01) | -| `cost_center` | 成本中心编号 | -| `headcount` | 编制人数(实时满编/缺编/超编状态提示) | -| `budget_allocation` | 年度预算额度 | -| `function_type` | 机构类型(5 选 1) | -| `level` | 组织层级(1-10,决定配色) | -| `description` | 部门职责描述 | - -编辑对话框自动展示**编制健康度**——实时计算当前在岗人数 vs 编制人数,标记满编/缺编/超编。 - ---- - -### 🔗 双线汇报关系 - -支持矩阵式管理中的**实线汇报**与**虚线汇报**: - -| 汇报类型 | 线条样式 | 适用场景 | -|----------|----------|----------| -| `solid` 实线汇报 | 实线连接 | 行政直属上级 | -| `dotted` 虚线汇报 | 虚线连接 | 项目/业务指导上级 | - -每名员工可配置多条汇报线,打破传统「一人一上级」的层级固囿。员工详情页直达「汇报关系」入口,独立弹窗配置全部汇报链。 - ---- - -### 📊 版本管理 · 组织快照 - -| 操作 | 说明 | -|------|------| -| **创建版本** | 录入版本号 + 描述,一键生成组织架构快照 | -| **状态流转** | 草稿 → 审批中 → 审批通过 → 已归档 | -| **版本列表** | 按时间倒序列出所有历史版本,彩色状态标签 | - ---- - -### 📥📤 导入导出 · 联防互通 - -| 方向 | 支持格式 | 说明 | -|------|----------|------| -| **导入** | XMind · Visio XML · JSON | 从外部工具一键导入完整组织树(部门+员工),后端智能解析数据结构 | -| **导出 PNG** | `.png` 高清位图 | 2x 像素比,浅灰色背景,适用于 PPT/文档插入 | -| **导出 SVG** | `.svg` 矢量图 | 无损缩放,适用于打印/画册 | -| **导出 PDF** | `.pdf` 文档 | 自动横竖版适配,高清渲染 | - ---- - -### 🧠 AI 智能补齐 - -新增 `POST /api/org/employees/:id/auto-fill` 端点:根据员工 `agent_type`(CEO/CTO/CFO...)调用 AI 自动填充岗位职责描述和技能配备,减少人工录入。 - ---- - -## 二、合同管理模块 全面增强 - -### 🚨 多级预警升级引擎 - -告别「一刀切」的预警方式。新引擎按**距到期天数**自动分级: - -| 级别 | 距到期 | 标识 | 处理策略 | -|------|--------|------|----------| -| 🔴 **紧急** | 已逾期 | `urgent` | 自动标记 + 写入升级日志 | -| 🟠 **警报** | ≤ 3 天 | `alert_danger` | 自动升级 → 通知直属上级 | -| 🟡 **预警** | ≤ 7 天 | `alert_warning` | 自动升级 → 站内提醒 | -| 🟢 **提醒** | ≤ 15 天 | `alert_info` | 自动升级 → 可选通知 | -| 🔵 **关注** | ≤ 30 天 | `alert_reminder` | 自动升级 → 静默记录 | - -新增能力: -- **升级历史追溯**:每个付款节点可查询完整升级时间线(触发时间、升级前级别→后级别、触发方式) -- **一键手动检测**:管理员可随时触发全量预警扫描与自动升级,无需等待定时任务 -- **预警级别配置**:租户级可自定义各级阈值 - ---- - -### 📅 甘特图 · 合同时间线全景视图 - -纯前端 CSS/SVG 渲染,零第三方图表库依赖。一图纵览全部合同的: - -| 信息维度 | 呈现方式 | -|----------|----------| -| **合同周期** | 按起止日期计算百分比,渲染渐变色条形图 | -| **收款合同** | 蓝紫色渐变条(左→右) | -| **付款合同** | 青绿色渐变条(左→右) | -| **付款节点** | 琥珀色圆点=待付 · 绿色圆点=已付 ✅ | -| **验收进度节点** | 紫色圆点标记关键里程碑 | - -交互特性: -- 左侧 260px 固定信息列(合同名称、编号、对方、金额、方向标签) -- 右侧按月滚动时间轴(26-01 → 27-03,自动推算范围) -- 方向筛选器(全部/收款/付款),即时重绘 -- 底部图例速查 - ---- - -### 📈 仪表盘 · 合约全景驾驶舱 - -一次请求聚合全部核心指标,无需多次 API 调用: - -``` -┌─────────────────────────────────────────────────────┐ -│ 合同总数: 3 执行中: 2 已签署: 0 │ -│ 已到期: 0 本月新增: 3 │ -├─────────────────────────────────────────────────────┤ -│ 应收 ¥0 (回收率0%) │ 应付 ¥0 (回收率0%) │ -│ 已收 ¥0 │ 已付 ¥0 │ -├───────────────────────────┬─────────────────────────┤ -│ 合同类型分布 │ 预警概览 │ -│ ████████ service 2 ¥79.9 │ 🔴 紧急 3 🟠 警报 0 │ -│ ████ procurement 1 ¥12.0 │ 🟡 预警 0 🟢 提醒 0 │ -│ │ TOP5 即将到期列表 │ -├───────────────────────────┴─────────────────────────┤ -│ 近6个月收付款趋势(柱状图) │ -│ 26-01 ~ 26-06 │ -└─────────────────────────────────────────────────────┘ -``` - ---- - -### 🐛 本日踩坑复盘 - -| # | 问题 | 根因 | 教训 | -|---|------|------|------| -| 1 | 甘特图/仪表盘路由 404 | Express `/:id` 通配路由吃了 `gantt` 和 `dashboard` 单段路径 | **铁律:所有单段特定路径必须定义在 `/:id` 之前** | -| 2 | JSX 标签闭合错误 | 图例 `` 内多了 ``,复制粘贴后未清理 | 遇到闭合标签报错,优先搜索多余的闭合标签 | -| 3 | 运行时引用崩溃 | 批量重命名状态变量时误删 `useState` 声明 | 重构后用 `grep` 核对每个变量的声明→引用完整性 | -| 4 | 后端改动未重启 | 只改了路由文件,以为 Vite HMR 能重载后端 | 改路由/服务层后必须 `taskkill /PID` 精确重启 | - ---- - -### 📝 变更文件 - -``` -frontend/src/pages/OrgChart.tsx 优化 (外派机构视觉隔离、五大机构类型、 - 双线汇报、版本管理、导入导出) -backend/routes/org.ts 增强 (部门管控字段、function_type、 - dispatched 类型支持) -backend/services/contract.ts +120行 (多级预警引擎 + 甘特图 + 仪表盘) -backend/routes/contracts.ts +60行 (Phase 4+5 共6个端点,路由顺序修复) -frontend/src/pages/ContractPage.tsx +220行 (甘特图 + 仪表盘 + 预警面板) -backups/2026-06-27-* 新增 (完整备份) -``` - -**破坏性变更:** 无(纯增量,零改动已有接口和函数签名) - ---- - -### 📋 版本历史 - -| 版本 | 代号 | 日期 | 主要特性 | -|------|------|------|----------| -| v4.0 | Origin | 2025-01-01 | 初始版本,多租户 AI 企业管理平台 | -| v4.1 | HITL | 2025-03-15 | 人在回路人工审核、治理引擎 | -| v4.2 | MCP | 2025-04-20 | MCP 协议服务端/客户端、工具调用日志 | -| v4.3 | Agent | 2025-05-15 | 向量记忆、SSE 流式输出、ReAct 推理 | -| v4.4 | Harmony | 2025-06-10 | 鸿蒙原生桥接、离线模式、端侧 SQLite | -| v4.5 | XinChuang | 2025-06-25 | 信创部署、品牌升级、租户自定义 | -| **v4.5.1** | **DBAdmin** | **2026-06-26** | **数据库管理、前端源码同步** | -| **v4.5.2** | **BranchControl** | **2026-06-27** | **集团管控架构升级、合同管理全面增强** | +Public candidate baseline recorded in the open-source quality report: bilingual workspace, Agent Studio, 12-module runtime, and release-gate scans. Suitable for local development and evaluation. Not represented as production-ready. diff --git a/backend/config/features.ts b/backend/config/features.ts index 821421c..3cbf852 100644 --- a/backend/config/features.ts +++ b/backend/config/features.ts @@ -1,13 +1,14 @@ /* - * XYOS V4.5 — 全局功能开关 (Feature Flags) - * 所有新功能通过环境变量控制启用/禁用 - * 支持运行时动态降级,不修改代码即可回滚 - * - * 使用方式: - * import { FEATURES } from './config/features'; - * if (FEATURES.ENABLE_HUMAN_IN_THE_LOOP) { ... } + * openXYOS feature flags. + * New capabilities are gated by environment variables so they can be disabled without a code change. + * + * Usage: + * import { FEATURE_FLAGS } from './config/features'; + * if (FEATURE_FLAGS.ENABLE_HUMAN_IN_THE_LOOP) { ... } */ +import { OPENXYOS_VERSION } from "../openxyos-identity"; + export const FEATURE_FLAGS = { // ============ V4.1 人在回路 ============ /** 人在回路人工审核机制 */ @@ -117,16 +118,10 @@ export function getEnabledModules(): string[] { } /** - * 获取当前版本信息 + * Public feature-set label. Matches package.json so operators never see commercial 4.x numbers. */ export function getFeatureVersion(): string { - const modules = getEnabledModules(); - if (modules.includes('private-deploy') && modules.includes('db-adapter')) return 'v4.5'; - if (modules.includes('native-bridge')) return 'v4.4'; - if (modules.includes('vector-memory') || modules.includes('react-agent')) return 'v4.3'; - if (modules.includes('mcp-server') || modules.includes('mcp-client')) return 'v4.2'; - if (modules.includes('hitl')) return 'v4.1'; - return 'v4.0'; + return OPENXYOS_VERSION; } /** diff --git a/backend/config/version.ts b/backend/config/version.ts index 1452a68..e757ea5 100644 --- a/backend/config/version.ts +++ b/backend/config/version.ts @@ -1,195 +1,19 @@ /* - * XYOS V4.5 — 版本信息管理 - * 集中管理版本号、构建信息、升级路径 + * Compatibility shim. Import from ../version or ../openxyos-identity instead. + * Kept so existing relative imports cannot drift onto a second version number. */ -export interface VersionInfo { - /** 语义化版本号 */ - semver: string; - /** 版本代号 */ - codename: string; - /** 发布日期 */ - releaseDate: string; - /** 功能集版本 */ - featureVersion: string; - /** 构建号 */ - buildNumber: number; - /** Git commit hash */ - gitHash: string; - /** 是否预发布版本 */ - isPrerelease: boolean; -} - -export interface UpgradePath { - from: string; - to: string; - migrations: string[]; - requiredFeatures: string[]; - breakingChanges: string[]; -} - -/** - * 当前版本信息 - */ -export const CURRENT_VERSION: VersionInfo = { - semver: '0.4.5.3', - codename: 'BranchControl', - releaseDate: '2026-06-27', - featureVersion: 'v4.5', - buildNumber: 452, - gitHash: process.env.GIT_HASH || 'unknown', - isPrerelease: false, -}; - -/** - * 版本历史 - */ -export const VERSION_HISTORY: VersionInfo[] = [ - { - semver: '4.0.0', - codename: 'Origin', - releaseDate: '2025-01-01', - featureVersion: 'v4.0', - buildNumber: 400, - gitHash: 'unknown', - isPrerelease: false, - }, - { - semver: '4.1.0', - codename: 'HITL', - releaseDate: '2025-03-15', - featureVersion: 'v4.1', - buildNumber: 410, - gitHash: 'unknown', - isPrerelease: false, - }, - { - semver: '4.2.0', - codename: 'MCP', - releaseDate: '2025-04-20', - featureVersion: 'v4.2', - buildNumber: 420, - gitHash: 'unknown', - isPrerelease: false, - }, - { - semver: '4.3.0', - codename: 'Agent', - releaseDate: '2025-05-15', - featureVersion: 'v4.3', - buildNumber: 430, - gitHash: 'unknown', - isPrerelease: false, - }, - { - semver: '4.4.0', - codename: 'Harmony', - releaseDate: '2025-06-10', - featureVersion: 'v4.4', - buildNumber: 440, - gitHash: 'unknown', - isPrerelease: false, - }, +export { CURRENT_VERSION, -]; - -/** - * 升级路径定义 - * 从低版本升级到高版本需要执行的迁移脚本 - */ -export const UPGRADE_PATHS: UpgradePath[] = [ - { - from: '4.0.0', - to: '4.1.0', - migrations: ['001_add_pending_reviews.sql'], - requiredFeatures: ['ENABLE_HUMAN_IN_THE_LOOP'], - breakingChanges: [], - }, - { - from: '4.1.0', - to: '4.2.0', - migrations: ['002_add_mcp_connections.sql', '003_add_mcp_tool_call_logs.sql'], - requiredFeatures: ['ENABLE_MCP_SERVER', 'ENABLE_MCP_CLIENT'], - breakingChanges: [], - }, - { - from: '4.2.0', - to: '4.3.0', - migrations: ['004_add_memory_vectors.sql', '005_add_agent_reasoning_logs.sql'], - requiredFeatures: ['ENABLE_VECTOR_MEMORY', 'ENABLE_STREAMING'], - breakingChanges: [], - }, - { - from: '4.3.0', - to: '4.4.0', - migrations: [], // V4.4 主要是端侧变更,后端无数据库变更 - requiredFeatures: ['ENABLE_NATIVE_BRIDGE', 'ENABLE_OFFLINE_MODE'], - breakingChanges: [], - }, - { - from: '4.4.0', - to: '4.5.0', - migrations: ['006_add_schema_migrations.sql', '007_add_db_adapter_config.sql'], - requiredFeatures: ['ENABLE_DB_ADAPTER', 'ENABLE_PRIVATE_DEPLOY'], - breakingChanges: ['数据库方言切换需要数据迁移'], - }, -]; - -/** - * 获取从指定版本升级到当前版本需要的迁移列表 - */ -export function getUpgradeMigrations(fromVersion: string): string[] { - const migrations: string[] = []; - let currentFrom = fromVersion; - - for (const path of UPGRADE_PATHS) { - if (path.from === currentFrom) { - migrations.push(...path.migrations); - currentFrom = path.to; - if (currentFrom === CURRENT_VERSION.semver) break; - } - } - - return migrations; -} - -/** - * 获取版本升级路径中的破坏性变更 - */ -export function getBreakingChanges(fromVersion: string): string[] { - const changes: string[] = []; - let currentFrom = fromVersion; - - for (const path of UPGRADE_PATHS) { - if (path.from === currentFrom) { - changes.push(...path.breakingChanges); - currentFrom = path.to; - if (currentFrom === CURRENT_VERSION.semver) break; - } - } - - return changes; -} - -/** - * 比较版本号 - * @returns -1 if a < b, 0 if a == b, 1 if a > b - */ -export function compareVersion(a: string, b: string): number { - const partsA = a.split('.').map(Number); - const partsB = b.split('.').map(Number); - for (let i = 0; i < 3; i++) { - if (partsA[i] < partsB[i]) return -1; - if (partsA[i] > partsB[i]) return 1; - } - return 0; -} - -/** - * 检查是否需要升级 - */ -export function needsUpgrade(currentDbVersion: string): boolean { - return compareVersion(currentDbVersion, CURRENT_VERSION.semver) < 0; -} - -export default CURRENT_VERSION; + OPENXYOS_EDITION, + OPENXYOS_PRODUCT, + OPENXYOS_VERSION, + UPGRADE_PATHS, + VERSION_HISTORY, + compareVersion, + getBreakingChanges, + getUpgradeMigrations, + needsUpgrade, +} from "../version"; +export type { UpgradePath, VersionInfo } from "../version"; +export { default } from "../version"; diff --git a/backend/openxyos-identity.ts b/backend/openxyos-identity.ts new file mode 100644 index 0000000..2990bee --- /dev/null +++ b/backend/openxyos-identity.ts @@ -0,0 +1,14 @@ +import { readFileSync } from "node:fs"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; + +const packageJson = JSON.parse( + readFileSync(join(dirname(fileURLToPath(import.meta.url)), "..", "package.json"), "utf8") +) as { name: string; version: string }; + +/** Public product name. Trademark use remains governed by TRADEMARKS.md. */ +export const OPENXYOS_PRODUCT = "openXYOS"; +export const OPENXYOS_EDITION = "community"; + +/** Single runtime/public version identity. Always read from package.json. */ +export const OPENXYOS_VERSION = packageJson.version; diff --git a/backend/routes/health.ts b/backend/routes/health.ts index 09b544e..138b300 100644 --- a/backend/routes/health.ts +++ b/backend/routes/health.ts @@ -1,5 +1,6 @@ import { Router } from "express"; import { dbGet } from "../db"; +import { OPENXYOS_EDITION, OPENXYOS_PRODUCT, OPENXYOS_VERSION } from "../openxyos-identity"; export const healthRoutes = Router(); @@ -10,8 +11,12 @@ function checkDatabase() { return { employees: employees.c, tasks: tasks.c, users: users.c }; } +function publicIdentity() { + return { product: OPENXYOS_PRODUCT, edition: OPENXYOS_EDITION, version: OPENXYOS_VERSION }; +} + healthRoutes.get("/livez", (_req, res) => { - res.status(200).json({ status: "live", uptime: Math.floor(process.uptime()) }); + res.status(200).json({ status: "live", uptime: Math.floor(process.uptime()), ...publicIdentity() }); }); healthRoutes.get("/readyz", (_req, res) => { @@ -19,13 +24,13 @@ healthRoutes.get("/readyz", (_req, res) => { const stats = checkDatabase(); res.status(200).json({ status: "ready", - version: process.env.XYOS_VERSION || "0.50.0-dev", + ...publicIdentity(), database: "ok", uptime: Math.floor(process.uptime()), stats, }); } catch { - res.status(503).json({ status: "not_ready", version: process.env.XYOS_VERSION || "0.50.0-dev", database: "error" }); + res.status(503).json({ status: "not_ready", ...publicIdentity(), database: "error" }); } }); @@ -33,8 +38,8 @@ healthRoutes.get("/readyz", (_req, res) => { healthRoutes.get("/", (_req, res) => { try { const stats = checkDatabase(); - res.status(200).json({ status: "ready", version: process.env.XYOS_VERSION || "0.50.0-dev", database: "ok", uptime: Math.floor(process.uptime()), stats }); + res.status(200).json({ status: "ready", ...publicIdentity(), database: "ok", uptime: Math.floor(process.uptime()), stats }); } catch { - res.status(503).json({ status: "not_ready", version: process.env.XYOS_VERSION || "0.50.0-dev", database: "error" }); + res.status(503).json({ status: "not_ready", ...publicIdentity(), database: "error" }); } }); diff --git a/backend/server.ts b/backend/server.ts index 64fe512..1fb79bb 100644 --- a/backend/server.ts +++ b/backend/server.ts @@ -54,6 +54,7 @@ import { seedDatabase } from "./seed"; import { authenticate } from "./middleware"; import { setupWebSocket } from "./services/websocket"; import { globalErrorHandler } from "./utils/error-handler"; +import { OPENXYOS_VERSION } from "./openxyos-identity"; async function main() { const app = express(); @@ -223,7 +224,7 @@ app.get("/admin/database", (req, res) => { setupWebSocket(server); server.listen(PORT, '0.0.0.0', () => { - console.log(`\n 🌐 openXYOS Community — Human + Agent OS`); + console.log(`\n 🌐 openXYOS Community ${OPENXYOS_VERSION} — Human + Agent OS`); console.log(` ─────────────────────────────────────`); console.log(` Server: http://localhost:${PORT}`); console.log(` WebSocket: ws://localhost:${PORT}/ws`); diff --git a/backend/services/mcp-client.ts b/backend/services/mcp-client.ts index 2e1cb13..ac80882 100644 --- a/backend/services/mcp-client.ts +++ b/backend/services/mcp-client.ts @@ -6,6 +6,7 @@ */ import { FEATURE_FLAGS } from "../config/features"; +import { OPENXYOS_VERSION } from "../openxyos-identity"; // ───────────────────────────────────────────── // 类型定义 @@ -100,7 +101,7 @@ async function connectToServer(server: MCPServerConfig): Promise { method: "initialize", params: { protocolVersion: "2024-11-05", - clientInfo: { name: "XYOS-MCP-Client", version: "4.2.0" }, + clientInfo: { name: "openXYOS-MCP-Client", version: OPENXYOS_VERSION }, capabilities: {}, }, id: 1, diff --git a/backend/services/mcp-server.ts b/backend/services/mcp-server.ts index 5d9342b..f66bc2a 100644 --- a/backend/services/mcp-server.ts +++ b/backend/services/mcp-server.ts @@ -16,6 +16,7 @@ import { dbGet, dbAll, dbRun } from "../db"; import { FEATURE_FLAGS } from "../config/features"; +import { OPENXYOS_VERSION } from "../openxyos-identity"; // ───────────────────────────────────────────── // MCP 协议类型定义 @@ -195,8 +196,8 @@ export function handleInitialize(): MCPInitializeResult { return { protocolVersion: "2024-11-05", serverInfo: { - name: "XYOS-MCP-Server", - version: "4.2.0", + name: "openXYOS-MCP-Server", + version: OPENXYOS_VERSION, }, capabilities: { tools: { diff --git a/backend/version.ts b/backend/version.ts index 9e419e5..fb281f2 100644 --- a/backend/version.ts +++ b/backend/version.ts @@ -1,22 +1,20 @@ /* - * XYOS V4.5 — 版本信息管理 - * 集中管理版本号、构建信息、升级路径 + * openXYOS community edition — public version identity. + * Semver is read from package.json; do not hard-code a second product version. */ +import { OPENXYOS_EDITION, OPENXYOS_PRODUCT, OPENXYOS_VERSION } from "./openxyos-identity"; + +export { OPENXYOS_EDITION, OPENXYOS_PRODUCT, OPENXYOS_VERSION }; + export interface VersionInfo { - /** 语义化版本号 */ + /** Semantic version from package.json */ semver: string; - /** 版本代号 */ - codename: string; - /** 发布日期 */ - releaseDate: string; - /** 功能集版本 */ + product: string; + edition: string; + /** Feature-set label shown to operators; matches the public semver. */ featureVersion: string; - /** 构建号 */ - buildNumber: number; - /** Git commit hash */ gitHash: string; - /** 是否预发布版本 */ isPrerelease: boolean; } @@ -28,166 +26,42 @@ export interface UpgradePath { breakingChanges: string[]; } -/** - * 当前版本信息 - */ export const CURRENT_VERSION: VersionInfo = { - semver: '4.5.2', - codename: 'BranchControl', - releaseDate: '2026-06-27', - featureVersion: 'v4.5', - buildNumber: 452, - gitHash: process.env.GIT_HASH || 'unknown', + semver: OPENXYOS_VERSION, + product: OPENXYOS_PRODUCT, + edition: OPENXYOS_EDITION, + featureVersion: OPENXYOS_VERSION, + gitHash: process.env.GIT_HASH || "unknown", isPrerelease: false, }; -/** - * 版本历史 - */ -export const VERSION_HISTORY: VersionInfo[] = [ - { - semver: '4.0.0', - codename: 'Origin', - releaseDate: '2025-01-01', - featureVersion: 'v4.0', - buildNumber: 400, - gitHash: 'unknown', - isPrerelease: false, - }, - { - semver: '4.1.0', - codename: 'HITL', - releaseDate: '2025-03-15', - featureVersion: 'v4.1', - buildNumber: 410, - gitHash: 'unknown', - isPrerelease: false, - }, - { - semver: '4.2.0', - codename: 'MCP', - releaseDate: '2025-04-20', - featureVersion: 'v4.2', - buildNumber: 420, - gitHash: 'unknown', - isPrerelease: false, - }, - { - semver: '4.3.0', - codename: 'Agent', - releaseDate: '2025-05-15', - featureVersion: 'v4.3', - buildNumber: 430, - gitHash: 'unknown', - isPrerelease: false, - }, - { - semver: '4.4.0', - codename: 'Harmony', - releaseDate: '2025-06-10', - featureVersion: 'v4.4', - buildNumber: 440, - gitHash: 'unknown', - isPrerelease: false, - }, - CURRENT_VERSION, -]; - -/** - * 升级路径定义 - * 从低版本升级到高版本需要执行的迁移脚本 - */ -export const UPGRADE_PATHS: UpgradePath[] = [ - { - from: '4.0.0', - to: '4.1.0', - migrations: ['001_add_pending_reviews.sql'], - requiredFeatures: ['ENABLE_HUMAN_IN_THE_LOOP'], - breakingChanges: [], - }, - { - from: '4.1.0', - to: '4.2.0', - migrations: ['002_add_mcp_connections.sql', '003_add_mcp_tool_call_logs.sql'], - requiredFeatures: ['ENABLE_MCP_SERVER', 'ENABLE_MCP_CLIENT'], - breakingChanges: [], - }, - { - from: '4.2.0', - to: '4.3.0', - migrations: ['004_add_memory_vectors.sql', '005_add_agent_reasoning_logs.sql'], - requiredFeatures: ['ENABLE_VECTOR_MEMORY', 'ENABLE_STREAMING'], - breakingChanges: [], - }, - { - from: '4.3.0', - to: '4.4.0', - migrations: [], // V4.4 主要是端侧变更,后端无数据库变更 - requiredFeatures: ['ENABLE_NATIVE_BRIDGE', 'ENABLE_OFFLINE_MODE'], - breakingChanges: [], - }, - { - from: '4.4.0', - to: '4.5.0', - migrations: ['006_add_schema_migrations.sql', '007_add_db_adapter_config.sql'], - requiredFeatures: ['ENABLE_DB_ADAPTER', 'ENABLE_PRIVATE_DEPLOY'], - breakingChanges: ['数据库方言切换需要数据迁移'], - }, -]; +/** Public community history only. Commercial XYOS 4.x notes live under docs/archive/. */ +export const VERSION_HISTORY: VersionInfo[] = [CURRENT_VERSION]; -/** - * 获取从指定版本升级到当前版本需要的迁移列表 - */ -export function getUpgradeMigrations(fromVersion: string): string[] { - const migrations: string[] = []; - let currentFrom = fromVersion; +export const UPGRADE_PATHS: UpgradePath[] = []; - for (const path of UPGRADE_PATHS) { - if (path.from === currentFrom) { - migrations.push(...path.migrations); - currentFrom = path.to; - if (currentFrom === CURRENT_VERSION.semver) break; - } - } - - return migrations; +export function getUpgradeMigrations(_fromVersion: string): string[] { + return []; } -/** - * 获取版本升级路径中的破坏性变更 - */ -export function getBreakingChanges(fromVersion: string): string[] { - const changes: string[] = []; - let currentFrom = fromVersion; - - for (const path of UPGRADE_PATHS) { - if (path.from === currentFrom) { - changes.push(...path.breakingChanges); - currentFrom = path.to; - if (currentFrom === CURRENT_VERSION.semver) break; - } - } - - return changes; +export function getBreakingChanges(_fromVersion: string): string[] { + return []; } -/** - * 比较版本号 - * @returns -1 if a < b, 0 if a == b, 1 if a > b - */ +/** Compare dotted numeric versions. Extra segments are treated as 0. */ export function compareVersion(a: string, b: string): number { - const partsA = a.split('.').map(Number); - const partsB = b.split('.').map(Number); - for (let i = 0; i < 3; i++) { - if (partsA[i] < partsB[i]) return -1; - if (partsA[i] > partsB[i]) return 1; + const partsA = a.split(".").map(Number); + const partsB = b.split(".").map(Number); + const length = Math.max(partsA.length, partsB.length, 3); + for (let i = 0; i < length; i++) { + const left = partsA[i] ?? 0; + const right = partsB[i] ?? 0; + if (left < right) return -1; + if (left > right) return 1; } return 0; } -/** - * 检查是否需要升级 - */ export function needsUpgrade(currentDbVersion: string): boolean { return compareVersion(currentDbVersion, CURRENT_VERSION.semver) < 0; } diff --git a/docs/architecture.md b/docs/architecture.md index 3eb18d6..8cb3abf 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -17,7 +17,7 @@ Express server ## Frontend -`frontend/src/App.tsx` owns routing. Pages use a shared authenticated fetch layer and Zustand stores. Tenant module settings load once after authentication; the shared store controls sidebar visibility and guards disabled routes. Vite provides the development server, production bundle, and PWA assets. +`frontend/src/OpenApp.tsx` owns the community-edition routes. The signed-in shell uses the 12-module open catalog from `frontend/src/open-modules.ts` and `/api/module-settings`. Pages use a shared authenticated fetch layer and Zustand stores. Tenant module settings load once after authentication; the shared store controls sidebar visibility and guards disabled routes. Vite provides the development server, production bundle, and PWA assets. Commercial leftover pages are archived under `docs/archive/` and are not part of the public runtime. ## Backend diff --git a/docs/archive/README.md b/docs/archive/README.md new file mode 100644 index 0000000..98f8268 --- /dev/null +++ b/docs/archive/README.md @@ -0,0 +1,11 @@ +# Archived XYOS materials + +These files are **not** part of the openXYOS community runtime. They are kept only as historical reference from the commercial XYOS line. + +| Path | Why it is archived | +| --- | --- | +| `XYOS-CHANGELOG.md` | Commercial XYOS 4.x / 0.4.5.x upgrade notes. The public changelog is `/CHANGELOG.md`. | +| `commercial-backend/` | Tenant catalog and `/api/module-settings` implementation that listed OA, assets, contracts, and other commercial modules. Live traffic uses `backend/open-module-catalog.ts` and `backend/routes/open-module-settings.ts`. | +| `commercial-frontend/` | Unused commercial App shell, sidebar, module store, workflow designer, and pages that `OpenApp` never imported. | + +Do not re-mount these files as the public product surface. Trademark, patent, and Apache-2.0 boundary documents stay in the repository root and `docs/governance/`. diff --git a/docs/archive/XYOS-CHANGELOG.md b/docs/archive/XYOS-CHANGELOG.md new file mode 100644 index 0000000..8c63834 --- /dev/null +++ b/docs/archive/XYOS-CHANGELOG.md @@ -0,0 +1,346 @@ +# XYOS 系统升级日志 + +## V0.4.5.3 (2026-07-02) — 监理集团OA管控 · 工程管理框架 + +代号:`SupervisionOA` | Build 453 + +--- + +### 🆕 新增功能 + +#### 1. 考勤管理系统(P26) +**路由**:`/attendance` + +| 功能 | API 端点 | 说明 | +|------|----------|------| +| 今日考勤 | `GET /api/attendance/today` | 当天打卡状态(签到/签退时间) | +| 签到 | `POST /api/attendance/check-in` | GPS 定位签到 | +| 签退 | `POST /api/attendance/check-out` | GPS 定位签退 | +| 考勤记录 | `GET /api/attendance/records` | 分页查询,支持日期/状态筛选 | +| 考勤统计 | `GET /api/attendance/stats` | 月度汇总(正常/迟到/早退/缺勤天数) | +| 补卡申请 | `GET/POST /api/attendance/supplements` | 发起补卡申请(关联workflow审批) | +| 补卡审批 | `PUT /api/attendance/supplements/:id/review` | 管理员审批,通过后自动创建考勤记录 | + +**特性**:迟到检测(基于排班表 `flexible_minutes`)、排班管理(行政班/弹性研发班)、多租户隔离、唯一日期约束 + +#### 2. 请假/报销/日报周报(P27) + +| 模块 | 路由 | 核心功能 | +|------|------|---------| +| 请假管理 | `/api/leave` | 7种请假类型、日期校验、workflow审批关联 | +| 费用报销 | `/api/expense` | 8种报销类型、多发票明细、付款状态跟踪 | +| 日报周报 | `/api/daily-report` | 日报周报提交、重复提交更新、评论互动 | + +**特性**:全部复用现有 workflow 引擎,不重复造审批系统;审批完成后自动更新业务状态 + +#### 3. 种子数据系统 +- 新增 `backend/seed-oa.ts`:为两个租户自动植入考勤/请假/报销/日报演示数据 +- 启动时自动运行,支持幂等(重复执行不重复插入) + +#### 4. 数据库向后兼容迁移 +- `db.ts` 新增 `ensureTables()`:启动时自动检查并创建旧数据库缺失的表 +- 解决已有数据库文件缺少 `announcements`/`attendance_*`/`leave_requests`/`expense_*` 等新表的问题 + +--- + +### 🔧 改进与优化 + +- **侧边栏重构**:合并核心导航与管理导航为统一列表,移除分组折叠 +- **导航顺序优化**:工作台 → 通知公告 → 组织架构 → 员工管理 → 技能插件 → 沟通协作 → 任务管理 → 流程管理 → 合同管理 → 工程管理 → 资产管理 → 考勤管理 → 费用报销 → 工作记录 → 目标管理 → 预算管理 → 绩效评估 → 效能仪表板 → 反思引擎 → 知识库 +- **请假管理并入考勤管理**:移除独立 `/leave` 侧边栏入口 +- **工作日报 → 工作记录**:统一日报/周报/月报入口 +- **知识库提升**:从底部移动到主导航列表 + +--- + +### 📝 修改文件清单 + +``` +backend/db.ts +200行 (P25-P27数据表 + ensureTables迁移) +backend/seed-oa.ts 新增 (OA种子数据脚本) +backend/server.ts +3行 (注册OA路由 + seed导入 + 版本号) +backend/config/version.ts 版本号 4.5.2 → 0.4.5.3 +backend/routes/attendance.ts +363行 (新增) +backend/routes/leave.ts +184行 (新增) +backend/routes/expense.ts +218行 (新增) +backend/routes/daily-report.ts +263行 (新增) +frontend/src/pages/AttendancePage.tsx +514行 (新增) +frontend/src/pages/LeavePage.tsx 新增 +frontend/src/pages/ExpensePage.tsx 新增 +frontend/src/pages/DailyReportPage.tsx 新增 +frontend/src/App.tsx +6行 (注册4个新路由) +frontend/src/components/Sidebar.tsx 重构 (统一导航 + 顺序调整 + 版本号) +frontend/src/components/Header.tsx 版本号 4.5.2 → 0.4.5.3 +frontend/src/components/Footer.tsx 版本号 4.5.2 → 0.4.5.3 +frontend/src/pages/Dashboard.tsx 版本号 4.5.2 → 0.4.5.3 +frontend/src/pages/DemoPage.tsx 版本号 4.5.2 → 0.4.5.3 +entry/src/main/ets/pages/Index.ets 版本号 4.5.2 → 0.4.5.3 +docs/监理集团OA管控体系开发计划v2.md 新增 (Phase 1-3 规划文档) +--- + +## V4.5.2 (2026-06-28) — 资产管理 · 通知公告 · 群组重构 + +代号:`AssetHub` | Build 452 + +--- + +### 🆕 新增功能 + +#### 1. 超级管理员 — 数据库管理系统 +**位置**:系统设置 → 数据库管理(仅 `super_admin` 角色可见) + +| 功能 | API 端点 | 说明 | +|------|----------|------| +| 数据库概览 | `GET /api/settings/database/info` | 引擎类型、表数、行数、文件大小、备份统计 | +| 立即备份 | `POST /api/settings/database/backup` | 一键创建 `.db` 快照,自动保留最近 20 个 | +| 备份列表 | `GET /api/settings/database/backups` | 查看所有历史备份(大小、时间) | +| 恢复备份 | `POST /api/settings/database/restore` | 从指定备份恢复(自动创建安全回滚点) | +| 删除备份 | `DELETE /api/settings/database/backups/:filename` | 清理不需要的备份文件 | + +**安全机制**: +- 所有端点均需 `requireSuperAdmin` + JWT 双重校验 +- 文件名防路径穿越检查(禁止 `..` `/` `\`) +- **恢复前自动创建 `pre-recover-{timestamp}.bak` 安全快照** +- 二次确认对话框(前端删除/恢复操作) +- 自动清理旧备份(最多保留 20 个手动备份) + +#### 2. 前端源码完整同步 +从参考版本 `XYOSv4` 同步前端开发环境到主项目: + +| 同步项 | 目标路径 | 用途 | +|--------|----------|------| +| Vite 配置 | `vite.config.ts` | 前端构建工具配置 | +| TS 配置 | `tsconfig.json` | TypeScript 编译选项 | +| 前端源码 | `frontend/src/` (37 files) | React 组件、页面、API 层 | +| 入口 HTML | `frontend/index.html` | SPA 入口 | +| 样式资源 | `frontend/public/`, `src/index.css` | 静态资源、全局样式 | + +**影响范围**:26 页面 + 4 公共组件 + authFetch API 层 + Zustand 状态管理 + +--- + +### 🔧 改进与优化 + +- **构建流程规范化**:`npm run build` → `dist/assets/index-*.js`,支持热更新开发 (`npm run dev`) +- **多端兼容确认**:H5 前端通过 `window.__API_BASE__` 注入机制适配鸿蒙 WebView +- **备份策略**:手动备份命名格式 `xyos-YYYYMMDD-HHMMSS.db`,自动轮转保留最近 20 个 + +--- + +### 📝 修改文件清单 + +``` +backend/routes/settings.ts +200行 (数据库管理API) +frontend/src/pages/SettingsPage.tsx +180行 (DatabaseManagementTab组件) +vite.config.ts 新增 (Vite构建配置) +tsconfig.json 新增 (TS编译配置) +frontend/ 新增 (37个源码文件) +dist/ 重建 (新构建产物) +``` + +--- + +### 🔄 升级路径 + +**从 V4.5.0 升级:** +```bash +# 1. 前端源码已同步,无需额外操作 +# 2. 重启后端加载新的 settings 路由 +# 3. 浏览器访问:系统设置 → 数据库管理 +``` + +**破坏性变更:** 无(纯增量更新,不影响现有功能) + +--- + +## V4.5.2 (2026-06-27) — 集团管控 · 合同增强 + +代号:`BranchControl` | Build 452 + +--- + +## 一、集团化多分支驻外机构管控架构 全面升级 + +### 🏢 设计理念 + +面向集团型企业的多层级、多架构、跨地域管理需求,我们彻底重构了组织架构引擎。支持一家企业同时使用**多种组织形态共存**——总部职能制、事业部分权制、项目矩阵制、创业扁平化和驻外二级机构,在同一棵组织树中无缝融合。 + +--- + +### 📐 五大机构类型 · 一树兼容 + +| 机构类型 | 标识 | 适用场景 | 视觉特征 | +|----------|------|----------|----------| +| **职能制** | 🏢 `functional` | 总部职能部门(财务、HR、行政) | 7 级递进配色(靛蓝→天蓝→翠绿→琥珀→赤红→紫罗兰→品红) | +| **事业部制** | 🏭 `divisional` | 独立核算产品线/区域 | 同上层级配色体系 | +| **矩阵制** | 🔀 `matrix` | 跨部门项目组、临时攻坚团队 | 同上层级配色体系 | +| **扁平化** | ⚡ `flat` | 创业团队、创新孵化器、工作室 | 同上层级配色体系 | +| **外派机构** | 📍 `dispatched` | 驻外办事处、海外分支机构、二级管理单元 | **专属青蓝系配色**(Teal → Cyan → Sky → Indigo)**虚线边框** · **MapPin 定位图标** · **「外派」标签** | + +> 🎨 外派机构在组织图中一目了然:专属青蓝色调 + 虚线描边的卡片,一眼区分总部分支/驻外机构。 + +--- + +### 🏗️ 部门管控字段 + +每个部门节点附带完整管控元数据: + +| 字段 | 说明 | +|------|------| +| `department_code` | 部门编码(如 TECH、SALES、HW-01) | +| `cost_center` | 成本中心编号 | +| `headcount` | 编制人数(实时满编/缺编/超编状态提示) | +| `budget_allocation` | 年度预算额度 | +| `function_type` | 机构类型(5 选 1) | +| `level` | 组织层级(1-10,决定配色) | +| `description` | 部门职责描述 | + +编辑对话框自动展示**编制健康度**——实时计算当前在岗人数 vs 编制人数,标记满编/缺编/超编。 + +--- + +### 🔗 双线汇报关系 + +支持矩阵式管理中的**实线汇报**与**虚线汇报**: + +| 汇报类型 | 线条样式 | 适用场景 | +|----------|----------|----------| +| `solid` 实线汇报 | 实线连接 | 行政直属上级 | +| `dotted` 虚线汇报 | 虚线连接 | 项目/业务指导上级 | + +每名员工可配置多条汇报线,打破传统「一人一上级」的层级固囿。员工详情页直达「汇报关系」入口,独立弹窗配置全部汇报链。 + +--- + +### 📊 版本管理 · 组织快照 + +| 操作 | 说明 | +|------|------| +| **创建版本** | 录入版本号 + 描述,一键生成组织架构快照 | +| **状态流转** | 草稿 → 审批中 → 审批通过 → 已归档 | +| **版本列表** | 按时间倒序列出所有历史版本,彩色状态标签 | + +--- + +### 📥📤 导入导出 · 联防互通 + +| 方向 | 支持格式 | 说明 | +|------|----------|------| +| **导入** | XMind · Visio XML · JSON | 从外部工具一键导入完整组织树(部门+员工),后端智能解析数据结构 | +| **导出 PNG** | `.png` 高清位图 | 2x 像素比,浅灰色背景,适用于 PPT/文档插入 | +| **导出 SVG** | `.svg` 矢量图 | 无损缩放,适用于打印/画册 | +| **导出 PDF** | `.pdf` 文档 | 自动横竖版适配,高清渲染 | + +--- + +### 🧠 AI 智能补齐 + +新增 `POST /api/org/employees/:id/auto-fill` 端点:根据员工 `agent_type`(CEO/CTO/CFO...)调用 AI 自动填充岗位职责描述和技能配备,减少人工录入。 + +--- + +## 二、合同管理模块 全面增强 + +### 🚨 多级预警升级引擎 + +告别「一刀切」的预警方式。新引擎按**距到期天数**自动分级: + +| 级别 | 距到期 | 标识 | 处理策略 | +|------|--------|------|----------| +| 🔴 **紧急** | 已逾期 | `urgent` | 自动标记 + 写入升级日志 | +| 🟠 **警报** | ≤ 3 天 | `alert_danger` | 自动升级 → 通知直属上级 | +| 🟡 **预警** | ≤ 7 天 | `alert_warning` | 自动升级 → 站内提醒 | +| 🟢 **提醒** | ≤ 15 天 | `alert_info` | 自动升级 → 可选通知 | +| 🔵 **关注** | ≤ 30 天 | `alert_reminder` | 自动升级 → 静默记录 | + +新增能力: +- **升级历史追溯**:每个付款节点可查询完整升级时间线(触发时间、升级前级别→后级别、触发方式) +- **一键手动检测**:管理员可随时触发全量预警扫描与自动升级,无需等待定时任务 +- **预警级别配置**:租户级可自定义各级阈值 + +--- + +### 📅 甘特图 · 合同时间线全景视图 + +纯前端 CSS/SVG 渲染,零第三方图表库依赖。一图纵览全部合同的: + +| 信息维度 | 呈现方式 | +|----------|----------| +| **合同周期** | 按起止日期计算百分比,渲染渐变色条形图 | +| **收款合同** | 蓝紫色渐变条(左→右) | +| **付款合同** | 青绿色渐变条(左→右) | +| **付款节点** | 琥珀色圆点=待付 · 绿色圆点=已付 ✅ | +| **验收进度节点** | 紫色圆点标记关键里程碑 | + +交互特性: +- 左侧 260px 固定信息列(合同名称、编号、对方、金额、方向标签) +- 右侧按月滚动时间轴(26-01 → 27-03,自动推算范围) +- 方向筛选器(全部/收款/付款),即时重绘 +- 底部图例速查 + +--- + +### 📈 仪表盘 · 合约全景驾驶舱 + +一次请求聚合全部核心指标,无需多次 API 调用: + +``` +┌─────────────────────────────────────────────────────┐ +│ 合同总数: 3 执行中: 2 已签署: 0 │ +│ 已到期: 0 本月新增: 3 │ +├─────────────────────────────────────────────────────┤ +│ 应收 ¥0 (回收率0%) │ 应付 ¥0 (回收率0%) │ +│ 已收 ¥0 │ 已付 ¥0 │ +├───────────────────────────┬─────────────────────────┤ +│ 合同类型分布 │ 预警概览 │ +│ ████████ service 2 ¥79.9 │ 🔴 紧急 3 🟠 警报 0 │ +│ ████ procurement 1 ¥12.0 │ 🟡 预警 0 🟢 提醒 0 │ +│ │ TOP5 即将到期列表 │ +├───────────────────────────┴─────────────────────────┤ +│ 近6个月收付款趋势(柱状图) │ +│ 26-01 ~ 26-06 │ +└─────────────────────────────────────────────────────┘ +``` + +--- + +### 🐛 本日踩坑复盘 + +| # | 问题 | 根因 | 教训 | +|---|------|------|------| +| 1 | 甘特图/仪表盘路由 404 | Express `/:id` 通配路由吃了 `gantt` 和 `dashboard` 单段路径 | **铁律:所有单段特定路径必须定义在 `/:id` 之前** | +| 2 | JSX 标签闭合错误 | 图例 `` 内多了 ``,复制粘贴后未清理 | 遇到闭合标签报错,优先搜索多余的闭合标签 | +| 3 | 运行时引用崩溃 | 批量重命名状态变量时误删 `useState` 声明 | 重构后用 `grep` 核对每个变量的声明→引用完整性 | +| 4 | 后端改动未重启 | 只改了路由文件,以为 Vite HMR 能重载后端 | 改路由/服务层后必须 `taskkill /PID` 精确重启 | + +--- + +### 📝 变更文件 + +``` +frontend/src/pages/OrgChart.tsx 优化 (外派机构视觉隔离、五大机构类型、 + 双线汇报、版本管理、导入导出) +backend/routes/org.ts 增强 (部门管控字段、function_type、 + dispatched 类型支持) +backend/services/contract.ts +120行 (多级预警引擎 + 甘特图 + 仪表盘) +backend/routes/contracts.ts +60行 (Phase 4+5 共6个端点,路由顺序修复) +frontend/src/pages/ContractPage.tsx +220行 (甘特图 + 仪表盘 + 预警面板) +backups/2026-06-27-* 新增 (完整备份) +``` + +**破坏性变更:** 无(纯增量,零改动已有接口和函数签名) + +--- + +### 📋 版本历史 + +| 版本 | 代号 | 日期 | 主要特性 | +|------|------|------|----------| +| v4.0 | Origin | 2025-01-01 | 初始版本,多租户 AI 企业管理平台 | +| v4.1 | HITL | 2025-03-15 | 人在回路人工审核、治理引擎 | +| v4.2 | MCP | 2025-04-20 | MCP 协议服务端/客户端、工具调用日志 | +| v4.3 | Agent | 2025-05-15 | 向量记忆、SSE 流式输出、ReAct 推理 | +| v4.4 | Harmony | 2025-06-10 | 鸿蒙原生桥接、离线模式、端侧 SQLite | +| v4.5 | XinChuang | 2025-06-25 | 信创部署、品牌升级、租户自定义 | +| **v4.5.1** | **DBAdmin** | **2026-06-26** | **数据库管理、前端源码同步** | +| **v4.5.2** | **BranchControl** | **2026-06-27** | **集团管控架构升级、合同管理全面增强** | diff --git a/backend/module-catalog.ts b/docs/archive/commercial-backend/module-catalog.ts similarity index 100% rename from backend/module-catalog.ts rename to docs/archive/commercial-backend/module-catalog.ts diff --git a/backend/routes/module-settings.ts b/docs/archive/commercial-backend/routes/module-settings.ts similarity index 100% rename from backend/routes/module-settings.ts rename to docs/archive/commercial-backend/routes/module-settings.ts diff --git a/frontend/src/App.tsx b/docs/archive/commercial-frontend/App.tsx similarity index 100% rename from frontend/src/App.tsx rename to docs/archive/commercial-frontend/App.tsx diff --git a/frontend/src/components/ModuleManagementTab.tsx b/docs/archive/commercial-frontend/components/ModuleManagementTab.tsx similarity index 100% rename from frontend/src/components/ModuleManagementTab.tsx rename to docs/archive/commercial-frontend/components/ModuleManagementTab.tsx diff --git a/frontend/src/components/Sidebar.tsx b/docs/archive/commercial-frontend/components/Sidebar.tsx similarity index 100% rename from frontend/src/components/Sidebar.tsx rename to docs/archive/commercial-frontend/components/Sidebar.tsx diff --git a/frontend/src/components/SmartAssistant.tsx b/docs/archive/commercial-frontend/components/SmartAssistant.tsx similarity index 100% rename from frontend/src/components/SmartAssistant.tsx rename to docs/archive/commercial-frontend/components/SmartAssistant.tsx diff --git a/frontend/src/components/workflow/FlowDesigner.tsx b/docs/archive/commercial-frontend/components/workflow/FlowDesigner.tsx similarity index 100% rename from frontend/src/components/workflow/FlowDesigner.tsx rename to docs/archive/commercial-frontend/components/workflow/FlowDesigner.tsx diff --git a/frontend/src/components/workflow/FlowPreview.tsx b/docs/archive/commercial-frontend/components/workflow/FlowPreview.tsx similarity index 100% rename from frontend/src/components/workflow/FlowPreview.tsx rename to docs/archive/commercial-frontend/components/workflow/FlowPreview.tsx diff --git a/frontend/src/components/workflow/FormDesigner.tsx b/docs/archive/commercial-frontend/components/workflow/FormDesigner.tsx similarity index 100% rename from frontend/src/components/workflow/FormDesigner.tsx rename to docs/archive/commercial-frontend/components/workflow/FormDesigner.tsx diff --git a/frontend/src/components/workflow/WorkflowDesigner.tsx b/docs/archive/commercial-frontend/components/workflow/WorkflowDesigner.tsx similarity index 100% rename from frontend/src/components/workflow/WorkflowDesigner.tsx rename to docs/archive/commercial-frontend/components/workflow/WorkflowDesigner.tsx diff --git a/frontend/src/components/workflow/types.ts b/docs/archive/commercial-frontend/components/workflow/types.ts similarity index 100% rename from frontend/src/components/workflow/types.ts rename to docs/archive/commercial-frontend/components/workflow/types.ts diff --git a/frontend/src/config/modules.ts b/docs/archive/commercial-frontend/config/modules.ts similarity index 100% rename from frontend/src/config/modules.ts rename to docs/archive/commercial-frontend/config/modules.ts diff --git a/frontend/src/pages/AdminPage.tsx b/docs/archive/commercial-frontend/pages/AdminPage.tsx similarity index 100% rename from frontend/src/pages/AdminPage.tsx rename to docs/archive/commercial-frontend/pages/AdminPage.tsx diff --git a/frontend/src/pages/AssetCountPage.tsx b/docs/archive/commercial-frontend/pages/AssetCountPage.tsx similarity index 100% rename from frontend/src/pages/AssetCountPage.tsx rename to docs/archive/commercial-frontend/pages/AssetCountPage.tsx diff --git a/frontend/src/pages/AssetDashboard.tsx b/docs/archive/commercial-frontend/pages/AssetDashboard.tsx similarity index 100% rename from frontend/src/pages/AssetDashboard.tsx rename to docs/archive/commercial-frontend/pages/AssetDashboard.tsx diff --git a/frontend/src/pages/AssetDetailPage.tsx b/docs/archive/commercial-frontend/pages/AssetDetailPage.tsx similarity index 100% rename from frontend/src/pages/AssetDetailPage.tsx rename to docs/archive/commercial-frontend/pages/AssetDetailPage.tsx diff --git a/frontend/src/pages/AssetPage.tsx b/docs/archive/commercial-frontend/pages/AssetPage.tsx similarity index 100% rename from frontend/src/pages/AssetPage.tsx rename to docs/archive/commercial-frontend/pages/AssetPage.tsx diff --git a/frontend/src/pages/AssetProcurementPage.tsx b/docs/archive/commercial-frontend/pages/AssetProcurementPage.tsx similarity index 100% rename from frontend/src/pages/AssetProcurementPage.tsx rename to docs/archive/commercial-frontend/pages/AssetProcurementPage.tsx diff --git a/frontend/src/pages/AssetVehicleExpensePage.tsx b/docs/archive/commercial-frontend/pages/AssetVehicleExpensePage.tsx similarity index 100% rename from frontend/src/pages/AssetVehicleExpensePage.tsx rename to docs/archive/commercial-frontend/pages/AssetVehicleExpensePage.tsx diff --git a/frontend/src/pages/AttendancePage.tsx b/docs/archive/commercial-frontend/pages/AttendancePage.tsx similarity index 100% rename from frontend/src/pages/AttendancePage.tsx rename to docs/archive/commercial-frontend/pages/AttendancePage.tsx diff --git a/frontend/src/pages/AuditTrailPage.tsx b/docs/archive/commercial-frontend/pages/AuditTrailPage.tsx similarity index 100% rename from frontend/src/pages/AuditTrailPage.tsx rename to docs/archive/commercial-frontend/pages/AuditTrailPage.tsx diff --git a/frontend/src/pages/BudgetPage.tsx b/docs/archive/commercial-frontend/pages/BudgetPage.tsx similarity index 100% rename from frontend/src/pages/BudgetPage.tsx rename to docs/archive/commercial-frontend/pages/BudgetPage.tsx diff --git a/frontend/src/pages/ConfigVersionPage.tsx b/docs/archive/commercial-frontend/pages/ConfigVersionPage.tsx similarity index 100% rename from frontend/src/pages/ConfigVersionPage.tsx rename to docs/archive/commercial-frontend/pages/ConfigVersionPage.tsx diff --git a/frontend/src/pages/ContractPage.tsx b/docs/archive/commercial-frontend/pages/ContractPage.tsx similarity index 100% rename from frontend/src/pages/ContractPage.tsx rename to docs/archive/commercial-frontend/pages/ContractPage.tsx diff --git a/frontend/src/pages/CustomerServicePage.tsx b/docs/archive/commercial-frontend/pages/CustomerServicePage.tsx similarity index 100% rename from frontend/src/pages/CustomerServicePage.tsx rename to docs/archive/commercial-frontend/pages/CustomerServicePage.tsx diff --git a/frontend/src/pages/DailyReportPage.tsx b/docs/archive/commercial-frontend/pages/DailyReportPage.tsx similarity index 100% rename from frontend/src/pages/DailyReportPage.tsx rename to docs/archive/commercial-frontend/pages/DailyReportPage.tsx diff --git a/frontend/src/pages/Dashboard.tsx b/docs/archive/commercial-frontend/pages/Dashboard.tsx similarity index 100% rename from frontend/src/pages/Dashboard.tsx rename to docs/archive/commercial-frontend/pages/Dashboard.tsx diff --git a/frontend/src/pages/EfficiencyDashboard.tsx b/docs/archive/commercial-frontend/pages/EfficiencyDashboard.tsx similarity index 100% rename from frontend/src/pages/EfficiencyDashboard.tsx rename to docs/archive/commercial-frontend/pages/EfficiencyDashboard.tsx diff --git a/frontend/src/pages/ElectricityMarketPage.tsx b/docs/archive/commercial-frontend/pages/ElectricityMarketPage.tsx similarity index 100% rename from frontend/src/pages/ElectricityMarketPage.tsx rename to docs/archive/commercial-frontend/pages/ElectricityMarketPage.tsx diff --git a/frontend/src/pages/ExpensePage.tsx b/docs/archive/commercial-frontend/pages/ExpensePage.tsx similarity index 100% rename from frontend/src/pages/ExpensePage.tsx rename to docs/archive/commercial-frontend/pages/ExpensePage.tsx diff --git a/frontend/src/pages/GoalPage.tsx b/docs/archive/commercial-frontend/pages/GoalPage.tsx similarity index 100% rename from frontend/src/pages/GoalPage.tsx rename to docs/archive/commercial-frontend/pages/GoalPage.tsx diff --git a/frontend/src/pages/LeavePage.tsx b/docs/archive/commercial-frontend/pages/LeavePage.tsx similarity index 100% rename from frontend/src/pages/LeavePage.tsx rename to docs/archive/commercial-frontend/pages/LeavePage.tsx diff --git a/frontend/src/pages/PerformancePage.tsx b/docs/archive/commercial-frontend/pages/PerformancePage.tsx similarity index 100% rename from frontend/src/pages/PerformancePage.tsx rename to docs/archive/commercial-frontend/pages/PerformancePage.tsx diff --git a/frontend/src/pages/RoutinePage.tsx b/docs/archive/commercial-frontend/pages/RoutinePage.tsx similarity index 100% rename from frontend/src/pages/RoutinePage.tsx rename to docs/archive/commercial-frontend/pages/RoutinePage.tsx diff --git a/frontend/src/pages/WorkflowPage.tsx b/docs/archive/commercial-frontend/pages/WorkflowPage.tsx similarity index 100% rename from frontend/src/pages/WorkflowPage.tsx rename to docs/archive/commercial-frontend/pages/WorkflowPage.tsx diff --git a/frontend/src/stores/modules.ts b/docs/archive/commercial-frontend/stores/modules.ts similarity index 100% rename from frontend/src/stores/modules.ts rename to docs/archive/commercial-frontend/stores/modules.ts diff --git a/eslint.config.mjs b/eslint.config.mjs index 776a236..d2defd8 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -28,6 +28,7 @@ export default tseslint.config( "eslint.config.*", "_*", "tmp-archive/**", + "docs/archive/**", "**/*.js", "**/*.mjs", "**/*.cjs", diff --git a/frontend/src/components/Footer.tsx b/frontend/src/components/Footer.tsx index 55228fd..d61cc3f 100644 --- a/frontend/src/components/Footer.tsx +++ b/frontend/src/components/Footer.tsx @@ -1,10 +1,11 @@ import { useLocale } from "../i18n"; +import { OPENXYOS_VERSION } from "../openxyos-identity"; export default function Footer() { const { message } = useLocale(); return ( ); } diff --git a/frontend/src/components/Header.tsx b/frontend/src/components/Header.tsx index dce308b..be3ba96 100644 --- a/frontend/src/components/Header.tsx +++ b/frontend/src/components/Header.tsx @@ -6,6 +6,7 @@ import { authFetch } from "../api/authFetch"; import { Sun, Moon, Menu, X, LogOut, Megaphone } from "lucide-react"; import NotificationPanel from "./NotificationPanel"; import { LanguageToggle, useLocale } from "../i18n"; +import { OPENXYOS_VERSION } from "../openxyos-identity"; interface HeaderProps { onMobileMenuToggle: () => void; @@ -58,7 +59,7 @@ export default function Header({ onMobileMenuToggle }: HeaderProps) { title={mobileOpen ? message("header.closeMenu") : message("header.openMenu")}> {mobileOpen ? : } - openXYOS + openXYOS {OPENXYOS_VERSION} {/* 置顶公告轮播 */} diff --git a/frontend/src/components/OpenSidebar.tsx b/frontend/src/components/OpenSidebar.tsx index ed3af0a..f99f949 100644 --- a/frontend/src/components/OpenSidebar.tsx +++ b/frontend/src/components/OpenSidebar.tsx @@ -4,6 +4,7 @@ import { Bell, Bot, Brain, Building2, ChevronLeft, LayoutDashboard, ListTodo, Me import type { LucideIcon } from "lucide-react"; import { useAuthStore } from "../stores/auth"; import { OpenModuleKey, useOpenModules } from "../open-modules"; +import { OPENXYOS_VERSION } from "../openxyos-identity"; import { useLocale } from "../i18n"; const NAV: Array<{path:string;key:OpenModuleKey;icon:LucideIcon;admin?:boolean}> = [ @@ -27,7 +28,7 @@ export default function OpenSidebar({collapsed,mobileOpen,onToggle,onMobileClose const render=(items:typeof NAV)=>items.map(item=>{if(!modules[item.key]||(item.admin&&!isAdmin))return null;const active=item.path==="/"?location.pathname==="/":location.pathname===item.path||location.pathname.startsWith(item.path+"/");return go(item.path)} title={collapsed ? (isEnglish ? EN_MODULE_LABELS[item.key] : labels[item.key]) : undefined} className={`w-full flex items-center ${collapsed?"justify-center px-2":"gap-3 px-3"} py-2 rounded text-sm transition-all ${active?"bg-primary text-white shadow-sm":"text-text-muted hover:bg-bg hover:text-text"}`}>{showText&&{isEnglish ? EN_MODULE_LABELS[item.key] : labels[item.key]}}}); const content=; diff --git a/frontend/src/locales/system.ts b/frontend/src/locales/system.ts index 34bf2c9..a4cf767 100644 --- a/frontend/src/locales/system.ts +++ b/frontend/src/locales/system.ts @@ -8,7 +8,7 @@ export const zhCN = { "common.refreshNow": "立即刷新", "common.updateLater": "稍后更新", "pwa.updateReady": "发现新版本,刷新后即可使用最新功能。", - "footer.community": "openXYOS 社区版 · Apache License 2.0 · 开放共建", + "footer.community": "openXYOS 社区版 {version} · Apache License 2.0 · 开放共建", "header.openMenu": "打开菜单", "header.closeMenu": "关闭菜单", "header.viewAnnouncement": "点击查看公告详情", @@ -39,7 +39,7 @@ export const en = { "common.refreshNow": "Refresh now", "common.updateLater": "Update later", "pwa.updateReady": "A new version is ready. Refresh to use the latest features.", - "footer.community": "openXYOS Community · Apache License 2.0 · Built in the open", + "footer.community": "openXYOS Community {version} · Apache License 2.0 · Built in the open", "header.openMenu": "Open menu", "header.closeMenu": "Close menu", "header.viewAnnouncement": "View announcement", diff --git a/frontend/src/openxyos-identity.ts b/frontend/src/openxyos-identity.ts new file mode 100644 index 0000000..c7bfff5 --- /dev/null +++ b/frontend/src/openxyos-identity.ts @@ -0,0 +1,5 @@ +import { version as packageVersion } from "../../package.json"; + +export const OPENXYOS_PRODUCT = "openXYOS"; +export const OPENXYOS_EDITION = "community"; +export const OPENXYOS_VERSION = packageVersion; diff --git a/package.json b/package.json index 01bd7a4..8e6484b 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,9 @@ "postinstall": "node scripts/patch-express-types.cjs", "typecheck": "tsc --noEmit", "lint": "eslint . --ext .ts,.tsx --max-warnings 0", - "test": "npm run i18n:check && npm run test:localized-errors && npm run test:runtime-config && npm run test:r0-access-control && npm run test:module-settings && npm run test:llm-onboarding && npm run test:ai-language && npm run test:agent-studio && npm run test:file-security && npm run test:download-token && npm run test:ws-ticket && npm run test:auth-provider && npm run test:pep && npm run test:audit-bundle && npm run test:tool-gateway && npm run test:v100", + "test": "npm run i18n:check && npm run test:localized-errors && npm run test:runtime-config && npm run test:openxyos-identity && npm run test:r0-access-control && npm run test:module-settings && npm run test:llm-onboarding && npm run test:ai-language && npm run test:agent-studio && npm run test:file-security && npm run test:download-token && npm run test:ws-ticket && npm run test:auth-provider && npm run test:pep && npm run test:audit-bundle && npm run test:tool-gateway && npm run test:v100", "test:runtime-config": "tsx scripts/test-runtime-config.ts", + "test:openxyos-identity": "tsx scripts/test-openxyos-identity.ts", "test:r0-access-control": "tsx scripts/test-r0-access-control.ts", "test:file-security": "tsx scripts/test-file-security.ts", "test:download-token": "tsx scripts/test-download-token.ts", diff --git a/scripts/test-openxyos-identity.ts b/scripts/test-openxyos-identity.ts new file mode 100644 index 0000000..31fbbe7 --- /dev/null +++ b/scripts/test-openxyos-identity.ts @@ -0,0 +1,53 @@ +import assert from "node:assert/strict"; +import fs from "node:fs"; +import path from "node:path"; +import { OPENXYOS_MODULES } from "../backend/open-module-catalog"; +import { CURRENT_VERSION, OPENXYOS_PRODUCT, OPENXYOS_VERSION } from "../backend/version"; +import { CURRENT_VERSION as CONFIG_VERSION, OPENXYOS_VERSION as CONFIG_OPENXYOS_VERSION } from "../backend/config/version"; +import { getFeatureVersion } from "../backend/config/features"; + +const root = path.resolve(import.meta.dirname, ".."); +const pkg = JSON.parse(fs.readFileSync(path.join(root, "package.json"), "utf8")) as { version: string }; + +assert.equal(pkg.version, "0.6.3"); +assert.equal(OPENXYOS_VERSION, pkg.version); +assert.equal(CURRENT_VERSION.semver, pkg.version); +assert.equal(CURRENT_VERSION.product, "openXYOS"); +assert.equal(CURRENT_VERSION.featureVersion, pkg.version); +assert.equal(CONFIG_VERSION.semver, pkg.version); +assert.equal(CONFIG_OPENXYOS_VERSION, pkg.version); +assert.equal(getFeatureVersion(), pkg.version); +assert.doesNotMatch(OPENXYOS_VERSION, /4\.5/); +assert.equal(OPENXYOS_PRODUCT, "openXYOS"); +assert.equal(OPENXYOS_MODULES.length, 12); +assert.deepEqual(OPENXYOS_MODULES.map(module => module.key), [ + "workspace", "announcements", "organization", "employees", "skills", "chat", + "agents", "tasks", "knowledge", "reflections", "governance", "settings", +]); + +const serverSource = fs.readFileSync(path.join(root, "backend/server.ts"), "utf8"); +assert.match(serverSource, /openModuleSettingsRoutes/); +assert.doesNotMatch(serverSource, /from ["'].*\/routes\/module-settings["']/); +assert.doesNotMatch(serverSource, /from ["'].*module-catalog["']/); + +assert.ok(!fs.existsSync(path.join(root, "backend/module-catalog.ts"))); +assert.ok(!fs.existsSync(path.join(root, "backend/routes/module-settings.ts"))); +assert.ok(!fs.existsSync(path.join(root, "frontend/src/App.tsx"))); +assert.ok(fs.existsSync(path.join(root, "docs/archive/commercial-backend/module-catalog.ts"))); +assert.ok(fs.existsSync(path.join(root, "docs/archive/XYOS-CHANGELOG.md"))); + +const healthSource = fs.readFileSync(path.join(root, "backend/routes/health.ts"), "utf8"); +assert.match(healthSource, /OPENXYOS_VERSION/); +assert.doesNotMatch(healthSource, /0\.50\.0-dev|4\.5\.2|0\.4\.5\.3|(?