Compare commits

...

249 Commits

Author SHA1 Message Date
hhb@hotmail.com 02fa60e427 update 修正顺序
3 days ago
hhb@hotmail.com d0379cd7b8 update
3 days ago
hhb@hotmail.com 74148a068a update
4 days ago
hhb@hotmail.com af6536c0fe update
2 weeks ago
PL a04ba227ec Merge remote-tracking branch 'origin/develop' into develop
3 weeks ago
PL e57affb790 update:jwt的修改
3 weeks ago
hhb@hotmail.com 128a05e90a update 调整参数
3 weeks ago
hhb@hotmail.com 13d095d02b update 教师分布统计空指针
3 weeks ago
hhb@hotmail.com cd421db42b update 教师分布统计返回值调整
3 weeks ago
hhb@hotmail.com 18b0acd648 update 教师分布统计返回值调整
3 weeks ago
hhb@hotmail.com e447351729 update 教师分布统计
3 weeks ago
hhb@hotmail.com 49cfb37404 update 教师身分信息
4 weeks ago
hhb@hotmail.com c1bbd8a7ac update 教师信息
4 weeks ago
hhb@hotmail.com e746605ee0 update 教师信息
4 weeks ago
hhb@hotmail.com ab78ec557f update 教龄 性别 学历
4 weeks ago
hhb@hotmail.com de621c8541 update 加上科目内容
1 month ago
hhb@hotmail.com 4153162ff1 update 每周不同层级课例数据加上科目内容
1 month ago
hhb@hotmail.com a9c6c6a499 update 每周不同层级课例数据
1 month ago
hhb@hotmail.com be289caf37 update 年级相关内容
1 month ago
hhb@hotmail.com 1dd21b136e update 教研组
1 month ago
hhb@hotmail.com 6e1bfdc6c9 update 学段内容
1 month ago
hhb@hotmail.com 5933e2daee update
1 month ago
hhb@hotmail.com 1dcd782331 update 教师看板个人数据
1 month ago
hhb@hotmail.com 3449d2bcbd update 教师相关数据
1 month ago
hhb@hotmail.com 7ec8d20ae8 update 教师相关数据
1 month ago
hhb@hotmail.com 12ad733286 update 教师相关统计数据
1 month ago
PL f07b7e9257 Merge remote-tracking branch 'origin/develop' into develop
2 months ago
PL d038fd631e update:优化字数限制语言描述
2 months ago
CrazyIter_Bin e64b8d8e8c update
2 months ago
CrazyIter_Bin 99337c5835 update
2 months ago
CrazyIter_Bin 7358250cd3 update
2 months ago
PL 8057c0f18f update:优化评语添加用户自定义限制条件
2 months ago
PL bb417b8613 update:评语添加用户自定义限制条件
2 months ago
hhb@hotmail.com 20a0bbfe8e update dto
2 months ago
hhb@hotmail.com 9e76f8ca43 update请求地址
2 months ago
CrazyIter_Bin ab67d282f1 Merge branch 'develop' of http://163.228.224.105:3000/WinTeachTeam/IESExtension into develop
2 months ago
CrazyIter_Bin 0d4864f7f7 update
2 months ago
hhb@hotmail.com 692015b0c7 Merge remote-tracking branch 'origin/develop' into develop
2 months ago
hhb@hotmail.com a5d404a025 update
2 months ago
PL 8100e15948 update:优化代码
2 months ago
PL 65d4740084 update:调试优化AI评语模版
2 months ago
PL 146adb9ae6 update:调试优化AI评语模版
2 months ago
PL baea216357 update:调试优化AI评语模版
2 months ago
PL ffb8af9546 update:调试优化AI评语模版
2 months ago
PL 817fe06787 update:优化AI评语版本
2 months ago
PL dda1342731 update:优化AI评语
2 months ago
PL d1018c375c update:优化AI评语
2 months ago
PL 469f19384b update:添加名称参数,并处理评语话术,与条件
2 months ago
PL 50f94cb38a 处理限制条件
2 months ago
PL 8c2a543bbb 处理评语智育
2 months ago
hhb@hotmail.com b68b576b8c update
3 months ago
hhb@hotmail.com 5eb9dcaadc update
3 months ago
hhb@hotmail.com 82f67e1afe 新增活动分析查询相关接口
3 months ago
CrazyIter_Bin 3fcc218292 update
3 months ago
CrazyIter_Bin 6b07db26bd update
3 months ago
PL fcfda1760a 处理智育,学科排行评语模版
3 months ago
hhb@hotmail.com 2f8bb75d6f update 查询参数
3 months ago
hhb@hotmail.com 87f75f34e5 update 参数
3 months ago
hhb@hotmail.com e7607e4b52 update 参数
3 months ago
hhb@hotmail.com 8b3ec87fb4 评测查询列表
3 months ago
zhouj1203@hotmail.com 63de395694 Merge remote-tracking branch 'origin/develop' into develop
3 months ago
zhouj1203@hotmail.com 0e5267f2ca 优化代码
3 months ago
PL 47bd34e760 处理智育,学科排行评语模版
3 months ago
PL bdd19d81b7 艺术评测的评语结构
4 months ago
PL bde76c5140 处理其他访问ai助手报错,修改jjwt插件
4 months ago
zhouj1203@hotmail.com 26e7574eec 调整返回内容
4 months ago
zhouj1203@hotmail.com 7ddcf2aed5 blob 相关权限内容
4 months ago
zhouj1203@hotmail.com 8879b87bd2 blob 相关权限内容
4 months ago
zhouj1203@hotmail.com f52559da2b 移除警告
4 months ago
zhouj1203@hotmail.com 763ce06af1 移除警告
4 months ago
zhouj1203@hotmail.com 4f3b4e6d6b 新增时间范围查询条件
4 months ago
zhouj1203@hotmail.com ec65450007 Merge remote-tracking branch 'origin/develop' into develop
4 months ago
zhouj1203@hotmail.com 4f2ea3d672 艺术看板相关内容
4 months ago
PL 5c47b00105 将每次读取json数据改为初始项目就读取json数据(获取模型数据)
4 months ago
PL 267facc601 排查读取json
4 months ago
PL 436e4d807a 读取json文件方式更换
4 months ago
PL 54bf566482 读取文件方式更换
4 months ago
zhouj1203@hotmail.com aeb6b5d17e 调整参数查询
4 months ago
PL abb7d9a136 排查读取文件异常
4 months ago
PL 472ad1589b 排查读取文件异常
4 months ago
CrazyIter_Bin c6e51008f1 update
4 months ago
CrazyIter_Bin f8b29d0b2f updaye
4 months ago
zhouj1203@hotmail.com 9b99c7db28 更新包结构
4 months ago
zhouj1203@hotmail.com 5efd36bce8 更新数据结构
4 months ago
zhouj1203@hotmail.com ab5ad3088b Merge remote-tracking branch 'origin/develop' into develop
4 months ago
zhouj1203@hotmail.com 741330e678 移除冗余包
4 months ago
PL 8eba7eb8dc Merge remote-tracking branch 'origin/develop' into develop
4 months ago
PL 110177681b 处理异常抛出问题
4 months ago
zhouj1203@hotmail.com 1fdc914ed6 调整评语结构
4 months ago
PL e5b87627cf 修改数组类型
4 months ago
PL cf1d4cbf30 排查测试无异常,正式站访问异常问题
4 months ago
PL ccda6b3c12 排查测试无异常,正式站访问异常问题
4 months ago
PL b332503a9e 处理文件字段问题
4 months ago
PL 2b1c8e7264 提交返回字数限制。与jwt安装包配置
4 months ago
zhouj1203@hotmail.com 70c3aaefbe 清理无用包
4 months ago
PL dc2a311ead 绝对路径改为相对路径读取文件信息
4 months ago
zhouj1203@hotmail.com 5658dabd32 Merge remote-tracking branch 'origin/develop' into develop
4 months ago
zhouj1203@hotmail.com 2e6d04aeff 评语一条龙
4 months ago
PL b9337b4f39 处理聊天评语模版暂无平均分的问题
4 months ago
zhouj1203@hotmail.com 0e38d74d08 更新查询条件
4 months ago
PL 1b67461abb 聊天评语聊天模块
4 months ago
zhouj1203@hotmail.com fd9909a5c4 智慧教育模块结算,实体架构评论
4 months ago
zhouj1203@hotmail.com af0a9eb205 调整参数
4 months ago
zhouj1203@hotmail.com d2fe43d289 修改注解
4 months ago
zhouj1203@hotmail.com 8198da6fa5 新增接口艺术模块pdf操作,新增智育模块API 分组内容
4 months ago
CrazyIter_Bin bfb5eb7beb Merge branch 'develop' of http://163.228.224.105:3000/WinTeachTeam/IESExtension.git into develop
4 months ago
CrazyIter_Bin a1da5adc6f Merge branch 'develop' of http://163.228.224.105:3000/WinTeachTeam/IESExtension into develop
4 months ago
PL d173babbd7 聊天评语设置接口
4 months ago
CrazyIter_Bin fa2bad9f86 Merge branch '11111' into develop
4 months ago
CrazyIter_Bin a70efb3c7b update
4 months ago
PL e5196290b2 Merge remote-tracking branch 'origin/develop' into develop
4 months ago
zhouj1203@hotmail.com 39f6e1eb8f 处理参考人数问题
4 months ago
zhouj1203@hotmail.com 33aaf13e9d Merge remote-tracking branch 'origin/develop' into develop
4 months ago
PL 0fc74a1819 Merge remote-tracking branch 'origin/develop' into develop
4 months ago
CrazyIter_Bin 37abc6a90c update
4 months ago
zhouj1203@hotmail.com 35a3d285c1 Merge remote-tracking branch 'origin/develop' into develop
4 months ago
CrazyIter_Bin 72380dc68a update
4 months ago
PL e8dfcf7f9f 聊天评语设置接口
4 months ago
zhouj1203@hotmail.com 523dfa47b6 处理年级与班级数据返回工具类
4 months ago
zhouj1203@hotmail.com 5200ec6f8c 更新名单接口,优化内容访问接口的方式,新增工具类操作外部接口
4 months ago
PL 678e7d302b 添加用于在Java对象和JSON数据之间进行快速、‌高效的转换。
4 months ago
PL d333e6809f Merge remote-tracking branch 'origin/develop' into develop
4 months ago
PL 812456a8e1 国培项目不能访问ai的问题,安装包的问题
4 months ago
PL 81a83a7566 将正式站数据库改为测试站数据库
4 months ago
zhouj1203@hotmail.com 6587bcca67 更新艺术评测相关内容 名单提取
4 months ago
PL d880be517b 处理配置问题
4 months ago
zhouj1203@hotmail.com f46d24223f Merge remote-tracking branch 'origin/develop' into develop
4 months ago
zhouj1203@hotmail.com 8e9d78dcc4 艺术评测相关内容
4 months ago
Li c20bbd2cf4 将科大讯飞的配置由原来的个人修改为企业配置,暂时注释个人配置信息
4 months ago
zhouj1203@hotmail.com 3451287df9 更新字段注解
5 months ago
zhouj1203@hotmail.com a1aa8c7187 新增班会科目逻辑代码,配置文件改为正式地址
5 months ago
zhouj1203@hotmail.com db6c7d402f 更新参数传递方式,调整参数解析内容,新增工具类,新增条件Dto
5 months ago
zhouj1203@hotmail.com a801724b75 redis 课堂纪律相关内容
5 months ago
winter c9e7268d87 fix: 修改 chatApp 权限时报
8 months ago
winter b7126f7bd8 refactor: 修改接口
8 months ago
winter 5d33226f94 refactor: ai接口token header修改
8 months ago
winter 5caf6de0ec refactor: ai接口token header修改
8 months ago
winter 2698f759a4 refactor: ai接口token header修改
8 months ago
winter f966dacb9c refactor: ai接口token header修改
8 months ago
winter a53efd1f7a fix: 修复 api
9 months ago
winter acf448e980 feat: 额外对国培AI对话接口的鉴权
9 months ago
winter 9aec66d1a7 refactor: 更改日志上传的api地址
9 months ago
winter b53fe0f7d6 feat: 新增接口日志上传拦截器
9 months ago
winter ea5c6fcb81 test: 暂时修改ai为public,下次更新回复先前版本
10 months ago
winter 52773b45ff refactor: 更新 pdf 模板
10 months ago
winter bbef6070fd refactor: 更新 pdf 模板
10 months ago
winter a00e0eaf2e refactor: 更新学生评价模板
10 months ago
winter 1a006ee304 fix: 添加字体文件,用代码让JChartFree用上simsun字体
10 months ago
winter 7aa14b1b82 fix: 修复乱码
10 months ago
winter c2c1f9cd0b fix: 测试线上Jfreechart图表汉字乱码
10 months ago
winter 32f2414cd8 fix: 饼图无数据时给与提示
10 months ago
winter fa1c6a9b20 refactor: 重构 PDF 模板
10 months ago
winter b9950c6022 refactor: 更新学生报告pdf
10 months ago
winter da1bb7fc87 feat: 值周巡检首页数据总览接口
10 months ago
winter 09140678bc feat: 新增首页数据展示
10 months ago
winter 9ff280a94e refactor: 拍照巡检暂时不用地点 id
10 months ago
winter 29f1fed4f1 feat: 新增通过 id 查询新闻
10 months ago
winter 94ac4286c3 fix: 修复计算学期学年的 start bug
10 months ago
winter 9f0cd7d01a refactor: 新闻新增学段字段
10 months ago
winter a539afb9e8 refactor: 新闻新增学段字段
10 months ago
winter 21790d5666 feat: 完善 News CRUD
10 months ago
winter 53f9492eb0 feat: 新闻的增删改查
10 months ago
winter 079f2fbf6f refactor: 更新 pdf 模板
10 months ago
winter bc13f67a29 feat: 学生评价的 pdf 生成
10 months ago
winter d5ad605b35 feat: 补充 chatApp 字段
11 months ago
winter 118fc413d3 fix: 修复sql小bug
11 months ago
winter 0ac22b5353 feat: 新增 pdfUtils 填充 stampter form
11 months ago
winter 8b25e112e8 feat: 学生评价报告 pdf 导出
11 months ago
winter f3e3f48422 feat: AI 应用初步实现
11 months ago
winter e74fee8812 refactor: 修改 tokenfilter 日志
12 months ago
winter 8bc0da460b refactor: 重构学生评价树的新增/更新节点,自构建 path
12 months ago
winter 70ffad27a3 feat: 新增后台条件查询值周评价
12 months ago
winter 2fb38aa62c refactor: 调整 admin dto 目录
12 months ago
winter 48588b12fc fix: 修复撤回值周评价
12 months ago
winter 256b233b4c refactor: 前台查询老师评价值周明细接口参数调整
12 months ago
winter 8c15427ff7 feat: 撤回值周投票
12 months ago
winter d155efe947 refactor: 钉钉异常信息推送异常栈的详情
12 months ago
winter 1a18105096 feat: 新增多条件查询评价明细接口
12 months ago
winter 327e399d5a refactor: 将接口文档名称标识"
12 months ago
winter 9f77aa9ede feat: 初步实现值周巡检树以及评价接口
12 months ago
winter 38699011e6 feat: 值周巡检投票
12 months ago
winter eec45f6921 feat: 新增值周巡检数个接口
12 months ago
winter 65c8fd598f refactor: 将包 dao 改为 repository
12 months ago
winter 5c01fca6c1 fix: 修复会话的 updateTime 为最后一条消息的发送时间
1 year ago
winter 0ded5af82d fix: 不是因为单例 是因为 Date 参数
1 year ago
winter ab2aaa1757 fix: 修复因为单例 OkHttpClient 的使用导致ws连接失败的bug
1 year ago
winter f2e0c0b19e fix: 修复跨域配置
1 year ago
winter fb49fea68e feat: 拉取聊天记录
1 year ago
winter d1bb7d56a9 feat: 拉取聊天记录
1 year ago
winter 56700192d9 fix: 修复学生排名没有头像
1 year ago
winter c9309087c3 doc: 增加一些代码注释
1 year ago
winter 8301c973c0 feat: 评价指标排序添加 path 和 praise
1 year ago
winter 178e3cfc03 doc: 补充 Readme
1 year ago
winter 83bdf4d6c1 fix: 学生排名增加学生头像
1 year ago
winter 2f972c65e3 fix: 修复成就计算的算法
1 year ago
winter ae729c05e8 feat: 获取评价树时root节点排序
1 year ago
winter 40d4826695 fix: 修复学生报告中的排位问题
1 year ago
winter ef1979cbd7 feat: 新增学生报告的指标
1 year ago
winter cec0a7e58d fix: 修复成就的 by zero 错误和增强参数校验
1 year ago
winter 6cf0ebaef3 doc: 补充部分文档
1 year ago
winter 316f9daa4a fix: 修复管理员首页数据接口如果多页数据结果异常的 bug
1 year ago
winter d185a3ffe7 refactor: 调整评价树的学段id,现摒弃default为默认,每个学段id都有自己的评价树
1 year ago
winter 646caaa926 refactor: 调整创建会话的接口,返回创建的会话ID
1 year ago
winter 76499c3904 fix: 修复查询会话的sql和updatetime
1 year ago
winter fede04c70d feat: 新增对话历史上下文缓存
1 year ago
winter fa03927579 refactor: 合并
1 year ago
winter 6ea7454973 feat: chat session 的实现
1 year ago
winter ccbd59f18f feat: chat session 的实现
1 year ago
winter fee64cb1ac feat: 初步走通 spark Gpt 的对接流程,留下扩展其他 AI 的空间
1 year ago
winter 0bae71207b fix: 修复评价记录按时间分页失效,改为按时间范围查询
1 year ago
winter aa35b01844 Merge remote-tracking branch 'origin/develop' into develop
1 year ago
winter 8ddf66c97d fix: 修改撤回学生评价权限的 bug
1 year ago
CrazyIter_Bin 890d23ae6a update
1 year ago
winter b610194f30 feat: 新增评价项 path 路径
1 year ago
winter 7918786641 feat: 新增被评价学生总数与补充评价对象的班级名
1 year ago
winter 79db32c215 feat: 新增部分管理员接口以及提升稳定性
1 year ago
winter 3477592027 feat: 下班!!!
1 year ago
winter 83c980dcae feat: 管理员相关接口
1 year ago
winter a138e16b40 feat: 首页数据展示(评价总数,按周统计等)
1 year ago
winter 6d631563c6 feat: vote 接口添加是否推送给家长字段
1 year ago
winter 8f7b1f9cc1 feat: 为查询学生评价记录添加分页和排序
1 year ago
winter c54edf3cfe fix: 暂时解决查询 Student 序列化错误的bug
1 year ago
winter a3922d8c2d feat: 新增撤回评价的接口
1 year ago
winter 6c47e0c59e refactor: 完善添加评价记录的逻辑(如果一个student确是不同的班级)
1 year ago
winter 18d42a36e6 doc: 完善已有的接口文档
1 year ago
winter a09d61b020 fix: 增加条件查询学生评价条件项为空白字符串时不计入条件的接口健壮性
1 year ago
winter c34e87ca0d feat: 新增评价树的模板替换与节点 ID 刷新
1 year ago
winter 18cfb50a46 fix: 添加 validation 依赖,修复参数校验不生效的 bug
1 year ago
winter a2d75a1c3d fix: 修复首次添加评价时不会记录得分的bug
1 year ago
winter 29d21f0233 新增评价学生或班级接口
1 year ago
winter 6dffd636ec feat: 新增以及完善部分数据结构
1 year ago
winter 8301cfd96d feat: 新增根据指定日期获取学年的工具
1 year ago
winter aa582361f8 refactor: 重构实体类,按其归属分类
1 year ago
winter 38f5bf39ef fix: 修复查询结果多就出错的bug
1 year ago
winter edc79455cc refactor: 抽取公共的实体类 BaseItem
1 year ago
winter 610c6d4e81 refactor: 将 evaluation 重构成 appraise
1 year ago
winter 5e06e8ed1e doc: 更新注释文档
1 year ago
winter d9a19736f2 feat: 不允许序列化为空的字段
1 year ago
winter 2b271547e7 feat: 新增鉴权时的异常处理
1 year ago
winter 148c31b323 fix: 从 token 中拿到 schoolId 而不是传递参数
1 year ago
winter 68f5303a4c 新增对评价树的crud以及测试bug修复
1 year ago
winter 1be6ca7e02 feat: 新增获取评价项树的接口
1 year ago
winter 46b88742d7 fix: 修复生成树的空指针bug
1 year ago
winter 676f6fc46b feat: 新增构建学生评价树
1 year ago
winter a16e8f8de8 doc: 补充文档
1 year ago
winter f0a9ba9243 feat: 新增钉钉机器人异常告警
1 year ago
winter 46fa7bf45e doc: 新增 README.md
1 year ago
winter c1e2a62527 feat: 新增双 token 鉴权实现
1 year ago
winter 38bb428c59 refactor: 项目改名为 Teammodel-extension
1 year ago

1
.gitignore vendored

@ -31,3 +31,4 @@ build/
### VS Code ### ### VS Code ###
.vscode/ .vscode/
/.vs

