library-picturebook-activity/.claude/skills/contest-detail-page.md

311 lines
8.1 KiB
Markdown
Raw Normal View History

2026-01-15 16:35:00 +08:00
# 赛事详情页面生成规范
## 概述
本规范用于快速生成赛事管理系统中的详情页面,这类页面具有统一的结构:
- 顶部导航栏(返回按钮 + 标题 + 操作按钮)
- 搜索表单
- 数据表格
## 页面结构
```
┌─────────────────────────────────────────────────┐
│ [← 返回] 页面标题 [操作按钮] │
├─────────────────────────────────────────────────┤
│ 搜索表单: [搜索条件...] [搜索] [重置] │
├─────────────────────────────────────────────────┤
│ 数据表格 │
│ ┌───┬──────┬──────┬──────┬──────┐ │
│ │序号│ 列1 │ 列2 │ 列3 │ 操作 │ │
│ ├───┼──────┼──────┼──────┼──────┤ │
│ │ 1 │ ... │ ... │ ... │ ... │ │
│ └───┴──────┴──────┴──────┴──────┘ │
└─────────────────────────────────────────────────┘
```
## 快速生成指令格式
向 Claude 提供以下格式的指令即可快速生成详情页面:
```
请生成一个详情页面:
页面名称xxx
文件路径xxx
数据来源xxx API
标题:字段名(如 contestName
操作按钮:按钮名称 -> 处理函数
搜索条件:
- 字段1类型
- 字段2类型
表格列:
- 列名1数据字段
- 列名2数据字段
- ...
排序:字段名 + 排序方式(升序/降序)
```
## 配置参数说明
### 1. 基础配置
| 参数 | 说明 | 示例 |
|------|------|------|
| 页面名称 | 显示在标题旁 | 赛果发布详情 |
| 文件路径 | Vue 文件位置 | views/contests/results/Detail.vue |
| 数据来源 | API 模块 | resultsApi / worksApi |
| 标题字段 | 动态标题来源 | record.contestName |
| 返回路径 | 返回按钮跳转 | 上一页 / 指定路径 |
### 2. 操作按钮
| 属性 | 说明 |
|------|------|
| 名称 | 按钮显示文本 |
| 类型 | primary / default / danger |
| 处理函数 | 点击触发的方法 |
| 确认弹窗 | 是否需要二次确认 |
### 3. 搜索条件类型
| 类型 | 说明 | 示例 |
|------|------|------|
| input | 输入框 | 作品编号、账号 |
| select | 下拉选择 | 状态筛选 |
| date | 日期选择 | 提交日期 |
| dateRange | 日期范围 | 时间区间 |
### 4. 表格列渲染类型
| 类型 | 说明 | 示例 |
|------|------|------|
| index | 序号 | 自动计算 |
| text | 纯文本 | 直接显示字段值 |
| nested | 嵌套字段 | record.user?.nickname |
| array | 数组拼接 | teachers.map(t => t.name).join('、') |
| score | 分数格式 | 保留2位小数 |
| tag | 标签样式 | 状态标签 |
| org | 机构信息 | 学校 + 年级 + 班级 |
### 5. 排序配置
| 属性 | 说明 |
|------|------|
| 字段 | 排序依据的字段名 |
| 方式 | asc升序/ desc降序|
## 示例
### 赛果发布详情页
```
请生成一个详情页面:
页面名称:赛果发布详情
文件路径views/contests/results/Detail.vue
数据来源resultsApi.getResults
标题contestName赛事名称
操作按钮:发布赛果 -> handlePublish需确认
搜索条件:
- workNo 作品编号input
- accountNo 报名账号input
表格列:
- 序号index
- 作品编号workNo
- 评委评分finalScore分数格式
- 姓名registration.user.nickname
- 账号registration.user.username
- 机构信息registration.user机构格式
- 指导老师registration.teachers数组拼接
排序finalScore 降序
```
### 报名记录详情页
```
请生成一个详情页面:
页面名称:报名记录
文件路径views/contests/registrations/Records.vue
数据来源registrationsApi.getList
标题contestName赛事名称
操作按钮:无
搜索条件:
- accountNo 报名账号input
- registrationState 审核状态select
表格列:
- 序号index
- 报名账号accountNo
- 姓名user.nickname
- 机构信息user机构格式
- 指导老师teachers数组拼接
- 审核状态registrationState标签
- 报名时间registrationTime日期
- 操作(查看详情、审核)
排序registrationTime 降序
```
## 页面模板代码
```vue
<template>
<div class="detail-page">
<!-- 顶部导航 -->
<div class="page-header">
<div class="header-left">
<a-button type="text" @click="handleBack">
<template #icon><ArrowLeftOutlined /></template>
返回
</a-button>
<span class="page-title">{{ pageTitle }}</span>
</div>
<div class="header-right">
<a-button type="primary" @click="handleAction">
{{ actionButtonText }}
</a-button>
</div>
</div>
<!-- 搜索表单 -->
<a-form
:model="searchParams"
layout="inline"
class="search-form"
@finish="handleSearch"
>
<!-- 根据配置生成搜索项 -->
<a-form-item>
<a-button type="primary" html-type="submit">
<template #icon><SearchOutlined /></template>
搜索
</a-button>
<a-button style="margin-left: 8px" @click="handleReset">
<template #icon><ReloadOutlined /></template>
重置
</a-button>
</a-form-item>
</a-form>
<!-- 数据表格 -->
<a-table
:columns="columns"
:data-source="dataSource"
:loading="loading"
:pagination="pagination"
row-key="id"
@change="handleTableChange"
>
<template #bodyCell="{ column, record, index }">
<!-- 根据配置生成列渲染 -->
</template>
</a-table>
</div>
</template>
```
## 特殊字段渲染规范
### 机构信息org 类型)
```vue
<template v-else-if="column.key === 'org'">
<div>
<div>{{ record.user?.tenant?.name || "-" }}</div>
<div v-if="record.user?.student?.class" class="org-detail">
{{ record.user.student.class.grade?.name }}
{{ record.user.student.class.name }}
</div>
</div>
</template>
```
### 指导老师(数组拼接)
```vue
<template v-else-if="column.key === 'teachers'">
{{ formatTeachers(record.teachers || record.registration?.teachers) }}
</template>
// 格式化函数
const formatTeachers = (teachers: any[]) => {
if (!teachers || teachers.length === 0) return "-"
return teachers.map(t => t.user?.nickname || t.user?.username).join("、")
}
```
### 分数格式
```vue
<template v-else-if="column.key === 'score'">
<span v-if="record.finalScore !== null" class="score">
{{ Number(record.finalScore).toFixed(2) }}
</span>
<span v-else>-</span>
</template>
```
## 样式规范
```css
.detail-page {
padding: 0;
}
.page-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px;
background: #fff;
border-radius: 8px;
margin-bottom: 16px;
}
.header-left {
display: flex;
align-items: center;
gap: 8px;
}
.page-title {
font-size: 16px;
font-weight: 500;
}
.search-form {
margin-bottom: 16px;
padding: 16px;
background: #fff;
border-radius: 8px;
}
.org-detail {
font-size: 12px;
color: #666;
margin-top: 2px;
}
.score {
font-weight: bold;
color: #52c41a;
}
```
## 注意事项
1. **API 数据**:确保后端返回了所需的关联数据(如 user、teachers、tenant、student.class.grade
2. **排序字段**:需要后端支持对应字段的排序
3. **权限控制**:操作按钮需要配置权限检查
4. **空值处理**:所有字段都需要处理空值情况,显示 "-"
5. **嵌套数据**:使用可选链操作符 `?.` 避免空指针错误