Skip to content

项目管理集成

Obsidian 可以与主流项目管理工具集成,将分散的项目信息集中管理。本文介绍各种集成方案和最佳实践。

集成方案概览

方案实时性双向同步难度
手动同步单向
URI/快捷指令即时单向
Local REST API即时双向
专用插件即时视情况
API 脚本定时双向

Jira 集成

使用 Jira 插件

安装 Jira Issue 社区插件,直接在 Obsidian 中查看和管理 Jira Issue。

通过 API 同步

python
#!/usr/bin/env python3
"""从 Jira 同步 Issue 到 Obsidian"""
import requests
import os
from datetime import datetime

JIRA_URL = os.getenv("JIRA_URL")
JIRA_EMAIL = os.getenv("JIRA_EMAIL")
JIRA_TOKEN = os.getenv("JIRA_TOKEN")
OBSIDIAN_API = "http://localhost:27124"

def get_jira_issues(project_key, jql=None):
    """获取 Jira Issues"""
    auth = (JIRA_EMAIL, JIRA_TOKEN)
    query = jql or f"project = {project_key} AND updated >= -7d ORDER BY updated DESC"
    
    response = requests.get(
        f"{JIRA_URL}/rest/api/2/search",
        params={"jql": query, "maxResults": 50},
        auth=auth,
    )
    response.raise_for_status()
    return response.json()["issues"]

def issue_to_markdown(issue):
    """将 Jira Issue 转为 Markdown"""
    key = issue["key"]
    fields = issue["fields"]
    
    return f"""# {key}: {fields["summary"]}

## 基本信息

| 字段 | 值 |
|------|-----|
| 状态 | {fields["status"]["name"]} |
| 优先级 | {fields.get("priority", {}).get("name", "N/A")} |
| 类型 | {fields["issuetype"]["name"]} |
| 负责人 | {fields.get("assignee", {}).get("displayName", "未分配")} |
| 创建时间 | {fields["created"][:10]} |
| 更新时间 | {fields["updated"][:10]} |

## 描述

{fields.get("description", "无描述") or "无描述"}

## 链接

[Jira Issue]({JIRA_URL}/browse/{key})
"""

def sync_jira_to_obsidian(project_key, vault="MyVault"):
    """同步 Jira Issues 到 Obsidian"""
    issues = get_jira_issues(project_key)
    
    for issue in issues:
        key = issue["key"]
        content = issue_to_markdown(issue)
        
        requests.put(
            f"{OBSIDIAN_API}/vault/{vault}/notes/Projects/Jira/{key}",
            headers={
                "Authorization": f"Bearer {os.getenv('OBSIDIAN_API_KEY')}",
                "Content-Type": "text/markdown",
            },
            data=content.encode("utf-8"),
        )
    
    print(f"同步完成: {len(issues)} 个 Issues")

if __name__ == "__main__":
    sync_jira_to_obsidian("PROJ")

Trello 集成

使用 Trello 插件

安装 Trello 社区插件,将 Trello 看板嵌入 Obsidian。

Webhook 同步

python
#!/usr/bin/env python3
"""Trello Webhook 同步到 Obsidian"""
from flask import Flask, request, jsonify
import requests
import os

app = Flask(__name__)
OBSIDIAN_API = "http://localhost:27124"

@app.route("/trello-webhook", methods=["POST"])
def trello_webhook():
    """处理 Trello Webhook 回调"""
    data = request.json
    action = data.get("action", {})
    action_type = action.get("type")
    
    if action_type == "createCard":
        card = action["data"]["card"]
        list_name = action["data"]["list"]["name"]
        
        content = f"""# {card["name"]}

## Trello 卡片

- **列表**: {list_name}
- **ID**: {card["idShort"]}
- **链接**: [查看卡片](https://trello.com/c/{card["idShort"]})

## 描述

{card.get("desc", "无描述") or "无描述"}

## 任务

- [ ] 
"""
        
        # 创建 Obsidian 笔记
        requests.put(
            f"{OBSIDIAN_API}/vault/MyVault/notes/Trello/{card['name']}",
            headers={
                "Authorization": f"Bearer {os.getenv('OBSIDIAN_API_KEY')}",
                "Content-Type": "text/markdown",
            },
            data=content.encode("utf-8"),
        )
    
    return jsonify({"status": "ok"})

if __name__ == "__main__":
    app.run(port=5000)

Notion 集成

从 Notion 同步到 Obsidian

python
#!/usr/bin/env python3
"""从 Notion 同步数据库到 Obsidian"""
import requests
import os
from datetime import datetime

NOTION_TOKEN = os.getenv("NOTION_TOKEN")
NOTION_DATABASE_ID = os.getenv("NOTION_DATABASE_ID")
OBSIDIAN_API = "http://localhost:27124"

def get_notion_pages():
    """获取 Notion 数据库页面"""
    response = requests.post(
        f"https://api.notion.com/v1/databases/{NOTION_DATABASE_ID}/query",
        headers={
            "Authorization": f"Bearer {NOTION_TOKEN}",
            "Notion-Version": "2022-06-28",
            "Content-Type": "application/json",
        },
        json={},
    )
    response.raise_for_status()
    return response.json()["results"]

