Files
leaudit-platform-frontend/docs/contract-draft-ui-fixes.md
T
2025-12-05 00:09:32 +08:00

306 lines
8.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 合同起草页面 UI 修复
## 修复内容
### 1. 修复 `json` 弃用警告
**问题**
```
"json"已弃用。ts(6385)
This utility is deprecated in favor of opting into Single Fetch via future.v3_singleFetch
and returning raw objects. This method will be removed in React Router v7.
```
**解决方案**
使用 `Response.json()` 替代 Remix 的 `json()` 函数。
**修改的代码**
```typescript
// ❌ 旧代码(已弃用)
import { json, redirect } from '@remix-run/node';
export async function loader() {
return json({ data });
}
export async function action() {
return json({ success: true }, { status: 200 });
}
```
```typescript
// ✅ 新代码(使用标准 Web API)
import { redirect } from '@remix-run/node';
export async function loader() {
return Response.json({ data });
}
export async function action() {
return Response.json({ success: true }, { status: 200 });
}
```
**优势**
- 使用标准 Web API,兼容性更好
- 未来 React Router v7 不会移除
- 符合现代 Web 标准
### 2. 修复 FilePreview 高度问题
**问题**
FilePreview 组件没有占满父级容器的高度,导致页面布局不完整。
**根本原因**
1. 父容器没有高度限制
2. FilePreview 根元素没有设置 `h-full`
3. 内容区域使用固定的 `maxHeight: calc(100vh - 150px)`,不适用于嵌套布局
**解决方案**
#### 修改 1:父容器添加高度
`app/routes/contract-draft.$draftId.tsx`:
```typescript
// ❌ 旧代码
<div className="w-[60%] border-r border-gray-200 bg-white">
<FilePreview ... />
</div>
<div className="w-[40%] bg-white">
<PlaceholderForm ... />
</div>
```
```typescript
// ✅ 新代码
<div className="w-[60%] border-r border-gray-200 bg-white h-full overflow-hidden">
<FilePreview ... />
</div>
<div className="w-[40%] bg-white h-full overflow-hidden">
<PlaceholderForm ... />
</div>
```
**变化**
- 添加 `h-full` - 高度占满父容器
- 添加 `overflow-hidden` - 防止内容溢出
#### 修改 2FilePreview 根元素使用 Flex 布局
`app/components/reviews/FilePreview.tsx`:
```typescript
// ❌ 旧代码
return (
<div className="file-preview">
<div className="file-preview-header ...">...</div>
<div className="file-preview-content" style={{ maxHeight: 'calc(100vh - 150px)' }}>...</div>
</div>
);
```
```typescript
// ✅ 新代码
return (
<div className="file-preview h-full flex flex-col">
<div className="file-preview-header ... flex-shrink-0">...</div>
<div className="file-preview-content flex-1 overflow-auto">...</div>
</div>
);
```
**变化**
- 根元素:添加 `h-full flex flex-col` - 占满高度,使用垂直 Flex 布局
- Header:添加 `flex-shrink-0` - 固定高度,不压缩
- Content:使用 `flex-1 overflow-auto` 替代固定 `maxHeight` - 占据剩余空间,自动滚动
## 布局原理
### Flex 布局结构
```
┌─────────────────────────────────────────┐
│ h-screen flex flex-col │ ← 全屏容器
├─────────────────────────────────────────┤
│ 顶部工具栏 (固定高度) │ ← flex-shrink-0
├─────────────────────────────────────────┤
│ flex-1 flex overflow-hidden │ ← 主内容区(占据剩余空间)
│ ┌─────────────┬─────────────────────┐ │
│ │ w-[60%] │ w-[40%] │ │
│ │ h-full │ h-full │ │
│ │ ┌─────────┐ │ ┌─────────────────┐ │ │
│ │ │FilePreview│ │PlaceholderForm │ │ │
│ │ │h-full │ │ │ │ │
│ │ │flex-col │ │ │ │ │
│ │ │┌────────┐│ │ │ │ │
│ │ ││Header ││ │ │ │ │
│ │ ││(固定) ││ │ │ │ │
│ │ │├────────┤│ │ │ │ │
│ │ ││Content ││ │ │ │ │
│ │ ││flex-1 ││ │ │ │ │
│ │ ││(自适应)││ │ │ │ │
│ │ │└────────┘│ │ │ │ │
│ │ └─────────┘ │ └─────────────────┘ │ │
│ └─────────────┴─────────────────────┘ │
└─────────────────────────────────────────┘
```
### 关键 CSS 类
| 类名 | 作用 | 使用位置 |
|------|------|----------|
| `h-screen` | 高度 100vh | 根容器 |
| `flex flex-col` | 垂直 Flex 布局 | 根容器、FilePreview |
| `flex-1` | 占据剩余空间 | 主内容区、Content |
| `h-full` | 高度 100% | 左右侧容器、FilePreview |
| `overflow-hidden` | 隐藏溢出 | 左右侧容器 |
| `overflow-auto` | 自动滚动 | Content 区域 |
| `flex-shrink-0` | 不压缩 | Header |
## 测试验证
### 1. 启动开发服务器
```bash
npm run dev
```
### 2. 访问草稿页面
```
http://localhost:5173/contract-draft/1
```
### 3. 验证布局
**应该看到**
- 页面占满整个屏幕(无滚动条)
- 左侧文档预览占 60% 宽度,**高度占满**
- 右侧表单占 40% 宽度,**高度占满**
- FilePreview 内容区域可以独立滚动
- 表单区域可以独立滚动
**不应该看到**
- FilePreview 底部有空白
- 页面外层有滚动条(应该在内容区域内滚动)
- 布局错乱或内容溢出
### 4. 响应式测试
- 调整浏览器窗口大小
- FilePreview 和 PlaceholderForm 应该始终占满高度
- 内容区域应该自动调整滚动
## 修改的文件
### 1. `app/routes/contract-draft.$draftId.tsx`
**变化**
- ✅ 移除 `json` 导入
- ✅ 所有 `json()` 替换为 `Response.json()`
- ✅ 左右侧容器添加 `h-full overflow-hidden`
**位置**
- Line 7: 移除 `json` 导入
- Line 104: `Response.json({ draft, template })`
- Line 117, 123, 138, 141, 144: `Response.json()`
- Line 353, 374: 添加 `h-full overflow-hidden`
### 2. `app/components/reviews/FilePreview.tsx`
**变化**
- ✅ 根元素添加 `h-full flex flex-col`
- ✅ Header 添加 `flex-shrink-0`
- ✅ Content 改用 `flex-1 overflow-auto`,移除固定 `maxHeight`
**位置**
- Line 429: `<div className="file-preview h-full flex flex-col">`
- Line 430: Header 添加 `flex-shrink-0`
- Line 525: `<div className="file-preview-content flex-1 overflow-auto">`
## 常见问题
### Q1: FilePreview 仍然没有占满高度
**原因**:浏览器缓存了旧的样式
**解决**
1. 硬刷新页面(Ctrl+Shift+R 或 Cmd+Shift+R
2. 清除浏览器缓存
3. 重启开发服务器
### Q2: 内容区域滚动不流畅
**原因**:可能是 `overflow-hidden``overflow-auto` 冲突
**解决**
确保父容器使用 `overflow-hidden`,子容器(内容区域)使用 `overflow-auto`
### Q3: 在其他页面 FilePreview 布局变了
**影响范围**:此修改影响所有使用 FilePreview 的页面
**如果出现问题**
- 检查该页面的父容器是否有足够的高度
- 可能需要给父容器添加 `h-full` 或明确的高度值
- 或者给 FilePreview 添加一个 prop 来控制是否使用 flex 布局
### Q4: 响应式布局问题
**现象**:小屏幕下布局错乱
**解决**
可以添加响应式类,例
```typescript
<div className="w-full md:w-[60%] h-full overflow-hidden">
```
## 后续优化
### 1. 添加 prop 控制布局模式(可选)
```typescript
interface FilePreviewProps {
// ... existing props
layoutMode?: 'flex' | 'fixed'; // 新增:控制布局模式
}
// 在组件中使用
<div className={`file-preview ${layoutMode === 'flex' ? 'h-full flex flex-col' : ''}`}>
```
### 2. 优化滚动性能
```typescript
<div
className="file-preview-content flex-1 overflow-auto"
style={{ scrollBehavior: 'smooth' }} // 平滑滚动
>
```
### 3. 添加加载状态
在文档加载时显示骨架屏或加载动画,占满高度,避免布局跳动。
## 总结
**已修复**
1. `json` 弃用警告 - 使用 `Response.json()`
2. FilePreview 高度问题 - 使用 Flex 布局占满父容器
**布局改进**
- 使用现代 Flex 布局替代固定高度
- 更好的响应式支持
- 内容区域独立滚动
**代码质量**
- 符合 Web 标准
- 更易维护
- 类型检查通过
🎯 **可以开始测试了**!页面布局应该正常了。