LokiTaskBoard 组件文档
目录
概述
LokiTaskBoard 是一个功能完善的看板式任务管理组件,提供了直观的任务可视化和交互功能。该组件采用 Web Component 技术构建,支持独立使用,不依赖特定的前端框架。
设计理念
组件设计遵循以下核心理念:
- 简洁直观:通过四列布局清晰展示任务状态流转
- 高效交互:支持拖拽排序、键盘导航和快速操作
- 主题适配:自动适配明暗主题,提供一致的视觉体验
- 状态同步:实时与后端API同步,支持本地缓存和离线任务
核心功能
1. 四列看板布局
组件固定使用四列布局来管理任务流程:
| 列名 | 状态值 | 颜色标识 | 用途 |
|---|---|---|---|
| Pending | pending |
灰色 | 待处理任务 |
| In Progress | in_progress |
蓝色 | 进行中任务 |
| In Review | review |
紫色 | 审核中任务 |
| Completed | done |
绿色 | 已完成任务 |
2. 拖拽交互
- 任务拖拽:支持在列间拖拽任务卡片改变状态
- 视觉反馈:拖拽过程中提供视觉提示和悬停效果
- 只读模式:可禁用拖拽功能,只展示任务
3. 数据管理
- API集成:自动与后端API同步任务数据
- 本地缓存:支持本地任务和缓存机制
- 实时更新:监听任务创建、更新、删除事件
- 乐观更新:先更新UI再确认API调用结果
4. 键盘导航
- 任务选择:使用Tab键在任务卡片间导航
- 任务详情:Enter或Space键打开任务详情
- 快速导航:ArrowUp/ArrowDown在任务列表中移动焦点
架构设计
组件层次结构
classDiagram
class LokiElement {
<<基类>>
+getBaseStyles()
}
class LokiTaskBoard {
-Array~Task~ _tasks
-boolean _loading
-string _error
-Object _draggedTask
-ApiClient _api
-State _state
+connectedCallback()
+disconnectedCallback()
+attributeChangedCallback()
-_setupApi()
-_loadTasks()
-_handleDragStart()
-_handleDrop()
+render()
}
class ApiClient {
+listTasks()
+moveTask()
+addEventListener()
+removeEventListener()
}
class State {
+get()
+update()
+moveLocalTask()
}
LokiElement <|-- LokiTaskBoard
LokiTaskBoard *-- ApiClient
LokiTaskBoard *-- State
数据流程图
sequenceDiagram
participant User as 用户
participant Board as LokiTaskBoard
participant API as ApiClient
participant State as 状态管理
participant Server as 后端服务
User->>Board: 拖拽任务到新列
Board->>Board: 乐观更新 (更新本地状态)
Board->>Board: 重新渲染 UI
alt 本地任务
Board->>State: moveLocalTask()
State->>Board: 更新完成
else 服务器任务
Board->>API: moveTask(taskId, newStatus)
API->>Server: PUT /api/tasks/:id/move
Server-->>API: 200 OK
API-->>Board: 成功响应
end
Board->>User: 触发 task-moved 事件
组件渲染流程
flowchart TD
A[connectedCallback] --> B[_setupApi]
B --> C[_loadTasks]
C --> D{加载状态?}
D -->|是| E[显示加载中]
D -->|否| F{有错误?}
F -->|是| G[显示错误信息]
F -->|否| H[渲染看板]
H --> I[渲染四列]
I --> J[渲染任务卡片]
J --> K[_attachEventListeners]
K --> L[完成渲染]
组件API
属性 (Attributes)
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
api-url |
string | window.location.origin |
API 基础 URL |
project-id |
string | - | 按项目 ID 过滤任务 |
theme |
string | auto-detect | 主题设置:'light' 或 'dark' |
readonly |
boolean | false | 只读模式,禁用拖拽和编辑 |
方法 (Methods)
公共方法
组件继承自 LokiElement,主要通过属性和事件进行交互。
内部方法
| 方法名 | 参数 | 返回值 | 说明 |
|---|---|---|---|
_setupApi() |
- | void | 设置 API 客户端和事件监听 |
_loadTasks() |
- | Promise<void> | 加载任务数据 |
_getTasksByStatus(status) |
status: string | Task[] | 根据状态获取任务列表 |
_handleDragStart(e, task) |
e: Event, task: Task | void | 处理拖拽开始 |
_handleDrop(e, newStatus) |
e: Event, newStatus: string | Promise<void> | 处理拖拽放置 |
_openAddTaskModal(status) |
status: string | void | 打开添加任务模态框 |
_openTaskDetail(task) |
task: Task | void | 打开任务详情 |
_escapeHtml(text) |
text: string | string | HTML 转义防止 XSS |
_navigateTaskCards(card, direction) |
card: Element, direction: string | void | 键盘导航任务卡片 |
任务数据结构 (Task)
{
id: number | string, // 任务唯一标识
title: string, // 任务标题
status: string, // 任务状态: pending, in_progress, review, done
priority: string, // 优先级: critical, high, medium, low
type: string, // 任务类型
assigned_agent_id: number, // 分配的代理 ID (可选)
isLocal: boolean, // 是否为本地任务
fromServer: boolean // 是否来自服务器
}
使用指南
基本使用
<!-- 基础使用 -->
<loki-task-board></loki-task-board>
<!-- 指定 API URL 和项目 -->
<loki-task-board
api-url="http://localhost:57374"
project-id="1">
</loki-task-board>
<!-- 暗色主题 -->
<loki-task-board theme="dark"></loki-task-board>
<!-- 只读模式 -->
<loki-task-board readonly></loki-task-board>
JavaScript 集成
// 在 JavaScript 中使用
const taskBoard = document.createElement('loki-task-board');
taskBoard.setAttribute('api-url', 'http://localhost:57374');
taskBoard.setAttribute('project-id', '123');
document.body.appendChild(taskBoard);
// 动态修改属性
taskBoard.setAttribute('theme', 'dark');
taskBoard.setAttribute('readonly', '');
// 监听事件
taskBoard.addEventListener('task-moved', (e) => {
console.log('Task moved:', e.detail);
});
taskBoard.addEventListener('task-click', (e) => {
console.log('Task clicked:', e.detail.task);
});
taskBoard.addEventListener('add-task', (e) => {
console.log('Add task requested for status:', e.detail.status);
// 显示添加任务表单
});
框架集成示例
React
import { useEffect, useRef } from 'react';
import 'dashboard-ui/components/loki-task-board.js';
function TaskBoardComponent() {
const boardRef = useRef(null);
useEffect(() => {
const board = boardRef.current;
const handleTaskMoved = (e) => {
console.log('Task moved:', e.detail);
};
const handleTaskClick = (e) => {
console.log('Task clicked:', e.detail.task);
};
board.addEventListener('task-moved', handleTaskMoved);
board.addEventListener('task-click', handleTaskClick);
return () => {
board.removeEventListener('task-moved', handleTaskMoved);
board.removeEventListener('task-click', handleTaskClick);
};
}, []);
return (
<loki-task-board
ref={boardRef}
api-url="http://localhost:57374"
project-id="1"
theme="dark"
/>
);
}
Vue
<template>
<loki-task-board
ref="taskBoard"
:api-url="apiUrl"
:project-id="projectId"
:theme="theme"
@task-moved="handleTaskMoved"
@task-click="handleTaskClick"
@add-task="handleAddTask"
/>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue';
import 'dashboard-ui/components/loki-task-board.js';
const apiUrl = ref('http://localhost:57374');
const projectId = ref('1');
const theme = ref('dark');
const taskBoard = ref(null);
const handleTaskMoved = (e) => {
console.log('Task moved:', e.detail);
};
const handleTaskClick = (e) => {
console.log('Task clicked:', e.detail.task);
};
const handleAddTask = (e) => {
console.log('Add task:', e.detail.status);
};
</script>
事件系统
自定义事件
| 事件名 | 触发时机 | detail 数据 |
|---|---|---|
task-moved |
任务被拖拽到新列后 | { taskId, oldStatus, newStatus } |
add-task |
点击添加任务按钮时 | { status } |
task-click |
点击任务卡片时 | { task } |
API 事件监听
组件内部监听以下 API 事件:
| 事件名 | 说明 | 响应 |
|---|---|---|
TASK_CREATED |
新任务创建 | 重新加载任务列表 |
TASK_UPDATED |
任务更新 | 重新加载任务列表 |
TASK_DELETED |
任务删除 | 重新加载任务列表 |
样式主题
CSS 变量
组件使用以下 CSS 自定义属性,可通过主题系统或直接覆盖进行定制:
:host {
/* 背景色 */
--loki-bg-secondary: #1a1a1a;
--loki-bg-tertiary: #2a2a2a;
--loki-bg-card: #252525;
--loki-bg-hover: #2d2d2d;
--loki-bg-accent-muted: rgba(99, 102, 241, 0.1);
/* 文字色 */
--loki-text-primary: #ffffff;
--loki-text-secondary: #a0a0a0;
--loki-text-muted: #6b6b6b;
/* 品牌色 */
--loki-accent: #6366f1;
--loki-blue: #3b82f6;
--loki-purple: #8b5cf6;
--loki-green: #22c55e;
--loki-red: #ef4444;
--loki-yellow: #eab308;
/* 半透明色 */
--loki-red-muted: rgba(239, 68, 68, 0.1);
--loki-yellow-muted: rgba(234, 179, 8, 0.1);
--loki-green-muted: rgba(34, 197, 94, 0.1);
/* 边框 */
--loki-border: #333333;
--loki-border-light: #404040;
/* 动画 */
--loki-transition: 0.2s ease;
}
响应式布局
组件内置响应式设计:
| 断点 | 布局 |
|---|---|
| > 1200px | 4 列布局 |
| 768px - 1200px | 2 列布局 |
| < 768px | 1 列布局 |
注意事项与限制
状态处理
-
任务状态映射:组件会将任务状态转换为小写并将连字符替换为下划线,确保兼容性
// 内部转换逻辑 const taskStatus = t.status?.toLowerCase().replace(/-/g, '_'); -
乐观更新:拖拽操作先更新 UI,API 失败时会自动回滚
- 用户体验优先
- 需注意网络延迟可能导致的临时不一致
数据安全
-
XSS 防护:所有用户输入的文本都会经过 HTML 转义
_escapeHtml(text) { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } -
属性验证:组件对传入的属性进行基本验证,但建议在使用前进行数据验证
性能考虑
- 任务数量:建议单项目任务数不超过 500 个,过多任务可能影响渲染性能
- 重渲染:每次任务变更都会触发完整重渲染,可考虑虚拟滚动优化大量任务场景
错误处理
- API 失败:API 调用失败时会显示错误信息并回退到本地缓存
- 网络断开:支持本地任务操作,网络恢复后可同步
- 数据一致性:提供
refresh按钮允许手动刷新任务列表
浏览器兼容性
- 支持所有现代浏览器(Chrome、Firefox、Safari、Edge)
- 需要支持 Web Components、Shadow DOM 和 Custom Events
- IE11 及以下版本不支持
已知限制
- 固定列数:当前只支持 4 列固定布局,不支持自定义列
- 任务排序:不支持在同一列内手动排序任务
- 批量操作:不支持批量选择和操作任务
- 筛选搜索:内置不支持任务筛选和搜索功能
扩展性
组件设计考虑了一定的扩展性:
- 可通过 CSS 变量自定义主题
- 可通过事件系统集成外部功能
- 可继承
LokiTaskBoard类进行功能扩展
如需更复杂的定制,建议参考相关模块文档:
- LokiTheme - 主题系统
- LokiState - 状态管理
- LokiApiClient - API 客户端