粥里有勺糖

vuePress-theme-reco 粥里有勺糖    2018 - 2023
粥里有勺糖 粥里有勺糖

Choose mode

  • dark
  • auto
  • light
关于我
备战春秋
  • 心得总结
  • 校招考点汇总
  • 面经汇总
  • 复习自查
技术笔记
  • 技术教程
  • 模板工程
  • 源码学习
  • 技术概念
  • 个人作品
  • 学习笔记
计算机基础
  • 算法与数据结构
  • 操作系统
  • 计算机网络
  • 设计模式
  • 剑指offer
大前端
  • javascript
  • vue
  • html
  • css
  • 🌏浏览器专题
  • Web性能优化
  • regexp
  • node
面试
  • 问解
  • javascript
  • css
  • 手撕代码
  • 性能优化
  • 综合问题
  • 面经汇总
  • 小程序
手撕代码
  • 数据结构与算法
  • javascript
  • css
个人站点
  • GitHub (opens new window)
  • 博客园 (opens new window)
  • 掘金 (opens new window)
线上作品
  • 轻取(文件收集) (opens new window)
  • 个人图床 (opens new window)
  • 考勤小程序 (opens new window)
  • 时光恋人 (opens new window)
  • 在线简历生成 (opens new window)
留言板
Github (opens new window)
author-avatar

粥里有勺糖

285

文章

40

标签

关于我
备战春秋
  • 心得总结
  • 校招考点汇总
  • 面经汇总
  • 复习自查
技术笔记
  • 技术教程
  • 模板工程
  • 源码学习
  • 技术概念
  • 个人作品
  • 学习笔记
计算机基础
  • 算法与数据结构
  • 操作系统
  • 计算机网络
  • 设计模式
  • 剑指offer
大前端
  • javascript
  • vue
  • html
  • css
  • 🌏浏览器专题
  • Web性能优化
  • regexp
  • node
面试
  • 问解
  • javascript
  • css
  • 手撕代码
  • 性能优化
  • 综合问题
  • 面经汇总
  • 小程序
手撕代码
  • 数据结构与算法
  • javascript
  • css
个人站点
  • GitHub (opens new window)
  • 博客园 (opens new window)
  • 掘金 (opens new window)
线上作品
  • 轻取(文件收集) (opens new window)
  • 个人图床 (opens new window)
  • 考勤小程序 (opens new window)
  • 时光恋人 (opens new window)
  • 在线简历生成 (opens new window)
留言板
Github (opens new window)
  • wheel

    • 个人作品
    • 时间管理CLI工具
      • 做一个CLI版的时间管理工具(一)
      • 做一个CLI版的时间管理工具(十)
      • 做一个CLI版的时间管理工具(11)
      • 做一个CLI版的时间管理工具(12)
      • 做一个CLI版的时间管理工具(13)
      • 做一个CLI版的时间管理工具(14)
      • 做一个CLI版的时间管理工具(15)
      • 做一个CLI版的时间管理工具(二)
      • 做一个CLI版的时间管理工具(三)
      • 做一个CLI版的时间管理工具(四)
      • 做一个CLI版的时间管理工具(五)
      • 做一个CLI版的时间管理工具(六)
      • 做一个CLI版的时间管理工具(七)
      • 做一个CLI版的时间管理工具(八)
      • 做一个CLI版的时间管理工具(九)
    • 组装个支持记笔记的CodePen
    • ESCheck工具原理解析及增强实现
    • 一款检测代码中TODO的eslint插件
    • 实现一个Web UI检测(视觉走查)工具ing
    • 从0-1实现文件下载CLI工具
    • 内联JS处理(ES语法降级&内容压缩)
    • Node CLI工具原理解析
    • 我打造的在线简历生成应用
    • 助你轻松编写与分享snippet的VsCode插件
    • SourceMap解析CLI工具实现
    • 一个通过NPM包共(分)享代码块的解决方案
    • 实践:给女朋友个性化定制应用-体重记录(一)
    • 实践:给女朋友个性化定制应用-体重记录(二)
    • 实践:给女朋友个性化定制应用-体重记录(三)

做一个CL版的时间管理工具(六)

vuePress-theme-reco 粥里有勺糖    2018 - 2023

做一个CL版的时间管理工具(六)

粥里有勺糖 2021-08-07 技术笔记个人作品CLI工具

# 做一个CLI版的时间管理工具(六)

# 前言

上一篇文章主要阐述了生成一段时间内的报告指令:

  • timec -or --range <startTime>_<endTime> <filename1> <filename1> .....

有时候期望直接导出的某一天,某一月,甚至某一年的数据,为此将会拓展几个日期相关的指令

  • 某一天:timec -or --day [date]
  • 某一月:timec -or --month [month]
    • 将默认为今年
  • 某一年:timec -or --year [year]
  • 某年某月:timec -or -Y [year] -M [month]
    • --month 与 --year组合使用
    • 其中-M,-Y分别是上述两个指令的缩写

除了这部分内容,本节也将会进入新的篇章,开始开发使用指令管理任务与事务

本文将会涉及任务相关的指令开发:timec task [name]

# 本期效果

图片

# 功能开发

本部分将会省略五官代码(前几篇文章已出现过)

# 日期相关指令

# 具体到天

首先是指定到某一天:

  • 通过option注册可选参数
  • 通过cmdObj的day属性拿到用户传入的值
.option('-D, --day [date]', 'One day')
// 省略actions code
const { day } = cmdObj
1
2
3

对输出报告的函数进行改造封装:

  • 参数分别是开始时间与结束时间
    • 这样其余几个可选参数指令也可直接复用
