diff --git a/common/src/main/java/com/groupshell/constant/ChatGPTConstants.java b/common/src/main/java/com/groupshell/constant/ChatGPTConstants.java new file mode 100644 index 0000000000000000000000000000000000000000..31013fba02c8062916e668e1461a5b20faa23bb7 --- /dev/null +++ b/common/src/main/java/com/groupshell/constant/ChatGPTConstants.java @@ -0,0 +1,11 @@ +package com.groupshell.constant; + +public interface ChatGPTConstants { + String DEFAULT_OPENAI_KEY = "sk-OA8YqWsVOIIPeGWlD86eB41a9284495085Ab17A08c514b1e"; + String DEFAULT_CHAT_MESSAGE = "你好!请问你是chatGPT吗?"; + String GPT3_OPENAI_API_URL = "https://one.aiskt.com/"; + String GPT4_OPENAI_API_URL = "https://pro.aiskt.com/"; + String OPENAI_CLIENT = "OpenAiClient"; + String OPENAI_STREAM_CLIENT = "OpenAiStreamClient"; + String CHATGPT_DONE = "[DONE]"; +} diff --git a/pojo/pom.xml b/pojo/pom.xml index ee66ef91d9d4ea0cf330b67f86715c1cc098e18c..49e2a84b01b9d6875a28953efde667f012efa888 100644 --- a/pojo/pom.xml +++ b/pojo/pom.xml @@ -32,6 +32,11 @@ chatgpt-java 1.0.14-beta1 + + com.alibaba + fastjson + 2.0.27 + com.groupshell common diff --git a/pojo/src/main/java/com/groupshell/entity/Invoice.java b/pojo/src/main/java/com/groupshell/entity/Invoice.java index 26b166b2b59080b7b9e90edeeff0ebf8ed39f832..107eee1fd84f6022bfddf8e30430a2c070840009 100644 --- a/pojo/src/main/java/com/groupshell/entity/Invoice.java +++ b/pojo/src/main/java/com/groupshell/entity/Invoice.java @@ -1,9 +1,14 @@ package com.groupshell.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; import com.groupshell.enumeration.InvoiceTypeEnum; import com.groupshell.enumeration.ReimburseStatusEnum; import lombok.*; +import java.io.Serializable; import java.math.BigDecimal; import java.time.LocalDateTime; @@ -18,20 +23,60 @@ import java.time.LocalDateTime; @NoArgsConstructor @AllArgsConstructor @Builder -public class Invoice -{ +@TableName("invoice") +public class Invoice implements Serializable { + /** + * The unique identifier for the invoice. + * 主键,自增 + */ + @TableId(value="id", type= IdType.AUTO) private Integer id; + + /** + * The amount of the invoice. + * 使用BigDecimal进行与财务相关的计算,避免出现浮点数运算误差 + */ private BigDecimal amount; - private InvoiceTypeEnum type;//EXPENSE,INCOME + + + private InvoiceTypeEnum type; + /** + * 非空 + */ + + /** + * The description of the invoice. + */ private String description; + + /** + * The category of the invoice. + */ private String category; + + /** + * The date and time when the invoice was created. + */ private LocalDateTime createdTime; + + //TODO:更新时间,更新人 + /** + * The user ID associated with the invoice. + * 外键引用user表的id + */ private Integer userId; //账单创建人 + private String payMethod; //支付方式 + private ReimburseStatusEnum reimburseStatus; + private LocalDateTime reimburseRequestTime; // 报销申请时间 + private LocalDateTime reimburseCompleteTime; // 报销完成时间 + private Integer approverId; // 审批者ID + private String reimburseNotes; // 报销备注 - private Integer groupId; + + private Integer groupId; } \ No newline at end of file diff --git a/pojo/src/main/java/com/groupshell/entity/Task.java b/pojo/src/main/java/com/groupshell/entity/Task.java index 68515dc5136fd3ddbe49a852de5155d0625df32b..e3745b3b893e909f5e4ad61654844f2e662d2c52 100644 --- a/pojo/src/main/java/com/groupshell/entity/Task.java +++ b/pojo/src/main/java/com/groupshell/entity/Task.java @@ -68,4 +68,6 @@ public class Task implements Serializable * The status of the task. */ private TaskStatusEnum status; + + private Integer groupId; } \ No newline at end of file diff --git a/pojo/src/main/java/com/groupshell/entity/chatgpt/ChatGPTConfig.java b/pojo/src/main/java/com/groupshell/entity/chatgpt/ChatGPTConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..9c5aea93ea722e324168b96d22889f08eda17228 --- /dev/null +++ b/pojo/src/main/java/com/groupshell/entity/chatgpt/ChatGPTConfig.java @@ -0,0 +1,172 @@ +package com.groupshell.entity.chatgpt; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.unfbx.chatgpt.OpenAiClient; +import com.unfbx.chatgpt.OpenAiStreamClient; +import com.unfbx.chatgpt.entity.chat.ChatCompletion; +import com.unfbx.chatgpt.entity.chat.ChatCompletionResponse; +import com.unfbx.chatgpt.entity.chat.Message; +import com.unfbx.chatgpt.interceptor.OpenAILogger; +import com.unfbx.chatgpt.sse.ConsoleEventSourceListener; +import lombok.*; +import okhttp3.OkHttpClient; +import okhttp3.logging.HttpLoggingInterceptor; + +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import static com.groupshell.constant.ChatGPTConstants.*; + +@Data +@ToString +@AllArgsConstructor +@Builder +public class ChatGPTConfig { + + private OkHttpClient okHttpClient; + private OpenAiClient openAiClient; //阻塞 + private OpenAiStreamClient openAiStreamClient; //非阻塞 + private CustomEventSourceListener eventSourceListener; + private ChatCompletion chatCompletion; + private ChatCompletion.Model model; + private List messages; + private ChatCompletionResponse chatCompletionResponse; //暂时没用 + private HttpLoggingInterceptor httpLoggingInterceptor; + + public ChatGPTConfig(String customization) throws InterruptedException { + if (customization == OPENAI_CLIENT) { + initHttpLoggingInterceptor(); + initOkHttpClient(); + initOpenAiClient(); //初始化阻塞式客户端 + initCustomEventSourceListener(new CustomEventSourceListener()); //初始化事件侦听器 + initChatCompletion(customization); + + //initChatCompletionResponse(); + } + else if (customization == OPENAI_STREAM_CLIENT) { + initHttpLoggingInterceptor(); + initOkHttpClient(); + initOpenAiStreamClient(); //初始化流式客户端 + initCustomEventSourceListener(new CustomEventSourceListener()); //初始化事件侦听器 + initChatCompletion(customization); + } + else { + initHttpLoggingInterceptor(); + initOkHttpClient(); + initOpenAiClient(); //初始化阻塞式客户端 + initCustomEventSourceListener(new CustomEventSourceListener()); //初始化事件侦听器 + initChatCompletion(customization); + //initChatCompletionResponse(); + } + } + + + public void initHttpLoggingInterceptor() { + //日志拦截器 + this.httpLoggingInterceptor = new HttpLoggingInterceptor(new OpenAILogger()); + //!!!!千万别再生产或者测试环境打开BODY级别日志!!!! + //!!!生产或者测试环境建议设置为这三种级别:NONE,BASIC,HEADERS,!!! + this.httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS); //除了BODY,只有HEADERS才会返回带有会话信息的内容 + } + + public void initOkHttpClient() { + this.okHttpClient = new OkHttpClient.Builder() + .proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 7890))) // 设置代理 + .addInterceptor(httpLoggingInterceptor) + .connectTimeout(15, TimeUnit.SECONDS) + .writeTimeout(15, TimeUnit.SECONDS) + .readTimeout(15, TimeUnit.SECONDS) + .build(); + } + + public void initOpenAiClient() { + this.openAiClient = OpenAiClient.builder() + .apiKey(Arrays.asList(DEFAULT_OPENAI_KEY)) + .apiHost(GPT4_OPENAI_API_URL) //支持GPT4 + .keyStrategy(new KeyRandomStrategy()) + .okHttpClient(okHttpClient) + .build(); + } + + public void initOpenAiStreamClient() { + this.openAiStreamClient = OpenAiStreamClient.builder() + .apiKey(Arrays.asList(DEFAULT_OPENAI_KEY)) + .apiHost(GPT4_OPENAI_API_URL) //支持GPT4 + .keyStrategy(new KeyRandomStrategy()) + .okHttpClient(okHttpClient) + .build(); + } + + + public void initCustomEventSourceListener(CustomEventSourceListener eventSourceListener) { + this.eventSourceListener = eventSourceListener; + } + + public void initChatCompletion(String customization) { + if (customization == OPENAI_CLIENT) { + this.messages = new ArrayList(); + this.chatCompletion = ChatCompletion.builder() + .messages(this.messages) + .build(); //这里必须设置发送给gpt的初始信息(提问) + chatCompletion.setModel(ChatCompletion.Model.GPT_4.getName()); //实际使用的是gpt-35-turbo + } + else if (customization == OPENAI_STREAM_CLIENT) { + this.messages = new ArrayList(); + this.chatCompletion = ChatCompletion.builder() + .messages(this.messages) + .stream(true) //流式输出 + .build(); //这里必须设置发送给gpt的初始信息(提问) + chatCompletion.setModel(ChatCompletion.Model.GPT_4.getName()); //实际使用的是gpt-35-turbo + } + else { + this.messages = new ArrayList(); + this.chatCompletion = ChatCompletion.builder() + .messages(this.messages) + .build(); //这里必须设置发送给gpt的初始信息(提问) + chatCompletion.setModel(ChatCompletion.Model.GPT_4.getName()); //实际使用的是gpt-35-turbo + } + } + + public void setChatCompletionResponse() { + this.chatCompletionResponse = openAiClient.chatCompletion(chatCompletion); + } + + + /** + * 设置聊天完成的配置,根据不同参数类型执行不同逻辑。 + * + * @param parameter 可以是 String, ChatCompletion 或 ChatCompletion.Model 类型的对象 + */ + public void setChatCompletion(Object parameter) { + if (parameter instanceof String) { //传入用户的对话信息 + String chatMessage = (String) parameter; + addMessage(chatMessage); + this.chatCompletion = ChatCompletion.builder().messages(messages).build(); + + } else if (parameter instanceof ChatCompletion) { + this.chatCompletion = (ChatCompletion) parameter; + + } else if (parameter instanceof ChatCompletion.Model) { //更换模型 + ChatCompletion.Model model = (ChatCompletion.Model) parameter; + if (this.chatCompletion == null) { + this.chatCompletion = new ChatCompletion(); + } + this.chatCompletion.setModel(model.getName()); + + } else { + throw new IllegalArgumentException("不支持的参数类型: " + parameter.getClass().getSimpleName()); + } + } + + public void addMessage(String chatMessage) { + this.messages.add(Message.builder().role(Message.Role.USER).content(chatMessage).build()); + System.out.println("调用addMessage"); + System.out.println(messages); + } + +} diff --git a/pojo/src/main/java/com/groupshell/entity/chatgpt/ChatGPTHistory.java b/pojo/src/main/java/com/groupshell/entity/chatgpt/ChatGPTHistory.java new file mode 100644 index 0000000000000000000000000000000000000000..1e9a65f38941124a12ccba6ffe072affc9a7cf78 --- /dev/null +++ b/pojo/src/main/java/com/groupshell/entity/chatgpt/ChatGPTHistory.java @@ -0,0 +1,38 @@ +package com.groupshell.entity.chatgpt; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.models.security.SecurityScheme; +import lombok.*; + +import java.time.LocalDateTime; +import java.util.Map; + +@Data +@ToString +//@NoArgsConstructor +@AllArgsConstructor +@Builder +@TableName("chatgpt_history") +public class ChatGPTHistory { + @TableId(type = IdType.AUTO) + private Integer id; + private Integer userId; + private String title; //对话的标题 + private Map userAsk; //用户询问语句:对话id与对话内容 + private Map chatgptAnswer; //chatgpt回答 + private LocalDateTime createdTime; + private LocalDateTime updatedTime; + + // 构造器中自动设置时间 + public ChatGPTHistory() { + this.createdTime = LocalDateTime.now(); + this.updatedTime = LocalDateTime.now(); + } + + // 更新时刷新时间戳 + public void refreshUpdatedTime() { + this.updatedTime = LocalDateTime.now(); + } +} diff --git a/pojo/src/main/java/com/groupshell/entity/chatgpt/ChatGPTMessageHandler.java b/pojo/src/main/java/com/groupshell/entity/chatgpt/ChatGPTMessageHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..05f473aeb5d45372522a468cb5bf921cb663b268 --- /dev/null +++ b/pojo/src/main/java/com/groupshell/entity/chatgpt/ChatGPTMessageHandler.java @@ -0,0 +1,81 @@ +package com.groupshell.entity.chatgpt; + +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONArray; +import com.alibaba.fastjson2.JSONObject; + + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import static com.groupshell.constant.ChatGPTConstants.CHATGPT_DONE; + +public class ChatGPTMessageHandler { + +// public String singleResponse; + public List responses = new ArrayList(); + public String responsesFomatted; + + + + + public String responseHandler(String jsonResponse) { +// // 使用 Fastjson 解析 JSON 数据 +// JSONObject jsonObject = JSON.parseObject(jsonResponse); +// +// // 提取 choices 数组中第一个元素的 delta 对象下的 content 字段 +// String content = jsonObject.getJSONArray("choices").getJSONObject(1) +// .getJSONObject("delta").getString("content"); +// //System.out.println(fullSentence.toString()); // 输出完整句子到控制台 +// return content; + if (Objects.equals(jsonResponse, CHATGPT_DONE)) { + return null; + } + JSONObject jsonObject = JSON.parseObject(jsonResponse); + JSONArray choices = jsonObject.getJSONArray("choices"); + + if (choices != null && !choices.isEmpty()) { + for (int i = 0; i < choices.size(); i++) { + JSONObject choice = choices.getJSONObject(i); + JSONObject delta = choice.getJSONObject("delta"); + if (delta != null && delta.containsKey("content")) { + String content = delta.getString("content"); + if (content != null && !content.isEmpty()) { + System.out.println(content); + return content; + //responses.add(content); + } else { + //System.out.println("Content is empty or not available."); + } + } else { + //System.out.println("Delta is null or does not contain 'content'."); + } + } + } else { + //System.out.println("Choices array is empty."); + } + return null; + } + + public String responseFormat(List responses) { + StringBuilder fullSentence = new StringBuilder(); + for (String word : responses) { + fullSentence = fullSentence.append(word); + } + this.responsesFomatted = fullSentence.toString(); + return fullSentence.toString(); + } + + public void printResponses() { + // 遍历responses数组并打印每个元素 + for (String response : responses) { + if (response != null) { + System.out.print(response); + } + } + System.out.println(); + responses.clear(); + } + +} diff --git a/pojo/src/main/java/com/groupshell/entity/chatgpt/CustomChatGPT.java b/pojo/src/main/java/com/groupshell/entity/chatgpt/CustomChatGPT.java new file mode 100644 index 0000000000000000000000000000000000000000..03b18880a7ffac531429f45a0820ae92fdc478d3 --- /dev/null +++ b/pojo/src/main/java/com/groupshell/entity/chatgpt/CustomChatGPT.java @@ -0,0 +1,133 @@ +package com.groupshell.entity.chatgpt; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.unfbx.chatgpt.OpenAiClient; +import com.unfbx.chatgpt.OpenAiStreamClient; +import com.unfbx.chatgpt.entity.chat.ChatCompletion; +import com.unfbx.chatgpt.entity.chat.ChatCompletionResponse; +import com.unfbx.chatgpt.entity.chat.Message; +import com.unfbx.chatgpt.sse.ConsoleEventSourceListener; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.ToString; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Scanner; +import java.util.concurrent.CountDownLatch; + +import static com.groupshell.constant.ChatGPTConstants.OPENAI_CLIENT; +import static com.groupshell.constant.ChatGPTConstants.OPENAI_STREAM_CLIENT; + +@Data +@ToString +@AllArgsConstructor +@Builder +public class CustomChatGPT { + + private List messages; //TODO:保存临时会话信息?? + private ChatGPTConfig chatGPTConfig; + private String openAiClientType; //OpenAiClient或OpenAiStreamClient + + //阻塞 + public CustomChatGPT(String customization) throws InterruptedException { + chatGPTConfig = new ChatGPTConfig(customization); + openAiClientType = customization; + } + + + //把对话信息发送给GPT并让它回复 + public void callCustomChatGPT() throws InterruptedException { + if (openAiClientType == OPENAI_CLIENT) { + return; + } + else if (openAiClientType == OPENAI_STREAM_CLIENT){ + chatGPTConfig.getOpenAiStreamClient().streamChatCompletion( + chatGPTConfig.getChatCompletion(), + chatGPTConfig.getEventSourceListener()); //new一个ConsoleEventSourceListener? + } + else { + return; + } +// CountDownLatch countDownLatch = new CountDownLatch(1); +// try { +// countDownLatch.await(); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// } + } + + private void sendMessageToChatGPT(String message) throws InterruptedException { + /* + //这里直接新建了一个ChatCompletion,看看能不能持续对话 + chatGPTConfig.addMessage(message); + ChatCompletion chatCompletion = ChatCompletion.builder() + .messages(chatGPTConfig.getMessages()) + .stream(true) + .build(); + chatGPTConfig.setChatCompletion(chatCompletion); + */ + //chatGPTConfig.initOkHttpClient(); + chatGPTConfig.setChatCompletion(message); + callCustomChatGPT(); + +// CountDownLatch countDownLatch = new CountDownLatch(1); +// try { +// countDownLatch.await(); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// //Thread.currentThread().interrupt(); // 保留中断状态 +// } + } + + public void startChattingWithConsole() throws InterruptedException { + Scanner scanner = new Scanner(System.in); + System.out.println("你好,开始与 ChatGPT 聊天吧!(输入 'exit' 退出)"); + + while (true) { + System.out.print("我: "); //非阻塞会把这句话打印在前面 + String input = scanner.nextLine(); + if ("exit".equalsIgnoreCase(input)) { + System.out.println("聊天结束。"); + break; + } + sendMessageToChatGPT(input); + System.out.println("打印ChatCompletion的Messages"); + System.out.println(chatGPTConfig.getChatCompletion().getMessages()); + + +// chatGPTConfig.getOpenAiStreamClient(); +// chatGPTConfig.getChatCompletion() +// chatGPTConfig.setChatCompletionResponse(); //TODO:ChatCompletionResponse会有Unrecognized field的问题 +// chatGPTConfig.getChatCompletionResponse().getChoices().forEach(e -> { +// System.out.println(e.getMessage()); +// }); + } + scanner.close(); + } + + + public String chatGPTResponseHandler(List jsonResponses) { + StringBuilder fullSentence = new StringBuilder(); + for (String jsonResponse : jsonResponses) { + JSONObject jsonObject = new JSONObject(Boolean.parseBoolean(jsonResponse)); //TODO:无法把jsonResponse转换为JSONObject + JSONArray choices = jsonObject.getJSONArray("choices"); + if (choices != null && choices.size() > 0) { + JSONObject choice = choices.getJSONObject(0); + JSONObject delta = choice.getJSONObject("delta"); + if (delta != null) { + String content = delta.getString("content"); + fullSentence.append(content); + } + } + } + + //System.out.println(fullSentence.toString()); // 输出完整句子到控制台 + return fullSentence.toString(); + } + + +} diff --git a/pojo/src/main/java/com/groupshell/entity/chatgpt/CustomEventSourceListener.java b/pojo/src/main/java/com/groupshell/entity/chatgpt/CustomEventSourceListener.java new file mode 100644 index 0000000000000000000000000000000000000000..2247a4fe06fd289c8a79d2b44778a02f5ca457bb --- /dev/null +++ b/pojo/src/main/java/com/groupshell/entity/chatgpt/CustomEventSourceListener.java @@ -0,0 +1,57 @@ +package com.groupshell.entity.chatgpt; + +import com.unfbx.chatgpt.sse.ConsoleEventSourceListener; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import okhttp3.Response; +import okhttp3.ResponseBody; +import okhttp3.sse.EventSource; + +import java.util.Objects; + +import static com.groupshell.constant.ChatGPTConstants.CHATGPT_DONE; + +@Slf4j +public class CustomEventSourceListener extends ConsoleEventSourceListener { + ChatGPTMessageHandler messageHandler = new ChatGPTMessageHandler(); + + @Override + public void onOpen(EventSource eventSource, Response response) { + log.info("OpenAI建立sse连接..."); + } + + @Override + public void onEvent(EventSource eventSource, String id, String type, String data) { + //log.info("OpenAI返回数据:{}", data); + String response = messageHandler.responseHandler(data); + messageHandler.responses.add(response); + if (data.equals(CHATGPT_DONE)) { + log.info("OpenAI返回数据结束了"); + messageHandler.printResponses(); + //eventSource.request(); + return; + } + } + + @Override + public void onClosed(EventSource eventSource) { + log.info("OpenAI关闭sse连接..."); + } + + @SneakyThrows + @Override + public void onFailure(EventSource eventSource, Throwable t, Response response) { + if(Objects.isNull(response)){ + log.error("OpenAI sse连接异常:{}", t); + eventSource.cancel(); + return; + } + ResponseBody body = response.body(); + if (Objects.nonNull(body)) { + log.error("OpenAI sse连接异常data:{},异常:{}", body.string(), t); + } else { + log.error("OpenAI sse连接异常data:{},异常:{}", response, t); + } + eventSource.cancel(); + } +} diff --git a/pojo/src/main/java/com/groupshell/entity/chatgpt/TestChatGPT6.java b/pojo/src/main/java/com/groupshell/entity/chatgpt/TestChatGPT6.java new file mode 100644 index 0000000000000000000000000000000000000000..29537f52e0d9b4b20babbf7428e835503750b7fe --- /dev/null +++ b/pojo/src/main/java/com/groupshell/entity/chatgpt/TestChatGPT6.java @@ -0,0 +1,18 @@ +package com.groupshell.entity.chatgpt; + +import com.unfbx.chatgpt.OpenAiClient; + +import static com.groupshell.constant.ChatGPTConstants.OPENAI_CLIENT; +import static com.groupshell.constant.ChatGPTConstants.OPENAI_STREAM_CLIENT; + +public class TestChatGPT6 { + public static void main(String[] args) throws InterruptedException { + CustomChatGPT customChatGPT = new CustomChatGPT(OPENAI_STREAM_CLIENT); + customChatGPT.startChattingWithConsole(); + + + //customChatGPT.runCustomChatGPT(); + //customChatGPT.startChattingWithConsole(); + //customChatGPT.setChatGPTConfig(); + } +} diff --git a/pojo/src/main/java/com/groupshell/entity/chatgpt/TestChatGpt4.java b/pojo/src/main/java/com/groupshell/entity/chatgpt/TestChatGpt4.java deleted file mode 100644 index 277a83c283e11d6d985adf166e60cf7ef2a0a6c7..0000000000000000000000000000000000000000 --- a/pojo/src/main/java/com/groupshell/entity/chatgpt/TestChatGpt4.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.groupshell.entity.chatgpt; - -import com.unfbx.chatgpt.OpenAiStreamClient; -import com.unfbx.chatgpt.entity.chat.ChatCompletion; -import com.unfbx.chatgpt.entity.chat.ChatCompletionResponse; -import com.unfbx.chatgpt.entity.chat.Message; -import com.unfbx.chatgpt.sse.ConsoleEventSourceListener; - -import java.util.Arrays; -import java.util.concurrent.CountDownLatch; - -public class TestChatGpt4 { - public static void main(String[] args) { -// //日志拦截器 -// HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(new OpenAILogger()); -// //!!!!千万别再生产或者测试环境打开BODY级别日志!!!! -// //!!!生产或者测试环境建议设置为这三种级别:NONE,BASIC,HEADERS,!!! -// httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS); -// -// OkHttpClient okHttpClient = new OkHttpClient.Builder() -//// .proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 8080))) // 设置代理 -// .proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 7890))) // 设置代理 -// .addInterceptor(httpLoggingInterceptor) -// .connectTimeout(15, TimeUnit.SECONDS) -// .writeTimeout(15, TimeUnit.SECONDS) -// .readTimeout(15, TimeUnit.SECONDS) -// .build(); -// -// OpenAiClient client = OpenAiClient.builder() -// .apiKey(Arrays.asList("sk-OA8YqWsVOIIPeGWlD86eB41a9284495085Ab17A08c514b1e")) -// .keyStrategy(new KeyRandomStrategy()) -// .okHttpClient(okHttpClient) -//// .apiHost("https://pro.aiskt.com/") -//// .apiHost("https://one.aiskt.com") -// .apiHost("https://key.aiskt.com") -// .build(); -// -// -// List messages = new ArrayList<>(); -// messages.add(Message.builder().role(Message.Role.USER).content("您好,我想了解更多关于您的服务。").build()); -// -// ChatCompletion chatCompletion = ChatCompletion.builder().messages(messages).build(); -// ChatCompletionResponse response = client.chatCompletion(chatCompletion); -// -// System.out.println("响应:" + response.getChoices().get(0).getMessage().getContent()); - - - OpenAiStreamClient streamClient = OpenAiStreamClient.builder() - .apiKey(Arrays.asList("sk-OA8YqWsVOIIPeGWlD86eB41a9284495085Ab17A08c514b1e")) -// .apiKey(Arrays.asList("sk-pBE3MEC3Q6g0KcrpF043815cAe494f2682Ac180032C33bB5")) - .apiHost("https://pro.aiskt.com/") //支持GPT4 -// .apiHost("https://one.aiskt.com/") //不支持GPT4 - .build(); - //聊天模型:gpt-3.5 - ConsoleEventSourceListener eventSourceListener = new ConsoleEventSourceListener(); - Message message = Message.builder().role(Message.Role.USER).content("你好,你是谁?").build(); -// Message message = Message.builder().role(Message.Role.USER).content("你是GPT4吗?").build(); - ChatCompletion chatCompletion = ChatCompletion.builder().messages(Arrays.asList(message)).build(); - chatCompletion.setModel(ChatCompletion.Model.GPT_4.getName()); - streamClient.streamChatCompletion(chatCompletion, eventSourceListener); - - ChatCompletionResponse chatCompletionResponse = new ChatCompletionResponse(); - - CountDownLatch countDownLatch = new CountDownLatch(1); - - try { - countDownLatch.await(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } -} diff --git a/pom.xml b/pom.xml index 23bc68d32167fe9d6590fcf0f023b7c8d071665d..5fdaf516bc31986ad5a2cb880f54a5b6f6735a36 100644 --- a/pom.xml +++ b/pom.xml @@ -35,4 +35,4 @@ - + \ No newline at end of file diff --git a/server/pom.xml b/server/pom.xml index 6f801980d7f8b91b98c37c80c394b71513168e1e..742baab04ac1e2efe2f53982d3154d96c2b5b6df 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -32,6 +32,12 @@ mybatis-plus-spring-boot3-starter 3.5.5 + + + com.baomidou + mybatis-plus-boot-starter + 3.1.0 + org.springframework.boot @@ -128,4 +134,4 @@ - + \ No newline at end of file diff --git a/server/src/main/java/com/groupshell/controller/ChatGPTCtrl.java b/server/src/main/java/com/groupshell/controller/ChatGPTCtrl.java new file mode 100644 index 0000000000000000000000000000000000000000..e1499db7d6e02b87013f96f37ac861939988d11d --- /dev/null +++ b/server/src/main/java/com/groupshell/controller/ChatGPTCtrl.java @@ -0,0 +1,35 @@ +//package com.groupshell.controller; +// +// +//import com.groupshell.service.ChatGPTService; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.http.HttpStatus; +//import org.springframework.http.ResponseEntity; +//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; +// +//@RestController +//@RequestMapping("api/chatgpt") +//public class ChatGPTCtrl { +// +// @Autowired +// private ChatGPTService chatGPTService; +// +//// @Autowired +//// public ChatGPTCtrl(ChatGPTService chatGPTService) { +//// this.chatGPTService = chatGPTService; +//// } +// +// +// @PostMapping("/ask") +// public ResponseEntity getResponse(@RequestBody String userInput) { +// try { +// String response = chatGPTService.getResponseFromOpenAi(userInput); +// return ResponseEntity.ok(response); +// } catch (Exception e) { +// return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error processing your request"); +// } +// } +//} diff --git a/server/src/main/java/com/groupshell/controller/InvoiceCtrl.java b/server/src/main/java/com/groupshell/controller/InvoiceCtrl.java index 41424d35c64d9c78c72df0da92b2d5985124ab34..d9d99a4ea1cd1fe36fbac8f200cfc96c58491a42 100644 --- a/server/src/main/java/com/groupshell/controller/InvoiceCtrl.java +++ b/server/src/main/java/com/groupshell/controller/InvoiceCtrl.java @@ -5,6 +5,7 @@ import com.groupshell.enumeration.ReimburseStatusEnum; import com.groupshell.result.Result; import com.groupshell.service.InvoiceService; import jakarta.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.math.BigDecimal; @@ -19,38 +20,41 @@ import java.util.Map; @RequestMapping("/api/invoice") public class InvoiceCtrl { - private final InvoiceService invoiceService; - public InvoiceCtrl(InvoiceService invoiceService) {this.invoiceService=invoiceService;} + @Autowired + private InvoiceService invoiceService; +// public InvoiceCtrl(InvoiceService invoiceService) { +// this.invoiceService=invoiceService; +// } @PostMapping public Result addInvoice(@RequestBody Invoice record) { - invoiceService.addInvoice(record); + invoiceService.save(record); return Result.success(); } // 根据ID获取发票信息 @GetMapping("/{id}") public Result getInvoiceById(@PathVariable Integer id) { - Invoice invoice=invoiceService.getInvoiceById(id); + Invoice invoice=invoiceService.getById(id); return Result.success(invoice); } @GetMapping public Result> getAllInvoices() { - List invoices=invoiceService.getAllInvoices(); + List invoices=invoiceService.listObjs(); return Result.success(invoices); } //没必要另传id,id直接写在record的id字段里面 @PutMapping public Result updateInvoice(@RequestBody Invoice record) { - invoiceService.updateInvoice(record); + invoiceService.updateById(record); return Result.success(); } @DeleteMapping("/{id}") public Result deleteInvoice(@PathVariable Integer id) { - invoiceService.deleteInvoice(id); + invoiceService.removeById(id); return Result.success(); } // 获取指定时间段内的总支出 diff --git a/server/src/main/java/com/groupshell/controller/TaskCtrl.java b/server/src/main/java/com/groupshell/controller/TaskCtrl.java index 5857a66474bb558beedc3c776bc522409f0b4362..db837eb79d099db5667a608ded17f56f6fe9182e 100644 --- a/server/src/main/java/com/groupshell/controller/TaskCtrl.java +++ b/server/src/main/java/com/groupshell/controller/TaskCtrl.java @@ -58,4 +58,11 @@ public class TaskCtrl { List tasks = taskService.listTasksByStatus(status); return Result.success(tasks); } + + + @GetMapping("/group/{groupId}") + public Result> listTasksByGroup(@PathVariable Integer groupId) { + List tasks = taskService.listTasksByGroup(groupId); + return Result.success(tasks); + } } diff --git a/server/src/main/java/com/groupshell/mapper/ChatGPTHistoryMapper.java b/server/src/main/java/com/groupshell/mapper/ChatGPTHistoryMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..61d32f62dbb5db13a005bfba7cf78efca1e3d046 --- /dev/null +++ b/server/src/main/java/com/groupshell/mapper/ChatGPTHistoryMapper.java @@ -0,0 +1,13 @@ +//package com.groupshell.mapper; +// +// +//import com.groupshell.entity.chatgpt.ChatGPTHistory; +//import org.apache.ibatis.annotations.Mapper; +// +//import java.util.List; +// +//@Mapper +//public interface ChatGPTHistoryMapper { +// void insertChatHistory(ChatGPTHistory chatHistory); +// List findAllChatHistories(); +//} diff --git a/server/src/main/java/com/groupshell/mapper/InvoiceMapper.java b/server/src/main/java/com/groupshell/mapper/InvoiceMapper.java index 46274dbbbf6f4eb1872da2fdd30f1599847b5848..e6abc0adaad724518cce78114258066f2416ab10 100644 --- a/server/src/main/java/com/groupshell/mapper/InvoiceMapper.java +++ b/server/src/main/java/com/groupshell/mapper/InvoiceMapper.java @@ -1,5 +1,6 @@ package com.groupshell.mapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.groupshell.entity.Invoice; import com.groupshell.enumeration.InvoiceTypeEnum; import com.groupshell.enumeration.ReimburseStatusEnum; @@ -11,27 +12,31 @@ import java.time.LocalDateTime; import java.util.List; @Mapper -public interface InvoiceMapper -{ - Invoice insert(Invoice record); - - Invoice findById(@Param("id") Integer id); - - List findAllInvoice(); - - Invoice updateInvoiceById(Invoice record); - - String deleteById(@Param("id") Integer id); - - BigDecimal sumAmountByDate(@Param("type") InvoiceTypeEnum type,@Param("start") LocalDateTime start, - @Param("end") LocalDateTime end); - - List findByCategoryAndDate(@Param("category") String category,@Param("start") LocalDateTime start,@Param( - "end") LocalDateTime end); - +public interface InvoiceMapper extends BaseMapper { + //Invoice insert(Invoice record); + + //Invoice findById(@Param("id") Integer id); + Invoice findByUserId(@Param("userId") Integer userId); + + //List findAllInvoice(); + + //Invoice updateInvoiceById(Invoice record); + + //String deleteById(@Param("id") Integer id); + + BigDecimal sumAmountByDate(@Param("type") InvoiceTypeEnum type, + @Param("start") LocalDateTime start, + @Param("end") LocalDateTime end); + + List findByCategoryAndDate(@Param("category") String category, + @Param("start") LocalDateTime start, + @Param("end") LocalDateTime end); + + List findByReimburseStatus(ReimburseStatusEnum status); - - BigDecimal sumReimburseAmountByDate(LocalDateTime start,LocalDateTime end); - + + BigDecimal sumReimburseAmountByDate(LocalDateTime start, LocalDateTime end); + List findReimbursementsByUserId(Integer userId); + List findReimbursementsByGroupId(Integer groupId); } diff --git a/server/src/main/java/com/groupshell/mapper/TaskMapper.java b/server/src/main/java/com/groupshell/mapper/TaskMapper.java index e740ff7ff8cd1f0519ad0734b2bb589fcc03f274..77466623693c85961bf8b2ce5efcffcf09991285 100644 --- a/server/src/main/java/com/groupshell/mapper/TaskMapper.java +++ b/server/src/main/java/com/groupshell/mapper/TaskMapper.java @@ -1,5 +1,6 @@ package com.groupshell.mapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.groupshell.entity.Task; import com.groupshell.enumeration.TaskStatusEnum; import org.apache.ibatis.annotations.Mapper; @@ -8,7 +9,7 @@ import org.apache.ibatis.annotations.Param; import java.util.List; @Mapper -public interface TaskMapper +public interface TaskMapper extends BaseMapper { int insertTask(Task task); @@ -21,4 +22,6 @@ public interface TaskMapper List findTasksByCreatorId(@Param("creatorId") Integer creatorId); List findTasksByStatus(@Param("status") TaskStatusEnum status); + + List findTasksByGroupId(@Param("groupId") Integer groupId); } \ No newline at end of file diff --git a/server/src/main/java/com/groupshell/service/ChatGPTService.java b/server/src/main/java/com/groupshell/service/ChatGPTService.java new file mode 100644 index 0000000000000000000000000000000000000000..28154aa3caab38a1fca28f8928d102c581658d98 --- /dev/null +++ b/server/src/main/java/com/groupshell/service/ChatGPTService.java @@ -0,0 +1,15 @@ +//package com.groupshell.service; +// +//import com.baomidou.mybatisplus.extension.service.IService; +//import com.groupshell.entity.chatgpt.CustomChatGPT; +//import org.springframework.stereotype.Service; +// +//import java.io.IOException; +// +////extends IService +//@Service +//public interface ChatGPTService { +// +// public String getResponseFromOpenAi(String userInput) throws IOException; +// +//} diff --git a/server/src/main/java/com/groupshell/service/InvoiceService.java b/server/src/main/java/com/groupshell/service/InvoiceService.java index dfd63b59904fb0c11d8d7588a00f65a8cdc9a1b0..7e73354c7fdc65d3e6ada5ac7b9f54a4dd37a1bf 100644 --- a/server/src/main/java/com/groupshell/service/InvoiceService.java +++ b/server/src/main/java/com/groupshell/service/InvoiceService.java @@ -1,27 +1,28 @@ package com.groupshell.service; +import com.baomidou.mybatisplus.extension.service.IService; import com.groupshell.entity.Invoice; import com.groupshell.enumeration.ReimburseStatusEnum; import jakarta.servlet.http.HttpServletResponse; -import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; import java.util.Map; -@Service -public interface InvoiceService { - public Invoice addInvoice(Invoice record); +public interface InvoiceService extends IService { - public Invoice getInvoiceById(Integer id); + //public int addInvoice(Invoice record); - public List getAllInvoices(); + //public Invoice getInvoiceById(Integer id); + public Invoice getInvoiceByUserId(Integer userId); - public Invoice updateInvoice(Invoice record); + //public List getAllInvoices(); - public String deleteInvoice(Integer id); + //public Invoice updateInvoice(Invoice record); + + //public String deleteInvoice(Integer id); public BigDecimal getExpensesByTime(LocalDateTime start, LocalDateTime end); @@ -38,6 +39,6 @@ public interface InvoiceService { BigDecimal sumReimburseAmount(LocalDateTime start, LocalDateTime end); List findReimburseByUserId(Integer userId); - + void exportInvoiceData(HttpServletResponse response); } diff --git a/server/src/main/java/com/groupshell/service/TaskService.java b/server/src/main/java/com/groupshell/service/TaskService.java index c1a5c7741833b03cee2306446d2af69c23d64e5b..c8a873003c892119eb2e7ab76d64fe4352530b59 100644 --- a/server/src/main/java/com/groupshell/service/TaskService.java +++ b/server/src/main/java/com/groupshell/service/TaskService.java @@ -1,11 +1,12 @@ package com.groupshell.service; +import com.baomidou.mybatisplus.extension.service.IService; import com.groupshell.entity.Task; import com.groupshell.enumeration.TaskStatusEnum; import java.util.List; -public interface TaskService +public interface TaskService extends IService { Task createTask(Task task); @@ -18,4 +19,6 @@ public interface TaskService List listTasksByAssignee(Integer assigneeId); List listTasksByStatus(TaskStatusEnum status); + + List listTasksByGroup(Integer groupId); } diff --git a/server/src/main/java/com/groupshell/service/impl/ChatGPTServiceImpl.java b/server/src/main/java/com/groupshell/service/impl/ChatGPTServiceImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..5a0a479a4d3ce13065654b8a82dcc1ba9798b6d2 --- /dev/null +++ b/server/src/main/java/com/groupshell/service/impl/ChatGPTServiceImpl.java @@ -0,0 +1,34 @@ +//package com.groupshell.service.impl; +// +//import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +//import com.groupshell.entity.Invoice; +//import com.groupshell.entity.chatgpt.CustomChatGPT; +//import com.groupshell.mapper.InvoiceMapper; +//import com.groupshell.service.ChatGPTService; +//import com.unfbx.chatgpt.entity.chat.ChatCompletion; +//import com.unfbx.chatgpt.entity.chat.ChatCompletionResponse; +//import com.unfbx.chatgpt.entity.chat.Message; +//import org.springframework.beans.factory.annotation.Autowired; +// +//import java.io.IOException; +//import java.util.Collections; +// +////extends ServiceImpl<...Mapper, ...> +//public class ChatGPTServiceImpl implements ChatGPTService { +// +// @Autowired +// private CustomChatGPT customChatGPT; +// +// @Override +// public String getResponseFromOpenAi(String userInput) throws IOException { +// return null; +// } +//// @Override +//// public String getResponseFromOpenAi(String userInput) throws IOException { +//// ChatCompletion chatCompletion = ChatCompletion.builder() +//// .messages(Collections.singletonList(Message.builder().content(userInput).build())) +//// .build(); +//// ChatCompletionResponse response = customChatGPT.getChatGPTConfig().getChatCompletion(); +//// return response.getChoices().get(0).getMessage().getContent(); +//// } +//} diff --git a/server/src/main/java/com/groupshell/service/impl/InvoiceServiceImpl.java b/server/src/main/java/com/groupshell/service/impl/InvoiceServiceImpl.java index d6007f08275c546639742254dc4e5f520ad04abe..f933139e78d09758abbe48cc10555718ab4fb347 100644 --- a/server/src/main/java/com/groupshell/service/impl/InvoiceServiceImpl.java +++ b/server/src/main/java/com/groupshell/service/impl/InvoiceServiceImpl.java @@ -1,111 +1,109 @@ package com.groupshell.service.impl; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.groupshell.entity.Invoice; import com.groupshell.enumeration.InvoiceTypeEnum; import com.groupshell.enumeration.ReimburseStatusEnum; import com.groupshell.mapper.InvoiceMapper; import com.groupshell.service.InvoiceService; -import jakarta.servlet.ServletOutputStream; import jakarta.servlet.http.HttpServletResponse; -import org.apache.poi.xssf.usermodel.XSSFRow; -import org.apache.poi.xssf.usermodel.XSSFSheet; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.io.IOException; -import java.io.InputStream; import java.math.BigDecimal; -import java.time.LocalDate; import java.time.LocalDateTime; -import java.time.LocalTime; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @Service -public class InvoiceServiceImpl implements InvoiceService -{ - @Autowired - private InvoiceMapper invoiceMapper; - @Override - public Invoice addInvoice(Invoice record) - { - return invoiceMapper.insert(record); - } - //TODO:实现Controller类的函数 - @Override - public Invoice getInvoiceById(Integer id) - { - return invoiceMapper.findById(id); - } - @Override - public List getAllInvoices() - { - return invoiceMapper.findAllInvoice(); - } - @Override - public Invoice updateInvoice(Invoice record) - { - return invoiceMapper.updateInvoiceById(record); +public class InvoiceServiceImpl extends ServiceImpl implements InvoiceService { + + //@Autowired + private final InvoiceMapper invoiceMapper; + public InvoiceServiceImpl(InvoiceMapper invoiceMapper) { + this.invoiceMapper=invoiceMapper; } + +// @Override +// public int addInvoice(Invoice record) { +// return invoiceMapper.insert(record); +// } + +// @Override +// public Invoice getInvoiceById(Integer id) { +// return invoiceMapper.findById(id); +// } + @Override - public String deleteInvoice(Integer id) - { - invoiceMapper.deleteById(id); - return "Record deleted successfully!"; + public Invoice getInvoiceByUserId(Integer userId) { + return invoiceMapper.findByUserId(userId); } + +// @Override +// public List getAllInvoices() { +// return invoiceMapper.findAllInvoice(); +// } +// +// @Override +// public Invoice updateInvoice(Invoice record) { +// return invoiceMapper.updateInvoiceById(record); +// } +// +// @Override +// public String deleteInvoice(Integer id) { +// invoiceMapper.deleteById(id); +// return "Record deleted successfully!"; +// } + //TODO:实现Controller类的函数 @Override - public BigDecimal getExpensesByTime(LocalDateTime start,LocalDateTime end) - { - return invoiceMapper.sumAmountByDate(InvoiceTypeEnum.EXPENSE,start,end); + public BigDecimal getExpensesByTime(LocalDateTime start, LocalDateTime end) { + return invoiceMapper.sumAmountByDate(InvoiceTypeEnum.EXPENSE, start, end); } + @Override - public BigDecimal getIncomesByTime(LocalDateTime start,LocalDateTime end) - { - return invoiceMapper.sumAmountByDate(InvoiceTypeEnum.INCOME,start,end); + public BigDecimal getIncomesByTime(LocalDateTime start, LocalDateTime end) { + return invoiceMapper.sumAmountByDate(InvoiceTypeEnum.INCOME, start, end); } + @Override - public BigDecimal getNetIncomeByTime(LocalDateTime start,LocalDateTime end) - { - BigDecimal income=invoiceMapper.sumAmountByDate(InvoiceTypeEnum.INCOME,start,end); - BigDecimal expenses=invoiceMapper.sumAmountByDate(InvoiceTypeEnum.EXPENSE,start,end); + public BigDecimal getNetIncomeByTime(LocalDateTime start, LocalDateTime end) { + BigDecimal income = invoiceMapper.sumAmountByDate(InvoiceTypeEnum.INCOME, start, end); + BigDecimal expenses = invoiceMapper.sumAmountByDate(InvoiceTypeEnum.EXPENSE, start, end); return income.subtract(expenses); } + + //从数据库查询特定类别和时间范围内的发票,然后计算每个类别的总金额,并以Map形式返回结果 @Override - public Map getExpensesByCategory(String category,LocalDateTime start,LocalDateTime end) - { - List records=invoiceMapper.findByCategoryAndDate(category,start,end); - return records.stream() - .collect(Collectors.groupingBy(Invoice::getCategory,Collectors.reducing(BigDecimal.ZERO, - Invoice::getAmount,BigDecimal::add))); + public Map getExpensesByCategory(String category, LocalDateTime start, LocalDateTime end) { + List records = invoiceMapper.findByCategoryAndDate(category, start, end); + return records.stream().collect(Collectors.groupingBy(Invoice::getCategory, + Collectors.reducing(BigDecimal.ZERO, Invoice::getAmount, BigDecimal::add))); } + // 新增方法:更新报销状态 - public Invoice updateReimburseStatus(Integer invoiceId,ReimburseStatusEnum status) - { - Invoice invoice=invoiceMapper.findById(invoiceId); - if(invoice!=null) - { + public Invoice updateReimburseStatus(Integer invoiceId, ReimburseStatusEnum status) { + Invoice invoice = invoiceMapper.selectById(invoiceId); + if (invoice != null) { invoice.setReimburseStatus(status); - invoiceMapper.updateInvoiceById(invoice); + invoiceMapper.updateById(invoice); } return invoice; } + // 新增方法:查询特定报销状态的账单 - public List findInvoicesByReimburseStatus(ReimburseStatusEnum status) - { + public List findInvoicesByReimburseStatus(ReimburseStatusEnum status) { return invoiceMapper.findByReimburseStatus(status); } + // 新增方法:统计特定时间段内的报销金额 - public BigDecimal sumReimburseAmount(LocalDateTime start,LocalDateTime end) - { - return invoiceMapper.sumReimburseAmountByDate(start,end); + public BigDecimal sumReimburseAmount(LocalDateTime start, LocalDateTime end) { + return invoiceMapper.sumReimburseAmountByDate(start, end); } + // 新增方法:查询特定用户的报销历史 - public List findReimburseByUserId(Integer userId) - { + public List findReimburseByUserId(Integer userId) { return invoiceMapper.findReimbursementsByUserId(userId); } //todo 导出某团队的账单数据 diff --git a/server/src/main/java/com/groupshell/service/impl/TaskServiceImpl.java b/server/src/main/java/com/groupshell/service/impl/TaskServiceImpl.java index 7b33165d6447f85c360ab09eb077288e9d60bdcb..320eda4d9996c11718c7b4d0b8348f3243c13627 100644 --- a/server/src/main/java/com/groupshell/service/impl/TaskServiceImpl.java +++ b/server/src/main/java/com/groupshell/service/impl/TaskServiceImpl.java @@ -1,5 +1,6 @@ package com.groupshell.service.impl; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.groupshell.entity.Task; import com.groupshell.enumeration.TaskStatusEnum; import com.groupshell.mapper.TaskMapper; @@ -11,10 +12,12 @@ import java.time.LocalDateTime; import java.util.List; @Service -public class TaskServiceImpl implements TaskService +public class TaskServiceImpl extends ServiceImpl implements TaskService { private final TaskMapper taskMapper; - public TaskServiceImpl(TaskMapper taskMapper) {this.taskMapper=taskMapper;} + public TaskServiceImpl(TaskMapper taskMapper) { + this.taskMapper=taskMapper; + } @Override public Task createTask(Task task) { @@ -50,4 +53,10 @@ public class TaskServiceImpl implements TaskService { return taskMapper.findTasksByStatus(status); } + + @Override + public List listTasksByGroup(Integer groupId) + { + return taskMapper.findTasksByGroupId(groupId); + } } diff --git a/server/src/main/resources/mapper/InvoiceMapper.xml b/server/src/main/resources/mapper/InvoiceMapper.xml index 2f95c4400b56adc5d628c00a270b692e85e87be8..12eadefe5978ef579ee4f29b7742d9d496eaea24 100644 --- a/server/src/main/resources/mapper/InvoiceMapper.xml +++ b/server/src/main/resources/mapper/InvoiceMapper.xml @@ -1,11 +1,11 @@ - + id, amount, type, description, category, created_time, user_id, pay_method, reimburse_status, reimburse_request_time, reimburse_complete_time, - approver_id, reimburse_notes + approver_id, reimburse_notes, group_id #{id}, @@ -21,24 +21,31 @@ #{reimburseCompleteTime}, #{approverId}, #{reimburseNotes} + #{groupId} - - INSERT INTO invoice () - VALUES () - + + + + - + + + + + - SELECT * FROM invoice + WHERE user_id = #{userId} + + + + + UPDATE invoice @@ -78,15 +85,18 @@ reimburse_notes = #{reimburseNotes}, + + group_id = #{groupId}, + WHERE id = #{id} - - DELETE - FROM invoice - WHERE id = #{id} - + + + + + + + + diff --git a/server/src/main/resources/mapper/TaskMapper.xml b/server/src/main/resources/mapper/TaskMapper.xml index d45423ed2be946282170ce363162064e53b861aa..97d78db259a4db80ac593dd57ba2362931106e9d 100644 --- a/server/src/main/resources/mapper/TaskMapper.xml +++ b/server/src/main/resources/mapper/TaskMapper.xml @@ -3,7 +3,7 @@ - id, title, description,create_time, update_time,start_time, deadline, assignee_id, creator_id, priority, status + id, title, description,created_time, updated_time,start_time, deadline, assignee_id, creator_id, priority, status, group_id id, title, description, - create_time, - update_time, + created_time, + updated_time, start_time, deadline, assignee_id, creator_id, priority, status, + group_id, #{id}, #{title}, #{description}, - #{createdTime}, - #{updatedTime}, + #{createdTime}, + #{updatedTime}, #{startTime}, #{deadline}, #{assigneeId}, #{creatorId}, #{priority}, #{status}, + #{groupId}, @@ -47,17 +49,16 @@ description = #{description}, - - create_time = #{createdTime}, + + created_time = #{createdTime}, - - update_time = #{updatedTime}, + + updated_time = #{updatedTime}, start_time = #{startTime}, - deadline = #{deadline}, @@ -72,6 +73,9 @@ status = #{status}, + + group_id = #{groupId}, + WHERE id = #{id} @@ -104,4 +108,11 @@ WHERE status = #{status} + + +