form-chain-effect-engine
Version:
A dependency-driven form effect engine for React + Ant Design
166 lines (162 loc) • 6.55 kB
JavaScript
;
var react = require('react');
function createChain(source, enableAdvanced, _triggerFn) {
const chain = {
source,
path: [source],
};
if (enableAdvanced) {
chain.isStopped = false;
chain.stop = () => {
chain.isStopped = true;
};
}
return chain;
}
function extendChain(chain, nextField) {
return Object.assign(Object.assign({}, chain), { path: [...chain.path, nextField] });
}
// =============核心 Hook=============
function useFormChainEffectEngine({ form, config, options = {}, onEffectResult, }) {
var _a, _b, _c;
const enableAdvanced = (_a = options.enableAdvancedControl) !== null && _a !== void 0 ? _a : false;
const debugLog = (_b = options.debugLog) !== null && _b !== void 0 ? _b : false;
const effectActions = (_c = options.effectActions) !== null && _c !== void 0 ? _c : {};
const trigger = react.useCallback((field, chain, visited, overrideValue) => {
// 参数验证
if (!field || typeof field !== "string") {
console.error("[form-chain-effect-engine] 无效的字段名称:", field);
return;
}
if (visited.has(field)) {
if (debugLog) {
console.warn(`[form-chain-effect-engine] 检测到循环依赖,链路已终止: ${[...chain.path, field].join(" → ")}`);
}
return;
}
visited.add(field);
const item = config[field];
if (!item) {
if (debugLog) {
console.log(`[form-chain-effect-engine] 字段 ${field} 未在配置中找到`);
}
return;
}
// 安全地获取表单值
let currentVal;
let allValues;
try {
currentVal =
overrideValue !== undefined
? overrideValue
: form.getFieldValue(field);
allValues = form.getFieldsValue();
}
catch (err) {
console.error(`[form-chain-effect-engine] 获取表单值失败: 字段 ${field}, 错误:`, err);
return;
}
if (debugLog) {
console.log(`[form-chain-effect-engine] 触发 effect: ${field}, 当前值:`, currentVal, ", 链路:", chain.path);
}
let result;
if (item.effect && typeof item.effect === "function") {
try {
result = item.effect(currentVal, allValues, chain, effectActions);
}
catch (err) {
console.error(`[form-chain-effect-engine] effect 执行异常: 字段 ${field}, 错误:`, err);
// 不中断链路,继续执行依赖字段
}
}
if (result) {
// 处理异步 effect 的返回值
if (result instanceof Promise) {
result
.then((resolvedResult) => {
if (resolvedResult) {
try {
onEffectResult === null || onEffectResult === void 0 ? void 0 : onEffectResult({
fieldName: field,
field: item,
result: resolvedResult,
chain,
currentVal,
allValues,
});
}
catch (err) {
console.error(`[form-chain-effect-engine] onEffectResult 回调执行异常: 字段 ${field}, 错误:`, err);
}
}
})
.catch((err) => {
console.error(`[form-chain-effect-engine] 异步 effect 执行异常: 字段 ${field}, 错误:`, err);
});
}
else {
try {
onEffectResult === null || onEffectResult === void 0 ? void 0 : onEffectResult({
fieldName: field,
field: item,
result,
chain,
currentVal,
allValues,
});
}
catch (err) {
console.error(`[form-chain-effect-engine] onEffectResult 回调执行异常: 字段 ${field}, 错误:`, err);
}
}
}
if (enableAdvanced && chain.isStopped) {
if (debugLog) {
console.log(`[form-chain-effect-engine] 链路已停止: ${field}`);
}
return;
}
if (item.dependents && item.dependents.length > 0) {
for (const dep of item.dependents) {
// 验证依赖字段名称
if (!dep || typeof dep !== "string") {
console.error(`[form-chain-effect-engine] 无效的依赖字段名称: ${dep}, 来源字段: ${field}`);
continue;
}
trigger(dep, extendChain(chain, dep), visited);
}
}
}, [form, config, enableAdvanced, debugLog, effectActions, onEffectResult]);
const onValuesChange = react.useCallback((changed) => {
if (!changed || typeof changed !== "object") {
console.error("[form-chain-effect-engine] 无效的 changed 参数:", changed);
return;
}
const visited = new Set();
const changedKeys = Object.keys(changed);
if (changedKeys.length === 0) {
if (debugLog) {
console.log("[form-chain-effect-engine] 没有检测到字段变更");
}
return;
}
// 只处理第一个变更的字段(保持原有逻辑)
const changedKey = changedKeys[0];
trigger(changedKey, createChain(changedKey, enableAdvanced), visited);
}, [trigger, enableAdvanced, debugLog]);
const manualTrigger = react.useCallback((field, value) => {
if (!field || typeof field !== "string") {
console.error("[form-chain-effect-engine] 无效的字段名称:", field);
return;
}
const visited = new Set();
const chain = createChain(field, enableAdvanced);
trigger(field, chain, visited, value);
}, [trigger, enableAdvanced]);
return {
onValuesChange,
manualTrigger,
};
}
exports.useFormChainEffectEngine = useFormChainEffectEngine;
//# sourceMappingURL=index.cjs.js.map