xieyonghong 3 лет назад
Родитель
Сommit
48a063c417

+ 1 - 1
config/defaultSettings.ts

@@ -8,7 +8,7 @@ const Settings: LayoutSettings & {
   // 拂晓蓝
   // primaryColor: '#1890ff',
   // 极光绿
-  primaryColor: '#52C41A',
+  primaryColor: '#1d39c4',
   layout: 'mix',
   contentWidth: 'Fluid',
   splitMenus: true,

+ 4 - 4
config/proxy.ts

@@ -9,10 +9,10 @@
 export default {
   dev: {
     '/jetlinks': {
-      // target: 'http://192.168.23.223:8800/',
-      // ws: 'ws://192.168.23.223:8800/',
-      ws: 'ws://demo.jetlinks.cn/jetlinks',
-      target: 'http://demo.jetlinks.cn/jetlinks',
+      target: 'http://192.168.33.222:8844/',
+      ws: 'ws://192.168.33.222:8844/',
+      // ws: 'ws://demo.jetlinks.cn/jetlinks',
+      // target: 'http://demo.jetlinks.cn/jetlinks',
       changeOrigin: true,
       pathRewrite: { '^/jetlinks': '' },
     },

+ 0 - 7
config/routes.ts

@@ -51,13 +51,6 @@
         component: './system/Permission',
       },
       {
-        path: '/system/org',
-        name: 'org',
-        icon: 'smile',
-        access: 'organization',
-        component: './system/Org',
-      },
-      {
         path: '/system/open-api',
         name: 'open-api',
         icon: 'smile',

+ 2 - 3
package.json

@@ -28,7 +28,7 @@
     "openapi": "umi openapi",
     "precommit": "lint-staged",
     "prettier": "prettier -c --write \"src/**/*\"",
-    "start": "cross-env UMI_ENV=dev umi dev",
+    "start": "cross-env UMI_ENV=dev PORT=9000 umi dev",
     "start:dev": "cross-env REACT_APP_ENV=dev MOCK=none UMI_ENV=dev umi dev",
     "start:no-mock": "cross-env MOCK=none UMI_ENV=dev umi dev",
     "start:no-ui": "cross-env UMI_UI=none UMI_ENV=dev umi dev",
@@ -62,7 +62,6 @@
     "@ant-design/pro-descriptions": "^1.6.8",
     "@ant-design/pro-form": "^1.18.3",
     "@ant-design/pro-layout": "^6.27.2",
-    "@dabeng/react-orgchart": "^1.0.0",
     "@formily/antd": "2.0.0-rc.17",
     "@formily/core": "2.0.0-rc.17",
     "@formily/json-schema": "2.0.0-rc.17",
@@ -71,7 +70,7 @@
     "@formily/reactive-react": "2.0.0-rc.17",
     "@formily/shared": "2.0.0-rc.17",
     "@jetlinks/pro-list": "^1.10.8",
-    "@jetlinks/pro-table": "^2.43.7",
+    "@jetlinks/pro-table": "^2.63.8",
     "@umijs/route-utils": "^1.0.36",
     "ahooks": "^2.10.9",
     "antd": "^4.17.0-alpha.9",

+ 22 - 3
src/components/BaseCrud/index.tsx

@@ -1,5 +1,5 @@
 import { useIntl } from '@@/plugin-locale/localeExports';
-import { Button, Dropdown } from 'antd';
+import { Button, Card, Divider, Dropdown } from 'antd';
 import ProTable from '@jetlinks/pro-table';
 import type { ProColumns, ActionType, RequestData } from '@jetlinks/pro-table';
 
@@ -12,8 +12,11 @@ import { CurdModel } from '@/components/BaseCrud/model';
 import type { ISchemaFieldProps } from '@formily/react/lib/types';
 import type { ModalProps } from 'antd/lib/modal/Modal';
 import type { TablePaginationConfig } from 'antd/lib/table/interface';
-import type { SearchConfig } from '@jetlinks/pro-table/lib/components/Form/FormRender';
 import type { Form } from '@formily/core';
+import SearchComponent from '@/components/SearchComponent';
+import { useRef, useState } from 'react';
+import type { ProFormInstance } from '@ant-design/pro-form';
+import type { SearchConfig } from '@ant-design/pro-form/lib/components/Submitter';
 
 export type Option = {
   model: 'edit' | 'preview' | 'add';
@@ -41,11 +44,13 @@ export type Props<T> = {
   search?: false | SearchConfig;
   formEffect?: () => void; // 与form参数 只有一个生效
   form?: Form;
+  /** @name 用于存储搜索历史记录的标记*/
+  moduleName?: string; //
 };
 
 const BaseCrud = <T extends Record<string, any>>(props: Props<T>) => {
   const intl = useIntl();
-
+  const ref = useRef<ProFormInstance>();
   const {
     columns,
     service,
@@ -62,11 +67,25 @@ const BaseCrud = <T extends Record<string, any>>(props: Props<T>) => {
     search,
     formEffect,
     form,
+    moduleName,
   } = props;
 
+  const [param, setParam] = useState({});
   return (
     <>
+      <Card>
+        <SearchComponent<T>
+          field={columns}
+          onSearch={async (data) => {
+            setParam({ terms: data });
+          }}
+          target={moduleName}
+        />
+      </Card>
+      <Divider />
       <ProTable<T>
+        params={param}
+        formRef={ref}
         columns={columns}
         actionRef={actionRef}
         options={{ fullScreen: true }}

+ 29 - 0
src/components/SearchComponent/GroupNameControl.tsx

@@ -0,0 +1,29 @@
+import { ArrayItems } from '@formily/antd';
+import { Select } from 'antd';
+
+interface Props {
+  name?: string;
+  value: string;
+  onChange: () => void;
+}
+
+const GroupNameControl = (props: Props) => {
+  const index = ArrayItems.useIndex!();
+  return (
+    <>
+      {index === 0 ? (
+        <div style={{ textAlign: 'center', fontWeight: 600 }}>{props?.name || '第一组'}</div>
+      ) : (
+        <Select
+          onChange={props.onChange}
+          value={props.value}
+          options={[
+            { label: '并且', value: 'and' },
+            { label: '或者', value: 'or' },
+          ]}
+        />
+      )}
+    </>
+  );
+};
+export default GroupNameControl;

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

@@ -0,0 +1,9 @@
+.action {
+  display: flex;
+  align-items: center;
+}
+
+.saveLog {
+  width: 100%;
+  margin-top: 5px;
+}

+ 355 - 0
src/components/SearchComponent/index.tsx

@@ -0,0 +1,355 @@
+import type { ISchema } from '@formily/json-schema';
+import { createSchemaField } from '@formily/react';
+import {
+  ArrayItems,
+  Form,
+  FormButtonGroup,
+  FormGrid,
+  FormItem,
+  FormTab,
+  Input,
+  PreviewText,
+  Select,
+} from '@formily/antd';
+import { createForm } from '@formily/core';
+import GroupNameControl from '@/components/SearchComponent/GroupNameControl';
+import { DeleteOutlined, DoubleRightOutlined } from '@ant-design/icons';
+import { Button, Dropdown, Input as AInput, Menu, message, Popconfirm, Popover } from 'antd';
+import { useState } from 'react';
+import type { ProColumns } from '@jetlinks/pro-table';
+import type { EnumData } from '@/utils/typings';
+import styles from './index.less';
+import Service from '@/components/SearchComponent/service';
+import _ from 'lodash';
+import { useIntl } from '@@/plugin-locale/localeExports';
+
+const ui2Server = (source: SearchTermsUI): SearchTermsServer => [
+  { terms: source.terms1, type: source.type },
+  { terms: source.terms2 },
+];
+
+const server2Ui = (source: SearchTermsServer): SearchTermsUI => ({
+  terms1: source[0].terms,
+  terms2: source[1].terms,
+  type: source[0].type || 'and',
+});
+
+interface Props<T> {
+  field: ProColumns<T>[];
+  onSearch: (params: any) => void;
+  target?: string;
+}
+
+const termType = [
+  { label: '=', value: 'eq' },
+  { label: '!=', value: 'not' },
+  { label: '包含', value: 'like' },
+  { label: '不包含', value: 'not like' },
+  { label: '>', value: 'gt' },
+  { label: '>=', value: 'gte' },
+  { label: '<', value: 'lt' },
+  { label: '<=', value: 'lte' },
+  { label: '属于', value: 'in' },
+  { label: '不属于', value: 'not in' },
+];
+
+const service = new Service();
+const defaultTerm = { termType: 'like' };
+
+const SearchComponent = <T extends Record<string, any>>({ field, onSearch, target }: Props<T>) => {
+  const intl = useIntl();
+  const [expand, setExpand] = useState<boolean>(true);
+  const initForm = server2Ui([{ terms: [defaultTerm], type: 'and' }, { terms: [defaultTerm] }]);
+  const [logVisible, setLogVisible] = useState<boolean>(false);
+  const [alias, setAlias] = useState<string>('');
+  const [aliasVisible, setAliasVisible] = useState<boolean>(false);
+  const [initParams, setInitParams] = useState<SearchTermsUI>(initForm);
+  const [history, setHistory] = useState([]);
+
+  const form = createForm<SearchTermsUI>({
+    validateFirst: true,
+    initialValues: initParams,
+  });
+
+  const queryHistory = async () => {
+    const response = await service.history.query(`${target}-search`);
+    if (response.status === 200) {
+      setHistory(response.result);
+    }
+  };
+
+  const handleExpand = () => {
+    const value = form.values;
+    if (!expand) {
+      value.terms1.splice(1, 2);
+      value.terms2.splice(1, 2);
+    } else {
+      value.terms2.push(defaultTerm, defaultTerm);
+      value.terms1.push(defaultTerm, defaultTerm);
+    }
+    setInitParams(value);
+    setExpand(!expand);
+  };
+  const SchemaField = createSchemaField({
+    components: {
+      FormItem,
+      FormTab,
+      Input,
+      Select,
+      FormGrid,
+      ArrayItems,
+      PreviewText,
+      GroupNameControl,
+    },
+  });
+
+  const filterSearchTerm = (): EnumData[] =>
+    field
+      .filter((item) => item.dataIndex)
+      .filter((item) => !['index', 'option'].includes(item.dataIndex as string))
+      .map((i) => ({ label: i.title, value: i.dataIndex } as EnumData));
+
+  const createGroup = (name: string): ISchema => ({
+    'x-decorator': 'FormItem',
+    'x-decorator-props': {
+      gridSpan: 4,
+    },
+    'x-component': 'ArrayItems',
+    type: 'array',
+    'x-value': new Array(expand ? 1 : 3).fill({ termType: 'like' }),
+    items: {
+      type: 'object',
+      'x-component': 'FormGrid',
+      'x-component-props': {
+        minColumns: 6,
+        maxColumns: 6,
+      },
+      properties: {
+        type: {
+          'x-decorator': 'FormItem',
+          'x-component': 'GroupNameControl',
+          'x-decorator-props': {
+            gridSpan: 1,
+          },
+          'x-component-props': {
+            name: name,
+          },
+        },
+        column: {
+          type: 'string',
+          'x-decorator': 'FormItem',
+          'x-component': 'Select',
+          'x-decorator-props': {
+            gridSpan: 2,
+          },
+          'x-component-props': {
+            placeholder: '请选择',
+          },
+          enum: filterSearchTerm(),
+        },
+        termType: {
+          type: 'enum',
+          'x-decorator': 'FormItem',
+          'x-component': 'Select',
+          'x-decorator-props': {
+            gridSpan: 1,
+          },
+          default: 'like',
+          enum: termType,
+        },
+        value: {
+          'x-decorator-props': {
+            gridSpan: 2,
+          },
+          'x-decorator': 'FormItem',
+          'x-component': 'Input',
+        },
+      },
+    },
+  });
+
+  const schema: ISchema = {
+    type: 'object',
+    properties: {
+      layout: {
+        type: 'void',
+        'x-component': 'FormGrid',
+        'x-component-props': {
+          minColumns: 9,
+          maxColumns: 9,
+        },
+        properties: {
+          terms1: createGroup('第一组'),
+          type: {
+            'x-decorator': 'FormItem',
+            'x-component': 'Select',
+            'x-decorator-props': {
+              gridSpan: 1,
+              style: {
+                display: 'flex',
+                alignItems: 'center',
+                marginTop: '-22px',
+                padding: '0 30px',
+              },
+            },
+            default: 'and',
+            enum: [
+              { label: '并且', value: 'and' },
+              { label: '或者', value: 'or' },
+            ],
+          },
+          terms2: createGroup('第二组'),
+        },
+      },
+    },
+  };
+
+  const handleHistory = (item: SearchHistory) => {
+    const log = JSON.parse(item.content) as SearchTermsUI;
+    form.setValues(log);
+    setExpand(!(log.terms1?.length > 1 || log.terms2?.length > 1));
+    setInitParams(log);
+  };
+  const historyDom = (
+    <Menu>
+      {history.map((item: SearchHistory) => (
+        <Menu.Item onClick={() => handleHistory(item)} key={item.id}>
+          <div
+            style={{
+              display: 'flex',
+              justifyContent: 'space-between',
+              alignItems: 'center',
+            }}
+          >
+            <span style={{ marginRight: '5px' }}>{item.name}</span>
+            <Popconfirm
+              onConfirm={async () => {
+                const response = await service.history.remove(`${target}-search`, item.key);
+                if (response.status === 200) {
+                  message.success('操作成功');
+                  const temp = history.filter((h: any) => h.key !== item.key);
+                  setHistory(temp);
+                }
+              }}
+              title={'确认删除吗?'}
+            >
+              <DeleteOutlined />
+            </Popconfirm>
+          </div>
+        </Menu.Item>
+      ))}
+    </Menu>
+  );
+
+  const formatValue = (value: SearchTermsUI): SearchTermsServer =>
+    ui2Server(value).map((term) => {
+      term.terms.map((item) => {
+        if (item.termType === 'like') {
+          item.value = `%${item.value}%`;
+          return item;
+        }
+        return item;
+      });
+      return term;
+    });
+
+  const handleSearch = async () => {
+    const value = form.values;
+    setInitParams(value);
+    const filterTerms = (data: Partial<Term>[]) =>
+      data.filter((item) => item.column != null).filter((item) => item.value);
+    const temp = _.cloneDeep(value);
+    temp.terms1 = filterTerms(temp.terms1);
+    temp.terms2 = filterTerms(temp.terms2);
+    onSearch(formatValue(temp));
+  };
+
+  const handleSaveLog = async () => {
+    const value = await form.submit<SearchTermsUI>();
+    const response = await service.history.save(`${target}-search`, {
+      name: alias,
+      content: JSON.stringify(value),
+    });
+    if (response.status === 200) {
+      message.success('保存成功!');
+    } else {
+      message.error('保存失败');
+    }
+    setAliasVisible(!aliasVisible);
+  };
+
+  const resetForm = async () => {
+    const temp = initParams;
+    temp.terms1 = temp.terms1.map(() => defaultTerm);
+    temp.terms2 = temp.terms2.map(() => defaultTerm);
+    setInitParams(temp);
+    await form.reset();
+  };
+  return (
+    <div>
+      <Form form={form} labelCol={4} wrapperCol={18}>
+        <SchemaField schema={schema} />
+        <div className={styles.action}>
+          <FormButtonGroup.FormItem labelCol={10} wrapperCol={14}>
+            <Dropdown.Button
+              placement={'bottomLeft'}
+              trigger={['click']}
+              onClick={handleSearch}
+              visible={logVisible}
+              onVisibleChange={async (visible) => {
+                setLogVisible(visible);
+                if (visible) {
+                  await queryHistory();
+                }
+              }}
+              type="primary"
+              overlay={historyDom}
+            >
+              搜索
+            </Dropdown.Button>
+            <Popover
+              content={
+                <>
+                  <AInput.TextArea
+                    rows={3}
+                    value={alias}
+                    onChange={(e) => setAlias(e.target.value)}
+                  />
+                  <Button onClick={handleSaveLog} type="primary" className={styles.saveLog}>
+                    保存
+                  </Button>
+                </>
+              }
+              visible={aliasVisible}
+              onVisibleChange={(visible) => {
+                setAlias('');
+                setInitParams(form.values);
+                setAliasVisible(visible);
+              }}
+              title="搜索名称"
+              trigger="click"
+            >
+              <Button block>
+                {intl.formatMessage({
+                  id: 'pages.data.option.save',
+                  defaultMessage: '保存',
+                })}
+              </Button>
+            </Popover>
+            <Button block onClick={resetForm}>
+              重置
+            </Button>
+          </FormButtonGroup.FormItem>
+          <div>
+            <DoubleRightOutlined
+              onClick={handleExpand}
+              style={{ fontSize: 20 }}
+              rotate={expand ? 90 : -90}
+            />
+          </div>
+        </div>
+      </Form>
+    </div>
+  );
+};
+export default SearchComponent;

+ 24 - 0
src/components/SearchComponent/service.ts

@@ -0,0 +1,24 @@
+import { request } from 'umi';
+import SystemConst from '@/utils/const';
+
+class Service {
+  private api = `/${SystemConst.API_BASE}/user/settings`;
+
+  public history = {
+    query: (type: string) =>
+      request(`${this.api}/${type}`, {
+        method: 'GET',
+      }),
+    save: (type: string, data: Record<string, unknown>) =>
+      request(`${this.api}/${type}`, {
+        method: 'POST',
+        data,
+      }),
+    remove: (type: string, key: string) =>
+      request(`${this.api}/${type}/${key}`, {
+        method: 'DELETE',
+      }),
+  };
+}
+
+export default Service;

+ 27 - 0
src/components/SearchComponent/typings.d.ts

@@ -0,0 +1,27 @@
+type Term = {
+  column: string | null;
+  value: string;
+  termType: string;
+  type?: 'or' | 'and';
+};
+
+type SearchTermsUI = {
+  terms1: Partial<Term>[];
+  type: 'or' | 'and';
+  terms2: Partial<Term>[];
+};
+
+type SearchTermsServer = {
+  terms: Partial<Term>[];
+  type?: 'or' | 'and';
+}[];
+
+type SearchHistory = {
+  id: string;
+  key: string;
+  name: string;
+  type: string;
+  userId: string;
+  createTime: number;
+  content: string;
+};

+ 1 - 0
src/locales/en-US/pages.ts

@@ -27,6 +27,7 @@ export default {
   'pages.data.option.detail': 'Detail',
   'pages.data.option.download': 'Download',
   'pages.data.option.record': 'Records',
+  'pages.data.option.save': 'Save',
   'pages.searchTable.new': 'New',
   'pages.searchTable.titleStatus': 'Status',
   'pages.searchTable.titleStatus.all': 'All',

+ 1 - 0
src/locales/zh-CN/pages.ts

@@ -27,6 +27,7 @@ export default {
   'pages.data.option.detail': '详情',
   'pages.data.option.download': '下载',
   'pages.data.option.record': '通知记录',
+  'pages.data.option.save': '保存',
   'pages.searchTable.new': '新建',
   'pages.searchTable.titleStatus': '状态',
   'pages.searchTable.titleStatus.all': '全部',

+ 5 - 5
src/pages/system/OpenAPI/index.tsx

@@ -63,29 +63,29 @@ const OpenAPI: React.FC = observer(() => {
       valueType: 'select',
       hideInForm: true,
       onFilter: true,
-      valueEnum: [
-        {
+      valueEnum: {
+        default: {
           text: intl.formatMessage({
             id: 'pages.searchTable.titleStatus.all',
             defaultMessage: '全部',
           }),
           status: 'Default',
         },
-        {
+        '1': {
           text: intl.formatMessage({
             id: 'pages.searchTable.titleStatus.normal',
             defaultMessage: '正常',
           }),
           status: '1',
         },
-        {
+        '0': {
           text: intl.formatMessage({
             id: 'pages.searchTable.titleStatus.disable',
             defaultMessage: '禁用',
           }),
           status: '0',
         },
-      ],
+      },
     },
     {
       title: intl.formatMessage({

+ 0 - 59
src/pages/system/Org/NodeTemplate/index.tsx

@@ -1,59 +0,0 @@
-import styles from '../index.less';
-import { Avatar, Dropdown } from 'antd';
-import { SmallDashOutlined, UserOutlined } from '@ant-design/icons';
-import React from 'react';
-import type { OrgItem } from '@/pages/system/Org/typings';
-import { useIntl } from '@@/plugin-locale/localeExports';
-
-declare type OverlayFunc = () => React.ReactElement;
-
-interface Props {
-  data: Partial<OrgItem>;
-  action: React.ReactElement | OverlayFunc;
-}
-
-const NodeTemplate: React.FC<Props> = (props) => {
-  const intl = useIntl();
-  const { data, action } = props;
-  return (
-    <div className={styles.node}>
-      <div className={styles.top}>
-        <span className={styles.title}>{data.name}</span>
-        <Avatar size="small" icon={<UserOutlined />} />
-      </div>
-
-      <div className={styles.content}>
-        <div className={styles.item}>
-          {data.code !== null && (
-            <div>
-              <span className={styles.mark}>
-                {intl.formatMessage({
-                  id: 'pages.system.org.encoding',
-                  defaultMessage: '编码',
-                })}
-              </span>
-              <span>{data.code}</span>
-            </div>
-          )}
-          <div>
-            <span className={styles.mark}>
-              {intl.formatMessage({
-                id: 'pages.system.org.count',
-                defaultMessage: '下级数量',
-              })}
-            </span>
-            <span>{data?.children?.length || 0}</span>
-          </div>
-        </div>
-        <div className={styles.action}>
-          <Dropdown overlay={action}>
-            <a className="ant-dropdown-link" onClick={(e) => e.preventDefault()}>
-              <SmallDashOutlined />
-            </a>
-          </Dropdown>
-        </div>
-      </div>
-    </div>
-  );
-};
-export default NodeTemplate;

+ 0 - 101
src/pages/system/Org/Save/index.tsx

@@ -1,101 +0,0 @@
-import { message, Modal } from 'antd';
-import { createForm } from '@formily/core';
-import { createSchemaField } from '@formily/react';
-import { NumberPicker, Form, Input, FormItem } from '@formily/antd';
-import { useIntl } from '@@/plugin-locale/localeExports';
-import OrgModel from '@/pages/system/Org/model';
-import { service } from '@/pages/system/Org';
-
-interface Props {
-  refresh?: () => void;
-  visible: boolean;
-}
-
-const Save = (props: Props) => {
-  const intl = useIntl();
-  const form = createForm({
-    initialValues: OrgModel.current,
-  });
-
-  const SchemaField = createSchemaField({
-    components: {
-      FormItem,
-      Input,
-      NumberPicker,
-    },
-  });
-
-  const schema = {
-    type: 'object',
-    properties: {
-      code: {
-        title: intl.formatMessage({
-          id: 'pages.system.org.encoding',
-          defaultMessage: '编码',
-        }),
-        type: 'string',
-        'x-decorator': 'FormItem',
-        'x-component': 'Input',
-        name: 'id',
-        required: true,
-      },
-      name: {
-        title: intl.formatMessage({
-          id: 'pages.table.name',
-          defaultMessage: '名称',
-        }),
-        type: 'string',
-        'x-decorator': 'FormItem',
-        'x-component': 'Input',
-        name: 'name',
-        required: true,
-      },
-      sortIndex: {
-        title: intl.formatMessage({
-          id: 'pages.system.org.add.orderNumber',
-          defaultMessage: '序号',
-        }),
-        type: 'string',
-        'x-decorator': 'FormItem',
-        'x-component': 'NumberPicker',
-        name: 'name',
-        required: true,
-      },
-      describe: {
-        title: intl.formatMessage({
-          id: 'pages.table.describe',
-          defaultMessage: '描述',
-        }),
-        type: 'string',
-        'x-decorator': 'FormItem',
-        'x-component': 'Input.TextArea',
-        name: 'describe',
-      },
-    },
-  };
-
-  const save = async () => {
-    const data: Record<string, unknown> = await form.submit!();
-    await service.update({ ...data, parentId: OrgModel.parentId });
-    message.success('保存成功');
-    OrgModel.closeEdit();
-    props.refresh?.();
-  };
-
-  return (
-    <Modal
-      onOk={() => save()}
-      title={`${OrgModel.parentId ? '添加下级' : '编辑'}`}
-      visible={props.visible}
-      onCancel={() => {
-        OrgModel.closeEdit();
-        props.refresh?.();
-      }}
-    >
-      <Form form={form} labelCol={5} wrapperCol={16}>
-        <SchemaField schema={schema} />
-      </Form>
-    </Modal>
-  );
-};
-export default Save;

+ 0 - 70
src/pages/system/Org/index.less

@@ -1,70 +0,0 @@
-.orgContainer {
-  :global {
-    .orgchart {
-      background: #fff;
-    }
-    .orgchart-container {
-      border: none;
-    }
-  }
-}
-
-.node {
-  display: flex;
-  flex-direction: column;
-  min-width: 140px;
-  border: 1px solid #4c77bf;
-  border-radius: 3px;
-  transition: 0.3s;
-}
-
-.node:hover {
-  box-shadow: 0 0 10px 10px #b1d9ff;
-}
-
-.top {
-  display: flex;
-  align-items: center;
-  justify-content: space-between;
-  height: 36px;
-  padding: 0 12px;
-  color: #fff;
-  font-size: 14px;
-  background: #4c77bf;
-}
-
-.title {
-  margin-right: 12px;
-  white-space: nowrap;
-}
-
-.content {
-  display: flex;
-  flex: 1 1;
-  align-items: center;
-  justify-content: space-between;
-  padding: 3px 12px;
-  background: #fff;
-}
-
-.item > div {
-  display: flex;
-}
-
-.mark {
-  display: flex;
-  justify-content: flex-start;
-  width: 50px;
-  margin-right: 10px;
-  color: rgba(0, 0, 0, 0.45);
-  font-size: 14px;
-  white-space: nowrap;
-}
-
-.action {
-  align-self: flex-end;
-  height: 100%;
-  padding-bottom: 3px;
-  vertical-align: bottom;
-  cursor: pointer;
-}

+ 0 - 179
src/pages/system/Org/index.tsx

@@ -1,179 +0,0 @@
-import { PageContainer } from '@ant-design/pro-layout';
-import OrganizationChart from '@dabeng/react-orgchart';
-import styles from './index.less';
-import { Drawer, Menu, message, Modal } from 'antd';
-import NodeTemplate from '@/pages/system/Org/NodeTemplate';
-import { observer } from '@formily/react';
-import { useEffect } from 'react';
-import Service from '@/pages/system/Org/service';
-import encodeQuery from '@/utils/encodeQuery';
-import Save from '@/pages/system/Org/Save';
-import { useIntl } from '@@/plugin-locale/localeExports';
-import autzModel from '@/components/Authorization/autz';
-import Authorization from '@/components/Authorization';
-import { BindModel } from '@/components/BindUser/model';
-import BindUser from '@/components/BindUser';
-import OrgModel from '@/pages/system/Org/model';
-
-export const service = new Service('organization');
-const Org = observer(() => {
-  const intl = useIntl();
-  const hitCenter = () => {
-    const orgChart = document.getElementsByClassName('orgchart-container')[0];
-    const { width } = orgChart.getBoundingClientRect();
-    orgChart.scrollLeft = width;
-  };
-
-  const query = async () => {
-    const response = await service.queryTree(
-      encodeQuery({
-        paging: false,
-        terms: { typeId: 'org' },
-      }),
-    );
-    OrgModel.data = {
-      id: null,
-      name: intl.formatMessage({
-        id: 'pages.system.org',
-        defaultMessage: '机构管理',
-      }),
-      title: '组织架构',
-      children: response.result,
-    };
-    hitCenter();
-    return OrgModel;
-  };
-
-  const remove = async (id: string) => {
-    await service.remove(id);
-    await query();
-    message.success(
-      intl.formatMessage({
-        id: 'pages.data.option.success',
-        defaultMessage: '操作成功!',
-      }),
-    );
-  };
-  useEffect(() => {
-    query();
-  }, []);
-
-  const menu = (nodeData: any) => {
-    const addNext = (
-      <Menu.Item key="addNext">
-        <a key="addNext" onClick={() => OrgModel.addNext(nodeData)}>
-          {intl.formatMessage({
-            id: 'pages.system.org.option.add',
-            defaultMessage: '添加下级',
-          })}
-        </a>
-      </Menu.Item>
-    );
-    return nodeData.id === null ? (
-      <Menu>{addNext}</Menu>
-    ) : (
-      <Menu>
-        <Menu.Item key="edit">
-          <a
-            key="edit"
-            onClick={() => {
-              OrgModel.update(nodeData);
-            }}
-          >
-            {intl.formatMessage({
-              id: 'pages.data.option.edit',
-              defaultMessage: '编辑',
-            })}
-          </a>
-        </Menu.Item>
-        {addNext}
-        <Menu.Item key="autz">
-          <a
-            key="autz"
-            onClick={() => {
-              autzModel.autzTarget.id = nodeData.id;
-              autzModel.autzTarget.name = nodeData.name;
-              autzModel.visible = true;
-            }}
-          >
-            {intl.formatMessage({
-              id: 'pages.system.org.option.permission',
-              defaultMessage: '权限分配',
-            })}
-          </a>
-        </Menu.Item>
-        <Menu.Item key="bindUser">
-          <a
-            key="bindUser"
-            onClick={() => {
-              BindModel.dimension = {
-                id: nodeData.id,
-                name: nodeData.name,
-                type: 'org',
-              };
-              BindModel.visible = true;
-            }}
-          >
-            {intl.formatMessage({
-              id: 'pages.system.org.option.bindUser',
-              defaultMessage: '绑定用户',
-            })}
-          </a>
-        </Menu.Item>
-        <Menu.Item key="delete">
-          <a key="delete" onClick={() => remove(nodeData.id)}>
-            {intl.formatMessage({
-              id: 'pages.data.option.remove',
-              defaultMessage: '删除',
-            })}
-          </a>
-        </Menu.Item>
-      </Menu>
-    );
-  };
-  return (
-    <PageContainer>
-      <div className={styles.orgContainer}>
-        <OrganizationChart
-          datasource={OrgModel.data}
-          pan={true}
-          NodeTemplate={(nodeData: any) => (
-            <NodeTemplate data={nodeData.nodeData} action={menu(nodeData.nodeData)} />
-          )}
-        />
-      </div>
-      <Save refresh={query} visible={OrgModel.edit} />
-      <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="50vw"
-        visible={autzModel.visible}
-        onClose={() => {
-          autzModel.visible = false;
-        }}
-      >
-        <Authorization
-          close={() => {
-            autzModel.visible = false;
-          }}
-          target={autzModel.autzTarget}
-        />
-      </Drawer>
-    </PageContainer>
-  );
-});
-
-export default Org;

+ 0 - 33
src/pages/system/Org/model.ts

@@ -1,33 +0,0 @@
-import { model } from '@formily/reactive';
-import type { OrgItem, OrgModelType } from '@/pages/system/Org/typings';
-
-const OrgModel = model<OrgModelType>({
-  edit: false,
-  parentId: '',
-  data: {},
-  current: {},
-  authorize: true,
-
-  update(data: Partial<OrgItem>) {
-    this.current = data;
-    this.edit = true;
-    this.parentId = undefined;
-  },
-
-  addNext(parentData: Partial<OrgItem>) {
-    this.parentId = parentData.id;
-    this.edit = true;
-    this.current = {};
-  },
-
-  authorized(data: Partial<OrgItem>) {
-    this.current = data;
-    this.authorize = true;
-  },
-  closeEdit() {
-    this.current = {};
-    this.edit = false;
-  },
-});
-
-export default OrgModel;

+ 0 - 11
src/pages/system/Org/service.ts

@@ -1,11 +0,0 @@
-import BaseService from '@/utils/BaseService';
-import type { OrgItem } from '@/pages/system/Org/typings';
-import { request } from '@@/plugin-request/request';
-
-class Service extends BaseService<OrgItem> {
-  queryTree(params: any): Promise<any> {
-    return request(`${this.uri}/_all/tree`, { params, method: 'GET' });
-  }
-}
-
-export default Service;

+ 0 - 32
src/pages/system/Org/typings.d.ts

@@ -1,32 +0,0 @@
-export type OrgItem = {
-  id: string;
-  parentId: string | undefined;
-  path: string;
-  sortIndex: number;
-  level: number;
-  name: string;
-  describe: string;
-  permissionExpresion: string;
-  url: string;
-  icon: string;
-  status: number;
-  code?: string;
-  children?: OrgItem[];
-};
-
-export type OrgModelType = {
-  data: Partial<{
-    id: null;
-    name: string;
-    title: string;
-    children: Partial<OrgItem>[];
-  }>;
-  current: Partial<OrgItem>;
-  parentId: string | undefined;
-  edit: boolean;
-  update: (data: Partial<OrgItem>) => void;
-  addNext: (parentData: Partial<OrgItem>) => void;
-  authorize: boolean;
-  authorized: (data: Partial<OrgItem>) => void;
-  closeEdit: () => void;
-};

+ 5 - 5
src/pages/system/Tenant/index.tsx

@@ -70,29 +70,29 @@ const Tenant = observer(() => {
       hideInForm: true,
       onFilter: true,
       search: false,
-      valueEnum: [
-        {
+      valueEnum: {
+        default: {
           text: intl.formatMessage({
             id: 'pages.searchTable.titleStatus.all',
             defaultMessage: '全部',
           }),
           status: 'Default',
         },
-        {
+        '1': {
           text: intl.formatMessage({
             id: 'pages.searchTable.titleStatus.normal',
             defaultMessage: '正常',
           }),
           status: '1',
         },
-        {
+        '0': {
           text: intl.formatMessage({
             id: 'pages.searchTable.titleStatus.disable',
             defaultMessage: '禁用',
           }),
           status: '0',
         },
-      ],
+      },
     },
     {
       title: intl.formatMessage({

+ 7 - 0
src/pages/system/User/index.tsx

@@ -18,6 +18,7 @@ import { useIntl } from '@@/plugin-locale/localeExports';
 import type { ISchema } from '@formily/json-schema';
 import Authorization from '@/components/Authorization';
 import autzModel from '@/components/Authorization/autz';
+// import SearchComponent from '@/components/SearchComponent';
 
 export const service = new BaseService<UserItem>('user');
 const User = observer(() => {
@@ -288,16 +289,22 @@ const User = observer(() => {
     },
   };
 
+  intl.formatMessage({
+    id: 'pages.system.user',
+    defaultMessage: '默认值',
+  });
   return (
     <PageContainer>
       <BaseCrud<UserItem>
         actionRef={actionRef}
         columns={columns}
+        search={false}
         service={service}
         title={intl.formatMessage({
           id: 'pages.system.user',
           defaultMessage: '用户管理',
         })}
+        moduleName="user"
         schema={schema}
       />
       <Drawer

+ 2 - 2
src/utils/BaseService.ts

@@ -19,8 +19,8 @@ class BaseService<T> implements IBaseService<T> {
     this.uri = `/${SystemConst.API_BASE}/${uri}`;
   }
 
-  query(params: any): Promise<any> {
-    return request(`${this.uri}/_query/`, { params, method: 'GET' });
+  query(data: any): Promise<any> {
+    return request(`${this.uri}/_query/`, { data, method: 'POST' });
   }
 
   queryNoPaging(params: any): Promise<unknown> {

+ 5 - 0
src/utils/typings.d.ts

@@ -20,3 +20,8 @@ type State = {
   value: string;
   text: string;
 };
+
+type EnumData = {
+  label: string;
+  value: string;
+};