CODE 1 year ago
parent
commit
35518c1eb3
  1. 27
      api/app/lib/controllers/project/group.js
  2. 4
      api/app/lib/models/form_data_table.js
  3. 35
      api/app/lib/schedule/workOrder.js
  4. 2
      api/config.js
  5. 1
      web/client/src/layout/actions/workOrders.js
  6. 42
      web/client/src/sections/projectGroup/containers/bigscreen.jsx

27
api/app/lib/controllers/project/group.js

@ -587,30 +587,30 @@ async function groupProject (ctx) {
} }
async function getProjectWorkOrders(){ async function getProjectWorkOrders(ctx){
try{ try{
// 计算一个月前的日期 // 计算一个月前的日期
const oneMonthAgo = moment().subtract(1, 'months').toDate() const oneMonthAgo = moment().subtract(1, 'months').toDate()
const { models } = ctx.fs.dc const { models } = ctx.fs.dc
const {Op, fn, col} = ctx.fs.dc.ORM.sequelize const sequelize = ctx.fs.dc.ORM
const { projectIds } = ctx.query const { projectIds } = ctx.query
if(projectIds&&projectIds.length){ if(projectIds&&projectIds.length){
const projectIdsArr=projectIds.split(',').map(Number) const projectIdsArr=projectIds.split(',').map(Number)
const res= await models.FormDataTable.findAll({ const res= await models.FormDataTable.findAll({
attributes: [ attributes: [
'projectId', 'projectId',
[fn('COUNT', col('id')), 'count'], [sequelize.fn('COUNT', sequelize.col('id')), 'count'],
], ],
where: { where: {
projectIds: { projectId: {
[Op.in]: projectIdsArr, $in: projectIdsArr,
}, },
startTime: { startTime: {
[Op.gte]: oneMonthAgo, $gte: oneMonthAgo,
}, },
}, },
group: ['projectId'], group: ['projectId'],
order: [[fn('COUNT', col('id')), 'DESC']], order: [[sequelize.fn('COUNT', sequelize.col('id')), 'DESC']],
}) })
ctx.body=res ctx.body=res
ctx.status=200 ctx.status=200
@ -628,24 +628,25 @@ async function getProjectWorkOrders(){
} }
} }
async function getWorkOrdersRepairRank(){ async function getWorkOrdersRepairRank(ctx){
try{ try{
const oneMonthAgo = moment().subtract(1, 'months').toDate() const oneMonthAgo = moment().subtract(1, 'months').toDate()
const { models } = ctx.fs.dc const { models } = ctx.fs.dc
const {Op, fn, col} = ctx.fs.dc.ORM.sequelize const sequelize = ctx.fs.dc.ORM
const { projectIds } = ctx.query const { projectIds } = ctx.query
if(projectIds&&projectIds.length){ if(projectIds&&projectIds.length){
const res= await models.FormDataTable.findAll({ const res= await models.FormDataTable.findAll({
where: { where: {
projectIds: { projectId: {
[Op.in]: projectIds.split(',').map(Number), $in: projectIds.split(',').map(Number)
}, },
startTime: { startTime: {
[Op.gte]: oneMonthAgo, $gte: oneMonthAgo,
} }
}, },
order: [ order: [
[fn('TIMESTAMPDIFF', literal('SECOND'), col('endTime'), col('startTime')), 'DESC'] [sequelize.literal('(EXTRACT(EPOCH FROM "end_time" - "start_time"))'), 'DESC']
] ]
}) })
ctx.body=res ctx.body=res

4
api/app/lib/models/form_data_table.js

@ -9,11 +9,11 @@ module.exports = dc => {
id: { id: {
type: DataTypes.INTEGER, type: DataTypes.INTEGER,
allowNull: false, allowNull: false,
defaultValue: "nextval(\"formDataTable_id_seq\"::regclass)", defaultValue: null,
comment: "id", comment: "id",
primaryKey: true, primaryKey: true,
field: "id", field: "id",
autoIncrement: false autoIncrement: true
}, },
projectId: { projectId: {
type: DataTypes.INTEGER, type: DataTypes.INTEGER,

35
api/app/lib/schedule/workOrder.js

@ -1,9 +1,11 @@
const schedule = require('node-schedule'); const schedule = require('node-schedule');
const moment = require('moment') const moment = require('moment')
const request = require('superagent');
let isDev = true let isDev = true
module.exports = function (app, opts) { module.exports = function (app, opts,ctx) {
const workOrder = app.fs.scheduleInit( const workOrder = app.fs.scheduleInit(
{ {
interval: '0 * * * *',//一小时执行一次 interval: '0 * * * *',//一小时执行一次
@ -14,16 +16,18 @@ module.exports = function (app, opts) {
try{ try{
//前一次执行时间 //前一次执行时间
console.log('工单数据抽取开始') console.log('工单数据抽取开始')
const username = "admin"
const password = "fs-workflow"
let lastExecutionTime = null; let lastExecutionTime = null;
const { parseProcessData } = app.fs.utils const { parseProcessData } = app.fs.utils
const startTime = moment() const startTime = moment().format('YYYY-MM-DD HH:mm:ss')
const { models } = app.fs.dc const { models } = app.fs.dc
const { clickHouse } = app.fs const { clickHouse } = app.fs
const { database: camWorkflow } = clickHouse.camWorkflow.opts.config const { database: camWorkflow } = clickHouse.camWorkflow.opts.config
//新建表是否有数据 //新建表是否有数据
const rescount=await models.FormDataTable.count() const rescount=await models.FormDataTable.count()
if (lastExecutionTime === null) { if (lastExecutionTime === null) {
lastExecutionTime = moment().subtract(1, 'hour'); lastExecutionTime = moment().subtract(1, 'hour').format('YYYY-MM-DD HH:mm:ss')
} }
const formRes = await clickHouse.pepEmis.query( const formRes = await clickHouse.pepEmis.query(
`SELECT `SELECT
@ -53,37 +57,48 @@ module.exports = function (app, opts) {
ON fgroup.id = fprocess.group_id ON fgroup.id = fprocess.group_id
INNER JOIN ${camWorkflow}.act_hi_procinst AS procin INNER JOIN ${camWorkflow}.act_hi_procinst AS procin
ON procin.id_ = story.procinst_id ON procin.id_ = story.procinst_id
AND procin.state_='COMPLETED'
${rescount ?` WHERE procin.end_time_ is not null ${rescount ?` WHERE procin.end_time_ is not null
AND procin.end_time_ > '${lastExecutionTime}' AND procin.end_time_ > '${lastExecutionTime}'
AND procin.end_time_ <='${startTime}'` AND procin.end_time_ <='${startTime}'`
: ''}` : ''}`
).toPromise() ).toPromise()
console.log('formRes1',formRes)
const procinstIds = [...new Set(formRes.map(e => e.procinstId))]; const procinstIds = [...new Set(formRes.map(e => e.procinstId))];
console.log('formRes1',procinstIds)
// 获取流程实例变量 // 获取流程实例变量
if(formRes && formRes.length > 0){ if(formRes && formRes.length > 0){
let procinstsVariables = await ctx.app.camunda.request.post(encodeURI(`/engine-rest/history/variable-instance`), { let procinstsVariables = await request.post(encodeURI(opts.camundarest.host+'/'+opts.camundarest.root+`/engine-rest/history/variable-instance`))
processInstanceIdIn: procinstIds .auth(username, password)
}) .set('Content-Type', 'application/json')
.send({processInstanceIdIn: procinstIds})
console.log('formRes2',procinstsVariables)
if(procinstsVariables.body&&procinstsVariables.body.length){
for (let f of formRes) { for (let f of formRes) {
const parseData = parseProcessData({ const parseData = parseProcessData({
formSchema: JSON.parse(f.formSchema), formSchema: JSON.parse(f.formSchema),
formData: JSON.parse(f.formData) formData: JSON.parse(f.formData)
}) })
await models.Workorder.create({ const res=await models.FormDataTable.create({
projectId:parseData.pomsProjectId.value || null, projectId:parseData.pomsProjectId.value || null,
formname:procinstsVariables.find(item=>item.id===f.procinstId).name||null, formname:procinstsVariables.body.find(t => t.name == 'fsEmisBusinessName') ? procinstsVariables.body.find(t => t.name == 'fsEmisBusinessName').value : '',
state: f.state||null, state: f.state||null,
endTime:f.endTime||null, endTime:f.endTime||null,
startTime:f.createTime||null startTime:f.createTime||null
}) })
console.log('formRes3',res)
console.log('工单数据抽取结束') console.log('工单数据抽取结束')
} }
}else{
console.log('未查询到数据')
}
}else{
console.log('未查询到数据')
} }
}catch(error){ }catch(error){
console.error(error) console.error('失败原因',error)
} }
} }
); );

2
api/config.js

@ -206,6 +206,8 @@ const product = {
{ p: '/project/group/statistic/alarm', o: 'GET' }, { p: '/project/group/statistic/alarm', o: 'GET' },
{ p: '/project/group/list', o: 'GET' }, { p: '/project/group/list', o: 'GET' },
{ p: '/project/group/:groupId/detail', o: 'GET' }, { p: '/project/group/:groupId/detail', o: 'GET' },
{p:'/project/workOrders/repairRank',o:'GET'},
{p:'/project/workOrders',o:'GET'}
], // 不做认证的路由,也可以使用 exclude: ["*"] 跳过所有路由 ], // 不做认证的路由,也可以使用 exclude: ["*"] 跳过所有路由
apMergeDeVeAnxinProjectId: AP_MERGE_DEVE_ANXINPROJECT_ID, apMergeDeVeAnxinProjectId: AP_MERGE_DEVE_ANXINPROJECT_ID,
anxinCloud: { anxinCloud: {

1
web/client/src/layout/actions/workOrders.js

@ -3,7 +3,6 @@
import { ApiTable, basicAction } from '$utils' import { ApiTable, basicAction } from '$utils'
export function getWorkOrders () { //获取工单的待办 export function getWorkOrders () { //获取工单的待办
console.log('xxxxx',ApiTable.workOrders)
return dispatch => basicAction({ return dispatch => basicAction({
type: 'get', type: 'get',
dispatch: dispatch, dispatch: dispatch,

42
web/client/src/sections/projectGroup/containers/bigscreen.jsx

@ -25,7 +25,7 @@ const Bigscreen = (props) => {
const [proportion, setProportion] = useState([]) const [proportion, setProportion] = useState([])
const [formatter, setFormatter] = useState({}) const [formatter, setFormatter] = useState({})
const [groupDetail, setGroupDetail] = useState({}) const [groupDetail, setGroupDetail] = useState({})
const [allProjects,setAllProjects]=useState([])
const [alarmData, setAlarmData] = useState()// const [alarmData, setAlarmData] = useState()//
const [biggest, setBiggest] = useState()// const [biggest, setBiggest] = useState()//
const [mockData, setMockData] = useState()// const [mockData, setMockData] = useState()//
@ -36,6 +36,7 @@ const Bigscreen = (props) => {
useEffect(() => { useEffect(() => {
let groupIdLocal = JSON.parse(localStorage.getItem('project_group'))?.find(v => user?.id == v.userId)?.projectGroupId let groupIdLocal = JSON.parse(localStorage.getItem('project_group'))?.find(v => user?.id == v.userId)?.projectGroupId
let search = restProps?.location?.search || ''; let search = restProps?.location?.search || '';
@ -67,7 +68,11 @@ const Bigscreen = (props) => {
setGroupDetail(res.payload.data) setGroupDetail(res.payload.data)
} }
}) })
dispatch(actions.workOrder.getPomsProjectBasicAll()).then(res => {
if (res.success) {
setAllProjects(res.payload.data)
}
})
@ -135,27 +140,27 @@ const Bigscreen = (props) => {
} }
}, [mockData]) }, [mockData])
console.log('xxx1',actions)
useEffect(() => { useEffect(() => {
if(groupDetail?.pomsProjectIds&&groupDetail?.pomsProjectIds.length){ if(groupDetail?.pomsProjectIds&&groupDetail?.pomsProjectIds.length&&allProjects&&allProjects.length){
const query=groupDetail?.pomsProjectIds+'' const query=groupDetail?.pomsProjectIds+''
dispatch(actions.projectGroup.getProjectWorkOrders({projectIds:query})).then(res=>{ dispatch(actions.projectGroup.getProjectWorkOrders({projectIds:query})).then(res=>{
if(res.success){ if(res.success){
setProportion([...res.payload.data?.slice(0, 3)?.map(v => ({ name: pomsProjectBasicAll.find(item=>item.valiue===v.projectId)?.label, value: v.count })), setProportion([...res.payload.data?.slice(0, 3)?.map(v => ({ name: allProjects?.find(item=>item.value===v.projectId)?.label, value: Number(v.count) })),
{ value: res.payload.data&&res.payload.data.length>3?res.payload.data?.slice(3)?.reduce((p,c)=>{ { name: '其它', value: res.payload.data&&res.payload.data.length>3?res.payload.data?.slice(3)?.reduce((p,c)=>{
return p+c.count return p+Number(c.count)
},0):0, name: '其它' }]) },0):0 }])
} }
}) })
dispatch(actions.projectGroup.getProjectWorkOrders({projectIds:query})).then(res=>{ dispatch(actions.projectGroup.getWorkOrdersRepairRank({projectIds:query})).then(res=>{
if(res.success){ if(res.success){
setGroupProject(res.payload.data?.slice(0, 10).map(v => ({name:v.formname,duration:v?.endTime.diff(v?.startTime,'hours') })) || []) setGroupProject(res.payload.data?.slice(0, 10).map(v => ({name:v.formname,startTime:moment(v?.startTime).format('YYYY-MM-DD'),duration:moment(v?.endTime).add(8, 'hours').diff(v?.startTime,'hours') })) || [])
} }
}) })
} }
},[groupDetail]) },[groupDetail,allProjects])
let statisticOnline = (groupId) => { let statisticOnline = (groupId) => {
dispatch(actions.projectGroup.groupStatisticOnline({ groupId })).then(res => { dispatch(actions.projectGroup.groupStatisticOnline({ groupId })).then(res => {
@ -225,6 +230,7 @@ console.log('xxx1',actions)
}, [proportion]); }, [proportion]);
return ( return (
<div className='project-group'> <div className='project-group'>
<Header match={match} history={history} {...props} groupDetail={groupDetail} /> <Header match={match} history={history} {...props} groupDetail={groupDetail} />
<Body> <Body>
<div style={{ width: "100%", height: '100%' }}> <div style={{ width: "100%", height: '100%' }}>
@ -321,8 +327,8 @@ console.log('xxx1',actions)
return index < 10 ? <div style={{ display: "flex", background: index % 2 == 1 ? "#F6F9FF" : '', padding: 6, height: 50, alignItems: 'center' }}> return index < 10 ? <div style={{ display: "flex", background: index % 2 == 1 ? "#F6F9FF" : '', padding: 6, height: 50, alignItems: 'center' }}>
<div style={{ textAlign: 'center', width: '25%', fontFamily: 'SourceHanSansCN-Regular', color: '#2C66F3', fontWeight: 400 }}> <div style={{ textAlign: 'center', width: '25%', fontFamily: 'SourceHanSansCN-Regular', color: '#2C66F3', fontWeight: 400 }}>
NO.{index + 1}</div> NO.{index + 1}</div>
<div title={c.fromname} style={{ textAlign: 'center', padding: '0 6px', width: '49%', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}> <div title={`${c.name}(${c.startTime})`} style={{ textAlign: 'center', padding: '0 6px', width: '49%', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
{c.fromname}</div> {c.name}({c.startTime})</div>
<div style={{ textAlign: 'center', width: '25%', fontFamily: 'SourceHanSansCN-Regular', fontWeight: 400 }}> <div style={{ textAlign: 'center', width: '25%', fontFamily: 'SourceHanSansCN-Regular', fontWeight: 400 }}>
{c.duration}h</div> {c.duration}h</div>
</div> : <></> </div> : <></>
@ -485,7 +491,7 @@ console.log('xxx1',actions)
return <div style={{ display: "flex", background: index % 2 == 1 ? "#F6F9FF" : '', height: 40, alignItems: 'center' }}> return <div style={{ display: "flex", background: index % 2 == 1 ? "#F6F9FF" : '', height: 40, alignItems: 'center' }}>
<div style={{ textAlign: 'center', width: '33%', fontFamily: 'SourceHanSansCN-Regular', color: '#2C66F3', fontWeight: 400 }}>{c.name}</div> <div style={{ textAlign: 'center', width: '33%', fontFamily: 'SourceHanSansCN-Regular', color: '#2C66F3', fontWeight: 400 }}>{c.name}</div>
<div style={{ textAlign: 'center', width: '33%' }}>{title}</div> <div style={{ textAlign: 'center', width: '33%' }}>{title}</div>
<div style={{ textAlign: 'center', width: '33%', fontFamily: 'SourceHanSansCN-Regular', color: '#F33B3B', fontWeight: 400 }}>{c.offnum + '/' + c.totnum+`(${(c.offnum/c.totnum).toFixed(4)*100}%)`}</div> <div style={{ textAlign: 'center', width: '33%', fontFamily: 'SourceHanSansCN-Regular', color: '#F33B3B', fontWeight: 400 }}>{c.offnum + '/' + c.totnum+`(${((c.offnum/c.totnum)*100).toFixed(2)}%)`}</div>
</div> </div>
})}</> } containerStyle={{ position: "relative", height: "85%", }} })}</> } containerStyle={{ position: "relative", height: "85%", }}
divHeight={"100%"} divId={"interruptchart"}/> divHeight={"100%"} divId={"interruptchart"}/>
@ -500,14 +506,16 @@ console.log('xxx1',actions)
</div > </div >
) )
} }
function mapStateToProps (state) { function mapStateToProps (state) {
const { auth, global, groupStatisticOnline } = state;
const { auth, global, groupStatisticOnline,pomsProjectBasicAll } = state;
return { return {
user: auth.user, user: auth.user,
actions: global.actions, actions: global.actions,
clientHeight: global.clientHeight, clientHeight: global.clientHeight,
groupStatisticOnline: groupStatisticOnline?.data groupStatisticOnline: groupStatisticOnline?.data,
pomsProjectBasicAll: pomsProjectBasicAll.data || [],
}; };
} }

Loading…
Cancel
Save