一个把 PowerDesigner 导出的 .pdm 文件直接拖进浏览器就能看的小工具。后端拿到文件后用 lxml 解析 XML,把表、字段、主外键关系、索引抽出来;前端用 React Flow 画 ER 图,点击任意表都能立刻看到列定义和关联关系。
不上传到任何远端服务器,文件解析后只存在后端进程内存里,重启服务就清掉。适合本地临时看一下 PDM,或者给团队演示数据模型时用。
- 拖拽上传
.pdm文件,支持 PowerDesigner 12/15/16/17 导出的版本 - 解析能力增强:支持"根 Model 直接挂表"和"多层
Package嵌套组织"两种典型 PDM 结构(大型复杂 PDM 的表常常分散在多个子包下,都能被递归扫描到并正确去重) - 左侧模型树浏览所有表,支持搜索筛选 — 按表名/代码、字段名/代码、注释全文搜,命中结果会带"表 / 字段"标签区分来源
- 中间区域可在「ER 图」和「表列表」两种视图之间切换
- ER 图使用 React Flow 渲染,支持多种布局(横向层次 LR、纵向层次 TB、环形、网格)、适配视图、重新应用布局、节点悬停高亮关联关系
- 右侧详情面板展示字段列表(代码 / 名称 / 类型 / 非空 ✔️)、索引、主键、外键与被引用关系
- DDL 生成:支持 MySQL / PostgreSQL / Oracle / SQL Server / SQLite 五种方言预览,可一键复制或下载
.sql文件 - 全格式导出:整库或单表可导出为 Excel (.xlsx)、CSV、Markdown、JSON 四种格式
- 左右两侧栏可折叠、可拖拽调整宽度;按钮 z-index 置顶避免与拖拽手柄冲突
- 内置一份电商示例模型(点击"加载示例数据",无需上传即可预览)
- 达到 500 张表或 1,000 条关系时,先显示虚拟表列表;进入 ER 视图时才加载图数据。大图默认网格布局、关闭小地图和连线动画,并只渲染视口附近的节点。
- 分层与环形布局在 Web Worker 中计算,切换视图或布局会取消旧任务;已完成的布局在当前页面内缓存。大图可拖动浏览,点击「适应视图」查看全图;选表后可切换「一层关联」。
- 表详情和单表 DDL 按需缓存;超过 100 个字段的表按每页 50 个字段显示。切表、搜索或切换 DDL 方言时会取消旧请求。
- 在
frontend/执行npm test运行图算法回归测试,npm run build验证生产构建。启动开发服务后,打开/tests/performance.html可用 1,000 张合成表检查滚动、布局切换和页面响应;该测试页面不包含在生产构建中。
| 层 | 技术 |
|---|---|
| 前端 | React 18、TypeScript 5、Vite 5、Ant Design 5、@xyflow/react (React Flow)、dagre(层次布局) |
| 后端 | Python 3.10+、FastAPI 0.115、uvicorn、lxml、Pydantic v2、openpyxl(Excel 导出) |
| 通信 | REST + JSON,前端开发期由 Vite 代理 /api 到后端 |
pdm-viewer/
├── backend/
│ ├── app/
│ │ ├── main.py # FastAPI 入口(日志、路由注册)
│ │ ├── pdm_parser.py # PDM XML 解析:支持 a/c/o 命名空间 + Package 递归 + 真假表过滤
│ │ ├── ddl.py # DDL 生成:5 种方言类型映射
│ │ ├── exporters.py # 导出 Excel / CSV / Markdown / JSON
│ │ ├── schemas.py # Pydantic 模型(表/列/搜索结果/DDL 参数等)
│ │ ├── storage.py # 内存存储 + 列表接口 + 搜索
│ │ └── routers/
│ │ ├── pdm.py # 上传 / 模型查询 / 搜索 / 加载示例
│ │ └── output.py # DDL / 导出 下载接口
│ ├── sample.pdm # 示例文件(电商 5 张表)
│ └── requirements.txt
└── frontend/
├── src/
│ ├── App.tsx # 页面主布局 + 左右可拖拽/折叠栏
│ ├── api/ # 接口封装
│ ├── components/ # Header / UploadZone / ModelTree / ERDiagram / Inspector
│ ├── types/ # 类型定义
│ └── styles/global.css
├── index.html
├── nginx.conf # 生产用:静态托管 + /api 反代 + 大文件/超时
├── package.json
├── vite.config.ts
├── Dockerfile
└── .dockerignore
需要本机已安装 Node.js 18+ 和 Python 3.10+。
-
启动后端(监听 8000 端口):
cd backend python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate pip install -r requirements.txt uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
-
另开一个终端启动前端(监听 5173 端口):
cd frontend npm install npm run dev -
浏览器打开
http://localhost:5173/,点「加载示例数据」即可看到效果,也可以直接拖入自己的.pdm文件。
推荐使用仓库根目录自带的 docker-compose 编排(前后端两个容器)。前端容器里 nginx 托管静态文件,并把 /api、/docs、/openapi.json 反代到后端容器,对外只开一个端口。
# 在项目根目录执行(一次性完成前后端构建 + 启动)
docker compose up -d --build启动完成后访问 http://localhost:8080/ 即可。查看日志、停止、重启:
docker compose logs -f # 查看实时日志
docker compose down # 停止并删除容器
docker compose restart # 重启服务如果不想用 compose,也可以手动分开部署:前端构建产物交给 Nginx,后端用 uvicorn 跑在 8000 端口,Nginx 中把 /api/ 转发到 8000,其余路径指向 frontend/dist。
# 不使用 compose 时的手动构建参考
cd frontend && npm run build # 产物在 frontend/dist
cd ../backend && uvicorn app.main:app --host 0.0.0.0 --port 8000- backend:基于
python:3.10-slim,内部监听 8000,只在 compose 内部网络暴露,默认不映射到宿主机;如需直接访问 Swagger 文档,可在docker-compose.yml中把ports: "8000:8000"的注释打开。 - frontend:两阶段构建,阶段 1 用
node:20-alpine跑npm ci && npm run build,阶段 2 用nginx:1.27-alpine托管 dist 并配置反代,宿主机 8080 映射到容器 80。 - 构建时默认已启用国内 npm/pip 镜像加速(Dockerfile 中配置,如不需要可删除对应行)。
- nginx 已把上传大小调到 52MB,并预留了 120s 读写超时,与后端 50MB PDM 文件上限匹配。
所有接口前缀 /api/v1,返回 JSON(下载接口返回对应 Content-Type + Attachment)。
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /pdm/upload |
上传 .pdm 文件,返回 model_id 与 tables/columns/references 摘要 |
| POST | /pdm/load-sample |
直接加载内置示例模型,返回结构同 upload |
| GET | /models |
当前内存中已解析的所有模型列表(按创建时间倒序,摘要信息) |
| GET | /models/{model_id} |
模型概览 |
| GET | /models/{model_id}/tables |
表列表(轻量,用于左侧树 + 列表视图) |
| GET | /tables/{table_id} |
单表详情(字段、索引、主外键、被引用关系) |
| GET | /models/{model_id}/graph |
ER 图数据(nodes + edges,含层次/环形/网格布局支持) |
| GET | /models/{model_id}/search?q= |
搜索表/字段,命中带 表/字段 标签区分来源 |
| GET | /models/{model_id}/ddl?dialect=mysql |
整库 DDL(方言可选 mysql/postgres/oracle/sqlserver/sqlite) |
| GET | /tables/{table_id}/ddl?dialect=mysql |
单表 DDL |
| GET | /models/{model_id}/export?format=xlsx |
整库导出,格式:xlsx / csv / md / json |
| GET | /tables/{table_id}/export?format=xlsx |
单表导出 |
| GET | /pdm/sample |
示例 PDM 文件原文 |
- 文件大小上限 50MB
- 数据仅在内存中,服务重启即丢失
- 支持 PDM 结构:标准
a=(attribute)/c=(collection)/o=(object)命名空间的 PowerDesigner PDM XML,表可直接挂在根o:Model,也可分散在任意深度的o:Package下 - 暂不支持:PDM 中的物理视图、存储过程、触发器、跨文件引用(Proxy/Shortcut)、扩展自定义脚本;这些对象会被忽略,只保证表结构、列、主键、索引、外键引用关系正确
把 PowerDesigner 匯出的 .pdm 檔案直接拖進瀏覽器就能檢視的小工具。後端收到檔案後以 lxml 解析 XML,把資料表、欄位、主外鍵關聯、索引抽出來;前端用 React Flow 繪製 ER 圖,點任一資料表都能立刻看到欄位定義與關聯。
檔案不會上傳到任何遠端伺服器,解析後只留在後端行程的記憶體裡,重啟服務即清空。適合本機臨時看一下 PDM,或在團隊內部展示資料模型時使用。
- 拖拉上傳
.pdm檔案,支援 PowerDesigner 12/15/16/17 匯出的版本 - 解析能力強化:同時支援「根 Model 直接掛表」與「多層
Package巢狀組織」兩種常見 PDM 結構(大型複雜 PDM 的表常分散在多個子 Package 下,都會被遞迴掃描並正確去重) - 左側模型樹瀏覽所有資料表,支援篩選搜尋 — 依資料表名/代碼、欄位名/代碼、備註全文檢索,命中結果會標註「表 / 欄位」標籤區分來源
- 中間區域可在「ER 圖」與「資料表清單」兩種檢視之間切換
- ER 圖以 React Flow 呈現,提供多種佈局(橫向層次 LR、縱向層次 TB、環狀、方格)、適應視窗、重新套用佈局、節點 hover 時高亮度關聯連線
- 右側詳情面板顯示欄位清單(代碼 / 名稱 / 型別 / 非空 ✔️)、索引、主鍵、外鍵與被參考關聯
- DDL 生成:支援 MySQL / PostgreSQL / Oracle / SQL Server / SQLite 五種方言預覽,可一鍵複製或下載
.sql - 全格式匯出:整庫或單表可匯出為 Excel (.xlsx)、CSV、Markdown、JSON 四種格式
- 左右兩側欄可收合、可拖曳調整寬度;折疊按鈕 z-index 頂層避免與拖曳把手衝突
- 內附一份電商範例模型(按「載入範例資料」即可預覽,無需上傳)
- 達到 500 張表或 1,000 條關聯時,先顯示虛擬表列表;進入 ER 視圖時才載入圖資料。大圖預設網格佈局、關閉小地圖與連線動畫,僅渲染視口附近的節點。
- 分層與環形佈局在 Web Worker 計算,切換視圖或佈局會取消舊工作;已完成的佈局在目前頁面內快取。可拖動瀏覽、按「适应视图」查看全圖,或選表後切換「一层关联」。
- 表詳情與單表 DDL 按需快取;超過 100 個欄位時,每頁顯示 50 個。切表、搜尋或切換 DDL 方言會取消舊請求。
- 在
frontend/執行npm test與npm run build。開發服務的/tests/performance.html提供 1,000 張合成表驗證滾動與佈局回應;此測試頁不包含於正式構建。
| 層 | 技術 |
|---|---|
| 前端 | React 18、TypeScript 5、Vite 5、Ant Design 5、@xyflow/react (React Flow)、dagre(階層式佈局) |
| 後端 | Python 3.10+、FastAPI 0.115、uvicorn、lxml、Pydantic v2、openpyxl(Excel 匯出) |
| 通訊 | REST + JSON,前端開發期由 Vite 將 /api 代理到後端 |
pdm-viewer/
├── backend/
│ ├── app/
│ │ ├── main.py # FastAPI 入口(日誌、路由註冊)
│ │ ├── pdm_parser.py # PDM XML 解析:支援 a/c/o 命名空間 + Package 遞迴 + 真假表過濾
│ │ ├── ddl.py # DDL 生成:5 種方言型別對應
│ │ ├── exporters.py # 匯出 Excel / CSV / Markdown / JSON
│ │ ├── schemas.py # Pydantic 模型(表/欄/搜尋結果/DDL 參數等)
│ │ ├── storage.py # 記憶體儲存 + 列表 + 搜尋
│ │ └── routers/
│ │ ├── pdm.py # 上傳 / 模型查詢 / 搜尋 / 載入範例
│ │ └── output.py # DDL / 匯出 下載介面
│ ├── sample.pdm # 範例檔案(電商 5 張表)
│ └── requirements.txt
└── frontend/
├── src/
│ ├── App.tsx # 頁面主佈局 + 左右可拖曳/收合欄
│ ├── api/ # API 封裝
│ ├── components/ # Header / UploadZone / ModelTree / ERDiagram / Inspector
│ ├── types/ # 型別定義
│ └── styles/global.css
├── index.html
├── nginx.conf # 生產用:靜態代管 + /api 反代 + 大檔案/逾時
├── package.json
├── vite.config.ts
├── Dockerfile
└── .dockerignore
本機需先安裝 Node.js 18+ 與 Python 3.10+。
-
啟動後端(監聽 8000 埠):
cd backend python -m venv venv source venv/bin/activate # Windows 請用 venv\Scripts\activate pip install -r requirements.txt uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
-
另開一個終端啟動前端(監聽 5173 埠):
cd frontend npm install npm run dev -
瀏覽器開啟
http://localhost:5173/,按「載入範例資料」即可看到效果,也可以直接拖入自己的.pdm檔案。
推薦使用倉庫根目錄附帶的 docker-compose 編排(前後端兩個容器)。前端容器以 nginx 代管靜態檔案,並把 /api、/docs、/openapi.json 反向代理到後端容器,對外只開一個連接埠。
# 在專案根目錄執行(一次完成前後端建置 + 啟動)
docker compose up -d --build啟動完成後開啟 http://localhost:8080/ 即可使用。查看日誌、停止、重啟:
docker compose logs -f # 查看即時日誌
docker compose down # 停止並移除容器
docker compose restart # 重啟服務若不想使用 compose,也可手動分開部署:前端建置產物交給 Nginx,後端以 uvicorn 跑在 8000 埠,Nginx 把 /api/ 轉送到 8000,其餘路徑指向 frontend/dist。
# 不使用 compose 時的手動建置參考
cd frontend && npm run build # 產出在 frontend/dist
cd ../backend && uvicorn app.main:app --host 0.0.0.0 --port 8000- backend:基於
python:3.10-slim,內部監聽 8000,僅在 compose 內部網路暴露,預設不對應到宿主机;若需直接存取 Swagger 文檔,可在docker-compose.yml中把ports: "8000:8000"的註解打開。 - frontend:兩階段建置,階段 1 用
node:20-alpine執行npm ci && npm run build,階段 2 用nginx:1.27-alpine代管 dist 並設定反向代理,宿主机 8080 對應到容器 80。 - 建置預設啟用國內 npm/pip 映像加速(寫在 Dockerfile 中,如不需要可刪除對應列)。
- nginx 已把上傳大小調到 52MB,並預留 120 秒讀寫超時,與後端 50MB PDM 檔案上限匹配。
所有介面前綴 /api/v1,回傳 JSON(下載介面回傳對應 Content-Type + Attachment)。
| 方法 | 路徑 | 說明 |
|---|---|---|
| POST | /pdm/upload |
上傳 .pdm 檔案,回傳 model_id 與 tables/columns/references 摘要 |
| POST | /pdm/load-sample |
直接載入內建範例模型,回傳結構同 upload |
| GET | /models |
目前記憶體中已解析的所有模型列表(依建立時間倒序,僅摘要) |
| GET | /models/{model_id} |
模型概覽 |
| GET | /models/{model_id}/tables |
資料表清單(左側樹 + 清單檢視用) |
| GET | /tables/{table_id} |
單一資料表詳情(欄位、索引、主鍵、外鍵、被參考關聯) |
| GET | /models/{model_id}/graph |
ER 圖資料(nodes + edges,支援階層/環狀/方格佈局) |
| GET | /models/{model_id}/search?q= |
搜尋表/欄位,命中回傳 表/欄位 標籤區分來源 |
| GET | /models/{model_id}/ddl?dialect=mysql |
整庫 DDL(方言:mysql/postgres/oracle/sqlserver/sqlite) |
| GET | /tables/{table_id}/ddl?dialect=mysql |
單表 DDL |
| GET | /models/{model_id}/export?format=xlsx |
整庫匯出,格式:xlsx / csv / md / json |
| GET | /tables/{table_id}/export?format=xlsx |
單表匯出 |
| GET | /pdm/sample |
範例 PDM 檔案原文 |
- 檔案大小上限 50MB
- 資料僅存在記憶體,服務重啟即消失
- 支援的 PDM 結構:標準
a=(attribute)/c=(collection)/o=(object)命名空間的 PowerDesigner PDM XML;表可直接掛在根o:Model,也可分散在任意深度的o:Package下 - 暫不支援:PDM 內的實體檢視、預存程序、觸發程序、跨檔案引用(Proxy/Shortcut)、擴充自訂指令碼;這些物件會被忽略,僅保證表結構、欄位、主鍵、索引、外鍵關聯正確
A small tool for viewing PowerDesigner .pdm files in the browser without installing anything. The backend parses the XML with lxml and pulls out tables, columns, primary/foreign keys, and indexes; the frontend renders an ER diagram with React Flow, and clicking any table shows its column definitions and relationships inline.
Nothing is uploaded to a remote server. Parsed models live in the backend process memory and disappear on restart. Useful for quickly inspecting a PDM locally or walking a team through a data model.
- Drag-and-drop upload of
.pdmfiles exported by PowerDesigner 12 / 15 / 16 / 17 - Robust parsing: handles both "tables under the root
o:Model" and "tables nested inside arbitrarily deepPackagehierarchies" layouts typically seen in large models — all tables are recursively scanned, de-duplicated, and correctly rendered - Model tree on the left with search & filter — match on table/code, column/code, or comments; results are tagged as "Table" and/or "Column" to indicate where the hit occurred
- Center area toggles between an ER diagram view and a table-list view
- ER diagram (React Flow) supports multiple layouts: hierarchical left-to-right / top-to-bottom, circular, grid; plus fit-to-view, reapply-layout, and hover highlighting of connected tables
- Right-hand inspector shows columns (code / name / type / not-null ✔️), indexes, primary keys, and both outgoing (FK) and incoming (references FK) relationships
- DDL generation for five dialects: MySQL / PostgreSQL / Oracle / SQL Server / SQLite, with one-click copy and
.sqldownload - Full-format exports — whole-model or single-table export to Excel (.xlsx), CSV, Markdown, and JSON
- Both side panels are collapsible and drag-resizable; collapse buttons are top-most (z-index) so they don't accidentally trigger the resize handle
- Ships with a sample e-commerce model (click "Load sample data" to try it without a file)
- Models with at least 500 tables or 1,000 references open in a virtual table list. Graph data loads on entering the ER view. Large graphs default to a grid, disable the minimap and animated edges, and render elements near the viewport.
- Hierarchical and circular layouts run in a Web Worker. Changing views/layouts cancels obsolete jobs; completed layouts are cached for the current page session. Pan to browse, use fit-to-view for an overview, or select a table and choose the one-hop relationship view.
- Table details and per-table DDL are cached on demand. Tables with more than 100 columns show 50 columns per page. Obsolete detail, search, and DDL requests are canceled.
- Run
npm testandnpm run buildfromfrontend/. With the dev server running,/tests/performance.htmlprovides 1,000 synthetic tables for scrolling, layout, and responsiveness checks. This test page is excluded from the production build.
| Layer | Technology |
|---|---|
| Frontend | React 18, TypeScript 5, Vite 5, Ant Design 5, @xyflow/react (React Flow), dagre (hierarchical layouts) |
| Backend | Python 3.10+, FastAPI 0.115, uvicorn, lxml, Pydantic v2, openpyxl (Excel export) |
| Communication | REST + JSON; Vite proxies /api to the backend in development |
pdm-viewer/
├── backend/
│ ├── app/
│ │ ├── main.py # FastAPI entry (logging, router registration)
│ │ ├── pdm_parser.py # PDM XML parser: a/c/o ns + recursive Packages + placeholder filtering
│ │ ├── ddl.py # DDL generator: 5-dialect type mapping
│ │ ├── exporters.py # Excel / CSV / Markdown / JSON exporters
│ │ ├── schemas.py # Pydantic models (tables/columns/search/ddl params etc)
│ │ ├── storage.py # In-memory store + list models + search
│ │ └── routers/
│ │ ├── pdm.py # Upload / model queries / search / load sample
│ │ └── output.py # DDL and export download endpoints
│ ├── sample.pdm # Sample file: 5-table e-commerce model
│ └── requirements.txt
└── frontend/
├── src/
│ ├── App.tsx # Main layout: collapsible + drag-resize side panels
│ ├── api/ # HTTP wrappers
│ ├── components/ # Header / UploadZone / ModelTree / ERDiagram / Inspector
│ ├── types/ # TypeScript types
│ └── styles/global.css
├── index.html
├── nginx.conf # Production: static hosting + /api proxy + body size / timeouts
├── package.json
├── vite.config.ts
├── Dockerfile
└── .dockerignore
Requires Node.js 18+ and Python 3.10+ on your machine.
-
Start the backend (port 8000):
cd backend python -m venv venv source venv/bin/activate # on Windows: venv\Scripts\activate pip install -r requirements.txt uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
-
In another terminal, start the frontend (port 5173):
cd frontend npm install npm run dev -
Open
http://localhost:5173/in your browser. Click "Load sample data" to see it in action, or drop in your own.pdmfile.
The repo ships with a docker-compose setup (separate frontend and backend containers). The frontend container serves the built site via nginx and proxies /api, /docs and /openapi.json to the backend — a single host port is all you need.
# From the project root: builds both images and starts them in the background
docker compose up -d --buildOnce up, open http://localhost:8080/ in your browser. Useful commands:
docker compose logs -f # tail logs
docker compose down # stop and remove containers
docker compose restart # restart servicesIf you prefer not to use compose, you can deploy manually: build the frontend and point Nginx at frontend/dist, run the backend with uvicorn on port 8000, and forward /api/ to it.
# Manual build reference (no compose)
cd frontend && npm run build # output in frontend/dist
cd ../backend && uvicorn app.main:app --host 0.0.0.0 --port 8000- backend: based on
python:3.10-slim, listens on internal port 8000 and is only reachable inside the compose network by default. Uncommentports: "8000:8000"indocker-compose.ymlif you want to reach the Swagger UI directly from the host. - frontend: multi-stage build — Stage 1 uses
node:20-alpineto runnpm ci && npm run build, Stage 2 usesnginx:1.27-alpineto servedistand handle reverse proxying. Host port 8080 maps to container port 80. - Chinese mirrors for npm and pip are configured in the Dockerfiles by default; remove the relevant lines if you're in a different network region.
- nginx sets a 52MB client body size and 120s read/write timeouts, matching the 50MB PDM upload limit on the backend.
All routes are prefixed with /api/v1 and return JSON (download endpoints return the corresponding Content-Type + Content-Disposition attachment).
| Method | Path | Description |
|---|---|---|
| POST | /pdm/upload |
Upload a .pdm file; returns model_id plus tables/columns/references summary |
| POST | /pdm/load-sample |
Load the built-in sample model; same response shape as upload |
| GET | /models |
List all currently-parsed in-memory models (newest first, summary only) |
| GET | /models/{model_id} |
Model overview |
| GET | /models/{model_id}/tables |
Lightweight table list (for tree + table-list view) |
| GET | /tables/{table_id} |
Single table detail (columns, indexes, PKs, FKs, incoming references) |
| GET | /models/{model_id}/graph |
ER graph (nodes + edges) consumable by React Flow |
| GET | /models/{model_id}/search?q= |
Search tables and columns; results tag hit source as Table / Column |
| GET | /models/{model_id}/ddl?dialect=mysql |
Whole-model DDL. Dialects: mysql/postgres/oracle/sqlserver/sqlite |
| GET | /tables/{table_id}/ddl?dialect=mysql |
Single-table DDL |
| GET | /models/{model_id}/export?format=xlsx |
Whole-model export. Formats: xlsx / csv / md / json |
| GET | /tables/{table_id}/export?format=xlsx |
Single-table export |
| GET | /pdm/sample |
Raw sample PDM file |
- File size capped at 50MB
- Models live in memory only and are lost on service restart
- Supported PDM layout: standard PowerDesigner XML using the
a=(attribute) /c=(collection) /o=(object) namespace pattern. Tables may live directly under the rooto:Modelor be distributed across arbitrarily nestedo:Packagecollections - Not currently parsed: physical views, stored procedures, triggers, cross-file references (Proxy / Shortcut), and custom extension scripts; these are ignored, and only table structure, columns, PKs, indexes, and FK relationships are guaranteed to be correct