Metadata-Version: 2.4
Name: orgchart-swan
Version: 0.1.1
Summary: A CLI tool to serve interactive organization charts from Excel data
Author-email: Chandler <275737875@qq.com>
License-Expression: MIT
Keywords: orgchart,organization,chart,excel,d3,visualization
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: End Users/Desktop
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Office/Business
Classifier: Topic :: Utilities
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: flask>=2.0.0
Requires-Dist: pandas>=1.5.0
Requires-Dist: watchdog>=2.0.0
Requires-Dist: typer>=0.9.0
Requires-Dist: openpyxl>=3.0.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: build>=0.8.0; extra == "dev"
Requires-Dist: twine>=4.0.0; extra == "dev"
Dynamic: license-file

# OrgChart-Swan

OrgChart-Swan 是一款 Python CLI 工具，可将 Excel 表格转换为交互式、可搜索的组织架构图。只需在 Excel 中定义团队结构，运行本地服务器，即可通过基于 D3.js 的美观图表浏览组织架构，支持简历弹窗、实时更新和多格式导出。

## 功能特性

1. **Excel 驱动数据管理**：在任何电子表格编辑器（Excel、Google Sheets、LibreOffice）中编辑组织架构，无需数据库或复杂配置。
2. **交互式 D3.js 可视化**：基于 d3-org-chart 构建，支持平滑缩放、拖拽、折叠/展开和搜索。
3. **智能搜索与高亮**：按姓名、职位、地点、公司或部门搜索，匹配节点自动高亮，祖先路径自动展开。
4. **简历弹窗**：带有简历数据的节点显示 "Resume" 标签，点击打开精美的 Markdown 渲染弹窗。
5. **实时热重载**：服务器运行时编辑 Excel 文件，图表通过 Server-Sent Events (SSE) 自动刷新。
6. **多种导出格式**：一键导出当前视图、完整图表、SVG 或 PDF。
7. **CLI 数据导出**：支持将 Excel 数据导出为 JSON、CSV、Excel 格式。
8. **数据格式检查**：内置 `check` 命令，可预先验证 Excel 文件格式是否正确。
9. **列名映射查看**：`show` 命令可查看所有支持的列名及其中英文别名。
10. **双语列名支持**：Excel 列头支持中英文别名，不区分大小写。
11. **零配置启动**：通过 pip 安装后，直接 serve Excel 文件即可运行。
12. **完善的异常处理**：文件不存在、格式错误、端口冲突等场景均有清晰的彩色错误提示。
13. **`demo` 快速上手命令**：内置示例数据与交互式教程，新手用户无需准备文件即可一键体验完整功能。
14. **内置示例数据导出**：`export` 命令支持不指定文件，直接使用内置示例数据进行导出，便于了解数据格式。
15. **完善的字段说明**：`demo` 命令提供详细的 Excel 字段含义说明和填写示例，降低学习成本。

## 安装和环境配置

需要 Python 3.8 或更高版本。

### 通过 pip 安装

```bash
pip install orgchart-swan
```


### 系统要求

- Python >= 3.8
- 现代浏览器（Chrome、Firefox、Safari、Edge）

## 使用示例和代码片段

### 快速开始（新手推荐）

无需准备任何文件，30 秒即可看到效果：

```bash
# 1. 复制示例文件并启动服务器
orgchart demo

# 2. 浏览器自动打开，查看交互式组织架构图
# 3. 对照示例文件了解数据格式，修改为自己的数据
```

`demo` 命令会自动复制示例 Excel 文件到当前目录，并显示完整的使用教程。如果你已经准备好了 Excel 文件，可以直接使用：

```bash
orgchart serve company.xlsx
```

浏览器将自动打开 `http://localhost:8080`，展示交互式架构图。

### CLI 命令

#### serve — 启动服务器

```bash
orgchart serve <excel_file> [选项]
```

| 选项 | 简写 | 默认值 | 说明 |
|------|------|--------|------|
| `--port` | `-p` | `8080` | 服务器端口 |
| `--host` | `-h` | `127.0.0.1` | 绑定主机 |
| `--watch / --no-watch` | `-w` | 启用 | 监听 Excel 文件变化 |
| `--browser / --no-browser` | `-b` | 启用 | 自动打开浏览器 |
| `--version` | `-v` | - | 显示版本并退出 |

```bash
# 使用自定义端口
orgchart serve org.xlsx --port 3000

# 禁用自动打开浏览器和文件监听
orgchart serve org.xlsx --no-browser --no-watch

# 绑定到所有网络接口（局域网共享）
orgchart serve org.xlsx --host 0.0.0.0 --port 8080

# 显示版本
orgchart --version
```

#### demo — 快速上手与教程

```bash
orgchart demo [选项]
```

