chore: api and demo update

This commit is contained in:
gchust 2025-04-20 15:50:50 +08:00
parent 2ac824c85a
commit f87d5f0e49
5 changed files with 112 additions and 62 deletions

View File

@ -139,36 +139,63 @@ eventFlowManager.addFlow({
],
});
// 主演示组件
const ConfigurableActionDemo = () => {
const [currentParams, setCurrentParams] = useState<Record<string, any>>({
const PARAMS = {
events: {
'button-id': {
stepParams: {
'message-step': {
title: '消息标题',
content: '这是一条测试消息',
type: 'info',
});
},
},
},
},
filters: {},
};
const getParams = async (id: string) => {
return new Promise((resolve) => {
setTimeout(() => {
resolve(PARAMS['events'][id]); // 模拟异步获取
}, 1000);
});
};
const setParams = async (id: string, params: Record<string, any>) => {
return new Promise((resolve) => {
setTimeout(() => {
PARAMS['events'][id] = params; // 模拟异步更新
resolve(params);
}, 1000);
});
};
// 主演示组件
const ConfigurableActionDemo = () => {
const componentId = 'button-id';
// 打开配置弹窗
const showConfig = () => {
const showConfig = async () => {
const step = eventFlowManager.getFlow('message-flow').getStep('message-step');
const ctx = {
payload: {
step,
onChange: (values) => {
setCurrentParams(values);
onChange: async (values) => {
await setParams(componentId, values);
},
currentParams,
currentParams: await getParams(componentId),
},
};
eventBus.dispatchEvent('configure:click', ctx);
};
// 触发消息动作
const triggerAction = () => {
const triggerAction = async () => {
const ctx = {
payload: {},
meta: {
stepParams: {
'message-step': currentParams,
'message-step': await getParams(componentId),
},
},
};
@ -182,15 +209,6 @@ const ConfigurableActionDemo = () => {
&quot;&quot;&quot;&quot;
</Typography.Paragraph>
<div style={{ marginBottom: 16 }}>
<Typography.Text strong>:</Typography.Text>
<ul>
<li>: {currentParams.title}</li>
<li>: {currentParams.content}</li>
<li>: {currentParams.type}</li>
</ul>
</div>
<Space>
<Button type="primary" onClick={showConfig}>

View File

@ -1,6 +1,6 @@
import { Button, Card, Form, Input, Select, Space, Typography, Modal, Switch, InputNumber } from 'antd';
import React, { useMemo, useState } from 'react';
import { FilterFlowManager, useApplyFilters } from '@nocobase/client';
import React, { useCallback, useMemo, useState } from 'react';
import { FilterFlowManager, FilterHandlerContext, FilterStepParams, useApplyFilters } from '@nocobase/client';
import { configureAction } from '../actions/open-configure-dialog';
// 创建FilterFlowManager实例
@ -135,9 +135,9 @@ filterFlowManager.addFlow({
],
});
const ConfigurableFilter = () => {
const [inputText, setInputText] = useState('Hello configurable filter demo');
const [stepParams, setStepParams] = useState({
const PARAMS = {
filters: {
'demo-id': {
'replace-step': {
search: 'Hello',
replacement: 'hi',
@ -147,30 +147,53 @@ const ConfigurableFilter = () => {
maxLength: 10,
suffix: '...',
},
});
},
},
};
const context = useMemo(
() => ({
const getParams = async (id: string): Promise<FilterStepParams> => {
return new Promise((resolve) => {
setTimeout(() => {
resolve(PARAMS['filters'][id]); // 模拟异步获取
}, 1000);
});
};
const setParams = async (id: string, params: Record<string, any>) => {
return new Promise((resolve) => {
setTimeout(() => {
PARAMS['filters'][id] = params; // 模拟异步更新
resolve(params);
}, 1000);
});
};
const ConfigurableFilter = () => {
const demoId = 'demo-id';
const [inputText, setInputText] = useState('Hello configurable filter demo');
const getContext = useCallback(
async (): Promise<FilterHandlerContext> => ({
meta: {
params: stepParams,
params: await getParams(demoId),
},
}),
[inputText, stepParams],
[demoId],
);
const outputText = useApplyFilters(filterFlowManager, 'configurable-text-transform', inputText, context);
const outputText = useApplyFilters(filterFlowManager, 'configurable-text-transform', inputText, getContext, demoId);
// 打开配置Modal
const openConfigModal = (stepKey) => {
const openConfigModal = async (stepKey) => {
const flow = filterFlowManager.getFlow('configurable-text-transform');
const step = flow.getStep(stepKey);
const actionContext = {
payload: {
step,
currentParams: stepParams[stepKey],
onChange: (values) => {
setStepParams({
...stepParams,
currentParams: (await getParams(demoId))?.[stepKey],
onChange: async (values) => {
// await setParams(demoId, PARAMS['filters'][demoId]);
await setParams(demoId, {
...PARAMS['filters'][demoId],
[stepKey]: values,
});
},

View File

@ -197,15 +197,6 @@ const HideShowFilterFlow = () => {
</div>
</Space>
</Card>
<Card title="过滤器结果" style={{ marginBottom: 16 }}>
<Space direction="vertical" style={{ width: '100%' }}>
<div>
<Typography.Text code>visibilityConfig:</Typography.Text>
<pre>{JSON.stringify(visibilityConfig, null, 2)}</pre>
</div>
</Space>
</Card>
</div>
);
};

View File

@ -21,6 +21,11 @@
<code src="./demos/filters/multi-step-filterflow.tsx"></code>
## 控制元素可见性过滤器流
演示如何控制元素的可见性
<code src="./demos/filters/hide-show-filterflow.tsx"></code>
## 数据转换过滤器流
展示如何使用过滤器流转换数据

View File

@ -25,24 +25,36 @@ export function useApplyFilters<T = any>(
filterFlowManager: FilterFlowManager,
flowName: string,
initialValue: any,
context?: FilterHandlerContext,
context?: FilterHandlerContext | (() => Promise<FilterHandlerContext>),
id?: string,
): T {
const [, forceUpdate] = useState(0);
const cacheKey = useMemo(() => {
const key = JSON.stringify([flowName, context]);
return key;
}, [flowName, context]);
if (id) {
return `${flowName}-${id}`;
}
return JSON.stringify([flowName, context]);
}, [flowName, context, id]);
const prevValue = useRef(initialValue);
const prevCacheKey = useRef(cacheKey);
const contextPromise = new Promise<FilterHandlerContext>((resolve, reject) => {
if (typeof context === 'function') {
context().then(resolve).catch(reject);
} else {
resolve(context);
}
});
useEffect(() => {
if (prevValue.current !== initialValue) {
const refreshData = async () => {
const cachedEntry = filterCache.get(cacheKey);
if (cachedEntry?.status === 'resolved') {
const newData = await filterFlowManager.applyFilters(flowName, initialValue, context);
const newData = await contextPromise.then((ctx) =>
filterFlowManager.applyFilters(flowName, initialValue, ctx),
);
filterCache.set(cacheKey, { status: 'resolved', data: newData, promise: Promise.resolve(newData) });
forceUpdate((prev) => prev + 1);
}
@ -50,7 +62,8 @@ export function useApplyFilters<T = any>(
refreshData();
prevValue.current = initialValue;
}
}, [initialValue]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [initialValue]); //输入变化时,应该重新计算
useEffect(() => {
if (prevCacheKey.current !== cacheKey) {
@ -77,8 +90,8 @@ export function useApplyFilters<T = any>(
}
// 创建新的 Promise
const promise = filterFlowManager
.applyFilters(flowName, initialValue, context)
const promise = contextPromise
.then((ctx) => filterFlowManager.applyFilters(flowName, initialValue, ctx))
.then((result) => {
// 成功时更新缓存
filterCache.set(cacheKey, { status: 'resolved', data: result, promise });