OKR(Objectives and Key Results)即目标与关键成果法,可以理解为对目标完成情况的一种管理方法。
一般需要列出当前周期的目标,然后列举一些关键结果来衡量目标的完成情况。
我个人的情况是,以每两个月为一个周期设定自己的目标。最初都是用markdown记录,每次列出表格,写下目标,结果,进度,最后给自己算分数。
然而这个算分的过程每次都得重新计算,十分麻烦,而且表格也得手工维护,总之就是麻烦。于是就有了写个软件管理的想法。
正好自己主要是做后端,所以想学习下前端知识,于是把这款软件定位在web应用上。
1. 产品设计
先给自己写了个简单的PRD(产品需求文档),大概自己能看懂就ok,理了理思路。传送门
2. 环境配置
3. 新建项目
使用命令vue ui
开启图形界面,新建项目,有个默认初始化git选项,按照喜好可要可不要
“预设”选项,选择“手动”,然后勾上这些包vuex
和router
,不选包linter
之后勾选使用html5历史模式
进入项目web管理页面后,添加element-ui
模块
项目建立后导入到IDEA,就可以开始编写代码了。
4. 难点记录
这一部分只挑一些重点来说,剩余的可以参考git仓库代码:ot
主要用了两个页面,App.vue
作为整个门面,保持不变,主要用于展示OKR的可选月份,图中红色圈出的部分即是。Home.vue
承接OKR的展示部分,为图中的非红色部分。
月份展示
提前算好月份列表,默认显示当前双月的目标。这里用v-model指定默认打开的tab。详细参考:官方文档-tabs
注意<router-view>
别放在循环里面,这样会产生多个,实际上我们只需要一个。
数据传递
当点击月份标签的时候,使用$router.push
把月份信息传递到Home.vue
。这里有个点要注意,push
方法在推送的URL和当前URL相同时,会在控制台报错。这里加了个catch忽略掉报错。
this.$router.push({path: '/okr/', query: {'month': tab.label}}).catch(() => {});
由于使用的是同一个Home.vue
,所以靠query词来区分页面。改写router/index.js
来映射到Home.vue
const routes = [
{
path: '/okr/*',
name: 'home',
component: Home
}
];
Home.vue考虑
本来只用了<el-table>
,后来发现需要标题,所以在外面嵌套了<el-card>
,最终布局是:
固定最后一行百分比
为了保证最后百分比总和为100%,就打算固定最后一行为不可更改的形式。
这里用了一个字典存是否可以修改hitBox: {}
,key是目标+结果+列名
,可以唯一确定一个单元格。
v-slot
用于获取父组件的数据,使其可以传递下来,具体参考:编译作用域
数据刷新
有两种情况页面需要刷新。一个是当双击单元格时,此时要显示单元格成编辑框,所以必须刷新页面。另一个是数据变动时,此时需要刷新页面。所以要特别注意hitBox
,在第一种情况下,不需要刷新,否则单元格又变回原样。
// 同样的页面,不需要初始化的数据
if (!isOldPage) {
this.hitBox = {};
this.editData = false;
}
数据直接用localstorage存,使用方式就是k-v,将结构化数据序列化后使用即可。
let tableData = localStorage.getItem(this.month);
tableData = JSON.parse(tableData);
5. 部署到github pages
官方说的很明白:传送门
部署完之后就可以愉快地使用啦~
6. 效果
项目github地址:https://github.com/GooZy/ot
部署页面:https://goozy.github.io/ot/