| 选项 | 简写 | 默认值 | 说明 |
|------|------|--------|------|
| `--output-dir` | `-d` | 当前目录 | 示例 Excel 文件的复制目标目录 |
| `--port` | `-p` | `8080` | 服务器端口（自动启动时） |
| `--host` | `-h` | `127.0.0.1` | 绑定主机（自动启动时） |
| `--auto-start / --no-auto-start` | - | 启用 | 是否自动启动服务器 |

```bash
# 默认模式：复制示例文件到当前目录，显示教程，并自动启动服务器
orgchart demo

# 仅复制示例文件和显示教程，不启动服务器
orgchart demo --no-auto-start

# 复制到指定目录
orgchart demo --output-dir ./my-org

# 自定义端口启动
orgchart demo --port 9090
```

执行效果：

- 若当前目录不存在 `sample_excel.xlsx`，自动从项目示例目录复制一份
- 终端显示彩色格式化的使用教程，包括：
  - 所有字段的中文名称、英文名称及含义
  - 必填字段（`name`、`position`）和可选字段说明
  - 层级规则（`parentId` 如何定义汇报关系）
  - 修改指引和注意事项
- 若启用 `--auto-start`，自动使用该示例文件启动服务器，浏览器打开可视化页面

#### export — 导出数据

```bash
orgchart export [excel_file] --type <json|csv|excel> [--output PATH]
```

```bash
# 使用内置示例数据导出为 JSON（默认）
orgchart export --type json

# 使用内置示例数据导出为 CSV
orgchart export --type csv

# 使用自己的 Excel 文件导出
orgchart export company.xlsx

# 导出为 Excel
orgchart export company.xlsx --type excel

# 指定输出路径
orgchart export company.xlsx --type json --output /tmp/org_data.json
```

**新特性**：当不提供 `excel_file` 参数时，系统会自动使用内置的示例组织架构数据（与 `demo` 命令中的示例一致），默认输出到当前工作目录，文件名为 `orgchart_demo.json` / `orgchart_demo.csv` / `orgchart_export.xlsx`。

#### show — 查看列名映射

```bash
# 显示所有支持的列及其中英文别名
orgchart show

# 仅查看某一列的映射
orgchart show --column name
```

#### check — 检查数据格式

```bash
orgchart check company.xlsx
```

检查内容包括：文件存在性、扩展名有效性、必填列是否缺失、ID 是否重复、parentId 是否指向不存在的节点、是否存在循环依赖等。检查通过返回绿色提示，失败则逐条列出具体错误。

### 新手完整使用流程

以下是从零开始到生成自己公司组织架构图的完整步骤：

#### 第 1 步：体验示例效果

```bash
# 复制示例文件并自动启动服务
orgchart demo
```

浏览器自动打开后，你可以：
- 缩放、拖拽查看完整的组织架构图
- 点击节点查看简历弹窗
- 使用搜索框查找特定人员
- 尝试导出为 SVG 或 PDF

#### 第 2 步：了解数据格式

运行 `demo` 命令后，终端会显示详细的字段说明。同时当前目录下会生成 `sample_excel.xlsx`，你可以用 Excel 或 WPS 打开查看：

```bash
# 查看示例数据的 JSON 格式（便于理解字段结构）
orgchart export --type json
```

#### 第 3 步：修改为自己的数据

复制 `sample_excel.xlsx` 并重命名，然后修改内容：

```bash
cp sample_excel.xlsx my_company.xlsx
```

修改要点：
1. **保留表头**：第一行是列名，不要删除或修改
2. **修改员工信息**：将示例中的姓名、职位替换为真实数据
3. **调整层级关系**：通过 `parentId` 列定义汇报关系。例如，某员工的 `parentId` 填 `1`，表示他汇报给 `id=1` 的人
4. **根节点留空**：CEO 或最高负责人的 `parentId` 列留空
5. **保存并刷新**：保存文件后，如果服务器仍在运行（带 `--watch`），页面会自动刷新

#### 第 4 步：启动自己的服务器

```bash
orgchart serve my_company.xlsx
```

### Python 模块调用

```python
from orgchart.excel_reader import load_org_data

nodes, errors, mtime = load_org_data("company.xlsx")
print(f"已加载 {len(nodes)} 名员工")
for node in nodes:
    print(f"{node.name} - {node.position}")
```

## Excel 数据格式

Excel 文件的第一行必须是表头。支持以下列（列名不区分大小写，支持中英文别名）：

### 必填列

| 列名 | 别名 | 说明 |
|------|------|------|
| `name` | 姓名、名字、名称、员工姓名 | 员工姓名 |
| `position` | 职位、岗位、职务、Title | 职位名称 |

### 可选列

