flnxi-Wu/docs/api/template-system-api.md
WuYongJie 473176997a docs: 完成API文档编写(任务26)
创建完整的API文档:
- 模板管理API(5个接口)
  * 获取模板列表
  * 获取模板详情(含使用统计)
  * 创建模板(含验证规则)
  * 更新模板(含版本控制)
  * 删除模板(含使用检查)

- 模板验证API
  * 内置模板验证逻辑
  * 自定义模板验证逻辑
  * 内置模板列表

- 字段池管理API(2个接口)
  * 获取字段池列表
  * 同步字段池

- 分类字段管理API
  * 获取分类管理字段

- 错误代码规范
  * 统一错误响应格式
  * 常见错误代码说明

- 性能指标
  * 响应时间目标
  * 数据库优化说明(20+个索引)

- 最佳实践
  * 版本控制使用方法
  * 错误处理示例
  * 字段验证示例
  * 性能优化建议

文档位置:docs/api/template-system-api.md
2025-12-13 15:42:39 +08:00

12 KiB
Raw Blame History

自定义上传模板系统 API 文档

概述

本文档描述了自定义上传模板系统的所有API接口,包括模板管理、字段管理、字段池管理等功能。

基础信息

  • Base URL: /api
  • 认证方式: Session Cookie
  • 内容类型: application/json
  • 字符编码: UTF-8

错误代码

所有API遵循统一的错误响应格式:

{
  "error": "错误信息",
  "errorCode": "ERROR_CODE",
  "details": {
    // 详细错误信息(可选)
  }
}

常见错误代码

错误代码 HTTP状态码 说明
VALIDATION_ERROR 400 请求参数验证失败
UNAUTHORIZED 401 未授权访问
FORBIDDEN 403 权限不足
NOT_FOUND 404 资源不存在
CONFLICT 409 资源冲突(如版本冲突)
INTERNAL_ERROR 500 服务器内部错误

模板管理 API

1. 获取模板列表

获取所有自定义上传模板列表。

请求

GET /api/admin/upload-templates

响应

[
  {
    "id": "uuid",
    "name": "3DMAX 素材模板",
    "description": "适用于 3D 模型类素材",
    "status": "active",
    "materialType": "3DMAX",
    "materialKind": "IMAGE",
    "version": 1,
    "fieldGroups": null,
    "displayConfig": null,
    "createdAt": "2024-01-01T00:00:00Z",
    "updatedAt": "2024-01-01T00:00:00Z",
    "fields": [
      {
        "id": "uuid",
        "key": "productModel",
        "label": "SPU型号",
        "type": "text",
        "required": true,
        "orderIndex": 0,
        "layoutWidth": "full",
        "validations": null,
        "optionsStatic": null,
        "allowedExtensions": null,
        "visibleOnHomeFilter": false,
        "isSearchable": true,
        "isReadOnly": false,
        "addToCategory": false,
        "conditions": null
      }
    ]
  }
]

字段说明

  • status: 模板状态 - draft(草稿)、active(启用)、archived(归档)
  • materialKind: 素材大类 - IMAGE、VIDEO、OTHER
  • fields: 模板字段数组,按 orderIndex 排序

2. 获取单个模板详情

获取指定模板的详细信息,包括使用统计。

请求

GET /api/admin/upload-templates/:id

响应

{
  "id": "uuid",
  "name": "3DMAX 素材模板",
  "description": "适用于 3D 模型类素材",
  "status": "active",
  "materialType": "3DMAX",
  "materialKind": "IMAGE",
  "version": 1,
  "fieldGroups": null,
  "displayConfig": null,
  "createdAt": "2024-01-01T00:00:00Z",
  "updatedAt": "2024-01-01T00:00:00Z",
  "fields": [...],
  "materialCount": 150,
  "materials": [
    {
      "id": "uuid",
      "previewUrl": "https://...",
      "productModel": "ABC-123"
    }
  ],
  "fieldStats": [
    {
      "key": "productModel",
      "label": "SPU型号",
      "filledCount": 150,
      "fillRate": 100,
      "isLowFillRate": false
    }
  ]
}

字段说明

  • materialCount: 使用该模板的素材数量
  • materials: 使用该模板的素材列表(最多10个预览)
  • fieldStats: 字段填写率统计
    • fillRate: 填写率百分比(0-100)
    • isLowFillRate: 是否为低填写率字段(<30%)