@ -0,0 +1,31 @@
# TeamModel extension
> SpringBoot base version of TeamModel extension
>
> **注意**: 所有复盘输出均已脱敏,不包含任何业务,密码等关键信息
## 迁移目录:
- Azure OIDC(SSO) 迁移
- id-token(jwt) 验证迁移 (出现语言框架之间的签名算法规范问题,解决见: [输出复盘](https://juejin.cn/post/7300036605099163702))
- 钉钉告警: 异常通知
- 异常文件记录
### MILESTONE:
- Java 框架搭建
- 教育评价系统前后台实现
- Chat with AI 接入
## 数据表规则:
> ID 没有特殊之指明则为 UUID
### 教育评价树
分区键: `Appraise` , 表内 `schoolId` 区分学校, `periodId` 区分学区
### 教育评价项
> 学生每学期所有的评价项都在一个项中,按学校进行分区
>
> 注意: 如果学生中途换班,也就是 classId 发生变动,那么会给这个学生在本学期新开一个文档,也就是说一个学生在一个学期的文档可能不止一个(小概率)
>
分区键: `AppraiseRecord-{学校id}`
academicYearId: `学年 + semesterId` -> eg: 2022.uuid

@ -9,31 +9,218 @@
<relativePath/> <!-- lookup parent from repository --> <relativePath/> <!-- lookup parent from repository -->
</parent> </parent>
<groupId>cn.teammodel</groupId> <groupId>cn.teammodel</groupId>
<artifactId>deployment-test</artifactId> <artifactId>Teammodel-extension</artifactId>
<version>0.0.1-SNAPSHOT</version> <version>1.0.1</version>
<name>deployment-test</name> <name>Teammodel-extension</name>
<description>deployment-test</description> <description>Teammodel-extension</description>
<properties> <properties>
<java.version>1.8</java.version> <java.version>1.8</java.version>
<spring-cloud-azure.version>4.11.0</spring-cloud-azure.version>
</properties> </properties>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-web</artifactId>
</dependency> </dependency>
<!-- Spring Security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-miniapp</artifactId>
<version>4.6.0</version>
</dependency>
<!-- Spring Security OAuth2 resource server -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<!-- pdf操作类 -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.10</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
<!--用于jfreechart制作统计图 -->
<dependency>
<groupId>org.jfree</groupId>
<artifactId>jfreechart</artifactId>
<version>1.5.0</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.14.9</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.36</version>
</dependency>
<!-- 选择一个具体的日志实现例如Logback -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.11</version>
</dependency>
<!-- cosmos -->
<!-- <dependency>-->
<!-- <groupId>com.azure.spring</groupId>-->
<!-- <artifactId>spring-cloud-azure-starter</artifactId>-->
<!-- </dependency>-->
<!-- knife4j -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-starter-data-cosmos</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.16</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- 修改后的jwt -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<!-- dingding -->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>alibaba-dingtalk-service-sdk</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<!-- 指定依赖的作用范围 -->
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.48</version>
</dependency>
<!--用于在Java对象和JSON数据之间进行快速、高效的转换-->
</dependencies>
<!-- 私服 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-dependencies</artifactId>
<version>${spring-cloud-azure.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies> </dependencies>
</dependencyManagement>
<repositories>
<repository>
<id>gitea</id>
<url>http://163.228.224.105:3000/api/packages/winteach/maven</url>
</repository>
</repositories>
<distributionManagement>
<repository>
<id>gitea</id>
<url>http://163.228.224.105:3000/api/packages/winteach/maven</url>
</repository>
<snapshotRepository>
<id>gitea</id>
<url>http://163.228.224.105:3000/api/packages/winteach/maven</url>
</snapshotRepository>
</distributionManagement>
<build> <build>
<plugins> <plugins>
<plugin> <plugin>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId> <artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<!-- 请使用你项目中实际的版本号 <version>1.0.1</version> -->
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<encoding>utf-8</encoding>
<useDefaultDelimiters>true</useDefaultDelimiters>
</configuration>
</plugin> </plugin>
</plugins> </plugins>
</build> </build>

@ -4,10 +4,10 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication @SpringBootApplication
public class DeploymentTestApplication { public class TeamModelExtensionApplication {
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication.run(DeploymentTestApplication.class, args); SpringApplication.run(TeamModelExtensionApplication.class, args);
} }
} }

@ -0,0 +1,73 @@
package cn.teammodel.ai;
import cn.teammodel.common.ErrorCode;
import cn.teammodel.config.exception.ServiceException;
import cn.teammodel.model.dto.ai.ChatModelDto;
import cn.teammodel.utils.FileUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.TypeReference;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* json
* 使
*
* json,Spring Bean
* SpringJSONSpring Bean使@PostConstructBeanJSON
*
*<-- pom.xml -->
*<dependency>
*<groupId>com.fasterxml.jackson.core</groupId>
*<artifactId>jackson-databind</artifactId>
*<version>2.13.1</version>
*</dependency>
*/
@Configuration
public class JsonLoader implements InitializingBean {
private List<ChatModelDto> chatModels = new ArrayList<>();
private void JsonLoader() {
// 私有构造函数防止实例化
}
/**
* json
*/
@PostConstruct
public void loadJsonData(){
try{
String fileText = FileUtil.getFileText("Json/ChatModel.json");
String jsonData = JSON.toJSONString(fileText);
//获取聊天字段中的数据
Object obj = JSON.parseObject(jsonData).get("chatModel");
String jsonData01 = JSON.toJSONString(obj);
//转换方式
chatModels = JSON.parseObject(jsonData01, new TypeReference<List<ChatModelDto>>() {});
}catch (Exception e){
throw new ServiceException(ErrorCode.OPERATION_ERROR.getCode(), "读取文件" + Arrays.toString(e.getStackTrace()) + e.getMessage());
}
}
/**
*
* @return
*/
@Bean
public List<ChatModelDto> myJsonDataBean(){
return chatModels;
}
@Override
public void afterPropertiesSet() throws Exception {
JsonLoader();
}
}

@ -0,0 +1,118 @@
package cn.teammodel.ai;
import cn.hutool.json.JSONUtil;
import cn.teammodel.ai.cache.HistoryCache;
import cn.teammodel.ai.domain.SparkChatRequestParam;
import cn.teammodel.ai.listener.SparkGptStreamListener;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* spark Gpt client
* @author winter
* @create 2023-12-15 14:29
*/
@Component
@Data
@Slf4j
public class SparkGptClient implements InitializingBean {
@Resource
private SparkGptProperties sparkGptProperties;
private OkHttpClient okHttpClient;
// private String authUrl;
/**
*
*/
public void init() {
// 初始化缓存
HistoryCache.init(sparkGptProperties.getCache_timeout(), sparkGptProperties.getCache_context());
// 初始化 authUrl
// log.info("[SPARK CHAT] 鉴权 endpoint : {}", this.authUrl);
this.okHttpClient = new OkHttpClient.Builder()
.connectTimeout(180, TimeUnit.SECONDS)
.readTimeout(180, TimeUnit.SECONDS) // sse 接口的 readTimeout 不能设置小了
.writeTimeout(180, TimeUnit.SECONDS)
.build();
}
/**
* , sse
*/
public void streamChatCompletion(SparkChatRequestParam param, SparkGptStreamListener listener) {
try {
param.setAppId(sparkGptProperties.getAppId());
String authUrl = genAuthUrl(sparkGptProperties.getEndpoint(), sparkGptProperties.getApiKey(), sparkGptProperties.getApiSecret());
authUrl = authUrl.replace("http://", "ws://").replace("https://", "wss://");
Request request = new Request.Builder().url(authUrl).build();
// 设置请求参数
listener.setRequestJson(param.toJsonParams());
log.info("[SPARK CHAT] 请求参数 {}", JSONUtil.parseObj(param.toJsonParams()).toStringPretty());
// 不能使用单例 client
okHttpClient.newWebSocket(request, listener);
} catch (Exception e) {
log.error("[SPARK CHAT] Spark AI 请求异常: {}", e.getMessage());
e.printStackTrace();
}
}
/**
* URL
*/
public static String genAuthUrl(String endpoint, String apiKey, String apiSecret) {
URL url = null;
String date = null;
String preStr = null;
Mac mac = null;
try {
url = new URL(endpoint);
// 时间
SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
format.setTimeZone(TimeZone.getTimeZone("GMT"));
date = format.format(new Date());
// 拼接
preStr = "host: " + url.getHost() + "\n" +
"date: " + date + "\n" +
"GET " + url.getPath() + " HTTP/1.1";
// SHA256加密
mac = Mac.getInstance("hmacsha256");
SecretKeySpec spec = new SecretKeySpec(apiSecret.getBytes(StandardCharsets.UTF_8), "hmacsha256");
mac.init(spec);
} catch (Exception e) {
log.error("[SPARK CHAT] 生成鉴权URL失败, endpoint: {}, apiKey: {}, apiSecret: {}", endpoint, apiKey, apiSecret);
throw new RuntimeException(e);
}
byte[] hexDigits = mac.doFinal(preStr.getBytes(StandardCharsets.UTF_8));
// Base64加密
String sha = Base64.getEncoder().encodeToString(hexDigits);
// 拼接
String authorization = String.format("api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"", apiKey, "hmac-sha256", "host date request-line", sha);
// 拼接地址
HttpUrl httpUrl = Objects.requireNonNull(HttpUrl.parse("https://" + url.getHost() + url.getPath())).newBuilder().
addQueryParameter("authorization", Base64.getEncoder().encodeToString(authorization.getBytes(StandardCharsets.UTF_8))).
addQueryParameter("date", date).//
addQueryParameter("host", url.getHost()).//
build();
return httpUrl.toString();
}
@Override
public void afterPropertiesSet() throws Exception {
init();
}
}

@ -0,0 +1,28 @@
package cn.teammodel.ai;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* @author winter
* @create 2023-12-15 14:29
*/
@Data
@Configuration
@ConfigurationProperties(prefix = "spark.gpt")
public class SparkGptProperties {
private String endpoint;
private String appId;
private String apiKey;
private String apiSecret;
/**
*
*/
private Long cache_timeout;
/**
*
*/
private Integer cache_context;
}

@ -0,0 +1,30 @@
package cn.teammodel.ai;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
@UtilityClass
@Slf4j
public class SseHelper {
/**
* server client sse
*/
public void complete(SseEmitter sseEmitter) {
try {
sseEmitter.complete();
} catch (Exception e) {
}
}
/**
* client
*/
public void send(SseEmitter sseEmitter, Object data) {
try {
sseEmitter.send(data);
} catch (Exception e) {
log.error("sseEmitter send error", e);
}
}
}

@ -0,0 +1,62 @@
package cn.teammodel.ai.cache;
import cn.hutool.cache.CacheUtil;
import cn.hutool.cache.impl.TimedCache;
import cn.hutool.core.collection.ListUtil;
import cn.teammodel.model.entity.ai.ChatSession.Message;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import java.util.List;
/**
*
* @author winter
* @create 2023-12-20 11:02
*/
@Slf4j
@SuppressWarnings("unchecked")
public class HistoryCache {
private static TimedCache<Object, Object> HISTORY;
private static Integer contextSize = 3;
/**
*
*/
public static void init(Long timeout, Integer contextNum) {
contextSize = contextNum;
HISTORY = CacheUtil.newTimedCache(timeout);
// 一分钟清理一次
HISTORY.schedulePrune(60 * 1000);
}
public static List<Message> getContext(String sessionId) {
return (List<Message>) HISTORY.get(sessionId);
}
public static void putContext(String sessionId, List<Message> context) {
HISTORY.put(sessionId, context);
}
public static void removeContext(String sessionId) {
HISTORY.remove(sessionId);}
/**
* , contextSize
*/
public static void updateContext(String sessionId, Message message) {
List<Message> messages = (List<Message>)HISTORY.get(sessionId);
if (ObjectUtils.isEmpty(messages)) {
List<Message> context = ListUtil.of(message);
HISTORY.put(sessionId, context);
} else if (messages.size() >= contextSize) {
// 队列
messages.remove(0);
messages.add(message);
} else {
messages.add(message);
}
}
}

@ -0,0 +1,86 @@
package cn.teammodel.ai.domain;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Builder.Default;
import lombok.Data;
import java.util.List;
/**
* endpoint
* @author winter
* @create 2023-12-15 16:04
*/
@Data
@Builder
// 注意这两个注解一起使用会让无参构造丢失
public class SparkChatRequestParam {
//应用appid从开放平台控制台创建的应用中获取
private String appId;
//每个用户的id用于区分不同用户
private String uid;
//指定访问的领域,general指向V1.5版本 generalv2指向V2版本。注意不同的取值对应的url也不一样
@Default
private String domain = "generalv3";
//核采样阈值。用于决定结果随机性,取值越高随机性越强即相同的问题得到的不同答案的可能性越高
@Default
private Float temperature = 0.5F;
//模型回答的tokens的最大长度
@Default
private Integer maxTokens = 2048;
//从k个候选中随机选择⼀个⾮等概率
@Default
private Integer top_k = 4;
/**
* (sessionId)
*/
private String chatId;
private List<Message> messageList;
@Data
@AllArgsConstructor
public static class Message {
private String role;
private String content;
/**
* ,使,
*/
public static Message ofUser(String content){
return new Message("user",content);
}
public static Message ofAssistant(String content){
return new Message("assistant",content);
}
}
public String toJsonParams(){
ObjectMapper om = new ObjectMapper();
ObjectNode root = om.createObjectNode();
ObjectNode header = om.createObjectNode();
header.put("app_id",appId);
header.put("uid",uid);
ObjectNode parameter = om.createObjectNode();
ObjectNode chat = om.createObjectNode();
chat.put("domain", domain);
chat.put("temperature", temperature);
chat.put("max_tokens", maxTokens);
chat.put("top_k", top_k);
chat.put("chat_id", chatId);
parameter.set("chat", chat);
ObjectNode payload = om.createObjectNode();
payload.set("message", om.createObjectNode().putPOJO("text", messageList));
root.set("header", header);
root.set("parameter", parameter);
root.set("payload", payload);
return root.toString();
}
}

@ -0,0 +1,77 @@
package cn.teammodel.ai.domain;
import lombok.Data;
import java.util.List;
/**
* spark ws
* @Author: winter
*/
@Data
public class SparkChatResponse {
private Header header;
private Payload payload;
@Data
public static class Header{
/**
* 00
*/
private Integer code;
private String message;
private String sid;
/**
* [0,1,2]012
*/
private Integer status;
}
@Data
public static class Payload{
private Choices choices;
private Usage usage;
}
@Data
public static class Choices{
private Integer status;
private Integer seq;
private List<Text> text;
}
@Data
public static class Usage{
private UsageText text;
}
@Data
public static class UsageText{
private Integer question_tokens;
/**
* tokens
*/
private Integer prompt_tokens;
/**
* tokens
*/
private Integer completion_tokens;
/**
* prompt_tokenscompletion_tokenstokens
*/
private Integer total_tokens;
}
@Data
public static class Text{
/**
* AI
*/
private String content;
/**
* assistantAI
*/
private String role;
private Integer index;
}
}

@ -0,0 +1,95 @@
package cn.teammodel.ai.listener;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.teammodel.ai.SseHelper;
import cn.teammodel.ai.domain.SparkChatResponse;
import cn.teammodel.common.ErrorCode;
import cn.teammodel.config.exception.ServiceException;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import javax.annotation.Nullable;
import javax.validation.constraints.NotNull;
import java.util.function.Consumer;
/**
* okhttp ws listener
* @author winter
* @create 2023-12-15 16:17
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Slf4j
@RequiredArgsConstructor
public class SparkGptStreamListener extends WebSocketListener {
private final SseEmitter sseEmitter;
private String requestJson;
/**
*
*/
private String answer = "";
@Override
public void onOpen(WebSocket webSocket, @NotNull Response response) {
// ws 建立连接后发送请求的数据, 在 onMessage 中接受 server 的响应数据
webSocket.send(requestJson);
// 执行成功回调
try {
onOpen.accept(webSocket);
} catch (Exception e) {
this.onFailure(webSocket, e, response);
}
}
@Override
public void onMessage(WebSocket webSocket, String text) {
// 向 sse 推送消息(一次 onMessage 事件推送一次)
SparkChatResponse sparkChatResponse = JSONUtil.toBean(text, SparkChatResponse.class);
// 请求是否异常
if (sparkChatResponse.getHeader().getCode() != 0) {
this.onFailure(
webSocket,
new ServiceException(ErrorCode.SYSTEM_ERROR.getCode(),
sparkChatResponse.getHeader().getMessage()),
null
);
}
// 推送回答 segment
String msgSegment = sparkChatResponse.getPayload().getChoices().getText().get(0).getContent();
// 处理消息格式(空格和换行符)
// msgSegment = StrUtil.replace(msgSegment, " ", "&#32;").replaceAll("\n", "&#92n");
msgSegment = StrUtil.replace(msgSegment, " ", "&#32;").replaceAll("\n", "<br>");
answer += msgSegment;
SseHelper.send(sseEmitter, msgSegment);
// 处理模型的最终响应
if (sparkChatResponse.getHeader().getStatus() == 2) {
// 其实 spark 会主动断开连接
webSocket.close(1000, "done");
onComplete.accept(answer);
SseHelper.complete(sseEmitter);
}
}
@Override
public void onFailure(WebSocket webSocket, Throwable t, @Nullable Response response) {
webSocket.close(1000, t.getMessage());
this.onError.accept(t);
// 失败时结束 sse 连接
SseHelper.send(sseEmitter,t.getMessage() + "[DONE]");
SseHelper.complete(sseEmitter);
}
// 这几个 function 可以在 listener 被调用时设置, 实现类似事件的回调(可以使用模板方法模式实现)
protected Consumer<WebSocket> onOpen = (s) -> {};
protected Consumer<Throwable> onError = (s) -> {};
protected Consumer<String> onComplete = (s) -> {};
}

@ -0,0 +1,50 @@
package cn.teammodel.aop;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.UUID;
@Aspect
@Component
@Slf4j
public class LogInterceptor {
/**
*
*/
@Around("execution(* cn.teammodel.controller.*.*(..))")
public Object doInterceptor(ProceedingJoinPoint point) throws Throwable {
// 计时
StopWatch stopWatch = new StopWatch();
stopWatch.start();
// 获取请求路径
RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
HttpServletRequest httpServletRequest = ((ServletRequestAttributes) requestAttributes).getRequest();
// 生成请求唯一 id
String requestId = UUID.randomUUID().toString();
String url = httpServletRequest.getRequestURI();
// 获取请求参数
Object[] args = point.getArgs();
String reqParam = "[" + StringUtils.join(args, ", ") + "]";
// 输出请求日志
log.info("request startid: {}, path: {}, ip: {}, params: {}", requestId, url,
httpServletRequest.getRemoteHost(), reqParam);
// 执行原方法
Object result = point.proceed();
// 输出响应日志
stopWatch.stop();
long totalTimeMillis = stopWatch.getTotalTimeMillis();
log.info("request end, id: {}, cost: {}ms", requestId, totalTimeMillis);
return result;
}
}

@ -0,0 +1,46 @@
package cn.teammodel.common;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author winter
* @create 2024-02-01 15:30
*/
public enum ChatAppScopeEnum {
PUBLIC("public", "公共"),
SCHOOL("school", "学校"),
PRIVATE("private", "私人");
private final String code;
private final String name;
public static List<String> codes() {
return Arrays.stream(values()).map(ChatAppScopeEnum::getCode).collect(Collectors.toList());
}
/**
* name code
*/
public static String getCodeByName(String name) {
ChatAppScopeEnum chatAppScopeEnum = Arrays.stream(values()).filter(item -> item.getName().equals(name)).findFirst().orElse(null);
String res = null;
if (chatAppScopeEnum != null) {
res = chatAppScopeEnum.getCode();
}
return res;
}
ChatAppScopeEnum(String code, String name) {
this.code = code;
this.name = name;
}
public String getCode() {
return code;
}
public String getName() {
return name;
}
}

@ -0,0 +1,10 @@
package cn.teammodel.common;
/**
* @author winter
* @create 2023-11-29 14:26
*/
public interface CommonConstant {
String DASH = "-";
}

@ -0,0 +1,37 @@
package cn.teammodel.common;
public enum ErrorCode {
SUCCESS(200, "ok"),
PARAMS_ERROR(40000, "请求参数错误"),
NOT_LOGIN_ERROR(40100, "未登录"),
NO_AUTH_ERROR(40101, "无权限"),
NOT_FOUND_ERROR(40400, "请求数据不存在"),
FORBIDDEN_ERROR(40300, "禁止访问"),
SYSTEM_ERROR(50000, "系统内部异常"),
OPERATION_ERROR(50001, "操作失败");
/**
*
*/
private final int code;
/**
*
*/
private final String message;
ErrorCode(int code, String message) {
this.code = code;
this.message = message;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
}

@ -0,0 +1,50 @@
package cn.teammodel.common;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
*
* @author winter
* @create 2023-12-14 12:19
*/
public enum FiveEducations {
VIRTUE("virtue", "德育"),
INTELLIGENCE("intelligence","智育"),
SPORTS("sports", "体育"),
ART("art", "美育"),
LABOUR("labour", "劳育");
private final String code;
private final String name;
public static List<String> codes() {
return Arrays.stream(values()).map(FiveEducations::getCode).collect(Collectors.toList());
}
/**
* name code
*/
public static String getCodeByName(String name) {
FiveEducations fiveEducation = Arrays.stream(values()).filter(item -> item.getName().equals(name)).findFirst().orElse(null);
String res = null;
if (fiveEducation != null) {
res = fiveEducation.getCode();
}
return res;
}
FiveEducations(String code, String name) {
this.code = code;
this.name = name;
}
public String getCode() {
return code;
}
public String getName() {
return name;
}
}

@ -0,0 +1,15 @@
package cn.teammodel.common;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
* @author winter
* @create 2023-12-04 9:55
*/
@Data
public class IdRequest {
@NotBlank(message = "id 不能为空")
private String id;
}

@ -0,0 +1,49 @@
package cn.teammodel.common;
import com.azure.cosmos.models.PartitionKey;
/**
*
* @author winter
* @create 2023-11-22 15:31
*/
public interface PK {
/**
*
*/
String PK_APPRAISE = "Appraise";
/**
*
* : 1 , : SchoolId
*/
String PK_APPRAISE_RECORD = "AppraiseRecord-%s";
String COMMON_BASE = "Base";
String PK_LESSON_RECORD = "LessonRecord-%s";
/**
* , id
*/
String STUDENT = "Base-%s";
String CLASS = "Class-%s";
String CHAT_SESSION = "ChatSession";
String WEEK_DUTY = "Duty";
String WEEK_DUTY_RECORD = "DutyRecord-%s";
String CHAT_APP = "ChatApp";
String NEWS = "News-%s";
/**
*
*/
static PartitionKey of(String pk) {
return new PartitionKey(pk);
}
/**
* <br/>
* : ,
*/
static PartitionKey buildOf(String pk, String... args) {
String pkStr = String.format(pk, args);
return new PartitionKey(pkStr);
}
}

@ -0,0 +1,18 @@
package cn.teammodel.common;
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.List;
/**
* @author winter
* @create 2023-12-08 17:30
*/
@Data
@AllArgsConstructor
public class PageVo<T> {
private Integer totalPages;
private Long totalItems;
private List<T> content;
}

@ -0,0 +1,16 @@
package cn.teammodel.common;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author winter
* @create 2023-12-05 14:58
*/
@Data
public class PageableRequest {
@ApiModelProperty("当前页码, 默认: 0")
private Integer current = 0;
@ApiModelProperty("每页数量, 默认: 10")
private Integer size = 10;
}

@ -1,37 +1,48 @@
package cn.teammodel.common; package cn.teammodel.common;
public class R { import lombok.Data;
private Integer code;
import java.io.Serializable;
@Data
public class R<T> implements Serializable {
private int code;
private T data;
private String message; private String message;
private String data;
public R(Integer code, String message, String data) { public R(int code, T data, String message) {
this.code = code; this.code = code;
this.message = message;
this.data = data; this.data = data;
this.message = message;
} }
public Integer getCode() { public R(int code, T data) {
return code; this(code, data, "");
} }
public void setCode(Integer code) { public R(ErrorCode errorCode) {
this.code = code; this(errorCode.getCode(), null, errorCode.getMessage());
}
public R(ErrorCode errorCode, T data) {
this(errorCode.getCode(), data, errorCode.getMessage());
} }
public String getMessage() { public static <T> R<T> success(T data) {
return message; return new R<>(ErrorCode.SUCCESS, data);
} }
public void setMessage(String message) { public static <T> R<T> error(String msg) {
this.message = message; return new R<>(ErrorCode.SYSTEM_ERROR.getCode(), null, msg);
} }
public String getData() { public static <T> R<T> error(Integer code, String msg) {
return data; return new R<>(code, null, msg);
} }
public void setData(String data) { public static <T> R<T> error(ErrorCode errorCode) {
this.data = data; return new R<>(errorCode);
} }
} }

@ -0,0 +1,55 @@
package cn.teammodel.config;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
/**
* request inputstream controller
*/
public class BodyReaderRequestWrapper extends HttpServletRequestWrapper {
// 将流中的内容保存
private final byte[] buff;
public BodyReaderRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
// 将 body 中的内容读取到 buff 中
InputStream is = request.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] b = new byte[1024];
int len;
while ((len = is.read(b)) != -1) {
baos.write(b, 0, len);
}
buff = baos.toByteArray();
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream bais = new ByteArrayInputStream(buff);
return new ServletInputStream() {
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener listener) {
}
@Override
public int read() throws IOException {
return bais.read();
}
};
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
}
public String getRequestBody() {
return new String(buff);
}
}

@ -0,0 +1,41 @@
package cn.teammodel.config;
import cn.teammodel.config.intercepter.EnhanceRequestServletFilter;
import cn.teammodel.config.intercepter.UploadApiLogInterceptor;
import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.NotNull;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* WebMvc :
* @author winter
* @create 2024-01-15 17:06
*/
@Configuration
@RequiredArgsConstructor
public class WebMvcConfig implements WebMvcConfigurer {
private final UploadApiLogInterceptor uploadApiLogInterceptor;
/**
*
*/
@Override
public void addInterceptors(@NotNull InterceptorRegistry registry) {
registry.addInterceptor(uploadApiLogInterceptor);
}
// 注册过滤器
@Bean
public FilterRegistrationBean<EnhanceRequestServletFilter> filterRegistrationBean(){
FilterRegistrationBean<EnhanceRequestServletFilter> filterRegistrationBean=new FilterRegistrationBean<>();
filterRegistrationBean.setFilter(new EnhanceRequestServletFilter());
filterRegistrationBean.addUrlPatterns("/*");
//order的数值越小 则优先级越高,这里直接使用的最高优先级
filterRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return filterRegistrationBean;
}
}

@ -0,0 +1,126 @@
package cn.teammodel.config.exception;
import cn.teammodel.common.ErrorCode;
import cn.teammodel.common.R;
import cn.teammodel.manager.notification.NotificationService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingPathVariableException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
*
*
* @author ruoyi
*/
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
@Resource
private NotificationService notificationService;
/**
*
*/
@ExceptionHandler(ServiceException.class)
public R<?> handleServiceException(ServiceException e, HttpServletRequest request)
{
log.error(e.getMessage(), e);
Integer code = e.getCode();
return ObjectUtils.isNotEmpty(code) ? R.error(code, e.getMessage()) : R.error(e.getMessage());
}
@ExceptionHandler(HttpMessageNotReadableException.class)
public R<?> handleHttpMsgNotReadableException(HttpMessageNotReadableException e, HttpServletRequest request)
{
log.error(e.getMessage(), e);
return R.error(ErrorCode.PARAMS_ERROR.getCode(), "参数格式有误");
}
/**
*
*/
@ExceptionHandler(MissingPathVariableException.class)
public R<?> handleMissingPathVariableException(MissingPathVariableException e, HttpServletRequest request)
{
String requestURI = request.getRequestURI();
log.error("请求路径中缺少必需的路径变量'{}',发生系统异常.", requestURI, e);
return R.error(String.format("请求路径中缺少必需的路径变量[%s]", e.getVariableName()));
}
/**
*
*/
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
public R<?> handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e, HttpServletRequest request)
{
String requestURI = request.getRequestURI();
log.error("请求参数类型不匹配'{}',发生系统异常.", requestURI, e);
return R.error(String.format("请求参数类型不匹配,参数[%s]要求类型为:'%s',但输入值为:'%s'", e.getName(), e.getRequiredType().getName(), e.getValue()));
}
/**
*
*/
@ExceptionHandler(RuntimeException.class)
public R<?> handleRuntimeException(RuntimeException e, HttpServletRequest request)
{
String requestURI = request.getRequestURI();
log.error("请求地址'{}',发生未知异常.", requestURI, e);
notificationService.send("RuntimeException 告警: " + getCausesAsString(e, 5));
return R.error(ErrorCode.SYSTEM_ERROR);
}
/**
*
*/
@ExceptionHandler(Exception.class)
public R<?> handleException(Exception e, HttpServletRequest request)
{
String requestURI = request.getRequestURI();
log.error("请求地址'{}',发生系统异常.", requestURI, e);
notificationService.send("Exception 告警: " + getCausesAsString(e, 5));
return R.error(e.getMessage());
}
/**
*
*/
@ExceptionHandler(BindException.class)
public R<?> handleBindException(BindException e)
{
log.error(e.getMessage(), e);
String message = e.getAllErrors().get(0).getDefaultMessage();
return R.error(message);
}
/**
*
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public Object handleMethodArgumentNotValidException(MethodArgumentNotValidException e)
{
log.error(e.getMessage(), e);
String message = Objects.requireNonNull(e.getBindingResult().getFieldError()).getDefaultMessage();
return R.error(message);
}
private static String getCausesAsString(Throwable throwable, int maxDepth) {
return Stream.iterate(throwable, Throwable::getCause)
.limit(maxDepth)
.map(e -> e.getClass().getSimpleName() + ": " + e.getMessage())
.collect(Collectors.joining(" <- "));
}
}

@ -0,0 +1,76 @@
package cn.teammodel.config.exception;
import cn.teammodel.common.ErrorCode;
/**
*
*
* @author winter
*/
public final class ServiceException extends RuntimeException
{
private static final long serialVersionUID = 1L;
/**
*
*/
private Integer code;
/**
*
*/
private String message;
/**
*
*/
private String detailMessage;
/**
*
*/
public ServiceException() {}
public ServiceException(String message)
{
this.code = ErrorCode.SYSTEM_ERROR.getCode();
this.message = message;
}
public ServiceException(Integer code, String message) {
this.message = message;
this.code = code;
}
public ServiceException(ErrorCode errorCode) {
this.code = errorCode.getCode();
this.message = errorCode.getMessage();
}
public String getDetailMessage()
{
return detailMessage;
}
@Override
public String getMessage()
{
return message;
}
public Integer getCode()
{
return code;
}
public ServiceException setMessage(String message)
{
this.message = message;
return this;
}
public ServiceException setDetailMessage(String detailMessage)
{
this.detailMessage = detailMessage;
return this;
}
}

