/// /// import { Aspect, EntityDict, CheckerType, AggregationResult, OpRecord, OakUserException } from "oak-domain/lib/types"; import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain'; import { Feature } from './Feature'; import { Pagination } from "./Pagination"; import { BasicFeatures } from "../features"; import { NamedFilterItem, NamedSorterItem } from './NamedCondition'; import { NotificationProps } from './Notification'; import { MessageProps } from './Message'; import { AsyncContext } from "oak-domain/lib/store/AsyncRowStore"; import { SyncContext } from "oak-domain/lib/store/SyncRowStore"; import React from "react"; export type DataOption = WechatMiniprogram.Component.DataOption; export type MethodOption = WechatMiniprogram.Component.MethodOption; /** * 微信的原声明中少写了FunctionConstructor,只能抄一遍 */ export type ActionDef = { action: ED[T]['Action']; filter?: ED[T]['Selection']['filter']; data?: Partial; label?: string; attrs?: (keyof ED[T]['Update']['data'] | '#all')[]; } | ED[T]['Action']; export type RowWithActions = Partial & { '#oakLegalActions': ActionDef[]; '#oakLegalCascadeActions': { [K in keyof ED[T]['Schema']]?: ActionDef[]; }; }; type FeatureDef, FrontCxt extends SyncContext, AD extends Record>, FD extends Record, FormedData extends Record, TData extends DataOption, TProperty extends DataOption, TMethod extends Record, EMethod extends Record = {}> = (keyof (FD & BasicFeatures)) | { feature: keyof (FD & BasicFeatures); behavior?: 'reRender' | 'refresh'; callback?: (this: ComponentPublicThisType) => void; }; type DevideWidth = 'pc' | 'mobile'; export type CreateDataDef = ED[T]['CreateSingle']['data'] | (() => ED[T]['CreateSingle']['data']); interface ComponentOption, FrontCxt extends SyncContext, AD extends Record>, FD extends Record, FormedData extends Record, TData extends DataOption, TProperty extends DataOption, TMethod extends Record, EMethod extends Record = {}> { /** * 是否为列表组件 */ isList?: IsList; stale?: boolean; zombie?: true; getTotal?: { max: number; deviceWidth?: DevideWidth | 'all'; } | number; /** * 组件所关联的实体 */ entity?: T | ((this: ComponentPublicThisType) => T); path?: string; /** * 需要监听的features */ features?: FeatureDef[]; cascadeActions?: (this: ComponentPublicThisType) => { [K in keyof ED[T]['Schema']]?: ActionDef[]; }; /** * 需要校验的actions */ actions?: ActionDef[] | ((this: ComponentPublicThisType) => ActionDef[]); /** * 需要获取的数据字段 * 若嵌套在list中,需要保证父list组件能够覆盖子组件的projection */ projection?: ED[T]['Selection']['data'] | ((this: ComponentPublicThisType) => ED[T]['Selection']['data'] | undefined); append?: boolean; /** * 分页信息 */ pagination?: Pick | Array & { deviceWidth: DevideWidth; }>; /** * 过滤器 */ filters?: Array<{ filter: NonNullable | ((this: ComponentPublicThisType) => ED[T]['Selection']['filter'] | undefined); '#name'?: string; }>; /** * 排序器 */ sorters?: Array<{ sorter: NonNullable[number] | ((this: ComponentPublicThisType) => ED[T]['Selection']['sorter'] | NonNullable[number]); '#name'?: string; }>; /** * 表单数据 * 在组件渲染前会调用此方法,将返回的数据放入组件的data中 * @param options 组件获取到的数据 * @returns 返回给页面的数据 */ formData?: (options: { data: IsList extends true ? RowWithActions[] : RowWithActions; origin?: IsList extends true ? RowWithActions[] : RowWithActions; features: BasicFeatures & FD; props: TProperty; legalActions?: ActionDef[]; originLegalActions?: ActionDef[]; dirty: boolean; modified: boolean; }) => FormedData; ns?: T | T[]; /** * 声明的State数据 */ data?: ((this: ComponentPublicThisType) => TData) | TData; /** * 需要参数传入的默认prop参数 */ properties?: TProperty; /** * 自定义方法 */ methods?: TMethod; } export type MiniprogramStyleMethods = { animate(selector: string, keyFrames: WechatMiniprogram.Component.KeyFrame[], duration: number, callback?: () => void): void; clearAnimation(selector: string, options?: WechatMiniprogram.Component.ClearAnimationOptions, callback?: () => void): void; triggerEvent: (name: string, detail?: DetailType, options?: WechatMiniprogram.Component.TriggerEventOption) => void; }; export type ComponentProps = OakComponentProperties & Partial; export type ReactComponentProps = ComponentProps & { className?: string; style?: Record; }; export type ComponentData = TData & FormedData & OakComponentData; export type ComponentPublicThisType, FrontCxt extends SyncContext, AD extends Record>, FD extends Record, FormedData extends Record, IsList extends boolean, TData extends Record = {}, TProperty extends DataOption = {}, TMethod extends MethodOption = {}, EMethod extends Record = {}> = { features: FD & BasicFeatures; state: ComponentData; props: Readonly>; setState: (data: Partial>, callback?: () => void) => void; triggerEvent: (name: string, detail?: DetailType, options?: WechatMiniprogram.Component.TriggerEventOption) => void; } & TMethod & EMethod & OakCommonComponentMethods & OakListComponentMethods & OakSingleComponentMethods; export type OakLifetime = 'born' | 'created' | 'attached' | 'ready' | 'detached'; export type ComponentFullThisType = { features: BasicFeatures; state: OakComponentData; props: ComponentProps; setState: (data: Partial>, callback?: () => void) => void; triggerEvent: (name: string, detail?: DetailType, options?: WechatMiniprogram.Component.TriggerEventOption) => void; oakLifetime: OakLifetime; } & OakCommonComponentMethods & OakListComponentMethods & OakSingleComponentMethods; export type OakComponentOption, FrontCxt extends SyncContext, AD extends Record>>, FD extends Record, FormedData extends Record, TData extends Record, TProperty extends DataOption, TMethod extends Record, EMethod extends Record = {}> = ComponentOption & Partial<{ /** * 生命周期回调 */ lifetimes: { /** * 在组件实例刚刚被创建时执行 * sync only */ created?(): void; /** * 在组件实例进入页面节点树时执行 * sync only */ attached?(): void; /** * 在组件实例进入页面节点树时执行 * async or sync */ ready?(): any; /** * 小程序专用,在组件实例被移动到节点树另一个位置时执行 * sync only */ moved?(): void; /** * 在组件实例被从页面节点树移除时执行 * sync only */ detached?(): void; /** * 小程序专用,每当组件方法抛出错误时执行 * sync only * @param err 错误信息 */ error?(err: Error): void; /** * 组件所在的页面被展示时执行 * sync only */ show?(): void; /** * 组件所在的页面被隐藏时执行 * sync only */ hide?(): void; /** * 组件所在的页面尺寸变化时执行 * sync only * @param size 页面尺寸信息 */ resize?(size: WechatMiniprogram.Page.IResizeOption): void; }; /** * 监听器,监听State或者Props的变化 * 名称:监听的属性名 * 回调:监听的回调函数 (prev, next) => void */ listeners: Record, prev: Record, next: Record) => void>; }> & Partial<{ wechatMp: { externalClasses?: string[]; options?: Partial | undefined; }; }> & ThisType>; type OakComponentProperties = Partial<{ width: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl'; oakPath: string; oakId: string; oakFrom: string; oakParentEntity: string; oakDisablePulldownRefresh: boolean; oakZombie: boolean; oakAutoUnmount: boolean; oakActions: string; oakCascadeActions: string; oakFilters: Array; } & React.RefAttributes>; export type OakListComponentProperties = Partial<{}>; export type OakNavigateToParameters = { oakId?: string; oakPath?: string; oakParent?: string; [k: string]: any; }; export type OakCommonComponentMethods = { addFeatureSub: (name: string, callback: (args?: any) => void) => void; removeFeatureSub: (name: string, callback: (args?: any) => void) => void; unsubscribeAll: () => void; subscribeAll: () => void; save: (key: string, item: any) => Promise; load: (key: string) => Promise; clear: (key?: string) => Promise; setNotification: (data: NotificationProps) => void; consumeNotification: () => NotificationProps | undefined; setMessage: (data: MessageProps) => void; consumeMessage: () => MessageProps | undefined; reRender: (extra?: Record) => void; getFreshValue: (path?: string) => Partial[] | Partial | undefined; navigateTo: (options: { url: string; } & OakNavigateToParameters, state?: Record, disableNamespace?: boolean) => Promise; navigateBack: (delta?: number) => Promise; redirectTo: (options: Parameters[0] & OakNavigateToParameters, state?: Record, disableNamespace?: boolean) => Promise; switchTab: (options: Parameters[0] & OakNavigateToParameters, state?: Record, disableNamespace?: boolean) => Promise; savePoint: () => number; clean: (lsn?: number, dontPublish?: true, path?: string) => void; isDirty: (path?: string) => boolean; t(key: string, params?: object): string; execute: (action?: ED[T]['Action'], messageProps?: boolean | MessageProps, path?: string, opers?: Array<{ entity: T; operation: ED[T]['Operation']; }>) => Promise; checkOperation: (entity: T2, operation: { action: ED[T2]['Action']; data?: ED[T2]['Operation']['data']; filter?: ED[T2]['Operation']['filter']; }, checkerTypes?: CheckerType[]) => boolean | OakUserException; tryExecute: (path?: string, action?: ED[T]['Action']) => boolean | OakUserException; getOperations: (path?: string) => { operation: ED[T]['Operation']; entity: T; }[] | undefined; refresh: (pageNumber?: number) => Promise; aggregate: (aggregation: ED[T]['Aggregation']) => Promise>; subDataEvents: (events: string[], callback?: (event: string, opRecords: OpRecord[]) => void) => Promise<() => void>; }; export type OakSingleComponentMethods = { setId: (id: string) => void; unsetId: () => void; getId: () => string | undefined; create: (data: Omit, path?: string) => void; update: (data: ED[T]['Update']['data'], action?: ED[T]['Action'], path?: string) => void; remove: (path?: string) => void; isCreation: (path?: string) => boolean; }; export type OakListComponentMethods = { loadMore: () => Promise; setFilters: (filters: NamedFilterItem[], path?: string) => void; getFilters: (path?: string) => ED[T]['Selection']['filter'][] | undefined; getFilterByName: (name: string, path?: string) => ED[T]['Selection']['filter'] | undefined; addNamedFilter: (filter: NamedFilterItem, refresh?: boolean, path?: string) => void; setNamedFilters: (filters: NamedFilterItem[], refresh?: boolean, path?: string) => void; removeNamedFilter: (filter: NamedFilterItem, refresh?: boolean, path?: string) => void; removeNamedFilterByName: (name: string, refresh?: boolean, path?: string) => void; setNamedSorters: (sorters: NamedSorterItem[], refresh?: boolean, path?: string) => void; getSorters: (path?: string) => ED[T]['Selection']['sorter'] | undefined; getSorterByName: (name: string, path?: string) => NonNullable[number] | undefined; addNamedSorter: (sorter: NamedSorterItem, refresh?: boolean, path?: string) => void; removeNamedSorter: (sorter: NamedSorterItem, refresh?: boolean, path?: string) => void; removeNamedSorterByName: (name: string, refresh?: boolean, path?: string) => void; getPagination: (path?: string) => Pagination | undefined; setPageSize: (pageSize: number, path?: string) => void; setCurrentPage: (current: number, path?: string) => void; addItem: (data: Omit & { id?: string; }, path?: string) => string; addItems: (data: Array & { id?: string; }>, path?: string) => string[]; removeItem: (id: string, path?: string) => void; removeItems: (ids: string[], path?: string) => void; updateItem: (data: ED[T]['Update']['data'], id: string, action?: ED[T]['Action'], path?: string) => void; updateItems: (data: ED[T]['Update']['data'], ids: string[], action?: ED[T]['Action'], path?: string) => void; recoverItem: (id: string, path?: string) => void; recoverItems: (ids: string[], path?: string) => void; resetItem: (id: string, path?: string) => void; }; type ComponentOnPropsChangeOption = { path?: string; parent?: string; }; export type OakComponentOnlyMethods = { onPropsChanged: (options: ComponentOnPropsChangeOption) => void; registerReRender: () => void; setOakActions: () => void; }; export type OakComponentData = { oakExecutable: boolean | Error; oakExecuting: boolean; oakFocused: { attr: string; message: string; }; oakModified: boolean; oakDirty: boolean; oakLoading: boolean; oakLoadingMore: boolean; oakPullDownRefreshLoading: boolean; oakEntity: T; oakFullpath: string; oakLegalActions?: ED[T]['Action'][]; oakLocales: Record; oakLocalesVersion: number; oakLng: string; oakDefaultLng: string; }; type OakListComoponetData = { oakPagination?: Pagination; }; export type MakeOakComponent, FrontCxt extends SyncContext, AD extends Record>>, FD extends Record> = (options: OakComponentOption) => (props: ReactComponentProps) => React.ReactElement; export type WebComponentCommonMethodNames = 'setNotification' | 'setMessage' | 'navigateTo' | 'navigateBack' | 'redirectTo' | 'clean' | 't' | 'execute' | 'refresh' | 'aggregate' | 'checkOperation' | 'isDirty'; export type WebComponentListMethodNames = 'loadMore' | 'setFilters' | 'addNamedFilter' | 'removeNamedFilter' | 'removeNamedFilterByName' | 'setNamedSorters' | 'addNamedSorter' | 'removeNamedSorter' | 'removeNamedSorterByName' | 'setPageSize' | 'setCurrentPage' | 'addItem' | 'addItems' | 'removeItem' | 'removeItems' | 'updateItem' | 'updateItems' | 'resetItem' | 'recoverItem' | 'recoverItems'; export type WebComponentSingleMethodNames = 'update' | 'remove' | 'create' | 'isCreation' | 'getId' | 'setId'; export type WebComponentProps = { methods: TMethod & OakCommonComponentMethods & OakListComponentMethods & OakSingleComponentMethods; data: TData & OakComponentData & (IsList extends true ? OakListComoponetData : { oakId?: string; }); }; export {};