refactor(ui): migrate ModelConfigs page to consistency baseline (ui-consistency ticket 04)

FormDrawer with footer submit and submitting guard, 20-row conditional
pagination, Empty locale, unified delete Popconfirm wording. Capability
and modality validation logic unchanged.
This commit is contained in:
sinohqb 2026-08-05 20:22:14 +08:00
parent 2e78c4befd
commit f1316578fe
2 changed files with 31 additions and 19 deletions

View File

@ -5,8 +5,8 @@
**Blocked by:** 03检查点通过后 **Blocked by:** 03检查点通过后
**Acceptance criteria:** **Acceptance criteria:**
- [ ] 创建/编辑表单统一 FormDrawer - [x] 创建/编辑表单统一 FormDrawer
- [ ] 删除有 Popconfirm启用/停用开关行为不变 - [x] 删除有 Popconfirm启用/停用开关行为不变
- [ ] 空态 Empty、20 行分页阈值 - [x] 空态 Empty、20 行分页阈值
- [ ] `tsc --noEmit` 通过 - [x] `tsc --noEmit` 通过
- [ ] t480 走查:模型配置 CRUD + 能力约束校验 golden path - [ ] t480 走查:模型配置 CRUD + 能力约束校验 golden path

View File

@ -1,15 +1,16 @@
import { useState } from 'react' import { useState } from 'react'
import { import {
Button, Divider, Drawer, Form, Input, InputNumber, message, Popconfirm, Select, Space, Switch, Table, Tag, Button, Divider, Empty, Form, Input, InputNumber, message, Popconfirm, Select, Space, Switch, Table, Tag,
Tooltip, Tooltip,
} from 'antd' } from 'antd'
import { import {
ApiOutlined, CheckCircleOutlined, DeleteOutlined, EditOutlined, PlusOutlined, ReloadOutlined, ApiOutlined, DeleteOutlined, EditOutlined, PlusOutlined, ReloadOutlined,
} from '@ant-design/icons' } from '@ant-design/icons'
import { import {
modelConfigsApi, type ModelCapability, type ModelConfig, type ModelConfigPayload, type ModelModality, modelConfigsApi, type ModelCapability, type ModelConfig, type ModelConfigPayload, type ModelModality,
type ModelProtocol, type ModelProtocol,
} from '../api' } from '../api'
import FormDrawer from '../components/FormDrawer'
import PageWrapper from '../components/PageWrapper' import PageWrapper from '../components/PageWrapper'
import { useResource } from '../hooks/useResource' import { useResource } from '../hooks/useResource'
import { formatDateTime } from '../utils/date' import { formatDateTime } from '../utils/date'
@ -85,6 +86,7 @@ const protocolOptions: Record<ModelProtocol, {
export default function ModelConfigsPage() { export default function ModelConfigsPage() {
const [drawerOpen, setDrawerOpen] = useState(false) const [drawerOpen, setDrawerOpen] = useState(false)
const [editing, setEditing] = useState<ModelConfig | null>(null) const [editing, setEditing] = useState<ModelConfig | null>(null)
const [submitting, setSubmitting] = useState(false)
const [testingId, setTestingId] = useState<string | null>(null) const [testingId, setTestingId] = useState<string | null>(null)
const [capability, setCapability] = useState<ModelCapability | undefined>() const [capability, setCapability] = useState<ModelCapability | undefined>()
const [enabled, setEnabled] = useState<boolean | undefined>() const [enabled, setEnabled] = useState<boolean | undefined>()
@ -170,11 +172,21 @@ export default function ModelConfigsPage() {
description: values.description || '', description: values.description || '',
} }
if (editing) { if (editing) {
await modelConfigsApi.update(editing.id, payload) setSubmitting(true)
message.success('模型配置已更新') try {
await modelConfigsApi.update(editing.id, payload)
message.success('模型配置已更新')
} finally {
setSubmitting(false)
}
} else { } else {
await modelConfigsApi.create(payload) setSubmitting(true)
message.success('模型配置已创建') try {
await modelConfigsApi.create(payload)
message.success('模型配置已创建')
} finally {
setSubmitting(false)
}
} }
notifyModelConfigsChanged() notifyModelConfigsChanged()
setDrawerOpen(false) setDrawerOpen(false)
@ -317,7 +329,7 @@ export default function ModelConfigsPage() {
<Tooltip title="编辑"> <Tooltip title="编辑">
<Button type="text" size="small" icon={<EditOutlined />} onClick={() => openEdit(record)} /> <Button type="text" size="small" icon={<EditOutlined />} onClick={() => openEdit(record)} />
</Tooltip> </Tooltip>
<Popconfirm title="确认删除该模型配置?" onConfirm={() => remove(record)}> <Popconfirm title="删除该模型配置?" onConfirm={() => remove(record)}>
<Tooltip title="删除"> <Tooltip title="删除">
<Button type="text" size="small" danger icon={<DeleteOutlined />} /> <Button type="text" size="small" danger icon={<DeleteOutlined />} />
</Tooltip> </Tooltip>
@ -356,25 +368,25 @@ export default function ModelConfigsPage() {
</Space> </Space>
} }
> >
<div style={{ height: '100%', minHeight: 0, overflow: 'hidden' }}> <div style={{ height: '100%', overflowY: 'auto', padding: '0 16px 16px' }}>
<Table <Table
dataSource={configs ?? []} dataSource={configs ?? []}
columns={columns} columns={columns}
rowKey="id" rowKey="id"
loading={loading} loading={loading}
pagination={{ pageSize: 15, showSizeChanger: true, showTotal: (total) => `${total}` }} pagination={(configs?.length ?? 0) > 20 ? { pageSize: 20, showTotal: (t) => `${t}` } : false}
scroll={{ y: 'calc(100vh - 200px)' }} locale={{ emptyText: <Empty description="还没有模型配置" /> }}
style={{ height: '100%' }}
tableLayout="auto" tableLayout="auto"
/> />
</div> </div>
<Drawer <FormDrawer
title={editing ? '编辑模型配置' : '新增模型配置'} title={editing ? '编辑模型配置' : '新增模型配置'}
width="min(680px, 100vw)"
open={drawerOpen} open={drawerOpen}
onClose={() => setDrawerOpen(false)} onClose={() => setDrawerOpen(false)}
extra={<Button type="primary" icon={<CheckCircleOutlined />} onClick={submit}></Button>} onSubmit={submit}
submitting={submitting}
okText="保存"
> >
<Form form={form} layout="vertical"> <Form form={form} layout="vertical">
<Divider orientation="left" plain style={{ marginTop: 0 }}></Divider> <Divider orientation="left" plain style={{ marginTop: 0 }}></Divider>
@ -472,7 +484,7 @@ export default function ModelConfigsPage() {
</Form.Item> </Form.Item>
</Space> </Space>
</Form> </Form>
</Drawer> </FormDrawer>
</PageWrapper> </PageWrapper>
) )
} }