Просмотр исходного кода

feat(merge): merge xyh

Next xyh
Lind 3 лет назад
Родитель
Сommit
31e9f68abc

+ 1 - 1
src/components/AMapComponent/APILoader.ts

@@ -19,7 +19,7 @@ export const getAMapPlugins = (type: string, map: any, callback: Function) => {
   }
 };
 
-export const getAMapUiPromise = (version: string = '1.1'): Promise<any> => {
+export const getAMapUiPromise = (version: string = '1.0'): Promise<any> => {
   if ((window as any).AMapUI) {
     return Promise.resolve();
   }

+ 4 - 3
src/components/AMapComponent/amap.tsx

@@ -12,7 +12,7 @@ interface AMapProps extends Omit<MapProps, 'amapkey' | 'useAMapUI'> {
 }
 
 export default (props: AMapProps) => {
-  const { style, className, events, onInstanceCreated, ...extraProps } = props;
+  const { style, className, events, onInstanceCreated, children, ...extraProps } = props;
 
   const [uiLoading, setUiLoading] = useState(false);
 
@@ -36,12 +36,13 @@ export default (props: AMapProps) => {
     }
   };
 
+  console.log(isOpenUi, uiLoading);
+
   return (
     <div style={style || { width: '100%', height: '100%' }} className={className}>
       {amapKey ? (
         // @ts-ignore
         <Map
-          version={'2.0'}
           amapkey={amapKey}
           zooms={[3, 20]}
           events={
@@ -56,7 +57,7 @@ export default (props: AMapProps) => {
           }
           {...extraProps}
         >
-          {isOpenUi ? (uiLoading ? props.children : null) : props.children}
+          {isOpenUi ? (uiLoading ? children : null) : children}
         </Map>
       ) : (
         <Empty description={'请配置高德地图key'} />

+ 39 - 5
src/components/DashBoard/header.tsx

@@ -1,8 +1,8 @@
-import React, { forwardRef, useImperativeHandle, useRef } from 'react';
+import React, { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';
 import Style from './index.less';
-import { Col, Form, Row } from 'antd';
+import { Col, Form, Radio, Row } from 'antd';
 import type { TimeType } from './timePicker';
-import RangePicker from './timePicker';
+import RangePicker, { TimeKey } from './timePicker';
 
 export interface HeaderProps {
   title: string;
@@ -22,11 +22,14 @@ export interface HeaderProps {
   closeInitialParams?: boolean;
   defaultTime?: TimeType;
   showTime?: boolean;
+  showTimeTool?: boolean;
 }
 
 export default forwardRef((props: HeaderProps, ref) => {
   const [form] = Form.useForm();
+  const [radioValue, setRadioValue] = useState<TimeType | undefined>(undefined);
   const isCloseInitial = useRef<boolean>(false);
+  const pickerRef = useRef<any>(null);
 
   const change = async (data: any) => {
     if (props.onParamsChange) {
@@ -38,6 +41,10 @@ export default forwardRef((props: HeaderProps, ref) => {
     getValues: form.getFieldsValue,
   }));
 
+  useEffect(() => {
+    setRadioValue(props.defaultTime || TimeKey.today);
+  }, []);
+
   return (
     <div className={Style.header}>
       <div className={Style.title}>{props.title}</div>
@@ -62,10 +69,37 @@ export default forwardRef((props: HeaderProps, ref) => {
                 <Form.Item name={props.extraParams.key}>{props.extraParams.Children}</Form.Item>
               </Col>
             )}
+            {}
             <Col span={props.extraParams ? 18 : 24}>
-              <div style={{ display: 'flex', justifyContent: 'flex-end' }}>
+              <div style={{ display: 'flex', justifyContent: 'flex-end', gap: 12 }}>
+                {props.showTimeTool ? (
+                  <Radio.Group
+                    defaultValue="day"
+                    buttonStyle="solid"
+                    value={radioValue}
+                    onChange={(e) => {
+                      setRadioValue(e.target.value);
+                      if (pickerRef.current) {
+                        pickerRef.current.timeChange(e.target.value);
+                      }
+                    }}
+                  >
+                    <Radio.Button value={TimeKey.today}>当天</Radio.Button>
+                    <Radio.Button value={TimeKey.week}>近一周</Radio.Button>
+                    <Radio.Button value={TimeKey.month}>近一月</Radio.Button>
+                    <Radio.Button value={TimeKey.year}>近一年</Radio.Button>
+                  </Radio.Group>
+                ) : null}
                 <Form.Item noStyle name={'time'}>
-                  <RangePicker defaultTime={props.defaultTime} showTime={props.showTime} />
+                  <RangePicker
+                    ref={pickerRef}
+                    defaultTime={props.defaultTime}
+                    showTime={props.showTime}
+                    showTimeTool={props.showTimeTool}
+                    pickerTimeChange={() => {
+                      setRadioValue(undefined);
+                    }}
+                  />
                 </Form.Item>
               </div>
             </Col>

+ 33 - 20
src/components/DashBoard/timePicker.tsx

@@ -1,7 +1,7 @@
 import type { DatePickerProps } from 'antd';
 import { DatePicker, Radio } from 'antd';
 import moment from 'moment';
-import { useEffect, useState } from 'react';
+import { useEffect, useState, forwardRef, useImperativeHandle } from 'react';
 
 export enum TimeKey {
   'today' = 'today',
@@ -18,7 +18,9 @@ interface ExtraTimePickerProps extends Omit<DatePickerProps, 'onChange' | 'value
   onChange?: (data: ValueType) => void;
   value?: ValueType;
   defaultTime?: TimeType;
+  pickerTimeChange?: () => void;
   showTime?: boolean;
+  showTimeTool?: boolean;
 }
 
 export const getTimeByType = (type: TimeType) => {
@@ -34,7 +36,7 @@ export const getTimeByType = (type: TimeType) => {
   }
 };
 
-export default (props: ExtraTimePickerProps) => {
+export default forwardRef((props: ExtraTimePickerProps, ref) => {
   const [radioValue, setRadioValue] = useState<TimeType | undefined>(undefined);
 
   const { value, onChange, ...extraProps } = props;
@@ -56,6 +58,10 @@ export default (props: ExtraTimePickerProps) => {
     change(startTime, endTime, type);
   };
 
+  useImperativeHandle(ref, () => ({
+    timeChange,
+  }));
+
   useEffect(() => {
     timeChange(props.defaultTime || TimeKey.today);
   }, []);
@@ -78,26 +84,33 @@ export default (props: ExtraTimePickerProps) => {
             if (rangeValue && rangeValue.length === 2) {
               change(rangeValue[0]!.valueOf(), rangeValue[1]!.valueOf(), radioValue!);
             }
+            if (props.pickerTimeChange) {
+              props.pickerTimeChange();
+            }
           }}
-          renderExtraFooter={() => (
-            <div style={{ padding: '12px 0' }}>
-              <Radio.Group
-                defaultValue="day"
-                buttonStyle="solid"
-                value={radioValue}
-                onChange={(e) => {
-                  timeChange(e.target.value);
-                }}
-              >
-                <Radio.Button value={TimeKey.today}>当天</Radio.Button>
-                <Radio.Button value={TimeKey.week}>近一周</Radio.Button>
-                <Radio.Button value={TimeKey.month}>近一月</Radio.Button>
-                <Radio.Button value={TimeKey.year}>近一年</Radio.Button>
-              </Radio.Group>
-            </div>
-          )}
+          renderExtraFooter={
+            props.showTimeTool !== true
+              ? () => (
+                  <div style={{ padding: '12px 0' }}>
+                    <Radio.Group
+                      defaultValue="day"
+                      buttonStyle="solid"
+                      value={radioValue}
+                      onChange={(e) => {
+                        timeChange(e.target.value);
+                      }}
+                    >
+                      <Radio.Button value={TimeKey.today}>当天</Radio.Button>
+                      <Radio.Button value={TimeKey.week}>近一周</Radio.Button>
+                      <Radio.Button value={TimeKey.month}>近一月</Radio.Button>
+                      <Radio.Button value={TimeKey.year}>近一年</Radio.Button>
+                    </Radio.Group>
+                  </div>
+                )
+              : undefined
+          }
         />
       }
     </>
   );
-};
+});

+ 117 - 0
src/components/FormItems/MetadataJsonInput/index.tsx

@@ -0,0 +1,117 @@
+import { Input, Modal } from 'antd';
+import { EnvironmentOutlined } from '@ant-design/icons';
+import { useEffect, useState } from 'react';
+import MonacoEditor from 'react-monaco-editor';
+import { isObject } from 'lodash';
+
+type MetaDataJsonInputProps = {
+  json: Record<string, any>;
+  value?: string;
+  onChange?: (value: string) => void;
+};
+
+export const MetaDataJsonHandle = (data: any): Record<string, any> => {
+  const _JSON = {};
+
+  if (isObject(data)) {
+    const type = (data as any).valueType.type;
+    const id = (data as any).id;
+
+    switch (type) {
+      case 'object':
+        _JSON[id] = MetaDataJsonHandle((data as any)['json']['properties'][0]);
+        break;
+      case 'array':
+        _JSON[id] = [];
+        break;
+      case 'int':
+      case 'long':
+      case 'float':
+      case 'double':
+        _JSON[id] = 0;
+        break;
+      case 'boolean':
+        _JSON[id] = false;
+        break;
+      default:
+        _JSON[id] = '';
+        break;
+    }
+  }
+
+  return _JSON;
+};
+
+export default (props: MetaDataJsonInputProps) => {
+  const [value, setValue] = useState(props.value || '');
+  const [visible, setVisible] = useState(false);
+  const [monacoValue, setMonacoValue] = useState<string>('');
+
+  const onChange = (data: string) => {
+    if (props.onChange) {
+      const newData = data.replace(/[ ]/g, '');
+      props.onChange(newData);
+    }
+  };
+
+  const editorDidMountHandle = (editor: any) => {
+    editor.onDidContentSizeChange?.(() => {
+      editor.getAction('editor.action.formatDocument').run();
+    });
+  };
+
+  useEffect(() => {
+    setValue(props.value || '');
+  }, [props.value]);
+
+  useEffect(() => {
+    if (props.json) {
+      const _json = MetaDataJsonHandle(props.json);
+      onChange(JSON.stringify(_json));
+    }
+  }, [props.json]);
+
+  return (
+    <>
+      <Input
+        addonAfter={
+          <EnvironmentOutlined
+            onClick={() => {
+              setMonacoValue(value);
+              setVisible(true);
+            }}
+          />
+        }
+        value={value}
+        onChange={(e) => {
+          setValue(e.target.value);
+          onChange(e.target.value);
+        }}
+      />
+      <Modal
+        visible={visible}
+        title={'编辑'}
+        onOk={() => {
+          onChange(monacoValue);
+          setVisible(false);
+        }}
+        onCancel={() => {
+          setVisible(false);
+        }}
+        width={700}
+      >
+        <MonacoEditor
+          width={'100%'}
+          height={400}
+          theme="vs-dark"
+          language={'json'}
+          value={monacoValue}
+          onChange={(newValue) => {
+            setMonacoValue(newValue);
+          }}
+          editorDidMount={editorDidMountHandle}
+        />
+      </Modal>
+    </>
+  );
+};

+ 97 - 0
src/components/GeoPoint/AMap.tsx

@@ -0,0 +1,97 @@
+import { AMap } from '@/components';
+import usePlaceSearch from '@/components/AMapComponent/hooks/PlaceSearch';
+import { Input, Modal, Select } from 'antd';
+import { debounce } from 'lodash';
+import { Marker } from 'react-amap';
+import { useEffect, useState } from 'react';
+import './style';
+
+interface Props {
+  value: any;
+  close: () => void;
+  ok: (data: any) => void;
+}
+
+type MarkerPointType = {
+  longitude: number;
+  latitude: number;
+};
+
+export default (props: Props) => {
+  const [markerCenter, setMarkerCenter] = useState<MarkerPointType>({ longitude: 0, latitude: 0 });
+  const [map, setMap] = useState<any>(null);
+
+  const { data, search } = usePlaceSearch(map);
+
+  const [value, setValue] = useState<any>(props.value);
+
+  const onSearch = (value1: string) => {
+    search(value1);
+  };
+
+  useEffect(() => {
+    setValue(props?.value || '');
+    const list = (props?.value || '').split(',') || [];
+    if (!!props.value && list.length === 2) {
+      setMarkerCenter({
+        longitude: list[0],
+        latitude: list[1],
+      });
+    }
+  }, [props.value]);
+  console.log(markerCenter);
+
+  return (
+    <Modal
+      visible
+      title="地理位置"
+      width={'55vw'}
+      onCancel={() => props.close()}
+      onOk={() => {
+        props.ok(value);
+      }}
+    >
+      <div className={'map-search-warp'}>
+        <div className={'map-search-select'}>
+          <Select
+            showSearch
+            options={data}
+            filterOption={false}
+            onSearch={debounce(onSearch, 300)}
+            style={{ width: '100%', marginBottom: 10 }}
+            onSelect={(key: string, node: any) => {
+              setValue(key);
+              setMarkerCenter({
+                longitude: node.lnglat.lng,
+                latitude: node.lnglat.lat,
+              });
+            }}
+          />
+          <Input value={value} readOnly />
+        </div>
+        <AMap
+          style={{
+            height: 500,
+            width: '100%',
+          }}
+          center={markerCenter.longitude ? markerCenter : undefined}
+          onInstanceCreated={setMap}
+          events={{
+            click: (e: any) => {
+              setValue(`${e.lnglat.lng},${e.lnglat.lat}`);
+              setMarkerCenter({
+                longitude: e.lnglat.lng,
+                latitude: e.lnglat.lat,
+              });
+            },
+          }}
+        >
+          {markerCenter.longitude ? (
+            // @ts-ignore
+            <Marker kye={'marker'} position={markerCenter} />
+          ) : null}
+        </AMap>
+      </div>
+    </Modal>
+  );
+};

+ 13 - 0
src/components/GeoPoint/index.less

@@ -0,0 +1,13 @@
+.map-search-warp {
+  position: relative;
+
+  .map-search-select {
+    position: absolute;
+    top: 5px;
+    right: 5px;
+    z-index: 9;
+    width: 300px;
+    padding: 10px;
+    background-color: #fff;
+  }
+}

+ 55 - 0
src/components/GeoPoint/index.tsx

@@ -0,0 +1,55 @@
+import { EnvironmentOutlined } from '@ant-design/icons';
+import { Input } from 'antd';
+import { useEffect, useState } from 'react';
+import AMap from './AMap';
+
+interface Props {
+  value?: string;
+  onChange?: (value: string) => void;
+}
+
+const GeoComponent = (props: Props) => {
+  const [visible, setVisible] = useState<boolean>(false);
+  const [value, setValue] = useState<any>(props?.value);
+
+  useEffect(() => {
+    setValue(props?.value);
+  }, [props.value]);
+
+  return (
+    <div>
+      <Input
+        addonAfter={
+          <EnvironmentOutlined
+            onClick={() => {
+              setVisible(true);
+            }}
+          />
+        }
+        value={value}
+        onChange={(e) => {
+          // setValue(e.target.value);
+          if (props.onChange) {
+            props.onChange(e.target.value);
+          }
+        }}
+      />
+      {visible && (
+        <AMap
+          value={value}
+          close={() => {
+            setVisible(false);
+          }}
+          ok={(param) => {
+            if (props.onChange) {
+              props.onChange(param);
+            }
+            // setValue(param);
+            setVisible(false);
+          }}
+        />
+      )}
+    </div>
+  );
+};
+export default GeoComponent;

+ 1 - 0
src/components/GeoPoint/style.js

@@ -0,0 +1 @@
+import './index.less';

+ 2 - 0
src/components/index.ts

@@ -12,3 +12,5 @@ export { default as TitleComponent } from './TitleComponent';
 export { default as AMap } from './AMapComponent/amap';
 export { default as PathSimplifier } from './AMapComponent/PathSimplifier';
 export { default as Empty } from './Empty';
+export { default as GeoPoint } from './GeoPoint';
+export { default as MetadataJsonInput } from './FormItems/MetadataJsonInput';

+ 1 - 0
src/pages/device/DashBoard/index.tsx

@@ -416,6 +416,7 @@ const DeviceBoard = () => {
           height={500}
           defaultTime={'week'}
           showTime={true}
+          showTimeTool={true}
           onParamsChange={getEcharts}
         />
         {amapKey && (

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

@@ -7,6 +7,7 @@ import MonacoEditor from 'react-monaco-editor';
 import { isObject } from 'lodash';
 
 import './index.less';
+import { MetaDataJsonHandle } from '@/components/FormItems/MetadataJsonInput';
 
 type FunctionProps = {
   data: FunctionMetadata;
@@ -44,9 +45,31 @@ export default (props: FunctionProps) => {
 
   const handleData = (data: any) => {
     const obj = {};
-    const properties = data.valueType ? data.valueType.properties : [];
+
+    const properties = data.valueType ? data.valueType.properties : data.inputs;
+
     for (const datum of properties) {
-      obj[datum.id] = '';
+      switch (datum.valueType.type) {
+        case 'object':
+          obj[datum.id] = MetaDataJsonHandle(datum['json']['properties'][0]);
+          break;
+        case 'array':
+          obj[datum.id] = [];
+          break;
+        case 'int':
+        case 'long':
+        case 'float':
+        case 'double':
+          obj[datum.id] = 0;
+          break;
+        case 'boolean':
+          obj[datum.id] = false;
+          break;
+        default:
+          obj[datum.id] = '';
+          break;
+      }
+      // obj[datum.id] = '';
     }
     setValue(JSON.stringify(obj));
 
@@ -57,6 +80,9 @@ export default (props: FunctionProps) => {
 
   const editorDidMountHandle = (editor: any) => {
     monacoRef.current = editor;
+    editor.onDidContentSizeChange?.(() => {
+      editor.getAction('editor.action.formatDocument').run();
+    });
   };
 
   useEffect(() => {

+ 14 - 4
src/pages/device/Instance/Detail/Functions/form.tsx

@@ -9,6 +9,7 @@ import ProForm from '@ant-design/pro-form';
 import { InstanceModel, service } from '@/pages/device/Instance';
 import moment from 'moment';
 import './index.less';
+import { GeoPoint, MetadataJsonInput } from '@/components';
 
 type FunctionProps = {
   data: FunctionMetadata;
@@ -57,6 +58,10 @@ export default (props: FunctionProps) => {
       case 'float':
       case 'double':
         return <InputNumber style={{ width: '100%' }} placeholder={'请输入' + name} />;
+      case 'geoPoint':
+        return <GeoPoint />;
+      case 'object':
+        return <MetadataJsonInput json={record.json} />;
       case 'date':
         return (
           <>
@@ -78,14 +83,14 @@ export default (props: FunctionProps) => {
     {
       dataIndex: 'name',
       title: '名称',
-      width: 200,
+      width: 120,
       editable: false,
       ellipsis: true,
     },
     {
       dataIndex: 'type',
       title: '类型',
-      width: 200,
+      width: 120,
       editable: false,
     },
     {
@@ -95,7 +100,6 @@ export default (props: FunctionProps) => {
       }),
       dataIndex: 'value',
       align: 'center',
-      width: 260,
       renderFormItem: (_, row: any) => {
         return getItemNode(row.record);
       },
@@ -107,12 +111,16 @@ export default (props: FunctionProps) => {
     const properties = data.valueType ? data.valueType.properties : data.inputs;
 
     for (const datum of properties) {
+      console.log(datum);
+      const type = datum.valueType ? datum.valueType.type : '-';
+
       array.push({
         id: datum.id,
         name: datum.name,
-        type: datum.valueType ? datum.valueType.type : '-',
+        type: type,
         format: datum.valueType ? datum.valueType.format : undefined,
         options: datum.valueType ? datum.valueType.elements : undefined,
+        json: type === 'object' ? datum['json']['properties'][0] : undefined,
         value: undefined,
       });
     }
@@ -135,6 +143,8 @@ export default (props: FunctionProps) => {
         if (d.value) {
           if (d.type === 'date') {
             data[d.id] = moment(d.value).format('YYYY-MM-DD HH:mm:ss');
+          } else if (d.type === 'object') {
+            data[d.id] = JSON.parse(d.value);
           } else {
             data[d.id] = d.value;
           }

+ 2 - 2
src/pages/device/Instance/Detail/Functions/index.less

@@ -2,7 +2,7 @@
   display: flex;
 
   .left {
-    width: 50%;
+    width: 60%;
 
     .button-tool {
       display: flex;
@@ -16,7 +16,7 @@
   }
 
   .right {
-    width: 50%;
+    width: 40%;
     padding-left: 24px;
   }
 }

+ 82 - 32
src/pages/device/Instance/Detail/Functions/index.tsx

@@ -1,49 +1,99 @@
-import { Card, Tabs } from 'antd';
+import { Button, Card, Tabs } from 'antd';
 import { InstanceModel } from '@/pages/device/Instance';
 import type { FunctionMetadata } from '@/pages/device/Product/typings';
 import FnForm from './form';
 import AModel from './AdvancedMode';
-import { Empty } from '@/components';
+import { Empty, PermissionButton } from '@/components';
 import { useDomFullHeight } from '@/hooks';
+import { getMenuPathByParams } from '@/utils/menu';
+import useHistory from '@/hooks/route/useHistory';
 
 const Functions = () => {
   const functionList = JSON.parse(InstanceModel.detail.metadata || '{}')
     .functions as FunctionMetadata[];
+  const history = useHistory();
 
   const { minHeight } = useDomFullHeight(`.device-detail-function`);
+  const { permission } = PermissionButton.usePermission('device/Product');
+
+  const empty = () => {
+    const isIndependent = InstanceModel.detail?.independentMetadata;
+    const path = isIndependent
+      ? getMenuPathByParams('device/Product/Detail', InstanceModel.detail?.productId)
+      : getMenuPathByParams('device/Instance/Detail', InstanceModel.detail?.id);
+
+    let description = <></>;
+    if (isIndependent) {
+      // 物模型解绑
+      if (!permission.update) {
+        description = <span>请联系管理员配置物模型属性</span>;
+      } else {
+        description = (
+          <span>
+            暂无数据, 请前往产品配置
+            <Button
+              style={{ margin: '0 6px' }}
+              type={'link'}
+              onClick={() => {
+                history.push(`${path}?key=metadata`);
+              }}
+            >
+              物模型-功能定义
+            </Button>
+          </span>
+        );
+      }
+    } else {
+      description = (
+        <span>
+          暂无数据,请配置
+          <Button
+            style={{ margin: '0 6px' }}
+            type={'link'}
+            onClick={() => {
+              history.push(`${path}?key=metadata`);
+            }}
+          >
+            物模型-功能定义
+          </Button>
+        </span>
+      );
+    }
+
+    return <Empty description={description} />;
+  };
 
   return (
     <Card className={'device-detail-function'} style={{ minHeight: minHeight }}>
-      <Tabs>
-        <Tabs.TabPane tab={'精简模式'} key={1}>
-          <Tabs tabPosition="left">
-            {functionList &&
-              functionList.map((fn) => {
-                return (
-                  <Tabs.TabPane tab={fn.name} key={fn.id}>
-                    <FnForm data={fn} />
-                  </Tabs.TabPane>
-                );
-              })}
-          </Tabs>
-        </Tabs.TabPane>
-        <Tabs.TabPane tab={'高级模式'} key={2}>
-          <Tabs tabPosition="left">
-            {functionList &&
-              functionList.map((fn) => {
-                return (
-                  <Tabs.TabPane tab={fn.name} key={fn.id}>
-                    <AModel data={fn} />
-                  </Tabs.TabPane>
-                );
-              })}
-          </Tabs>
-        </Tabs.TabPane>
-      </Tabs>
-      {!functionList && (
-        <div style={{ height: minHeight - 150 }}>
-          <Empty />
-        </div>
+      {functionList ? (
+        <Tabs>
+          <Tabs.TabPane tab={'精简模式'} key={1}>
+            <Tabs tabPosition="left">
+              {functionList &&
+                functionList.map((fn) => {
+                  return (
+                    <Tabs.TabPane tab={fn.name} key={fn.id}>
+                      <FnForm data={fn} />
+                    </Tabs.TabPane>
+                  );
+                })}
+            </Tabs>
+          </Tabs.TabPane>
+          <Tabs.TabPane tab={'高级模式'} key={2}>
+            <Tabs tabPosition="left">
+              {functionList &&
+                functionList.map((fn) => {
+                  return (
+                    <Tabs.TabPane tab={fn.name} key={fn.id}>
+                      <AModel data={fn} />
+                    </Tabs.TabPane>
+                  );
+                })}
+            </Tabs>
+          </Tabs.TabPane>
+        </Tabs>
+      ) : (
+        <div style={{ height: minHeight - 150 }}>{empty()}</div>
       )}
     </Card>
   );

+ 1 - 0
src/pages/device/Instance/Detail/index.tsx

@@ -233,6 +233,7 @@ const InstanceDetail = observer(() => {
   }, [params.id]);
 
   useEffect(() => {
+    console.log(location.query);
     if ((location as any).query?.key) {
       setTab((location as any).query?.key || 'detail');
     }

+ 1 - 0
src/pages/link/DashBoard/index.tsx

@@ -429,6 +429,7 @@ export default () => {
             initialValues={{ type: 'bytesSent' }}
             height={400}
             closeInitialParams={true}
+            showTimeTool={true}
             extraParams={{
               key: 'type',
               Children: (

+ 1 - 0
src/pages/media/DashBoard/index.tsx

@@ -223,6 +223,7 @@ export default () => {
           </DashBoardTopCard.Item>
         </DashBoardTopCard>
         <DashBoard
+          showTimeTool={true}
           className={'media-dash-board-body'}
           title={'播放数量(人次)'}
           options={options}

+ 1 - 0
src/pages/rule-engine/DashBoard/index.tsx

@@ -336,6 +336,7 @@ const Dashboard = observer(() => {
         <DashBoard
           title="告警统计"
           height={600}
+          showTimeTool={true}
           options={options}
           onParamsChange={getEcharts}
           ref={alarmCountRef}

+ 21 - 29
src/pages/system/Menu/Detail/edit.tsx

@@ -32,7 +32,7 @@ type EditProps = {
 
 export default (props: EditProps) => {
   const intl = useIntl();
-  const [disabled, setDisabled] = useState(true);
+  // const [disabled, setDisabled] = useState(true);
   const [show] = useState(true);
   const [loading, setLoading] = useState(false);
   const [accessSupport, setAccessSupport] = useState('unsupported');
@@ -79,7 +79,7 @@ export default (props: EditProps) => {
       setLoading(false);
       if (response.status === 200) {
         message.success('操作成功!');
-        setDisabled(true);
+        // setDisabled(true);
         // 新增后刷新页面,编辑则不需要
         if (!props.data.id) {
           pageJump(response.result.id);
@@ -120,7 +120,7 @@ export default (props: EditProps) => {
       });
       setAccessSupport(props.data.accessSupport ? props.data.accessSupport.value : 'unsupported');
     }
-    setDisabled(!!props.data.id);
+    // setDisabled(!!props.data.id);
 
     // if (props.data.options) {
     //   setShow(props.data.options.switch);
@@ -146,7 +146,7 @@ export default (props: EditProps) => {
                   disabled={disabled}
                   style={{ width: 140, height: 130 }}
                 /> */}
-                <Icons disabled={disabled} />
+                <Icons />
               </Form.Item>
             </Col>
             <Col span={21}>
@@ -164,7 +164,7 @@ export default (props: EditProps) => {
                       { max: 64, message: '最多可输入64个字符' },
                     ]}
                   >
-                    <Input disabled={disabled} placeholder={'请输入名称'} />
+                    <Input placeholder={'请输入名称'} />
                   </Form.Item>
                 </Col>
                 <Col span={12}>
@@ -177,7 +177,7 @@ export default (props: EditProps) => {
                     required={true}
                     rules={[{ required: true, message: '请输入编码' }]}
                   >
-                    <Input disabled={disabled} placeholder={'请输入编码'} />
+                    <Input placeholder={'请输入编码'} />
                   </Form.Item>
                 </Col>
               </Row>
@@ -195,7 +195,7 @@ export default (props: EditProps) => {
                       { max: 120, message: '最多可输入120字符' },
                     ]}
                   >
-                    <Input disabled={disabled} placeholder={'请输入页面地址'} />
+                    <Input placeholder={'请输入页面地址'} />
                   </Form.Item>
                 </Col>
                 <Col span={12}>
@@ -212,24 +212,14 @@ export default (props: EditProps) => {
                       },
                     ]}
                   >
-                    <InputNumber
-                      style={{ width: '100%' }}
-                      disabled={disabled}
-                      placeholder={'请输入排序'}
-                    />
+                    <InputNumber style={{ width: '100%' }} placeholder={'请输入排序'} />
                   </Form.Item>
                 </Col>
               </Row>
             </Col>
             <Col span={24}>
               <Form.Item name={'describe'} label={'说明'}>
-                <Input.TextArea
-                  disabled={disabled}
-                  rows={4}
-                  maxLength={200}
-                  showCount
-                  placeholder={'请输入说明'}
-                />
+                <Input.TextArea rows={4} maxLength={200} showCount placeholder={'请输入说明'} />
               </Form.Item>
             </Col>
           </Row>
@@ -262,7 +252,7 @@ export default (props: EditProps) => {
                     onChange={(e) => {
                       setAccessSupport(e.target.value);
                     }}
-                    disabled={disabled}
+                    // disabled={disabled}
                   >
                     <Radio value={'unsupported'}>不支持</Radio>
                     <Radio value={'support'}>支持</Radio>
@@ -284,7 +274,7 @@ export default (props: EditProps) => {
                   >
                     <Select
                       style={{ width: 500 }}
-                      disabled={disabled}
+                      // disabled={disabled}
                       placeholder={'请选择资产类型'}
                       options={
                         assetsType
@@ -301,7 +291,7 @@ export default (props: EditProps) => {
                   >
                     <TreeSelect
                       style={{ width: 400 }}
-                      disabled={disabled}
+                      // disabled={disabled}
                       multiple
                       placeholder={'请选择关联菜单'}
                       fieldNames={{ label: 'name', value: 'id' }}
@@ -323,7 +313,7 @@ export default (props: EditProps) => {
                       id: 'page.system.menu.permissions.operate',
                       defaultMessage: '操作权限',
                     })}
-                    disabled={disabled}
+                    // disabled={disabled}
                     data={permissions}
                   />
                   {/*</Form.Item>*/}
@@ -334,17 +324,19 @@ export default (props: EditProps) => {
           <PermissionButton
             type="primary"
             onClick={() => {
-              if (disabled) {
-                setDisabled(false);
-              } else {
-                saveData();
-              }
+              // if (disabled) {
+              //   setDisabled(false);
+              // } else {
+              //   saveData();
+              // }
+              saveData();
             }}
             loading={loading}
             isPermission={getOtherPermission(['add', 'update'])}
           >
             {intl.formatMessage({
-              id: `pages.data.option.${disabled ? 'edit' : 'save'}`,
+              // id: `pages.data.option.${disabled ? 'edit' : 'save'}`,
+              id: `pages.data.option.save`,
               defaultMessage: '编辑',
             })}
           </PermissionButton>

+ 2 - 2
src/pages/system/Platforms/save.tsx

@@ -385,8 +385,8 @@ export default (props: SaveProps) => {
             },
             'x-validator': [
               {
-                max: 64,
-                message: '最多可输入64个字符',
+                max: 128,
+                message: '最多可输入128个字符',
               },
               {
                 required: true,