# 提交请求页面

## 概述

提交请求页面是用户发起新审批流程的入口，采用飞书风格的应用选择界面。用户可以浏览和搜索所有可用的表单应用，选择后进入表单填写页面。

## 功能特性

### 1. 搜索功能
- 顶部全局搜索框
- 支持按表单名称、Key、描述搜索
- 实时过滤结果

### 2. 最近编辑
- 显示最近使用的表单
- 快速访问常用表单
- 支持清除记录

### 3. 推荐应用
- 基于使用频率和最近使用推荐
- 网格卡片布局
- 最多显示 6 个

### 4. 分类浏览
- 左侧分类导航
- 右侧表单列表
- 按分类组织表单

### 5. 表单卡片
- 图标 + 名称展示
- 悬停效果（边框变蓝、阴影）
- 点击跳转到填写页面

## 技术实现

### 数据加载

```typescript
// 并行加载最近表单和所有表单
const [recentRes, allRes] = await Promise.all([
  getRecentForms(5),
  getFormDefinitions({ 
    forUse: true, 
    status: 'PUBLISHED',
    limit: 100 
  })
]);
```

### 分类分组

```typescript
const getCategoryGroups = (forms: FormDefinition[]): CategoryGroup[] => {
  const groupMap = new Map<string, FormDefinition[]>();
  
  forms.forEach(form => {
    const category = form.category || '未分类';
    if (!groupMap.has(category)) {
      groupMap.set(category, []);
    }
    groupMap.get(category)!.push(form);
  });
  
  return Array.from(groupMap.entries()).map(([name, forms]) => ({
    name,
    forms,
  }));
};
```

### 图标系统

```typescript
// 图标映射
const iconMap: Record<string, React.ReactNode> = {
  car: <Car />,
  dollar: <DollarSign />,
  shopping: <ShoppingCart />,
  // ...
};

// 颜色映射
const iconColorMap: Record<string, string> = {
  car: 'bg-orange-500',
  dollar: 'bg-blue-500',
  shopping: 'bg-blue-600',
  // ...
};
```

## 设计规范

### 布局结构

```
┌─────────────────────────────────────────┐
│  [搜索框]                                │
├─────────────────────────────────────────┤
│  最近编辑：Company Demo Car Application │
├─────────────────────────────────────────┤
│  推荐                                    │
│  [卡片] [卡片] [卡片] [卡片]            │
├─────────────────────────────────────────┤
│  所有应用                                │
│  ┌─────────┬───────────────────────────┐│
│  │ 分类1   │  [卡片] [卡片] [卡片]     ││
│  │ 分类2   │                           ││
│  │ 分类3   │  [卡片] [卡片] [卡片]     ││
│  └─────────┴───────────────────────────┘│
└─────────────────────────────────────────┘
```

### 卡片样式

```typescript
<button className="
  flex items-center gap-3 p-4 
  bg-white border border-gray-200 rounded-lg 
  hover:border-[#3370ff] hover:shadow-md 
  transition-all group text-left
">
  {/* 图标 */}
  <div className="w-10 h-10 rounded-lg bg-orange-500 flex items-center justify-center text-white">
    <Car className="w-5 h-5" />
  </div>
  
  {/* 内容 */}
  <div className="flex-1 min-w-0">
    <h3 className="text-sm font-medium text-gray-900 truncate group-hover:text-[#3370ff]">
      表单名称
    </h3>
    <p className="text-xs text-gray-500 mt-0.5 truncate">
      分类
    </p>
  </div>
</button>
```

### 颜色系统

- **主色**：`#3370ff` (飞书蓝)
- **背景色**：`#f7f8fa` (浅灰)
- **边框色**：`#e5e6eb` (灰色)
- **图标颜色**：
  - 橙色：`bg-orange-500`
  - 蓝色：`bg-blue-500`, `bg-blue-600`
  - 绿色：`bg-green-500`
  - 粉色：`bg-pink-500`
  - 紫色：`bg-purple-500`
  - 灰色：`bg-gray-500`

## 路由配置

### 当前页面
- 路径：`/submit-request`
- 组件：`submit-request/page.tsx`

### 跳转目标
- 表单填写：`/forms/fill/{formKey}`
- 示例：点击表单后跳转到 `/forms/fill/company-demo-car-application`

## 国际化

支持中英文切换：

```typescript
// 中文
submitRequest: {
  title: '提交请求',
  searchPlaceholder: '请输入应用名称',
  lastEdited: '最近编辑：',
  recommended: '推荐',
  allApplications: '所有应用',
}

// 英文
submitRequest: {
  title: 'Submit Request',
  searchPlaceholder: 'Please enter the name of the application',
  lastEdited: 'Last edited:',
  recommended: 'Recommended',
  allApplications: 'All Applications',
}
```

## 使用示例

### 基本使用

1. 访问 `/submit-request` 页面
2. 浏览推荐应用或搜索表单
3. 点击表单卡片
4. 跳转到表单填写页面

### 搜索表单

```typescript
// 在搜索框输入关键词
setSearchTerm('报销');

// 自动过滤表单
const filteredForms = allForms.filter(form => {
  const term = searchTerm.toLowerCase();
  return (
    form.name.toLowerCase().includes(term) ||
    form.key.toLowerCase().includes(term) ||
    form.description?.toLowerCase().includes(term)
  );
});
```

### 按分类浏览

```typescript
// 选择分类
setSelectedCategory('财务');

// 只显示选中分类的表单
{categoryGroups.map(group => {
  if (selectedCategory && group.name !== selectedCategory) {
    return null;
  }
  return <div>{/* 渲染表单 */}</div>;
})}
```

## 依赖 API

### 1. getRecentForms
```typescript
/**
 * 获取最近编辑的表单
 */
export async function getRecentForms(limit?: number): Promise<FormDefinition[]>
```

### 2. getFormDefinitions
```typescript
/**
 * 获取表单定义列表
 */
export async function getFormDefinitions(
  params?: QueryFormDefinitionsDto
): Promise<PaginatedResponse<FormDefinition>>
```

### 参数说明

```typescript
interface QueryFormDefinitionsDto {
  page?: number;
  limit?: number;
  status?: FormDefinitionStatus;  // 'PUBLISHED' - 只显示已发布的表单
  category?: string;
  keyword?: string;
  forUse?: boolean;  // true - 用于提交表单，跳过创建者权限过滤
}
```

## 性能优化

### 1. 并行加载
```typescript
const [recentRes, allRes] = await Promise.all([
  getRecentForms(5),
  getFormDefinitions({ forUse: true, status: 'PUBLISHED', limit: 100 })
]);
```

### 2. 错误容错
```typescript
getRecentForms(5).catch(() => [])  // 最近表单加载失败不影响主功能
```

### 3. 本地过滤
```typescript
// 搜索和分类过滤在前端完成，减少 API 请求
const filteredForms = allForms.filter(/* ... */);
```

## 待优化项

1. **分类多语言**
   - 当前分类名称未支持多语言
   - 需要在数据库中存储分类的 i18n 信息

2. **图标动态化**
   - 当前图标映射是硬编码
   - 可以改为从后端配置

3. **缓存优化**
   - 最近表单可以使用 localStorage 缓存
   - 表单列表可以设置过期时间

4. **懒加载**
   - 分类下的表单可以按需加载
   - 图片/图标懒加载

## 相关文档

- [表单管理 API](../../services/api/form-management.ts)
- [审批中心页面](../approvals/README.md)
- [表单填写页面](../forms/fill/README.md)
- [飞书设计规范](../../../../docs/standards/03-design-system/lark-style-guide.md)

