feat: action bar for the descriptions block
This commit is contained in:
		
							parent
							
								
									41cbb26b2e
								
							
						
					
					
						commit
						8f746ae319
					
				@ -1,3 +1,3 @@
 | 
			
		||||
import { createContext } from "react";
 | 
			
		||||
 | 
			
		||||
export const VisibleContext = createContext<any>(null);
 | 
			
		||||
export const VisibleContext = createContext<any>([]);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										256
									
								
								packages/client/src/schemas/action/ActionBar.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										256
									
								
								packages/client/src/schemas/action/ActionBar.tsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,256 @@
 | 
			
		||||
import { DndContext, DragOverlay } from '@dnd-kit/core';
 | 
			
		||||
import { ISchema, observer, RecursionField, Schema } from '@formily/react';
 | 
			
		||||
import React, { useState } from 'react';
 | 
			
		||||
import { createSchema, removeSchema, updateSchema } from '..';
 | 
			
		||||
import {
 | 
			
		||||
  findPropertyByPath,
 | 
			
		||||
  getSchemaPath,
 | 
			
		||||
  useDesignable,
 | 
			
		||||
} from '../../components/schema-renderer';
 | 
			
		||||
import { DisplayedMapProvider, useDisplayedMapContext } from '../../constate';
 | 
			
		||||
import cls from 'classnames';
 | 
			
		||||
import { Button, Dropdown, Menu, Space } from 'antd';
 | 
			
		||||
import SwitchMenuItem from '../../components/SwitchMenuItem';
 | 
			
		||||
import { uid } from '@formily/shared';
 | 
			
		||||
import { PlusOutlined } from '@ant-design/icons';
 | 
			
		||||
import { Droppable, SortableItem } from '../../components/Sortable';
 | 
			
		||||
 | 
			
		||||
