作一個CLI版的時間管理工具(五)

作一個CLI版的時間管理工具(五)

這是我參與8月更文挑戰的第6天,活動詳情查看:8月更文挑戰git

前言

上一篇文章主要闡述了兩個指令的開發:github

  • 初始化項目模板指令:timec init <projectName>
  • 初始化記錄模板指令:timec create <filename>

本節將主要介紹:自動生成一段時間內的報告json

指望效果的指令爲:timec -or --range <startTime>_<endTime> <filename1> <filename1> .....數組

本期效果

圖片

功能開發

必定時間範圍內的報告生成

可用於週報,日報,月報的統計數據生成,方便本身覆盤一週所作的事情markdown

指令註冊

注意:省略了前幾篇裏已經出現過的指令邏輯數據結構

輕車熟路,使用option方法註冊新的可選參數:app

  • -r:表明要輸出報告
  • -R:表明要輸出的事件範圍
// 導出
commander.arguments('<filenames...>') // 多個文件/目錄
    .option('-o, --output', 'Export analysis results')
    .option('-r, --report', 'Export the result as a md report')
    .option('-R, --range [startDate_endDate]', 'A time period')
    // .action
複製代碼

再添加簡單的判斷邏輯:ide

  • -r對應的是report屬性,爲true代表啓用了這個option
  • -R對應range屬性,其值爲string類型
    • 開始與結束時間使用下劃線_分割
  • 主要關注getJSONByRangeoutPutReport這兩個方法的實現
  • 內容的讀取邏輯(content),在前幾篇的文章已經詳細介紹過了,這裏就再也不贅述
.action((filenames, cmdObj) => {
        const { output,report } = cmdObj
        // 導出
        if (output) {
            let outFileName = 'res'

            if(report){
                const {range} = cmdObj
                if(range){
                    const [startTime,endTime] = range.split('_')
                    // createFile(getFilePath(cwd, `report-${outFileName}.md`),outPutReport(getJSONByRange(content,startTime,endTime)),false)
                    // 方便觀察調用結構,展開以下
                    const outPutPath = getFilePath(cwd, `report-${outFileName}.md`)
                    const json = getJSONByRange(content,startTime,endTime)
                    const data = outPutReport(json)
                    createFile(outPutPath,data,false)
                }
            }
        }
    })
複製代碼

範圍內的json獲取

這個邏輯相對簡單:工具

  1. 先調用getJSON方法將傳入的內容轉爲json對象
    • 其中每一項數據的titleyyyy-mm-dd的日期
  2. 先調用sort方法對數據按時間從小到大排序
  3. 在使用filter方法對數據按照傳入的起止時間進行過濾篩選
  4. 最後便產生了所須要的結果
function getJSONByRange(fileContent, startTime, endTime) {
    let jsonSchema = getJSON(fileContent)
    // 從小到大排
    jsonSchema = jsonSchema.sort((a, b) => {
        const d1 = new Date(a.title)
        const d2 = new Date(b.title)
        return d1 - d2
    }).filter(v => {
        const d = new Date(v.title)
        const s = new Date(startTime)
        const e = new Date(endTime)
        return d >= s && d <= e
    })
    return jsonSchema
}
複製代碼

JSON轉報告內容

指望的報告內容格式以下oop

# 開始時間 - 結束時間
**總耗時** xxx

## 任務名
>耗時:yyyy
* 事件1
* 事件2
* 事件3

## 任務名
>耗時:yyyy
* 事件1
* 事件2
* 事件3
複製代碼

結構定下來後,我們開始對json數據進行操刀

JSON數據結構以下(複習一下)

[
  {
    "title": "2021-08-03",
    "tasks": [
      {
        "title": "任務1",
        "things": [
          {
            "time": "0.2",
            "content": "a組件"
          },
          {
            "time": "0.3",
            "content": "b組件"
          }
        ]
      },
    ]
  },
] 
複製代碼

首先使用一個數組存放每一行的數據的結果(最終md的每一行)

const res = []

// 記錄總耗時
let sumTime = 0
複製代碼

開始結束時間分別爲json對象的第一項和最後一項的title

const startDate = jsonSchema[0].title
const endDate = jsonSchema[jsonSchema.length-1].title
// 時間
res.push(`# ${startDate}${endDate}`)
複製代碼

肯定時間以後,就是任務的歸類

後面大部分操做都是使用Array.prototype.reduce,不熟悉的同窗能夠MDN查詢一下

先將全部任務收進同一個數組裏:

  • 遍歷而後用concat連接這些數組
// 過濾出全部的tasks
const allTasks = jsonSchema.reduce((pre,current)=>{
    return pre.concat(current.tasks)
},[])
複製代碼

合併相同任務(task)的事務(things)

合併前

[
  {
    "title": "任務1",
    "things": [
      {
        "time": "0.2",
        "content": "a組件"
      },
    ]
  },
    {
    "title": "任務1",
    "things": [
      {
        "time": "0.3",
        "content": "b組件"
      }
    ]
  },
]
複製代碼

合併後

[
  {
    "title": "任務1",
    "things": [
      {
        "time": "0.2",
        "content": "a組件"
      },
      {
        "time": "0.3",
        "content": "b組件"
      }
    ]
  }
]
複製代碼

肯定好先後的結構後,邏輯代碼就容易書寫了:

  • 若是pre爲空數組則直接存入
  • 遍歷已經存入的內容,判斷是否存在相同的任務
    • 不存在,則加入pre
    • 存在,則將其things加入pre.things
// 合併相同的任務
const tasks = allTasks.reduce((pre,current)=>{
    if(pre.length===0){
        pre.push(current)
        return pre
    }
    let sameTask = pre.find(v=>v.title===current.title)
    if(!sameTask){
        pre.push(current)
        return pre
    }
    sameTask.things.push(...current.things)
    return pre
},[])
複製代碼

結構整理完畢,接着就是內容的生成了:

  • 使用for...of 遍歷每個任務
  • 內部使用Array.prototype.map遍歷事務
    • 遍歷的同時將任務時間計算出來
  • 一個任務遍歷完,先添加任務耗時,再添加事務列表
  • 最後,將全部任務使用的總時間利用數組的splice方法,將其插入結果第二項

到此,生成範圍報告的邏輯就完成了

for (const taskItem of tasks) {
    res.push('')
    res.push(`## ${taskItem.title}`)
    let taskTime = 0
    let things = taskItem.things.map(thing=>{
        const {time,content} = thing
        taskTime += (+time)
        return `* ${content}`
    })
    res.push(`>耗時:${taskTime.toFixed(2)}`)
    res.push(...things)
    sumTime += taskTime
}
res.splice(1,0,`**總耗時** ${sumTime.toFixed(2)}`)
複製代碼

本部分的完整代碼地址

其它

因爲天天空閒時間有限,本文就先到這

若是讀者還感受意猶未盡,敬請期待後續更新,或先關注一下倉庫

歡迎評論區提需求,交流探討

本系列會不斷的更新迭代,直至產品初代完成

相關文章
相關標籤/搜索