13 KiB
汕头市智界科技 IT 服务插件 — 实施计划
For agentic workers: REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: 为汕头市智界科技有限公司创建 freelance(自由职业者工作台)和 itops(IT 运维服务台)两个 WASM 插件,覆盖其全部 12 条经营范围。
Architecture: 两个独立的 WASM 插件 crate,每个包含 Cargo.toml(cdylib)、src/lib.rs(Guest trait 实现)、plugin.toml(声明式 schema)。通过插件安装 API 上传到系统,平台自动创建动态表、注册权限、生成前端页面。itops 通过 ref_plugin 跨插件引用 freelance 的 client 实体。
Tech Stack: Rust (wit-bindgen 0.55, cdylib → WASM Component)、TOML manifest、Axum Host API
Spec: docs/superpowers/specs/2026-04-19-shantou-zhijie-it-services-plugins-design.md
Chunk 1: freelance 插件
Task 1: 创建 crate 目录和 Cargo.toml
Files:
-
Create:
crates/erp-plugin-freelance/Cargo.toml -
Create:
crates/erp-plugin-freelance/src/lib.rs(空文件占位) -
Step 1: 创建目录结构
mkdir -p crates/erp-plugin-freelance/src
- Step 2: 编写 Cargo.toml
创建 crates/erp-plugin-freelance/Cargo.toml:
[package]
name = "erp-plugin-freelance"
version = "0.1.0"
edition = "2024"
description = "自由职业者工作台 WASM 插件"
[lib]
crate-type = ["cdylib"]
[dependencies]
wit-bindgen = "0.55"
- Step 3: 编写 src/lib.rs
创建 crates/erp-plugin-freelance/src/lib.rs:
//! 自由职业者工作台 WASM 插件
wit_bindgen::generate!({
path: "../erp-plugin-prototype/wit/plugin.wit",
world: "plugin-world",
});
use crate::exports::erp::plugin::plugin_api::Guest;
struct FreelancePlugin;
impl Guest for FreelancePlugin {
fn init() -> Result<(), String> {
Ok(())
}
fn on_tenant_created(_tenant_id: String) -> Result<(), String> {
Ok(())
}
fn handle_event(_event_type: String, _payload: Vec<u8>) -> Result<(), String> {
Ok(())
}
}
export!(FreelancePlugin);
- Step 4: 注册到 workspace
编辑根 Cargo.toml,在 members 数组末尾添加:
"crates/erp-plugin-freelance",
- Step 5: 验证编译
cargo check -p erp-plugin-freelance
Expected: 编译通过,无错误
- Step 6: Commit
git add crates/erp-plugin-freelance/ Cargo.toml
git commit -m "feat(freelance): 创建插件 crate 骨架"
Task 2: 编写 plugin.toml(freelance)
Files:
-
Create:
crates/erp-plugin-freelance/plugin.toml -
Step 1: 从设计规格文档复制完整 plugin.toml 内容
从设计规格 docs/superpowers/specs/2026-04-19-shantou-zhijie-it-services-plugins-design.md 中提取 2.1(元数据)+ 2.2(权限)+ 2.3(10 个实体)+ 2.4(编号规则)+ 2.5(页面声明)的所有 TOML 内容,合并为完整的 plugin.toml 文件。
文件结构:
[metadata]段[[permissions]]× 20[[schema.entities]]× 10(client, opportunity, quote, quote_line, contract, project, task, time_entry, invoice, expense),每个实体包含 fields 和 relations[[numbering]]× 3(quote_number, contract_number, invoice_number)[[ui.pages]]× 7(dashboard, tabs+detail+kanban for client, crud+detail for project, tabs for finance, crud for expense)
注意要点:
-
client 实体必须标记
is_public = true(被 itops 跨插件引用) -
quote 到 quote_line 有 cascade 关系
-
project 到 task 和 time_entry 有 cascade 关系
-
所有 uuid 引用字段使用
ui_widget = "entity_select"+ref_label_field+ref_search_fields -
所有 select 字段使用
options = [{ label = "X", value = "x" }]格式 -
长文本使用
field_type = "string"+ui_widget = "textarea" -
金额使用
field_type = "decimal" -
时间戳使用
field_type = "date_time" -
Step 2: 验证 TOML 格式
cargo check -p erp-plugin-freelance
- Step 3: Commit
git add crates/erp-plugin-freelance/plugin.toml
git commit -m "feat(freelance): 添加 plugin.toml — 10 实体/20 权限/7 页面"
Task 3: 编译 WASM 并安装
- Step 1: 编译为 WASM
cargo build -p erp-plugin-freelance --target wasm32-unknown-unknown --release
Expected: 编译成功,产出 target/wasm32-unknown-unknown/release/erp_plugin_freelance.wasm
- Step 2: 转换为 Component
wasm-tools component new target/wasm32-unknown-unknown/release/erp_plugin_freelance.wasm -o target/erp_plugin_freelance.component.wasm
- Step 3: 检查产物大小
ls -la target/erp_plugin_freelance.component.wasm
Expected: < 100KB(CRM 约 22KB)
- Step 4: 启动后端服务
cd crates/erp-server && cargo run
等待服务启动完成(看到 "listening on 0.0.0.0:3000" 日志)
- Step 5: 登录获取 Token
curl -s -X POST http://localhost:3000/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"admin123"}' | jq -r '.data.access_token'
保存输出的 token。
- Step 6: 上传安装插件
TOKEN="<上一步的 token>"
MANIFEST=$(cat crates/erp-plugin-freelance/plugin.toml)
curl -s -X POST http://localhost:3000/api/v1/admin/plugins/upload \
-H "Authorization: Bearer $TOKEN" \
-F "wasm=@target/erp_plugin_freelance.component.wasm" \
-F "manifest=$MANIST"
Expected: 返回插件 ID,状态为 installed
- Step 7: 启用插件
使用上一步返回的插件 ID:
PLUGIN_ID="<返回的插件 ID>"
curl -s -X POST "http://localhost:3000/api/v1/admin/plugins/$PLUGIN_ID/enable" \
-H "Authorization: Bearer $TOKEN"
Expected: 状态变为 running
- Step 8: Commit
git add -A
git commit -m "feat(freelance): 编译 WASM 并验证安装"
Task 4: 浏览器验证 freelance 插件
-
Step 1: 打开浏览器访问 http://localhost:5174
-
Step 2: 登录后检查侧边栏
Expected: 看到"自由职业者工作台"菜单组,包含:工作台、客户管理、商机看板、项目管理、项目详情、财务中心、支出管理
- Step 3: 测试客户 CRUD
进入客户管理 → 新增客户(填写名称、联系人、电话、行业等)→ 保存 → 列表中可见
- Step 4: 测试项目 → 任务级联
进入项目管理 → 新增项目 → 进入项目详情 → 新增任务 → 验证任务关联到项目
- Step 5: 测试报价 → 报价明细级联
进入财务中心 → 报价管理 tab → 新增报价 → 验证明细行可添加
- Step 6: 测试商机看板
进入商机看板 → 新增商机 → 拖拽改变阶段 → 验证数据更新
- Step 7: 验证数据库表创建
PGPASSWORD=123123 "D:\postgreSQL\bin\psql.exe" -U postgres -h localhost -d erp -c "\dt plugin_erp_freelance_*"
Expected: 看到 10 张动态表
Chunk 2: itops 插件
Task 5: 创建 itops 插件 crate
Files:
-
Create:
crates/erp-plugin-itops/Cargo.toml -
Create:
crates/erp-plugin-itops/src/lib.rs -
Create:
crates/erp-plugin-itops/plugin.toml -
Step 1: 创建目录结构
mkdir -p crates/erp-plugin-itops/src
- Step 2: 编写 Cargo.toml
创建 crates/erp-plugin-itops/Cargo.toml:
[package]
name = "erp-plugin-itops"
version = "0.1.0"
edition = "2024"
description = "IT 运维服务台 WASM 插件"
[lib]
crate-type = ["cdylib"]
[dependencies]
wit-bindgen = "0.55"
- Step 3: 编写 src/lib.rs
创建 crates/erp-plugin-itops/src/lib.rs:
//! IT 运维服务台 WASM 插件
wit_bindgen::generate!({
path: "../erp-plugin-prototype/wit/plugin.wit",
world: "plugin-world",
});
use crate::exports::erp::plugin::plugin_api::Guest;
struct ItopsPlugin;
impl Guest for ItopsPlugin {
fn init() -> Result<(), String> {
Ok(())
}
fn on_tenant_created(_tenant_id: String) -> Result<(), String> {
Ok(())
}
fn handle_event(_event_type: String, _payload: Vec<u8>) -> Result<(), String> {
Ok(())
}
}
export!(ItopsPlugin);
- Step 4: 编写 plugin.toml
从设计规格文档 Section 3 提取完整内容:
[metadata]— id="erp-itops",无 dependencies(松耦合)[[permissions]]× 8[[schema.entities]]× 4(service_contract, ticket, check_plan, check_record),每个实体包含 fields 和 relations[[numbering]]× 1(contract_number)[[ui.pages]]× 4(crud+detail for service_contract, tabs for ticket center)
关键注意点:
-
4 个实体的
client_id字段都使用ref_plugin = "erp-freelance"+ref_fallback_label = "外部客户" -
filterable只用于 string 类型的 status/type/category 字段,不用于 uuid 字段 -
check_items和items_data使用field_type = "json" -
responded_at/resolved_at/closed_at使用field_type = "date_time" -
Step 5: 注册到 workspace
编辑根 Cargo.toml,在 members 数组末尾添加:
"crates/erp-plugin-itops",
- Step 6: 验证编译
cargo check -p erp-plugin-itops
- Step 7: Commit
git add crates/erp-plugin-itops/ Cargo.toml
git commit -m "feat(itops): 创建 IT 运维服务台插件 — 4 实体/8 权限/4 页面"
Task 6: 编译 WASM 并安装 itops
- Step 1: 编译为 WASM
cargo build -p erp-plugin-itops --target wasm32-unknown-unknown --release
- Step 2: 转换为 Component
wasm-tools component new target/wasm32-unknown-unknown/release/erp_plugin_itops.wasm -o target/erp_plugin_itops.component.wasm
- Step 3: 上传安装插件
TOKEN="<之前获取的 token>"
MANIFEST=$(cat crates/erp-plugin-itops/plugin.toml)
curl -s -X POST http://localhost:3000/api/v1/admin/plugins/upload \
-H "Authorization: Bearer $TOKEN" \
-F "wasm=@target/erp_plugin_itops.component.wasm" \
-F "manifest=$MANIFEST"
- Step 4: 启用插件
PLUGIN_ID="<返回的插件 ID>"
curl -s -X POST "http://localhost:3000/api/v1/admin/plugins/$PLUGIN_ID/enable" \
-H "Authorization: Bearer $TOKEN"
Task 7: 浏览器验证 itops 插件
- Step 1: 检查侧边栏
Expected: 看到"IT 运维服务台"菜单组,包含:合同管理、合同详情、工单中心
- Step 2: 测试维保合同 CRUD
进入合同管理 → 新增维保合同(选择客户时验证:如 freelance 已安装,客户下拉显示 freelance 的客户列表)
- Step 3: 测试跨插件引用
场景 A(freelance 已安装):创建工单时 client_id 字段显示为下拉选择器,可搜索 freelance.client 场景 B(freelance 未安装):client_id 降级为文本输入,显示"外部客户"
- Step 4: 测试合同 → 工单 → 巡检级联
进入合同详情 → 工单 tab → 新增工单 → 巡检计划 tab → 新增巡检计划 → 巡检记录 tab → 新增巡检记录
- Step 5: 验证数据库表
PGPASSWORD=123123 "D:\postgreSQL\bin\psql.exe" -U postgres -h localhost -d erp -c "\dt plugin_erp_itops_*"
Expected: 看到 4 张动态表
Chunk 3: 集成验证
Task 8: 全链路端到端验证
- Step 1: 创建客户
freelance → 客户管理 → 新增客户"汕头市XX科技有限公司"
- Step 2: 创建商机
商机看板 → 新增商机 → 选择客户 → 填写"官网开发"→ 拖拽到"成交"阶段
- Step 3: 创建报价单
财务中心 → 报价管理 → 新增报价 → 选择客户 → 添加明细行 → 保存
- Step 4: 创建合同
财务中心 → 合同管理 → 新增合同 → 选择客户 → 填写金额和日期 → 保存
- Step 5: 创建项目
项目管理 → 新增项目 → 选择客户和合同 → 填写"官网开发项目" → 添加任务 → 记录工时
- Step 6: 创建发票
财务中心 → 发票/收款 → 新增发票 → 选择客户和项目 → 填写金额 → 标记已收款
- Step 7: 创建运维工单
itops → 合同管理 → 新增维保合同 → 选择客户(验证跨插件引用)→ 保存 itops → 工单中心 → 新增工单 → 选择客户和合同 → 保存
- Step 8: 记录支出
freelance → 支出管理 → 新增支出 → 选择类别"云服务" → 填写金额 → 保存
- Step 9: 提交并推送
git add -A
git commit -m "feat(freelance,itops): 汕头市智界科技 IT 服务行业插件验证通过"
git push
关键参考文件
| 文件 | 用途 |
|---|---|
crates/erp-plugin-crm/Cargo.toml |
Cargo.toml 模板参考 |
crates/erp-plugin-crm/src/lib.rs |
lib.rs 代码模式参考 |
crates/erp-plugin-crm/plugin.toml |
plugin.toml 格式参考(同插件内引用) |
crates/erp-plugin-inventory/plugin.toml |
跨插件引用格式参考(ref_plugin) |
crates/erp-plugin/src/manifest.rs |
PluginField/PluginFieldType 完整定义 |
crates/erp-plugin-prototype/wit/plugin.wit |
WIT 接口定义 |
wiki/infrastructure.md |
数据库连接、端口、登录凭据 |
wiki/wasm-plugin.md |
插件制作完整流程 |