""" TAPD链接解析模块 负责从TAPD链接中提取需求单号 支持的链接格式: 1. 列表页弹窗链接: https://www.tapd.cn/tapd_fe/{workspace_id}/story/list?...dialog_preview_id=story_{单号} 2. 详情页链接: https://www.tapd.cn/{workspace_id}/prong/stories/view/{单号} """ import re from typing import Tuple, Optional # 链接类型常量 LINK_TYPE_DIALOG = "dialog" # 列表页弹窗链接 LINK_TYPE_VIEW = "view" # 详情页链接 LINK_TYPE_UNKNOWN = "unknown" def parse_tapd_link(url: str) -> Tuple[bool, str, str]: """ 解析TAPD链接,提取需求单号 Args: url: TAPD链接字符串 Returns: Tuple[bool, str, str]: (是否成功, 单号或错误信息, 链接类型) - 成功时: (True, "1234567890", "dialog" 或 "view") - 失败时: (False, "错误信息", "unknown") """ if not url: return (False, "链接为空", LINK_TYPE_UNKNOWN) # 确保是字符串类型 if not isinstance(url, str): url = str(url) url = url.strip() if not url: return (False, "链接为空", LINK_TYPE_UNKNOWN) # 格式一:列表页弹窗链接 # 匹配 dialog_preview_id=story_(\d+) pattern_dialog = r'dialog_preview_id=story_(\d+)' match_dialog = re.search(pattern_dialog, url) if match_dialog: story_id = match_dialog.group(1) return (True, story_id, LINK_TYPE_DIALOG) # 格式二:详情页链接 # 匹配 /stories/view/(\d+) pattern_view = r'/stories/view/(\d+)' match_view = re.search(pattern_view, url) if match_view: story_id = match_view.group(1) return (True, story_id, LINK_TYPE_VIEW) # 未匹配到任何格式 return (False, f"无法识别的链接格式: {url[:100]}", LINK_TYPE_UNKNOWN) def extract_story_id(url: str) -> Optional[str]: """ 从TAPD链接中提取需求单号(简化接口) Args: url: TAPD链接字符串 Returns: Optional[str]: 成功返回单号,失败返回None """ success, result, _ = parse_tapd_link(url) return result if success else None def is_valid_tapd_link(url: str) -> bool: """ 检查是否为有效的TAPD链接 Args: url: TAPD链接字符串 Returns: bool: 是否为有效链接 """ success, _, _ = parse_tapd_link(url) return success if __name__ == "__main__": print("=== TAPD链接解析器测试 ===\n") # 测试用例 test_cases = [ # 格式一:列表页弹窗链接 "https://www.tapd.cn/tapd_fe/58335167/story/list?dialog_preview_id=story_1158335167001044388", # 格式二:详情页链接 "https://www.tapd.cn/58335167/prong/stories/view/1158335167001044388", # 无效链接 "https://www.tapd.cn/58335167/bugtrace/bugs/view/123456", "https://www.google.com", "", None, ] for i, url in enumerate(test_cases, 1): print(f"测试 {i}: {url}") success, result, link_type = parse_tapd_link(url) if success: print(f" ✓ 解析成功: 单号={result}, 类型={link_type}") else: print(f" ✗ 解析失败: {result}") print()