feat:优化配置项分类,maisaka聊天流监控展示

This commit is contained in:
SengokuCola
2026-05-04 17:28:14 +08:00
parent 120acb835f
commit ccb1d60e06
12 changed files with 561 additions and 46 deletions

View File

@@ -34,6 +34,16 @@ function hasTopLevelAdvancedFields(schema: ConfigSchema) {
return schema.fields.some((field) => field.advanced && !schema.nested?.[field.name])
}
function resolveSectionTitle(schema: ConfigSchema) {
return schema.uiLabel || schema.classDoc || schema.className
}
function resolveSectionDescription(schema: ConfigSchema, sectionTitle: string) {
return schema.classDoc && schema.classDoc !== sectionTitle
? schema.classDoc
: undefined
}
function SectionIcon({ iconName }: { iconName?: string }) {
if (!iconName) return null
const IconComponent = LucideIcons[iconName as keyof typeof LucideIcons] as
@@ -66,23 +76,33 @@ function DynamicConfigSection({
basePath,
hooks,
level,
mergedChildren = [],
nestedSchema,
onChange,
sectionDescription,
sectionKey,
sectionTitle,
values,
}: {
basePath: string
hooks: FieldHookRegistry
level: number
mergedChildren?: Array<{
key: string
schema: ConfigSchema
values: Record<string, unknown>
}>
nestedSchema: ConfigSchema
onChange: (field: string, value: unknown) => void
sectionDescription?: string
sectionKey: string
sectionTitle: string
values: Record<string, unknown>
}) {
const [advancedVisible, setAdvancedVisible] = React.useState(false)
const hasAdvanced = hasTopLevelAdvancedFields(nestedSchema)
const hasAdvanced =
hasTopLevelAdvancedFields(nestedSchema) ||
mergedChildren.some((child) => hasTopLevelAdvancedFields(child.schema))
return (
<Card>
@@ -109,12 +129,43 @@ function DynamicConfigSection({
<DynamicConfigForm
schema={nestedSchema}
values={values}
onChange={onChange}
onChange={(field, value) => onChange(`${sectionKey}.${field}`, value)}
basePath={basePath}
hooks={hooks}
level={level}
advancedVisible={hasAdvanced ? advancedVisible : undefined}
/>
{mergedChildren.map((child) => {
const childTitle = resolveSectionTitle(child.schema)
const childDescription = resolveSectionDescription(child.schema, childTitle)
const parentPath = basePath.includes('.')
? basePath.replace(/\.[^.]+$/, '')
: ''
const childPath = buildFieldPath(parentPath, child.key)
return (
<div key={child.key} className="mt-5 border-t border-border/50 pt-4">
<div className="mb-3 space-y-1">
<div className="flex items-center gap-2">
<SectionIcon iconName={child.schema.uiIcon} />
<h3 className="text-sm font-medium">{childTitle}</h3>
</div>
{childDescription && (
<p className="text-xs text-muted-foreground">{childDescription}</p>
)}
</div>
<DynamicConfigForm
schema={child.schema}
values={child.values}
onChange={(field, value) => onChange(`${child.key}.${field}`, value)}
basePath={childPath}
hooks={hooks}
level={level}
advancedVisible={hasAdvanced ? advancedVisible : undefined}
/>
</div>
)
})}
</CardContent>
</Card>
)
@@ -146,6 +197,17 @@ export const DynamicConfigForm: React.FC<DynamicConfigFormProps> = ({
() => new Map(schema.fields.map((field) => [field.name, field])),
[schema.fields],
)
const mergedChildKeys = React.useMemo(() => {
const keys = new Set<string>()
for (const nestedSchema of Object.values(schema.nested ?? {})) {
for (const childKey of nestedSchema.uiMergeChildren ?? []) {
if (schema.nested?.[childKey]) {
keys.add(childKey)
}
}
}
return keys
}, [schema.nested])
const renderField = (field: FieldSchema) => {
const fieldPath = buildFieldPath(basePath, field.name)
@@ -231,7 +293,9 @@ export const DynamicConfigForm: React.FC<DynamicConfigFormProps> = ({
)}
{schema.nested &&
Object.entries(schema.nested).map(([key, nestedSchema]) => {
Object.entries(schema.nested)
.filter(([key]) => !mergedChildKeys.has(key))
.map(([key, nestedSchema]) => {
const nestedField = fieldMap.get(key)
const nestedFieldPath = buildFieldPath(basePath, key)
@@ -276,23 +340,43 @@ export const DynamicConfigForm: React.FC<DynamicConfigFormProps> = ({
)
}
const sectionTitle =
nestedSchema.uiLabel || nestedSchema.classDoc || nestedSchema.className
const sectionDescription =
nestedSchema.classDoc && nestedSchema.classDoc !== sectionTitle
? nestedSchema.classDoc
: undefined
const sectionTitle = resolveSectionTitle(nestedSchema)
const sectionDescription = resolveSectionDescription(nestedSchema, sectionTitle)
const mergedChildren = (nestedSchema.uiMergeChildren ?? [])
.map((childKey) => {
const childSchema = schema.nested?.[childKey]
if (!childSchema) {
return null
}
return {
key: childKey,
schema: childSchema,
values: (values[childKey] as Record<string, unknown>) || {},
}
})
.filter(
(
child,
): child is {
key: string
schema: ConfigSchema
values: Record<string, unknown>
} => Boolean(child),
)
if (level === 0) {
return (
<DynamicConfigSection
key={key}
mergedChildren={mergedChildren}
nestedSchema={nestedSchema}
values={(values[key] as Record<string, unknown>) || {}}
onChange={(field, value) => onChange(`${key}.${field}`, value)}
onChange={onChange}
basePath={nestedFieldPath}
hooks={hooks}
level={level + 1}
sectionKey={key}
sectionTitle={sectionTitle}
sectionDescription={sectionDescription}
/>