关于 frappe-impl-workspace
面向 Frappe 应用开发者和管理员的 Workspace 页面创建与定制工作流参考,涵盖区块布局、访问规则、版本差异及随应用打包依赖项。
主要功能
- 01通过界面或代码创建工作区
- 02在网格中排列仪表板区块
- 03配置模块与角色访问权限
- 04管理图表、快捷方式和指标卡
- 05导出工作区并打包依赖项
适用场景
- 01构建带指标的模块仪表板
- 02创建受角色限制的工作区视图
- 03随 Frappe 应用发布工作区页面
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ impertio-studio/ frappe_claude_skill_package --skill frappe-impl-workspace安装后在 Claude Code 中输入/frappe-impl-workspace确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/anti-patterns.mdshipping-with-app.mdworkspace-components.md详细介绍
Frappe 工作区实施工作流
创建和自定义工作区页面的分步工作流。工作区是 Frappe Desk 中基于区块的仪表板/导航页面。
版本:v14/v15/v16(已注明特定版本的功能)
快速参考
| 概念 | 说明 |
|---|---|
| 工作区 | 采用 12 列网格布局的区块式页面 |
| 公共工作区 | 对所有获准用户可见;编辑需要 Workspace Manager 角色 |
| 私有工作区 | 位于“My Workspaces”下的个人仪表板;任何 Desk User 都可以创建 |
| 内容字段 | 存储区块布局的 JSON 数组 |
| 子表 | 6 个表:charts、shortcuts、links、quick_lists、number_cards、custom_blocks |
| 模块关联 | 主要访问控制机制 |
关键决策:你需要什么?
NEED A WORKSPACE?
│
├─► Default DocType landing page?
│ └─► NO workspace needed — Frappe auto-generates list views
│
├─► Custom dashboard for a module?
│ └─► Create PUBLIC Workspace (Workspace Manager role required)
│
├─► Personal dashboard for a user?
│ └─► Create PRIVATE Workspace (appears under "My Workspaces")
│
└─► Navigation link in sidebar?
└─► type="Link" (internal) or type="URL" (external)
ADDING COMPONENTS?
│
├─► Key metrics (counts, sums) → Number Cards
├─► Trend / time-series data → Dashboard Charts
├─► Quick navigation links → Shortcuts
├─► Grouped link categories → Link Cards (Card Break + Links)
├─► Custom HTML/JS content → Custom HTML Blocks
└─► Recent record lists → Quick Lists
Workspace DocType 结构
关键字段
| 字段 | 类型 | 用途 |
|---|---|---|
label | Data | 侧边栏中的显示名称 |
title | Data | 页面标题(默认为 label) |
module | Link → Module Def | 将工作区关联到模块以进行访问控制 |
parent_page | Link → Workspace | 在侧边栏中嵌套到其他工作区下 |
icon | Data | 侧边栏图标(例如,"chart-line") |
type | Select | Workspace / Link / URL(v15+) |
sequence_id | Int | 侧边栏排序 |
content | JSON | 以 JSON 数组形式存储的区块布局 |
for_user | Data | 如果已设置,工作区仅对该用户私有 |
roles | Table → Has Role | 基于角色的访问限制 |
app | Data | 所属应用标识符(v15+) |
indicator_color | Color | 侧边栏指示点(v15+) |
子表(共 6 个)
| 子表 | DocType | 用途 |
|---|---|---|
charts | Workspace Chart | Dashboard Chart 引用 |
shortcuts | Workspace Shortcut | DocType/Report/Page/URL 快捷方式 |
links | Workspace Link | 分组导航链接 |
quick_lists | Workspace Quick List | 最近记录列表 |
number_cards | Workspace Number Card | 指标卡片引用 |
custom_blocks | Workspace Custom Block | HTML 区块引用 |
重要:
contentJSON 和子表必须保持同步。始终使用 Workspace Builder UI 或程序化 API——切勿在未更新子表的情况下手动编辑contentJSON。请参阅references/anti-patterns.md。
内容 JSON 格式
content 字段是一个 JSON 数组。每个元素代表 12 列网格中的一个区块:
[
{
"id": "unique-block-id",
"type": "header",
"data": {"text": "Overview", "level": 4, "col": 12}
},
{
"id": "unique-block-id-2",
"type": "chart",
"data": {
"chart_name": "Sales Trends",
"col": 12
}
},
{
"id": "unique-block-id-3",
"type": "number_card",
"data": {
"number_card_name": "Open Orders",
"col": 4
}
},
{
"id": "unique-block-id-4",
"type": "shortcut",
"data": {
"shortcut_name": "New Sales Order",
"col": 4
}
},
{
"id": "unique-block-id-5",
"type": "spacer",
"data": {"col": 12}
}
]
区块类型
| 类型 | data 字段 | 说明 |
|---|---|---|
header | text、level、col | 分区标题(h3/h4/h5) |
chart | chart_name、col | 引用一个 Dashboard Chart 文档 |
number_card | number_card_name、col | 引用一个 Number Card 文档 |
shortcut | shortcut_name、col | 引用一个 Workspace Shortcut 子项 |
card | card_name、col | 分组链接的卡片分隔 |
quick_list | quick_list_name、col | 某个 DocType 的最近记录 |
custom_block | custom_block_name、col | 引用一个 Custom HTML Block 文档 |
text | body、col | 富文本/Markdown 区块 |
spacer | col | 垂直留白 |
onboarding | onboarding_name、col | 模块引导小组件 |
col的值必须在 1-12 之间,表示网格列宽。同一行中的区块列宽总和必须 ≤ 12。
实施工作流
工作流 1:通过 UI 创建公共工作区
- 前往
/app/workspace→ 点击 + New Workspace - 设置 Label(显示在侧边栏中)、Module、Icon
- 使用 Workspace Builder 拖放区块
- 添加组件:图表、数字卡片、快捷方式、链接
- 点击 Save → 工作区将显示在获准用户的侧边栏中
- 在开发者模式下:JSON 会自动导出到你的应用目录
工作流 2:以编程方式创建工作区
import frappe
import json
workspace = frappe.new_doc("Workspace")
workspace.label = "Project Dashboard"
workspace.module = "Projects"
workspace.icon = "project"
workspace.type = "Workspace"
workspace.sequence_id = 10
# Build content blocks
workspace.content = json.dumps([
{
"id": frappe.generate_hash(length=10),
"type": "header",
"data": {"text": "Project Overview", "level": 4, "col": 12}
},
{
"id": frappe.generate_hash(length=10),
"type": "number_card",
"data": {"number_card_name": "Active Projects", "col": 4}
},
{
"id": frappe.generate_hash(length=10),
"type": "chart",
"data": {"chart_name": "Project Status", "col": 12}
}
])
# Add child table entries (MUST match content JSON)
workspace.append("number_cards", {
"number_card_name": "Active Projects"
})
workspace.append("charts", {
"chart_name": "Project Status"
})
# Role restrictions (optional)
workspace.append("roles", {"role": "Projects Manager"})
workspace.insert(ignore_permissions=True)
frappe.db.commit()
务必在以编程方式设置
contentJSON 时,添加相应的子表行。
工作流 3:先创建支持文档
向工作区添加组件之前,请先创建所引用的文档:
数字卡片:
card = frappe.new_doc("Number Card")
card.label = "Active Projects"
card.document_type = "Project"
card.function = "Count"
card.filters_json = json.dumps([["Project", "status", "=", "Open"]])
card.is_public = 1
card.insert(ignore_permissions=True)
仪表板图表:
chart = frappe.new_doc("Dashboard Chart")
chart.chart_name = "Project Status"
chart.chart_type = "Group By"
chart.document_type = "Project"
chart.group_by_type = "Count"
chart.group_by_based_on = "status"
chart.type = "Donut"
chart.is_public = 1
chart.insert(ignore_permissions=True)
快捷方式: 快捷方式是 Workspace 上的子表条目,而不是独立文档:
workspace.append("shortcuts", {
"label": "New Project",
"type": "DocType",
"link_to": "Project",
"color": "Blue",
"format": "{} Active",
"stats_filter": json.dumps([["Project", "status", "=", "Open"]])
})
完整的组件参考请参阅 references/workspace-components.md。
权限模型
三层访问控制
Layer 1: Module Access (PRIMARY)
└─► User must have access to the workspace's module
└─► Controlled via "Module Def" and user's "Block Modules" list
Layer 2: Role Restrictions (OPTIONAL)
└─► workspace.roles child table
└─► If populated: ONLY users with listed roles see the workspace
└─► If empty: ALL users with module access see it
Layer 3: Workspace Manager Role
└─► Required to create/edit PUBLIC workspaces
└─► NOT required for private workspaces
规则
- 对公开工作区务必设置
module—— 否则该工作区对所有 Desk 用户可见 - 对敏感仪表板(财务、人力资源)务必添加角色限制
- 切勿对随应用发布的工作区设置
for_user—— 这会创建私有工作区
版本差异
| 功能 | v14 | v15 | v16 |
|---|---|---|---|
| Workspace Builder UI | 基础 | 重新设计(拖放网格) | 增量修复 |
type 字段(Workspace/Link/URL) | 不可用 | 已添加 | 可用 |
app 字段 | 不可用 | 已添加 | 可用 |
indicator_color | 不可用 | 已添加 | 可用 |
| 名称冲突保护 | 手动 | 手动 | 自动去重 |
| 欢迎页眉配置 | 不可用 | 不可用 | 已添加 |
| Content JSON 格式 | 相同 | 相同 | 相同 |
迁移说明
- v14 → v15:Workspace Builder UI 有重大变化;现有 JSON 内容仍兼容
- v15 → v16:新增少量字段;工作区结构没有不兼容的变更
- 大版本升级后务必测试工作区渲染效果
使用自定义应用发布工作区
目录结构
myapp/
└── mymodule/
└── workspace/
└── my_workspace/
└── my_workspace.json
导出流程
- 启用 Developer Mode(
frappe.conf.developer_mode = 1) - 通过 Workspace Builder UI 创建或编辑工作区
- 保存时,Frappe 会自动导出到上述应用目录
- 将 JSON 文件提交到版本控制系统
重要:同时发布依赖项
仅有工作区 JSON 是不够的。还必须同时发布:
| 组件 | 发布方式 |
|---|---|
| 数字卡片 | 使用 hooks.py 中的 fixtures 或 myapp/fixtures/ |
| 仪表板图表 | 使用 hooks.py 中的 fixtures 或 myapp/fixtures/ |
| 自定义 HTML 块 | 使用 hooks.py 中的 fixtures 或 myapp/fixtures/ |
| 链接的报表 | 已通过报表目录结构发布 |
| 链接的页面 | 已通过页面目录结构发布 |
# hooks.py
fixtures = [
{"dt": "Number Card", "filters": [["module", "=", "My Module"]]},
{"dt": "Dashboard Chart", "filters": [["module", "=", "My Module"]]},
{"dt": "Custom HTML Block", "filters": [["name", "in", ["My Block"]]]},
]
完整的发布指南请参阅 references/shipping-with-app.md。
常见模式
模式 1:包含 KPI 的模块仪表板
[Header: "Key Metrics"]
[Number Card: Open Orders (col=3)] [Number Card: Revenue (col=3)]
[Number Card: Pending (col=3)] [Number Card: Overdue (col=3)]
[Spacer]
[Header: "Trends"]
[Chart: Monthly Revenue (col=12)]
[Header: "Quick Access"]
[Shortcut: New Order (col=4)] [Shortcut: Reports (col=4)] [Shortcut: Settings (col=4)]
模式 2:基于角色的工作区
# Sales Manager sees full dashboard; Sales User sees limited view
# Option A: Two separate workspaces with different role restrictions
# Option B: One workspace — use Number Card/Chart permissions to filter
# Option A implementation:
ws_manager = frappe.get_doc({"doctype": "Workspace", "label": "Sales Management", ...})
ws_manager.append("roles", {"role": "Sales Manager"})
ws_user = frappe.get_doc({"doctype": "Workspace", "label": "Sales Overview", ...})
ws_user.append("roles", {"role": "Sales User"})
模式 3:侧边栏层级结构
# Parent workspace
parent = frappe.get_doc({"doctype": "Workspace", "label": "CRM", "module": "CRM"})
# Child workspaces (nested in sidebar)
child = frappe.get_doc({
"doctype": "Workspace",
"label": "Lead Pipeline",
"module": "CRM",
"parent_page": "CRM" # References parent workspace label
})
参考文件
| 文件 | 内容 |
|---|---|
references/workspace-components.md | 数字卡片、仪表板图表、快捷方式、自定义块——完整 API |
references/shipping-with-app.md | JSON 格式、fixtures、模块结构、安装钩子 |
references/anti-patterns.md | 常见工作区错误及其规避方法 |
评论
支持 Markdown