library-picturebook-activity/.claude/skills/contest-detail-page.md
2026-01-15 16:35:00 +08:00

8.1 KiB
Raw Blame History

赛事详情页面生成规范

概述

本规范用于快速生成赛事管理系统中的详情页面,这类页面具有统一的结构:

  • 顶部导航栏(返回按钮 + 标题 + 操作按钮)
  • 搜索表单
  • 数据表格

页面结构

┌─────────────────────────────────────────────────┐
│  [← 返回]  页面标题                    [操作按钮] │
├─────────────────────────────────────────────────┤
│  搜索表单: [搜索条件...] [搜索] [重置]           │
├─────────────────────────────────────────────────┤
│  数据表格                                        │
│  ┌───┬──────┬──────┬──────┬──────┐              │
│  │序号│ 列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 降序

页面模板代码

<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 类型)

<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>

指导老师(数组拼接)

<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("、")
}

分数格式

<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>

样式规范

.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. 嵌套数据:使用可选链操作符 ?. 避免空指针错误