CRM低代码平台数据库设计(PostgreSQL)

CRM低代码平台数据库设计(PostgreSQL)

以下是专为CRM场景设计的完整数据库架构,分为元数据层、业务数据层、工作流层、权限层、CRM业务层五大模块。 一、元数据层(Metadata Layer) 1.1 实体元数据表(Core Entity

以下是专为CRM场景设计的完整数据库架构,分为元数据层、业务数据层、工作流层、权限层、CRM业务层五大模块。

一、元数据层(Metadata Layer)

1.1 实体元数据表(Core Entity)

CREATE TABLE lc_entities (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    entity_code VARCHAR(100) NOT NULL,           -- 编码:customer/contact/opportunity
    entity_name VARCHAR(100) NOT NULL,           -- 名称:客户/联系人/销售机会
    table_name VARCHAR(100) NOT NULL,            -- 物理表名:ent_customer
    storage_type VARCHAR(20) DEFAULT 'jsonb',    -- 存储策略:jsonb/ddl/hybrid
    tenant_id UUID NOT NULL,                     -- 多租户隔离
    is_system BOOLEAN DEFAULT false,             -- 是否为系统预置(不可删除)
    is_enabled BOOLEAN DEFAULT true,
    description TEXT,
    created_by VARCHAR(50),
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW(),
    -- 租户内实体编码唯一
    UNIQUE(tenant_id, entity_code)
);

COMMENT ON TABLE lc_entities IS '实体元数据表,定义CRM所有业务对象';
CREATE INDEX idx_lc_entities_tenant ON lc_entities(tenant_id);

1.2 字段元数据表(Field Definition)

CREATE TABLE lc_fields (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    entity_id UUID NOT NULL REFERENCES lc_entities(id) ON DELETE CASCADE,
    field_code VARCHAR(100) NOT NULL,            -- 字段编码:name/phone/amount
    field_name VARCHAR(100) NOT NULL,            -- 显示名称:客户名称
    field_type VARCHAR(30) NOT NULL,             -- 基础类型:text/number/date/select/boolean
    component_type VARCHAR(50),                  -- 组件类型:Input/Select/ImageUpload
    
    -- 布局与分组
    field_group VARCHAR(50),                     -- 分组:基础信息/扩展信息/系统信息
    sort_order INT DEFAULT 0,                    -- 排序
    width VARCHAR(20) DEFAULT '1',               -- 布局宽度:1/2/1/3/1/4
    
    -- 校验规则
    is_required BOOLEAN DEFAULT false,
    is_unique BOOLEAN DEFAULT false,
    validation_rules JSONB,                      -- {"minLength":2,"maxLength":50,"regex":"^1[3-9]\\d{9}$"}
    
    -- 类型扩展属性
    attributes JSONB,                            -- 单选:{"options":[{"label":"男","value":"M","color":"blue"}]} 数字:{"precision":2,"isAmount":true}
    
    -- 关联关系(外键)
    ref_entity_id UUID REFERENCES lc_entities(id), -- 关联实体ID(如联系人关联客户)
    ref_type VARCHAR(20),                        -- 关联类型:oneToOne/oneToMany/manyToMany
    
    -- 统计配置
    is_summary BOOLEAN DEFAULT false,            -- 是否参与汇总
    
    -- 状态
    is_system BOOLEAN DEFAULT false,             -- 系统字段(不可删除)
    is_enabled BOOLEAN DEFAULT true,
    
    -- 审计
    created_by VARCHAR(50),
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW(),
    
    -- 实体内字段编码唯一
    UNIQUE(entity_id, field_code)
);

COMMENT ON TABLE lc_fields IS '字段元数据表,定义每个实体的动态字段';
CREATE INDEX idx_lc_fields_entity ON lc_fields(entity_id);
CREATE INDEX idx_lc_fields_type ON lc_fields(field_type);

1.3 表单元数据(Layout & UI)

CREATE TABLE lc_forms (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    entity_id UUID NOT NULL REFERENCES lc_entities(id) ON DELETE CASCADE,
    form_code VARCHAR(100) NOT NULL,             -- 表单编码:create_form/update_form
    form_name VARCHAR(100) NOT NULL,             -- 表单名称:新建客户
    layout_config JSONB,                         -- 布局:{"columns":2,"titlePosition":"top"}
    field_ids UUID[] NOT NULL,                   -- 字段ID列表(按顺序)
    is_default BOOLEAN DEFAULT false,            -- 是否为默认表单
    is_enabled BOOLEAN DEFAULT true,
    created_by VARCHAR(50),
    created_at TIMESTAMP DEFAULT NOW(),
    
    UNIQUE(entity_id, form_code)
);

COMMENT ON TABLE lc_forms IS '表单元数据,定义表单布局';
CREATE INDEX idx_lc_forms_entity ON lc_forms(entity_id);

低代码CRM工作流数据库架构设计

CRM低代码平台数据库设计(PostgreSQL)

以下是专为CRM场景设计的完整数据库架构,分为元数据层、业务数据层、工作流层、权限层、CRM业务层五大模块。


一、元数据层(Metadata Layer)

1.1 实体元数据表(Core Entity)

sql

复制

CREATE TABLE lc_entities (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    entity_code VARCHAR(100) NOT NULL,           -- 编码:customer/contact/opportunity
    entity_name VARCHAR(100) NOT NULL,           -- 名称:客户/联系人/销售机会
    table_name VARCHAR(100) NOT NULL,            -- 物理表名:ent_customer
    storage_type VARCHAR(20) DEFAULT 'jsonb',    -- 存储策略:jsonb/ddl/hybrid
    tenant_id UUID NOT NULL,                     -- 多租户隔离
    is_system BOOLEAN DEFAULT false,             -- 是否为系统预置(不可删除)
    is_enabled BOOLEAN DEFAULT true,
    description TEXT,
    created_by VARCHAR(50),
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW(),
    -- 租户内实体编码唯一
    UNIQUE(tenant_id, entity_code)
);

COMMENT ON TABLE lc_entities IS '实体元数据表,定义CRM所有业务对象';
CREATE INDEX idx_lc_entities_tenant ON lc_entities(tenant_id);

1.2 字段元数据表(Field Definition)

sql

复制

CREATE TABLE lc_fields (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    entity_id UUID NOT NULL REFERENCES lc_entities(id) ON DELETE CASCADE,
    field_code VARCHAR(100) NOT NULL,            -- 字段编码:name/phone/amount
    field_name VARCHAR(100) NOT NULL,            -- 显示名称:客户名称
    field_type VARCHAR(30) NOT NULL,             -- 基础类型:text/number/date/select/boolean
    component_type VARCHAR(50),                  -- 组件类型:Input/Select/ImageUpload
    
    -- 布局与分组
    field_group VARCHAR(50),                     -- 分组:基础信息/扩展信息/系统信息
    sort_order INT DEFAULT 0,                    -- 排序
    width VARCHAR(20) DEFAULT '1',               -- 布局宽度:1/2/1/3/1/4
    
    -- 校验规则
    is_required BOOLEAN DEFAULT false,
    is_unique BOOLEAN DEFAULT false,
    validation_rules JSONB,                      -- {"minLength":2,"maxLength":50,"regex":"^1[3-9]\\d{9}$"}
    
    -- 类型扩展属性
    attributes JSONB,                            -- 单选:{"options":[{"label":"男","value":"M","color":"blue"}]} 数字:{"precision":2,"isAmount":true}
    
    -- 关联关系(外键)
    ref_entity_id UUID REFERENCES lc_entities(id), -- 关联实体ID(如联系人关联客户)
    ref_type VARCHAR(20),                        -- 关联类型:oneToOne/oneToMany/manyToMany
    
    -- 统计配置
    is_summary BOOLEAN DEFAULT false,            -- 是否参与汇总
    
    -- 状态
    is_system BOOLEAN DEFAULT false,             -- 系统字段(不可删除)
    is_enabled BOOLEAN DEFAULT true,
    
    -- 审计
    created_by VARCHAR(50),
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW(),
    
    -- 实体内字段编码唯一
    UNIQUE(entity_id, field_code)
);

COMMENT ON TABLE lc_fields IS '字段元数据表,定义每个实体的动态字段';
CREATE INDEX idx_lc_fields_entity ON lc_fields(entity_id);
CREATE INDEX idx_lc_fields_type ON lc_fields(field_type);

1.3 表单元数据(Layout & UI)

sql

复制

CREATE TABLE lc_forms (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    entity_id UUID NOT NULL REFERENCES lc_entities(id) ON DELETE CASCADE,
    form_code VARCHAR(100) NOT NULL,             -- 表单编码:create_form/update_form
    form_name VARCHAR(100) NOT NULL,             -- 表单名称:新建客户
    layout_config JSONB,                         -- 布局:{"columns":2,"titlePosition":"top"}
    field_ids UUID[] NOT NULL,                   -- 字段ID列表(按顺序)
    is_default BOOLEAN DEFAULT false,            -- 是否为默认表单
    is_enabled BOOLEAN DEFAULT true,
    created_by VARCHAR(50),
    created_at TIMESTAMP DEFAULT NOW(),
    
    UNIQUE(entity_id, form_code)
);

COMMENT ON TABLE lc_forms IS '表单元数据,定义表单布局';
CREATE INDEX idx_lc_forms_entity ON lc_forms(entity_id);

1.4 字段依赖关系表(Field Dependencies)

sql

复制

CREATE TABLE lc_field_deps (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    entity_id UUID NOT NULL REFERENCES lc_entities(id) ON DELETE CASCADE,
    parent_field_id UUID NOT NULL REFERENCES lc_fields(id),
    child_field_id UUID NOT NULL REFERENCES lc_fields(id),
    data_source_url TEXT,                        -- 级联数据源:/api/options/city?province={value}
    created_at TIMESTAMP DEFAULT NOW(),
    
    UNIQUE(entity_id, parent_field_id, child_field_id)
);

COMMENT ON TABLE lc_field_deps IS '字段依赖关系(级联选择)';

二、业务数据层(Business Data Layer)

2.1 统一动态数据表(JSONB 存储)

CREATE TABLE lc_data (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    entity_id UUID NOT NULL REFERENCES lc_entities(id),
    tenant_id UUID NOT NULL,
    record_id UUID NOT NULL,                     -- 业务记录ID(用于关联)
    
    -- 动态数据(核心)
    field_values JSONB NOT NULL DEFAULT '{}',    -- {"name":"客户A","phone":"13800000000","amount":10000}
    
    -- 系统字段
    created_by VARCHAR(50),
    created_at TIMESTAMP DEFAULT NOW(),
    updated_by VARCHAR(50),
    updated_at TIMESTAMP DEFAULT NOW(),
    owner_id UUID,                               -- 负责人
    dept_id UUID,                                -- 所属部门
    
    -- 辅助字段(提升查询性能)
    is_starred BOOLEAN DEFAULT false,            -- 是否重点客户
    last_follow_time TIMESTAMP,                  -- 最后跟进时间
    
    -- 索引
    INDEX idx_lc_data_entity_tenant (entity_id, tenant_id),
    INDEX idx_lc_data_record (record_id),
    INDEX idx_lc_data_created (created_at DESC),
    INDEX idx_lc_data_owner (owner_id),
    
    -- GIN 索引(JSONB 全文检索)
    INDEX idx_lc_data_values_gin ON lc_data USING GIN (field_values)
);

COMMENT ON TABLE lc_data IS '统一业务数据表,所有实体的动态数据存入 JSONB';

2.2 数据关系表(ManyToMany)

CREATE TABLE lc_relations (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    entity_id UUID NOT NULL REFERENCES lc_entities(id),
    from_record_id UUID NOT NULL,                -- 源记录ID
    to_record_id UUID NOT NULL,                  -- 目标记录ID
    relation_type VARCHAR(50),                   -- 关联类型:contact/opportunity/order
    created_at TIMESTAMP DEFAULT NOW(),
    
    -- 联合索引(双向查询)
    INDEX idx_relations_from (entity_id, from_record_id),
    INDEX idx_relations_to (entity_id, to_record_id)
);

COMMENT ON TABLE lc_relations IS '实体关系表(客户-联系人、客户-机会)';

2.3 数据快照表(历史版本)

CREATE TABLE lc_data_history (

id UUID PRIMARY KEY DEFAULT gen_random_uuid(),

data_id UUID NOT NULL REFERENCES lc_data(id) ON DELETE CASCADE,

version INT NOT NULL, -- 版本号

field_values JSONB NOT NULL, -- 历史数据快照

operation_type VARCHAR(20), -- create/update/delete

operator VARCHAR(50),

operated_at TIMESTAMP DEFAULT NOW(),

INDEX idx_history_data (data_id, version DESC)

);

COMMENT ON TABLE lc_data_history IS '数据历史版本表(操作日志)';

三、工作流层(Workflow Layer)

3.1 工作流定义表

CREATE TABLE wf_definitions (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    wf_code VARCHAR(100) NOT NULL,               -- 编码:contract_approval
    wf_name VARCHAR(100) NOT NULL,               -- 名称:合同审批流
    entity_id UUID REFERENCES lc_entities(id),   -- 关联实体(可选)
    tenant_id UUID NOT NULL,
    
    -- BPMN 流程定义
    bpmn_xml TEXT,                               -- BPMN 2.0 XML
    process_definition_id VARCHAR(100),          -- Flowable/Camunda 流程定义ID
    
    is_enabled BOOLEAN DEFAULT true,
    version INT DEFAULT 1,
    created_by VARCHAR(50),
    created_at TIMESTAMP DEFAULT NOW(),
    
    UNIQUE(tenant_id, wf_code, version)
);

COMMENT ON TABLE wf_definitions IS '工作流定义表';
CREATE INDEX idx_wf_def_tenant ON wf_definitions(tenant_id);

3.2 流程实例表

CREATE TABLE wf_instances (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    wf_definition_id UUID NOT NULL REFERENCES wf_definitions(id),
    business_key VARCHAR(100),                   -- 业务主键(如合同ID)
    record_id UUID,                              -- 关联业务记录
    
    -- 流程状态
    status VARCHAR(20) DEFAULT 'running',        -- running/completed/suspended
    current_node VARCHAR(100),                   -- 当前节点
    
    -- 发起人
    starter_id UUID,
    start_time TIMESTAMP DEFAULT NOW(),
    end_time TIMESTAMP,
    
    INDEX idx_wf_instances_business (business_key),
    INDEX idx_wf_instances_record (record_id)
);

COMMENT ON TABLE wf_instances IS '流程实例表';

3.3 任务表(待办事项)

CREATE TABLE wf_tasks (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    instance_id UUID NOT NULL REFERENCES wf_instances(id) ON DELETE CASCADE,
    node_id VARCHAR(100) NOT NULL,
    node_name VARCHAR(100),                      -- 节点名称:部门经理审批
    
    -- 任务分配
    assignee_id UUID,                            -- 负责人
    assignee_dept_id UUID,                       -- 负责部门(支持部门负责人审批)
    
    -- 任务状态
    status VARCHAR(20) DEFAULT 'pending',        -- pending/completed/delegated
    priority INT DEFAULT 5,                      -- 优先级 1-10
    
    -- 时间
    create_time TIMESTAMP DEFAULT NOW(),
    due_time TIMESTAMP,                          -- 截止时间
    complete_time TIMESTAMP,
    
    -- 扩展
    variables JSONB,                             -- 流程变量
    
    INDEX idx_wf_tasks_assignee (assignee_id, status),
    INDEX idx_wf_tasks_due (due_time)
);

COMMENT ON TABLE wf_tasks IS '工作流任务表(用户待办)';

3.4 任务操作日志

CREATE TABLE wf_task_logs (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    task_id UUID NOT NULL REFERENCES wf_tasks(id),
    operation VARCHAR(20),                       -- approve/reject/delegate
    operator_id UUID,
    comment TEXT,
    operate_time TIMESTAMP DEFAULT NOW(),
    
    INDEX idx_logs_task (task_id)
);

COMMENT ON TABLE wf_task_logs IS '任务操作日志';

四、权限层(Permission Layer)

4.1 角色表

sql

复制

CREATE TABLE perm_roles (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,
    role_code VARCHAR(100) NOT NULL,             -- admin/manager/sales
    role_name VARCHAR(100),
    is_system BOOLEAN DEFAULT false,
    parent_id UUID REFERENCES perm_roles(id),    -- 角色层级
    
    UNIQUE(tenant_id, role_code)
);

COMMENT ON TABLE perm_roles IS '角色表';
CREATE INDEX idx_perm_roles_tenant ON perm_roles(tenant_id);

4.2 用户角色关系

sql

复制

CREATE TABLE perm_user_roles (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL,
    role_id UUID NOT NULL REFERENCES perm_roles(id),
    tenant_id UUID NOT NULL,
    
    UNIQUE(user_id, role_id, tenant_id)
);

COMMENT ON TABLE perm_user_roles IS '用户角色关系';

4.3 数据权限规则(核心)

sql

复制

CREATE TABLE perm_data_rules (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    entity_id UUID NOT NULL REFERENCES lc_entities(id),
    role_id UUID REFERENCES perm_roles(id),
    user_id UUID,                                -- 特定用户规则(优先级高于角色)
    
    -- 规则类型
    rule_type VARCHAR(20),                       -- owner/dept/created/custom
    
    -- 自定义规则(SQL WHERE 片段)
    custom_filter TEXT,                          -- owner_id = ${currentUserId}
    
    is_enabled BOOLEAN DEFAULT true,
    priority INT DEFAULT 0,                      -- 规则优先级
    
    INDEX idx_perm_rules_entity (entity_id)
);

COMMENT ON TABLE perm_data_rules IS '数据权限规则(谁能看什么数据)';

4.4 字段权限表

sql

复制

CREATE TABLE perm_field_rules (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    field_id UUID NOT NULL REFERENCES lc_fields(id),
    role_id UUID REFERENCES perm_roles(id),
    user_id UUID,
    
    -- 权限
    can_visible BOOLEAN DEFAULT true,
    can_edit BOOLEAN DEFAULT false,
    
    -- 高级规则(排除特定用户)
    exclude_user_ids UUID[],
    
    is_enabled BOOLEAN DEFAULT true,
    
    UNIQUE(field_id, role_id, user_id)
);

COMMENT ON TABLE perm_field_rules IS '字段级权限(谁能看/编辑某个字段)';

五、CRM 业务层(CRM-Specific)

5.1 租户配置表

sql

复制

CREATE TABLE crm_tenant_config (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL UNIQUE,
    
    -- 客户查重规则
    dedup_enabled BOOLEAN DEFAULT true,
    dedup_fields TEXT[] DEFAULT '{name,phone}',  -- 默认查重字段
    
    -- 公海池规则
    pool_enabled BOOLEAN DEFAULT true,
    pool_expire_days INT DEFAULT 30,             -- 多久未跟进进入公海
    
    -- 客户编号规则
    serial_number_rule TEXT DEFAULT 'KH{yyyy}{MM}{dddd}',  -- 流水号规则
    
    created_at TIMESTAMP DEFAULT NOW()
);

COMMENT ON TABLE crm_tenant_config IS '租户级CRM配置';

5.2 公海池记录

sql

复制

CREATE TABLE crm_customer_pool (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    customer_id UUID NOT NULL,                   -- 客户ID(关联 lc_data)
    tenant_id UUID NOT NULL,
    
    -- 进入公海原因
    enter_reason VARCHAR(50),                    -- expire/manual
    enter_time TIMESTAMP DEFAULT NOW(),
    
    -- 领取限制
    last_pickup_user_id UUID,                    -- 上次负责人(防止重复领取)
    
    INDEX idx_pool_tenant (tenant_id, enter_time)
);

COMMENT ON TABLE crm_customer_pool IS '公海池客户';

5.3 跟进计划

sql

复制

CREATE TABLE crm_visit_plans (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    record_id UUID NOT NULL,                     -- 关联业务记录(客户ID)
    entity_id UUID NOT NULL,
    tenant_id UUID NOT NULL,
    
    -- 计划内容
    plan_time TIMESTAMP NOT NULL,                -- 计划时间
    plan_content TEXT,
    plan_type VARCHAR(20),                       -- phone/visit/demo
    
    -- 执行结果
    execute_time TIMESTAMP,
    execute_result TEXT,
    status VARCHAR(20) DEFAULT 'pending',        -- pending/completed/overdue
    
    -- 负责人
    owner_id UUID,
    
    INDEX idx_plans_record (record_id, plan_time),
    INDEX idx_plans_owner (owner_id, plan_time)
);

COMMENT ON TABLE crm_visit_plans IS '访客计划';

六、扩展功能表(Extension)

6.1 查重日志

sql

复制

CREATE TABLE dup_check_logs (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    entity_id UUID NOT NULL,
    tenant_id UUID NOT NULL,
    checked_data JSONB,                          -- {name: "客户A", phone: "138000"}
    matched_records UUID[],                      -- 匹配到的记录ID
    match_score FLOAT,                           -- 匹配度
    created_at TIMESTAMP DEFAULT NOW(),
    
    INDEX idx_dup_log_tenant (tenant_id, created_at)
);

COMMENT ON TABLE dup_check_logs IS '查重检测日志';

6.2 操作审计表

sql

复制

CREATE TABLE audit_logs (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,
    user_id UUID NOT NULL,
    entity_id UUID,
    record_id UUID,
    
    operation VARCHAR(20),                       -- create/read/update/delete
    old_values JSONB,                            -- 旧值
    new_values JSONB,                            -- 新值
    
    ip_address INET,
    user_agent TEXT,
    operated_at TIMESTAMP DEFAULT NOW(),
    
    INDEX idx_audit_user (user_id, operated_at),
    INDEX idx_audit_record (entity_id, record_id)
);

COMMENT ON TABLE audit_logs IS '全量操作审计';

七、PostgreSQL 高级特性应用

7.1 行级安全(RLS)- 实现多租户隔离

sql

复制

-- 启用RLS
ALTER TABLE lc_data ENABLE ROW LEVEL SECURITY;

-- 创建策略(每个租户只能看到自己的数据)
CREATE POLICY tenant_isolation ON lc_data
    FOR ALL
    USING (tenant_id = current_setting('app.current_tenant')::UUID);

-- 应用连接时设置租户上下文
SET app.current_tenant = 'your-tenant-id';

7.2 分区表(应对大数据量)

sql

复制

-- 按创建时间分区(每月一个分区)
CREATE TABLE lc_data_2025_01 PARTITION OF lc_data
    FOR VALUES FROM ('2025-01-01') TO ('2025-02-01');

CREATE TABLE lc_data_2025_02 PARTITION OF lc_data
    FOR VALUES FROM ('2025-02-01') TO ('2025-03-01');

-- 自动分区函数(每月执行)
CREATE OR REPLACE FUNCTION create_monthly_partition()
RETURNS void AS $$
DECLARE
    partition_name TEXT;
    start_date DATE;
    end_date DATE;
BEGIN
    start_date := date_trunc('month', CURRENT_DATE + interval '1 month');
    end_date := start_date + interval '1 month';
    partition_name := 'lc_data_' || to_char(start_date, 'YYYY_MM');
    
    EXECUTE format(
        'CREATE TABLE IF NOT EXISTS %I PARTITION OF lc_data FOR VALUES FROM (%L) TO (%L)',
        partition_name, start_date, end_date
    );
END;
$$ LANGUAGE plpgsql;

7.3 JSONB 查询性能优化

sql

复制

-- 表达式索引(高频字段)
CREATE INDEX idx_customer_name ON lc_data ((field_values->>'name')) 
    WHERE entity_id = 'customer-entity-id';

-- 复合GIN索引
CREATE INDEX idx_lc_data_multi_gin ON lc_data 
    USING GIN (field_values jsonb_path_ops);

-- 覆盖索引
CREATE INDEX idx_lc_data_covering 
    ON lc_data (tenant_id, entity_id, created_at DESC) 
    INCLUDE (field_values);

八、初始化 SQL 脚本

sql

复制

-- 执行顺序:先元数据 → 再业务 → 最后工作流

-- 1. 创建扩展
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "pg_trgm";  -- 模糊匹配

-- 2. 创建元数据表
\i 01_metadata_tables.sql

-- 3. 创建业务数据表
\i 02_business_tables.sql

-- 4. 创建工作流表
\i 03_workflow_tables.sql

-- 5. 创建权限表
\i 04_permission_tables.sql

-- 6. 创建CRM业务表
\i 05_crm_tables.sql

-- 7. 创建索引
\i 06_create_indexes.sql

-- 8. 创建RLS策略(可选)
\i 07_rls_policies.sql

九、核心使用示例

9.1 创建客户实体

sql

复制

-- 1. 插入实体元数据
INSERT INTO lc_entities (entity_code, entity_name, table_name, tenant_id)
VALUES ('customer', '客户管理', 'ent_customer', 'tenant-001');

-- 2. 插入字段元数据
INSERT INTO lc_fields (entity_id, field_code, field_name, field_type, component_type, sort_order, is_required)
VALUES 
    (currval('lc_entities_id_seq'), 'name', '客户名称', 'text', 'Input', 10, true),
    (currval('lc_entities_id_seq'), 'phone', '手机号', 'text', 'Input', 20, true),
    (currval('lc_entities_id_seq'), 'amount', '合同金额', 'number', 'NumberPicker', 30, false);

9.2 查询客户数据

sql

复制

-- 根据元数据动态查询
SELECT 
    field_values->>'name' AS name,
    field_values->>'phone' AS phone,
    (field_values->>'amount')::DECIMAL AS amount
FROM lc_data
WHERE entity_id = 'customer-entity-id' 
  AND tenant_id = 'tenant-001'
  AND field_values->>'name' ILIKE '%阿里巴巴%'
ORDER BY created_at DESC
LIMIT 20;

9.3 创建工作流

sql

复制

INSERT INTO wf_definitions (wf_code, wf_name, entity_id, tenant_id, bpmn_xml)
VALUES (
    'contract_approval', 
    '合同审批流',
    'contract-entity-id',
    'tenant-001',
    '<bpmn:process>...</bpmn:process>'  -- BPMN XML
);

十、性能与安全建议

性能优化清单

  1. 大表分区lc_datatenant_id + created_at 分区

  2. 索引策略:每个租户高频查询字段建表达式索引

  3. 查询限流:复杂查询强制走 EXPLAIN ANALYZE,超时自动熔断

  4. 读写分离:只读查询走从库,写入走主库

安全加固清单

  1. 强制 RLS:所有业务表启用行级安全

  2. SQL 注入防护:使用参数化查询,禁止拼接 SQL

  3. 字段权限:后端每次查询后,根据 perm_field_rules 过滤字段

  4. 审计日志:所有写操作记录到 audit_logs

总结

  1. 元数据层是大脑:存储"如何展示、如何校验、谁能看"的配置

  2. 业务数据层是血液:存储实际业务数据,通过 entity_id 与元数据关联

  3. 工作流层是神经:驱动业务流程,通过 record_id 关联业务数据

  4. 权限层是免疫系统:所有访问必须经过权限校验

核心查询逻辑所有查询都从 lc_entities 开始 → 加载 lc_fields → 生成动态 SQL → 查询 lc_data,权限过滤贯穿始终。

LICENSED UNDER CC BY-NC-SA 4.0
评论