前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >项目管理系统自研之路

项目管理系统自研之路

作者头像
测试加
发布2022-12-05 12:15:32
6720
发布2022-12-05 12:15:32
举报

背景

我司的项目管理比较乱,核心数据存在了外部购买的系统上"teambition",比如项目排期、测试用例、bug等数据。PMO同学在做数据统计的时候,先要从teambition倒出一份原始数据,再按照PMO约定的规则计算人效,计算的效率极低。

项目管理系统主要目的最开始是为了解决提高PMO手动出人效的效率,核心是计算产研人员效能。

当时PMO计算人效的公式是内部协商出来的: 1、当研发阶段的时候,开发人效+1 2、当测试阶段的时候,开发人效+0.5、测试人效+1 3、当前上线阶段,开发人效+0.5、测试人效+1 等等还有一些公式。

基于上面的痛点,我们决定开发一条可视化项目管理平台,直观展示研发效能数据。

实现方案

1、经过调研在teambition中,如果达成pmo的效果,需要给teambition提需求,经过沟通比较难实现。

2、自研项目管理系统,通过同步teambition把数据存储到研项目管理系统,把计算人效逻辑封装到后端服务中。

自研系统好处: 1)、锻炼后端开发技术 2)、PMO、产品、研发共建系统,拉起目标 3)、向上管理工具

自研系统缺点: 1)、产品缺乏架构设计 2)、项目质量一般 3)、服务架构单一

业务架构

如下图是当时PMO计得产品原型图,包含从项目管理角度出发覆盖研发效能到质量分报告,涉及功能模块比较全。

首页图表

需求维度

质量分报告

如下图是,思维导图梳理的产品架构:

开发架构

前端

参考vue admin平台,隐藏不需要代码即可,开箱即用。

代码语言:javascript
复制
https://github.com/PanJiaChen/vue-element-admin

依赖如下库

代码语言:javascript
复制
vue2.x、axios、echarts、element-ui、stylus等库

后端

后端系统主要使用django全家桶开发,类库比较多、并且ORM功能强大、部署方便。

代码语言:javascript
复制
django全家桶、 mysql 、redis 、request 、gunicorn等库

经过几个迭代以后,代码越来越多,所有功能模块都写到一个服务上,变得越来越重。应该考虑微服务架构解耦代码问题。

定时任务

1、jenkins

jenkins主要做同步数据脚本使用,配置灵活方便。

2、apscheduler

apscheduler库,为了实现内部方法做定时任务使用。

登录

接入公司的单点sso登录

每个公司为了统一账号密码登录控制,都会由运维部门统一认证后,才能登录各个子系统。目的在于安全、统一管理账号密码。

下图是单点登录的首页,支持账号密码登录或者扫描二维码登录。

接入后,登录后可以拿到姓名、岗位等信息,方便后续权限管理模块开发。

接单点登录系统,一般需要和单点登录系统注册,注册后会把给clientid和clientsecret两个参数,为了安全性考虑。

需要在前端启动首页的时候,如果没有登录就去访问登录首页。

在router.beforeEach函数中,从cookie中获取token,如果没有token跳转到登录页面。

