fix(frontend): 稳定虚拟环境探测状态,避免输入时闪烁

探测状态保留上一次结果,新结果返回后再更新;空目录改为中性提示;防抖期间不因旧工作目录闪出警告;占位数据期间不自动回填虚拟环境。
This commit is contained in:
2026-11-04 23:02:30 +08:00
parent 10f8e6bb66
commit 78ddc17fce
+30 -18
View File
@@ -1,5 +1,10 @@
import { zodResolver } from '@hookform/resolvers/zod'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import {
keepPreviousData,
useMutation,
useQuery,
useQueryClient,
} from '@tanstack/react-query'
import {
Button,
Checkbox,
@@ -209,6 +214,7 @@ export function TaskEditorModal({
actionType === 'script' &&
isPythonScript &&
Boolean(debouncedWorkingDir.trim()),
placeholderData: keepPreviousData,
retry: false,
staleTime: 15_000,
})
@@ -230,7 +236,9 @@ export function TaskEditorModal({
onError: (error) => toast.error(error.message),
})
const linkedVenv =
isPythonScript && venvProbe.data?.status === 'linked'
isPythonScript &&
!venvProbe.isPlaceholderData &&
venvProbe.data?.status === 'linked'
? venvProbe.data
: null
const previewVirtualEnv = isPythonScript
@@ -270,7 +278,7 @@ export function TaskEditorModal({
// 探测到虚拟环境就自动填进「虚拟环境目录」,但用户自己改过就保留用户的值。
useEffect(() => {
if (!open || !isPythonScript) {
if (!open || !isPythonScript || venvProbe.isPlaceholderData) {
return
}
const probe = venvProbe.data
@@ -295,7 +303,7 @@ export function TaskEditorModal({
shouldDirty: true,
shouldValidate: true,
})
}, [debouncedVenv, debouncedWorkingDir, getValues, isPythonScript, open, setValue, venvProbe.data])
}, [debouncedVenv, debouncedWorkingDir, getValues, isPythonScript, open, setValue, venvProbe.data, venvProbe.isPlaceholderData])
// 打开后把焦点给第一个可编辑字段:新建时是任务标识,编辑时 ID 已锁定,跳名称。
// 原生 dialog 默认聚焦关闭按钮,不符合编辑表单的节奏。
@@ -595,7 +603,7 @@ export function TaskEditorModal({
</FormField>
<VenvDetectorBar
workingDir={debouncedWorkingDir}
workingDir={scriptPreview.working_dir}
probe={venvProbe.data}
pending={venvProbe.isPending}
failed={venvProbe.isError}
@@ -1013,25 +1021,29 @@ function VenvDetectorBar({
if (!workingDir.trim()) {
return (
<div className="env-detector-bar" role="status">
<span className="env-status-badge warn">
● 请输入有效的工作目录以探测环境
</span>
<span className="env-detector-hint">填写工作目录后自动检测环境</span>
</div>
)
}
if (pending) {
if (!probe) {
if (pending) {
return (
<div className="env-detector-bar" role="status">
<span className="env-status-badge pending">⏳ 正在检测环境...</span>
</div>
)
}
if (failed) {
return (
<div className="env-detector-bar" role="status">
<span className="env-status-badge warn">● 环境探测失败,可稍后重试</span>
</div>
)
}
return (
<div className="env-detector-bar" role="status">
<span className="env-status-badge pending">⏳ 正在探测解释器...</span>
</div>
)
}
if (failed || !probe) {
return (
<div className="env-detector-bar" role="status">
<span className="env-status-badge warn">● 环境探测失败,可稍后重试</span>
<span className="env-detector-hint">正在检测环境...</span>
</div>
)
}