antd/lib/table#PaginationConfig TypeScript Examples
The following examples show how to use
antd/lib/table#PaginationConfig.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: ProTable.tsx From jetlinks-ui-antd with MIT License | 5 votes |
ProTable = (props: Props) => {
const { loading, dataSource, columns, rowKey, onSearch, paginationConfig,title } = props;
const onTableChange = (
pagination: PaginationConfig,
filters: any,
sorter: SorterResult<any>,
) => {
onSearch({
pageIndex: Number(pagination.current) - 1,
pageSize: pagination.pageSize,
sorts: sorter,
terms: converFilter(filters, '$IN'),
})
};
return (
<Table
{...props}
size={props.size}
// loading={loading}
// dataSource={dataSource}
// columns={columns}
// rowKey={rowKey}
onChange={onTableChange}
pagination={typeof paginationConfig === "boolean" ? paginationConfig : {
current: paginationConfig?.pageIndex + 1 || 0,
total: paginationConfig?.total || 0,
pageSize: paginationConfig?.pageSize || 0,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ['10', '20', '50', '100'],
showTotal: (total: number) =>
`共 ${total} 条记录 第 ${paginationConfig?.pageIndex + 1}/${Math.ceil(
paginationConfig?.total / paginationConfig?.pageSize,
)}页`,
}}
/>
)
}
Example #2
Source File: index.tsx From jetlinks-ui-antd with MIT License | 5 votes |
Event: React.FC<Props> = props => {
const initState: State = {
list: {},
searchParam: { pageIndex: 0, pageSize: 10 },
};
const [list, setList] = useState(initState.list);
const [searchParam, setSearchParam] = useState(initState.searchParam);
const handleSearch = (params?: any) => {
apis.ruleInstance.event(props.data.id, encodeQueryParam(params)).then(response => {
if (response.status === 200) {
setList(response.result);
}
});
setSearchParam(params);
};
useEffect(() => {
handleSearch({
pageIndex: 0,
pageSize: 10,
});
}, []);
const onTableChange = (pagination: PaginationConfig) => {
handleSearch({
pageIndex: Number(pagination.current) - 1,
pageSize: pagination.pageSize,
sorts: {
field: 'createTime',
order: 'desc',
},
terms: searchParam.terms,
});
};
return (
<div>
<Search
search={(params: any) => {
handleSearch({ terms: params, pageSize: 10 });
}}
/>
<Table
rowKey="id"
onChange={onTableChange}
pagination={{
current: list.pageIndex + 1,
total: list.total,
pageSize: list.pageSize,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ['10', '20', '50', '100'],
showTotal: (total: number) =>
`共 ${total} 条记录 第 ${list.pageIndex + 1}/${Math.ceil(
list.total / list.pageSize,
)}页`,
}}
columns={[
{
dataIndex: 'createTime',
title: '时间',
defaultSortOrder: 'descend',
render: text => moment(text).format('YYYY-MM-DD HH:mm:ss'),
},
{
dataIndex: 'event',
title: '事件',
},
{
dataIndex: 'ruleData',
title: '数据',
},
]}
dataSource={list.data}
/>
</div>
);
}
Example #3
Source File: index-backups.tsx From jetlinks-ui-antd with MIT License | 4 votes |
DeviceInstancePage: React.FC<Props> = props => {
const { result } = props.deviceInstance;
const initState: State = {
data: result,
searchParam: { pageSize: 10 },
addVisible: false,
currentItem: {},
processVisible: false,
importLoading: false,
action: '',
};
const [searchParam, setSearchParam] = useState(initState.searchParam);
const [addVisible, setAddvisible] = useState(initState.addVisible);
const [currentItem, setCurrentItem] = useState(initState.currentItem);
const [importLoading, setImportLoading] = useState(initState.importLoading);
const [action, setAction] = useState(initState.action);
const { dispatch } = props;
const statusMap = new Map();
statusMap.set('在线', 'success');
statusMap.set('离线', 'error');
statusMap.set('未激活', 'processing');
const handleSearch = (params?: any) => {
setSearchParam(params);
dispatch({
type: 'deviceInstance/query',
payload: encodeQueryParam(params),
});
};
const delelteInstance = (record: any) => {
apis.deviceInstance
.remove(record.id)
.then(response => {
if (response.status === 200) {
message.success('操作成功');
handleSearch(searchParam);
}
})
.catch(() => {});
};
const changeDeploy = (record: any) => {
apis.deviceInstance
.changeDeploy(record.id)
.then(response => {
if (response.status === 200) {
message.success('操作成功');
handleSearch(searchParam);
}
})
.catch(() => {});
};
const unDeploy = (record: any) => {
apis.deviceInstance
.unDeploy(record.id)
.then(response => {
if (response.status === 200) {
message.success('操作成功');
handleSearch(searchParam);
}
})
.catch(() => {});
};
const columns: ColumnProps<DeviceInstance>[] = [
{
title: 'ID',
dataIndex: 'id',
},
{
title: '设备名称',
dataIndex: 'name',
},
{
title: '产品名称',
dataIndex: 'productName',
},
{
title: '注册时间',
dataIndex: 'registryTime',
width: '200px',
render: (text: any) => moment(text).format('YYYY-MM-DD HH:mm:ss'),
sorter: true,
defaultSortOrder: 'descend',
},
{
title: '状态',
dataIndex: 'state',
render: record =>
record ? <Badge status={statusMap.get(record.text)} text={record.text} /> : '',
},
{
title: '描述',
dataIndex: 'describe',
},
{
title: '操作',
width: '200px',
align: 'center',
render: (record: any) => (
<Fragment>
<a
onClick={() => {
router.push(`/device/instance/save/${record.id}`);
}}
>
查看
</a>
<Divider type="vertical" />
<a
onClick={() => {
setCurrentItem(record);
setAddvisible(true);
}}
>
编辑
</a>
<Divider type="vertical" />
{record.state?.value === 'notActive' ? (
<span>
<Popconfirm
title="确认激活?"
onConfirm={() => {
changeDeploy(record);
}}
>
<a>激活</a>
</Popconfirm>
<Divider type="vertical" />
<Popconfirm
title="确认删除?"
onConfirm={() => {
delelteInstance(record);
}}
>
<a>删除</a>
</Popconfirm>
</span>
) : (
<Popconfirm
title="确认注销设备?"
onConfirm={() => {
unDeploy(record);
}}
>
<a>注销</a>
</Popconfirm>
)}
</Fragment>
),
},
];
useEffect(() => {
handleSearch(searchParam);
}, []);
const saveDeviceInstance = (item: any) => {
dispatch({
type: 'deviceInstance/update',
payload: encodeQueryParam(item),
callback: (response:any) => {
if (response.status === 200) {
message.success('保存成功');
setAddvisible(false);
router.push(`/device/instance/save/${item.id}`);
}
},
});
};
const onTableChange = (
pagination: PaginationConfig,
filters: any,
sorter: SorterResult<DeviceInstance>,
) => {
handleSearch({
pageIndex: Number(pagination.current) - 1,
pageSize: pagination.pageSize,
terms: searchParam.terms,
sorts: sorter,
});
};
const [processVisible, setProcessVisible] = useState(false);
const [api, setAPI] = useState<string>('');
const getSearchParam = () => {
const data = encodeQueryParam(searchParam);
let temp = '';
Object.keys(data).forEach((i: string) => {
if (data[i] && i !== 'pageSize' && i !== 'pageIndex') {
temp += `${i}=${data[i]}&`;
}
});
return encodeURI(temp.replace(/%/g, '%'));
};
// 激活全部设备
const startImport = () => {
// let dt = 0;
setProcessVisible(true);
const activeAPI = `/jetlinks/device-instance/deploy?${getSearchParam()}:X_Access_Token=${getAccessToken()} `;
setAPI(activeAPI);
setAction('active');
};
const startSync = () => {
setProcessVisible(true);
const syncAPI = `/jetlinks/device-instance/state/_sync/?${getSearchParam()}:X_Access_Token=${getAccessToken()}`;
setAPI(syncAPI);
setAction('sync');
};
const activeDevice = () => {
Modal.confirm({
title: `确认激活全部设备`,
okText: '确定',
okType: 'primary',
cancelText: '取消',
onOk() {
startImport();
},
});
};
const syncDevice = () => {
Modal.confirm({
title: '确定同步设备真实状态?',
okText: '确定',
okType: 'primary',
cancelText: '取消',
onOk() {
// 同步设备
startSync();
},
});
};
const [uploading, setUploading] = useState(false);
const exportDevice = () => {
const formElement = document.createElement('form');
formElement.style.display = 'display:none;';
formElement.method = 'post';
formElement.action = `/jetlinks/device-instance/export?:X_Access_Token=${getAccessToken()}`;
const params = encodeQueryParam(searchParam);
Object.keys(params).forEach((key: string) => {
const inputElement = document.createElement('input');
inputElement.type = 'hidden';
inputElement.name = key;
inputElement.value = params[key];
formElement.appendChild(inputElement);
});
document.body.appendChild(formElement);
formElement.submit();
document.body.removeChild(formElement);
};
const uploadProps: UploadProps = {
accept: '.xlsx, .xls',
action: '/jetlinks/file/static',
headers: {
'X-Access-Token': getAccessToken(),
},
showUploadList: false,
onChange(info) {
if (info.file.status === 'done') {
setUploading(false);
const fileUrl = info.file.response.result;
const url = `/jetlinks/device-instance/import?fileUrl=${fileUrl}&:X_Access_Token=${getAccessToken()}`;
setAPI(url);
setAction('import');
setImportLoading(true);
}
if (info.file.status === 'uploading') {
setUploading(true);
}
},
};
return (
<PageHeaderWrapper title="设备管理">
<Spin spinning={uploading} tip="上传中...">
<Card bordered={false}>
<div className={styles.tableList}>
<div className={styles.tableListForm}>
<Search
search={(params: any) => {
setSearchParam(params);
handleSearch({ terms: params, pageSize: 10 });
}}
/>
</div>
<div className={styles.tableListOperator}>
<Button
icon="plus"
type="primary"
onClick={() => {
setCurrentItem({});
setAddvisible(true);
}}
>
新建
</Button>
<Divider type="vertical" />
<Button href={template} download="设备模版" icon="download">
下载模版
</Button>
<Divider type="vertical" />
<Button icon="download" type="default" onClick={() => exportDevice()}>
导出设备
</Button>
<Divider type="vertical" />
<Upload {...uploadProps}>
<Button icon="upload">导入设备</Button>
</Upload>
<Divider type="vertical" />
<Button icon="check-circle" type="danger" onClick={() => activeDevice()}>
激活全部设备
</Button>
<Divider type="vertical" />
<Button icon="sync" type="danger" onClick={() => syncDevice()}>
同步设备状态
</Button>
</div>
<div className={styles.StandardTable}>
<Table
loading={props.loading}
columns={columns}
dataSource={(result || {}).data}
rowKey="id"
onChange={onTableChange}
pagination={{
current: result.pageIndex + 1,
total: result.total,
pageSize: result.pageSize,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ['10', '20', '50', '100'],
showTotal: (total: number) =>
`共 ${total} 条记录 第 ${result.pageIndex + 1}/${Math.ceil(
result.total / result.pageSize,
)}页`,
}}
/>
</div>
</div>
</Card>
{addVisible && (
<Save
data={currentItem}
close={() => {
setAddvisible(false);
setCurrentItem({});
}}
save={(item: any) => {
saveDeviceInstance(item);
}}
/>
)}
{(processVisible || importLoading) && (
<Process
api={api}
action={action}
closeVisible={() => {
setProcessVisible(false);
setImportLoading(false);
handleSearch(searchParam);
}}
/>
)}
</Spin>
</PageHeaderWrapper>
);
}
Example #4
Source File: propertiesInfo.tsx From jetlinks-ui-antd with MIT License | 4 votes |
PropertiesInfo: React.FC<Props> = props => {
const {
form: { getFieldDecorator },
form,
} = props;
const initState: State = {
eventColumns: [
{
title: '时间',
dataIndex: 'timestamp',
render: text => moment(text).format('YYYY-MM-DD HH:mm:ss'),
},
{
title: `${props.item.name}(点击可复制)`,
dataIndex: 'formatValue',
ellipsis: true,
render: text => (
<CopyToClipboard text={text} onCopy={() => message.success('已复制')}>
<span>{typeof (text) === 'object' ? JSON.stringify(text) : text}<Icon type="copy" /></span>
</CopyToClipboard>
)
},
{
title: '操作',
dataIndex: 'value',
render: (text) => (
<>
<a onClick={() => {
Modal.info({
title: '详情',
width: 850,
content: (
<Form.Item wrapperCol={{ span: 20 }} labelCol={{ span: 4 }} label={props.item.name}>
<AceEditor
value={JSON.stringify((text), null, 2)}
mode='json'
theme="eclipse"
name="app_code_editor"
key='deviceShadow'
fontSize={14}
showPrintMargin
showGutter
wrapEnabled
highlightActiveLine //突出活动线
enableSnippets //启用代码段
style={{ width: '100%', height: '50vh' }}
setOptions={{
enableBasicAutocompletion: true, //启用基本自动完成功能
enableLiveAutocompletion: true, //启用实时自动完成功能 (比如:智能代码提示)
enableSnippets: true, //启用代码段
showLineNumbers: true,
tabSize: 2,
}}
/>
</Form.Item>
),
okText: '关闭',
onOk() {
console.log('OK');
},
});
}}>详情</a>
</>
)
}
],
propertiesInfo: {},
marksCreated: {},
gatewayDataList: [],
lineArr: [],
labelMarkerList: [],
labelsDataList: [],
mapCenter: [106.57, 29.52],
markerPosition: [],
mapCreated: {},
tabsType: '1',
};
const [marksCreated, setMarksCreated] = useState(initState.marksCreated);
const [mapCenter, setMapCenter] = useState(initState.mapCenter);
const [propertiesInfo, setPropertiesInfo] = useState<any>({});
const [gatewayData, setGatewayData] = useState(initState.gatewayDataList);
const [lineArr, setLineArr] = useState(initState.lineArr);
const [spinning, setSpinning] = useState(true);
const [statistics, setStatistics] = useState(false);
const [mapCreated, setMapCreated] = useState(initState.mapCreated);
const [labelMarkerList] = useState(initState.labelMarkerList);
const [labelsDataList, setLabelsDataList] = useState(initState.labelMarkerList);
const [markerPosition, setMarkerPosition] = useState(initState.markerPosition);
const [tabsType, setTabsType] = useState(initState.tabsType);
const [labelsLayer, setLabelsLayer] = useState<any>();
const [drawPolyline, setDrawPolyline] = useState<any>();
const [passedPolyline, setPassedPolyline] = useState<any>();
const handleSearch = (params?: any) => {
apis.deviceInstance.propertieInfo(props.deviceId, encodeQueryParam({
terms: {
...params.terms,
property: props.item.id
},
sorts: {
field: 'timestamp',
order: 'desc',
},
pageIndex: params.pageIndex || 0,
pageSize: params.pageSize || 10
}))
.then((response: any) => {
if (response.status === 200) {
setPropertiesInfo(response.result);
}
setSpinning(false);
})
.catch(() => {
});
};
const statisticsChart = (params?: any) => {
apis.deviceInstance.propertieInfo(props.deviceId, encodeQueryParam(params))
.then((response: any) => {
if (response.status === 200) {
const dataList: any[] = [];
response.result.data.forEach((item: any) => {
dataList.push({
year: moment(item.timestamp).format('YYYY-MM-DD HH:mm:ss'),
value: Number(item.value),
type: props.item.name
});
});
setGatewayData(dataList);
}
setSpinning(false);
})
.catch(() => {
});
};
const trajectory = (params?: any) => {
apis.deviceInstance.propertieInfo(props.deviceId, encodeQueryParam(params))
.then((response: any) => {
if (response.status === 200) {
let list: any[] = [];
let labelsData: any[] = [];
let position: any[] = [];
response.result.data?.map((item: any, index: number) => {
if (index === 0) {
setMapCenter([item.geoValue.lon, item.geoValue.lat]);
setMarkerPosition([item.geoValue.lon, item.geoValue.lat]);
position = [item.geoValue.lon, item.geoValue.lat];
}
list.push([item.geoValue.lon, item.geoValue.lat]);
labelsData.push({
name: item.timestamp, // 时间
position: [item.geoValue.lon, item.geoValue.lat], //经纬度
zooms: [3, 20],
opacity: 1,
rank: index, //index
icon: {
type: 'image',
image: mark_b,
size: [19, 22],
anchor: 'bottom-center',
},
text: {
content: moment(item.timestamp).format('YYYY-MM-DD HH:mm:ss'), //时间
direction: 'top',
offset: [0, -2],
lnglat: [item.geoValue.lon, item.geoValue.lat], //经纬度
style: {
fontSize: 12,
fontWeight: 'normal',
fillColor: '#FFFFFF',
padding: '6 10 6 10',
backgroundColor: '#5C5C5C',
},
},
});
});
setLineArr([...list]);
setLabelsDataList([...labelsData]);
if (Object.keys(mapCreated).length != 0) {
mapElement(mapCreated, position, list, labelsData);
}
}
setSpinning(false);
})
.catch(() => {
});
};
useEffect(() => {
if (props.item.valueType.type === 'int' || props.item.valueType.type === 'float'
|| props.item.valueType.type === 'double' || props.item.valueType.type === 'long') {
setStatistics(true);
}
handleSearch({
pageIndex: 0,
pageSize: 10,
sorts: {
field: 'timestamp',
order: 'desc',
},
terms: { property: props.item.id },
});
if (props.item.valueType.type === 'geoPoint') {
trajectory({
pageIndex: 0,
pageSize: 1000,
sorts: {
field: 'timestamp',
order: 'asc',
},
terms: { property: props.item.id },
}
);
}
}, []);
const onTableChange = (pagination: PaginationConfig) => {
const params = queryParams();
handleSearch({
pageIndex: Number(pagination.current) - 1,
pageSize: pagination.pageSize,
sorts: {
field: 'timestamp',
order: 'desc',
},
terms: { ...params, property: props.item.id },
});
};
const queryParams = () => {
let params = form.getFieldsValue();
if (params.timestamp$BTW) {
let formatDate = params.timestamp$BTW.map((e: Moment) =>
moment(e).format('YYYY-MM-DD HH:mm:ss'),
);
params.timestamp$BTW = formatDate.join(',');
}
return params;
};
const unSearch = () => {
if (tabsType === '1') {
if (Object.keys(mapCreated).length != 0) {
mapCreated.remove(labelsLayer);
labelsLayer.clear();
}
handleSearch({
pageIndex: 0,
pageSize: 10,
sorts: {
field: 'timestamp',
order: 'desc',
},
terms: { property: props.item.id },
});
if (props.item.valueType.type === 'geoPoint') {
geoPoint();
}
} else if (tabsType === '2') {
statisticsChart(
{
pageIndex: 0,
pageSize: 60,
sorts: {
field: 'timestamp',
order: 'desc',
},
terms: { property: props.item.id },
}
);
} else {
geoPoint();
}
};
const geoPoint = (params?: any) => {
if (Object.keys(mapCreated).length != 0) {
mapCreated.remove([marksCreated, labelsLayer, passedPolyline, drawPolyline]);
labelsLayer.clear();
}
setLineArr([]);
setLabelsDataList([]);
setMarkerPosition([]);
trajectory({
pageIndex: 0,
pageSize: 1000,
sorts: {
field: 'timestamp',
order: 'asc',
},
terms: { ...params, property: props.item.id },
}
);
};
const tabs = (params: any) => {
if (Object.keys(mapCreated).length != 0) {
mapCreated.remove(labelsLayer);
labelsLayer.clear();
}
setSpinning(true);
handleSearch({
pageIndex: 0,
pageSize: 10,
sorts: {
field: 'timestamp',
order: 'desc',
},
terms: { ...params, property: props.item.id },
});
if (props.item.valueType.type === 'geoPoint') {
geoPoint(params);
}
};
const onSearch = () => {
setSpinning(true);
let params = queryParams();
if (tabsType === '1') {
tabs(params);
} else if (tabsType === '2') {
statisticsChart(
{
pageIndex: 0,
pageSize: 60,
sorts: {
field: 'timestamp',
order: 'desc',
},
terms: { ...params, property: props.item.id },
}
);
} else {
geoPoint(params);
}
};
const mapElement = (ins: any, position: any, line: any, labelsData: any) => {
let marker = new window.AMap.Marker({
map: ins,
position: position,
icon: img26,
offset: new window.AMap.Pixel(-13, -13),
autoRotation: true,
angle: -90,
});
setMarksCreated(marker);
// 绘制轨迹
let draw = new window.AMap.Polyline({
map: ins,
path: line,
showDir: true,
strokeColor: "#f5222d", //线颜色
// strokeOpacity: 1, //线透明度
strokeWeight: 6, //线宽
// strokeStyle: "solid" //线样式
});
setDrawPolyline(draw);
// 运动轨迹
let passed = new window.AMap.Polyline({
map: ins,
// path: lineArr,
strokeColor: "#AF5", //线颜色
// strokeOpacity: 1, //线透明度
strokeWeight: 6, //线宽
// strokeStyle: "solid" //线样式
});
setPassedPolyline(passed);
marker.on('moving', function (e: any) {
passed.setPath(e.passedPath);
});
// 创建轨迹上的点位
let layer = new window.AMap.LabelsLayer({
zooms: [3, 20],
visible: true,
collision: false,
});
layer.remove(labelMarkerList);
setLabelsLayer(layer);
ins.add(layer);
labelMarkerList.splice(0, labelMarkerList.length);
let labelMarker = {};
labelsData.map((item: any) => {
labelMarker = new window.AMap.LabelMarker(item);
labelMarkerList.push(labelMarker);
layer.add(labelMarker);
});
};
// map事件列表
const mapEvents = {
created: (ins: any) => {
setMapCreated(ins);
mapElement(ins, markerPosition, lineArr, labelsDataList);
},
};
return (
<Modal
title="属性详情"
visible
onCancel={() => props.close()}
onOk={() => props.close()}
width="70%"
>
<Spin spinning={spinning}>
<Form labelCol={{ span: 0 }} wrapperCol={{ span: 18 }}>
<Row gutter={{ md: 8, lg: 4, xl: 48 }}>
<Col md={10} sm={24}>
<Form.Item>
{getFieldDecorator('timestamp$BTW')(
<DatePicker.RangePicker
showTime={{ format: 'HH:mm:ss' }}
format="YYYY-MM-DD HH:mm:ss"
placeholder={['开始时间', '结束时间']}
onChange={(value: any[]) => {
if (value.length === 0) {
unSearch();
}
}}
onOk={onSearch}
/>,
)}
</Form.Item>
</Col>
</Row>
</Form>
<Tabs defaultActiveKey="1" tabPosition="top" type="card"
onTabClick={(value: string) => {
setTabsType(value);
let params = queryParams();
if (value === '1') {
tabs(params);
} else if (value === '2') {
setSpinning(true);
statisticsChart(
{
pageIndex: 0,
pageSize: 60,
sorts: {
field: 'timestamp',
order: 'desc',
},
terms: { ...params, property: props.item.id },
}
);
}
}}
>
<Tabs.TabPane tab="列表" key="1">
<Table
loading={spinning}
columns={initState.eventColumns}
dataSource={(propertiesInfo || {}).data}
rowKey="id"
size="small"
onChange={onTableChange}
pagination={{
current: propertiesInfo.pageIndex + 1,
total: propertiesInfo.total,
pageSize: propertiesInfo.pageSize,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ['10', '20', '50', '100'],
showTotal: (total: number) =>
`共 ${total} 条记录 第 ${propertiesInfo.pageIndex + 1}/${Math.ceil(
propertiesInfo.total / propertiesInfo.pageSize,
)}页`,
}}
/>
</Tabs.TabPane>
{statistics && (
<Tabs.TabPane tab="图表" key="2">
<Chart
height={400}
data={gatewayData}
scale={{
value: { min: 0 },
year: {
range: [0, 0.96],
type: 'timeCat'
},
}}
forceFit
>
<Axis name="year" />
<Axis name="value" label={{
formatter: val => parseFloat(val).toLocaleString()
}} />
<Legend />
<Tooltip crosshairs={{ type: 'y' }} />
<Geom type="line" position="year*value" size={2} tooltip={[
"year*value*type",
(year, value, type) => ({
title: moment(year).format('YYYY-MM-DD HH:mm:ss'),
name: type,
value: value
})
]} />
<Geom type="area" position="year*value" shape={'circle'} tooltip={[
"year*value*type",
(year, value, type) => ({
title: moment(year).format('YYYY-MM-DD HH:mm:ss'),
name: type,
value: value
})
]}
/>
</Chart>
</Tabs.TabPane>
)}
{props.item.valueType.type === 'geoPoint' && (
<Tabs.TabPane tab={
<span>
轨迹
<AntdTooltip title='默认启动循环执行动画,运动速度为:200km/h'>
<Icon type="question-circle-o" style={{ paddingLeft: 10 }} />
</AntdTooltip>
</span>
} key="3">
<div style={{ width: '100%', height: '60vh' }}>
<Map version="1.4.15" resizeEnable events={mapEvents} center={mapCenter} />
</div>
<div style={{ marginTop: '-6.4%', paddingRight: 2, textAlign: 'right', float: 'right' }}>
<Card style={{ width: 240 }}>
<Button type="primary"
onClick={() => {
marksCreated.moveAlong(
lineArr, // 路径坐标串
200, // 指定速度,单位:千米/小时,不可为0
function (k: any) { // 回调函数f为变化曲线函数,缺省为function(k){return k}
return k
},
true // true表明是否循环执行动画,默认为false
);
}}
>
开始动画
</Button>
<Button style={{ marginLeft: 10 }} type="primary"
onClick={() => {
marksCreated.stopMove();
}}
>
停止动画
</Button>
</Card>
</div>
</Tabs.TabPane>
)}
</Tabs>
</Spin>
</Modal>
);
}
Example #5
Source File: index.tsx From jetlinks-ui-antd with MIT License | 4 votes |
DeviceInstancePage: React.FC<Props> = props => {
const { result } = props.deviceInstance;
const { dispatch, location } = props;
const map = new Map();
map.set('id', 'id$like');
map.set('name', 'name$like');
map.set('orgId', 'orgId$in');
map.set('devTag', 'id$dev-tag');
map.set('devBind', 'id$dev-bind$any');
map.set('devProd', 'productId$dev-prod-cat');
map.set('productId', 'productId');
const initState: State = {
data: result,
searchParam: {
pageSize: 10,
terms: location?.query?.terms,
sorts: {
order: 'desc',
field: 'id',
},
},
addVisible: false,
currentItem: {},
processVisible: false,
importLoading: false,
action: '',
deviceCount: {
notActiveCount: 0,
offlineCount: 0,
onlineCount: 0,
deviceTotal: 0,
loading: true,
},
productList: [],
deviceIdList: [],
};
const [searchParam, setSearchParam] = useState(initState.searchParam);
const [addVisible, setAddVisible] = useState(initState.addVisible);
const [currentItem, setCurrentItem] = useState(initState.currentItem);
const [importLoading, setImportLoading] = useState(initState.importLoading);
const [action, setAction] = useState(initState.action);
const [productList, setProductList] = useState(initState.productList);
const [product, setProduct] = useState<string>();
const [deviceCount, setDeviceCount] = useState(initState.deviceCount);
const [deviceImport, setDeviceImport] = useState(false);
const [deviceExport, setDeviceExport] = useState(false);
const [deviceIdList, setDeviceIdLIst] = useState(initState.deviceIdList);
const statusMap = new Map();
statusMap.set('在线', 'success');
statusMap.set('离线', 'error');
statusMap.set('未激活', 'processing');
statusMap.set('online', 'success');
statusMap.set('offline', 'error');
statusMap.set('notActive', 'processing');
const handleSearch = (params?: any) => {
setSearchParam(params);
dispatch({
type: 'deviceInstance/query',
payload: encodeQueryParam(params),
});
};
const delelteInstance = (record: any) => {
apis.deviceInstance
.remove(record.id)
.then(response => {
if (response.status === 200) {
message.success('操作成功');
deviceIdList.splice(0, deviceIdList.length);
handleSearch(searchParam);
}
})
.catch(() => {});
};
const changeDeploy = (record: any) => {
apis.deviceInstance
.changeDeploy(record.id)
.then(response => {
if (response.status === 200) {
message.success('操作成功');
deviceIdList.splice(0, deviceIdList.length);
handleSearch(searchParam);
}
})
.catch(() => {});
};
const unDeploy = (record: any) => {
apis.deviceInstance
.unDeploy(record.id)
.then(response => {
if (response.status === 200) {
message.success('操作成功');
deviceIdList.splice(0, deviceIdList.length);
handleSearch(searchParam);
}
})
.catch(() => {});
};
const columns: ColumnProps<DeviceInstance>[] = [
{
title: 'ID',
dataIndex: 'id',
},
{
title: '设备名称',
dataIndex: 'name',
ellipsis: true,
},
{
title: '产品名称',
dataIndex: 'productName',
ellipsis: true,
},
{
title: '注册时间',
dataIndex: 'registryTime',
width: '200px',
render: (text: any) => (text ? moment(text).format('YYYY-MM-DD HH:mm:ss') : '/'),
sorter: true,
},
{
title: '状态',
dataIndex: 'state',
width: '90px',
render: record =>
record ? <Badge status={statusMap.get(record.value)} text={record.text} /> : '',
filters: [
{
text: '未启用',
value: 'notActive',
},
{
text: '离线',
value: 'offline',
},
{
text: '在线',
value: 'online',
},
],
filterMultiple: false,
},
{
title: '说明',
dataIndex: 'describe',
width: '15%',
ellipsis: true,
},
{
title: '操作',
width: '200px',
align: 'center',
render: (record: any) => (
<Fragment>
<a
onClick={() => {
router.push(`/device/instance/save/${record.id}`);
}}
>
查看
</a>
<Divider type="vertical" />
<a
onClick={() => {
setCurrentItem(record);
setAddVisible(true);
}}
>
编辑
</a>
<Divider type="vertical" />
{record.state?.value === 'notActive' ? (
<span>
<Popconfirm
title="确认启用?"
onConfirm={() => {
changeDeploy(record);
}}
>
<a>启用</a>
</Popconfirm>
<Divider type="vertical" />
<Popconfirm
title="确认删除?"
onConfirm={() => {
delelteInstance(record);
}}
>
<a>删除</a>
</Popconfirm>
</span>
) : (
<Popconfirm
title="确认禁用设备?"
onConfirm={() => {
unDeploy(record);
}}
>
<a>禁用</a>
</Popconfirm>
)}
</Fragment>
),
},
];
const stateCount = (productId: string) => {
const map = {
notActiveCount: 0,
offlineCount: 0,
onlineCount: 0,
deviceTotal: 0,
loading: true,
};
apis.deviceInstance
.count(
encodeQueryParam({
terms: {
state: 'notActive',
productId,
...location?.query?.terms,
...(location?.query.iop && JSON.parse(location?.query.iop)?.terms),
},
}),
)
.then(res => {
if (res.status === 200) {
map.notActiveCount = res.result;
setDeviceCount({ ...map });
}
})
.catch();
apis.deviceInstance
.count(
encodeQueryParam({
terms: {
state: 'offline',
productId,
...location?.query?.terms,
...(location?.query.iop && JSON.parse(location?.query.iop)?.terms),
},
}),
)
.then(res => {
if (res.status === 200) {
map.offlineCount = res.result;
setDeviceCount({ ...map });
}
})
.catch();
apis.deviceInstance
.count(
encodeQueryParam({
terms: {
state: 'online',
productId,
...location?.query?.terms,
...(location?.query.iop && JSON.parse(location?.query.iop)?.terms),
},
}),
)
.then(res => {
if (res.status === 200) {
map.onlineCount = res.result;
setDeviceCount({ ...map });
}
})
.catch();
apis.deviceInstance
.count(
encodeQueryParam({
terms: {
productId,
...location?.query?.terms,
...(location?.query.iop && JSON.parse(location?.query.iop)?.terms),
},
}),
)
.then(res => {
if (res.status === 200) {
map.deviceTotal = res.result;
map.loading = false;
setDeviceCount({ ...map });
}
})
.catch();
};
useEffect(() => {
// 获取下拉框数据
apis.deviceProdcut
.queryNoPagin(
encodeQueryParam({
paging: false,
}),
)
.then(e => {
setProductList(e.result);
})
.catch(() => {});
const query: any = getPageQuery();
if (query.hasOwnProperty('productId')) {
const { productId } = query;
setProduct(productId);
handleSearch({
terms: {
productId: query.productId,
},
pageSize: 10,
});
stateCount(productId);
} else if (location?.query) {
let key = Object.keys(location?.query)[0];
let params = {};
params[map.get(key)] = location?.query[key];
handleSearch({
terms: { ...params, ...(location?.query.iop && JSON.parse(location?.query.iop)?.terms) },
pageSize: 10,
sorts: searchParam.sorts,
});
stateCount('');
} else {
handleSearch(searchParam);
stateCount('');
}
}, []);
const onTableChange = (
pagination: PaginationConfig,
filters: any,
sorter: SorterResult<DeviceInstance>,
) => {
let { terms } = searchParam;
if (filters.state) {
if (terms) {
terms.state = filters.state[0];
} else {
terms = {
state: filters.state[0],
};
}
}
handleSearch({
pageIndex: Number(pagination.current) - 1,
pageSize: pagination.pageSize,
terms,
sorts: sorter,
});
};
const [processVisible, setProcessVisible] = useState(false);
const [api, setAPI] = useState<string>('');
const getSearchParam = () => {
const data = encodeQueryParam(searchParam);
let temp = '';
Object.keys(data).forEach((i: string) => {
if (data[i] && i !== 'pageSize' && i !== 'pageIndex') {
temp += `${i}=${data[i]}&`;
}
});
return encodeURI(temp.replace(/%/g, '%'));
};
// 激活全部设备
const startImport = () => {
setProcessVisible(true);
const activeAPI = `/jetlinks/device-instance/deploy?${getSearchParam()}:X_Access_Token=${getAccessToken()} `;
setAPI(activeAPI);
setAction('active');
};
const startSync = () => {
setProcessVisible(true);
const syncAPI = `/jetlinks/device-instance/state/_sync/?${getSearchParam()}:X_Access_Token=${getAccessToken()}`;
setAPI(syncAPI);
setAction('sync');
};
const activeDevice = () => {
Modal.confirm({
title: `确认激活全部设备`,
okText: '确定',
okType: 'primary',
cancelText: '取消',
onOk() {
startImport();
},
});
};
const syncDevice = () => {
Modal.confirm({
title: '确定同步设备真实状态?',
okText: '确定',
okType: 'primary',
cancelText: '取消',
onOk() {
// 同步设备
startSync();
},
});
};
const onDeviceProduct = (value: string) => {
let { terms } = searchParam;
if (terms) {
terms.productId = value;
} else {
terms = {
productId: value,
};
}
handleSearch({
pageIndex: searchParam.pageIndex,
pageSize: searchParam.pageSize,
terms,
sorts: searchParam.sorter,
});
stateCount(value);
};
const rowSelection = {
onChange: (selectedRowKeys: any) => {
setDeviceIdLIst(selectedRowKeys);
},
};
const _delete = (deviceId: any[]) => {
Modal.confirm({
title: `确认删除选中设备`,
okText: '确定',
okType: 'primary',
cancelText: '取消',
onOk() {
apis.deviceInstance
._delete(deviceId)
.then(response => {
if (response.status === 200) {
message.success('成功删除选中设备');
deviceIdList.splice(0, deviceIdList.length);
handleSearch(searchParam);
}
})
.catch(() => {});
},
});
};
const _unDeploy = (deviceId: any[]) => {
Modal.confirm({
title: `确认注销选中设备`,
okText: '确定',
okType: 'primary',
cancelText: '取消',
onOk() {
apis.deviceInstance
._unDeploy(deviceId)
.then(response => {
if (response.status === 200) {
message.success('成功注销选中设备');
deviceIdList.splice(0, deviceIdList.length);
handleSearch(searchParam);
}
})
.catch(() => {});
},
});
};
const _deploy = (deviceId: any[]) => {
Modal.confirm({
title: `确认激活选中设备`,
okText: '确定',
okType: 'primary',
cancelText: '取消',
onOk() {
apis.deviceInstance
._deploy(deviceId)
.then(response => {
if (response.status === 200) {
message.success('成功激活选中设备');
deviceIdList.splice(0, deviceIdList.length);
handleSearch(searchParam);
}
})
.catch(() => {});
},
});
};
const Info: FC<{
title: React.ReactNode;
value: React.ReactNode;
}> = ({ title, value }) => (
<div>
<span>{title}</span>
<p style={{ fontSize: '26px' }}>{value}</p>
</div>
);
const menu = (
<Menu>
<Menu.Item key="1">
<Button
icon="download"
type="default"
onClick={() => {
setDeviceExport(true);
}}
>
批量导出设备
</Button>
</Menu.Item>
<Menu.Item key="2">
<Button
icon="upload"
onClick={() => {
setDeviceImport(true);
}}
>
批量导入设备
</Button>
</Menu.Item>
{deviceIdList.length > 0 && (
<Menu.Item key="3">
<Button
icon="delete"
onClick={() => {
_delete(deviceIdList);
}}
>
删除选中设备
</Button>
</Menu.Item>
)}
{deviceIdList.length > 0 && (
<Menu.Item key="6">
<Button
icon="stop"
onClick={() => {
_unDeploy(deviceIdList);
}}
>
注销选中设备
</Button>
</Menu.Item>
)}
{deviceIdList.length > 0 ? (
<Menu.Item key="4">
<Button icon="check-circle" type="danger" onClick={() => _deploy(deviceIdList)}>
激活选中设备
</Button>
</Menu.Item>
) : (
<Menu.Item key="4">
<Button icon="check-circle" type="danger" onClick={() => activeDevice()}>
激活全部设备
</Button>
</Menu.Item>
)}
<Menu.Item key="5">
<Button icon="sync" type="danger" onClick={() => syncDevice()}>
同步设备状态
</Button>
</Menu.Item>
</Menu>
);
return (
<PageHeaderWrapper title="设备管理">
<div className={styles.standardList}>
<Card bordered={false} style={{ height: 95 }}>
<Spin spinning={deviceCount.loading}>
<Row>
<Col sm={7} xs={24}>
<Select
placeholder="选择产品"
showSearch
optionFilterProp='label'
allowClear
style={{ width: '70%', marginTop: 7 }}
value={product}
onChange={(value: string) => {
let key = Object.keys(location?.query)[0];
let params = {};
if (location?.query) {
params[key] = location?.query[key];
}
params['productId'] = value;
router.push({ pathname: `/device/instance`, query: params });
setProduct(() => value);
setDeviceCount({ loading: true });
onDeviceProduct(value);
}}
>
{productList?.map(item => (
<Select.Option key={item.id} label={item.name}>{item.name}</Select.Option>
))}
</Select>
</Col>
<Col sm={4} xs={24}>
<Info title="全部设备" value={numeral(deviceCount.deviceTotal).format('0,0')} />
</Col>
<Col sm={4} xs={24}>
<Info
title={<Badge status={statusMap.get('online')} text="在线" />}
value={numeral(deviceCount.onlineCount).format('0,0')}
/>
</Col>
<Col sm={4} xs={24}>
<Info
title={<Badge status={statusMap.get('offline')} text="离线" />}
value={numeral(deviceCount.offlineCount).format('0,0')}
/>
</Col>
<Col sm={4} xs={24}>
<Info
title={<Badge status={statusMap.get('notActive')} text="未启用" />}
value={numeral(deviceCount.notActiveCount).format('0,0')}
/>
</Col>
<Col sm={1} xs={24}>
<Tooltip title="刷新">
<Icon
type="sync"
style={{ fontSize: 20 }}
onClick={() => {
setDeviceCount({ loading: true });
stateCount(product);
}}
/>
</Tooltip>
</Col>
</Row>
</Spin>
</Card>
<br />
<Card bordered={false}>
<div className={styles.tableList}>
<div className={styles.tableListForm}>
<Search
type={'device-instance'}
search={(params: any) => {
if (Object.keys(params).length === 0) {
deviceIdList.splice(0, deviceIdList.length);
}
if (product) {
params.productId = product;
}
params.state = searchParam.terms?.state;
handleSearch({ terms: params, pageSize: 10, sorts: searchParam.sorts });
}}
/>
</div>
<div className={styles.tableListOperator}>
<Button
icon="plus"
type="primary"
onClick={() => {
setCurrentItem({});
setAddVisible(true);
}}
>
添加设备
</Button>
<Divider type="vertical" />
<Dropdown overlay={menu}>
<Button icon="menu">
其他批量操作
<Icon type="down" />
</Button>
</Dropdown>
</div>
<div className={styles.StandardTable}>
<Table
loading={props.loading}
columns={columns}
dataSource={(result || {}).data}
rowKey="id"
onChange={onTableChange}
rowSelection={{
type: 'checkbox',
...rowSelection,
}}
pagination={{
current: result.pageIndex + 1,
total: result.total,
pageSize: result.pageSize,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ['10', '20', '50', '100'],
showTotal: (total: number) =>
`共 ${total} 条记录 第 ${result.pageIndex + 1}/${Math.ceil(
result.total / result.pageSize,
)}页`,
}}
/>
</div>
</div>
</Card>
{addVisible && (
<Save
data={currentItem}
close={() => {
setAddVisible(false);
setCurrentItem({});
}}
/>
)}
{(processVisible || importLoading) && (
<Process
api={api}
action={action}
closeVisible={() => {
setProcessVisible(false);
setImportLoading(false);
handleSearch(searchParam);
}}
/>
)}
{deviceImport && (
<Import
productId={product}
close={() => {
setDeviceImport(false);
handleSearch(searchParam);
}}
/>
)}
{deviceExport && (
<Export
productId={product}
searchParam={searchParam}
close={() => {
setDeviceExport(false);
handleSearch(searchParam);
}}
/>
)}
</div>
</PageHeaderWrapper>
);
}
Example #6
Source File: index-backups.tsx From jetlinks-ui-antd with MIT License | 4 votes |
DeviceModel: React.FC<Props> = props => {
const { result } = props.deviceProduct;
const initState: State = {
data: result,
searchParam: { pageSize: 10 },
saveVisible: false,
};
const [searchParam, setSearchParam] = useState(initState.searchParam);
const [saveVisible, setSaveVisible] = useState(initState.saveVisible);
const [filterData, setFilterData] = useState({});
const { dispatch } = props;
const handleSearch = (params?: any) => {
setSearchParam(params);
dispatch({
type: 'deviceProduct/query',
payload: encodeQueryParam(params),
});
};
const deploy = (record: any) => {
dispatch({
type: 'deviceProduct/deploy',
payload: record.id,
callback: response => {
if (response.status === 200) {
message.success('操作成功');
handleSearch(searchParam);
}
},
});
};
const unDeploy = (record: any) => {
dispatch({
type: 'deviceProduct/unDeploy',
payload: record.id,
callback: response => {
if (response.status === 200) {
message.success('操作成功');
handleSearch(searchParam);
}
},
});
};
const handleDelete = (params: any) => {
dispatch({
type: 'deviceProduct/remove',
payload: params.id,
callback: response => {
if (response.status === 200) {
message.success('删除成功');
handleSearch(searchParam);
}
},
});
};
const columns: ColumnProps<DeviceProduct>[] = [
{
title: 'ID',
dataIndex: 'id',
width: '250px',
},
{
title: '产品名称',
dataIndex: 'name',
},
{
title: '类型',
dataIndex: 'deviceType',
width: '150px',
align: 'center',
render: (text: any) => (text || {}).text,
sorter: true,
},
{
title: '创建时间',
dataIndex: 'createTime',
width: '200px',
align: 'center',
render: (text: any) => moment(text).format('YYYY-MM-DD HH:mm:ss'),
sorter: true,
defaultSortOrder: 'descend',
},
{
title: '发布状态',
dataIndex: 'state',
align: 'center',
filters: [{
value: '0',
text: '未发布'
}, {
value: '1',
text: '已发布'
}],
render: (text: any) => {
const color = text === 0 ? 'red' : 'green';
const status = text === 0 ? '未发布' : '已发布';
return <Badge color={color} text={status} />;
},
},
{
title: '操作',
width: '300px',
align: 'center',
render: (record: DeviceProduct) => (
<Fragment>
<a
onClick={() => {
router.push(`/device/product/save/${record.id}`);
}}
>
查看
</a>
<Divider type="vertical" />
{record.state === 0 ? (
<span>
<Popconfirm
title="确认发布?"
onConfirm={() => {
deploy(record);
}}
>
<a>发布</a>
</Popconfirm>
<Divider type="vertical" />
<Popconfirm title="确定删除?" onConfirm={() => handleDelete(record)}>
<a>删除</a>
</Popconfirm>
</span>
) : (
<Popconfirm
title="确认停用"
onConfirm={() => {
unDeploy(record);
}}
>
<a>停用</a>
</Popconfirm>
)}
<Divider type="vertical" />
<a
onClick={() => {
downloadObject(record, '产品');
}}
>
下载配置
</a>
<Divider type="vertical" />
<a
onClick={() => {
router.push(`/device/instance?productId=${record.id}`);
}}
>
查看设备
</a>
</Fragment>
),
},
];
useEffect(() => {
handleSearch(searchParam);
}, []);
const handeSave = (record: any) => {
dispatch({
type: 'deviceProduct/insert',
payload: record,
callback: response => {
if (response.status === 200) {
setSaveVisible(false);
message.success('保存成功');
router.push(`/device/product/save/${record.id}`);
}
},
});
};
const onTableChange = (
pagination: PaginationConfig,
filters: any,
sorter: SorterResult<DeviceProduct>
) => {
const tempFilter = converObjectKey(filters, { state: 'state$IN' });
setFilterData(tempFilter);
handleSearch({
pageIndex: Number(pagination.current) - 1,
pageSize: pagination.pageSize,
terms: { ...searchParam, ...tempFilter },
sorts: sorter,
});
};
const uploadProps: UploadProps = {
accept: '.json',
action: '/jetlinks/file/static',
headers: {
'X-Access-Token': getAccessToken(),
},
showUploadList: false,
onChange(info) {
if (info.file.status === 'done') {
const fileUrl = info.file.response.result;
request(fileUrl, { method: 'GET' }).then(e => {
if (e || e !== null) {
dispatch({
type: 'deviceProduct/insert',
payload: e,
callback: (response: any) => {
if (response.status === 200) {
message.success('导入成功');
handleSearch(searchParam);
}
},
});
}
}).catch(() => {
message.error('导入配置失败');
});
}
},
};
// 消息协议
const [protocolSupports, setProtocolSupports] = useState([]);
useEffect(() => {
apis.deviceProdcut
.protocolSupport()
.then(response => {
if (response.status === 200) {
setProtocolSupports(response.result.map((i: any) => ({ id: i.id, name: i.name })));
}
})
.catch(() => { });
}, []);
return (
<PageHeaderWrapper title="产品管理">
<Card bordered={false}>
<div className={styles.tableList}>
<div>
<SearchForm
search={(params: any) => {
handleSearch({
terms: { ...params, ...filterData },
pageSize: 10,
sorts: searchParam.sorts
});
}}
formItems={[{
label: '产品名称',
key: 'name$LIKE',
type: 'string',
},
{
label: '设备类型',
key: 'deviceType',
type: 'list',
props: {
data: [
{ id: 'gateway', name: '网关' },
{ id: 'device', name: '设备' }
]
}
},
{
label: '消息协议',
key: 'messageProtocol',
type: 'list',
props: {
data: protocolSupports
}
},]}
/>
</div>
<div className={styles.tableListOperator}>
<Button icon="plus" type="primary" onClick={() => setSaveVisible(true)}>
新建
</Button>
<Divider type="vertical" />
<Upload {...uploadProps}>
<Button>
<Icon type="upload" /> 导入配置
</Button>
</Upload>
</div>
<div className={styles.StandardTable}>
<Table
loading={props.loading}
dataSource={(result || {}).data}
columns={columns}
rowKey='id'
onChange={onTableChange}
pagination={{
current: result.pageIndex + 1,
total: result.total,
pageSize: result.pageSize,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ['10', '20', '50', '100'],
showTotal: (total: number) => (
`共 ${total} 条记录 第 ${
result.pageIndex + 1
}/${
Math.ceil(result.total / result.pageSize)
}页`
),
}}
/>
</div>
</div>
</Card>
{saveVisible && <Save close={() => setSaveVisible(false)} save={item => handeSave(item)} />}
</PageHeaderWrapper>
);
}
Example #7
Source File: Properties.tsx From jetlinks-ui-antd with MIT License | 4 votes |
Properties: React.FC<Props> = (props: Props) => {
const tenantContextData = useContext(TenantContext);
const productContext = useContext(ProductContext);
const initState: State = {
data: props.data || [],
current: {},
visible: false,
importVisible: false,
product: {}
};
const [visible, setVisible] = useState(initState.visible);
const [importVisible, setImportVisible] = useState(initState.importVisible);
const [data, setData] = useState(initState.data);
const [product, setProduct] = useState(initState.product);
const [current, setCurrent] = useState(initState.current);
const [searchParam, setSearchParam] = useState<any>({});
const [dataList, setDataList] = useState(initState.data);
const sourceList = new Map();
sourceList.set('device', '设备');
sourceList.set('manual', '手动');
sourceList.set('rule', '规则');
useEffect(() => {
setData(tenantContextData.properties || [])
}, [tenantContextData]);
useEffect(() => {
setProduct(productContext || {});
}, [productContext])
const editItem = (item: any) => {
setVisible(true);
setCurrent(item);
};
const deleteItem = (item: any) => {
const temp = data.filter(e => e.id !== item.id);
setData([...temp]);
props.save(temp, true);
};
const columns: ColumnProps<PropertiesMeta>[] = [
{
title: '属性标识',
dataIndex: 'id',
align: 'center',
},
{
title: '属性名称',
dataIndex: 'name',
align: 'center',
},
{
title: '数据类型',
dataIndex: 'valueType.type',
align: 'center',
render: text => text,
filters: [
{
value: 'int',
text: '整数型',
},
{
value: 'long',
text: '长整数型',
},
{
value: 'float',
text: '单精度浮点型',
},
{
value: 'double',
text: '双精度浮点数',
},
{
value: 'string',
text: '字符串',
},
{
value: 'boolean',
text: '布尔型',
},
{
value: 'date',
text: '时间型',
},
{
value: 'enum',
text: '枚举',
},
{
value: 'array',
text: '数组',
},
{
value: 'object',
text: '结构体',
},
{
value: 'file',
text: '文件',
},
{
value: 'password',
text: '密码',
},
{
value: 'geoPoint',
text: '地理位置',
},
],
filterMultiple: false,
},
{
title: '属性值来源',
dataIndex: 'expands.source',
align: 'center',
render: text => sourceList.get(text),
filters: [
{
value: 'device',
text: '设备',
},
{
value: 'manual',
text: '手动',
},
{
value: 'rule',
text: '规则',
}
],
filterMultiple: false,
},
{
title: '是否只读',
dataIndex: 'expands.readOnly',
align: 'center',
render: text => ((text === 'true' || text === true) ? '是' : '否'),
},
{
title: '说明',
dataIndex: 'description',
align: 'center',
ellipsis: true
},
{
title: '操作',
render: (text, record) => (
<Fragment>
<a onClick={() => editItem(record)}>编辑</a>
<Divider type="vertical" />
<a onClick={() => deleteItem(record)}>删除</a>
</Fragment>
),
},
];
const savePropertiesData = (item: PropertiesMeta, onlySave: boolean) => {
const i = data.findIndex((j: any) => j.id === item.id);
if (i > -1) {
data[i] = item;
} else {
data.push(item);
}
setData([...data]);
props.save(data, onlySave);
setVisible(false);
};
const onTableChange = (
pagination: PaginationConfig,
filters: any) => {
let params = { ...searchParam }
Object.keys(filters || {}).forEach((i: string) => {
params[i] = filters[i][0]
})
handleSearch(params);
}
const handleSearch = (params?: any) => {
setSearchParam(params);
let items = [...data]
Object.keys(params || {}).forEach((item) => {
if (!!params[item]) {
items = items.filter((i) => {
return !!_.at(i, item)[0] && _.at(i, item)[0].indexOf(params[item]) !== -1
})
}
})
setDataList([...items]);
}
useEffect(() => {
handleSearch(searchParam);
}, [data])
return (
<div>
<Card
title="属性定义"
style={{ marginBottom: 20 }}
extra={
<>
<Button style={{ marginRight: '10px' }} onClick={() => {
setImportVisible(true);
}}>导入属性</Button>
<Button type="primary" onClick={() => {
setCurrent({});
setVisible(true);
}}>
添加
</Button>
</>
}
>
<div style={{ margin: '10px 0px 20px', display: 'flex', alignItems: 'center' }}>
<Input.Search allowClear style={{ width: 300 }} placeholder="请输入属性名称" onSearch={(value) => {
handleSearch({
...searchParam,
name: value
})
}} />
</div>
<Table rowKey="id" columns={columns} dataSource={dataList} onChange={onTableChange} />
</Card>
{visible && (
<PropertiesDefin
dataList={data}
data={current}
unitsData={props.unitsData}
save={(item: PropertiesMeta, onlySave: boolean) => {
savePropertiesData(item, onlySave);
}}
close={() => {
setVisible(false);
setCurrent({});
}}
/>
)}
{importVisible && <Import data={{
productId: product?.id
}} close={() => {
setImportVisible(false);
}}
save={(params: any) => {
setImportVisible(false);
let dataParams = JSON.parse(params) || {};
let list = dataParams?.properties || [];
props.update(list);
setData(list);
}}
/>}
</div>
);
}
Example #8
Source File: index.tsx From jetlinks-ui-antd with MIT License | 4 votes |
Alarm: React.FC<Props> = props => {
const service = new Service('rule-engine-alarm');
const {
form: { getFieldDecorator },
form,
} = props;
const initState: State = {
data: {},
saveAlarmData: {},
searchParam: {
pageSize: 10,
// sorts:[{name:"alarmTime",order: 'desc' }]
sorts: {
order: "desc",
field: "alarmTime"
}
},
searchAlarmParam: {
pageSize: 10
},
alarmLogData: {},
alarmDataList: [],
};
const [data, setData] = useState(initState.data);
const [spinning, setSpinning] = useState(true);
const [saveVisible, setSaveVisible] = useState(false);
const [solveVisible, setSolveVisible] = useState(false);
const [saveAlarmData, setSaveAlarmData] = useState(initState.saveAlarmData);
const [alarmActiveKey, setAlarmActiveKey] = useState('');
const [alarmLogId, setAlarmLogId] = useState<string>("");
const [solveAlarmLog, setSolveAlarmLog] = useState<any>({});
const [searchParam, setSearchParam] = useState(initState.searchParam);
const [searchAlarmParam, setSearchAlarmParam] = useState(initState.searchAlarmParam);
const [alarmLogData, setAlarmLogData] = useState(initState.alarmLogData);
const [alarmDataList, setAlarmDataList] = useState(initState.alarmDataList);
const statusMap = new Map();
statusMap.set('运行中', 'success');
statusMap.set('已停止', 'error');
const getProductAlarms = () => {
alarmDataList.splice(0, alarmDataList.length);
setSpinning(false)
service.getAlarmsList(props.device.id, {
paging: false
}).subscribe(
(res) => {
res.data.map((item: any) => {
alarmDataList.push(item);
});
setAlarmDataList([...alarmDataList]);
},
() => setSpinning(false)
)
};
const getData = (params?: any) => {
setSearchAlarmParam(params)
service.getAlarmsList(props.device.id, params).subscribe(
(res) => {
setData(res);
},
() => setSpinning(false)
)
}
useEffect(() => {
setAlarmActiveKey('info');
getProductAlarms();
getData(searchAlarmParam);
handleSearch(searchParam);
}, []);
const submitData = (data: any) => {
service.saveAlarms(props.device.id, data).subscribe(
res => {
message.success('保存成功');
setSaveVisible(false);
getProductAlarms();
getData(searchAlarmParam);
},
() => setSpinning(false)
)
};
const _start = (item: alarm) => {
service._start(props.device.id, { id: item.id }).subscribe(
() => {
message.success('启动成功');
getProductAlarms();
getData(searchAlarmParam);
setSpinning(false)
},
() => { },
() => setSpinning(false)
)
};
const _stop = (item: any) => {
service._stop(props.device.id, { id: item.id }).subscribe(
() => {
message.success('停止成功');
getProductAlarms();
getData(searchAlarmParam);
setSpinning(false)
},
() => { },
() => setSpinning(false)
)
};
const deleteAlarm = (id: string) => {
service._remove(props.device.id, { id: id }).subscribe(
() => {
message.success('删除成功');
getProductAlarms();
getData(searchAlarmParam);
setSpinning(false)
},
() => { },
() => setSpinning(false)
)
};
const columns: ColumnProps<alarm>[] = [
{
title: '告警名称',
dataIndex: 'name',
},
{
title: '创建时间',
dataIndex: 'createTime',
render: (text: any) => text ? moment(text).format('YYYY-MM-DD HH:mm:ss') : '/',
},
{
title: '运行状态',
dataIndex: 'state',
render: record => record ? <Badge status={statusMap.get(record.text)} text={record.text} /> : '',
},
{
title: '操作',
width: '250px',
align: 'center',
render: (record: any) => (
<Fragment>
<a onClick={() => {
setSaveAlarmData(record);
setSaveVisible(true);
}}>编辑</a>
<Divider type="vertical" />
<a onClick={() => {
setAlarmLogId(record.id);
onAlarmProduct(record.id);
setAlarmActiveKey('logList');
}}>告警日志</a>
<Divider type="vertical" />
{record.state?.value === 'stopped' ? (
<span>
<Popconfirm
title="确认启动此告警?"
onConfirm={() => {
setSpinning(true);
_start(record);
}}
>
<a>启动</a>
</Popconfirm>
<Divider type="vertical" />
<Popconfirm
title="确认删除此告警?"
onConfirm={() => {
setSpinning(true);
deleteAlarm(record.id);
}}
>
<a>删除</a>
</Popconfirm>
</span>
) : (
<Popconfirm
title="确认停止此告警?"
onConfirm={() => {
setSpinning(true);
_stop(record);
}}
>
<a>停止</a>
</Popconfirm>
)}
</Fragment>
),
},
];
const alarmLogColumns: ColumnProps<AlarmLog>[] = [
{
title: '设备ID',
dataIndex: 'deviceId',
},
{
title: '设备名称',
dataIndex: 'deviceName',
},
{
title: '告警名称',
dataIndex: 'alarmName',
},
{
title: '告警时间',
dataIndex: 'alarmTime',
width: '300px',
render: (text: any) => text ? moment(text).format('YYYY-MM-DD HH:mm:ss') : '/',
sorter: true,
defaultSortOrder: 'descend'
},
{
title: '处理状态',
dataIndex: 'state',
align: 'center',
width: '100px',
render: text => text === 'solve' ? <Tag color="#87d068">已处理</Tag> : <Tag color="#f50">未处理</Tag>,
},
{
title: '操作',
width: '120px',
align: 'center',
render: (record: any) => (
<Fragment>
<a onClick={() => {
let content: string;
try {
content = JSON.stringify(record.alarmData, null, 2);
} catch (error) {
content = record.alarmData;
}
Modal.confirm({
width: '40VW',
title: '告警数据',
content: <pre>{content}
{record.state === 'solve' && (
<>
<br /><br />
<span style={{ fontSize: 16 }}>处理结果:</span>
<br />
<p>{record.description}</p>
</>
)}
</pre>,
okText: '确定',
cancelText: '关闭',
})
}}>详情</a>
{
record.state !== 'solve' && (
<>
<Divider type="vertical" />
<a onClick={() => {
setSolveAlarmLog(record);
setSolveVisible(true);
}}>处理</a>
</>
)
}
</Fragment>
)
},
];
const alarmSolve = () => {
form.validateFields((err, fileValue) => {
if (err) return;
let params = {
descriptionMono: fileValue.description,
id: solveAlarmLog.id,
state: 'solve'
}
service.updataAlarmLog(props.device.id, params).subscribe(res => {
setSolveVisible(false);
handleSearch(searchParam);
message.success('操作成功!');
})
});
};
const handleSearch = (params?: any) => {
setSearchParam(params);
service.getAlarmLogList(props.device.id, params).subscribe(
res => {
setAlarmLogData(res);
}
)
};
const onAlarmProduct = (value?: string) => {
handleSearch({
pageSize: 10,
where: `alarmId=${value}`
});
};
// useEffect(() => {
// handleSearch(searchParam);
// }, [alarmActiveKey]);
const onTableChange = (
pagination: PaginationConfig,
filters: any,
sorter: SorterResult<AlarmLog>,
) => {
handleSearch({
...searchParam,
pageIndex: Number(pagination.current) - 1,
pageSize: pagination.pageSize,
sorts:sorter
});
};
const onTableAlarmChange = (
pagination: PaginationConfig,
) => {
getData({
pageIndex: Number(pagination.current) - 1,
pageSize: pagination.pageSize,
terms: searchParam.terms,
})
};
return (
<Spin tip="加载中..." spinning={spinning}>
<Card>
<Tabs tabPosition="top" type="card" activeKey={alarmActiveKey} onTabClick={(key: any) => {
setAlarmActiveKey(key);
// if (key = 'logList') {
// setAlarmLogId("");
// handleSearch(searchParam);
// }
}}>
<Tabs.TabPane tab="告警设置" key="info">
<Card title={
<Button
icon="plus"
type="primary"
onClick={() => {
setSaveAlarmData({});
setSaveVisible(true);
}}
>
新增告警
</Button>
} bordered={false}>
<Table rowKey="id" columns={columns} dataSource={data.data}
onChange={onTableAlarmChange}
pagination={{
current: data.pageIndex + 1,
total: data.total,
pageSize: data.pageSize,
showQuickJumper: true,
showSizeChanger: true,
hideOnSinglePage: true,
pageSizeOptions: ['10', '20', '50', '100'],
style: { marginTop: -20 },
showTotal: (total: number) =>
`共 ${total} 条记录 第 ${data.pageIndex + 1}/${Math.ceil(
data.total / data.pageSize,
)}页`,
}} />
</Card>
</Tabs.TabPane>
<Tabs.TabPane tab="告警记录" key="logList">
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<Select placeholder="选择告警设置" allowClear style={{ width: 300 }} value={alarmLogId}
onChange={(value: string) => {
setAlarmLogId(value);
if (value !== '' && value !== undefined) {
onAlarmProduct(value);
} else {
handleSearch({
pageIndex: searchParam.pageIndex,
pageSize: searchParam.pageSize
});
}
}}
>
{alarmDataList.length > 0 && alarmDataList.map(item => (
<Select.Option key={item.id}>{item.name}</Select.Option>
))}
</Select>
<div>
<Button type="primary" onClick={() => {
handleSearch(searchParam);
}}>刷新</Button>
</div>
</div>
<div className={styles.StandardTable} style={{ marginTop: 10 }}>
<Table
dataSource={alarmLogData.data}
columns={alarmLogColumns}
rowKey='id'
onChange={onTableChange}
pagination={{
current: alarmLogData.pageIndex + 1,
total: alarmLogData.total,
pageSize: alarmLogData.pageSize
}}
/>
</div>
</Tabs.TabPane>
</Tabs>
</Card>
{saveVisible && <AlarmSave
close={() => {
setSaveAlarmData({});
setSaveVisible(false);
getProductAlarms();
}}
save={(data: any) => {
setSpinning(true);
submitData(data);
}}
data={saveAlarmData}
deviceId={props.device.id}
/>}
{solveVisible && (
<Modal
title='告警处理结果'
visible
okText="确定"
cancelText="取消"
width='700px'
onOk={() => {
alarmSolve();
}}
onCancel={() => {
setSolveVisible(false);
setSolveAlarmLog({});
}}
>
<Form labelCol={{ span: 3 }} wrapperCol={{ span: 21 }} key="solve_form">
<Form.Item key="description" label="处理结果">
{getFieldDecorator('description', {
rules: [
{ required: true, message: '请输入处理结果' },
{ max: 2000, message: '处理结果不超过2000个字符' }
],
})(
<Input.TextArea rows={8} placeholder="请输入处理结果" />,
)}
</Form.Item>
</Form>
</Modal>
)}
</Spin>
);
}
Example #9
Source File: bind.tsx From jetlinks-ui-antd with MIT License | 4 votes |
DeviceGatewayBind: React.FC<Props> = props => {
const service = new Service('device-network');
const initState: State = {
searchParam: { pageSize: 10 },
deviceData: {},
deviceId: [],
};
const [searchParam, setSearchParam] = useState(initState.searchParam);
const [deviceData, setDeviceData] = useState(initState.deviceData);
const [deviceId, setDeviceId] = useState(initState.deviceId);
const submitData = () => {
props.save(deviceId);
};
const handleSearch = (params?: any) => {
setSearchParam(params);
service.getDeviceList(props.deviceId, params).subscribe(
(res) => {
setDeviceData(res)
})
// apis.deviceInstance
// .list(encodeQueryParam(params))
// .then(response => {
// if (response.status === 200) {
// setDeviceData(response.result);
// }
// })
// .catch(() => {
// });
};
useEffect(() => {
if (props.selectionType === 'checkbox') {
searchParam.terms = { parentId$isnull: 1 };
}
handleSearch(searchParam);
}, []);
const onTableChange = (pagination: PaginationConfig, filters: any, sorter: SorterResult<any>) => {
service.getDeviceList(props.deviceId, encodeQueryParam({
pageIndex: Number(pagination.current) - 1,
pageSize: pagination.pageSize,
sorts: sorter,
})).subscribe(
(res) => {
setDeviceData(res)
})
};
const rowSelection = {
onChange: (selectedRowKeys: any) => {
setDeviceId(selectedRowKeys);
},
};
const statusMap = new Map();
statusMap.set('在线', 'success');
statusMap.set('离线', 'error');
statusMap.set('未激活', 'processing');
const columns = [
{
title: 'ID',
dataIndex: 'id',
ellipsis: true,
},
{
title: '设备名称',
dataIndex: 'name',
ellipsis: true,
},
{
title: '产品名称',
dataIndex: 'productName',
ellipsis: true,
},
{
title: '注册时间',
dataIndex: 'registryTime',
width: '200px',
ellipsis: true,
render: (text: any) => moment(text).format('YYYY-MM-DD HH:mm:ss'),
sorter: true,
defaultSortOrder: 'descend',
},
{
title: '状态',
dataIndex: 'state',
width: '120px',
render: record =>
record ? <Badge status={statusMap.get(record.text)} text={record.text} /> : '',
}
];
return (
<Modal
title="绑定子设备"
visible
okText="确定"
cancelText="取消"
onOk={() => {
submitData();
}}
width="60%"
style={{ marginTop: -30 }}
onCancel={() => props.close()}
>
<div className={styles.tableList} style={{ maxHeight: 600, overflowY: 'auto', overflowX: 'hidden' }}>
<div className={styles.tableListForm}>
<SearchForm
formItems={[
{
label: '名称',
key: 'name',
type: 'string',
}
]}
search={(params: any) => {
if (params?.name) {
setSearchParam({
where: `name like '%${params?.name}%'`,
pageSize: 10
})
handleSearch({
where: `name like '%${params?.name}%'`,
pageSize: 10
});
} else {
setSearchParam({ pageSize: 10 })
handleSearch({ pageSize: 10 });
}
}}
/>
</div>
<div className={styles.StandardTable}>
<Table
columns={columns}
dataSource={deviceData.data}
rowKey="id"
onChange={onTableChange}
rowSelection={{
type: props.selectionType,
...rowSelection,
}}
pagination={{
current: deviceData.pageIndex + 1,
total: deviceData.total,
pageSize: deviceData.pageSize,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ['10', '20', '50', '100'],
showTotal: (total: number) =>
`共 ${total} 条记录 第 ${deviceData.pageIndex + 1}/${Math.ceil(
deviceData.total / deviceData.pageSize,
)}页`,
}}
/>
</div>
</div>
</Modal>
);
}
Example #10
Source File: index.tsx From jetlinks-ui-antd with MIT License | 4 votes |
Add: React.FC<Props> = props => {
const [spin, setSpin] = useState(false);
const [addVisible, setAddVisible] = useState(false);
const [channelVisible, setChannelVisible] = useState(false);
const [playVisible, setPlaylVisible] = useState(false);
const [leftData, setLeftData] = useState<any>({});
const [deviceLength, setDeviceLength] = useState(0);
const [rightData, setRightData] = useState<any>({});
const [deviceParams, setDeviceParams] = useState({
pageSize: 8,
});
const [channelParams, setChannelParams] = useState({
pageSize: 8,
});
const [device, setDevice] = useState({});
const [deviceId, setDeviceId] = useState('');
const [channel, setChannel] = useState({});
const statusMap = new Map();
statusMap.set('在线', 'success');
statusMap.set('离线', 'error');
statusMap.set('未激活', 'processing');
const columnsLeft = [
{
title: '序号',
align: 'center',
width: 60,
render: (text: string, record: any, index: number) => `${index + 1}`,
},
{
title: '视频设备',
key: 'device',
align: 'center',
render: (text: string, record: any) => (
<div style={{ width: '100%', textAlign: 'center' }}>
<div style={{ width: '100%', fontWeight: 600, textAlign: 'center' }}>{record.name}</div>
<div
style={{
width: '100%',
display: 'flex',
justifyContent: 'center',
color: 'rgba(0, 0, 0, 0.4)',
}}
>
<div style={{ fontSize: '10px', marginRight: '5px' }}>IP: {record.host}</div>
<div style={{ fontSize: '10px' }}>通道:{record.channelNumber || 0}个</div>
</div>
</div>
),
},
{
title: '状态',
dataIndex: 'state',
key: 'state',
align: 'center',
render: (record: any) =>
record ? <Badge status={statusMap.get(record.text)} text={record.text} /> : '',
},
{
title: '协议',
dataIndex: 'provider',
key: 'provider',
align: 'center',
with: 180,
},
{
title: '操作',
key: 'action',
align: 'center',
width: 100,
fixed: 'right',
render: (text: string, record: any) => (
<>
<a
onClick={() => {
setAddVisible(true);
setDevice(record);
}}
>
编辑
</a>
<Divider type="vertical" />
<Popconfirm
title="确认删除吗?"
onConfirm={() => {
setSpin(true);
apis.edgeDevice.delDevice(props.device.id, { deviceId: record.id }).then(res => {
if (res.status === 200) {
message.success('删除成功!');
setSpin(false);
getDevice(props.device.id, deviceParams);
}
});
}}
>
<a>删除</a>
</Popconfirm>
</>
),
},
];
const columnsRight = [
{
title: '序号',
align: 'center',
width: 60,
render: (text: string, record: any, index: number) => `${index + 1}`,
},
{
title: '通道名称',
dataIndex: 'name',
key: 'name',
align: 'center',
width: 140,
ellipsis: true,
render: (name: string) => {
return (
<Tooltip arrowPointAtCenter title={name}>
{name}
</Tooltip>
);
},
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
align: 'center',
width: 100,
render: (record: any) =>
record ? <Badge status={statusMap.get(record.text)} text={record.text} /> : '',
},
{
title: '通道ID',
dataIndex: 'channelId',
key: 'channelId',
width: 120,
align: 'center',
ellipsis: true,
render: (channelId: string) => {
return (
<Tooltip arrowPointAtCenter title={channelId}>
{channelId}
</Tooltip>
);
},
},
{
title: '协议',
dataIndex: 'provider',
key: 'provider',
width: 100,
align: 'center',
},
{
title: '操作',
key: 'action',
width: 150,
fixed: 'right',
align: 'center',
render: (text: string, record: any) => (
<>
<a
onClick={() => {
setChannel(record);
setChannelVisible(true);
}}
>
编辑
</a>
{props.edgeTag && (
<>
<Divider type="vertical" />
<a
onClick={() => {
setChannel(record);
setPlaylVisible(true);
}}
>
播放
</a>
</>
)}
<Divider type="vertical" />
<Popconfirm
title="确认删除吗?"
onConfirm={() => {
apis.edgeDevice
.delChannel(props.device.id, { channelDataId: record.id })
.then(res => {
if (res.status === 200) {
message.success('删除成功!');
getChannel(props.device.id, channelParams);
}
});
}}
>
<a>删除</a>
</Popconfirm>
</>
),
},
];
const getDevice = (id: string, params: any) => {
setSpin(true);
setDeviceParams(params);
apis.edgeDevice.getDeviceList(id, params).then(res => {
if (res.status === 200) {
setLeftData(res.result[0]);
setSpin(false);
setDeviceLength(res.result[0].total);
}
});
};
const getChannel = (id: string, params: any) => {
setChannelParams(params);
apis.edgeDevice.getChannelList(id, params).then(res => {
if (res.status === 200) {
setRightData(res.result[0]);
}
});
};
const backgroundStyle = (record: any) => {
return record.id === deviceId ? styles.clickRowStyl : '';
};
const saveOnvif = (fileValue: any) => {
if (!!fileValue.id) {
apis.edgeDevice.addOnvif(props.device.id, fileValue).then(response => {
if (response.status === 200) {
message.success('保存成功!');
}
setSpin(false);
getDevice(props.device.id, deviceParams);
});
} else {
let param = {
url: fileValue.url,
username: fileValue.username,
password: fileValue.password,
};
apis.edgeDevice.getOnvif(props.device.id, param).then(res => {
if (res.status === 200) {
if (res.result.length > 0) {
let data = res.result[0];
let mediaProfiles = (res.result[0]?.mediaProfiles || []).map(
(item: any, index: number) => {
let ra = Math.round(Math.random() * 10000000000);
return {
name: item.name,
token: item.token,
id: `channel${index}${ra}`,
};
},
);
let params = {
id: `device${Math.round(Math.random() * 10000000000)}`,
firmwareVersion: data.firmwareVersion,
hardwareId: data.hardwareId,
description: fileValue.description,
manufacturer: data.manufacturer,
mediaProfiles: mediaProfiles,
model: data.model,
name: fileValue.name || data.name,
password: data.password,
serialNumber: data.serialNumber,
url: data.url,
username: data.username,
};
apis.edgeDevice.addOnvif(props.device.id, params).then(response => {
if (response.status === 200) {
message.success('保存成功!');
}
setSpin(false);
getDevice(props.device.id, deviceParams);
});
}
} else {
setSpin(false);
}
});
}
};
const onTableChange = (pagination: PaginationConfig) => {
getDevice(props.device.id, {
pageIndex: Number(pagination.current) - 1,
pageSize: pagination.pageSize,
});
};
const onRightTableChange = (pagination: PaginationConfig) => {
getChannel(props.device.id, {
pageIndex: Number(pagination.current) - 1,
pageSize: pagination.pageSize,
});
};
useEffect(() => {
getDevice(props.device.id, deviceParams);
getChannel(props.device.id, channelParams);
}, []);
return (
<Spin spinning={spin}>
<div className={styles.box}>
<div className={styles.left}>
<Card
title="视频设备"
bordered={false}
extra={
<div className={styles.leftTop}>
<div>
<span>已接入设备: {deviceLength}</span>
</div>
<div>
<Button
type="primary"
onClick={() => {
setAddVisible(true);
setDevice({});
}}
>
添加设备
</Button>
</div>
<div>
<Button
type="primary"
onClick={() => {
getDevice(props.device.id, deviceParams);
setDeviceId('');
getChannel(props.device.id, {
pageSize: 8,
});
}}
>
刷新
</Button>
</div>
</div>
}
>
<div className={styles.leftTable}>
<Table
size="small"
rowKey="id"
scroll={{ x: 600 }}
rowClassName={backgroundStyle}
onRow={record => {
return {
onClick: () => {
setDeviceId(record.id);
let params = {
where: `deviceId = ${record.id}`,
pageSize: 8,
};
getChannel(props.device.id, params);
},
};
}}
onChange={onTableChange}
columns={columnsLeft}
dataSource={leftData?.data || []}
pagination={{
current: leftData.pageIndex + 1,
total: leftData.total,
pageSize: leftData.pageSize,
}}
/>
</div>
</Card>
</div>
<div className={styles.right}>
<Card
title="视频通道"
bordered={false}
extra={
<Button
type="primary"
onClick={() => {
if (deviceId === '') {
getChannel(props.device.id, channelParams);
} else {
getChannel(props.device.id, {
where: `deviceId = ${deviceId}`,
pageSize: 8,
});
}
}}
>
刷新
</Button>
}
>
<div className={styles.rightTable}>
<Table
rowKey="id"
scroll={{ x: 600 }}
onChange={onRightTableChange}
columns={columnsRight}
dataSource={rightData?.data || []}
pagination={{
current: rightData.pageIndex + 1,
total: rightData.total,
pageSize: rightData.pageSize,
}}
/>
</div>
</Card>
</div>
{addVisible && (
<AddDevice
deviceId={props.device.id}
close={() => {
setAddVisible(false);
}}
data={{ ...device }}
save={(data: any) => {
setSpin(true);
saveOnvif(data);
setAddVisible(false);
}}
/>
)}
{channelVisible && (
<ChannelEdit
id={props.device.id}
close={() => {
setChannelVisible(false);
}}
data={{ ...channel }}
save={() => {
setChannelVisible(false);
getChannel(props.device.id, channelParams);
}}
/>
)}
{playVisible && (
<Play
close={() => {
setPlaylVisible(false);
}}
data={{ ...channel }}
deviceId={props.device.id}
save={() => {
setPlaylVisible(false);
}}
/>
)}
</div>
</Spin>
);
}
Example #11
Source File: index.tsx From jetlinks-ui-antd with MIT License | 4 votes |
MediaDevice: React.FC<Props> = props => {
const {location: {pathname},} = props;
const service = new Service('media/channel');
const [loading, setLoading] = useState<boolean>(false);
const [deviceId, setDeviceId] = useState<string>("");
const [result, setResult] = useState<any>({});
const [deviceInfo, setDeviceInfo] = useState<any>({});
const [channel, setChannel] = useState<boolean>(false);
const [channelInfo, setChannelInfo] = useState<any>({});
const [playing, setPlaying] = useState<boolean>(false);
const [playback, setPalyback] = useState<boolean>(false)
const [data, setData] = useState<any>({});
const [searchParam, setSearchParam] = useState(initState.searchParam);
const statusMap = new Map();
statusMap.set('online', 'success');
statusMap.set('offline', 'error');
statusMap.set('notActive', 'processing');
const ptzType = new Map();
ptzType.set(0, '未知');
ptzType.set(1, '球体');
ptzType.set(2, '半球体');
ptzType.set(3, '固定枪机');
ptzType.set(4, '遥控枪机');
const deviceDetail = (deviceId: string) => {
service.mediaDevice(deviceId).subscribe((data) => {
setDeviceInfo(data);
},
() => {
},
() => {
})
};
const handleSearch = (params?: any) => {
setSearchParam(params);
setLoading(true);
service.query(encodeQueryParam(params)).subscribe(
data => setResult(data),
() => {
},
() => setLoading(false));
};
const columns: ColumnProps<any>[] = [
{
title: '通道国标编号',
dataIndex: 'channelId',
ellipsis: true,
},
{
title: '通道名称',
dataIndex: 'name',
ellipsis: true,
},
{
title: '厂商',
dataIndex: 'manufacturer',
width: 100,
ellipsis: true,
},
{
title: '安装地址',
dataIndex: 'address',
width: '10%',
ellipsis: true,
},
{
title: '云台类型',
dataIndex: 'ptzType',
width: 100,
render: record => ptzType.get(record?.value || 0),
ellipsis: true,
},
{
title: '在线状态',
dataIndex: 'status',
width: 110,
render: record => record ? <Badge status={statusMap.get(record.value)} text={record.text}/> : '',
filters: [
{
text: '离线',
value: 'offline',
},
{
text: '在线',
value: 'online',
},
],
filterMultiple: false,
},
{
title: '经纬度',
width: 200,
ellipsis: true,
render: (record: any) => (
<span>{record.longitude ? `${record.longitude ? record.longitude : ''},${record.latitude ? record.latitude : ''}` : ''}</span>
)
},
{
title: '子通道数',
dataIndex: 'subCount',
width: 100,
},
{
title: '描述',
dataIndex: 'description',
width: '10%',
ellipsis: true
},
{
title: '操作',
align: 'center',
// fixed: 'right',
render: (record: any) => (
<Fragment>
<a
onClick={() => {
setChannel(true);
setChannelInfo(record);
}}
>
编辑
</a>
<Divider type="vertical"/>
{record.status.value === 'online' ? (
<>
<a
onClick={() => {
setPlaying(true);
setData(record)
}}
>
播放
</a>
<Divider type="vertical"/>
<a
onClick={() => {
setPalyback(true);
setData(record)
}}
>
回放
</a>
</>
) : (
<Popconfirm
placement="topRight"
title="确定删除此通道吗?"
onConfirm={() => {
setLoading(true);
service.remove(record.id).subscribe(
() => {
message.success('通道删除成功');
},
() => {
message.error('通道删除失败');
},
() => {
handleSearch(searchParam);
setLoading(false);
},
);
}}
>
<a>删除</a>
</Popconfirm>
)}
</Fragment>
)
},
];
useEffect(() => {
if (pathname.indexOf('channel') > 0) {
const list = pathname.split('/');
deviceDetail(list[list.length - 1]);
setDeviceId(list[list.length - 1]);
searchParam.terms = {deviceId: list[list.length - 1]};
handleSearch(searchParam);
}
}, [window.location.hash]);
const onTableChange = (
pagination: PaginationConfig,
filters: any,
sorter: SorterResult<DeviceInstance>,
) => {
const {terms} = searchParam;
handleSearch({
pageIndex: Number(pagination.current) - 1,
pageSize: pagination.pageSize,
terms: {...terms, ...filters},
sorts: sorter,
})
};
const content = (
<div style={{marginTop: 30}}>
<Descriptions column={4}>
<Descriptions.Item label="设备名称">
<div>
{deviceInfo.name}
</div>
</Descriptions.Item>
</Descriptions>
</div>
);
const titleInfo = (
<Row>
<div>
<span style={{paddingRight: 20}}>
通道列表:{deviceId}
</span>
<Badge status={statusMap.get(deviceInfo.state?.value)} text={deviceInfo.state?.text}/>
</div>
</Row>
);
return (
<PageHeaderWrapper title={titleInfo} content={content}>
<Card style={{height: 92, marginBottom: 16}}>
<div className={styles.tableList} style={{marginTop: -22}}>
<div>
<SearchForm
search={(params: any) => {
setSearchParam(params);
params ? params.deviceId = deviceId : params = {deviceId: deviceId};
handleSearch({pageSize: 10, terms: {...params}, sorts: {field: 'id', order: 'desc'}});
}}
formItems={[
{
label: '名称',
key: 'name$LIKE',
type: 'string',
},
]}
/>
</div>
</div>
</Card>
<Card>
<div className={styles.StandardTable}>
<Table
loading={loading}
columns={columns}
dataSource={(result || {}).data}
rowKey="id"
onChange={onTableChange}
pagination={{
current: result?.pageIndex + 1,
total: result?.total,
pageSize: result?.pageSize,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ['10', '20', '50', '100'],
showTotal: (total: number) =>
`共 ${total} 条记录 第 ${result?.pageIndex + 1}/${Math.ceil(
result?.total / result?.pageSize,
)}页`,
}}
/>
</div>
</Card>
{playing && <Play data={data} close={() => {
setPlaying(false)
}} ok={() => {
setPlaying(false)
}}/>}
{channel && <ChannelEdit data={channelInfo} close={() => {
setChannel(false);
handleSearch(searchParam);
}}/>
}
{playback && <Playback data={data} close={() => {
setPalyback(false)
}} ok={() => {
setPalyback(false)
}} />}
</PageHeaderWrapper>
)
}
Example #12
Source File: index.tsx From jetlinks-ui-antd with MIT License | 4 votes |
ChoiceDevice = (props: Props) => {
const { masterId } = props
const initState: State = {
searchParam: {
pageSize: 10,
pageIndex: 0,
terms: []
},
deviceData: {},
deviceList: []
};
const [searchParam, setSearchParam] = useState(initState.searchParam);
const [deviceData, setDeviceData] = useState(initState.deviceData);
const [deviceList, setDeviceList] = useState(initState.deviceList);
const [spinning, setSpinning] = useState(true);
const handleSearch = (params?: any) => {
setSearchParam(params);
const data = {
pageSize: params.pageSize || 10,
pageIndex: params.pageIndex || 0,
"terms": [
{
"terms": [
{
"column": "id$modbus-master$not",
"value": masterId
},
...params?.terms
]
}
]
}
apis.modbus.getDeviceList(data).then(response => {
if (response.status === 200) {
setDeviceData(response.result);
}
setSpinning(false);
})
};
useEffect(() => {
handleSearch(searchParam);
}, []);
const onTableChange = (
pagination: PaginationConfig
) => {
handleSearch({
pageIndex: Number(pagination.current) - 1,
pageSize: pagination.pageSize,
terms: searchParam?.terms || []
});
};
const rowSelection = {
onChange: (selectedRowKeys: any) => {
setDeviceList(selectedRowKeys);
},
};
const statusMap = new Map();
statusMap.set('在线', 'success');
statusMap.set('离线', 'error');
statusMap.set('未激活', 'processing');
const columns: ColumnProps<DeviceInstance>[] = [
{
title: 'ID',
dataIndex: 'id',
ellipsis: true,
},
{
title: '设备名称',
dataIndex: 'name',
ellipsis: true,
},
{
title: '产品名称',
dataIndex: 'productName',
ellipsis: true,
},
{
title: '注册时间',
dataIndex: 'registryTime',
width: '200px',
render: (text: any) => moment(text).format('YYYY-MM-DD HH:mm:ss'),
ellipsis: true,
},
{
title: '状态',
dataIndex: 'state',
width: '80px',
render: record =>
record ? <Badge status={statusMap.get(record.text)} text={record.text} /> : '',
},
];
return (
<Modal
title="绑定设备"
visible
width="80vw"
onCancel={() => {
props.save([]);
}}
onOk={() => {
props.save(deviceList)
}}
>
<Spin spinning={spinning}>
<div className={styles.tableList}>
<div className={styles.tableListForm}>
<SearchForm
search={(params: any) => {
const data: any[] = []
if (params) {
Object.keys(params).forEach(key => {
if (params[key]) {
data.push({
"column": key,
"value": `%${params[key]}%`,
"termType": "like",
"type": "and"
})
}
})
}
handleSearch({
pageSize: 10,
terms: [...data]
})
}}
formItems={[
{
label: '设备ID',
key: 'id',
type: 'string',
},
{
label: '设备名称',
key: 'name',
type: 'string',
}
]}
/>
</div>
<div className={styles.StandardTable}>
<Table
columns={columns}
dataSource={deviceData.data}
rowKey="id"
onChange={onTableChange}
rowSelection={{
type: 'checkbox',
...rowSelection,
selectedRowKeys: deviceList
}}
size='middle'
pagination={{
current: deviceData.pageIndex + 1,
total: deviceData.total,
pageSize: deviceData.pageSize,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ['10', '20', '50', '100'],
showTotal: (total: number) =>
`共 ${total} 条记录 第 ${deviceData.pageIndex + 1}/${Math.ceil(
deviceData.total / deviceData.pageSize,
)}页`,
}}
/>
</div>
</div>
</Spin>
</Modal>
);
}
Example #13
Source File: index.tsx From jetlinks-ui-antd with MIT License | 4 votes |
Config: React.FC<Props> = props => {
const { noticeConfig, loading, dispatch } = props;
const initState: State = {
typeList: [],
// activeType: '',
saveVisible: false,
currentItem: {},
searchParam: {},
filterType: [],
filterName: '',
debugVisible: false,
};
const [typeList, setTypeList] = useState(initState.typeList);
// const [activeType, setActiveType] = useState(initState.activeType);
const [saveVisible, setSaveVisible] = useState(initState.saveVisible);
const [currentItem, setCurrentItem] = useState(initState.currentItem);
const [searchParam, setSearchParam] = useState(initState.searchParam);
const [filterType, setFilterType] = useState(initState.filterType);
const [filterName, setFilterName] = useState(initState.filterName);
const [debugVisible, setDebugVisible] = useState(initState.debugVisible);
const [logVisible, setLogVisible] = useState(false);
const handlerSearch = (params?: any) => {
dispatch({
type: 'noticeConfig/query',
payload: encodeQueryParam(params),
});
setSearchParam(params);
};
const onSearch = (type?: string[], name?: string) => {
const tempType = type || filterType;
const tempName = name || filterName;
const param = {
paging: false,
sorts: {
field: 'id',
order: 'desc',
},
terms: {
type$IN: tempType,
name$LIKE: tempName,
},
};
setSearchParam(param);
dispatch({
type: 'noticeConfig/query',
payload: encodeQueryParam(param),
});
};
useEffect(() => {
apis.notifier.configType().then((res: any) => {
if (res) {
setTypeList(res.result);
}
});
handlerSearch({
pageIndex: 0,
pageSize: 10,
});
}, []);
const remove = (record: any) => {
dispatch({
type: 'noticeConfig/remove',
payload: record.id,
callback: () => {
message.success('删除成功');
handlerSearch(searchParam);
},
});
};
const saveData = (item: any) => {
dispatch({
type: 'noticeConfig/insert',
payload: item,
callback: () => {
message.success('保存成功');
setSaveVisible(false);
handlerSearch(searchParam);
},
});
};
const onTableChange = (
pagination: PaginationConfig,
filters: any,
sorter: any,
) => {
handlerSearch({
pageIndex: Number(pagination.current) - 1,
pageSize: pagination.pageSize,
terms: searchParam,
sorts: sorter,
});
};
const uploadProps = (item: any) => {
dispatch({
type: 'noticeConfig/insert',
payload: item,
callback: (data) => {
if(data.status===200){
message.success('导入成功');
}
handlerSearch(searchParam);
},
});
};
/*const uploadProps: UploadProps = {
accept: '.json',
action: '/jetlinks/file/static',
headers: {
'X-Access-Token': getAccessToken(),
},
showUploadList: false,
onChange(info) {
if (info.file.status === 'done') {
const fileUrl = info.file.response.result;
request(fileUrl, { method: 'GET' }).then(e => {
dispatch({
type: 'noticeConfig/insert',
payload: e,
callback: () => {
message.success('导入成功');
handlerSearch(searchParam);
},
});
});
}
if (info.file.status === 'error') {
message.error(`${info.file.name} 导入失败.`);
}
},
};*/
return (
<PageHeaderWrapper title="通知配置">
<div className={styles.filterCardList}>
<Card bordered={false}>
<Form layout="inline">
<StandardFormRow title="组件类型" block style={{ paddingBottom: 11 }}>
<Form.Item>
<TagSelect
// expandable
onChange={(value: any[]) => {
setFilterType(value);
onSearch(value, undefined);
}}
>
{(typeList || []).map(item => (
<TagSelect.Option key={item.id} value={item.id}>
{item.name}
</TagSelect.Option>
))}
</TagSelect>
</Form.Item>
</StandardFormRow>
<StandardFormRow title="其它选项" grid last>
<Row gutter={16}>
<Col lg={8} md={10} sm={10} xs={24}>
<Form.Item {...formItemLayout} label="配置名称">
<Input
onChange={e => {
setFilterName(e.target.value);
onSearch(undefined, e.target.value);
}}
/>
</Form.Item>
</Col>
</Row>
</StandardFormRow>
</Form>
</Card>
<br />
<Card>
<Button
onClick={() => {
setCurrentItem({});
setSaveVisible(true);
}}
type="primary"
style={{ marginBottom: 16 }}
>
新建
</Button>
<Divider type="vertical" />
<Button
onClick={() => {
downloadObject(noticeConfig.result?.data, '通知配置');
}}
style={{ marginBottom: 16 }}
>
导出配置
</Button>
<Divider type="vertical" />
{/*<Upload {...uploadProps}>
<Button type="primary" style={{ marginBottom: 16 }}>
导入配置
</Button>
</Upload>*/}
<Upload
action="/jetlinks/file/static"
headers={{
'X-Access-Token': getAccessToken(),
}}
showUploadList={false} accept='.json'
beforeUpload={(file) => {
const reader = new FileReader();
reader.readAsText(file);
reader.onload = (result) => {
try {
uploadProps(JSON.parse(result.target.result));
} catch (error) {
message.error('文件格式错误');
}
}
}}
>
<Button>
<Icon type="upload" />导入配置
</Button>
</Upload>
<Table
rowKey="id"
loading={loading}
onChange={onTableChange}
columns={[
{
dataIndex: 'id',
title: 'ID',
defaultSortOrder: 'descend',
},
{
dataIndex: 'name',
title: '配置名称',
},
{
dataIndex: 'type',
title: '通知类型',
},
{
dataIndex: 'provider',
title: '服务商',
},
{
dataIndex: 'option',
title: '操作',
render: (text, record: any) => (
<Fragment>
<a
onClick={() => {
setCurrentItem(record);
setSaveVisible(true);
}}
>
编辑
</a>
<Divider type="vertical" />
<Popconfirm
title="确认删除?"
onConfirm={() => {
remove(record);
}}
>
<a>删除</a>
</Popconfirm>
<Divider type="vertical" />
<a onClick={() => downloadObject(record, '通知配置')}>下载配置</a>
<Divider type="vertical" />
<a
onClick={() => {
setCurrentItem(record);
setDebugVisible(true);
}}
>
调试
</a>
<Divider type="vertical" />
<a
onClick={() => {
setCurrentItem(record);
setLogVisible(true);
}}
>
通知记录
</a>
</Fragment>
),
},
]}
dataSource={noticeConfig.result?.data}
pagination={{
current: noticeConfig.result?.pageIndex + 1,
total: noticeConfig.result?.total,
pageSize: noticeConfig.result?.pageSize,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ['10', '20', '50', '100'],
showTotal: (total: number) =>
`共 ${total} 条记录 第 ${noticeConfig.result?.pageIndex + 1}/${Math.ceil(
noticeConfig.result?.total / noticeConfig.result?.pageSize,
)}页`,
}}
/>
</Card>
</div>
{saveVisible && (
<Save
data={currentItem}
close={() => setSaveVisible(false)}
save={(item: any) => saveData(item)}
/>
)}
{debugVisible && <Debug data={currentItem} close={() => setDebugVisible(false)} />}
{logVisible && <Logger close={() => setLogVisible(false)} data={currentItem} />}
</PageHeaderWrapper>
);
}
Example #14
Source File: index.tsx From jetlinks-ui-antd with MIT License | 4 votes |
Template: React.FC<Props> = props => {
const { noticeTemplate, loading, dispatch } = props;
const initState: State = {
typeList: [],
activeType: '',
saveVisible: false,
currentItem: {},
searchParam: {},
filterType: [],
filterName: '',
debugVisible: false,
};
const [typeList, setTypeList] = useState(initState.typeList);
// const [activeType, setActiveType] = useState(initState.activeType);
const [saveVisible, setSaveVisible] = useState(initState.saveVisible);
const [currentItem, setCurrentItem] = useState(initState.currentItem);
const [searchParam, setSearchParam] = useState(initState.searchParam);
const [filterType, setFilterType] = useState(initState.filterType);
const [filterName, setFilterName] = useState(initState.filterName);
const [debugVisible, setDebugVisible] = useState(initState.debugVisible);
const handlerSearch = (params?: any) => {
const temp = params;
temp.sorts = {
field: 'id',
order: 'desc',
};
dispatch({
type: 'noticeTemplate/query',
payload: encodeQueryParam(temp),
});
setSearchParam(temp);
};
const onSearch = (type?: string[], name?: string) => {
const tempType = type || filterType;
const tempName = name || filterName;
dispatch({
type: 'noticeTemplate/query',
payload: encodeQueryParam({
paging: false,
sorts: {
field: 'id',
order: 'desc',
},
terms: {
type$IN: tempType,
name$LIKE: name === '' ? undefined : tempName,
},
}),
});
};
useEffect(() => {
apis.notifier.configType().then((res: any) => {
if (res) {
setTypeList(res.result);
}
});
handlerSearch({
pageIndex: 0,
pageSize: 10,
});
}, []);
const remove = (record: any) => {
dispatch({
type: 'noticeTemplate/remove',
payload: record.id,
callback: (res) => {
if (res.status === 200) {
message.success('删除成功');
handlerSearch(searchParam);
}
},
});
};
const saveData = (item: any) => {
dispatch({
type: 'noticeTemplate/insert',
payload: item,
callback: (res) => {
if (res.status === 200) {
message.success('保存成功');
setSaveVisible(false);
handlerSearch(searchParam);
}
},
});
};
const onTableChange = (
pagination: PaginationConfig,
filters: any,
sorter: any,
// extra: any,
) => {
handlerSearch({
pageIndex: Number(pagination.current) - 1,
pageSize: pagination.pageSize,
terms: searchParam,
sorts: sorter,
});
};
const uploadProps = (item: any) => {
dispatch({
type: 'noticeTemplate/insert',
payload: item,
callback: (res) => {
if (res.status === 200) {
message.success('导入成功');
handlerSearch(searchParam);
}
},
});
};
/*const uploadProps: UploadProps = {
accept: '.json',
action: '/jetlinks/file/static',
headers: {
'X-Access-Token': getAccessToken(),
},
showUploadList: false,
onChange(info) {
if (info.file.status !== 'uploading') {
// console.log(info.file, info.fileList);
}
if (info.file.status === 'done') {
const fileUrl = info.file.response.result;
request(fileUrl, { method: 'GET' }).then(e => {
dispatch({
type: 'noticeTemplate/insert',
payload: e,
callback: () => {
message.success('导入成功');
handlerSearch(searchParam);
},
});
});
}
if (info.file.status === 'error') {
message.error(`${info.file.name} 导入失败.`);
}
},
};*/
return (
<PageHeaderWrapper title="通知模版">
<div className={styles.filterCardList}>
<Card bordered={false}>
<Form layout="inline">
<StandardFormRow title="组件类型" block style={{ paddingBottom: 11 }}>
<Form.Item>
<TagSelect
// expandable
onChange={(value: any[]) => {
setFilterType(value);
onSearch(value, undefined);
}}
>
{typeList?.map(item => (
<TagSelect.Option key={item.id} value={item.id}>
{item.name}
</TagSelect.Option>
))}
</TagSelect>
</Form.Item>
</StandardFormRow>
<StandardFormRow title="其它选项" grid last>
<Row gutter={16}>
<Col lg={8} md={10} sm={10} xs={24}>
<Form.Item {...formItemLayout} label="配置名称">
<Input
onChange={e => {
const tempValue = e.target.value;
setFilterName(tempValue);
onSearch(undefined, tempValue === '' ? undefined : tempValue);
}}
/>
</Form.Item>
</Col>
</Row>
</StandardFormRow>
</Form>
</Card>
<br />
<Card>
<Button
onClick={() => {
setCurrentItem({});
setSaveVisible(true);
}}
type="primary"
style={{ marginBottom: 16 }}
>
新建
</Button>
<Divider type="vertical" />
<Button
onClick={() => {
downloadObject(noticeTemplate.result?.data, '通知模板');
}}
style={{ marginBottom: 16 }}
>
导出配置
</Button>
<Divider type="vertical" />
{/*<Upload {...uploadProps}>
<Button type="primary" style={{ marginBottom: 16 }}>
导入配置
</Button>
</Upload>*/}
<Upload
action="/jetlinks/file/static"
headers={{
'X-Access-Token': getAccessToken(),
}}
showUploadList={false} accept='.json'
beforeUpload={(file) => {
const reader = new FileReader();
reader.readAsText(file);
reader.onload = (result) => {
try {
uploadProps(JSON.parse(result.target.result));
} catch (error) {
message.error('文件格式错误');
}
}
}}
>
<Button>
<Icon type="upload" />导入配置
</Button>
</Upload>
<Table
rowKey="id"
onChange={onTableChange}
loading={loading}
columns={[
{
dataIndex: 'id',
title: 'ID',
defaultSortOrder: 'descend',
},
{
dataIndex: 'name',
title: '模版名称',
},
{
dataIndex: 'type',
title: '通知类型',
},
{
dataIndex: 'provider',
title: '服务商',
},
{
dataIndex: 'option',
title: '操作',
render: (text, record: any) => (
<Fragment>
<a
onClick={() => {
setCurrentItem(record);
setSaveVisible(true);
}}
>
编辑
</a>
<Divider type="vertical" />
<Popconfirm
title="确认删除?"
onConfirm={() => {
remove(record);
}}
>
<a>删除</a>
</Popconfirm>
<Divider type="vertical" />
<a onClick={() => downloadObject(record, '通知模版')}>下载配置</a>
<Divider type="vertical" />
<a
onClick={() => {
setCurrentItem(record);
setDebugVisible(true);
}}
>
调试
</a>
</Fragment>
),
},
]}
dataSource={noticeTemplate.result?.data}
pagination={{
current: noticeTemplate.result?.pageIndex + 1,
total: noticeTemplate.result?.total,
pageSize: noticeTemplate.result?.pageSize,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ['10', '20', '50', '100'],
showTotal: (total: number) =>
`共 ${total} 条记录 第 ${noticeTemplate.result?.pageIndex + 1}/${Math.ceil(
noticeTemplate.result?.total / noticeTemplate.result?.pageSize,
)}页`,
}}
/>
</Card>
</div>
{saveVisible && (
<Save
data={currentItem}
close={() => setSaveVisible(false)}
save={(item: any) => saveData(item)}
/>
)}
{debugVisible && <Debug data={currentItem} close={() => setDebugVisible(false)} />}
</PageHeaderWrapper>
);
}
Example #15
Source File: index.tsx From jetlinks-ui-antd with MIT License | 4 votes |
Log: React.FC<Props> = props => {
const initState: State = {
list: {},
searchParam: { pageIndex: 0, pageSize: 10 },
};
const [list, setList] = useState(initState.list);
const [searchParam, setSearchParam] = useState(initState.searchParam);
const handleSearch = (params?: any) => {
apis.ruleInstance.log(props.data.id, encodeQueryParam(params)).then(response => {
if (response.status === 200) {
setList(response.result);
}
});
setSearchParam(params);
};
useEffect(() => {
handleSearch({
pageIndex: 0,
pageSize: 10,
});
}, []);
const onTableChange = (pagination: PaginationConfig) => {
handleSearch({
pageIndex: Number(pagination.current) - 1,
pageSize: pagination.pageSize,
sorts: {
field: 'createTime',
order: 'desc',
},
terms: searchParam.terms,
});
};
return (
<div>
<Search
search={(params: any) => {
handleSearch({ terms: params, pageSize: 10 });
}}
/>
<Table
rowKey="id"
onChange={onTableChange}
pagination={{
current: list.pageIndex + 1,
total: list.total,
pageSize: list.pageSize,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ['10', '20', '50', '100'],
showTotal: (total: number) =>
`共 ${total} 条记录 第 ${list.pageIndex + 1}/${Math.ceil(
list.total / list.pageSize,
)}页`,
}}
columns={[
{
dataIndex: 'createTime',
title: '时间',
defaultSortOrder: 'descend',
render: text => moment(text).format('YYYY-MM-DD HH:mm:ss'),
},
{
dataIndex: 'level',
title: 'LEVEL',
render: text => <Tag color="#f50">{text}</Tag>,
},
{
dataIndex: 'message',
title: '消息',
},
]}
dataSource={list.data}
/>
</div>
);
}
Example #16
Source File: bind.tsx From jetlinks-ui-antd with MIT License | 4 votes |
DeviceGatewayBind: React.FC<Props> = props => {
const initState: State = {
searchParam: {pageSize: 10},
deviceData: {},
deviceId: [],
};
const [searchParam, setSearchParam] = useState(initState.searchParam);
const [deviceData, setDeviceData] = useState(initState.deviceData);
const [deviceId, setDeviceId] = useState(initState.deviceId);
const submitData = () => {
props.save(deviceId);
};
const handleSearch = (params?: any) => {
setSearchParam(params);
apis.deviceInstance
.list(encodeQueryParam(params))
.then(response => {
if (response.status === 200) {
setDeviceData(response.result);
}
})
.catch(() => {
});
};
useEffect(() => {
if (props.selectionType === 'checkbox') {
searchParam.terms = {parentId$isnull: 1};
}
handleSearch(searchParam);
}, []);
const onTableChange = (pagination: PaginationConfig, filters: any, sorter: SorterResult<any>) => {
apis.deviceInstance
.list(
encodeQueryParam({
pageIndex: Number(pagination.current) - 1,
pageSize: pagination.pageSize,
sorts: sorter,
}),
)
.then(response => {
if (response.status === 200) {
setDeviceData(response.result);
}
})
.catch(() => {
});
};
const rowSelection = {
onChange: (selectedRowKeys: any) => {
setDeviceId(selectedRowKeys);
},
};
const statusMap = new Map();
statusMap.set('在线', 'success');
statusMap.set('离线', 'error');
statusMap.set('未激活', 'processing');
const columns: ColumnProps<DeviceInstance>[] = [
{
title: 'ID',
dataIndex: 'id',
ellipsis: true,
},
{
title: '设备名称',
dataIndex: 'name',
ellipsis: true,
},
{
title: '产品名称',
dataIndex: 'productName',
ellipsis: true,
},
{
title: '注册时间',
dataIndex: 'registryTime',
width: '200px',
ellipsis: true,
render: (text: any) => moment(text).format('YYYY-MM-DD HH:mm:ss'),
sorter: true,
defaultSortOrder: 'descend',
},
{
title: '状态',
dataIndex: 'state',
width: '120px',
render: record =>
record ? <Badge status={statusMap.get(record.text)} text={record.text}/> : '',
}
];
return (
<Modal
title="绑定子设备"
visible
okText="确定"
cancelText="取消"
onOk={() => {
submitData();
}}
width="60%"
style={{marginTop: -30}}
onCancel={() => props.close()}
>
<div className={styles.tableList} style={{maxHeight: 600, overflowY: 'auto', overflowX: 'hidden'}}>
<div className={styles.tableListForm}>
<Search
search={(params: any) => {
setSearchParam(params);
if (props.selectionType === 'checkbox') {
params['parentId$isnull'] = 1;
}
handleSearch({terms: params, sorter: searchParam.sorter, pageSize: 10});
}}
/>
</div>
<div className={styles.StandardTable}>
<Table
columns={columns}
dataSource={deviceData.data}
rowKey="id"
onChange={onTableChange}
rowSelection={{
type: props.selectionType,
...rowSelection,
}}
pagination={{
current: deviceData.pageIndex + 1,
total: deviceData.total,
pageSize: deviceData.pageSize,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ['10', '20', '50', '100'],
showTotal: (total: number) =>
`共 ${total} 条记录 第 ${deviceData.pageIndex + 1}/${Math.ceil(
deviceData.total / deviceData.pageSize,
)}页`,
}}
/>
</div>
</div>
</Modal>
);
}
Example #17
Source File: index.tsx From jetlinks-ui-antd with MIT License | 4 votes |
OrgList: React.FC<Props> = props => {
const {
dispatch,
org: { result },
} = props;
const initState: State = {
data: result,
searchParam: { pageSize: 10 },
saveVisible: false,
currentItem: {},
parentId: null,
autzVisible: false,
userVisible: false,
};
const [searchParam, setSearchParam] = useState(initState.searchParam);
const [saveVisible, setSaveVisible] = useState(initState.saveVisible);
const [currentItem, setCurrentItem] = useState(initState.currentItem);
const [parentId, setParentId] = useState(initState.parentId);
const [autzVisible, setAutzVisible] = useState(initState.autzVisible);
const [userVisible, setUserVisible] = useState(initState.userVisible);
const handleSearch = (params?: any) => {
dispatch({
type: 'org/query',
payload: encodeQueryParam(params),
});
setSearchParam(params);
};
useEffect(() => {
handleSearch({
terms: {
typeId: 'org',
},
paging: false,
});
}, []);
const saveOrUpdate = (item: OrgItem) => {
if (currentItem.id) {
dispatch({
//编辑
type: 'org/insert',
payload: encodeQueryParam(item),
callback: (response: any) => {
if (response.status === 200) {
message.success('保存成功');
}
setSaveVisible(false);
handleSearch(searchParam);
},
});
} else {
apis.org.add(item).then(res => {
if (res.status === 200) {
message.success('保存成功');
}
setSaveVisible(false);
handleSearch(searchParam);
});
}
};
const handleDelete = (item: any) => {
dispatch({
type: 'org/remove',
payload: item.id,
callback: (response: any) => {
if (response) {
message.success('删除成功');
handleSearch(searchParam);
}
},
});
};
const onTableChange = (pagination: PaginationConfig, filters: any, sorter: any) => {
handleSearch({
pageIndex: Number(pagination.current) - 1,
pageSize: pagination.pageSize,
terms: searchParam.terms,
sorts: sorter,
});
};
const columns: ColumnProps<OrgItem>[] = [
{
title: '机构标识',
dataIndex: 'id',
width: '45%',
},
{
title: '机构名称',
dataIndex: 'name',
width: '15%',
},
{
title: '描述',
dataIndex: 'describe',
width: '10%',
},
{
title: '操作',
width: '20%',
render: (text, record) => (
<Fragment>
<a
onClick={() => {
setCurrentItem(record);
setParentId(null);
setSaveVisible(true);
}}
>
编辑
</a>
<Divider type="vertical" />
<a
onClick={() => {
setCurrentItem({});
setSaveVisible(true);
setParentId(record.id);
}}
>
添加子机构
</a>
<Divider type="vertical" />
<a
onClick={() => {
setCurrentItem(record);
setAutzVisible(true);
}}
>
权限分配
</a>
<Divider type="vertical" />
<a
onClick={() => {
setCurrentItem(record);
setUserVisible(true);
}}
>
绑定用户
</a>
<Divider type="vertical" />
<Popconfirm
title="确认删除此机构吗?"
onConfirm={() => {
handleDelete(record);
}}
>
<a>删除</a>
</Popconfirm>
</Fragment>
),
},
];
return (
<PageHeaderWrapper title="机构管理">
<Card bordered={false}>
<div className={styles.tableList}>
<div className={styles.tableListForm}>
{/* <Search search={(params: any) => {
setSearchParam(params);
handleSearch({ terms: params, pageSize: 10 })
}} /> */}
</div>
<div className={styles.tableListOperator}>
<Button
icon="plus"
type="primary"
onClick={() => {
setParentId(null);
setCurrentItem({});
setSaveVisible(true);
}}
>
新建
</Button>
</div>
<div className={styles.StandardTable}>
<Table
loading={props.loading}
dataSource={result}
columns={columns}
rowKey="id"
onChange={onTableChange}
pagination={false}
// pagination={{
// current: result.pageIndex + 1,
// total: result.total,
// pageSize: result.pageSize,
// showQuickJumper: true,
// showSizeChanger: true,
// pageSizeOptions: ['10', '20', '50', '100'],
// showTotal: (total: number) => `共 ${total} 条记录 第 ${result.pageIndex + 1}/${Math.ceil(result.total / result.pageSize)}页`
// }}
/>
</div>
</div>
</Card>
{saveVisible && (
<Save
parentId={parentId}
save={(item: any) => saveOrUpdate(item)}
data={currentItem}
close={() => {
setSaveVisible(false);
setCurrentItem({});
}}
/>
)}
{autzVisible && (
<Authorization
close={() => {
setAutzVisible(false);
setCurrentItem({});
}}
target={currentItem}
targetType="org"
/>
)}
{userVisible && (
<BindUser
data={currentItem}
close={() => {
setUserVisible(false);
}}
/>
)}
</PageHeaderWrapper>
);
}
Example #18
Source File: ChoiceDevice.tsx From jetlinks-ui-antd with MIT License | 4 votes |
ChoiceDevice: React.FC<Props> = props => {
const initState: State = {
searchParam: { pageSize: 10 },
deviceData: {},
};
const [searchParam, setSearchParam] = useState(initState.searchParam);
const [deviceData, setDeviceData] = useState(initState.deviceData);
const handleSearch = (params?: any) => {
setSearchParam(params);
apis.deviceInstance
.list(encodeQueryParam(params))
.then(response => {
if (response.status === 200) {
setDeviceData(response.result);
}
})
.catch(() => {
});
};
useEffect(() => {
searchParam.terms = { productId: props.productId };
handleSearch(searchParam);
}, []);
const onTableChange = (
pagination: PaginationConfig,
filters: any,
sorter: SorterResult<DeviceInstance>,
) => {
handleSearch({
pageIndex: Number(pagination.current) - 1,
pageSize: pagination.pageSize,
terms: searchParam.terms,
sorts: sorter,
});
};
const rowSelection = {
onChange: (selectedRowKeys: any) => {
props.save(selectedRowKeys);
},
};
const statusMap = new Map();
statusMap.set('在线', 'success');
statusMap.set('离线', 'error');
statusMap.set('未激活', 'processing');
const columns: ColumnProps<DeviceInstance>[] = [
{
title: 'ID',
dataIndex: 'id',
},
{
title: '设备名称',
dataIndex: 'name',
},
{
title: '产品名称',
dataIndex: 'productName',
},
{
title: '注册时间',
dataIndex: 'registryTime',
width: '200px',
render: (text: any) => moment(text).format('YYYY-MM-DD HH:mm:ss'),
sorter: true,
defaultSortOrder: 'descend',
},
{
title: '状态',
dataIndex: 'state',
render: record =>
record ? <Badge status={statusMap.get(record.text)} text={record.text}/> : '',
},
];
return (
<div className={styles.tableList}>
<div className={styles.tableListForm}>
<Search
search={(params: any) => {
setSearchParam(params);
searchParam.terms = { productId: props.productId };
handleSearch({ terms: params, sorter: searchParam.sorter, pageSize: 10 });
}}
/>
</div>
<div className={styles.StandardTable}>
<Table
columns={columns}
dataSource={deviceData.data}
rowKey="id"
onChange={onTableChange}
rowSelection={{
type: 'checkbox',
...rowSelection,
}}
size='middle'
pagination={{
current: deviceData.pageIndex + 1,
total: deviceData.total,
pageSize: deviceData.pageSize,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ['10', '20', '50', '100'],
showTotal: (total: number) =>
`共 ${total} 条记录 第 ${deviceData.pageIndex + 1}/${Math.ceil(
deviceData.total / deviceData.pageSize,
)}页`,
}}
/>
</div>
</div>
);
}
Example #19
Source File: index.tsx From jetlinks-ui-antd with MIT License | 4 votes |
TenantAlarm: React.FC<Props> = (props) => {
const initState: State = {
data: [],
saveAlarmData: {},
searchParam: {
pageSize: 10, sorts: {
order: "descend",
field: "alarmTime"
}
},
alarmLogData: {},
alarmDataList: [],
};
const [spinning, setSpinning] = useState(true);
const [searchParam, setSearchParam] = useState(initState.searchParam);
const [alarmLogData, setAlarmLogData] = useState(initState.alarmLogData);
const statusMap = new Map();
statusMap.set('在线', 'success');
statusMap.set('离线', 'error');
const handleSearch = (params?: any) => {
setSearchParam(params);
apis.deviceAlarm.findAlarmLog(encodeQueryParam(params))
.then((response: any) => {
if (response.status === 200) {
setAlarmLogData(response.result);
}
setSpinning(false);
})
.catch(() => {
});
};
useEffect(() => {
handleSearch(searchParam);
}, []);
const alarmLogColumns: ColumnProps<AlarmLog>[] = [
{
title: '设备ID',
dataIndex: 'deviceId',
},
{
title: '设备名称',
dataIndex: 'deviceName',
},
{
title: '告警名称',
dataIndex: 'alarmName',
},
{
title: '告警时间',
dataIndex: 'alarmTime',
width: '180px',
render: (text: any) => text ? moment(text).format('YYYY-MM-DD HH:mm:ss') : '/',
sorter: true,
defaultSortOrder: 'descend'
},
{
title: '处理状态',
dataIndex: 'state',
align: 'center',
width: '100px',
render: text => text === 'solve' ? <Tag color="#87d068">已处理</Tag> : <Tag color="#f50">未处理</Tag>,
},
];
const onTableChange = (
pagination: PaginationConfig,
filters: any,
sorter: SorterResult<AlarmLog>,
) => {
handleSearch({
pageIndex: Number(pagination.current) - 1,
pageSize: pagination.pageSize,
terms: searchParam.terms,
sorts: sorter,
});
};
return (
<Spin spinning={spinning}>
<Card bordered={false}>
<div className={styles.tableList}>
<div className={styles.tableListForm}>
<Search
search={(params: any) => {
setSpinning(true);
handleSearch({terms: params, pageSize: 10, sorts: searchParam.sorts});
}}
/>
</div>
<div className={styles.StandardTable} style={{marginTop: 10}}>
<Table
size='middle'
dataSource={(alarmLogData || {}).data}
columns={alarmLogColumns}
rowKey='id'
onChange={onTableChange}
pagination={{
current: alarmLogData.pageIndex + 1,
total: alarmLogData.total,
pageSize: alarmLogData.pageSize,
}}
/>
</div>
</div>
</Card>
</Spin>
);
}
Example #20
Source File: index.tsx From jetlinks-ui-antd with MIT License | 4 votes |
TenantDevice: React.FC<Props> = (props) => { const initState: State = { searchParam: { pageSize: 10, sorts: { order: "descend", field: "createTime" } }, productList: [], deviceData: {}, }; const [searchParam, setSearchParam] = useState(initState.searchParam); const [deviceData, setDeviceData] = useState(initState.deviceData); const [spinning, setSpinning] = useState(true); const statusMap = new Map(); statusMap.set('online', <Tag color="#87d068">在线</Tag>); statusMap.set('offline', <Tag color="#f50">离线</Tag>); statusMap.set('notActive', <Tag color="#1890ff">未激活</Tag>); const handleSearch = (params?: any) => { setSearchParam(params); apis.deviceInstance.list(encodeQueryParam(params)) .then((response: any) => { if (response.status === 200) { setDeviceData(response.result); } setSpinning(false); }) .catch(() => { }) }; const columns: ColumnProps<DeviceInstance>[] = [ { title: 'ID', dataIndex: 'id', }, { title: '设备名称', dataIndex: 'name', }, { title: '产品名称', dataIndex: 'productName', }, { title: '状态', dataIndex: 'state', width: '90px', render: record => record ? statusMap.get(record.value) : '', filters: [ { text: '未激活', value: 'notActive', }, { text: '离线', value: 'offline', }, { text: '在线', value: 'online', }, ], filterMultiple: false, }, ]; useEffect(() => { handleSearch(searchParam); }, []); const onTableChange = ( pagination: PaginationConfig, filters: any, sorter: SorterResult<DeviceInstance>,) => { setSpinning(true); let { terms } = searchParam; if (filters.state) { if (terms) { terms.state = filters.state[0]; } else { terms = { state: filters.state[0], }; } } handleSearch({ pageIndex: Number(pagination.current) - 1, pageSize: pagination.pageSize, terms, sorts: sorter, }); }; const service = new Service(''); const [data, setData] = useState<any[]>([]); const user = JSON.parse(localStorage.getItem('user-detail') || '{}'); const tenantId = (user.tenants || []).filter((i: any) => i.mainTenant)[0]?.tenantId; const tenantAdmin = (user.tenants || []).filter((i: any) => i.mainTenant)[0]?.adminMember; const getProduct = (userId: string) => service.assets.productNopaging(encodeQueryParam({ terms: { id$assets: JSON.stringify({ tenantId: tenantId, assetType: 'product', memberId: userId, }), } })); const getDeviceState = (product: any, userId: string) => service.assets.instanceNopaging(encodeQueryParam({ terms: { productId: product.id, // id$assets: JSON.stringify({ // tenantId: tenantId, // assetType: 'device', // memberId: userId, // }), } })).pipe( groupBy((instance: any) => instance.state.value), mergeMap(group$ => group$.pipe( count(), map(count => { let v: any = {}; v[group$.key] = count; return v; }), )), map(state => ({ productName: product.name, online: state.online || 0, offline: state.offline || 0 })), defaultIfEmpty({ productName: product.name, 'online': 0, 'offline': 0 }), ); const getAlarmCount = (productId: string, userId: string) => service.alarm.count(encodeQueryParam({ terms: { // deviceId$assets: JSON.stringify({ // tenantId: tenantId, // assetType: 'device', // memberId: userId, // }), productId: productId, } })); useEffect(() => { // todo 查询租户 if (tenantId) { service.member.queryNoPaging({}) .pipe( flatMap((i: any) => getProduct(i.userId) .pipe( flatMap((product: any) => zip(getDeviceState(product, i.userId), getAlarmCount(product.id, i.userId))), map(tp2 => ({ userId: i.userId, name: i.name, key: `${i.userId}-${randomString(7)}`, ...tp2[0], alarmCount: tp2[1] })), defaultIfEmpty({ userId: i.userId, name: i.name, key: `${i.userId}` }) )), toArray(), map(list => list.sort((a, b) => a.userId - b.userId)), ).subscribe((result) => { setData(result); }); } }, [tenantId]); const test: string[] = []; const columns2 = [ { title: '成员', dataIndex: 'name', render: (text, row, index) => { test.push(text); return { children: text, props: { rowSpan: test.filter(i => i === text).length > 1 ? 0 : data.filter(i => i.name === text).length, }, }; }, }, { title: '产品', dataIndex: 'productName', // render: renderContent, }, { title: '设备在线', // colSpan: 2, dataIndex: 'online', render: (text: any) => text || 0, // render: (value, row, index) => { // const obj = { // children: value, // props: { // // rowSpan: 0, // }, // }; // if (index === 2) { // obj.props.rowSpan = 2; // } // // These two are merged into above cell // if (index === 3) { // obj.props.rowSpan = 0; // } // if (index === 4) { // obj.props.colSpan = 0; // } // return obj; // }, }, { title: '设备离线', // colSpan: 0, dataIndex: 'offline', render: (text: any) => text || 0, }, { dataIndex: 'alarmCount', title: '告警记录', render: (text: any) => text || 0, }, ]; return ( <Spin spinning={spinning}> <Card bordered={false}> <div className={styles.tableList}> <div className={styles.tableListForm}> {/* <Search search={(params: any) => { setSpinning(true); params.state = searchParam.terms?.state; handleSearch({ terms: params, pageSize: 10, sorts: searchParam.sorts }); }} /> */} </div> <div className={styles.StandardTable} style={{ marginTop: 10 }}> {/* <Table size='middle' columns={columns} dataSource={(deviceData || {}).data} rowKey="id" onChange={onTableChange} pagination={{ current: deviceData.pageIndex + 1, total: deviceData.total, pageSize: deviceData.pageSize, }} /> */} <Table size="small" pagination={false} columns={tenantAdmin ? columns2 : columns2.filter(i => i.dataIndex !== 'name')} dataSource={data} bordered /> </div> </div> </Card> </Spin> ); }
Example #21
Source File: bindDevice.tsx From jetlinks-ui-antd with MIT License | 4 votes |
BindDecide: React.FC<Props> = props => {
const [spinning, setSpinning] = useState(true);
const [authority, setAuthority] = useState(false);
const [deviceData, setDeviceData] = useState<any>({});
const [deviceIdList, setDeviceIdList] = useState<any[]>([]);
const [searchParam, setSearchParam] = useState<any>({
pageSize: 10,
terms: {},
sorts: {
order: 'descend',
field: 'id',
},
});
const statusMap = new Map();
statusMap.set('在线', 'success');
statusMap.set('离线', 'error');
statusMap.set('未激活', 'processing');
statusMap.set('online', 'success');
statusMap.set('offline', 'error');
statusMap.set('notActive', 'processing');
const handleSearch = (parmes: any) => {
setSearchParam(parmes);
parmes.terms = {
...parmes.terms,
"id#dim-assets$not": `{"assetType":"device","targets":[{"type":"${props.targetType}","id":"${props.targetId}"}]}`
};
api.deviceInstance
.list(encodeParam(parmes))
.then(res => {
setSpinning(false);
if (res.status === 200) {
setDeviceData(res.result);
}
});
};
useEffect(() => {
handleSearch(searchParam);
}, []);
const bindProduct = (value: any) => {
const data = [{
"targetType": props.targetType,
"targetId": props.targetId,
"assetType": "device",
"assetIdList": deviceIdList,
"permission": value.permission
}];
api.assets.BindAssets("device", data)
.then((result: any) => {
if (result.status === 200) {
message.success("资产分配成功");
props.close();
} else {
message.error("资产分配失败");
}
}).catch(() => {
})
};
const columns: ColumnProps<DeviceInstance>[] = [
{
title: 'ID',
dataIndex: 'id',
ellipsis: true,
},
{
title: '设备名称',
dataIndex: 'name',
ellipsis: true,
},
{
title: '产品名称',
dataIndex: 'productName',
ellipsis: true,
},
{
title: '注册时间',
dataIndex: 'registryTime',
width: '200px',
render: (text: any) => (text ? moment(text).format('YYYY-MM-DD HH:mm:ss') : '/'),
sorter: true,
},
{
title: '状态',
dataIndex: 'state',
width: '90px',
render: record =>
record ? <Badge status={statusMap.get(record.value)} text={record.text}/> : '',
filterMultiple: false,
}
];
const onTableChange = (
pagination: PaginationConfig,
filters: any,
sorter: SorterResult<DeviceInstance>,
) => {
let {terms} = searchParam;
handleSearch({
pageIndex: Number(pagination.current) - 1,
pageSize: pagination.pageSize,
terms,
sorts: sorter,
})
};
const rowSelection = {
onChange: (selectedRowKeys: any) => {
setDeviceIdList(selectedRowKeys);
},
};
return (
<Drawer
visible
title='分配设备资产'
width='50%'
onClose={() => props.close()}
closable
>
<Spin spinning={spinning}>
<SearchForm
search={(params: any) => {
handleSearch({
terms: {...params},
pageSize: 10,
sorts: searchParam.sorts,
});
}}
formItems={[
{
label: '设备ID',
key: 'id$like',// id
type: 'string',
},
{
label: '设备名称',
key: 'name$LIKE',
type: 'string',
}
]}
/>
<Table
columns={columns}
dataSource={(deviceData || {}).data}
rowKey="id"
onChange={onTableChange}
rowSelection={{
type: 'checkbox',
...rowSelection,
}}
pagination={{
current: deviceData.pageIndex + 1,
total: deviceData.total,
pageSize: deviceData.pageSize,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ['10', '20', '50', '100'],
showTotal: (total: number) =>
`共 ${total} 条记录 第 ${deviceData.pageIndex + 1}/${Math.ceil(
deviceData.total / deviceData.pageSize,
)}页`,
}}
/>
</Spin>
<div
style={{
position: 'absolute',
right: 0,
bottom: 0,
width: '100%',
borderTop: '1px solid #e9e9e9',
padding: '10px 16px',
background: '#fff',
textAlign: 'right',
}}
>
<Button
onClick={() => {
props.close();
}}
style={{marginRight: 8}}
>
关闭
</Button>
{deviceIdList.length > 0 && <Button
onClick={() => {
setAuthority(true);
}}
type="primary"
>
绑定
</Button>}
</div>
{authority && <Authority close={(data: any) => {
setAuthority(false);
if (data) {
bindProduct(data);
}
}}/>}
</Drawer>
);
}
Example #22
Source File: index.tsx From jetlinks-ui-antd with MIT License | 4 votes |
deviceBind: React.FC<Props> = (props) => {
const [searchParam, setSearchParam] = useState({
pageSize: 10,
terms: {},
sorts: {
order: 'descend',
field: 'id',
},
});
const [spinning, setSpinning] = useState<boolean>(false);
const [deviceIdList, setDeviceIdLIst] = useState<any[]>([]);
const [deviceData, setDeviceData] = useState<any>({});
const [deviceBind, setDeviceBind] = useState<any>();
const statusMap = new Map();
statusMap.set('在线', 'success');
statusMap.set('离线', 'error');
statusMap.set('未激活', 'processing');
statusMap.set('online', 'success');
statusMap.set('offline', 'error');
statusMap.set('notActive', 'processing');
const handleSearch = (params: any) => {
setSearchParam(params);
params.terms = {
...params.terms,
"id#dim-assets": `{"assetType":"device","targets":[{"type":"${props.targetType}","id":"${props.targetId}"}]}`
};
api.deviceInstance
.list(encodeParam(params))
.then(res => {
setSpinning(false);
if (res.status === 200) {
setDeviceData(res.result);
}
});
};
const unBindClassify = (value: any[]) => {
const data = [{
"targetType": props.targetType,
"targetId": props.targetId,
"assetType": "device",
"assetIdList": value
}];
api.assets.UnBindAssets("device", data)
.then((result: any) => {
if (result.status === 200) {
message.success("资产解绑成功");
deviceIdList.splice(0, deviceIdList.length);
handleSearch(searchParam);
} else {
message.error("资产解绑失败");
handleSearch(searchParam);
}
}).catch(() => {
})
};
const columns: ColumnProps<DeviceInstance>[] = [
{
title: 'ID',
dataIndex: 'id',
ellipsis: true,
},
{
title: '设备名称',
dataIndex: 'name',
ellipsis: true,
},
{
title: '产品名称',
dataIndex: 'productName',
ellipsis: true,
},
{
title: '注册时间',
dataIndex: 'registryTime',
width: '200px',
render: (text: any) => (text ? moment(text).format('YYYY-MM-DD HH:mm:ss') : '/'),
sorter: true,
},
{
title: '状态',
dataIndex: 'state',
width: '90px',
render: record =>
record ? <Badge status={statusMap.get(record.value)} text={record.text}/> : '',
filterMultiple: false,
},
{
title: '操作',
width: '200px',
align: 'center',
render: (record: any) => (
<Fragment>
<Popconfirm
title="确认解绑?"
onConfirm={() => {
setSpinning(true);
unBindClassify([record.id])
}}
>
<a>解绑</a>
</Popconfirm>
</Fragment>
),
},
];
useEffect(() => {
if (props.targetId != null || props.targetId != "") {
handleSearch(searchParam);
}
}, [props.targetId]);
const onTableChange = (
pagination: PaginationConfig,
filters: any,
sorter: SorterResult<DeviceInstance>,
) => {
let {terms} = searchParam;
handleSearch({
pageIndex: Number(pagination.current) - 1,
pageSize: pagination.pageSize,
terms,
sorts: sorter,
});
};
const rowSelection = {
onChange: (selectedRowKeys: any) => {
setDeviceIdLIst(selectedRowKeys);
},
};
return (
<div>
<Spin spinning={spinning}>
<Card>
<SearchForm
search={(params: any) => {
handleSearch({
terms: {...params},
pageSize: 10,
sorts: searchParam.sorts,
});
}}
formItems={[
{
label: '设备ID',
key: 'id$like',
type: 'string',
},
{
label: '设备名称',
key: 'name$LIKE',
type: 'string',
}
]}
/>
<Button
icon="plus"
type="primary"
style={{marginBottom: '20px'}}
onClick={() => {
setDeviceBind(true);
}}
>
分配资产
</Button>
{deviceIdList.length > 0 && (
<Popconfirm
title="确认批量解绑?"
onConfirm={() => {
setSpinning(true);
unBindClassify(deviceIdList);
}}
>
<Button
icon="delete"
type="primary"
style={{marginBottom: '20px', marginLeft: "20px"}}
>
批量解绑
</Button>
</Popconfirm>
)}
<Table
columns={columns}
dataSource={(deviceData || {}).data}
rowKey="id"
onChange={onTableChange}
rowSelection={{
type: 'checkbox',
...rowSelection,
}}
pagination={{
current: deviceData.pageIndex + 1,
total: deviceData.total,
pageSize: deviceData.pageSize,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ['10', '20', '50', '100'],
showTotal: (total: number) =>
`共 ${total} 条记录 第 ${deviceData.pageIndex + 1}/${Math.ceil(
deviceData.total / deviceData.pageSize,
)}页`,
}}
/>
</Card>
{deviceBind && <BindDecide targetId={props.targetId} targetType={props.targetType} close={() => {
setDeviceBind(false);
handleSearch(searchParam);
}}/>}
</Spin>
</div>
);
}
Example #23
Source File: bindProduct.tsx From jetlinks-ui-antd with MIT License | 4 votes |
BindProduct: React.FC<Props> = props => {
const [spinning, setSpinning] = useState(true);
const [authority, setAuthority] = useState(false);
const [productData, setProductData] = useState<any>({});
const [productIdList, setProductIdList] = useState<any[]>([]);
const [searchParam, setSearchParam] = useState<any>({
pageSize: 10,
terms: {},
sorts: {
order: 'descend',
field: 'id',
},
});
const handleSearch = (parmes: any) => {
setSearchParam(parmes);
parmes.terms = {
...parmes.terms,
"id#dim-assets$not": `{"assetType":"product","targets":[{"type":"${props.targetType}","id":"${props.targetId}"}]}`
};
api.deviceProdcut
.query(encodeParam(parmes))
.then(res => {
setSpinning(false);
if (res.status === 200) {
setProductData(res.result);
}
});
};
useEffect(() => {
handleSearch(searchParam);
}, []);
const bindProduct = (value: any) => {
const data = [{
"targetType": props.targetType,
"targetId": props.targetId,
"assetType": "product",
"assetIdList": productIdList,
"permission": value.permission
}];
api.assets.BindAssets("product",data)
.then((result: any) => {
if (result.status === 200) {
message.success("资产分配成功");
props.close();
} else {
message.error("资产分配失败");
}
}).catch(() => {
})
};
const columns: ColumnProps<any>[] = [
{
title: '分类ID',
align: 'left',
width: 150,
dataIndex: 'id',
ellipsis: true,
},
{
title: '标识',
align: 'left',
dataIndex: 'key',
},
{
title: '分类名称',
dataIndex: 'name',
align: 'center',
}
];
const onTableChange = (
pagination: PaginationConfig,
filters: any,
sorter: SorterResult<DeviceInstance>,
) => {
let {terms} = searchParam;
handleSearch({
pageIndex: Number(pagination.current) - 1,
pageSize: pagination.pageSize,
terms,
sorts: sorter,
})
};
const rowSelection = {
onChange: (selectedRowKeys: any) => {
setProductIdList(selectedRowKeys);
},
};
return (
<Drawer
visible
title='分配产品资产'
width='50%'
onClose={() => props.close()}
closable
>
<Spin spinning={spinning}>
<SearchForm
search={(params: any) => {
handleSearch({
terms: {...params},
pageSize: 10,
sorts: searchParam.sorts,
});
}}
formItems={[
{
label: '产品名称',
key: 'name$LIKE',
type: 'string',
},
{
label: '产品类型',
key: 'deviceType$IN',
type: 'list',
props: {
data: [
{id: 'device', name: '直连设备'},
{id: 'childrenDevice', name: '网关子设备'},
{id: 'gateway', name: '网关设备'},
],
mode: 'tags',
},
},
]}
/>
<Table
columns={columns}
dataSource={(productData || {}).data}
rowKey="id"
onChange={onTableChange}
rowSelection={{
type: 'checkbox',
...rowSelection,
}}
pagination={{
current: productData.pageIndex + 1,
total: productData.total,
pageSize: productData.pageSize,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ['10', '20', '50', '100'],
showTotal: (total: number) =>
`共 ${total} 条记录 第 ${productData.pageIndex + 1}/${Math.ceil(
productData.total / productData.pageSize,
)}页`,
}}
/>
</Spin>
<div
style={{
position: 'absolute',
right: 0,
bottom: 0,
width: '100%',
borderTop: '1px solid #e9e9e9',
padding: '10px 16px',
background: '#fff',
textAlign: 'right',
}}
>
<Button
onClick={() => {
props.close();
}}
style={{marginRight: 8}}
>
关闭
</Button>
{productIdList.length > 0 && <Button
onClick={() => {
setAuthority(true);
}}
type="primary"
>
绑定
</Button>}
</div>
{authority && <Authority close={(data: any) => {
setAuthority(false);
if (data) {
bindProduct(data);
}
}}/>}
</Drawer>
);
}
Example #24
Source File: index.tsx From jetlinks-ui-antd with MIT License | 4 votes |
productBind: React.FC<Props> = (props) => {
const [spinning, setSpinning] = useState(true);
const [productIdList, setProductIdList] = useState([]);
const [productData, setProductData] = useState<any>({});
const [searchParam, setSearchParam] = useState<any>({
pageSize: 10,
terms: {},
sorts: {
order: 'descend',
field: 'id',
},
});
const [productBind, setProductBind] = useState<boolean>(false);
const columns: ColumnProps<any>[] = [
{
title: '产品ID',
align: 'left',
width: 150,
dataIndex: 'id',
ellipsis: true,
},
{
title: '产品名称',
align: 'left',
width: 150,
dataIndex: 'name',
},
{
title: '说明',
dataIndex: 'description',
width: 300,
align: 'center',
ellipsis: true,
render: (description: string) => (description ? description : '--'),
},
{
title: '操作',
width: '200px',
align: 'center',
render: (record: any) => (
<Fragment>
<Popconfirm
title="确认解绑?"
onConfirm={() => {
setSpinning(true);
unBindClassify([record.id])
}}
>
<a>解绑</a>
</Popconfirm>
</Fragment>
),
},
];
const handleSearch = (params: any) => {
setSearchParam(params);
params.terms = {
...params.terms,
"id#dim-assets": `{"assetType":"product","targets":[{"type":"${props.targetType}","id":"${props.targetId}"}]}`
};
api.deviceProdcut
.query(encodeParam(params))
.then(res => {
setSpinning(false);
if (res.status === 200) {
setProductData(res.result);
}
});
};
const unBindClassify = (value: any[]) => {
const data = [{
"targetType": props.targetType,
"targetId": props.targetId,
"assetType": "product",
"assetIdList": value
}];
api.assets.UnBindAssets("product", data)
.then((result: any) => {
if (result.status === 200) {
message.success("资产解绑成功");
productIdList.splice(0, productIdList.length);
handleSearch(searchParam);
} else {
message.error("资产解绑失败");
handleSearch(searchParam);
}
}).catch(() => {
})
};
const rowSelection = {
onChange: (selectedRowKeys: any) => {
setProductIdList(selectedRowKeys);
},
};
useEffect(() => {
if (props.targetId != null || props.targetId != "") {
handleSearch(searchParam);
}
}, [props.targetId]);
const onTableChange = (
pagination: PaginationConfig,
filters: any,
sorter: SorterResult<DeviceInstance>,
) => {
let {terms} = searchParam;
handleSearch({
pageIndex: Number(pagination.current) - 1,
pageSize: pagination.pageSize,
terms,
sorts: sorter,
})
};
return (
<div>
<Spin spinning={spinning}>
<Card>
<SearchForm
search={(params: any) => {
handleSearch({
terms: {...params},
pageSize: 10,
sorts: searchParam.sorts,
});
}}
formItems={[
{
label: '产品名称',
key: 'name$LIKE',
type: 'string',
},
{
label: '产品类型',
key: 'deviceType$IN',
type: 'list',
props: {
data: [
{id: 'device', name: '直连设备'},
{id: 'childrenDevice', name: '网关子设备'},
{id: 'gateway', name: '网关设备'},
],
mode: 'tags',
},
},
]}
/>
<Button
icon="plus"
type="primary"
style={{marginBottom: '20px'}}
onClick={() => {
setProductBind(true);
}}
>
分配资产
</Button>
{productIdList.length > 0 && (
<Popconfirm
title="确认批量解绑?"
onConfirm={() => {
setSpinning(true);
unBindClassify(productIdList);
}}
>
<Button
icon="delete"
type="primary"
style={{marginBottom: '20px', marginLeft: "20px"}}
>
批量解绑
</Button>
</Popconfirm>
)}
<Table
columns={columns}
dataSource={(productData || {}).data}
rowKey="id"
onChange={onTableChange}
rowSelection={{
type: 'checkbox',
...rowSelection,
}}
pagination={{
current: productData.pageIndex + 1,
total: productData.total,
pageSize: productData.pageSize,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ['10', '20', '50', '100'],
showTotal: (total: number) =>
`共 ${total} 条记录 第 ${productData.pageIndex + 1}/${Math.ceil(
productData.total / productData.pageSize,
)}页`,
}}
/>
</Card>
</Spin>
{productBind && <BindProduct targetId={props.targetId} targetType={props.targetType} close={() => {
setProductBind(false);
handleSearch(searchParam);
}}/>
}
</div>
);
}
Example #25
Source File: index.tsx From jetlinks-ui-antd with MIT License | 4 votes |
Alarm: React.FC<Props> = props => {
const {
form: { getFieldDecorator },
form,
} = props;
const initState: State = {
data: [],
saveAlarmData: {},
searchParam: {
pageSize: 10,
sorts: {
order: 'descend',
field: 'alarmTime',
},
},
alarmLogData: {},
alarmDataList: [],
};
const [data, setData] = useState(initState.data);
const [spinning, setSpinning] = useState(true);
const [saveVisible, setSaveVisible] = useState(false);
const [solveVisible, setSolveVisible] = useState(false);
const [saveAlarmData, setSaveAlarmData] = useState(initState.saveAlarmData);
const [alarmActiveKey, setAlarmActiveKey] = useState('');
const [alarmLogId, setAlarmLogId] = useState<any>(null);
const [solveAlarmLogId, setSolveAlarmLogId] = useState();
const [searchParam, setSearchParam] = useState(initState.searchParam);
const [alarmLogData, setAlarmLogData] = useState(initState.alarmLogData);
const [alarmDataList, setAlarmDataList] = useState(initState.alarmDataList);
const statusMap = new Map();
statusMap.set('运行中', 'success');
statusMap.set('已停止', 'error');
const getProductAlarms = () => {
alarmDataList.splice(0, alarmDataList.length);
apis.deviceAlarm
.getProductAlarms(props.target, props.targetId)
.then((response: any) => {
if (response.status === 200) {
setData(response.result);
response.result.map((item: any) => {
alarmDataList.push(item);
});
setAlarmDataList([...alarmDataList]);
}
setSpinning(false);
})
.catch(() => {});
if (props.target === 'device') {
apis.deviceAlarm
.getProductAlarms('product', props.productId)
.then((response: any) => {
if (response.status === 200) {
response.result.map((item: any) => {
alarmDataList.push(item);
});
setAlarmDataList([...alarmDataList]);
}
})
.catch(() => {});
}
};
useEffect(() => {
setAlarmActiveKey('info');
getProductAlarms();
}, []);
const submitData = (data: any) => {
apis.deviceAlarm
.saveProductAlarms(props.target, props.targetId, data)
.then((response: any) => {
if (response.status === 200) {
message.success('保存成功');
setSaveVisible(false);
getProductAlarms();
}
setSpinning(false);
})
.catch(() => {});
};
const _start = (item: alarm) => {
apis.deviceAlarm
._start(item.id)
.then((response: any) => {
if (response.status === 200) {
message.success('启动成功');
getProductAlarms();
} else {
setSpinning(false);
}
})
.catch();
};
const _stop = (item: any) => {
apis.deviceAlarm
._stop(item.id)
.then((response: any) => {
if (response.status === 200) {
message.success('停止成功');
getProductAlarms();
} else {
setSpinning(false);
}
})
.catch();
};
const deleteAlarm = (id: string) => {
apis.deviceAlarm
.remove(id)
.then((response: any) => {
if (response.status === 200) {
getProductAlarms();
} else {
setSpinning(false);
}
})
.catch(() => {});
};
const columns: ColumnProps<alarm>[] = [
{
title: '告警名称',
dataIndex: 'name',
},
{
title: '创建时间',
dataIndex: 'createTime',
render: (text: any) => (text ? moment(text).format('YYYY-MM-DD HH:mm:ss') : '/'),
},
{
title: '运行状态',
dataIndex: 'state',
render: record =>
record ? <Badge status={statusMap.get(record.text)} text={record.text} /> : '',
},
{
title: '操作',
width: '250px',
align: 'center',
render: (record: any) => (
<Fragment>
<a
onClick={() => {
setSaveAlarmData(record);
setSaveVisible(true);
}}
>
编辑
</a>
<Divider type="vertical" />
<a
onClick={() => {
setAlarmLogId(record.id);
setAlarmActiveKey('logList');
}}
>
告警日志
</a>
<Divider type="vertical" />
{record.state?.value === 'stopped' ? (
<span>
<Popconfirm
title="确认启动此告警?"
onConfirm={() => {
setSpinning(true);
_start(record);
}}
>
<a>启动</a>
</Popconfirm>
<Divider type="vertical" />
<Popconfirm
title="确认删除此告警?"
onConfirm={() => {
setSpinning(true);
deleteAlarm(record.id);
}}
>
<a>删除</a>
</Popconfirm>
</span>
) : (
<Popconfirm
title="确认停止此告警?"
onConfirm={() => {
setSpinning(true);
_stop(record);
}}
>
<a>停止</a>
</Popconfirm>
)}
</Fragment>
),
},
];
const alarmLogColumns: ColumnProps<AlarmLog>[] = [
{
title: '设备ID',
dataIndex: 'deviceId',
},
{
title: '设备名称',
dataIndex: 'deviceName',
},
{
title: '告警名称',
dataIndex: 'alarmName',
},
{
title: '告警时间',
dataIndex: 'alarmTime',
width: '300px',
render: (text: any) => (text ? moment(text).format('YYYY-MM-DD HH:mm:ss') : '/'),
sorter: true,
defaultSortOrder: 'descend',
},
{
title: '处理状态',
dataIndex: 'state',
align: 'center',
width: '100px',
render: text =>
text === 'solve' ? <Tag color="#87d068">已处理</Tag> : <Tag color="#f50">未处理</Tag>,
},
{
title: '操作',
width: '120px',
align: 'center',
render: (record: any) => (
<Fragment>
<a
onClick={() => {
let content: string;
try {
content = JSON.stringify(record.alarmData, null, 2);
} catch (error) {
content = record.alarmData;
}
Modal.confirm({
width: '40VW',
title: '告警数据',
content: (
<pre>
{content}
{record.state === 'solve' && (
<>
<br />
<br />
<span style={{ fontSize: 16 }}>处理结果:</span>
<br />
<p>{record.description}</p>
</>
)}
</pre>
),
okText: '确定',
cancelText: '关闭',
});
}}
>
详情
</a>
<Divider type="vertical" />
{record.state !== 'solve' && (
<a
onClick={() => {
setSolveAlarmLogId(record.id);
setSolveVisible(true);
}}
>
处理
</a>
)}
</Fragment>
),
},
];
const alarmSolve = () => {
form.validateFields((err, fileValue) => {
if (err) return;
apis.deviceAlarm
.alarmLogSolve(solveAlarmLogId || '', fileValue.description)
.then((response: any) => {
if (response.status === 200) {
message.success('保存成功');
setSolveAlarmLogId(undefined);
setSolveVisible(false);
handleSearch(searchParam);
}
})
.catch(() => {});
});
};
const handleSearch = (params?: any) => {
setSearchParam(params);
apis.deviceAlarm
.findAlarmLog(encodeQueryParam(params))
.then((response: any) => {
if (response.status === 200) {
setAlarmLogData(response.result);
}
})
.catch(() => {});
};
const onAlarmProduct = (value: string) => {
let { terms } = searchParam;
if (terms) {
terms.alarmId = value;
} else {
terms = {
alarmId: value,
};
}
handleSearch({
pageIndex: searchParam.pageIndex,
pageSize: searchParam.pageSize,
terms,
sorts: searchParam.sorter || {
order: 'descend',
field: 'alarmTime',
},
});
};
useEffect(() => {
if (alarmActiveKey === 'logList') {
if (props.target === 'device') {
searchParam.terms = {
deviceId: props.targetId,
};
if (alarmLogId != '' && alarmLogId != null && alarmLogId) {
searchParam.terms.alarmId = alarmLogId;
}
} else {
searchParam.terms = {
productId: props.targetId,
};
if (alarmLogId != '' && alarmLogId != null && alarmLogId) {
searchParam.terms.alarmId = alarmLogId;
}
}
handleSearch(searchParam);
}
}, [alarmActiveKey]);
const onTableChange = (
pagination: PaginationConfig,
filters: any,
sorter: SorterResult<AlarmLog>,
) => {
handleSearch({
pageIndex: Number(pagination.current) - 1,
pageSize: pagination.pageSize,
terms: searchParam.terms,
sorts: sorter,
});
};
return (
<Spin tip="加载中..." spinning={spinning}>
<Card>
<Tabs
activeKey={alarmActiveKey}
onTabClick={(key: any) => {
setAlarmLogId(undefined);
setAlarmActiveKey(key);
}}
>
<Tabs.TabPane tab="告警设置" key="info">
<Card
title={
<Button
icon="plus"
type="primary"
onClick={() => {
setSaveAlarmData({});
setSaveVisible(true);
}}
>
新增告警
</Button>
}
bordered={false}
>
<Table rowKey="id" columns={columns} dataSource={data} pagination={false} />
</Card>
</Tabs.TabPane>
<Tabs.TabPane tab="告警记录" key="logList">
<div>
<Select
placeholder="选择告警设置"
allowClear
style={{ width: 300 }}
value={alarmLogId}
onChange={(value: string) => {
onAlarmProduct(value);
setAlarmLogId(value);
}}
>
{alarmDataList.length > 0 &&
alarmDataList.map(item => (
<Select.Option key={item.id}>{item.name}</Select.Option>
))}
</Select>
</div>
<div className={styles.StandardTable} style={{ marginTop: 10 }}>
<Table
dataSource={alarmLogData.data}
columns={alarmLogColumns}
rowKey="id"
onChange={onTableChange}
pagination={{
current: alarmLogData.pageIndex + 1,
total: alarmLogData.total,
pageSize: alarmLogData.pageSize,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ['10', '20', '50', '100'],
showTotal: (total: number) =>
`共 ${total} 条记录 第 ${alarmLogData.pageIndex + 1}/${Math.ceil(
alarmLogData.total / alarmLogData.pageSize,
)}页`,
}}
/>
</div>
</Tabs.TabPane>
</Tabs>
</Card>
{saveVisible && (
<Save
close={() => {
setSaveAlarmData({});
setSaveVisible(false);
getProductAlarms();
}}
save={(data: any) => {
setSpinning(true);
submitData(data);
}}
data={saveAlarmData}
targetId={props.targetId}
target={props.target}
metaData={props.metaData}
name={props.name}
productName={props.productName}
productId={props.productId}
/>
)}
{solveVisible && (
<Modal
title="告警处理结果"
visible
okText="确定"
cancelText="取消"
width="700px"
onOk={() => {
alarmSolve();
}}
onCancel={() => {
setSolveVisible(false);
setSolveAlarmLogId(undefined);
}}
>
<Form labelCol={{ span: 3 }} wrapperCol={{ span: 21 }} key="solve_form">
<Form.Item key="description" label="处理结果">
{getFieldDecorator('description', {
rules: [
{ required: true, message: '请输入处理结果' },
{ max: 2000, message: '处理结果不超过2000个字符' },
],
})(<Input.TextArea rows={8} placeholder="请输入处理结果" />)}
</Form.Item>
</Form>
</Modal>
)}
</Spin>
);
}
Example #26
Source File: History.tsx From jetlinks-ui-antd with MIT License | 4 votes |
UpgradeHistory: React.FC<Props> = (props) => {
const initState: State = {
data: {},
searchParam: { pageSize: 10 },
spinning: false,
};
const [searchParam, setSearchParam] = useState(initState.searchParam);
const [data, setData] = useState(initState.data);
const [spinning, setSpinning] = useState(initState.spinning);
const upgradeStatus = new Map();
upgradeStatus.set('waiting', 'warning');
upgradeStatus.set('processing', 'processing');
upgradeStatus.set('success', 'success');
upgradeStatus.set('failed', 'error');
upgradeStatus.set('canceled', 'default');
const handleSearch = (params?: any) => {
setSearchParam(params);
apis.firmware.upgradeHistory(encodeQueryParam(params))
.then((response: any) => {
if (response.status === 200) {
setData(response.result);
}
setSpinning(false);
},
).catch(() => {
});
};
useEffect(() => {
setSpinning(true);
let terms = {
firmwareId: props.firmwareId,
};
if (props.taskId !== '' && props.taskId) {
terms['taskId'] = props.taskId;
}
if (props.historyState !== '' && props.historyState) {
terms['state'] = props.historyState;
}
handleSearch({
pageSize: 10,
terms: terms,
});
}, []);
const columns: ColumnProps<UpgradeHistoryData>[] = [
{
title: '设备名称',
dataIndex: 'deviceName',
},
{
title: '任务名称',
dataIndex: 'taskName',
},
{
title: '版本',
dataIndex: 'version',
},
{
title: '状态',
dataIndex: 'state',
render: record => <Badge status={upgradeStatus.get(record.value)} text={record.text}/>,
},
{
title: '进度',
dataIndex: 'progress',
render: (text: any) => text + ' %',
},
{
title: '创建时间',
dataIndex: 'createTime',
width: '200px',
render: (text: any) => moment(text).format('YYYY-MM-DD HH:mm:ss'),
sorter: true,
defaultSortOrder: 'descend',
},
];
const onTableChange = (
pagination: PaginationConfig,
filters: any,
sorter: SorterResult<UpgradeHistoryData>,
) => {
handleSearch({
pageIndex: Number(pagination.current) - 1,
pageSize: pagination.pageSize,
terms: searchParam.terms,
sorts: sorter,
});
};
return (
<div>
<Spin spinning={spinning}>
<Card style={{ marginBottom: 20 }}>
<div>
<SearchForm
search={(params: any) => {
let terms = {
firmwareId: props.firmwareId,
taskName$LIKE:params['taskName$LIKE'],
};
if (props.taskId !== '' && props.taskId) {
terms['taskId'] = props.taskId;
}
if (props.historyState !== '' && props.historyState) {
terms['state'] = props.historyState;
}
handleSearch({
terms: { ...terms },
pageSize: 10,
sorts: searchParam.sorts,
});
}}
formItems={[{
label: '任务名称',
key: 'taskName$LIKE',
type: 'string',
}]}
/>
</div>
<div className={styles.StandardTable}>
<Table
columns={columns}
dataSource={data?.data}
rowKey="id"
onChange={onTableChange}
pagination={{
current: data.pageIndex + 1,
total: data.total,
pageSize: data.pageSize,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ['10', '20', '50', '100'],
showTotal: (total: number) =>
`共 ${total} 条记录 第 ${data.pageIndex + 1}/${Math.ceil(
data.total / data.pageSize,
)}页`,
}}
/>
</div>
</Card>
</Spin>
</div>
);
}
Example #27
Source File: index.tsx From jetlinks-ui-antd with MIT License | 4 votes |
DeviceList = (props: Props) => {
const [searchParam, setSearchParam] = useState({
pageSize: 10,
terms: { productId: props.productId },
});
const [deviceData, setDeviceData] = useState<any>({});
const [deviceId, setDeviceId] = useState(props.data);
const submitData = () => {
props.save(deviceId);
};
const handleSearch = (params?: any) => {
setSearchParam(params);
apis.deviceInstance
.list(encodeQueryParam(params))
.then(response => {
if (response.status === 200) {
setDeviceData(response.result);
}
})
.catch(() => {});
};
useEffect(() => {
handleSearch(searchParam);
}, []);
const onTableChange = (pagination: PaginationConfig, filters: any, sorter: SorterResult<any>) => {
apis.deviceInstance
.list(
encodeQueryParam({
pageIndex: Number(pagination.current) - 1,
pageSize: pagination.pageSize,
sorts: sorter,
terms: { productId: props.productId },
}),
)
.then(response => {
if (response.status === 200) {
setDeviceData(response.result);
}
})
.catch(() => {});
};
const rowSelection = {
onChange: (selectedRowKeys: any) => {
setDeviceId(selectedRowKeys);
},
};
const statusMap = new Map();
statusMap.set('在线', 'success');
statusMap.set('离线', 'error');
statusMap.set('未激活', 'processing');
const columns: ColumnProps<any>[] = [
{
title: 'ID',
dataIndex: 'id',
ellipsis: true,
},
{
title: '设备名称',
dataIndex: 'name',
ellipsis: true,
},
{
title: '产品名称',
dataIndex: 'productName',
ellipsis: true,
},
{
title: '注册时间',
dataIndex: 'registryTime',
width: '200px',
ellipsis: true,
render: (text: any) => moment(text).format('YYYY-MM-DD HH:mm:ss'),
sorter: true,
defaultSortOrder: 'descend',
},
{
title: '状态',
dataIndex: 'state',
width: '120px',
render: record =>
record ? <Badge status={statusMap.get(record.text)} text={record.text} /> : '',
},
];
return (
<Modal
title="选择设备"
visible
okText="确定"
cancelText="取消"
onOk={() => {
submitData();
}}
width="60%"
style={{ marginTop: -30 }}
onCancel={() => props.close()}
>
<div
className={styles.tableList}
style={{ maxHeight: 600, overflowY: 'auto', overflowX: 'hidden' }}
>
<div className={styles.tableListForm}>
<SearchForm
search={(params: any) => {
handleSearch({ terms: { ...searchParam.terms, ...params }, pageSize: 10 });
}}
formItems={[
{
label: '设备名称',
key: 'name$LIKE',
type: 'string',
},
{
label: '设备ID',
key: 'deviceId$IN',
type: 'string',
},
]}
/>
</div>
<div className={styles.StandardTable}>
<Table
columns={columns}
dataSource={deviceData.data}
rowKey="id"
onChange={onTableChange}
rowSelection={{
selectedRowKeys: deviceId,
type: 'checkbox',
...rowSelection,
}}
pagination={{
current: deviceData.pageIndex + 1,
total: deviceData.total,
pageSize: deviceData.pageSize,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ['10', '20', '50', '100'],
showTotal: (total: number) =>
`共 ${total} 条记录 第 ${deviceData.pageIndex + 1}/${Math.ceil(
deviceData.total / deviceData.pageSize,
)}页`,
}}
/>
</div>
</div>
</Modal>
);
}
Example #28
Source File: upgrade-task.tsx From jetlinks-ui-antd with MIT License | 4 votes |
UpgradeTask: React.FC<Props> = (props) => {
const initState: State = {
data: {},
saveUpgradeTaskData: {},
searchParam: { pageSize: 10 },
spinning: false,
};
const [searchParam, setSearchParam] = useState(initState.searchParam);
const [data, setData] = useState(initState.data);
const [spinning, setSpinning] = useState(initState.spinning);
const handleSearch = (params?: any) => {
setSearchParam(params);
apis.firmware.upgradeTask(encodeQueryParam(params))
.then((response: any) => {
if (response.status === 200) {
setData(response.result);
}
setSpinning(false);
},
).catch(() => {
});
};
useEffect(() => {
setSpinning(true);
handleSearch({
pageSize: 10,
terms: {
firmwareId: props.firmwareId,
},
});
}, []);
const columns: ColumnProps<UpgradeTaskData>[] = [
{
title: 'ID',
dataIndex: 'id',
},
{
title: '任务名称',
dataIndex: 'name',
},
{
title: '升级方式',
dataIndex: 'mode.text',
},
{
title: '超时时间',
dataIndex: 'timeoutSeconds',
render: (text: any) => text + ' 秒',
},
{
title: '创建时间',
dataIndex: 'createTime',
width: '200px',
render: (text: any) => moment(text).format('YYYY-MM-DD HH:mm:ss'),
sorter: true,
defaultSortOrder: 'descend',
},
{
title: '操作',
width: '120px',
align: 'center',
render: (record: any) => (
<Fragment>
<a onClick={() => {
props.jumpPedal(record);
}}
>
查看
</a>
<Divider type="vertical"/>
<Popconfirm title="确定删除此任务吗?请谨慎操作" onConfirm={() => removeUpgrade(record)}>
<a>
删除
</a>
</Popconfirm>
</Fragment>
),
},
];
const onTableChange = (
pagination: PaginationConfig,
filters: any,
sorter: SorterResult<UpgradeTaskData>,
) => {
handleSearch({
pageIndex: Number(pagination.current) - 1,
pageSize: pagination.pageSize,
terms: searchParam.terms,
sorts: sorter,
});
};
const removeUpgrade = (item: any) => {
setSpinning(true);
apis.firmware.removeUpgrade(item.id)
.then((response: any) => {
if (response.status === 200) {
message.success('删除成功');
handleSearch(searchParam);
}
}).catch(() => {
});
};
return (
<div>
<Spin spinning={spinning}>
<Card style={{ marginBottom: 20 }}>
<div className={styles.tableListOperator} style={{ paddingBottom: 20 }}>
<Button icon="plus" type="primary" onClick={() => {
props.jumpPedal({});
}}>
新建
</Button>
</div>
<div className={styles.StandardTable}>
<Table
columns={columns}
dataSource={data?.data}
rowKey="id"
onChange={onTableChange}
pagination={{
current: data.pageIndex + 1,
total: data.total,
pageSize: data.pageSize,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ['10', '20', '50', '100'],
showTotal: (total: number) =>
`共 ${total} 条记录 第 ${data.pageIndex + 1}/${Math.ceil(
data.total / data.pageSize,
)}页`,
}}
/>
</div>
</Card>
</Spin>
</div>
);
}
Example #29
Source File: index.tsx From jetlinks-ui-antd with MIT License | 4 votes |
Firmware: React.FC<Props> = props => {
const initState: State = {
searchParam: {
pageSize: 10,
sorts: {
order: 'descend',
field: 'id',
},
},
saveVisible: false,
firmwareData: {},
saveFirmwareData: {},
};
const [productList, setProductList] = useState([]);
const [searchParam, setSearchParam] = useState(initState.searchParam);
const [saveVisible, setSaveVisible] = useState(initState.saveVisible);
const [firmwareData, setFirmwareData] = useState(initState.firmwareData);
const [saveFirmwareData, setSaveFirmwareData] = useState(initState.saveFirmwareData);
const [spinning, setSpinning] = useState(true);
const handleSearch = (params?: any) => {
setSearchParam(params);
apis.firmware
.list(encodeQueryParam(params))
.then((response: any) => {
if (response.status === 200) {
setFirmwareData(response.result);
}
setSpinning(false);
})
.catch(() => {});
};
useEffect(() => {
apis.deviceProdcut
.queryNoPagin({
paging: false
})
.then(response => {
setProductList(response.result);
})
.catch(() => {});
handleSearch(searchParam);
}, []);
const handleDelete = (params: FirmwareData) => {
apis.firmware
.remove(params.id)
.then((response: any) => {
if (response.status === 200) {
message.success('删除成功');
handleSearch(searchParam);
}
})
.catch(() => {});
};
const handleSave = (item: any) => {
apis.firmware
.saveOrUpdate(item)
.then((response: any) => {
if (response.status === 200) {
message.success('保存成功');
handleSearch(searchParam);
}
})
.catch(() => {});
};
const columns: ColumnProps<FirmwareData>[] = [
{
title: '固件名称',
dataIndex: 'name',
},
{
title: '固件版本',
dataIndex: 'version',
},
{
title: '所属产品',
dataIndex: 'productName',
},
{
title: '签名方式',
dataIndex: 'signMethod',
},
{
title: '创建时间',
dataIndex: 'createTime',
width: '200px',
align: 'center',
render: (text: any) => moment(text).format('YYYY-MM-DD HH:mm:ss'),
sorter: true,
defaultSortOrder: 'descend',
},
{
title: '操作',
width: '300px',
align: 'center',
render: (record: FirmwareData) => (
<Fragment>
<a
onClick={() => {
router.push(`/device/firmware/save/${record.id}`);
}}
>
查看
</a>
<Divider type="vertical" />
<a
onClick={() => {
setSaveFirmwareData(record);
setSaveVisible(true);
}}
>
编辑
</a>
<Divider type="vertical" />
<Popconfirm
title="确定删除?"
onConfirm={() => {
handleDelete(record);
}}
>
<a>删除</a>
</Popconfirm>
</Fragment>
),
},
];
const onTableChange = (
pagination: PaginationConfig,
filters: any,
sorter: SorterResult<FirmwareData>,
) => {
setSpinning(true);
handleSearch({
pageIndex: Number(pagination.current) - 1,
pageSize: pagination.pageSize,
terms: searchParam.terms,
sorts: sorter,
});
};
return (
<PageHeaderWrapper title="固件升级">
<Spin spinning={spinning}>
<Card bordered={false}>
<div className={styles.tableList}>
<div>
<SearchForm
search={(params: any) => {
setSpinning(true);
handleSearch({
terms: params,
pageSize: 10,
sorts: searchParam.sorts,
});
}}
formItems={[
{
label: '固件名称',
key: 'name$LIKE',
type: 'string',
},
{
label: '所属产品',
key: 'productId',
type: 'list',
props: {
data: productList,
mode: 'tags',
},
},
]}
/>
</div>
<div className={styles.tableListOperator}>
<Button
icon="plus"
type="primary"
onClick={() => {
setSaveFirmwareData({});
setSaveVisible(true);
}}
>
新建
</Button>
</div>
<div className={styles.StandardTable}>
<Table
loading={props.loading}
dataSource={(firmwareData || {}).data}
columns={columns}
rowKey="id"
onChange={onTableChange}
pagination={{
current: firmwareData?.pageIndex + 1,
total: firmwareData?.total,
pageSize: firmwareData?.pageSize,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ['10', '20', '50', '100'],
showTotal: (total: number) =>
`共 ${total} 条记录 第 ${firmwareData?.pageIndex + 1}/${Math.ceil(
firmwareData?.total / firmwareData?.pageSize,
)}页`,
}}
/>
</div>
</div>
</Card>
</Spin>
{saveVisible && (
<Save
data={saveFirmwareData}
close={() => {
setSaveVisible(false);
setSpinning(true);
handleSearch(searchParam);
}}
save={(item: any) => {
setSaveVisible(false);
setSpinning(true);
handleSave(item);
}}
/>
)}
</PageHeaderWrapper>
);
}