@ -0,0 +1,13 @@
package cn.teammodel.config.ies;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
@Getter
@Configuration
public class IESConfig {
@Value("${ies.server-url}")
private String serverUrl;
}

@ -0,0 +1,19 @@
package cn.teammodel.config.intercepter;
import cn.teammodel.config.BodyReaderRequestWrapper;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
public class EnhanceRequestServletFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 防止流读取一次后就没有了, 所以需要将流继续写出去
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
// 这里将原始request传入读出流并存储
ServletRequest requestWrapper = new BodyReaderRequestWrapper(httpServletRequest);
// 这里将原始request替换为包装后的request此后所有进入controller的request均为包装后的
filterChain.doFilter(requestWrapper, servletResponse);//
}
}

@ -0,0 +1,144 @@
package cn.teammodel.config.intercepter;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.jwt.JWTUtil;
import cn.teammodel.manager.notification.NotificationService;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.List;
/**
*
* @author winter
* @create 2024-03-18 10:00
*/
@Component
@Slf4j
public class UploadApiLogInterceptor implements HandlerInterceptor {
@Value("${spring.env}")
private String env;
@Resource
private NotificationService notificationService;
private final ObjectMapper mapper = new ObjectMapper();
@Override
public boolean preHandle(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler) throws Exception {
if (!env.equals("dev")) {
doUploadLog(request);
}
return true;
}
private void doUploadLog(@NotNull HttpServletRequest request) throws IOException {
String ip = ServletUtil.getClientIP(request);
String client = "";
String tokenSha = "";
String id = "";
String name = "";
String school = "";
String scope = "";
String referer = request.getHeader("Referer");
Long requestTime = Instant.now().toEpochMilli();
// 获取 json 请求参数(这里读了后,后面就再也读不到了,需要处理)
BufferedReader streamReader = new BufferedReader(new InputStreamReader(request.getInputStream(), StandardCharsets.UTF_8));
StringBuilder responseStrBuilder = new StringBuilder();
String inputStr;
while ((inputStr = streamReader.readLine()) != null)
responseStrBuilder.append(inputStr);
JsonNode jsonNode = mapper.readTree(responseStrBuilder.toString());
String xAuthToken = request.getHeader("x-auth-AuthToken");
// 如果有 authorization
String authorization = request.getHeader("Authorization");
if (StringUtils.isNotBlank(authorization)) {
authorization = authorization.replace("Bearer ", "");
List<String> roles = (List<String>) JWTUtil.parseToken(authorization).getPayload("roles");
if (ObjectUtils.isNotEmpty(roles)) {
client = roles.get(0);
}
tokenSha = SecureUtil.sha1("Bearer " + authorization);
}
String xAuthIdToken = request.getHeader("X-Auth-IdToken");
if (StringUtils.isNotBlank(xAuthIdToken)) {
id = (String) JWTUtil.parseToken(xAuthIdToken).getPayload("sub");
name = (String) JWTUtil.parseToken(xAuthIdToken).getPayload("name");
if (StringUtils.isNotBlank(tokenSha)) {
tokenSha = SecureUtil.sha1(xAuthIdToken);
}
}
String xAuthSchool = request.getHeader("X-Auth-School");
if (StringUtils.isNotBlank(xAuthSchool)) {
school = xAuthSchool;
}
if (StringUtils.isNotBlank(xAuthToken)) {
id = (String) JWTUtil.parseToken(xAuthToken).getPayload("sub");
name = (String) JWTUtil.parseToken(xAuthToken).getPayload("name");
school = (String) JWTUtil.parseToken(xAuthToken).getPayload("azp");
scope = (String) JWTUtil.parseToken(xAuthToken).getPayload("scope");
if (StringUtils.isNotBlank(tokenSha)) {
tokenSha = SecureUtil.sha1(xAuthToken);
}
}
ObjectNode root = mapper.createObjectNode();
root.put("ip", ip);
root.put("time", requestTime);
root.put("id", id);
root.put("name", name);
root.set("param", jsonNode);
root.put("school", school);
root.put("client", client);
root.put("tid", tokenSha);
root.put("scope", scope);
root.put("path", request.getContextPath() + request.getRequestURI());
root.put("host", request.getServerName());
root.put("p", "appraisal");
// 发送请求
// OkHttpClient okHttpClient = new OkHttpClient();
// String requestData = root.toString();
// RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), requestData);
// Request okRequest = new Request.Builder()
// .url("http://52.130.252.100:8806/api/http-log")
// .post(requestBody)
// .build();
//
// okHttpClient.newCall(okRequest).enqueue(new Callback() {
// @Override
// public void onFailure(Call call, IOException e) {
// log.error("UploadApiLogIntercepter error") ;
// notificationService.send("日志上传告警: 请求发送失败,检查请求发送客户端");
// }
//
// @Override
// public void onResponse(Call call, Response response) throws IOException {
// if (!response.isSuccessful()) {
// log.error("UploadApiLogIntercepter error" ) ;
// notificationService.send("日志上传告警: 请求响应异常,检查 API 源是否正常");
// } else {
// log.info("UploadApiLogIntercepter success");
// }
// }
// });
}
}

@ -0,0 +1,37 @@
package cn.teammodel.config.knife;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* Knife4j <br/>
* https://doc.xiaominfo.com/knife4j/documentation/get_start.html
*/
@Configuration
@EnableSwagger2
@Profile({"dev", "test"})
public class Knife4jConfig {
@Bean
public Docket defaultApi2() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(new ApiInfoBuilder()
.title("五育评价接口文档")
.description("五育评价接口描述")
.version("1.0.1")
.build())
.select()
// 指定 Controller 扫描包路径
.apis(RequestHandlerSelectors.basePackage("cn.teammodel.controller"))
.paths(PathSelectors.any())
.build();
}
}

@ -0,0 +1,34 @@
package cn.teammodel.config.redis;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
@Bean
public LettuceConnectionFactory dbConnectionFactory() {
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration("52.130.252.100", 6379);
config.setDatabase(8); // 设置数据库编号为8
config.setPassword("habook");
return new LettuceConnectionFactory(config);
}
@Bean
public StringRedisTemplate db1Template(LettuceConnectionFactory dbConnectionFactory) {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(dbConnectionFactory);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
return template;
}
}

@ -1,16 +0,0 @@
package cn.teammodel.controller;
import cn.teammodel.common.R;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/")
public class HelloController {
@GetMapping("hello")
public R helo() {
return new R(200, "sucess","hello world");
}
}

@ -0,0 +1,39 @@
package cn.teammodel.controller.admin.controller;
import cn.teammodel.common.R;
import cn.teammodel.controller.admin.service.AdminAppraiseService;
import cn.teammodel.model.dto.admin.appraise.UpdateAchievementRuleDto;
import cn.teammodel.model.entity.appraise.AchievementRule;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;
/**
* @author winter
* @create 2023-12-13 16:07
*/
@RestController
@RequestMapping("admin/appraise")
@Api(tags = "管理员端-学生评价管理")
public class AdminAppraiseController {
@Resource
private AdminAppraiseService adminAppraiseService;
@PostMapping("updateAchieveRule")
@ApiOperation("更新的 rule 节点将会直接覆盖老节点")
public R<List<AchievementRule>> updateAchieveRule(@RequestBody @Valid UpdateAchievementRuleDto ruleDto) {
List<AchievementRule> res = adminAppraiseService.updateAchieveRule(ruleDto);
return R.success(res);
}
@GetMapping("getAchieveRules/{periodId}")
@ApiOperation("获取当前学段下的成就规则")
public R<List<AchievementRule>> getAchieveRules(@PathVariable String periodId){
List<AchievementRule> res = adminAppraiseService.getAchieveRules(periodId);
return R.success(res);
}
}

@ -0,0 +1,80 @@
package cn.teammodel.controller.admin.controller;
import cn.teammodel.common.R;
import cn.teammodel.controller.admin.service.AdminIndexDutyService;
import cn.teammodel.model.dto.admin.appraise.TimeRangeDto;
import cn.teammodel.model.dto.admin.weekduty.AdminFindDutyRecordDto;
import cn.teammodel.model.dto.weekDuty.LessonRecordDto;
import cn.teammodel.model.vo.admin.AppraiseNodeRankVo;
import cn.teammodel.model.vo.admin.DutyIndexData;
import cn.teammodel.model.vo.admin.DutyNodeRankVo;
import cn.teammodel.model.vo.admin.DutyRankPo;
import cn.teammodel.model.vo.weekDuty.DutyRecordVo;
import cn.teammodel.service.DutyService;
import com.google.gson.JsonElement;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.List;
import java.util.Map;
/**
* @author winter
* @create 2024-01-09 17:59
*/
@RestController
@RequestMapping("admin/duty")
@Api(tags = "管理员端-值周巡检")
public class AdminDutyController {
@Resource
private DutyService dutyService;
@Resource
private AdminIndexDutyService adminIndexDutyService;
@PostMapping("records")
@ApiOperation("获取班级评价数据")
public R<List<DutyRecordVo>> findRecords(@Valid @RequestBody AdminFindDutyRecordDto adminFindDutyRecordDto) {
List<DutyRecordVo> res = dutyService.findAdminRecords(adminFindDutyRecordDto);
return R.success(res);
}
@PostMapping("index")
@ApiOperation("获取首页数据")
public R<DutyIndexData> index(@Valid @RequestBody TimeRangeDto timeRangeDto){
DutyIndexData dutyIndexData = adminIndexDutyService.getIndexData(timeRangeDto);
return R.success(dutyIndexData);
}
@PostMapping("classRank")
@ApiOperation("班级评价活跃排行榜: Top10")
public R<List<DutyRankPo>> classRank(@Valid @RequestBody TimeRangeDto timeRangeDto) {
List<DutyRankPo> res = adminIndexDutyService.classRank(timeRangeDto);
return R.success(res);
}
@PostMapping("teacherRank")
@ApiOperation("老师评价活跃排行榜: Top10")
public R<List<DutyRankPo>> teacherRank(@Valid @RequestBody TimeRangeDto timeRangeDto) {
List<DutyRankPo> res = adminIndexDutyService.teacherRank(timeRangeDto);
return R.success(res);
}
@PostMapping("dutyNodeRank")
@ApiOperation("评价指标活跃排行榜: Top10")
public R<List<DutyNodeRankVo>> appraiseNodeRank(@Valid @RequestBody TimeRangeDto timeRangeDto) {
List<DutyNodeRankVo> res = adminIndexDutyService.appraiseNodeRank(timeRangeDto);
return R.success(res);
}
@PostMapping("getLessonRecord")
@ApiOperation("获取课堂记录")
public R<Map<String, Object> > appraiseNodeRank(@Valid @RequestBody LessonRecordDto lessonRecordDto , HttpServletRequest request) {
Map<String, Object> res = adminIndexDutyService.getLessonRecord(lessonRecordDto,request);
return R.success(res);
}
}

@ -0,0 +1,67 @@
package cn.teammodel.controller.admin.controller;
import cn.teammodel.common.R;
import cn.teammodel.controller.admin.service.ArtService;
import cn.teammodel.model.dto.admin.art.ArtAnalysisDto;
import cn.teammodel.model.dto.admin.art.ArtFindDto;
import cn.teammodel.model.dto.admin.art.DataFileCommentDto;
import cn.teammodel.model.dto.admin.art.DataFileDto;
import cn.teammodel.model.dto.admin.common.GroupDto;
import cn.teammodel.model.dto.admin.common.RGroupList;
import cn.teammodel.model.vo.admin.ArtElementsVo;
import cn.teammodel.model.vo.admin.DataFileVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.List;
import java.util.Map;
/**
* @author zzzzz
* @since 2024-01-09 17:59
*/
@RestController
@RequestMapping("admin/art")
@Api(tags = "管理员端-艺术评测")
public class ArtController {
@Resource
private ArtService ArtService;
@PostMapping("getArtList")
@ApiOperation("获取当前学校艺术评测列表")
public R<List<ArtElementsVo>> findRecords(@Valid @RequestBody ArtFindDto artFindDto,HttpServletRequest request) {
List<ArtElementsVo> res = ArtService.getArtList(artFindDto,request);
return R.success(res);
}
@PostMapping("getGroupList")
@ApiOperation("获取当前学校指定成员名单详细信息")
public R<List<RGroupList>> findGroups(@Valid @RequestBody GroupDto groupDto, HttpServletRequest request) {
List<RGroupList> res = ArtService.getGroupList(groupDto,request);
return R.success(res);
}
@PostMapping("getPdfData")
@ApiOperation("请求学生的pdf数据文件")
public R<List<DataFileVo>> getPdfData(@Valid @RequestBody DataFileDto dataFileDto, HttpServletRequest request) {
List<DataFileVo> res = ArtService.getPdfData(dataFileDto,request);
return R.success(res);
}
@PostMapping("updateComment")
@ApiOperation("更新评论")
public R<List<DataFileVo>> updateComment(@Valid @RequestBody DataFileCommentDto dataFileCommentDto, HttpServletRequest request) {
List<DataFileVo> res = ArtService.updateComment(dataFileCommentDto,request);
return R.success(res);
}
@PostMapping("artAnalysis")
@ApiOperation("艺术评测校级看板分析")
public R<Map<String,Object>> getArtAnalysis(@Valid @RequestBody ArtAnalysisDto artAnalysisDto, HttpServletRequest request) {
Map<String, Object> res = ArtService.getArtAnalytics(artAnalysisDto,request);
return R.success(res);
}
}

@ -0,0 +1,31 @@
package cn.teammodel.controller.admin.controller;
import cn.teammodel.common.R;
import cn.teammodel.controller.admin.service.BlobService;
import cn.teammodel.model.dto.admin.exam.BlobSasDto;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.Map;
@RestController
@RequestMapping("admin/blob")
@Api(tags = "管理员-blob相关操作")
public class BlobController {
@Resource
private BlobService blobService;
@PostMapping("getBlobSas")
@ApiOperation("获取blob 读写权限")
public R<Map<String, Object>> getBlobSas(@Valid @RequestBody BlobSasDto blobSasDto, HttpServletRequest request) {
Map<String, Object> res = blobService.getBlobSas(blobSasDto,request);
return R.success(res);
}
}

@ -0,0 +1,51 @@
package cn.teammodel.controller.admin.controller;
import cn.teammodel.common.R;
import cn.teammodel.controller.admin.service.CommonService;
import cn.teammodel.model.dto.admin.common.CommentDto;
import cn.teammodel.model.dto.admin.common.GCDto;
import cn.teammodel.model.entity.common.Comment;
import cn.teammodel.model.vo.admin.GradeAndClassVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;
@RestController
@RequestMapping("admin/common")
@Api(tags = "管理员端-公共组件")
public class CommonController {
@Resource
private CommonService commonService ;
@PostMapping("getGradeAndClass")
@ApiOperation("获取当前学校当前学段年级班级信息")
public R<List<GradeAndClassVo>> findRecords(@Valid @RequestBody GCDto gcDto) {
List<GradeAndClassVo> res = commonService.getGradeAndClass(gcDto);
return R.success(res);
}
@PostMapping("save")
@ApiOperation("保存评语")
public R<Comment> saveOrUpdateComment(@Valid @RequestBody Comment comment) {
Comment res = commonService.saveOrUpdateComment(comment);
return R.success(res);
}
@PostMapping("delete")
@ApiOperation("删除评语")
public R<List<String>> deleteComment(@Valid @RequestBody CommentDto comment) {
List<String> res = commonService.deleteComment(comment);
return R.success(res);
}
@PostMapping("find")
@ApiOperation("根据ID查询评语")
public R<List<Comment>> findComment(@Valid @RequestBody Comment comment) {
List<Comment> res = commonService.getCommentById(comment);
return R.success(res);
}
}

@ -0,0 +1,59 @@
package cn.teammodel.controller.admin.controller;
import cn.teammodel.common.R;
import cn.teammodel.controller.admin.service.ExamService;
import cn.teammodel.model.dto.admin.art.ArtFindDto;
import cn.teammodel.model.dto.admin.exam.*;
import cn.teammodel.model.vo.admin.ArtElementsVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("admin/exam")
@Api(tags = "管理员端-智育分析")
public class ExamController {
@Resource
private ExamService examService;
@PostMapping("getOverView")
@ApiOperation("获取智育看板详细内容")
public R<Map<String, Object>> getOverView(@Valid @RequestBody OverViewDto overViewDto, HttpServletRequest request) {
Map<String, Object> res = examService.getAnalysis(overViewDto,request);
return R.success(res);
}
@PostMapping("getExamList")
@ApiOperation("获取该学校该学段全年评测数据")
public R<Map<String, Object>> getExamList(@Valid @RequestBody AnalysisDto analysisDto, HttpServletRequest request) {
Map<String, Object> res = examService.getExamList(analysisDto,request);
return R.success(res);
}
@PostMapping("getExamRecord")
@ApiOperation("获取该活动的作答记录")
public R<Map<String, Object>> getExamRecord(@Valid @RequestBody ExamRecordDto examRecordDto, HttpServletRequest request) {
Map<String, Object> res = examService.getExamRecord(examRecordDto,request);
return R.success(res);
}
@PostMapping("getExamSummary")
@ApiOperation("获取该活动详细信息和部分分析结果")
public R<Map<String, Object>> getExamSummary(@Valid @RequestBody FindExamDto findExamDto, HttpServletRequest request) {
Map<String, Object> res = examService.getExamSimpleAnalysis(findExamDto,request);
return R.success(res);
}
@PostMapping("getExamByStudent")
@ApiOperation("获取单个学生的简易分析结果")
public R<Map<String, Object>> getExamByStudent(@Valid @RequestBody FindByStudentDto findByStudentDto, HttpServletRequest request) {
Map<String, Object> res = examService.getExamByStudent(findByStudentDto,request);
return R.success(res);
}
}

@ -0,0 +1,68 @@
package cn.teammodel.controller.admin.controller;
import cn.teammodel.common.R;
import cn.teammodel.controller.admin.service.AdminAppraiseService;
import cn.teammodel.model.dto.admin.appraise.TimeRangeDto;
import cn.teammodel.model.vo.admin.*;
import cn.teammodel.model.vo.appraise.RecordVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;
/**
*
* @author winter
* &#064;create 2023-12-06 14:37
*/
@RestController
@RequestMapping("admin/index")
@Api(tags = "管理员端-首页数据")
public class IndexController {
@Resource
private AdminAppraiseService adminAppraiseService;
@PostMapping("/")
@ApiOperation("获取首页数据")
public R<AppraiseIndexData> index(@Valid @RequestBody TimeRangeDto timeRangeDto){
AppraiseIndexData appraiseIndexData = adminAppraiseService.getIndexData(timeRangeDto);
return R.success(appraiseIndexData);
}
@PostMapping("latestRecord")
@ApiOperation("查询时间范围最近评价(无参则当前周的所有记录)")
public R<List<RecordVo>> latestRecord(@Valid @RequestBody TimeRangeDto timeRangeDto) {
List<RecordVo> res = adminAppraiseService.conditionLatestRecord(timeRangeDto);
return R.success(res);
}
@PostMapping("classRank")
@ApiOperation("班级评价活跃排行榜: Top10")
public R<List<RankPo>> classRank(@Valid @RequestBody TimeRangeDto timeRangeDto) {
List<RankPo> res = adminAppraiseService.classRank(timeRangeDto);
return R.success(res);
}
@PostMapping("studentRank")
@ApiOperation("学生评价活跃排行榜: Top10")
public R<List<StudentRankVo>> studentRank(@Valid @RequestBody TimeRangeDto timeRangeDto) {
List<StudentRankVo> res = adminAppraiseService.studentRank(timeRangeDto);
return R.success(res);
}
@PostMapping("teacherRank")
@ApiOperation("老师评价活跃排行榜: Top10")
public R<List<RankVo>> teacherRank(@Valid @RequestBody TimeRangeDto timeRangeDto) {
List<RankVo> res = adminAppraiseService.teacherRank(timeRangeDto);
return R.success(res);
}
@PostMapping("appraiseNodeRank")
@ApiOperation("评价指标活跃排行榜: Top10")
public R<List<AppraiseNodeRankVo>> appraiseNodeRank(@Valid @RequestBody TimeRangeDto timeRangeDto) {
List<AppraiseNodeRankVo> res = adminAppraiseService.appraiseNodeRank(timeRangeDto);
return R.success(res);
}
}

@ -0,0 +1,26 @@
package cn.teammodel.controller.admin.controller;
import cn.teammodel.common.R;
import cn.teammodel.test.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.Map;
@RestController
@RequestMapping("/test")
public class RedisController {
private final RedisService redisService;
@Autowired
public RedisController(RedisService redisService) {
this.redisService = redisService;
}
@PostMapping("/redis")
public Map<Object, Object> getValueByKey(@RequestBody @Valid String key) {
Map<Object,Object> juri = redisService.getValueByKey(key);
return R.success(juri).getData();
}
}

@ -0,0 +1,79 @@
package cn.teammodel.controller.admin.controller;
import cn.teammodel.common.R;
import cn.teammodel.controller.admin.service.TeacherService;
import cn.teammodel.model.dto.admin.exam.ExamRecordDto;
import cn.teammodel.model.dto.admin.exam.OverViewDto;
import cn.teammodel.model.dto.admin.teacher.TeacherDto;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("admin/teacher")
@Api(tags = "教师相关接口内容")
public class TeacherController {
@Resource
private TeacherService teacherService;
@PostMapping("getCount")
@ApiOperation("获取教师基础数据统计内容")
public R<List<Map<String, Integer>>> getCount(@Valid @RequestBody TeacherDto teacherDto) {
List<Map<String, Integer>> res = teacherService.getTeacherList(teacherDto);
return R.success(res);
}
@PostMapping("getTeacherDetail")
@ApiOperation("获取教师详细数据")
public R<Map<String, Object>> getTeacherDetail(@Valid @RequestBody TeacherDto teacherDto, HttpServletRequest request) {
Map<String, Object> res = teacherService.getTeacherDetail(teacherDto,request);
return R.success(res);
}
@PostMapping("getTeacherCountRecordOfWeek")
@ApiOperation("获取当前学期指定教师每周课程数")
public R<Map<Long, Integer>> getTeacherCountRecordOfWeek(@Valid @RequestBody TeacherDto teacherDto) {
Map<Long, Integer> res = teacherService.getTeacherByRecord(teacherDto);
return R.success(res);
}
@PostMapping("getTeacherLearningCategoryCount")
@ApiOperation("获取指定教师教学法统计")
public R<Map<String, Object>> getTeacherLearningCategoryCount(@Valid @RequestBody TeacherDto teacherDto) {
Map<String, Object> res = teacherService.getTeacherLearningCategory(teacherDto);
return R.success(res);
}
@PostMapping("getTeacherGradeCount")
@ApiOperation("获取年级人数以及分配情况")
public R<Map<String, Object>> getTeacherGradeCount(@Valid @RequestBody TeacherDto teacherDto, HttpServletRequest request) {
Map<String, Object> res = teacherService.getTeacherGradeCount(teacherDto,request);
return R.success(res);
}
@PostMapping("getDistributionOfTeachers")
@ApiOperation("获取教师分布情况")
public R<List<Map<String,Map<String, Long>>>> getDistributionOfTeachers(@Valid @RequestBody TeacherDto teacherDto, HttpServletRequest request) {
List<Map<String,Map<String, Long>>> res = teacherService.getDistributionOfTeachers(teacherDto,request);
return R.success(res);
}
@PostMapping("getTeachingAndResearch")
@ApiOperation("获取教师教研数据")
public R<Map<String,Object>> getTeachingAndResearch(@Valid @RequestBody TeacherDto teacherDto, HttpServletRequest request) {
Map<String,Object> res = teacherService.getTeachingAndResearch(teacherDto,request);
return R.success(res);
}
@PostMapping("getTeachingOfTeacher")
@ApiOperation("获取教师教学法数据")
public R<List<LinkedHashMap<String, LinkedHashMap<String,Object>>> > getTeachingOfTeacher(@Valid @RequestBody TeacherDto teacherDto, HttpServletRequest request) {
List<LinkedHashMap<String,LinkedHashMap<String,Object>>> res = teacherService.getTeachingOfTeacher(teacherDto,request);
return R.success(res);
}
}

