feat: 浏览器类型字段改为下拉选择
- catalog.json: WebBrowser_Create/V2/V3/CreateBackground 的 type 字段补 options(内置运行浏览器/Chrome/Edge,label 与存储值分离)
- shared/types.ts: CatalogField.options 支持字符串或 {label,value} 对象
- Properties.tsx: select/radio 选项归一化渲染 label;当前值不在选项中时追加显示(兼容历史手填值如 zexplorer)
- typecheck 通过;全量 vitest 除 4 项依赖真实 COM 的历史失败外全部通过
This commit is contained in:
1 parent
3d64392eb0
commit
f28b5ffc5e
3 files changed
+87
-13
No files matched your search
+60
-4
@@ -100005,7 +100005,21 @@
|
|||||||
"placeholder": "",
|
"placeholder": "",
|
||||||
"description": "",
|
"description": "",
|
||||||
"advanced": false,
|
"advanced": false,
|
||||||
"valueTypes": []
|
"valueTypes": [],
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"label": "内置运行浏览器",
|
||||||
|
"value": "zexplorer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Chrome 浏览器",
|
||||||
|
"value": "chrome"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Edge 浏览器",
|
||||||
|
"value": "edge"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "url",
|
"key": "url",
|
||||||
@@ -101046,7 +101060,21 @@
|
|||||||
"placeholder": "",
|
"placeholder": "",
|
||||||
"description": "选择浏览器类型",
|
"description": "选择浏览器类型",
|
||||||
"advanced": false,
|
"advanced": false,
|
||||||
"valueTypes": []
|
"valueTypes": [],
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"label": "内置运行浏览器",
|
||||||
|
"value": "zexplorer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Chrome 浏览器",
|
||||||
|
"value": "chrome"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Edge 浏览器",
|
||||||
|
"value": "edge"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "url",
|
"key": "url",
|
||||||
@@ -103389,7 +103417,21 @@
|
|||||||
"placeholder": "",
|
"placeholder": "",
|
||||||
"description": "选择浏览器类型",
|
"description": "选择浏览器类型",
|
||||||
"advanced": false,
|
"advanced": false,
|
||||||
"valueTypes": []
|
"valueTypes": [],
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"label": "内置运行浏览器",
|
||||||
|
"value": "zexplorer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Chrome 浏览器",
|
||||||
|
"value": "chrome"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Edge 浏览器",
|
||||||
|
"value": "edge"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "url",
|
"key": "url",
|
||||||
@@ -106333,7 +106375,21 @@
|
|||||||
"placeholder": "",
|
"placeholder": "",
|
||||||
"description": "选择浏览器类型",
|
"description": "选择浏览器类型",
|
||||||
"advanced": false,
|
"advanced": false,
|
||||||
"valueTypes": []
|
"valueTypes": [],
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"label": "内置运行浏览器",
|
||||||
|
"value": "zexplorer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Chrome 浏览器",
|
||||||
|
"value": "chrome"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Edge 浏览器",
|
||||||
|
"value": "edge"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "url",
|
"key": "url",
|
||||||
|
|||||||
@@ -46,6 +46,23 @@ function numberOr(value: unknown, fallback: number): number {
|
|||||||
return Number.isFinite(parsed) ? parsed : fallback;
|
return Number.isFinite(parsed) ? parsed : fallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface SelectOption {
|
||||||
|
label: string;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 归一化下拉/单选选项:字符串 → {label,value};当前值不在选项中时追加进去(兼容历史手填值) */
|
||||||
|
function selectOptionsWith(field: CatalogField, rawValue: unknown): SelectOption[] {
|
||||||
|
const normalized = (field.options ?? []).map((option): SelectOption =>
|
||||||
|
typeof option === "string" ? { label: option, value: option } : { label: option.label, value: option.value }
|
||||||
|
);
|
||||||
|
const current = textOf(rawValue);
|
||||||
|
if (current && !normalized.some((option) => option.value === current)) {
|
||||||
|
normalized.unshift({ label: `${current}(当前值)`, value: current });
|
||||||
|
}
|
||||||
|
return normalized;
|
||||||
|
}
|
||||||
|
|
||||||
export function Properties({ catalog, onToast }: PropertiesProps) {
|
export function Properties({ catalog, onToast }: PropertiesProps) {
|
||||||
const [tab, setTab] = useState<Tab>("props");
|
const [tab, setTab] = useState<Tab>("props");
|
||||||
const flow = useEditorStore((state) => state.flow);
|
const flow = useEditorStore((state) => state.flow);
|
||||||
@@ -575,22 +592,22 @@ function FieldControl({
|
|||||||
) : field.widget === "select" && field.options?.length ? (
|
) : field.widget === "select" && field.options?.length ? (
|
||||||
<select className="select-input" value={textOf(raw)} onChange={(event) => onChange(field.key, event.target.value)}>
|
<select className="select-input" value={textOf(raw)} onChange={(event) => onChange(field.key, event.target.value)}>
|
||||||
<option value="">请选择</option>
|
<option value="">请选择</option>
|
||||||
{field.options.map((option) => (
|
{selectOptionsWith(field, raw).map((option) => (
|
||||||
<option key={option} value={option}>
|
<option key={option.value} value={option.value}>
|
||||||
{option}
|
{option.label}
|
||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
) : field.widget === "radio" && field.options?.length ? (
|
) : field.widget === "radio" && field.options?.length ? (
|
||||||
<div className="chip-row">
|
<div className="chip-row">
|
||||||
{field.options.map((option) => (
|
{selectOptionsWith(field, raw).map((option) => (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
key={option}
|
key={option.value}
|
||||||
className={`option-chip${textOf(raw) === option ? " active" : ""}`}
|
className={`option-chip${textOf(raw) === option.value ? " active" : ""}`}
|
||||||
onClick={() => onChange(field.key, option)}
|
onClick={() => onChange(field.key, option.value)}
|
||||||
>
|
>
|
||||||
{option}
|
{option.label}
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+2
-1
@@ -25,7 +25,8 @@ export interface CatalogField {
|
|||||||
description: string;
|
description: string;
|
||||||
advanced: boolean;
|
advanced: boolean;
|
||||||
valueTypes: string[];
|
valueTypes: string[];
|
||||||
options?: string[];
|
/** 下拉/单选选项:字符串(显示=存储值)或 { label, value }(显示与存储分离) */
|
||||||
|
options?: Array<string | { label: string; value: string }>;
|
||||||
unit?: string;
|
unit?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user