add modbus log

This commit is contained in:
Jay 2017-03-29 15:06:50 +08:00
parent 77bf5f58d2
commit 3e66691b67
15 changed files with 5579 additions and 4735 deletions

View File

@ -18,7 +18,8 @@
"db6": "jcmbrt",
"db7": "jcioclc",
"db8": "jciocln",
"db9": "jcbtwristband"
"db9": "jcbtwristband",
"db10": "jcmblog"
},
"permission": {
"dio": true,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -271,6 +271,7 @@
"schedule": "排程控制",
"modbus": "Modbus",
"modbuscmd": "Modbus CMD",
"modbuslog": "Modbus Log",
"link": "連動",
"ipcam": "網路攝影機",
"logout": "登出"

View File

@ -498,6 +498,39 @@ router
n();
})
})
.post('/getmodbuslog', (req,res,n) => {
if (!config.permission.modbus) return n('ERR9000');
let arr = req.body;
if(!arr.data) return n('ERR0000');
if(!arr.data.ids || !Array.isArray(arr.data.ids)) return n('ERR0028');
if(!arr.data.stime || !arr.data.etime) return n('ERR0015');
let query = "select log.`node`, log.`type`, log.`port`, log.`value2` as value, log.`tst`, dev.`name` as devname, aio.`name` as aioname \
from ??.?? log \
left join ??.?? dev \
on dev.`node` = log.`node`\
left join ??.?? io \
on io.`devuid` = dev.`uid` \
and io.`type` = log.`type` \
left join ??.?? aio \
on aio.`iouid` = io.`uid` \
and aio.`portnum` = log.`port` \
where \
dev.`uid` in (?) \
and ( log.`tst` >= ? \
and log.`tst` <= ? ) \
order by log.`uid` desc, log.`tst` desc \
limit 0, 100";
let param = [config.db.db10, 'jcmbrt', config.db.db5, 'device', config.db.db5, 'iolist', config.db.db5, 'aioset', arr.data.ids, arr.data.stime, arr.data.etime];
res.db.query(query, param, (err,row) => {
if(err) return n('ERR8000');
res.api_res = {
record: tool.checkArray(row)
}
n();
})
})
.all('*', rt.send);
module.exports = router;

View File

