فهرست منبع

fix: merge next

Wzyyy98 3 سال پیش
والد
کامیت
c78e8cc3bb

+ 5 - 1
src/components/FIndicators/index.tsx

@@ -86,7 +86,11 @@ const FIndicators = (props: Props) => {
           <DatePicker1
             showTime
             allowClear={false}
-            value={value?.value ? moment(value.value[0], 'YYYY-MM-DD HH:mm:ss') : ''}
+            value={
+              value?.value && value.value?.[0]
+                ? moment(value.value[0], 'YYYY-MM-DD HH:mm:ss')
+                : undefined
+            }
             onChange={(_: any, date: string) => {
               onChange({
                 ...value,

+ 1 - 1
src/components/Metadata/EditTable/index.tsx

@@ -155,7 +155,7 @@ Editable.Popover = observer((props) => {
   if ((field.title === '配置参数' || field.title === '指标数据') && !props.title) {
     const filterKeys = ['config', 'edit'];
     const path = field.path.segments.filter((key: any) => !filterKeys.includes(key));
-    console.log('EditTable', path, field.form.values);
+    // console.log('EditTable', path, field.form.values);
     const value = get(field.form.values, path)?.name;
     title = value || '配置参数';
   }

+ 2 - 1
src/pages/account/NotificationRecord/detail/index.tsx

@@ -62,8 +62,9 @@ const Detail = (props: Props) => {
           {data?.description || ''}
         </Descriptions.Item>
         <Descriptions.Item label="告警流水" span={2}>
-          <div style={{ maxHeight: 200, overflowY: 'auto' }}>
+          <div style={{ maxHeight: 400, overflowY: 'auto' }}>
             <ReactJson
+              enableClipboard={false}
               displayObjectSize={false}
               displayDataTypes={false}
               name={false}

+ 6 - 2
src/pages/device/Category/Save/index.tsx

@@ -12,7 +12,7 @@ import {
   Switch,
   Upload,
 } from '@formily/antd';
-import React from 'react';
+import React, { useState } from 'react';
 import { createForm } from '@formily/core';
 import { createSchemaField } from '@formily/react';
 import FUpload from '@/components/Upload';
@@ -33,7 +33,7 @@ interface Props {
 
 const Save = (props: Props) => {
   const intl = useIntl();
-
+  const [loading, setLoading] = useState(false);
   const form = createForm({
     validateFirst: true,
     initialValues: props.data,
@@ -62,6 +62,7 @@ const Save = (props: Props) => {
   });
 
   const save = async () => {
+    setLoading(true);
     const value: CategoryItem = await form.submit();
     if (!!state.parentId) {
       value.parentId = state.parentId;
@@ -71,11 +72,13 @@ const Save = (props: Props) => {
       : ((await service.save(value as any)) as Response<CategoryItem>);
     if (resp.status === 200) {
       onlyMessage('操作成功');
+      setLoading(false);
       if (props.reload) {
         props.reload();
       }
     } else {
       onlyMessage('操作失败', 'error');
+      setLoading(false);
     }
     props.close();
   };
@@ -164,6 +167,7 @@ const Save = (props: Props) => {
       visible={props.visible}
       onCancel={() => props.close()}
       onOk={save}
+      confirmLoading={loading}
     >
       <Form layout={'vertical'} form={form}>
         <SchemaField schema={schema} />

+ 3 - 3
src/pages/device/Instance/Detail/Functions/AdvancedMode.tsx

@@ -3,11 +3,11 @@ import { useCallback, useEffect, useRef, useState } from 'react';
 import { Button, Input } from 'antd';
 import { useIntl } from '@@/plugin-locale/localeExports';
 import { InstanceModel, service } from '@/pages/device/Instance';
-import MonacoEditor from 'react-monaco-editor';
 import { isObject } from 'lodash';
 
 import './index.less';
 import { MetaDataJsonHandle } from '@/components/FormItems/MetadataJsonInput';
+import { JMonacoEditor } from '@/components/FMonacoEditor';
 
 type FunctionProps = {
   data: FunctionMetadata;
@@ -94,13 +94,13 @@ export default (props: FunctionProps) => {
     <div className="device-function-content">
       <div className="left">
         <div style={{ marginBottom: 12 }}>
-          <MonacoEditor
+          <JMonacoEditor
             width={'100%'}
             height={400}
             theme="vs-dark"
             language={'json'}
             value={value}
-            onChange={(newValue) => {
+            onChange={(newValue: any) => {
               setValue(newValue);
             }}
             editorDidMount={editorDidMountHandle}

+ 3 - 2
src/pages/device/Instance/Detail/MetadataLog/Property/index.tsx

@@ -450,8 +450,9 @@ const PropertyLog = (props: Props) => {
           activeKey={tab}
           onChange={(key: string) => {
             setTab(key);
-            if (key === 'charts' && !!data.valueType?.type) {
-              if (list.includes(data.valueType?.type)) {
+            if (key === 'charts') {
+              if (!!data.valueType?.type && list.includes(data.valueType?.type)) {
+                setCycle('*');
                 queryChartsList(start, end);
               } else {
                 setCycle('1m');

+ 15 - 0
src/pages/device/Instance/Detail/Running/Property/Indicators.less

@@ -0,0 +1,15 @@
+.indicators {
+  :global {
+    .ant-formily-array-items-item {
+      height: 80px;
+    }
+  }
+  .indicators-asterisk {
+    :global {
+      .ant-formily-item-asterisk {
+        //display: none;
+        color: white;
+      }
+    }
+  }
+}

+ 37 - 21
src/pages/device/Instance/Detail/Running/Property/Indicators.tsx

@@ -16,7 +16,7 @@ import type { PropertyMetadata } from '@/pages/device/Product/typings';
 import { useEffect, useState } from 'react';
 import { InstanceModel, service } from '@/pages/device/Instance';
 import { onlyMessage } from '@/utils/util';
-
+import styles from './Indicators.less';
 interface Props {
   data: Partial<PropertyMetadata>;
   onCancel: () => void;
@@ -101,45 +101,45 @@ const Indicators = (props: Props) => {
             },
             space: {
               type: 'void',
-              title: '指标值',
               'x-decorator': 'FormItem',
               'x-component': 'FormGrid',
-              'x-decorator-props': {
-                labelAlign: 'left',
-                layout: 'vertical',
-              },
               'x-component-props': {
                 maxColumns: 12,
                 minColumns: 12,
               },
-              'x-reactions': [
-                {
-                  dependencies: ['.name'],
-                  fulfill: {
-                    state: {
-                      title: '{{$deps[0]}}',
-                    },
-                  },
-                },
-              ],
               properties: {
                 'value[0]': {
                   'x-decorator': 'FormItem',
+                  title: '指标值',
                   'x-component': componentMap[data.valueType?.type || ''] || 'Input',
                   'x-reactions': [
                     {
-                      dependencies: ['..range', data.valueType?.type],
+                      dependencies: ['..range', data.valueType?.type, '..name'],
                       fulfill: {
                         state: {
                           decoratorProps: {
-                            gridSpan: '{{!!$deps[0]?5:$deps[1]==="boolean"?12:10}}',
+                            gridSpan: '{{!!$deps[0]?6:12}}',
                           },
+                          title: '{{$deps[2]}}',
                         },
                       },
                     },
                   ],
+                  required: true,
+                  'x-validator': [
+                    {
+                      required: true,
+                      message: `请${
+                        ['date', 'boolean'].includes(data?.valueType?.type as string)
+                          ? '选择'
+                          : '输入'
+                      }指标值`,
+                    },
+                  ],
                   'x-decorator-props': {
-                    gridSpan: 5,
+                    gridSpan: 6,
+                    labelAlign: 'left',
+                    layout: 'vertical',
                   },
                 },
                 'value[1]': {
@@ -156,8 +156,24 @@ const Indicators = (props: Props) => {
                       },
                     },
                   ],
+                  required: true,
+                  'x-validator': [
+                    {
+                      required: true,
+                      message: `请${
+                        ['date', 'boolean'].includes(data?.valueType?.type as string)
+                          ? '选择'
+                          : '输入'
+                      }指标值`,
+                    },
+                  ],
                   'x-decorator-props': {
-                    gridSpan: 5,
+                    gridSpan: 6,
+                    style: {
+                      marginTop: 30,
+                      color: 'white',
+                    },
+                    className: styles['indicators-asterisk'],
                   },
                 },
                 range: {
@@ -243,7 +259,7 @@ const Indicators = (props: Props) => {
       >
         场景联动页面可引用指标配置触发条件
       </div>
-      <div style={{ marginTop: '30px' }}>
+      <div style={{ marginTop: '30px' }} className={styles['indicators']}>
         <Form form={form} layout="vertical">
           <SchemaField schema={schema} />
         </Form>

+ 20 - 13
src/pages/device/Instance/index.tsx

@@ -470,6 +470,11 @@ const Instance = () => {
     return url.toString();
   };
 
+  const unSelect = () => {
+    setBindKeys([]);
+    InstanceModel.selectedRows.clear();
+  };
+
   const menu = (
     <Menu>
       <Menu.Item key="1">
@@ -547,19 +552,20 @@ const Instance = () => {
             popConfirm={{
               title: '已启用的设备无法删除,确认删除选中的禁用状态设备?',
               onConfirm: () => {
-                const array: any = [];
-                InstanceModel.selectedRows.forEach((value, key) => {
-                  if (value !== 'notActive') {
-                    InstanceModel.selectedRows.delete(key);
-                    array.push(key);
-                  }
-                });
+                // const array: any = [];
+                // InstanceModel.selectedRows.forEach((value, key) => {
+                //   if (value !== 'notActive') {
+                //     InstanceModel.selectedRows.delete(key);
+                //     array.push(key);
+                //   }
+                // });
                 if (!InstanceModel.selectedRows.size) return;
                 service.batchDeleteDevice([...InstanceModel.selectedRows.keys()]).then((resp) => {
                   if (resp.status === 200) {
                     onlyMessage('操作成功');
                     actionRef.current?.reset?.();
-                    setBindKeys(array);
+                    // setBindKeys(array);
+                    unSelect();
                   }
                 });
               },
@@ -581,8 +587,7 @@ const Instance = () => {
                 service.batchDeployDevice(bindKeys).then((resp) => {
                   if (resp.status === 200) {
                     onlyMessage('操作成功');
-                    setBindKeys([]);
-                    InstanceModel.selectedRows.clear();
+                    unSelect();
                     actionRef.current?.reset?.();
                   }
                 });
@@ -606,8 +611,7 @@ const Instance = () => {
                 service.batchUndeployDevice(bindKeys).then((resp) => {
                   if (resp.status === 200) {
                     onlyMessage('操作成功');
-                    setBindKeys([]);
-                    InstanceModel.selectedRows.clear();
+                    unSelect();
                     actionRef.current?.reset?.();
                   }
                 });
@@ -726,7 +730,7 @@ const Instance = () => {
           return (
             <a
               onClick={() => {
-                setBindKeys([]);
+                unSelect();
               }}
             >
               取消选择
@@ -781,6 +785,9 @@ const Instance = () => {
             <Button>批量操作</Button>
           </Dropdown>,
         ]}
+        modelChange={() => {
+          unSelect();
+        }}
         cardRender={(record) => (
           <DeviceCard
             {...record}

+ 17 - 0
src/pages/device/components/Metadata/Base/Edit/index.tsx

@@ -760,6 +760,23 @@ const Edit = observer((props: Props) => {
             'x-decorator-props': {
               tooltip: '场景联动页面可引用指标配置作为触发条件',
             },
+            'x-validator': [
+              {
+                triggerType: 'onBlur',
+                validator: (value: any[]) => {
+                  return new Promise((resolve) => {
+                    const flag = value.every((item) => {
+                      return item.id && item.name && item.value;
+                    });
+                    if (flag) {
+                      resolve('');
+                    } else {
+                      resolve('请输入指标配置');
+                    }
+                  });
+                },
+              },
+            ],
             // 'x-visible': props.type === 'product',
             items: {
               type: 'object',

+ 4 - 9
src/pages/device/components/Metadata/Import/index.tsx

@@ -303,17 +303,12 @@ const Import = (props: Props) => {
       props.close();
     } else {
       try {
+        const _object = JSON.parse(data[props?.type === 'device' ? 'import' : data?.type] || '{}');
         const params = {
           id: param.id,
-          metadata: JSON.stringify(
-            operateLimits(
-              JSON.parse(data[props?.type === 'device' ? 'import' : data?.type] || '{}'),
-            ),
-          ),
+          metadata: JSON.stringify(operateLimits(_object as DeviceMetadata)),
         };
-        const paramsDevice = JSON.stringify(
-          operateLimits(JSON.parse(data[props?.type === 'device' ? 'import' : data?.type] || '{}')),
-        );
+        const paramsDevice = JSON.stringify(operateLimits(_object as DeviceMetadata));
         let resp: any = undefined;
         if (props?.type === 'device') {
           resp = await deviceService.saveMetadata(param.id, paramsDevice);
@@ -334,7 +329,7 @@ const Import = (props: Props) => {
         Store.set(SystemConst.GET_METADATA, true);
         Store.set(SystemConst.REFRESH_METADATA_TABLE, true);
         props.close();
-      } catch (err) {
+      } catch (e) {
         onlyMessage('请上传正确的json格式文件', 'error');
       }
     }

+ 2 - 2
src/pages/link/DashBoard/index.tsx

@@ -312,7 +312,7 @@ export default () => {
         left: 30,
         right: 0,
         top: 10,
-        bottom: 10,
+        bottom: 65,
       },
       dataZoom: [
         {
@@ -373,7 +373,7 @@ export default () => {
         left: 30,
         right: 0,
         top: 10,
-        bottom: 10,
+        bottom: 65,
       },
       dataZoom: [
         {

+ 2 - 1
src/pages/rule-engine/Alarm/Log/Detail/Info.tsx

@@ -65,8 +65,9 @@ const Info = (props: Props) => {
           </Tooltip>
         </Descriptions.Item>
         <Descriptions.Item label="告警流水" span={2}>
-          <div style={{ maxHeight: 200, overflowY: 'auto' }}>
+          <div style={{ maxHeight: 500, overflowY: 'auto' }}>
             <ReactJson
+              enableClipboard={false}
               displayObjectSize={false}
               displayDataTypes={false}
               name={false}

+ 2 - 2
src/pages/rule-engine/Scene/Save/action/ListItem/Item.tsx

@@ -381,7 +381,7 @@ export default (props: ItemProps) => {
           </div>
         </Popconfirm>
       </div>
-      {!props.isLast && (
+      {!props.isLast && props.type === 'serial' ? (
         <div
           className={classNames('actions-item-filter-warp', {
             'filter-border': !!thenTerms?.length,
@@ -522,7 +522,7 @@ export default (props: ItemProps) => {
             )}
           </div>
         </div>
-      )}
+      ) : null}
       {visible && (
         <Modal
           name={props.name}

+ 11 - 7
src/pages/rule-engine/Scene/Save/action/index.tsx

@@ -33,7 +33,10 @@ export default (props: ActionsProps) => {
     const serialArr = props.thenOptions.filter((item) => !item.parallel);
     setParallelArray(parallelArr);
     setSerialArray(serialArr);
-    if (!lock && parallelArr.length && !serialArr.length) {
+    const isSerialActions = serialArr.some((item) => {
+      return !!item.actions.length;
+    });
+    if (!lock && parallelArr.length && (!serialArr.length || !isSerialActions)) {
       setActiveKey(['2']);
       setLock(true);
     }
@@ -140,17 +143,18 @@ export default (props: ActionsProps) => {
                 parallel={true}
                 actions={parallelArray.length ? parallelArray[0].actions : []}
                 onAdd={(actionItem) => {
-                  if (parallelArray.length) {
-                    const indexOf = parallelArray[0].actions?.findIndex(
+                  const newParallelArray = [...parallelArray];
+                  if (newParallelArray.length) {
+                    const indexOf = newParallelArray[0].actions?.findIndex(
                       (aItem) => aItem.key === actionItem.key,
                     );
                     if (indexOf !== -1) {
-                      parallelArray[0].actions.splice(indexOf, 1, actionItem);
+                      newParallelArray[0].actions.splice(indexOf, 1, actionItem);
                     } else {
-                      parallelArray[0].actions.push(actionItem);
+                      newParallelArray[0].actions.push(actionItem);
                     }
-                    setParallelArray([...parallelArray]);
-                    props.onUpdate(parallelArray[0], true);
+                    setParallelArray([...newParallelArray]);
+                    props.onUpdate(newParallelArray[0], true);
                   } else {
                     actionItem.key = randomString();
                     props.onAdd({

+ 5 - 1
src/pages/rule-engine/Scene/Save/save.tsx

@@ -2,7 +2,7 @@ import { Modal } from '@/components';
 import { Form, Input } from 'antd';
 import TriggerWay from '@/pages/rule-engine/Scene/Save/components/TriggerWay';
 import type { SceneItem } from '@/pages/rule-engine/Scene/typings';
-import { useEffect } from 'react';
+import { useEffect, useState } from 'react';
 import { getMenuPathByCode } from '@/utils/menu';
 import useHistory from '@/hooks/route/useHistory';
 import { service } from '../index';
@@ -15,6 +15,7 @@ interface Props {
 export default (props: Props) => {
   const [form] = Form.useForm();
   const history = useHistory();
+  const [loading, setLoading] = useState(false);
 
   useEffect(() => {
     form.setFieldsValue({
@@ -31,6 +32,7 @@ export default (props: Props) => {
         props.close();
       }}
       width={750}
+      confirmLoading={loading}
       onOk={async () => {
         const values = await form.validateFields();
         const obj = {
@@ -41,9 +43,11 @@ export default (props: Props) => {
             ...values.trigger,
           },
         };
+        setLoading(true);
         const resp = props.data?.id
           ? await service.modify(props.data?.id, { ...obj })
           : await service.save(obj);
+        setLoading(false);
         if (resp.status === 200) {
           props.close();
           const url = getMenuPathByCode('rule-engine/Scene/Save');

+ 1 - 1
src/pages/system/Menu/Setting/baseMenu.ts

@@ -630,7 +630,7 @@ export default [
             //id: '1-3-4',
             sortIndex: 4,
             url: '/iot/device/Category',
-            icon: 'icon-chanpinfenlei1',
+            icon: 'icon-chanpinfenlei',
             accessSupport: 'support',
             assetType: 'deviceCategory',
             showPage: ['device-category'],