收藏夹文件夹功能 (2026-05-18)

变更概览

在现有收藏功能基础上新增文件夹分组能力。用户可以创建多个文件夹,将收藏按主题归类,同一收藏可属于多个文件夹。

核心概念:

  • 每个用户有一个默认文件夹 Default,注册时自动创建,不可删除、不可重命名
  • 文件夹支持混合类型(一个文件夹可包含 artist、artwork、service、product)
  • 单个文件夹收藏上限 1000
  • 文件夹名不需要多语言,最大 20 字符

接口变更

收藏操作

文件夹管理

文件夹内容查询

接口示例

收藏操作

POST /api/bookmark/save_artist

  • 功能说明:收藏/取消收藏 artist。
  • 变更说明:新增可选参数 folder_ids。收藏时若不传或为空数组,自动存入默认文件夹;取消收藏时自动清除所有文件夹关联。

请求参数

字段类型必填说明
artist_idnumberartist id
actionstringsave / unsave
folder_idsnumber[]目标文件夹 id 列表。为空时存入默认文件夹

请求示例

{
  "artist_id": 123,
  "action": "save",
  "folder_ids": [1, 3]
}

响应示例

{
  "status": "success",
  "message": "Save Artist Success",
  "code": 200
}

错误响应

无新增,沿用原有错误语义。


POST /api/bookmark/save_artwork

save_artist,参数字段为 artwork_id


POST /api/bookmark/save_service

save_artist,参数字段为 service_id


POST /api/bookmark/save_product

save_artist,参数字段为 product_id


POST /api/bookmark/sync_folders

  • 功能说明:同步收藏到指定文件夹。以传入的 folder_ids 为最终状态覆盖:不在列表中的文件夹会被移除,新加入的文件夹会添加。传空数组表示从所有文件夹移除。
  • 变更说明:新增接口。单个文件夹收藏上限 1000。

请求参数

字段类型必填说明
typestringartist / artwork / service / product
artist_idnumbertype=artist 时必填artist id
artwork_idnumbertype=artwork 时必填artwork id
service_idnumbertype=service 时必填service id
product_idnumbertype=product 时必填product id
folder_idsnumber[]目标文件夹 id 列表。为空数组或不传时表示从所有文件夹移除

请求示例

{
  "type": "artwork",
  "artwork_id": 456,
  "folder_ids": [1, 3, 5]
}

响应示例

{
  "status": "success",
  "message": "Sync Folders Success",
  "code": 200
}

错误响应

400:文件夹不存在或不属于当前用户

{
  "code": 80001,
  "message": "Folder not found"
}

400:目标文件夹已满 1000

{
  "code": 80005,
  "message": "Folder item limit reached (max 1000)"
}

POST /api/bookmark/remove_from_folder

  • 功能说明:从指定文件夹移除收藏。移除后若该收藏不在任何文件夹中,自动取消收藏(扣减计数器)。
  • 变更说明:新增接口。适用于用户在已收藏状态下再次点击,直接从当前文件夹移除,无需弹窗。

请求参数

字段类型必填说明
typestringartist / artwork / service / product
artist_idnumbertype=artist 时必填artist id
artwork_idnumbertype=artwork 时必填artwork id
service_idnumbertype=service 时必填service id
product_idnumbertype=product 时必填product id
folder_idnumber要移除的文件夹 id

请求示例

{
  "type": "artwork",
  "artwork_id": 456,
  "folder_id": 5
}

响应示例

{
  "status": "success",
  "message": "Remove From Folder Success",
  "code": 200
}

错误响应

无新增。


文件夹管理

POST /api/bookmark/create_folder

  • 功能说明:创建收藏文件夹。
  • 变更说明:新增接口。

请求参数

字段类型必填说明
namestring文件夹名称,最大 20 字符

请求示例

{
  "name": "日系风格"
}

响应示例

