# 一个简洁但功能全面的项目进度管理工具 KanBoard

## 概述

在项目建设中，为了及时掌握项目推进情况，项目承建人员需要定期汇报工作进展，而项目管理员需要将这些信息整合成日报、周报和月报。

项目数量较少时，联系各承建人员、收集并整理进展信息还不复杂。然而，当项目数量增多、规模扩大时，往往需要安排多人分级负责、逐层上报汇总。这种方式不仅会降低灵活性，还易导致信息传递滞后。因此，我们不禁思考：是否有一种项目进度管理工具，能够帮助我们更高效、更灵活地管理项目进展？

因为工作上的原因，本人要参与几十个项目的管理工作，为了实现上述的效果，本人尝试部署了多款项目管理工具，并最终选择了 [KanBoard](https://kanboard.org/)。主要原因是：

-  Github 上的各种开源项目管理工具都是英文为第一语言的，翻译这块做的不是很好，包括 KanBoard，交给承建人员使用时就需要考虑他们的适应性。
- 大部分的开源项目管理工具不支持 Webhook 和 API，为了自动化生成报表和消息提醒，这个功能是必备的。
- KanBoard 本身的功能比较完善，可定制的内容比其他项目要多，并且支持插件市场，可以增加很多插件来完善其功能。此外，程序的 Bug 也比较少，自己魔改的成本比较低。

## 部署

这里同样使用 Docker 进行部署：

```dockerfile
docker run -itd --name KanBorad --restart always \
-p 「port」:80 \
-e DATABASE_URL="postgres://「user」:「password」@「host」:「port」/「db」" \
-e PLUGIN_INSTALLER=true \
-v /「path」/data:/var/www/app/data \
-v /「path」/plugins:/var/www/app/plugins \
-v /「path」/Locale:/var/www/app/app/Locale:ro \
-v /share/Web/KanBoard/Model:/var/www/app/app/Model:ro \
-v /「path」/Template:/var/www/app/app/Template:ro \
-v /share/Web/KanBoard/Controller:/var/www/app/app/Controller:ro \
-v /「path」/css:/var/www/app/assets/css:ro \
-v /「path」/js:/var/www/app/assets/js:ro \
kanboard/kanboard:latest
```

其中：

- `DATABASE_URL`：可以选择`PostgreSQL`或者`MySQL(MariaDB)`，不过我实测下来，我使用的MariaDB 在容器初始化的时候会有些问题，导致无法正常部署。
- `PLUGIN_INSTALLER`：表示可以安装插件，如果想要更好的体验，插件还是需要的。
- `data`和`plugins`目录时官方推荐的挂载目录，`Locale`、`Model`、`Template`、`Controller`、`css`和`js`目录是我个人的挂载目录。KanBoard 是 PHP 项目：
	- `Locale`和项目汉化相关，将原项目中的英文翻译成中文，因为原先的中文汉化有种机翻的味道，有些内容明明是中文却看不懂，所以需要重新翻译。
	- `Model`和`Controller`定义了数据和控制器，可以在修改过程中参考。
	- `Template`是项目页面的模板，修改模板可以控制页面上显示的内容，可以把一些不常见的或者不想让用户使用的功能删除。
	- `css`和`js`设计页面的样式和部分逻辑，本人用到的不是很多，主要是因为安装了插件以后，在`plugins`里头也可以修改样式，并且优先级会高一些。

> [!warning]  警告
> `Locale`、`Template`、`css`和`js`目录需要先建立容器将里面的内容手动复制出来才行，不管有没有`ro`，只要映射了目录，目录内就不会生成文件了。

## 主要功能

### 权限

KanBoard 在权限这块基本做的比较完善：

![](https://img.papergate.top:5000/i/2025/11/69250cdd6461e.webp)

应用默认有三种角色：超级管理员、管理员和用户。

- 超级管理员：可以理解成是后台人员，可以对应用的设置进行修改。
- 管理员：可以理解成是项目管理人员，可以对「项目」以及项目下的「任务」进行修改。
- 用户：可以理解成是项目承建人员，可以对「任务」进行修改。

### 常用插件

使用超级管理员账户可以配置项目的插件，我安装的插件如下：

![](https://img.papergate.top:5000/i/2025/11/69250e4d2abc2.webp)

- [Customizer](https://github.com/creecros/Customizer)主要用来设置主题，安装以后可以在`plugins`里头直接修改样式，里头的主题大多都一般，名为`Breathe`的主题看着还可以，可以以这个主题为模板，魔改自己的主题，我最终使用的就是这款主题。

> [!warning]  警告
> 我使用的这个版本的 Customizer 有一个 Bug，因为它覆盖了原来项目中的`logout`也就是退出登录的`.php`文件，而它新写的代码中有些问题，导致无法正常退出登录，需要手动修复后才可以。

- [Calendar](https://codeberg.org/abu/Calendar/)主要用来生成项目日历，可以清晰展示每一天的任务。
- [metaMagik](https://github.com/creecros/MetaMagik)主要用来增加自定义字段，比如原来任务中不含有「任务进度」这个字段，新增这个字段以后，就可以在面板上显示这个字段了。

![](https://img.papergate.top:5000/i/2025/11/692510a00952a.webp)

> [!warning]  警告
> 要注意的是，这个插件对于中文的支持不是很好，录入的时候，如果将名称（比如任务进度）以中文输入，将不会正常录入到数据库中，我采用的方法是先以英文名称的方式录入，再通过连接数据库找到记录手动修改为中文。表名是`metadata_types`，修改的列名是`human_name`和`beauty_name`。

- [里程碑](https://github.com/oliviermaridat/kanboard-milestone-plugin)：用来生成里程碑。
- [Gantt](https://github.com/kanboard/plugin-gantt)：用来生成甘特图。
- [Bigboard](https://github.com/BlueTeck/kanboard_plugin_bigboard)：将勾选的多个项目聚合到一块，生成项目总览。
- [EnableAttachmentRenaming](https://github.com/Chaosmeister/EAR)可以对上传的附件进行重命名。

> [!info]  信息
> 上面这些插件对于中文的支持都不是很好，如果想要愉快的使用，都需要提前进行一定的汉化工作。

## 项目

> [!info]  信息
> 从下面开始，展示的内容就是我魔改以后的 KanBoard 页面了，很多功能都经过了修改，不常用的功能也都删除了，所以和正常部署还是有很大的差别的，仅供参考。

项目管理人员（超级管理员或管理员权限）可以对项目进行编辑：

![](https://img.papergate.top:5000/i/2025/11/6925158527a48.webp)

项目承建人员（用户权限）可以对项目进行浏览，但是不可以进行编辑：

![](https://img.papergate.top:5000/i/2025/11/69265a328384e.webp)

### 新建项目

![](https://img.papergate.top:5000/i/2025/11/6925140514b96.webp)

新建项目的时候可以以其他项目作为模板快速搭建一个新的项目，或者建立一个全新的项目。

以其他项目为模板时，「项目配置」会自动配置成和模板项目一致，会生成一个空白的、没有任何任务的项目。

### 项目配置

创建好项目以后可以点击「项目配置」对项目进行更加细致的修改：

![](https://img.papergate.top:5000/i/2025/11/6925154184c69.webp)

可编辑内容包括「修改项目」、「进度」、「阶段」、「权限」这几个部分，其中：进度、阶段和权限可以通过模板进行继承，只要设置好模板然后引用即可。

![](https://img.papergate.top:5000/i/2025/11/69251752a4f87.webp)

#### 修改项目

「修改项目」可以设置项目的「描述」、「项目负责人」和项目的「启动时间」和「结束时间」：

![](https://img.papergate.top:5000/i/2025/11/6925161edfc76.webp)

#### 阶段和进度

「阶段」是项目从立项到验收的一段段时间区间，比如可以设置成如下内容：

![](https://img.papergate.top:5000/i/2025/11/6925180ff3edf.webp)

「进度」是某个任务从发布到完成的过程，比如可以设置成如下内容：

![](https://img.papergate.top:5000/i/2025/11/692518019063f.webp)

这样项目内的任务面板上就可以看到如下内容：

![](https://img.papergate.top:5000/i/2025/11/692518bacf06c.webp)

#### 权限

权限用于添加项目的参与者，包括「项目管理员」、「项目成员」和「项目观察者」，这些人员都需要提前注册账号，项目只对项目的参与者可见。

权限通过模板继承，所以选择模板时，应当尽可能选择承建单位相同的项目。

![](https://img.papergate.top:5000/i/2025/11/6926604d2dae9.webp)

## 任务

项目管理人员（超级管理员或管理员）和项目承建人员（用户）可以对项目任务进行编辑：

### 新增任务

点击任务面板中对应「阶段」和「进度」前面的`+`号，可以新增任务：

![](https://img.papergate.top:5000/i/2025/11/69252096af24a.webp)

新增的任务对全部的项目参与者都是可见的，可以通过设置过滤器只显示指派给自己的项目：

![](https://img.papergate.top:5000/i/2025/11/69266211c6739.webp)

### 任务配置

![](https://img.papergate.top:5000/i/2025/11/692521a66a3df.webp)

点击上图框内部分可进行「快捷操作」，点击框外部分可以进入「任务详情」页面。

#### 快捷操作

点击卡片上的「下拉」按钮有以下快捷操作，点击「编辑」按钮可以快速「修改任务」：

![](https://img.papergate.top:5000/i/2025/11/692521f58d249.webp)

#### 任务详情

点击其余部分进入「任务详情」页面，除了「快捷操作」以外的一些内容在这里使用：

![](https://img.papergate.top:5000/i/2025/11/692522a71ff22.webp)

## API

KanBoard 的 API 可以通过如下[网址](https://docs.kanboard.org/v1/api/)访问。

API 有两种，一种是应用程序 API，一种是用户 API。应用程序 API 能够获取全部的信息，但是只有超级管理员可见。用户 API 能够访问用户自身授权的信息，使用用户自己的用户名和密码登录即可。

因为应用程序 API 功能更加全面一些，所以就直接使用应用程序 API了。

### 通用部分

这里使用`python`调用 API 接口，通用的使用方法如下：

```python
import requests

url = 'https://host:port/jsonrpc.php'
username = "jsonrpc"
password = "xxxxx"
payload = {
    "jsonrpc": "2.0",
    "method": "xxx",
    "id": 1
    "params":{}
}

response = requests.post(
    url,
    auth=(username, password),
    json=payload
)
data = response.json()
```

不同的 API 接口差别在于`payload`不同。Kanboard 使用 JSON-RPC 协议，和其他使用 JSON-RPC 协议的应用程序使用方法相同。`payload`里的`id`由自己设定，主要用于异步通信的时候确定`response`和`requests`的对应关系。

### 获取全部项目

```python
payload = {
    "jsonrpc": "2.0",
    "method": "getAllProjects",
    "id": 1
}
```

### 设置项目的 MetaData

```python
payload = {
    "jsonrpc": "2.0",
    "method": "saveProjectMetadata",
    "id": 1,
    "params": {
        "project_id": 1,
        "values": {
            key: value
        }
    }
}
```

### 获取项目的 MetaData

可以一次获取全部的 MetaData：

```python
payload = {
    "jsonrpc": "2.0",
    "method": "getProjectMetadata",
    "id": 1,
    "params": {
        "project_id": project_id
    }
}
```

或者获取指定名称的 MetaData：

```python
payload = {
    "jsonrpc": "2.0",
    "method": "getProjectMetadataByName",
    "id": 1,
    "params": {
        "project_id": 1,
        "name": key
    }
}
```

### 获取项目活动

```python
payload = {
    "jsonrpc": "2.0",
    "method": "getProjectActivity",
    "id": 1,
    "params": {
        "project_id": project_id
    }
}
```

### 获取任务

```python
payload = {
    "jsonrpc": "2.0",
    "method": "getTask",
    "id": 1,
    "params": {
        "task_id": task_id
    }
}
```

### 更新任务

```python
payload = {
    "jsonrpc": "2.0",
    "method": "updateTask",
    "id": 1,
    "params": {
        "id": task_id,
        key: value,
        key2: value2
    }
}
```

可选的字段包括：

- `title`：标题
- `description`：描述
- `date_started`：开始日期，格式是`YYYY-MM-DD HH:MM`
- `date_due`：到期日期，格式是`YYYY-MM-DD HH:MM`
- `owner_id`：任务的指派人

### 设置任务的MetaData

```python
payload = {
    "jsonrpc": "2.0",
    "method": "saveTaskMetadata",
    "id": 1,
    "params": [
        task_id,
        {
            key: value
        }
    ]
}
```

### 获取任务的MetaData

可以一次获取全部的 MetaData：

```python
payload = {
    "jsonrpc": "2.0",
    "method": "getTaskMetadata",
    "id": 1,
    "params": [
        task_id
    ]
}
```

或者获取指定名称的 MetaData：

```python
payload = {
    "jsonrpc": "2.0",
    "method": "getTaskMetadataByName",
    "id": 133280317,
    "params": [
        task_id,
        "key"
    ]
}
```

### 获取评论

获取任务下的全部评论：

```python
payload = {
    "jsonrpc": "2.0",
    "method": "getAllComments",
    "id": 1,
    "params": {
        "task_id": task_id
    }
}
```

> [!info]  信息
> 不过说起来我能直接访问数据库，所以用 API 反而更加复杂一些，原来以为会用不上的，直到我需要使用 WebHook 时，这时需要修改一些数据，所以用 API 会更加保险一些。

## WebHook

发送过来的 WebHook 主要由以下数据组成：

```json
{
    "event_name": "task.move.column",
    "event_data": {
        "task_id": 29,
        "task": {
            "id": 29,
            "title": "555",
            "description": "",
            "date_creation": 1764419467,
            "color_id": "yellow",
            "project_id": 3,
            "column_id": 9,
            "owner_id": 0,
            "position": 1,
            "is_active": true,
            "date_completed": null,
            "score": 0,
            "date_due": 0,
            "category_id": 0,
            "creator_id": 1,
            "date_modification": 1764420519,
            "reference": "",
            "date_started": 0,
            "time_spent": 0,
            "time_estimated": 0,
            "swimlane_id": 7,
            "date_moved": 1764420519,
            "recurrence_status": 0,
            "recurrence_trigger": 0,
            "recurrence_factor": 0,
            "recurrence_timeframe": 0,
            "recurrence_basedate": 0,
            "recurrence_parent": null,
            "recurrence_child": null,
            "priority": 0,
            "external_provider": null,
            "external_uri": null,
            "category_name": null,
            "swimlane_name": "可研立项",
            "project_name": "项目模板",
            "column_title": "待办",
            "assignee_username": null,
            "assignee_name": null,
            "creator_username": "xxx",
            "creator_name": "xxx",
            "category_description": null,
            "column_position": 1
        },
        "changes": {
            "src_column_id": 10,
            "dst_column_id": "9",
            "date_moved": 1764420438
        },
        "project_id": 3,
        "position": 1,
        "column_id": "9",
        "swimlane_id": "7",
        "src_column_id": 10,
        "dst_column_id": "9",
        "date_moved": 1764420438,
        "recurrence_status": 0,
        "recurrence_trigger": 0
    },
    "event_author": "xxx"
}
```

以`task.move.column`为例，就是移动进度（待办、进行中、已完成），传过来的`json`中有三个字段`event_name`、`event_data`和`event_author`。

`event_data`中包含了大部分信息，这样我们收到了 WebHook 以后就可以得知项目的承建人员进行了哪些活动，主要有两方面的作用：

- 一是当项目进展有变动时，可以推送消息给我们，让我们在第一时间知道项目的变化。
- 二是项目承建人员在填写任务时，可能有一些字段没有填入，我们可以进行推断，使用 API 给这些任务填入默认值。

> [!info]  信息
> KanBoard 的项目中，很多地方都留有了 Hook Refer，在触发事件时让用户执行自己的操作，只需要自己写`plugin`定义 Hook 即可。不过 Hook Refer 的位置不是很全面，有时候需要自己去定义一些 Hook Refer。出于省事的考虑，本人就直接用 WebHook 来处理了。

## 与其他项目的联动

为了方便 KanBoard 的使用体验，本人结合之前布置的其他项目，与 KanBoard 进行了一些联动操作，介绍如下：

- **Chanify**：当新建任务、任务状态变动和任务评论时，会推送消息到手机
- **n8n**：结合 AI Agent 生成日报和周报，调用 FastAPI 处理结果并根据模板调用 `docxtpl` 生成 Word 文档
- **MetaBase**：生成周工作的 BI 图表
- **Habitica**：在 KanBoard 中建立个人工作记录，个人工作创建和完成同步到 Habitica 的待办事项并自动记分

因为上述内容讲述起来比较繁琐，并且本身实现起来并不困难，所以不再继续阐述。

---

> 作者: Aphros  
> URL: https://blog.papergate.top/posts/%E4%B8%80%E4%B8%AA%E7%AE%80%E6%B4%81%E4%BD%86%E5%8A%9F%E8%83%BD%E5%85%A8%E9%9D%A2%E7%9A%84%E9%A1%B9%E7%9B%AE%E8%BF%9B%E5%BA%A6%E7%AE%A1%E7%90%86%E5%B7%A5%E5%85%B7-kanboard/  