代码语言:javascript
复制
var hasToken = getCookie('token')
  var myDate = new Date()
  const logs = {}
  const newDate = formatDate(myDate, 'yyyy-M-d h:m:s')
  logs.username = hasToken
  logs.content = newDate + ' ' + hasToken + ' ' + '登录'
  logs.type = "logs"
  createLogs(logs).then(res => {
  })
  if (hasToken) {
    if (to.path === '/login') {
      next({ path: '/' })
      NProgress.done()
    } else {
      const hasPerms = store.getters.perms && store.getters.perms.length > 0
      if (hasPerms) {
        next()
      } else {
        try { 
          const { perms } = await store.dispatch('user/getInfo')
          const accessRoutes = await store.dispatch('permission/generateRoutes', perms)
          router.addRoutes(accessRoutes)
          history record
          next({ ...to, replace: true })
        } catch (error) {
          NProgress.done()
        }
      }
    }

登陆页面的逻辑,首页会判断是有code,没有的话调用接口获取code,code参数通过前端页面拦截获取,所以这样是很安全的.拿到code再去换token,最后获取用户信息的接口携带token参数,跳转到首页。

代码语言:javascript
复制
mounted() {
this.getTokenByCode()
},
created() {
this.goSSO()
},

goSSO() {
  if (!this.code) {
    var sso_url =
      'https://sso.xxxx.com/oauth/authorize/?client_id=' +
      client_id +
      '&redirect_uri=' +
      redirect_uri +
      '&response_type=code'
    // console.log("sso_url is " + sso_url);
    window.location.href = sso_url
  }
},

getTokenByCode() {
  if (this.code) {
    // SSO登录回调
    const params = {
      code: this.code,
      client_id: client_id,
      client_secret: constclient_secret,
      grant_type: 'authorization_code',
      redirect_uri: redirect_uri
    }
    // console.log(params);
    const axiospost = axios.create({
      timeout: 500000,
      headers: { 'Content-Type': 'multipart/form-data' },
      withCredentials: true
    })
    const formData = new FormData()
    for (const k in params) {
      formData.append(k, params[k])
    }
    axiospost.post(tokenURL, formData).then(res => {)
      const access_token = res.data['access_token']
      this.getTokenByUserName(access_token)
    })
  }
},
    getTokenByUserName(access_token) {
      console.log('getTokenByUserName')
      const axiospost = axios.create({
        timeout: 500000,
        headers: {
          'Content-Type': 'multipart/form-data',
          Authorization: 'Bearer ' + access_token
        },
        withCredentials: true
      })
      axiospost.get(infoURL, null).then(res => {
        const username = res.data['name'])
        if (username) {
          setCookie('userName', username, 7)
          this.$router.push('/dashboard')
        } else {
          this.$router.push('/login')
        }
      })
    }

共享登录状态

内部有很多系统都接入了单点登陆系统,为了能登陆一次系统后,再登陆其他系统就不需要再登陆,需要共享登陆状态。

如果设置cookie的话,把cookie种在根域下就可以,这样就通过cookie完成了共享登录状态。

代码语言:javascript
复制
export function setCookie(cname, cvalue, exdays) {
  var d = new Date()
  d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000))
  var expires = 'expires=' + d.toUTCString()
  document.cookie = cname + '=' + cvalue + '; ' + expires + ';' + 'domain=.xxxx.com;'
}

首页

数据来源

由于我们和"teambition"第三方公司签约到很久,需求数据、bug、测试用例都存在了 "teambition"平台。所以需要使用对接"teambition"的api完成数据同步。

teambition接口鉴权这款还是比较复杂的,首先有管理员账号并且生成对应的token。

使用jwt对参数进行编码解码等一系列操作生成token,放在请求的header中。

代码语言:javascript
复制
def get_token():
    """
    生成token
    :return:
    """
    payload = {}
    iat = math.floor(int(time.time()) / 3600 * 3600)
    payload['iat'] = iat
    payload['_appId'] = appId

    headers = {
        "alg": "xxx",
        "typ": "JWT"
    }
    token = jwt.encode(payload, appSecret, headers=headers).decode('utf-8')
    return token

teambition的官方接口文档,如果对接第三方系统,没有好的接口文档,开发的过程中会很痛苦。

代码语言:javascript
复制
https://open.teambition.com/help

查询任务,只需要把task id传过去就行了。

还支持tql查询,扩展性比较强。

增量同步

因为增量同步可以减少同步时间,但是可能会存在同步数据存在误差。

主要有几个原因,需要保持新增、删除、变更的数据一样,这样就需要同步脚本有大量的逻辑判断。所以写完脚本,需要测试各种场景保障数据的一致性。

全量同步

这种用法比较少,暴力做法就是删库重新同步。

webhook方式同步