| 列名 | 别名 | 说明 |
|------|------|------|
| `id` | ID、编号、序号 | 唯一标识符（省略时自动生成） |
| `parentId` | 上级ID、汇报对象、上级、父节点、manager | 上级节点 ID |
| `linkedin` | LinkedIn、领英、linkedin链接 | LinkedIn 个人资料链接 |
| `location` | 地点、位置、城市、办公地点 | 工作地点 |
| `company` | 公司、企业、所属公司 | 公司名称 |
| `department` | 部门、事业部、所属部门 | 部门名称 |
| `bio` | 简介、一句话简介、个人简介 | 一句话简介 |
| `resume` | 简历、详细简历、个人简历 | Markdown 格式的详细简历 |
| `image` | 头像、照片、图片、avatar | 头像图片 URL |
| `link` | 个人链接、主页、个人主页、website | 个人主页链接 |

### 层级规则

- 使用 `parentId` 定义汇报关系。
- 顶层节点的 `parentId` 应留空。
- 支持多个根节点。
- `id` 和 `parentId` 可以是数字或字符串，内部统一按字符串处理。
- 省略 `id` 时，自动从 1 开始递增分配。
- `parentId` 引用不存在的 ID 时，自动重置为 `None`（根节点）并发出警告。

### 示例数据结构

| id | parentId | name | position | location | company | department | linkedin | bio | resume |
|----|----------|------|----------|----------|---------|------------|----------|-----|--------|
| 1 | | Alex Chen | CEO | San Francisco | TechVision | Executive | https://... | 20+ years | # Resume... |
| 2 | 1 | Jamie O'Brien | CTO | Austin | TechVision | Engineering | https://... | Scaling... | # Resume... |
| 3 | 2 | Casey Li | Engineering Manager | Seattle | TechVision | Engineering | https://... | Full-stack... | # Resume... |

### 示例文件

- `examples/sample_excel.xlsx` — 完整模板，包含所有字段（公司、部门、简介等）。

## 前端交互特性

### 节点卡片布局

- **动态高度**：根据实际字段内容自动调整卡片高度， company/department 标签、location、bio 字段仅在存在时显示。
- **溢出省略**：所有文本字段（姓名、职位、地点、公司、部门、简介）超出宽度时自动截断，以省略号显示。
- **悬停浮层**：鼠标悬停在截断的文本上时，浏览器弹出原生浮层显示完整内容。
- **姓名点击跳转**：点击节点卡片上的姓名，在新标签页打开该员工的 LinkedIn 个人资料页。
- **Resume 标签**：右上角仅保留 "Resume" 标签（字体 9px），点击可打开 Markdown 简历弹窗。

### 搜索与导出

- 支持按姓名、职位、地点、公司、部门实时搜索过滤。
- 支持导出当前视图、完整图表、SVG、PDF。

## 项目架构

### 目录结构

```
orgchart/
├── orgchart/                 # 主包
│   ├── __init__.py          # 包初始化
│   ├── __main__.py          # python -m orgchart 入口
│   ├── cli.py              # Typer CLI 实现（serve/export/show/check）
│   ├── server.py           # Flask HTTP 服务器 + SSE
│   ├── excel_reader.py     # Excel 读取（pandas）
│   ├── data_models.py      # 数据模型（dataclasses）
│   ├── watcher.py          # 文件系统监听（watchdog）
│   └── static/             # 前端资源
│       └── index.html      # 交互式图表 UI
├── examples/               # 示例文件
│   ├── sample_org.xlsx     # 原始 14 人示例
│   └── sample_excel.xlsx   # 全字段模板
├── tests/                  # 测试套件
│   ├── test_cli.py
│   ├── test_data_models.py
│   ├── test_excel_reader.py
│   └── test_server.py
├── README.md              # 项目文档
├── LICENSE                # MIT 许可证
├── pyproject.toml         # 项目配置
└── requirements.txt       # 运行时依赖
```

### 数据流

```
Excel 文件 (.xlsx)
    |
    v
pandas.read_excel()  -->  orgchart/excel_reader.py
    |
    v
OrgNode 数据类        -->  orgchart/data_models.py
    |
    v
Flask REST API       -->  orgchart/server.py
    |                     /api/data, /api/config, /api/events
    v
前端 (D3.js)         -->  orgchart/static/index.html
    |
    v
浏览器渲染 + SSE 实时更新
```

### 组件交互

- **cli.py**：解析命令行参数，启动服务器或执行导出/查看/检查命令。
- **server.py**：创建 Flask 应用，提供静态文件服务和 REST/SSE 接口。
- **excel_reader.py**：通过 pandas 读取 Excel，标准化列名，验证数据，并将行转换为 `OrgNode` 对象。
- **data_models.py**：定义 `OrgNode`、`OrgMeta`、`OrgConfigResponse` 数据类，以及双语列名映射表。
- **watcher.py**：使用 watchdog 监听 Excel 文件变化，变化时调用 `reload_data()` 并通过 SSE 向所有浏览器广播更新事件。
- **index.html**：从 `/api/data` 获取数据，使用 `d3-org-chart` 渲染组织架构图，通过 `marked.js` 打开简历弹窗，并通过 `/api/events` 的 SSE 监听实时更新。

