Julin
1 year ago
5 changed files with 536 additions and 228 deletions
@ -0,0 +1,83 @@ |
|||||
|
module.exports = [ |
||||
|
// 硬件产品化系列
|
||||
|
'分布式数据采集节点', |
||||
|
'称重采集仪', |
||||
|
'振动采集仪', |
||||
|
'云振动采集仪', |
||||
|
'地灾产品', |
||||
|
'模块化动态采集模块', |
||||
|
'光电扰度仪', |
||||
|
'移动测斜仪', |
||||
|
'光纤光栅解调仪', |
||||
|
'塔吊监测', |
||||
|
'水质在线监测', |
||||
|
'扬尘在线监测', |
||||
|
'分布式数据采集系统网关\\/节点', |
||||
|
'静力水准仪', |
||||
|
'振弦采集仪', |
||||
|
'分布式GPRS节点', |
||||
|
'一体化振动\\/测斜', |
||||
|
'磁通量产品', |
||||
|
'振弦类传感器', |
||||
|
'盒式固定测斜仪', |
||||
|
'导轮式固定测斜仪', |
||||
|
'外购传感器', |
||||
|
'多功能静态数据采集仪', |
||||
|
'激光测距仪', |
||||
|
'DTU-通讯设备', |
||||
|
'分布式振弦数据采集模块', |
||||
|
'加速度计', |
||||
|
'聚醚管&聚安酯管', |
||||
|
'硬件机械辅材设计', |
||||
|
'地质灾害监测预警监测设备-一体式倾角/加速度/裂缝计(FS-YTZD-QJ/JS/LF)', |
||||
|
'微型应变计', |
||||
|
'FS-RTU-P4', |
||||
|
'水利RTU FS-SL-RTU', |
||||
|
'国产化MCU替代', |
||||
|
'智能空气净化器(FS-KJ02)', |
||||
|
'模块化-多功能静态数据采集仪(FS-M24)', |
||||
|
'微型振弦采集仪(FS-iVW)', |
||||
|
'分布式节点', |
||||
|
'无线倾角传感器', |
||||
|
'高支模监测系统V3.00', |
||||
|
'振弦式温度计', |
||||
|
'高精度渗压计', |
||||
|
'高精度渗压计开发项目', |
||||
|
'智芯系列振弦产品开发项目', |
||||
|
'一体化水位传感器', |
||||
|
'分布式采集节点(FS-LPWAN02-LORA/4G/NB)', |
||||
|
|
||||
|
// 第三方检定
|
||||
|
'UI设计', |
||||
|
'第三方检定', |
||||
|
'第三方检定支撑', |
||||
|
|
||||
|
// 测试部
|
||||
|
'测试部', |
||||
|
|
||||
|
// 软件研发部项目集
|
||||
|
'软件研发部日常工作', |
||||
|
|
||||
|
// 外场故障
|
||||
|
'外场故障', |
||||
|
|
||||
|
// ci-cd
|
||||
|
'Jenkins集成', |
||||
|
'禅道', |
||||
|
'研发看板系统', |
||||
|
|
||||
|
// 硬件研发--嵌入式开发
|
||||
|
'固件库开发', |
||||
|
'单片机开发', |
||||
|
'linux开发', |
||||
|
'上位机开发', |
||||
|
|
||||
|
// 测试部
|
||||
|
'测试部门', |
||||
|
|
||||
|
// 硬件研发部项目型任务
|
||||
|
'硬件研发部任务', |
||||
|
|
||||
|
// 软件共性技术研究
|
||||
|
'共性技术', |
||||
|
]; |
@ -0,0 +1,225 @@ |
|||||
|
const request = require('superagent'); |
||||
|
const moment = require('moment'); |
||||
|
const productExcluded = require('../../config-product-excluded'); |
||||
|
|
||||
|
module.exports = { |
||||
|
entry(app, router, opts) { |
||||
|
async function auth() { |
||||
|
const session = await request.get('https://pms.anxinyun.cn/api-getSessionID.json'); |
||||
|
const sessionData = JSON.parse(session.text).data; |
||||
|
const { sessionName, sessionID } = JSON.parse(sessionData); |
||||
|
|
||||
|
const loginInfo = await request |
||||
|
.post('https://pms.anxinyun.cn/user-login.json') |
||||
|
.set({ 'Content-Type': 'application/x-www-form-urlencoded' }) |
||||
|
.query({ [`${sessionName}`]: sessionID }) |
||||
|
.send({ account: 'admin', password: 'Fashion123' }); |
||||
|
|
||||
|
app.fs = app.fs || {}; |
||||
|
app.fs.session = { sessionName, sessionID }; |
||||
|
} |
||||
|
|
||||
|
(async function () { |
||||
|
await auth(); |
||||
|
setInterval(async () => { |
||||
|
await auth(); |
||||
|
}, 1200000); // 每 20分钟 刷新一次
|
||||
|
}()); |
||||
|
|
||||
|
function extractBuildTime(inputString) { |
||||
|
const pattern = /[(\(]构建时间:(.*?)[\))]/; |
||||
|
const match = inputString.match(pattern); |
||||
|
const buildDate = match ? match[1] : null; |
||||
|
return buildDate; |
||||
|
} |
||||
|
|
||||
|
async function getExecutionDetail(executionId) { |
||||
|
const { sessionName, sessionID } = app.fs.session; |
||||
|
|
||||
|
const executionDetailRes = await request |
||||
|
.get(`https://pms.anxinyun.cn/execution-view-${executionId}.json`) |
||||
|
.set('Cookie', `${sessionName}=${sessionID}`); |
||||
|
const executionDetailText = JSON.parse(executionDetailRes.text); |
||||
|
const executionDetailData = JSON.parse(executionDetailText.data); |
||||
|
|
||||
|
const executionTeamRDs = []; |
||||
|
const executionTeamMembers = executionDetailData.teamMembers; |
||||
|
for (const member of Object.values(executionTeamMembers)) { |
||||
|
if (member.role === '研发') executionTeamRDs.push({ name_people: member.realname }); |
||||
|
} |
||||
|
|
||||
|
const executionProducts = Object.values(executionDetailData.products).map((product) => product.name); |
||||
|
|
||||
|
return { executionTeamRDs, executionProducts }; |
||||
|
} |
||||
|
|
||||
|
async function getExecutionProgress(executionId) { |
||||
|
const { sessionName, sessionID } = app.fs.session; |
||||
|
|
||||
|
const testTaskRes = await request |
||||
|
.get(`https://pms.anxinyun.cn/execution-testtask-${executionId}.json`) |
||||
|
.set('Cookie', `${sessionName}=${sessionID}`); |
||||
|
|
||||
|
const testTaskText = JSON.parse(testTaskRes.text); |
||||
|
const progress = Object.keys(JSON.parse(testTaskText.data).tasks).length ? '测试中' : '研发中'; |
||||
|
|
||||
|
return progress; |
||||
|
} |
||||
|
|
||||
|
async function getExecutionStats(baseURL, recPerPage) { |
||||
|
const { sessionName, sessionID } = app.fs.session; |
||||
|
|
||||
|
const executionRes = await request |
||||
|
.get(baseURL) |
||||
|
.set('Cookie', `${sessionName}=${sessionID}; pagerExecutionAll=${recPerPage || 10}`); |
||||
|
const executionText = JSON.parse(executionRes.text); |
||||
|
const executionData = JSON.parse(executionText.data); |
||||
|
|
||||
|
let executionAll = executionData.executionStats; |
||||
|
|
||||
|
const pg = executionData.pager; |
||||
|
let pid = pg.pageID; |
||||
|
while (pid < pg.pageTotal) { |
||||
|
const res = await request |
||||
|
.get(baseURL.replace('.json', `-${pg.recTotal}-${pg.recPerPage}-${pid + 1}.json`)) |
||||
|
.set('Cookie', `${sessionName}=${sessionID}`); |
||||
|
const resText = JSON.parse(res.text); |
||||
|
const resData = JSON.parse(resText.data); |
||||
|
executionAll = executionAll.concat(resData.executionStats); |
||||
|
pid++; |
||||
|
} |
||||
|
|
||||
|
const currentMonth = moment().format('YYYY-MM'); |
||||
|
|
||||
|
const executionStats = executionAll.filter((item) => item.type === 'sprint' && ( |
||||
|
moment(item.begin).format('YYYY-MM') === currentMonth |
||||
|
|| moment(item.end).format('YYYY-MM') === currentMonth |
||||
|
)); |
||||
|
|
||||
|
return executionStats; |
||||
|
} |
||||
|
|
||||
|
async function getOngoingProjects(ctx, next) { |
||||
|
try { |
||||
|
const { sessionName, sessionID } = app.fs.session; |
||||
|
|
||||
|
const executions = []; |
||||
|
const currentMonth = moment().format('YYYY-MM'); |
||||
|
|
||||
|
// 执行(未开始)
|
||||
|
const waitExecutionBaseURL = 'https://pms.anxinyun.cn/execution-all-wait-0-order_asc-0.json'; |
||||
|
const waitExecutionStats = await getExecutionStats(waitExecutionBaseURL, 200); |
||||
|
for (const item of waitExecutionStats) { |
||||
|
const { id, name, end } = item; |
||||
|
const { executionTeamRDs, executionProducts } = await getExecutionDetail(id); |
||||
|
if (executionProducts.some((p) => productExcluded.includes(p))) continue; |
||||
|
executions.push({ |
||||
|
execution_id: id, |
||||
|
name_project: name, |
||||
|
build_time: extractBuildTime(name), |
||||
|
publish_time: end, |
||||
|
part_people: executionTeamRDs, |
||||
|
progress: '需求评审中', |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
// 执行(进行中)
|
||||
|
const doingExecutionBaseURL = 'https://pms.anxinyun.cn/execution-all-doing-0-order_asc-0.json'; |
||||
|
const doingExecutionStats = await getExecutionStats(doingExecutionBaseURL, 200); |
||||
|
for (const item of doingExecutionStats) { |
||||
|
const { id, name, end } = item; |
||||
|
const { executionTeamRDs, executionProducts } = await getExecutionDetail(id); |
||||
|
if (executionProducts.some((p) => productExcluded.includes(p))) continue; |
||||
|
const executionProgress = await getExecutionProgress(id); |
||||
|
executions.push({ |
||||
|
execution_id: id, |
||||
|
name_project: name.replace('&', '&'), |
||||
|
build_time: extractBuildTime(name), |
||||
|
publish_time: end, |
||||
|
part_people: executionTeamRDs, |
||||
|
progress: executionProgress, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
ctx.status = 200; |
||||
|
ctx.body = { |
||||
|
total: executions.length, |
||||
|
projects: executions, |
||||
|
}; |
||||
|
} catch (e) { |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { |
||||
|
name: 'FindError', |
||||
|
message: `版本计划获取失败${e}`, |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async function getOngoingPersons(ctx, next) { |
||||
|
try { |
||||
|
const { sessionName, sessionID } = app.fs.session; |
||||
|
|
||||
|
const executions = []; |
||||
|
|
||||
|
const currentDate = moment(); |
||||
|
// 获取当前周的第一天(周一)
|
||||
|
const firstDayOfWeek = currentDate.clone().startOf('isoWeek'); |
||||
|
// 获取当前周的最后一天(周日)
|
||||
|
const lastDayOfWeek = currentDate.clone().endOf('isoWeek'); |
||||
|
|
||||
|
// 执行(未开始)
|
||||
|
const waitExecutionRes = await request |
||||
|
.get('https://pms.anxinyun.cn/execution-all-wait-0-order_asc-0.json') |
||||
|
.set('Cookie', `${sessionName}=${sessionID}`); |
||||
|
const waitExecutionText = JSON.parse(waitExecutionRes.text); |
||||
|
const waitExecutionStats = JSON.parse(waitExecutionText.data).executionStats |
||||
|
.filter((item) => item.type === 'sprint' && ( |
||||
|
moment(item.begin).isBetween(firstDayOfWeek, lastDayOfWeek, undefined, '[]') |
||||
|
|| moment(item.end).isBetween(firstDayOfWeek, lastDayOfWeek, undefined, '[]') |
||||
|
)); |
||||
|
|
||||
|
for (const item of waitExecutionStats) { |
||||
|
const { |
||||
|
id, name, begin, end, |
||||
|
} = item; |
||||
|
const { executionTeamRDs, executionProducts } = await getExecutionDetail(id); |
||||
|
if (executionProducts.some((p) => productExcluded.includes(p))) continue; |
||||
|
executions.push({ |
||||
|
name_project: name, |
||||
|
begin, |
||||
|
build_time: extractBuildTime(name), |
||||
|
end, |
||||
|
part_people: executionTeamRDs, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
const memberExecutions = executions.reduce((p, c) => { |
||||
|
const { part_people, ...rest } = c; |
||||
|
part_people.forEach((member) => { |
||||
|
if (p[member.name_people]) { |
||||
|
p[member.name_people].push(rest); |
||||
|
} else { |
||||
|
p[member.name_people] = [rest]; |
||||
|
} |
||||
|
}); |
||||
|
return p; |
||||
|
}, {}); |
||||
|
|
||||
|
ctx.status = 200; |
||||
|
ctx.body = { |
||||
|
total: Object.keys(memberExecutions).length, |
||||
|
projects: memberExecutions, |
||||
|
}; |
||||
|
} catch (e) { |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { |
||||
|
name: 'FindError', |
||||
|
message: `人员计划获取失败${e}`, |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
router.get('/ongoing/projects', getOngoingProjects); |
||||
|
router.get('/ongoing/persons', getOngoingPersons); |
||||
|
}, |
||||
|
}; |
Loading…
Reference in new issue