feat: execute node python version

This commit is contained in:
tao.chen
2026-08-11 19:00:55 +08:00
parent 38cd06ee7a
commit e80cbbd81c
5 changed files with 56 additions and 22 deletions
@@ -1,15 +1,7 @@
import { type ScheduleNode } from "../../services/api"; import { type ScheduleNode } from "../../services/api";
import Icon from "../../components/common/Icon"; import Icon from "../../components/common/Icon";
import { shortHash } from "./utils"; import { shortHash } from "./utils";
import { PYTHON_VERSION_OPTIONS, type NodeForm } from "./state/schedulesStore";
type NodeForm = {
nodeName: string;
timeoutSeconds: string;
retryCount: string;
retryIntervalSec: string;
argumentsJson: string;
envRefsJson: string;
};
export function NodeInspector({ export function NodeInspector({
node, node,
@@ -88,18 +80,36 @@ export function NodeInspector({
/> />
</label> </label>
</div> </div>
<label> <div className="inspector-grid">
<span></span> <label>
<input <span></span>
type="number" <input
min="0" type="number"
value={form.retryIntervalSec} min="0"
onChange={(event) => onChange({ value={form.retryIntervalSec}
...form, onChange={(event) => onChange({
retryIntervalSec: event.target.value, ...form,
})} retryIntervalSec: event.target.value,
/> })}
</label> />
</label>
<label>
<span>Python </span>
<select
value={form.pythonVersion}
onChange={(event) => onChange({
...form,
pythonVersion: event.target.value as NodeForm["pythonVersion"],
})}
>
{PYTHON_VERSION_OPTIONS.map((option) => (
<option key={option} value={option}>
{option}
</option>
))}
</select>
</label>
</div>
</section> </section>
<section> <section>
<h3></h3> <h3></h3>
@@ -24,6 +24,7 @@ export const EMPTY_NODE_FORM = {
retryIntervalSec: "5", retryIntervalSec: "5",
argumentsJson: "{}", argumentsJson: "{}",
envRefsJson: "{}", envRefsJson: "{}",
pythonVersion: "3.12" as "3.8" | "3.10" | "3.12",
}; };
export const RUN_STATUS_LABELS: Record<string, string> = { export const RUN_STATUS_LABELS: Record<string, string> = {
@@ -33,6 +33,14 @@ export type ScheduleForm = {
failurePolicy: "stop" | "continue"; failurePolicy: "stop" | "continue";
}; };
export type PythonVersion = "3.8" | "3.10" | "3.12";
export const PYTHON_VERSION_OPTIONS: readonly PythonVersion[] = [
"3.8",
"3.10",
"3.12",
];
export type NodeForm = { export type NodeForm = {
nodeName: string; nodeName: string;
timeoutSeconds: string; timeoutSeconds: string;
@@ -40,6 +48,7 @@ export type NodeForm = {
retryIntervalSec: string; retryIntervalSec: string;
argumentsJson: string; argumentsJson: string;
envRefsJson: string; envRefsJson: string;
pythonVersion: PythonVersion;
}; };
export type NodePositionDraft = { export type NodePositionDraft = {
@@ -77,6 +86,7 @@ export const EMPTY_NODE_FORM: NodeForm = {
retryIntervalSec: "5", retryIntervalSec: "5",
argumentsJson: "{}", argumentsJson: "{}",
envRefsJson: "{}", envRefsJson: "{}",
pythonVersion: "3.12",
}; };
// ---- Module-level non-reactive holders ---- // ---- Module-level non-reactive holders ----
@@ -124,6 +134,7 @@ function nodeToForm(node: ScheduleNode): NodeForm {
retryIntervalSec: String(node.retry_interval_sec), retryIntervalSec: String(node.retry_interval_sec),
argumentsJson: JSON.stringify(node.arguments_json ?? {}, null, 2), argumentsJson: JSON.stringify(node.arguments_json ?? {}, null, 2),
envRefsJson: JSON.stringify(node.env_refs_json ?? {}, null, 2), envRefsJson: JSON.stringify(node.env_refs_json ?? {}, null, 2),
pythonVersion: (node.python_version ?? "3.12") as PythonVersion,
}; };
} }
@@ -855,6 +866,7 @@ export const useSchedulesStore = create<State & Actions>((set, get) => {
position_y: Math.max(20, Math.round(positionY)), position_y: Math.max(20, Math.round(positionY)),
arguments_json: {}, arguments_json: {},
env_refs_json: {}, env_refs_json: {},
python_version: "3.12",
}), }),
`${artifact.script_name} 已加入画布`, `${artifact.script_name} 已加入画布`,
); );
@@ -883,6 +895,9 @@ export const useSchedulesStore = create<State & Actions>((set, get) => {
if (!Number.isInteger(retryIntervalSec) || retryIntervalSec < 0) { if (!Number.isInteger(retryIntervalSec) || retryIntervalSec < 0) {
throw new Error("重试间隔必须是非负整数"); throw new Error("重试间隔必须是非负整数");
} }
if (!PYTHON_VERSION_OPTIONS.includes(nodeForm.pythonVersion)) {
throw new Error("Python 版本必须是 3.8 / 3.10 / 3.12");
}
const argumentsJson = parseObject(nodeForm.argumentsJson, "运行参数"); const argumentsJson = parseObject(nodeForm.argumentsJson, "运行参数");
const rawEnv = parseObject(nodeForm.envRefsJson, "环境引用"); const rawEnv = parseObject(nodeForm.envRefsJson, "环境引用");
const envRefsJson = Object.fromEntries( const envRefsJson = Object.fromEntries(
@@ -907,6 +922,7 @@ export const useSchedulesStore = create<State & Actions>((set, get) => {
retry_interval_sec: retryIntervalSec, retry_interval_sec: retryIntervalSec,
arguments_json: argumentsJson, arguments_json: argumentsJson,
env_refs_json: envRefsJson, env_refs_json: envRefsJson,
python_version: nodeForm.pythonVersion,
}, },
), ),
"节点配置已保存", "节点配置已保存",
+3 -1
View File
@@ -6,6 +6,7 @@ import {
type ScheduleRunSummary, type ScheduleRunSummary,
} from "../../services/api"; } from "../../services/api";
import { EMPTY_SCHEDULE_FORM, EMPTY_NODE_FORM } from "./constants"; import { EMPTY_SCHEDULE_FORM, EMPTY_NODE_FORM } from "./constants";
import type { NodeForm } from "./state/schedulesStore";
export function formatTime(value: string | null): string { export function formatTime(value: string | null): string {
if (!value) return "尚未执行"; if (!value) return "尚未执行";
@@ -82,7 +83,7 @@ export function scheduleToForm(schedule: Schedule) {
}; };
} }
export function nodeToForm(node: ScheduleNode) { export function nodeToForm(node: ScheduleNode): NodeForm {
return { return {
nodeName: node.node_name, nodeName: node.node_name,
timeoutSeconds: String(node.timeout_seconds), timeoutSeconds: String(node.timeout_seconds),
@@ -90,6 +91,7 @@ export function nodeToForm(node: ScheduleNode) {
retryIntervalSec: String(node.retry_interval_sec), retryIntervalSec: String(node.retry_interval_sec),
argumentsJson: JSON.stringify(node.arguments_json ?? {}, null, 2), argumentsJson: JSON.stringify(node.arguments_json ?? {}, null, 2),
envRefsJson: JSON.stringify(node.env_refs_json ?? {}, null, 2), envRefsJson: JSON.stringify(node.env_refs_json ?? {}, null, 2),
pythonVersion: node.python_version ?? "3.12",
}; };
} }
+5
View File
@@ -658,6 +658,8 @@ export type ScheduleArtifact = {
created_at: string; created_at: string;
}; };
export type PythonVersion = "3.8" | "3.10" | "3.12";
export type ScheduleNode = { export type ScheduleNode = {
node_id: string; node_id: string;
schedule_id: string; schedule_id: string;
@@ -671,6 +673,7 @@ export type ScheduleNode = {
position_y: number; position_y: number;
arguments_json: Record<string, unknown>; arguments_json: Record<string, unknown>;
env_refs_json: Record<string, string>; env_refs_json: Record<string, string>;
python_version: PythonVersion;
created_at: string; created_at: string;
updated_at: string; updated_at: string;
version: { version: {
@@ -1093,6 +1096,7 @@ export async function createScheduleNode(
position_y?: number; position_y?: number;
arguments_json?: Record<string, unknown>; arguments_json?: Record<string, unknown>;
env_refs_json?: Record<string, string>; env_refs_json?: Record<string, string>;
python_version?: PythonVersion;
}, },
): Promise<Schedule> { ): Promise<Schedule> {
return apiRequest<Schedule>( return apiRequest<Schedule>(
@@ -1117,6 +1121,7 @@ export async function updateScheduleNode(
position_y?: number; position_y?: number;
arguments_json?: Record<string, unknown>; arguments_json?: Record<string, unknown>;
env_refs_json?: Record<string, string>; env_refs_json?: Record<string, string>;
python_version?: PythonVersion;
}, },
): Promise<Schedule> { ): Promise<Schedule> {
return apiRequest<Schedule>( return apiRequest<Schedule>(