Przeglądaj źródła

Merge xyh

Next xyh
XieYongHong 3 lat temu
rodzic
commit
caf5b7e598

+ 4 - 4
config/proxy.ts

@@ -12,11 +12,11 @@ export default {
       // target: 'http://192.168.32.28:8844/',
       // ws: 'ws://192.168.32.28:8844/',
       // 开发环境
-      // target: 'http://120.79.18.123:8844/',
-      // ws: 'ws://120.79.18.123:8844/',
+      target: 'http://120.79.18.123:8844/',
+      ws: 'ws://120.79.18.123:8844/',
       // 测试环境
-      target: 'http://120.77.179.54:8844/',
-      ws: 'ws://120.77.179.54:8844/',
+      // target: 'http://120.77.179.54:8844/',
+      // ws: 'ws://120.77.179.54:8844/',
       // target: 'http://192.168.66.5:8844/',
       // ws: 'ws://192.168.66.5:8844/',
       // ws: 'ws://demo.jetlinks.cn/jetlinks',

Plik diff jest za duży
+ 263 - 1891
src/pages/init-home/components/data/RoleData.ts


+ 1 - 1
src/pages/notice/Template/Detail/doc/DingTalkRebot.tsx

@@ -5,7 +5,7 @@ const DingTalkRebot = () => {
   return (
     <div className="doc">
       <div className="url">
-        钉钉管理后台:
+        钉钉开放平台:
         <a href="https://open-dev.dingtalk.com" target="_blank" rel="noopener noreferrer">
           https://open-dev.dingtalk.com
         </a>

+ 63 - 43
src/pages/rule-engine/DashBoard/index.tsx

@@ -13,6 +13,7 @@ import Echarts from '@/components/DashBoard/echarts';
 import encodeQuery from '@/utils/encodeQuery';
 import useHistory from '@/hooks/route/useHistory';
 import { getMenuPathByCode } from '@/utils/menu';
+import { Empty } from '@/components';
 
 const service = new Service();
 export const state = model<{
@@ -102,7 +103,10 @@ const Dashboard = observer(() => {
       state.today = _data.find((item) => item.group === 'today')?.data.value;
       state.thisMonth = _data.find((item) => item.group === 'thisMonth')?.data.value;
 
-      const fifteenData = _data.filter((item) => item.group === '15day').map((item) => item.data);
+      const fifteenData = _data
+        .filter((item) => item.group === '15day')
+        .map((item) => item.data)
+        .sort((a, b) => b.timestamp - a.timestamp);
       state.fifteenOptions = {
         xAxis: {
           type: 'category',
@@ -126,7 +130,7 @@ const Dashboard = observer(() => {
         series: [
           {
             name: '告警数',
-            data: fifteenData.sort((a, b) => b.timestamp - a.timestamp).map((item) => item.value),
+            data: fifteenData.map((item) => item.value),
             type: 'bar',
             itemStyle: {
               color: '#2F54EB',
@@ -239,6 +243,16 @@ const Dashboard = observer(() => {
     // 请求数据
     const resp = await service.dashboard([chartData, order]);
 
+    let tip = '其它';
+
+    if (params.targetType === 'device') {
+      tip = '设备';
+    } else if (params.targetType === 'product') {
+      tip = '产品';
+    } else if (params.targetType === 'org') {
+      tip = '部门';
+    }
+
     if (resp?.status === 200) {
       const xData: string[] = [];
       const sData: number[] = [];
@@ -278,7 +292,7 @@ const Dashboard = observer(() => {
         ],
         series: [
           {
-            name: 'Direct',
+            name: tip,
             type: 'bar',
             barWidth: '30%',
             itemStyle: {
@@ -327,48 +341,54 @@ const Dashboard = observer(() => {
                 <div className={'content-left-title'}>最新告警</div>
                 <div className={'new-alarm-items'}>
                   <ul>
-                    {state.alarmList.slice(0, 3).map((item) => (
-                      <li key={item.id}>
-                        <div className={'new-alarm-item'}>
-                          <div className={'new-alarm-item-time'}>
-                            <img src={require('/public/images/alarm/bashboard.png')} alt="" />
-                            {moment(item.alarmTime).format('YYYY-MM-DD HH:mm:ss')}
-                          </div>
-                          <div className={'new-alarm-item-content ellipsis'}>
-                            <Tooltip title={item.alarmName} placement="topLeft">
-                              <a
-                                onClick={() => {
-                                  console.log(item);
-                                  const url = getMenuPathByCode('rule-engine/Alarm/Log');
-                                  history.push(`${url}/detail/${item.id}`, {
-                                    param: {
-                                      detail: true,
-                                    },
-                                  });
-                                }}
-                              >
-                                {item.alarmName}
-                              </a>
-                            </Tooltip>
-                          </div>
-                          <div className={'new-alarm-item-state'}>
-                            <Badge
-                              status={item.state?.value === 'warning' ? 'error' : 'default'}
-                              text={
-                                <span
-                                  className={item.state?.value === 'warning' ? 'error' : 'default'}
+                    {state.alarmList.length ? (
+                      state.alarmList.slice(0, 3).map((item) => (
+                        <li key={item.id}>
+                          <div className={'new-alarm-item'}>
+                            <div className={'new-alarm-item-time'}>
+                              <img src={require('/public/images/alarm/bashboard.png')} alt="" />
+                              {moment(item.alarmTime).format('YYYY-MM-DD HH:mm:ss')}
+                            </div>
+                            <div className={'new-alarm-item-content ellipsis'}>
+                              <Tooltip title={item.alarmName} placement="topLeft">
+                                <a
+                                  onClick={() => {
+                                    console.log(item);
+                                    const url = getMenuPathByCode('rule-engine/Alarm/Log');
+                                    history.push(`${url}/detail/${item.id}`, {
+                                      param: {
+                                        detail: true,
+                                      },
+                                    });
+                                  }}
                                 >
-                                  {item.state?.text}
-                                </span>
-                              }
-                            />
-                          </div>
-                          <div className={`new-alarm-item-level level-${item.level}`}>
-                            {item.levelName}
+                                  {item.alarmName}
+                                </a>
+                              </Tooltip>
+                            </div>
+                            <div className={'new-alarm-item-state'}>
+                              <Badge
+                                status={item.state?.value === 'warning' ? 'error' : 'default'}
+                                text={
+                                  <span
+                                    className={
+                                      item.state?.value === 'warning' ? 'error' : 'default'
+                                    }
+                                  >
+                                    {item.state?.text}
+                                  </span>
+                                }
+                              />
+                            </div>
+                            <div className={`new-alarm-item-level level-${item.level}`}>
+                              {item.levelName}
+                            </div>
                           </div>
-                        </div>
-                      </li>
-                    ))}
+                        </li>
+                      ))
+                    ) : (
+                      <Empty />
+                    )}
                   </ul>
                 </div>
               </div>

+ 17 - 1
src/pages/rule-engine/Scene/Save/action/action.tsx

@@ -45,6 +45,7 @@ export default observer((props: ActionProps) => {
   const [deviceMessageType, setDeviceMessageType] = useState('WRITE_PROPERTY');
   const [properties, setProperties] = useState([]); // 物模型-属性
   const [functionList, setFunctionList] = useState([]); // 物模型-功能
+  const [propertiesId, setPropertiesId] = useState<string | undefined>(''); // 物模型-属性ID,用于串行
 
   const [productId, setProductId] = useState('');
 
@@ -84,6 +85,12 @@ export default observer((props: ActionProps) => {
             { column: 'type', value: data.notify.notifyType },
             { column: 'provider', value: notifierItem.provider },
           ],
+          sorts: [
+            {
+              name: 'createTime',
+              order: 'desc',
+            },
+          ],
         });
       }
     }
@@ -103,6 +110,12 @@ export default observer((props: ActionProps) => {
     ) {
       queryMessageConfigs({
         terms: [{ column: 'type$IN', value: props.actionItemData.notify.notifyType }],
+        sorts: [
+          {
+            name: 'createTime',
+            order: 'desc',
+          },
+        ],
       }).then(async (resp) => {
         if (props.actionItemData.notify.notifierId) {
           await handleNotifier(resp, props.actionItemData);
@@ -365,6 +378,7 @@ export default observer((props: ActionProps) => {
                   parallel={props.parallel}
                   productId={productId}
                   isEdit={props.isEdit}
+                  propertiesChange={setPropertiesId}
                 />
               </Form.Item>
             </Col>
@@ -377,6 +391,7 @@ export default observer((props: ActionProps) => {
                 form={props.form}
                 data={props.actionItemData.terms}
                 productId={productId}
+                propertiesId={propertiesId}
               />
             </Row>
           )}
@@ -392,7 +407,7 @@ export default observer((props: ActionProps) => {
                 name={[name, 'device', 'message', 'properties']}
                 rules={[{ required: true, message: '请选择属性' }]}
               >
-                <ReadProperty properties={properties} />
+                <ReadProperty properties={properties} propertiesChange={setPropertiesId} />
               </Form.Item>
             </Col>
             {parallelNode}
@@ -404,6 +419,7 @@ export default observer((props: ActionProps) => {
                 form={props.form}
                 data={props.actionItemData.terms}
                 productId={productId}
+                propertiesId={propertiesId}
               />
             </Row>
           )}

+ 17 - 6
src/pages/rule-engine/Scene/Save/action/device/ConditionalFiltering.tsx

@@ -9,6 +9,7 @@ interface ConditionalFilteringProps {
   form: FormInstance;
   data?: any;
   productId: string;
+  propertiesId?: string;
 }
 
 export default (props: ConditionalFilteringProps) => {
@@ -23,7 +24,7 @@ export default (props: ConditionalFilteringProps) => {
       case 'float':
       case 'double':
       case 'long':
-        return <InputNumber />;
+        return <InputNumber placeholder={'请输入过滤条件值'} />;
       case 'date':
         return (
           <>
@@ -36,6 +37,7 @@ export default (props: ConditionalFilteringProps) => {
       case 'boolean':
         return (
           <Select
+            placeholder={'请选择过滤条件值'}
             options={[
               { label: '是', value: 'true' },
               { label: '否', value: 'false' },
@@ -43,7 +45,7 @@ export default (props: ConditionalFilteringProps) => {
           />
         );
       default:
-        return <Input />;
+        return <Input placeholder={'请输入过滤条件值'} />;
     }
   };
 
@@ -108,13 +110,22 @@ export default (props: ConditionalFilteringProps) => {
   };
 
   useEffect(() => {
-    if (props.data && props.data[0] && props.data[0].column && builtInList && builtInList.length) {
-      getBuiltItemById(props.data[0].column);
+    if (props.data && props.data[0] && props.data[0].column) {
+      if (builtInList && builtInList.length) {
+        getBuiltItemById(props.data[0].column);
+      }
     }
   }, [props.data, builtInList]);
 
   useEffect(() => {
-    if (props.productId) {
+    if (props.data && props.data[0] && props.data[0].column) {
+      setSource(props.data[0].value.source);
+    }
+    getBuiltInParamsData();
+  }, []);
+
+  useEffect(() => {
+    if (props.productId || props.propertiesId) {
       getBuiltInParamsData();
       const actions = props.form.getFieldValue('actions');
       if (actions?.[props.name].terms?.[0]) {
@@ -129,7 +140,7 @@ export default (props: ConditionalFilteringProps) => {
       }
       setSource('fixed');
     }
-  }, [props.productId]);
+  }, [props.productId, props.propertiesId]);
 
   return (
     <>

+ 2 - 0
src/pages/rule-engine/Scene/Save/action/device/WriteProperty/index.tsx

@@ -13,6 +13,7 @@ interface WritePropertyProps {
   form: FormInstance;
   value?: any;
   onChange?: (value?: any) => void;
+  propertiesChange?: (value?: string) => void;
   parallel?: boolean;
   name: number;
   trigger?: any;
@@ -56,6 +57,7 @@ export default (props: WritePropertyProps) => {
 
   const onChange = (key?: string, value?: any, _source: string = 'fixed') => {
     if (props.onChange) {
+      props.propertiesChange?.(key);
       props.onChange({
         [key || 0]: {
           value: value,

+ 11 - 1
src/pages/rule-engine/Scene/Save/action/device/deviceModal.tsx

@@ -195,7 +195,17 @@ export default (props: DeviceModelProps) => {
                 取消选择
               </Button>
             )}
-            request={(params) => queryDevice(params)}
+            request={(params) =>
+              queryDevice({
+                ...params,
+                sorts: [
+                  {
+                    name: 'createTime',
+                    order: 'desc',
+                  },
+                ],
+              })
+            }
             params={searchParam}
           ></ProTable>
         </Modal>

+ 6 - 1
src/pages/rule-engine/Scene/Save/action/device/index.tsx

@@ -6,6 +6,7 @@ import Device from './deviceModal';
 import TagModal from './tagModal';
 import { ItemGroup } from '@/pages/rule-engine/Scene/Save/components';
 import RelationSelect from './relationSelect';
+import encodeQuery from '@/utils/encodeQuery';
 
 interface DeviceProps {
   name: number;
@@ -67,7 +68,11 @@ export default (props: DeviceProps) => {
   };
 
   const getProducts = async () => {
-    const resp = await getProductList({ paging: false });
+    const params = encodeQuery({
+      paging: false,
+      sorts: { createTime: 'desc' },
+    });
+    const resp = await getProductList(params);
     if (resp && resp.status === 200) {
       setProductList(resp.result);
       if (props.value && props.value.productId) {

+ 2 - 0
src/pages/rule-engine/Scene/Save/action/device/readProperty.tsx

@@ -4,6 +4,7 @@ interface ReadPropertyProps {
   properties: any[];
   value?: any;
   onChange?: (value?: any) => void;
+  propertiesChange?: (value?: string) => void;
   id?: string;
 }
 
@@ -23,6 +24,7 @@ export default (props: ReadPropertyProps) => {
       onSelect={(key: any) => {
         if (props.onChange) {
           props.onChange([key]);
+          props.propertiesChange?.(key);
         }
       }}
       placeholder={'请选择属性'}

Plik diff jest za duży
+ 202 - 120
src/pages/rule-engine/Scene/Save/components/TimingTrigger/refactor.tsx


+ 9 - 11
src/pages/rule-engine/Scene/Save/trigger/index.tsx

@@ -1,4 +1,4 @@
-import { useCallback, useEffect, useState } from 'react';
+import { useCallback, useEffect, useRef, useState } from 'react';
 import type { FormInstance } from 'antd';
 import { Col, Form, Row, Select } from 'antd';
 import { ItemGroup, TimingTrigger } from '@/pages/rule-engine/Scene/Save/components';
@@ -33,7 +33,7 @@ enum OperatorEnum {
 export default observer((props: TriggerProps) => {
   const [productList, setProductList] = useState<any[]>([]);
   const [productId, setProductId] = useState('');
-  const [selector, setSelector] = useState('fixed');
+  const [selector, setSelector] = useState(props.value?.device?.selector || 'fixed');
 
   const [operatorOptions, setOperatorOptions] = useState<any[] | undefined>(undefined);
 
@@ -43,6 +43,8 @@ export default observer((props: TriggerProps) => {
 
   const [functionItem, setFunctionItem] = useState<any[]>([]); // 单个功能-属性列表
 
+  const isInitRef = useRef<boolean>(true);
+
   const handleMetadata = (metadata?: string) => {
     try {
       const metadataObj = JSON.parse(metadata || '{}');
@@ -125,15 +127,11 @@ export default observer((props: TriggerProps) => {
   }, []);
 
   useEffect(() => {
-    const triggerData = props.value;
-    if (triggerData && triggerData.device) {
-      const _device = triggerData.device;
-
-      if (_device.selector) {
-        setSelector(_device.selector);
-      }
+    if (props.value?.device?.selector && isInitRef.current) {
+      isInitRef.current = false;
+      setSelector(props.value?.device?.selector);
     }
-  }, [props.value]);
+  }, [props.value?.device?.selector]);
 
   return (
     <div className={classNames(props.className)}>
@@ -154,7 +152,6 @@ export default observer((props: TriggerProps) => {
                 props.form?.resetFields([['trigger', 'device', 'selector']]);
                 props.form?.resetFields([['trigger', 'device', 'selectorValues']]);
                 props.form?.resetFields([['trigger', 'device', 'operation']]);
-                productIdChange(key, node?.metadata);
                 setSelector('fixed');
                 props.form?.setFieldsValue({
                   trigger: {
@@ -166,6 +163,7 @@ export default observer((props: TriggerProps) => {
                     productId: key,
                   },
                 });
+                productIdChange(key, node?.metadata);
               }}
               fieldNames={{ label: 'name', value: 'id' }}
               filterOption={(input: string, option: any) =>

+ 17 - 1
src/pages/rule-engine/Scene/TriggerTerm/index.tsx

@@ -175,6 +175,16 @@ const TriggerTerm = (props: Props, ref: any) => {
                   date: DatePicker,
                   boolean: Select,
                 };
+                let tip: string | undefined = '';
+
+                switch (valueType) {
+                  case 'boolean':
+                    tip = '请选择过滤条件值';
+                    break;
+                  default:
+                    tip = '请输入过滤条件值';
+                    break;
+                }
 
                 form1.setFieldState(value, (state) => {
                   state.componentType = valueTypeMap[valueType];
@@ -182,6 +192,7 @@ const TriggerTerm = (props: Props, ref: any) => {
                     style: {
                       width: '100%',
                     },
+                    placeholder: tip,
                   };
                   if (valueType === 'date') {
                     state.componentProps = {
@@ -199,6 +210,11 @@ const TriggerTerm = (props: Props, ref: any) => {
                   if (valueType === 'date') {
                     state.componentProps = {
                       showTime: true,
+                      placeholder: tip,
+                    };
+                  } else {
+                    state.componentProps = {
+                      placeholder: tip,
                     };
                   }
                 });
@@ -211,7 +227,7 @@ const TriggerTerm = (props: Props, ref: any) => {
                   state.dataSource = target?.metrics
                     ?.filter((i: { range: boolean }) => i.range === tag)
                     .map((item: any) => ({
-                      label: item.name,
+                      label: item.name + `(${item.value})`,
                       value: item.id,
                     }));
                   if (modified) {

+ 54 - 27
src/pages/system/Menu/Setting/tree.tsx

@@ -2,10 +2,11 @@ import { Input, Tree } from 'antd';
 import { SearchOutlined } from '@ant-design/icons';
 import DragItem from '@/pages/system/Menu/Setting/dragItem';
 import { useDrop } from 'react-dnd';
-import { useEffect, useState } from 'react';
+import { useEffect, useRef, useState } from 'react';
 import type { TreeProps } from 'antd';
 import { cloneDeep, debounce } from 'lodash';
 import './DragItem.less';
+import { Empty } from '@/components';
 
 interface TreeBodyProps {
   treeData: any[];
@@ -38,9 +39,11 @@ export default (props: TreeBodyProps) => {
   const [searchKeys, setSearchKeys] = useState<(string | number)[]>([]);
   const [expandedKeys, setExpandedKeys] = useState<(string | number)[]>([]);
   const [autoExpandParent, setAutoExpandParent] = useState(true);
+  const DefaultTreeRef = useRef<any[]>(props.treeData);
 
   useEffect(() => {
     setNewData(cloneDeep(props.treeData));
+    DefaultTreeRef.current = cloneDeep(props.treeData);
   }, [props.treeData]);
 
   useEffect(() => {
@@ -125,6 +128,18 @@ export default (props: TreeBodyProps) => {
     return parentKey;
   };
 
+  const findItem = (data: any[], keys: string[]): any[] => {
+    return data.filter((item) => {
+      if (item.children) {
+        item.children = findItem(item.children, keys);
+      }
+      if (keys.includes(item.code) || !!item.children?.length) {
+        return true;
+      }
+      return false;
+    });
+  };
+
   const findAllItem = (data: any[], value: string): string[] => {
     return data.reduce((pre, next) => {
       const childrenKeys = next.children ? findAllItem(next.children, value) : [];
@@ -142,10 +157,14 @@ export default (props: TreeBodyProps) => {
       const newExpandedKeys = newKeys.map((key) => {
         return getParentKey(key, props.treeData);
       });
+      const expandKeysSet = new Set([...newExpandedKeys, ...newKeys]);
+      const searchData = findItem(cloneDeep(DefaultTreeRef.current), [...expandKeysSet.keys()]);
+      setNewData(cloneDeep(searchData));
       setSearchKeys(newKeys);
-      setExpandedKeys(newExpandedKeys);
+      setExpandedKeys([...expandKeysSet.keys()]);
     } else {
       setSearchKeys([]);
+      setNewData(cloneDeep(DefaultTreeRef.current));
     }
     setAutoExpandParent(true);
   };
@@ -162,34 +181,42 @@ export default (props: TreeBodyProps) => {
       </div>
       {props.droppableId === 'source' ? (
         <div className={'tree-body'}>
-          <Tree
-            expandedKeys={expandedKeys}
-            onExpand={(_expandedKeys) => {
-              setExpandedKeys(_expandedKeys);
-              setAutoExpandParent(false);
-            }}
-            autoExpandParent={autoExpandParent}
-          >
-            {createTreeNode(newData, props.droppableId)}
-          </Tree>
+          {newData.length ? (
+            <Tree
+              expandedKeys={expandedKeys}
+              onExpand={(_expandedKeys) => {
+                setExpandedKeys(_expandedKeys);
+                setAutoExpandParent(false);
+              }}
+              autoExpandParent={autoExpandParent}
+            >
+              {createTreeNode(newData, props.droppableId)}
+            </Tree>
+          ) : (
+            <Empty />
+          )}
         </div>
       ) : (
         <div className={'tree-body'} ref={drop}>
-          <Tree
-            expandedKeys={expandedKeys}
-            onExpand={(_expandedKeys) => {
-              setExpandedKeys(_expandedKeys);
-              setAutoExpandParent(false);
-            }}
-            autoExpandParent={autoExpandParent}
-            draggable={{
-              icon: false,
-            }}
-            onDrop={props.onTreeDrop}
-            className="menu-setting-drag-tree"
-          >
-            {createTreeNode(props.treeData, props.droppableId)}
-          </Tree>
+          {newData.length ? (
+            <Tree
+              expandedKeys={expandedKeys}
+              onExpand={(_expandedKeys) => {
+                setExpandedKeys(_expandedKeys);
+                setAutoExpandParent(false);
+              }}
+              autoExpandParent={autoExpandParent}
+              draggable={{
+                icon: false,
+              }}
+              onDrop={props.onTreeDrop}
+              className="menu-setting-drag-tree"
+            >
+              {createTreeNode(newData, props.droppableId)}
+            </Tree>
+          ) : (
+            <Empty />
+          )}
         </div>
       )}
     </div>