├── .gitignore ├── LICENSE ├── pom.xml ├── readme.md ├── src ├── main │ ├── java │ │ └── com │ │ │ └── blue │ │ │ └── cat │ │ │ ├── BlueCatApplication.java │ │ │ ├── bean │ │ │ ├── annotation │ │ │ │ └── VisitLimit.java │ │ │ ├── common │ │ │ │ ├── BaseCode.java │ │ │ │ └── BaseCodeEnum.java │ │ │ ├── constants │ │ │ │ ├── CommonConstant.java │ │ │ │ ├── LimitEnum.java │ │ │ │ ├── ModelEnum.java │ │ │ │ ├── ModelServiceTypeConstant.java │ │ │ │ ├── UserLevelConstant.java │ │ │ │ └── UserLevelEnum.java │ │ │ ├── entity │ │ │ │ ├── LoginUserInfo.java │ │ │ │ ├── PopupInfo.java │ │ │ │ ├── PromptModel.java │ │ │ │ ├── UserAccessRule.java │ │ │ │ └── UserInfo.java │ │ │ ├── gpt │ │ │ │ ├── ChatReq.java │ │ │ │ ├── ChoiceMessage.java │ │ │ │ ├── GptTurbo.java │ │ │ │ ├── ImageReq.java │ │ │ │ ├── OpenReq.java │ │ │ │ └── drawImageRes.java │ │ │ ├── req │ │ │ │ ├── CompletionReq.java │ │ │ │ ├── PopupReq.java │ │ │ │ ├── UserAccessRuleUpdateReq.java │ │ │ │ ├── UserInfoLoginReq.java │ │ │ │ ├── UserInfoRegisterReq.java │ │ │ │ ├── UserQueryReq.java │ │ │ │ └── UserUpdateReq.java │ │ │ ├── util │ │ │ │ ├── UserAccessRuleUtil.java │ │ │ │ └── UserInfoUtil.java │ │ │ └── vo │ │ │ │ ├── CacheUserInfoVo.java │ │ │ │ ├── PromptModelVo.java │ │ │ │ └── UserLevelAccessVo.java │ │ │ ├── config │ │ │ └── WebConfig.java │ │ │ ├── controller │ │ │ ├── OpenAPIController.java │ │ │ ├── PopupController.java │ │ │ ├── PromptModelController.java │ │ │ ├── UserAccessRuleController.java │ │ │ └── UserInfoController.java │ │ │ ├── handler │ │ │ ├── PopupHandler.java │ │ │ ├── PromptModelHandler.java │ │ │ ├── ThreadPoolManager.java │ │ │ ├── UserHandler.java │ │ │ └── access │ │ │ │ ├── UserAccessHandler.java │ │ │ │ ├── UserLevelVisitFactory.java │ │ │ │ └── rule │ │ │ │ ├── CommonUserChatGptUserServiceTypeRule3.java │ │ │ │ ├── CommonUserChatGptUserServiceTypeRule4.java │ │ │ │ ├── DurationUserChatGptUserServiceTypeRule3.java │ │ │ │ ├── DurationUserChatGptUserServiceTypeRule4.java │ │ │ │ ├── PermanentUserChatGptUserServiceTypeRule3.java │ │ │ │ ├── PermanentUserChatGptUserServiceTypeRule4.java │ │ │ │ └── UserServiceTypeRule.java │ │ │ ├── interceptor │ │ │ ├── ChatGptInterceptor3.java │ │ │ ├── ChatGptInterceptor4.java │ │ │ ├── LoginInterceptor.java │ │ │ └── VisitLimitInterceptor.java │ │ │ ├── job │ │ │ ├── UserAccessJob.java │ │ │ └── UserLoginUserJob.java │ │ │ ├── mapper │ │ │ ├── LoginUserInfoMapper.java │ │ │ ├── PopupInfoMapper.java │ │ │ ├── PromptModelMapper.java │ │ │ ├── UserAccessRuleMapper.java │ │ │ └── UserInfoMapper.java │ │ │ ├── service │ │ │ ├── ILoginUserInfoService.java │ │ │ ├── IPopupInfoService.java │ │ │ ├── IUserAccessRuleService.java │ │ │ ├── IUserInfoService.java │ │ │ └── impl │ │ │ │ ├── LoginUserInfoServiceImpl.java │ │ │ │ ├── PopupInfoServiceImpl.java │ │ │ │ ├── UserAccessRuleServiceImpl.java │ │ │ │ └── UserInfoServiceImpl.java │ │ │ └── utils │ │ │ ├── CacheUtil.java │ │ │ ├── ChatGptUtils.java │ │ │ ├── HttpUtil.java │ │ │ ├── IpCacheUtil.java │ │ │ ├── MybatisPlusGeneratorUtil.java │ │ │ ├── OkHttpUtils.java │ │ │ ├── OpenGptUtil.java │ │ │ ├── RegexUtil.java │ │ │ ├── ResultVO.java │ │ │ ├── SessionUser.java │ │ │ └── WebUtils.java │ └── resources │ │ ├── application-dev.yml │ │ └── application-prod.yml └── test │ └── java │ └── com │ └── blue │ └── cat │ ├── BlueCatApplicationTests.java │ ├── RunnerTest.java │ ├── access │ └── AccessTest.java │ └── user │ └── UserInfoTest.java └── 执行SQL └── blueCat.sql /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.3.0.RELEASE 9 | 10 | 11 | com.blue.cat 12 | blue-cat 13 | 0.0.1-SNAPSHOT 14 | blue-cat 15 | blue-cat 16 | jar 17 | 18 | 1.8 19 | 2.0.0 20 | 21 | 22 | 23 | 24 | 25 | eu.bitwalker 26 | UserAgentUtils 27 | 1.21 28 | 29 | 30 | 31 | 32 | org.hibernate 33 | hibernate-validator 34 | 6.2.0.Final 35 | 36 | 37 | 38 | javax.validation 39 | validation-api 40 | 1.1.0.Final 41 | 42 | 43 | 44 | 45 | 46 | com.github.ulisesbocchio 47 | jasypt-spring-boot-starter 48 | ${jasypt-spring-boot-starter.version} 49 | 50 | 51 | 52 | 53 | 54 | org.springframework.boot 55 | spring-boot-starter 56 | 57 | 58 | 59 | org.springframework.boot 60 | spring-boot-starter-web 61 | 62 | 63 | 64 | org.springframework.boot 65 | spring-boot-starter-aop 66 | 67 | 68 | 69 | org.springframework.boot 70 | spring-boot-starter-test 71 | test 72 | 73 | 74 | 75 | org.springframework 76 | spring-context 77 | 78 | 79 | 80 | org.projectlombok 81 | lombok 82 | 1.18.16 83 | 84 | 85 | 86 | 87 | com.alibaba 88 | fastjson 89 | 1.2.83 90 | 91 | 92 | 93 | 94 | org.springframework.boot 95 | spring-boot-starter-jdbc 96 | 97 | 98 | 99 | mysql 100 | mysql-connector-java 101 | runtime 102 | 103 | 104 | 105 | com.baomidou 106 | mybatis-plus-boot-starter 107 | 3.3.2 108 | 109 | 110 | mybatis-plus-extension 111 | com.baomidou 112 | 113 | 114 | 115 | 116 | 117 | com.baomidou 118 | mybatis-plus-generator 119 | 3.3.0 120 | 121 | 122 | 123 | io.github.asleepyfish 124 | chatgpt 125 | 1.1.4 126 | 127 | 128 | 129 | com.google.guava 130 | guava 131 | 31.1-jre 132 | 133 | 134 | 135 | commons-collections 136 | commons-collections 137 | 3.2.2 138 | 139 | 140 | 141 | com.squareup.okhttp3 142 | okhttp-sse 143 | 4.9.3 144 | 145 | 146 | 147 | org.apache.commons 148 | commons-lang3 149 | 3.4 150 | 151 | 152 | 153 | org.hibernate 154 | hibernate-validator 155 | 6.2.0.Final 156 | 157 | 158 | 159 | org.apache.velocity 160 | velocity-engine-core 161 | 2.0 162 | 163 | 164 | 165 | javax.persistence 166 | persistence-api 167 | 1.0.2 168 | 169 | 170 | 171 | 172 | 173 | 174 | org.springframework.boot 175 | spring-boot-maven-plugin 176 | 177 | 178 | org.apache.maven.plugins 179 | maven-jar-plugin 180 | 3.2.0 181 | 182 | 183 | **/Test*.class 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ### 使用Java语言作为后端对接 chatgpt,使用简单,并且有可以免费chatgpt3.5,没有套路 2 | ### 后端架构:mysql,springBoot 部署简单维护也简单 3 | ###蓝猫AI后端服务指引 4 | ### 效果可以体验 : http://www.chosen1.xyz/ 5 | ### 对应前端地址: https://github.com/linyours/chatgpt-web-java 6 | ## 后端定制化返回markdowm格式给前端进行图片展示: 7 | ![提示词]("url") 8 | 9 | ##上效果图 10 | ![pc端的聊天效果图](https://gitee.com/lixinjiuhao/chatgpt-java-web/raw/master/image/pc-chat-black.jpg) 11 | ![pc端的黑色背景聊天图](image/pc-chat-black.jpg) 12 | ![pc端的黑白色背景聊天图](image/image/pc-chat-white.jpg) 13 | ![pc端prompt工具图](image/pc-tool.jpg) 14 | ![手机端的黑色背景聊天图](image/phone-chat-black.jpg) 15 | ![手机端的白色背景聊天图](image/phone-chat-white.jpg) 16 | ![手机端的prompt工具图](image/phton-tool.jpg) 17 | 18 | ## 项目启动准备 19 | ### 添加gpt的token,和本地或者线上环境的 mysql连接信息 20 | ![项目启动前必填](image/项目启动前必填.jpeg) 21 | ### 本地根据vm指令去加载不同环境的配置 22 | #### 步骤一 23 | ![步骤一](image/idea的vm配置步骤1.jpeg) 24 | #### 步骤二 25 | ![步骤二](image/idea的vm配置步骤2.jpeg) 26 | 解释说明 27 | 按照上面操作: 28 | vm options添加: -Dspring.profiles.active=dev 则代表 加载 application-dev.yml 配置 29 | vm options添加: -Dspring.profiles.active=prod 则代表 加载 application-prod.yml 配置 30 | 对应下图的 31 | ![步骤二](image/vm配置解释说明.jpeg) 32 | 33 | # 项目部署 方式1: 34 | ##服务器中运行脚本: 35 | java -jar xxx.jar --spring.profiles.active=dev 36 | ## 本地运行: 37 | 线上环境 38 | vm option添加:-Dspring.profiles.active=prod 39 | nohup java -jar -Xmx512m -Xms512m -XX:MaxPermSize=256m -XX:PermSize=128m -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M -XX:+UseParallelGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/var/log/myapp/gc.log blue-cat-0.0.8-SNAPSHOT.jar --spring.profiles.active=prod 40 | 本地环境 41 | vm option添加:-Dspring.profiles.active=dev 42 | 43 | ## maven打包命令 44 | mvn clean install -U -Dmaven.test.skip=true 45 | 46 | # 项目部署部署 方式2 47 | ## 通过脚本一键部署 48 | ### 步骤一: 49 | 前提: 需要在服务器安装 git , maven , jdk 50 | ### 步骤二: 51 | 打开目标脚本: bin/server.sh ,按照你自己的配置进行改动脚本里面的自定义脚本配置 52 | ![脚本需要关心的配置](image/脚本配置.jpeg) 53 | ### 步骤三: 54 | 拷贝server.sh 到项目所需要保存的位置 55 | 执行sh server.sh start // 启动命令 56 | 执行sh server.sh restart //重启项目 57 | 执行sh server.sh stop // 停止项目 58 | # 疑问 59 | 如果还有什么不清晰的,可以提 issues ,希望大家点点 star 60 | 如果有兴趣想要一起维护此项目的,可以留言,了解过后可以开给你权限 61 | 62 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/BlueCatApplication.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat; 2 | 3 | import io.github.asleepyfish.annotation.EnableChatGPT; 4 | import org.mybatis.spring.annotation.MapperScan; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.scheduling.annotation.EnableAsync; 8 | import org.springframework.scheduling.annotation.EnableScheduling; 9 | 10 | 11 | @SpringBootApplication 12 | @EnableScheduling 13 | @EnableAsync 14 | @EnableChatGPT 15 | @MapperScan("com.blue.cat.mapper.**") 16 | public class BlueCatApplication { 17 | 18 | public static void main(String[] args) { 19 | SpringApplication.run(BlueCatApplication.class, args); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/bean/annotation/VisitLimit.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.bean.annotation; 2 | 3 | import com.blue.cat.bean.constants.CommonConstant; 4 | import com.blue.cat.bean.constants.LimitEnum; 5 | 6 | import java.lang.annotation.*; 7 | 8 | @Target({ElementType.METHOD, ElementType.TYPE}) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | @Documented 11 | public @interface VisitLimit { 12 | LimitEnum[] value() default {}; 13 | 14 | /** 15 | * 作用域 默认为1,当为1的时候 在用户登录状态下生效,2的时候不生效 16 | * @return 17 | */ 18 | int scope() default CommonConstant.ALL_SCOPE; 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/bean/common/BaseCode.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.bean.common; 2 | 3 | public interface BaseCode { 4 | int getCode(); 5 | String getMsg(); 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/bean/common/BaseCodeEnum.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.bean.common; 2 | 3 | import com.blue.cat.bean.constants.CommonConstant; 4 | 5 | public enum BaseCodeEnum implements BaseCode { 6 | 7 | // 成功 8 | SUCCESS(200, "OK"), 9 | FAIL(-1, "FAIL"), 10 | PARAM_ERROR(400, "PARAM VALID NOT PASS!"), 11 | SIGNATURE_NOT_MATCH(401, "SIGNATURE NOT MATCH!"), 12 | INTERNAL_SERVER_ERROR(500, "INTERNAL SERVER ERROR!"), 13 | SERVER_BUSY(503, "系统繁忙,请稍微再试!"), 14 | NO_VISITS_NUMBER(1002,"您的访问次数已经达到上限,请关注公众号“蓝猫三千问”获取访问次数 " + 15 | " ![蓝猫三千问]( "+ CommonConstant.OFFICIAL_ACCOUNT +" ) "), 16 | LOGIN_EXPIRE(1001, "blueCat-login-expire"), 17 | HAVE_FILTER_WORD(1003, "问题中包含保存违规信息,请重新编辑!"), 18 | IP_LIMIT_MSG(1006,"您好,不好意思!为防止接口被刷次数,登录账号即可重新访问!"), 19 | VISIT_BUZY(1008,"您好,不好意思!为防止接口被刷次数,发现您现在访问过于频繁,请等待五秒再进行访问!"); 20 | private int value; 21 | 22 | private String text; 23 | 24 | BaseCodeEnum(int value, String text) { 25 | this.value = value; 26 | this.text = text; 27 | } 28 | 29 | @Override 30 | public int getCode() { 31 | return this.value; 32 | } 33 | 34 | @Override 35 | public String getMsg() { 36 | return this.text; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/bean/constants/CommonConstant.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.bean.constants; 2 | 3 | public class CommonConstant { 4 | 5 | /** 6 | * 登录成功 cookie的key 7 | */ 8 | public final static String TOKEN = "blueCat_token"; 9 | 10 | /** 11 | * 登录失效三小时 12 | */ 13 | public final static int CACHE_TIME_OUT = 10800; 14 | 15 | /** 16 | * 通用的敏感词过滤通道ID 17 | */ 18 | public final static Long COMMON_FILTER_CHANNEL_ID = 22L; 19 | 20 | public final static Long COMMON_REGEX_CHANNEL_ID = 5232962780960694399L; 21 | 22 | /** 23 | * 公众号的二维码 24 | */ 25 | public final static String OFFICIAL_ACCOUNT = "http://43.153.112.145:1002/wechat.jpeg"; 26 | /** 27 | * 聊天的来源 28 | */ 29 | public final static String CHAT_SOURCE = "chat"; 30 | 31 | public final static String PROMPT_TOOL_SOURCE = "AITool"; 32 | 33 | /** 34 | * 限流规则ip 35 | */ 36 | public final static String LIMIT_IP = "IP"; 37 | 38 | /** 39 | * 如果用户没有登录的话 最多访问次数 40 | */ 41 | public final static Integer LIMIT_IP_COUNT = 10; 42 | 43 | /** 44 | * 默认十秒才能发一次话 45 | */ 46 | public final static Integer CHAT_LIMIT_TIME = 5; 47 | 48 | /** 49 | * 登录的作用域 50 | */ 51 | public final static int LOGIN_SCOPE = 1; 52 | 53 | 54 | /** 55 | * 不登录的作用域 56 | */ 57 | public final static int NO_LOGIN_SCOPE = 2; 58 | 59 | 60 | /** 61 | * 所有的作用域 62 | */ 63 | public final static int ALL_SCOPE = 3; 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/bean/constants/LimitEnum.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.bean.constants; 2 | 3 | 4 | import lombok.AllArgsConstructor; 5 | import lombok.Getter; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Getter 9 | @AllArgsConstructor 10 | @NoArgsConstructor 11 | public enum LimitEnum { 12 | 13 | IP(CommonConstant.LIMIT_IP,5,86400L); 14 | 15 | private String limit;//规则标识 16 | private Integer number;// 次数 17 | private Long time;// 时间 单位自定义 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/bean/constants/ModelEnum.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.bean.constants; 2 | 3 | 4 | /** 5 | * 目前系统支持的模型type 6 | */ 7 | public enum ModelEnum { 8 | 9 | CHAT_GPT3(ModelServiceTypeConstant.CHAT_GPT_MODEL3,"chat-gpt3.5模型"), 10 | CHAT_GPT4(ModelServiceTypeConstant.CHAT_GPT_MODEL4,"chat-gpt4模型"); 11 | 12 | private String modelType; 13 | private String desc; 14 | 15 | ModelEnum(String modelType, String desc) { 16 | this.modelType = modelType; 17 | this.desc = desc; 18 | } 19 | 20 | public String getModelType() { 21 | return modelType; 22 | } 23 | 24 | public String getDesc() { 25 | return desc; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/bean/constants/ModelServiceTypeConstant.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.bean.constants; 2 | 3 | 4 | /** 5 | * 系统支持的模型type标识 6 | */ 7 | public class ModelServiceTypeConstant { 8 | 9 | /** 10 | * chat-gpt模型3.5 11 | */ 12 | public static final String CHAT_GPT_MODEL3 = "chat_gpt_model3.5"; 13 | 14 | /** 15 | * chat-gpt模型4 16 | */ 17 | public static final String CHAT_GPT_MODEL4 = "chat_gpt_model4"; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/bean/constants/UserLevelConstant.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.bean.constants; 2 | 3 | public class UserLevelConstant { 4 | 5 | public static final String COMMON_USER = "common_user"; 6 | 7 | public static final String DURATION_USER = "duration_user"; 8 | 9 | public static final String PERMANENT_USERS= "permanent_users"; 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/bean/constants/UserLevelEnum.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.bean.constants; 2 | 3 | 4 | import java.util.Objects; 5 | 6 | /** 7 | * 用户的表示 8 | */ 9 | public enum UserLevelEnum { 10 | 11 | COMMON_USER(UserLevelConstant.COMMON_USER,"普通用户"), 12 | DURATION_USER(UserLevelConstant.DURATION_USER,"时长用户"), 13 | PERMANENT_USERS(UserLevelConstant.PERMANENT_USERS,"永久用户"); 14 | 15 | private String userLevel; 16 | private String desc; 17 | 18 | UserLevelEnum(String userLevel, String desc) { 19 | this.userLevel = userLevel; 20 | this.desc = desc; 21 | } 22 | 23 | public String getUserLevel() { 24 | return userLevel; 25 | } 26 | 27 | public String getDesc() { 28 | return desc; 29 | } 30 | 31 | /** 32 | * 根据userLevel获取desc 33 | * @param userLevel 34 | * @return 35 | */ 36 | public static String getDescByUserLevel(String userLevel){ 37 | for (UserLevelEnum value : values()) { 38 | if(Objects.equals(value.getUserLevel(),userLevel)){ 39 | return value.getDesc(); 40 | } 41 | } 42 | return ""; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/bean/entity/LoginUserInfo.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.bean.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import java.io.Serializable; 5 | import lombok.Data; 6 | import lombok.EqualsAndHashCode; 7 | import lombok.experimental.Accessors; 8 | 9 | /** 10 | *

