From 333f65f10a6098c216a3eb9625a1b1a29514f309 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 17 Sep 2026 14:31:06 +0000 Subject: [PATCH 1/2] align public identity to openXYOS 0.6.3 Use package.json as the only product version for health, runtime, and UI. Archive commercial XYOS changelog, catalog, and unused pages so the community shell stays on the 12-module OpenApp routes. Signed-off-by: Cursor Agent Co-authored-by: XYAI Labs --- CHANGELOG.md | 351 +----------------- backend/config/features.ts | 25 +- backend/config/version.ts | 206 +--------- backend/openxyos-identity.ts | 14 + backend/routes/health.ts | 15 +- backend/server.ts | 3 +- backend/services/mcp-client.ts | 3 +- backend/services/mcp-server.ts | 5 +- backend/version.ts | 188 ++-------- docs/architecture.md | 2 +- docs/archive/README.md | 11 + docs/archive/XYOS-CHANGELOG.md | 346 +++++++++++++++++ .../commercial-backend}/module-catalog.ts | 0 .../routes/module-settings.ts | 0 .../archive/commercial-frontend}/App.tsx | 0 .../components/ModuleManagementTab.tsx | 0 .../components/Sidebar.tsx | 0 .../components/SmartAssistant.tsx | 0 .../components/workflow/FlowDesigner.tsx | 0 .../components/workflow/FlowPreview.tsx | 0 .../components/workflow/FormDesigner.tsx | 0 .../components/workflow/WorkflowDesigner.tsx | 0 .../components/workflow/types.ts | 0 .../commercial-frontend}/config/modules.ts | 0 .../commercial-frontend}/pages/AdminPage.tsx | 0 .../pages/AssetCountPage.tsx | 0 .../pages/AssetDashboard.tsx | 0 .../pages/AssetDetailPage.tsx | 0 .../commercial-frontend}/pages/AssetPage.tsx | 0 .../pages/AssetProcurementPage.tsx | 0 .../pages/AssetVehicleExpensePage.tsx | 0 .../pages/AttendancePage.tsx | 0 .../pages/AuditTrailPage.tsx | 0 .../commercial-frontend}/pages/BudgetPage.tsx | 0 .../pages/ConfigVersionPage.tsx | 0 .../pages/ContractPage.tsx | 0 .../pages/CustomerServicePage.tsx | 0 .../pages/DailyReportPage.tsx | 0 .../commercial-frontend}/pages/Dashboard.tsx | 0 .../pages/EfficiencyDashboard.tsx | 0 .../pages/ElectricityMarketPage.tsx | 0 .../pages/ExpensePage.tsx | 0 .../commercial-frontend}/pages/GoalPage.tsx | 0 .../commercial-frontend}/pages/LeavePage.tsx | 0 .../pages/PerformancePage.tsx | 0 .../pages/RoutinePage.tsx | 0 .../pages/WorkflowPage.tsx | 0 .../commercial-frontend}/stores/modules.ts | 0 eslint.config.mjs | 1 + frontend/src/components/Footer.tsx | 3 +- frontend/src/components/Header.tsx | 3 +- frontend/src/components/OpenSidebar.tsx | 3 +- frontend/src/locales/system.ts | 4 +- frontend/src/openxyos-identity.ts | 5 + package.json | 3 +- scripts/test-openxyos-identity.ts | 53 +++ tsconfig.json | 3 +- 57 files changed, 533 insertions(+), 714 deletions(-) create mode 100644 backend/openxyos-identity.ts create mode 100644 docs/archive/README.md create mode 100644 docs/archive/XYOS-CHANGELOG.md rename {backend => docs/archive/commercial-backend}/module-catalog.ts (100%) rename {backend => docs/archive/commercial-backend}/routes/module-settings.ts (100%) rename {frontend/src => docs/archive/commercial-frontend}/App.tsx (100%) rename {frontend/src => docs/archive/commercial-frontend}/components/ModuleManagementTab.tsx (100%) rename {frontend/src => docs/archive/commercial-frontend}/components/Sidebar.tsx (100%) rename {frontend/src => docs/archive/commercial-frontend}/components/SmartAssistant.tsx (100%) rename {frontend/src => docs/archive/commercial-frontend}/components/workflow/FlowDesigner.tsx (100%) rename {frontend/src => docs/archive/commercial-frontend}/components/workflow/FlowPreview.tsx (100%) rename {frontend/src => docs/archive/commercial-frontend}/components/workflow/FormDesigner.tsx (100%) rename {frontend/src => docs/archive/commercial-frontend}/components/workflow/WorkflowDesigner.tsx (100%) rename {frontend/src => docs/archive/commercial-frontend}/components/workflow/types.ts (100%) rename {frontend/src => docs/archive/commercial-frontend}/config/modules.ts (100%) rename {frontend/src => docs/archive/commercial-frontend}/pages/AdminPage.tsx (100%) rename {frontend/src => docs/archive/commercial-frontend}/pages/AssetCountPage.tsx (100%) rename {frontend/src => docs/archive/commercial-frontend}/pages/AssetDashboard.tsx (100%) rename {frontend/src => docs/archive/commercial-frontend}/pages/AssetDetailPage.tsx (100%) rename {frontend/src => docs/archive/commercial-frontend}/pages/AssetPage.tsx (100%) rename {frontend/src => docs/archive/commercial-frontend}/pages/AssetProcurementPage.tsx (100%) rename {frontend/src => docs/archive/commercial-frontend}/pages/AssetVehicleExpensePage.tsx (100%) rename {frontend/src => docs/archive/commercial-frontend}/pages/AttendancePage.tsx (100%) rename {frontend/src => docs/archive/commercial-frontend}/pages/AuditTrailPage.tsx (100%) rename {frontend/src => docs/archive/commercial-frontend}/pages/BudgetPage.tsx (100%) rename {frontend/src => docs/archive/commercial-frontend}/pages/ConfigVersionPage.tsx (100%) rename {frontend/src => docs/archive/commercial-frontend}/pages/ContractPage.tsx (100%) rename {frontend/src => docs/archive/commercial-frontend}/pages/CustomerServicePage.tsx (100%) rename {frontend/src => docs/archive/commercial-frontend}/pages/DailyReportPage.tsx (100%) rename {frontend/src => docs/archive/commercial-frontend}/pages/Dashboard.tsx (100%) rename {frontend/src => docs/archive/commercial-frontend}/pages/EfficiencyDashboard.tsx (100%) rename {frontend/src => docs/archive/commercial-frontend}/pages/ElectricityMarketPage.tsx (100%) rename {frontend/src => docs/archive/commercial-frontend}/pages/ExpensePage.tsx (100%) rename {frontend/src => docs/archive/commercial-frontend}/pages/GoalPage.tsx (100%) rename {frontend/src => docs/archive/commercial-frontend}/pages/LeavePage.tsx (100%) rename {frontend/src => docs/archive/commercial-frontend}/pages/PerformancePage.tsx (100%) rename {frontend/src => docs/archive/commercial-frontend}/pages/RoutinePage.tsx (100%) rename {frontend/src => docs/archive/commercial-frontend}/pages/WorkflowPage.tsx (100%) rename {frontend/src => docs/archive/commercial-frontend}/stores/modules.ts (100%) create mode 100644 frontend/src/openxyos-identity.ts create mode 100644 scripts/test-openxyos-identity.ts 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 (
- {message("footer.community")} + {message("footer.community", { version: OPENXYOS_VERSION })}
); } 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 }); 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..157c551 --- /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|XYOS_VERSION/); + +const versionSource = fs.readFileSync(path.join(root, "backend/version.ts"), "utf8"); +assert.doesNotMatch(versionSource, /4\.5\.2|0\.4\.5\.3|BranchControl/); + +const frontendIdentity = fs.readFileSync(path.join(root, "frontend/src/openxyos-identity.ts"), "utf8"); +assert.match(frontendIdentity, /package\.json/); + +const openApp = fs.readFileSync(path.join(root, "frontend/src/OpenApp.tsx"), "utf8"); +assert.match(openApp, /OpenDashboard/); +assert.doesNotMatch(openApp, /WorkflowPage|ContractPage|AttendancePage|AssetPage/); + +console.log(`openXYOS identity tests passed (${OPENXYOS_PRODUCT} ${OPENXYOS_VERSION}, ${OPENXYOS_MODULES.length} modules)`); diff --git a/tsconfig.json b/tsconfig.json index 7a04df7..c5e0fd8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -24,6 +24,7 @@ "backups", "backend/backups", "V0.5", - "dist-backup-20260626" + "dist-backup-20260626", + "docs/archive" ] } From 33d7f3aff00d40e33d7b85d24abd0ec604a3119f Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 17 Sep 2026 14:33:17 +0000 Subject: [PATCH 2/2] fix identity test matching OPENXYOS_VERSION Avoid treating the new constant name as the retired XYOS_VERSION env fallback. Signed-off-by: Cursor Agent Co-authored-by: XYAI Labs --- scripts/test-openxyos-identity.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/test-openxyos-identity.ts b/scripts/test-openxyos-identity.ts index 157c551..31fbbe7 100644 --- a/scripts/test-openxyos-identity.ts +++ b/scripts/test-openxyos-identity.ts @@ -38,7 +38,7 @@ 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|XYOS_VERSION/); +assert.doesNotMatch(healthSource, /0\.50\.0-dev|4\.5\.2|0\.4\.5\.3|(?