添加必读项 Args: profile: 用户画像 item_type: 类型 (author/institution/keyword) value: 值 Returns: 结果字典
(profile: Dict, item_type: str, value: str)
| 277 | |
| 278 | |
| 279 | def add_must_read(profile: Dict, item_type: str, value: str) -> Dict[str, Any]: |
| 280 | """ |
| 281 | 添加必读项 |
| 282 | |
| 283 | Args: |
| 284 | profile: 用户画像 |
| 285 | item_type: 类型 (author/institution/keyword) |
| 286 | value: 值 |
| 287 | |
| 288 | Returns: |
| 289 | 结果字典 |
| 290 | """ |
| 291 | must_read = profile.get("must_read", {"authors": [], "institutions": [], "keywords": []}) |
| 292 | |
| 293 | key = f"{item_type}s" |
| 294 | current_list = must_read.get(key, []) |
| 295 | item_label = ITEM_TYPE_LABELS.get(item_type, item_type) |
| 296 | |
| 297 | cleaned_value = clean_must_read_value(value) |
| 298 | if item_type == "keyword": |
| 299 | broad_direction = _resolve_broad_must_read_keyword(cleaned_value) |
| 300 | if broad_direction: |
| 301 | return _route_keyword_to_interest_direction(profile, cleaned_value, broad_direction) |
| 302 | |
| 303 | normalized_value = normalize_must_read_value(cleaned_value) |
| 304 | existing_value = next( |
| 305 | (item for item in current_list if normalize_must_read_value(str(item)) == normalized_value), |
| 306 | None, |
| 307 | ) |
| 308 | if existing_value is not None: |
| 309 | return {"success": False, "message": f"{existing_value} 已在必读清单中"} |
| 310 | |
| 311 | current_list.append(cleaned_value) |
| 312 | must_read[key] = current_list |
| 313 | profile["must_read"] = must_read |
| 314 | profile["updated_at"] = datetime.now().isoformat() |
| 315 | |
| 316 | return {"success": True, "message": f"已添加 {cleaned_value} 到必读{item_label}清单"} |
| 317 | |
| 318 | |
| 319 | def remove_must_read(profile: Dict, item_type: str, value: str) -> Dict[str, Any]: |
no test coverage detected