Compare commits
249 Commits
Author | SHA1 | Date |
---|---|---|
hhb@hotmail.com | 02fa60e427 | 3 days ago |
hhb@hotmail.com | d0379cd7b8 | 3 days ago |
hhb@hotmail.com | 74148a068a | 4 days ago |
hhb@hotmail.com | af6536c0fe | 2 weeks ago |
PL | a04ba227ec | 3 weeks ago |
PL | e57affb790 | 3 weeks ago |
hhb@hotmail.com | 128a05e90a | 3 weeks ago |
hhb@hotmail.com | 13d095d02b | 3 weeks ago |
hhb@hotmail.com | cd421db42b | 3 weeks ago |
hhb@hotmail.com | 18b0acd648 | 3 weeks ago |
hhb@hotmail.com | e447351729 | 3 weeks ago |
hhb@hotmail.com | 49cfb37404 | 4 weeks ago |
hhb@hotmail.com | c1bbd8a7ac | 4 weeks ago |
hhb@hotmail.com | e746605ee0 | 4 weeks ago |
hhb@hotmail.com | ab78ec557f | 4 weeks ago |
hhb@hotmail.com | de621c8541 | 1 month ago |
hhb@hotmail.com | 4153162ff1 | 1 month ago |
hhb@hotmail.com | a9c6c6a499 | 1 month ago |
hhb@hotmail.com | be289caf37 | 1 month ago |
hhb@hotmail.com | 1dd21b136e | 1 month ago |
hhb@hotmail.com | 6e1bfdc6c9 | 1 month ago |
hhb@hotmail.com | 5933e2daee | 1 month ago |
hhb@hotmail.com | 1dcd782331 | 1 month ago |
hhb@hotmail.com | 3449d2bcbd | 1 month ago |
hhb@hotmail.com | 7ec8d20ae8 | 1 month ago |
hhb@hotmail.com | 12ad733286 | 1 month ago |
PL | f07b7e9257 | 2 months ago |
PL | d038fd631e | 2 months ago |
CrazyIter_Bin | e64b8d8e8c | 2 months ago |
CrazyIter_Bin | 99337c5835 | 2 months ago |
CrazyIter_Bin | 7358250cd3 | 2 months ago |
PL | 8057c0f18f | 2 months ago |
PL | bb417b8613 | 2 months ago |
hhb@hotmail.com | 20a0bbfe8e | 2 months ago |
hhb@hotmail.com | 9e76f8ca43 | 2 months ago |
CrazyIter_Bin | ab67d282f1 | 2 months ago |
CrazyIter_Bin | 0d4864f7f7 | 2 months ago |
hhb@hotmail.com | 692015b0c7 | 2 months ago |
hhb@hotmail.com | a5d404a025 | 2 months ago |
PL | 8100e15948 | 2 months ago |
PL | 65d4740084 | 2 months ago |
PL | 146adb9ae6 | 2 months ago |
PL | baea216357 | 2 months ago |
PL | ffb8af9546 | 2 months ago |
PL | 817fe06787 | 2 months ago |
PL | dda1342731 | 2 months ago |
PL | d1018c375c | 2 months ago |
PL | 469f19384b | 2 months ago |
PL | 50f94cb38a | 2 months ago |
PL | 8c2a543bbb | 2 months ago |
hhb@hotmail.com | b68b576b8c | 3 months ago |
hhb@hotmail.com | 5eb9dcaadc | 3 months ago |
hhb@hotmail.com | 82f67e1afe | 3 months ago |
CrazyIter_Bin | 3fcc218292 | 3 months ago |
CrazyIter_Bin | 6b07db26bd | 3 months ago |
PL | fcfda1760a | 3 months ago |
hhb@hotmail.com | 2f8bb75d6f | 3 months ago |
hhb@hotmail.com | 87f75f34e5 | 3 months ago |
hhb@hotmail.com | e7607e4b52 | 3 months ago |
hhb@hotmail.com | 8b3ec87fb4 | 3 months ago |
zhouj1203@hotmail.com | 63de395694 | 3 months ago |
zhouj1203@hotmail.com | 0e5267f2ca | 3 months ago |
PL | 47bd34e760 | 3 months ago |
PL | bdd19d81b7 | 4 months ago |
PL | bde76c5140 | 4 months ago |
zhouj1203@hotmail.com | 26e7574eec | 4 months ago |
zhouj1203@hotmail.com | 7ddcf2aed5 | 4 months ago |
zhouj1203@hotmail.com | 8879b87bd2 | 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 | 4 months ago |
zhouj1203@hotmail.com | 4f2ea3d672 | 4 months ago |
PL | 5c47b00105 | 4 months ago |
PL | 267facc601 | 4 months ago |
PL | 436e4d807a | 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 | 4 months ago |
CrazyIter_Bin | f8b29d0b2f | 4 months ago |
zhouj1203@hotmail.com | 9b99c7db28 | 4 months ago |
zhouj1203@hotmail.com | 5efd36bce8 | 4 months ago |
zhouj1203@hotmail.com | ab5ad3088b | 4 months ago |
zhouj1203@hotmail.com | 741330e678 | 4 months ago |
PL | 8eba7eb8dc | 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 | 4 months ago |
zhouj1203@hotmail.com | 70c3aaefbe | 4 months ago |
PL | dc2a311ead | 4 months ago |
zhouj1203@hotmail.com | 5658dabd32 | 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 | 4 months ago |
CrazyIter_Bin | bfb5eb7beb | 4 months ago |
CrazyIter_Bin | a1da5adc6f | 4 months ago |
PL | d173babbd7 | 4 months ago |
CrazyIter_Bin | fa2bad9f86 | 4 months ago |
CrazyIter_Bin | a70efb3c7b | 4 months ago |
PL | e5196290b2 | 4 months ago |
zhouj1203@hotmail.com | 39f6e1eb8f | 4 months ago |
zhouj1203@hotmail.com | 33aaf13e9d | 4 months ago |
PL | 0fc74a1819 | 4 months ago |
CrazyIter_Bin | 37abc6a90c | 4 months ago |
zhouj1203@hotmail.com | 35a3d285c1 | 4 months ago |
CrazyIter_Bin | 72380dc68a | 4 months ago |
PL | e8dfcf7f9f | 4 months ago |
zhouj1203@hotmail.com | 523dfa47b6 | 4 months ago |
zhouj1203@hotmail.com | 5200ec6f8c | 4 months ago |
PL | 678e7d302b | 4 months ago |
PL | d333e6809f | 4 months ago |
PL | 812456a8e1 | 4 months ago |
PL | 81a83a7566 | 4 months ago |
zhouj1203@hotmail.com | 6587bcca67 | 4 months ago |
PL | d880be517b | 4 months ago |
zhouj1203@hotmail.com | f46d24223f | 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 | 5 months ago |
zhouj1203@hotmail.com | a801724b75 | 5 months ago |
winter | c9e7268d87 | 8 months ago |
winter | b7126f7bd8 | 8 months ago |
winter | 5d33226f94 | 8 months ago |
winter | 5caf6de0ec | 8 months ago |
winter | 2698f759a4 | 8 months ago |
winter | f966dacb9c | 8 months ago |
winter | a53efd1f7a | 9 months ago |
winter | acf448e980 | 9 months ago |
winter | 9aec66d1a7 | 9 months ago |
winter | b53fe0f7d6 | 9 months ago |
winter | ea5c6fcb81 | 10 months ago |
winter | 52773b45ff | 10 months ago |
winter | bbef6070fd | 10 months ago |
winter | a00e0eaf2e | 10 months ago |
winter | 1a006ee304 | 10 months ago |
winter | 7aa14b1b82 | 10 months ago |
winter | c2c1f9cd0b | 10 months ago |
winter | 32f2414cd8 | 10 months ago |
winter | fa1c6a9b20 | 10 months ago |
winter | b9950c6022 | 10 months ago |
winter | da1bb7fc87 | 10 months ago |
winter | 09140678bc | 10 months ago |
winter | 9ff280a94e | 10 months ago |
winter | 29f1fed4f1 | 10 months ago |
winter | 94ac4286c3 | 10 months ago |
winter | 9f0cd7d01a | 10 months ago |
winter | a539afb9e8 | 10 months ago |
winter | 21790d5666 | 10 months ago |
winter | 53f9492eb0 | 10 months ago |
winter | 079f2fbf6f | 10 months ago |
winter | bc13f67a29 | 10 months ago |
winter | d5ad605b35 | 11 months ago |
winter | 118fc413d3 | 11 months ago |
winter | 0ac22b5353 | 11 months ago |
winter | 8b25e112e8 | 11 months ago |
winter | f3e3f48422 | 11 months ago |
winter | e74fee8812 | 12 months ago |
winter | 8bc0da460b | 12 months ago |
winter | 70ffad27a3 | 12 months ago |
winter | 2fb38aa62c | 12 months ago |
winter | 48588b12fc | 12 months ago |
winter | 256b233b4c | 12 months ago |
winter | 8c15427ff7 | 12 months ago |
winter | d155efe947 | 12 months ago |
winter | 1a18105096 | 12 months ago |
winter | 327e399d5a | 12 months ago |
winter | 9f77aa9ede | 12 months ago |
winter | 38699011e6 | 12 months ago |
winter | eec45f6921 | 12 months ago |
winter | 65c8fd598f | 12 months ago |
winter | 5c01fca6c1 | 1 year ago |
winter | 0ded5af82d | 1 year ago |
winter | ab2aaa1757 | 1 year ago |
winter | f2e0c0b19e | 1 year ago |
winter | fb49fea68e | 1 year ago |
winter | d1bb7d56a9 | 1 year ago |
winter | 56700192d9 | 1 year ago |
winter | c9309087c3 | 1 year ago |
winter | 8301c973c0 | 1 year ago |
winter | 178e3cfc03 | 1 year ago |
winter | 83bdf4d6c1 | 1 year ago |
winter | 2f972c65e3 | 1 year ago |
winter | ae729c05e8 | 1 year ago |
winter | 40d4826695 | 1 year ago |
winter | ef1979cbd7 | 1 year ago |
winter | cec0a7e58d | 1 year ago |
winter | 6cf0ebaef3 | 1 year ago |
winter | 316f9daa4a | 1 year ago |
winter | d185a3ffe7 | 1 year ago |
winter | 646caaa926 | 1 year ago |
winter | 76499c3904 | 1 year ago |
winter | fede04c70d | 1 year ago |
winter | fa03927579 | 1 year ago |
winter | 6ea7454973 | 1 year ago |
winter | ccbd59f18f | 1 year ago |
winter | fee64cb1ac | 1 year ago |
winter | 0bae71207b | 1 year ago |
winter | aa35b01844 | 1 year ago |
winter | 8ddf66c97d | 1 year ago |
CrazyIter_Bin | 890d23ae6a | 1 year ago |
winter | b610194f30 | 1 year ago |
winter | 7918786641 | 1 year ago |
winter | 79db32c215 | 1 year ago |
winter | 3477592027 | 1 year ago |
winter | 83c980dcae | 1 year ago |
winter | a138e16b40 | 1 year ago |
winter | 6d631563c6 | 1 year ago |
winter | 8f7b1f9cc1 | 1 year ago |
winter | c54edf3cfe | 1 year ago |
winter | a3922d8c2d | 1 year ago |
winter | 6c47e0c59e | 1 year ago |
winter | 18d42a36e6 | 1 year ago |
winter | a09d61b020 | 1 year ago |
winter | c34e87ca0d | 1 year ago |
winter | 18cfb50a46 | 1 year ago |
winter | a2d75a1c3d | 1 year ago |
winter | 29d21f0233 | 1 year ago |
winter | 6dffd636ec | 1 year ago |
winter | 8301cfd96d | 1 year ago |
winter | aa582361f8 | 1 year ago |
winter | 38f5bf39ef | 1 year ago |
winter | edc79455cc | 1 year ago |
winter | 610c6d4e81 | 1 year ago |
winter | 5e06e8ed1e | 1 year ago |
winter | d9a19736f2 | 1 year ago |
winter | 2b271547e7 | 1 year ago |
winter | 148c31b323 | 1 year ago |
winter | 68f5303a4c | 1 year ago |
winter | 1be6ca7e02 | 1 year ago |
winter | 46b88742d7 | 1 year ago |
winter | 676f6fc46b | 1 year ago |
winter | a16e8f8de8 | 1 year ago |
winter | f0a9ba9243 | 1 year ago |
winter | 46fa7bf45e | 1 year ago |
winter | c1e2a62527 | 1 year ago |
winter | 38bb428c59 | 1 year ago |
@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType">
|
||||
<booleanAttribute key="editedByExternalToolsMainTab" value="true"/>
|
||||
<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="full,incremental,"/>
|
||||
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
|
||||
</launchConfiguration>
|
@ -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
|
@ -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,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, " ", " ").replaceAll("\n", "\n");
|
||||
msgSegment = StrUtil.replace(msgSegment, " ", " ").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,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;
|
||||
|
||||
public class R {
|
||||
private Integer code;
|
||||
private String message;
|
||||
private String data;
|
||||
|
||||
public R(Integer code, String message, String data) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public Integer getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(Integer code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(String data) {
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
package cn.teammodel.common;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class R<T> implements Serializable {
|
||||
|
||||
private int code;
|
||||
|
||||
private T data;
|
||||
|
||||
private String message;
|
||||
|
||||
public R(int code, T data, String message) {
|
||||
this.code = code;
|
||||
this.data = data;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public R(int code, T data) {
|
||||
this(code, data, "");
|
||||
}
|
||||
|
||||
public R(ErrorCode errorCode) {
|
||||
this(errorCode.getCode(), null, errorCode.getMessage());
|
||||
}
|
||||
public R(ErrorCode errorCode, T data) {
|
||||
this(errorCode.getCode(), data, errorCode.getMessage());
|
||||
}
|
||||
|
||||
public static <T> R<T> success(T data) {
|
||||
return new R<>(ErrorCode.SUCCESS, data);
|
||||
}
|
||||
|
||||
public static <T> R<T> error(String msg) {
|
||||
return new R<>(ErrorCode.SYSTEM_ERROR.getCode(), null, msg);
|
||||
}
|
||||
|
||||
public static <T> R<T> error(Integer code, String msg) {
|
||||
return new R<>(code, null, msg);
|
||||
}
|
||||
|
||||
public static <T> R<T> error(ErrorCode errorCode) {
|
||||
return new R<>(errorCode);
|
||||
}
|
||||
}
|
@ -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,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,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
|
||||
* @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
|
||||
* @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
|
||||
* @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,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,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,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,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;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue