GitHub 地址:https://github.com/dom-bro/task-manager
雖說是一個任務管理系統,但簡單地講,其實就是任務的增刪改查(CRUD),
其中最重要的又當屬增,即創建任務,此為資料之源,刪改查都依賴于它所產生的資料,
互動設計
憑著程式員的直覺,最初做成了一個表單如下圖,表單項也對應了資料庫中的表的欄位,簡單直接,
后來經過同事的建議,對比了 tower,teambition,worktile 這些成熟產品的互動設計,
tower 看板如下圖所示
teambition 看板如下圖所示
worktile 看板如下圖所示
發現看板形式確實是比較適合任務的展現的,于是最終改版為如下任務卡片看板
任務的創建和展現全部放在一塊看板上,互動路徑更短,更易用,
資料庫表結構設計
作為一個地地道道的前端,資料庫知識依然來源于大學時期的殘存,為了最小化學習成本,自然而然選擇了 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: '已完成',
},
最后
實作效果如下
正文結束,點擊查看代碼變更
閑言碎語
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 的優勢,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/502594.html
標籤:其他
上一篇:ts的介面和泛型的基本語法
下一篇:【Telerik和Kendo UI組件】上海道寧與progress為您提供Web、移動和桌面構建功能更豐富的現代體驗
