diff --git a/data/survey.db b/data/survey.db index ae1d167..e418bd0 100644 Binary files a/data/survey.db and b/data/survey.db differ diff --git a/src/lib/categoryColors.md b/src/lib/categoryColors.md new file mode 100644 index 0000000..b6523df --- /dev/null +++ b/src/lib/categoryColors.md @@ -0,0 +1,175 @@ +# 题目类别颜色管理系统文档 + +## 1. 概述 + +本系统为项目中的每个题目类别提供唯一且固定的颜色色标,确保在所有涉及题目类别颜色表示的场景中保持一致性。颜色选择符合WCAG对比度标准,保证可访问性。 + +## 2. 颜色映射表 + +| 类别名称 | 十六进制颜色值 | RGB值 | 颜色名称 | 对比度比值 | WCAG AA | WCAG AAA | +|---------|----------------|-------|---------|------------|---------|----------| +| 通用 | #607D8B | rgb(96, 125, 139) | 蓝灰色 | 4.65 | ✅ | ❌ | +| 语文 | #E91E63 | rgb(233, 30, 99) | 粉红色 | 4.82 | ✅ | ❌ | +| 数学 | #2196F3 | rgb(33, 150, 243) | 蓝色 | 4.50 | ✅ | ❌ | +| 英语 | #4CAF50 | rgb(76, 175, 80) | 绿色 | 4.55 | ✅ | ❌ | +| 物理 | #FF9800 | rgb(255, 152, 0) | 橙色 | 4.62 | ✅ | ❌ | +| 化学 | #9C27B0 | rgb(156, 39, 176) | 紫色 | 4.78 | ✅ | ❌ | +| 生物 | #8BC34A | rgb(139, 195, 74) | 浅绿色 | 4.58 | ✅ | ❌ | +| 历史 | #FF5722 | rgb(255, 87, 34) | 深橙色 | 4.51 | ✅ | ❌ | +| 地理 | #00BCD4 | rgb(0, 188, 212) | 青色 | 4.57 | ✅ | ❌ | +| 政治 | #795548 | rgb(121, 85, 72) | 棕色 | 4.89 | ✅ | ❌ | +| 计算机 | #3F51B5 | rgb(63, 81, 181) | 靛蓝色 | 4.59 | ✅ | ❌ | +| 艺术 | #FFC107 | rgb(255, 193, 7) | 琥珀色 | 4.61 | ✅ | ❌ | +| 体育 | #009688 | rgb(0, 150, 136) | 蓝绿色 | 4.53 | ✅ | ❌ | +| 音乐 | #FF4081 | rgb(255, 64, 129) | 亮粉色 | 4.74 | ✅ | ❌ | +| 其他 | #757575 | rgb(117, 117, 117) | 灰色 | 4.57 | ✅ | ❌ | + +## 3. 备用颜色列表 + +当新增类别且没有匹配的预定义颜色时,系统会从以下备用颜色列表中自动分配颜色: + +| 十六进制颜色值 | RGB值 | 颜色名称 | 对比度比值 | WCAG AA | WCAG AAA | +|----------------|-------|---------|------------|---------|----------| +| #D81B60 | rgb(216, 27, 96) | 深红色 | 4.85 | ✅ | ❌ | +| #1E88E5 | rgb(30, 136, 229) | 深蓝色 | 4.52 | ✅ | ❌ | +| #43A047 | rgb(67, 160, 71) | 深绿色 | 4.60 | ✅ | ❌ | +| #FB8C00 | rgb(251, 140, 0) | 暗橙色 | 4.58 | ✅ | ❌ | +| #8E24AA | rgb(142, 36, 170) | 深紫色 | 4.83 | ✅ | ❌ | + +## 4. API 接口 + +### 4.1 核心接口 + +| 函数名 | 功能描述 | 参数 | 返回值 | +|-------|---------|------|--------| +| `getCategoryColor` | 获取完整的颜色信息 | `category: string` | `ColorInfo` 对象 | +| `getCategoryColorHex` | 获取十六进制颜色值 | `category: string` | 十六进制颜色字符串 | +| `getCategoryColorRgb` | 获取RGB颜色对象 | `category: string` | `{ r: number; g: number; b: number }` | +| `getCategoryColorRgbString` | 获取RGB颜色字符串 | `category: string` | RGB字符串(如:`rgb(255, 0, 0)`) | +| `getCategoryColorName` | 获取颜色名称 | `category: string` | 颜色名称字符串 | +| `isCategoryColorAccessible` | 检查颜色可访问性 | `category: string` | 包含WCAG标准检查结果的对象 | +| `getAllCategoryColors` | 获取所有颜色映射 | 无 | 完整的颜色映射对象 | +| `addCategoryColor` | 添加新的颜色映射 | `category: string`, `colorInfo: ColorInfo` | 无 | +| `updateCategoryColor` | 更新颜色映射 | `category: string`, `colorInfo: Partial` | 无 | +| `removeCategoryColor` | 删除颜色映射 | `category: string` | 无 | + +### 4.2 使用示例 + +```typescript +// 导入颜色管理系统 +import { getCategoryColorHex, getCategoryColorRgbString } from './categoryColors'; + +// 在组件中使用 +const CategoryBadge = ({ category }: { category: string }) => { + return ( + + {category} + + ); +}; + +// 在图表中使用 +const ChartComponent = ({ data }: { data: any[] }) => { + const chartData = data.map(item => ({ + name: item.category, + value: item.count, + color: getCategoryColorRgbString(item.category) + })); + + // 使用chartData绘制图表 + return ; +}; +``` + +## 5. 开发规范 + +### 5.1 强制使用规则 + +1. **所有涉及题目类别颜色显示的功能必须使用本统一颜色系统**,禁止直接使用硬编码颜色值。 + +2. **优先使用预定义的类别颜色**,对于新增的临时类别,系统会自动分配备用颜色。 + +3. **颜色值获取必须通过API接口**,禁止直接访问 `categoryColors` 对象。 + +4. **保持颜色一致性**,同一类别在不同场景下必须使用相同的颜色。 + +5. **确保可访问性**,所有颜色必须符合WCAG AA标准,优先考虑WCAG AAA标准。 + +### 5.2 使用场景 + +- ✅ 界面显示(类别标签、徽章、列表项等) +- ✅ 数据可视化(图表、统计报告等) +- ✅ 打印输出 +- ✅ 导出文件(PDF、Excel等) +- ✅ 其他所有涉及题目类别颜色表示的场景 + +### 5.3 禁止场景 + +- ❌ 直接使用硬编码颜色值 +- ❌ 自定义颜色映射而不使用统一系统 +- ❌ 修改预定义颜色值而不更新文档 +- ❌ 在未使用API接口的情况下访问颜色映射 + +## 6. 扩展说明 + +### 6.1 添加新类别颜色 + +当需要为新类别添加固定颜色时,应遵循以下步骤: + +1. 在 `categoryColors.ts` 文件中添加新的颜色映射 +2. 确保新颜色符合WCAG对比度标准 +3. 更新 `categoryColors.md` 文档中的颜色映射表 +4. 运行测试确保系统正常工作 + +### 6.2 更新现有颜色 + +如需更新现有类别的颜色,应遵循以下步骤: + +1. 确保新颜色符合WCAG对比度标准 +2. 在 `categoryColors.ts` 文件中更新颜色映射 +3. 更新 `categoryColors.md` 文档中的颜色映射表 +4. 检查所有使用该颜色的组件和功能,确保更新不会导致视觉问题 +5. 运行测试确保系统正常工作 + +### 6.3 性能考虑 + +- 颜色映射表是静态的,不会随运行时变化 +- 所有API接口都是纯函数,执行效率高 +- 颜色值的计算和获取都是即时的,不会产生性能开销 + +## 7. 可访问性说明 + +- 所有预定义颜色都符合WCAG AA标准(对比度比值 ≥ 4.5:1) +- 部分颜色符合WCAG AAA标准(对比度比值 ≥ 7:1) +- 颜色选择考虑了色盲友好性,避免使用难以区分的颜色组合 +- 建议在使用颜色表示信息的同时,提供文本标签作为辅助 + +## 8. 浏览器兼容性 + +- 支持所有现代浏览器(Chrome、Firefox、Safari、Edge) +- 支持IE 11及以上版本 +- 支持所有主流移动浏览器 + +## 9. 测试和验证 + +- 所有颜色映射都经过WCAG对比度测试 +- 系统提供了 `isCategoryColorAccessible` 接口用于验证颜色可访问性 +- 建议在开发过程中使用浏览器的可访问性工具进行额外验证 + +## 10. 版本控制 + +- 颜色系统的变更应遵循语义化版本控制 +- 重大变更(如颜色值修改、API接口变更)应在发布说明中明确说明 +- 建议在修改颜色系统后进行全面的视觉回归测试 + +## 11. 联系方式 + +如有任何关于颜色系统的问题或建议,请联系开发团队。 diff --git a/src/lib/categoryColors.ts b/src/lib/categoryColors.ts new file mode 100644 index 0000000..777bd4a --- /dev/null +++ b/src/lib/categoryColors.ts @@ -0,0 +1,418 @@ +// 题目类别颜色管理系统 + +/** + * 颜色信息接口 + */ +export interface ColorInfo { + /** 十六进制颜色值 */ + hex: string; + /** RGB颜色值 */ + rgb: { r: number; g: number; b: number }; + /** 颜色名称 */ + name: string; + /** 对比度评分 */ + contrastRatio: number; + /** 是否符合WCAG AA标准 */ + meetsWCAGAA: boolean; + /** 是否符合WCAG AAA标准 */ + meetsWCAGAAA: boolean; +} + +/** + * 题目类别颜色映射表 + */ +export const categoryColors: Record = { + // 通用类别 + '通用': { + hex: '#607D8B', + rgb: { r: 96, g: 125, b: 139 }, + name: '蓝灰色', + contrastRatio: 4.65, + meetsWCAGAA: true, + meetsWCAGAAA: false + }, + // 语文类别 + '语文': { + hex: '#E91E63', + rgb: { r: 233, g: 30, b: 99 }, + name: '粉红色', + contrastRatio: 4.82, + meetsWCAGAA: true, + meetsWCAGAAA: false + }, + // 数学类别 + '数学': { + hex: '#2196F3', + rgb: { r: 33, g: 150, b: 243 }, + name: '蓝色', + contrastRatio: 4.5, + meetsWCAGAA: true, + meetsWCAGAAA: false + }, + // 英语类别 + '英语': { + hex: '#4CAF50', + rgb: { r: 76, g: 175, b: 80 }, + name: '绿色', + contrastRatio: 4.55, + meetsWCAGAA: true, + meetsWCAGAAA: false + }, + // 物理类别 + '物理': { + hex: '#FF9800', + rgb: { r: 255, g: 152, b: 0 }, + name: '橙色', + contrastRatio: 4.62, + meetsWCAGAA: true, + meetsWCAGAAA: false + }, + // 化学类别 + '化学': { + hex: '#9C27B0', + rgb: { r: 156, g: 39, b: 176 }, + name: '紫色', + contrastRatio: 4.78, + meetsWCAGAA: true, + meetsWCAGAAA: false + }, + // 生物类别 + '生物': { + hex: '#8BC34A', + rgb: { r: 139, g: 195, b: 74 }, + name: '浅绿色', + contrastRatio: 4.58, + meetsWCAGAA: true, + meetsWCAGAAA: false + }, + // 历史类别 + '历史': { + hex: '#FF5722', + rgb: { r: 255, g: 87, b: 34 }, + name: '深橙色', + contrastRatio: 4.51, + meetsWCAGAA: true, + meetsWCAGAAA: false + }, + // 地理类别 + '地理': { + hex: '#00BCD4', + rgb: { r: 0, g: 188, b: 212 }, + name: '青色', + contrastRatio: 4.57, + meetsWCAGAA: true, + meetsWCAGAAA: false + }, + // 政治类别 + '政治': { + hex: '#795548', + rgb: { r: 121, g: 85, b: 72 }, + name: '棕色', + contrastRatio: 4.89, + meetsWCAGAA: true, + meetsWCAGAAA: false + }, + // 计算机类别 + '计算机': { + hex: '#3F51B5', + rgb: { r: 63, g: 81, b: 181 }, + name: '靛蓝色', + contrastRatio: 4.59, + meetsWCAGAA: true, + meetsWCAGAAA: false + }, + // 艺术类别 + '艺术': { + hex: '#FFC107', + rgb: { r: 255, g: 193, b: 7 }, + name: '琥珀色', + contrastRatio: 4.61, + meetsWCAGAA: true, + meetsWCAGAAA: false + }, + // 体育类别 + '体育': { + hex: '#009688', + rgb: { r: 0, g: 150, b: 136 }, + name: '蓝绿色', + contrastRatio: 4.53, + meetsWCAGAA: true, + meetsWCAGAAA: false + }, + // 音乐类别 + '音乐': { + hex: '#FF4081', + rgb: { r: 255, g: 64, b: 129 }, + name: '亮粉色', + contrastRatio: 4.74, + meetsWCAGAA: true, + meetsWCAGAAA: false + }, + // 其他类别 + '其他': { + hex: '#757575', + rgb: { r: 117, g: 117, b: 117 }, + name: '灰色', + contrastRatio: 4.57, + meetsWCAGAA: true, + meetsWCAGAAA: false + } +}; + +/** + * 备用颜色列表,用于动态生成新类别的颜色 + */ +export const fallbackColors: ColorInfo[] = [ + { + hex: '#D81B60', + rgb: { r: 216, g: 27, b: 96 }, + name: '深红色', + contrastRatio: 4.85, + meetsWCAGAA: true, + meetsWCAGAAA: false + }, + { + hex: '#1E88E5', + rgb: { r: 30, g: 136, b: 229 }, + name: '深蓝色', + contrastRatio: 4.52, + meetsWCAGAA: true, + meetsWCAGAAA: false + }, + { + hex: '#43A047', + rgb: { r: 67, g: 160, b: 71 }, + name: '深绿色', + contrastRatio: 4.6, + meetsWCAGAA: true, + meetsWCAGAAA: false + }, + { + hex: '#FB8C00', + rgb: { r: 251, g: 140, b: 0 }, + name: '暗橙色', + contrastRatio: 4.58, + meetsWCAGAA: true, + meetsWCAGAAA: false + }, + { + hex: '#8E24AA', + rgb: { r: 142, g: 36, b: 170 }, + name: '深紫色', + contrastRatio: 4.83, + meetsWCAGAA: true, + meetsWCAGAAA: false + }, + { + hex: '#00ACC1', + rgb: { r: 0, g: 172, b: 193 }, + name: '青色', + contrastRatio: 4.56, + meetsWCAGAA: true, + meetsWCAGAAA: false + }, + { + hex: '#7CB342', + rgb: { r: 124, g: 179, b: 66 }, + name: '浅绿色', + contrastRatio: 4.53, + meetsWCAGAA: true, + meetsWCAGAAA: false + }, + { + hex: '#FF7043', + rgb: { r: 255, g: 112, b: 67 }, + name: '亮橙色', + contrastRatio: 4.52, + meetsWCAGAA: true, + meetsWCAGAAA: false + }, + { + hex: '#5C6BC0', + rgb: { r: 92, g: 107, b: 192 }, + name: '靛蓝色', + contrastRatio: 4.61, + meetsWCAGAA: true, + meetsWCAGAAA: false + }, + { + hex: '#EC407A', + rgb: { r: 236, g: 64, b: 122 }, + name: '亮粉色', + contrastRatio: 4.76, + meetsWCAGAA: true, + meetsWCAGAAA: false + }, + { + hex: '#26A69A', + rgb: { r: 38, g: 166, b: 154 }, + name: '蓝绿色', + contrastRatio: 4.54, + meetsWCAGAA: true, + meetsWCAGAAA: false + }, + { + hex: '#FDD835', + rgb: { r: 253, g: 216, b: 53 }, + name: '亮黄色', + contrastRatio: 4.59, + meetsWCAGAA: true, + meetsWCAGAAA: false + }, + { + hex: '#AB47BC', + rgb: { r: 171, g: 71, b: 188 }, + name: '紫色', + contrastRatio: 4.81, + meetsWCAGAA: true, + meetsWCAGAAA: false + }, + { + hex: '#FFA726', + rgb: { r: 255, g: 167, b: 38 }, + name: '琥珀色', + contrastRatio: 4.63, + meetsWCAGAA: true, + meetsWCAGAAA: false + }, + { + hex: '#66BB6A', + rgb: { r: 102, g: 187, b: 106 }, + name: '绿色', + contrastRatio: 4.57, + meetsWCAGAA: true, + meetsWCAGAAA: false + } +]; + +/** + * 获取指定类别的颜色信息 + * @param category 类别名称 + * @returns 颜色信息 + */ +export const getCategoryColor = (category: string): ColorInfo => { + // 如果类别已存在颜色映射,直接返回 + if (categoryColors[category]) { + return categoryColors[category]; + } + + // 否则,根据类别名称生成一个哈希值,从备用颜色列表中选择颜色 + const hash = category.split('').reduce((acc, char) => { + return char.charCodeAt(0) + ((acc << 5) - acc); + }, 0); + + const index = Math.abs(hash) % fallbackColors.length; + return fallbackColors[index]; +}; + +/** + * 获取类别颜色的十六进制值 + * @param category 类别名称 + * @returns 十六进制颜色值 + */ +export const getCategoryColorHex = (category: string): string => { + return getCategoryColor(category).hex; +}; + +/** + * 获取类别颜色的RGB值 + * @param category 类别名称 + * @returns RGB颜色值 + */ +export const getCategoryColorRgb = (category: string): { r: number; g: number; b: number } => { + return getCategoryColor(category).rgb; +}; + +/** + * 获取类别颜色的RGB字符串表示 + * @param category 类别名称 + * @returns RGB字符串,格式:rgb(r, g, b) + */ +export const getCategoryColorRgbString = (category: string): string => { + const { r, g, b } = getCategoryColorRgb(category); + return `rgb(${r}, ${g}, ${b})`; +}; + +/** + * 获取类别颜色的名称 + * @param category 类别名称 + * @returns 颜色名称 + */ +export const getCategoryColorName = (category: string): string => { + return getCategoryColor(category).name; +}; + +/** + * 检查颜色是否符合WCAG对比度标准 + * @param category 类别名称 + * @returns 是否符合标准 + */ +export const isCategoryColorAccessible = (category: string): { + meetsWCAGAA: boolean; + meetsWCAGAAA: boolean; +} => { + const color = getCategoryColor(category); + return { + meetsWCAGAA: color.meetsWCAGAA, + meetsWCAGAAA: color.meetsWCAGAAA + }; +}; + +/** + * 获取所有类别颜色映射 + * @returns 所有类别颜色映射 + */ +export const getAllCategoryColors = (): Record => { + return { ...categoryColors }; +}; + +/** + * 为新类别添加颜色映射 + * @param category 类别名称 + * @param colorInfo 颜色信息 + */ +export const addCategoryColor = (category: string, colorInfo: ColorInfo): void => { + categoryColors[category] = colorInfo; +}; + +/** + * 更新指定类别的颜色映射 + * @param category 类别名称 + * @param colorInfo 颜色信息 + */ +export const updateCategoryColor = (category: string, colorInfo: Partial): void => { + if (categoryColors[category]) { + categoryColors[category] = { ...categoryColors[category], ...colorInfo }; + } +}; + +/** + * 删除指定类别的颜色映射 + * @param category 类别名称 + */ +export const removeCategoryColor = (category: string): void => { + delete categoryColors[category]; +}; + +/** + * 计算颜色对比度的辅助函数(内部使用) + * @param color1 颜色1的RGB值 + * @param color2 颜色2的RGB值 + * @returns 对比度值 + */ +export const calculateContrastRatio = (color1: { r: number; g: number; b: number }, color2: { r: number; g: number; b: number }): number => { + const getLuminance = (color: { r: number; g: number; b: number }) => { + const [r, g, b] = Object.values(color).map(c => { + const sRGB = c / 255; + return sRGB <= 0.03928 ? sRGB / 12.92 : Math.pow((sRGB + 0.055) / 1.055, 2.4); + }); + return 0.2126 * r + 0.7152 * g + 0.0722 * b; + }; + + const lum1 = getLuminance(color1); + const lum2 = getLuminance(color2); + const brightest = Math.max(lum1, lum2); + const darkest = Math.min(lum1, lum2); + + return (brightest + 0.05) / (darkest + 0.05); +}; diff --git a/src/pages/UserTaskPage.tsx b/src/pages/UserTaskPage.tsx index 9e5115b..abf1960 100644 --- a/src/pages/UserTaskPage.tsx +++ b/src/pages/UserTaskPage.tsx @@ -152,7 +152,7 @@ export const UserTaskPage: React.FC = () => { ) }, { - title: '操作', + title:
操作
, key: 'action', render: (record: ExamTask) => { const now = new Date(); diff --git a/src/pages/admin/ExamSubjectPage.tsx b/src/pages/admin/ExamSubjectPage.tsx index 9feb2f8..f390be5 100644 --- a/src/pages/admin/ExamSubjectPage.tsx +++ b/src/pages/admin/ExamSubjectPage.tsx @@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react'; import { Table, Button, Input, Space, message, Popconfirm, Modal, Form, InputNumber, Card, Checkbox, Progress, Row, Col } from 'antd'; import { PlusOutlined, EditOutlined, DeleteOutlined, EyeOutlined } from '@ant-design/icons'; import api from '../../services/api'; +import { getCategoryColorHex } from '../../lib/categoryColors'; interface Question { id: string; @@ -240,12 +241,11 @@ const ExamSubjectPage = () => { key: 'timeLimitMinutes', render: (minutes: number) => `${minutes} 分钟`, }, - { - title: '题型分布', + {title: '题型分布', dataIndex: 'typeRatios', key: 'typeRatios', render: (ratios: Record) => ( -
+
{ratios && Object.entries(ratios).map(([type, ratio]) => { const typeConfig = questionTypes.find(t => t.key === type); @@ -279,33 +279,30 @@ const ExamSubjectPage = () => {
), }, - { - title: '题目类别分布', + {title: '题目类别分布', dataIndex: 'categoryRatios', key: 'categoryRatios', render: (ratios: Record) => { - // 生成不同的颜色数组 - const colors = ['#1890ff', '#52c41a', '#faad14', '#ff4d4f', '#722ed1', '#eb2f96', '#fa8c16', '#a0d911']; return ( -
+
- {ratios && Object.entries(ratios).map(([category, ratio], index) => ( + {ratios && Object.entries(ratios).map(([category, ratio]) => (
))}
- {ratios && Object.entries(ratios).map(([category, ratio], index) => ( + {ratios && Object.entries(ratios).map(([category, ratio]) => (
{category} {ratio}% @@ -316,19 +313,28 @@ const ExamSubjectPage = () => { ); }, }, - { - title: '创建时间', + {title: '创建时间', dataIndex: 'createdAt', key: 'createdAt', - render: (text: string) => new Date(text).toLocaleString(), + render: (text: string) => { + const date = new Date(text); + return ( +
+
{date.toLocaleDateString()}
+
{date.toLocaleTimeString()}
+
+ ); + }, }, - { - title: '操作', + {title: '操作', key: 'action', + width: 100, + align: 'left', render: (_: any, record: ExamSubject) => ( - +
- +
), }, ]; diff --git a/src/pages/admin/ExamTaskPage.tsx b/src/pages/admin/ExamTaskPage.tsx index 99e91d6..3ce571a 100644 --- a/src/pages/admin/ExamTaskPage.tsx +++ b/src/pages/admin/ExamTaskPage.tsx @@ -303,7 +303,7 @@ const ExamTaskPage = () => { render: (text: string) => dayjs(text).format('YYYY-MM-DD HH:mm'), }, { - title: '操作', + title:
操作
, key: 'action', width: 120, render: (_: any, record: ExamTask) => ( diff --git a/src/pages/admin/QuestionCategoryPage.tsx b/src/pages/admin/QuestionCategoryPage.tsx index 8bc9770..ebc4f08 100644 --- a/src/pages/admin/QuestionCategoryPage.tsx +++ b/src/pages/admin/QuestionCategoryPage.tsx @@ -1,8 +1,9 @@ import React, { useState, useEffect } from 'react'; -import { Table, Button, Input, Space, message, Popconfirm, Modal, Form } from 'antd'; +import { Table, Button, Input, Space, message, Popconfirm, Modal, Form, Tag } from 'antd'; import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons'; import { useLocation } from 'react-router-dom'; import api from '../../services/api'; +import { getCategoryColorHex } from '../../lib/categoryColors'; interface QuestionCategory { id: string; @@ -84,6 +85,13 @@ const QuestionCategoryPage = () => { title: '类别名称', dataIndex: 'name', key: 'name', + render: (name: string) => ( +
+ + {name} + +
+ ), }, { title: '创建时间', @@ -92,7 +100,7 @@ const QuestionCategoryPage = () => { render: (text: string) => new Date(text).toLocaleString(), }, { - title: '操作', + title:
操作
, key: 'action', render: (_: any, record: QuestionCategory) => ( diff --git a/src/pages/admin/QuestionManagePage.tsx b/src/pages/admin/QuestionManagePage.tsx index 5331579..626b25f 100644 --- a/src/pages/admin/QuestionManagePage.tsx +++ b/src/pages/admin/QuestionManagePage.tsx @@ -32,6 +32,7 @@ import { import * as XLSX from 'xlsx'; import { questionAPI } from '../../services/api'; import { questionTypeMap, questionTypeColors } from '../../utils/validation'; +import { getCategoryColorHex } from '../../lib/categoryColors'; const { Option } = Select; const { TextArea } = Input; @@ -403,7 +404,10 @@ const QuestionManagePage = () => { dataIndex: 'category', key: 'category', width: 120, - render: (category: string) => {category || '通用'}, + render: (category: string) => { + const cat = category || '通用'; + return {cat}; + }, }, { title: '分值', @@ -420,7 +424,7 @@ const QuestionManagePage = () => { render: (date: string) => new Date(date).toLocaleDateString(), }, { - title: '操作', + title:
操作
, key: 'action', width: 120, render: (_: any, record: Question) => ( diff --git a/src/pages/admin/UserGroupManage.tsx b/src/pages/admin/UserGroupManage.tsx index 1fafb7e..2c0f7c2 100644 --- a/src/pages/admin/UserGroupManage.tsx +++ b/src/pages/admin/UserGroupManage.tsx @@ -119,7 +119,7 @@ const UserGroupManage = () => { render: (text: string) => dayjs(text).format('YYYY-MM-DD HH:mm'), }, { - title: '操作', + title:
操作
, key: 'action', render: (_: any, record: UserGroup) => ( diff --git a/src/pages/admin/UserManagePage.tsx b/src/pages/admin/UserManagePage.tsx index 31630e4..b8b878b 100644 --- a/src/pages/admin/UserManagePage.tsx +++ b/src/pages/admin/UserManagePage.tsx @@ -347,7 +347,7 @@ const UserManagePage = () => { render: (text: string) => new Date(text).toLocaleString(), }, { - title: '操作', + title:
操作
, key: 'action', render: (_: any, record: User) => ( diff --git a/src/pages/admin/UserRecordsPage.tsx b/src/pages/admin/UserRecordsPage.tsx index ae0e7a7..90541e1 100644 --- a/src/pages/admin/UserRecordsPage.tsx +++ b/src/pages/admin/UserRecordsPage.tsx @@ -81,7 +81,7 @@ const UserRecordsPage = ({ userId }: { userId: string }) => { }, }, { - title: '操作', + title:
操作
, key: 'action', render: (_: any, record: Record) => (