03 开源任务管理系统:创建一个任务

  • 03 开源任务管理系统:创建一个任务已关闭评论
  • 24 次浏览
  • A+
所属分类:Web前端
摘要

GitHub 地址:https://github.com/dom-bro/task-manager虽说是一个任务管理系统,但简单地讲,其实就是任务的增删改查(CRUD)。


GitHub 地址:https://github.com/dom-bro/task-manager

虽说是一个任务管理系统,但简单地讲,其实就是任务的增删改查(CRUD)

其中最重要的又当属,即创建任务,此为数据之源,删改查都依赖于它所产生的数据。

交互设计

凭着程序员的直觉,最初做成了一个表单如下图,表单项也对应了数据库中的表的字段,简单直接。

03 开源任务管理系统:创建一个任务

后来经过同事的建议,对比了 towerteambitionworktile 这些成熟产品的交互设计。

tower 看板如下图所示

03 开源任务管理系统:创建一个任务

teambition 看板如下图所示

03 开源任务管理系统:创建一个任务

worktile 看板如下图所示

03 开源任务管理系统:创建一个任务

发现看板形式确实是比较适合任务的展现的。于是最终改版为如下任务卡片看板

03 开源任务管理系统:创建一个任务

任务的创建和展现全部放在一块看板上。交互路径更短,更易用。

数据库表结构设计

作为一个地地道道的前端,数据库知识依然来源于大学时期的残存。为了最小化学习成本,自然而然选择了 MongoDB。使用 MongoDB
可以简单地理解为操作 json 对象,写数据库也只是把一堆 json 对象存到了数据库里。

MongoDB 为每个主流编程语言都提供了相应的 driver,直接给 node 提供了一个 npm 包。

npm i mongodb

接下来就开始设计数据库里的第一张表,任务表。任务表的数据结构完全由一个任务的组成因素去映射。

想一想实际工作中的任务是怎样的

  • 任务标题

    显然必不可少,除了这个字段必选,其他都是可选项

  • 任务排期

    至关重要,是之后汇总周报,季报的依据。想必在座的各位都被催过排期吧

  • 需求文档

    链接也好,文字描述也好,凡是需求相关的通通放进来,好记性不如烂笔头。什么!没有需求文档!全靠嘴说脑记!珍惜生命,趁早放手吧。然鹅这只是辅助记录而已,对频繁需求变更这个老大难问题着实是无能为力哈哈

  • 相关人员

    产品,UI,后端,测试,各个岗位的对接人得清楚。

  • 项目分支

    项目再多,分支再乱,也别搞错哦。分支搞不对,加班两行泪。

好了,为了简单起见,先暂定这几个字段吧。其他字段可根据需要再增加。

目前任务的数据结构大致如下

{   title: String, // 任务标题   schedule: [String, String], // 任务排期,[开始时间,结束时间]   doc: { // 相关文档     pm: String, // 需求文档     ui: String, // 设计文档     api: String, // 接口文档   },   workmate: { // 相关人员     pm: Object, // 产品     ui: Object, // UI     api: Object, // 后端     qa: Object, // 测试   },   repos: [ // 项目分支     {       name: String, // 项目名称       branch: String, // 分支名称     }   ],   status: String, // 任务状态 未开始|开发中|已提测|已完成 } 

后端实现

这里只需要一个创建的接口即可

在开发接口的过程中可能需要频繁重启服务来测试接口,所以在开始开发接口之前,隆重引入一个新轮子 nodemon,服务端进程就由它来守护,实现文件变更时重启服务器。

可以在根目录给 nodemon 一个配置文件 nodemon.json,简单配置下

{   "watch": [     "server.js"   ] } 

这样在改变 server.js 的时候服务器就会自动重启

好了,接下来就开始写创建接口

由于是数据库写入,这显然是一个 POST 请求,koa 需要一个中间件来解析 post 请求出入的参数。

npm i koa-bodyparser

使用起来也极其简单,koa 中间件使用方式都一样

import bodyparser from 'koa-bodyparser' app.use(bodyparser()) 

万事俱备,只欠写入数据库了

import { MongoClient, ObjectId } from 'mongodb' // 连接数据库 const client = new MongoClient('mongodb://localhost:27017')  router.post('/task/upsert', async (ctx, next) => {   // 要操作的数据库   const db = client.db('task-manager')   // 要操作的表,mongodb 中叫做集合   const collection = db.collection('task')   // post 请求的参数经 bodyparser 后放在 ctx.request.body 里   const doc = ctx.request.body   const { _id } = doc   const result = await collection.updateOne(     // _id 是 mongodb 默认主键名,ObjectId 可用于生成一个唯一 id     { _id: _id || ObjectId() },     { $set: doc },     // upsert 表示存在则更新,不存在则插入     { upsert: true }   )   // 接口返回   ctx.body = {     doc,     result,   } }) 

这里只需要关注一个 api,mongodb 的 db.collection.updateOne(),用于数据的插入或更新。

前端实现

根据交互设计,任务的查看和创建都在同一个页面,即看板视图。

在 components 目录新建一个组件 NewTaskCard.vue

关键代码就是请求创建任务接口

// src/components/NewTaskCard.vue async submitNewTask () {   await axios.post('/task/upsert', this.task) }, 

由于服务器域名和开发服务器域名不一致,所以需要在 main.js 里设置一下服务端的域名

// main.js axios.defaults.baseURL = `${location.protocol}//${location.hostname}:${SERVER_PORT}` 

为了简单起见,看板暂时先放在 src/pages/Home.vue

关键代码就是定义任务的状态

// src/pages/Home.vue taskStatus: {   draft: '未开始',   dev: '开发中',   qa: '已提测',   done: '已完成', }, 

最后

实现效果如下

03 开源任务管理系统:创建一个任务

正文结束。点击查看代码变更

闲言碎语

mongodb or mongoose

mongodb 包是 MongoDB 官方给 node.js 出的 driver,通过它就可以直接调用数据库的 api,就像直接在 shell 中使用数据库一样方便。

mongodb 相对传统 MySQL 这种数据库,最重要的区别就是没有了表的概念,取而代之使用集合,集合中的每一条数据甚至不需要结构相同。

例如 mongodb 的集合中可能存的是这样子的数据

[   { a: 1, b: true },   { a: 'DOM', c: [ { d: null } ]} ] 

一句话,自由,随便存,只要是 json 就能往里存。

mongoose 则是为了重现表的概念,核心概念是 Schema 和 Model,Schema 用来定义数据结构,Model 用来定义表。这样使得集合中的数据结构严整统一,少有冗余,像一张 excel 表格一样。当然 mongoose 还提供了其它高级特性,但我还不太熟悉,这里不再赘述。

为了减少 mongoose 的概念和知识产生的额外学习成本,这里就选择直接自由自在的操作 mongodb 吧

有对 mongoose 了解的同学欢迎评论区补充相对 mongodb 的优势。