3. 创建模板

创建新的自定义上传模板。

请求

POST /api/admin/upload-templates
Content-Type: application/json

{
  "name": "新模板",
  "description": "模板描述",
  "status": "draft",
  "materialType": "3DMAX",
  "materialKind": "IMAGE",
  "fieldGroups": null,
  "displayConfig": null,
  "fields": [
    {
      "key": "productModel",
      "label": "SPU型号",
      "type": "text",
      "required": true,
      "orderIndex": 0,
      "layoutWidth": "full",
      "validations": null,
      "optionsStatic": null,
      "allowedExtensions": null,
      "visibleOnHomeFilter": false,
      "isSearchable": true,
      "isReadOnly": false,
      "addToCategory": false,
      "conditions": null
    }
  ]
}

验证规则

  • name: 必填,不能为空
  • materialType: 必填,有效值:3DMAX、PSD、AI 工作流、视频、模特、其他
  • materialKind: 必填,有效值:IMAGE、VIDEO、OTHER
  • fields: 必填,至少包含一个字段
  • fields[].key: 必填,只能包含字母、数字、下划线,必须以字母开头,长度不超过50
  • fields[].key: 在同一模板内必须唯一
  • fields[].type: 必填,有效值:text、textarea、number、select、checkbox、radio、date、uppercase

响应

{
  "id": "uuid",
  "name": "新模板",
  "version": 1,
  ...
}

错误响应示例

{
  "error": "字段键名重复:字段 2 已使用键名 productModel",
  "errorCode": "VALIDATION_ERROR"
}

4. 更新模板

更新现有模板,支持版本控制。

请求

PUT /api/admin/upload-templates/:id
Content-Type: application/json

{
  "name": "更新后的模板名称",
  "description": "更新后的描述",
  "status": "active",
  "materialType": "3DMAX",
  "materialKind": "IMAGE",
  "version": 1,
  "fieldGroups": null,
  "displayConfig": null,
  "fields": [...]
}

版本控制

  • 请求必须包含 version 字段
  • 如果服务器上的版本号与请求中的版本号不匹配,返回 409 冲突错误
  • 更新成功后,版本号自动递增

响应

{
  "id": "uuid",
  "name": "更新后的模板名称",
  "version": 2,
  ...
}

版本冲突错误

{
  "error": "模板版本冲突,请刷新后重试",
  "errorCode": "VERSION_CONFLICT",
  "details": {
    "clientVersion": 1,
    "serverVersion": 2,
    "lastUpdated": "2024-01-01T00:00:00Z"
  }
}

5. 删除模板

删除指定模板。如果模板正在被使用,会返回警告信息。

请求

DELETE /api/admin/upload-templates/:id

响应

{
  "success": true,
  "message": "模板已删除"
}

使用中的模板错误

{
  "error": "该模板正在被 150 个素材使用,无法删除",
  "errorCode": "TEMPLATE_IN_USE",
  "details": {
    "materialCount": 150
  }
}

模板验证 API

验证模板ID

验证模板ID是否有效(内置模板或自定义模板)。

内部使用

此功能在素材上传API中自动调用,不需要单独调用。

验证逻辑

  1. 如果 templateId 以 builtin- 开头,验证是否为有效的内置模板
  2. 否则,从数据库查询验证模板是否存在
  3. 如果 templateId 为空或 null,允许通过(向后兼容)

内置模板列表

  • builtin-3dmax-material: 3DMAX 素材模板
  • builtin-psd-material: PSD 素材模板
  • builtin-ai-material: AI 工作流模板
  • builtin-video-material: 视频素材模板
  • builtin-model-material: 模特素材模板
  • builtin-other-material: 其他素材模板

字段池管理 API

1. 获取字段池列表

获取所有字段定义及其选项。

请求

GET /api/field-pool

响应

[
  {
    "id": "uuid",
    "key": "categoryName",
    "label": "使用店铺",
    "type": "select",
    "description": "素材使用的店铺分类",
    "source": "custom",
    "sourceTemplateIds": ["uuid1", "uuid2"],
    "isStandard": false,
    "isFilterEnabled": true,
    "filterDisplayName": "店铺",
    "filterOrder": 1,
    "createdAt": "2024-01-01T00:00:00Z",
    "updatedAt": "2024-01-01T00:00:00Z",
    "options": [
      {
        "id": "uuid",
        "value": "默认店铺",
        "label": "默认店铺",
        "orderIndex": 0
      }
    ]
  }
]

