Browse Source

报表优化

dev
wenlele 1 year ago
parent
commit
a56b9390b5
  1. 45
      api/app/lib/controllers/service/report.js
  2. 5
      api/app/lib/routes/service/report.js
  3. 5
      api/config.js
  4. 13
      web/client/src/sections/service/actions/report.js
  5. 27
      web/client/src/sections/service/components/automatic-Modal.jsx
  6. 31
      web/client/src/sections/service/containers/automaticReport.jsx
  7. 1
      web/client/src/utils/webapi.js

45
api/app/lib/controllers/service/report.js

@ -107,12 +107,13 @@ async function getFactorList (ctx) {
const factorId = factor.map(a => a.id) const factorId = factor.map(a => a.id)
const sensor = factorId.length ? await clickHouse.anxinyun.query(` const sensor = factorId.length && anxinStrucIds.length ? await clickHouse.anxinyun.query(`
SELECT SELECT
id,name,factor id,name,factor,structure
FROM t_sensor FROM t_sensor
WHERE WHERE
t_sensor.factor IN (${factorId.join(',')}, -1) t_sensor.factor IN (${factorId.join(',')}, -1)
AND t_sensor.structure IN (${anxinStrucIds.join(',')}, -1)
`).toPromise() : [] `).toPromise() : []
@ -134,7 +135,7 @@ async function getFactorList (ctx) {
anxinStruc.forEach(s => { anxinStruc.forEach(s => {
s.factor = factor.filter(d => { s.factor = factor.filter(d => {
if (d.structure == s.strucId) { if (d.structure == s.strucId) {
d.sensor = sensor.filter(f => f.factor == d.id) d.sensor = sensor.filter(f => f.factor == d.id && f.structure == s.strucId)
return true return true
} else { } else {
return false return false
@ -167,7 +168,8 @@ async function postAutomaticReport (ctx) {
await models.ReportAutomatic.update(data, { await models.ReportAutomatic.update(data, {
where: { where: {
id: data.id id: data.id
}}) }
})
} else { } else {
await models.ReportAutomatic.create(data) await models.ReportAutomatic.create(data)
} }
@ -239,6 +241,38 @@ async function delAutomaticReport (ctx) {
} }
async function postGenerateReport (ctx) {
try {
const { models } = ctx.fs.dc;
const data = ctx.request.body
let res = await ctx.app.fs.reportGenerate.post('gen', {
data: data
})
if (res.code == 200) {
await models.ReportFile.create({
fileName: data.reportName,
projectId: data.projectId,
url: res.outLink,
startTime: moment().format('YYYY-MM-DD HH:mm:ss'),
reportType: data.reportType
})
ctx.status = 200;
ctx.body = res.outLink
} else {
throw '生成报表失败'
}
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
module.exports = { module.exports = {
@ -248,5 +282,6 @@ module.exports = {
getFactorList, getFactorList,
postAutomaticReport, postAutomaticReport,
getAutomaticReport, getAutomaticReport,
delAutomaticReport delAutomaticReport,
postGenerateReport
}; };

5
api/app/lib/routes/service/report.js

@ -24,9 +24,8 @@ module.exports = function (app, router, opts) {
app.fs.api.logAttr['DEL/automatic/report/:id'] = { content: '删除报表规则', visible: true }; app.fs.api.logAttr['DEL/automatic/report/:id'] = { content: '删除报表规则', visible: true };
router.del('/automatic/report/:id', report.delAutomaticReport); router.del('/automatic/report/:id', report.delAutomaticReport);
app.fs.api.logAttr['POST/generate/report'] = { content: '生成报表', visible: true };
router.post('/generate/report', report.postGenerateReport);
// app.fs.api.logAttr['GET/respond-record'] = { content: '获取响应记录数据', visible: true };
// router.get('/respond-record', record.respondRecord);
}; };

5
api/config.js

@ -90,6 +90,8 @@ const AP_MERGE_DEVE_ANXINPROJECT_ID = process.env.AP_MERGE_DEVE_ANXINPROJECT_ID
const API_ANXINYUN_URL = process.env.API_ANXINYUN_URL || flags.axyApiUrl; const API_ANXINYUN_URL = process.env.API_ANXINYUN_URL || flags.axyApiUrl;
// 企业管理 api // 企业管理 api
const API_EMIS_URL = process.env.API_EMIS_URL || flags.apiEmisUrl; const API_EMIS_URL = process.env.API_EMIS_URL || flags.apiEmisUrl;
//报表生成 api
const API_REPOR_GENERATE_URL = process.env.API_REPOR_GENERATE_URL || 'http://222.186.227.196:30567';
// 视频平台 api // 视频平台 api
const API_VCMP_URL = process.env.API_VCMP_URL || flags.apiVcmpUrl; const API_VCMP_URL = process.env.API_VCMP_URL || flags.apiVcmpUrl;
// iot鉴权平台 api // iot鉴权平台 api
@ -281,6 +283,9 @@ const product = {
}, { }, {
name: 'emisRequest', name: 'emisRequest',
root: API_EMIS_URL root: API_EMIS_URL
}, {
name: 'reportGenerate',
root: API_REPOR_GENERATE_URL
}, { }, {
name: 'vcmpRequest', name: 'vcmpRequest',
root: API_VCMP_URL root: API_VCMP_URL

13
web/client/src/sections/service/actions/report.js

@ -57,7 +57,7 @@ export function getFactorList (query = {}) { //获取报表文件
}); });
} }
export function postAutomaticReport (data = {}) { //上传文件 export function postAutomaticReport (data = {}) {
return dispatch => basicAction({ return dispatch => basicAction({
type: 'post', type: 'post',
data, data,
@ -97,9 +97,18 @@ export function delAutomaticReport (id) {//删除报表文件
}); });
} }
export function postGenerateReport (data = {}) { //生成报表
return dispatch => basicAction({
type: 'post',
data,
dispatch: dispatch,
actionType: 'POST_GENERATE_REPORT',
url: `${ApiTable.generateReport}`,
msg: { option: "生成报表" },
});
}

27
web/client/src/sections/service/components/automatic-Modal.jsx

@ -16,6 +16,7 @@ const AutomaticModal = ({ actions, dispatch, apiRoot, qiniuUrl, visible, eidtDat
const [factorId, setFactorId] = useState([]); //id const [factorId, setFactorId] = useState([]); //id
const [factorList, setFactorList] = useState([]); // const [factorList, setFactorList] = useState([]); //
const [factorChech, setFactorChech] = useState([]); // const [factorChech, setFactorChech] = useState([]); //
const [activeKey, setActiveKey] = useState([]); //
useEffect(async () => { useEffect(async () => {
@ -28,6 +29,7 @@ const AutomaticModal = ({ actions, dispatch, apiRoot, qiniuUrl, visible, eidtDat
let Factor = data?.find(s => s.strucId == eidtData?.structId)?.factor || [] let Factor = data?.find(s => s.strucId == eidtData?.structId)?.factor || []
setFactorList(Factor) setFactorList(Factor)
setFactorChech(Factor?.filter(s => eidtData?.factors?.map(s => s.codeName)?.includes(s.proto))) setFactorChech(Factor?.filter(s => eidtData?.factors?.map(s => s.codeName)?.includes(s.proto)))
setActiveKey(eidtData?.factors?.map(s => s.codeName) || [])
} }
}, []) }, [])
@ -50,8 +52,8 @@ const AutomaticModal = ({ actions, dispatch, apiRoot, qiniuUrl, visible, eidtDat
cancelText="取消" cancelText="取消"
visible={visible} visible={visible}
onOk={() => { onOk={() => {
form.current.validate().then((v) => { form.current.validate().then((v) => {
console.log(v);
let data = { let data = {
id: eidtData?.id, id: eidtData?.id,
reportName: v.reportName, reportName: v.reportName,
@ -100,8 +102,8 @@ const AutomaticModal = ({ actions, dispatch, apiRoot, qiniuUrl, visible, eidtDat
}) })
} }
if (key?.slice(index) == 'factorDescrip') factorData.factorDescrip = v[key] if (key?.slice(index) == 'factorDescrip') factorData.factorDescrip = v[key]
if (key?.slice(index) == 'glStaName') factorData.glStaName = v[key] // if (key?.slice(index) == 'glStaName') factorData.glStaName = v[key]
if (key?.slice(index) == 'tempStaName') factorData.tempStaName = v[key] // if (key?.slice(index) == 'tempStaName') factorData.tempStaName = v[key]
if (key?.slice(index) == 'initialTime') factorData.initialTime = v[key] && moment(v[key]).format('YYYY-MM-DD HH:mm:ss') if (key?.slice(index) == 'initialTime') factorData.initialTime = v[key] && moment(v[key]).format('YYYY-MM-DD HH:mm:ss')
if (key?.slice(index) == 'releTime') { if (key?.slice(index) == 'releTime') {
factorData.releStartTime = v[key] && moment(v[key][0]).format('YYYY-MM-DD HH:mm:ss') factorData.releStartTime = v[key] && moment(v[key][0]).format('YYYY-MM-DD HH:mm:ss')
@ -109,12 +111,13 @@ const AutomaticModal = ({ actions, dispatch, apiRoot, qiniuUrl, visible, eidtDat
} }
} }
} }
factorData.glStaName = factorData?.tempName?.find(s => s.index == 1)?.name
factorData.tempStaName = factorData?.tempName?.find(s => s.index == 2)?.name || factorData?.tempName?.find(s => s.index == 1)?.name
data.factors?.push(factorData) data.factors?.push(factorData)
}) })
console.log(111, data); console.log(111, data);
dispatch(service.postAutomaticReport(data)).then((res) => { dispatch(service.postAutomaticReport(data)).then((res) => {
console.log(res);
if (res.success) { if (res.success) {
close() close()
success() success()
@ -215,6 +218,7 @@ const AutomaticModal = ({ actions, dispatch, apiRoot, qiniuUrl, visible, eidtDat
rules={[{ required: true, message: "请选择监测因素" }]} disabled={structId ? false : true} rules={[{ required: true, message: "请选择监测因素" }]} disabled={structId ? false : true}
onChange={v => { onChange={v => {
setFactorChech(factorList?.filter(s => v.includes(s.proto))) setFactorChech(factorList?.filter(s => v.includes(s.proto)))
setActiveKey(v)
}} > }} >
{factorList?.map((item) => { {factorList?.map((item) => {
return <Form.Select.Option value={item.proto} label={item.name}></Form.Select.Option> return <Form.Select.Option value={item.proto} label={item.name}></Form.Select.Option>
@ -222,16 +226,23 @@ const AutomaticModal = ({ actions, dispatch, apiRoot, qiniuUrl, visible, eidtDat
</Form.Select> </Form.Select>
{factorChech?.length > 0 ? <Collapse style={{ margin: '20px 0 20px 30px', width: '90%', background: '#b7c9e624' }}> {factorChech?.length > 0 ? <Collapse style={{ margin: '20px 0 20px 30px', width: '90%', background: '#b7c9e624' }}
activeKey={activeKey}
onChange={v => {
// setActiveKey(v)
}}
>
{ {
factorChech?.map(s => { factorChech?.map(s => {
return <Collapse.Panel header={s.name} itemKey={s.proto}> return <Collapse.Panel header={s.name} itemKey={s.proto}>
<div style={{ background: "#FFF" }}> <div style={{ background: "#FFF" }}>
<Form.TextArea field={s.proto + "pointDescrip"} label='布点描述' style={{ width: 400 }} autosize={{ minRows: 2, maxRows: 10 }} placeholder="请输入布点描述" showClear <Form.TextArea field={s.proto + "pointDescrip"} label='布点描述' style={{ width: 400 }} autosize={{ minRows: 2, maxRows: 10 }} placeholder="请输入布点描述" showClear
initValue={eidtData?.factors?.find(c => c.codeName == s.proto)?.pointDescrip || ""} initValue={eidtData?.factors?.find(c => c.codeName == s.proto)?.pointDescrip || ""}
rules={[{ required: true, message: "请输入布点描述" }]}
/> />
<Form.Upload label="布点图片" field={s.proto + "pointPicPath"} style={{ display: 'inline-block', }} <Form.Upload label="布点图片" field={s.proto + "pointPicPath"} style={{ display: 'inline-block', }}
initValue={eidtData?.factors?.find(c => c.codeName == s.proto)?.pointPicPath && [{ url: `/_file-server/${eidtData?.factors?.find(c => c.codeName == s.proto)?.pointPicPath?.slice(qiniuUrl.length + 1)}`, name: eidtData?.factors?.find(c => c.codeName == s.proto)?.pointPicPath?.split('/')?.pop(), status: 'success', preview: ['png', 'jpg', 'jpeg'].includes(eidtData?.factors?.find(c => c.codeName == s.proto)?.pointPicPath?.split('.')?.pop()?.replace('.', '')) }] || null} initValue={eidtData?.factors?.find(c => c.codeName == s.proto)?.pointPicPath && [{ url: `/_file-server/${eidtData?.factors?.find(c => c.codeName == s.proto)?.pointPicPath?.slice(qiniuUrl.length + 1)}`, name: eidtData?.factors?.find(c => c.codeName == s.proto)?.pointPicPath?.split('/')?.pop(), status: 'success', preview: ['png', 'jpg', 'jpeg'].includes(eidtData?.factors?.find(c => c.codeName == s.proto)?.pointPicPath?.split('.')?.pop()?.replace('.', '')) }] || null}
rules={[{ required: true, message: "请删上传布点图片" }]}
action={`${apiRoot}/attachments/p`} action={`${apiRoot}/attachments/p`}
accept={'.png, .jpg, .jpeg'} accept={'.png, .jpg, .jpeg'}
limit={1} maxSize={5120} limit={1} maxSize={5120}
@ -249,6 +260,7 @@ const AutomaticModal = ({ actions, dispatch, apiRoot, qiniuUrl, visible, eidtDat
<Form.Select label="测点选择" field={s.proto + "sensorNames"} multiple={true} placeholder="请选择测点选择" style={{ width: 300 }} filter <Form.Select label="测点选择" field={s.proto + "sensorNames"} multiple={true} placeholder="请选择测点选择" style={{ width: 300 }} filter
initValue={eidtData?.factors?.find(c => c.codeName == s.proto)?.sensorNames?.map(a => a.id) || []} initValue={eidtData?.factors?.find(c => c.codeName == s.proto)?.sensorNames?.map(a => a.id) || []}
rules={[{ required: true, message: "请选择测点选择" }]}
> >
{s.sensor?.map((item) => { {s.sensor?.map((item) => {
return <Form.Select.Option value={item.id} label={item.name}></Form.Select.Option> return <Form.Select.Option value={item.id} label={item.name}></Form.Select.Option>
@ -256,6 +268,7 @@ const AutomaticModal = ({ actions, dispatch, apiRoot, qiniuUrl, visible, eidtDat
</Form.Select> </Form.Select>
<Form.DatePicker field={s.proto + 'startEndTime'} label='开始结束时间' type='dateTimeRange' showClear style={{ width: 360 }} <Form.DatePicker field={s.proto + 'startEndTime'} label='开始结束时间' type='dateTimeRange' showClear style={{ width: 360 }}
initValue={eidtData?.factors?.find(c => c.codeName == s.proto)?.startTime && [moment(eidtData?.factors?.find(c => c.codeName == s.proto)?.startTime).format('YYYY-MM-DD HH:mm:ss'), moment(eidtData?.factors?.find(c => c.codeName == s.proto)?.endTime).format('YYYY-MM-DD HH:mm:ss')] || null} initValue={eidtData?.factors?.find(c => c.codeName == s.proto)?.startTime && [moment(eidtData?.factors?.find(c => c.codeName == s.proto)?.startTime).format('YYYY-MM-DD HH:mm:ss'), moment(eidtData?.factors?.find(c => c.codeName == s.proto)?.endTime).format('YYYY-MM-DD HH:mm:ss')] || null}
rules={[{ required: true, message: "请选择开始结束时间" }]}
/> />
{ {
['2001', '4004', '4007', '4008'].includes(s.proto) && ['2001', '4004', '4007', '4008'].includes(s.proto) &&
@ -280,12 +293,12 @@ const AutomaticModal = ({ actions, dispatch, apiRoot, qiniuUrl, visible, eidtDat
})} })}
</Form.Select> </Form.Select>
<Form.Input field={s.proto + "glStaName"} label='关联温度的测点名称' style={{ width: 300 }} placeholder="请输入关联温度的测点名称" showClear {/* <Form.Input field={s.proto + "glStaName"} label='' style={{ width: 300 }} placeholder="" showClear
initValue={eidtData?.factors?.find(c => c.codeName == s.proto)?.glStaName || ""} initValue={eidtData?.factors?.find(c => c.codeName == s.proto)?.glStaName || ""}
/> />
<Form.Input field={s.proto + "tempStaName"} label='关联温度名称' style={{ width: 300 }} placeholder="请输入关联温度名称" showClear <Form.Input field={s.proto + "tempStaName"} label='关联温度名称' style={{ width: 300 }} placeholder="请输入关联温度名称" showClear
initValue={eidtData?.factors?.find(c => c.codeName == s.proto)?.tempStaName || ""} initValue={eidtData?.factors?.find(c => c.codeName == s.proto)?.tempStaName || ""}
/> /> */}
<Form.DatePicker field={s.proto + 'releTime'} label='关联开始结束时间' type='dateTimeRange' showClear style={{ width: 360 }} <Form.DatePicker field={s.proto + 'releTime'} label='关联开始结束时间' type='dateTimeRange' showClear style={{ width: 360 }}
initValue={eidtData?.factors?.find(c => c.codeName == s.proto)?.releStartTime && [moment(eidtData?.factors?.find(c => c.codeName == s.proto)?.releStartTime).format('YYYY-MM-DD HH:mm:ss'), moment(eidtData?.factors?.find(c => c.codeName == s.proto)?.releEndTime).format('YYYY-MM-DD HH:mm:ss')] || null} initValue={eidtData?.factors?.find(c => c.codeName == s.proto)?.releStartTime && [moment(eidtData?.factors?.find(c => c.codeName == s.proto)?.releStartTime).format('YYYY-MM-DD HH:mm:ss'), moment(eidtData?.factors?.find(c => c.codeName == s.proto)?.releEndTime).format('YYYY-MM-DD HH:mm:ss')] || null}
/> />

31
web/client/src/sections/service/containers/automaticReport.jsx

@ -104,7 +104,38 @@ const AutomaticReport = ({ dispatch, actions, user, clientHeight, loading, socke
<Button theme="borderless" type='danger'>删除</Button> <Button theme="borderless" type='danger'>删除</Button>
</Popconfirm> </Popconfirm>
<Button theme="borderless" onClick={() => { <Button theme="borderless" onClick={() => {
// WSDJC(湿) 1002
// FSFXJC() 1001
// SSFJC() 4009
// SLJC() 2001
// YBJC() 3001
// NDJC() 4004
// ZDJC() 5002
// CLZHJC()
// ZZWYJC() 4001
// QTPWJC() 4002
// LFJC() 4008
// QDQXJC() 4007
// JGWDJC() 1004
let dataList = {
1002: 'WSDJC',
1001: 'FSFXJC',
4009: 'SSFJC',
2001: 'SLJC',
3001: 'YBJC',
4004: 'NDJC',
5002: 'ZDJC',
4001: 'ZZWYJC',
4002: 'QTPWJC',
4008: 'LFJC',
4007: 'QDQXJC',
1004: 'JGWDJC'
}
row?.factors?.forEach(d => {
d.codeName = dataList[d.codeName]
})
dispatch(service.postGenerateReport(row))
}}> }}>
立即生成 立即生成
</Button> </Button>

1
web/client/src/utils/webapi.js

@ -83,6 +83,7 @@ export const ApiTable = {
factorList: "factor/list", //获取监测因素数据 factorList: "factor/list", //获取监测因素数据
automaticReport: "automatic/report", //自动化报表 automaticReport: "automatic/report", //自动化报表
delAutomaticReport: "automatic/report/{id}", //删除报表规则 delAutomaticReport: "automatic/report/{id}", //删除报表规则
generateReport: "generate/report", //报表生成
//控制台 //控制台
consoleToollink: 'console/toollink', //常用工具 consoleToollink: 'console/toollink', //常用工具

Loading…
Cancel
Save