const output = (s, e) => {
  const outPutPath = getFilePath(cwd, `report-${outFileName}.md`)
  const json = getJSONByRange(content, s, e)
  if (json.length === 0) {
      console.log('没有符合条件的数据');
      return
  }
  const data = outPutReport(json)
  createFile(outPutPath, data, false)
  console.log(`导出成功`);
}
1
2
3
4
5
6
7
8
9
10
11

判断日期是否存在,存在则直接导出

  • 开始与结束时间都是传入的日期
if (day) {
    return output(day, day)
}
1
2
3

# 具体到月

老规矩先注册相关指令

.option('-M, --month [month]', 'One month')
1

如果只有月,那么默认年就是今年,起止时间分别是

  • nowYear-month-01
  • nowYear-month-days

插播一条技巧:如何快速获取某年某月的天数:

  1. Date构造函数支持传入年,月,日三个参数的函数重载
  2. 其中月是从0开始计算:"1-12"分别对应"0-11"
  3. 当日部分的参数传入0时,表示上月最后一天的日期
  4. 此时再调用getDate方法获取日期,则获取到目标月份的天数

例如:2021-08月的天数:

  • new Date(2021,8,0)
  • 标识2021年9月开始的前一天日期,即2021年8月31日
  • getDate返回结果即为31
const days = new Date(year,month,0).getDate()
1

导出逻辑如下:

  • 今年的年份通过new Date().getFullYear()获取
if (month) {
    const year = new Date().getFullYear()
    return output(`${year}-${month}-01`, `${year}-${month}-${new Date(year, month, 0).getDate()}`)
}
1
2
3
4

# 具体到年

如果是年,那么起止时间分别就是:

  • year-01-01
  • year-12-31

这个没得太多说法,轻车熟路写好

.option('-Y, --year [year]', 'One year')
// ...more code
if (year) {
    return output(`${year}-01-01`, `${year}-12-31`)
}
1
2
3
4
5

# 具体到某年某月

这个就是-M与-Y参数组合使用时的场景

只需要将上述两种导出方式的逻辑做一个合并即可,逻辑简单

if (year && month) {
    return output(`${year}-${month}-01`, `${year}-${month}-${new Date(year, month, 0).getDate()}`)
}
1
2
3

几个日期相关的指令搞完,接着就开始整任务相关的指令

# 任务管理指令

指令格式如下

timec task [name]
1

name参数是可选的,有如下几种逻辑:

  • 当name为空时,展示所有的任务,并标记正在进行中的任务
  • 当name不存在时,将其添加进任务列表
  • 当name存在时,将其设置为正在进行中的任务

理清逻辑后,进入开发

# 初始化配置文件

在项目工程的根目录创建一个.config/record.json文件

/Users/sugar/Documents/fe-project/time-control
├── bin
├── src
├── test
├── .config
├────└──record.json
└── test2.md
1
2
3
4
5
6
7

配置文件结构如下:

{
    "recordFilepath": "",
    "tasks": [],
    "defaultTaskIdx": -1,
    "thing": {
        "name": "",
        "startTime": "2021-01-01",
        "endTime": "2021-12-31",
        "pauseTime": "2021-12-26"
    }
}
1
2
3
4
5
6
7
8
9
10
11

这里将主要用到tasks与defaultTaskIdx两个属性,前者记录所有的任务,后者记录当前正在进行的任务

# 注册指令

使用commander.command注册指令:

  • 其中使用[]包裹的参数标识可选参数
/**
 * 创建任务、切换任务、查看任务列表
 */
commander.command("task [name]")
    .alias('t')
    .description('check tasks/add task/checkout task')
    .action((name) => {
        // ...code 后文介绍
    })
1
2
3
4
5
6
7
8
9

配置文件的路径

  • 通过__dirname与配置文件的相对路径定位配置文件
const configPath = path.join(__dirname, '../.config/record.json')
1

通过require方法引入json配置文件

  • 引入的内容就是一个对象,无需调用JSON.parse进行转换
const config = require(configPath)
1

下面就到具体的业务逻辑代码

  • 先判断是否传入任务名name
    • 没有,判断是否有任务,有则顺序打印,无则打印提示信息
  • 如果任务名不存在,则加入任务列表tasks
    • 存在,则将这个任务设置为正在进行的任务,即更新defaultTaskIdx的值
  • 最后更新配置文件的内容
const { tasks, defaultTaskIdx } = config
const idx = tasks.findIndex(v => v === name)
if(!name){
    if(tasks.length===0){
        console.log('no tasks, you can use command add task');
        console.log('timec task [name]');
        return 
    }
    tasks.forEach((v,i)=>{
        let mark = '[ ]'
        if(i===+defaultTaskIdx){
            mark = '[*]'
        }
        console.log(mark,v);
    })
    return
}
if (idx === -1) {
    tasks.push(name)
    if(tasks.length===1){
        config.defaultTaskIdx = 0
    }
    console.log('add task success');
}else{
    config.defaultTaskIdx = idx
    console.log('now use task:',tasks[idx]);
}
writeFileSync(configPath,JSON.stringify(config))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

这个指令就开发完了,时间仓促,代码质量可能不会太高

TODO:后续优化

# 小结

到目前为止已经支持如下指令:

图片

这些指令都还不是最终版本,由于时间太紧凑,设计时间也较短,后期会不断完善

# 其它

由于每天空闲时间有限,本文就先到这

如果读者还感觉意犹未尽,敬请期待后续更新,或持续关注一下仓库 (opens new window)的状态

欢迎评论区提需求,交流探讨

本系列会不断的更新迭代,直至产品初代完成

  • 仓库地址 (opens new window)
Edit this page (opens new window)
Last Updated: 2022/5/15 12:46:34