api_bd_compose_guide.md 17 KB

业务领域组合创建接口 - 前端开发指南

本文档为前端开发人员提供业务领域组合创建 (/compose) 接口的详细使用说明。

目录


接口概述

功能说明

该接口用于从已有的元数据中组合创建新的业务领域。用户可以从不同的业务领域中选择需要的元数据(DataMeta),将它们组合到一个新的业务领域中。

业务流程

┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│   用户选择      │     │   提交创建      │     │   返回结果      │
│   元数据列表    │ ──► │   请求          │ ──► │   新业务领域    │
└─────────────────┘     └─────────────────┘     └─────────────────┘

核心特性

  • ✅ 支持选择多个元数据
  • ✅ 自动翻译中文名称为英文(若未提供)
  • ✅ 支持关联标签和数据源
  • ✅ 自动创建业务领域与元数据的 INCLUDES 关系

接口规格

基本信息

项目 说明
请求URL POST /api/bd/compose
Content-Type application/json
请求方法 POST

请求头

Content-Type: application/json

请求参数详解

参数列表

参数名 类型 必填 默认值 说明
name_zh string ✅ 是 - 业务领域中文名称
name_en string 自动翻译 业务领域英文名称
id_list array ✅ 是 - 选中的元数据ID列表
describe string - 业务领域描述
type string - 业务领域类型
category string - 业务领域分类
tag array/integer - 标签ID或标签对象数组
data_source integer - 数据源ID

id_list 参数格式

id_list 支持两种格式,前端可根据实际情况选择:

格式一:纯ID数组(推荐)

最简洁的格式,直接传递元数据的 ID 列表:

{
  "name_zh": "销售分析域",
  "id_list": [123, 456, 789]
}

格式二:对象数组

兼容旧格式,传递包含 id 字段的对象数组:

{
  "name_zh": "销售分析域",
  "id_list": [
    { "id": 123 },
    { "id": 456 },
    { "id": 789 }
  ]
}

tag 参数格式

tag 参数支持多种格式:

// 格式1:单个标签ID
{ "tag": 100 }

// 格式2:标签ID数组
{ "tag": [100, 101, 102] }

// 格式3:标签对象数组
{ "tag": [{ "id": 100 }, { "id": 101 }] }

// 格式4:完整标签对象
{ "tag": [{ "id": 100, "name_zh": "核心业务", "name_en": "core" }] }

可选字段说明

以下字段均为可选,根据业务需求选择性传递:

字段名 类型 说明
leader string 负责人
organization string 所属组织
status string 状态
keywords string 关键词
data_sensitivity string 数据敏感性
frequency string 更新频率
url string 相关URL
storage_location string 存储位置

响应格式

成功响应

{
  "code": 200,
  "message": "操作成功",
  "data": {
    "business_domain": {
      "id": 12350,
      "name_zh": "销售分析域",
      "name_en": "sales_analysis_domain",
      "describe": "整合订单和客户数据的销售分析业务领域",
      "type": "analysis",
      "category": "业务分析",
      "create_time": "2025-01-09 10:30:00",
      "update_time": "2025-01-09 10:30:00",
      "tag": [
        {
          "id": 100,
          "name_zh": "核心业务",
          "name_en": "core_business"
        }
      ]
    }
  }
}

响应字段说明

字段路径 类型 说明
code integer 状态码,200 表示成功
message string 操作结果消息
data.business_domain object 创建的业务领域详情
data.business_domain.id integer 新创建的业务领域节点ID
data.business_domain.name_zh string 中文名称
data.business_domain.name_en string 英文名称
data.business_domain.tag array 关联的标签列表

失败响应

{
  "code": 500,
  "message": "组合创建业务领域失败",
  "data": null,
  "error": "具体错误信息"
}

前端实现示例

使用 Axios

import axios from 'axios';

/**
 * 组合创建业务领域
 * @param {Object} params - 创建参数
 * @param {string} params.name_zh - 中文名称(必填)
 * @param {string} [params.name_en] - 英文名称(可选,自动翻译)
 * @param {number[]} params.id_list - 元数据ID列表(必填)
 * @param {string} [params.describe] - 描述
 * @param {string} [params.type] - 类型
 * @param {string} [params.category] - 分类
 * @param {number|number[]} [params.tag] - 标签ID
 * @param {number} [params.data_source] - 数据源ID
 * @returns {Promise<Object>} 创建结果
 */
async function composeBusinessDomain(params) {
  try {
    const response = await axios.post('/api/bd/compose', params);
    
    if (response.data.code === 200) {
      return {
        success: true,
        data: response.data.data.business_domain
      };
    } else {
      return {
        success: false,
        message: response.data.message,
        error: response.data.error
      };
    }
  } catch (error) {
    console.error('组合创建业务领域失败:', error);
    throw error;
  }
}

// 使用示例
const result = await composeBusinessDomain({
  name_zh: '客户订单分析域',
  describe: '整合客户信息和订单数据的分析业务领域',
  id_list: [101, 102, 103, 201, 202],  // 选中的元数据ID
  tag: [100],  // 标签ID
  category: '业务分析'
});

