{ "openapi": "3.0.3", "info": { "title": "FloorVisualizer API", "description": "FloorVisualizer 后端接口文档\n\n## 全局响应格式\n所有 API 统一返回 JSON 信封格式:\n```\n成功: {\"code\": 200, \"data\": {...}}\n失败: {\"code\": 400, \"error\": \"错误描述\"}\n```\n\n认证方式:注册/登录获取 JWT token,在需要认证的接口中设置 Header: Authorization: Bearer {token}\n\n---\n## 产品筛选层层递进说明\n产品列表支持 category / material / color_tone / finish / wood_species / brand / series_name 多维度组合筛选。\n前端实现层层递进:用户每选一个筛选项,将已选参数传给 /products 获取结果,再根据返回的 filter_options 动态更新其他筛选项的可选范围。\n\n---\n## AI换地板对接说明\n1. GET /floor/options 获取可用的地板样式(从产品库动态加载,每个样式对应真实SKU)\n2. POST /floor/generate 上传图片 + floor_id(产品SKU)+ pattern_code(1-9)+ room_code(0-7)→ 返回 job_id\n3. GET /floor/progress?job_id=xxx(SSE)跟踪进度 → check → mask → inpaint → done\n4. 生成完成后保存到用户项目:POST /user/projects\n\n---\n## 数字编码对照\n\n### 铺设方式 (pattern_code)\n| code | 木地板 | 瓷砖 |\n|------|--------|------|\n| 1 | Straight Lay | — |\n| 2 | Horizontal Lay | — |\n| 3 | Herringbone | — |\n| 4 | Chevron | — |\n| 5 | — | Straight Grid |\n| 6 | — | Running Bond |\n| 7 | — | 1/3 Offset |\n| 8 | — | Hexagonal |\n| 9 | — | Diagonal (45°) |\n\n### 房间类型 (room_code)\n| code | 房间 |\n|------|------|\n| 0 | Auto Detect(不传房间信息给AI) |\n| 1 | Living Room |\n| 2 | Bedroom |\n| 3 | Kitchen |\n| 4 | Dining Room |\n| 5 | Bathroom |\n| 6 | Study Room |\n| 7 | Hallway |\n\n---\n## 静态文件路径\n- 上传图片: /static/images/\n- 知识图片: /knowledge_images/ 或 /images/knowledge/\n- 生成结果: /outputs/\n- 用户上传: /uploads/", "version": "1.0.0" }, "servers": [ { "url": "http://localhost:8099", "description": "本地开发环境" } ], "components": { "securitySchemes": { "BearerAuth": { "type": "http", "scheme": "bearer", "bearerFormat": "JWT", "description": "注册或登录后获取的 JWT token" } }, "schemas": { "AuthResponse": { "type": "object", "properties": { "token": { "type": "string", "description": "JWT token,后续请求放 Authorization header" }, "user": { "$ref": "#/components/schemas/User" } }, "example": { "username": "demo", "password": "123456", "name": "Demo User" } }, "User": { "type": "object", "properties": { "id": { "type": "string", "description": "用户唯一ID (UUID)" }, "username": { "type": "string", "description": "用户名" }, "name": { "type": "string", "description": "显示名称" }, "avatar_url": { "type": "string", "description": "头像URL" }, "created_at": { "type": "string", "format": "date-time", "description": "注册时间" }, "updated_at": { "type": "string", "format": "date-time", "description": "更新时间" } } }, "Favorite": { "type": "object", "properties": { "id": { "type": "integer", "description": "收藏记录ID" }, "user_id": { "type": "string", "description": "用户ID" }, "sku": { "type": "string", "description": "产品SKU编码" }, "brand": { "type": "string", "description": "品牌" }, "series_name": { "type": "string", "description": "系列名称" }, "style_name": { "type": "string", "description": "花色/款式名称" }, "main_image_url": { "type": "string", "description": "产品主图URL" }, "category": { "type": "string", "description": "分类" }, "material": { "type": "string", "description": "材质" }, "color_tone": { "type": "string", "description": "色调" }, "price_per_sqft": { "type": "number", "description": "每平方英尺价格" }, "created_at": { "type": "string", "format": "date-time", "description": "收藏时间" } } }, "Project": { "type": "object", "properties": { "id": { "type": "string", "description": "项目唯一ID (UUID)" }, "user_id": { "type": "string", "description": "用户ID" }, "name": { "type": "string", "description": "项目名称" }, "original_image_url": { "type": "string", "description": "换地板前的原图URL" }, "generated_image_url": { "type": "string", "description": "AI生成后的效果图URL" }, "floor_style": { "type": "string", "description": "使用的款式(如 Light Oak)" }, "pattern": { "type": "string", "description": "铺设方式(如 Herringbone, Straight Lay)" }, "room_type": { "type": "string", "description": "房间类型(如 Living Room)" }, "created_at": { "type": "string", "format": "date-time", "description": "创建时间" }, "updated_at": { "type": "string", "format": "date-time", "description": "更新时间" } } }, "ProductItem": { "type": "object", "properties": { "brand": { "type": "string", "description": "品牌" }, "series_name": { "type": "string", "description": "系列名称" }, "style_name": { "type": "string", "description": "花色/款式名称" }, "sku": { "type": "string", "description": "产品SKU编码" }, "category": { "type": "string", "description": "分类(Hardwood / Laminate / SPC/LVP / Engineered Wood / Wood-Look Tile)" }, "material": { "type": "string", "description": "材质(如 Oak, Porcelain, Walnut)" }, "color_tone": { "type": "string", "description": "色调(如 Light Gray, Natural Oak, Dark Brown)" }, "finish": { "type": "string", "description": "表面处理(如 Matte, Gloss, Textured)" }, "price_per_sqft": { "type": "number", "description": "每平方英尺价格(美元)" }, "price_tier": { "type": "string", "description": "价格段位(Budget/Value, Mid-Range, Upper Mid-Range, Premium)" }, "main_image_url": { "type": "string", "description": "产品主图URL" }, "size_label": { "type": "string", "description": "Size label" }, "coverage_sqft_per_box": { "type": "number", "description": "Coverage per box (sqft)" }, "is_favorited": { "type": "boolean", "description": "当前用户是否已收藏。未登录时始终为 false" }, "spec_count": { "type": "integer", "description": "该花色的规格数量(同品牌同花色的SKU数,含自身)。>1 表示有多种尺寸可选" }, "is_official_price": { "type": "boolean", "description": "是否为官方定价。true=品牌官网标价,false=市场估价或未找到" } } }, "ProductListResponse": { "type": "object", "properties": { "products": { "type": "array", "items": { "$ref": "#/components/schemas/ProductItem" }, "description": "产品列表" }, "total": { "type": "integer", "description": "总数" }, "page": { "type": "integer", "description": "当前页码" }, "limit": { "type": "integer", "description": "每页数量" }, "total_pages": { "type": "integer", "description": "总页数" }, "filter_options": { "type": "object", "properties": { "categories": { "type": "array", "items": { "type": "string" }, "description": "所有分类" }, "series_names": { "type": "array", "items": { "type": "string" }, "description": "所有系列" }, "brands": { "type": "array", "items": { "$ref": "#/components/schemas/BrandInfo" }, "description": "所有品牌(含logo、款式数、类型数)" } } } } }, "RecommendResponse": { "type": "object", "properties": { "source": { "": "#/components/schemas/ProductDetail", "description": "源产品信息" }, "products": { "type": "array", "items": { "": "#/components/schemas/ProductItem" }, "description": "推荐产品列表" }, "scores": { "type": "array", "items": { "type": "string" }, "description": "匹配度(如 90%)" }, "total": { "type": "integer", "description": "推荐总数" } } }, "ProductDetail": { "type": "object", "properties": { "brand": { "type": "string" }, "group_name": { "type": "string" }, "sku": { "type": "string" }, "series_name": { "type": "string" }, "style_name": { "type": "string" }, "category": { "type": "string" }, "material": { "type": "string" }, "color_tone": { "type": "string" }, "finish": { "type": "string" }, "price_per_sqft": { "type": "number" }, "price_tier": { "type": "string" }, "price_source": { "type": "string" }, "main_image_url": { "type": "string" }, "room_image_url": { "type": "string" }, "source_url": { "type": "string" }, "description": { "type": "string" }, "status": { "type": "string" }, "coverage_sqft_per_box": { "type": "number", "description": "Coverage per box (sqft)" }, "wood_species": { "type": "string", "description": "Wood species" }, "size_label": { "type": "string", "description": "Size label (e.g. 6 x 48 in)" }, "width_in": { "type": "number", "description": "Width (inches)" }, "length_in": { "type": "number", "description": "Length (inches)" }, "variants": { "type": "array", "description": "同款不同尺寸的完整产品数据。仅当同品牌同花色的其他SKU存在时返回(旧格式,建议使用 specs)", "items": { "$ref": "#/components/schemas/ProductVariant" } }, "specs": { "type": "array", "description": "规格列表:该花色的所有尺寸+价格。包含主产品自身(至少1条)。多规格时前端可展示尺寸选择器", "items": { "$ref": "#/components/schemas/ProductSpec" } }, "is_favorited": { "type": "boolean", "description": "当前用户是否已收藏。未登录时始终为 false" }, "is_official_price": { "type": "boolean", "description": "是否为官方定价。true=品牌官网标价,false=市场估价或未找到" } } }, "ProductSpec": { "type": "object", "description": "单个规格(尺寸+价格)", "properties": { "sku": { "type": "string", "description": "该规格对应的SKU" }, "size_label": { "type": "string", "description": "尺寸标签,如 6 x 48 in" }, "width_in": { "type": "number", "description": "宽度(英寸)" }, "length_in": { "type": "number", "description": "长度(英寸)" }, "price_per_sqft": { "type": "number", "description": "每平方英尺价格(美元)" }, "price_tier": { "type": "string", "description": "价格段位" }, "coverage_sqft_per_box": { "type": "number", "description": "每箱覆盖面积(平方英尺)" }, "main_image_url": { "type": "string", "description": "该规格产品图片URL" } } }, "ProductVariant": { "type": "object", "description": "Product variant (same style, different size/price)", "properties": { "sku": { "type": "string" }, "size_label": { "type": "string" }, "width_in": { "type": "number" }, "length_in": { "type": "number" }, "price_per_sqft": { "type": "number" }, "price_tier": { "type": "string" }, "series_name": { "type": "string" }, "main_image_url": { "type": "string" } } }, "FilterHierarchy": { "type": "object", "properties": { "filters": { "type": "array", "items": { "$ref": "#/components/schemas/FilterGroup" } } } }, "FilterGroup": { "type": "object", "properties": { "key": { "type": "string", "description": "Filter parameter name (used with /products)" }, "label": { "type": "string", "description": "Display label" }, "options": { "type": "array", "items": { "type": "string" }, "description": "Available values (flat structure)" }, "groups": { "type": "array", "items": { "$ref": "#/components/schemas/FilterGroup" }, "description": "Sub-groups (hierarchical, e.g. Material > Wood/Porcelain/Vinyl)" } } }, "BrandInfo": { "type": "object", "description": "品牌信息(含统计和logo)", "properties": { "name": { "type": "string", "description": "品牌名称" }, "logo_url": { "type": "string", "description": "品牌 logo 图片 URL(存在 static/brand_logos/ 下),可能为空" }, "style_count": { "type": "integer", "description": "该品牌下的款式数量(distinct style_name)" }, "collection_count": { "type": "integer", "description": "该品牌下的产品合集数量(distinct category)" } }, "example": { "name": "Shaw Floors", "logo_url": "/static/brand_logos/shaw_floors.webp", "style_count": 1797, "collection_count": 4 } }, "Article": { "type": "object", "properties": { "id": { "type": "integer" }, "title": { "type": "string" }, "summary": { "type": "string" }, "content": { "type": "string", "description": "Full article text" }, "cover_url": { "type": "string", "description": "Cover image URL" }, "image_urls": { "type": "array", "items": { "type": "string" }, "description": "Article images" }, "created_at": { "type": "string", "format": "date-time" } } }, "ArticleListResponse": { "type": "object", "properties": { "articles": { "type": "array", "items": { "$ref": "#/components/schemas/Article" } }, "total": { "type": "integer" }, "page": { "type": "integer" }, "limit": { "type": "integer" }, "total_pages": { "type": "integer" } } }, "ArticleRecommendResponse": { "type": "object", "properties": { "articles": { "type": "array", "items": { "$ref": "#/components/schemas/Article" } }, "total": { "type": "integer" } } }, "FloorStyleOption": { "type": "object", "description": "Floor style loaded from product database. Each entry = one unique style (dedup by brand+style_name). Variants list different sizes.", "properties": { "id": { "type": "string", "description": "Product SKU(用于 floor_id 参数)" }, "sku": { "type": "string", "description": "Product SKU(同 id,兼容旧版)" }, "name": { "type": "string", "description": "Style name (花色名称)" }, "material": { "type": "string", "description": "Material (材质,如 Oak/Porcelain/Luxury Vinyl)" }, "color_tone": { "type": "string", "description": "Color tone (色调,如 Light Gray/Natural Oak/Dark Brown)" }, "finish": { "type": "string", "description": "Finish (表面处理,如 Matte/Gloss/Textured)" }, "size_label": { "type": "string", "description": "Size label, e.g. 6 x 48 in. 多尺寸时为首个尺寸" }, "width_in": { "type": "number", "description": "Width in inches. Used in AI prompt for physical scale" }, "length_in": { "type": "number", "description": "Length in inches. Used in AI prompt for physical scale" }, "image_url": { "type": "string", "description": "Preview image URL" }, "category": { "type": "string", "description": "Product category (Solid Hardwood / Engineered Hardwood / Tile/Stone / SPC-LVP / Laminate)" }, "description": { "type": "string", "description": "Product description. Used in AI prompt for richer visual detail" }, "variants": { "type": "array", "description": "Size variants of the same style (same brand+style_name, different SKU/size). Empty array if only one size.", "items": { "type": "object", "properties": { "sku": { "type": "string", "description": "Variant SKU" }, "size_label": { "type": "string", "description": "Variant size label" }, "width_in": { "type": "number" }, "length_in": { "type": "number" } } } } } }, "FloorOptionsResponse": { "type": "object", "properties": { "wood_floors": { "type": "array", "items": { "$ref": "#/components/schemas/FloorStyleOption" }, "description": "Wood products (Oak/Ash/Hickory/Maple etc.) — classified by material field" }, "tile_floors": { "type": "array", "items": { "$ref": "#/components/schemas/FloorStyleOption" }, "description": "Tile/Stone (Porcelain/Stone Look/Glass) + Laminate products" }, "vinyl_floors": { "type": "array", "items": { "$ref": "#/components/schemas/FloorStyleOption" }, "description": "Vinyl products (Luxury Vinyl/Rigid Core)" }, "wood_patterns": { "type": "array", "items": { "$ref": "#/components/schemas/PatternOption" } }, "tile_patterns": { "type": "array", "items": { "$ref": "#/components/schemas/PatternOption" } }, "rooms": { "type": "array", "items": { "$ref": "#/components/schemas/RoomOption" } } } }, "PatternOption": { "type": "object", "description": "铺设方式选项。code 1-4 为木地板,5-9 为瓷砖", "properties": { "code": { "type": "integer", "description": "铺设方式编码(1-9),见文档顶部数字编码对照表" }, "name": { "type": "string", "description": "铺设方式名称" }, "pattern": { "type": "string", "description": "AI提示词用的铺设描述" }, "category": { "type": "string", "description": "所属类型:wood 或 tile" } }, "example": { "code": 3, "name": "Herringbone", "pattern": "herringbone/zigzag pattern with rectangular planks arranged in a broken V shape", "category": "wood" } }, "RoomOption": { "type": "object", "description": "房间类型选项。code 0 为自动检测", "properties": { "code": { "type": "integer", "description": "房间编码(0-7),见文档顶部数字编码对照表" }, "name": { "type": "string", "description": "房间名称" } }, "example": { "code": 1, "name": "Living Room" } }, "CalcInput": { "type": "object", "required": [ "floor_type", "rooms", "piece_length", "piece_width" ], "properties": { "floor_type": { "type": "string", "enum": [ "wood", "tile" ], "description": "地板类型" }, "rooms": { "type": "array", "description": "房间列表,至少一个", "items": { "type": "object", "required": [ "length", "width" ], "properties": { "name": { "type": "string", "description": "房间名称,如 Living Room" }, "length": { "type": "number", "description": "长(米),如 5" }, "width": { "type": "number", "description": "宽(米),如 4" }, "deductions": { "type": "array", "description": "扣减区域,如柜子、壁炉等不铺地板的区域", "items": { "type": "object", "properties": { "name": { "type": "string", "description": "区域名称,如 Fireplace / Kitchen Island" }, "shape": { "type": "string", "enum": [ "rectangle", "circle", "custom" ], "description": "形状类型:rectangle=矩形(填length+width) / circle=圆形(填radius直径) / custom=自定义(填area)" }, "length": { "type": "number", "description": "长(米),仅 rectangle 矩形时填写" }, "width": { "type": "number", "description": "宽(米),仅 rectangle 矩形时填写" }, "radius": { "type": "number", "description": "半径(米),仅 circle 圆形时填写,直径=radius*2" }, "area": { "type": "number", "description": "面积(平方米),仅 custom 自定义时填写" } } } } } } }, "pattern_index": { "type": "integer", "default": 0, "description": "铺设方式索引(0-5)" }, "piece_length": { "type": "number", "description": "单片长度(米),必填,如 1.2" }, "piece_width": { "type": "number", "description": "单片宽度(米),必填,如 0.19" }, "pieces_per_box": { "type": "integer", "description": "每箱片数,选填,如 8" }, "price_per_sqm": { "type": "number", "description": "每平方米单价,选填,如 45" }, "joint_width": { "type": "number", "description": "缝宽(米),瓷砖用,如 0.002" } }, "example": { "floor_type": "wood", "rooms": [ { "name": "Living Room", "length": 5, "width": 4, "deductions": [ { "name": "Fireplace", "shape": "rectangle", "length": 1.5, "width": 0.8 } ] }, { "name": "Hallway", "length": 3, "width": 1.2, "deductions": [] } ], "pattern_index": 0, "piece_length": 1.2, "piece_width": 0.19, "pieces_per_box": 8, "price_per_sqm": 45 } }, "CalcRoomInput": { "type": "object", "properties": { "name": { "type": "string", "description": "房间名称" }, "length": { "type": "number", "description": "长(米)" }, "width": { "type": "number", "description": "宽(米)" }, "deductions": { "type": "array", "items": { "": "#/components/schemas/CalcDeduction" }, "description": "扣减区域(柜子/壁炉等不铺地板的区域)" } } }, "CalcDeduction": { "type": "object", "properties": { "name": { "type": "string" }, "shape": { "type": "string", "enum": [ "rectangle", "circle", "custom" ], "description": "形状" }, "length": { "type": "number", "description": "长(rectangle时用)" }, "width": { "type": "number", "description": "宽(rectangle时用)" }, "radius": { "type": "number", "description": "半径(circle时用)" }, "area": { "type": "number", "description": "自定义面积(custom时用)" } } }, "CalcResult": { "type": "object", "properties": { "floor_type": { "type": "string" }, "rooms": { "type": "array", "items": { "": "#/components/schemas/CalcRoomResult" } }, "total_room_area": { "type": "number", "description": "房间总面积" }, "total_deduct": { "type": "number", "description": "总扣减面积" }, "total_net_area": { "type": "number", "description": "总净面积(需铺地板)" }, "waste_rate": { "type": "number", "description": "损耗率(%)" }, "waste_area": { "type": "number", "description": "损耗面积" }, "total_area": { "type": "number", "description": "含损耗总面积" }, "pieces_needed": { "type": "integer", "description": "需要片数" }, "boxes_needed": { "type": "number", "description": "需要箱数(仅传入pieces_per_box时返回)" }, "joint_width": { "type": "number" }, "grout_kg": { "type": "number", "description": "填缝剂重量kg(仅瓷砖模式返回)" }, "grout_bags": { "type": "integer", "description": "填缝剂袋数(仅瓷砖模式返回)" }, "price_per_sqm": { "type": "number" }, "total_price": { "type": "number", "description": "总价(仅传入price_per_sqm时返回)" }, "pattern_name": { "type": "string" }, "piece_length": { "type": "number" }, "piece_width": { "type": "number" } } }, "CalcRoomResult": { "type": "object", "properties": { "name": { "type": "string" }, "length": { "type": "number" }, "width": { "type": "number" }, "area": { "type": "number" }, "deductions": { "type": "array", "items": { "": "#/components/schemas/CalcDeduction" } }, "deduction_total": { "type": "number" }, "net_area": { "type": "number" } } }, "FrequentBrand": { "type": "object", "description": "用户常用品牌", "properties": { "brand": { "type": "string", "description": "品牌名称" }, "view_count": { "type": "integer", "description": "浏览次数" }, "fav_count": { "type": "integer", "description": "收藏次数" }, "logo_url": { "type": "string", "description": "品牌logo URL" }, "style_count": { "type": "integer", "description": "该品牌款式总数" } } } } }, "paths": { "/auth/register": { "post": { "tags": [ "认证" ], "summary": "用户注册", "description": "使用用户名和密码注册新账号,返回 JWT token 和用户信息", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "username", "password" ], "properties": { "username": { "type": "string", "description": "用户名" }, "password": { "type": "string", "description": "密码" }, "name": { "type": "string", "description": "显示名称(选填)" } } } } } }, "responses": { "201": { "description": "注册成功", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AuthResponse" } } } }, "400": { "description": "参数错误(用户名或密码为空/用户名已存在)" } } } }, "/auth/login": { "post": { "tags": [ "认证" ], "summary": "用户登录", "description": "用户名+密码登录,返回 JWT token 和用户信息", "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "username", "password" ], "properties": { "username": { "type": "string", "description": "用户名" }, "password": { "type": "string", "description": "密码" } } } } } }, "responses": { "200": { "description": "登录成功", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AuthResponse" } } } }, "401": { "description": "用户名或密码错误" } } } }, "/user/me": { "get": { "tags": [ "用户" ], "summary": "获取个人信息", "security": [ { "BearerAuth": [] } ], "responses": { "200": { "description": "用户信息", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/User" } } } }, "401": { "description": "未登录或token过期" } } }, "put": { "tags": [ "用户" ], "summary": "更新个人信息", "security": [ { "BearerAuth": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "name": { "type": "string", "description": "显示名称" }, "avatar_url": { "type": "string", "description": "头像URL" } } } } } }, "responses": { "200": { "description": "更新成功", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/User" } } } } } } }, "/user/favorites": { "get": { "tags": [ "收藏" ], "summary": "获取收藏列表", "security": [ { "BearerAuth": [] } ], "responses": { "200": { "description": "收藏列表", "content": { "application/json": { "schema": { "type": "object", "properties": { "favorites": { "type": "array", "items": { "$ref": "#/components/schemas/Favorite" } }, "total": { "type": "integer" } } } } } } } }, "post": { "tags": [ "收藏" ], "summary": "添加收藏", "security": [ { "BearerAuth": [] } ], "responses": { "201": { "description": "收藏成功" } }, "description": "传入产品SKU,后端自动查库补全产品信息", "parameters": [ { "name": "sku", "in": "query", "required": true, "schema": { "type": "string" }, "description": "产品SKU编码" } ] } }, "/user/favorites/{sku}": { "delete": { "tags": [ "收藏" ], "summary": "取消收藏", "security": [ { "BearerAuth": [] } ], "parameters": [ { "name": "sku", "in": "path", "required": true, "schema": { "type": "string" }, "description": "产品SKU编码" } ], "responses": { "200": { "description": "取消成功" } } } }, "/user/projects": { "get": { "tags": [ "项目" ], "summary": "获取项目列表", "description": "获取当前用户的所有AI换地板项目记录", "security": [ { "BearerAuth": [] } ], "responses": { "200": { "description": "项目列表", "content": { "application/json": { "schema": { "type": "object", "properties": { "projects": { "type": "array", "items": { "$ref": "#/components/schemas/Project" } }, "total": { "type": "integer" } } } } } } } }, "post": { "tags": [ "项目" ], "summary": "创建项目", "description": "保存一次AI换地板记录", "security": [ { "BearerAuth": [] } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "properties": { "name": { "type": "string", "description": "项目名称,默认 Untitled", "default": "Untitled" }, "original_image_url": { "type": "string", "description": "换地板前原图URL" }, "generated_image_url": { "type": "string", "description": "AI生成效果图URL" }, "floor_style": { "type": "string", "description": "使用的款式" }, "pattern": { "type": "string", "description": "铺设方式" }, "room_type": { "type": "string", "description": "房间类型" } } } } } }, "responses": { "201": { "description": "创建成功", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Project" } } } } } } }, "/user/projects/{id}": { "get": { "tags": [ "项目" ], "summary": "获取单个项目", "security": [ { "BearerAuth": [] } ], "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "项目UUID" } ], "responses": { "200": { "description": "项目详情", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Project" } } } }, "404": { "description": "项目不存在" } } }, "put": { "tags": [ "项目" ], "summary": "重命名项目", "security": [ { "BearerAuth": [] } ], "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "项目UUID" } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "name" ], "properties": { "name": { "type": "string", "description": "新名称" } } } } } }, "responses": { "200": { "description": "更新成功", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Project" } } } } } }, "delete": { "tags": [ "项目" ], "summary": "删除项目", "security": [ { "BearerAuth": [] } ], "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "项目UUID" } ], "responses": { "200": { "description": "删除成功" } } } }, "/products": { "get": { "tags": [ "产品" ], "summary": "产品列表(多维度筛选+搜索+分页)", "parameters": [ { "name": "category", "in": "query", "schema": { "type": "string" }, "description": "类目:Hardwood / Engineered Wood / Laminate / SPC/LVP / Wood-Look Tile" }, { "name": "material", "in": "query", "schema": { "type": "string" }, "description": "材质:Oak / Porcelain / Luxury Vinyl / Maple / Hickory 等" }, { "name": "color_tone", "in": "query", "schema": { "type": "string" }, "description": "色调:Light Gray / Natural Oak / Dark Brown / Taupe 等" }, { "name": "finish", "in": "query", "schema": { "type": "string" }, "description": "表面处理:Matte / Gloss / Textured / Wire-Brushed 等" }, { "name": "wood_species", "in": "query", "schema": { "type": "string" }, "description": "木种:Oak / Maple / Hickory / Walnut / Birch 等" }, { "name": "brand", "in": "query", "schema": { "type": "string" }, "description": "品牌筛选" }, { "name": "series_name", "in": "query", "schema": { "type": "string" }, "description": "系列名称筛选" }, { "name": "search", "in": "query", "schema": { "type": "string" }, "description": "模糊搜索(匹配款式名称/编号/品牌)" }, { "name": "page", "in": "query", "schema": { "type": "integer", "default": 1 }, "description": "页码" }, { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 20 }, "description": "每页数量" } ], "responses": { "200": { "description": "产品列表", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProductListResponse" } } } } }, "description": "所有筛选参数可任意组合。\n\n前端层层递进实现方式:用户每选择一个筛选项,将已选参数传给本接口,根据返回结果中的 filter_options 动态收窄其他筛选项的可选范围。" } }, "/product-options": { "get": { "tags": [ "产品" ], "summary": "筛选选项(扁平结构)", "description": "返回分类/系列/品牌列表。品牌包含名称、logo、款式数、类型数。", "responses": { "200": { "description": "筛选项", "content": { "application/json": { "schema": { "type": "object", "properties": { "code": { "type": "integer", "example": 200 }, "data": { "type": "object", "properties": { "categories": { "type": "array", "items": { "type": "string" }, "description": "分类列表" }, "series_names": { "type": "array", "items": { "type": "string" }, "description": "系列名称列表" }, "brands": { "type": "array", "items": { "$ref": "#/components/schemas/BrandInfo" }, "description": "品牌列表(含统计和logo)" } } } } }, "example": { "code": 200, "data": { "categories": [ "Hardwood", "Laminate", "SPC/LVP", "Engineered Wood", "Wood-Look Tile" ], "series_names": [ "American Retreat", "Nature's Splendor", "Timeless Design" ], "brands": [ { "name": "Shaw Floors", "logo_url": "/static/brand_logos/shaw_floors.webp", "style_count": 1797, "collection_count": 4 }, { "name": "Bruce", "logo_url": "/static/brand_logos/bruce.jpg", "style_count": 224, "collection_count": 4 }, { "name": "Karndean", "logo_url": "/static/brand_logos/karndean.jpg", "style_count": 251, "collection_count": 1 } ] } } } } } } } }, "/recommend": { "post": { "tags": [ "推荐" ], "summary": "智能推荐", "description": "输入产品SKU,返回跨品牌相似地板推荐", "responses": { "200": { "description": "推荐结果", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RecommendResponse" } } } } }, "parameters": [ { "name": "sku", "in": "query", "required": true, "schema": { "type": "string" }, "description": "产品SKU编码", "example": "CB218LG" } ] } }, "/calculator/calc": { "post": { "tags": [ "计算器" ], "summary": "地板面积计算", "description": "支持多房间、扣减区域、单片尺寸、铺设方式损耗、每箱片数、缝宽、单价。报告由前端根据返回结果自行生成。", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CalcInput" } } } }, "responses": { "200": { "description": "计算结果", "content": { "application/json": { "schema": { "": "#/components/schemas/CalcResult" } } } }, "400": { "description": "参数错误" } } } }, "/floor/options": { "get": { "tags": [ "地板更换" ], "summary": "获取地板样式选项(从产品库动态加载,含尺寸变体)", "description": "从产品数据库动态加载地板样式选项。每个样式对应一个真实产品SKU,含 width_in/length_in/description/variants 等字段。\n\n材质分类(按 material 字段自动归类):\n- wood_floors:Oak/Ash/Hickory/Maple 等木材\n- tile_floors:Porcelain/Stone Look/Glass + Laminate\n- vinyl_floors:Luxury Vinyl/Rigid Core\n\n前端应使用 variants 渲染尺寸选择面板。", "responses": { "200": { "description": "成功", "content": { "application/json": { "schema": { "type": "object", "properties": { "code": { "type": "integer", "example": 200 }, "data": { "$ref": "#/components/schemas/FloorOptionsResponse" } } }, "example": { "code": 200, "data": { "wood_floors": [], "tile_floors": [], "vinyl_floors": [], "wood_floors": [ { "id": "CB218LG", "sku": "CB218LG", "name": "Cherry", "material": "Oak", "color_tone": "Natural Oak", "finish": "Matte", "size_label": "2.25 x 84 in", "width_in": 2.25, "length_in": 84.0, "image_url": "https://...", "category": "Solid Hardwood", "description": "Natural cherry oak with subtle grain", "variants": [ { "sku": "CB4218", "size_label": "4 x 84 in", "width_in": 4.0, "length_in": 84.0 }, { "sku": "CB5218", "size_label": "5 x 84 in", "width_in": 5.0, "length_in": 84.0 } ] } ], "tile_floors": [], "vinyl_floors": [], "wood_patterns": [ { "code": 1, "name": "直铺(工字拼)Straight Lay", "pattern": "straight/parallel planks running from front to back with staggered joints", "category": "wood" }, { "code": 2, "name": "横铺 Horizontal Lay", "pattern": "horizontal planks running side to side across the width of the room", "category": "wood" }, { "code": 3, "name": "人字拼 Herringbone", "pattern": "herringbone/zigzag pattern with rectangular planks arranged in a broken V shape", "category": "wood" }, { "code": 4, "name": "鱼骨拼 Chevron", "pattern": "chevron pattern with planks cut at an angle forming a continuous V shape", "category": "wood" } ], "tile_patterns": [ { "code": 5, "name": "直铺(网格对缝)Straight Grid", "pattern": "straight grid layout with tiles perfectly aligned in rows and columns, clean orthogonal grout lines", "category": "tile" }, { "code": 6, "name": "工字铺(1/2错缝)Running Bond", "pattern": "running bond/brick pattern with each row offset by 50%, staggered brickwork appearance", "category": "tile" }, { "code": 7, "name": "三七错铺 1/3 Offset", "pattern": "tiles offset by 1/3 of their length in each row, subtle stepped pattern", "category": "tile" }, { "code": 8, "name": "六边形 Hexagonal", "pattern": "hexagonal/honeycomb tiles fitted together in a seamless honeycomb mesh", "category": "tile" }, { "code": 9, "name": "斜铺(45度对角)Diagonal", "pattern": "tiles laid at a 45-degree diagonal angle to the walls, diamond orientation", "category": "tile" } ], "rooms": [ { "code": 0, "name": "自动识别" }, { "code": 1, "name": "客厅" }, { "code": 2, "name": "卧室" }, { "code": 3, "name": "厨房" }, { "code": 4, "name": "餐厅" }, { "code": 5, "name": "浴室" }, { "code": 6, "name": "书房" }, { "code": 7, "name": "走廊" } ] } } } } } } } }, "/floor/generate": { "post": { "tags": [ "地板更换" ], "summary": "AI换地板(使用真实产品数据,含尺寸/变体)", "description": "上传房间照片 + 地板选项,加入 Redis 异步队列,返回 job_id。用 GET /floor/status?job_id=xxx 查询进度。\n\nfloor_id 支持有尺寸变体的产品——选择变体对应 SKU 即可,AI 会根据 width_in/length_in 生成对应物理尺寸的地板。", "requestBody": { "content": { "multipart/form-data": { "schema": { "type": "object", "required": [ "image", "floor_id", "pattern_code" ], "properties": { "image": { "type": "string", "format": "binary", "description": "房间照片" }, "floor_id": { "type": "string", "description": "产品SKU,从 /floor/options 获取(如 \"CB218LG\"),必须是真实产品SKU" }, "pattern_code": { "type": "integer", "description": "铺设方式编码(1-9),见文档顶部数字编码对照表", "example": 3 }, "room_code": { "type": "integer", "description": "房间类型编码(0-7),见文档顶部数字编码对照表。0 或省略表示自动检测", "example": 1 }, "grout_lines": { "type": "boolean", "description": "Optional. Tile floors only. true adds realistic visible grout lines between tiles.", "example": false }, "white_baseboard": { "type": "boolean", "description": "Optional. true adds or refreshes a realistic white baseboard/skirting board along visible wall-floor edges.", "example": false } } } } } }, "responses": { "200": { "description": "成功返回 job_id", "content": { "application/json": { "schema": { "type": "object", "properties": { "code": { "type": "integer", "example": 200 }, "data": { "type": "object", "properties": { "job_id": { "type": "string", "description": "用于查询进度的 job_id" } } } } }, "example": { "code": 200, "data": { "job_id": "1750123456789000000" } } } } }, "400": { "description": "参数错误", "content": { "application/json": { "schema": { "type": "object", "properties": { "code": { "type": "integer", "example": 400 }, "error": { "type": "string" } } }, "example": { "code": 400, "error": "Invalid options" } } } } } } }, "/products/{sku}": { "get": { "tags": [ "Products" ], "summary": "产品详情(含同花色多尺寸变体)", "description": "返回产品完整信息。如果该产品有同品牌+同花色(style_name)的其他SKU(不同尺寸/价格),会自动聚合到 variants 数组中,形成父子关系展示。\n\n例如:查询 Matte White 3×6 in,variants 返回 4×16 / 12×24 / 24×24 等其他尺寸。", "parameters": [ { "name": "sku", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Product SKU code" } ], "responses": { "200": { "description": "Product with variants", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProductDetail" } } } }, "404": { "description": "Product not found" } } } }, "/filter-options": { "get": { "tags": [ "Products" ], "summary": "分级筛选选项(层级结构)", "description": "返回所有可用的筛选值,支持层级结构(Material 下分 Wood / Porcelain / Vinyl / Other 子组)。\n\n前端层层递进实现方式:\n1. 页面加载时调用本接口获取全部选项\n2. 用户选择某个筛选项后,将已选参数传给 /products 接口\n3. 根据 /products 返回的 filter_options 动态收窄其他筛选项的可选范围", "responses": { "200": { "description": "Filter hierarchy", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FilterHierarchy" } } } } } } }, "/articles": { "get": { "tags": [ "Knowledge" ], "summary": "科普文章列表(分页)", "parameters": [ { "name": "page", "in": "query", "schema": { "type": "integer", "default": 1 } }, { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 10 } } ], "responses": { "200": { "description": "Article list", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ArticleListResponse" } } } } } } }, "/articles/{id}": { "get": { "tags": [ "Knowledge" ], "summary": "文章详情", "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } } ], "responses": { "200": { "description": "Article detail", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Article" } } } }, "404": { "description": "Article not found" } } } }, "/articles/recommend": { "get": { "tags": [ "Knowledge" ], "summary": "随机推荐文章(默认6篇)", "description": "每次随机返回指定数量的文章,默认6篇,最多20篇", "parameters": [ { "name": "count", "in": "query", "schema": { "type": "integer", "default": 6 }, "description": "Count (1-20)" } ], "responses": { "200": { "description": "Recommended articles", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ArticleRecommendResponse" } } } } } } }, "/user/avatar": { "post": { "tags": [ "用户" ], "summary": "上传头像", "description": "上传用户头像图片,自动替换旧头像。最大5MB。头像存储在 uploads/avatars/ 目录。", "security": [ { "BearerAuth": [] } ], "requestBody": { "required": true, "content": { "multipart/form-data": { "schema": { "type": "object", "properties": { "image": { "type": "string", "format": "binary", "description": "头像图片文件" } } } } } }, "responses": { "200": { "description": "上传成功,返回用户信息(含avatar_url)" } } } }, "/floor/status": { "get": { "tags": [ "地板更换" ], "summary": "查询生成进度(HTTP 轮询,含耗时统计)", "description": "Redis 异步队列任务状态查询。status: pending | processing | done | error。\n\n返回 timings_ms 字段包含每步耗时:check/mask/inpaint/cleanup/total。elapsed_ms 为总运行时间。", "parameters": [ { "name": "job_id", "in": "query", "required": true, "schema": { "type": "string" }, "description": "floor-generate 返回的 job_id" } ], "responses": { "200": { "description": "Job status with timing", "content": { "application/json": { "schema": { "type": "object", "properties": { "code": { "type": "integer", "example": 200 }, "data": { "type": "object", "properties": { "job_id": { "type": "string" }, "status": { "type": "string", "description": "pending | processing | done | error" }, "step": { "type": "string", "description": "check | mask | inpaint | done | error" }, "message": { "type": "string" }, "result": { "type": "string", "description": "Generated image path, e.g. /outputs/result_xxx.png" }, "error": { "type": "string" }, "elapsed_ms": { "type": "integer", "description": "Total elapsed milliseconds since job start" }, "timings_ms": { "type": "object", "description": "Per-step duration in milliseconds", "properties": { "check": { "type": "integer" }, "mask": { "type": "integer" }, "inpaint": { "type": "integer" }, "total": { "type": "integer" } } } } } } }, "example": { "code": 200, "data": { "job_id": "1784530075874083600", "status": "done", "step": "done", "message": "Done", "result": "/outputs/result_1784530075874083600.png", "elapsed_ms": 100340, "timings_ms": { "check": 5148, "mask": 25971, "inpaint": 69218, "total": 100340 } } } } } } } } }, "/upload": { "post": { "tags": [ "Upload" ], "summary": "通用图片上传", "description": "上传图片文件,返回访问URL。最大20MB,自动检测图片类型。存于 static/images/ 目录", "requestBody": { "required": true, "content": { "multipart/form-data": { "schema": { "type": "object", "properties": { "image": { "type": "string", "format": "binary", "description": "图片文件" } } } } } }, "responses": { "200": { "description": "上传成功", "content": { "application/json": { "schema": { "type": "object", "properties": { "code": { "type": "integer", "example": 200 }, "data": { "type": "object", "properties": { "url": { "type": "string", "example": "/static/images/abc123.jpg" }, "filename": { "type": "string", "example": "abc123.jpg" } } } } } } } } } } }, "/user/frequent-brands": { "get": { "tags": [ "Brand Tracking" ], "summary": "获取常用品牌", "description": "返回浏览≥3次或收藏≥2次的品牌。需登录。按权重排序", "security": [ { "BearerAuth": [] } ], "responses": { "200": { "description": "常用品牌列表", "content": { "application/json": { "schema": { "type": "object", "properties": { "code": { "type": "integer", "example": 200 }, "data": { "type": "object", "properties": { "brands": { "type": "array", "items": { "$ref": "#/components/schemas/FrequentBrand" } }, "total": { "type": "integer" } } } } } } } } } } } } }