ServiceProvidersPage 抽屉缺少保存按钮
背景
在 ProviderSheet.tsx 中,点击编辑提供商时弹出的抽屉(Sheet)底部有"取消"和"保存"按钮。但在 ServiceProvidersPage.tsx 中,点击编辑按钮弹出的抽屉没有底部保存按钮,用户无法通过点击按钮提交表单。
问题原因
ProviderSheet.tsx 第 186 行,<Sheet> 组件通过 footer prop 传入了底部按钮区域(取消 + 保存/创建按钮)。
而 ServiceProvidersPage.tsx 第 1127 行,<Sheet> 没有传入 footer prop,所以抽屉底部没有任何操作按钮。
ProviderSheet.tsx 有 footer:
tsx
<Sheet
open={state.open}
onClose={onClose}
footer={footer} // ← 有 footer prop
>ServiceProvidersPage.tsx 没有 footer:
tsx
<Sheet
open={sheetOpen}
onClose={() => setSheetOpen(false)}
title={t('providersPage.detail.title')}
> // ← 没有 footer prop修改方案
只需修改 ServiceProvidersPage.tsx 一个文件,共 4 处改动:
改动 1:添加 useId 到 React import(第 1 行)
diff
- import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
+ import { useCallback, useEffect, useId, useMemo, useRef, useState } from 'react';改动 2:导入 sharedForm.module.scss 样式(第 32 行后)
复用 ProviderSheet.tsx 中已使用的 footer 按钮样式(.footerBtn、.footerBtnGhost、.footerBtnPrimary)。
diff
+ import formStyles from '@/features/providers/sheets/forms/sharedForm.module.scss';
import styles from './ServiceProvidersPage.module.scss';改动 3:添加 editSubmitting 状态和 editFormId(第 231 行后)
diff
const [sheetOpen, setSheetOpen] = useState(false);
+ const [editSubmitting, setEditSubmitting] = useState(false);
+ const editFormId = useId();
const [editTarget, setEditTarget] = useState<{editSubmitting:追踪表单提交中状态,提交时禁用按钮并显示加载图标editFormId:用useId()生成唯一表单 ID,替代硬编码的"sp-edit-form"
改动 4:给 <Sheet> 添加 footer prop(第 1126-1149 行)
将原来的:
tsx
<Sheet
open={sheetOpen}
onClose={() => setSheetOpen(false)}
title={t('providersPage.detail.title')}
>
<BaseProviderForm
brand="openaiCompatibility"
resource={buildEditResource(editTarget.provider, editTarget.providerIdx)}
mode="edit"
mutating={false}
formId="sp-edit-form"
onSubmit={handleFormSubmit}
renderEntryCardExtra={(realIdx) => (
<MoveDropdown
provider={editTarget.provider}
allProviders={providers}
onMove={(target) => handleMoveFromDrawer(realIdx, target)}
disabled={false}
/>
)}
/>
</Sheet>替换为:
tsx
<Sheet
open={sheetOpen}
onClose={() => setSheetOpen(false)}
title={t('providersPage.form.editEyebrow')}
footer={
<>
<button
type="button"
className={`${formStyles.footerBtn} ${formStyles.footerBtnGhost}`}
onClick={() => setSheetOpen(false)}
disabled={editSubmitting}
>
{t('providersPage.actions.cancel')}
</button>
<button
type="submit"
form={editFormId}
className={`${formStyles.footerBtn} ${formStyles.footerBtnPrimary}`}
disabled={editSubmitting}
>
{editSubmitting ? (
<IconLoader2 size={14} />
) : null}
{t('providersPage.actions.save')}
</button>
</>
}
closeDisabled={editSubmitting}
>
<BaseProviderForm
brand="openaiCompatibility"
resource={buildEditResource(editTarget.provider, editTarget.providerIdx)}
mode="edit"
mutating={editSubmitting}
formId={editFormId}
onSubmit={async (input) => {
setEditSubmitting(true);
try {
await handleFormSubmit(input);
} finally {
setEditSubmitting(false);
}
}}
renderEntryCardExtra={(realIdx) => (
<MoveDropdown
provider={editTarget.provider}
allProviders={providers}
onMove={(target) => handleMoveFromDrawer(realIdx, target)}
disabled={false}
/>
)}
/>
</Sheet>改动要点说明
| 改动点 | 说明 |
|---|---|
footer prop | 添加取消 + 保存按钮,与 ProviderSheet.tsx 保持一致 |
closeDisabled={editSubmitting} | 提交中禁止关闭抽屉,防止数据丢失 |
mutating={editSubmitting} | 将提交状态传递给 BaseProviderForm,禁用表单输入 |
formId={editFormId} | 使用 useId() 生成唯一 ID,避免硬编码字符串冲突 |
onSubmit 包装 | 在原有 handleFormSubmit 外包一层 setEditSubmitting 状态管理 |
title 改为 t('providersPage.form.editEyebrow') | 与 ProviderSheet.tsx 的编辑模式标题保持一致 |