11 | * 用户登录的id 12 | *

13 | * 14 | * @author lixin 15 | * @since 2023-05-11 16 | */ 17 | @Data 18 | @EqualsAndHashCode(callSuper = false) 19 | @Accessors(chain = true) 20 | @TableName("login_user_info") 21 | public class LoginUserInfo implements Serializable { 22 | 23 | private static final long serialVersionUID=1L; 24 | 25 | private Long id; 26 | 27 | /** 28 | * session_key 29 | */ 30 | private String sessionId; 31 | 32 | /** 33 | * 用户登录信息的json串 34 | */ 35 | private String userInfo; 36 | 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/bean/entity/PopupInfo.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.bean.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import lombok.Data; 5 | import lombok.EqualsAndHashCode; 6 | import lombok.experimental.Accessors; 7 | 8 | import javax.persistence.Column; 9 | import java.io.Serializable; 10 | import java.time.LocalDateTime; 11 | 12 | /** 13 | * 14 | * @author linyous 15 | * @since 2023-05-10 16 | */ 17 | @Data 18 | @EqualsAndHashCode(callSuper = false) 19 | @Accessors(chain = true) 20 | @TableName("popup_info") 21 | public class PopupInfo implements Serializable { 22 | 23 | private static final long serialVersionUID=1L; 24 | 25 | private Long id; 26 | 27 | /** 28 | * 标题 29 | */ 30 | @Column(name = "title") 31 | private String title; 32 | 33 | /** 34 | * 公告内容-富文本 35 | */ 36 | @Column(name = "content") 37 | private String content; 38 | 39 | /** 40 | * 创建时间 41 | */ 42 | @Column(name = "createTime") 43 | private LocalDateTime createTime; 44 | /** 45 | * 创建时间 46 | */ 47 | @Column(name = "popupLocation") 48 | private String popupLocation; 49 | 50 | /** 51 | * 创建时间 52 | */ 53 | @Column(name = "isShow") 54 | private Integer isShow; 55 | 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/bean/entity/PromptModel.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.bean.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import lombok.Data; 5 | import lombok.EqualsAndHashCode; 6 | import lombok.experimental.Accessors; 7 | 8 | import javax.persistence.Column; 9 | import java.io.Serializable; 10 | import java.util.Date; 11 | 12 | 13 | @Data 14 | @EqualsAndHashCode(callSuper = false) 15 | @Accessors(chain = true) 16 | @TableName("prompt_model") 17 | public class PromptModel implements Serializable { 18 | 19 | private static final long serialVersionUID=1L; 20 | 21 | private Long id; 22 | 23 | /** 24 | * 类型:效率工具、生活、娱乐、学习 25 | */ 26 | @Column(name = "type") 27 | private String type; 28 | 29 | /** 30 | * 标题 31 | */ 32 | @Column(name = "title") 33 | private String title; 34 | 35 | /** 36 | * 简介 37 | */ 38 | @Column(name = "introduce") 39 | private String introduce; 40 | 41 | /** 42 | * 示例 43 | */ 44 | @Column(name = "demo") 45 | private String demo; 46 | 47 | /** 48 | * 内容 49 | */ 50 | @Column(name = "content") 51 | private String content; 52 | 53 | /** 54 | * 0,无效;1,有效 55 | */ 56 | @Column(name = "state") 57 | private Integer state; 58 | 59 | /** 60 | * 排序值 61 | */ 62 | @Column(name = "sort") 63 | private Integer sort; 64 | 65 | /** 66 | * 创建时间 67 | */ 68 | @Column(name = "createTime") 69 | private Date createTime; 70 | 71 | /** 72 | * 更新时间 73 | */ 74 | @Column(name = "updateTime") 75 | private Date updateTime; 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/bean/entity/UserAccessRule.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.bean.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import lombok.Data; 5 | import lombok.EqualsAndHashCode; 6 | import lombok.experimental.Accessors; 7 | 8 | import java.io.Serializable; 9 | import java.time.LocalDateTime; 10 | 11 | /** 12 | *

13 | * 用户访问规则 14 | *

15 | * 16 | * @author lixin 17 | * @since 2023-05-10 18 | */ 19 | @Data 20 | @EqualsAndHashCode(callSuper = false) 21 | @Accessors(chain = true) 22 | @TableName("user_access_rule") 23 | public class UserAccessRule implements Serializable { 24 | 25 | private static final long serialVersionUID=1L; 26 | 27 | /** 28 | * 用户id 29 | */ 30 | private Long id; 31 | 32 | private Long userId; 33 | 34 | /** 35 | * 模型标识 36 | */ 37 | private String serviceType; 38 | 39 | /** 40 | * 使用次数, 如果 = -2 代表不限制次数 41 | */ 42 | private Integer useNumber; 43 | 44 | /** 45 | * 开始生效时间 46 | */ 47 | private LocalDateTime startEffectiveTime; 48 | 49 | /** 50 | * 有效结束时间 51 | */ 52 | private LocalDateTime endEffectiveTime; 53 | 54 | /** 55 | * 创建时间 56 | */ 57 | private LocalDateTime createTime; 58 | 59 | /** 60 | * 更新时间 61 | */ 62 | private LocalDateTime updateTime; 63 | 64 | private String updateUser; 65 | 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/bean/entity/UserInfo.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.bean.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import lombok.Data; 5 | import lombok.EqualsAndHashCode; 6 | import lombok.experimental.Accessors; 7 | 8 | import java.io.Serializable; 9 | import java.time.LocalDateTime; 10 | 11 | /** 12 | *

13 | * 14 | *

15 | * 16 | * @author lixin 17 | * @since 2023-05-07 18 | */ 19 | @Data 20 | @EqualsAndHashCode(callSuper = false) 21 | @Accessors(chain = true) 22 | @TableName("user_info") 23 | public class UserInfo implements Serializable { 24 | 25 | private static final long serialVersionUID=1L; 26 | 27 | private Long id; 28 | 29 | /** 30 | * 用户昵称 31 | */ 32 | private String username; 33 | 34 | /** 35 | * 微信授权的openId 36 | */ 37 | private String openId; 38 | 39 | /** 40 | * 用户头像 41 | */ 42 | private String avatar; 43 | 44 | /** 45 | * 电话信息 46 | */ 47 | private String phone; 48 | 49 | /** 50 | * 用户账号 51 | */ 52 | private String account; 53 | 54 | /** 55 | * 登录密码 56 | */ 57 | private String password; 58 | 59 | /** 60 | * 创建时间 61 | */ 62 | private LocalDateTime createTime; 63 | 64 | /** 65 | * 更新时间 66 | */ 67 | private LocalDateTime updateTime; 68 | 69 | /** 70 | * 账号状态 71 | * 0:状态 1:禁用 72 | */ 73 | private Integer status; 74 | 75 | /** 76 | * 用户等级 77 | */ 78 | private String userLevel; 79 | 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/bean/gpt/ChatReq.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.bean.gpt; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @Builder 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class ChatReq { 13 | private String prompt; 14 | 15 | private String conversationId; 16 | 17 | private String userId; 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/bean/gpt/ChoiceMessage.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.bean.gpt; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author huyd 7 | * @date 2023/3/6 9:47 PM 8 | */ 9 | @Data 10 | public class ChoiceMessage { 11 | 12 | private String role; 13 | private String content; 14 | 15 | public ChoiceMessage() { 16 | } 17 | 18 | public ChoiceMessage(String role, String content) { 19 | this.role = role; 20 | this.content = content; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/bean/gpt/GptTurbo.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.bean.gpt; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * @author huyd 9 | * @date 2023/3/6 9:42 PM 10 | */ 11 | @Data 12 | public class GptTurbo { 13 | private String model; 14 | private List messages; 15 | private String user; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/bean/gpt/ImageReq.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.bean.gpt; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.util.Map; 9 | 10 | /** 11 | * @author liuzilin 12 | * @date 2023/5/5 11:22 PM 13 | */ 14 | @Data 15 | @Builder 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | public class ImageReq { 19 | 20 | private String authToken; 21 | 22 | private String modelId; 23 | 24 | private String negativePrompt; 25 | 26 | private String prompt; 27 | 28 | private Integer modelIsPublic; 29 | 30 | private Integer width; 31 | 32 | private Integer height; 33 | 34 | private Integer imageNum; 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/bean/gpt/OpenReq.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.bean.gpt; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.util.Map; 9 | 10 | /** 11 | * @author huyd 12 | * @date 2023/5/5 11:22 PM 13 | */ 14 | @Data 15 | @Builder 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | public class OpenReq { 19 | 20 | private String method; 21 | 22 | private String url; 23 | 24 | private Map headers; 25 | 26 | private String body; 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/bean/gpt/drawImageRes.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.bean.gpt; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @author liuzilin 12 | * @date 2023/5/5 11:22 PM 13 | */ 14 | @Data 15 | @Builder 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | public class drawImageRes { 19 | 20 | private String authToken; 21 | 22 | private List taskIds; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/bean/req/CompletionReq.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.bean.req; 2 | 3 | import lombok.Data; 4 | 5 | import javax.validation.constraints.NotBlank; 6 | 7 | /** 8 | * @author huyd 9 | * @date 2023/5/14 12:16 AM 10 | */ 11 | @Data 12 | public class CompletionReq { 13 | 14 | /** 15 | * 提示模板id 16 | */ 17 | @NotBlank(message = "模板id不能为空") 18 | private String modelId; 19 | 20 | /** 21 | * 提交的内容 22 | */ 23 | @NotBlank(message = "内容不能为空") 24 | private String content; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/bean/req/PopupReq.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.bean.req; 2 | 3 | import lombok.Data; 4 | 5 | 6 | @Data 7 | public class PopupReq { 8 | 9 | /** 10 | * 登录密码 11 | */ 12 | private String source; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/bean/req/UserAccessRuleUpdateReq.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.bean.req; 2 | 3 | import lombok.Data; 4 | 5 | import javax.validation.constraints.NotNull; 6 | import java.time.LocalDateTime; 7 | 8 | @Data 9 | public class UserAccessRuleUpdateReq { 10 | 11 | @NotNull(message = "规则ID不能为空") 12 | private Long id; 13 | 14 | /** 15 | * 使用次数, 如果 = -2 代表不限制次数 16 | */ 17 | private Integer useNumber; 18 | 19 | /** 20 | * 本次更新的用户id 21 | */ 22 | @NotNull(message = "用户ID不能为空") 23 | private Long userId; 24 | 25 | /** 26 | * 开始生效时间 27 | */ 28 | private LocalDateTime startEffectiveTime; 29 | 30 | /** 31 | * 有效结束时间 32 | */ 33 | private LocalDateTime endEffectiveTime; 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/bean/req/UserInfoLoginReq.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.bean.req; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import javax.annotation.Nonnull; 9 | import javax.validation.constraints.NotNull; 10 | 11 | /** 12 | * 用户登录 13 | */ 14 | @AllArgsConstructor 15 | @NoArgsConstructor 16 | @Builder 17 | @Data 18 | public class UserInfoLoginReq { 19 | /** 20 | * 账号 21 | */ 22 | @NotNull(message = "账号不能为空") 23 | private String account; 24 | /** 25 | * 密码 26 | */ 27 | @NotNull(message = "密码不能为空") 28 | private String password; 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/bean/req/UserInfoRegisterReq.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.bean.req; 2 | 3 | import lombok.Data; 4 | 5 | import javax.validation.constraints.NotNull; 6 | 7 | /** 8 | * 用户登录 9 | */ 10 | @Data 11 | public class UserInfoRegisterReq { 12 | /** 13 | * 账号 14 | */ 15 | @NotNull(message = "账号不能为空") 16 | private String account; 17 | /** 18 | * 密码 19 | */ 20 | @NotNull(message = "密码不能为空") 21 | private String password; 22 | 23 | /** 24 | * 账号头像 25 | */ 26 | private String avatar; 27 | 28 | /** 29 | * 用户昵称 30 | */ 31 | private String username; 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/bean/req/UserQueryReq.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.bean.req; 2 | 3 | 4 | import lombok.Data; 5 | 6 | import java.time.LocalDateTime; 7 | 8 | /** 9 | * 用户查询请求实体 10 | */ 11 | @Data 12 | public class UserQueryReq { 13 | 14 | /** 15 | * 用户id 16 | */ 17 | private Long userId; 18 | 19 | /** 20 | * 状态 21 | */ 22 | private Integer status; 23 | 24 | /** 25 | * 账号 26 | */ 27 | private String account; 28 | 29 | /** 30 | * 搜索开始时间 31 | */ 32 | private LocalDateTime startTime; 33 | 34 | /** 35 | * 搜索结束时间 36 | */ 37 | private LocalDateTime endTime; 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/bean/req/UserUpdateReq.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.bean.req; 2 | 3 | import lombok.Data; 4 | 5 | import javax.validation.constraints.NotNull; 6 | 7 | @Data 8 | public class UserUpdateReq { 9 | 10 | /** 11 | * 用户id 12 | */ 13 | @NotNull(message = "用户ID不能为空") 14 | private Long userId; 15 | 16 | /** 17 | * 登录密码 18 | */ 19 | 20 | private String password; 21 | 22 | /** 23 | * 账号状态 24 | * 0:状态 1:禁用 25 | */ 26 | private Integer status; 27 | 28 | /** 29 | * 用户等级 30 | */ 31 | private String userLevel; 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/bean/util/UserAccessRuleUtil.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.bean.util; 2 | 3 | import com.blue.cat.bean.constants.ModelServiceTypeConstant; 4 | import com.blue.cat.bean.entity.UserAccessRule; 5 | import lombok.Getter; 6 | 7 | import java.time.LocalDateTime; 8 | 9 | /** 10 | * 用户chat-gpt的默认配置 11 | */ 12 | @Getter 13 | public class UserAccessRuleUtil{ 14 | 15 | /** 16 | * 模型3的默认配置 17 | * @param userId 18 | * @return 19 | */ 20 | public static UserAccessRule getAccessRuleGpt3(Long userId){ 21 | UserAccessRule userAccessRule = new UserAccessRule(); 22 | userAccessRule.setUserId(userId); 23 | userAccessRule.setServiceType(ModelServiceTypeConstant.CHAT_GPT_MODEL3); 24 | userAccessRule.setUseNumber(30); 25 | userAccessRule.setStartEffectiveTime(LocalDateTime.now()); 26 | userAccessRule.setEndEffectiveTime(LocalDateTime.now().plusDays(1)); 27 | userAccessRule.setCreateTime(LocalDateTime.now()); 28 | return userAccessRule; 29 | } 30 | 31 | /** 32 | * 模型4的默认配置 33 | * @param userId 34 | * @return 35 | */ 36 | public static UserAccessRule getAccessRuleGpt4(Long userId){ 37 | UserAccessRule userAccessRule = new UserAccessRule(); 38 | userAccessRule.setUserId(userId); 39 | userAccessRule.setServiceType(ModelServiceTypeConstant.CHAT_GPT_MODEL4); 40 | userAccessRule.setUseNumber(30); 41 | userAccessRule.setStartEffectiveTime(LocalDateTime.now()); 42 | userAccessRule.setEndEffectiveTime(LocalDateTime.now().plusDays(1)); 43 | userAccessRule.setCreateTime(LocalDateTime.now()); 44 | return userAccessRule; 45 | } 46 | 47 | public static void main(String[] args) { 48 | System.out.println(UserAccessRuleUtil.getAccessRuleGpt3(123L)); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/bean/util/UserInfoUtil.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.bean.util; 2 | 3 | import com.blue.cat.bean.entity.UserInfo; 4 | import com.blue.cat.bean.req.UserInfoRegisterReq; 5 | import com.blue.cat.bean.vo.CacheUserInfoVo; 6 | import org.apache.commons.lang3.StringUtils; 7 | 8 | import java.time.LocalDateTime; 9 | 10 | public class UserInfoUtil { 11 | 12 | 13 | /** 14 | * 注册类实体转化为实体bean 15 | * @param registerReq 16 | * @return 17 | */ 18 | public static UserInfo reqToEntity(UserInfoRegisterReq registerReq){ 19 | UserInfo userInfo = new UserInfo(); 20 | if(StringUtils.isNotBlank(registerReq.getAvatar())){ 21 | userInfo.setAvatar(registerReq.getAvatar()); 22 | } 23 | userInfo.setAccount(registerReq.getAccount()); 24 | userInfo.setPassword(registerReq.getPassword()); 25 | if(StringUtils.isNotEmpty(registerReq.getUsername())){ 26 | userInfo.setUsername(registerReq.getUsername()); 27 | } 28 | userInfo.setCreateTime(LocalDateTime.now()); 29 | return userInfo; 30 | } 31 | 32 | /** 33 | * 用户实体转化为vo 34 | * @param userInfo 35 | * @return 36 | */ 37 | public static CacheUserInfoVo entityToVo(UserInfo userInfo){ 38 | CacheUserInfoVo vo = new CacheUserInfoVo(); 39 | if(userInfo.getId()!=null){ 40 | vo.setId(userInfo.getId()); 41 | } 42 | if(StringUtils.isNotBlank(userInfo.getAccount())){ 43 | vo.setAccount(userInfo.getAccount()); 44 | } 45 | if(StringUtils.isNotBlank(userInfo.getAvatar())){ 46 | vo.setAvatar(userInfo.getAvatar()); 47 | } 48 | if(StringUtils.isNotBlank(userInfo.getUsername())){ 49 | vo.setUsername(userInfo.getUsername()); 50 | } 51 | if(userInfo.getStatus()!=null){ 52 | vo.setStatus(userInfo.getStatus()); 53 | } 54 | if(StringUtils.isNotBlank(userInfo.getUserLevel())){ 55 | vo.setUserLevel(userInfo.getUserLevel()); 56 | } 57 | return vo; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/bean/vo/CacheUserInfoVo.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.bean.vo; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import lombok.Data; 5 | 6 | import java.util.Map; 7 | 8 | @Data 9 | public class CacheUserInfoVo { 10 | 11 | @JsonFormat(shape = JsonFormat.Shape.STRING) 12 | private Long id; 13 | 14 | /** 15 | * 用户昵称 16 | */ 17 | private String username; 18 | 19 | /** 20 | * 用户头像 21 | */ 22 | private String avatar; 23 | 24 | /** 25 | * 用户账号 26 | */ 27 | private String account; 28 | 29 | 30 | /** 31 | * 账号状态 0正常 1:禁止登录 32 | */ 33 | private Integer status; 34 | 35 | 36 | /** 37 | * 用户等级 38 | */ 39 | private String userLevel; 40 | 41 | /** 42 | * 用户模型访问规则配置 43 | * key: 模型标识 44 | * value: 相应模型的规则 45 | */ 46 | private Map userLevelAccessVoMap; 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/bean/vo/PromptModelVo.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.bean.vo; 2 | 3 | import com.blue.cat.bean.entity.PromptModel; 4 | import lombok.Data; 5 | 6 | import java.util.List; 7 | 8 | @Data 9 | public class PromptModelVo { 10 | 11 | private String type; 12 | 13 | private List promptModels; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/bean/vo/UserLevelAccessVo.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.bean.vo; 2 | 3 | import lombok.Data; 4 | 5 | import java.time.LocalDateTime; 6 | import java.util.concurrent.atomic.AtomicInteger; 7 | 8 | @Data 9 | public class UserLevelAccessVo { 10 | 11 | /** 12 | * 主键id 13 | */ 14 | private Long id; 15 | 16 | /** 17 | * 访问次数 18 | */ 19 | private volatile AtomicInteger useNumber; 20 | 21 | /** 22 | * 模型标识 23 | */ 24 | private String serviceType; 25 | 26 | /** 27 | * 开始生效时间 28 | */ 29 | private volatile LocalDateTime startEffectiveTime; 30 | 31 | /** 32 | * 有效结束时间 33 | */ 34 | private volatile LocalDateTime endEffectiveTime; 35 | 36 | /** 37 | * 上一次访问时间 38 | */ 39 | private volatile LocalDateTime lastVisitDate; 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/config/WebConfig.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.config; 2 | 3 | import com.blue.cat.interceptor.ChatGptInterceptor3; 4 | import com.blue.cat.interceptor.LoginInterceptor; 5 | import com.blue.cat.interceptor.VisitLimitInterceptor; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.web.servlet.config.annotation.CorsRegistry; 9 | import org.springframework.web.servlet.config.annotation.InterceptorRegistry; 10 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 11 | 12 | import javax.annotation.PostConstruct; 13 | 14 | @Configuration 15 | public class WebConfig implements WebMvcConfigurer { 16 | 17 | @Autowired 18 | private LoginInterceptor loginInterceptor; 19 | 20 | @Autowired 21 | private ChatGptInterceptor3 chatGptInterceptor3; 22 | 23 | @Autowired 24 | private VisitLimitInterceptor visitLimitInterceptor; 25 | 26 | 27 | /** 28 | * 支持跨域 29 | * 30 | * @param registry 31 | */ 32 | @Override 33 | public void addCorsMappings(CorsRegistry registry) { 34 | registry.addMapping("/**") 35 | .allowCredentials(true) 36 | .allowedHeaders("*") 37 | .allowedOrigins("*") 38 | .allowedMethods("*"); 39 | } 40 | 41 | // 临时放开 回话限制 42 | @Override 43 | public void addInterceptors(InterceptorRegistry registry) { 44 | registry.addInterceptor(loginInterceptor).addPathPatterns("/**") 45 | .excludePathPatterns("/chat/createTask","/chat/drawTaskResult","/prompt/getPromptGroup","/popupInfo/getPopupInfo","/userInfo/login","/userInfo/register","/check/text") 46 | .order(-1); 47 | registry.addInterceptor(visitLimitInterceptor).addPathPatterns("/**") 48 | .order(1); 49 | registry.addInterceptor(chatGptInterceptor3).addPathPatterns("/chat/streamChatWithWeb/V3") 50 | .order(2); 51 | } 52 | } 53 | 54 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/controller/OpenAPIController.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.controller; 2 | 3 | import com.blue.cat.bean.annotation.VisitLimit; 4 | import com.blue.cat.bean.common.BaseCodeEnum; 5 | import com.blue.cat.bean.constants.CommonConstant; 6 | import com.blue.cat.bean.constants.LimitEnum; 7 | import com.blue.cat.bean.constants.ModelServiceTypeConstant; 8 | import com.blue.cat.bean.gpt.ChatReq; 9 | import com.blue.cat.bean.gpt.ImageReq; 10 | import com.blue.cat.bean.gpt.drawImageRes; 11 | import com.blue.cat.utils.HttpUtil; 12 | import com.blue.cat.utils.OpenGptUtil; 13 | import com.blue.cat.utils.SessionUser; 14 | import io.github.asleepyfish.util.OpenAiUtils; 15 | import lombok.extern.slf4j.Slf4j; 16 | import org.apache.commons.lang3.StringUtils; 17 | import org.springframework.beans.factory.annotation.Autowired; 18 | import org.springframework.web.bind.annotation.PostMapping; 19 | import org.springframework.web.bind.annotation.RequestBody; 20 | import org.springframework.web.bind.annotation.RequestMapping; 21 | import org.springframework.web.bind.annotation.RestController; 22 | 23 | import javax.servlet.http.HttpServletResponse; 24 | import java.io.IOException; 25 | 26 | /** 27 | * @author huyd 28 | * @date 2023/5/5 11:19 PM 29 | */ 30 | @Slf4j 31 | @RestController 32 | @RequestMapping("/chat") 33 | public class OpenAPIController { 34 | 35 | 36 | @VisitLimit(value = {LimitEnum.IP},scope = CommonConstant.NO_LOGIN_SCOPE) 37 | @PostMapping("/streamChatWithWeb/V2") 38 | public void streamChatWithWebV2(@RequestBody ChatReq chatReq, HttpServletResponse response) throws Exception{ 39 | try { 40 | response.setContentType("text/event-stream"); 41 | response.setCharacterEncoding("UTF-8"); 42 | response.setHeader("Cache-Control", "no-cache"); 43 | Long id = SessionUser.getUserId(); 44 | String userId = id == null ? "" : String.valueOf(id); 45 | String uid = StringUtils.isBlank(chatReq.getConversationId()) ? userId : userId + "_" + chatReq.getConversationId(); 46 | OpenAiUtils.createStreamChatCompletion(chatReq.getPrompt(), StringUtils.isBlank(uid) ? null : uid, response.getOutputStream()); 47 | }catch (Exception e){ 48 | log.error("streamChatWithWebV2 error",e); 49 | response.getOutputStream().write(BaseCodeEnum.SERVER_BUSY.getMsg().getBytes()); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/controller/PopupController.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.controller; 2 | 3 | 4 | import com.blue.cat.bean.req.PopupReq; 5 | import com.blue.cat.handler.PopupHandler; 6 | import com.blue.cat.utils.ResultVO; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.web.bind.annotation.*; 10 | 11 | 12 | 13 | /** 14 | * 15 | * @author linyous 16 | * @since 2023-05-10 17 | */ 18 | @Slf4j 19 | @RestController 20 | @RequestMapping("/popupInfo") 21 | public class PopupController { 22 | 23 | @Autowired 24 | private PopupHandler popupHandler; 25 | 26 | /** 27 | * 获取公告内容 28 | * @return 29 | */ 30 | @PostMapping("/getPopupInfo") 31 | public ResultVO getPopupInfo(@RequestBody PopupReq source){ 32 | try { 33 | return popupHandler.queryPopupInfo(source.getSource()); 34 | }catch (Exception e){ 35 | log.error("getPopupInfo error",e); 36 | } 37 | return ResultVO.fail("服务器繁忙!请联系作者!"); 38 | } 39 | 40 | } 41 | 42 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/controller/PromptModelController.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.controller; 2 | 3 | 4 | import com.blue.cat.bean.annotation.VisitLimit; 5 | import com.blue.cat.bean.constants.CommonConstant; 6 | import com.blue.cat.bean.constants.LimitEnum; 7 | import com.blue.cat.bean.constants.ModelServiceTypeConstant; 8 | import com.blue.cat.bean.entity.PromptModel; 9 | import com.blue.cat.bean.req.CompletionReq; 10 | import com.blue.cat.bean.vo.PromptModelVo; 11 | import com.blue.cat.handler.PromptModelHandler; 12 | import com.blue.cat.utils.HttpUtil; 13 | import com.blue.cat.utils.ResultVO; 14 | import com.blue.cat.utils.SessionUser; 15 | import io.github.asleepyfish.util.OpenAiUtils; 16 | import lombok.extern.slf4j.Slf4j; 17 | import org.apache.commons.lang3.StringUtils; 18 | import org.springframework.beans.factory.annotation.Autowired; 19 | import org.springframework.validation.annotation.Validated; 20 | import org.springframework.web.bind.annotation.*; 21 | 22 | import javax.servlet.http.HttpServletResponse; 23 | import java.io.IOException; 24 | import java.util.List; 25 | import java.util.UUID; 26 | 27 | 28 | @Slf4j 29 | @RestController 30 | @RequestMapping("/prompt") 31 | public class PromptModelController { 32 | 33 | @Autowired 34 | private PromptModelHandler promptHandler; 35 | 36 | @GetMapping("/getPromptGroup") 37 | public ResultVO> getPromptGroup() { 38 | try { 39 | List modelVos = promptHandler.getPromptGroup(); 40 | return ResultVO.success(modelVos); 41 | } catch (Exception e) { 42 | log.error("getPromptGroup error",e); 43 | } 44 | return ResultVO.fail("服务器繁忙!请联系作者!"); 45 | } 46 | 47 | @VisitLimit(value = {LimitEnum.IP}) 48 | @PostMapping("/completion") 49 | public void completion(@RequestBody @Validated CompletionReq completionReq, HttpServletResponse response) throws IOException { 50 | response.setContentType("text/event-stream"); 51 | response.setCharacterEncoding("UTF-8"); 52 | response.setHeader("Cache-Control", "no-cache"); 53 | 54 | StringBuilder builder = new StringBuilder(); 55 | PromptModel prompt = promptHandler.getPromptById(Long.parseLong(completionReq.getModelId())); 56 | if(prompt == null || StringUtils.isBlank(prompt.getContent())){ 57 | response.getOutputStream().write("模板已过期,请联系管理员".getBytes()); 58 | return; 59 | } 60 | Long id = SessionUser.getUserId(); 61 | String ip = HttpUtil.getIpAddress(); 62 | String browserName = HttpUtil.browserName(); 63 | builder.append(prompt.getContent()).append("\n"); 64 | builder.append(completionReq.getContent()); 65 | OpenAiUtils.createStreamChatCompletion(builder.toString(), UUID.randomUUID().toString(), response.getOutputStream()); 66 | } 67 | } 68 | 69 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/controller/UserAccessRuleController.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.controller; 2 | 3 | 4 | import com.blue.cat.bean.req.UserAccessRuleUpdateReq; 5 | import com.blue.cat.handler.access.UserAccessHandler; 6 | import com.blue.cat.utils.ResultVO; 7 | import com.blue.cat.utils.SessionUser; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.web.bind.annotation.PostMapping; 11 | import org.springframework.web.bind.annotation.RequestBody; 12 | import org.springframework.web.bind.annotation.RequestMapping; 13 | 14 | import org.springframework.stereotype.Controller; 15 | import org.springframework.web.bind.annotation.RestController; 16 | 17 | import javax.validation.Valid; 18 | 19 | /** 20 | *

21 | * 用户访问规则 前端控制器 22 | *

23 | * 24 | * @author lixin 25 | * @since 2023-05-10 26 | */ 27 | @Slf4j 28 | @RestController 29 | @RequestMapping("/userAccessRule") 30 | public class UserAccessRuleController { 31 | 32 | @Autowired 33 | private UserAccessHandler userAccessHandler; 34 | 35 | @PostMapping("/update") 36 | public ResultVO updateUserAccessRule(@RequestBody @Valid UserAccessRuleUpdateReq updateReq){ 37 | Boolean result = null; 38 | try { 39 | 40 | boolean admin = SessionUser.isAdmin(); 41 | if(!admin){ 42 | return ResultVO.fail("操作失败!当前登录账号不是管理账号!"); 43 | } 44 | result = userAccessHandler.updateUserAccess(updateReq); 45 | if(result){ 46 | return ResultVO.success("更新成功!"); 47 | } 48 | }catch (Exception e){ 49 | log.error("updateUserAccessRule updateReq={}",updateReq,e); 50 | }finally { 51 | log.info("updateUserAccessRule updateReq={},result={}",updateReq,result); 52 | } 53 | return ResultVO.fail("更新失败!出现未知错误!"); 54 | } 55 | 56 | } 57 | 58 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/controller/UserInfoController.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.controller; 2 | 3 | 4 | import com.alibaba.fastjson.JSONObject; 5 | import com.blue.cat.bean.annotation.VisitLimit; 6 | import com.blue.cat.bean.constants.LimitEnum; 7 | import com.blue.cat.bean.constants.UserLevelEnum; 8 | import com.blue.cat.bean.req.UserInfoLoginReq; 9 | import com.blue.cat.bean.req.UserInfoRegisterReq; 10 | import com.blue.cat.bean.req.UserUpdateReq; 11 | import com.blue.cat.bean.vo.CacheUserInfoVo; 12 | import com.blue.cat.handler.UserHandler; 13 | import com.blue.cat.utils.CacheUtil; 14 | import com.blue.cat.utils.RegexUtil; 15 | import com.blue.cat.utils.ResultVO; 16 | import com.blue.cat.utils.SessionUser; 17 | import lombok.extern.slf4j.Slf4j; 18 | import org.springframework.beans.BeanUtils; 19 | import org.springframework.beans.factory.annotation.Autowired; 20 | import org.springframework.web.bind.annotation.*; 21 | 22 | import javax.servlet.http.HttpServletResponse; 23 | import javax.validation.Valid; 24 | import java.util.Optional; 25 | 26 | /** 27 | *

28 | * 前端控制器 29 | *

30 | * 31 | * @author lixin 32 | * @since 2023-05-07 33 | */ 34 | @Slf4j 35 | @RestController 36 | @RequestMapping("/userInfo") 37 | public class UserInfoController { 38 | 39 | @Autowired 40 | private UserHandler userHandler; 41 | 42 | /** 43 | * 获取已登录的用户信息 44 | * @return 45 | */ 46 | @GetMapping("/info") 47 | public ResultVO getUserInfo(){ 48 | Optional userInfoVO = SessionUser.getUserInfoVO(); 49 | if(userInfoVO.isPresent()){ 50 | CacheUserInfoVo vo = new CacheUserInfoVo(); 51 | BeanUtils.copyProperties(userInfoVO.get(),vo); 52 | vo.setUserLevel(UserLevelEnum.getDescByUserLevel(vo.getUserLevel())); 53 | return ResultVO.success(vo); 54 | } 55 | return ResultVO.success(); 56 | } 57 | 58 | 59 | /** 60 | * 更新用户信息 61 | * @param updateReq 62 | * @return 63 | */ 64 | @PostMapping("/update") 65 | public ResultVO update(UserUpdateReq updateReq){ 66 | Boolean result=null; 67 | try { 68 | boolean admin = SessionUser.isAdmin(); 69 | if(!admin){ 70 | return ResultVO.fail("操作失败!当前登录账号不是管理账号!"); 71 | } 72 | 73 | CacheUserInfoVo cacheUser = userHandler.updateUserInfo(updateReq); 74 | if(cacheUser==null){ 75 | return ResultVO.fail("更新用户信息失败!"); 76 | } 77 | String loginUser = CacheUtil.getIfPresent(String.valueOf(cacheUser.getId())); 78 | if(loginUser!=null){ 79 | //此用户是登录中 更新登录缓存 80 | CacheUtil.put(String.valueOf(cacheUser.getId()), JSONObject.toJSONString(cacheUser)); 81 | } 82 | return ResultVO.success("更新成功"); 83 | }catch (Exception e){ 84 | log.error("update updateReq={}",updateReq,e); 85 | }finally { 86 | log.info("update updateReq={},result={}",updateReq,result); 87 | } 88 | return ResultVO.fail("服务器繁忙!请联系作者!"); 89 | } 90 | 91 | /** 92 | * 退出登录 93 | * @return 94 | */ 95 | @GetMapping("/loginOut") 96 | public ResultVO loginOut(){ 97 | try { 98 | Optional userInfoVO = SessionUser.getUserInfoVO(); 99 | if(userInfoVO.isPresent()){ 100 | CacheUtil.removeCache(String.valueOf(SessionUser.getUserId())); 101 | } 102 | }finally { 103 | //不管如何直接放回退出成功信息给前端 104 | return ResultVO.success(); 105 | } 106 | } 107 | 108 | 109 | /** 110 | * 登录 111 | * @param loginReq 112 | * @return 113 | */ 114 | @PostMapping("/login") 115 | public ResultVO login(@RequestBody @Valid UserInfoLoginReq loginReq, HttpServletResponse response){ 116 | 117 | try { 118 | String account = loginReq.getAccount(); 119 | if( RegexUtil.validateEmail(account) || RegexUtil.validatePhone(account)){ 120 | CacheUserInfoVo infoVo = userHandler.login(loginReq); 121 | if(infoVo!=null){ 122 | return ResultVO.success(infoVo); 123 | } 124 | return ResultVO.fail("账号或者密码错误!"); 125 | } 126 | return ResultVO.fail("账号格式不正确!"); 127 | }catch (Exception e){ 128 | log.error("login error loginReq={}",loginReq,e); 129 | }finally { 130 | log.info("login loginReq={}",loginReq); 131 | } 132 | return ResultVO.fail("服务器繁忙!请联系作者!"); 133 | } 134 | 135 | /** 136 | * 用户注册 137 | * @param registerReq 138 | * @return 139 | */ 140 | @VisitLimit(value = {LimitEnum.IP}) 141 | @PostMapping("/register") 142 | public ResultVO register(@RequestBody @Valid UserInfoRegisterReq registerReq){ 143 | log.info("register registerReq = {}",registerReq); 144 | try { 145 | String account = registerReq.getAccount(); 146 | if(RegexUtil.validateEmail(account)||RegexUtil.validatePhone(account)){ 147 | return userHandler.register(registerReq); 148 | } 149 | return ResultVO.fail("账号格式不正确!"); 150 | }catch (Exception e){ 151 | log.error("register error registerReq = {}",registerReq,e); 152 | }finally { 153 | log.info("register registerReq = {}",registerReq); 154 | } 155 | return ResultVO.fail("服务器繁忙!请联系作者!"); 156 | } 157 | } 158 | 159 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/handler/PopupHandler.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.handler; 2 | 3 | import com.blue.cat.bean.entity.PopupInfo; 4 | import com.blue.cat.service.impl.PopupInfoServiceImpl; 5 | import com.blue.cat.utils.ResultVO; 6 | import org.springframework.stereotype.Component; 7 | 8 | import javax.annotation.Resource; 9 | import java.util.Optional; 10 | 11 | @Component 12 | public class PopupHandler { 13 | 14 | @Resource 15 | private PopupInfoServiceImpl popupInfoService; 16 | 17 | /** 18 | * 获取公告内容 19 | * @return 20 | */ 21 | public ResultVO queryPopupInfo(String source){ 22 | Optional popupInfo = popupInfoService.queryPopupInfo(source); 23 | return popupInfo.map(ResultVO::success).orElseGet(() -> ResultVO.success(new PopupInfo())); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/handler/PromptModelHandler.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.handler; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.blue.cat.bean.entity.PromptModel; 5 | import com.blue.cat.bean.vo.PromptModelVo; 6 | import com.blue.cat.mapper.PromptModelMapper; 7 | import org.apache.commons.collections.CollectionUtils; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Component; 10 | 11 | import java.util.*; 12 | import java.util.stream.Collectors; 13 | 14 | @Component 15 | public class PromptModelHandler { 16 | 17 | @Autowired 18 | private PromptModelMapper promptMapper; 19 | 20 | public List getPromptGroup() { 21 | QueryWrapper wrapper = new QueryWrapper<>(); 22 | wrapper.eq("state", 1); 23 | wrapper.orderByDesc("sort"); 24 | List promptModels = promptMapper.selectList(wrapper); 25 | if (CollectionUtils.isEmpty(promptModels)) { 26 | return Collections.EMPTY_LIST; 27 | } 28 | // 使用Stream API进行分组 29 | Map> groupedPromptModels = promptModels.stream() 30 | .collect(Collectors.groupingBy(PromptModel::getType)); 31 | 32 | // 将分组后的结果转换为List 33 | List promptModelVos = groupedPromptModels.entrySet().stream() 34 | .map(entry -> { 35 | PromptModelVo vo = new PromptModelVo(); 36 | vo.setType(entry.getKey()); 37 | vo.setPromptModels(entry.getValue()); 38 | return vo; 39 | }) 40 | .collect(Collectors.toList()); 41 | 42 | // List voList = promptModels.stream().collect(Collectors.groupingBy(PromptModel::getType)).entrySet().stream() 43 | // .map(entry -> { 44 | // PromptModelVo vo = new PromptModelVo(); 45 | // vo.setType(entry.getKey()); 46 | // vo.setPromptModels(entry.getValue()); 47 | // return vo; 48 | // }).collect(Collectors.toList()); 49 | return promptModelVos; 50 | } 51 | 52 | public PromptModel getPromptById(Long modelId) { 53 | return promptMapper.selectById(modelId); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/handler/ThreadPoolManager.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.handler; 2 | 3 | import com.google.common.util.concurrent.ThreadFactoryBuilder; 4 | 5 | import java.util.concurrent.ArrayBlockingQueue; 6 | import java.util.concurrent.ThreadFactory; 7 | import java.util.concurrent.ThreadPoolExecutor; 8 | import java.util.concurrent.TimeUnit; 9 | 10 | public class ThreadPoolManager { 11 | 12 | private static ThreadFactory baseThreadFactory = new ThreadFactoryBuilder() 13 | .setNameFormat("promptRecord-pool-%d").build(); 14 | public static ThreadPoolExecutor promptRecordPool = new ThreadPoolExecutor(1, 2, 10, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(100),baseThreadFactory); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/handler/UserHandler.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.handler; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.blue.cat.bean.constants.CommonConstant; 5 | import com.blue.cat.bean.entity.UserInfo; 6 | import com.blue.cat.bean.req.UserInfoLoginReq; 7 | import com.blue.cat.bean.req.UserInfoRegisterReq; 8 | import com.blue.cat.bean.req.UserUpdateReq; 9 | import com.blue.cat.bean.util.UserAccessRuleUtil; 10 | import com.blue.cat.bean.util.UserInfoUtil; 11 | import com.blue.cat.bean.vo.CacheUserInfoVo; 12 | import com.blue.cat.bean.vo.UserLevelAccessVo; 13 | import com.blue.cat.handler.access.UserAccessHandler; 14 | import com.blue.cat.service.impl.UserAccessRuleServiceImpl; 15 | import com.blue.cat.service.impl.UserInfoServiceImpl; 16 | import com.blue.cat.utils.CacheUtil; 17 | import com.blue.cat.utils.ResultVO; 18 | import lombok.extern.slf4j.Slf4j; 19 | import org.apache.commons.collections.map.HashedMap; 20 | import org.springframework.beans.factory.annotation.Autowired; 21 | import org.springframework.stereotype.Component; 22 | import org.springframework.transaction.annotation.Transactional; 23 | 24 | import javax.annotation.Resource; 25 | import java.time.LocalDateTime; 26 | import java.util.Map; 27 | import java.util.Optional; 28 | 29 | @Slf4j 30 | @Component 31 | public class UserHandler { 32 | 33 | @Resource 34 | private UserInfoServiceImpl userInfoService; 35 | 36 | @Resource 37 | private UserAccessRuleServiceImpl ruleService; 38 | 39 | @Autowired 40 | private UserAccessHandler userAccessHandler; 41 | 42 | private UserInfo updateReqToEntity(UserUpdateReq updateReq){ 43 | UserInfo entity = new UserInfo(); 44 | entity.setId(updateReq.getUserId()); 45 | entity.setPassword(updateReq.getPassword()); 46 | entity.setUserLevel(updateReq.getUserLevel()); 47 | entity.setUpdateTime(LocalDateTime.now()); 48 | entity.setStatus(updateReq.getStatus()); 49 | return entity; 50 | } 51 | 52 | /** 53 | * 更新用户信息 54 | * @param updateReq 55 | * @return 56 | */ 57 | @Transactional 58 | public CacheUserInfoVo updateUserInfo(UserUpdateReq updateReq){ 59 | UserInfo entity = updateReqToEntity(updateReq); 60 | boolean result = userInfoService.updateById(entity); 61 | if(result){ 62 | UserInfo userInfo = userInfoService.getBaseMapper().selectById(entity.getId()); 63 | return buildCacheUserInfoVo(userInfo); 64 | } 65 | return null; 66 | } 67 | 68 | 69 | /** 70 | * 用户登录 71 | * @param loginReq 72 | * @return 73 | */ 74 | public CacheUserInfoVo login(UserInfoLoginReq loginReq){ 75 | Optional entity = userInfoService.queryUserByAccountAndPassword(loginReq.getAccount(), loginReq.getPassword()); 76 | if(entity.isPresent()){ 77 | UserInfo user = entity.get(); 78 | CacheUserInfoVo userVo = buildCacheUserInfoVo(user); 79 | CacheUtil.put(String.valueOf(user.getId()), JSONObject.toJSONString(userVo)); 80 | return userVo; 81 | } 82 | return null; 83 | } 84 | 85 | /** 86 | * 构建缓存实体 87 | * @param user 88 | */ 89 | private CacheUserInfoVo buildCacheUserInfoVo(UserInfo user){ 90 | CacheUserInfoVo cacheUserInfoVo = UserInfoUtil.entityToVo(user); 91 | Map accessVoMap = userAccessHandler.getUserAccessRule(user.getId()); 92 | cacheUserInfoVo.setUserLevelAccessVoMap(accessVoMap); 93 | return cacheUserInfoVo; 94 | } 95 | 96 | /** 97 | * 用户注册 98 | * @param registerReq 99 | * @return 100 | */ 101 | @Transactional 102 | public ResultVO register(UserInfoRegisterReq registerReq){ 103 | String account = registerReq.getAccount(); 104 | boolean existAccount = userInfoService.checkExistAccount(account); 105 | if(existAccount){ 106 | return ResultVO.fail("该账号已经被注册过了!"); 107 | } 108 | 109 | UserInfo userInfo = UserInfoUtil.reqToEntity(registerReq); 110 | int result = userInfoService.addUser(userInfo); 111 | if(result>0){ 112 | ruleService.addAccess(UserAccessRuleUtil.getAccessRuleGpt3(userInfo.getId())); 113 | login(UserInfoLoginReq.builder().account(registerReq.getAccount()).password(registerReq.getPassword()).build()); 114 | Map reqMap = new HashedMap(); 115 | reqMap.put(CommonConstant.TOKEN,String.valueOf(userInfo.getId())); 116 | return ResultVO.success(reqMap); 117 | } 118 | return ResultVO.fail("注册失败!服务器繁忙!"); 119 | } 120 | 121 | } 122 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/handler/access/UserAccessHandler.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.handler.access; 2 | 3 | import com.blue.cat.bean.entity.UserAccessRule; 4 | import com.blue.cat.bean.req.UserAccessRuleUpdateReq; 5 | import com.blue.cat.bean.vo.UserLevelAccessVo; 6 | import com.blue.cat.service.impl.UserAccessRuleServiceImpl; 7 | import com.blue.cat.utils.SessionUser; 8 | import org.springframework.stereotype.Component; 9 | 10 | import javax.annotation.Resource; 11 | import java.time.LocalDateTime; 12 | import java.util.Arrays; 13 | import java.util.List; 14 | import java.util.Map; 15 | import java.util.function.Function; 16 | import java.util.stream.Collectors; 17 | 18 | @Component 19 | public class UserAccessHandler { 20 | 21 | @Resource 22 | private UserAccessRuleServiceImpl ruleService; 23 | 24 | private UserAccessRule updateReqToEntity(UserAccessRuleUpdateReq updateReq){ 25 | UserAccessRule entity = new UserAccessRule(); 26 | entity.setId(updateReq.getId()); 27 | entity.setUseNumber(updateReq.getUseNumber()); 28 | entity.setStartEffectiveTime(updateReq.getStartEffectiveTime()); 29 | entity.setEndEffectiveTime(updateReq.getEndEffectiveTime()); 30 | return entity; 31 | } 32 | 33 | /** 34 | * 更新 35 | * @param updateReq 36 | * @return 37 | */ 38 | public boolean updateUserAccess(UserAccessRuleUpdateReq updateReq){ 39 | UserAccessRule entity = updateReqToEntity(updateReq); 40 | entity.setUpdateUser(SessionUser.getAccount()); 41 | entity.setUpdateTime(LocalDateTime.now()); 42 | return ruleService.updateBatchById(Arrays.asList(entity)); 43 | } 44 | 45 | 46 | /** 47 | * 获取用户的模型访问配置 48 | * @param userId 49 | * @return 50 | */ 51 | public Map getUserAccessRule(Long userId){ 52 | List userLevelAccessVos = ruleService.getAllAccessRuleByUserId(userId); 53 | return userLevelAccessVos.stream() 54 | .collect(Collectors.toMap(UserLevelAccessVo::getServiceType, Function.identity())); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/handler/access/UserLevelVisitFactory.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.handler.access; 2 | 3 | import com.blue.cat.bean.vo.CacheUserInfoVo; 4 | import com.blue.cat.bean.vo.UserLevelAccessVo; 5 | import com.blue.cat.utils.SessionUser; 6 | import com.blue.cat.handler.access.rule.UserServiceTypeRule; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.springframework.beans.BeansException; 9 | import org.springframework.context.ApplicationContext; 10 | import org.springframework.context.ApplicationContextAware; 11 | import org.springframework.stereotype.Component; 12 | 13 | import java.util.HashMap; 14 | import java.util.Map; 15 | import java.util.Optional; 16 | 17 | @Slf4j 18 | @Component 19 | public class UserLevelVisitFactory implements ApplicationContextAware { 20 | 21 | private static Map userServiceTypeRuleMap = new HashMap<>(); 22 | 23 | @Override 24 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 25 | userServiceTypeRuleMap = applicationContext.getBeansOfType(UserServiceTypeRule.class); 26 | } 27 | 28 | /** 29 | * 获取用户等级的访问处理类 30 | * @param userLevel 31 | * @return 32 | */ 33 | private static Optional getUserServiceTypeRule(String userLevel,String serviceType){ 34 | String key = userLevel + serviceType; 35 | UserServiceTypeRule userServiceTypeRule = userServiceTypeRuleMap.get(key); 36 | if(userServiceTypeRule==null){ 37 | return Optional.empty(); 38 | } 39 | return Optional.of(userServiceTypeRule); 40 | } 41 | 42 | /** 43 | * 判断当前用户是否可以访问 当前模型 44 | * @param userId 45 | * @param serviceType 46 | * @return 47 | */ 48 | public static boolean access(Long userId,String serviceType){ 49 | Optional userInfoVO = SessionUser.getUserInfoVO(); 50 | if(!userInfoVO.isPresent()){ 51 | log.info("access not login info userId={}",userId); 52 | return false; 53 | } 54 | // 获取 用户模型访问配置类 55 | UserLevelAccessVo userLevelAccessVo = getUserLevelAccessVo(userInfoVO.get(),serviceType); 56 | if(userLevelAccessVo==null){ 57 | log.info("access user not have LevelAccess userId={},serviceType={}",userId,serviceType); 58 | return false; 59 | } 60 | Optional userServiceTypeRule = getUserServiceTypeRule(userInfoVO.get().getUserLevel(),serviceType); 61 | return userServiceTypeRule.map(rule->rule.rule(userInfoVO.get().getUserLevel(),userLevelAccessVo)).orElse(false); 62 | } 63 | 64 | private static UserLevelAccessVo getUserLevelAccessVo(CacheUserInfoVo cacheUserInfoVO, String serviceType) { 65 | Map userLevelAccessVoMap = cacheUserInfoVO.getUserLevelAccessVoMap(); 66 | return userLevelAccessVoMap != null ? userLevelAccessVoMap.get(serviceType) : null; 67 | } 68 | 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/handler/access/rule/CommonUserChatGptUserServiceTypeRule3.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.handler.access.rule; 2 | 3 | import com.blue.cat.bean.constants.CommonConstant; 4 | import com.blue.cat.bean.constants.ModelServiceTypeConstant; 5 | import com.blue.cat.bean.constants.UserLevelConstant; 6 | import com.blue.cat.bean.vo.UserLevelAccessVo; 7 | import org.springframework.stereotype.Component; 8 | 9 | import java.time.LocalDateTime; 10 | 11 | 12 | /** 13 | * 普通用户 14 | * 调用chat-gpt3模型的 每天 10次 15 | */ 16 | @Component(UserLevelConstant.COMMON_USER + ModelServiceTypeConstant.CHAT_GPT_MODEL3) 17 | public class CommonUserChatGptUserServiceTypeRule3 implements UserServiceTypeRule { 18 | 19 | @Override 20 | public boolean rule(String userLevel, UserLevelAccessVo accessVo) { 21 | LocalDateTime lastVisitDate = accessVo.getLastVisitDate(); 22 | if(lastVisitDate==null){ 23 | return true; 24 | } 25 | LocalDateTime canVisitTime = lastVisitDate.plusSeconds(CommonConstant.CHAT_LIMIT_TIME); 26 | LocalDateTime now = LocalDateTime.now(); 27 | int diff = now.compareTo(canVisitTime); 28 | return diff>0; 29 | // int useNumber = accessVo.getUseNumber().get(); 30 | // if(useNumber>0){ 31 | // return true; 32 | // } 33 | // return false; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/handler/access/rule/CommonUserChatGptUserServiceTypeRule4.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.handler.access.rule; 2 | 3 | import com.blue.cat.bean.constants.ModelServiceTypeConstant; 4 | import com.blue.cat.bean.constants.UserLevelConstant; 5 | import com.blue.cat.bean.vo.UserLevelAccessVo; 6 | import org.springframework.stereotype.Component; 7 | 8 | 9 | /** 10 | * 普通用户 11 | * 调用chat-gpt3模型的 每天 10次 12 | */ 13 | @Component(UserLevelConstant.COMMON_USER + ModelServiceTypeConstant.CHAT_GPT_MODEL4) 14 | public class CommonUserChatGptUserServiceTypeRule4 implements UserServiceTypeRule { 15 | 16 | @Override 17 | public boolean rule(String userLevel, UserLevelAccessVo accessVo) { 18 | 19 | int useNumber = accessVo.getUseNumber().get(); 20 | if(useNumber>0){ 21 | return true; 22 | } 23 | return false; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/handler/access/rule/DurationUserChatGptUserServiceTypeRule3.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.handler.access.rule; 2 | 3 | import com.blue.cat.bean.constants.ModelServiceTypeConstant; 4 | import com.blue.cat.bean.constants.UserLevelConstant; 5 | import com.blue.cat.bean.vo.UserLevelAccessVo; 6 | import org.springframework.stereotype.Component; 7 | 8 | import java.time.LocalDateTime; 9 | 10 | 11 | /** 12 | * 时长用户 13 | * 调用chat-gpt3模型的 根据时长范围 原则上不限制次数 14 | */ 15 | @Component(UserLevelConstant.DURATION_USER + ModelServiceTypeConstant.CHAT_GPT_MODEL3) 16 | public class DurationUserChatGptUserServiceTypeRule3 implements UserServiceTypeRule { 17 | 18 | @Override 19 | public boolean rule(String userLevel, UserLevelAccessVo accessVo) { 20 | LocalDateTime nowDate = LocalDateTime.now(); 21 | LocalDateTime expirationDate = accessVo.getEndEffectiveTime(); 22 | int diff = expirationDate.compareTo(nowDate); 23 | return diff>=0; //过期时间是否大于当前时间 24 | } 25 | 26 | public static void main(String[] args) { 27 | System.out.println(LocalDateTime.now()); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/handler/access/rule/DurationUserChatGptUserServiceTypeRule4.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.handler.access.rule; 2 | 3 | import com.blue.cat.bean.constants.ModelServiceTypeConstant; 4 | import com.blue.cat.bean.constants.UserLevelConstant; 5 | import com.blue.cat.bean.vo.UserLevelAccessVo; 6 | import org.springframework.stereotype.Component; 7 | 8 | import java.time.LocalDateTime; 9 | 10 | 11 | /** 12 | * 时长用户 13 | * 调用chat-gpt3模型的 根据时长范围 原则上不限制次数 14 | */ 15 | @Component(UserLevelConstant.DURATION_USER + ModelServiceTypeConstant.CHAT_GPT_MODEL4) 16 | public class DurationUserChatGptUserServiceTypeRule4 implements UserServiceTypeRule { 17 | 18 | @Override 19 | public boolean rule(String userLevel, UserLevelAccessVo accessVo) { 20 | LocalDateTime nowDate = LocalDateTime.now(); 21 | LocalDateTime expirationDate = accessVo.getEndEffectiveTime(); 22 | int diff = expirationDate.compareTo(nowDate); 23 | return diff>=0; //过期时间是否大于当前时间 24 | } 25 | 26 | public static void main(String[] args) { 27 | System.out.println(LocalDateTime.now()); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/handler/access/rule/PermanentUserChatGptUserServiceTypeRule3.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.handler.access.rule; 2 | 3 | import com.blue.cat.bean.constants.ModelServiceTypeConstant; 4 | import com.blue.cat.bean.constants.UserLevelConstant; 5 | import com.blue.cat.bean.vo.UserLevelAccessVo; 6 | import org.springframework.stereotype.Component; 7 | 8 | 9 | /** 10 | * 尊贵的付费用户 11 | * 调用chat-gpt3模型的 随便玩 12 | */ 13 | @Component(UserLevelConstant.PERMANENT_USERS + ModelServiceTypeConstant.CHAT_GPT_MODEL3) 14 | public class PermanentUserChatGptUserServiceTypeRule3 implements UserServiceTypeRule { 15 | 16 | @Override 17 | public boolean rule(String userLevel, UserLevelAccessVo accessVo) { 18 | return true; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/handler/access/rule/PermanentUserChatGptUserServiceTypeRule4.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.handler.access.rule; 2 | 3 | import com.blue.cat.bean.constants.ModelServiceTypeConstant; 4 | import com.blue.cat.bean.constants.UserLevelConstant; 5 | import com.blue.cat.bean.vo.UserLevelAccessVo; 6 | import org.springframework.stereotype.Component; 7 | 8 | 9 | /** 10 | * 尊贵的付费用户 11 | * 调用chat-gpt3模型的 随便玩 12 | */ 13 | @Component(UserLevelConstant.PERMANENT_USERS + ModelServiceTypeConstant.CHAT_GPT_MODEL4) 14 | public class PermanentUserChatGptUserServiceTypeRule4 implements UserServiceTypeRule { 15 | 16 | @Override 17 | public boolean rule(String userLevel, UserLevelAccessVo accessVo) { 18 | return true; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/handler/access/rule/UserServiceTypeRule.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.handler.access.rule; 2 | 3 | 4 | /** 5 | * 模型的匹配的规则 6 | * 不同模型 针对不同的身份的用户 的限制规则是不一样的 7 | */ 8 | public interface UserServiceTypeRule { 9 | 10 | boolean rule(String userLevel,T accessVo); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/interceptor/ChatGptInterceptor3.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.interceptor; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.blue.cat.bean.common.BaseCodeEnum; 5 | import com.blue.cat.bean.constants.ModelServiceTypeConstant; 6 | import com.blue.cat.bean.vo.CacheUserInfoVo; 7 | import com.blue.cat.bean.vo.UserLevelAccessVo; 8 | import com.blue.cat.handler.access.UserLevelVisitFactory; 9 | import com.blue.cat.utils.CacheUtil; 10 | import com.blue.cat.utils.SessionUser; 11 | import lombok.extern.slf4j.Slf4j; 12 | import org.springframework.stereotype.Component; 13 | import org.springframework.web.servlet.HandlerInterceptor; 14 | import org.springframework.web.servlet.ModelAndView; 15 | 16 | import javax.servlet.http.HttpServletRequest; 17 | import javax.servlet.http.HttpServletResponse; 18 | import java.time.LocalDateTime; 19 | 20 | 21 | /** 22 | * chat gpt3模型的拦截类 23 | */ 24 | @Slf4j 25 | @Component 26 | public class ChatGptInterceptor3 implements HandlerInterceptor { 27 | 28 | @Override 29 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 30 | try { 31 | String method = request.getMethod(); 32 | if("OPTIONS".equals(method)){ 33 | return true; 34 | } 35 | CacheUserInfoVo cacheUserInfoVo = SessionUser.get(); 36 | if(cacheUserInfoVo!=null){ 37 | boolean access = UserLevelVisitFactory.access(cacheUserInfoVo.getId(), ModelServiceTypeConstant.CHAT_GPT_MODEL3); 38 | if(!access){ 39 | // responseResult(response, BaseCodeEnum.NO_VISITS_NUMBER.getMsg()); 40 | responseResult(response, BaseCodeEnum.VISIT_BUZY.getMsg()); 41 | return false; 42 | } 43 | } 44 | return true; 45 | }catch (Exception e){ 46 | log.error("ChatGptInterceptor3 error",e); 47 | responseResult(response, BaseCodeEnum.SERVER_BUSY.getMsg()); 48 | return false; 49 | } 50 | } 51 | 52 | private void responseResult(HttpServletResponse response, String msg) throws Exception { 53 | response.setCharacterEncoding("utf-8"); 54 | response.setContentType("application/json; charset=utf-8"); 55 | response.setHeader("Access-Control-Allow-Origin", "*"); 56 | response.getWriter().write(msg); 57 | } 58 | 59 | @Override 60 | public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { 61 | 62 | } 63 | 64 | /** 65 | * chat-gpt3正常回答完了,就会回调到这里 66 | * @param request 67 | * @param response 68 | * @param handler 69 | * @param ex 70 | * @throws Exception 71 | */ 72 | @Override 73 | public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { 74 | // todo 现在暂时放开次数限制 75 | CacheUserInfoVo cacheUserInfoVo = SessionUser.get(); 76 | if(cacheUserInfoVo==null){ 77 | return; 78 | } 79 | UserLevelAccessVo userLevelAccessVo = cacheUserInfoVo.getUserLevelAccessVoMap().get(ModelServiceTypeConstant.CHAT_GPT_MODEL3); 80 | if(userLevelAccessVo!=null){ 81 | // userLevelAccessVo.getUseNumber().addAndGet(-1); 82 | userLevelAccessVo.setLastVisitDate(LocalDateTime.now()); 83 | CacheUtil.put(String.valueOf(cacheUserInfoVo.getId()), JSONObject.toJSONString(cacheUserInfoVo)); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/interceptor/ChatGptInterceptor4.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.interceptor; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.blue.cat.bean.common.BaseCodeEnum; 5 | import com.blue.cat.bean.constants.ModelServiceTypeConstant; 6 | import com.blue.cat.bean.vo.CacheUserInfoVo; 7 | import com.blue.cat.bean.vo.UserLevelAccessVo; 8 | import com.blue.cat.handler.access.UserLevelVisitFactory; 9 | import com.blue.cat.utils.CacheUtil; 10 | import com.blue.cat.utils.SessionUser; 11 | import lombok.extern.slf4j.Slf4j; 12 | import org.springframework.stereotype.Component; 13 | import org.springframework.web.servlet.HandlerInterceptor; 14 | import org.springframework.web.servlet.ModelAndView; 15 | 16 | import javax.servlet.http.HttpServletRequest; 17 | import javax.servlet.http.HttpServletResponse; 18 | import java.time.LocalDateTime; 19 | 20 | 21 | /** 22 | * chat gpt3模型的拦截类 23 | */ 24 | @Slf4j 25 | @Component 26 | public class ChatGptInterceptor4 implements HandlerInterceptor { 27 | 28 | @Override 29 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 30 | try { 31 | String method = request.getMethod(); 32 | if("OPTIONS".equals(method)){ 33 | return true; 34 | } 35 | CacheUserInfoVo cacheUserInfoVo = SessionUser.get(); 36 | boolean access = UserLevelVisitFactory.access(cacheUserInfoVo.getId(), ModelServiceTypeConstant.CHAT_GPT_MODEL4); 37 | if(!access){ 38 | responseResult(response, BaseCodeEnum.NO_VISITS_NUMBER.getMsg()); 39 | return false; 40 | } 41 | return true; 42 | }catch (Exception e){ 43 | log.error("ChatGptInterceptor3 error",e); 44 | responseResult(response, BaseCodeEnum.SERVER_BUSY.getMsg()); 45 | return false; 46 | } 47 | } 48 | 49 | private void responseResult(HttpServletResponse response, String msg) throws Exception { 50 | response.setCharacterEncoding("utf-8"); 51 | response.setContentType("application/json; charset=utf-8"); 52 | response.setHeader("Access-Control-Allow-Origin", "*"); 53 | response.getWriter().write(msg); 54 | } 55 | 56 | @Override 57 | public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { 58 | 59 | } 60 | 61 | /** 62 | * chat-gpt3正常回答完了,就会回调到这里 63 | * @param request 64 | * @param response 65 | * @param handler 66 | * @param ex 67 | * @throws Exception 68 | */ 69 | @Override 70 | public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { 71 | CacheUserInfoVo cacheUserInfoVo = SessionUser.get(); 72 | if(cacheUserInfoVo == null){ 73 | return; 74 | } 75 | UserLevelAccessVo userLevelAccessVo = cacheUserInfoVo.getUserLevelAccessVoMap().get(ModelServiceTypeConstant.CHAT_GPT_MODEL3); 76 | if(userLevelAccessVo!=null){ 77 | userLevelAccessVo.getUseNumber().addAndGet(-1); 78 | userLevelAccessVo.setLastVisitDate(LocalDateTime.now()); 79 | CacheUtil.put(String.valueOf(cacheUserInfoVo.getId()), JSONObject.toJSONString(cacheUserInfoVo)); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/interceptor/LoginInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.interceptor; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.blue.cat.bean.common.BaseCodeEnum; 5 | import com.blue.cat.bean.constants.CommonConstant; 6 | import com.blue.cat.bean.vo.CacheUserInfoVo; 7 | import com.blue.cat.utils.CacheUtil; 8 | import com.blue.cat.utils.SessionUser; 9 | import lombok.extern.slf4j.Slf4j; 10 | import org.springframework.stereotype.Component; 11 | import org.springframework.web.servlet.HandlerInterceptor; 12 | import org.springframework.web.servlet.ModelAndView; 13 | 14 | import javax.servlet.http.HttpServletRequest; 15 | import javax.servlet.http.HttpServletResponse; 16 | 17 | @Slf4j 18 | @Component 19 | public class LoginInterceptor implements HandlerInterceptor { 20 | 21 | @Override 22 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 23 | try { 24 | //放行OPTIONS请求 25 | String method = request.getMethod(); 26 | if("OPTIONS".equals(method)){ 27 | return true; 28 | } 29 | CacheUserInfoVo userInfo = null; 30 | String sessionId= request.getHeader(CommonConstant.TOKEN); 31 | log.info("LoginInterceptor sessionId ={}", sessionId); 32 | if (sessionId != null) { 33 | String sessionUser = CacheUtil.getIfPresent(sessionId); 34 | log.info("LoginInterceptor sessionUser ={}", sessionUser); 35 | if (sessionUser != null) { 36 | CacheUtil.put(sessionId, sessionUser); 37 | userInfo = JSONObject.parseObject(sessionUser, CacheUserInfoVo.class); 38 | log.info("LoginInterceptor userDTO={}", JSONObject.toJSONString(userInfo)); 39 | } 40 | } 41 | // 重定向到登录 42 | // if (userInfo == null) { 43 | // responseResult(response, BaseCodeEnum.LOGIN_EXPIRE.getMsg()); 44 | // return false; 45 | // } 46 | if(userInfo!=null){ 47 | SessionUser.setSessionUserInfo(userInfo); 48 | } 49 | return true; 50 | }catch (Exception e){ 51 | log.error("LoginInterceptor error",e); 52 | responseResult(response, BaseCodeEnum.SERVER_BUSY.getMsg()); 53 | return false; 54 | } 55 | } 56 | 57 | private void responseResult(HttpServletResponse response, String msg) throws Exception { 58 | response.setCharacterEncoding("utf-8"); 59 | response.setContentType("application/json; charset=utf-8"); 60 | response.setHeader("Access-Control-Allow-Origin", "*"); 61 | response.getWriter().write(msg); 62 | } 63 | 64 | @Override 65 | public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { 66 | 67 | } 68 | 69 | @Override 70 | public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { 71 | //一次请求后需要删除线程变量,否则会造成内存泄漏 72 | SessionUser.remove(); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/interceptor/VisitLimitInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.interceptor; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.blue.cat.bean.annotation.VisitLimit; 5 | import com.blue.cat.bean.common.BaseCodeEnum; 6 | import com.blue.cat.bean.constants.CommonConstant; 7 | import com.blue.cat.bean.constants.LimitEnum; 8 | import com.blue.cat.bean.vo.CacheUserInfoVo; 9 | import com.blue.cat.utils.HttpUtil; 10 | import com.blue.cat.utils.IpCacheUtil; 11 | import com.blue.cat.utils.ResultVO; 12 | import com.blue.cat.utils.SessionUser; 13 | import lombok.extern.slf4j.Slf4j; 14 | import org.apache.commons.lang3.StringUtils; 15 | import org.springframework.stereotype.Component; 16 | import org.springframework.web.method.HandlerMethod; 17 | import org.springframework.web.servlet.HandlerInterceptor; 18 | import org.springframework.web.servlet.ModelAndView; 19 | 20 | import javax.servlet.http.HttpServletRequest; 21 | import javax.servlet.http.HttpServletResponse; 22 | import java.util.concurrent.atomic.AtomicInteger; 23 | 24 | @Slf4j 25 | @Component 26 | public class VisitLimitInterceptor implements HandlerInterceptor { 27 | 28 | @Override 29 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 30 | try { 31 | //放行OPTIONS请求 32 | String method = request.getMethod(); 33 | if("OPTIONS".equals(method)){ 34 | return true; 35 | } 36 | String requestURI = request.getRequestURI(); 37 | CacheUserInfoVo cacheUserInfoVo = SessionUser.get(); 38 | VisitLimit visitLimit = getVisitLimitAnnotation((HandlerMethod) handler); 39 | // 当用户没有登录的时候,进行ip限访问次数 40 | if(visitLimit!=null){ 41 | if(visitLimit.scope()==CommonConstant.NO_LOGIN_SCOPE){ 42 | //该注解只在不登录的情况下起作用,如果当前用户是登录状态,则不生效 43 | if(cacheUserInfoVo!=null){ 44 | return true; 45 | } 46 | } 47 | 48 | LimitEnum[] limitEnums = visitLimit.value(); 49 | for (LimitEnum limitEnum : limitEnums) { 50 | if(CommonConstant.LIMIT_IP.equals(limitEnum.getLimit())){ 51 | String ip = HttpUtil.getIpAddress(); 52 | if(StringUtils.isNoneEmpty(ip)){ 53 | String key = requestURI+":"+ip; 54 | AtomicInteger atomicInteger = initLimitCount(key); 55 | if(atomicInteger.get()>limitEnum.getNumber()){ 56 | responseResult(response, BaseCodeEnum.IP_LIMIT_MSG.getMsg()); 57 | return false; 58 | } 59 | } 60 | break; 61 | } 62 | } 63 | } 64 | return true; 65 | }catch (Exception e){ 66 | log.error("LoginInterceptor error",e); 67 | responseResult(response, BaseCodeEnum.SERVER_BUSY.getMsg()); 68 | return false; 69 | } 70 | } 71 | 72 | private void responseResult(HttpServletResponse response, String msg) throws Exception { 73 | response.setCharacterEncoding("utf-8"); 74 | response.setContentType("application/json; charset=utf-8"); 75 | response.setHeader("Access-Control-Allow-Origin", "*"); 76 | response.getWriter().write(JSONObject.toJSONString(ResultVO.fail(msg))); 77 | } 78 | 79 | @Override 80 | public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { 81 | 82 | } 83 | 84 | @Override 85 | public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { 86 | } 87 | 88 | private VisitLimit getVisitLimitAnnotation(HandlerMethod handler) { 89 | VisitLimit visitLimit = handler.getMethod().getAnnotation(VisitLimit.class); 90 | if (visitLimit == null) { 91 | visitLimit = handler.getBeanType().getAnnotation(VisitLimit.class); 92 | } 93 | return visitLimit; 94 | } 95 | 96 | 97 | private AtomicInteger initLimitCount(String ip){ 98 | AtomicInteger ipLimit = IpCacheUtil.getIfPresent(ip); 99 | if(ipLimit==null){ 100 | AtomicInteger integer = new AtomicInteger(1); 101 | IpCacheUtil.put(ip,integer); 102 | return integer; 103 | } 104 | ipLimit.getAndIncrement(); 105 | return ipLimit; 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/job/UserAccessJob.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.job; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.blue.cat.bean.entity.UserAccessRule; 5 | import com.blue.cat.bean.vo.CacheUserInfoVo; 6 | import com.blue.cat.bean.vo.UserLevelAccessVo; 7 | import com.blue.cat.service.impl.UserAccessRuleServiceImpl; 8 | import com.blue.cat.utils.CacheUtil; 9 | import lombok.extern.slf4j.Slf4j; 10 | import org.apache.commons.collections.CollectionUtils; 11 | import org.springframework.scheduling.annotation.Async; 12 | import org.springframework.scheduling.annotation.Scheduled; 13 | import org.springframework.stereotype.Component; 14 | 15 | import javax.annotation.Resource; 16 | import java.time.LocalDateTime; 17 | import java.util.*; 18 | import java.util.function.Function; 19 | import java.util.stream.Collectors; 20 | 21 | /** 22 | * 更新用户访问规则 23 | */ 24 | @Slf4j 25 | @Component 26 | public class UserAccessJob { 27 | 28 | @Resource 29 | private UserAccessRuleServiceImpl ruleService; 30 | 31 | /** 32 | * 定时更新缓存中的 访问规则类 33 | */ 34 | @Async 35 | @Scheduled(cron = "0 0/1 * * * ?") 36 | public void updateAccess(){ 37 | long startTime = System.currentTimeMillis(); 38 | log.info("updateAccess 开始执行"); 39 | Collection userInfoJsons = CacheUtil.getUserInfo(); 40 | 41 | List accessVos = new ArrayList<>(); 42 | for (String userInfoJson : userInfoJsons) { 43 | CacheUserInfoVo cacheUserInfoVo = JSONObject.parseObject(userInfoJson, CacheUserInfoVo.class); 44 | Map accessVoMap = cacheUserInfoVo.getUserLevelAccessVoMap(); 45 | if(accessVoMap!=null && accessVoMap.size()>0){ 46 | // todo 一次性更新所有登录用户的模型配置 这样到导致不需要更新的也会进行更新 待优化 等量大这里可能会有问题 47 | accessVos.addAll(accessVoMap.values()); 48 | } 49 | } 50 | if(CollectionUtils.isEmpty(accessVos)){ 51 | log.info("updateAccess not have update access rule"); 52 | return; 53 | } 54 | List needUpdateRuleList = getNeedUpdateRule(accessVos); 55 | boolean result = ruleService.batchUpdate(needUpdateRuleList); 56 | log.info("updateAccess 执行结束 result={} cost={}",result,System.currentTimeMillis()-startTime); 57 | } 58 | 59 | /** 60 | * 获取需要更新的规则类 61 | * @param accessVos 62 | * @return 63 | */ 64 | private List getNeedUpdateRule(List accessVos){ 65 | 66 | //需要更新的访问配置 67 | List needUpdateRuleList = new ArrayList<>(); 68 | 69 | Map accessVoMap = accessVos.stream() 70 | .collect(Collectors.toMap(UserLevelAccessVo::getId, Function.identity())); 71 | 72 | Set ids = accessVoMap.keySet(); 73 | List userAccessRules = ruleService.getByIds(ids); 74 | for (UserAccessRule entity : userAccessRules) { 75 | UserLevelAccessVo vo = accessVoMap.get(entity.getId()); 76 | // 如果实体和缓存的调用次数不一致 则是需要更新到数据库 77 | if(entity.getUseNumber() != vo.getUseNumber().get()){ 78 | entity.setUseNumber(vo.getUseNumber().get()); 79 | entity.setUpdateUser("system_auto"); 80 | entity.setUpdateTime(LocalDateTime.now()); 81 | needUpdateRuleList.add(entity); 82 | } 83 | } 84 | return needUpdateRuleList; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/job/UserLoginUserJob.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.job; 2 | 3 | import com.blue.cat.bean.entity.LoginUserInfo; 4 | import com.blue.cat.service.impl.LoginUserInfoServiceImpl; 5 | import com.blue.cat.utils.CacheUtil; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.apache.commons.collections.CollectionUtils; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.scheduling.annotation.Async; 10 | import org.springframework.scheduling.annotation.Scheduled; 11 | import org.springframework.stereotype.Component; 12 | 13 | import javax.annotation.PostConstruct; 14 | import javax.annotation.PreDestroy; 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | import java.util.Map; 18 | import java.util.concurrent.ConcurrentMap; 19 | 20 | @Slf4j 21 | @Component 22 | public class UserLoginUserJob { 23 | 24 | @Autowired 25 | private LoginUserInfoServiceImpl loginUserInfoService; 26 | 27 | @Async 28 | @Scheduled(cron = "0 0/10 * * * ?") 29 | public void buildLoginUserInfo(){ 30 | loginUserInfoService.buildLogInfoUser(); 31 | } 32 | 33 | /** 34 | * 重新将登录的账号重新加入缓存中 35 | */ 36 | @PostConstruct 37 | public void reCacheLoginUser(){ 38 | long startTime = System.currentTimeMillis(); 39 | List loginUserInfos = loginUserInfoService.getBaseMapper().getAll(); 40 | if(CollectionUtils.isNotEmpty(loginUserInfos)){ 41 | for (LoginUserInfo loginUserInfo : loginUserInfos) { 42 | CacheUtil.put(loginUserInfo.getSessionId(),loginUserInfo.getUserInfo()); 43 | } 44 | } 45 | log.info("reCacheLoginUser end cacheSize={} cost={}",loginUserInfos.size(),System.currentTimeMillis()-startTime); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/mapper/LoginUserInfoMapper.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.mapper; 2 | 3 | import com.blue.cat.bean.entity.LoginUserInfo; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | import org.apache.ibatis.annotations.Delete; 6 | import org.apache.ibatis.annotations.Mapper; 7 | import org.apache.ibatis.annotations.Select; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | *

13 | * 用户登录的id Mapper 接口 14 | *

15 | * 16 | * @author lixin 17 | * @since 2023-05-11 18 | */ 19 | @Mapper 20 | public interface LoginUserInfoMapper extends BaseMapper { 21 | 22 | @Delete("delete from login_user_info ") 23 | int deleteAll(); 24 | 25 | @Select("select * from login_user_info ") 26 | List getAll(); 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/mapper/PopupInfoMapper.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.blue.cat.bean.entity.PopupInfo; 5 | import org.apache.ibatis.annotations.Param; 6 | import org.apache.ibatis.annotations.Select; 7 | 8 | /** 9 | * 10 | * @author linyous 11 | * @since 2023-05-10 12 | */ 13 | public interface PopupInfoMapper extends BaseMapper { 14 | 15 | @Select("select id,title,content, createTime, popupLocation,isShow from popup_info where popupLocation=#{source} order by createTime desc limit 1") 16 | PopupInfo getPopup(@Param("source")String source); 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/mapper/PromptModelMapper.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.blue.cat.bean.entity.PromptModel; 5 | 6 | /** 7 | * 8 | * @author linyous 9 | * @since 2023-05-10 10 | */ 11 | public interface PromptModelMapper extends BaseMapper { 12 | 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/mapper/UserAccessRuleMapper.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.mapper; 2 | 3 | import com.blue.cat.bean.entity.UserAccessRule; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | import org.apache.ibatis.annotations.Mapper; 6 | import org.apache.ibatis.annotations.Param; 7 | import org.apache.ibatis.annotations.Select; 8 | 9 | import java.util.List; 10 | import java.util.Set; 11 | 12 | /** 13 | *

14 | * 用户访问规则 Mapper 接口 15 | *

16 | * 17 | * @author lixin 18 | * @since 2023-05-10 19 | */ 20 | @Mapper 21 | public interface UserAccessRuleMapper extends BaseMapper { 22 | 23 | @Select("select * from user_access_rule where user_id = #{userId}") 24 | List queryByUserId(@Param("userId") Long userId); 25 | 26 | @Select({ 27 | "" 34 | }) 35 | List queryByIds(@Param("ids") Set ids); 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/mapper/UserInfoMapper.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.blue.cat.bean.entity.UserInfo; 5 | import org.apache.ibatis.annotations.Param; 6 | import org.apache.ibatis.annotations.Select; 7 | 8 | /** 9 | *

10 | * Mapper 接口 11 | *

12 | * 13 | * @author lixin 14 | * @since 2023-05-07 15 | */ 16 | public interface UserInfoMapper extends BaseMapper { 17 | 18 | @Select("select id,username,account, avatar ,status ,user_level as userLevel from user_info where account=#{account} and password=#{password} and status = 0 limit 1") 19 | UserInfo queryAccountAndPassword(@Param("account") String account, @Param("password") String password); 20 | 21 | @Select("select id from user_info where account = #{account} limit 1") 22 | UserInfo queryByAccount(@Param("account")String account); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/service/ILoginUserInfoService.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.service; 2 | 3 | import com.blue.cat.bean.entity.LoginUserInfo; 4 | import com.baomidou.mybatisplus.extension.service.IService; 5 | 6 | /** 7 | *

8 | * 用户登录的id 服务类 9 | *

10 | * 11 | * @author lixin 12 | * @since 2023-05-11 13 | */ 14 | public interface ILoginUserInfoService extends IService { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/service/IPopupInfoService.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.blue.cat.bean.entity.PopupInfo; 5 | import com.blue.cat.bean.entity.UserInfo; 6 | 7 | /** 8 | * 9 | * @author linyous 10 | * @since 2023-05-10 11 | */ 12 | public interface IPopupInfoService extends IService { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/service/IUserAccessRuleService.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.service; 2 | 3 | import com.blue.cat.bean.entity.UserAccessRule; 4 | import com.baomidou.mybatisplus.extension.service.IService; 5 | 6 | /** 7 | *

8 | * 用户访问规则 服务类 9 | *

10 | * 11 | * @author lixin 12 | * @since 2023-05-10 13 | */ 14 | public interface IUserAccessRuleService extends IService { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/service/IUserInfoService.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.blue.cat.bean.entity.UserInfo; 5 | 6 | /** 7 | *

8 | * 服务类 9 | *

10 | * 11 | * @author lixin 12 | * @since 2023-05-07 13 | */ 14 | public interface IUserInfoService extends IService { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/service/impl/LoginUserInfoServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.service.impl; 2 | 3 | import com.blue.cat.bean.entity.LoginUserInfo; 4 | import com.blue.cat.mapper.LoginUserInfoMapper; 5 | import com.blue.cat.service.ILoginUserInfoService; 6 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 7 | import com.blue.cat.utils.CacheUtil; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.springframework.stereotype.Service; 10 | import org.springframework.transaction.annotation.Transactional; 11 | 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | import java.util.Map; 15 | import java.util.concurrent.ConcurrentMap; 16 | 17 | /** 18 | *

19 | * 用户登录的id 服务实现类 20 | *

21 | * 22 | * @author lixin 23 | * @since 2023-05-11 24 | */ 25 | @Slf4j 26 | @Service 27 | public class LoginUserInfoServiceImpl extends ServiceImpl implements ILoginUserInfoService { 28 | 29 | @Transactional 30 | public void buildLogInfoUser(){ 31 | long startTime = System.currentTimeMillis(); 32 | Boolean result = null; 33 | this.getBaseMapper().deleteAll(); 34 | ConcurrentMap cacheUserInfo = CacheUtil.getAllCacheUserInfo(); 35 | if(cacheUserInfo.size()>0){ 36 | List loginUserInfos = new ArrayList<>(); 37 | for (Map.Entry entry : cacheUserInfo.entrySet()) { 38 | LoginUserInfo loginUserInfo = new LoginUserInfo(); 39 | loginUserInfo.setSessionId(entry.getKey()); 40 | loginUserInfo.setUserInfo(entry.getValue()); 41 | loginUserInfos.add(loginUserInfo); 42 | } 43 | result = this.saveBatch(loginUserInfos); 44 | } 45 | log.info("buildLoginUserInfo end cacheSize={} ,result={} cost={}",cacheUserInfo.size(),result,System.currentTimeMillis()-startTime); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/service/impl/PopupInfoServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.blue.cat.bean.entity.PopupInfo; 5 | import com.blue.cat.mapper.PopupInfoMapper; 6 | import com.blue.cat.service.IPopupInfoService; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.springframework.stereotype.Service; 9 | 10 | import java.util.Optional; 11 | 12 | /** 13 | * 14 | * @author linyous 15 | * @since 2023-05-10 16 | */ 17 | @Slf4j 18 | @Service 19 | public class PopupInfoServiceImpl extends ServiceImpl implements IPopupInfoService { 20 | 21 | /** 22 | * 查询最新公告的内容 23 | * @return 24 | */ 25 | public Optional queryPopupInfo(String source) { 26 | PopupInfo popupInfo = super.baseMapper.getPopup(source); 27 | log.info("queryPopupInfo PopupInfo={}",popupInfo); 28 | if(popupInfo==null){ 29 | return Optional.empty(); 30 | } 31 | return Optional.of(popupInfo); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/service/impl/UserAccessRuleServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.service.impl; 2 | 3 | import com.blue.cat.bean.entity.UserAccessRule; 4 | import com.blue.cat.bean.vo.UserLevelAccessVo; 5 | import com.blue.cat.mapper.UserAccessRuleMapper; 6 | import com.blue.cat.service.IUserAccessRuleService; 7 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.apache.commons.collections.CollectionUtils; 10 | import org.springframework.stereotype.Service; 11 | 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | import java.util.Map; 15 | import java.util.Set; 16 | import java.util.concurrent.atomic.AtomicInteger; 17 | import java.util.function.Function; 18 | import java.util.stream.Collectors; 19 | 20 | /** 21 | *

22 | * 用户访问规则 服务实现类 23 | *

24 | * 25 | * @author lixin 26 | * @since 2023-05-10 27 | */ 28 | @Slf4j 29 | @Service 30 | public class UserAccessRuleServiceImpl extends ServiceImpl implements IUserAccessRuleService { 31 | 32 | 33 | public List getAllAccessRuleByUserId(Long userId){ 34 | 35 | List userAccessRules = super.baseMapper.queryByUserId(userId); 36 | return userAccessRules.stream().map(this::entityToVo).collect(Collectors.toList()); 37 | } 38 | 39 | /** 40 | * 默认添加默认访问规则配置 41 | * @return 42 | */ 43 | public int addAccess(UserAccessRule accessRule){ 44 | return super.baseMapper.insert(accessRule); 45 | } 46 | 47 | 48 | /** 49 | * 根据ids查询 50 | * @param ids 51 | * @return 52 | */ 53 | public List getByIds(Set ids){ 54 | return this.baseMapper.queryByIds(ids); 55 | } 56 | 57 | /** 58 | * 实体转化为vo 59 | * @param accessRule 60 | * @return 61 | */ 62 | private UserLevelAccessVo entityToVo(UserAccessRule accessRule){ 63 | UserLevelAccessVo vo = new UserLevelAccessVo(); 64 | vo.setId(accessRule.getId()); 65 | vo.setUseNumber(new AtomicInteger(accessRule.getUseNumber())); 66 | vo.setServiceType(accessRule.getServiceType()); 67 | vo.setStartEffectiveTime(accessRule.getStartEffectiveTime()); 68 | vo.setEndEffectiveTime(accessRule.getEndEffectiveTime()); 69 | return vo; 70 | } 71 | 72 | /** 73 | * 批量更新 用户访问配置 74 | * @param accessRules 75 | * @return 76 | */ 77 | public boolean batchUpdate(List accessRules){ 78 | if(CollectionUtils.isEmpty(accessRules)){ 79 | log.info("batchUpdate accessVos is empty"); 80 | return false; 81 | } 82 | return this.updateBatchById(accessRules); 83 | } 84 | 85 | 86 | 87 | /** 88 | * vo转实体 89 | * @param vo 90 | * @return 91 | */ 92 | private UserAccessRule voToEntity(UserLevelAccessVo vo){ 93 | UserAccessRule entity = new UserAccessRule(); 94 | entity.setId(vo.getId()); 95 | entity.setStartEffectiveTime(vo.getStartEffectiveTime()); 96 | entity.setEndEffectiveTime(vo.getEndEffectiveTime()); 97 | entity.setUpdateUser("system_auto"); 98 | entity.setUseNumber(vo.getUseNumber().get()); 99 | return entity; 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/service/impl/UserInfoServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.blue.cat.bean.entity.UserInfo; 5 | import com.blue.cat.mapper.UserInfoMapper; 6 | import com.blue.cat.service.IUserInfoService; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.springframework.stereotype.Service; 9 | 10 | import java.util.Optional; 11 | 12 | /** 13 | *

14 | * 服务实现类 15 | *

16 | * 17 | * @author lixin 18 | * @since 2023-05-07 19 | */ 20 | @Slf4j 21 | @Service 22 | public class UserInfoServiceImpl extends ServiceImpl implements IUserInfoService { 23 | 24 | /** 25 | * 根据账号和密码查询用户信息 26 | * @param account 27 | * @param password 28 | * @return 29 | */ 30 | public Optional queryUserByAccountAndPassword(String account, String password) { 31 | UserInfo userInfo = super.baseMapper.queryAccountAndPassword(account, password); 32 | log.info("login account={},userInfo={}",account,userInfo); 33 | if(userInfo==null){ 34 | return Optional.empty(); 35 | } 36 | return Optional.of(userInfo); 37 | } 38 | 39 | /** 40 | * 检测账号是否已经存在了 41 | * @param account 42 | * @return 43 | */ 44 | public boolean checkExistAccount(String account){ 45 | UserInfo userInfo = super.baseMapper.queryByAccount(account); 46 | log.info("checkExistAccount userInfo={}",userInfo); 47 | return userInfo!=null; 48 | } 49 | 50 | /** 51 | * 添加用户 52 | * @param userInfo 53 | * @return 54 | */ 55 | public int addUser(UserInfo userInfo){ 56 | return this.baseMapper.insert(userInfo); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/utils/CacheUtil.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.utils; 2 | 3 | import com.blue.cat.bean.constants.CommonConstant; 4 | import com.google.common.cache.Cache; 5 | import com.google.common.cache.CacheBuilder; 6 | 7 | import java.util.Collection; 8 | import java.util.concurrent.ConcurrentMap; 9 | import java.util.concurrent.TimeUnit; 10 | 11 | public class CacheUtil { 12 | 13 | private static Cache cache = CacheBuilder.newBuilder().expireAfterWrite(CommonConstant.CACHE_TIME_OUT, TimeUnit.SECONDS).build(); 14 | 15 | public static void put(String key, String value) { 16 | cache.put(key, value); 17 | } 18 | 19 | public static String getIfPresent(String key){ 20 | return cache.getIfPresent(key); 21 | } 22 | 23 | 24 | /** 25 | * 获取所有的登录的用户信息 26 | * @return 27 | */ 28 | public static ConcurrentMap getAllCacheUserInfo(){ 29 | return cache.asMap(); 30 | } 31 | 32 | /** 33 | * 获取所有的缓存的用户信息 34 | * @return 35 | */ 36 | public static Collection getUserInfo(){ 37 | return cache.asMap().values(); 38 | } 39 | 40 | 41 | public static void invalidate(String key){ 42 | cache.invalidate(key); 43 | } 44 | 45 | /** 46 | * 删除登录缓存 47 | * @param key 48 | */ 49 | public static void removeCache(String key){ 50 | cache.asMap().remove(key); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/utils/ChatGptUtils.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.utils; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.blue.cat.bean.gpt.ChoiceMessage; 5 | import com.blue.cat.bean.gpt.GptTurbo; 6 | import com.blue.cat.bean.gpt.OpenReq; 7 | import org.apache.commons.lang3.StringUtils; 8 | 9 | import java.util.ArrayList; 10 | import java.util.HashMap; 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | /** 15 | * @author huyd 16 | * @date 2023/5/5 11:42 PM 17 | */ 18 | public class ChatGptUtils { 19 | 20 | public static void main(String[] args) throws Exception{ 21 | String chat = chatWithSangiu(null, "西红柿炒鸡蛋怎么做"); 22 | System.out.println(chat); 23 | } 24 | 25 | public static String chatWithSangiu(String systemDesc, String message) throws Exception { 26 | //String req = "http://amd2.watilion.top:8088/api/open/req"; 27 | String req = "http://localhost:8088/api/open/req"; 28 | String method = "POST"; 29 | Map map = new HashMap<>(); 30 | map.put("Content-Type", "application/json"); 31 | map.put("Authorization", "Bearer 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"); 32 | 33 | String url = "https://api.openai.com/v1/chat/completions"; 34 | List list = new ArrayList<>(); 35 | if (StringUtils.isNotBlank(systemDesc)) { 36 | list.add(new ChoiceMessage("system", systemDesc)); 37 | } 38 | list.add(new ChoiceMessage("user", "user question: " + message)); 39 | 40 | GptTurbo gptTurbo = new GptTurbo(); 41 | gptTurbo.setModel("gpt-3.5-turbo"); 42 | gptTurbo.setMessages(list); 43 | String body = JSONObject.toJSONString(gptTurbo); 44 | 45 | OpenReq reqGpt = OpenReq.builder().method(method).url(url).body(body).headers(map).build(); 46 | 47 | Map headers = new HashMap<>(2); 48 | headers.put("Content-Type", "application/json"); 49 | headers.put("gpt-token", "OldSanGiuNBPlus666"); 50 | 51 | String result = OkHttpUtils.postReq(req, JSONObject.toJSONString(reqGpt), headers); 52 | if(StringUtils.isBlank(result)){ 53 | return null; 54 | } 55 | 56 | JSONObject jsonObject = JSONObject.parseObject(result); 57 | int code = jsonObject.getIntValue("code"); 58 | if(code != 0){ 59 | return null; 60 | } 61 | String msg = jsonObject.getString("msg"); 62 | JSONObject msgJb = JSONObject.parseObject(msg); 63 | Object choices = msgJb.getJSONArray("choices").get(0); 64 | Object messageContent = JSONObject.parseObject(choices.toString()).get("message"); 65 | return JSONObject.parseObject(messageContent.toString()).getString("content"); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/utils/HttpUtil.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.utils; 2 | 3 | import eu.bitwalker.useragentutils.Browser; 4 | import eu.bitwalker.useragentutils.OperatingSystem; 5 | import eu.bitwalker.useragentutils.UserAgent; 6 | 7 | import javax.servlet.http.HttpServletRequest; 8 | import java.io.BufferedReader; 9 | import java.io.IOException; 10 | import java.io.InputStreamReader; 11 | import java.util.regex.Matcher; 12 | import java.util.regex.Pattern; 13 | 14 | public class HttpUtil { 15 | 16 | public static String browserName(){ 17 | HttpServletRequest request = WebUtils.getRequest(); 18 | String userAgent = request.getHeader("User-Agent"); 19 | UserAgent ua = UserAgent.parseUserAgentString(userAgent); 20 | Browser browser = ua.getBrowser(); 21 | return browser.getName() + "-" + browser.getVersion(userAgent); 22 | } 23 | 24 | /** 25 | * 根据IP获取MAC地址 26 | * @return 27 | */ 28 | public static String getMacAddrByIp(String ip) { 29 | String macAddr = null; 30 | try { 31 | Process process = Runtime.getRuntime().exec("nbtstat -a " + ip); 32 | BufferedReader br = new BufferedReader( 33 | new InputStreamReader(process.getInputStream())); 34 | Pattern pattern = Pattern.compile("([A-F0-9]{2}-){5}[A-F0-9]{2}"); 35 | Matcher matcher; 36 | for (String strLine = br.readLine(); strLine != null; 37 | strLine = br.readLine()) { 38 | matcher = pattern.matcher(strLine); 39 | if (matcher.find()) { 40 | macAddr = matcher.group(); 41 | break; 42 | } 43 | } 44 | } catch (IOException e) { 45 | e.printStackTrace(); 46 | } 47 | return macAddr; 48 | } 49 | 50 | public static String osName(HttpServletRequest request){ 51 | String userAgent = request.getHeader("User-Agent"); 52 | UserAgent ua = UserAgent.parseUserAgentString(userAgent); 53 | OperatingSystem os = ua.getOperatingSystem(); 54 | return os.getName(); 55 | } 56 | 57 | /** 58 | * 用户的ip 59 | * @param request 60 | * @return 61 | */ 62 | public static String getIpAddress() { 63 | HttpServletRequest request = WebUtils.getRequest(); 64 | String ip = request.getHeader("X-Forwarded-For"); 65 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 66 | ip = request.getHeader("Proxy-Client-IP"); 67 | } 68 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 69 | ip = request.getHeader("WL-Proxy-Client-IP"); 70 | } 71 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 72 | ip = request.getHeader("HTTP_X_FORWARDED_FOR"); 73 | } 74 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 75 | ip = request.getHeader("HTTP_X_FORWARDED"); 76 | } 77 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 78 | ip = request.getHeader("HTTP_X_CLUSTER_CLIENT_IP"); 79 | } 80 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 81 | ip = request.getHeader("HTTP_CLIENT_IP"); 82 | } 83 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 84 | ip = request.getHeader("HTTP_FORWARDED_FOR"); 85 | } 86 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 87 | ip = request.getHeader("HTTP_FORWARDED"); 88 | } 89 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 90 | ip = request.getHeader("HTTP_VIA"); 91 | } 92 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 93 | ip = request.getHeader("REMOTE_ADDR"); 94 | } 95 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 96 | ip = request.getRemoteAddr(); 97 | } 98 | if (ip.contains(",")) { 99 | return ip.split(",")[0]; 100 | } else { 101 | return ip; 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/utils/IpCacheUtil.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.utils; 2 | 3 | import com.blue.cat.bean.constants.LimitEnum; 4 | import com.google.common.cache.Cache; 5 | import com.google.common.cache.CacheBuilder; 6 | 7 | import java.util.concurrent.TimeUnit; 8 | import java.util.concurrent.atomic.AtomicInteger; 9 | 10 | public class IpCacheUtil { 11 | 12 | private static Cache cache = CacheBuilder.newBuilder().expireAfterWrite(LimitEnum.IP.getTime(), TimeUnit.SECONDS).build(); 13 | 14 | public static void put(String key, AtomicInteger value) { 15 | cache.put(key, value); 16 | } 17 | 18 | public static AtomicInteger getIfPresent(String key){ 19 | return cache.getIfPresent(key); 20 | } 21 | 22 | /** 23 | * 删除缓存 24 | * @param key 25 | */ 26 | public static void removeCache(String key){ 27 | cache.asMap().remove(key); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/utils/MybatisPlusGeneratorUtil.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.utils; 2 | 3 | import com.baomidou.mybatisplus.annotation.DbType; 4 | import com.baomidou.mybatisplus.generator.AutoGenerator; 5 | import com.baomidou.mybatisplus.generator.config.DataSourceConfig; 6 | import com.baomidou.mybatisplus.generator.config.GlobalConfig; 7 | import com.baomidou.mybatisplus.generator.config.PackageConfig; 8 | import com.baomidou.mybatisplus.generator.config.StrategyConfig; 9 | import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy; 10 | 11 | /** 12 | * @author melo 13 | * @date 2020/5/31 14 | */ 15 | public class MybatisPlusGeneratorUtil { 16 | public static void main(String[] args) { 17 | String author = "lixin"; 18 | String database = "bluecat"; 19 | String tableName = "discern_record"; 20 | generateByTables(author, database,tableName); 21 | } 22 | 23 | private static void generateByTables(String author, String database, String... tableNames) { 24 | GlobalConfig config = new GlobalConfig(); 25 | String dbUrl = "jdbc:mysql://127.0.0.1:3306/" + database + "?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC"; 26 | config.setActiveRecord(false) 27 | .setAuthor(author) 28 | .setOutputDir(System.getProperty("user.dir") +"/src/main/java/") 29 | .setFileOverride(true) 30 | .setEnableCache(false) 31 | .setEntityName("%s") 32 | .setMapperName("%sMapper") 33 | // .setServiceName("%sService") 34 | //.setServiceImplName("%sServiceImpl") 35 | .setOpen(false); 36 | 37 | DataSourceConfig dataSourceConfig = new DataSourceConfig(); 38 | dataSourceConfig.setDbType(DbType.MYSQL) 39 | .setUrl(dbUrl) 40 | .setUsername("root") 41 | // .setPassword("root") 42 | .setDriverName("com.mysql.cj.jdbc.Driver"); 43 | 44 | StrategyConfig strategyConfig = new StrategyConfig(); 45 | strategyConfig 46 | .setCapitalMode(true) 47 | .setEntityLombokModel(true) 48 | .setNaming(NamingStrategy.underline_to_camel) 49 | // .setSuperMapperClass("") 50 | .setInclude(tableNames);//修改替换成你需要的表名,多个表名传数组 51 | 52 | new AutoGenerator().setGlobalConfig(config) 53 | .setDataSource(dataSourceConfig) 54 | .setStrategy(strategyConfig) 55 | .setPackageInfo( 56 | new PackageConfig() 57 | .setParent("com.blue.cat") 58 | .setEntity("bean.entity.DiscernRecord") 59 | .setMapper("mapper") 60 | //.setService("service") 61 | //.setServiceImpl("service.impl") 62 | //.setXml("mybatis.mappers") 63 | ).execute(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/utils/OkHttpUtils.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.utils; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import okhttp3.*; 5 | 6 | import java.util.Map; 7 | import java.util.concurrent.TimeUnit; 8 | 9 | /** 10 | * 请求微信接口获取相关Json信息 11 | */ 12 | @Slf4j 13 | public class OkHttpUtils { 14 | 15 | /** 16 | * OkHttpClient使用了连接池,应保持一个实例存在 17 | * 可以定制配置连接池 18 | */ 19 | private static final OkHttpClient okHttpClient = new OkHttpClient().newBuilder() 20 | .connectTimeout(180,TimeUnit.SECONDS) 21 | .readTimeout(180,TimeUnit.SECONDS) 22 | .writeTimeout(180,TimeUnit.SECONDS) 23 | .build(); 24 | 25 | public static String getReq(String url, Map headers) throws Exception { 26 | Request.Builder request = new Request.Builder().url(url); 27 | if(!headers.isEmpty()){ 28 | for (Map.Entry entry : headers.entrySet()) { 29 | request.addHeader(entry.getKey(), entry.getValue()); 30 | } 31 | } 32 | 33 | Response response = okHttpClient.newCall(request.build()).execute(); 34 | if (response.body() == null) { 35 | return null; 36 | } 37 | String result = response.body().string(); 38 | response.close(); 39 | return result; 40 | } 41 | 42 | public static String postReq(String url, String body, Map headers) throws Exception { 43 | Request.Builder req = new Request.Builder().url(url); 44 | if(!headers.isEmpty()){ 45 | for (Map.Entry entry : headers.entrySet()) { 46 | req.addHeader(entry.getKey(), entry.getValue()); 47 | } 48 | } 49 | 50 | if(body != null){ 51 | RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), body); 52 | req.post(requestBody); 53 | } 54 | 55 | Response response = okHttpClient.newCall(req.build()).execute(); 56 | String result = response.body() == null ? null : response.body().string(); 57 | response.close(); 58 | return result; 59 | } 60 | } 61 | 62 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/utils/OpenGptUtil.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.utils; 2 | 3 | /** 4 | * @author huyd 5 | * @date 2023/5/2 7:43 PM 6 | */ 7 | 8 | import com.alibaba.fastjson.JSONObject; 9 | import com.blue.cat.bean.gpt.ChatReq; 10 | import com.blue.cat.bean.gpt.ImageReq; 11 | import com.blue.cat.bean.gpt.drawImageRes; 12 | import com.google.common.collect.Lists; 13 | import com.theokanning.openai.completion.chat.ChatCompletionRequest; 14 | import com.theokanning.openai.completion.chat.ChatMessage; 15 | import lombok.extern.slf4j.Slf4j; 16 | 17 | import javax.servlet.http.HttpServletResponse; 18 | import java.io.*; 19 | import java.net.HttpURLConnection; 20 | import java.net.URL; 21 | import java.net.URLEncoder; 22 | import java.nio.charset.Charset; 23 | import java.nio.charset.StandardCharsets; 24 | 25 | @Slf4j 26 | public class OpenGptUtil { 27 | 28 | public static void main(String[] args) { 29 | } 30 | 31 | public static void stramChatV2() { 32 | try { 33 | ChatMessage message = new ChatMessage(); 34 | message.setContent("香辣嗦螺怎么做好吃"); 35 | message.setRole("system"); 36 | 37 | ChatCompletionRequest request = new ChatCompletionRequest(); 38 | request.setMessages(Lists.newArrayList(message)); 39 | request.setUser("123"); 40 | request.setModel("gpt-3.5-turbo"); 41 | 42 | // 指定接口地址 43 | String req = "http://localhost:8088/api/stream?request=%s"; 44 | URL url = new URL(String.format(req, URLEncoder.encode(JSONObject.toJSONString(request), "UTF-8"))); 45 | 46 | HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 47 | connection.setRequestMethod("GET"); 48 | connection.setRequestProperty("Accept", "text/event-stream"); 49 | 50 | InputStream inputStream = connection.getInputStream(); 51 | BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); 52 | 53 | String line; 54 | while ((line = reader.readLine()) != null) { 55 | System.out.println(line); 56 | } 57 | reader.close(); 58 | connection.disconnect(); 59 | } catch (Exception e) { 60 | e.printStackTrace(); 61 | } 62 | } 63 | 64 | public static void setBodyParameter(String str, HttpURLConnection conn) throws IOException { 65 | try (DataOutputStream out = new DataOutputStream(conn.getOutputStream())) { 66 | out.write(str.getBytes(StandardCharsets.UTF_8)); 67 | out.flush(); 68 | } catch (Exception e) { 69 | System.out.println("setBodyParameter error:" + e); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/utils/RegexUtil.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.utils; 2 | 3 | import java.util.regex.Matcher; 4 | import java.util.regex.Pattern; 5 | 6 | public class RegexUtil { 7 | 8 | 9 | /** 10 | * 验证手机号 11 | * @param hex 12 | * @return 13 | */ 14 | public static boolean validatePhone(final String hex) { 15 | Pattern pattern; 16 | Matcher matcher; 17 | String PHONE_PATTERN = "^\\d{11}$"; 18 | pattern = Pattern.compile(PHONE_PATTERN); 19 | matcher = pattern.matcher(hex); 20 | return matcher.matches(); 21 | } 22 | 23 | 24 | 25 | /** 26 | * 验证手机号 27 | * @param hex 28 | * @return 29 | */ 30 | public static boolean validateEmail(final String hex) { 31 | Pattern pattern; 32 | Matcher matcher; 33 | String EMAIL_PATTERN = 34 | "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@" 35 | + "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$"; 36 | pattern = Pattern.compile(EMAIL_PATTERN); 37 | matcher = pattern.matcher(hex); 38 | return matcher.matches(); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/utils/ResultVO.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.utils; 2 | 3 | import com.blue.cat.bean.common.BaseCode; 4 | import com.blue.cat.bean.common.BaseCodeEnum; 5 | 6 | /** 7 | * web接口统一返回结果 8 | */ 9 | public class ResultVO { 10 | 11 | /** 12 | * 响应状态码 13 | */ 14 | private int code; 15 | 16 | /** 17 | * 响应消息 18 | */ 19 | private String msg; 20 | 21 | /** 22 | * 响应数据 23 | */ 24 | private T data; 25 | 26 | public static ResultVO build(BaseCode baseCode, T data) { 27 | return new ResultVO<>(baseCode, data); 28 | } 29 | 30 | public static ResultVO build(BaseCode baseCode) { 31 | return new ResultVO<>(baseCode); 32 | } 33 | 34 | public static ResultVO success() { 35 | return new ResultVO<>(BaseCodeEnum.SUCCESS); 36 | } 37 | 38 | public static ResultVO success(String msg) { 39 | return new ResultVO<>(BaseCodeEnum.SUCCESS.getCode(), msg); 40 | } 41 | 42 | public static ResultVO success(T data) { 43 | return new ResultVO<>(BaseCodeEnum.SUCCESS, data); 44 | } 45 | 46 | public static ResultVO error(BaseCode baseCode) { 47 | return new ResultVO<>(baseCode.getCode(), baseCode.getMsg()); 48 | } 49 | 50 | public static ResultVO error(int code, String msg) { 51 | return new ResultVO<>(code, msg); 52 | } 53 | 54 | public static ResultVO fail(int code, String msg) { 55 | return new ResultVO<>(code, msg); 56 | } 57 | 58 | public static ResultVO fail(BaseCode baseCode) { 59 | return new ResultVO<>(baseCode.getCode(), baseCode.getMsg()); 60 | } 61 | 62 | public static ResultVO fail(String msg) { 63 | return new ResultVO<>(BaseCodeEnum.FAIL.getCode(), msg); 64 | } 65 | 66 | public ResultVO() { 67 | } 68 | 69 | public ResultVO(int code, String msg) { 70 | this.code = code; 71 | this.msg = msg; 72 | } 73 | 74 | public ResultVO(BaseCode baseCode) { 75 | this.code = baseCode.getCode(); 76 | this.msg = baseCode.getMsg(); 77 | } 78 | 79 | public ResultVO(BaseCode baseCode, T data) { 80 | this.code = baseCode.getCode(); 81 | this.msg = baseCode.getMsg(); 82 | this.data = data; 83 | } 84 | 85 | public int getCode() { 86 | return code; 87 | } 88 | 89 | public void setCode(int code) { 90 | this.code = code; 91 | } 92 | 93 | public String getMsg() { 94 | return msg; 95 | } 96 | 97 | public void setMsg(String msg) { 98 | this.msg = msg; 99 | } 100 | 101 | public T getData() { 102 | return data; 103 | } 104 | 105 | public void setData(T data) { 106 | this.data = data; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/utils/SessionUser.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.utils; 2 | 3 | import com.blue.cat.bean.vo.CacheUserInfoVo; 4 | import org.apache.commons.lang3.StringUtils; 5 | 6 | import java.util.HashSet; 7 | import java.util.Optional; 8 | import java.util.Set; 9 | 10 | public class SessionUser { 11 | 12 | private static ThreadLocal sessionUser = new ThreadLocal<>(); 13 | 14 | public static void setSessionUserInfo(CacheUserInfoVo adminUserVO) { 15 | sessionUser.set(adminUserVO); 16 | } 17 | 18 | public static CacheUserInfoVo get(){return sessionUser.get();} 19 | 20 | public static Long getUserId(){ 21 | CacheUserInfoVo cacheUserInfoVo = sessionUser.get(); 22 | if(cacheUserInfoVo == null){ 23 | return null; 24 | } 25 | return cacheUserInfoVo.getId(); 26 | } 27 | 28 | /** 29 | * 用户登录的信息 30 | * @return 31 | */ 32 | public static Optional getUserInfoVO(){ 33 | CacheUserInfoVo cacheUserInfoVo = sessionUser.get(); 34 | if(cacheUserInfoVo == null){ 35 | return Optional.empty(); 36 | } 37 | return Optional.of(cacheUserInfoVo); 38 | } 39 | 40 | public static Optional getUserName(){ 41 | CacheUserInfoVo cacheUserInfoVo = sessionUser.get(); 42 | if(cacheUserInfoVo == null){ 43 | return Optional.empty(); 44 | } 45 | return Optional.of(cacheUserInfoVo.getUsername()); 46 | } 47 | 48 | public static String getAccount(){ 49 | CacheUserInfoVo cacheUserInfoVo = sessionUser.get(); 50 | if(cacheUserInfoVo == null){ 51 | return null; 52 | } 53 | return cacheUserInfoVo.getAccount(); 54 | } 55 | 56 | public static void remove(){ 57 | sessionUser.remove(); 58 | } 59 | 60 | 61 | /** 62 | * 管理账号集合,目前直接写死到项目中 63 | */ 64 | private static Set adminSet = new HashSet<>(); 65 | 66 | static { 67 | adminSet.add("xxxxx");// laoban 68 | } 69 | 70 | /** 71 | * 判断是否是管理账号 72 | * @param account 73 | * @return 74 | */ 75 | public static boolean isAdmin(String account){ 76 | if(StringUtils.isEmpty(account)){ 77 | return false; 78 | } 79 | return adminSet.contains(account); 80 | } 81 | 82 | public static boolean isAdmin(){ 83 | String account = getAccount(); 84 | return isAdmin(account); 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/com/blue/cat/utils/WebUtils.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.utils; 2 | 3 | import org.springframework.web.context.request.RequestAttributes; 4 | import org.springframework.web.context.request.RequestContextHolder; 5 | import org.springframework.web.context.request.ServletRequestAttributes; 6 | 7 | import javax.servlet.http.HttpServletRequest; 8 | import javax.servlet.http.HttpServletResponse; 9 | import javax.servlet.http.HttpSession; 10 | 11 | /** 12 | * @author Ths Sun 13 | * @create 2020/7/30. 14 | */ 15 | public class WebUtils { 16 | 17 | /** 18 | * 获取request 19 | */ 20 | public static HttpServletRequest getRequest() 21 | { 22 | return getRequestAttributes().getRequest(); 23 | } 24 | 25 | /** 26 | * 获取response 27 | */ 28 | public static HttpServletResponse getResponse() 29 | { 30 | return getRequestAttributes().getResponse(); 31 | } 32 | 33 | /** 34 | * 获取session 35 | */ 36 | public static HttpSession getSession() 37 | { 38 | return getRequest().getSession(); 39 | } 40 | 41 | public static ServletRequestAttributes getRequestAttributes(){ 42 | RequestAttributes attributes = RequestContextHolder.getRequestAttributes(); 43 | return (ServletRequestAttributes) attributes; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/resources/application-dev.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8080 3 | servlet: 4 | context-path: /api 5 | 6 | # 填写自己的open-api key 7 | chatgpt: 8 | token: 9 | session-expiration-time: 2 10 | 11 | spring: 12 | http: 13 | encoding: 14 | charset: UTF-8 15 | 16 | servlet: 17 | multipart: 18 | enabled: true 19 | max-file-size: 500MB 20 | max-request-size: 500MB 21 | 22 | datasource: 23 | driver-class-name: com.mysql.cj.jdbc.Driver 24 | url: jdbc:mysql://127.0.0.1:3306/bluecat?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai 25 | username: root 26 | # password: root 27 | 28 | 29 | mybatis-plus: 30 | configuration: 31 | map-underscore-to-camel-case: true 32 | global-config: 33 | db-config: 34 | column-underline: true 35 | -------------------------------------------------------------------------------- /src/main/resources/application-prod.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8080 3 | servlet: 4 | context-path: /api 5 | 6 | #填写自己的open api的token 7 | chatgpt: 8 | token: 9 | session-expiration-time: 2 10 | 11 | spring: 12 | http: 13 | encoding: 14 | charset: UTF-8 15 | 16 | servlet: 17 | multipart: 18 | enabled: true 19 | max-file-size: 500MB 20 | max-request-size: 500MB 21 | 22 | datasource: 23 | driver-class-name: com.mysql.cj.jdbc.Driver 24 | url: jdbc:mysql://127.0.0.1:3306/bluecat?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai 25 | username: root 26 | password: root 27 | 28 | mybatis-plus: 29 | configuration: 30 | map-underscore-to-camel-case: true 31 | global-config: 32 | db-config: 33 | column-underline: true 34 | -------------------------------------------------------------------------------- /src/test/java/com/blue/cat/BlueCatApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat; 2 | 3 | import io.github.asleepyfish.util.OpenAiUtils; 4 | import org.junit.jupiter.api.Test; 5 | 6 | 7 | class BlueCatApplicationTests extends RunnerTest { 8 | 9 | @Test 10 | public void testGenerateImg() { 11 | OpenAiUtils.createImage("英短").forEach(System.out::println); 12 | } 13 | 14 | @Test 15 | public void createStreamChatCompletion() { 16 | System.out.println("tets"); 17 | } 18 | 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/test/java/com/blue/cat/RunnerTest.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat; 2 | 3 | import org.springframework.boot.test.context.SpringBootTest; 4 | import org.springframework.test.context.ActiveProfiles; 5 | 6 | 7 | /** 8 | * 所有测试类都需要继承此类 9 | */ 10 | @ActiveProfiles(value = "dev") 11 | @SpringBootTest 12 | public class RunnerTest { 13 | 14 | 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/test/java/com/blue/cat/access/AccessTest.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.access; 2 | 3 | import com.blue.cat.RunnerTest; 4 | import com.blue.cat.bean.entity.UserAccessRule; 5 | import com.blue.cat.bean.util.UserAccessRuleUtil; 6 | import com.blue.cat.mapper.UserAccessRuleMapper; 7 | import com.blue.cat.service.impl.UserAccessRuleServiceImpl; 8 | import org.junit.jupiter.api.Test; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | 11 | import javax.annotation.Resource; 12 | import java.util.Arrays; 13 | import java.util.HashSet; 14 | import java.util.List; 15 | 16 | public class AccessTest extends RunnerTest { 17 | 18 | @Autowired 19 | private UserAccessRuleServiceImpl accessRuleService; 20 | 21 | @Resource 22 | private UserAccessRuleMapper ruleMapper; 23 | 24 | @Test 25 | public void addAccess(){ 26 | int i = accessRuleService.addAccess(UserAccessRuleUtil.getAccessRuleGpt3(1234L)); 27 | System.out.println(i); 28 | } 29 | 30 | 31 | @Test 32 | public void queryIds(){ 33 | List userAccessRules = ruleMapper.queryByIds(new HashSet<>(Arrays.asList(1656217949066317826L))); 34 | System.out.println(userAccessRules); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/test/java/com/blue/cat/user/UserInfoTest.java: -------------------------------------------------------------------------------- 1 | package com.blue.cat.user; 2 | 3 | 4 | import com.blue.cat.RunnerTest; 5 | import com.blue.cat.bean.req.UserInfoLoginReq; 6 | import com.blue.cat.bean.req.UserInfoRegisterReq; 7 | import com.blue.cat.controller.UserInfoController; 8 | import com.blue.cat.mapper.UserInfoMapper; 9 | import com.blue.cat.utils.ResultVO; 10 | import org.junit.jupiter.api.Test; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | 13 | public class UserInfoTest extends RunnerTest { 14 | 15 | @Autowired 16 | UserInfoMapper userInfoMapper; 17 | 18 | @Autowired 19 | UserInfoController userInfoController; 20 | 21 | @Test 22 | public void login() { 23 | UserInfoLoginReq loginReq = new UserInfoLoginReq(); 24 | loginReq.setAccount("admin4"); 25 | loginReq.setPassword("admin"); 26 | ResultVO login = userInfoController.login(loginReq,null); 27 | assert login !=null; 28 | } 29 | 30 | @Test 31 | public void register(){ 32 | UserInfoRegisterReq registerReq = new UserInfoRegisterReq(); 33 | registerReq.setAccount("admin"); 34 | registerReq.setPassword("admin"); 35 | registerReq.setUsername("ai助手-test"); 36 | ResultVO register = userInfoController.register(registerReq); 37 | assert register!=null; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /执行SQL/blueCat.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Navicat MySQL Data Transfer 3 | 4 | Source Server : localhost_3306 5 | Source Server Version : 50712 6 | Source Host : localhost:3306 7 | Source Database : driver 8 | 9 | Target Server Type : MYSQL 10 | Target Server Version : 50712 11 | File Encoding : 65001 12 | 13 | Date: 2023-06-02 08:26:13 14 | */ 15 | 16 | SET FOREIGN_KEY_CHECKS=0; 17 | 18 | -- ---------------------------- 19 | -- Table structure for `login_user_info` 20 | -- ---------------------------- 21 | DROP TABLE IF EXISTS `login_user_info`; 22 | CREATE TABLE `login_user_info` ( 23 | `id` bigint(22) NOT NULL, 24 | `session_id` varchar(64) NOT NULL COMMENT 'session_key', 25 | `user_info` varchar(512) NOT NULL COMMENT '用户登录信息的json串', 26 | PRIMARY KEY (`id`) 27 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户登录的id'; 28 | 29 | -- ---------------------------- 30 | -- Records of login_user_info 31 | -- ---------------------------- 32 | 33 | -- ---------------------------- 34 | -- Table structure for `popup_info` 35 | -- ---------------------------- 36 | DROP TABLE IF EXISTS `popup_info`; 37 | CREATE TABLE `popup_info` ( 38 | `id` int(11) NOT NULL AUTO_INCREMENT, 39 | `title` varchar(255) NOT NULL, 40 | `content` text NOT NULL, 41 | `createTime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 42 | `popupLocation` varchar(255) DEFAULT NULL, 43 | `isShow` int(11) NOT NULL DEFAULT '0', 44 | PRIMARY KEY (`id`) 45 | ) ENGINE=InnoDB AUTO_INCREMENT=41 DEFAULT CHARSET=utf8mb4; 46 | 47 | -- ---------------------------- 48 | -- Records of popup_info 49 | -- ---------------------------- 50 | INSERT INTO `popup_info` VALUES ('11', '蓝猫AI', '蓝猫AI目前已开源,源码地址
ChatGpt3.5功能会一直免费下去,不限速,不限制次数。', '2023-05-30 23:57:42', 'login', '1'); 51 | INSERT INTO `popup_info` VALUES ('40', '蓝猫AI第1版公告', '蓝猫AI目前已开源,源码地址:点击联系我们', '2023-05-30 23:55:16', 'index', '1'); 52 | 53 | -- ---------------------------- 54 | -- Table structure for `prompt_model` 55 | -- ---------------------------- 56 | DROP TABLE IF EXISTS `prompt_model`; 57 | CREATE TABLE `prompt_model` ( 58 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 59 | `type` varchar(100) NOT NULL COMMENT '分类', 60 | `title` varchar(255) CHARACTER SET utf8mb4 NOT NULL COMMENT '标题', 61 | `introduce` varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '简介', 62 | `demo` varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '示例', 63 | `content` varchar(1000) CHARACTER SET utf8mb4 NOT NULL COMMENT '提示内容', 64 | `state` tinyint(4) NOT NULL COMMENT '0,无效;1,有效', 65 | `sort` tinyint(4) NOT NULL DEFAULT '0' COMMENT '排序值', 66 | `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 67 | `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 68 | PRIMARY KEY (`id`) 69 | ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8; 70 | 71 | -- ---------------------------- 72 | -- Records of prompt_model 73 | -- ---------------------------- 74 | INSERT INTO `prompt_model` VALUES ('1', 'Java', 'Java代码优化', '只需要将你想要的优化的代码复制到输入框,AI将会自动帮你优化它', '请输入/粘贴你想要优化的代码', '假如你是高级Java开发工程师,有着丰富的代码编写能力,那么请使用JDK8新语法将下面的代码进行优化并且将优化后的代码能够被markdowm渲染的代码出来:', '1', '0', '2023-05-21 22:42:46', '2023-05-21 22:56:34'); 75 | INSERT INTO `prompt_model` VALUES ('7', 'Java', '使用JDK8新特性优化代码', '只需要将你想要的优化的代码复制到输入框,AI将会自动使用JDK8新语法帮你优化它', '请输入/粘贴你想要优化的代码', '假如你是高级Java开发工程师,非常擅长使用JDK8新语法,那么请使用JDK8新语法将下面的代码进行优化并且将优化后的代码能够被markdowm渲染的代码出来:', '1', '0', '2023-05-21 22:47:14', '2023-05-21 22:55:46'); 76 | INSERT INTO `prompt_model` VALUES ('8', 'Java', 'Java面试打分工具', '只需要将你的问题和回答复制到输入框,AI将会自动根据你的问题和回答进行分析和打分', '问题:在synchronized代码块中调用wait方法进入等待的线程和因为拿不到锁而等待线程是否同一种状态?blocking?waiting?\r\n回答:1. 因为拿不到锁会处于 blocking状态;\r\n2. 调用wait方法,会处于 waiting状态,不会释放锁。\r\n', '假如你是Java面试官,有着非常丰富的面试经验,那么请基于下面的问题和回答进行系统的分析,给出相应的分数,并且以markdown的格式分点输出回答中不足的地方并且加以补充:', '1', '0', '2023-05-21 22:58:02', '2023-05-21 23:15:45'); 77 | 78 | -- ---------------------------- 79 | -- Table structure for `user_access_rule` 80 | -- ---------------------------- 81 | DROP TABLE IF EXISTS `user_access_rule`; 82 | CREATE TABLE `user_access_rule` ( 83 | `id` bigint(22) NOT NULL COMMENT '用户id', 84 | `user_id` bigint(22) NOT NULL, 85 | `service_type` varchar(32) COLLATE utf8mb4_bin NOT NULL COMMENT '模型标识', 86 | `use_number` tinyint(4) NOT NULL DEFAULT '10' COMMENT '使用次数, 如果 = -2 代表不限制次数', 87 | `start_effective_time` datetime NOT NULL COMMENT '开始生效时间', 88 | `end_effective_time` datetime NOT NULL COMMENT '有效结束时间', 89 | `create_time` datetime DEFAULT NULL COMMENT '创建时间', 90 | `update_time` datetime DEFAULT NULL COMMENT '更新时间', 91 | `update_user` varchar(32) COLLATE utf8mb4_bin DEFAULT NULL, 92 | PRIMARY KEY (`id`) 93 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='用户访问规则'; 94 | 95 | -- ---------------------------- 96 | -- Records of user_access_rule 97 | -- ---------------------------- 98 | INSERT INTO `user_access_rule` VALUES ('1664427904947597313', '1664427904784019457', 'chat_gpt_model3.5', '30', '2023-06-02 08:25:11', '2023-06-03 08:25:11', '2023-06-02 08:25:11', null, null); 99 | 100 | -- ---------------------------- 101 | -- Table structure for `user_info` 102 | -- ---------------------------- 103 | DROP TABLE IF EXISTS `user_info`; 104 | CREATE TABLE `user_info` ( 105 | `id` bigint(22) NOT NULL, 106 | `username` varchar(64) DEFAULT '小可爱!' COMMENT '用户昵称', 107 | `open_id` varchar(128) DEFAULT NULL COMMENT '微信授权的openId', 108 | `avatar` varchar(128) DEFAULT '/src/assets/avatar.jpg' COMMENT '用户头像', 109 | `phone` varchar(11) DEFAULT NULL COMMENT '电话信息', 110 | `account` varchar(32) NOT NULL COMMENT '用户账号', 111 | `user_level` varchar(16) DEFAULT 'common_user' COMMENT '用户等级', 112 | `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '账号状态,0正常,1禁用', 113 | `password` varchar(64) NOT NULL COMMENT '登录密码', 114 | `create_time` datetime DEFAULT NULL COMMENT '创建时间', 115 | `update_time` datetime DEFAULT NULL COMMENT '更新时间', 116 | PRIMARY KEY (`id`), 117 | UNIQUE KEY `account_index` (`account`) USING HASH 118 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; 119 | 120 | -- ---------------------------- 121 | -- Records of user_info 122 | -- ---------------------------- 123 | INSERT INTO `user_info` VALUES ('1664427904784019457', '小可爱!', null, '/src/assets/avatar.jpg', null, '18230675983', 'common_user', '0', 'acaaf694427dcb42423626d4aa74c4ae', '2023-06-02 08:25:11', null); 124 | --------------------------------------------------------------------------------