diff --git a/code/web/client/assets/color.less b/code/web/client/assets/color.less
index 0047c87..96c2350 100644
--- a/code/web/client/assets/color.less
+++ b/code/web/client/assets/color.less
@@ -174,7 +174,7 @@ button::-moz-focus-inner,
[type='submit']::-moz-focus-inner {border-style: none;}
fieldset {border: 0;}
legend {color: inherit;}
-mark {background-color: color(~`colorPalette("@{table-header-sort-active-bg}", 2)`);}
+mark {background-color: #feffe6;}
::selection {color: #fff;background: @primary-color;}
.anticon {color: inherit;}
.ant-fade-enter, .ant-fade-appear {animation-fill-mode: both;}
@@ -1147,10 +1147,10 @@ tr > .ant-picker-cell-in-view.ant-picker-cell-range-hover-start:last-child::afte
.ant-mentions-dropdown-menu-item-active {background-color: @item-hover-bg;}
.ant-menu-item-danger.ant-menu-item {color: #ff4d4f;}
.ant-menu-item-danger.ant-menu-item:hover, .ant-menu-item-danger.ant-menu-item-active {color: #ff4d4f;}
-.ant-menu-item-danger.ant-menu-item:active {background: color(~`colorPalette("@{alert-info-border-color}", 4)`);}
+.ant-menu-item-danger.ant-menu-item:active {background: color(~`colorPalette("@{skeleton-color}", 1)`);}
.ant-menu-item-danger.ant-menu-item-selected {color: #ff4d4f;}
.ant-menu-item-danger.ant-menu-item-selected > a, .ant-menu-item-danger.ant-menu-item-selected > a:hover {color: #ff4d4f;}
-.ant-menu:not(.ant-menu-horizontal) .ant-menu-item-danger.ant-menu-item-selected {background-color: color(~`colorPalette("@{alert-info-border-color}", 4)`);}
+.ant-menu:not(.ant-menu-horizontal) .ant-menu-item-danger.ant-menu-item-selected {background-color: color(~`colorPalette("@{skeleton-color}", 1)`);}
.ant-menu-inline .ant-menu-item-danger.ant-menu-item::after {border-right-color: #ff4d4f;}
.ant-menu-dark .ant-menu-item-danger.ant-menu-item, .ant-menu-dark .ant-menu-item-danger.ant-menu-item:hover, .ant-menu-dark .ant-menu-item-danger.ant-menu-item > a {color: #ff4d4f;}
.ant-menu-dark.ant-menu-dark:not(.ant-menu-horizontal) .ant-menu-item-danger.ant-menu-item-selected {color: #fff;background-color: #ff4d4f;}
@@ -1727,17 +1727,17 @@ tr.ant-table-expanded-row:hover > td {background: @table-expanded-row-bg;}
.ant-tag-checkable:active, .ant-tag-checkable-checked {color: #fff;}
.ant-tag-checkable-checked {background-color: @primary-color;}
.ant-tag-checkable:active {background-color: color(~`colorPalette("@{primary-color}", 7)`);}
-.ant-tag-pink {color: #c41d7f;background: #fff0f6;border-color: #ffadd2;}
+.ant-tag-pink {color: #c41d7f;background: color(~`colorPalette("@{shadow-color}", 1)`);border-color: #ffadd2;}
.ant-tag-pink-inverse {color: #fff;background: #eb2f96;border-color: #eb2f96;}
-.ant-tag-magenta {color: #c41d7f;background: #fff0f6;border-color: #ffadd2;}
+.ant-tag-magenta {color: #c41d7f;background: color(~`colorPalette("@{shadow-color}", 1)`);border-color: #ffadd2;}
.ant-tag-magenta-inverse {color: #fff;background: #eb2f96;border-color: #eb2f96;}
-.ant-tag-red {color: #cf1322;background: color(~`colorPalette("@{alert-info-border-color}", 4)`);border-color: #ffa39e;}
+.ant-tag-red {color: #cf1322;background: color(~`colorPalette("@{skeleton-color}", 1)`);border-color: #ffa39e;}
.ant-tag-red-inverse {color: #fff;background: #f5222d;border-color: #f5222d;}
.ant-tag-volcano {color: #d4380d;background: #fff2e8;border-color: #ffbb96;}
.ant-tag-volcano-inverse {color: #fff;background: #fa541c;border-color: #fa541c;}
-.ant-tag-orange {color: #d46b08;background: #fff7e6;border-color: #ffd591;}
+.ant-tag-orange {color: #d46b08;background: color(~`colorPalette("@{switch-bg}", 1)`);border-color: #ffd591;}
.ant-tag-orange-inverse {color: #fff;background: #fa8c16;border-color: #fa8c16;}
-.ant-tag-yellow {color: #d4b106;background: color(~`colorPalette("@{table-header-sort-active-bg}", 2)`);border-color: #fffb8f;}
+.ant-tag-yellow {color: #d4b106;background: #feffe6;border-color: #fffb8f;}
.ant-tag-yellow-inverse {color: #fff;background: #fadb14;border-color: #fadb14;}
.ant-tag-gold {color: #d48806;background: #fffbe6;border-color: #ffe58f;}
.ant-tag-gold-inverse {color: #fff;background: #faad14;border-color: #faad14;}
@@ -1749,9 +1749,9 @@ tr.ant-table-expanded-row:hover > td {background: @table-expanded-row-bg;}
.ant-tag-green-inverse {color: #fff;background: #52c41a;border-color: #52c41a;}
.ant-tag-blue {color: #096dd9;background: #e6f7ff;border-color: #91d5ff;}
.ant-tag-blue-inverse {color: #fff;background: #1890ff;border-color: #1890ff;}
-.ant-tag-geekblue {color: #1d39c4;background: color(~`colorPalette("@{slider-rail-background-color-hover}", 1)`);border-color: #adc6ff;}
+.ant-tag-geekblue {color: #1d39c4;background: color(~`colorPalette("@{disabled-color}", 1)`);border-color: #adc6ff;}
.ant-tag-geekblue-inverse {color: #fff;background: #2f54eb;border-color: #2f54eb;}
-.ant-tag-purple {color: #531dab;background: color(~`colorPalette("@{shadow-color-inverse}", 1)`);border-color: #d3adf7;}
+.ant-tag-purple {color: #531dab;background: #f9f0ff;border-color: #d3adf7;}
.ant-tag-purple-inverse {color: #fff;background: #722ed1;border-color: #722ed1;}
.ant-tag-success {color: #52c41a;background: @success-color-deprecated-bg;border-color: @success-color-deprecated-border;}
.ant-tag-processing {color: @primary-color;background: @info-color-deprecated-bg;border-color: @info-color-deprecated-border;}
diff --git a/code/web/client/src/app.js b/code/web/client/src/app.js
index 844a85a..dde044d 100644
--- a/code/web/client/src/app.js
+++ b/code/web/client/src/app.js
@@ -5,6 +5,7 @@ import Layout from './layout';
import Auth from './sections/auth';
import Gateway from './sections/gateway';
import Search from './sections/search';
+import Factor from './sections/factor';
const App = props => {
const { projectName } = props
@@ -16,7 +17,7 @@ const App = props => {
return (
)
}
diff --git a/code/web/client/src/layout/components/header/index.js b/code/web/client/src/layout/components/header/index.js
index 13856ff..7701c74 100644
--- a/code/web/client/src/layout/components/header/index.js
+++ b/code/web/client/src/layout/components/header/index.js
@@ -76,6 +76,9 @@ const Header = props => {
} >
网关配置
+ } >
+ 监测因素
+
主题切换} >
diff --git a/code/web/client/src/sections/factor/actions/factors.js b/code/web/client/src/sections/factor/actions/factors.js
new file mode 100644
index 0000000..792cd96
--- /dev/null
+++ b/code/web/client/src/sections/factor/actions/factors.js
@@ -0,0 +1,16 @@
+'use strict';
+
+import { basicAction } from '@peace/utils'
+import { ApiTable } from '$utils'
+
+export function list(query) {
+ return dispatch => basicAction({
+ type: 'get',
+ dispatch: dispatch,
+ query: query,
+ actionType: 'GET_FACTOR_LIST',
+ url: ApiTable.getFactors,
+ msg: { error: '获取监测原型列表失败' },
+ reducer: { name: 'factors' }
+ })
+}
\ No newline at end of file
diff --git a/code/web/client/src/sections/factor/actions/index.js b/code/web/client/src/sections/factor/actions/index.js
new file mode 100644
index 0000000..335a5b6
--- /dev/null
+++ b/code/web/client/src/sections/factor/actions/index.js
@@ -0,0 +1,7 @@
+'use strict';
+
+import * as factor from './factors'
+
+export default {
+ ...factor
+}
\ No newline at end of file
diff --git a/code/web/client/src/sections/factor/containers/ConfigModal.js b/code/web/client/src/sections/factor/containers/ConfigModal.js
new file mode 100644
index 0000000..91cc7c3
--- /dev/null
+++ b/code/web/client/src/sections/factor/containers/ConfigModal.js
@@ -0,0 +1,145 @@
+import React, { useEffect, useRef } from 'react';
+import { connect } from 'react-redux';
+import { Spin, Select, Divider, Space, Button, Modal, Input, Form, Switch, AutoComplete } from 'antd';
+import ProForm, { ProFormText, ProFormSelect, ProFormTextArea } from '@ant-design/pro-form';
+import { useState } from 'react';
+import { InMode, OutMode, ProtocolTypes } from './models';
+import { PlusOutlined } from '@ant-design/icons';
+const { Option } = Select;
+
+const ConfigModal = (props) => {
+ const { dispatch, actions, visible, close, editData } = props
+ const formRef = useRef()
+ const inputRef = useRef()
+ const { gateway } = actions
+ const [protocols, setProtocols] = useState([])
+ const [newProtocol, setNewProtocol] = useState('')
+
+ useEffect(() => {
+ setProtocols([]);
+ dispatch(gateway.getProtocols()).then(res => {
+ if (res.success) {
+ setProtocols(res.payload.data.sort())
+ }
+ })
+ }, [])
+
+ const onNewProtocolChange = (e) => {
+ setNewProtocol(e.target.value)
+ }
+
+ const addNewProtocol = (e) => {
+ e.preventDefault();
+ setProtocols([...protocols, newProtocol])
+ setNewProtocol('');
+ setTimeout(()=>{
+ inputRef.current?.focus();
+ })
+ }
+
+ const batchAdd=(v)=>{
+
+ }
+
+ return {
+ formRef.current.validateFields()
+ .then(v => {
+ v.id = editData?.id;
+ if (!v.in_config) {
+ v.in_config = '{}'
+ }
+ if (!v.out_config) {
+ v.out_config = '{}'
+ }
+ dispatch(editData ? gateway.edit([v]) : gateway.add([v]))
+ .then(res => {
+ if (res.success) {
+ dispatch(gateway.list())
+ close()
+ }
+ })
+ })
+ }}
+ onCancel={() => {
+ close()
+ }}
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+function mapStateToProps(state) {
+ const { auth, global } = state;
+ return {
+ user: auth.user,
+ actions: global.actions,
+ };
+}
+
+export default connect(mapStateToProps)(ConfigModal);
diff --git a/code/web/client/src/sections/factor/containers/FactorProfile.js b/code/web/client/src/sections/factor/containers/FactorProfile.js
new file mode 100644
index 0000000..4b57163
--- /dev/null
+++ b/code/web/client/src/sections/factor/containers/FactorProfile.js
@@ -0,0 +1,196 @@
+import React, { useState, useEffect, useRef } from 'react';
+import { connect } from 'react-redux';
+import { Spin, Button, Card, Input, Space, Tag, Table } from 'antd';
+import '../style.less';
+import { push } from 'react-router-redux'
+import ProTable, { TableDropdown } from '@ant-design/pro-table';
+import { InMode, OutMode, ProtocolTypes } from './models';
+import ConfigModal from './ConfigModal';
+import { request } from 'superagent';
+
+const FactorProfile = (props) => {
+ const { dispatch, actions, user, loading, factors, total } = props
+
+ const { factor } = actions;
+ const [configModalVis, setConfigModalVis] = useState(false)
+ const [editData, setEditData] = useState(null)
+ const [fdata, setFdata] = useState([])
+
+ const pageSize = 10
+
+ useEffect(() => {
+ // dispatch(factor.list())
+ }, [])
+
+ const actionRef = useRef();
+ const columns = [
+ {
+ dataIndex: 'id',
+ valueType: 'indexBorder',
+ width: 48,
+ }, {
+ title: '名称',
+ dataIndex: 'Name',
+ ellipsis: true
+ },
+ {
+ title: '编码',
+ dataIndex: 'Proto',
+ },
+ {
+ title: '监测项',
+ dataIndex: 'Factor_proto_item',
+ ellipsis: true,
+ render: (_, record) => (
+
+ {record.Factor_proto_item.map(({ Name }) => (
+
+ {Name}
+
+ ))}
+
+ ),
+ }, {
+ title: '操作',
+ valueType: 'option',
+ key: 'option',
+ render: (txt, row, _, action) => [
+
+ ],
+ }
+ ]
+
+ const requestList = async (params) => {
+ const ret = await dispatch(factor.list());
+ console.log(ret)
+ let tmp = []
+ tmp = ret.payload.data.data;
+ if (!!params.Name) {
+ tmp = tmp.filter(a => a.Name.includes(params.Name))
+ }
+ if (!!params.Proto) {
+ tmp = tmp.filter(a => a.Proto.includes(params.Proto))
+ }
+ if(!!params.Factor_proto_item){
+ tmp = tmp.filter(a => a.Factor_proto_item.some(d=>{
+ return d.Name.includes(params.Factor_proto_item) ||
+ d.Field_name.includes(params.Factor_proto_item) ||
+ d.Item_unit.includes(params.Factor_proto_item)
+ }))
+ }
+ let data = tmp.slice(params.pageSize * (params.current - 1), params.pageSize * params.current);
+ data = data.map(d => ({
+ ...d,
+ key: d.Proto + d.Name
+ }))
+ setFdata(data)
+ return {
+ total: tmp.length,
+ data: data
+ }
+ const query = {
+ limit: params.pageSize,
+ offset: params.pageSize * (params.current - 1)
+ }
+ const res = await dispatch(factor.list(query));
+ return {
+ ...res,
+ total: res.payload.data ? res.payload.data.total : 0
+ }
+ }
+
+ const expandRow = (record, index, indent, expanded) => {
+ let cols = []
+ if (expanded) {
+ cols = [{
+ title: '名称',
+ dataIndex: 'Name',
+ ellipsis: true
+ }, {
+ title: '字段',
+ dataIndex: 'Field_name',
+ ellipsis: true
+ }, {
+ title: '单位',
+ dataIndex: 'Item_unit',
+ ellipsis: true
+ },
+ ]
+ return
+ }
+ }
+ const [activeExpRow, setActiveExpRow] = React.useState();
+
+ return (
+
+ {/*
*/}
+ [
+ ,
+ ]}
+ pagination={{
+ pageSize: pageSize,
+ onChange: (page) => console.log(page),
+ }}
+ expandedRowKeys={activeExpRow}
+ rowExpandable={(record) => { return true; }}
+ expandedRowRender={expandRow}
+ onExpand={
+ (expanded, record) => {
+ const keys = [];
+ if (expanded) {
+ keys.push(record.Proto + record.Name);
+ }
+ console.log(keys);
+ setActiveExpRow(keys);
+ }
+ }
+ >
+
+
+ {
+ configModalVis ?
+ {
+ setConfigModalVis(false)
+ setEditData(null)
+ }}
+ editData={editData}
+ /> : ''
+ }
+ {/* */}
+
+ )
+}
+
+function mapStateToProps(state) {
+ const { auth, global, factors } = state;
+ return {
+ user: auth.user,
+ actions: global.actions,
+ loading: factors.isRequesting,
+ factors: factors.data?.data ?? [],
+ };
+}
+
+export default connect(mapStateToProps)(FactorProfile);
diff --git a/code/web/client/src/sections/factor/containers/index.js b/code/web/client/src/sections/factor/containers/index.js
new file mode 100644
index 0000000..a3e33d1
--- /dev/null
+++ b/code/web/client/src/sections/factor/containers/index.js
@@ -0,0 +1,5 @@
+'use strict';
+
+import FactorProfile from './FactorProfile';
+
+export { FactorProfile };
\ No newline at end of file
diff --git a/code/web/client/src/sections/factor/containers/models.js b/code/web/client/src/sections/factor/containers/models.js
new file mode 100644
index 0000000..e479d43
--- /dev/null
+++ b/code/web/client/src/sections/factor/containers/models.js
@@ -0,0 +1,4 @@
+const GatewayMode = ["tcp", "udp", "mqtt", "http", "dtu"]
+export const InMode = GatewayMode
+export const OutMode = GatewayMode
+export const ProtocolTypes = ["DeviceA", "DeviceB", "DeviceC", "DeviceD"]
\ No newline at end of file
diff --git a/code/web/client/src/sections/factor/index.js b/code/web/client/src/sections/factor/index.js
new file mode 100644
index 0000000..3f4f724
--- /dev/null
+++ b/code/web/client/src/sections/factor/index.js
@@ -0,0 +1,15 @@
+'use strict';
+
+import reducers from './reducers';
+import routes from './routes';
+import actions from './actions';
+import { getNavItem } from './nav-item';
+
+export default {
+ key: 'factor',
+ name: '监测因素',
+ reducers: reducers,
+ routes: routes,
+ actions: actions,
+ getNavItem: getNavItem
+};
\ No newline at end of file
diff --git a/code/web/client/src/sections/factor/nav-item.js b/code/web/client/src/sections/factor/nav-item.js
new file mode 100644
index 0000000..8eb5fa8
--- /dev/null
+++ b/code/web/client/src/sections/factor/nav-item.js
@@ -0,0 +1,16 @@
+import React from 'react';
+import { Link } from 'react-router-dom';
+import { Menu } from 'antd';
+import { SettingOutlined } from '@ant-design/icons';
+
+const SubMenu = Menu.SubMenu;
+
+export function getNavItem(user, dispatch) {
+ return (
+ } title={'监测因素'}>
+
+ 监测因素列表
+
+
+ );
+}
\ No newline at end of file
diff --git a/code/web/client/src/sections/factor/reducers/index.js b/code/web/client/src/sections/factor/reducers/index.js
new file mode 100644
index 0000000..7ed1088
--- /dev/null
+++ b/code/web/client/src/sections/factor/reducers/index.js
@@ -0,0 +1,5 @@
+'use strict';
+
+export default {
+
+}
\ No newline at end of file
diff --git a/code/web/client/src/sections/factor/routes.js b/code/web/client/src/sections/factor/routes.js
new file mode 100644
index 0000000..393f9ee
--- /dev/null
+++ b/code/web/client/src/sections/factor/routes.js
@@ -0,0 +1,12 @@
+'use strict';
+import { FactorProfile} from './containers';
+
+export default [{
+ type: 'inner',
+ route: {
+ path: '/factor_profile',
+ key: 'factor',
+ breadcrumb: '监测因素管理',
+ component: FactorProfile
+ }
+}];
\ No newline at end of file
diff --git a/code/web/client/src/sections/factor/style.less b/code/web/client/src/sections/factor/style.less
new file mode 100644
index 0000000..3323452
--- /dev/null
+++ b/code/web/client/src/sections/factor/style.less
@@ -0,0 +1,3 @@
+#example:hover {
+ font-size: larger;
+}
\ No newline at end of file
diff --git a/code/web/client/src/utils/webapi.js b/code/web/client/src/utils/webapi.js
index 9b10f25..d9093ee 100644
--- a/code/web/client/src/utils/webapi.js
+++ b/code/web/client/src/utils/webapi.js
@@ -17,6 +17,9 @@ export const ApiTable = {
delGatewayConfig: 'gateway/{gatewayId}',
getGatewayProtocols: 'v1/deviceProxy/protocols',
+ // 监测因素
+ getFactors: 'v1/searchFactor',
+
getEnterprisesMembers: 'enterprises/{enterpriseId}/members',
};