@ -584,6 +584,22 @@ export const del_mb_aio = data => dispatch => {
return dispatch(mb_aio_api('/api/modbus/delaioset', data));
}
export const get_mb_log = data => dispatch => {
dispatch(toggle_loading(1));
return fetch('/api/modbus/getmodbuslog', getRequest(data))
.then(response => response.json())
.then(json => {
dispatch(toggle_loading(0));
if(json.status != 1) return dispatch(add_dialog_msg(json.message));
dispatch(mb_log(json.data.record || []));
});
}
const mb_log = (list) => ({
type: 'mb_log',
list
});
export const get_link_list = () => dispatch => {
dispatch(toggle_loading(1));
return fetch('/api/link/getlinklist', getRequest())

View File

@ -0,0 +1,29 @@
import React from 'react';
import {Menu, Header} from 'semantic-ui-react';
import ListItem from './DeviceListItem';
const DeviceList = ({i18n, list, selected, toggleSelect}) => {
return (
<Menu vertical={true}>
<Menu.Item>
<Menu.Header content="裝置列表" />
<Menu.Menu>
{
list.map((t, idx) => {
return (
<ListItem key={idx}
i18n={i18n}
data={t}
toggleSelect={toggleSelect}
checked={selected.indexOf(t.uid) == -1 ? false : true} />
)
})
}
</Menu.Menu>
</Menu.Item>
</Menu>
)
}
export default DeviceList;

View File

@ -0,0 +1,13 @@
import React from 'react';
import {Menu, Checkbox} from 'semantic-ui-react';
const ListItem = ({i18n, data, checked, toggleSelect}) => {
return (
<Menu.Item>
<Checkbox label={data.name} checked={checked} onChange={(e,d)=>{ toggleSelect(data.uid) }}/>
</Menu.Item>
)
}
export default ListItem;

View File

@ -0,0 +1,25 @@
import React from 'react';
import {Table} from 'semantic-ui-react';
import {convertTime} from '../../../tools'
const ListItem = ({i18n, data}) => {
let iotype = i18n&&i18n.getResource&&i18n.language ? i18n.getResource(i18n.language + '.translation.porttype') : [];
let t = '';
for(let i in iotype) {
if(data.type == iotype[i].code) t = iotype[i].name;
}
return (
<Table.Row>
<Table.Cell>{data.devname}</Table.Cell>
<Table.Cell>{data.aioname}</Table.Cell>
<Table.Cell>{data.port}</Table.Cell>
<Table.Cell>{t}</Table.Cell>
<Table.Cell>{data.value}</Table.Cell>
<Table.Cell>{convertTime(data.tst)}</Table.Cell>
</Table.Row>
)
}
export default ListItem;

View File

@ -0,0 +1,35 @@
import React from 'react';
import {Table, Segment} from 'semantic-ui-react';
import ListItem from './LogListItem';
const LogPanel = ({i18n, log}) => {
return (
<Segment>
<Table>
<Table.Header>
<Table.Row>
<Table.HeaderCell>裝置名稱</Table.HeaderCell>
<Table.HeaderCell>接口名稱</Table.HeaderCell>
<Table.HeaderCell>接口號碼</Table.HeaderCell>
<Table.HeaderCell>接口類型</Table.HeaderCell>
<Table.HeaderCell>數值</Table.HeaderCell>
<Table.HeaderCell>時間</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
{
log.map((t,idx)=>{
return (
<ListItem key={idx} i18n={i18n}
data={t} />
)
})
}
</Table.Body>
</Table>
</Segment>
)
}
export default LogPanel;

View File

@ -0,0 +1,101 @@
import React from 'react';
import {Container, Menu, Grid, Button, Input, Segment, Table} from 'semantic-ui-react';
import DeviceList from './DeviceList';
import {convertTime} from '../../../tools';
import Datetime from 'react-datetime';
import LogPanel from './LogPanel';
let getDayTime = () => {
let date = new Date();
date.setHours(0,0,0,0);
return date.getTime();
}
class ModbusLogPage extends React.Component {
state = {
selected: [],
stime: getDayTime(),
etime: Date.now()
}
toggleSelect = (id) => {
let selected = [...this.state.selected];
let idx = selected.indexOf(id);
if(idx == -1) selected.push(id);
else selected.splice(idx, 1);
this.setState({
selected
})
}
getLogList = () => {
let ids = [...this.state.selected];
let data = {
ids,
stime: Math.floor(this.state.stime /1000),
etime: Math.floor(this.state.etime)
}
if(ids.length == 0) return this.props.showDialog('請選擇裝置');
this.props.getMBLog(data);
}
componentDidMount(){
this.props.getList();
this.props.router.setRouteLeaveHook(this.props.route, () => {
this.props.clearList();
});
}
render(){
let {i18n, list, log} = this.props;
return (
<Container>
<Menu>
<Menu.Item>
<Input label="起始時間" input={
<Datetime dateFormat="YYYY-MM-DD"
timeFormat="HH:mm"
value={convertTime(this.state.stime)}
input={true}
onChange={(e)=>{ this.setState({stime: e.valueOf()}) }} />
}/>
</Menu.Item>
<Menu.Item>
<Input label="結束時間" input={
<Datetime dateFormat="YYYY-MM-DD"
timeFormat="HH:mm"
value={convertTime(this.state.etime)}
input={true}
onChange={(e)=>{ this.setState({etime: e.valueOf()}) }} />
}/>
</Menu.Item>
<Menu.Menu position="right">
<Menu.Item>
<Button type="button" content="搜尋" size="tiny" basic onClick={()=>{this.getLogList()}} />
</Menu.Item>
</Menu.Menu>
</Menu>
<Grid>
<Grid.Column width={4}>
<DeviceList i18n={i18n}
list={list}
selected={this.state.selected}
toggleSelect={this.toggleSelect}
/>
</Grid.Column>
<Grid.Column width={12}>
<LogPanel i18n={i18n}
log={log} />
</Grid.Column>
</Grid>
</Container>
)
}
}
export default ModbusLogPage;

View File

@ -17,6 +17,7 @@ const MainMenu = ({i18n, show, toggleMenu, children, permissions, showDashboard,
<MItem toLink="/admin/schedule" txt={i18n && 't' in i18n ? i18n.t('menu.item.schedule') : ''} permission={permissions.schedule} onClick={()=>toggleMenu()} />
<MItem toLink="/admin/modbus" txt={i18n && 't' in i18n ? i18n.t('menu.item.modbus') : ''} permission={permissions.modbus} onClick={()=>toggleMenu()} />
<MItem toLink="/admin/modbuscmd" txt={i18n && 't' in i18n ? i18n.t('menu.item.modbuscmd') : ''} permission={permissions.modbus} onClick={()=>toggleMenu()} />
<MItem toLink="/admin/modbuslog" txt={i18n && 't' in i18n ? i18n.t('menu.item.modbuslog') : ''} permission={permissions.modbus} onClick={()=>toggleMenu()} />
<MItem toLink="/admin/link" txt={i18n && 't' in i18n ? i18n.t('menu.item.link') : ''} permission={permissions.link} onClick={()=>toggleMenu()} />
<MItem toLink="/admin/ipcam" txt={i18n && 't' in i18n ? i18n.t('menu.item.ipcam') : ''} permission={permissions.ipcam} onClick={()=>toggleMenu()} />
<MItem toLink="/admin" txt={i18n && 't' in i18n ? i18n.t('menu.item.logout') : ''} permission={true} onClick={()=>{

View File

@ -0,0 +1,29 @@
import {connect} from 'react-redux';
import {add_dialog_msg, toggle_loading, get_modbus_list, get_mb_log, clear_modbus} from '../../actions';
import ModbusLogPage from '../../components/AdminPage/ModbusLog';
const mapStateToProps = (state) => ({
i18n: state.i18n,
list: state.lists.modbus.list,
log: state.lists.modbus.log
});
const mapDispatchToProps = (dispatch, ownProps) => ({
showDialog: (msg) => {
dispatch(add_dialog_msg(msg));
},
toggleLoading: (flag = false) => {
dispatch(toggle_loading(flag));
},
getList: () => {
dispatch(get_modbus_list());
},
clearList: ()=>{
dispatch(clear_modbus())
},
getMBLog: (data) => {
dispatch(get_mb_log(data));
}
})
export default connect(mapStateToProps, mapDispatchToProps)(ModbusLogPage);

View File

@ -28,7 +28,8 @@ const getDefaultState = () => ({
iogroup: []
},
modbus: {
list: []
list: [],
log: []
},
link: {
list: []
@ -152,6 +153,7 @@ const listsReducer = (state = getDefaultState(), action) => {
return {
...state,
modbus: {
...state.modbus,
list: state.modbus.list.map(t=> mb_data(t, action))
}
}
@ -159,9 +161,18 @@ const listsReducer = (state = getDefaultState(), action) => {
return {
...state,
modbus: {
...state.modbus,
list: state.modbus.list.map(t=> mb_data(t, action))
}
}
case 'mb_log':
return {
...state,
modbus: {
...state.modbus,
log: action.list
}
}
case 'clear_modbus':
return {...state, modbus: {...getDefaultState().modbus}};
case 'link_list':

View File

@ -11,6 +11,7 @@ import IOCmd from './containers/AdminPage/IOCmd';
import Schedule from './containers/AdminPage/Schedule';
import Modbus from './containers/AdminPage/Modbus';
import ModbusCmd from './containers/AdminPage/ModbusCmd';
import ModbusLog from './containers/AdminPage/ModbusLog';
import ActionLink from './containers/AdminPage/ActionLink';
import ActionLinkAdd from './containers/AdminPage/ActionLinkAdd';
import IPCam from './containers/AdminPage/IPCam';
@ -29,6 +30,7 @@ const Routes = (
<Route path="link" component={ActionLink} />
<Route path="addlink" component={ActionLinkAdd} />
<Route path="modbuscmd" component={ModbusCmd} />
<Route path="modbuslog" component={ModbusLog} />
<Route path="ipcam" component={IPCam} />
</Route>
);