sun-chaochao 3 лет назад
Родитель
Сommit
00f7ffc10f

+ 15 - 4
src/components/ProTableCard/CardItems/aliyun.tsx

@@ -2,6 +2,7 @@ import React from 'react';
 import { TableCard } from '@/components';
 import '@/style/common.less';
 import '../index.less';
+import { StatusColorEnum } from '@/components/BadgeStatus';
 
 export interface AliyunCardProps extends AliCloudType {
   detail?: React.ReactNode;
@@ -13,23 +14,33 @@ const defaultImage = require('/public/images/northbound/aliyun.png');
 
 export default (props: AliyunCardProps) => {
   return (
-    <TableCard showStatus={false} actions={props.actions} showMask={false}>
+    <TableCard
+      detail={props.detail}
+      actions={props.actions}
+      status={props?.state?.value}
+      statusText={props?.state?.text}
+      statusNames={{
+        enabled: StatusColorEnum.processing,
+        disabled: StatusColorEnum.error,
+      }}
+      showMask={false}
+    >
       <div className={'pro-table-card-item'}>
         <div className={'card-item-avatar'}>
           <img width={88} height={88} src={defaultImage} alt={''} />
         </div>
         <div className={'card-item-body'}>
           <div className={'card-item-header'}>
-            <span className={'card-item-header-name ellipsis'}>{props.name}</span>
+            <span className={'card-item-header-name ellipsis'}>{props?.name}</span>
           </div>
           <div className={'card-item-content'}>
             <div>
               <label>网桥产品</label>
-              <div className={'ellipsis'}>{'网桥产品' || '--'}</div>
+              <div className={'ellipsis'}>{props?.bridgeProductName || '--'}</div>
             </div>
             <div>
               <label>说明</label>
-              <div className={'ellipsis'}>{'说明' || '--'}</div>
+              <div className={'ellipsis'}>{props?.description || '--'}</div>
             </div>
           </div>
         </div>

+ 180 - 87
src/pages/Northbound/AliCloud/Detail/index.tsx

@@ -1,4 +1,4 @@
-import { TitleComponent } from '@/components';
+import { PermissionButton, TitleComponent } from '@/components';
 import { PageContainer } from '@ant-design/pro-layout';
 import {
   ArrayItems,
@@ -8,26 +8,65 @@ import {
   FormItem,
   Input,
   Select,
-  Submit,
   ArrayCollapse,
 } from '@formily/antd';
 import type { Field } from '@formily/core';
+import { onFieldValueChange } from '@formily/core';
 import { createForm } from '@formily/core';
-import { createSchemaField } from '@formily/react';
-import { Card, Col, Row, Image } from 'antd';
-import { useEffect } from 'react';
+import { createSchemaField, observer } from '@formily/react';
+import { Card, Col, Row, Image, message } from 'antd';
+import { useEffect, useMemo, useState } from 'react';
 import { useParams } from 'umi';
+import { useAsyncDataSource } from '@/utils/util';
 import './index.less';
-import type { Response } from '@/utils/typings';
 import { service } from '@/pages/Northbound/AliCloud';
-import { action } from '@formily/reactive';
+import usePermissions from '@/hooks/permission';
 
-const Detail = () => {
+const Detail = observer(() => {
   const params = useParams<{ id: string }>();
+  const [dataList, setDataList] = useState<any[]>([]);
+  const [productList, setProductList] = useState<any[]>([]);
 
-  const form = createForm({
-    validateFirst: true,
-  });
+  const form = useMemo(
+    () =>
+      createForm({
+        validateFirst: true,
+        effects() {
+          onFieldValueChange('accessConfig.*', async (field, f) => {
+            const regionId = field.query('accessConfig.regionId').value();
+            const accessKeyId = field.query('accessConfig.accessKeyId').value();
+            const accessSecret = field.query('accessConfig.accessSecret').value();
+            if (regionId && accessKeyId && accessSecret) {
+              const response = await service.getAliyunProductsList({
+                regionId,
+                accessKeyId,
+                accessSecret,
+              });
+              f.setFieldState(field.query('bridgeProductKey'), (state) => {
+                state.dataSource = response;
+                setDataList(response);
+              });
+            } else {
+              f.setFieldState(field.query('bridgeProductKey'), (state) => {
+                state.dataSource = [];
+                setDataList([]);
+              });
+            }
+          });
+        },
+      }),
+    [],
+  );
+
+  useEffect(() => {
+    if (params.id) {
+      service.detail(params.id).then((resp) => {
+        if (resp.status === 200) {
+          form.setValues(resp.result);
+        }
+      });
+    }
+  }, [params.id]);
 
   const SchemaField = createSchemaField({
     components: {
@@ -42,23 +81,44 @@ const Detail = () => {
 
   const queryRegionsList = () => service.getRegionsList();
 
-  const queryAliyunProductList = () => service.getProductsList();
+  const queryProductList = (f: Field) => {
+    const items = form.getValuesIn('mappings')?.map((i: any) => i?.productId) || [];
+    const checked = [...items];
+    const index = checked.findIndex((i) => i === f.value);
+    checked.splice(index, 1);
+    if (productList?.length > 0) {
+      return new Promise((resolve) => {
+        const list = productList.filter((j: any) => !checked.includes(j.value));
+        resolve(list);
+      });
+    } else {
+      return service.getProductsList({ paging: false }).then((resp) => {
+        setProductList(resp);
+        return resp.filter((j: any) => !checked.includes(j.value));
+      });
+    }
+  };
 
-  const useAsyncDataSource = (api: any) => (field: Field) => {
-    field.loading = true;
-    api(field).then(
-      action.bound!((resp: Response<any>) => {
-        field.dataSource = resp.result?.map((item: Record<string, unknown>) => ({
-          ...item,
-          label: item.name,
-          value: item.id,
-        }));
-        field.loading = false;
-      }),
-    );
+  const queryAliyunProductList = (f: Field) => {
+    const items = form.getValuesIn('mappings')?.map((i: any) => i?.productKey) || [];
+    const checked = [...items];
+    const index = checked.findIndex((i) => i === f.value);
+    checked.splice(index, 1);
+    if (dataList?.length > 0) {
+      return new Promise((resolve) => {
+        const list = dataList.filter((j: any) => !checked.includes(j.value));
+        resolve(list);
+      });
+    } else {
+      const accessConfig = form.getValuesIn('accessConfig') || {};
+      return service.getAliyunProductsList(accessConfig).then((resp) => {
+        setDataList(resp);
+        return resp.filter((j: any) => !checked.includes(j.value));
+      });
+    }
   };
 
-  const schema = {
+  const schema: any = {
     type: 'object',
     properties: {
       name: {
@@ -77,62 +137,67 @@ const Detail = () => {
           },
         ],
       },
-      address: {
-        type: 'string',
-        title: '服务地址',
-        required: true,
-        'x-decorator': 'FormItem',
-        'x-component': 'Select',
-        'x-component-props': {
-          placeholder: '请选择服务地址',
-          showSearch: true,
-          filterOption: (input: string, option: any) =>
-            option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0,
-        },
-        'x-decorator-props': {
-          tooltip: '阿里云内部给每台机器设置的唯一编号',
-        },
-        'x-reactions': ['{{useAsyncDataSource(queryRegionsList)}}'],
-      },
-      accessKey: {
-        type: 'string',
-        title: 'accessKey',
-        required: true,
-        'x-decorator': 'FormItem',
-        'x-component': 'Input',
-        'x-component-props': {
-          placeholder: '请输入accessKey',
-        },
-        'x-validator': [
-          {
-            max: 64,
-            message: '最多可输入64个字符',
+      accessConfig: {
+        type: 'object',
+        properties: {
+          regionId: {
+            type: 'string',
+            title: '服务地址',
+            required: true,
+            'x-decorator': 'FormItem',
+            'x-component': 'Select',
+            'x-component-props': {
+              placeholder: '请选择服务地址',
+              showSearch: true,
+              filterOption: (input: string, option: any) =>
+                option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0,
+            },
+            'x-decorator-props': {
+              tooltip: '阿里云内部给每台机器设置的唯一编号',
+            },
+            'x-reactions': ['{{useAsyncDataSource(queryRegionsList)}}'],
           },
-        ],
-        'x-decorator-props': {
-          tooltip: '用于程序通知方式调用云服务API的用户标识',
-        },
-      },
-      accessSecret: {
-        type: 'string',
-        title: 'accessSecret',
-        required: true,
-        'x-decorator': 'FormItem',
-        'x-component': 'Input',
-        'x-component-props': {
-          placeholder: '请输入accessSecret',
-        },
-        'x-validator': [
-          {
-            max: 64,
-            message: '最多可输入64个字符',
+          accessKeyId: {
+            type: 'string',
+            title: 'accessKey',
+            required: true,
+            'x-decorator': 'FormItem',
+            'x-component': 'Input',
+            'x-component-props': {
+              placeholder: '请输入accessKey',
+            },
+            'x-validator': [
+              {
+                max: 64,
+                message: '最多可输入64个字符',
+              },
+            ],
+            'x-decorator-props': {
+              tooltip: '用于程序通知方式调用云服务API的用户标识',
+            },
+          },
+          accessSecret: {
+            type: 'string',
+            title: 'accessSecret',
+            required: true,
+            'x-decorator': 'FormItem',
+            'x-component': 'Input',
+            'x-component-props': {
+              placeholder: '请输入accessSecret',
+            },
+            'x-validator': [
+              {
+                max: 64,
+                message: '最多可输入64个字符',
+              },
+            ],
+            'x-decorator-props': {
+              tooltip: '用于程序通知方式调用云服务费API的秘钥标识',
+            },
           },
-        ],
-        'x-decorator-props': {
-          tooltip: '用于程序通知方式调用云服务费API的秘钥标识',
         },
       },
-      network: {
+      bridgeProductKey: {
         type: 'string',
         title: '网桥产品',
         required: true,
@@ -144,14 +209,15 @@ const Detail = () => {
         'x-decorator-props': {
           tooltip: '物联网平台对应的阿里云产品',
         },
-        'x-reactions': ['{{useAsyncDataSource(queryAliyunProductList)}}'],
       },
-      array: {
+      mappings: {
         type: 'array',
+        required: true,
         'x-component': 'ArrayCollapse',
         title: '产品映射',
         items: {
           type: 'object',
+          required: true,
           'x-component': 'ArrayCollapse.CollapsePanel',
           'x-component-props': {
             header: '产品映射',
@@ -165,7 +231,8 @@ const Detail = () => {
                 maxColumns: [24],
               },
               properties: {
-                product1: {
+                type: 'object',
+                productKey: {
                   type: 'string',
                   'x-decorator': 'FormItem',
                   title: '阿里云产品',
@@ -178,8 +245,9 @@ const Detail = () => {
                     gridSpan: 12,
                     tooltip: '阿里云物联网平台产品标识',
                   },
+                  'x-reactions': ['{{useAsyncDataSource(queryAliyunProductList)}}'],
                 },
-                product2: {
+                productId: {
                   type: 'string',
                   title: '平台产品',
                   required: true,
@@ -191,6 +259,7 @@ const Detail = () => {
                   'x-component-props': {
                     placeholder: '请选择平台产品',
                   },
+                  'x-reactions': ['{{useAsyncDataSource(queryProductList)}}'],
                 },
               },
             },
@@ -222,7 +291,18 @@ const Detail = () => {
     },
   };
 
-  useEffect(() => {}, [params.id]);
+  const handleSave = async () => {
+    const data: any = await form.submit();
+    const product = dataList.find((item) => item?.value === data?.bridgeProductKey);
+    data.bridgeProductName = product?.label || '';
+    const response: any = data.id ? await service.update(data) : await service.save(data);
+    if (response.status === 200) {
+      message.success('保存成功');
+      history.back();
+    }
+  };
+
+  const { getOtherPermission } = usePermissions('Northbound/AliCloud');
 
   return (
     <PageContainer>
@@ -233,11 +313,24 @@ const Detail = () => {
             <Form form={form} layout="vertical" onAutoSubmit={console.log}>
               <SchemaField
                 schema={schema}
-                scope={{ useAsyncDataSource, queryRegionsList, queryAliyunProductList }}
+                scope={{
+                  useAsyncDataSource,
+                  queryRegionsList,
+                  queryProductList,
+                  queryAliyunProductList,
+                }}
               />
-              <FormButtonGroup.FormItem>
-                <Submit>保存</Submit>
-              </FormButtonGroup.FormItem>
+              <FormButtonGroup.Sticky>
+                <FormButtonGroup.FormItem>
+                  <PermissionButton
+                    type="primary"
+                    isPermission={getOtherPermission(['add', 'update'])}
+                    onClick={() => handleSave()}
+                  >
+                    保存
+                  </PermissionButton>
+                </FormButtonGroup.FormItem>
+              </FormButtonGroup.Sticky>
             </Form>
           </Col>
           <Col span={10}>
@@ -284,6 +377,6 @@ const Detail = () => {
       </Card>
     </PageContainer>
   );
-};
+});
 
 export default Detail;

+ 127 - 31
src/pages/Northbound/AliCloud/index.tsx

@@ -8,12 +8,15 @@ import {
   DeleteOutlined,
   EditOutlined,
   ExclamationCircleFilled,
+  PlayCircleOutlined,
   PlusOutlined,
+  StopOutlined,
 } from '@ant-design/icons';
 import { useIntl } from '@@/plugin-locale/localeExports';
 import { getMenuPathByParams, MENUS_CODE } from '@/utils/menu';
 import AliyunCard from '@/components/ProTableCard/CardItems/aliyun';
 import Service from './service';
+import { Badge, message } from 'antd';
 
 export const service = new Service('device/aliyun/bridge');
 
@@ -51,6 +54,40 @@ const AliCloud = () => {
           })}
       </PermissionButton>,
       <PermissionButton
+        key={'action'}
+        type={'link'}
+        style={{ padding: 0 }}
+        isPermission={permission.action}
+        popConfirm={{
+          title: intl.formatMessage({
+            id: `pages.data.option.${
+              record?.state?.value !== 'disabled' ? 'disabled' : 'enabled'
+            }.tips`,
+            defaultMessage: '确认禁用?',
+          }),
+          onConfirm: async () => {
+            const resp =
+              record?.state?.value !== 'disabled'
+                ? await service._disable(record.id)
+                : await service._enable(record.id);
+            if (resp.status === 200) {
+              message.success('操作成功!');
+              actionRef.current?.reload?.();
+            } else {
+              message.error('操作失败!');
+            }
+          },
+        }}
+        tooltip={{
+          title: intl.formatMessage({
+            id: `pages.data.option.${record?.state?.value !== 'disabled' ? 'disabled' : 'enabled'}`,
+            defaultMessage: '启用',
+          }),
+        }}
+      >
+        {record?.state?.value !== 'disabled' ? <StopOutlined /> : <PlayCircleOutlined />}
+      </PermissionButton>,
+      <PermissionButton
         key={'delete'}
         type={'link'}
         style={{ padding: 0 }}
@@ -78,13 +115,33 @@ const AliCloud = () => {
     },
     {
       title: '网桥产品',
-      dataIndex: 'name1',
+      dataIndex: 'bridgeProductName',
     },
     {
       title: '说明',
       dataIndex: 'description',
     },
     {
+      title: '状态',
+      dataIndex: 'state',
+      render: (text: any) => (
+        <span>
+          <Badge status={text.value === 'disabled' ? 'error' : 'success'} text={text.text} />
+        </span>
+      ),
+      valueType: 'select',
+      valueEnum: {
+        disabled: {
+          text: '停用',
+          status: 'disabled',
+        },
+        enabled: {
+          text: '正常',
+          status: 'enabled',
+        },
+      },
+    },
+    {
       title: intl.formatMessage({
         id: 'pages.data.option',
         defaultMessage: '操作',
@@ -100,9 +157,9 @@ const AliCloud = () => {
     <PageContainer>
       <SearchComponent<AliCloudType>
         field={columns}
-        target="device-instance"
+        target="aliyun"
         onSearch={(data) => {
-          actionRef.current?.reset?.();
+          actionRef.current?.reload?.();
           setSearchParams(data);
         }}
       />
@@ -142,7 +199,6 @@ const AliCloud = () => {
           <PermissionButton
             onClick={() => {
               const url = `${getMenuPathByParams(MENUS_CODE['Northbound/AliCloud/Detail'])}`;
-              console.log(url);
               history.push(url);
             }}
             style={{ marginRight: 12 }}
@@ -163,7 +219,13 @@ const AliCloud = () => {
             actions={[
               <PermissionButton
                 type={'link'}
-                onClick={() => {}}
+                onClick={() => {
+                  const url = `${getMenuPathByParams(
+                    MENUS_CODE['Northbound/AliCloud/Detail'],
+                    record.id,
+                  )}`;
+                  history.push(url);
+                }}
                 key={'edit'}
                 isPermission={permission.update}
               >
@@ -174,36 +236,70 @@ const AliCloud = () => {
                 })}
               </PermissionButton>,
               <PermissionButton
+                key={'action'}
+                type={'link'}
+                style={{ padding: 0 }}
+                isPermission={permission.action}
+                popConfirm={{
+                  title: intl.formatMessage({
+                    id: `pages.data.option.${
+                      record?.state?.value !== 'disabled' ? 'disabled' : 'enabled'
+                    }.tips`,
+                    defaultMessage: '确认禁用?',
+                  }),
+                  onConfirm: async () => {
+                    const resp =
+                      record?.state?.value !== 'disabled'
+                        ? await service._disable(record.id)
+                        : await service._enable(record.id);
+                    if (resp.status === 200) {
+                      message.success('操作成功!');
+                      actionRef.current?.reload?.();
+                    } else {
+                      message.error('操作失败!');
+                    }
+                  },
+                }}
+              >
+                {record?.state?.value !== 'disabled' ? <StopOutlined /> : <PlayCircleOutlined />}
+                {intl.formatMessage({
+                  id: `pages.data.option.${
+                    record?.state?.value !== 'disabled' ? 'disabled' : 'enabled'
+                  }`,
+                  defaultMessage: record?.state?.value !== 'disabled' ? '禁用' : '启用',
+                })}
+              </PermissionButton>,
+              <PermissionButton
                 key="delete"
                 isPermission={permission.delete}
                 type={'link'}
                 style={{ padding: 0 }}
-                // tooltip={
-                //   record.state.value !== 'notActive'
-                //     ? { title: intl.formatMessage({ id: 'pages.device.instance.deleteTip' }) }
-                //     : undefined
-                // }
-                // disabled={record.state.value !== 'notActive'}
-                // popConfirm={{
-                //   title: intl.formatMessage({
-                //     id: 'pages.data.option.remove.tips',
-                //   }),
-                //   disabled: record.state.value !== 'notActive',
-                //   onConfirm: async () => {
-                //     if (record.state.value === 'notActive') {
-                //       await service.remove(record.id);
-                //       message.success(
-                //         intl.formatMessage({
-                //           id: 'pages.data.option.success',
-                //           defaultMessage: '操作成功!',
-                //         }),
-                //       );
-                //       actionRef.current?.reload();
-                //     } else {
-                //       message.error(intl.formatMessage({ id: 'pages.device.instance.deleteTip' }));
-                //     }
-                //   },
-                // }}
+                tooltip={
+                  record?.state?.value !== 'disabled'
+                    ? { title: intl.formatMessage({ id: 'pages.device.instance.deleteTip' }) }
+                    : undefined
+                }
+                disabled={record?.state?.value !== 'disabled'}
+                popConfirm={{
+                  title: intl.formatMessage({
+                    id: 'pages.data.option.remove.tips',
+                  }),
+                  disabled: record?.state?.value !== 'disabled',
+                  onConfirm: async () => {
+                    if (record?.state?.value === 'disabled') {
+                      await service.remove(record.id);
+                      message.success(
+                        intl.formatMessage({
+                          id: 'pages.data.option.success',
+                          defaultMessage: '操作成功!',
+                        }),
+                      );
+                      actionRef.current?.reload();
+                    } else {
+                      message.error(intl.formatMessage({ id: 'pages.device.instance.deleteTip' }));
+                    }
+                  },
+                }}
               >
                 <DeleteOutlined />
               </PermissionButton>,

+ 37 - 2
src/pages/Northbound/AliCloud/service.ts

@@ -7,13 +7,48 @@ class Service extends BaseService<AliCloudType> {
     request(`/${SystemConst.API_BASE}/device/aliyun/bridge/regions`, {
       method: 'GET',
       params,
+    }).then((resp: any) => {
+      return resp.result?.map((item: any) => ({
+        label: item.name,
+        value: item.id,
+      }));
     });
-
   // 产品映射中的阿里云产品下拉列表
-  public getProductsList = (data?: any) =>
+  public getAliyunProductsList = (data?: any) =>
     request(`/${SystemConst.API_BASE}/device/aliyun/bridge/products/_query`, {
       method: 'POST',
       data,
+    }).then((resp: any) => {
+      return resp.result.data?.map((item: any) => ({
+        label: item.productName,
+        value: item.productKey,
+      }));
+    });
+
+  // 产品下拉列表
+  public getProductsList = (data?: any) =>
+    request(`/${SystemConst.API_BASE}/device-product/_query/no-paging`, {
+      method: 'POST',
+      data,
+    }).then((resp: any) => {
+      return resp.result?.map((item: any) => ({
+        label: item.name,
+        value: item.id,
+      }));
+    });
+
+  // 启用
+  public _enable = (id: string, data?: any) =>
+    request(`/${SystemConst.API_BASE}/device/aliyun/bridge/${id}/enable`, {
+      method: 'POST',
+      data,
+    });
+
+  // 禁用
+  public _disable = (id: string, data?: any) =>
+    request(`/${SystemConst.API_BASE}/device/aliyun/bridge/${id}/disable`, {
+      method: 'POST',
+      data,
     });
 }
 

+ 13 - 0
src/pages/Northbound/AliCloud/typings.d.ts

@@ -1,4 +1,17 @@
 type AliCloudType = {
   id: string;
   name: string;
+  bridgeProductKey: string;
+  bridgeProductName: string;
+  accessConfig: {
+    regionId: string;
+    accessKeyId: string;
+    accessSecret: string;
+  };
+  state?: {
+    text: string;
+    value: string;
+  };
+  mappings: any[];
+  description?: string;
 };

+ 67 - 9
src/pages/device/Instance/Detail/Tags/location/AMap.tsx

@@ -1,6 +1,9 @@
 import { AMap } from '@/components';
-import { Input, Modal } from 'antd';
-import { useEffect } from 'react';
+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';
 
 interface Props {
   value: any;
@@ -9,7 +12,27 @@ interface Props {
 }
 
 export default (props: Props) => {
-  useEffect(() => {}, [props.value]);
+  const [markerCenter, setMarkerCenter] = useState<any>({ longitude: 0, latitude: 0 });
+  const [map, setMap] = useState(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]);
   return (
     <Modal
       visible
@@ -17,12 +40,36 @@ export default (props: Props) => {
       width={'55vw'}
       onCancel={() => props.close()}
       onOk={() => {
-        props.ok('');
+        props.ok(value);
       }}
     >
       <div style={{ position: 'relative' }}>
-        <div style={{ position: 'absolute', right: 5, top: 5, zIndex: 999 }}>
-          <Input />
+        <div
+          style={{
+            position: 'absolute',
+            width: 300,
+            padding: 10,
+            right: 5,
+            top: 5,
+            zIndex: 999,
+            backgroundColor: 'white',
+          }}
+        >
+          <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
           AMapUI
@@ -30,12 +77,23 @@ export default (props: Props) => {
             height: 500,
             width: '100%',
           }}
+          center={markerCenter.longitude ? markerCenter : undefined}
+          onInstanceCreated={setMap}
           events={{
-            click: (value: any) => {
-              console.log(value);
+            click: (e: any) => {
+              setValue(`${e.lnglat.lng},${e.lnglat.lat}`);
+              setMarkerCenter({
+                longitude: e.lnglat.lng,
+                latitude: e.lnglat.lat,
+              });
             },
           }}
-        />
+        >
+          {markerCenter.longitude ? (
+            // @ts-ignore
+            <Marker position={markerCenter} />
+          ) : null}
+        </AMap>
       </div>
     </Modal>
   );

+ 16 - 5
src/pages/device/Instance/Detail/Tags/location/GeoComponent.tsx

@@ -1,6 +1,6 @@
 import { EnvironmentOutlined } from '@ant-design/icons';
 import { Input } from 'antd';
-import { useState } from 'react';
+import { useEffect, useState } from 'react';
 import AMap from './AMap';
 
 interface Props {
@@ -10,10 +10,15 @@ interface Props {
 
 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
-        readOnly
         addonAfter={
           <EnvironmentOutlined
             onClick={() => {
@@ -21,16 +26,22 @@ const GeoComponent = (props: Props) => {
             }}
           />
         }
-        value={props.value}
+        value={value}
+        onChange={(e) => {
+          setValue(e.target.value);
+          props.onChange(e.target.value);
+        }}
       />
       {visible && (
         <AMap
-          value={props.value}
+          value={value}
           close={() => {
             setVisible(false);
           }}
           ok={(param) => {
-            console.log(param);
+            props.onChange(param);
+            setValue(param);
+            setVisible(false);
           }}
         />
       )}