From f4afc969bd01a85f2ff8a5069d83d262a84cba4d Mon Sep 17 00:00:00 2001 From: iven Date: Mon, 20 Apr 2026 00:43:34 +0800 Subject: [PATCH] =?UTF-8?q?docs(spec):=20=E8=87=AA=E7=94=B1=E8=81=8C?= =?UTF-8?q?=E4=B8=9A=E8=80=85/IT=E8=BF=90=E7=BB=B4=E6=8F=92=E4=BB=B6?= =?UTF-8?q?=E5=A2=9E=E5=BC=BA=E8=AE=BE=E8=AE=A1=E8=A7=84=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 三层增强方案:智能业务引擎 + 仪表盘重构 + 专业输出 纯插件层实现,无需修改平台代码 --- ...eelance-itops-plugin-enhancement-design.md | 609 ++++++++++++++++++ 1 file changed, 609 insertions(+) create mode 100644 docs/superpowers/specs/2026-04-20-freelance-itops-plugin-enhancement-design.md diff --git a/docs/superpowers/specs/2026-04-20-freelance-itops-plugin-enhancement-design.md b/docs/superpowers/specs/2026-04-20-freelance-itops-plugin-enhancement-design.md new file mode 100644 index 0000000..4341fe8 --- /dev/null +++ b/docs/superpowers/specs/2026-04-20-freelance-itops-plugin-enhancement-design.md @@ -0,0 +1,609 @@ +# freelance + itops 插件增强设计规格 + +> 日期: 2026-04-20 +> 来源: 多专家头脑风暴(UX专家 + 业务顾问 + 运维专家 + 财务专家) +> 状态: Draft +> 前置: `docs/superpowers/specs/2026-04-19-shantou-zhijie-it-services-plugins-design.md` + +--- + +## 1. 背景与动机 + +当前插件是「数据录入系统」,不是「赚钱工具」。一人 IT 服务公司的核心痛点: + +1. **钱从哪里来?** — 商机跟进靠人记,没有自动提醒、没有漏斗分析 +2. **项目做到哪了?** — 任务状态和工时手动填,跟合同金额/应收款脱节 +3. **钱收回来了吗?** — 报价→合同→开票→收款割裂,没有串联 +4. **运维服务会不会忘?** — 巡检计划写了没人催,SLA 超时了才知道 +5. **税和利润算不清?** — 收支分散在不同表里,月底做账要手动汇总 + +**问题根因:** 平台已有 trigger_events、settings、templates、cascade_from、visible_when、validation 六大能力,但两个插件完全没有使用。 + +**改进目标:** 纯插件层增强,三层递进: +- Layer 1: 智能业务引擎 — 让系统主动驱动用户做事 +- Layer 2: 仪表盘重构 — 一个页面掌控全局 +- Layer 3: 专业输出 — 一键生成报价单/发票/合同 PDF + +--- + +## 2. Layer 1: 智能业务引擎 — freelance 插件 + +### 2.1 Settings(插件配置页) + +一次性配置公司信息和业务偏好,后续自动生效: + +```toml +[settings] + + # ── 基本信息 ── + [[settings.fields]] + name = "company_name" + display_name = "公司名称" + field_type = "text" + required = true + group = "基本信息" + + [[settings.fields]] + name = "currency_symbol" + display_name = "货币符号" + field_type = "text" + default_value = "¥" + group = "基本信息" + + # ── 财务 ── + [[settings.fields]] + name = "default_tax_rate" + display_name = "默认税率(%)" + field_type = "number" + default_value = 6 + range = [0.0, 100.0] + group = "财务" + + # ── 提醒 ── + [[settings.fields]] + name = "payment_reminder_days" + display_name = "收款提前提醒(天)" + field_type = "number" + default_value = 3 + range = [1.0, 30.0] + group = "提醒" + + [[settings.fields]] + name = "notify_contract_expiring" + display_name = "合同到期提醒" + field_type = "boolean" + default_value = true + group = "提醒" + + [[settings.fields]] + name = "notify_payment_overdue" + display_name = "逾期收款提醒" + field_type = "boolean" + default_value = true + group = "提醒" + + [[settings.fields]] + name = "notify_opportunity_followup" + display_name = "商机跟进提醒" + field_type = "boolean" + default_value = true + group = "提醒" +``` + +### 2.2 Trigger Events(自动事件驱动) + +关键操作时自动发通知,把"人找事"变"事找人": + +```toml +[[trigger_events]] +name = "opportunity_stage_changed" +display_name = "商机阶段变更" +description = "商机阶段发生变化时通知,特别是成交或失败" +entity = "opportunity" +on = "update" + +[[trigger_events]] +name = "contract_status_changed" +display_name = "合同状态变更" +description = "合同状态变化时检查到期预警" +entity = "contract" +on = "update" + +[[trigger_events]] +name = "invoice_status_changed" +display_name = "发票状态变更" +description = "发票状态变化时检查逾期收款" +entity = "invoice" +on = "update" + +[[trigger_events]] +name = "task_status_changed" +display_name = "任务状态变更" +description = "任务完成或取消时通知" +entity = "task" +on = "update" + +[[trigger_events]] +name = "expense_created" +display_name = "新支出记录" +description = "记录新支出时通知" +entity = "expense" +on = "create" +``` + +### 2.3 Cascade(智能联动下拉) + +选客户后自动过滤其关联数据: + +**contract 实体新增:** +```toml + # client_id 选择后,opportunity_id 自动过滤只显示该客户的商机 + [[schema.entities.fields]] + name = "opportunity_id" + field_type = "uuid" + display_name = "关联商机" + ref_entity = "opportunity" + cascade_from = "client_id" + cascade_filter = "client_id" + + # client_id 选择后,quote_id 自动过滤只显示该客户的报价 + [[schema.entities.fields]] + name = "quote_id" + field_type = "uuid" + display_name = "关联报价" + ref_entity = "quote" + cascade_from = "client_id" + cascade_filter = "client_id" +``` + +**invoice 实体新增:** +```toml + # client_id 选择后,project_id 自动过滤 + [[schema.entities.fields]] + name = "project_id" + field_type = "uuid" + display_name = "关联项目" + ref_entity = "project" + cascade_from = "client_id" + cascade_filter = "client_id" + + # client_id 选择后,contract_id 自动过滤 + [[schema.entities.fields]] + name = "contract_id" + field_type = "uuid" + display_name = "关联合同" + ref_entity = "contract" + cascade_from = "client_id" + cascade_filter = "client_id" +``` + +**time_entry 实体新增:** +```toml + # project_id 选择后,task_id 自动过滤只显示该项目的任务 + [[schema.entities.fields]] + name = "task_id" + field_type = "uuid" + display_name = "关联任务" + ui_widget = "entity_select" + ref_entity = "task" + ref_label_field = "title" + ref_search_fields = ["title"] + cascade_from = "project_id" + cascade_filter = "project_id" +``` + +### 2.4 Visible When(条件显示) + +只在有意义时才显示字段: + +| 实体 | 字段 | 条件 | +|------|------|------| +| invoice | payment_date | `status == 'paid' \|\| status == 'partial'` | +| contract | paid_amount | `status != 'drafting'` | +| task | actual_hours | `status != 'todo'` | +| quote | total_amount | `status != 'draft'` | + +### 2.5 Validation(字段校验) + +```toml + # client 实体 - email 字段增加校验 + [[schema.entities.fields]] + name = "email" + field_type = "string" + display_name = "邮箱" + validation = { pattern = "^[^@]+@[^@]+\\.[^@]+$", message = "请输入有效的邮箱地址" } + + # client 实体 - phone 字段增加校验 + [[schema.entities.fields]] + name = "phone" + field_type = "string" + display_name = "电话" + validation = { pattern = "^1[3-9]\\d{9}$", message = "请输入有效的手机号" } +``` + +--- + +## 3. Layer 2: 仪表盘重构 — freelance 插件 + +将占位符仪表盘升级为真正的指挥中心。通过 `widgets` 声明告诉平台该展示什么: + +```toml +[[ui.pages]] +type = "dashboard" +label = "工作台" +icon = "DashboardOutlined" + + # ── 财务概览卡片 ── + [[ui.pages.widgets]] + type = "stat_cards" + label = "财务概览" + cards = [ + { entity = "invoice", aggregate = "sum", field = "amount", filter = "type == 'payment' && status != 'overdue'", label = "本月收入", icon = "rise", color = "green" }, + { entity = "expense", aggregate = "sum", field = "amount", label = "本月支出", icon = "fall", color = "red" }, + { entity = "invoice", aggregate = "sum", field = "amount", filter = "status == 'overdue' || status == 'pending'", label = "应收总额", icon = "dollar", color = "orange" }, + { entity = "invoice", aggregate = "count", filter = "status == 'overdue'", label = "逾期笔数", icon = "warning", color = "red" } + ] + + # ── 紧急待办 ── + [[ui.pages.widgets]] + type = "action_list" + label = "紧急待办" + max_items = 5 + queries = [ + { entity = "invoice", filter = "status == 'overdue'", label_field = "invoice_number", subtitle_field = "amount", action = "查看", icon = "warning" }, + { entity = "task", filter = "status != 'done' && status != 'cancelled'", sort = "due_date asc", label_field = "title", subtitle_field = "due_date", action = "处理", icon = "clock" }, + { entity = "contract", filter = "status == 'active'", sort = "end_date asc", label_field = "title", subtitle_field = "end_date", action = "续约", icon = "file-text" }, + { entity = "opportunity", filter = "next_follow_up <= today", label_field = "title", subtitle_field = "next_follow_up", action = "跟进", icon = "phone" } + ] + + # ── 商机漏斗 ── + [[ui.pages.widgets]] + type = "funnel" + label = "商机漏斗" + entity = "opportunity" + lane_field = "stage" + value_field = "estimated_amount" + lane_order = ["visit", "requirement", "quote", "negotiation", "won", "lost"] + + # ── 活跃项目卡片 ── + [[ui.pages.widgets]] + type = "card_list" + label = "活跃项目" + entity = "project" + filter = "status == 'in_progress'" + max_items = 4 + title_field = "name" + subtitle_field = "contract_amount" + tags = ["business_type", "status"] +``` + +**依赖:** 仪表盘 widgets 渲染需要前端配合解析 `widgets` 声明。数据源来自平台已有的聚合 API(`/count`、`/aggregate`)。 + +--- + +## 4. Layer 3: 专业输出 — freelance 插件 + +一键生成专业 PDF,替代手动排 Word: + +### 4.1 报价单模板 + +```toml +[[templates]] +name = "quote_pdf" +display_name = "报价单" +entity = "quote" +format = "pdf" +template_html = """ + + + +

