lots of updates
This commit is contained in:
		
							parent
							
								
									c23d2c5c3c
								
							
						
					
					
						commit
						5b014bc67e
					
				@ -21,6 +21,7 @@ import * as uiSchema from './ui-schema';
 | 
				
			|||||||
  const Collection = database.getModel('collections');
 | 
					  const Collection = database.getModel('collections');
 | 
				
			||||||
  const collection = await Collection.create(config);
 | 
					  const collection = await Collection.create(config);
 | 
				
			||||||
  await collection.updateAssociations(config);
 | 
					  await collection.updateAssociations(config);
 | 
				
			||||||
 | 
					  await collection.migrate();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const Route = database.getModel('routes');
 | 
					  const Route = database.getModel('routes');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -29,6 +29,7 @@
 | 
				
			|||||||
    "axios": "^0.21.1",
 | 
					    "axios": "^0.21.1",
 | 
				
			||||||
    "beautiful-react-hooks": "^0.35.0",
 | 
					    "beautiful-react-hooks": "^0.35.0",
 | 
				
			||||||
    "constate": "^3.3.0",
 | 
					    "constate": "^3.3.0",
 | 
				
			||||||
 | 
					    "flat": "^5.0.2",
 | 
				
			||||||
    "html-react-parser": "^1.2.7",
 | 
					    "html-react-parser": "^1.2.7",
 | 
				
			||||||
    "lodash": "^4.17.21",
 | 
					    "lodash": "^4.17.21",
 | 
				
			||||||
    "monaco-editor": "^0.25.2",
 | 
					    "monaco-editor": "^0.25.2",
 | 
				
			||||||
 | 
				
			|||||||
@ -19,7 +19,7 @@ import { useMemo } from 'react';
 | 
				
			|||||||
import { CodeOutlined } from '@ant-design/icons';
 | 
					import { CodeOutlined } from '@ant-design/icons';
 | 
				
			||||||
import Editor from '@monaco-editor/react';
 | 
					import Editor from '@monaco-editor/react';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { ArrayCollapse, FormLayout, FormItem as FormilyFormItem } from '@formily/antd';
 | 
					import { ArrayItems, ArrayCollapse, FormLayout, FormItem as FormilyFormItem } from '@formily/antd';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Space, Card, Modal, Spin } from 'antd';
 | 
					import { Space, Card, Modal, Spin } from 'antd';
 | 
				
			||||||
import { ArrayTable } from '../../schemas/array-table';
 | 
					import { ArrayTable } from '../../schemas/array-table';
 | 
				
			||||||