@ -0,0 +1,34 @@
package cn.teammodel.controller.admin.service;
import cn.teammodel.model.dto.admin.appraise.TimeRangeDto;
import cn.teammodel.model.dto.admin.appraise.UpdateAchievementRuleDto;
import cn.teammodel.model.entity.appraise.AchievementRule;
import cn.teammodel.model.vo.admin.*;
import cn.teammodel.model.vo.appraise.RecordVo;
import java.util.List;
/**
* @author winter
* @create 2023-12-06 14:45
*/
public interface AdminAppraiseService {
AppraiseIndexData getIndexData(TimeRangeDto timeRangeDto);
/**
*
*/
List<RecordVo> conditionLatestRecord(TimeRangeDto timeRangeDto);
List<RankPo> classRank(TimeRangeDto timeRangeDto);
List<RankVo> teacherRank(TimeRangeDto timeRangeDto);
List<AppraiseNodeRankVo> appraiseNodeRank(TimeRangeDto timeRangeDto);
List<StudentRankVo> studentRank(TimeRangeDto timeRangeDto);
List<AchievementRule> updateAchieveRule(UpdateAchievementRuleDto ruleDto);
List<AchievementRule> getAchieveRules(String periodId);
}

@ -0,0 +1,29 @@
package cn.teammodel.controller.admin.service;
import cn.teammodel.model.dto.admin.appraise.TimeRangeDto;
import cn.teammodel.model.dto.weekDuty.LessonRecordDto;
import cn.teammodel.model.vo.admin.DutyIndexData;
import cn.teammodel.model.vo.admin.DutyNodeRankVo;
import cn.teammodel.model.vo.admin.DutyRankPo;
import com.google.gson.JsonElement;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
/**
* @author winter
* @create 2024-02-28 15:07
*/
public interface AdminIndexDutyService {
DutyIndexData getIndexData(TimeRangeDto timeRangeDto);
List<DutyRankPo> classRank(TimeRangeDto timeRangeDto);
List<DutyRankPo> teacherRank(TimeRangeDto timeRangeDto);
List<DutyNodeRankVo> appraiseNodeRank(TimeRangeDto timeRangeDto);
Map<String, Object> getLessonRecord (LessonRecordDto lessonRecordDto, HttpServletRequest request);
}

@ -0,0 +1,22 @@
package cn.teammodel.controller.admin.service;
import cn.teammodel.model.dto.admin.art.ArtAnalysisDto;
import cn.teammodel.model.dto.admin.art.ArtFindDto;
import cn.teammodel.model.dto.admin.art.DataFileCommentDto;
import cn.teammodel.model.dto.admin.art.DataFileDto;
import cn.teammodel.model.dto.admin.common.GroupDto;
import cn.teammodel.model.dto.admin.common.RGroupList;
import cn.teammodel.model.vo.admin.ArtElementsVo;
import cn.teammodel.model.vo.admin.DataFileVo;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
public interface ArtService {
List<ArtElementsVo> getArtList(ArtFindDto artFindDto, HttpServletRequest request);
List<RGroupList> getGroupList(GroupDto groupDto, HttpServletRequest request);
List<DataFileVo> getPdfData(DataFileDto dataFileDto,HttpServletRequest request);
List<DataFileVo> updateComment(DataFileCommentDto dataFileCommentDto, HttpServletRequest request);
Map<String,Object> getArtAnalytics(ArtAnalysisDto artAnalysisDto, HttpServletRequest request);
}

@ -0,0 +1,10 @@
package cn.teammodel.controller.admin.service;
import cn.teammodel.model.dto.admin.exam.BlobSasDto;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
public interface BlobService {
Map<String,Object> getBlobSas(BlobSasDto blobSasDto, HttpServletRequest request);
}

@ -0,0 +1,15 @@
package cn.teammodel.controller.admin.service;
import cn.teammodel.model.dto.admin.common.CommentDto;
import cn.teammodel.model.dto.admin.common.GCDto;
import cn.teammodel.model.entity.common.Comment;
import cn.teammodel.model.vo.admin.GradeAndClassVo;
import org.springframework.stereotype.Service;
import java.util.List;
public interface CommonService {
List<GradeAndClassVo> getGradeAndClass(GCDto gcDto);
Comment saveOrUpdateComment(Comment comment);
List<String> deleteComment(CommentDto comment);
List<Comment> getCommentById(Comment comment);
}

@ -0,0 +1,14 @@
package cn.teammodel.controller.admin.service;
import cn.teammodel.model.dto.admin.exam.*;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
public interface ExamService {
Map<String,Object> getAnalysis(OverViewDto overViewDto, HttpServletRequest request);
Map<String,Object> getExamList(AnalysisDto analysisDto, HttpServletRequest request);
Map<String,Object> getExamSimpleAnalysis(FindExamDto findExamDto, HttpServletRequest request);
Map<String,Object> getExamRecord(ExamRecordDto examRecordDto, HttpServletRequest request);
Map<String,Object> getExamByStudent(FindByStudentDto findByStudentDto, HttpServletRequest request);
}

@ -0,0 +1,20 @@
package cn.teammodel.controller.admin.service;
import cn.teammodel.model.dto.admin.teacher.GpTeacherDto;
import cn.teammodel.model.dto.admin.teacher.TeacherDto;
import javax.servlet.http.HttpServletRequest;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public interface TeacherService {
List<Map<String,Integer>> getTeacherList(TeacherDto teacherDto);
Map<String,Object> getTeacherDetail(TeacherDto teacherDto, HttpServletRequest request);
Map<Long, Integer> getTeacherByRecord(TeacherDto teacherDto);
Map<String,Object> getTeacherLearningCategory(TeacherDto teacherDto);
Map<String,Object> getTeacherGradeCount(TeacherDto teacherDto, HttpServletRequest request);
List<Map<String,Map<String, Long>>> getDistributionOfTeachers(TeacherDto teacherDto, HttpServletRequest request);
Map<String,Object> getTeachingAndResearch(TeacherDto teacherDto, HttpServletRequest request);
List<LinkedHashMap<String, LinkedHashMap<String,Object>>> getTeachingOfTeacher(TeacherDto teacherDto, HttpServletRequest request);
}

@ -0,0 +1,412 @@
package cn.teammodel.controller.admin.service.impl;
import cn.teammodel.common.ErrorCode;
import cn.teammodel.common.PK;
import cn.teammodel.config.exception.ServiceException;
import cn.teammodel.controller.admin.service.AdminAppraiseService;
import cn.teammodel.repository.*;
import cn.teammodel.model.dto.admin.appraise.TimeRangeDto;
import cn.teammodel.model.dto.admin.appraise.UpdateAchievementRuleDto;
import cn.teammodel.model.entity.User;
import cn.teammodel.model.entity.appraise.AchievementRule;
import cn.teammodel.model.entity.appraise.Appraise;
import cn.teammodel.model.entity.appraise.AppraiseTreeNode;
import cn.teammodel.model.entity.school.ClassInfo;
import cn.teammodel.model.entity.school.School;
import cn.teammodel.model.entity.school.Student;
import cn.teammodel.model.entity.school.Teacher;
import cn.teammodel.model.vo.admin.*;
import cn.teammodel.model.vo.appraise.RecordVo;
import cn.teammodel.security.utils.SecurityUtil;
import cn.teammodel.utils.RepositoryUtil;
import cn.teammodel.utils.SchoolDateUtil;
import com.azure.cosmos.models.CosmosPatchOperations;
import com.azure.cosmos.models.PartitionKey;
import com.azure.spring.data.cosmos.core.query.CosmosPageRequest;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Slice;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.time.*;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;
import static cn.teammodel.utils.SchoolDateUtil.calculateWeekNum;
/**
* @author winter
* &#064;create 2023-12-06 14:46
*/
@Service
public class AdminAppraiseServiceImpl implements AdminAppraiseService {
@Resource
private SchoolRepository schoolRepository;
@Resource
private ClassRepository classRepository;
@Resource
private TeacherRepository teacherRepository;
@Resource
private AppraiseRepository appraiseRepository;
@Resource
private StudentRepository studentRepository;
@Resource
private AppraiseRecordRepository appraiseRecordRepository;
@Override
public AppraiseIndexData getIndexData(TimeRangeDto timeRangeDto) {
final int SLICE_SIZE = 100;
if (StringUtils.isBlank(timeRangeDto.getPeriodId())) {
throw new ServiceException(ErrorCode.PARAMS_ERROR.getCode(), "不能为空");
}
final AppraiseIndexData appraiseIndexData = new AppraiseIndexData();
int totalCount = 0;
int criticalCount = 0;
Set<String> creatorIdSet = new HashSet<>();
Set<String> studentSet = new HashSet<>();
User loginUser = SecurityUtil.getLoginUser();
String schoolId = loginUser.getSchoolId();
// 获取学期起止时间
List<School.Semester> semesters = schoolRepository.findSemestersById(schoolId, timeRangeDto.getPeriodId());
SchoolDateUtil.semesterModel semesterModel = SchoolDateUtil.getSemesterByNow(semesters, LocalDate.now());
LocalDateTime startDatetime = null;
LocalDateTime endDatetime = null;
String academicYearId = null;
if(timeRangeDto.getStartTime() != null) {
startDatetime = LocalDateTime.ofInstant(Instant.ofEpochMilli(timeRangeDto.getStartTime()), ZoneId.systemDefault());
endDatetime = LocalDateTime.ofInstant(Instant.ofEpochMilli(timeRangeDto.getEndTime()), ZoneId.systemDefault());
academicYearId = timeRangeDto.getAcademicYearId();
}else {
academicYearId = semesterModel.getAcademicYearId();
startDatetime = semesterModel.getStartDatetime();
endDatetime = semesterModel.getEndDatetime();
}
if (startDatetime == null || endDatetime == null) throw new ServiceException(ErrorCode.PARAMS_ERROR);
long totalWeek = calculateWeekNum(startDatetime, endDatetime, null);
// slice 分段读取
CosmosPageRequest pageRequest = new CosmosPageRequest(0, SLICE_SIZE, null);
Slice<RecordVo> slice;
Map<Long, Integer> countByWeek = SchoolDateUtil.createEmptyWeekMap(totalWeek);
do {
slice = appraiseRecordRepository.findAllByAcademicYearId(String.format(PK.PK_APPRAISE_RECORD, schoolId), academicYearId, pageRequest);
List<RecordVo> content = slice.getContent();
if (ObjectUtils.isEmpty(content)) {
break;
}
// 分批次计算
for (RecordVo item : content) {
// 处理每周的评价数
long weekNum = calculateWeekNum(startDatetime, endDatetime, item.getCreateTime());
countByWeek.put(weekNum, countByWeek.getOrDefault(weekNum, 0) + 1);
// 处理总评价数
totalCount++;
// 处理批评数
if (!item.isPraise()) {
criticalCount++;
}
// 处理已评价老师总数
creatorIdSet.add(item.getCreatorId());
// 处理被评价的学生数
if ("student".equals(item.getTargetType())) {
studentSet.add(item.getTargetId());
}
}
if (slice.hasNext()) {
pageRequest = (CosmosPageRequest) slice.nextPageable();
}
} while (slice.hasNext());
// 组装数据
appraiseIndexData.setCountByWeek(countByWeek);
appraiseIndexData.setTotalCount(totalCount);
appraiseIndexData.setCriticalCount(criticalCount);
appraiseIndexData.setPraiseCount(totalCount - criticalCount);
appraiseIndexData.setTeacherCount(creatorIdSet.size());
appraiseIndexData.setStudentCount(studentSet.size());
return appraiseIndexData;
}
@Override
public List<RecordVo> conditionLatestRecord(TimeRangeDto timeRangeDto) {
Long startTime = timeRangeDto.getStartTime();
Long endTime = timeRangeDto.getEndTime();
String academicYearId = timeRangeDto.getAcademicYearId();
String schoolId = SecurityUtil.getLoginUser().getSchoolId();
// fixme: 是否对时间范围做一些限制(不能确保当前周有数据)
// 无参默认当前周
if (startTime == null || endTime == null) {
// 将时间范围调整为当前周的周一到当前时间
LocalDateTime mondayOfCurWeek = LocalDateTime.now().with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY))
.withHour(0)
.withMinute(0)
.withSecond(0)
.withNano(0);
startTime = mondayOfCurWeek.atZone(ZoneOffset.systemDefault()).toInstant().toEpochMilli();
endTime = Instant.now().toEpochMilli();
}
List<RecordVo> res = appraiseRecordRepository.latestRecords(
String.format(PK.PK_APPRAISE_RECORD, schoolId),
academicYearId,
startTime,
endTime
);
if (res != null) {
res = res.stream().sorted((o1, o2) -> o2.getCreateTime().compareTo(o1.getCreateTime())).collect(Collectors.toList());
}
return res;
}
@Override
public List<RankPo> classRank(TimeRangeDto timeRangeDto) {
// todo 不要 page| 批评和表扬数量
Long startTime = timeRangeDto.getStartTime();
Long endTime = timeRangeDto.getEndTime();
String academicYearId = timeRangeDto.getAcademicYearId();
String schoolId = SecurityUtil.getLoginUser().getSchoolId();
List<RankPo> rankPoList = appraiseRecordRepository.classRank(
String.format(PK.PK_APPRAISE_RECORD, schoolId),
academicYearId,
startTime,
endTime
);
if (ObjectUtils.isEmpty(rankPoList)) return null;
Set<String> classIdSet = rankPoList.stream().map(RankPo::getId).collect(Collectors.toSet());
// 注意: 如果查询 in 的查询集在数据库中不存在,则在结果集也不会为 null.
if (ObjectUtils.isEmpty(classIdSet)) return rankPoList;
List<ClassInfo> classes = classRepository.findAllByCodeAndIdIn(String.format(PK.CLASS, schoolId), classIdSet);
Map<String, String> idNameMap = classes.stream().collect(Collectors.toMap(ClassInfo::getId, ClassInfo::getName));
rankPoList.forEach(rankVo -> rankVo.setName(idNameMap.get(rankVo.getId())));
return rankPoList;
}
@Override
public List<RankVo> teacherRank(TimeRangeDto timeRangeDto) {
Long startTime = timeRangeDto.getStartTime();
Long endTime = timeRangeDto.getEndTime();
String academicYearId = timeRangeDto.getAcademicYearId();
String schoolId = SecurityUtil.getLoginUser().getSchoolId();
List<RankPo> rankPoList = appraiseRecordRepository.teacherRank(
String.format(PK.PK_APPRAISE_RECORD, schoolId),
academicYearId,
startTime,
endTime
);
// 根据 id 分组
Map<String, List<RankPo>> idRankPoMap = rankPoList.stream().collect(Collectors.groupingBy(RankPo::getId));
final List<RankVo> rankVos = new ArrayList<>();
idRankPoMap.forEach((id, list) -> {
RankVo rankVo = new RankVo();
int praiseCount = 0;
int criticalCount = 0;
rankVo.setId(id);
for (RankPo po : list) {
if (po.getIsPraise()) {
praiseCount += po.getCount();
} else {
criticalCount += po.getCount();
}
}
rankVo.setPraiseCount(praiseCount);
rankVo.setCriticalCount(criticalCount);
rankVo.setTotalCount(praiseCount + criticalCount);
rankVos.add(rankVo);
});
// 排序
List<RankVo> res = rankVos.stream()
.sorted(Comparator.comparing(RankVo::getTotalCount).reversed())
.collect(Collectors.toList());
// 设置 name
if (ObjectUtils.isEmpty(res)) return null;
Set<String> teacherIdSet = res.stream().map(RankVo::getId).collect(Collectors.toSet());
if (ObjectUtils.isEmpty(teacherIdSet)) return res;
List<Teacher> teachers = teacherRepository.findAllByCodeAndIdIn(PK.COMMON_BASE, teacherIdSet);
Map<String, String> idNameMap = teachers.stream().collect(Collectors.toMap(Teacher::getId, Teacher::getName));
res.forEach(rankVo -> rankVo.setName(idNameMap.get(rankVo.getId())));
return res;
}
@Override
public List<AppraiseNodeRankVo> appraiseNodeRank(TimeRangeDto timeRangeDto) {
Long startTime = timeRangeDto.getStartTime();
Long endTime = timeRangeDto.getEndTime();
String academicYearId = timeRangeDto.getAcademicYearId();
String schoolId = SecurityUtil.getLoginUser().getSchoolId();
List<AppraiseNodeRankVo> rankVoList = appraiseRecordRepository.appraiseNodeRank(
String.format(PK.PK_APPRAISE_RECORD, schoolId),
academicYearId,
startTime,
endTime
);
if (rankVoList == null) return null;
List<String> names = rankVoList.stream().map(AppraiseNodeRankVo::getName).collect(Collectors.toList());
if (ObjectUtils.isEmpty(names)) return null;
// 去重后的 nodes
List<AppraiseTreeNode> nodesByName = appraiseRecordRepository.findAppraiseRecordInNames(String.format(PK.PK_APPRAISE_RECORD, schoolId), academicYearId, names);
// 正常情况下 name 一一对应 todo: 临时解决
Map<String, AppraiseTreeNode> nameNodeMap = nodesByName.stream()
.collect(Collectors.toMap(AppraiseTreeNode::getName, item -> item, (existing, replacement) -> {
if (replacement.getPath() != null) {
return replacement;
}
return existing;
}));
rankVoList = rankVoList.stream()
.sorted(Comparator.comparing(RankPo::getCount).reversed())
// 流中对元素操作但不改变流
.peek(s -> {
AppraiseTreeNode node = nameNodeMap.get(s.getName());
if (node != null) {
s.setPath(node.getPath());
s.setIsPraise(node.isPraise());
}
})
.collect(Collectors.toList());
return rankVoList;
}
@Override
public List<StudentRankVo> studentRank(TimeRangeDto timeRangeDto) {
Long startTime = timeRangeDto.getStartTime();
Long endTime = timeRangeDto.getEndTime();
String academicYearId = timeRangeDto.getAcademicYearId();
String schoolId = SecurityUtil.getLoginUser().getSchoolId();
List<RankPo> rankPoList = appraiseRecordRepository.studentRank(
String.format(PK.PK_APPRAISE_RECORD, schoolId),
academicYearId,
startTime,
endTime
);
// 根据 id 分组
Map<String, List<RankPo>> idRankPoMap = rankPoList.stream().collect(Collectors.groupingBy(RankPo::getId));
final List<StudentRankVo> rankVos = new ArrayList<>();
idRankPoMap.forEach((id, list) -> {
StudentRankVo rankVo = new StudentRankVo();
int praiseCount = 0;
int criticalCount = 0;
rankVo.setId(id);
for (RankPo po : list) {
if (po.getIsPraise()) {
praiseCount += po.getCount();
} else {
criticalCount += po.getCount();
}
}
rankVo.setPraiseCount(praiseCount);
rankVo.setCriticalCount(criticalCount);
rankVo.setTotalCount(praiseCount + criticalCount);
rankVos.add(rankVo);
});
// 排序
List<StudentRankVo> res = rankVos.stream()
.sorted(Comparator.comparing(StudentRankVo::getTotalCount).reversed())
.collect(Collectors.toList());
// 设置 student name
if (ObjectUtils.isEmpty(res)) return null;
Set<String> studentIdSet = res.stream().map(StudentRankVo::getId).collect(Collectors.toSet());
if (ObjectUtils.isEmpty(studentIdSet)) return res;
List<Student> students = studentRepository.findAllByCodeAndIdIn(String.format(PK.STUDENT, schoolId), studentIdSet);
// 利用数组作为三元组,提取 Student 中的 name 和 classId, picture
Map<String, String[]> idNameMap = students.stream().collect(Collectors.toMap(Student::getId, item -> {
String[] studentInfo = new String[3];
studentInfo[0] = item.getName();
studentInfo[1] = item.getClassId();
studentInfo[2] = item.getPicture();
return studentInfo;
}));
res.forEach(rankVo -> {
rankVo.setName(idNameMap.get(rankVo.getId())[0]);
rankVo.setClassName(idNameMap.get(rankVo.getId())[1]);
rankVo.setPicture(idNameMap.get(rankVo.getId())[2]);
});
// 设置 class name
Set<String> classIds = students.stream().map(Student::getClassId).collect(Collectors.toSet());
List<ClassInfo> classes = classRepository.findAllByCodeAndIdIn(String.format(PK.CLASS, schoolId), classIds);
Map<String, String> idClassNameMap = classes.stream().collect(Collectors.toMap(ClassInfo::getId, ClassInfo::getName));
res.forEach(rankVo -> rankVo.setClassName(idClassNameMap.getOrDefault(rankVo.getClassName(), null)));
return res;
}
@Override
public List<AchievementRule> updateAchieveRule(UpdateAchievementRuleDto ruleDto) {
String periodId = ruleDto.getPeriodId();
UpdateAchievementRuleDto.UpdateRule updateRule = ruleDto.getUpdateRule();
if (ObjectUtils.isEmpty(updateRule) || StringUtils.isBlank(updateRule.getId()) || ObjectUtils.isEmpty(updateRule.getName())) {
throw new ServiceException(ErrorCode.PARAMS_ERROR.getCode(), "rule id/name 不能为空");
}
if (updateRule.getLevelCount() == null || updateRule.getLevelCount() <= 0 || updateRule.getPromotionLevel() == null || updateRule.getPromotionLevel() <= 0) {
throw new ServiceException(ErrorCode.PARAMS_ERROR.getCode(), "规则不能为空或小于等于0");
}
User user = SecurityUtil.getLoginUser();
String schoolId = user.getSchoolId();
Appraise appraise = RepositoryUtil.findOne(appraiseRepository.findRulesById(schoolId, periodId), "参数错误,找不到该学段下的评价规则");
List<AchievementRule> rules = appraise.getAchievementRules();
if (ObjectUtils.isEmpty(rules)) {
throw new ServiceException(ErrorCode.OPERATION_ERROR.getCode(), "该学段暂无没有成就规则");
}
// sort rules by level
rules = rules.stream().sorted(Comparator.comparing(AchievementRule::getLevel)).collect(Collectors.toList());
boolean flag = false;
int lastPromotionCount = 0;
for (AchievementRule rule : rules) {
if (updateRule.getId().equals(rule.getId())) {
BeanUtils.copyProperties(updateRule, rule);
lastPromotionCount = rule.getLevelCount() * rule.getPromotionLevel();
rule.setPromotionCount(lastPromotionCount);
flag = true;
continue;
}
// 处理后面的节点,将 promotionCount 依次修改
if (flag) {
lastPromotionCount = lastPromotionCount + rule.getLevelCount() * rule.getPromotionLevel();
rule.setPromotionCount(lastPromotionCount);
}
}
CosmosPatchOperations operations = CosmosPatchOperations.create().replace("/achievementRules", rules);
Appraise saved = appraiseRepository.save(appraise.getId(), new PartitionKey(PK.PK_APPRAISE), Appraise.class, operations);
return saved.getAchievementRules();
}
@Override
public List<AchievementRule> getAchieveRules(String periodId) {
User user = SecurityUtil.getLoginUser();
String schoolId = user.getSchoolId();
Appraise appraise = RepositoryUtil.findOne(appraiseRepository.findRulesById(schoolId, periodId), "还未创建该学段下的评价规则");
List<AchievementRule> rules = appraise.getAchievementRules();
if (ObjectUtils.isEmpty(rules)) {
rules = Collections.emptyList();
}
return rules;
}
}

