refactor(ui): clean code

This commit is contained in:
Fu Diwei 2025-03-06 20:59:40 +08:00
parent 5b2bc6bff9
commit 574ad0445e
5 changed files with 59 additions and 31 deletions

View File

@ -8,7 +8,6 @@
1. 原始包必须通过移动云私有仓库获取, 为构建带来不便。
2. 原始包存在部分内容错误, 需要自行修改, 如:
- 存在一些编译错误;
- 返回错误的时候, 未返回错误信息;
- 解析响应体错误。

View File

@ -173,8 +173,13 @@ export type WorkflowNodeIOValueSelector = {
id: string;
name: string;
};
// #endregion
const isBranchLike = (node: WorkflowNode) => {
return node.type === WorkflowNodeType.Branch || node.type === WorkflowNodeType.ExecuteResultBranch;
};
type InitWorkflowOptions = {
template?: "standard";
};
@ -268,11 +273,15 @@ export const updateNode = (node: WorkflowNode, targetNode: WorkflowNode) => {
Object.assign(current, targetNode);
break;
}
if (current.type === WorkflowNodeType.Branch || current.type === WorkflowNodeType.ExecuteResultBranch) {
current.branches = current.branches!.map((branch) => updateNode(branch, targetNode));
if (isBranchLike(current)) {
current.branches ??= [];
current.branches = current.branches.map((branch) => updateNode(branch, targetNode));
}
current = current.next as WorkflowNode;
}
return draft;
});
};
@ -281,20 +290,24 @@ export const addNode = (node: WorkflowNode, previousNodeId: string, targetNode:
return produce(node, (draft) => {
let current = draft;
while (current) {
if (current.id === previousNodeId && targetNode.type !== WorkflowNodeType.Branch && targetNode.type !== WorkflowNodeType.ExecuteResultBranch) {
if (current.id === previousNodeId && !isBranchLike(targetNode)) {
targetNode.next = current.next;
current.next = targetNode;
break;
} else if (current.id === previousNodeId && (targetNode.type === WorkflowNodeType.Branch || targetNode.type === WorkflowNodeType.ExecuteResultBranch)) {
} else if (current.id === previousNodeId && isBranchLike(targetNode)) {
targetNode.branches![0].next = current.next;
current.next = targetNode;
break;
}
if (current.type === WorkflowNodeType.Branch || current.type === WorkflowNodeType.ExecuteResultBranch) {
current.branches = current.branches!.map((branch) => addNode(branch, previousNodeId, targetNode));
if (isBranchLike(current)) {
current.branches ??= [];
current.branches = current.branches.map((branch) => addNode(branch, previousNodeId, targetNode));
}
current = current.next as WorkflowNode;
}
return draft;
});
};
@ -307,18 +320,24 @@ export const addBranch = (node: WorkflowNode, branchNodeId: string) => {
if (current.type !== WorkflowNodeType.Branch) {
return draft;
}
current.branches!.push(
current.branches ??= [];
current.branches.push(
newNode(WorkflowNodeType.Condition, {
branchIndex: current.branches!.length,
branchIndex: current.branches.length,
})
);
break;
}
if (current.type === WorkflowNodeType.Branch || current.type === WorkflowNodeType.ExecuteResultBranch) {
current.branches = current.branches!.map((branch) => addBranch(branch, branchNodeId));
if (isBranchLike(current)) {
current.branches ??= [];
current.branches = current.branches.map((branch) => addBranch(branch, branchNodeId));
}
current = current.next as WorkflowNode;
}
return draft;
});
};
@ -331,11 +350,15 @@ export const removeNode = (node: WorkflowNode, targetNodeId: string) => {
current.next = current.next.next;
break;
}
if (current.type === WorkflowNodeType.Branch || current.type === WorkflowNodeType.ExecuteResultBranch) {
current.branches = current.branches!.map((branch) => removeNode(branch, targetNodeId));
if (isBranchLike(current)) {
current.branches ??= [];
current.branches = current.branches.map((branch) => removeNode(branch, targetNodeId));
}
current = current.next as WorkflowNode;
}
return draft;
});
};
@ -351,14 +374,16 @@ export const removeBranch = (node: WorkflowNode, branchNodeId: string, branchInd
};
while (current && last) {
if (current.id === branchNodeId) {
if (current.type !== WorkflowNodeType.Branch && current.type !== WorkflowNodeType.ExecuteResultBranch) {
if (!isBranchLike(current)) {
return draft;
}
current.branches!.splice(branchIndex, 1);
current.branches ??= [];
current.branches.splice(branchIndex, 1);
// 如果仅剩一个分支,删除分支节点,将分支节点的下一个节点挂载到当前节点
if (current.branches!.length === 1) {
const branch = current.branches![0];
if (current.branches.length === 1) {
const branch = current.branches[0];
if (branch.next) {
last.next = branch.next;
let lastNode: WorkflowNode | undefined = branch.next;
@ -373,19 +398,23 @@ export const removeBranch = (node: WorkflowNode, branchNodeId: string, branchInd
break;
}
if (current.type === WorkflowNodeType.Branch || current.type === WorkflowNodeType.ExecuteResultBranch) {
current.branches = current.branches!.map((branch) => removeBranch(branch, branchNodeId, branchIndex));
if (isBranchLike(current)) {
current.branches ??= [];
current.branches = current.branches.map((branch) => removeBranch(branch, branchNodeId, branchIndex));
}
current = current.next as WorkflowNode;
last = last.next;
}
return draft;
});
};
export const getWorkflowOutputBeforeId = (root: WorkflowNode, nodeId: string, type: string): WorkflowNode[] => {
// 1 个分支的节点,不应该能获取到相邻分支上节点的输出
const output: WorkflowNode[] = [];
export const getOutputBeforeNodeId = (root: WorkflowNode, nodeId: string, type: string): WorkflowNode[] => {
// 个分支的节点,不应该能获取到相邻分支上节点的输出
const outputs: WorkflowNode[] = [];
const traverse = (current: WorkflowNode, output: WorkflowNode[]) => {
if (!current) {
@ -395,7 +424,7 @@ export const getWorkflowOutputBeforeId = (root: WorkflowNode, nodeId: string, ty
return true;
}
// 如果当前节点是execute_failure,清除execute_result_branch节点前一个节点的输出
// 如果当前节点是 ExecuteFailure清除 ExecuteResultBranch 节点前一个节点的输出
if (current.type === WorkflowNodeType.ExecuteFailure) {
output.splice(output.length - 1);
}
@ -407,7 +436,7 @@ export const getWorkflowOutputBeforeId = (root: WorkflowNode, nodeId: string, ty
});
}
if (current.type === WorkflowNodeType.Branch || current.type === WorkflowNodeType.ExecuteResultBranch) {
if (isBranchLike(current)) {
const currentLength = output.length;
for (const branch of current.branches!) {
if (traverse(branch, output)) {
@ -423,14 +452,14 @@ export const getWorkflowOutputBeforeId = (root: WorkflowNode, nodeId: string, ty
return traverse(current.next as WorkflowNode, output);
};
traverse(root, output);
return output;
traverse(root, outputs);
return outputs;
};
export const isAllNodesValidated = (node: WorkflowNode): boolean => {
let current = node as typeof node | undefined;
while (current) {
if (current.type === WorkflowNodeType.Branch || current.type === WorkflowNodeType.ExecuteResultBranch) {
if (isBranchLike(current)) {
for (const branch of current.branches!) {
if (!isAllNodesValidated(branch)) {
return false;

View File

@ -20,7 +20,7 @@
"workflow_node.start.form.trigger_cron.errmsg.invalid": "Please enter a valid cron expression",
"workflow_node.start.form.trigger_cron.tooltip": "Exactly 5 space separated segments. Time zone is based on the server.",
"workflow_node.start.form.trigger_cron.extra": "Expected execution time for the last 5 times:",
"workflow_node.start.form.trigger_cron.guide": "Tips: If you have multiple workflows, it is recommended to set them to run at multiple times of the day instead of always running at specific times.<br><br>Reference links:<br>1. <a href=\"https://letsencrypt.org/docs/rate-limits/\" target=\"_blank\">Lets Encrypt rate limits</a><br>2. <a href=\"https://letsencrypt.org/docs/faq/#why-should-my-let-s-encrypt-acme-client-run-at-a-random-time\" target=\"_blank\">Why should my Lets Encrypt (ACME) client run at a random time?</a>",
"workflow_node.start.form.trigger_cron.guide": "Tips: If you have multiple workflows, it is recommended to set them to run at multiple times of the day instead of always running at specific times. Don't always set it to midnight every day to avoid spikes in traffic.<br><br>Reference links:<br>1. <a href=\"https://letsencrypt.org/docs/rate-limits/\" target=\"_blank\">Lets Encrypt rate limits</a><br>2. <a href=\"https://letsencrypt.org/docs/faq/#why-should-my-let-s-encrypt-acme-client-run-at-a-random-time\" target=\"_blank\">Why should my Lets Encrypt (ACME) client run at a random time?</a>",
"workflow_node.apply.label": "Application",
"workflow_node.apply.form.domains.label": "Domains",

View File

@ -20,7 +20,7 @@
"workflow_node.start.form.trigger_cron.errmsg.invalid": "请输入正确的 Cron 表达式",
"workflow_node.start.form.trigger_cron.tooltip": "五段式表达式,支持使用任意值(即 <strong>*</strong>)、值列表分隔符(即 <strong>,</strong>)、值的范围(即 <strong>-</strong>)、步骤值(即 <strong>/</strong>)等四种表达式。时区以服务器设置为准。",
"workflow_node.start.form.trigger_cron.extra": "预计最近 5 次执行时间:",
"workflow_node.start.form.trigger_cron.guide": "小贴士:如果你有多个工作流,建议将它们设置为在一天中的多个时间段运行,而非总是在相同的特定时间。<br><br>参考链接:<br>1. <a href=\"https://letsencrypt.org/zh-cn/docs/rate-limits/\" target=\"_blank\">Lets Encrypt 速率限制</a><br>2. <a href=\"https://letsencrypt.org/zh-cn/docs/faq/#%E4%B8%BA%E4%BB%80%E4%B9%88%E6%88%91%E7%9A%84-let-s-encrypt-acme-%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%90%AF%E5%8A%A8%E6%97%B6%E9%97%B4%E5%BA%94%E5%BD%93%E9%9A%8F%E6%9C%BA\" target=\"_blank\">为什么我的 Lets Encrypt (ACME) 客户端启动时间应当随机?</a>",
"workflow_node.start.form.trigger_cron.guide": "小贴士:如果你有多个工作流,建议将它们设置为在一天中的多个时间段运行,而非总是在相同的特定时间。也不要总是设置为每日零时,以免遭遇证书颁发机构的流量高峰。<br><br>参考链接:<br>1. <a href=\"https://letsencrypt.org/zh-cn/docs/rate-limits/\" target=\"_blank\">Lets Encrypt 速率限制</a><br>2. <a href=\"https://letsencrypt.org/zh-cn/docs/faq/#%E4%B8%BA%E4%BB%80%E4%B9%88%E6%88%91%E7%9A%84-let-s-encrypt-acme-%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%90%AF%E5%8A%A8%E6%97%B6%E9%97%B4%E5%BA%94%E5%BD%93%E9%9A%8F%E6%9C%BA\" target=\"_blank\">为什么我的 Lets Encrypt (ACME) 客户端启动时间应当随机?</a>",
"workflow_node.apply.label": "申请",
"workflow_node.apply.form.domains.label": "域名",

View File

@ -7,7 +7,7 @@ import {
type WorkflowNodeConfigForStart,
addBranch,
addNode,
getWorkflowOutputBeforeId,
getOutputBeforeNodeId,
removeBranch,
removeNode,
updateNode,
@ -244,6 +244,6 @@ export const useWorkflowStore = create<WorkflowState>((set, get) => ({
},
getWorkflowOuptutBeforeId: (nodeId: string, type: string) => {
return getWorkflowOutputBeforeId(get().workflow.draft as WorkflowNode, nodeId, type);
return getOutputBeforeNodeId(get().workflow.draft as WorkflowNode, nodeId, type);
},
}));