116 lines
3.2 KiB
Python
116 lines
3.2 KiB
Python
"""
|
||
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()
|