{
  "status": "success",
  "message": "Create Folder Success",
  "code": 200,
  "data": {
    "id": 5,
    "user_id": 100,
    "name": "日系风格",
    "is_default": false,
    "is_public": true,
    "sort_order": 0,
    "created_at": "2026-05-18T12:00:00.000000Z",
    "updated_at": "2026-05-18T12:00:00.000000Z"
  }
}

错误响应

400:文件夹名超过 20 字符

{
  "code": 80004,
  "message": "Folder name cannot exceed 20 characters"
}

POST /api/bookmark/update_folder

  • 功能说明:重命名收藏文件夹。
  • 变更说明:新增接口。默认文件夹不可重命名。

请求参数

字段类型必填说明
folder_idnumber文件夹 id
namestring新名称,最大 20 字符

请求示例

{
  "folder_id": 5,
  "name": "插画收藏"
}

响应示例

{
  "status": "success",
  "message": "Update Folder Success",
  "code": 200,
  "data": {
    "id": 5,
    "user_id": 100,
    "name": "插画收藏",
    "is_default": false,
    "is_public": true,
    "sort_order": 0,
    "created_at": "2026-05-18T12:00:00.000000Z",
    "updated_at": "2026-05-18T12:05:00.000000Z"
  }
}

错误响应

400:文件夹不存在

{
  "code": 80001,
  "message": "Folder not found"
}

400:尝试重命名默认文件夹

{
  "code": 80003,
  "message": "Cannot rename default folder"
}

400:名称超过 20 字符

{
  "code": 80004,
  "message": "Folder name cannot exceed 20 characters"
}

POST /api/bookmark/delete_folder

  • 功能说明:删除收藏文件夹。
  • 变更说明:新增接口。默认文件夹不可删除。

请求参数

字段类型必填说明
folder_idnumber文件夹 id

请求示例

{
  "folder_id": 5
}

响应示例

{
  "status": "success",
  "message": "Delete Folder Success",
  "code": 200
}

错误响应

400:文件夹不存在

{
  "code": 80001,
  "message": "Folder not found"
}

400:尝试删除默认文件夹

{
  "code": 80002,
  "message": "Cannot delete default folder"
}

GET /api/bookmark/folder_list

  • 功能说明:获取用户所有收藏文件夹列表,含每个文件夹的收藏数量。
  • 变更说明:新增接口。

请求参数

响应示例

{
  "status": "success",
  "message": "Get Folders Success",
  "code": 200,
  "data": [
    {
      "id": 1,
      "user_id": 100,
      "name": "Default",
      "is_default": true,
      "is_public": true,
      "sort_order": 0,
      "items_count": 25,
      "created_at": "2026-01-01T00:00:00.000000Z",
      "updated_at": "2026-01-01T00:00:00.000000Z"
    },
    {
      "id": 5,
      "user_id": 100,
      "name": "日系风格",
      "is_default": false,
      "is_public": true,
      "sort_order": 0,
      "items_count": 8,
      "created_at": "2026-05-18T12:00:00.000000Z",
      "updated_at": "2026-05-18T12:00:00.000000Z"
    }
  ]
}

错误响应

无新增。


文件夹内容查询

GET /api/bookmark/folder_items

  • 功能说明:获取指定文件夹的收藏内容,支持按类型筛选和分页。
  • 变更说明:新增接口。

请求参数

字段类型必填说明
folder_idnumber文件夹 id
typestring筛选类型:artist / artwork / service / product
pagenumber页码,默认 1
sizenumber每页数量,默认 15,最大 50

请求示例

GET /api/bookmark/folder_items?folder_id=5&type=artwork&page=1&size=15

响应示例

{
  "status": "success",
  "message": "Get Folder Items Success",
  "code": 200,
  "data": [
    {
      "id": 100,
      "user_save_folder_id": 5,
      "user_savable_id": 456,
      "user_savable_type": "App\\Models\\Artwork",
      "savable": {
        "id": 456,
        "name": "Sample Artwork"
      },
      "created_at": "2026-05-18T12:10:00.000000Z",
      "updated_at": "2026-05-18T12:10:00.000000Z"
    }
  ],
  "total": 1
}