if (result.success) {
  console.log('创建成功,新业务领域ID:', result.data.id);
} else {
  console.error('创建失败:', result.message);
}

使用 Fetch API

/**
 * 组合创建业务领域
 */
async function composeBusinessDomain(params) {
  const response = await fetch('/api/bd/compose', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(params)
  });
  
  const data = await response.json();
  
  if (data.code !== 200) {
    throw new Error(data.message || '创建失败');
  }
  
  return data.data.business_domain;
}

// 使用示例
try {
  const newDomain = await composeBusinessDomain({
    name_zh: '销售报表域',
    id_list: [301, 302, 303]
  });
  console.log('创建成功:', newDomain);
} catch (error) {
  console.error('创建失败:', error.message);
}

Vue 3 组件示例

<template>
  <div class="compose-form">
    <el-form :model="form" :rules="rules" ref="formRef" label-width="100px">
      <el-form-item label="中文名称" prop="name_zh">
        <el-input v-model="form.name_zh" placeholder="请输入业务领域中文名称" />
      </el-form-item>
      
      <el-form-item label="英文名称" prop="name_en">
        <el-input v-model="form.name_en" placeholder="可选,不填则自动翻译" />
      </el-form-item>
      
      <el-form-item label="描述" prop="describe">
        <el-input type="textarea" v-model="form.describe" :rows="3" />
      </el-form-item>
      
      <el-form-item label="元数据" prop="id_list">
        <div class="selected-meta">
          <el-tag 
            v-for="id in form.id_list" 
            :key="id" 
            closable 
            @close="removeMeta(id)"
          >
            {{ getMetaName(id) }}
          </el-tag>
        </div>
        <el-button type="primary" text @click="openMetaSelector">
          选择元数据
        </el-button>
      </el-form-item>
      
      <el-form-item>
        <el-button type="primary" @click="handleSubmit" :loading="loading">
          创建业务领域
        </el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<script setup>
import { ref, reactive } from 'vue';
import { ElMessage } from 'element-plus';
import axios from 'axios';

const formRef = ref(null);
const loading = ref(false);

const form = reactive({
  name_zh: '',
  name_en: '',
  describe: '',
  id_list: []
});

const rules = {
  name_zh: [
    { required: true, message: '请输入中文名称', trigger: 'blur' }
  ],
  id_list: [
    { 
      required: true, 
      validator: (rule, value, callback) => {
        if (!value || value.length === 0) {
          callback(new Error('请至少选择一个元数据'));
        } else {
          callback();
        }
      }, 
      trigger: 'change' 
    }
  ]
};

// 选择元数据
const openMetaSelector = () => {
  // 打开元数据选择器对话框
  // 实现略...
};

// 移除已选元数据
const removeMeta = (id) => {
  const index = form.id_list.indexOf(id);
  if (index > -1) {
    form.id_list.splice(index, 1);
  }
};

// 获取元数据名称(用于显示)
const getMetaName = (id) => {
  // 根据ID获取元数据名称
  // 实现略...
  return `元数据-${id}`;
};

// 提交表单
const handleSubmit = async () => {
  try {
    await formRef.value.validate();
    
    loading.value = true;
    
    const response = await axios.post('/api/bd/compose', {
      name_zh: form.name_zh,
      name_en: form.name_en || undefined,
      describe: form.describe || undefined,
      id_list: form.id_list
    });
    
    if (response.data.code === 200) {
      ElMessage.success('业务领域创建成功');
      const newDomain = response.data.data.business_domain;
      console.log('新建业务领域:', newDomain);
      // 跳转到详情页或刷新列表
    } else {
      ElMessage.error(response.data.message || '创建失败');
    }
  } catch (error) {
    if (error.name !== 'Error') {
      // 非表单验证错误
      ElMessage.error('创建失败: ' + error.message);
    }
  } finally {
    loading.value = false;
  }
};
</script>

React 组件示例

import React, { useState } from 'react';
import axios from 'axios';