@ -0,0 +1,237 @@
package cn.teammodel.controller.admin.service.impl;
import cn.teammodel.common.ErrorCode;
import cn.teammodel.common.PK;
import cn.teammodel.config.exception.ServiceException;
import cn.teammodel.controller.admin.service.AdminIndexDutyService;
import cn.teammodel.model.dto.admin.appraise.TimeRangeDto;
import cn.teammodel.model.dto.weekDuty.LessonRecordDto;
import cn.teammodel.model.entity.User;
import cn.teammodel.model.entity.school.ClassInfo;
import cn.teammodel.model.entity.school.School;
import cn.teammodel.model.entity.school.Teacher;
import cn.teammodel.model.entity.weekDuty.WeekDuty;
import cn.teammodel.model.vo.admin.DutyIndexData;
import cn.teammodel.model.vo.admin.DutyIndexPo;
import cn.teammodel.model.vo.admin.DutyNodeRankVo;
import cn.teammodel.model.vo.admin.DutyRankPo;
import cn.teammodel.repository.ClassRepository;
import cn.teammodel.repository.DutyRecordRepository;
import cn.teammodel.repository.SchoolRepository;
import cn.teammodel.repository.TeacherRepository;
import cn.teammodel.security.utils.SecurityUtil;
import cn.teammodel.utils.GroupUtil;
import cn.teammodel.utils.SchoolDateUtil;
import com.azure.spring.data.cosmos.core.query.CosmosPageRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.data.domain.Slice;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;
import static cn.teammodel.utils.SchoolDateUtil.calculateWeekNum;
/**
* @author winter
* &#064;create 2024-02-28 15:07
*/
@Service
@Slf4j
public class AdminIndexDutyServiceImpl implements AdminIndexDutyService {
@Resource
private SchoolRepository schoolRepository;
@Resource
private TeacherRepository teacherRepository;
@Resource
private ClassRepository classRepository;
@Resource
private DutyRecordRepository dutyRecordRepository;
@Autowired
private Environment env;
/* @Autowired
public AdminIndexDutyServiceImpl(Environment env) {
this.env = env;
}*/
@Override
public DutyIndexData getIndexData(TimeRangeDto timeRangeDto) {
User loginUser = SecurityUtil.getLoginUser();
String schoolId = loginUser.getSchoolId();
final int SLICE_SIZE = 100;
if (StringUtils.isBlank(timeRangeDto.getPeriodId())) {
throw new ServiceException(ErrorCode.PARAMS_ERROR.getCode(), "不能为空");
}
final DutyIndexData DutyIndexData = new DutyIndexData();
int totalCount = 0;
int negetiveCount = 0;
Set<String> creatorIdSet = new HashSet<>();
// todo
Set<String> classIdSet = new HashSet<>();
// 获取学期起止时间
List<School.Semester> semesters = schoolRepository.findSemestersById(schoolId, timeRangeDto.getPeriodId());
SchoolDateUtil.semesterModel semesterModel = SchoolDateUtil.getSemesterByNow(semesters, LocalDate.now());
LocalDateTime startDatetime = null;
LocalDateTime endDatetime = null;
String academicYearId = null;
if(timeRangeDto.getStartTime() != null) {
startDatetime = LocalDateTime.ofInstant(Instant.ofEpochMilli(timeRangeDto.getStartTime()), ZoneId.systemDefault());
endDatetime = LocalDateTime.ofInstant(Instant.ofEpochMilli(timeRangeDto.getEndTime()), ZoneId.systemDefault());
academicYearId = timeRangeDto.getAcademicYearId();
}else {
academicYearId = semesterModel.getAcademicYearId();
startDatetime = semesterModel.getStartDatetime();
endDatetime = semesterModel.getEndDatetime();
}
if (startDatetime == null || endDatetime == null) throw new ServiceException(ErrorCode.PARAMS_ERROR);
long totalWeek = calculateWeekNum(startDatetime, endDatetime, null);
// slice 分段读取
CosmosPageRequest pageRequest = new CosmosPageRequest(0, SLICE_SIZE, null);
Slice<DutyIndexPo> slice;
Map<Long, Integer> countByWeek = SchoolDateUtil.createEmptyWeekMap(totalWeek);
do {
slice = dutyRecordRepository.findAllByAcademicYearId(String.format(PK.WEEK_DUTY_RECORD, schoolId), academicYearId, pageRequest);
List<DutyIndexPo> content = slice.getContent();
if (ObjectUtils.isEmpty(content)) {
break;
}
// 分批次计算
for (DutyIndexPo item : content) {
// 处理每周的评价数
long weekNum = calculateWeekNum(startDatetime, endDatetime, item.getCreateTime());
countByWeek.put(weekNum, countByWeek.getOrDefault(weekNum, 0) + 1);
// 处理总评价数
totalCount++;
// 处理批评数
if (item.getDutyTreeNodeScore() < 0) {
negetiveCount++;
}
// 处理已评价老师总数
creatorIdSet.add(item.getCreatorId());
// 处理被评价的学生数
classIdSet.add(item.getClassId());
}
if (slice.hasNext()) {
pageRequest = (CosmosPageRequest) slice.nextPageable();
}
} while (slice.hasNext());
// 组装数据
DutyIndexData.setCountByWeek(countByWeek);
DutyIndexData.setTotalCount(totalCount);
DutyIndexData.setClassCount(classIdSet.size());
DutyIndexData.setPositiveCount(totalCount - negetiveCount);
DutyIndexData.setTeacherCount(creatorIdSet.size());
return DutyIndexData;
}
@Override
public List<DutyRankPo> classRank(TimeRangeDto timeRangeDto) {
Long startTime = timeRangeDto.getStartTime();
Long endTime = timeRangeDto.getEndTime();
String academicYearId = timeRangeDto.getAcademicYearId();
String schoolId = SecurityUtil.getLoginUser().getSchoolId();
List<DutyRankPo> res = dutyRecordRepository.classRank(String.format(PK.WEEK_DUTY_RECORD, schoolId), academicYearId, startTime, endTime);
if (ObjectUtils.isEmpty(res)) return null;
List<String> classIds = res.stream().map(DutyRankPo::getId).collect(Collectors.toList());
if (ObjectUtils.isEmpty(classIds)) {
return null;
}
List<ClassInfo> classes = classRepository.findAllByCodeAndIdIn(String.format(PK.CLASS, schoolId), classIds);
Map<String, String> idNameMap = classes.stream().collect(Collectors.toMap(ClassInfo::getId, ClassInfo::getName));
// reversed sort by score
res = res.stream().peek(s -> s.setName(idNameMap.get(s.getId()))).sorted((a, b) -> b.getScore() - a.getScore()).collect(Collectors.toList());
return res;
}
@Override
public List<DutyRankPo> teacherRank(TimeRangeDto timeRangeDto) {
Long startTime = timeRangeDto.getStartTime();
Long endTime = timeRangeDto.getEndTime();
String academicYearId = timeRangeDto.getAcademicYearId();
String schoolId = SecurityUtil.getLoginUser().getSchoolId();
List<DutyRankPo> res = dutyRecordRepository.teacherRank(String.format(PK.WEEK_DUTY_RECORD, schoolId), academicYearId, startTime, endTime);
// set teacher name
if (ObjectUtils.isEmpty(res)) return null;
Set<String> teacherIdSet = res.stream().map(DutyRankPo::getId).collect(Collectors.toSet());
if (ObjectUtils.isEmpty(teacherIdSet)) return res;
List<Teacher> teachers = teacherRepository.findAllByCodeAndIdIn(PK.COMMON_BASE, teacherIdSet);
Map<String, String> idNameMap = teachers.stream().collect(Collectors.toMap(Teacher::getId, Teacher::getName));
res = res.stream().peek(s -> s.setName(idNameMap.get(s.getId()))).sorted((a, b) -> b.getScore() - a.getScore()).collect(Collectors.toList());
return res;
}
@Override
public List<DutyNodeRankVo> appraiseNodeRank(TimeRangeDto timeRangeDto) {
Long startTime = timeRangeDto.getStartTime();
Long endTime = timeRangeDto.getEndTime();
String academicYearId = timeRangeDto.getAcademicYearId();
String schoolId = SecurityUtil.getLoginUser().getSchoolId();
List<DutyNodeRankVo> res = dutyRecordRepository.dutyNodeRank(String.format(PK.WEEK_DUTY_RECORD, schoolId), academicYearId, startTime, endTime);
if (ObjectUtils.isEmpty(res)) return null;
List<String> names = res.stream().map(DutyNodeRankVo::getName).collect(Collectors.toList());
if (ObjectUtils.isEmpty(names)) return null;
// 去重后的 nodes
List<WeekDuty.DutyTreeNode> nodesByName = dutyRecordRepository.findDutyRecordInNames(String.format(PK.WEEK_DUTY_RECORD, schoolId), academicYearId, names);
// 正常情况下 name 一一对应 // TODO: 2024/2/29
Map<String, WeekDuty.DutyTreeNode> nameNodeMap = nodesByName.stream()
.collect(Collectors.toMap(WeekDuty.DutyTreeNode::getName, item -> item, (existing, replacement) -> {
if (replacement.getPath() != null) {
return replacement;
}
return existing;
}));
res = res.stream()
.sorted(Comparator.comparing(DutyNodeRankVo::getCount).reversed())
// 流中对元素操作但不改变流
.peek(s -> {
WeekDuty.DutyTreeNode node = nameNodeMap.get(s.getName());
if (node != null) {
s.setPath(node.getPath());
s.setScore(node.getScore());
}
})
.collect(Collectors.toList());
return res;
}
@Override
public Map<String, Object> getLessonRecord(LessonRecordDto lessonRecordDto, HttpServletRequest request) {
Map<String, Object> mapper;
String url = env.getProperty("ies.server-url");
if(lessonRecordDto.isClassMeeting()) {
List<School.Subject> subjects = schoolRepository.findSubjectById(lessonRecordDto.getSchool(), lessonRecordDto.getPeriodId());
List<String> subjectIds = subjects.stream().filter(subject -> "班会".equals(subject.getName()))
.map(School.Subject::getId).collect(Collectors.toList());
lessonRecordDto.setSubjectId(subjectIds);
}
mapper = GroupUtil.getGroupId(lessonRecordDto,new GroupUtil(env), request,url);
return mapper;
}
}

@ -0,0 +1,162 @@
package cn.teammodel.controller.admin.service.impl;
import cn.teammodel.common.ErrorCode;
import cn.teammodel.config.exception.ServiceException;
import cn.teammodel.controller.admin.service.ArtService;
import cn.teammodel.model.dto.admin.art.ArtAnalysisDto;
import cn.teammodel.model.dto.admin.art.ArtFindDto;
import cn.teammodel.model.dto.admin.art.DataFileCommentDto;
import cn.teammodel.model.dto.admin.art.DataFileDto;
import cn.teammodel.model.dto.admin.common.GroupDto;
import cn.teammodel.model.dto.admin.common.RGroupList;
import cn.teammodel.model.dto.admin.common.RMember;
import cn.teammodel.model.vo.admin.ArtElementsVo;
import cn.teammodel.model.vo.admin.DataFileVo;
import cn.teammodel.repository.ArtRepository;
import cn.teammodel.utils.GroupUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
@Service
public class ArtServiceImpl implements ArtService {
@Resource
private ArtRepository artRepository;
@Autowired
private Environment env;
@Override
public List<ArtElementsVo> getArtList(ArtFindDto artFindDto, HttpServletRequest request) {
List<ArtElementsVo> artElementsVos = artRepository.findPeriodById(artFindDto.getPeriodId(),"Art-"+ artFindDto.getCode(), artFindDto.getStartTime(), artFindDto.getEndTime());
List<String> classIds = artElementsVos.stream()
.map(ArtElementsVo::getClasses) // 正确的方法引用
.flatMap(List::stream) // 将内部列表扁平化
.collect(Collectors.toList());
GroupDto groupDto = new GroupDto();
groupDto.setIds(classIds);
groupDto.setSchoolId(artFindDto.getCode());
String url = env.getProperty("ies.server-url-group");
//List<ClassInfo> classes = classRepository.findAllByCodeAndIdIn("Class-"+artFindDto.getCode(),classIds);
Map<String, Object> groupId = GroupUtil.getGroupId(groupDto,new GroupUtil(env), request,url);
List<RGroupList> rGroupList = new ArrayList<>();
List<RMember> rMembers = new ArrayList<>();
for (Map.Entry<String, Object> entry : groupId.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
if (key.equals("groups")) {
String jsonGroups = JSON.toJSONString(value);
rGroupList = JSON.parseObject(jsonGroups, new TypeReference<List<RGroupList>>() {});
}
if (key.equals("members")) {
String jsonGroups = JSON.toJSONString(value);
rMembers = JSON.parseObject(jsonGroups, new TypeReference<List<RMember>>() {});
}
}
try {
for (ArtElementsVo artElementsVo : artElementsVos) {
List<String> classes1 = artElementsVo.getClasses();
int stuInClassCount = 0;
for(String classId : classes1) {
stuInClassCount += (int) rMembers.stream().filter(rMember -> rMember.getClassId().equals(classId)).count();
//stuInClassCount += studentRepository.countByClassIdAndCode(classId, String.format(PK.STUDENT, artFindDto.getCode()));
ArtElementsVo.ClassInfos classInfos = new ArtElementsVo.ClassInfos();
rGroupList.stream().filter(rGroupList1 -> rGroupList1.getId().equals(classId)).findFirst().ifPresent(rGroupList1 -> {
classInfos.setId(rGroupList1.getId());
classInfos.setName(rGroupList1.getName());
});
artElementsVo.addClassesInfos(classInfos);
}
artElementsVo.setCount(stuInClassCount);
}
} catch (Exception e) {
throw new ServiceException(ErrorCode.SYSTEM_ERROR.getCode(), "数据转换错误");
}
return artElementsVos;
}
@Override
public List<RGroupList> getGroupList(GroupDto groupDto, HttpServletRequest request) {
List<RGroupList> rGroupList = new ArrayList<>();
String url = env.getProperty("ies.server-url-group");
try {
Map<String, Object> groupId = GroupUtil.getGroupId(groupDto,new GroupUtil(env), request,url);
//List<RMember> rMembers = new ArrayList<>();
for (Map.Entry<String, Object> entry : groupId.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
if (key.equals("groups")) {
String jsonGroups = JSON.toJSONString(value);
rGroupList = JSON.parseObject(jsonGroups, new TypeReference<List<RGroupList>>() {});
}
}
}catch (Exception e) {
throw new ServiceException(ErrorCode.SYSTEM_ERROR.getCode(), "数据转换错误");
}
return rGroupList;
}
@Override
public List<DataFileVo> getPdfData(DataFileDto dataFileDto,HttpServletRequest request) {
List<DataFileVo> dataFile = new ArrayList<>();
String url = env.getProperty("ies.server-url-pdf-data");
try {
Map<String, Object> groupId = GroupUtil.getGroupId(dataFileDto,new GroupUtil(env), request,url);
//List<RMember> rMembers = new ArrayList<>();
for (Map.Entry<String, Object> entry : groupId.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
if (key.equals("dataFiles")) {
String jsonGroups = JSON.toJSONString(value);
dataFile = JSON.parseObject(jsonGroups, new TypeReference<List<DataFileVo>>() {});
}
}
}catch (Exception e) {
throw new ServiceException(ErrorCode.SYSTEM_ERROR.getCode(), "数据转换错误");
}
return dataFile;
}
@Override
public List<DataFileVo> updateComment(DataFileCommentDto dataFileCommentDto, HttpServletRequest request) {
List<DataFileVo> dataFile = new ArrayList<>();
String url = env.getProperty("ies.server-url-update-custom-comment");
try {
Map<String, Object> groupId = GroupUtil.getGroupId(dataFileCommentDto,new GroupUtil(env), request,url);
//List<RMember> rMembers = new ArrayList<>();
for (Map.Entry<String, Object> entry : groupId.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
if (key.equals("dataFile")) {
String jsonGroups = JSON.toJSONString(value);
dataFile = JSON.parseObject(jsonGroups, new TypeReference<List<DataFileVo>>() {});
}
}
}catch (Exception e) {
throw new ServiceException(ErrorCode.SYSTEM_ERROR.getCode(), "数据转换错误");
}
return dataFile;
}
@Override
public Map<String, Object> getArtAnalytics(ArtAnalysisDto artAnalysisDto, HttpServletRequest request) {
Map<String, Object> analysis;
String url = env.getProperty("ies.server-url-art-analysis");
try {
analysis = GroupUtil.getGroupId(artAnalysisDto,new GroupUtil(env), request,url);
}catch (Exception e) {
throw new ServiceException(ErrorCode.SYSTEM_ERROR.getCode(), "数据转换错误");
}
return analysis;
}
}

@ -0,0 +1,33 @@
package cn.teammodel.controller.admin.service.impl;
import cn.teammodel.common.ErrorCode;
import cn.teammodel.config.exception.ServiceException;
import cn.teammodel.controller.admin.service.BlobService;
import cn.teammodel.model.dto.admin.exam.BlobSasDto;
import cn.teammodel.utils.GroupUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
@Service
public class BlobServiceImpl implements BlobService {
@Autowired
private Environment env;
@Override
public Map<String, Object> getBlobSas(BlobSasDto blobSasDto, HttpServletRequest request) {
Map<String, Object> sas;
String url = env.getProperty("ies.server-url-blob-sas-rcwld");
try {
sas = GroupUtil.getGroupId(blobSasDto,new GroupUtil(env), request,url);
}catch (Exception e) {
throw new ServiceException(ErrorCode.SYSTEM_ERROR.getCode(), "数据转换错误");
}
return sas;
}
}

@ -0,0 +1,163 @@
package cn.teammodel.controller.admin.service.impl;
import cn.teammodel.controller.admin.service.CommonService;
import cn.teammodel.model.dto.admin.common.CommentDto;
import cn.teammodel.model.dto.admin.common.GCDto;
import cn.teammodel.model.entity.common.Comment;
import cn.teammodel.model.entity.school.ClassInfo;
import cn.teammodel.model.entity.school.School;
import cn.teammodel.model.vo.admin.GradeAndClassVo;
import cn.teammodel.repository.ClassRepository;
import cn.teammodel.repository.CommentRepository;
import cn.teammodel.repository.SchoolRepository;
import cn.teammodel.utils.MonthToNumberConverter;
import com.azure.cosmos.models.PartitionKey;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.time.Instant;
import java.time.LocalDate;
import java.time.Month;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.List;
import static java.time.LocalDate.now;
@Service
public class CommonServiceImpl implements CommonService {
@Resource
private SchoolRepository schoolRepository;
@Resource
private ClassRepository classRepository;
@Resource
private CommentRepository commentRepository;
@Override
public List<GradeAndClassVo> getGradeAndClass(GCDto gcDto) {
List<GradeAndClassVo> gradeAndClassVos = new ArrayList<>();
try {
//获取当前学校该学段下详细信息
List<School.Period> period = schoolRepository.findPeriodById(gcDto.getSchoolId(), gcDto.getPeriodId());
List<ClassInfo> classes = classRepository.findClassBySchoolIdAndPeriodId(gcDto.getPeriodId());
int year;
int mon;
int day;
if (gcDto.getTime() != null && gcDto.getTime() != 0L) {
LocalDate date = Instant.ofEpochMilli(gcDto.getTime()).atZone(ZoneId.systemDefault()).toLocalDate();
year = date.getYear();
mon = date.getMonthValue();
day = date.getDayOfMonth();
}else {
year = now().getYear();
Month month = now().getMonth();
mon = MonthToNumberConverter.convertMonthToNumber(month.name());
day = now().getDayOfMonth();
}
//处理年级ID
for (ClassInfo classInfo : classes) {
if(period.get(0).getId().equalsIgnoreCase(classInfo.getPeriodId())) {
for (School.Semester semester : period.get(0).getSemesters()) {
int time;
if(semester.getStart() == 1) {
if (mon == semester.getMonth())
{
time = day >= semester.getDay() ? 0 : 1;
}
else
{
time = mon > semester.getMonth() ? 0 : 1;
}
int eYear = year - time;
classInfo.setGrade(eYear- classInfo.getYear());
}
}
}
}
List<String> grades = period.get(0).getGrades();
int index = 0;
//根据当前时间去判定各个年级的入学年
int time = 0;
if(period.get(0).getId().equalsIgnoreCase(gcDto.getPeriodId())) {
for (School.Semester semester : period.get(0).getSemesters()) {
if(semester.getStart() == 1) {
if (mon == semester.getMonth())
{
time = day >= semester.getDay() ? 0 : 1;
}
else
{
time = mon > semester.getMonth() ? 0 : 1;
}
}
}
}
for (String grade : grades) {
GradeAndClassVo gradeAndClassVo = new GradeAndClassVo();
gradeAndClassVo.setGradeId(index);
gradeAndClassVo.setYear(year - time - index);
gradeAndClassVo.setGradeName(grade);
classes.stream().filter(classInfo -> classInfo.getGrade() == gradeAndClassVo.getGradeId()).forEach(classInfo -> {
GradeAndClassVo.CI ci = new GradeAndClassVo.CI();
ci.setClassId(classInfo.getId());
ci.setClassName(classInfo.getName());
ci.setYear(classInfo.getYear());
gradeAndClassVo.AddClass(ci);
});
index ++;
gradeAndClassVos.add(gradeAndClassVo);
}
return gradeAndClassVos;
}catch (Exception e) {
throw new RuntimeException("获取当前学校当前学段年级班级信息失败" + e);
}
}
@Override
public Comment saveOrUpdateComment(Comment comment) {
String formattedString = String.format("Comment-%s-%s-%s",
comment.getSchool(),
comment.getYear(),
comment.getSemester());
List<Comment> comments = commentRepository.findById(comment.getId(),comment.getSchool(),comment.getActivityType(),formattedString);
Comment existingComment = comments.stream().findFirst().orElse(null);
if (existingComment != null) {
// 如果评论对象存在,则进行更新操作
// 这里你可以根据需要更新评论对象的属性
existingComment.setContentInfo(comment.getContentInfo());
existingComment.setUpdateTime(Instant.now().toEpochMilli());
//commentRepository.deleteById(existingComment.getId(),new PartitionKey(existingComment.getSchool()));
// 最后保存更新后的评论对象
return commentRepository.save(existingComment);
} else {
// 如果评论对象不存在,则创建新的记录
comment.setCode(formattedString);
comment.setCreateTime(Instant.now().toEpochMilli());
return commentRepository.save(comment);
}
}
@Override
public List<String> deleteComment(CommentDto comment) {
for (String id : comment.getIds()) {
commentRepository.deleteById(id,new PartitionKey(comment.getCode()));
}
return comment.getIds();
}
@Override
public List<Comment> getCommentById(Comment comment) {
String formattedString = String.format("Comment-%s-%s-%s",
comment.getSchool(),
comment.getYear(),
comment.getSemester());
return commentRepository.findById(comment.getId(),comment.getSchool(),comment.getActivityType(),formattedString);
}
}

@ -0,0 +1,108 @@
package cn.teammodel.controller.admin.service.impl;
import cn.teammodel.common.ErrorCode;
import cn.teammodel.config.exception.ServiceException;
import cn.teammodel.controller.admin.service.ExamService;
import cn.teammodel.model.dto.admin.exam.*;
import cn.teammodel.model.entity.common.Exam;
import cn.teammodel.model.entity.school.School;
import cn.teammodel.repository.ExamRepository;
import cn.teammodel.repository.SchoolRepository;
import cn.teammodel.utils.GroupUtil;
import com.azure.cosmos.models.PartitionKey;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
@Service
public class ExamServiceImpl implements ExamService {
@Resource
private ExamRepository examRepository;
@Resource
private SchoolRepository schoolRepository;
@Autowired
private Environment env;
@Override
public Map<String, Object> getAnalysis(OverViewDto overViewDto, HttpServletRequest request) {
Map<String, Object> overView;
Map<String, Object> examRate;
String url = env.getProperty("ies.server-url-overview");
String url_exam = env.getProperty("ies.server-url-exam-rate");
try {
Optional<School> school = schoolRepository.findById(overViewDto.getSchool(), new PartitionKey("Base"));
overView = GroupUtil.getGroupId(overViewDto,new GroupUtil(env), request,url);
examRate = GroupUtil.getGroupId(overViewDto,new GroupUtil(env), request,url_exam);
//SnowflakeIdGenerator generator = new SnowflakeIdGenerator(1);
//overView.put("reportId",generator.nextId());
overView.putAll(examRate);
school.ifPresent(value -> overView.put("schoolName", value.getName()));
school.flatMap(value -> value.getPeriod().stream().filter(period ->
period.getId().equals(overViewDto.getPeriodId())).findFirst()).ifPresent(value1 ->
overView.put("semesters", value1.getSemesters()));
}catch (Exception e) {
throw new ServiceException(ErrorCode.SYSTEM_ERROR.getCode(), "数据转换错误");
}
return overView;
}
@Override
public Map<String, Object> getExamList(AnalysisDto analysisDto, HttpServletRequest request) {
Map<String, Object> overView;
String url = env.getProperty("ies.server-url-exam-analysis-list");
try {
overView = GroupUtil.getGroupId(analysisDto,new GroupUtil(env), request,url);
}catch (Exception e) {
throw new ServiceException(ErrorCode.SYSTEM_ERROR.getCode(), "数据转换错误");
}
return overView;
}
@Override
public Map<String, Object> getExamSimpleAnalysis(FindExamDto findExamDto, HttpServletRequest request) {
Map<String, Object> simpleView;
String url_simple = env.getProperty("ies.server-url-analysis-simple");
try {
List<Exam> examList = examRepository.findExamById("Exam-"+findExamDto.getCode(), findExamDto.getId());
simpleView = GroupUtil.getGroupId(findExamDto,new GroupUtil(env), request,url_simple);
simpleView.put("examList",examList);
}catch (Exception e) {
throw new ServiceException(ErrorCode.SYSTEM_ERROR.getCode(), "数据转换错误");
}
return simpleView;
}
@Override
public Map<String, Object> getExamRecord(ExamRecordDto examRecordDto, HttpServletRequest request) {
Map<String, Object> record;
String url = env.getProperty("ies.server-url-exam-find-record");
try {
record = GroupUtil.getGroupId(examRecordDto,new GroupUtil(env), request,url);
}catch (Exception e) {
throw new ServiceException(ErrorCode.SYSTEM_ERROR.getCode(), "数据转换错误");
}
return record;
}
@Override
public Map<String, Object> getExamByStudent(FindByStudentDto findByStudentDto, HttpServletRequest request) {
Map<String, Object> studentView;
String url = env.getProperty("ies.server-url-find-simple-by-student");
try {
studentView = GroupUtil.getGroupId(findByStudentDto,new GroupUtil(env), request,url);
}catch (Exception e) {
throw new ServiceException(ErrorCode.SYSTEM_ERROR.getCode(), "数据转换错误");
}
return studentView;
}
}