当"teambition"的数据发生变化,主动给我们服务发送请求告知数据变化。这种可以满足数据实时更新,但是需要服务端有逻辑判断。

数据管理

迭代填报

迭代填报主要是从"teambition"同步过来数据,这里只做展示,一般不会手动改数据。

人事管理

人事管理对接了"薪人薪事"系统,可以拿到人员状态。

请假管理

请假管理需要手动填报,具体因为很多人请假不走"薪人薪事"系统,每周五时候pmo手动同级。

需求管理

需求管理也是同步"teambition"空间的数据,需求有几种流转状态,当状态变更时候需要记录。

数据展示

业务线人效统计

从业务线唯独可以清晰的知道,每个业务线的数据。

按职能人效统计

因为我们公司前端在业务线干活,但是隶属统一前端leader管理,职能人效可以发现谁不忙就让谁补其他人得需求开发。

人员饱和度看板

人员饱和度主要是想细化到每人身上,关注每个人得产出。

项目投入统计

App发版日历

App发版日历主要想看本次发版的需求,共涉及多少个需求。

PMO项目人员统计

人事数据统计

周报分析统计

项目总结统计

项目管理甘特图

项目各阶段周期

系统设置

当时有个OKR是,想看看我们得系统使用率,所以做了埋点数据统计。

权限管理

权限管理是通过vue的动态路由实现和并且结合自定义指令控制按钮权限。

菜单控制

项目迭代的心得

1、每次版本开发前,PMO会做立项会。

2、每次版本发布前,PMO会做产品发布会。

3、内部系统一样做好技术文档沉淀。

4、项目完成后做复盘。

5、测试环境和线上环境隔离。

6、内部系统一样提bug,标明优先级。

落地效果

有几点用: 1、老板的确很喜欢这种系统。

2、通过数字化、图表化,反映研发效能。

3、产品也喜欢看谁有排期。

不好的点: 1、开发很diss这个系统,也能明白。

2、有一定的维持成本。

总结

研发效能开发会是未来趋势,大厂都开始自研内部效能系统了并且开始商业化了,为啥大家不计成本开始做研发效能呢,我觉得可能有几点思考:

1、随着自动化测试体系搭建,需要有一套流水线串联自动化测试。

2、需求迭代过程产生的数据需要被存储归档。

3、项目过程和结果需要被度量。

4、通过效能平台打通各个内部系统,串联研发流程。

回到项目管理系统本身,在小公司可能测开就去完成了,但是是否能成一个比较好得产品还是比较难,在大厂会是研发效能去当一个产品迭代开发,服务整体研发团队.从另外一个角度来开,QA应该从这个研发效能去看问题,这样才能看到更多团队内得问题。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-09-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 测试加 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 实现方案
  • 业务架构
  • 开发架构
    • 前端
      • 后端
        • 定时任务
        • 登录
          • 接入公司的单点sso登录
            • 共享登录状态
              • 首页
              • 数据来源
                • 增量同步
                  • 全量同步
                    • webhook方式同步
                    • 数据管理
                      • 迭代填报
                        • 人事管理
                          • 请假管理
                            • 需求管理
                            • 数据展示
                              • 业务线人效统计
                                • 按职能人效统计
                                  • 人员饱和度看板
                                    • 项目投入统计
                                      • App发版日历
                                      • PMO项目人员统计
                                      • 人事数据统计
                                      • 周报分析统计
                                      • 项目总结统计
                                      • 项目管理甘特图
                                      • 项目各阶段周期
                                      • 系统设置
                                      • 权限管理
                                      • 落地效果
                                      • 总结
                                      相关产品与服务
                                      访问管理
                                      访问管理(Cloud Access Management,CAM)可以帮助您安全、便捷地管理对腾讯云服务和资源的访问。您可以使用CAM创建子用户、用户组和角色,并通过策略控制其访问范围。CAM支持用户和角色SSO能力,您可以根据具体管理场景针对性设置企业内用户和腾讯云的互通能力。
                                      领券
                                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档