From cc1a3ce343e09adf7f385ed2cc03a57e5994155e Mon Sep 17 00:00:00 2001 From: RockYang Date: Tue, 30 Apr 2024 22:54:39 +0800 Subject: [PATCH] opt: close unused websocket connections --- api/core/app_server.go | 1 + api/handler/chatimpl/chat_handler.go | 1 + api/service/license_service.go | 13 +++-- web/src/App.vue | 10 ++++ web/src/assets/css/mobile/chat-session.styl | 4 +- web/src/components/SendMsg.vue | 16 +++--- web/src/utils/dialog.js | 43 +++++++++++++++ web/src/views/ChatPlus.vue | 5 +- web/src/views/ImageMj.vue | 9 ++- web/src/views/ImageSd.vue | 5 +- web/src/views/Login.vue | 11 ++-- web/src/views/Register.vue | 17 +++--- web/src/views/mobile/ChatSession.vue | 61 ++++++++++++--------- web/src/views/mobile/Home.vue | 10 ---- web/src/views/mobile/Index.vue | 1 + web/src/views/mobile/pages/ImageMj.vue | 14 ++--- web/src/views/mobile/pages/ImageSd.vue | 8 ++- 17 files changed, 144 insertions(+), 85 deletions(-) create mode 100644 web/src/utils/dialog.js diff --git a/api/core/app_server.go b/api/core/app_server.go index d40feb90..fc410bb1 100644 --- a/api/core/app_server.go +++ b/api/core/app_server.go @@ -204,6 +204,7 @@ func needLogin(c *gin.Context) bool { c.Request.URL.Path == "/api/admin/login" || c.Request.URL.Path == "/api/admin/login/captcha" || c.Request.URL.Path == "/api/user/register" || + c.Request.URL.Path == "/api/user/session" || c.Request.URL.Path == "/api/chat/history" || c.Request.URL.Path == "/api/chat/detail" || c.Request.URL.Path == "/api/chat/list" || diff --git a/api/handler/chatimpl/chat_handler.go b/api/handler/chatimpl/chat_handler.go index 80077ea9..125a1d8e 100644 --- a/api/handler/chatimpl/chat_handler.go +++ b/api/handler/chatimpl/chat_handler.go @@ -137,6 +137,7 @@ func (h *ChatHandler) ChatHandle(c *gin.Context) { for { _, msg, err := client.Receive() if err != nil { + logger.Debugf("close connection: %s", client.Conn.RemoteAddr()) client.Close() h.App.ChatClients.Delete(sessionId) h.App.ChatSession.Delete(sessionId) diff --git a/api/service/license_service.go b/api/service/license_service.go index f30ce098..18f1d6d1 100644 --- a/api/service/license_service.go +++ b/api/service/license_service.go @@ -6,10 +6,11 @@ import ( "chatplus/store" "errors" "fmt" - "github.com/imroc/req/v3" - "github.com/shirou/gopsutil/host" "strings" "time" + + "github.com/imroc/req/v3" + "github.com/shirou/gopsutil/host" ) type LicenseService struct { @@ -20,7 +21,7 @@ type LicenseService struct { machineId string } -func NewLicenseService(server *core.AppServer, levelDB *store.LevelDB) * LicenseService { +func NewLicenseService(server *core.AppServer, levelDB *store.LevelDB) *LicenseService { var license types.License var machineId string _ = levelDB.Get(types.LicenseKey, &license) @@ -60,7 +61,7 @@ func (s *LicenseService) ActiveLicense(license string, machineId string) error { } if response.IsErrorState() { - return fmt.Errorf( "发送激活请求失败:%v", response.Status) + return fmt.Errorf("发送激活请求失败:%v", response.Status) } if res.Code != types.Success { @@ -119,7 +120,7 @@ func (s *LicenseService) SyncLicense() { IsActive: true, } s.urlWhiteList = res.Data.Urls - logger.Debugf("同步 License 成功:%v\n%v", s.license, s.urlWhiteList) + //logger.Debugf("同步 License 成功:%v\n%v", s.license, s.urlWhiteList) next: time.Sleep(time.Second * 10) } @@ -151,4 +152,4 @@ func (s *LicenseService) IsValidApiURL(uri string) error { } } return fmt.Errorf("当前 API 地址 %s 不在白名单列表当中。", uri) -} \ No newline at end of file +} diff --git a/web/src/App.vue b/web/src/App.vue index ae0a0856..c57704ea 100644 --- a/web/src/App.vue +++ b/web/src/App.vue @@ -66,4 +66,14 @@ html, body { white-space: nowrap; } +.van-toast--fail { + background #fef0f0 + color #f56c6c +} + +.van-toast--success { + background #D6FBCC + color #07C160 +} + diff --git a/web/src/assets/css/mobile/chat-session.styl b/web/src/assets/css/mobile/chat-session.styl index 25aa54d0..65a73fd3 100644 --- a/web/src/assets/css/mobile/chat-session.styl +++ b/web/src/assets/css/mobile/chat-session.styl @@ -9,7 +9,7 @@ .chat-list-wrapper { padding 10px 0 10px 0 - background #F5F5F5; + background var(--van-background); overflow hidden @@ -81,7 +81,7 @@ .van-theme-dark { .mobile-chat { - .message-list-box { + .chat-list-wrapper { background #232425; } } diff --git a/web/src/components/SendMsg.vue b/web/src/components/SendMsg.vue index 19364531..435fccc8 100644 --- a/web/src/components/SendMsg.vue +++ b/web/src/components/SendMsg.vue @@ -38,11 +38,11 @@ import {ref} from "vue"; import lodash from 'lodash' import {validateEmail, validateMobile} from "@/utils/validate"; -import {ElMessage} from "element-plus"; import {httpGet, httpPost} from "@/utils/http"; import CaptchaPlus from "@/components/CaptchaPlus.vue"; import SlideCaptcha from "@/components/SlideCaptcha.vue"; import {isMobile} from "@/utils/libs"; +import {showMessageError, showMessageOK} from "@/utils/dialog"; // eslint-disable-next-line no-undef const props = defineProps({ @@ -66,13 +66,13 @@ const handleRequestCaptCode = () => { thumbBase64.value = data.thumb captKey.value = data.key }).catch(e => { - ElMessage.error('获取人机验证数据失败:' + e.message) + showMessageError('获取人机验证数据失败:' + e.message) }) } const handleConfirm = (dots) => { if (lodash.size(dots) <= 0) { - return ElMessage.error('请进行人机验证再操作') + return showMessageError('请进行人机验证再操作') } let dotArr = [] @@ -88,14 +88,14 @@ const handleConfirm = (dots) => { showCaptcha.value = false sendMsg() }).catch(() => { - ElMessage.error('人机验证失败') + showMessageError('人机验证失败') handleRequestCaptCode() }) } const loadCaptcha = () => { if (!validateMobile(props.receiver) && !validateEmail(props.receiver)) { - return ElMessage.error("请输入合法的手机号/邮箱地址") + return showMessageError("请输入合法的手机号/邮箱地址") } showCaptcha.value = true @@ -114,7 +114,7 @@ const sendMsg = () => { canSend.value = false httpPost('/api/sms/code', {receiver: props.receiver, key: captKey.value, dots: dots.value}).then(() => { - ElMessage.success('验证码发送成功') + showMessageOK('验证码发送成功') let time = 120 btnText.value = time const handler = setInterval(() => { @@ -129,7 +129,7 @@ const sendMsg = () => { }, 1000) }).catch(e => { canSend.value = true - ElMessage.error('验证码发送失败:' + e.message) + showMessageError('验证码发送失败:' + e.message) }) } @@ -145,7 +145,7 @@ const getSlideCaptcha = () => { bgImg.value = res.data.bgImg captKey.value = res.data.key }).catch(e => { - ElMessage.error('获取人机验证数据失败:' + e.message) + showMessageError('获取人机验证数据失败:' + e.message) }) } diff --git a/web/src/utils/dialog.js b/web/src/utils/dialog.js new file mode 100644 index 00000000..7be47aee --- /dev/null +++ b/web/src/utils/dialog.js @@ -0,0 +1,43 @@ +/** + * Util lib functions + */ +import {showConfirmDialog, showFailToast, showSuccessToast, showToast} from "vant"; +import {isMobile} from "@/utils/libs"; +import {ElMessage} from "element-plus"; + +export function showLoginDialog(router) { + showConfirmDialog({ + title: '登录', + message: + '此操作需要登录才能进行,前往登录?', + }).then(() => { + router.push("/login") + }).catch(() => { + // on cancel + }); +} + +export function showMessageOK(message) { + if (isMobile()) { + showSuccessToast(message) + } else { + ElMessage.success(message) + } +} + + +export function showMessageInfo(message) { + if (isMobile()) { + showToast(message) + } else { + ElMessage.info(message) + } +} + +export function showMessageError(message) { + if (isMobile()) { + showFailToast(message) + } else { + ElMessage.error(message) + } +} diff --git a/web/src/views/ChatPlus.vue b/web/src/views/ChatPlus.vue index ae08ffdc..31f220e2 100644 --- a/web/src/views/ChatPlus.vue +++ b/web/src/views/ChatPlus.vue @@ -330,7 +330,10 @@ onMounted(() => { }); onUnmounted(() => { - socket.value = null + if (socket.value !== null) { + socket.value.close() + socket.value = null + } }) // 初始化数据 diff --git a/web/src/views/ImageMj.vue b/web/src/views/ImageMj.vue index d6b13933..7b480bdb 100644 --- a/web/src/views/ImageMj.vue +++ b/web/src/views/ImageMj.vue @@ -761,7 +761,10 @@ onMounted(() => { onUnmounted(() => { clipboard.value.destroy() - socket.value = null + if (socket.value !== null) { + socket.value.close() + socket.value = null + } }) // 初始化数据 @@ -779,10 +782,6 @@ const initData = () => { }); } -onUnmounted(() => { - clipboard.value.destroy() -}) - const mjPower = ref(1) const mjActionPower = ref(1) httpGet("/api/config/get?key=system").then(res => { diff --git a/web/src/views/ImageSd.vue b/web/src/views/ImageSd.vue index 5baefea3..32697da1 100644 --- a/web/src/views/ImageSd.vue +++ b/web/src/views/ImageSd.vue @@ -616,7 +616,10 @@ onMounted(() => { onUnmounted(() => { clipboard.value.destroy() - socket.value = null + if (socket.value !== null) { + socket.value.close() + socket.value = null + } }) diff --git a/web/src/views/Login.vue b/web/src/views/Login.vue index ddffa5bf..aaf582bc 100644 --- a/web/src/views/Login.vue +++ b/web/src/views/Login.vue @@ -56,13 +56,13 @@ import {ref} from "vue"; import {Lock, UserFilled} from "@element-plus/icons-vue"; import {httpGet, httpPost} from "@/utils/http"; -import {ElMessage} from "element-plus"; import {useRouter} from "vue-router"; import FooterBar from "@/components/FooterBar.vue"; import {isMobile} from "@/utils/libs"; import {checkSession} from "@/action/session"; import {setUserToken} from "@/store/session"; import ResetPass from "@/components/ResetPass.vue"; +import {showMessageError} from "@/utils/dialog"; const router = useRouter(); const title = ref('Geek-AI'); @@ -76,7 +76,7 @@ httpGet("/api/config/get?key=system").then(res => { logo.value = res.data.logo title.value = res.data.title }).catch(e => { - ElMessage.error("获取系统配置失败:" + e.message) + showMessageError("获取系统配置失败:" + e.message) }) @@ -97,10 +97,10 @@ const handleKeyup = (e) => { const login = function () { if (username.value.trim() === '') { - return ElMessage.error("请输入用户民") + return showMessageError("请输入用户民") } if (password.value.trim() === '') { - return ElMessage.error('请输入密码'); + return showMessageError('请输入密码'); } httpPost('/api/user/login', {username: username.value.trim(), password: password.value.trim()}).then((res) => { @@ -112,11 +112,10 @@ const login = function () { } }).catch((e) => { - ElMessage.error('登录失败,' + e.message) + showMessageError('登录失败,' + e.message) }) } -