创建完整的API文档: - 模板管理API(5个接口) * 获取模板列表 * 获取模板详情(含使用统计) * 创建模板(含验证规则) * 更新模板(含版本控制) * 删除模板(含使用检查) - 模板验证API * 内置模板验证逻辑 * 自定义模板验证逻辑 * 内置模板列表 - 字段池管理API(2个接口) * 获取字段池列表 * 同步字段池 - 分类字段管理API * 获取分类管理字段 - 错误代码规范 * 统一错误响应格式 * 常见错误代码说明 - 性能指标 * 响应时间目标 * 数据库优化说明(20+个索引) - 最佳实践 * 版本控制使用方法 * 错误处理示例 * 字段验证示例 * 性能优化建议 文档位置:docs/api/template-system-api.md
12 KiB
12 KiB
自定义上传模板系统 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、OTHERfields: 模板字段数组,按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、OTHERfields: 必填,至少包含一个字段fields[].key: 必填,只能包含字母、数字、下划线,必须以字母开头,长度不超过50fields[].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中自动调用,不需要单独调用。
验证逻辑
- 如果
templateId以builtin-开头,验证是否为有效的内置模板 - 否则,从数据库查询验证模板是否存在
- 如果
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
- 实现模板验证功能