feat: manually mirror opencoze's code from bytedance
Change-Id: I09a73aadda978ad9511264a756b2ce51f5761adf
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { FieldItem, type FieldItemProps } from './item';
|
||||
@@ -0,0 +1,46 @@
|
||||
.field-item {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.item-title {
|
||||
position: relative;
|
||||
margin-bottom: 4px;
|
||||
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
overflow-wrap: break-word;
|
||||
|
||||
.item-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.item-tag {
|
||||
flex-shrink: 0;
|
||||
margin-left: 4px;
|
||||
}
|
||||
.tooltip-icon {
|
||||
margin-left: 4px;
|
||||
color: var(--coz-fg-dim);
|
||||
}
|
||||
}
|
||||
|
||||
.title-text {
|
||||
color: var(--coz-fg-primary);
|
||||
}
|
||||
|
||||
.title-required {
|
||||
color: var(--coz-fg-hglt-red);
|
||||
}
|
||||
.item-description {
|
||||
color: var(--coz-fg-secondary);
|
||||
}
|
||||
|
||||
.item-feedback {
|
||||
margin-top: 2px;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
color: var(--coz-fg-hglt-red);
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { IconCozInfoCircle } from '@coze-arch/coze-design/icons';
|
||||
import { Tag, Tooltip, Typography } from '@coze-arch/coze-design';
|
||||
|
||||
import css from './item.module.less';
|
||||
|
||||
export interface FieldItemProps {
|
||||
title?: React.ReactNode;
|
||||
description?: React.ReactNode;
|
||||
tag?: React.ReactNode;
|
||||
tooltip?: React.ReactNode;
|
||||
feedback?: string;
|
||||
required?: boolean;
|
||||
['data-testid']?: string;
|
||||
}
|
||||
|
||||
export const FieldItem: React.FC<React.PropsWithChildren<FieldItemProps>> = ({
|
||||
title,
|
||||
required,
|
||||
tooltip,
|
||||
tag,
|
||||
description,
|
||||
children,
|
||||
feedback,
|
||||
...props
|
||||
}) => (
|
||||
<div className={css['field-item']} data-testid={props['data-testid']}>
|
||||
{/* title */}
|
||||
<div className={css['item-title']}>
|
||||
<div className={css['item-label']}>
|
||||
<Typography.Text className={css['title-text']} strong size="small">
|
||||
{title}
|
||||
</Typography.Text>
|
||||
{required ? (
|
||||
<Typography.Text className={css['title-required']}>*</Typography.Text>
|
||||
) : null}
|
||||
{tooltip ? (
|
||||
<Tooltip content={tooltip}>
|
||||
<IconCozInfoCircle className={css['tooltip-icon']} />
|
||||
</Tooltip>
|
||||
) : null}
|
||||
|
||||
{tag ? (
|
||||
<Tag className={css['item-tag']} size="mini" color="primary">
|
||||
{tag}
|
||||
</Tag>
|
||||
) : null}
|
||||
</div>
|
||||
{description ? (
|
||||
<Typography.Text
|
||||
ellipsis={{
|
||||
showTooltip: {
|
||||
opts: {
|
||||
position: 'left',
|
||||
style: {
|
||||
maxWidth: 500,
|
||||
},
|
||||
},
|
||||
},
|
||||
}}
|
||||
className={css['item-description']}
|
||||
size="small"
|
||||
>
|
||||
{description}
|
||||
</Typography.Text>
|
||||
) : null}
|
||||
</div>
|
||||
{/* children */}
|
||||
<div>{children}</div>
|
||||
{/* feedback */}
|
||||
{feedback ? <div className={css['item-feedback']}>{feedback}</div> : null}
|
||||
</div>
|
||||
);
|
||||
@@ -0,0 +1,53 @@
|
||||
.collapse-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
height: 40px;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
background: var(--coz-bg-plus);
|
||||
border-bottom: 1px solid var(--coz-bg-plus);
|
||||
z-index: 1;
|
||||
cursor: pointer;
|
||||
&:hover .collapse-icon{
|
||||
opacity: 1;
|
||||
}
|
||||
&.is-sticky {
|
||||
border-color: var(--coz-stroke-primary);
|
||||
}
|
||||
}
|
||||
.collapse-label {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
height: 20px;
|
||||
color: var(--coz-fg-primary);
|
||||
}
|
||||
.collapse-label-tooltip {
|
||||
font-size: 14px;
|
||||
margin-left: 4px;
|
||||
color: var(--coz-fg-dim);
|
||||
}
|
||||
.collapse-icon {
|
||||
transition: transform 0.3s ease-in-out, opacity 0.2s ease-in-out;
|
||||
opacity: 0;
|
||||
color: var(--coz-fg-dim);
|
||||
font-size: 14px;
|
||||
margin: 0 1px;
|
||||
&.is-show {
|
||||
opacity: 1;
|
||||
}
|
||||
&.is-close {
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
}
|
||||
|
||||
.collapse-content {
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
.collapse-extra {
|
||||
width: 0;
|
||||
flex-grow: 1;
|
||||
padding-right: 16px;
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React, { useState, useRef } from 'react';
|
||||
|
||||
import { clsx } from 'clsx';
|
||||
import { useInViewport } from 'ahooks';
|
||||
import {
|
||||
IconCozArrowDownFill,
|
||||
IconCozInfoCircle,
|
||||
} from '@coze-arch/coze-design/icons';
|
||||
import { Collapsible, Tooltip } from '@coze-arch/coze-design';
|
||||
|
||||
import css from './collapse.module.less';
|
||||
|
||||
interface CollapseProps {
|
||||
label: React.ReactNode;
|
||||
tooltip?: React.ReactNode;
|
||||
extra?: React.ReactNode;
|
||||
fade?: boolean;
|
||||
duration?: number;
|
||||
}
|
||||
|
||||
export const GroupCollapse: React.FC<
|
||||
React.PropsWithChildren<CollapseProps>
|
||||
> = ({ label, tooltip, extra, children }) => {
|
||||
const [isOpen, setIsOpen] = useState(true);
|
||||
const ref = useRef(null);
|
||||
/**
|
||||
* 探测标题是否处于 sticky 状态
|
||||
*/
|
||||
const [inViewport] = useInViewport(ref);
|
||||
return (
|
||||
<div>
|
||||
{/* 探测元素 */}
|
||||
<div ref={ref} />
|
||||
{/* header */}
|
||||
<div
|
||||
onClick={() => setIsOpen(!isOpen)}
|
||||
className={clsx(
|
||||
css['collapse-title'],
|
||||
(!inViewport || !isOpen) && css['is-sticky'],
|
||||
)}
|
||||
>
|
||||
<IconCozArrowDownFill
|
||||
className={clsx(css['collapse-icon'], !isOpen && css['is-close'])}
|
||||
/>
|
||||
<span className={css['collapse-label']}>{label}</span>
|
||||
{tooltip ? (
|
||||
<Tooltip content={tooltip}>
|
||||
<IconCozInfoCircle className={css['collapse-label-tooltip']} />
|
||||
</Tooltip>
|
||||
) : null}
|
||||
{extra ? (
|
||||
<div
|
||||
className={css['collapse-extra']}
|
||||
onClick={e => e.stopPropagation()}
|
||||
>
|
||||
{extra}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
{/* children */}
|
||||
<Collapsible isOpen={isOpen} keepDOM fade duration={300}>
|
||||
<div className={css['collapse-content']}>{children}</div>
|
||||
</Collapsible>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { GroupCollapse } from './collapse';
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 基础表单物料
|
||||
*/
|
||||
export { InputNumber, InputNumberProps } from './input-number';
|
||||
export { InputString, type InputStringProps } from './input-string';
|
||||
export { InputTime, type InputTimeProps } from './input-time';
|
||||
export { InputJson, type InputJsonProps } from './input-json';
|
||||
export { SelectBoolean } from './select-boolean';
|
||||
export { SelectVoice } from './select-voice';
|
||||
export { FieldItem, type FieldItemProps } from './field-item';
|
||||
export { GroupCollapse } from './group-collapse';
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { InputJson, type InputJsonProps } from './json';
|
||||
@@ -0,0 +1,33 @@
|
||||
.input-json-wrap {
|
||||
border: 1px solid var(--coz-stroke-plus);
|
||||
border-radius: 8px;
|
||||
&.disabled {
|
||||
background-color: rgba(var(--coze-bg-5), var(--coze-bg-5-alpha));
|
||||
cursor: not-allowed;
|
||||
}
|
||||
&.error {
|
||||
border: 1px solid var(--coz-stroke-hglt-red);
|
||||
}
|
||||
}
|
||||
|
||||
.json-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
height: 28px;
|
||||
padding: 0 4px;
|
||||
|
||||
border-bottom: 1px solid var(--coz-stroke-plus);
|
||||
border-top-left-radius: 8px;
|
||||
border-top-right-radius: 8px;
|
||||
.json-label {
|
||||
font-size: 12px;
|
||||
color: var(--coz-fg-secondary);
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
.json-editor {
|
||||
overflow: hidden;
|
||||
border-bottom-left-radius: 8px;
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { clsx } from 'clsx';
|
||||
import {
|
||||
JsonEditor,
|
||||
safeFormatJsonString,
|
||||
} from '@coze-workflow/test-run-shared';
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
import { IconCozBroom } from '@coze-arch/coze-design/icons';
|
||||
import { Tooltip, IconButton } from '@coze-arch/coze-design';
|
||||
|
||||
import css from './json.module.less';
|
||||
|
||||
export interface InputJsonProps {
|
||||
value?: string;
|
||||
disabled?: boolean;
|
||||
extensions?: any;
|
||||
jsonSchema?: any;
|
||||
height?: string;
|
||||
validateStatus?: 'error';
|
||||
['data-testid']?: string;
|
||||
onChange?: (v?: string) => void;
|
||||
didMount?: (editor: any) => void;
|
||||
}
|
||||
|
||||
export const InputJson: React.FC<InputJsonProps> = ({
|
||||
value,
|
||||
disabled,
|
||||
validateStatus,
|
||||
onChange,
|
||||
...props
|
||||
}) => {
|
||||
const handleFormat = () => {
|
||||
const next = safeFormatJsonString(value);
|
||||
if (next !== value) {
|
||||
onChange?.(next);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
css['input-json-wrap'],
|
||||
disabled && css.disabled,
|
||||
validateStatus === 'error' && css.error,
|
||||
)}
|
||||
data-testid={props['data-testid']}
|
||||
>
|
||||
<div className={css['json-header']}>
|
||||
<div className={css['json-label']}>JSON</div>
|
||||
<div>
|
||||
<Tooltip content={I18n.t('workflow_exception_ignore_format')}>
|
||||
<IconButton
|
||||
icon={<IconCozBroom />}
|
||||
disabled={disabled}
|
||||
size="small"
|
||||
color="secondary"
|
||||
onMouseDown={e => e.preventDefault()}
|
||||
onClick={handleFormat}
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div className={css['json-editor']}>
|
||||
<JsonEditor
|
||||
value={value}
|
||||
disabled={disabled}
|
||||
onChange={onChange}
|
||||
{...props}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { InputNumber, type InputNumberProps } from './input-number';
|
||||
@@ -0,0 +1,27 @@
|
||||
.buttons {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 20px;
|
||||
position: relative;
|
||||
right: -7px;
|
||||
}
|
||||
|
||||
.button {
|
||||
font-size: 10px;
|
||||
color: var(--coz-fg-primary);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background-color: rgba(var(--coze-bg-5), var(--coze-bg-5-alpha));
|
||||
}
|
||||
&.up {
|
||||
border-top-left-radius: var(--coze-5);
|
||||
border-top-right-radius: var(--coze-5);
|
||||
}
|
||||
&.down {
|
||||
border-bottom-left-radius: var(--coze-5);
|
||||
border-bottom-right-radius: var(--coze-5);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { useRef, useEffect } from 'react';
|
||||
|
||||
import clsx from 'clsx';
|
||||
import BigNumber, { type BigNumber as IBigNumber } from 'bignumber.js';
|
||||
import {
|
||||
IconCozArrowDownFill,
|
||||
IconCozArrowUpFill,
|
||||
} from '@coze-arch/coze-design/icons';
|
||||
import { Input, type InputProps } from '@coze-arch/coze-design';
|
||||
|
||||
import css from './input-number.module.less';
|
||||
|
||||
export interface InputNumberProps {
|
||||
value?: string;
|
||||
style?: React.CSSProperties;
|
||||
placeholder?: string;
|
||||
validateStatus?: InputProps['validateStatus'];
|
||||
disabled?: boolean;
|
||||
onChange: (v?: string) => void;
|
||||
onBlur: () => void;
|
||||
onFocus: () => void;
|
||||
/** 整型 */
|
||||
int?: boolean;
|
||||
}
|
||||
|
||||
/** 是否是合法的数字字符串 */
|
||||
function isValidNumber(str: string) {
|
||||
try {
|
||||
const value = new BigNumber(str);
|
||||
return !value.isNaN();
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeNumber(str?: string) {
|
||||
if (!str || !isValidNumber(str)) {
|
||||
return;
|
||||
}
|
||||
return new BigNumber(str);
|
||||
}
|
||||
|
||||
export const InputNumber: React.FC<InputNumberProps> = ({
|
||||
int,
|
||||
onChange,
|
||||
onBlur,
|
||||
...props
|
||||
}) => {
|
||||
const verifiedRef = useRef<undefined | IBigNumber>(
|
||||
normalizeNumber(props.value),
|
||||
);
|
||||
|
||||
const fixed = (num: IBigNumber, innerInt?: boolean) =>
|
||||
innerInt ? num.toFixed(0, BigNumber.ROUND_DOWN) : num.toFixed();
|
||||
|
||||
const handleBlur = () => {
|
||||
if (props.value === '' || props.value === undefined) {
|
||||
/** 失焦时若值为空,则同时清空验证值 */
|
||||
verifiedRef.current = undefined;
|
||||
if (props.value === '') {
|
||||
onChange(undefined);
|
||||
}
|
||||
} else {
|
||||
/** 失焦时若值不为空,则需要验证值的合法性 */
|
||||
/**
|
||||
* 1. 若值本身合法,则对值做格式化
|
||||
* 2. 若值不合法,则采纳最近一次的合法值
|
||||
* 3. 若都没有,则返回 undefined
|
||||
*/
|
||||
let next: undefined | string;
|
||||
const nextBig = normalizeNumber(props.value) || verifiedRef.current;
|
||||
if (nextBig) {
|
||||
next = fixed(nextBig, int);
|
||||
}
|
||||
if (next !== props.value) {
|
||||
onChange(next);
|
||||
}
|
||||
}
|
||||
onBlur();
|
||||
};
|
||||
|
||||
const handlePlus = () => {
|
||||
let next = '1';
|
||||
if (verifiedRef.current) {
|
||||
const nextNum = verifiedRef.current.plus('1');
|
||||
next = fixed(nextNum, int);
|
||||
}
|
||||
onChange(next);
|
||||
};
|
||||
|
||||
const handleMinus = () => {
|
||||
let next = '0';
|
||||
if (verifiedRef.current) {
|
||||
const nextNum = verifiedRef.current.minus('1');
|
||||
next = fixed(nextNum, int);
|
||||
}
|
||||
onChange(next);
|
||||
};
|
||||
|
||||
/** 当值发生变化,需要把值同步到合法数字 */
|
||||
useEffect(() => {
|
||||
if (props.value === '' || props.value === undefined) {
|
||||
verifiedRef.current = undefined;
|
||||
}
|
||||
const next = normalizeNumber(props.value);
|
||||
if (next) {
|
||||
verifiedRef.current = normalizeNumber(props.value);
|
||||
}
|
||||
}, [props.value]);
|
||||
|
||||
return (
|
||||
<Input
|
||||
onChange={onChange}
|
||||
onBlur={handleBlur}
|
||||
size="small"
|
||||
suffix={
|
||||
props.disabled ? null : (
|
||||
<div className={css.buttons}>
|
||||
<div className={clsx(css.button, css.up)} onClick={handlePlus}>
|
||||
<IconCozArrowUpFill />
|
||||
</div>
|
||||
<div className={clsx(css.button, css.down)} onClick={handleMinus}>
|
||||
<IconCozArrowDownFill />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { InputString, type InputStringProps } from './input';
|
||||
@@ -0,0 +1,14 @@
|
||||
// semi 和 coze 都不支持小尺寸的 textarea 需要业务实现
|
||||
.input-string.small {
|
||||
font-size: 12px;
|
||||
line-height: 20px;
|
||||
padding: 1px 3px;
|
||||
border-radius: 6px;
|
||||
:global textarea {
|
||||
font-size: 12px;
|
||||
line-height: 20px;
|
||||
}
|
||||
:global .semi-input-clearbtn {
|
||||
height: 22px;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import clsx from 'clsx';
|
||||
import { TextArea } from '@coze-arch/coze-design';
|
||||
|
||||
import css from './input.module.less';
|
||||
|
||||
export interface InputStringProps {
|
||||
value?: string;
|
||||
}
|
||||
|
||||
export const InputString: React.FC<InputStringProps> = props => (
|
||||
<TextArea
|
||||
className={clsx(css['input-string'], css.small)}
|
||||
autosize={{ minRows: 1, maxRows: 5 }}
|
||||
rows={1}
|
||||
showClear
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { InputTime, type InputTimeProps } from './time';
|
||||
@@ -0,0 +1,6 @@
|
||||
.input-time {
|
||||
width: 100%;
|
||||
:global .semi-select {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { clsx } from 'clsx';
|
||||
import { DatePicker } from '@coze-arch/coze-design';
|
||||
|
||||
import css from './time.module.less';
|
||||
|
||||
export interface InputTimeProps {
|
||||
className?: string;
|
||||
value?: string;
|
||||
onChange?: (v?: string) => void;
|
||||
}
|
||||
|
||||
export const InputTime: React.FC<InputTimeProps> = ({
|
||||
className,
|
||||
value,
|
||||
onChange,
|
||||
...props
|
||||
}) => (
|
||||
<DatePicker
|
||||
className={clsx(css['input-time'], className)}
|
||||
type="dateTime"
|
||||
size="small"
|
||||
showClear={false}
|
||||
showSuffix={false}
|
||||
value={value}
|
||||
onChange={(_date, dateString) => {
|
||||
if (typeof dateString === 'string' || dateString === undefined) {
|
||||
onChange?.(dateString);
|
||||
}
|
||||
}}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { SelectBoolean } from './select';
|
||||
@@ -0,0 +1,3 @@
|
||||
.select-boolean {
|
||||
width: 100%;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
|
||||
import { clsx } from 'clsx';
|
||||
import { Select, type SelectProps } from '@coze-arch/coze-design';
|
||||
|
||||
import css from './select.module.less';
|
||||
|
||||
interface SelectBooleanProps {
|
||||
className?: string;
|
||||
value?: boolean;
|
||||
onChange?: (v?: boolean) => void;
|
||||
}
|
||||
|
||||
export const SelectBoolean: React.FC<SelectBooleanProps> = ({
|
||||
className,
|
||||
value,
|
||||
onChange,
|
||||
...props
|
||||
}) => {
|
||||
const formattedValue = useMemo(
|
||||
() => (value === undefined ? undefined : Number(value)),
|
||||
[value],
|
||||
);
|
||||
|
||||
const handleChange = useCallback(
|
||||
(v?: SelectProps['value']) => {
|
||||
const next = v === undefined ? v : Boolean(v);
|
||||
onChange?.(next);
|
||||
},
|
||||
[onChange],
|
||||
);
|
||||
|
||||
return (
|
||||
<Select
|
||||
className={clsx(css['select-boolean'], className)}
|
||||
size="small"
|
||||
value={formattedValue}
|
||||
onChange={handleChange}
|
||||
{...props}
|
||||
>
|
||||
<Select.Option value={1}>True</Select.Option>
|
||||
<Select.Option value={0}>False</Select.Option>
|
||||
</Select>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { VoiceSelect } from '@coze-workflow/components';
|
||||
|
||||
interface SelectVoiceProps {
|
||||
value?: string;
|
||||
onChange?: (v?: string) => void;
|
||||
onBlur?: () => void;
|
||||
}
|
||||
|
||||
export const SelectVoice: React.FC<SelectVoiceProps> = ({
|
||||
onChange,
|
||||
onBlur,
|
||||
...props
|
||||
}) => {
|
||||
const handleChange = (v?: string) => {
|
||||
onChange?.(v);
|
||||
onBlur?.();
|
||||
};
|
||||
|
||||
return <VoiceSelect onChange={handleChange} {...props} />;
|
||||
};
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
|
||||
import {
|
||||
FieldItem as BaseFieldItem,
|
||||
type FieldItemProps,
|
||||
} from '../../base-form-materials';
|
||||
import { useFieldSchema } from '../../../form-engine';
|
||||
import { TestFormFieldName } from '../../../constants';
|
||||
|
||||
export const FieldItem: React.FC<React.PropsWithChildren<FieldItemProps>> = ({
|
||||
tag,
|
||||
...props
|
||||
}) => {
|
||||
const schema = useFieldSchema();
|
||||
|
||||
const isBatchField = schema.path.includes(TestFormFieldName.Batch);
|
||||
/** 批处理变量 tag 增加额外描述 */
|
||||
const currentTag =
|
||||
tag && isBatchField
|
||||
? `${tag} - ${I18n.t('workflow_detail_node_batch')}`
|
||||
: tag;
|
||||
|
||||
return (
|
||||
<BaseFieldItem
|
||||
title={schema.title}
|
||||
description={schema.description}
|
||||
required={schema.required}
|
||||
tag={currentTag}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 表单物料
|
||||
*/
|
||||
export { InputString } from './input-string';
|
||||
export { FieldItem } from './field-item';
|
||||
export { InputNumber } from './input-number';
|
||||
export { InputInteger } from './input-integer';
|
||||
export { InputTime } from './input-time';
|
||||
export { InputJson } from './input-json';
|
||||
export { SelectBoolean } from './select-boolean';
|
||||
export { SelectVoice } from './select-voice';
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { InputNumber as BaseInputNumber } from '../../base-form-materials';
|
||||
|
||||
export const InputInteger = props => <BaseInputNumber int {...props} />;
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { InputJson } from '../../base-form-materials';
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { InputNumber as BaseInputNumber } from '../../base-form-materials';
|
||||
|
||||
export const InputNumber = props => <BaseInputNumber {...props} />;
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { InputString as BaseInputString } from '../../base-form-materials';
|
||||
|
||||
export const InputString = BaseInputString;
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { InputTime } from '../../base-form-materials';
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { SelectBoolean } from '../../base-form-materials';
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { SelectVoice } from '../../base-form-materials';
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { TestRunForm } from './test-run-form';
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Form, type FormModel } from '@flowgram-adapter/free-layout-editor';
|
||||
|
||||
import {
|
||||
InputString,
|
||||
InputNumber,
|
||||
InputInteger,
|
||||
InputJson,
|
||||
SelectBoolean,
|
||||
SelectVoice,
|
||||
InputTime,
|
||||
FieldItem,
|
||||
} from '../form-materials';
|
||||
import {
|
||||
createSchemaField,
|
||||
type FormSchema,
|
||||
useCreateForm,
|
||||
type IFormSchema,
|
||||
type FormSchemaReactComponents,
|
||||
} from '../../form-engine';
|
||||
|
||||
const SchemaField = createSchemaField({
|
||||
components: {
|
||||
InputString,
|
||||
InputNumber,
|
||||
InputInteger,
|
||||
InputTime,
|
||||
InputJson,
|
||||
SelectBoolean,
|
||||
SelectVoice,
|
||||
FieldItem,
|
||||
},
|
||||
});
|
||||
|
||||
interface TestRunFormProps {
|
||||
schema: IFormSchema;
|
||||
components?: FormSchemaReactComponents;
|
||||
onFormValuesChange?: (payload: any) => void;
|
||||
onMounted?: (formModel: FormModel, schema: FormSchema) => void;
|
||||
}
|
||||
|
||||
export const TestRunForm: React.FC<TestRunFormProps> = ({
|
||||
schema,
|
||||
components,
|
||||
onFormValuesChange,
|
||||
onMounted,
|
||||
}) => {
|
||||
const { control, formSchema } = useCreateForm(schema, {
|
||||
onFormValuesChange,
|
||||
onMounted,
|
||||
});
|
||||
return (
|
||||
<Form control={control}>
|
||||
<SchemaField schema={formSchema} components={components} />
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 固定的内部 field name
|
||||
*/
|
||||
export enum TestFormFieldName {
|
||||
Node = '_node',
|
||||
Batch = '_batch',
|
||||
Input = '_input',
|
||||
Setting = '_setting',
|
||||
JSON = '_json',
|
||||
/** 关联内容 */
|
||||
Related = '_related',
|
||||
Bot = '_bot',
|
||||
Conversation = '_conversation',
|
||||
TestsetSelect = '_testset_select',
|
||||
TestsetSave = '_testset_save',
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { createContext, useContext, useRef } from 'react';
|
||||
|
||||
import {
|
||||
createWithEqualityFn,
|
||||
type UseBoundStoreWithEqualityFn,
|
||||
} from 'zustand/traditional';
|
||||
import { shallow } from 'zustand/shallow';
|
||||
import { type StoreApi } from 'zustand';
|
||||
|
||||
import { type IFormSchema } from '../form-engine';
|
||||
|
||||
/**
|
||||
* 单一表单内的全局性质状态集中管理
|
||||
*/
|
||||
export interface TestRunFormState {
|
||||
schema: IFormSchema | null;
|
||||
mode: 'form' | 'json';
|
||||
patch: (next: Partial<TestRunFormState>) => void;
|
||||
getSchema: () => TestRunFormState['schema'];
|
||||
}
|
||||
|
||||
const createStore = () =>
|
||||
createWithEqualityFn<TestRunFormState>(
|
||||
(set, get) => ({
|
||||
schema: null,
|
||||
mode: 'form',
|
||||
patch: next => set(() => next),
|
||||
getSchema: () => get().schema,
|
||||
}),
|
||||
shallow,
|
||||
);
|
||||
|
||||
type FormStore = UseBoundStoreWithEqualityFn<StoreApi<TestRunFormState>>;
|
||||
|
||||
const FormContext = createContext<FormStore>({} as unknown as FormStore);
|
||||
|
||||
export const TestRunFormProvider: React.FC<React.PropsWithChildren> = ({
|
||||
children,
|
||||
}) => {
|
||||
const ref = useRef(createStore());
|
||||
return (
|
||||
<FormContext.Provider value={ref.current}>{children}</FormContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useTestRunFormStore = <T,>(
|
||||
selector: (s: TestRunFormState) => T,
|
||||
) => {
|
||||
const store = useContext(FormContext);
|
||||
|
||||
return store(selector);
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export {
|
||||
TestRunFormProvider,
|
||||
useTestRunFormStore,
|
||||
type TestRunFormState,
|
||||
} from './form';
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { type FormSchemaReactComponents } from '../types';
|
||||
import { SchemaField, type SchemaFieldProps } from './schema-field';
|
||||
|
||||
interface CreateSchemaFieldOptions {
|
||||
components: FormSchemaReactComponents;
|
||||
}
|
||||
|
||||
type InnerSchemaField = React.FC<
|
||||
Omit<SchemaFieldProps, 'components'> &
|
||||
Pick<Partial<SchemaFieldProps>, 'components'>
|
||||
>;
|
||||
|
||||
export const createSchemaField = (options: CreateSchemaFieldOptions) => {
|
||||
const InnerSchemaField: InnerSchemaField = ({ components, ...props }) => (
|
||||
<SchemaField
|
||||
components={{
|
||||
...options.components,
|
||||
...components,
|
||||
}}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
||||
return InnerSchemaField;
|
||||
};
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { Field } from '@flowgram-adapter/free-layout-editor';
|
||||
|
||||
import { SchemaContext, type FormSchema } from '../shared';
|
||||
import { useFieldUIState } from '../hooks';
|
||||
import { ReactiveField } from './reactive-field';
|
||||
|
||||
interface FieldProps {
|
||||
name: string;
|
||||
schema: FormSchema;
|
||||
}
|
||||
|
||||
export const GeneralField: React.FC<React.PropsWithChildren<FieldProps>> = ({
|
||||
schema,
|
||||
}) => {
|
||||
const parentUIState = useFieldUIState();
|
||||
return (
|
||||
<SchemaContext.Provider value={schema}>
|
||||
<Field name={schema.path.join('.')} defaultValue={schema.defaultValue}>
|
||||
<ReactiveField parentUIState={parentUIState} />
|
||||
</Field>
|
||||
</SchemaContext.Provider>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { createSchemaField } from './create-schema-field';
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { SchemaContext, type FormSchema } from '../shared';
|
||||
import { useComponents } from '../hooks';
|
||||
|
||||
interface ObjectFieldProps {
|
||||
schema: FormSchema;
|
||||
}
|
||||
|
||||
export const ObjectField: React.FC<
|
||||
React.PropsWithChildren<ObjectFieldProps>
|
||||
> = ({ schema, children }) => {
|
||||
const components = useComponents();
|
||||
const renderDecorator = () => {
|
||||
if (!schema.decoratorType || !components[schema.decoratorType]) {
|
||||
return <>{children}</>;
|
||||
}
|
||||
return React.createElement(
|
||||
components[schema.decoratorType],
|
||||
schema.decoratorProps,
|
||||
children,
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<SchemaContext.Provider value={schema}>
|
||||
{renderDecorator()}
|
||||
</SchemaContext.Provider>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { useCurrentField, useCurrentFieldState } from '@flowgram-adapter/free-layout-editor';
|
||||
|
||||
import { type FormSchemaUIState } from '../types';
|
||||
import {
|
||||
useFieldUIState,
|
||||
useFieldSchema,
|
||||
useComponents,
|
||||
useFormUIState,
|
||||
} from '../hooks';
|
||||
|
||||
interface ReactiveFieldProps {
|
||||
parentUIState?: FormSchemaUIState;
|
||||
}
|
||||
|
||||
/**
|
||||
* 接入响应式的 Field
|
||||
*/
|
||||
const ReactiveField: React.FC<ReactiveFieldProps> = ({ parentUIState }) => {
|
||||
const components = useComponents();
|
||||
const schema = useFieldSchema();
|
||||
const field = useCurrentField();
|
||||
const uiState = useFieldUIState();
|
||||
const formUIState = useFormUIState();
|
||||
const fieldState = useCurrentFieldState();
|
||||
/**
|
||||
* 自生的 disabled 态由父亲和自身一起控制
|
||||
*/
|
||||
const disabled =
|
||||
parentUIState?.disabled || uiState.disabled || formUIState.disabled;
|
||||
const validateStatus = fieldState.errors?.length ? 'error' : undefined;
|
||||
|
||||
const renderComponent = () => {
|
||||
if (!schema.componentType || !components[schema.componentType]) {
|
||||
return null;
|
||||
}
|
||||
return React.createElement(components[schema.componentType], {
|
||||
disabled,
|
||||
validateStatus,
|
||||
value: field.value,
|
||||
onChange: field.onChange,
|
||||
onFocus: field.onFocus,
|
||||
onBlur: field.onBlur,
|
||||
['data-testid']: ['workflow', 'testrun', 'form', 'component']
|
||||
.concat(schema.path)
|
||||
.join('.'),
|
||||
...schema.componentProps,
|
||||
});
|
||||
};
|
||||
|
||||
const renderDecorator = (children: React.ReactNode) => {
|
||||
if (!schema.decoratorType || !components[schema.decoratorType]) {
|
||||
return <>{children}</>;
|
||||
}
|
||||
return React.createElement(
|
||||
components[schema.decoratorType],
|
||||
{
|
||||
...schema.decoratorProps,
|
||||
['data-testid']: ['workflow', 'testrun', 'form', 'decorator']
|
||||
.concat(schema.path)
|
||||
.join('.'),
|
||||
},
|
||||
children,
|
||||
);
|
||||
};
|
||||
|
||||
return renderDecorator(renderComponent());
|
||||
};
|
||||
|
||||
export { ReactiveField, ReactiveFieldProps };
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { FormSchema } from '../shared';
|
||||
import { ObjectField } from './object-field';
|
||||
import { GeneralField } from './general-field';
|
||||
|
||||
interface RecursionFieldProps {
|
||||
schema: FormSchema;
|
||||
name?: string;
|
||||
}
|
||||
|
||||
const computePath = (path?: string[], name?: string) =>
|
||||
[...(path || []), name].filter((i): i is string => Boolean(i));
|
||||
|
||||
/**
|
||||
* 递归 Field
|
||||
*/
|
||||
const RecursionField: React.FC<RecursionFieldProps> = ({ name, schema }) => {
|
||||
const renderProperties = () => {
|
||||
const properties = FormSchema.getProperties(schema);
|
||||
if (!properties.length) {
|
||||
return null;
|
||||
}
|
||||
const { path } = schema;
|
||||
return (
|
||||
<ObjectField schema={schema}>
|
||||
{properties.map((item, index) => (
|
||||
<RecursionField
|
||||
name={item.key}
|
||||
schema={new FormSchema(item.schema, computePath(path, item.key))}
|
||||
key={`${index}-${item.key}`}
|
||||
/>
|
||||
))}
|
||||
</ObjectField>
|
||||
);
|
||||
};
|
||||
|
||||
if (!name) {
|
||||
return renderProperties();
|
||||
}
|
||||
if (schema.type === 'object') {
|
||||
return renderProperties();
|
||||
}
|
||||
|
||||
return <GeneralField name={name} schema={schema} />;
|
||||
};
|
||||
|
||||
export { RecursionField, type RecursionFieldProps };
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import type { FormSchemaReactComponents } from '../types';
|
||||
import {
|
||||
ComponentsContext,
|
||||
FormSchemaContext,
|
||||
type FormSchema,
|
||||
} from '../shared';
|
||||
import { RecursionField } from './recursion-field';
|
||||
|
||||
export interface SchemaFieldProps {
|
||||
schema: FormSchema;
|
||||
components: FormSchemaReactComponents;
|
||||
}
|
||||
|
||||
export const SchemaField: React.FC<SchemaFieldProps> = props => (
|
||||
<ComponentsContext.Provider value={props.components}>
|
||||
<FormSchemaContext.Provider value={props.schema}>
|
||||
<RecursionField schema={props.schema} />
|
||||
</FormSchemaContext.Provider>
|
||||
</ComponentsContext.Provider>
|
||||
);
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { useCreateForm } from './use-create-form';
|
||||
export { useFieldSchema } from './use-field-schema';
|
||||
export { useFieldUIState } from './use-field-ui-state';
|
||||
export { useComponents } from './use-components';
|
||||
export { useFormSchema } from './use-form-schema';
|
||||
export { useFormUIState } from './use-form-ui-state';
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { useContext } from 'react';
|
||||
|
||||
import { ComponentsContext } from '../shared';
|
||||
|
||||
export const useComponents = () => useContext(ComponentsContext);
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { useEffect, useMemo } from 'react';
|
||||
|
||||
import { createForm, ValidateTrigger } from '@flowgram-adapter/free-layout-editor';
|
||||
|
||||
import type { IFormSchema, IFormSchemaValidate } from '../types';
|
||||
import { FormSchema } from '../shared';
|
||||
|
||||
type Rules = Record<string, IFormSchemaValidate>;
|
||||
|
||||
const getFieldPath = (...args: (string | undefined)[]) =>
|
||||
args.filter(path => path).join('.');
|
||||
|
||||
export function validateResolver(schema: IFormSchema): Rules {
|
||||
const rules = {};
|
||||
|
||||
visit(schema);
|
||||
|
||||
return rules;
|
||||
|
||||
function visit(current: IFormSchema, name?: string) {
|
||||
if (name && current['x-validator']) {
|
||||
rules[name] = current['x-validator'];
|
||||
}
|
||||
if (current.type === 'object' && current.properties) {
|
||||
Object.entries(current.properties).forEach(([key, value]) => {
|
||||
visit(value, getFieldPath(name, key));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const useCreateForm = (schema: IFormSchema, options: any = {}) => {
|
||||
const { validate } = options;
|
||||
const innerValidate = useMemo(
|
||||
() => ({
|
||||
...validateResolver(schema),
|
||||
...validate,
|
||||
}),
|
||||
[schema],
|
||||
);
|
||||
const { form, control } = useMemo(
|
||||
() =>
|
||||
createForm({
|
||||
validate: innerValidate,
|
||||
validateTrigger: ValidateTrigger.onBlur,
|
||||
...options,
|
||||
}),
|
||||
[schema, innerValidate],
|
||||
);
|
||||
const formSchema = useMemo(
|
||||
() => new FormSchema({ type: 'object', ...schema }),
|
||||
[schema],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (options.onMounted) {
|
||||
options.onMounted(control._formModel, formSchema);
|
||||
}
|
||||
const disposable = control._formModel.onFormValuesUpdated(payload => {
|
||||
if (options?.onFormValuesChange) {
|
||||
options.onFormValuesChange(payload);
|
||||
}
|
||||
});
|
||||
return () => disposable.dispose();
|
||||
}, [control]);
|
||||
|
||||
return {
|
||||
form,
|
||||
control,
|
||||
model: control._formModel,
|
||||
formSchema,
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { useContext } from 'react';
|
||||
|
||||
import { SchemaContext } from '../shared';
|
||||
|
||||
export const useFieldSchema = () => useContext(SchemaContext);
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { useObserve } from '@flowgram-adapter/common';
|
||||
|
||||
import { useFieldSchema } from './use-field-schema';
|
||||
|
||||
export const useFieldUIState = () => {
|
||||
const schema = useFieldSchema();
|
||||
return useObserve(schema?.uiState?.value);
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { useContext } from 'react';
|
||||
|
||||
import { FormSchemaContext } from '../shared';
|
||||
|
||||
export const useFormSchema = () => useContext(FormSchemaContext);
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { useObserve } from '@flowgram-adapter/common';
|
||||
|
||||
import { useFormSchema } from './use-form-schema';
|
||||
|
||||
export const useFormUIState = () => {
|
||||
const schema = useFormSchema();
|
||||
return useObserve(schema?.uiState?.value);
|
||||
};
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 表单引擎
|
||||
*/
|
||||
export { createSchemaField } from './fields';
|
||||
export { FormSchema } from './shared';
|
||||
export { useCreateForm, useFieldSchema, useFormSchema } from './hooks';
|
||||
export type {
|
||||
IFormSchema,
|
||||
IFormSchemaValidate,
|
||||
FormSchemaReactComponents,
|
||||
} from './types';
|
||||
|
||||
export {
|
||||
useForm,
|
||||
useCurrentFieldState,
|
||||
type FormModel,
|
||||
} from '@flowgram-adapter/free-layout-editor';
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { createContext } from 'react';
|
||||
|
||||
import type { FormSchemaReactComponents } from '../types';
|
||||
|
||||
export const ComponentsContext = createContext<FormSchemaReactComponents>({});
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { type ReactNode } from 'react';
|
||||
|
||||
import { ReactiveState } from '@flowgram-adapter/common';
|
||||
|
||||
import type { IFormSchema, FormSchemaUIState } from '../types';
|
||||
|
||||
interface PropertyWithKey {
|
||||
key: string;
|
||||
schema: IFormSchema;
|
||||
}
|
||||
|
||||
export class FormSchema implements IFormSchema {
|
||||
/** IFormSchema 透传属性 */
|
||||
type?: string | undefined;
|
||||
title?: ReactNode;
|
||||
description?: ReactNode;
|
||||
required?: boolean;
|
||||
properties?: Record<string, IFormSchema>;
|
||||
defaultValue?: any;
|
||||
|
||||
/** 模型属性 */
|
||||
uiState = new ReactiveState<FormSchemaUIState>({ disabled: false });
|
||||
path: string[] = [];
|
||||
|
||||
constructor(json: IFormSchema, path: string[] = []) {
|
||||
this.fromJSON(json);
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
get componentType() {
|
||||
return this['x-component'];
|
||||
}
|
||||
get componentProps() {
|
||||
return this['x-component-props'];
|
||||
}
|
||||
get decoratorType() {
|
||||
return this['x-decorator'];
|
||||
}
|
||||
get decoratorProps() {
|
||||
return this['x-decorator-props'];
|
||||
}
|
||||
|
||||
fromJSON(json: IFormSchema) {
|
||||
Object.entries(json).forEach(([key, value]) => {
|
||||
this[key] = value;
|
||||
});
|
||||
this.uiState.value.disabled = json['x-disabled'] ?? false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得有序的 properties
|
||||
*/
|
||||
static getProperties(schema: FormSchema | IFormSchema) {
|
||||
const orderProperties: PropertyWithKey[] = [];
|
||||
const unOrderProperties: PropertyWithKey[] = [];
|
||||
Object.entries(schema.properties || {}).forEach(([key, item]) => {
|
||||
const index = item['x-index'];
|
||||
if (index !== undefined && !isNaN(index)) {
|
||||
orderProperties[index] = { schema: item, key };
|
||||
} else {
|
||||
unOrderProperties.push({ schema: item, key });
|
||||
}
|
||||
});
|
||||
return orderProperties.concat(unOrderProperties).filter(item => !!item);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { ComponentsContext } from './components-context';
|
||||
export { FormSchema } from './form-schema';
|
||||
export { SchemaContext, FormSchemaContext } from './schema-context';
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { createContext } from 'react';
|
||||
|
||||
import type { FormSchema } from './form-schema';
|
||||
|
||||
export const SchemaContext = createContext<FormSchema>({} as any);
|
||||
|
||||
export const FormSchemaContext = createContext<FormSchema>({} as any);
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
type JSXComponent =
|
||||
| keyof JSX.IntrinsicElements
|
||||
| React.JSXElementConstructor<any>;
|
||||
|
||||
export type FormSchemaReactComponents = Record<string, JSXComponent>;
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export type {
|
||||
IFormSchema,
|
||||
IFormSchemaValidate,
|
||||
FormSchemaUIState,
|
||||
} from './schema';
|
||||
export type { FormSchemaReactComponents } from './context';
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { Validate } from '@flowgram-adapter/free-layout-editor';
|
||||
|
||||
export type FormSchemaTypes =
|
||||
| 'string'
|
||||
| 'object'
|
||||
| 'array'
|
||||
| 'number'
|
||||
| 'boolean'
|
||||
| 'void'
|
||||
| string;
|
||||
|
||||
export type IFormSchemaValidate = Validate;
|
||||
|
||||
export interface FormSchemaUIState {
|
||||
disabled: boolean;
|
||||
}
|
||||
|
||||
export interface IFormSchema<FrameworkComponent = React.ReactNode> {
|
||||
/*******************************************************
|
||||
* 核心属性
|
||||
*/
|
||||
version?: string;
|
||||
name?: string;
|
||||
type?: FormSchemaTypes;
|
||||
/** 默认值,“default” 是 jsonSchema 标准字段,但其为 js 关键字,遂使用 defaultValue */
|
||||
defaultValue?: any;
|
||||
|
||||
/*******************************************************
|
||||
* 下钻属性
|
||||
*/
|
||||
properties?: Record<string, IFormSchema<FrameworkComponent>>;
|
||||
items?: IFormSchema<FrameworkComponent>[];
|
||||
|
||||
/*******************************************************
|
||||
* ui 属性
|
||||
*/
|
||||
title?: FrameworkComponent | string;
|
||||
description?: FrameworkComponent | string;
|
||||
/** 顺序 */
|
||||
['x-index']?: number;
|
||||
['x-visible']?: boolean;
|
||||
['x-hidden']?: boolean;
|
||||
['x-disabled']?: boolean;
|
||||
/** 渲染的组件 */
|
||||
['x-component']?: string;
|
||||
['x-component-props']?: Record<string, unknown>;
|
||||
/** 装饰器 */
|
||||
['x-decorator']?: string;
|
||||
['x-decorator-props']?: Record<string, unknown>;
|
||||
|
||||
/*******************************************************
|
||||
* 合法性属性
|
||||
*/
|
||||
required?: boolean;
|
||||
['x-validator']?: IFormSchemaValidate;
|
||||
|
||||
/*******************************************************
|
||||
* 不常用或实现成本较高
|
||||
*/
|
||||
['x-reactions']?: any;
|
||||
['x-content']?: FrameworkComponent;
|
||||
/** 通配符字段 */
|
||||
patternProperties?: Record<string, IFormSchema<FrameworkComponent>>;
|
||||
/** 定义之外的字段 */
|
||||
additionalProperties?: IFormSchema<FrameworkComponent>;
|
||||
/** 定义之外的项 */
|
||||
additionalItems?: IFormSchema<FrameworkComponent>;
|
||||
|
||||
/*******************************************************
|
||||
* 业务自定义字段
|
||||
*/
|
||||
/** 节点 id */
|
||||
['x-node-id']?: string;
|
||||
/** 节点类型 */
|
||||
['x-node-type']?: string;
|
||||
/** 表单模式 */
|
||||
['x-form-mode']?: 'form' | 'json';
|
||||
/** 字段对应变量原始类型 */
|
||||
['x-origin-type']?: string;
|
||||
[key: string]: any;
|
||||
}
|
||||
26
frontend/packages/workflow/test-run-next/form/src/global.d.ts
vendored
Normal file
26
frontend/packages/workflow/test-run-next/form/src/global.d.ts
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/// <reference types='@coze-arch/bot-typings' />
|
||||
declare module '*.otf' {
|
||||
const content: string;
|
||||
export default content;
|
||||
}
|
||||
|
||||
declare module '*.ttf' {
|
||||
const content: string;
|
||||
export default content;
|
||||
}
|
||||
55
frontend/packages/workflow/test-run-next/form/src/index.ts
Normal file
55
frontend/packages/workflow/test-run-next/form/src/index.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* TestRun Form
|
||||
*/
|
||||
/** Form Engine */
|
||||
export {
|
||||
createSchemaField,
|
||||
useFormSchema,
|
||||
useForm,
|
||||
useCurrentFieldState,
|
||||
FormSchema,
|
||||
type FormModel,
|
||||
type IFormSchema,
|
||||
} from './form-engine';
|
||||
|
||||
/** components */
|
||||
export { TestRunForm } from './components/test-run-form';
|
||||
export {
|
||||
InputJson as FormBaseInputJson,
|
||||
GroupCollapse as FormBaseGroupCollapse,
|
||||
FieldItem as FormBaseFieldItem,
|
||||
} from './components/base-form-materials';
|
||||
|
||||
/** context */
|
||||
export {
|
||||
TestRunFormProvider,
|
||||
useTestRunFormStore,
|
||||
type TestRunFormState,
|
||||
} from './context';
|
||||
|
||||
/** utils */
|
||||
export {
|
||||
generateField,
|
||||
generateFieldValidator,
|
||||
isFormSchemaPropertyEmpty,
|
||||
stringifyFormValuesFromBacked,
|
||||
} from './utils';
|
||||
|
||||
/** constants */
|
||||
export { TestFormFieldName } from './constants';
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ViewVariableType, getFileAccept } from '@coze-workflow/base';
|
||||
|
||||
interface GenerateFieldComponentOptions {
|
||||
type: ViewVariableType;
|
||||
validateJsonSchema?: any;
|
||||
}
|
||||
|
||||
export const generateFieldComponent = (
|
||||
options: GenerateFieldComponentOptions,
|
||||
) => {
|
||||
const { type, validateJsonSchema } = options;
|
||||
/** 音色类型 */
|
||||
if (ViewVariableType.Voice === type) {
|
||||
return {
|
||||
['x-component']: 'SelectVoice',
|
||||
};
|
||||
}
|
||||
/** 文件类型 */
|
||||
if (ViewVariableType.isFileType(type)) {
|
||||
const fileType = [
|
||||
ViewVariableType.Image,
|
||||
ViewVariableType.ArrayImage,
|
||||
].includes(type)
|
||||
? 'image'
|
||||
: 'object';
|
||||
return {
|
||||
['x-component']: 'TypedFileInput',
|
||||
['x-component-props']: {
|
||||
// 如果是数组类型,则表明是多选的文件选择器
|
||||
multiple: ViewVariableType.isArrayType(type),
|
||||
accept: getFileAccept(type),
|
||||
fileType,
|
||||
},
|
||||
};
|
||||
}
|
||||
/** 排除文件类型的对象类型、数组类型 */
|
||||
if (ViewVariableType.isArrayType(type) || ViewVariableType.Object === type) {
|
||||
return {
|
||||
['x-component']: 'InputJson',
|
||||
['x-component-props']: {
|
||||
jsonSchema: validateJsonSchema,
|
||||
},
|
||||
defaultValue: ViewVariableType.Object === type ? '{}' : '[]',
|
||||
};
|
||||
}
|
||||
if (type === ViewVariableType.Integer) {
|
||||
return {
|
||||
['x-component']: 'InputInteger',
|
||||
};
|
||||
}
|
||||
if (type === ViewVariableType.Number) {
|
||||
return {
|
||||
['x-component']: 'InputNumber',
|
||||
};
|
||||
}
|
||||
if (type === ViewVariableType.Boolean) {
|
||||
return {
|
||||
['x-component']: 'SelectBoolean',
|
||||
defaultValue: true,
|
||||
};
|
||||
}
|
||||
if (type === ViewVariableType.Time) {
|
||||
return {
|
||||
['x-component']: 'InputTime',
|
||||
};
|
||||
}
|
||||
/** string 类型和其它未知类型都渲染普通输入框 */
|
||||
return {
|
||||
['x-component']: 'InputString',
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import Ajv from 'ajv';
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
|
||||
import { type IFormSchemaValidate } from '../form-engine';
|
||||
|
||||
const isEmptyValue = (v: unknown) => v === undefined || v === null || v === '';
|
||||
|
||||
interface GenerateFieldValidatorOptions {
|
||||
name: string;
|
||||
title?: string;
|
||||
required?: boolean;
|
||||
validateJsonSchema?: any;
|
||||
}
|
||||
|
||||
/**
|
||||
* ajv 实例缓存
|
||||
* 无需导入创建或者多次创建,优化内存开销
|
||||
*/
|
||||
let ajvCache: undefined | Ajv;
|
||||
|
||||
export const generateFieldValidator = (
|
||||
options: GenerateFieldValidatorOptions,
|
||||
) => {
|
||||
const { required, title, name, validateJsonSchema } = options;
|
||||
|
||||
const validator: IFormSchemaValidate = ({ value }) => {
|
||||
if (required && isEmptyValue(value)) {
|
||||
return I18n.t('workflow_testset_required_tip', {
|
||||
param_name: title || name,
|
||||
});
|
||||
}
|
||||
// 如果有结构化描述,还需要对值进行反序列化校验
|
||||
if (validateJsonSchema && value !== undefined) {
|
||||
if (!ajvCache) {
|
||||
ajvCache = new Ajv();
|
||||
}
|
||||
try {
|
||||
const valueObject = JSON.parse(value);
|
||||
const validate = ajvCache.compile(validateJsonSchema);
|
||||
const valid = validate(valueObject);
|
||||
return valid ? undefined : I18n.t('workflow_debug_wrong_json');
|
||||
} catch {
|
||||
/**
|
||||
* 报错有多种可能,预期结果都是校验不通过
|
||||
* 1. 值反序列化失败
|
||||
* 2. 反序列化的值不合法
|
||||
*/
|
||||
return I18n.t('workflow_debug_wrong_json');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
['x-validator']: validator,
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ViewVariableType } from '@coze-workflow/base';
|
||||
|
||||
import { type IFormSchema } from '../form-engine';
|
||||
import { generateFieldValidator } from './generate-field-validator';
|
||||
import { generateFieldComponent } from './generate-field-component';
|
||||
|
||||
interface GenerateFieldOptions {
|
||||
type: ViewVariableType;
|
||||
name: string;
|
||||
title?: string;
|
||||
required?: boolean;
|
||||
description?: string;
|
||||
defaultValue?: string;
|
||||
validateJsonSchema?: any;
|
||||
extra?: IFormSchema;
|
||||
}
|
||||
|
||||
/**
|
||||
* 表单 Field Schema 计算
|
||||
*/
|
||||
export const generateField = (options: GenerateFieldOptions): IFormSchema => {
|
||||
const {
|
||||
type,
|
||||
name,
|
||||
title,
|
||||
required = true,
|
||||
description,
|
||||
defaultValue,
|
||||
validateJsonSchema,
|
||||
extra,
|
||||
} = options;
|
||||
|
||||
return {
|
||||
name,
|
||||
title,
|
||||
description,
|
||||
required,
|
||||
['x-decorator']: 'FieldItem',
|
||||
['x-decorator-props']: {
|
||||
tag: ViewVariableType.LabelMap[type],
|
||||
},
|
||||
['x-origin-type']: type as unknown as string,
|
||||
...generateFieldValidator(options),
|
||||
// 渲染组件相关
|
||||
...generateFieldComponent({ type, validateJsonSchema }),
|
||||
// component 也自带默认值,入参的默认值优先级更高
|
||||
defaultValue,
|
||||
...extra,
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { generateField } from './generate-field';
|
||||
export { generateFieldValidator } from './generate-field-validator';
|
||||
export { isFormSchemaPropertyEmpty } from './is-property-empty';
|
||||
export { stringifyFormValuesFromBacked } from './stringify-form-values-from-backed';
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { isObject } from 'lodash-es';
|
||||
|
||||
/**
|
||||
* 是否是空的 properties
|
||||
*/
|
||||
export const isFormSchemaPropertyEmpty = (properties: unknown) =>
|
||||
isObject(properties) ? !Object.keys(properties).length : true;
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { isBoolean } from 'lodash-es';
|
||||
|
||||
export const stringifyFormValuesFromBacked = (value: object) => {
|
||||
if (!value) {
|
||||
return undefined;
|
||||
}
|
||||
return Object.keys(value).reduce((acc, key) => {
|
||||
const val = value[key];
|
||||
if (val === null || val === undefined) {
|
||||
acc[key] = undefined;
|
||||
} else if (typeof val === 'string' || isBoolean(val)) {
|
||||
acc[key] = val;
|
||||
} else {
|
||||
acc[key] = JSON.stringify(value[key]);
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
};
|
||||
Reference in New Issue
Block a user