@ -0,0 +1,910 @@
package cn.teammodel.controller.admin.service.impl;
import cn.teammodel.common.ErrorCode;
import cn.teammodel.common.PK;
import cn.teammodel.config.exception.ServiceException;
import cn.teammodel.controller.admin.service.TeacherService;
import cn.teammodel.model.dto.admin.teacher.GpTeacherDto;
import cn.teammodel.model.dto.admin.teacher.TeacherDto;
import cn.teammodel.model.entity.common.GroupList;
import cn.teammodel.model.entity.school.GpTeacher;
import cn.teammodel.model.entity.school.LessonRecord;
import cn.teammodel.model.entity.school.School;
import cn.teammodel.model.entity.school.SchoolTeacher;
import cn.teammodel.model.vo.admin.GpTeacherVo;
import cn.teammodel.model.vo.admin.TeacherGradeVo;
import cn.teammodel.repository.LessonRecordRepository;
import cn.teammodel.repository.SchoolGroupListRepository;
import cn.teammodel.repository.SchoolRepository;
import cn.teammodel.repository.SchoolTeacherRepository;
import cn.teammodel.utils.GroupUtil;
import cn.teammodel.utils.SchoolDateUtil;
import com.azure.spring.data.cosmos.core.query.CosmosPageRequest;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.SliceImpl;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.*;
import java.util.*;
import java.util.stream.Collectors;
import static cn.teammodel.utils.SchoolDateUtil.calculateWeekNum;
@Service
public class TeacherServiceImpl implements TeacherService {
@Resource
private SchoolTeacherRepository schoolTeacherRepository;
@Resource
private SchoolGroupListRepository schoolGroupListRepository;
@Resource
private SchoolRepository schoolRepository;
@Resource
private LessonRecordRepository lessonRecordRepository;
@Autowired
private Environment env;
@Override
public List<Map<String, Integer>> getTeacherList(TeacherDto teacherDto) {
List<Map<String, Integer>> result = new ArrayList<>();
Map<String, Integer> teacherCountMap = new HashMap<>();
Map<String, Integer> groupCountMap = new HashMap<>();
List<GroupList> groupLists = schoolGroupListRepository.findAllByCode("GroupList-" + teacherDto.getCode());
List<SchoolTeacher> schoolTeachers = schoolTeacherRepository.findAllByCode("Teacher-" + teacherDto.getCode());
teacherCountMap.put("教师总人数", schoolTeachers.size());
List<School> school = schoolRepository.findBaseById(teacherDto.getCode());
List<School.Subject> subjects = new ArrayList<>();
List<School.Period> periods = new ArrayList<>();
for (School sc : school) {
if (sc.getPeriod() != null) {
// 遍历每个 Period 对象
for (School.Period period : sc.getPeriod()) {
periods.add(period);
// 检查 period 是否有 subjects 列表
if (period.getSubjects() != null) {
// 将 period 中的 subjects 添加到总的 subjects 列表中
subjects.addAll(period.getSubjects());
}
}
}
}
Map<String, Integer> updatedSubjectCountMap = getStringIntegerMap(subjects, schoolTeachers);
// 创建一个映射,用于存储每个职位的教师数量
Map<String, Integer> jobCountMap = new HashMap<>();
// 遍历所有教师
for (SchoolTeacher teacher : schoolTeachers) {
// 获取教师的职位
String job = teacher.getJob();
if (job != null) {
// 更新每个职位的教师数量
jobCountMap.put(job, jobCountMap.getOrDefault(job, 0) + 1);
}
}
jobCountMap.entrySet().removeIf(entry -> entry.getKey().isEmpty());
Map<String, Integer> periodCountMap = getPeriodCountMap(periods,schoolTeachers);
for (GroupList groupList : groupLists) {
groupCountMap.put(groupList.getName(), groupList.getMembers().size());
}
periodCountMap.entrySet().removeIf(entry -> entry.getKey().isEmpty());
updatedSubjectCountMap.entrySet().removeIf(entry -> entry.getKey().isEmpty());
result.add(updatedSubjectCountMap);
result.add(jobCountMap);
result.add(periodCountMap);
result.add(teacherCountMap);
result.add(groupCountMap);
return result;
}
@Override
public Map<String, Object> getTeacherDetail(TeacherDto teacherDto, HttpServletRequest request) {
Map<String, Object> teachers;
//获取全学校教师名单详情
String url = env.getProperty("ies.server-url-get-teacher-all");
try {
teachers = GroupUtil.getGroupId(teacherDto,new GroupUtil(env), request,url);
List<GpTeacherVo> teachersList = new ArrayList<>();
for (Map.Entry<String, Object> entry : teachers.entrySet()) {
// 假设 entry.getValue() 返回的是 List<Map<String, Object>>
List<Map<String, Object>> mapList = (List<Map<String, Object>>) entry.getValue();
for (Map<String, Object> map : mapList) {
// 将 Map 转换为 GpTeacherVo 对象
GpTeacherVo teacher = convertToGpTeacherVo(map);
teachersList.add(teacher);
}
}
List<String> phones = new ArrayList<>();
// 进一步处理 teachersList
for (GpTeacherVo teacher : teachersList) {
phones.add(teacher.getPhone());
}
GpTeacherDto gpTeacherDto = new GpTeacherDto();
gpTeacherDto.setMobiles(phones);
Map<String, Object> tBase = getTeacherBase(gpTeacherDto, request);
List<GpTeacher> gpTeachers = new ArrayList<>();
for (Map.Entry<String, Object> entry : tBase.entrySet()) {
if (entry.getKey().equals("teachers")) {
List<Map<String, Object>> dataList = (List<Map<String, Object>>) entry.getValue();
for (Map<String, Object> dataMap : dataList) {
GpTeacher gpTeacher = convertToGpTeacher(dataMap);
gpTeachers.add(gpTeacher);
}
}
}
Map<String, Long> genderCount = gpTeachers.stream()
.collect(Collectors.groupingBy(gpTeacher -> gpTeacher.getBasic().getGender(), Collectors.counting()));
Map<String, Long> degreeCount = gpTeachers.stream()
.filter(gpTeacher -> gpTeacher.getDegree() != null)
.collect(Collectors.groupingBy(GpTeacher::getDegree, Collectors.counting()));
//Map<String, Integer> practiceCount = getStringIntegerMap(teacherDto, gpTeachers);
if(!genderCount.containsKey("F")) {
genderCount.put("F",0L);
}else if (!genderCount.containsKey("S")) {
genderCount.put("S",0L);
}else if (!genderCount.containsKey("M")){
genderCount.put("M",0L);
}
/* Map<String, Object> genderMap = new HashMap<>();
Map<String, Object> practiceMap = new HashMap<>();
for (GpTeacher gpTeacher : gpTeachers) {
genderMap.put(gpTeacher.basic.name, gpTeacher.basic.gender);
practiceMap.put(gpTeacher.basic.name, gpTeacher.practiceTime);
}*/
for (GpTeacherVo teacher : teachersList) {
for(GpTeacher gpTeacher : gpTeachers) {
if(StringUtils.isNotEmpty(teacher.phone) && teacher.phone.equalsIgnoreCase(gpTeacher.mobile)) {
if(gpTeacher.basic.gender != null) {
teacher.setGender(gpTeacher.basic.gender);
}else {
teacher.setGender("");
}
if (gpTeacher.getPracticeTime() != null && gpTeacher.getPracticeTime() > 0) {
teacher.setPracticeTime(gpTeacher.getPracticeTime());
}else {
teacher.setPracticeTime(0L);
}
if(gpTeacher.degree != null) {
teacher.setDegree(gpTeacher.degree);
}else {
teacher.setDegree("");
}
break;
}
}
}
//teachers.put("practice", practiceCount);
//teachers.put("practiceMap", practiceMap);
//teachers.put("genderMap", genderMap);
teachers.put("gender", genderCount);
teachers.put("degree", degreeCount);
teachers.put("info", teachersList);
teachers.remove("teachers");
}catch (Exception e) {
throw new ServiceException(ErrorCode.SYSTEM_ERROR.getCode(), "数据转换错误");
}
return teachers;
}
private static @NotNull Map<String, Integer> getStringIntegerMap(TeacherDto teacherDto, List<GpTeacher> gpTeachers) {
Map<String,Integer> practiceCount = new HashMap<>();
for (GpTeacher gpTeacher : gpTeachers) {
if(gpTeacher.practiceTime > 0) {
// 将时间戳转换为 LocalDateTime
LocalDateTime dateTime = LocalDateTime.ofInstant(
Instant.ofEpochMilli(gpTeacher.practiceTime),
ZoneId.systemDefault()
);
// 获取年份
int year = dateTime.getYear();
practiceCount.put(gpTeacher.basic.name, teacherDto.year - year);
}
}
return practiceCount;
}
private GpTeacherVo convertToGpTeacherVo(Map<String, Object> map) {
GpTeacherVo teacher = new GpTeacherVo();
// 假设 GpTeacherVo 有以下属性name, age, subject
teacher.setName((String) map.get("name"));
teacher.setPhone((String) map.get("phone"));
teacher.setId((String) map.get("id"));
teacher.setEmail((String) map.get("email"));
teacher.setPicture((String) map.get("picture"));
teacher.setIname((String) map.get("iname"));
teacher.setJob((String) map.get("job"));
teacher.setRoles((List<String>) map.get("roles"));
//teacher.setGroups((List<GpTeacherVo.IdNameCode>) map.get("groups"));
List<Map<String, Object>> groupList = (List<Map<String, Object>>) map.get("groups");
if (groupList != null) {
List<GpTeacherVo.IdNameCode> groups = new ArrayList<>();
for (Map<String, Object> groupMap : groupList) {
GpTeacherVo.IdNameCode group = new GpTeacherVo.IdNameCode();
group.setId((String) groupMap.get("id"));
group.setName((String) groupMap.get("name"));
group.setCode((String) groupMap.get("code"));
group.setPicture((String) groupMap.get("picture"));
group.setNickname((String) groupMap.get("nickname"));
groups.add(group);
}
teacher.setGroups(groups);
}
//teacher.setDegree((String) map.get("degree"));
//teacher.setPracticeTime((String) map.get("practiceTime"));
//teacher.setGender((String) map.get("gender"));
teacher.setNote((String) map.get("note"));
teacher.setSubjectIds((List<String>) map.get("subjectIds"));
teacher.setSubjectNames((List<String>) map.get("subjectNames"));
// 根据实际属性进行转换
return teacher;
}
private TeacherGradeVo convertToTeacherGradeVo(Map<String, Object> map) {
TeacherGradeVo teacher = new TeacherGradeVo();
teacher.setName((String) map.get("name"));
teacher.setId((String) map.get("tmdId"));
teacher.setPeriodId((String) map.get("periodId"));
// 处理 grade 字段
List<Map<String, Object>> gradeList = (List<Map<String, Object>>) map.get("grade");
if (gradeList != null) {
List<TeacherGradeVo.IdAndName> grades = new ArrayList<>();
for (Map<String, Object> gradeMap : gradeList) {
TeacherGradeVo.IdAndName grade = new TeacherGradeVo.IdAndName();
grade.setGrade((Integer) gradeMap.get("grade"));
grade.setGradeName((String) gradeMap.get("gradeName"));
grades.add(grade);
}
teacher.setGrade(grades);
}
// 根据实际属性进行转换
return teacher;
}
private GpTeacher convertToGpTeacher(Map<String, Object> map) {
GpTeacher teacher = new GpTeacher();
// 假设 GpTeacherVo 有以下属性name, age, subject
Object describeObj = map.get("describe");
if (describeObj instanceof String) {
teacher.setDescribe((String) describeObj);
} else {
teacher.setDescribe(null); // 或者设置一个默认值
}
Object IdObj = map.get("id");
if (describeObj instanceof String) {
teacher.setId((String) IdObj);
} else {
teacher.setId(null); // 或者设置一个默认值
}
Object depictObj = map.get("depict");
if (depictObj instanceof String) {
teacher.setDepict((String) depictObj);
} else {
teacher.setDepict(null); // 或者设置一个默认值
}
teacher.setPeriods((ArrayList<GpTeacher.GnericBase>) map.get("periods"));
teacher.setSubjects((ArrayList<GpTeacher.GnericBase>) map.get("subjects"));
teacher.setGrades((ArrayList<GpTeacher.GnericBase>) map.get("grades"));
Object practiceTimeObj = map.get("practiceTime");
if (practiceTimeObj instanceof Long) {
teacher.setPracticeTime((Long) practiceTimeObj);
} else {
teacher.setPracticeTime(0L); // 或者设置一个默认值
}
Object titleObj = map.get("title");
if (titleObj instanceof String) {
teacher.setTitle((String) titleObj);
} else {
teacher.setTitle(null); // 或者设置一个默认值
}
Object mobileObj = map.get("mobile");
if (mobileObj instanceof String) {
teacher.setMobile((String) mobileObj);
} else {
teacher.setMobile(null); // 或者设置一个默认值
}
Object degreeObj = map.get("degree");
if (degreeObj instanceof String) {
teacher.setDegree((String) degreeObj);
} else {
teacher.setDegree(null); // 或者设置一个默认值
}
Map<String, Object> basicMap = (Map<String, Object>) map.get("basic");
//teacher.setBasic(new GpTeacher.GPBasicInfo(basicMap.get("name").toString(),basicMap.get("fullName").toString(),basicMap.get("picture").toString(),basicMap.get("region").toString(),basicMap.get("province").toString(),basicMap.get("city").toString(),basicMap.get("dist").toString(),basicMap.get("gender").toString(),basicMap.get("age").toString(),basicMap.get("address").toString()));
GpTeacher.GPBasicInfo basic = new GpTeacher.GPBasicInfo();
Object nameObj = basicMap.get("name");
if (nameObj instanceof String) {
basic.setName((String) nameObj);
} else {
basic.setName(null); // 或者设置一个默认值
}
Object fullNameObj = basicMap.get("fullName");
if (fullNameObj instanceof String) {
basic.setFullName((String) fullNameObj);
} else {
basic.setFullName(null); // 或者设置一个默认值
}
Object distObj = basicMap.get("dist");
if (distObj instanceof String) {
basic.setDist((String) distObj);
} else {
basic.setDist(null); // 或者设置一个默认值
}
Object genderObj = basicMap.get("gender");
if (genderObj instanceof String) {
basic.setGender((String) genderObj);
} else {
basic.setGender(null); // 或者设置一个默认值
}
Object ageObj = basicMap.get("age");
if (ageObj instanceof Integer) {
basic.setAge((Integer) ageObj);
} else {
basic.setAge(0); // 或者设置一个默认值
}
teacher.basic = basic;
// 根据实际属性进行转换
return teacher;
}
@Override
public Map<Long, Integer> getTeacherByRecord(TeacherDto teacherDto) {
final int SLICE_SIZE = 100;
// 获取学期起止时间
List<School.Semester> semesters = schoolRepository.findSemestersById(teacherDto.getCode(), teacherDto.getPeriodId());
SchoolDateUtil.semesterModel semesterModel = SchoolDateUtil.getSemesterByNow(semesters, LocalDate.now());
LocalDateTime startDatetime;
LocalDateTime endDatetime;
if(teacherDto.getStartTime() != null) {
startDatetime = LocalDateTime.ofInstant(Instant.ofEpochMilli(teacherDto.getStartTime()), ZoneId.systemDefault());
endDatetime = LocalDateTime.ofInstant(Instant.ofEpochMilli(teacherDto.getEndTime()), ZoneId.systemDefault());
}else {
startDatetime = semesterModel.getStartDatetime();
endDatetime = semesterModel.getEndDatetime();
}
if (startDatetime == null || endDatetime == null) throw new ServiceException(ErrorCode.PARAMS_ERROR);
long totalWeek = calculateWeekNum(startDatetime, endDatetime, null);
// slice 分段读取
CosmosPageRequest pageRequest = new CosmosPageRequest(0, SLICE_SIZE, null);
Slice<LessonRecord> slice;
Map<Long, Integer> countByWeek = SchoolDateUtil.createEmptyWeekMap(totalWeek);
do {
if(StringUtils.isNotEmpty(teacherDto.getGrade())) {
slice = lessonRecordRepository.findAllByGrade(String.format(PK.PK_LESSON_RECORD, teacherDto.getCode()), teacherDto.getGrade(),teacherDto.getSubjectId(),pageRequest);
} else if(StringUtils.isNotEmpty(teacherDto.getTmdId())) {
slice = lessonRecordRepository.findAllByAcademicYearId(String.format(PK.PK_LESSON_RECORD, teacherDto.getCode()), teacherDto.getTmdId(),teacherDto.getSubjectId(),pageRequest);
} else {
slice = lessonRecordRepository.findAll(String.format(PK.PK_LESSON_RECORD, teacherDto.getCode()), teacherDto.getSubjectId(), pageRequest);
}
List<LessonRecord> content = slice.getContent();
if (ObjectUtils.isEmpty(content)) {
break;
}
// 分批次计算
for (LessonRecord item : content) {
// 处理每周的课程数
long weekNum = calculateWeekNum(startDatetime, endDatetime, item.getStartTime());
countByWeek.put(weekNum, countByWeek.getOrDefault(weekNum, 0) + 1);
}
if (slice.hasNext()) {
pageRequest = (CosmosPageRequest) slice.nextPageable();
}
} while (slice.hasNext());
countByWeek.entrySet().removeIf(entry -> entry.getKey() == -1);
return countByWeek;
}
@Override
public Map<String, Object> getTeacherLearningCategory(TeacherDto teacherDto) {
Map<String, Object> LearningCategory = new HashMap<>(Collections.emptyMap());
try {
// 获取学期起止时间
List<School.Semester> semesters = schoolRepository.findSemestersById(teacherDto.getCode(), teacherDto.getPeriodId());
SchoolDateUtil.semesterModel semesterModel = SchoolDateUtil.getSemesterByNow(semesters, LocalDate.now());
LocalDateTime startDatetime;
LocalDateTime endDatetime;
if(teacherDto.getStartTime() != null) {
startDatetime = LocalDateTime.ofInstant(Instant.ofEpochMilli(teacherDto.getStartTime()), ZoneId.systemDefault());
endDatetime = LocalDateTime.ofInstant(Instant.ofEpochMilli(teacherDto.getEndTime()), ZoneId.systemDefault());
}else {
startDatetime = semesterModel.getStartDatetime();
endDatetime = semesterModel.getEndDatetime();
}
if (startDatetime == null || endDatetime == null) throw new ServiceException(ErrorCode.PARAMS_ERROR);
// 将 LocalDateTime 转换为 Long 类型的时间戳
long startTimestamp = startDatetime.toInstant(ZoneOffset.UTC).toEpochMilli();
long endTimestamp = endDatetime.toInstant(ZoneOffset.UTC).toEpochMilli();
List<LessonRecord> lessonRecords = lessonRecordRepository.getLessonsByConditions(String.format(PK.PK_LESSON_RECORD, teacherDto.getCode()), startTimestamp, endTimestamp, teacherDto.getSubjectId(),teacherDto.getTmdId());
int[] counts = {0, 0, 0, 0, 0};
String[] keys = {"cooperation", "internet", "task", "exam", "diffential"};
for (LessonRecord record : lessonRecords) {
if (record.getLearningCategory() != null) {
counts[0] += record.getLearningCategory().getCooperation();
counts[1] += record.getLearningCategory().getInteraction();
counts[2] += record.getLearningCategory().getTask();
counts[3] += record.getLearningCategory().getExam();
counts[4] += record.getLearningCategory().getDiffential();
}
}
for (int i = 0; i < keys.length; i++) {
LearningCategory.put(keys[i], counts[i]);
}
}catch (Exception e) {
throw new ServiceException(ErrorCode.SYSTEM_ERROR.getCode(), "数据转换错误");
}
return LearningCategory;
}
@Override
public Map<String, Object> getTeacherGradeCount(TeacherDto teacherDto, HttpServletRequest request) {
Map<String, Object> gradeMap;
String url = env.getProperty("ies.server-url-get-teacher-grade-count");
try {
gradeMap = GroupUtil.getGroupId(teacherDto,new GroupUtil(env), request,url);
}catch (Exception e) {
throw new ServiceException(ErrorCode.SYSTEM_ERROR.getCode(), "数据转换错误");
}
return gradeMap;
}
@Override
public List<Map<String,Map<String, Long>>> getDistributionOfTeachers(TeacherDto teacherDto, HttpServletRequest request) {
List<Map<String,Map<String, Long>>> distributionList = new ArrayList<>();
Map<String,Map<String, Long>> gradesMap = new HashMap<>();
Map<String,Map<String, Long>> degreesMap = new HashMap<>();
Map<String,Map<String, Long>> subjectsMap= new HashMap<>();
Map<String,Map<String, Long>> groupsMap = new HashMap<>();
Map<String, Object> teachers;
//获取全学校教师名单详情
String url = env.getProperty("ies.server-url-get-teacher-all");
try {
teachers = GroupUtil.getGroupId(teacherDto,new GroupUtil(env), request,url);
List<GpTeacherVo> teachersList = new ArrayList<>();
for (Map.Entry<String, Object> entry : teachers.entrySet()) {
// 假设 entry.getValue() 返回的是 List<Map<String, Object>>
List<Map<String, Object>> mapList = (List<Map<String, Object>>) entry.getValue();
for (Map<String, Object> map : mapList) {
// 将 Map 转换为 GpTeacherVo 对象
GpTeacherVo teacher = convertToGpTeacherVo(map);
teachersList.add(teacher);
}
}
List<String> phones = new ArrayList<>();
// 进一步处理 teachersList
for (GpTeacherVo teacher : teachersList) {
phones.add(teacher.getPhone());
}
GpTeacherDto gpTeacherDto = new GpTeacherDto();
gpTeacherDto.setMobiles(phones);
Map<String, Object> tBase = getTeacherBase(gpTeacherDto, request);
List<GpTeacher> gpTeachers = new ArrayList<>();
for (Map.Entry<String, Object> entry : tBase.entrySet()) {
if (entry.getKey().equals("teachers")) {
List<Map<String, Object>> dataList = (List<Map<String, Object>>) entry.getValue();
for (Map<String, Object> dataMap : dataList) {
GpTeacher gpTeacher = convertToGpTeacher(dataMap);
gpTeachers.add(gpTeacher);
}
}
}
//把对应年级的信息进行映射
List<TeacherGradeVo> gradeList = new ArrayList<>();
Map<String,Object> gradeInfo = getTeacherGradeCount(teacherDto, request);
for (Map.Entry<String, Object> entry : gradeInfo.entrySet()) {
if (entry.getKey().equals("teacher")) {
List<Map<String, Object>> dataList = (List<Map<String, Object>>) entry.getValue();
for (Map<String, Object> dataMap : dataList) {
TeacherGradeVo teacherGradeVo = convertToTeacherGradeVo(dataMap);
gradeList.add(teacherGradeVo);
}
}
}
for (GpTeacherVo teacher : teachersList) {
for(GpTeacher gpTeacher : gpTeachers) {
if(StringUtils.isNotEmpty(teacher.phone) && teacher.phone.equalsIgnoreCase(gpTeacher.mobile)) {
if(gpTeacher.basic.gender != null) {
teacher.setGender(gpTeacher.basic.gender);
}else {
teacher.setGender("");
}
if (gpTeacher.getPracticeTime() != null && gpTeacher.getPracticeTime() > 0) {
teacher.setPracticeTime(gpTeacher.getPracticeTime());
}else {
teacher.setPracticeTime(0L);
}
if(gpTeacher.degree != null) {
teacher.setDegree(gpTeacher.degree);
}else {
teacher.setDegree("");
}
break;
}
}
for (TeacherGradeVo grade : gradeList) {
if(StringUtils.isNotEmpty(teacher.getId()) && teacher.getId().equals(grade.getId())) {
if(StringUtils.isNotEmpty(grade.getPeriodId())) {
teacher.setPeriodId(grade.getPeriodId());
}
List<TeacherGradeVo.IdAndName> grades = grade.getGrade();
for (TeacherGradeVo.IdAndName gg : grades) {
String id = String.valueOf(teacherDto.year - gg.getGrade());
if (teacher.grade == null) {
teacher.setGrade(new ArrayList<>());
}
teacher.grade.add(id);
}
}
}
}
teachersList = teachersList.stream()
.filter(teacher -> teacherDto.periodId.equals(teacher.getPeriodId()))
.collect(Collectors.toList());
Map<String, Long> gradeCount = new HashMap<>();
Map<String, Long> degreeCount = new HashMap<>();
Map<String, Long> subjectCount = new HashMap<>();
Map<String, Long> GroupCount = new HashMap<>();
if(StringUtils.isNotEmpty(teacherDto.getGrade()) && StringUtils.isNotEmpty(teacherDto.getSubjectId())) {
for (GpTeacherVo teacher : teachersList) {
if(teacher.getGrade() != null &&teacher.getSubjectIds() != null &&teacher.getGrade().contains(teacherDto.getGrade()) && teacher.getSubjectIds().contains(teacherDto.getSubjectId())) {
{
Long count = gradeCount.getOrDefault(teacherDto.getGrade(), 0L);
gradeCount.put(teacherDto.getGrade(), count + 1);
}
if(StringUtils.isNotEmpty(teacher.getDegree())) {
{
Long count = degreeCount.getOrDefault(teacher.getDegree(), 0L);
degreeCount.put(teacher.getDegree(), count + 1);
}
}
{
int index = teacher.subjectIds.indexOf(teacherDto.getSubjectId());
String name = "";
if (index >= 0) {
name = teacher.subjectNames.get(index);
}
Long count = subjectCount.getOrDefault(name, 0L);
subjectCount.put(name, count + 1);
}
if(teacher.getGroups() != null) {
for (GpTeacherVo.IdNameCode group : teacher.getGroups()) {
Long count = GroupCount.getOrDefault(group.getName(), 0L);
GroupCount.put(group.getName(), count + 1);
}
}
}
}
}else if(StringUtils.isEmpty(teacherDto.getGrade()) && StringUtils.isNotEmpty(teacherDto.getSubjectId())) {
for (GpTeacherVo teacher : teachersList) {
if(teacher.getSubjectIds() != null && teacher.getSubjectIds().contains(teacherDto.getSubjectId())) {
if(teacher.getGrade() != null) {
for (String grade : teacher.getGrade()) {
Long count = gradeCount.getOrDefault(grade, 0L);
gradeCount.put(grade, count + 1);
}
}
if(StringUtils.isNotEmpty(teacher.getDegree())) {
{
Long count = degreeCount.getOrDefault(teacher.getDegree(), 0L);
degreeCount.put(teacher.getDegree(), count + 1);
}
}
{
int index = teacher.subjectIds.indexOf(teacherDto.getSubjectId());
String name = "";
if (index >= 0) {
name = teacher.subjectNames.get(index);
}
Long count = subjectCount.getOrDefault(name, 0L);
subjectCount.put(name, count + 1);
}
if(teacher.getGroups() != null) {
for (GpTeacherVo.IdNameCode group : teacher.getGroups()) {
Long count = GroupCount.getOrDefault(group.getName(), 0L);
GroupCount.put(group.getName(), count + 1);
}
}
}
}
}else if(StringUtils.isNotEmpty(teacherDto.getGrade()) && StringUtils.isEmpty(teacherDto.getSubjectId())) {
for (GpTeacherVo teacher : teachersList) {
if(teacher.getGrade() != null && teacher.getGrade().contains(teacherDto.getGrade())) {
{
Long count = gradeCount.getOrDefault(teacherDto.getGrade(), 0L);
gradeCount.put(teacherDto.getGrade(), count + 1);
}
if(StringUtils.isNotEmpty(teacher.getDegree())) {
{
Long count = degreeCount.getOrDefault(teacher.getDegree(), 0L);
degreeCount.put(teacher.getDegree(), count + 1);
}
}
if(teacher.getSubjectIds()!= null) {
for (String subjectId : teacher.getSubjectIds()) {
int index = teacher.subjectIds.indexOf(subjectId);
String name = "";
if (index >= 0) {
name = teacher.subjectNames.get(index);
}
Long count = subjectCount.getOrDefault(name, 0L);
subjectCount.put(name, count + 1);
}
}
if(teacher.getGroups() != null) {
for (GpTeacherVo.IdNameCode group : teacher.getGroups()) {
Long count = GroupCount.getOrDefault(group.getName(), 0L);
GroupCount.put(group.getName(), count + 1);
}
}
}
}
}else {
for (GpTeacherVo teacher : teachersList) {
if(teacher.getGrade() != null) {
for (String grade : teacher.getGrade()) {
Long count = gradeCount.getOrDefault(grade, 0L);
gradeCount.put(grade, count + 1);
}
}
if(StringUtils.isNotEmpty(teacher.getDegree())) {
{
Long count = degreeCount.getOrDefault(teacher.getDegree(), 0L);
degreeCount.put(teacher.getDegree(), count + 1);
}
}
if(teacher.getSubjectIds()!= null) {
for (String subjectId : teacher.getSubjectIds()) {
int index = teacher.subjectIds.indexOf(subjectId);
String name = "";
if (index >= 0) {
name = teacher.subjectNames.get(index);
}
Long count = subjectCount.getOrDefault(name, 0L);
subjectCount.put(name, count + 1);
}
}
if(teacher.getGroups() != null) {
for (GpTeacherVo.IdNameCode group : teacher.getGroups()) {
Long count = GroupCount.getOrDefault(group.getName(), 0L);
GroupCount.put(group.getName(), count + 1);
}
}
}
}
gradeCount.keySet().removeIf(key -> key.startsWith("20"));
gradesMap.put("grade", gradeCount);
degreesMap.put("degree", degreeCount);
subjectsMap.put("subject", subjectCount);
groupsMap.put("group", GroupCount);
distributionList.add(gradesMap);
distributionList.add(degreesMap);
distributionList.add(subjectsMap);
distributionList.add(groupsMap);
/* Map<String, Long> genderCount = gpTeachers.stream()
.collect(Collectors.groupingBy(gpTeacher -> gpTeacher.getBasic().getGender(), Collectors.counting()));
Map<String, Long> degreeCount = gpTeachers.stream()
.filter(gpTeacher -> gpTeacher.getDegree() != null)
.collect(Collectors.groupingBy(GpTeacher::getDegree, Collectors.counting()));*/
}catch (Exception e) {
throw new ServiceException(ErrorCode.SYSTEM_ERROR.getCode(), "数据转换错误");
}
return distributionList;
}
@Override
public Map<String, Object> getTeachingAndResearch(TeacherDto teacherDto, HttpServletRequest request) {
Map<String, Object> map = new HashMap<>();
//录课数
map.put("Lessons",new Random().nextInt(100) + 1);
//T(数据)
map.put("TData",new Random().nextInt(100) + 1);
//T绿灯
map.put("TGreen",new Random().nextInt(100) + 1);
//双绿灯
map.put("DoubleGreen",new Random().nextInt(100) + 1);
//观课数
map.put("WLessons",new Random().nextInt(100) + 1);
//议课数
map.put("TLessons",new Random().nextInt(100) + 1);
//频道数
map.put("Channels",new Random().nextInt(20) + 1);
//公开课
map.put("OLessons",new Random().nextInt(100) + 1);
//课件数
map.put("Coursewares",new Random().nextInt(100) + 1);
//教案数
map.put("TeachingPlan",new Random().nextInt(40) + 1);
//公开标记
map.put("OMarkers",new Random().nextInt(30) + 1);
//个人标记
map.put("PMarkers",new Random().nextInt(30) + 1);
//被标记数
map.put("TMarkers",new Random().nextInt(30) + 1);
//被点阅数
map.put("ClickAndRead",new Random().nextInt(100) + 1);
return map;
}
@Override
public List<LinkedHashMap<String,LinkedHashMap<String,Object>>> getTeachingOfTeacher(TeacherDto teacherDto, HttpServletRequest request) {
List<LinkedHashMap<String,LinkedHashMap<String,Object>>> list = new ArrayList<>();
if(teacherDto.getGrade() != null) {
LinkedHashMap<String,LinkedHashMap<String,Object>> map = new LinkedHashMap<>();
LinkedHashMap<String,Object> mapTeach = new LinkedHashMap<>();
mapTeach.put("interaction", new Random().nextInt(50) + 1);
mapTeach.put("cooperation", new Random().nextInt(50) + 1);
mapTeach.put("test", new Random().nextInt(50) + 1);
mapTeach.put("quest", new Random().nextInt(50) + 1);
mapTeach.put("differentiation", new Random().nextInt(50) + 1);
map.put(teacherDto.getGrade(), mapTeach);
list.add(map);
}else {
List<School> school = schoolRepository.findBaseById(teacherDto.getCode());
List<String> grades = getGrades(teacherDto, school);
LinkedHashMap<String,LinkedHashMap<String,Object>> map = new LinkedHashMap<>();
for (String grade : grades) {
LinkedHashMap<String,Object> mapTeach = new LinkedHashMap<>();
mapTeach.put("interaction", new Random().nextInt(50) + 1);
mapTeach.put("cooperation", new Random().nextInt(50) + 1);
mapTeach.put("test", new Random().nextInt(50) + 1);
mapTeach.put("quest", new Random().nextInt(50) + 1);
mapTeach.put("differentiation", new Random().nextInt(50) + 1);
map.put(grade, mapTeach);
}
list.add(map);
}
return list;
}
private static @NotNull List<String> getGrades(TeacherDto teacherDto, List<School> school) {
List<String> grades = new ArrayList<>();
if(school != null && !school.isEmpty()) {
for (School base : school) {
for (School.Period period : base.getPeriod()) {
if(period.getId().equals(teacherDto.getPeriodId())) {
for(String grade : period.getGrades()) {
grades.add(grade.trim());
}
}
}
}
}
return grades;
}
public Map<String, Object> getTeacherBase(GpTeacherDto gpTeacherDto, HttpServletRequest request) {
Map<String, Object> gradeMap;
try {
gradeMap = GroupUtil.getTeacherInfo(gpTeacherDto,new GroupUtil(env), request);
}catch (Exception e) {
throw new ServiceException(ErrorCode.SYSTEM_ERROR.getCode(), "国培数据转换错误");
}
return gradeMap;
}
private static @NotNull Map<String, Integer> getStringIntegerMap(List<School.Subject> subjects, List<SchoolTeacher> schoolTeachers) {
Map<String, String> subjectNameMap = new HashMap<>();
for (School.Subject subject : subjects) {
subjectNameMap.put(subject.getId(), subject.getName());
}
Map<String, Integer> subjectCountMap = new HashMap<>();
// 遍历所有教师
for (SchoolTeacher teacher : schoolTeachers) {
// 获取教师的科目列表
List<String> subjectIds = teacher.getSubjectIds();
if (subjectIds != null) {
for (String subjectId : subjectIds) {
// 更新每个科目的教师数量
subjectCountMap.put(subjectId, subjectCountMap.getOrDefault(subjectId, 0) + 1);
}
}
}
Map<String, Integer> updatedSubjectCountMap = new HashMap<>();
for (Map.Entry<String, Integer> entry : subjectCountMap.entrySet()) {
String subjectId = entry.getKey();
Integer count = entry.getValue();
String subjectName = subjectNameMap.get(subjectId);
if (subjectName != null) {
updatedSubjectCountMap.put(subjectName, count);
}
}
return updatedSubjectCountMap;
}
private static @NotNull Map<String, Integer> getPeriodCountMap(List<School.Period> periods,List<SchoolTeacher> schoolTeachers) {
Map<String, Integer> periodCountMap = new HashMap<>();
for (School.Period period : periods) {
for ( School.Subject subject : period.getSubjects()) {
for (SchoolTeacher schoolTeacher : schoolTeachers) {
if (schoolTeacher.getSubjectIds().contains(subject.getId())) {
periodCountMap.put(period.getId(), periodCountMap.getOrDefault(period.getId(), 0) + 1);
}
}
}
}
Map<String, String> periodNameMap = new HashMap<>();
List<String> periodNames = new ArrayList<>();
for (School.Period period : periods) {
periodNameMap.put(period.getId(), period.getName());
periodNames.add(period.getName());
}
//Map<String, Integer> periodCountMap = getStringIntegerMap(groupLists);
// 更新 periodCountMap 的 key 为 period 名称
Map<String, Integer> updatedPeriodCountMap = new HashMap<>();
for (Map.Entry<String, Integer> entry : periodCountMap.entrySet()) {
String periodId = entry.getKey();
Integer count = entry.getValue();
String periodName = periodNameMap.get(periodId);
if (periodName != null) {
updatedPeriodCountMap.put(periodName, count);
}
}
for (String periodName : periodNames) {
if(!updatedPeriodCountMap.containsKey(periodName)) {
updatedPeriodCountMap.put(periodName, 0);
}
}
return updatedPeriodCountMap;
}
/*private static @NotNull Map<String, Integer> getStringIntegerMap(List<GroupList> groupLists) {
Map<String, Integer> periodCountMap = new HashMap<>();
// 遍历所有 GroupList 对象
for (GroupList group : groupLists) {
// 获取 periodId
String periodId = group.getPeriodId();
if (periodId != null) {
// 计算成员数量
int memberCount = (int) group.getMembers().stream().filter(member -> member.type == 1).count();
// 更新 periodCountMap
periodCountMap.put(periodId, periodCountMap.getOrDefault(periodId, 0) + memberCount);
}
}
return periodCountMap;
}*/
}