function ComposeBusinessDomain({ selectedMetaIds, onSuccess }) {
  const [form, setForm] = useState({
    name_zh: '',
    name_en: '',
    describe: ''
  });
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  const handleChange = (e) => {
    const { name, value } = e.target;
    setForm(prev => ({ ...prev, [name]: value }));
  };

  const handleSubmit = async (e) => {
    e.preventDefault();
    
    if (!form.name_zh.trim()) {
      setError('请输入中文名称');
      return;
    }
    
    if (!selectedMetaIds || selectedMetaIds.length === 0) {
      setError('请至少选择一个元数据');
      return;
    }

    setLoading(true);
    setError(null);

    try {
      const response = await axios.post('/api/bd/compose', {
        name_zh: form.name_zh,
        name_en: form.name_en || undefined,
        describe: form.describe || undefined,
        id_list: selectedMetaIds
      });

      if (response.data.code === 200) {
        onSuccess?.(response.data.data.business_domain);
      } else {
        setError(response.data.message || '创建失败');
      }
    } catch (err) {
      setError(err.response?.data?.message || err.message);
    } finally {
      setLoading(false);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <div className="form-group">
        <label>中文名称 *</label>
        <input
          type="text"
          name="name_zh"
          value={form.name_zh}
          onChange={handleChange}
          placeholder="请输入业务领域中文名称"
          required
        />
      </div>

      <div className="form-group">
        <label>英文名称</label>
        <input
          type="text"
          name="name_en"
          value={form.name_en}
          onChange={handleChange}
          placeholder="可选,不填则自动翻译"
        />
      </div>

      <div className="form-group">
        <label>描述</label>
        <textarea
          name="describe"
          value={form.describe}
          onChange={handleChange}
          rows={3}
        />
      </div>

      <div className="form-group">
        <label>已选元数据</label>
        <div className="selected-count">
          已选择 {selectedMetaIds?.length || 0} 个元数据
        </div>
      </div>

      {error && <div className="error-message">{error}</div>}

      <button type="submit" disabled={loading}>
        {loading ? '创建中...' : '创建业务领域'}
      </button>
    </form>
  );
}

export default ComposeBusinessDomain;

典型使用场景

场景一:从多个业务领域选取元数据

用户浏览多个现有业务领域,从中选取需要的元数据字段,组合成新的业务领域。

// 用户从订单域选取了 order_id, order_amount
// 从客户域选取了 customer_id, customer_name
// 组合创建 "订单客户分析域"

const selectedMetaIds = [
  101,  // order_id
  102,  // order_amount
  201,  // customer_id
  202   // customer_name
];

await composeBusinessDomain({
  name_zh: '订单客户分析域',
  describe: '用于分析订单与客户关联关系',
  id_list: selectedMetaIds,
  category: '分析域'
});

场景二:快速创建子域

从一个大的业务领域中选取部分元数据,创建更细粒度的子域。

// 从 "销售管理" 域中选取部分字段创建 "销售统计" 子域
await composeBusinessDomain({
  name_zh: '销售统计域',
  id_list: [301, 302, 303, 304],
  tag: [100],  // 关联 "核心业务" 标签
  data_source: 1  // 关联数据源
});

场景三:跨数据源整合

整合来自不同数据源的元数据,创建统一的业务视图。

await composeBusinessDomain({
  name_zh: '统一客户视图',
  describe: '整合CRM、ERP、电商系统的客户数据',
  id_list: [
    ...crmCustomerFieldIds,
    ...erpCustomerFieldIds,
    ...ecommerceCustomerFieldIds
  ],
  category: 'MDM',
  tag: [200]  // "主数据" 标签
});

错误处理

错误码说明

错误消息 原因 解决方案
请求数据不能为空 未发送请求体 检查请求是否包含 JSON body
name_zh 为必填项 未提供中文名称 添加 name_zh 参数
id_list 为必填项 未提供元数据列表 添加 id_list 参数
创建业务领域节点失败 Neo4j 数据库错误 联系后端排查

前端错误处理示例

async function handleComposeError(error, response) {
  // 网络错误
  if (!response) {
    showMessage('网络连接失败,请检查网络');
    return;
  }
  
  const { code, message, error: errorDetail } = response.data;
  
  switch (message) {
    case 'name_zh 为必填项':
      showMessage('请输入业务领域中文名称');
      focusField('name_zh');
      break;
      
    case 'id_list 为必填项':
      showMessage('请至少选择一个元数据');
      break;
      
    default:
      showMessage(`创建失败: ${message}`);
      console.error('详细错误:', errorDetail);
  }
}

最佳实践

1. 参数校验

在调用接口前进行前端校验,减少无效请求:

function validateComposeParams(params) {
  const errors = [];
  
  if (!params.name_zh?.trim()) {
    errors.push('中文名称不能为空');
  }
  
  if (!params.id_list || params.id_list.length === 0) {
    errors.push('请至少选择一个元数据');
  }
  
  if (params.name_zh && params.name_zh.length > 100) {
    errors.push('中文名称不能超过100个字符');
  }
  
  return errors;
}

2. 去重处理

确保 id_list 中没有重复的 ID:

const uniqueIds = [...new Set(selectedMetaIds)];

3. 用户体验优化

// 1. 添加加载状态
setLoading(true);

// 2. 成功后给予反馈
ElMessage.success({
  message: `业务领域"${result.name_zh}"创建成功`,
  duration: 3000
});

// 3. 提供快捷操作
showDialog({
  title: '创建成功',
  message: '是否立即查看新创建的业务领域?',
  confirmText: '查看详情',
  cancelText: '继续创建',
  onConfirm: () => router.push(`/bd/detail/${result.id}`)
});

4. 批量选择元数据

提供高效的元数据选择方式:

// 支持按业务领域批量选择
async function selectMetaFromDomain(domainId) {
  const metaList = await fetchDomainMeta(domainId);
  return metaList.map(meta => meta.id);
}

// 支持搜索过滤
async function searchAndSelectMeta(keyword) {
  const results = await searchMeta(keyword);
  // 显示选择器...
}

更新日志

版本 日期 更新内容
2.0.0 2025-01-09 简化 id_list 格式,支持纯ID数组;移除 domain_id 参数
1.0.0 2025-12-06 初始版本

相关接口


如有问题,请联系后端开发团队。