## API 接口说明

### GET /api/data

返回完整的组织数据（JSON 格式）。

```json
{
  "data": [
    {
      "id": "1",
      "parentId": null,
      "name": "Alex Chen",
      "position": "CEO & Founder",
      "location": "San Francisco, CA",
      "company": "TechVision",
      "department": "Executive",
      "linkedin": "https://linkedin.com/in/alexchen",
      "bio": "20+ years in tech industry",
      "resume": "# Alex Chen\n\n## Experience...",
      "image": "https://...",
      "link": "https://alexchen.dev"
    }
  ],
  "meta": {
    "total": 14,
    "generatedAt": "2026-05-09T12:00:00",
    "source": "company.xlsx",
    "version": "0.1.0"
  },
  "errors": []
}
```

### GET /api/config

返回服务器配置信息。

```json
{
  "watchEnabled": true,
  "lastModified": "2026-05-09T12:00:00",
  "columns": ["id", "parentId", "name", "position", "location",
              "company", "department", "linkedin", "bio", "resume",
              "image", "link"]
}
```

### GET /api/events

Server-Sent Events (SSE) 端点。浏览器通过 `EventSource` 连接，接收 Excel 文件变化时的实时更新。

```
event: connected
data: {}

event: data-update
data: {"message": "Excel file updated", "timestamp": "2026-05-09T12:00:00Z"}
```

### GET /

返回交互式前端应用（HTML/CSS/JS）。

## 依赖项清单

### 运行时依赖

| 包名 | 版本 | 用途 |
|------|------|------|
| Flask | >=2.0.0 | HTTP 服务器和静态文件服务 |
| pandas | >=1.5.0 | Excel 数据读取和处理 |
| watchdog | >=2.0.0 | 文件系统监听，实现热重载 |
| typer | >=0.9.0 | CLI 参数解析 |
| openpyxl | - | pandas 读取 .xlsx 所需的引擎 |

### 前端依赖（CDN）

| 库名 | 版本 | 用途 |
|------|------|------|
| D3.js | v7 | 数据可视化核心 |
| d3-org-chart | 3.0.1 | 组织架构图渲染 |
| d3-flextree | 2.1.2 | 灵活树形布局 |
| marked.js | latest | Markdown 简历渲染 |
| html2canvas | 1.1.4 | 图片导出（Canvas） |
| jsPDF | 2.3.1 | PDF 导出 |

### 开发依赖

| 包名 | 版本 | 用途 |
|------|------|------|
| pytest | >=7.0.0 | 单元测试 |
| build | >=0.8.0 | 打包构建 |
| twine | >=4.0.0 | PyPI 发布 |

## 故障排除

### `ModuleNotFoundError: No module named 'pandas'`

安装项目及其依赖：
```bash
pip install -e .
```

### `ImportError: Missing dependency for reading Excel files`

pandas 需要引擎来读取 `.xlsx` 文件。安装 openpyxl：
```bash
pip install openpyxl
```

### 端口已被占用

更换端口：
```bash
orgchart serve company.xlsx --port 9090
```

### Excel 文件修改后图表未更新

确保已保存文件。如果使用了 `--no-watch`，需手动重启服务器。

### 浏览器未自动打开

使用 `--no-browser`，然后手动访问终端打印的 URL。

### 循环依赖警告

检查 `parentId` 是否形成环路（如 A 的上级是 B，B 的上级是 A）。工具会自动检测并打断循环，同时发出警告。

## 贡献指南与许可证

### 贡献指南

欢迎贡献！参与方式：

1. Fork 本仓库
2. 创建功能分支（`git checkout -b feature/amazing-feature`）
3. 提交更改（`git commit -m 'Add amazing feature'`）
4. 推送到分支（`git push origin feature/amazing-feature`）
5. 发起 Pull Request

请确保代码通过现有测试，并为新功能添加测试。

### 许可证

本项目采用 MIT 许可证。详见 [LICENSE](LICENSE) 文件。


## 免责声明

本软件按"现状"提供，不提供任何明示或暗示的担保，包括但不限于对适销性、特定用途适用性和非侵权性的担保。在任何情况下，作者或版权持有人均不对因使用本软件或与本软件相关的其他交易而产生的任何索赔、损害或其他责任负责，无论是合同诉讼、侵权行为还是其他情况。

使用本软件生成的组织架构图和数据导出结果仅供参考，用户应自行核实数据的准确性和完整性。本软件不会将任何数据上传至远程服务器，所有数据处理均在本地完成。