@ -0,0 +1,170 @@
package cn.teammodel.controller.frontend;
import cn.teammodel.common.IdRequest;
import cn.teammodel.common.R;
import cn.teammodel.model.dto.ai.*;
import cn.teammodel.model.dto.ai.comment.ChatCommentsDto;
import cn.teammodel.model.entity.TmdUserDetail;
import cn.teammodel.model.entity.ai.ChatApp;
import cn.teammodel.model.entity.ai.ChatSession;
import cn.teammodel.security.utils.SecurityUtil;
import cn.teammodel.service.ChatAppService;
import cn.teammodel.service.ChatMessageService;
import cn.teammodel.service.ChatSessionService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@RestController
@RequestMapping("/ai")
@Api(tags = "AI 能力")
public class AiController {
@Resource
private ChatSessionService chatSessionService;
@Resource
private ChatMessageService chatMessageService;
@Resource
private ChatAppService chatAppService;
@PostMapping("api/chat/completion")
@ApiOperation("与 spark 的流式对话")
public SseEmitter chatCompletionToApi(@RequestBody @Valid ChatCompletionReqDto chatCompletionReqDto) {
String userId = ((TmdUserDetail) SecurityUtil.getAuthentication().getPrincipal()).getClaims().getSubject();
return chatMessageService.chatCompletion(chatCompletionReqDto, userId);
}
@PostMapping("chat/completion")
@ApiOperation("与 spark 的流式对话")
public SseEmitter chatCompletion(@RequestBody @Valid ChatCompletionReqDto chatCompletionReqDto) {
return chatMessageService.chatCompletion(chatCompletionReqDto, null);
}
@PostMapping("chat/test/completion")
@ApiOperation("与 spark 的流式对话")
public SseEmitter testCompletion(@RequestBody @Valid ChatCompletionReqDto chatCompletionReqDto) throws IOException, InterruptedException {
SseEmitter sseEmitter = new SseEmitter();
CompletableFuture.runAsync(() -> {
try {
sseEmitter.send("曾经以为我们");
Thread.sleep(1000);
sseEmitter.send("开始了就会走到最后,可是当分手之后才明白我想的");
Thread.sleep(1000);
sseEmitter.send("你不一定能做到,当我开始去遗忘我们");
Thread.sleep(1500);
sseEmitter.send("的经历时,却不知道遗忘已变成另一种开始,");
Thread.sleep(800);
sseEmitter.send("回忆是淡了,可是痛却还在,还是最真实。放手的时候微笑着说无所谓");
Thread.sleep(800);
sseEmitter.send(",离开了你我还可以过的很好");
Thread.sleep(1000);
sseEmitter.send(",而你却不知道微笑只是用来掩盖疼痛的伤疤。");
Thread.sleep(1200);
sseEmitter.send("离开你之后的自己陷入一种无助的状态,空洞的");
Thread.sleep(1300);
sseEmitter.send("双眼回忆不起曾经的你,那时候以为与世隔绝或许才是维护自己的最好方式。");
Thread.sleep(1100);
sseEmitter.send("[DONE]");
sseEmitter.complete();
} catch (IOException | InterruptedException e) {
throw new RuntimeException(e);
}
});
return sseEmitter;
}
@GetMapping("api/session/my")
@ApiOperation("查询我的聊天会话")
public R<List<ChatSession>> listMySession() {
String userId = ((TmdUserDetail) SecurityUtil.getAuthentication().getPrincipal()).getClaims().getSubject();
List<ChatSession> sessions = chatSessionService.listMySession(userId);
return R.success(sessions);
}
@GetMapping("api/chat/history/{sessionId}")
@ApiOperation("查询我的聊天记录")
public R<List<ChatSession.Message>> getHistory(@PathVariable String sessionId) {
String userId = ((TmdUserDetail) SecurityUtil.getAuthentication().getPrincipal()).getClaims().getSubject();
List<ChatSession.Message> history = chatSessionService.listHistory(sessionId, userId);
return R.success(history);
}
@PostMapping("api/session/create")
@ApiOperation("创建聊天会话")
public R<String> createSession() {
String userId = ((TmdUserDetail) SecurityUtil.getAuthentication().getPrincipal()).getClaims().getSubject();
String name = (String) ((TmdUserDetail) SecurityUtil.getAuthentication().getPrincipal()).getClaims().get("name");
name = StringUtils.isBlank(name) ? "老师" : name;
String sessionId = chatSessionService.createSession(userId, name);
return R.success(sessionId);
}
@PostMapping("api/session/remove")
@ApiOperation("删除聊天会话")
public R<String> removeSession(@RequestBody @Valid IdRequest idRequest) {
String userId = ((TmdUserDetail) SecurityUtil.getAuthentication().getPrincipal()).getClaims().getSubject();
chatSessionService.deleteSession(idRequest.getId(), userId);
return R.success("删除会话成功");
}
@PostMapping("api/session/update")
@ApiOperation("更新聊天会话")
public R<ChatSession> updateSession(@RequestBody @Valid UpdateSessionDto updateSessionDto) {
String userId = ((TmdUserDetail) SecurityUtil.getAuthentication().getPrincipal()).getClaims().getSubject();
ChatSession session = chatSessionService.updateSession(updateSessionDto, userId);
return R.success(session);
}
@PostMapping("app/list")
@ApiOperation("查询聊天应用列表")
public R<List<ChatApp>> listApp(@RequestBody @Valid SearchAppDto searchAppDto) {
List<ChatApp> chatApps = chatAppService.listApp(searchAppDto);
return R.success(chatApps);
}
@PostMapping("app/create")
@ApiOperation("创建聊天应用")
public R<ChatApp> createApp(@RequestBody @Valid CreateChatAppDto createChatAppDto) {
ChatApp chatApp = chatAppService.createApp(createChatAppDto);
return R.success(chatApp);
}
@PostMapping("app/update")
@ApiOperation("更新聊天应用")
public R<ChatApp> updateApp(@RequestBody @Valid UpdateChatAppDto updateChatAppDto) {
ChatApp chatApp = chatAppService.updateApp(updateChatAppDto);
return R.success(chatApp);
}
@PostMapping("app/remove")
@ApiOperation("删除聊天应用")
public R<String> updateApp(@RequestBody @Valid IdRequest idRequest) {
chatAppService.deleteApp(idRequest);
return R.success("删除应用成功");
}
@PostMapping("chat/comments")
@ApiOperation("设置评语")
public SseEmitter chatComments(@RequestBody @Valid ChatCommentsDto chatCommentsDto) {
//String userId = ((TmdUserDetail) SecurityUtil.getAuthentication().getPrincipal()).getClaims().getSubject();
// 获取getClaims时为空
String userId = ((TmdUserDetail) SecurityUtil.getAuthentication().getPrincipal()).getUser().getId();
String userName = ((TmdUserDetail) SecurityUtil.getAuthentication().getPrincipal()).getUser().getName();
//获取会话id 看是否有sessionId 有则直接赋值 没有则赋值userId
String sessionId = StringUtils.isBlank(chatCommentsDto.getSessionId()) ? userId: chatCommentsDto.getSessionId();
chatCommentsDto.setSessionId(sessionId);
int repeat = chatCommentsDto.getRepeat();
if (repeat <= 1)
{
chatCommentsDto.setRepeat(repeat);
}
return chatMessageService.chatComments(chatCommentsDto, userId, userName);
}
}

@ -0,0 +1,94 @@
package cn.teammodel.controller.frontend;
import cn.teammodel.common.IdRequest;
import cn.teammodel.common.R;
import cn.teammodel.model.dto.Appraise.*;
import cn.teammodel.model.entity.appraise.Appraise;
import cn.teammodel.model.vo.appraise.AppraiseRecordVo;
import cn.teammodel.model.vo.appraise.StudentReportVo;
import cn.teammodel.service.EvaluationService;
import com.itextpdf.text.DocumentException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.List;
/**
* @author winter
* @create 2023-11-22 15:10
*/
@RestController
@RequestMapping("/appraise")
@Api(tags = "学生评价")
public class AppraiseController {
@Resource
private EvaluationService evaluationService;
@PostMapping("getTrees")
@ApiOperation(value = "获取评价树", notes = "获取评价树")
public R<Appraise> getEvaluateTree(@RequestBody @Valid GetEvaluateTreeDto getEvaluateTreeDto) {
Appraise appraise = evaluationService.getTree(getEvaluateTreeDto);
return R.success(appraise);
}
@PostMapping("insertNode")
@ApiOperation(value = "新增评价树的节点")
public R<Appraise> insertNode(@RequestBody @Valid InsertNodeDto insertNodeDto) {
Appraise appraise = evaluationService.insertNode(insertNodeDto);
return R.success(appraise);
}
@PostMapping("updateNode")
@ApiOperation(value = "更新评价树的节点", notes = "传递更新后的节点,而不是局部更新的值")
public R<Appraise> updateTree(@RequestBody @Valid UpdateNodeDto updateNodeDto) {
// fixme: 更新一二级节点应该同时更新三级的 path
Appraise appraise = evaluationService.updateNode(updateNodeDto);
return R.success(appraise);
}
@PostMapping("deleteNode")
@ApiOperation(value = "删除评价树的节点")
public R<Appraise> deleteNode(@RequestBody @Valid DeleteNodeDto deleteNodeDto) {
Appraise appraise = evaluationService.deleteNode(deleteNodeDto);
return R.success(appraise);
}
@PostMapping("vote")
@ApiOperation(value = "给某个学生评价(投票)")
public R<String> vote(@RequestBody @Valid AppraiseVoteDto appraiseVoteDto) {
evaluationService.vote(appraiseVoteDto);
return R.success("评价成功");
}
@PostMapping("recallVote")
@ApiOperation(value = "撤回给某个学生评价(投票)")
public R<String> recallVote(@RequestBody @Valid RecallVoteDto recallVoteDto) {
evaluationService.recallVote(recallVoteDto);
return R.success("撤回评价成功");
}
@PostMapping("findVoteRecord")
@ApiOperation(value = "多条件查询当前登录老师的学生评价(投票)")
public R<List<AppraiseRecordVo>> findMyVoteRecord(@Valid @RequestBody FindVoteRecordDto findVoteRecordDto) {
List<AppraiseRecordVo> res = evaluationService.findVoteRecord(findVoteRecordDto);
return R.success(res);
}
@PostMapping("studentReport")
@ApiOperation(value = "查看学生当前的学期的实时评价报告")
public R<StudentReportVo> studentReport(@Valid @RequestBody IdRequest idRequest) {
StudentReportVo res = evaluationService.studentReport(idRequest);
return R.success(res);
}
@PostMapping("studentReportPDF")
@ApiOperation(value = "导出学生当前的学期的实时评价报告 PDF")
public void exportStuReportPdf(@Valid @RequestBody IdRequest idRequest, HttpServletResponse response) throws DocumentException, IOException {
evaluationService.exportStuReportPdf(idRequest, response);
}
}

@ -0,0 +1,93 @@
package cn.teammodel.controller.frontend;
import cn.teammodel.common.IdRequest;
import cn.teammodel.common.R;
import cn.teammodel.model.dto.weekDuty.*;
import cn.teammodel.model.entity.weekDuty.WeekDuty;
import cn.teammodel.model.vo.weekDuty.DutyRecordVo;
import cn.teammodel.service.DutyService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;
/**
* @author winter
* @create 2024-01-03 10:06
*/
@RestController
@RequestMapping("/duty")
@Api(tags = "值周巡检")
public class DutyController {
@Resource
private DutyService dutyService;
@GetMapping("/getTree")
@ApiOperation("获取值周评价标准树(不存在则拷贝模板)")
public R<WeekDuty> getTree() {
WeekDuty weekDuty = dutyService.getTree();
return R.success(weekDuty);
}
@PostMapping("/insertNode")
@ApiOperation("插入值周评价标准树节点")
public R<WeekDuty> insertNode(@RequestBody @Valid InsertDutyNodeDto insertDutyNodeDto) {
WeekDuty weekDuty = dutyService.insertNode(insertDutyNodeDto);
return R.success(weekDuty);
}
@PostMapping("/deleteNode")
@ApiOperation("删除值周评价标准树节点")
public R<WeekDuty> deleteNode(@RequestBody @Valid DeleteDutyNodeDto deleteDutyNodeDto) {
WeekDuty weekDuty = dutyService.deleteNode(deleteDutyNodeDto);
return R.success(weekDuty);
}
@PostMapping("/updateNode")
@ApiOperation("更新值周评价标准树节点")
public R<WeekDuty> updateNode(@RequestBody @Valid UpdateDutyNodeDto updateDutyNodeDto) {
WeekDuty weekDuty = dutyService.updateNode(updateDutyNodeDto);
return R.success(weekDuty);
}
@PostMapping("/vote")
@ApiOperation("值周评价投票")
public R<String> vote(@RequestBody @Valid DutyVoteDto dutyVoteDto) {
dutyService.vote(dutyVoteDto);
return R.success("评价成功");
}
@PostMapping("/recallVote")
@ApiOperation("撤回评价投票")
public R<String> recallVote(@RequestBody @Valid RecallDutyVoteDto recallDutyVoteDto) {
dutyService.recallVote(recallDutyVoteDto);
return R.success("撤回评价成功");
}
@PostMapping("/insertSpot")
@ApiOperation("插入值周评价地点")
public R<List<WeekDuty.DutySpot>> insertSpot(@RequestBody @Valid InsertSpotDto insertSpotDto) {
List<WeekDuty.DutySpot> spots = dutyService.insertSpot(insertSpotDto);
return R.success(spots);
}
@PostMapping("/deleteSpot")
@ApiOperation("删除值周评价地点")
public R<List<WeekDuty.DutySpot>> deleteSpot(@RequestBody @Valid IdRequest idRequest) {
List<WeekDuty.DutySpot> spots = dutyService.deleteSpot(idRequest.getId());
return R.success(spots);
}
@PostMapping("/findRecords")
@ApiOperation(value = "多条件查询评价明细", notes = "只带 periodId 默认查询当前登录老师在本周的评价明细")
public R<List<DutyRecordVo>> findRecords(@RequestBody @Valid FindDutyRecordDto findDutyRecordDto) {
List<DutyRecordVo> items = dutyService.findRecords(findDutyRecordDto);
return R.success(items);
}
}

