diff --git a/IFLOW.md b/IFLOW.md new file mode 100644 index 0000000..ea88afd --- /dev/null +++ b/IFLOW.md @@ -0,0 +1,226 @@ +# IFLOW.md - 核心工作规则 + +## Global Protocols + +所有操作必须严格遵循以下系统约束: + +- **交互语言**:技术术语、工具与模型交互强制使用 **English**;用户输出强制使用 **中文**。 +- **最小改动**:仅对需求做针对性改动,严禁影响用户现有的其他功能。 +- **风格一致**:遵循项目现有的代码风格,使用项目已有的工具函数。 + +## Tool Priority + +在执行任何操作前,必须按照以下顺序选择工具,严禁跳级使用: + +**1. MCP 工具**:当 MCP 工具能够完成任务时,必须使用 MCP,禁止降级到内置工具或 Shell 命令。 + +**2. 内置工具**:仅当 MCP 工具**无法覆盖**该功能时,使用内置工具。 + +**3. Shell 命令**:Shell 命令是最后手段,同时遵循以下规则: + +- 只读类安全操作允许直接执行 + +| 类别 | 安全操作示例 | +| ---------------- | ------------------------------------------------- | +| Git 只读操作 | `git status`、`git log`、`git diff`、`git branch` | +| 包管理器只读操作 | `npm list`、`pnpm why`、`pip show` | +| 容器只读操作 | `docker ps`、`docker logs` | +| 环境检查 | `node -v`、`python -version`、`which xxx` | + +- 写入/删除/修改/安装等危险操作必须征得用户同意 + +| 类别 | 危险操作示例 | +| ------------ | ------------------------------------------------------------ | +| Git 写操作 | `commit`、`push`、`pull`、`merge`、`rebase`、`reset`、`checkout ` | +| 文件删除 | `rm`、`rmdir`、清空目录 | +| 批量文件修改 | `sed -i`(多文件)、批量重命名 | +| 包管理写操作 | `pnpm install/uninstall`、`pnpm add/remove`、`uv add/remove` | +| 容器写操作 | `docker rm`、`docker rmi`、`docker-compose down` | +| 系统级操作 | 修改环境变量、修改系统配置文件 | + +- 触发危险操作时告知用户 + + ``` + # 告知示例 + !!!即将执行危险操作!!!: + 命令:git push origin main + 影响:将本地 main 分支的提交推送到远程仓库 + + 是否继续?请回复"确认"或"取消" + ``` + +## Technology Stack + +如果是对已有项目二次开发/修改bug,则遵循项目已有技术栈。 + +如果是从0到1开发新的项目,尽可能使用下方给出的技术栈: + +### 后端 - Go(主力) + +| 配置项 | 要求 | +| -------- | -------------------------------------- | +| 语言版本 | Go 1.21+ | +| 开发框架 | Gin | +| ORM框架 | GORM | +| 代码规范 | Google Go 编程规范 | + +### 后端 - Java + +| 配置项 | 要求 | +| -------- | -------------------------------------- | +| 语言版本 | Java 17 | +| 开发框架 | Spring Boot 3.x + Spring Cloud Alibaba | +| ORM框架 | MyBatis Plus | +| 包管理器 | Maven | +| 代码规范 | 阿里巴巴Java开发手册(嵩山版) | + +### 后端 - Python(辅助/小工具) + +| 配置项 | 要求 | +| ---------- | ------------------------------------------------------------ | +| 语言版本 | Python 3.10+ | +| 开发框架 | FastAPI(轻量级API)/ Typer(CLI工具)/ Streamlit(数据可视化) | +| 包管理工具 | uv | +| 代码规范 | PEP 8 + Google Python Style Guide | +| 虚拟环境 | **强制启用**(uv venv) | + +### 后端 - 其他组件 + +| 组件 | 选型 | +| -------- | --------- | +| 数据库 | MySQL 8.x | +| 缓存 | Redis | + +### 前端 - TypeScript + Vue 3 + +| 配置项 | 要求 | +| -------- | ---------------------------- | +| 语言版本 | TypeScript 5.x | +| 开发框架 | Vue 3(Composition API) | +| UI组件库 | TailWind CSS | +| 包管理器 | pnpm | +| 构建工具 | Vite | +| 代码规范 | ESLint(严格模式)+ Prettier | + +### 桌面端 - Electron + +| 配置项 | 要求 | +| -------- | ------------------ | +| 基础框架 | Vue 3 + TypeScript | +| 打包工具 | electron-builder | + +## Workflow + +在开发过程中,严格按照以下阶段顺序执行任务。 + +**格式要求**: 每次回复必须在开头标注 `【当前阶段: [阶段名称]】` + +--- + +### Phase 0:上下文全量检索 + +**执行条件**:在生成任何建议或代码前。 + +**调用工具**:`mcp__auggie-mcp__codebase-retrieval` + +**检索策略**: + +- 禁止基于假设(Assumption)回答。 +- 使用自然语言(NL)构建语义查询(Where/What/How)。 +- **完整性检查**:必须获取相关类、函数、变量的完整定义与签名。若上下文不足,触发递归检索。 + +**需求对齐**:若检索后需求仍有模糊空间,**必须**向用户输出引导性问题列表,直至需求边界清晰(无遗漏、无冗余)。 + +--- + +### Phase 1: 产品需求分析 + +**角色**:产品经理 + +**方法**:通过`AskUserQuestion`工具进行多轮提问引导,直到需求完全量化。 + +**最小维度**: + +- 目标用户与使用场景。 +- 核心功能清单(按优先级 P0/P1/P2 排列)。 +- 业务规则与约束条件。 + +**输出**:`requirement.md`(需求规格书) + +--- + +### Phase 2: UI/UX 设计 + +**角色**:UI/UX 设计师 + +**方法**:基于`requirement.md`,通过多轮提问引导,定义交互与视觉规范。 + +**最小维度**: + +- 核心用户流程。 +- 页面结构与布局。 +- 组件状态定义。 + +**冲突检测**:与`requirement.md`中的约束进行一致性校验,如有冲突,必须提问澄清后再继续。 + +**输出**:`ui_ux_specifications.md`(UI/UX 规范) + +--- + +### Phase 3: 架构设计 + +**角色**:系统架构师 + +**方法**:基于`requirement.md`和`ui_ux_specifications.md`,通过多轮提问引导,设计技术方案。 + +**最小维度**: + +- 技术栈选型(遵循本文档`Technology Stack`章节)。 +- 系统分层、模块划分、目录结构。 +- API 契约定义。 + +**冲突检测**:与`requirement.md`中的约束进行一致性校验,如有冲突,必须提问澄清后再继续。 + +**输出**:`architecture_design_document.md`(架构设计文档) + +--- + +### Phase 4: 代码实现 + +**角色**:全栈开发工程师 + +**方法**: + +1. 根据 `requirement.md` 和 `architecture_design_document.md`,拆分开发任务 +2. 在 `task_list.md` 中记录任务清单,将**待开发/已开发/跳过**的任务通过不同的复选框进行标记 +3. 逐个任务开发,每个任务完成后更新状态 + +**输出**:`task_list.md`(任务清单,持续更新)、`deployment.md`(部署文档) + +--- + +### Phase 5: 代码审计 + +**执行条件**:每个任务模块开发完成后进行增量审计,全部完成后进行最终审计。 + +**角色**:代码审计工程师 + +**方法**:根据`task_list.md`,逐个对已完成代码进行 Code Review。 + +**审计范围**: + +- 功能完整性:是否覆盖`requirement.md`对应功能的全部需求 +- 代码质量:命名规范、无重复代码、适当抽象、注释完整 +- 安全检查:输入验证、SQL注入防护、XSS防护、敏感数据处理、权限控制 +- 性能检查:算法效率、数据库查询优化、资源释放 + +**问题分级与处理**: + +| 级别 | 定义 | 处理方式 | +| ---- | -------------------------------- | ------------------ | +| P0 | 安全漏洞、数据风险、核心功能缺失 | 阻断发布,立即修复 | +| P1 | 功能不完整、明显性能问题 | 当前迭代必须修复 | +| P2 | 代码规范、可维护性问题 | 可选 | +| P3 | 优化建议 | 可选 | + +**输出**:`audit_report.md`(审计报告)、`fix_changelog.md`(修复记录) \ No newline at end of file diff --git a/docs/dict-system.md b/docs/dict-system.md new file mode 100644 index 0000000..72b657d --- /dev/null +++ b/docs/dict-system.md @@ -0,0 +1,162 @@ +# 字典系统使用指南 + +## 概述 + +字典系统是为了解决项目中数据字典不统一、硬编码问题而设计的统一管理方案。系统支持静态字典(本地定义)和动态字典(API获取),并提供了便捷的访问接口。 + +## 系统架构 + +字典系统由以下几个部分组成: + +1. **工具类** (`src/utils/dict.ts`) - 提供静态字典数据和工具函数 +2. **Store** (`src/stores/dict.ts`) - 管理动态字典数据,与现有Pinia架构集成 +3. **API服务** (`src/service/api/dict.ts`) - 提供动态字典获取接口 +4. **组件示例** - 展示如何在组件中使用字典系统 + +## 使用方法 + +### 1. 在组件中使用字典 + +```typescript + +``` + +### 2. 在模板中使用 + +```vue + +``` + +### 3. 静态字典工具函数 + +```typescript +// 获取字典项列表 +const items = getDictItems('professionalCategory') + +// 获取字典标签 +const label = getDictLabel('professionalCategory', 'science') + +// 获取字典值 +const value = getDictValue('professionalCategory', '理工类') + +// 获取字典颜色 +const color = getDictColor('professionalCategory', 'science') + +// 获取字典项对象 +const item = getDictItem('professionalCategory', 'science') +``` + +### 4. 动态字典管理 + +```typescript +// 加载动态字典 +await dictStore.loadDynamicDicts() + +// 加载特定类型的动态字典 +await dictStore.loadDynamicDicts(['dynamic_type1', 'dynamic_type2']) + +// 手动设置动态字典 +dictStore.setDynamicDict('custom_type', [ + { label: '自定义项1', value: 'custom1' }, + { label: '自定义项2', value: 'custom2' } +]) + +// 清空动态字典 +dictStore.clearDynamicDicts() +``` + +## 字典数据结构 + +字典项接口定义: + +```typescript +interface DictItem { + label: string // 显示标签 + value: string | number // 实际值 + disabled?: boolean // 是否禁用 + color?: string // 颜色值 + order?: number // 排序 + [key: string]: any // 扩展属性 +} +``` + +## 静态字典类型 + +目前系统已内置以下静态字典: + +- `professionalCategory` - 专业类别 +- `educationalLevel` - 学历层次 +- `provinces` - 省份 +- `subjectList` - 科目列表 +- `gender` - 性别 +- `status` - 状态 +- `type` - 类型 + +## 动态字典API + +动态字典通过API获取,支持以下接口: + +- `GET /dict/list` - 获取字典列表 +- `GET /dict/type/{type}` - 获取指定类型的字典 + +## 在现有组件中集成 + +以ScoreForm.vue为例,展示了如何将现有硬编码的选项替换为字典系统: + +1. 导入字典Store +2. 使用computed属性获取字典项 +3. 在模板中使用字典数据 + +## 扩展字典类型 + +如需添加新的静态字典类型: + +1. 在 `src/utils/dict.ts` 中的 `staticDicts` 对象中添加新类型 +2. 确保遵循 `DictItem[]` 的数据结构 + +如需添加新的动态字典类型: + +1. 在后端API中提供相应的字典数据接口 +2. 在前端调用 `dictStore.loadDynamicDicts()` 时指定类型 + +## 最佳实践 + +1. **优先使用字典系统** - 避免在代码中硬编码选项数据 +2. **统一管理** - 所有字典数据通过字典系统统一管理 +3. **性能优化** - 字典数据通常在应用初始化时加载一次,后续直接使用 +4. **扩展性** - 支持静态和动态字典,满足不同业务场景需求 +5. **类型安全** - 提供完整的TypeScript类型定义 + +## 注意事项 + +1. 动态字典加载失败时,系统会继续使用静态字典数据 +2. 字典数据在应用生命周期内会被缓存,避免重复请求 +3. 在组件中使用字典前,确保字典数据已加载完成 +4. 动态字典会覆盖同名的静态字典数据 \ No newline at end of file diff --git a/src/auto-imports.d.ts b/src/auto-imports.d.ts index 4a86acd..86264e1 100644 --- a/src/auto-imports.d.ts +++ b/src/auto-imports.d.ts @@ -169,6 +169,7 @@ declare global { const useDeviceOrientation: typeof import('@vueuse/core')['useDeviceOrientation'] const useDevicePixelRatio: typeof import('@vueuse/core')['useDevicePixelRatio'] const useDevicesList: typeof import('@vueuse/core')['useDevicesList'] + const useDictStore: typeof import('./stores/dict')['useDictStore'] const useDisplayMedia: typeof import('@vueuse/core')['useDisplayMedia'] const useDocumentVisibility: typeof import('@vueuse/core')['useDocumentVisibility'] const useDraggable: typeof import('@vueuse/core')['useDraggable'] @@ -495,6 +496,7 @@ declare module 'vue' { readonly useDeviceOrientation: UnwrapRef readonly useDevicePixelRatio: UnwrapRef readonly useDevicesList: UnwrapRef + readonly useDictStore: UnwrapRef readonly useDisplayMedia: UnwrapRef readonly useDocumentVisibility: UnwrapRef readonly useDraggable: UnwrapRef diff --git a/src/components.d.ts b/src/components.d.ts index b8911dd..91be82a 100644 --- a/src/components.d.ts +++ b/src/components.d.ts @@ -10,11 +10,13 @@ declare module 'vue' { export interface GlobalComponents { BackToTop: typeof import('./components/BackToTop.vue')['default'] copy: typeof import('./components/ScoreForm copy.vue')['default'] + DictDemo: typeof import('./components/DictDemo.vue')['default'] FilterBar: typeof import('./components/FilterBar.vue')['default'] LoginForm: typeof import('./components/LoginForm.vue')['default'] README: typeof import('./components/README.md')['default'] RouterLink: typeof import('vue-router')['RouterLink'] RouterView: typeof import('vue-router')['RouterView'] + ScoreDictForm: typeof import('./components/ScoreDictForm.vue')['default'] ScoreForm: typeof import('./components/ScoreForm.vue')['default'] TheCounter: typeof import('./components/TheCounter.vue')['default'] TheFooter: typeof import('./components/TheFooter.vue')['default'] diff --git a/src/components/DictDemo.vue b/src/components/DictDemo.vue new file mode 100644 index 0000000..d8d16ff --- /dev/null +++ b/src/components/DictDemo.vue @@ -0,0 +1,192 @@ + + + + + \ No newline at end of file diff --git a/src/components/ScoreDictForm.vue b/src/components/ScoreDictForm.vue new file mode 100644 index 0000000..57c6488 --- /dev/null +++ b/src/components/ScoreDictForm.vue @@ -0,0 +1,254 @@ + + + \ No newline at end of file diff --git a/src/components/ScoreForm.vue b/src/components/ScoreForm.vue index b9d6ba2..9fe9ebc 100644 --- a/src/components/ScoreForm.vue +++ b/src/components/ScoreForm.vue @@ -1,10 +1,12 @@ \ No newline at end of file diff --git a/src/pages/volunteer.vue b/src/pages/volunteer.vue new file mode 100644 index 0000000..00988fb --- /dev/null +++ b/src/pages/volunteer.vue @@ -0,0 +1,316 @@ + + + \ No newline at end of file diff --git a/src/service/api/dict.ts b/src/service/api/dict.ts new file mode 100644 index 0000000..4beea4c --- /dev/null +++ b/src/service/api/dict.ts @@ -0,0 +1,52 @@ +/** + * 字典API服务 + * 用于获取动态字典数据 + */ + +import request from '~/service/request' + +// 字典项接口 +export interface DictItem { + label: string + value: string | number + disabled?: boolean + color?: string + order?: number + [key: string]: any +} + +// 字典响应数据接口 +export interface DictData { + type: string + items: DictItem[] +} + +/** + * 获取字典列表 + * @param types 字典类型列表,如果为空则获取所有字典 + * @returns 字典数据列表 + */ +export function getDictionaryList(types?: string[]): Promise { + const params: any = {} + if (types && types.length > 0) { + params.types = types.join(',') + } + + return request.get('/dict/list', { + params, + showLoading: false + }) +} + +/** + * 获取单个字典类型的数据 + * @param type 字典类型 + * @returns 字典项列表 + */ +export function getDictionaryByType(type: string): Promise { + return request.get(`/dict/type/${type}`, { + showLoading: false + }) +} + +// 如果需要其他字典相关API,可以在这里添加 \ No newline at end of file diff --git a/src/stores/dict.ts b/src/stores/dict.ts new file mode 100644 index 0000000..6b0a1aa --- /dev/null +++ b/src/stores/dict.ts @@ -0,0 +1,118 @@ +import { acceptHMRUpdate, defineStore } from 'pinia' +import { ref, computed } from 'vue' +import { DictItem, DictType, getDictItems, staticDicts } from '~/utils/dict' +import { getDictionaryList } from '~/service/api/dict' + +export const useDictStore = defineStore('dict', () => { + // 存储动态字典数据 + const dynamicDicts = ref({}) + + // 合并静态和动态字典 + const allDicts = computed(() => ({ + ...staticDicts, + ...dynamicDicts.value + })) + + /** + * 获取字典项 + * @param dictType 字典类型 + * @returns 字典项列表 + */ + function getDictItems(dictType: string): DictItem[] { + return allDicts.value[dictType] || [] + } + + /** + * 获取字典项标签 + * @param dictType 字典类型 + * @param value 字典值 + * @returns 字典项标签 + */ + function getDictLabel(dictType: string, value: string | number): string { + const dictItems = getDictItems(dictType) + const item = dictItems.find(item => item.value === value) + return item ? item.label : '' + } + + /** + * 获取字典项颜色 + * @param dictType 字典类型 + * @param value 字典值 + * @returns 字典项颜色 + */ + function getDictColor(dictType: string, value: string | number): string { + const dictItems = getDictItems(dictType) + const item = dictItems.find(item => item.value === value) + return item ? item.color || '' : '' + } + + /** + * 获取字典项对象 + * @param dictType 字典类型 + * @param value 字典值 + * @returns 字典项对象 + */ + function getDictItem(dictType: string, value: string | number): DictItem | undefined { + const dictItems = getDictItems(dictType) + return dictItems.find(item => item.value === value) + } + + /** + * 加载动态字典数据 + * @param dictTypes 字典类型列表,如果为空则加载所有动态字典 + */ + async function loadDynamicDicts(dictTypes?: string[]): Promise { + try { + // 调用API获取动态字典数据 + const response = await getDictionaryList(dictTypes) + + // 更新动态字典数据 + if (response && Array.isArray(response)) { + response.forEach((dictData: any) => { + if (dictData.type && Array.isArray(dictData.items)) { + dynamicDicts.value[dictData.type] = dictData.items + } + }) + } + } catch (error) { + console.error('加载动态字典失败:', error) + throw error + } + } + + /** + * 添加或更新动态字典 + * @param dictType 字典类型 + * @param items 字典项列表 + */ + function setDynamicDict(dictType: string, items: DictItem[]): void { + dynamicDicts.value[dictType] = items + } + + /** + * 清空动态字典 + */ + function clearDynamicDicts(): void { + dynamicDicts.value = {} + } + + return { + // 状态 + dynamicDicts, + allDicts, + + // 计算属性 + getDictItems, + getDictLabel, + getDictColor, + getDictItem, + + // 动作 + loadDynamicDicts, + setDynamicDict, + clearDynamicDicts, + } +}) + +if (import.meta.hot) + import.meta.hot.accept(acceptHMRUpdate(useDictStore as any, import.meta.hot)) \ No newline at end of file diff --git a/src/typed-router.d.ts b/src/typed-router.d.ts index c57e03f..eaaeb70 100644 --- a/src/typed-router.d.ts +++ b/src/typed-router.d.ts @@ -24,6 +24,7 @@ declare module 'vue-router/auto-routes' { '/agreement': RouteRecordInfo<'/agreement', '/agreement', Record, Record>, '/contact-us': RouteRecordInfo<'/contact-us', '/contact-us', Record, Record>, '/demo/pop-confirm': RouteRecordInfo<'/demo/pop-confirm', '/demo/pop-confirm', Record, Record>, + '/dict-demo': RouteRecordInfo<'/dict-demo', '/dict-demo', Record, Record>, '/hi/[name]': RouteRecordInfo<'/hi/[name]', '/hi/:name', { name: ParamValue }, { name: ParamValue }>, '/majors': RouteRecordInfo<'/majors', '/majors', Record, Record>, '/privacy-policy': RouteRecordInfo<'/privacy-policy', '/privacy-policy', Record, Record>, @@ -31,5 +32,6 @@ declare module 'vue-router/auto-routes' { '/school/[schoolCode]': RouteRecordInfo<'/school/[schoolCode]', '/school/:schoolCode', { schoolCode: ParamValue }, { schoolCode: ParamValue }>, '/simulate': RouteRecordInfo<'/simulate', '/simulate', Record, Record>, '/universities': RouteRecordInfo<'/universities', '/universities', Record, Record>, + '/volunteer': RouteRecordInfo<'/volunteer', '/volunteer', Record, Record>, } } diff --git a/src/utils/dict.ts b/src/utils/dict.ts new file mode 100644 index 0000000..2a4b875 --- /dev/null +++ b/src/utils/dict.ts @@ -0,0 +1,171 @@ +/** + * 字典工具类 - 用于管理应用中的所有字典数据 + * 包括静态字典(本地定义)和动态字典(API获取) + */ + +// 字典项接口 +export interface DictItem { + label: string + value: string | number + disabled?: boolean + color?: string + order?: number + [key: string]: any +} + +// 字典类型 +export interface DictType { + [key: string]: DictItem[] +} + +// 静态字典数据 +const staticDicts: DictType = { + // 专业类别 + professionalCategory: [ + { label: '理工类', value: 'science', color: '#108ee9' }, + { label: '文史类', value: 'liberal_arts', color: '#2db7f5' }, + { label: '艺术类', value: 'art', color: '#87d068' }, + { label: '体育类', value: 'sports', color: '#ff5500' }, + ], + + // 学历层次 + educationalLevel: [ + { label: '本科', value: 'undergraduate', color: '#108ee9' }, + { label: '专科', value: 'college', color: '#2db7f5' }, + { label: '研究生', value: 'graduate', color: '#87d068' }, + ], + + // 省份 + provinces: [ + { label: '北京市', value: 'beijing', order: 1 }, + { label: '上海市', value: 'shanghai', order: 2 }, + { label: '广东省', value: 'guangdong', order: 3 }, + { label: '江苏省', value: 'jiangsu', order: 4 }, + { label: '浙江省', value: 'zhejiang', order: 5 }, + { label: '山东省', value: 'shandong', order: 6 }, + { label: '河南省', value: 'henan', order: 7 }, + { label: '河北省', value: 'hebei', order: 8 }, + { label: '山西省', value: 'shanxi', order: 9 }, + { label: '辽宁省', value: 'liaoning', order: 10 }, + { label: '吉林省', value: 'jilin', order: 11 }, + { label: '黑龙江省', value: 'heilongjiang', order: 12 }, + { label: '安徽省', value: 'anhui', order: 13 }, + { label: '福建省', value: 'fujian', order: 14 }, + { label: '江西省', value: 'jiangxi', order: 15 }, + { label: '湖北省', value: 'hubei', order: 16 }, + { label: '湖南省', value: 'hunan', order: 17 }, + { label: '四川省', value: 'sichuan', order: 18 }, + { label: '贵州省', value: 'guizhou', order: 19 }, + { label: '云南省', value: 'yunnan', order: 20 }, + { label: '陕西省', value: 'shaanxi', order: 21 }, + { label: '甘肃省', value: 'gansu', order: 22 }, + { label: '青海省', value: 'qinghai', order: 23 }, + { label: '海南省', value: 'hainan', order: 24 }, + { label: '台湾省', value: 'taiwan', order: 25 }, + { label: '内蒙古自治区', value: 'neimenggu', order: 26 }, + { label: '广西壮族自治区', value: 'guangxi', order: 27 }, + { label: '西藏自治区', value: 'xizang', order: 28 }, + { label: '宁夏回族自治区', value: 'ningxia', order: 29 }, + { label: '新疆维吾尔自治区', value: 'xinjiang', order: 30 }, + { label: '香港特别行政区', value: 'hongkong', order: 31 }, + { label: '澳门特别行政区', value: 'aomen', order: 32 }, + ], + + // 科目列表 + subjectList: [ + { label: '语文', value: 'chinese', color: '#108ee9' }, + { label: '数学', value: 'mathematics', color: '#2db7f5' }, + { label: '英语', value: 'english', color: '#87d068' }, + { label: '物理', value: 'physics', color: '#ff5500' }, + { label: '化学', value: 'chemistry', color: '#f5222d' }, + { label: '生物', value: 'biology', color: '#fa8c16' }, + { label: '政治', value: 'politics', color: '#faad14' }, + { label: '历史', value: 'history', color: '#a0d911' }, + { label: '地理', value: 'geography', color: '#52c41a' }, + ], + + // 性别 + gender: [ + { label: '男', value: 'male' }, + { label: '女', value: 'female' }, + ], + + // 状态 + status: [ + { label: '启用', value: 'enabled', color: '#52c41a' }, + { label: '禁用', value: 'disabled', color: '#f5222d' }, + ], + + // 类型 + type: [ + { label: '系统', value: 'system', color: '#108ee9' }, + { label: '用户', value: 'user', color: '#2db7f5' }, + ] +} + +/** + * 获取字典项 + * @param dictType 字典类型 + * @returns 字典项列表 + */ +export function getDictItems(dictType: string): DictItem[] { + return staticDicts[dictType] || [] +} + +/** + * 获取字典项标签 + * @param dictType 字典类型 + * @param value 字典值 + * @returns 字典项标签 + */ +export function getDictLabel(dictType: string, value: string | number): string { + const dictItems = getDictItems(dictType) + const item = dictItems.find(item => item.value === value) + return item ? item.label : '' +} + +/** + * 获取字典项值 + * @param dictType 字典类型 + * @param label 字典标签 + * @returns 字典项值 + */ +export function getDictValue(dictType: string, label: string): string | number | undefined { + const dictItems = getDictItems(dictType) + const item = dictItems.find(item => item.label === label) + return item ? item.value : undefined +} + +/** + * 获取字典项颜色 + * @param dictType 字典类型 + * @param value 字典值 + * @returns 字典项颜色 + */ +export function getDictColor(dictType: string, value: string | number): string { + const dictItems = getDictItems(dictType) + const item = dictItems.find(item => item.value === value) + return item ? item.color || '' : '' +} + +/** + * 获取所有字典类型 + * @returns 字典类型列表 + */ +export function getAllDictTypes(): string[] { + return Object.keys(staticDicts) +} + +/** + * 获取字典项对象 + * @param dictType 字典类型 + * @param value 字典值 + * @returns 字典项对象 + */ +export function getDictItem(dictType: string, value: string | number): DictItem | undefined { + const dictItems = getDictItems(dictType) + return dictItems.find(item => item.value === value) +} + +// 导出静态字典 +export { staticDicts } \ No newline at end of file