推荐系统接口文档
概述
推荐系统基于多维度因素计算推荐分数,支持管理后台调控。
一、作品推荐 (Artwork)
权重配置
| 因素 | 权重 |
|---|
| 上传时间 | 0.2 |
| 画师粉丝数 | 0.1 |
| 最近7天申请数 | 0.2 |
| 点赞数 | 0.2 |
| 人工因子 | 0.3 |
内容 API
获取作品列表(推荐排序)
POST /api/content/artwork/list
请求参数:
| 参数名 | 类型 | 必填 | 说明 |
|---|
| order_by | string | 否 | recommend/newest/recent_hot,默认 newest |
| category_ids | array | 否 | 分类 ID 数组 |
| art_style_ids | array | 否 | 艺术风格 ID 数组 |
| page | integer | 否 | 页码,默认 1 |
| per_page | integer | 否 | 每页数量,默认 20 |
| seed | string | 否 | 随机种子(仅 recommend 模式) |
响应:
{
"data": [...],
"current_page": 1,
"total": 150,
"seed": "abc123xyz"
}
管理员 API
需要管理员权限
更新作品人工因子
POST /api/admin_center/artwork_recommend/update_manual_factor
| 参数名 | 类型 | 必填 | 说明 |
|---|
| artwork_id | integer | 是 | 作品 ID |
| manual_factor | number | 是 | 人工因子 [-1, 1] |
响应:
{
"message": "更新成功",
"data": {
"id": 1,
"artwork_id": 123,
"manual_factor": 0.5,
"artist_followers": 500,
"likes_count": 100,
"recent_requests_7d": 5,
"time_score": 0.18,
"followers_score": 0.08,
"requests_score": 0.15,
"likes_score": 0.12,
"manual_score": 0.15,
"created_at": "2025-12-20T10:00:00.000000Z",
"updated_at": "2025-12-26T14:30:00.000000Z"
}
}
批量更新人工因子
POST /api/admin_center/artwork_recommend/batch_update_manual_factor
| 参数名 | 类型 | 必填 | 说明 |
|---|
| updates | array | 是 | [{artwork_id, manual_factor}, ...] |
响应:
{
"message": "批量更新成功,共更新 3 个作品",
"updated": 3
}
获取推荐统计列表
POST /api/admin_center/artwork_recommend/stats
| 参数名 | 类型 | 必填 | 说明 |
|---|
| page | integer | 否 | 页码,默认 1 |
| per_page | integer | 否 | 每页数量,默认 20,最大 100 |
| order_by | string | 否 | recommend_score/manual_factor,默认 recommend_score |
| order_direction | string | 否 | desc/asc,默认 desc |
响应:
{
"data": [
{
"id": 123,
"title": "作品标题",
"recommend_score": 680000,
"artist": {
"id": 1,
"name": "画师名称",
"cname": "artist_cname"
},
"recommend_stat": {
"id": 1,
"artwork_id": 123,
"manual_factor": 0.5,
"artist_followers": 500,
"likes_count": 100,
"recent_requests_7d": 5,
"time_score": 0.18,
"followers_score": 0.08,
"requests_score": 0.15,
"likes_score": 0.12,
"manual_score": 0.15,
"created_at": "2025-12-20T10:00:00.000000Z",
"updated_at": "2025-12-26T14:30:00.000000Z"
}
}
],
"current_page": 1,
"total": 150
}
获取单个作品推荐统计
POST /api/admin_center/artwork_recommend/stat
| 参数名 | 类型 | 必填 | 说明 |
|---|
| artwork_id | integer | 是 | 作品 ID |
响应:
{
"data": {
"id": 1,
"artwork_id": 123,
"manual_factor": 0.5,
"artist_followers": 500,
"likes_count": 100,
"recent_requests_7d": 5,
"time_score": 0.18,
"followers_score": 0.08,
"requests_score": 0.15,
"likes_score": 0.12,
"manual_score": 0.15,
"recommend_score": 680000,
"created_at": "2025-12-20T10:00:00.000000Z",
"updated_at": "2025-12-26T14:30:00.000000Z"
}
}
字段说明:
| 字段 | 类型 | 说明 |
|---|
| id | integer | 统计记录 ID |
| artwork_id | integer | 作品 ID |
| manual_factor | float | 人工因子,范围 [-1, 1],权重 0.3 |
| artist_followers | integer | 画师粉丝数 |
| likes_count | integer | 作品点赞数 |
| recent_requests_7d | integer | 最近 7 天申请数 |
| time_score | float | 上传时间归一化分数,权重 0.2 |
| followers_score | float | 画师粉丝数归一化分数,权重 0.1 |
| requests_score | float | 申请数归一化分数,权重 0.2 |
| likes_score | float | 点赞数归一化分数,权重 0.2 |
| manual_score | float | 人工因子计算后的分数(manual_factor × 0.3) |
| recommend_score | integer | 推荐分数(从关联的 artwork 获取) |
| created_at | datetime | 创建时间 |
| updated_at | datetime | 更新时间 |
分数计算公式:
recommend_score = (time_score × 0.2 + followers_score × 0.1 + requests_score × 0.2 + likes_score × 0.2 + manual_score × 0.3) × 1000000
触发重新计算推荐分数
POST /api/admin_center/artwork_recommend/trigger_calculate
| 参数名 | 类型 | 必填 | 说明 |
|---|
| artwork_id | integer | 否 | 作品 ID,不传则计算全部 |
响应(单个):
{
"message": "推荐分数计算完成",
"artwork_id": 123
}
响应(全部):
{
"message": "所有作品的推荐分数计算已触发,请稍后查看结果"
}
清除推荐缓存
POST /api/admin_center/artwork_recommend/clear_cache
无参数
响应:
{
"message": "缓存清除成功",
"deleted_keys": 5
}
二、画师推荐 (Artist)
权重配置
| 因素 | 权重 |
|---|
| 粉丝数 | 0.3 |
| 最近30天接到申请数 | 0.2 |
| 人工因子 | 0.5 |
内容 API
获取画师列表(推荐排序)
POST /api/content/artist/list
请求参数:
| 参数名 | 类型 | 必填 | 说明 |
|---|
| order_by | string | 否 | recommend/newest/recent_hot,默认 newest |
| category_ids | array | 否 | 分类 ID 数组 |
| art_style_ids | array | 否 | 艺术风格 ID 数组 |
| is_open | boolean | 否 | 是否开放接单 |
| keyword | string | 否 | 搜索关键词 |
| page | integer | 否 | 页码,默认 1 |
| per_page | integer | 否 | 每页数量,默认 5 |
| seed | string | 否 | 随机种子(仅 recommend 模式) |
响应:
{
"data": [
{
"id": 1,
"name": "画师名称",
"followers": 500,
"artworks": [...],
"avatar": {...}
}
],
"current_page": 1,
"total": 100,
"seed": "abc123xyz"
}
管理员 API
需要管理员权限
更新画师人工因子
POST /api/admin_center/artist_recommend/update_manual_factor
| 参数名 | 类型 | 必填 | 说明 |
|---|
| artist_id | integer | 是 | 画师 ID |
| manual_factor | number | 是 | 人工因子 [-1, 1] |
响应:
{
"message": "人工因子更新成功",
"data": {
"id": 1,
"artist_id": 123,
"manual_factor": 0.5,
"followers": 500,
"recent_requests_30d": 10,
"followers_score": 0.15,
"requests_score": 0.08,
"manual_score": 0.25,
"created_at": "2025-12-20T10:00:00.000000Z",
"updated_at": "2025-12-26T14:30:00.000000Z"
}
}
批量更新人工因子
POST /api/admin_center/artist_recommend/batch_update_manual_factor
| 参数名 | 类型 | 必填 | 说明 |
|---|
| updates | array | 是 | [{artist_id, manual_factor}, ...] |
响应:
{
"message": "批量更新成功",
"updated": 3
}
获取推荐统计列表
POST /api/admin_center/artist_recommend/stats
| 参数名 | 类型 | 必填 | 说明 |
|---|
| page | integer | 否 | 页码,默认 1 |
| per_page | integer | 否 | 每页数量,默认 20,最大 100 |
| order_by | string | 否 | recommend_score/manual_factor,默认 recommend_score |
| order_direction | string | 否 | desc/asc,默认 desc |
响应:
{
"data": [
{
"id": 1,
"name": "画师名称",
"cname": "artist_cname",
"followers": 500,
"recommend_score": 580000,
"recommend_stat": {
"id": 1,
"artist_id": 1,
"manual_factor": 0.5,
"followers": 500,
"recent_requests_30d": 10,
"followers_score": 0.15,
"requests_score": 0.08,
"manual_score": 0.25,
"created_at": "2025-12-20T10:00:00.000000Z",
"updated_at": "2025-12-26T14:30:00.000000Z"
}
}
],
"current_page": 1,
"total": 100
}
获取单个画师推荐统计
POST /api/admin_center/artist_recommend/stat
| 参数名 | 类型 | 必填 | 说明 |
|---|
| artist_id | integer | 是 | 画师 ID |
响应:
{
"data": {
"id": 1,
"artist_id": 123,
"manual_factor": 0.5,
"followers": 500,
"recent_requests_30d": 10,
"followers_score": 0.15,
"requests_score": 0.08,
"manual_score": 0.25,
"recommend_score": 580000,
"created_at": "2025-12-20T10:00:00.000000Z",
"updated_at": "2025-12-26T14:30:00.000000Z"
}
}
字段说明:
| 字段 | 类型 | 说明 |
|---|
| id | integer | 统计记录 ID |
| artist_id | integer | 画师 ID |
| manual_factor | float | 人工因子,范围 [-1, 1],权重 0.5 |
| followers | integer | 画师粉丝数 |
| recent_requests_30d | integer | 最近 30 天接到的申请数 |
| followers_score | float | 粉丝数归一化分数,权重 0.3 |
| requests_score | float | 申请数归一化分数,权重 0.2 |
| manual_score | float | 人工因子计算后的分数(manual_factor × 0.5) |
| recommend_score | integer | 推荐分数(从关联的 artist 获取) |
| created_at | datetime | 创建时间 |
| updated_at | datetime | 更新时间 |
分数计算公式:
recommend_score = (followers_score × 0.3 + requests_score × 0.2 + manual_score × 0.5) × 1000000
触发重新计算推荐分数
POST /api/admin_center/artist_recommend/trigger_calculate
| 参数名 | 类型 | 必填 | 说明 |
|---|
| artist_id | integer | 否 | 画师 ID,不传则计算全部 |
响应(单个):
{
"message": "推荐分数计算完成",
"artist_id": 123
}
响应(全部):
{
"message": "所有画师的推荐分数计算已触发"
}
清除推荐缓存
POST /api/admin_center/artist_recommend/clear_cache
无参数
响应:
{
"message": "缓存清除成功",
"deleted_keys": 2
}
三、服务推荐 (Service)
权重配置
| 因素 | 权重 |
|---|
| 艺术家粉丝数 | 0.2 |
| 服务收藏数 | 0.3 |
| 最近7天订单数 | 0.6 |
| 人工因子 | 0.3 |
内容 API
获取服务列表(推荐排序)
GET /api/content/services
请求参数:
| 参数名 | 类型 | 必填 | 说明 |
|---|
| order_by | string | 否 | recommend/newest/recent_hot,默认 newest |
| category_ids | array | 否 | 分类 ID 数组 |
| art_style_ids | array | 否 | 艺术风格 ID 数组 |
| is_open | boolean | 否 | 是否开放接单 |
| page | integer | 否 | 页码,默认 1 |
| per_page | integer | 否 | 每页数量,默认 20 |
| seed | string | 否 | 随机种子(仅 recommend 模式) |
响应:
{
"data": [
{
"id": 123,
"name": {"zh": "头像定制", "en": "Avatar Commission"},
"recommend_score": 850432,
"artist": {...},
"showcase": [...]
}
],
"current_page": 1,
"total": 500,
"seed": "abc123xyz"
}
说明: 推荐模式下,前 99 名会根据 seed 进行随机打乱,确保不同用户看到不同排序,同时保持分页稳定性。
管理员 API
需要管理员权限
更新服务人工因子
POST /api/admin_center/service_recommend/update_manual_factor
| 参数名 | 类型 | 必填 | 说明 |
|---|
| service_id | integer | 是 | 服务 ID |
| manual_factor | number | 是 | 人工因子 [-1, 1] |
响应:
{
"message": "更新成功",
"data": {
"id": 1,
"service_id": 123,
"manual_factor": 0.5,
"artist_fans": 500,
"bookmark_count": 100,
"recent_orders_7d": 5,
"fans_score": 0.12,
"bookmarks_score": 0.18,
"orders_score": 0.36,
"manual_score": 0.15,
"penalty_score": 0,
"recommend_score": 680000,
"exposure_position": 0,
"today_position": 15,
"created_at": "2025-12-20T10:00:00.000000Z",
"updated_at": "2025-12-26T14:30:00.000000Z"
}
}
批量更新人工因子
POST /api/admin_center/service_recommend/batch_update_manual_factor
| 参数名 | 类型 | 必填 | 说明 |
|---|
| updates | array | 是 | [{service_id, manual_factor}, ...] |
响应:
{
"message": "批量更新成功,共更新 3 个服务",
"updated": 3
}
获取推荐统计列表
POST /api/admin_center/service_recommend/stats
| 参数名 | 类型 | 必填 | 说明 |
|---|
| page | integer | 否 | 页码,默认 1 |
| per_page | integer | 否 | 每页数量,默认 20,最大 100 |
| order_by | string | 否 | recommend_score/manual_factor/exposure_position,默认 recommend_score |
| order_direction | string | 否 | desc/asc,默认 desc |
响应:
{
"data": [
{
"id": 123,
"name": {"zh": "头像定制", "en": "Avatar Commission"},
"recommend_score": 680000,
"artist": {
"id": 1,
"name": "画师名称",
"cname": "artist_cname"
},
"recommend_stat": {
"id": 1,
"service_id": 123,
"manual_factor": 0.5,
"artist_fans": 500,
"bookmark_count": 100,
"recent_orders_7d": 5,
"fans_score": 0.12,
"bookmarks_score": 0.18,
"orders_score": 0.36,
"manual_score": 0.15,
"penalty_score": 0,
"exposure_position": 0,
"today_position": 15,
"created_at": "2025-12-20T10:00:00.000000Z",
"updated_at": "2025-12-26T14:30:00.000000Z"
}
}
],
"current_page": 1,
"total": 150
}
获取单个服务推荐统计
POST /api/admin_center/service_recommend/stat
| 参数名 | 类型 | 必填 | 说明 |
|---|
| service_id | integer | 是 | 服务 ID |
响应:
{
"data": {
"id": 1,
"service_id": 123,
"manual_factor": 0.5,
"artist_fans": 500,
"bookmark_count": 100,
"recent_orders_7d": 5,
"fans_score": 0.12,
"bookmarks_score": 0.18,
"orders_score": 0.36,
"manual_score": 0.15,
"penalty_score": 0,
"recommend_score": 680000,
"exposure_position": 0,
"today_position": 15,
"created_at": "2025-12-20T10:00:00.000000Z",
"updated_at": "2025-12-26T14:30:00.000000Z"
}
}
字段说明:
| 字段 | 类型 | 说明 |
|---|
| id | integer | 统计记录 ID |
| service_id | integer | 服务 ID |
| manual_factor | float | 人工因子,范围 [-1, 1],权重 0.3 |
| artist_fans | integer | 艺术家粉丝数 |
| bookmark_count | integer | 服务收藏数 |
| recent_orders_7d | integer | 最近 7 天订单数 |
| fans_score | float | 粉丝数归一化分数,权重 0.2 |
| bookmarks_score | float | 收藏数归一化分数,权重 0.3 |
| orders_score | float | 订单数归一化分数,权重 0.6 |
| manual_score | float | 人工因子计算后的分数(manual_factor × 0.3) |
| penalty_score | float | 曝光惩罚分数(当前已禁用) |
| recommend_score | integer | 推荐分数(从关联的 service 获取) |
| exposure_position | integer | 前一天曝光位置(Top 1000 排名) |
| today_position | integer | 当天排序位置 |
| created_at | datetime | 创建时间 |
| updated_at | datetime | 更新时间 |
分数计算公式:
recommend_score = (fans_score × 0.2 + bookmarks_score × 0.3 + orders_score × 0.6 + manual_score × 0.3) × 1000000
触发重新计算推荐分数
POST /api/admin_center/service_recommend/trigger_calculate
| 参数名 | 类型 | 必填 | 说明 |
|---|
| service_id | integer | 否 | 服务 ID,不传则计算全部 |
响应(单个):
{
"message": "推荐分数计算完成",
"service_id": 123
}
响应(全部):
{
"message": "所有服务的推荐分数计算已触发,请稍后查看结果"
}
清除推荐缓存
POST /api/admin_center/service_recommend/clear_cache
无参数
响应:
{
"message": "缓存清除成功",
"deleted_keys": 5
}
四、产品推荐 (Product)
权重配置
| 因素 | 权重 |
|---|
| 艺术家粉丝数 | 0.2 |
| 产品收藏数 | 0.3 |
| 最近7天销量 | 0.6 |
| 人工因子 | 0.3 |
内容 API
获取产品列表(推荐排序)
GET /api/content/product/list
请求参数:
| 参数名 | 类型 | 必填 | 说明 |
|---|
| order_by | string | 否 | recommend/newest/recent_hot,默认 newest |
| category_ids | array | 否 | 分类 ID 数组 |
| artist_cname | string | 否 | 画师 cname |
| price_currency_id | integer | 否 | 货币 ID |
| price_from | number | 否 | 最低价格 |
| price_to | number | 否 | 最高价格 |
| stock_type | string | 否 | 库存类型 |
| page | integer | 否 | 页码,默认 1 |
| size | integer | 否 | 每页数量,默认 20 |
| seed | string | 否 | 随机种子(仅 recommend 模式) |
响应:
{
"data": [
{
"id": 123,
"name": "产品名称",
"recommend_score": 1500000,
"artist": {
"name": "画师名称",
"rating_score": 4.8
},
"lowest_price_option": {...}
}
],
"current_page": 1,
"total": 500,
"seed": "abc123xyz"
}
说明: 推荐模式下,前 99 名会根据 seed 进行随机打乱,确保不同用户看到不同排序,同时保持分页稳定性。
管理员 API
需要管理员权限
更新产品人工因子
POST /api/admin_center/product_recommend/update_manual_factor
| 参数名 | 类型 | 必填 | 说明 |
|---|
| product_id | integer | 是 | 产品 ID |
| manual_factor | number | 是 | 人工因子 [-1, 1] |
响应:
{
"message": "更新成功",
"data": {
"id": 1,
"product_id": 123,
"manual_factor": 0.5,
"artist_fans": 500,
"bookmark_count": 100,
"recent_sales_7d": 10,
"fans_score": 0.12,
"bookmarks_score": 0.18,
"sales_score": 0.42,
"manual_score": 0.15,
"recommend_score": 870000,
"created_at": "2025-12-20T10:00:00.000000Z",
"updated_at": "2025-12-26T14:30:00.000000Z"
}
}
批量更新人工因子
POST /api/admin_center/product_recommend/batch_update_manual_factor
| 参数名 | 类型 | 必填 | 说明 |
|---|
| updates | array | 是 | [{product_id, manual_factor}, ...] |
响应:
{
"message": "批量更新成功,共更新 3 个产品",
"updated": 3
}
获取推荐统计列表
POST /api/admin_center/product_recommend/stats
| 参数名 | 类型 | 必填 | 说明 |
|---|
| page | integer | 否 | 页码,默认 1 |
| per_page | integer | 否 | 每页数量,默认 20,最大 100 |
| order_direction | string | 否 | desc/asc,默认 desc |
响应:
{
"data": [
{
"id": 123,
"name": "产品名称",
"recommend_score": 870000,
"artist": {
"id": 1,
"name": "画师名称",
"cname": "artist_cname"
},
"recommend_stat": {
"id": 1,
"product_id": 123,
"manual_factor": 0.5,
"artist_fans": 500,
"bookmark_count": 100,
"recent_sales_7d": 10,
"fans_score": 0.12,
"bookmarks_score": 0.18,
"sales_score": 0.42,
"manual_score": 0.15,
"created_at": "2025-12-20T10:00:00.000000Z",
"updated_at": "2025-12-26T14:30:00.000000Z"
}
}
],
"current_page": 1,
"total": 150
}
获取单个产品推荐统计
POST /api/admin_center/product_recommend/stat
| 参数名 | 类型 | 必填 | 说明 |
|---|
| product_id | integer | 是 | 产品 ID |
响应:
{
"data": {
"id": 1,
"product_id": 123,
"manual_factor": 0.5,
"artist_fans": 500,
"bookmark_count": 100,
"recent_sales_7d": 10,
"fans_score": 0.12,
"bookmarks_score": 0.18,
"sales_score": 0.42,
"manual_score": 0.15,
"recommend_score": 870000,
"created_at": "2025-12-20T10:00:00.000000Z",
"updated_at": "2025-12-26T14:30:00.000000Z"
}
}
字段说明:
| 字段 | 类型 | 说明 |
|---|
| id | integer | 统计记录 ID |
| product_id | integer | 产品 ID |
| manual_factor | float | 人工因子,范围 [-1, 1],权重 0.3 |
| artist_fans | integer | 艺术家粉丝数 |
| bookmark_count | integer | 产品收藏数 |
| recent_sales_7d | integer | 最近 7 天销量 |
| fans_score | float | 粉丝数归一化分数,权重 0.2 |
| bookmarks_score | float | 收藏数归一化分数,权重 0.3 |
| sales_score | float | 销量归一化分数,权重 0.6 |
| manual_score | float | 人工因子计算后的分数(manual_factor × 0.3) |
| recommend_score | integer | 推荐分数(从关联的 product 获取) |
| created_at | datetime | 创建时间 |
| updated_at | datetime | 更新时间 |
分数计算公式:
recommend_score = (fans_score × 0.2 + bookmarks_score × 0.3 + sales_score × 0.6 + manual_score × 0.3) × 1000000
触发重新计算推荐分数
POST /api/admin_center/product_recommend/trigger_calculate
| 参数名 | 类型 | 必填 | 说明 |
|---|
| product_id | integer | 否 | 产品 ID,不传则计算全部 |
响应(单个):
{
"message": "推荐分数计算完成",
"product_id": 123
}
响应(全部):
{
"message": "所有产品的推荐分数计算已触发,请稍后查看结果"
}
清除推荐缓存
POST /api/admin_center/product_recommend/clear_cache
无参数
响应:
{
"message": "缓存清除成功",
"deleted_keys": 5
}
定时任务
# 作品推荐分数
php artisan pipipen:calculate-artwork-recommend-score
php artisan pipipen:calculate-artwork-recommend-score --artwork_id=123
# 画师推荐分数
php artisan pipipen:calculate-artist-recommend-score
php artisan pipipen:calculate-artist-recommend-score --artist_id=123
# 服务推荐分数
php artisan pipipen:calculate-service-recommend-score
php artisan pipipen:calculate-service-recommend-score --service_id=123
# 产品推荐分数
php artisan pipipen:calculate-product-recommend-score
php artisan pipipen:calculate-product-recommend-score --product_id=123