@ -0,0 +1,98 @@
package cn.teammodel.controller.frontend;
import cn.teammodel.common.R;
import cn.teammodel.model.entity.school.Teacher;
import cn.teammodel.repository.AppraiseRepository;
import cn.teammodel.repository.TeacherRepository;
import cn.teammodel.service.EvaluationService;
import com.itextpdf.text.DocumentException;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@RestController
@RequestMapping("/")
@Api(tags = "鉴权测试")
public class HelloController {
@Resource
private EvaluationService evaluationService;
@Resource
private AppraiseRepository appraiseRepository;
@Resource
private TeacherRepository teacherRepository;
@Autowired
private Environment env;
@GetMapping("hello")
@PreAuthorize("@ss.hasRole('admin')")
public R<String> hello() {
System.out.println(SecurityContextHolder.getContext().getAuthentication());
return new R(200, "success","hello world");
}
@GetMapping("public/free")
@PreAuthorize("permitAll()")
public R<String> free() {
return new R(200, "success","hello world");
}
@GetMapping("public/curr")
public R<String> curr() {
String curr = env.getProperty("spring.env");
HashSet<String> set= new HashSet<String>() ;
set.add("1595321354");
List<Teacher> techers= teacherRepository.findAllByCodeAndIdIn("Base", set);
return new R(200, techers,curr);
}
@GetMapping("public/pdf")
public void freepdf(HttpServletResponse response) throws DocumentException, IOException { // 设置response参数
// response.reset();
// response.setContentType("application/pdf");
// response.setHeader("Content-disposition",
// "attachment;filename=report_student_" + System.currentTimeMillis() + ".pdf");
// ClassPathResource resource = new ClassPathResource("templates/pdf_templates/student_report.pdf");
// InputStream in = resource.getInputStream();
// ServletOutputStream os = response.getOutputStream();
// // 处理 stampter
// PdfReader pdfReader = new PdfReader(in);
// PdfStamper stamper = new PdfStamper(pdfReader, os);
//
// Map<String, String> data = PdfUtil.data();
// DefaultPieDataset dataset = new DefaultPieDataset( );
// dataset.setValue( "IPhone 5s" , new Double( 20 ) );
// dataset.setValue( "SamSung Grand" , new Double( 20 ) );
// dataset.setValue( "MotoG" , new Double( 40 ) );
// dataset.setValue( "Nokia Lumia" , new Double( 10 ) );
//
// JFreeChart pieChart = ChartUtil.pieChart("手机销量统计", dataset);
// ByteArrayOutputStream bos = new ByteArrayOutputStream();
// ChartUtils.writeChartAsJPEG(bos, pieChart, 850, 440);
// // 填充表单
// PdfUtil.fillPdfForm(stamper, data);
// PdfUtil.fillImage(stamper, "praiseDistribution", bos.toByteArray());
// PdfUtil.fillImage(stamper, "criticalDistribution", bos.toByteArray());
// // 关闭流
// stamper.setFormFlattening(true);
// stamper.close();
// os.close();
//
}
}

@ -0,0 +1,63 @@
package cn.teammodel.controller.frontend;
import cn.teammodel.common.IdRequest;
import cn.teammodel.common.R;
import cn.teammodel.model.dto.news.CreateNewsDto;
import cn.teammodel.model.dto.news.UpdateNewsDto;
import cn.teammodel.model.entity.news.News;
import cn.teammodel.service.NewsService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;
/**
* @author winter
* @create 2024-02-26 17:04
*/
@RestController
@RequestMapping("/news")
@Api(tags = "新闻设置")
public class NewsController {
@Resource
private NewsService newsService;
@GetMapping("list/{periodId}")
@ApiOperation("查询新闻")
public R<List<News>> listNews(@PathVariable String periodId) {
List<News> Newss = newsService.listNews(periodId);
return R.success(Newss);
}
@GetMapping("get/{newsId}")
@ApiOperation("根据id查询新闻")
public R<News> getNewsById(@PathVariable String newsId) {
News news = newsService.getNewsById(newsId);
return R.success(news);
}
@PostMapping("create")
@ApiOperation("创建新闻")
public R<News> createNews(@RequestBody @Valid CreateNewsDto createNewsDto) {
News News = newsService.createNews(createNewsDto);
return R.success(News);
}
@PostMapping("update")
@ApiOperation("更新新闻")
public R<News> updateNews(@RequestBody @Valid UpdateNewsDto updateNewsDto) {
News News = newsService.updateNews(updateNewsDto);
return R.success(News);
}
@PostMapping("remove")
@ApiOperation("删除新闻")
public R<String> deleteNews(@RequestBody @Valid IdRequest idRequest) {
newsService.deleteNews(idRequest);
return R.success("删除新闻成功");
}
}

@ -0,0 +1,44 @@
package cn.teammodel.manager.notification;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiRobotSendRequest;
import com.taobao.api.ApiException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
*
* @author winter
* @create 2023-11-14 10:11
*/
@Component
@Slf4j
public class DingAlertNotifier implements NotificationService{
private final DingTalkClient client;
@Autowired
public DingAlertNotifier(@Value("${ding.server-url}") String dingServerUrl) {
this.client = new DefaultDingTalkClient(dingServerUrl);
}
@Override
public void send(String message) {
OapiRobotSendRequest request = new OapiRobotSendRequest();
// 文本消息
request.setMsgtype("text");
OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text();
text.setContent(message);
request.setText(text);
// at 管理员提醒异常
OapiRobotSendRequest.At atAll = new OapiRobotSendRequest.At();
atAll.setIsAtAll(true);
request.setAt(atAll);
try {
client.execute(request);
} catch (ApiException e) {
log.error("钉钉 robot 推送消息渠道异常: {}", e.getMessage());
}
}
}

@ -0,0 +1,16 @@
package cn.teammodel.manager.notification;
/**
*
* @author winter
* @create 2023-11-14 10:08
*/
public interface NotificationService {
/**
*
* @author: winter
* @date: 2023/11/14 10:09
*/
void send(String message);
}

@ -0,0 +1,12 @@
package cn.teammodel.manager.wx;
import org.springframework.stereotype.Service;
/**
* @author winter
* @create 2024-03-26 11:08
*/
@Service
public class MiniProgramSevice {
}

@ -0,0 +1,33 @@
package cn.teammodel.model.dto.Appraise;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* @author winter
* @create 2023-11-28 16:16
*/
@Data
public class AppraiseVoteDto {
@NotNull
@ApiModelProperty(value = "评价对象 Id")
private String targetId;
@NotNull
@ApiModelProperty(value = "评价对象类型:", allowableValues = "student ,class")
private String targetType;
@ApiModelProperty(value = "评分是否传播到班级下的所有学生(评价 CLASS 时生效)")
private boolean spread;
@ApiModelProperty(value = "是否推送给家长(评价 STUDENT 时生效)")
private boolean pushParent;
/**
* id
*/
@NotNull
@ApiModelProperty(value = "评价项唯一 id", required = true)
private String appraiseId;
}

@ -0,0 +1,17 @@
package cn.teammodel.model.dto.Appraise;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* @author winter
* @create 2023-11-22 16:16
*/
@Data
public class DeleteNodeDto {
@NotNull(message = "学段 id 不能为空")
String periodId;
@NotNull(message = "评价项节点 id 不能为空")
String id;
}

@ -0,0 +1,32 @@
package cn.teammodel.model.dto.Appraise;
import cn.teammodel.common.PageableRequest;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotNull;
/**
* @author winter
* @create 2023-11-28 16:16
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class FindVoteRecordDto extends PageableRequest {
@NotNull
@ApiModelProperty(value = "必要参数,用于获取当前学年,注意: 其他参数不传则默认获取登录老师在该学年下评价的所有记录", required = true)
private String periodId;
@ApiModelProperty(value = "班级或学生 id")
private String targetId;
@ApiModelProperty(value = "评价对象类型:", allowableValues = "student ,class")
private String targetType;
@ApiModelProperty(value = "按班级 id 搜索")
private String classId;
@ApiModelProperty(value = "是否为表扬")
private Boolean isPraise;
}

@ -0,0 +1,17 @@
package cn.teammodel.model.dto.Appraise;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* @author winter
* @create 2023-11-22 15:21
*/
@Data
public class GetEvaluateTreeDto {
@ApiModelProperty(value = "学段 id", required = true)
@NotNull(message = "学段 id 不能为空")
String periodId;
}

@ -0,0 +1,27 @@
package cn.teammodel.model.dto.Appraise;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* @author winter
* @create 2023-11-22 16:16
*/
@Data
public class InsertNodeDto {
@ApiModelProperty(value = "学段 id", required = true)
@NotNull(message = "学段 id 不能为空")
String periodId;
@ApiModelProperty(value = "父亲节点,不传则为根节点")
String pid;
@ApiModelProperty(value = "父亲节点,不传则为根节点", required = true)
@NotBlank(message = "name 不能为空")
String name;
String logo;
Integer order = 0;
Integer score = 0;
Boolean isPraise = true;
}

@ -0,0 +1,20 @@
package cn.teammodel.model.dto.Appraise;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* @author winter
* @create 2023-11-22 16:16
*/
@Data
public class RecallVoteDto {
@NotNull
@ApiModelProperty(value = "学生评价记录的文档id", required = true)
String recordId;
@NotNull
@ApiModelProperty(value = "学生评价记录的具体节点id", required = true)
String nodeId;
}

@ -0,0 +1,23 @@
package cn.teammodel.model.dto.Appraise;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* @author winter
* @create 2023-11-22 16:16
*/
@Data
public class UpdateNodeDto {
@ApiModelProperty(value = "学段 id", required = true)
@NotNull(message = "学段 id 不能为空")
String periodId;
@ApiModelProperty(value = "评价项节点的 id")
String id;
String name;
String logo;
Integer order;
boolean isPraise;
}

@ -0,0 +1,19 @@
package cn.teammodel.model.dto.admin.appraise;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* @author winter
* @since 2023-12-06 19:03
*/
@Data
public class TimeRangeDto {
private Long startTime;
private Long endTime;
@NotNull
private String periodId;
@NotNull
// todo: 似乎不需要(有时间范围就不需要这个字段来划分时间,如果不传时间那就需要)
private String academicYearId;
}

@ -0,0 +1,34 @@
package cn.teammodel.model.dto.admin.appraise;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* @author winter
* @create 2023-12-13 17:34
*/
@Data
public class UpdateAchievementRuleDto {
@NotNull
@ApiModelProperty("学段 id")
private String periodId;
@ApiModelProperty("更新的 rule 节点: 将会直接覆盖老节点")
private UpdateRule updateRule;
@Data
public static class UpdateRule {
private String id;
/**
*
*/
private String name = "";
@ApiModelProperty("等级 logo")
private String logo = "";
@ApiModelProperty("每次所需表扬数")
private Integer levelCount = 0;
@ApiModelProperty("晋级所需下一等级所需当前等级次数")
private Integer promotionLevel = 0;
}
}

@ -0,0 +1,26 @@
package cn.teammodel.model.dto.admin.art;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@Data
public class ArtAnalysisDto {
@ApiModelProperty("艺术活动唯一ID")
public String id;
@ApiModelProperty("科目ID 针对艺术评测 ID如下 subject_music 为音乐 subject_painting为美术")
public String subjectId;
@ApiModelProperty("学校编码")
public String code;
@ApiModelProperty("学段ID")
public String periodId;
@ApiModelProperty("区域ID 为了获取当前学校所在区域 配置内容")
public String areaId;
@ApiModelProperty("艺术评测下的评测id 可根据回传的settings里面指标quota_21获取子对象的acId")
public String examId;
@ApiModelProperty("班级ID集合为了查询效率减少数据回传过大的问题目前设计了几种方式查询年级 则传该年级所有班级ID集合此方式下不会返回学生数据查指定班级则传对应班级ID即可")
List<String> classIds;
}

@ -0,0 +1,21 @@
package cn.teammodel.model.dto.admin.art;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
@Data
public class ArtFindDto
{
@ApiModelProperty("学校编码")
private String code;
@ApiModelProperty("学段ID")
private String periodId;
@ApiModelProperty("学段类型")
private String periodType;
@ApiModelProperty("开始时间")
private Long startTime;
@ApiModelProperty("结束时间")
private Long endTime;
}

@ -0,0 +1,19 @@
package cn.teammodel.model.dto.admin.art;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class DataFileCommentDto {
private String artId;
private String schoolId;
private String schoolCode;
private String headLang;
private String studentId;
@ApiModelProperty(value = "自定义评语,不传或者传空字符串代表清空之前的")
private String comment;
@ApiModelProperty(value = "自定义评语音乐,不传或者传空字符串代表清空之前的")
private String comment_music;
@ApiModelProperty(value = "自定义评语美术,不传或者传空字符串代表清空之前的")
private String comment_painting;
}

@ -0,0 +1,15 @@
package cn.teammodel.model.dto.admin.art;
import lombok.Data;
import java.util.List;
@Data
public class DataFileDto {
private String artId;
private String schoolId;
private String schoolCode;
private String opt;
private String headLang;
List<String> studentIds;
}

@ -0,0 +1,14 @@
package cn.teammodel.model.dto.admin.common;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@Data
public class CommentDto {
@ApiModelProperty("需要删除的id集合")
private List<String> ids;
@ApiModelProperty("完成的编码如Comment-hbcn")
private String code;
}

@ -0,0 +1,10 @@
package cn.teammodel.model.dto.admin.common;
import lombok.Data;
@Data
public class GCDto {
private String schoolId;
private String periodId;
private Long time;
}

@ -0,0 +1,11 @@
package cn.teammodel.model.dto.admin.common;
import lombok.Data;
import java.util.List;
@Data
public class GroupDto {
public List<String> ids;
public String schoolId;
}

@ -0,0 +1,73 @@
package cn.teammodel.model.dto.admin.common;
import lombok.Data;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
@Data
public class RGroupList {
public String id ;
public String code ;
public String pk ;
public String name ;
//标记该名单唯一code
public String no ;
public String periodId ;
//课程id,需要标记则标记
//public String courseId ;
public String scope ;
public String school ;
public String creatorId ;
/// <summary>
///研修培训名单yxtrain 教学班teach 行政班学生搜寻classId动态返回class ,教研组research学科组学科搜寻动态返回subject好友friend管理manage群组group等,"activity",
///TeacherAll 全体教师StudentAll全体学生 TchStuAll全体师生 动态返回
/// </summary>
public String type ;
public int year ;
/// <summary>
/// 名单过期时间。
/// </summary>
public long expire ;
/// <summary>
/// 醍摩豆id成员数量
/// </summary>
public int tcount ;
/// <summary>
/// 校内账号成员数量
/// </summary>
public int scount ;
public List<RMember> members = new ArrayList<>();
public String leader ;
public int froms ;
/// <summary>
/// 个人名单是否开放 加入。0 不允许1 允许。
/// </summary>
public int joinLock ;
/// <summary>
///补充毕业0在校1毕业
/// </summary>
public int graduate ;
/// <summary>
/// 是否开启审核0未开启1开启。
/// </summary>
public int review ;
/// <summary>
/// 加入人数200人学生加入已满200 自动关闭加入。可手动解除限制,开启审核时,关闭人数上限设置机制
/// </summary>
public int limitCount ;
/// <summary>
/// 自选座号 0 不允许1 运行
/// </summary>
public int optNo ;
/// <summary>
/// 二维码过期时间
/// </summary>
public long qrcodeExpire ;
/// <summary>
/// 二维码 天数
/// </summary>
public int qrcodeDays ;
public HashSet<Integer> grades = new HashSet<Integer>();
}

@ -0,0 +1,73 @@
package cn.teammodel.model.dto.admin.common;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
@Data
public class RMember {
/// <summary>
/// 账号id
/// </summary>
public String id ;
//学生所在的学校
public String code ;
//兼容HiTeach 需要的字段
public String schoolId ;
//学生所在的学校
public String schoolName ;
/// <summary>
/// 名称
/// </summary>
public String name ;
/// <summary>
///类型 1 tmdid,2 student
/// </summary>
public int type ;
/// <summary>
/// 头像
/// </summary>
public String picture ;
/// <summary>
/// 性别 M( male,男) F (female 女) N(secret 保密)
/// </summary>
public String gender ;
/// <summary>
///座号
/// </summary>
public String no ;
/// <summary>
/// IRS WebIRS编号。
/// </summary>
public String irs ;
public String tag ;
/// <summary>
/// 行政班
/// </summary>
public String classId ;
/// <summary>
/// 名单分组id
/// </summary>
public String groupId ;
/// <summary>
/// 名单分组名称
/// </summary>
public String groupName ;
public String nickname ;
//补充毕业
//0在校1毕业
public int graduate ;
//所在名单集合
public List<String> groupListIds = new ArrayList<String>();
public int year ;
public String periodId ;
/// <summary>
/// 0 自动的座号和irs,1 手动的irs
/// </summary>
public int manual ;
}

@ -0,0 +1,22 @@
package cn.teammodel.model.dto.admin.exam;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class AnalysisDto {
@ApiModelProperty("学校编码")
private String code;
@ApiModelProperty("当前学校指定学段")
private String period;
@ApiModelProperty("当前评测活动所属范围,目前制定查询属于学校的数据,直接传 school")
private String owner;
@ApiModelProperty("指定查询的条数,为了后续滚动翻页")
private int count;
@ApiModelProperty("翻页参数,后续滚动翻页回传给后端,没有就不管")
private String token;
@ApiModelProperty("开始时间")
private Long startTime;
@ApiModelProperty("结束时间")
private Long endTime;
}

@ -0,0 +1,10 @@
package cn.teammodel.model.dto.admin.exam;
import lombok.Data;
@Data
public class BlobSasDto {
public String name;
public String role;
public String code;
}

@ -0,0 +1,19 @@
package cn.teammodel.model.dto.admin.exam;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class ExamRecordDto {
@ApiModelProperty("班级ID")
private String classId;
@ApiModelProperty("学校编码")
private String code;
@ApiModelProperty("该活动唯一ID")
private String id;
@ApiModelProperty("科目ID")
private String subjectId;
@ApiModelProperty("该活动开始时间")
private long startTime;
}

@ -0,0 +1,18 @@
package cn.teammodel.model.dto.admin.exam;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class FindByStudentDto {
@ApiModelProperty("该活动唯一ID")
private String id;
@ApiModelProperty("学校编码")
private String code;
@ApiModelProperty("学生ID")
private String studentId;
@ApiModelProperty("原本活动的完成code,在返回的列表数据中应该有类似Exam-hbcn的字段")
private String scode;
@ApiModelProperty("科目ID")
private String subjectId;
}

@ -0,0 +1,12 @@
package cn.teammodel.model.dto.admin.exam;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class FindExamDto {
@ApiModelProperty("该活动唯一ID")
private String id;
@ApiModelProperty("学校编码")
private String code;
}

@ -0,0 +1,19 @@
package cn.teammodel.model.dto.admin.exam;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@Data
public class OverViewDto {
@ApiModelProperty("指定学年")
private int studyYear;
private String semesterId;
private String school;
private String studentId;
private String periodId;
@ApiModelProperty("学生入学年")
private int studentYear;
private List<String> classIds;
}

@ -0,0 +1,12 @@
package cn.teammodel.model.dto.admin.teacher;
import lombok.Data;
import java.util.List;
@Data
public class GpTeacherDto {
private String grant_type = "mobiles_infos";
private String client = "7D340153-3B66-4BAF-8F1E-2EE02F7E1828";
private List<String> mobiles;
}

@ -0,0 +1,24 @@
package cn.teammodel.model.dto.admin.teacher;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class TeacherDto {
@ApiModelProperty("学校编码")
public String code;
@ApiModelProperty("学校编码")
public String school_code;
@ApiModelProperty("TmdId")
public String tmdId;
public Long startTime;
public Long endTime;
@ApiModelProperty("学段Id")
public String periodId;
public Integer year;
@ApiModelProperty("年级")
public String grade;
@ApiModelProperty("科目信息")
public String subjectId;
public String semesterId;
}

@ -0,0 +1,27 @@
package cn.teammodel.model.dto.admin.weekduty;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* @author winter
* @create 2024-01-15 10:30
*/
@Data
public class AdminFindDutyRecordDto {
@ApiModelProperty("老师 id")
private String teacherId;
@ApiModelProperty(value = "班级 id", notes = "若不携带默认不指定某个班级")
private String classId;
@ApiModelProperty(required = true)
@NotNull(message = "academicYearid 不能为空")
private String academicYearId;
@ApiModelProperty(value = "是否加分", notes = "若不携带默认为全部")
private Boolean positive;
@ApiModelProperty(value = "起始时间", notes = "若不携带默认为当前周")
private Long startTime;
@ApiModelProperty(value = "结束时间", notes = "若不携带默认为当前周")
private Long endTime;
}

@ -0,0 +1,16 @@
package cn.teammodel.model.dto.ai;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
public class ChatCompletionReqDto {
private String sessionId;
/**
* id
*/
private String appId;
@NotBlank(message = "请输入消息内容")
private String text;
}

@ -0,0 +1,21 @@
package cn.teammodel.model.dto.ai;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
*
*/
@Data
public class ChatModelDto {
public String type;
public String name;
public ArrayList<String> role;
public ArrayList<String> chat;
public ArrayList<String> cycleChats;
public ArrayList<String> end;
}

@ -0,0 +1,14 @@
package cn.teammodel.model.dto.ai;
import lombok.Data;
import java.util.List;
/**
* json
*/
@Data
public class ChatModelReqDto {
public List<ChatModelDto> chatModel;
}

@ -0,0 +1,30 @@
package cn.teammodel.model.dto.ai;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
public class CreateChatAppDto {
@ApiModelProperty("应用图标")
private String icon;
@ApiModelProperty("应用名称")
@NotBlank(message = "请输入应用名称")
private String name;
private String lang;
private String bizType;
@ApiModelProperty("应用域")
@NotBlank(message = "请输入应用域")
private String scope;
private String itemType;;
private String period;
private String subject;
@ApiModelProperty("应用描述")
private String description;
@NotBlank(message = "请输入应用提示词")
@ApiModelProperty("应用提示词")
private String prompt;
}

@ -0,0 +1,20 @@
package cn.teammodel.model.dto.ai;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
* @author winter
* @create 2024-02-01 15:40
*/
@Data
public class SearchAppDto {
@NotBlank(message = "scope不能为空")
private String scope;
private String bizType;
private String lang;
private String itemType;;
private String period;
private String subject;
}

@ -0,0 +1,34 @@
package cn.teammodel.model.dto.ai;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
public class UpdateChatAppDto {
@ApiModelProperty("应用 id")
@NotBlank(message = "请输入应用 id")
private String id;
@ApiModelProperty("应用图标")
private String icon;
@ApiModelProperty("应用名称")
@NotBlank(message = "请输入应用名称")
private String name;
private String lang;
private String bizType;
@ApiModelProperty("应用域")
@NotBlank(message = "请输入应用域")
private String scope;
private String itemType;;
private String period;
private String subject;
@ApiModelProperty("应用描述")
private String description;
@NotBlank(message = "请输入应用提示词")
@ApiModelProperty("应用提示词")
private String prompt;
}

@ -0,0 +1,18 @@
package cn.teammodel.model.dto.ai;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
* @author winter
* @create 2023-12-19 15:42
*/
@Data
public class UpdateSessionDto {
@ApiModelProperty(value = "session id", required = true)
@NotBlank
private String id;
private String title;
}

@ -0,0 +1,19 @@
package cn.teammodel.model.dto.ai.comment;
import lombok.Data;
/**
*
*/
@Data
public class ArtLatitudeDto {
public String quotaN1;
public String quotaN2;
public String quotaN3;
public int quotaP1;
public int quotaP2;
public int quotaP3;
public String percent;
public String level;
}

@ -0,0 +1,16 @@
package cn.teammodel.model.dto.ai.comment;
import lombok.Data;
/**
*
*/
@Data
public class ArtSubjectDto {
public String dimension;
public String block;
public String point;
public int score;
public int percent;
public int totalScore;
}

@ -0,0 +1,69 @@
package cn.teammodel.model.dto.ai.comment;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
*
*/
@Data
public class ChatCommentsDto {
/**
* id
*/
private String sessionId;
/**
* id
*/
private String appId;
/**
*
*/
@NotNull
@ApiModelProperty(value = "评语类型不能为空")
private String type;
@ApiModelProperty(value = "教师学段")
private String period;
@ApiModelProperty(value = "教师学科")
private String subject;
/**
*
*/
private int repeat;
/**
*
*/
private String name;
/*
*
*/
private int phase;
/**
*
*/
private int size;
/**
*
*/
private String text;
/**
*
*/
private List<String> limitTexts;
/**
*
*/
private Object data;
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save