refactor code

This commit is contained in:
Yoan.liu
2025-05-22 17:09:14 +08:00
parent 75326b1ddd
commit 9cdc59b272
15 changed files with 312 additions and 176 deletions

View File

@@ -5,7 +5,7 @@ import { Button, Card, Popover } from "antd";
import SharedNode, { type SharedNodeProps } from "./_SharedNode";
import AddNode from "./AddNode";
import ConditionNodeConfigForm, { ConditionItem, ConditionNodeConfigFormFieldValues, ConditionNodeConfigFormInstance } from "./ConditionNodeConfigForm";
import { Expr, WorkflowNodeIoValueType, Value } from "@/domain/workflow";
import { Expr, WorkflowNodeIoValueType, ExprType } from "@/domain/workflow";
import { produce } from "immer";
import { useWorkflowStore } from "@/stores/workflow";
import { useZustandShallowSelector } from "@/hooks";
@@ -32,7 +32,7 @@ const ConditionNode = ({ node, disabled, branchId, branchIndex }: ConditionNodeP
const selectors = condition.leftSelector.split("#");
const t = selectors[2] as WorkflowNodeIoValueType;
const left: Expr = {
type: "var",
type: ExprType.Var,
selector: {
id: selectors[0],
name: selectors[1],
@@ -40,27 +40,10 @@ const ConditionNode = ({ node, disabled, branchId, branchIndex }: ConditionNodeP
},
};
let value: Value = condition.rightValue;
switch (t) {
case "boolean":
if (value === "true") {
value = true;
} else if (value === "false") {
value = false;
}
break;
case "number":
value = parseInt(value as string);
break;
case "string":
value = value as string;
break;
}
const right: Expr = { type: "const", value: value, valueType: t };
const right: Expr = { type: ExprType.Const, value: condition.rightValue, valueType: t };
return {
type: "compare",
type: ExprType.Compare,
op: condition.operator,
left,
right,
@@ -77,7 +60,7 @@ const ConditionNode = ({ node, disabled, branchId, branchIndex }: ConditionNodeP
for (let i = 1; i < values.conditions.length; i++) {
expr = {
type: "logical",
type: ExprType.Logical,
op: values.logicalOperator,
left: expr,
right: createComparisonExpr(values.conditions[i]),

View File

@@ -14,6 +14,7 @@ import {
WorkflowNode,
workflowNodeIOOptions,
WorkflowNodeIoValueType,
ExprType,
} from "@/domain/workflow";
import { FormInstance } from "antd";
import { useZustandShallowSelector } from "@/hooks";
@@ -58,7 +59,7 @@ const initFormModel = (): ConditionNodeConfigFormFieldValues => {
rightValue: "",
},
],
logicalOperator: "and",
logicalOperator: LogicalOperator.And,
};
};
@@ -67,10 +68,10 @@ const expressionToForm = (expr?: Expr): ConditionNodeConfigFormFieldValues => {
if (!expr) return initFormModel();
const conditions: ConditionItem[] = [];
let logicalOp: LogicalOperator = "and";
let logicalOp: LogicalOperator = LogicalOperator.And;
const extractComparisons = (expr: Expr): void => {
if (expr.type === "compare") {
if (expr.type === ExprType.Compare) {
// 确保左侧是变量,右侧是常量
if (isVarExpr(expr.left) && isConstExpr(expr.right)) {
conditions.push({
@@ -79,7 +80,7 @@ const expressionToForm = (expr?: Expr): ConditionNodeConfigFormFieldValues => {
rightValue: String(expr.right.value),
});
}
} else if (expr.type === "logical") {
} else if (expr.type === ExprType.Logical) {
logicalOp = expr.op;
extractComparisons(expr.left);
extractComparisons(expr.right);
@@ -304,25 +305,18 @@ const formToExpression = (values: ConditionNodeConfigFormFieldValues): Expr => {
const type = typeStr as WorkflowNodeIoValueType;
const left: Expr = {
type: "var",
type: ExprType.Var,
selector: { id, name, type },
};
let rightValue: any = condition.rightValue;
if (type === "number") {
rightValue = Number(condition.rightValue);
} else if (type === "boolean") {
rightValue = condition.rightValue === "true";
}
const right: Expr = {
type: "const",
value: rightValue,
type: ExprType.Const,
value: condition.rightValue,
valueType: type,
};
return {
type: "compare",
type: ExprType.Compare,
op: condition.operator,
left,
right,
@@ -339,7 +333,7 @@ const formToExpression = (values: ConditionNodeConfigFormFieldValues): Expr => {
for (let i = 1; i < values.conditions.length; i++) {
expr = {
type: "logical",
type: ExprType.Logical,
op: values.logicalOperator,
left: expr,
right: createComparisonExpr(values.conditions[i]),

View File

@@ -39,7 +39,7 @@ const InspectNode = ({ node, disabled }: InspectNodeProps) => {
const config = (node.config as WorkflowNodeConfigForInspect) ?? {};
return (
<Flex className="size-full overflow-hidden" align="center" gap={8}>
<Typography.Text className="truncate">{config.domain ?? ""}</Typography.Text>
<Typography.Text className="truncate">{config.host ?? ""}</Typography.Text>
</Flex>
);
}, [node]);

View File

@@ -7,7 +7,7 @@ import { z } from "zod";
import { type WorkflowNodeConfigForInspect } from "@/domain/workflow";
import { useAntdForm } from "@/hooks";
import { validDomainName, validPortNumber } from "@/utils/validators";
import { validDomainName, validIPv4Address, validPortNumber } from "@/utils/validators";
type InspectNodeConfigFormFieldValues = Partial<WorkflowNodeConfigForInspect>;
@@ -29,6 +29,8 @@ const initFormModel = (): InspectNodeConfigFormFieldValues => {
return {
domain: "",
port: "443",
path: "",
host: "",
};
};
@@ -37,12 +39,14 @@ const InspectNodeConfigForm = forwardRef<InspectNodeConfigFormInstance, InspectN
const { t } = useTranslation();
const formSchema = z.object({
domain: z.string().refine((val) => validDomainName(val), {
message: t("workflow_node.inspect.form.domain.placeholder"),
host: z.string().refine((val) => validIPv4Address(val) || validDomainName(val), {
message: t("workflow_node.inspect.form.host.placeholder"),
}),
domain: z.string().optional(),
port: z.string().refine((val) => validPortNumber(val), {
message: t("workflow_node.inspect.form.port.placeholder"),
}),
path: z.string().optional(),
});
const formRule = createSchemaFieldRule(formSchema);
const { form: formInst, formProps } = useAntdForm({
@@ -70,13 +74,21 @@ const InspectNodeConfigForm = forwardRef<InspectNodeConfigFormInstance, InspectN
return (
<Form className={className} style={style} {...formProps} disabled={disabled} layout="vertical" scrollToFirstError onValuesChange={handleFormChange}>
<Form.Item name="domain" label={t("workflow_node.inspect.form.domain.label")} rules={[formRule]}>
<Input variant="filled" placeholder={t("workflow_node.inspect.form.domain.placeholder")} />
<Form.Item name="host" label={t("workflow_node.inspect.form.host.label")} rules={[formRule]}>
<Input variant="filled" placeholder={t("workflow_node.inspect.form.host.placeholder")} />
</Form.Item>
<Form.Item name="port" label={t("workflow_node.inspect.form.port.label")} rules={[formRule]}>
<Input variant="filled" placeholder={t("workflow_node.inspect.form.port.placeholder")} />
</Form.Item>
<Form.Item name="domain" label={t("workflow_node.inspect.form.domain.label")} rules={[formRule]}>
<Input variant="filled" placeholder={t("workflow_node.inspect.form.domain.placeholder")} />
</Form.Item>
<Form.Item name="path" label={t("workflow_node.inspect.form.path.label")} rules={[formRule]}>
<Input variant="filled" placeholder={t("workflow_node.inspect.form.path.placeholder")} />
</Form.Item>
</Form>
);
}

View File

@@ -67,7 +67,7 @@ const workflowNodeTypeDefaultInputs: Map<WorkflowNodeType, WorkflowNodeIO[]> = n
name: "certificate",
type: "certificate",
required: true,
label: "证书",
label: i18n.t("workflow.variables.certificate.label"),
},
],
],
@@ -82,7 +82,7 @@ const workflowNodeTypeDefaultOutputs: Map<WorkflowNodeType, WorkflowNodeIO[]> =
name: "certificate",
type: "certificate",
required: true,
label: "证书",
label: i18n.t("workflow.variables.certificate.label"),
},
],
],
@@ -93,7 +93,7 @@ const workflowNodeTypeDefaultOutputs: Map<WorkflowNodeType, WorkflowNodeIO[]> =
name: "certificate",
type: "certificate",
required: true,
label: "证书",
label: i18n.t("workflow.variables.certificate.label"),
},
],
],
@@ -104,7 +104,7 @@ const workflowNodeTypeDefaultOutputs: Map<WorkflowNodeType, WorkflowNodeIO[]> =
name: "certificate",
type: "certificate",
required: true,
label: "证书",
label: i18n.t("workflow.variables.certificate.label"),
},
],
],
@@ -161,6 +161,8 @@ export type WorkflowNodeConfigForUpload = {
export type WorkflowNodeConfigForInspect = {
domain: string;
port: string;
host: string;
path: string;
};
export type WorkflowNodeConfigForDeploy = {
@@ -200,14 +202,20 @@ export type WorkflowNodeIO = {
valueSelector?: WorkflowNodeIOValueSelector;
};
export const VALUE_TYPES = Object.freeze({
STRING: "string",
NUMBER: "number",
BOOLEAN: "boolean",
} as const);
export type WorkflowNodeIoValueType = (typeof VALUE_TYPES)[keyof typeof VALUE_TYPES];
export type WorkflowNodeIOValueSelector = {
id: string;
name: string;
type: WorkflowNodeIoValueType;
};
export type WorkflowNodeIoValueType = "string" | "number" | "boolean";
type WorkflowNodeIOOptions = {
label: string;
value: string;
@@ -224,12 +232,12 @@ export const workflowNodeIOOptions = (node: WorkflowNode) => {
switch (output.type) {
case "certificate":
rs.options.push({
label: `${node.name} - ${output.label} - 是否有效`,
label: `${node.name} - ${output.label} - ${i18n.t("workflow.variables.is_validated.label")}`,
value: `${node.id}#${output.name}.validated#boolean`,
});
rs.options.push({
label: `${node.name} - ${output.label} - 剩余天数`,
label: `${node.name} - ${output.label} - ${i18n.t("workflow.variables.days_left.label")}`,
value: `${node.id}#${output.name}.daysLeft#number`,
});
break;
@@ -254,22 +262,34 @@ export type Value = string | number | boolean;
export type ComparisonOperator = ">" | "<" | ">=" | "<=" | "==" | "!=" | "is";
export type LogicalOperator = "and" | "or" | "not";
export enum LogicalOperator {
And = "and",
Or = "or",
Not = "not",
}
export type ConstExpr = { type: "const"; value: Value; valueType: WorkflowNodeIoValueType };
export type VarExpr = { type: "var"; selector: WorkflowNodeIOValueSelector };
export type CompareExpr = { type: "compare"; op: ComparisonOperator; left: Expr; right: Expr };
export type LogicalExpr = { type: "logical"; op: LogicalOperator; left: Expr; right: Expr };
export type NotExpr = { type: "not"; expr: Expr };
export enum ExprType {
Const = "const",
Var = "var",
Compare = "compare",
Logical = "logical",
Not = "not",
}
export type ConstExpr = { type: ExprType.Const; value: string; valueType: WorkflowNodeIoValueType };
export type VarExpr = { type: ExprType.Var; selector: WorkflowNodeIOValueSelector };
export type CompareExpr = { type: ExprType.Compare; op: ComparisonOperator; left: Expr; right: Expr };
export type LogicalExpr = { type: ExprType.Logical; op: LogicalOperator; left: Expr; right: Expr };
export type NotExpr = { type: ExprType.Not; expr: Expr };
export type Expr = ConstExpr | VarExpr | CompareExpr | LogicalExpr | NotExpr;
export const isConstExpr = (expr: Expr): expr is ConstExpr => {
return expr.type === "const";
return expr.type === ExprType.Const;
};
export const isVarExpr = (expr: Expr): expr is VarExpr => {
return expr.type === "var";
return expr.type === ExprType.Var;
};
// #endregion

View File

@@ -53,5 +53,9 @@
"workflow.detail.orchestration.action.run": "Run",
"workflow.detail.orchestration.action.run.confirm": "You have unreleased changes. Do you really want to run this workflow based on the latest released version?",
"workflow.detail.orchestration.action.run.prompt": "Running... Please check the history later",
"workflow.detail.runs.tab": "History runs"
"workflow.detail.runs.tab": "History runs",
"workflow.variables.is_validated.label": "Is valid",
"workflow.variables.days_left.label": "Days left",
"workflow.variables.certificate.label": "Certificate"
}

View File

@@ -806,6 +806,10 @@
"workflow_node.inspect.form.domain.placeholder": "Please enter domain name",
"workflow_node.inspect.form.port.label": "Port",
"workflow_node.inspect.form.port.placeholder": "Please enter port",
"workflow_node.inspect.form.host.label": "Host",
"workflow_node.inspect.form.host.placeholder": "Please enter host",
"workflow_node.inspect.form.path.label": "Path",
"workflow_node.inspect.form.path.placeholder": "Please enter path",
"workflow_node.notify.label": "Notification",
"workflow_node.notify.form.subject.label": "Subject",

View File

@@ -53,5 +53,9 @@
"workflow.detail.orchestration.action.run": "执行",
"workflow.detail.orchestration.action.run.confirm": "你有尚未发布的更改。确定要以最近一次发布的版本继续执行吗?",
"workflow.detail.orchestration.action.run.prompt": "执行中……请稍后查看执行历史",
"workflow.detail.runs.tab": "执行历史"
"workflow.detail.runs.tab": "执行历史",
"workflow.variables.is_validated.label": "是否有效",
"workflow.variables.days_left.label": "剩余天数",
"workflow.variables.certificate.label": "证书"
}

View File

@@ -805,6 +805,10 @@
"workflow_node.inspect.form.domain.placeholder": "请输入要检查的网站域名",
"workflow_node.inspect.form.port.label": "端口号",
"workflow_node.inspect.form.port.placeholder": "请输入要检查的端口号",
"workflow_node.inspect.form.host.label": "Host",
"workflow_node.inspect.form.host.placeholder": "请输入 Host",
"workflow_node.inspect.form.path.label": "Path",
"workflow_node.inspect.form.path.placeholder": "请输入 Path",
"workflow_node.notify.label": "推送通知",
"workflow_node.notify.form.subject.label": "通知主题",