فهرست منبع

fix(merge): merge menu

xieyonghong 4 سال پیش
والد
کامیت
c965e9d932
27فایلهای تغییر یافته به همراه474 افزوده شده و 454 حذف شده
  1. 2 2
      package.json
  2. 23 12
      src/components/BaseCrud/index.tsx
  3. 1 0
      src/components/BaseCrud/save/index.tsx
  4. 1 1
      src/components/BindUser/index.tsx
  5. 22 0
      src/components/SearchComponent/index.less
  6. 152 85
      src/components/SearchComponent/index.tsx
  7. 2 2
      src/components/SearchComponent/typings.d.ts
  8. 1 1
      src/pages/device/Instance/Detail/MetadataLog/Property/index.tsx
  9. 50 37
      src/pages/device/Product/Save/index.tsx
  10. 6 0
      src/pages/device/components/Metadata/Base/Edit/index.tsx
  11. 1 7
      src/pages/system/Department/Assets/deivce/bind.tsx
  12. 21 42
      src/pages/system/Department/Assets/deivce/index.tsx
  13. 1 1
      src/pages/system/Department/Assets/permissionModal.tsx
  14. 1 1
      src/pages/system/Department/Assets/product/bind.tsx
  15. 19 35
      src/pages/system/Department/Assets/product/index.tsx
  16. 1 1
      src/pages/system/Department/Assets/productCategory/bind.tsx
  17. 19 35
      src/pages/system/Department/Assets/productCategory/index.tsx
  18. 6 4
      src/pages/system/Department/Member/bind.tsx
  19. 12 16
      src/pages/system/Department/Member/index.tsx
  20. 23 15
      src/pages/system/Department/index.tsx
  21. 9 4
      src/pages/system/Department/save.tsx
  22. 38 69
      src/pages/system/Permission/index.tsx
  23. 1 1
      src/pages/system/Role/Edit/UserManage/BindUser.tsx
  24. 1 1
      src/pages/system/Role/Edit/UserManage/index.tsx
  25. 16 50
      src/pages/system/Role/index.tsx
  26. 11 6
      src/pages/system/User/Save/index.tsx
  27. 34 26
      src/pages/system/User/index.tsx

+ 2 - 2
package.json

@@ -70,10 +70,10 @@
     "@formily/reactive-react": "2.0.0-rc.17",
     "@formily/reactive-react": "2.0.0-rc.17",
     "@formily/shared": "2.0.0-rc.17",
     "@formily/shared": "2.0.0-rc.17",
     "@jetlinks/pro-list": "^1.10.8",
     "@jetlinks/pro-list": "^1.10.8",
-    "@jetlinks/pro-table": "^2.63.9",
+    "@jetlinks/pro-table": "^2.63.10",
     "@umijs/route-utils": "^1.0.36",
     "@umijs/route-utils": "^1.0.36",
     "ahooks": "^2.10.9",
     "ahooks": "^2.10.9",
-    "antd": "^4.17.0-alpha.9",
+    "antd": "^4.18.8",
     "braft-editor": "^2.3.9",
     "braft-editor": "^2.3.9",
     "classnames": "^2.2.6",
     "classnames": "^2.2.6",
     "dexie": "^3.0.3",
     "dexie": "^3.0.3",

+ 23 - 12
src/components/BaseCrud/index.tsx

@@ -1,5 +1,5 @@
 import { useIntl } from '@@/plugin-locale/localeExports';
 import { useIntl } from '@@/plugin-locale/localeExports';
-import { Button, Card, Divider, Dropdown } from 'antd';
+import { Button, Dropdown } from 'antd';
 import ProTable from '@jetlinks/pro-table';
 import ProTable from '@jetlinks/pro-table';
 import type { ProColumns, ActionType, RequestData } from '@jetlinks/pro-table';
 import type { ProColumns, ActionType, RequestData } from '@jetlinks/pro-table';
 
 
@@ -73,23 +73,34 @@ const BaseCrud = <T extends Record<string, any>>(props: Props<T>) => {
   const [param, setParam] = useState({});
   const [param, setParam] = useState({});
   return (
   return (
     <>
     <>
-      <Card>
-        <SearchComponent<T>
-          field={columns}
-          onSearch={async (data) => {
-            setParam({ terms: data });
-          }}
-          target={moduleName}
-        />
-      </Card>
-      <Divider />
+      <SearchComponent<T>
+        field={columns}
+        onSearch={async (data) => {
+          // actionRef.current?.reset?.();
+          actionRef.current?.setPageInfo?.({ pageSize: 10 });
+          setParam(data);
+        }}
+        target={moduleName}
+        onReset={() => {
+          // 重置分页及搜索参数
+          actionRef.current?.reset?.();
+          setParam({});
+        }}
+      />
       <ProTable<T>
       <ProTable<T>
         params={param}
         params={param}
         formRef={ref}
         formRef={ref}
         columns={columns}
         columns={columns}
         actionRef={actionRef}
         actionRef={actionRef}
         options={{ fullScreen: true }}
         options={{ fullScreen: true }}
-        request={request || (async (params = {}) => service.query(params))}
+        request={
+          request ||
+          (async (params = {}) =>
+            service.query({
+              ...params,
+              sorts: [{ name: 'createTime', order: 'desc' }], // 默认排序
+            }))
+        }
         editable={{
         editable={{
           type: 'multiple',
           type: 'multiple',
         }}
         }}

+ 1 - 0
src/components/BaseCrud/save/index.tsx

@@ -125,6 +125,7 @@ const Save = <T extends Record<string, any>>(props: Props<T>) => {
         id: `pages.data.option.${model}`,
         id: `pages.data.option.${model}`,
         defaultMessage: '编辑',
         defaultMessage: '编辑',
       })}
       })}
+      maskClosable={false}
       visible={visible}
       visible={visible}
       onCancel={CurdModel.close}
       onCancel={CurdModel.close}
       onOk={save}
       onOk={save}

+ 1 - 1
src/components/BindUser/index.tsx

@@ -17,7 +17,7 @@ export const columns: ProColumns<UserItem>[] = [
   {
   {
     title: '姓名',
     title: '姓名',
     dataIndex: 'name',
     dataIndex: 'name',
-    copyable: true,
+    // copyable: true,
     ellipsis: true,
     ellipsis: true,
     align: 'center',
     align: 'center',
   },
   },

+ 22 - 0
src/components/SearchComponent/index.less

@@ -3,6 +3,28 @@
   align-items: center;
   align-items: center;
 }
 }
 
 
