模块开发指南

学习如何基于 JSaas 基座开发一个完整的 SaaS 业务模块,涵盖规范、API、数据库及前端开发。

模块规范

每个 JSaas 模块都必须遵循统一的模块规范,通过 module.json 文件声明模块的元数据信息:

json
{
  "name": "crm-module",
  "displayName": "CRM 客户管理",
  "version": "1.0.0",
  "description": "客户关系管理模块,支持客户跟进、商机管理和销售漏斗分析",
  "author": "your-company",
  "license": "MIT",
  "icon": "Users",
  "category": "CRM",
  "tags": ["客户管理", "销售", "CRM"],
  "dependencies": {
    "base-platform": ">=2.0.0",
    "notification-module": ">=1.0.0"
  },
  "permissions": [
    { "code": "crm:customer:read", "name": "查看客户" },
    { "code": "crm:customer:write", "name": "编辑客户" },
    { "code": "crm:opportunity:read", "name": "查看商机" }
  ],
  "menu": {
    "name": "客户管理",
    "icon": "Users",
    "order": 10
  }
}

name 字段为模块唯一标识,发布后不可修改。 版本号需遵循语义化版本规范(SemVer),升级时向后兼容。

API 开发

JSaas 模块基于 Spring Boot,推荐采用 RESTful 风格设计 API。 基座提供统一的响应格式和异常处理机制:

java
@RestController
@RequestMapping("/api/v1/contacts")
@Tag(name = "联系人管理")
public class ContactController {

    @GetMapping
    @RequireAuth("crm:contact:read")
    @Operation(summary = "查询联系人列表")
    public Result<PageResult<ContactVO>> list(
        @Parameter(description = "关键词搜索") @RequestParam(required = false) String keyword,
        @Parameter(description = "分页参数") @Valid PageParam pageParam
    ) {
        PageResult<ContactVO> result = contactService.list(keyword, pageParam);
        return Result.success(result);
    }

    @PostMapping
    @RequireAuth("crm:contact:write")
    @Operation(summary = "创建联系人")
    public Result<ContactVO> create(
        @Valid @RequestBody ContactCreateDTO dto
    ) {
        ContactVO vo = contactService.create(dto);
        return Result.success(vo);
    }
}

基座统一返回格式 Result<T>,包含 codemessagedata 三个字段。 业务异常抛出 BusinessException 即可自动转换为标准错误响应。

数据库设计

数据库变更使用 Flyway 管理,迁移脚本放置在 src/main/resources/db/migration/ 目录下。基座启动时会自动执行待迁移的脚本:

sql
-- V1.0.0__create_contact_table.sql
CREATE TABLE IF NOT EXISTS crm_contact (
  id          BIGINT PRIMARY KEY AUTO_INCREMENT,
  tenant_id   VARCHAR(32)  NOT NULL COMMENT '租户ID',
  name        VARCHAR(64)  NOT NULL COMMENT '联系人名称',
  phone       VARCHAR(20)  COMMENT '联系电话',
  email       VARCHAR(128) COMMENT '电子邮箱',
  company     VARCHAR(128) COMMENT '所属公司',
  source      VARCHAR(32)  COMMENT '客户来源',
  status      TINYINT      DEFAULT 1 COMMENT '状态 1-正常 0-删除',
  created_by  BIGINT       COMMENT '创建人ID',
  created_at  DATETIME     DEFAULT CURRENT_TIMESTAMP,
  updated_at  DATETIME     DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  INDEX idx_tenant (tenant_id),
  INDEX idx_tenant_name (tenant_id, name)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='联系人表';

所有业务表必须包含 tenant_id 字段, 并建立租户联合索引。基座的 MyBatis 插件会自动在 SQL 中追加 AND tenant_id = ? 条件,保障数据隔离。

前端开发

模块前端基于 React + TypeScript,通过基座提供的微前端框架嵌入管理后台。 前端项目结构如下:

bash
ui/
├── package.json
├── vite.config.ts          # Vite 构建配置
├── src/
│   ├── index.tsx            # 入口文件,注册微前端模块
│   ├── App.tsx              # 根组件
│   ├── pages/               # 页面组件
│   │   ├── ContactList.tsx
│   │   └── ContactDetail.tsx
│   ├── services/            # API 调用
│   │   └── contact.ts
│   └── components/          # 共享组件
└── tsconfig.json
typescript
// src/index.tsx - 微前端注册入口
import { defineModule } from '@jsaas/ui-kit';
import App from './App';

export default defineModule({
  name: 'crm-module',
  routes: [
    { path: '/contacts', component: () => import('./pages/ContactList') },
    { path: '/contacts/:id', component: () => import('./pages/ContactDetail') },
  ],
  render: (container) => {
    const root = createRoot(container);
    root.render(<App />);
  },
});