Procházet zdrojové kódy

fix(merge): merge sc

Lind před 3 roky
rodič
revize
19c3037084

+ 2 - 0
src/pages/link/AccessConfig/Detail/Access/index.tsx

@@ -294,6 +294,7 @@ const Access = (props: Props) => {
             <Alert message="选择与设备通信的网络组件" type="warning" showIcon />
             <div className={styles.search}>
               <Input.Search
+                key={'network'}
                 placeholder="请输入名称"
                 onSearch={(value: string) => {
                   queryNetworkList(
@@ -394,6 +395,7 @@ const Access = (props: Props) => {
             />
             <div className={styles.search}>
               <Input.Search
+                key={'protocol'}
                 placeholder="请输入名称"
                 onSearch={(value: string) => {
                   queryProcotolList(

+ 62 - 29
src/pages/rule-engine/Instance/index.tsx

@@ -10,9 +10,10 @@ import {
   MinusOutlined,
   ReloadOutlined,
 } from '@ant-design/icons';
-import { Tooltip } from 'antd';
+import { Badge, Tooltip } from 'antd';
 import BaseCrud from '@/components/BaseCrud';
 import { useIntl } from '@@/plugin-locale/localeExports';
+import type { ISchema } from '@formily/json-schema';
 
 export const service = new BaseService<InstanceItem>('rule-engine/instance');
 const Instance = () => {
@@ -21,31 +22,24 @@ const Instance = () => {
 
   const columns: ProColumns<InstanceItem>[] = [
     {
-      dataIndex: 'index',
-      valueType: 'indexBorder',
-      width: 48,
-    },
-    {
       dataIndex: 'name',
       title: intl.formatMessage({
         id: 'pages.table.name',
         defaultMessage: '名称',
       }),
+      ellipsis: true,
     },
     {
-      dataIndex: 'modelType',
-      title: intl.formatMessage({
-        id: 'pages.link.type',
-        defaultMessage: '类型',
-      }),
+      dataIndex: 'state',
+      title: '状态',
+      render: (text: any) => (
+        <Badge color={text?.value === 'stopped' ? 'red' : 'green'} text={text?.text} />
+      ),
     },
     {
-      dataIndex: 'state',
-      title: intl.formatMessage({
-        id: 'pages.searchTable.titleStatus',
-        defaultMessage: '状态',
-      }),
-      render: (text, record) => record.state.value,
+      dataIndex: 'description',
+      title: '说明',
+      ellipsis: true,
     },
     {
       title: intl.formatMessage({
@@ -56,27 +50,27 @@ const Instance = () => {
       align: 'center',
       width: 200,
       render: (text, record) => [
-        <a>
+        <a key={'edit'} onClick={() => console.log(record)}>
           <Tooltip
             title={intl.formatMessage({
-              id: 'pages.ruleEngine.option.detail',
-              defaultMessage: '查看',
+              id: 'pages.data.option.edit',
+              defaultMessage: '编辑',
             })}
           >
-            <EyeOutlined />
+            <EditOutlined />
           </Tooltip>
         </a>,
-        <a onClick={() => console.log(record)}>
+        <a key={'see'}>
           <Tooltip
             title={intl.formatMessage({
-              id: 'pages.data.option.edit',
-              defaultMessage: '编辑',
+              id: 'pages.ruleEngine.option.detail',
+              defaultMessage: '查看',
             })}
           >
-            <EditOutlined />
+            <EyeOutlined />
           </Tooltip>
         </a>,
-        <a onClick={() => console.log(record)}>
+        <a key={'enabled'} onClick={() => console.log(record)}>
           <Tooltip
             title={intl.formatMessage({
               id: 'pages.ruleEngine.option.start',
@@ -86,7 +80,7 @@ const Instance = () => {
             <CaretRightOutlined />
           </Tooltip>
         </a>,
-        <a onClick={() => console.log(record)}>
+        <a key={'reload'} onClick={() => console.log(record)}>
           <Tooltip
             title={intl.formatMessage({
               id: 'pages.ruleEngine.option.restart',
@@ -97,7 +91,7 @@ const Instance = () => {
           </Tooltip>
         </a>,
 
-        <a>
+        <a key={'delete'}>
           <Tooltip
             title={intl.formatMessage({
               id: 'pages.data.option.remove',
@@ -111,13 +105,52 @@ const Instance = () => {
     },
   ];
 
-  const schema = {};
+  const schema: ISchema = {
+    type: 'object',
+    properties: {
+      name: {
+        title: intl.formatMessage({
+          id: 'pages.table.name',
+          defaultMessage: '名称',
+        }),
+        type: 'string',
+        'x-decorator': 'FormItem',
+        'x-component': 'Input',
+        name: 'name',
+        'x-validator': [
+          {
+            max: 64,
+            message: '最多可输入64个字符',
+          },
+          {
+            required: true,
+            message: '请输入名称',
+          },
+        ],
+      },
+      description: {
+        title: '说明',
+        'x-decorator': 'FormItem',
+        'x-component': 'Input.TextArea',
+        'x-component-props': {
+          rows: 5,
+        },
+        'x-validator': [
+          {
+            max: 200,
+            message: '最多可输入200个字符',
+          },
+        ],
+      },
+    },
+  };
 
   return (
     <PageContainer>
       <BaseCrud
         columns={columns}
         service={service}
+        search={false}
         title={intl.formatMessage({
           id: 'pages.ruleEngine.instance',
           defaultMessage: '规则实例',

+ 60 - 27
src/pages/system/Role/Detail/Permission/Allocate/MenuPermission.tsx

@@ -1,5 +1,5 @@
 import { CaretDownOutlined, QuestionCircleOutlined } from '@ant-design/icons';
-import { Checkbox, Radio, Tooltip } from 'antd';
+import { Checkbox, Radio, Select, Tooltip } from 'antd';
 import type { CheckboxValueType } from 'antd/lib/checkbox/Group';
 import _ from 'lodash';
 import { useEffect, useState } from 'react';
@@ -8,7 +8,9 @@ interface Props {
   value: any;
   check?: boolean;
   level?: number;
+  assetsList?: any[];
   change: (data: any) => void;
+  checkChange?: (data: any) => void;
 }
 
 const MenuPermission = (props: Props) => {
@@ -16,11 +18,16 @@ const MenuPermission = (props: Props) => {
   const [checkAll, setCheckAll] = useState<boolean>(props.value?.check === 1);
   const [visible, setVisible] = useState<boolean>(value.id === 'menu-permission');
   const [indeterminate, setIndeterminate] = useState<boolean>(props.value?.check === 2);
+  const [checkbox, setCheckbox] = useState<boolean>(false);
+  const [checkValue, setCheckValue] = useState<string>('');
 
   useEffect(() => {
     setValue(props.value);
     setCheckAll(props.value?.check === 1);
     setIndeterminate(props.value?.check === 2);
+    const val =
+      (props.value?.assetAccesses || []).filter((i: any) => i?.granted)[0]?.supportId || '';
+    setCheckValue(val);
   }, [props.value]);
 
   const checkAllData: any = (data: any[], check: boolean) => {
@@ -29,7 +36,7 @@ const MenuPermission = (props: Props) => {
         const buttons = (item?.buttons || []).map((i: any) => {
           return {
             ...i,
-            enabled: check,
+            granted: check,
           };
         });
         return {
@@ -52,6 +59,7 @@ const MenuPermission = (props: Props) => {
           paddingLeft: (props?.level || 0) * 10,
           transition: 'background .3s',
           borderBottom: '1px solid #f0f0f0',
+          height: 50,
         }}
         key={value?.id}
       >
@@ -96,7 +104,7 @@ const MenuPermission = (props: Props) => {
                 const buttons = (value?.buttons || []).map((i: any) => {
                   return {
                     ...i,
-                    enabled: e.target.checked,
+                    granted: e.target.checked,
                   };
                 });
                 props.change({
@@ -113,20 +121,20 @@ const MenuPermission = (props: Props) => {
           <div>
             {value.id === 'menu-permission' ? (
               <span style={{ fontWeight: value.id === 'menu-permission' ? 600 : 400 }}>
-                权限数据
+                操作权限
               </span>
             ) : (
               <Checkbox.Group
                 name={value?.id}
                 value={_.map(
-                  (value?.buttons || []).filter((i: any) => i?.enabled),
+                  (value?.buttons || []).filter((i: any) => i?.granted),
                   'id',
                 )}
                 onChange={(data: CheckboxValueType[]) => {
                   const buttons = value.buttons.map((i: any) => {
                     return {
                       ...i,
-                      enabled: data.includes(i.id),
+                      granted: data.includes(i.id),
                     };
                   });
                   const clen = (value?.children || []).filter((i: any) => i.check !== 3).length;
@@ -164,36 +172,61 @@ const MenuPermission = (props: Props) => {
           }}
         >
           {value.id === 'menu-permission' ? (
-            <span style={{ fontWeight: value.id === 'menu-permission' ? 600 : 400 }}>
-              数据权限
-              <Tooltip title="勾选任意数据权限均能看到自己创建的数据权限">
-                <QuestionCircleOutlined />
-              </Tooltip>
-            </span>
+            <div style={{ display: 'flex', alignItems: 'center' }}>
+              <span style={{ fontWeight: value.id === 'menu-permission' ? 600 : 400 }}>
+                数据权限
+                <Tooltip title="勾选任意数据权限均能看到自己创建的数据权限">
+                  <QuestionCircleOutlined />
+                </Tooltip>
+              </span>
+              <Checkbox
+                checked={checkbox}
+                style={{ margin: '0 10px' }}
+                onChange={(e) => {
+                  setCheckbox(e.target.checked);
+                  setCheckValue('');
+                }}
+              >
+                批量设置
+              </Checkbox>
+              {checkbox && (
+                <Select
+                  showSearch
+                  placeholder="请选择"
+                  optionFilterProp="children"
+                  style={{ width: 200 }}
+                  onChange={(val: string) => {
+                    setCheckValue(val);
+                    if (props.checkChange) {
+                      props.checkChange(val);
+                    }
+                  }}
+                  filterOption={(input: any, option: any) =>
+                    (option?.children || '').toLowerCase().indexOf(input.toLowerCase()) >= 0
+                  }
+                >
+                  {(props?.assetsList || []).map((item) => (
+                    <Select.Option key={`${item?.supportId}`} value={item?.supportId}>
+                      {item?.name}
+                    </Select.Option>
+                  ))}
+                </Select>
+              )}
+            </div>
           ) : (
             <div>
-              {value?.accessSupport?.value === 'unsupported' ? (
+              {value?.accessSupport?.value !== 'support' ? (
                 <div>{value?.accessDescription}</div>
               ) : (
                 <Radio.Group
                   defaultValue={value?.assetAccesses[0]?.supportId}
-                  value={
-                    _.map(
-                      (value?.assetAccesses || []).filter((i: any) => i?.enabled),
-                      'supportId',
-                    )[0]
-                  }
+                  value={checkValue}
                   onChange={(e) => {
+                    setCheckValue(e.target.value);
                     const access = (value?.assetAccesses || []).map((i: any) => {
-                      if (i.supportId === e.target.value) {
-                        return {
-                          ...i,
-                          enabled: true,
-                        };
-                      }
                       return {
                         ...i,
-                        enabled: false,
+                        granted: i.supportId === e.target.value,
                       };
                     });
                     const d = {
@@ -230,7 +263,7 @@ const MenuPermission = (props: Props) => {
                 });
                 let check: number = 3;
                 const blen = value.buttons?.length || 0;
-                const bblen = (value?.buttons || []).filter((i: any) => i.enabled).length || 0;
+                const bblen = (value?.buttons || []).filter((i: any) => i.granted).length || 0;
                 const clen = children.length || 0;
                 const cclen = (children || []).filter((i: any) => i.check !== 3).length || 0;
                 const cclen1 = (children || []).filter((i: any) => i.check === 1).length || 0;

+ 52 - 0
src/pages/system/Role/Detail/Permission/Allocate/index.tsx

@@ -1,3 +1,5 @@
+import { flattenArray } from '@/utils/util';
+import _ from 'lodash';
 import { useEffect, useState } from 'react';
 import MenuPermission from './MenuPermission';
 
@@ -13,6 +15,7 @@ const Allocate = (props: Props) => {
     name: '菜单权限',
     children: [],
   });
+  const [assetsList, setAssetsList] = useState<any[]>([]);
 
   const getDataList: any = (data1: any[]) => {
     if (Array.isArray(data1) && data1.length > 0) {
@@ -44,8 +47,24 @@ const Allocate = (props: Props) => {
     return [];
   };
 
+  const deRepeat = (arr: any[]) => {
+    const list = new Map();
+    arr.forEach((item) => {
+      list.set(item.supportId, item);
+    });
+    return [...list.values()];
+  };
+
   useEffect(() => {
     if (props?.value) {
+      const list =
+        flattenArray(props.value.children).filter(
+          (item: any) =>
+            item?.accessSupport?.value !== 'unsupported' &&
+            item?.assetAccesses &&
+            item?.assetAccesses?.length > 0,
+        ) || [];
+      setAssetsList(deRepeat(_.flatten(_.map(list, 'assetAccesses') || []) || []) || []);
       if (!props.value?.check) {
         const children = getDataList(props.value?.children || []) || [];
         let check: number = 3;
@@ -73,6 +92,28 @@ const Allocate = (props: Props) => {
     }
   }, [props.value]);
 
+  const getAccessData: any = (arr: any[], str: string) => {
+    if (Array.isArray(arr) && arr.length > 0) {
+      return arr.map((item) => {
+        let li: any[] = [];
+        if (item?.assetAccesses.length > 0) {
+          li = item.assetAccesses.map((i: any) => {
+            return {
+              ...i,
+              granted: i.supportId === str,
+            };
+          });
+        }
+        return {
+          ...item,
+          assetAccesses: li,
+          children: item?.children ? getAccessData(item.children, str) : [],
+        };
+      });
+    }
+    return [];
+  };
+
   return (
     <div style={{ border: '1px solid #f0f0f0', paddingBottom: 10 }}>
       <div style={{ overflowY: 'scroll', maxHeight: '500px' }}>
@@ -80,6 +121,17 @@ const Allocate = (props: Props) => {
           key={'menu-permission'}
           value={dataSource}
           level={1}
+          assetsList={assetsList}
+          checkChange={(data: any) => {
+            const dt = {
+              ...dataSource,
+              children: getAccessData(dataSource.children || [], data),
+            };
+            setDataSource(dt);
+            if (props.onChange) {
+              props.onChange(dt);
+            }
+          }}
           change={(data: any) => {
             setDataSource(data);
             if (props.onChange) {

+ 58 - 75
src/pages/system/Role/Detail/Permission/index.tsx

@@ -1,15 +1,18 @@
-import { Button, Card, Col, Form, Input, message, Row } from 'antd';
+import { Button, Card, Col, Form, Input, message, Row, Spin } from 'antd';
 import Allocate from '@/pages/system/Role/Detail/Permission/Allocate';
 import { useEffect, useState } from 'react';
 import { history, useParams } from 'umi';
 import { service } from '@/pages/system/Role';
 import styles from './index.less';
+import { flattenArray } from '@/utils/util';
 
 const Permission = () => {
   const params = useParams<{ id: string }>();
   const [form] = Form.useForm();
   const [data, setData] = useState<RoleItem>();
+  const [spinning, setSpinning] = useState<boolean>(true);
   const getDetail = async (id: string) => {
+    setSpinning(true);
     const res = await service.detail(id);
     if (res.status === 200) {
       setData(res.result);
@@ -25,6 +28,7 @@ const Permission = () => {
             },
           });
         }
+        setSpinning(false);
       });
     }
   };
@@ -38,29 +42,6 @@ const Permission = () => {
     }
   }, [params, params.id]);
 
-  // const getDataList: any = (data1: any[]) => {
-  //   if (Array.isArray(data1) && data1.length > 0) {
-  //     return data1.map((item) => {
-  //       const check = item.check;
-  //       delete item.check;
-  //       return {
-  //         ...item,
-  //         granted: check === 1 || check === 2,
-  //         children: item?.children ? getDataList(item.children) : [],
-  //       };
-  //     });
-  //   }
-  //   return [];
-  // };
-  /**
-   * 扁平化树数组
-   */
-  const flattenArray: any = (arr: any[]) => {
-    return arr.reduce((result, item) => {
-      return result.concat(item, Array.isArray(item.children) ? flattenArray(item.children) : []);
-    }, []);
-  };
-
   const getDataList: any = (data1: any[]) => {
     if (Array.isArray(data1) && data1.length > 0) {
       return data1.map((item) => {
@@ -77,58 +58,60 @@ const Permission = () => {
   };
 
   return (
-    <Form
-      layout="vertical"
-      form={form}
-      onFinish={async (values: any) => {
-        await service.update({
-          ...data,
-          name: values?.name,
-          description: values?.description || '',
-        });
-        const list = getDataList(flattenArray([...values.permission?.children]) || []) || [];
-        service
-          .saveGrantTree('role', params?.id, {
-            menus: list.filter((item: any) => item.granted) || [],
-          })
-          .subscribe((resp) => {
-            if (resp.status === 200) {
-              message.success('操作成功');
-            }
+    <Spin spinning={spinning}>
+      <Form
+        layout="vertical"
+        form={form}
+        onFinish={async (values: any) => {
+          await service.update({
+            ...data,
+            name: values?.name,
+            description: values?.description || '',
           });
-      }}
-    >
-      <Card>
-        <div className={styles.title}>基本信息</div>
-        <Row>
-          <Col span={14}>
-            <Form.Item
-              label="名称"
-              name="name"
-              rules={[{ required: true, message: '请输入名称!' }]}
-            >
-              <Input />
-            </Form.Item>
-          </Col>
-          <Col span={14}>
-            <Form.Item label="说明" name="description">
-              <Input.TextArea showCount maxLength={200} />
-            </Form.Item>
-          </Col>
-        </Row>
-      </Card>
-      <Card style={{ marginTop: 20 }}>
-        <div className={styles.title}>权限分配</div>
-        <Form.Item name="permission" rules={[{ required: true }]}>
-          <Allocate />
-        </Form.Item>
-        <Form.Item>
-          <Button type="primary" htmlType="submit">
-            保存
-          </Button>
-        </Form.Item>
-      </Card>
-    </Form>
+          const list = getDataList(flattenArray([...values.permission?.children]) || []) || [];
+          service
+            .saveGrantTree('role', params?.id, {
+              menus: list.filter((item: any) => item.granted) || [],
+            })
+            .subscribe((resp) => {
+              if (resp.status === 200) {
+                message.success('操作成功');
+              }
+            });
+        }}
+      >
+        <Card>
+          <div className={styles.title}>基本信息</div>
+          <Row>
+            <Col span={14}>
+              <Form.Item
+                label="名称"
+                name="name"
+                rules={[{ required: true, message: '请输入名称!' }]}
+              >
+                <Input />
+              </Form.Item>
+            </Col>
+            <Col span={14}>
+              <Form.Item label="说明" name="description">
+                <Input.TextArea showCount maxLength={200} />
+              </Form.Item>
+            </Col>
+          </Row>
+        </Card>
+        <Card style={{ marginTop: 20 }}>
+          <div className={styles.title}>权限分配</div>
+          <Form.Item name="permission" rules={[{ required: true }]}>
+            <Allocate />
+          </Form.Item>
+          <Form.Item>
+            <Button type="primary" htmlType="submit">
+              保存
+            </Button>
+          </Form.Item>
+        </Card>
+      </Form>
+    </Spin>
   );
 };
 

+ 9 - 0
src/utils/util.ts

@@ -71,3 +71,12 @@ export const getDateFormat = (
 ): string => {
   return date ? moment(date).format(format) : '-';
 };
+
+/**
+ * 扁平化树数组
+ */
+export const flattenArray: any = (arr: any[]) => {
+  return arr.reduce((result, item) => {
+    return result.concat(item, Array.isArray(item.children) ? flattenArray(item.children) : []);
+  }, []);
+};