+.simple {
+  display: flex;
+  flex-direction: row;
+
+  :global {
+    .ant-formily-grid-layout {
+      width: 550px;
+      height: 40px;
+    }
+  }
+}
+
+.history {
+  width: 176px;
+  .list {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    width: 148px;
+  }
+}
+
 .saveLog {
 .saveLog {
   width: 100%;
   width: 100%;
   margin-top: 5px;
   margin-top: 5px;

+ 152 - 85
src/components/SearchComponent/index.tsx

@@ -8,15 +8,27 @@ import {
   FormItem,
   FormItem,
   FormTab,
   FormTab,
   Input,
   Input,
+  NumberPicker,
   PreviewText,
   PreviewText,
   Select,
   Select,
+  Space,
 } from '@formily/antd';
 } from '@formily/antd';
 import type { Field } from '@formily/core';
 import type { Field } from '@formily/core';
 import { createForm, onFieldReact } from '@formily/core';
 import { createForm, onFieldReact } from '@formily/core';
 import GroupNameControl from '@/components/SearchComponent/GroupNameControl';
 import GroupNameControl from '@/components/SearchComponent/GroupNameControl';
 import { DeleteOutlined, DoubleRightOutlined } from '@ant-design/icons';
 import { DeleteOutlined, DoubleRightOutlined } from '@ant-design/icons';
-import { Button, Dropdown, Empty, Menu, message, Popconfirm, Popover, Typography } from 'antd';
-import { useState } from 'react';
+import {
+  Button,
+  Card,
+  Dropdown,
+  Empty,
+  Menu,
+  message,
+  Popconfirm,
+  Popover,
+  Typography,
+} from 'antd';
+import { useEffect, useMemo, useState } from 'react';
 import type { ProColumns } from '@jetlinks/pro-table';
 import type { ProColumns } from '@jetlinks/pro-table';
 import type { EnumData } from '@/utils/typings';
 import type { EnumData } from '@/utils/typings';
 import styles from './index.less';
 import styles from './index.less';
@@ -31,15 +43,19 @@ const ui2Server = (source: SearchTermsUI): SearchTermsServer => [
 
 
 const server2Ui = (source: SearchTermsServer): SearchTermsUI => ({
 const server2Ui = (source: SearchTermsServer): SearchTermsUI => ({
   terms1: source[0].terms,
   terms1: source[0].terms,
-  terms2: source[1].terms,
-  type: source[0].type || 'and',
+  terms2: source[1]?.terms,
+  type: source[0]?.type || 'and',
 });
 });
 
 
 interface Props<T> {
 interface Props<T> {
+  /** @name 搜索条件 */
   field: ProColumns<T>[];
   field: ProColumns<T>[];
-  onSearch: (params: any) => void;
+  onSearch: (params: { terms: SearchTermsServer }) => void;
   target?: string;
   target?: string;
   onReset?: () => void;
   onReset?: () => void;
+  /** @name 固定查询参数*/
+  defaultParam?: Term[];
+  pattern?: 'simple' | 'advance';
 }
 }
 
 
 const termType = [
 const termType = [
@@ -56,48 +72,78 @@ const termType = [
 ];
 ];
 
 
 const service = new Service();
 const service = new Service();
-const defaultTerm = { termType: 'like' };
+const initTerm = { termType: 'like' };
+const SchemaField = createSchemaField({
+  components: {
+    FormItem,
+    FormTab,
+    Input,
+    Select,
+    NumberPicker,
+    FormGrid,
+    ArrayItems,
+    PreviewText,
+    GroupNameControl,
+    Space,
+  },
+});
 
 
-const SearchComponent = <T extends Record<string, any>>({
-  field,
-  onSearch,
-  target,
-  onReset,
-}: Props<T>) => {
+const SearchComponent = <T extends Record<string, any>>(props: Props<T>) => {
+  const { field, target, onReset, onSearch, defaultParam, pattern = 'advance' } = props;
   const intl = useIntl();
   const intl = useIntl();
   const [expand, setExpand] = useState<boolean>(true);
   const [expand, setExpand] = useState<boolean>(true);
-  const initForm = server2Ui([{ terms: [defaultTerm], type: 'and' }, { terms: [defaultTerm] }]);
+  const initForm = server2Ui(
+    pattern === 'advance'
+      ? [
+          {
+            terms: [initTerm],
+            type: 'and',
+          },
+          { terms: [initTerm] },
+        ]
+      : [{ terms: [initTerm] }],
+  );
   const [logVisible, setLogVisible] = useState<boolean>(false);
   const [logVisible, setLogVisible] = useState<boolean>(false);
   const [aliasVisible, setAliasVisible] = useState<boolean>(false);
   const [aliasVisible, setAliasVisible] = useState<boolean>(false);
   const [initParams, setInitParams] = useState<SearchTermsUI>(initForm);
   const [initParams, setInitParams] = useState<SearchTermsUI>(initForm);
   const [history, setHistory] = useState([]);
   const [history, setHistory] = useState([]);
 
 
-  const form = createForm<SearchTermsUI>({
-    validateFirst: true,
-    initialValues: initParams,
-    effects() {
-      onFieldReact('*.*.column', (typeFiled, f) => {
-        const _column = (typeFiled as Field).value;
-        const _field = field.find((item) => item.dataIndex === _column);
-        if (_field?.valueType === 'select') {
-          const option = Object.values(_field?.valueEnum || {}).map((item) => ({
-            label: item.text,
-            value: item.status,
-          }));
-
-          f.setFieldState(typeFiled.query('.termType'), async (state) => {
-            state.value = 'eq';
+  const form = useMemo(
+    () =>
+      createForm<SearchTermsUI>({
+        validateFirst: true,
+        initialValues: initParams,
+        effects() {
+          onFieldReact('*.*.column', (typeFiled, f) => {
+            const _column = (typeFiled as Field).value;
+            const _field = field.find((item) => item.dataIndex === _column);
+            if (_field?.valueType === 'select') {
+              const option = Object.values(_field?.valueEnum || {}).map((item) => ({
+                label: item.text,
+                value: item.status,
+              }));
+              f.setFieldState(typeFiled.query('.termType'), async (state) => {
+                state.value = 'eq';
+              });
+              f.setFieldState(typeFiled.query('.value'), async (state) => {
+                state.componentType = 'Select';
+                state.loading = true;
+                state.dataSource = option;
+                state.loading = false;
+              });
+            } else if (_field?.valueType === 'digit') {
+              f.setFieldState(typeFiled.query('.value'), async (state) => {
+                state.componentType = 'NumberPicker';
+              });
+              f.setFieldState(typeFiled.query('.termType'), async (state) => {
+                state.value = 'eq';
+              });
+            }
           });
           });
-          f.setFieldState(typeFiled.query('.value'), async (state) => {
-            state.componentType = 'Select';
-            state.loading = true;
-            state.dataSource = option;
-            state.loading = false;
-          });
-        }
-      });
-    },
-  });
+        },
+      }),
+    [expand],
+  );
 
 
   const historyForm = createForm();
   const historyForm = createForm();
 
 
@@ -114,24 +160,12 @@ const SearchComponent = <T extends Record<string, any>>({
       value.terms1.splice(1, 2);
       value.terms1.splice(1, 2);
       value.terms2.splice(1, 2);
       value.terms2.splice(1, 2);
     } else {
     } else {
-      value.terms2.push(defaultTerm, defaultTerm);
-      value.terms1.push(defaultTerm, defaultTerm);
+      value.terms2.push(initTerm, initTerm);
+      value.terms1.push(initTerm, initTerm);
     }
     }
     setInitParams(value);
     setInitParams(value);
     setExpand(!expand);
     setExpand(!expand);
   };
   };
-  const SchemaField = createSchemaField({
-    components: {
-      FormItem,
-      FormTab,
-      Input,
-      Select,
-      FormGrid,
-      ArrayItems,
-      PreviewText,
-      GroupNameControl,
-    },
-  });
 
 
   const filterSearchTerm = (): EnumData[] =>
   const filterSearchTerm = (): EnumData[] =>
     field
     field
@@ -164,6 +198,7 @@ const SearchComponent = <T extends Record<string, any>>({
           'x-component-props': {
           'x-component-props': {
             name: name,
             name: name,
           },
           },
+          'x-visible': pattern === 'advance',
         },
         },
         column: {
         column: {
           type: 'string',
           type: 'string',
@@ -234,28 +269,28 @@ const SearchComponent = <T extends Record<string, any>>({
     },
     },
   };
   };
 
 
+  const simpleSchema: ISchema = {
+    type: 'object',
+    properties: {
+      terms1: createGroup('第一组'),
+    },
+  };
   const handleHistory = (item: SearchHistory) => {
   const handleHistory = (item: SearchHistory) => {
     const log = JSON.parse(item.content) as SearchTermsUI;
     const log = JSON.parse(item.content) as SearchTermsUI;
     form.setValues(log);
     form.setValues(log);
     setExpand(!(log.terms1?.length > 1 || log.terms2?.length > 1));
     setExpand(!(log.terms1?.length > 1 || log.terms2?.length > 1));
-    setInitParams(log);
   };
   };
+
   const historyDom = (
   const historyDom = (
-    <Menu style={{ width: '176px' }}>
+    <Menu className={styles.history}>
       {history.length > 0 ? (
       {history.length > 0 ? (
         history.map((item: SearchHistory) => (
         history.map((item: SearchHistory) => (
           <Menu.Item onClick={() => handleHistory(item)} key={item.id}>
           <Menu.Item onClick={() => handleHistory(item)} key={item.id}>
-            <div
-              style={{
-                display: 'flex',
-                justifyContent: 'space-between',
-                alignItems: 'center',
-                width: '148px',
-              }}
-            >
+            <div className={styles.list}>
               <Typography.Text ellipsis={{ tooltip: item.name }}>{item.name}</Typography.Text>
               <Typography.Text ellipsis={{ tooltip: item.name }}>{item.name}</Typography.Text>
               <Popconfirm
               <Popconfirm
-                onConfirm={async () => {
+                onConfirm={async (e) => {
+                  e?.stopPropagation();
                   const response = await service.history.remove(`${target}-search`, item.key);
                   const response = await service.history.remove(`${target}-search`, item.key);
                   if (response.status === 200) {
                   if (response.status === 200) {
                     message.success('操作成功');
                     message.success('操作成功');
@@ -265,7 +300,7 @@ const SearchComponent = <T extends Record<string, any>>({
                 }}
                 }}
                 title={'确认删除吗?'}
                 title={'确认删除吗?'}
               >
               >
-                <DeleteOutlined />
+                <DeleteOutlined onClick={(e) => e.stopPropagation()} />
               </Popconfirm>
               </Popconfirm>
             </div>
             </div>
           </Menu.Item>
           </Menu.Item>
@@ -289,7 +324,7 @@ const SearchComponent = <T extends Record<string, any>>({
 
 
   const formatValue = (value: SearchTermsUI): SearchTermsServer =>
   const formatValue = (value: SearchTermsUI): SearchTermsServer =>
     ui2Server(value).map((term) => {
     ui2Server(value).map((term) => {
-      term.terms.map((item) => {
+      term.terms?.map((item) => {
         if (item.termType === 'like') {
         if (item.termType === 'like') {
           item.value = `%${item.value}%`;
           item.value = `%${item.value}%`;
           return item;
           return item;
@@ -301,15 +336,23 @@ const SearchComponent = <T extends Record<string, any>>({
 
 
   const handleSearch = async () => {
   const handleSearch = async () => {
     const value = form.values;
     const value = form.values;
-    setInitParams(value);
     const filterTerms = (data: Partial<Term>[]) =>
     const filterTerms = (data: Partial<Term>[]) =>
-      data.filter((item) => item.column != null).filter((item) => item.value != null);
-    const temp = _.cloneDeep(value);
-    temp.terms1 = filterTerms(temp.terms1);
-    temp.terms2 = filterTerms(temp.terms2);
-    onSearch(formatValue(temp));
+      data && data.filter((item) => item.column != null).filter((item) => item.value != null);
+    const _terms = _.cloneDeep(value);
+    _terms.terms1 = filterTerms(_terms.terms1);
+    _terms.terms2 = filterTerms(_terms.terms2);
+    if (defaultParam) {
+      _terms.terms1 = _terms.terms1.concat(defaultParam);
+    }
+    onSearch({ terms: formatValue(_terms) });
   };
   };
 
 
+  useEffect(() => {
+    if (defaultParam) {
+      handleSearch();
+    }
+  }, []);
+
   const handleSaveLog = async () => {
   const handleSaveLog = async () => {
     const value = await form.submit<SearchTermsUI>();
     const value = await form.submit<SearchTermsUI>();
     const value2 = await historyForm.submit<{ alias: string }>();
     const value2 = await historyForm.submit<{ alias: string }>();
@@ -327,15 +370,17 @@ const SearchComponent = <T extends Record<string, any>>({
 
 
   const resetForm = async () => {
   const resetForm = async () => {
     const temp = initForm;
     const temp = initForm;
-    temp.terms1 = temp.terms1.map(() => defaultTerm);
-    temp.terms2 = temp.terms2.map(() => defaultTerm);
-    setInitParams(temp);
+    const expandData = Array(expand ? 1 : 3).fill(initTerm);
+    temp.terms1 = expandData;
+    temp.terms2 = expandData;
+    // setInitParams(temp);
     await form.reset();
     await form.reset();
     onReset?.();
     onReset?.();
   };
   };
-  return (
-    <div>
-      <Form form={form} labelCol={4} wrapperCol={18}>
+
+  const renderAdvance = () => {
+    return (
+      <>
         <SchemaField schema={schema} />
         <SchemaField schema={schema} />
         <div className={styles.action}>
         <div className={styles.action}>
           <FormButtonGroup.FormItem labelCol={10} wrapperCol={14}>
           <FormButtonGroup.FormItem labelCol={10} wrapperCol={14}>
@@ -346,8 +391,6 @@ const SearchComponent = <T extends Record<string, any>>({
               visible={logVisible}
               visible={logVisible}
               onVisibleChange={async (visible) => {
               onVisibleChange={async (visible) => {
                 setLogVisible(visible);
                 setLogVisible(visible);
-                const value = form.values;
-                setInitParams(value);
                 if (visible) {
                 if (visible) {
                   await queryHistory();
                   await queryHistory();
                 }
                 }
@@ -367,7 +410,12 @@ const SearchComponent = <T extends Record<string, any>>({
                         alias: {
                         alias: {
                           'x-decorator': 'FormItem',
                           'x-decorator': 'FormItem',
                           'x-component': 'Input.TextArea',
                           'x-component': 'Input.TextArea',
-                          maxLength: 50,
+                          'x-validator': [
+                            {
+                              max: 50,
+                              message: '最多可输入50个字符',
+                            },
+                          ],
                         },
                         },
                       },
                       },
                     }}
                     }}
@@ -378,10 +426,7 @@ const SearchComponent = <T extends Record<string, any>>({
                 </Form>
                 </Form>
               }
               }
               visible={aliasVisible}
               visible={aliasVisible}
-              onVisibleChange={(visible) => {
-                setInitParams(form.values);
-                setAliasVisible(visible);
-              }}
+              onVisibleChange={setAliasVisible}
               title="搜索名称"
               title="搜索名称"
               trigger="click"
               trigger="click"
             >
             >
@@ -404,8 +449,30 @@ const SearchComponent = <T extends Record<string, any>>({
             />
             />
           </div>
           </div>
         </div>
         </div>
+      </>
+    );
+  };
+  const renderSimple = () => {
+    return (
+      <div className={styles.simple}>
+        <SchemaField schema={simpleSchema} />
+        <FormButtonGroup.FormItem labelCol={0} wrapperCol={14}>
+          <Button onClick={handleSearch} type="primary">
+            搜索
+          </Button>
+          <Button block onClick={resetForm}>
+            重置
+          </Button>
+        </FormButtonGroup.FormItem>
+      </div>
+    );
+  };
+  return (
+    <Card bordered={false} style={{ marginBottom: '20px', borderBottom: '1px solid #f0f0f0' }}>
+      <Form form={form} className={styles.form} labelCol={4} wrapperCol={18}>
+        {pattern === 'advance' ? renderAdvance() : renderSimple()}
       </Form>
       </Form>
-    </div>
+    </Card>
   );
   );
 };
 };
 export default SearchComponent;
 export default SearchComponent;

+ 2 - 2
src/components/SearchComponent/typings.d.ts

@@ -1,7 +1,7 @@
 type Term = {
 type Term = {
   column: string | null;
   column: string | null;
-  value: string;
-  termType: string;
+  value: string | object;
+  termType?: string;
   type?: 'or' | 'and';
   type?: 'or' | 'and';
 };
 };
 
 

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

@@ -39,7 +39,7 @@ const PropertyLog = (props: Props) => {
           {
           {
             dataIndex: 'formatValue',
             dataIndex: 'formatValue',
             title: '数据',
             title: '数据',
-            copyable: true,
+            // copyable: true,
           },
           },
         ]}
         ]}
       />
       />

+ 50 - 37
src/pages/device/Product/Save/index.tsx

@@ -1,4 +1,4 @@
-import { Button, Drawer, message } from 'antd';
+import { message, Modal } from 'antd';
 import type { Field } from '@formily/core';
 import type { Field } from '@formily/core';
 import { createForm, onFieldValueChange } from '@formily/core';
 import { createForm, onFieldValueChange } from '@formily/core';
 import { TreeSelect, Form, FormItem, FormLayout, Input, Radio, Select } from '@formily/antd';
 import { TreeSelect, Form, FormItem, FormLayout, Input, Radio, Select } from '@formily/antd';
@@ -142,11 +142,24 @@ const Save = (props: Props) => {
             title: 'ID',
             title: 'ID',
             'x-component': 'Input',
             'x-component': 'Input',
             'x-decorator': 'FormItem',
             'x-decorator': 'FormItem',
+            'x-decorator-props': {
+              tooltip: <div>若不填写,系统将自动生成唯一ID</div>,
+            },
           },
           },
           name: {
           name: {
             title: '名称',
             title: '名称',
             'x-component': 'Input',
             'x-component': 'Input',
             'x-decorator': 'FormItem',
             'x-decorator': 'FormItem',
+            'x-validator': [
+              {
+                required: true,
+                message: '请输入名称',
+              },
+              {
+                max: 64,
+                message: '最多可输入64个字符',
+              },
+            ],
           },
           },
           classifiedId: {
           classifiedId: {
             title: '所属品类',
             title: '所属品类',
@@ -157,29 +170,29 @@ const Save = (props: Props) => {
             },
             },
             'x-reactions': ['{{useAsyncDataSource("classifiedId")}}'],
             'x-reactions': ['{{useAsyncDataSource("classifiedId")}}'],
           },
           },
-          orgId: {
-            title: '所属机构',
-            'x-component': 'Select',
-            'x-decorator': 'FormItem',
-            'x-reactions': ['{{useAsyncDataSource("org")}}'],
-          },
-          messageProtocol: {
-            title: '消息协议',
-            'x-component': 'Select',
-            'x-decorator': 'FormItem',
-            'x-reactions': ['{{useAsyncDataSource("protocol")}}'],
-          },
-          transportProtocol: {
-            title: '传输协议',
-            'x-component': 'Select',
-            'x-decorator': 'FormItem',
-          },
-          storePolicy: {
-            title: '存储策略',
-            'x-component': 'Select',
-            'x-decorator': 'FormItem',
-            'x-reactions': ['{{useAsyncDataSource("storePolicy")}}'],
-          },
+          // orgId: {
+          //   title: '所属机构',
+          //   'x-component': 'Select',
+          //   'x-decorator': 'FormItem',
+          //   'x-reactions': ['{{useAsyncDataSource("org")}}'],
+          // },
+          // messageProtocol: {
+          //   title: '消息协议',
+          //   'x-component': 'Select',
+          //   'x-decorator': 'FormItem',
+          //   'x-reactions': ['{{useAsyncDataSource("protocol")}}'],
+          // },
+          // transportProtocol: {
+          //   title: '传输协议',
+          //   'x-component': 'Select',
+          //   'x-decorator': 'FormItem',
+          // },
+          // storePolicy: {
+          //   title: '存储策略',
+          //   'x-component': 'Select',
+          //   'x-decorator': 'FormItem',
+          //   'x-reactions': ['{{useAsyncDataSource("storePolicy")}}'],
+          // },
           deviceType: {
           deviceType: {
             title: '设备类型',
             title: '设备类型',
             'x-component': 'Radio.Group',
             'x-component': 'Radio.Group',
@@ -189,32 +202,32 @@ const Save = (props: Props) => {
               { label: '网关子设备', value: 'childrenDevice' },
               { label: '网关子设备', value: 'childrenDevice' },
               { label: '网关设备', value: 'gateway' },
               { label: '网关设备', value: 'gateway' },
             ],
             ],
+            'x-validator': [
+              {
+                required: true,
+                message: '请选择设备类型',
+              },
+            ],
           },
           },
           describe: {
           describe: {
             title: '描述',
             title: '描述',
             'x-component': 'Input.TextArea',
             'x-component': 'Input.TextArea',
             'x-decorator': 'FormItem',
             'x-decorator': 'FormItem',
+            'x-component-props': {
+              showCount: true,
+              maxLength: 200,
+            },
           },
           },
         },
         },
       },
       },
     },
     },
   };
   };
   return (
   return (
-    <Drawer
-      visible={visible}
-      onClose={() => close()}
-      width="25vw"
-      title="新增产品"
-      extra={
-        <Button type="primary" onClick={handleSave}>
-          保存数据
-        </Button>
-      }
-    >
-      <Form form={form} size="small">
+    <Modal visible={visible} onCancel={() => close()} width="30vw" title="新增" onOk={handleSave}>
+      <Form form={form}>
         <SchemaField schema={schema} scope={{ useAsyncDataSource }} />
         <SchemaField schema={schema} scope={{ useAsyncDataSource }} />
       </Form>
       </Form>
-    </Drawer>
+    </Modal>
   );
   );
 };
 };
 export default Save;
 export default Save;

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

@@ -42,6 +42,7 @@ import DB from '@/db';
 import _ from 'lodash';
 import _ from 'lodash';
 import { useParams } from 'umi';
 import { useParams } from 'umi';
 import { InstanceModel } from '@/pages/device/Instance';
 import { InstanceModel } from '@/pages/device/Instance';
+import FRuleEditor from '@/components/FRuleEditor';
 
 
 interface Props {
 interface Props {
   type: 'product' | 'device';
   type: 'product' | 'device';
@@ -96,6 +97,7 @@ const Edit = (props: Props) => {
       EnumParam,
       EnumParam,
       BooleanEnum,
       BooleanEnum,
       ConfigParam,
       ConfigParam,
+      FRuleEditor,
     },
     },
     scope: {
     scope: {
       async asyncOtherConfig(field: Field) {
       async asyncOtherConfig(field: Field) {
@@ -356,6 +358,10 @@ const Edit = (props: Props) => {
             'x-component': 'Select',
             'x-component': 'Select',
             enum: PropertySource,
             enum: PropertySource,
           },
           },
+          rule: {
+            type: 'string',
+            'x-component': 'FRuleEditor',
+          },
           readOnly: {
           readOnly: {
             title: intl.formatMessage({
             title: intl.formatMessage({
               id: 'pages.device.productDetail.metadata.whetherReadOnly',
               id: 'pages.device.productDetail.metadata.whetherReadOnly',

+ 1 - 7
src/pages/system/Department/Assets/deivce/bind.tsx

@@ -35,9 +35,6 @@ const Bind = observer((props: Props) => {
         id: 'pages.table.name',
         id: 'pages.table.name',
         defaultMessage: '名称',
         defaultMessage: '名称',
       }),
       }),
-      search: {
-        transform: (value) => ({ name$LIKE: value }),
-      },
     },
     },
     {
     {
       title: intl.formatMessage({
       title: intl.formatMessage({
@@ -48,7 +45,6 @@ const Bind = observer((props: Props) => {
       render: (_, row) => {
       render: (_, row) => {
         return row.productName;
         return row.productName;
       },
       },
-      search: false,
     },
     },
     {
     {
       title: intl.formatMessage({
       title: intl.formatMessage({
@@ -56,7 +52,6 @@ const Bind = observer((props: Props) => {
         defaultMessage: '注册时间',
         defaultMessage: '注册时间',
       }),
       }),
       dataIndex: 'registryTime',
       dataIndex: 'registryTime',
-      search: false,
     },
     },
     {
     {
       title: intl.formatMessage({
       title: intl.formatMessage({
@@ -65,7 +60,6 @@ const Bind = observer((props: Props) => {
       }),
       }),
       dataIndex: 'state',
       dataIndex: 'state',
       render: (_, row) => <DeviceBadge type={row.state.value} text={row.state.text} />,
       render: (_, row) => <DeviceBadge type={row.state.value} text={row.state.text} />,
-      search: false,
     },
     },
   ];
   ];
 
 
@@ -73,7 +67,7 @@ const Bind = observer((props: Props) => {
     if (Models.bindKeys.length) {
     if (Models.bindKeys.length) {
       setPerVisible(true);
       setPerVisible(true);
     } else {
     } else {
-      message.warn('请先勾选数据')
+      message.warn('请先勾选数据');
       // props.onCancel();
       // props.onCancel();
     }
     }
   };
   };

+ 21 - 42
src/pages/system/Department/Assets/deivce/index.tsx

@@ -33,23 +33,7 @@ export default observer(() => {
   const actionRef = useRef<ActionType>();
   const actionRef = useRef<ActionType>();
 
 
   const param = useParams<{ id: string }>();
   const param = useParams<{ id: string }>();
-  const [searchParam, setSearchParam] = useState({
-    terms: [
-      {
-        column: 'id',
-        termType: 'dim-assets',
-        value: {
-          assetType: 'device',
-          targets: [
-            {
-              type: 'org',
-              id: param.id,
-            },
-          ],
-        },
-      },
-    ],
-  });
+  const [searchParam, setSearchParam] = useState({});
   /**
   /**
    * 解除资产绑定
    * 解除资产绑定
    */
    */
@@ -90,9 +74,6 @@ export default observer(() => {
         id: 'pages.table.name',
         id: 'pages.table.name',
         defaultMessage: '名称',
         defaultMessage: '名称',
       }),
       }),
-      search: {
-        transform: (value) => ({ name$LIKE: value }),
-      },
     },
     },
     {
     {
       title: intl.formatMessage({
       title: intl.formatMessage({
@@ -103,7 +84,6 @@ export default observer(() => {
       render: (_, row) => {
       render: (_, row) => {
         return row.productName;
         return row.productName;
       },
       },
-      search: false,
     },
     },
     {
     {
       title: intl.formatMessage({
       title: intl.formatMessage({
@@ -111,7 +91,6 @@ export default observer(() => {
         defaultMessage: '注册时间',
         defaultMessage: '注册时间',
       }),
       }),
       dataIndex: 'registryTime',
       dataIndex: 'registryTime',
-      search: false,
     },
     },
     {
     {
       title: intl.formatMessage({
       title: intl.formatMessage({
@@ -119,8 +98,8 @@ export default observer(() => {
         defaultMessage: '状态',
         defaultMessage: '状态',
       }),
       }),
       dataIndex: 'state',
       dataIndex: 'state',
-      filters: true,
-      onFilter: true,
+      // filters: true,
+      // onFilter: true,
       valueType: 'select',
       valueType: 'select',
       valueEnum: {
       valueEnum: {
         all: {
         all: {
@@ -203,25 +182,25 @@ export default observer(() => {
       />
       />
       <SearchComponent<DeviceItem>
       <SearchComponent<DeviceItem>
         field={columns}
         field={columns}
-        onSearch={async (data) => {
-          setSearchParam({
-            terms: [
-              ...data,
-              {
-                column: 'id',
-                termType: 'dim-assets',
-                value: {
-                  assetType: 'device',
-                  targets: [
-                    {
-                      type: 'org',
-                      id: param.id,
-                    },
-                  ],
+        pattern={'simple'}
+        defaultParam={[
+          {
+            column: 'id',
+            termType: 'dim-assets',
+            value: {
+              assetType: 'device',
+              targets: [
+                {
+                  type: 'org',
+                  id: param.id,
                 },
                 },
-              },
-            ],
-          });
+              ],
+            },
+          },
+        ]}
+        onSearch={async (data) => {
+          actionRef.current?.reset?.();
+          setSearchParam(data);
         }}
         }}
         target="department-assets-device"
         target="department-assets-device"
       />
       />

+ 1 - 1
src/pages/system/Department/Assets/permissionModal.tsx

@@ -84,7 +84,7 @@ export default (props: PerModalProps) => {
           { label: '编辑', value: 'save' },
           { label: '编辑', value: 'save' },
           { label: '删除', value: 'delete' },
           { label: '删除', value: 'delete' },
         ],
         ],
-        'x-value': ['read']
+        'x-value': ['read'],
       },
       },
     },
     },
   };
   };

+ 1 - 1
src/pages/system/Department/Assets/product/bind.tsx

@@ -55,7 +55,7 @@ const Bind = observer((props: Props) => {
     if (Models.bindKeys.length) {
     if (Models.bindKeys.length) {
       setPerVisible(true);
       setPerVisible(true);
     } else {
     } else {
-      message.warn('请先勾选数据')
+      message.warn('请先勾选数据');
       // props.onCancel();
       // props.onCancel();
     }
     }
   };
   };

+ 19 - 35
src/pages/system/Department/Assets/product/index.tsx

@@ -20,23 +20,7 @@ export default observer(() => {
   const actionRef = useRef<ActionType>();
   const actionRef = useRef<ActionType>();
 
 
   const param = useParams<{ id: string }>();
   const param = useParams<{ id: string }>();
-  const [searchParam, setSearchParam] = useState({
-    terms: [
-      {
-        column: 'id',
-        termType: 'dim-assets',
-        value: {
-          assetType: 'product',
-          targets: [
-            {
-              type: 'org',
-              id: param.id,
-            },
-          ],
-        },
-      },
-    ],
-  });
+  const [searchParam, setSearchParam] = useState({});
 
 
   /**
   /**
    * 解除资产绑定
    * 解除资产绑定
@@ -139,25 +123,25 @@ export default observer(() => {
       />
       />
       <SearchComponent<ProductItem>
       <SearchComponent<ProductItem>
         field={columns}
         field={columns}
-        onSearch={async (data) => {
-          setSearchParam({
-            terms: [
-              ...data,
-              {
-                column: 'id',
-                termType: 'dim-assets',
-                value: {
-                  assetType: 'product',
-                  targets: [
-                    {
-                      type: 'org',
-                      id: param.id,
-                    },
-                  ],
+        pattern={'simple'}
+        defaultParam={[
+          {
+            column: 'id',
+            termType: 'dim-assets',
+            value: {
+              assetType: 'product',
+              targets: [
+                {
+                  type: 'org',
+                  id: param.id,
                 },
                 },
-              },
-            ],
-          });
+              ],
+            },
+          },
+        ]}
+        onSearch={async (data) => {
+          actionRef.current?.reset?.();
+          setSearchParam(data);
         }}
         }}
         target="department-assets-product"
         target="department-assets-product"
       />
       />

+ 1 - 1
src/pages/system/Department/Assets/productCategory/bind.tsx

@@ -53,7 +53,7 @@ const Bind = observer((props: Props) => {
     if (Models.bindKeys.length) {
     if (Models.bindKeys.length) {
       setPerVisible(true);
       setPerVisible(true);
     } else {
     } else {
-      message.warn('请先勾选数据')
+      message.warn('请先勾选数据');
       // props.onCancel();
       // props.onCancel();
     }
     }
   };
   };

+ 19 - 35
src/pages/system/Department/Assets/productCategory/index.tsx

@@ -31,23 +31,7 @@ export default observer(() => {
   const intl = useIntl();
   const intl = useIntl();
   const actionRef = useRef<ActionType>();
   const actionRef = useRef<ActionType>();
   const param = useParams<{ id: string }>();
   const param = useParams<{ id: string }>();
-  const [searchParam, setSearchParam] = useState({
-    terms: [
-      {
-        column: 'id',
-        termType: 'dim-assets',
-        value: {
-          assetType: 'deviceCategory',
-          targets: [
-            {
-              type: 'org',
-              id: param.id,
-            },
-          ],
-        },
-      },
-    ],
-  });
+  const [searchParam, setSearchParam] = useState({});
 
 
   /**
   /**
    * 解除资产绑定
    * 解除资产绑定
@@ -157,25 +141,25 @@ export default observer(() => {
       />
       />
       <SearchComponent<ProductCategoryItem>
       <SearchComponent<ProductCategoryItem>
         field={columns}
         field={columns}
-        onSearch={async (data) => {
-          setSearchParam({
-            terms: [
-              ...data,
-              {
-                column: 'id',
-                termType: 'dim-assets',
-                value: {
-                  assetType: 'deviceCategory',
-                  targets: [
-                    {
-                      type: 'org',
-                      id: param.id,
-                    },
-                  ],
+        pattern="simple"
+        defaultParam={[
+          {
+            column: 'id',
+            termType: 'dim-assets',
+            value: {
+              assetType: 'deviceCategory',
+              targets: [
+                {
+                  type: 'org',
+                  id: param.id,
                 },
                 },
-              },
-            ],
-          });
+              ],
+            },
+          },
+        ]}
+        onSearch={async (data) => {
+          actionRef.current?.reset?.();
+          setSearchParam(data);
         }}
         }}
         target="department-assets-category"
         target="department-assets-category"
       />
       />

+ 6 - 4
src/pages/system/Department/Member/bind.tsx

@@ -82,10 +82,12 @@ const Bind = observer((props: Props) => {
           pageSize: 5,
           pageSize: 5,
         }}
         }}
         params={{
         params={{
-          terms: [{
-            column: 'id$in-dimension$org$not',
-            value: param.id
-          }]
+          terms: [
+            {
+              column: 'id$in-dimension$org$not',
+              value: param.id,
+            },
+          ],
         }}
         }}
         rowSelection={{
         rowSelection={{
           selectedRowKeys: MemberModel.bindUsers,
           selectedRowKeys: MemberModel.bindUsers,

+ 12 - 16
src/pages/system/Department/Member/index.tsx

@@ -3,7 +3,7 @@ import { PageContainer } from '@ant-design/pro-layout';
 import ProTable from '@jetlinks/pro-table';
 import ProTable from '@jetlinks/pro-table';
 import type { ActionType, ProColumns } from '@jetlinks/pro-table';
 import type { ActionType, ProColumns } from '@jetlinks/pro-table';
 import { useIntl } from '@@/plugin-locale/localeExports';
 import { useIntl } from '@@/plugin-locale/localeExports';
-import { Badge, Button, Card, Divider, message, Popconfirm, Tooltip } from 'antd';
+import { Badge, Button, message, Popconfirm, Tooltip } from 'antd';
 import { useRef, useState } from 'react';
 import { useRef, useState } from 'react';
 import { useParams } from 'umi';
 import { useParams } from 'umi';
 import { observer } from '@formily/react';
 import { observer } from '@formily/react';
@@ -21,9 +21,7 @@ const Member = observer(() => {
   const actionRef = useRef<ActionType>();
   const actionRef = useRef<ActionType>();
 
 
   const param = useParams<{ id: string }>();
   const param = useParams<{ id: string }>();
-  const [searchParam, setSearchParam] = useState({
-    terms: [{ column: 'id$in-dimension$org', value: param.id }],
-  });
+  const [searchParam, setSearchParam] = useState({});
 
 
   const handleUnBind = () => {
   const handleUnBind = () => {
     service.handleUser(param.id, MemberModel.unBindUsers, 'unbind').subscribe({
     service.handleUser(param.id, MemberModel.unBindUsers, 'unbind').subscribe({
@@ -156,18 +154,16 @@ const Member = observer(() => {
         onCancel={closeModal}
         onCancel={closeModal}
         reload={() => actionRef.current?.reload()}
         reload={() => actionRef.current?.reload()}
       />
       />
-      <Card>
-        <SearchComponent<MemberItem>
-          field={columns}
-          onSearch={async (data) => {
-            setSearchParam({
-              terms: [...data, { column: 'id$in-dimension$org', value: param.id }],
-            });
-          }}
-          target="department-user"
-        />
-      </Card>
-      <Divider />
+      <SearchComponent<MemberItem>
+        pattern={'simple'}
+        field={columns}
+        defaultParam={[{ column: 'id$in-dimension$org', value: param.id, termType: 'eq' }]}
+        onSearch={async (data) => {
+          actionRef.current?.reset?.();
+          setSearchParam(data);
+        }}
+        target="department-user"
+      />
       <ProTable<MemberItem>
       <ProTable<MemberItem>
         actionRef={actionRef}
         actionRef={actionRef}
         columns={columns}
         columns={columns}

+ 23 - 15
src/pages/system/Department/index.tsx

@@ -4,7 +4,7 @@ import ProTable from '@jetlinks/pro-table';
 import type { ActionType, ProColumns } from '@jetlinks/pro-table';
 import type { ActionType, ProColumns } from '@jetlinks/pro-table';
 import { useEffect, useRef, useState } from 'react';
 import { useEffect, useRef, useState } from 'react';
 import { useIntl } from 'umi';
 import { useIntl } from 'umi';
-import { Button, message, Popconfirm, Tooltip, Card, Divider } from 'antd';
+import { Button, message, Popconfirm, Tooltip } from 'antd';
 import {
 import {
   EditOutlined,
   EditOutlined,
   PlusOutlined,
   PlusOutlined,
@@ -38,9 +38,7 @@ export const State = model<ModelType>({
 export default observer(() => {
 export default observer(() => {
   const actionRef = useRef<ActionType>();
   const actionRef = useRef<ActionType>();
   const intl = useIntl();
   const intl = useIntl();
-  const [param, setParam] = useState({
-    terms: [{ column: 'typeId', value: 'org' }],
-  });
+  const [param, setParam] = useState({});
 
 
   /**
   /**
    * 根据部门ID删除数据
    * 根据部门ID删除数据
@@ -73,6 +71,7 @@ export default observer(() => {
         defaultMessage: '排序',
         defaultMessage: '排序',
       }),
       }),
       search: false,
       search: false,
+      valueType: 'digit',
       dataIndex: 'sortIndex',
       dataIndex: 'sortIndex',
     },
     },
     {
     {
@@ -209,21 +208,30 @@ export default observer(() => {
 
 
   return (
   return (
     <PageContainer>
     <PageContainer>
-      <Card>
-        <SearchComponent<DepartmentItem>
-          field={columns}
-          onSearch={async (data) => {
-            setParam({ terms: [...data, { column: 'typeId', value: 'org' }] });
-          }}
-          target="department"
-        />
-      </Card>
-      <Divider />
+      <SearchComponent<DepartmentItem>
+        field={columns}
+        defaultParam={[{ column: 'typeId', value: 'org', termType: 'eq' }]}
+        onSearch={async (data) => {
+          // 重置分页数据
+          actionRef.current?.reset?.();
+          setParam(data);
+        }}
+        onReset={() => {
+          // 重置分页及搜索参数
+          actionRef.current?.reset?.();
+          setParam({});
+        }}
+        target="department"
+      />
       <ProTable<DepartmentItem>
       <ProTable<DepartmentItem>
         columns={columns}
         columns={columns}
         actionRef={actionRef}
         actionRef={actionRef}
         request={async (params) => {
         request={async (params) => {
-          const response = await service.queryOrgThree({ paging: false, ...params });
+          const response = await service.queryOrgThree({
+            paging: false,
+            ...params,
+            sorts: [{ name: 'createTime', order: 'desc' }],
+          });
           return {
           return {
             code: response.message,
             code: response.message,
             result: {
             result: {

+ 9 - 4
src/pages/system/Department/save.tsx

@@ -101,10 +101,15 @@ const Save = <T extends object>(props: SaveModalProps<T>) => {
 
 
   return (
   return (
     <Modal
     <Modal
-      title={props.title ? props.title : intl.formatMessage({
-        id: `pages.data.option.${data && 'id' in data ? 'edit' : 'add'}`,
-        defaultMessage: '新增',
-      })}
+      title={
+        props.title
+          ? props.title
+          : intl.formatMessage({
+              id: `pages.data.option.${data && 'id' in data ? 'edit' : 'add'}`,
+              defaultMessage: '新增',
+            })
+      }
+      maskClosable={false}
       visible={props.visible}
       visible={props.visible}
       onOk={saveData}
       onOk={saveData}
       onCancel={() => {
       onCancel={() => {

+ 38 - 69
src/pages/system/Permission/index.tsx

@@ -4,9 +4,9 @@ import {
   EditOutlined,
   EditOutlined,
   CloseCircleOutlined,
   CloseCircleOutlined,
   PlayCircleOutlined,
   PlayCircleOutlined,
-  MinusOutlined,
+  DeleteOutlined,
 } from '@ant-design/icons';
 } from '@ant-design/icons';
-import { Menu, Tooltip, Popconfirm, message, Button, Upload } from 'antd';
+import { Menu, Tooltip, Popconfirm, message, Button, Upload, Badge } from 'antd';
 import type { ProColumns, ActionType } from '@jetlinks/pro-table';
 import type { ProColumns, ActionType } from '@jetlinks/pro-table';
 import { useIntl } from '@@/plugin-locale/localeExports';
 import { useIntl } from '@@/plugin-locale/localeExports';
 import BaseCrud from '@/components/BaseCrud';
 import BaseCrud from '@/components/BaseCrud';
@@ -121,32 +121,16 @@ const Permission: React.FC = observer(() => {
 
 
   const columns: ProColumns<PermissionItem>[] = [
   const columns: ProColumns<PermissionItem>[] = [
     {
     {
-      dataIndex: 'index',
-      valueType: 'indexBorder',
-      width: 48,
-    },
-    {
       title: intl.formatMessage({
       title: intl.formatMessage({
         id: 'pages.system.permission.id',
         id: 'pages.system.permission.id',
         defaultMessage: '标识',
         defaultMessage: '标识',
       }),
       }),
       dataIndex: 'id',
       dataIndex: 'id',
-      copyable: true,
+      // copyable: true,
       ellipsis: true,
       ellipsis: true,
       align: 'center',
       align: 'center',
-      sorter: true,
+      // sorter: true,
       defaultSortOrder: 'ascend',
       defaultSortOrder: 'ascend',
-      formItemProps: {
-        rules: [
-          {
-            required: true,
-            message: '此项为必填项',
-          },
-        ],
-      },
-      search: {
-        transform: (value) => ({ id$LIKE: value }),
-      },
     },
     },
     {
     {
       title: intl.formatMessage({
       title: intl.formatMessage({
@@ -154,24 +138,9 @@ const Permission: React.FC = observer(() => {
         defaultMessage: '名称',
         defaultMessage: '名称',
       }),
       }),
       dataIndex: 'name',
       dataIndex: 'name',
-      copyable: true,
+      // copyable: true,
       ellipsis: true,
       ellipsis: true,
       align: 'center',
       align: 'center',
-      tip: intl.formatMessage({
-        id: 'pages.system.permission.name.tip',
-        defaultMessage: '名称过长会自动收缩',
-      }),
-      formItemProps: {
-        rules: [
-          {
-            required: true,
-            message: '此项为必填项',
-          },
-        ],
-      },
-      search: {
-        transform: (value) => ({ name$LIKE: value }),
-      },
     },
     },
     {
     {
       title: intl.formatMessage({
       title: intl.formatMessage({
@@ -179,18 +148,10 @@ const Permission: React.FC = observer(() => {
         defaultMessage: '状态',
         defaultMessage: '状态',
       }),
       }),
       dataIndex: 'status',
       dataIndex: 'status',
-      filters: true,
+      // filters: true,
       align: 'center',
       align: 'center',
-      onFilter: true,
       valueType: 'select',
       valueType: 'select',
       valueEnum: {
       valueEnum: {
-        all: {
-          text: intl.formatMessage({
-            id: 'pages.searchTable.titleStatus.all',
-            defaultMessage: '全部',
-          }),
-          status: 'Default',
-        },
         1: {
         1: {
           text: intl.formatMessage({
           text: intl.formatMessage({
             id: 'pages.searchTable.titleStatus.normal',
             id: 'pages.searchTable.titleStatus.normal',
@@ -206,6 +167,9 @@ const Permission: React.FC = observer(() => {
           status: 0,
           status: 0,
         },
         },
       },
       },
+      render: (text, record) => (
+        <Badge status={record.status === 1 ? 'success' : 'error'} text={text} />
+      ),
     },
     },
     {
     {
       title: intl.formatMessage({
       title: intl.formatMessage({
@@ -262,33 +226,38 @@ const Permission: React.FC = observer(() => {
             </Tooltip>
             </Tooltip>
           </Popconfirm>
           </Popconfirm>
         </a>,
         </a>,
-        <a key="delete">
-          <Popconfirm
-            title={intl.formatMessage({
-              id: 'pages.data.option.remove.tips',
-              defaultMessage: '确认删除?',
-            })}
-            onConfirm={async () => {
-              await service.remove(record.id);
-              message.success(
-                intl.formatMessage({
-                  id: 'pages.data.option.success',
-                  defaultMessage: '操作成功!',
-                }),
-              );
-              actionRef.current?.reload();
-            }}
-          >
-            <Tooltip
+        <Tooltip
+          key="delete"
+          title={
+            record.status === 0
+              ? intl.formatMessage({
+                  id: 'pages.data.option.remove',
+                  defaultMessage: '删除',
+                })
+              : '请先禁用该权限,再删除。'
+          }
+        >
+          <Button type="link" style={{ padding: 0 }} disabled={record.status === 1}>
+            <Popconfirm
               title={intl.formatMessage({
               title={intl.formatMessage({
-                id: 'pages.data.option.remove',
-                defaultMessage: '删除',
+                id: 'pages.data.option.remove.tips',
+                defaultMessage: '确认删除?',
               })}
               })}
+              onConfirm={async () => {
+                await service.remove(record.id);
+                message.success(
+                  intl.formatMessage({
+                    id: 'pages.data.option.success',
+                    defaultMessage: '操作成功!',
+                  }),
+                );
+                actionRef.current?.reload();
+              }}
             >
             >
-              <MinusOutlined />
-            </Tooltip>
-          </Popconfirm>
-        </a>,
+              <DeleteOutlined />
+            </Popconfirm>
+          </Button>
+        </Tooltip>,
       ],
       ],
     },
     },
   ];
   ];

+ 1 - 1
src/pages/system/Role/Edit/UserManage/BindUser.tsx

@@ -29,7 +29,7 @@ const BindUser = (props: Props) => {
         defaultMessage: '名称',
         defaultMessage: '名称',
       }),
       }),
       dataIndex: 'name',
       dataIndex: 'name',
-      copyable: true,
+      // copyable: true,
       ellipsis: true,
       ellipsis: true,
       tip: intl.formatMessage({
       tip: intl.formatMessage({
         id: 'pages.system.userName.tips',
         id: 'pages.system.userName.tips',

+ 1 - 1
src/pages/system/Role/Edit/UserManage/index.tsx

@@ -37,7 +37,7 @@ const UserManage = () => {
         defaultMessage: '名称',
         defaultMessage: '名称',
       }),
       }),
       dataIndex: 'name',
       dataIndex: 'name',
-      copyable: true,
+      // copyable: true,
       ellipsis: true,
       ellipsis: true,
       tip: intl.formatMessage({
       tip: intl.formatMessage({
         id: 'pages.system.userName.tips',
         id: 'pages.system.userName.tips',

+ 16 - 50
src/pages/system/Role/index.tsx

@@ -1,16 +1,12 @@
 import { PageContainer } from '@ant-design/pro-layout';
 import { PageContainer } from '@ant-design/pro-layout';
 import React, { useEffect, useRef } from 'react';
 import React, { useEffect, useRef } from 'react';
-import { EditOutlined, MinusOutlined } from '@ant-design/icons';
+import { DeleteOutlined, EditOutlined } from '@ant-design/icons';
 import { message, Popconfirm, Tooltip } from 'antd';
 import { message, Popconfirm, Tooltip } from 'antd';
 import type { ProColumns, ActionType } from '@jetlinks/pro-table';
 import type { ProColumns, ActionType } from '@jetlinks/pro-table';
 import BaseCrud from '@/components/BaseCrud';
 import BaseCrud from '@/components/BaseCrud';
 import BaseService from '@/utils/BaseService';
 import BaseService from '@/utils/BaseService';
 import { useIntl } from '@@/plugin-locale/localeExports';
 import { useIntl } from '@@/plugin-locale/localeExports';
 import { observer } from '@formily/react';
 import { observer } from '@formily/react';
-// import autzModel from '@/components/Authorization/autz';
-// import Authorization from '@/components/Authorization';
-// import { BindModel } from '@/components/BindUser/model';
-// import BindUser from '@/components/BindUser';
 import { Link, useLocation } from 'umi';
 import { Link, useLocation } from 'umi';
 import { Store } from 'jetlinks-store';
 import { Store } from 'jetlinks-store';
 import SystemConst from '@/utils/const';
 import SystemConst from '@/utils/const';
@@ -23,21 +19,21 @@ const Role: React.FC = observer(() => {
   const actionRef = useRef<ActionType>();
   const actionRef = useRef<ActionType>();
 
 
   const columns: ProColumns<RoleItem>[] = [
   const columns: ProColumns<RoleItem>[] = [
-    {
-      dataIndex: 'index',
-      valueType: 'indexBorder',
-      width: 48,
-    },
+    // {
+    //   dataIndex: 'index',
+    //   valueType: 'indexBorder',
+    //   width: 48,
+    // },
     {
     {
       title: intl.formatMessage({
       title: intl.formatMessage({
         id: 'pages.system.role.id',
         id: 'pages.system.role.id',
         defaultMessage: '标识',
         defaultMessage: '标识',
       }),
       }),
       dataIndex: 'id',
       dataIndex: 'id',
-      copyable: true,
+      // copyable: true,
       ellipsis: true,
       ellipsis: true,
-      sorter: true,
-      defaultSortOrder: 'ascend',
+      // sorter: true,
+      // defaultSortOrder: 'ascend',
       formItemProps: {
       formItemProps: {
         rules: [
         rules: [
           {
           {
@@ -53,12 +49,12 @@ const Role: React.FC = observer(() => {
         defaultMessage: '名称',
         defaultMessage: '名称',
       }),
       }),
       dataIndex: 'name',
       dataIndex: 'name',
-      copyable: true,
+      // copyable: true,
       ellipsis: true,
       ellipsis: true,
-      tip: intl.formatMessage({
-        id: 'pages.system.userName.tips',
-        defaultMessage: '用户名过长会自动收缩',
-      }),
+      // tip: intl.formatMessage({
+      //   id: 'pages.system.userName.tips',
+      //   defaultMessage: '用户名过长会自动收缩',
+      // }),
       formItemProps: {
       formItemProps: {
         rules: [
         rules: [
           {
           {
@@ -120,7 +116,7 @@ const Role: React.FC = observer(() => {
                 defaultMessage: '删除',
                 defaultMessage: '删除',
               })}
               })}
             >
             >
-              <MinusOutlined />
+              <DeleteOutlined />
             </Tooltip>
             </Tooltip>
           </Popconfirm>
           </Popconfirm>
         </a>,
         </a>,
@@ -186,40 +182,10 @@ const Role: React.FC = observer(() => {
         search={false}
         search={false}
         title={intl.formatMessage({
         title={intl.formatMessage({
           id: 'pages.system.role',
           id: 'pages.system.role',
-          defaultMessage: '角色管理',
+          defaultMessage: '角色列表',
         })}
         })}
         schema={schema}
         schema={schema}
-        // defaultParams={{ typeId: 'role' }}
       />
       />
-      {/* <Modal
-        visible={BindModel.visible}
-        closable={false}
-        onCancel={() => {
-          BindModel.visible = false;
-          BindModel.bind = false;
-        }}
-        width={BindModel.bind ? '90vw' : '60vw'}
-      >
-        <BindUser />
-      </Modal> */}
-      {/* <Drawer
-        title={intl.formatMessage({
-          id: 'pages.data.option.authorize',
-          defaultMessage: '授权',
-        })}
-        width="70vw"
-        visible={autzModel.visible}
-        onClose={() => {
-          autzModel.visible = false;
-        }}
-      >
-        <Authorization
-          close={() => {
-            autzModel.visible = false;
-          }}
-          target={autzModel.autzTarget}
-        />
-      </Drawer> */}
     </PageContainer>
     </PageContainer>
   );
   );
 });
 });

+ 11 - 6
src/pages/system/User/Save/index.tsx

@@ -5,7 +5,7 @@ import { createForm } from '@formily/core';
 import { createSchemaField } from '@formily/react';
 import { createSchemaField } from '@formily/react';
 import React, { useEffect, useState } from 'react';
 import React, { useEffect, useState } from 'react';
 import * as ICONS from '@ant-design/icons';
 import * as ICONS from '@ant-design/icons';
-import { Form, FormItem, Input, Password, Select, Switch } from '@formily/antd';
+import { Form, FormItem, Input, Password, Select, Switch, TreeSelect } from '@formily/antd';
 import type { ISchema } from '@formily/json-schema';
 import type { ISchema } from '@formily/json-schema';
 import { PlusOutlined } from '@ant-design/icons';
 import { PlusOutlined } from '@ant-design/icons';
 import { action } from '@formily/reactive';
 import { action } from '@formily/reactive';
@@ -33,6 +33,7 @@ const Save = (props: Props) => {
     api(field).then(
     api(field).then(
       action.bound!((resp: Response<any>) => {
       action.bound!((resp: Response<any>) => {
         field.dataSource = resp.result?.map((item: Record<string, unknown>) => ({
         field.dataSource = resp.result?.map((item: Record<string, unknown>) => ({
+          ...item,
           label: item.name,
           label: item.name,
           value: item.id,
           value: item.id,
         }));
         }));
@@ -43,7 +44,6 @@ const Save = (props: Props) => {
 
 
   const getUser = async () => {
   const getUser = async () => {
     if (props.data.id) {
     if (props.data.id) {
-      console.log('id');
       const response: Response<UserItem> = await service.queryDetail(props.data?.id);
       const response: Response<UserItem> = await service.queryDetail(props.data?.id);
       if (response.status === 200) {
       if (response.status === 200) {
         const temp = response.result as UserItem;
         const temp = response.result as UserItem;
@@ -73,6 +73,7 @@ const Save = (props: Props) => {
       Password,
       Password,
       Switch,
       Switch,
       Select,
       Select,
+      TreeSelect,
     },
     },
     scope: {
     scope: {
       icon(name: any) {
       icon(name: any) {
@@ -245,12 +246,17 @@ const Save = (props: Props) => {
       orgIdList: {
       orgIdList: {
         title: '部门',
         title: '部门',
         'x-decorator': 'FormItem',
         'x-decorator': 'FormItem',
-        'x-component': 'Select',
+        'x-component': 'TreeSelect',
         'x-component-props': {
         'x-component-props': {
-          mode: 'multiple',
+          multiple: true,
           showArrow: true,
           showArrow: true,
           filterOption: (input: string, option: any) =>
           filterOption: (input: string, option: any) =>
             option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0,
             option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0,
+          fieldNames: {
+            label: 'name',
+            value: 'id',
+          },
+          treeNodeFilterProp: 'name',
         },
         },
         'x-decorator-props': {
         'x-decorator-props': {
           addonAfter: (
           addonAfter: (
@@ -259,7 +265,6 @@ const Save = (props: Props) => {
                 const tab: any = window.open(`${origin}/#/system/department?save=true`);
                 const tab: any = window.open(`${origin}/#/system/department?save=true`);
                 tab!.onTabSaveSuccess = (value: any) => {
                 tab!.onTabSaveSuccess = (value: any) => {
                   form.setFieldState('orgIdList', (state) => {
                   form.setFieldState('orgIdList', (state) => {
-                    console.log(value, 'value');
                     state.dataSource = state.dataSource?.concat([
                     state.dataSource = state.dataSource?.concat([
                       { label: value.name, value: value.id },
                       { label: value.name, value: value.id },
                     ]);
                     ]);
@@ -307,7 +312,7 @@ const Save = (props: Props) => {
       visible={model !== 'query'}
       visible={model !== 'query'}
       onCancel={props.close}
       onCancel={props.close}
       onOk={save}
       onOk={save}
-      width="30vw"
+      width="35vw"
     >
     >
       <Form form={form} labelCol={4} wrapperCol={18}>
       <Form form={form} labelCol={4} wrapperCol={18}>
         <SchemaField schema={schema} scope={{ useAsyncDataSource, getRole, getOrg }} />
         <SchemaField schema={schema} scope={{ useAsyncDataSource, getRole, getOrg }} />

+ 34 - 26
src/pages/system/User/index.tsx

@@ -3,7 +3,7 @@ import { PageContainer } from '@ant-design/pro-layout';
 import SearchComponent from '@/components/SearchComponent';
 import SearchComponent from '@/components/SearchComponent';
 import type { ActionType, ProColumns } from '@jetlinks/pro-table';
 import type { ActionType, ProColumns } from '@jetlinks/pro-table';
 import ProTable from '@jetlinks/pro-table';
 import ProTable from '@jetlinks/pro-table';
-import { Button, Card, message, Popconfirm, Tooltip } from 'antd';
+import { Badge, Button, message, Popconfirm, Tooltip } from 'antd';
 import {
 import {
   CloseCircleOutlined,
   CloseCircleOutlined,
   DeleteOutlined,
   DeleteOutlined,
@@ -36,7 +36,7 @@ const User = observer(() => {
         defaultMessage: '姓名',
         defaultMessage: '姓名',
       }),
       }),
       dataIndex: 'name',
       dataIndex: 'name',
-      copyable: true,
+      // copyable: true,
       ellipsis: true,
       ellipsis: true,
       align: 'center',
       align: 'center',
       // tip: intl.formatMessage({
       // tip: intl.formatMessage({
@@ -63,7 +63,7 @@ const User = observer(() => {
         defaultMessage: '用户名',
         defaultMessage: '用户名',
       }),
       }),
       dataIndex: 'username',
       dataIndex: 'username',
-      copyable: true,
+      // copyable: true,
       ellipsis: true,
       ellipsis: true,
       align: 'center',
       align: 'center',
       // tip: intl.formatMessage({
       // tip: intl.formatMessage({
@@ -108,6 +108,9 @@ const User = observer(() => {
           status: 0,
           status: 0,
         },
         },
       },
       },
+      render: (text, record) => (
+        <Badge status={record.status === 1 ? 'success' : 'error'} text={text} />
+      ),
     },
     },
     {
     {
       title: intl.formatMessage({
       title: intl.formatMessage({
@@ -158,42 +161,47 @@ const User = observer(() => {
             </Tooltip>
             </Tooltip>
           </Popconfirm>
           </Popconfirm>
         </a>,
         </a>,
-        <a key="delete">
-          <Popconfirm
-            onConfirm={async () => {
-              await service.remove(record.id);
-              actionRef.current?.reload();
-            }}
-            title="确认删除?"
-          >
-            <Tooltip title="删除">
+        <Tooltip title={record.status === 0 ? '删除' : '请先禁用该用户,再删除。'} key="delete">
+          <Button type="link" style={{ padding: 0 }} disabled={record.status === 1}>
+            <Popconfirm
+              onConfirm={async () => {
+                await service.remove(record.id);
+                actionRef.current?.reload();
+              }}
+              title="确认删除?"
+            >
               <DeleteOutlined />
               <DeleteOutlined />
-            </Tooltip>
-          </Popconfirm>
-        </a>,
+            </Popconfirm>
+          </Button>
+        </Tooltip>,
       ],
       ],
     },
     },
   ];
   ];
 
 
   const [param, setParam] = useState({});
   const [param, setParam] = useState({});
+
   return (
   return (
     <PageContainer>
     <PageContainer>
-      <Card style={{ marginBottom: '20px' }}>
-        <SearchComponent
-          field={columns}
-          onSearch={(data) => setParam({ terms: data, total: null })}
-          target="user"
-          onReset={() => {
-            setParam({});
-            actionRef.current?.reset?.();
-          }}
-        />
-      </Card>
+      <SearchComponent<UserItem>
+        field={columns}
+        target="user"
+        onSearch={(data) => {
+          // 重置分页数据
+          actionRef.current?.reset?.();
+          setParam(data);
+        }}
+        // onReset={() => {
+        //   // 重置分页及搜索参数
+        //   actionRef.current?.reset?.();
+        //   setParam({});
+        // }}
+      />
       <ProTable<UserItem>
       <ProTable<UserItem>
         actionRef={actionRef}
         actionRef={actionRef}
         params={param}
         params={param}
         columns={columns}
         columns={columns}
         search={false}
         search={false}
+        headerTitle={'用户列表'}
         request={async (params) =>
         request={async (params) =>
           service.query({ ...params, sorts: [{ name: 'createTime', order: 'desc' }] })
           service.query({ ...params, sorts: [{ name: 'createTime', order: 'desc' }] })
         }
         }