feat: show panel struct

This commit is contained in:
Joel 2025-03-10 16:03:16 +08:00
parent e32cb0fdf8
commit 6913f64083
6 changed files with 31 additions and 24 deletions

View File

@ -27,7 +27,7 @@ const Field: FC<Props> = ({
<Tooltip popupContent={t('app.structOutput.moreFillTip')} disabled={depth !== MAX_DEPTH + 1}> <Tooltip popupContent={t('app.structOutput.moreFillTip')} disabled={depth !== MAX_DEPTH + 1}>
<div className={cn('flex pr-2 items-center justify-between rounded-md hover:bg-state-base-hover', depth !== MAX_DEPTH + 1 && 'cursor-pointer')}> <div className={cn('flex pr-2 items-center justify-between rounded-md hover:bg-state-base-hover', depth !== MAX_DEPTH + 1 && 'cursor-pointer')}>
<div className='grow flex items-stretch'> <div className='grow flex items-stretch'>
<TreeIndentLine depth={depth} isMoreFill={depth === MAX_DEPTH + 1} /> <TreeIndentLine depth={depth} />
{depth === MAX_DEPTH + 1 ? ( {depth === MAX_DEPTH + 1 ? (
<RiMoreFill className='w-3 h-3 text-text-tertiary' /> <RiMoreFill className='w-3 h-3 text-text-tertiary' />
) : (<div className='h-6 leading-6 grow w-0 truncate system-sm-medium text-text-secondary'>{name}</div>)} ) : (<div className='h-6 leading-6 grow w-0 truncate system-sm-medium text-text-secondary'>{name}</div>)}

View File

@ -7,8 +7,8 @@ import type { Field as FieldType } from '../../../../../llm/types'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
import TreeIndentLine from '../tree-indent-line' import TreeIndentLine from '../tree-indent-line'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { useBoolean } from 'ahooks'
const MAX_DEPTH = 10 import { RiArrowDropDownLine } from '@remixicon/react'
type Props = { name: string, payload: FieldType, depth?: number } type Props = { name: string, payload: FieldType, depth?: number }
@ -18,31 +18,37 @@ const Field: FC<Props> = ({
depth = 1, depth = 1,
}) => { }) => {
const { t } = useTranslation() const { t } = useTranslation()
if (depth > MAX_DEPTH + 1) const hasChildren = payload.type === Type.object && payload.properties
return null const [fold, {
toggle: toggleFold,
}] = useBoolean(false)
return ( return (
<div>
<div> <div>
<div className={cn('flex pr-2')}> <div className={cn('flex pr-2')}>
<TreeIndentLine depth={depth} /> <TreeIndentLine depth={depth} />
<div> <div className='grow'>
<div className='flex'> <div className='flex relative select-none'>
{hasChildren && (
<RiArrowDropDownLine
className={cn('absolute top-[50%] translate-y-[-50%] left-[-18px] bg-components-panel-bg w-4 h-4 text-text-tertiary cursor-pointer', fold && 'rotate-[270deg] text-text-accent')}
onClick={toggleFold}
/>
)}
<div className='h-6 truncate system-sm-medium text-text-secondary leading-6'>{name}</div> <div className='h-6 truncate system-sm-medium text-text-secondary leading-6'>{name}</div>
<div className='ml-3 shrink-0 system-xs-regular text-text-tertiary leading-6'>{getFieldType(payload)}</div> <div className='ml-3 shrink-0 system-xs-regular text-text-tertiary leading-6'>{getFieldType(payload)}</div>
<div className='ml-3 text-text-warning system-2xs-medium-uppercase leading-6'>Required</div> <div className='ml-3 text-text-warning system-2xs-medium-uppercase leading-6'>{t('app.structOutput.required')}</div>
</div> </div>
{payload.description && ( {payload.description && (
<div className='system-xs-regular text-text-tertiary truncate'>{payload.description}</div> <div className='flex'>
<div className='w-0 grow system-xs-regular text-text-tertiary truncate'>{payload.description}</div>
</div>
)} )}
</div> </div>
</div> </div>
</div> {hasChildren && !fold && (
{payload.type === Type.object && payload.properties && (
<div> <div>
{Object.keys(payload.properties).map(name => ( {Object.keys(payload.properties!).map(name => (
<Field <Field
key={name} key={name}
name={name} name={name}

View File

@ -5,12 +5,10 @@ import cn from '@/utils/classnames'
type Props = { type Props = {
depth?: number depth?: number
isMoreFill?: boolean
} }
const TreeIndentLine: FC<Props> = ({ const TreeIndentLine: FC<Props> = ({
depth = 1, depth = 1,
isMoreFill = false,
}) => { }) => {
const depthArray = Array.from({ length: depth }, (_, index) => index) const depthArray = Array.from({ length: depth }, (_, index) => index)
return ( return (

View File

@ -6,14 +6,14 @@ const data: StructuredOutput = {
properties: { properties: {
string_field: { string_field: {
type: Type.string, type: Type.string,
description: '可为空', description: '这是一个字符串类型的字段',
}, },
obj_field: { obj_field: {
type: Type.object, type: Type.object,
properties: { properties: {
string_field_1: { string_field_1: {
type: Type.string, type: Type.string,
description: '描述可为空', description: 'this is a string type field',
}, },
number_field_2: { number_field_2: {
type: Type.number, type: Type.number,
@ -62,6 +62,7 @@ const data: StructuredOutput = {
properties: { properties: {
sub_item_12: { sub_item_12: {
type: Type.object, type: Type.object,
description: 'This is a object type field.This is a object type field.This is a object type field.',
}, },
}, },
}, },

View File

@ -182,6 +182,7 @@ const translation = {
showMyCreatedAppsOnly: 'Created by me', showMyCreatedAppsOnly: 'Created by me',
structOutput: { structOutput: {
moreFillTip: 'Showing max 10 levels of nesting', moreFillTip: 'Showing max 10 levels of nesting',
required: 'Required',
}, },
} }

View File

@ -183,6 +183,7 @@ const translation = {
showMyCreatedAppsOnly: '我创建的', showMyCreatedAppsOnly: '我创建的',
structOutput: { structOutput: {
moreFillTip: '最多显示 10 级嵌套', moreFillTip: '最多显示 10 级嵌套',
required: '必填',
}, },
} }