diff --git a/code/web/client/assets/color.less b/code/web/client/assets/color.less index 5f56f53..0047c87 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: #feffe6;} +mark {background-color: color(~`colorPalette("@{table-header-sort-active-bg}", 2)`);} ::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: #fff1f0;} +.ant-menu-item-danger.ant-menu-item:active {background: color(~`colorPalette("@{alert-info-border-color}", 4)`);} .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: #fff1f0;} +.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-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,31 +1727,31 @@ 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: color(~`colorPalette("@{alert-warning-border-color}", 1)`);border-color: #ffadd2;} +.ant-tag-pink {color: #c41d7f;background: #fff0f6;border-color: #ffadd2;} .ant-tag-pink-inverse {color: #fff;background: #eb2f96;border-color: #eb2f96;} -.ant-tag-magenta {color: #c41d7f;background: color(~`colorPalette("@{alert-warning-border-color}", 1)`);border-color: #ffadd2;} +.ant-tag-magenta {color: #c41d7f;background: #fff0f6;border-color: #ffadd2;} .ant-tag-magenta-inverse {color: #fff;background: #eb2f96;border-color: #eb2f96;} -.ant-tag-red {color: #cf1322;background: #fff1f0;border-color: #ffa39e;} +.ant-tag-red {color: #cf1322;background: color(~`colorPalette("@{alert-info-border-color}", 4)`);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: color(~`colorPalette("@{shadow-color}", 1)`);border-color: #ffd591;} +.ant-tag-orange {color: #d46b08;background: #fff7e6;border-color: #ffd591;} .ant-tag-orange-inverse {color: #fff;background: #fa8c16;border-color: #fa8c16;} -.ant-tag-yellow {color: #d4b106;background: #feffe6;border-color: #fffb8f;} +.ant-tag-yellow {color: #d4b106;background: color(~`colorPalette("@{table-header-sort-active-bg}", 2)`);border-color: #fffb8f;} .ant-tag-yellow-inverse {color: #fff;background: #fadb14;border-color: #fadb14;} -.ant-tag-gold {color: #d48806;background: color(~`colorPalette("@{btn-shadow}", 1)`);border-color: #ffe58f;} +.ant-tag-gold {color: #d48806;background: #fffbe6;border-color: #ffe58f;} .ant-tag-gold-inverse {color: #fff;background: #faad14;border-color: #faad14;} .ant-tag-cyan {color: #08979c;background: #e6fffb;border-color: #87e8de;} .ant-tag-cyan-inverse {color: #fff;background: #13c2c2;border-color: #13c2c2;} -.ant-tag-lime {color: #7cb305;background: color(~`colorPalette("@{dropdown-menu-submenu-disabled-bg}", 1)`);border-color: #eaff8f;} +.ant-tag-lime {color: #7cb305;background: #fcffe6;border-color: #eaff8f;} .ant-tag-lime-inverse {color: #fff;background: #a0d911;border-color: #a0d911;} .ant-tag-green {color: #389e0d;background: #f6ffed;border-color: #b7eb8f;} .ant-tag-green-inverse {color: #fff;background: #52c41a;border-color: #52c41a;} -.ant-tag-blue {color: #096dd9;background: color(~`colorPalette("@{transfer-item-hover-bg}", 1)`);border-color: #91d5ff;} +.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("@{badge-text-color}", 1)`);border-color: #adc6ff;} +.ant-tag-geekblue {color: #1d39c4;background: color(~`colorPalette("@{slider-rail-background-color-hover}", 1)`);border-color: #adc6ff;} .ant-tag-geekblue-inverse {color: #fff;background: #2f54eb;border-color: #2f54eb;} -.ant-tag-purple {color: #531dab;background: color(~`colorPalette("@{table-header-sort-bg}", 2)`);border-color: #d3adf7;} +.ant-tag-purple {color: #531dab;background: color(~`colorPalette("@{shadow-color-inverse}", 1)`);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;} @@ -1988,7 +1988,7 @@ a.ant-typography.ant-typography-disabled:hover, .ant-typography a.ant-typography .ant-upload-list-picture .ant-upload-list-item-error, .ant-upload-list-picture-card .ant-upload-list-item-error {border-color: #ff4d4f;} .ant-upload-list-picture .ant-upload-list-item:hover .ant-upload-list-item-info, .ant-upload-list-picture-card .ant-upload-list-item:hover .ant-upload-list-item-info {background: transparent;} .ant-upload-list-picture .ant-upload-list-item-uploading, .ant-upload-list-picture-card .ant-upload-list-item-uploading {border-style: dashed;} -.ant-upload-list-picture .ant-upload-list-item-error .ant-upload-list-item-thumbnail .anticon svg path[fill='color(~`colorPalette("@{transfer-item-hover-bg}", 1)`)'], .ant-upload-list-picture-card .ant-upload-list-item-error .ant-upload-list-item-thumbnail .anticon svg path[fill='color(~`colorPalette("@{transfer-item-hover-bg}", 1)`)'] {fill: @error-color-deprecated-bg;} +.ant-upload-list-picture .ant-upload-list-item-error .ant-upload-list-item-thumbnail .anticon svg path[fill='#e6f7ff'], .ant-upload-list-picture-card .ant-upload-list-item-error .ant-upload-list-item-thumbnail .anticon svg path[fill='#e6f7ff'] {fill: @error-color-deprecated-bg;} .ant-upload-list-picture .ant-upload-list-item-error .ant-upload-list-item-thumbnail .anticon svg path[fill='#1890ff'], .ant-upload-list-picture-card .ant-upload-list-item-error .ant-upload-list-item-thumbnail .anticon svg path[fill='#1890ff'] {fill: #ff4d4f;} .ant-upload-list-picture-card .ant-upload-list-item-info::before {background-color: rgba(0, 0, 0, 0.5);} .ant-upload-list-picture-card .ant-upload-list-item-actions .anticon-eye, .ant-upload-list-picture-card .ant-upload-list-item-actions .anticon-download, .ant-upload-list-picture-card .ant-upload-list-item-actions .anticon-delete {color: rgba(255, 255, 255, 0.85);} diff --git a/code/web/client/src/sections/gateway/actions/gateway.js b/code/web/client/src/sections/gateway/actions/gateway.js index e38120e..8e67fcc 100644 --- a/code/web/client/src/sections/gateway/actions/gateway.js +++ b/code/web/client/src/sections/gateway/actions/gateway.js @@ -15,6 +15,17 @@ export function list(query) { }) } +export function getProtocols() { + return dispatch => basicAction({ + type: 'get', + dispatch: dispatch, + actionType: 'GET_GATEWAY_PROTOCOLS', + url: ApiTable.getGatewayProtocols, + msg: { error: '获取网关协议类型失败' }, + reducer: { name: 'gatewayProtocols' } + }) +} + export function add(data) { return dispatch => basicAction({ type: 'post', @@ -26,13 +37,13 @@ export function add(data) { }) } -export function edit(data, gatewayId) { +export function edit(data) { return dispatch => basicAction({ - type: 'put', + type: 'post', dispatch: dispatch, data: data, actionType: 'EDIT_GATEWAY_CONFIG', - url: `${ApiTable.editGatewayConfig.replace('{gatewayId}', gatewayId)}`, + url: `${ApiTable.editGatewayConfig}`, msg: { option: '编辑网关配置' } }) } diff --git a/code/web/client/src/sections/gateway/containers/ConfigModal.js b/code/web/client/src/sections/gateway/containers/ConfigModal.js index faec21c..91cc7c3 100644 --- a/code/web/client/src/sections/gateway/containers/ConfigModal.js +++ b/code/web/client/src/sections/gateway/containers/ConfigModal.js @@ -1,13 +1,45 @@ import React, { useEffect, useRef } from 'react'; import { connect } from 'react-redux'; -import { Spin, Button, Modal, Form, Switch } from 'antd'; -import ProForm, { ProFormText, ProFormSelect, ProFormDateTimePicker } from '@ant-design/pro-form'; +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, types, catalogs } = 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 { onOk={() => { formRef.current.validateFields() .then(v => { - dispatch(editData ? gateway.edit(v, editData.id) : gateway.add(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()) @@ -31,55 +70,75 @@ const ConfigModal = (props) => { - + - + + + + + + + )} + > + {protocols.map(item => ( + + ))} + + + + } function mapStateToProps(state) { - const { auth, global, } = state; + const { auth, global } = state; return { user: auth.user, - actions: global.actions + actions: global.actions, }; } diff --git a/code/web/client/src/sections/gateway/containers/Gateway.js b/code/web/client/src/sections/gateway/containers/Gateway.js index 9f8212e..2f3ab09 100644 --- a/code/web/client/src/sections/gateway/containers/Gateway.js +++ b/code/web/client/src/sections/gateway/containers/Gateway.js @@ -1,25 +1,19 @@ -import React, { useState,useEffect,useRef } from 'react'; +import React, { useState, useEffect, useRef } from 'react'; import { connect } from 'react-redux'; -import { Spin,Button, Card, Input } from 'antd'; +import { Spin, Button, Card, Input } from 'antd'; import '../style.less'; import { push } from 'react-router-redux' import ProTable, { TableDropdown } from '@ant-design/pro-table'; - -const GatewayMode = ["tcp", "udp", "mqtt", "http", "dtu"] -const InMode = GatewayMode -const OutMode = GatewayMode -const ProtocolTypes = ["DeviceA", "DeviceB", "DeviceC", "DeviceD"] - - +import { InMode, OutMode, ProtocolTypes } from './models'; +import ConfigModal from './ConfigModal'; const Gateway = (props) => { - const { dispatch, actions, user, loading, gateways } = props + const { dispatch, actions, user, loading, gateways, total } = props const { gateway } = actions; const [configModalVis, setConfigModalVis] = useState(false) const [editData, setEditData] = useState(null) - useEffect(() => { // dispatch(task.getTaskList()) }, []) @@ -97,7 +91,7 @@ const Gateway = (props) => { const res = await dispatch(gateway.list(query)); return { ...res, - total: res.payload.data ? res.payload.data.count : 0 + total: res.payload.data ? res.payload.data.total : 0 } }} options={false} @@ -125,10 +119,12 @@ const Gateway = (props) => { } function mapStateToProps(state) { - const { auth, global } = state; + const { auth, global, gateways } = state; return { user: auth.user, - actions: global.actions + actions: global.actions, + loading: gateways.isRequesting, + gateways: gateways.data?.data ?? [], }; } diff --git a/code/web/client/src/sections/gateway/containers/models.js b/code/web/client/src/sections/gateway/containers/models.js new file mode 100644 index 0000000..e479d43 --- /dev/null +++ b/code/web/client/src/sections/gateway/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/utils/webapi.js b/code/web/client/src/utils/webapi.js index 75a17b7..9b10f25 100644 --- a/code/web/client/src/utils/webapi.js +++ b/code/web/client/src/utils/webapi.js @@ -10,11 +10,12 @@ export const ApiTable = { search: 'v1/search/{wd}', //网关配置 - getGateways: 'gateway/list', - addGatewayConfig: 'gateway', + getGateways: 'v1/deviceProxy/query', + addGatewayConfig: 'v1/deviceProxy/add', + editGatewayConfig: 'v1/deviceProxy/update', getGatewayConfig: 'gateway/{gatewayId}', - editGatewayConfig: 'gateway/{gatewayId}', delGatewayConfig: 'gateway/{gatewayId}', + getGatewayProtocols: 'v1/deviceProxy/protocols', getEnterprisesMembers: 'enterprises/{enterpriseId}/members', }; diff --git a/code/web/package.json b/code/web/package.json index 21112a0..8a18993 100644 --- a/code/web/package.json +++ b/code/web/package.json @@ -6,7 +6,7 @@ "scripts": { "test": "mocha", "start": "cross-env NODE_ENV=development npm run start-params", - "start-params": "npm run color && node server -p 5000 -u http://127.0.0.1:4100", + "start-params": "npm run color && node server -p 5000 -u http://127.0.0.1:4101", "deploy": "export NODE_ENV=production&&npm run color && npm run build && node server", "build-dev": "export NODE_ENV=development&&webpack --config webpack.config.js", "build": "export NODE_ENV=production&&webpack --config webpack.config.prod.js",