错误响应

400:文件夹不存在

{
  "code": 80001,
  "message": "Folder not found"
}

GET /api/bookmark/item_folders

  • 功能说明:查询某个收藏所在的文件夹 ID 列表。用于收藏弹窗中预选已关联的文件夹。
  • 变更说明:新增接口。

请求参数

字段类型必填说明
typestringartist / artwork / service / product
artist_idnumbertype=artist 时必填artist id
artwork_idnumbertype=artwork 时必填artwork id
service_idnumbertype=service 时必填service id
product_idnumbertype=product 时必填product id

请求示例

GET /api/bookmark/item_folders?type=artwork&artwork_id=456

响应示例

{
  "status": "success",
  "message": "Get Item Folders Success",
  "code": 200,
  "data": [1, 5]
}

说明:data 为该收藏所在的文件夹 id 数组。

错误响应

无新增。


错误码汇总

错误码场景
80001文件夹不存在或不属于当前用户
80002尝试删除默认文件夹
80003尝试重命名默认文件夹
80004文件夹名超过 20 字符
80005文件夹收藏数已满 1000

接入指引

场景 1:快速收藏/取消收藏(不弹窗)

适用于列表页的心形按钮。

收藏:点击后直接收藏到默认文件夹。

POST /api/bookmark/save_artwork
{
  "artwork_id": 456,
  "action": "save"
}

不传 folder_ids,自动存入默认文件夹。

取消收藏:已收藏状态下再次点击,直接从默认文件夹移除。

POST /api/bookmark/remove_from_folder
{
  "type": "artwork",
  "artwork_id": 456,
  "folder_id": 1
}

前端可通过 item_folders 接口获取当前收藏所在的文件夹 id,或使用 is_saved 字段判断状态。

场景 2:收藏弹窗(选择文件夹)

适用于详情页的收藏按钮,点击后弹出文件夹选择弹窗。

步骤 1:打开弹窗时并行请求两个接口

GET /api/bookmark/folder_list          → 获取所有文件夹(含 items_count)
GET /api/bookmark/item_folders?type=artwork&artwork_id=456  → 获取该收藏已在哪些文件夹

步骤 2:渲染弹窗

  • 列出所有文件夹,checkbox 多选
  • item_folders 返回的 id 数组对应的 checkbox 设为选中状态
  • 底部显示"新建文件夹"输入框(调用 create_folder

步骤 3:用户点击保存

POST /api/bookmark/sync_folders
{
  "type": "artwork",
  "artwork_id": 456,
  "folder_ids": [1, 3, 5]
}
  • folder_ids 为用户最终勾选的文件夹 id 列表
  • 传空数组 [] 表示从所有文件夹移除(但不影响收藏状态)

场景 3:用户后台管理收藏

适用于用户中心的收藏管理页。

左侧文件夹列表

GET /api/bookmark/folder_list

默认文件夹 is_default: true,前端可据此隐藏编辑/删除按钮。

右侧文件夹内容

GET /api/bookmark/folder_items?folder_id=5&type=artwork&page=1&size=15

支持按 type 筛选,支持分页。

编辑单个收藏的文件夹归属

点击某个收藏的"编辑"按钮,弹出与场景 2 相同的弹窗,调用 sync_folders 保存。

注意事项

  1. save_{type}folder_ids 参数是可选的。不传时行为与旧版完全兼容(存入默认文件夹)。
  2. sync_folders 只管理文件夹归属,不影响收藏状态。要取消收藏仍需调用 save_{type}unsave
  3. 取消收藏(unsave)会自动清除该收藏在所有文件夹中的记录。
  4. 默认文件夹不可删除、不可重命名,前端应根据 is_default 字段控制 UI。