From bd5f497ccb6b0ef333cd2a2140e3ede8dfa4a255 Mon Sep 17 00:00:00 2001 From: OpenClaw Bot Date: Fri, 20 Feb 2026 00:17:33 +0800 Subject: [PATCH] Update entity attribute API to support flexible attribute creation --- backend/main.py | 88 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 71 insertions(+), 17 deletions(-) diff --git a/backend/main.py b/backend/main.py index d7645ce..9dcb9fe 100644 --- a/backend/main.py +++ b/backend/main.py @@ -1530,8 +1530,11 @@ class AttributeTemplateUpdate(BaseModel): class EntityAttributeSet(BaseModel): - template_id: str - value: str + name: str + type: str + value: Optional[Union[str, int, float, List[str]]] = None + template_id: Optional[str] = None + options: Optional[List[str]] = None change_reason: Optional[str] = "" @@ -1665,31 +1668,82 @@ async def set_entity_attribute_endpoint(entity_id: str, attr: EntityAttributeSet if not DB_AVAILABLE: raise HTTPException(status_code=500, detail="Database not available") - from db_manager import EntityAttribute - db = get_db_manager() entity = db.get_entity(entity_id) if not entity: raise HTTPException(status_code=404, detail="Entity not found") - # 验证模板存在 - template = db.get_attribute_template(attr.template_id) - if not template: - raise HTTPException(status_code=404, detail="Attribute template not found") + # 验证类型 + valid_types = ['text', 'number', 'date', 'select', 'multiselect'] + if attr.type not in valid_types: + raise HTTPException(status_code=400, detail=f"Invalid type. Must be one of: {valid_types}") - new_attr = EntityAttribute( - id=str(uuid.uuid4())[:8], - entity_id=entity_id, - template_id=attr.template_id, - value=attr.value - ) + # 处理 value + value = attr.value + if attr.type == 'multiselect' and isinstance(value, list): + value = json.dumps(value) + elif value is not None: + value = str(value) - db.set_entity_attribute(new_attr, changed_by="user", change_reason=attr.change_reason) + # 处理 options + options = attr.options + if options: + options = json.dumps(options) + + # 检查是否已存在 + conn = db.get_conn() + existing = conn.execute( + "SELECT * FROM entity_attributes WHERE entity_id = ? AND name = ?", + (entity_id, attr.name) + ).fetchone() + + now = datetime.now().isoformat() + + if existing: + # 记录历史 + conn.execute( + """INSERT INTO attribute_history + (id, entity_id, attribute_name, old_value, new_value, changed_by, changed_at, change_reason) + VALUES (?, ?, ?, ?, ?, ?, ?, ?)""", + (str(uuid.uuid4())[:8], entity_id, attr.name, existing['value'], value, + "user", now, attr.change_reason or "") + ) + + # 更新 + conn.execute( + """UPDATE entity_attributes + SET value = ?, type = ?, options = ?, updated_at = ? + WHERE id = ?""", + (value, attr.type, options, now, existing['id']) + ) + attr_id = existing['id'] + else: + # 创建 + attr_id = str(uuid.uuid4())[:8] + conn.execute( + """INSERT INTO entity_attributes + (id, entity_id, template_id, name, type, value, options, created_at, updated_at) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)""", + (attr_id, entity_id, attr.template_id, attr.name, attr.type, value, options, now, now) + ) + + # 记录历史 + conn.execute( + """INSERT INTO attribute_history + (id, entity_id, attribute_name, old_value, new_value, changed_by, changed_at, change_reason) + VALUES (?, ?, ?, ?, ?, ?, ?, ?)""", + (str(uuid.uuid4())[:8], entity_id, attr.name, None, value, + "user", now, attr.change_reason or "创建属性") + ) + + conn.commit() + conn.close() return { + "id": attr_id, "entity_id": entity_id, - "template_id": attr.template_id, - "template_name": template.name, + "name": attr.name, + "type": attr.type, "value": attr.value, "success": True }