@ -74,6 +74,7 @@ export const SchemaField = createSchemaField({
 | 
				
			|||||||
    Page,
 | 
					    Page,
 | 
				
			||||||
    Chart,
 | 
					    Chart,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ArrayItems,
 | 
				
			||||||
    ArrayCollapse,
 | 
					    ArrayCollapse,
 | 
				
			||||||
    ArrayTable,
 | 
					    ArrayTable,
 | 
				
			||||||
    FormLayout,
 | 
					    FormLayout,
 | 
				
			||||||
@ -365,6 +366,47 @@ export function useDesignable(path?: any) {
 | 
				
			|||||||
      refresh();
 | 
					      refresh();
 | 
				
			||||||
      return target;
 | 
					      return target;
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    moveToBefore(path1, path2) {
 | 
				
			||||||
 | 
					      const source = findPropertyByPath(schema, path1);
 | 
				
			||||||
 | 
					      const property = source.toJSON();
 | 
				
			||||||
 | 
					      const target = findPropertyByPath(schema, path2);
 | 
				
			||||||
 | 
					      if (!target) {
 | 
				
			||||||
 | 
					        console.error('target schema does not exist.');
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if (!property.name) {
 | 
				
			||||||
 | 
					        property.name = uid();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if (target['parentKey']) {
 | 
				
			||||||
 | 
					        property['parentKey'] = target['parentKey'];
 | 
				
			||||||
 | 
					        setKeys(property);
 | 
				
			||||||
 | 
					        property['__insertBefore__'] = target['key'];
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      addPropertyBefore(target, property);
 | 
				
			||||||
 | 
					      refresh();
 | 
				
			||||||
 | 
					      return target.parent.properties[property.name];
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    moveToAfter(path1, path2) {
 | 
				
			||||||
 | 
					      const source = findPropertyByPath(schema, path1);
 | 
				
			||||||
 | 
					      const property = source.toJSON();
 | 
				
			||||||
 | 
					      const target = findPropertyByPath(schema, path2);
 | 
				
			||||||
 | 
					      if (!target) {
 | 
				
			||||||
 | 
					        console.error('target schema does not exist.');
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if (!property.name) {
 | 
				
			||||||
 | 
					        property.name = uid();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if (target['parentKey']) {
 | 
				
			||||||
 | 
					        property['parentKey'] = target['parentKey'];
 | 
				
			||||||
 | 
					        setKeys(property);
 | 
				
			||||||
 | 
					        property['__insertAfter__'] = target['key'];
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      addPropertyAfter(target, property);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      refresh();
 | 
				
			||||||
 | 
					      return target.parent.properties[property.name];
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -14,31 +14,36 @@ export interface CollectionProviderProps {
 | 
				
			|||||||
  collectionName?: string;
 | 
					  collectionName?: string;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const [CollectionProvider, useCollectionContext] = constate(
 | 
					export function useCollection(props: CollectionProviderProps) {
 | 
				
			||||||
  (props: CollectionProviderProps) => {
 | 
					  const { collectionName } = props;
 | 
				
			||||||
    const { collectionName } = props;
 | 
					  const { collections = [], loading, refresh } = useCollectionsContext();
 | 
				
			||||||
    const { collections = [], loading, refresh } = useCollectionsContext();
 | 
					  let collection: any;
 | 
				
			||||||
    let collection: any;
 | 
					  let fields = [];
 | 
				
			||||||
    let fields = [];
 | 
					  if (collectionName) {
 | 
				
			||||||
    if (collectionName) {
 | 
					    collection = collections.find((item) => item.name === collectionName);
 | 
				
			||||||
      collection = collections.find((item) => item.name === collectionName);
 | 
					  }
 | 
				
			||||||
    }
 | 
					  if (collection) {
 | 
				
			||||||
    if (collection) {
 | 
					    fields = collection?.fields || [];
 | 
				
			||||||
      fields = collection?.fields || [];
 | 
					  }
 | 
				
			||||||
    }
 | 
					  let sortableField = collection.sortable;
 | 
				
			||||||
    return {
 | 
					  if (collection.sortable && typeof collection.sortable === 'object') {
 | 
				
			||||||
      collection,
 | 
					    sortableField = collection.sortable?.name;
 | 
				
			||||||
      fields,
 | 
					  }
 | 
				
			||||||
      loading,
 | 
					  return {
 | 
				
			||||||
      refresh,
 | 
					    sortableField,
 | 
				
			||||||
      getField(name: string) {
 | 
					    collection,
 | 
				
			||||||
        if (!name) {
 | 
					    fields,
 | 
				
			||||||
          return null;
 | 
					    loading,
 | 
				
			||||||
        }
 | 
					    refresh,
 | 
				
			||||||
        return fields.find((item) => item.name === name);
 | 
					    getField(name: string) {
 | 
				
			||||||
      },
 | 
					      if (!name) {
 | 
				
			||||||
    };
 | 
					        return null;
 | 
				
			||||||
  },
 | 
					      }
 | 
				
			||||||
);
 | 
					      return fields.find((item) => item.name === name);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const [CollectionProvider, useCollectionContext] = constate(useCollection);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export { CollectionProvider, useCollectionContext };
 | 
					export { CollectionProvider, useCollectionContext };
 | 
				
			||||||
 | 
				
			|||||||
@ -17,6 +17,8 @@ export interface SaveOptions {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface ListOptions {
 | 
					export interface ListOptions {
 | 
				
			||||||
 | 
					  defaultFilter?: any;
 | 
				
			||||||
 | 
					  filter?: any;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export class Resource {
 | 
					export class Resource {
 | 
				
			||||||
@ -31,9 +33,28 @@ export class Resource {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  list(options: ListOptions = {}) {
 | 
					  sort(options) {
 | 
				
			||||||
    const { resourceName } = this.options;
 | 
					    const { resourceName } = this.options;
 | 
				
			||||||
    return request(`${resourceName}:list`);
 | 
					    const { resourceKey, target, field = 'sort' } = options;
 | 
				
			||||||
 | 
					    return request(`${resourceName}:sort/${resourceKey}`, {
 | 
				
			||||||
 | 
					      method: 'post',
 | 
				
			||||||
 | 
					      data: {
 | 
				
			||||||
 | 
					        target,
 | 
				
			||||||
 | 
					        field,
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  list(options: ListOptions = {}) {
 | 
				
			||||||
 | 
					    const { defaultFilter, filter, ...others } = options;
 | 
				
			||||||
 | 
					    const { resourceName } = this.options;
 | 
				
			||||||
 | 
					    return request(`${resourceName}:list`, {
 | 
				
			||||||
 | 
					      method: 'get',
 | 
				
			||||||
 | 
					      params: {
 | 
				
			||||||
 | 
					        filter: decodeURIComponent(JSON.stringify({ and: [defaultFilter, filter].filter(Boolean) })),
 | 
				
			||||||
 | 
					        ...others,
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  get(options: GetOptions = {}) {
 | 
					  get(options: GetOptions = {}) {
 | 
				
			||||||
 | 
				
			|||||||
@ -7,6 +7,7 @@ export const createdAt: ISchema = {
 | 
				
			|||||||
  group: 'systemInfo',
 | 
					  group: 'systemInfo',
 | 
				
			||||||
  order: 1,
 | 
					  order: 1,
 | 
				
			||||||
  title: '创建时间',
 | 
					  title: '创建时间',
 | 
				
			||||||
 | 
					  sortable: true,
 | 
				
			||||||
  default: {
 | 
					  default: {
 | 
				
			||||||
    dataType: 'date',
 | 
					    dataType: 'date',
 | 
				
			||||||
    field: 'created_at',
 | 
					    field: 'created_at',
 | 
				
			||||||
 | 
				
			|||||||
@ -7,6 +7,7 @@ export const datetime: ISchema = {
 | 
				
			|||||||
  group: 'datetime',
 | 
					  group: 'datetime',
 | 
				
			||||||
  order: 1,
 | 
					  order: 1,
 | 
				
			||||||
  title: '日期',
 | 
					  title: '日期',
 | 
				
			||||||
 | 
					  sortable: true,
 | 
				
			||||||
  default: {
 | 
					  default: {
 | 
				
			||||||
    dataType: 'date',
 | 
					    dataType: 'date',
 | 
				
			||||||
    // name,
 | 
					    // name,
 | 
				
			||||||
 | 
				
			|||||||
@ -7,6 +7,7 @@ export const email: ISchema = {
 | 
				
			|||||||
  group: 'basic',
 | 
					  group: 'basic',
 | 
				
			||||||
  order: 4,
 | 
					  order: 4,
 | 
				
			||||||
  title: '电子邮箱',
 | 
					  title: '电子邮箱',
 | 
				
			||||||
 | 
					  sortable: true,
 | 
				
			||||||
  default: {
 | 
					  default: {
 | 
				
			||||||
    dataType: 'string',
 | 
					    dataType: 'string',
 | 
				
			||||||
    // name,
 | 
					    // name,
 | 
				
			||||||
 | 
				
			|||||||
@ -7,6 +7,7 @@ export const number: ISchema = {
 | 
				
			|||||||
  group: 'basic',
 | 
					  group: 'basic',
 | 
				
			||||||
  order: 5,
 | 
					  order: 5,
 | 
				
			||||||
  title: '数字',
 | 
					  title: '数字',
 | 
				
			||||||
 | 
					  sortable: true,
 | 
				
			||||||
  default: {
 | 
					  default: {
 | 
				
			||||||
    dataType: 'float',
 | 
					    dataType: 'float',
 | 
				
			||||||
    // name,
 | 
					    // name,
 | 
				
			||||||
 | 
				
			|||||||
@ -7,6 +7,7 @@ export const percent: ISchema = {
 | 
				
			|||||||
  group: 'basic',
 | 
					  group: 'basic',
 | 
				
			||||||
  order: 6,
 | 
					  order: 6,
 | 
				
			||||||
  title: '百分比',
 | 
					  title: '百分比',
 | 
				
			||||||
 | 
					  sortable: true,
 | 
				
			||||||
  default: {
 | 
					  default: {
 | 
				
			||||||
    dataType: 'float',
 | 
					    dataType: 'float',
 | 
				
			||||||
    // name,
 | 
					    // name,
 | 
				
			||||||
 | 
				
			|||||||
@ -7,6 +7,7 @@ export const phone: ISchema = {
 | 
				
			|||||||
  group: 'basic',
 | 
					  group: 'basic',
 | 
				
			||||||
  order: 3,
 | 
					  order: 3,
 | 
				
			||||||
  title: '手机号码',
 | 
					  title: '手机号码',
 | 
				
			||||||
 | 
					  sortable: true,
 | 
				
			||||||
  default: {
 | 
					  default: {
 | 
				
			||||||
    dataType: 'string',
 | 
					    dataType: 'string',
 | 
				
			||||||
    // name,
 | 
					    // name,
 | 
				
			||||||
 | 
				
			|||||||
@ -7,6 +7,7 @@ export const string: ISchema = {
 | 
				
			|||||||
  group: 'basic',
 | 
					  group: 'basic',
 | 
				
			||||||
  order: 1,
 | 
					  order: 1,
 | 
				
			||||||
  title: '单行文本',
 | 
					  title: '单行文本',
 | 
				
			||||||
 | 
					  sortable: true,
 | 
				
			||||||
  default: {
 | 
					  default: {
 | 
				
			||||||
    interface: 'string',
 | 
					    interface: 'string',
 | 
				
			||||||
    dataType: 'string',
 | 
					    dataType: 'string',
 | 
				
			||||||
 | 
				
			|||||||
@ -7,6 +7,7 @@ export const time: ISchema = {
 | 
				
			|||||||
  group: 'datetime',
 | 
					  group: 'datetime',
 | 
				
			||||||
  order: 2,
 | 
					  order: 2,
 | 
				
			||||||
  title: '时间',
 | 
					  title: '时间',
 | 
				
			||||||
 | 
					  sortable: true,
 | 
				
			||||||
  default: {
 | 
					  default: {
 | 
				
			||||||
    dataType: 'time',
 | 
					    dataType: 'time',
 | 
				
			||||||
    // name,
 | 
					    // name,
 | 
				
			||||||
 | 
				
			|||||||
@ -7,6 +7,7 @@ export const updatedAt: ISchema = {
 | 
				
			|||||||
  group: 'systemInfo',
 | 
					  group: 'systemInfo',
 | 
				
			||||||
  order: 2,
 | 
					  order: 2,
 | 
				
			||||||
  title: '最后更新时间',
 | 
					  title: '最后更新时间',
 | 
				
			||||||
 | 
					  sortable: true,
 | 
				
			||||||
  default: {
 | 
					  default: {
 | 
				
			||||||
    dataType: 'date',
 | 
					    dataType: 'date',
 | 
				
			||||||
    field: 'updated_at',
 | 
					    field: 'updated_at',
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
import React, { useContext, useMemo, useState } from 'react';
 | 
					import React, { useContext, useMemo, useState } from 'react';
 | 
				
			||||||
import { SchemaField } from '..';
 | 
					import { SchemaField } from '..';
 | 
				
			||||||
import { createForm, onFieldChange, onFieldReact } from '@formily/core';
 | 
					import { createForm, onFieldChange, onFieldReact, onFormValuesChange } from '@formily/core';
 | 
				
			||||||
import { FormProvider, FormConsumer, useFieldSchema, Schema, SchemaOptionsContext, ISchema } from '@formily/react';
 | 
					import { FormProvider, FormConsumer, useFieldSchema, Schema, SchemaOptionsContext, ISchema, SchemaKey } from '@formily/react';
 | 
				
			||||||
import { Field } from '@formily/core/esm/models/Field';
 | 
					import { Field } from '@formily/core/esm/models/Field';
 | 
				
			||||||
import { Form } from '@formily/core/esm/models/Form';
 | 
					import { Form } from '@formily/core/esm/models/Form';
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
@ -14,26 +14,73 @@ import {
 | 
				
			|||||||
} from '@formily/antd';
 | 
					} from '@formily/antd';
 | 
				
			||||||
import { CloseCircleOutlined } from '@ant-design/icons';
 | 
					import { CloseCircleOutlined } from '@ant-design/icons';
 | 
				
			||||||
import { get } from 'lodash';
 | 
					import { get } from 'lodash';
 | 
				
			||||||
 | 
					import { isValid } from '@formily/shared';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function useFilterColumns(): Schema[] {
 | 
					function useFilterColumns(): Map<SchemaKey, Schema> {
 | 
				
			||||||
  const schema = useFieldSchema();
 | 
					  const schema = useFieldSchema();
 | 
				
			||||||
  const columns = schema.reduceProperties((columns, current) => {
 | 
					  const columns = schema.reduceProperties((columns, current) => {
 | 
				
			||||||
    if (current['x-component'] === 'Filter.Column') {
 | 
					    if (current['x-component'] === 'Filter.Column') {
 | 
				
			||||||
      return [...columns, current];
 | 
					      const fieldName = Object.keys(current.properties).shift();
 | 
				
			||||||
 | 
					      columns.set(fieldName, current);
 | 
				
			||||||
 | 
					      return columns;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return [...columns];
 | 
					    return columns;
 | 
				
			||||||
  }, []);
 | 
					  }, new Map<SchemaKey, Schema>());
 | 
				
			||||||
  return columns;
 | 
					  return columns;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const FilterItem = (props) => {
 | 
					export const FilterItem = (props) => {
 | 
				
			||||||
  const { initialValues = {}, onRemove } = props;
 | 
					  const { value, initialValues = {}, onRemove, onChange } = props;
 | 
				
			||||||
 | 
					 | 
				
			||||||
  const options = useContext(SchemaOptionsContext);
 | 
					  const options = useContext(SchemaOptionsContext);
 | 
				
			||||||
 | 
					 | 
				
			||||||
  const { key } = initialValues;
 | 
					 | 
				
			||||||
  const columns = useFilterColumns();
 | 
					  const columns = useFilterColumns();
 | 
				
			||||||
  console.log('useFilterColumns', columns);
 | 
					  console.log('FilterItem', value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const toValues = (value) => {
 | 
				
			||||||
 | 
					    if (!value) {
 | 
				
			||||||
 | 
					      return {};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (Object.keys(value).length === 0) {
 | 
				
			||||||
 | 
					      return {};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const fieldName = Object.keys(value).shift();
 | 
				
			||||||
 | 
					    const nested = value[fieldName];
 | 
				
			||||||
 | 
					    const column = columns.get(fieldName).toJSON();
 | 
				
			||||||
 | 
					    if (!nested) {
 | 
				
			||||||
 | 
					      return {
 | 
				
			||||||
 | 
					        column,
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (Object.keys(nested).length === 0) {
 | 
				
			||||||
 | 
					      return {
 | 
				
			||||||
 | 
					        column,
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const operationValue = Object.keys(nested).shift();
 | 
				
			||||||
 | 
					    console.log('toValues', {operationValue});
 | 
				
			||||||
 | 
					    const operations = column?.['x-component-props']?.['operations']||[];
 | 
				
			||||||
 | 
					    const operation = operations.find(operation => operation.value === operationValue);
 | 
				
			||||||
 | 
					    console.log('toValues', {operation});
 | 
				
			||||||
 | 
					    if (!operation) {
 | 
				
			||||||
 | 
					      return {
 | 
				
			||||||
 | 
					        column,
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (operation.noValue) {
 | 
				
			||||||
 | 
					      return {
 | 
				
			||||||
 | 
					        column,
 | 
				
			||||||
 | 
					        operation,
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					      column,
 | 
				
			||||||
 | 
					      operation,
 | 
				
			||||||
 | 
					      value: nested[operationValue],
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const values = toValues(value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // console.log('toValues', values, value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const Remove = (props) => {
 | 
					  const Remove = (props) => {
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
@ -53,7 +100,7 @@ export const FilterItem = (props) => {
 | 
				
			|||||||
  const form = useMemo(
 | 
					  const form = useMemo(
 | 
				
			||||||
    () =>
 | 
					    () =>
 | 
				
			||||||
      createForm({
 | 
					      createForm({
 | 
				
			||||||
        initialValues,
 | 
					        initialValues: values,
 | 
				
			||||||
        effects: (form) => {
 | 
					        effects: (form) => {
 | 
				
			||||||
          onFieldChange('column', (field: Field, form: Form) => {
 | 
					          onFieldChange('column', (field: Field, form: Form) => {
 | 
				
			||||||
            const column = (field.value || {}) as ISchema;
 | 
					            const column = (field.value || {}) as ISchema;
 | 
				
			||||||
@ -76,12 +123,28 @@ export const FilterItem = (props) => {
 | 
				
			|||||||
              f.visible = !operation.noValue;
 | 
					              f.visible = !operation.noValue;
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
          });
 | 
					          });
 | 
				
			||||||
 | 
					          onFormValuesChange((form) => {
 | 
				
			||||||
 | 
					            const { column, operation, value } = form.values;
 | 
				
			||||||
 | 
					            if (!operation?.value) {
 | 
				
			||||||
 | 
					              return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            const fieldName = Object.keys(column.properties).shift();
 | 
				
			||||||
 | 
					            if (operation?.noValue) {
 | 
				
			||||||
 | 
					              onChange({[fieldName]: {
 | 
				
			||||||
 | 
					                [operation.value]: true,
 | 
				
			||||||
 | 
					              }});
 | 
				
			||||||
 | 
					            } else if (isValid(value)) {
 | 
				
			||||||
 | 
					              onChange({[fieldName]: {
 | 
				
			||||||
 | 
					                [operation.value]: value,
 | 
				
			||||||
 | 
					              }});
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            console.log('form.values', form.values);
 | 
				
			||||||
 | 
					          })
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
      }),
 | 
					      }),
 | 
				
			||||||
    [],
 | 
					    [],
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <FormProvider form={form}>
 | 
					    <FormProvider form={form}>
 | 
				
			||||||
      <FormLayout layout={'inline'}>
 | 
					      <FormLayout layout={'inline'}>
 | 
				
			||||||
@ -89,7 +152,7 @@ export const FilterItem = (props) => {
 | 
				
			|||||||
          <SchemaField.Void x-component="Space">
 | 
					          <SchemaField.Void x-component="Space">
 | 
				
			||||||
            <SchemaField.String
 | 
					            <SchemaField.String
 | 
				
			||||||
              name="column"
 | 
					              name="column"
 | 
				
			||||||
              x-decorator="FormItem"
 | 
					              x-decorator="FormilyFormItem"
 | 
				
			||||||
              x-decorator-props={{
 | 
					              x-decorator-props={{
 | 
				
			||||||
                asterisk: true,
 | 
					                asterisk: true,
 | 
				
			||||||
                feedbackLayout: 'none',
 | 
					                feedbackLayout: 'none',
 | 
				
			||||||
@ -105,11 +168,11 @@ export const FilterItem = (props) => {
 | 
				
			|||||||
                  value: 'name',
 | 
					                  value: 'name',
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
              }}
 | 
					              }}
 | 
				
			||||||
              enum={columns.map((column) => column.toJSON())}
 | 
					              enum={[...columns.values()].map((column) => column.toJSON())}
 | 
				
			||||||
            />
 | 
					            />
 | 
				
			||||||
            <SchemaField.String
 | 
					            <SchemaField.String
 | 
				
			||||||
              name="operation"
 | 
					              name="operation"
 | 
				
			||||||
              x-decorator="FormItem"
 | 
					              x-decorator="FormilyFormItem"
 | 
				
			||||||
              x-decorator-props={{
 | 
					              x-decorator-props={{
 | 
				
			||||||
                asterisk: true,
 | 
					                asterisk: true,
 | 
				
			||||||
                feedbackLayout: 'none',
 | 
					                feedbackLayout: 'none',
 | 
				
			||||||
@ -124,7 +187,7 @@ export const FilterItem = (props) => {
 | 
				
			|||||||
            />
 | 
					            />
 | 
				
			||||||
            <SchemaField.String
 | 
					            <SchemaField.String
 | 
				
			||||||
              name="value"
 | 
					              name="value"
 | 
				
			||||||
              x-decorator="FormItem"
 | 
					              x-decorator="FormilyFormItem"
 | 
				
			||||||
              x-decorator-props={{
 | 
					              x-decorator-props={{
 | 
				
			||||||
                asterisk: true,
 | 
					                asterisk: true,
 | 
				
			||||||
                feedbackLayout: 'none',
 | 
					                feedbackLayout: 'none',
 | 
				
			||||||
 | 
				
			|||||||
@ -38,6 +38,20 @@ const schema = {
 | 
				
			|||||||
  name: 'filter',
 | 
					  name: 'filter',
 | 
				
			||||||
  type: 'object',
 | 
					  type: 'object',
 | 
				
			||||||
  'x-component': 'Filter',
 | 
					  'x-component': 'Filter',
 | 
				
			||||||
 | 
					  default: {
 | 
				
			||||||
 | 
					    and: [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        field1: {
 | 
				
			||||||
 | 
					          eq: 'aa',
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        field1: {
 | 
				
			||||||
 | 
					          eq: 'bbb',
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
  properties: {
 | 
					  properties: {
 | 
				
			||||||
    column1: {
 | 
					    column1: {
 | 
				
			||||||
      type: 'void',
 | 
					      type: 'void',
 | 
				
			||||||
@ -68,7 +82,7 @@ const schema = {
 | 
				
			|||||||
        ],
 | 
					        ],
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      properties: {
 | 
					      properties: {
 | 
				
			||||||
        field1: {
 | 
					        field2: {
 | 
				
			||||||
          type: 'number',
 | 
					          type: 'number',
 | 
				
			||||||
          'x-component': 'InputNumber',
 | 
					          'x-component': 'InputNumber',
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
@ -79,7 +93,7 @@ const schema = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export default () => {
 | 
					export default () => {
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <SchemaRenderer schema={schema} />
 | 
					    <SchemaRenderer debug={true} schema={schema} />
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
				
			|||||||
@ -5,12 +5,39 @@ import { useDynamicList } from 'ahooks';
 | 
				
			|||||||
import { Select } from 'antd';
 | 
					import { Select } from 'antd';
 | 
				
			||||||
import { CloseCircleOutlined } from '@ant-design/icons';
 | 
					import { CloseCircleOutlined } from '@ant-design/icons';
 | 
				
			||||||
import { FilterItem } from './FilterItem';
 | 
					import { FilterItem } from './FilterItem';
 | 
				
			||||||
 | 
					import cls from 'classnames';
 | 
				
			||||||
import './style.less';
 | 
					import './style.less';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const toValue = (value) => {
 | 
				
			||||||
 | 
					  if (!value) {
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					      logical: 'and',
 | 
				
			||||||
 | 
					      list: [{}],
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (value.and) {
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					      logical: 'and',
 | 
				
			||||||
 | 
					      list: value.and,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (value.or) {
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					      logical: 'and',
 | 
				
			||||||
 | 
					      list: value.or,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return {
 | 
				
			||||||
 | 
					    logical: 'and',
 | 
				
			||||||
 | 
					    list: [{}],
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function FilterGroup(props) {
 | 
					export function FilterGroup(props) {
 | 
				
			||||||
  const { onRemove } = props;
 | 
					  const { bordered = true, onRemove, onChange } = props;
 | 
				
			||||||
 | 
					  const value = toValue(props.value);
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <div className={'nb-filter-group'}>
 | 
					    <div className={cls('nb-filter-group', { bordered })}>
 | 
				
			||||||
      {onRemove && (
 | 
					      {onRemove && (
 | 
				
			||||||
        <a className={'nb-filter-group-close'} onClick={() => onRemove()}>
 | 
					        <a className={'nb-filter-group-close'} onClick={() => onRemove()}>
 | 
				
			||||||
          <CloseCircleOutlined />
 | 
					          <CloseCircleOutlined />
 | 
				
			||||||
@ -20,8 +47,13 @@ export function FilterGroup(props) {
 | 
				
			|||||||
        满足组内{' '}
 | 
					        满足组内{' '}
 | 
				
			||||||
        <Select
 | 
					        <Select
 | 
				
			||||||
          style={{ width: 80 }}
 | 
					          style={{ width: 80 }}
 | 
				
			||||||
          onChange={(value) => {}}
 | 
					          onChange={(logical) => {
 | 
				
			||||||
          defaultValue={'and'}
 | 
					            onChange &&
 | 
				
			||||||
 | 
					              onChange({
 | 
				
			||||||
 | 
					                [logical]: value.list,
 | 
				
			||||||
 | 
					              });
 | 
				
			||||||
 | 
					          }}
 | 
				
			||||||
 | 
					          defaultValue={value.logical}
 | 
				
			||||||
        >
 | 
					        >
 | 
				
			||||||
          <Select.Option value={'and'}>全部</Select.Option>
 | 
					          <Select.Option value={'and'}>全部</Select.Option>
 | 
				
			||||||
          <Select.Option value={'or'}>任意</Select.Option>
 | 
					          <Select.Option value={'or'}>任意</Select.Option>
 | 
				
			||||||
@ -29,9 +61,12 @@ export function FilterGroup(props) {
 | 
				
			|||||||
        条件
 | 
					        条件
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
      <FilterList
 | 
					      <FilterList
 | 
				
			||||||
        initialValue={[{}]}
 | 
					        initialValue={value.list}
 | 
				
			||||||
        onChange={(list) => {
 | 
					        onChange={(list: any[]) => {
 | 
				
			||||||
          console.log({ list });
 | 
					          onChange &&
 | 
				
			||||||
 | 
					            onChange({
 | 
				
			||||||
 | 
					              [value.logical]: list.filter((item) => Object.keys(item).length),
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
        }}
 | 
					        }}
 | 
				
			||||||
      />
 | 
					      />
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
@ -40,7 +75,9 @@ export function FilterGroup(props) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export function FilterList(props) {
 | 
					export function FilterList(props) {
 | 
				
			||||||
  const { initialValue } = props;
 | 
					  const { initialValue } = props;
 | 
				
			||||||
  const { list, push, remove } = useDynamicList<any>(initialValue || []);
 | 
					  const { list, push, remove, replace } = useDynamicList<any>(
 | 
				
			||||||
 | 
					    initialValue || [],
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
  useEffect(() => {
 | 
					  useEffect(() => {
 | 
				
			||||||
    props.onChange && props.onChange(list);
 | 
					    props.onChange && props.onChange(list);
 | 
				
			||||||
  }, [list]);
 | 
					  }, [list]);
 | 
				
			||||||
@ -48,18 +85,29 @@ export function FilterList(props) {
 | 
				
			|||||||
    <div className={'nb-filter-list'}>
 | 
					    <div className={'nb-filter-list'}>
 | 
				
			||||||
      <div>
 | 
					      <div>
 | 
				
			||||||
        {list.map((item, index) => {
 | 
					        {list.map((item, index) => {
 | 
				
			||||||
          if (item.type === 'group') {
 | 
					          if (item.and || item.or) {
 | 
				
			||||||
            return <FilterGroup key={index} onRemove={() => remove(index)} />;
 | 
					            return (
 | 
				
			||||||
 | 
					              <FilterGroup
 | 
				
			||||||
 | 
					                key={index}
 | 
				
			||||||
 | 
					                value={item}
 | 
				
			||||||
 | 
					                onChange={(value: any) => replace(index, value)}
 | 
				
			||||||
 | 
					                onRemove={() => remove(index)}
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
          return <FilterItem key={index} onRemove={() => remove(index)} />;
 | 
					          return (
 | 
				
			||||||
 | 
					            <FilterItem
 | 
				
			||||||
 | 
					              key={index}
 | 
				
			||||||
 | 
					              value={item}
 | 
				
			||||||
 | 
					              onChange={(value: any) => replace(index, value)}
 | 
				
			||||||
 | 
					              onRemove={() => remove(index)}
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					          );
 | 
				
			||||||
        })}
 | 
					        })}
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
      <a
 | 
					      <a
 | 
				
			||||||
        onClick={() => {
 | 
					        onClick={() => {
 | 
				
			||||||
          push({
 | 
					          push({});
 | 
				
			||||||
            type: 'item',
 | 
					 | 
				
			||||||
            key: new Date().toTimeString(),
 | 
					 | 
				
			||||||
          });
 | 
					 | 
				
			||||||
        }}
 | 
					        }}
 | 
				
			||||||
      >
 | 
					      >
 | 
				
			||||||
        添加条件
 | 
					        添加条件
 | 
				
			||||||
@ -67,8 +115,7 @@ export function FilterList(props) {
 | 
				
			|||||||
      <a
 | 
					      <a
 | 
				
			||||||
        onClick={() => {
 | 
					        onClick={() => {
 | 
				
			||||||
          push({
 | 
					          push({
 | 
				
			||||||
            type: 'group',
 | 
					            and: [{}],
 | 
				
			||||||
            key: new Date().toTimeString(),
 | 
					 | 
				
			||||||
          });
 | 
					          });
 | 
				
			||||||
        }}
 | 
					        }}
 | 
				
			||||||
      >
 | 
					      >
 | 
				
			||||||
@ -80,9 +127,10 @@ export function FilterList(props) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export const Filter = connect(
 | 
					export const Filter = connect(
 | 
				
			||||||
  (props) => {
 | 
					  (props) => {
 | 
				
			||||||
 | 
					    // console.log('Filter.props', { props });
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
      <div>
 | 
					      <div>
 | 
				
			||||||
        <FilterGroup />
 | 
					        <FilterGroup bordered={false} {...props} />
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
				
			|||||||
@ -1,10 +1,18 @@
 | 
				
			|||||||
.nb-filter-group {
 | 
					.nb-filter-group {
 | 
				
			||||||
  position: relative;
 | 
					  position: relative;
 | 
				
			||||||
  margin-bottom: 14px;
 | 
					  margin-bottom: 14px;
 | 
				
			||||||
  padding: 14px;
 | 
					  min-width: 400px;
 | 
				
			||||||
  border: 1px dashed rgb(222, 222, 222);
 | 
					 | 
				
			||||||
  &-close {
 | 
					  &-close {
 | 
				
			||||||
    position: absolute;
 | 
					    position: absolute;
 | 
				
			||||||
    right: 10px;
 | 
					    right: 10px;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  &.bordered {
 | 
				
			||||||
 | 
					    border: 1px dashed rgb(222, 222, 222);
 | 
				
			||||||
 | 
					    padding: 14px;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.nb-filter-list {
 | 
				
			||||||
 | 
					  .ant-form-inline {
 | 
				
			||||||
 | 
					    margin-bottom: 8px;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -123,7 +123,6 @@ export function SortableBodyRow(props: any) {
 | 
				
			|||||||
        <SortableContext
 | 
					        <SortableContext
 | 
				
			||||||
          strategy={horizontalListSortingStrategy}
 | 
					          strategy={horizontalListSortingStrategy}
 | 
				
			||||||
          items={React.Children.map(props.children, (child) => {
 | 
					          items={React.Children.map(props.children, (child) => {
 | 
				
			||||||
            console.log(child.key, 'child.key');
 | 
					 | 
				
			||||||
            return `td${child.key}`;
 | 
					            return `td${child.key}`;
 | 
				
			||||||
          })}
 | 
					          })}
 | 
				
			||||||
        >
 | 
					        >
 | 
				
			||||||
 | 
				
			|||||||
@ -17,7 +17,7 @@ import { uid } from '@formily/shared';
 | 
				
			|||||||
import useRequest from '@ahooksjs/use-request';
 | 
					import useRequest from '@ahooksjs/use-request';
 | 
				
			||||||
import { BaseResult } from '@ahooksjs/use-request/lib/types';
 | 
					import { BaseResult } from '@ahooksjs/use-request/lib/types';
 | 
				
			||||||
import cls from 'classnames';
 | 
					import cls from 'classnames';
 | 
				
			||||||
import { MenuOutlined, DragOutlined } from '@ant-design/icons';
 | 
					import { MenuOutlined, DragOutlined, FilterOutlined } from '@ant-design/icons';
 | 
				
			||||||
import { DndContext, DragOverlay } from '@dnd-kit/core';
 | 
					import { DndContext, DragOverlay } from '@dnd-kit/core';
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  SortableContext,
 | 
					  SortableContext,
 | 
				
			||||||
@ -42,6 +42,7 @@ import { Resource } from '../../resource';
 | 
				
			|||||||
import {
 | 
					import {
 | 
				
			||||||
  CollectionProvider,
 | 
					  CollectionProvider,
 | 
				
			||||||
  DisplayedMapProvider,
 | 
					  DisplayedMapProvider,
 | 
				
			||||||
 | 
					  useCollection,
 | 
				
			||||||
  useCollectionContext,
 | 
					  useCollectionContext,
 | 
				
			||||||
  useDisplayedMapContext,
 | 
					  useDisplayedMapContext,
 | 
				
			||||||
} from '../../constate';
 | 
					} from '../../constate';
 | 
				
			||||||
@ -59,7 +60,10 @@ import {
 | 
				
			|||||||
  SortableRowHandle,
 | 
					  SortableRowHandle,
 | 
				
			||||||
} from './Sortable';
 | 
					} from './Sortable';
 | 
				
			||||||
import { DragHandle, Droppable, SortableItem } from '../../components/Sortable';
 | 
					import { DragHandle, Droppable, SortableItem } from '../../components/Sortable';
 | 
				
			||||||
import { VisibleContext } from '../../context';
 | 
					import { isValid } from '@formily/shared';
 | 
				
			||||||
 | 
					import { FormButtonGroup, FormDialog, FormLayout, Submit } from '@formily/antd';
 | 
				
			||||||
 | 
					import flatten from 'flat';
 | 
				
			||||||
 | 
					import IconPicker from '../../components/icon-picker';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface ITableContext {
 | 
					export interface ITableContext {
 | 
				
			||||||
  props: any;
 | 
					  props: any;
 | 
				
			||||||
@ -79,12 +83,12 @@ export interface ITableRowContext {
 | 
				
			|||||||
  record: any;
 | 
					  record: any;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const TableConetxt = createContext<ITableContext>(null);
 | 
					const TableContext = createContext<ITableContext>({} as any);
 | 
				
			||||||
const TableRowContext = createContext<ITableRowContext>(null);
 | 
					const TableRowContext = createContext<ITableRowContext>(null);
 | 
				
			||||||
const CollectionFieldContext = createContext(null);
 | 
					const CollectionFieldContext = createContext(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const useTable = () => {
 | 
					const useTable = () => {
 | 
				
			||||||
  return useContext(TableConetxt);
 | 
					  return useContext(TableContext);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const useTableRow = () => {
 | 
					const useTableRow = () => {
 | 
				
			||||||
@ -98,10 +102,15 @@ function useTableFilterAction() {
 | 
				
			|||||||
    refresh,
 | 
					    refresh,
 | 
				
			||||||
    props: { refreshRequestOnChange },
 | 
					    props: { refreshRequestOnChange },
 | 
				
			||||||
  } = useTable();
 | 
					  } = useTable();
 | 
				
			||||||
 | 
					  const form = useForm();
 | 
				
			||||||
  return {
 | 
					  return {
 | 
				
			||||||
    async run() {
 | 
					    async run() {
 | 
				
			||||||
 | 
					      console.log('useTableFilterAction', form.values);
 | 
				
			||||||
      if (refreshRequestOnChange) {
 | 
					      if (refreshRequestOnChange) {
 | 
				
			||||||
        return service.refresh();
 | 
					        return service.run({
 | 
				
			||||||
 | 
					          ...service.params[0],
 | 
				
			||||||
 | 
					          // filter,
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
@ -204,7 +213,7 @@ const useTableIndex = () => {
 | 
				
			|||||||
  const { pagination, props } = useTable();
 | 
					  const { pagination, props } = useTable();
 | 
				
			||||||
  const ctx = useContext(TableRowContext);
 | 
					  const ctx = useContext(TableRowContext);
 | 
				
			||||||
  if (pagination && !props.clientSidePagination) {
 | 
					  if (pagination && !props.clientSidePagination) {
 | 
				
			||||||
    const { pageSize, page } = pagination;
 | 
					    const { pageSize, page = 1 } = pagination;
 | 
				
			||||||
    return ctx.index + (page - 1) * pageSize;
 | 
					    return ctx.index + (page - 1) * pageSize;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return ctx.index;
 | 
					  return ctx.index;
 | 
				
			||||||
@ -433,11 +442,13 @@ const useDataSource = () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const TableMain = () => {
 | 
					const TableMain = () => {
 | 
				
			||||||
  const {
 | 
					  const {
 | 
				
			||||||
 | 
					    resource,
 | 
				
			||||||
    selectedRowKeys,
 | 
					    selectedRowKeys,
 | 
				
			||||||
    setSelectedRowKeys,
 | 
					    setSelectedRowKeys,
 | 
				
			||||||
    service,
 | 
					    service,
 | 
				
			||||||
    field,
 | 
					    field,
 | 
				
			||||||
    props: { rowKey, dragSort, showIndex },
 | 
					    props: { rowKey, dragSort, showIndex },
 | 
				
			||||||
 | 
					    refresh,
 | 
				
			||||||
  } = useTable();
 | 
					  } = useTable();
 | 
				
			||||||
  const columns = useTableColumns();
 | 
					  const columns = useTableColumns();
 | 
				
			||||||
  const dataSource = useDataSource();
 | 
					  const dataSource = useDataSource();
 | 
				
			||||||
@ -446,8 +457,29 @@ const TableMain = () => {
 | 
				
			|||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <div className={'nb-table'}>
 | 
					    <div className={'nb-table'}>
 | 
				
			||||||
      <DndContext
 | 
					      <DndContext
 | 
				
			||||||
        onDragEnd={(event) => {
 | 
					        onDragEnd={async (event) => {
 | 
				
			||||||
          console.log({ event });
 | 
					          const fromId = event.active?.id as any;
 | 
				
			||||||
 | 
					          const toId = event.over?.id as any;
 | 
				
			||||||
 | 
					          if (isValid(fromId) && isValid(toId)) {
 | 
				
			||||||
 | 
					            const fromIndex = findIndex(
 | 
				
			||||||
 | 
					              field.value,
 | 
				
			||||||
 | 
					              (item) => item[rowKey] === fromId,
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					            const toIndex = findIndex(
 | 
				
			||||||
 | 
					              field.value,
 | 
				
			||||||
 | 
					              (item) => item[rowKey] === toId,
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					            console.log({ fromId, toId, fromIndex, toIndex });
 | 
				
			||||||
 | 
					            field.move(fromIndex, toIndex);
 | 
				
			||||||
 | 
					            refresh();
 | 
				
			||||||
 | 
					            await resource.sort({
 | 
				
			||||||
 | 
					              resourceKey: fromId,
 | 
				
			||||||
 | 
					              target: {
 | 
				
			||||||
 | 
					                [rowKey]: toId,
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            await service.refresh();
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        }}
 | 
					        }}
 | 
				
			||||||
      >
 | 
					      >
 | 
				
			||||||
        {actionBars.map((actionBar) => (
 | 
					        {actionBars.map((actionBar) => (
 | 
				
			||||||
@ -541,13 +573,35 @@ const TableMain = () => {
 | 
				
			|||||||
  );
 | 
					  );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const usePagination = (paginationProps?: any) => {
 | 
					const usePagination = () => {
 | 
				
			||||||
  return useState(() => {
 | 
					  const field = useField<Formily.Core.Models.ArrayField>();
 | 
				
			||||||
    if (!paginationProps) {
 | 
					  const paginationProps = field.componentProps.pagination;
 | 
				
			||||||
      return false;
 | 
					
 | 
				
			||||||
    }
 | 
					  let pagination = paginationProps;
 | 
				
			||||||
    return { page: 1, pageSize: 10, ...paginationProps };
 | 
					
 | 
				
			||||||
  });
 | 
					  // const [pagination, setPagination] = useState(() => {
 | 
				
			||||||
 | 
					  //   if (!paginationProps) {
 | 
				
			||||||
 | 
					  //     return false;
 | 
				
			||||||
 | 
					  //   }
 | 
				
			||||||
 | 
					  //   const { defaultPageSize = 10, ...others } = paginationProps;
 | 
				
			||||||
 | 
					  //   return { page: 1, pageSize: defaultPageSize, ...others };
 | 
				
			||||||
 | 
					  // });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // useEffect(() => {
 | 
				
			||||||
 | 
					  //   if (!paginationProps) {
 | 
				
			||||||
 | 
					  //     return setPagination(false);
 | 
				
			||||||
 | 
					  //   }
 | 
				
			||||||
 | 
					  //   const { defaultPageSize = 10, ...others } = paginationProps;
 | 
				
			||||||
 | 
					  //   setPagination({ page: 1, pageSize: defaultPageSize, ...others });
 | 
				
			||||||
 | 
					  // }, [paginationProps]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return [
 | 
				
			||||||
 | 
					    pagination,
 | 
				
			||||||
 | 
					    (params) => {
 | 
				
			||||||
 | 
					      const defaults = field.componentProps.pagination;
 | 
				
			||||||
 | 
					      field.componentProps.pagination = { ...defaults, ...params };
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const TableProvider = (props: any) => {
 | 
					const TableProvider = (props: any) => {
 | 
				
			||||||
@ -559,10 +613,25 @@ const TableProvider = (props: any) => {
 | 
				
			|||||||
  } = props;
 | 
					  } = props;
 | 
				
			||||||
  const { schema } = useDesignable();
 | 
					  const { schema } = useDesignable();
 | 
				
			||||||
  const field = useField<Formily.Core.Models.ArrayField>();
 | 
					  const field = useField<Formily.Core.Models.ArrayField>();
 | 
				
			||||||
  const [pagination, setPagination] = usePagination(props.pagination);
 | 
					  const [pagination, setPagination] = usePagination();
 | 
				
			||||||
  const [selectedRowKeys, setSelectedRowKeys] = useState<any>([]);
 | 
					  const [selectedRowKeys, setSelectedRowKeys] = useState<any>([]);
 | 
				
			||||||
  const [, refresh] = useState(uid());
 | 
					  const [, refresh] = useState(uid());
 | 
				
			||||||
  const { resource } = useResource();
 | 
					  const { resource } = useResource();
 | 
				
			||||||
 | 
					  const { sortableField } = useCollectionContext();
 | 
				
			||||||
 | 
					  const dragSort = props.dragSort;
 | 
				
			||||||
 | 
					  const getDefaultParams = () => {
 | 
				
			||||||
 | 
					    const defaultParams = { ...pagination };
 | 
				
			||||||
 | 
					    if (dragSort) {
 | 
				
			||||||
 | 
					      defaultParams['sort'] = [sortableField || 'sort'];
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      defaultParams['sort'] = (props.defaultSort || []).join(',');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (props.defaultFilter) {
 | 
				
			||||||
 | 
					      defaultParams['defaultFilter'] = props.defaultFilter;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    console.log({ defaultParams });
 | 
				
			||||||
 | 
					    return defaultParams;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
  const service = useRequest(
 | 
					  const service = useRequest(
 | 
				
			||||||
    (params?: any) => {
 | 
					    (params?: any) => {
 | 
				
			||||||
      if (!resource) {
 | 
					      if (!resource) {
 | 
				
			||||||
@ -582,12 +651,20 @@ const TableProvider = (props: any) => {
 | 
				
			|||||||
      onSuccess(data: any) {
 | 
					      onSuccess(data: any) {
 | 
				
			||||||
        field.setValue(data?.list || []);
 | 
					        field.setValue(data?.list || []);
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      defaultParams: [{ ...pagination }],
 | 
					      manual: true,
 | 
				
			||||||
 | 
					      // defaultParams: [getDefaultParams()],
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
  console.log('refresh', { pagination });
 | 
					  useEffect(() => {
 | 
				
			||||||
 | 
					    service.run(getDefaultParams());
 | 
				
			||||||
 | 
					  }, [
 | 
				
			||||||
 | 
					    pagination.pageSize,
 | 
				
			||||||
 | 
					    props.dragSort,
 | 
				
			||||||
 | 
					    props.defaultSort,
 | 
				
			||||||
 | 
					    props.defaultFilter,
 | 
				
			||||||
 | 
					  ]);
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <TableConetxt.Provider
 | 
					    <TableContext.Provider
 | 
				
			||||||
      value={{
 | 
					      value={{
 | 
				
			||||||
        resource,
 | 
					        resource,
 | 
				
			||||||
        refresh: () => {
 | 
					        refresh: () => {
 | 
				
			||||||
@ -597,7 +674,7 @@ const TableProvider = (props: any) => {
 | 
				
			|||||||
            : service?.data?.total;
 | 
					            : service?.data?.total;
 | 
				
			||||||
          const maxPage = Math.ceil(total / pageSize);
 | 
					          const maxPage = Math.ceil(total / pageSize);
 | 
				
			||||||
          if (page > maxPage) {
 | 
					          if (page > maxPage) {
 | 
				
			||||||
            setPagination((prev) => ({ ...prev, page: maxPage }));
 | 
					            setPagination({ page: maxPage });
 | 
				
			||||||
          } else {
 | 
					          } else {
 | 
				
			||||||
            refresh(uid());
 | 
					            refresh(uid());
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
@ -613,7 +690,7 @@ const TableProvider = (props: any) => {
 | 
				
			|||||||
      }}
 | 
					      }}
 | 
				
			||||||
    >
 | 
					    >
 | 
				
			||||||
      <TableMain />
 | 
					      <TableMain />
 | 
				
			||||||
    </TableConetxt.Provider>
 | 
					    </TableContext.Provider>
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -654,19 +731,18 @@ Table.Pagination = observer(() => {
 | 
				
			|||||||
        total={total}
 | 
					        total={total}
 | 
				
			||||||
        onChange={(current, pageSize) => {
 | 
					        onChange={(current, pageSize) => {
 | 
				
			||||||
          const page = pagination.pageSize !== pageSize ? 1 : current;
 | 
					          const page = pagination.pageSize !== pageSize ? 1 : current;
 | 
				
			||||||
          setPagination((prev) => ({
 | 
					          setPagination({
 | 
				
			||||||
            ...prev,
 | 
					 | 
				
			||||||
            page,
 | 
					 | 
				
			||||||
            pageSize,
 | 
					 | 
				
			||||||
          }));
 | 
					 | 
				
			||||||
          if (clientSidePagination) {
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
          service.run({
 | 
					 | 
				
			||||||
            ...service.params,
 | 
					 | 
				
			||||||
            page,
 | 
					            page,
 | 
				
			||||||
            pageSize,
 | 
					            pageSize,
 | 
				
			||||||
          });
 | 
					          });
 | 
				
			||||||
 | 
					          // if (clientSidePagination) {
 | 
				
			||||||
 | 
					          //   return;
 | 
				
			||||||
 | 
					          // }
 | 
				
			||||||
 | 
					          // service.run({
 | 
				
			||||||
 | 
					          //   ...service.params[0],
 | 
				
			||||||
 | 
					          //   page,
 | 
				
			||||||
 | 
					          //   pageSize,
 | 
				
			||||||
 | 
					          // });
 | 
				
			||||||
        }}
 | 
					        }}
 | 
				
			||||||
      />
 | 
					      />
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
@ -1031,42 +1107,74 @@ Table.ActionBar = observer((props: any) => {
 | 
				
			|||||||
  );
 | 
					  );
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const fieldsToFilterColumns = (fields: any[], options: any = {}) => {
 | 
				
			||||||
 | 
					  const { fieldNames = [] } = options;
 | 
				
			||||||
 | 
					  const properties = {};
 | 
				
			||||||
 | 
					  fields.forEach((field, index) => {
 | 
				
			||||||
 | 
					    if (fieldNames?.length && !fieldNames.includes(field.name)) {
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const fieldOption = interfaces.get(field.interface);
 | 
				
			||||||
 | 
					    if (!fieldOption.operations) {
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    properties[`column${index}`] = {
 | 
				
			||||||
 | 
					      type: 'void',
 | 
				
			||||||
 | 
					      title: field?.uiSchema?.title,
 | 
				
			||||||
 | 
					      'x-component': 'Filter.Column',
 | 
				
			||||||
 | 
					      'x-component-props': {
 | 
				
			||||||
 | 
					        operations: fieldOption.operations,
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      properties: {
 | 
				
			||||||
 | 
					        [field.name]: {
 | 
				
			||||||
 | 
					          ...field.uiSchema,
 | 
				
			||||||
 | 
					          'x-decorator': 'FormilyFormItem',
 | 
				
			||||||
 | 
					          title: null,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					  return properties;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const fieldsToSortColumns = (fields: any[]) => {
 | 
				
			||||||
 | 
					  const dataSource = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  fields.forEach((field) => {
 | 
				
			||||||
 | 
					    const fieldOption = interfaces.get(field.interface);
 | 
				
			||||||
 | 
					    if (!fieldOption.sortable) {
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    dataSource.push({
 | 
				
			||||||
 | 
					      value: field.name,
 | 
				
			||||||
 | 
					      label: field?.uiSchema?.title,
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return dataSource;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Table.Filter = observer((props: any) => {
 | 
					Table.Filter = observer((props: any) => {
 | 
				
			||||||
 | 
					  const { service } = useTable();
 | 
				
			||||||
  const { fieldNames = [] } = props;
 | 
					  const { fieldNames = [] } = props;
 | 
				
			||||||
  const { schema, DesignableBar } = useDesignable();
 | 
					  const { schema, DesignableBar } = useDesignable();
 | 
				
			||||||
  const form = useMemo(() => createForm(), []);
 | 
					  const form = useMemo(() => createForm(), []);
 | 
				
			||||||
  const { fields = [] } = useCollectionContext();
 | 
					  const { fields = [] } = useCollectionContext();
 | 
				
			||||||
  const fields2properties = (fields: any[]) => {
 | 
					  const [visible, setVisible] = useState(false);
 | 
				
			||||||
    const properties = {};
 | 
					  const obj = flatten(form.values.filter || {});
 | 
				
			||||||
    fields.forEach((field, index) => {
 | 
					  console.log('flatten', obj, Object.values(obj));
 | 
				
			||||||
      if (fieldNames?.length && !fieldNames.includes(field.name)) {
 | 
					  const count = Object.values(obj).filter((i) =>
 | 
				
			||||||
        return;
 | 
					    Array.isArray(i) ? i.length : i,
 | 
				
			||||||
      }
 | 
					  ).length;
 | 
				
			||||||
      const fieldOption = interfaces.get(field.interface);
 | 
					
 | 
				
			||||||
      if (!fieldOption.operations) {
 | 
					  const icon = props.icon || 'FilterOutlined';
 | 
				
			||||||
        return;
 | 
					
 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      properties[`column${index}`] = {
 | 
					 | 
				
			||||||
        type: 'void',
 | 
					 | 
				
			||||||
        title: field?.uiSchema?.title,
 | 
					 | 
				
			||||||
        'x-component': 'Filter.Column',
 | 
					 | 
				
			||||||
        'x-component-props': {
 | 
					 | 
				
			||||||
          operations: fieldOption.operations,
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        properties: {
 | 
					 | 
				
			||||||
          [field.name]: {
 | 
					 | 
				
			||||||
            ...field.uiSchema,
 | 
					 | 
				
			||||||
            title: null,
 | 
					 | 
				
			||||||
          },
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
      };
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
    return properties;
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <Popover
 | 
					    <Popover
 | 
				
			||||||
      trigger={['click']}
 | 
					      trigger={['click']}
 | 
				
			||||||
      placement={'bottomLeft'}
 | 
					      placement={'bottomLeft'}
 | 
				
			||||||
 | 
					      visible={visible}
 | 
				
			||||||
 | 
					      onVisibleChange={setVisible}
 | 
				
			||||||
      content={
 | 
					      content={
 | 
				
			||||||
        <div>
 | 
					        <div>
 | 
				
			||||||
          <FormProvider form={form}>
 | 
					          <FormProvider form={form}>
 | 
				
			||||||
@ -1077,17 +1185,32 @@ Table.Filter = observer((props: any) => {
 | 
				
			|||||||
                  filter: {
 | 
					                  filter: {
 | 
				
			||||||
                    type: 'object',
 | 
					                    type: 'object',
 | 
				
			||||||
                    'x-component': 'Filter',
 | 
					                    'x-component': 'Filter',
 | 
				
			||||||
                    properties: fields2properties(fields),
 | 
					                    properties: fieldsToFilterColumns(fields, { fieldNames }),
 | 
				
			||||||
                  },
 | 
					                  },
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
              }}
 | 
					              }}
 | 
				
			||||||
            />
 | 
					            />
 | 
				
			||||||
 | 
					            <FormButtonGroup align={'right'}>
 | 
				
			||||||
 | 
					              <Submit
 | 
				
			||||||
 | 
					                onSubmit={() => {
 | 
				
			||||||
 | 
					                  const { filter } = form.values;
 | 
				
			||||||
 | 
					                  console.log('Table.Filter', form.values);
 | 
				
			||||||
 | 
					                  setVisible(false);
 | 
				
			||||||
 | 
					                  return service.run({
 | 
				
			||||||
 | 
					                    ...service.params[0],
 | 
				
			||||||
 | 
					                    filter,
 | 
				
			||||||
 | 
					                  });
 | 
				
			||||||
 | 
					                }}
 | 
				
			||||||
 | 
					              >
 | 
				
			||||||
 | 
					                提交
 | 
				
			||||||
 | 
					              </Submit>
 | 
				
			||||||
 | 
					            </FormButtonGroup>
 | 
				
			||||||
          </FormProvider>
 | 
					          </FormProvider>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    >
 | 
					    >
 | 
				
			||||||
      <Button>
 | 
					      <Button icon={<IconPicker type={icon} />}>
 | 
				
			||||||
        {schema.title}
 | 
					        {count > 0 ? `${count} 个筛选项` : schema.title}
 | 
				
			||||||
        <DesignableBar />
 | 
					        <DesignableBar />
 | 
				
			||||||
      </Button>
 | 
					      </Button>
 | 
				
			||||||
    </Popover>
 | 
					    </Popover>
 | 
				
			||||||
@ -1099,7 +1222,11 @@ Table.Filter.DesignableBar = () => {
 | 
				
			|||||||
  const [visible, setVisible] = useState(false);
 | 
					  const [visible, setVisible] = useState(false);
 | 
				
			||||||
  const displayed = useDisplayedMapContext();
 | 
					  const displayed = useDisplayedMapContext();
 | 
				
			||||||
  const { fields } = useCollectionContext();
 | 
					  const { fields } = useCollectionContext();
 | 
				
			||||||
 | 
					  const field = useField();
 | 
				
			||||||
 | 
					  let fieldNames = field.componentProps.fieldNames || [];
 | 
				
			||||||
 | 
					  if (fieldNames.length === 0) {
 | 
				
			||||||
 | 
					    fieldNames = fields.map((field) => field.name);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <div className={cls('designable-bar', { active: visible })}>
 | 
					    <div className={cls('designable-bar', { active: visible })}>
 | 
				
			||||||
      <span
 | 
					      <span
 | 
				
			||||||
@ -1119,22 +1246,72 @@ Table.Filter.DesignableBar = () => {
 | 
				
			|||||||
            <Menu>
 | 
					            <Menu>
 | 
				
			||||||
              <Menu.ItemGroup title={'筛选字段'}>
 | 
					              <Menu.ItemGroup title={'筛选字段'}>
 | 
				
			||||||
                {fields
 | 
					                {fields
 | 
				
			||||||
                  .filter((field) => {
 | 
					                  .filter((collectionField) => {
 | 
				
			||||||
                    const option = interfaces.get(field.interface);
 | 
					                    const option = interfaces.get(collectionField.interface);
 | 
				
			||||||
                    return option.operations?.length;
 | 
					                    return option.operations?.length;
 | 
				
			||||||
                  })
 | 
					                  })
 | 
				
			||||||
                  .map((field) => (
 | 
					                  .map((collectionField) => (
 | 
				
			||||||
                    <SwitchMenuItem
 | 
					                    <SwitchMenuItem
 | 
				
			||||||
                      title={field?.uiSchema?.title}
 | 
					                      title={collectionField?.uiSchema?.title}
 | 
				
			||||||
                      checked={true}
 | 
					                      checked={fieldNames.includes(collectionField.name)}
 | 
				
			||||||
                      onChange={async (checked) => {}}
 | 
					                      onChange={async (checked) => {
 | 
				
			||||||
 | 
					                        if (checked) {
 | 
				
			||||||
 | 
					                          fieldNames.push(collectionField.name);
 | 
				
			||||||
 | 
					                        } else {
 | 
				
			||||||
 | 
					                          const index = fieldNames.indexOf(
 | 
				
			||||||
 | 
					                            collectionField.name,
 | 
				
			||||||
 | 
					                          );
 | 
				
			||||||
 | 
					                          if (index > -1) {
 | 
				
			||||||
 | 
					                            fieldNames.splice(index, 1);
 | 
				
			||||||
 | 
					                          }
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        console.log({ fieldNames, field });
 | 
				
			||||||
 | 
					                        schema['x-component-props']['fieldNames'] = fieldNames;
 | 
				
			||||||
 | 
					                        field.componentProps.fieldNames = fieldNames;
 | 
				
			||||||
 | 
					                        updateSchema(schema);
 | 
				
			||||||
 | 
					                      }}
 | 
				
			||||||
                    />
 | 
					                    />
 | 
				
			||||||
                  ))}
 | 
					                  ))}
 | 
				
			||||||
              </Menu.ItemGroup>
 | 
					              </Menu.ItemGroup>
 | 
				
			||||||
              <Menu.Divider />
 | 
					              <Menu.Divider />
 | 
				
			||||||
              <Menu.Item
 | 
					              <Menu.Item
 | 
				
			||||||
                onClick={(e) => {
 | 
					                onClick={async (e) => {
 | 
				
			||||||
                  schema.title = uid();
 | 
					                  const values = await FormDialog('修改名称和图标', () => {
 | 
				
			||||||
 | 
					                    return (
 | 
				
			||||||
 | 
					                      <FormLayout layout={'vertical'}>
 | 
				
			||||||
 | 
					                        <SchemaField
 | 
				
			||||||
 | 
					                          schema={{
 | 
				
			||||||
 | 
					                            type: 'object',
 | 
				
			||||||
 | 
					                            properties: {
 | 
				
			||||||
 | 
					                              title: {
 | 
				
			||||||
 | 
					                                type: 'string',
 | 
				
			||||||
 | 
					                                title: '按钮名称',
 | 
				
			||||||
 | 
					                                required: true,
 | 
				
			||||||
 | 
					                                'x-decorator': 'FormItem',
 | 
				
			||||||
 | 
					                                'x-component': 'Input',
 | 
				
			||||||
 | 
					                              },
 | 
				
			||||||
 | 
					                              icon: {
 | 
				
			||||||
 | 
					                                type: 'string',
 | 
				
			||||||
 | 
					                                title: '按钮图标',
 | 
				
			||||||
 | 
					                                'x-decorator': 'FormItem',
 | 
				
			||||||
 | 
					                                'x-component': 'IconPicker',
 | 
				
			||||||
 | 
					                              },
 | 
				
			||||||
 | 
					                            },
 | 
				
			||||||
 | 
					                          }}
 | 
				
			||||||
 | 
					                        />
 | 
				
			||||||
 | 
					                      </FormLayout>
 | 
				
			||||||
 | 
					                    );
 | 
				
			||||||
 | 
					                  }).open({
 | 
				
			||||||
 | 
					                    initialValues: {
 | 
				
			||||||
 | 
					                      title: schema['title'],
 | 
				
			||||||
 | 
					                      icon: schema['x-component-props']?.['icon'],
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                  });
 | 
				
			||||||
 | 
					                  schema['title'] = values.title;
 | 
				
			||||||
 | 
					                  schema['x-component-props']['icon'] = values.icon;
 | 
				
			||||||
 | 
					                  field.componentProps.icon = values.icon;
 | 
				
			||||||
 | 
					                  field.title = values.title;
 | 
				
			||||||
 | 
					                  updateSchema(schema);
 | 
				
			||||||
                  refresh();
 | 
					                  refresh();
 | 
				
			||||||
                }}
 | 
					                }}
 | 
				
			||||||
              >
 | 
					              >
 | 
				
			||||||
@ -1153,7 +1330,7 @@ Table.Filter.DesignableBar = () => {
 | 
				
			|||||||
                  setVisible(false);
 | 
					                  setVisible(false);
 | 
				
			||||||
                }}
 | 
					                }}
 | 
				
			||||||
              >
 | 
					              >
 | 
				
			||||||
                删除
 | 
					                移除
 | 
				
			||||||
              </Menu.Item>
 | 
					              </Menu.Item>
 | 
				
			||||||
            </Menu>
 | 
					            </Menu>
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
@ -1262,6 +1439,7 @@ Table.Action.DesignableBar = () => {
 | 
				
			|||||||
  const isPopup = Object.keys(schema.properties || {}).length > 0;
 | 
					  const isPopup = Object.keys(schema.properties || {}).length > 0;
 | 
				
			||||||
  const inActionBar = schema.parent['x-component'] === 'Table.ActionBar';
 | 
					  const inActionBar = schema.parent['x-component'] === 'Table.ActionBar';
 | 
				
			||||||
  const displayed = useDisplayedMapContext();
 | 
					  const displayed = useDisplayedMapContext();
 | 
				
			||||||
 | 
					  const field = useField();
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <div className={cls('designable-bar', { active: visible })}>
 | 
					    <div className={cls('designable-bar', { active: visible })}>
 | 
				
			||||||
      <span
 | 
					      <span
 | 
				
			||||||
@ -1280,8 +1458,43 @@ Table.Action.DesignableBar = () => {
 | 
				
			|||||||
          overlay={
 | 
					          overlay={
 | 
				
			||||||
            <Menu>
 | 
					            <Menu>
 | 
				
			||||||
              <Menu.Item
 | 
					              <Menu.Item
 | 
				
			||||||
                onClick={(e) => {
 | 
					                onClick={async (e) => {
 | 
				
			||||||
                  schema.title = uid();
 | 
					                  const values = await FormDialog('修改名称和图标', () => {
 | 
				
			||||||
 | 
					                    return (
 | 
				
			||||||
 | 
					                      <FormLayout layout={'vertical'}>
 | 
				
			||||||
 | 
					                        <SchemaField
 | 
				
			||||||
 | 
					                          schema={{
 | 
				
			||||||
 | 
					                            type: 'object',
 | 
				
			||||||
 | 
					                            properties: {
 | 
				
			||||||
 | 
					                              title: {
 | 
				
			||||||
 | 
					                                type: 'string',
 | 
				
			||||||
 | 
					                                title: '按钮名称',
 | 
				
			||||||
 | 
					                                required: true,
 | 
				
			||||||
 | 
					                                'x-decorator': 'FormItem',
 | 
				
			||||||
 | 
					                                'x-component': 'Input',
 | 
				
			||||||
 | 
					                              },
 | 
				
			||||||
 | 
					                              icon: {
 | 
				
			||||||
 | 
					                                type: 'string',
 | 
				
			||||||
 | 
					                                title: '按钮图标',
 | 
				
			||||||
 | 
					                                'x-decorator': 'FormItem',
 | 
				
			||||||
 | 
					                                'x-component': 'IconPicker',
 | 
				
			||||||
 | 
					                              },
 | 
				
			||||||
 | 
					                            },
 | 
				
			||||||
 | 
					                          }}
 | 
				
			||||||
 | 
					                        />
 | 
				
			||||||
 | 
					                      </FormLayout>
 | 
				
			||||||
 | 
					                    );
 | 
				
			||||||
 | 
					                  }).open({
 | 
				
			||||||
 | 
					                    initialValues: {
 | 
				
			||||||
 | 
					                      title: schema['title'],
 | 
				
			||||||
 | 
					                      icon: schema['x-component-props']?.['icon'],
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                  });
 | 
				
			||||||
 | 
					                  schema['title'] = values.title;
 | 
				
			||||||
 | 
					                  schema['x-component-props']['icon'] = values.icon;
 | 
				
			||||||
 | 
					                  field.componentProps.icon = values.icon;
 | 
				
			||||||
 | 
					                  field.title = values.title;
 | 
				
			||||||
 | 
					                  updateSchema(schema);
 | 
				
			||||||
                  refresh();
 | 
					                  refresh();
 | 
				
			||||||
                }}
 | 
					                }}
 | 
				
			||||||
              >
 | 
					              >
 | 
				
			||||||
@ -1293,11 +1506,19 @@ Table.Action.DesignableBar = () => {
 | 
				
			|||||||
                  <Select
 | 
					                  <Select
 | 
				
			||||||
                    bordered={false}
 | 
					                    bordered={false}
 | 
				
			||||||
                    size={'small'}
 | 
					                    size={'small'}
 | 
				
			||||||
                    defaultValue={'modal'}
 | 
					                    defaultValue={'Action.Modal'}
 | 
				
			||||||
 | 
					                    onChange={(value) => {
 | 
				
			||||||
 | 
					                      const s = Object.values(schema.properties).shift();
 | 
				
			||||||
 | 
					                      s['x-component'] = value;
 | 
				
			||||||
 | 
					                      refresh();
 | 
				
			||||||
 | 
					                      updateSchema(s);
 | 
				
			||||||
 | 
					                      // const f = field.query(getSchemaPath(s)).take()
 | 
				
			||||||
 | 
					                      // console.log('fffffff', { schema, f });
 | 
				
			||||||
 | 
					                    }}
 | 
				
			||||||
                  >
 | 
					                  >
 | 
				
			||||||
                    <Select.Option value={'modal'}>对话框</Select.Option>
 | 
					                    <Select.Option value={'Action.Modal'}>对话框</Select.Option>
 | 
				
			||||||
                    <Select.Option value={'drawer'}>抽屉</Select.Option>
 | 
					                    <Select.Option value={'Action.Drawer'}>抽屉</Select.Option>
 | 
				
			||||||
                    <Select.Option value={'window'}>浏览器窗口</Select.Option>
 | 
					                    <Select.Option value={'Action.Window'}>浏览器窗口</Select.Option>
 | 
				
			||||||
                  </Select>{' '}
 | 
					                  </Select>{' '}
 | 
				
			||||||
                  内打开
 | 
					                  内打开
 | 
				
			||||||
                </Menu.Item>
 | 
					                </Menu.Item>
 | 
				
			||||||
@ -1321,7 +1542,7 @@ Table.Action.DesignableBar = () => {
 | 
				
			|||||||
                  setVisible(false);
 | 
					                  setVisible(false);
 | 
				
			||||||
                }}
 | 
					                }}
 | 
				
			||||||
              >
 | 
					              >
 | 
				
			||||||
                删除
 | 
					                移除
 | 
				
			||||||
              </Menu.Item>
 | 
					              </Menu.Item>
 | 
				
			||||||
            </Menu>
 | 
					            </Menu>
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
@ -1389,7 +1610,8 @@ Table.Column.DesignableBar = () => {
 | 
				
			|||||||
  const { schema, remove, refresh, insertAfter } = useDesignable();
 | 
					  const { schema, remove, refresh, insertAfter } = useDesignable();
 | 
				
			||||||
  const [visible, setVisible] = useState(false);
 | 
					  const [visible, setVisible] = useState(false);
 | 
				
			||||||
  const displayed = useDisplayedMapContext();
 | 
					  const displayed = useDisplayedMapContext();
 | 
				
			||||||
  const ctx = useContext(ColDraggableContext);
 | 
					  const collectionField = useContext(CollectionFieldContext);
 | 
				
			||||||
 | 
					  console.log('displayed.map', displayed.map);
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <div className={cls('designable-bar', { active: visible })}>
 | 
					    <div className={cls('designable-bar', { active: visible })}>
 | 
				
			||||||
      <span
 | 
					      <span
 | 
				
			||||||
@ -1409,7 +1631,38 @@ Table.Column.DesignableBar = () => {
 | 
				
			|||||||
            <Menu>
 | 
					            <Menu>
 | 
				
			||||||
              <Menu.Item
 | 
					              <Menu.Item
 | 
				
			||||||
                onClick={async (e) => {
 | 
					                onClick={async (e) => {
 | 
				
			||||||
                  const title = uid();
 | 
					                  const values = await FormDialog('修改列标题', () => {
 | 
				
			||||||
 | 
					                    return (
 | 
				
			||||||
 | 
					                      <FormLayout layout={'vertical'}>
 | 
				
			||||||
 | 
					                        <SchemaField
 | 
				
			||||||
 | 
					                          schema={{
 | 
				
			||||||
 | 
					                            type: 'object',
 | 
				
			||||||
 | 
					                            properties: {
 | 
				
			||||||
 | 
					                              fieldName: {
 | 
				
			||||||
 | 
					                                type: 'string',
 | 
				
			||||||
 | 
					                                title: '原字段名称',
 | 
				
			||||||
 | 
					                                'x-read-pretty': true,
 | 
				
			||||||
 | 
					                                'x-decorator': 'FormItem',
 | 
				
			||||||
 | 
					                                'x-component': 'Input',
 | 
				
			||||||
 | 
					                              },
 | 
				
			||||||
 | 
					                              title: {
 | 
				
			||||||
 | 
					                                type: 'string',
 | 
				
			||||||
 | 
					                                title: '自定义列标题',
 | 
				
			||||||
 | 
					                                'x-decorator': 'FormItem',
 | 
				
			||||||
 | 
					                                'x-component': 'Input',
 | 
				
			||||||
 | 
					                              },
 | 
				
			||||||
 | 
					                            },
 | 
				
			||||||
 | 
					                          }}
 | 
				
			||||||
 | 
					                        />
 | 
				
			||||||
 | 
					                      </FormLayout>
 | 
				
			||||||
 | 
					                    );
 | 
				
			||||||
 | 
					                  }).open({
 | 
				
			||||||
 | 
					                    initialValues: {
 | 
				
			||||||
 | 
					                      fieldName: collectionField?.uiSchema?.title,
 | 
				
			||||||
 | 
					                      title: schema['title'],
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                  });
 | 
				
			||||||
 | 
					                  const title = values.title || null;
 | 
				
			||||||
                  field.title = title;
 | 
					                  field.title = title;
 | 
				
			||||||
                  schema.title = title;
 | 
					                  schema.title = title;
 | 
				
			||||||
                  refresh();
 | 
					                  refresh();
 | 
				
			||||||
@ -1420,8 +1673,9 @@ Table.Column.DesignableBar = () => {
 | 
				
			|||||||
                  setVisible(false);
 | 
					                  setVisible(false);
 | 
				
			||||||
                }}
 | 
					                }}
 | 
				
			||||||
              >
 | 
					              >
 | 
				
			||||||
                编辑列
 | 
					                修改列标题
 | 
				
			||||||
              </Menu.Item>
 | 
					              </Menu.Item>
 | 
				
			||||||
 | 
					              <Menu.Divider />
 | 
				
			||||||
              <Menu.Item
 | 
					              <Menu.Item
 | 
				
			||||||
                onClick={async () => {
 | 
					                onClick={async () => {
 | 
				
			||||||
                  const s = remove();
 | 
					                  const s = remove();
 | 
				
			||||||
@ -1430,7 +1684,7 @@ Table.Column.DesignableBar = () => {
 | 
				
			|||||||
                  await removeSchema(s);
 | 
					                  await removeSchema(s);
 | 
				
			||||||
                }}
 | 
					                }}
 | 
				
			||||||
              >
 | 
					              >
 | 
				
			||||||
                删除列
 | 
					                移除
 | 
				
			||||||
              </Menu.Item>
 | 
					              </Menu.Item>
 | 
				
			||||||
            </Menu>
 | 
					            </Menu>
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
@ -1453,14 +1707,14 @@ Table.SortHandle = observer((props: any) => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Table.DesignableBar = observer((props) => {
 | 
					Table.DesignableBar = observer((props) => {
 | 
				
			||||||
  const field = useField();
 | 
					  const field = useField();
 | 
				
			||||||
  const { designable, schema, refresh, deepRemove } = useDesignable();
 | 
					  const { schema, refresh, deepRemove } = useDesignable();
 | 
				
			||||||
  const [visible, setVisible] = useState(false);
 | 
					  const [visible, setVisible] = useState(false);
 | 
				
			||||||
  const { dragRef } = useContext(DraggableBlockContext);
 | 
					  const { dragRef } = useContext(DraggableBlockContext);
 | 
				
			||||||
  if (!designable) {
 | 
					 | 
				
			||||||
    return null;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  const defaultPageSize =
 | 
					  const defaultPageSize =
 | 
				
			||||||
    schema['x-component-props']?.['pagination']?.['defaultPageSize'] || 20;
 | 
					    field?.componentProps?.pagination?.defaultPageSize || 10;
 | 
				
			||||||
 | 
					  const collectionName = field?.componentProps?.collectionName;
 | 
				
			||||||
 | 
					  const { fields } = useCollection({ collectionName });
 | 
				
			||||||
 | 
					  console.log({ collectionName });
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <div className={cls('designable-bar', { active: visible })}>
 | 
					    <div className={cls('designable-bar', { active: visible })}>
 | 
				
			||||||
      <span
 | 
					      <span
 | 
				
			||||||
@ -1486,9 +1740,16 @@ Table.DesignableBar = observer((props) => {
 | 
				
			|||||||
                    const bool = !field.componentProps.showIndex;
 | 
					                    const bool = !field.componentProps.showIndex;
 | 
				
			||||||
                    schema['x-component-props']['showIndex'] = bool;
 | 
					                    schema['x-component-props']['showIndex'] = bool;
 | 
				
			||||||
                    field.componentProps.showIndex = bool;
 | 
					                    field.componentProps.showIndex = bool;
 | 
				
			||||||
 | 
					                    updateSchema(schema);
 | 
				
			||||||
                  }}
 | 
					                  }}
 | 
				
			||||||
                >
 | 
					                >
 | 
				
			||||||
                  {field.componentProps.showIndex ? '隐藏序号' : '显示序号'}
 | 
					                  <div className={'nb-space-between'}>
 | 
				
			||||||
 | 
					                    显示序号{' '}
 | 
				
			||||||
 | 
					                    <Switch
 | 
				
			||||||
 | 
					                      size={'small'}
 | 
				
			||||||
 | 
					                      checked={field.componentProps.showIndex}
 | 
				
			||||||
 | 
					                    />
 | 
				
			||||||
 | 
					                  </div>
 | 
				
			||||||
                </Menu.Item>
 | 
					                </Menu.Item>
 | 
				
			||||||
                <Menu.Item
 | 
					                <Menu.Item
 | 
				
			||||||
                  key={'dragSort'}
 | 
					                  key={'dragSort'}
 | 
				
			||||||
@ -1498,16 +1759,166 @@ Table.DesignableBar = observer((props) => {
 | 
				
			|||||||
                      : 'sort';
 | 
					                      : 'sort';
 | 
				
			||||||
                    schema['x-component-props']['dragSort'] = dragSort;
 | 
					                    schema['x-component-props']['dragSort'] = dragSort;
 | 
				
			||||||
                    field.componentProps.dragSort = dragSort;
 | 
					                    field.componentProps.dragSort = dragSort;
 | 
				
			||||||
 | 
					                    updateSchema(schema);
 | 
				
			||||||
                  }}
 | 
					                  }}
 | 
				
			||||||
                >
 | 
					                >
 | 
				
			||||||
                  {field.componentProps.dragSort
 | 
					                  <div className={'nb-space-between'}>
 | 
				
			||||||
                    ? '禁用拖拽排序'
 | 
					                    启用拖拽排序{' '}
 | 
				
			||||||
                    : '启用拖拽排序'}
 | 
					                    <Switch
 | 
				
			||||||
 | 
					                      size={'small'}
 | 
				
			||||||
 | 
					                      checked={field.componentProps.dragSort}
 | 
				
			||||||
 | 
					                    />
 | 
				
			||||||
 | 
					                  </div>
 | 
				
			||||||
                </Menu.Item>
 | 
					                </Menu.Item>
 | 
				
			||||||
                {!field.componentProps.dragSort && (
 | 
					                {!field.componentProps.dragSort && (
 | 
				
			||||||
                  <Menu.Item key={'defaultSort'}>默认排序</Menu.Item>
 | 
					                  <Menu.Item
 | 
				
			||||||
 | 
					                    key={'defaultSort'}
 | 
				
			||||||
 | 
					                    onClick={async () => {
 | 
				
			||||||
 | 
					                      const defaultSort =
 | 
				
			||||||
 | 
					                        field.componentProps?.defaultSort?.map(
 | 
				
			||||||
 | 
					                          (item: string) => {
 | 
				
			||||||
 | 
					                            return item.startsWith('-')
 | 
				
			||||||
 | 
					                              ? {
 | 
				
			||||||
 | 
					                                  field: item.substring(1),
 | 
				
			||||||
 | 
					                                  direction: 'desc',
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                              : {
 | 
				
			||||||
 | 
					                                  field: item,
 | 
				
			||||||
 | 
					                                  direction: 'asc',
 | 
				
			||||||
 | 
					                                };
 | 
				
			||||||
 | 
					                          },
 | 
				
			||||||
 | 
					                        );
 | 
				
			||||||
 | 
					                      const values = await FormDialog('设置默认排序', () => {
 | 
				
			||||||
 | 
					                        return (
 | 
				
			||||||
 | 
					                          <FormLayout layout={'vertical'}>
 | 
				
			||||||
 | 
					                            <SchemaField
 | 
				
			||||||
 | 
					                              schema={{
 | 
				
			||||||
 | 
					                                type: 'object',
 | 
				
			||||||
 | 
					                                properties: {
 | 
				
			||||||
 | 
					                                  defaultSort: {
 | 
				
			||||||
 | 
					                                    type: 'array',
 | 
				
			||||||
 | 
					                                    'x-component': 'ArrayItems',
 | 
				
			||||||
 | 
					                                    'x-decorator': 'FormItem',
 | 
				
			||||||
 | 
					                                    items: {
 | 
				
			||||||
 | 
					                                      type: 'object',
 | 
				
			||||||
 | 
					                                      properties: {
 | 
				
			||||||
 | 
					                                        space: {
 | 
				
			||||||
 | 
					                                          type: 'void',
 | 
				
			||||||
 | 
					                                          'x-component': 'Space',
 | 
				
			||||||
 | 
					                                          properties: {
 | 
				
			||||||
 | 
					                                            sort: {
 | 
				
			||||||
 | 
					                                              type: 'void',
 | 
				
			||||||
 | 
					                                              'x-decorator': 'FormItem',
 | 
				
			||||||
 | 
					                                              'x-component':
 | 
				
			||||||
 | 
					                                                'ArrayItems.SortHandle',
 | 
				
			||||||
 | 
					                                            },
 | 
				
			||||||
 | 
					                                            field: {
 | 
				
			||||||
 | 
					                                              type: 'string',
 | 
				
			||||||
 | 
					                                              'x-decorator': 'FormItem',
 | 
				
			||||||
 | 
					                                              'x-component': 'Select',
 | 
				
			||||||
 | 
					                                              enum: fieldsToSortColumns(fields),
 | 
				
			||||||
 | 
					                                              'x-component-props': {
 | 
				
			||||||
 | 
					                                                style: {
 | 
				
			||||||
 | 
					                                                  width: 260,
 | 
				
			||||||
 | 
					                                                },
 | 
				
			||||||
 | 
					                                              },
 | 
				
			||||||
 | 
					                                            },
 | 
				
			||||||
 | 
					                                            direction: {
 | 
				
			||||||
 | 
					                                              type: 'string',
 | 
				
			||||||
 | 
					                                              'x-decorator': 'FormItem',
 | 
				
			||||||
 | 
					                                              'x-component': 'Select',
 | 
				
			||||||
 | 
					                                              'x-component-props': {
 | 
				
			||||||
 | 
					                                                style: {
 | 
				
			||||||
 | 
					                                                  width: 100,
 | 
				
			||||||
 | 
					                                                },
 | 
				
			||||||
 | 
					                                              },
 | 
				
			||||||
 | 
					                                              enum: [
 | 
				
			||||||
 | 
					                                                { label: '正序', value: 'asc' },
 | 
				
			||||||
 | 
					                                                {
 | 
				
			||||||
 | 
					                                                  label: '倒序',
 | 
				
			||||||
 | 
					                                                  value: 'desc',
 | 
				
			||||||
 | 
					                                                },
 | 
				
			||||||
 | 
					                                              ],
 | 
				
			||||||
 | 
					                                            },
 | 
				
			||||||
 | 
					                                            remove: {
 | 
				
			||||||
 | 
					                                              type: 'void',
 | 
				
			||||||
 | 
					                                              'x-decorator': 'FormItem',
 | 
				
			||||||
 | 
					                                              'x-component':
 | 
				
			||||||
 | 
					                                                'ArrayItems.Remove',
 | 
				
			||||||
 | 
					                                            },
 | 
				
			||||||
 | 
					                                          },
 | 
				
			||||||
 | 
					                                        },
 | 
				
			||||||
 | 
					                                      },
 | 
				
			||||||
 | 
					                                    },
 | 
				
			||||||
 | 
					                                    properties: {
 | 
				
			||||||
 | 
					                                      add: {
 | 
				
			||||||
 | 
					                                        type: 'void',
 | 
				
			||||||
 | 
					                                        title: '新增',
 | 
				
			||||||
 | 
					                                        'x-component': 'ArrayItems.Addition',
 | 
				
			||||||
 | 
					                                      },
 | 
				
			||||||
 | 
					                                    },
 | 
				
			||||||
 | 
					                                  },
 | 
				
			||||||
 | 
					                                },
 | 
				
			||||||
 | 
					                              }}
 | 
				
			||||||
 | 
					                            />
 | 
				
			||||||
 | 
					                          </FormLayout>
 | 
				
			||||||
 | 
					                        );
 | 
				
			||||||
 | 
					                      }).open({
 | 
				
			||||||
 | 
					                        initialValues: {
 | 
				
			||||||
 | 
					                          defaultSort,
 | 
				
			||||||
 | 
					                        },
 | 
				
			||||||
 | 
					                      });
 | 
				
			||||||
 | 
					                      const sort = values.defaultSort.map((item) => {
 | 
				
			||||||
 | 
					                        return item.direction === 'desc'
 | 
				
			||||||
 | 
					                          ? `-${item.field}`
 | 
				
			||||||
 | 
					                          : item.field;
 | 
				
			||||||
 | 
					                      });
 | 
				
			||||||
 | 
					                      schema['x-component-props']['defaultSort'] = sort;
 | 
				
			||||||
 | 
					                      field.componentProps.defaultSort = sort;
 | 
				
			||||||
 | 
					                      await updateSchema(schema);
 | 
				
			||||||
 | 
					                      console.log('defaultSort', sort);
 | 
				
			||||||
 | 
					                    }}
 | 
				
			||||||
 | 
					                  >
 | 
				
			||||||
 | 
					                    设置默认排序
 | 
				
			||||||
 | 
					                  </Menu.Item>
 | 
				
			||||||
                )}
 | 
					                )}
 | 
				
			||||||
                <Menu.Item key={'defaultFilter'}>筛选范围</Menu.Item>
 | 
					                <Menu.Item
 | 
				
			||||||
 | 
					                  key={'defaultFilter'}
 | 
				
			||||||
 | 
					                  onClick={async () => {
 | 
				
			||||||
 | 
					                    const { defaultFilter } = await FormDialog(
 | 
				
			||||||
 | 
					                      '设置筛选范围',
 | 
				
			||||||
 | 
					                      () => {
 | 
				
			||||||
 | 
					                        return (
 | 
				
			||||||
 | 
					                          <FormLayout layout={'vertical'}>
 | 
				
			||||||
 | 
					                            <SchemaField
 | 
				
			||||||
 | 
					                              schema={{
 | 
				
			||||||
 | 
					                                type: 'object',
 | 
				
			||||||
 | 
					                                properties: {
 | 
				
			||||||
 | 
					                                  defaultFilter: {
 | 
				
			||||||
 | 
					                                    type: 'object',
 | 
				
			||||||
 | 
					                                    'x-component': 'Filter',
 | 
				
			||||||
 | 
					                                    properties: fieldsToFilterColumns(fields),
 | 
				
			||||||
 | 
					                                  },
 | 
				
			||||||
 | 
					                                },
 | 
				
			||||||
 | 
					                              }}
 | 
				
			||||||
 | 
					                            />
 | 
				
			||||||
 | 
					                          </FormLayout>
 | 
				
			||||||
 | 
					                        );
 | 
				
			||||||
 | 
					                      },
 | 
				
			||||||
 | 
					                    ).open({
 | 
				
			||||||
 | 
					                      initialValues: {
 | 
				
			||||||
 | 
					                        defaultFilter:
 | 
				
			||||||
 | 
					                          field?.componentProps?.defaultFilter || {},
 | 
				
			||||||
 | 
					                      },
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					                    schema['x-component-props']['defaultFilter'] =
 | 
				
			||||||
 | 
					                      defaultFilter;
 | 
				
			||||||
 | 
					                    field.componentProps.defaultFilter = defaultFilter;
 | 
				
			||||||
 | 
					                    await updateSchema(schema);
 | 
				
			||||||
 | 
					                  }}
 | 
				
			||||||
 | 
					                >
 | 
				
			||||||
 | 
					                  设置筛选范围
 | 
				
			||||||
 | 
					                </Menu.Item>
 | 
				
			||||||
                <Menu.Item key={'defaultPageSize'}>
 | 
					                <Menu.Item key={'defaultPageSize'}>
 | 
				
			||||||
                  每页默认显示{' '}
 | 
					                  每页默认显示{' '}
 | 
				
			||||||
                  <Select
 | 
					                  <Select
 | 
				
			||||||
@ -1516,11 +1927,16 @@ Table.DesignableBar = observer((props) => {
 | 
				
			|||||||
                    onChange={(value) => {
 | 
					                    onChange={(value) => {
 | 
				
			||||||
                      const componentProps = schema['x-component-props'] || {};
 | 
					                      const componentProps = schema['x-component-props'] || {};
 | 
				
			||||||
                      set(componentProps, 'pagination.defaultPageSize', value);
 | 
					                      set(componentProps, 'pagination.defaultPageSize', value);
 | 
				
			||||||
 | 
					                      set(componentProps, 'pagination.pageSize', value);
 | 
				
			||||||
                      schema['x-component-props'] = componentProps;
 | 
					                      schema['x-component-props'] = componentProps;
 | 
				
			||||||
 | 
					                      field.componentProps.pagination.pageSize = value;
 | 
				
			||||||
 | 
					                      field.componentProps.pagination.defaultPageSize = value;
 | 
				
			||||||
                      refresh();
 | 
					                      refresh();
 | 
				
			||||||
 | 
					                      updateSchema(schema);
 | 
				
			||||||
                    }}
 | 
					                    }}
 | 
				
			||||||
                    defaultValue={defaultPageSize}
 | 
					                    defaultValue={defaultPageSize}
 | 
				
			||||||
                  >
 | 
					                  >
 | 
				
			||||||
 | 
					                    <Select.Option value={10}>10</Select.Option>
 | 
				
			||||||
                    <Select.Option value={20}>20</Select.Option>
 | 
					                    <Select.Option value={20}>20</Select.Option>
 | 
				
			||||||
                    <Select.Option value={50}>50</Select.Option>
 | 
					                    <Select.Option value={50}>50</Select.Option>
 | 
				
			||||||
                    <Select.Option value={100}>100</Select.Option>
 | 
					                    <Select.Option value={100}>100</Select.Option>
 | 
				
			||||||
@ -1539,7 +1955,7 @@ Table.DesignableBar = observer((props) => {
 | 
				
			|||||||
                    }
 | 
					                    }
 | 
				
			||||||
                  }}
 | 
					                  }}
 | 
				
			||||||
                >
 | 
					                >
 | 
				
			||||||
                  删除当前区块
 | 
					                  移除
 | 
				
			||||||
                </Menu.Item>
 | 
					                </Menu.Item>
 | 
				
			||||||
              </Menu>
 | 
					              </Menu>
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
				
			|||||||
@ -225,3 +225,9 @@ td.nb-table-operation {
 | 
				
			|||||||
  min-height: 32px;
 | 
					  min-height: 32px;
 | 
				
			||||||
  background-color: #e6f7ff;
 | 
					  background-color: #e6f7ff;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.nb-space-between {
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  align-items: center;
 | 
				
			||||||
 | 
					  justify-content: space-between;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,12 @@
 | 
				
			|||||||
import { observer, connect, useField, RecursionField } from '@formily/react';
 | 
					import { observer, connect, useField, RecursionField } from '@formily/react';
 | 
				
			||||||
import React from 'react';
 | 
					import React from 'react';
 | 
				
			||||||
import { Button, Tabs as AntdTabs, Dropdown, Menu, Switch } from 'antd';
 | 
					import { Button, Tabs as AntdTabs, Dropdown, Menu, Switch } from 'antd';
 | 
				
			||||||
import { findPropertyByPath, getSchemaPath, useDesignable } from '../../components/schema-renderer';
 | 
					import {
 | 
				
			||||||
 | 
					  findPropertyByPath,
 | 
				
			||||||
 | 
					  getSchemaPath,
 | 
				
			||||||
 | 
					  SchemaField,
 | 
				
			||||||
 | 
					  useDesignable,
 | 
				
			||||||
 | 
					} from '../../components/schema-renderer';
 | 
				
			||||||
import { Schema, SchemaKey } from '@formily/react';
 | 
					import { Schema, SchemaKey } from '@formily/react';
 | 
				
			||||||
import { PlusOutlined, MenuOutlined } from '@ant-design/icons';
 | 
					import { PlusOutlined, MenuOutlined } from '@ant-design/icons';
 | 
				
			||||||
import { useState } from 'react';
 | 
					import { useState } from 'react';
 | 
				
			||||||
@ -11,6 +16,8 @@ import './style.less';
 | 
				
			|||||||
import { uid } from '@formily/shared';
 | 
					import { uid } from '@formily/shared';
 | 
				
			||||||
import { DragHandle, SortableItem } from '../../components/Sortable';
 | 
					import { DragHandle, SortableItem } from '../../components/Sortable';
 | 
				
			||||||
import { DndContext, DragOverlay } from '@dnd-kit/core';
 | 
					import { DndContext, DragOverlay } from '@dnd-kit/core';
 | 
				
			||||||
 | 
					import { FormDialog, FormLayout } from '@formily/antd';
 | 
				
			||||||
 | 
					import IconPicker from '../../components/icon-picker';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const useTabs = ({ singleton }) => {
 | 
					const useTabs = ({ singleton }) => {
 | 
				
			||||||
  const tabsField = useField();
 | 
					  const tabsField = useField();
 | 
				
			||||||
@ -38,7 +45,8 @@ const useTabs = ({ singleton }) => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export const Tabs: any = observer((props: any) => {
 | 
					export const Tabs: any = observer((props: any) => {
 | 
				
			||||||
  const { singleton, ...others } = props;
 | 
					  const { singleton, ...others } = props;
 | 
				
			||||||
  const { schema, DesignableBar, appendChild, root, remove, insertAfter } = useDesignable();
 | 
					  const { schema, DesignableBar, appendChild, root, remove, insertAfter } =
 | 
				
			||||||
 | 
					    useDesignable();
 | 
				
			||||||
  const tabs = useTabs({ singleton });
 | 
					  const tabs = useTabs({ singleton });
 | 
				
			||||||
  const [dragOverlayContent, setDragOverlayContent] = useState('');
 | 
					  const [dragOverlayContent, setDragOverlayContent] = useState('');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -93,14 +101,45 @@ export const Tabs: any = observer((props: any) => {
 | 
				
			|||||||
              type={'dashed'}
 | 
					              type={'dashed'}
 | 
				
			||||||
              icon={<PlusOutlined />}
 | 
					              icon={<PlusOutlined />}
 | 
				
			||||||
              onClick={async () => {
 | 
					              onClick={async () => {
 | 
				
			||||||
 | 
					                const values = await FormDialog('新增标签页', () => {
 | 
				
			||||||
 | 
					                  return (
 | 
				
			||||||
 | 
					                    <FormLayout layout={'vertical'}>
 | 
				
			||||||
 | 
					                      <SchemaField
 | 
				
			||||||
 | 
					                        schema={{
 | 
				
			||||||
 | 
					                          type: 'object',
 | 
				
			||||||
 | 
					                          properties: {
 | 
				
			||||||
 | 
					                            title: {
 | 
				
			||||||
 | 
					                              type: 'string',
 | 
				
			||||||
 | 
					                              title: '标签名称',
 | 
				
			||||||
 | 
					                              required: true,
 | 
				
			||||||
 | 
					                              'x-decorator': 'FormItem',
 | 
				
			||||||
 | 
					                              'x-component': 'Input',
 | 
				
			||||||
 | 
					                            },
 | 
				
			||||||
 | 
					                            icon: {
 | 
				
			||||||
 | 
					                              type: 'string',
 | 
				
			||||||
 | 
					                              title: '标签图标',
 | 
				
			||||||
 | 
					                              'x-decorator': 'FormItem',
 | 
				
			||||||
 | 
					                              'x-component': 'IconPicker',
 | 
				
			||||||
 | 
					                            },
 | 
				
			||||||
 | 
					                          },
 | 
				
			||||||
 | 
					                        }}
 | 
				
			||||||
 | 
					                      />
 | 
				
			||||||
 | 
					                    </FormLayout>
 | 
				
			||||||
 | 
					                  );
 | 
				
			||||||
 | 
					                }).open({
 | 
				
			||||||
 | 
					                  initialValues: {
 | 
				
			||||||
 | 
					                    title: schema['title'],
 | 
				
			||||||
 | 
					                    icon: schema['x-component-props']?.['icon'],
 | 
				
			||||||
 | 
					                  },
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
                const data = appendChild({
 | 
					                const data = appendChild({
 | 
				
			||||||
                  type: 'void',
 | 
					                  type: 'void',
 | 
				
			||||||
                  name: uid(),
 | 
					                  name: uid(),
 | 
				
			||||||
                  title: uid(),
 | 
					                  title: values.title,
 | 
				
			||||||
                  'x-component': 'Tabs.TabPane',
 | 
					                  'x-component': 'Tabs.TabPane',
 | 
				
			||||||
                  'x-designable-bar': 'Tabs.TabPane.DesignableBar',
 | 
					                  'x-designable-bar': 'Tabs.TabPane.DesignableBar',
 | 
				
			||||||
                  'x-component-props': {
 | 
					                  'x-component-props': {
 | 
				
			||||||
                    tab: uid(),
 | 
					                    icon: values.icon,
 | 
				
			||||||
                  },
 | 
					                  },
 | 
				
			||||||
                  properties: {
 | 
					                  properties: {
 | 
				
			||||||
                    [uid()]: {
 | 
					                    [uid()]: {
 | 
				
			||||||
@ -151,6 +190,7 @@ Tabs.TabPane = observer((props: any) => {
 | 
				
			|||||||
      }}
 | 
					      }}
 | 
				
			||||||
    >
 | 
					    >
 | 
				
			||||||
      <div className={'nb-tab-pane'}>
 | 
					      <div className={'nb-tab-pane'}>
 | 
				
			||||||
 | 
					        <IconPicker type={props.icon} />
 | 
				
			||||||
        {schema.title} <DesignableBar />
 | 
					        {schema.title} <DesignableBar />
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    </SortableItem>
 | 
					    </SortableItem>
 | 
				
			||||||
@ -185,10 +225,14 @@ Tabs.DesignableBar = () => {
 | 
				
			|||||||
                    schema['x-component-props'] || {};
 | 
					                    schema['x-component-props'] || {};
 | 
				
			||||||
                  schema['x-component-props'].singleton = singleton;
 | 
					                  schema['x-component-props'].singleton = singleton;
 | 
				
			||||||
                  field.componentProps.singleton = singleton;
 | 
					                  field.componentProps.singleton = singleton;
 | 
				
			||||||
 | 
					                  updateSchema(schema);
 | 
				
			||||||
                }}
 | 
					                }}
 | 
				
			||||||
              >
 | 
					              >
 | 
				
			||||||
                禁用标签页 <span style={{ marginRight: 24 }}></span>{' '}
 | 
					                禁用标签页 <span style={{ marginRight: 24 }}></span>{' '}
 | 
				
			||||||
                <Switch size={'small'} checked={!!field.componentProps.singleton}/>
 | 
					                <Switch
 | 
				
			||||||
 | 
					                  size={'small'}
 | 
				
			||||||
 | 
					                  checked={!!field.componentProps.singleton}
 | 
				
			||||||
 | 
					                />
 | 
				
			||||||
              </Menu.Item>
 | 
					              </Menu.Item>
 | 
				
			||||||
            </Menu>
 | 
					            </Menu>
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
@ -203,7 +247,7 @@ Tabs.DesignableBar = () => {
 | 
				
			|||||||
Tabs.TabPane.DesignableBar = () => {
 | 
					Tabs.TabPane.DesignableBar = () => {
 | 
				
			||||||
  const { schema, remove, refresh, insertAfter } = useDesignable();
 | 
					  const { schema, remove, refresh, insertAfter } = useDesignable();
 | 
				
			||||||
  const [visible, setVisible] = useState(false);
 | 
					  const [visible, setVisible] = useState(false);
 | 
				
			||||||
 | 
					  const field = useField();
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <div className={cls('designable-bar', { active: visible })}>
 | 
					    <div className={cls('designable-bar', { active: visible })}>
 | 
				
			||||||
      <span
 | 
					      <span
 | 
				
			||||||
@ -222,12 +266,45 @@ Tabs.TabPane.DesignableBar = () => {
 | 
				
			|||||||
          overlay={
 | 
					          overlay={
 | 
				
			||||||
            <Menu>
 | 
					            <Menu>
 | 
				
			||||||
              <Menu.Item
 | 
					              <Menu.Item
 | 
				
			||||||
                onClick={() => {
 | 
					                onClick={async () => {
 | 
				
			||||||
                  schema.title = uid();
 | 
					                  const values = await FormDialog('修改名称和图标', () => {
 | 
				
			||||||
 | 
					                    return (
 | 
				
			||||||
 | 
					                      <FormLayout layout={'vertical'}>
 | 
				
			||||||
 | 
					                        <SchemaField
 | 
				
			||||||
 | 
					                          schema={{
 | 
				
			||||||
 | 
					                            type: 'object',
 | 
				
			||||||
 | 
					                            properties: {
 | 
				
			||||||
 | 
					                              title: {
 | 
				
			||||||
 | 
					                                type: 'string',
 | 
				
			||||||
 | 
					                                title: '标签名称',
 | 
				
			||||||
 | 
					                                required: true,
 | 
				
			||||||
 | 
					                                'x-decorator': 'FormItem',
 | 
				
			||||||
 | 
					                                'x-component': 'Input',
 | 
				
			||||||
 | 
					                              },
 | 
				
			||||||
 | 
					                              icon: {
 | 
				
			||||||
 | 
					                                type: 'string',
 | 
				
			||||||
 | 
					                                title: '标签图标',
 | 
				
			||||||
 | 
					                                'x-decorator': 'FormItem',
 | 
				
			||||||
 | 
					                                'x-component': 'IconPicker',
 | 
				
			||||||
 | 
					                              },
 | 
				
			||||||
 | 
					                            },
 | 
				
			||||||
 | 
					                          }}
 | 
				
			||||||
 | 
					                        />
 | 
				
			||||||
 | 
					                      </FormLayout>
 | 
				
			||||||
 | 
					                    );
 | 
				
			||||||
 | 
					                  }).open({
 | 
				
			||||||
 | 
					                    initialValues: {
 | 
				
			||||||
 | 
					                      title: schema['title'],
 | 
				
			||||||
 | 
					                      icon: schema['x-component-props']?.['icon'],
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                  });
 | 
				
			||||||
 | 
					                  field.componentProps.icon = values.icon;
 | 
				
			||||||
 | 
					                  schema.title = values.title;
 | 
				
			||||||
                  schema['x-component-props'] =
 | 
					                  schema['x-component-props'] =
 | 
				
			||||||
                    schema['x-component-props'] || {};
 | 
					                    schema['x-component-props'] || {};
 | 
				
			||||||
                  schema['x-component-props']['tab'] = uid();
 | 
					                  schema['x-component-props']['icon'] = values.icon;
 | 
				
			||||||
                  refresh();
 | 
					                  refresh();
 | 
				
			||||||
 | 
					                  updateSchema(schema);
 | 
				
			||||||
                }}
 | 
					                }}
 | 
				
			||||||
              >
 | 
					              >
 | 
				
			||||||
                修改名称和图标
 | 
					                修改名称和图标
 | 
				
			||||||
@ -240,7 +317,7 @@ Tabs.TabPane.DesignableBar = () => {
 | 
				
			|||||||
                  setVisible(false);
 | 
					                  setVisible(false);
 | 
				
			||||||
                }}
 | 
					                }}
 | 
				
			||||||
              >
 | 
					              >
 | 
				
			||||||
                删除
 | 
					                移除
 | 
				
			||||||
              </Menu.Item>
 | 
					              </Menu.Item>
 | 
				
			||||||
            </Menu>
 | 
					            </Menu>
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
 | 
				
			|||||||
@ -144,6 +144,7 @@ export class Table {
 | 
				
			|||||||
      model,
 | 
					      model,
 | 
				
			||||||
      fields = [],
 | 
					      fields = [],
 | 
				
			||||||
      indexes = [],
 | 
					      indexes = [],
 | 
				
			||||||
 | 
					      sortable,
 | 
				
			||||||
    } = options;
 | 
					    } = options;
 | 
				
			||||||
    this.options = options;
 | 
					    this.options = options;
 | 
				
			||||||
    this.database = database;
 | 
					    this.database = database;
 | 
				
			||||||
@ -155,9 +156,28 @@ export class Table {
 | 
				
			|||||||
    this.addIndexes(indexes, 'modelOnly');
 | 
					    this.addIndexes(indexes, 'modelOnly');
 | 
				
			||||||
    // this.modelInit('modelOnly');
 | 
					    // this.modelInit('modelOnly');
 | 
				
			||||||
    this.setFields(fields);
 | 
					    this.setFields(fields);
 | 
				
			||||||
 | 
					    this.initSortable();
 | 
				
			||||||
    database.runHooks('afterTableInit', this);
 | 
					    database.runHooks('afterTableInit', this);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public initSortable() {
 | 
				
			||||||
 | 
					    const { sortable } = this.options;
 | 
				
			||||||
 | 
					    if (!sortable) {
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (typeof sortable === 'string') {
 | 
				
			||||||
 | 
					      this.addField({
 | 
				
			||||||
 | 
					        type: 'sort',
 | 
				
			||||||
 | 
					        name: sortable,
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    } else if (typeof sortable === 'object') {
 | 
				
			||||||
 | 
					      this.addField({
 | 
				
			||||||
 | 
					        ...sortable,
 | 
				
			||||||
 | 
					        type: 'sort',
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public modelInit(reinitialize: Reinitialize = false) {
 | 
					  public modelInit(reinitialize: Reinitialize = false) {
 | 
				
			||||||
    if (reinitialize || !this.Model) {
 | 
					    if (reinitialize || !this.Model) {
 | 
				
			||||||
      this.Model = this.defaultModel || class extends Model { };
 | 
					      this.Model = this.defaultModel || class extends Model { };
 | 
				
			||||||
@ -389,6 +409,7 @@ export class Table {
 | 
				
			|||||||
    for (const key in fields) {
 | 
					    for (const key in fields) {
 | 
				
			||||||
      this.addField(fields[key], false);
 | 
					      this.addField(fields[key], false);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    this.initSortable();
 | 
				
			||||||
    // @ts-ignore
 | 
					    // @ts-ignore
 | 
				
			||||||
    this.addIndexes(indexes, false);
 | 
					    this.addIndexes(indexes, false);
 | 
				
			||||||
    this.modelInit(true);
 | 
					    this.modelInit(true);
 | 
				
			||||||
 | 
				
			|||||||
@ -4,11 +4,12 @@ export default {
 | 
				
			|||||||
  name: 'collections',
 | 
					  name: 'collections',
 | 
				
			||||||
  title: '数据表配置',
 | 
					  title: '数据表配置',
 | 
				
			||||||
  model: 'Collection',
 | 
					  model: 'Collection',
 | 
				
			||||||
 | 
					  sortable: 'sort',
 | 
				
			||||||
  fields: [
 | 
					  fields: [
 | 
				
			||||||
    {
 | 
					    // {
 | 
				
			||||||
      type: 'sort',
 | 
					    //   type: 'sort',
 | 
				
			||||||
      name: 'sort',
 | 
					    //   name: 'sort',
 | 
				
			||||||
    },
 | 
					    // },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      type: 'uid',
 | 
					      type: 'uid',
 | 
				
			||||||
      name: 'name',
 | 
					      name: 'name',
 | 
				
			||||||
@ -24,6 +25,11 @@ export default {
 | 
				
			|||||||
      type: 'string',
 | 
					      type: 'string',
 | 
				
			||||||
      name: 'privilege',
 | 
					      name: 'privilege',
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      type: 'json',
 | 
				
			||||||
 | 
					      name: 'sortable',
 | 
				
			||||||
 | 
					      defaultValue: 'sort',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      type: 'json',
 | 
					      type: 'json',
 | 
				
			||||||
      name: 'options',
 | 
					      name: 'options',
 | 
				
			||||||
 | 
				
			|||||||
@ -5,12 +5,17 @@ export default {
 | 
				
			|||||||
  name: 'fields',
 | 
					  name: 'fields',
 | 
				
			||||||
  title: '字段配置',
 | 
					  title: '字段配置',
 | 
				
			||||||
  model: 'Field',
 | 
					  model: 'Field',
 | 
				
			||||||
 | 
					  sortable: {
 | 
				
			||||||
 | 
					    type: 'sort',
 | 
				
			||||||
 | 
					    name: 'sort',
 | 
				
			||||||
 | 
					    scope: ['parentKey'],
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
  fields: [
 | 
					  fields: [
 | 
				
			||||||
    {
 | 
					    // {
 | 
				
			||||||
      type: 'sort',
 | 
					    //   type: 'sort',
 | 
				
			||||||
      name: 'sort',
 | 
					    //   name: 'sort',
 | 
				
			||||||
      scope: ['parentKey'],
 | 
					    //   scope: ['parentKey'],
 | 
				
			||||||
    },
 | 
					    // },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      type: 'uid',
 | 
					      type: 'uid',
 | 
				
			||||||
      name: 'key',
 | 
					      name: 'key',
 | 
				
			||||||
 | 
				
			|||||||
@ -4,12 +4,17 @@ export default {
 | 
				
			|||||||
  name: 'routes',
 | 
					  name: 'routes',
 | 
				
			||||||
  title: '路由表',
 | 
					  title: '路由表',
 | 
				
			||||||
  model: 'Route',
 | 
					  model: 'Route',
 | 
				
			||||||
 | 
					  sortable: {
 | 
				
			||||||
 | 
					    type: 'sort',
 | 
				
			||||||
 | 
					    name: 'sort',
 | 
				
			||||||
 | 
					    scope: ['parentKey'],
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
  fields: [
 | 
					  fields: [
 | 
				
			||||||
    {
 | 
					    // {
 | 
				
			||||||
      type: 'sort',
 | 
					    //   type: 'sort',
 | 
				
			||||||
      name: 'sort',
 | 
					    //   name: 'sort',
 | 
				
			||||||
      scope: ['parentKey'],
 | 
					    //   scope: ['parentKey'],
 | 
				
			||||||
    },
 | 
					    // },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      type: 'uid',
 | 
					      type: 'uid',
 | 
				
			||||||
      name: 'key',
 | 
					      name: 'key',
 | 
				
			||||||
 | 
				
			|||||||
@ -4,17 +4,22 @@ export default {
 | 
				
			|||||||
  name: 'ui_schemas',
 | 
					  name: 'ui_schemas',
 | 
				
			||||||
  title: '字段配置',
 | 
					  title: '字段配置',
 | 
				
			||||||
  model: 'UISchema',
 | 
					  model: 'UISchema',
 | 
				
			||||||
 | 
					  sortable: {
 | 
				
			||||||
 | 
					    type: 'sort',
 | 
				
			||||||
 | 
					    name: 'sort',
 | 
				
			||||||
 | 
					    scope: ['parentKey'],
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
  fields: [
 | 
					  fields: [
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      type: 'uid',
 | 
					      type: 'uid',
 | 
				
			||||||
      name: 'key',
 | 
					      name: 'key',
 | 
				
			||||||
      primaryKey: true,
 | 
					      primaryKey: true,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    // {
 | 
				
			||||||
      type: 'sort',
 | 
					    //   type: 'sort',
 | 
				
			||||||
      name: 'sort',
 | 
					    //   name: 'sort',
 | 
				
			||||||
      scope: ['parentKey'],
 | 
					    //   scope: ['parentKey'],
 | 
				
			||||||
    },
 | 
					    // },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      type: 'string',
 | 
					      type: 'string',
 | 
				
			||||||
      name: 'name',
 | 
					      name: 'name',
 | 
				
			||||||
 | 
				
			|||||||
@ -8710,6 +8710,11 @@ flat-to-nested@^1.1.1:
 | 
				
			|||||||
  resolved "https://registry.npmjs.org/flat-to-nested/-/flat-to-nested-1.1.1.tgz#ec183cd9a72f6bfbf8ca21acb0fc8235e509f581"
 | 
					  resolved "https://registry.npmjs.org/flat-to-nested/-/flat-to-nested-1.1.1.tgz#ec183cd9a72f6bfbf8ca21acb0fc8235e509f581"
 | 
				
			||||||
  integrity sha512-Sym5oik6BO9JnsDEjv9Q9hPTCexG2ttk0UiM2mgLEiCiiUOQr8acBd33r8ixnoSGR0HAxPoP8WtLAL5oV46IhQ==
 | 
					  integrity sha512-Sym5oik6BO9JnsDEjv9Q9hPTCexG2ttk0UiM2mgLEiCiiUOQr8acBd33r8ixnoSGR0HAxPoP8WtLAL5oV46IhQ==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					flat@^5.0.2:
 | 
				
			||||||
 | 
					  version "5.0.2"
 | 
				
			||||||
 | 
					  resolved "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241"
 | 
				
			||||||
 | 
					  integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==
 | 
				
			||||||
 | 
					
 | 
				
			||||||
flatted@^3.1.0:
 | 
					flatted@^3.1.0:
 | 
				
			||||||
  version "3.1.1"
 | 
					  version "3.1.1"
 | 
				
			||||||
  resolved "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469"
 | 
					  resolved "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469"
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user