@jswork/react-ant-resource-form 1.0.29 → 1.0.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.cjs.js +1 -1
- package/dist/main.cjs.js.map +1 -1
- package/dist/main.d.mts +10 -0
- package/dist/main.d.ts +10 -0
- package/dist/main.esm.js +1 -1
- package/dist/main.esm.js.map +1 -1
- package/package.json +2 -2
- package/src/index.tsx +72 -47
package/dist/main.cjs.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }var w=Object.defineProperty;var
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }var w=Object.defineProperty;var R=Object.getOwnPropertySymbols;var I=Object.prototype.hasOwnProperty,x=Object.prototype.propertyIsEnumerable;var E=(a,i,e)=>i in a?w(a,i,{enumerable:!0,configurable:!0,writable:!0,value:e}):a[i]=e,d=(a,i)=>{for(var e in i||(i={}))I.call(i,e)&&E(a,e,i[e]);if(R)for(var e of R(i))x.call(i,e)&&E(a,e,i[e]);return a};var h=(a,i)=>w(a,"name",{value:i,configurable:!0});var y=(a,i)=>{var e={};for(var t in a)I.call(a,t)&&i.indexOf(t)<0&&(e[t]=a[t]);if(a!=null&&R)for(var t of R(a))i.indexOf(t)<0&&x.call(a,t)&&(e[t]=a[t]);return e};var u=(a,i,e)=>E(a,typeof i!="symbol"?i+"":i,e);var _classnames = require('classnames'); var _classnames2 = _interopRequireDefault(_classnames);var _react = require('react'); var _react2 = _interopRequireDefault(_react);var _antd = require('antd');var _reactantformschema = require('@jswork/react-ant-form-schema'); var _reactantformschema2 = _interopRequireDefault(_reactantformschema);var _icons = require('@ant-design/icons');var A={"zh-CN":{create:"\u521B\u5EFA",update:"\u4FDD\u5B58",create_title:"\u521B\u5EFA",update_title:"\u66F4\u65B0",create_success:"\u521B\u5EFA\u6210\u529F",update_success:"\u66F4\u65B0\u6210\u529F",submit:"\u63D0\u4EA4",back:"\u8FD4\u56DE",no_change:"\u6CA1\u6709\u4FEE\u6539"},"en-US":{create:"Create",update:"Save",create_title:"Create",update_title:"Update",create_success:"Create success",update_success:"Update success",submit:"Submit",back:"Back",no_change:"No change"}};var _next = require('@jswork/next'); var _next2 = _interopRequireDefault(_next);require('@jswork/next-compact-object');var _reactrouterdom = require('react-router-dom');var _fastdeepequal = require('fast-deep-equal'); var _fastdeepequal2 = _interopRequireDefault(_fastdeepequal);var _fromentries = require('fromentries'); var _fromentries2 = _interopRequireDefault(_fromentries);var F="react-ant-resource-form",J=h((a,i)=>(_next2.default.forIn(a,e=>{i.includes(e)||delete a[e]}),a),"retainKeys"),f,N=(f=class extends _react.Component{constructor(e){var t;super(e);u(this,"formRef",_react2.default.createRef());u(this,"_isMounted",!1);u(this,"_initialValues",null);u(this,"handleBack",h(()=>{history.back()},"handleBack"));u(this,"setInitialValues",h(e=>{var t;this._initialValues=e||((t=this.formInstance)==null?void 0:t.getFieldsValue())||{}},"setInitialValues"));u(this,"handleFinish",h(e=>{if(!this.canSave){_antd.message.info(this.t("no_change"));return}this.isEdit?this.onResourceUpdate(e):this.onResourceCreate(e)},"handleFinish"));u(this,"onResourceUpdate",h(e=>{let{params:t,name:s,submitGuard:n,onMutate:r}=this.props,l=d(d({id:t.id},e),t),c=this.handleStateRequest({stage:"update",payload:l}),p={name:s,payload:c,isEdit:!0,values:e,params:t},g={name:s,payload:c,isEdit:!0,values:e};n==null||n(p).then(()=>{_next2.default.$api[`${s}_update`](c).then(m=>{_antd.message.success(this.t("update_success")),this.handleStateResponse({stage:"update",data:m}),r==null||r(g)}).finally(()=>{this.setState({loading:!1}),this.setInitialValues(),this.handleValuesChange(null,this._initialValues)})})},"onResourceUpdate"));u(this,"onResourceCreate",h(e=>{let{params:t,name:s,submitGuard:n,onMutate:r}=this.props,l=d(d({},e),t),c=this.handleStateRequest({stage:"create",payload:l}),p={name:s,payload:c,isEdit:!1,values:e,params:t},g={name:s,payload:c,isEdit:!1,values:e};n==null||n(p).then(()=>{_next2.default.$api[`${s}_create`](c).then(m=>{var S;_antd.message.success(this.t("create_success")),this.handleStateResponse({stage:"create",data:m}),(S=this.formInstance)==null||S.resetFields(),r==null||r(g),history.back()}).finally(()=>this.setState({loading:!1}))})},"onResourceCreate"));u(this,"handleKeydown",h(e=>{var n;let{disableHotkeySave:t}=this.props;(e.ctrlKey||e.metaKey)&&(e.key==="s"||e.key==="S")&&(e.preventDefault(),t||(n=this.formInstance)==null||n.submit())},"handleKeydown"));u(this,"handleValuesChange",h((e,t)=>{this.setState({touched:!_fastdeepequal2.default.call(void 0, this._initialValues,t)})},"handleValuesChange"));this.state={loading:e.loading,touched:!1},this.handleStateRequest=this.handleStateRequest.bind(this),this.handleStateResponse=this.handleStateResponse.bind(this),this.initDetailIfNeeded=this.initDetailIfNeeded.bind(this),(t=e.onInit)==null||t.call(e,this)}get isEdit(){let{params:e}=this.props;return!!(e!=null&&e.id)}get canSave(){let{touched:e,loading:t}=this.state;return this.isEdit?e&&!t:!t}get titleView(){let{title:e}=this.props,t=e||(this.isEdit?this.t("update_title"):this.t("create_title"));return _react2.default.createElement(_antd.Space,null,t,_react2.default.createElement("span",null,this.touchedView))}get touchedView(){return this.isEdit&&this.state.touched?_react2.default.createElement("em",{style:{color:"#f60"}},_react2.default.createElement(_icons.DiffOutlined,null)):null}get extraView(){let{extra:e,backText:t,backProps:s}=this.props;return e||_react2.default.createElement(_antd.Button,d({size:"small",icon:_react2.default.createElement(_icons.ArrowLeftOutlined,null),onClick:this.handleBack},s),t||this.t("back"))}get childrenView(){let{okText:e,backText:t,okProps:s,backProps:n,children:r}=this.props,l=e||(this.isEdit?this.t("update"):this.t("create"));return r||_react2.default.createElement(_antd.Space,null,_react2.default.createElement(_antd.Button,d({disabled:!this.canSave,htmlType:"submit",type:"primary",icon:_react2.default.createElement(_icons.SaveOutlined,null)},s),l||this.t("submit")),_react2.default.createElement(_antd.Button,d({icon:_react2.default.createElement(_icons.ArrowLeftOutlined,null),onClick:this.handleBack},n),t||this.t("back")))}get formInstance(){var e;return(e=this.formRef)==null?void 0:e.current}t(e){let{lang:t}=this.props;return A[t][e]}handleStateRequest(e){var t,s;return this.setState({loading:!0}),((s=(t=this.props).transformRequest)==null?void 0:s.call(t,e))||e.payload}handleStateResponse(e){var s,n,r,l;let{name:t}=this.props;return this.setState({loading:!1}),(n=(s=_next2.default.$event)==null?void 0:s.emit)==null||n.call(s,`${t}:refetch`),((l=(r=this.props).transformResponse)==null?void 0:l.call(r,e))||e.data}componentDidMount(){this._isMounted=!0,window.addEventListener("keydown",this.handleKeydown),this.initDetailIfNeeded()}componentDidUpdate(e){var n,r;let t=(n=e.params)==null?void 0:n.id,s=(r=this.props.params)==null?void 0:r.id;t!==s&&this.initDetailIfNeeded(),e.loading!==this.props.loading&&this.setState({loading:this.props.loading})}componentWillUnmount(){window.removeEventListener("keydown",this.handleKeydown),this._isMounted=!1}initDetailIfNeeded(){let{params:e,name:t,initGuard:s}=this.props,n=`${t}_show`;if(this.isEdit){let r={id:e.id},l=this.handleStateRequest({stage:"show",payload:r}),c={name:t,payload:l,isEdit:!0,params:e};s==null||s(c).then(()=>{_next2.default.$api[n](l).then(p=>{var m,S;if(!this._isMounted)return;let g=this.handleStateResponse({stage:"show",data:p});(S=(m=this.formInstance)==null?void 0:m.setFieldsValue)==null||S.call(m,g)}).finally(()=>{this.setState({loading:!1}),this.setInitialValues()})})}else{let r={name:t,payload:null,isEdit:!1,params:e};s==null||s(r).then(()=>{this.setInitialValues(),this.setState({loading:!1})})}}render(){let V=this.props,{className:e,name:t,meta:s,children:n,lang:r,title:l,extra:c,size:p,okText:g,backText:m,okProps:S,backProps:X,classNames:q,params:Y,transformRequest:Z,transformResponse:j,disableHotkeySave:ee,blocker:D,onInit:te,initGuard:se,submitGuard:ae,loading:ie}=V,L=y(V,["className","name","meta","children","lang","title","extra","size","okText","backText","okProps","backProps","classNames","params","transformRequest","transformResponse","disableHotkeySave","blocker","onInit","initGuard","submitGuard","loading"]);return _react2.default.createElement(_antd.Card,{title:this.titleView,extra:this.extraView,size:p,classNames:q,"data-component":F,"data-blocker":D,className:_classnames2.default.call(void 0, F,e)},_react2.default.createElement(_antd.Spin,{spinning:this.state.loading},_react2.default.createElement(_reactantformschema2.default,d({meta:s,ref:this.formRef,onValuesChange:this.handleValuesChange,onFinish:this.handleFinish},L),this.childrenView)))}},h(f,"ReactAntResourceForm"),u(f,"defaultProps",{lang:"zh-CN",disableHotkeySave:!1,blocker:!1,initGuard:h(()=>Promise.resolve(),"initGuard"),submitGuard:h(()=>Promise.resolve(),"submitGuard")}),f),Q= exports.ReactAntResourceFormFc =h(a=>{let c=a,{params:i,allowFields:e}=c,t=y(c,["params","allowFields"]),s=_reactrouterdom.useParams.call(void 0, ),[n]=_reactrouterdom.useSearchParams.call(void 0, ),r=_fromentries2.default.call(void 0, n),l=_next2.default.compactObject(d(d(d({},r),s),i));return e!=null&&e.length&&e.length>0&&J(l,e),_react2.default.createElement(N,d({params:l},t))},"ReactAntResourceFormFc"),P=N;var ye=P;exports.ReactAntResourceFormFc = Q; exports.default = ye;
|
|
2
2
|
//# sourceMappingURL=main.cjs.js.map
|
package/dist/main.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/ap7/github/react-ant-resource-form/packages/lib/dist/main.cjs.js","../src/index.tsx","../src/locales.ts"],"names":["API_FORM_LOCALES","create","update","create_title","update_title","create_success","update_success","submit","back","no_change","CLASS_NAME","retainKeys","__name","obj","keys","nx","forIn","key","includes","_a","ReactAntResourceForm","Component","props","formRef","React","createRef","_isMounted","_initialValues","handleBack","history","setInitialValues","values","formInstance","getFieldsValue","handleFinish","params","name","submitGuard","resourceEdit"],"mappings":"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","file":"/Users/ap7/github/react-ant-resource-form/packages/lib/dist/main.cjs.js","sourcesContent":[null,"// import noop from '@jswork/noop';\nimport cx from 'classnames';\nimport React, { Component, FC } from 'react';\nimport type { FormInstance } from 'antd';\nimport { Button, ButtonProps, Card, CardProps, message, Space, Spin } from 'antd';\nimport ReactAntdFormSchema, { ReactAntdFormSchemaProps } from '@jswork/react-ant-form-schema';\nimport { ArrowLeftOutlined, DiffOutlined, SaveOutlined } from '@ant-design/icons';\nimport { API_FORM_LOCALES } from './locales';\nimport nx from '@jswork/next';\nimport '@jswork/next-compact-object';\nimport { useParams, useSearchParams } from 'react-router-dom';\nimport deepEqual from 'fast-deep-equal';\nimport fromEntries from 'fromentries';\n\ndeclare global {\n interface NxStatic {\n $api: Record<string, any>;\n $event: any;\n }\n}\n\ntype StagePayload = {\n stage: 'show' | 'create' | 'update';\n payload: any;\n};\n\ntype StageData = {\n stage: 'show' | 'create' | 'update';\n data: any;\n};\n\ntype InitGuardArgs = {\n name?: string;\n params?: Record<string, any>;\n payload: any;\n isEdit: boolean;\n};\n\ntype SubmitGuardArgs = {\n name?: string;\n params?: Record<string, any>;\n payload: any;\n isEdit: boolean;\n values: any;\n};\n\nexport type ReactAntResourceFormProps = {\n lang?: string;\n loading?: boolean;\n okText?: string;\n backText?: string;\n params?: Record<string, any>;\n blocker?: boolean;\n disableHotkeySave?: boolean;\n initGuard?: (args: InitGuardArgs) => Promise<void>;\n submitGuard?: (args: SubmitGuardArgs) => Promise<void>;\n transformRequest?: (payload: StagePayload) => any;\n transformResponse?: (res: StageData) => any;\n okProps?: ButtonProps;\n backProps?: ButtonProps;\n classNames?: CardProps['classNames'];\n size?: CardProps['size'];\n extra?: CardProps['extra'];\n title?: CardProps['title'];\n onInit?: (ctx: ReactAntResourceForm) => void;\n} & ReactAntdFormSchemaProps;\n\ntype IState = {\n loading: boolean;\n touched: boolean;\n};\n\nconst CLASS_NAME = 'react-ant-resource-form';\n\nconst retainKeys = (obj: Record<string, any>, keys: string[]) => {\n nx.forIn(obj, (key) => {\n if (!keys.includes(key)) {\n delete obj[key];\n }\n });\n return obj;\n};\n\n/**\n * 当前 card loading 不要直接使用,因为这个 loading 会导致 Card 里的 formRef 被设置成 null\n * 这个情况仅在 class component 里才会出现,function component 里不会:\n * 报错示例:\n *\n * this.formRef?: null\n * index.tsx:229 this.formRef?: {getFieldValue: ƒ, getFieldsValue: ƒ, getFieldError: ƒ, getFieldWarning: ƒ, getFieldsError: ƒ, …}\n * index.tsx:229 this.formRef?: null\n *\n * initGuard | submitGuard:\n * https://chat.qwen.ai/c/60329863-0e5e-47f9-a075-a65ad30940cc\n */\n\nclass ReactAntResourceForm extends Component<ReactAntResourceFormProps, IState> {\n public static defaultProps = {\n lang: 'zh-CN',\n disableHotkeySave: false,\n blocker: false,\n initGuard: () => Promise.resolve(),\n submitGuard: () => Promise.resolve(),\n };\n\n private formRef = React.createRef<FormInstance>(); // 注意类型\n private _isMounted = false;\n private _initialValues = null;\n\n get isEdit() {\n const { params } = this.props;\n return Boolean(params?.id);\n }\n\n get canSave() {\n const { touched, loading } = this.state;\n if (!this.isEdit) return !loading;\n return touched && !loading;\n }\n\n get titleView() {\n const { title } = this.props;\n const _title = title || (this.isEdit ? this.t('update_title') : this.t('create_title'));\n return (\n <Space>\n {_title}\n <span>{this.touchedView}</span>\n </Space>\n );\n }\n\n get touchedView() {\n if (!this.isEdit) return null;\n return this.state.touched ? (\n <em style={{ color: '#f60' }}>\n <DiffOutlined />\n </em>\n ) : null;\n }\n\n get extraView() {\n const { extra, backText, backProps } = this.props;\n if (extra) return extra;\n return (\n <Button size=\"small\" icon={<ArrowLeftOutlined />} onClick={this.handleBack} {...backProps}>\n {backText || this.t('back')}\n </Button>\n );\n }\n\n get childrenView() {\n const { okText, backText, okProps, backProps, children } = this.props;\n const _okText = okText || (this.isEdit ? this.t('update') : this.t('create'));\n if (children) return children;\n\n return (\n <Space>\n <Button\n disabled={!this.canSave}\n htmlType=\"submit\"\n type=\"primary\"\n icon={<SaveOutlined />}\n {...okProps}>\n {_okText || this.t('submit')}\n </Button>\n <Button icon={<ArrowLeftOutlined />} onClick={this.handleBack} {...backProps}>\n {backText || this.t('back')}\n </Button>\n </Space>\n );\n }\n\n get formInstance() {\n return this.formRef?.current;\n }\n\n constructor(props: ReactAntResourceFormProps) {\n super(props);\n this.state = {\n loading: props.loading!,\n touched: false,\n };\n\n this.handleStateRequest = this.handleStateRequest.bind(this);\n this.handleStateResponse = this.handleStateResponse.bind(this);\n this.initDetailIfNeeded = this.initDetailIfNeeded.bind(this);\n\n props.onInit?.(this);\n }\n\n private t(key: string) {\n const { lang } = this.props;\n return API_FORM_LOCALES[lang!][key];\n }\n\n private handleBack = () => {\n history.back();\n };\n\n private setInitialValues = (values?: any) => {\n this._initialValues = values || this.formInstance?.getFieldsValue() || {};\n };\n\n handleStateRequest(stagePayload: StagePayload) {\n this.setState({ loading: true });\n return this.props.transformRequest?.(stagePayload) || stagePayload.payload;\n }\n\n handleStateResponse(res: StageData) {\n const { name } = this.props;\n this.setState({ loading: false });\n nx.$event?.emit?.(`${name}:refetch`);\n return this.props.transformResponse?.(res) || res.data;\n }\n\n handleFinish = (values: any) => {\n const { params, name, submitGuard } = this.props;\n const resourceEdit = `${name}_update`;\n const resourceCreate = `${name}_create`;\n\n if (!this.canSave) {\n void message.info(this.t('no_change'));\n return;\n }\n\n if (this.isEdit) {\n const payload = { id: params!.id, ...values, ...params };\n const _payload = this.handleStateRequest({ stage: 'update', payload });\n const submitGuardArgs: SubmitGuardArgs = {\n name,\n payload: _payload,\n isEdit: true,\n values,\n params,\n };\n\n submitGuard?.(submitGuardArgs).then(() => {\n nx.$api[resourceEdit](_payload)\n .then((res: any) => {\n void message.success(this.t('update_success'));\n this.handleStateResponse({ stage: 'update', data: res });\n })\n .finally(() => {\n this.setState({ loading: false });\n this.setInitialValues();\n this.handleValuesChange(null, this._initialValues);\n });\n });\n } else {\n const payload = { ...values, ...params };\n const _payload = this.handleStateRequest({ stage: 'create', payload });\n const submitGuardArgs: SubmitGuardArgs = {\n name,\n payload: _payload,\n isEdit: false,\n values,\n params,\n };\n\n submitGuard?.(submitGuardArgs).then(() => {\n nx.$api[resourceCreate](_payload)\n .then((res: any) => {\n void message.success(this.t('create_success'));\n this.handleStateResponse({ stage: 'create', data: res });\n this.formInstance?.resetFields();\n history.back();\n })\n .finally(() => this.setState({ loading: false }));\n });\n }\n };\n\n // hotkey save handler (replaces useKeyboardSave hook)\n handleKeydown = (e: KeyboardEvent) => {\n const { disableHotkeySave } = this.props;\n const isSave = (e.ctrlKey || e.metaKey) && (e.key === 's' || e.key === 'S');\n if (isSave) {\n e.preventDefault();\n if (!disableHotkeySave) {\n this.formInstance?.submit();\n }\n }\n };\n\n handleValuesChange = (_: any, allValues: any) => {\n this.setState({\n touched: !deepEqual(this._initialValues, allValues),\n });\n };\n\n componentDidMount() {\n this._isMounted = true;\n // attach hotkey listener\n window.addEventListener('keydown', this.handleKeydown);\n // initialize detail if editing\n this.initDetailIfNeeded();\n }\n\n componentDidUpdate(prevProps: ReactAntResourceFormProps) {\n const prevId = prevProps.params?.id;\n const curId = this.props.params?.id;\n // re-init when id changed or from create -> edit\n if (prevId !== curId) {\n this.initDetailIfNeeded();\n }\n\n // loading update\n if (prevProps.loading !== this.props.loading) {\n this.setState({ loading: this.props.loading! });\n }\n }\n\n componentWillUnmount() {\n window.removeEventListener('keydown', this.handleKeydown);\n this._isMounted = false;\n }\n\n initDetailIfNeeded() {\n const { params, name, initGuard } = this.props;\n const resourceShow = `${name}_show`;\n\n if (this.isEdit) {\n const payload = { id: params!.id };\n const _payload = this.handleStateRequest({ stage: 'show', payload });\n const initGuardArgs: InitGuardArgs = {\n name,\n payload: _payload,\n isEdit: true,\n params,\n };\n initGuard?.(initGuardArgs).then(() => {\n nx.$api[resourceShow](_payload)\n .then((res: any) => {\n if (!this._isMounted) return; // 👈 关键:防止操作已卸载组件\n const data = this.handleStateResponse({ stage: 'show', data: res });\n this.formInstance?.setFieldsValue?.(data);\n })\n .finally(() => {\n this.setState({ loading: false });\n this.setInitialValues();\n });\n });\n } else {\n const initGuardArgs: InitGuardArgs = {\n name,\n payload: null,\n isEdit: false,\n params,\n };\n initGuard?.(initGuardArgs).then(() => {\n this.setInitialValues();\n this.setState({ loading: false });\n });\n }\n }\n\n render() {\n const {\n className,\n name,\n meta,\n children,\n lang,\n title,\n extra,\n size,\n okText,\n backText,\n okProps,\n backProps,\n classNames,\n params,\n transformRequest,\n transformResponse,\n disableHotkeySave,\n blocker,\n onInit,\n initGuard,\n submitGuard,\n loading,\n ...rest\n } = this.props;\n\n return (\n <Card\n title={this.titleView}\n extra={this.extraView}\n size={size}\n classNames={classNames}\n data-component={CLASS_NAME}\n data-blocker={blocker}\n className={cx(CLASS_NAME, className)}>\n <Spin spinning={this.state.loading}>\n <ReactAntdFormSchema\n meta={meta}\n ref={this.formRef}\n onValuesChange={this.handleValuesChange}\n onFinish={this.handleFinish}\n {...rest}>\n {this.childrenView}\n </ReactAntdFormSchema>\n </Spin>\n </Card>\n );\n }\n}\n\nexport type ReactAntResourceFormFcProps = ReactAntResourceFormProps & {\n allowFields?: string[];\n}\n\nconst ReactAntResourceFormFc: FC<ReactAntResourceFormFcProps> = (props) => {\n const { params: overrideParams, allowFields, ...rest } = props;\n const params = useParams();\n const [searchParams] = useSearchParams();\n const _searchParams = fromEntries(searchParams as any);\n const _params = nx.compactObject({ ..._searchParams, ...params, ...overrideParams });\n if (allowFields?.length && allowFields.length > 0) retainKeys(_params, allowFields);\n return <ReactAntResourceForm params={_params} {...rest} />;\n};\n\nexport default ReactAntResourceForm;\nexport { ReactAntResourceFormFc };\n","export const API_FORM_LOCALES = {\n 'zh-CN': {\n create: '创建',\n update: '保存',\n create_title: '创建',\n update_title: '更新',\n create_success: '创建成功',\n update_success: '更新成功',\n submit: '提交',\n back: '返回',\n no_change: '没有修改',\n },\n 'en-US': {\n create: 'Create',\n update: 'Save',\n create_title: 'Create',\n update_title: 'Update',\n create_success: 'Create success',\n update_success: 'Update success',\n submit: 'Submit',\n back: 'Back',\n no_change: 'No change',\n },\n};\n"]}
|
|
1
|
+
{"version":3,"sources":["/Users/ap7/github/react-ant-resource-form/packages/lib/dist/main.cjs.js","../src/index.tsx","../src/locales.ts"],"names":["API_FORM_LOCALES","create","update","create_title","update_title","create_success","update_success","submit","back","no_change","CLASS_NAME","retainKeys","__name","obj","keys","nx","forIn","key","includes","_a","ReactAntResourceForm","Component","props","formRef","React","createRef","_isMounted","_initialValues","handleBack","history","setInitialValues","values","formInstance","getFieldsValue","handleFinish","canSave","message","info","t","isEdit","onResourceUpdate","onResourceCreate","params","name","submitGuard","onMutate","payload","__spreadValues","id","_payload","handleStateRequest","stage","submitGuardArgs","mutateArgs","then","$api"],"mappings":"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","file":"/Users/ap7/github/react-ant-resource-form/packages/lib/dist/main.cjs.js","sourcesContent":[null,"// import noop from '@jswork/noop';\nimport cx from 'classnames';\nimport React, { Component, FC } from 'react';\nimport type { FormInstance } from 'antd';\nimport { Button, ButtonProps, Card, CardProps, message, Space, Spin } from 'antd';\nimport ReactAntdFormSchema, { ReactAntdFormSchemaProps } from '@jswork/react-ant-form-schema';\nimport { ArrowLeftOutlined, DiffOutlined, SaveOutlined } from '@ant-design/icons';\nimport { API_FORM_LOCALES } from './locales';\nimport nx from '@jswork/next';\nimport '@jswork/next-compact-object';\nimport { useParams, useSearchParams } from 'react-router-dom';\nimport deepEqual from 'fast-deep-equal';\nimport fromEntries from 'fromentries';\n\ndeclare global {\n interface NxStatic {\n $api: Record<string, any>;\n $event: any;\n }\n}\n\ntype StagePayload = {\n stage: 'show' | 'create' | 'update';\n payload: any;\n};\n\ntype StageData = {\n stage: 'show' | 'create' | 'update';\n data: any;\n};\n\ntype MutateArgs = {\n name?: string;\n params?: Record<string, any>;\n payload: any;\n isEdit: boolean;\n values: any;\n};\n\ntype InitGuardArgs = {\n name?: string;\n params?: Record<string, any>;\n payload: any;\n isEdit: boolean;\n};\n\ntype SubmitGuardArgs = {\n name?: string;\n params?: Record<string, any>;\n payload: any;\n isEdit: boolean;\n values: any;\n};\n\nexport type ReactAntResourceFormProps = {\n lang?: string;\n loading?: boolean;\n okText?: string;\n backText?: string;\n params?: Record<string, any>;\n blocker?: boolean;\n disableHotkeySave?: boolean;\n initGuard?: (args: InitGuardArgs) => Promise<void>;\n submitGuard?: (args: SubmitGuardArgs) => Promise<void>;\n transformRequest?: (payload: StagePayload) => any;\n transformResponse?: (res: StageData) => any;\n okProps?: ButtonProps;\n backProps?: ButtonProps;\n classNames?: CardProps['classNames'];\n size?: CardProps['size'];\n extra?: CardProps['extra'];\n title?: CardProps['title'];\n onInit?: (ctx: ReactAntResourceForm) => void;\n onMutate?: (args: MutateArgs) => void;\n} & ReactAntdFormSchemaProps;\n\ntype IState = {\n loading: boolean;\n touched: boolean;\n};\n\nconst CLASS_NAME = 'react-ant-resource-form';\n\nconst retainKeys = (obj: Record<string, any>, keys: string[]) => {\n nx.forIn(obj, (key) => {\n if (!keys.includes(key)) {\n delete obj[key];\n }\n });\n return obj;\n};\n\n/**\n * 当前 card loading 不要直接使用,因为这个 loading 会导致 Card 里的 formRef 被设置成 null\n * 这个情况仅在 class component 里才会出现,function component 里不会:\n * 报错示例:\n *\n * this.formRef?: null\n * index.tsx:229 this.formRef?: {getFieldValue: ƒ, getFieldsValue: ƒ, getFieldError: ƒ, getFieldWarning: ƒ, getFieldsError: ƒ, …}\n * index.tsx:229 this.formRef?: null\n *\n * initGuard | submitGuard:\n * https://chat.qwen.ai/c/60329863-0e5e-47f9-a075-a65ad30940cc\n */\n\nclass ReactAntResourceForm extends Component<ReactAntResourceFormProps, IState> {\n public static defaultProps = {\n lang: 'zh-CN',\n disableHotkeySave: false,\n blocker: false,\n initGuard: () => Promise.resolve(),\n submitGuard: () => Promise.resolve(),\n };\n\n private formRef = React.createRef<FormInstance>(); // 注意类型\n private _isMounted = false;\n private _initialValues = null;\n\n get isEdit() {\n const { params } = this.props;\n return Boolean(params?.id);\n }\n\n get canSave() {\n const { touched, loading } = this.state;\n if (!this.isEdit) return !loading;\n return touched && !loading;\n }\n\n get titleView() {\n const { title } = this.props;\n const _title = title || (this.isEdit ? this.t('update_title') : this.t('create_title'));\n return (\n <Space>\n {_title}\n <span>{this.touchedView}</span>\n </Space>\n );\n }\n\n get touchedView() {\n if (!this.isEdit) return null;\n return this.state.touched ? (\n <em style={{ color: '#f60' }}>\n <DiffOutlined />\n </em>\n ) : null;\n }\n\n get extraView() {\n const { extra, backText, backProps } = this.props;\n if (extra) return extra;\n return (\n <Button size=\"small\" icon={<ArrowLeftOutlined />} onClick={this.handleBack} {...backProps}>\n {backText || this.t('back')}\n </Button>\n );\n }\n\n get childrenView() {\n const { okText, backText, okProps, backProps, children } = this.props;\n const _okText = okText || (this.isEdit ? this.t('update') : this.t('create'));\n if (children) return children;\n\n return (\n <Space>\n <Button\n disabled={!this.canSave}\n htmlType=\"submit\"\n type=\"primary\"\n icon={<SaveOutlined />}\n {...okProps}>\n {_okText || this.t('submit')}\n </Button>\n <Button icon={<ArrowLeftOutlined />} onClick={this.handleBack} {...backProps}>\n {backText || this.t('back')}\n </Button>\n </Space>\n );\n }\n\n get formInstance() {\n return this.formRef?.current;\n }\n\n constructor(props: ReactAntResourceFormProps) {\n super(props);\n this.state = {\n loading: props.loading!,\n touched: false,\n };\n\n this.handleStateRequest = this.handleStateRequest.bind(this);\n this.handleStateResponse = this.handleStateResponse.bind(this);\n this.initDetailIfNeeded = this.initDetailIfNeeded.bind(this);\n\n props.onInit?.(this);\n }\n\n private t(key: string) {\n const { lang } = this.props;\n return API_FORM_LOCALES[lang!][key];\n }\n\n private handleBack = () => {\n history.back();\n };\n\n private setInitialValues = (values?: any) => {\n this._initialValues = values || this.formInstance?.getFieldsValue() || {};\n };\n\n handleStateRequest(stagePayload: StagePayload) {\n this.setState({ loading: true });\n return this.props.transformRequest?.(stagePayload) || stagePayload.payload;\n }\n\n handleStateResponse(res: StageData) {\n const { name } = this.props;\n this.setState({ loading: false });\n nx.$event?.emit?.(`${name}:refetch`);\n return this.props.transformResponse?.(res) || res.data;\n }\n\n handleFinish = (values: any) => {\n if (!this.canSave) {\n void message.info(this.t('no_change'));\n return;\n }\n this.isEdit ? this.onResourceUpdate(values) : this.onResourceCreate(values);\n };\n\n private onResourceUpdate = (values: any) => {\n const { params, name, submitGuard, onMutate } = this.props;\n const payload = { id: params!.id, ...values, ...params };\n const _payload = this.handleStateRequest({ stage: 'update', payload });\n const submitGuardArgs: SubmitGuardArgs = {\n name,\n payload: _payload,\n isEdit: true,\n values,\n params,\n };\n const mutateArgs: MutateArgs = {\n name,\n payload: _payload,\n isEdit: true,\n values,\n };\n\n submitGuard?.(submitGuardArgs).then(() => {\n nx.$api[`${name}_update`](_payload)\n .then((res: any) => {\n void message.success(this.t('update_success'));\n this.handleStateResponse({ stage: 'update', data: res });\n onMutate?.(mutateArgs);\n })\n .finally(() => {\n this.setState({ loading: false });\n this.setInitialValues();\n this.handleValuesChange(null, this._initialValues);\n });\n });\n };\n\n private onResourceCreate = (values: any) => {\n const { params, name, submitGuard, onMutate } = this.props;\n const payload = { ...values, ...params };\n const _payload = this.handleStateRequest({ stage: 'create', payload });\n const submitGuardArgs: SubmitGuardArgs = {\n name,\n payload: _payload,\n isEdit: false,\n values,\n params,\n };\n\n const mutateArgs: MutateArgs = {\n name,\n payload: _payload,\n isEdit: false,\n values,\n };\n\n submitGuard?.(submitGuardArgs).then(() => {\n nx.$api[`${name}_create`](_payload)\n .then((res: any) => {\n void message.success(this.t('create_success'));\n this.handleStateResponse({ stage: 'create', data: res });\n this.formInstance?.resetFields();\n onMutate?.(mutateArgs);\n history.back();\n })\n .finally(() => this.setState({ loading: false }));\n });\n };\n\n // hotkey save handler (replaces useKeyboardSave hook)\n handleKeydown = (e: KeyboardEvent) => {\n const { disableHotkeySave } = this.props;\n const isSave = (e.ctrlKey || e.metaKey) && (e.key === 's' || e.key === 'S');\n if (isSave) {\n e.preventDefault();\n if (!disableHotkeySave) {\n this.formInstance?.submit();\n }\n }\n };\n\n handleValuesChange = (_: any, allValues: any) => {\n this.setState({\n touched: !deepEqual(this._initialValues, allValues),\n });\n };\n\n componentDidMount() {\n this._isMounted = true;\n // attach hotkey listener\n window.addEventListener('keydown', this.handleKeydown);\n // initialize detail if editing\n this.initDetailIfNeeded();\n }\n\n componentDidUpdate(prevProps: ReactAntResourceFormProps) {\n const prevId = prevProps.params?.id;\n const curId = this.props.params?.id;\n // re-init when id changed or from create -> edit\n if (prevId !== curId) {\n this.initDetailIfNeeded();\n }\n\n // loading update\n if (prevProps.loading !== this.props.loading) {\n this.setState({ loading: this.props.loading! });\n }\n }\n\n componentWillUnmount() {\n window.removeEventListener('keydown', this.handleKeydown);\n this._isMounted = false;\n }\n\n initDetailIfNeeded() {\n const { params, name, initGuard } = this.props;\n const resourceShow = `${name}_show`;\n\n if (this.isEdit) {\n const payload = { id: params!.id };\n const _payload = this.handleStateRequest({ stage: 'show', payload });\n const initGuardArgs: InitGuardArgs = {\n name,\n payload: _payload,\n isEdit: true,\n params,\n };\n initGuard?.(initGuardArgs).then(() => {\n nx.$api[resourceShow](_payload)\n .then((res: any) => {\n if (!this._isMounted) return; // 👈 关键:防止操作已卸载组件\n const data = this.handleStateResponse({ stage: 'show', data: res });\n this.formInstance?.setFieldsValue?.(data);\n })\n .finally(() => {\n this.setState({ loading: false });\n this.setInitialValues();\n });\n });\n } else {\n const initGuardArgs: InitGuardArgs = {\n name,\n payload: null,\n isEdit: false,\n params,\n };\n initGuard?.(initGuardArgs).then(() => {\n this.setInitialValues();\n this.setState({ loading: false });\n });\n }\n }\n\n render() {\n const {\n className,\n name,\n meta,\n children,\n lang,\n title,\n extra,\n size,\n okText,\n backText,\n okProps,\n backProps,\n classNames,\n params,\n transformRequest,\n transformResponse,\n disableHotkeySave,\n blocker,\n onInit,\n initGuard,\n submitGuard,\n loading,\n ...rest\n } = this.props;\n\n return (\n <Card\n title={this.titleView}\n extra={this.extraView}\n size={size}\n classNames={classNames}\n data-component={CLASS_NAME}\n data-blocker={blocker}\n className={cx(CLASS_NAME, className)}>\n <Spin spinning={this.state.loading}>\n <ReactAntdFormSchema\n meta={meta}\n ref={this.formRef}\n onValuesChange={this.handleValuesChange}\n onFinish={this.handleFinish}\n {...rest}>\n {this.childrenView}\n </ReactAntdFormSchema>\n </Spin>\n </Card>\n );\n }\n}\n\nexport type ReactAntResourceFormFcProps = ReactAntResourceFormProps & {\n allowFields?: string[];\n}\n\nconst ReactAntResourceFormFc: FC<ReactAntResourceFormFcProps> = (props) => {\n const { params: overrideParams, allowFields, ...rest } = props;\n const params = useParams();\n const [searchParams] = useSearchParams();\n const _searchParams = fromEntries(searchParams as any);\n const _params = nx.compactObject({ ..._searchParams, ...params, ...overrideParams });\n if (allowFields?.length && allowFields.length > 0) retainKeys(_params, allowFields);\n return <ReactAntResourceForm params={_params} {...rest} />;\n};\n\nexport default ReactAntResourceForm;\nexport { ReactAntResourceFormFc };\n","export const API_FORM_LOCALES = {\n 'zh-CN': {\n create: '创建',\n update: '保存',\n create_title: '创建',\n update_title: '更新',\n create_success: '创建成功',\n update_success: '更新成功',\n submit: '提交',\n back: '返回',\n no_change: '没有修改',\n },\n 'en-US': {\n create: 'Create',\n update: 'Save',\n create_title: 'Create',\n update_title: 'Update',\n create_success: 'Create success',\n update_success: 'Update success',\n submit: 'Submit',\n back: 'Back',\n no_change: 'No change',\n },\n};\n"]}
|
package/dist/main.d.mts
CHANGED
|
@@ -17,6 +17,13 @@ type StageData = {
|
|
|
17
17
|
stage: 'show' | 'create' | 'update';
|
|
18
18
|
data: any;
|
|
19
19
|
};
|
|
20
|
+
type MutateArgs = {
|
|
21
|
+
name?: string;
|
|
22
|
+
params?: Record<string, any>;
|
|
23
|
+
payload: any;
|
|
24
|
+
isEdit: boolean;
|
|
25
|
+
values: any;
|
|
26
|
+
};
|
|
20
27
|
type InitGuardArgs = {
|
|
21
28
|
name?: string;
|
|
22
29
|
params?: Record<string, any>;
|
|
@@ -49,6 +56,7 @@ type ReactAntResourceFormProps = {
|
|
|
49
56
|
extra?: CardProps['extra'];
|
|
50
57
|
title?: CardProps['title'];
|
|
51
58
|
onInit?: (ctx: ReactAntResourceForm) => void;
|
|
59
|
+
onMutate?: (args: MutateArgs) => void;
|
|
52
60
|
} & ReactAntdFormSchemaProps;
|
|
53
61
|
type IState = {
|
|
54
62
|
loading: boolean;
|
|
@@ -91,6 +99,8 @@ declare class ReactAntResourceForm extends Component<ReactAntResourceFormProps,
|
|
|
91
99
|
handleStateRequest(stagePayload: StagePayload): any;
|
|
92
100
|
handleStateResponse(res: StageData): any;
|
|
93
101
|
handleFinish: (values: any) => void;
|
|
102
|
+
private onResourceUpdate;
|
|
103
|
+
private onResourceCreate;
|
|
94
104
|
handleKeydown: (e: KeyboardEvent) => void;
|
|
95
105
|
handleValuesChange: (_: any, allValues: any) => void;
|
|
96
106
|
componentDidMount(): void;
|
package/dist/main.d.ts
CHANGED
|
@@ -17,6 +17,13 @@ type StageData = {
|
|
|
17
17
|
stage: 'show' | 'create' | 'update';
|
|
18
18
|
data: any;
|
|
19
19
|
};
|
|
20
|
+
type MutateArgs = {
|
|
21
|
+
name?: string;
|
|
22
|
+
params?: Record<string, any>;
|
|
23
|
+
payload: any;
|
|
24
|
+
isEdit: boolean;
|
|
25
|
+
values: any;
|
|
26
|
+
};
|
|
20
27
|
type InitGuardArgs = {
|
|
21
28
|
name?: string;
|
|
22
29
|
params?: Record<string, any>;
|
|
@@ -49,6 +56,7 @@ type ReactAntResourceFormProps = {
|
|
|
49
56
|
extra?: CardProps['extra'];
|
|
50
57
|
title?: CardProps['title'];
|
|
51
58
|
onInit?: (ctx: ReactAntResourceForm) => void;
|
|
59
|
+
onMutate?: (args: MutateArgs) => void;
|
|
52
60
|
} & ReactAntdFormSchemaProps;
|
|
53
61
|
type IState = {
|
|
54
62
|
loading: boolean;
|
|
@@ -91,6 +99,8 @@ declare class ReactAntResourceForm extends Component<ReactAntResourceFormProps,
|
|
|
91
99
|
handleStateRequest(stagePayload: StagePayload): any;
|
|
92
100
|
handleStateResponse(res: StageData): any;
|
|
93
101
|
handleFinish: (values: any) => void;
|
|
102
|
+
private onResourceUpdate;
|
|
103
|
+
private onResourceCreate;
|
|
94
104
|
handleKeydown: (e: KeyboardEvent) => void;
|
|
95
105
|
handleValuesChange: (_: any, allValues: any) => void;
|
|
96
106
|
componentDidMount(): void;
|
package/dist/main.esm.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var w=Object.defineProperty;var
|
|
1
|
+
var w=Object.defineProperty;var R=Object.getOwnPropertySymbols;var I=Object.prototype.hasOwnProperty,x=Object.prototype.propertyIsEnumerable;var E=(a,i,e)=>i in a?w(a,i,{enumerable:!0,configurable:!0,writable:!0,value:e}):a[i]=e,d=(a,i)=>{for(var e in i||(i={}))I.call(i,e)&&E(a,e,i[e]);if(R)for(var e of R(i))x.call(i,e)&&E(a,e,i[e]);return a};var h=(a,i)=>w(a,"name",{value:i,configurable:!0});var y=(a,i)=>{var e={};for(var t in a)I.call(a,t)&&i.indexOf(t)<0&&(e[t]=a[t]);if(a!=null&&R)for(var t of R(a))i.indexOf(t)<0&&x.call(a,t)&&(e[t]=a[t]);return e};var u=(a,i,e)=>E(a,typeof i!="symbol"?i+"":i,e);import O from"classnames";import o,{Component as $}from"react";import{Button as k,Card as T,message as b,Space as C,Spin as U}from"antd";import B from"@jswork/react-ant-form-schema";import{ArrowLeftOutlined as v,DiffOutlined as K,SaveOutlined as M}from"@ant-design/icons";var A={"zh-CN":{create:"\u521B\u5EFA",update:"\u4FDD\u5B58",create_title:"\u521B\u5EFA",update_title:"\u66F4\u65B0",create_success:"\u521B\u5EFA\u6210\u529F",update_success:"\u66F4\u65B0\u6210\u529F",submit:"\u63D0\u4EA4",back:"\u8FD4\u56DE",no_change:"\u6CA1\u6709\u4FEE\u6539"},"en-US":{create:"Create",update:"Save",create_title:"Create",update_title:"Update",create_success:"Create success",update_success:"Update success",submit:"Submit",back:"Back",no_change:"No change"}};import _ from"@jswork/next";import"@jswork/next-compact-object";import{useParams as z,useSearchParams as G}from"react-router-dom";import H from"fast-deep-equal";import W from"fromentries";var F="react-ant-resource-form",J=h((a,i)=>(_.forIn(a,e=>{i.includes(e)||delete a[e]}),a),"retainKeys"),f,N=(f=class extends ${constructor(e){var t;super(e);u(this,"formRef",o.createRef());u(this,"_isMounted",!1);u(this,"_initialValues",null);u(this,"handleBack",h(()=>{history.back()},"handleBack"));u(this,"setInitialValues",h(e=>{var t;this._initialValues=e||((t=this.formInstance)==null?void 0:t.getFieldsValue())||{}},"setInitialValues"));u(this,"handleFinish",h(e=>{if(!this.canSave){b.info(this.t("no_change"));return}this.isEdit?this.onResourceUpdate(e):this.onResourceCreate(e)},"handleFinish"));u(this,"onResourceUpdate",h(e=>{let{params:t,name:s,submitGuard:n,onMutate:r}=this.props,l=d(d({id:t.id},e),t),c=this.handleStateRequest({stage:"update",payload:l}),p={name:s,payload:c,isEdit:!0,values:e,params:t},g={name:s,payload:c,isEdit:!0,values:e};n==null||n(p).then(()=>{_.$api[`${s}_update`](c).then(m=>{b.success(this.t("update_success")),this.handleStateResponse({stage:"update",data:m}),r==null||r(g)}).finally(()=>{this.setState({loading:!1}),this.setInitialValues(),this.handleValuesChange(null,this._initialValues)})})},"onResourceUpdate"));u(this,"onResourceCreate",h(e=>{let{params:t,name:s,submitGuard:n,onMutate:r}=this.props,l=d(d({},e),t),c=this.handleStateRequest({stage:"create",payload:l}),p={name:s,payload:c,isEdit:!1,values:e,params:t},g={name:s,payload:c,isEdit:!1,values:e};n==null||n(p).then(()=>{_.$api[`${s}_create`](c).then(m=>{var S;b.success(this.t("create_success")),this.handleStateResponse({stage:"create",data:m}),(S=this.formInstance)==null||S.resetFields(),r==null||r(g),history.back()}).finally(()=>this.setState({loading:!1}))})},"onResourceCreate"));u(this,"handleKeydown",h(e=>{var n;let{disableHotkeySave:t}=this.props;(e.ctrlKey||e.metaKey)&&(e.key==="s"||e.key==="S")&&(e.preventDefault(),t||(n=this.formInstance)==null||n.submit())},"handleKeydown"));u(this,"handleValuesChange",h((e,t)=>{this.setState({touched:!H(this._initialValues,t)})},"handleValuesChange"));this.state={loading:e.loading,touched:!1},this.handleStateRequest=this.handleStateRequest.bind(this),this.handleStateResponse=this.handleStateResponse.bind(this),this.initDetailIfNeeded=this.initDetailIfNeeded.bind(this),(t=e.onInit)==null||t.call(e,this)}get isEdit(){let{params:e}=this.props;return!!(e!=null&&e.id)}get canSave(){let{touched:e,loading:t}=this.state;return this.isEdit?e&&!t:!t}get titleView(){let{title:e}=this.props,t=e||(this.isEdit?this.t("update_title"):this.t("create_title"));return o.createElement(C,null,t,o.createElement("span",null,this.touchedView))}get touchedView(){return this.isEdit&&this.state.touched?o.createElement("em",{style:{color:"#f60"}},o.createElement(K,null)):null}get extraView(){let{extra:e,backText:t,backProps:s}=this.props;return e||o.createElement(k,d({size:"small",icon:o.createElement(v,null),onClick:this.handleBack},s),t||this.t("back"))}get childrenView(){let{okText:e,backText:t,okProps:s,backProps:n,children:r}=this.props,l=e||(this.isEdit?this.t("update"):this.t("create"));return r||o.createElement(C,null,o.createElement(k,d({disabled:!this.canSave,htmlType:"submit",type:"primary",icon:o.createElement(M,null)},s),l||this.t("submit")),o.createElement(k,d({icon:o.createElement(v,null),onClick:this.handleBack},n),t||this.t("back")))}get formInstance(){var e;return(e=this.formRef)==null?void 0:e.current}t(e){let{lang:t}=this.props;return A[t][e]}handleStateRequest(e){var t,s;return this.setState({loading:!0}),((s=(t=this.props).transformRequest)==null?void 0:s.call(t,e))||e.payload}handleStateResponse(e){var s,n,r,l;let{name:t}=this.props;return this.setState({loading:!1}),(n=(s=_.$event)==null?void 0:s.emit)==null||n.call(s,`${t}:refetch`),((l=(r=this.props).transformResponse)==null?void 0:l.call(r,e))||e.data}componentDidMount(){this._isMounted=!0,window.addEventListener("keydown",this.handleKeydown),this.initDetailIfNeeded()}componentDidUpdate(e){var n,r;let t=(n=e.params)==null?void 0:n.id,s=(r=this.props.params)==null?void 0:r.id;t!==s&&this.initDetailIfNeeded(),e.loading!==this.props.loading&&this.setState({loading:this.props.loading})}componentWillUnmount(){window.removeEventListener("keydown",this.handleKeydown),this._isMounted=!1}initDetailIfNeeded(){let{params:e,name:t,initGuard:s}=this.props,n=`${t}_show`;if(this.isEdit){let r={id:e.id},l=this.handleStateRequest({stage:"show",payload:r}),c={name:t,payload:l,isEdit:!0,params:e};s==null||s(c).then(()=>{_.$api[n](l).then(p=>{var m,S;if(!this._isMounted)return;let g=this.handleStateResponse({stage:"show",data:p});(S=(m=this.formInstance)==null?void 0:m.setFieldsValue)==null||S.call(m,g)}).finally(()=>{this.setState({loading:!1}),this.setInitialValues()})})}else{let r={name:t,payload:null,isEdit:!1,params:e};s==null||s(r).then(()=>{this.setInitialValues(),this.setState({loading:!1})})}}render(){let V=this.props,{className:e,name:t,meta:s,children:n,lang:r,title:l,extra:c,size:p,okText:g,backText:m,okProps:S,backProps:X,classNames:q,params:Y,transformRequest:Z,transformResponse:j,disableHotkeySave:ee,blocker:D,onInit:te,initGuard:se,submitGuard:ae,loading:ie}=V,L=y(V,["className","name","meta","children","lang","title","extra","size","okText","backText","okProps","backProps","classNames","params","transformRequest","transformResponse","disableHotkeySave","blocker","onInit","initGuard","submitGuard","loading"]);return o.createElement(T,{title:this.titleView,extra:this.extraView,size:p,classNames:q,"data-component":F,"data-blocker":D,className:O(F,e)},o.createElement(U,{spinning:this.state.loading},o.createElement(B,d({meta:s,ref:this.formRef,onValuesChange:this.handleValuesChange,onFinish:this.handleFinish},L),this.childrenView)))}},h(f,"ReactAntResourceForm"),u(f,"defaultProps",{lang:"zh-CN",disableHotkeySave:!1,blocker:!1,initGuard:h(()=>Promise.resolve(),"initGuard"),submitGuard:h(()=>Promise.resolve(),"submitGuard")}),f),Q=h(a=>{let c=a,{params:i,allowFields:e}=c,t=y(c,["params","allowFields"]),s=z(),[n]=G(),r=W(n),l=_.compactObject(d(d(d({},r),s),i));return e!=null&&e.length&&e.length>0&&J(l,e),o.createElement(N,d({params:l},t))},"ReactAntResourceFormFc"),P=N;var ye=P;export{Q as ReactAntResourceFormFc,ye as default};
|
|
2
2
|
//# sourceMappingURL=main.esm.js.map
|
package/dist/main.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.tsx","../src/locales.ts","../src/main.tsx"],"sourcesContent":["// import noop from '@jswork/noop';\nimport cx from 'classnames';\nimport React, { Component, FC } from 'react';\nimport type { FormInstance } from 'antd';\nimport { Button, ButtonProps, Card, CardProps, message, Space, Spin } from 'antd';\nimport ReactAntdFormSchema, { ReactAntdFormSchemaProps } from '@jswork/react-ant-form-schema';\nimport { ArrowLeftOutlined, DiffOutlined, SaveOutlined } from '@ant-design/icons';\nimport { API_FORM_LOCALES } from './locales';\nimport nx from '@jswork/next';\nimport '@jswork/next-compact-object';\nimport { useParams, useSearchParams } from 'react-router-dom';\nimport deepEqual from 'fast-deep-equal';\nimport fromEntries from 'fromentries';\n\ndeclare global {\n interface NxStatic {\n $api: Record<string, any>;\n $event: any;\n }\n}\n\ntype StagePayload = {\n stage: 'show' | 'create' | 'update';\n payload: any;\n};\n\ntype StageData = {\n stage: 'show' | 'create' | 'update';\n data: any;\n};\n\ntype InitGuardArgs = {\n name?: string;\n params?: Record<string, any>;\n payload: any;\n isEdit: boolean;\n};\n\ntype SubmitGuardArgs = {\n name?: string;\n params?: Record<string, any>;\n payload: any;\n isEdit: boolean;\n values: any;\n};\n\nexport type ReactAntResourceFormProps = {\n lang?: string;\n loading?: boolean;\n okText?: string;\n backText?: string;\n params?: Record<string, any>;\n blocker?: boolean;\n disableHotkeySave?: boolean;\n initGuard?: (args: InitGuardArgs) => Promise<void>;\n submitGuard?: (args: SubmitGuardArgs) => Promise<void>;\n transformRequest?: (payload: StagePayload) => any;\n transformResponse?: (res: StageData) => any;\n okProps?: ButtonProps;\n backProps?: ButtonProps;\n classNames?: CardProps['classNames'];\n size?: CardProps['size'];\n extra?: CardProps['extra'];\n title?: CardProps['title'];\n onInit?: (ctx: ReactAntResourceForm) => void;\n} & ReactAntdFormSchemaProps;\n\ntype IState = {\n loading: boolean;\n touched: boolean;\n};\n\nconst CLASS_NAME = 'react-ant-resource-form';\n\nconst retainKeys = (obj: Record<string, any>, keys: string[]) => {\n nx.forIn(obj, (key) => {\n if (!keys.includes(key)) {\n delete obj[key];\n }\n });\n return obj;\n};\n\n/**\n * 当前 card loading 不要直接使用,因为这个 loading 会导致 Card 里的 formRef 被设置成 null\n * 这个情况仅在 class component 里才会出现,function component 里不会:\n * 报错示例:\n *\n * this.formRef?: null\n * index.tsx:229 this.formRef?: {getFieldValue: ƒ, getFieldsValue: ƒ, getFieldError: ƒ, getFieldWarning: ƒ, getFieldsError: ƒ, …}\n * index.tsx:229 this.formRef?: null\n *\n * initGuard | submitGuard:\n * https://chat.qwen.ai/c/60329863-0e5e-47f9-a075-a65ad30940cc\n */\n\nclass ReactAntResourceForm extends Component<ReactAntResourceFormProps, IState> {\n public static defaultProps = {\n lang: 'zh-CN',\n disableHotkeySave: false,\n blocker: false,\n initGuard: () => Promise.resolve(),\n submitGuard: () => Promise.resolve(),\n };\n\n private formRef = React.createRef<FormInstance>(); // 注意类型\n private _isMounted = false;\n private _initialValues = null;\n\n get isEdit() {\n const { params } = this.props;\n return Boolean(params?.id);\n }\n\n get canSave() {\n const { touched, loading } = this.state;\n if (!this.isEdit) return !loading;\n return touched && !loading;\n }\n\n get titleView() {\n const { title } = this.props;\n const _title = title || (this.isEdit ? this.t('update_title') : this.t('create_title'));\n return (\n <Space>\n {_title}\n <span>{this.touchedView}</span>\n </Space>\n );\n }\n\n get touchedView() {\n if (!this.isEdit) return null;\n return this.state.touched ? (\n <em style={{ color: '#f60' }}>\n <DiffOutlined />\n </em>\n ) : null;\n }\n\n get extraView() {\n const { extra, backText, backProps } = this.props;\n if (extra) return extra;\n return (\n <Button size=\"small\" icon={<ArrowLeftOutlined />} onClick={this.handleBack} {...backProps}>\n {backText || this.t('back')}\n </Button>\n );\n }\n\n get childrenView() {\n const { okText, backText, okProps, backProps, children } = this.props;\n const _okText = okText || (this.isEdit ? this.t('update') : this.t('create'));\n if (children) return children;\n\n return (\n <Space>\n <Button\n disabled={!this.canSave}\n htmlType=\"submit\"\n type=\"primary\"\n icon={<SaveOutlined />}\n {...okProps}>\n {_okText || this.t('submit')}\n </Button>\n <Button icon={<ArrowLeftOutlined />} onClick={this.handleBack} {...backProps}>\n {backText || this.t('back')}\n </Button>\n </Space>\n );\n }\n\n get formInstance() {\n return this.formRef?.current;\n }\n\n constructor(props: ReactAntResourceFormProps) {\n super(props);\n this.state = {\n loading: props.loading!,\n touched: false,\n };\n\n this.handleStateRequest = this.handleStateRequest.bind(this);\n this.handleStateResponse = this.handleStateResponse.bind(this);\n this.initDetailIfNeeded = this.initDetailIfNeeded.bind(this);\n\n props.onInit?.(this);\n }\n\n private t(key: string) {\n const { lang } = this.props;\n return API_FORM_LOCALES[lang!][key];\n }\n\n private handleBack = () => {\n history.back();\n };\n\n private setInitialValues = (values?: any) => {\n this._initialValues = values || this.formInstance?.getFieldsValue() || {};\n };\n\n handleStateRequest(stagePayload: StagePayload) {\n this.setState({ loading: true });\n return this.props.transformRequest?.(stagePayload) || stagePayload.payload;\n }\n\n handleStateResponse(res: StageData) {\n const { name } = this.props;\n this.setState({ loading: false });\n nx.$event?.emit?.(`${name}:refetch`);\n return this.props.transformResponse?.(res) || res.data;\n }\n\n handleFinish = (values: any) => {\n const { params, name, submitGuard } = this.props;\n const resourceEdit = `${name}_update`;\n const resourceCreate = `${name}_create`;\n\n if (!this.canSave) {\n void message.info(this.t('no_change'));\n return;\n }\n\n if (this.isEdit) {\n const payload = { id: params!.id, ...values, ...params };\n const _payload = this.handleStateRequest({ stage: 'update', payload });\n const submitGuardArgs: SubmitGuardArgs = {\n name,\n payload: _payload,\n isEdit: true,\n values,\n params,\n };\n\n submitGuard?.(submitGuardArgs).then(() => {\n nx.$api[resourceEdit](_payload)\n .then((res: any) => {\n void message.success(this.t('update_success'));\n this.handleStateResponse({ stage: 'update', data: res });\n })\n .finally(() => {\n this.setState({ loading: false });\n this.setInitialValues();\n this.handleValuesChange(null, this._initialValues);\n });\n });\n } else {\n const payload = { ...values, ...params };\n const _payload = this.handleStateRequest({ stage: 'create', payload });\n const submitGuardArgs: SubmitGuardArgs = {\n name,\n payload: _payload,\n isEdit: false,\n values,\n params,\n };\n\n submitGuard?.(submitGuardArgs).then(() => {\n nx.$api[resourceCreate](_payload)\n .then((res: any) => {\n void message.success(this.t('create_success'));\n this.handleStateResponse({ stage: 'create', data: res });\n this.formInstance?.resetFields();\n history.back();\n })\n .finally(() => this.setState({ loading: false }));\n });\n }\n };\n\n // hotkey save handler (replaces useKeyboardSave hook)\n handleKeydown = (e: KeyboardEvent) => {\n const { disableHotkeySave } = this.props;\n const isSave = (e.ctrlKey || e.metaKey) && (e.key === 's' || e.key === 'S');\n if (isSave) {\n e.preventDefault();\n if (!disableHotkeySave) {\n this.formInstance?.submit();\n }\n }\n };\n\n handleValuesChange = (_: any, allValues: any) => {\n this.setState({\n touched: !deepEqual(this._initialValues, allValues),\n });\n };\n\n componentDidMount() {\n this._isMounted = true;\n // attach hotkey listener\n window.addEventListener('keydown', this.handleKeydown);\n // initialize detail if editing\n this.initDetailIfNeeded();\n }\n\n componentDidUpdate(prevProps: ReactAntResourceFormProps) {\n const prevId = prevProps.params?.id;\n const curId = this.props.params?.id;\n // re-init when id changed or from create -> edit\n if (prevId !== curId) {\n this.initDetailIfNeeded();\n }\n\n // loading update\n if (prevProps.loading !== this.props.loading) {\n this.setState({ loading: this.props.loading! });\n }\n }\n\n componentWillUnmount() {\n window.removeEventListener('keydown', this.handleKeydown);\n this._isMounted = false;\n }\n\n initDetailIfNeeded() {\n const { params, name, initGuard } = this.props;\n const resourceShow = `${name}_show`;\n\n if (this.isEdit) {\n const payload = { id: params!.id };\n const _payload = this.handleStateRequest({ stage: 'show', payload });\n const initGuardArgs: InitGuardArgs = {\n name,\n payload: _payload,\n isEdit: true,\n params,\n };\n initGuard?.(initGuardArgs).then(() => {\n nx.$api[resourceShow](_payload)\n .then((res: any) => {\n if (!this._isMounted) return; // 👈 关键:防止操作已卸载组件\n const data = this.handleStateResponse({ stage: 'show', data: res });\n this.formInstance?.setFieldsValue?.(data);\n })\n .finally(() => {\n this.setState({ loading: false });\n this.setInitialValues();\n });\n });\n } else {\n const initGuardArgs: InitGuardArgs = {\n name,\n payload: null,\n isEdit: false,\n params,\n };\n initGuard?.(initGuardArgs).then(() => {\n this.setInitialValues();\n this.setState({ loading: false });\n });\n }\n }\n\n render() {\n const {\n className,\n name,\n meta,\n children,\n lang,\n title,\n extra,\n size,\n okText,\n backText,\n okProps,\n backProps,\n classNames,\n params,\n transformRequest,\n transformResponse,\n disableHotkeySave,\n blocker,\n onInit,\n initGuard,\n submitGuard,\n loading,\n ...rest\n } = this.props;\n\n return (\n <Card\n title={this.titleView}\n extra={this.extraView}\n size={size}\n classNames={classNames}\n data-component={CLASS_NAME}\n data-blocker={blocker}\n className={cx(CLASS_NAME, className)}>\n <Spin spinning={this.state.loading}>\n <ReactAntdFormSchema\n meta={meta}\n ref={this.formRef}\n onValuesChange={this.handleValuesChange}\n onFinish={this.handleFinish}\n {...rest}>\n {this.childrenView}\n </ReactAntdFormSchema>\n </Spin>\n </Card>\n );\n }\n}\n\nexport type ReactAntResourceFormFcProps = ReactAntResourceFormProps & {\n allowFields?: string[];\n}\n\nconst ReactAntResourceFormFc: FC<ReactAntResourceFormFcProps> = (props) => {\n const { params: overrideParams, allowFields, ...rest } = props;\n const params = useParams();\n const [searchParams] = useSearchParams();\n const _searchParams = fromEntries(searchParams as any);\n const _params = nx.compactObject({ ..._searchParams, ...params, ...overrideParams });\n if (allowFields?.length && allowFields.length > 0) retainKeys(_params, allowFields);\n return <ReactAntResourceForm params={_params} {...rest} />;\n};\n\nexport default ReactAntResourceForm;\nexport { ReactAntResourceFormFc };\n","export const API_FORM_LOCALES = {\n 'zh-CN': {\n create: '创建',\n update: '保存',\n create_title: '创建',\n update_title: '更新',\n create_success: '创建成功',\n update_success: '更新成功',\n submit: '提交',\n back: '返回',\n no_change: '没有修改',\n },\n 'en-US': {\n create: 'Create',\n update: 'Save',\n create_title: 'Create',\n update_title: 'Update',\n create_success: 'Create success',\n update_success: 'Update success',\n submit: 'Submit',\n back: 'Back',\n no_change: 'No change',\n },\n};\n","import ReactAntResourceForm, { ReactAntResourceFormFc } from '.';\nimport type { ReactAntResourceFormProps } from '.';\n\nexport default ReactAntResourceForm;\nexport { ReactAntResourceFormFc };\nexport type { ReactAntResourceFormProps };\n"],"mappings":"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","names":["cx","React","Component","Button","Card","message","Space","Spin","ReactAntdFormSchema","ArrowLeftOutlined","DiffOutlined","SaveOutlined","API_FORM_LOCALES","create","update","create_title","update_title","create_success","update_success","submit","back","no_change","nx","useParams","useSearchParams","deepEqual","fromEntries","CLASS_NAME","retainKeys","__name","obj","keys","nx","forIn","key","includes","_a","ReactAntResourceForm","Component","props","formRef","React","createRef","_isMounted","_initialValues","handleBack","history","back","setInitialValues","values","formInstance","getFieldsValue","handleFinish","params","name","submitGuard","resourceEdit","resourceCreate","canSave","message","info","t","isEdit","payload","__spreadValues","id","_payload","handleStateRequest","stage","submitGuardArgs","then","$api","res","success","handleStateResponse","data","finally","setState","loading","handleValuesChange","resetFields","handleKeydown","e","disableHotkeySave","ctrlKey","metaKey","preventDefault","submit","_","allValues","touched","deepEqual","state","bind","initDetailIfNeeded","onInit","Boolean","titleView","title","_title","Space","span","touchedView","em","style","color","DiffOutlined","extraView","extra","backText","backProps","Button","size","icon","ArrowLeftOutlined","onClick","childrenView","okText","okProps","children","_okText","disabled","htmlType","type","SaveOutlined","current","lang","API_FORM_LOCALES","stagePayload","_b","transformRequest","_c","_d","$event","emit","transformResponse","componentDidMount","window","addEventListener","componentDidUpdate","prevProps","prevId","curId","componentWillUnmount","removeEventListener","initGuard","resourceShow","initGuardArgs","setFieldsValue","render","className","meta","classNames","blocker","rest","Card","data-component","data-blocker","cx","Spin","spinning","ReactAntdFormSchema","ref","onValuesChange","onFinish","__publicField","defaultProps","Promise","resolve","ReactAntResourceFormFc","overrideParams","allowFields","useParams","searchParams","useSearchParams","_searchParams","fromEntries","_params","compactObject","length","index_default","main_default","ReactAntResourceForm"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.tsx","../src/locales.ts","../src/main.tsx"],"sourcesContent":["// import noop from '@jswork/noop';\nimport cx from 'classnames';\nimport React, { Component, FC } from 'react';\nimport type { FormInstance } from 'antd';\nimport { Button, ButtonProps, Card, CardProps, message, Space, Spin } from 'antd';\nimport ReactAntdFormSchema, { ReactAntdFormSchemaProps } from '@jswork/react-ant-form-schema';\nimport { ArrowLeftOutlined, DiffOutlined, SaveOutlined } from '@ant-design/icons';\nimport { API_FORM_LOCALES } from './locales';\nimport nx from '@jswork/next';\nimport '@jswork/next-compact-object';\nimport { useParams, useSearchParams } from 'react-router-dom';\nimport deepEqual from 'fast-deep-equal';\nimport fromEntries from 'fromentries';\n\ndeclare global {\n interface NxStatic {\n $api: Record<string, any>;\n $event: any;\n }\n}\n\ntype StagePayload = {\n stage: 'show' | 'create' | 'update';\n payload: any;\n};\n\ntype StageData = {\n stage: 'show' | 'create' | 'update';\n data: any;\n};\n\ntype MutateArgs = {\n name?: string;\n params?: Record<string, any>;\n payload: any;\n isEdit: boolean;\n values: any;\n};\n\ntype InitGuardArgs = {\n name?: string;\n params?: Record<string, any>;\n payload: any;\n isEdit: boolean;\n};\n\ntype SubmitGuardArgs = {\n name?: string;\n params?: Record<string, any>;\n payload: any;\n isEdit: boolean;\n values: any;\n};\n\nexport type ReactAntResourceFormProps = {\n lang?: string;\n loading?: boolean;\n okText?: string;\n backText?: string;\n params?: Record<string, any>;\n blocker?: boolean;\n disableHotkeySave?: boolean;\n initGuard?: (args: InitGuardArgs) => Promise<void>;\n submitGuard?: (args: SubmitGuardArgs) => Promise<void>;\n transformRequest?: (payload: StagePayload) => any;\n transformResponse?: (res: StageData) => any;\n okProps?: ButtonProps;\n backProps?: ButtonProps;\n classNames?: CardProps['classNames'];\n size?: CardProps['size'];\n extra?: CardProps['extra'];\n title?: CardProps['title'];\n onInit?: (ctx: ReactAntResourceForm) => void;\n onMutate?: (args: MutateArgs) => void;\n} & ReactAntdFormSchemaProps;\n\ntype IState = {\n loading: boolean;\n touched: boolean;\n};\n\nconst CLASS_NAME = 'react-ant-resource-form';\n\nconst retainKeys = (obj: Record<string, any>, keys: string[]) => {\n nx.forIn(obj, (key) => {\n if (!keys.includes(key)) {\n delete obj[key];\n }\n });\n return obj;\n};\n\n/**\n * 当前 card loading 不要直接使用,因为这个 loading 会导致 Card 里的 formRef 被设置成 null\n * 这个情况仅在 class component 里才会出现,function component 里不会:\n * 报错示例:\n *\n * this.formRef?: null\n * index.tsx:229 this.formRef?: {getFieldValue: ƒ, getFieldsValue: ƒ, getFieldError: ƒ, getFieldWarning: ƒ, getFieldsError: ƒ, …}\n * index.tsx:229 this.formRef?: null\n *\n * initGuard | submitGuard:\n * https://chat.qwen.ai/c/60329863-0e5e-47f9-a075-a65ad30940cc\n */\n\nclass ReactAntResourceForm extends Component<ReactAntResourceFormProps, IState> {\n public static defaultProps = {\n lang: 'zh-CN',\n disableHotkeySave: false,\n blocker: false,\n initGuard: () => Promise.resolve(),\n submitGuard: () => Promise.resolve(),\n };\n\n private formRef = React.createRef<FormInstance>(); // 注意类型\n private _isMounted = false;\n private _initialValues = null;\n\n get isEdit() {\n const { params } = this.props;\n return Boolean(params?.id);\n }\n\n get canSave() {\n const { touched, loading } = this.state;\n if (!this.isEdit) return !loading;\n return touched && !loading;\n }\n\n get titleView() {\n const { title } = this.props;\n const _title = title || (this.isEdit ? this.t('update_title') : this.t('create_title'));\n return (\n <Space>\n {_title}\n <span>{this.touchedView}</span>\n </Space>\n );\n }\n\n get touchedView() {\n if (!this.isEdit) return null;\n return this.state.touched ? (\n <em style={{ color: '#f60' }}>\n <DiffOutlined />\n </em>\n ) : null;\n }\n\n get extraView() {\n const { extra, backText, backProps } = this.props;\n if (extra) return extra;\n return (\n <Button size=\"small\" icon={<ArrowLeftOutlined />} onClick={this.handleBack} {...backProps}>\n {backText || this.t('back')}\n </Button>\n );\n }\n\n get childrenView() {\n const { okText, backText, okProps, backProps, children } = this.props;\n const _okText = okText || (this.isEdit ? this.t('update') : this.t('create'));\n if (children) return children;\n\n return (\n <Space>\n <Button\n disabled={!this.canSave}\n htmlType=\"submit\"\n type=\"primary\"\n icon={<SaveOutlined />}\n {...okProps}>\n {_okText || this.t('submit')}\n </Button>\n <Button icon={<ArrowLeftOutlined />} onClick={this.handleBack} {...backProps}>\n {backText || this.t('back')}\n </Button>\n </Space>\n );\n }\n\n get formInstance() {\n return this.formRef?.current;\n }\n\n constructor(props: ReactAntResourceFormProps) {\n super(props);\n this.state = {\n loading: props.loading!,\n touched: false,\n };\n\n this.handleStateRequest = this.handleStateRequest.bind(this);\n this.handleStateResponse = this.handleStateResponse.bind(this);\n this.initDetailIfNeeded = this.initDetailIfNeeded.bind(this);\n\n props.onInit?.(this);\n }\n\n private t(key: string) {\n const { lang } = this.props;\n return API_FORM_LOCALES[lang!][key];\n }\n\n private handleBack = () => {\n history.back();\n };\n\n private setInitialValues = (values?: any) => {\n this._initialValues = values || this.formInstance?.getFieldsValue() || {};\n };\n\n handleStateRequest(stagePayload: StagePayload) {\n this.setState({ loading: true });\n return this.props.transformRequest?.(stagePayload) || stagePayload.payload;\n }\n\n handleStateResponse(res: StageData) {\n const { name } = this.props;\n this.setState({ loading: false });\n nx.$event?.emit?.(`${name}:refetch`);\n return this.props.transformResponse?.(res) || res.data;\n }\n\n handleFinish = (values: any) => {\n if (!this.canSave) {\n void message.info(this.t('no_change'));\n return;\n }\n this.isEdit ? this.onResourceUpdate(values) : this.onResourceCreate(values);\n };\n\n private onResourceUpdate = (values: any) => {\n const { params, name, submitGuard, onMutate } = this.props;\n const payload = { id: params!.id, ...values, ...params };\n const _payload = this.handleStateRequest({ stage: 'update', payload });\n const submitGuardArgs: SubmitGuardArgs = {\n name,\n payload: _payload,\n isEdit: true,\n values,\n params,\n };\n const mutateArgs: MutateArgs = {\n name,\n payload: _payload,\n isEdit: true,\n values,\n };\n\n submitGuard?.(submitGuardArgs).then(() => {\n nx.$api[`${name}_update`](_payload)\n .then((res: any) => {\n void message.success(this.t('update_success'));\n this.handleStateResponse({ stage: 'update', data: res });\n onMutate?.(mutateArgs);\n })\n .finally(() => {\n this.setState({ loading: false });\n this.setInitialValues();\n this.handleValuesChange(null, this._initialValues);\n });\n });\n };\n\n private onResourceCreate = (values: any) => {\n const { params, name, submitGuard, onMutate } = this.props;\n const payload = { ...values, ...params };\n const _payload = this.handleStateRequest({ stage: 'create', payload });\n const submitGuardArgs: SubmitGuardArgs = {\n name,\n payload: _payload,\n isEdit: false,\n values,\n params,\n };\n\n const mutateArgs: MutateArgs = {\n name,\n payload: _payload,\n isEdit: false,\n values,\n };\n\n submitGuard?.(submitGuardArgs).then(() => {\n nx.$api[`${name}_create`](_payload)\n .then((res: any) => {\n void message.success(this.t('create_success'));\n this.handleStateResponse({ stage: 'create', data: res });\n this.formInstance?.resetFields();\n onMutate?.(mutateArgs);\n history.back();\n })\n .finally(() => this.setState({ loading: false }));\n });\n };\n\n // hotkey save handler (replaces useKeyboardSave hook)\n handleKeydown = (e: KeyboardEvent) => {\n const { disableHotkeySave } = this.props;\n const isSave = (e.ctrlKey || e.metaKey) && (e.key === 's' || e.key === 'S');\n if (isSave) {\n e.preventDefault();\n if (!disableHotkeySave) {\n this.formInstance?.submit();\n }\n }\n };\n\n handleValuesChange = (_: any, allValues: any) => {\n this.setState({\n touched: !deepEqual(this._initialValues, allValues),\n });\n };\n\n componentDidMount() {\n this._isMounted = true;\n // attach hotkey listener\n window.addEventListener('keydown', this.handleKeydown);\n // initialize detail if editing\n this.initDetailIfNeeded();\n }\n\n componentDidUpdate(prevProps: ReactAntResourceFormProps) {\n const prevId = prevProps.params?.id;\n const curId = this.props.params?.id;\n // re-init when id changed or from create -> edit\n if (prevId !== curId) {\n this.initDetailIfNeeded();\n }\n\n // loading update\n if (prevProps.loading !== this.props.loading) {\n this.setState({ loading: this.props.loading! });\n }\n }\n\n componentWillUnmount() {\n window.removeEventListener('keydown', this.handleKeydown);\n this._isMounted = false;\n }\n\n initDetailIfNeeded() {\n const { params, name, initGuard } = this.props;\n const resourceShow = `${name}_show`;\n\n if (this.isEdit) {\n const payload = { id: params!.id };\n const _payload = this.handleStateRequest({ stage: 'show', payload });\n const initGuardArgs: InitGuardArgs = {\n name,\n payload: _payload,\n isEdit: true,\n params,\n };\n initGuard?.(initGuardArgs).then(() => {\n nx.$api[resourceShow](_payload)\n .then((res: any) => {\n if (!this._isMounted) return; // 👈 关键:防止操作已卸载组件\n const data = this.handleStateResponse({ stage: 'show', data: res });\n this.formInstance?.setFieldsValue?.(data);\n })\n .finally(() => {\n this.setState({ loading: false });\n this.setInitialValues();\n });\n });\n } else {\n const initGuardArgs: InitGuardArgs = {\n name,\n payload: null,\n isEdit: false,\n params,\n };\n initGuard?.(initGuardArgs).then(() => {\n this.setInitialValues();\n this.setState({ loading: false });\n });\n }\n }\n\n render() {\n const {\n className,\n name,\n meta,\n children,\n lang,\n title,\n extra,\n size,\n okText,\n backText,\n okProps,\n backProps,\n classNames,\n params,\n transformRequest,\n transformResponse,\n disableHotkeySave,\n blocker,\n onInit,\n initGuard,\n submitGuard,\n loading,\n ...rest\n } = this.props;\n\n return (\n <Card\n title={this.titleView}\n extra={this.extraView}\n size={size}\n classNames={classNames}\n data-component={CLASS_NAME}\n data-blocker={blocker}\n className={cx(CLASS_NAME, className)}>\n <Spin spinning={this.state.loading}>\n <ReactAntdFormSchema\n meta={meta}\n ref={this.formRef}\n onValuesChange={this.handleValuesChange}\n onFinish={this.handleFinish}\n {...rest}>\n {this.childrenView}\n </ReactAntdFormSchema>\n </Spin>\n </Card>\n );\n }\n}\n\nexport type ReactAntResourceFormFcProps = ReactAntResourceFormProps & {\n allowFields?: string[];\n}\n\nconst ReactAntResourceFormFc: FC<ReactAntResourceFormFcProps> = (props) => {\n const { params: overrideParams, allowFields, ...rest } = props;\n const params = useParams();\n const [searchParams] = useSearchParams();\n const _searchParams = fromEntries(searchParams as any);\n const _params = nx.compactObject({ ..._searchParams, ...params, ...overrideParams });\n if (allowFields?.length && allowFields.length > 0) retainKeys(_params, allowFields);\n return <ReactAntResourceForm params={_params} {...rest} />;\n};\n\nexport default ReactAntResourceForm;\nexport { ReactAntResourceFormFc };\n","export const API_FORM_LOCALES = {\n 'zh-CN': {\n create: '创建',\n update: '保存',\n create_title: '创建',\n update_title: '更新',\n create_success: '创建成功',\n update_success: '更新成功',\n submit: '提交',\n back: '返回',\n no_change: '没有修改',\n },\n 'en-US': {\n create: 'Create',\n update: 'Save',\n create_title: 'Create',\n update_title: 'Update',\n create_success: 'Create success',\n update_success: 'Update success',\n submit: 'Submit',\n back: 'Back',\n no_change: 'No change',\n },\n};\n","import ReactAntResourceForm, { ReactAntResourceFormFc } from '.';\nimport type { ReactAntResourceFormProps } from '.';\n\nexport default ReactAntResourceForm;\nexport { ReactAntResourceFormFc };\nexport type { ReactAntResourceFormProps };\n"],"mappings":"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","names":["cx","React","Component","Button","Card","message","Space","Spin","ReactAntdFormSchema","ArrowLeftOutlined","DiffOutlined","SaveOutlined","API_FORM_LOCALES","create","update","create_title","update_title","create_success","update_success","submit","back","no_change","nx","useParams","useSearchParams","deepEqual","fromEntries","CLASS_NAME","retainKeys","__name","obj","keys","nx","forIn","key","includes","_a","ReactAntResourceForm","Component","props","formRef","React","createRef","_isMounted","_initialValues","handleBack","history","back","setInitialValues","values","formInstance","getFieldsValue","handleFinish","canSave","message","info","t","isEdit","onResourceUpdate","onResourceCreate","params","name","submitGuard","onMutate","payload","__spreadValues","id","_payload","handleStateRequest","stage","submitGuardArgs","mutateArgs","then","$api","res","success","handleStateResponse","data","finally","setState","loading","handleValuesChange","resetFields","handleKeydown","e","disableHotkeySave","ctrlKey","metaKey","preventDefault","submit","_","allValues","touched","deepEqual","state","bind","initDetailIfNeeded","onInit","Boolean","titleView","title","_title","Space","span","touchedView","em","style","color","DiffOutlined","extraView","extra","backText","backProps","Button","size","icon","ArrowLeftOutlined","onClick","childrenView","okText","okProps","children","_okText","disabled","htmlType","type","SaveOutlined","current","lang","API_FORM_LOCALES","stagePayload","_b","transformRequest","_c","_d","$event","emit","transformResponse","componentDidMount","window","addEventListener","componentDidUpdate","prevProps","prevId","curId","componentWillUnmount","removeEventListener","initGuard","resourceShow","initGuardArgs","setFieldsValue","render","className","meta","classNames","blocker","rest","Card","data-component","data-blocker","cx","Spin","spinning","ReactAntdFormSchema","ref","onValuesChange","onFinish","__publicField","defaultProps","Promise","resolve","ReactAntResourceFormFc","overrideParams","allowFields","useParams","searchParams","useSearchParams","_searchParams","fromEntries","_params","compactObject","length","index_default","main_default","ReactAntResourceForm"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jswork/react-ant-resource-form",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.31",
|
|
4
4
|
"main": "dist/main.cjs.js",
|
|
5
5
|
"module": "dist/main.esm.js",
|
|
6
6
|
"types": "dist/main.d.ts",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"release": "release-it"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@jswork/next-compact-object": "^1.0.
|
|
20
|
+
"@jswork/next-compact-object": "^1.0.7",
|
|
21
21
|
"fast-deep-equal": "^3.1.3",
|
|
22
22
|
"fromentries": "^1.3.2"
|
|
23
23
|
},
|
package/src/index.tsx
CHANGED
|
@@ -29,6 +29,14 @@ type StageData = {
|
|
|
29
29
|
data: any;
|
|
30
30
|
};
|
|
31
31
|
|
|
32
|
+
type MutateArgs = {
|
|
33
|
+
name?: string;
|
|
34
|
+
params?: Record<string, any>;
|
|
35
|
+
payload: any;
|
|
36
|
+
isEdit: boolean;
|
|
37
|
+
values: any;
|
|
38
|
+
};
|
|
39
|
+
|
|
32
40
|
type InitGuardArgs = {
|
|
33
41
|
name?: string;
|
|
34
42
|
params?: Record<string, any>;
|
|
@@ -63,6 +71,7 @@ export type ReactAntResourceFormProps = {
|
|
|
63
71
|
extra?: CardProps['extra'];
|
|
64
72
|
title?: CardProps['title'];
|
|
65
73
|
onInit?: (ctx: ReactAntResourceForm) => void;
|
|
74
|
+
onMutate?: (args: MutateArgs) => void;
|
|
66
75
|
} & ReactAntdFormSchemaProps;
|
|
67
76
|
|
|
68
77
|
type IState = {
|
|
@@ -214,60 +223,76 @@ class ReactAntResourceForm extends Component<ReactAntResourceFormProps, IState>
|
|
|
214
223
|
}
|
|
215
224
|
|
|
216
225
|
handleFinish = (values: any) => {
|
|
217
|
-
const { params, name, submitGuard } = this.props;
|
|
218
|
-
const resourceEdit = `${name}_update`;
|
|
219
|
-
const resourceCreate = `${name}_create`;
|
|
220
|
-
|
|
221
226
|
if (!this.canSave) {
|
|
222
227
|
void message.info(this.t('no_change'));
|
|
223
228
|
return;
|
|
224
229
|
}
|
|
230
|
+
this.isEdit ? this.onResourceUpdate(values) : this.onResourceCreate(values);
|
|
231
|
+
};
|
|
225
232
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
233
|
+
private onResourceUpdate = (values: any) => {
|
|
234
|
+
const { params, name, submitGuard, onMutate } = this.props;
|
|
235
|
+
const payload = { id: params!.id, ...values, ...params };
|
|
236
|
+
const _payload = this.handleStateRequest({ stage: 'update', payload });
|
|
237
|
+
const submitGuardArgs: SubmitGuardArgs = {
|
|
238
|
+
name,
|
|
239
|
+
payload: _payload,
|
|
240
|
+
isEdit: true,
|
|
241
|
+
values,
|
|
242
|
+
params,
|
|
243
|
+
};
|
|
244
|
+
const mutateArgs: MutateArgs = {
|
|
245
|
+
name,
|
|
246
|
+
payload: _payload,
|
|
247
|
+
isEdit: true,
|
|
248
|
+
values,
|
|
249
|
+
};
|
|
236
250
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
const _payload = this.handleStateRequest({ stage: 'create', payload });
|
|
252
|
-
const submitGuardArgs: SubmitGuardArgs = {
|
|
253
|
-
name,
|
|
254
|
-
payload: _payload,
|
|
255
|
-
isEdit: false,
|
|
256
|
-
values,
|
|
257
|
-
params,
|
|
258
|
-
};
|
|
251
|
+
submitGuard?.(submitGuardArgs).then(() => {
|
|
252
|
+
nx.$api[`${name}_update`](_payload)
|
|
253
|
+
.then((res: any) => {
|
|
254
|
+
void message.success(this.t('update_success'));
|
|
255
|
+
this.handleStateResponse({ stage: 'update', data: res });
|
|
256
|
+
onMutate?.(mutateArgs);
|
|
257
|
+
})
|
|
258
|
+
.finally(() => {
|
|
259
|
+
this.setState({ loading: false });
|
|
260
|
+
this.setInitialValues();
|
|
261
|
+
this.handleValuesChange(null, this._initialValues);
|
|
262
|
+
});
|
|
263
|
+
});
|
|
264
|
+
};
|
|
259
265
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
}
|
|
266
|
+
private onResourceCreate = (values: any) => {
|
|
267
|
+
const { params, name, submitGuard, onMutate } = this.props;
|
|
268
|
+
const payload = { ...values, ...params };
|
|
269
|
+
const _payload = this.handleStateRequest({ stage: 'create', payload });
|
|
270
|
+
const submitGuardArgs: SubmitGuardArgs = {
|
|
271
|
+
name,
|
|
272
|
+
payload: _payload,
|
|
273
|
+
isEdit: false,
|
|
274
|
+
values,
|
|
275
|
+
params,
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
const mutateArgs: MutateArgs = {
|
|
279
|
+
name,
|
|
280
|
+
payload: _payload,
|
|
281
|
+
isEdit: false,
|
|
282
|
+
values,
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
submitGuard?.(submitGuardArgs).then(() => {
|
|
286
|
+
nx.$api[`${name}_create`](_payload)
|
|
287
|
+
.then((res: any) => {
|
|
288
|
+
void message.success(this.t('create_success'));
|
|
289
|
+
this.handleStateResponse({ stage: 'create', data: res });
|
|
290
|
+
this.formInstance?.resetFields();
|
|
291
|
+
onMutate?.(mutateArgs);
|
|
292
|
+
history.back();
|
|
293
|
+
})
|
|
294
|
+
.finally(() => this.setState({ loading: false }));
|
|
295
|
+
});
|
|
271
296
|
};
|
|
272
297
|
|
|
273
298
|
// hotkey save handler (replaces useKeyboardSave hook)
|