diff --git a/button.d.ts b/button.d.ts index 9b04a89..a56034c 100644 --- a/button.d.ts +++ b/button.d.ts @@ -1,5 +1,6 @@ -import React from 'react'; -import PropTypes from 'prop-types'; +import { ReactNode } from 'react'; +import { PopupContainerProps } from './container'; +export { PopupContainerProps } from './container'; declare const _default: OperationAuth; @@ -23,93 +24,151 @@ declare class OperationAuth { #private; } +/** antd Button 的视觉类型 */ +type ButtonType = 'primary' | 'default' | 'danger' | '' + +/** 按钮尺寸 */ +type ButtonSize = 'large' | 'middle' | 'small' + +/** 按钮外观分类,对应 entry(cate) 的参数 */ +type ButtonCate = 'default' | 'link' | 'circle' | 'round' | 'dashed' + +/** 按钮触发的行为类型 */ +type WidgetType = + | 'redirect' + | 'func' + | 'component' + | 'fsdpf-component' + | 'grid-layout-form' + | 'grid-layout' + | 'data-list' + | 'destroy' + +/** antd Tooltip / Popconfirm 支持的弹出位置 */ +type PlacementType = + | 'top' | 'left' | 'right' | 'bottom' + | 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight' + | 'leftTop' | 'leftBottom' | 'rightTop' | 'rightBottom' + +/** Button props.tooltip 配置 */ +interface ButtonTooltip { + /** 提示文字 */ + title: string + /** 弹出位置 */ + placement?: PlacementType + /** 是否启用,0 视同 false */ + enabled?: boolean | number + getPopupContainer?: (e: HTMLElement) => HTMLElement +} + +/** Button props.confirm 二次确认气泡配置 */ +interface ButtonConfirm { + /** 确认提示文字 */ + title: string + cancelText?: string + okText?: string + /** 确认按钮类型 */ + okType?: ButtonType + placement?: PlacementType + /** 是否启用,0 视同 false */ + enabled?: boolean | number + getPopupContainer?: (e: HTMLElement) => HTMLElement + arrow?: boolean | { pointAtCenter: boolean } +} + +/** + * 按钮点击行为的容器配置;在 PopupContainerProps 基础上叠加 Popover 专有字段和 Button 专有的 mode, + * 流经 Button → Popover → Popup.modal 三层,各层按需取用不同字段 + */ +interface WidgetContainerProps extends Omit { + /** 'popover' 时按钮触发内嵌气泡卡片,否则走 Popup.modal */ + mode?: 'popover' | string + /** 弹窗标题,支持 lodash template 插值(以点击时的 raw data 为上下文) */ + title?: string + /** antd Popover 的弹出位置(12 方向) */ + placement?: PlacementType | string + /** antd Popover 对齐微调配置 */ + align?: unknown + /** antd Popover 的 zIndex */ + zIndex?: number + /** antd Popover 的箭头配置 */ + arrow?: boolean | { pointAtCenter: boolean } + getPopupContainer?: (e: HTMLElement) => HTMLElement + /** 气泡挂载到 body,false 时挂载到触发元素父节点;默认 true */ + isPopupMountBodyContainer?: boolean +} + + +/** useButton 第二个参数:回调处理器 */ +interface UseButtonHandlers { + onAfterClick?: (result: unknown) => void + onBeforeClick?: (data: unknown) => void +} + +/** useButton 返回 / ButtonProps 共用的状态字段 */ +interface UseButtonStatus { + loading?: boolean + disabled?: boolean +} + +/** useButton 第一个参数:行为配置 */ +interface UseButtonProps { + /** 行为目标:组件 / 函数 / 路由 / 表达式,含义随 widgetType 而定 */ + widget?: unknown + /** 行为类型,决定 widget 的解释方式和触发后的动作 */ + widgetType?: WidgetType + /** 触发时附带的额外数据,合并到 widgetProps 求值结果后传给动作处理器 */ + widgetData?: Record + /** 触发前解析的 props 映射配置(经 getWidgetPropsData 求值) */ + widgetProps?: Record + /** 传给目标弹窗/表单/请求的 $setting 配置 */ + widgetSetting?: Record + /** 传给弹窗容器的配置(title/placement/zIndex 等) */ + widgetContainerProps?: WidgetContainerProps +} + +/** Button 组件的 props(所有变体共用) */ +interface ButtonProps extends UseButtonProps, UseButtonHandlers, UseButtonStatus { + className?: string + /** 覆盖工厂默认外观分类 */ + variant?: ButtonCate + children?: ReactNode + /** 按钮文字,与 children 二选一 */ + name?: string + /** 图标 class 名 */ + icon?: string + type?: ButtonType + iconPosition?: 'start' | 'end' + /** 按钮操作的权限标识 */ + noAuthType?: string + /** onClick 时传给动作处理器的数据源 */ + data?: unknown + tooltip?: ButtonTooltip + confirm?: ButtonConfirm + [key: string]: unknown +} + + +/** useButton 返回值:[点击处理函数(已防抖), 当前 loading/disabled 状态] */ +type UseButtonReturn = [(data: unknown) => void, UseButtonStatus] + +/** ButtonGroupPopover props.options 中每一项的结构(ButtonProps + uuid + 必填 widgetType) */ +interface ButtonOption extends ButtonProps { + /** 操作项唯一标识,用于权限校验 */ + uuid?: string + widgetType: WidgetType + /** 操作项自身的容器配置,与外层 widgetContainerProps 合并 */ + widgetContainerSetting?: WidgetContainerProps +} + /** * Button 组件点击行为的核心 hook;按 widgetType 把点击行为分发到对应的处理器 * (跳转/自定义函数/弹窗组件/表单弹窗/数据列表弹窗/删除请求等) - * @param {Object} config - * @param {*} config.widget 目标(组件/函数名/表达式/路由等,含义随 widgetType 而定) - * @param {'redirect'|'func'|'component'|'fsdpf-component'|'grid-layout-form'|'data-list'|'destroy'} [config.widgetType] 行为类型 - * @param {*} [config.widgetData] 触发时附带的数据 - * @param {Object} [config.widgetProps] 触发前解析的 props 配置(经 getWidgetPropsData) - * @param {Object} [config.widgetSetting] 传给目标(弹窗/表单/请求)的配置 - * @param {Object} [config.widgetContainerProps] 传给弹窗容器的 props - * @param {Object} [handlers] - * @param {(result: *) => void} [handlers.onAfterClick] 动作完成后的回调 - * @param {(data: *) => void} [handlers.onBeforeClick] 动作开始前的回调 - * @returns {[(data: *) => void, {loading?: boolean, disabled?: boolean}]} [点击处理函数(已做 300ms 防抖), 当前 loading/disabled 状态] + * @param {UseButtonProps} config + * @param {UseButtonHandlers} [handlers] + * @returns {UseButtonReturn} [点击处理函数(已做 300ms 防抖), 当前 loading/disabled 状态] */ -declare function useButton({ widget, widgetType, widgetData, widgetProps, widgetSetting, widgetContainerProps, }: { - widget: any; - widgetType?: "redirect" | "func" | "component" | "fsdpf-component" | "grid-layout-form" | "data-list" | "destroy"; - widgetData?: any; - widgetProps?: any; - widgetSetting?: any; - widgetContainerProps?: any; -}, { onAfterClick, onBeforeClick }?: { - onAfterClick?: (result: any) => void; - onBeforeClick?: (data: any) => void; -}): [(data: any) => void, { - loading?: boolean; - disabled?: boolean; -}]; +declare function useButton({ widget, widgetType, widgetData, widgetProps, widgetSetting, widgetContainerProps, }: UseButtonProps, { onAfterClick, onBeforeClick }?: UseButtonHandlers): UseButtonReturn; -declare function Button({ className, variant, children, name, icon, type, iconPosition, noAuthType, onAfterClick, onBeforeClick, data, loading: customLoading, disabled: customDisabled, tooltip, confirm, widget, widgetType, widgetData, widgetProps, widgetSetting, widgetContainerProps, ...props }: { - [x: string]: any; - className: any; - variant: any; - children: any; - name: any; - icon: any; - type?: string; - iconPosition?: string; - noAuthType: any; - onAfterClick: any; - onBeforeClick: any; - data: any; - loading: any; - disabled: any; - tooltip: any; - confirm: any; - widget?: () => void; - widgetType: any; - widgetData: any; - widgetProps: any; - widgetSetting: any; - widgetContainerProps: any; -}): React.JSX.Element; -declare namespace Button { - namespace propTypes { - let type: PropTypes.Requireable; - let size: PropTypes.Requireable; - let name: PropTypes.Requireable; - let icon: PropTypes.Requireable; - let iconPosition: PropTypes.Requireable; - let data: PropTypes.Requireable; - let widget: PropTypes.Requireable; - let widgetType: PropTypes.Requireable; - let widgetData: PropTypes.Requireable; - let widgetProps: PropTypes.Requireable; - let widgetSetting: PropTypes.Requireable; - let widgetContainerProps: PropTypes.Requireable; - let tooltip: PropTypes.Requireable; - placement: PropTypes.Requireable; - enabled: PropTypes.Requireable>; - getPopupContainer: PropTypes.Requireable<(...args: any[]) => any>; - }>>>; - let confirm: PropTypes.Requireable; - cancelText: PropTypes.Requireable; - okText: PropTypes.Requireable; - okType: PropTypes.Requireable; - placement: PropTypes.Requireable; - enabled: PropTypes.Requireable>; - getPopupContainer: PropTypes.Requireable<(...args: any[]) => any>; - arrow: PropTypes.Requireable; - }>>>>; - }>>>; - } -} - -export { _default as auth, Button as default, useButton }; +export { _default as auth, useButton }; +export type { ButtonCate, ButtonConfirm, ButtonOption, ButtonProps, ButtonSize, ButtonTooltip, ButtonType, PlacementType, UseButtonHandlers, UseButtonProps, UseButtonReturn, UseButtonStatus, WidgetContainerProps, WidgetType }; diff --git a/button.js b/button.js index 67bf5d8..9f11199 100644 --- a/button.js +++ b/button.js @@ -1,6 +1,6 @@ -import { an as o, am as s, ao as u } from "./common/main.js"; +import { al as s, ak as u, am as e } from "./common/main.js"; export { - o as auth, - s as default, - u as useButton + s as auth, + u as default, + e as useButton }; diff --git a/common/main.js b/common/main.js index ff87db1..e1b3305 100644 --- a/common/main.js +++ b/common/main.js @@ -1,155 +1,153 @@ -var Tn = Object.defineProperty; -var yr = (t) => { +var xn = Object.defineProperty; +var mr = (t) => { throw TypeError(t); }; -var On = (t, e, r) => e in t ? Tn(t, e, { enumerable: !0, configurable: !0, writable: !0, value: r }) : t[e] = r; -var O = (t, e, r) => On(t, typeof e != "symbol" ? e + "" : e, r), wr = (t, e, r) => e.has(t) || yr("Cannot " + r); -var d = (t, e, r) => (wr(t, e, "read from private field"), r ? r.call(t) : e.get(t)), N = (t, e, r) => e.has(t) ? yr("Cannot add the same private member more than once") : e instanceof WeakSet ? e.add(t) : e.set(t, r), K = (t, e, r, n) => (wr(t, e, "write to private field"), n ? n.call(t, r) : e.set(t, r), r); -import { jsx as h, jsxs as D } from "react/jsx-runtime"; -import E, { useEffect as z, useState as V, useCallback as H, useRef as J, useContext as ue, useMemo as W, useId as Vt, isValidElement as Rn, useLayoutEffect as Fn } from "react"; -import pe from "pathe"; -import S from "prop-types"; -import j from "classnames"; -import { useNotification as jn } from "rc-notification"; -import w from "lodash"; -import { useMountedState as An, useDeepCompareEffect as Gt, useUpdateEffect as Xt, usePrevious as Ar, useAsync as br } from "react-use"; -import se, { Field as Zt, FieldContext as Ir } from "rc-field-form"; -import { _ as Cr, C as Qt, L as In, M as Ft, N as Qe, b as Ve, s as Dt, c as Ln, S as Vn } from "./vendor.js"; -import Dn from "rc-util/lib/hooks/useMergedState"; -import ie from "immutability-helper"; -import { Space as Mt, Form as yt, Input as Mn, Button as bt, Pagination as Bn, Tree as Un, Breadcrumb as Wn, Empty as Bt, Table as kr, Popover as zn, Popconfirm as qn, Tooltip as Kn, Divider as _n } from "antd"; -import { useMergedState as Jn } from "rc-util"; -import { generatePath as Hn, useInRouterContext as Lr, useParams as Yn, useLocation as Gn, createBrowserRouter as Xn, Navigate as Zn } from "react-router-dom"; -import Qn from "rc-drawer"; -import ei from "rc-dialog"; -import * as Sr from "react-is"; -var qe, tt, Ke, xe, De, Me; -class ti { +var vn = (t, e, r) => e in t ? xn(t, e, { enumerable: !0, configurable: !0, writable: !0, value: r }) : t[e] = r; +var O = (t, e, r) => vn(t, typeof e != "symbol" ? e + "" : e, r), fr = (t, e, r) => e.has(t) || mr("Cannot " + r); +var d = (t, e, r) => (fr(t, e, "read from private field"), r ? r.call(t) : e.get(t)), P = (t, e, r) => e.has(t) ? mr("Cannot add the same private member more than once") : e instanceof WeakSet ? e.add(t) : e.set(t, r), K = (t, e, r, n) => (fr(t, e, "write to private field"), n ? n.call(t, r) : e.set(t, r), r); +import { jsx as h, jsxs as j } from "react/jsx-runtime"; +import E, { useEffect as z, useState as L, useCallback as H, useRef as _, useContext as de, useMemo as W, useId as jt, isValidElement as Pn, useLayoutEffect as Nn } from "react"; +import ue from "pathe"; +import F from "classnames"; +import { useNotification as On } from "rc-notification"; +import y from "lodash"; +import { useMountedState as Rn, useDeepCompareEffect as Gt, useUpdateEffect as Yt, usePrevious as Fr, useAsync as yr } from "react-use"; +import se, { Field as Xt, FieldContext as Tr } from "rc-field-form"; +import { _ as wr, C as Zt, L as Fn, M as Rt, N as Ze, b as Le, s as Lt, c as Tn, S as In } from "./vendor.js"; +import An from "rc-util/lib/hooks/useMergedState"; +import ne from "immutability-helper"; +import { Space as Mt, Form as ft, Input as jn, Button as wt, Pagination as Ln, Tree as Mn, Breadcrumb as Dn, Empty as Dt, Table as br, Popover as Vn, Popconfirm as Un, Tooltip as Wn, Divider as Bn } from "antd"; +import { useMergedState as zn } from "rc-util"; +import { generatePath as Kn, useInRouterContext as Ir, useParams as qn, useLocation as _n, createBrowserRouter as Hn, Navigate as Jn } from "react-router-dom"; +import Gn from "prop-types"; +import Yn from "rc-drawer"; +import Xn from "rc-dialog"; +import * as Cr from "react-is"; +var ze, et, Ke, $e, Me, De; +class Zn { constructor(e, r) { - N(this, qe, /* @__PURE__ */ new Map()); - N(this, tt, !0); - N(this, Ke, []); - N(this, xe); - N(this, De, () => d(this, xe)); - N(this, Me, () => Promise.resolve()); + P(this, ze, /* @__PURE__ */ new Map()); + P(this, et, !0); + P(this, Ke, []); + P(this, $e); + P(this, Me, () => d(this, $e)); + P(this, De, () => Promise.resolve()); O(this, "get", (...e) => new Promise((r, n) => { const i = JSON.stringify(e); - if (d(this, qe).has(i)) return r(d(this, Me).call(this, d(this, xe), ...e)); - if (d(this, xe) === void 0) d(this, Ke).push([e, r, n]), d(this, tt) && (K(this, tt, !1), Promise.resolve(typeof d(this, De) == "function" ? d(this, De).call(this) : d(this, De)).then((o) => K(this, xe, o || null)).finally(() => { - d(this, Ke).forEach(([o, s, a]) => { + if (d(this, ze).has(i)) return r(d(this, De).call(this, d(this, $e), ...e)); + if (d(this, $e) === void 0) d(this, Ke).push([e, r, n]), d(this, et) && (K(this, et, !1), Promise.resolve(typeof d(this, Me) == "function" ? d(this, Me).call(this) : d(this, Me)).then((s) => K(this, $e, s || null)).finally(() => { + d(this, Ke).forEach(([s, o, a]) => { try { - const l = d(this, Me).call(this, d(this, xe), ...o); - d(this, qe).set(JSON.stringify(o), l), s(l); + const l = d(this, De).call(this, d(this, $e), ...s); + d(this, ze).set(JSON.stringify(s), l), o(l); } catch (l) { a(l); } }), d(this, Ke).length = 0; })); else { - const o = d(this, Me).call(this, d(this, xe), ...e); - d(this, qe).set(i, o), r(o); + const s = d(this, De).call(this, d(this, $e), ...e); + d(this, ze).set(i, s), r(s); } })); - K(this, Me, r), K(this, De, e); + K(this, De, r), K(this, Me, e); } } -qe = new WeakMap(), tt = new WeakMap(), Ke = new WeakMap(), xe = new WeakMap(), De = new WeakMap(), Me = new WeakMap(); -const ri = () => h("div", { children: "Empty" }), Ze = E.createContext({ ele: {}, mount: () => { +ze = new WeakMap(), et = new WeakMap(), Ke = new WeakMap(), $e = new WeakMap(), Me = new WeakMap(), De = new WeakMap(); +const Qn = () => h("div", { children: "Empty" }), Xe = E.createContext({ ele: {}, mount: () => { }, unmount: () => { -} }), re = ({ rootClassName: t, className: e, children: r, actions: n, title: i, subTitle: o, extras: s, style: a = {} }) => { - const { mount: l, unmount: c } = E.useContext(Ze); - return re.Action({ children: n }), re.Title({ children: i }), re.SubTitle({ children: o }), re.Extra({ children: s }), z(() => (l("rootClassName", t), () => c("rootClassName")), [t]), h("div", { className: j("ff-container", e), style: a, children: r }); -}, ft = (t) => ({ children: e, className: r }) => { - const { mount: n, unmount: i } = E.useContext(Ze); - return z(() => (e && n(t, E.createElement("div", { key: `ff-${t}`, className: j(`ff-popup-${t}`, r) }, e)), () => i(t)), [r, e]), null; +} }), re = ({ rootClassName: t, className: e, children: r, actions: n, title: i, subTitle: s, extras: o, style: a = {} }) => { + const { mount: l, unmount: c } = E.useContext(Xe); + return re.Action({ children: n }), re.Title({ children: i }), re.SubTitle({ children: s }), re.Extra({ children: o }), z(() => (l("rootClassName", t), () => c("rootClassName")), [t]), h("div", { className: F("ff-container", e), style: a, children: r }); +}, mt = (t) => ({ children: e, className: r }) => { + const { mount: n, unmount: i } = E.useContext(Xe); + return z(() => (e && n(t, E.createElement("div", { key: `ff-${t}`, className: F(`ff-popup-${t}`, r) }, e)), () => i(t)), [r, e]), null; }; -re.Action = ft("actions"), re.Title = ft("title"), re.SubTitle = ft("subTitle"), re.Extra = ft("extras"), re.propTypes = { className: S.string, style: S.object, title: S.any, subTitle: S.any, actions: S.any, extras: S.any }; -const Po = () => h(re, { className: "ff-loading", children: D("div", { className: "loader", children: [D("div", { className: "square", children: [h("span", {}), h("span", {}), h("span", {})] }), D("div", { className: "square", children: [h("span", {}), h("span", {}), h("span", {})] }), D("div", { className: "square", children: [h("span", {}), h("span", {}), h("span", {})] }), D("div", { className: "square", children: [h("span", {}), h("span", {}), h("span", {})] })] }) }), vo = () => h("div", { children: "NotFound" }), Vr = ({ children: t }) => { - const [e, r] = V({}), n = H((o, s) => r((a) => ({ ...a, [o]: s })), []), i = H((o) => r((s) => ({ ...s, [o]: void 0 })), []); - return typeof (t == null ? void 0 : t.type) == "string" ? t : h(Ze.Provider, { value: { ele: e, mount: n, unmount: i }, children: E.cloneElement(t, { className: e.rootClassName, title: e.title, subTitle: e.subTitle, actions: e.actions, extras: e.extras }) }); -}; -Vr.propTypes = { children: S.element.isRequired }; -const Er = { close: ["M563.8 512l262.5-312.9c4.4-5.2 0.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9c-4.4 5.2-0.7 13.1 6.1 13.1h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"], check: ["M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474c-6.1-7.7-15.3-12.2-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1 0.4-12.8-6.3-12.8z"], info: ["M512 224m-64 0a64 64 0 1 0 128 0 64 64 0 1 0-128 0Z", "M544 392h-64c-4.4 0-8 3.6-8 8v464c0 4.4 3.6 8 8 8h64c4.4 0 8-3.6 8-8V400c0-4.4-3.6-8-8-8z"] }, er = ({ type: t, props: e }) => h("i", { ...e, children: h("svg", { viewBox: "0 0 1024 1024", width: "1em", height: "1em", fill: "currentColor", children: (Er[t] || Er.info).map((r, n) => h("path", { d: r }, n)) }) }), Dr = ({ className: t, content: e, icon: r, $close: n }) => D(E.Fragment, { children: [r && h("div", { className: j("ff-notification-icon", t), children: h(er, { type: r }) }), e] }), ni = ({}) => h(re, { children: "Confirm" }); -var Oe, _e; -const ge = class ge { +re.Action = mt("actions"), re.Title = mt("title"), re.SubTitle = mt("subTitle"), re.Extra = mt("extras"); +const $s = () => h(re, { className: "ff-loading", children: j("div", { className: "loader", children: [j("div", { className: "square", children: [h("span", {}), h("span", {}), h("span", {})] }), j("div", { className: "square", children: [h("span", {}), h("span", {}), h("span", {})] }), j("div", { className: "square", children: [h("span", {}), h("span", {}), h("span", {})] }), j("div", { className: "square", children: [h("span", {}), h("span", {}), h("span", {})] })] }) }), xs = () => h("div", { children: "NotFound" }), ei = ({ children: t }) => { + const [e, r] = L({}), n = H((s, o) => r((a) => ({ ...a, [s]: o })), []), i = H((s) => r((o) => ({ ...o, [s]: void 0 })), []); + return typeof (t == null ? void 0 : t.type) == "string" ? t : h(Xe.Provider, { value: { ele: e, mount: n, unmount: i }, children: E.cloneElement(t, { className: e.rootClassName, title: e.title, subTitle: e.subTitle, actions: e.actions, extras: e.extras }) }); +}, kr = { close: ["M563.8 512l262.5-312.9c4.4-5.2 0.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9c-4.4 5.2-0.7 13.1 6.1 13.1h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"], check: ["M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474c-6.1-7.7-15.3-12.2-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1 0.4-12.8-6.3-12.8z"], info: ["M512 224m-64 0a64 64 0 1 0 128 0 64 64 0 1 0-128 0Z", "M544 392h-64c-4.4 0-8 3.6-8 8v464c0 4.4 3.6 8 8 8h64c4.4 0 8-3.6 8-8V400c0-4.4-3.6-8-8-8z"] }, Qt = ({ type: t, props: e }) => h("i", { ...e, children: h("svg", { viewBox: "0 0 1024 1024", width: "1em", height: "1em", fill: "currentColor", children: (kr[t] || kr.info).map((r, n) => h("path", { d: r }, n)) }) }), Ar = ({ className: t, content: e, icon: r, $close: n }) => j(E.Fragment, { children: [r && h("div", { className: F("ff-notification-icon", t), children: h(Qt, { type: r }) }), e] }), ti = ({}) => h(re, { children: "Confirm" }); +var Oe, qe; +const pe = class pe { constructor() { - N(this, _e, /* @__PURE__ */ new Map()); - O(this, "init", (e) => K(this, _e, new Map(e))); - O(this, "check", (e) => !d(this, _e).has(e) || d(this, _e).get(e)); - if (d(ge, Oe)) return d(ge, Oe); + P(this, qe, /* @__PURE__ */ new Map()); + O(this, "init", (e) => K(this, qe, new Map(e))); + O(this, "check", (e) => !d(this, qe).has(e) || d(this, qe).get(e)); + if (d(pe, Oe)) return d(pe, Oe); } }; -Oe = new WeakMap(), _e = new WeakMap(), N(ge, Oe, null), O(ge, "getInstance", () => (d(ge, Oe) || K(ge, Oe, new ge()), d(ge, Oe))); -let Ut = ge; -const Mr = Ut.getInstance(), ii = (t, e, r = "children") => { - if (w.isEmpty(t)) return {}; - const n = w.find(t, ["value", e]); - if (!w.isEmpty(n)) return n; +Oe = new WeakMap(), qe = new WeakMap(), P(pe, Oe, null), O(pe, "getInstance", () => (d(pe, Oe) || K(pe, Oe, new pe()), d(pe, Oe))); +let Vt = pe; +const jr = Vt.getInstance(), ri = (t, e, r = "children") => { + if (y.isEmpty(t)) return {}; + const n = y.find(t, ["value", e]); + if (!y.isEmpty(n)) return n; const i = t.length; - for (let o = 0; o < i; o++) { - const { [r]: s } = t[o], a = ii(s, e, r); - if (!w.isEmpty(a)) return a; + for (let s = 0; s < i; s++) { + const { [r]: o } = t[s], a = ri(o, e, r); + if (!y.isEmpty(a)) return a; } return {}; -}, Br = (t = "Input", e = "@pkg/ff/grid-layout-forms") => t != null && t.startsWith("@") || t != null && t.startsWith("blob:") ? t : `${e}/${t}`; -var Re, rt; -const he = class he { +}, Lr = (t = "Input", e = "@pkg/ff/grid-layout-forms") => t != null && t.startsWith("@") || t != null && t.startsWith("blob:") ? t : `${e}/${t}`; +var Re, tt; +const ge = class ge { constructor() { - N(this, rt, null); - O(this, "init", (e) => K(this, rt, e)); - O(this, "get", (e, r) => w.get(d(this, rt), e, r)); - if (d(he, Re)) return d(he, Re); + P(this, tt, null); + O(this, "init", (e) => K(this, tt, e)); + O(this, "get", (e, r) => y.get(d(this, tt), e, r)); + if (d(ge, Re)) return d(ge, Re); } }; -Re = new WeakMap(), rt = new WeakMap(), N(he, Re, null), O(he, "getInstance", () => (d(he, Re) || K(he, Re, new he()), d(he, Re))); -let Wt = he; -const We = Wt.getInstance(); -var Je, St, nt, it, Et; -const Te = class Te { +Re = new WeakMap(), tt = new WeakMap(), P(ge, Re, null), O(ge, "getInstance", () => (d(ge, Re) || K(ge, Re, new ge()), d(ge, Re))); +let Ut = ge; +const We = Ut.getInstance(); +var _e, Ct, rt, nt, kt; +const Ne = class Ne { constructor(...e) { - N(this, nt, []); - N(this, it, (e) => { + P(this, rt, []); + P(this, nt, (e) => { var r; - for (let n of e) Array.isArray(n[0]) ? d(this, it).call(this, n) : d(this, nt).push(d(r = Te, St).call(r, n[0], n[1])); + for (let n of e) Array.isArray(n[0]) ? d(this, nt).call(this, n) : d(this, rt).push(d(r = Ne, Ct).call(r, n[0], n[1])); }); O(this, "toValue", async (e, r = null) => { const n = { getValue: () => e, getRecord: () => r }; let i = e; - for (const o of d(this, nt)) try { - const s = await o; - if (typeof s != "function") { - console.warn("middleware is not a function, skip:", s); + for (const s of d(this, rt)) try { + const o = await s; + if (typeof o != "function") { + console.warn("middleware is not a function, skip:", o); continue; } - i = await s.call(n, i); - } catch (s) { - console.error("middleware error, skip:", s); + i = await o.call(n, i); + } catch (o) { + console.error("middleware error, skip:", o); } return i; }); - O(this, "toRender", (e, r, n = null) => E.createElement(d(this, Et), { value: e, record: r }, n)); - N(this, Et, ({ value: e, record: r, children: n }) => { - const [i, o] = V(n), s = An(); + O(this, "toRender", (e, r, n = null) => E.createElement(d(this, kt), { value: e, record: r }, n)); + P(this, kt, ({ value: e, record: r, children: n }) => { + const [i, s] = L(n), o = Rn(); return Gt(() => { - o(n), this.toValue(e, r).then((a) => s() && o(a)).catch((a) => s() && o(`${a}`)); + s(n), this.toValue(e, r).then((a) => o() && s(a)).catch((a) => o() && s(`${a}`)); }, [e, r]), i; }); - d(this, it).call(this, e); + d(this, nt).call(this, e); } }; -Je = new WeakMap(), St = new WeakMap(), nt = new WeakMap(), it = new WeakMap(), Et = new WeakMap(), N(Te, Je, null), N(Te, St, w.memoize((e, r) => { +_e = new WeakMap(), Ct = new WeakMap(), rt = new WeakMap(), nt = new WeakMap(), kt = new WeakMap(), P(Ne, _e, null), P(Ne, Ct, y.memoize((e, r) => { if (typeof e == "function") return e(r); if (typeof e == "string") return X.getWidgetComponent(e).then((n) => { var i; - return ((i = n.default) == null ? void 0 : i.call(n, r)) || ((o) => o); + return ((i = n.default) == null ? void 0 : i.call(n, r)) || ((s) => s); }); throw new TypeError("middleware must be a string or a function"); }, (...e) => { var r; - return d(Te, Je) || K(Te, Je, Fi()), d(r = Te, Je).call(r, ...e); + return d(Ne, _e) || K(Ne, _e, Fi()), d(r = Ne, _e).call(r, ...e); })); -let Ct = Te; -const ae = E.createContext({ listCode: "", classNames: {}, getBase62params: (t, e) => { +let bt = Ne; +const oe = E.createContext({ listCode: "", classNames: {}, getBase62params: (t, e) => { }, getSelectedRows: () => [], onReload: () => { }, onClickCallback: () => { }, onConditionChange: () => { @@ -165,416 +163,407 @@ const ae = E.createContext({ listCode: "", classNames: {}, getBase62params: (t, }, setSider: () => { }, setKeyword: () => { }, setCondition: () => { -} }), $r = ({ className: t, record: e, column: r, ...n }) => { +} }), Er = ({ className: t, record: e, column: r, ...n }) => { if (r != null && r.editableByJs && (r != null && r.uuid)) { - const { formSetting: i = { primaryKey: "id" }, widgetSetting: o = {}, widgetContainerSetting: s = {} } = (r == null ? void 0 : r.editableByJsSetting) || {}; - return h(R.Popover, { widget: Ur, widgetData: { record: e, column: r }, widgetSetting: { widgetSetting: o, formSetting: i }, widgetContainerProps: { title: r != null && r.title ? `${r.title} - 编辑` : "编辑", width: 260, zIndex: 1050, arrow: !0, ...s }, children: h("td", { className: j("ff-data-list-cell-editable", t), ...n }) }); + const { formSetting: i = { primaryKey: "id" }, widgetSetting: s = {}, widgetContainerSetting: o = {} } = (r == null ? void 0 : r.editableByJsSetting) || {}; + return h(V.Popover, { widget: Mr, widgetData: { record: e, column: r }, widgetSetting: { widgetSetting: s, formSetting: i }, widgetContainerProps: { title: r != null && r.title ? `${r.title} - 编辑` : "编辑", width: 260, zIndex: 1050, arrow: !0, ...o }, children: h("td", { className: F("ff-data-list-cell-editable", t), ...n }) }); } return h("td", { className: t, ...n }); -}, Ur = ({ record: t, column: e, $close: r, $setting: n }) => { - const i = J(Oi(w.get(t, e == null ? void 0 : e.dataIndex))), { listCode: o, onClickCallback: s } = ue(ae), [a] = se.useForm(), { formSetting: l, widgetSetting: c } = n, { primaryKey: u = "id", help: p, validators: m } = l || {}, g = () => { - a.setFieldsValue({ value: w.get(t, e == null ? void 0 : e.dataIndex), __PROPS__: t }); +}, Mr = ({ record: t, column: e, $close: r, $setting: n }) => { + const i = _(Oi(y.get(t, e == null ? void 0 : e.dataIndex))), { listCode: s, onClickCallback: o } = de(oe), [a] = se.useForm(), { formSetting: l, widgetSetting: c } = n, { primaryKey: u = "id", help: p, validators: m } = l || {}, g = () => { + a.setFieldsValue({ value: y.get(t, e == null ? void 0 : e.dataIndex), __PROPS__: t }); }; - return Nt(() => g(), [t, e == null ? void 0 : e.dataIndex, o]), h(re, { actions: D(E.Fragment, { children: [h(R, { size: "small", onClick: g, children: "重置" }), D(Mt.Compact, { block: !0, children: [h(R, { size: "small", widget: r, children: "取消" }), h(R, { type: "primary", size: "small", widget: () => a.validateFields().then(({ value: f }) => { - const y = w.get(t, u.substring(u.indexOf(".") + 1)); - if (!y) throw "获取更新主键失败!"; - B.put(`/api/${o}-storeBy-${e == null ? void 0 : e.uuid}/${y}`, { value: f }).msg(() => s(2, t)).then(r); - }).catch(console.warn), children: "保存" })] })] }), children: D(se, { form: a, children: [h(nr, { label: "", code: "value", type: i.current, widget: e == null ? void 0 : e.editableByJs, help: p, extras: c, validators: m }), h(Zt, { noStyle: !0, name: ["__PROPS__"], children: () => { + return Pt(() => g(), [t, e == null ? void 0 : e.dataIndex, s]), h(re, { actions: j(E.Fragment, { children: [h(V, { size: "small", onClick: g, children: "重置" }), j(Mt.Compact, { block: !0, children: [h(V, { size: "small", widget: r, children: "取消" }), h(V, { type: "primary", size: "small", widget: () => a.validateFields().then(({ value: w }) => { + const f = y.get(t, u.substring(u.indexOf(".") + 1)); + if (!f) throw "获取更新主键失败!"; + U.put(`/api/${s}-storeBy-${e == null ? void 0 : e.uuid}/${f}`, { value: w }).msg(() => o(2, t)).then(r); + }).catch(console.warn), children: "保存" })] })] }), children: j(se, { form: a, children: [h(rr, { label: "", code: "value", type: i.current, widget: e == null ? void 0 : e.editableByJs, help: p, extras: c, validators: m }), h(Xt, { noStyle: !0, name: ["__PROPS__"], children: () => { } })] }) }); }; -Ur.displayName = "DataListCellEditableContainer"; -const oi = (t) => function(e) { +Mr.displayName = "DataListCellEditableContainer"; +const ni = (t) => function(e) { return t(e, getRecord()); -}, si = async ({ widgetByJs: t, widgetByJsSetting: e }) => { +}, ii = async ({ widgetByJs: t, widgetByJsSetting: e }) => { const r = await X.getWidgetComponent(t).then((n) => n.default || ((i) => i)); return function(n) { return h(r, { value: n, $setting: e }); }; -}, ai = (t, e = {}) => W(() => { +}, si = (t, e = {}) => W(() => { var r; - return (r = t == null ? void 0 : t.filter(Boolean)) == null ? void 0 : r.map(({ widgetByJs: n, widgetByJsSetting: i, middlewares: o, ...s }, a) => { - const l = (c) => ({ record: c, column: s }); - return o || (o = []), n && o.push([si, { widgetByJs: n, widgetByJsSetting: i }]), o.length > 0 ? (s != null && s.render && o.push([oi, s.render]), { ...s, onCell: l, render: (c, u) => new Ct(o).toRender(c, u, "-") }) : { ...s, onCell: l }; + return (r = t == null ? void 0 : t.filter(Boolean)) == null ? void 0 : r.map(({ widgetByJs: n, widgetByJsSetting: i, middlewares: s, ...o }, a) => { + const l = (c) => ({ record: c, column: o }); + return s || (s = []), n && s.push([ii, { widgetByJs: n, widgetByJsSetting: i }]), s.length > 0 ? (o != null && o.render && s.push([ni, o.render]), { ...o, onCell: l, render: (c, u) => new bt(s).toRender(c, u, "-") }) : { ...o, onCell: l }; }); -}, [t, e]), li = (t = {}) => W(() => { +}, [t, e]), oi = (t = {}) => W(() => { var e; - return t.body ?? (t.body = { cell: $r }), (e = t.body).cell ?? (e.cell = $r), t; -}, [t]), No = (t) => { - const [e, r] = V({}); - return z(() => { - let n = !1; - return t && B.get(`/api/_/${t}`).then((i) => w.pick(i, ["uuid", "name", "code", "resource", "marginX", "marginY", "cols", "rowHeight", "primaryKey", "columns", "itemOperations", "batchOperations", "isConditionFormLayout", "layout", "tabs", "pageSize", "layoutConfig", "selectionType"])).then((i) => !n && r(i)), () => n = !0; - }, [t]), e; -}, To = (t, e = {}) => { - const [r, n] = V({ dataSource: [] }); - return gt(() => { - let i = !1; - return t && B.get(`/api/${t}/${B.encode({ page: 1, ...e })}`).then((o) => !i && n(o)), () => i = !0; - }, [t, e]), r; -}, Wr = (t = [], e = /* @__PURE__ */ new Map(), r = "id", n) => { - const i = H(n ? (o) => w.get(o, r, w.get(o, [n, r])) : (o) => w.get(o, r), [r, n]); - return H((o) => t == null ? void 0 : t.filter((s) => !s.uuid || !e.has(s.uuid) || e.get(s.uuid).some((a) => a == i(o))), [t, e, i]); -}, zt = (t = [], e = /* @__PURE__ */ new Map(), r = [], n = "id", i) => { - const o = H(i ? (s) => w.get(s, n, w.get(s, [i, n])) : (s) => w.get(s, n), [n, i]); + return t.body ?? (t.body = { cell: Er }), (e = t.body).cell ?? (e.cell = Er), t; +}, [t]), Dr = (t = [], e = /* @__PURE__ */ new Map(), r = "id", n) => { + const i = H(n ? (s) => y.get(s, r, y.get(s, [n, r])) : (s) => y.get(s, r), [r, n]); + return H((s) => t == null ? void 0 : t.filter((o) => !o.uuid || !e.has(o.uuid) || e.get(o.uuid).some((a) => a == i(s))), [t, e, i]); +}, Wt = (t = [], e = /* @__PURE__ */ new Map(), r = [], n = "id", i) => { + const s = H(i ? (o) => y.get(o, n, y.get(o, [i, n])) : (o) => y.get(o, n), [n, i]); return W(() => { - if (w.isEmpty(t) || !t.some(({ uuid: a }) => Mr.check(a))) return !1; - if (w.isEmpty(e) || w.isEmpty(r)) return !0; - const s = r.map((a) => o(a)); - return t.some(({ uuid: a }) => !a || !e.has(a) || e.get(a).some((l) => s.some((c) => c == l))); - }, [t, r, e, o]); -}, ci = (t, e, r = "id", n = null) => { - const i = vt(), o = J(!1), s = J(t.dataSource), a = J(t.itemOperationsAccess); - return z(() => (s.current = t.dataSource, a.current = t.itemOperationsAccess, () => o.current = !1), [t.dataSource, t.itemOperationsAccess]), o.current && (t.dataSource = s.current, t.itemOperationsAccess = a.current), [t, (l = 0, c = null) => { + if (y.isEmpty(t) || !t.some(({ uuid: a }) => jr.check(a))) return !1; + if (y.isEmpty(e) || y.isEmpty(r)) return !0; + const o = r.map((a) => s(a)); + return t.some(({ uuid: a }) => !a || !e.has(a) || e.get(a).some((l) => o.some((c) => c == l))); + }, [t, r, e, s]); +}, ai = (t, e, r = "id", n = null) => { + const i = xt(), s = _(!1), o = _(t.dataSource), a = _(t.itemOperationsAccess); + return z(() => (o.current = t.dataSource, a.current = t.itemOperationsAccess, () => s.current = !1), [t.dataSource, t.itemOperationsAccess]), s.current && (t.dataSource = o.current, t.itemOperationsAccess = a.current), [t, (l = 0, c = null) => { var u, p; - if (o.current = !1, l === 1) return (u = t.onReload) == null ? void 0 : u.call(t); + if (s.current = !1, l === 1) return (u = t.onReload) == null ? void 0 : u.call(t); if (l === 2) { - const m = w.get(c, "__PARENT_ID__", ""), g = w.get(c, r, w.get(c, [n, r], "")), f = w.findIndex(s.current, ["__PARENT_ID__", m]), y = w.findIndex(f > -1 ? w.get(s.current, [f, "children"]) : s.current, [r, g]); - if (y === -1) return (p = t.onReload) == null ? void 0 : p.call(t); - Promise.all([B.get(`/api/${e}/detail/${g}`), B.post(`/api/${e}/list-operations-access`, { ids: g })]).then(([k, b]) => { - const $ = w.get(s.current, f > -1 ? [f, "children", y, "children"] : [y, "children"]); - s.current = ie(s.current, f > -1 ? { [f]: { children: { $splice: [[y, 1, { ...k, children: $ }]] } } } : { $splice: [[y, 1, { ...k, children: $ }]] }); - const C = new Map(b); - a.current.forEach((x, F) => { + const m = y.get(c, "__PARENT_ID__", ""), g = y.get(c, r, y.get(c, [n, r], "")), w = y.findIndex(o.current, ["__PARENT_ID__", m]), f = y.findIndex(w > -1 ? y.get(o.current, [w, "children"]) : o.current, [r, g]); + if (f === -1) return (p = t.onReload) == null ? void 0 : p.call(t); + Promise.all([U.get(`/api/${e}/detail/${g}`), U.post(`/api/${e}/list-operations-access`, { ids: g })]).then(([C, b]) => { + const S = y.get(o.current, w > -1 ? [w, "children", f, "children"] : [f, "children"]); + o.current = ne(o.current, w > -1 ? { [w]: { children: { $splice: [[f, 1, { ...C, children: S }]] } } } : { $splice: [[f, 1, { ...C, children: S }]] }); + const k = new Map(b); + a.current.forEach(($, R) => { var I; - (I = C.get(F)) != null && I.some((T) => T == g) || a.current.set(F, x.filter((T) => T !== g)); - }), C.forEach((x, F) => { - a.current.has(F) ? a.current.set(F, w.uniq([...a.current.get(F) || [], ...x])) : a.current.set(F, x); + (I = k.get(R)) != null && I.some((N) => N == g) || a.current.set(R, $.filter((N) => N !== g)); + }), k.forEach(($, R) => { + a.current.has(R) ? a.current.set(R, y.uniq([...a.current.get(R) || [], ...$])) : a.current.set(R, $); }); }).then(() => { - o.current = !0, i(); + s.current = !0, i(); }); } }]; -}, di = (t, e) => { - const r = vt(), n = J(e), i = J(/* @__PURE__ */ new Map()), o = J([]), s = w.throttle((l) => { - o.current = [], B.list(t, w.pick({ ...n.current, ...l }, ["tab", "page", "pageSize", "condition", "sider", "keyword"])).then(({ keyword: c, condition: u, total: p, tab: m, sider: g, page: f, pageSize: y, operationsAccess: k, dataSource: b }) => { - n.current = { tab: m, condition: u, sider: g, keyword: c, total: p, pageSize: y, page: b != null && b.length ? f : 1 }, o.current = b, i.current = new Map(k), r(); +}, li = (t, e) => { + const r = xt(), n = _(e), i = _(/* @__PURE__ */ new Map()), s = _([]), o = y.throttle((l) => { + s.current = [], U.list(t, y.pick({ ...n.current, ...l }, ["tab", "page", "pageSize", "condition", "sider", "keyword"])).then(({ keyword: c, condition: u, total: p, tab: m, sider: g, page: w, pageSize: f, operationsAccess: C, dataSource: b }) => { + n.current = { tab: m, condition: u, sider: g, keyword: c, total: p, pageSize: f, page: b != null && b.length ? w : 1 }, s.current = b, i.current = new Map(C), r(); }); }, 380, { leading: !1, trailing: !0 }); - Nt(() => { - o.current = [], t && s(e); + Pt(() => { + s.current = [], t && o(e); }, [t, e]); - const a = W(() => w.pick(n.current, ["total", "tab", "page", "pageSize", "condition", "sider", "keyword", "primaryKey"]), [n.current]); - return Object.assign(a, { onTabChange: (l) => s({ tab: l, page: 1 }), onPageChange: (l, c) => s({ page: l, pageSize: c }), onPageSizeChange: (l) => s({ pageSize: l, page: 1 }), onConditionChange: (l, c) => s({ keyword: c, condition: ie(n.current.condition || {}, { $merge: l || {} }), page: 1 }), onSiderChange: (l) => s({ sider: l, page: 1 }), onKeywordChange: (l) => s({ keyword: l, page: 1 }), itemOperationsAccess: i.current, dataSource: o.current, onReload: s, payload: e == null ? void 0 : e.payload }); -}, ui = ({ listCode: t, className: e, layouts: r = {}, dataSource: n, isPaginate: i, isItemOperations: o, isBatchOperations: s, batchOperations: a, itemOperations: l, itemOperationsAccess: c, resource: u, primaryKey: p, title: m, itemGridLayout: g, $setting: f, tabs: y, isConditionFormLayout: k, isTreeSider: b, treeSiderConfig: $, rowSelection: C }) => { - const { classNames: x, onClickCallback: F } = ue(ae), I = w.pick(f, ["column", "colWidth", "beforeRender", "afterRender", "style", "itemMargin", "containerPadding"]), T = f == null ? void 0 : f.isMarkSelected, v = Wr(l, c, p, u), A = H((P, L, M) => h(pi, { isMarkSelected: T, className: j("ff-data-list-framework-item", x == null ? void 0 : x.item), operations: o ? v(L) : [], data: u ? { [u]: L } : L, children: P, onClickCallback: F }), [T, u, p, o, F, l, c]); - return D("div", { className: j("ff-data-list-framework", e), children: [h(r.sider, { isTreeSider: b, ...$ }), D("div", { className: j("ff-data-list-container", x == null ? void 0 : x.container), children: [h(r.filter, { isConditionFormLayout: k }), h(r.toolbar, { title: m, tabs: y }), h(Pi, { ...g, ...I, rowSelection: C, empty: h(r.empty, { className: x == null ? void 0 : x.empty }), primaryKey: p, itemRender: A, dataSource: n }), h(r.footer, { isPaginate: i, isOperations: s, operations: a })] })] }); -}, pi = ({ className: t, operations: e, children: r, data: n, onClickCallback: i, onSelect: o, isMarkSelected: s, isSelected: a, selectionType: l }) => D("div", { className: j("data-list-grid-layout-item", { "is-mark-selected": s, "is-selected": a, "is-selectable": !!l }, t), onClick: o, children: [h("div", { className: "data-list-grid-layout-item-container", children: r }), !!(e != null && e.length) && h("div", { className: "data-list-grid-layout-item-actions", children: e.map((c) => h("span", { className: "data-list-grid-layout-item-action", children: h(R.Link, { uuid: c.uuid, type: c.type, name: c.name, widget: c.widget, widgetType: c.widgetType, widgetProps: c.widgetProps, widgetSetting: c.widgetSetting, widgetContainerProps: c.widgetContainerSetting, data: n, confirm: c.confirm, onAfterClick: (u) => u !== !1 && (i == null ? void 0 : i(c.isRefresh, n)) }, c.uuid || Vt()) }, (c == null ? void 0 : c.uuid) || Vt())) })] }), gi = ({ listCode: t, className: e, layouts: r = {}, dataSource: n, columns: i, isItemOperations: o, isBatchOperations: s, batchOperations: a, itemOperations: l, itemOperationsAccess: c, resource: u, primaryKey: p, title: m, tabs: g, isPaginate: f, rowSelection: y, isTreeSider: k, treeSiderConfig: b, isConditionFormLayout: $, ...C }) => { - const { classNames: x, onClickCallback: F } = ue(ae), I = Wr(l, c, p, u), T = zt(l, c, n, p, u); - return D("div", { className: j("ff-data-table-framework", e), children: [h(r.sider, { isTreeSider: k, ...b }), D("div", { className: j("ff-data-table-container", x == null ? void 0 : x.container), children: [h(r.filter, { isConditionFormLayout: $ }), h(r.toolbar, { title: m, tabs: g }), h(Ci, { ...C, primaryKey: p, className: "ff-data-table-content", columns: i, dataSource: n, rowSelection: y, operationRender: T ? (v) => { - var A; - return h("div", { className: "ff-data-table-actions", children: (A = I(v)) == null ? void 0 : A.map((P, L) => h(R, { size: "small", uuid: P.uuid, type: P.type, name: P.name, widget: P.widget, widgetType: P.widgetType, widgetProps: P.widgetProps, widgetData: P.widgetData, widgetSetting: P.widgetSetting, widgetContainerProps: P.widgetContainerSetting, data: v, confirm: P.confirm, onAfterClick: (M) => M !== !1 && (F == null ? void 0 : F(P.isRefresh, v)) }, P.uuid || L)) }); - } : null }), h(r.footer, { isPaginate: f, isOperations: s, operations: a })] })] }); -}, tr = (t = [], e, r = null) => { + const a = W(() => y.pick(n.current, ["total", "tab", "page", "pageSize", "condition", "sider", "keyword", "primaryKey"]), [n.current]); + return Object.assign(a, { onTabChange: (l) => o({ tab: l, page: 1 }), onPageChange: (l, c) => o({ page: l, pageSize: c }), onPageSizeChange: (l) => o({ pageSize: l, page: 1 }), onConditionChange: (l, c) => o({ keyword: c, condition: ne(n.current.condition || {}, { $merge: l || {} }), page: 1 }), onSiderChange: (l) => o({ sider: l, page: 1 }), onKeywordChange: (l) => o({ keyword: l, page: 1 }), itemOperationsAccess: i.current, dataSource: s.current, onReload: o, payload: e == null ? void 0 : e.payload }); +}, ci = ({ listCode: t, className: e, layouts: r = {}, dataSource: n, isPaginate: i, isItemOperations: s, isBatchOperations: o, batchOperations: a, itemOperations: l, itemOperationsAccess: c, resource: u, primaryKey: p, title: m, itemGridLayout: g, $setting: w, tabs: f, isConditionFormLayout: C, isTreeSider: b, treeSiderConfig: S, rowSelection: k }) => { + const { classNames: $, onClickCallback: R } = de(oe), I = y.pick(w, ["column", "colWidth", "beforeRender", "afterRender", "style", "itemMargin", "containerPadding"]), N = w == null ? void 0 : w.isMarkSelected, v = Dr(l, c, p, u), T = H((x, A, M) => h(di, { isMarkSelected: N, className: F("ff-data-list-framework-item", $ == null ? void 0 : $.item), operations: s ? v(A) : [], data: u ? { [u]: A } : A, children: x, onClickCallback: R }), [N, u, p, s, R, l, c]); + return j("div", { className: F("ff-data-list-framework", e), children: [h(r.sider, { isTreeSider: b, ...S }), j("div", { className: F("ff-data-list-container", $ == null ? void 0 : $.container), children: [h(r.filter, { isConditionFormLayout: C }), h(r.toolbar, { title: m, tabs: f }), h(xi, { ...g, ...I, rowSelection: k, empty: h(r.empty, { className: $ == null ? void 0 : $.empty }), primaryKey: p, itemRender: T, dataSource: n }), h(r.footer, { isPaginate: i, isOperations: o, operations: a })] })] }); +}, di = ({ className: t, operations: e, children: r, data: n, onClickCallback: i, onSelect: s, isMarkSelected: o, isSelected: a, selectionType: l }) => j("div", { className: F("data-list-grid-layout-item", { "is-mark-selected": o, "is-selected": a, "is-selectable": !!l }, t), onClick: s, children: [h("div", { className: "data-list-grid-layout-item-container", children: r }), !!(e != null && e.length) && h("div", { className: "data-list-grid-layout-item-actions", children: e.map((c) => h("span", { className: "data-list-grid-layout-item-action", children: h(V.Link, { uuid: c.uuid, type: c.type, name: c.name, widget: c.widget, widgetType: c.widgetType, widgetProps: c.widgetProps, widgetSetting: c.widgetSetting, widgetContainerProps: c.widgetContainerSetting, data: n, confirm: c.confirm, onAfterClick: (u) => u !== !1 && (i == null ? void 0 : i(c.isRefresh, n)) }, c.uuid || jt()) }, (c == null ? void 0 : c.uuid) || jt())) })] }), ui = ({ listCode: t, className: e, layouts: r = {}, dataSource: n, columns: i, isItemOperations: s, isBatchOperations: o, batchOperations: a, itemOperations: l, itemOperationsAccess: c, resource: u, primaryKey: p, title: m, tabs: g, isPaginate: w, rowSelection: f, isTreeSider: C, treeSiderConfig: b, isConditionFormLayout: S, ...k }) => { + const { classNames: $, onClickCallback: R } = de(oe), I = Dr(l, c, p, u), N = Wt(l, c, n, p, u); + return j("div", { className: F("ff-data-table-framework", e), children: [h(r.sider, { isTreeSider: C, ...b }), j("div", { className: F("ff-data-table-container", $ == null ? void 0 : $.container), children: [h(r.filter, { isConditionFormLayout: S }), h(r.toolbar, { title: m, tabs: g }), h(bi, { ...k, primaryKey: p, className: "ff-data-table-content", columns: i, dataSource: n, rowSelection: f, operationRender: N ? (v) => { + var T; + return h("div", { className: "ff-data-table-actions", children: (T = I(v)) == null ? void 0 : T.map((x, A) => h(V, { size: "small", uuid: x.uuid, type: x.type, name: x.name, widget: x.widget, widgetType: x.widgetType, widgetProps: x.widgetProps, widgetData: x.widgetData, widgetSetting: x.widgetSetting, widgetContainerProps: x.widgetContainerSetting, data: v, confirm: x.confirm, onAfterClick: (M) => M !== !1 && (R == null ? void 0 : R(x.isRefresh, v)) }, x.uuid || A)) }); + } : null }), h(r.footer, { isPaginate: w, isOperations: o, operations: a })] })] }); +}, er = (t = [], e, r = null) => { var n; - return (n = w.sortBy(t, ["y", "x"])) == null ? void 0 : n.map(({ i, x: o, y: s, w: a, h: l, field: { boxStyle: c, ...u } = {} }, p) => h("div", { className: "grid-layout-item", style: zr(o, s, a, l, c), children: h(e, { ...u, basicForm: r }) }, i ?? p)); -}, zr = (t, e, r, n, i = {}, o = 0) => { - const s = { "--grid-layout-h": `${n}`, "--grid-layout-w": `${r}`, "--grid-layout-x": `${t}`, "--grid-layout-y": `${e}`, "--grid-layout-row-height-offset": "0px" }; - return i != null && i.autoHeight ? s.height = "fit-content" : s["--grid-layout-row"] = `${n}`, i != null && i.alignItems && (s["--grid-layout-box-align-items"] = i.alignItems), i != null && i.justifyContent && (s["--grid-layout-box-justify-content"] = i.justifyContent), s["--grid-layout-box-margin"] = xr(i == null ? void 0 : i.marginTop, i == null ? void 0 : i.marginRight, i == null ? void 0 : i.marginBottom, i == null ? void 0 : i.marginLeft), s["--grid-layout-box-padding"] = xr(i == null ? void 0 : i.paddingTop, i == null ? void 0 : i.paddingRight, i == null ? void 0 : i.paddingBottom, i == null ? void 0 : i.paddingLeft), o && (s.height = `${o}px`), s; -}, xr = (t, e, r, n) => `${t || 0}px ${e || 0}px ${r || 0}px ${n || 0}px`, Oo = (t = "Text", e = "@pkg/ff/grid-layouts") => t != null && t.startsWith("@") || t != null && t.startsWith("blob:") ? t : `${e}/${t}`, qr = (t) => Object.keys(t).reduce((e, r) => (/^on[A-Z]/.test(r) && (e[r] = t[r]), e), {}), Kr = ({ className: t, isConditionFormLayout: e }) => { + return (n = y.sortBy(t, ["y", "x"])) == null ? void 0 : n.map(({ i, x: s, y: o, w: a, h: l, field: { boxStyle: c, ...u } = {} }, p) => h("div", { className: "grid-layout-item", style: Vr(s, o, a, l, c), children: h(e, { ...u, basicForm: r }) }, i ?? p)); +}, Vr = (t, e, r, n, i = {}, s = 0) => { + const o = { "--grid-layout-h": `${n}`, "--grid-layout-w": `${r}`, "--grid-layout-x": `${t}`, "--grid-layout-y": `${e}`, "--grid-layout-row-height-offset": "0px" }; + return i != null && i.autoHeight ? o.height = "fit-content" : o["--grid-layout-row"] = `${n}`, i != null && i.alignItems && (o["--grid-layout-box-align-items"] = i.alignItems), i != null && i.justifyContent && (o["--grid-layout-box-justify-content"] = i.justifyContent), o["--grid-layout-box-margin"] = Sr(i == null ? void 0 : i.marginTop, i == null ? void 0 : i.marginRight, i == null ? void 0 : i.marginBottom, i == null ? void 0 : i.marginLeft), o["--grid-layout-box-padding"] = Sr(i == null ? void 0 : i.paddingTop, i == null ? void 0 : i.paddingRight, i == null ? void 0 : i.paddingBottom, i == null ? void 0 : i.paddingLeft), s && (o.height = `${s}px`), o; +}, Sr = (t, e, r, n) => `${t || 0}px ${e || 0}px ${r || 0}px ${n || 0}px`, vs = (t = "Text", e = "@pkg/ff/grid-layouts") => t != null && t.startsWith("@") || t != null && t.startsWith("blob:") ? t : `${e}/${t}`, Ur = (t) => Object.keys(t).reduce((e, r) => (/^on[A-Z]/.test(r) && (e[r] = t[r]), e), {}), Wr = ({ className: t, isConditionFormLayout: e }) => { var m, g; - const [r, n] = V({}), { listCode: i, onKeywordChange: o, onConditionChange: s, getBase62params: a, classNames: l } = E.useContext(ae), { keyword: c, condition: u } = (a == null ? void 0 : a()) || {}, [p] = yt.useForm(); + const [r, n] = L({}), { listCode: i, onKeywordChange: s, onConditionChange: o, getBase62params: a, classNames: l } = E.useContext(oe), { keyword: c, condition: u } = (a == null ? void 0 : a()) || {}, [p] = ft.useForm(); return z(() => { - i && e && B.get(`/api/_/${i}/list-condition-form-layout`).then(({ resource: f, marginX: y, marginY: k, rowHeight: b, cols: $, fields: C }) => { - n({ resource: f, itemMargin: [y, k], rowHeight: b, cols: $, fields: C }); + i && e && U.get(`/api/_/${i}/list-condition-form-layout`).then(({ resource: w, marginX: f, marginY: C, rowHeight: b, cols: S, fields: k }) => { + n({ resource: w, itemMargin: [f, C], rowHeight: b, cols: S, fields: k }); }).catch(() => n({})); }, [i, e]), z(() => { p.setFieldsValue({ keyword: c, ...u }); - }, [JSON.stringify([c, u])]), h("div", { className: j("ff-data-list-filter", l.filter, t), children: h(yt, { form: p, layout: "vertical", autoComplete: "off", onFinish: ((m = r.fields) == null ? void 0 : m.length) > 1 ? (f) => s({ [r.resource]: f[r.resource] }, f.keyword) : () => { - }, onValuesChange: (f) => { - w.isEmpty(w.omit(f, ["keyword"])) || p.submit(); - }, children: ((g = r.fields) == null ? void 0 : g.length) > 1 ? h(ir, { ...r, children: h(hi, { onReset: () => { - const { keyword: f, condition: y } = a("init") || {}; - p.setFieldsValue({ keyword: f, ...y }); - } }) }) : h("div", { className: "ff-data-list-filter-default-form ff-grid-layout-form", children: h("div", { className: "grid-layout-item", style: zr(20, 0, 5, 2), children: h(yt.Item, { name: ["keyword"], children: h(Mn.Search, { allowClear: !0, enterButton: "搜索", placeholder: "多关键字 | 分割", onSearch: (f) => o(f) }) }) }) }) }) }); -}, hi = ({ cols: t, fields: e, onReset: r }) => { - const [n, i] = V(!1), o = W(() => e == null ? void 0 : e.toReversed().some((s) => s.y > 1 || s.x + s.w >= t - 5), [t, e]); - return D(yt.Item, { label: " ", style: { "--item-span": 5 }, className: j("ff-data-list-filter-actions", { expanded: n }), children: [h(bt, { onClick: r, children: "重置" }), h(bt, { type: "primary", htmlType: "submit", children: "查询" }), o && h(R.Link, { className: "ff-data-list-filter-expanded-button", widget: () => i((s) => !s), type: "primary", name: n ? "关闭" : "展开", icon: n ? "icon-up" : "icon-down", iconPosition: "end" })] }); + }, [JSON.stringify([c, u])]), h("div", { className: F("ff-data-list-filter", l.filter, t), children: h(ft, { form: p, layout: "vertical", autoComplete: "off", onFinish: ((m = r.fields) == null ? void 0 : m.length) > 1 ? (w) => o({ [r.resource]: w[r.resource] }, w.keyword) : () => { + }, onValuesChange: (w) => { + y.isEmpty(y.omit(w, ["keyword"])) || p.submit(); + }, children: ((g = r.fields) == null ? void 0 : g.length) > 1 ? h(Qr, { ...r, children: h(pi, { onReset: () => { + const { keyword: w, condition: f } = a("init") || {}; + p.setFieldsValue({ keyword: w, ...f }); + } }) }) : h("div", { className: "ff-data-list-filter-default-form ff-grid-layout-form", children: h("div", { className: "grid-layout-item", style: Vr(20, 0, 5, 2), children: h(ft.Item, { name: ["keyword"], children: h(jn.Search, { allowClear: !0, enterButton: "搜索", placeholder: "多关键字 | 分割", onSearch: (w) => s(w) }) }) }) }) }) }); +}, pi = ({ cols: t, fields: e, onReset: r }) => { + const [n, i] = L(!1), s = W(() => e == null ? void 0 : e.toReversed().some((o) => o.y > 1 || o.x + o.w >= t - 5), [t, e]); + return j(ft.Item, { label: " ", style: { "--item-span": 5 }, className: F("ff-data-list-filter-actions", { expanded: n }), children: [h(wt, { onClick: r, children: "重置" }), h(wt, { type: "primary", htmlType: "submit", children: "查询" }), s && h(V.Link, { className: "ff-data-list-filter-expanded-button", widget: () => i((o) => !o), type: "primary", name: n ? "关闭" : "展开", icon: n ? "icon-up" : "icon-down", iconPosition: "end" })] }); }; -Kr.reservedFields = [{ x: 0, y: 0, h: 3, w: 5, field: { isVirtual: !0, widgetPrefix: "@pkg/ff/grid-layout-forms", widget: "Input", code: "keyword", label: "关键字", placeholder: "多关键字 | 分割", extras: { prefix: "icon-search" } } }]; -const mi = ({ className: t, operations: e, isOperations: r, isPaginate: n }) => { - const { onPageChange: i, onPageSizeChange: o, onClickCallback: s, getBase62params: a } = E.useContext(ae), { total: l, page: c, pageSize: u } = (a == null ? void 0 : a()) || {}; - return r && !w.isEmpty(e) || n ? D("div", { className: j("ff-data-list-footer", t), children: [h("div", { className: "ff-data-list-actions", children: e == null ? void 0 : e.map((p, m) => h(R, { uuid: p.uuid, type: p.type, name: p.name, widget: p.widget, widgetType: p.widgetType, widgetProps: p.widgetProps, widgetData: p.widgetData, widgetSetting: p.widgetSetting, widgetContainerProps: p.widgetContainerSetting, onAfterClick: (g) => g !== !1 && (s == null ? void 0 : s(p.isRefresh, null)) }, p.uuid || m)) }), n && h(Bn, { size: "small", total: l, pageSize: u, showSizeChanger: !1, showTotal: (p) => `第 ${c} 页 / 总共 ${p} 条`, onChange: i, onShowSizeChange: o })] }) : null; -}, fi = [{ title: "parent 1", key: "0-0", children: [{ title: "parent 1-0", key: "0-0-0", disabled: !0, children: [{ title: "leaf", key: "0-0-0-0", disableCheckbox: !0 }, { title: "leaf", key: "0-0-0-1" }] }, { title: "parent 1-1", key: "0-0-1", children: [{ title: h("span", { style: { color: "#1677ff" }, children: "sss" }), key: "0-0-1-0" }] }] }], yi = ({ className: t, width: e = 280, isTreeSider: r }) => { - const { classNames: n } = ue(ae); - return r ? h(Un.DirectoryTree, { className: j("ff-data-list-sider", n.sider, t), style: { "--sider-width": e }, showLine: !0, showIcon: !1, treeData: fi }) : null; -}, wi = ({ className: t, title: e, tabs: r }) => { - const { getBase62params: n, onTabChange: i, onReload: o, classNames: s } = ue(ae), { tab: a } = (n == null ? void 0 : n()) || {}, [l, c] = Jn((r == null ? void 0 : r[0].value) ?? (r == null ? void 0 : r[0].code), { value: a, onChange: i }); - return D("div", { className: j("ff-data-list-toolbar", s.toolbar, t), children: [h("div", { className: "ff-data-list-title", children: e }), h(Wn, { className: "ff-data-list-tabs", itemRender: ({ label: u, code: p, value: m }) => h("span", { onClick: () => c(m ?? p), className: j("ff-data-list-tab", { active: (m ?? p) == l }), children: u }), items: r }), D("div", { className: "ff-data-list-actions", children: [h(R.Link, { icon: "icon-reload", widget: () => o() }), h(R.Link, { icon: "icon-setting" })] })] }); -}, bi = ({ className: t, ...e }) => h(Bt, { className: j(t, "ff-data-list-empty"), image: Bt.PRESENTED_IMAGE_SIMPLE, ...e }), _r = ({ isItemGridLayout: t, theme: e, themeProps: r, onClickCallback: n, onReload: i, listCode: o, total: s = 0, page: a = 0, onPageChange: l, pageSize: c = 30, onPageSizeChange: u, tab: p, onTabChange: m, keyword: g, onKeywordChange: f, condition: y, onConditionChange: k, sider: b, onSiderChange: $, layouts: C, classNames: x = {}, payload: F = {}, dataSource: I = [], rowSelection: T, getSelectedRows: v, primaryKey: A, ...P }) => { - const [L, M] = V(), U = v ?? (() => I), Z = H((q, le) => { - const _ = { tab: p, page: a, pageSize: c, keyword: g, sider: b, condition: y, total: s, payload: F }; - return q && q != "init" ? w.get(_, q, le) : _; - }, [JSON.stringify(y), JSON.stringify(F), p, a, c, g, b, s]), $e = W(() => { - let q = { sider: yi, filter: Kr, footer: mi, toolbar: wi, empty: bi }; - C === !1 ? q = { sider: null, filter: null, footer: null, toolbar: null, empty: null } : w.isPlainObject(C) && (q = Object.assign({}, q, C)); - for (const le in q) if (q[le]) { - if (Rn(q[le])) { - const _ = q[le]; - q[le] = (mt) => E.cloneElement(_, mt); +Wr.reservedFields = [{ x: 0, y: 0, h: 3, w: 5, field: { isVirtual: !0, widgetPrefix: "@pkg/ff/grid-layout-forms", widget: "Input", code: "keyword", label: "关键字", placeholder: "多关键字 | 分割", extras: { prefix: "icon-search" } } }]; +const gi = ({ className: t, operations: e, isOperations: r, isPaginate: n }) => { + const { onPageChange: i, onPageSizeChange: s, onClickCallback: o, getBase62params: a } = E.useContext(oe), { total: l, page: c, pageSize: u } = (a == null ? void 0 : a()) || {}; + return r && !y.isEmpty(e) || n ? j("div", { className: F("ff-data-list-footer", t), children: [h("div", { className: "ff-data-list-actions", children: e == null ? void 0 : e.map((p, m) => h(V, { uuid: p.uuid, type: p.type, name: p.name, widget: p.widget, widgetType: p.widgetType, widgetProps: p.widgetProps, widgetData: p.widgetData, widgetSetting: p.widgetSetting, widgetContainerProps: p.widgetContainerSetting, onAfterClick: (g) => g !== !1 && (o == null ? void 0 : o(p.isRefresh, null)) }, p.uuid || m)) }), n && h(Ln, { size: "small", total: l, pageSize: u, showSizeChanger: !1, showTotal: (p) => `第 ${c} 页 / 总共 ${p} 条`, onChange: i, onShowSizeChange: s })] }) : null; +}, hi = [{ title: "parent 1", key: "0-0", children: [{ title: "parent 1-0", key: "0-0-0", disabled: !0, children: [{ title: "leaf", key: "0-0-0-0", disableCheckbox: !0 }, { title: "leaf", key: "0-0-0-1" }] }, { title: "parent 1-1", key: "0-0-1", children: [{ title: h("span", { style: { color: "#1677ff" }, children: "sss" }), key: "0-0-1-0" }] }] }], mi = ({ className: t, width: e = 280, isTreeSider: r }) => { + const { classNames: n } = de(oe); + return r ? h(Mn.DirectoryTree, { className: F("ff-data-list-sider", n.sider, t), style: { "--sider-width": e }, showLine: !0, showIcon: !1, treeData: hi }) : null; +}, fi = ({ className: t, title: e, tabs: r }) => { + const { getBase62params: n, onTabChange: i, onReload: s, classNames: o } = de(oe), { tab: a } = (n == null ? void 0 : n()) || {}, [l, c] = zn((r == null ? void 0 : r[0].value) ?? (r == null ? void 0 : r[0].code), { value: a, onChange: i }); + return j("div", { className: F("ff-data-list-toolbar", o.toolbar, t), children: [h("div", { className: "ff-data-list-title", children: e }), h(Dn, { className: "ff-data-list-tabs", itemRender: ({ label: u, code: p, value: m }) => h("span", { onClick: () => c(m ?? p), className: F("ff-data-list-tab", { active: (m ?? p) == l }), children: u }), items: r }), j("div", { className: "ff-data-list-actions", children: [h(V.Link, { icon: "icon-reload", widget: () => s() }), h(V.Link, { icon: "icon-setting" })] })] }); +}, yi = ({ className: t, ...e }) => h(Dt, { className: F(t, "ff-data-list-empty"), image: Dt.PRESENTED_IMAGE_SIMPLE, ...e }), wi = ({ isItemGridLayout: t, theme: e, themeProps: r, onClickCallback: n, onReload: i, listCode: s, total: o = 0, page: a = 0, onPageChange: l, pageSize: c = 30, onPageSizeChange: u, tab: p, onTabChange: m, keyword: g, onKeywordChange: w, condition: f, onConditionChange: C, sider: b, onSiderChange: S, layouts: k, classNames: $ = {}, payload: R = {}, dataSource: I = [], rowSelection: N, getSelectedRows: v, primaryKey: T, ...x }) => { + const [A, M] = L(), D = v ?? (() => I), Z = H((B, ae) => { + const q = { tab: p, page: a, pageSize: c, keyword: g, sider: b, condition: f, total: o, payload: R }; + return B && B != "init" ? y.get(q, B, ae) : q; + }, [JSON.stringify(f), JSON.stringify(R), p, a, c, g, b, o]), Se = W(() => { + let B = { sider: mi, filter: Wr, footer: gi, toolbar: fi, empty: yi }; + k === !1 ? B = { sider: null, filter: null, footer: null, toolbar: null, empty: null } : y.isPlainObject(k) && (B = Object.assign({}, B, k)); + for (const ae in B) if (B[ae]) { + if (Pn(B[ae])) { + const q = B[ae]; + B[ae] = (gt) => E.cloneElement(q, gt); } - } else q[le] = () => h(E.Fragment, {}); - return q; - }, [C]); + } else B[ae] = () => h(E.Fragment, {}); + return B; + }, [k]); return z(() => { - e ? X.getWidgetComponent(e).then((q) => { - if (!q) throw `${e} not found`; - return q; - }).catch((q) => ({ default: () => `${q}` })).then((q) => M(E.createElement(q.default, { ...P, layouts: $e, $setting: r }))) : M(h(t ? ui : gi, { ...P, layouts: $e, $setting: r })); - }, [e, r]), h(ae.Provider, { value: { classNames: x, listCode: o, onClickCallback: n, onReload: i, getBase62params: Z, onPageChange: l, onPageSizeChange: u, onTabChange: m, onSiderChange: $, onKeywordChange: f, onConditionChange: k, setPage: l, setPageSize: u, setTab: m, setSider: $, setKeyword: f, setCondition: k, getSelectedRows: U }, children: L && E.cloneElement(L, { dataSource: I, primaryKey: A, rowSelection: T, ...P }) }); + e ? X.getWidgetComponent(e).then((B) => { + if (!B) throw `${e} not found`; + return B; + }).catch((B) => ({ default: () => `${B}` })).then((B) => M(E.createElement(B.default, { ...x, layouts: Se, $setting: r }))) : M(h(t ? ci : ui, { ...x, layouts: Se, $setting: r })); + }, [e, r]), h(oe.Provider, { value: { classNames: $, listCode: s, onClickCallback: n, onReload: i, getBase62params: Z, onPageChange: l, onPageSizeChange: u, onTabChange: m, onSiderChange: S, onKeywordChange: w, onConditionChange: C, setPage: l, setPageSize: u, setTab: m, setSider: S, setKeyword: w, setCondition: C, getSelectedRows: D }, children: A && E.cloneElement(A, { dataSource: I, primaryKey: T, rowSelection: N, ...x }) }); }; -_r.propTypes = { classNames: S.exact({ sider: S.string, filter: S.string, footer: S.string, toolbar: S.string, container: S.string, content: S.string, item: S.string, empty: S.string }), layouts: S.oneOfType([S.exact({ sider: S.oneOfType([S.elementType, S.element]), filter: S.oneOfType([S.elementType, S.element]), footer: S.oneOfType([S.elementType, S.element]), toolbar: S.oneOfType([S.elementType, S.element]), empty: S.oneOfType([S.elementType, S.element]) }), S.bool]) }; -var Fe, Pe, Be, $t; -const me = class me { +var Fe, xe, Ve, Et; +const he = class he { constructor() { - N(this, Pe, null); - N(this, Be, /* @__PURE__ */ new Map()); - N(this, $t, () => { - if (d(this, Pe)) return d(this, Pe).port.postMessage({ command: "status", data: [] }); - K(this, Pe, new SharedWorker(new URL("/ff-worker/res-ws.js", self.location))), d(this, Pe).port.onmessage = (e) => { + P(this, xe, null); + P(this, Ve, /* @__PURE__ */ new Map()); + P(this, Et, () => { + if (d(this, xe)) return d(this, xe).port.postMessage({ command: "status", data: [] }); + K(this, xe, new SharedWorker(new URL("/ff-worker/res-ws.js", self.location))), d(this, xe).port.onmessage = (e) => { var r, n; - (r = e.data) != null && r.uuid ? d(this, Be).forEach((i, o) => { - var s; - (i == "*" || (s = i == null ? void 0 : i.includes) != null && s.call(i, e.data.uuid)) && o(e.data); - }) : ((n = e.data) == null ? void 0 : n.readyState) == WebSocket.CLOSED && B.get("/api/user-api-token").then(({ token: i, expire_at: o }) => { - d(this, Pe).port.postMessage({ command: "initWs", data: [`ws${w.trimStart(B.appUrl, "http")}api/user-resource-status-ws?token=${i}`] }); + (r = e.data) != null && r.uuid ? d(this, Ve).forEach((i, s) => { + var o; + (i == "*" || (o = i == null ? void 0 : i.includes) != null && o.call(i, e.data.uuid)) && s(e.data); + }) : ((n = e.data) == null ? void 0 : n.readyState) == WebSocket.CLOSED && U.get("/api/user-api-token").then(({ token: i, expire_at: s }) => { + d(this, xe).port.postMessage({ command: "initWs", data: [`ws${y.trimStart(U.appUrl, "http")}api/user-resource-status-ws?token=${i}`] }); }); - }, d(this, Pe).port.postMessage({ command: "status", data: [] }); + }, d(this, xe).port.postMessage({ command: "status", data: [] }); }); - O(this, "subscribe", (e, r = []) => (r ? Array.isArray(r) && r.length == 0 ? r = "*" : Array.isArray(r) || (r = [r].flat()) : r = "*", d(this, Be).set(e, r), d(this, Be).size == 1 && d(this, $t).call(this), () => this.unsubscribe(e))); - O(this, "unsubscribe", (e) => d(this, Be).delete(e)); - if (d(me, Fe)) return d(me, Fe); + O(this, "subscribe", (e, r = []) => (r ? Array.isArray(r) && r.length == 0 ? r = "*" : Array.isArray(r) || (r = [r].flat()) : r = "*", d(this, Ve).set(e, r), d(this, Ve).size == 1 && d(this, Et).call(this), () => this.unsubscribe(e))); + O(this, "unsubscribe", (e) => d(this, Ve).delete(e)); + if (d(he, Fe)) return d(he, Fe); } }; -Fe = new WeakMap(), Pe = new WeakMap(), Be = new WeakMap(), $t = new WeakMap(), N(me, Fe, null), O(me, "getInstance", () => (d(me, Fe) || K(me, Fe, new me()), d(me, Fe))); -let qt = me; -const Jr = qt.getInstance(), rr = E.forwardRef(({ listCode: t, base62params: e, className: r, theme: n, themeProps: i, layouts: o, classNames: s, rowSelection: a = null, onDataSourceChange: l }, c) => { - const [{ resource: u, primaryKey: p, batchOperations: m = [], itemOperations: g = [], columns: f = [], isConditionFormLayout: y = !1, isTreeSider: k, treeSiderConfig: b, theme: $, themeConfig: C, isItemGridLayout: x, itemGridLayout: { themeConfig: F, ...I } = {}, title: T, isPaginate: v, tabs: A, selectionType: P }, L] = V({ isItemGridLayout: !1, itemGridLayout: {} }), { type: M = P, selectedRowKeys: U, defaultSelectedRowKeys: Z, onChange: $e, ...q } = a ?? {}, le = di(t, e), [{ dataSource: _, itemOperationsAccess: mt, condition: cn, tab: dn, keyword: un, page: lr, total: cr, pageSize: dr, sider: pn, onConditionChange: gn, onTabChange: hn, onKeywordChange: mn, onPageChange: fn, onPageSizeChange: yn, onSiderChange: wn, onReload: Ot, payload: bn }, ur] = ci(le, t, p, u), Cn = Cr(l); - Xt(() => { - Cn(_, { primaryKey: p, page: lr, pageSize: dr, total: cr }); - }, [_]); - const [pr, kn] = Dn([], { defaultValue: Z ?? [], value: U }), [gr, Sn] = V([]), hr = H(() => M ? gr : _, [M, gr, _]), En = zt(g, mt, _, p), $n = zt(m); +Fe = new WeakMap(), xe = new WeakMap(), Ve = new WeakMap(), Et = new WeakMap(), P(he, Fe, null), O(he, "getInstance", () => (d(he, Fe) || K(he, Fe, new he()), d(he, Fe))); +let Bt = he; +const Br = Bt.getInstance(), tr = E.forwardRef(({ listCode: t, base62params: e, className: r, theme: n, themeProps: i, layouts: s, classNames: o, rowSelection: a = null, onDataSourceChange: l }, c) => { + const [{ resource: u, primaryKey: p, batchOperations: m = [], itemOperations: g = [], columns: w = [], isConditionFormLayout: f = !1, isTreeSider: C, treeSiderConfig: b, theme: S, themeConfig: k, isItemGridLayout: $, itemGridLayout: { themeConfig: R, ...I } = {}, title: N, isPaginate: v, tabs: T, selectionType: x }, A] = L({ isItemGridLayout: !1, itemGridLayout: {} }), { type: M = x, selectedRowKeys: D, defaultSelectedRowKeys: Z, onChange: Se, ...B } = a ?? {}, ae = li(t, e), [{ dataSource: q, itemOperationsAccess: gt, condition: sn, tab: on, keyword: an, page: ar, total: lr, pageSize: cr, sider: ln, onConditionChange: cn, onTabChange: dn, onKeywordChange: un, onPageChange: pn, onPageSizeChange: gn, onSiderChange: hn, onReload: ht, payload: mn }, Nt] = ai(ae, t, p, u), fn = wr(l); + Yt(() => { + fn(q, { primaryKey: p, page: ar, pageSize: cr, total: lr }); + }, [q]); + const [dr, yn] = An([], { defaultValue: Z ?? [], value: D }), [ur, wn] = L([]), pr = H(() => M ? ur : q, [M, ur, q]), bn = Wt(g, gt, q, p), Cn = Wt(m); z(() => { - let Q = null; - return t && B.get(`/api/_/${t}`).resp(({ data: Le, res: Rt }) => { - Le != null && Le.isDynamicRefresh && (Q = Jr.subscribe(() => Ot(), Rt)), L(Le); - }).catch(() => L({})), () => Q == null ? void 0 : Q(); - }, [t]), E.useImperativeHandle(c, () => ({ onReload: Ot, onClickCallback: ur, getSelectedRows: hr })); - const mr = Cr((Q, Le) => { - Sn((Rt) => { - const fr = new Map(Rt.map((ce) => [ce == null ? void 0 : ce[p], ce])); - return Le.forEach((ce) => fr.set(ce == null ? void 0 : ce[p], ce)), Q.map((ce) => fr.get(ce)).filter(Boolean); - }), kn(Q), $e == null || $e(Q, Le); - }), xn = W(() => M ? { columnWidth: 80, ...q, type: M, selectedRowKeys: pr, onChange: mr } : void 0, [M, pr, mr, a]), Pn = W(() => w.merge({}, C, i), [C, i]), vn = W(() => g == null ? void 0 : g.map((Q) => w.isEmpty(Q == null ? void 0 : Q.confirm) ? Q : { ...Q, confirm: Object.assign({}, Q.confirm, { getPopupContainer: () => document.body }) }), [g]), Nn = W(() => ({ ...I, themeProps: F }), [I, F]); - return h(_r, { listCode: t, title: T, classNames: s, layouts: o, resource: u, primaryKey: p, theme: n || $, themeProps: Pn, isTreeSider: k, treeSiderConfig: b, isPaginate: v, rowSelection: xn, getSelectedRows: hr, tabs: A, isItemOperations: En, itemOperations: vn, isBatchOperations: $n, batchOperations: m, isItemGridLayout: x, columns: f, itemGridLayout: Nn, isConditionFormLayout: y, itemOperationsAccess: mt, dataSource: _, onConditionChange: gn, onTabChange: hn, onKeywordChange: mn, onPageChange: fn, onPageSizeChange: yn, onSiderChange: wn, condition: cn, tab: dn, keyword: un, page: lr, total: cr, pageSize: dr, sider: pn, payload: bn, className: j("ff-data-list-helper", r), onReload: Ot, onClickCallback: ur }); -}), Hr = (t, e, r = !0) => r !== !0 && r-- <= 0 ? [] : w.isArray(t) && !w.isEmpty(t) ? t.reduce((n, i) => (Reflect.has(i, e) && Reflect.has(i, "children") && n.push(i[e]), Reflect.has(i, "children") && !w.isEmpty(i.children) ? n.concat(Hr(i.children, e, r)) : n), []) : [], Ci = ({ className: t, primaryKey: e, columns: r = [], dataSource: n = [], operationRender: i, operationWidth: o = 180, components: s = {}, rowSelection: a, ...l }) => { - const { classNames: c } = ue(ae), u = J(null), p = J(null), [m, g] = V([]), [f, y] = V({ width: 0, height: 0 }); + let J = null; + return t && U.get(`/api/_/${t}`).resp(({ data: je, res: Ot }) => { + je != null && je.isDynamicRefresh && (J = Br.subscribe(() => ht(), Ot)), A(je); + }).catch(() => A({})), () => J == null ? void 0 : J(); + }, [t]), E.useImperativeHandle(c, () => ({ reload: ht, emitOperation: Nt, getSelectedRows: pr, onReload: (...J) => (console.warn("[DataListHelper] onReload 已废弃,请使用 reload"), ht(...J)), onClickCallback: (...J) => (console.warn("[DataListHelper] onClickCallback 已废弃,请使用 emitOperation"), Nt(...J)) })); + const gr = wr((J, je) => { + wn((Ot) => { + const hr = new Map(Ot.map((le) => [le == null ? void 0 : le[p], le])); + return je.forEach((le) => hr.set(le == null ? void 0 : le[p], le)), J.map((le) => hr.get(le)).filter(Boolean); + }), yn(J), Se == null || Se(J, je); + }), kn = W(() => M ? { columnWidth: 80, ...B, type: M, selectedRowKeys: dr, onChange: gr } : void 0, [M, dr, gr, a]), En = W(() => y.merge({}, k, i), [k, i]), Sn = W(() => g == null ? void 0 : g.map((J) => y.isEmpty(J == null ? void 0 : J.confirm) ? J : { ...J, confirm: Object.assign({}, J.confirm, { getPopupContainer: () => document.body }) }), [g]), $n = W(() => ({ ...I, themeProps: R }), [I, R]); + return h(wi, { listCode: t, title: N, classNames: o, layouts: s, resource: u, primaryKey: p, theme: n || S, themeProps: En, isTreeSider: C, treeSiderConfig: b, isPaginate: v, rowSelection: kn, getSelectedRows: pr, tabs: T, isItemOperations: bn, itemOperations: Sn, isBatchOperations: Cn, batchOperations: m, isItemGridLayout: $, columns: w, itemGridLayout: $n, isConditionFormLayout: f, itemOperationsAccess: gt, dataSource: q, onConditionChange: cn, onTabChange: dn, onKeywordChange: un, onPageChange: pn, onPageSizeChange: gn, onSiderChange: hn, condition: sn, tab: on, keyword: an, page: ar, total: lr, pageSize: cr, sider: ln, payload: mn, className: F("ff-data-list-helper", r), onReload: ht, onClickCallback: Nt }); +}), zr = (t, e, r = !0) => r !== !0 && r-- <= 0 ? [] : y.isArray(t) && !y.isEmpty(t) ? t.reduce((n, i) => (Reflect.has(i, e) && Reflect.has(i, "children") && n.push(i[e]), Reflect.has(i, "children") && !y.isEmpty(i.children) ? n.concat(zr(i.children, e, r)) : n), []) : [], bi = ({ className: t, primaryKey: e, columns: r = [], dataSource: n = [], operationRender: i, operationWidth: s = 180, components: o = {}, rowSelection: a, ...l }) => { + const { classNames: c } = de(oe), u = _(null), p = _(null), [m, g] = L([]), [w, f] = L({ width: 0, height: 0 }); z(() => { - g(Hr(n, e)); - }, [n, e]), Fn(() => { - const C = new ResizeObserver(() => { - var x; - y({ width: ((x = u.current) == null ? void 0 : x.nativeElement.querySelector(".ant-table-body").scrollWidth) || p.current.offsetWidth, height: p.current.offsetHeight }); + g(zr(n, e)); + }, [n, e]), Nn(() => { + const k = new ResizeObserver(() => { + var $; + f({ width: (($ = u.current) == null ? void 0 : $.nativeElement.querySelector(".ant-table-body").scrollWidth) || p.current.offsetWidth, height: p.current.offsetHeight }); }); - return p.current && C.observe(p.current), () => { - p.current && C.unobserve(p.current); + return p.current && k.observe(p.current), () => { + p.current && k.unobserve(p.current); }; }, []); - const k = W(() => { - if (!(f != null && f.width) || !(r != null && r.length)) return r; - const C = (a ? a.columnWidth ?? 32 : 0) + (i ? o : 0), x = r.reduce((T, v) => T + (v != null && v.isWidthFixed && v.width ? v.width : 0), 0), F = r.filter((T) => !(T != null && T.isWidthFixed)).reduce((T, v) => T + ((v == null ? void 0 : v.width) ?? 100), 0); - if (x + F + C >= f.width) return r; - const I = f.width - x - C; - return r.map((T) => T != null && T.isWidthFixed ? T : { ...T, width: Math.floor(I * ((T == null ? void 0 : T.width) ?? 100) / F) }); - }, [r, f.width, a, i, o]), b = ai(k), $ = li(s); - return h("div", { ref: p, className: j("ff-data-list-table", c.content, t), children: f.height ? h(kr, { bordered: !0, ...l, components: $, ref: u, rowKey: (C) => (C == null ? void 0 : C[e]) ?? Math.random(), rowSelection: a, columns: (() => { - var x, F; - const C = [...b ?? []]; - return a && C.splice((F = (x = C[0]) == null ? void 0 : x.key) != null && F.startsWith("__") ? 1 : 0, 0, kr.SELECTION_COLUMN), i && C.push({ title: "操作", align: "center", fixed: "right", className: "ff-data-list-table-operations", width: `${Math.ceil(o / f.width * 100).toFixed(2)}%`, render: (I, T, v) => i(T, v) }), C; - })(), dataSource: n, size: "middle", scroll: { x: "max-content", y: f.height - 50 }, pagination: !1, expandable: { defaultExpandAllRows: !0, expandRowByClick: !0, onExpandedRowsChange: g, expandedRowKeys: m } }) : null }); -}, ki = "RC_FORM_INTERNAL_HOOKS", Si = (t) => { + const C = W(() => { + if (!(w != null && w.width) || !(r != null && r.length)) return r; + const k = (a ? a.columnWidth ?? 32 : 0) + (i ? s : 0), $ = r.reduce((N, v) => N + (v != null && v.isWidthFixed && v.width ? v.width : 0), 0), R = r.filter((N) => !(N != null && N.isWidthFixed)).reduce((N, v) => N + ((v == null ? void 0 : v.width) ?? 100), 0); + if ($ + R + k >= w.width) return r; + const I = w.width - $ - k; + return r.map((N) => N != null && N.isWidthFixed ? N : { ...N, width: Math.floor(I * ((N == null ? void 0 : N.width) ?? 100) / R) }); + }, [r, w.width, a, i, s]), b = si(C), S = oi(o); + return h("div", { ref: p, className: F("ff-data-list-table", c.content, t), children: w.height ? h(br, { bordered: !0, ...l, components: S, ref: u, rowKey: (k) => (k == null ? void 0 : k[e]) ?? Math.random(), rowSelection: a, columns: (() => { + var $, R; + const k = [...b ?? []]; + return a && k.splice((R = ($ = k[0]) == null ? void 0 : $.key) != null && R.startsWith("__") ? 1 : 0, 0, br.SELECTION_COLUMN), i && k.push({ title: "操作", align: "center", fixed: "right", className: "ff-data-list-table-operations", width: `${Math.ceil(s / w.width * 100).toFixed(2)}%`, render: (I, N, v) => i(N, v) }), k; + })(), dataSource: n, size: "middle", scroll: { x: "max-content", y: w.height - 50 }, pagination: !1, expandable: { defaultExpandAllRows: !0, expandRowByClick: !0, onExpandedRowsChange: g, expandedRowKeys: m } }) : null }); +}, Ci = "RC_FORM_INTERNAL_HOOKS", ki = (t) => { const [e, r] = E.useState({ items: [] }); return z(() => { - t && B.get(`/api/_/${t}`).then(({ uuid: n, code: i, name: o, resource: s, primaryKey: a, marginX: l, marginY: c, cols: u, rowHeight: p, fields: m, theme: g, themeSetting: f, groups: y }) => ({ uuid: n, code: i, name: o, resource: s, primaryKey: a, marginX: l, marginY: c, cols: u, rowHeight: p, theme: g, themeProps: f, groups: y, items: m })).then(r); + t && U.get(`/api/_/${t}`).then(({ uuid: n, code: i, name: s, resource: o, primaryKey: a, marginX: l, marginY: c, cols: u, rowHeight: p, fields: m, theme: g, themeSetting: w, groups: f }) => ({ uuid: n, code: i, name: s, resource: o, primaryKey: a, itemMargin: [c, l], cols: u, rowHeight: p, theme: g, themeProps: w, groups: f, items: m })).then(r); }, [t]), e; -}, Ei = (t, { initialValue: e, initialValueLanguage: r, convertJs: n, convertJsSetting: i, type: o = "string" }, s = null) => { - const a = J(!1), l = ue(Ir), [c, u] = V(), [p, m] = V(r != "javascript" && t ? l.getFieldValue(t) : void 0), { registerWatch: g } = l.getInternalHooks(ki) || {}; - return z(() => g == null ? void 0 : g((f, y, k) => { +}, Ei = (t, { initialValue: e, initialValueLanguage: r, convertJs: n, convertJsSetting: i, type: s = "string" }, o = null) => { + const a = _(!1), l = de(Tr), [c, u] = L(), [p, m] = L(r != "javascript" && t ? l.getFieldValue(t) : void 0), { registerWatch: g } = l.getInternalHooks(Ci) || {}; + return z(() => g == null ? void 0 : g((w, f, C) => { if (!a.current) return; - const b = w.get(y, t); - w.isEqual(b, p) || m(oe(b, o)); + const b = y.get(f, t); + y.isEqual(b, p) || m(ie(b, s)); }), [p]), z(() => { - r == "javascript" && e ? ze.exec(e, {}, { getFieldValueForBasicForm: (f) => s ? s.getFieldValue(f) : l.getFieldValue(f), getFieldValue: (f) => l.getFieldValue(f) }).then((f) => m(oe(f, o))).catch((f) => notification.error({ message: `布局数据错误: ${JSON.stringify(f)}` })).finally(() => a.current = !0) : (e && m(oe(e ?? l.getFieldValue(t), o)), a.current = !0); - }, [e, r]), gt(() => { - a.current && n && new Ct([n, i]).toValue(p, l.getFieldsValue(!0)).then(u).catch((f) => { - u(f), console.error("布局数据转换错误: ", f, n); + if (r == "javascript" && e) { + const w = { getFieldValueForBasicForm: (f) => o ? o.getFieldValue(f) : l.getFieldValue(f), getFieldValue: (f) => l.getFieldValue(f) }; + Be.exec(e, {}, w).then((f) => m(ie(f, s))).catch((f) => notification.error({ message: `布局数据错误: ${JSON.stringify(f)}` })).finally(() => a.current = !0); + } else e && m(ie(e ?? l.getFieldValue(t), s)), a.current = !0; + }, [e, r]), vt(() => { + a.current && n && new bt([n, i]).toValue(p, l.getFieldsValue(!0)).then(u).catch((w) => { + u(w), console.error("布局数据转换错误: ", w, n); }); }, [p, n, i]), [c ?? p, p]; -}, Ro = (t, e, r = null) => W(() => tr(t, e, r), [t]), Yr = (t, e, r = {}, n = {}, i = {}, o = null) => { - const s = ue(Ir), a = vt(), l = J(!0), c = J([]), [u, p] = V(e), [m, g] = V(), f = se.useWatch((y) => JSON.stringify(w.pick(y, c.current)), s) || "{}"; - return Nt(() => { - t && ze.exec(t, r, { ...n, getFieldValueForBasicForm: (y) => i ? i.getFieldValue(y) : null, getFieldValue: w.wrap(s.getFieldValue, (y, k) => (c.current.some((b) => w.isEqual(b, k)) || (c.current.push(k), a()), y == null ? void 0 : y(k))), isFieldTouched: s.isFieldTouched, isFieldsTouched: s.isFieldsTouched }).then((y) => { - l.current && (p(y), g(null)); - }).catch((y) => { - l.current && (p(e), g(y)); +}, Ps = (t, e, r = null) => W(() => er(t, e, r), [t]), Kr = (t, e, r = {}, n = {}, i = {}, s = null) => { + const o = de(Tr), a = xt(), l = _(!0), c = _([]), [u, p] = L(e), [m, g] = L(), w = se.useWatch((f) => JSON.stringify(y.pick(f, c.current)), o) || "{}"; + return Pt(() => { + const f = { ...n, getFieldValueForBasicForm: (C) => i ? i.getFieldValue(C) : null, getFieldValue: y.wrap(o.getFieldValue, (C, b) => (c.current.some((S) => y.isEqual(S, b)) || (c.current.push(b), a()), C == null ? void 0 : C(b))), isFieldTouched: o.isFieldTouched, isFieldsTouched: o.isFieldsTouched }; + t && Be.exec(t, r, f).then((C) => { + l.current && (p(C), g(null)); + }).catch((C) => { + l.current && (p(e), g(C)); }); - }, [t, f, s, r, n]), z(() => () => l.current = !1, []), t ? [o ? oe(u, o) : u, m] : [o ? oe(e, o) : e, null]; -}, $i = ({ widget: t, widgetPrefix: e = "@pkg/ff/grid-layouts", basicForm: r, ...n }) => { - const i = t != null && t.startsWith("@") || t != null && t.startsWith("blob:") ? t : `${e}/${t}`, [o, s] = V(); + }, [t, w, o, r, n]), z(() => () => l.current = !1, []), t ? [s ? ie(u, s) : u, m] : [s ? ie(e, s) : e, null]; +}, Si = ({ widget: t, widgetPrefix: e = "@pkg/ff/grid-layouts", basicForm: r, ...n }) => { + const i = t != null && t.startsWith("@") || t != null && t.startsWith("blob:") ? t : `${e}/${t}`, [s, o] = L(); return z(() => { - i && X.getWidgetComponent(i).then(({ defaultProps: a = {}, default: l }) => ({ default: xi(l, a, r) })).catch((a) => ({ default: () => `${a}` })).then((a) => s(E.createElement(a.default, n))); - }, [i]), o; -}, xi = (t, e = {}, r = null) => (n) => { - const { code: i, label: o, extras: s, isVirtual: a, initialValue: l, initialValueLanguage: c, convertJs: u, convertJsSetting: p, value: m, ...g } = w.merge({}, e, n), [f, y] = Ei(a ? null : i, { initialValue: l, initialValueLanguage: c, convertJs: u, convertJsSetting: p, type: (g == null ? void 0 : g.type) || "string" }, r), k = W(() => { - const C = Object.keys((e == null ? void 0 : e.extras) || {}); - return w.over([w.partialRight(w.pick, C), w.partialRight(w.omit, C)]); - }, [e == null ? void 0 : e.extras]), [b, $] = k(g); - return h(t, { ...$, value: f, rawValue: y, $setting: Object.assign({}, s, b) }); -}, Gr = ({ theme: t, basicForm: e, items: r = [{ key: "default", label: "默认" }], fields: n = [], itemRender: i, chunks: o = [], children: s, $setting: a = {}, ...l }) => { - const [c, u] = V(); + i && X.getWidgetComponent(i).then(({ defaultProps: a = {}, default: l }) => ({ default: $i(l, a, r) })).catch((a) => ({ default: () => `${a}` })).then((a) => o(E.createElement(a.default, n))); + }, [i]), s; +}, $i = (t, e = {}, r = null) => (n) => { + const { code: i, label: s, extras: o, isVirtual: a, initialValue: l, initialValueLanguage: c, convertJs: u, convertJsSetting: p, value: m, ...g } = y.merge({}, e, n), [w, f] = Ei(a ? null : i, { initialValue: l, initialValueLanguage: c, convertJs: u, convertJsSetting: p, type: (g == null ? void 0 : g.type) || "string" }, r), C = W(() => { + const k = Object.keys((e == null ? void 0 : e.extras) || {}); + return y.over([y.partialRight(y.pick, k), y.partialRight(y.omit, k)]); + }, [e == null ? void 0 : e.extras]), [b, S] = C(g); + return h(t, { ...S, value: w, rawValue: f, $setting: Object.assign({}, o, b) }); +}, qr = ({ theme: t, basicForm: e, items: r = [{ key: "default", label: "默认" }], fields: n = [], itemRender: i, chunks: s = [], children: o, $setting: a = {}, ...l }) => { + const [c, u] = L(); z(() => { t ? X.getWidgetComponent(t).then((m) => { if (!(m != null && m.default)) throw "not found"; return m; }).catch((m) => ({ default: () => `${t} ${m}` })).then((m) => u(E.createElement(m.default, {}))) : u(null); }, [t]); - const p = W(() => r == null ? void 0 : r.map((m) => ({ ...m, children: i(m, n == null ? void 0 : n.filter((g) => !(g != null && g.group) && m.key == "default" || g.group == m.key), m.key == "default" ? s : null) })).concat(o), [r, s, o]); + const p = W(() => r == null ? void 0 : r.map((m) => ({ ...m, children: i(m, n == null ? void 0 : n.filter((g) => !(g != null && g.group) && m.key == "default" || g.group == m.key), m.key == "default" ? o : null) })).concat(s), [r, o, s]); return c && E.cloneElement(c, { items: p, basicForm: e, $setting: { ...a, ...l } }); -}, Xr = ({ name: t, form: e = null, basicForm: r = null, style: n = {}, className: i, cols: o = 12, rowHeight: s = 21, containerPadding: a = [0, 0], itemMargin: l = [4, 0], formProps: c = {}, formFields: u = [], fields: p = [], data: m, theme: g, themeProps: f = {}, groups: y = [{ key: "default", label: "默认" }], children: k, ...b }) => { - const [$] = se.useForm(e), C = W(() => [{ name: "__PROPS__", value: c }].concat(u), [c, u]); - gt(() => ($.setFieldsValue(m), () => $.resetFields()), [m]); - const x = (F, I, T) => { - const v = tr(I, $i, r), A = qr(b); - return D("div", { ...A, className: j("ff-grid-layout", i), style: { ...n, "--grid-layout-item-margin-y": `${(l == null ? void 0 : l[0]) || 0}px`, "--grid-layout-item-margin-x": `${(l == null ? void 0 : l[1]) || 0}px`, "--grid-layout-container-padding-y": `${(a == null ? void 0 : a[0]) || 0}px`, "--grid-layout-container-padding-x": `${(a == null ? void 0 : a[1]) || 0}px`, "--grid-layout-cols": o, "--grid-layout-row-height": `${s}px` }, children: [v, T && E.cloneElement(T, { cols: o, rowHeight: s, itemMargin: l, containerPadding: a, fields: I, basicForm: r })] }); +}, _r = ({ name: t, form: e = null, basicForm: r = null, style: n = {}, className: i, cols: s = 12, rowHeight: o = 21, containerPadding: a = [0, 0], itemMargin: l = [4, 0], formProps: c = {}, formFields: u = [], fields: p = [], data: m, theme: g, themeProps: w = {}, groups: f = [{ key: "default", label: "默认" }], children: C, ...b }) => { + const [S] = se.useForm(e), k = W(() => [{ name: "__PROPS__", value: c }].concat(u), [c, u]); + vt(() => (S.setFieldsValue(m), () => S.resetFields()), [m]); + const $ = (R, I, N) => { + const v = er(I, Si, r), T = Ur(b); + return j("div", { ...T, className: F("ff-grid-layout", i), style: { ...n, "--grid-layout-item-margin-y": `${(l == null ? void 0 : l[0]) || 0}px`, "--grid-layout-item-margin-x": `${(l == null ? void 0 : l[1]) || 0}px`, "--grid-layout-container-padding-y": `${(a == null ? void 0 : a[0]) || 0}px`, "--grid-layout-container-padding-x": `${(a == null ? void 0 : a[1]) || 0}px`, "--grid-layout-cols": s, "--grid-layout-row-height": `${o}px` }, children: [v, N && E.cloneElement(N, { cols: s, rowHeight: o, itemMargin: l, containerPadding: a, fields: I, basicForm: r })] }); }; - return h(se, { ...b, fields: C, form: $, component: !1, children: g ? h(Gr, { ...f, items: y, theme: g, itemRender: x, fields: p, children: k, basicForm: r }) : x(0, p, k) }); -}, Fo = /* @__PURE__ */ ((t) => function({ code: e, data: r, ...n }) { - const { uuid: i, resource: o, items: s, hides: a, rowHeight: l, marginX: c, marginY: u, cols: p, theme: m, themeProps: g, groups: f } = Si(e) || {}, y = W(() => [{ name: "__RESOURCE__", value: o }, { name: "__LAYOUT_KEY__", value: e }, { name: "__LAYOUT_UUID__", value: i }], [e, i, o]); - return o && h(t, { name: e, theme: m, themeProps: g, groups: f, ...n, fields: s, formFields: y, rowHeight: l, cols: p, itemMargin: [c, u], data: o ? { [o]: r } : r }); -})(Xr), Pi = ({ column: t = 0, colWidth: e = 0, cols: r, rowHeight: n, itemMargin: i, containerPadding: o, fields: s, primaryKey: a, dataSource: l, beforeRender: c = null, afterRender: u = null, itemClassName: p, itemRender: m = (x, F, I) => x, empty: g = h(Bt, { description: null }), className: f, style: y = {}, theme: k, themeProps: b = {}, groups: $ = [{ key: "default", label: "默认" }], rowSelection: C }) => { - const { classNames: x } = ue(ae), F = H((v) => { - if (!C) return; - const { selectedRowKeys: A = [], onChange: P, type: L = "checkbox" } = C, M = v == null ? void 0 : v[a]; - let U; - U = L === "radio" ? [M] : A.includes(M) ? A.filter((Z) => Z !== M) : [...A, M], P == null || P(U, l.filter((Z) => U.includes(Z == null ? void 0 : Z[a]))); - }, [C, a, l]), I = W(() => h(Xr, { groups: $, theme: k, themeProps: b, cols: r, rowHeight: n, itemMargin: i, containerPadding: o, fields: s, className: p }), [s, r, n, i, o, $, k, b]), T = w.isEmpty(l); - return D("div", { className: j("ff-data-list-content", x.content, f), style: Object.assign({}, y, t && { "--col-num": t }, e && { "--col-width": e }), children: [c == null ? void 0 : c(l), T ? g : l.map((v, A) => { - var U; - const P = (v == null ? void 0 : v[a]) ?? A, L = `${P}-${Ri(v)}`, M = m(E.cloneElement(I, { data: v }), v, A); - return E.cloneElement(M, { key: L, ...C && { isSelected: (U = C == null ? void 0 : C.selectedRowKeys) == null ? void 0 : U.includes(P), selectionType: C.type ?? "checkbox", onSelect: () => F(v) } }); + return h(se, { ...b, fields: k, form: S, component: !1, children: g ? h(qr, { ...w, items: f, theme: g, itemRender: $, fields: p, children: C, basicForm: r }) : $(0, p, C) }); +}, Ns = /* @__PURE__ */ ((t) => function({ code: e, data: r, ...n }) { + const { uuid: i, resource: s, items: o, hides: a, rowHeight: l, itemMargin: c, cols: u, theme: p, themeProps: m, groups: g } = ki(e) || {}, w = W(() => [{ name: "__RESOURCE__", value: s }, { name: "__LAYOUT_KEY__", value: e }, { name: "__LAYOUT_UUID__", value: i }], [e, i, s]); + return s && h(t, { name: e, theme: p, themeProps: m, groups: g, ...n, fields: o, formFields: w, rowHeight: l, cols: u, itemMargin: c, data: s ? { [s]: r } : r }); +})(_r), xi = ({ column: t = 0, colWidth: e = 0, cols: r, rowHeight: n, itemMargin: i, containerPadding: s, fields: o, primaryKey: a, dataSource: l, beforeRender: c = null, afterRender: u = null, itemClassName: p, itemRender: m = ($, R, I) => $, empty: g = h(Dt, { description: null }), className: w, style: f = {}, theme: C, themeProps: b = {}, groups: S = [{ key: "default", label: "默认" }], rowSelection: k }) => { + const { classNames: $ } = de(oe), R = H((v) => { + if (!k) return; + const { selectedRowKeys: T = [], onChange: x, type: A = "checkbox" } = k, M = v == null ? void 0 : v[a]; + let D; + D = A === "radio" ? [M] : T.includes(M) ? T.filter((Z) => Z !== M) : [...T, M], x == null || x(D, l.filter((Z) => D.includes(Z == null ? void 0 : Z[a]))); + }, [k, a, l]), I = W(() => h(_r, { groups: S, theme: C, themeProps: b, cols: r, rowHeight: n, itemMargin: i, containerPadding: s, fields: o, className: p }), [o, r, n, i, s, S, C, b]), N = y.isEmpty(l); + return j("div", { className: F("ff-data-list-content", $.content, w), style: Object.assign({}, f, t && { "--col-num": t }, e && { "--col-width": e }), children: [c == null ? void 0 : c(l), N ? g : l.map((v, T) => { + var D; + const x = (v == null ? void 0 : v[a]) ?? T, A = `${x}-${Ri(v)}`, M = m(E.cloneElement(I, { data: v }), v, T); + return E.cloneElement(M, { key: A, ...k && { isSelected: (D = k == null ? void 0 : k.selectedRowKeys) == null ? void 0 : D.includes(x), selectionType: k.type ?? "checkbox", onSelect: () => R(v) } }); }), u == null ? void 0 : u(l)] }); }, vi = ({ component: t, $props: e }) => { - const { base62params: r } = Pt(e, {}); - return h(re, { children: h(rr, { listCode: t, base62params: B.decode(r) }) }); -}, jo = () => h(Zr, {}), Zr = () => "Empty", Ni = ({ component: t, $setting: e, $props: r }) => { - const [n, i] = V(), [o, s] = nn(r); + const { base62params: r } = $t(e, {}); + return h(re, { children: h(tr, { listCode: t, base62params: U.decode(r) }) }); +}, Os = () => h(Hr, {}), Hr = () => "Empty", Pi = ({ component: t, $setting: e, $props: r }) => { + const [n, i] = L(), [s, o] = Zr(r); return z(() => { - if (!t) return i(h(Zr, { description: null })); + if (!t) return i(h(Hr, { description: null })); X.getWidgetComponent(t).catch((a) => ({ default: () => `${a}` })).then((a) => E.createElement(a.default, { $setting: e })).then(i); - }, [t]), n ? E.cloneElement(n, { ...o, $setProps: s }) : null; -}, Ao = () => "NotFoundPage"; -var je, de, Ae, we, ot, st; -const fe = class fe { + }, [t]), n ? E.cloneElement(n, { ...s, $setProps: o }) : null; +}, Rs = () => "NotFoundPage"; +var Te, ce, Ie, ye, it, st; +const me = class me { constructor() { - N(this, de, /* @__PURE__ */ new Map()); - N(this, Ae, {}); - N(this, we, null); + P(this, ce, /* @__PURE__ */ new Map()); + P(this, Ie, {}); + P(this, ye, null); O(this, "init", (e, r) => { - K(this, de, e), K(this, Ae, r); + K(this, ce, e), K(this, Ie, r); }); - O(this, "get", (e) => (d(this, de).has(e) || (e = Array.from(d(this, de).keys()).find((r) => d(this, de).get(r).uri === e)), d(this, de).get(e) || {})); + O(this, "get", (e) => (d(this, ce).has(e) || (e = Array.from(d(this, ce).keys()).find((r) => d(this, ce).get(r).uri === e)), d(this, ce).get(e) || {})); O(this, "redirect", (e, r, n = {}) => { - var f; - const { uri: i, type: o, widgetProps: s } = this.get(e) || {}, { router: a, query: l, ...c } = r || {}, u = Object.assign({}, c, a), p = Object.assign({}, c, l); - o == "list" && (u.base62params = B.encode(u != null && u.base62params ? u.base62params : u)); - let m = Hn(i || e, u); + var w; + const { uri: i, type: s, widgetProps: o } = this.get(e) || {}, { router: a, query: l, ...c } = r || {}, u = Object.assign({}, c, a), p = Object.assign({}, c, l); + s == "list" && (u.base62params = U.encode(u != null && u.base62params ? u.base62params : u)); + let m = Kn(i || e, u); const g = new URLSearchParams(); - for (const y in s || {}) ((f = s[y]) == null ? void 0 : f.type) == "query" && Object.has(p, y) && g.append(y, JSON.stringify(p[y])); - return g.size > 0 && (m = `${m}?${g.toString()}`), n != null && n.isOpenWindow ? window.open(m) : d(this, we).navigate(m, { replace: !!(n != null && n.isReplaceRouteHistory) }); + for (const f in o || {}) ((w = o[f]) == null ? void 0 : w.type) == "query" && Object.has(p, f) && g.append(f, JSON.stringify(p[f])); + return g.size > 0 && (m = `${m}?${g.toString()}`), n != null && n.isOpenWindow ? window.open(m) : d(this, ye).navigate(m, { replace: !!(n != null && n.isReplaceRouteHistory) }); }); O(this, "getMenus", (e) => { var r; - return ((r = d(this, Ae)) == null ? void 0 : r[e]) || []; + return ((r = d(this, Ie)) == null ? void 0 : r[e]) || []; }); O(this, "findMenuPathByUuid", (e) => { let r = []; - for (const n in d(this, Ae)) if (r = d(this, ot).call(this, d(this, Ae)[n], e, [n]), r.length > 1) return r; + for (const n in d(this, Ie)) if (r = d(this, it).call(this, d(this, Ie)[n], e, [n]), r.length > 1) return r; return r; }); - O(this, "getMenusByRouteUuid", (e) => d(this, st).call(this, e, Object.values(d(this, Ae)).flat())); - N(this, ot, (e, r, n = []) => { - if (w.isEmpty(e)) return n; - for (const { uuid: i, children: o } of e) { + O(this, "getMenusByRouteUuid", (e) => d(this, st).call(this, e, Object.values(d(this, Ie)).flat())); + P(this, it, (e, r, n = []) => { + if (y.isEmpty(e)) return n; + for (const { uuid: i, children: s } of e) { if (i == r) return n.concat(i); - if (!w.isEmpty(o)) return n.concat(i, d(this, ot).call(this, o, r)); + if (!y.isEmpty(s)) return n.concat(i, d(this, it).call(this, s, r)); } return n; }); - N(this, st, (e, r) => { + P(this, st, (e, r) => { var i; let n = []; - for (const o of r) o.widgetType == "redirect" && (o.uuid == e || o.widget == e ? n.push(o) : (i = o.children) != null && i.length && (n = n.concat(d(this, st).call(this, e, o.children)))); + for (const s of r) s.widgetType == "redirect" && (s.uuid == e || s.widget == e ? n.push(s) : (i = s.children) != null && i.length && (n = n.concat(d(this, st).call(this, e, s.children)))); return n; }); O(this, "getCurrentMenu", () => { const { uuid: e } = this.getCurrentRoute() || {}; if (!e) return; const r = this.getMenusByRouteUuid(e); - return w.isEmpty(r) ? void 0 : r[0]; + return y.isEmpty(r) ? void 0 : r[0]; }); O(this, "getCurrentRoute", (e = 0) => { var n; - const r = (n = d(this, we).state.matches[d(this, we).state.matches.length - 1 - e]) == null ? void 0 : n.route; + const r = (n = d(this, ye).state.matches[d(this, ye).state.matches.length - 1 - e]) == null ? void 0 : n.route; if (!r) return null; - for (let [i, o] of d(this, de)) if (o.uri === r.path) return o; + for (let [i, s] of d(this, ce)) if (s.uri === r.path) return s; return null; }); O(this, "getPageParams", (e) => { - var s, a; - const { location: r = {}, matches: n = [] } = ((s = d(this, we)) == null ? void 0 : s.state) || {}, i = { ...((a = n[n.length - 1]) == null ? void 0 : a.params) || {} }, o = r.search; - return o && new URLSearchParams(o).forEach((l, c) => { + var o, a; + const { location: r = {}, matches: n = [] } = ((o = d(this, ye)) == null ? void 0 : o.state) || {}, i = { ...((a = n[n.length - 1]) == null ? void 0 : a.params) || {} }, s = r.search; + return s && new URLSearchParams(s).forEach((l, c) => { i[c] = l; - }), e ? w.get(i, e) : i; + }), e ? y.get(i, e) : i; }); O(this, "usePageParams", (e) => { var n; - let r = Lr() ? { ...Yn(), ...Object.fromEntries(new URLSearchParams(((n = Gn()) == null ? void 0 : n.search) ?? "")) } : this.getPageParams(); - return e ? w.get(r, e) : r; + let r = Ir() ? { ...qn(), ...Object.fromEntries(new URLSearchParams(((n = _n()) == null ? void 0 : n.search) ?? "")) } : this.getPageParams(); + return e ? y.get(r, e) : r; }); O(this, "createBrowserRouter", (e = {}) => { - if (d(this, de).size == 0) return null; - if (d(this, we)) return d(this, we); - const r = We.get("Common.WEBSITE_DEFAULT_THEME", "@pkg/ff/frameworks/DefaultTheme"), n = We.get(X.checkUserToken() ? "Common.WEBSITE_LOGIN_REDIRECT" : "Common.WEBSITE_DEFAULT", "/index"), i = { [r]: 0 }, o = (a, l) => () => Promise.all([X.getWidgetComponent(a), Pt(l)]).then(([c, u]) => [c.default || function() { + if (d(this, ce).size == 0) return null; + if (d(this, ye)) return d(this, ye); + const r = We.get("Common.WEBSITE_DEFAULT_THEME", "@pkg/ff/frameworks/DefaultTheme"), n = We.get(X.checkUserToken() ? "Common.WEBSITE_LOGIN_REDIRECT" : "Common.WEBSITE_DEFAULT", "/index"), i = { [r]: 0 }, s = (a, l) => () => Promise.all([X.getWidgetComponent(a), $t(l)]).then(([c, u]) => [c.default || function() { return `${a}`; - }, u]).then(([c, u]) => ({ Component: () => E.createElement(Vr, {}, E.createElement(c, { $setting: u })) })), s = Array.from(d(this, de).values()).reduce((a, { uuid: l, uri: c, name: u, type: p, component: m, widgetSetting: g, widgetProps: f, isLogin: y, isLayout: k, extra: b }) => { - let $ = {}, C = 0; + }, u]).then(([c, u]) => ({ Component: () => E.createElement(ei, {}, E.createElement(c, { $setting: u })) })), o = Array.from(d(this, ce).values()).reduce((a, { uuid: l, uri: c, name: u, type: p, component: m, widgetSetting: g, widgetProps: w, isLogin: f, isLayout: C, extra: b }) => { + let S = {}, k = 0; switch (p) { case "list": - $.element = E.createElement(vi, { component: m, $props: f }); + S.element = E.createElement(vi, { component: m, $props: w }); break; case "fsdpf-component": - $.element = E.createElement(Ni, { key: c, component: m, $setting: g, $props: f }); + S.element = E.createElement(Pi, { key: c, component: m, $setting: g, $props: w }); } - const x = (b == null ? void 0 : b.theme) ?? (b == null ? void 0 : b.layout); - if (x) { - const F = (b == null ? void 0 : b.themeProps) ?? (b == null ? void 0 : b.layoutProps); - if (!i[x]) return i[x] = a.length, [...a, { path: "/", lazy: o(x, F), children: [{ path: c, ...$ }] }]; - C = i[x]; + const $ = (b == null ? void 0 : b.theme) ?? (b == null ? void 0 : b.layout); + if ($) { + const R = (b == null ? void 0 : b.themeProps) ?? (b == null ? void 0 : b.layoutProps); + if (!i[$]) return i[$] = a.length, [...a, { path: "/", lazy: s($, R), children: [{ path: c, ...S }] }]; + k = i[$]; } - return k && C > -1 ? (a[C].children.push({ path: c, ...$ }), a) : [...a, { path: c, ...$ }]; - }, [{ path: "/", lazy: o(r, {}), children: [] }]); - return s.push({ index: !0, element: E.createElement(Ti, { to: n, replace: !0 }) }), K(this, we, Xn(s, e)); + return C && k > -1 ? (a[k].children.push({ path: c, ...S }), a) : [...a, { path: c, ...S }]; + }, [{ path: "/", lazy: s(r, {}), children: [] }]); + return o.push({ index: !0, element: E.createElement(Ni, { to: n, replace: !0 }) }), K(this, ye, Hn(o, e)); }); - if (d(fe, je)) return d(fe, je); + if (d(me, Te)) return d(me, Te); } }; -je = new WeakMap(), de = new WeakMap(), Ae = new WeakMap(), we = new WeakMap(), ot = new WeakMap(), st = new WeakMap(), N(fe, je, null), O(fe, "getInstance", () => (d(fe, je) || K(fe, je, new fe()), d(fe, je))); -let Kt = fe; -const Ti = ({ to: t, replace: e }) => Lr() ? E.createElement(Zn, { to: t, replace: e }) : (window.document.location = t, "redirect"), Se = Kt.getInstance(); -Qt.chainableTypes = [In]; -const ze = Qt.getInstance(new URL("/ff-worker-pipe/worker.js", self.location), { type: "module" }); -Qt.fns = { http: Object.fromEntries(["get", "post", "put", "del", "list", "decode", "encode", "cache", "refreshCache"].map((t) => [t, (...e) => B[t](...e)])), generateUUID: () => Ai(), user: { logout: () => X.logout(() => window.location.replace(We.get("Common.WEBSITE_LOGIN_PAGE", "/index"))), getUserInfo: (t = !0) => X.getUserInfo(t), checkUserToken: () => X.checkUserToken(), getUserToken: () => X.getUserToken() }, getConfigure: (t) => We.get(t), route: Object.fromEntries(["redirect", "getPageParams", "getCurrentRoute", "get", "getMenus", "findMenuPathByUuid"].map((t) => [t, (...e) => Se[t](...e)])), popup: Object.fromEntries(["notification", "success", "error", "form", "modal", "confirm"].map((t) => [t, (...e) => Ee[t](...e)])) }; -const Pr = { null2json: (t) => Object.create(), null2array: (t) => [], null2number: (t) => 0, null2bool: (t) => !1, null2string: (t) => "", null2integer: (t) => 0, null2float: (t) => 0, string2json: (t) => t ? JSON.parse(t) : "{}", string2array: (t) => t.substr(0, 1) === "[" && t.substr(-1) === "]" ? JSON.parse(t) : t.split(","), string2number: (t) => t == "" ? 0 : +t, string2integer: (t) => t == "" ? 0 : +t, string2float: (t) => t == "" ? 0 : +t, string2bool: (t) => { +Te = new WeakMap(), ce = new WeakMap(), Ie = new WeakMap(), ye = new WeakMap(), it = new WeakMap(), st = new WeakMap(), P(me, Te, null), O(me, "getInstance", () => (d(me, Te) || K(me, Te, new me()), d(me, Te))); +let zt = me; +const Ni = ({ to: t, replace: e }) => Ir() ? E.createElement(Jn, { to: t, replace: e }) : (window.document.location = t, "redirect"), ke = zt.getInstance(); +Zt.chainableTypes = [Fn]; +const Be = Zt.getInstance(new URL("/ff-worker-pipe/worker.js", self.location), { type: "module" }); +Zt.fns = { http: Object.fromEntries(["get", "post", "put", "del", "list", "decode", "encode", "cache", "refreshCache"].map((t) => [t, (...e) => U[t](...e)])), generateUUID: () => Ii(), user: { logout: () => X.logout(() => window.location.replace(We.get("Common.WEBSITE_LOGIN_PAGE", "/index"))), getUserInfo: (t = !0) => X.getUserInfo(t), checkUserToken: () => X.checkUserToken(), getUserToken: () => X.getUserToken() }, getConfigure: (t) => We.get(t), route: Object.fromEntries(["redirect", "getPageParams", "getCurrentRoute", "get", "getMenus", "findMenuPathByUuid"].map((t) => [t, (...e) => ke[t](...e)])), popup: Object.fromEntries(["notification", "success", "error", "form", "modal", "confirm"].map((t) => [t, (...e) => Ee[t](...e)])) }; +const $r = { null2json: (t) => Object.create(), null2array: (t) => [], null2number: (t) => 0, null2bool: (t) => !1, null2string: (t) => "", null2integer: (t) => 0, null2float: (t) => 0, string2json: (t) => t ? JSON.parse(t) : "{}", string2array: (t) => t.substr(0, 1) === "[" && t.substr(-1) === "]" ? JSON.parse(t) : t.split(","), string2number: (t) => t == "" ? 0 : +t, string2integer: (t) => t == "" ? 0 : +t, string2float: (t) => t == "" ? 0 : +t, string2bool: (t) => { switch (`${t}`.toLowerCase()) { case "0": case "false": @@ -583,86 +572,86 @@ const Pr = { null2json: (t) => Object.create(), null2array: (t) => [], null2numb return !1; } return !!t; -}, string2string: (t) => t, json2json: (t) => t, json2array: (t) => t ? Object.values(t) : [], json2number: (t) => Object.keys(t).length, json2integer: (t) => Object.keys(t).length, json2float: (t) => Object.keys(t).length, json2bool: (t) => Object.keys(t).length > 0, json2string: (t) => t ? JSON.stringify(t) : "", array2json: (t) => ({ ...t }), array2array: (t) => t, array2number: (t) => t.length, array2integer: (t) => t.length, array2float: (t) => t.length, array2bool: (t) => t.length > 0, array2string: (t) => JSON.stringify(t), number2json: (t) => ({}), number2array: (t) => [t], number2number: (t) => t, number2integer: (t) => t, number2float: (t) => t, number2bool: (t) => !!t, number2string: (t) => t.toString(), boolean2json: (t) => ({}), boolean2array: (t) => [], boolean2number: (t) => +t, boolean2integer: (t) => +t, boolean2float: (t) => +t, boolean2bool: (t) => t, boolean2string: (t) => t ? "true" : "false" }, oe = (t, e) => { +}, string2string: (t) => t, json2json: (t) => t, json2array: (t) => t ? Object.values(t) : [], json2number: (t) => Object.keys(t).length, json2integer: (t) => Object.keys(t).length, json2float: (t) => Object.keys(t).length, json2bool: (t) => Object.keys(t).length > 0, json2string: (t) => t ? JSON.stringify(t) : "", array2json: (t) => ({ ...t }), array2array: (t) => t, array2number: (t) => t.length, array2integer: (t) => t.length, array2float: (t) => t.length, array2bool: (t) => t.length > 0, array2string: (t) => JSON.stringify(t), number2json: (t) => ({}), number2array: (t) => [t], number2number: (t) => t, number2integer: (t) => t, number2float: (t) => t, number2bool: (t) => !!t, number2string: (t) => t.toString(), boolean2json: (t) => ({}), boolean2array: (t) => [], boolean2number: (t) => +t, boolean2integer: (t) => +t, boolean2float: (t) => +t, boolean2bool: (t) => t, boolean2string: (t) => t ? "true" : "false" }, ie = (t, e) => { let r = "string"; - r = Array.isArray(t) ? "array" : typeof t, w.isObject(t) && (r = "json"); + r = Array.isArray(t) ? "array" : typeof t, y.isObject(t) && (r = "json"); const n = `${r}2${e}`; - return Reflect.has(Pr, n) ? Pr[n](t) : t; -}, Oi = (t) => t === null ? "null" : Array.isArray(t) ? "array" : typeof t == "object" ? "json" : typeof t == "boolean" ? "bool" : typeof t == "string" ? "string" : typeof t == "number" ? Number.isInteger(t) ? "integer" : "float" : typeof t, Pt = (t = {}, e = {}, r = {}, n = "") => Qr(t, (i, o) => o === "type" && i === "code") ? en(t, e, r, n) : tn(t, e, n), Qr = (t, e = () => !1) => w.some(t, (r) => !!w.some(r, e) || (w.isEmpty(r) || !w.isPlainObject(r) && !w.isArray(r) ? void 0 : Qr(r, e))), en = async (t = {}, e = {}, r = {}, n = "") => { + return Reflect.has($r, n) ? $r[n](t) : t; +}, Oi = (t) => t === null ? "null" : Array.isArray(t) ? "array" : typeof t == "object" ? "json" : typeof t == "boolean" ? "bool" : typeof t == "string" ? "string" : typeof t == "number" ? Number.isInteger(t) ? "integer" : "float" : typeof t, $t = (t = {}, e = {}, r = {}, n = "") => Jr(t, (i, s) => s === "type" && i === "code") ? Gr(t, e, r, n) : Yr(t, e, n), Jr = (t, e = () => !1) => y.some(t, (r) => !!y.some(r, e) || (y.isEmpty(r) || !y.isPlainObject(r) && !y.isArray(r) ? void 0 : Jr(r, e))), Gr = async (t = {}, e = {}, r = {}, n = "") => { let i = /* @__PURE__ */ Object.create(null); - for (let o in t) { - let s; - if (Reflect.has(t[o], "type") && ["code", "field", "router", "query", "string"].includes(t[o].type)) { - const { type: a, value: l = "", default: c = n } = t[o]; + for (let s in t) { + let o; + if (Reflect.has(t[s], "type") && ["code", "field", "router", "query", "string"].includes(t[s].type)) { + const { type: a, value: l = "", default: c = n } = t[s]; switch (a) { case "code": try { - s = await ze.exec(l, e, r); + o = await Be.exec(l, e, r); } catch (u) { console.error("getWidgetPropsData", u); } break; case "field": - s = w.get(e, l) ?? w.get(e, l.substring(l.indexOf(".") + 1)); + o = y.get(e, l) ?? y.get(e, l.substring(l.indexOf(".") + 1)); break; case "router": case "query": - s = Se.getPageParams(l); + o = ke.getPageParams(l); break; case "string": - s = l; + o = l; } - s ?? (s = c); - } else s = await en(t[o], e, r, n); - w.set(i, o, s); + o ?? (o = c); + } else o = await Gr(t[s], e, r, n); + y.set(i, s, o); } return i; -}, tn = (t = {}, e = {}, r = "") => Object.keys(t || {}).reduce((n, i) => { - if (w.isPlainObject(t[i])) { - let o; +}, Yr = (t = {}, e = {}, r = "") => Object.keys(t || {}).reduce((n, i) => { + if (y.isPlainObject(t[i])) { + let s; if (Reflect.has(t[i], "type") && ["field", "router", "query", "string"].includes(t[i].type)) { - const { type: s, value: a = "", default: l = r } = t[i]; - switch (s) { + const { type: o, value: a = "", default: l = r } = t[i]; + switch (o) { case "field": - o = w.get(e, a) ?? w.get(e, a.substring(a.indexOf(".") + 1)); + s = y.get(e, a) ?? y.get(e, a.substring(a.indexOf(".") + 1)); break; case "router": case "query": - o = Se.getPageParams(a); + s = ke.getPageParams(a); break; case "string": - o = a; + s = a; } - o ?? (o = l); - } else o = tn(t[i], e, r); - w.set(n, i, o); + s ?? (s = l); + } else s = Yr(t[i], e, r); + y.set(n, i, s); } return n; -}, {}), jt = (t, e) => t && typeof t == "object" ? Array.isArray(t) ? t.map((r) => jt(r, e)) : Object.keys(t).reduce((r, n) => (e[n] ? r[e[n]] = jt(t[n], e) : r[n] = jt(t[n], e), r), {}) : t, Io = () => "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (t) => { +}, {}), Ft = (t, e) => t && typeof t == "object" ? Array.isArray(t) ? t.map((r) => Ft(r, e)) : Object.keys(t).reduce((r, n) => (e[n] ? r[e[n]] = Ft(t[n], e) : r[n] = Ft(t[n], e), r), {}) : t, Fs = () => "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (t) => { const e = 16 * Math.random() | 0; return (t === "x" ? e : 3 & e | 8).toString(16); -}), Lo = (t) => { +}), Ts = (t) => { var e, r; return t ? (r = (e = t.match(/^@pkg(?:[^\/]*\/){3}(?[^\/]+)/)) == null ? void 0 : e.groups) == null ? void 0 : r.name : ""; -}, Vo = (t) => { +}, Is = (t) => { var e, r; return t ? (r = (e = t.match(/^@pkg(?:[^\/]*\/){2}(?[^\/]+)/)) == null ? void 0 : e.groups) == null ? void 0 : r.category : ""; -}, Do = (t) => { +}, As = (t) => { var e, r; return t ? (r = (e = t.match(/^@pkg(?:[^\/]*\/){1}(?[^\/]+)/)) == null ? void 0 : e.groups) == null ? void 0 : r.owner : ""; }, Ri = (t, e = 32, r = "auto") => { - const n = _t(t), i = r === "auto" ? "x64" : r; - if (e === 32) return Ft.x86.hash32(n).toString(); - if (e === 128) return i === "x64" ? Ft.x64.hash128(n) : Ft.x86.hash128(n); + const n = Kt(t), i = r === "auto" ? "x64" : r; + if (e === 32) return Rt.x86.hash32(n).toString(); + if (e === 128) return i === "x64" ? Rt.x64.hash128(n) : Rt.x86.hash128(n); throw new Error("bits 只能是 32 或 128"); -}, _t = (t) => t == null ? "null" : typeof t == "string" ? t : typeof t == "number" || typeof t == "boolean" ? String(t) : typeof t == "function" ? t.toString() : Array.isArray(t) ? "[" + t.map(_t).join(",") + "]" : typeof t == "object" ? "{" + Object.keys(t).sort().map((e) => `${e}:${_t(t[e])}`).join(",") + "}" : String(t), Fi = () => { +}, Kt = (t) => t == null ? "null" : typeof t == "string" ? t : typeof t == "number" || typeof t == "boolean" ? String(t) : typeof t == "function" ? t.toString() : Array.isArray(t) ? "[" + t.map(Kt).join(",") + "]" : typeof t == "object" ? "{" + Object.keys(t).sort().map((e) => `${e}:${Kt(t[e])}`).join(",") + "}" : String(t), Fi = () => { let t = 1; const e = /* @__PURE__ */ new WeakMap(), r = /* @__PURE__ */ new Map(); return (...n) => n.length === 0 ? "" : n.map((i) => { - return String((o = i) === null || typeof o != "object" && typeof o != "function" ? (r.has(o) || r.set(o, t++), r.get(o)) : (e.has(o) || e.set(o, t++), e.get(o))); - var o; + return String((s = i) === null || typeof s != "object" && typeof s != "function" ? (r.has(s) || r.set(s, t++), r.get(s)) : (e.has(s) || e.set(s, t++), e.get(s))); + var s; }).join("::"); -}, ji = (t) => { +}, Ti = (t) => { if (!t || typeof t != "string" || t.startsWith("/") || t.startsWith("./") || t.startsWith("../")) return !1; try { let e = t.startsWith("//") ? `http:${t}` : t; @@ -670,84 +659,84 @@ const Pr = { null2json: (t) => Object.create(), null2array: (t) => [], null2numb } catch { return !1; } -}, Mo = (t, e = "") => { - if (!t || typeof t != "string" || ji(t)) return t; +}, js = (t, e = "") => { + if (!t || typeof t != "string" || Ti(t)) return t; let r = e; return !r && typeof window < "u" && window.location && (r = `${window.location.protocol}//${window.location.host}`), t.startsWith("/") ? r ? `${r}${t}` : t : r ? `${r}/${t}` : t; -}, Ai = () => typeof crypto < "u" && crypto.randomUUID ? crypto.randomUUID() : typeof crypto < "u" && crypto.getRandomValues ? "10000000-1000-4000-8000-100000000000".replace(/[018]/g, (t) => (+t ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> +t / 4).toString(16)) : "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (t) => { +}, Ii = () => typeof crypto < "u" && crypto.randomUUID ? crypto.randomUUID() : typeof crypto < "u" && crypto.getRandomValues ? "10000000-1000-4000-8000-100000000000".replace(/[018]/g, (t) => (+t ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> +t / 4).toString(16)) : "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (t) => { const e = 16 * Math.random() | 0; return (t === "x" ? e : 3 & e | 8).toString(16); -}), vt = () => { - const t = J(!0), [, e] = E.useReducer((r) => r + 1, 0); +}), xt = () => { + const t = _(!0), [, e] = E.useReducer((r) => r + 1, 0); return z(() => () => t.current = !1, []), () => t.current && e(); -}, Bo = (t) => { - const [e, r] = V(t), n = J(null), i = H((o, s) => { - n.current = s, r(o); +}, Ls = (t) => { + const [e, r] = L(t), n = _(null), i = H((s, o) => { + n.current = o, r(s); }, []); return z(() => { n.current && (n.current(e), n.current = null); }, [e]), [e, i]; -}, gt = (t = (n) => { -}, e, r = w.isEqual) => { +}, vt = (t = (n) => { +}, e, r = y.isEqual) => { const n = E.useRef(); - r(e, n.current) || (n.current = w.cloneDeep(e)), E.useEffect(t, [n.current]); -}, Nt = gt, rn = (t, e = "string") => { + r(e, n.current) || (n.current = y.cloneDeep(e)), E.useEffect(t, [n.current]); +}, Pt = vt, Xr = (t, e = "string") => { var r; if (!Array.isArray(t)) return t; - for (let n = 0; n < t.length; n++) t[n].value = oe((r = t[n]) == null ? void 0 : r.value, e), t[n] && Reflect.has(t[n], "children") && (t[n].children = rn(t[n].children, e)); + for (let n = 0; n < t.length; n++) t[n].value = ie((r = t[n]) == null ? void 0 : r.value, e), t[n] && Reflect.has(t[n], "children") && (t[n].children = Xr(t[n].children, e)); return t; -}, Uo = (t, e = "json", r = "string", n = null, i = null) => { - const [o] = se.useForm(n), [s, a] = V([{ label: "无", value: "", disabled: !0 }]), l = J([]), c = se.useWatch((u) => l.current.length === 0 ? null : w.pick(u, l.current), o) || null; +}, Ms = (t, e = "json", r = "string", n = null, i = null) => { + const [s] = se.useForm(n), [o, a] = L([{ label: "无", value: "", disabled: !0 }]), l = _([]), c = se.useWatch((u) => l.current.length === 0 ? null : y.pick(u, l.current), s) || null; return z(() => { - Array.isArray(t) ? a(t) : e === "javascript" && t ? ze.exec(t, {}, { getFieldValue: (u) => (l.current.includes(u) || l.current.push(u), o.getFieldValue(u)), getFieldValueForBasicForm: (u) => (l.current.includes(u) || l.current.push(u), i ? i.getFieldValue(u) : o.getFieldValue(u)) }).then((u) => { - a(oe(u, "array")); - }).catch((u) => console.error("useOptions", u)) : t && a(oe(t, "array")); - }, [t, e, c]), rn(s, r); -}, Wo = (t) => { - const [e, r] = V(), n = { type: "GET" }; - if (typeof t == "string" ? n.url = t : w.isPlainObject(t) && Object.assign(n, t), !(n != null && n.url)) throw "url is required"; - const i = (o) => B.request(n, !1).resp((s) => (console.log("useSubscribeRequest", o), r(s), s)); - return gt(() => { - let o = null; - return i().then((s) => { - o = Jr.subscribe(w.throttle(i, 180, { leading: !1, trailing: !0 }), s.res); - }), () => o == null ? void 0 : o(); + Array.isArray(t) ? a(t) : e === "javascript" && t ? Be.exec(t, {}, { getFieldValue: (u) => (l.current.includes(u) || l.current.push(u), s.getFieldValue(u)), getFieldValueForBasicForm: (u) => (l.current.includes(u) || l.current.push(u), i ? i.getFieldValue(u) : s.getFieldValue(u)) }).then((u) => { + a(ie(u, "array")); + }).catch((u) => console.error("useOptions", u)) : t && a(ie(t, "array")); + }, [t, e, c]), Xr(o, r); +}, Ds = (t) => { + const [e, r] = L(), n = { type: "GET" }; + if (typeof t == "string" ? n.url = t : y.isPlainObject(t) && Object.assign(n, t), !(n != null && n.url)) throw "url is required"; + const i = (s) => U.request(n, !1).resp((o) => (console.log("useSubscribeRequest", s), r(o), o)); + return vt(() => { + let s = null; + return i().then((o) => { + s = Br.subscribe(y.throttle(i, 180, { leading: !1, trailing: !0 }), o.res); + }), () => s == null ? void 0 : s(); }, n), e; -}, Ii = (t, e) => H((r) => { +}, Ai = (t, e) => H((r) => { const n = {}; - for (const [i, o] of Object.entries(r)) { - const s = t == null ? void 0 : t[i]; - if ((s == null ? void 0 : s.type) === "router" || (s == null ? void 0 : s.type) === "query") { - const a = Se.getCurrentRoute(); - a != null && a.uuid && Se.redirect(a.uuid, { ...Se.getPageParams(), [s.type]: { [s.value || i]: o } }, { isReplaceRouteHistory: !0 }); - } else n[i] = o; + for (const [i, s] of Object.entries(r)) { + const o = t == null ? void 0 : t[i]; + if ((o == null ? void 0 : o.type) === "router" || (o == null ? void 0 : o.type) === "query") { + const a = ke.getCurrentRoute(); + a != null && a.uuid && ke.redirect(a.uuid, { ...ke.getPageParams(), [o.type]: { [o.value || i]: s } }, { isReplaceRouteHistory: !0 }); + } else n[i] = s; } Object.keys(n).length > 0 && e(n); -}, [t, e]), nn = (t, e = {}, r = {}, n = []) => { - const [i, o] = V({}), [s, a] = V({}), l = Ar(s), c = Se.usePageParams(); +}, [t, e]), Zr = (t, e = {}, r = {}, n = []) => { + const [i, s] = L({}), [o, a] = L({}), l = Fr(o), c = ke.usePageParams(); Gt(() => { - Promise.resolve(Pt(t, e, r)).then(a); - }, [t, e, c, ...n]), Xt(() => { - const m = l ?? {}, g = Object.keys({ ...m, ...s }).reduce((f, y) => (m[y] !== s[y] && (f[y] = s[y]), f), {}); - Object.keys(g).length > 0 && o((f) => ({ ...f, ...g })); - }, [s]); - const u = Ii(t, (m) => { - o((g) => ({ ...g, ...m })); - }), p = W(() => Object.fromEntries(Object.entries(i).filter(([m, g]) => g !== s[m])), [i, s]); + Promise.resolve($t(t, e, r)).then(a); + }, [t, e, c, ...n]), Yt(() => { + const m = l ?? {}, g = Object.keys({ ...m, ...o }).reduce((w, f) => (m[f] !== o[f] && (w[f] = o[f]), w), {}); + Object.keys(g).length > 0 && s((w) => ({ ...w, ...g })); + }, [o]); + const u = Ai(t, (m) => { + s((g) => ({ ...g, ...m })); + }), p = W(() => Object.fromEntries(Object.entries(i).filter(([m, g]) => g !== o[m])), [i, o]); return [i, u, p]; -}, Li = (t) => { +}, ji = (t) => { const [e, r] = E.useState({ items: [], hides: [] }); return E.useEffect(() => { - t && B.get(`/api/_/${t}`).then(({ pk: n, uuid: i, code: o, resource: s, align: a, cols: l, rowHeight: c, marginX: u, marginY: p, listenChangeFields: m, listenChangeFieldsFunc: g, fields: f, theme: y, themeSetting: k, groups: b }) => ({ pk: n, uuid: i, code: o, resource: s, align: a, cols: l, rowHeight: c, marginX: u, marginY: p, theme: y, themeProps: k, groups: b, listenChangeFields: m, listenChangeFieldsFunc: g, ...f.reduce(($, C) => { - var x; - return (x = C == null ? void 0 : C.field) != null && x.hidden ? $.hides.push(C == null ? void 0 : C.field) : $.items.push(C), $; + t && U.get(`/api/_/${t}`).then(({ pk: n, uuid: i, code: s, resource: o, align: a, cols: l, rowHeight: c, marginX: u, marginY: p, listenChangeFields: m, listenChangeFieldsFunc: g, fields: w, theme: f, themeSetting: C, groups: b }) => ({ pk: n, uuid: i, code: s, resource: o, align: a, cols: l, rowHeight: c, itemMargin: [p, u], theme: f, themeProps: C, groups: b, listenChangeFields: m, listenChangeFieldsFunc: g, ...w.reduce((S, k) => { + var $; + return ($ = k == null ? void 0 : k.field) != null && $.hidden ? S.hides.push(k == null ? void 0 : k.field) : S.items.push(k), S; }, { items: [], hides: [] }) })).then(r); }, [t]), e; -}, Vi = ({ max: t = 0, min: e = 0, type: r = "", message: n, pattern: i, required: o = !1, validator: s } = {}, a, l) => { - const [c, u] = V([]); +}, Li = ({ max: t = 0, min: e = 0, type: r = "", message: n, pattern: i, required: s = !1, validator: o } = {}, a, l) => { + const [c, u] = L([]); return z(() => { const p = []; - if (o) { + if (s) { let m = l; switch (l) { case "number": @@ -770,378 +759,375 @@ const Pr = { null2json: (t) => Object.create(), null2array: (t) => [], null2numb p.push({ type: "string", pattern: i, message: n }); break; case "validator": - s && p.push(({ getFieldValue: m }) => ({ validator: async (g, f) => { - const y = await ze.exec(s, { value: f, fieldName: a }, { getFieldValue: m }); - return w.isString(y) && y ? Promise.reject(y) : w.isBoolean(y) && !y ? Promise.reject(n) : Promise.resolve(); + o && p.push(({ getFieldValue: m }) => ({ validator: async (g, w) => { + const f = await Be.exec(o, { value: w, fieldName: a }, { getFieldValue: m }); + return y.isString(f) && f ? Promise.reject(f) : y.isBoolean(f) && !f ? Promise.reject(n) : Promise.resolve(); } })); } u(p); - }, [t, e, r, n, i, o, s]), c; -}, Di = (t, e, r) => { - const [n, i] = V(null); + }, [t, e, r, n, i, s, o]), c; +}, Mi = (t, e, r) => { + const [n, i] = L(null); return z(() => { - const { initDataUri: o = `/api/${t}`, initDataMethod: s = "GET" } = r || {}; - e && B.request({ method: s, url: w.trimEnd(`${o}/${e}`, "/") }).then((a) => { + const { initDataUri: s = `/api/${t}`, initDataMethod: o = "GET" } = r || {}; + e && U.request({ method: o, url: y.trimEnd(`${s}/${e}`, "/") }).then((a) => { i(a); }); }, [t, e, r]), n; -}, Mi = (t, e, r) => H((n, i = { serialize: (o) => o, onSuccess: () => { -}, onFail: (o) => (o == null ? void 0 : o.errorFields) && Ee.error("请先完善表单信息", { duration: 2e3 }) }) => { - const o = n.getFieldValue("__RESOURCE__"), { submitDataUri: s = `/api/${t}`, submitDataMethod: a = "POST" } = r || {}; - return n.validateFields().then((l) => o ? w.pick(l, [o]) : l).then(i.serialize).then((l) => B.request({ method: a, url: w.trimEnd(`${s}/${e || ""}`, "/"), data: l }).msg(i.onSuccess)).catch(i.onFail); -}, [t, e, r]), Bi = (t, e, r, n) => { - const i = Di(e, r, n); +}, Di = (t, e, r) => H((n, i = { serialize: (s) => s, onSuccess: () => { +}, onFail: (s) => (s == null ? void 0 : s.errorFields) && Ee.error("请先完善表单信息", { duration: 2e3 }) }) => { + const s = n.getFieldValue("__RESOURCE__"), { submitDataUri: o = `/api/${t}`, submitDataMethod: a = "POST" } = r || {}; + return n.validateFields().then((l) => s ? y.pick(l, [s]) : l).then(i.serialize).then((l) => U.request({ method: a, url: y.trimEnd(`${o}/${e || ""}`, "/"), data: l }).msg(i.onSuccess)).catch(i.onFail); +}, [t, e, r]), Vi = (t, e, r, n) => { + const i = Mi(e, r, n); z(() => { i ? t.setFieldsValue(i) : t.resetFields(); }, [t, i]); - const o = Mi(e, r, n); - return w.partial(o, t); + const s = Di(e, r, n); + return y.partial(s, t); }, Ui = (t, e, r = [], n = {}) => { - const i = J({}), o = J(), s = w.debounce(vt(), 180), a = ["disabled", "required"], l = (m, g) => { - a.includes(m) && (i.current[m] = g), s(); - }, c = W(() => ({ setDisabled: (m) => l("disabled", m), setRequired: (m) => l("required", m), getDisabled: () => i.current.disabled, getRequired: () => i.current.required }), [e]), [u, p] = Yr(e, -1, {}, c, n); - if (!p && o.current != u && (u >= 0 || !w.isEmpty(r == null ? void 0 : r[u]))) { - o.current = u; - const { widget: m, widgetPrefix: g, props: f } = r == null ? void 0 : r[u]; - t = Br(m, g), i.current = w.merge(f, w.pick(i.current, a)); + const i = _({}), s = _(), o = y.debounce(xt(), 180), a = ["disabled", "required"], l = (m, g) => { + a.includes(m) && (i.current[m] = g), o(); + }, c = W(() => ({ setDisabled: (m) => l("disabled", m), setRequired: (m) => l("required", m), getDisabled: () => i.current.disabled, getRequired: () => i.current.required }), [e]), [u, p] = Kr(e, -1, {}, c, n); + if (!p && s.current != u && (u >= 0 || !y.isEmpty(r == null ? void 0 : r[u]))) { + s.current = u; + const { widget: m, widgetPrefix: g, props: w } = r == null ? void 0 : r[u]; + t = Lr(m, g), i.current = y.merge(w, y.pick(i.current, a)); } return [t, i.current]; -}, vr = (t) => t === void 0 || t === !1 ? "" : (Array.isArray(t) ? t : [t]).join("_"), zo = ({ value: t, onChange: e }, r = null) => { - const n = J(), [i] = se.useForm(r), o = J({}); - return Nt(() => { - w.isEqual(n.current, t) || i.setFieldsValue(t); - }, [t]), z(() => () => i.resetFields(), []), [W(() => i.__INTERNAL__ ? i : { ...i, __INTERNAL__: { itemRef: (s) => (a) => { - const l = vr(s); - a ? o.current[l] = a : delete o.current[l]; - } }, scrollToField: (s, a = {}) => { +}, xr = (t) => t === void 0 || t === !1 ? "" : (Array.isArray(t) ? t : [t]).join("_"), Vs = ({ value: t, onChange: e }, r = null) => { + const n = _(), [i] = se.useForm(r), s = _({}); + return Pt(() => { + y.isEqual(n.current, t) || i.setFieldsValue(t); + }, [t]), z(() => () => i.resetFields(), []), [W(() => i.__INTERNAL__ ? i : { ...i, __INTERNAL__: { itemRef: (o) => (a) => { + const l = xr(o); + a ? s.current[l] = a : delete s.current[l]; + } }, scrollToField: (o, a = {}) => { console.warn("useMergedFormValuesChange scrollToField not work, unreferenced antd form"); - }, focusField: (s) => { + }, focusField: (o) => { console.warn("useMergedFormValuesChange focusField not work, unreferenced antd form"); - }, getFieldInstance: (s) => { - const a = vr(s); - return o.current[a]; - } }, [i]), (s, a) => { + }, getFieldInstance: (o) => { + const a = xr(o); + return s.current[a]; + } }, [i]), (o, a) => { n.current = a, e == null || e(a); }]; -}, qo = (t, e) => { - const r = oe(w.isEmpty(t) ? [] : t, "array"), n = J([]), i = J(0), o = () => "row-" + i.current++; - return n.current.length !== r.length && (n.current = Array.from({ length: r.length }, (s, a) => n.current[a] ?? o())), { items: r, keyAt: (s) => n.current[s], append: (...s) => { - n.current = ie(n.current, { $push: s.map(o) }), e(ie(r, { $push: s })); - }, prepend: (...s) => { - n.current = ie(n.current, { $unshift: s.map(o) }), e(ie(r, { $unshift: s })); - }, insert: (s, ...a) => { - n.current = ie(n.current, { $splice: [[s, 0, ...a.map(o)]] }), e(ie(r, { $splice: [[s, 0, ...a]] })); - }, remove: (...s) => { - const a = new Set(s); +}, Us = (t, e) => { + const r = ie(y.isEmpty(t) ? [] : t, "array"), n = _([]), i = _(0), s = () => "row-" + i.current++; + return n.current.length !== r.length && (n.current = Array.from({ length: r.length }, (o, a) => n.current[a] ?? s())), { items: r, keyAt: (o) => n.current[o], append: (...o) => { + n.current = ne(n.current, { $push: o.map(s) }), e(ne(r, { $push: o })); + }, prepend: (...o) => { + n.current = ne(n.current, { $unshift: o.map(s) }), e(ne(r, { $unshift: o })); + }, insert: (o, ...a) => { + n.current = ne(n.current, { $splice: [[o, 0, ...a.map(s)]] }), e(ne(r, { $splice: [[o, 0, ...a]] })); + }, remove: (...o) => { + const a = new Set(o); n.current = n.current.filter((l, c) => !a.has(c)), e(r.filter((l, c) => !a.has(c))); }, clear: () => { n.current = [], e([]); - }, update: (s, a) => e(ie(r, { [s]: { $set: a } })), reset: (s) => { - e(oe(w.isEmpty(s) ? [] : s, "array")); - }, swap: (s, a) => { - n.current = ie(n.current, { [s]: { $set: n.current[a] }, [a]: { $set: n.current[s] } }), e(ie(r, { [s]: { $set: r[a] }, [a]: { $set: r[s] } })); - }, move: (s, a) => { - n.current = ie(n.current, { $splice: [[s, 1], [a, 0, n.current[s]]] }), e(ie(r, { $splice: [[s, 1], [a, 0, r[s]]] })); + }, update: (o, a) => e(ne(r, { [o]: { $set: a } })), reset: (o) => { + e(ie(y.isEmpty(o) ? [] : o, "array")); + }, swap: (o, a) => { + n.current = ne(n.current, { [o]: { $set: n.current[a] }, [a]: { $set: n.current[o] } }), e(ne(r, { [o]: { $set: r[a] }, [a]: { $set: r[o] } })); + }, move: (o, a) => { + n.current = ne(n.current, { $splice: [[o, 1], [a, 0, n.current[o]]] }), e(ne(r, { $splice: [[o, 1], [a, 0, r[o]]] })); } }; -}, nr = ({ widget: t = "Input", widgetPrefix: e = "@pkg/ff/grid-layout-forms", widgetDecorator: r, subWidgets: n = [], basicForm: i, ...o }) => { - const s = Br(t, e), [a, l] = Ui(s, r, n, i), [c, u] = V(); +}, rr = ({ widget: t = "Input", widgetPrefix: e = "@pkg/ff/grid-layout-forms", widgetDecorator: r, subWidgets: n = [], basicForm: i, ...s }) => { + const o = Lr(t, e), [a, l] = Ui(o, r, n, i), [c, u] = L(); return z(() => { - a && X.getWidgetComponent(a).then(({ defaultProps: p = {}, default: m }) => ({ default: Wi(m, p, i) })).catch((p) => ({ default: () => `${p}` })).then((p) => u(E.createElement(p.default, o))); - }, [a]), c && E.cloneElement(c, { ...o, ...l }); + a && X.getWidgetComponent(a).then(({ defaultProps: p = {}, default: m }) => ({ default: Wi(m, p, i) })).catch((p) => ({ default: () => `${p}` })).then((p) => u(E.createElement(p.default, s))); + }, [a]), c && E.cloneElement(c, { ...s, ...l }); }, Wi = (t, e = {}, r = null) => (n) => { - const { type: i, code: o, label: s, noStyle: a, style: l, placeholder: c, required: u = !1, extras: p, validators: m, help: g, isVirtual: f, $isReserved: y, initialValue: k, initialValueLanguage: b, ...$ } = w.omit(w.merge({}, e, n), ["convertJs", "convertJsSetting", "widget", "widgetPerfix", "widgetDecorator", "subWidgets", "boxStyle"]), C = Vi(Object.assign({}, m, u ? { required: !0 } : {}), o, i), x = W(() => { - const A = Object.keys((e == null ? void 0 : e.extras) || {}); - return w.over([w.partialRight(w.pick, A), w.partialRight(w.omit, A)]); - }, [e == null ? void 0 : e.extras]), [F, I] = x($), T = { label: s, noStyle: a, style: l, colon: !1, layout: "vertical" }, v = H((A) => A == null ? void 0 : oe(A, i), [i]); - return h(Zt, { name: o, rules: C, initialValue: v(k), normalize: v, children: (A, P, L) => { + const { type: i, code: s, label: o, noStyle: a, style: l, placeholder: c, required: u = !1, extras: p, validators: m, help: g, isVirtual: w, $isReserved: f, initialValue: C, initialValueLanguage: b, ...S } = y.omit(y.merge({}, e, n), ["convertJs", "convertJsSetting", "widget", "widgetPerfix", "widgetDecorator", "subWidgets", "boxStyle"]), k = Li(Object.assign({}, m, u ? { required: !0 } : {}), s, i), $ = W(() => { + const T = Object.keys((e == null ? void 0 : e.extras) || {}); + return y.over([y.partialRight(y.pick, T), y.partialRight(y.omit, T)]); + }, [e == null ? void 0 : e.extras]), [R, I] = $(S), N = { label: o, noStyle: a, style: l, colon: !1, layout: "vertical" }, v = H((T) => T == null ? void 0 : ie(T, i), [i]); + return h(Xt, { name: s, rules: k, initialValue: v(C), normalize: v, children: (T, x, A) => { var M; - return h(t, { type: i, rcform: L, basicForm: r, itemProps: { validateStatus: P.errors.length > 0 ? "error" : "success", tooltip: g || null, help: P.errors.length > 0 ? P.errors.join("、") : null, required: ((M = C == null ? void 0 : C[0]) == null ? void 0 : M.required) || !1, ...T }, fieldProps: { placeholder: c, ...I, ...A }, $setting: Object.assign({}, p, F) }); + return h(t, { type: i, rcform: A, basicForm: r, itemProps: { validateStatus: x.errors.length > 0 ? "error" : "success", tooltip: g || null, help: x.errors.length > 0 ? x.errors.join("、") : null, required: ((M = k == null ? void 0 : k[0]) == null ? void 0 : M.required) || !1, ...N }, fieldProps: { placeholder: c, ...I, ...T }, $setting: Object.assign({}, p, R) }); } }); -}, ir = ({ name: t, form: e = null, basicForm: r = null, style: n = {}, className: i, cols: o = 24, rowHeight: s = 16, itemMargin: a = [8, 16], containerPadding: l = [0, 0], fields: c = [], hides: u = [], primaryKey: p = 0, formProps: m = {}, formFields: g = [], listenChangeFields: f, listenChangeFieldsFunc: y, onValuesChange: k, theme: b, themeProps: $ = {}, groups: C = [{ key: "default", label: "默认" }], children: x, ...F }) => { - const [I] = se.useForm(e), T = H((P, L) => { - k == null || k(P, L), y && Array.isArray(f) && ze.exec(y, { changedValues: P, allValues: L }, { getFieldValue: I.getFieldValue, setFieldValue: I.setFieldValue, setFieldsValue: I.setFieldsValue, isFieldTouched: I.isFieldTouched, isFieldsTouched: I.isFieldsTouched }).catch((M) => console.error("onFormValuesChange", t, M)); - }, [t, I, k, f, y]), v = W(() => [{ name: "__PROPS__", value: m }, { name: "__PRIMARY_KEY__", value: p }].concat(g), [p, m, g]), A = (P, L, M) => { - const U = tr(L, nr, r), Z = qr(F); - return D("div", { ...Z, className: j("ff-grid-layout-form", i), style: { ...n, "--grid-layout-item-margin-x": `${(a == null ? void 0 : a[0]) ?? 8}px`, "--grid-layout-item-margin-y": `${(a == null ? void 0 : a[1]) ?? 16}px`, "--grid-layout-container-padding-y": `${(l == null ? void 0 : l[0]) || 0}px`, "--grid-layout-container-padding-x": `${(l == null ? void 0 : l[1]) || 0}px`, "--grid-layout-cols": o, "--grid-layout-row-height": `${s}px` }, children: [U, M && E.cloneElement(M, { cols: o, rowHeight: s, itemMargin: a, containerPadding: l, fields: L, basicForm: r })] }); +}, Qr = ({ name: t, form: e = null, basicForm: r = null, style: n = {}, className: i, cols: s = 24, rowHeight: o = 16, itemMargin: a = [8, 16], containerPadding: l = [0, 0], fields: c = [], hides: u = [], primaryKey: p = 0, formProps: m = {}, formFields: g = [], listenChangeFields: w, listenChangeFieldsFunc: f, onValuesChange: C, theme: b, themeProps: S = {}, groups: k = [{ key: "default", label: "默认" }], children: $, ...R }) => { + const [I] = se.useForm(e), N = H((x, A) => { + if (C == null || C(x, A), f && Array.isArray(w)) { + const M = { getFieldValue: I.getFieldValue, setFieldValue: I.setFieldValue, setFieldsValue: I.setFieldsValue, isFieldTouched: I.isFieldTouched, isFieldsTouched: I.isFieldsTouched }; + Be.exec(f, { changedValues: x, allValues: A }, M).catch((D) => console.error("onFormValuesChange", t, D)); + } + }, [t, I, C, w, f]), v = W(() => [{ name: "__PROPS__", value: m }, { name: "__PRIMARY_KEY__", value: p }].concat(g), [p, m, g]), T = (x, A, M) => { + const D = er(A, rr, r), Z = Ur(R); + return j("div", { ...Z, className: F("ff-grid-layout-form", i), style: { ...n, "--grid-layout-item-margin-x": `${(a == null ? void 0 : a[0]) ?? 8}px`, "--grid-layout-item-margin-y": `${(a == null ? void 0 : a[1]) ?? 16}px`, "--grid-layout-container-padding-y": `${(l == null ? void 0 : l[0]) || 0}px`, "--grid-layout-container-padding-x": `${(l == null ? void 0 : l[1]) || 0}px`, "--grid-layout-cols": s, "--grid-layout-row-height": `${o}px` }, children: [D, M && E.cloneElement(M, { cols: s, rowHeight: o, itemMargin: a, containerPadding: l, fields: A, basicForm: r })] }); }; - return D(se, { ...F, form: I, fields: v, onValuesChange: T, children: [b ? h(Gr, { ...$, items: C, theme: b, itemRender: A, fields: c, children: x, basicForm: r }) : A(0, c, x), u == null ? void 0 : u.map((P) => { - var L; - return h(Zt, { name: P.code, children: h(zi, { form: I, basicForm: r, name: P.code, type: P.type, initialValue: P.initialValue, initialValueLanguage: (L = P.extras) == null ? void 0 : L.initialValueLanguage }) }, JSON.stringify(P.code)); + return j(se, { ...R, form: I, fields: v, onValuesChange: N, children: [b ? h(qr, { ...S, items: k, theme: b, itemRender: T, fields: c, children: $, basicForm: r }) : T(0, c, $), u == null ? void 0 : u.map((x) => { + var A; + return h(Xt, { name: x.code, children: h(Bi, { form: I, basicForm: r, name: x.code, type: x.type, initialValue: x.initialValue, initialValueLanguage: (A = x.extras) == null ? void 0 : A.initialValueLanguage }) }, JSON.stringify(x.code)); })] }); -}, zi = ({ type: t, initialValue: e, initialValueLanguage: r, onChange: n, basicForm: i }) => { - const [o, s] = Yr(r == "javascript" && e, r == "javascript" ? void 0 : e, {}, {}, i); +}, Bi = ({ type: t, initialValue: e, initialValueLanguage: r, onChange: n, basicForm: i }) => { + const [s, o] = Kr(r == "javascript" && e, r == "javascript" ? void 0 : e, {}, {}, i); return z(() => { - r == "javascript" ? n(oe(o, t)) : e && n(oe(e, t)); - }, [t, e, o]), null; -}; -ir.propTypes = { fields: S.array, hides: S.array }; -const qi = /* @__PURE__ */ ((t) => ({ code: e, isPreview: r = !1, ...n }) => { - const { align: i, autoComplete: o, resource: s, items: a, hides: l, rowHeight: c, marginX: u, marginY: p, cols: m, listenChangeFields: g, listenChangeFieldsFunc: f, pk: y, uuid: k, theme: b, themeProps: $, groups: C } = Li(e), x = W(() => [{ name: "__PK__", value: y }, { name: "__RESOURCE__", value: s }, { name: "__LAYOUT_KEY__", value: e }, { name: "__LAYOUT_UUID__", value: k }], [y, e, k, s]); - return h(t, { name: e, autoComplete: o, theme: b, themeProps: $, groups: C, ...n, formFields: x, listenChangeFields: g, listenChangeFieldsFunc: f, fields: a, hides: l, cols: m, rowHeight: c, itemMargin: [u, p] }); -})(ir), on = ({ $setting: t, $close: e, extras: r, code: n, primaryKey: i, ...o }) => { - const [s] = se.useForm(), a = Bi(s, n, i, t); - return h(re, { actions: D(E.Fragment, { children: [h(R, { name: (t == null ? void 0 : t.okText) || "保存", type: "primary", widget: () => a({ onSuccess: e }) }), h(R, { name: (t == null ? void 0 : t.cancelText) || "取消", widget: () => e(!1) })] }), extras: r, children: h(qi, { form: s, code: n, primaryKey: i, ...o }) }); -}, Nr = /* @__PURE__ */ new Set(), Jt = (t = [], e = 0) => { + r == "javascript" ? n(ie(s, t)) : e && n(ie(e, t)); + }, [t, e, s]), null; +}, zi = /* @__PURE__ */ ((t) => ({ code: e, isPreview: r = !1, ...n }) => { + const { align: i, autoComplete: s, resource: o, items: a, hides: l, rowHeight: c, itemMargin: u, cols: p, listenChangeFields: m, listenChangeFieldsFunc: g, pk: w, uuid: f, theme: C, themeProps: b, groups: S } = ji(e), k = W(() => [{ name: "__PK__", value: w }, { name: "__RESOURCE__", value: o }, { name: "__LAYOUT_KEY__", value: e }, { name: "__LAYOUT_UUID__", value: f }], [w, e, f, o]); + return h(t, { name: e, autoComplete: s, theme: C, themeProps: b, groups: S, ...n, formFields: k, listenChangeFields: m, listenChangeFieldsFunc: g, fields: a, hides: l, cols: p, rowHeight: c, itemMargin: u }); +})(Qr), en = ({ $setting: t, $close: e, extras: r, code: n, primaryKey: i, ...s }) => { + const [o] = se.useForm(), a = Vi(o, n, i, t); + return h(re, { actions: j(E.Fragment, { children: [h(V, { name: (t == null ? void 0 : t.okText) || "保存", type: "primary", widget: () => a({ onSuccess: e }) }), h(V, { name: (t == null ? void 0 : t.cancelText) || "取消", widget: () => e(!1) })] }), extras: r, children: h(zi, { form: o, code: n, primaryKey: i, ...s }) }); +}, vr = /* @__PURE__ */ new Set(), qt = (t = [], e = 0) => { const r = t[e]; - if (r.length && !Nr.has(r)) { + if (r.length && !vr.has(r)) { const n = document.createElement("script"); n.setAttribute("src", r), n.setAttribute("data-namespace", r), t.length > e + 1 && (n.onload = () => { - Jt(t, e + 1); + qt(t, e + 1); }, n.onerror = () => { - Jt(t, e + 1); - }), Nr.add(r), document.body.appendChild(n); + qt(t, e + 1); + }), vr.add(r), document.body.appendChild(n); } -}, kt = ({ className: t, type: e, style: r = {}, rotate: n, spin: i, twoToneColor: o, compact: s, ...a }) => h("span", { role: "img", className: j("ff-iconfont", s && "ff-iconfont--compact", t), style: r, ...a, children: h("svg", { style: { width: "1em", height: "1em", fill: "currentColor", overflow: "hidden", ...n != null && { transform: `rotate(${n}deg)` }, ...i && { animation: "ff-iconfont-spin 1s linear infinite" }, ...o && { "--ff-icon-second-color": o } }, viewBox: "0 0 1024 1024", children: h("use", { xlinkHref: `#${e}` }) }) }); -kt.propTypes = { className: S.string, type: S.string.isRequired, style: S.object }, kt.init = Jt; -const Ki = (t, e, r, n) => Se.redirect(r, e, n), _i = (t, e = {}, r, n = {}) => { - var o; - const i = (o = n.router) == null ? void 0 : o.reduce((s, [a, l, c]) => { - const u = w.get(e, ["router", a]); +}, nr = ({ className: t, type: e, style: r = {}, rotate: n, spin: i, twoToneColor: s, compact: o, ...a }) => h("span", { role: "img", className: F("ff-iconfont", o && "ff-iconfont--compact", t), style: r, ...a, children: h("svg", { style: { width: "1em", height: "1em", fill: "currentColor", overflow: "hidden", ...n != null && { transform: `rotate(${n}deg)` }, ...i && { animation: "ff-iconfont-spin 1s linear infinite" }, ...s && { "--ff-icon-second-color": s } }, viewBox: "0 0 1024 1024", children: h("use", { xlinkHref: `#${e}` }) }) }); +nr.init = qt; +const Ki = (t, e, r, n) => ke.redirect(r, e, n), qi = (t, e = {}, r, n = {}) => { + var s; + const i = (s = n.router) == null ? void 0 : s.reduce((o, [a, l, c]) => { + const u = y.get(e, ["router", a]); if (!u && u !== 0 && l) throw `请传入 ${c}`; - return `${s}/${u}`; + return `${o}/${u}`; }, `/api/${r}`); - return B.del(i, e.param).msg(); -}, Tr = (t, e, r, { status: { loading: n, disabled: i }, setStatus: o, listFn: s }) => { - const a = { loading: (l) => l === void 0 ? n : o((c) => ({ ...c, loading: l })), disabled: (l) => l === void 0 ? i : o((c) => ({ ...c, disabled: l })), list: s }; - return w.isFunction(r) ? r.call(null, e, a) : w.isString(r) && r ? ze.exec(r, e, a) : null; -}, Or = (t, e, r, n, i) => w.isString(r) && r ? X.getWidgetComponent(r).then(({ default: o }) => Ee.modal(o, { ...e, $setting: n }, i != null && i.title ? { ...i, title: w.template(i.title)(t) } : i)).catch((o) => { - Ee.error(r, { content: o.toString() }); -}) : Ee.modal(r, { ...e, $setting: n }, i != null && i.title ? { ...i, title: w.template(i.title)(t) } : i), Ji = (t, e, r, n, i) => Ee.modal(on, { ...e, $setting: n, code: r }, i != null && i.title ? { ...i, title: w.template(i.title)(t) } : i), Hi = (t, e, r, n, i) => Ee.modal(rr, { ...n, base62params: e, listCode: r }, i != null && i.title ? { ...i, title: w.template(i.title)(t) } : i), Yi = ({ widget: t, widgetType: e, widgetData: r, widgetProps: n, widgetSetting: i, widgetContainerProps: o }, { onAfterClick: s, onBeforeClick: a } = {}) => { - const l = ue(ae), [c, u] = V({ leading: !0, trailing: !1 }), p = J(null), [m, g] = W(() => { + return U.del(i, e.param).msg(); +}, Pr = (t, e, r, { status: { loading: n, disabled: i }, setStatus: s, listFn: o }) => { + const a = { loading: (l) => l === void 0 ? n : s((c) => ({ ...c, loading: l })), disabled: (l) => l === void 0 ? i : s((c) => ({ ...c, disabled: l })), list: o }; + return y.isFunction(r) ? r.call(null, e, a) : y.isString(r) && r ? Be.exec(r, e, a) : null; +}, Nr = (t, e, r, n, i) => y.isString(r) && r ? X.getWidgetComponent(r).then(({ default: s }) => Ee.modal(s, { ...e, $setting: n }, i != null && i.title ? { ...i, title: y.template(i.title)(t) } : i)).catch((s) => { + Ee.error(r, { content: s.toString() }); +}) : Ee.modal(r, { ...e, $setting: n }, i != null && i.title ? { ...i, title: y.template(i.title)(t) } : i), _i = (t, e, r, n, i) => Ee.modal(en, { ...e, $setting: n, code: r }, i != null && i.title ? { ...i, title: y.template(i.title)(t) } : i), Hi = (t, e, r, n, i) => Ee.modal(tr, { ...n, base62params: e, listCode: r }, i != null && i.title ? { ...i, title: y.template(i.title)(t) } : i), Ji = ({ widget: t, widgetType: e, widgetData: r, widgetProps: n, widgetSetting: i, widgetContainerProps: s }, { onAfterClick: o, onBeforeClick: a } = {}) => { + const l = de(oe), [c, u] = L({ loading: !1, disabled: !1 }), p = _(null), [m, g] = W(() => { switch (e) { case "redirect": - return [w.partialRight(Ki, t, i), null]; + return [y.partialRight(Ki, t, i), null]; case "func": - return [w.partialRight(Tr, (i == null ? void 0 : i.code) ?? t, { status: c, setStatus: u, listFn: l }), null]; + return [y.partialRight(Pr, (i == null ? void 0 : i.code) ?? t, { status: c, setStatus: u, listFn: l }), null]; case "component": case "fsdpf-component": - return [w.partialRight(Or, t, i, o), (y) => ({ $setting: y })]; + return [y.partialRight(Nr, t, i, s), (f) => ({ $setting: f })]; case "grid-layout-form": - return [w.partialRight(Ji, t, i, o), (y) => ({ $setting: y })]; + return [y.partialRight(_i, t, i, s), (f) => ({ $setting: f })]; case "data-list": - return [w.partialRight(Hi, t, i, o), (y) => y]; + return [y.partialRight(Hi, t, i, s), (f) => f]; case "destroy": - return [w.partialRight(_i, t, i, o), null]; + return [y.partialRight(qi, t, i, s), null]; default: - if (sr(t) || E.isValidElement(t)) return [w.partialRight(Or, t, i, o), (y) => ({ $setting: y })]; - if (w.isFunction(t)) return [w.partialRight(Tr, (i == null ? void 0 : i.code) || t, { status: c, setStatus: u }), null]; + if (sr(t) || E.isValidElement(t)) return [y.partialRight(Nr, t, i, s), (f) => ({ $setting: f })]; + if (y.isFunction(t)) return [y.partialRight(Pr, (i == null ? void 0 : i.code) || t, { status: c, setStatus: u }), null]; } - return [(...y) => console.error("useButton unknown widgetType", e, ...y), null]; - }, [t, e, i, o, l.getBase62params, l.getSelectedRows]), f = w.debounce((y) => (a == null || a(y), Promise.resolve(Pt(n, y, { list: l })).then((k) => { - const b = m(y, { ...r, ...k }); - return b != null && b.update && g && (p.current = ($, C) => b.update(g($), C)), b; - }).then((k) => s == null ? void 0 : s(k)).catch(console.error)), 300, { leading: !0, trailing: !1 }); - return Xt(() => { - var y; - (y = p.current) == null || y.call(p, i, o); - }, [i, o]), [f, c]; -}, sn = ({ type: t, name: e, className: r, icon: n, iconPosition: i, size: o }, s = "default") => W(() => { - const a = { type: "primary", className: j("ff-button", r), iconPosition: i, size: o }; - return t === "danger" ? a.danger = !0 : t === "default" && (a.type = t), s === "link" || s === "dashed" ? (a.type = s, t === "default" && (a.className = j(a.className, "ff-default"))) : s !== "circle" && s !== "round" || (a.shape = s), n && (a.icon = h(kt, { type: n })), e && (a.children = e), a; -}, [s, t, r, n, i]), Tt = ({ data: t, widget: e, widgetType: r = "fsdpf-component", widgetData: n, widgetProps: i, widgetSetting: o, widgetContainerProps: s, onAfterClick: a, onBeforeClick: l, children: c, extras: u }) => { - const p = ue(ae), [m, g] = V(!1), [f, y] = V("hover"), [k, b] = nn(i, t, { list: p }, [p.getBase62params, p.getSelectedRows]), [$, C] = V(), { placement: x, align: F, zIndex: I, arrow: T = { pointAtCenter: !0 }, getPopupContainer: v, isPopupMountBodyContainer: A = !0, ...P } = s || {}; + return [(...f) => console.error("useButton unknown widgetType", e, ...f), null]; + }, [t, e, i, s, l.getBase62params, l.getSelectedRows]), w = y.debounce((f) => (a == null || a(f), Promise.resolve($t(n, f, { list: l })).then((C) => { + const b = m(f, { ...r, ...C }); + return b != null && b.update && g && (p.current = (S, k) => b.update(g(S), k)), b; + }).then((C) => o == null ? void 0 : o(C)).catch(console.error)), 300, { leading: !0, trailing: !1 }); + return Yt(() => { + var f; + (f = p.current) == null || f.call(p, i, s); + }, [i, s]), [w, c]; +}, tn = ({ type: t, name: e, className: r, icon: n, iconPosition: i, size: s }, o = "default") => W(() => { + const a = { type: "primary", className: F("ff-button", r), iconPosition: i, size: s }; + return t === "danger" ? a.danger = !0 : t === "default" && (a.type = t), o === "link" || o === "dashed" ? (a.type = o, t === "default" && (a.className = F(a.className, "ff-default"))) : o !== "circle" && o !== "round" || (a.shape = o), n && (a.icon = h(nr, { type: n })), e && (a.children = e), a; +}, [o, t, r, n, i]), _t = ({ data: t, widget: e, widgetType: r = "fsdpf-component", widgetData: n, widgetProps: i, widgetSetting: s, widgetContainerProps: o, onAfterClick: a, onBeforeClick: l, children: c, extras: u }) => { + const p = de(oe), [m, g] = L(!1), [w, f] = L("hover"), [C, b] = Zr(i, t, { list: p }, [p.getBase62params, p.getSelectedRows]), [S, k] = L(), { placement: $, align: R, zIndex: I, arrow: N = { pointAtCenter: !0 }, getPopupContainer: v, isPopupMountBodyContainer: T = !0, ...x } = o || {}; z(() => { - r == "grid-layout-form" ? C(E.createElement(on, { ...n, $setting: o, code: e })) : r == "data-list" ? C(E.createElement(rr, { base62params: t, $setting: o, listCode: e })) : w.isString(e) ? X.getWidgetComponent(e).then(({ default: U }) => { - C(E.createElement(U, { ...n, $setting: o })); - }).catch((U) => C(U.toString())) : E.isValidElement(e) ? C(E.cloneElement(e, { ...n, $setting: o })) : (sr(e) || w.isFunction(e) && ["component", "fsdpf-component"].includes(r)) && C(E.createElement(e, { ...n, $setting: o })); + r == "grid-layout-form" ? k(E.createElement(en, { ...n, $setting: s, code: e })) : r == "data-list" ? k(E.createElement(tr, { base62params: t, $setting: s, listCode: e })) : y.isString(e) ? X.getWidgetComponent(e).then(({ default: D }) => { + k(E.createElement(D, { ...n, $setting: s })); + }).catch((D) => k(D.toString())) : E.isValidElement(e) ? k(E.cloneElement(e, { ...n, $setting: s })) : (sr(e) || y.isFunction(e) && ["component", "fsdpf-component"].includes(r)) && k(E.createElement(e, { ...n, $setting: s })); }, [e, r, n]); - const L = (U, Z = !1) => (g(U), !U && y("hover"), U ? l == null ? void 0 : l(k) : a == null ? void 0 : a(Z)), M = (U) => { - g(!0), y("click"); + const A = (D, Z = !1) => (g(D), !D && f("hover"), D ? l == null ? void 0 : l(C) : a == null ? void 0 : a(Z)), M = (D) => { + g(!0), f("click"); }; - return h(zn, { zIndex: I, placement: x, onPopupClick: M, onClick: M, open: m, align: F, arrow: T, trigger: f, getPopupContainer: v || A ? void 0 : (U) => U, content: h(Gi, { ...P, extras: u, children: $ && E.cloneElement($, { ...k, $setProps: b, $close: (U) => L(!1, U) }) }), children: c, onOpenChange: L }); -}, Gi = ({ title: t, className: e, classNames: r, children: n, extras: i, width: o, height: s, style: a, ...l }) => { - const [c, u] = V({}), p = H((y, k) => u((b) => ({ ...b, [y]: k })), []), m = H((y) => u((k) => ({ ...k, [y]: void 0 })), []), g = t ? E.createElement("div", { className: "ff-popup-title" }, t) : c == null ? void 0 : c.title, f = i ?? E.createElement("div", { className: "ff-popup-reserved-extras" }, i); - return h(Ze.Provider, { value: { ele: c, mount: p, unmount: m }, children: D("div", { className: j("ff-popup ff-popover", e, c.rootClassName), style: { ...a, width: o ?? 260, height: s }, ...l, children: [D("div", { className: j("ff-popup-header", "ff-popover-header", r == null ? void 0 : r.header), children: [g, c == null ? void 0 : c.subTitle] }), h("div", { className: j("ff-popup-body", "ff-popover-body", r == null ? void 0 : r.body), children: n }), D("div", { className: j("ff-popup-footer", "ff-popover-footer", r == null ? void 0 : r.footer), children: [f, c == null ? void 0 : c.extras, c == null ? void 0 : c.actions] })] }) }); -}; -Tt.propTypes = { widgetType: S.oneOf(["fsdpf-component", "grid-layout-form", "data-list"]) }; -const ht = (t) => function({ className: e, variant: r, children: n, name: i, icon: o, type: s = "default", iconPosition: a = "start", noAuthType: l, onAfterClick: c, onBeforeClick: u, data: p, loading: m, disabled: g, tooltip: f, confirm: y, widget: k = () => { -}, widgetType: b, widgetData: $, widgetProps: C, widgetSetting: x, widgetContainerProps: F, ...I }) { - const { mode: T, ...v } = F || {}, A = sn({ className: e, name: i, type: s, icon: o, iconPosition: a }, r ?? t), P = h(bt, { ...A, ...I, children: n || i }); - if (T === "popover" && !["destroy", "redirect", "func"].includes(b)) return h(Tt, { data: p, widget: k, widgetType: b, widgetData: $, widgetProps: C, widgetSetting: x, widgetContainerProps: v, onAfterClick: c, onBeforeClick: u, children: P }); - const L = w.isEmpty(f) || !f.enabled ? {} : f, M = w.isEmpty(y) ? { enabled: !1 } : Object.assign({ enabled: !0 }, y), [U, Z] = V(!1), [$e, { disabled: q, loading: le }] = Yi({ widget: k, widgetType: b, widgetData: $, widgetProps: C, widgetSetting: x, widgetContainerProps: v }, { onAfterClick: c, onBeforeClick: u }); - return h(qn, { okText: "确定", cancelText: "取消", getPopupContainer: (_) => _, ...M, disabled: q || g, open: U, onOpenChange: (_) => { - if (!_) return Z(_); - M.enabled ? Z(_) : $e(p); - }, onConfirm: (_) => { - $e(p, _); - }, onClick: (_) => { - _.stopPropagation(); - }, children: h(Kn, { getPopupContainer: (_) => _, ...L, title: U ? null : L == null ? void 0 : L.title, trigger: ["hover", "click"], children: E.cloneElement(P, { loading: le || m, disabled: q || g }) }) }); -}, R = ht("default"); -R.propTypes = { type: S.oneOf(["primary", "default", "danger", ""]), size: S.oneOf(["large", "middle", "small"]), name: S.string, icon: S.string, iconPosition: S.oneOf(["start", "end"]), data: S.any, widget: S.any, widgetType: S.oneOf(["destroy", "redirect", "func", "component", "fsdpf-component", "grid-layout-form", "grid-layout", "data-list"]), widgetData: S.object, widgetProps: S.object, widgetSetting: S.object, widgetContainerProps: S.object, tooltip: S.exact({ title: S.string.isRequired, placement: S.oneOf(["top", "left", "right", "bottom", "topLeft", "topRight", "bottomLeft", "bottomRight", "leftTop", "leftBottom", "rightTop", "rightBottom"]), enabled: S.oneOfType([S.bool, S.number]), getPopupContainer: S.func }), confirm: S.exact({ title: S.string.isRequired, cancelText: S.string, okText: S.string, okType: S.oneOf(["primary", "default", "danger", ""]), placement: S.oneOf(["top", "left", "right", "bottom", "topLeft", "topRight", "bottomLeft", "bottomRight", "leftTop", "leftBottom", "rightTop", "rightBottom"]), enabled: S.oneOfType([S.bool, S.number]), getPopupContainer: S.func, arrow: S.oneOfType([S.bool, S.exact({ pointAtCenter: S.bool })]) }) }; -const Xi = ht("link"), Zi = ht("circle"), Qi = ht("round"), eo = ht("dashed"), Rr = ({ options: t = [], triggerWeights: e = ["grid-layout-form", "grid-layout", "fsdpf-component", "print"], onAfterClick: r = (g, f, y) => { -}, onBeforeClick: n = (g, f, y) => { -}, labelVariant: i = "link", labelSize: o, labelRender: s, btnVariant: a, btnSize: l, btnRender: c = (g, f) => h(R, { ...g, data: f }, g.uuid || Vt()), widgetContainerProps: u = {}, children: p, data: m }) => { - if (w.isEmpty(t)) return p; - l ?? (l = o), a ?? (a = i); - const [g, f] = W(() => (t || []).reduce((b, $) => { - const C = e.indexOf($.widgetType); - return C === -1 ? b[1].push($) : b[0] ? C < e.indexOf(b[0].widgetType) ? (b[1].push(b[0]), b[0] = $) : b[1].push($) : b[0] = $, b; + return h(Vn, { zIndex: I, placement: $, onPopupClick: M, onClick: M, open: m, align: R, arrow: N, trigger: w, getPopupContainer: v || T ? void 0 : (D) => D, content: h(Gi, { ...x, extras: u, children: S && E.cloneElement(S, { ...C, $setProps: b, $close: (D) => A(!1, D) }) }), children: c, onOpenChange: A }); +}, Gi = ({ title: t, className: e, classNames: r, children: n, extras: i, width: s, height: o, style: a, ...l }) => { + const [c, u] = L({}), p = H((f, C) => u((b) => ({ ...b, [f]: C })), []), m = H((f) => u((C) => ({ ...C, [f]: void 0 })), []), g = t ? E.createElement("div", { className: "ff-popup-title" }, t) : c == null ? void 0 : c.title, w = i ?? E.createElement("div", { className: "ff-popup-reserved-extras" }, i); + return h(Xe.Provider, { value: { ele: c, mount: p, unmount: m }, children: j("div", { className: F("ff-popup ff-popover", e, c.rootClassName), style: { ...a, width: s ?? 260, height: o }, ...l, children: [j("div", { className: F("ff-popup-header", "ff-popover-header", r == null ? void 0 : r.header), children: [g, c == null ? void 0 : c.subTitle] }), h("div", { className: F("ff-popup-body", "ff-popover-body", r == null ? void 0 : r.body), children: n }), j("div", { className: F("ff-popup-footer", "ff-popover-footer", r == null ? void 0 : r.footer), children: [w, c == null ? void 0 : c.extras, c == null ? void 0 : c.actions] })] }) }); +}, pt = (t) => function({ className: e, variant: r, children: n, name: i, icon: s, type: o = "default", iconPosition: a = "start", noAuthType: l, onAfterClick: c, onBeforeClick: u, data: p, loading: m, disabled: g, tooltip: w, confirm: f, widget: C = () => { +}, widgetType: b, widgetData: S, widgetProps: k, widgetSetting: $, widgetContainerProps: R, ...I }) { + const { mode: N, ...v } = R || {}, T = tn({ className: e, name: i, type: o, icon: s, iconPosition: a }, r ?? t), x = h(wt, { ...T, ...I, children: n || i }); + if (N === "popover" && !["destroy", "redirect", "func"].includes(b)) return h(_t, { data: p, widget: C, widgetType: b, widgetData: S, widgetProps: k, widgetSetting: $, widgetContainerProps: v, onAfterClick: c, onBeforeClick: u, children: x }); + const A = y.isEmpty(w) || !w.enabled ? {} : w, M = y.isEmpty(f) ? { enabled: !1 } : Object.assign({ enabled: !0 }, f), [D, Z] = L(!1), [Se, { disabled: B, loading: ae }] = Ji({ widget: C, widgetType: b, widgetData: S, widgetProps: k, widgetSetting: $, widgetContainerProps: v }, { onAfterClick: c, onBeforeClick: u }); + return h(Un, { okText: "确定", cancelText: "取消", getPopupContainer: (q) => q, ...M, disabled: B || g, open: D, onOpenChange: (q) => { + if (!q) return Z(q); + M.enabled ? Z(q) : Se(p); + }, onConfirm: (q) => { + Se(p, q); + }, onClick: (q) => { + q.stopPropagation(); + }, children: h(Wn, { getPopupContainer: (q) => q, ...A, title: D ? null : A == null ? void 0 : A.title, trigger: ["hover", "click"], children: E.cloneElement(x, { loading: ae || m, disabled: B || g }) }) }); +}, V = pt("default"), Yi = pt("link"), Xi = pt("circle"), Zi = pt("round"), Qi = pt("dashed"); +V.Link = Yi, V.Link.defaultProps = V.defaultProps, V.Circle = Xi, V.Circle.defaultProps = V.defaultProps, V.Round = Zi, V.Round.defaultProps = V.defaultProps, V.Dashed = Qi, V.Dashed.defaultProps = V.defaultProps, V.Popover = _t, V.GroupPopover = ({ options: t = [], triggerWeights: e = ["grid-layout-form", "grid-layout", "fsdpf-component", "print"], onAfterClick: r = (g, w, f) => { +}, onBeforeClick: n = (g, w, f) => { +}, labelVariant: i = "link", labelSize: s, labelRender: o, btnVariant: a, btnSize: l, btnRender: c = (g, w) => h(V, { ...g, data: w }, g.uuid || jt()), widgetContainerProps: u = {}, children: p, data: m }) => { + if (y.isEmpty(t)) return p; + l ?? (l = s), a ?? (a = i); + const [g, w] = W(() => (t || []).reduce((b, S) => { + const k = e.indexOf(S.widgetType); + return k === -1 ? b[1].push(S) : b[0] ? k < e.indexOf(b[0].widgetType) ? (b[1].push(b[0]), b[0] = S) : b[1].push(S) : b[0] = S, b; }, [null, []]), [t, e]); - s ? p = s(g, m) || p : p || (p = h(bt, { ...sn(Object.assign(g != null && g.name || g != null && g.icon ? {} : { icon: "icon-location" }, g, { size: o }), i) })); - const y = f.map((b) => c(Object.assign({ uuid: b.uuid, type: b.type, name: b.name, widget: b.widget, widgetType: b.widgetType, widgetProps: b.widgetProps, widgetData: b.widgetData, widgetSetting: b.widgetSetting, widgetContainerProps: b.widgetContainerSetting, confirm: b.confirm, onAfterClick: w.partialRight(r, b, m), onBeforeClick: w.partialRight(n, b, m) }, { size: l, variant: a }), m)); - let k = y; - return (y == null ? void 0 : y.length) > 1 && (k = a == "link" ? h(Mt, { split: h(_n, { type: "vertical" }), size: l, children: y }) : h(Mt.Compact, { size: l, children: y })), g ? h(Tt, { widget: g == null ? void 0 : g.widget, widgetType: g == null ? void 0 : g.widgetType, widgetProps: g == null ? void 0 : g.widgetProps, widgetSetting: g == null ? void 0 : g.widgetSetting, widgetContainerProps: Object.assign({}, u, g == null ? void 0 : g.widgetContainerProps), data: m, widgetData: g == null ? void 0 : g.widgetData, extras: k, onAfterClick: w.partialRight(r, g, m), onBeforeClick: w.partialRight(n, g, m), children: p }) : k; + o ? p = o(g, m) || p : p || (p = h(wt, { ...tn(Object.assign(g != null && g.name || g != null && g.icon ? {} : { icon: "icon-location" }, g, { size: s }), i) })); + const f = w.map((b) => c(Object.assign({ uuid: b.uuid, type: b.type, name: b.name, widget: b.widget, widgetType: b.widgetType, widgetProps: b.widgetProps, widgetData: b.widgetData, widgetSetting: b.widgetSetting, widgetContainerProps: b.widgetContainerSetting, confirm: b.confirm, onAfterClick: y.partialRight(r, b, m), onBeforeClick: y.partialRight(n, b, m) }, { size: l, variant: a }), m)); + let C = f; + return (f == null ? void 0 : f.length) > 1 && (C = a == "link" ? h(Mt, { split: h(Bn, { type: "vertical" }), size: l, children: f }) : h(Mt.Compact, { size: l, children: f })), g ? h(_t, { widget: g == null ? void 0 : g.widget, widgetType: g == null ? void 0 : g.widgetType, widgetProps: g == null ? void 0 : g.widgetProps, widgetSetting: g == null ? void 0 : g.widgetSetting, widgetContainerProps: Object.assign({}, u, g == null ? void 0 : g.widgetContainerProps), data: m, widgetData: g == null ? void 0 : g.widgetData, extras: C, onAfterClick: y.partialRight(r, g, m), onBeforeClick: y.partialRight(n, g, m), children: p }) : C; }; -Rr.propTypes = { triggerWeights: S.array, options: S.arrayOf(S.shape({ ...R.propTypes, widgetType: R.propTypes.widgetType.isRequired })), btnSize: R.propTypes.size, btnRender: S.func, btnVariant: S.oneOf(["", "default", "link", "circle", "round", "dashed"]), labelVariant: S.oneOf(["", "default", "link", "circle", "round", "dashed"]), labelRender: S.func, labelSize: R.propTypes.size, onAfterClick: S.func, onBeforeClick: S.func, widgetContainerProps: R.propTypes.widgetContainerProps, data: R.propTypes.data }, R.Link = Xi, R.Link.defaultProps = R.defaultProps, R.Link.propTypes = R.propTypes, R.Circle = Zi, R.Circle.defaultProps = R.defaultProps, R.Circle.propTypes = R.propTypes, R.Round = Qi, R.Round.defaultProps = R.defaultProps, R.Round.propTypes = R.propTypes, R.Dashed = eo, R.Dashed.defaultProps = R.defaultProps, R.Dashed.propTypes = R.propTypes, R.Popover = Tt, R.GroupPopover = Rr; -const to = ({ fields: t, formProps: e, $close: r }) => { +const es = ({ fields: t, formProps: e, $close: r }) => { const [n] = se.useForm(), i = W(() => [{ name: "__PROPS__", value: e }], [e]); - return h(re, { actions: D(E.Fragment, { children: [h(R, { name: "取消", widget: () => r(!1) }), h(R, { name: "确定", type: "primary", widget: () => n.validateFields(!0).then(r) })] }), children: h(se, { fields: i, form: n, className: "ff-modal-form", children: t == null ? void 0 : t.map(({ code: o, ...s }) => h(nr, { code: o, ...s }, o)) }) }); -}, ro = ({ className: t, classNames: e, $close: r, children: n, title: i, subTitle: o, actions: s, extras: a, ...l }) => D(Qn, { ...l, prefixCls: "ff-drawer", className: j("ff-popup", t), maskMotion: { motionAppear: !0, motionName: "mask-motion" }, motion: (c) => ({ motionAppear: !0, motionName: `panel-motion-${c}` }), children: [D("div", { className: j("ff-popup-header", "ff-drawer-header", e == null ? void 0 : e.header), children: [h("button", { "aria-label": "Close", className: j("ff-popup-close", "ff-drawer-close", e == null ? void 0 : e.close), onClick: l.onClose, children: h(er, { type: "close" }) }), i, o] }), h("div", { className: j("ff-popup-body", "ff-drawer-body", e == null ? void 0 : e.body), children: n }), D("div", { className: j("ff-popup-footer", "ff-drawer-footer", e == null ? void 0 : e.footer), children: [a, s] })] }), no = ({ className: t, classNames: e, $close: r, $event: n, children: i, title: o, subTitle: s, actions: a, extras: l, placement: c, ...u }) => { - const { style: p, rest: m } = ((f, y = ["height", "width", "style"]) => { - const k = { ...f }, b = {}; - for (const $ of y) $ === "style" ? Object.assign(b, k.style) : k[$] !== void 0 && (b[$] = k[$]), delete k[$]; - return { style: b, rest: k }; + return h(re, { actions: j(E.Fragment, { children: [h(V, { name: "取消", widget: () => r(!1) }), h(V, { name: "确定", type: "primary", widget: () => n.validateFields(!0).then(r) })] }), children: h(se, { fields: i, form: n, className: "ff-modal-form", children: t == null ? void 0 : t.map(({ code: s, ...o }) => h(rr, { code: s, ...o }, s)) }) }); +}, ts = ({ className: t, classNames: e, $close: r, children: n, title: i, subTitle: s, actions: o, extras: a, ...l }) => j(Yn, { ...l, prefixCls: "ff-drawer", className: F("ff-popup", t), maskMotion: { motionAppear: !0, motionName: "mask-motion" }, motion: (c) => ({ motionAppear: !0, motionName: `panel-motion-${c}` }), children: [j("div", { className: F("ff-popup-header", "ff-drawer-header", e == null ? void 0 : e.header), children: [h("button", { "aria-label": "Close", className: F("ff-popup-close", "ff-drawer-close", e == null ? void 0 : e.close), onClick: l.onClose, children: h(Qt, { type: "close" }) }), i, s] }), h("div", { className: F("ff-popup-body", "ff-drawer-body", e == null ? void 0 : e.body), children: n }), j("div", { className: F("ff-popup-footer", "ff-drawer-footer", e == null ? void 0 : e.footer), children: [a, o] })] }), rs = ({ className: t, classNames: e, $close: r, $event: n, children: i, title: s, subTitle: o, actions: a, extras: l, placement: c, ...u }) => { + const { style: p, rest: m } = ((w, f = ["height", "width", "style"]) => { + const C = { ...w }, b = {}; + for (const S of f) S === "style" ? Object.assign(b, C.style) : C[S] !== void 0 && (b[S] = C[S]), delete C[S]; + return { style: b, rest: C }; })(u), g = (n == null ? void 0 : n.pageX) === void 0 ? { animation: null, maskAnimation: null, mousePosition: { x: null, y: null } } : { animation: "zoom", maskAnimation: "fade", mousePosition: { x: n == null ? void 0 : n.pageX, y: n == null ? void 0 : n.pageY } }; - return h(ei, { ...m, ...g, prefixCls: "ff-modal", className: j("ff-popup", t), modalRender: () => D(E.Fragment, { children: [h("button", { className: j("ff-popup-close", "ff-modal-close", e == null ? void 0 : e.close), onClick: m.onClose, children: h(er, { type: "close" }) }), D("div", { className: j("ff-modal-content"), style: p, children: [D("div", { className: j("ff-popup-header", "ff-modal-header", e == null ? void 0 : e.header), children: [o, s] }), h("div", { className: j("ff-popup-body", "ff-modal-body", e == null ? void 0 : e.body), children: i }), D("div", { className: j("ff-popup-footer", "ff-modal-footer", e == null ? void 0 : e.footer), children: [l, a] })] })] }) }); -}, an = ({ placement: t, $close: e, $event: r, children: n, title: i, ...o }) => { - const [s, a] = V({}), [l, c] = V(!0), u = H((f, y) => a((k) => ({ ...k, [f]: y })), []), p = H((f) => a((y) => ({ ...y, [f]: void 0 })), []); - let m = { ...o, className: s.rootClassName, title: s.title || i && E.createElement("div", { className: j("ff-popup-title") }, i), subTitle: s.subTitle, actions: s.actions, extras: s.extras, children: n, $close: e, $event: r, onClose: () => c(!1) }; + return h(Xn, { ...m, ...g, prefixCls: "ff-modal", className: F("ff-popup", t), modalRender: () => j(E.Fragment, { children: [h("button", { className: F("ff-popup-close", "ff-modal-close", e == null ? void 0 : e.close), onClick: m.onClose, children: h(Qt, { type: "close" }) }), j("div", { className: F("ff-modal-content"), style: p, children: [j("div", { className: F("ff-popup-header", "ff-modal-header", e == null ? void 0 : e.header), children: [s, o] }), h("div", { className: F("ff-popup-body", "ff-modal-body", e == null ? void 0 : e.body), children: i }), j("div", { className: F("ff-popup-footer", "ff-modal-footer", e == null ? void 0 : e.footer), children: [l, a] })] })] }) }); +}, rn = ({ placement: t, $close: e, $event: r, children: n, title: i, ...s }) => { + const [o, a] = L({}), [l, c] = L(!0), u = H((w, f) => a((C) => ({ ...C, [w]: f })), []), p = H((w) => a((f) => ({ ...f, [w]: void 0 })), []); + let m = { ...s, className: o.rootClassName, title: o.title || i && E.createElement("div", { className: F("ff-popup-title") }, i), subTitle: o.subTitle, actions: o.actions, extras: o.extras, children: n, $close: e, $event: r, onClose: () => c(!1) }; const g = () => { e(!1); }; - return h(Ze.Provider, { value: { ele: s, mount: u, unmount: p }, children: t && t !== "center" ? h(ro, { ...m, placement: t, open: l, afterOpenChange: (f) => !f && g() }) : h(no, { ...m, visible: l, afterClose: g }) }); + return h(Xe.Provider, { value: { ele: o, mount: u, unmount: p }, children: t && t !== "center" ? h(ts, { ...m, placement: t, open: l, afterOpenChange: (w) => !w && g() }) : h(rs, { ...m, visible: l, afterClose: g }) }); }; -an.propTypes = { placement: S.oneOf(["center", "left", "top", "right", "bottom"]) }; -const io = ({ widget: t, widgetProps: e, $close: r, onSetProps: n }) => { - const [i, o] = V(e || {}), s = Ar(e); +rn.propTypes = { placement: Gn.oneOf(["center", "left", "top", "right", "bottom"]) }; +const ns = ({ widget: t, widgetProps: e, $close: r, onSetProps: n }) => { + const [i, s] = L(e || {}), o = Fr(e); Gt(() => { - const l = s ?? {}, c = e ?? {}, u = Object.keys({ ...l, ...c }).reduce((p, m) => (l[m] !== c[m] && (p[m] = c[m]), p), {}); - Object.keys(u).length > 0 && o((p) => ({ ...p, ...u })); + const l = o ?? {}, c = e ?? {}, u = Object.keys({ ...l, ...c }).reduce((p, m) => (l[m] !== c[m] && (p[m] = c[m]), p), {}); + Object.keys(u).length > 0 && s((p) => ({ ...p, ...u })); }, [e]); const a = H((l) => { - o((c) => ({ ...c, ...l })), n == null || n(l); + s((c) => ({ ...c, ...l })), n == null || n(l); }, [n]); - return E.isValidElement(t) ? E.cloneElement(t, { ...i, $close: r, $setProps: a }) : t != null && t.name || Sr.isForwardRef(t) || (t == null ? void 0 : t.$$typeof) === Sr.ForwardRef ? E.createElement(t, { ...i, $close: r, $setProps: a }) : t; -}, G = () => { - const [t, e] = jn({ maxCount: 6, motion: { motionName: "ff-notification-fade", motionAppear: !0, motionEnter: !0, motionLeave: !0, onLeaveStart: (o) => { - const { offsetHeight: s } = o; - return { height: s }; - }, onLeaveActive: () => ({ height: 0, opacity: 0, margin: 0 }) }, prefixCls: "ff-notification" }), [, r] = E.useReducer((o) => o + 1, 0); + return E.isValidElement(t) ? E.cloneElement(t, { ...i, $close: r, $setProps: a }) : t != null && t.name || Cr.isForwardRef(t) || (t == null ? void 0 : t.$$typeof) === Cr.ForwardRef ? E.createElement(t, { ...i, $close: r, $setProps: a }) : t; +}, Y = () => { + const [t, e] = On({ maxCount: 6, motion: { motionName: "ff-notification-fade", motionAppear: !0, motionEnter: !0, motionLeave: !0, onLeaveStart: (s) => { + const { offsetHeight: o } = s; + return { height: o }; + }, onLeaveActive: () => ({ height: 0, opacity: 0, margin: 0 }) }, prefixCls: "ff-notification" }), [, r] = E.useReducer((s) => s + 1, 0); z(() => { - G.$onClick = n, G.$queue.forEach(([o, s, a, l]) => { - l == null || l(i([s, a], ...o)); - }), G.$queue = []; + Y.$onClick = n, Y.$queue.forEach(([s, o, a, l]) => { + l == null || l(i([o, a], ...s)); + }), Y.$queue = []; }, []); - const n = (o, s = {}, a = {}) => { + const n = (s, o = {}, a = {}) => { let l; const c = new Promise((u, p) => { - l = i([u, p], o, s, a); + l = i([u, p], s, o, a); }); return c.update = l, c; - }, i = ([o, s], a, l = {}, c = {}) => { - const u = G.$index++, p = (f) => ((y, k) => (G.$popups.delete(y), r(), k == null ? void 0 : k()))(u, () => o(f)); - if (a === Dr) return t.open({ ...c, key: u, content: E.createElement(a, { ...l, $close: () => t.close(u) }), onClose: () => p() }), () => { + }, i = ([s, o], a, l = {}, c = {}) => { + const u = Y.$index++, p = (w) => ((f, C) => (Y.$popups.delete(f), r(), C == null ? void 0 : C()))(u, () => s(w)); + if (a === Ar) return t.open({ ...c, key: u, content: E.createElement(a, { ...l, $close: () => t.close(u) }), onClose: () => p() }), () => { }; const { $setProps: m, ...g } = l; - return G.$popups.set(u, { widget: a, widgetProps: g, widgetContainerProps: c, $close: p, onSetProps: m }), r(), (f, y) => { - const k = G.$popups.get(u); - k && (G.$popups.set(u, { ...k, widgetProps: f ? { ...k.widgetProps, ...f } : k.widgetProps, widgetContainerProps: y ? { ...k.widgetContainerProps, ...y } : k.widgetContainerProps }), r()); + return Y.$popups.set(u, { widget: a, widgetProps: g, widgetContainerProps: c, $close: p, onSetProps: m }), r(), (w, f) => { + const C = Y.$popups.get(u); + C && (Y.$popups.set(u, { ...C, widgetProps: w ? { ...C.widgetProps, ...w } : C.widgetProps, widgetContainerProps: f ? { ...C.widgetContainerProps, ...f } : C.widgetContainerProps }), r()); }; }; - return D(E.Fragment, { children: [Array.from(G.$popups).map(([o, { widget: s, widgetProps: a, widgetContainerProps: l, $close: c, onSetProps: u }]) => h(an, { maskClosable: !1, $event: a == null ? void 0 : a.$event, ...l, $close: c, children: h(io, { widget: s, widgetProps: a, $close: c, onSetProps: u }) }, o)), e] }); + return j(E.Fragment, { children: [Array.from(Y.$popups).map(([s, { widget: o, widgetProps: a, widgetContainerProps: l, $close: c, onSetProps: u }]) => h(rn, { maskClosable: !1, $event: a == null ? void 0 : a.$event, ...l, $close: c, children: h(ns, { widget: o, widgetProps: a, $close: c, onSetProps: u }) }, s)), e] }); }; -G.$popups = /* @__PURE__ */ new Map(), G.$index = 0, G.$queue = [], G.$onClick = (...t) => { +Y.$popups = /* @__PURE__ */ new Map(), Y.$index = 0, Y.$queue = [], Y.$onClick = (...t) => { const e = new Promise((r, n) => { - G.$queue.push([t, r, n, (i) => { + Y.$queue.push([t, r, n, (i) => { e.update = i; }]); }); return e; }; -const Fr = (t, e, r = {}) => G.$onClick(t, e, r), At = (t, { showProgress: e, duration: r, ...n } = { duration: 1.5 }) => G.$onClick(Dr, { content: t, ...n }, { showProgress: e, duration: r }), Ee = { modal: Fr, confirm: (t, e = {}) => G.$onClick(ni, { content: t, ...e }, { placement: "center" }), form: (t, e = {}, r = {}) => Fr(to, { formProps: r, fields: t }, { placement: "center", ...e }).then((n) => { +const Or = (t, e, r = {}) => Y.$onClick(t, e, r), Tt = (t, { showProgress: e, duration: r, ...n } = { duration: 1.5 }) => Y.$onClick(Ar, { content: t, ...n }, { showProgress: e, duration: r }), Ee = { modal: Or, confirm: (t, e = {}) => Y.$onClick(ti, { content: t, ...e }, { placement: "center" }), form: (t, e = {}, r = {}) => Or(es, { formProps: r, fields: t }, { placement: "center", ...e }).then((n) => { if (n === !1) throw !1; return n; -}), notification: At, success: (t, e = { duration: 1.5 }) => At(t, { ...e, className: "ff-notification-success", icon: "check" }), error: (t, e = { duration: 1.5 }) => At(t, { ...e, className: "ff-notification-error", icon: "close" }) }; -Qe.configure({ showSpinner: !1 }); -const ln = () => { - const t = window.localStorage.getItem(wt); +}), notification: Tt, success: (t, e = { duration: 1.5 }) => Tt(t, { ...e, className: "ff-notification-success", icon: "check" }), error: (t, e = { duration: 1.5 }) => Tt(t, { ...e, className: "ff-notification-error", icon: "close" }) }; +Ze.configure({ showSpinner: !1 }); +const nn = () => { + const t = window.localStorage.getItem(yt); return Object.freeze({ Platform: "web", SaaS: window.localStorage.getItem("SaaS"), Authorization: t ? `Bearer ${t} ` : void 0 }); }; -Ve.interceptors.request.use((t) => (Object.assign(t.headers, ln()), Qe.inc(), t), (t) => (Qe.done(), Promise.reject({ code: -1, msg: t }))), Ve.interceptors.response.use(({ data: t, headers: e }) => (Qe.done(), { ...t, res: e == null ? void 0 : e.res }), function(t) { - return Qe.done(), Promise.reject(t.message); -}), window.addEventListener("unhandledrejection", Dt.onUnhandledRejection), Dt.onMsg = (t, e) => Ee[[0, 1].includes(t) ? "success" : "error"](e).then(() => t === 20300 && Se.redirect(We.get("Common.WEBSITE_LOGIN_PAGE"))); -var He, Ue, Ye; -const ee = class ee { +Le.interceptors.request.use((t) => (Object.assign(t.headers, nn()), Ze.inc(), t), (t) => (Ze.done(), Promise.reject({ code: -1, msg: t }))), Le.interceptors.response.use(({ data: t, headers: e }) => (Ze.done(), { ...t, res: e == null ? void 0 : e.res }), function(t) { + return Ze.done(), Promise.reject(t.message); +}), window.addEventListener("unhandledrejection", Lt.onUnhandledRejection), Lt.onMsg = (t, e) => Ee[[0, 1].includes(t) ? "success" : "error"](e).then(() => t === 20300 && ke.redirect(We.get("Common.WEBSITE_LOGIN_PAGE"))); +var He, Ue, Je; +const Q = class Q { constructor() { O(this, "appUrl", ""); - N(this, He, null); - return d(ee, Ue) || (K(ee, Ye, new Dt()), K(ee, Ue, new Proxy(this, { get(e, r) { + P(this, He, null); + return d(Q, Ue) || (K(Q, Je, new Lt()), K(Q, Ue, new Proxy(this, { get(e, r) { if (r in e) { const n = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(e), r); return n != null && n.get ? Reflect.get(e, r, e) : typeof e[r] == "function" ? e[r].bind(e) : e[r]; } - return d(ee, Ye)[r]; - } }))), d(ee, Ue); + return d(Q, Je)[r]; + } }))), d(Q, Ue); } init(e, r, n) { - Ve.defaults.baseURL = this.appUrl = n, Ve.defaults.timeout = 15e3, d(ee, Ye).init(e, r, Ve); + Le.defaults.baseURL = this.appUrl = n, Le.defaults.timeout = 15e3, d(Q, Je).init(e, r, Le); } get driver() { - return Ve; + return Le; } get headers() { - return ln(); + return nn(); } mock(e = {}) { - return d(this, He) ?? K(this, He, new Ln(Ve, { onNoMatch: "passthrough", ...e })); + return d(this, He) ?? K(this, He, new Tn(Le, { onNoMatch: "passthrough", ...e })); } unmock() { var e; (e = d(this, He)) == null || e.restore(), K(this, He, null); } }; -He = new WeakMap(), Ue = new WeakMap(), Ye = new WeakMap(), N(ee, Ue), N(ee, Ye), O(ee, "getInstance", () => d(ee, Ue) ?? K(ee, Ue, new ee())); -let Ht = ee; -const B = Ht.getInstance(); -class or extends Error { +He = new WeakMap(), Ue = new WeakMap(), Je = new WeakMap(), P(Q, Ue), P(Q, Je), O(Q, "getInstance", () => d(Q, Ue) ?? K(Q, Ue, new Q())); +let Ht = Q; +const U = Ht.getInstance(); +class ir extends Error { constructor(e, r) { - super(r), Error.captureStackTrace && Error.captureStackTrace(this, or), !r instanceof et && (this.name = `${e} Error Runtime`); + super(r), Error.captureStackTrace && Error.captureStackTrace(this, ir), !r instanceof Qe && (this.name = `${e} Error Runtime`); } } -class et extends Error { +class Qe extends Error { constructor(e, ...r) { - super(...r), Error.captureStackTrace && Error.captureStackTrace(this, et), this.name = `${e} Not Found`; + super(...r), Error.captureStackTrace && Error.captureStackTrace(this, Qe), this.name = `${e} Not Found`; } } -const It = "mine", wt = "token", Lt = "user-login-intended-url"; -var Ie, Ge, at; -const ye = class ye { +const It = "mine", yt = "token", At = "user-login-intended-url"; +var Ae, Ge, ot; +const fe = class fe { constructor() { - N(this, Ge, /* @__PURE__ */ new Map()); - N(this, at, (/* @__PURE__ */ new Date()).toISOString().slice(0, 10)); + P(this, Ge, /* @__PURE__ */ new Map()); + P(this, ot, (/* @__PURE__ */ new Date()).toISOString().slice(0, 10)); O(this, "setPkgVersion", (e) => { - K(this, at, e); + K(this, ot, e); }); - O(this, "setVendor", (e, r) => d(this, Ge).set(e, new ti(r, async (n, i) => { - var s, a; + O(this, "setVendor", (e, r) => d(this, Ge).set(e, new Zn(r, async (n, i) => { + var o, a; if (!(n != null && n.default)) throw "@pkg not found"; - let o = () => i; + let s = () => i; switch ("function") { - case typeof (o = (s = n.default) == null ? void 0 : s[`./${i}/index.jsx`]): - case typeof (o = (a = n.default) == null ? void 0 : a[`./${i}/index.js`]): - return o(); + case typeof (s = (o = n.default) == null ? void 0 : o[`./${i}/index.jsx`]): + case typeof (s = (a = n.default) == null ? void 0 : a[`./${i}/index.js`]): + return s(); } - throw new et(i); + throw new Qe(i); }))); O(this, "getWidgetComponent", async (e) => { if (!e) throw "getWidgetComponent widget is required"; if (e != null && e.startsWith("blob:") || e != null && e.startsWith("http:") || e != null && e.startsWith("https:")) return await import(e); const [, r] = e == null ? void 0 : e.split("@pkg/"); - if (!r) throw new et(e); + if (!r) throw new Qe(e); try { - return d(this, Ge).has("pkg") ? await d(this, Ge).get("pkg").get(r) : await import(`${B.appUrl}/api/pkg-import/web?name=${e}&v=${d(this, at)}`); + return d(this, Ge).has("pkg") ? await d(this, Ge).get("pkg").get(r) : await import(`${U.appUrl}/api/pkg-import/web?name=${e}&v=${d(this, ot)}`); } catch (n) { - throw new or(e, n); + throw new ir(e, n); } }); - O(this, "getRoutes", () => B.get("/api/my-router").then((e) => [...e, { uuid: "data-list-setting", isLayout: !0, uri: "/data-list-setting/:category/:categoryUuid", type: "fsdpf-component", component: "@pkg/ff-design/components/DataListSetting", extra: { layout: "@pkg/ff-design/frameworks/DesignTheme" } }, { uuid: "grid-layout-setting", isLayout: !0, uri: "/grid-layout-setting/:category/:categoryUuid", type: "fsdpf-component", component: "@pkg/ff-design/components/GridLayoutSetting", extra: { layout: "@pkg/ff-design/frameworks/DesignTheme" } }, { uuid: "grid-layout-form-setting", isLayout: !0, uri: "/grid-layout-form-setting/:category/:categoryUuid", type: "fsdpf-component", component: "@pkg/ff-design/components/GridLayoutFormSetting", extra: { layout: "@pkg/ff-design/frameworks/DesignTheme" } }, { uuid: "resource-api-setting", isLayout: !0, uri: "/resource-api-setting/:category/:categoryUuid", type: "fsdpf-component", component: "@pkg/ff-design/components/ResourceApiSetting", extra: { layout: "@pkg/ff-design/frameworks/DesignTheme" } }, { uuid: "charts-setting", isLayout: !0, uri: "/resource-api-setting/:category/:categoryUuid", type: "fsdpf-component", component: "@pkg/ff-design/components/ChartsSetting", extra: { layout: "@pkg/ff-design/frameworks/DesignTheme" } }, { uuid: "fsm-setting", isLayout: !0, uri: "/fsm-setting/:category/:categoryUuid", type: "fsdpf-component", component: "@pkg/ff-design/components/FsmSetting", extra: { layout: "@pkg/ff-design/frameworks/DesignTheme" } }, { uuid: "component-setting", isLayout: !0, uri: "/component-setting/:category/:categoryUuid", type: "fsdpf-component", component: "@pkg/ff-design/components/ComponentSetting", extra: { layout: "@pkg/ff-design/frameworks/DesignTheme" } }, { uuid: "login", uri: "/login", name: "登录", type: "fsdpf-component", isLogin: !1, component: "@pkg/ff/components/Login" }, { uuid: "not-found", uri: "*", name: "Not Found", type: "fsdpf-component", isLogin: !1, component: "@pkg/ff/components/NotFound" }].map(({ uuid: r, ...n }) => [r, { uuid: r, ...n }])).then((e) => new Map(e))); - O(this, "getMenus", () => B.get("/api/my-menu")); - O(this, "getConfigure", () => B.get("api/init-configure")); - O(this, "getWidgetOperationAuth", () => B.get("/api/init-widget-operation-auth").then((e) => e.reduce((r, { uuid: n, auth: i }) => [...r, [n, i]], []))); - O(this, "getPhoneNumber", (e) => B.get(`/api/user-wx-phone-number/${e}`)); + O(this, "getRoutes", () => U.get("/api/my-router").then((e) => [...e, { uuid: "data-list-setting", isLayout: !0, uri: "/data-list-setting/:category/:categoryUuid", type: "fsdpf-component", component: "@pkg/ff-design/components/DataListSetting", extra: { layout: "@pkg/ff-design/frameworks/DesignTheme" } }, { uuid: "grid-layout-setting", isLayout: !0, uri: "/grid-layout-setting/:category/:categoryUuid", type: "fsdpf-component", component: "@pkg/ff-design/components/GridLayoutSetting", extra: { layout: "@pkg/ff-design/frameworks/DesignTheme" } }, { uuid: "grid-layout-form-setting", isLayout: !0, uri: "/grid-layout-form-setting/:category/:categoryUuid", type: "fsdpf-component", component: "@pkg/ff-design/components/GridLayoutFormSetting", extra: { layout: "@pkg/ff-design/frameworks/DesignTheme" } }, { uuid: "resource-api-setting", isLayout: !0, uri: "/resource-api-setting/:category/:categoryUuid", type: "fsdpf-component", component: "@pkg/ff-design/components/ResourceApiSetting", extra: { layout: "@pkg/ff-design/frameworks/DesignTheme" } }, { uuid: "charts-setting", isLayout: !0, uri: "/resource-api-setting/:category/:categoryUuid", type: "fsdpf-component", component: "@pkg/ff-design/components/ChartsSetting", extra: { layout: "@pkg/ff-design/frameworks/DesignTheme" } }, { uuid: "fsm-setting", isLayout: !0, uri: "/fsm-setting/:category/:categoryUuid", type: "fsdpf-component", component: "@pkg/ff-design/components/FsmSetting", extra: { layout: "@pkg/ff-design/frameworks/DesignTheme" } }, { uuid: "component-setting", isLayout: !0, uri: "/component-setting/:category/:categoryUuid", type: "fsdpf-component", component: "@pkg/ff-design/components/ComponentSetting", extra: { layout: "@pkg/ff-design/frameworks/DesignTheme" } }, { uuid: "login", uri: "/login", name: "登录", type: "fsdpf-component", isLogin: !1, component: "@pkg/ff/components/Login" }, { uuid: "not-found", uri: "*", name: "Not Found", type: "fsdpf-component", isLogin: !1, component: "@pkg/ff/components/NotFound" }].map(({ uuid: r, ...n }) => [r, { uuid: r, ...n }])).then((e) => new Map(e))); + O(this, "getMenus", () => U.get("/api/my-menu")); + O(this, "getConfigure", () => U.get("api/init-configure")); + O(this, "getWidgetOperationAuth", () => U.get("/api/init-widget-operation-auth").then((e) => e.reduce((r, { uuid: n, auth: i }) => [...r, [n, i]], []))); + O(this, "getPhoneNumber", (e) => U.get(`/api/user-wx-phone-number/${e}`)); O(this, "getUserToken", () => { - const e = window.localStorage.getItem(wt); + const e = window.localStorage.getItem(yt); if (!e) return ""; const r = e.split("."); if (!Array.isArray(r) || r.length !== 3) throw "登录令牌无效!"; @@ -1161,31 +1147,31 @@ const ye = class ye { try { const n = this.getUserToken(); if (!n) return Promise.resolve(null); - const { iat: i } = JSON.parse(window.atob((r = n == null ? void 0 : n.split(".")) == null ? void 0 : r[1])), { iat: o, ...s } = B.decode(window.localStorage.getItem(It) || "", {}); - return o === i ? Promise.resolve(s) : B.get("/api/mine-info").then(({ User: a = null }) => (window.localStorage.setItem(It, B.encode({ ...a, iat: i })), a)).catch((a) => (console.error(a), e && Ee.error("请登录").then(this.logout), null)); + const { iat: i } = JSON.parse(window.atob((r = n == null ? void 0 : n.split(".")) == null ? void 0 : r[1])), { iat: s, ...o } = U.decode(window.localStorage.getItem(It) || "", {}); + return s === i ? Promise.resolve(o) : U.get("/api/mine-info").then(({ User: a = null }) => (window.localStorage.setItem(It, U.encode({ ...a, iat: i })), a)).catch((a) => (console.error(a), e && Ee.error("请登录").then(this.logout), null)); } catch (n) { console.error(n), e && Ee.error("请登录").then(this.logout); } return Promise.resolve(null); }); - O(this, "login", (e, r, n = {}) => B.post("/api/user-token", { username: e, passwd: Vn.hash(r), platform: "web", ...n }).then(({ token: i }) => (window.localStorage.setItem(wt, i), i)).then(async (i) => (await this.initAppEnv(), i))); - O(this, "setLoginIntendedUrl", (e) => sessionStorage.setItem(Lt, e)); + O(this, "login", (e, r, n = {}) => U.post("/api/user-token", { username: e, passwd: In.hash(r), platform: "web", ...n }).then(({ token: i }) => (window.localStorage.setItem(yt, i), i)).then(async (i) => (await this.initAppEnv(), i))); + O(this, "setLoginIntendedUrl", (e) => sessionStorage.setItem(At, e)); O(this, "getLoginIntendedUrl", (e = !1) => { - const r = sessionStorage.getItem(Lt); - return e && sessionStorage.removeItem(Lt), r; + const r = sessionStorage.getItem(At); + return e && sessionStorage.removeItem(At), r; }); - O(this, "logout", (e) => (window.localStorage.removeItem(It), window.localStorage.removeItem(wt), e == null ? void 0 : e())); + O(this, "logout", (e) => (window.localStorage.removeItem(It), window.localStorage.removeItem(yt), e == null ? void 0 : e())); O(this, "initAppEnv", async () => { const [e, r, n, i] = await Promise.all([this.getWidgetOperationAuth(), this.getRoutes(), this.getMenus(), this.getConfigure()]); - return Mr.init(e), We.init(i), Se.init(r, n), kt.init(We.get("Common.ICONFONT")), { widgetOperationAuth: e, routes: r, menus: n, configures: i }; + return jr.init(e), We.init(i), ke.init(r, n), nr.init(We.get("Common.ICONFONT")), { widgetOperationAuth: e, routes: r, menus: n, configures: i }; }); - if (d(ye, Ie)) return d(ye, Ie); + if (d(fe, Ae)) return d(fe, Ae); } }; -Ie = new WeakMap(), Ge = new WeakMap(), at = new WeakMap(), N(ye, Ie, null), O(ye, "getInstance", () => (d(ye, Ie) || K(ye, Ie, new ye()), d(ye, Ie))); -let Yt = ye; -const X = Yt.getInstance(), Ko = E.createContext({ user: {}, initUser: () => { -}, initUserComplete: !1 }), _o = E.createContext({ set: () => { +Ae = new WeakMap(), Ge = new WeakMap(), ot = new WeakMap(), P(fe, Ae, null), O(fe, "getInstance", () => (d(fe, Ae) || K(fe, Ae, new fe()), d(fe, Ae))); +let Jt = fe; +const X = Jt.getInstance(), Ws = E.createContext({ user: {}, initUser: () => { +}, initUserComplete: !1 }), Bs = E.createContext({ set: () => { }, get: () => { }, assign: () => { }, currentRoute: () => { @@ -1197,269 +1183,269 @@ const X = Yt.getInstance(), Ko = E.createContext({ user: {}, initUser: () => { return !e || /^[A-Z]/.test(e); } return !1; -}, Jo = (t, e) => { +}, zs = (t, e) => { if (!t || typeof window > "u") return; let r = document.querySelector(`style[ff-style-token="${e}"]`); return r ? (r.innerHTML = t, t) : (r = document.createElement("style"), r.setAttribute("ff-style-token", e), r.setAttribute("type", "text/css"), r.innerHTML = t, document.head.appendChild(r), t); }; -var ve, Xe, Ne, be, Ce, ne, te, Y, ke, lt, ct, dt, ut, xt, pt; -const ar = class ar { +var ve, Ye, Pe, we, be, te, ee, G, Ce, at, lt, ct, dt, St, ut; +const or = class or { constructor(e, r = "/") { - N(this, ve, "/"); - N(this, Xe, /* @__PURE__ */ new Set()); - N(this, Ne, (e) => { - for (const r of d(this, Xe)) try { + P(this, ve, "/"); + P(this, Ye, /* @__PURE__ */ new Set()); + P(this, Pe, (e) => { + for (const r of d(this, Ye)) try { r(e); } catch (n) { console.error("Error in VirtualFS event listener:", n); } }); - N(this, be, (e) => { + P(this, we, (e) => { const r = Date.now(); if (e && (e.lastModified = r), d(this, ve) != "/") { - const n = d(this, Y).call(this, d(this, ve)); + const n = d(this, G).call(this, d(this, ve)); n && (n.lastModified = r); } this.root.lastModified = r; }); - N(this, Ce, (e) => { - let r = pe.normalize(e); + P(this, be, (e) => { + let r = ue.normalize(e); return r.startsWith("/") || (r = "/" + r), r.length > 1 && r.endsWith("/") && (r = r.slice(0, -1)), r; }); - N(this, ne, (e) => { - const r = pe.join(d(this, ve), e); - return d(this, Ce).call(this, r); + P(this, te, (e) => { + const r = ue.join(d(this, ve), e); + return d(this, be).call(this, r); }); - N(this, te, (e) => { + P(this, ee, (e) => { if (!e || typeof e != "string") return !1; - const r = d(this, Ce).call(this, e); + const r = d(this, be).call(this, e); return !r.includes("..") && r.startsWith("/"); }); - N(this, Y, (e) => { - var o; - const r = d(this, Ce).call(this, e); + P(this, G, (e) => { + var s; + const r = d(this, be).call(this, e); if (r === "/") return this.root; - const n = r.split("/").filter((s) => s); + const n = r.split("/").filter((o) => o); let i = this.root; - for (const s of n) { + for (const o of n) { if (i.type !== "dir") return null; - const a = (o = i.children) == null ? void 0 : o.find((l) => l.name === s); + const a = (s = i.children) == null ? void 0 : s.find((l) => l.name === o); if (!a) return null; i = a; } return i; }); - N(this, ke, (e) => { - const r = d(this, Ce).call(this, e), n = pe.basename(r), i = pe.dirname(r); - return { parent: d(this, Y).call(this, i), name: n }; + P(this, Ce, (e) => { + const r = d(this, be).call(this, e), n = ue.basename(r), i = ue.dirname(r); + return { parent: d(this, G).call(this, i), name: n }; }); - N(this, lt, (e, r, n) => n === !1 ? e : n === "root" ? e.map((i) => pe.join(r, i)) : n === !0 || n === "working" ? e.map((i) => pe.relative(d(this, ve), pe.join(r, i))) : e); - N(this, ct, async (e, r, n, i = "") => { - const o = [], s = d(this, Y).call(this, e); - if (!s || s.type !== "dir") return o; - const a = s.children; + P(this, at, (e, r, n) => n === !1 ? e : n === "root" ? e.map((i) => ue.join(r, i)) : n === !0 || n === "working" ? e.map((i) => ue.relative(d(this, ve), ue.join(r, i))) : e); + P(this, lt, async (e, r, n, i = "") => { + const s = [], o = d(this, G).call(this, e); + if (!o || o.type !== "dir") return s; + const a = o.children; for (const l of a) { const c = l.name, u = e === "/" ? `/${c}` : `${e}/${c}`, p = i ? `${i}/${c}` : c; try { - if (l.type === "file") r(n ? p : c) && o.push(p); + if (l.type === "file") r(n ? p : c) && s.push(p); else if (l.type === "dir" && n) { - const m = await d(this, ct).call(this, u, r, n, p); - o.push(...m); + const m = await d(this, lt).call(this, u, r, n, p); + s.push(...m); } } catch { continue; } } - return o; + return s; }); - N(this, dt, async (e, r, n, i = "") => { - const o = [], s = Array.isArray(r) ? r : [r], a = d(this, Y).call(this, e); - if (!a || a.type !== "dir") return o; + P(this, ct, async (e, r, n, i = "") => { + const s = [], o = Array.isArray(r) ? r : [r], a = d(this, G).call(this, e); + if (!a || a.type !== "dir") return s; if (!n) { - for (const c of s) if (d(this, ut).call(this, c)) { - const u = await d(this, xt).call(this, e, c); - o.push(...u); + for (const c of o) if (d(this, dt).call(this, c)) { + const u = await d(this, St).call(this, e, c); + s.push(...u); } else { - const u = pe.join(e, c), p = d(this, Ce).call(this, u); - d(this, Y).call(this, p) && o.push(c); + const u = ue.join(e, c), p = d(this, be).call(this, u); + d(this, G).call(this, p) && s.push(c); } - return o; + return s; } const l = a.children; for (const c of l) { const u = c.name, p = e === "/" ? `/${u}` : `${e}/${u}`, m = i ? `${i}/${u}` : u; try { - if (c.type === "file") for (const g of s) { - let f = !1; - if (f = d(this, ut).call(this, g) ? d(this, pt).call(this, u, g) : u === g, f) { - o.push(m); + if (c.type === "file") for (const g of o) { + let w = !1; + if (w = d(this, dt).call(this, g) ? d(this, ut).call(this, u, g) : u === g, w) { + s.push(m); break; } } else if (c.type === "dir") { - const g = await d(this, dt).call(this, p, r, n, m); - o.push(...g); + const g = await d(this, ct).call(this, p, r, n, m); + s.push(...g); } } catch { continue; } } - return o; + return s; }); - N(this, ut, (e) => /[*?[\]{}]/.test(e)); - N(this, xt, async (e, r) => { - const n = [], i = d(this, Y).call(this, e); + P(this, dt, (e) => /[*?[\]{}]/.test(e)); + P(this, St, async (e, r) => { + const n = [], i = d(this, G).call(this, e); if (!i || i.type !== "dir") return n; - const o = i.children.map((s) => s.name); - for (const s of o) d(this, pt).call(this, s, r) && n.push(s); + const s = i.children.map((o) => o.name); + for (const o of s) d(this, ut).call(this, o, r) && n.push(o); return n; }); - N(this, pt, (e, r) => { - const n = r.replace(/\./g, "\\.").replace(/\*/g, ".*").replace(/\?/g, ".").replace(/\{([^}]+)\}/g, (i, o) => "(" + o.split(",").join("|") + ")"); + P(this, ut, (e, r) => { + const n = r.replace(/\./g, "\\.").replace(/\*/g, ".*").replace(/\?/g, ".").replace(/\{([^}]+)\}/g, (i, s) => "(" + s.split(",").join("|") + ")"); return new RegExp(`^${n}$`).test(e); }); - var n, i, o; - K(this, ve, r), this.root = { name: "/", type: "dir", children: [], lastModified: Date.now() }, Array.isArray(e) ? this.root.children = e : e && typeof e == "object" && (e.name && e.name !== "/" ? this.root.children.push(e) : (this.root = e, (n = this.root).name ?? (n.name = "/"), (i = this.root).children ?? (i.children = []), (o = this.root).lastModified ?? (o.lastModified = Date.now()))); + var n, i, s; + K(this, ve, r), this.root = { name: "/", type: "dir", children: [], lastModified: Date.now() }, Array.isArray(e) ? this.root.children = e : e && typeof e == "object" && (e.name && e.name !== "/" ? this.root.children.push(e) : (this.root = e, (n = this.root).name ?? (n.name = "/"), (i = this.root).children ?? (i.children = []), (s = this.root).lastModified ?? (s.lastModified = Date.now()))); } async stat(e) { - const r = d(this, ne).call(this, e); - if (!d(this, te).call(this, r)) throw new Error(`EINVAL: invalid path '${e}'`); - const n = d(this, Y).call(this, r); + const r = d(this, te).call(this, e); + if (!d(this, ee).call(this, r)) throw new Error(`EINVAL: invalid path '${e}'`); + const n = d(this, G).call(this, r); if (!n) throw new Error(`ENOENT: no such file or directory, stat '${e}'`); return { isFile: () => n.type === "file", isDirectory: () => n.type === "dir", lastModified: n.lastModified }; } async dir(e) { - const r = d(this, ne).call(this, e); - if (!d(this, te).call(this, r)) throw new Error(`EINVAL: invalid path '${e}'`); - const n = d(this, Y).call(this, r); + const r = d(this, te).call(this, e); + if (!d(this, ee).call(this, r)) throw new Error(`EINVAL: invalid path '${e}'`); + const n = d(this, G).call(this, r); if (!n) throw new Error(`ENOENT: no such file or directory, scandir '${e}'`); if (n.type !== "dir") throw new Error(`ENOTDIR: not a directory, scandir '${e}'`); return n.children.map((i) => i.name); } async readFile(e) { - const r = d(this, ne).call(this, e); - if (!d(this, te).call(this, r)) throw new Error(`EINVAL: invalid path '${e}'`); - const n = d(this, Y).call(this, r); + const r = d(this, te).call(this, e); + if (!d(this, ee).call(this, r)) throw new Error(`EINVAL: invalid path '${e}'`); + const n = d(this, G).call(this, r); if (!n) throw new Error(`ENOENT: no such file or directory, open '${e}'`); if (n.type !== "file") throw new Error("EISDIR: illegal operation on a directory, read"); return n.content || ""; } async writeFile(e, r) { - const n = d(this, ne).call(this, e); - if (!d(this, te).call(this, n)) throw new Error(`EINVAL: invalid path '${e}'`); - const { parent: i, name: o } = d(this, ke).call(this, n); + const n = d(this, te).call(this, e); + if (!d(this, ee).call(this, n)) throw new Error(`EINVAL: invalid path '${e}'`); + const { parent: i, name: s } = d(this, Ce).call(this, n); if (!i) throw new Error(`ENOENT: no such file or directory, open '${e}'`); if (i.type !== "dir") throw new Error("ENOTDIR: not a directory"); - const s = i.children.findIndex((c) => c.name === o), a = s >= 0, l = { name: o, type: "file", content: r, lastModified: Date.now() }; - a ? i.children[s] = l : i.children.push(l), d(this, be).call(this, i), d(this, Ne).call(this, { action: a ? "update" : "create", path: n, type: "file", timestamp: Date.now() }); + const o = i.children.findIndex((c) => c.name === s), a = o >= 0, l = { name: s, type: "file", content: r, lastModified: Date.now() }; + a ? i.children[o] = l : i.children.push(l), d(this, we).call(this, i), d(this, Pe).call(this, { action: a ? "update" : "create", path: n, type: "file", timestamp: Date.now() }); } async mkdir(e, r = {}) { - const n = d(this, ne).call(this, e); - if (!d(this, te).call(this, n)) throw new Error(`EINVAL: invalid path '${e}'`); + const n = d(this, te).call(this, e); + if (!d(this, ee).call(this, n)) throw new Error(`EINVAL: invalid path '${e}'`); const { recursive: i } = r; if (i) { - const o = n.split("/").filter((a) => a); - let s = "/"; - for (const a of o) - if (s = pe.join(s, a), !d(this, Y).call(this, s)) { - const { parent: l, name: c } = d(this, ke).call(this, s); + const s = n.split("/").filter((a) => a); + let o = "/"; + for (const a of s) + if (o = ue.join(o, a), !d(this, G).call(this, o)) { + const { parent: l, name: c } = d(this, Ce).call(this, o); if (l && l.type === "dir") { const u = { name: c, type: "dir", children: [], lastModified: Date.now() }; - l.children.push(u), d(this, be).call(this, l), d(this, Ne).call(this, { action: "create", path: d(this, Ce).call(this, s), type: "dir", timestamp: Date.now() }); + l.children.push(u), d(this, we).call(this, l), d(this, Pe).call(this, { action: "create", path: d(this, be).call(this, o), type: "dir", timestamp: Date.now() }); } } } else { - const { parent: o, name: s } = d(this, ke).call(this, n); - if (!o) throw new Error(`ENOENT: no such file or directory, mkdir '${e}'`); - if (o.type !== "dir") throw new Error("ENOTDIR: not a directory"); - if (o.children.find((l) => l.name === s)) throw new Error(`EEXIST: file already exists, mkdir '${e}'`); - const a = { name: s, type: "dir", children: [], lastModified: Date.now() }; - o.children.push(a), d(this, be).call(this, o), d(this, Ne).call(this, { action: "create", path: n, type: "dir", timestamp: Date.now() }); + const { parent: s, name: o } = d(this, Ce).call(this, n); + if (!s) throw new Error(`ENOENT: no such file or directory, mkdir '${e}'`); + if (s.type !== "dir") throw new Error("ENOTDIR: not a directory"); + if (s.children.find((l) => l.name === o)) throw new Error(`EEXIST: file already exists, mkdir '${e}'`); + const a = { name: o, type: "dir", children: [], lastModified: Date.now() }; + s.children.push(a), d(this, we).call(this, s), d(this, Pe).call(this, { action: "create", path: n, type: "dir", timestamp: Date.now() }); } } async unlink(e) { - const r = d(this, ne).call(this, e); - if (!d(this, te).call(this, r)) throw new Error(`EINVAL: invalid path '${e}'`); - const { parent: n, name: i } = d(this, ke).call(this, r); + const r = d(this, te).call(this, e); + if (!d(this, ee).call(this, r)) throw new Error(`EINVAL: invalid path '${e}'`); + const { parent: n, name: i } = d(this, Ce).call(this, r); if (!n) throw new Error(`ENOENT: no such file or directory, unlink '${e}'`); - const o = n.children.findIndex((s) => s.name === i); - if (o < 0) throw new Error(`ENOENT: no such file or directory, unlink '${e}'`); - if (n.children[o].type !== "file") throw new Error(`EISDIR: illegal operation on a directory, unlink '${e}'`); - n.children.splice(o, 1), d(this, be).call(this, n), d(this, Ne).call(this, { action: "delete", path: r, type: "file", timestamp: Date.now() }); + const s = n.children.findIndex((o) => o.name === i); + if (s < 0) throw new Error(`ENOENT: no such file or directory, unlink '${e}'`); + if (n.children[s].type !== "file") throw new Error(`EISDIR: illegal operation on a directory, unlink '${e}'`); + n.children.splice(s, 1), d(this, we).call(this, n), d(this, Pe).call(this, { action: "delete", path: r, type: "file", timestamp: Date.now() }); } async rmdir(e, r = {}) { - const n = d(this, ne).call(this, e); - if (!d(this, te).call(this, n)) throw new Error(`EINVAL: invalid path '${e}'`); - const { parent: i, name: o } = d(this, ke).call(this, n); + const n = d(this, te).call(this, e); + if (!d(this, ee).call(this, n)) throw new Error(`EINVAL: invalid path '${e}'`); + const { parent: i, name: s } = d(this, Ce).call(this, n); if (!i) throw new Error(`ENOENT: no such file or directory, rmdir '${e}'`); - const s = i.children.findIndex((l) => l.name === o); - if (s < 0) throw new Error(`ENOENT: no such file or directory, rmdir '${e}'`); - const a = i.children[s]; + const o = i.children.findIndex((l) => l.name === s); + if (o < 0) throw new Error(`ENOENT: no such file or directory, rmdir '${e}'`); + const a = i.children[o]; if (a.type !== "dir") throw new Error(`ENOTDIR: not a directory, rmdir '${e}'`); if (!r.recursive && a.children.length > 0) throw new Error(`ENOTEMPTY: directory not empty, rmdir '${e}'`); - i.children.splice(s, 1), d(this, be).call(this, i), d(this, Ne).call(this, { action: "delete", path: n, type: "dir", timestamp: Date.now() }); + i.children.splice(o, 1), d(this, we).call(this, i), d(this, Pe).call(this, { action: "delete", path: n, type: "dir", timestamp: Date.now() }); } async rename(e, r) { - const n = d(this, ne).call(this, e), i = d(this, ne).call(this, r); - if (!d(this, te).call(this, n)) throw new Error(`EINVAL: invalid path '${e}'`); - if (!d(this, te).call(this, i)) throw new Error(`EINVAL: invalid path '${r}'`); - if (!d(this, Y).call(this, n)) throw new Error(`ENOENT: no such file or directory, rename '${e}' -> '${r}'`); - const { parent: o, name: s } = d(this, ke).call(this, n), { parent: a, name: l } = d(this, ke).call(this, i); + const n = d(this, te).call(this, e), i = d(this, te).call(this, r); + if (!d(this, ee).call(this, n)) throw new Error(`EINVAL: invalid path '${e}'`); + if (!d(this, ee).call(this, i)) throw new Error(`EINVAL: invalid path '${r}'`); + if (!d(this, G).call(this, n)) throw new Error(`ENOENT: no such file or directory, rename '${e}' -> '${r}'`); + const { parent: s, name: o } = d(this, Ce).call(this, n), { parent: a, name: l } = d(this, Ce).call(this, i); if (!a) throw new Error(`ENOENT: no such file or directory, rename '${e}' -> '${r}'`); - if (d(this, Y).call(this, i)) throw new Error(`EEXIST: file already exists, rename '${e}' -> '${r}'`); - const c = o.children.findIndex((p) => p.name === s), u = { ...o.children[c], name: l, lastModified: Date.now() }; - o.children.splice(c, 1), a.children.push(u), d(this, be).call(this, o), o !== a && d(this, be).call(this, a), d(this, Ne).call(this, { action: "rename", path: i, oldPath: n, type: u.type, timestamp: Date.now() }); + if (d(this, G).call(this, i)) throw new Error(`EEXIST: file already exists, rename '${e}' -> '${r}'`); + const c = s.children.findIndex((p) => p.name === o), u = { ...s.children[c], name: l, lastModified: Date.now() }; + s.children.splice(c, 1), a.children.push(u), d(this, we).call(this, s), s !== a && d(this, we).call(this, a), d(this, Pe).call(this, { action: "rename", path: i, oldPath: n, type: u.type, timestamp: Date.now() }); } async exists(e) { - const r = d(this, ne).call(this, e); - return d(this, te).call(this, r) ? d(this, Y).call(this, r) !== null : !1; + const r = d(this, te).call(this, e); + return d(this, ee).call(this, r) ? d(this, G).call(this, r) !== null : !1; } getLastModified() { return this.root.lastModified; } subscribe(e) { if (typeof e != "function") throw new Error("Callback must be a function"); - return d(this, Xe).add(e), () => { - d(this, Xe).delete(e); + return d(this, Ye).add(e), () => { + d(this, Ye).delete(e); }; } getWorkingDirectory() { return d(this, ve); } scope(e = "/") { - const r = d(this, Ce).call(this, e); - if (!d(this, te).call(this, r)) throw new Error(`EINVAL: invalid path '${e}'`); - const n = d(this, Y).call(this, r); + const r = d(this, be).call(this, e); + if (!d(this, ee).call(this, r)) throw new Error(`EINVAL: invalid path '${e}'`); + const n = d(this, G).call(this, r); if (!n) throw new Error(`ENOENT: no such file or directory '${e}'`); if (n.type !== "dir") throw new Error(`ENOTDIR: not a directory '${e}'`); - return n.children ?? (n.children = []), n.lastModified ?? (n.lastModified = Date.now()), new ar(this.root, r); + return n.children ?? (n.children = []), n.lastModified ?? (n.lastModified = Date.now()), new or(this.root, r); } async findFiles(e, r, n = {}) { - const i = d(this, ne).call(this, e); - if (!d(this, te).call(this, i)) throw new Error(`EINVAL: invalid path '${e}'`); - const o = d(this, Y).call(this, i); - if (!o) throw new Error(`ENOENT: no such file or directory '${e}'`); - if (o.type !== "dir") throw new Error(`ENOTDIR: not a directory '${e}'`); - const { recursive: s = !1, fullPath: a = !1 } = n; + const i = d(this, te).call(this, e); + if (!d(this, ee).call(this, i)) throw new Error(`EINVAL: invalid path '${e}'`); + const s = d(this, G).call(this, i); + if (!s) throw new Error(`ENOENT: no such file or directory '${e}'`); + if (s.type !== "dir") throw new Error(`ENOTDIR: not a directory '${e}'`); + const { recursive: o = !1, fullPath: a = !1 } = n; if (typeof r == "function") { - const c = await d(this, ct).call(this, i, r, s); - return d(this, lt).call(this, c, i, a); + const c = await d(this, lt).call(this, i, r, o); + return d(this, at).call(this, c, i, a); } - const l = await d(this, dt).call(this, i, r, s); - return d(this, lt).call(this, l, i, a); + const l = await d(this, ct).call(this, i, r, o); + return d(this, at).call(this, l, i, a); } }; -ve = new WeakMap(), Xe = new WeakMap(), Ne = new WeakMap(), be = new WeakMap(), Ce = new WeakMap(), ne = new WeakMap(), te = new WeakMap(), Y = new WeakMap(), ke = new WeakMap(), lt = new WeakMap(), ct = new WeakMap(), dt = new WeakMap(), ut = new WeakMap(), xt = new WeakMap(), pt = new WeakMap(); -let jr = ar; -const oo = async (t, e = "/", r = "") => { +ve = new WeakMap(), Ye = new WeakMap(), Pe = new WeakMap(), we = new WeakMap(), be = new WeakMap(), te = new WeakMap(), ee = new WeakMap(), G = new WeakMap(), Ce = new WeakMap(), at = new WeakMap(), lt = new WeakMap(), ct = new WeakMap(), dt = new WeakMap(), St = new WeakMap(), ut = new WeakMap(); +let Rr = or; +const is = async (t, e = "/", r = "") => { try { - const n = await t.stat(e), i = e === "/" ? "/" : pe.basename(e), o = { title: i, key: r ? `${r}${e}` : e, isLeaf: n.isFile() }; + const n = await t.stat(e), i = e === "/" ? "/" : ue.basename(e), s = { title: i, key: r ? `${r}${e}` : e, isLeaf: n.isFile() }; if (n.isDirectory()) { - const s = await t.dir(e); - if (s.length > 0) { - o.children = []; + const o = await t.dir(e); + if (o.length > 0) { + s.children = []; const a = [], l = []; - for (const c of s) { + for (const c of o) { const u = e === "/" ? `/${c}` : `${e}/${c}`; try { (await t.stat(u)).isDirectory() ? a.push(c) : l.push(c); @@ -1471,20 +1457,20 @@ const oo = async (t, e = "/", r = "") => { for (const c of [...a, ...l]) { const u = e === "/" ? `/${c}` : `${e}/${c}`; try { - const p = await oo(t, u, r); - o.children.push(p); + const p = await is(t, u, r); + s.children.push(p); } catch (p) { console.warn(`Failed to process ${u}:`, p.message); } } } } - return o; + return s; } catch { return null; } }; -class so extends E.Component { +class ss extends E.Component { constructor() { super(...arguments); O(this, "state", { error: null }); @@ -1497,14 +1483,14 @@ class so extends E.Component { return { error: r }; } componentDidCatch(r, n) { - var i, o; - console.error("[ErrorBoundary]", r), (o = (i = this.props).onError) == null || o.call(i, r, n); + var i, s; + console.error("[ErrorBoundary]", r), (s = (i = this.props).onError) == null || s.call(i, r, n); } componentDidUpdate(r) { const { resetKeys: n } = this.props; - this.state.error && (n != null && n.length) && n.some((i, o) => { - var s; - return i !== ((s = r.resetKeys) == null ? void 0 : s[o]); + this.state.error && (n != null && n.length) && n.some((i, s) => { + var o; + return i !== ((o = r.resetKeys) == null ? void 0 : o[s]); }) && this.reset(); } render() { @@ -1516,126 +1502,124 @@ class so extends E.Component { return this.props.children; } } -const Ho = ({ widget: t, widgetProps: e, widgetSetting: r, theme: n, themeProps: i, className: o, classNames: s, style: a, styles: l, fallback: c = null, fallbackOnError: u, onError: p }) => { - const [m, g] = V({}), f = H((A, P) => g((L) => ({ ...L, [A]: P })), []), y = H((A) => g((P) => ({ ...P, [A]: void 0 })), []), { loading: k, value: b, error: $ } = br(async () => { +const Ks = ({ widget: t, widgetProps: e, widgetSetting: r, theme: n, themeProps: i, className: s, classNames: o, style: a, styles: l, fallback: c = null, fallbackOnError: u, onError: p }) => { + const [m, g] = L({}), w = H((T, x) => g((A) => ({ ...A, [T]: x })), []), f = H((T) => g((x) => ({ ...x, [T]: void 0 })), []), { loading: C, value: b, error: S } = yr(async () => { if (!t) return null; if (E.isValidElement(t)) return t; if (sr(t)) return E.createElement(t); - const { default: A } = await X.getWidgetComponent(t); - return E.createElement(A); - }, [t]), { value: C } = br(async () => { + const { default: T } = await X.getWidgetComponent(t); + return E.createElement(T); + }, [t]), { value: k } = yr(async () => { if (!n) return null; if (typeof n == "function") return n; - const { default: A } = await X.getWidgetComponent(n); - return (P) => E.createElement(A, P); + const { default: T } = await X.getWidgetComponent(n); + return (x) => E.createElement(T, x); }, [n]); - if (k) return c; - if (!t || b === null) return h(ri, {}); - if ($) return p == null || p($, null), typeof u == "function" ? u($, null) : u ?? String($); - const x = E.cloneElement(b, { ...e, $setting: r }), F = { ele: m, mount: f, unmount: y }, { rootClassName: I, ...T } = m, v = { ...T, children: x, className: j(o, I), classNames: s, style: a, styles: l, $setting: i }; - return h(so, { fallback: u, onError: p, children: h(Ze.Provider, { value: F, children: C ? C(v) : x }) }); + if (C) return c; + if (!t || b === null) return h(Qn, {}); + if (S) return p == null || p(S, null), typeof u == "function" ? u(S, null) : u ?? String(S); + const $ = E.cloneElement(b, { ...e, $setting: r }), R = { ele: m, mount: w, unmount: f }, { rootClassName: I, ...N } = m, v = { ...N, children: $, className: F(s, I), classNames: o, style: a, styles: l, $setting: i }; + return h(ss, { fallback: u, onError: p, children: h(Xe.Provider, { value: R, children: k ? k(v) : $ }) }); }; export { - Mo as $, - li as A, - No as B, - To as C, - Ct as D, - Wr as E, - zt as F, - Fo as G, - ki as H, - ci as I, - di as J, - vi as K, - Ni as L, - jo as M, - Ao as N, - oe as O, - Oi as P, - Pt as Q, - Jr as R, - Qr as S, - jt as T, - Io as U, - Lo as V, - Vo as W, - Do as X, - Ri as Y, - Fi as Z, - ji as _, - Br as a, - Ai as a0, + xt as $, + oi as A, + Dr as B, + Wt as C, + bt as D, + ai as E, + li as F, + Ns as G, + Ci as H, + vi as I, + Pi as J, + Os as K, + ie as L, + Oi as M, + Rs as N, + $t as O, + Jr as P, + Ft as Q, + Br as R, + Fs as S, + Ts as T, + Is as U, + As as V, + Ri as W, + Fi as X, + Ti as Y, + js as Z, + Ii as _, + Lr as a, + Ls as a0, vt as a1, - Bo as a2, - gt as a3, - Nt as a4, - Uo as a5, - Wo as a6, - Ii as a7, - nn as a8, - qi as a9, - B as aA, - ti as aB, - We as aC, - ze as aD, - Se as aE, - Ko as aF, - _o as aG, - jr as aH, - oo as aI, - io as aJ, - so as aK, - Ho as aL, - ir as aa, - nr as ab, - on as ac, - Li as ad, - Vi as ae, - Di as af, - Mi as ag, - Bi as ah, - Ui as ai, - zo as aj, - qo as ak, - kt as al, - R as am, - Mr as an, - Yi as ao, - re as ap, - Ze as aq, - Vr as ar, - G as as, - Ee as at, - ri as au, - Po as av, - vo as aw, - X as ax, - sr as ay, - Jo as az, - zr as b, - Oo as c, - qr as d, - tr as e, - Hr as f, - ii as g, - Xr as h, - $i as i, - Gr as j, + Pt as a2, + Ms as a3, + Ds as a4, + Ai as a5, + Zr as a6, + zi as a7, + Qr as a8, + rr as a9, + We as aA, + Be as aB, + ke as aC, + Ws as aD, + Bs as aE, + Rr as aF, + is as aG, + ns as aH, + ss as aI, + Ks as aJ, + en as aa, + ji as ab, + Li as ac, + Mi as ad, + Di as ae, + Vi as af, + Ui as ag, + Vs as ah, + Us as ai, + nr as aj, + V as ak, + jr as al, + Ji as am, + re as an, + Xe as ao, + ei as ap, + Y as aq, + Ee as ar, + Qn as as, + $s as at, + xs as au, + X as av, + sr as aw, + zs as ax, + U as ay, + Zn as az, + Vr as b, + vs as c, + Ur as d, + er as e, + zr as f, + ri as g, + _r as h, + Si as i, + qr as j, Ei as k, - Ro as l, - Yr as m, - _r as n, - Kr as o, - wi as p, - yi as q, - mi as r, - rr as s, - ae as t, - Si as u, - Ci as v, - Pi as w, - ui as x, - gi as y, - ai as z + Ps as l, + Kr as m, + wi as n, + Wr as o, + fi as p, + mi as q, + gi as r, + tr as s, + oe as t, + ki as u, + bi as v, + xi as w, + ci as x, + ui as y, + si as z }; diff --git a/components.d.ts b/components.d.ts index 8f6255c..69b6c87 100644 --- a/components.d.ts +++ b/components.d.ts @@ -1,51 +1,8 @@ -import * as React from 'react'; -import React__default, { ReactElement, ComponentType } from 'react'; -import PropTypes from 'prop-types'; - -/** - * 渲染一个 iconfont symbol 图标(依赖 Iconfont.init 注入的 SVG symbol 脚本) - * @param {Object} props - * @param {string} [props.className] 额外的 class 名 - * @param {string} props.type 图标名,对应 svg symbol 的 id - * @param {Object} [props.style] 行内样式 - */ -declare function Iconfont({ className, type, style, rotate, spin, twoToneColor, compact, ...props }: { - className?: string; - type: string; - style?: any; -}): React__default.JSX.Element; -declare namespace Iconfont { - export namespace propTypes { - let className: PropTypes.Requireable; - let type: PropTypes.Validator; - let style: PropTypes.Requireable; - } - export { createScriptUrlElements as init }; -} - -/** - * 依次注入 iconfont symbol 的 script 地址(单个 url 只会注入一次); - * 也是 Iconfont.init 挂载的实现,支持传入多个 url 按顺序加载(前一个 load/error 后再加载下一个) - * @param {string[]} [scriptUrls] iconfont symbol 脚本地址列表 - * @param {number} [index] 内部递归用的当前下标 - */ -declare function createScriptUrlElements(scriptUrls?: string[], index?: number): void; - -/** - * 包装一个弹窗内容组件,让它可以通过 $setProps 更新自己的 props(与外部传入的 widgetProps 做浅合并), - * 同时注入 $close 用于关闭弹窗 - * @param {Object} props - * @param {import('react').ReactElement|Function} props.widget 要渲染的元素或组件 - * @param {Object} [props.widgetProps] 外部传入的初始 props,变化时会合并进内部状态 - * @param {(result?: *) => void} props.$close 关闭弹窗的函数,会透传给 widget - * @param {(patch: Object) => void} [props.onSetProps] $setProps 被调用时的回调,用于同步外部状态 - */ -declare function SetPropsWrapper({ widget, widgetProps: externalProps, $close, onSetProps }: { - widget: React.ReactElement | Function; - widgetProps?: any; - $close: (result?: any) => void; - onSetProps?: (patch: any) => void; -}): Function | React__default.ReactElement>; +export { default as Icon } from './iconfont'; +export { default as SetPropsWrapper } from './container'; +import React, { ReactElement, ComponentType, ReactNode, CSSProperties } from 'react'; +import { SlotKey } from './container'; +export { Empty, Loading, NotFound, Popup } from './container'; /** * 通用错误边界组件 @@ -57,7 +14,7 @@ declare function SetPropsWrapper({ widget, widgetProps: externalProps, $close, o * @param {Function} [props.onReset] 重置回调 () => void * @param {any[]} [props.resetKeys] 任一值变化时自动重置(类似 react-error-boundary) */ -declare class ErrorBoundary extends React__default.Component { +declare class ErrorBoundary extends React.Component { static getDerivedStateFromError(error: any): { error: any; }; @@ -75,8 +32,42 @@ declare class ErrorBoundary extends React__default.Component { /** widget 支持的三种形式 */ type WidgetInput = string | ReactElement | ComponentType +/** theme 布局区块 key,用于 classNames / styles(在 SlotKey 基础上加入容器区块) */ +type LayoutKey = SlotKey | 'header' | 'body' | 'footer' + +/** theme function 收到的上下文,ele slot 展开 + children + 样式 + $setting */ +type ThemeContext = { + /** 已渲染的 widget 实例 */ + children: ReactNode + /** slot 注入的标题 */ + title?: ReactNode + /** slot 注入的副标题 */ + subTitle?: ReactNode + /** slot 注入的额外内容,通常显示在底栏左侧(与 actions 两端对齐) */ + extras?: ReactNode + /** slot 注入的操作区,通常显示在底栏右侧(与 extras 两端对齐) */ + actions?: ReactNode + /** 根节点 className */ + className?: string + /** 各布局区块的 className */ + classNames?: Partial> + /** 根节点行内样式 */ + style?: CSSProperties + /** 各布局区块的行内样式 */ + styles?: Partial> + /** 即 themeProps,主题自身的配置 */ + $setting?: Record +} + +/** theme function render prop 签名 */ +type ThemeRenderer = (ctx: ThemeContext) => ReactNode + +/** fallbackOnError 的 function 形式 */ +type FallbackOnError = (error: Error, reset: null) => ReactNode + /** * 按组件名动态加载并渲染组件,支持 theme 容器框架(string 异步加载 或 function render prop) + * @param {Object} [props] * @param {WidgetInput} [props.widget] 组件名(@pkg/xxx)、ReactElement 或组件函数/类 * @param {Object} [props.widgetProps] 直接 spread 给 widget 的 props * @param {Object} [props.widgetSetting] 传给 widget 的 $setting @@ -91,71 +82,20 @@ type WidgetInput = string | ReactElement | ComponentType * @param {ReactNode | FallbackOnError} [props.fallbackOnError] * @param {(error: Error, info: null) => void} [props.onError] */ -declare function ImportWidgetComponent({ widget, widgetProps, widgetSetting, theme, themeProps, className, classNames, style, styles, fallback, fallbackOnError, onError, }?: WidgetInput): any; +declare function ImportWidgetComponent({ widget, widgetProps, widgetSetting, theme, themeProps, className, classNames, style, styles, fallback, fallbackOnError, onError, }?: { + widget?: WidgetInput; + widgetProps?: any; + widgetSetting?: any; + theme?: string | ThemeRenderer; + themeProps?: any; + className?: string; + classNames?: Partial>; + style?: React.CSSProperties; + styles?: Partial>; + fallback?: any; + fallbackOnError?: React.ReactNode | FallbackOnError; + onError?: (error: Error, info: null) => void; +}): any; -/** 空状态占位组件 */ -declare function Empty(): React__default.JSX.Element; - -/** 加载中占位组件 */ -declare function Loading(): React__default.JSX.Element; - -/** 未找到占位组件 */ -declare function NotFound(): React__default.JSX.Element; - -declare namespace FFPopup { - export { modal }; - export { confirm }; - export { form }; - export { notification }; - export { success }; - export { error }; -} - -/** - * 打开一个任意组件的弹窗 - * @param {Function} widget 要渲染的组件 - * @param {Object} [widgetData] 传给组件的 props - * @param {Object} [widgetContainerProps] 传给弹窗容器(PopupContainer)的 props - * @returns {Promise<*>&{update: Function}} resolve 弹窗关闭时传入的值;promise.update(patch, containerPatch) 可用来更新弹窗内容 - */ -declare function modal(widget: Function, widgetData?: any, widgetContainerProps?: any): Promise & { - update: Function; -}; -/** - * 弹出一个确认框 - * @param {*} content 确认框内容 - * @param {Object} [opts] 其余透传给 Confirm 组件的 props - * @returns {Promise<*>} 点击确认时 resolve,点击取消/关闭时按 modal 的语义处理 - */ -declare function confirm(content: any, opts?: any): Promise; -/** - * 弹出一个模态表单;取消时 reject(false) - * @param {Array} fields 表单字段配置(传给 FormModal 的 fields) - * @param {Object} [widgetContainerProps] 传给弹窗容器的 props - * @param {Object} [formProps] 传给表单的额外 props - * @returns {Promise} 提交后的表单数据 - */ -declare function form(fields: any[], widgetContainerProps?: any, formProps?: any): Promise; -/** - * 弹出一条消息提示 - * @param {*} content 提示内容 - * @param {Object} [opts] 其余透传给 Notification 组件的 props,duration/showProgress 会转发到容器 props - * @returns {Promise<*>} - */ -declare function notification(content: any, { showProgress, duration, ...opts }?: any): Promise; -/** - * 成功提示(绿色图标样式的 notification) - * @param {*} content 提示内容 - * @param {Object} [opts] 其余透传给 notification 的选项 - * @returns {Promise<*>} - */ -declare function success(content: any, opts?: any): Promise; -/** - * 错误提示(红色图标样式的 notification) - * @param {*} content 提示内容 - * @param {Object} [opts] 其余透传给 notification 的选项 - * @returns {Promise<*>} - */ -declare function error(content: any, opts?: any): Promise; - -export { Empty, ErrorBoundary, Iconfont as Icon, ImportWidgetComponent, Loading, NotFound, FFPopup as Popup, SetPropsWrapper }; +export { ErrorBoundary, ImportWidgetComponent }; +export type { FallbackOnError, LayoutKey, ThemeContext, ThemeRenderer, WidgetInput }; diff --git a/components.js b/components.js index 29d8c8f..85ddee8 100644 --- a/components.js +++ b/components.js @@ -1,11 +1,13 @@ -import { au as r, aK as p, al as s, aL as t, av as n, aw as e, at as d, aJ as m } from "./common/main.js"; +import { as as s, aI as t, aj as m, aJ as n, at as e, au as d, ar as i, aH as u } from "./common/main.js"; +import "react/jsx-runtime"; +import "react"; export { - r as Empty, - p as ErrorBoundary, - s as Icon, - t as ImportWidgetComponent, - n as Loading, - e as NotFound, - d as Popup, - m as SetPropsWrapper + s as Empty, + t as ErrorBoundary, + m as Icon, + n as ImportWidgetComponent, + e as Loading, + d as NotFound, + i as Popup, + u as SetPropsWrapper }; diff --git a/container.d.ts b/container.d.ts index 1bf6a80..ab618a8 100644 --- a/container.d.ts +++ b/container.d.ts @@ -1,87 +1,101 @@ -import * as React from 'react'; -import React__default from 'react'; -import PropTypes from 'prop-types'; +import React, { ReactNode, CSSProperties } from 'react'; +import { GridLayoutFormField } from './grid-layout-form'; /** 空状态占位组件 */ -declare function Empty(): React__default.JSX.Element; +declare function Empty(): React.JSX.Element; /** 加载中占位组件 */ -declare function Loading(): React__default.JSX.Element; +declare function Loading(): React.JSX.Element; /** 未找到占位组件 */ -declare function NotFound(): React__default.JSX.Element; +declare function NotFound(): React.JSX.Element; /** * 为页面级布局提供 SlotContext,把子元素(通常是 FFContainer)挂载的 * title/subTitle/actions/extras 等插槽内容收集起来,再作为 props 传回给这个子元素 * @param {Object} props - * @param {import('react').ReactElement} props.children 单个子元素(字符串类型的元素会跳过插槽逻辑,原样返回) + * @param {ReactElement} props.children 单个子元素(字符串类型的元素会跳过插槽逻辑,原样返回) */ declare function FFPageRender({ children }: { children: React.ReactElement; -}): React__default.JSX.Element; -declare namespace FFPageRender { - namespace propTypes { - let children: PropTypes.Validator; - } -} +}): React.JSX.Element; -/** FFContainer 内部用来把 title/subTitle/actions/extras 等具名插槽挂载到外层布局的 context */ -declare const SlotContext: React__default.Context<{ - ele: {}; - mount: () => void; - unmount: () => void; -}>; +/** 已知的内容插槽 key(由 FFContainer.slot / PopupContainer 维护) */ +type SlotKey = 'title' | 'subTitle' | 'actions' | 'extras' + +/** 插槽元素映射;由 FFPageRender / PopupContainer 的 useState 维护 */ +interface SlotElements { + /** title 插槽内容 */ + title?: ReactNode + /** 副标题插槽内容 */ + subTitle?: ReactNode + /** 操作按钮插槽内容 */ + actions?: ReactNode + /** 扩展区插槽内容 */ + extras?: ReactNode + /** 挂载到外层布局根节点的 className */ + rootClassName?: string + [key: string]: ReactNode | string | undefined +} /** - * 页面级容器,通过 SlotContext 把 title/subTitle/actions/extras 挂载到外层布局的对应插槽位置 - * @param {Object} props - * @param {string} [props.rootClassName] 挂载到外层布局根节点的 className - * @param {string} [props.className] 容器自身的 className - * @param {*} [props.children] 容器内容 - * @param {*} [props.actions] 挂载到 actions 插槽的内容 - * @param {*} [props.title] 挂载到 title 插槽的内容 - * @param {*} [props.subTitle] 挂载到 sub-title 插槽的内容 - * @param {*} [props.extras] 挂载到 extras 插槽的内容 - * @param {Object} [props.style] 容器行内样式 + * SlotContext 的值结构;由 FFPageRender / PopupContainer 提供,FFContainer / slot 内部消费 + * (也可在自定义 theme 容器中消费) */ -declare function FFContainer({ rootClassName, className, children, actions, title, subTitle, extras, style }: { - rootClassName?: string; - className?: string; - children?: any; - actions?: any; - title?: any; - subTitle?: any; - extras?: any; - style?: any; -}): React__default.JSX.Element; -declare namespace FFContainer { - function Action({ children, className }: { - children: any; - className: any; - }): any; - function Title({ children, className }: { - children: any; - className: any; - }): any; - function SubTitle({ children, className }: { - children: any; - className: any; - }): any; - function Extra({ children, className }: { - children: any; - className: any; - }): any; - namespace propTypes { - let className: PropTypes.Requireable; - let style: PropTypes.Requireable; - let title: PropTypes.Requireable; - let subTitle: PropTypes.Requireable; - let actions: PropTypes.Requireable; - let extras: PropTypes.Requireable; - } +interface SlotContextValue { + /** 已挂载的插槽元素映射 */ + ele: SlotElements + /** 挂载一个插槽元素 */ + mount: (slot: string, element: ReactNode) => void + /** 卸载一个插槽元素 */ + unmount: (slot: string) => void } +/** Popup.modal / PopupContainer 的容器配置参数 */ +interface PopupContainerProps { + /** 弹窗标题;支持 lodash template 插值(以触发时的 raw data 为上下文) */ + title?: string + /** + * 弹出位置;'center'(默认)渲染为居中模态框, + * 'left'/'right'/'top'/'bottom' 渲染为对应方向的抽屉 + */ + placement?: 'center' | 'left' | 'top' | 'right' | 'bottom' + /** 内容区宽度(模态框有效) */ + width?: number | string + /** 内容区高度 */ + height?: number | string + /** 内容区行内样式(模态框有效) */ + style?: CSSProperties + /** 根节点额外 class */ + className?: string + /** 各分区 class */ + classNames?: { + header?: string + body?: string + footer?: string + close?: string + } + /** 点击蒙层是否关闭弹窗,默认 false */ + maskClosable?: boolean + [key: string]: unknown +} + +/** + * Popup.modal 的返回值; + * 关闭时 resolve 传入的值,`update` 可在弹窗打开期间动态更新内容 props 和容器 props + */ +type PopupHandle = Promise & { + update: ( + widgetPatch?: Record, + containerPatch?: Partial + ) => void +} + +/** FFContainer 内部用来把 title/subTitle/actions/extras 等具名插槽挂载到外层布局的 context + * @type {Context} + */ +declare const SlotContext: React.Context; + declare namespace FFPopup { export { modal }; export { confirm }; @@ -93,55 +107,53 @@ declare namespace FFPopup { /** * 打开一个任意组件的弹窗 - * @param {Function} widget 要渲染的组件 - * @param {Object} [widgetData] 传给组件的 props - * @param {Object} [widgetContainerProps] 传给弹窗容器(PopupContainer)的 props - * @returns {Promise<*>&{update: Function}} resolve 弹窗关闭时传入的值;promise.update(patch, containerPatch) 可用来更新弹窗内容 + * @param {ComponentType} widget 要渲染的组件 + * @param {Record} [widgetData] 传给组件的 props + * @param {PopupContainerProps} [widgetContainerProps] 传给弹窗容器(PopupContainer)的 props + * @returns {PopupHandle} 关闭时 resolve 传入的值;`promise.update(patch, containerPatch)` 可动态更新弹窗 */ -declare function modal(widget: Function, widgetData?: any, widgetContainerProps?: any): Promise & { - update: Function; -}; +declare function modal(widget: React.ComponentType, widgetData?: Record, widgetContainerProps?: PopupContainerProps): PopupHandle; /** * 弹出一个确认框 - * @param {*} content 确认框内容 + * @param {ReactNode} content 确认框内容 * @param {Object} [opts] 其余透传给 Confirm 组件的 props - * @returns {Promise<*>} 点击确认时 resolve,点击取消/关闭时按 modal 的语义处理 + * @returns {PopupHandle} 点击确认时 resolve,点击取消/关闭时 resolve(false) */ -declare function confirm(content: any, opts?: any): Promise; +declare function confirm(content: React.ReactNode, opts?: any): PopupHandle; /** - * 弹出一个模态表单;取消时 reject(false) - * @param {Array} fields 表单字段配置(传给 FormModal 的 fields) - * @param {Object} [widgetContainerProps] 传给弹窗容器的 props - * @param {Object} [formProps] 传给表单的额外 props - * @returns {Promise} 提交后的表单数据 + * 弹出一个模态表单;取消时 resolve(false) + * @param {GridLayoutFormField[]} fields 表单字段配置(传给 FormModal 的 fields) + * @param {PopupContainerProps} [widgetContainerProps] 传给弹窗容器的 props + * @param {Record} [formProps] 传给表单的额外 props + * @returns {PopupHandle>} 提交后的表单数据 */ -declare function form(fields: any[], widgetContainerProps?: any, formProps?: any): Promise; +declare function form(fields: GridLayoutFormField[], widgetContainerProps?: PopupContainerProps, formProps?: Record): PopupHandle>; /** * 弹出一条消息提示 - * @param {*} content 提示内容 - * @param {Object} [opts] 其余透传给 Notification 组件的 props,duration/showProgress 会转发到容器 props - * @returns {Promise<*>} + * @param {ReactNode} content 提示内容 + * @param {Object} [opts] 其余透传给 Notification 组件的 props,duration/showProgress 会转发到容器 props + * @returns {PopupHandle} */ -declare function notification(content: any, { showProgress, duration, ...opts }?: any): Promise; +declare function notification(content: React.ReactNode, { showProgress, duration, ...opts }?: any): PopupHandle; /** - * 成功提示(绿色图标样式的 notification) - * @param {*} content 提示内容 + * 成功提示(绿色图标样式的 notification) + * @param {ReactNode} content 提示内容 * @param {Object} [opts] 其余透传给 notification 的选项 - * @returns {Promise<*>} + * @returns {PopupHandle} */ -declare function success(content: any, opts?: any): Promise; +declare function success(content: React.ReactNode, opts?: any): PopupHandle; /** - * 错误提示(红色图标样式的 notification) - * @param {*} content 提示内容 + * 错误提示(红色图标样式的 notification) + * @param {ReactNode} content 提示内容 * @param {Object} [opts] 其余透传给 notification 的选项 - * @returns {Promise<*>} + * @returns {PopupHandle} */ -declare function error(content: any, opts?: any): Promise; +declare function error(content: React.ReactNode, opts?: any): PopupHandle; /** * 弹层渲染出口(通常挂载一份到页面根部);负责渲染 FFPopup 触发的所有弹窗/模态框和 notification。 * 在挂载前调用 FFPopup 的方法会被排队,挂载后统一渲染出来 */ -declare function FFPopupRender(): React__default.JSX.Element; +declare function FFPopupRender(): React.JSX.Element; declare namespace FFPopupRender { let $popups: Map; let $index: number; @@ -149,4 +161,5 @@ declare namespace FFPopupRender { function $onClick(...args: any[]): Promise; } -export { SlotContext as Context, Empty, Loading, NotFound, FFPageRender as PageRender, FFPopup as Popup, FFPopupRender as PopupRender, FFContainer as default }; +export { SlotContext as Context, Empty, Loading, NotFound, FFPageRender as PageRender, FFPopup as Popup, FFPopupRender as PopupRender }; +export type { PopupContainerProps, PopupHandle, SlotContextValue, SlotElements, SlotKey }; diff --git a/container.js b/container.js index 612e558..a3bd404 100644 --- a/container.js +++ b/container.js @@ -1,11 +1,11 @@ -import { aq as e, au as o, av as p, aw as t, ar as d, at as n, as as r, ap as u } from "./common/main.js"; +import { ao as s, as as e, at as p, au as t, ap as n, ar as d, aq as r, an as u } from "./common/main.js"; export { - e as Context, - o as Empty, + s as Context, + e as Empty, p as Loading, t as NotFound, - d as PageRender, - n as Popup, + n as PageRender, + d as Popup, r as PopupRender, u as default }; diff --git a/data-converter.d.ts b/data-converter.d.ts index 58142f9..77f7923 100644 --- a/data-converter.d.ts +++ b/data-converter.d.ts @@ -1,33 +1,112 @@ -import React from 'react'; +import { WidgetType, WidgetContainerProps } from './button'; -/** - * 按一串中间件(middleware)链式转换数据;每个中间件可以是函数,也可以是要动态加载的 - * 组件名字符串(通过 core.getWidgetComponent 解析),支持嵌套数组表示的中间件组 - */ -declare class DataConverter { - static "__#private@#resolver": any; - static "__#private@#newMiddleware": any; - /** - * @param {...(Array|[string|Function, *])} middlewares 中间件列表,每项是 - * [中间件名或函数, 传给中间件的配置],或者是这种元组的嵌套数组(会被展开) - */ - constructor(...middlewares: (any[] | [string | Function, any])[]); - /** - * 依次跑完所有中间件,把 value 转换成最终结果;单个中间件报错会被跳过,不中断整条链 - * @param {*} value 原始值 - * @param {*} [record] 关联的记录数据,中间件里可通过 this.getRecord() 取到 - * @returns {Promise<*>} 转换后的结果 - */ - toValue: (value: any, record?: any) => Promise; - /** - * 把 toValue 的异步转换结果渲染成 React 元素;转换完成前显示 loading,转换出错则显示错误信息 - * @param {*} value 原始值 - * @param {*} record 关联的记录数据 - * @param {*} [loading] 转换完成前显示的占位内容 - * @returns {React.ReactElement} - */ - toRender: (value: any, record: any, loading?: any) => React.ReactElement; - #private; +// ===== 用户数据结构(复用类型,JSDoc 无法跨文件引用,放 .d.ts) ===== + +interface UserRoleBinding { + user_uuid: string + role_uuid: string + created_at: string + updated_at: string + created_user: string + owned_user: string } -export { DataConverter as default }; +interface UserInfo { + uuid: string + username: string + nickname: string + email: string + last_login_ip: string + is_active: 0 | 1 + UserRole: UserRoleBinding[] + [key: string]: unknown +} + + +interface MenuItem { + /** 菜单唯一标识 */ + uuid: string + /** 菜单显示名称 */ + name: string + /** 图标 class 名 */ + icon: string + /** 行为目标(组件标识 / 路由 uuid 等),含义随 widgetType 而定 */ + widget: string + /** 行为类型 */ + widgetType: WidgetType + /** 传给目标组件的 props 映射配置 */ + widgetProps: Record + /** 传给目标组件的 $setting 配置 */ + widgetSetting: Record + /** 弹窗容器配置 */ + widgetContainerSetting: WidgetContainerProps + /** 子菜单 */ + children?: MenuItem[] +} + +interface RouteItem { + /** 路由唯一标识 */ + uuid: string + /** 路由名称 */ + name: string + /** react-router path,支持动态参数(如 /page/:id) */ + uri: string + /** 是否为布局路由(外层 layout,不直接渲染页面内容) */ + isLayout: boolean + /** 是否需要登录才能访问 */ + isLogin: boolean + /** 是否为手机端专属路由 */ + isPhone: boolean + /** 路由类型 */ + type: Exclude + /** 是否精确匹配路径 */ + exact: boolean + /** widget 标识(等同于 ButtonProps.widget),经 core.getWidgetComponent 加载 */ + component: string + /** 传给页面组件的 props 映射配置 */ + widgetProps: Record + /** 传给页面组件的 $setting 配置 */ + widgetSetting: Record + /** 弹窗容器配置 */ + widgetContainerSetting: WidgetContainerProps + /** 附加配置(如 layout 标识等) */ + extra?: Record +} + +// ===== http — Proxy 模式产生交叉类型,JSDoc 无法表达 ===== + +/** 每次请求自动附加的请求头 */ +interface HttpHeaders { + /** 客户端平台标识,固定为 'web' */ + Platform: string + /** SaaS 租户标识,单租户时为 null */ + SaaS: string | null + /** JWT Bearer token,未登录时为 undefined */ + Authorization: string | undefined +} + +// ===== func — ff-worker-pipe 无类型文件,显式声明 ===== + +/** + * 基于 Worker 的表达式执行引擎单例; + * exec 在独立 Worker 上下文中求值一段 JS 表达式/源码 + */ +interface WorkerPipeInstance { + /** + * 在 Worker 上下文中执行一段 JS 表达式 + * @param expression 要执行的表达式字符串 + * @param args 传给表达式的参数(可在表达式内作为第一个参数使用) + * @param fns 注入到表达式执行作用域的额外可调用函数 + * @param session 会话标识;相同 session 共享 Worker 侧工作区(this) + */ + exec: ( + expression: string, + args?: Record, + fns?: Record, + session?: string + ) => Promise + /** 清除指定 session 的 Worker 侧工作区 */ + clear: (session: string) => void +} + +export type { HttpHeaders, MenuItem, RouteItem, UserInfo, UserRoleBinding, WorkerPipeInstance }; diff --git a/data-list.d.ts b/data-list.d.ts index 2f82fd2..c6f7058 100644 --- a/data-list.d.ts +++ b/data-list.d.ts @@ -1,51 +1,259 @@ -import React from 'react'; -import PropTypes from 'prop-types'; +import React, { ReactNode as ReactNode$1, ComponentType, ReactElement } from 'react'; +import { ButtonOption, WidgetContainerProps } from './button'; +import { GridLayoutProps } from './grid-layout'; + +/** 宫格卡片的 GridLayout 布局配置,透传给 DataListContent / GridLayout */ +interface DataListItemForGridLayout extends GridLayoutProps {} + +/** 列表操作按钮配置(行内操作 / 批量操作通用) */ +type DataListOperation = ButtonOption & { + /** 操作后是否刷新:0 不刷新,1 整体刷新,2 局部刷新(只更新当前行) */ + isRefresh?: 0 | 1 | 2 +} + +/** 表格列配置,在 antd ColumnType 基础上扩展数据列表能力 */ +interface DataListColumn { + /** 列标题 */ + title?: string + /** 对应数据字段名 */ + dataIndex?: string | string[] + /** 列唯一 key */ + key?: string + /** 列宽(px) */ + width?: number + /** 是否固定宽度,不参与自适应缩放 */ + isWidthFixed?: boolean + /** 固定列方向 */ + fixed?: 'left' | 'right' | boolean + /** 对齐方式 */ + align?: 'left' | 'center' | 'right' + /** 自定义渲染函数 */ + render?: (value: unknown, record: Record, index: number) => ReactNode$1 + /** 渲染中间件列表,由 DataConverter 链式处理 */ + middlewares?: unknown[] + /** 动态渲染控件标识(通过 core.getWidgetComponent 加载) */ + widgetByJs?: string + /** widgetByJs 的 $setting 配置 */ + widgetByJsSetting?: Record + /** 是否可行内编辑 */ + editableByJs?: boolean + /** 行内编辑配置 */ + editableByJsSetting?: { + formSetting?: { primaryKey?: string; help?: string; validators?: Record } + widgetSetting?: Record + widgetContainerSetting?: WidgetContainerProps + } + [key: string]: unknown +} + +/** 列表 tab 配置项 */ +interface DataListTab { + /** tab 唯一标识(优先使用) */ + value?: unknown + /** tab 编码(value 不存在时使用) */ + code?: unknown + /** tab 显示文本 */ + label?: string + [key: string]: unknown +} + +/** DataList / DataListHelper 各区块自定义 className */ +interface DataListClassNames { + sider?: string + filter?: string + footer?: string + toolbar?: string + container?: string + content?: string + item?: string + empty?: string +} + +/** DataList layouts prop — 各子区块组件,false 表示全部隐藏 */ +interface DataListLayouts { + sider?: ComponentType | ReactElement | null + filter?: ComponentType | ReactElement | null + footer?: ComponentType | ReactElement | null + toolbar?: ComponentType | ReactElement | null + empty?: ComponentType | ReactElement | null +} + +/** 行选择配置 */ +interface DataListRowSelection { + /** 选择模式 */ + type?: 'checkbox' | 'radio' + /** 受控选中的行 key 列表 */ + selectedRowKeys?: unknown[] + /** 默认选中行 key(非受控) */ + defaultSelectedRowKeys?: unknown[] + /** 选中行变化回调 */ + onChange?: (keys: unknown[], rows: Record[]) => void + /** 选择列宽度(px),默认 32 */ + columnWidth?: number + [key: string]: unknown +} + +/** /api/_/{listCode} 返回的列表结构配置,由 DataListHelper 通过 setStructure 消费 */ +interface DataListStructure { + /** 关联资源标识 */ + resource?: string + /** 主键字段名 */ + primaryKey?: string + /** 表格列配置 */ + columns?: DataListColumn[] + /** 行内操作按钮配置 */ + itemOperations?: DataListOperation[] + /** 批量操作按钮配置 */ + batchOperations?: DataListOperation[] + /** 是否使用表单布局模式的筛选条件 */ + isConditionFormLayout?: boolean + /** 是否启用树形侧边栏 */ + isTreeSider?: boolean + /** 树形侧边栏配置 */ + treeSiderConfig?: Record + /** 主题组件标识 */ + theme?: string + /** 传给主题组件的 $setting */ + themeConfig?: Record + /** 是否使用宫格卡片布局 */ + isItemGridLayout?: boolean + /** + * 宫格卡片布局配置(API 格式) + * 注:themeConfig 在 DataListHelper 中会被重命名为 themeProps 后再传给组件 + */ + itemGridLayout?: Omit & { themeConfig?: Record } + /** 列表标题 */ + title?: string + /** 是否分页 */ + isPaginate?: boolean + /** tab 配置 */ + tabs?: DataListTab[] + /** 行选择模式 */ + selectionType?: 'checkbox' | 'radio' + /** 是否启用动态刷新(WebSocket 订阅) */ + isDynamicRefresh?: boolean + [key: string]: unknown +} + +/** + * 行内操作权限映射:key 为操作按钮 uuid,value 为拥有该权限的行主键列表; + * 由后端 list-operations-access 接口返回,通过 useOperationCallback 管理 + */ +type DataListItemOperationsAccess = Map + +/** 列表查询参数,用于分页/筛选/tab/关键字等,经 base62 编码后传给后端 */ +interface DataListQueryParams { + /** 当前页码,默认 1 */ + page?: number + /** 每页条数,默认 30 */ + pageSize?: number + /** 当前选中的 tab 值 */ + tab?: unknown + /** 关键字搜索值 */ + keyword?: string + /** 筛选条件(字段名 → 值) */ + condition?: Record + /** 侧边栏选中值 */ + sider?: unknown + /** 数据总条数(仅用于回显,不参与请求) */ + total?: number + /** 附加请求参数,透传到后端 */ + payload?: Record + [key: string]: unknown +} + +/** + * DataList 对外暴露的操作 API; + * 由 DataList 通过 Context 注入,供动态脚本及子组件(如 ff-button)调用 + */ +interface DataListAPI { + /** 获取当前查询参数;k 为字段名时返回单个值,'init' 或空时返回全量对象 */ + getBase62params: (k?: string, defaultValue?: unknown) => unknown + /** 获取当前已选中行数据 */ + getSelectedRows: () => Record[] + reload: (params?: Partial) => void + setPage: (page: number, pageSize?: number) => void + setPageSize: (pageSize: number) => void + setTab: (tab: unknown) => void + setSider: (sider: unknown) => void + setKeyword: (keyword: string) => void + setCondition: (value: Record, keyword?: string) => void +} + +/** DataListContext 的值结构,由 DataList 通过 Provider 注入,内部子组件通过 useContext 消费 */ +interface DataListContextValue extends DataListAPI { + listCode?: string + classNames?: DataListClassNames + onReload: (params?: Partial) => void + onClickCallback?: (isRefresh: number, item?: Record | null) => void + onConditionChange: (value: Record, keyword?: string) => void + onTabChange: (tab: unknown) => void + onSiderChange: (sider: unknown) => void + onKeywordChange: (keyword: string) => void + onPageChange: (page: number, pageSize?: number) => void + onPageSizeChange: (pageSize: number) => void +} + +/** useDataListHelper 的返回值:继承 DataListQueryParams 当前状态 + 数据 + 各维度更新方法 */ +interface DataListHelperState extends DataListQueryParams { + /** 当前页数据 */ + dataSource: Record[] + /** 操作权限映射:操作 uuid → 有权限的行主键列表 */ + itemOperationsAccess: DataListItemOperationsAccess + /** 主键字段名(来自结构配置) */ + primaryKey?: string + onReload: DataListContextValue['onReload'] + onTabChange: DataListContextValue['onTabChange'] + onPageChange: DataListContextValue['onPageChange'] + onPageSizeChange: DataListContextValue['onPageSizeChange'] + onConditionChange: DataListContextValue['onConditionChange'] + onSiderChange: DataListContextValue['onSiderChange'] + onKeywordChange: DataListContextValue['onKeywordChange'] + onClickCallback?: DataListContextValue['onClickCallback'] +} + +/** DataListHelper 通过 ref 暴露的方法 */ +interface DataListHelperRef { + /** 触发整体刷新 */ + reload: () => void + /** 获取已选中行数据 */ + getSelectedRows: () => Record[] + /** Button 操作完成后通知列表刷新:isRefresh=1 整体刷新,2 局部刷新(item 为当前行数据) */ + emitOperation: (isRefresh: number, item?: Record | null) => void +} /** * 处理表格列配置:为每列注入 onCell,并按 middlewares/widgetByJs 组装渲染中间件链(通过 DataConverter)生成最终的 render 函数 - * @param {Array} columns 原始列配置(可能包含 widgetByJs/widgetByJsSetting/middlewares/render) + * @param {DataListColumn[]} columns 原始列配置(可能包含 widgetByJs/widgetByJsSetting/middlewares/render) * @param {Object} [base62params={}] 分页/查询参数,仅作为依赖项触发重新计算 - * @returns {Array} 处理后可直接传给 antd Table 的列配置 + * @returns {DataListColumn[]} 处理后可直接传给 antd Table 的列配置 */ -declare function useColumnsRender(columns: Array, base62params?: any): Array; +declare function useColumnsRender(columns: DataListColumn[], base62params?: any): DataListColumn[]; /** * 补全 antd Table 的 components 配置,确保 body.cell 默认使用可编辑单元格组件 DataListCellEditable * @param {Object} [components={}] 原始 components 配置 * @returns {Object} 补全后的 components 配置 */ declare function useCellEditableComponents(components?: any): any; -/** - * 根据 listCode 拉取列表结构配置(字段/列/分页/布局等元数据) - * @param {string} listCode 列表标识 - * @returns {Object} 列表结构配置,请求完成前为空对象 - */ -declare function useStructure(listCode: string): any; -/** - * 根据 listCode 及查询参数拉取列表数据 - * @param {string} listCode 列表标识 - * @param {Object} [base62params={}] 查询参数,会与 page:1 合并后进行 base62 编码请求 - * @returns {Object} 接口返回的数据,包含 dataSource 等字段;请求完成前为 { dataSource: [] } - */ -declare function useDataSource(listCode: string, base62params?: any): any; /** * 生成一个按权限映射过滤某行数据可用行内操作按钮的函数 - * @param {Array} [itemOperations=[]] 行内操作按钮配置 - * @param {Map} [itemOperationsAccess=new Map] 操作 uuid 到有权限的数据主键列表的映射 + * @param {DataListOperation[]} [itemOperations=[]] 行内操作按钮配置 + * @param {DataListItemOperationsAccess} [itemOperationsAccess=new Map] 操作 uuid 到有权限的数据主键列表的映射 * @param {string} [pk='id'] 主键字段名 * @param {string} [resource] 数据嵌套的资源字段名(主键从 data[resource][pk] 取值) - * @returns {(data: Object) => Array} 传入一行数据,返回其可用操作按钮列表 + * @returns {(data: Record) => DataListOperation[]} 传入一行数据,返回其可用操作按钮列表 */ -declare function useItemOperationsAccess(itemOperations?: Array, itemOperationsAccess?: Map, pk?: string, resource?: string): (data: any) => Array; +declare function useItemOperationsAccess(itemOperations?: DataListOperation[], itemOperationsAccess?: DataListItemOperationsAccess, pk?: string, resource?: string): (data: Record) => DataListOperation[]; /** * 判断是否需要渲染操作列:操作按钮需通过全局权限校验(auth.check),且(若配置了行级权限映射)当前数据中至少一行拥有权限 - * @param {Array} [operations=[]] 操作按钮配置 - * @param {Map} [itemOperationsAccess=new Map] 操作 uuid 到有权限的数据主键列表的映射 - * @param {Array} [dataSource=[]] 当前页数据 + * @param {DataListOperation[]} [operations=[]] 操作按钮配置 + * @param {DataListItemOperationsAccess} [itemOperationsAccess=new Map] 操作 uuid 到有权限的数据主键列表的映射 + * @param {Record[]} [dataSource=[]] 当前页数据 * @param {string} [pk='id'] 主键字段名 * @param {string} [resource] 数据嵌套的资源字段名 * @returns {boolean} 是否存在可展示的操作列 */ -declare function useHasOperationColumn(operations?: Array, itemOperationsAccess?: Map, dataSource?: Array, pk?: string, resource?: string): boolean; +declare function useHasOperationColumn(operations?: DataListOperation[], itemOperationsAccess?: DataListItemOperationsAccess, dataSource?: Record[], pk?: string, resource?: string): boolean; /** * 生成行内/批量操作点击后的处理逻辑:isRefresh=1 触发整体刷新(onReload),isRefresh=2 仅拉取该行最新详情与权限并合并回 dataSource(局部刷新) * @param {Object} props 列表状态,须包含 dataSource/itemOperationsAccess/onReload @@ -58,91 +266,10 @@ declare function useOperationCallback(props: any, listCode: string, primaryKey?: /** * 组合式获取并管理列表数据(分页/tab/筛选条件/侧边栏/关键字等),供 DataListHelper 使用 * @param {string} listCode 列表标识 - * @param {Object} base62params 初始查询参数 - * @returns {Object} 列表状态与操作方法(dataSource/tab/page/pageSize/condition/sider/keyword/total/itemOperationsAccess/onXxxChange/onReload/payload 等) + * @param {DataListQueryParams} base62params 初始查询参数 + * @returns {DataListHelperState} */ -declare function useDataListHelper(listCode: string, base62params: any): any; - -/** - * 数据列表根组件:根据 isItemGridLayout 选择宫格(DataListFramework)或表格(DataTableFramework)布局, - * 也可通过 theme 动态加载自定义主题组件替代默认布局;并通过 DataListContext 向下透传分页/筛选/选中等状态与操作方法 - * @param {Object} props - * @param {boolean} [props.isItemGridLayout] 是否使用宫格布局(否则使用表格布局,theme 设置时忽略) - * @param {string} [props.theme] 自定义主题组件标识,设置后通过 core.getWidgetComponent 动态加载并替代默认布局 - * @param {Object} [props.themeProps] 传给自定义主题组件的 $setting - * @param {Function} [props.onClickCallback] 行内/批量操作点击后的回调 - * @param {Function} [props.onReload] 刷新回调 - * @param {string} [props.listCode] 列表标识 - * @param {number} [props.total=0] 数据总条数 - * @param {number} [props.page=0] 当前页码 - * @param {Function} [props.onPageChange] 页码变更回调 - * @param {number} [props.pageSize=30] 每页条数 - * @param {Function} [props.onPageSizeChange] 每页条数变更回调 - * @param {*} [props.tab] 当前选中的 tab - * @param {Function} [props.onTabChange] tab 变更回调 - * @param {string} [props.keyword] 关键字搜索值 - * @param {Function} [props.onKeywordChange] 关键字变更回调 - * @param {Object} [props.condition] 筛选条件 - * @param {Function} [props.onConditionChange] 筛选条件变更回调 - * @param {*} [props.sider] 侧边栏选中值 - * @param {Function} [props.onSiderChange] 侧边栏选中值变更回调 - * @param {boolean|Object} [props.layouts] 自定义子布局组件集合(sider/filter/footer/toolbar/empty),false 表示全部隐藏 - * @param {Object} [props.classNames={}] 各区块自定义 className - * @param {Object} [props.payload={}] 附加请求参数 - * @param {Array} [props.dataSource=[]] 列表数据 - * @param {Object} [props.rowSelection] 行选择配置 - * @param {Function} [props.getSelectedRows] 获取已选中行的方法,未提供时默认返回 dataSource - * @param {string} [props.primaryKey] 主键字段名 - */ -declare function DataList({ isItemGridLayout, theme, themeProps, onClickCallback, onReload, listCode, total, page, onPageChange, pageSize, onPageSizeChange, tab, onTabChange, keyword, onKeywordChange, condition, onConditionChange, sider, onSiderChange, layouts, classNames, payload, dataSource, rowSelection, getSelectedRows: getSelectedRowsProp, primaryKey, ...props }: { - isItemGridLayout?: boolean; - theme?: string; - themeProps?: any; - onClickCallback?: Function; - onReload?: Function; - listCode?: string; - total?: number; - page?: number; - onPageChange?: Function; - pageSize?: number; - onPageSizeChange?: Function; - tab?: any; - onTabChange?: Function; - keyword?: string; - onKeywordChange?: Function; - condition?: any; - onConditionChange?: Function; - sider?: any; - onSiderChange?: Function; - layouts?: boolean | any; - classNames?: any; - payload?: any; - dataSource?: any[]; - rowSelection?: any; - getSelectedRows?: Function; - primaryKey?: string; -}): React.JSX.Element; -declare namespace DataList { - namespace propTypes { - let classNames: PropTypes.Requireable; - filter: PropTypes.Requireable; - footer: PropTypes.Requireable; - toolbar: PropTypes.Requireable; - container: PropTypes.Requireable; - content: PropTypes.Requireable; - item: PropTypes.Requireable; - empty: PropTypes.Requireable; - }>>>; - let layouts: PropTypes.Requireable>; - filter: PropTypes.Requireable>; - footer: PropTypes.Requireable>; - toolbar: PropTypes.Requireable>; - empty: PropTypes.Requireable>; - }>>>>; - } -} +declare function useDataListHelper(listCode: string, base62params: DataListQueryParams): DataListHelperState; /** * 列表筛选区:isConditionFormLayout 为 true 时拉取后台配置的条件表单结构并渲染 GridLayoutForm,否则渲染默认的关键字搜索框 @@ -179,12 +306,12 @@ declare namespace DataListFilter { * @param {Object} props * @param {string} [props.className] 自定义 className * @param {string} [props.title] 列表标题 - * @param {Array} [props.tabs] tab 配置列表 + * @param {DataListTab[]} [props.tabs] tab 配置列表 */ declare function DataListToolbar({ className, title, tabs }: { className?: string; title?: string; - tabs?: Array; + tabs?: DataListTab[]; }): React.JSX.Element; /** @@ -204,29 +331,29 @@ declare function DataListSider({ className, width, isTreeSider }: { * 列表底部:渲染批量操作按钮与分页器;operations 为空且不分页时不渲染任何内容 * @param {Object} props * @param {string} [props.className] 自定义 className - * @param {Array} [props.operations] 批量操作按钮配置 + * @param {DataListOperation[]} [props.operations] 批量操作按钮配置 * @param {boolean} [props.isOperations] 是否展示批量操作按钮 * @param {boolean} [props.isPaginate] 是否展示分页器 */ declare function DataListFooter({ className, operations, isOperations, isPaginate }: { className?: string; - operations?: Array; + operations?: DataListOperation[]; isOperations?: boolean; isPaginate?: boolean; }): React.JSX.Element; /** * DataList 的开箱即用封装:根据 listCode 自动拉取结构与数据、管理分页/筛选/选中等状态, - * 并通过 ref 暴露 onReload/onClickCallback/getSelectedRows + * 并通过 ref 暴露 reload/emitOperation/getSelectedRows * @param {Object} props * @param {string} props.listCode 列表标识 - * @param {Object} [props.base62params] 初始查询参数 + * @param {DataListQueryParams} [props.base62params] 初始查询参数 * @param {string} [props.className] 自定义 className * @param {string} [props.theme] 自定义主题组件标识,未传时使用结构配置中的 theme * @param {Object} [props.themeProps] 传给主题组件的 $setting,会与结构配置中的 themeConfig 合并 - * @param {boolean|Object} [props.layouts] 自定义子布局组件集合 - * @param {Object} [props.classNames] 各区块自定义 className - * @param {Object} [props.rowSelection] 行选择配置(type/selectedRowKeys/defaultSelectedRowKeys/onChange 等) + * @param {DataListLayouts|false} [props.layouts] 自定义子布局组件集合 + * @param {DataListClassNames} [props.classNames] 各区块自定义 className + * @param {DataListRowSelection} [props.rowSelection] 行选择配置(type/selectedRowKeys/defaultSelectedRowKeys/onChange 等) * @param {(dataSource: Array, meta: Object) => void} [props.onDataSourceChange] dataSource 变更后的回调 */ declare const DataListHelper: React.ForwardRefExoticComponent>; @@ -234,7 +361,7 @@ declare const DataListHelper: React.ForwardRefExoticComponent void; + getBase62params: (k: string, defaultValue: unknown) => void; getSelectedRows: () => any[]; onReload: () => void; onClickCallback: () => void; @@ -258,22 +385,22 @@ declare const _default: React.Context<{ * @param {Object} props * @param {string} [props.className] 自定义 className * @param {string} [props.primaryKey] 主键字段名 - * @param {Array} [props.columns=[]] 列配置 - * @param {Array} [props.dataSource=[]] 表格数据 - * @param {(record: Object, index: number) => *} [props.operationRender] 操作列渲染函数,提供时会追加一列操作列 + * @param {DataListColumn[]} [props.columns=[]] 列配置 + * @param {Record[]} [props.dataSource=[]] 表格数据 + * @param {(record: Record, index: number) => ReactNode} [props.operationRender] 操作列渲染函数,提供时会追加一列操作列 * @param {number} [props.operationWidth=180] 操作列宽度 * @param {Object} [props.components={}] antd Table 的 components 配置 - * @param {Object} [props.rowSelection] 行选择配置 + * @param {DataListRowSelection} [props.rowSelection] 行选择配置 */ declare function DataListTable({ className, primaryKey, columns, dataSource, operationRender, operationWidth, components, rowSelection, ...props }: { className?: string; primaryKey?: string; - columns?: Array; - dataSource?: Array; - operationRender?: (record: any, index: number) => any; + columns?: DataListColumn[]; + dataSource?: Record[]; + operationRender?: (record: Record, index: number) => ReactNode; operationWidth?: number; components?: any; - rowSelection?: any; + rowSelection?: DataListRowSelection; }): React.JSX.Element; /** @@ -285,20 +412,20 @@ declare function DataListTable({ className, primaryKey, columns, dataSource, ope * @param {number} [props.rowHeight] 行高 * @param {[number, number]} [props.itemMargin] 卡片间距 [marginX, marginY] * @param {*} [props.containerPadding] 容器内边距 - * @param {Array} [props.fields] 卡片内字段/组件布局配置 + * @param {GridLayoutItem[]} [props.fields] 卡片内字段/组件布局配置 * @param {string} [props.primaryKey] 主键字段名 - * @param {Array} [props.dataSource] 列表数据 - * @param {(dataSource: Array) => *} [props.beforeRender=null] 数据渲染前的额外内容 - * @param {(dataSource: Array) => *} [props.afterRender=null] 数据渲染后的额外内容 + * @param {Record[]} [props.dataSource] 列表数据 + * @param {(dataSource: Record[]) => ReactNode} [props.beforeRender=null] 数据渲染前的额外内容 + * @param {(dataSource: Record[]) => ReactNode} [props.afterRender=null] 数据渲染后的额外内容 * @param {string} [props.itemClassName] 传给每张卡片(itemRender.children)的 className - * @param {(children: *, data: Object, index: number) => *} [props.itemRender] 卡片渲染包装函数 + * @param {(children: ReactNode, data: Record, index: number) => ReactNode} [props.itemRender] 卡片渲染包装函数 * @param {*} [props.empty] 空数据时展示的内容 * @param {string} [props.className] 自定义 className * @param {Object} [props.style={}] 容器行内样式 * @param {string} [props.theme] GridLayout 主题 * @param {Object} [props.themeProps={}] GridLayout 主题参数 - * @param {Array} [props.groups=[{ key: 'default', label: '默认' }]] 分组配置 - * @param {Object} [props.rowSelection] 行选择配置(selectedRowKeys/onChange/type) + * @param {GridLayoutGroup[]} [props.groups=[{ key: 'default', label: '默认' }]] 分组配置 + * @param {DataListRowSelection} [props.rowSelection] 行选择配置(selectedRowKeys/onChange/type) */ declare function DataListContent({ column, colWidth, cols, rowHeight, itemMargin, containerPadding, fields, primaryKey, dataSource, beforeRender, afterRender, itemClassName, itemRender, empty, className, style, theme, themeProps, groups, rowSelection, }: { column?: number; @@ -307,20 +434,20 @@ declare function DataListContent({ column, colWidth, cols, rowHeight, itemMargin rowHeight?: number; itemMargin?: [number, number]; containerPadding?: any; - fields?: Array; + fields?: _[]; primaryKey?: string; - dataSource?: Array; - beforeRender?: (dataSource: any[]) => any; - afterRender?: (dataSource: any[]) => any; + dataSource?: Record[]; + beforeRender?: (dataSource: Record[]) => _; + afterRender?: (dataSource: Record[]) => _; itemClassName?: string; - itemRender?: (children: any, data: any, index: number) => any; + itemRender?: (children: _, data: Record, index: number) => _; empty?: any; className?: string; style?: any; theme?: string; themeProps?: any; - groups?: Array; - rowSelection?: any; + groups?: _[]; + rowSelection?: DataListRowSelection; }): React.JSX.Element; /** @@ -328,46 +455,46 @@ declare function DataListContent({ column, colWidth, cols, rowHeight, itemMargin * @param {Object} props * @param {string} [props.listCode] 列表标识 * @param {string} [props.className] 自定义 className - * @param {Object} [props.layouts={}] 子布局组件集合 { sider, filter, toolbar, footer, empty } - * @param {Array} [props.dataSource] 列表数据 + * @param {DataListLayouts} [props.layouts={}] 子布局组件集合 { sider, filter, toolbar, footer, empty } + * @param {Record[]} [props.dataSource] 列表数据 * @param {boolean} [props.isPaginate] 是否分页 * @param {boolean} [props.isItemOperations] 是否展示行内操作按钮 * @param {boolean} [props.isBatchOperations] 是否展示批量操作按钮 - * @param {Array} [props.batchOperations] 批量操作按钮配置 - * @param {Array} [props.itemOperations] 行内操作按钮配置 - * @param {Map} [props.itemOperationsAccess] 行内操作权限映射 + * @param {DataListOperation[]} [props.batchOperations] 批量操作按钮配置 + * @param {DataListOperation[]} [props.itemOperations] 行内操作按钮配置 + * @param {DataListItemOperationsAccess} [props.itemOperationsAccess] 行内操作权限映射 * @param {string} [props.resource] 数据嵌套的资源字段名 * @param {string} [props.primaryKey] 主键字段名 * @param {string} [props.title] 列表标题 - * @param {Object} [props.itemGridLayout] 卡片宫格布局配置,透传给 DataListContent + * @param {DataListItemForGridLayout} [props.itemGridLayout] 卡片宫格布局配置,透传给 DataListContent * @param {Object} [props.$setting] 主题设置,包含 column/colWidth/beforeRender/afterRender/style/itemMargin/containerPadding/isMarkSelected - * @param {Array} [props.tabs] tab 配置 + * @param {DataListTab[]} [props.tabs] tab 配置 * @param {boolean} [props.isConditionFormLayout] 是否使用条件表单布局 * @param {boolean} [props.isTreeSider] 是否展示树形侧边栏 * @param {Object} [props.treeSiderConfig] 树形侧边栏配置 - * @param {Object} [props.rowSelection] 行选择配置 + * @param {DataListRowSelection} [props.rowSelection] 行选择配置 */ declare function DataListFramework({ listCode, className, layouts, dataSource, isPaginate, isItemOperations, isBatchOperations, batchOperations, itemOperations, itemOperationsAccess, resource, primaryKey, title, itemGridLayout, $setting, tabs, isConditionFormLayout, isTreeSider, treeSiderConfig, rowSelection, }: { listCode?: string; className?: string; - layouts?: any; - dataSource?: Array; + layouts?: DataListLayouts; + dataSource?: Record[]; isPaginate?: boolean; isItemOperations?: boolean; isBatchOperations?: boolean; - batchOperations?: Array; - itemOperations?: Array; - itemOperationsAccess?: Map; + batchOperations?: DataListOperation[]; + itemOperations?: DataListOperation[]; + itemOperationsAccess?: DataListItemOperationsAccess; resource?: string; primaryKey?: string; title?: string; - itemGridLayout?: any; + itemGridLayout?: DataListItemForGridLayout; $setting?: any; - tabs?: Array; + tabs?: DataListTab[]; isConditionFormLayout?: boolean; isTreeSider?: boolean; treeSiderConfig?: any; - rowSelection?: any; + rowSelection?: DataListRowSelection; }): React.JSX.Element; /** @@ -375,20 +502,20 @@ declare function DataListFramework({ listCode, className, layouts, dataSource, i * @param {Object} props * @param {string} [props.listCode] 列表标识 * @param {string} [props.className] 自定义 className - * @param {Object} [props.layouts={}] 子布局组件集合 { sider, filter, toolbar, footer } - * @param {Array} [props.dataSource] 表格数据 - * @param {Array} [props.columns] 表格列配置 + * @param {DataListLayouts} [props.layouts={}] 子布局组件集合 { sider, filter, toolbar, footer } + * @param {Record[]} [props.dataSource] 表格数据 + * @param {DataListColumn[]} [props.columns] 表格列配置 * @param {boolean} [props.isItemOperations] 是否展示行内操作按钮(结合权限计算实际是否展示操作列) * @param {boolean} [props.isBatchOperations] 是否展示批量操作按钮 - * @param {Array} [props.batchOperations] 批量操作按钮配置 - * @param {Array} [props.itemOperations] 行内操作按钮配置 - * @param {Map} [props.itemOperationsAccess] 行内操作权限映射 + * @param {DataListOperation[]} [props.batchOperations] 批量操作按钮配置 + * @param {DataListOperation[]} [props.itemOperations] 行内操作按钮配置 + * @param {DataListItemOperationsAccess} [props.itemOperationsAccess] 行内操作权限映射 * @param {string} [props.resource] 数据嵌套的资源字段名 * @param {string} [props.primaryKey] 主键字段名 * @param {string} [props.title] 列表标题 - * @param {Array} [props.tabs] tab 配置 + * @param {DataListTab[]} [props.tabs] tab 配置 * @param {boolean} [props.isPaginate] 是否分页 - * @param {Object} [props.rowSelection] 行选择配置 + * @param {DataListRowSelection} [props.rowSelection] 行选择配置 * @param {boolean} [props.isTreeSider] 是否展示树形侧边栏 * @param {Object} [props.treeSiderConfig] 树形侧边栏配置 * @param {boolean} [props.isConditionFormLayout] 是否使用条件表单布局 @@ -396,23 +523,24 @@ declare function DataListFramework({ listCode, className, layouts, dataSource, i declare function DataTableFramework({ listCode, className, layouts, dataSource, columns, isItemOperations, isBatchOperations, batchOperations, itemOperations, itemOperationsAccess, resource, primaryKey, title, tabs, isPaginate, rowSelection, isTreeSider, treeSiderConfig, isConditionFormLayout, ...props }: { listCode?: string; className?: string; - layouts?: any; - dataSource?: Array; - columns?: Array; + layouts?: DataListLayouts; + dataSource?: Record[]; + columns?: DataListColumn[]; isItemOperations?: boolean; isBatchOperations?: boolean; - batchOperations?: Array; - itemOperations?: Array; - itemOperationsAccess?: Map; + batchOperations?: DataListOperation[]; + itemOperations?: DataListOperation[]; + itemOperationsAccess?: DataListItemOperationsAccess; resource?: string; primaryKey?: string; title?: string; - tabs?: Array; + tabs?: DataListTab[]; isPaginate?: boolean; - rowSelection?: any; + rowSelection?: DataListRowSelection; isTreeSider?: boolean; treeSiderConfig?: any; isConditionFormLayout?: boolean; }): React.JSX.Element; -export { DataListContent, _default as DataListContext, DataListFilter, DataListFooter, DataListFramework, DataListHelper, DataListSider, DataListTable, DataListToolbar, DataTableFramework, DataList as default, useCellEditableComponents, useColumnsRender, useDataListHelper, useDataSource, useHasOperationColumn, useItemOperationsAccess, useOperationCallback, useStructure }; +export { DataListContent, _default as DataListContext, DataListFilter, DataListFooter, DataListFramework, DataListHelper, DataListSider, DataListTable, DataListToolbar, DataTableFramework, useCellEditableComponents, useColumnsRender, useDataListHelper, useHasOperationColumn, useItemOperationsAccess, useOperationCallback }; +export type { DataListAPI, DataListClassNames, DataListColumn, DataListContextValue, DataListHelperRef, DataListHelperState, DataListItemForGridLayout, DataListItemOperationsAccess, DataListLayouts, DataListOperation, DataListQueryParams, DataListRowSelection, DataListStructure, DataListTab }; diff --git a/data-list.js b/data-list.js index a64469d..5fd7c98 100644 --- a/data-list.js +++ b/data-list.js @@ -1,22 +1,20 @@ -import { w as t, t as e, o as r, r as o, x as i, s as l, q as u, v as n, p as D, y as L, n as p, A as C, z as m, J as b, C as c, F, E as d, I as k, B as w } from "./common/main.js"; +import { w as t, t as e, o, r, x as i, s as l, q as n, v as D, p as L, y as u, n as p, A as C, z as m, F as b, C as F, B as d, E as c } from "./common/main.js"; export { t as DataListContent, e as DataListContext, - r as DataListFilter, - o as DataListFooter, + o as DataListFilter, + r as DataListFooter, i as DataListFramework, l as DataListHelper, - u as DataListSider, - n as DataListTable, - D as DataListToolbar, - L as DataTableFramework, + n as DataListSider, + D as DataListTable, + L as DataListToolbar, + u as DataTableFramework, p as default, C as useCellEditableComponents, m as useColumnsRender, b as useDataListHelper, - c as useDataSource, F as useHasOperationColumn, d as useItemOperationsAccess, - k as useOperationCallback, - w as useStructure + c as useOperationCallback }; diff --git a/grid-layout-form.d.ts b/grid-layout-form.d.ts index 25c8af0..bbf0672 100644 --- a/grid-layout-form.d.ts +++ b/grid-layout-form.d.ts @@ -1,21 +1,12 @@ import React, { CSSProperties } from 'react'; -import { FormInstance, Rule } from 'rc-field-form/es/interface'; -import PropTypes from 'prop-types'; - -/** - * 执行一段 JS 表达式/函数并跟踪其依赖的表单字段,依赖字段变化时自动重新执行 - * @param {string} fn 要执行的表达式源码,为空时直接返回 initialValue - * @param {*} initialValue 初始值/执行出错时的回退值 - * @param {Object} [params] 传给表达式的额外参数 - * @param {Object} [fns] 传给表达式的额外可调用函数 - * @param {*} [basicForm] 表达式里 getFieldValueForBasicForm 取值用的外层表单实例 - * @param {string} [resultType] 结果值的目标类型,用于类型转换 - * @returns {[*, *]} [执行结果(按 resultType 转换后), 执行出错时的错误对象] - */ -declare function useFnRun(fn: string, initialValue: any, params?: any, fns?: any, basicForm?: any, resultType?: string): [any, any]; +import { GridLayoutProps, LayoutField, GridLayoutItem, GridLayoutGroup, FormInstance } from './grid-layout'; +export { FormInstance } from './grid-layout'; +import { Rule } from 'rc-field-form/es/interface'; +export { Rule } from 'rc-field-form/es/interface'; +export { useFnRun } from './grid-layout'; /** useStructure 返回的表单结构数据,请求完成前为 `{ items: [], hides: [] }` */ -interface FormStructure { +interface GridLayoutFormStructure extends GridLayoutProps { /** 记录主键 */ pk?: unknown /** 表单唯一标识 */ @@ -26,38 +17,18 @@ interface FormStructure { resource?: string /** 字段对齐方式 */ align?: unknown - /** 网格列数 */ - cols?: number - /** 网格行高(px) */ - rowHeight?: number - /** 网格水平间距(px) */ - marginX?: number - /** 网格垂直间距(px) */ - marginY?: number - /** 容器主题标识,对应 core.getWidgetComponent 的加载路径 */ - theme?: string - /** 传给 theme 组件的 $setting 配置 */ - themeProps?: Record - /** 字段分组配置 */ - groups?: FormGroup[] /** 字段联动监听字段列表(字段 code 数组) */ listenChangeFields?: string[] /** 字段联动处理函数/表达式,经 func.exec 执行 */ - listenChangeFieldsFunc?: WidgetDecorator + listenChangeFieldsFunc?: GridLayoutFormWidgetDecorator /** 可见字段列表(field.hidden 为 false) */ - items?: FormItem[] + items?: GridLayoutFormItem[] /** 隐藏字段列表(field.hidden 为 true) */ - hides?: FormField[] + hides?: GridLayoutFormField[] } -/** 表单字段定义(对应后端返回的 field 对象) */ -interface FormField { - /** 字段 name,对应 rc-field-form Field.name */ - code?: string - /** 字段值类型(string/number/boolean/array/bool/json 等) */ - type?: string - /** 字段标签 */ - label?: string +/** 表单字段定义(对应后端返回的 field 对象,继承布局通用字段) */ +interface GridLayoutFormField extends LayoutField { /** 是否必填 */ required?: boolean /** 是否隐藏 */ @@ -71,47 +42,42 @@ interface FormField { /** 字段提示文字 */ help?: string /** 校验规则配置 */ - validators?: FieldValidators - /** 透传给控件 $setting 的扩展配置 */ - extras?: Record - /** 字段初始值 */ - initialValue?: unknown - /** 初始值语言(用于特定类型的取值转换) */ - initialValueLanguage?: string - /** 虚拟字段,不参与表单提交 */ - isVirtual?: boolean - /** 控件标识 */ - widget?: string - /** 控件前缀 */ - widgetPrefix?: string + validators?: GridLayoutFormFieldValidators /** 控件切换表达式/函数 */ - widgetDecorator?: WidgetDecorator + widgetDecorator?: GridLayoutFormWidgetDecorator /** 可切换的候选子控件列表 */ - subWidgets?: SubWidget[] + subWidgets?: GridLayoutFormSubWidget[] } /** 表单项(网格布局单元,包含字段定义与布局信息) */ -interface FormItem { - /** 字段定义 */ - field?: FormField - /** 网格 x 坐标 */ - x?: number - /** 网格 y 坐标 */ - y?: number - /** 网格宽度(列数) */ - w?: number - /** 网格高度(行数) */ - h?: number - [key: string]: unknown +interface GridLayoutFormItem extends GridLayoutItem { + /** 表单字段定义(收窄自 GridLayoutItem.field) */ + field?: GridLayoutFormField } -/** 字段分组配置,用于主题多分组渲染 */ -interface FormGroup { - /** 分组唯一标识 */ - key: string - /** 分组显示标签 */ - label?: string - [key: string]: unknown +/** 字段分组配置,用于主题多分组渲染(结构等同于 GridLayoutGroup) */ +type GridLayoutFormGroup = GridLayoutGroup + +/** itemWidgetRender 生成的渲染函数接收的字段 props(即 GridLayoutFormField 字段在运行时的合并结果) */ +type GridLayoutFormItemWidgetProps = GridLayoutFormField & Record + +/** + * itemWidgetRender 中实际渲染的部件组件约定接收的 props + * (由 itemWidgetRender 注入,开发者在实现自定义控件时参考此约定) + */ +interface GridLayoutFormItemWidgetComponentProps { + /** 字段值类型 */ + type?: string + /** rc-field-form 表单实例 */ + rcform?: unknown + /** 外层表单实例,用于字段联动/表达式求值 */ + basicForm?: unknown + /** 传给 antd FormItem 的属性(label/noStyle/style/required/validateStatus/help 等) */ + itemProps?: Record + /** 传给实际输入控件的属性(placeholder/value/onChange 等) */ + fieldProps?: Record + /** 扩展配置,由 defaultProps.extras 的 key 从 props 中拆分而来 */ + $setting?: Record } /** @@ -121,7 +87,7 @@ interface FormGroup { type EnhancedFormInstance = FormInstance & Record /** useFormData / useFormSubmit / useFormAction 的表单配置参数 */ -interface FormSetting { +interface GridLayoutFormSetting { /** 初始化数据的请求地址,默认 `/api/{code}` */ initDataUri?: string /** 初始化数据的请求方法,默认 `'GET'` */ @@ -143,7 +109,7 @@ interface SubmitOptions { } /** widgetDecorator 命中时可切换的候选子控件 */ -interface SubWidget { +interface GridLayoutFormSubWidget { /** 控件标识,规则同 GridLayoutFormWidget.widget */ widget: string /** 控件前缀,默认同外层 widgetPrefix */ @@ -153,7 +119,16 @@ interface SubWidget { } /** 决定控件切换的表达式或函数,经 useFnRun 执行,返回值作为 subWidgets 下标 */ -type WidgetDecorator = string | ((...args: unknown[]) => number | undefined) +type GridLayoutFormWidgetDecorator = string | ((...args: unknown[]) => number | undefined) + +/** + * listenChangeFieldsFunc / validator 动态表达式可调用的表单字段 API; + * 由 GridLayoutForm 和 useRules 通过 func.exec 第三参数注入 + */ +type GridLayoutFormAPI = Pick< + FormInstance, + 'getFieldValue' | 'setFieldValue' | 'setFieldsValue' | 'isFieldTouched' | 'isFieldsTouched' +> /** useFieldArray 的返回值 */ interface UseFieldArrayReturn { @@ -185,7 +160,7 @@ interface UseFieldArrayReturn { * GridLayoutFormWidget 字段校验规则配置 * 对应 useRules 的入参,由 validators prop 传入 */ -interface FieldValidators { +interface GridLayoutFormFieldValidators { /** 校验类型:string 长度校验 / pattern 正则校验 / validator 自定义 */ type?: 'string' | 'pattern' | 'validator' | '' /** 是否必填 */ @@ -205,53 +180,53 @@ interface FieldValidators { /** * 按表单编码(code)拉取表单结构定义,并把字段列表拆分为可见项(items)与隐藏项(hides) * @param {string} code 表单编码,为空时不发起请求 - * @returns {FormStructure} 表单结构数据,请求完成前为 `{ items: [], hides: [] }` + * @returns {GridLayoutFormStructure} 表单结构数据,请求完成前为 `{ items: [], hides: [] }` */ -declare function useStructure(code: string): FormStructure; +declare function useStructure(code: string): GridLayoutFormStructure; /** * 根据字段的校验配置生成 rc-field-form 的 rules 数组;支持必填、长度限制、正则、自定义校验函数 - * @param {FieldValidators} config + * @param {GridLayoutFormFieldValidators} config * @param {string} fieldName 字段名,传给自定义 validator 表达式 * @param {string} fieldType 字段类型('number'|'string'|'array'|'bool'|'json' 等),决定必填校验的 type 及 bool/json 的映射 * @returns {Rule[]} rc-field-form 规则数组 */ -declare function useRules({ max, min, type, message, pattern, required, validator, }: FieldValidators, fieldName: string, fieldType: string): Rule[]; +declare function useRules({ max, min, type, message, pattern, required, validator, }: GridLayoutFormFieldValidators, fieldName: string, fieldType: string): Rule[]; /** * 按主键(primaryKey)拉取表单初始数据;primaryKey 为空时不请求 * @param {string} code 表单编码,用于拼接默认的请求地址 `/api/{code}` * @param {string|number} primaryKey 记录主键,为空时不发起请求 - * @param {FormSetting} [formSetting] 表单配置 + * @param {GridLayoutFormSetting} [formSetting] 表单配置 * @returns {Record|null} 拉取到的表单数据,请求完成前为 `null` */ -declare function useFormData(code: string, primaryKey: string | number, formSetting?: FormSetting): Record | null; +declare function useFormData(code: string, primaryKey: string | number, formSetting?: GridLayoutFormSetting): Record | null; /** * 生成提交表单的回调函数;校验通过后按 `__RESOURCE__` 字段值裁剪数据(若存在),经 opt.serialize 序列化后提交 * @param {string} code 表单编码,用于拼接默认的请求地址 `/api/{code}` * @param {string|number} primaryKey 记录主键,存在时拼到请求地址后面 - * @param {FormSetting} [formSetting] 表单配置 + * @param {GridLayoutFormSetting} [formSetting] 表单配置 * @returns {(form: FormInstance, opt?: SubmitOptions) => Promise<*>} 提交函数 */ -declare function useFormSubmit(code: string, primaryKey: string | number, formSetting?: FormSetting): (form: FormInstance, opt?: SubmitOptions) => Promise; +declare function useFormSubmit(code: string, primaryKey: string | number, formSetting?: GridLayoutFormSetting): (form: FormInstance, opt?: SubmitOptions) => Promise; /** * 组合 useFormData 与 useFormSubmit:数据拉取到后自动回填表单(否则重置),并返回已绑定 form 的提交函数 * @param {FormInstance} form rc-field-form 的表单实例 * @param {string} code 表单编码 * @param {string|number} primaryKey 记录主键 - * @param {FormSetting} [formSetting] 表单配置(透传给 useFormData/useFormSubmit) + * @param {GridLayoutFormSetting} [formSetting] 表单配置(透传给 useFormData/useFormSubmit) * @returns {(opt?: SubmitOptions) => Promise<*>} 已绑定当前 form 的提交函数 */ -declare function useFormAction(form: FormInstance, code: string, primaryKey: string | number, formSetting?: FormSetting): (opt?: SubmitOptions) => Promise; +declare function useFormAction(form: FormInstance, code: string, primaryKey: string | number, formSetting?: GridLayoutFormSetting): (opt?: SubmitOptions) => Promise; /** * 根据 widgetDecorator 表达式动态决定字段实际渲染的控件; * widgetDecorator 执行结果为 subWidgets 的下标时,切换为对应子控件(合并其 props), * 同时暴露 setDisabled/setRequired/getDisabled/getRequired 供 widgetDecorator 内部调用来动态调整禁用/必填状态 * @param {string} itemWidget 默认使用的控件(已归一化的 widget 路径) - * @param {WidgetDecorator} widgetDecorator 决定控件切换的表达式/函数,经 useFnRun 执行,返回值作为 subWidgets 下标 - * @param {SubWidget[]} [subWidgets=[]] 可切换的候选子控件列表 + * @param {GridLayoutFormWidgetDecorator} widgetDecorator 决定控件切换的表达式/函数,经 useFnRun 执行,返回值作为 subWidgets 下标 + * @param {GridLayoutFormSubWidget[]} [subWidgets=[]] 可切换的候选子控件列表 * @param {FormInstance|null} [basicForm={}] 传给 widgetDecorator 执行上下文的表单实例 * @returns {[string, Object]} `[实际渲染的控件路径, 当前生效的控件 props]` */ -declare function useWidgetDecorator(itemWidget: string, widgetDecorator: WidgetDecorator, subWidgets?: SubWidget[], basicForm?: FormInstance | null): [string, any]; +declare function useWidgetDecorator(itemWidget: string, widgetDecorator: GridLayoutFormWidgetDecorator, subWidgets?: GridLayoutFormSubWidget[], basicForm?: FormInstance | null): [string, any]; /** * 把受控的 value/onChange 与 rc-field-form 表单实例双向桥接:外部 value 变化时同步进表单 * (仅当与内部最近一次变更不同,避免循环),表单内部变化时回调 onChange; @@ -289,8 +264,8 @@ declare function useFieldArray(value: any, onChange: (value: any[]) => void): Us * @param {Object} props * @param {string} [props.widget='Input'] 部件标识;以 `@` 或 `blob:` 开头时按原样使用,否则拼接 widgetPrefix 前缀 * @param {string} [props.widgetPrefix='@pkg/ff/grid-layout-forms'] widget 非绝对标识时使用的前缀 - * @param {WidgetDecorator} [props.widgetDecorator] 决定控件切换的表达式/函数,详见 useWidgetDecorator - * @param {SubWidget[]} [props.subWidgets=[]] widgetDecorator 命中时可切换的候选子控件列表 + * @param {GridLayoutFormWidgetDecorator} [props.widgetDecorator] 决定控件切换的表达式/函数,详见 useWidgetDecorator + * @param {GridLayoutFormSubWidget[]} [props.subWidgets=[]] widgetDecorator 命中时可切换的候选子控件列表 * @param {FormInstance|null} [props.basicForm] 表达式求值/字段联动用的外层表单实例 * @param {string} [props.code] 字段 name,对应 rc-field-form Field.name * @param {string} [props.type] 字段值类型(string/number/boolean 等),用于取值归一化 @@ -300,7 +275,7 @@ declare function useFieldArray(value: any, onChange: (value: any[]) => void): Us * @param {boolean} [props.noStyle] 是否隐藏 FormItem 的 label/border 等样式 * @param {Object} [props.style] FormItem 根节点行内样式 * @param {string} [props.help] 字段提示文字(tooltip) - * @param {FieldValidators} [props.validators] 校验规则配置,合并到 rc-field-form rules + * @param {GridLayoutFormFieldValidators} [props.validators] 校验规则配置,合并到 rc-field-form rules * @param {Object} [props.extras] 透传给 ItemWidget.$setting 的扩展配置(key 由 defaultProps.extras 定义) * @param {*} [props.initialValue] 字段初始值 * @param {string} [props.initialValueLanguage] 初始值语言(用于特定类型的取值转换) @@ -310,8 +285,8 @@ declare function useFieldArray(value: any, onChange: (value: any[]) => void): Us declare function GridLayoutFormWidget({ widget, widgetPrefix, widgetDecorator, subWidgets, basicForm, ...props }: { widget?: string; widgetPrefix?: string; - widgetDecorator?: WidgetDecorator; - subWidgets?: SubWidget[]; + widgetDecorator?: GridLayoutFormWidgetDecorator; + subWidgets?: GridLayoutFormSubWidget[]; basicForm?: FormInstance | null; code?: string; type?: string; @@ -321,7 +296,7 @@ declare function GridLayoutFormWidget({ widget, widgetPrefix, widgetDecorator, s noStyle?: boolean; style?: any; help?: string; - validators?: FieldValidators; + validators?: GridLayoutFormFieldValidators; extras?: any; initialValue?: any; initialValueLanguage?: string; @@ -360,17 +335,17 @@ declare function GridLayoutFormHelper({ $setting, $close, extras, code, primaryK * @param {number} [props.rowHeight=16] 栅格行高(px) * @param {[number, number]} [props.itemMargin=[8, 16]] 字段项间距 [横向, 纵向](px) * @param {[number, number]} [props.containerPadding=[0, 0]] 容器内边距 [纵向, 横向](px) - * @param {FormItem[]} [props.fields=[]] 可见字段配置列表(位置、尺寸、部件类型等) - * @param {FormField[]} [props.hides=[]] 隐藏字段配置列表,按 initialValueLanguage 求值后写入对应字段 + * @param {GridLayoutFormItem[]} [props.fields=[]] 可见字段配置列表(位置、尺寸、部件类型等) + * @param {GridLayoutFormField[]} [props.hides=[]] 隐藏字段配置列表,按 initialValueLanguage 求值后写入对应字段 * @param {string|number} [props.primaryKey=0] 记录主键,注入为 `__PRIMARY_KEY__` 字段值 * @param {Record} [props.formProps={}] 注入为 `__PROPS__` 字段值的表单级参数 - * @param {FormItem[]} [props.formFields=[]] 额外注入的表单字段(与 formProps/primaryKey 一并作为初始 fields) + * @param {GridLayoutFormItem[]} [props.formFields=[]] 额外注入的表单字段(与 formProps/primaryKey 一并作为初始 fields) * @param {string[]} [props.listenChangeFields] 触发联动表达式重新求值的字段列表 * @param {*} [props.listenChangeFieldsFunc] 字段值变化时执行的联动表达式(经 func.exec 执行) * @param {(changedValues: Object, allValues: Object) => void} [props.onValuesChange] 表单值变化回调,先于联动表达式执行 * @param {string} [props.theme] 主题组件标识,指定时通过 GridLayoutFramework 渲染主题外壳 * @param {Object} [props.themeProps={}] 传给主题组件的额外参数 - * @param {FormGroup[]} [props.groups=[{key:'default',label:'默认'}]] 字段分组配置,用于主题多分组渲染 + * @param {GridLayoutFormGroup[]} [props.groups=[{key:'default',label:'默认'}]] 字段分组配置,用于主题多分组渲染 * @param {ReactNode} [props.children] 附加渲染在字段项之后的内容 */ declare function GridLayoutForm({ name, form: initForm, basicForm, style, className, cols, rowHeight, itemMargin, containerPadding, fields, hides, primaryKey, formProps, formFields, listenChangeFields, listenChangeFieldsFunc, onValuesChange, theme, themeProps, groups, children, ...props }: { @@ -383,29 +358,19 @@ declare function GridLayoutForm({ name, form: initForm, basicForm, style, classN rowHeight?: number; itemMargin?: [number, number]; containerPadding?: [number, number]; - fields?: FormItem[]; - hides?: FormField[]; + fields?: GridLayoutFormItem[]; + hides?: GridLayoutFormField[]; primaryKey?: string | number; formProps?: Record; - formFields?: FormItem[]; + formFields?: GridLayoutFormItem[]; listenChangeFields?: string[]; listenChangeFieldsFunc?: any; onValuesChange?: (changedValues: any, allValues: any) => void; theme?: string; themeProps?: any; - groups?: FormGroup[]; + groups?: GridLayoutFormGroup[]; children?: React.ReactNode; }): React.JSX.Element; -declare namespace GridLayoutForm { - namespace propTypes { - let fields: PropTypes.Requireable; - let hides: PropTypes.Requireable; - } -} -declare const _default: ({ code, isPreview, ...props }: { - [x: string]: any; - code: any; - isPreview?: boolean; -}) => React.JSX.Element; -export { GridLayoutForm, GridLayoutFormHelper, GridLayoutFormWidget, _default as default, useFieldArray, useFnRun, useFormAction, useFormData, useFormSubmit, useMergedFormValuesChange, useRules, useStructure, useWidgetDecorator }; +export { GridLayoutForm, GridLayoutFormHelper, GridLayoutFormWidget, useFieldArray, useFormAction, useFormData, useFormSubmit, useMergedFormValuesChange, useRules, useStructure, useWidgetDecorator }; +export type { EnhancedFormInstance, GridLayoutFormAPI, GridLayoutFormField, GridLayoutFormFieldValidators, GridLayoutFormGroup, GridLayoutFormItem, GridLayoutFormItemWidgetComponentProps, GridLayoutFormItemWidgetProps, GridLayoutFormSetting, GridLayoutFormStructure, GridLayoutFormSubWidget, GridLayoutFormWidgetDecorator, SubmitOptions, UseFieldArrayReturn }; diff --git a/grid-layout-form.js b/grid-layout-form.js index 72a784a..510620a 100644 --- a/grid-layout-form.js +++ b/grid-layout-form.js @@ -1,4 +1,4 @@ -import { aa as s, ac as r, ab as u, a9 as o, ak as t, m, ah as d, af as i, ag as F, aj as g, ae as l, ad as c, ai as n } from "./common/main.js"; +import { a8 as s, aa as r, a9 as u, a7 as o, ai as t, m, af as d, ad as i, ae as F, ah as g, ac as l, ab as c, ag as n } from "./common/main.js"; export { s as GridLayoutForm, r as GridLayoutFormHelper, diff --git a/grid-layout.d.ts b/grid-layout.d.ts index 1d7f3da..246fa19 100644 --- a/grid-layout.d.ts +++ b/grid-layout.d.ts @@ -1,24 +1,168 @@ +import { FormInstance } from 'rc-field-form/es/interface'; +export { FormInstance } from 'rc-field-form/es/interface'; import React from 'react'; +/** 布局分组配置,用于主题多分组渲染 */ +interface GridLayoutGroup { + /** 分组唯一标识 */ + key: string + /** 分组显示标签 */ + label?: string + [key: string]: unknown +} + +/** 字段项盒模型配置(margin / padding / align / autoHeight) */ +interface BoxStyle { + /** 是否按内容自适应高度(不再固定跨行) */ + autoHeight?: boolean + /** 对齐方式,写入 `--grid-layout-box-align-items` */ + alignItems?: string + /** 主轴对齐方式,写入 `--grid-layout-box-justify-content` */ + justifyContent?: string + /** 外边距 - 上(px) */ + marginTop?: number + /** 外边距 - 右(px) */ + marginRight?: number + /** 外边距 - 下(px) */ + marginBottom?: number + /** 外边距 - 左(px) */ + marginLeft?: number + /** 内边距 - 上(px) */ + paddingTop?: number + /** 内边距 - 右(px) */ + paddingRight?: number + /** 内边距 - 下(px) */ + paddingBottom?: number + /** 内边距 - 左(px) */ + paddingLeft?: number +} + +/** + * 字段内容配置基础类型(ff-grid-layout 与 ff-grid-layout-form 共用) + */ +interface LayoutField { + /** 字段标识,对应 rc-field-form 的 name */ + code?: string + /** 字段标签 */ + label?: string + /** 传给控件 $setting 的扩展配置 key 集合(key 存在时从 props 拆分为 extraProps) */ + extras?: Record + /** 是否虚拟字段,为 true 时不绑定表单字段(name 传 null) */ + isVirtual?: boolean + /** 初始值,或 initialValueLanguage 为 'javascript' 时的表达式源码 */ + initialValue?: unknown + /** 初始值类型,'javascript' 时把 initialValue 当表达式执行 */ + initialValueLanguage?: string + /** 字段值目标类型(string / number / boolean / array 等),用于 toPrimitive 转换 */ + type?: string + /** 部件标识;以 `@` 或 `blob:` 开头时按原样使用,否则拼接 widgetPrefix */ + widget?: string + /** widget 非绝对标识时使用的前缀 */ + widgetPrefix?: string + /** 盒模型配置;getNormalizeFields 渲染时从 field 中提取,不传给 ItemWidget */ + boxStyle?: BoxStyle + [key: string]: unknown +} + +/** + * ff-grid-layout 字段内容配置(在 LayoutField 基础上增加展示值转换配置) + */ +interface GridLayoutField extends LayoutField { + /** 展示值转换表达式(交给 DataConverter 处理) */ + convertJs?: unknown + /** convertJs 表达式的附加配置 */ + convertJsSetting?: unknown +} + +/** 布局字段项(网格坐标 + 字段内容),对应 getNormalizeFields 入参列表的每一项 */ +interface GridLayoutItem { + /** 字段唯一标识,用作 React key;优先于数组下标 */ + i?: unknown + /** 网格 x 坐标(起始列,0-indexed) */ + x?: number + /** 网格 y 坐标(起始行,0-indexed) */ + y?: number + /** 网格宽度(列数) */ + w?: number + /** 网格高度(行数) */ + h?: number + /** 所属分组的 key,缺省时归入 'default' 分组 */ + group?: string + /** 字段内容配置;field.boxStyle 决定盒模型,其余字段传给 ItemWidget */ + field?: GridLayoutField + [key: string]: unknown +} + +/** GridLayout 组件的布局配置参数(不含 form/DOM 相关 props) */ +interface GridLayoutProps { + /** 栅格列数,默认 12 */ + cols?: number + /** 栅格行高(px),默认 21 */ + rowHeight?: number + /** 容器内边距 [纵向, 横向](px),默认 [0, 0] */ + containerPadding?: [number, number] + /** 字段项间距 [纵向, 横向](px),默认 [4, 0] */ + itemMargin?: [number, number] + /** 布局字段配置列表 */ + fields?: GridLayoutItem[] + /** 字段分组配置,用于主题多分组渲染 */ + groups?: GridLayoutGroup[] + /** 主题组件标识,通过 core.getWidgetComponent 异步加载 */ + theme?: string + /** 传给主题组件的 $setting 配置 */ + themeProps?: Record +} + +/** useStructure 返回的布局结构数据,请求完成前为 `{ items: [] }` */ +interface GridLayoutStructure extends GridLayoutProps { + /** 布局唯一标识 */ + uuid?: string + /** 布局编码 */ + code?: string + /** 布局名称 */ + name?: string + /** 关联资源标识 */ + resource?: string + /** 记录主键 */ + primaryKey?: unknown + /** 布局字段配置列表(API 返回名,组件侧对应 GridLayoutProps.fields) */ + items?: GridLayoutItem[] +} + +/** useField 返回值:[经 convertJs 转换后的展示值(未配置时等于原值), 原始字段值] */ +/** + * useFnRun / useField 内 func.exec 脚本上下文中可调用的字段读取 API; + * 由 useFnRun 注入,包含当前表单与外层(basicForm)表单的只读接口 + */ +type GridLayoutFieldAPI = Pick & { + /** 从外层(basicForm)表单获取字段值;无 basicForm 时返回 null */ + getFieldValueForBasicForm: (name: Parameters[0]) => unknown +} + +type UseFieldReturn = [displayValue: unknown, rawValue: unknown] + +/** useFnRun 返回值:[按 resultType 转换后的执行结果, 执行出错时的错误对象(null 表示无错误)] */ +type UseFnRunReturn = [result: unknown, error: unknown] + /** rc-field-form 内部钩子的注册标识 */ declare const HOOK_MARK: "RC_FORM_INTERNAL_HOOKS"; /** * 按布局 code 拉取布局结构定义(字段、主题、栅格设置等),code 变化时重新请求 * @param {string} code 布局的唯一编码 - * @returns {Object} 布局结构数据,初始为 `{ items: [] }` + * @returns {GridLayoutStructure} 布局结构数据,请求完成前为 `{ items: [] }` */ -declare function useStructure(code: string): any; +declare function useStructure(code: string): GridLayoutStructure; /** * 关联表单字段值,支持初始值表达式求值、watch 联动更新以及经 DataConverter 转换后的展示值 - * @param {string} name 字段名(rc-field-form 的字段路径) + * @param {string} name 字段名(rc-field-form 的字段路径) * @param {Object} setting 字段取值相关配置 - * @param {*} [setting.initialValue] 初始值,或语言为 javascript 时的表达式源码 - * @param {string} [setting.initialValueLanguage] 初始值类型,'javascript' 时把 initialValue 当表达式执行 - * @param {*} [setting.convertJs] 用于生成展示值的转换表达式(交给 DataConverter 处理) + * @param {*} [setting.initialValue] 初始值,或语言为 javascript 时的表达式源码 + * @param {string} [setting.initialValueLanguage] 初始值类型,'javascript' 时把 initialValue 当表达式执行 + * @param {*} [setting.convertJs] 用于生成展示值的转换表达式(交给 DataConverter 处理) * @param {*} [setting.convertJsSetting] convertJs 表达式的附加配置 - * @param {string} [setting.type='string'] 字段值的目标类型,用于类型转换 + * @param {string} [setting.type='string'] 字段值的目标类型,用于类型转换 * @param {*} [pContext] 表达式里 getFieldValueForBasicForm 取值用的外层表单实例 - * @returns {[*, *]} [经 convertJs 转换后的展示值(未配置时等于原值), 原始字段值] + * @returns {UseFieldReturn} */ declare function useField(name: string, { initialValue, initialValueLanguage, convertJs, convertJsSetting, type, }: { initialValue?: any; @@ -26,39 +170,39 @@ declare function useField(name: string, { initialValue, initialValueLanguage, co convertJs?: any; convertJsSetting?: any; type?: string; -}, pContext?: any): [any, any]; +}, pContext?: any): UseFieldReturn; /** * 按 (y, x) 排序将字段列表归一化为渲染项列表(每项已用给定的 ItemWidget 渲染成元素) - * @param {Array} fields 字段配置列表 + * @param {GridLayoutItem[]} fields 字段配置列表 * @param {Function} ItemWidget 用于渲染每个字段的组件 * @param {*} [basicForm] 传给每个字段渲染项的外层表单实例 - * @returns {Array} 已排序并渲染完成的元素列表 + * @returns {ReactNode[]} 已排序并渲染完成的元素列表 */ -declare function useGridLayoutFields(fields: any[], ItemWidget: Function, basicForm?: any): any[]; +declare function useGridLayoutFields(fields: GridLayoutItem[], ItemWidget: Function, basicForm?: any): React.ReactNode[]; /** * 执行一段 JS 表达式/函数并跟踪其依赖的表单字段,依赖字段变化时自动重新执行 * @param {string} fn 要执行的表达式源码,为空时直接返回 initialValue * @param {*} initialValue 初始值/执行出错时的回退值 * @param {Object} [params] 传给表达式的额外参数 - * @param {Object} [fns] 传给表达式的额外可调用函数 + * @param {Partial} [fns] 传给表达式的额外可调用函数(useFnRun 会在此基础上注入 getFieldValue/isFieldTouched 等) * @param {*} [basicForm] 表达式里 getFieldValueForBasicForm 取值用的外层表单实例 * @param {string} [resultType] 结果值的目标类型,用于类型转换 - * @returns {[*, *]} [执行结果(按 resultType 转换后), 执行出错时的错误对象] + * @returns {UseFnRunReturn} */ -declare function useFnRun(fn: string, initialValue: any, params?: any, fns?: any, basicForm?: any, resultType?: string): [any, any]; +declare function useFnRun(fn: string, initialValue: any, params?: any, fns?: Partial, basicForm?: any, resultType?: string): UseFnRunReturn; /** * 按 widget 标识异步加载并渲染对应的部件组件,加载完成前不渲染任何内容; * 加载出错时渲染错误信息文本 * @param {Object} props - * @param {string} [props.widget] 部件标识;以 `@` 或 `blob:` 开头时按原样使用,否则拼接 widgetPrefix 前缀 + * @param {string} [props.widget] 部件标识;以 `@` 或 `blob:` 开头时按原样使用,否则拼接 widgetPrefix 前缀 * @param {string} [props.widgetPrefix='@pkg/ff/grid-layouts'] widget 非绝对标识时使用的前缀 - * @param {*} [props.basicForm] 表达式求值/字段联动用的外层表单实例 + * @param {FormInstance} [props.basicForm] 表达式求值/字段联动用的外层表单实例 */ declare function GridLayoutWidget({ widget, widgetPrefix, basicForm, ...props }: { widget?: string; widgetPrefix?: string; - basicForm?: any; + basicForm?: FormInstance; }): undefined; /** @@ -67,9 +211,9 @@ declare function GridLayoutWidget({ widget, widgetPrefix, basicForm, ...props }: * @param {Object} props * @param {string} [props.theme] 主题组件标识,通过 core.getWidgetComponent 加载 * @param {*} [props.basicForm] 传给主题组件及各分组内容的外层表单实例 - * @param {Array} [props.items=[{key:'default',label:'默认'}]] 分组配置列表 - * @param {Array} [props.fields=[]] 全部布局字段,按分组 key 过滤后分给对应 items 项 - * @param {Function} [props.itemRender] 生成单个分组渲染内容的函数,签名为 (item, fields, children) + * @param {GridLayoutGroup[]} [props.items=[{key:'default',label:'默认'}]] 分组配置列表 + * @param {GridLayoutItem[]} [props.fields=[]] 全部布局字段,按分组 key 过滤后分给对应 items 项 + * @param {(item: GridLayoutGroup, fields: GridLayoutItem[], children: *) => *} [props.itemRender] 生成单个分组渲染内容的函数 * @param {Array} [props.chunks=[]] 额外附加在 items 之后、不参与过滤的分组项 * @param {*} [props.children] 仅附加给 key 为 'default' 的分组的内容 * @param {Object} [props.$setting={}] 传给主题组件的基础设置,会与 themeSetting 合并 @@ -77,9 +221,9 @@ declare function GridLayoutWidget({ widget, widgetPrefix, basicForm, ...props }: declare function GridLayoutFramework({ theme, basicForm, items, fields, itemRender, chunks, children, $setting, ...themeSetting }: { theme?: string; basicForm?: any; - items?: any[]; - fields?: any[]; - itemRender?: Function; + items?: GridLayoutGroup[]; + fields?: GridLayoutItem[]; + itemRender?: (item: GridLayoutGroup, fields: GridLayoutItem[], children: any) => any; chunks?: any[]; children?: any; $setting?: any; @@ -90,8 +234,8 @@ declare function GridLayoutFramework({ theme, basicForm, items, fields, itemRend * 指定 theme 时委托 GridLayoutFramework 渲染主题外壳,否则直接渲染默认分组 * @param {Object} props * @param {string} [props.name] 表单字段容器名(即 __LAYOUT_KEY__ 语义,由 GridLayoutHoc 传入) - * @param {*} [props.form] 外部传入的 rc-field-form 表单实例,不传时内部自建 - * @param {*} [props.basicForm] 表达式求值/字段联动用的外层表单实例 + * @param {FormInstance} [props.form] 外部传入的 rc-field-form 表单实例,不传时内部自建 + * @param {FormInstance} [props.basicForm] 表达式求值/字段联动用的外层表单实例 * @param {Object} [props.style] 容器行内样式 * @param {string} [props.className] 容器额外 class 名 * @param {number} [props.cols=12] 栅格列数 @@ -100,17 +244,17 @@ declare function GridLayoutFramework({ theme, basicForm, items, fields, itemRend * @param {[number, number]} [props.itemMargin=[4, 0]] 字段项间距 [纵向, 横向](px) * @param {Object} [props.formProps={}] 注入为 `__PROPS__` 字段值的表单级参数 * @param {Array} [props.formFields=[]] 额外注入的表单字段(与 formProps 一并作为初始 fields) - * @param {Array} [props.fields=[]] 布局字段配置列表(位置、尺寸、部件类型等) + * @param {GridLayoutItem[]} [props.fields=[]] 布局字段配置列表(位置、尺寸、部件类型等) * @param {Object} [props.data] 初始化/回填表单的数据 - * @param {string} [props.theme] 主题组件标识,指定时通过 GridLayoutFramework 渲染主题外壳 + * @param {string} [props.theme] 主题组件标识,指定时通过 GridLayoutFramework 渲染主题外壳 * @param {Object} [props.themeProps={}] 传给主题组件的额外参数 - * @param {Array} [props.groups=[{key:'default',label:'默认'}]] 字段分组配置,用于主题多分组渲染 + * @param {GridLayoutGroup[]} [props.groups=[{key:'default',label:'默认'}]] 字段分组配置,用于主题多分组渲染 * @param {*} [props.children] 附加渲染在字段项之后的内容 */ declare function GridLayout({ name, form: initForm, basicForm, style, className, cols, rowHeight, containerPadding, itemMargin, formProps, formFields, fields, data, theme, themeProps, groups, children, ...props }: { name?: string; - form?: any; - basicForm?: any; + form?: FormInstance; + basicForm?: FormInstance; style?: any; className?: string; cols?: number; @@ -119,17 +263,13 @@ declare function GridLayout({ name, form: initForm, basicForm, style, className, itemMargin?: [number, number]; formProps?: any; formFields?: any[]; - fields?: any[]; + fields?: GridLayoutItem[]; data?: any; theme?: string; themeProps?: any; - groups?: any[]; + groups?: GridLayoutGroup[]; children?: any; }): React.JSX.Element; -declare const _default: ({ code, data, ...props }: { - [x: string]: any; - code: any; - data: any; -}) => React.JSX.Element; -export { GridLayout, GridLayoutFramework, GridLayoutWidget, HOOK_MARK, _default as default, useField, useFnRun, useGridLayoutFields, useStructure }; +export { GridLayout, GridLayoutFramework, GridLayoutWidget, HOOK_MARK, useField, useFnRun, useGridLayoutFields, useStructure }; +export type { BoxStyle, GridLayoutField, GridLayoutFieldAPI, GridLayoutGroup, GridLayoutItem, GridLayoutProps, GridLayoutStructure, LayoutField, UseFieldReturn, UseFnRunReturn }; diff --git a/grid-layout/utils.d.ts b/grid-layout/utils.d.ts index 37d6876..6d91b73 100644 --- a/grid-layout/utils.d.ts +++ b/grid-layout/utils.d.ts @@ -1,46 +1,25 @@ +import { GridLayoutItem, BoxStyle } from '../grid-layout'; + /** * 将布局字段配置按 (y, x) 排序并渲染为定位好的字段项元素列表 - * @param {Array} [fields=[]] 布局字段配置列表,每项包含 i/x/y/w/h 及 field(可含 boxStyle) + * @param {GridLayoutItem[]} [fields=[]] 布局字段配置列表,每项包含 i/x/y/w/h 及 field(可含 boxStyle) * @param {Function} ItemWidget 用于渲染每个字段内容的组件 * @param {*} [basicForm] 传给每个字段项的外层表单实例 * @returns {Array} 已定位、可直接渲染的字段项元素列表 */ -declare function getNormalizeFields(fields?: any[], ItemWidget: Function, basicForm?: any): any[]; +declare function getNormalizeFields(fields?: GridLayoutItem[], ItemWidget: Function, basicForm?: any): any[]; /** - * 根据栅格坐标/尺寸及盒模型配置,生成布局字段项的行内样式(以 CSS 自定义属性表达) + * 根据栅格坐标/尺寸及盒模型配置,生成布局字段项的行内样式(以 CSS 自定义属性表达) * @param {number} x 栅格列坐标 * @param {number} y 栅格行坐标 - * @param {number} w 栅格宽度(列数) - * @param {number} h 栅格高度(行数) - * @param {Object} [boxStyle={}] 盒模型配置 - * @param {boolean} [boxStyle.autoHeight] 是否按内容自适应高度(不再固定跨行) - * @param {string} [boxStyle.alignItems] 对齐方式,写入 `--grid-layout-box-align-items` - * @param {string} [boxStyle.justifyContent] 主轴对齐方式,写入 `--grid-layout-box-justify-content` - * @param {number} [boxStyle.marginTop] 外边距-上(px) - * @param {number} [boxStyle.marginRight] 外边距-右(px) - * @param {number} [boxStyle.marginBottom] 外边距-下(px) - * @param {number} [boxStyle.marginLeft] 外边距-左(px) - * @param {number} [boxStyle.paddingTop] 内边距-上(px) - * @param {number} [boxStyle.paddingRight] 内边距-右(px) - * @param {number} [boxStyle.paddingBottom] 内边距-下(px) - * @param {number} [boxStyle.paddingLeft] 内边距-左(px) - * @param {number} [height=0] 显式高度(px),传入时覆盖 autoHeight 计算出的 height + * @param {number} w 栅格宽度(列数) + * @param {number} h 栅格高度(行数) + * @param {BoxStyle} [boxStyle={}] 盒模型配置 + * @param {number} [height=0] 显式高度(px),传入时覆盖 autoHeight 计算出的 height * @returns {Object} 可直接用作 React style 的样式对象 */ -declare function getBoxStyle(x: number, y: number, w: number, h: number, boxStyle?: { - autoHeight?: boolean; - alignItems?: string; - justifyContent?: string; - marginTop?: number; - marginRight?: number; - marginBottom?: number; - marginLeft?: number; - paddingTop?: number; - paddingRight?: number; - paddingBottom?: number; - paddingLeft?: number; -}, height?: number): any; +declare function getBoxStyle(x: number, y: number, w: number, h: number, boxStyle?: BoxStyle, height?: number): any; /** * 将部件名归一化为完整标识;以 `@` 或 `blob:` 开头时按原样返回,否则拼接 widgetPrefix 前缀 * @param {string} [widget='Text'] 部件名 diff --git a/hooks.d.ts b/hooks.d.ts index 9b94f3d..c9d3628 100644 --- a/hooks.d.ts +++ b/hooks.d.ts @@ -1,3 +1,4 @@ +import { WidgetType, WidgetContainerProps } from './button'; export { default as useMergedState } from 'rc-util/lib/hooks/useMergedState'; export { default as useEvent } from 'rc-util/lib/hooks/useEvent'; @@ -57,4 +58,114 @@ declare function useWidgetPropsUpdater($props: any, setLocal: (local: any) => vo */ declare function useWidgetProps($props: any, data?: any, fns?: any, deps?: any[]): [any, (patch: any) => void, any]; +// ===== 用户数据结构(复用类型,JSDoc 无法跨文件引用,放 .d.ts) ===== + +interface UserRoleBinding { + user_uuid: string + role_uuid: string + created_at: string + updated_at: string + created_user: string + owned_user: string +} + +interface UserInfo { + uuid: string + username: string + nickname: string + email: string + last_login_ip: string + is_active: 0 | 1 + UserRole: UserRoleBinding[] + [key: string]: unknown +} + + +interface MenuItem { + /** 菜单唯一标识 */ + uuid: string + /** 菜单显示名称 */ + name: string + /** 图标 class 名 */ + icon: string + /** 行为目标(组件标识 / 路由 uuid 等),含义随 widgetType 而定 */ + widget: string + /** 行为类型 */ + widgetType: WidgetType + /** 传给目标组件的 props 映射配置 */ + widgetProps: Record + /** 传给目标组件的 $setting 配置 */ + widgetSetting: Record + /** 弹窗容器配置 */ + widgetContainerSetting: WidgetContainerProps + /** 子菜单 */ + children?: MenuItem[] +} + +interface RouteItem { + /** 路由唯一标识 */ + uuid: string + /** 路由名称 */ + name: string + /** react-router path,支持动态参数(如 /page/:id) */ + uri: string + /** 是否为布局路由(外层 layout,不直接渲染页面内容) */ + isLayout: boolean + /** 是否需要登录才能访问 */ + isLogin: boolean + /** 是否为手机端专属路由 */ + isPhone: boolean + /** 路由类型 */ + type: Exclude + /** 是否精确匹配路径 */ + exact: boolean + /** widget 标识(等同于 ButtonProps.widget),经 core.getWidgetComponent 加载 */ + component: string + /** 传给页面组件的 props 映射配置 */ + widgetProps: Record + /** 传给页面组件的 $setting 配置 */ + widgetSetting: Record + /** 弹窗容器配置 */ + widgetContainerSetting: WidgetContainerProps + /** 附加配置(如 layout 标识等) */ + extra?: Record +} + +// ===== http — Proxy 模式产生交叉类型,JSDoc 无法表达 ===== + +/** 每次请求自动附加的请求头 */ +interface HttpHeaders { + /** 客户端平台标识,固定为 'web' */ + Platform: string + /** SaaS 租户标识,单租户时为 null */ + SaaS: string | null + /** JWT Bearer token,未登录时为 undefined */ + Authorization: string | undefined +} + +// ===== func — ff-worker-pipe 无类型文件,显式声明 ===== + +/** + * 基于 Worker 的表达式执行引擎单例; + * exec 在独立 Worker 上下文中求值一段 JS 表达式/源码 + */ +interface WorkerPipeInstance { + /** + * 在 Worker 上下文中执行一段 JS 表达式 + * @param expression 要执行的表达式字符串 + * @param args 传给表达式的参数(可在表达式内作为第一个参数使用) + * @param fns 注入到表达式执行作用域的额外可调用函数 + * @param session 会话标识;相同 session 共享 Worker 侧工作区(this) + */ + exec: ( + expression: string, + args?: Record, + fns?: Record, + session?: string + ) => Promise + /** 清除指定 session 的 Worker 侧工作区 */ + clear: (session: string) => void +} + export { useDeepEffect, useDeepEqualEffect, useOptions, useStateWithCallback, useSubscribeRequest, useUpdate, useWidgetProps, useWidgetPropsUpdater }; +export type { HttpHeaders, MenuItem, RouteItem, UserInfo, UserRoleBinding, WorkerPipeInstance }; diff --git a/hooks.js b/hooks.js index fb7d1d8..fbcdecb 100644 --- a/hooks.js +++ b/hooks.js @@ -2,7 +2,7 @@ import "lodash"; import "rc-field-form"; import "react"; import "react-use"; -import { a4 as u, a3 as o, a5 as i, a2 as f, a6 as m, a1 as d, a8 as c, a7 as l } from "./common/main.js"; +import { a2 as u, a1 as o, a3 as i, a0 as f, a4 as m, $ as d, a6 as c, a5 as l } from "./common/main.js"; import { default as b } from "rc-util/lib/hooks/useMergedState"; import { a as x } from "./common/vendor.js"; export { diff --git a/iconfont.d.ts b/iconfont.d.ts index fdaa1df..476bd40 100644 --- a/iconfont.d.ts +++ b/iconfont.d.ts @@ -1,5 +1,4 @@ import React from 'react'; -import PropTypes from 'prop-types'; /** * 渲染一个 iconfont symbol 图标(依赖 Iconfont.init 注入的 SVG symbol 脚本) @@ -7,18 +6,21 @@ import PropTypes from 'prop-types'; * @param {string} [props.className] 额外的 class 名 * @param {string} props.type 图标名,对应 svg symbol 的 id * @param {Object} [props.style] 行内样式 + * @param {number} [props.rotate] 旋转角度(deg) + * @param {boolean} [props.spin] 是否开启旋转动画 + * @param {string} [props.twoToneColor] 双色图标的第二色 + * @param {boolean} [props.compact] 是否紧凑模式(去除默认间距) */ declare function Iconfont({ className, type, style, rotate, spin, twoToneColor, compact, ...props }: { className?: string; type: string; style?: any; + rotate?: number; + spin?: boolean; + twoToneColor?: string; + compact?: boolean; }): React.JSX.Element; declare namespace Iconfont { - export namespace propTypes { - let className: PropTypes.Requireable; - let type: PropTypes.Validator; - let style: PropTypes.Requireable; - } export { createScriptUrlElements as init }; } diff --git a/iconfont.js b/iconfont.js index 4f67d43..d492dfb 100644 --- a/iconfont.js +++ b/iconfont.js @@ -1,8 +1,7 @@ import "react/jsx-runtime"; import "react"; -import "prop-types"; import "classnames"; -import { al as a } from "./common/main.js"; +import { aj as a } from "./common/main.js"; export { a as default }; diff --git a/index.d.ts b/index.d.ts index 7c64188..04c9c98 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,75 +1,2 @@ -import * as axios from 'axios'; -import Request from 'ff-request'; -import MockAdapter from 'axios-mock-adapter'; -import React from 'react'; - -declare const _default$3: any; - -declare const _default$2: Http & Request; - -/** - * 应用统一的 HTTP 客户端单例;自身只实现 init/driver/headers/mock/unmock, - * 其余属性通过 Proxy 代理到内部的 ff-request 实例(HttpRequest), - * 所以 get/post/del 等请求方法可以直接在这个单例上调用 - */ -declare class Http { - static "__#private@#instance": any; - static "__#private@#core": any; - /** @returns {Http & Request} 单例实例 */ - static getInstance: () => Http & Request; - appUrl: string; - /** - * 初始化(设置请求 baseURL/超时,并初始化内部 ff-request 实例) - * @param {string} appKey - * @param {string} appSecret - * @param {string} appUrl 接口请求的 baseURL - */ - init(appKey: string, appSecret: string, appUrl: string): void; - get driver(): axios.AxiosStatic; - get headers(): Readonly<{ - Platform: "web"; - SaaS: string; - Authorization: `Bearer ${string} `; - }>; - /** - * 开启请求 mock(基于 axios-mock-adapter),未匹配的请求会透传到真实接口 - * @param {Object} [opt] 传给 MockAdapter 的选项 - * @returns {MockAdapter} mock 适配器实例,用于注册具体的 mock 规则 - */ - mock(opt?: any): MockAdapter; - /** 关闭并清除 mock */ - unmock(): void; - #private; -} - -declare class Cache { - constructor(target: any, fn: any); - get: (...args: any[]) => Promise; - #private; -} - -declare const _default$1: any; - -declare const pipe: any; - -declare const _default: any; - -declare const AppContext: React.Context<{ - user: {}; - initUser: () => void; - initUserComplete: boolean; -}>; -declare const AppGlobalParamsContext: React.Context<{ - set: () => void; - get: () => void; - assign: () => void; - currentRoute: () => void; -}>; - -/** - * 判断是否是 React 组件, 大写字母开头的函数则判断为组件 - */ -declare function isReactComponent(component: any): boolean; -declare function insertStyle(css: any, id: any): any; - -export { AppContext, AppGlobalParamsContext, Cache as cache, _default$1 as configure, _default$3 as default, pipe as func, _default$2 as http, insertStyle, isReactComponent, _default as route }; +export * from './index'; +export { default } from './index'; diff --git a/index.js b/index.js index b686eb0..e19e2d5 100644 --- a/index.js +++ b/index.js @@ -1,4 +1,4 @@ -import { aF as t, aG as e, aB as o, aC as n, ax as p, aD as r, aA as c, az as f, ay as l, aE as u } from "./common/main.js"; +import { aD as t, aE as e, az as o, aA as n, av as p, aB as r, ay as c, ax as f, aw as l, aC as u } from "./common/main.js"; export { t as AppContext, e as AppGlobalParamsContext, diff --git a/package.json b/package.json index 73546d8..51e463c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ff", - "version": "0.7.13", + "version": "0.7.14", "author": "www.fsdpf.com", "type": "module", "main": "./index.js", diff --git a/pages.js b/pages.js index 831ec8d..f5ba6a3 100644 --- a/pages.js +++ b/pages.js @@ -1,4 +1,4 @@ -import { L as t, K as e, M as o, N as g } from "./common/main.js"; +import { J as t, I as e, K as o, N as g } from "./common/main.js"; export { t as CustomPage, e as DataListPage, diff --git a/res-ws.d.ts b/res-ws.d.ts index 34aa38d..77f7923 100644 --- a/res-ws.d.ts +++ b/res-ws.d.ts @@ -1,28 +1,112 @@ -declare const _default: ResWs; +import { WidgetType, WidgetContainerProps } from './button'; -/** - * 基于 SharedWorker 的资源状态 WebSocket 单例;多个页面/标签页共用同一条连接, - * 按资源 uuid 把服务端推送的状态变化分发给各自的订阅回调 - */ -declare class ResWs { - /** @type {ResWs} */ - static "__#private@#instance": ResWs; - /** @returns {ResWs} 单例实例 */ - static getInstance: () => ResWs; - /** - * 订阅资源状态变化 - * @param {(data: *) => void} cb 状态变化时的回调,收到服务端推送的原始数据 - * @param {string|string[]} [res] 要订阅的资源 uuid,不传/空数组表示订阅全部('*') - * @returns {() => void} 取消订阅的函数 - */ - subscribe: (cb: (data: any) => void, res?: string | string[]) => () => void; - /** - * 取消订阅 - * @param {Function} cb 订阅时传入的回调 - * @returns {boolean} 是否成功移除 - */ - unsubscribe: (cb: Function) => boolean; - #private; +// ===== 用户数据结构(复用类型,JSDoc 无法跨文件引用,放 .d.ts) ===== + +interface UserRoleBinding { + user_uuid: string + role_uuid: string + created_at: string + updated_at: string + created_user: string + owned_user: string } -export { _default as default }; +interface UserInfo { + uuid: string + username: string + nickname: string + email: string + last_login_ip: string + is_active: 0 | 1 + UserRole: UserRoleBinding[] + [key: string]: unknown +} + + +interface MenuItem { + /** 菜单唯一标识 */ + uuid: string + /** 菜单显示名称 */ + name: string + /** 图标 class 名 */ + icon: string + /** 行为目标(组件标识 / 路由 uuid 等),含义随 widgetType 而定 */ + widget: string + /** 行为类型 */ + widgetType: WidgetType + /** 传给目标组件的 props 映射配置 */ + widgetProps: Record + /** 传给目标组件的 $setting 配置 */ + widgetSetting: Record + /** 弹窗容器配置 */ + widgetContainerSetting: WidgetContainerProps + /** 子菜单 */ + children?: MenuItem[] +} + +interface RouteItem { + /** 路由唯一标识 */ + uuid: string + /** 路由名称 */ + name: string + /** react-router path,支持动态参数(如 /page/:id) */ + uri: string + /** 是否为布局路由(外层 layout,不直接渲染页面内容) */ + isLayout: boolean + /** 是否需要登录才能访问 */ + isLogin: boolean + /** 是否为手机端专属路由 */ + isPhone: boolean + /** 路由类型 */ + type: Exclude + /** 是否精确匹配路径 */ + exact: boolean + /** widget 标识(等同于 ButtonProps.widget),经 core.getWidgetComponent 加载 */ + component: string + /** 传给页面组件的 props 映射配置 */ + widgetProps: Record + /** 传给页面组件的 $setting 配置 */ + widgetSetting: Record + /** 弹窗容器配置 */ + widgetContainerSetting: WidgetContainerProps + /** 附加配置(如 layout 标识等) */ + extra?: Record +} + +// ===== http — Proxy 模式产生交叉类型,JSDoc 无法表达 ===== + +/** 每次请求自动附加的请求头 */ +interface HttpHeaders { + /** 客户端平台标识,固定为 'web' */ + Platform: string + /** SaaS 租户标识,单租户时为 null */ + SaaS: string | null + /** JWT Bearer token,未登录时为 undefined */ + Authorization: string | undefined +} + +// ===== func — ff-worker-pipe 无类型文件,显式声明 ===== + +/** + * 基于 Worker 的表达式执行引擎单例; + * exec 在独立 Worker 上下文中求值一段 JS 表达式/源码 + */ +interface WorkerPipeInstance { + /** + * 在 Worker 上下文中执行一段 JS 表达式 + * @param expression 要执行的表达式字符串 + * @param args 传给表达式的参数(可在表达式内作为第一个参数使用) + * @param fns 注入到表达式执行作用域的额外可调用函数 + * @param session 会话标识;相同 session 共享 Worker 侧工作区(this) + */ + exec: ( + expression: string, + args?: Record, + fns?: Record, + session?: string + ) => Promise + /** 清除指定 session 的 Worker 侧工作区 */ + clear: (session: string) => void +} + +export type { HttpHeaders, MenuItem, RouteItem, UserInfo, UserRoleBinding, WorkerPipeInstance }; diff --git a/utils.d.ts b/utils.d.ts index 9c19839..b4dcbc0 100644 --- a/utils.d.ts +++ b/utils.d.ts @@ -1,3 +1,5 @@ +import { WidgetType, WidgetContainerProps } from './button'; + /** * 把任意值按目标类型做类型转换(json/array/number/integer/float/bool/string 互转) * @param {*} data 待转换的值 @@ -112,4 +114,114 @@ declare function getUrlWithPrefix(url: string, defaultPrefix?: string): string; */ declare function generateUUID(): string; +// ===== 用户数据结构(复用类型,JSDoc 无法跨文件引用,放 .d.ts) ===== + +interface UserRoleBinding { + user_uuid: string + role_uuid: string + created_at: string + updated_at: string + created_user: string + owned_user: string +} + +interface UserInfo { + uuid: string + username: string + nickname: string + email: string + last_login_ip: string + is_active: 0 | 1 + UserRole: UserRoleBinding[] + [key: string]: unknown +} + + +interface MenuItem { + /** 菜单唯一标识 */ + uuid: string + /** 菜单显示名称 */ + name: string + /** 图标 class 名 */ + icon: string + /** 行为目标(组件标识 / 路由 uuid 等),含义随 widgetType 而定 */ + widget: string + /** 行为类型 */ + widgetType: WidgetType + /** 传给目标组件的 props 映射配置 */ + widgetProps: Record + /** 传给目标组件的 $setting 配置 */ + widgetSetting: Record + /** 弹窗容器配置 */ + widgetContainerSetting: WidgetContainerProps + /** 子菜单 */ + children?: MenuItem[] +} + +interface RouteItem { + /** 路由唯一标识 */ + uuid: string + /** 路由名称 */ + name: string + /** react-router path,支持动态参数(如 /page/:id) */ + uri: string + /** 是否为布局路由(外层 layout,不直接渲染页面内容) */ + isLayout: boolean + /** 是否需要登录才能访问 */ + isLogin: boolean + /** 是否为手机端专属路由 */ + isPhone: boolean + /** 路由类型 */ + type: Exclude + /** 是否精确匹配路径 */ + exact: boolean + /** widget 标识(等同于 ButtonProps.widget),经 core.getWidgetComponent 加载 */ + component: string + /** 传给页面组件的 props 映射配置 */ + widgetProps: Record + /** 传给页面组件的 $setting 配置 */ + widgetSetting: Record + /** 弹窗容器配置 */ + widgetContainerSetting: WidgetContainerProps + /** 附加配置(如 layout 标识等) */ + extra?: Record +} + +// ===== http — Proxy 模式产生交叉类型,JSDoc 无法表达 ===== + +/** 每次请求自动附加的请求头 */ +interface HttpHeaders { + /** 客户端平台标识,固定为 'web' */ + Platform: string + /** SaaS 租户标识,单租户时为 null */ + SaaS: string | null + /** JWT Bearer token,未登录时为 undefined */ + Authorization: string | undefined +} + +// ===== func — ff-worker-pipe 无类型文件,显式声明 ===== + +/** + * 基于 Worker 的表达式执行引擎单例; + * exec 在独立 Worker 上下文中求值一段 JS 表达式/源码 + */ +interface WorkerPipeInstance { + /** + * 在 Worker 上下文中执行一段 JS 表达式 + * @param expression 要执行的表达式字符串 + * @param args 传给表达式的参数(可在表达式内作为第一个参数使用) + * @param fns 注入到表达式执行作用域的额外可调用函数 + * @param session 会话标识;相同 session 共享 Worker 侧工作区(this) + */ + exec: ( + expression: string, + args?: Record, + fns?: Record, + session?: string + ) => Promise + /** 清除指定 session 的 Worker 侧工作区 */ + clear: (session: string) => void +} + export { deepSome, generateUUID, getPkgCategory, getPkgName, getPkgOwner, getPrimitiveType, getUrlWithPrefix, getWidgetPropsData, hasUrlPrefix, hashJSON, makeUniqueIdGenerator, replaceKeys, toPrimitive, uuid }; +export type { HttpHeaders, MenuItem, RouteItem, UserInfo, UserRoleBinding, WorkerPipeInstance }; diff --git a/utils.js b/utils.js index bd3d363..ec8666b 100644 --- a/utils.js +++ b/utils.js @@ -1,5 +1,5 @@ import "lodash"; -import { S as r, a0 as i, W as g, V as o, X as P, P as m, $ as p, Q as U, _ as d, Y as h, Z as k, T as n, O as f, U as l } from "./common/main.js"; +import { P as r, _ as i, U as g, T as o, V as P, M as m, Z as p, O as U, Y as d, W as h, X as k, Q as n, L as f, S as l } from "./common/main.js"; import "./common/vendor.js"; export { r as deepSome, diff --git a/virtual-fs.d.ts b/virtual-fs.d.ts index 12d9dfc..2586f0f 100644 --- a/virtual-fs.d.ts +++ b/virtual-fs.d.ts @@ -1,3 +1,5 @@ +import { WidgetType, WidgetContainerProps } from './button'; + /** * 把 VirtualFS 里某个路径下的结构递归转换成 antd Tree 组件可用的节点结构 * (目录排在文件前面,各自按名称排序) @@ -292,4 +294,114 @@ declare class VirtualFS { #private; } -export { VirtualFS as default, toTreePaths }; +// ===== 用户数据结构(复用类型,JSDoc 无法跨文件引用,放 .d.ts) ===== + +interface UserRoleBinding { + user_uuid: string + role_uuid: string + created_at: string + updated_at: string + created_user: string + owned_user: string +} + +interface UserInfo { + uuid: string + username: string + nickname: string + email: string + last_login_ip: string + is_active: 0 | 1 + UserRole: UserRoleBinding[] + [key: string]: unknown +} + + +interface MenuItem { + /** 菜单唯一标识 */ + uuid: string + /** 菜单显示名称 */ + name: string + /** 图标 class 名 */ + icon: string + /** 行为目标(组件标识 / 路由 uuid 等),含义随 widgetType 而定 */ + widget: string + /** 行为类型 */ + widgetType: WidgetType + /** 传给目标组件的 props 映射配置 */ + widgetProps: Record + /** 传给目标组件的 $setting 配置 */ + widgetSetting: Record + /** 弹窗容器配置 */ + widgetContainerSetting: WidgetContainerProps + /** 子菜单 */ + children?: MenuItem[] +} + +interface RouteItem { + /** 路由唯一标识 */ + uuid: string + /** 路由名称 */ + name: string + /** react-router path,支持动态参数(如 /page/:id) */ + uri: string + /** 是否为布局路由(外层 layout,不直接渲染页面内容) */ + isLayout: boolean + /** 是否需要登录才能访问 */ + isLogin: boolean + /** 是否为手机端专属路由 */ + isPhone: boolean + /** 路由类型 */ + type: Exclude + /** 是否精确匹配路径 */ + exact: boolean + /** widget 标识(等同于 ButtonProps.widget),经 core.getWidgetComponent 加载 */ + component: string + /** 传给页面组件的 props 映射配置 */ + widgetProps: Record + /** 传给页面组件的 $setting 配置 */ + widgetSetting: Record + /** 弹窗容器配置 */ + widgetContainerSetting: WidgetContainerProps + /** 附加配置(如 layout 标识等) */ + extra?: Record +} + +// ===== http — Proxy 模式产生交叉类型,JSDoc 无法表达 ===== + +/** 每次请求自动附加的请求头 */ +interface HttpHeaders { + /** 客户端平台标识,固定为 'web' */ + Platform: string + /** SaaS 租户标识,单租户时为 null */ + SaaS: string | null + /** JWT Bearer token,未登录时为 undefined */ + Authorization: string | undefined +} + +// ===== func — ff-worker-pipe 无类型文件,显式声明 ===== + +/** + * 基于 Worker 的表达式执行引擎单例; + * exec 在独立 Worker 上下文中求值一段 JS 表达式/源码 + */ +interface WorkerPipeInstance { + /** + * 在 Worker 上下文中执行一段 JS 表达式 + * @param expression 要执行的表达式字符串 + * @param args 传给表达式的参数(可在表达式内作为第一个参数使用) + * @param fns 注入到表达式执行作用域的额外可调用函数 + * @param session 会话标识;相同 session 共享 Worker 侧工作区(this) + */ + exec: ( + expression: string, + args?: Record, + fns?: Record, + session?: string + ) => Promise + /** 清除指定 session 的 Worker 侧工作区 */ + clear: (session: string) => void +} + +export { toTreePaths }; +export type { HttpHeaders, MenuItem, RouteItem, UserInfo, UserRoleBinding, WorkerPipeInstance }; diff --git a/virtual-fs.js b/virtual-fs.js index a4fc55c..6f7c95c 100644 --- a/virtual-fs.js +++ b/virtual-fs.js @@ -1,5 +1,5 @@ import "pathe"; -import { aH as o, aI as r } from "./common/main.js"; +import { aF as o, aG as r } from "./common/main.js"; export { o as default, r as toTreePaths