export const ActionBar = observer((props: any) => {
 | 
			
		||||
  const { align = 'top' } = props;
 | 
			
		||||
  // const { schema, designable } = useDesignable();
 | 
			
		||||
  const { root, schema, insertAfter, remove, appendChild } = useDesignable();
 | 
			
		||||
  const moveToAfter = (path1, path2, extra = {}) => {
 | 
			
		||||
    if (!path1 || !path2) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    if (path1.join('.') === path2.join('.')) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    const data = findPropertyByPath(root, path1);
 | 
			
		||||
    if (!data) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    remove(path1);
 | 
			
		||||
    return insertAfter(
 | 
			
		||||
      {
 | 
			
		||||
        ...data.toJSON(),
 | 
			
		||||
        ...extra,
 | 
			
		||||
      },
 | 
			
		||||
      path2,
 | 
			
		||||
    );
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const [dragOverlayContent, setDragOverlayContent] = useState('');
 | 
			
		||||
  return (
 | 
			
		||||
    <DndContext
 | 
			
		||||
      onDragStart={(event) => {
 | 
			
		||||
        setDragOverlayContent(event.active.data?.current?.title || '');
 | 
			
		||||
        // const previewRef = event.active.data?.current?.previewRef;
 | 
			
		||||
        // if (previewRef) {
 | 
			
		||||
        //   setDragOverlayContent(previewRef?.current?.innerHTML);
 | 
			
		||||
        // } else {
 | 
			
		||||
        //   setDragOverlayContent('');
 | 
			
		||||
        // }
 | 
			
		||||
      }}
 | 
			
		||||
      onDragEnd={async (event) => {
 | 
			
		||||
        const path1 = event.active?.data?.current?.path;
 | 
			
		||||
        const path2 = event.over?.data?.current?.path;
 | 
			
		||||
        const align = event.over?.data?.current?.align;
 | 
			
		||||
        const draggable = event.over?.data?.current?.draggable;
 | 
			
		||||
        if (!path1 || !path2) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        if (path1.join('.') === path2.join('.')) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        if (!draggable) {
 | 
			
		||||
          console.log('alignalignalignalign', align);
 | 
			
		||||
          const p = findPropertyByPath(root, path1);
 | 
			
		||||
          if (!p) {
 | 
			
		||||
            return;
 | 
			
		||||
          }
 | 
			
		||||
          remove(path1);
 | 
			
		||||
          const data = appendChild(
 | 
			
		||||
            {
 | 
			
		||||
              ...p.toJSON(),
 | 
			
		||||
              'x-align': align,
 | 
			
		||||
            },
 | 
			
		||||
            path2,
 | 
			
		||||
          );
 | 
			
		||||
          await updateSchema(data);
 | 
			
		||||
        } else {
 | 
			
		||||
          const data = moveToAfter(path1, path2, {
 | 
			
		||||
            'x-align': align,
 | 
			
		||||
          });
 | 
			
		||||
          await updateSchema(data);
 | 
			
		||||
        }
 | 
			
		||||
      }}
 | 
			
		||||
    >
 | 
			
		||||
      <DragOverlay style={{ pointerEvents: 'none', whiteSpace: 'nowrap' }}>
 | 
			
		||||
        {dragOverlayContent}
 | 
			
		||||
        {/* <div style={{ transform: 'translateX(-100%)' }} dangerouslySetInnerHTML={{__html: dragOverlayContent}}></div> */}
 | 
			
		||||
      </DragOverlay>
 | 
			
		||||
      <DisplayedMapProvider>
 | 
			
		||||
        <div className={cls('nb-action-bar', `align-${align}`)}>
 | 
			
		||||
          <div style={{ width: '50%' }}>
 | 
			
		||||
            <Actions align={'left'} />
 | 
			
		||||
          </div>
 | 
			
		||||
          <div style={{ marginLeft: 'auto', width: '50%', textAlign: 'right' }}>
 | 
			
		||||
            <Actions align={'right'} />
 | 
			
		||||
          </div>
 | 
			
		||||
          <AddActionButton />
 | 
			
		||||
        </div>
 | 
			
		||||
      </DisplayedMapProvider>
 | 
			
		||||
    </DndContext>
 | 
			
		||||
  );
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function generateActionSchema(type) {
 | 
			
		||||
  const actions: { [key: string]: ISchema } = {
 | 
			
		||||
    update: {
 | 
			
		||||
      type: 'void',
 | 
			
		||||
      title: '编辑',
 | 
			
		||||
      'x-align': 'right',
 | 
			
		||||
      'x-decorator': 'AddNew.Displayed',
 | 
			
		||||
      'x-decorator-props': {
 | 
			
		||||
        displayName: 'update',
 | 
			
		||||
      },
 | 
			
		||||
      'x-component': 'Action',
 | 
			
		||||
      'x-component-props': {
 | 
			
		||||
        type: 'primary',
 | 
			
		||||
      },
 | 
			
		||||
      'x-action-type': 'update',
 | 
			
		||||
      'x-designable-bar': 'Action.DesignableBar',
 | 
			
		||||
      properties: {
 | 
			
		||||
        modal: {
 | 
			
		||||
          type: 'void',
 | 
			
		||||
          title: '编辑数据',
 | 
			
		||||
          'x-decorator': 'Form',
 | 
			
		||||
          'x-decorator-props': {
 | 
			
		||||
            useResource: '{{ Table.useResource }}',
 | 
			
		||||
            useValues: '{{ Table.useTableRowRecord }}',
 | 
			
		||||
          },
 | 
			
		||||
          'x-component': 'Action.Modal',
 | 
			
		||||
          'x-component-props': {
 | 
			
		||||
            useOkAction: '{{ Table.useTableUpdateAction }}',
 | 
			
		||||
          },
 | 
			
		||||
          properties: {
 | 
			
		||||
            [uid()]: {
 | 
			
		||||
              type: 'void',
 | 
			
		||||
              'x-component': 'Grid',
 | 
			
		||||
              'x-component-props': {
 | 
			
		||||
                addNewComponent: 'AddNew.FormItem',
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    destroy: {
 | 
			
		||||
      type: 'void',
 | 
			
		||||
      title: '删除',
 | 
			
		||||
      'x-align': 'right',
 | 
			
		||||
      'x-decorator': 'AddNew.Displayed',
 | 
			
		||||
      'x-decorator-props': {
 | 
			
		||||
        displayName: 'destroy',
 | 
			
		||||
      },
 | 
			
		||||
      'x-action-type': 'destroy',
 | 
			
		||||
      'x-component': 'Action',
 | 
			
		||||
      'x-designable-bar': 'Action.DesignableBar',
 | 
			
		||||
      'x-component-props': {
 | 
			
		||||
        useAction: '{{ Table.useTableDestroyAction }}',
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
  };
 | 
			
		||||
  return actions[type];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function AddActionButton() {
 | 
			
		||||
  const [visible, setVisible] = useState(false);
 | 
			
		||||
  const displayed = useDisplayedMapContext();
 | 
			
		||||
  const { appendChild, remove } = useDesignable();
 | 
			
		||||
  const { schema, designable } = useDesignable();
 | 
			
		||||
  if (!designable) {
 | 
			
		||||
    return null;
 | 
			
		||||
  }
 | 
			
		||||
  return (
 | 
			
		||||
    <Dropdown
 | 
			
		||||
      trigger={['click']}
 | 
			
		||||
      visible={visible}
 | 
			
		||||
      onVisibleChange={setVisible}
 | 
			
		||||
      overlay={
 | 
			
		||||
        <Menu>
 | 
			
		||||
          <Menu.ItemGroup title={'操作展示'}>
 | 
			
		||||
            {[
 | 
			
		||||
              { title: '编辑', name: 'update' },
 | 
			
		||||
              { title: '删除', name: 'destroy' },
 | 
			
		||||
            ].map((item) => (
 | 
			
		||||
              <SwitchMenuItem
 | 
			
		||||
                key={item.name}
 | 
			
		||||
                checked={displayed.has(item.name)}
 | 
			
		||||
                title={item.title}
 | 
			
		||||
                onChange={async (checked) => {
 | 
			
		||||
                  if (!checked) {
 | 
			
		||||
                    const s = displayed.get(item.name) as Schema;
 | 
			
		||||
                    const path = getSchemaPath(s);
 | 
			
		||||
                    displayed.remove(item.name);
 | 
			
		||||
                    const removed = remove(path);
 | 
			
		||||
                    await removeSchema(removed);
 | 
			
		||||
                  } else {
 | 
			
		||||
                    const s = generateActionSchema(item.name);
 | 
			
		||||
                    const data = appendChild(s);
 | 
			
		||||
                    await createSchema(data);
 | 
			
		||||
                  }
 | 
			
		||||
                }}
 | 
			
		||||
              />
 | 
			
		||||
            ))}
 | 
			
		||||
          </Menu.ItemGroup>
 | 
			
		||||
          <Menu.Divider />
 | 
			
		||||
          <Menu.SubMenu title={'自定义'}>
 | 
			
		||||
            <Menu.Item style={{ minWidth: 120 }}>函数操作</Menu.Item>
 | 
			
		||||
            <Menu.Item>弹窗表单</Menu.Item>
 | 
			
		||||
            <Menu.Item>复杂弹窗</Menu.Item>
 | 
			
		||||
          </Menu.SubMenu>
 | 
			
		||||
        </Menu>
 | 
			
		||||
      }
 | 
			
		||||
    >
 | 
			
		||||
      <Button style={{ marginLeft: 8 }} type={'dashed'} icon={<PlusOutlined />}>
 | 
			
		||||
        配置操作
 | 
			
		||||
      </Button>
 | 
			
		||||
    </Dropdown>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function Actions(props: any) {
 | 
			
		||||
  const { align = 'left' } = props;
 | 
			
		||||
  const { schema, designable } = useDesignable();
 | 
			
		||||
  return (
 | 
			
		||||
    <Droppable
 | 
			
		||||
      id={`${schema.name}-${align}`}
 | 
			
		||||
      className={`action-bar-align-${align}`}
 | 
			
		||||
      data={{ align, path: getSchemaPath(schema) }}
 | 
			
		||||
    >
 | 
			
		||||
      <Space>
 | 
			
		||||
        {schema.mapProperties((s) => {
 | 
			
		||||
          const currentAlign = s['x-align'] || 'left';
 | 
			
		||||
          if (currentAlign !== align) {
 | 
			
		||||
            return null;
 | 
			
		||||
          }
 | 
			
		||||
          return (
 | 
			
		||||
            <SortableItem
 | 
			
		||||
              id={s.name}
 | 
			
		||||
              data={{
 | 
			
		||||
                align,
 | 
			
		||||
                draggable: true,
 | 
			
		||||
                title: s.title,
 | 
			
		||||
                path: getSchemaPath(s),
 | 
			
		||||
              }}
 | 
			
		||||
            >
 | 
			
		||||
              <RecursionField name={s.name} schema={s} />
 | 
			
		||||
            </SortableItem>
 | 
			
		||||
          );
 | 
			
		||||
        })}
 | 
			
		||||
      </Space>
 | 
			
		||||
    </Droppable>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
@ -420,3 +420,28 @@ export default () => {
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Action.Bar
 | 
			
		||||
 | 
			
		||||
```tsx
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import { SchemaRenderer } from '@nocobase/client';
 | 
			
		||||
 | 
			
		||||
const schema = {
 | 
			
		||||
  type: 'void',
 | 
			
		||||
  name: 'actionbar1',
 | 
			
		||||
  'x-component': 'Action.Bar',
 | 
			
		||||
  'x-designable-bar': 'Action.Bar.DesignableBar',
 | 
			
		||||
  'x-component-props': {
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default () => {
 | 
			
		||||
  return (
 | 
			
		||||
    <SchemaRenderer 
 | 
			
		||||
      schema={schema} 
 | 
			
		||||
    />
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
@ -11,23 +11,41 @@ import {
 | 
			
		||||
  useField,
 | 
			
		||||
  SchemaExpressionScopeContext,
 | 
			
		||||
} from '@formily/react';
 | 
			
		||||
import { Button, Dropdown, Menu, Popover, Space, Drawer, Modal } from 'antd';
 | 
			
		||||
import { Link, useHistory, LinkProps } from 'react-router-dom';
 | 
			
		||||
import { useDesignable, useDefaultAction, updateSchema } from '..';
 | 
			
		||||
import {
 | 
			
		||||
  Button,
 | 
			
		||||
  Dropdown,
 | 
			
		||||
  Menu,
 | 
			
		||||
  Popover,
 | 
			
		||||
  Space,
 | 
			
		||||
  Drawer,
 | 
			
		||||
  Modal,
 | 
			
		||||
  Select,
 | 
			
		||||
} from 'antd';
 | 
			
		||||
import { Link, useHistory, LinkProps, Switch } from 'react-router-dom';
 | 
			
		||||
import {
 | 
			
		||||
  useDesignable,
 | 
			
		||||
  useDefaultAction,
 | 
			
		||||
  updateSchema,
 | 
			
		||||
  removeSchema,
 | 
			
		||||
} from '..';
 | 
			
		||||
import './style.less';
 | 
			
		||||
import { uid } from '@formily/shared';
 | 
			
		||||
import cls from 'classnames';
 | 
			
		||||
import { MenuOutlined } from '@ant-design/icons';
 | 
			
		||||
import { FormLayout } from '@formily/antd';
 | 
			
		||||
import { FormDialog, FormLayout } from '@formily/antd';
 | 
			
		||||
import IconPicker from '../../components/icon-picker';
 | 
			
		||||
import {
 | 
			
		||||
  findPropertyByPath,
 | 
			
		||||
  getSchemaPath,
 | 
			
		||||
  SchemaField,
 | 
			
		||||
  useSchemaComponent,
 | 
			
		||||
} from '../../components/schema-renderer';
 | 
			
		||||
import { VisibleContext } from '../../context';
 | 
			
		||||
import { DndContext, DragOverlay } from '@dnd-kit/core';
 | 
			
		||||
import { createPortal } from 'react-dom';
 | 
			
		||||
import { ActionBar } from './ActionBar';
 | 
			
		||||
import { DragHandle } from '../../components/Sortable';
 | 
			
		||||
import { useDisplayedMapContext } from '../../constate';
 | 
			
		||||
 | 
			
		||||
export const ButtonComponentContext = createContext(null);
 | 
			
		||||
 | 
			
		||||
@ -90,6 +108,8 @@ Action.Modal = observer((props: any) => {
 | 
			
		||||
  const { run: runOk } = useOkAction();
 | 
			
		||||
  const { run: runCancel } = useCancelAction();
 | 
			
		||||
  const isFormDecorator = schema['x-decorator'] === 'Form';
 | 
			
		||||
  const field = useField();
 | 
			
		||||
  console.log('Action.Modal.field', field);
 | 
			
		||||
  return (
 | 
			
		||||
    <Modal
 | 
			
		||||
      title={schema.title}
 | 
			
		||||
@ -304,10 +324,11 @@ Action.Popover = observer((props) => {
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
Action.DesignableBar = (props: any) => {
 | 
			
		||||
  const field = useField();
 | 
			
		||||
  // const schema = useFieldSchema();
 | 
			
		||||
  const { schema, insertAfter, refresh } = useDesignable(props.path);
 | 
			
		||||
  const { schema, remove, refresh, insertAfter } = useDesignable();
 | 
			
		||||
  const [visible, setVisible] = useState(false);
 | 
			
		||||
  const isPopup = Object.keys(schema.properties || {}).length > 0;
 | 
			
		||||
  const displayed = useDisplayedMapContext();
 | 
			
		||||
  const field = useField();
 | 
			
		||||
  return (
 | 
			
		||||
    <div className={cls('designable-bar', { active: visible })}>
 | 
			
		||||
      <span
 | 
			
		||||
@ -316,6 +337,7 @@ Action.DesignableBar = (props: any) => {
 | 
			
		||||
        }}
 | 
			
		||||
        className={cls('designable-bar-actions', { active: visible })}
 | 
			
		||||
      >
 | 
			
		||||
        <DragHandle />
 | 
			
		||||
        <Dropdown
 | 
			
		||||
          trigger={['click']}
 | 
			
		||||
          visible={visible}
 | 
			
		||||
@ -325,25 +347,85 @@ Action.DesignableBar = (props: any) => {
 | 
			
		||||
          overlay={
 | 
			
		||||
            <Menu>
 | 
			
		||||
              <Menu.Item
 | 
			
		||||
                onClick={(e) => {
 | 
			
		||||
                  console.log('按钮文案被修改了', { schema });
 | 
			
		||||
                  schema.title = '按钮文案被修改了';
 | 
			
		||||
                  // field.setTitle('按钮文案被修改了');
 | 
			
		||||
                  // setVisible(false);
 | 
			
		||||
                onClick={async (e) => {
 | 
			
		||||
                  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();
 | 
			
		||||
                }}
 | 
			
		||||
              >
 | 
			
		||||
                点击修改按钮文案
 | 
			
		||||
                修改名称和图标
 | 
			
		||||
              </Menu.Item>
 | 
			
		||||
              <Menu.Item
 | 
			
		||||
                onClick={() => {
 | 
			
		||||
                  insertAfter({
 | 
			
		||||
                    name: uid(),
 | 
			
		||||
                    'x-component': 'Input',
 | 
			
		||||
                  });
 | 
			
		||||
              {isPopup && (
 | 
			
		||||
                <Menu.Item>
 | 
			
		||||
                  在{' '}
 | 
			
		||||
                  <Select
 | 
			
		||||
                    bordered={false}
 | 
			
		||||
                    size={'small'}
 | 
			
		||||
                    defaultValue={'Action.Modal'}
 | 
			
		||||
                    onChange={(value) => {
 | 
			
		||||
                      const s = Object.values(schema.properties).shift();
 | 
			
		||||
                      s['x-component'] = value;
 | 
			
		||||
                      refresh();
 | 
			
		||||
                      updateSchema(s);
 | 
			
		||||
                    }}
 | 
			
		||||
                  >
 | 
			
		||||
                insertAfter
 | 
			
		||||
                    <Select.Option value={'Action.Modal'}>对话框</Select.Option>
 | 
			
		||||
                    <Select.Option value={'Action.Drawer'}>抽屉</Select.Option>
 | 
			
		||||
                    <Select.Option value={'Action.Window'}>
 | 
			
		||||
                      浏览器窗口
 | 
			
		||||
                    </Select.Option>
 | 
			
		||||
                  </Select>{' '}
 | 
			
		||||
                  内打开
 | 
			
		||||
                </Menu.Item>
 | 
			
		||||
              )}
 | 
			
		||||
              <Menu.Divider />
 | 
			
		||||
              <Menu.Item
 | 
			
		||||
                onClick={async () => {
 | 
			
		||||
                  const displayName =
 | 
			
		||||
                    schema?.['x-decorator-props']?.['displayName'];
 | 
			
		||||
                  const data = remove();
 | 
			
		||||
                  await removeSchema(data);
 | 
			
		||||
                  if (displayName) {
 | 
			
		||||
                    displayed.remove(displayName);
 | 
			
		||||
                  }
 | 
			
		||||
                  setVisible(false);
 | 
			
		||||
                }}
 | 
			
		||||
              >
 | 
			
		||||
                移除
 | 
			
		||||
              </Menu.Item>
 | 
			
		||||
            </Menu>
 | 
			
		||||
          }
 | 
			
		||||
@ -354,3 +436,5 @@ Action.DesignableBar = (props: any) => {
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Action.Bar = ActionBar;
 | 
			
		||||
 | 
			
		||||
@ -225,7 +225,6 @@ function generateCardItemSchema(component) {
 | 
			
		||||
          properties: {
 | 
			
		||||
            [uid()]: {
 | 
			
		||||
              type: 'void',
 | 
			
		||||
              name: 'action1',
 | 
			
		||||
              'x-component': 'Action',
 | 
			
		||||
              'x-component-props': {
 | 
			
		||||
                icon: 'EllipsisOutlined',
 | 
			
		||||
@ -844,6 +843,12 @@ AddNew.PaneItem = observer((props: any) => {
 | 
			
		||||
                  },
 | 
			
		||||
                  'x-designable-bar': 'Form.DesignableBar',
 | 
			
		||||
                  properties: {
 | 
			
		||||
                    [uid()]: {
 | 
			
		||||
                      type: 'void',
 | 
			
		||||
                      'x-component': 'Action.Bar',
 | 
			
		||||
                      'x-designable-bar': 'Action.Bar.DesignableBar',
 | 
			
		||||
                      'x-component-props': {},
 | 
			
		||||
                    },
 | 
			
		||||
                    [uid()]: {
 | 
			
		||||
                      type: 'void',
 | 
			
		||||
                      'x-component': 'Grid',
 | 
			
		||||
 | 
			
		||||
@ -37,6 +37,18 @@ import {
 | 
			
		||||
  useDisplayedMapContext,
 | 
			
		||||
} from '../../constate';
 | 
			
		||||
import { useResource as useGeneralResource } from '../../hooks/useResource';
 | 
			
		||||
import { Resource } from '../../resource';
 | 
			
		||||
import { BaseResult } from '@ahooksjs/use-request/lib/types';
 | 
			
		||||
 | 
			
		||||
export interface FormReadPrettyContextProps {
 | 
			
		||||
  resource?: Resource;
 | 
			
		||||
  service?: BaseResult<any, any>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const FormContext = createContext<FormReadPrettyContextProps>({});
 | 
			
		||||
export const FormReadPrettyContext = createContext<FormReadPrettyContextProps>(
 | 
			
		||||
  {},
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
const FormMain = (props: any) => {
 | 
			
		||||
  const {
 | 
			
		||||
@ -50,9 +62,11 @@ const FormMain = (props: any) => {
 | 
			
		||||
      readPretty: schema['x-read-pretty'],
 | 
			
		||||
    });
 | 
			
		||||
  }, []);
 | 
			
		||||
  const { resource, run } = useResource({
 | 
			
		||||
  const { resource, run, service } = useResource({
 | 
			
		||||
    onSuccess: (initialValues: any) => {
 | 
			
		||||
      console.log('onSuccess', { initialValues });
 | 
			
		||||
      form.setInitialValues(initialValues);
 | 
			
		||||
      form.setValues(initialValues);
 | 
			
		||||
    },
 | 
			
		||||
  });
 | 
			
		||||
  const path = useSchemaPath();
 | 
			
		||||
@ -66,7 +80,7 @@ const FormMain = (props: any) => {
 | 
			
		||||
      console.log(displayed.map, 'displayed.map', collection?.name);
 | 
			
		||||
    }
 | 
			
		||||
  }, [displayed.map]);
 | 
			
		||||
  return (
 | 
			
		||||
  const content = (
 | 
			
		||||
    <FormProvider form={form}>
 | 
			
		||||
      {schema['x-decorator'] === 'Form' ? (
 | 
			
		||||
        <SchemaField
 | 
			
		||||
@ -119,6 +133,14 @@ const FormMain = (props: any) => {
 | 
			
		||||
      )}
 | 
			
		||||
    </FormProvider>
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  return schema['x-read-pretty'] ? (
 | 
			
		||||
    <FormReadPrettyContext.Provider value={{ resource, service }}>
 | 
			
		||||
      {content}
 | 
			
		||||
    </FormReadPrettyContext.Provider>
 | 
			
		||||
  ) : (
 | 
			
		||||
    <>{content}</>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const Form: any = observer((props: any) => {
 | 
			
		||||
 | 
			
		||||
@ -70,6 +70,8 @@ import { isValid } from '@formily/shared';
 | 
			
		||||
import { FormButtonGroup, FormDialog, FormLayout, Submit } from '@formily/antd';
 | 
			
		||||
import flatten from 'flat';
 | 
			
		||||
import IconPicker from '../../components/icon-picker';
 | 
			
		||||
import { FormReadPrettyContext } from '../form';
 | 
			
		||||
import { VisibleContext } from '../../context';
 | 
			
		||||
 | 
			
		||||
export interface ITableContext {
 | 
			
		||||
  props: any;
 | 
			
		||||
@ -153,6 +155,7 @@ const useTableUpdateAction = () => {
 | 
			
		||||
  } = useTable();
 | 
			
		||||
  const ctx = useContext(TableRowContext);
 | 
			
		||||
  const form = useForm();
 | 
			
		||||
  const { service: formService } = useContext(FormReadPrettyContext);
 | 
			
		||||
 | 
			
		||||
  return {
 | 
			
		||||
    async run() {
 | 
			
		||||
@ -160,7 +163,11 @@ const useTableUpdateAction = () => {
 | 
			
		||||
        await resource.save(form.values, {
 | 
			
		||||
          resourceKey: ctx.record[rowKey],
 | 
			
		||||
        });
 | 
			
		||||
        return service.refresh();
 | 
			
		||||
        if (formService) {
 | 
			
		||||
          await formService.refresh();
 | 
			
		||||
        }
 | 
			
		||||
        await service.refresh();
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      field.value[ctx.index] = form.values;
 | 
			
		||||
      // refresh();
 | 
			
		||||
@ -179,6 +186,7 @@ const useTableDestroyAction = () => {
 | 
			
		||||
    props: { refreshRequestOnChange, rowKey },
 | 
			
		||||
  } = useTable();
 | 
			
		||||
  const ctx = useContext(TableRowContext);
 | 
			
		||||
  const [, setVisible] = useContext(VisibleContext);
 | 
			
		||||
  return {
 | 
			
		||||
    async run() {
 | 
			
		||||
      if (refreshRequestOnChange) {
 | 
			
		||||
@ -190,6 +198,7 @@ const useTableDestroyAction = () => {
 | 
			
		||||
          [`${rowKey}.in`]: rowKeys,
 | 
			
		||||
        });
 | 
			
		||||
        setSelectedRowKeys([]);
 | 
			
		||||
        setVisible && setVisible(false);
 | 
			
		||||
        return service.refresh();
 | 
			
		||||
      }
 | 
			
		||||
      if (ctx) {
 | 
			
		||||
@ -873,7 +882,7 @@ function generateMenuActionSchema(type) {
 | 
			
		||||
      properties: {
 | 
			
		||||
        [uid()]: {
 | 
			
		||||
          type: 'void',
 | 
			
		||||
          title: '查看',
 | 
			
		||||
          title: '查看数据',
 | 
			
		||||
          'x-component': 'Action.Modal',
 | 
			
		||||
          'x-component-props': {
 | 
			
		||||
            bodyStyle: {
 | 
			
		||||
@ -2011,7 +2020,7 @@ Table.useResource = ({ onSuccess }) => {
 | 
			
		||||
    resourceName: collection.name,
 | 
			
		||||
    resourceKey: ctx.record[props.rowKey],
 | 
			
		||||
  });
 | 
			
		||||
  const { data, loading, run } = useRequest(
 | 
			
		||||
  const service = useRequest(
 | 
			
		||||
    (params?: any) => {
 | 
			
		||||
      console.log('Table.useResource', params);
 | 
			
		||||
      return resource.get(params);
 | 
			
		||||
@ -2022,7 +2031,7 @@ Table.useResource = ({ onSuccess }) => {
 | 
			
		||||
      manual: true,
 | 
			
		||||
    },
 | 
			
		||||
  );
 | 
			
		||||
  return { initialValues: data, loading, run, resource };
 | 
			
		||||
  return { resource, service, initialValues: service.data, ...service };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Table.useTableFilterAction = useTableFilterAction;
 | 
			
		||||
 | 
			
		||||
@ -69,6 +69,7 @@
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.ant-drawer-body,
 | 
			
		||||
.ant-card-body,
 | 
			
		||||
.ant-modal-body {
 | 
			
		||||
  .nb-tabs {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user