From 5d211faee1b373d9ad832e18b36a5a997f51b099 Mon Sep 17 00:00:00 2001 From: wangys <3401275564@qq.com> Date: Sat, 25 Oct 2025 17:45:47 +0800 Subject: [PATCH] =?UTF-8?q?web-=E6=A8=A1=E5=9D=97=E3=80=81=E6=9D=83?= =?UTF-8?q?=E9=99=90=E3=80=81=E6=88=90=E5=B0=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../img/achievement}/v1-icon.svg | 0 .../imgs => public/img/achievement}/v1.svg | 0 .../img/achievement}/v2-icon.svg | 0 .../imgs => public/img/achievement}/v2.svg | 0 .../img/achievement}/v3-icon.svg | 0 .../imgs => public/img/achievement}/v3.svg | 0 .../img/achievement}/v4-icon.svg | 0 .../imgs => public/img/achievement}/v4.svg | 0 .../public/img/achievement/v5-icon.svg | 414 ++++++ .../public/img/achievement/v6-icon.svg | 414 ++++++ .../src/apis/achievement/achievement.ts | 233 ++++ schoolNewsWeb/src/apis/achievement/index.ts | 1 + schoolNewsWeb/src/apis/index.ts | 3 - schoolNewsWeb/src/apis/system/index.ts | 1 + schoolNewsWeb/src/apis/system/module.ts | 197 +++ .../src/apis/usercenter/achievement.ts | 46 - schoolNewsWeb/src/apis/usercenter/index.ts | 1 - schoolNewsWeb/src/config/index.ts | 2 +- .../src/types/achievement/achievement.ts | 114 ++ schoolNewsWeb/src/types/achievement/index.ts | 1 + .../src/types/enums/achievement-enums.ts | 186 +++ schoolNewsWeb/src/types/enums/index.ts | 87 ++ schoolNewsWeb/src/types/index.ts | 6 + schoolNewsWeb/src/types/module/index.ts | 162 +++ schoolNewsWeb/src/types/permission/index.ts | 6 +- schoolNewsWeb/src/types/usercenter/index.ts | 32 - .../achievement/AchievementManagementView.vue | 618 +++++++++ .../views/admin/manage/achievement/index.ts | 2 + .../admin/manage/system/ModuleManageView.vue | 0 .../system/ModulePermissionManageView.vue | 1159 +++++++++++++++++ .../manage/system/PermissionManageView.vue | 721 ---------- .../views/user-center/MyAchievementsView.vue | 494 ++++++- 32 files changed, 4024 insertions(+), 876 deletions(-) rename schoolNewsWeb/{src/assets/imgs => public/img/achievement}/v1-icon.svg (100%) rename schoolNewsWeb/{src/assets/imgs => public/img/achievement}/v1.svg (100%) rename schoolNewsWeb/{src/assets/imgs => public/img/achievement}/v2-icon.svg (100%) rename schoolNewsWeb/{src/assets/imgs => public/img/achievement}/v2.svg (100%) rename schoolNewsWeb/{src/assets/imgs => public/img/achievement}/v3-icon.svg (100%) rename schoolNewsWeb/{src/assets/imgs => public/img/achievement}/v3.svg (100%) rename schoolNewsWeb/{src/assets/imgs => public/img/achievement}/v4-icon.svg (100%) rename schoolNewsWeb/{src/assets/imgs => public/img/achievement}/v4.svg (100%) create mode 100644 schoolNewsWeb/public/img/achievement/v5-icon.svg create mode 100644 schoolNewsWeb/public/img/achievement/v6-icon.svg create mode 100644 schoolNewsWeb/src/apis/achievement/achievement.ts create mode 100644 schoolNewsWeb/src/apis/achievement/index.ts create mode 100644 schoolNewsWeb/src/apis/system/module.ts delete mode 100644 schoolNewsWeb/src/apis/usercenter/achievement.ts create mode 100644 schoolNewsWeb/src/types/achievement/achievement.ts create mode 100644 schoolNewsWeb/src/types/achievement/index.ts create mode 100644 schoolNewsWeb/src/types/enums/achievement-enums.ts create mode 100644 schoolNewsWeb/src/types/module/index.ts create mode 100644 schoolNewsWeb/src/views/admin/manage/achievement/AchievementManagementView.vue create mode 100644 schoolNewsWeb/src/views/admin/manage/achievement/index.ts delete mode 100644 schoolNewsWeb/src/views/admin/manage/system/ModuleManageView.vue create mode 100644 schoolNewsWeb/src/views/admin/manage/system/ModulePermissionManageView.vue delete mode 100644 schoolNewsWeb/src/views/admin/manage/system/PermissionManageView.vue diff --git a/schoolNewsWeb/src/assets/imgs/v1-icon.svg b/schoolNewsWeb/public/img/achievement/v1-icon.svg similarity index 100% rename from schoolNewsWeb/src/assets/imgs/v1-icon.svg rename to schoolNewsWeb/public/img/achievement/v1-icon.svg diff --git a/schoolNewsWeb/src/assets/imgs/v1.svg b/schoolNewsWeb/public/img/achievement/v1.svg similarity index 100% rename from schoolNewsWeb/src/assets/imgs/v1.svg rename to schoolNewsWeb/public/img/achievement/v1.svg diff --git a/schoolNewsWeb/src/assets/imgs/v2-icon.svg b/schoolNewsWeb/public/img/achievement/v2-icon.svg similarity index 100% rename from schoolNewsWeb/src/assets/imgs/v2-icon.svg rename to schoolNewsWeb/public/img/achievement/v2-icon.svg diff --git a/schoolNewsWeb/src/assets/imgs/v2.svg b/schoolNewsWeb/public/img/achievement/v2.svg similarity index 100% rename from schoolNewsWeb/src/assets/imgs/v2.svg rename to schoolNewsWeb/public/img/achievement/v2.svg diff --git a/schoolNewsWeb/src/assets/imgs/v3-icon.svg b/schoolNewsWeb/public/img/achievement/v3-icon.svg similarity index 100% rename from schoolNewsWeb/src/assets/imgs/v3-icon.svg rename to schoolNewsWeb/public/img/achievement/v3-icon.svg diff --git a/schoolNewsWeb/src/assets/imgs/v3.svg b/schoolNewsWeb/public/img/achievement/v3.svg similarity index 100% rename from schoolNewsWeb/src/assets/imgs/v3.svg rename to schoolNewsWeb/public/img/achievement/v3.svg diff --git a/schoolNewsWeb/src/assets/imgs/v4-icon.svg b/schoolNewsWeb/public/img/achievement/v4-icon.svg similarity index 100% rename from schoolNewsWeb/src/assets/imgs/v4-icon.svg rename to schoolNewsWeb/public/img/achievement/v4-icon.svg diff --git a/schoolNewsWeb/src/assets/imgs/v4.svg b/schoolNewsWeb/public/img/achievement/v4.svg similarity index 100% rename from schoolNewsWeb/src/assets/imgs/v4.svg rename to schoolNewsWeb/public/img/achievement/v4.svg diff --git a/schoolNewsWeb/public/img/achievement/v5-icon.svg b/schoolNewsWeb/public/img/achievement/v5-icon.svg new file mode 100644 index 0000000..74f892c --- /dev/null +++ b/schoolNewsWeb/public/img/achievement/v5-icon.svg @@ -0,0 +1,414 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/schoolNewsWeb/public/img/achievement/v6-icon.svg b/schoolNewsWeb/public/img/achievement/v6-icon.svg new file mode 100644 index 0000000..265a582 --- /dev/null +++ b/schoolNewsWeb/public/img/achievement/v6-icon.svg @@ -0,0 +1,414 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/schoolNewsWeb/src/apis/achievement/achievement.ts b/schoolNewsWeb/src/apis/achievement/achievement.ts new file mode 100644 index 0000000..37c83d0 --- /dev/null +++ b/schoolNewsWeb/src/apis/achievement/achievement.ts @@ -0,0 +1,233 @@ +/** + * @description 成就相关API + * @author yslg + * @since 2025-10-24 + */ + +import { api } from '@/apis/index'; +import type { Achievement, UserAchievement, UserAchievementProgress, AchievementVO, AchievementEvent, ResultDomain, PageParam } from '@/types'; + +/** + * 成就API服务 + */ +export const achievementApi = { + // ==================== 成就定义管理(管理员)==================== + + /** + * 创建成就 + * @param achievement 成就信息 + * @returns Promise> + */ + async createAchievement(achievement: Achievement): Promise> { + const response = await api.post('/achievements/achievement', achievement); + return response.data; + }, + + /** + * 更新成就 + * @param achievement 成就信息 + * @returns Promise> + */ + async updateAchievement(achievement: Achievement): Promise> { + const response = await api.put('/achievements/achievement', achievement); + return response.data; + }, + + /** + * 删除成就 + * @param achievement 成就信息(包含achievementID) + * @returns Promise> + */ + async deleteAchievement(achievement: Achievement): Promise> { + const response = await api.delete('/achievements/achievement', achievement); + return response.data; + }, + + /** + * 获取所有成就列表 + * @param filter 过滤条件(type: 成就类型, level: 成就等级) + * @returns Promise> + */ + async getAllAchievements(filter?: Partial): Promise> { + const response = await api.post('/achievements/list', filter || {}); + return response.data; + }, + + /** + * 分页查询成就 + * @param filter 过滤条件 + * @param pageParam 分页参数 + * @returns Promise> + */ + async getAchievementPage(filter?: Partial, pageParam?: PageParam): Promise> { + const response = await api.post('/achievements/page', { filter, pageParam }); + return response.data; + }, + + /** + * 获取成就详情 + * @param achievementID 成就ID + * @returns Promise> + */ + async getAchievementDetail(achievementID: string): Promise> { + const response = await api.get(`/achievements/detail/${achievementID}`); + return response.data; + }, + + // ==================== 用户成就查询 ==================== + + /** + * 获取用户已获得的成就 + * @param userID 用户ID + * @param type 成就类型(可选) + * @returns Promise> + */ + async getUserAchievements(userID: string, type?: number): Promise> { + const params: Record = {}; + if (type !== undefined) { + params.type = type; + } + const response = await api.get(`/achievements/user/${userID}`, params); + return response.data; + }, + + /** + * 获取当前用户的成就列表(含进度信息) + * 返回所有成就,包括: + * - 已获得的成就:显示获得时间 + * - 未获得的成就:显示当前进度 + * @param type 成就类型(可选) + * @returns Promise> + */ + async getMyAchievements(type?: number): Promise> { + const params: Record = {}; + if (type !== undefined) { + params.type = type; + } + const response = await api.get('/achievements/my', params); + return response.data; + }, + + /** + * 检查用户是否已获得成就 + * @param userID 用户ID + * @param achievementID 成就ID + * @returns Promise> + */ + async hasAchievement(userID: string, achievementID: string): Promise> { + const response = await api.get(`/achievements/check/${userID}/${achievementID}`); + return response.data; + }, + + // ==================== 成就授予(管理员)==================== + + /** + * 手动授予用户成就 + * @param userID 用户ID + * @param achievementID 成就ID + * @returns Promise> + */ + async grantAchievement(userID: string, achievementID: string): Promise> { + const response = await api.post('/achievements/grant', null, { + params: { userID, achievementID } + }); + return response.data; + }, + + /** + * 撤销用户成就 + * @param userID 用户ID + * @param achievementID 成就ID + * @returns Promise> + */ + async revokeAchievement(userID: string, achievementID: string): Promise> { + const response = await api.delete('/achievements/revoke', null, { + params: { userID, achievementID } + }); + return response.data; + }, + + // ==================== 成就进度查询 ==================== + + /** + * 获取用户成就进度 + * @param userID 用户ID + * @param achievementID 成就ID(可选,为空则获取所有进度) + * @returns Promise> + */ + async getUserAchievementProgress(userID: string, achievementID?: string): Promise> { + const params: Record = {}; + if (achievementID) { + params.achievementID = achievementID; + } + const response = await api.get(`/achievements/progress/${userID}`, params); + return response.data; + }, + + // ==================== 成就检测 ==================== + + /** + * 处理成就事件(内部接口,由其他服务调用) + * @param event 成就事件 + * @returns Promise> + */ + async processAchievementEvent(event: AchievementEvent): Promise> { + const response = await api.post('/achievements/event/process', event); + return response.data; + }, + + /** + * 检查用户是否满足成就条件 + * @param userID 用户ID + * @param achievementID 成就ID + * @returns Promise> + */ + async checkAchievementCondition(userID: string, achievementID: string): Promise> { + const response = await api.get(`/achievements/condition/check/${userID}/${achievementID}`); + return response.data; + }, + + /** + * 批量检查用户可获得的成就 + * @param userID 用户ID + * @returns Promise> + */ + async checkAvailableAchievements(userID: string): Promise> { + const response = await api.get(`/achievements/available/${userID}`); + return response.data; + }, + + // ==================== 成就统计 ==================== + + /** + * 获取用户成就统计 + * @param userID 用户ID + * @returns Promise>> + */ + async getUserAchievementStatistics(userID: string): Promise>> { + const response = await api.get>(`/achievements/statistics/${userID}`); + return response.data; + }, + + /** + * 获取成就排行榜 + * @param limit 排行榜条数(默认10条) + * @returns Promise>> + */ + async getAchievementRanking(limit = 10): Promise>> { + const response = await api.get>('/achievements/ranking', { limit }); + return response.data; + }, + + /** + * 获取最近获得成就的用户 + * @param pageParam 分页参数 + * @param filter 过滤条件 + * @param limit 查询条数(默认10条) + * @returns Promise> + */ + async getRecentAchievers(pageParam: PageParam, filter?:Achievement ): Promise> { + const response = await api.post(`/achievements/recent`, {pageParam, filter }); + return response.data; + } +}; diff --git a/schoolNewsWeb/src/apis/achievement/index.ts b/schoolNewsWeb/src/apis/achievement/index.ts new file mode 100644 index 0000000..3e98de6 --- /dev/null +++ b/schoolNewsWeb/src/apis/achievement/index.ts @@ -0,0 +1 @@ +export * from './achievement'; \ No newline at end of file diff --git a/schoolNewsWeb/src/apis/index.ts b/schoolNewsWeb/src/apis/index.ts index ddc750c..b2acf9d 100644 --- a/schoolNewsWeb/src/apis/index.ts +++ b/schoolNewsWeb/src/apis/index.ts @@ -178,9 +178,6 @@ request.interceptors.response.use( } ); -/** - * API封装 - */ /** * API封装 */ diff --git a/schoolNewsWeb/src/apis/system/index.ts b/schoolNewsWeb/src/apis/system/index.ts index 7f1a884..3dadd75 100644 --- a/schoolNewsWeb/src/apis/system/index.ts +++ b/schoolNewsWeb/src/apis/system/index.ts @@ -12,4 +12,5 @@ export { menuApi } from './menu'; export { permissionApi } from './permission'; export { authApi } from './auth'; export { fileApi } from './file'; +export { moduleApi } from './module'; diff --git a/schoolNewsWeb/src/apis/system/module.ts b/schoolNewsWeb/src/apis/system/module.ts new file mode 100644 index 0000000..4a5cf85 --- /dev/null +++ b/schoolNewsWeb/src/apis/system/module.ts @@ -0,0 +1,197 @@ +/** + * @description 系统模块相关API + * @author yslg + * @since 2025-10-25 + */ + +import { api } from '@/apis/index'; +import type { SysModule, ResultDomain, PageParam, SysPermission } from '@/types'; + +/** + * 系统模块API服务 + */ +export const moduleApi = { + baseUrl: '/system/modules', + /** + * 查询模块列表 + * @param filter 过滤条件 + * @returns Promise> + */ + async getModuleList(filter?: Partial): Promise> { + const response = await api.post(`${this.baseUrl}/list`, filter); + return response.data; + }, + + /** + * 根据模块ID查询模块信息 + * @param moduleID 模块ID + * @returns Promise> + */ + async getModuleById(moduleID: string): Promise> { + const response = await api.get(`${this.baseUrl}/${moduleID}`); + return response.data; + }, + + /** + * 根据模块代码查询模块信息 + * @param code 模块代码 + * @returns Promise> + */ + async getModuleByCode(code: string): Promise> { + const response = await api.get(`${this.baseUrl}/code/${code}`); + return response.data; + }, + + /** + * 查询启用的模块列表 + * @returns Promise> + */ + async getActiveModules(): Promise> { + const response = await api.get(`${this.baseUrl}/active`); + return response.data; + }, + + /** + * 创建模块 + * @param module 模块信息 + * @returns Promise> + */ + async createModule(module: SysModule): Promise> { + const response = await api.post(`${this.baseUrl}/module`, module); + return response.data; + }, + + /** + * 更新模块 + * @param module 模块信息 + * @returns Promise> + */ + async updateModule(module: SysModule): Promise> { + const response = await api.put(`${this.baseUrl}/module`, module); + return response.data; + }, + + /** + * 删除模块 + * @param moduleID 模块ID + * @returns Promise> + */ + async deleteModule(moduleID: string): Promise> { + const response = await api.delete(`${this.baseUrl}/module`, { moduleID }); + return response.data; + }, + + /** + * 批量删除模块 + * @param moduleIDs 模块ID列表 + * @returns Promise> + */ + async batchDeleteModules(moduleIDs: string[]): Promise> { + const response = await api.delete(`${this.baseUrl}/batch`, { moduleIDs }); + return response.data; + }, + + /** + * 更新模块状态 + * @param moduleID 模块ID + * @param status 状态(0禁用 1启用) + * @returns Promise> + */ + async updateModuleStatus(moduleID: string, status: number): Promise> { + const response = await api.put(`${this.baseUrl}/${moduleID}/status/${status}`); + return response.data; + }, + + /** + * 更新模块排序 + * @param moduleID 模块ID + * @param orderNum 排序号 + * @returns Promise> + */ + async updateModuleOrder(moduleID: string, orderNum: number): Promise> { + const response = await api.put(`${this.baseUrl}/${moduleID}/order/${orderNum}`); + return response.data; + }, + + /** + * 分页查询模块列表 + * @param filter 过滤条件 + * @param pageParam 分页参数 + * @returns Promise> + */ + async getModuleListPage(filter?: Partial, pageParam?: PageParam): Promise> { + const response = await api.post(`${this.baseUrl}/page`, { + filter, + pageParam: {pageNumber: pageParam?.page || 1, pageSize: pageParam?.size || 10} + }); + return response.data; + }, + + /** + * 统计模块数量 + * @param filter 过滤条件 + * @returns Promise> + */ + async countModules(filter?: Partial): Promise> { + const response = await api.post(`${this.baseUrl}/count`, filter); + return response.data; + }, + + /** + * 检查模块代码是否存在 + * @param code 模块代码 + * @param excludeID 排除的模块ID + * @returns Promise> + */ + async checkModuleCodeExists(code: string, excludeID?: string): Promise> { + const response = await api.get(`${this.baseUrl}/check-code`, { + code, + excludeID + }); + return response.data; + }, + + /** + * 在模块中创建权限 + * @param moduleID 模块ID + * @param permission 权限信息 + * @returns Promise> + */ + async createPermissionInModule(moduleID: string, permission: SysPermission): Promise> { + const response = await api.post(`${this.baseUrl}/${moduleID}/permissions`, permission); + return response.data; + }, + + /** + * 更新模块中的权限 + * @param moduleID 模块ID + * @param permission 权限信息 + * @returns Promise> + */ + async updatePermissionInModule(moduleID: string, permission: SysPermission): Promise> { + const response = await api.put(`${this.baseUrl}/${moduleID}/permissions`, permission); + return response.data; + }, + + /** + * 删除模块中的权限 + * @param moduleID 模块ID + * @param permissionID 权限ID + * @returns Promise> + */ + async deletePermissionInModule(moduleID: string, permissionID: string): Promise> { + const response = await api.delete(`${this.baseUrl}/${moduleID}/permissions/${permissionID}`); + return response.data; + }, + + /** + * 获取模块的权限列表 + * @param moduleID 模块ID + * @returns Promise> + */ + async getModulePermissions(moduleID: string): Promise> { + const response = await api.get(`${this.baseUrl}/${moduleID}/permissions`); + return response.data; + } +}; + diff --git a/schoolNewsWeb/src/apis/usercenter/achievement.ts b/schoolNewsWeb/src/apis/usercenter/achievement.ts deleted file mode 100644 index 5224072..0000000 --- a/schoolNewsWeb/src/apis/usercenter/achievement.ts +++ /dev/null @@ -1,46 +0,0 @@ -/** - * @description 用户成就相关API - * @author yslg - * @since 2025-10-15 - */ - -import { api } from '@/apis/index'; -import type { UserAchievement, Achievement, ResultDomain } from '@/types'; - -/** - * 用户成就API服务 - */ -export const userAchievementApi = { - /** - * 获取用户成就列表 - * @param userID 用户ID - * @returns Promise> - */ - async getUserAchievements(userID: string): Promise> { - const response = await api.get('/usercenter/achievement/user-list', { userID }); - return response.data; - }, - - /** - * 获取所有成就列表 - * @returns Promise> - */ - async getAllAchievements(): Promise> { - const response = await api.get('/usercenter/achievement/list'); - return response.data; - }, - - /** - * 检查用户成就进度 - * @param userID 用户ID - * @param achievementID 成就ID - * @returns Promise> - */ - async checkAchievementProgress(userID: string, achievementID: string): Promise> { - const response = await api.get<{ progress: number; isCompleted: boolean }>('/usercenter/achievement/progress', { - userID, - achievementID - }); - return response.data; - } -}; diff --git a/schoolNewsWeb/src/apis/usercenter/index.ts b/schoolNewsWeb/src/apis/usercenter/index.ts index 98dbe43..7d79c27 100644 --- a/schoolNewsWeb/src/apis/usercenter/index.ts +++ b/schoolNewsWeb/src/apis/usercenter/index.ts @@ -8,5 +8,4 @@ export { userCollectionApi } from './collection'; export { userBrowseRecordApi } from './browse-record'; export { userPointsApi } from './points'; -export { userAchievementApi } from './achievement'; export { userProfileApi } from './profile'; diff --git a/schoolNewsWeb/src/config/index.ts b/schoolNewsWeb/src/config/index.ts index 5faf353..9127809 100644 --- a/schoolNewsWeb/src/config/index.ts +++ b/schoolNewsWeb/src/config/index.ts @@ -51,6 +51,6 @@ export const APP_CONFIG = { refreshThreshold: 5 * 60 * 1000 // 提前5分钟刷新 } }; - +export const PUBLIC_IMG_PATH = '/schoolNewsWeb/img'; export default APP_CONFIG; diff --git a/schoolNewsWeb/src/types/achievement/achievement.ts b/schoolNewsWeb/src/types/achievement/achievement.ts new file mode 100644 index 0000000..87a89db --- /dev/null +++ b/schoolNewsWeb/src/types/achievement/achievement.ts @@ -0,0 +1,114 @@ + +import { BaseDTO } from '../base'; +import { AchievementEventType } from '../enums'; + +/** + * 成就实体 + */ +export interface Achievement extends BaseDTO { + /** 成就唯一标识 */ + achievementID?: string; + /** 成就名称 */ + name?: string; + /** 成就描述 */ + description?: string; + /** 成就图标 */ + icon?: string; + /** 成就类型(1勋章 2等级) */ + type?: number; + /** 成就等级 */ + level?: number; + /** 获取条件类型(1学习时长 2资源数量 3课程数量 4连续学习天数) */ + conditionType?: number; + /** 条件值 */ + conditionValue?: number; + /** 获得积分 */ + points?: number; + /** 排序号 */ + orderNum?: number; + /** 创建者 */ + creator?: string; + /** 更新者 */ + updater?: string; + } + + /** + * 用户成就实体 + */ + export interface UserAchievement extends BaseDTO { + /** 用户ID */ + userID?: string; + /** 成就ID */ + achievementID?: string; + /** 获得时间 */ + obtainTime?: string; + } + + /** + * 用户成就进度实体 + */ + export interface UserAchievementProgress extends BaseDTO { + /** 用户ID */ + userID?: string; + /** 成就ID */ + achievementID?: string; + /** 当前进度值 */ + currentValue?: number; + /** 目标进度值 */ + targetValue?: number; + /** 进度百分比 (0-100) */ + progressPercentage?: number; + /** 是否已完成 */ + completed?: boolean; + /** 最后更新时间 */ + lastUpdateTime?: string; + } + + /** + * 成就视图对象 - 包含成就信息、获得状态和进度信息 + */ + export interface AchievementVO extends Achievement { + // ==================== 用户成就表的字段 ==================== + /** 用户成就记录ID */ + userAchievementID?: string; + /** 用户ID */ + userID?: string; + /** 获得时间 */ + obtainTime?: string; + + // ==================== 成就进度表的字段 ==================== + /** 进度记录ID */ + progressID?: string; + /** 当前进度值 */ + currentValue?: number; + /** 目标进度值 */ + targetValue?: number; + /** 进度百分比 (0-100) */ + progressPercentage?: number; + /** 是否已完成 */ + completed?: boolean; + /** 最后更新时间 */ + lastUpdateTime?: string; + + // ==================== 扩展字段 ==================== + /** 是否已获得该成就 */ + obtained?: boolean; + } + + /** + * 成就事件实体 + * 用于触发成就检测和授予 + * @since 2025-10-24 + */ + export interface AchievementEvent { + /** 用户ID */ + userID: string; + /** 事件类型 */ + eventType: AchievementEventType; + /** 事件值(如学习时长、资源数量等) */ + eventValue?: number; + /** 事件时间 */ + eventTime?: string; + /** 额外数据 */ + extraData?: Record; + } \ No newline at end of file diff --git a/schoolNewsWeb/src/types/achievement/index.ts b/schoolNewsWeb/src/types/achievement/index.ts new file mode 100644 index 0000000..3e98de6 --- /dev/null +++ b/schoolNewsWeb/src/types/achievement/index.ts @@ -0,0 +1 @@ +export * from './achievement'; \ No newline at end of file diff --git a/schoolNewsWeb/src/types/enums/achievement-enums.ts b/schoolNewsWeb/src/types/enums/achievement-enums.ts new file mode 100644 index 0000000..79e928e --- /dev/null +++ b/schoolNewsWeb/src/types/enums/achievement-enums.ts @@ -0,0 +1,186 @@ +/** + * @description 成就相关枚举辅助工具 + * @author yslg + * @since 2025-10-25 + */ + +import { AchievementType, AchievementConditionType, AchievementEventType } from './index'; + +/** + * 成就类型描述映射 + */ +export const AchievementTypeDescriptions: Record = { + [AchievementType.BADGE]: '勋章', + [AchievementType.LEVEL]: '等级' +}; + +/** + * 成就条件类型描述映射 + */ +export const AchievementConditionTypeDescriptions: Record = { + [AchievementConditionType.LEARNING_TIME]: '学习时长', + [AchievementConditionType.RESOURCE_VIEW_COUNT]: '浏览资源数量', + [AchievementConditionType.COURSE_COMPLETE_COUNT]: '完成课程数量', + [AchievementConditionType.CONTINUOUS_LOGIN_DAYS]: '连续登录天数', + [AchievementConditionType.RESOURCE_COLLECT_COUNT]: '收藏资源数量', + [AchievementConditionType.TASK_COMPLETE_COUNT]: '完成任务数量', + [AchievementConditionType.POINTS_EARNED]: '获得积分数量', + [AchievementConditionType.COMMENT_COUNT]: '发表评论数量', + [AchievementConditionType.CHAPTER_COMPLETE_COUNT]: '完成章节数量', + [AchievementConditionType.TOTAL_LOGIN_DAYS]: '累计登录天数' +}; + +/** + * 成就事件类型描述映射 + */ +export const AchievementEventTypeDescriptions: Record = { + // 学习相关事件 + [AchievementEventType.LEARNING_TIME_UPDATED]: '学习时长更新', + [AchievementEventType.COURSE_COMPLETED]: '课程完成', + [AchievementEventType.COURSE_STARTED]: '开始学习课程', + [AchievementEventType.CHAPTER_COMPLETED]: '章节完成', + // 资源相关事件 + [AchievementEventType.RESOURCE_VIEWED]: '浏览资源', + [AchievementEventType.RESOURCE_COLLECTED]: '收藏资源', + [AchievementEventType.RESOURCE_SHARED]: '分享资源', + // 任务相关事件 + [AchievementEventType.TASK_COMPLETED]: '任务完成', + [AchievementEventType.TASK_ITEM_COMPLETED]: '任务项完成', + // 互动相关事件 + [AchievementEventType.COMMENT_POSTED]: '发表评论', + [AchievementEventType.LIKE_GIVEN]: '点赞', + // 登录相关事件 + [AchievementEventType.USER_LOGIN]: '用户登录', + [AchievementEventType.CONTINUOUS_LOGIN]: '连续登录', + // 积分相关事件 + [AchievementEventType.POINTS_EARNED_EVENT]: '获得积分', + // 测试相关事件 + [AchievementEventType.TEST_PASSED]: '测试通过', + [AchievementEventType.TEST_PERFECT_SCORE]: '测试满分' +}; + +/** + * 成就枚举辅助类 + */ +export class AchievementEnumHelper { + + /** + * 获取成就类型描述 + * @param type 成就类型 + * @returns 描述文本 + */ + static getAchievementTypeDescription(type: AchievementType): string { + return AchievementTypeDescriptions[type] || '未知类型'; + } + + /** + * 获取成就条件类型描述 + * @param type 条件类型 + * @returns 描述文本 + */ + static getConditionTypeDescription(type: AchievementConditionType): string { + return AchievementConditionTypeDescriptions[type] || '未知条件'; + } + + /** + * 获取成就事件类型描述 + * @param type 事件类型 + * @returns 描述文本 + */ + static getEventTypeDescription(type: AchievementEventType): string { + return AchievementEventTypeDescriptions[type] || '未知事件'; + } + + /** + * 根据code获取成就条件类型 + * @param code 条件类型代码 + * @returns 条件类型枚举值或null + */ + static getConditionTypeFromCode(code: number): AchievementConditionType | null { + const types = Object.values(AchievementConditionType).filter( + (value): value is AchievementConditionType => typeof value === 'number' + ); + return types.find(type => type === code) || null; + } + + /** + * 根据code获取成就事件类型 + * @param code 事件类型代码 + * @returns 事件类型枚举值或null + */ + static getEventTypeFromCode(code: string): AchievementEventType | null { + const types = Object.values(AchievementEventType).filter( + (value): value is AchievementEventType => typeof value === 'string' + ); + return types.find(type => type === code) || null; + } + + /** + * 获取所有成就条件类型选项(用于下拉框等) + * @returns 选项数组 + */ + static getAllConditionTypeOptions(): Array<{ value: AchievementConditionType; label: string }> { + return Object.entries(AchievementConditionTypeDescriptions).map(([value, label]) => ({ + value: Number(value) as AchievementConditionType, + label + })); + } + + /** + * 获取所有成就类型选项(用于下拉框等) + * @returns 选项数组 + */ + static getAllAchievementTypeOptions(): Array<{ value: AchievementType; label: string }> { + return Object.entries(AchievementTypeDescriptions).map(([value, label]) => ({ + value: Number(value) as AchievementType, + label + })); + } + + /** + * 获取所有成就事件类型选项(用于下拉框等) + * @returns 选项数组 + */ + static getAllEventTypeOptions(): Array<{ value: AchievementEventType; label: string }> { + return Object.entries(AchievementEventTypeDescriptions).map(([value, label]) => ({ + value: value as AchievementEventType, + label + })); + } + + /** + * 格式化条件值显示 + * @param conditionType 条件类型 + * @param conditionValue 条件值 + * @returns 格式化后的显示文本 + */ + static formatConditionValue(conditionType: AchievementConditionType, conditionValue: number): string { + const typeDesc = this.getConditionTypeDescription(conditionType); + + switch (conditionType) { + case AchievementConditionType.LEARNING_TIME: + return `${typeDesc}达到${conditionValue}分钟`; + case AchievementConditionType.RESOURCE_VIEW_COUNT: + return `${typeDesc}达到${conditionValue}个`; + case AchievementConditionType.COURSE_COMPLETE_COUNT: + return `${typeDesc}达到${conditionValue}门`; + case AchievementConditionType.CONTINUOUS_LOGIN_DAYS: + return `${typeDesc}达到${conditionValue}天`; + case AchievementConditionType.RESOURCE_COLLECT_COUNT: + return `${typeDesc}达到${conditionValue}个`; + case AchievementConditionType.TASK_COMPLETE_COUNT: + return `${typeDesc}达到${conditionValue}个`; + case AchievementConditionType.POINTS_EARNED: + return `${typeDesc}达到${conditionValue}分`; + case AchievementConditionType.COMMENT_COUNT: + return `${typeDesc}达到${conditionValue}条`; + case AchievementConditionType.CHAPTER_COMPLETE_COUNT: + return `${typeDesc}达到${conditionValue}个`; + case AchievementConditionType.TOTAL_LOGIN_DAYS: + return `${typeDesc}达到${conditionValue}天`; + default: + return `${typeDesc}达到${conditionValue}`; + } + } +} + diff --git a/schoolNewsWeb/src/types/enums/index.ts b/schoolNewsWeb/src/types/enums/index.ts index 276b0b3..ee1b951 100644 --- a/schoolNewsWeb/src/types/enums/index.ts +++ b/schoolNewsWeb/src/types/enums/index.ts @@ -210,3 +210,90 @@ export enum TaskItemType { /** 课程类型 */ COURSE = 2 } + +/** + * 成就类型枚举 + */ +export enum AchievementType { + /** 勋章 */ + BADGE = 1, + /** 等级 */ + LEVEL = 2 +} + +/** + * 成就条件类型枚举 + */ +export enum AchievementConditionType { + /** 学习时长(分钟) */ + LEARNING_TIME = 1, + /** 浏览资源数量 */ + RESOURCE_VIEW_COUNT = 2, + /** 完成课程数量 */ + COURSE_COMPLETE_COUNT = 3, + /** 连续登录天数 */ + CONTINUOUS_LOGIN_DAYS = 4, + /** 收藏资源数量 */ + RESOURCE_COLLECT_COUNT = 5, + /** 完成任务数量 */ + TASK_COMPLETE_COUNT = 6, + /** 获得积分数量 */ + POINTS_EARNED = 7, + /** 发表评论数量 */ + COMMENT_COUNT = 8, + /** 完成章节数量 */ + CHAPTER_COMPLETE_COUNT = 9, + /** 累计登录天数 */ + TOTAL_LOGIN_DAYS = 10 +} + +/** + * 成就事件类型枚举 + */ +export enum AchievementEventType { + // ==================== 学习相关事件 ==================== + /** 学习时长更新 */ + LEARNING_TIME_UPDATED = 'learning_time_updated', + /** 课程完成 */ + COURSE_COMPLETED = 'course_completed', + /** 开始学习课程 */ + COURSE_STARTED = 'course_started', + /** 章节完成 */ + CHAPTER_COMPLETED = 'chapter_completed', + + // ==================== 资源相关事件 ==================== + /** 浏览资源 */ + RESOURCE_VIEWED = 'resource_viewed', + /** 收藏资源 */ + RESOURCE_COLLECTED = 'resource_collected', + /** 分享资源 */ + RESOURCE_SHARED = 'resource_shared', + + // ==================== 任务相关事件 ==================== + /** 任务完成 */ + TASK_COMPLETED = 'task_completed', + /** 任务项完成 */ + TASK_ITEM_COMPLETED = 'task_item_completed', + + // ==================== 互动相关事件 ==================== + /** 发表评论 */ + COMMENT_POSTED = 'comment_posted', + /** 点赞 */ + LIKE_GIVEN = 'like_given', + + // ==================== 登录相关事件 ==================== + /** 用户登录 */ + USER_LOGIN = 'user_login', + /** 连续登录 */ + CONTINUOUS_LOGIN = 'continuous_login', + + // ==================== 积分相关事件 ==================== + /** 获得积分 */ + POINTS_EARNED_EVENT = 'points_earned', + + // ==================== 测试相关事件 ==================== + /** 测试通过 */ + TEST_PASSED = 'test_passed', + /** 测试满分 */ + TEST_PERFECT_SCORE = 'test_perfect_score' +} \ No newline at end of file diff --git a/schoolNewsWeb/src/types/index.ts b/schoolNewsWeb/src/types/index.ts index af0b25c..8410af4 100644 --- a/schoolNewsWeb/src/types/index.ts +++ b/schoolNewsWeb/src/types/index.ts @@ -22,6 +22,11 @@ export * from './menu'; // 权限相关 export * from './permission'; +// 系统相关 +export * from './module'; + +export * from './achievement'; + // 认证相关 export * from './auth'; @@ -42,6 +47,7 @@ export * from './usercenter'; // 枚举类型 export * from './enums'; +export * from './enums/achievement-enums'; // 常量 export * from './constants'; diff --git a/schoolNewsWeb/src/types/module/index.ts b/schoolNewsWeb/src/types/module/index.ts new file mode 100644 index 0000000..0e34805 --- /dev/null +++ b/schoolNewsWeb/src/types/module/index.ts @@ -0,0 +1,162 @@ +/** + * @description 系统相关类型定义 + * @author yslg + * @since 2025-10-25 + */ + +import { BaseDTO } from '../base'; + +/** + * 系统模块 + */ +export interface SysModule extends BaseDTO { + /** 模块ID */ + moduleID?: string; + /** 模块名称 */ + name?: string; + /** 模块代码 */ + code?: string; + /** 模块描述 */ + description?: string; + /** 模块图标 */ + icon?: string; + /** 模块排序号 */ + orderNum?: number; + /** 模块状态(0禁用 1启用) */ + status?: number; + /** 创建者 */ + creator?: string; + /** 更新者 */ + updater?: string; +} + +/** + * 系统配置 + */ +export interface SysConfig extends BaseDTO { + /** 配置键 */ + configKey?: string; + /** 配置值 */ + configValue?: string; + /** 配置名称 */ + configName?: string; + /** 配置描述 */ + description?: string; + /** 配置类型 */ + configType?: string; + /** 是否系统内置 */ + isSystem?: boolean; + /** 创建者 */ + creator?: string; + /** 更新者 */ + updater?: string; +} + +/** + * 系统字典类型 + */ +export interface SysDictType extends BaseDTO { + /** 字典类型 */ + dictType?: string; + /** 字典名称 */ + dictName?: string; + /** 状态(0禁用 1启用) */ + status?: number; + /** 备注 */ + remark?: string; + /** 创建者 */ + creator?: string; + /** 更新者 */ + updater?: string; +} + +/** + * 系统字典数据 + */ +export interface SysDictData extends BaseDTO { + /** 字典排序 */ + dictSort?: number; + /** 字典标签 */ + dictLabel?: string; + /** 字典键值 */ + dictValue?: string; + /** 字典类型 */ + dictType?: string; + /** 状态(0禁用 1启用) */ + status?: number; + /** 是否默认 */ + isDefault?: boolean; + /** 备注 */ + remark?: string; + /** 创建者 */ + creator?: string; + /** 更新者 */ + updater?: string; +} + +/** + * 系统通知 + */ +export interface SysNotification extends BaseDTO { + /** 通知ID */ + notificationID?: string; + /** 通知标题 */ + title?: string; + /** 通知内容 */ + content?: string; + /** 通知类型 */ + type?: number; + /** 接收用户ID */ + receiverID?: string; + /** 是否已读 */ + isRead?: boolean; + /** 已读时间 */ + readTime?: string; + /** 创建者 */ + creator?: string; +} + +/** + * 系统操作日志 + */ +export interface SysOperationLog extends BaseDTO { + /** 操作用户 */ + operator?: string; + /** 操作模块 */ + module?: string; + /** 操作类型 */ + operationType?: string; + /** 操作方法 */ + method?: string; + /** 请求参数 */ + requestParams?: string; + /** 返回结果 */ + responseResult?: string; + /** 操作状态(0失败 1成功) */ + status?: number; + /** 错误消息 */ + errorMsg?: string; + /** 操作IP */ + operationIP?: string; + /** 操作时间 */ + operationTime?: string; + /** 执行时长(毫秒) */ + duration?: number; +} + +/** + * 系统访问统计 + */ +export interface SysVisitStatistics extends BaseDTO { + /** 统计日期 */ + statisticsDate?: string; + /** 访问量 */ + visitCount?: number; + /** 独立访客数 */ + uniqueVisitors?: number; + /** 页面浏览量 */ + pageViews?: number; + /** 平均访问时长(秒) */ + avgDuration?: number; +} + diff --git a/schoolNewsWeb/src/types/permission/index.ts b/schoolNewsWeb/src/types/permission/index.ts index e5ef849..69e60e1 100644 --- a/schoolNewsWeb/src/types/permission/index.ts +++ b/schoolNewsWeb/src/types/permission/index.ts @@ -7,6 +7,7 @@ import { BaseDTO } from '../base'; import { SysMenu } from '../menu'; import { SysRole } from '../role'; +import { SysModule } from '../module'; /** * 系统权限 @@ -16,6 +17,7 @@ export interface SysPermission extends BaseDTO { id?:string; /** 权限ID */ permissionID?: string; + moduleID?: string; /** 权限名称 */ name?: string; /** 权限描述 */ @@ -34,5 +36,5 @@ export interface SysPermission extends BaseDTO { menus?: SysMenu[]; roles?: SysRole[]; permissions?: SysPermission[]; -} - + module?: SysModule; +} \ No newline at end of file diff --git a/schoolNewsWeb/src/types/usercenter/index.ts b/schoolNewsWeb/src/types/usercenter/index.ts index 2f15c3b..8eaf9ea 100644 --- a/schoolNewsWeb/src/types/usercenter/index.ts +++ b/schoolNewsWeb/src/types/usercenter/index.ts @@ -68,38 +68,6 @@ export interface PointsRecord extends BaseDTO { relatedType?: number; } -/** - * 用户成就实体 - */ -export interface UserAchievement extends BaseDTO { - /** 用户ID */ - userID?: string; - /** 成就ID */ - achievementID?: string; - /** 获得时间 */ - achieveTime?: string; -} - -/** - * 成就实体 - */ -export interface Achievement extends BaseDTO { - /** 成就名称 */ - name?: string; - /** 成就描述 */ - description?: string; - /** 成就图标 */ - icon?: string; - /** 成就类型 */ - type?: number; - /** 获得条件 */ - condition?: string; - /** 奖励积分 */ - rewardPoints?: number; - /** 状态(0禁用 1启用) */ - status?: number; -} - /** * 个人中心统计信息 */ diff --git a/schoolNewsWeb/src/views/admin/manage/achievement/AchievementManagementView.vue b/schoolNewsWeb/src/views/admin/manage/achievement/AchievementManagementView.vue new file mode 100644 index 0000000..ef976b2 --- /dev/null +++ b/schoolNewsWeb/src/views/admin/manage/achievement/AchievementManagementView.vue @@ -0,0 +1,618 @@ + + + + + + diff --git a/schoolNewsWeb/src/views/admin/manage/achievement/index.ts b/schoolNewsWeb/src/views/admin/manage/achievement/index.ts new file mode 100644 index 0000000..765895a --- /dev/null +++ b/schoolNewsWeb/src/views/admin/manage/achievement/index.ts @@ -0,0 +1,2 @@ +export { default as AchievementManagementView } from './AchievementManagementView.vue'; + diff --git a/schoolNewsWeb/src/views/admin/manage/system/ModuleManageView.vue b/schoolNewsWeb/src/views/admin/manage/system/ModuleManageView.vue deleted file mode 100644 index e69de29..0000000 diff --git a/schoolNewsWeb/src/views/admin/manage/system/ModulePermissionManageView.vue b/schoolNewsWeb/src/views/admin/manage/system/ModulePermissionManageView.vue new file mode 100644 index 0000000..a3b2b4d --- /dev/null +++ b/schoolNewsWeb/src/views/admin/manage/system/ModulePermissionManageView.vue @@ -0,0 +1,1159 @@ + + + + + + diff --git a/schoolNewsWeb/src/views/admin/manage/system/PermissionManageView.vue b/schoolNewsWeb/src/views/admin/manage/system/PermissionManageView.vue deleted file mode 100644 index 1263140..0000000 --- a/schoolNewsWeb/src/views/admin/manage/system/PermissionManageView.vue +++ /dev/null @@ -1,721 +0,0 @@ - - - - - \ No newline at end of file diff --git a/schoolNewsWeb/src/views/user-center/MyAchievementsView.vue b/schoolNewsWeb/src/views/user-center/MyAchievementsView.vue index d5d8449..5f51e90 100644 --- a/schoolNewsWeb/src/views/user-center/MyAchievementsView.vue +++ b/schoolNewsWeb/src/views/user-center/MyAchievementsView.vue @@ -3,59 +3,257 @@

我的成就

- 已获得 {{ earnedCount }} / {{ totalCount }} 个成就 +
+ 已获得 + {{ earnedCount }} + / {{ totalCount }} +
+
+ 完成率 + {{ completionRate }}% +
-
+ +
+ + 全部 + + {{ option.label }} + + + + + 仅显示已获得 + +
+ + +
+ +
+ + +
- -
+ + + +
+ +
+
+ Lv.{{ achievement.level }} +
-

{{ achievement.name }}

-

{{ achievement.description }}

-
-
-
-
- {{ achievement.progress }}% +
+

{{ achievement.name }}

+ + {{ getAchievementTypeLabel(achievement.type) }} +
-
- 获得时间:{{ achievement.earnedDate }} +

{{ achievement.description }}

+ + +
+ + {{ formatConditionValue(achievement.conditionType, achievement.conditionValue) }} +
+ + +
+
+ 进度 + + {{ achievement.currentValue || 0 }} / {{ achievement.targetValue || achievement.conditionValue }} + +
+ +
+ + + + + +
+ + 奖励 {{ achievement.points }} 积分
+ + +