报价单 {{quote_number}}

+

客户:{{client.name}} | 有效期至:{{valid_until}}

+ + + {{#each lines}} + + {{/each}} +
项目描述数量单价金额
{{item_name}}{{description}}{{quantity}}{{unit_price}}{{amount}}
+

小计:{{subtotal}} | 税率:{{tax_rate}}% | 总计:{{total_amount}}

+ + + +""" +``` + +### 4.2 发票模板 + +```toml +[[templates]] +name = "invoice_pdf" +display_name = "发票" +entity = "invoice" +format = "pdf" +template_html = """ + + + +

发票 {{invoice_number}}

+
+
客户:{{client.name}}
+
类型:{{type}}
+
开票日期:{{issue_date}}
+
到期日:{{due_date}}
+
+
¥{{amount}}
+

状态:{{status}}

+

备注:{{notes}}

+ + +""" +``` + +### 4.3 合同模板 + +```toml +[[templates]] +name = "contract_pdf" +display_name = "合同" +entity = "contract" +format = "pdf" +template_html = """ + + + +

{{title}}

+

合同编号:{{contract_number}}

+
+

甲方:{{client.name}}

+

合同金额:¥{{amount}} | 已付:¥{{paid_amount}}

+

期限:{{start_date}} 至 {{end_date}}

+

付款条款:{{payment_terms}}

+
+

备注:{{notes}}

+
+
甲方签章
+
乙方签章
+
+ + +""" +``` + +--- + +## 5. itops 插件增强 + +### 5.1 Settings + +```toml +[settings] + + [[settings.fields]] + name = "default_sla_response" + display_name = "默认SLA响应时间(小时)" + field_type = "number" + default_value = 8 + range = [1.0, 72.0] + group = "SLA" + + [[settings.fields]] + name = "default_sla_resolve" + display_name = "默认SLA解决时间(小时)" + field_type = "number" + default_value = 48 + range = [1.0, 168.0] + group = "SLA" + + [[settings.fields]] + name = "notify_sla_breach" + display_name = "SLA超标提醒" + field_type = "boolean" + default_value = true + group = "提醒" + + [[settings.fields]] + name = "notify_check_due" + display_name = "巡检到期提醒" + field_type = "boolean" + default_value = true + group = "提醒" +``` + +### 5.2 Trigger Events + +```toml +[[trigger_events]] +name = "ticket_created" +display_name = "新工单" +description = "创建工单时开始SLA计时并通知" +entity = "ticket" +on = "create" + +[[trigger_events]] +name = "ticket_status_changed" +display_name = "工单状态变更" +description = "工单状态变化时检查SLA是否达标" +entity = "ticket" +on = "update" + +[[trigger_events]] +name = "contract_status_changed" +display_name = "维保合同状态变更" +description = "合同状态变化时检查到期预警" +entity = "service_contract" +on = "update" + +[[trigger_events]] +name = "check_plan_updated" +display_name = "巡检计划更新" +description = "巡检计划更新时检查下次巡检日期" +entity = "check_plan" +on = "update" +``` + +### 5.3 Cascade + +```toml +# ticket 实体:选客户后过滤其维保合同 + [[schema.entities.fields]] + name = "contract_id" + field_type = "uuid" + display_name = "维保合同" + ui_widget = "entity_select" + ref_entity = "service_contract" + ref_label_field = "name" + ref_search_fields = ["name"] + cascade_from = "client_id" + cascade_filter = "client_id" + +# check_record 实体:选巡检计划后过滤合同 + [[schema.entities.fields]] + name = "contract_id" + field_type = "uuid" + display_name = "维保合同" + ref_entity = "service_contract" + cascade_from = "plan_id" + cascade_filter = "contract_id" +``` + +### 5.4 Visible When + +| 实体 | 字段 | 条件 | +|------|------|------| +| ticket | resolution | `status == 'resolved' \|\| status == 'closed'` | +| ticket | responded_at | `status != 'open'` | +| ticket | resolved_at | `status == 'resolved' \|\| status == 'closed'` | +| ticket | closed_at | `status == 'closed'` | +| check_record | issues_found | `result == 'abnormal'` | +| check_record | actions_taken | `result == 'abnormal'` | + +### 5.5 Validation + +```toml + # service_contract - contract_number 格式校验 + validation = { pattern = "^SC-\\d{4}-\\d{4}$", message = "格式:SC-YYYY-NNNN" } +``` + +### 5.6 Dashboard + +```toml +[[ui.pages]] +type = "dashboard" +label = "运维概览" +icon = "DashboardOutlined" + + [[ui.pages.widgets]] + type = "stat_cards" + label = "运维概览" + cards = [ + { entity = "service_contract", aggregate = "count", filter = "status == 'active'", label = "活跃合同", icon = "file-text", color = "blue" }, + { entity = "ticket", aggregate = "count", filter = "status == 'open' || status == 'in_progress'", label = "待处理工单", icon = "tool", color = "orange" }, + { entity = "ticket", aggregate = "count", filter = "status == 'resolved'", label = "已解决工单", icon = "check-circle", color = "green" }, + { entity = "check_plan", aggregate = "count", filter = "status == 'active'", label = "活跃巡检", icon = "schedule", color = "blue" } + ] + + [[ui.pages.widgets]] + type = "action_list" + label = "紧急待办" + max_items = 5 + queries = [ + { entity = "ticket", filter = "status == 'open'", sort = "priority asc", label_field = "title", subtitle_field = "type", action = "处理", icon = "warning" }, + { entity = "service_contract", filter = "status == 'active'", sort = "end_date asc", label_field = "name", subtitle_field = "end_date", action = "续约", icon = "file-text" }, + { entity = "check_plan", filter = "status == 'active'", sort = "next_check_date asc", label_field = "name", subtitle_field = "next_check_date", action = "巡检", icon = "schedule" } + ] +``` + +### 5.7 Template(维保合同 PDF) + +```toml +[[templates]] +name = "service_contract_pdf" +display_name = "维保合同" +entity = "service_contract" +format = "pdf" +template_html = """ + + + +

{{name}}

+

合同编号:{{contract_number}}

+
+
客户:{{client.name}}
+
合同金额:¥{{amount}}
+
期限:{{start_date}} 至 {{end_date}}
+
状态:{{status}}
+
+
+ SLA 承诺:响应 {{sla_response_hours}} 小时内 / 解决 {{sla_resolve_hours}} 小时内 +
+

服务范围:{{service_scope}}

+

付款条款:{{payment_terms}}

+

备注:{{notes}}

+
+
甲方签章
+
乙方签章
+
+ + +""" +``` + +--- + +## 6. 改进汇总 + +| 层次 | 能力 | freelance | itops | +|------|------|-----------|-------| +| Layer 1 | settings | 7 个配置项(公司名/税率/提醒偏好) | 4 个配置项(SLA默认值/提醒偏好) | +| Layer 1 | trigger_events | 5 个事件(商机/合同/发票/任务/支出) | 4 个事件(工单/合同/巡检) | +| Layer 1 | cascade | 4 处联动(合同/发票/工时表单) | 2 处联动(工单/巡检记录) | +| Layer 1 | visible_when | 4 个条件字段 | 6 个条件字段 | +| Layer 1 | validation | 2 个校验(邮箱/手机) | 1 个校验(合同编号格式) | +| Layer 2 | dashboard widgets | 财务卡片+紧急待办+商机漏斗+项目卡片 | 运维卡片+紧急待办 | +| Layer 3 | templates | 3 个 PDF(报价单/发票/合同) | 1 个 PDF(维保合同) | + +**总计:** 2 个插件 × 3 层增强,从「数据录入」升级为「赚钱工具」。 + +--- + +## 7. 实施优先级 + +``` +P1: freelance Layer 1(settings + trigger_events + cascade + visible_when + validation) +P2: itops Layer 1(settings + trigger_events + cascade + visible_when + validation) +P3: freelance Layer 3(3 个 PDF 模板) +P4: itops Layer 3(维保合同 PDF 模板) +P5: freelance Layer 2(仪表盘 widgets) +P6: itops Layer 2(仪表盘 widgets) +``` + +P1-P4 是纯 plugin.toml 改动,可立即实施。P5-P6 的仪表盘 widgets 需要前端配合解析 widgets 声明。