def page_to_markdown(page):
    """将 Notion 页面转为 Markdown"""
    props = page["properties"]
    title = ""
    for prop in props.values():
        if prop["type"] == "title":
            title = prop["title"][0]["plain_text"] if prop["title"] else "Untitled"
            break
    
    # 构建属性表
    props_md = "| 属性 | 值 |\n|------|-----|\n"
    for name, prop in props.items():
        if prop["type"] == "select":
            value = prop["select"]["name"] if prop["select"] else ""
        elif prop["type"] == "multi_select":
            value = ", ".join(t["name"] for t in prop["multi_select"])
        elif prop["type"] == "date":
            value = prop["date"]["start"] if prop["date"] else ""
        elif prop["type"] == "checkbox":
            value = "✅" if prop["checkbox"] else "❌"
        elif prop["type"] == "url":
            value = prop["url"] or ""
        else:
            value = ""
        
        if value:
            props_md += f"| {name} | {value} |\n"
    
    return f"""# {title}

## 属性

{props_md}

## 链接

[Notion 页面]({page["url"]})

## 内容

> 从 Notion 同步于 {datetime.now().strftime("%Y-%m-%d %H:%M")}
"""

def sync_notion_to_obsidian(vault="MyVault"):
    """同步 Notion 到 Obsidian"""
    pages = get_notion_pages()
    
    for page in pages:
        content = page_to_markdown(page)
        title = content.split("\n")[0].replace("# ", "")
        
        requests.put(
            f"{OBSIDIAN_API}/vault/{vault}/notes/Notion/{title}",
            headers={
                "Authorization": f"Bearer {os.getenv('OBSIDIAN_API_KEY')}",
                "Content-Type": "text/markdown",
            },
            data=content.encode("utf-8"),
        )
    
    print(f"同步完成: {len(pages)} 个页面")

if __name__ == "__main__":
    sync_notion_to_obsidian()

GitHub Projects 集成

使用 gh CLI

bash
#!/bin/bash
# sync-github-projects.sh — 同步 GitHub Projects 到 Obsidian

REPO="owner/repo"
OBSIDIAN_API="http://localhost:27124"
VAULT="MyVault"
API_KEY="${OBSIDIAN_API_KEY}"

# 获取 Open Issues
gh issue list --repo "$REPO" --state open --limit 50 --json number,title,labels,assignees,state,createdAt,updatedAt --jq '.[] | @base64' | while read -r issue_b64; do
  issue=$(echo "$issue_b64" | base64 -d)
  
  number=$(echo "$issue" | jq -r '.number')
  title=$(echo "$issue" | jq -r '.title')
  labels=$(echo "$issue" | jq -r '.labels | map(.name) | join(", ")')
  assignees=$(echo "$issue" | jq -r '.assignees | map(.login) | join(", ")')
  
  content="# Issue #$number: $title

## 信息

| 字段 | 值 |
|------|-----|
| 编号 | #$number |
| 标签 | $labels |
| 负责人 | $assignees |

## 链接

[GitHub Issue](https://github.com/$REPO/issues/$number)
"
  
  # 创建笔记
  curl -s -X PUT "$OBSIDIAN_API/vault/$VAULT/notes/GitHub/Issue-$number" \
    -H "Authorization: Bearer $API_KEY" \
    -H "Content-Type: text/markdown" \
    -d "$content"
done

echo "GitHub Issues 同步完成"

在 Obsidian 中管理项目

项目看板模板

使用 Bases 数据库或 Dataview 创建项目看板:

markdown
# 项目看板

## 进行中

```dataview
TABLE status, priority, due_date
FROM "Projects"
WHERE status = "in-progress"
SORT priority DESC

待办

dataview
TABLE status, priority, due_date
FROM "Projects"
WHERE status = "todo"
SORT priority DESC

已完成

dataview
TABLE status, completion_date
FROM "Projects"
WHERE status = "done"
SORT completion_date DESC

### 项目仪表盘

```markdown
---
title: 项目仪表盘
date: {{date}}
---

# 项目仪表盘

## 📊 总览

```dataview
TABLE 
  length(filter(rows, (r) => r.status = "in-progress")) AS "进行中",
  length(filter(rows, (r) => r.status = "todo")) AS "待办",
  length(filter(rows, (r) => r.status = "done")) AS "已完成"
FROM "Projects"
GROUP BY project

🔥 高优先级

dataview
TABLE priority, status, due_date
FROM "Projects"
WHERE priority = "high" AND status != "done"
SORT due_date ASC

⏰ 即将到期

dataview
TABLE status, due_date
FROM "Projects"
WHERE due_date <= date(today) + dur(3 days) AND status != "done"
SORT due_date ASC

## 最佳实践

### 1. 选择合适的集成深度

| 需求 | 推荐方案 |
|------|----------|
| 仅查看项目状态 | Dataview 查询 |
| 单向同步任务 | API 脚本 + cron |
| 双向同步 | Local REST API |
| 团队协作 | 直接使用项目管理工具,Obsidian 做笔记 |

### 2. 保持数据一致

- 为同步的笔记添加来源标记
- 使用统一的状态标签命名
- 定期同步避免数据过时

### 3. 避免过度集成

- Obsidian 的核心优势是知识管理
- 项目管理有其专业工具
- 集成应补充而非替代

## 常见问题

### 同步频率如何设置?

| 场景 | 建议频率 |
|------|----------|
| 查看项目概览 | 每日一次 |
| 追踪紧急任务 | 每小时 |
| 团队项目 | 每 15 分钟 |
| 个人项目 | 手动触发 |

### 双向同步如何处理冲突?

1. 以最后修改时间为准
2. 为关键字段添加来源标记
3. 不自动合并,标记冲突让用户决定

### 大量任务时性能如何?

- Dataview 查询 1000+ 任务可能有延迟
- 建议分项目存储
- 使用 `LIMIT` 限制查询数量

## 相关资源

- [Bases 数据库](/advanced/bases) — Obsidian 内置数据库
- [Dataview 实战](/advanced/dataview-guide) — 数据查询
- [任务管理系统](/advanced/task-management) — 任务管理方案
- [Tasks 插件](/advanced/tasks-plugin) — 任务插件
- [自动化集成](/integrations/automation) — 通用自动化方案