字段说明

  • source: 字段来源 - standard(标准字段)、custom(自定义字段)
  • isFilterEnabled: 是否启用为筛选字段
  • filterDisplayName: 筛选时显示的名称(优先于 label)
  • filterOrder: 筛选字段的排序顺序

2. 同步字段池

从模板同步字段到字段池(管理员操作)。

请求

POST /api/admin/field-pool/sync

响应

{
  "success": true,
  "syncedFields": 5,
  "syncedOptions": 25,
  "message": "字段池同步成功"
}

分类字段管理 API

获取分类管理字段

获取启用了分类管理的字段列表。

请求

GET /api/category-fields

响应

{
  "managedFields": [
    "categoryName",
    "sceneName",
    "renderer",
    "brandName",
    "seriesName",
    "materialTexture"
  ]
}

性能指标

响应时间目标

API 目标响应时间 说明
获取模板列表 < 200ms 已添加数据库索引优化
获取模板详情 < 300ms 包含统计信息
创建模板 < 500ms 包含字段验证和同步
更新模板 < 500ms 包含版本检查和同步
删除模板 < 200ms 包含使用检查
字段池同步 < 2s 批量操作,支持重试

数据库优化

已添加以下索引以优化查询性能:

UploadTemplate 表

  • status - 按状态筛选
  • materialType - 按素材类型筛选
  • materialKind - 按素材大类筛选
  • createdAt / updatedAt - 按时间排序

UploadField 表

  • templateId - 查询模板字段
  • key - 按字段键名查询
  • type - 按字段类型筛选
  • visibleOnHomeFilter - 查询首页筛选字段
  • isSearchable - 查询可搜索字段
  • addToCategory - 查询分类管理字段
  • templateId, orderIndex - 复合索引优化排序

FieldDefinition 表

  • source - 按来源筛选
  • isStandard - 查询标准字段
  • isFilterEnabled - 查询启用的筛选字段
  • isFilterEnabled, filterOrder - 复合索引优化筛选查询

FieldOption 表

  • fieldId - 查询字段选项
  • fieldId, orderIndex - 复合索引优化选项排序

最佳实践

1. 版本控制

更新模板时始终包含版本号,避免并发冲突:

// 获取模板
const template = await fetch(`/api/admin/upload-templates/${id}`)
const data = await template.json()

// 更新时包含版本号
await fetch(`/api/admin/upload-templates/${id}`, {
  method: 'PUT',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    ...data,
    name: '新名称',
    version: data.version // 必须包含
  })
})

2. 错误处理

始终处理API错误并向用户显示友好的错误信息:

try {
  const response = await fetch('/api/admin/upload-templates', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(templateData)
  })
  
  if (!response.ok) {
    const error = await response.json()
    // 显示错误信息
    showError(error.error || '操作失败')
    return
  }
  
  const result = await response.json()
  // 处理成功结果
} catch (error) {
  // 处理网络错误
  showError('网络错误,请重试')
}

3. 字段验证

创建或更新模板前,在前端进行字段验证:

// 验证字段key格式
const keyPattern = /^[a-zA-Z][a-zA-Z0-9_]*$/
if (!keyPattern.test(field.key)) {
  showError('字段键名必须以字母开头,只能包含字母、数字和下划线')
  return
}

// 验证字段key唯一性
const keys = fields.map(f => f.key)
const duplicates = keys.filter((key, index) => keys.indexOf(key) !== index)
if (duplicates.length > 0) {
  showError(`字段键名重复:${duplicates[0]}`)
  return
}

4. 性能优化

使用SWR或类似的缓存库减少不必要的API请求:

import useSWR from 'swr'

function TemplateList() {
  const { data, error, mutate } = useSWR(
    '/api/admin/upload-templates',
    fetcher,
    {
      revalidateOnFocus: false,
      dedupingInterval: 5000
    }
  )
  
  // 使用缓存的数据
  return <div>{/* 渲染模板列表 */}</div>
}

更新日志

2024-12-13

  • 添加数据库索引优化查询性能
  • 添加模板使用统计API
  • 添加字段填写率统计
  • 优化错误响应格式
  • 添加版本控制支持

2024-12-12

  • 初始版本
  • 实现模板CRUD API
  • 实现字段池管理API
  • 实现模板验证功能