diff --git a/packages/app/src/components/pages/AdminLoader/Actions/index.tsx b/packages/app/src/components/pages/AdminLoader/Actions/index.tsx index 6e1d9cf62..315e5a69b 100644 --- a/packages/app/src/components/pages/AdminLoader/Actions/index.tsx +++ b/packages/app/src/components/pages/AdminLoader/Actions/index.tsx @@ -1,6 +1,6 @@ import React, { useState } from 'react'; import { Space, Button, Popconfirm, Popover } from 'antd'; -import { FilterOutlined, PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons'; +import { FilterOutlined, PlusOutlined, SelectOutlined, DeleteOutlined } from '@ant-design/icons'; import Drawer from '@/components/pages/AdminLoader/Drawer'; import View from '@/components/pages/AdminLoader/View'; import get from 'lodash/get'; @@ -8,7 +8,7 @@ import set from 'lodash/set'; export function Create(props) { const { size, onFinish, schema = {}, associatedKey, ...restProps } = props; - const { title, viewName } = schema; + const { title, viewName, transform } = schema; return ( <> ) diff --git a/packages/app/src/components/pages/AdminLoader/Drawer/index.tsx b/packages/app/src/components/pages/AdminLoader/Drawer/index.tsx index abc4eb535..e5551001e 100644 --- a/packages/app/src/components/pages/AdminLoader/Drawer/index.tsx +++ b/packages/app/src/components/pages/AdminLoader/Drawer/index.tsx @@ -3,7 +3,7 @@ import ReactDOM, { createPortal } from 'react-dom' import { createForm } from '@formily/core' // import { FormProvider } from '@formily/react' import { isNum, isStr, isBool, isFn } from '@formily/shared' -import { Drawer } from 'antd' +import { Modal, Drawer } from 'antd' import { DrawerProps } from 'antd/lib/drawer' import { useContext } from 'react' import { ConfigProvider } from 'antd' @@ -77,7 +77,7 @@ export function FormDrawer(title: any, content: any): IFormDrawer { width: '75%', ...props, onClose: (e: any) => { - props?.onClose?.(e) + props?.onClose?.(e); formDrawer.close() }, afterVisibleChange: (visible: boolean) => { @@ -88,25 +88,13 @@ export function FormDrawer(title: any, content: any): IFormDrawer { env.root = undefined }, } - const render = (visible = true, resolve?: () => any, reject?: () => any) => { - ReactDOM.render( - - - {createElement(content, { - resolve, - reject, - })} - - , - env.root - ) - } - document.body.appendChild(env.root) + const formDrawer = { open: (props: any) => { render( false, () => { + formDrawer.closeWithConfirm = false; formDrawer.close() }, () => { @@ -117,6 +105,7 @@ export function FormDrawer(title: any, content: any): IFormDrawer { render( true, () => { + formDrawer.closeWithConfirm = false; formDrawer.close() }, () => { @@ -127,14 +116,53 @@ export function FormDrawer(title: any, content: any): IFormDrawer { }, close: () => { if (!env.root) return - const els = document.querySelectorAll('.env-root-push'); - if (els.length) { - const last = els[els.length-1]; - last.className = 'env-root'; + if (formDrawer.closeWithConfirm) { + Modal.confirm({ + title: '表单内容发生变化,确定不保存吗?', + okText: '确定', + cancelText: '取消', + onOk() { + formDrawer.closeWithConfirm = false; + const els = document.querySelectorAll('.env-root-push'); + if (els.length) { + const last = els[els.length-1]; + last.className = 'env-root'; + } + render(false) + }, + }); + } else { + const els = document.querySelectorAll('.env-root-push'); + if (els.length) { + const last = els[els.length-1]; + last.className = 'env-root'; + } + render(false) } - render(false) }, + closeWithConfirm: false, } + + const closeWithConfirm = (bool) => { + formDrawer.closeWithConfirm = bool; + } + + const render = (visible = true, resolve?: () => any, reject?: () => any) => { + ReactDOM.render( + + + {createElement(content, { + resolve, + reject, + closeWithConfirm, + })} + + , + env.root + ) + } + document.body.appendChild(env.root) + return formDrawer } diff --git a/packages/app/src/components/pages/AdminLoader/View/Form.tsx b/packages/app/src/components/pages/AdminLoader/View/Form.tsx index 94fd8615c..19d7cd7fe 100644 --- a/packages/app/src/components/pages/AdminLoader/View/Form.tsx +++ b/packages/app/src/components/pages/AdminLoader/View/Form.tsx @@ -23,7 +23,8 @@ import cloneDeep from 'lodash/cloneDeep' import { Spin } from '@nocobase/client'; import { markdown } from '@/components/views/Field'; -export function fields2properties(fields = []) { +export function fields2properties(fields = [], options: any = {}) { + const { mode } = options; const properties = {}; fields.forEach(field => { const data = { @@ -31,6 +32,9 @@ export function fields2properties(fields = []) { title: field.title, required: field.required, }; + if (field.createOnly && mode !== 'create') { + set(data, 'x-component-props.disabled', true); + } const linkages = field.linkages; delete field.linkages; set(data, 'x-component-props.schema', cloneDeep(field)); @@ -80,13 +84,13 @@ export function fields2properties(fields = []) { data.description =
; } }); - console.log({properties}); + console.log({properties, options}); return properties; } const actions = createFormActions(); export function Form(props: any) { - const { onReset, __parent, noRequest = false, onFinish, onDraft, resolve, data: record = {}, associatedKey, schema = {} } = props; + const { onValueChange, onReset, __parent, noRequest = false, onFinish, onDraft, resolve, data: record = {}, associatedKey, schema = {} } = props; console.log({ noRequest, record, associatedKey, __parent }); const { statusable, resourceName, rowKey = 'id', fields = [], appends = [], associationField = {} } = schema; @@ -125,11 +129,15 @@ export function Form(props: any) { // actions={actions} schema={{ type: 'object', - properties: fields2properties(fields), + properties: fields2properties(fields, { mode: !!Object.keys(data).length ? null : 'create' }), }} onReset={async () => { onReset && await onReset(); }} + onChange={(values) => { + console.log('onValueChange') + onValueChange && onValueChange(values) + }} onSubmit={async (values) => { console.log({status}); if (!noRequest) { diff --git a/packages/app/src/components/pages/AdminLoader/View/SubTable.tsx b/packages/app/src/components/pages/AdminLoader/View/SubTable.tsx index 52ffbc89e..e3d4ca19c 100644 --- a/packages/app/src/components/pages/AdminLoader/View/SubTable.tsx +++ b/packages/app/src/components/pages/AdminLoader/View/SubTable.tsx @@ -5,7 +5,7 @@ import { Spin } from '@nocobase/client'; import { useRequest, useLocation } from 'umi'; import api from '@/api-client'; import { Actions } from '../Actions'; -import { Table as AntdTable, Card, Pagination, Button, Tabs, Descriptions, Tooltip } from 'antd'; +import { Modal, Table as AntdTable, Card, Pagination, Button, Tabs, Descriptions, Tooltip } from 'antd'; import { LoadingOutlined } from '@ant-design/icons'; import { components, fields2columns } from '@/components/views/SortableTable'; import ReactDragListView from 'react-drag-listview'; @@ -19,7 +19,7 @@ import { Form } from './Form'; import { View } from './'; export function Details(props) { - const { onReset, __parent, noRequest, associatedKey, resourceName, onFinish, onDataChange, data, items = [], resolve } = props; + const { onValueChange, onReset, __parent, noRequest, associatedKey, resourceName, onFinish, onDataChange, data, items = [], resolve } = props; if (!items || items.length === 0) { return null; } @@ -46,6 +46,7 @@ export function Details(props) { } return ( { return !associatedKey || type === 'virtual' || type === 'json' ? Promise.resolve({ data: (props.data||[]).map(item => { @@ -231,7 +231,7 @@ export function SubTable(props: any) { rowKey={rowKey} dataSource={dataSource} size={size} - columns={fields2columns(cloneFields)} + columns={fields2columns(cloneFields, { mutate, dataSource, onChange })} pagination={false} onChange={(pagination, filters, sorter, extra) => { @@ -253,7 +253,7 @@ export function SubTable(props: any) { bodyStyle: { // padding: 0, }, - content: ({resolve}) => ( + content: ({resolve, closeWithConfirm}) => (
{ + }} + onValueChange={() => { + closeWithConfirm && closeWithConfirm(true); }} noRequest={true} data={data} diff --git a/packages/app/src/components/pages/AdminLoader/View/Table.tsx b/packages/app/src/components/pages/AdminLoader/View/Table.tsx index 7b62837b1..2314b4c42 100644 --- a/packages/app/src/components/pages/AdminLoader/View/Table.tsx +++ b/packages/app/src/components/pages/AdminLoader/View/Table.tsx @@ -5,7 +5,7 @@ import { Spin } from '@nocobase/client'; import { useRequest, useHistory } from 'umi'; import api from '@/api-client'; import { Actions } from '../Actions'; -import { PageHeader, Table as AntdTable, Card, Pagination, Button, Tabs, Descriptions, Tooltip } from 'antd'; +import { Modal, PageHeader, Table as AntdTable, Card, Pagination, Button, Tabs, Descriptions, Tooltip } from 'antd'; import { LoadingOutlined } from '@ant-design/icons'; import { components, fields2columns } from '@/components/views/SortableTable'; import ReactDragListView from 'react-drag-listview'; @@ -21,7 +21,7 @@ import pathToRegexp from 'path-to-regexp' export const icon = ; export function Details(props) { - const { __parent, associatedKey, resourceName, onFinish, onReset, onDataChange, data, items = [], resolve } = props; + const { __parent, associatedKey, resourceName, onFinish, onReset, onDataChange, data, items = [], resolve, onValueChange } = props; if (!items || items.length === 0) { return null; } @@ -47,7 +47,10 @@ export function Details(props) { viewName = `${resourceName}.${view.name}`; } return ( - + ); })}
@@ -403,7 +406,7 @@ export function Table(props: any) { bodyStyle: { // padding: 0, }, - content: ({resolve}) => ( + content: ({resolve, closeWithConfirm}) => (
{ + closeWithConfirm && closeWithConfirm(true); + }} onDraft={async () => { await refresh(); resolve(); diff --git a/packages/app/src/components/views/Field/index.tsx b/packages/app/src/components/views/Field/index.tsx index e91a11ef3..efd229599 100644 --- a/packages/app/src/components/views/Field/index.tsx +++ b/packages/app/src/components/views/Field/index.tsx @@ -12,6 +12,7 @@ import './style.less'; import { getImageByUrl, testUrl } from '@/components/form.fields'; import { CheckOutlined, CloseOutlined } from '@ant-design/icons'; import marked from 'marked'; +import set from 'lodash/set'; import Lightbox from 'react-image-lightbox'; import 'react-image-lightbox/style.css'; import api from '@/api-client'; @@ -231,22 +232,22 @@ export function SubTableField(props: any) { } export function LinkToField(props: any) { - const { data, schema, value } = props; + const { ctx, data, schema, value } = props; if (!value) { return null; } - console.log({props}); + // console.log({props}); const values = Array.isArray(value) ? value : [value]; + const isArr = Array.isArray(value); return (
- {values.map(item => )} + {values.map((item, itemIndex) => )}
); } export function LinkToFieldLink(props) { - const { parent, schema, schema: { title, labelField, viewName, name, target, collection_name } } = props; - const [visible, setVisible] = useState(false); + const { isArr, itemIndex, ctx, parent, schema, schema: { title, labelField, viewName, name, target, collection_name } } = props; const [data, setData] = useState(props.data||{}); return ( @@ -255,14 +256,25 @@ export function LinkToFieldLink(props) { // setVisible(true); Drawer.open({ title: data[labelField], - content: ({resolve}) => { - console.log({parent, data, props, schema}); + content: ({resolve, closeWithConfirm}) => { + // console.log({ctx, parent, data, props, schema}); + const { index, mutate, dataSource, onChange } = ctx; return (
- { + { + closeWithConfirm && closeWithConfirm(true); + }} + noRequest={!!onChange} onFinish={(values) => { + let items = [...dataSource]; + const parentData = {...parent}; + set(parentData, isArr ? [name, itemIndex] : [name], values); + items[index] = parentData; setData(values); + mutate(items); + onChange(items); resolve(); - console.log({data, values}); + // console.log({values, parentData, data, items}); }} associatedKey={parent.id} data={data} viewName={viewName || `${collection_name}.${name}.descriptions`}/>
); diff --git a/packages/app/src/components/views/SortableTable/index.tsx b/packages/app/src/components/views/SortableTable/index.tsx index f09a8c666..ac027fcde 100644 --- a/packages/app/src/components/views/SortableTable/index.tsx +++ b/packages/app/src/components/views/SortableTable/index.tsx @@ -66,7 +66,7 @@ export function fields2columns(fields = [], ctx: any = {}) { if (!field.dataIndex) { field.dataIndex = field.name.split('.'); } - field.render = (value, record) => field.interface === 'sort' ? : ; + field.render = (value, record, index) => field.interface === 'sort' ? : ; field.className = `${field.className||''} noco-field-${field.interface}`; if (field.editable && field.interface === 'boolean') { field.title = (