import { getJSExpressionPrototype, getParamSetterPrototype, getStyleListByPosition, } from './common-style'; import React, { useEffect } from 'react'; import qs from 'query-string'; import { ButtonPosition } from './position/button-position'; import { createRequestSuccessPrototype, createServiceSelectPrototype, getRealResponse, handleRequestParams, handleResultProcessFunc, makeRequest, transRequestConfigToRemote, } from '../util/request'; import { calculateTextExprValue, executeFunction, executeObjectExpr, getArrayTableCurrentRowByField2, getArrayTableFieldList, getBizComponent, getBizComponentNameList, getDataSourceList, getDataSourceListWithAllPath, getDownloadProps, getNodeById, getRealizeValue, getRealRequestUrl, getRunTimeBizComponent, getVariableDsList, handleI18nLabel, handlePrototypeCondition, isArrayNotEmpty, isRecursionComponent, renderIcon, uuid, } from '../util/util'; import { CnButton, CnDialog, CnDownload, CnMenuButton, CnMenuButtonItem, CnMessage, } from '@cainiaofe/cn-ui'; import uniq from 'lodash/uniq'; import isPlainObject from 'lodash/isPlainObject'; import cloneDeep from 'lodash/cloneDeep'; import flatten from 'lodash/flatten'; import './button.scss'; import { createMessageSetters } from '@/common/util/message'; import $i18n from 'panda-i18n'; import CheckboxSetter from '@/common/setter/checkbox-setter'; import { getFieldSelectSetterSnippet, getFormHandleTypeSetterSnippet, getJSXTemplate, getSelectDialogSnippet, getSetterSnippet, } from '@/common/manager/setter-snippet'; import groupBy from 'lodash/groupBy'; import { __arrayTableCurrentRow__, __dataSource__, __flowData__, componentRefSplit, getCommonBoolDataSource, getOpenDialogModeEnum, openDialogModeLabel, } from '@/common/util/expr-const'; import { getSelectParamSelectSetter } from '@/common/manager/filter-item/select'; import { formComponentRefStorage, pageDataSource, } from '@/common/util/const'; import { CnDataSourceChange, emitEvent, } from '@/common/util/event-name'; import { ActionRunEnv } from '@/common/util/action-run-env'; import ExprSetter from '@/common/setter/expr-setter'; import isNaN from 'lodash/isNaN'; import isNumber from 'lodash/isNumber'; import isFunction from 'lodash/isFunction'; import { ParamSelectSetter } from '@/common/setter/param-select-setter'; import set from 'lodash/set'; import isUndefined from 'lodash/isUndefined'; import findLastIndex from 'lodash/findLastIndex'; import { DisplayPosition } from '@/common/manager/position/display-position'; const { ActionSetter } = window.VisualEngineUtils || {}; const jsActionMap = { [ButtonPosition.formItemEvent]: `/** * onFieldValueChange * 用法请参考formily官方示例 * https://formilyjs.org/zh-CN/guide/advanced/linkages#effects-%E7%94%A8%E4%BE%8B-2 * * @param field 当前字段 * @param form 当前表单实例 */ function onFieldValueChange(field, form) { // 当前字段的值 // const value = field.value; // 查询其他字段的值 // const otherFieldValue = field.query('xxx').value() // 设置字段的值 // form.setFieldState('xxx', (state) => { // state.value = yyy; // }) }`, [ButtonPosition.filterItemEvent]: `/** * onFieldValueChange * * @param field 当前字段 * @param form 当前筛选栏实例 */ function onFieldValueChange(field, form) { // 当前字段的值 // const value = field.value; // 查询其他字段的值 // const otherFieldValue = field.query('xxx').value() // 设置字段的值 // form.setFieldState('xxx', (state) => { // state.value = yyy; // }) }`, // [ButtonPosition.formDialogItemEvent]: this[ButtonPosition.formItemEvent], [ButtonPosition.cnArrayTableItemEvent]: `/** * onFieldValueChange * 用法请参考formily官方示例 * https://formilyjs.org/zh-CN/guide/advanced/linkages#effects-%E7%94%A8%E4%BE%8B-2 * * @param field 当前字段 * @param form 当前表单实例 */ function onFieldValueChange(field, form) { // 当前字段的值 // const value = field.value; // 当前行的index // const index = field?.path?.segments?.[1]; // 查询当前行其他字段的值,xxx代表可编辑表格的字段编码,yyy代表表格某列的字段编码 // const otherFieldValue = field.query(\`xxx.$\{index}.yyy\`).value() // 查询表单其他字段的值 // const otherFieldValue2 = field.query('xxx').value() // 设置当前行其他字段的值 // form.setFieldState(\`xxx.$\{index}.yyy\`, (state) => { // state.value = zzz; // }); }`, [ButtonPosition.form]: `/** * js脚本 * */ function jsAction({ form, state }) { // state:全部组件的数据 // form:表单实例 }`, [ButtonPosition.tabEvent]: `/** * js脚本 * */ function jsAction(activeKey, state) { }`, }; jsActionMap[ButtonPosition.formDialogItemEvent] = jsActionMap[ButtonPosition.formItemEvent]; jsActionMap[ButtonPosition.formDialog] = jsActionMap[ButtonPosition.form]; jsActionMap[ButtonPosition.cnArraySubAreaCardItemEvent] = jsActionMap[ButtonPosition.cnArrayTableItemEvent]; jsActionMap[ButtonPosition.formEvent] = jsActionMap[ButtonPosition.form]; const ALL_BUTTON_POSITION_LIST = Object.values(ButtonPosition); const componentLoopMap = {}; const jsAction = { title: 'js脚本', value: 'jsAction', position: ALL_BUTTON_POSITION_LIST, // getPrototypeList: (position) => { // if([ButtonPosition.filterItemEvent,ButtonPosition.formItemEvent,ButtonPosition.formDialogItemEvent].includes(position)) { // return [ // { // title: '自定义脚本', // name: 'jsFunction', // setter: // } // ] // } // }, getPrototypeList: (position, config) => { const { __field } = config || {}; if ( [ ButtonPosition.filterItemEvent, ButtonPosition.formItemEvent, ButtonPosition.formDialogItemEvent, ButtonPosition.cnArrayTableItemEvent, ].includes(position) ) { return [ { title: '自定义脚本', name: 'jsFunction', // isRequired: true, // editable:true, display: 'inline', // condition(){ // return true; // }, className: 'cn-action-setter', // setter: , setter: { componentName: ( ), props: () => { let defaultCode = jsActionMap[position]; let defaultActionName = 'onFieldValueChange'; if (__field?.getValue?.()?.name === 'onFieldReact') { if (ButtonPosition.cnArrayTableItemEvent === position) { defaultCode = `/** * onFieldReact * 用法请参考formily官方示例 * https://formilyjs.org/zh-CN/guide/advanced/linkages#%E8%A2%AB%E5%8A%A8%E6%A8%A1%E5%BC%8F * * @param field 当前字段 * @param form 当前表单实例 */ function onFieldReact(field, form) { // 当前字段的值 // const value = field.value; // 当前行的index // const index = field?.path?.segments?.[1]; // 查询当前行其他字段的值,xxx代表可编辑表格的字段编码,yyy代表表格某列的字段编码 // const otherFieldValue = field.query(\`xxx.$\{index}.yyy\`).value() // 查询表单其他字段的值 // const otherFieldValue2 = field.query('xxx').value() // 示例:当前字段的值等于 自身的值 + 当前行其他字段的值。 // field.value = value + otherFieldValue }`; } else { defaultCode = `/** * onFieldReact * 用法请参考formily官方示例 * https://formilyjs.org/zh-CN/guide/advanced/linkages#%E8%A2%AB%E5%8A%A8%E6%A8%A1%E5%BC%8F * * @param field 当前字段 * @param form 当前表单实例 */ function onFieldReact(field, form) { // 查询其他字段的值 // const otherFieldValue = field.query('xxx').value() // 查询其他字段的值 // const otherFieldValue2 = field.query('xxx2').value() // 示例:当前字段的值等于otherFieldValue乘otherFieldValue2。 // field.value = otherFieldValue * otherFieldValue2 }`; } defaultActionName = 'onFieldReact'; } return { supportTypes: ['page'], defaultCode, defaultActionName, }; }, }, }, ]; } else { return [ { title: '自定义脚本', name: 'jsFunction', // isRequired: true, // editable:true, display: 'inline', // condition(){ // return true; // }, className: 'cn-action-setter', // setter: , setter: { componentName: ( ), props: () => { const defaultCode = jsActionMap[position]; const defaultActionName = 'jsAction'; return { supportTypes: ['page'], defaultCode, defaultActionName, }; }, }, }, ]; } }, action: (config) => { const { buttonConfig, _context, position, extraParams = {}, formInstance, field, recordDataSource, } = config; const { name, options } = buttonConfig; const { jsFunction } = options || {}; if (typeof jsFunction === 'function') { if ( [ ButtonPosition.filterItemEvent, ButtonPosition.formItemEvent, ButtonPosition.formDialogItemEvent, ].includes(position) ) { if (name === 'onChange') { const { formValue, fieldName } = extraParams; const value = ''; return jsFunction(value, fieldName, formValue, _context); } else { return jsFunction(field, getRealizeValue(formInstance)); } } else if ( [ ButtonPosition.form, ButtonPosition.formDialog, ButtonPosition.formEvent, ].includes(position) ) { const form = getRealizeValue(formInstance); const state = _context?.state; async function executeJsFunction() { await jsFunction({ state, form }); } return executeJsFunction(); } else if ([ButtonPosition.tabEvent].includes(position)) { const state = _context?.state; async function executeJsFunction() { await jsFunction(recordDataSource, state); } return executeJsFunction(); } else { async function executeJsFunction() { await jsFunction(); } return executeJsFunction(); } } }, }; const link = { title: '跳转链接', value: 'link', position: ALL_BUTTON_POSITION_LIST, getDefaultProps: () => { return { redirectType: 'open', routerType: 'location', }; }, getPrototypeList: (position, config) => { let paramSetter = 'StringSetter'; let urlSetter = 'StringSetter'; const setterSnippet = getSetterSnippet({ position, optType: 'link', ...config, }); const { urlSetter: newUrlSetter, requestParamSetter } = setterSnippet || {}; if (requestParamSetter) { paramSetter = requestParamSetter; } if (newUrlSetter) { urlSetter = newUrlSetter; } return [ // { // title: '路由类型', // name: 'routerType', // condition() { // return false; // }, // description: '路由类型', // setter: 'StringSetter', // }, { title: '链接地址', name: 'url', // condition: { // "type": "JSFunction", // "value": "() => false" // }, description: '链接地址', className: 'cn-link-url-setter', setter: urlSetter, }, { title: '跳转方式', name: 'redirectType', description: '跳转方式', setter: { componentName: 'RadioGroupSetter', initialValue: 'current', props: { options: [ { title: '当前页面', value: 'current', }, { title: '新开页面', value: 'open', }, { title: '返回上一页', value: 'back', }, ], }, }, }, { title: 'url参数', name: 'urlParams', description: 'url参数', // extraProps: { // }, className: 'cn-button-url-param-setter', setter: { componentName: 'ArraySetter', props: { mode: 'list', itemSetter: { componentName: 'ObjectSetter', // initialValue: { // "type": "JSFunction", // "value": "() => {return {primaryKey: String(Math.floor(Math.random() * 10000)),children: \"Title\",optType:\"link\" };}" // }, initialValue: { label: 'param', }, props: { config: { items: [ { title: '参数名', name: 'label', isRequired: true, description: '参数名', setter: 'StringSetter', }, // { // title: '参数值', // name: 'value', // isRequired: true, // description: '参数值', // supportVariable: true, // setter: 'StringSetter', // }, { title: '参数值', name: 'value', isRequired: true, description: '参数值', // supportVariable: true, className: 'cn-param-select-setter', setter: paramSetter, }, ], }, }, }, }, }, }, ]; }, action: (config, extra) => { const { buttonConfig, urlParamsDataSource, recordDataSource: originalRecordDataSource, state, position, arrayTableConfig, selectedRowKeys = [], selectedRowRecords = [], getExtraParam, arrayTableCurrentRow, arrayBaseFieldIndex, parentPosition, } = config; const needDelay = position === ButtonPosition.formDialogSubmitAfterRequestSuccess || position === ButtonPosition.formSubmitAfterRequestSuccess; const { options } = buttonConfig || {}; let extraParamList = []; let recordDataSource = getRealizeValue(originalRecordDataSource); if (position === ButtonPosition.arraySubAreaCardOperate) { recordDataSource = arrayTableCurrentRow; extraParamList = [arrayBaseFieldIndex]; } else if (position === ButtonPosition.arrayTableOperate) { if (extra?.field) { const { field } = extra; const { formItemConfig } = arrayTableConfig || {}; if (formItemConfig?.name && field) { const list = field?.query?.(formItemConfig?.name)?.value?.(); if (Array.isArray(list) && list[field?.index]) { recordDataSource = list[field.index]; extraParamList = [field.index]; } } } } else if (position === ButtonPosition.arrayTableCell) { const { field } = extra || {}; if (field) { const index = +field?.path?.segments?.[1]; if (typeof index === 'number' && !isNaN(index)) { recordDataSource = field.query('..').value()?.[index]; extraParamList = [index]; } } } else { extraParamList.push(selectedRowKeys); extraParamList.push(selectedRowRecords); } if ( position === ButtonPosition.subCardAction && parentPosition === DisplayPosition.cnArraySubAreaCard ) { extraParamList = [ { [__arrayTableCurrentRow__]: arrayTableCurrentRow, }, ]; } if (options) { const { url, redirectType, urlParams = [] } = options; let search = ''; if (redirectType === 'back') { window?.history?.back?.(); } else { if (urlParams && urlParams.length > 0) { const temp = handleRequestParams(urlParams, { urlParamsDataSource, recordDataSource, state, extraParamList, getExtraParam, }); search = qs.stringify(temp); } if (url) { let realUrl = calculateTextExprValue(url, { urlParamsDataSource, recordDataSource, state, extraParamList, getExtraParam, }); if (typeof realUrl === 'string' && realUrl.length > 0) { if (realUrl.indexOf('?') !== -1) { if (search) { realUrl += `&${search}`; } } else if (search) { realUrl += `?${search}`; } const temp = () => { if (redirectType === 'current') { if (typeof window.jumpTo === 'function') { const tempList = realUrl?.split('?'); window.jumpTo({ pathname: tempList?.[0], search: tempList?.[1], reload: true, }); } else { location.href = realUrl; } } else if (redirectType === 'open') { if (typeof window.jumpTo === 'function') { const tempList = realUrl?.split('?'); window.jumpTo({ pathname: tempList?.[0], search: tempList?.[1], type: '_blank', }); } else { window.open(realUrl); } } }; if (needDelay) { setTimeout(temp, 1500); } else { temp(); } } } } } }, // getButtonNode: (arg) => { // const { buttonConfig, record, index } = arg; // const { optType, options = {}, children } = buttonConfig; // if (children) { // let events = {}; // if (optType) { // const button = componentMap[optType]; // if (typeof button?.action === 'function') { // events = { // onClick: button.action.bind(this, arg), // }; // } // } // return {children}; // } // return null; // }, }; const pollingAction = { title: '轮询操作', value: 'pollingAction', position: ALL_BUTTON_POSITION_LIST, getPrototypeList: (position, config) => { return [ { name: 'pollingItem', display: 'inline', title: '轮询项配置', tip: '以配置的项为基础单位都会不停轮询', setter: createPollingListSetters({ position, activeSetter: { componentName: 'MixedSetter', props: { setters: [ { componentName: , title: '启用/禁用', }, { componentName: ( ), props(field) { const [flowList, index] = getPollingFlowList(field); // 是否开启的地方 return { configList: [ { groupName: '动作编排的数据', groupExprName: __flowData__, needSecondParam: true, flowList, currentFlowIndex: index, }, { groupName: '其他数据', groupExprName: __dataSource__, needSecondParam: true, }, ], }; }, title: '简单表达式', }, { title: '写js表达式', componentName: 'CnRowDataSetter', props(field) { const [flowList, index] = getPollingFlowList(field); // 是否开启的js 地方 const stateList = getDataSourceListWithAllPath({ needChildren: true, prototypeConfig: { flowList, currentFlowIndex: index, }, }); return { list: stateList, initialCode: `(arg, state) => { // return state.urlParams.xxx; }`, tip: ` state:全部的数据,在左侧列表中选择使用。 `, }; }, }, ], }, }, excludeButtonList: ['pollingAction', 'submit'] }) }, { name: 'checkIsEnd', display: 'block', title: '判断是否结束(根据接口返回数据)', setter: getJSExpressionPrototype({ type: 'pollService' }), }, { name: 'interval', display: 'block', title: '间隔时间(秒)', setter: 'NumberSetter', } ] }, action: async (config, ...otherArgs) => { const { buttonConfig, position, _context, getFlowActionInfo } = config || {}; const { options, optType: fromOptType } = buttonConfig || {}; const { pollingItem, checkIsEnd, interval } = options; async function executeFlowListInPolling(list) { let isStop = false; const result = []; while(!isStop) { for (const index in list) { const item = list[index]; const { active, optType } = item || {}; const isActive = executeObjectExpr( active, { [__dataSource__]: _context?.state, }, {}, _context?.state, ); if (isActive === true) { let action = getButtonAction({ ...item, position, }); if (!action) { const componentDefine = getRunTimeItem(optType); const component = getRealizeValue(componentDefine?.component); if (typeof component?.action === 'function') { action = component.action; } } let flowResult; if (typeof action === 'function') { flowResult = await action( { needSuccessToast: false, ...config, buttonConfig: { ...item }, // 动作执行的环境 actionRunEnv: 'pollingAction', getFlowActionInfo: () => { return { pollingItem, currentFlowIndex: index, }; }, }, ...otherArgs, ); } const handleFlowResult = getItem( position, optType, 'handleFlowResult', ); if (typeof handleFlowResult === 'function') { flowResult = handleFlowResult(flowResult); } if (flowResult && _context) { let realIndex = +index; if (realIndex === 0) { realIndex = ''; } // _context.state.valueOf.polling = { // ...(_context.state.valueOf.polling ?? {}), // [optType + realIndex]: flowResult, // } const parentIndex = fromOptType === "pollingAction" ? getFlowActionInfo()?.currentFlowIndex : ''; _context.state.valueOf[ `polling${parentIndex}_${optType}${realIndex}`] = flowResult; } !isUndefined(flowResult) && result.push(flowResult); if(!isStop) { isStop = executeFunction(checkIsEnd, flowResult, _context?.state ); } } } if(!isStop) { await waitAsync(interval ? interval * 1000 :2000); } } return result[result.length - 1]; } if (Array.isArray(pollingItem) && pollingItem.length > 0) { if (_context?.state) { const flowDataKeys = Object.keys(_context.state.valueOf); if (Array.isArray(flowDataKeys) && flowDataKeys.length > 0) { flowDataKeys.forEach((key) => { if (key) { if (key.includes('$$$') || key.startsWith('Cn')) { } else { _context.state.valueOf[key] = undefined; } } }); } } return await executeFlowListInPolling(pollingItem); } } } const request = { title: '发请求', value: 'request', position: ALL_BUTTON_POSITION_LIST, getPrototypeList: (position, config) => { let paramSetter = 'StringSetter'; let paramSelectSetter; let jsExpressionSetter; let wholeParamSetter; const setterSnippet = getSetterSnippet({ position, optType: 'request', ...config, }); const { requestParamSetter } = setterSnippet || {}; if (requestParamSetter) { paramSetter = requestParamSetter; if (Array.isArray(requestParamSetter?.props?.setters)) { paramSelectSetter = requestParamSetter?.props?.setters?.find( (item) => item?.componentName === 'ParamSelectSetter', ); jsExpressionSetter = requestParamSetter?.props?.setters?.find( (item) => item?.componentName === 'CnRowDataSetter', ); } } if ([ButtonPosition.tableOperate].includes(position)) { wholeParamSetter = { name: 'params', title: '请求参数配置', className: 'params-list', setter: { componentName: 'MixedSetter', props: { setters: [ { title: '设置每个字段的值', componentName: 'ArraySetter', props: { mode: 'list', itemSetter: { componentName: 'ObjectSetter', initialValue: {}, props: { config: { items: [ { name: 'label', isRequired: true, title: '参数名', setter: 'StringSetter', }, { name: 'value', isRequired: true, title: '参数值', setter: paramSetter, }, ], }, }, }, }, }, jsExpressionSetter, ], }, }, }; } return createServiceSelectPrototype({ optType: 'request', paramSetter, position, paramSelectSetter, jsExpressionSetter, wholeParamSetter, }); }, action: (config, extra) => { let { buttonConfig = {}, record, componentProps = {}, position, tableRef, state, urlParamsDataSource, recordDataSource, needSuccessToast, extraParamList, arrayTableConfig, noNeedHandleResult, isDesign, _context, field, formInstance, actionRunEnv, getExtraParam, arrayTableCurrentRow, arrayBaseFieldIndex, parentComponentName, } = config; const { options = {} } = buttonConfig; const { keepPagination } = options; if (isRecursionComponent(parentComponentName)) { recordDataSource = getArrayTableCurrentRowByField2(field) || {}; const segments = field?.path?.segments || []; extraParamList = segments[segments?.length - 2]; } if (position === ButtonPosition.arraySubAreaCardOperate) { recordDataSource = arrayTableCurrentRow; extraParamList = [arrayBaseFieldIndex]; } else if (position === ButtonPosition.arrayTableOperate) { if (extra?.field) { const { field } = extra; const { formItemConfig } = arrayTableConfig || {}; if (formItemConfig?.name && field) { const list = field?.query?.('..')?.value?.(); if (Array.isArray(list) && list[field?.index]) { recordDataSource = list[field.index]; if (!extraParamList) { extraParamList = [field.index]; } } } } } const realField = field || extra?.field; return makeRequest({ buttonConfig, urlParamsDataSource, recordDataSource: getRealizeValue(recordDataSource), state, needSuccessToast, noNeedHandleResult, extraParamList, position, isDesign, _context, getExtraParam: () => { const tempExtraParam = executeFunction(getExtraParam); let extraParam = {}; if (isPlainObject(tempExtraParam)) { extraParam = { ...tempExtraParam, }; } // const realFormInstance = getRealizeValue(formInstance); // if(realFormInstance && field && position === ButtonPosition.formItemEvent) { // const tempFormValue = realFormInstance.values; // if(tempFormValue) { // const segments = field?.path?.segments; // if(isArrayNotEmpty(segments) && segments.length >= 3) { // const needSegments = segments.slice(0,2) // const tempCurrentRow = get(tempFormValue, needSegments) // if(isPlainObject(tempCurrentRow)) { // extraParam[__arrayTableCurrentRow__] = tempCurrentRow; // } // } // // } // } const realFormInstance = getRealizeValue(formInstance); if ( realFormInstance && realField && [ ButtonPosition.formItemEvent, ButtonPosition.arraySubAreaCardOperate, ].includes(position) ) { const realPath = field?.path?.parent?.()?.segments; if (ButtonPosition.arraySubAreaCardOperate === position) { } const tempCurrentRow = realFormInstance?.getValuesIn?.( field?.path?.parent?.()?.segments, ); if (isPlainObject(tempCurrentRow)) { extraParam[__arrayTableCurrentRow__] = tempCurrentRow; } } return extraParam; }, handleParams: () => { const params = {}; if (position === ButtonPosition.tableOperate) { const { primaryKey } = componentProps; if (primaryKey && record[primaryKey] !== undefined) { params[primaryKey] = record[primaryKey]; } } return params; }, }).then((res) => { if (position !== ButtonPosition.tableToolArea) { if (actionRunEnv === ActionRunEnv.flowAction) { } else if (position === ButtonPosition.tableOperate) { if (keepPagination === true) { tableRef?.tableLoad()?.(); } else { tableRef?.load?.(); } } else { tableRef?.load?.(); } } return res; }); }, handleFlowResult: (res) => { return getRealResponse(res); }, // getButtonNode: (arg) => { // const { buttonConfig, record, index } = arg; // const { optType, options = {}, children } = buttonConfig; // if (children) { // let events = {}; // if (optType) { // const { needConfirm, confirmInfo = {} } = options; // const button = componentMap[optType]; // if (typeof button?.action === 'function') { // const action = button.action.bind(this, arg); // events = { // onClick: needConfirm ? () => { // Dialog.confirm({ // v2: true, // title: confirmInfo.title || '通知', // content: confirmInfo.content || '是否确认', // onOk: action, // cancelProps: { // children: '关闭弹框', // }, // }); // } : action, // }; // } // } // return {children}; // } // return null; // }, }; const batch = { title: '批量操作', value: 'batch', position: [ButtonPosition.tableBatchArea], getPrototypeList: (position) => { let paramSetter = 'StringSetter'; let paramSelectSetter; let jsExpressionSetter; const setterSnippet = getSetterSnippet({ position, optType: 'batch', }); const { requestParamSetter } = setterSnippet || {}; if (requestParamSetter) { paramSetter = requestParamSetter; if (Array.isArray(requestParamSetter?.props?.setters)) { paramSelectSetter = requestParamSetter?.props?.setters?.find( (item) => item?.componentName === 'ParamSelectSetter', ); jsExpressionSetter = requestParamSetter?.props?.setters?.find( (item) => item?.componentName === 'CnRowDataSetter', ); } } return [ ...createServiceSelectPrototype({ optType: 'batch', paramSetter, position, paramSelectSetter, jsExpressionSetter, }), createRequestSuccessPrototype( ButtonPosition.tableBatchAreaAfterRequestSuccess, ), ]; }, action: ({ buttonConfig, selectedRowKeys, selectedRowRecords, tableRef, urlParamsDataSource, recordDataSource, state, position, }) => { if (selectedRowKeys?.length > 0) { return makeRequest({ position, buttonConfig, urlParamsDataSource, recordDataSource, state, extraParamList: [selectedRowKeys, selectedRowRecords], handleParams: (params) => { return { selectedRowKeys, selectedRowRecords, }; }, }).then((res) => { tableRef?.load?.(); }); } else { CnMessage.error( $i18n.get({ id: 'PleaseSelectTableData', dm: '请选择表格数据' }), ); return Promise.reject(); } }, }; const submit = { title: '提交(先校验表单,再发请求)', value: 'submit', position: [ ButtonPosition.formDialog, ButtonPosition.form, ButtonPosition.cardAction, ], getPrototypeList: (position, config) => { let afterRequestPosition; let dynamicUrlTemplate; if (ButtonPosition.formDialog === position) { afterRequestPosition = ButtonPosition.formDialogSubmitAfterRequestSuccess; dynamicUrlTemplate = `function(state, { openDialogMode }) { // openDialogMode: ${openDialogModeLabel}: 新增(new)、编辑(edit)、详情(detail) return '/xxx'; }`; } else if (ButtonPosition.form === position) { afterRequestPosition = ButtonPosition.formSubmitAfterRequestSuccess; } let paramSetter = 'StringSetter'; let paramSelectSetter; let jsExpressionSetter; const setterSnippet = getSetterSnippet({ position, optType: 'submit', ...config, }); const { requestParamSetter } = setterSnippet || {}; if (requestParamSetter) { paramSetter = requestParamSetter; if (Array.isArray(requestParamSetter?.props?.setters)) { paramSelectSetter = requestParamSetter?.props?.setters?.find( (item) => item?.componentName === 'ParamSelectSetter', ); jsExpressionSetter = requestParamSetter?.props?.setters?.find( (item) => item?.componentName === 'CnRowDataSetter', ); } } let afterRequestPrototype; if (afterRequestPosition) { afterRequestPrototype = createRequestSuccessPrototype(afterRequestPosition); } const result = [ ...createServiceSelectPrototype({ optType: 'submit', paramSetter, position, paramSelectSetter, jsExpressionSetter, paramTitleDom: (
请求参数配置{' '} 提示:提交时会默认带上当前表单的全部数据作为参数,无需手动配置
), dynamicUrlTemplate, }), ]; if (afterRequestPrototype) { result.push(afterRequestPrototype); } if ([ButtonPosition.formDialog].includes(position)) { result.push({ name: 'afterRequestNotCloseDialog', title: '请求成功后不关闭弹窗', setter: 'BoolSetter', }); } return result; }, action: (config) => { const { buttonConfig, formInstance, position, close, urlParamsDataSource, recordDataSource, state, _context, dialogRef, needSuccessToast: paramNeedSuccessToast, getExtraParam, getFormInstance, } = config; let realFormInstance = getRealizeValue(formInstance); if (typeof getFormInstance === 'function') { realFormInstance = getRealizeValue(executeFunction(getFormInstance)); } if (buttonConfig && realFormInstance) { if (realFormInstance?.submitting) { } else { let afterRequestPosition; if (ButtonPosition.formDialog === position) { afterRequestPosition = ButtonPosition.formDialogSubmitAfterRequestSuccess; } else if (ButtonPosition.form === position) { afterRequestPosition = ButtonPosition.formSubmitAfterRequestSuccess; } const { options } = buttonConfig || {}; const { afterRequest = {}, requestConfig = {}, afterRequestNotCloseDialog, } = options || {}; const realUrl = getRealRequestUrl({ requestConfig, state, extraParam: getExtraParam?.(), }); if (realUrl) { requestConfig.url = realUrl; requestConfig.dynamicUrl = undefined; requestConfig.useDynamicUrl = undefined; return realFormInstance?.submit((value) => { if (value) { let needSuccessToast = true; if (paramNeedSuccessToast !== undefined) { needSuccessToast = paramNeedSuccessToast; } if (afterRequestPosition && afterRequest?.optType === 'message') { needSuccessToast = false; } if ([ButtonPosition.cardAction].includes(position)) { needSuccessToast = true; } return makeRequest({ buttonConfig, urlParamsDataSource, recordDataSource: value, state, needSuccessToast, getExtraParam, handleParams: () => { return value; }, onCancel: () => { if (realFormInstance?.setSubmitting) { realFormInstance.setSubmitting(false); } }, extraParamList: [ dialogRef?.selectedRowKeys, dialogRef?.selectedRowRecords, ], }) .then((res) => { const { optType } = afterRequest || {}; if (optType && afterRequestPosition) { const action = getButtonAction({ ...afterRequest, position: afterRequestPosition, }); action?.({ position: afterRequestPosition, urlParamsDataSource, recordDataSource: getRealizeValue(recordDataSource), state, buttonConfig: afterRequest, _context, response: res, formInstance: realFormInstance, }); } if (afterRequestNotCloseDialog !== true) { close && close(); } return res; }) .finally((res) => { if (realFormInstance?.setSubmitting) { realFormInstance.setSubmitting(false); } }); } }); } else { return realFormInstance?.validate?.(); } } } }, // getButtonNode: (arg) => { // const { buttonConfig } = arg; // const { optType, options = {}, children } = buttonConfig; // if (children) { // let events = {}; // if (optType) { // const button = componentMap[optType]; // if (typeof button?.action === 'function') { // events = { // onClick: button.action.bind(this, arg), // }; // } // } // return ; // } // return null; // }, }; const cancel = { title: '取消(关闭当前弹窗)', value: 'cancel', position: [ ButtonPosition.dialog, ButtonPosition.formDialog, ButtonPosition.form, ButtonPosition.blockButton, ], action: ({ buttonConfig, formData, open, close }) => { if (buttonConfig) { close && close(); } }, // getButtonNode: (arg) => { // const { buttonConfig } = arg; // const { optType, options = {}, children } = buttonConfig; // if (children) { // let events = {}; // if (optType) { // const button = componentMap[optType]; // if (typeof button?.action === 'function') { // events = { // onClick: button.action.bind(this, arg), // }; // } // } // return ; // } // return null; // }, }; const reset = { title: '重置', value: 'reset', position: [ButtonPosition.formDialog, ButtonPosition.form], action: (config) => { const { buttonConfig, formInstance, position } = config; const realFormInstance = getRealizeValue(formInstance); if (buttonConfig && realFormInstance) { realFormInstance.reset('*'); } }, // getButtonNode: (arg) => { // const { buttonConfig } = arg; // const { optType, options = {}, children } = buttonConfig; // if (children) { // let events = {}; // if (optType) { // const button = componentMap[optType]; // if (typeof button?.action === 'function') { // events = { // onClick: button.action.bind(this, arg), // }; // } // } // return ; // } // return null; // }, }; const dialog = { title: '弹窗', value: 'dialog', position: ALL_BUTTON_POSITION_LIST, action: (config, extra) => { const { arrayTableConfig, buttonConfig, _context, position, componentProps, record, index, selectedRowKeys, selectedRowRecords, response, arrayTableCurrentRow, formProps, } = config || {}; const { _dataSourceName } = formProps || {}; let recordDataSource = record; if (position === ButtonPosition.arraySubAreaCardOperate) { recordDataSource = arrayTableCurrentRow; } else if (!record && extra?.field) { const { field } = extra; const { formItemConfig } = arrayTableConfig || {}; if (position === ButtonPosition.arrayTableCell) { const tempCurrentRow = getArrayTableCurrentRowByField2(field); const fieldName = field?.path?.segments?.[0]; if (fieldName && isPlainObject(tempCurrentRow)) { recordDataSource = cloneDeep(tempCurrentRow); set( _context?.state, `valueOf.${_dataSourceName}.${fieldName}.${__arrayTableCurrentRow__}`, { ...recordDataSource }, ); } } else if (formItemConfig?.name && field) { if (field.path.segments.length === 5) { const path = field.path.segments.slice(0, 4); const tempRow = field?.form?.getValuesIn?.(path); if (isPlainObject(tempRow)) { recordDataSource = cloneDeep(tempRow); } } else { const list = field?.query?.(formItemConfig?.name)?.value?.(); if (Array.isArray(list) && list[field?.index]) { recordDataSource = cloneDeep(list[field.index]); } } } } if (position === ButtonPosition.tableCellAfterRequestSuccess) { recordDataSource = response?.data || {}; } if (buttonConfig && _context) { const { options = {} } = buttonConfig; const { _bindDialog, setCurrentRowToDialog } = options; if (_bindDialog) { const dialogNode = _context.$(_bindDialog); // let data; // if (ButtonPosition.tableOperate === position && dialogNode && _context && record) { // data = record; // const { props = {} } = dialogNode; // const { _dataSourceName } = props; // if (_dataSourceName) { // _context?.setState({ // [_dataSourceName]: record, // }); // } // } let realRecordDataSource = recordDataSource; if (setCurrentRowToDialog === false) { realRecordDataSource = undefined; } return new Promise((resolve) => { setTimeout(() => { const p = dialogNode?.open?.(realRecordDataSource, { buttonConfig, position, selectedRowKeys, selectedRowRecords, }); if (typeof p?.then === 'function') { p.then((res) => { setTimeout(() => { resolve(true); }, 8); }); } else { setTimeout(() => { resolve(true); }, 8); } }); }); // table?.load?.(); } } }, getPrototypeList: (position) => { const result = [ getSelectDialogSnippet(), { name: 'openDialogMode', title: '当一个弹窗复用于新增和编辑多个场景时,你希望本次打开的弹窗用途', setter: { componentName: 'CnSelectSetter', props: { options: getOpenDialogModeEnum({ prefix: '用于', }), selectProps: { hasClear: true, }, }, }, }, ]; if ( [ ButtonPosition.tableOperate, ButtonPosition.arrayTableOperate, ButtonPosition.tableCell, ].includes(position) ) { result.splice(1, 0, { title: '是否将表格当前行数据默认带入到弹窗表单中', name: 'setCurrentRowToDialog', setter: { componentName: 'RadioGroupSetter', props: { options: getCommonBoolDataSource(), }, }, defaultValue: true, }); } return result; }, // getButtonNode: (arg) => { // const { buttonConfig } = arg; // const { optType, options = {}, children } = buttonConfig; // if (children) { // const events = {}; // if (optType) { // // const button = componentMap[optType]; // // if(typeof button?.action === 'function'){ // // events = { // // onClick: button.action.bind(this, arg), // // } // // } // } // return {children}; // } // return null; // }, }; const ossImport = { title: '导入', value: 'ossImport', position: [ButtonPosition.tableToolArea], action: ({ buttonConfig, _context }) => {}, getPrototypeList: () => { return [ { name: 'uploadService', title: '文件上传API', display: 'inline', setter: { componentName: 'ServiceChoiceSetter', props: { buttonText: '选择请求API', params: { env: 'pre', pageSize: 999, // serviceType: 'HSF', }, paramTitleDom: (
请求参数配置: 接口文档
), paramSetter: [ getParamSetterPrototype({ type: 'filter', }), { componentName: 'StringSetter', title: '字符串', }, getJSExpressionPrototype({ type: 'formRequest' }), ], }, }, }, { name: 'createService', title: '创建任务API', display: 'inline', setter: { componentName: 'ServiceChoiceSetter', props: { buttonText: '选择请求API', params: { env: 'pre', pageSize: 999, // serviceType: 'HSF', }, paramTitleDom: (
请求参数配置: 接口文档
), resultProcessFuncTemplate: `function(res) { // 需要返回的如下的数据结构 // return { // success: true, // data: { // jobId: number // } // } return res; }`, paramSetter: [ getParamSetterPrototype({ type: 'filter', }), { componentName: 'StringSetter', title: '字符串', }, getJSExpressionPrototype({ type: 'formRequest' }), ], }, }, }, { name: 'pollingService', title: '任务轮询API', display: 'inline', setter: { componentName: 'ServiceChoiceSetter', props: { buttonText: '选择请求API', params: { env: 'pre', pageSize: 999, // serviceType: 'HSF', }, paramTitleDom: (
请求参数配置: 接口文档
), paramSetter: [ getParamSetterPrototype({ type: 'filter', }), { componentName: 'StringSetter', title: '字符串', }, getJSExpressionPrototype({ type: 'formRequest' }), ], }, }, }, { name: 'templateUrl', title: '导入模板文件的链接', display: 'inline', setter: { componentName: 'MixedSetter', props: { setters: [ { title: '配置文件链接', componentName: 'StringSetter', props: { placeholder: '请填写导入模板文件的url', }, }, { title: '配置请求获取文件链接', componentName: 'ServiceChoiceSetter', props: { buttonText: '选择请求API', params: { env: 'pre', pageSize: 999, // serviceType: 'HSF', }, paramSetter: [ { componentName: 'ParamSelectSetter', props: { dataKey: 'config', labelKey: 'label', valueKey: 'name', groupName: '筛选栏', relativeDataSourceName: '_bindFilterDataSourceName', relativeDataSourceNameKey: '_dataSourceName', }, title: '选择参数', }, { componentName: 'StringSetter', title: '字符串', }, getJSExpressionPrototype({ type: 'formRequest' }), ], }, }, ], }, }, }, { name: 'hideLoop', title: '关闭任务轮询', display: 'inline', setter: { componentName: 'RadioGroupSetter', props: { options: [ { title: '是', value: true }, { title: '否', value: false }, { title: '不设置' }, ], }, }, }, { name: 'dialogDescription', title: '提示信息', display: 'inline', setter: { componentName: 'MixedSetter', props: { setters: [ { title: '文本', componentName: 'CnI18nSetter', }, getJSXTemplate({ position: ButtonPosition.tableToolArea, }), ], }, }, }, ]; }, }; const download = { title: '下载', value: 'download', position: [ ButtonPosition.tableBatchArea, ButtonPosition.subCardAction, ButtonPosition.cardAction, ], getRenderDom: (config) => { const { buttonConfig, recordDataSource, state, urlParamsDataSource, btnProps, } = config || {}; const { children, options, iconType } = buttonConfig || {}; const { url } = options || {}; const formValue = getRealizeValue(recordDataSource) || {}; let downloadProps; if (typeof url === 'function') { downloadProps = { url: executeFunction(url, formValue, state), }; } else { downloadProps = getDownloadProps({ url, extraParams: { state, recordDataSource: getRealizeValue(recordDataSource) || {}, urlParamsDataSource, }, }); } let realChildren = children; if (iconType) { realChildren = ( <> {renderIcon(iconType)} {children} ); } return ( ); }, getPrototypeList: (position, config) => { const setterSnippet = getSetterSnippet({ position, optType: 'download', }); const { requestParamSetter } = setterSnippet || {}; return [ { name: 'url', title: '文件下载链接', display: 'inline', setter: { componentName: 'MixedSetter', props: { setters: [ { componentName: 'StringSetter', title: '纯文本', }, { title: '配置请求获取文件链接', componentName: 'ServiceChoiceSetter', props: { buttonText: '选择请求API', params: { env: 'pre', pageSize: 999, // serviceType: 'HSF', }, paramSetter: requestParamSetter?.props?.setters || [], }, }, getJSExpressionPrototype({ type: 'formRequest', }), ], }, }, }, ]; }, }; const exportButton = { title: '导出', value: 'export', position: [ ButtonPosition.tableToolArea, ButtonPosition.tableBatchArea, window?.__page__?.siteName || window?.siteInfo?.appName === 'Apollo2.0' ? ButtonPosition.tableOperate : null, ], action: ({ buttonConfig, _context }) => {}, getPrototypeList: (position) => { let paramSetter = 'StringSetter'; const setterSnippet = getSetterSnippet({ position, optType: 'export', }); const { requestParamSetter } = setterSnippet || {}; if (requestParamSetter) { paramSetter = requestParamSetter; } return [ { name: 'createService', title: '创建任务API', display: 'inline', setter: { componentName: 'ServiceChoiceSetter', props: { buttonText: '选择请求API', params: { env: 'pre', pageSize: 999, // serviceType: 'HSF', }, paramTitleDom: (
请求参数配置: 接口文档 提示:导出时会默认带上筛选栏的数据作为参数,无需手动配置
), resultProcessFuncTemplate: `function(res) { // 需要返回的如下的数据结构 // return { // success: true, // data: { // jobId: number // } // } return res; }`, paramSetter: [ getParamSetterPrototype({ type: 'filter', }), { componentName: 'StringSetter', title: '字符串', }, getJSExpressionPrototype({ type: 'formRequest' }), ], paramSetter, }, }, }, { name: 'pollingService', title: '任务轮询API', display: 'inline', setter: { componentName: 'ServiceChoiceSetter', props: { buttonText: '选择请求API', params: { env: 'pre', pageSize: 999, // serviceType: 'HSF', }, paramTitleDom: (
请求参数配置: 接口文档
), paramSetter, }, }, }, { name: 'hideLoop', title: '关闭任务轮询', display: 'inline', setter: { componentName: 'RadioGroupSetter', props: { options: [ { title: '是', value: true }, { title: '否', value: false }, { title: '不设置' }, ], }, }, }, { name: 'needRename', title: '自定义导出任务的名称', display: 'inline', setter: { componentName: 'RadioGroupSetter', props: { options: [ { title: '是', value: true }, { title: '否', value: false }, { title: '不设置' }, ], }, }, }, { name: 'defaultJobName', title: '设置导出任务的默认名称', display: 'inline', setter: 'StringSetter', condition(prop) { return prop?.parent?.getPropValue?.('needRename') === true; }, }, { name: 'autoDownload', title: '导出完成后自动下载', display: 'inline', defaultValue: true, setter: { componentName: 'RadioGroupSetter', props: { options: [ { title: '是', value: true }, { title: '否', value: false }, ], }, }, }, ]; }, }; const tableReload = { title: '表格重新请求', value: 'tableReload', position: ALL_BUTTON_POSITION_LIST, getPrototypeList: () => { return [ ...createTableSelectSetters(), { name: 'keepPagination', title: '表格重新请求时保留分页信息', setter: 'BoolSetter', }, { name: 'refreshExceptPaging', title: '表格重新请求时清除勾选数据', setter: 'BoolSetter', condition(prop) { return prop?.parent?.getValue?.()?.keepPagination === true; }, }, ]; }, action: (arg) => { const { buttonConfig, _context } = arg || {}; const { options = {} } = buttonConfig; const { _bindTable, keepPagination, refreshExceptPaging } = options; function reloadOneTable(id) { if (typeof id === 'string') { const table = _context.$(id); if (keepPagination === true && refreshExceptPaging === true) { table?.refreshExceptPaging()?.(); } else if (keepPagination === true) { table?.tableLoad()?.(); } else { table?.load?.(); } } } if (_bindTable && _context) { if (Array.isArray(_bindTable)) { _bindTable.forEach((item) => { reloadOneTable(item); }); } else { reloadOneTable(_bindTable); } } }, }; const arrayTableRemove = { title: '删除', value: 'arrayTableRemove', position: [ButtonPosition.arrayTableOperate], action: (config) => { const { field } = config || {}; if (typeof field?.parent?.remove === 'function') { const segments = field?.path?.segments; let currentIndex = +segments?.[1]; if (typeof currentIndex !== 'number') { currentIndex = segments?.[segments?.length - 2]; } if (typeof currentIndex === 'number') { field?.parent?.remove(currentIndex); } } }, }; const arrayTableMoveUp = { title: '上移', value: 'arrayTableMoveUp', position: [ButtonPosition.arrayTableOperate], }; const arrayTableMoveDown = { title: '下移', value: 'arrayTableMoveDown', position: [ButtonPosition.arrayTableOperate], }; const arrayTableAdd = { title: '添加一行', value: 'arrayTableAdd', position: [ButtonPosition.arrayTableOperate], getPrototypeList: (position) => { return [ { name: 'defaultValue', title: '添加一行时的默认值', display: 'block', setter: { componentName: 'MixedSetter', props: { setters: [ { componentName: 'ArraySetter', props: { mode: 'list', itemSetter: { componentName: 'ObjectSetter', props: { config: { items: [ { name: 'label', display: 'inline', title: '字段名', isRequired: true, setter: { componentName: 'SelectSetter', props: (field) => { const options = []; const arrayTableConfig = field?.parent?.parent?.parent?.parent?.parent?.parent?.getPropValue?.( 'config', ); if ( Array.isArray(arrayTableConfig) && arrayTableConfig.length > 0 ) { arrayTableConfig.forEach((item) => { const { label, name } = item || {}; if (name !== '_index' && name) { options.push({ label: handleI18nLabel(label) || name, value: name, }); } }); } return { showSearch: true, options, }; }, }, }, { name: 'value', display: 'inline', title: '默认值', isRequired: true, initialValue: 'value', setter: { componentName: 'MixedSetter', props: { setters: [ { componentName: 'StringSetter', title: '字符串', }, { componentName: 'NumberSetter', title: '数字', }, { componentName: 'BoolSetter', title: '布尔(true/false)', }, getJSExpressionPrototype({ type: 'formRequest', }), ], }, }, }, ], }, }, }, }, }, getJSExpressionPrototype({ type: 'base', }), ], }, }, }, ]; }, action: ({ buttonConfig, formData, open, close }) => { if (buttonConfig) { } }, }; const arraySubAreaCardAdd = { title: '添加', value: 'arraySubAreaCardAdd', position: [ButtonPosition.arraySubAreaCardOperate], getPrototypeList: (position) => { return [ // { // name: 'defaultValue', // title:'添加一行时的默认值', // display:'block', // setter:{ // componentName: 'ArraySetter', // props: { // mode: 'list', // itemSetter: { // componentName: 'ObjectSetter', // props: { // config: { // items: [ // { // name: 'label', // display: 'inline', // title: '字段名', // isRequired: true, // setter:{ // componentName: 'SelectSetter', // props: (field)=>{ // const options = []; // const arrayTableConfig = field?.parent?.parent?.parent?.parent?.parent?.parent?.getPropValue?.('config'); // if(Array.isArray(arrayTableConfig) && arrayTableConfig.length > 0) { // arrayTableConfig.forEach(item=>{ // const { label, name } = item || {}; // if(name !== '_index' && name) { // options.push({ // label: handleI18nLabel(label) || name, // value: name, // }) // } // }) // } // return { // showSearch: true, // options, // } // } // } // }, // { // name: 'value', // display: 'inline', // title: '默认值', // isRequired: true, // initialValue: 'value', // setter: { // componentName: 'MixedSetter', // props: { // setters: [ // { // componentName:'StringSetter', // title:'字符串', // }, // { // componentName:'NumberSetter', // title:'数字', // }, // { // componentName:'BoolSetter', // title:'布尔(true/false)', // }, // ], // }, // } // }, // ], // }, // }, // }, // }, // }, // }, ]; }, action: ({ buttonConfig, formData, open, close }) => { if (buttonConfig) { } }, }; const arraySubAreaCardRemove = { title: '删除', value: 'arraySubAreaCardRemove', position: [ButtonPosition.arraySubAreaCardOperate], action: (config) => { const { arrayBaseField, arrayBaseFieldIndex } = config || {}; if ( typeof arrayBaseField?.remove === 'function' && typeof arrayBaseFieldIndex === 'number' ) { arrayBaseField.remove(arrayBaseFieldIndex); } }, }; const arraySubAreaCardMoveUp = { title: '上移', value: 'arraySubAreaCardMoveUp', position: [ButtonPosition.arraySubAreaCardOperate], action:(config)=>{ const { arrayBaseField, arrayBaseFieldIndex } = config || {} if(arrayBaseField) { if(arrayBaseField?.disabled === true || arrayBaseField?.pattern !== 'editable') { return } arrayBaseField?.moveUp(arrayBaseFieldIndex); } } }; const arraySubAreaCardMoveDown = { title: '下移', value: 'arraySubAreaCardMoveDown', position: [ButtonPosition.arraySubAreaCardOperate], action:(config)=>{ const { arrayBaseField, arrayBaseFieldIndex } = config || {} if(arrayBaseField) { if(arrayBaseField?.disabled === true || arrayBaseField?.pattern !== 'editable') { return } arrayBaseField?.moveDown(arrayBaseFieldIndex); } } }; const message = { title: '提示信息(toast)', value: 'message', position: ALL_BUTTON_POSITION_LIST, getPrototypeList: (position, config) => { return createMessageSetters({ position, isToast: true, config }); }, action: (config) => { const { buttonConfig, urlParamsDataSource, state, _context, recordDataSource, actionRunEnv, getFlowActionInfo, position, } = config || {}; let { response = {} } = config || {}; if (ActionRunEnv.flowAction === actionRunEnv) { const flowInfo = getFlowActionInfo?.(); const { flowList, currentFlowIndex } = flowInfo || {}; if (isArrayNotEmpty(flowList) && currentFlowIndex) { const realIndex = +currentFlowIndex; if (isNumber(realIndex) && !isNaN(realIndex)) { const beforeList = flowList.slice(0, realIndex); let path = 'request'; const lastRequestIndex = findLastIndex( beforeList, (item) => { if(item?.optType === 'request') { return true; }else if(item?.optType === 'submit') { path = 'submit' return true; } return false; }, ); if (lastRequestIndex !== 0) { path += lastRequestIndex; } const realResponse = state?.valueOf?.[path]; if (isPlainObject(realResponse)) { response = realResponse; } } } } const msg = response?.msg; const { options = {} } = buttonConfig || {}; const { type, title, content, ...rest } = options; let realContent = content; const realType = calculateTextExprValue(type, { urlParamsDataSource, recordDataSource: getRealizeValue(recordDataSource), state, }) || 'success'; if (typeof content === 'function') { let realFirstParam = response; if ( [ ButtonPosition.formItemEvent, ButtonPosition.formDialogItemEvent, ].includes(position) ) { realFirstParam = getRealizeValue(recordDataSource); } realContent = content(realFirstParam, state); } if (!realContent && !title) { realContent = msg; } CnMessage?.[realType]?.({ title, content: realContent, ...rest }); }, }; const confirm = { title: '带确认的提示信息(confirm)', value: 'confirm', position: [ButtonPosition.tableBatchAreaAfterRequestSuccess], getPrototypeList: (position) => { return createMessageSetters({ isConfirm: true }); }, action: (config) => { const { response = {}, buttonConfig, urlParamsDataSource, state, _context, } = config || {}; const msg = response?.msg; const { options = {} } = buttonConfig || {}; const { type = 'success', title, content } = options; let realContent = content; if (typeof content === 'function') { realContent = content(response, state); } if (!realContent && !title) { realContent = msg; } CnDialog?.[type]?.({ title, content: realContent, }); }, }; const formReload = { title: '表单重新请求', value: 'formReload', position: ALL_BUTTON_POSITION_LIST, getPrototypeList: () => { return createFormSelectSetters({ mode: 'multiple', }); }, action: (arg) => { const { buttonConfig, _context } = arg || {}; const { options = {} } = buttonConfig; const { _bindForm } = options; function reloadOneForm(id) { if (typeof id === 'string') { const form = _context.$(id); form?.load?.(); } } if (_bindForm && _context) { if (Array.isArray(_bindForm)) { _bindForm.forEach((item) => { reloadOneForm(item); }); } else { reloadOneForm(_bindForm); } } }, }; const componentReload = { title: '组件重新请求', value: 'componentReload', position: ALL_BUTTON_POSITION_LIST, getPrototypeList: () => { return createComponentSelectSetters({ mode: 'multiple', containsKey: ['isCnList', 'isCnStep'], }); }, action: (arg) => { const { buttonConfig, _context } = arg || {}; const { options = {} } = buttonConfig; const { _bindComponent } = options; function reloadOneComponent(id) { if (typeof id === 'string') { const com = _context.$(id); com?.load?.(); } } if (_bindComponent && _context) { if (Array.isArray(_bindComponent)) { _bindComponent.forEach((item) => { reloadOneComponent(item); }); } else { reloadOneComponent(_bindComponent); } } }, }; const filterReset = { title: '筛选栏重置', value: 'filterReset', position: [ ButtonPosition.tabEvent, ButtonPosition.dialog, ButtonPosition.blockButton, ], getPrototypeList: () => { return createFilterSelectSetters({ mode: 'multiple', }); }, action: (arg) => { const { buttonConfig, _context } = arg || {}; const { options = {} } = buttonConfig; const { _bindFilter } = options; function reloadOneFilter(id) { if (typeof id === 'string') { const filter = _context.$(id); filter?.reset?.(); } } if (_bindFilter && _context) { if (Array.isArray(_bindFilter)) { _bindFilter.forEach((item) => { reloadOneFilter(item); }); } else { reloadOneFilter(_bindFilter); } } }, }; const filterSearch = { title: '筛选栏查询', value: 'filterSearch', position: ALL_BUTTON_POSITION_LIST, getPrototypeList: () => { return createFilterSelectSetters({ mode: 'multiple', }); }, action: (arg) => { const { buttonConfig, _context } = arg || {}; const { options = {} } = buttonConfig; const { _bindFilter } = options; function searchOneFilter(id) { if (typeof id === 'string') { const filter = _context.$(id); filter?.search?.(); } } if (_bindFilter && _context) { if (Array.isArray(_bindFilter)) { _bindFilter.forEach((item) => { searchOneFilter(item); }); } else { searchOneFilter(_bindFilter); } } }, }; const setFormData = { title: '将请求数据(res.data)填入表单', value: 'setFormData', position: [ ButtonPosition.formDialogSubmitAfterRequestSuccess, ButtonPosition.formSubmitAfterRequestSuccess, ], action: (arg) => { const { formInstance, response } = arg || {}; if (formInstance && response) { const { success, data } = response; if (success && isPlainObject(data)) { formInstance.setValues?.(data, 'overwrite'); } } }, }; const locationReload = { title: '刷新页面(location.reload)', value: 'locationReload', position: ALL_BUTTON_POSITION_LIST, action: (arg) => { location?.reload?.(); }, }; const textRender = { title: '展示文本', value: 'textRender', position: [ ButtonPosition.tableToolArea, ButtonPosition.tableBatchArea, ButtonPosition.formDialog, ButtonPosition.dialog, ButtonPosition.form, ButtonPosition.step, ButtonPosition.pageRightButton, ButtonPosition.blockButton, ], getRenderDom: (config) => { if (config) { const { buttonConfig, state, position, selectedRowKeys, selectedRowRecords, recordDataSource, } = config; const { options, children } = buttonConfig || {}; const { content, color } = options || {}; let realContent = children; if (typeof content === 'string' && content.length > 0) { realContent = content; } else if (typeof content === 'function') { if ( [ ButtonPosition.tableBatchArea, ButtonPosition.tableToolArea, ].includes(position) ) { realContent = executeFunction( content, recordDataSource, state, selectedRowKeys, selectedRowRecords, ); } else { const formValue = getRealizeValue(recordDataSource); realContent = executeFunction(content, formValue || {}, state); } } const style = { display: 'inline-block', }; if (color) { style.color = color; } return ( {realContent} ); } }, getPrototypeList: (position) => { return [ { name: 'content', title: '内容', setter: { componentName: 'MixedSetter', props: { setters: [ { componentName: 'CnI18nSetter', title: '字符串', }, getJSXTemplate({ position, }), ], }, }, }, { name: 'color', title: '文本颜色', setter: { componentName: 'CnSelectSetter', props: { options: [ { label: '绿色', value: '#1ad78c', }, { label: '黄色', value: '#ff9f00', }, { label: '红色', value: '#ff4b4b', }, { label: '蓝色', value: '#4576f5', }, ], selectProps: { hasClear: true, }, }, }, }, ]; }, }; const tableLoop = { title: '表格轮询', value: 'tableLoop', position: [ButtonPosition.tableToolArea, ButtonPosition.tableBatchArea], getDefaultProps: () => { return { active: true, interval: 5, }; }, getRenderDom: (config) => { useEffect(() => { const { options, tableRef, isDesign, state } = config || {}; const { active, interval, keepPagination, stopLoop } = options; const isActive = isFunction(active) ? executeFunction(active, {}, state) : active; let loopId; function doStopLoop() { const stop = calculateTextExprValue(stopLoop, { recordDataSource: {}, state, }); if (stop === true && loopId) { clearInterval(loopId); } } function loopOneTable() { loopId = setInterval(() => { if (keepPagination === true) { tableRef?.tableLoad()?.(); } else { tableRef?.load?.(); } tableRef ?.getRemoteOperation?.() ?.current?.innerInfo?.setLoading?.(false); doStopLoop(); }, interval * 1000); } if ( !isDesign && isActive && tableRef?.load && typeof interval === 'number' && interval >= 2 ){ loopOneTable(); } return () => { if (loopId !== undefined) { clearInterval(loopId); } }; }, []); return null; }, getPrototypeList: (position) => { return [ { name: 'active', title: '启用', display: 'inline', setter: { componentName: 'MixedSetter', props: { setters: [ { componentName: 'BoolSetter', title: '开关启用', }, getJSExpressionPrototype({ type: 'base' }), ], }, }, }, { name: 'interval', title: '轮询间隔时间(单位秒)', display: 'inline', setter: 'NumberSetter', }, { name: 'keepPagination', title: '表格重新请求时保留分页信息', setter: 'BoolSetter', }, { name: 'stopLoop', title: '何时终止轮询', display: 'inline', setter: { componentName: 'MixedSetter', props: { setters: [ getJSExpressionPrototype({ type: 'base', }), ], }, }, }, ]; }, }; const tableLoop2 = { title: '表格轮询', value: 'tableLoop2', position: [ ButtonPosition.form, ButtonPosition.formDialog, ButtonPosition.tableOperate, ButtonPosition.pageDidMount, ], getDefaultProps: () => { return { active: true, interval: 5, }; }, getPrototypeList: (position) => { return [ ...createTableSelectSetters(), { name: 'active', title: '启用', display: 'inline', setter: 'BoolSetter', }, { name: 'interval', title: '轮询间隔时间(单位秒)', display: 'inline', setter: 'NumberSetter', }, { name: 'stopLoop', title: '何时终止轮询', display: 'inline', setter: { componentName: 'MixedSetter', props: { setters: [ getJSExpressionPrototype({ type: 'base', }), ], }, }, }, ]; }, action: (config) => { const { buttonConfig, _context, state, urlParamsDataSource } = config || {}; const { options } = buttonConfig || {}; const { _bindTable, active, interval, stopLoop } = options || {}; function doStopLoop(id) { const stop = calculateTextExprValue(stopLoop, { urlParamsDataSource, recordDataSource: {}, state, }); const isLooping = componentLoopMap[id]; if (stop === true && typeof isLooping === 'number') { clearInterval(isLooping); componentLoopMap[id] = undefined; } } function loopOneTable(id) { if (typeof id === 'string') { const table = _context.$(id); if (table) { const isLooping = componentLoopMap[id]; if ( isLooping === undefined && active && typeof interval === 'number' ) { componentLoopMap[id] = setInterval(() => { table.load?.(); table ?.getRemoteOperation?.() ?.current?.innerInfo?.setLoading?.(false); doStopLoop(id); }, interval * 1000); } } } } if (isArrayNotEmpty(_bindTable) && _context) { _bindTable.forEach((item) => { loopOneTable(item); }); } }, }; const setTableSelectRowKeys = { title: '设置表格选中项', value: 'setTableSelectRowKeys', position: ALL_BUTTON_POSITION_LIST, getPrototypeList: (position, config) => { const { flowList, currentFlowIndex } = config || {}; return [ ...createTableSelectSetters(), { name: 'selectedRowKeys', display: 'inline', title: '设置选中项', className: 'cn-param-select-setter', setter: { componentName: 'MixedSetter', props: { setters: [ { componentName: 'ParamSelectSetter', props: { configList: [ { groupName: '其他数据', groupExprName: __dataSource__, needSecondParam: true, }, { groupName: '动作编排的数据', groupExprName: __flowData__, needSecondParam: true, flowList, currentFlowIndex, }, ], }, title: '从数据源选择', }, getJSExpressionPrototype({ type: 'base', prototypeConfig: config, }), ], }, }, }, ]; }, action: (config) => { const { buttonConfig, _context, state, urlParamsDataSource } = config || {}; const { options } = buttonConfig || {}; const { _bindTable, selectedRowKeys } = options || {}; function selectOneTable(id, keys) { if (typeof id === 'string') { const table = _context.$(id); if (table) { const innerInfo = table.getRemoteOperation?.()?.current?.innerInfo; if (innerInfo) { innerInfo?.setSelectKeys(keys); } } } } if (isArrayNotEmpty(_bindTable) && _context && selectedRowKeys) { const realSelectedRowKeys = calculateTextExprValue(selectedRowKeys, { urlParamsDataSource, recordDataSource: {}, state, }); if (isArrayNotEmpty(realSelectedRowKeys)) { _bindTable.forEach((item) => { selectOneTable(item, realSelectedRowKeys); }); } } }, }; const setTableOpenKeys = { title: '设置表格展开项', value: 'setTableOpenKeys', position: ALL_BUTTON_POSITION_LIST, getPrototypeList: (position, config) => { const { flowList, currentFlowIndex } = config || {}; return [ ...createTableSelectSetters(), { name: 'openKeys', display: 'inline', title: '设置展开项', className: 'cn-param-select-setter', setter: { componentName: 'MixedSetter', props: { setters: [ { componentName: 'ParamSelectSetter', props: { configList: [ { groupName: '其他数据', groupExprName: __dataSource__, needSecondParam: true, }, { groupName: '动作编排的数据', groupExprName: __flowData__, needSecondParam: true, flowList, currentFlowIndex, }, ], }, title: '从数据源选择', }, getJSExpressionPrototype({ type: 'base', prototypeConfig: config, }), ], }, }, }, ]; }, action: (config) => { const { buttonConfig, _context, state, urlParamsDataSource } = config || {}; const { options } = buttonConfig || {}; const { _bindTable, openKeys } = options || {}; function selectOneTable(id, keys) { if (typeof id === 'string') { const table = _context.$(id); if (table) { const innerInfo = table.getRemoteOperation?.()?.current?.innerInfo; if (innerInfo) { innerInfo?.setTreeKeys(keys); } } } } if (isArrayNotEmpty(_bindTable) && _context && openKeys) { const realOpenKeys = calculateTextExprValue(openKeys, { urlParamsDataSource, recordDataSource: {}, state, }); if (isArrayNotEmpty(realOpenKeys)) { _bindTable.forEach((item) => { selectOneTable(item, realOpenKeys); }); } } }, }; const flowAction = { title: '动作编排', value: 'flowAction', position: ALL_BUTTON_POSITION_LIST, getPrototypeList: (position) => { return [ { name: 'flowList', title: '动作编排', display: 'plain', setter: createFlowListSetters({ position, activeSetter: { componentName: 'MixedSetter', props: { setters: [ { componentName: , title: '启用/禁用', }, { componentName: ( ), props(field) { const flowList = field?.parent?.parent?.getValue?.(); const index = field?.parent?.name; return { configList: [ { groupName: '动作编排的数据', groupExprName: __flowData__, needSecondParam: true, flowList, currentFlowIndex: index, }, { groupName: '其他数据', groupExprName: __dataSource__, needSecondParam: true, }, ], }; }, title: '简单表达式', }, { title: '写js表达式', componentName: 'CnRowDataSetter', props(field) { const stateList = getDataSourceListWithAllPath({ needChildren: true, prototypeConfig: { flowList: field?.parent?.parent?.getValue?.(), currentFlowIndex: field?.parent?.name, }, }); return { list: stateList, initialCode: `(arg, state) => { // return state.urlParams.xxx; }`, tip: ` state:全部的数据,在左侧列表中选择使用。 `, }; }, }, ], }, }, }), }, ]; }, action: (config, ...otherArgs) => { const { buttonConfig, position, _context } = config || {}; const { options } = buttonConfig || {}; const { flowList } = options; if (Array.isArray(flowList) && flowList.length > 0) { async function executeFlowList(list) { const result = []; for (const index in list) { const item = list[index]; const { active, optType, options: itemOptions } = item || {}; const isActive = executeObjectExpr( active, { [__dataSource__]: _context?.state, }, {}, _context?.state, ); if (isActive === true) { let action = getButtonAction({ ...item, position, }); if (!action) { const componentDefine = getRunTimeItem(optType); const component = getRealizeValue(componentDefine?.component); if (typeof component?.action === 'function') { action = component.action; } } let flowResult; if (typeof action === 'function') { flowResult = await action( { needSuccessToast: false, ...config, buttonConfig: { ...item }, // 动作执行的环境 actionRunEnv: 'flowAction', getFlowActionInfo: () => { return { flowList, currentFlowIndex: index, }; }, }, ...otherArgs, ); } const handleFlowResult = getItem( position, optType, 'handleFlowResult', ); if (typeof handleFlowResult === 'function') { flowResult = handleFlowResult(flowResult); } if (flowResult && _context) { let realIndex = +index; if (realIndex === 0) { realIndex = ''; } _context.state.valueOf[optType + realIndex] = flowResult; } result.push(flowResult); } } return result; } if (_context?.state) { const flowDataKeys = Object.keys(_context.state.valueOf); if (Array.isArray(flowDataKeys) && flowDataKeys.length > 0) { flowDataKeys.forEach((key) => { if (key) { if (key.includes('$$$') || key.startsWith('Cn')) { } else { _context.state.valueOf[key] = undefined; } } }); } } executeFlowList(flowList); // try { // }catch (e){ // console.log('flow action run error', e); // } } }, }; const setFormValue = { title: '给表单设置数据', value: 'setFormValue', position: ALL_BUTTON_POSITION_LIST, getDefaultProps: () => { return { mode: 'merge', }; }, getPrototypeList: (position, config) => { const { flowList, currentFlowIndex } = config || {}; let jsExpressionPrototype = getJSExpressionPrototype({ type: 'formRequest', prototypeConfig: config, }); if ([ButtonPosition.cnArrayTableItemEvent].includes(position)) { jsExpressionPrototype = getJSExpressionPrototype({ type: 'arrayTableCurrentRowRequest', prototypeConfig: config, }); } return [ ...createFormSelectSetters({ mode: 'single', }), getFormHandleTypeSetterSnippet(), // { // name:'mode', // title:'新数据填入表单的方式', // setter: { // componentName: 'RadioGroupSetter', // props: { // options: [ // { // title: '和原表单值合并', // value: 'merge', // }, // { // title: '清空表单重新设值', // value: 'overwrite', // }, // ], // }, // }, // }, { name: 'formValues', title: '要填入表单的数据', className: 'cn-button-url-param-setter', condition(prop) { return ( prop?.parent?.getPropValue?.('handleType') === 'setFormFieldValue' ); }, originalCondition(prop) { return ( prop?.parent?.getPropValue?.('handleType') === 'setFormFieldValue' ); }, setter: { title: '给表单每个字段设置数据', componentName: 'ArraySetter', props: { mode: 'list', itemSetter: { componentName: 'ObjectSetter', // initialValue: { // }, props: { config: { items: [ getFieldSelectSetterSnippet(), { name: 'value', display: 'inline', title: '数据', isRequired: true, className: 'cn-param-select-setter', setter: { componentName: 'MixedSetter', props: { setters: [ { componentName: 'ParamSelectSetter', props: { ParamSelectSetterComponent: ParamSelectSetter, configList: [ { groupName: '其他数据', groupExprName: __dataSource__, needSecondParam: true, }, { groupName: '动作编排的数据', groupExprName: __flowData__, needSecondParam: true, flowList, currentFlowIndex, }, ], }, title: '从数据源选择', }, jsExpressionPrototype, ], }, }, }, ], }, }, }, }, }, }, { name: 'allFormValues', display: 'inline', condition(prop) { return ( prop?.parent?.getPropValue?.('handleType') === 'setAllFormValue' ); }, originalCondition(prop) { return ( prop?.parent?.getPropValue?.('handleType') === 'setAllFormValue' ); }, title: '新的表单数据', className: 'cn-param-select-setter', // className: 'cn-button-url-param-setter', setter: { componentName: 'MixedSetter', props: { setters: [ { componentName: 'ParamSelectSetter', props: { configList: [ { groupName: '其他数据', groupExprName: __dataSource__, needSecondParam: true, }, { groupName: '动作编排的数据', groupExprName: __flowData__, needSecondParam: true, flowList, currentFlowIndex, }, ], }, title: '从数据源选择', }, { componentName: 'StringSetter', title: '字符串', }, { componentName: 'NumberSetter', title: '数字', }, getJSExpressionPrototype({ type: 'formRequest', prototypeConfig: config, }), ], }, }, }, ]; }, action: (config) => { const { buttonConfig, urlParamsDataSource, state, _context, field, position, arrayBaseFieldIndex, parentComponentName, } = config || {}; const { options } = buttonConfig || {}; const { formValues, _bindForm, handleType, allFormValues } = options || {}; if (_bindForm) { const formNode = _context?.$(_bindForm); const formInstance = formNode?.getFormInstance?.(); if (formInstance) { const oldFormValue = cloneDeep(formInstance?.values); if (handleType === 'clearFormValue') { formInstance.setValues?.({}, 'overwrite'); } else if (handleType === 'setAllFormValue') { const newFormValue = calculateTextExprValue(allFormValues, { urlParamsDataSource, recordDataSource: oldFormValue, state, }); if (isPlainObject(newFormValue)) { formInstance.setValues?.(newFormValue, 'overwrite'); } } else { let newFormValue; let extraParamList = [{}]; if ( [ButtonPosition.formItemEvent].includes(position) && ['CnArrayTable'].includes(parentComponentName) ) { extraParamList = [ { [__arrayTableCurrentRow__]: getArrayTableCurrentRowByField2(field) || {}, }, ]; } if (Array.isArray(formValues)) { if (formValues.length > 0) { const arrayTableValues = []; const notArrayTableValues = []; formValues.forEach((item) => { if (item?.label?.includes(__arrayTableCurrentRow__)) { arrayTableValues.push(item); } else { notArrayTableValues.push(item); } }); const temp = handleRequestParams(notArrayTableValues, { urlParamsDataSource, recordDataSource: oldFormValue || {}, state, extraParamList, }); if (isArrayNotEmpty(arrayTableValues)) { let fieldIndex; if (position === ButtonPosition.arraySubAreaCardOperate) { fieldIndex = arrayBaseFieldIndex; } else if (field) { fieldIndex = field?.path?.segments?.[1]; } if (typeof fieldIndex === 'number') { const tempFormValue = { ...oldFormValue, ...temp }; arrayTableValues.forEach((aitem) => { const { label, value } = aitem || {}; const arr = label?.split?.(`.${__arrayTableCurrentRow__}.`); if (arr.length === 2) { const fieldName = arr[0]; const arrayTableFieldName = arr[1]; const temp2 = handleRequestParams([aitem], { urlParamsDataSource, recordDataSource: tempFormValue, state, extraParamList, }); if ( fieldName && arrayTableFieldName && tempFormValue[fieldName]?.[fieldIndex] ) { tempFormValue[fieldName][fieldIndex][ arrayTableFieldName ] = temp2[label]; temp[fieldName] = tempFormValue[fieldName]; } } }); } } if (isPlainObject(temp)) { newFormValue = temp; } } } formInstance.setValues?.(newFormValue); } } } return Promise.resolve(); }, }; const loadDynamicFormConfig = { title: '动态加载表单', value: 'loadDynamicFormConfig', position: [ ButtonPosition.formItemEvent, ButtonPosition.formDialogItemEvent, ButtonPosition.treeEvent, ButtonPosition.filterEvent, ], getPrototypeList: (position, config) => { const paramSelectSetter = getSelectParamSelectSetter({ position }); const result = [ { name: 'requestConfig', title: '查询服务', display: 'inline', setter: { componentName: 'ServiceChoiceSetter', props: { paramTitleDom:
请求参数配置:
, // responseDom:
// 请求返回结果的数据结构:接口文档 接口预览} // > //
// //
//
//
, buttonText: '选择请求API', params: { env: 'pre', pageSize: 999, // serviceType: 'HSF', }, paramSetter: { componentName: 'MixedSetter', props: { setters: [ paramSelectSetter, { componentName: 'StringSetter', title: '字符串', }, getJSExpressionPrototype({ type: 'formRequest' }), ], }, }, }, }, }, ]; if (ButtonPosition.treeEvent === position) { result.unshift(...createFormSelectSetters({ mode: 'multiple' })); } return result; }, action: (config) => { const { buttonConfig, urlParamsDataSource, state, _context, formRef, recordDataSource, isDesign, } = config || {}; const { options } = buttonConfig || {}; const { requestConfig, _bindForm } = options || {}; const realFormRef = getRealizeValue(formRef); if (requestConfig?.url) { function reloadOne(ref) { const tempConfig = transRequestConfigToRemote({ requestConfig, state, urlParamsDataSource, recordDataSource: getRealizeValue(recordDataSource), isDesign, }); const formatResult = handleResultProcessFunc(requestConfig); if (typeof formatResult === 'function') { tempConfig.formatResult = formatResult; } ref?.reLoad?.(tempConfig); } if (realFormRef) { reloadOne(realFormRef); } else if (isArrayNotEmpty(_bindForm)) { _bindForm.forEach((id) => { if (typeof id === 'string' && id) { const tempFormRef = _context?.$(id)?.getFormRef?.(); reloadOne(tempFormRef); } }); } } }, }; const buttonGroup = { title: '按钮组', value: 'buttonGroup', position: [ButtonPosition.tableBatchArea, ButtonPosition.tableToolArea], getRenderDom: (config) => { const { state, children, optType, options = {}, position, selectedRowKeys, selectedRowRecords, makeButton, } = config; const { buttonList } = options; const menu = []; if (Array.isArray(buttonList) && buttonList.length > 0 && makeButton) { buttonList.forEach((item, index) => { const tempButton = makeButton(item, position, { buttonProps: { text: true, }, }); if (tempButton) { const { disabled, onClick } = tempButton; if (isPlainObject(tempButton) && onClick) { const isDisabled = executeObjectExpr(disabled, {}, selectedRowKeys); menu.push( {tempButton.children} , ); } else if (typeof tempButton === 'function') { const tempButton2 = executeFunction( tempButton, selectedRowKeys, selectedRowRecords, ); if (tempButton2) { menu.push( {tempButton2}, ); } } } }); } return ( {menu} ); }, getPrototypeList: (position) => { return [ { name: 'buttonList', title: '按钮组', display: 'plain', setter: createButtonListSetters({ position, excludeButtonList: ['buttonGroup'], }), }, ]; }, action: (arg) => {}, }; const setSelectDataSource = { title: '给选择框/树选择/级联选择设置下拉列表', value: 'setSelectDataSource', position: [ ButtonPosition.formItemEvent, ButtonPosition.formDialogItemEvent, ButtonPosition.cnArrayTableItemEvent, ButtonPosition.filterItemEvent, ], getPrototypeList: (position, config) => { const { flowList, currentFlowIndex } = config || {}; let jsExpressionPrototype = getJSExpressionPrototype({ type: 'formRequest', prototypeConfig: config, }); if (ButtonPosition.cnArrayTableItemEvent === position) { jsExpressionPrototype = getJSExpressionPrototype({ type: 'arrayTableCurrentRow', prototypeConfig: config, }); } return [ { name: 'toSetDataSourceList', title: '给选择框设置下拉列表', className: 'cn-button-url-param-setter', setter: { componentName: 'MixedSetter', props: { setters: [ { componentName: 'ArraySetter', props: { mode: 'list', itemSetter: { componentName: 'ObjectSetter', // initialValue: { // }, props: { config: { items: [ { name: 'label', display: 'inline', title: '选择字段', isRequired: true, setter: { componentName: 'CnTreeSelectSetter', props: (field) => { const dataSource = []; const config = field ?.getNode?.() .getPropValue?.('config'); if ( Array.isArray(config) && config.length > 0 ) { config.forEach((item) => { if (item?.name) { const temp = { label: handleI18nLabel(item?.label) || item.name, value: item.name, }; dataSource.push(temp); if ( item?.componentName === 'CnArrayTable' ) { const children = getArrayTableFieldList( { config: item?.options?.config, arrayTableName: item.name, }, ); if (isArrayNotEmpty(children)) { temp.children = children; } } } }); } return { dataSource, popupClassName: 'cn-tree-select-setter-pupup', }; }, }, }, { name: 'value', display: 'inline', title: '下拉列表数据', isRequired: true, className: 'cn-param-select-setter', setter: { componentName: 'MixedSetter', props: { setters: [ { componentName: 'ParamSelectSetter', props: { configList: [ { groupName: '其他数据', groupExprName: __dataSource__, needSecondParam: true, }, { groupName: '动作编排的数据', groupExprName: __flowData__, needSecondParam: true, flowList, currentFlowIndex, }, ], }, title: '从数据源选择', }, { componentName: 'StringSetter', title: '字符串', }, { componentName: 'NumberSetter', title: '数字', }, jsExpressionPrototype, ], }, }, }, ], }, }, }, }, }, // getJSExpressionPrototype({type:'base'}) ], }, }, }, ]; }, action: (arg) => { const { buttonConfig, _context, formInstance, urlParamsDataSource, recordDataSource, state, componentProps, field, } = arg || {}; const { options } = buttonConfig || {}; const { toSetDataSourceList } = options || {}; const realFormInstance = getRealizeValue(formInstance); if (realFormInstance) { if ( Array.isArray(toSetDataSourceList) && toSetDataSourceList.length > 0 ) { const temp = handleRequestParams(toSetDataSourceList, { urlParamsDataSource, recordDataSource: getRealizeValue(recordDataSource), state, extraParamList: [ { __arrayTableCurrentRow__: getArrayTableCurrentRowByField2(field) || {}, }, ], }); if (isPlainObject(temp)) { const newValue = cloneDeep(temp); for (const key in newValue) { if (key) { let newDataSource = newValue[key]; if (!Array.isArray(newDataSource)) { newDataSource = []; } let newKey = key; let newIndex; if (key.includes(__arrayTableCurrentRow__)) { const segments = field?.path?.segments; if (isArrayNotEmpty(segments)) { newIndex = +segments[segments.length - 2]; } newKey = key.replace(__arrayTableCurrentRow__, newIndex); } const { _dataSourceName } = componentProps || {}; if (_dataSourceName) { const selectRef = formComponentRefStorage[ `${_dataSourceName}${componentRefSplit}${newKey}` ]; if ( typeof selectRef?.current?.mutateDataSource === 'function' ) { selectRef?.current?.mutateDataSource(newDataSource); } } } } } } } }, }; const closeDialog = { title: '关闭弹窗', value: 'closeDialog', position: ALL_BUTTON_POSITION_LIST, action: (config) => { const { buttonConfig, _context } = config; if (buttonConfig && _context) { const { options = {} } = buttonConfig; const { _bindDialog } = options; if (_bindDialog) { const dialogNode = _context.$(_bindDialog); dialogNode?.close?.(); return new Promise((resolve, reject) => { setTimeout(() => { resolve(); }, 400); }); } } }, getPrototypeList: () => { return [getSelectDialogSnippet()]; }, }; const previousStep = { title: '上一步', value: 'previousStep', position: [ButtonPosition.formDialog, ButtonPosition.form], // getPrototypeList: (position) => { // return []; // }, action: (config) => { const { buttonConfig, formInstance, position, close, urlParamsDataSource, recordDataSource, state, _context, dialogRef, needSuccessToast: paramNeedSuccessToast, formStepInstance, isFormStep, } = config; const realFormInstance = getRealizeValue(formInstance); if (buttonConfig && realFormInstance && formStepInstance) { formStepInstance.back?.(); } }, }; const nextStep = { title: '下一步', value: 'nextStep', position: [ButtonPosition.formDialog, ButtonPosition.form], // getPrototypeList: (position) => { // return []; // }, action: (config) => { const { buttonConfig, formInstance, position, close, urlParamsDataSource, recordDataSource, state, _context, dialogRef, needSuccessToast: paramNeedSuccessToast, formStepInstance, isFormStep, } = config; const realFormInstance = getRealizeValue(formInstance); if (buttonConfig && realFormInstance && formStepInstance) { formStepInstance.next?.(); } }, }; const clearTableCurrentRow = { title: '清空表格当前点击行数据', value: 'clearTableCurrentRow', position: [ButtonPosition.tableToolArea, ButtonPosition.tableBatchArea], // getDefaultProps: () => { // return { // }; // }, getPrototypeList: (position, config) => { return createTableSelectSetters(); }, action: (config) => { const { buttonConfig, _context } = config || {}; const { options = {} } = buttonConfig; const { _bindTable } = options || {}; function handleOneTable(id) { if (typeof id === 'string') { const table = _context.$(id); table?.setDataSource?.({ __tableCurrentRow__: undefined, }); } } if (_bindTable && _context) { if (Array.isArray(_bindTable)) { _bindTable.forEach((item) => { handleOneTable(item); }); } else { handleOneTable(_bindTable); } } return Promise.resolve(); }, }; const setDataSourceValue = { title: '给数据源设置数据', value: 'setDataSourceValue', position: ALL_BUTTON_POSITION_LIST, getDefaultProps: () => { return {}; }, getPrototypeList: (position, config) => { const { flowList, currentFlowIndex } = config || {}; return [ { name: 'dataSourceValues', title: '给数据源设置数据', className: 'cn-button-url-param-setter', setter: { componentName: 'MixedSetter', props: { setters: [ { title: '给数据源设置数据', componentName: 'ArraySetter', props: { mode: 'list', itemSetter: { componentName: 'ObjectSetter', // initialValue: { // }, props: { config: { items: [ { name: 'label', display: 'inline', title: '选择数据源', isRequired: true, setter: { componentName: 'CnSelectSetter', props: (field) => { return { options: getVariableDsList(), selectProps: { showSearch: true, }, }; }, }, }, { name: 'value', display: 'inline', title: '数据', isRequired: true, className: 'cn-param-select-setter', setter: { componentName: 'MixedSetter', props: { setters: [ { componentName: 'ParamSelectSetter', props: { configList: [ { groupName: '其他数据', groupExprName: __dataSource__, needSecondParam: true, }, { groupName: '动作编排的数据', groupExprName: __flowData__, needSecondParam: true, flowList, currentFlowIndex, }, ], }, title: '从数据源选择', }, { componentName: 'StringSetter', title: '字符串', }, { componentName: 'NumberSetter', title: '数字', }, { componentName: 'BoolSetter', title: '布尔(true/false)', }, getJSExpressionPrototype({ type: 'formRequest', prototypeConfig: config, }), ], }, }, }, ], }, }, }, }, }, // getJSExpressionPrototype({type:'base'}) ], }, }, }, ]; }, action: (config) => { const { buttonConfig, urlParamsDataSource, state, _context, recordDataSource, } = config || {}; const { options } = buttonConfig || {}; const { dataSourceValues } = options || {}; if (Array.isArray(dataSourceValues) && dataSourceValues.length > 0) { const temp = handleRequestParams(dataSourceValues, { urlParamsDataSource, recordDataSource: getRealizeValue(recordDataSource) || {}, state, }); if (isPlainObject(temp) && Object.keys(temp).length > 0) { _context?.setState?.(temp); emitEvent(CnDataSourceChange); } } return Promise.resolve(); }, }; const setTabActiveKey = { title: '设置Tab组件选中项', value: 'setTabActiveKey', position: ALL_BUTTON_POSITION_LIST, getPrototypeList: () => { return [ ...createTabSelectSetters(), { name: 'activeKey', title: '当前选中项', setter: { componentName: 'MixedSetter', props: { setters: [ // { // componentName: 'CnSelectSetter', // title: '选择tab项', // props(prop){ // const dataSource = [] // const _bindTab = prop?.parent?.getValue?.()?._bindTab; // if(_bindTab) { // const items = prop?.getNode?.()?.document?.getNode?.(_bindTab)?.getPropValue?.('items'); // if(isArrayNotEmpty(items)) { // items.forEach(item=>{ // const label = handleI18nLabel(item.title) // const value = item.primaryKey; // if(label && value) { // dataSource.push({ // label, // value, // }) // } // }) // } // } // return { // options:dataSource, // } // } // }, { componentName: 'StringSetter', title: '字符串', }, { componentName: 'ParamSelectSetter', props: { configList: [ { groupName: '其他数据', groupExprName: __dataSource__, needSecondParam: true, }, ], }, title: '从数据源选择', }, getJSExpressionPrototype({ type: 'base' }), ], }, }, }, ]; }, action: (arg) => { const { buttonConfig, _context } = arg || {}; const { options } = buttonConfig || {}; const { activeKey, _bindTab } = options || {}; const realActiveKey = calculateTextExprValue(activeKey, { state: _context?.state, recordDataSource: {}, }); if (realActiveKey && _bindTab) { const dom = _context?.$?.(_bindTab); if (typeof dom?.setTabActiveKey === 'function') { dom.setTabActiveKey(realActiveKey); } } }, }; const treeReload = { title: '左树右表中的树重新请求', value: 'treeReload', position: ALL_BUTTON_POSITION_LIST, getPrototypeList: () => { return createTreeSelectSetters({ mode: 'multiple', }); }, action: (arg) => { const { buttonConfig, _context } = arg || {}; const { options } = buttonConfig || {}; const { _bindTree } = options || {}; function reloadOneTree(id) { if (typeof id === 'string') { const tree = _context?.$(id); tree?.load?.(); } } if (isArrayNotEmpty(_bindTree) && _context) { _bindTree.forEach((item) => { reloadOneTree(item); }); } }, }; const wait = { title: '等待一会', value: 'wait', position: [ ButtonPosition.form, ButtonPosition.dialog, ButtonPosition.formDialog, ButtonPosition.tableBatchArea, ButtonPosition.tableToolArea, ButtonPosition.tableOperate, ButtonPosition.tabEvent, ButtonPosition.subCardAction, ButtonPosition.arrayTableOperate, ButtonPosition.blockButton, ], getPrototypeList: () => { return [ { name: 'seconds', title: '等待毫秒数 单位:毫秒', setter: 'NumberSetter', }, ]; }, action: (arg) => { const { buttonConfig, _context } = arg || {}; const { options } = buttonConfig || {}; const { seconds } = options || {}; if (typeof seconds === 'number') { return new Promise((resolve) => { setTimeout(() => { resolve(true); }, seconds); }); } }, }; const setStepActiveKey = { title: '设置步骤组件(CnStep)的激活步骤', value: 'setStepActiveKey', position: [ButtonPosition.step], getPrototypeList: () => { return [ ...createStepSelectSetters(), { name: 'activeKey', title: '设置激活步骤', setter: { componentName: 'MixedSetter', props: { setters: [ { componentName: 'NumberSetter', title: '指定第几步', }, { componentName: 'StringSetter', title: '设置激活步骤的编码', }, { componentName: 'ParamSelectSetter', props: { configList: [ { groupName: '其他数据', groupExprName: __dataSource__, needSecondParam: true, }, ], }, title: '从数据源选择', }, getJSExpressionPrototype({ type: 'base' }), ], }, }, }, ]; }, action: (arg) => { const { buttonConfig, _context } = arg || {}; const { options } = buttonConfig || {}; const { activeKey, _bindStep } = options || {}; if (activeKey && _bindStep) { const dom = _context?.$?.(_bindStep); if (typeof dom?.changeStep === 'function') { dom.changeStep(activeKey, { needSetState: true }); } } }, }; /** * 分步表单步骤 */ const setFormStepCurrent = { title: '跳转对应步骤', value: 'setFormStepCurrent', position: [ButtonPosition.formEvent], // getPrototypeList: () => { // return [ // { // name:'current', // title:'设置激活步骤', // setter:{ // componentName: 'MixedSetter', // props: { // setters: [ // { // componentName: 'NumberSetter', // title: '指定第几步', // }, // { // componentName: 'StringSetter', // title: '设置激活步骤的编码', // }, // { // componentName: 'ParamSelectSetter', // props: { // configList:[ // { // groupName:'其他数据', // groupExprName: __dataSource__, // needSecondParam:true, // }, // ], // }, // title: '从数据源选择', // }, // getJSExpressionPrototype({ type: 'base' }), // ], // }, // }, // } // ] // }, // action: (arg) => { // const { buttonConfig, _context } = arg || {}; // const { options } = buttonConfig || {} // const { current, _bindStep } = options || {}; // if(current && _bindStep) { // const dom = _context?.$?.(_bindStep); // if(typeof dom?.changeStep === 'function') { // dom.changeStep(current, { needSetState: true}); // } // } // }, }; const setFilterValue = { title: '给筛选栏设置数据', value: 'setFilterValue', position: ALL_BUTTON_POSITION_LIST, getDefaultProps: () => { return { handleFilterType: 'setFilterFieldValue', }; }, getPrototypeList: (position, config) => { const { flowList, currentFlowIndex } = config || {}; return [ ...createFilterSelectSetters({ mode: 'single', }), getFormHandleTypeSetterSnippet({ componentTitle: '筛选栏', componentName: 'Filter', handleTypeName: 'handleFilterType', }), { name: 'formValues', title: '要填入筛选栏的数据', className: 'cn-button-url-param-setter', condition(prop) { return ( prop?.parent?.getPropValue?.('handleFilterType') === 'setFilterFieldValue' ); }, originalCondition(prop) { return ( prop?.parent?.getPropValue?.('handleFilterType') === 'setFilterFieldValue' ); }, setter: { title: '给筛选栏每个字段设置数据', componentName: 'ArraySetter', props: { mode: 'list', itemSetter: { componentName: 'ObjectSetter', props: { config: { items: [ { name: 'label', display: 'inline', title: '选择字段', isRequired: true, setter: { componentName: 'CnTreeSelectSetter', props: (field) => { const dataSource = []; const currentData = field?.parent?.parent?.parent?.getValue?.(); const { _bindFilter } = currentData || {}; if (_bindFilter && field) { const node = getNodeById({ field, id: _bindFilter, }); if (node?.id) { const config = node?.getPropValue?.('config'); if (Array.isArray(config) && config.length > 0) { config.forEach((item) => { if (item?.name) { const temp = { label: handleI18nLabel(item?.label) || item.name, value: item.name, }; dataSource.push(temp); } }); } } } return { dataSource, popupClassName: 'cn-tree-select-setter-pupup', }; }, }, }, { name: 'value', display: 'inline', title: '数据', isRequired: true, className: 'cn-param-select-setter', setter: { componentName: 'MixedSetter', props: { setters: [ { componentName: 'ParamSelectSetter', props: { ParamSelectSetterComponent: ParamSelectSetter, configList: [ { groupName: '其他数据', groupExprName: __dataSource__, needSecondParam: true, }, { groupName: '动作编排的数据', groupExprName: __flowData__, needSecondParam: true, flowList, currentFlowIndex, }, ], }, title: '从数据源选择', }, getJSExpressionPrototype({ type: 'formRequest', prototypeConfig: config, }), ], }, }, }, ], }, }, }, }, }, }, { name: 'allFilterValues', display: 'inline', condition(prop) { return ( prop?.parent?.getPropValue?.('handleFilterType') === 'setAllFilterValue' ); }, originalCondition(prop) { return ( prop?.parent?.getPropValue?.('handleFilterType') === 'setAllFilterValue' ); }, title: '新的表单数据', className: 'cn-param-select-setter', // className: 'cn-button-url-param-setter', setter: { componentName: 'MixedSetter', props: { setters: [ { componentName: 'ParamSelectSetter', props: { ParamSelectSetterComponent: ParamSelectSetter, configList: [ { groupName: '其他数据', groupExprName: __dataSource__, needSecondParam: true, }, { groupName: '动作编排的数据', groupExprName: __flowData__, needSecondParam: true, flowList, currentFlowIndex, }, ], }, title: '从数据源选择', }, { componentName: 'StringSetter', title: '字符串', }, { componentName: 'NumberSetter', title: '数字', }, getJSExpressionPrototype({ type: 'formRequest', prototypeConfig: config, }), ], }, }, }, ]; }, action: (config) => { const { buttonConfig, urlParamsDataSource, state, _context } = config || {}; const { options } = buttonConfig || {}; const { formValues, _bindFilter, handleFilterType, allFilterValues } = options || {}; if (_bindFilter) { const formNode = _context?.$(_bindFilter); const formInstance = formNode?.getFormInstance?.(); const oldFormValue = cloneDeep(formInstance?.values); if (formInstance) { if (handleFilterType === 'clearFilterValue') { formInstance.setValues?.({}, 'overwrite'); } else if (handleFilterType === 'setAllFilterValue') { const newFormValue = calculateTextExprValue(allFilterValues, { urlParamsDataSource, recordDataSource: oldFormValue, state, }); if (isPlainObject(newFormValue)) { formInstance.setValues?.(newFormValue, 'overwrite'); } } else { let newFormValue; if (Array.isArray(formValues)) { if (formValues.length > 0) { const temp = handleRequestParams(formValues, { urlParamsDataSource, recordDataSource: oldFormValue || {}, state, }); if (isPlainObject(temp)) { newFormValue = temp; } } } formInstance.setValues?.(newFormValue); } } } return Promise.resolve(); }, }; const filterValidate = { title: '筛选栏校验', value: 'filterValidate', position: [ButtonPosition.tableToolArea, ButtonPosition.tableBatchArea], getPrototypeList: () => { return createFilterSelectSetters(); }, action: (arg) => { const { buttonConfig, _context } = arg || {}; const { options = {} } = buttonConfig; const { _bindFilter } = options; if (typeof _bindFilter === 'string' && _context) { const filter = _context.$(_bindFilter); const formInstance = filter?.getFormInstance?.(); if (formInstance?.validate) { return formInstance.validate(); } } }, }; const tabReload = { title: 'Tab重新请求', value: 'tabReload', position: ALL_BUTTON_POSITION_LIST, getPrototypeList: () => { return createTabSelectSetters({ mode: 'multiple', }); }, action: (arg) => { const { buttonConfig, _context } = arg || {}; const { options = {} } = buttonConfig; const { _bindTab } = options; function reloadOneTab(id) { if (typeof id === 'string') { const tab = _context.$(id); tab?.getData?.(); } } if (_bindTab && _context) { if (Array.isArray(_bindTab)) { _bindTab.forEach((item) => { reloadOneTab(item); }); } else { reloadOneTab(_bindTab); } } }, }; const formReRender = { title: '表单重新渲染', value: 'formReRender', position: [ButtonPosition.filterEvent], getPrototypeList: () => { return createFormSelectSetters({ mode: 'multiple', }); }, action: (arg) => { const { buttonConfig, _context } = arg || {}; const { options = {} } = buttonConfig; const { _bindForm } = options; function reloadOneForm(id) { if (typeof id === 'string') { const form = _context.$(id); form?.reRender()?.(); } } if (_bindForm && _context) { if (Array.isArray(_bindForm)) { _bindForm.forEach((item) => { reloadOneForm(item); }); } else { reloadOneForm(_bindForm); } } }, }; const setFormFieldState = { title: '设置表单/筛选栏字段状态', value: 'setFormFieldState', position: ALL_BUTTON_POSITION_LIST, getDefaultProps: () => { return { handleType: 'setByField', }; }, getPrototypeList: (position, config) => { return [ ...createFormOrFilterSelectSetters({ mode: 'single', }), { title: `对字段做何处理`, name: 'handleType', defaultValue: 'setByField', setter: { componentName: 'CnSelectSetter', props: { selectProps: { hasClear: true, }, options: [ { label: `给每个字段单独设置状态`, value: `setByField`, }, { label: `批量设置字段状态`, value: `batchSetField`, }, ], }, }, }, { condition(prop) { return prop?.parent?.getPropValue?.('handleType') === 'setByField'; }, originalCondition(prop) { return prop?.parent?.getPropValue?.('handleType') === 'setByField'; }, name: 'fieldStateList', title: '字段列表', className: 'cn-button-url-param-setter', setter: { title: '给每个字段设置状态', componentName: 'ArraySetter', props: { mode: 'list', itemSetter: { componentName: 'ObjectSetter', props: { config: { items: [ getFieldSelectSetterSnippet(), { name: 'value', display: 'inline', title: '状态', isRequired: true, setter: { componentName: 'CnSelectSetter', props: { options: [ { label: '禁用', value: 'disabled', }, { label: '隐藏', value: 'hidden', }, { label: '只读', value: 'readOnly', }, ], selectProps: { hasClear: true, }, }, }, }, { name: 'state', display: 'inline', title: '是 / 否', defaultValue: true, isRequired: true, setter: { componentName: 'MixedSetter', props: { setters: [ { componentName: 'BoolSetter', title: '布尔(true/false)', }, getJSExpressionPrototype({ type: 'base', }), ], }, }, }, ], }, }, }, }, }, }, { condition(prop) { return prop?.parent?.getPropValue?.('handleType') === 'batchSetField'; }, originalCondition(prop) { return prop?.parent?.getPropValue?.('handleType') === 'batchSetField'; }, name: 'batchSetFieldFieldCallback', title: '批量设置字段状态', className: 'cn-action-setter', setter: { componentName: ( {fieldState.hidden = true}) }`} defaultActionName={'batchSetFieldField'} /> ), }, }, ]; }, action: (config) => { const { buttonConfig, urlParamsDataSource, state, _context, field, position, } = config || {}; const { options } = buttonConfig || {}; const { _bindForm, fieldStateList, handleType, batchSetFieldFieldCallback, } = options || {}; if (_bindForm) { const formNode = _context?.$(_bindForm); const formInstance = formNode?.getFormInstance?.(); if (formInstance) { if (handleType === 'batchSetField') { if (typeof batchSetFieldFieldCallback === 'function') { executeFunction(batchSetFieldFieldCallback, { form: formInstance, state, }); } } else { if (isArrayNotEmpty(fieldStateList)) { const groupFieldState = groupBy(fieldStateList, 'label'); for (const key in groupFieldState) { const stateList = groupFieldState[key]; let realKey = key; if (key && isArrayNotEmpty(stateList)) { if (key?.includes(__arrayTableCurrentRow__) && field) { const arr = key?.split?.(`.${__arrayTableCurrentRow__}.`); if (arr.length === 2) { const fieldName = arr[0]; const arrayTableFieldName = arr[1]; const segments = field?.path?.segments || []; const fieldIndex = +segments[segments?.length - 2]; if (!isNaN(fieldIndex)) { realKey = `${fieldName}.${fieldIndex}.${arrayTableFieldName}`; } } } formInstance.setFieldState(realKey, (fieldState) => { stateList.forEach((item) => { const { value, state } = item; if (value && state !== undefined) { fieldState[value] = executeObjectExpr( state, {}, {}, _context?.state, ); } }); }); } } } } } } return Promise.resolve(); }, }; const componentReRender = { title: '组件重新渲染', value: 'componentReRender', position: ALL_BUTTON_POSITION_LIST, getPrototypeList: () => { return createComponentSelectSetters({ mode: 'multiple', containsKey: [ 'isCnTable', 'isCnTab', 'isCnStatisticCard', 'isCnForm', 'isCnFormDialog', 'isCnPieChart', 'isCnPage', ...(window?.cnLowCodeUtils?.canForceUpdate || []).map((i) => i.propKey), ], }); }, action: (arg) => { const { buttonConfig, _context } = arg || {}; const { options = {} } = buttonConfig; const { _bindComponent } = options; function reloadOneComponent(id) { if (typeof id === 'string') { const compIns = _context.$(id); if (isFunction(compIns?.reRender)) { compIns?.reRender?.()?.(); } else { compIns?.forceUpdate?.(); } } } if (_bindComponent && _context) { if (Array.isArray(_bindComponent)) { _bindComponent.forEach((item) => { reloadOneComponent(item); }); } else { reloadOneComponent(_bindComponent); } } }, }; const componentMap = { link, request, pollingAction, batch, submit, reset, cancel, dialog, ossImport, export: exportButton, download, tableReload, jsAction, arrayTableRemove, arrayTableAdd, arrayTableMoveUp, arrayTableMoveDown, arraySubAreaCardRemove, arraySubAreaCardAdd, arraySubAreaCardMoveUp, arraySubAreaCardMoveDown, componentReload, message, confirm, formReload, setFormData, textRender, tableLoop, setFormValue, loadDynamicFormConfig, filterReset, filterSearch, filterValidate, buttonGroup, setSelectDataSource, closeDialog, previousStep, nextStep, tabReload, clearTableCurrentRow, setDataSourceValue, locationReload, setTableSelectRowKeys, setTableOpenKeys, setTabActiveKey, setStepActiveKey, setFormStepCurrent, treeReload, wait, setFilterValue, tableLoop2, formReRender, setFormFieldState, componentReRender, flowAction, }; // 注册回调动作 export function registerButton(plugin) { const { name } = plugin || {}; if (name) { componentMap[name] = plugin; } } // 获取按钮列表 export function getButtonListByPosition(position, config) { const { excludeButtonList = [] } = config || {}; const defaultList = Object.keys(componentMap); const bizComponentNameList = getBizComponentNameList(); const allComponentList = uniq([...defaultList, ...bizComponentNameList]); const result = []; if (position !== undefined) { allComponentList.forEach((name) => { if (excludeButtonList?.includes(name)) { } else { const component = getItem(position, name); if (component) { const { bizInfo = [] } = component; if (bizInfo.length > 0) { bizInfo.forEach((item) => { const { label, value } = item; const existGroup = result.find((item2) => item2.value === value); if (existGroup) { existGroup?.children.push(component); } else { result.push({ title: label, value, children: [component], }); } }); return; } result.push(component); } } }); } return result; } export function getItem(position, componentName, propKey) { let result; if (componentName) { let item = componentMap[componentName]; if (!item) { item = getBizComponent(componentName, position); } if (item && item.position && item.position.includes(position)) { if (!item.label) { item.label = item.title; } if (!item.value) { item.value = item.componentName; } if (propKey) { result = item[propKey]; } else { result = item; } } } return result; } // 获取按钮prototype列表by position export function getButtonPrototypeListByPosition(position, config) { const defaultList = Object.keys(componentMap); let prototypeList = []; const bizComponentNameList = getBizComponentNameList(); const allComponentList = uniq([...defaultList, ...bizComponentNameList]); if (position !== undefined) { allComponentList.forEach((name) => { const item = getItem(position, name) || {}; const { getPrototypeList, configure = [] } = item; if (typeof getPrototypeList === 'function') { const temp = getPrototypeList(position, config); if (temp && temp.length > 0) { prototypeList = [ ...prototypeList, ...handlePrototypeCondition(temp, name, 'optType'), ]; } } else if (configure?.length > 0) { prototypeList = [ ...prototypeList, ...handlePrototypeCondition(configure, name, 'optType'), ]; } }); } return prototypeList; } export function getItemDefaultProps(position, componentName) { const func = getItem(position, componentName, 'getDefaultProps'); if (typeof func === 'function') { return func(); } } export function getButtonAction(buttonConfig) { const { optType, position } = buttonConfig || {}; if (optType) { const action = getItem(position, optType, 'action'); if (typeof action === 'function') { return action; } } } export function getRunTimeItem(componentName) { let result; if (componentName) { result = componentMap[componentName]; if (!result) { result = getRunTimeBizComponent(componentName); } } return result; } // // 获取button的node // export function getButtonNode(arg){ // const { buttonConfig = {}} = arg; // const { optType } = buttonConfig; // if(optType) { // const button = componentMap[optType]; // if(typeof button?.getButtonNode === 'function'){ // // 传递record,index , 这样onClick就能拿到 // return button.getButtonNode(arg) // } // } // return null; // } export const createButtonListSetters = (config) => { const { position, childrenTitle, additionalPosition, extraInitialValues } = config || {}; const tempButtonList = getButtonListByPosition(position, config); let titleSetter = 'CnI18nSetter'; if ( [ ButtonPosition.cardAction, ButtonPosition.subCardAction, ButtonPosition.blockButton, ].includes(position) ) { titleSetter = { componentName: 'MixedSetter', props: { setters: [ { componentName: 'CnI18nSetter', title: '纯文本', }, getJSExpressionPrototype({ type: 'formRequest', }), ], }, }; } const configure = [ { name: 'primaryKey', title: '唯一标识', condition: { type: 'JSFunction', value: '() => false', }, initialValue: { type: 'JSFunction', value: 'val => {\n if (val) return val;\n return String(Math.floor(Math.random() * 10000));\n }', }, setter: 'StringSetter', }, { name: 'children', isRequired: true, title: childrenTitle || '标题', // initialValue: "按钮", // extraProps: { // setValue(target,value){ // }, // }, setter: titleSetter, }, { name: 'optType', title: '按钮功能', isRequired: true, display: 'inline', extraProps: { setValue(target, value) { const currentRowValue = target?.parent?.getValue(); const newButtonInitialValue = getItemDefaultProps(position, value); target?.parent.setValue({ ...currentRowValue, optType: value, options: newButtonInitialValue, }); }, }, // "extraProps": { // "setValue": { // "type": "JSFunction", // "value": "(target, value) => {}" // } // }, // initialValue: tempButtonList[0]?.value, editable: true, setter: { componentName: 'CnSelectSetter', // props: { // options: getButtonListByPosition(position), // }, props: () => { return { options: getButtonListByPosition(position, config), selectProps: { showSearch: true, }, }; }, }, }, ]; configure.push({ name: 'options', // display: 'accordion', display: 'block', title: '按钮配置项', extraProps: { defaultCollapsed: false, }, setter: { componentName: 'ObjectSetter', props: () => { return { config: { items: [ ...getButtonPrototypeListByPosition(position, { additionalPosition, }), ], }, }; }, }, }); const styleList = getStyleListByPosition(position); if (styleList?.length > 0) { configure.push({ title: '样式', type: 'group', display: 'accordion', collapsed: true, items: styleList, }); // configure.push({ // name: 'style', // display: 'block', // title: '样式', // setter: { // componentName: "ObjectSetter", // props: { // config: { // items: [ // { // name: 'type', // title: '按钮样式', // // supportVariable: true, // display:'inline', // initialValue: 'normal', // setter: // } // ] // } // } // } // }) } // configure.push({ // title: '高级配置(请谨慎使用)', // name: __advancedCodeConfig__, // display: 'accordion', // extraProps: { // defaultCollapsed: true, // }, // setter: { // componentName: 'ObjectSetter', // props: { // config: { // items: [ // { // name: 'handleProps', // title: '手动设置组件props', // display: 'inline', // setter: getJSExpressionPrototype({ // type:'props', // }), // }, // ] // } // } // } // }) const buttonInitialValue = getItemDefaultProps( position, tempButtonList[0]?.value, ); return { componentName: 'ArraySetter', props: { mode: 'list', itemSetter: { componentName: 'ObjectSetter', // initialValue: { // "type": "JSFunction", // "value": "() => {return {primaryKey: String(Math.floor(Math.random() * 10000)),children: \"Title\",optType:\"link\" };}" // }, initialValue() { return { primaryKey: uuid(6), children: '按钮', optType: tempButtonList[0]?.value, options: buttonInitialValue, ...extraInitialValues, }; }, props: { config: { items: configure, }, }, }, }, }; // return }; function getPollingFlowList(field) { let flowList = field?.parent?.parent?.getValue?.()?.slice?.() ?? []; let flowIndex = field?.parent?.name; const lastParentName = field?.parent?.parent?.parent?.parent?.parent?.name; if(lastParentName === 'flowList') { let parentIndex = field?.parent?.parent?.parent?.parent?.name; flowList?.forEach(item=> { if(isPlainObject(item)) { item.prefix = { text: `轮询${parentIndex || ''}`, path: `polling${parentIndex || ''}`, changeIndex: -parentIndex } } }) let parentFlowList = field?.parent?.parent?.parent?.parent?.parent?.getValue?.()?.slice?.(); parentFlowList[parentIndex] = flowList; flowList = flatten(parentFlowList); flowIndex = flowIndex + parentIndex; } return [flowList, flowIndex]; } export const createPollingListSetters = (config) => { const { position, activeSetter, excludeButtonList = [] } = config || {}; return { componentName: 'ArraySetter', props: { mode: 'list', itemSetter: { componentName: 'ObjectSetter', initialValue: { active: true, }, props: { config: { items: [ { name: 'optType', display: 'inline', title: '动作类型', isRequired: true, setter: { componentName: 'CnSelectSetter', props: () => { return { options: getButtonListByPosition(position, { excludeButtonList: ['flowAction', ...(excludeButtonList ?? [])], }), selectProps: { showSearch: true, }, }; }, }, }, { name: 'active', display: 'inline', title: '启用', isRequired: true, setter: activeSetter || { componentName: , title: '启用/禁用', }, }, { name: 'options', // display: 'accordion', display: 'plain', title: '动作配置项', extraProps: { defaultCollapsed: false, }, setter: { componentName: 'ObjectSetter', props: (field) => { const [flowList, flowIndex] = getPollingFlowList(field); // 内部的 数据直接下啦选择的地方 return { config: { items: [ ...getButtonPrototypeListByPosition(position, { flowList, currentFlowIndex: flowIndex, }), ], }, }; }, }, }, ], }, }, }, }, }; }; export const createFlowListSetters = (config) => { const { position, activeSetter, excludeButtonList = [] } = config || {}; return { componentName: 'ArraySetter', props: { mode: 'list', itemSetter: { componentName: 'ObjectSetter', initialValue: { active: true, }, props: { config: { items: [ { name: 'optType', display: 'inline', title: '动作类型', isRequired: true, setter: { componentName: 'CnSelectSetter', props: () => { return { options: getButtonListByPosition(position, { excludeButtonList: ['flowAction', ...(excludeButtonList ?? [])], }), selectProps: { showSearch: true, }, }; }, }, }, { name: 'active', display: 'inline', title: '启用', isRequired: true, setter: activeSetter || { componentName: , title: '启用/禁用', }, }, { name: 'options', // display: 'accordion', display: 'plain', title: '动作配置项', extraProps: { defaultCollapsed: false, }, setter: { componentName: 'ObjectSetter', props: (field) => { const flowList = field?.parent?.parent?.getValue?.(); const index = field?.parent?.name; return { config: { items: [ ...getButtonPrototypeListByPosition(position, { flowList, currentFlowIndex: index, }), ], }, }; }, }, }, ], }, }, }, }, }; }; export function createFormSelectSetters(config) { const { mode } = config || {}; const getSelectSetterItemInfoByNodeItem = getSelectSetterItemFuntion([ 'isCnForm', 'isCnFormDialog', ]); return [ { name: '_bindForm', title: '选择表单', setter(prop) { const options = []; prop?.getNode?.()?.document?.nodesMap?.forEach((item) => { const { title } = getSelectSetterItemInfoByNodeItem(item); title && options.push({ title, value: item.id, }); }); return { componentName: 'SelectSetter', props: { mode, // hasClear: true, options, }, }; }, }, ]; } // propKey 用于判断组件类型 prefix为前缀 titleKey是获取 const allBindComponentMatchConfig = [ { propKey: 'isCnTable', prefix: '表格', titleKey: 'tableName', }, { propKey: 'isCnTab', prefix: '选项卡', }, { propKey: 'isCnStatisticCard', prefix: '指标卡', }, { propKey: 'isCnForm', prefix: '表单', }, { propKey: 'isCnFormDialog', prefix: '弹窗表单', }, { propKey: 'isCnPieChart', prefix: '饼图', }, { propKey: 'isCnList', prefix: '列表', titleKey: 'header', }, { propKey: 'isCnStep', prefix: '步骤条', }, { propKey: 'isCnPage', prefix: 'CnPage', }, ]; // function getSelectSetterItemFuntion(containsKey: string[] = []) { const realAllBindComponentMatchConfig = allBindComponentMatchConfig.concat( window?.cnLowCodeUtils?.canForceUpdate || [], ); const filterConfig = containsKey?.length > 0 ? realAllBindComponentMatchConfig.filter((configItem) => containsKey.includes(configItem?.propKey), ) : realAllBindComponentMatchConfig; // 根据config return function getSelectSetterItemInfoByNodeItem(item) { if (isFunction(item?.getPropValue)) { let matchConfig = null; filterConfig.forEach((configItem) => { const { propKey, prefix, titleKey = 'title' } = configItem; const isMatch = item.getPropValue(propKey); if (isMatch) { const componentTitle = item?.propsData?.[titleKey] ?? ''; matchConfig = { prefix, title: `${prefix}_${handleI18nLabel(componentTitle) || ''}`, }; } }); if (matchConfig) { return matchConfig; } } return { prefix: '', title: '', }; }; } export function createComponentSelectSetters(config) { const { mode, containsKey } = config || {}; const getSelectSetterItemInfoByNodeItem = getSelectSetterItemFuntion( containsKey || [ 'isCnTable', 'isCnTab', 'isCnStatisticCard', 'isCnForm', 'isCnFormDialog', 'isCnPieChart', ...(window?.cnLowCodeUtils?.canForceUpdate || []).map((i) => i.propKey), ], ); return [ { name: '_bindComponent', title: '选择组件', setter(prop) { const options = []; prop?.getNode?.()?.document?.nodesMap?.forEach((item) => { const { title } = getSelectSetterItemInfoByNodeItem(item); if (title) { options.push({ title, value: item.id || '', }); } }); return { componentName: 'SelectSetter', props: { mode, // hasClear: true, options, }, }; }, }, ]; } export function createFilterSelectSetters(config, extraConfig) { const { mode } = config || {}; return [ { name: '_bindFilter', title: '选择筛选栏', setter(prop) { const options = []; prop?.getNode?.()?.document?.nodesMap?.forEach((item) => { if (item.getPropValue('isCnFilter')) { const prefix = '筛选栏'; const id = item.id || ''; const title = `${prefix}_${ handleI18nLabel(item?.propsData?.title) || '' }`; options.push({ title, value: id, }); } }); return { componentName: 'SelectSetter', props: { mode, // hasClear: true, options, }, }; }, ...extraConfig, }, ]; } export function createFormOrFilterSelectSetters(config) { const { mode } = config || {}; return [ { name: '_bindForm', title: '选择筛选栏/表单', setter(prop) { const options = []; prop?.getNode?.()?.document?.nodesMap?.forEach((item) => { const isCnFilter = item.getPropValue('isCnFilter'); const isCnForm = item.getPropValue('isCnForm'); const isCnFormDialog = item.getPropValue('isCnFormDialog'); if (isCnFilter || isCnForm || isCnFormDialog) { let prefix = '筛选栏'; if (isCnForm) { prefix = '表单'; } if (isCnFormDialog) { prefix = '表单弹窗'; } const id = item.id || ''; const title = `${prefix}_${ handleI18nLabel(item?.propsData?.title) || '' }`; options.push({ title, value: id, }); } }); return { componentName: 'SelectSetter', props: { mode, // hasClear: true, options, }, }; }, }, ]; } export function createTableSelectSetters(config, extraConfig) { const { mode } = config || {}; return [ { name: '_bindTable', title: '选择表格', setter(prop) { const options = []; prop?.getNode?.()?.document?.nodesMap?.forEach((item) => { if (item.getPropValue('isCnTable')) { const id = item.id || ''; const tableName = item?.propsData?.tableName || ''; const title = `表格_${tableName}`; options.push({ title, value: id, }); } }); return { componentName: 'SelectSetter', props: { mode: mode || 'multiple', // hasClear: true, options, }, }; }, ...extraConfig, }, ]; } // 选择Tab setter export function createTabSelectSetters(config) { const { mode } = config || {}; return [ { name: '_bindTab', title: '选择Tab组件', setter(prop) { const options = []; prop?.getNode?.()?.document?.nodesMap?.forEach((item) => { if (item.getPropValue('isCnTab')) { const prefix = 'Tab'; const id = item?.id || ''; const title = `${prefix}_${ handleI18nLabel(item?.propsData?.title) || '' }`; options.push({ title, value: id, }); } }); return { componentName: 'SelectSetter', props: { mode, // hasClear: true, options, }, }; }, }, ]; } // 选择Step setter export function createStepSelectSetters(config) { const { mode } = config || {}; return [ { name: '_bindStep', title: '选择组件', setter: { componentName: 'CnSelectSetter', props(prop) { const options = []; prop?.getNode?.()?.document?.nodesMap?.forEach((item) => { if (item.getPropValue('isCnStep')) { const prefix = 'Step'; const id = item?.id || ''; const title = `${prefix}_${ handleI18nLabel(item?.propsData?.title) || '' }`; options.push({ title, value: id, }); } }); return { mode, hasClear: true, options, }; }, }, }, ]; } // 选择树 setter export function createTreeSelectSetters(config) { const { mode } = config || {}; return [ { name: '_bindTree', title: '选择树组件', setter(prop) { const options = []; prop?.getNode?.()?.document?.nodesMap?.forEach((item) => { if (item?.getPropValue('isCnLeftTree')) { const prefix = '树'; const id = item?.id || ''; const title = `${prefix}_${ handleI18nLabel(item?.propsData?.title) || '' }`; options.push({ title, value: id, }); } }); return { componentName: 'SelectSetter', props: { mode, // hasClear: true, options, }, }; }, }, ]; } function waitAsync(time: number) { return new Promise((resolve)=> { setTimeout(() => { resolve(true); }, time) }) }