commit c0ca154d318b2f275cc3dc5d5d9869ee43586d38 Author: luojie Date: Thu Sep 7 00:56:03 2023 +0800 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..485f9f0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +**/.idea +/logs +**/im-service/target +**/im-codec/target +**/im-common/target +**/im-message-store/target +**/im-tcp/target diff --git a/app-sqlite-master/app-sqlite/.gitignore b/app-sqlite-master/app-sqlite/.gitignore new file mode 100644 index 0000000..79c8b4a --- /dev/null +++ b/app-sqlite-master/app-sqlite/.gitignore @@ -0,0 +1,2 @@ +/unpackage +/.hbuilderx diff --git a/app-sqlite-master/app-sqlite/App.vue b/app-sqlite-master/app-sqlite/App.vue new file mode 100644 index 0000000..57e56d4 --- /dev/null +++ b/app-sqlite-master/app-sqlite/App.vue @@ -0,0 +1,36 @@ + + + diff --git a/app-sqlite-master/app-sqlite/README.md b/app-sqlite-master/app-sqlite/README.md new file mode 100644 index 0000000..e69de29 diff --git a/app-sqlite-master/app-sqlite/common/common.css b/app-sqlite-master/app-sqlite/common/common.css new file mode 100644 index 0000000..f18c391 --- /dev/null +++ b/app-sqlite-master/app-sqlite/common/common.css @@ -0,0 +1,33 @@ +/* 1. 页面背景色 */ +.page{ + background-color: #EDEDED; + /* #ifndef APP-PLUS-NVUE */ + min-height: 100vh; + height: auto; + /* #endif */ + /* #ifdef APP-PLUS-NVUE */ + flex: 1; + /* #endif */ +} +/* 2. 主背景色(原谅绿) */ +.main-bg-color{ + background-color: #08C060; +} +.main-bg-hover-color{ + background-color: #08d869; +} +/* 3. 主文字色(原谅绿) */ +.main-text-color{ + color: #08C060; +} + +.border-main{ + border-color: #08C060!important; +} + +.bg-chat-item{ + background-color: #6BEE68; +} +.text-chat-item{ + color: #6BEE68; +} \ No newline at end of file diff --git a/app-sqlite-master/app-sqlite/common/icon.css b/app-sqlite-master/app-sqlite/common/icon.css new file mode 100644 index 0000000..11540c0 --- /dev/null +++ b/app-sqlite-master/app-sqlite/common/icon.css @@ -0,0 +1,11 @@ +@font-face {font-family: "iconfont"; + src:url('data:application/x-font-woff2;charset=utf-8;base64,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') format('woff2') +} + +.iconfont { + font-family: "iconfont" !important; + font-size: 16px; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} \ No newline at end of file diff --git a/app-sqlite-master/app-sqlite/common/lib/config.js b/app-sqlite-master/app-sqlite/common/lib/config.js new file mode 100644 index 0000000..0b263c5 --- /dev/null +++ b/app-sqlite-master/app-sqlite/common/lib/config.js @@ -0,0 +1,14 @@ +export default { + // #ifndef H5 + baseUrl:"http://192.168.100.12:8000", + // #endif + + // #ifdef H5 + baseUrl:"http://192.168.100.12:8000", + // #endif + + version: "/v1", + + env:"dev", + appId: 10000 +} \ No newline at end of file diff --git a/app-sqlite-master/app-sqlite/common/lib/request.js b/app-sqlite-master/app-sqlite/common/lib/request.js new file mode 100644 index 0000000..e29592d --- /dev/null +++ b/app-sqlite-master/app-sqlite/common/lib/request.js @@ -0,0 +1,95 @@ +import $C from './config.js'; +import $U from './util.js'; + +export default { + // 全局配置 + common:{ + baseUrl:$C.baseUrl + $C.version, + header:{ + 'Content-Type':'application/json;charset=UTF-8', + }, + data:{}, + method:'GET', + dataType:'json', + token:true, + }, + // 请求 返回promise + request(options = {}){ + // 组织参数 + options.url = this.common.baseUrl + options.url + options.header = options.header || this.common.header + options.data = options.data || this.common.data + options.method = options.method || this.common.method + options.dataType = options.dataType || this.common.dataType + options.token = options.token === false ? false : this.common.token + // params + options.url = options.url + "?appId=10000" + console.log(options.url) + + // 请求 + return new Promise((res,rej)=>{ + // 请求中... + uni.request({ + ...options, + success: (result) => { + // 返回原始数据 + if(options.native){ + return res(result) + } + console.log(result.statusCode) + // 服务端失败 + if(result.statusCode !== 200){ + if (options.toast !== false) { + uni.showToast({ + title: result.data.data || '服务端失败', + icon: 'none' + }); + } + return rej(result.data) + } + // 其他验证... + // 成功 + let data = result.data + + res(data) + }, + fail: (error) => { + uni.showToast({ title: error.errMsg || '请求失败', icon: 'none' }); + return rej(error) + } + }); + }) + }, + setQueryConfig(params){ +   var _str = "?"; +   for(var o in params){ +     if(params[o] != -1){ +       _str += o + "=" + params[o] + "&"; +     } +   } +    var _str = _str.substring(0, _str.length-1); //末尾是& +    return _str; + }, + // get请求 + get(url,data = {},options = {}){ + options.url = url + options.data = data + options.method = 'GET' + return this.request(options) + }, + // post请求 + post(url,data = {},options = {}){ + options.url = url + options.data = data + options.method = 'POST' + console.log(options) + return this.request(options) + }, + // delete请求 + del(url,data = {},options = {}){ + options.url = url + options.data = data + options.method = 'DELETE' + return this.request(options) + } +} \ No newline at end of file diff --git a/app-sqlite-master/app-sqlite/common/lib/util.js b/app-sqlite-master/app-sqlite/common/lib/util.js new file mode 100644 index 0000000..f3b83de --- /dev/null +++ b/app-sqlite-master/app-sqlite/common/lib/util.js @@ -0,0 +1,44 @@ +import $C from './config.js' +export default { + // 获取存储列表数据 + getStorage(key){ + let data = null; + // #ifdef H5 + if($C.env === 'dev'){ + data = window.sessionStorage.getItem(key) + } else { + data = uni.getStorageSync(key) + } + // #endif + // #ifndef H5 + data = uni.getStorageSync(key) + // #endif + return data + }, + // 设置存储 + setStorage(key,data){ + // #ifdef H5 + if($C.env === 'dev'){ + return window.sessionStorage.setItem(key,data) + } else { + return uni.setStorageSync(key,data) + } + // #endif + // #ifndef H5 + return uni.setStorageSync(key,data) + // #endif + }, + // 删除存储 + removeStorage(key){ + // #ifdef H5 + if($C.env === 'dev'){ + return window.sessionStorage.removeItem(key); + } else { + return uni.removeStorageSync(key) + } + // #endif + // #ifndef H5 + return uni.removeStorageSync(key) + // #endif + } +} \ No newline at end of file diff --git a/app-sqlite-master/app-sqlite/common/my.css b/app-sqlite-master/app-sqlite/common/my.css new file mode 100644 index 0000000..5bfe76a --- /dev/null +++ b/app-sqlite-master/app-sqlite/common/my.css @@ -0,0 +1,399 @@ +/* 图标 */ +.iconfont{ + font-family:iconfont; +} +.view,.text{ + font-size:28rpx; + line-height:1.8; + color:#0E151D; +} +/* 宽度 */ +.w-100{ width: 750rpx; } + +.row { + margin-right: -20rpx; + margin-left: -20rpx; + /* #ifndef APP-PLUS-NVUE */ + display: flex; + /* #endif */ + flex-wrap: wrap; + flex-direction: row; +} + +.col-1, +.col-2, +.col-3, +.col-4, +.col-5, +.col-6, +.col-7, +.col-8, +.col-9, +.col-10, +.col-11, +.col-12{ + position: relative; + padding-right: 20rpx; + padding-left: 20rpx; +} +.col-12 { width: 750rpx;} +.col-11 { width: 687.5rpx; } +.col-10 { width: 625rpx; } +.col-9 { width: 562.5rpx; } +.col-8 { width: 500rpx; } +.col-7 { width: 437.5rpx; } +.col-6 { width: 375rpx; } +.col-5 { width: 312.5rpx;} +.col-4 {width: 250rpx;} +.col-3 {width: 187.5rpx;} +.col-2 {width: 125rpx;} +.col-1 {width: 62.5rpx;} + +.col-offset-12 { margin-left: 750rpx;} +.col-offset-11 { margin-left: 687.5rpx; } +.col-offset-10 { margin-left: 625rpx; } +.col-offset-9 { margin-left: 562.5rpx; } +.col-offset-8 { margin-left: 500rpx; } +.col-offset-7 { margin-left: 437.5rpx; } +.col-offset-6 { margin-left: 375rpx; } +.col-offset-5 { margin-left: 312.5rpx;} +.col-offset-4 {margin-left: 250rpx;} +.col-offset-3 {margin-left: 187.5rpx;} +.col-offset-2 {margin-left: 125rpx;} +.col-offset-1 {margin-left: 62.5rpx;} +.col-offset-0 {margin-left: 0;} + +/* flex 布局 */ +.flex{ + /* #ifndef APP-PLUS-NVUE */ + display:flex; + /* #endif */ + flex-direction:row; +} +.flex-row{ flex-direction:row!important; } +.flex-column{ flex-direction:column!important; } +.flex-row-reverse{ flex-direction:row-reverse!important; } +.flex-column-reverse{ flex-direction:column-reverse!important; } +.flex-wrap{ flex-wrap:wrap;} +.flex-nowrap{ flex-wrap:nowrap;} +.justify-start{justify-content:flex-start;} +.justify-end{justify-content:flex-end;} +.justify-between{justify-content:space-between;} +.justify-center{justify-content:center;} +.align-center{ align-items: center; } +.align-stretch{ align-items: stretch; } +.align-start{ align-items: flex-start; } +.align-end{ align-items: flex-end; } +/* #ifndef APP-PLUS-NVUE */ +.content-start {align-content: flex-start;} +.content-end {align-content: flex-end;} +.content-center {align-content: center;} +.content-between {align-content: space-between;} +.content-around {align-content: space-around;} +.content-stretch {align-content: stretch;} +/* #endif */ +.flex-1{ flex: 1; } +.flex-2{ flex: 2; } +.flex-3{ flex: 3; } +.flex-4{ flex: 4; } +.flex-5{ flex: 5; } +/* #ifndef APP-PLUS-NVUE */ +.flex-shrink{ flex-shrink: 0; } +/* #endif */ + +.container { + padding-right: 20rpx; + padding-left: 20rpx; +} +/* -- 内外边距 -- */ +.m-0 { margin: 0; } +/* #ifndef APP-PLUS-NVUE */ +.m-auto{ margin: auto; } +/* #endif */ +.m-1 { margin: 10rpx; } +.m-2 { margin: 20rpx; } +.m-3 { margin: 30rpx; } +.m-4 { margin: 40rpx; } +.m-5 { margin: 50rpx; } +.mt-0 { margin-top: 0; } +/* #ifndef APP-PLUS-NVUE */ +.mt-auto { margin-top: auto; } +/* #endif */ +.mt-1 { margin-top: 10rpx; } +.mt-2 { margin-top: 20rpx; } +.mt-3 { margin-top: 30rpx; } +.mt-4 { margin-top: 40rpx; } +.mt-5 { margin-top: 50rpx; } +.mb-0 { margin-bottom: 0; } +/* #ifndef APP-PLUS-NVUE */ +.mb-auto { margin-bottom: auto; } +/* #endif */ +.mb-1 { margin-bottom: 10rpx; } +.mb-2 { margin-bottom: 20rpx; } +.mb-3 { margin-bottom: 30rpx; } +.mb-4 { margin-bottom: 40rpx; } +.mb-5 { margin-bottom: 50rpx; } +.ml-0 { margin-left: 0; } +/* #ifndef APP-PLUS-NVUE */ +.ml-auto { margin-left: auto; } +/* #endif */ +.ml-1 { margin-left: 10rpx; } +.ml-2 { margin-left: 20rpx; } +.ml-3 { margin-left: 30rpx; } +.ml-4 { margin-left: 40rpx; } +.ml-5 { margin-left: 50rpx; } +.mr-0 { margin-right: 0; } +/* #ifndef APP-PLUS-NVUE */ +.mr-auto { margin-right: auto; } +/* #endif */ +.mr-1 { margin-right: 10rpx; } +.mr-2 { margin-right: 20rpx; } +.mr-3 { margin-right: 30rpx; } +.mr-4 { margin-right: 40rpx; } +.mr-5 { margin-right: 50rpx; } +.my-0 { margin-top: 0; margin-bottom: 0; } +/* #ifndef APP-PLUS-NVUE */ +.my-auto { margin-top: auto; margin-bottom: auto; } +/* #endif */ +.my-1 { margin-top: 10rpx; margin-bottom: 10rpx; } +.my-2 { margin-top: 20rpx; margin-bottom: 20rpx; } +.my-3 { margin-top: 30rpx; margin-bottom: 30rpx; } +.my-4 { margin-top: 40rpx; margin-bottom: 40rpx; } +.my-5 { margin-top: 50rpx; margin-bottom: 50rpx; } +.mx-0 { margin-left: 0; margin-right: 0; } +/* #ifndef APP-PLUS-NVUE */ +.mx-auto { margin-left: auto; margin-right: auto; } +/* #endif */ +.mx-1 { margin-left: 10rpx; margin-right: 10rpx;} +.mx-2 { margin-left: 20rpx; margin-right: 20rpx;} +.mx-3 { margin-left: 30rpx; margin-right: 30rpx;} +.mx-4 { margin-left: 40rpx; margin-right: 40rpx;} +.mx-5 { margin-left: 50rpx; margin-right: 50rpx;} + +.p-0 { padding: 0; } +.p { padding: 5rpx; } +.p-1 { padding: 10rpx; } +.p-2 { padding: 20rpx; } +.p-3 { padding: 30rpx; } +.p-4 { padding: 40rpx; } +.p-5 { padding: 50rpx; } +.pt-0 { padding-top: 0; } +.pt { padding-top: 5rpx; } +.pt-1 { padding-top: 10rpx; } +.pt-2 { padding-top: 20rpx; } +.pt-3 { padding-top: 30rpx; } +.pt-4 { padding-top: 40rpx; } +.pt-5 { padding-top: 50rpx; } +.pb-0 { padding-bottom: 0; } +.pb-1 { padding-bottom: 10rpx; } +.pb { padding-bottom: 5rpx; } +.pb-2 { padding-bottom: 20rpx; } +.pb-3 { padding-bottom: 30rpx; } +.pb-4 { padding-bottom: 40rpx; } +.pb-5 { padding-bottom: 50rpx; } +.pl-0 { padding-left: 0; } +.pl { padding-left: 5rpx; } +.pl-1 { padding-left: 10rpx; } +.pl-2 { padding-left: 20rpx; } +.pl-3 { padding-left: 30rpx; } +.pl-4 { padding-left: 40rpx; } +.pl-5 { padding-left: 50rpx; } +.pr-0 { padding-right: 0; } +.pr { padding-right: 5rpx; } +.pr-1 { padding-right: 10rpx; } +.pr-2 { padding-right: 20rpx; } +.pr-3 { padding-right: 30rpx; } +.pr-4 { padding-right: 40rpx; } +.pr-5 { padding-right: 50rpx; } +.py-0 { padding-top: 0; padding-bottom: 0; } +.py { padding-top: 5rpx; padding-bottom: 5rpx; } +.py-1 { padding-top: 10rpx; padding-bottom: 10rpx; } +.py-2 { padding-top: 20rpx; padding-bottom: 20rpx; } +.py-3 { padding-top: 30rpx; padding-bottom: 30rpx; } +.py-4 { padding-top: 40rpx; padding-bottom: 40rpx; } +.py-5 { padding-top: 50rpx; padding-bottom: 50rpx; } +.px-0 { padding-left: 0; padding-right: 0; } +.px-1 { padding-left: 10rpx; padding-right: 10rpx;} +.px { padding-left: 5rpx; padding-right: 5rpx;} +.px-2 { padding-left: 20rpx; padding-right: 20rpx;} +.px-3 { padding-left: 30rpx; padding-right: 30rpx;} +.px-4 { padding-left: 40rpx; padding-right: 40rpx;} +.px-5 { padding-left: 50rpx; padding-right: 50rpx;} +/* 文字大小 */ +.font-small { font-size: 20upx;} +.font-sm { font-size: 25upx;} +.font { font-size: 30upx;} +.font-md { font-size: 35upx;} +.font-lg { font-size: 40upx;} +.h1{font-size:80upx; line-height:1.8;} +.h2{font-size:60upx; line-height:1.8;} +.h3{font-size:45upx; line-height:1.8;} +.h4{font-size:32upx; line-height:1.8;} +.h5{font-size:30upx; line-height:1.8;} +.h6{font-size:28upx; line-height:1.8;} +/* 文字缩进 */ +/* #ifndef APP-PLUS-NVUE */ +.text-indent{text-indent:2;} +/* #endif */ +/* 文字划线 */ +.text-through{text-decoration:line-through;} +/* 文字对齐 */ +.text-left { text-align: left;} +.text-right { text-align: right;} +.text-center { text-align: center;} +/* 文字换行溢出处理 */ +.text-ellipsis { + /* #ifndef APP-PLUS-NVUE */ + overflow: hidden;text-overflow: ellipsis;white-space: nowrap; + /* #endif */ + /* #ifdef APP-PLUS-NVUE */ + lines: 1; + /* #endif */ +} +/* 文字粗细和斜体 */ +.font-weight-light {font-weight: 300;} /*细*/ +.font-weight-lighter {font-weight: 100;}/*更细*/ +.font-weight-normal { font-weight: 400;} /*正常*/ +.font-weight-bold { font-weight: 700;} /*粗*/ +.font-weight-bolder { font-weight: bold;} /*更粗*/ +.font-italic { font-style: italic;} /*斜体*/ +/* 文字颜色 */ +.text-white {color: #ffffff;} +.text-primary {color: #007bff;} +.text-hover-primary { color: #0056b3;} +.text-secondary {color: #6c757d;} +.text-hover-secondary { color: #494f54;} +.text-success {color: #28a745;} +.text-hover-success{color: #19692c;} +.text-info { color: #17a2b8;} +.text-hover-info {color: #0f6674;} +.text-warning {color: #ffc107;} +.text-hover-warning { color: #ba8b00;} +.text-danger { color: #dc3545;} +.text-hover-danger { color: #a71d2a;} +.text-light { color: #f8f9fa;} +.text-hover-light { color: #cbd3da;} +.text-dark { color: #343a40;} +.text-hover-dark{ color: #121416;} +.text-body { color: #212529;} +.text-muted { color: #6c757d;} +.text-light-muted { color: #A9A5A0;} +.text-light-black { color: rgba(0, 0, 0, 0.5);} +.text-light-white { color: rgba(255, 255, 255, 0.5);} + +/* 背景颜色 */ +.bg-primary { background-color: #007bff;} +.bg-hover-primary:hover{ background-color: #0062cc;} +.bg-secondary { background-color: #6c757d;} +.bg-hover-secondary:hover{ background-color: #545b62;} +.bg-success { background-color: #28a745;} +.bg-hover-success { background-color: #1e7e34;} +.bg-info { background-color: #17a2b8;} +.bg-hover-info { background-color: #117a8b;} +.bg-warning { background-color: #ffc107;} +.bg-hover-warning { background-color: #d39e00;} +.bg-danger { background-color: #dc3545;} +.bg-hover-danger{ background-color: #bd2130;} +.bg-light { background-color: #f8f9fa;} +.bg-hover-light{ background-color: #dae0e5;} +.bg-dark { background-color: #343a40;} +.bg-hover-dark { background-color: #1d2124;} +.bg-white { background-color: #ffffff;} +.bg-transparent { background-color: transparent;} +/* 边框 */ +.border { border-width: 1rpx;border-style: solid;border-color: #dee2e6;} +.border-top { + border-top-width: 1rpx; + border-top-style: solid; + border-top-color: #dee2e6; +} +.border-right { + border-right-width: 1rpx; + border-right-style: solid; + border-right-color: #dee2e6; +} +.border-bottom { + border-bottom-width: 1rpx; + border-bottom-style: solid; + border-bottom-color: #dee2e6; +} +.border-left { + border-left-width: 1rpx; + border-left-style: solid; + border-left-color: #dee2e6; +} +.border-0 { border-width: 0!important;} +.border-top-0 { border-top-width: 0!important;} +.border-right-0 {border-right-width: 0!important;} +.border-bottom-0 {border-bottom-width: 0!important;} +.border-left-0 {border-left-width: 0!important;} +.border-primary { border-color: #007bff;} +.border-secondary {border-color: #6c757d;} +.border-light-secondary {border-color: #E9E8E5;} +.border-success {border-color: #28a745;} +.border-info {border-color: #17a2b8;} +.border-warning {border-color: #ffc107;} +.border-danger {border-color: #dc3545;} +.border-light {border-color: #f8f9fa;} +.border-dark {border-color: #343a40;} +.border-white {border-color: #FFFFFF;} +/* 圆角 */ +.rounded { border-radius: 8rpx;} +.rounded-top { + border-top-left-radius: 8rpx; + border-top-right-radius: 8rpx; +} +.rounded-right { + border-top-right-radius: 8rpx; + border-bottom-right-radius: 8rpx; +} +.rounded-bottom { + border-bottom-right-radius: 8rpx; + border-bottom-left-radius: 8rpx; +} +.rounded-left { + border-top-left-radius: 8rpx; + border-bottom-left-radius: 8rpx; + } +.rounded-circle { border-radius: 100rpx;} +.rounded-0 { border-radius: 0;} +/* 显示 */ +/* #ifndef APP-PLUS-NVUE */ +.d-none{ display: none; } +.d-inline-block{ display: inline-block; } +.d-block{ display: block; } +/* #endif */ +/* 内容溢出 */ +.overflow-hidden { overflow: hidden;} +/* 定位 */ +.position-relative { position: relative;} +.position-absolute { position: absolute;} +.position-fixed { position: fixed;} +/* 定位 - 固定顶部 */ +.fixed-top { + position: fixed; + top: 0; + right: 0; + left: 0; + z-index: 1030; +} +/* 定位 - 固定底部 */ +.fixed-bottom { + position: fixed; + right: 0; + bottom: 0; + left: 0; + z-index: 1030; +} +.top-0 { top: 0; } +.left-0 { left: 0; } +.right-0 { right: 0; } +.bottom-0 { bottom: 0; } + +/* 阴影 */ +/* #ifndef APP-PLUS-NVUE */ +.shadow { box-shadow: 0 2upx 12upx rgba(0, 0, 0, 0.15);} +.shadow-lg { box-shadow: 0upx 40upx 100upx 0upx rgba(0, 0, 0, 0.175);} +.shadow-none { box-shadow: none !important;} +/* #endif */ + diff --git a/app-sqlite-master/app-sqlite/font.ttf b/app-sqlite-master/app-sqlite/font.ttf new file mode 100644 index 0000000..c40d35d Binary files /dev/null and b/app-sqlite-master/app-sqlite/font.ttf differ diff --git a/app-sqlite-master/app-sqlite/index.html b/app-sqlite-master/app-sqlite/index.html new file mode 100644 index 0000000..c3ff205 --- /dev/null +++ b/app-sqlite-master/app-sqlite/index.html @@ -0,0 +1,20 @@ + + + + + + + + + + +
+ + + diff --git a/app-sqlite-master/app-sqlite/main.js b/app-sqlite-master/app-sqlite/main.js new file mode 100644 index 0000000..4befaf9 --- /dev/null +++ b/app-sqlite-master/app-sqlite/main.js @@ -0,0 +1,12 @@ +import Vue from 'vue' +import App from './App' + + +Vue.config.productionTip = false + +App.mpType = 'app' + +const app = new Vue({ + ...App +}) +app.$mount() diff --git a/app-sqlite-master/app-sqlite/manifest.json b/app-sqlite-master/app-sqlite/manifest.json new file mode 100644 index 0000000..f2ab563 --- /dev/null +++ b/app-sqlite-master/app-sqlite/manifest.json @@ -0,0 +1,88 @@ +{ + "name" : "l-im-app", + "appid" : "__UNI__621989A", + "description" : "l-im-app", + "versionName" : "1.0.0", + "versionCode" : "100", + "transformPx" : false, + /* 5+App特有相关 */ + "app-plus" : { + "nvueCompiler" : "uni-app", + "usingComponents" : true, + "splashscreen" : { + "alwaysShowBeforeRender" : true, + "waiting" : true, + "autoclose" : true, + "delay" : 0 + }, + /* 模块配置 */ + "modules" : { + "VideoPlayer" : {}, + "SQLite" : {} + }, + /* 应用发布信息 */ + "distribute" : { + /* android打包配置 */ + "android" : { + "permissions" : [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ] + }, + /* ios打包配置 */ + "ios" : { + "UIBackgroundModes" : "audio", + "idfa" : false + }, + /* SDK配置 */ + "sdkConfigs" : {} + }, + "compilerVersion" : 3, + "renderer" : "native" + }, + /* 快应用特有相关 */ + "quickapp" : {}, + /* 小程序特有相关 */ + "mp-weixin" : { + "appid" : "", + "setting" : { + "urlCheck" : false + }, + "usingComponents" : true + }, + "mp-alipay" : { + "usingComponents" : true + }, + "mp-baidu" : { + "usingComponents" : true + }, + "mp-toutiao" : { + "usingComponents" : true + }, + "uniStatistics" : { + "enable" : false + }, + "vueVersion" : "2" +} + + diff --git a/app-sqlite-master/app-sqlite/pages.json b/app-sqlite-master/app-sqlite/pages.json new file mode 100644 index 0000000..7d732bb --- /dev/null +++ b/app-sqlite-master/app-sqlite/pages.json @@ -0,0 +1,20 @@ +{ + "pages": [ + //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages + { + "path": "pages/common/study/study", + "style": {} + } + ], + "globalStyle": { + "navigationBarTextStyle": "black", + "navigationBarTitleText": "l-im-app", + "navigationBarBackgroundColor": "#F8F8F8", + "backgroundColor": "#F8F8F8", + "app-plus": { + "titleNView": false, + "scrollIndicator": "none" + } + }, + "uniIdRouter": {} +} diff --git a/app-sqlite-master/app-sqlite/pages/common/study/study.nvue b/app-sqlite-master/app-sqlite/pages/common/study/study.nvue new file mode 100644 index 0000000..cd2d1a9 --- /dev/null +++ b/app-sqlite-master/app-sqlite/pages/common/study/study.nvue @@ -0,0 +1,92 @@ + + + + + diff --git a/app-sqlite-master/app-sqlite/store/modules/sql.js b/app-sqlite-master/app-sqlite/store/modules/sql.js new file mode 100644 index 0000000..451428d --- /dev/null +++ b/app-sqlite-master/app-sqlite/store/modules/sql.js @@ -0,0 +1,194 @@ +let sqlite = { + //创建数据库或者有该数据库就打开 + openSqlite: function() { + //创建数据库或者打开 + //这plus.sqlite只在手机上运行 + return new Promise((resolve, reject) => { + console.log("打开数据库"); + plus.sqlite.openDatabase({ + name: "main", //数据库名称 + path: "_doc/sql.db", //数据库地址,uniapp推荐以下划线为开头,这到底存在哪里去了,我也不清楚,哈哈 + success(e) { + console.log("success") + resolve(e); //成功回调 + }, + fail(e) { + console.log(e) + reject(e); //失败回调 + }, + }); + }); + }, + + getFriendMaxSeq: function(fromId, appId) { + + var sql = ""; + + + sql = + "select ifnull(max(friend_sequence),0) as maxSeq from im_friendship " + + " where app_id = " + + appId + + " and from_id = '" + + fromId + "'"; + return new Promise((resolve, reject) => { + plus.sqlite.selectSql({ + name: "main", + sql: sql, + success(e) { + console.log(e) + resolve(e); + }, + fail(e) { + console.log(e) + reject(e); + }, + }); + }); + }, + + addFriend: function(fromId, toId, remark, status, black, friendSeq, blackSeq, addSource, ex, appId) { + var sql = + " insert into im_friendship(from_id,to_id,remark,status,black,friend_sequence,black_sequence,add_source,extra,app_id) " + + ' values ("' + + fromId + + '","' + + toId + + '","' + + remark + + '","' + + status + + '","' + + black + + '","' + + friendSeq + + '","' + + blackSeq + + '","' + + addSource + + '","' + + 123 + + '","' + + appId + + '")'; + console.log(sql) + plus.sqlite.executeSql({ + name: "main", + sql: sql, + success(e) { + console.log("插入成功") + resolve(e); + }, + fail(e) { + console.log(e) + reject(e); + }, + }); + }, + + bathAddFriend: function(data) { + // console.log(data) + var sql = + " insert into im_friendship(from_id,to_id,remark,status,black,friend_sequence,black_sequence,add_source,extra,app_id) values "; + for (var i = 0; i < data.length; i++) { + var f = data[i]; + sql += ' ("' + + f.fromId + + '","' + + f.toId + + '","' + + f.remark + + '","' + + f.status + + '","' + + f.black + + '","' + + f.friendSequence + + '","' + + f.blackSequence + + '","' + + f.addSource + + '","' + + 123 + + '","' + + f.appId + + '"),'; + } + + sql = sql.substring(0, sql.length - 1); //末尾是& + // console.log(sql) + plus.sqlite.executeSql({ + name: "main", + sql: sql, + success(e) { + console.log("插入成功") + resolve(e); + }, + fail(e) { + console.log(e) + reject(e); + }, + }); + }, + clearAllFriend: function() { + var sql = "delete from im_friendship" + plus.sqlite.executeSql({ + name: "main", + sql: sql, + success(e) { + console.log("清除成功") + resolve(e); + }, + fail(e) { + console.log(e) + reject(e); + }, + }); + }, + // ---------------------------------------------------监听数据库是否开启----------------------------------------------------------------- + //监听数据库是否开启 + isOpen: function(name, path) { + var ss = name || "main"; + var qq = path || "_doc/sql.db"; + //数据库打开了就返回true,否则返回false + var open = plus.sqlite.isOpenDatabase({ + name: ss, + path: qq, + }); + return open; + }, + + // ---------------------------------------------------创建表---------------------------------------------------------------- + + //在该数据库里创建表格, 这一步也必须要! + //下面注释里说的都是说sql:'create table if not exists....这里 + //userInfo是表格名,你也可以写其他的名,不能用数字作为表格名的开头!!! + //括号里是表格的结构,列,这里我写了四列,list,id,gender,avatar这四列 + //list后面大写的英文是自动增加的意思,因为表格里的每一行必须有唯一标识 + //这sql语句会数据库的应该都看的懂,我是前端菜鸡,所以详细说明以便跟我一样不懂sql的前端看 + //"id" TEXT 意思是这一列放的值为字符串之类的,如果是想存数字之类的就改为INTEGER + //数据库不能存对象,数组 + //创建 9、定位表(d_location) + createTable: function() { + return new Promise((resolve, reject) => { + //创建表格在executeSql方法里写 + plus.sqlite.executeSql({ + name: "main", + //表格创建或者打开,后面为表格结构 + sql: "create table if not exists im_friendship(\"from_id\" text(50) NOT NULL,\"to_id\" text(50),\"app_id\" INTEGER(10) NOT NULL,\"remark\" TEXT(50),\"status\" int(5),\"black\" int(5),\"friend_sequence\" bigint(20),\"black_sequence\" bigint(20),\"add_source\" TEXT(20),\"extra\" TEXT(2000),PRIMARY KEY (\"app_id\", \"from_id\", \"to_id\"))", + success(e) { + console.log("创建成功") + resolve(e); + }, + fail(e) { + console.log(e) + console.log("创建失败") + reject(e); + }, + }); + }); + } +}; + +//把这些方法导出去 +export default sqlite; diff --git a/app-sqlite-master/app-sqlite/uni.scss b/app-sqlite-master/app-sqlite/uni.scss new file mode 100644 index 0000000..a05adb4 --- /dev/null +++ b/app-sqlite-master/app-sqlite/uni.scss @@ -0,0 +1,76 @@ +/** + * 这里是uni-app内置的常用样式变量 + * + * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量 + * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App + * + */ + +/** + * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能 + * + * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件 + */ + +/* 颜色变量 */ + +/* 行为相关颜色 */ +$uni-color-primary: #007aff; +$uni-color-success: #4cd964; +$uni-color-warning: #f0ad4e; +$uni-color-error: #dd524d; + +/* 文字基本颜色 */ +$uni-text-color:#333;//基本色 +$uni-text-color-inverse:#fff;//反色 +$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息 +$uni-text-color-placeholder: #808080; +$uni-text-color-disable:#c0c0c0; + +/* 背景颜色 */ +$uni-bg-color:#ffffff; +$uni-bg-color-grey:#f8f8f8; +$uni-bg-color-hover:#f1f1f1;//点击状态颜色 +$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色 + +/* 边框颜色 */ +$uni-border-color:#c8c7cc; + +/* 尺寸变量 */ + +/* 文字尺寸 */ +$uni-font-size-sm:12px; +$uni-font-size-base:14px; +$uni-font-size-lg:16; + +/* 图片尺寸 */ +$uni-img-size-sm:20px; +$uni-img-size-base:26px; +$uni-img-size-lg:40px; + +/* Border Radius */ +$uni-border-radius-sm: 2px; +$uni-border-radius-base: 3px; +$uni-border-radius-lg: 6px; +$uni-border-radius-circle: 50%; + +/* 水平间距 */ +$uni-spacing-row-sm: 5px; +$uni-spacing-row-base: 10px; +$uni-spacing-row-lg: 15px; + +/* 垂直间距 */ +$uni-spacing-col-sm: 4px; +$uni-spacing-col-base: 8px; +$uni-spacing-col-lg: 12px; + +/* 透明度 */ +$uni-opacity-disabled: 0.3; // 组件禁用态的透明度 + +/* 文章场景相关 */ +$uni-color-title: #2C405A; // 文章标题颜色 +$uni-font-size-title:20px; +$uni-color-subtitle: #555555; // 二级标题颜色 +$uni-font-size-subtitle:26px; +$uni-color-paragraph: #3F536E; // 文章段落颜色 +$uni-font-size-paragraph:15px; diff --git a/chapter-3-code-master/chapter-3-code/.gitignore b/chapter-3-code-master/chapter-3-code/.gitignore new file mode 100644 index 0000000..5fa1743 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/.gitignore @@ -0,0 +1,4 @@ +/.idea +/logs +/im-service/target +/im-common/target diff --git a/chapter-3-code-master/chapter-3-code/README.md b/chapter-3-code-master/chapter-3-code/README.md new file mode 100644 index 0000000..e69de29 diff --git a/chapter-3-code-master/chapter-3-code/im-common/pom.xml b/chapter-3-code-master/chapter-3-code/im-common/pom.xml new file mode 100644 index 0000000..f13bea3 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-common/pom.xml @@ -0,0 +1,52 @@ + + + + im-system + com.lld + 1.0.0-SNAPSHOT + + 4.0.0 + + common + + + 1.8 + + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-logging + + + + + + org.apache.httpcomponents + httpclient + + + + + org.apache.commons + commons-lang3 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + \ No newline at end of file diff --git a/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/BaseErrorCode.java b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/BaseErrorCode.java new file mode 100644 index 0000000..d0b3e1e --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/BaseErrorCode.java @@ -0,0 +1,31 @@ +package com.lld.im.common; + + +import com.lld.im.common.exception.ApplicationExceptionEnum; + + +public enum BaseErrorCode implements ApplicationExceptionEnum { + + SUCCESS(200,"success"), + SYSTEM_ERROR(90000,"服务器内部错误,请联系管理员"), + PARAMETER_ERROR(90001,"参数校验错误"), + + + ; + + private int code; + private String error; + + BaseErrorCode(int code, String error){ + this.code = code; + this.error = error; + } + public int getCode() { + return this.code; + } + + public String getError() { + return this.error; + } + +} diff --git a/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/ClientType.java b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/ClientType.java new file mode 100644 index 0000000..244194b --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/ClientType.java @@ -0,0 +1,34 @@ +package com.lld.im.common; + +/** + * @author: Chackylee + * @description: + **/ +public enum ClientType { + + WEBAPI(0,"webApi"), + WEB(1,"web"), + IOS(2,"ios"), + ANDROID(3,"android"), + WINDOWS(4,"windows"), + MAC(5,"mac"), + ; + + private int code; + private String error; + + ClientType(int code, String error){ + this.code = code; + this.error = error; + } + public int getCode() { + return this.code; + } + + public String getError() { + return this.error; + } + + + +} diff --git a/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/ResponseVO.java b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/ResponseVO.java new file mode 100644 index 0000000..7917aba --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/ResponseVO.java @@ -0,0 +1,66 @@ +package com.lld.im.common; + +import com.lld.im.common.exception.ApplicationExceptionEnum; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ResponseVO { + + private int code; + + private String msg; + + private T data; + + public static ResponseVO successResponse(Object data) { + return new ResponseVO(200, "success", data); + } + + public static ResponseVO successResponse() { + return new ResponseVO(200, "success"); + } + + public static ResponseVO errorResponse() { + return new ResponseVO(500, "系统内部异常"); + } + + public static ResponseVO errorResponse(int code, String msg) { + return new ResponseVO(code, msg); + } + + public static ResponseVO errorResponse(ApplicationExceptionEnum enums) { + return new ResponseVO(enums.getCode(), enums.getError()); + } + + public boolean isOk(){ + return this.code == 200; + } + + + public ResponseVO(int code, String msg) { + this.code = code; + this.msg = msg; +// this.data = null; + } + + public ResponseVO success(){ + this.code = 200; + this.msg = "success"; + return this; + } + + public ResponseVO success(T data){ + this.code = 200; + this.msg = "success"; + this.data = data; + return this; + } + +} diff --git a/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/AllowFriendTypeEnum.java b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/AllowFriendTypeEnum.java new file mode 100644 index 0000000..17093c0 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/AllowFriendTypeEnum.java @@ -0,0 +1,27 @@ +package com.lld.im.common.enums; + +public enum AllowFriendTypeEnum { + + /** + * 验证 + */ + NEED(2), + + /** + * 不需要验证 + */ + NOT_NEED(1), + + ; + + + private int code; + + AllowFriendTypeEnum(int code){ + this.code=code; + } + + public int getCode() { + return code; + } +} diff --git a/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/ApproverFriendRequestStatusEnum.java b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/ApproverFriendRequestStatusEnum.java new file mode 100644 index 0000000..d4998d8 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/ApproverFriendRequestStatusEnum.java @@ -0,0 +1,22 @@ +package com.lld.im.common.enums; + +public enum ApproverFriendRequestStatusEnum { + + /** + * 1 同意;2 拒绝。 + */ + AGREE(1), + + REJECT(2), + ; + + private int code; + + ApproverFriendRequestStatusEnum(int code){ + this.code=code; + } + + public int getCode() { + return code; + } +} diff --git a/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/CheckFriendShipTypeEnum.java b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/CheckFriendShipTypeEnum.java new file mode 100644 index 0000000..8c69d6c --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/CheckFriendShipTypeEnum.java @@ -0,0 +1,22 @@ +package com.lld.im.common.enums; + +public enum CheckFriendShipTypeEnum { + + /** + * 1 单方校验;2双方校验。 + */ + SINGLE(1), + + BOTH(2), + ; + + private int type; + + CheckFriendShipTypeEnum(int type){ + this.type=type; + } + + public int getType() { + return type; + } +} diff --git a/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/DelFlagEnum.java b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/DelFlagEnum.java new file mode 100644 index 0000000..2ba3b9e --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/DelFlagEnum.java @@ -0,0 +1,22 @@ +package com.lld.im.common.enums; + +public enum DelFlagEnum { + + /** + * 0 正常;1 删除。 + */ + NORMAL(0), + + DELETE(1), + ; + + private int code; + + DelFlagEnum(int code){ + this.code=code; + } + + public int getCode() { + return code; + } +} diff --git a/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/FriendShipErrorCode.java b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/FriendShipErrorCode.java new file mode 100644 index 0000000..3c0e25c --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/FriendShipErrorCode.java @@ -0,0 +1,57 @@ +package com.lld.im.common.enums; + +import com.lld.im.common.exception.ApplicationExceptionEnum; + +public enum FriendShipErrorCode implements ApplicationExceptionEnum { + + + IMPORT_SIZE_BEYOND(30000,"导入數量超出上限"), + + ADD_FRIEND_ERROR(30001,"添加好友失败"), + + TO_IS_YOUR_FRIEND(30002,"对方已经是你的好友"), + + TO_IS_NOT_YOUR_FRIEND(30003,"对方不是你的好友"), + + FRIEND_IS_DELETED(30004,"好友已被删除"), + + FRIEND_IS_BLACK(30006,"好友已被拉黑"), + + TARGET_IS_BLACK_YOU(30007,"对方把你拉黑"), + + REPEATSHIP_IS_NOT_EXIST(30008,"关系链记录不存在"), + + ADD_BLACK_ERROR(30009,"添加黑名單失败"), + + FRIEND_IS_NOT_YOUR_BLACK(30010,"好友已經不在你的黑名單内"), + + NOT_APPROVER_OTHER_MAN_REQUEST(30011,"无法审批其他人的好友请求"), + + FRIEND_REQUEST_IS_NOT_EXIST(30012,"好友申请不存在"), + + FRIEND_SHIP_GROUP_CREATE_ERROR(30014,"好友分组创建失败"), + + FRIEND_SHIP_GROUP_IS_EXIST(30015,"好友分组已存在"), + + FRIEND_SHIP_GROUP_IS_NOT_EXIST(30016,"好友分组不存在"), + + + + ; + + private int code; + private String error; + + FriendShipErrorCode(int code, String error){ + this.code = code; + this.error = error; + } + public int getCode() { + return this.code; + } + + public String getError() { + return this.error; + } + +} diff --git a/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/FriendShipStatusEnum.java b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/FriendShipStatusEnum.java new file mode 100644 index 0000000..88f77d9 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/FriendShipStatusEnum.java @@ -0,0 +1,31 @@ +package com.lld.im.common.enums; + +public enum FriendShipStatusEnum { + + /** + * 0未添加 1正常 2删除 + */ + FRIEND_STATUS_NO_FRIEND(0), + + FRIEND_STATUS_NORMAL(1), + + FRIEND_STATUS_DELETE(2), + + /** + * 0未添加 1正常 2删除 + */ + BLACK_STATUS_NORMAL(1), + + BLACK_STATUS_BLACKED(2), + ; + + private int code; + + FriendShipStatusEnum(int code){ + this.code=code; + } + + public int getCode() { + return code; + } +} diff --git a/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/GroupErrorCode.java b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/GroupErrorCode.java new file mode 100644 index 0000000..aa2a2fe --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/GroupErrorCode.java @@ -0,0 +1,66 @@ +package com.lld.im.common.enums; + +import com.lld.im.common.exception.ApplicationExceptionEnum; + +/** + * @author: Chackylee + * @description: + **/ +public enum GroupErrorCode implements ApplicationExceptionEnum { + + GROUP_IS_NOT_EXIST(40000,"群不存在"), + + GROUP_IS_EXIST(40001,"群已存在"), + + GROUP_IS_HAVE_OWNER(40002,"群已存在群主"), + + USER_IS_JOINED_GROUP(40003,"该用户已经进入该群"), + + USER_JOIN_GROUP_ERROR(40004,"群成员添加失败"), + + GROUP_MEMBER_IS_BEYOND(40005,"群成员已达到上限"), + + MEMBER_IS_NOT_JOINED_GROUP(40006,"该用户不在群内"), + + THIS_OPERATE_NEED_MANAGER_ROLE(40007,"该操作只允许群主/管理员操作"), + + THIS_OPERATE_NEED_APPMANAGER_ROLE(40008,"该操作只允许APP管理员操作"), + + THIS_OPERATE_NEED_OWNER_ROLE(40009,"该操作只允许群主操作"), + + GROUP_OWNER_IS_NOT_REMOVE(40010,"群主无法移除"), + + UPDATE_GROUP_BASE_INFO_ERROR(40011,"更新群信息失败"), + + THIS_GROUP_IS_MUTE(40012,"该群禁止发言"), + + IMPORT_GROUP_ERROR(40013,"导入群组失败"), + + THIS_OPERATE_NEED_ONESELF(40014,"该操作只允许自己操作"), + + PRIVATE_GROUP_CAN_NOT_DESTORY(40015,"私有群不允许解散"), + + PUBLIC_GROUP_MUST_HAVE_OWNER(40016,"公开群必须指定群主"), + + GROUP_MEMBER_IS_SPEAK(40017,"群成员被禁言"), + + GROUP_IS_DESTROY(40018,"群组已解散"), + + ; + + private int code; + private String error; + + GroupErrorCode(int code, String error){ + this.code = code; + this.error = error; + } + public int getCode() { + return this.code; + } + + public String getError() { + return this.error; + } + +} diff --git a/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/GroupMemberRoleEnum.java b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/GroupMemberRoleEnum.java new file mode 100644 index 0000000..3326b34 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/GroupMemberRoleEnum.java @@ -0,0 +1,50 @@ +package com.lld.im.common.enums; + +public enum GroupMemberRoleEnum { + + /** + * 普通成员 + */ + ORDINARY(0), + + /** + * 管理员 + */ + MAMAGER(1), + + /** + * 群主 + */ + OWNER(2), + + /** + * 离开 + */ + LEAVE(3); + ; + + + private int code; + + /** + * 不能用 默认的 enumType b= enumType.values()[i]; 因为本枚举是类形式封装 + * @param ordinal + * @return + */ + public static GroupMemberRoleEnum getItem(int ordinal) { + for (int i = 0; i < GroupMemberRoleEnum.values().length; i++) { + if (GroupMemberRoleEnum.values()[i].getCode() == ordinal) { + return GroupMemberRoleEnum.values()[i]; + } + } + return null; + } + + GroupMemberRoleEnum(int code){ + this.code=code; + } + + public int getCode() { + return code; + } +} diff --git a/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/GroupMuteTypeEnum.java b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/GroupMuteTypeEnum.java new file mode 100644 index 0000000..d518113 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/GroupMuteTypeEnum.java @@ -0,0 +1,43 @@ +package com.lld.im.common.enums; + +public enum GroupMuteTypeEnum { + + /** + * 是否全员禁言,0 不禁言;1 全员禁言。 + */ + NOT_MUTE(0), + + + MUTE(1), + + ; + + /** + * 不能用 默认的 enumType b= enumType.values()[i]; 因为本枚举是类形式封装 + * @param ordinal + * @return + */ + public static GroupMuteTypeEnum getEnum(Integer ordinal) { + + if(ordinal == null){ + return null; + } + + for (int i = 0; i < GroupMuteTypeEnum.values().length; i++) { + if (GroupMuteTypeEnum.values()[i].getCode() == ordinal) { + return GroupMuteTypeEnum.values()[i]; + } + } + return null; + } + + private int code; + + GroupMuteTypeEnum(int code){ + this.code=code; + } + + public int getCode() { + return code; + } +} diff --git a/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/GroupStatusEnum.java b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/GroupStatusEnum.java new file mode 100644 index 0000000..338868e --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/GroupStatusEnum.java @@ -0,0 +1,42 @@ +package com.lld.im.common.enums; + +public enum GroupStatusEnum { + + /** + * 1正常 2解散 其他待定比如封禁... + */ + NORMAL(1), + + DESTROY(2), + + ; + + /** + * 不能用 默认的 enumType b= enumType.values()[i]; 因为本枚举是类形式封装 + * @param ordinal + * @return + */ + public static GroupStatusEnum getEnum(Integer ordinal) { + + if(ordinal == null){ + return null; + } + + for (int i = 0; i < GroupStatusEnum.values().length; i++) { + if (GroupStatusEnum.values()[i].getCode() == ordinal) { + return GroupStatusEnum.values()[i]; + } + } + return null; + } + + private int code; + + GroupStatusEnum(int code){ + this.code=code; + } + + public int getCode() { + return code; + } +} diff --git a/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/GroupTypeEnum.java b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/GroupTypeEnum.java new file mode 100644 index 0000000..be7a908 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/GroupTypeEnum.java @@ -0,0 +1,42 @@ +package com.lld.im.common.enums; + +public enum GroupTypeEnum { + + /** + * 群类型 1私有群(类似微信) 2公开群(类似qq) + */ + PRIVATE(1), + + PUBLIC(2), + + ; + + /** + * 不能用 默认的 enumType b= enumType.values()[i]; 因为本枚举是类形式封装 + * @param ordinal + * @return + */ + public static GroupTypeEnum getEnum(Integer ordinal) { + + if(ordinal == null){ + return null; + } + + for (int i = 0; i < GroupTypeEnum.values().length; i++) { + if (GroupTypeEnum.values()[i].getCode() == ordinal) { + return GroupTypeEnum.values()[i]; + } + } + return null; + } + + private int code; + + GroupTypeEnum(int code){ + this.code=code; + } + + public int getCode() { + return code; + } +} diff --git a/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/UserErrorCode.java b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/UserErrorCode.java new file mode 100644 index 0000000..76c2cd0 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/UserErrorCode.java @@ -0,0 +1,30 @@ +package com.lld.im.common.enums; + +import com.lld.im.common.exception.ApplicationExceptionEnum; + +public enum UserErrorCode implements ApplicationExceptionEnum { + + + IMPORT_SIZE_BEYOND(20000,"导入數量超出上限"), + USER_IS_NOT_EXIST(20001,"用户不存在"), + SERVER_GET_USER_ERROR(20002,"服务获取用户失败"), + MODIFY_USER_ERROR(20003,"更新用户失败"), + SERVER_NOT_AVAILABLE(71000, "没有可用的服务"), + ; + + private int code; + private String error; + + UserErrorCode(int code, String error){ + this.code = code; + this.error = error; + } + public int getCode() { + return this.code; + } + + public String getError() { + return this.error; + } + +} diff --git a/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/UserForbiddenFlagEnum.java b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/UserForbiddenFlagEnum.java new file mode 100644 index 0000000..bc0fffc --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/UserForbiddenFlagEnum.java @@ -0,0 +1,22 @@ +package com.lld.im.common.enums; + +public enum UserForbiddenFlagEnum { + + /** + * 0 正常;1 禁用。 + */ + NORMAL(0), + + FORBIBBEN(1), + ; + + private int code; + + UserForbiddenFlagEnum(int code){ + this.code=code; + } + + public int getCode() { + return code; + } +} diff --git a/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/UserSilentFlagEnum.java b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/UserSilentFlagEnum.java new file mode 100644 index 0000000..3e5ccb3 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/enums/UserSilentFlagEnum.java @@ -0,0 +1,22 @@ +package com.lld.im.common.enums; + +public enum UserSilentFlagEnum { + + /** + * 0 正常;1 禁言。 + */ + NORMAL(0), + + MUTE(1), + ; + + private int code; + + UserSilentFlagEnum(int code){ + this.code=code; + } + + public int getCode() { + return code; + } +} diff --git a/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/exception/ApplicationException.java b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/exception/ApplicationException.java new file mode 100644 index 0000000..12bf555 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/exception/ApplicationException.java @@ -0,0 +1,44 @@ +package com.lld.im.common.exception; + +/** + * @author: Chackylee + * @description: + **/ +public class ApplicationException extends RuntimeException { + + private int code; + + private String error; + + + public ApplicationException(int code, String message) { + super(message); + this.code = code; + this.error = message; + } + + public ApplicationException(ApplicationExceptionEnum exceptionEnum) { + super(exceptionEnum.getError()); + this.code = exceptionEnum.getCode(); + this.error = exceptionEnum.getError(); + } + + public int getCode() { + return code; + } + + public String getError() { + return error; + } + + + /** + * avoid the expensive and useless stack trace for api exceptions + * @see Throwable#fillInStackTrace() + */ + @Override + public Throwable fillInStackTrace() { + return this; + } + +} diff --git a/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/exception/ApplicationExceptionEnum.java b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/exception/ApplicationExceptionEnum.java new file mode 100644 index 0000000..af1df84 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/exception/ApplicationExceptionEnum.java @@ -0,0 +1,8 @@ +package com.lld.im.common.exception; + +public interface ApplicationExceptionEnum { + + int getCode(); + + String getError(); +} diff --git a/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/model/ClientInfo.java b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/model/ClientInfo.java new file mode 100644 index 0000000..0116c79 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/model/ClientInfo.java @@ -0,0 +1,25 @@ +package com.lld.im.common.model; + +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author: Chackylee + * @description: + **/ +@Data +@NoArgsConstructor +public class ClientInfo { + + private Integer appId; + + private Integer clientType; + + private String imei; + + public ClientInfo(Integer appId, Integer clientType, String imei) { + this.appId = appId; + this.clientType = clientType; + this.imei = imei; + } +} diff --git a/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/model/RequestBase.java b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/model/RequestBase.java new file mode 100644 index 0000000..12ff3fc --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/model/RequestBase.java @@ -0,0 +1,19 @@ +package com.lld.im.common.model; + +import lombok.Data; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Data +public class RequestBase { + private Integer appId; + + private String operater; + + private Integer clientType; + + private String imei; +} diff --git a/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/model/UserClientDto.java b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/model/UserClientDto.java new file mode 100644 index 0000000..1dcc36d --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/model/UserClientDto.java @@ -0,0 +1,21 @@ +package com.lld.im.common.model; + +import lombok.Data; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Data +public class UserClientDto { + + private Integer appId; + + private Integer clientType; + + private String userId; + + private String imei; + +} diff --git a/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/model/UserSession.java b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/model/UserSession.java new file mode 100644 index 0000000..907c5aa --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-common/src/main/java/com/lld/im/common/model/UserSession.java @@ -0,0 +1,37 @@ +package com.lld.im.common.model; + +import lombok.Data; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Data +public class UserSession { + + private String userId; + + /** + * 应用ID + */ + private Integer appId; + + /** + * 端的标识 + */ + private Integer clientType; + + //sdk 版本号 + private Integer version; + + //连接状态 1=在线 2=离线 + private Integer connectState; + + private Integer brokerId; + + private String brokerHost; + + private String imei; + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/im-service.iml b/chapter-3-code-master/chapter-3-code/im-service/im-service.iml new file mode 100644 index 0000000..e69de29 diff --git a/chapter-3-code-master/chapter-3-code/im-service/pom.xml b/chapter-3-code-master/chapter-3-code/im-service/pom.xml new file mode 100644 index 0000000..637de92 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/pom.xml @@ -0,0 +1,101 @@ + + + + im-system + com.lld + 1.0.0-SNAPSHOT + + 4.0.0 + + lld-im-service project + + 1.8 + + + service + + + + + + + + + + org.springframework.boot + spring-boot-starter-validation + + + + + + + + + + + + + + + + org.springframework.boot + spring-boot-starter-web + + + + + + + + + + + cn.hutool + hutool-all + + + + + org.springframework.boot + spring-boot-starter-jdbc + + + + + mysql + mysql-connector-java + runtime + + + + + com.baomidou + mybatis-plus-boot-starter + + + com.github.jeffreyning + mybatisplus-plus + 1.5.1-RELEASE + + + + + com.lld + common + 1.0.0-SNAPSHOT + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + \ No newline at end of file diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/Application.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/Application.java new file mode 100644 index 0000000..272d021 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/Application.java @@ -0,0 +1,20 @@ +package com.lld.im.service; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +@MapperScan("com.lld.im.service.*.dao.mapper") +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + + +} + + + + diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/config/BeanConfig.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/config/BeanConfig.java new file mode 100644 index 0000000..c07d827 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/config/BeanConfig.java @@ -0,0 +1,13 @@ +package com.lld.im.service.config; + +import org.springframework.context.annotation.Configuration; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Configuration +public class BeanConfig { + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/config/WebConfig.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/config/WebConfig.java new file mode 100644 index 0000000..b6bd571 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/config/WebConfig.java @@ -0,0 +1,26 @@ +package com.lld.im.service.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Configuration +public class WebConfig implements WebMvcConfigurer { + + + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedOrigins("*") + .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS") + .allowCredentials(true) + .maxAge(3600) + .allowedHeaders("*"); + } + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/exception/GlobalExceptionHandler.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..e5a5657 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/exception/GlobalExceptionHandler.java @@ -0,0 +1,110 @@ +package com.lld.im.service.exception; + +import com.lld.im.common.BaseErrorCode; +import com.lld.im.common.ResponseVO; +import com.lld.im.common.exception.ApplicationException; +import org.hibernate.validator.internal.engine.path.PathImpl; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.validation.FieldError; +import org.springframework.validation.ObjectError; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import javax.validation.ConstraintViolation; +import javax.validation.ConstraintViolationException; +import java.util.Set; + +@RestControllerAdvice +public class GlobalExceptionHandler { + + + @ExceptionHandler(value=Exception.class) + @ResponseBody + public ResponseVO unknowException(Exception e){ + e.printStackTrace(); + ResponseVO resultBean =new ResponseVO(); + resultBean.setCode(BaseErrorCode.SYSTEM_ERROR.getCode()); + resultBean.setMsg(BaseErrorCode.SYSTEM_ERROR.getError()); + /** + * 未知异常的话,这里写逻辑,发邮件,发短信都可以、、 + */ + return resultBean; + } + + + /** + * Validator 参数校验异常处理 + * + * @param ex + * @return + */ + @ExceptionHandler(value = ConstraintViolationException.class) + @ResponseBody + public Object handleMethodArgumentNotValidException(ConstraintViolationException ex) { + + Set> constraintViolations = ex.getConstraintViolations(); + ResponseVO resultBean =new ResponseVO(); + resultBean.setCode(BaseErrorCode.PARAMETER_ERROR.getCode()); + for (ConstraintViolation constraintViolation : constraintViolations) { + PathImpl pathImpl = (PathImpl) constraintViolation.getPropertyPath(); + // 读取参数字段,constraintViolation.getMessage() 读取验证注解中的message值 + String paramName = pathImpl.getLeafNode().getName(); + String message = "参数{".concat(paramName).concat("}").concat(constraintViolation.getMessage()); + resultBean.setMsg(message); + + return resultBean; + } + resultBean.setMsg(BaseErrorCode.PARAMETER_ERROR.getError() + ex.getMessage()); + return resultBean; + } + + @ExceptionHandler(ApplicationException.class) + @ResponseBody + public Object applicationExceptionHandler(ApplicationException e) { + // 使用公共的结果类封装返回结果, 这里我指定状态码为 + ResponseVO resultBean =new ResponseVO(); + resultBean.setCode(e.getCode()); + resultBean.setMsg(e.getError()); + return resultBean; + } + + /** + * Validator 参数校验异常处理 + * + * @param ex + * @return + */ + @ExceptionHandler(value = BindException.class) + @ResponseBody + public Object handleException2(BindException ex) { + FieldError err = ex.getFieldError(); + String message = "参数{".concat(err.getField()).concat("}").concat(err.getDefaultMessage()); + ResponseVO resultBean =new ResponseVO(); + resultBean.setCode(BaseErrorCode.PARAMETER_ERROR.getCode()); + resultBean.setMsg(message); + return resultBean; + + + } + + //json格式 + @ExceptionHandler(value = MethodArgumentNotValidException.class) + @ResponseBody + public Object handleException1(MethodArgumentNotValidException ex) { + StringBuilder errorMsg = new StringBuilder(); + BindingResult re = ex.getBindingResult(); + for (ObjectError error : re.getAllErrors()) { + errorMsg.append(error.getDefaultMessage()).append(","); + } + errorMsg.delete(errorMsg.length() - 1, errorMsg.length()); + + ResponseVO resultBean =new ResponseVO(); + resultBean.setCode(BaseErrorCode.PARAMETER_ERROR.getCode()); + resultBean.setMsg(BaseErrorCode.PARAMETER_ERROR.getError() + " : " + errorMsg.toString()); + return resultBean; + } + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/controller/ImFriendShipController.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/controller/ImFriendShipController.java new file mode 100644 index 0000000..80524c4 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/controller/ImFriendShipController.java @@ -0,0 +1,86 @@ +package com.lld.im.service.friendship.controller; + +import com.lld.im.common.ResponseVO; +import com.lld.im.service.friendship.model.req.*; +import com.lld.im.service.friendship.service.ImFriendService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("v1/friendship") +public class ImFriendShipController { + + @Autowired + ImFriendService imFriendShipService; + + @RequestMapping("/importFriendShip") + public ResponseVO importFriendShip(@RequestBody @Validated ImporFriendShipReq req, Integer appId){ + req.setAppId(appId); + return imFriendShipService.importFriendShip(req); + } + + @RequestMapping("/addFriend") + public ResponseVO addFriend(@RequestBody @Validated AddFriendReq req, Integer appId){ + req.setAppId(appId); + return imFriendShipService.addFriend(req); + } + + @RequestMapping("/updateFriend") + public ResponseVO updateFriend(@RequestBody @Validated UpdateFriendReq req, Integer appId){ + req.setAppId(appId); + return imFriendShipService.updateFriend(req); + } + + @RequestMapping("/deleteFriend") + public ResponseVO deleteFriend(@RequestBody @Validated DeleteFriendReq req, Integer appId){ + req.setAppId(appId); + return imFriendShipService.deleteFriend(req); + } + + @RequestMapping("/deleteAllFriend") + public ResponseVO deleteAllFriend(@RequestBody @Validated DeleteFriendReq req, Integer appId){ + req.setAppId(appId); + return imFriendShipService.deleteAllFriend(req); + } + + @RequestMapping("/getAllFriendShip") + public ResponseVO getAllFriendShip(@RequestBody @Validated GetAllFriendShipReq req, Integer appId){ + req.setAppId(appId); + return imFriendShipService.getAllFriendShip(req); + } + + @RequestMapping("/getRelation") + public ResponseVO getRelation(@RequestBody @Validated GetRelationReq req, Integer appId){ + req.setAppId(appId); + return imFriendShipService.getRelation(req); + } + + @RequestMapping("/checkFriend") + public ResponseVO checkFriend(@RequestBody @Validated CheckFriendShipReq req, Integer appId){ + req.setAppId(appId); + return imFriendShipService.checkFriendship(req); + } + + @RequestMapping("/addBlack") + public ResponseVO addBlack(@RequestBody @Validated AddFriendShipBlackReq req, Integer appId){ + req.setAppId(appId); + return imFriendShipService.addBlack(req); + } + + @RequestMapping("/deleteBlack") + public ResponseVO deleteBlack(@RequestBody @Validated DeleteBlackReq req, Integer appId){ + req.setAppId(appId); + return imFriendShipService.deleteBlack(req); + } + + @RequestMapping("/checkBlck") + public ResponseVO checkBlck(@RequestBody @Validated CheckFriendShipReq req, Integer appId){ + req.setAppId(appId); + return imFriendShipService.checkBlck(req); + } + + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/controller/ImFriendShipGroupController.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/controller/ImFriendShipGroupController.java new file mode 100644 index 0000000..9a3ced9 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/controller/ImFriendShipGroupController.java @@ -0,0 +1,56 @@ +package com.lld.im.service.friendship.controller; + +import com.lld.im.common.ResponseVO; +import com.lld.im.service.friendship.model.req.AddFriendShipGroupMemberReq; +import com.lld.im.service.friendship.model.req.AddFriendShipGroupReq; +import com.lld.im.service.friendship.model.req.DeleteFriendShipGroupMemberReq; +import com.lld.im.service.friendship.model.req.DeleteFriendShipGroupReq; +import com.lld.im.service.friendship.service.ImFriendShipGroupMemberService; +import com.lld.im.service.friendship.service.ImFriendShipGroupService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author: Chackylee + * @description: + **/ +@RestController +@RequestMapping("v1/friendship/group") +public class ImFriendShipGroupController { + + @Autowired + ImFriendShipGroupService imFriendShipGroupService; + + @Autowired + ImFriendShipGroupMemberService imFriendShipGroupMemberService; + + + @RequestMapping("/add") + public ResponseVO add(@RequestBody @Validated AddFriendShipGroupReq req, Integer appId) { + req.setAppId(appId); + return imFriendShipGroupService.addGroup(req); + } + + @RequestMapping("/del") + public ResponseVO del(@RequestBody @Validated DeleteFriendShipGroupReq req, Integer appId) { + req.setAppId(appId); + return imFriendShipGroupService.deleteGroup(req); + } + + @RequestMapping("/member/add") + public ResponseVO memberAdd(@RequestBody @Validated AddFriendShipGroupMemberReq req, Integer appId) { + req.setAppId(appId); + return imFriendShipGroupMemberService.addGroupMember(req); + } + + @RequestMapping("/member/del") + public ResponseVO memberdel(@RequestBody @Validated DeleteFriendShipGroupMemberReq req, Integer appId) { + req.setAppId(appId); + return imFriendShipGroupMemberService.delGroupMember(req); + } + + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/controller/ImFriendShipRequestController.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/controller/ImFriendShipRequestController.java new file mode 100644 index 0000000..57ad0b8 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/controller/ImFriendShipRequestController.java @@ -0,0 +1,42 @@ +package com.lld.im.service.friendship.controller; + +import com.lld.im.common.ResponseVO; +import com.lld.im.service.friendship.model.req.ApproverFriendRequestReq; +import com.lld.im.service.friendship.model.req.GetFriendShipRequestReq; +import com.lld.im.service.friendship.model.req.ReadFriendShipRequestReq; +import com.lld.im.service.friendship.service.ImFriendShipRequestService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + + +@RestController +@RequestMapping("v1/friendshipRequest") +public class ImFriendShipRequestController { + + @Autowired + ImFriendShipRequestService imFriendShipRequestService; + + @RequestMapping("/approveFriendRequest") + public ResponseVO approveFriendRequest(@RequestBody @Validated + ApproverFriendRequestReq req, Integer appId, String identifier){ + req.setAppId(appId); + req.setOperater(identifier); + return imFriendShipRequestService.approverFriendRequest(req); + } + @RequestMapping("/getFriendRequest") + public ResponseVO getFriendRequest(@RequestBody @Validated GetFriendShipRequestReq req, Integer appId){ + req.setAppId(appId); + return imFriendShipRequestService.getFriendRequest(req.getFromId(),req.getAppId()); + } + + @RequestMapping("/readFriendShipRequestReq") + public ResponseVO readFriendShipRequestReq(@RequestBody @Validated ReadFriendShipRequestReq req, Integer appId){ + req.setAppId(appId); + return imFriendShipRequestService.readFriendShipRequestReq(req); + } + + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/dao/ImFriendShipEntity.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/dao/ImFriendShipEntity.java new file mode 100644 index 0000000..bc98d52 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/dao/ImFriendShipEntity.java @@ -0,0 +1,46 @@ +package com.lld.im.service.friendship.dao; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.github.jeffreyning.mybatisplus.anno.AutoMap; +import lombok.Data; + +/** + * @author: Chackylee + * @description: + **/ + +@Data +@TableName("im_friendship") +@AutoMap +public class ImFriendShipEntity { + + @TableField(value = "app_id") + private Integer appId; + + @TableField(value = "from_id") + private String fromId; + + @TableField(value = "to_id") + private String toId; + /** 备注*/ + private String remark; + /** 状态 1正常 2删除*/ + private Integer status; + /** 状态 1正常 2拉黑*/ + private Integer black; +// @TableField(updateStrategy = FieldStrategy.IGNORED) + private Long createTime; + /** 好友关系序列号*/ +// @TableField(updateStrategy = FieldStrategy.IGNORED) + private Long friendSequence; + + /** 黑名单关系序列号*/ + private Long blackSequence; + /** 好友来源*/ +// @TableField(updateStrategy = FieldStrategy.IGNORED) + private String addSource; + + private String extra; + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/dao/ImFriendShipGroupEntity.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/dao/ImFriendShipGroupEntity.java new file mode 100644 index 0000000..2319f3f --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/dao/ImFriendShipGroupEntity.java @@ -0,0 +1,32 @@ +package com.lld.im.service.friendship.dao; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +@Data +@TableName("im_friendship_group") +public class ImFriendShipGroupEntity { + + @TableId(value = "group_id",type = IdType.AUTO) + private Long groupId; + + private String fromId; + + private Integer appId; + + private String groupName; + /** 备注*/ + private Long createTime; + + /** 备注*/ + private Long updateTime; + + /** 序列号*/ + private Long sequence; + + private int delFlag; + + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/dao/ImFriendShipGroupMemberEntity.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/dao/ImFriendShipGroupMemberEntity.java new file mode 100644 index 0000000..c8cf26b --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/dao/ImFriendShipGroupMemberEntity.java @@ -0,0 +1,17 @@ +package com.lld.im.service.friendship.dao; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + + +@Data +@TableName("im_friendship_group_member") +public class ImFriendShipGroupMemberEntity { + + @TableId(value = "group_id") + private Long groupId; + + private String toId; + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/dao/ImFriendShipRequestEntity.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/dao/ImFriendShipRequestEntity.java new file mode 100644 index 0000000..c2de949 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/dao/ImFriendShipRequestEntity.java @@ -0,0 +1,49 @@ +package com.lld.im.service.friendship.dao; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + + +@Data +@TableName("im_friendship_request") +public class ImFriendShipRequestEntity { + + @TableId(type = IdType.AUTO) + private Long id; + + private Integer appId; + + private String fromId; + + private String toId; + /** 备注*/ +// @TableField(updateStrategy = FieldStrategy.IGNORED) + private String remark; + + //是否已读 1已读 + private Integer readStatus; + + /** 好友来源*/ +// @TableField(updateStrategy = FieldStrategy.IGNORED) + private String addSource; + +// @TableField(updateStrategy = FieldStrategy.IGNORED) + private String addWording; + + //审批状态 1同意 2拒绝 + private Integer approveStatus; + +// @TableField(updateStrategy = FieldStrategy.IGNORED) + private Long createTime; + + private Long updateTime; + + /** 序列号*/ + private Long sequence; + + + + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/dao/mapper/ImFriendShipGroupMapper.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/dao/mapper/ImFriendShipGroupMapper.java new file mode 100644 index 0000000..b621a23 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/dao/mapper/ImFriendShipGroupMapper.java @@ -0,0 +1,9 @@ +package com.lld.im.service.friendship.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lld.im.service.friendship.dao.ImFriendShipGroupEntity; + +public interface ImFriendShipGroupMapper extends BaseMapper { + + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/dao/mapper/ImFriendShipGroupMemberMapper.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/dao/mapper/ImFriendShipGroupMemberMapper.java new file mode 100644 index 0000000..b477445 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/dao/mapper/ImFriendShipGroupMemberMapper.java @@ -0,0 +1,9 @@ +package com.lld.im.service.friendship.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lld.im.service.friendship.dao.ImFriendShipGroupMemberEntity; + +public interface ImFriendShipGroupMemberMapper extends BaseMapper { + + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/dao/mapper/ImFriendShipMapper.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/dao/mapper/ImFriendShipMapper.java new file mode 100644 index 0000000..87e0430 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/dao/mapper/ImFriendShipMapper.java @@ -0,0 +1,91 @@ +package com.lld.im.service.friendship.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lld.im.service.friendship.dao.ImFriendShipEntity; +import com.lld.im.service.friendship.model.req.CheckFriendShipReq; +import com.lld.im.service.friendship.model.resp.CheckFriendShipResp; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +@Mapper +public interface ImFriendShipMapper extends BaseMapper { + + + + + @Select("") + public List checkFriendShip(CheckFriendShipReq req); + + + @Select("" + ) + List checkFriendShipBoth(CheckFriendShipReq toId); + + + + + + + @Select("" + ) + List checkFriendShipBlack(CheckFriendShipReq req); + + @Select("" + ) + List checkFriendShipBlackBoth(CheckFriendShipReq toId); + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/dao/mapper/ImFriendShipRequestMapper.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/dao/mapper/ImFriendShipRequestMapper.java new file mode 100644 index 0000000..c153dae --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/dao/mapper/ImFriendShipRequestMapper.java @@ -0,0 +1,9 @@ +package com.lld.im.service.friendship.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lld.im.service.friendship.dao.ImFriendShipRequestEntity; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface ImFriendShipRequestMapper extends BaseMapper { +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/AddFriendReq.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/AddFriendReq.java new file mode 100644 index 0000000..cd31d0a --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/AddFriendReq.java @@ -0,0 +1,19 @@ +package com.lld.im.service.friendship.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + + +@Data +public class AddFriendReq extends RequestBase { + + @NotBlank(message = "fromId不能为空") + private String fromId; + + @NotNull(message = "toItem不能为空") + private FriendDto toItem; + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/AddFriendShipBlackReq.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/AddFriendShipBlackReq.java new file mode 100644 index 0000000..69f5017 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/AddFriendShipBlackReq.java @@ -0,0 +1,16 @@ +package com.lld.im.service.friendship.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + + +@Data +public class AddFriendShipBlackReq extends RequestBase { + + @NotBlank(message = "用户id不能为空") + private String fromId; + + private String toId; +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/AddFriendShipGroupMemberReq.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/AddFriendShipGroupMemberReq.java new file mode 100644 index 0000000..4f02bf7 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/AddFriendShipGroupMemberReq.java @@ -0,0 +1,24 @@ +package com.lld.im.service.friendship.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import java.util.List; + + +@Data +public class AddFriendShipGroupMemberReq extends RequestBase { + + @NotBlank(message = "fromId不能为空") + private String fromId; + + @NotBlank(message = "分组名称不能为空") + private String groupName; + + @NotEmpty(message = "请选择用户") + private List toIds; + + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/AddFriendShipGroupReq.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/AddFriendShipGroupReq.java new file mode 100644 index 0000000..ed3ed09 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/AddFriendShipGroupReq.java @@ -0,0 +1,21 @@ +package com.lld.im.service.friendship.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import java.util.List; + + +@Data +public class AddFriendShipGroupReq extends RequestBase { + + @NotBlank(message = "fromId不能为空") + public String fromId; + + @NotBlank(message = "分组名称不能为空") + private String groupName; + + private List toIds; + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/ApproverFriendRequestReq.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/ApproverFriendRequestReq.java new file mode 100644 index 0000000..22d1833 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/ApproverFriendRequestReq.java @@ -0,0 +1,14 @@ +package com.lld.im.service.friendship.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + + +@Data +public class ApproverFriendRequestReq extends RequestBase { + + private Long id; + + //1同意 2拒绝 + private Integer status; +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/CheckFriendShipReq.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/CheckFriendShipReq.java new file mode 100644 index 0000000..721d8b2 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/CheckFriendShipReq.java @@ -0,0 +1,27 @@ +package com.lld.im.service.friendship.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Data +public class CheckFriendShipReq extends RequestBase { + + @NotBlank(message = "fromId不能为空") + private String fromId; + + @NotEmpty(message = "toIds不能为空") + private List toIds; + + @NotNull(message = "checkType不能为空") + private Integer checkType; +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/DeleteBlackReq.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/DeleteBlackReq.java new file mode 100644 index 0000000..0ae5dd6 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/DeleteBlackReq.java @@ -0,0 +1,19 @@ +package com.lld.im.service.friendship.model.req; + + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + + +@Data +public class DeleteBlackReq extends RequestBase { + + @NotBlank(message = "用户id不能为空") + private String fromId; + + @NotBlank(message = "好友id不能为空") + private String toId; + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/DeleteFriendReq.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/DeleteFriendReq.java new file mode 100644 index 0000000..3915d90 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/DeleteFriendReq.java @@ -0,0 +1,18 @@ +package com.lld.im.service.friendship.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + + +@Data +public class DeleteFriendReq extends RequestBase { + + @NotBlank(message = "fromId不能为空") + private String fromId; + + @NotBlank(message = "toId不能为空") + private String toId; + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/DeleteFriendShipGroupMemberReq.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/DeleteFriendShipGroupMemberReq.java new file mode 100644 index 0000000..af98c18 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/DeleteFriendShipGroupMemberReq.java @@ -0,0 +1,27 @@ +package com.lld.im.service.friendship.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import java.util.List; + +/** + * @author: Chackylee + * @description: + **/ +@Data +public class DeleteFriendShipGroupMemberReq extends RequestBase { + + @NotBlank(message = "fromId不能为空") + private String fromId; + + @NotBlank(message = "分组名称不能为空") + private String groupName; + + @NotEmpty(message = "请选择用户") + private List toIds; + + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/DeleteFriendShipGroupReq.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/DeleteFriendShipGroupReq.java new file mode 100644 index 0000000..7d23925 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/DeleteFriendShipGroupReq.java @@ -0,0 +1,23 @@ +package com.lld.im.service.friendship.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import java.util.List; + +/** + * @author: Chackylee + * @description: 删除分组,同时删除分组下的成员 + **/ +@Data +public class DeleteFriendShipGroupReq extends RequestBase { + + @NotBlank(message = "fromId不能为空") + private String fromId; + + @NotEmpty(message = "分组名称不能为空") + private List groupName; + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/FriendDto.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/FriendDto.java new file mode 100644 index 0000000..2a69fdf --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/FriendDto.java @@ -0,0 +1,19 @@ +package com.lld.im.service.friendship.model.req; + +import lombok.Data; + + +@Data +public class FriendDto { + + private String toId; + + private String remark; + + private String addSource; + + private String extra; + + private String addWording; + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/GetAllFriendShipReq.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/GetAllFriendShipReq.java new file mode 100644 index 0000000..e997236 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/GetAllFriendShipReq.java @@ -0,0 +1,14 @@ +package com.lld.im.service.friendship.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + + +@Data +public class GetAllFriendShipReq extends RequestBase { + + @NotBlank(message = "用户id不能为空") + private String fromId; +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/GetFriendShipRequestReq.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/GetFriendShipRequestReq.java new file mode 100644 index 0000000..a277767 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/GetFriendShipRequestReq.java @@ -0,0 +1,19 @@ +package com.lld.im.service.friendship.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Data +public class GetFriendShipRequestReq extends RequestBase { + + @NotBlank(message = "用户id不能为空") + private String fromId; + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/GetRelationReq.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/GetRelationReq.java new file mode 100644 index 0000000..eb97c78 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/GetRelationReq.java @@ -0,0 +1,16 @@ +package com.lld.im.service.friendship.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + + +@Data +public class GetRelationReq extends RequestBase { + @NotBlank(message = "fromId不能为空") + private String fromId; + + @NotBlank(message = "toId不能为空") + private String toId; +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/ImporFriendShipReq.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/ImporFriendShipReq.java new file mode 100644 index 0000000..8e6a6cd --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/ImporFriendShipReq.java @@ -0,0 +1,33 @@ +package com.lld.im.service.friendship.model.req; + +import com.lld.im.common.enums.FriendShipStatusEnum; +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import java.util.List; + + +@Data +public class ImporFriendShipReq extends RequestBase { + + @NotBlank(message = "fromId不能为空") + private String fromId; + + private List friendItem; + + @Data + public static class ImportFriendDto{ + + private String toId; + + private String remark; + + private String addSource; + + private Integer status = FriendShipStatusEnum.FRIEND_STATUS_NO_FRIEND.getCode(); + + private Integer black = FriendShipStatusEnum.BLACK_STATUS_NORMAL.getCode(); + } + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/ReadFriendShipRequestReq.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/ReadFriendShipRequestReq.java new file mode 100644 index 0000000..afbe591 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/ReadFriendShipRequestReq.java @@ -0,0 +1,14 @@ +package com.lld.im.service.friendship.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + + +@Data +public class ReadFriendShipRequestReq extends RequestBase { + + @NotBlank(message = "用户id不能为空") + private String fromId; +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/UpdateFriendReq.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/UpdateFriendReq.java new file mode 100644 index 0000000..3250543 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/req/UpdateFriendReq.java @@ -0,0 +1,18 @@ +package com.lld.im.service.friendship.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + + +@Data +public class UpdateFriendReq extends RequestBase { + + @NotBlank(message = "fromId不能为空") + private String fromId; + + @NotNull(message = "toItem不能为空") + private FriendDto toItem; +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/resp/CheckFriendShipResp.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/resp/CheckFriendShipResp.java new file mode 100644 index 0000000..c8951e2 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/resp/CheckFriendShipResp.java @@ -0,0 +1,30 @@ +package com.lld.im.service.friendship.model.resp; + +import lombok.Data; + + +@Data +public class CheckFriendShipResp { + + private String fromId; + + private String toId; + + + //校验状态,根据双向校验和单向校验有不同的status + //单向校验:1 from添加了to,不确定to是否添加了from CheckResult_single_Type_AWithB; + // 0 from没有添加to,也不确定to有没有添加from CheckResult_single_Type_NoRelation + //双向校验 1 from添加了to,to也添加了from CheckResult_Type_BothWay + // 2 from添加了t0,to没有添加from CheckResult_Both_Type_AWithB + // 3 from没有添加to,to添加了from, CheckResult_Both_Type_BWithA + // 4 双方都没有添加 CheckResult_Both_Type_NoRelation + + //单向校验黑名单:1 from没有拉黑to,不确定to是否拉黑了from CheckResult_singe_Type_AWithB; + // 0 from拉黑to,不确定to是佛拉黑from CheckResult_singe_Type_NoRelation + //双向校验黑名单 1 from没有拉黑to,to也没有拉黑from CheckResult_Type_BothWay + // 2 from没有拉黑to,to拉黑from CheckResult_Both_Type_AWithB + // 3 from拉黑了to,to没有拉黑from CheckResult_Both_Type_BWithA + // 4 双方都拉黑 CheckResult_Both_Type_NoRelation + private Integer status; + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/resp/ImportFriendShipResp.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/resp/ImportFriendShipResp.java new file mode 100644 index 0000000..240016b --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/model/resp/ImportFriendShipResp.java @@ -0,0 +1,14 @@ +package com.lld.im.service.friendship.model.resp; + +import lombok.Data; + +import java.util.List; + + +@Data +public class ImportFriendShipResp { + + private List successId; + + private List errorId; +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/service/ImFriendService.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/service/ImFriendService.java new file mode 100644 index 0000000..885cfd5 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/service/ImFriendService.java @@ -0,0 +1,40 @@ +package com.lld.im.service.friendship.service; + +import com.lld.im.common.ResponseVO; +import com.lld.im.common.model.RequestBase; +import com.lld.im.service.friendship.model.req.*; + +import java.util.List; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +public interface ImFriendService { + + public ResponseVO importFriendShip(ImporFriendShipReq req); + + public ResponseVO addFriend(AddFriendReq req); + + public ResponseVO updateFriend(UpdateFriendReq req); + + public ResponseVO deleteFriend(DeleteFriendReq req); + + public ResponseVO deleteAllFriend(DeleteFriendReq req); + + public ResponseVO getAllFriendShip(GetAllFriendShipReq req); + + public ResponseVO getRelation(GetRelationReq req); + + public ResponseVO doAddFriend(RequestBase requestBase,String fromId, FriendDto dto, Integer appId); + + public ResponseVO checkFriendship(CheckFriendShipReq req); + + public ResponseVO addBlack(AddFriendShipBlackReq req); + + public ResponseVO deleteBlack(DeleteBlackReq req); + + public ResponseVO checkBlck(CheckFriendShipReq req); + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/service/ImFriendShipGroupMemberService.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/service/ImFriendShipGroupMemberService.java new file mode 100644 index 0000000..2783dbe --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/service/ImFriendShipGroupMemberService.java @@ -0,0 +1,20 @@ +package com.lld.im.service.friendship.service; + +import com.lld.im.common.ResponseVO; +import com.lld.im.service.friendship.model.req.AddFriendShipGroupMemberReq; +import com.lld.im.service.friendship.model.req.DeleteFriendShipGroupMemberReq; + +/** + * @author: Chackylee + * @description: + **/ +public interface ImFriendShipGroupMemberService { + + public ResponseVO addGroupMember(AddFriendShipGroupMemberReq req); + + public ResponseVO delGroupMember(DeleteFriendShipGroupMemberReq req); + + public int doAddGroupMember(Long groupId, String toId); + + public int clearGroupMember(Long groupId); +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/service/ImFriendShipGroupService.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/service/ImFriendShipGroupService.java new file mode 100644 index 0000000..2a1c268 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/service/ImFriendShipGroupService.java @@ -0,0 +1,21 @@ +package com.lld.im.service.friendship.service; + +import com.lld.im.common.ResponseVO; +import com.lld.im.service.friendship.dao.ImFriendShipGroupEntity; +import com.lld.im.service.friendship.model.req.AddFriendShipGroupReq; +import com.lld.im.service.friendship.model.req.DeleteFriendShipGroupReq; + +/** + * @author: Chackylee + * @description: + **/ +public interface ImFriendShipGroupService { + + public ResponseVO addGroup(AddFriendShipGroupReq req); + + public ResponseVO deleteGroup(DeleteFriendShipGroupReq req); + + public ResponseVO getGroup(String fromId, String groupName, Integer appId); + + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/service/ImFriendShipRequestService.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/service/ImFriendShipRequestService.java new file mode 100644 index 0000000..8f98a2b --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/service/ImFriendShipRequestService.java @@ -0,0 +1,18 @@ +package com.lld.im.service.friendship.service; + +import com.lld.im.common.ResponseVO; +import com.lld.im.service.friendship.model.req.ApproverFriendRequestReq; +import com.lld.im.service.friendship.model.req.FriendDto; +import com.lld.im.service.friendship.model.req.ReadFriendShipRequestReq; + + +public interface ImFriendShipRequestService { + + public ResponseVO addFienshipRequest(String fromId, FriendDto dto, Integer appId); + + public ResponseVO approverFriendRequest(ApproverFriendRequestReq req); + + public ResponseVO readFriendShipRequestReq(ReadFriendShipRequestReq req); + + public ResponseVO getFriendRequest(String fromId, Integer appId); +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/service/impl/ImFriendServiceImpl.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/service/impl/ImFriendServiceImpl.java new file mode 100644 index 0000000..88c4142 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/service/impl/ImFriendServiceImpl.java @@ -0,0 +1,439 @@ +package com.lld.im.service.friendship.service.impl; + +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import com.lld.im.common.ResponseVO; +import com.lld.im.common.enums.AllowFriendTypeEnum; +import com.lld.im.common.enums.CheckFriendShipTypeEnum; +import com.lld.im.common.enums.FriendShipErrorCode; +import com.lld.im.common.enums.FriendShipStatusEnum; +import com.lld.im.common.exception.ApplicationException; +import com.lld.im.common.model.RequestBase; +import com.lld.im.service.friendship.dao.ImFriendShipEntity; +import com.lld.im.service.friendship.dao.mapper.ImFriendShipMapper; +import com.lld.im.service.friendship.model.req.*; +import com.lld.im.service.friendship.model.resp.CheckFriendShipResp; +import com.lld.im.service.friendship.model.resp.ImportFriendShipResp; +import com.lld.im.service.friendship.service.ImFriendService; +import com.lld.im.service.friendship.service.ImFriendShipRequestService; +import com.lld.im.service.user.dao.ImUserDataEntity; +import com.lld.im.service.user.service.ImUserService; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Service +public class ImFriendServiceImpl implements ImFriendService { + + @Autowired + ImFriendShipMapper imFriendShipMapper; + + @Autowired + ImUserService imUserService; + + @Autowired + ImFriendService imFriendService; + + @Autowired + ImFriendShipRequestService imFriendShipRequestService; + + @Override + public ResponseVO importFriendShip(ImporFriendShipReq req) { + + if(req.getFriendItem().size() > 100){ + return ResponseVO.errorResponse(FriendShipErrorCode.IMPORT_SIZE_BEYOND); + } + ImportFriendShipResp resp = new ImportFriendShipResp(); + List successId = new ArrayList<>(); + List errorId = new ArrayList<>(); + + for (ImporFriendShipReq.ImportFriendDto dto: + req.getFriendItem()) { + ImFriendShipEntity entity = new ImFriendShipEntity(); + BeanUtils.copyProperties(dto,entity); + entity.setAppId(req.getAppId()); + entity.setFromId(req.getFromId()); + try { + int insert = imFriendShipMapper.insert(entity); + if(insert == 1){ + successId.add(dto.getToId()); + }else{ + errorId.add(dto.getToId()); + } + }catch (Exception e){ + e.printStackTrace(); + errorId.add(dto.getToId()); + } + + } + + resp.setErrorId(errorId); + resp.setSuccessId(successId); + + return ResponseVO.successResponse(resp); + } + + @Override + public ResponseVO addFriend(AddFriendReq req) { + + ResponseVO fromInfo = imUserService.getSingleUserInfo(req.getFromId(), req.getAppId()); + if(!fromInfo.isOk()){ + return fromInfo; + } + + ResponseVO toInfo = imUserService.getSingleUserInfo(req.getToItem().getToId(), req.getAppId()); + if(!toInfo.isOk()){ + return toInfo; + } + + ImUserDataEntity data = toInfo.getData(); + + if(data.getFriendAllowType() != null && data.getFriendAllowType() == AllowFriendTypeEnum.NOT_NEED.getCode()){ + return this.doAddFriend(req,req.getFromId(), req.getToItem(), req.getAppId()); + }else{ + QueryWrapper query = new QueryWrapper<>(); + query.eq("app_id",req.getAppId()); + query.eq("from_id",req.getFromId()); + query.eq("to_id",req.getToItem().getToId()); + ImFriendShipEntity fromItem = imFriendShipMapper.selectOne(query); + if(fromItem == null || fromItem.getStatus() + != FriendShipStatusEnum.FRIEND_STATUS_NORMAL.getCode()){ + //插入一条好友申请的数据 + ResponseVO responseVO = imFriendShipRequestService.addFienshipRequest(req.getFromId(), req.getToItem(), req.getAppId()); + if(!responseVO.isOk()){ + return responseVO; + } + }else{ + return ResponseVO.errorResponse(FriendShipErrorCode.TO_IS_YOUR_FRIEND); + } + + } + + return ResponseVO.successResponse(); + } + + @Override + public ResponseVO updateFriend(UpdateFriendReq req) { + + ResponseVO fromInfo = imUserService.getSingleUserInfo(req.getFromId(), req.getAppId()); + if(!fromInfo.isOk()){ + return fromInfo; + } + + ResponseVO toInfo = imUserService.getSingleUserInfo(req.getToItem().getToId(), req.getAppId()); + if(!toInfo.isOk()){ + return toInfo; + } + + ResponseVO responseVO = this.doUpdate(req.getFromId(), req.getToItem(), req.getAppId()); + return responseVO; + } + + @Transactional + public ResponseVO doUpdate(String fromId, FriendDto dto,Integer appId){ + + + UpdateWrapper updateWrapper = new UpdateWrapper<>(); + updateWrapper.lambda().set(ImFriendShipEntity::getAddSource,dto.getAddSource()) + .set(ImFriendShipEntity::getExtra,dto.getExtra()) + .set(ImFriendShipEntity::getRemark,dto.getRemark()) + .eq(ImFriendShipEntity::getAppId,appId) + .eq(ImFriendShipEntity::getToId,dto.getToId()) + .eq(ImFriendShipEntity::getFromId,fromId); + + int update = imFriendShipMapper.update(null, updateWrapper); + if(update == 1){ + return ResponseVO.successResponse(); + } + + return ResponseVO.errorResponse(); + } + + @Override + @Transactional + public ResponseVO doAddFriend(RequestBase requestBase,String fromId, FriendDto dto, Integer appId){ + + //A-B + //Friend表插入A 和 B 两条记录 + //查询是否有记录存在,如果存在则判断状态,如果是已添加,则提示已添加,如果是未添加,则修改状态 + + QueryWrapper query = new QueryWrapper<>(); + query.eq("app_id",appId); + query.eq("from_id",fromId); + query.eq("to_id",dto.getToId()); + ImFriendShipEntity fromItem = imFriendShipMapper.selectOne(query); + if(fromItem == null){ + //走添加逻辑。 + fromItem = new ImFriendShipEntity(); + fromItem.setAppId(appId); + fromItem.setFromId(fromId); +// entity.setToId(to); + BeanUtils.copyProperties(dto,fromItem); + fromItem.setStatus(FriendShipStatusEnum.FRIEND_STATUS_NORMAL.getCode()); + fromItem.setCreateTime(System.currentTimeMillis()); + int insert = imFriendShipMapper.insert(fromItem); + if(insert != 1){ + return ResponseVO.errorResponse(FriendShipErrorCode.ADD_FRIEND_ERROR); + } + } else{ + //如果存在则判断状态,如果是已添加,则提示已添加,如果是未添加,则修改状态 + if(fromItem.getStatus() == FriendShipStatusEnum.FRIEND_STATUS_NORMAL.getCode()){ + return ResponseVO.errorResponse(FriendShipErrorCode.TO_IS_YOUR_FRIEND); + } else{ + ImFriendShipEntity update = new ImFriendShipEntity(); + + if(StringUtils.isNotBlank(dto.getAddSource())){ + update.setAddSource(dto.getAddSource()); + } + + if(StringUtils.isNotBlank(dto.getRemark())){ + update.setRemark(dto.getRemark()); + } + + if(StringUtils.isNotBlank(dto.getExtra())){ + update.setExtra(dto.getExtra()); + } + update.setStatus(FriendShipStatusEnum.FRIEND_STATUS_NORMAL.getCode()); + + int result = imFriendShipMapper.update(update, query); + if(result != 1){ + return ResponseVO.errorResponse(FriendShipErrorCode.ADD_FRIEND_ERROR); + } + } + + } + + QueryWrapper toQuery = new QueryWrapper<>(); + toQuery.eq("app_id",appId); + toQuery.eq("from_id",dto.getToId()); + toQuery.eq("to_id",fromId); + ImFriendShipEntity toItem = imFriendShipMapper.selectOne(toQuery); + if(toItem == null){ + toItem = new ImFriendShipEntity(); + toItem.setAppId(appId); + toItem.setFromId(dto.getToId()); + BeanUtils.copyProperties(dto,toItem); + toItem.setToId(fromId); + toItem.setStatus(FriendShipStatusEnum.FRIEND_STATUS_NORMAL.getCode()); + toItem.setCreateTime(System.currentTimeMillis()); +// toItem.setBlack(FriendShipStatusEnum.BLACK_STATUS_NORMAL.getCode()); + int insert = imFriendShipMapper.insert(toItem); + }else{ + if(FriendShipStatusEnum.FRIEND_STATUS_NORMAL.getCode() != + toItem.getStatus()){ + ImFriendShipEntity update = new ImFriendShipEntity(); + update.setStatus(FriendShipStatusEnum.FRIEND_STATUS_NORMAL.getCode()); + imFriendShipMapper.update(update,toQuery); + } + } + return ResponseVO.successResponse(); + } + + + @Override + public ResponseVO deleteFriend(DeleteFriendReq req) { + + QueryWrapper query = new QueryWrapper<>(); + query.eq("app_id",req.getAppId()); + query.eq("from_id",req.getFromId()); + query.eq("to_id",req.getToId()); + ImFriendShipEntity fromItem = imFriendShipMapper.selectOne(query); + if(fromItem == null){ + return ResponseVO.errorResponse(FriendShipErrorCode.TO_IS_NOT_YOUR_FRIEND); + }else{ + if(fromItem.getStatus() != null && fromItem.getStatus() == FriendShipStatusEnum.FRIEND_STATUS_NORMAL.getCode()){ + ImFriendShipEntity update = new ImFriendShipEntity(); + update.setStatus(FriendShipStatusEnum.FRIEND_STATUS_DELETE.getCode()); + imFriendShipMapper.update(update,query); + + }else{ + return ResponseVO.errorResponse(FriendShipErrorCode.FRIEND_IS_DELETED); + } + } + return ResponseVO.successResponse(); + } + + @Override + public ResponseVO deleteAllFriend(DeleteFriendReq req) { + QueryWrapper query = new QueryWrapper<>(); + query.eq("app_id",req.getAppId()); + query.eq("from_id",req.getFromId()); + query.eq("status",FriendShipStatusEnum.FRIEND_STATUS_NORMAL.getCode()); + + ImFriendShipEntity update = new ImFriendShipEntity(); + update.setStatus(FriendShipStatusEnum.FRIEND_STATUS_DELETE.getCode()); + imFriendShipMapper.update(update,query); + return ResponseVO.successResponse(); + } + + @Override + public ResponseVO getAllFriendShip(GetAllFriendShipReq req) { + QueryWrapper query = new QueryWrapper<>(); + query.eq("app_id",req.getAppId()); + query.eq("from_id",req.getFromId()); + return ResponseVO.successResponse(imFriendShipMapper.selectList(query)); + } + + @Override + public ResponseVO getRelation(GetRelationReq req) { + + QueryWrapper query = new QueryWrapper<>(); + query.eq("app_id",req.getAppId()); + query.eq("from_id",req.getFromId()); + query.eq("to_id",req.getToId()); + + ImFriendShipEntity entity = imFriendShipMapper.selectOne(query); + if(entity == null){ + return ResponseVO.errorResponse(FriendShipErrorCode.REPEATSHIP_IS_NOT_EXIST); + } + return ResponseVO.successResponse(entity); + } + + @Override + public ResponseVO checkBlck(CheckFriendShipReq req) { + + Map toIdMap + = req.getToIds().stream().collect(Collectors + .toMap(Function.identity(), s -> 0)); + List result = new ArrayList<>(); + if (req.getCheckType() == CheckFriendShipTypeEnum.SINGLE.getType()) { + result = imFriendShipMapper.checkFriendShipBlack(req); + } else { + result = imFriendShipMapper.checkFriendShipBlackBoth(req); + } + + Map collect = result.stream() + .collect(Collectors + .toMap(CheckFriendShipResp::getToId, + CheckFriendShipResp::getStatus)); + for (String toId: + toIdMap.keySet()) { + if(!collect.containsKey(toId)){ + CheckFriendShipResp checkFriendShipResp = new CheckFriendShipResp(); + checkFriendShipResp.setToId(toId); + checkFriendShipResp.setFromId(req.getFromId()); + checkFriendShipResp.setStatus(toIdMap.get(toId)); + result.add(checkFriendShipResp); + } + } + + return ResponseVO.successResponse(result); + } + + + @Override + public ResponseVO addBlack(AddFriendShipBlackReq req) { + + ResponseVO fromInfo = imUserService.getSingleUserInfo(req.getFromId(), req.getAppId()); + if(!fromInfo.isOk()){ + return fromInfo; + } + + ResponseVO toInfo = imUserService.getSingleUserInfo(req.getToId(), req.getAppId()); + if(!toInfo.isOk()){ + return toInfo; + } + QueryWrapper query = new QueryWrapper<>(); + query.eq("app_id",req.getAppId()); + query.eq("from_id",req.getFromId()); + query.eq("to_id",req.getToId()); + + ImFriendShipEntity fromItem = imFriendShipMapper.selectOne(query); + if(fromItem == null){ + //走添加逻辑。 + fromItem = new ImFriendShipEntity(); + fromItem.setFromId(req.getFromId()); + fromItem.setToId(req.getToId()); + fromItem.setAppId(req.getAppId()); + fromItem.setBlack(FriendShipStatusEnum.BLACK_STATUS_BLACKED.getCode()); + fromItem.setCreateTime(System.currentTimeMillis()); + int insert = imFriendShipMapper.insert(fromItem); + if(insert != 1){ + return ResponseVO.errorResponse(FriendShipErrorCode.ADD_FRIEND_ERROR); + } + + } else{ + //如果存在则判断状态,如果是拉黑,则提示已拉黑,如果是未拉黑,则修改状态 + if(fromItem.getBlack() != null && fromItem.getBlack() == FriendShipStatusEnum.BLACK_STATUS_BLACKED.getCode()){ + return ResponseVO.errorResponse(FriendShipErrorCode.FRIEND_IS_BLACK); + } else { + ImFriendShipEntity update = new ImFriendShipEntity(); + update.setBlack(FriendShipStatusEnum.BLACK_STATUS_BLACKED.getCode()); + int result = imFriendShipMapper.update(update, query); + if(result != 1){ + return ResponseVO.errorResponse(FriendShipErrorCode.ADD_BLACK_ERROR); + } + } + } + + return ResponseVO.successResponse(); + } + + @Override + public ResponseVO deleteBlack(DeleteBlackReq req) { + QueryWrapper queryFrom = new QueryWrapper<>() + .eq("from_id", req.getFromId()) + .eq("app_id", req.getAppId()) + .eq("to_id", req.getToId()); + ImFriendShipEntity fromItem = imFriendShipMapper.selectOne(queryFrom); + if (fromItem.getBlack() != null && fromItem.getBlack() == FriendShipStatusEnum.BLACK_STATUS_NORMAL.getCode()) { + throw new ApplicationException(FriendShipErrorCode.FRIEND_IS_NOT_YOUR_BLACK); + } + + ImFriendShipEntity update = new ImFriendShipEntity(); + update.setBlack(FriendShipStatusEnum.BLACK_STATUS_NORMAL.getCode()); + int update1 = imFriendShipMapper.update(update, queryFrom); + if(update1 == 1){ + return ResponseVO.successResponse(); + } + return ResponseVO.errorResponse(); + } + + @Override + public ResponseVO checkFriendship(CheckFriendShipReq req) { + + Map result + = req.getToIds().stream() + .collect(Collectors.toMap(Function.identity(), s -> 0)); + + List resp = new ArrayList<>(); + + if(req.getCheckType() == CheckFriendShipTypeEnum.SINGLE.getType()){ + resp =imFriendShipMapper.checkFriendShip(req); + }else { + resp =imFriendShipMapper.checkFriendShipBoth(req); + } + + Map collect = resp.stream() + .collect(Collectors.toMap(CheckFriendShipResp::getToId + , CheckFriendShipResp::getStatus)); + + for (String toId : result.keySet()){ + if(!collect.containsKey(toId)){ + CheckFriendShipResp checkFriendShipResp = new CheckFriendShipResp(); + checkFriendShipResp.setFromId(req.getFromId()); + checkFriendShipResp.setToId(toId); + checkFriendShipResp.setStatus(result.get(toId)); + resp.add(checkFriendShipResp); + } + } + + return ResponseVO.successResponse(resp); + } + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/service/impl/ImFriendShipGroupMemberServiceImpl.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/service/impl/ImFriendShipGroupMemberServiceImpl.java new file mode 100644 index 0000000..0431113 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/service/impl/ImFriendShipGroupMemberServiceImpl.java @@ -0,0 +1,122 @@ +package com.lld.im.service.friendship.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.lld.im.common.ResponseVO; +import com.lld.im.service.friendship.dao.ImFriendShipGroupEntity; +import com.lld.im.service.friendship.dao.ImFriendShipGroupMemberEntity; +import com.lld.im.service.friendship.dao.mapper.ImFriendShipGroupMemberMapper; +import com.lld.im.service.friendship.model.req.AddFriendShipGroupMemberReq; +import com.lld.im.service.friendship.model.req.DeleteFriendShipGroupMemberReq; +import com.lld.im.service.friendship.service.ImFriendShipGroupMemberService; +import com.lld.im.service.friendship.service.ImFriendShipGroupService; +import com.lld.im.service.user.dao.ImUserDataEntity; +import com.lld.im.service.user.service.ImUserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author: Chackylee + * @description: + **/ +@Service +public class ImFriendShipGroupMemberServiceImpl + implements ImFriendShipGroupMemberService { + + @Autowired + ImFriendShipGroupMemberMapper imFriendShipGroupMemberMapper; + + @Autowired + ImFriendShipGroupService imFriendShipGroupService; + + @Autowired + ImUserService imUserService; + + @Autowired + ImFriendShipGroupMemberService thisService; + + @Override + @Transactional + public ResponseVO addGroupMember(AddFriendShipGroupMemberReq req) { + + ResponseVO group = imFriendShipGroupService + .getGroup(req.getFromId(),req.getGroupName(),req.getAppId()); + if(!group.isOk()){ + return group; + } + + List successId = new ArrayList<>(); + for (String toId : req.getToIds()) { + ResponseVO singleUserInfo = imUserService.getSingleUserInfo(toId, req.getAppId()); + if(singleUserInfo.isOk()){ + int i = thisService.doAddGroupMember(group.getData().getGroupId(), toId); + if(i == 1){ + successId.add(toId); + } + } + } + + return ResponseVO.successResponse(successId); + } + + @Override + public ResponseVO delGroupMember(DeleteFriendShipGroupMemberReq req) { + ResponseVO group = imFriendShipGroupService + .getGroup(req.getFromId(),req.getGroupName(),req.getAppId()); + if(!group.isOk()){ + return group; + } + + ArrayList list = new ArrayList(); + for (String toId : req.getToIds()) { + ResponseVO singleUserInfo = imUserService.getSingleUserInfo(toId, req.getAppId()); + if(singleUserInfo.isOk()){ + int i = deleteGroupMember(group.getData().getGroupId(), toId); + if(i == 1){ + list.add(toId); + } + } + } + return ResponseVO.successResponse(list); + } + + @Override + public int doAddGroupMember(Long groupId, String toId) { + ImFriendShipGroupMemberEntity imFriendShipGroupMemberEntity = new ImFriendShipGroupMemberEntity(); + imFriendShipGroupMemberEntity.setGroupId(groupId); + imFriendShipGroupMemberEntity.setToId(toId); + try { + int insert = imFriendShipGroupMemberMapper.insert(imFriendShipGroupMemberEntity); + return insert; + }catch (Exception e){ + e.printStackTrace(); + return 0; + } + } + + public int deleteGroupMember(Long groupId, String toId) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("group_id",groupId); + queryWrapper.eq("to_id",toId); + + try { + int delete = imFriendShipGroupMemberMapper.delete(queryWrapper); +// int insert = imFriendShipGroupMemberMapper.insert(imFriendShipGroupMemberEntity); + return delete; + }catch (Exception e){ + e.printStackTrace(); + return 0; + } + } + + @Override + public int clearGroupMember(Long groupId) { + QueryWrapper query = new QueryWrapper<>(); + query.eq("group_id",groupId); + int delete = imFriendShipGroupMemberMapper.delete(query); + return delete; + } +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/service/impl/ImFriendShipGroupServiceImpl.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/service/impl/ImFriendShipGroupServiceImpl.java new file mode 100644 index 0000000..350e226 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/service/impl/ImFriendShipGroupServiceImpl.java @@ -0,0 +1,119 @@ +package com.lld.im.service.friendship.service.impl; + +import cn.hutool.core.collection.CollectionUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.lld.im.common.ResponseVO; +import com.lld.im.common.enums.DelFlagEnum; +import com.lld.im.common.enums.FriendShipErrorCode; +import com.lld.im.service.friendship.dao.ImFriendShipGroupEntity; +import com.lld.im.service.friendship.dao.mapper.ImFriendShipGroupMapper; +import com.lld.im.service.friendship.model.req.AddFriendShipGroupMemberReq; +import com.lld.im.service.friendship.model.req.AddFriendShipGroupReq; +import com.lld.im.service.friendship.model.req.DeleteFriendShipGroupReq; +import com.lld.im.service.friendship.service.ImFriendShipGroupMemberService; +import com.lld.im.service.friendship.service.ImFriendShipGroupService; +import com.lld.im.service.user.service.ImUserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class ImFriendShipGroupServiceImpl implements ImFriendShipGroupService { + + @Autowired + ImFriendShipGroupMapper imFriendShipGroupMapper; + + @Autowired + ImFriendShipGroupMemberService imFriendShipGroupMemberService; + + @Autowired + ImUserService imUserService; + + @Override + @Transactional + public ResponseVO addGroup(AddFriendShipGroupReq req) { + + QueryWrapper query = new QueryWrapper<>(); + query.eq("group_name", req.getGroupName()); + query.eq("app_id", req.getAppId()); + query.eq("from_id", req.getFromId()); + query.eq("del_flag", DelFlagEnum.NORMAL.getCode()); + + ImFriendShipGroupEntity entity = imFriendShipGroupMapper.selectOne(query); + + if (entity != null) { + return ResponseVO.errorResponse(FriendShipErrorCode.FRIEND_SHIP_GROUP_IS_EXIST); + } + + //写入db + ImFriendShipGroupEntity insert = new ImFriendShipGroupEntity(); + insert.setAppId(req.getAppId()); + insert.setCreateTime(System.currentTimeMillis()); + insert.setDelFlag(DelFlagEnum.NORMAL.getCode()); + insert.setGroupName(req.getGroupName()); + insert.setFromId(req.getFromId()); + try { + int insert1 = imFriendShipGroupMapper.insert(insert); + + if (insert1 != 1) { + return ResponseVO.errorResponse(FriendShipErrorCode.FRIEND_SHIP_GROUP_CREATE_ERROR); + } + + if (insert1 == 1 && CollectionUtil.isNotEmpty(req.getToIds())) { + AddFriendShipGroupMemberReq addFriendShipGroupMemberReq = new AddFriendShipGroupMemberReq(); + addFriendShipGroupMemberReq.setFromId(req.getFromId()); + addFriendShipGroupMemberReq.setGroupName(req.getGroupName()); + addFriendShipGroupMemberReq.setToIds(req.getToIds()); + addFriendShipGroupMemberReq.setAppId(req.getAppId()); + imFriendShipGroupMemberService.addGroupMember(addFriendShipGroupMemberReq); + return ResponseVO.successResponse(); + } + } catch (DuplicateKeyException e) { + e.getStackTrace(); + return ResponseVO.errorResponse(FriendShipErrorCode.FRIEND_SHIP_GROUP_IS_EXIST); + } + return ResponseVO.successResponse(); + } + + @Override + @Transactional + public ResponseVO deleteGroup(DeleteFriendShipGroupReq req) { + + for (String groupName : req.getGroupName()) { + QueryWrapper query = new QueryWrapper<>(); + query.eq("group_name", groupName); + query.eq("app_id", req.getAppId()); + query.eq("from_id", req.getFromId()); + query.eq("del_flag", DelFlagEnum.NORMAL.getCode()); + + ImFriendShipGroupEntity entity = imFriendShipGroupMapper.selectOne(query); + + if (entity != null) { + ImFriendShipGroupEntity update = new ImFriendShipGroupEntity(); + update.setGroupId(entity.getGroupId()); + update.setDelFlag(DelFlagEnum.DELETE.getCode()); + imFriendShipGroupMapper.updateById(update); + imFriendShipGroupMemberService.clearGroupMember(entity.getGroupId()); + + } + } + return ResponseVO.successResponse(); + } + + @Override + public ResponseVO getGroup(String fromId, String groupName, Integer appId) { + QueryWrapper query = new QueryWrapper<>(); + query.eq("group_name", groupName); + query.eq("app_id", appId); + query.eq("from_id", fromId); + query.eq("del_flag", DelFlagEnum.NORMAL.getCode()); + + ImFriendShipGroupEntity entity = imFriendShipGroupMapper.selectOne(query); + if (entity == null) { + return ResponseVO.errorResponse(FriendShipErrorCode.FRIEND_SHIP_GROUP_IS_NOT_EXIST); + } + return ResponseVO.successResponse(entity); + } + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/service/impl/ImFriendShipRequestServiceImpl.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/service/impl/ImFriendShipRequestServiceImpl.java new file mode 100644 index 0000000..d806731 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/friendship/service/impl/ImFriendShipRequestServiceImpl.java @@ -0,0 +1,140 @@ +package com.lld.im.service.friendship.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.lld.im.common.ResponseVO; +import com.lld.im.common.enums.ApproverFriendRequestStatusEnum; +import com.lld.im.common.enums.FriendShipErrorCode; +import com.lld.im.common.exception.ApplicationException; +import com.lld.im.service.friendship.dao.ImFriendShipRequestEntity; +import com.lld.im.service.friendship.dao.mapper.ImFriendShipRequestMapper; +import com.lld.im.service.friendship.model.req.ApproverFriendRequestReq; +import com.lld.im.service.friendship.model.req.FriendDto; +import com.lld.im.service.friendship.model.req.ReadFriendShipRequestReq; +import com.lld.im.service.friendship.service.ImFriendService; +import com.lld.im.service.friendship.service.ImFriendShipRequestService; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + + +@Service +public class ImFriendShipRequestServiceImpl implements ImFriendShipRequestService { + + @Autowired + ImFriendShipRequestMapper imFriendShipRequestMapper; + + @Autowired + ImFriendService imFriendShipService; + + @Override + public ResponseVO getFriendRequest(String fromId, Integer appId) { + + QueryWrapper query = new QueryWrapper(); + query.eq("app_id", appId); + query.eq("to_id", fromId); + + List requestList = imFriendShipRequestMapper.selectList(query); + + return ResponseVO.successResponse(requestList); + } + + + //A + B + @Override + public ResponseVO addFienshipRequest(String fromId, FriendDto dto, Integer appId) { + + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("app_id",appId); + queryWrapper.eq("from_id",fromId); + queryWrapper.eq("to_id",dto.getToId()); + ImFriendShipRequestEntity request = imFriendShipRequestMapper.selectOne(queryWrapper); + + if(request == null){ + request = new ImFriendShipRequestEntity(); + request.setAddSource(dto.getAddSource()); + request.setAddWording(dto.getAddWording()); + request.setAppId(appId); + request.setFromId(fromId); + request.setToId(dto.getToId()); + request.setReadStatus(0); + request.setApproveStatus(0); + request.setRemark(dto.getRemark()); + request.setCreateTime(System.currentTimeMillis()); + imFriendShipRequestMapper.insert(request); + + }else { + //修改记录内容 和更新时间 + if(StringUtils.isNotBlank(dto.getAddSource())){ + request.setAddWording(dto.getAddWording()); + } + if(StringUtils.isNotBlank(dto.getRemark())){ + request.setRemark(dto.getRemark()); + } + if(StringUtils.isNotBlank(dto.getAddWording())){ + request.setAddWording(dto.getAddWording()); + } + request.setApproveStatus(0); + request.setReadStatus(0); + imFriendShipRequestMapper.updateById(request); + } + + return ResponseVO.successResponse(); + } + + @Override + @Transactional + public ResponseVO approverFriendRequest(ApproverFriendRequestReq req) { + + ImFriendShipRequestEntity imFriendShipRequestEntity = imFriendShipRequestMapper.selectById(req.getId()); + if(imFriendShipRequestEntity == null){ + throw new ApplicationException(FriendShipErrorCode.FRIEND_REQUEST_IS_NOT_EXIST); + } + + if(!req.getOperater().equals(imFriendShipRequestEntity.getToId())){ + //只能审批发给自己的好友请求 + throw new ApplicationException(FriendShipErrorCode.NOT_APPROVER_OTHER_MAN_REQUEST); + } + + ImFriendShipRequestEntity update = new ImFriendShipRequestEntity(); + update.setApproveStatus(req.getStatus()); + update.setUpdateTime(System.currentTimeMillis()); + update.setId(req.getId()); + imFriendShipRequestMapper.updateById(update); + + if(ApproverFriendRequestStatusEnum.AGREE.getCode() == req.getStatus()){ + //同意 ===> 去执行添加好友逻辑 + FriendDto dto = new FriendDto(); + dto.setAddSource(imFriendShipRequestEntity.getAddSource()); + dto.setAddWording(imFriendShipRequestEntity.getAddWording()); + dto.setRemark(imFriendShipRequestEntity.getRemark()); + dto.setToId(imFriendShipRequestEntity.getToId()); + ResponseVO responseVO = imFriendShipService.doAddFriend(req,imFriendShipRequestEntity.getFromId(), dto,req.getAppId()); +// if(!responseVO.isOk()){ +//// TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); +// return responseVO; +// } + if(!responseVO.isOk() && responseVO.getCode() != FriendShipErrorCode.TO_IS_YOUR_FRIEND.getCode()){ + return responseVO; + } + } + + return ResponseVO.successResponse(); + } + + @Override + public ResponseVO readFriendShipRequestReq(ReadFriendShipRequestReq req) { + QueryWrapper query = new QueryWrapper<>(); + query.eq("app_id", req.getAppId()); + query.eq("to_id", req.getFromId()); + + ImFriendShipRequestEntity update = new ImFriendShipRequestEntity(); + update.setReadStatus(1); + imFriendShipRequestMapper.update(update, query); + + return ResponseVO.successResponse(); + } + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/controller/ImGroupController.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/controller/ImGroupController.java new file mode 100644 index 0000000..f1bd328 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/controller/ImGroupController.java @@ -0,0 +1,80 @@ +package com.lld.im.service.group.controller; + +import com.lld.im.common.ResponseVO; +import com.lld.im.service.group.model.req.*; +import com.lld.im.service.group.service.ImGroupService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@RestController +@RequestMapping("v1/group") +public class ImGroupController { + + @Autowired + ImGroupService groupService; + + @RequestMapping("/importGroup") + public ResponseVO importGroup(@RequestBody @Validated ImportGroupReq req, Integer appId, String identifier) { + req.setAppId(appId); + req.setOperater(identifier); + return groupService.importGroup(req); + } + + @RequestMapping("/createGroup") + public ResponseVO createGroup(@RequestBody @Validated CreateGroupReq req, Integer appId, String identifier) { + req.setAppId(appId); + req.setOperater(identifier); + return groupService.createGroup(req); + } + + @RequestMapping("/getGroupInfo") + public ResponseVO getGroupInfo(@RequestBody @Validated GetGroupReq req, Integer appId) { + req.setAppId(appId); + return groupService.getGroup(req); + } + + @RequestMapping("/update") + public ResponseVO update(@RequestBody @Validated UpdateGroupReq req, Integer appId, String identifier) { + req.setAppId(appId); + req.setOperater(identifier); + return groupService.updateBaseGroupInfo(req); + } + + @RequestMapping("/getJoinedGroup") + public ResponseVO getJoinedGroup(@RequestBody @Validated GetJoinedGroupReq req, Integer appId, String identifier) { + req.setAppId(appId); + req.setOperater(identifier); + return groupService.getJoinedGroup(req); + } + + + @RequestMapping("/destroyGroup") + public ResponseVO destroyGroup(@RequestBody @Validated DestroyGroupReq req, Integer appId, String identifier) { + req.setAppId(appId); + req.setOperater(identifier); + return groupService.destroyGroup(req); + } + + @RequestMapping("/transferGroup") + public ResponseVO transferGroup(@RequestBody @Validated TransferGroupReq req, Integer appId, String identifier) { + req.setAppId(appId); + req.setOperater(identifier); + return groupService.transferGroup(req); + } + + @RequestMapping("/forbidSendMessage") + public ResponseVO forbidSendMessage(@RequestBody @Validated MuteGroupReq req, Integer appId, String identifier) { + req.setAppId(appId); + req.setOperater(identifier); + return groupService.muteGroup(req); + } + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/controller/ImGroupMemberController.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/controller/ImGroupMemberController.java new file mode 100644 index 0000000..4d9ce84 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/controller/ImGroupMemberController.java @@ -0,0 +1,59 @@ +package com.lld.im.service.group.controller; + +import com.lld.im.common.ResponseVO; +import com.lld.im.service.group.model.req.*; +import com.lld.im.service.group.service.ImGroupMemberService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@RestController +@RequestMapping("v1/group/member") +public class ImGroupMemberController { + + @Autowired + ImGroupMemberService groupMemberService; + + @RequestMapping("/importGroupMember") + public ResponseVO importGroupMember(@RequestBody @Validated ImportGroupMemberReq req, Integer appId, String identifier) { + req.setAppId(appId); + req.setOperater(identifier); + return groupMemberService.importGroupMember(req); + } + + @RequestMapping("/add") + public ResponseVO addMember(@RequestBody @Validated AddGroupMemberReq req, Integer appId, String identifier) { + req.setAppId(appId); + req.setOperater(identifier); + return groupMemberService.addMember(req); + } + + @RequestMapping("/remove") + public ResponseVO removeMember(@RequestBody @Validated RemoveGroupMemberReq req, Integer appId, String identifier) { + req.setAppId(appId); + req.setOperater(identifier); + return groupMemberService.removeMember(req); + } + + @RequestMapping("/update") + public ResponseVO updateGroupMember(@RequestBody @Validated UpdateGroupMemberReq req, Integer appId, String identifier) { + req.setAppId(appId); + req.setOperater(identifier); + return groupMemberService.updateGroupMember(req); + } + + @RequestMapping("/speak") + public ResponseVO speak(@RequestBody @Validated SpeaMemberReq req, Integer appId, String identifier) { + req.setAppId(appId); + req.setOperater(identifier); + return groupMemberService.speak(req); + } + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/dao/ImGroupEntity.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/dao/ImGroupEntity.java new file mode 100644 index 0000000..a9c2b73 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/dao/ImGroupEntity.java @@ -0,0 +1,54 @@ +package com.lld.im.service.group.dao; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Data +@TableName("im_group") +public class ImGroupEntity { + + @TableId(value = "group_id") + private String groupId; + + private Integer appId; + + //群主id + private String ownerId; + + //群类型 1私有群(类似微信) 2公开群(类似qq) + private Integer groupType; + + private String groupName; + + private Integer mute;// 是否全员禁言,0 不禁言;1 全员禁言。 + +// 申请加群选项包括如下几种: +// 0 表示禁止任何人申请加入 +// 1 表示需要群主或管理员审批 +// 2 表示允许无需审批自由加入群组 + private Integer applyJoinType; + + private String introduction;//群简介 + + private String notification;//群公告 + + private String photo;//群头像 + + private Integer maxMemberCount;//群成员上限 + + private Integer status;//群状态 0正常 1解散 + + private Long sequence; + + private Long createTime; + + private Long updateTime; + + private String extra; +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/dao/ImGroupMemberEntity.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/dao/ImGroupMemberEntity.java new file mode 100644 index 0000000..8d0ae0b --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/dao/ImGroupMemberEntity.java @@ -0,0 +1,44 @@ +package com.lld.im.service.group.dao; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Data +@TableName("im_group_member") +public class ImGroupMemberEntity { + + @TableId(type = IdType.AUTO) + private Long groupMemberId; + + private Integer appId; + + private String groupId; + + //成员id + private String memberId; + + //群成员类型,0 普通成员, 1 管理员, 2 群主, 3 禁言,4 已经移除的成员 + private Integer role; + + private Long speakDate; + + //群昵称 + private String alias; + + //加入时间 + private Long joinTime; + + //离开时间 + private Long leaveTime; + + private String joinType; + + private String extra; +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/dao/ImGroupMessageHistoryEntity.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/dao/ImGroupMessageHistoryEntity.java new file mode 100644 index 0000000..cd95cf4 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/dao/ImGroupMessageHistoryEntity.java @@ -0,0 +1,32 @@ +package com.lld.im.service.group.dao; + +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @author: Chackylee + * @description: + **/ +@Data +@TableName("im_group_message_history") +public class ImGroupMessageHistoryEntity { + + private Integer appId; + + private String fromId; + + private String groupId; + + /** messageBodyId*/ + private Long messageKey; + /** 序列号*/ + private Long sequence; + + private String messageRandom; + + private Long messageTime; + + private Long createTime; + + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/dao/mapper/ImGroupMapper.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/dao/mapper/ImGroupMapper.java new file mode 100644 index 0000000..c361fcc --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/dao/mapper/ImGroupMapper.java @@ -0,0 +1,13 @@ +package com.lld.im.service.group.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lld.im.service.group.dao.ImGroupEntity; +import org.apache.ibatis.annotations.Select; +import org.springframework.stereotype.Repository; + +import java.util.Collection; + +@Repository +public interface ImGroupMapper extends BaseMapper { + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/dao/mapper/ImGroupMemberMapper.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/dao/mapper/ImGroupMemberMapper.java new file mode 100644 index 0000000..e7a9311 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/dao/mapper/ImGroupMemberMapper.java @@ -0,0 +1,65 @@ +package com.lld.im.service.group.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lld.im.service.group.dao.ImGroupMemberEntity; +import com.lld.im.service.group.model.req.GroupMemberDto; +import org.apache.ibatis.annotations.Result; +import org.apache.ibatis.annotations.Results; +import org.apache.ibatis.annotations.Select; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface ImGroupMemberMapper extends BaseMapper { + + @Select("select group_id from im_group_member where app_id = #{appId} AND member_id = #{memberId} ") + public List getJoinedGroupId(Integer appId, String memberId); + + + + @Results({ + @Result(column = "member_id", property = "memberId"), +// @Result(column = "speak_flag", property = "speakFlag"), + @Result(column = "speak_date", property = "speakDate"), + @Result(column = "role", property = "role"), + @Result(column = "alias", property = "alias"), + @Result(column = "join_time", property = "joinTime"), + @Result(column = "join_type", property = "joinType") + }) + @Select("select " + + " member_id, " + +// " speak_flag, " + + " speak_date, " + + " role, " + + " alias, " + + " join_time ," + + " join_type " + + " from im_group_member where app_id = #{appId} AND group_id = #{groupId} ") + public List getGroupMember(Integer appId, String groupId); + + @Select("select " + + " member_id " + + " from im_group_member where app_id = #{appId} AND group_id = #{groupId} and role != 3") + public List getGroupMemberId(Integer appId, String groupId); + + + @Results({ + @Result(column = "member_id", property = "memberId"), +// @Result(column = "speak_flag", property = "speakFlag"), + @Result(column = "role", property = "role") +// @Result(column = "alias", property = "alias"), +// @Result(column = "join_time", property = "joinTime"), +// @Result(column = "join_type", property = "joinType") + }) + @Select("select " + + " member_id, " + +// " speak_flag, " + + " role " + +// " alias, " + +// " join_time ," + +// " join_type " + + " from im_group_member where app_id = #{appId} AND group_id = #{groupId} and role in (1,2) ") + public List getGroupManager(String groupId, Integer appId); + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/dao/mapper/ImGroupMessageHistoryMapper.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/dao/mapper/ImGroupMessageHistoryMapper.java new file mode 100644 index 0000000..4962788 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/dao/mapper/ImGroupMessageHistoryMapper.java @@ -0,0 +1,11 @@ +package com.lld.im.service.group.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lld.im.service.group.dao.ImGroupMessageHistoryEntity; +import org.springframework.stereotype.Repository; + +@Repository +public interface ImGroupMessageHistoryMapper extends BaseMapper { + + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/AddGroupMemberReq.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/AddGroupMemberReq.java new file mode 100644 index 0000000..6f8ce3b --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/AddGroupMemberReq.java @@ -0,0 +1,24 @@ +package com.lld.im.service.group.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import java.util.List; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Data +public class AddGroupMemberReq extends RequestBase { + + @NotBlank(message = "群id不能为空") + private String groupId; + + @NotEmpty(message = "群成员不能为空") + private List members; + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/CreateGroupReq.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/CreateGroupReq.java new file mode 100644 index 0000000..ba4f30b --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/CreateGroupReq.java @@ -0,0 +1,41 @@ +package com.lld.im.service.group.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import java.util.List; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Data +public class CreateGroupReq extends RequestBase { + + private String groupId; + //群主id + private String ownerId; + + //群类型 1私有群(类似微信) 2公开群(类似qq) + private Integer groupType; + + private String groupName; + + private Integer mute;// 是否全员禁言,0 不禁言;1 全员禁言。 + + private Integer applyJoinType;//加入群权限,0 所有人可以加入;1 群成员可以拉人;2 群管理员或群组可以拉人。 + + private String introduction;//群简介 + + private String notification;//群公告 + + private String photo;//群头像 + + private Integer MaxMemberCount; + + private List member; + + private String extra; + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/DestroyGroupReq.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/DestroyGroupReq.java new file mode 100644 index 0000000..15bffb8 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/DestroyGroupReq.java @@ -0,0 +1,18 @@ +package com.lld.im.service.group.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author: Chackylee + * @description: + **/ +@Data +public class DestroyGroupReq extends RequestBase { + + @NotNull(message = "群id不能为空") + private String groupId; + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/GetGroupReq.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/GetGroupReq.java new file mode 100644 index 0000000..6c1c007 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/GetGroupReq.java @@ -0,0 +1,15 @@ +package com.lld.im.service.group.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +/** + * @author: Chackylee + * @description: + **/ +@Data +public class GetGroupReq extends RequestBase { + + private String groupId; + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/GetJoinedGroupReq.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/GetJoinedGroupReq.java new file mode 100644 index 0000000..8038d60 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/GetJoinedGroupReq.java @@ -0,0 +1,29 @@ +package com.lld.im.service.group.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import java.util.List; + +/** + * @author: Chackylee + * @description: + **/ +@Data +public class GetJoinedGroupReq extends RequestBase { + + @NotBlank(message = "用户id不能为空") + private String memberId; + + //群类型 + private List groupType; + + //单次拉取的群组数量,如果不填代表所有群组 + private Integer limit; + + //第几页 + private Integer offset; + + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/GetRoleInGroupReq.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/GetRoleInGroupReq.java new file mode 100644 index 0000000..bb3f242 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/GetRoleInGroupReq.java @@ -0,0 +1,18 @@ +package com.lld.im.service.group.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import java.util.List; + +/** + * @author: Chackylee + * @description: + **/ +@Data +public class GetRoleInGroupReq extends RequestBase { + + private String groupId; + + private List memberId; +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/GroupMemberDto.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/GroupMemberDto.java new file mode 100644 index 0000000..f6fb2c4 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/GroupMemberDto.java @@ -0,0 +1,28 @@ +package com.lld.im.service.group.model.req; + +import lombok.Data; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ + +@Data +public class GroupMemberDto { + + private String memberId; + + private String alias; + + private Integer role;//群成员类型,0 普通成员, 1 管理员, 2 群主, 3 已经移除的成员,当修改群成员信息时,只能取值0/1,其他值由其他接口实现,暂不支持3 + +// private Integer speakFlag; + + private Long speakDate; + + private String joinType; + + private Long joinTime; + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/ImportGroupMemberReq.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/ImportGroupMemberReq.java new file mode 100644 index 0000000..0a61e0f --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/ImportGroupMemberReq.java @@ -0,0 +1,22 @@ +package com.lld.im.service.group.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import java.util.List; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Data +public class ImportGroupMemberReq extends RequestBase { + + @NotBlank(message = "群id不能为空") + private String groupId; + + private List members; + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/ImportGroupReq.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/ImportGroupReq.java new file mode 100644 index 0000000..422dabb --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/ImportGroupReq.java @@ -0,0 +1,42 @@ +package com.lld.im.service.group.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Data +public class ImportGroupReq extends RequestBase { + + private String groupId; + //群主id + private String ownerId; + + //群类型 1私有群(类似微信) 2公开群(类似qq) + private Integer groupType; + + @NotBlank(message = "群名称不能为空") + private String groupName; + + private Integer mute;// 是否全员禁言,0 不禁言;1 全员禁言。 + + private Integer applyJoinType;//加入群权限,0 所有人可以加入;1 群成员可以拉人;2 群管理员或群组可以拉人。 + + private String introduction;//群简介 + + private String notification;//群公告 + + private String photo;//群头像 + + private Integer MaxMemberCount; + + private Long createTime; + + private String extra; + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/MuteGroupReq.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/MuteGroupReq.java new file mode 100644 index 0000000..680e432 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/MuteGroupReq.java @@ -0,0 +1,22 @@ +package com.lld.im.service.group.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + * @author: Chackylee + * @description: + **/ +@Data +public class MuteGroupReq extends RequestBase { + + @NotBlank(message = "groupId不能为空") + private String groupId; + + @NotNull(message = "mute不能为空") + private Integer mute; + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/RemoveGroupMemberReq.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/RemoveGroupMemberReq.java new file mode 100644 index 0000000..32db73e --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/RemoveGroupMemberReq.java @@ -0,0 +1,20 @@ +package com.lld.im.service.group.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + +/** + * @author: Chackylee + * @description: + **/ +@Data +public class RemoveGroupMemberReq extends RequestBase { + + @NotBlank(message = "群id不能为空") + private String groupId; + + private String memberId; + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/SendGroupMessageReq.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/SendGroupMessageReq.java new file mode 100644 index 0000000..f9e6781 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/SendGroupMessageReq.java @@ -0,0 +1,35 @@ +package com.lld.im.service.group.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Data +public class SendGroupMessageReq extends RequestBase { + + //客户端传的messageId + private String messageId; + + private String fromId; + + private String groupId; + + private int messageRandom; + + private long messageTime; + + private String messageBody; + /** + * 这个字段缺省或者为 0 表示需要计数,为 1 表示本条消息不需要计数,即右上角图标数字不增加 + */ + private int badgeMode; + + private Long messageLifeTime; + + private Integer appId; + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/SpeaMemberReq.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/SpeaMemberReq.java new file mode 100644 index 0000000..64cbae7 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/SpeaMemberReq.java @@ -0,0 +1,25 @@ +package com.lld.im.service.group.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + * @author: Chackylee + * @description: + **/ +@Data +public class SpeaMemberReq extends RequestBase { + + @NotBlank(message = "群id不能为空") + private String groupId; + + @NotBlank(message = "memberId不能为空") + private String memberId; + + //禁言时间,单位毫秒 + @NotNull(message = "禁言时间不能为空") + private Long speakDate; +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/TransferGroupReq.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/TransferGroupReq.java new file mode 100644 index 0000000..f53567f --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/TransferGroupReq.java @@ -0,0 +1,17 @@ +package com.lld.im.service.group.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotNull; + + +@Data +public class TransferGroupReq extends RequestBase { + + @NotNull(message = "群id不能为空") + private String groupId; + + private String ownerId; + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/UpdateGroupMemberReq.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/UpdateGroupMemberReq.java new file mode 100644 index 0000000..e44d4ba --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/UpdateGroupMemberReq.java @@ -0,0 +1,27 @@ +package com.lld.im.service.group.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + +/** + * @author: Chackylee + * @description: + **/ +@Data +public class UpdateGroupMemberReq extends RequestBase { + + @NotBlank(message = "群id不能为空") + private String groupId; + + @NotBlank(message = "memberId不能为空") + private String memberId; + + private String alias; + + private Integer role; + + private String extra; + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/UpdateGroupReq.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/UpdateGroupReq.java new file mode 100644 index 0000000..d70a9a7 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/req/UpdateGroupReq.java @@ -0,0 +1,34 @@ +package com.lld.im.service.group.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + +/** + * @author: Chackylee + * @description: + **/ +@Data +public class UpdateGroupReq extends RequestBase { + + @NotBlank(message = "群id不能为空") + private String groupId; + + private String groupName; + + private Integer mute;// 是否全员禁言,0 不禁言;1 全员禁言。 + + private Integer applyJoinType;//加入群权限,0 所有人可以加入;1 群成员可以拉人;2 群管理员或群组可以拉人。 + + private String introduction;//群简介 + + private String notification;//群公告 + + private String photo;//群头像 + + private Integer maxMemberCount;//群成员上限 + + private String extra; + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/resp/AddMemberResp.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/resp/AddMemberResp.java new file mode 100644 index 0000000..8614833 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/resp/AddMemberResp.java @@ -0,0 +1,19 @@ +package com.lld.im.service.group.model.resp; + +import lombok.Data; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Data +public class AddMemberResp { + + private String memberId; + + // 加人结果:0 为成功;1 为失败;2 为已经是群成员 + private Integer result; + + private String resultMessage; +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/resp/GetGroupResp.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/resp/GetGroupResp.java new file mode 100644 index 0000000..3cd10bb --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/resp/GetGroupResp.java @@ -0,0 +1,48 @@ +package com.lld.im.service.group.model.resp; + +import com.lld.im.service.group.model.req.GroupMemberDto; +import lombok.Data; + +import java.util.List; + +/** + * @author: Chackylee + * @description: + **/ +@Data +public class GetGroupResp { + + private String groupId; + + private Integer appId; + + //群主id + private String ownerId; + + //群类型 1私有群(类似微信) 2公开群(类似qq) + private Integer groupType; + + private String groupName; + + private Integer mute;// 是否全员禁言,0 不禁言;1 全员禁言。 + + // 申请加群选项包括如下几种: +// 0 表示禁止任何人申请加入 +// 1 表示需要群主或管理员审批 +// 2 表示允许无需审批自由加入群组 + private Integer applyJoinType; + + private Integer privateChat; //是否禁止私聊,0 允许群成员发起私聊;1 不允许群成员发起私聊。 + + private String introduction;//群简介 + + private String notification;//群公告 + + private String photo;//群头像 + + private Integer maxMemberCount;//群成员上限 + + private Integer status;//群状态 0正常 1解散 + + private List memberList; +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/resp/GetJoinedGroupResp.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/resp/GetJoinedGroupResp.java new file mode 100644 index 0000000..a156a49 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/resp/GetJoinedGroupResp.java @@ -0,0 +1,19 @@ +package com.lld.im.service.group.model.resp; + +import com.lld.im.service.group.dao.ImGroupEntity; +import lombok.Data; + +import java.util.List; + +/** + * @author: Chackylee + * @description: + **/ +@Data +public class GetJoinedGroupResp { + + private Integer totalCount; + + private List groupList; + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/resp/GetRoleInGroupResp.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/resp/GetRoleInGroupResp.java new file mode 100644 index 0000000..e4cf87d --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/model/resp/GetRoleInGroupResp.java @@ -0,0 +1,20 @@ +package com.lld.im.service.group.model.resp; + +import lombok.Data; + +/** + * @author: Chackylee + * @description: + **/ +@Data +public class GetRoleInGroupResp { + + private Long groupMemberId; + + private String memberId; + + private Integer role; + + private Long speakDate; + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/service/ImGroupMemberService.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/service/ImGroupMemberService.java new file mode 100644 index 0000000..6154733 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/service/ImGroupMemberService.java @@ -0,0 +1,43 @@ +package com.lld.im.service.group.service; + +import com.lld.im.common.ResponseVO; +import com.lld.im.service.group.model.req.*; +import com.lld.im.service.group.model.resp.GetRoleInGroupResp; + +import java.util.Collection; +import java.util.List; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +public interface ImGroupMemberService { + + public ResponseVO importGroupMember(ImportGroupMemberReq req); + + public ResponseVO addMember(AddGroupMemberReq req); + + public ResponseVO removeMember(RemoveGroupMemberReq req); + + public ResponseVO addGroupMember(String groupId, Integer appId, GroupMemberDto dto); + + public ResponseVO removeGroupMember(String groupId, Integer appId, String memberId); + + public ResponseVO getRoleInGroupOne(String groupId, String memberId, Integer appId); + + public ResponseVO> getMemberJoinedGroup(GetJoinedGroupReq req); + + public ResponseVO> getGroupMember(String groupId, Integer appId); + + public List getGroupMemberId(String groupId, Integer appId); + + public List getGroupManager(String groupId, Integer appId); + + public ResponseVO updateGroupMember(UpdateGroupMemberReq req); + + public ResponseVO transferGroupMember(String owner, String groupId, Integer appId); + + public ResponseVO speak(SpeaMemberReq req); + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/service/ImGroupService.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/service/ImGroupService.java new file mode 100644 index 0000000..eeb140c --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/service/ImGroupService.java @@ -0,0 +1,32 @@ +package com.lld.im.service.group.service; + +import com.lld.im.common.ResponseVO; +import com.lld.im.service.group.dao.ImGroupEntity; +import com.lld.im.service.group.model.req.*; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +public interface ImGroupService { + + public ResponseVO importGroup(ImportGroupReq req); + + public ResponseVO createGroup(CreateGroupReq req); + + public ResponseVO updateBaseGroupInfo(UpdateGroupReq req); + + public ResponseVO getJoinedGroup(GetJoinedGroupReq req); + + public ResponseVO destroyGroup(DestroyGroupReq req); + + public ResponseVO transferGroup(TransferGroupReq req); + + public ResponseVO getGroup(String groupId, Integer appId); + + public ResponseVO getGroup(GetGroupReq req); + + public ResponseVO muteGroup(MuteGroupReq req); + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/service/impl/ImGroupMemberServiceImpl.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/service/impl/ImGroupMemberServiceImpl.java new file mode 100644 index 0000000..df91cd8 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/service/impl/ImGroupMemberServiceImpl.java @@ -0,0 +1,537 @@ +package com.lld.im.service.group.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.lld.im.common.ResponseVO; +import com.lld.im.common.enums.GroupErrorCode; +import com.lld.im.common.enums.GroupMemberRoleEnum; +import com.lld.im.common.enums.GroupStatusEnum; +import com.lld.im.common.enums.GroupTypeEnum; +import com.lld.im.common.exception.ApplicationException; +import com.lld.im.service.group.dao.ImGroupEntity; +import com.lld.im.service.group.dao.ImGroupMemberEntity; +import com.lld.im.service.group.dao.mapper.ImGroupMemberMapper; +import com.lld.im.service.group.model.req.*; +import com.lld.im.service.group.model.resp.AddMemberResp; +import com.lld.im.service.group.model.resp.GetRoleInGroupResp; +import com.lld.im.service.group.service.ImGroupMemberService; +import com.lld.im.service.group.service.ImGroupService; +import com.lld.im.service.user.dao.ImUserDataEntity; +import com.lld.im.service.user.service.ImUserService; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Service +@Slf4j +public class ImGroupMemberServiceImpl implements ImGroupMemberService { + + @Autowired + ImGroupMemberMapper imGroupMemberMapper; + + @Autowired + ImGroupService groupService; + + @Autowired + ImGroupMemberService groupMemberService; + + @Autowired + ImUserService imUserService; + + @Override + public ResponseVO importGroupMember(ImportGroupMemberReq req) { + + List resp = new ArrayList<>(); + + ResponseVO groupResp = groupService.getGroup(req.getGroupId(), req.getAppId()); + if (!groupResp.isOk()) { + return groupResp; + } + + for (GroupMemberDto memberId : + req.getMembers()) { + ResponseVO responseVO = null; + try { + responseVO = groupMemberService.addGroupMember(req.getGroupId(), req.getAppId(), memberId); + } catch (Exception e) { + e.printStackTrace(); + responseVO = ResponseVO.errorResponse(); + } + AddMemberResp addMemberResp = new AddMemberResp(); + addMemberResp.setMemberId(memberId.getMemberId()); + if (responseVO.isOk()) { + addMemberResp.setResult(0); + } else if (responseVO.getCode() == GroupErrorCode.USER_IS_JOINED_GROUP.getCode()) { + addMemberResp.setResult(2); + } else { + addMemberResp.setResult(1); + } + resp.add(addMemberResp); + } + + return ResponseVO.successResponse(resp); + } + + /** + * @param + * @return com.lld.im.common.ResponseVO + * @description: 添加群成员,内部调用 + * @author lld + */ + @Override + @Transactional + public ResponseVO addGroupMember(String groupId, Integer appId, GroupMemberDto dto) { + + ResponseVO singleUserInfo = imUserService.getSingleUserInfo(dto.getMemberId(), appId); + if (!singleUserInfo.isOk()) { + return singleUserInfo; + } + + if (dto.getRole() != null && GroupMemberRoleEnum.OWNER.getCode() == dto.getRole()) { + QueryWrapper queryOwner = new QueryWrapper<>(); + queryOwner.eq("group_id", groupId); + queryOwner.eq("app_id", appId); + queryOwner.eq("role", GroupMemberRoleEnum.OWNER.getCode()); + Integer ownerNum = imGroupMemberMapper.selectCount(queryOwner); + if (ownerNum > 0) { + return ResponseVO.errorResponse(GroupErrorCode.GROUP_IS_HAVE_OWNER); + } + } + + QueryWrapper query = new QueryWrapper<>(); + query.eq("group_id", groupId); + query.eq("app_id", appId); + query.eq("member_id", dto.getMemberId()); + ImGroupMemberEntity memberDto = imGroupMemberMapper.selectOne(query); + + long now = System.currentTimeMillis(); + if (memberDto == null) { + //初次加群 + memberDto = new ImGroupMemberEntity(); + BeanUtils.copyProperties(dto, memberDto); + memberDto.setGroupId(groupId); + memberDto.setAppId(appId); + memberDto.setJoinTime(now); + int insert = imGroupMemberMapper.insert(memberDto); + if (insert == 1) { + return ResponseVO.successResponse(); + } + return ResponseVO.errorResponse(GroupErrorCode.USER_JOIN_GROUP_ERROR); + } else if (GroupMemberRoleEnum.LEAVE.getCode() == memberDto.getRole()) { + //重新进群 + memberDto = new ImGroupMemberEntity(); + BeanUtils.copyProperties(dto, memberDto); + memberDto.setJoinTime(now); + int update = imGroupMemberMapper.update(memberDto, query); + if (update == 1) { + return ResponseVO.successResponse(); + } + return ResponseVO.errorResponse(GroupErrorCode.USER_JOIN_GROUP_ERROR); + } + + return ResponseVO.errorResponse(GroupErrorCode.USER_IS_JOINED_GROUP); + + } + + /** + * @param + * @return com.lld.im.common.ResponseVO + * @description: 删除群成员,内部调用 + * @author lld + */ + @Override + public ResponseVO removeGroupMember(String groupId, Integer appId, String memberId) { + + ResponseVO singleUserInfo = imUserService.getSingleUserInfo(memberId, appId); + if (!singleUserInfo.isOk()) { + return singleUserInfo; + } + + ResponseVO roleInGroupOne = getRoleInGroupOne(groupId, memberId, appId); + if (!roleInGroupOne.isOk()) { + return roleInGroupOne; + } + + GetRoleInGroupResp data = roleInGroupOne.getData(); + ImGroupMemberEntity imGroupMemberEntity = new ImGroupMemberEntity(); + imGroupMemberEntity.setRole(GroupMemberRoleEnum.LEAVE.getCode()); + imGroupMemberEntity.setLeaveTime(System.currentTimeMillis()); + imGroupMemberEntity.setGroupMemberId(data.getGroupMemberId()); + imGroupMemberMapper.updateById(imGroupMemberEntity); + return ResponseVO.successResponse(); + } + + /** + * @param [groupId, memberId, appId] + * @return com.lld.im.common.ResponseVO + * @description 查询用户在群内的角色 + * @author chackylee + */ + @Override + public ResponseVO getRoleInGroupOne(String groupId, String memberId, Integer appId) { + + GetRoleInGroupResp resp = new GetRoleInGroupResp(); + + QueryWrapper queryOwner = new QueryWrapper<>(); + queryOwner.eq("group_id", groupId); + queryOwner.eq("app_id", appId); + queryOwner.eq("member_id", memberId); + + ImGroupMemberEntity imGroupMemberEntity = imGroupMemberMapper.selectOne(queryOwner); + if (imGroupMemberEntity == null || imGroupMemberEntity.getRole() == GroupMemberRoleEnum.LEAVE.getCode()) { + return ResponseVO.errorResponse(GroupErrorCode.MEMBER_IS_NOT_JOINED_GROUP); + } + + resp.setSpeakDate(imGroupMemberEntity.getSpeakDate()); + resp.setGroupMemberId(imGroupMemberEntity.getGroupMemberId()); + resp.setMemberId(imGroupMemberEntity.getMemberId()); + resp.setRole(imGroupMemberEntity.getRole()); + return ResponseVO.successResponse(resp); + } + + @Override + public ResponseVO> getMemberJoinedGroup(GetJoinedGroupReq req) { + + if (req.getLimit() != null) { + Page objectPage = new Page<>(req.getOffset(), req.getLimit()); + QueryWrapper query = new QueryWrapper<>(); + query.eq("app_id", req.getAppId()); + query.eq("member_id", req.getMemberId()); + IPage imGroupMemberEntityPage = imGroupMemberMapper.selectPage(objectPage, query); + + Set groupId = new HashSet<>(); + List records = imGroupMemberEntityPage.getRecords(); + records.forEach(e -> { + groupId.add(e.getGroupId()); + }); + + return ResponseVO.successResponse(groupId); + } else { + return ResponseVO.successResponse(imGroupMemberMapper.getJoinedGroupId(req.getAppId(), req.getMemberId())); + } + } + + /** + * @param + * @return com.lld.im.common.ResponseVO + * @description: 添加群成员,拉人入群的逻辑,直接进入群聊。如果是后台管理员,则直接拉入群, + * 否则只有私有群可以调用本接口,并且群成员也可以拉人入群.只有私有群可以调用本接口 + * @author lld + */ + @Override + public ResponseVO addMember(AddGroupMemberReq req) { + + List resp = new ArrayList<>(); + + boolean isAdmin = false; + ResponseVO groupResp = groupService.getGroup(req.getGroupId(), req.getAppId()); + if (!groupResp.isOk()) { + return groupResp; + } + + List memberDtos = req.getMembers(); + + ImGroupEntity group = groupResp.getData(); + + /** + * 私有群(private) 类似普通微信群,创建后仅支持已在群内的好友邀请加群,且无需被邀请方同意或群主审批 + * 公开群(Public) 类似 QQ 群,创建后群主可以指定群管理员,需要群主或管理员审批通过才能入群 + * 群类型 1私有群(类似微信) 2公开群(类似qq) + */ + if (!isAdmin && GroupTypeEnum.PUBLIC.getCode() == group.getGroupType()) { + throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_APPMANAGER_ROLE); + } + + List successId = new ArrayList<>(); + for (GroupMemberDto memberId : + memberDtos) { + ResponseVO responseVO = null; + try { + responseVO = groupMemberService.addGroupMember(req.getGroupId(), req.getAppId(), memberId); + } catch (Exception e) { + e.printStackTrace(); + responseVO = ResponseVO.errorResponse(); + } + AddMemberResp addMemberResp = new AddMemberResp(); + addMemberResp.setMemberId(memberId.getMemberId()); + if (responseVO.isOk()) { + successId.add(memberId.getMemberId()); + addMemberResp.setResult(0); + } else if (responseVO.getCode() == GroupErrorCode.USER_IS_JOINED_GROUP.getCode()) { + addMemberResp.setResult(2); + addMemberResp.setResultMessage(responseVO.getMsg()); + } else { + addMemberResp.setResult(1); + addMemberResp.setResultMessage(responseVO.getMsg()); + } + resp.add(addMemberResp); + } + + return ResponseVO.successResponse(resp); + } + + @Override + public ResponseVO removeMember(RemoveGroupMemberReq req) { + + boolean isAdmin = false; + ResponseVO groupResp = groupService.getGroup(req.getGroupId(), req.getAppId()); + if (!groupResp.isOk()) { + return groupResp; + } + + ImGroupEntity group = groupResp.getData(); + + if (!isAdmin) { + if (GroupTypeEnum.PUBLIC.getCode() == group.getGroupType()) { + + //获取操作人的权限 是管理员or群主or群成员 + ResponseVO role = getRoleInGroupOne(req.getGroupId(), req.getOperater(), req.getAppId()); + if (!role.isOk()) { + return role; + } + + GetRoleInGroupResp data = role.getData(); + Integer roleInfo = data.getRole(); + + boolean isOwner = roleInfo == GroupMemberRoleEnum.OWNER.getCode(); + boolean isManager = roleInfo == GroupMemberRoleEnum.MAMAGER.getCode(); + + if (!isOwner && !isManager) { + throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_MANAGER_ROLE); + } + + //私有群必须是群主才能踢人 + if (!isOwner && GroupTypeEnum.PRIVATE.getCode() == group.getGroupType()) { + throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_OWNER_ROLE); + } + + //公开群管理员和群主可踢人,但管理员只能踢普通群成员 + if (GroupTypeEnum.PUBLIC.getCode() == group.getGroupType()) { +// throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_MANAGER_ROLE); + //获取被踢人的权限 + ResponseVO roleInGroupOne = this.getRoleInGroupOne(req.getGroupId(), req.getMemberId(), req.getAppId()); + if (!roleInGroupOne.isOk()) { + return roleInGroupOne; + } + GetRoleInGroupResp memberRole = roleInGroupOne.getData(); + if (memberRole.getRole() == GroupMemberRoleEnum.OWNER.getCode()) { + throw new ApplicationException(GroupErrorCode.GROUP_OWNER_IS_NOT_REMOVE); + } + //是管理员并且被踢人不是群成员,无法操作 + if (isManager && memberRole.getRole() != GroupMemberRoleEnum.ORDINARY.getCode()) { + throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_OWNER_ROLE); + } + } + } + } + ResponseVO responseVO = groupMemberService.removeGroupMember(req.getGroupId(), req.getAppId(), req.getMemberId()); + return responseVO; + } + + @Override + public ResponseVO> getGroupMember(String groupId, Integer appId) { + List groupMember = imGroupMemberMapper.getGroupMember(appId, groupId); + return ResponseVO.successResponse(groupMember); + } + + @Override + public List getGroupMemberId(String groupId, Integer appId) { + return imGroupMemberMapper.getGroupMemberId(appId, groupId); + } + + @Override + public List getGroupManager(String groupId, Integer appId) { + return imGroupMemberMapper.getGroupManager(groupId, appId); + } + + @Override + public ResponseVO updateGroupMember(UpdateGroupMemberReq req) { + + boolean isadmin = false; + + ResponseVO group = groupService.getGroup(req.getGroupId(), req.getAppId()); + if (!group.isOk()) { + return group; + } + + ImGroupEntity groupData = group.getData(); + if (groupData.getStatus() == GroupStatusEnum.DESTROY.getCode()) { + throw new ApplicationException(GroupErrorCode.GROUP_IS_DESTROY); + } + + //是否是自己修改自己的资料 + boolean isMeOperate = req.getOperater().equals(req.getMemberId()); + + if (!isadmin) { + //昵称只能自己修改 权限只能群主或管理员修改 + if (StringUtils.isBlank(req.getAlias()) && !isMeOperate) { + return ResponseVO.errorResponse(GroupErrorCode.THIS_OPERATE_NEED_ONESELF); + } + + //如果要修改权限相关的则走下面的逻辑 + if (req.getRole() != null) { + //私有群不能设置管理员 + if (groupData.getGroupType() == GroupTypeEnum.PRIVATE.getCode() && + req.getRole() != null && (req.getRole() == GroupMemberRoleEnum.MAMAGER.getCode() || + req.getRole() == GroupMemberRoleEnum.OWNER.getCode())) { + return ResponseVO.errorResponse(GroupErrorCode.THIS_OPERATE_NEED_APPMANAGER_ROLE); + } + + //获取被操作人的是否在群内 + ResponseVO roleInGroupOne = this.getRoleInGroupOne(req.getGroupId(), req.getMemberId(), req.getAppId()); + if (!roleInGroupOne.isOk()) { + return roleInGroupOne; + } + + //获取操作人权限 + ResponseVO operateRoleInGroupOne = this.getRoleInGroupOne(req.getGroupId(), req.getOperater(), req.getAppId()); + if (!operateRoleInGroupOne.isOk()) { + return operateRoleInGroupOne; + } + + GetRoleInGroupResp data = operateRoleInGroupOne.getData(); + Integer roleInfo = data.getRole(); + boolean isOwner = roleInfo == GroupMemberRoleEnum.OWNER.getCode(); + boolean isManager = roleInfo == GroupMemberRoleEnum.MAMAGER.getCode(); + + //不是管理员不能修改权限 + if (req.getRole() != null && !isOwner && !isManager) { + return ResponseVO.errorResponse(GroupErrorCode.THIS_OPERATE_NEED_MANAGER_ROLE); + } + + //管理员只有群主能够设置 + if (req.getRole() != null && req.getRole() == GroupMemberRoleEnum.MAMAGER.getCode() && !isOwner) { + return ResponseVO.errorResponse(GroupErrorCode.THIS_OPERATE_NEED_OWNER_ROLE); + } + + } + } + + ImGroupMemberEntity update = new ImGroupMemberEntity(); + + if (StringUtils.isNotBlank(req.getAlias())) { + update.setAlias(req.getAlias()); + } + + //不能直接修改为群主 + if(req.getRole() != null && req.getRole() != GroupMemberRoleEnum.OWNER.getCode()){ + update.setRole(req.getRole()); + } + + UpdateWrapper objectUpdateWrapper = new UpdateWrapper<>(); + objectUpdateWrapper.eq("app_id", req.getAppId()); + objectUpdateWrapper.eq("member_id", req.getMemberId()); + objectUpdateWrapper.eq("group_id", req.getGroupId()); + imGroupMemberMapper.update(update, objectUpdateWrapper); + + return ResponseVO.successResponse(); + } + + @Override + @Transactional + public ResponseVO transferGroupMember(String owner, String groupId, Integer appId) { + + //更新旧群主 + ImGroupMemberEntity imGroupMemberEntity = new ImGroupMemberEntity(); + imGroupMemberEntity.setRole(GroupMemberRoleEnum.ORDINARY.getCode()); + UpdateWrapper updateWrapper = new UpdateWrapper<>(); + updateWrapper.eq("app_id", appId); + updateWrapper.eq("group_id", groupId); + updateWrapper.eq("role", GroupMemberRoleEnum.OWNER.getCode()); + imGroupMemberMapper.update(imGroupMemberEntity, updateWrapper); + + //更新新群主 + ImGroupMemberEntity newOwner = new ImGroupMemberEntity(); + newOwner.setRole(GroupMemberRoleEnum.OWNER.getCode()); + UpdateWrapper ownerWrapper = new UpdateWrapper<>(); + ownerWrapper.eq("app_id", appId); + ownerWrapper.eq("group_id", groupId); + ownerWrapper.eq("member_id", owner); + imGroupMemberMapper.update(newOwner, ownerWrapper); + + return ResponseVO.successResponse(); + } + + @Override + public ResponseVO speak(SpeaMemberReq req) { + + ResponseVO groupResp = groupService.getGroup(req.getGroupId(), req.getAppId()); + if (!groupResp.isOk()) { + return groupResp; + } + + boolean isadmin = false; + boolean isOwner = false; + boolean isManager = false; + GetRoleInGroupResp memberRole = null; + + if (!isadmin) { + + //获取操作人的权限 是管理员or群主or群成员 + ResponseVO role = getRoleInGroupOne(req.getGroupId(), req.getOperater(), req.getAppId()); + if (!role.isOk()) { + return role; + } + + GetRoleInGroupResp data = role.getData(); + Integer roleInfo = data.getRole(); + + isOwner = roleInfo == GroupMemberRoleEnum.OWNER.getCode(); + isManager = roleInfo == GroupMemberRoleEnum.MAMAGER.getCode(); + + if (!isOwner && !isManager) { + throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_MANAGER_ROLE); + } + + //获取被操作的权限 + ResponseVO roleInGroupOne = this.getRoleInGroupOne(req.getGroupId(), req.getMemberId(), req.getAppId()); + if (!roleInGroupOne.isOk()) { + return roleInGroupOne; + } + memberRole = roleInGroupOne.getData(); + //被操作人是群主只能app管理员操作 + if (memberRole.getRole() == GroupMemberRoleEnum.OWNER.getCode()) { + throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_APPMANAGER_ROLE); + } + + //是管理员并且被操作人不是群成员,无法操作 + if (isManager && memberRole.getRole() != GroupMemberRoleEnum.ORDINARY.getCode()) { + throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_OWNER_ROLE); + } + } + + ImGroupMemberEntity imGroupMemberEntity = new ImGroupMemberEntity(); + if (memberRole == null) { + //获取被操作的权限 + ResponseVO roleInGroupOne = this.getRoleInGroupOne(req.getGroupId(), req.getMemberId(), req.getAppId()); + if (!roleInGroupOne.isOk()) { + return roleInGroupOne; + } + memberRole = roleInGroupOne.getData(); + } + + imGroupMemberEntity.setGroupMemberId(memberRole.getGroupMemberId()); + if (req.getSpeakDate() > 0) { + imGroupMemberEntity.setSpeakDate(System.currentTimeMillis() + req.getSpeakDate()); + } else { + imGroupMemberEntity.setSpeakDate(req.getSpeakDate()); + } + + int i = imGroupMemberMapper.updateById(imGroupMemberEntity); + return ResponseVO.successResponse(); + } + + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/service/impl/ImGroupServiceImpl.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/service/impl/ImGroupServiceImpl.java new file mode 100644 index 0000000..d8760e9 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/group/service/impl/ImGroupServiceImpl.java @@ -0,0 +1,393 @@ +package com.lld.im.service.group.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import com.lld.im.common.ResponseVO; +import com.lld.im.common.enums.GroupErrorCode; +import com.lld.im.common.enums.GroupMemberRoleEnum; +import com.lld.im.common.enums.GroupStatusEnum; +import com.lld.im.common.enums.GroupTypeEnum; +import com.lld.im.common.exception.ApplicationException; +import com.lld.im.common.model.ClientInfo; +import com.lld.im.service.group.dao.ImGroupEntity; +import com.lld.im.service.group.dao.mapper.ImGroupMapper; +import com.lld.im.service.group.model.req.*; +import com.lld.im.service.group.model.resp.GetGroupResp; +import com.lld.im.service.group.model.resp.GetJoinedGroupResp; +import com.lld.im.service.group.model.resp.GetRoleInGroupResp; +import com.lld.im.service.group.service.ImGroupMemberService; +import com.lld.im.service.group.service.ImGroupService; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.UUID; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Service +public class ImGroupServiceImpl implements ImGroupService { + + @Autowired + ImGroupMapper imGroupDataMapper; + + @Autowired + ImGroupMemberService groupMemberService; + + + @Override + public ResponseVO importGroup(ImportGroupReq req) { + + //1.判断群id是否存在 + QueryWrapper query = new QueryWrapper<>(); + + if (StringUtils.isEmpty(req.getGroupId())) { + req.setGroupId(UUID.randomUUID().toString().replace("-", "")); + } else { + query.eq("group_id", req.getGroupId()); + query.eq("app_id", req.getAppId()); + Integer integer = imGroupDataMapper.selectCount(query); + if (integer > 0) { + throw new ApplicationException(GroupErrorCode.GROUP_IS_EXIST); + } + } + + ImGroupEntity imGroupEntity = new ImGroupEntity(); + + if (req.getGroupType() == GroupTypeEnum.PUBLIC.getCode() && StringUtils.isBlank(req.getOwnerId())) { + throw new ApplicationException(GroupErrorCode.PUBLIC_GROUP_MUST_HAVE_OWNER); + } + + if (req.getCreateTime() == null) { + imGroupEntity.setCreateTime(System.currentTimeMillis()); + } + imGroupEntity.setStatus(GroupStatusEnum.NORMAL.getCode()); + BeanUtils.copyProperties(req, imGroupEntity); + int insert = imGroupDataMapper.insert(imGroupEntity); + + if (insert != 1) { + throw new ApplicationException(GroupErrorCode.IMPORT_GROUP_ERROR); + } + + return ResponseVO.successResponse(); + } + + @Override + @Transactional + public ResponseVO createGroup(CreateGroupReq req) { + + boolean isAdmin = false; + + if (!isAdmin) { + req.setOwnerId(req.getOperater()); + } + + //1.判断群id是否存在 + QueryWrapper query = new QueryWrapper<>(); + + if (StringUtils.isEmpty(req.getGroupId())) { + req.setGroupId(UUID.randomUUID().toString().replace("-", "")); + } else { + query.eq("group_id", req.getGroupId()); + query.eq("app_id", req.getAppId()); + Integer integer = imGroupDataMapper.selectCount(query); + if (integer > 0) { + throw new ApplicationException(GroupErrorCode.GROUP_IS_EXIST); + } + } + + if (req.getGroupType() == GroupTypeEnum.PUBLIC.getCode() && StringUtils.isBlank(req.getOwnerId())) { + throw new ApplicationException(GroupErrorCode.PUBLIC_GROUP_MUST_HAVE_OWNER); + } + + ImGroupEntity imGroupEntity = new ImGroupEntity(); + imGroupEntity.setCreateTime(System.currentTimeMillis()); + imGroupEntity.setStatus(GroupStatusEnum.NORMAL.getCode()); + BeanUtils.copyProperties(req, imGroupEntity); + int insert = imGroupDataMapper.insert(imGroupEntity); + + GroupMemberDto groupMemberDto = new GroupMemberDto(); + groupMemberDto.setMemberId(req.getOwnerId()); + groupMemberDto.setRole(GroupMemberRoleEnum.OWNER.getCode()); + groupMemberDto.setJoinTime(System.currentTimeMillis()); + groupMemberService.addGroupMember(req.getGroupId(), req.getAppId(), groupMemberDto); + + //插入群成员 + for (GroupMemberDto dto : req.getMember()) { + groupMemberService.addGroupMember(req.getGroupId(), req.getAppId(), dto); + } + + return ResponseVO.successResponse(); + } + + /** + * @param [req] + * @return com.lld.im.common.ResponseVO + * @description 修改群基础信息,如果是后台管理员调用,则不检查权限,如果不是则检查权限,如果是私有群(微信群)任何人都可以修改资料,公开群只有管理员可以修改 + * 如果是群主或者管理员可以修改其他信息。 + * @author chackylee + */ + @Override + @Transactional + public ResponseVO updateBaseGroupInfo(UpdateGroupReq req) { + + //1.判断群id是否存在 + QueryWrapper query = new QueryWrapper<>(); + query.eq("group_id", req.getGroupId()); + query.eq("app_id", req.getAppId()); + ImGroupEntity imGroupEntity = imGroupDataMapper.selectOne(query); + if (imGroupEntity == null) { + throw new ApplicationException(GroupErrorCode.GROUP_IS_EXIST); + } + + if(imGroupEntity.getStatus() == GroupStatusEnum.DESTROY.getCode()){ + throw new ApplicationException(GroupErrorCode.GROUP_IS_DESTROY); + } + + boolean isAdmin = false; + + if (!isAdmin) { + //不是后台调用需要检查权限 + ResponseVO role = groupMemberService.getRoleInGroupOne(req.getGroupId(), req.getOperater(), req.getAppId()); + + if (!role.isOk()) { + return role; + } + + GetRoleInGroupResp data = role.getData(); + Integer roleInfo = data.getRole(); + + boolean isManager = roleInfo == GroupMemberRoleEnum.MAMAGER.getCode() || roleInfo == GroupMemberRoleEnum.OWNER.getCode(); + + //公开群只能群主修改资料 + if (!isManager && GroupTypeEnum.PUBLIC.getCode() == imGroupEntity.getGroupType()) { + throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_MANAGER_ROLE); + } + + } + + ImGroupEntity update = new ImGroupEntity(); + BeanUtils.copyProperties(req, update); + update.setUpdateTime(System.currentTimeMillis()); + int row = imGroupDataMapper.update(update, query); + if (row != 1) { + throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_MANAGER_ROLE); + } + + return ResponseVO.successResponse(); + } + + /** + * @param [req] + * @return com.lld.im.common.ResponseVO + * @description 获取用户加入的群组 + * @author chackylee + */ + @Override + public ResponseVO getJoinedGroup(GetJoinedGroupReq req) { + + ResponseVO> memberJoinedGroup = groupMemberService.getMemberJoinedGroup(req); + if (memberJoinedGroup.isOk()) { + + GetJoinedGroupResp resp = new GetJoinedGroupResp(); + + if (CollectionUtils.isEmpty(memberJoinedGroup.getData())) { + resp.setTotalCount(0); + resp.setGroupList(new ArrayList<>()); + return ResponseVO.successResponse(resp); + } + + QueryWrapper query = new QueryWrapper<>(); + query.eq("app_id", req.getAppId()); + query.in("group_id", memberJoinedGroup.getData()); + + if (CollectionUtils.isNotEmpty(req.getGroupType())) { + query.in("group_type", req.getGroupType()); + } + + List groupList = imGroupDataMapper.selectList(query); + resp.setGroupList(groupList); + if (req.getLimit() == null) { + resp.setTotalCount(groupList.size()); + } else { + resp.setTotalCount(imGroupDataMapper.selectCount(query)); + } + return ResponseVO.successResponse(resp); + } else { + return memberJoinedGroup; + } + } + + + /** + * @param [req] + * @return com.lld.im.common.ResponseVO + * @description 解散群组,只支持后台管理员和群主解散 + * @author chackylee + */ + @Override + @Transactional + public ResponseVO destroyGroup(DestroyGroupReq req) { + + boolean isAdmin = false; + + QueryWrapper objectQueryWrapper = new QueryWrapper<>(); + objectQueryWrapper.eq("group_id", req.getGroupId()); + objectQueryWrapper.eq("app_id", req.getAppId()); + ImGroupEntity imGroupEntity = imGroupDataMapper.selectOne(objectQueryWrapper); + if (imGroupEntity == null) { + throw new ApplicationException(GroupErrorCode.PRIVATE_GROUP_CAN_NOT_DESTORY); + } + + if(imGroupEntity.getStatus() == GroupStatusEnum.DESTROY.getCode()){ + throw new ApplicationException(GroupErrorCode.GROUP_IS_DESTROY); + } + + if (!isAdmin) { + if (imGroupEntity.getGroupType() == GroupTypeEnum.PUBLIC.getCode()) { + throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_OWNER_ROLE); + } + + if (imGroupEntity.getGroupType() == GroupTypeEnum.PUBLIC.getCode() && + !imGroupEntity.getOwnerId().equals(req.getOperater())) { + throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_OWNER_ROLE); + } + } + + ImGroupEntity update = new ImGroupEntity(); + + update.setStatus(GroupStatusEnum.DESTROY.getCode()); + int update1 = imGroupDataMapper.update(update, objectQueryWrapper); + if (update1 != 1) { + throw new ApplicationException(GroupErrorCode.UPDATE_GROUP_BASE_INFO_ERROR); + } + return ResponseVO.successResponse(); + } + + @Override + @Transactional + public ResponseVO transferGroup(TransferGroupReq req) { + + ResponseVO roleInGroupOne = groupMemberService.getRoleInGroupOne(req.getGroupId(), req.getOperater(), req.getAppId()); + if (!roleInGroupOne.isOk()) { + return roleInGroupOne; + } + + if (roleInGroupOne.getData().getRole() != GroupMemberRoleEnum.OWNER.getCode()) { + return ResponseVO.errorResponse(GroupErrorCode.THIS_OPERATE_NEED_OWNER_ROLE); + } + + ResponseVO newOwnerRole = groupMemberService.getRoleInGroupOne(req.getGroupId(), req.getOwnerId(), req.getAppId()); + if (!newOwnerRole.isOk()) { + return newOwnerRole; + } + + QueryWrapper objectQueryWrapper = new QueryWrapper<>(); + objectQueryWrapper.eq("group_id", req.getGroupId()); + objectQueryWrapper.eq("app_id", req.getAppId()); + ImGroupEntity imGroupEntity = imGroupDataMapper.selectOne(objectQueryWrapper); + if(imGroupEntity.getStatus() == GroupStatusEnum.DESTROY.getCode()){ + throw new ApplicationException(GroupErrorCode.GROUP_IS_DESTROY); + } + + ImGroupEntity updateGroup = new ImGroupEntity(); + updateGroup.setOwnerId(req.getOwnerId()); + UpdateWrapper updateGroupWrapper = new UpdateWrapper<>(); + updateGroupWrapper.eq("app_id", req.getAppId()); + updateGroupWrapper.eq("group_id", req.getGroupId()); + imGroupDataMapper.update(updateGroup, updateGroupWrapper); + groupMemberService.transferGroupMember(req.getOwnerId(), req.getGroupId(), req.getAppId()); + + return ResponseVO.successResponse(); + } + + @Override + public ResponseVO getGroup(String groupId, Integer appId) { + + QueryWrapper query = new QueryWrapper<>(); + query.eq("app_id", appId); + query.eq("group_id", groupId); + ImGroupEntity imGroupEntity = imGroupDataMapper.selectOne(query); + + if (imGroupEntity == null) { + return ResponseVO.errorResponse(GroupErrorCode.GROUP_IS_NOT_EXIST); + } + return ResponseVO.successResponse(imGroupEntity); + } + + @Override + public ResponseVO getGroup(GetGroupReq req) { + + ResponseVO group = this.getGroup(req.getGroupId(), req.getAppId()); + + if(!group.isOk()){ + return group; + } + + GetGroupResp getGroupResp = new GetGroupResp(); + BeanUtils.copyProperties(group.getData(), getGroupResp); + try { + ResponseVO> groupMember = groupMemberService.getGroupMember(req.getGroupId(), req.getAppId()); + if (groupMember.isOk()) { + getGroupResp.setMemberList(groupMember.getData()); + } + } catch (Exception e) { + e.printStackTrace(); + } + return ResponseVO.successResponse(getGroupResp); + } + + @Override + public ResponseVO muteGroup(MuteGroupReq req) { + + ResponseVO groupResp = getGroup(req.getGroupId(), req.getAppId()); + if (!groupResp.isOk()) { + return groupResp; + } + + if(groupResp.getData().getStatus() == GroupStatusEnum.DESTROY.getCode()){ + throw new ApplicationException(GroupErrorCode.GROUP_IS_DESTROY); + } + + boolean isadmin = false; + + if (!isadmin) { + //不是后台调用需要检查权限 + ResponseVO role = groupMemberService.getRoleInGroupOne(req.getGroupId(), req.getOperater(), req.getAppId()); + + if (!role.isOk()) { + return role; + } + + GetRoleInGroupResp data = role.getData(); + Integer roleInfo = data.getRole(); + + boolean isManager = roleInfo == GroupMemberRoleEnum.MAMAGER.getCode() || roleInfo == GroupMemberRoleEnum.OWNER.getCode(); + + //公开群只能群主修改资料 + if (!isManager) { + throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_MANAGER_ROLE); + } + } + + ImGroupEntity update = new ImGroupEntity(); + update.setMute(req.getMute()); + + UpdateWrapper wrapper = new UpdateWrapper<>(); + wrapper.eq("group_id",req.getGroupId()); + wrapper.eq("app_id",req.getAppId()); + imGroupDataMapper.update(update,wrapper); + + return ResponseVO.successResponse(); + } + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/controller/ImUserController.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/controller/ImUserController.java new file mode 100644 index 0000000..b91428f --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/controller/ImUserController.java @@ -0,0 +1,35 @@ +package com.lld.im.service.user.controller; + +import com.lld.im.common.ResponseVO; +import com.lld.im.service.user.model.req.*; +import com.lld.im.service.user.service.ImUserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@RestController +@RequestMapping("v1/user") +public class ImUserController { + @Autowired + ImUserService imUserService; + + @RequestMapping("importUser") + public ResponseVO importUser(@RequestBody ImportUserReq req, Integer appId) { + return imUserService.importUser(req); + } + + @RequestMapping("/deleteUser") + public ResponseVO deleteUser(@RequestBody @Validated DeleteUserReq req, Integer appId) { + req.setAppId(appId); + return imUserService.deleteUser(req); + } + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/controller/ImUserDataController.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/controller/ImUserDataController.java new file mode 100644 index 0000000..1999b0f --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/controller/ImUserDataController.java @@ -0,0 +1,47 @@ +package com.lld.im.service.user.controller; + +import com.lld.im.common.ResponseVO; +import com.lld.im.service.user.model.req.GetUserInfoReq; +import com.lld.im.service.user.model.req.ModifyUserInfoReq; +import com.lld.im.service.user.model.req.UserId; +import com.lld.im.service.user.service.ImUserService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@RestController +@RequestMapping("v1/user/data") +public class ImUserDataController { + + private static Logger logger = LoggerFactory.getLogger(ImUserDataController.class); + + @Autowired + ImUserService imUserService; + + @RequestMapping("/getUserInfo") + public ResponseVO getUserInfo(@RequestBody GetUserInfoReq req, Integer appId){//@Validated + req.setAppId(appId); + return imUserService.getUserInfo(req); + } + + @RequestMapping("/getSingleUserInfo") + public ResponseVO getSingleUserInfo(@RequestBody @Validated UserId req, Integer appId){ + req.setAppId(appId); + return imUserService.getSingleUserInfo(req.getUserId(),req.getAppId()); + } + + @RequestMapping("/modifyUserInfo") + public ResponseVO modifyUserInfo(@RequestBody @Validated ModifyUserInfoReq req, Integer appId){ + req.setAppId(appId); + return imUserService.modifyUserInfo(req); + } +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/dao/ImUserDataEntity.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/dao/ImUserDataEntity.java new file mode 100644 index 0000000..e9afb2b --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/dao/ImUserDataEntity.java @@ -0,0 +1,60 @@ +package com.lld.im.service.user.dao; + +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @author: Chackylee + * @description: 数据库用户数据实体类 + **/ + +@Data +@TableName("im_user_data") +public class ImUserDataEntity { + + // 用户id + private String userId; + + // 用户名称 + private String nickName; + + //位置 + private String location; + + //生日 + private String birthDay; + + private String password; + + // 头像 + private String photo; + + // 性别 + private Integer userSex; + + // 个性签名 + private String selfSignature; + + // 加好友验证类型(Friend_AllowType) 1需要验证 + private Integer friendAllowType; + + // 管理员禁止用户添加加好友:0 未禁用 1 已禁用 + private Integer disableAddFriend; + + // 禁用标识(0 未禁用 1 已禁用) + private Integer forbiddenFlag; + + // 禁言标识 + private Integer silentFlag; + /** + * 用户类型 1普通用户 2客服 3机器人 + */ + private Integer userType; + + private Integer appId; + + private Integer delFlag; + + private String extra; + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/dao/mapper/ImUserDataMapper.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/dao/mapper/ImUserDataMapper.java new file mode 100644 index 0000000..b21552b --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/dao/mapper/ImUserDataMapper.java @@ -0,0 +1,9 @@ +package com.lld.im.service.user.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lld.im.service.user.dao.ImUserDataEntity; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface ImUserDataMapper extends BaseMapper { +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/model/UserStatusChangeNotifyContent.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/model/UserStatusChangeNotifyContent.java new file mode 100644 index 0000000..40e23b4 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/model/UserStatusChangeNotifyContent.java @@ -0,0 +1,22 @@ +package com.lld.im.service.user.model; + +import com.lld.im.common.model.ClientInfo; +import lombok.Data; + +/** + * @description: status区分是上线还是下线 + * @author: lld + * @version: 1.0 + */ +@Data +public class UserStatusChangeNotifyContent extends ClientInfo { + + + private String userId; + + //服务端状态 1上线 2离线 + private Integer status; + + + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/model/req/DeleteUserReq.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/model/req/DeleteUserReq.java new file mode 100644 index 0000000..82f3169 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/model/req/DeleteUserReq.java @@ -0,0 +1,15 @@ +package com.lld.im.service.user.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import java.util.List; + + +@Data +public class DeleteUserReq extends RequestBase { + + @NotEmpty(message = "用户id不能为空") + private List userId; +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/model/req/GetUserInfoReq.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/model/req/GetUserInfoReq.java new file mode 100644 index 0000000..0c1c9c4 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/model/req/GetUserInfoReq.java @@ -0,0 +1,15 @@ +package com.lld.im.service.user.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import java.util.List; + + +@Data +public class GetUserInfoReq extends RequestBase { + + private List userIds; + + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/model/req/GetUserSequenceReq.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/model/req/GetUserSequenceReq.java new file mode 100644 index 0000000..2984d9c --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/model/req/GetUserSequenceReq.java @@ -0,0 +1,16 @@ +package com.lld.im.service.user.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Data +public class GetUserSequenceReq extends RequestBase { + + private String userId; + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/model/req/ImportUserReq.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/model/req/ImportUserReq.java new file mode 100644 index 0000000..3ae365c --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/model/req/ImportUserReq.java @@ -0,0 +1,16 @@ +package com.lld.im.service.user.model.req; + +import com.lld.im.common.model.RequestBase; +import com.lld.im.service.user.dao.ImUserDataEntity; +import lombok.Data; + +import java.util.List; + + +@Data +public class ImportUserReq extends RequestBase { + + private List userData; + + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/model/req/ModifyUserInfoReq.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/model/req/ModifyUserInfoReq.java new file mode 100644 index 0000000..3132523 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/model/req/ModifyUserInfoReq.java @@ -0,0 +1,46 @@ +package com.lld.im.service.user.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Data +public class ModifyUserInfoReq extends RequestBase { + + // 用户id + @NotEmpty(message = "用户id不能为空") + private String userId; + + // 用户名称 + private String nickName; + + //位置 + private String location; + + //生日 + private String birthDay; + + private String password; + + // 头像 + private String photo; + + // 性别 + private String userSex; + + // 个性签名 + private String selfSignature; + + // 加好友验证类型(Friend_AllowType) 1需要验证 + private Integer friendAllowType; + + private String extra; + + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/model/req/UserId.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/model/req/UserId.java new file mode 100644 index 0000000..3856261 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/model/req/UserId.java @@ -0,0 +1,15 @@ +package com.lld.im.service.user.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +/** + * @author: Chackylee + * @description: + **/ +@Data +public class UserId extends RequestBase { + + private String userId; + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/model/resp/GetUserInfoResp.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/model/resp/GetUserInfoResp.java new file mode 100644 index 0000000..742618c --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/model/resp/GetUserInfoResp.java @@ -0,0 +1,20 @@ +package com.lld.im.service.user.model.resp; + +import com.lld.im.service.user.dao.ImUserDataEntity; +import lombok.Data; + +import java.util.List; + +/** + * @author: Chackylee + * @description: + **/ +@Data +public class GetUserInfoResp { + + private List userDataItem; + + private List failUser; + + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/model/resp/ImportUserResp.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/model/resp/ImportUserResp.java new file mode 100644 index 0000000..2440a67 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/model/resp/ImportUserResp.java @@ -0,0 +1,18 @@ +package com.lld.im.service.user.model.resp; + +import lombok.Data; + +import java.util.List; + +/** + * @author: Chackylee + * @description: + **/ +@Data +public class ImportUserResp { + + private List successId; + + private List errorId; + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/model/resp/UserOnlineStatusResp.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/model/resp/UserOnlineStatusResp.java new file mode 100644 index 0000000..60f48a0 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/model/resp/UserOnlineStatusResp.java @@ -0,0 +1,22 @@ +package com.lld.im.service.user.model.resp; + +import com.lld.im.common.model.UserSession; +import lombok.Data; + +import java.util.List; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Data +public class UserOnlineStatusResp { + + private List session; + + private String customText; + + private Integer customStatus; + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/service/ImUserService.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/service/ImUserService.java new file mode 100644 index 0000000..81b61f9 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/service/ImUserService.java @@ -0,0 +1,26 @@ +package com.lld.im.service.user.service; + +import com.lld.im.common.ResponseVO; +import com.lld.im.service.user.dao.ImUserDataEntity; +import com.lld.im.service.user.model.req.*; +import com.lld.im.service.user.model.resp.GetUserInfoResp; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +public interface ImUserService { + + public ResponseVO importUser(ImportUserReq req); + + public ResponseVO getUserInfo(GetUserInfoReq req); + + public ResponseVO getSingleUserInfo(String userId , Integer appId); + + public ResponseVO deleteUser(DeleteUserReq req); + + public ResponseVO modifyUserInfo(ModifyUserInfoReq req); + + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/service/impl/ImUserviceImpl.java b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/service/impl/ImUserviceImpl.java new file mode 100644 index 0000000..ef590bd --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/java/com/lld/im/service/user/service/impl/ImUserviceImpl.java @@ -0,0 +1,173 @@ +package com.lld.im.service.user.service.impl; + +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.lld.im.common.ResponseVO; +import com.lld.im.common.enums.DelFlagEnum; +import com.lld.im.common.enums.UserErrorCode; +import com.lld.im.common.exception.ApplicationException; +import com.lld.im.service.group.service.ImGroupService; +import com.lld.im.service.user.dao.ImUserDataEntity; +import com.lld.im.service.user.dao.mapper.ImUserDataMapper; +import com.lld.im.service.user.model.req.*; +import com.lld.im.service.user.model.resp.GetUserInfoResp; +import com.lld.im.service.user.model.resp.ImportUserResp; +import com.lld.im.service.user.service.ImUserService; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Service +public class ImUserviceImpl implements ImUserService { + + @Autowired + ImUserDataMapper imUserDataMapper; + + + @Autowired + ImGroupService imGroupService; + + @Override + public ResponseVO importUser(ImportUserReq req) { + + if(req.getUserData().size() > 100){ + return ResponseVO.errorResponse(UserErrorCode.IMPORT_SIZE_BEYOND); + } + + ImportUserResp resp = new ImportUserResp(); + List successId = new ArrayList<>(); + List errorId = new ArrayList<>(); + + for (ImUserDataEntity data: + req.getUserData()) { + try { + data.setAppId(req.getAppId()); + int insert = imUserDataMapper.insert(data); + if(insert == 1){ + successId.add(data.getUserId()); + } + }catch (Exception e){ + e.printStackTrace(); + errorId.add(data.getUserId()); + } + } + + resp.setErrorId(errorId); + resp.setSuccessId(successId); + return ResponseVO.successResponse(resp); + } + + @Override + public ResponseVO getUserInfo(GetUserInfoReq req) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("app_id",req.getAppId()); + queryWrapper.in("user_id",req.getUserIds()); + queryWrapper.eq("del_flag", DelFlagEnum.NORMAL.getCode()); + + List userDataEntities = imUserDataMapper.selectList(queryWrapper); + HashMap map = new HashMap<>(); + + for (ImUserDataEntity data: + userDataEntities) { + map.put(data.getUserId(),data); + } + + List failUser = new ArrayList<>(); + for (String uid: + req.getUserIds()) { + if(!map.containsKey(uid)){ + failUser.add(uid); + } + } + + GetUserInfoResp resp = new GetUserInfoResp(); + resp.setUserDataItem(userDataEntities); + resp.setFailUser(failUser); + return ResponseVO.successResponse(resp); + } + + @Override + public ResponseVO getSingleUserInfo(String userId, Integer appId) { + QueryWrapper objectQueryWrapper = new QueryWrapper<>(); + objectQueryWrapper.eq("app_id",appId); + objectQueryWrapper.eq("user_id",userId); + objectQueryWrapper.eq("del_flag", DelFlagEnum.NORMAL.getCode()); + + ImUserDataEntity ImUserDataEntity = imUserDataMapper.selectOne(objectQueryWrapper); + if(ImUserDataEntity == null){ + return ResponseVO.errorResponse(UserErrorCode.USER_IS_NOT_EXIST); + } + + return ResponseVO.successResponse(ImUserDataEntity); + } + + @Override + public ResponseVO deleteUser(DeleteUserReq req) { + ImUserDataEntity entity = new ImUserDataEntity(); + entity.setDelFlag(DelFlagEnum.DELETE.getCode()); + + List errorId = new ArrayList(); + List successId = new ArrayList(); + + for (String userId: + req.getUserId()) { + QueryWrapper wrapper = new QueryWrapper(); + wrapper.eq("app_id",req.getAppId()); + wrapper.eq("user_id",userId); + wrapper.eq("del_flag",DelFlagEnum.NORMAL.getCode()); + int update = 0; + + try { + update = imUserDataMapper.update(entity, wrapper); + if(update > 0){ + successId.add(userId); + }else{ + errorId.add(userId); + } + }catch (Exception e){ + errorId.add(userId); + } + } + + ImportUserResp resp = new ImportUserResp(); + resp.setSuccessId(successId); + resp.setErrorId(errorId); + return ResponseVO.successResponse(resp); + } + + @Override + @Transactional + public ResponseVO modifyUserInfo(ModifyUserInfoReq req) { + QueryWrapper query = new QueryWrapper<>(); + query.eq("app_id",req.getAppId()); + query.eq("user_id",req.getUserId()); + query.eq("del_flag",DelFlagEnum.NORMAL.getCode()); + ImUserDataEntity user = imUserDataMapper.selectOne(query); + if(user == null){ + throw new ApplicationException(UserErrorCode.USER_IS_NOT_EXIST); + } + + ImUserDataEntity update = new ImUserDataEntity(); + BeanUtils.copyProperties(req,update); + + update.setAppId(null); + update.setUserId(null); + int update1 = imUserDataMapper.update(update, query); + if(update1 == 1){ + return ResponseVO.successResponse(); + } + throw new ApplicationException(UserErrorCode.MODIFY_USER_ERROR); + } + +} diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/resources/application.yml b/chapter-3-code-master/chapter-3-code/im-service/src/main/resources/application.yml new file mode 100644 index 0000000..e52fae9 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/resources/application.yml @@ -0,0 +1,39 @@ +spring: + profiles: + active: dev + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + password: frfr46467979+ + url: jdbc:mysql://127.0.0.1:3306/im-core?serverTimezone=UTC&useSSL=false&characterEncoding=UTF8 + username: root + + application: + name: im-core + +# logger 配置 +logging: + config: classpath:logback-spring.xml + +server: + port: 8000 + + +mybatis-plus: + configuration: + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + mapper-locations: classpath*:mapper/*.xml + global-config: + db-config: + update-strategy: NOT_EMPTY + +#mybatis: +# configuration: +# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + +httpclient: + maxTotal: 100 + defaultMaxPerRoute: 50 + connectTimeout: 2000 + connectionRequestTimeout: 2000 + socketTimeout: 5000 + staleConnectionCheckEnabled: true diff --git a/chapter-3-code-master/chapter-3-code/im-service/src/main/resources/logback-spring.xml b/chapter-3-code-master/chapter-3-code/im-service/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..b9cd630 --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/im-service/src/main/resources/logback-spring.xml @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + DEBUG + + + ${CONSOLE_LOG_PATTERN} + utf8 + + + + + + + + + + + + + true + + + ${logFile}.%d{yyyy-MM-dd}.log + + + + + %d{yyyy-MM-dd HH:mm:ss} -%msg%n + + + + + + + + + + + + true + + + ${logFile}.%d{yyyy-MM-dd}.log + + + + + %d{yyyy-MM-dd HH:mm:ss} -%msg%n + + + + + + + + + + \ No newline at end of file diff --git a/chapter-3-code-master/chapter-3-code/pom.xml b/chapter-3-code-master/chapter-3-code/pom.xml new file mode 100644 index 0000000..136f53c --- /dev/null +++ b/chapter-3-code-master/chapter-3-code/pom.xml @@ -0,0 +1,216 @@ + + 4.0.0 + + com.lld + im-system + pom + 1.0.0-SNAPSHOT + lld-im + l-im project + + + org.springframework.boot + spring-boot-starter-parent + 2.3.2.RELEASE + + + + + im-service + im-common + + + + 1.8 + 3.4.2 + 5.0.6 + 3.15.6 + 1.27 + 1.0.10 + 0.1 + 4.5.9 + 5.6.0 + 3.12.0 + 1.2.51 + 2.3.2.RELEASE + 4.1.35.Final + 8.18.0 + + + + + + ch.qos.logback + logback-classic + + + ch.qos.logback + logback-core + + + ch.qos.logback + logback-access + + + + + com.alibaba + fastjson + + + + + org.projectlombok + lombok + + + + + + + + + + com.dyuproject.protostuff + protostuff-api + ${protostuff-api} + + + com.dyuproject.protostuff + protostuff-core + ${protostuff-api} + + + com.dyuproject.protostuff + protostuff-runtime + ${protostuff-api} + + + + + + org.apache.commons + commons-lang3 + ${apache.commons.version} + + + + + com.alibaba + fastjson + ${fastjson.version} + + + + + org.springframework.boot + spring-boot-starter-data-redis + ${springboot.version} + + + + + org.springframework.boot + spring-boot-starter-amqp + ${springboot.version} + + + com.rabbitmq + amqp-client + ${rabbit.client.version} + + + + + com.baomidou + mybatis-plus-boot-starter + ${mybatis-plus.version} + + + + + + + + + + + org.hibernate + hibernate-validator + ${hibernate-validator.version} + + + + + org.redisson + redisson + ${redisson.version} + + + + + org.yaml + snakeyaml + ${snakeyaml.version} + + + + + cn.hutool + hutool-all + ${hutool.version} + + + + org.apache.httpcomponents + httpclient + ${apache.httpclient.version} + + + + + com.github.sgroschupf + zkclient + ${zkClient.version} + + + + + io.netty + netty-all + ${netty.version} + + + + + com.netflix.feign + feign-core + ${feign.version} + + + com.netflix.feign + feign-jackson + ${feign.version} + + + + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 8 + 8 + + + + + + \ No newline at end of file diff --git a/im-server/.gitignore b/im-server/.gitignore new file mode 100644 index 0000000..5fa1743 --- /dev/null +++ b/im-server/.gitignore @@ -0,0 +1,4 @@ +/.idea +/logs +/im-service/target +/im-common/target diff --git a/im-server/README.md b/im-server/README.md new file mode 100644 index 0000000..e69de29 diff --git a/im-server/im-common/common.iml b/im-server/im-common/common.iml new file mode 100644 index 0000000..0ee4389 --- /dev/null +++ b/im-server/im-common/common.iml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/im-server/im-common/pom.xml b/im-server/im-common/pom.xml new file mode 100644 index 0000000..f13bea3 --- /dev/null +++ b/im-server/im-common/pom.xml @@ -0,0 +1,52 @@ + + + + im-system + com.lld + 1.0.0-SNAPSHOT + + 4.0.0 + + common + + + 1.8 + + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-logging + + + + + + org.apache.httpcomponents + httpclient + + + + + org.apache.commons + commons-lang3 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + \ No newline at end of file diff --git a/im-server/im-common/src/main/java/com/lld/im/common/BaseErrorCode.java b/im-server/im-common/src/main/java/com/lld/im/common/BaseErrorCode.java new file mode 100644 index 0000000..d0b3e1e --- /dev/null +++ b/im-server/im-common/src/main/java/com/lld/im/common/BaseErrorCode.java @@ -0,0 +1,31 @@ +package com.lld.im.common; + + +import com.lld.im.common.exception.ApplicationExceptionEnum; + + +public enum BaseErrorCode implements ApplicationExceptionEnum { + + SUCCESS(200,"success"), + SYSTEM_ERROR(90000,"服务器内部错误,请联系管理员"), + PARAMETER_ERROR(90001,"参数校验错误"), + + + ; + + private int code; + private String error; + + BaseErrorCode(int code, String error){ + this.code = code; + this.error = error; + } + public int getCode() { + return this.code; + } + + public String getError() { + return this.error; + } + +} diff --git a/im-server/im-common/src/main/java/com/lld/im/common/ClientType.java b/im-server/im-common/src/main/java/com/lld/im/common/ClientType.java new file mode 100644 index 0000000..244194b --- /dev/null +++ b/im-server/im-common/src/main/java/com/lld/im/common/ClientType.java @@ -0,0 +1,34 @@ +package com.lld.im.common; + +/** + * @author: Chackylee + * @description: + **/ +public enum ClientType { + + WEBAPI(0,"webApi"), + WEB(1,"web"), + IOS(2,"ios"), + ANDROID(3,"android"), + WINDOWS(4,"windows"), + MAC(5,"mac"), + ; + + private int code; + private String error; + + ClientType(int code, String error){ + this.code = code; + this.error = error; + } + public int getCode() { + return this.code; + } + + public String getError() { + return this.error; + } + + + +} diff --git a/im-server/im-common/src/main/java/com/lld/im/common/ResponseVO.java b/im-server/im-common/src/main/java/com/lld/im/common/ResponseVO.java new file mode 100644 index 0000000..7917aba --- /dev/null +++ b/im-server/im-common/src/main/java/com/lld/im/common/ResponseVO.java @@ -0,0 +1,66 @@ +package com.lld.im.common; + +import com.lld.im.common.exception.ApplicationExceptionEnum; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ResponseVO { + + private int code; + + private String msg; + + private T data; + + public static ResponseVO successResponse(Object data) { + return new ResponseVO(200, "success", data); + } + + public static ResponseVO successResponse() { + return new ResponseVO(200, "success"); + } + + public static ResponseVO errorResponse() { + return new ResponseVO(500, "系统内部异常"); + } + + public static ResponseVO errorResponse(int code, String msg) { + return new ResponseVO(code, msg); + } + + public static ResponseVO errorResponse(ApplicationExceptionEnum enums) { + return new ResponseVO(enums.getCode(), enums.getError()); + } + + public boolean isOk(){ + return this.code == 200; + } + + + public ResponseVO(int code, String msg) { + this.code = code; + this.msg = msg; +// this.data = null; + } + + public ResponseVO success(){ + this.code = 200; + this.msg = "success"; + return this; + } + + public ResponseVO success(T data){ + this.code = 200; + this.msg = "success"; + this.data = data; + return this; + } + +} diff --git a/im-server/im-common/src/main/java/com/lld/im/common/enums/AllowFriendTypeEnum.java b/im-server/im-common/src/main/java/com/lld/im/common/enums/AllowFriendTypeEnum.java new file mode 100644 index 0000000..17093c0 --- /dev/null +++ b/im-server/im-common/src/main/java/com/lld/im/common/enums/AllowFriendTypeEnum.java @@ -0,0 +1,27 @@ +package com.lld.im.common.enums; + +public enum AllowFriendTypeEnum { + + /** + * 验证 + */ + NEED(2), + + /** + * 不需要验证 + */ + NOT_NEED(1), + + ; + + + private int code; + + AllowFriendTypeEnum(int code){ + this.code=code; + } + + public int getCode() { + return code; + } +} diff --git a/im-server/im-common/src/main/java/com/lld/im/common/enums/ApproverFriendRequestStatusEnum.java b/im-server/im-common/src/main/java/com/lld/im/common/enums/ApproverFriendRequestStatusEnum.java new file mode 100644 index 0000000..d4998d8 --- /dev/null +++ b/im-server/im-common/src/main/java/com/lld/im/common/enums/ApproverFriendRequestStatusEnum.java @@ -0,0 +1,22 @@ +package com.lld.im.common.enums; + +public enum ApproverFriendRequestStatusEnum { + + /** + * 1 同意;2 拒绝。 + */ + AGREE(1), + + REJECT(2), + ; + + private int code; + + ApproverFriendRequestStatusEnum(int code){ + this.code=code; + } + + public int getCode() { + return code; + } +} diff --git a/im-server/im-common/src/main/java/com/lld/im/common/enums/CheckFriendShipTypeEnum.java b/im-server/im-common/src/main/java/com/lld/im/common/enums/CheckFriendShipTypeEnum.java new file mode 100644 index 0000000..8c69d6c --- /dev/null +++ b/im-server/im-common/src/main/java/com/lld/im/common/enums/CheckFriendShipTypeEnum.java @@ -0,0 +1,22 @@ +package com.lld.im.common.enums; + +public enum CheckFriendShipTypeEnum { + + /** + * 1 单方校验;2双方校验。 + */ + SINGLE(1), + + BOTH(2), + ; + + private int type; + + CheckFriendShipTypeEnum(int type){ + this.type=type; + } + + public int getType() { + return type; + } +} diff --git a/im-server/im-common/src/main/java/com/lld/im/common/enums/DelFlagEnum.java b/im-server/im-common/src/main/java/com/lld/im/common/enums/DelFlagEnum.java new file mode 100644 index 0000000..2ba3b9e --- /dev/null +++ b/im-server/im-common/src/main/java/com/lld/im/common/enums/DelFlagEnum.java @@ -0,0 +1,22 @@ +package com.lld.im.common.enums; + +public enum DelFlagEnum { + + /** + * 0 正常;1 删除。 + */ + NORMAL(0), + + DELETE(1), + ; + + private int code; + + DelFlagEnum(int code){ + this.code=code; + } + + public int getCode() { + return code; + } +} diff --git a/im-server/im-common/src/main/java/com/lld/im/common/enums/FriendShipErrorCode.java b/im-server/im-common/src/main/java/com/lld/im/common/enums/FriendShipErrorCode.java new file mode 100644 index 0000000..3c0e25c --- /dev/null +++ b/im-server/im-common/src/main/java/com/lld/im/common/enums/FriendShipErrorCode.java @@ -0,0 +1,57 @@ +package com.lld.im.common.enums; + +import com.lld.im.common.exception.ApplicationExceptionEnum; + +public enum FriendShipErrorCode implements ApplicationExceptionEnum { + + + IMPORT_SIZE_BEYOND(30000,"导入數量超出上限"), + + ADD_FRIEND_ERROR(30001,"添加好友失败"), + + TO_IS_YOUR_FRIEND(30002,"对方已经是你的好友"), + + TO_IS_NOT_YOUR_FRIEND(30003,"对方不是你的好友"), + + FRIEND_IS_DELETED(30004,"好友已被删除"), + + FRIEND_IS_BLACK(30006,"好友已被拉黑"), + + TARGET_IS_BLACK_YOU(30007,"对方把你拉黑"), + + REPEATSHIP_IS_NOT_EXIST(30008,"关系链记录不存在"), + + ADD_BLACK_ERROR(30009,"添加黑名單失败"), + + FRIEND_IS_NOT_YOUR_BLACK(30010,"好友已經不在你的黑名單内"), + + NOT_APPROVER_OTHER_MAN_REQUEST(30011,"无法审批其他人的好友请求"), + + FRIEND_REQUEST_IS_NOT_EXIST(30012,"好友申请不存在"), + + FRIEND_SHIP_GROUP_CREATE_ERROR(30014,"好友分组创建失败"), + + FRIEND_SHIP_GROUP_IS_EXIST(30015,"好友分组已存在"), + + FRIEND_SHIP_GROUP_IS_NOT_EXIST(30016,"好友分组不存在"), + + + + ; + + private int code; + private String error; + + FriendShipErrorCode(int code, String error){ + this.code = code; + this.error = error; + } + public int getCode() { + return this.code; + } + + public String getError() { + return this.error; + } + +} diff --git a/im-server/im-common/src/main/java/com/lld/im/common/enums/FriendShipStatusEnum.java b/im-server/im-common/src/main/java/com/lld/im/common/enums/FriendShipStatusEnum.java new file mode 100644 index 0000000..88f77d9 --- /dev/null +++ b/im-server/im-common/src/main/java/com/lld/im/common/enums/FriendShipStatusEnum.java @@ -0,0 +1,31 @@ +package com.lld.im.common.enums; + +public enum FriendShipStatusEnum { + + /** + * 0未添加 1正常 2删除 + */ + FRIEND_STATUS_NO_FRIEND(0), + + FRIEND_STATUS_NORMAL(1), + + FRIEND_STATUS_DELETE(2), + + /** + * 0未添加 1正常 2删除 + */ + BLACK_STATUS_NORMAL(1), + + BLACK_STATUS_BLACKED(2), + ; + + private int code; + + FriendShipStatusEnum(int code){ + this.code=code; + } + + public int getCode() { + return code; + } +} diff --git a/im-server/im-common/src/main/java/com/lld/im/common/enums/GroupErrorCode.java b/im-server/im-common/src/main/java/com/lld/im/common/enums/GroupErrorCode.java new file mode 100644 index 0000000..aa2a2fe --- /dev/null +++ b/im-server/im-common/src/main/java/com/lld/im/common/enums/GroupErrorCode.java @@ -0,0 +1,66 @@ +package com.lld.im.common.enums; + +import com.lld.im.common.exception.ApplicationExceptionEnum; + +/** + * @author: Chackylee + * @description: + **/ +public enum GroupErrorCode implements ApplicationExceptionEnum { + + GROUP_IS_NOT_EXIST(40000,"群不存在"), + + GROUP_IS_EXIST(40001,"群已存在"), + + GROUP_IS_HAVE_OWNER(40002,"群已存在群主"), + + USER_IS_JOINED_GROUP(40003,"该用户已经进入该群"), + + USER_JOIN_GROUP_ERROR(40004,"群成员添加失败"), + + GROUP_MEMBER_IS_BEYOND(40005,"群成员已达到上限"), + + MEMBER_IS_NOT_JOINED_GROUP(40006,"该用户不在群内"), + + THIS_OPERATE_NEED_MANAGER_ROLE(40007,"该操作只允许群主/管理员操作"), + + THIS_OPERATE_NEED_APPMANAGER_ROLE(40008,"该操作只允许APP管理员操作"), + + THIS_OPERATE_NEED_OWNER_ROLE(40009,"该操作只允许群主操作"), + + GROUP_OWNER_IS_NOT_REMOVE(40010,"群主无法移除"), + + UPDATE_GROUP_BASE_INFO_ERROR(40011,"更新群信息失败"), + + THIS_GROUP_IS_MUTE(40012,"该群禁止发言"), + + IMPORT_GROUP_ERROR(40013,"导入群组失败"), + + THIS_OPERATE_NEED_ONESELF(40014,"该操作只允许自己操作"), + + PRIVATE_GROUP_CAN_NOT_DESTORY(40015,"私有群不允许解散"), + + PUBLIC_GROUP_MUST_HAVE_OWNER(40016,"公开群必须指定群主"), + + GROUP_MEMBER_IS_SPEAK(40017,"群成员被禁言"), + + GROUP_IS_DESTROY(40018,"群组已解散"), + + ; + + private int code; + private String error; + + GroupErrorCode(int code, String error){ + this.code = code; + this.error = error; + } + public int getCode() { + return this.code; + } + + public String getError() { + return this.error; + } + +} diff --git a/im-server/im-common/src/main/java/com/lld/im/common/enums/GroupMemberRoleEnum.java b/im-server/im-common/src/main/java/com/lld/im/common/enums/GroupMemberRoleEnum.java new file mode 100644 index 0000000..3326b34 --- /dev/null +++ b/im-server/im-common/src/main/java/com/lld/im/common/enums/GroupMemberRoleEnum.java @@ -0,0 +1,50 @@ +package com.lld.im.common.enums; + +public enum GroupMemberRoleEnum { + + /** + * 普通成员 + */ + ORDINARY(0), + + /** + * 管理员 + */ + MAMAGER(1), + + /** + * 群主 + */ + OWNER(2), + + /** + * 离开 + */ + LEAVE(3); + ; + + + private int code; + + /** + * 不能用 默认的 enumType b= enumType.values()[i]; 因为本枚举是类形式封装 + * @param ordinal + * @return + */ + public static GroupMemberRoleEnum getItem(int ordinal) { + for (int i = 0; i < GroupMemberRoleEnum.values().length; i++) { + if (GroupMemberRoleEnum.values()[i].getCode() == ordinal) { + return GroupMemberRoleEnum.values()[i]; + } + } + return null; + } + + GroupMemberRoleEnum(int code){ + this.code=code; + } + + public int getCode() { + return code; + } +} diff --git a/im-server/im-common/src/main/java/com/lld/im/common/enums/GroupMuteTypeEnum.java b/im-server/im-common/src/main/java/com/lld/im/common/enums/GroupMuteTypeEnum.java new file mode 100644 index 0000000..d518113 --- /dev/null +++ b/im-server/im-common/src/main/java/com/lld/im/common/enums/GroupMuteTypeEnum.java @@ -0,0 +1,43 @@ +package com.lld.im.common.enums; + +public enum GroupMuteTypeEnum { + + /** + * 是否全员禁言,0 不禁言;1 全员禁言。 + */ + NOT_MUTE(0), + + + MUTE(1), + + ; + + /** + * 不能用 默认的 enumType b= enumType.values()[i]; 因为本枚举是类形式封装 + * @param ordinal + * @return + */ + public static GroupMuteTypeEnum getEnum(Integer ordinal) { + + if(ordinal == null){ + return null; + } + + for (int i = 0; i < GroupMuteTypeEnum.values().length; i++) { + if (GroupMuteTypeEnum.values()[i].getCode() == ordinal) { + return GroupMuteTypeEnum.values()[i]; + } + } + return null; + } + + private int code; + + GroupMuteTypeEnum(int code){ + this.code=code; + } + + public int getCode() { + return code; + } +} diff --git a/im-server/im-common/src/main/java/com/lld/im/common/enums/GroupStatusEnum.java b/im-server/im-common/src/main/java/com/lld/im/common/enums/GroupStatusEnum.java new file mode 100644 index 0000000..338868e --- /dev/null +++ b/im-server/im-common/src/main/java/com/lld/im/common/enums/GroupStatusEnum.java @@ -0,0 +1,42 @@ +package com.lld.im.common.enums; + +public enum GroupStatusEnum { + + /** + * 1正常 2解散 其他待定比如封禁... + */ + NORMAL(1), + + DESTROY(2), + + ; + + /** + * 不能用 默认的 enumType b= enumType.values()[i]; 因为本枚举是类形式封装 + * @param ordinal + * @return + */ + public static GroupStatusEnum getEnum(Integer ordinal) { + + if(ordinal == null){ + return null; + } + + for (int i = 0; i < GroupStatusEnum.values().length; i++) { + if (GroupStatusEnum.values()[i].getCode() == ordinal) { + return GroupStatusEnum.values()[i]; + } + } + return null; + } + + private int code; + + GroupStatusEnum(int code){ + this.code=code; + } + + public int getCode() { + return code; + } +} diff --git a/im-server/im-common/src/main/java/com/lld/im/common/enums/GroupTypeEnum.java b/im-server/im-common/src/main/java/com/lld/im/common/enums/GroupTypeEnum.java new file mode 100644 index 0000000..be7a908 --- /dev/null +++ b/im-server/im-common/src/main/java/com/lld/im/common/enums/GroupTypeEnum.java @@ -0,0 +1,42 @@ +package com.lld.im.common.enums; + +public enum GroupTypeEnum { + + /** + * 群类型 1私有群(类似微信) 2公开群(类似qq) + */ + PRIVATE(1), + + PUBLIC(2), + + ; + + /** + * 不能用 默认的 enumType b= enumType.values()[i]; 因为本枚举是类形式封装 + * @param ordinal + * @return + */ + public static GroupTypeEnum getEnum(Integer ordinal) { + + if(ordinal == null){ + return null; + } + + for (int i = 0; i < GroupTypeEnum.values().length; i++) { + if (GroupTypeEnum.values()[i].getCode() == ordinal) { + return GroupTypeEnum.values()[i]; + } + } + return null; + } + + private int code; + + GroupTypeEnum(int code){ + this.code=code; + } + + public int getCode() { + return code; + } +} diff --git a/im-server/im-common/src/main/java/com/lld/im/common/enums/UserErrorCode.java b/im-server/im-common/src/main/java/com/lld/im/common/enums/UserErrorCode.java new file mode 100644 index 0000000..76c2cd0 --- /dev/null +++ b/im-server/im-common/src/main/java/com/lld/im/common/enums/UserErrorCode.java @@ -0,0 +1,30 @@ +package com.lld.im.common.enums; + +import com.lld.im.common.exception.ApplicationExceptionEnum; + +public enum UserErrorCode implements ApplicationExceptionEnum { + + + IMPORT_SIZE_BEYOND(20000,"导入數量超出上限"), + USER_IS_NOT_EXIST(20001,"用户不存在"), + SERVER_GET_USER_ERROR(20002,"服务获取用户失败"), + MODIFY_USER_ERROR(20003,"更新用户失败"), + SERVER_NOT_AVAILABLE(71000, "没有可用的服务"), + ; + + private int code; + private String error; + + UserErrorCode(int code, String error){ + this.code = code; + this.error = error; + } + public int getCode() { + return this.code; + } + + public String getError() { + return this.error; + } + +} diff --git a/im-server/im-common/src/main/java/com/lld/im/common/enums/UserForbiddenFlagEnum.java b/im-server/im-common/src/main/java/com/lld/im/common/enums/UserForbiddenFlagEnum.java new file mode 100644 index 0000000..bc0fffc --- /dev/null +++ b/im-server/im-common/src/main/java/com/lld/im/common/enums/UserForbiddenFlagEnum.java @@ -0,0 +1,22 @@ +package com.lld.im.common.enums; + +public enum UserForbiddenFlagEnum { + + /** + * 0 正常;1 禁用。 + */ + NORMAL(0), + + FORBIBBEN(1), + ; + + private int code; + + UserForbiddenFlagEnum(int code){ + this.code=code; + } + + public int getCode() { + return code; + } +} diff --git a/im-server/im-common/src/main/java/com/lld/im/common/enums/UserSilentFlagEnum.java b/im-server/im-common/src/main/java/com/lld/im/common/enums/UserSilentFlagEnum.java new file mode 100644 index 0000000..3e5ccb3 --- /dev/null +++ b/im-server/im-common/src/main/java/com/lld/im/common/enums/UserSilentFlagEnum.java @@ -0,0 +1,22 @@ +package com.lld.im.common.enums; + +public enum UserSilentFlagEnum { + + /** + * 0 正常;1 禁言。 + */ + NORMAL(0), + + MUTE(1), + ; + + private int code; + + UserSilentFlagEnum(int code){ + this.code=code; + } + + public int getCode() { + return code; + } +} diff --git a/im-server/im-common/src/main/java/com/lld/im/common/exception/ApplicationException.java b/im-server/im-common/src/main/java/com/lld/im/common/exception/ApplicationException.java new file mode 100644 index 0000000..12bf555 --- /dev/null +++ b/im-server/im-common/src/main/java/com/lld/im/common/exception/ApplicationException.java @@ -0,0 +1,44 @@ +package com.lld.im.common.exception; + +/** + * @author: Chackylee + * @description: + **/ +public class ApplicationException extends RuntimeException { + + private int code; + + private String error; + + + public ApplicationException(int code, String message) { + super(message); + this.code = code; + this.error = message; + } + + public ApplicationException(ApplicationExceptionEnum exceptionEnum) { + super(exceptionEnum.getError()); + this.code = exceptionEnum.getCode(); + this.error = exceptionEnum.getError(); + } + + public int getCode() { + return code; + } + + public String getError() { + return error; + } + + + /** + * avoid the expensive and useless stack trace for api exceptions + * @see Throwable#fillInStackTrace() + */ + @Override + public Throwable fillInStackTrace() { + return this; + } + +} diff --git a/im-server/im-common/src/main/java/com/lld/im/common/exception/ApplicationExceptionEnum.java b/im-server/im-common/src/main/java/com/lld/im/common/exception/ApplicationExceptionEnum.java new file mode 100644 index 0000000..af1df84 --- /dev/null +++ b/im-server/im-common/src/main/java/com/lld/im/common/exception/ApplicationExceptionEnum.java @@ -0,0 +1,8 @@ +package com.lld.im.common.exception; + +public interface ApplicationExceptionEnum { + + int getCode(); + + String getError(); +} diff --git a/im-server/im-common/src/main/java/com/lld/im/common/model/ClientInfo.java b/im-server/im-common/src/main/java/com/lld/im/common/model/ClientInfo.java new file mode 100644 index 0000000..0116c79 --- /dev/null +++ b/im-server/im-common/src/main/java/com/lld/im/common/model/ClientInfo.java @@ -0,0 +1,25 @@ +package com.lld.im.common.model; + +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author: Chackylee + * @description: + **/ +@Data +@NoArgsConstructor +public class ClientInfo { + + private Integer appId; + + private Integer clientType; + + private String imei; + + public ClientInfo(Integer appId, Integer clientType, String imei) { + this.appId = appId; + this.clientType = clientType; + this.imei = imei; + } +} diff --git a/im-server/im-common/src/main/java/com/lld/im/common/model/RequestBase.java b/im-server/im-common/src/main/java/com/lld/im/common/model/RequestBase.java new file mode 100644 index 0000000..12ff3fc --- /dev/null +++ b/im-server/im-common/src/main/java/com/lld/im/common/model/RequestBase.java @@ -0,0 +1,19 @@ +package com.lld.im.common.model; + +import lombok.Data; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Data +public class RequestBase { + private Integer appId; + + private String operater; + + private Integer clientType; + + private String imei; +} diff --git a/im-server/im-common/src/main/java/com/lld/im/common/model/UserClientDto.java b/im-server/im-common/src/main/java/com/lld/im/common/model/UserClientDto.java new file mode 100644 index 0000000..1dcc36d --- /dev/null +++ b/im-server/im-common/src/main/java/com/lld/im/common/model/UserClientDto.java @@ -0,0 +1,21 @@ +package com.lld.im.common.model; + +import lombok.Data; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Data +public class UserClientDto { + + private Integer appId; + + private Integer clientType; + + private String userId; + + private String imei; + +} diff --git a/im-server/im-common/src/main/java/com/lld/im/common/model/UserSession.java b/im-server/im-common/src/main/java/com/lld/im/common/model/UserSession.java new file mode 100644 index 0000000..907c5aa --- /dev/null +++ b/im-server/im-common/src/main/java/com/lld/im/common/model/UserSession.java @@ -0,0 +1,37 @@ +package com.lld.im.common.model; + +import lombok.Data; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Data +public class UserSession { + + private String userId; + + /** + * 应用ID + */ + private Integer appId; + + /** + * 端的标识 + */ + private Integer clientType; + + //sdk 版本号 + private Integer version; + + //连接状态 1=在线 2=离线 + private Integer connectState; + + private Integer brokerId; + + private String brokerHost; + + private String imei; + +} diff --git a/im-server/im-service/im-service.iml b/im-server/im-service/im-service.iml new file mode 100644 index 0000000..e69de29 diff --git a/im-server/im-service/pom.xml b/im-server/im-service/pom.xml new file mode 100644 index 0000000..637de92 --- /dev/null +++ b/im-server/im-service/pom.xml @@ -0,0 +1,101 @@ + + + + im-system + com.lld + 1.0.0-SNAPSHOT + + 4.0.0 + + lld-im-service project + + 1.8 + + + service + + + + + + + + + + org.springframework.boot + spring-boot-starter-validation + + + + + + + + + + + + + + + + org.springframework.boot + spring-boot-starter-web + + + + + + + + + + + cn.hutool + hutool-all + + + + + org.springframework.boot + spring-boot-starter-jdbc + + + + + mysql + mysql-connector-java + runtime + + + + + com.baomidou + mybatis-plus-boot-starter + + + com.github.jeffreyning + mybatisplus-plus + 1.5.1-RELEASE + + + + + com.lld + common + 1.0.0-SNAPSHOT + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + \ No newline at end of file diff --git a/im-server/im-service/service.iml b/im-server/im-service/service.iml new file mode 100644 index 0000000..fa3e3ce --- /dev/null +++ b/im-server/im-service/service.iml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/im-server/im-service/src/main/java/com/lld/im/service/Application.java b/im-server/im-service/src/main/java/com/lld/im/service/Application.java new file mode 100644 index 0000000..272d021 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/Application.java @@ -0,0 +1,20 @@ +package com.lld.im.service; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +@MapperScan("com.lld.im.service.*.dao.mapper") +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + + +} + + + + diff --git a/im-server/im-service/src/main/java/com/lld/im/service/config/BeanConfig.java b/im-server/im-service/src/main/java/com/lld/im/service/config/BeanConfig.java new file mode 100644 index 0000000..c07d827 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/config/BeanConfig.java @@ -0,0 +1,13 @@ +package com.lld.im.service.config; + +import org.springframework.context.annotation.Configuration; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Configuration +public class BeanConfig { + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/config/WebConfig.java b/im-server/im-service/src/main/java/com/lld/im/service/config/WebConfig.java new file mode 100644 index 0000000..b6bd571 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/config/WebConfig.java @@ -0,0 +1,26 @@ +package com.lld.im.service.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Configuration +public class WebConfig implements WebMvcConfigurer { + + + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedOrigins("*") + .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS") + .allowCredentials(true) + .maxAge(3600) + .allowedHeaders("*"); + } + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/exception/GlobalExceptionHandler.java b/im-server/im-service/src/main/java/com/lld/im/service/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..e5a5657 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/exception/GlobalExceptionHandler.java @@ -0,0 +1,110 @@ +package com.lld.im.service.exception; + +import com.lld.im.common.BaseErrorCode; +import com.lld.im.common.ResponseVO; +import com.lld.im.common.exception.ApplicationException; +import org.hibernate.validator.internal.engine.path.PathImpl; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.validation.FieldError; +import org.springframework.validation.ObjectError; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import javax.validation.ConstraintViolation; +import javax.validation.ConstraintViolationException; +import java.util.Set; + +@RestControllerAdvice +public class GlobalExceptionHandler { + + + @ExceptionHandler(value=Exception.class) + @ResponseBody + public ResponseVO unknowException(Exception e){ + e.printStackTrace(); + ResponseVO resultBean =new ResponseVO(); + resultBean.setCode(BaseErrorCode.SYSTEM_ERROR.getCode()); + resultBean.setMsg(BaseErrorCode.SYSTEM_ERROR.getError()); + /** + * 未知异常的话,这里写逻辑,发邮件,发短信都可以、、 + */ + return resultBean; + } + + + /** + * Validator 参数校验异常处理 + * + * @param ex + * @return + */ + @ExceptionHandler(value = ConstraintViolationException.class) + @ResponseBody + public Object handleMethodArgumentNotValidException(ConstraintViolationException ex) { + + Set> constraintViolations = ex.getConstraintViolations(); + ResponseVO resultBean =new ResponseVO(); + resultBean.setCode(BaseErrorCode.PARAMETER_ERROR.getCode()); + for (ConstraintViolation constraintViolation : constraintViolations) { + PathImpl pathImpl = (PathImpl) constraintViolation.getPropertyPath(); + // 读取参数字段,constraintViolation.getMessage() 读取验证注解中的message值 + String paramName = pathImpl.getLeafNode().getName(); + String message = "参数{".concat(paramName).concat("}").concat(constraintViolation.getMessage()); + resultBean.setMsg(message); + + return resultBean; + } + resultBean.setMsg(BaseErrorCode.PARAMETER_ERROR.getError() + ex.getMessage()); + return resultBean; + } + + @ExceptionHandler(ApplicationException.class) + @ResponseBody + public Object applicationExceptionHandler(ApplicationException e) { + // 使用公共的结果类封装返回结果, 这里我指定状态码为 + ResponseVO resultBean =new ResponseVO(); + resultBean.setCode(e.getCode()); + resultBean.setMsg(e.getError()); + return resultBean; + } + + /** + * Validator 参数校验异常处理 + * + * @param ex + * @return + */ + @ExceptionHandler(value = BindException.class) + @ResponseBody + public Object handleException2(BindException ex) { + FieldError err = ex.getFieldError(); + String message = "参数{".concat(err.getField()).concat("}").concat(err.getDefaultMessage()); + ResponseVO resultBean =new ResponseVO(); + resultBean.setCode(BaseErrorCode.PARAMETER_ERROR.getCode()); + resultBean.setMsg(message); + return resultBean; + + + } + + //json格式 + @ExceptionHandler(value = MethodArgumentNotValidException.class) + @ResponseBody + public Object handleException1(MethodArgumentNotValidException ex) { + StringBuilder errorMsg = new StringBuilder(); + BindingResult re = ex.getBindingResult(); + for (ObjectError error : re.getAllErrors()) { + errorMsg.append(error.getDefaultMessage()).append(","); + } + errorMsg.delete(errorMsg.length() - 1, errorMsg.length()); + + ResponseVO resultBean =new ResponseVO(); + resultBean.setCode(BaseErrorCode.PARAMETER_ERROR.getCode()); + resultBean.setMsg(BaseErrorCode.PARAMETER_ERROR.getError() + " : " + errorMsg.toString()); + return resultBean; + } + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/controller/ImFriendShipController.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/controller/ImFriendShipController.java new file mode 100644 index 0000000..80524c4 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/controller/ImFriendShipController.java @@ -0,0 +1,86 @@ +package com.lld.im.service.friendship.controller; + +import com.lld.im.common.ResponseVO; +import com.lld.im.service.friendship.model.req.*; +import com.lld.im.service.friendship.service.ImFriendService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("v1/friendship") +public class ImFriendShipController { + + @Autowired + ImFriendService imFriendShipService; + + @RequestMapping("/importFriendShip") + public ResponseVO importFriendShip(@RequestBody @Validated ImporFriendShipReq req, Integer appId){ + req.setAppId(appId); + return imFriendShipService.importFriendShip(req); + } + + @RequestMapping("/addFriend") + public ResponseVO addFriend(@RequestBody @Validated AddFriendReq req, Integer appId){ + req.setAppId(appId); + return imFriendShipService.addFriend(req); + } + + @RequestMapping("/updateFriend") + public ResponseVO updateFriend(@RequestBody @Validated UpdateFriendReq req, Integer appId){ + req.setAppId(appId); + return imFriendShipService.updateFriend(req); + } + + @RequestMapping("/deleteFriend") + public ResponseVO deleteFriend(@RequestBody @Validated DeleteFriendReq req, Integer appId){ + req.setAppId(appId); + return imFriendShipService.deleteFriend(req); + } + + @RequestMapping("/deleteAllFriend") + public ResponseVO deleteAllFriend(@RequestBody @Validated DeleteFriendReq req, Integer appId){ + req.setAppId(appId); + return imFriendShipService.deleteAllFriend(req); + } + + @RequestMapping("/getAllFriendShip") + public ResponseVO getAllFriendShip(@RequestBody @Validated GetAllFriendShipReq req, Integer appId){ + req.setAppId(appId); + return imFriendShipService.getAllFriendShip(req); + } + + @RequestMapping("/getRelation") + public ResponseVO getRelation(@RequestBody @Validated GetRelationReq req, Integer appId){ + req.setAppId(appId); + return imFriendShipService.getRelation(req); + } + + @RequestMapping("/checkFriend") + public ResponseVO checkFriend(@RequestBody @Validated CheckFriendShipReq req, Integer appId){ + req.setAppId(appId); + return imFriendShipService.checkFriendship(req); + } + + @RequestMapping("/addBlack") + public ResponseVO addBlack(@RequestBody @Validated AddFriendShipBlackReq req, Integer appId){ + req.setAppId(appId); + return imFriendShipService.addBlack(req); + } + + @RequestMapping("/deleteBlack") + public ResponseVO deleteBlack(@RequestBody @Validated DeleteBlackReq req, Integer appId){ + req.setAppId(appId); + return imFriendShipService.deleteBlack(req); + } + + @RequestMapping("/checkBlck") + public ResponseVO checkBlck(@RequestBody @Validated CheckFriendShipReq req, Integer appId){ + req.setAppId(appId); + return imFriendShipService.checkBlck(req); + } + + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/controller/ImFriendShipGroupController.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/controller/ImFriendShipGroupController.java new file mode 100644 index 0000000..9a3ced9 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/controller/ImFriendShipGroupController.java @@ -0,0 +1,56 @@ +package com.lld.im.service.friendship.controller; + +import com.lld.im.common.ResponseVO; +import com.lld.im.service.friendship.model.req.AddFriendShipGroupMemberReq; +import com.lld.im.service.friendship.model.req.AddFriendShipGroupReq; +import com.lld.im.service.friendship.model.req.DeleteFriendShipGroupMemberReq; +import com.lld.im.service.friendship.model.req.DeleteFriendShipGroupReq; +import com.lld.im.service.friendship.service.ImFriendShipGroupMemberService; +import com.lld.im.service.friendship.service.ImFriendShipGroupService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author: Chackylee + * @description: + **/ +@RestController +@RequestMapping("v1/friendship/group") +public class ImFriendShipGroupController { + + @Autowired + ImFriendShipGroupService imFriendShipGroupService; + + @Autowired + ImFriendShipGroupMemberService imFriendShipGroupMemberService; + + + @RequestMapping("/add") + public ResponseVO add(@RequestBody @Validated AddFriendShipGroupReq req, Integer appId) { + req.setAppId(appId); + return imFriendShipGroupService.addGroup(req); + } + + @RequestMapping("/del") + public ResponseVO del(@RequestBody @Validated DeleteFriendShipGroupReq req, Integer appId) { + req.setAppId(appId); + return imFriendShipGroupService.deleteGroup(req); + } + + @RequestMapping("/member/add") + public ResponseVO memberAdd(@RequestBody @Validated AddFriendShipGroupMemberReq req, Integer appId) { + req.setAppId(appId); + return imFriendShipGroupMemberService.addGroupMember(req); + } + + @RequestMapping("/member/del") + public ResponseVO memberdel(@RequestBody @Validated DeleteFriendShipGroupMemberReq req, Integer appId) { + req.setAppId(appId); + return imFriendShipGroupMemberService.delGroupMember(req); + } + + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/controller/ImFriendShipRequestController.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/controller/ImFriendShipRequestController.java new file mode 100644 index 0000000..57ad0b8 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/controller/ImFriendShipRequestController.java @@ -0,0 +1,42 @@ +package com.lld.im.service.friendship.controller; + +import com.lld.im.common.ResponseVO; +import com.lld.im.service.friendship.model.req.ApproverFriendRequestReq; +import com.lld.im.service.friendship.model.req.GetFriendShipRequestReq; +import com.lld.im.service.friendship.model.req.ReadFriendShipRequestReq; +import com.lld.im.service.friendship.service.ImFriendShipRequestService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + + +@RestController +@RequestMapping("v1/friendshipRequest") +public class ImFriendShipRequestController { + + @Autowired + ImFriendShipRequestService imFriendShipRequestService; + + @RequestMapping("/approveFriendRequest") + public ResponseVO approveFriendRequest(@RequestBody @Validated + ApproverFriendRequestReq req, Integer appId, String identifier){ + req.setAppId(appId); + req.setOperater(identifier); + return imFriendShipRequestService.approverFriendRequest(req); + } + @RequestMapping("/getFriendRequest") + public ResponseVO getFriendRequest(@RequestBody @Validated GetFriendShipRequestReq req, Integer appId){ + req.setAppId(appId); + return imFriendShipRequestService.getFriendRequest(req.getFromId(),req.getAppId()); + } + + @RequestMapping("/readFriendShipRequestReq") + public ResponseVO readFriendShipRequestReq(@RequestBody @Validated ReadFriendShipRequestReq req, Integer appId){ + req.setAppId(appId); + return imFriendShipRequestService.readFriendShipRequestReq(req); + } + + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/dao/ImFriendShipEntity.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/dao/ImFriendShipEntity.java new file mode 100644 index 0000000..bc98d52 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/dao/ImFriendShipEntity.java @@ -0,0 +1,46 @@ +package com.lld.im.service.friendship.dao; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.github.jeffreyning.mybatisplus.anno.AutoMap; +import lombok.Data; + +/** + * @author: Chackylee + * @description: + **/ + +@Data +@TableName("im_friendship") +@AutoMap +public class ImFriendShipEntity { + + @TableField(value = "app_id") + private Integer appId; + + @TableField(value = "from_id") + private String fromId; + + @TableField(value = "to_id") + private String toId; + /** 备注*/ + private String remark; + /** 状态 1正常 2删除*/ + private Integer status; + /** 状态 1正常 2拉黑*/ + private Integer black; +// @TableField(updateStrategy = FieldStrategy.IGNORED) + private Long createTime; + /** 好友关系序列号*/ +// @TableField(updateStrategy = FieldStrategy.IGNORED) + private Long friendSequence; + + /** 黑名单关系序列号*/ + private Long blackSequence; + /** 好友来源*/ +// @TableField(updateStrategy = FieldStrategy.IGNORED) + private String addSource; + + private String extra; + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/dao/ImFriendShipGroupEntity.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/dao/ImFriendShipGroupEntity.java new file mode 100644 index 0000000..2319f3f --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/dao/ImFriendShipGroupEntity.java @@ -0,0 +1,32 @@ +package com.lld.im.service.friendship.dao; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +@Data +@TableName("im_friendship_group") +public class ImFriendShipGroupEntity { + + @TableId(value = "group_id",type = IdType.AUTO) + private Long groupId; + + private String fromId; + + private Integer appId; + + private String groupName; + /** 备注*/ + private Long createTime; + + /** 备注*/ + private Long updateTime; + + /** 序列号*/ + private Long sequence; + + private int delFlag; + + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/dao/ImFriendShipGroupMemberEntity.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/dao/ImFriendShipGroupMemberEntity.java new file mode 100644 index 0000000..c8cf26b --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/dao/ImFriendShipGroupMemberEntity.java @@ -0,0 +1,17 @@ +package com.lld.im.service.friendship.dao; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + + +@Data +@TableName("im_friendship_group_member") +public class ImFriendShipGroupMemberEntity { + + @TableId(value = "group_id") + private Long groupId; + + private String toId; + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/dao/ImFriendShipRequestEntity.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/dao/ImFriendShipRequestEntity.java new file mode 100644 index 0000000..c2de949 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/dao/ImFriendShipRequestEntity.java @@ -0,0 +1,49 @@ +package com.lld.im.service.friendship.dao; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + + +@Data +@TableName("im_friendship_request") +public class ImFriendShipRequestEntity { + + @TableId(type = IdType.AUTO) + private Long id; + + private Integer appId; + + private String fromId; + + private String toId; + /** 备注*/ +// @TableField(updateStrategy = FieldStrategy.IGNORED) + private String remark; + + //是否已读 1已读 + private Integer readStatus; + + /** 好友来源*/ +// @TableField(updateStrategy = FieldStrategy.IGNORED) + private String addSource; + +// @TableField(updateStrategy = FieldStrategy.IGNORED) + private String addWording; + + //审批状态 1同意 2拒绝 + private Integer approveStatus; + +// @TableField(updateStrategy = FieldStrategy.IGNORED) + private Long createTime; + + private Long updateTime; + + /** 序列号*/ + private Long sequence; + + + + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/dao/mapper/ImFriendShipGroupMapper.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/dao/mapper/ImFriendShipGroupMapper.java new file mode 100644 index 0000000..b621a23 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/dao/mapper/ImFriendShipGroupMapper.java @@ -0,0 +1,9 @@ +package com.lld.im.service.friendship.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lld.im.service.friendship.dao.ImFriendShipGroupEntity; + +public interface ImFriendShipGroupMapper extends BaseMapper { + + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/dao/mapper/ImFriendShipGroupMemberMapper.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/dao/mapper/ImFriendShipGroupMemberMapper.java new file mode 100644 index 0000000..b477445 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/dao/mapper/ImFriendShipGroupMemberMapper.java @@ -0,0 +1,9 @@ +package com.lld.im.service.friendship.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lld.im.service.friendship.dao.ImFriendShipGroupMemberEntity; + +public interface ImFriendShipGroupMemberMapper extends BaseMapper { + + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/dao/mapper/ImFriendShipMapper.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/dao/mapper/ImFriendShipMapper.java new file mode 100644 index 0000000..87e0430 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/dao/mapper/ImFriendShipMapper.java @@ -0,0 +1,91 @@ +package com.lld.im.service.friendship.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lld.im.service.friendship.dao.ImFriendShipEntity; +import com.lld.im.service.friendship.model.req.CheckFriendShipReq; +import com.lld.im.service.friendship.model.resp.CheckFriendShipResp; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +@Mapper +public interface ImFriendShipMapper extends BaseMapper { + + + + + @Select("") + public List checkFriendShip(CheckFriendShipReq req); + + + @Select("" + ) + List checkFriendShipBoth(CheckFriendShipReq toId); + + + + + + + @Select("" + ) + List checkFriendShipBlack(CheckFriendShipReq req); + + @Select("" + ) + List checkFriendShipBlackBoth(CheckFriendShipReq toId); + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/dao/mapper/ImFriendShipRequestMapper.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/dao/mapper/ImFriendShipRequestMapper.java new file mode 100644 index 0000000..c153dae --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/dao/mapper/ImFriendShipRequestMapper.java @@ -0,0 +1,9 @@ +package com.lld.im.service.friendship.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lld.im.service.friendship.dao.ImFriendShipRequestEntity; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface ImFriendShipRequestMapper extends BaseMapper { +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/AddFriendReq.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/AddFriendReq.java new file mode 100644 index 0000000..cd31d0a --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/AddFriendReq.java @@ -0,0 +1,19 @@ +package com.lld.im.service.friendship.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + + +@Data +public class AddFriendReq extends RequestBase { + + @NotBlank(message = "fromId不能为空") + private String fromId; + + @NotNull(message = "toItem不能为空") + private FriendDto toItem; + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/AddFriendShipBlackReq.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/AddFriendShipBlackReq.java new file mode 100644 index 0000000..69f5017 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/AddFriendShipBlackReq.java @@ -0,0 +1,16 @@ +package com.lld.im.service.friendship.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + + +@Data +public class AddFriendShipBlackReq extends RequestBase { + + @NotBlank(message = "用户id不能为空") + private String fromId; + + private String toId; +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/AddFriendShipGroupMemberReq.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/AddFriendShipGroupMemberReq.java new file mode 100644 index 0000000..4f02bf7 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/AddFriendShipGroupMemberReq.java @@ -0,0 +1,24 @@ +package com.lld.im.service.friendship.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import java.util.List; + + +@Data +public class AddFriendShipGroupMemberReq extends RequestBase { + + @NotBlank(message = "fromId不能为空") + private String fromId; + + @NotBlank(message = "分组名称不能为空") + private String groupName; + + @NotEmpty(message = "请选择用户") + private List toIds; + + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/AddFriendShipGroupReq.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/AddFriendShipGroupReq.java new file mode 100644 index 0000000..ed3ed09 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/AddFriendShipGroupReq.java @@ -0,0 +1,21 @@ +package com.lld.im.service.friendship.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import java.util.List; + + +@Data +public class AddFriendShipGroupReq extends RequestBase { + + @NotBlank(message = "fromId不能为空") + public String fromId; + + @NotBlank(message = "分组名称不能为空") + private String groupName; + + private List toIds; + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/ApproverFriendRequestReq.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/ApproverFriendRequestReq.java new file mode 100644 index 0000000..22d1833 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/ApproverFriendRequestReq.java @@ -0,0 +1,14 @@ +package com.lld.im.service.friendship.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + + +@Data +public class ApproverFriendRequestReq extends RequestBase { + + private Long id; + + //1同意 2拒绝 + private Integer status; +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/CheckFriendShipReq.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/CheckFriendShipReq.java new file mode 100644 index 0000000..721d8b2 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/CheckFriendShipReq.java @@ -0,0 +1,27 @@ +package com.lld.im.service.friendship.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Data +public class CheckFriendShipReq extends RequestBase { + + @NotBlank(message = "fromId不能为空") + private String fromId; + + @NotEmpty(message = "toIds不能为空") + private List toIds; + + @NotNull(message = "checkType不能为空") + private Integer checkType; +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/DeleteBlackReq.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/DeleteBlackReq.java new file mode 100644 index 0000000..0ae5dd6 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/DeleteBlackReq.java @@ -0,0 +1,19 @@ +package com.lld.im.service.friendship.model.req; + + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + + +@Data +public class DeleteBlackReq extends RequestBase { + + @NotBlank(message = "用户id不能为空") + private String fromId; + + @NotBlank(message = "好友id不能为空") + private String toId; + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/DeleteFriendReq.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/DeleteFriendReq.java new file mode 100644 index 0000000..3915d90 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/DeleteFriendReq.java @@ -0,0 +1,18 @@ +package com.lld.im.service.friendship.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + + +@Data +public class DeleteFriendReq extends RequestBase { + + @NotBlank(message = "fromId不能为空") + private String fromId; + + @NotBlank(message = "toId不能为空") + private String toId; + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/DeleteFriendShipGroupMemberReq.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/DeleteFriendShipGroupMemberReq.java new file mode 100644 index 0000000..af98c18 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/DeleteFriendShipGroupMemberReq.java @@ -0,0 +1,27 @@ +package com.lld.im.service.friendship.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import java.util.List; + +/** + * @author: Chackylee + * @description: + **/ +@Data +public class DeleteFriendShipGroupMemberReq extends RequestBase { + + @NotBlank(message = "fromId不能为空") + private String fromId; + + @NotBlank(message = "分组名称不能为空") + private String groupName; + + @NotEmpty(message = "请选择用户") + private List toIds; + + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/DeleteFriendShipGroupReq.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/DeleteFriendShipGroupReq.java new file mode 100644 index 0000000..7d23925 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/DeleteFriendShipGroupReq.java @@ -0,0 +1,23 @@ +package com.lld.im.service.friendship.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import java.util.List; + +/** + * @author: Chackylee + * @description: 删除分组,同时删除分组下的成员 + **/ +@Data +public class DeleteFriendShipGroupReq extends RequestBase { + + @NotBlank(message = "fromId不能为空") + private String fromId; + + @NotEmpty(message = "分组名称不能为空") + private List groupName; + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/FriendDto.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/FriendDto.java new file mode 100644 index 0000000..2a69fdf --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/FriendDto.java @@ -0,0 +1,19 @@ +package com.lld.im.service.friendship.model.req; + +import lombok.Data; + + +@Data +public class FriendDto { + + private String toId; + + private String remark; + + private String addSource; + + private String extra; + + private String addWording; + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/GetAllFriendShipReq.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/GetAllFriendShipReq.java new file mode 100644 index 0000000..e997236 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/GetAllFriendShipReq.java @@ -0,0 +1,14 @@ +package com.lld.im.service.friendship.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + + +@Data +public class GetAllFriendShipReq extends RequestBase { + + @NotBlank(message = "用户id不能为空") + private String fromId; +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/GetFriendShipRequestReq.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/GetFriendShipRequestReq.java new file mode 100644 index 0000000..a277767 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/GetFriendShipRequestReq.java @@ -0,0 +1,19 @@ +package com.lld.im.service.friendship.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Data +public class GetFriendShipRequestReq extends RequestBase { + + @NotBlank(message = "用户id不能为空") + private String fromId; + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/GetRelationReq.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/GetRelationReq.java new file mode 100644 index 0000000..eb97c78 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/GetRelationReq.java @@ -0,0 +1,16 @@ +package com.lld.im.service.friendship.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + + +@Data +public class GetRelationReq extends RequestBase { + @NotBlank(message = "fromId不能为空") + private String fromId; + + @NotBlank(message = "toId不能为空") + private String toId; +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/ImporFriendShipReq.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/ImporFriendShipReq.java new file mode 100644 index 0000000..8e6a6cd --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/ImporFriendShipReq.java @@ -0,0 +1,33 @@ +package com.lld.im.service.friendship.model.req; + +import com.lld.im.common.enums.FriendShipStatusEnum; +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import java.util.List; + + +@Data +public class ImporFriendShipReq extends RequestBase { + + @NotBlank(message = "fromId不能为空") + private String fromId; + + private List friendItem; + + @Data + public static class ImportFriendDto{ + + private String toId; + + private String remark; + + private String addSource; + + private Integer status = FriendShipStatusEnum.FRIEND_STATUS_NO_FRIEND.getCode(); + + private Integer black = FriendShipStatusEnum.BLACK_STATUS_NORMAL.getCode(); + } + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/ReadFriendShipRequestReq.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/ReadFriendShipRequestReq.java new file mode 100644 index 0000000..afbe591 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/ReadFriendShipRequestReq.java @@ -0,0 +1,14 @@ +package com.lld.im.service.friendship.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + + +@Data +public class ReadFriendShipRequestReq extends RequestBase { + + @NotBlank(message = "用户id不能为空") + private String fromId; +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/UpdateFriendReq.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/UpdateFriendReq.java new file mode 100644 index 0000000..3250543 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/req/UpdateFriendReq.java @@ -0,0 +1,18 @@ +package com.lld.im.service.friendship.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + + +@Data +public class UpdateFriendReq extends RequestBase { + + @NotBlank(message = "fromId不能为空") + private String fromId; + + @NotNull(message = "toItem不能为空") + private FriendDto toItem; +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/resp/CheckFriendShipResp.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/resp/CheckFriendShipResp.java new file mode 100644 index 0000000..c8951e2 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/resp/CheckFriendShipResp.java @@ -0,0 +1,30 @@ +package com.lld.im.service.friendship.model.resp; + +import lombok.Data; + + +@Data +public class CheckFriendShipResp { + + private String fromId; + + private String toId; + + + //校验状态,根据双向校验和单向校验有不同的status + //单向校验:1 from添加了to,不确定to是否添加了from CheckResult_single_Type_AWithB; + // 0 from没有添加to,也不确定to有没有添加from CheckResult_single_Type_NoRelation + //双向校验 1 from添加了to,to也添加了from CheckResult_Type_BothWay + // 2 from添加了t0,to没有添加from CheckResult_Both_Type_AWithB + // 3 from没有添加to,to添加了from, CheckResult_Both_Type_BWithA + // 4 双方都没有添加 CheckResult_Both_Type_NoRelation + + //单向校验黑名单:1 from没有拉黑to,不确定to是否拉黑了from CheckResult_singe_Type_AWithB; + // 0 from拉黑to,不确定to是佛拉黑from CheckResult_singe_Type_NoRelation + //双向校验黑名单 1 from没有拉黑to,to也没有拉黑from CheckResult_Type_BothWay + // 2 from没有拉黑to,to拉黑from CheckResult_Both_Type_AWithB + // 3 from拉黑了to,to没有拉黑from CheckResult_Both_Type_BWithA + // 4 双方都拉黑 CheckResult_Both_Type_NoRelation + private Integer status; + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/resp/ImportFriendShipResp.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/resp/ImportFriendShipResp.java new file mode 100644 index 0000000..240016b --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/model/resp/ImportFriendShipResp.java @@ -0,0 +1,14 @@ +package com.lld.im.service.friendship.model.resp; + +import lombok.Data; + +import java.util.List; + + +@Data +public class ImportFriendShipResp { + + private List successId; + + private List errorId; +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/service/ImFriendService.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/service/ImFriendService.java new file mode 100644 index 0000000..885cfd5 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/service/ImFriendService.java @@ -0,0 +1,40 @@ +package com.lld.im.service.friendship.service; + +import com.lld.im.common.ResponseVO; +import com.lld.im.common.model.RequestBase; +import com.lld.im.service.friendship.model.req.*; + +import java.util.List; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +public interface ImFriendService { + + public ResponseVO importFriendShip(ImporFriendShipReq req); + + public ResponseVO addFriend(AddFriendReq req); + + public ResponseVO updateFriend(UpdateFriendReq req); + + public ResponseVO deleteFriend(DeleteFriendReq req); + + public ResponseVO deleteAllFriend(DeleteFriendReq req); + + public ResponseVO getAllFriendShip(GetAllFriendShipReq req); + + public ResponseVO getRelation(GetRelationReq req); + + public ResponseVO doAddFriend(RequestBase requestBase,String fromId, FriendDto dto, Integer appId); + + public ResponseVO checkFriendship(CheckFriendShipReq req); + + public ResponseVO addBlack(AddFriendShipBlackReq req); + + public ResponseVO deleteBlack(DeleteBlackReq req); + + public ResponseVO checkBlck(CheckFriendShipReq req); + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/service/ImFriendShipGroupMemberService.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/service/ImFriendShipGroupMemberService.java new file mode 100644 index 0000000..2783dbe --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/service/ImFriendShipGroupMemberService.java @@ -0,0 +1,20 @@ +package com.lld.im.service.friendship.service; + +import com.lld.im.common.ResponseVO; +import com.lld.im.service.friendship.model.req.AddFriendShipGroupMemberReq; +import com.lld.im.service.friendship.model.req.DeleteFriendShipGroupMemberReq; + +/** + * @author: Chackylee + * @description: + **/ +public interface ImFriendShipGroupMemberService { + + public ResponseVO addGroupMember(AddFriendShipGroupMemberReq req); + + public ResponseVO delGroupMember(DeleteFriendShipGroupMemberReq req); + + public int doAddGroupMember(Long groupId, String toId); + + public int clearGroupMember(Long groupId); +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/service/ImFriendShipGroupService.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/service/ImFriendShipGroupService.java new file mode 100644 index 0000000..2a1c268 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/service/ImFriendShipGroupService.java @@ -0,0 +1,21 @@ +package com.lld.im.service.friendship.service; + +import com.lld.im.common.ResponseVO; +import com.lld.im.service.friendship.dao.ImFriendShipGroupEntity; +import com.lld.im.service.friendship.model.req.AddFriendShipGroupReq; +import com.lld.im.service.friendship.model.req.DeleteFriendShipGroupReq; + +/** + * @author: Chackylee + * @description: + **/ +public interface ImFriendShipGroupService { + + public ResponseVO addGroup(AddFriendShipGroupReq req); + + public ResponseVO deleteGroup(DeleteFriendShipGroupReq req); + + public ResponseVO getGroup(String fromId, String groupName, Integer appId); + + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/service/ImFriendShipRequestService.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/service/ImFriendShipRequestService.java new file mode 100644 index 0000000..8f98a2b --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/service/ImFriendShipRequestService.java @@ -0,0 +1,18 @@ +package com.lld.im.service.friendship.service; + +import com.lld.im.common.ResponseVO; +import com.lld.im.service.friendship.model.req.ApproverFriendRequestReq; +import com.lld.im.service.friendship.model.req.FriendDto; +import com.lld.im.service.friendship.model.req.ReadFriendShipRequestReq; + + +public interface ImFriendShipRequestService { + + public ResponseVO addFienshipRequest(String fromId, FriendDto dto, Integer appId); + + public ResponseVO approverFriendRequest(ApproverFriendRequestReq req); + + public ResponseVO readFriendShipRequestReq(ReadFriendShipRequestReq req); + + public ResponseVO getFriendRequest(String fromId, Integer appId); +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/service/impl/ImFriendServiceImpl.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/service/impl/ImFriendServiceImpl.java new file mode 100644 index 0000000..88c4142 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/service/impl/ImFriendServiceImpl.java @@ -0,0 +1,439 @@ +package com.lld.im.service.friendship.service.impl; + +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import com.lld.im.common.ResponseVO; +import com.lld.im.common.enums.AllowFriendTypeEnum; +import com.lld.im.common.enums.CheckFriendShipTypeEnum; +import com.lld.im.common.enums.FriendShipErrorCode; +import com.lld.im.common.enums.FriendShipStatusEnum; +import com.lld.im.common.exception.ApplicationException; +import com.lld.im.common.model.RequestBase; +import com.lld.im.service.friendship.dao.ImFriendShipEntity; +import com.lld.im.service.friendship.dao.mapper.ImFriendShipMapper; +import com.lld.im.service.friendship.model.req.*; +import com.lld.im.service.friendship.model.resp.CheckFriendShipResp; +import com.lld.im.service.friendship.model.resp.ImportFriendShipResp; +import com.lld.im.service.friendship.service.ImFriendService; +import com.lld.im.service.friendship.service.ImFriendShipRequestService; +import com.lld.im.service.user.dao.ImUserDataEntity; +import com.lld.im.service.user.service.ImUserService; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Service +public class ImFriendServiceImpl implements ImFriendService { + + @Autowired + ImFriendShipMapper imFriendShipMapper; + + @Autowired + ImUserService imUserService; + + @Autowired + ImFriendService imFriendService; + + @Autowired + ImFriendShipRequestService imFriendShipRequestService; + + @Override + public ResponseVO importFriendShip(ImporFriendShipReq req) { + + if(req.getFriendItem().size() > 100){ + return ResponseVO.errorResponse(FriendShipErrorCode.IMPORT_SIZE_BEYOND); + } + ImportFriendShipResp resp = new ImportFriendShipResp(); + List successId = new ArrayList<>(); + List errorId = new ArrayList<>(); + + for (ImporFriendShipReq.ImportFriendDto dto: + req.getFriendItem()) { + ImFriendShipEntity entity = new ImFriendShipEntity(); + BeanUtils.copyProperties(dto,entity); + entity.setAppId(req.getAppId()); + entity.setFromId(req.getFromId()); + try { + int insert = imFriendShipMapper.insert(entity); + if(insert == 1){ + successId.add(dto.getToId()); + }else{ + errorId.add(dto.getToId()); + } + }catch (Exception e){ + e.printStackTrace(); + errorId.add(dto.getToId()); + } + + } + + resp.setErrorId(errorId); + resp.setSuccessId(successId); + + return ResponseVO.successResponse(resp); + } + + @Override + public ResponseVO addFriend(AddFriendReq req) { + + ResponseVO fromInfo = imUserService.getSingleUserInfo(req.getFromId(), req.getAppId()); + if(!fromInfo.isOk()){ + return fromInfo; + } + + ResponseVO toInfo = imUserService.getSingleUserInfo(req.getToItem().getToId(), req.getAppId()); + if(!toInfo.isOk()){ + return toInfo; + } + + ImUserDataEntity data = toInfo.getData(); + + if(data.getFriendAllowType() != null && data.getFriendAllowType() == AllowFriendTypeEnum.NOT_NEED.getCode()){ + return this.doAddFriend(req,req.getFromId(), req.getToItem(), req.getAppId()); + }else{ + QueryWrapper query = new QueryWrapper<>(); + query.eq("app_id",req.getAppId()); + query.eq("from_id",req.getFromId()); + query.eq("to_id",req.getToItem().getToId()); + ImFriendShipEntity fromItem = imFriendShipMapper.selectOne(query); + if(fromItem == null || fromItem.getStatus() + != FriendShipStatusEnum.FRIEND_STATUS_NORMAL.getCode()){ + //插入一条好友申请的数据 + ResponseVO responseVO = imFriendShipRequestService.addFienshipRequest(req.getFromId(), req.getToItem(), req.getAppId()); + if(!responseVO.isOk()){ + return responseVO; + } + }else{ + return ResponseVO.errorResponse(FriendShipErrorCode.TO_IS_YOUR_FRIEND); + } + + } + + return ResponseVO.successResponse(); + } + + @Override + public ResponseVO updateFriend(UpdateFriendReq req) { + + ResponseVO fromInfo = imUserService.getSingleUserInfo(req.getFromId(), req.getAppId()); + if(!fromInfo.isOk()){ + return fromInfo; + } + + ResponseVO toInfo = imUserService.getSingleUserInfo(req.getToItem().getToId(), req.getAppId()); + if(!toInfo.isOk()){ + return toInfo; + } + + ResponseVO responseVO = this.doUpdate(req.getFromId(), req.getToItem(), req.getAppId()); + return responseVO; + } + + @Transactional + public ResponseVO doUpdate(String fromId, FriendDto dto,Integer appId){ + + + UpdateWrapper updateWrapper = new UpdateWrapper<>(); + updateWrapper.lambda().set(ImFriendShipEntity::getAddSource,dto.getAddSource()) + .set(ImFriendShipEntity::getExtra,dto.getExtra()) + .set(ImFriendShipEntity::getRemark,dto.getRemark()) + .eq(ImFriendShipEntity::getAppId,appId) + .eq(ImFriendShipEntity::getToId,dto.getToId()) + .eq(ImFriendShipEntity::getFromId,fromId); + + int update = imFriendShipMapper.update(null, updateWrapper); + if(update == 1){ + return ResponseVO.successResponse(); + } + + return ResponseVO.errorResponse(); + } + + @Override + @Transactional + public ResponseVO doAddFriend(RequestBase requestBase,String fromId, FriendDto dto, Integer appId){ + + //A-B + //Friend表插入A 和 B 两条记录 + //查询是否有记录存在,如果存在则判断状态,如果是已添加,则提示已添加,如果是未添加,则修改状态 + + QueryWrapper query = new QueryWrapper<>(); + query.eq("app_id",appId); + query.eq("from_id",fromId); + query.eq("to_id",dto.getToId()); + ImFriendShipEntity fromItem = imFriendShipMapper.selectOne(query); + if(fromItem == null){ + //走添加逻辑。 + fromItem = new ImFriendShipEntity(); + fromItem.setAppId(appId); + fromItem.setFromId(fromId); +// entity.setToId(to); + BeanUtils.copyProperties(dto,fromItem); + fromItem.setStatus(FriendShipStatusEnum.FRIEND_STATUS_NORMAL.getCode()); + fromItem.setCreateTime(System.currentTimeMillis()); + int insert = imFriendShipMapper.insert(fromItem); + if(insert != 1){ + return ResponseVO.errorResponse(FriendShipErrorCode.ADD_FRIEND_ERROR); + } + } else{ + //如果存在则判断状态,如果是已添加,则提示已添加,如果是未添加,则修改状态 + if(fromItem.getStatus() == FriendShipStatusEnum.FRIEND_STATUS_NORMAL.getCode()){ + return ResponseVO.errorResponse(FriendShipErrorCode.TO_IS_YOUR_FRIEND); + } else{ + ImFriendShipEntity update = new ImFriendShipEntity(); + + if(StringUtils.isNotBlank(dto.getAddSource())){ + update.setAddSource(dto.getAddSource()); + } + + if(StringUtils.isNotBlank(dto.getRemark())){ + update.setRemark(dto.getRemark()); + } + + if(StringUtils.isNotBlank(dto.getExtra())){ + update.setExtra(dto.getExtra()); + } + update.setStatus(FriendShipStatusEnum.FRIEND_STATUS_NORMAL.getCode()); + + int result = imFriendShipMapper.update(update, query); + if(result != 1){ + return ResponseVO.errorResponse(FriendShipErrorCode.ADD_FRIEND_ERROR); + } + } + + } + + QueryWrapper toQuery = new QueryWrapper<>(); + toQuery.eq("app_id",appId); + toQuery.eq("from_id",dto.getToId()); + toQuery.eq("to_id",fromId); + ImFriendShipEntity toItem = imFriendShipMapper.selectOne(toQuery); + if(toItem == null){ + toItem = new ImFriendShipEntity(); + toItem.setAppId(appId); + toItem.setFromId(dto.getToId()); + BeanUtils.copyProperties(dto,toItem); + toItem.setToId(fromId); + toItem.setStatus(FriendShipStatusEnum.FRIEND_STATUS_NORMAL.getCode()); + toItem.setCreateTime(System.currentTimeMillis()); +// toItem.setBlack(FriendShipStatusEnum.BLACK_STATUS_NORMAL.getCode()); + int insert = imFriendShipMapper.insert(toItem); + }else{ + if(FriendShipStatusEnum.FRIEND_STATUS_NORMAL.getCode() != + toItem.getStatus()){ + ImFriendShipEntity update = new ImFriendShipEntity(); + update.setStatus(FriendShipStatusEnum.FRIEND_STATUS_NORMAL.getCode()); + imFriendShipMapper.update(update,toQuery); + } + } + return ResponseVO.successResponse(); + } + + + @Override + public ResponseVO deleteFriend(DeleteFriendReq req) { + + QueryWrapper query = new QueryWrapper<>(); + query.eq("app_id",req.getAppId()); + query.eq("from_id",req.getFromId()); + query.eq("to_id",req.getToId()); + ImFriendShipEntity fromItem = imFriendShipMapper.selectOne(query); + if(fromItem == null){ + return ResponseVO.errorResponse(FriendShipErrorCode.TO_IS_NOT_YOUR_FRIEND); + }else{ + if(fromItem.getStatus() != null && fromItem.getStatus() == FriendShipStatusEnum.FRIEND_STATUS_NORMAL.getCode()){ + ImFriendShipEntity update = new ImFriendShipEntity(); + update.setStatus(FriendShipStatusEnum.FRIEND_STATUS_DELETE.getCode()); + imFriendShipMapper.update(update,query); + + }else{ + return ResponseVO.errorResponse(FriendShipErrorCode.FRIEND_IS_DELETED); + } + } + return ResponseVO.successResponse(); + } + + @Override + public ResponseVO deleteAllFriend(DeleteFriendReq req) { + QueryWrapper query = new QueryWrapper<>(); + query.eq("app_id",req.getAppId()); + query.eq("from_id",req.getFromId()); + query.eq("status",FriendShipStatusEnum.FRIEND_STATUS_NORMAL.getCode()); + + ImFriendShipEntity update = new ImFriendShipEntity(); + update.setStatus(FriendShipStatusEnum.FRIEND_STATUS_DELETE.getCode()); + imFriendShipMapper.update(update,query); + return ResponseVO.successResponse(); + } + + @Override + public ResponseVO getAllFriendShip(GetAllFriendShipReq req) { + QueryWrapper query = new QueryWrapper<>(); + query.eq("app_id",req.getAppId()); + query.eq("from_id",req.getFromId()); + return ResponseVO.successResponse(imFriendShipMapper.selectList(query)); + } + + @Override + public ResponseVO getRelation(GetRelationReq req) { + + QueryWrapper query = new QueryWrapper<>(); + query.eq("app_id",req.getAppId()); + query.eq("from_id",req.getFromId()); + query.eq("to_id",req.getToId()); + + ImFriendShipEntity entity = imFriendShipMapper.selectOne(query); + if(entity == null){ + return ResponseVO.errorResponse(FriendShipErrorCode.REPEATSHIP_IS_NOT_EXIST); + } + return ResponseVO.successResponse(entity); + } + + @Override + public ResponseVO checkBlck(CheckFriendShipReq req) { + + Map toIdMap + = req.getToIds().stream().collect(Collectors + .toMap(Function.identity(), s -> 0)); + List result = new ArrayList<>(); + if (req.getCheckType() == CheckFriendShipTypeEnum.SINGLE.getType()) { + result = imFriendShipMapper.checkFriendShipBlack(req); + } else { + result = imFriendShipMapper.checkFriendShipBlackBoth(req); + } + + Map collect = result.stream() + .collect(Collectors + .toMap(CheckFriendShipResp::getToId, + CheckFriendShipResp::getStatus)); + for (String toId: + toIdMap.keySet()) { + if(!collect.containsKey(toId)){ + CheckFriendShipResp checkFriendShipResp = new CheckFriendShipResp(); + checkFriendShipResp.setToId(toId); + checkFriendShipResp.setFromId(req.getFromId()); + checkFriendShipResp.setStatus(toIdMap.get(toId)); + result.add(checkFriendShipResp); + } + } + + return ResponseVO.successResponse(result); + } + + + @Override + public ResponseVO addBlack(AddFriendShipBlackReq req) { + + ResponseVO fromInfo = imUserService.getSingleUserInfo(req.getFromId(), req.getAppId()); + if(!fromInfo.isOk()){ + return fromInfo; + } + + ResponseVO toInfo = imUserService.getSingleUserInfo(req.getToId(), req.getAppId()); + if(!toInfo.isOk()){ + return toInfo; + } + QueryWrapper query = new QueryWrapper<>(); + query.eq("app_id",req.getAppId()); + query.eq("from_id",req.getFromId()); + query.eq("to_id",req.getToId()); + + ImFriendShipEntity fromItem = imFriendShipMapper.selectOne(query); + if(fromItem == null){ + //走添加逻辑。 + fromItem = new ImFriendShipEntity(); + fromItem.setFromId(req.getFromId()); + fromItem.setToId(req.getToId()); + fromItem.setAppId(req.getAppId()); + fromItem.setBlack(FriendShipStatusEnum.BLACK_STATUS_BLACKED.getCode()); + fromItem.setCreateTime(System.currentTimeMillis()); + int insert = imFriendShipMapper.insert(fromItem); + if(insert != 1){ + return ResponseVO.errorResponse(FriendShipErrorCode.ADD_FRIEND_ERROR); + } + + } else{ + //如果存在则判断状态,如果是拉黑,则提示已拉黑,如果是未拉黑,则修改状态 + if(fromItem.getBlack() != null && fromItem.getBlack() == FriendShipStatusEnum.BLACK_STATUS_BLACKED.getCode()){ + return ResponseVO.errorResponse(FriendShipErrorCode.FRIEND_IS_BLACK); + } else { + ImFriendShipEntity update = new ImFriendShipEntity(); + update.setBlack(FriendShipStatusEnum.BLACK_STATUS_BLACKED.getCode()); + int result = imFriendShipMapper.update(update, query); + if(result != 1){ + return ResponseVO.errorResponse(FriendShipErrorCode.ADD_BLACK_ERROR); + } + } + } + + return ResponseVO.successResponse(); + } + + @Override + public ResponseVO deleteBlack(DeleteBlackReq req) { + QueryWrapper queryFrom = new QueryWrapper<>() + .eq("from_id", req.getFromId()) + .eq("app_id", req.getAppId()) + .eq("to_id", req.getToId()); + ImFriendShipEntity fromItem = imFriendShipMapper.selectOne(queryFrom); + if (fromItem.getBlack() != null && fromItem.getBlack() == FriendShipStatusEnum.BLACK_STATUS_NORMAL.getCode()) { + throw new ApplicationException(FriendShipErrorCode.FRIEND_IS_NOT_YOUR_BLACK); + } + + ImFriendShipEntity update = new ImFriendShipEntity(); + update.setBlack(FriendShipStatusEnum.BLACK_STATUS_NORMAL.getCode()); + int update1 = imFriendShipMapper.update(update, queryFrom); + if(update1 == 1){ + return ResponseVO.successResponse(); + } + return ResponseVO.errorResponse(); + } + + @Override + public ResponseVO checkFriendship(CheckFriendShipReq req) { + + Map result + = req.getToIds().stream() + .collect(Collectors.toMap(Function.identity(), s -> 0)); + + List resp = new ArrayList<>(); + + if(req.getCheckType() == CheckFriendShipTypeEnum.SINGLE.getType()){ + resp =imFriendShipMapper.checkFriendShip(req); + }else { + resp =imFriendShipMapper.checkFriendShipBoth(req); + } + + Map collect = resp.stream() + .collect(Collectors.toMap(CheckFriendShipResp::getToId + , CheckFriendShipResp::getStatus)); + + for (String toId : result.keySet()){ + if(!collect.containsKey(toId)){ + CheckFriendShipResp checkFriendShipResp = new CheckFriendShipResp(); + checkFriendShipResp.setFromId(req.getFromId()); + checkFriendShipResp.setToId(toId); + checkFriendShipResp.setStatus(result.get(toId)); + resp.add(checkFriendShipResp); + } + } + + return ResponseVO.successResponse(resp); + } + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/service/impl/ImFriendShipGroupMemberServiceImpl.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/service/impl/ImFriendShipGroupMemberServiceImpl.java new file mode 100644 index 0000000..0431113 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/service/impl/ImFriendShipGroupMemberServiceImpl.java @@ -0,0 +1,122 @@ +package com.lld.im.service.friendship.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.lld.im.common.ResponseVO; +import com.lld.im.service.friendship.dao.ImFriendShipGroupEntity; +import com.lld.im.service.friendship.dao.ImFriendShipGroupMemberEntity; +import com.lld.im.service.friendship.dao.mapper.ImFriendShipGroupMemberMapper; +import com.lld.im.service.friendship.model.req.AddFriendShipGroupMemberReq; +import com.lld.im.service.friendship.model.req.DeleteFriendShipGroupMemberReq; +import com.lld.im.service.friendship.service.ImFriendShipGroupMemberService; +import com.lld.im.service.friendship.service.ImFriendShipGroupService; +import com.lld.im.service.user.dao.ImUserDataEntity; +import com.lld.im.service.user.service.ImUserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author: Chackylee + * @description: + **/ +@Service +public class ImFriendShipGroupMemberServiceImpl + implements ImFriendShipGroupMemberService { + + @Autowired + ImFriendShipGroupMemberMapper imFriendShipGroupMemberMapper; + + @Autowired + ImFriendShipGroupService imFriendShipGroupService; + + @Autowired + ImUserService imUserService; + + @Autowired + ImFriendShipGroupMemberService thisService; + + @Override + @Transactional + public ResponseVO addGroupMember(AddFriendShipGroupMemberReq req) { + + ResponseVO group = imFriendShipGroupService + .getGroup(req.getFromId(),req.getGroupName(),req.getAppId()); + if(!group.isOk()){ + return group; + } + + List successId = new ArrayList<>(); + for (String toId : req.getToIds()) { + ResponseVO singleUserInfo = imUserService.getSingleUserInfo(toId, req.getAppId()); + if(singleUserInfo.isOk()){ + int i = thisService.doAddGroupMember(group.getData().getGroupId(), toId); + if(i == 1){ + successId.add(toId); + } + } + } + + return ResponseVO.successResponse(successId); + } + + @Override + public ResponseVO delGroupMember(DeleteFriendShipGroupMemberReq req) { + ResponseVO group = imFriendShipGroupService + .getGroup(req.getFromId(),req.getGroupName(),req.getAppId()); + if(!group.isOk()){ + return group; + } + + ArrayList list = new ArrayList(); + for (String toId : req.getToIds()) { + ResponseVO singleUserInfo = imUserService.getSingleUserInfo(toId, req.getAppId()); + if(singleUserInfo.isOk()){ + int i = deleteGroupMember(group.getData().getGroupId(), toId); + if(i == 1){ + list.add(toId); + } + } + } + return ResponseVO.successResponse(list); + } + + @Override + public int doAddGroupMember(Long groupId, String toId) { + ImFriendShipGroupMemberEntity imFriendShipGroupMemberEntity = new ImFriendShipGroupMemberEntity(); + imFriendShipGroupMemberEntity.setGroupId(groupId); + imFriendShipGroupMemberEntity.setToId(toId); + try { + int insert = imFriendShipGroupMemberMapper.insert(imFriendShipGroupMemberEntity); + return insert; + }catch (Exception e){ + e.printStackTrace(); + return 0; + } + } + + public int deleteGroupMember(Long groupId, String toId) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("group_id",groupId); + queryWrapper.eq("to_id",toId); + + try { + int delete = imFriendShipGroupMemberMapper.delete(queryWrapper); +// int insert = imFriendShipGroupMemberMapper.insert(imFriendShipGroupMemberEntity); + return delete; + }catch (Exception e){ + e.printStackTrace(); + return 0; + } + } + + @Override + public int clearGroupMember(Long groupId) { + QueryWrapper query = new QueryWrapper<>(); + query.eq("group_id",groupId); + int delete = imFriendShipGroupMemberMapper.delete(query); + return delete; + } +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/service/impl/ImFriendShipGroupServiceImpl.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/service/impl/ImFriendShipGroupServiceImpl.java new file mode 100644 index 0000000..350e226 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/service/impl/ImFriendShipGroupServiceImpl.java @@ -0,0 +1,119 @@ +package com.lld.im.service.friendship.service.impl; + +import cn.hutool.core.collection.CollectionUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.lld.im.common.ResponseVO; +import com.lld.im.common.enums.DelFlagEnum; +import com.lld.im.common.enums.FriendShipErrorCode; +import com.lld.im.service.friendship.dao.ImFriendShipGroupEntity; +import com.lld.im.service.friendship.dao.mapper.ImFriendShipGroupMapper; +import com.lld.im.service.friendship.model.req.AddFriendShipGroupMemberReq; +import com.lld.im.service.friendship.model.req.AddFriendShipGroupReq; +import com.lld.im.service.friendship.model.req.DeleteFriendShipGroupReq; +import com.lld.im.service.friendship.service.ImFriendShipGroupMemberService; +import com.lld.im.service.friendship.service.ImFriendShipGroupService; +import com.lld.im.service.user.service.ImUserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class ImFriendShipGroupServiceImpl implements ImFriendShipGroupService { + + @Autowired + ImFriendShipGroupMapper imFriendShipGroupMapper; + + @Autowired + ImFriendShipGroupMemberService imFriendShipGroupMemberService; + + @Autowired + ImUserService imUserService; + + @Override + @Transactional + public ResponseVO addGroup(AddFriendShipGroupReq req) { + + QueryWrapper query = new QueryWrapper<>(); + query.eq("group_name", req.getGroupName()); + query.eq("app_id", req.getAppId()); + query.eq("from_id", req.getFromId()); + query.eq("del_flag", DelFlagEnum.NORMAL.getCode()); + + ImFriendShipGroupEntity entity = imFriendShipGroupMapper.selectOne(query); + + if (entity != null) { + return ResponseVO.errorResponse(FriendShipErrorCode.FRIEND_SHIP_GROUP_IS_EXIST); + } + + //写入db + ImFriendShipGroupEntity insert = new ImFriendShipGroupEntity(); + insert.setAppId(req.getAppId()); + insert.setCreateTime(System.currentTimeMillis()); + insert.setDelFlag(DelFlagEnum.NORMAL.getCode()); + insert.setGroupName(req.getGroupName()); + insert.setFromId(req.getFromId()); + try { + int insert1 = imFriendShipGroupMapper.insert(insert); + + if (insert1 != 1) { + return ResponseVO.errorResponse(FriendShipErrorCode.FRIEND_SHIP_GROUP_CREATE_ERROR); + } + + if (insert1 == 1 && CollectionUtil.isNotEmpty(req.getToIds())) { + AddFriendShipGroupMemberReq addFriendShipGroupMemberReq = new AddFriendShipGroupMemberReq(); + addFriendShipGroupMemberReq.setFromId(req.getFromId()); + addFriendShipGroupMemberReq.setGroupName(req.getGroupName()); + addFriendShipGroupMemberReq.setToIds(req.getToIds()); + addFriendShipGroupMemberReq.setAppId(req.getAppId()); + imFriendShipGroupMemberService.addGroupMember(addFriendShipGroupMemberReq); + return ResponseVO.successResponse(); + } + } catch (DuplicateKeyException e) { + e.getStackTrace(); + return ResponseVO.errorResponse(FriendShipErrorCode.FRIEND_SHIP_GROUP_IS_EXIST); + } + return ResponseVO.successResponse(); + } + + @Override + @Transactional + public ResponseVO deleteGroup(DeleteFriendShipGroupReq req) { + + for (String groupName : req.getGroupName()) { + QueryWrapper query = new QueryWrapper<>(); + query.eq("group_name", groupName); + query.eq("app_id", req.getAppId()); + query.eq("from_id", req.getFromId()); + query.eq("del_flag", DelFlagEnum.NORMAL.getCode()); + + ImFriendShipGroupEntity entity = imFriendShipGroupMapper.selectOne(query); + + if (entity != null) { + ImFriendShipGroupEntity update = new ImFriendShipGroupEntity(); + update.setGroupId(entity.getGroupId()); + update.setDelFlag(DelFlagEnum.DELETE.getCode()); + imFriendShipGroupMapper.updateById(update); + imFriendShipGroupMemberService.clearGroupMember(entity.getGroupId()); + + } + } + return ResponseVO.successResponse(); + } + + @Override + public ResponseVO getGroup(String fromId, String groupName, Integer appId) { + QueryWrapper query = new QueryWrapper<>(); + query.eq("group_name", groupName); + query.eq("app_id", appId); + query.eq("from_id", fromId); + query.eq("del_flag", DelFlagEnum.NORMAL.getCode()); + + ImFriendShipGroupEntity entity = imFriendShipGroupMapper.selectOne(query); + if (entity == null) { + return ResponseVO.errorResponse(FriendShipErrorCode.FRIEND_SHIP_GROUP_IS_NOT_EXIST); + } + return ResponseVO.successResponse(entity); + } + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/friendship/service/impl/ImFriendShipRequestServiceImpl.java b/im-server/im-service/src/main/java/com/lld/im/service/friendship/service/impl/ImFriendShipRequestServiceImpl.java new file mode 100644 index 0000000..d806731 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/friendship/service/impl/ImFriendShipRequestServiceImpl.java @@ -0,0 +1,140 @@ +package com.lld.im.service.friendship.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.lld.im.common.ResponseVO; +import com.lld.im.common.enums.ApproverFriendRequestStatusEnum; +import com.lld.im.common.enums.FriendShipErrorCode; +import com.lld.im.common.exception.ApplicationException; +import com.lld.im.service.friendship.dao.ImFriendShipRequestEntity; +import com.lld.im.service.friendship.dao.mapper.ImFriendShipRequestMapper; +import com.lld.im.service.friendship.model.req.ApproverFriendRequestReq; +import com.lld.im.service.friendship.model.req.FriendDto; +import com.lld.im.service.friendship.model.req.ReadFriendShipRequestReq; +import com.lld.im.service.friendship.service.ImFriendService; +import com.lld.im.service.friendship.service.ImFriendShipRequestService; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + + +@Service +public class ImFriendShipRequestServiceImpl implements ImFriendShipRequestService { + + @Autowired + ImFriendShipRequestMapper imFriendShipRequestMapper; + + @Autowired + ImFriendService imFriendShipService; + + @Override + public ResponseVO getFriendRequest(String fromId, Integer appId) { + + QueryWrapper query = new QueryWrapper(); + query.eq("app_id", appId); + query.eq("to_id", fromId); + + List requestList = imFriendShipRequestMapper.selectList(query); + + return ResponseVO.successResponse(requestList); + } + + + //A + B + @Override + public ResponseVO addFienshipRequest(String fromId, FriendDto dto, Integer appId) { + + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("app_id",appId); + queryWrapper.eq("from_id",fromId); + queryWrapper.eq("to_id",dto.getToId()); + ImFriendShipRequestEntity request = imFriendShipRequestMapper.selectOne(queryWrapper); + + if(request == null){ + request = new ImFriendShipRequestEntity(); + request.setAddSource(dto.getAddSource()); + request.setAddWording(dto.getAddWording()); + request.setAppId(appId); + request.setFromId(fromId); + request.setToId(dto.getToId()); + request.setReadStatus(0); + request.setApproveStatus(0); + request.setRemark(dto.getRemark()); + request.setCreateTime(System.currentTimeMillis()); + imFriendShipRequestMapper.insert(request); + + }else { + //修改记录内容 和更新时间 + if(StringUtils.isNotBlank(dto.getAddSource())){ + request.setAddWording(dto.getAddWording()); + } + if(StringUtils.isNotBlank(dto.getRemark())){ + request.setRemark(dto.getRemark()); + } + if(StringUtils.isNotBlank(dto.getAddWording())){ + request.setAddWording(dto.getAddWording()); + } + request.setApproveStatus(0); + request.setReadStatus(0); + imFriendShipRequestMapper.updateById(request); + } + + return ResponseVO.successResponse(); + } + + @Override + @Transactional + public ResponseVO approverFriendRequest(ApproverFriendRequestReq req) { + + ImFriendShipRequestEntity imFriendShipRequestEntity = imFriendShipRequestMapper.selectById(req.getId()); + if(imFriendShipRequestEntity == null){ + throw new ApplicationException(FriendShipErrorCode.FRIEND_REQUEST_IS_NOT_EXIST); + } + + if(!req.getOperater().equals(imFriendShipRequestEntity.getToId())){ + //只能审批发给自己的好友请求 + throw new ApplicationException(FriendShipErrorCode.NOT_APPROVER_OTHER_MAN_REQUEST); + } + + ImFriendShipRequestEntity update = new ImFriendShipRequestEntity(); + update.setApproveStatus(req.getStatus()); + update.setUpdateTime(System.currentTimeMillis()); + update.setId(req.getId()); + imFriendShipRequestMapper.updateById(update); + + if(ApproverFriendRequestStatusEnum.AGREE.getCode() == req.getStatus()){ + //同意 ===> 去执行添加好友逻辑 + FriendDto dto = new FriendDto(); + dto.setAddSource(imFriendShipRequestEntity.getAddSource()); + dto.setAddWording(imFriendShipRequestEntity.getAddWording()); + dto.setRemark(imFriendShipRequestEntity.getRemark()); + dto.setToId(imFriendShipRequestEntity.getToId()); + ResponseVO responseVO = imFriendShipService.doAddFriend(req,imFriendShipRequestEntity.getFromId(), dto,req.getAppId()); +// if(!responseVO.isOk()){ +//// TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); +// return responseVO; +// } + if(!responseVO.isOk() && responseVO.getCode() != FriendShipErrorCode.TO_IS_YOUR_FRIEND.getCode()){ + return responseVO; + } + } + + return ResponseVO.successResponse(); + } + + @Override + public ResponseVO readFriendShipRequestReq(ReadFriendShipRequestReq req) { + QueryWrapper query = new QueryWrapper<>(); + query.eq("app_id", req.getAppId()); + query.eq("to_id", req.getFromId()); + + ImFriendShipRequestEntity update = new ImFriendShipRequestEntity(); + update.setReadStatus(1); + imFriendShipRequestMapper.update(update, query); + + return ResponseVO.successResponse(); + } + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/group/controller/ImGroupController.java b/im-server/im-service/src/main/java/com/lld/im/service/group/controller/ImGroupController.java new file mode 100644 index 0000000..f1bd328 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/group/controller/ImGroupController.java @@ -0,0 +1,80 @@ +package com.lld.im.service.group.controller; + +import com.lld.im.common.ResponseVO; +import com.lld.im.service.group.model.req.*; +import com.lld.im.service.group.service.ImGroupService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@RestController +@RequestMapping("v1/group") +public class ImGroupController { + + @Autowired + ImGroupService groupService; + + @RequestMapping("/importGroup") + public ResponseVO importGroup(@RequestBody @Validated ImportGroupReq req, Integer appId, String identifier) { + req.setAppId(appId); + req.setOperater(identifier); + return groupService.importGroup(req); + } + + @RequestMapping("/createGroup") + public ResponseVO createGroup(@RequestBody @Validated CreateGroupReq req, Integer appId, String identifier) { + req.setAppId(appId); + req.setOperater(identifier); + return groupService.createGroup(req); + } + + @RequestMapping("/getGroupInfo") + public ResponseVO getGroupInfo(@RequestBody @Validated GetGroupReq req, Integer appId) { + req.setAppId(appId); + return groupService.getGroup(req); + } + + @RequestMapping("/update") + public ResponseVO update(@RequestBody @Validated UpdateGroupReq req, Integer appId, String identifier) { + req.setAppId(appId); + req.setOperater(identifier); + return groupService.updateBaseGroupInfo(req); + } + + @RequestMapping("/getJoinedGroup") + public ResponseVO getJoinedGroup(@RequestBody @Validated GetJoinedGroupReq req, Integer appId, String identifier) { + req.setAppId(appId); + req.setOperater(identifier); + return groupService.getJoinedGroup(req); + } + + + @RequestMapping("/destroyGroup") + public ResponseVO destroyGroup(@RequestBody @Validated DestroyGroupReq req, Integer appId, String identifier) { + req.setAppId(appId); + req.setOperater(identifier); + return groupService.destroyGroup(req); + } + + @RequestMapping("/transferGroup") + public ResponseVO transferGroup(@RequestBody @Validated TransferGroupReq req, Integer appId, String identifier) { + req.setAppId(appId); + req.setOperater(identifier); + return groupService.transferGroup(req); + } + + @RequestMapping("/forbidSendMessage") + public ResponseVO forbidSendMessage(@RequestBody @Validated MuteGroupReq req, Integer appId, String identifier) { + req.setAppId(appId); + req.setOperater(identifier); + return groupService.muteGroup(req); + } + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/group/controller/ImGroupMemberController.java b/im-server/im-service/src/main/java/com/lld/im/service/group/controller/ImGroupMemberController.java new file mode 100644 index 0000000..4d9ce84 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/group/controller/ImGroupMemberController.java @@ -0,0 +1,59 @@ +package com.lld.im.service.group.controller; + +import com.lld.im.common.ResponseVO; +import com.lld.im.service.group.model.req.*; +import com.lld.im.service.group.service.ImGroupMemberService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@RestController +@RequestMapping("v1/group/member") +public class ImGroupMemberController { + + @Autowired + ImGroupMemberService groupMemberService; + + @RequestMapping("/importGroupMember") + public ResponseVO importGroupMember(@RequestBody @Validated ImportGroupMemberReq req, Integer appId, String identifier) { + req.setAppId(appId); + req.setOperater(identifier); + return groupMemberService.importGroupMember(req); + } + + @RequestMapping("/add") + public ResponseVO addMember(@RequestBody @Validated AddGroupMemberReq req, Integer appId, String identifier) { + req.setAppId(appId); + req.setOperater(identifier); + return groupMemberService.addMember(req); + } + + @RequestMapping("/remove") + public ResponseVO removeMember(@RequestBody @Validated RemoveGroupMemberReq req, Integer appId, String identifier) { + req.setAppId(appId); + req.setOperater(identifier); + return groupMemberService.removeMember(req); + } + + @RequestMapping("/update") + public ResponseVO updateGroupMember(@RequestBody @Validated UpdateGroupMemberReq req, Integer appId, String identifier) { + req.setAppId(appId); + req.setOperater(identifier); + return groupMemberService.updateGroupMember(req); + } + + @RequestMapping("/speak") + public ResponseVO speak(@RequestBody @Validated SpeaMemberReq req, Integer appId, String identifier) { + req.setAppId(appId); + req.setOperater(identifier); + return groupMemberService.speak(req); + } + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/group/dao/ImGroupEntity.java b/im-server/im-service/src/main/java/com/lld/im/service/group/dao/ImGroupEntity.java new file mode 100644 index 0000000..a9c2b73 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/group/dao/ImGroupEntity.java @@ -0,0 +1,54 @@ +package com.lld.im.service.group.dao; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Data +@TableName("im_group") +public class ImGroupEntity { + + @TableId(value = "group_id") + private String groupId; + + private Integer appId; + + //群主id + private String ownerId; + + //群类型 1私有群(类似微信) 2公开群(类似qq) + private Integer groupType; + + private String groupName; + + private Integer mute;// 是否全员禁言,0 不禁言;1 全员禁言。 + +// 申请加群选项包括如下几种: +// 0 表示禁止任何人申请加入 +// 1 表示需要群主或管理员审批 +// 2 表示允许无需审批自由加入群组 + private Integer applyJoinType; + + private String introduction;//群简介 + + private String notification;//群公告 + + private String photo;//群头像 + + private Integer maxMemberCount;//群成员上限 + + private Integer status;//群状态 0正常 1解散 + + private Long sequence; + + private Long createTime; + + private Long updateTime; + + private String extra; +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/group/dao/ImGroupMemberEntity.java b/im-server/im-service/src/main/java/com/lld/im/service/group/dao/ImGroupMemberEntity.java new file mode 100644 index 0000000..8d0ae0b --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/group/dao/ImGroupMemberEntity.java @@ -0,0 +1,44 @@ +package com.lld.im.service.group.dao; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Data +@TableName("im_group_member") +public class ImGroupMemberEntity { + + @TableId(type = IdType.AUTO) + private Long groupMemberId; + + private Integer appId; + + private String groupId; + + //成员id + private String memberId; + + //群成员类型,0 普通成员, 1 管理员, 2 群主, 3 禁言,4 已经移除的成员 + private Integer role; + + private Long speakDate; + + //群昵称 + private String alias; + + //加入时间 + private Long joinTime; + + //离开时间 + private Long leaveTime; + + private String joinType; + + private String extra; +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/group/dao/ImGroupMessageHistoryEntity.java b/im-server/im-service/src/main/java/com/lld/im/service/group/dao/ImGroupMessageHistoryEntity.java new file mode 100644 index 0000000..cd95cf4 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/group/dao/ImGroupMessageHistoryEntity.java @@ -0,0 +1,32 @@ +package com.lld.im.service.group.dao; + +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @author: Chackylee + * @description: + **/ +@Data +@TableName("im_group_message_history") +public class ImGroupMessageHistoryEntity { + + private Integer appId; + + private String fromId; + + private String groupId; + + /** messageBodyId*/ + private Long messageKey; + /** 序列号*/ + private Long sequence; + + private String messageRandom; + + private Long messageTime; + + private Long createTime; + + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/group/dao/mapper/ImGroupMapper.java b/im-server/im-service/src/main/java/com/lld/im/service/group/dao/mapper/ImGroupMapper.java new file mode 100644 index 0000000..c361fcc --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/group/dao/mapper/ImGroupMapper.java @@ -0,0 +1,13 @@ +package com.lld.im.service.group.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lld.im.service.group.dao.ImGroupEntity; +import org.apache.ibatis.annotations.Select; +import org.springframework.stereotype.Repository; + +import java.util.Collection; + +@Repository +public interface ImGroupMapper extends BaseMapper { + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/group/dao/mapper/ImGroupMemberMapper.java b/im-server/im-service/src/main/java/com/lld/im/service/group/dao/mapper/ImGroupMemberMapper.java new file mode 100644 index 0000000..e7a9311 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/group/dao/mapper/ImGroupMemberMapper.java @@ -0,0 +1,65 @@ +package com.lld.im.service.group.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lld.im.service.group.dao.ImGroupMemberEntity; +import com.lld.im.service.group.model.req.GroupMemberDto; +import org.apache.ibatis.annotations.Result; +import org.apache.ibatis.annotations.Results; +import org.apache.ibatis.annotations.Select; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface ImGroupMemberMapper extends BaseMapper { + + @Select("select group_id from im_group_member where app_id = #{appId} AND member_id = #{memberId} ") + public List getJoinedGroupId(Integer appId, String memberId); + + + + @Results({ + @Result(column = "member_id", property = "memberId"), +// @Result(column = "speak_flag", property = "speakFlag"), + @Result(column = "speak_date", property = "speakDate"), + @Result(column = "role", property = "role"), + @Result(column = "alias", property = "alias"), + @Result(column = "join_time", property = "joinTime"), + @Result(column = "join_type", property = "joinType") + }) + @Select("select " + + " member_id, " + +// " speak_flag, " + + " speak_date, " + + " role, " + + " alias, " + + " join_time ," + + " join_type " + + " from im_group_member where app_id = #{appId} AND group_id = #{groupId} ") + public List getGroupMember(Integer appId, String groupId); + + @Select("select " + + " member_id " + + " from im_group_member where app_id = #{appId} AND group_id = #{groupId} and role != 3") + public List getGroupMemberId(Integer appId, String groupId); + + + @Results({ + @Result(column = "member_id", property = "memberId"), +// @Result(column = "speak_flag", property = "speakFlag"), + @Result(column = "role", property = "role") +// @Result(column = "alias", property = "alias"), +// @Result(column = "join_time", property = "joinTime"), +// @Result(column = "join_type", property = "joinType") + }) + @Select("select " + + " member_id, " + +// " speak_flag, " + + " role " + +// " alias, " + +// " join_time ," + +// " join_type " + + " from im_group_member where app_id = #{appId} AND group_id = #{groupId} and role in (1,2) ") + public List getGroupManager(String groupId, Integer appId); + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/group/dao/mapper/ImGroupMessageHistoryMapper.java b/im-server/im-service/src/main/java/com/lld/im/service/group/dao/mapper/ImGroupMessageHistoryMapper.java new file mode 100644 index 0000000..4962788 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/group/dao/mapper/ImGroupMessageHistoryMapper.java @@ -0,0 +1,11 @@ +package com.lld.im.service.group.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lld.im.service.group.dao.ImGroupMessageHistoryEntity; +import org.springframework.stereotype.Repository; + +@Repository +public interface ImGroupMessageHistoryMapper extends BaseMapper { + + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/AddGroupMemberReq.java b/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/AddGroupMemberReq.java new file mode 100644 index 0000000..6f8ce3b --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/AddGroupMemberReq.java @@ -0,0 +1,24 @@ +package com.lld.im.service.group.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import java.util.List; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Data +public class AddGroupMemberReq extends RequestBase { + + @NotBlank(message = "群id不能为空") + private String groupId; + + @NotEmpty(message = "群成员不能为空") + private List members; + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/CreateGroupReq.java b/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/CreateGroupReq.java new file mode 100644 index 0000000..ba4f30b --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/CreateGroupReq.java @@ -0,0 +1,41 @@ +package com.lld.im.service.group.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import java.util.List; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Data +public class CreateGroupReq extends RequestBase { + + private String groupId; + //群主id + private String ownerId; + + //群类型 1私有群(类似微信) 2公开群(类似qq) + private Integer groupType; + + private String groupName; + + private Integer mute;// 是否全员禁言,0 不禁言;1 全员禁言。 + + private Integer applyJoinType;//加入群权限,0 所有人可以加入;1 群成员可以拉人;2 群管理员或群组可以拉人。 + + private String introduction;//群简介 + + private String notification;//群公告 + + private String photo;//群头像 + + private Integer MaxMemberCount; + + private List member; + + private String extra; + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/DestroyGroupReq.java b/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/DestroyGroupReq.java new file mode 100644 index 0000000..15bffb8 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/DestroyGroupReq.java @@ -0,0 +1,18 @@ +package com.lld.im.service.group.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author: Chackylee + * @description: + **/ +@Data +public class DestroyGroupReq extends RequestBase { + + @NotNull(message = "群id不能为空") + private String groupId; + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/GetGroupReq.java b/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/GetGroupReq.java new file mode 100644 index 0000000..6c1c007 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/GetGroupReq.java @@ -0,0 +1,15 @@ +package com.lld.im.service.group.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +/** + * @author: Chackylee + * @description: + **/ +@Data +public class GetGroupReq extends RequestBase { + + private String groupId; + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/GetJoinedGroupReq.java b/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/GetJoinedGroupReq.java new file mode 100644 index 0000000..8038d60 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/GetJoinedGroupReq.java @@ -0,0 +1,29 @@ +package com.lld.im.service.group.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import java.util.List; + +/** + * @author: Chackylee + * @description: + **/ +@Data +public class GetJoinedGroupReq extends RequestBase { + + @NotBlank(message = "用户id不能为空") + private String memberId; + + //群类型 + private List groupType; + + //单次拉取的群组数量,如果不填代表所有群组 + private Integer limit; + + //第几页 + private Integer offset; + + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/GetRoleInGroupReq.java b/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/GetRoleInGroupReq.java new file mode 100644 index 0000000..bb3f242 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/GetRoleInGroupReq.java @@ -0,0 +1,18 @@ +package com.lld.im.service.group.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import java.util.List; + +/** + * @author: Chackylee + * @description: + **/ +@Data +public class GetRoleInGroupReq extends RequestBase { + + private String groupId; + + private List memberId; +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/GroupMemberDto.java b/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/GroupMemberDto.java new file mode 100644 index 0000000..f6fb2c4 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/GroupMemberDto.java @@ -0,0 +1,28 @@ +package com.lld.im.service.group.model.req; + +import lombok.Data; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ + +@Data +public class GroupMemberDto { + + private String memberId; + + private String alias; + + private Integer role;//群成员类型,0 普通成员, 1 管理员, 2 群主, 3 已经移除的成员,当修改群成员信息时,只能取值0/1,其他值由其他接口实现,暂不支持3 + +// private Integer speakFlag; + + private Long speakDate; + + private String joinType; + + private Long joinTime; + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/ImportGroupMemberReq.java b/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/ImportGroupMemberReq.java new file mode 100644 index 0000000..0a61e0f --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/ImportGroupMemberReq.java @@ -0,0 +1,22 @@ +package com.lld.im.service.group.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import java.util.List; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Data +public class ImportGroupMemberReq extends RequestBase { + + @NotBlank(message = "群id不能为空") + private String groupId; + + private List members; + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/ImportGroupReq.java b/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/ImportGroupReq.java new file mode 100644 index 0000000..422dabb --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/ImportGroupReq.java @@ -0,0 +1,42 @@ +package com.lld.im.service.group.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Data +public class ImportGroupReq extends RequestBase { + + private String groupId; + //群主id + private String ownerId; + + //群类型 1私有群(类似微信) 2公开群(类似qq) + private Integer groupType; + + @NotBlank(message = "群名称不能为空") + private String groupName; + + private Integer mute;// 是否全员禁言,0 不禁言;1 全员禁言。 + + private Integer applyJoinType;//加入群权限,0 所有人可以加入;1 群成员可以拉人;2 群管理员或群组可以拉人。 + + private String introduction;//群简介 + + private String notification;//群公告 + + private String photo;//群头像 + + private Integer MaxMemberCount; + + private Long createTime; + + private String extra; + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/MuteGroupReq.java b/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/MuteGroupReq.java new file mode 100644 index 0000000..680e432 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/MuteGroupReq.java @@ -0,0 +1,22 @@ +package com.lld.im.service.group.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + * @author: Chackylee + * @description: + **/ +@Data +public class MuteGroupReq extends RequestBase { + + @NotBlank(message = "groupId不能为空") + private String groupId; + + @NotNull(message = "mute不能为空") + private Integer mute; + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/RemoveGroupMemberReq.java b/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/RemoveGroupMemberReq.java new file mode 100644 index 0000000..32db73e --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/RemoveGroupMemberReq.java @@ -0,0 +1,20 @@ +package com.lld.im.service.group.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + +/** + * @author: Chackylee + * @description: + **/ +@Data +public class RemoveGroupMemberReq extends RequestBase { + + @NotBlank(message = "群id不能为空") + private String groupId; + + private String memberId; + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/SendGroupMessageReq.java b/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/SendGroupMessageReq.java new file mode 100644 index 0000000..f9e6781 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/SendGroupMessageReq.java @@ -0,0 +1,35 @@ +package com.lld.im.service.group.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Data +public class SendGroupMessageReq extends RequestBase { + + //客户端传的messageId + private String messageId; + + private String fromId; + + private String groupId; + + private int messageRandom; + + private long messageTime; + + private String messageBody; + /** + * 这个字段缺省或者为 0 表示需要计数,为 1 表示本条消息不需要计数,即右上角图标数字不增加 + */ + private int badgeMode; + + private Long messageLifeTime; + + private Integer appId; + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/SpeaMemberReq.java b/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/SpeaMemberReq.java new file mode 100644 index 0000000..64cbae7 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/SpeaMemberReq.java @@ -0,0 +1,25 @@ +package com.lld.im.service.group.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + * @author: Chackylee + * @description: + **/ +@Data +public class SpeaMemberReq extends RequestBase { + + @NotBlank(message = "群id不能为空") + private String groupId; + + @NotBlank(message = "memberId不能为空") + private String memberId; + + //禁言时间,单位毫秒 + @NotNull(message = "禁言时间不能为空") + private Long speakDate; +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/TransferGroupReq.java b/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/TransferGroupReq.java new file mode 100644 index 0000000..f53567f --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/TransferGroupReq.java @@ -0,0 +1,17 @@ +package com.lld.im.service.group.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotNull; + + +@Data +public class TransferGroupReq extends RequestBase { + + @NotNull(message = "群id不能为空") + private String groupId; + + private String ownerId; + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/UpdateGroupMemberReq.java b/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/UpdateGroupMemberReq.java new file mode 100644 index 0000000..e44d4ba --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/UpdateGroupMemberReq.java @@ -0,0 +1,27 @@ +package com.lld.im.service.group.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + +/** + * @author: Chackylee + * @description: + **/ +@Data +public class UpdateGroupMemberReq extends RequestBase { + + @NotBlank(message = "群id不能为空") + private String groupId; + + @NotBlank(message = "memberId不能为空") + private String memberId; + + private String alias; + + private Integer role; + + private String extra; + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/UpdateGroupReq.java b/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/UpdateGroupReq.java new file mode 100644 index 0000000..d70a9a7 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/group/model/req/UpdateGroupReq.java @@ -0,0 +1,34 @@ +package com.lld.im.service.group.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + +/** + * @author: Chackylee + * @description: + **/ +@Data +public class UpdateGroupReq extends RequestBase { + + @NotBlank(message = "群id不能为空") + private String groupId; + + private String groupName; + + private Integer mute;// 是否全员禁言,0 不禁言;1 全员禁言。 + + private Integer applyJoinType;//加入群权限,0 所有人可以加入;1 群成员可以拉人;2 群管理员或群组可以拉人。 + + private String introduction;//群简介 + + private String notification;//群公告 + + private String photo;//群头像 + + private Integer maxMemberCount;//群成员上限 + + private String extra; + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/group/model/resp/AddMemberResp.java b/im-server/im-service/src/main/java/com/lld/im/service/group/model/resp/AddMemberResp.java new file mode 100644 index 0000000..8614833 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/group/model/resp/AddMemberResp.java @@ -0,0 +1,19 @@ +package com.lld.im.service.group.model.resp; + +import lombok.Data; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Data +public class AddMemberResp { + + private String memberId; + + // 加人结果:0 为成功;1 为失败;2 为已经是群成员 + private Integer result; + + private String resultMessage; +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/group/model/resp/GetGroupResp.java b/im-server/im-service/src/main/java/com/lld/im/service/group/model/resp/GetGroupResp.java new file mode 100644 index 0000000..3cd10bb --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/group/model/resp/GetGroupResp.java @@ -0,0 +1,48 @@ +package com.lld.im.service.group.model.resp; + +import com.lld.im.service.group.model.req.GroupMemberDto; +import lombok.Data; + +import java.util.List; + +/** + * @author: Chackylee + * @description: + **/ +@Data +public class GetGroupResp { + + private String groupId; + + private Integer appId; + + //群主id + private String ownerId; + + //群类型 1私有群(类似微信) 2公开群(类似qq) + private Integer groupType; + + private String groupName; + + private Integer mute;// 是否全员禁言,0 不禁言;1 全员禁言。 + + // 申请加群选项包括如下几种: +// 0 表示禁止任何人申请加入 +// 1 表示需要群主或管理员审批 +// 2 表示允许无需审批自由加入群组 + private Integer applyJoinType; + + private Integer privateChat; //是否禁止私聊,0 允许群成员发起私聊;1 不允许群成员发起私聊。 + + private String introduction;//群简介 + + private String notification;//群公告 + + private String photo;//群头像 + + private Integer maxMemberCount;//群成员上限 + + private Integer status;//群状态 0正常 1解散 + + private List memberList; +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/group/model/resp/GetJoinedGroupResp.java b/im-server/im-service/src/main/java/com/lld/im/service/group/model/resp/GetJoinedGroupResp.java new file mode 100644 index 0000000..a156a49 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/group/model/resp/GetJoinedGroupResp.java @@ -0,0 +1,19 @@ +package com.lld.im.service.group.model.resp; + +import com.lld.im.service.group.dao.ImGroupEntity; +import lombok.Data; + +import java.util.List; + +/** + * @author: Chackylee + * @description: + **/ +@Data +public class GetJoinedGroupResp { + + private Integer totalCount; + + private List groupList; + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/group/model/resp/GetRoleInGroupResp.java b/im-server/im-service/src/main/java/com/lld/im/service/group/model/resp/GetRoleInGroupResp.java new file mode 100644 index 0000000..e4cf87d --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/group/model/resp/GetRoleInGroupResp.java @@ -0,0 +1,20 @@ +package com.lld.im.service.group.model.resp; + +import lombok.Data; + +/** + * @author: Chackylee + * @description: + **/ +@Data +public class GetRoleInGroupResp { + + private Long groupMemberId; + + private String memberId; + + private Integer role; + + private Long speakDate; + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/group/service/ImGroupMemberService.java b/im-server/im-service/src/main/java/com/lld/im/service/group/service/ImGroupMemberService.java new file mode 100644 index 0000000..6154733 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/group/service/ImGroupMemberService.java @@ -0,0 +1,43 @@ +package com.lld.im.service.group.service; + +import com.lld.im.common.ResponseVO; +import com.lld.im.service.group.model.req.*; +import com.lld.im.service.group.model.resp.GetRoleInGroupResp; + +import java.util.Collection; +import java.util.List; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +public interface ImGroupMemberService { + + public ResponseVO importGroupMember(ImportGroupMemberReq req); + + public ResponseVO addMember(AddGroupMemberReq req); + + public ResponseVO removeMember(RemoveGroupMemberReq req); + + public ResponseVO addGroupMember(String groupId, Integer appId, GroupMemberDto dto); + + public ResponseVO removeGroupMember(String groupId, Integer appId, String memberId); + + public ResponseVO getRoleInGroupOne(String groupId, String memberId, Integer appId); + + public ResponseVO> getMemberJoinedGroup(GetJoinedGroupReq req); + + public ResponseVO> getGroupMember(String groupId, Integer appId); + + public List getGroupMemberId(String groupId, Integer appId); + + public List getGroupManager(String groupId, Integer appId); + + public ResponseVO updateGroupMember(UpdateGroupMemberReq req); + + public ResponseVO transferGroupMember(String owner, String groupId, Integer appId); + + public ResponseVO speak(SpeaMemberReq req); + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/group/service/ImGroupService.java b/im-server/im-service/src/main/java/com/lld/im/service/group/service/ImGroupService.java new file mode 100644 index 0000000..eeb140c --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/group/service/ImGroupService.java @@ -0,0 +1,32 @@ +package com.lld.im.service.group.service; + +import com.lld.im.common.ResponseVO; +import com.lld.im.service.group.dao.ImGroupEntity; +import com.lld.im.service.group.model.req.*; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +public interface ImGroupService { + + public ResponseVO importGroup(ImportGroupReq req); + + public ResponseVO createGroup(CreateGroupReq req); + + public ResponseVO updateBaseGroupInfo(UpdateGroupReq req); + + public ResponseVO getJoinedGroup(GetJoinedGroupReq req); + + public ResponseVO destroyGroup(DestroyGroupReq req); + + public ResponseVO transferGroup(TransferGroupReq req); + + public ResponseVO getGroup(String groupId, Integer appId); + + public ResponseVO getGroup(GetGroupReq req); + + public ResponseVO muteGroup(MuteGroupReq req); + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/group/service/impl/ImGroupMemberServiceImpl.java b/im-server/im-service/src/main/java/com/lld/im/service/group/service/impl/ImGroupMemberServiceImpl.java new file mode 100644 index 0000000..df91cd8 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/group/service/impl/ImGroupMemberServiceImpl.java @@ -0,0 +1,537 @@ +package com.lld.im.service.group.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.lld.im.common.ResponseVO; +import com.lld.im.common.enums.GroupErrorCode; +import com.lld.im.common.enums.GroupMemberRoleEnum; +import com.lld.im.common.enums.GroupStatusEnum; +import com.lld.im.common.enums.GroupTypeEnum; +import com.lld.im.common.exception.ApplicationException; +import com.lld.im.service.group.dao.ImGroupEntity; +import com.lld.im.service.group.dao.ImGroupMemberEntity; +import com.lld.im.service.group.dao.mapper.ImGroupMemberMapper; +import com.lld.im.service.group.model.req.*; +import com.lld.im.service.group.model.resp.AddMemberResp; +import com.lld.im.service.group.model.resp.GetRoleInGroupResp; +import com.lld.im.service.group.service.ImGroupMemberService; +import com.lld.im.service.group.service.ImGroupService; +import com.lld.im.service.user.dao.ImUserDataEntity; +import com.lld.im.service.user.service.ImUserService; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Service +@Slf4j +public class ImGroupMemberServiceImpl implements ImGroupMemberService { + + @Autowired + ImGroupMemberMapper imGroupMemberMapper; + + @Autowired + ImGroupService groupService; + + @Autowired + ImGroupMemberService groupMemberService; + + @Autowired + ImUserService imUserService; + + @Override + public ResponseVO importGroupMember(ImportGroupMemberReq req) { + + List resp = new ArrayList<>(); + + ResponseVO groupResp = groupService.getGroup(req.getGroupId(), req.getAppId()); + if (!groupResp.isOk()) { + return groupResp; + } + + for (GroupMemberDto memberId : + req.getMembers()) { + ResponseVO responseVO = null; + try { + responseVO = groupMemberService.addGroupMember(req.getGroupId(), req.getAppId(), memberId); + } catch (Exception e) { + e.printStackTrace(); + responseVO = ResponseVO.errorResponse(); + } + AddMemberResp addMemberResp = new AddMemberResp(); + addMemberResp.setMemberId(memberId.getMemberId()); + if (responseVO.isOk()) { + addMemberResp.setResult(0); + } else if (responseVO.getCode() == GroupErrorCode.USER_IS_JOINED_GROUP.getCode()) { + addMemberResp.setResult(2); + } else { + addMemberResp.setResult(1); + } + resp.add(addMemberResp); + } + + return ResponseVO.successResponse(resp); + } + + /** + * @param + * @return com.lld.im.common.ResponseVO + * @description: 添加群成员,内部调用 + * @author lld + */ + @Override + @Transactional + public ResponseVO addGroupMember(String groupId, Integer appId, GroupMemberDto dto) { + + ResponseVO singleUserInfo = imUserService.getSingleUserInfo(dto.getMemberId(), appId); + if (!singleUserInfo.isOk()) { + return singleUserInfo; + } + + if (dto.getRole() != null && GroupMemberRoleEnum.OWNER.getCode() == dto.getRole()) { + QueryWrapper queryOwner = new QueryWrapper<>(); + queryOwner.eq("group_id", groupId); + queryOwner.eq("app_id", appId); + queryOwner.eq("role", GroupMemberRoleEnum.OWNER.getCode()); + Integer ownerNum = imGroupMemberMapper.selectCount(queryOwner); + if (ownerNum > 0) { + return ResponseVO.errorResponse(GroupErrorCode.GROUP_IS_HAVE_OWNER); + } + } + + QueryWrapper query = new QueryWrapper<>(); + query.eq("group_id", groupId); + query.eq("app_id", appId); + query.eq("member_id", dto.getMemberId()); + ImGroupMemberEntity memberDto = imGroupMemberMapper.selectOne(query); + + long now = System.currentTimeMillis(); + if (memberDto == null) { + //初次加群 + memberDto = new ImGroupMemberEntity(); + BeanUtils.copyProperties(dto, memberDto); + memberDto.setGroupId(groupId); + memberDto.setAppId(appId); + memberDto.setJoinTime(now); + int insert = imGroupMemberMapper.insert(memberDto); + if (insert == 1) { + return ResponseVO.successResponse(); + } + return ResponseVO.errorResponse(GroupErrorCode.USER_JOIN_GROUP_ERROR); + } else if (GroupMemberRoleEnum.LEAVE.getCode() == memberDto.getRole()) { + //重新进群 + memberDto = new ImGroupMemberEntity(); + BeanUtils.copyProperties(dto, memberDto); + memberDto.setJoinTime(now); + int update = imGroupMemberMapper.update(memberDto, query); + if (update == 1) { + return ResponseVO.successResponse(); + } + return ResponseVO.errorResponse(GroupErrorCode.USER_JOIN_GROUP_ERROR); + } + + return ResponseVO.errorResponse(GroupErrorCode.USER_IS_JOINED_GROUP); + + } + + /** + * @param + * @return com.lld.im.common.ResponseVO + * @description: 删除群成员,内部调用 + * @author lld + */ + @Override + public ResponseVO removeGroupMember(String groupId, Integer appId, String memberId) { + + ResponseVO singleUserInfo = imUserService.getSingleUserInfo(memberId, appId); + if (!singleUserInfo.isOk()) { + return singleUserInfo; + } + + ResponseVO roleInGroupOne = getRoleInGroupOne(groupId, memberId, appId); + if (!roleInGroupOne.isOk()) { + return roleInGroupOne; + } + + GetRoleInGroupResp data = roleInGroupOne.getData(); + ImGroupMemberEntity imGroupMemberEntity = new ImGroupMemberEntity(); + imGroupMemberEntity.setRole(GroupMemberRoleEnum.LEAVE.getCode()); + imGroupMemberEntity.setLeaveTime(System.currentTimeMillis()); + imGroupMemberEntity.setGroupMemberId(data.getGroupMemberId()); + imGroupMemberMapper.updateById(imGroupMemberEntity); + return ResponseVO.successResponse(); + } + + /** + * @param [groupId, memberId, appId] + * @return com.lld.im.common.ResponseVO + * @description 查询用户在群内的角色 + * @author chackylee + */ + @Override + public ResponseVO getRoleInGroupOne(String groupId, String memberId, Integer appId) { + + GetRoleInGroupResp resp = new GetRoleInGroupResp(); + + QueryWrapper queryOwner = new QueryWrapper<>(); + queryOwner.eq("group_id", groupId); + queryOwner.eq("app_id", appId); + queryOwner.eq("member_id", memberId); + + ImGroupMemberEntity imGroupMemberEntity = imGroupMemberMapper.selectOne(queryOwner); + if (imGroupMemberEntity == null || imGroupMemberEntity.getRole() == GroupMemberRoleEnum.LEAVE.getCode()) { + return ResponseVO.errorResponse(GroupErrorCode.MEMBER_IS_NOT_JOINED_GROUP); + } + + resp.setSpeakDate(imGroupMemberEntity.getSpeakDate()); + resp.setGroupMemberId(imGroupMemberEntity.getGroupMemberId()); + resp.setMemberId(imGroupMemberEntity.getMemberId()); + resp.setRole(imGroupMemberEntity.getRole()); + return ResponseVO.successResponse(resp); + } + + @Override + public ResponseVO> getMemberJoinedGroup(GetJoinedGroupReq req) { + + if (req.getLimit() != null) { + Page objectPage = new Page<>(req.getOffset(), req.getLimit()); + QueryWrapper query = new QueryWrapper<>(); + query.eq("app_id", req.getAppId()); + query.eq("member_id", req.getMemberId()); + IPage imGroupMemberEntityPage = imGroupMemberMapper.selectPage(objectPage, query); + + Set groupId = new HashSet<>(); + List records = imGroupMemberEntityPage.getRecords(); + records.forEach(e -> { + groupId.add(e.getGroupId()); + }); + + return ResponseVO.successResponse(groupId); + } else { + return ResponseVO.successResponse(imGroupMemberMapper.getJoinedGroupId(req.getAppId(), req.getMemberId())); + } + } + + /** + * @param + * @return com.lld.im.common.ResponseVO + * @description: 添加群成员,拉人入群的逻辑,直接进入群聊。如果是后台管理员,则直接拉入群, + * 否则只有私有群可以调用本接口,并且群成员也可以拉人入群.只有私有群可以调用本接口 + * @author lld + */ + @Override + public ResponseVO addMember(AddGroupMemberReq req) { + + List resp = new ArrayList<>(); + + boolean isAdmin = false; + ResponseVO groupResp = groupService.getGroup(req.getGroupId(), req.getAppId()); + if (!groupResp.isOk()) { + return groupResp; + } + + List memberDtos = req.getMembers(); + + ImGroupEntity group = groupResp.getData(); + + /** + * 私有群(private) 类似普通微信群,创建后仅支持已在群内的好友邀请加群,且无需被邀请方同意或群主审批 + * 公开群(Public) 类似 QQ 群,创建后群主可以指定群管理员,需要群主或管理员审批通过才能入群 + * 群类型 1私有群(类似微信) 2公开群(类似qq) + */ + if (!isAdmin && GroupTypeEnum.PUBLIC.getCode() == group.getGroupType()) { + throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_APPMANAGER_ROLE); + } + + List successId = new ArrayList<>(); + for (GroupMemberDto memberId : + memberDtos) { + ResponseVO responseVO = null; + try { + responseVO = groupMemberService.addGroupMember(req.getGroupId(), req.getAppId(), memberId); + } catch (Exception e) { + e.printStackTrace(); + responseVO = ResponseVO.errorResponse(); + } + AddMemberResp addMemberResp = new AddMemberResp(); + addMemberResp.setMemberId(memberId.getMemberId()); + if (responseVO.isOk()) { + successId.add(memberId.getMemberId()); + addMemberResp.setResult(0); + } else if (responseVO.getCode() == GroupErrorCode.USER_IS_JOINED_GROUP.getCode()) { + addMemberResp.setResult(2); + addMemberResp.setResultMessage(responseVO.getMsg()); + } else { + addMemberResp.setResult(1); + addMemberResp.setResultMessage(responseVO.getMsg()); + } + resp.add(addMemberResp); + } + + return ResponseVO.successResponse(resp); + } + + @Override + public ResponseVO removeMember(RemoveGroupMemberReq req) { + + boolean isAdmin = false; + ResponseVO groupResp = groupService.getGroup(req.getGroupId(), req.getAppId()); + if (!groupResp.isOk()) { + return groupResp; + } + + ImGroupEntity group = groupResp.getData(); + + if (!isAdmin) { + if (GroupTypeEnum.PUBLIC.getCode() == group.getGroupType()) { + + //获取操作人的权限 是管理员or群主or群成员 + ResponseVO role = getRoleInGroupOne(req.getGroupId(), req.getOperater(), req.getAppId()); + if (!role.isOk()) { + return role; + } + + GetRoleInGroupResp data = role.getData(); + Integer roleInfo = data.getRole(); + + boolean isOwner = roleInfo == GroupMemberRoleEnum.OWNER.getCode(); + boolean isManager = roleInfo == GroupMemberRoleEnum.MAMAGER.getCode(); + + if (!isOwner && !isManager) { + throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_MANAGER_ROLE); + } + + //私有群必须是群主才能踢人 + if (!isOwner && GroupTypeEnum.PRIVATE.getCode() == group.getGroupType()) { + throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_OWNER_ROLE); + } + + //公开群管理员和群主可踢人,但管理员只能踢普通群成员 + if (GroupTypeEnum.PUBLIC.getCode() == group.getGroupType()) { +// throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_MANAGER_ROLE); + //获取被踢人的权限 + ResponseVO roleInGroupOne = this.getRoleInGroupOne(req.getGroupId(), req.getMemberId(), req.getAppId()); + if (!roleInGroupOne.isOk()) { + return roleInGroupOne; + } + GetRoleInGroupResp memberRole = roleInGroupOne.getData(); + if (memberRole.getRole() == GroupMemberRoleEnum.OWNER.getCode()) { + throw new ApplicationException(GroupErrorCode.GROUP_OWNER_IS_NOT_REMOVE); + } + //是管理员并且被踢人不是群成员,无法操作 + if (isManager && memberRole.getRole() != GroupMemberRoleEnum.ORDINARY.getCode()) { + throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_OWNER_ROLE); + } + } + } + } + ResponseVO responseVO = groupMemberService.removeGroupMember(req.getGroupId(), req.getAppId(), req.getMemberId()); + return responseVO; + } + + @Override + public ResponseVO> getGroupMember(String groupId, Integer appId) { + List groupMember = imGroupMemberMapper.getGroupMember(appId, groupId); + return ResponseVO.successResponse(groupMember); + } + + @Override + public List getGroupMemberId(String groupId, Integer appId) { + return imGroupMemberMapper.getGroupMemberId(appId, groupId); + } + + @Override + public List getGroupManager(String groupId, Integer appId) { + return imGroupMemberMapper.getGroupManager(groupId, appId); + } + + @Override + public ResponseVO updateGroupMember(UpdateGroupMemberReq req) { + + boolean isadmin = false; + + ResponseVO group = groupService.getGroup(req.getGroupId(), req.getAppId()); + if (!group.isOk()) { + return group; + } + + ImGroupEntity groupData = group.getData(); + if (groupData.getStatus() == GroupStatusEnum.DESTROY.getCode()) { + throw new ApplicationException(GroupErrorCode.GROUP_IS_DESTROY); + } + + //是否是自己修改自己的资料 + boolean isMeOperate = req.getOperater().equals(req.getMemberId()); + + if (!isadmin) { + //昵称只能自己修改 权限只能群主或管理员修改 + if (StringUtils.isBlank(req.getAlias()) && !isMeOperate) { + return ResponseVO.errorResponse(GroupErrorCode.THIS_OPERATE_NEED_ONESELF); + } + + //如果要修改权限相关的则走下面的逻辑 + if (req.getRole() != null) { + //私有群不能设置管理员 + if (groupData.getGroupType() == GroupTypeEnum.PRIVATE.getCode() && + req.getRole() != null && (req.getRole() == GroupMemberRoleEnum.MAMAGER.getCode() || + req.getRole() == GroupMemberRoleEnum.OWNER.getCode())) { + return ResponseVO.errorResponse(GroupErrorCode.THIS_OPERATE_NEED_APPMANAGER_ROLE); + } + + //获取被操作人的是否在群内 + ResponseVO roleInGroupOne = this.getRoleInGroupOne(req.getGroupId(), req.getMemberId(), req.getAppId()); + if (!roleInGroupOne.isOk()) { + return roleInGroupOne; + } + + //获取操作人权限 + ResponseVO operateRoleInGroupOne = this.getRoleInGroupOne(req.getGroupId(), req.getOperater(), req.getAppId()); + if (!operateRoleInGroupOne.isOk()) { + return operateRoleInGroupOne; + } + + GetRoleInGroupResp data = operateRoleInGroupOne.getData(); + Integer roleInfo = data.getRole(); + boolean isOwner = roleInfo == GroupMemberRoleEnum.OWNER.getCode(); + boolean isManager = roleInfo == GroupMemberRoleEnum.MAMAGER.getCode(); + + //不是管理员不能修改权限 + if (req.getRole() != null && !isOwner && !isManager) { + return ResponseVO.errorResponse(GroupErrorCode.THIS_OPERATE_NEED_MANAGER_ROLE); + } + + //管理员只有群主能够设置 + if (req.getRole() != null && req.getRole() == GroupMemberRoleEnum.MAMAGER.getCode() && !isOwner) { + return ResponseVO.errorResponse(GroupErrorCode.THIS_OPERATE_NEED_OWNER_ROLE); + } + + } + } + + ImGroupMemberEntity update = new ImGroupMemberEntity(); + + if (StringUtils.isNotBlank(req.getAlias())) { + update.setAlias(req.getAlias()); + } + + //不能直接修改为群主 + if(req.getRole() != null && req.getRole() != GroupMemberRoleEnum.OWNER.getCode()){ + update.setRole(req.getRole()); + } + + UpdateWrapper objectUpdateWrapper = new UpdateWrapper<>(); + objectUpdateWrapper.eq("app_id", req.getAppId()); + objectUpdateWrapper.eq("member_id", req.getMemberId()); + objectUpdateWrapper.eq("group_id", req.getGroupId()); + imGroupMemberMapper.update(update, objectUpdateWrapper); + + return ResponseVO.successResponse(); + } + + @Override + @Transactional + public ResponseVO transferGroupMember(String owner, String groupId, Integer appId) { + + //更新旧群主 + ImGroupMemberEntity imGroupMemberEntity = new ImGroupMemberEntity(); + imGroupMemberEntity.setRole(GroupMemberRoleEnum.ORDINARY.getCode()); + UpdateWrapper updateWrapper = new UpdateWrapper<>(); + updateWrapper.eq("app_id", appId); + updateWrapper.eq("group_id", groupId); + updateWrapper.eq("role", GroupMemberRoleEnum.OWNER.getCode()); + imGroupMemberMapper.update(imGroupMemberEntity, updateWrapper); + + //更新新群主 + ImGroupMemberEntity newOwner = new ImGroupMemberEntity(); + newOwner.setRole(GroupMemberRoleEnum.OWNER.getCode()); + UpdateWrapper ownerWrapper = new UpdateWrapper<>(); + ownerWrapper.eq("app_id", appId); + ownerWrapper.eq("group_id", groupId); + ownerWrapper.eq("member_id", owner); + imGroupMemberMapper.update(newOwner, ownerWrapper); + + return ResponseVO.successResponse(); + } + + @Override + public ResponseVO speak(SpeaMemberReq req) { + + ResponseVO groupResp = groupService.getGroup(req.getGroupId(), req.getAppId()); + if (!groupResp.isOk()) { + return groupResp; + } + + boolean isadmin = false; + boolean isOwner = false; + boolean isManager = false; + GetRoleInGroupResp memberRole = null; + + if (!isadmin) { + + //获取操作人的权限 是管理员or群主or群成员 + ResponseVO role = getRoleInGroupOne(req.getGroupId(), req.getOperater(), req.getAppId()); + if (!role.isOk()) { + return role; + } + + GetRoleInGroupResp data = role.getData(); + Integer roleInfo = data.getRole(); + + isOwner = roleInfo == GroupMemberRoleEnum.OWNER.getCode(); + isManager = roleInfo == GroupMemberRoleEnum.MAMAGER.getCode(); + + if (!isOwner && !isManager) { + throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_MANAGER_ROLE); + } + + //获取被操作的权限 + ResponseVO roleInGroupOne = this.getRoleInGroupOne(req.getGroupId(), req.getMemberId(), req.getAppId()); + if (!roleInGroupOne.isOk()) { + return roleInGroupOne; + } + memberRole = roleInGroupOne.getData(); + //被操作人是群主只能app管理员操作 + if (memberRole.getRole() == GroupMemberRoleEnum.OWNER.getCode()) { + throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_APPMANAGER_ROLE); + } + + //是管理员并且被操作人不是群成员,无法操作 + if (isManager && memberRole.getRole() != GroupMemberRoleEnum.ORDINARY.getCode()) { + throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_OWNER_ROLE); + } + } + + ImGroupMemberEntity imGroupMemberEntity = new ImGroupMemberEntity(); + if (memberRole == null) { + //获取被操作的权限 + ResponseVO roleInGroupOne = this.getRoleInGroupOne(req.getGroupId(), req.getMemberId(), req.getAppId()); + if (!roleInGroupOne.isOk()) { + return roleInGroupOne; + } + memberRole = roleInGroupOne.getData(); + } + + imGroupMemberEntity.setGroupMemberId(memberRole.getGroupMemberId()); + if (req.getSpeakDate() > 0) { + imGroupMemberEntity.setSpeakDate(System.currentTimeMillis() + req.getSpeakDate()); + } else { + imGroupMemberEntity.setSpeakDate(req.getSpeakDate()); + } + + int i = imGroupMemberMapper.updateById(imGroupMemberEntity); + return ResponseVO.successResponse(); + } + + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/group/service/impl/ImGroupServiceImpl.java b/im-server/im-service/src/main/java/com/lld/im/service/group/service/impl/ImGroupServiceImpl.java new file mode 100644 index 0000000..d8760e9 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/group/service/impl/ImGroupServiceImpl.java @@ -0,0 +1,393 @@ +package com.lld.im.service.group.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import com.lld.im.common.ResponseVO; +import com.lld.im.common.enums.GroupErrorCode; +import com.lld.im.common.enums.GroupMemberRoleEnum; +import com.lld.im.common.enums.GroupStatusEnum; +import com.lld.im.common.enums.GroupTypeEnum; +import com.lld.im.common.exception.ApplicationException; +import com.lld.im.common.model.ClientInfo; +import com.lld.im.service.group.dao.ImGroupEntity; +import com.lld.im.service.group.dao.mapper.ImGroupMapper; +import com.lld.im.service.group.model.req.*; +import com.lld.im.service.group.model.resp.GetGroupResp; +import com.lld.im.service.group.model.resp.GetJoinedGroupResp; +import com.lld.im.service.group.model.resp.GetRoleInGroupResp; +import com.lld.im.service.group.service.ImGroupMemberService; +import com.lld.im.service.group.service.ImGroupService; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.UUID; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Service +public class ImGroupServiceImpl implements ImGroupService { + + @Autowired + ImGroupMapper imGroupDataMapper; + + @Autowired + ImGroupMemberService groupMemberService; + + + @Override + public ResponseVO importGroup(ImportGroupReq req) { + + //1.判断群id是否存在 + QueryWrapper query = new QueryWrapper<>(); + + if (StringUtils.isEmpty(req.getGroupId())) { + req.setGroupId(UUID.randomUUID().toString().replace("-", "")); + } else { + query.eq("group_id", req.getGroupId()); + query.eq("app_id", req.getAppId()); + Integer integer = imGroupDataMapper.selectCount(query); + if (integer > 0) { + throw new ApplicationException(GroupErrorCode.GROUP_IS_EXIST); + } + } + + ImGroupEntity imGroupEntity = new ImGroupEntity(); + + if (req.getGroupType() == GroupTypeEnum.PUBLIC.getCode() && StringUtils.isBlank(req.getOwnerId())) { + throw new ApplicationException(GroupErrorCode.PUBLIC_GROUP_MUST_HAVE_OWNER); + } + + if (req.getCreateTime() == null) { + imGroupEntity.setCreateTime(System.currentTimeMillis()); + } + imGroupEntity.setStatus(GroupStatusEnum.NORMAL.getCode()); + BeanUtils.copyProperties(req, imGroupEntity); + int insert = imGroupDataMapper.insert(imGroupEntity); + + if (insert != 1) { + throw new ApplicationException(GroupErrorCode.IMPORT_GROUP_ERROR); + } + + return ResponseVO.successResponse(); + } + + @Override + @Transactional + public ResponseVO createGroup(CreateGroupReq req) { + + boolean isAdmin = false; + + if (!isAdmin) { + req.setOwnerId(req.getOperater()); + } + + //1.判断群id是否存在 + QueryWrapper query = new QueryWrapper<>(); + + if (StringUtils.isEmpty(req.getGroupId())) { + req.setGroupId(UUID.randomUUID().toString().replace("-", "")); + } else { + query.eq("group_id", req.getGroupId()); + query.eq("app_id", req.getAppId()); + Integer integer = imGroupDataMapper.selectCount(query); + if (integer > 0) { + throw new ApplicationException(GroupErrorCode.GROUP_IS_EXIST); + } + } + + if (req.getGroupType() == GroupTypeEnum.PUBLIC.getCode() && StringUtils.isBlank(req.getOwnerId())) { + throw new ApplicationException(GroupErrorCode.PUBLIC_GROUP_MUST_HAVE_OWNER); + } + + ImGroupEntity imGroupEntity = new ImGroupEntity(); + imGroupEntity.setCreateTime(System.currentTimeMillis()); + imGroupEntity.setStatus(GroupStatusEnum.NORMAL.getCode()); + BeanUtils.copyProperties(req, imGroupEntity); + int insert = imGroupDataMapper.insert(imGroupEntity); + + GroupMemberDto groupMemberDto = new GroupMemberDto(); + groupMemberDto.setMemberId(req.getOwnerId()); + groupMemberDto.setRole(GroupMemberRoleEnum.OWNER.getCode()); + groupMemberDto.setJoinTime(System.currentTimeMillis()); + groupMemberService.addGroupMember(req.getGroupId(), req.getAppId(), groupMemberDto); + + //插入群成员 + for (GroupMemberDto dto : req.getMember()) { + groupMemberService.addGroupMember(req.getGroupId(), req.getAppId(), dto); + } + + return ResponseVO.successResponse(); + } + + /** + * @param [req] + * @return com.lld.im.common.ResponseVO + * @description 修改群基础信息,如果是后台管理员调用,则不检查权限,如果不是则检查权限,如果是私有群(微信群)任何人都可以修改资料,公开群只有管理员可以修改 + * 如果是群主或者管理员可以修改其他信息。 + * @author chackylee + */ + @Override + @Transactional + public ResponseVO updateBaseGroupInfo(UpdateGroupReq req) { + + //1.判断群id是否存在 + QueryWrapper query = new QueryWrapper<>(); + query.eq("group_id", req.getGroupId()); + query.eq("app_id", req.getAppId()); + ImGroupEntity imGroupEntity = imGroupDataMapper.selectOne(query); + if (imGroupEntity == null) { + throw new ApplicationException(GroupErrorCode.GROUP_IS_EXIST); + } + + if(imGroupEntity.getStatus() == GroupStatusEnum.DESTROY.getCode()){ + throw new ApplicationException(GroupErrorCode.GROUP_IS_DESTROY); + } + + boolean isAdmin = false; + + if (!isAdmin) { + //不是后台调用需要检查权限 + ResponseVO role = groupMemberService.getRoleInGroupOne(req.getGroupId(), req.getOperater(), req.getAppId()); + + if (!role.isOk()) { + return role; + } + + GetRoleInGroupResp data = role.getData(); + Integer roleInfo = data.getRole(); + + boolean isManager = roleInfo == GroupMemberRoleEnum.MAMAGER.getCode() || roleInfo == GroupMemberRoleEnum.OWNER.getCode(); + + //公开群只能群主修改资料 + if (!isManager && GroupTypeEnum.PUBLIC.getCode() == imGroupEntity.getGroupType()) { + throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_MANAGER_ROLE); + } + + } + + ImGroupEntity update = new ImGroupEntity(); + BeanUtils.copyProperties(req, update); + update.setUpdateTime(System.currentTimeMillis()); + int row = imGroupDataMapper.update(update, query); + if (row != 1) { + throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_MANAGER_ROLE); + } + + return ResponseVO.successResponse(); + } + + /** + * @param [req] + * @return com.lld.im.common.ResponseVO + * @description 获取用户加入的群组 + * @author chackylee + */ + @Override + public ResponseVO getJoinedGroup(GetJoinedGroupReq req) { + + ResponseVO> memberJoinedGroup = groupMemberService.getMemberJoinedGroup(req); + if (memberJoinedGroup.isOk()) { + + GetJoinedGroupResp resp = new GetJoinedGroupResp(); + + if (CollectionUtils.isEmpty(memberJoinedGroup.getData())) { + resp.setTotalCount(0); + resp.setGroupList(new ArrayList<>()); + return ResponseVO.successResponse(resp); + } + + QueryWrapper query = new QueryWrapper<>(); + query.eq("app_id", req.getAppId()); + query.in("group_id", memberJoinedGroup.getData()); + + if (CollectionUtils.isNotEmpty(req.getGroupType())) { + query.in("group_type", req.getGroupType()); + } + + List groupList = imGroupDataMapper.selectList(query); + resp.setGroupList(groupList); + if (req.getLimit() == null) { + resp.setTotalCount(groupList.size()); + } else { + resp.setTotalCount(imGroupDataMapper.selectCount(query)); + } + return ResponseVO.successResponse(resp); + } else { + return memberJoinedGroup; + } + } + + + /** + * @param [req] + * @return com.lld.im.common.ResponseVO + * @description 解散群组,只支持后台管理员和群主解散 + * @author chackylee + */ + @Override + @Transactional + public ResponseVO destroyGroup(DestroyGroupReq req) { + + boolean isAdmin = false; + + QueryWrapper objectQueryWrapper = new QueryWrapper<>(); + objectQueryWrapper.eq("group_id", req.getGroupId()); + objectQueryWrapper.eq("app_id", req.getAppId()); + ImGroupEntity imGroupEntity = imGroupDataMapper.selectOne(objectQueryWrapper); + if (imGroupEntity == null) { + throw new ApplicationException(GroupErrorCode.PRIVATE_GROUP_CAN_NOT_DESTORY); + } + + if(imGroupEntity.getStatus() == GroupStatusEnum.DESTROY.getCode()){ + throw new ApplicationException(GroupErrorCode.GROUP_IS_DESTROY); + } + + if (!isAdmin) { + if (imGroupEntity.getGroupType() == GroupTypeEnum.PUBLIC.getCode()) { + throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_OWNER_ROLE); + } + + if (imGroupEntity.getGroupType() == GroupTypeEnum.PUBLIC.getCode() && + !imGroupEntity.getOwnerId().equals(req.getOperater())) { + throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_OWNER_ROLE); + } + } + + ImGroupEntity update = new ImGroupEntity(); + + update.setStatus(GroupStatusEnum.DESTROY.getCode()); + int update1 = imGroupDataMapper.update(update, objectQueryWrapper); + if (update1 != 1) { + throw new ApplicationException(GroupErrorCode.UPDATE_GROUP_BASE_INFO_ERROR); + } + return ResponseVO.successResponse(); + } + + @Override + @Transactional + public ResponseVO transferGroup(TransferGroupReq req) { + + ResponseVO roleInGroupOne = groupMemberService.getRoleInGroupOne(req.getGroupId(), req.getOperater(), req.getAppId()); + if (!roleInGroupOne.isOk()) { + return roleInGroupOne; + } + + if (roleInGroupOne.getData().getRole() != GroupMemberRoleEnum.OWNER.getCode()) { + return ResponseVO.errorResponse(GroupErrorCode.THIS_OPERATE_NEED_OWNER_ROLE); + } + + ResponseVO newOwnerRole = groupMemberService.getRoleInGroupOne(req.getGroupId(), req.getOwnerId(), req.getAppId()); + if (!newOwnerRole.isOk()) { + return newOwnerRole; + } + + QueryWrapper objectQueryWrapper = new QueryWrapper<>(); + objectQueryWrapper.eq("group_id", req.getGroupId()); + objectQueryWrapper.eq("app_id", req.getAppId()); + ImGroupEntity imGroupEntity = imGroupDataMapper.selectOne(objectQueryWrapper); + if(imGroupEntity.getStatus() == GroupStatusEnum.DESTROY.getCode()){ + throw new ApplicationException(GroupErrorCode.GROUP_IS_DESTROY); + } + + ImGroupEntity updateGroup = new ImGroupEntity(); + updateGroup.setOwnerId(req.getOwnerId()); + UpdateWrapper updateGroupWrapper = new UpdateWrapper<>(); + updateGroupWrapper.eq("app_id", req.getAppId()); + updateGroupWrapper.eq("group_id", req.getGroupId()); + imGroupDataMapper.update(updateGroup, updateGroupWrapper); + groupMemberService.transferGroupMember(req.getOwnerId(), req.getGroupId(), req.getAppId()); + + return ResponseVO.successResponse(); + } + + @Override + public ResponseVO getGroup(String groupId, Integer appId) { + + QueryWrapper query = new QueryWrapper<>(); + query.eq("app_id", appId); + query.eq("group_id", groupId); + ImGroupEntity imGroupEntity = imGroupDataMapper.selectOne(query); + + if (imGroupEntity == null) { + return ResponseVO.errorResponse(GroupErrorCode.GROUP_IS_NOT_EXIST); + } + return ResponseVO.successResponse(imGroupEntity); + } + + @Override + public ResponseVO getGroup(GetGroupReq req) { + + ResponseVO group = this.getGroup(req.getGroupId(), req.getAppId()); + + if(!group.isOk()){ + return group; + } + + GetGroupResp getGroupResp = new GetGroupResp(); + BeanUtils.copyProperties(group.getData(), getGroupResp); + try { + ResponseVO> groupMember = groupMemberService.getGroupMember(req.getGroupId(), req.getAppId()); + if (groupMember.isOk()) { + getGroupResp.setMemberList(groupMember.getData()); + } + } catch (Exception e) { + e.printStackTrace(); + } + return ResponseVO.successResponse(getGroupResp); + } + + @Override + public ResponseVO muteGroup(MuteGroupReq req) { + + ResponseVO groupResp = getGroup(req.getGroupId(), req.getAppId()); + if (!groupResp.isOk()) { + return groupResp; + } + + if(groupResp.getData().getStatus() == GroupStatusEnum.DESTROY.getCode()){ + throw new ApplicationException(GroupErrorCode.GROUP_IS_DESTROY); + } + + boolean isadmin = false; + + if (!isadmin) { + //不是后台调用需要检查权限 + ResponseVO role = groupMemberService.getRoleInGroupOne(req.getGroupId(), req.getOperater(), req.getAppId()); + + if (!role.isOk()) { + return role; + } + + GetRoleInGroupResp data = role.getData(); + Integer roleInfo = data.getRole(); + + boolean isManager = roleInfo == GroupMemberRoleEnum.MAMAGER.getCode() || roleInfo == GroupMemberRoleEnum.OWNER.getCode(); + + //公开群只能群主修改资料 + if (!isManager) { + throw new ApplicationException(GroupErrorCode.THIS_OPERATE_NEED_MANAGER_ROLE); + } + } + + ImGroupEntity update = new ImGroupEntity(); + update.setMute(req.getMute()); + + UpdateWrapper wrapper = new UpdateWrapper<>(); + wrapper.eq("group_id",req.getGroupId()); + wrapper.eq("app_id",req.getAppId()); + imGroupDataMapper.update(update,wrapper); + + return ResponseVO.successResponse(); + } + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/user/controller/ImUserController.java b/im-server/im-service/src/main/java/com/lld/im/service/user/controller/ImUserController.java new file mode 100644 index 0000000..b91428f --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/user/controller/ImUserController.java @@ -0,0 +1,35 @@ +package com.lld.im.service.user.controller; + +import com.lld.im.common.ResponseVO; +import com.lld.im.service.user.model.req.*; +import com.lld.im.service.user.service.ImUserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@RestController +@RequestMapping("v1/user") +public class ImUserController { + @Autowired + ImUserService imUserService; + + @RequestMapping("importUser") + public ResponseVO importUser(@RequestBody ImportUserReq req, Integer appId) { + return imUserService.importUser(req); + } + + @RequestMapping("/deleteUser") + public ResponseVO deleteUser(@RequestBody @Validated DeleteUserReq req, Integer appId) { + req.setAppId(appId); + return imUserService.deleteUser(req); + } + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/user/controller/ImUserDataController.java b/im-server/im-service/src/main/java/com/lld/im/service/user/controller/ImUserDataController.java new file mode 100644 index 0000000..1999b0f --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/user/controller/ImUserDataController.java @@ -0,0 +1,47 @@ +package com.lld.im.service.user.controller; + +import com.lld.im.common.ResponseVO; +import com.lld.im.service.user.model.req.GetUserInfoReq; +import com.lld.im.service.user.model.req.ModifyUserInfoReq; +import com.lld.im.service.user.model.req.UserId; +import com.lld.im.service.user.service.ImUserService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@RestController +@RequestMapping("v1/user/data") +public class ImUserDataController { + + private static Logger logger = LoggerFactory.getLogger(ImUserDataController.class); + + @Autowired + ImUserService imUserService; + + @RequestMapping("/getUserInfo") + public ResponseVO getUserInfo(@RequestBody GetUserInfoReq req, Integer appId){//@Validated + req.setAppId(appId); + return imUserService.getUserInfo(req); + } + + @RequestMapping("/getSingleUserInfo") + public ResponseVO getSingleUserInfo(@RequestBody @Validated UserId req, Integer appId){ + req.setAppId(appId); + return imUserService.getSingleUserInfo(req.getUserId(),req.getAppId()); + } + + @RequestMapping("/modifyUserInfo") + public ResponseVO modifyUserInfo(@RequestBody @Validated ModifyUserInfoReq req, Integer appId){ + req.setAppId(appId); + return imUserService.modifyUserInfo(req); + } +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/user/dao/ImUserDataEntity.java b/im-server/im-service/src/main/java/com/lld/im/service/user/dao/ImUserDataEntity.java new file mode 100644 index 0000000..e9afb2b --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/user/dao/ImUserDataEntity.java @@ -0,0 +1,60 @@ +package com.lld.im.service.user.dao; + +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @author: Chackylee + * @description: 数据库用户数据实体类 + **/ + +@Data +@TableName("im_user_data") +public class ImUserDataEntity { + + // 用户id + private String userId; + + // 用户名称 + private String nickName; + + //位置 + private String location; + + //生日 + private String birthDay; + + private String password; + + // 头像 + private String photo; + + // 性别 + private Integer userSex; + + // 个性签名 + private String selfSignature; + + // 加好友验证类型(Friend_AllowType) 1需要验证 + private Integer friendAllowType; + + // 管理员禁止用户添加加好友:0 未禁用 1 已禁用 + private Integer disableAddFriend; + + // 禁用标识(0 未禁用 1 已禁用) + private Integer forbiddenFlag; + + // 禁言标识 + private Integer silentFlag; + /** + * 用户类型 1普通用户 2客服 3机器人 + */ + private Integer userType; + + private Integer appId; + + private Integer delFlag; + + private String extra; + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/user/dao/mapper/ImUserDataMapper.java b/im-server/im-service/src/main/java/com/lld/im/service/user/dao/mapper/ImUserDataMapper.java new file mode 100644 index 0000000..b21552b --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/user/dao/mapper/ImUserDataMapper.java @@ -0,0 +1,9 @@ +package com.lld.im.service.user.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lld.im.service.user.dao.ImUserDataEntity; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface ImUserDataMapper extends BaseMapper { +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/user/model/UserStatusChangeNotifyContent.java b/im-server/im-service/src/main/java/com/lld/im/service/user/model/UserStatusChangeNotifyContent.java new file mode 100644 index 0000000..40e23b4 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/user/model/UserStatusChangeNotifyContent.java @@ -0,0 +1,22 @@ +package com.lld.im.service.user.model; + +import com.lld.im.common.model.ClientInfo; +import lombok.Data; + +/** + * @description: status区分是上线还是下线 + * @author: lld + * @version: 1.0 + */ +@Data +public class UserStatusChangeNotifyContent extends ClientInfo { + + + private String userId; + + //服务端状态 1上线 2离线 + private Integer status; + + + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/user/model/req/DeleteUserReq.java b/im-server/im-service/src/main/java/com/lld/im/service/user/model/req/DeleteUserReq.java new file mode 100644 index 0000000..82f3169 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/user/model/req/DeleteUserReq.java @@ -0,0 +1,15 @@ +package com.lld.im.service.user.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import java.util.List; + + +@Data +public class DeleteUserReq extends RequestBase { + + @NotEmpty(message = "用户id不能为空") + private List userId; +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/user/model/req/GetUserInfoReq.java b/im-server/im-service/src/main/java/com/lld/im/service/user/model/req/GetUserInfoReq.java new file mode 100644 index 0000000..0c1c9c4 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/user/model/req/GetUserInfoReq.java @@ -0,0 +1,15 @@ +package com.lld.im.service.user.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import java.util.List; + + +@Data +public class GetUserInfoReq extends RequestBase { + + private List userIds; + + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/user/model/req/GetUserSequenceReq.java b/im-server/im-service/src/main/java/com/lld/im/service/user/model/req/GetUserSequenceReq.java new file mode 100644 index 0000000..2984d9c --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/user/model/req/GetUserSequenceReq.java @@ -0,0 +1,16 @@ +package com.lld.im.service.user.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Data +public class GetUserSequenceReq extends RequestBase { + + private String userId; + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/user/model/req/ImportUserReq.java b/im-server/im-service/src/main/java/com/lld/im/service/user/model/req/ImportUserReq.java new file mode 100644 index 0000000..3ae365c --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/user/model/req/ImportUserReq.java @@ -0,0 +1,16 @@ +package com.lld.im.service.user.model.req; + +import com.lld.im.common.model.RequestBase; +import com.lld.im.service.user.dao.ImUserDataEntity; +import lombok.Data; + +import java.util.List; + + +@Data +public class ImportUserReq extends RequestBase { + + private List userData; + + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/user/model/req/ModifyUserInfoReq.java b/im-server/im-service/src/main/java/com/lld/im/service/user/model/req/ModifyUserInfoReq.java new file mode 100644 index 0000000..3132523 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/user/model/req/ModifyUserInfoReq.java @@ -0,0 +1,46 @@ +package com.lld.im.service.user.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Data +public class ModifyUserInfoReq extends RequestBase { + + // 用户id + @NotEmpty(message = "用户id不能为空") + private String userId; + + // 用户名称 + private String nickName; + + //位置 + private String location; + + //生日 + private String birthDay; + + private String password; + + // 头像 + private String photo; + + // 性别 + private String userSex; + + // 个性签名 + private String selfSignature; + + // 加好友验证类型(Friend_AllowType) 1需要验证 + private Integer friendAllowType; + + private String extra; + + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/user/model/req/UserId.java b/im-server/im-service/src/main/java/com/lld/im/service/user/model/req/UserId.java new file mode 100644 index 0000000..3856261 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/user/model/req/UserId.java @@ -0,0 +1,15 @@ +package com.lld.im.service.user.model.req; + +import com.lld.im.common.model.RequestBase; +import lombok.Data; + +/** + * @author: Chackylee + * @description: + **/ +@Data +public class UserId extends RequestBase { + + private String userId; + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/user/model/resp/GetUserInfoResp.java b/im-server/im-service/src/main/java/com/lld/im/service/user/model/resp/GetUserInfoResp.java new file mode 100644 index 0000000..742618c --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/user/model/resp/GetUserInfoResp.java @@ -0,0 +1,20 @@ +package com.lld.im.service.user.model.resp; + +import com.lld.im.service.user.dao.ImUserDataEntity; +import lombok.Data; + +import java.util.List; + +/** + * @author: Chackylee + * @description: + **/ +@Data +public class GetUserInfoResp { + + private List userDataItem; + + private List failUser; + + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/user/model/resp/ImportUserResp.java b/im-server/im-service/src/main/java/com/lld/im/service/user/model/resp/ImportUserResp.java new file mode 100644 index 0000000..2440a67 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/user/model/resp/ImportUserResp.java @@ -0,0 +1,18 @@ +package com.lld.im.service.user.model.resp; + +import lombok.Data; + +import java.util.List; + +/** + * @author: Chackylee + * @description: + **/ +@Data +public class ImportUserResp { + + private List successId; + + private List errorId; + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/user/model/resp/UserOnlineStatusResp.java b/im-server/im-service/src/main/java/com/lld/im/service/user/model/resp/UserOnlineStatusResp.java new file mode 100644 index 0000000..60f48a0 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/user/model/resp/UserOnlineStatusResp.java @@ -0,0 +1,22 @@ +package com.lld.im.service.user.model.resp; + +import com.lld.im.common.model.UserSession; +import lombok.Data; + +import java.util.List; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Data +public class UserOnlineStatusResp { + + private List session; + + private String customText; + + private Integer customStatus; + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/user/service/ImUserService.java b/im-server/im-service/src/main/java/com/lld/im/service/user/service/ImUserService.java new file mode 100644 index 0000000..81b61f9 --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/user/service/ImUserService.java @@ -0,0 +1,26 @@ +package com.lld.im.service.user.service; + +import com.lld.im.common.ResponseVO; +import com.lld.im.service.user.dao.ImUserDataEntity; +import com.lld.im.service.user.model.req.*; +import com.lld.im.service.user.model.resp.GetUserInfoResp; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +public interface ImUserService { + + public ResponseVO importUser(ImportUserReq req); + + public ResponseVO getUserInfo(GetUserInfoReq req); + + public ResponseVO getSingleUserInfo(String userId , Integer appId); + + public ResponseVO deleteUser(DeleteUserReq req); + + public ResponseVO modifyUserInfo(ModifyUserInfoReq req); + + +} diff --git a/im-server/im-service/src/main/java/com/lld/im/service/user/service/impl/ImUserviceImpl.java b/im-server/im-service/src/main/java/com/lld/im/service/user/service/impl/ImUserviceImpl.java new file mode 100644 index 0000000..ef590bd --- /dev/null +++ b/im-server/im-service/src/main/java/com/lld/im/service/user/service/impl/ImUserviceImpl.java @@ -0,0 +1,173 @@ +package com.lld.im.service.user.service.impl; + +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.lld.im.common.ResponseVO; +import com.lld.im.common.enums.DelFlagEnum; +import com.lld.im.common.enums.UserErrorCode; +import com.lld.im.common.exception.ApplicationException; +import com.lld.im.service.group.service.ImGroupService; +import com.lld.im.service.user.dao.ImUserDataEntity; +import com.lld.im.service.user.dao.mapper.ImUserDataMapper; +import com.lld.im.service.user.model.req.*; +import com.lld.im.service.user.model.resp.GetUserInfoResp; +import com.lld.im.service.user.model.resp.ImportUserResp; +import com.lld.im.service.user.service.ImUserService; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Service +public class ImUserviceImpl implements ImUserService { + + @Autowired + ImUserDataMapper imUserDataMapper; + + + @Autowired + ImGroupService imGroupService; + + @Override + public ResponseVO importUser(ImportUserReq req) { + + if(req.getUserData().size() > 100){ + return ResponseVO.errorResponse(UserErrorCode.IMPORT_SIZE_BEYOND); + } + + ImportUserResp resp = new ImportUserResp(); + List successId = new ArrayList<>(); + List errorId = new ArrayList<>(); + + for (ImUserDataEntity data: + req.getUserData()) { + try { + data.setAppId(req.getAppId()); + int insert = imUserDataMapper.insert(data); + if(insert == 1){ + successId.add(data.getUserId()); + } + }catch (Exception e){ + e.printStackTrace(); + errorId.add(data.getUserId()); + } + } + + resp.setErrorId(errorId); + resp.setSuccessId(successId); + return ResponseVO.successResponse(resp); + } + + @Override + public ResponseVO getUserInfo(GetUserInfoReq req) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("app_id",req.getAppId()); + queryWrapper.in("user_id",req.getUserIds()); + queryWrapper.eq("del_flag", DelFlagEnum.NORMAL.getCode()); + + List userDataEntities = imUserDataMapper.selectList(queryWrapper); + HashMap map = new HashMap<>(); + + for (ImUserDataEntity data: + userDataEntities) { + map.put(data.getUserId(),data); + } + + List failUser = new ArrayList<>(); + for (String uid: + req.getUserIds()) { + if(!map.containsKey(uid)){ + failUser.add(uid); + } + } + + GetUserInfoResp resp = new GetUserInfoResp(); + resp.setUserDataItem(userDataEntities); + resp.setFailUser(failUser); + return ResponseVO.successResponse(resp); + } + + @Override + public ResponseVO getSingleUserInfo(String userId, Integer appId) { + QueryWrapper objectQueryWrapper = new QueryWrapper<>(); + objectQueryWrapper.eq("app_id",appId); + objectQueryWrapper.eq("user_id",userId); + objectQueryWrapper.eq("del_flag", DelFlagEnum.NORMAL.getCode()); + + ImUserDataEntity ImUserDataEntity = imUserDataMapper.selectOne(objectQueryWrapper); + if(ImUserDataEntity == null){ + return ResponseVO.errorResponse(UserErrorCode.USER_IS_NOT_EXIST); + } + + return ResponseVO.successResponse(ImUserDataEntity); + } + + @Override + public ResponseVO deleteUser(DeleteUserReq req) { + ImUserDataEntity entity = new ImUserDataEntity(); + entity.setDelFlag(DelFlagEnum.DELETE.getCode()); + + List errorId = new ArrayList(); + List successId = new ArrayList(); + + for (String userId: + req.getUserId()) { + QueryWrapper wrapper = new QueryWrapper(); + wrapper.eq("app_id",req.getAppId()); + wrapper.eq("user_id",userId); + wrapper.eq("del_flag",DelFlagEnum.NORMAL.getCode()); + int update = 0; + + try { + update = imUserDataMapper.update(entity, wrapper); + if(update > 0){ + successId.add(userId); + }else{ + errorId.add(userId); + } + }catch (Exception e){ + errorId.add(userId); + } + } + + ImportUserResp resp = new ImportUserResp(); + resp.setSuccessId(successId); + resp.setErrorId(errorId); + return ResponseVO.successResponse(resp); + } + + @Override + @Transactional + public ResponseVO modifyUserInfo(ModifyUserInfoReq req) { + QueryWrapper query = new QueryWrapper<>(); + query.eq("app_id",req.getAppId()); + query.eq("user_id",req.getUserId()); + query.eq("del_flag",DelFlagEnum.NORMAL.getCode()); + ImUserDataEntity user = imUserDataMapper.selectOne(query); + if(user == null){ + throw new ApplicationException(UserErrorCode.USER_IS_NOT_EXIST); + } + + ImUserDataEntity update = new ImUserDataEntity(); + BeanUtils.copyProperties(req,update); + + update.setAppId(null); + update.setUserId(null); + int update1 = imUserDataMapper.update(update, query); + if(update1 == 1){ + return ResponseVO.successResponse(); + } + throw new ApplicationException(UserErrorCode.MODIFY_USER_ERROR); + } + +} diff --git a/im-server/im-service/src/main/resources/application.yml b/im-server/im-service/src/main/resources/application.yml new file mode 100644 index 0000000..e52fae9 --- /dev/null +++ b/im-server/im-service/src/main/resources/application.yml @@ -0,0 +1,39 @@ +spring: + profiles: + active: dev + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + password: frfr46467979+ + url: jdbc:mysql://127.0.0.1:3306/im-core?serverTimezone=UTC&useSSL=false&characterEncoding=UTF8 + username: root + + application: + name: im-core + +# logger 配置 +logging: + config: classpath:logback-spring.xml + +server: + port: 8000 + + +mybatis-plus: + configuration: + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + mapper-locations: classpath*:mapper/*.xml + global-config: + db-config: + update-strategy: NOT_EMPTY + +#mybatis: +# configuration: +# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + +httpclient: + maxTotal: 100 + defaultMaxPerRoute: 50 + connectTimeout: 2000 + connectionRequestTimeout: 2000 + socketTimeout: 5000 + staleConnectionCheckEnabled: true diff --git a/im-server/im-service/src/main/resources/logback-spring.xml b/im-server/im-service/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..b9cd630 --- /dev/null +++ b/im-server/im-service/src/main/resources/logback-spring.xml @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + DEBUG + + + ${CONSOLE_LOG_PATTERN} + utf8 + + + + + + + + + + + + + true + + + ${logFile}.%d{yyyy-MM-dd}.log + + + + + %d{yyyy-MM-dd HH:mm:ss} -%msg%n + + + + + + + + + + + + true + + + ${logFile}.%d{yyyy-MM-dd}.log + + + + + %d{yyyy-MM-dd HH:mm:ss} -%msg%n + + + + + + + + + + \ No newline at end of file diff --git a/im-server/im-system.iml b/im-server/im-system.iml new file mode 100644 index 0000000..a536e42 --- /dev/null +++ b/im-server/im-system.iml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/im-server/pom.xml b/im-server/pom.xml new file mode 100644 index 0000000..136f53c --- /dev/null +++ b/im-server/pom.xml @@ -0,0 +1,216 @@ + + 4.0.0 + + com.lld + im-system + pom + 1.0.0-SNAPSHOT + lld-im + l-im project + + + org.springframework.boot + spring-boot-starter-parent + 2.3.2.RELEASE + + + + + im-service + im-common + + + + 1.8 + 3.4.2 + 5.0.6 + 3.15.6 + 1.27 + 1.0.10 + 0.1 + 4.5.9 + 5.6.0 + 3.12.0 + 1.2.51 + 2.3.2.RELEASE + 4.1.35.Final + 8.18.0 + + + + + + ch.qos.logback + logback-classic + + + ch.qos.logback + logback-core + + + ch.qos.logback + logback-access + + + + + com.alibaba + fastjson + + + + + org.projectlombok + lombok + + + + + + + + + + com.dyuproject.protostuff + protostuff-api + ${protostuff-api} + + + com.dyuproject.protostuff + protostuff-core + ${protostuff-api} + + + com.dyuproject.protostuff + protostuff-runtime + ${protostuff-api} + + + + + + org.apache.commons + commons-lang3 + ${apache.commons.version} + + + + + com.alibaba + fastjson + ${fastjson.version} + + + + + org.springframework.boot + spring-boot-starter-data-redis + ${springboot.version} + + + + + org.springframework.boot + spring-boot-starter-amqp + ${springboot.version} + + + com.rabbitmq + amqp-client + ${rabbit.client.version} + + + + + com.baomidou + mybatis-plus-boot-starter + ${mybatis-plus.version} + + + + + + + + + + + org.hibernate + hibernate-validator + ${hibernate-validator.version} + + + + + org.redisson + redisson + ${redisson.version} + + + + + org.yaml + snakeyaml + ${snakeyaml.version} + + + + + cn.hutool + hutool-all + ${hutool.version} + + + + org.apache.httpcomponents + httpclient + ${apache.httpclient.version} + + + + + com.github.sgroschupf + zkclient + ${zkClient.version} + + + + + io.netty + netty-all + ${netty.version} + + + + + com.netflix.feign + feign-core + ${feign.version} + + + com.netflix.feign + feign-jackson + ${feign.version} + + + + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 8 + 8 + + + + + + \ No newline at end of file diff --git a/io-study-master/io-study/.gitignore b/io-study-master/io-study/.gitignore new file mode 100644 index 0000000..0aa5210 --- /dev/null +++ b/io-study-master/io-study/.gitignore @@ -0,0 +1,3 @@ +/.idea +/*.iml +/target diff --git a/io-study-master/io-study/pom.xml b/io-study-master/io-study/pom.xml new file mode 100644 index 0000000..8594e1e --- /dev/null +++ b/io-study-master/io-study/pom.xml @@ -0,0 +1,45 @@ + + + 4.0.0 + + org.example + io-study + 1.0-SNAPSHOT + + + 1.8 + + + + + + io.netty + netty-all + 4.1.35.Final + + + + + org.projectlombok + lombok + 1.18.12 + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 8 + 8 + + + + + + \ No newline at end of file diff --git a/io-study-master/io-study/src/main/java/bio/SocketServer.java b/io-study-master/io-study/src/main/java/bio/SocketServer.java new file mode 100644 index 0000000..0a328fe --- /dev/null +++ b/io-study-master/io-study/src/main/java/bio/SocketServer.java @@ -0,0 +1,60 @@ +package bio; + +import java.io.IOException; +import java.net.ServerSocket; +import java.net.Socket; + +/** + * @description: bio演示代码 + * @param + * @return + * @author lld + */ +public class SocketServer { + + //1.0 服务端在处理完第一个客户端的所有事件之前,无法为其他客户端提供服务。 + //2.0 会产生大量空闲线程,浪费服务器资源。 + public static void main(String[] args) throws Exception { + ServerSocket serverSocket = new ServerSocket(9001); + while (true) { + System.out.println("等待连接.."); + //阻塞方法 + Socket clientSocket = serverSocket.accept(); + System.out.println("有客户端连接了.."); + +// handler(clientSocket); + + new Thread(new Runnable() { + @Override + public void run() { + try { + handler(clientSocket); + } catch (Exception e) { + e.printStackTrace(); + } + } + }).start(); + } + } + + private static void handler(Socket clientSocket) throws Exception { +// while (true){ + byte[] bytes = new byte[1024]; + System.out.println("准备read.."); + //接收客户端的数据,阻塞方法,没有数据可读时就阻塞 + int read = clientSocket.getInputStream().read(bytes); + System.out.println("read完毕。。"); + if (read != -1) { +// int i = (int) (1 + Math.random() * (10 - 1 + 1)); +// System.out.println("收到客户端: " + Thread.currentThread().getName() + "收到了数据开始休眠"); +// Thread.sleep(i*1000L); + System.out.println("接收到客户端的数据:" + new String(bytes, 0, read)); + } +// clientSocket.getOutputStream().write("HelloClient".getBytes()); +// clientSocket.getOutputStream().flush(); +// } + + } + + +} \ No newline at end of file diff --git a/io-study-master/io-study/src/main/java/netty/base/Starter.java b/io-study-master/io-study/src/main/java/netty/base/Starter.java new file mode 100644 index 0000000..948bb33 --- /dev/null +++ b/io-study-master/io-study/src/main/java/netty/base/Starter.java @@ -0,0 +1,14 @@ +package netty.base; + +import netty.base.server.DiscardServer; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +public class Starter { + public static void main(String[] args) throws Exception { + new DiscardServer(9001).run(); + } +} diff --git a/io-study-master/io-study/src/main/java/netty/base/handler/DiscardServerHandler.java b/io-study-master/io-study/src/main/java/netty/base/handler/DiscardServerHandler.java new file mode 100644 index 0000000..39a9b05 --- /dev/null +++ b/io-study-master/io-study/src/main/java/netty/base/handler/DiscardServerHandler.java @@ -0,0 +1,33 @@ +package netty.base.handler; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.util.CharsetUtil; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +public class DiscardServerHandler extends ChannelInboundHandlerAdapter { + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + System.out.println("有客户端连接了"); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + ByteBuf out = (ByteBuf) msg; + String data = out.toString(CharsetUtil.UTF_8); + System.out.println(data); + short length = (short) data + .getBytes().length; + ByteBuf byteBuf = Unpooled.directBuffer(8); + byteBuf.writeShort(length); + byteBuf.writeBytes(data.getBytes()); + ctx.writeAndFlush(byteBuf); + } +} diff --git a/io-study-master/io-study/src/main/java/netty/base/server/DiscardServer.java b/io-study-master/io-study/src/main/java/netty/base/server/DiscardServer.java new file mode 100644 index 0000000..2f0bc3a --- /dev/null +++ b/io-study-master/io-study/src/main/java/netty/base/server/DiscardServer.java @@ -0,0 +1,66 @@ +package netty.base.server; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.LengthFieldBasedFrameDecoder; +import netty.base.handler.DiscardServerHandler; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +public class DiscardServer { + + private int port; + + public DiscardServer(int port) { + this.port = port; + } + + public void run() throws Exception { + EventLoopGroup bossGroup = new NioEventLoopGroup(1); //线程池 + EventLoopGroup workerGroup = new NioEventLoopGroup();// + + try { + ServerBootstrap b = new ServerBootstrap(); // (2) + b.group(bossGroup, workerGroup) + .channel(NioServerSocketChannel.class) // (3) + .childHandler(new ChannelInitializer() { // (4) + @Override + public void initChannel(SocketChannel ch) throws Exception { + ch.pipeline().addLast(new LengthFieldBasedFrameDecoder( + 1024,0, + 4,0,4 + )); +// ch.pipeline().addLast(new LengthFieldPrepender(2)); +// ch.pipeline().addLast(new StringDecoder()); +// ch.pipeline().addLast(new StringEncoder()); + ch.pipeline().addLast(new DiscardServerHandler()); + } + }) + .option(ChannelOption.SO_BACKLOG, 128) // (5) + .childOption(ChannelOption.SO_KEEPALIVE, true); // (6) + + // Bind and start to accept incoming connections. + System.out.println("tcp start success"); + ChannelFuture f = b.bind(port).sync(); // (7) + + + // Wait until the server socket is closed. + // In this example, this does not happen, but you can do that to gracefully + // shut down your server. + f.channel().closeFuture().sync(); + } finally { + workerGroup.shutdownGracefully(); + bossGroup.shutdownGracefully(); + } + } + +} diff --git a/io-study-master/io-study/src/main/java/netty/bytebuf/NettyByteBuf.java b/io-study-master/io-study/src/main/java/netty/bytebuf/NettyByteBuf.java new file mode 100644 index 0000000..79f1264 --- /dev/null +++ b/io-study-master/io-study/src/main/java/netty/bytebuf/NettyByteBuf.java @@ -0,0 +1,29 @@ +package netty.bytebuf; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; + +public class NettyByteBuf { + public static void main(String[] args) { + // 创建byteBuf对象,该对象内部包含一个字节数组byte[10] + ByteBuf byteBuf = Unpooled.buffer(10); + System.out.println("byteBuf=" + byteBuf); + + for (int i = 0; i < 8; i++) { + byteBuf.writeByte(i); + } + System.out.println("byteBuf=" + byteBuf); + + for (int i = 0; i < 5; i++) { + System.out.println(byteBuf.getByte(i)); + } + System.out.println("byteBuf=" + byteBuf); + + for (int i = 0; i < 5; i++) { + System.out.println(byteBuf.readByte()); + } + System.out.println("byteBuf=" + byteBuf); + + + } +} diff --git a/io-study-master/io-study/src/main/java/netty/chat/Starter.java b/io-study-master/io-study/src/main/java/netty/chat/Starter.java new file mode 100644 index 0000000..715a211 --- /dev/null +++ b/io-study-master/io-study/src/main/java/netty/chat/Starter.java @@ -0,0 +1,19 @@ +package netty.chat; + +import netty.chat.server.DiscardServer; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +public class Starter { + + // line + // header + // body + + public static void main(String[] args) throws Exception { + new DiscardServer(9001).run(); + } +} diff --git a/io-study-master/io-study/src/main/java/netty/chat/handler/DiscardServerHandler.java b/io-study-master/io-study/src/main/java/netty/chat/handler/DiscardServerHandler.java new file mode 100644 index 0000000..915d08b --- /dev/null +++ b/io-study-master/io-study/src/main/java/netty/chat/handler/DiscardServerHandler.java @@ -0,0 +1,67 @@ +package netty.chat.handler; + +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; + +import java.util.HashSet; +import java.util.Set; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +public class DiscardServerHandler extends ChannelInboundHandlerAdapter { + + static Set channelList = new HashSet<>(); + +// @Override +// public void channelActive(ChannelHandlerContext ctx) throws Exception { +// //通知其他人 我上线了 +// channelList.forEach(e->{ +// e.writeAndFlush("[客户端]" + ctx.channel().remoteAddress() + "上线了"); +// }); +// +// channelList.add(ctx.channel()); +// } + + //网络调试助手 -> 服务端 + //?直接发送!? + //网络调试助手 -> 操作系统 -> 网络 -> 对方操作系统 -> 9000找到对应进程(我们的服务端) + //!字符串 + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + + String message = (String) msg; +// Charset gbk = Charset.forName("GBK"); + System.out.println("收到数据:" + message); +// 分发给聊天室内的所有客户端 +// 通知其他人 我上线了 + channelList.forEach(e->{ + if(e == ctx.channel()){ + e.writeAndFlush("[自己] : " + message); + }else{ + e.writeAndFlush("[客户端] " +ctx.channel().remoteAddress()+":" + message); + } + }); + + + } + + /** + * @description: channel 处于不活跃的时候会调用 + * @param + * @return void + * @author lld + */ + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + //通知其他客户端 我下线了 + channelList.remove(ctx.channel()); + //通知其他人 我上线了 + channelList.forEach(e->{ + e.writeAndFlush("[客户端]" + ctx.channel().remoteAddress() + "下线了"); + }); + } +} diff --git a/io-study-master/io-study/src/main/java/netty/chat/server/DiscardServer.java b/io-study-master/io-study/src/main/java/netty/chat/server/DiscardServer.java new file mode 100644 index 0000000..28f64b1 --- /dev/null +++ b/io-study-master/io-study/src/main/java/netty/chat/server/DiscardServer.java @@ -0,0 +1,69 @@ +package netty.chat.server; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.DelimiterBasedFrameDecoder; +import io.netty.handler.codec.string.StringDecoder; +import io.netty.handler.codec.string.StringEncoder; +import netty.chat.handler.DiscardServerHandler; + +import java.nio.charset.Charset; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +public class DiscardServer { + + private int port; + + public DiscardServer(int port) { + this.port = port; + } + + public void run() throws Exception { + EventLoopGroup bossGroup = new NioEventLoopGroup(1); //线程池 + EventLoopGroup workerGroup = new NioEventLoopGroup();// + + try { + ServerBootstrap b = new ServerBootstrap(); // (2) + b.group(bossGroup, workerGroup) + .channel(NioServerSocketChannel.class) // (3) + .childHandler(new ChannelInitializer() { // (4) + @Override + public void initChannel(SocketChannel ch) throws Exception { + Charset gbk = Charset.forName("utf-8"); + ch.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, Unpooled.copiedBuffer("_" + .getBytes()))); + ch.pipeline().addLast("encoder", new StringEncoder(gbk));//out + ch.pipeline().addLast("decoder", new StringDecoder(gbk));//in + ch.pipeline().addLast(new DiscardServerHandler()); + } + }) + .option(ChannelOption.SO_BACKLOG, 128) // (5) + .childOption(ChannelOption.SO_KEEPALIVE, true); // (6) + + // Bind and start to accept incoming connections. + System.out.println("tcp start success"); + ChannelFuture f = b.bind(port).sync(); // (7) + + + // Wait until the server socket is closed. + // In this example, this does not happen, but you can do that to gracefully + // shut down your server. + f.channel().closeFuture().sync(); + } finally { + workerGroup.shutdownGracefully(); + bossGroup.shutdownGracefully(); + } + } + +} diff --git a/io-study-master/io-study/src/main/java/netty/heaetbeat/Starter.java b/io-study-master/io-study/src/main/java/netty/heaetbeat/Starter.java new file mode 100644 index 0000000..a1ea762 --- /dev/null +++ b/io-study-master/io-study/src/main/java/netty/heaetbeat/Starter.java @@ -0,0 +1,22 @@ +package netty.heaetbeat; + +import netty.heaetbeat.server.DiscardServer; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +public class Starter { + + + //2 + + // + + //0-2 + 1 = 3 ___3 //5 + + public static void main(String[] args) throws Exception { + new DiscardServer(9001).run(); + } +} diff --git a/io-study-master/io-study/src/main/java/netty/heaetbeat/handler/HeartbeatHandler.java b/io-study-master/io-study/src/main/java/netty/heaetbeat/handler/HeartbeatHandler.java new file mode 100644 index 0000000..d4439e9 --- /dev/null +++ b/io-study-master/io-study/src/main/java/netty/heaetbeat/handler/HeartbeatHandler.java @@ -0,0 +1,32 @@ +package netty.heaetbeat.handler; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.handler.timeout.IdleState; +import io.netty.handler.timeout.IdleStateEvent; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +public class HeartbeatHandler extends ChannelInboundHandlerAdapter { + + int readTimeOut = 0; + + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { + IdleStateEvent event = (IdleStateEvent) evt; + + if(event.state() == IdleState.READER_IDLE){ + readTimeOut++; + } + + if(readTimeOut >= 3){ + System.out.println("超时超过3次,断开连接"); + ctx.close(); + } + +// System.out.println("触发了:" + event.state() + "事件"); + } +} diff --git a/io-study-master/io-study/src/main/java/netty/heaetbeat/server/DiscardServer.java b/io-study-master/io-study/src/main/java/netty/heaetbeat/server/DiscardServer.java new file mode 100644 index 0000000..fd0bd85 --- /dev/null +++ b/io-study-master/io-study/src/main/java/netty/heaetbeat/server/DiscardServer.java @@ -0,0 +1,60 @@ +package netty.heaetbeat.server; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.timeout.IdleStateHandler; +import netty.heaetbeat.handler.HeartbeatHandler; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +public class DiscardServer { + + private int port; + + public DiscardServer(int port) { + this.port = port; + } + + public void run() throws Exception { + EventLoopGroup bossGroup = new NioEventLoopGroup(1); //线程池 + EventLoopGroup workerGroup = new NioEventLoopGroup();// + + try { + ServerBootstrap b = new ServerBootstrap(); // (2) + b.group(bossGroup, workerGroup) + .channel(NioServerSocketChannel.class) // (3) + .childHandler(new ChannelInitializer() { // (4) + @Override + public void initChannel(SocketChannel ch) throws Exception { + ch.pipeline().addLast(new IdleStateHandler(3,0,0)); + ch.pipeline().addLast(new HeartbeatHandler()); + } + }) + .option(ChannelOption.SO_BACKLOG, 128) // (5) + .childOption(ChannelOption.SO_KEEPALIVE, true); // (6) + + // Bind and start to accept incoming connections. + System.out.println("tcp start success"); + ChannelFuture f = b.bind(port).sync(); // (7) + + + // Wait until the server socket is closed. + // In this example, this does not happen, but you can do that to gracefully + // shut down your server. + f.channel().closeFuture().sync(); + } finally { + workerGroup.shutdownGracefully(); + bossGroup.shutdownGracefully(); + } + } + +} diff --git a/io-study-master/io-study/src/main/java/netty/my/Starter.java b/io-study-master/io-study/src/main/java/netty/my/Starter.java new file mode 100644 index 0000000..13bec31 --- /dev/null +++ b/io-study-master/io-study/src/main/java/netty/my/Starter.java @@ -0,0 +1,15 @@ +package netty.my; + +import netty.my.server.DiscardServer; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +public class Starter { + + public static void main(String[] args) throws Exception { + new DiscardServer(9001).run(); + } +} diff --git a/io-study-master/io-study/src/main/java/netty/my/codec/MyDecodecer.java b/io-study-master/io-study/src/main/java/netty/my/codec/MyDecodecer.java new file mode 100644 index 0000000..512646e --- /dev/null +++ b/io-study-master/io-study/src/main/java/netty/my/codec/MyDecodecer.java @@ -0,0 +1,34 @@ +package netty.my.codec; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; + +import java.util.List; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +public class MyDecodecer extends ByteToMessageDecoder { + + + //数据长度 + 数据 + @Override + protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { + if(in.readableBytes() < 4){ + return; + } + //数据长度 4 + 10000 9999 + int i = in.readInt(); + if(in.readableBytes() < i){ + in.resetReaderIndex(); + return; + } + byte[] data = new byte[i];//10000 + in.readBytes(data); + System.out.println(new String(data)); + in.markReaderIndex();//10004 + } +} diff --git a/io-study-master/io-study/src/main/java/netty/my/handler/DiscardServerHandler.java b/io-study-master/io-study/src/main/java/netty/my/handler/DiscardServerHandler.java new file mode 100644 index 0000000..56ad295 --- /dev/null +++ b/io-study-master/io-study/src/main/java/netty/my/handler/DiscardServerHandler.java @@ -0,0 +1,43 @@ +package netty.my.handler; + +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; + +import java.util.HashSet; +import java.util.Set; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +public class DiscardServerHandler extends ChannelInboundHandlerAdapter { + + static Set channelList = new HashSet<>(); + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + } + + //网络调试助手 -> 服务端 + //?直接发送!? + //网络调试助手 -> 操作系统 -> 网络 -> 对方操作系统 -> 9000找到对应进程(我们的服务端) + //!字符串 + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + + + + } + + /** + * @description: channel 处于不活跃的时候会调用 + * @param + * @return void + * @author lld + */ + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + } +} diff --git a/io-study-master/io-study/src/main/java/netty/my/server/DiscardServer.java b/io-study-master/io-study/src/main/java/netty/my/server/DiscardServer.java new file mode 100644 index 0000000..36e8bc8 --- /dev/null +++ b/io-study-master/io-study/src/main/java/netty/my/server/DiscardServer.java @@ -0,0 +1,62 @@ +package netty.my.server; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import netty.my.codec.MyDecodecer; + +import java.nio.charset.Charset; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +public class DiscardServer { + + private int port; + + public DiscardServer(int port) { + this.port = port; + } + + public void run() throws Exception { + EventLoopGroup bossGroup = new NioEventLoopGroup(1); //线程池 + EventLoopGroup workerGroup = new NioEventLoopGroup();// + + try { + ServerBootstrap b = new ServerBootstrap(); // (2) + b.group(bossGroup, workerGroup) + .channel(NioServerSocketChannel.class) // (3) + .childHandler(new ChannelInitializer() { // (4) + @Override + public void initChannel(SocketChannel ch) throws Exception { + Charset gbk = Charset.forName("utf-8"); + ch.pipeline().addLast(new MyDecodecer()); +// ch.pipeline().addLast(new DiscardServerHandler()); + } + }) + .option(ChannelOption.SO_BACKLOG, 128) // (5) + .childOption(ChannelOption.SO_KEEPALIVE, true); // (6) + + // Bind and start to accept incoming connections. + System.out.println("tcp start success"); + ChannelFuture f = b.bind(port).sync(); // (7) + + + // Wait until the server socket is closed. + // In this example, this does not happen, but you can do that to gracefully + // shut down your server. + f.channel().closeFuture().sync(); + } finally { + workerGroup.shutdownGracefully(); + bossGroup.shutdownGracefully(); + } + } + +} diff --git a/io-study-master/io-study/src/main/java/netty/upload/FileDto.java b/io-study-master/io-study/src/main/java/netty/upload/FileDto.java new file mode 100644 index 0000000..7ffe9ba --- /dev/null +++ b/io-study-master/io-study/src/main/java/netty/upload/FileDto.java @@ -0,0 +1,19 @@ +package netty.upload; + +import lombok.Data; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +@Data +public class FileDto { + + private String fileName; //文件名称 + + private Integer command; // 1请求创建文件 2传输文件 + + private byte[] bytes; //文件字节;再实际应用中可以使用非对称加密,以保证传输信息安全 + +} diff --git a/io-study-master/io-study/src/main/java/netty/upload/Starter.java b/io-study-master/io-study/src/main/java/netty/upload/Starter.java new file mode 100644 index 0000000..24e3076 --- /dev/null +++ b/io-study-master/io-study/src/main/java/netty/upload/Starter.java @@ -0,0 +1,22 @@ +package netty.upload; + + +import netty.upload.server.UploadFileServer; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +public class Starter { + + //请求上传 + //创建文件 + //将客户端数据写入本地磁盘 + //command 4 fileName 4 8 + + //请求上传 -> 是否能够上传 -> 上传(客户端) -》将客户端数据写入本地磁盘 + public static void main(String[] args) throws Exception { + new UploadFileServer(9001).run(); + } +} diff --git a/io-study-master/io-study/src/main/java/netty/upload/codec/UploadFileDecodecer.java b/io-study-master/io-study/src/main/java/netty/upload/codec/UploadFileDecodecer.java new file mode 100644 index 0000000..18c5b1d --- /dev/null +++ b/io-study-master/io-study/src/main/java/netty/upload/codec/UploadFileDecodecer.java @@ -0,0 +1,59 @@ +package netty.upload.codec; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; +import netty.upload.FileDto; + +import java.util.List; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +public class UploadFileDecodecer extends ByteToMessageDecoder { + + + //请求上传 + //创建文件 + //将客户端数据写入本地磁盘 + //command 4 fileName 4 8 + //数据长度 + 数据 + @Override + protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { + if(in.readableBytes() < 8){ + return; + } + //command 4 + int command = in.readInt(); + + FileDto fileDto = new FileDto(); + + int fileNameLen = in.readInt(); + + if(in.readableBytes() < fileNameLen){ + in.resetReaderIndex(); + return; + } + + byte[] data = new byte[fileNameLen]; + in.readBytes(data); + String fileName = new String(data); + fileDto.setCommand(command); + fileDto.setFileName(fileName); + + if(command == 2){ + int dataLen = in.readInt(); + if(in.readableBytes() < dataLen){ + in.resetReaderIndex(); + return; + } + byte[] fileData = new byte[dataLen]; + in.readBytes(fileData); + fileDto.setBytes(fileData); + } + in.markReaderIndex();//10004 + out.add(fileDto); + } +} diff --git a/io-study-master/io-study/src/main/java/netty/upload/handler/UploadFileHandler.java b/io-study-master/io-study/src/main/java/netty/upload/handler/UploadFileHandler.java new file mode 100644 index 0000000..12b849f --- /dev/null +++ b/io-study-master/io-study/src/main/java/netty/upload/handler/UploadFileHandler.java @@ -0,0 +1,68 @@ +package netty.upload.handler; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import netty.upload.FileDto; + +import java.io.*; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +public class UploadFileHandler extends ChannelInboundHandlerAdapter { + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + if(msg instanceof FileDto){ + FileDto dto = (FileDto) msg; + if(dto.getCommand() == 1){ + //创建文件 + File file = new File("C://"+dto.getFileName()); + if(!file.exists()){ + file.createNewFile(); + } + }else if(dto.getCommand() == 2){ + //写入文件 + save2File("C://"+dto.getFileName(),dto.getBytes()); + } + } + + } + + public static boolean save2File(String fname, byte[] msg){ + OutputStream fos = null; + try{ + File file = new File(fname); + File parent = file.getParentFile(); + boolean bool; + if ((!parent.exists()) & + (!parent.mkdirs())) { + return false; + } + fos = new FileOutputStream(file,true); + fos.write(msg); + fos.flush(); + return true; + }catch (FileNotFoundException e){ + return false; + }catch (IOException e){ + File parent; + return false; + } + finally{ + if (fos != null) { + try{ + fos.close(); + }catch (IOException e) {} + } + } + } + + +} diff --git a/io-study-master/io-study/src/main/java/netty/upload/server/UploadFileServer.java b/io-study-master/io-study/src/main/java/netty/upload/server/UploadFileServer.java new file mode 100644 index 0000000..d635068 --- /dev/null +++ b/io-study-master/io-study/src/main/java/netty/upload/server/UploadFileServer.java @@ -0,0 +1,60 @@ +package netty.upload.server; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import netty.upload.codec.UploadFileDecodecer; +import netty.upload.handler.UploadFileHandler; + +/** + * @description: + * @author: lld + * @version: 1.0 + */ +public class UploadFileServer { + + private int port; + + public UploadFileServer(int port) { + this.port = port; + } + + public void run() throws Exception { + EventLoopGroup bossGroup = new NioEventLoopGroup(1); //线程池 + EventLoopGroup workerGroup = new NioEventLoopGroup();// + + try { + ServerBootstrap b = new ServerBootstrap(); // (2) + b.group(bossGroup, workerGroup) + .channel(NioServerSocketChannel.class) // (3) + .childHandler(new ChannelInitializer() { // (4) + @Override + public void initChannel(SocketChannel ch) throws Exception { + ch.pipeline().addLast(new UploadFileDecodecer()); + ch.pipeline().addLast(new UploadFileHandler()); + } + }) + .option(ChannelOption.SO_BACKLOG, 128) // (5) + .childOption(ChannelOption.SO_KEEPALIVE, true); // (6) + + // Bind and start to accept incoming connections. + System.out.println("tcp start success"); + ChannelFuture f = b.bind(port).sync(); // (7) + + + // Wait until the server socket is closed. + // In this example, this does not happen, but you can do that to gracefully + // shut down your server. + f.channel().closeFuture().sync(); + } finally { + workerGroup.shutdownGracefully(); + bossGroup.shutdownGracefully(); + } + } + +} diff --git a/io-study-master/io-study/src/main/java/nio/NioSelectorServer.java b/io-study-master/io-study/src/main/java/nio/NioSelectorServer.java new file mode 100644 index 0000000..87f9815 --- /dev/null +++ b/io-study-master/io-study/src/main/java/nio/NioSelectorServer.java @@ -0,0 +1,88 @@ +package nio; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; +import java.util.Iterator; +import java.util.Set; + +/** + * @description: nio Selector演示代码 + * @param + * @return + * @author lld + */ +public class NioSelectorServer { + + //BIO + //1.0 + // 2 2 1 1 1 1 + // 0 + // 1 1 2 1 1 1 + // 0 0 0 0 0 0 + + //NIO + //1.0 + // 2 2 2 2 2 2 + // 0 + //2.0 + // 2 2 2 2 2 2 + // 0 + + public static void main(String[] args) throws IOException { + + int OP_ACCEPT = 1 << 4; + System.out.println(OP_ACCEPT); + + // 创建NIO ServerSocketChannel + ServerSocketChannel serverSocket = ServerSocketChannel.open(); + serverSocket.socket().bind(new InetSocketAddress(9001)); + // 设置ServerSocketChannel为非阻塞 + serverSocket.configureBlocking(false); + // 打开Selector处理Channel,即创建epoll + Selector selector = Selector.open(); + // 把ServerSocketChannel注册到selector上,并且selector对客户端accept连接操作感兴趣 + SelectionKey selectionKey = serverSocket.register(selector, SelectionKey.OP_ACCEPT); + System.out.println("服务启动成功"); + + while (true) { + // 阻塞等待需要处理的事件发生 已注册事件发生后,会执行后面逻辑 + selector.select(); + + // 获取selector中注册的全部事件的 SelectionKey 实例 + Set selectionKeys = selector.selectedKeys(); + Iterator iterator = selectionKeys.iterator(); + + // 遍历SelectionKey对事件进行处理 + while (iterator.hasNext()) { + SelectionKey key = iterator.next(); + // 如果是OP_ACCEPT事件,则进行连接获取和事件注册 + if (key.isAcceptable()) { + ServerSocketChannel server = (ServerSocketChannel) key.channel(); + SocketChannel socketChannel = server.accept(); + socketChannel.configureBlocking(false); + // 这里只注册了读事件,如果需要给客户端发送数据可以注册写事件 + SelectionKey selKey = socketChannel.register(selector, SelectionKey.OP_READ); + System.out.println("客户端连接成功"); + } else if (key.isReadable()) { // 如果是OP_READ事件,则进行读取和打印 + SocketChannel socketChannel = (SocketChannel) key.channel(); + ByteBuffer byteBuffer = ByteBuffer.allocate(128); + int len = socketChannel.read(byteBuffer); + // 如果有数据,把数据打印出来 + if (len > 0) { + System.out.println(Thread.currentThread().getName() + "接收到消息:" + new String(byteBuffer.array())); + } else if (len == -1) { // 如果客户端断开连接,关闭Socket + System.out.println("客户端断开连接"); + socketChannel.close(); + } + } + //从事件集合里删除本次处理的key,防止下次select重复处理 + iterator.remove(); + } + } + } +} \ No newline at end of file diff --git a/io-study-master/io-study/src/main/java/nio/NioServer.java b/io-study-master/io-study/src/main/java/nio/NioServer.java new file mode 100644 index 0000000..1278a34 --- /dev/null +++ b/io-study-master/io-study/src/main/java/nio/NioServer.java @@ -0,0 +1,63 @@ +package nio; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * @description: nio演示代码 + * @param + * @return + * @author lld + */ +public class NioServer { + + // 保存客户端连接 + static List channelList = new ArrayList<>(); + + //10w + //1w + // + public static void main(String[] args) throws IOException { + + // 创建NIO ServerSocketChannel,与BIO的serverSocket类似 + ServerSocketChannel serverSocket = ServerSocketChannel.open(); + serverSocket.socket().bind(new InetSocketAddress(9001)); + // 设置ServerSocketChannel为非阻塞 + serverSocket.configureBlocking(false); + System.out.println("服务启动成功"); + + while (true) { + // 非阻塞模式accept方法不会阻塞,否则会阻塞 + // NIO的非阻塞是由操作系统内部实现的,底层调用了linux内核的accept函数 + SocketChannel socketChannel = serverSocket.accept(); + if (socketChannel != null) { // 如果有客户端进行连接 + System.out.println("连接成功"); + // 设置SocketChannel为非阻塞 + socketChannel.configureBlocking(false); + // 保存客户端连接在List中 + channelList.add(socketChannel); + } + // 遍历连接进行数据读取 10w - 1000 读写事件 + Iterator iterator = channelList.iterator(); + while (iterator.hasNext()) { + SocketChannel sc = iterator.next(); + ByteBuffer byteBuffer = ByteBuffer.allocate(128); + // 非阻塞模式read方法不会阻塞,否则会阻塞 + int len = sc.read(byteBuffer); + // 如果有数据,把数据打印出来 + if (len > 0) { + System.out.println(Thread.currentThread().getName() + " 接收到消息:" + new String(byteBuffer.array())); + } else if (len == -1) { // 如果客户端断开,把socket从集合中去掉 + iterator.remove(); + System.out.println("客户端断开连接"); + } + } + } + } +} \ No newline at end of file diff --git a/io-study-master/io-study/src/main/resources/mulitSend.py b/io-study-master/io-study/src/main/resources/mulitSend.py new file mode 100644 index 0000000..42d5393 --- /dev/null +++ b/io-study-master/io-study/src/main/resources/mulitSend.py @@ -0,0 +1,14 @@ + +import socket + +s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) +s.connect(("127.0.0.1",9001)) + +for i in range(100): + print(i) + string = "hello1哈_"; + body = bytes(string, 'utf-8') + s.sendall(body) + + + diff --git a/io-study-master/io-study/src/main/resources/mycodecer.py b/io-study-master/io-study/src/main/resources/mycodecer.py new file mode 100644 index 0000000..a03fada --- /dev/null +++ b/io-study-master/io-study/src/main/resources/mycodecer.py @@ -0,0 +1,21 @@ + +import uuid +import socket + + +s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) +s.connect(("127.0.0.1",9001)) +data = "哈哈哈asdasdadfasdfasdfa哈123" +print(data) +dataBytes = bytes(data,"utf-8") +dataLen = len(dataBytes) + +data_len = dataLen.to_bytes(4, byteorder='big') +# s.sendall(data_len + dataBytes) + +for i in range(100): + print(i) + s.sendall(data_len + dataBytes) + + + diff --git a/io-study-master/io-study/src/main/resources/uploadFile.py b/io-study-master/io-study/src/main/resources/uploadFile.py new file mode 100644 index 0000000..5e149cf --- /dev/null +++ b/io-study-master/io-study/src/main/resources/uploadFile.py @@ -0,0 +1,34 @@ +#-*- coding: UTF-8 -*- +import socket,os,struct +s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) +s.connect(("127.0.0.1",9001)) + +filepath = "D://natapp.zip" +if os.path.isfile(filepath): + + filename = os.path.basename(filepath).encode('utf-8') + + # 请求传输文件 + command = 1 + + body_len = len(filename) + fileNameData = bytes(filename) + i = body_len.to_bytes(4, byteorder='big') + c = command.to_bytes(4, byteorder='big') + + s.sendall(c + i + fileNameData) + + fo = open(filepath,'rb') + while True: + command = 2; + c = command.to_bytes(4, byteorder='big') + filedata = fo.read(1024) + print(len(filedata)) + b = len(filedata).to_bytes(4, byteorder='big') + if not filedata: + break + s.sendall(c + i + fileNameData + b + filedata) + fo.close() + #s.close() +else: + print(False) \ No newline at end of file diff --git a/l-im-app-imooc-master/l-im-app-imooc/.gitignore b/l-im-app-imooc-master/l-im-app-imooc/.gitignore new file mode 100644 index 0000000..b673845 --- /dev/null +++ b/l-im-app-imooc-master/l-im-app-imooc/.gitignore @@ -0,0 +1,4 @@ +/unpackage +/.hbuilderx +/node_modules + diff --git a/l-im-app-imooc-master/l-im-app-imooc/App.vue b/l-im-app-imooc-master/l-im-app-imooc/App.vue new file mode 100644 index 0000000..698ecd7 --- /dev/null +++ b/l-im-app-imooc-master/l-im-app-imooc/App.vue @@ -0,0 +1,43 @@ + + + diff --git a/l-im-app-imooc-master/l-im-app-imooc/README.md b/l-im-app-imooc-master/l-im-app-imooc/README.md new file mode 100644 index 0000000..e69de29 diff --git a/l-im-app-imooc-master/l-im-app-imooc/common/common.css b/l-im-app-imooc-master/l-im-app-imooc/common/common.css new file mode 100644 index 0000000..bb665fd --- /dev/null +++ b/l-im-app-imooc-master/l-im-app-imooc/common/common.css @@ -0,0 +1,33 @@ +/* 1. 背景色 */ +.page{ + background-color: #EDEDED; + /* #ifndef APP-PLUS-NVUE */ + min-height: 100vh; + height: auto; + /* #endif */ + /* #ifdef APP-PLUS-NVUE */ + flex: 1; + /* #endif */ +} +/* 2. 主背景色 绿 */ +.main-bg-color{ + background-color: #06a1c0; +} +.main-bg-hover-color{ + background-color: #06a1c0; +} +/* 3. 主文字色(绿) */ +.main-text-color{ + color: #06a1c0; +} + +.border-main{ + border-color: #06a1c0!important; +} + +.bg-chat-item{ + background-color: #06a1c0; +} +.text-chat-item{ + color: #06a1c0; +} \ No newline at end of file diff --git a/l-im-app-imooc-master/l-im-app-imooc/common/css.css b/l-im-app-imooc-master/l-im-app-imooc/common/css.css new file mode 100644 index 0000000..2459dba --- /dev/null +++ b/l-im-app-imooc-master/l-im-app-imooc/common/css.css @@ -0,0 +1,394 @@ + +.view,.text{ + font-size:28rpx; + line-height:1.8; + color:#0E151D; +} +/* 宽度 */ +.w-100{ width: 750rpx; } + +.row { + margin-right: -20rpx; + margin-left: -20rpx; + /* #ifndef APP-PLUS-NVUE */ + display: flex; + /* #endif */ + flex-wrap: wrap; + flex-direction: row; +} + +.col-1, +.col-2, +.col-3, +.col-4, +.col-5, +.col-6, +.col-7, +.col-8, +.col-9, +.col-10, +.col-11, +.col-12{ + position: relative; + padding-right: 20rpx; + padding-left: 20rpx; +} +.col-12 { width: 750rpx;} +.col-11 { width: 687.5rpx; } +.col-10 { width: 625rpx; } +.col-9 { width: 562.5rpx; } +.col-8 { width: 500rpx; } +.col-7 { width: 437.5rpx; } +.col-6 { width: 375rpx; } +.col-5 { width: 312.5rpx;} +.col-4 {width: 250rpx;} +.col-3 {width: 187.5rpx;} +.col-2 {width: 125rpx;} +.col-1 {width: 62.5rpx;} + +.col-offset-12 { margin-left: 750rpx;} +.col-offset-11 { margin-left: 687.5rpx; } +.col-offset-10 { margin-left: 625rpx; } +.col-offset-9 { margin-left: 562.5rpx; } +.col-offset-8 { margin-left: 500rpx; } +.col-offset-7 { margin-left: 437.5rpx; } +.col-offset-6 { margin-left: 375rpx; } +.col-offset-5 { margin-left: 312.5rpx;} +.col-offset-4 {margin-left: 250rpx;} +.col-offset-3 {margin-left: 187.5rpx;} +.col-offset-2 {margin-left: 125rpx;} +.col-offset-1 {margin-left: 62.5rpx;} +.col-offset-0 {margin-left: 0;} + +/* 背景颜色 */ +.bg-primary { background-color: #007bff;} +.bg-hover-primary:hover{ background-color: #0062cc;} +.bg-secondary { background-color: #6c757d;} +.bg-hover-secondary:hover{ background-color: #545b62;} +.bg-success { background-color: #28a745;} +.bg-hover-success { background-color: #1e7e34;} +.bg-info { background-color: #17a2b8;} +.bg-hover-info { background-color: #117a8b;} +.bg-warning { background-color: #ffc107;} +.bg-hover-warning { background-color: #d39e00;} +.bg-danger { background-color: #dc3545;} +.bg-hover-danger{ background-color: #bd2130;} +.bg-light { background-color: #f8f9fa;} +.bg-hover-light{ background-color: #dae0e5;} +.bg-dark { background-color: #343a40;} +.bg-hover-dark { background-color: #1d2124;} +.bg-white { background-color: #ffffff;} +.bg-transparent { background-color: transparent;} +/* flex 布局 */ +.flex{ + /* #ifndef APP-PLUS-NVUE */ + display:flex; + /* #endif */ + flex-direction:row; +} +.flex-row{ flex-direction:row!important; } +.flex-column{ flex-direction:column!important; } +.flex-row-reverse{ flex-direction:row-reverse!important; } +.flex-column-reverse{ flex-direction:column-reverse!important; } +.flex-wrap{ flex-wrap:wrap;} +.flex-nowrap{ flex-wrap:nowrap;} +.justify-start{justify-content:flex-start;} +.justify-end{justify-content:flex-end;} +.justify-between{justify-content:space-between;} +.justify-center{justify-content:center;} +.align-center{ align-items: center; } +.align-stretch{ align-items: stretch; } +.align-start{ align-items: flex-start; } +.align-end{ align-items: flex-end; } +/* #ifndef APP-PLUS-NVUE */ +.content-start {align-content: flex-start;} +.content-end {align-content: flex-end;} +.content-center {align-content: center;} +.content-between {align-content: space-between;} +.content-around {align-content: space-around;} +.content-stretch {align-content: stretch;} +/* #endif */ +.flex-1{ flex: 1; } +.flex-2{ flex: 2; } +.flex-3{ flex: 3; } +.flex-4{ flex: 4; } +.flex-5{ flex: 5; } +/* #ifndef APP-PLUS-NVUE */ +.flex-shrink{ flex-shrink: 0; } +/* #endif */ + +.container { + padding-right: 20rpx; + padding-left: 20rpx; +} +/* -- 内外边距 -- */ +.m-0 { margin: 0; } +/* #ifndef APP-PLUS-NVUE */ +.m-auto{ margin: auto; } +/* #endif */ +.m-1 { margin: 10rpx; } +.m-2 { margin: 20rpx; } +.m-3 { margin: 30rpx; } +.m-4 { margin: 40rpx; } +.m-5 { margin: 50rpx; } +.mt-0 { margin-top: 0; } +/* #ifndef APP-PLUS-NVUE */ +.mt-auto { margin-top: auto; } +/* #endif */ +.mt-1 { margin-top: 10rpx; } +.mt-2 { margin-top: 20rpx; } +.mt-3 { margin-top: 30rpx; } +.mt-4 { margin-top: 40rpx; } +.mt-5 { margin-top: 50rpx; } +.mb-0 { margin-bottom: 0; } +/* #ifndef APP-PLUS-NVUE */ +.mb-auto { margin-bottom: auto; } +/* #endif */ +.mb-1 { margin-bottom: 10rpx; } +.mb-2 { margin-bottom: 20rpx; } +.mb-3 { margin-bottom: 30rpx; } +.mb-4 { margin-bottom: 40rpx; } +.mb-5 { margin-bottom: 50rpx; } +.ml-0 { margin-left: 0; } +/* #ifndef APP-PLUS-NVUE */ +.ml-auto { margin-left: auto; } +/* #endif */ +.ml-1 { margin-left: 10rpx; } +.ml-2 { margin-left: 20rpx; } +.ml-3 { margin-left: 30rpx; } +.ml-4 { margin-left: 40rpx; } +.ml-5 { margin-left: 50rpx; } +.mr-0 { margin-right: 0; } +/* #ifndef APP-PLUS-NVUE */ +.mr-auto { margin-right: auto; } +/* #endif */ +.mr-1 { margin-right: 10rpx; } +.mr-2 { margin-right: 20rpx; } +.mr-3 { margin-right: 30rpx; } +.mr-4 { margin-right: 40rpx; } +.mr-5 { margin-right: 50rpx; } +.my-0 { margin-top: 0; margin-bottom: 0; } +/* #ifndef APP-PLUS-NVUE */ +.my-auto { margin-top: auto; margin-bottom: auto; } +/* #endif */ +.my-1 { margin-top: 10rpx; margin-bottom: 10rpx; } +.my-2 { margin-top: 20rpx; margin-bottom: 20rpx; } +.my-3 { margin-top: 30rpx; margin-bottom: 30rpx; } +.my-4 { margin-top: 40rpx; margin-bottom: 40rpx; } +.my-5 { margin-top: 50rpx; margin-bottom: 50rpx; } +.mx-0 { margin-left: 0; margin-right: 0; } +/* #ifndef APP-PLUS-NVUE */ +.mx-auto { margin-left: auto; margin-right: auto; } +/* #endif */ +.mx-1 { margin-left: 10rpx; margin-right: 10rpx;} +.mx-2 { margin-left: 20rpx; margin-right: 20rpx;} +.mx-3 { margin-left: 30rpx; margin-right: 30rpx;} +.mx-4 { margin-left: 40rpx; margin-right: 40rpx;} +.mx-5 { margin-left: 50rpx; margin-right: 50rpx;} + +.p-0 { padding: 0; } +.p { padding: 5rpx; } +.p-1 { padding: 10rpx; } +.p-2 { padding: 20rpx; } +.p-3 { padding: 30rpx; } +.p-4 { padding: 40rpx; } +.p-5 { padding: 50rpx; } +.pt-0 { padding-top: 0; } +.pt { padding-top: 5rpx; } +.pt-1 { padding-top: 10rpx; } +.pt-2 { padding-top: 20rpx; } +.pt-3 { padding-top: 30rpx; } +.pt-4 { padding-top: 40rpx; } +.pt-5 { padding-top: 50rpx; } +.pb-0 { padding-bottom: 0; } +.pb-1 { padding-bottom: 10rpx; } +.pb { padding-bottom: 5rpx; } +.pb-2 { padding-bottom: 20rpx; } +.pb-3 { padding-bottom: 30rpx; } +.pb-4 { padding-bottom: 40rpx; } +.pb-5 { padding-bottom: 50rpx; } +.pl-0 { padding-left: 0; } +.pl { padding-left: 5rpx; } +.pl-1 { padding-left: 10rpx; } +.pl-2 { padding-left: 20rpx; } +.pl-3 { padding-left: 30rpx; } +.pl-4 { padding-left: 40rpx; } +.pl-5 { padding-left: 50rpx; } +.pr-0 { padding-right: 0; } +.pr { padding-right: 5rpx; } +.pr-1 { padding-right: 10rpx; } +.pr-2 { padding-right: 20rpx; } +.pr-3 { padding-right: 30rpx; } +.pr-4 { padding-right: 40rpx; } +.pr-5 { padding-right: 50rpx; } +.py-0 { padding-top: 0; padding-bottom: 0; } +.py { padding-top: 5rpx; padding-bottom: 5rpx; } +.py-1 { padding-top: 10rpx; padding-bottom: 10rpx; } +.py-2 { padding-top: 20rpx; padding-bottom: 20rpx; } +.py-3 { padding-top: 30rpx; padding-bottom: 30rpx; } +.py-4 { padding-top: 40rpx; padding-bottom: 40rpx; } +.py-5 { padding-top: 50rpx; padding-bottom: 50rpx; } +.px-0 { padding-left: 0; padding-right: 0; } +.px-1 { padding-left: 10rpx; padding-right: 10rpx;} +.px { padding-left: 5rpx; padding-right: 5rpx;} +.px-2 { padding-left: 20rpx; padding-right: 20rpx;} +.px-3 { padding-left: 30rpx; padding-right: 30rpx;} +.px-4 { padding-left: 40rpx; padding-right: 40rpx;} +.px-5 { padding-left: 50rpx; padding-right: 50rpx;} +/* 文字大小 */ +.font-small { font-size: 20upx;} +.font-sm { font-size: 25upx;} +.font { font-size: 30upx;} +.font-md { font-size: 35upx;} +.font-lg { font-size: 40upx;} +.h1{font-size:80upx; line-height:1.8;} +.h2{font-size:60upx; line-height:1.8;} +.h3{font-size:45upx; line-height:1.8;} +.h4{font-size:32upx; line-height:1.8;} +.h5{font-size:30upx; line-height:1.8;} +.h6{font-size:28upx; line-height:1.8;} +/* 文字缩进 */ +/* #ifndef APP-PLUS-NVUE */ +.text-indent{text-indent:2;} +/* #endif */ +/* 文字划线 */ +.text-through{text-decoration:line-through;} +/* 文字对齐 */ +.text-left { text-align: left;} +.text-right { text-align: right;} +.text-center { text-align: center;} +/* 文字换行溢出处理 */ +.text-ellipsis { + /* #ifndef APP-PLUS-NVUE */ + overflow: hidden;text-overflow: ellipsis;white-space: nowrap; + /* #endif */ + /* #ifdef APP-PLUS-NVUE */ + lines: 1; + /* #endif */ +} +/* 文字粗细和斜体 */ +.font-weight-light {font-weight: 300;} /*细*/ +.font-weight-lighter {font-weight: 100;}/*更细*/ +.font-weight-normal { font-weight: 400;} /*正常*/ +.font-weight-bold { font-weight: 700;} /*粗*/ +.font-weight-bolder { font-weight: bold;} /*更粗*/ +.font-italic { font-style: italic;} /*斜体*/ +/* 文字颜色 */ +.text-white {color: #ffffff;} +.text-primary {color: #007bff;} +.text-hover-primary { color: #0056b3;} +.text-secondary {color: #6c757d;} +.text-hover-secondary { color: #494f54;} +.text-success {color: #28a745;} +.text-hover-success{color: #19692c;} +.text-info { color: #17a2b8;} +.text-hover-info {color: #0f6674;} +.text-warning {color: #ffc107;} +.text-hover-warning { color: #ba8b00;} +.text-danger { color: #dc3545;} +.text-hover-danger { color: #a71d2a;} +.text-light { color: #f8f9fa;} +.text-hover-light { color: #cbd3da;} +.text-dark { color: #343a40;} +.text-hover-dark{ color: #121416;} +.text-body { color: #212529;} +.text-muted { color: #6c757d;} +.text-light-muted { color: #A9A5A0;} +.text-light-black { color: rgba(0, 0, 0, 0.5);} +.text-light-white { color: rgba(255, 255, 255, 0.5);} + + +/* 边框 */ +.border { border-width: 1rpx;border-style: solid;border-color: #dee2e6;} +.border-top { + border-top-width: 1rpx; + border-top-style: solid; + border-top-color: #dee2e6; +} +.border-right { + border-right-width: 1rpx; + border-right-style: solid; + border-right-color: #dee2e6; +} +.border-bottom { + border-bottom-width: 1rpx; + border-bottom-style: solid; + border-bottom-color: #dee2e6; +} +.border-left { + border-left-width: 1rpx; + border-left-style: solid; + border-left-color: #dee2e6; +} +.border-0 { border-width: 0!important;} +.border-top-0 { border-top-width: 0!important;} +.border-right-0 {border-right-width: 0!important;} +.border-bottom-0 {border-bottom-width: 0!important;} +.border-left-0 {border-left-width: 0!important;} +.border-primary { border-color: #007bff;} +.border-secondary {border-color: #6c757d;} +.border-light-secondary {border-color: #E9E8E5;} +.border-success {border-color: #28a745;} +.border-info {border-color: #17a2b8;} +.border-warning {border-color: #ffc107;} +.border-danger {border-color: #dc3545;} +.border-light {border-color: #f8f9fa;} +.border-dark {border-color: #343a40;} +.border-white {border-color: #FFFFFF;} +/* 圆角 */ +.rounded { border-radius: 8rpx;} +.rounded-top { + border-top-left-radius: 8rpx; + border-top-right-radius: 8rpx; +} +.rounded-right { + border-top-right-radius: 8rpx; + border-bottom-right-radius: 8rpx; +} +.rounded-bottom { + border-bottom-right-radius: 8rpx; + border-bottom-left-radius: 8rpx; +} +.rounded-left { + border-top-left-radius: 8rpx; + border-bottom-left-radius: 8rpx; + } +.rounded-circle { border-radius: 100rpx;} +.rounded-0 { border-radius: 0;} +/* 显示 */ +/* #ifndef APP-PLUS-NVUE */ +.d-none{ display: none; } +.d-inline-block{ display: inline-block; } +.d-block{ display: block; } +/* #endif */ +/* 内容溢出 */ +.overflow-hidden { overflow: hidden;} +/* 定位 */ +.position-relative { position: relative;} +.position-absolute { position: absolute;} +.position-fixed { position: fixed;} +/* 定位 - 固定顶部 */ +.fixed-top { + position: fixed; + top: 0; + right: 0; + left: 0; + z-index: 1030; +} +/* 定位 - 固定底部 */ +.fixed-bottom { + position: fixed; + right: 0; + bottom: 0; + left: 0; + z-index: 1030; +} +.top-0 { top: 0; } +.left-0 { left: 0; } +.right-0 { right: 0; } +.bottom-0 { bottom: 0; } + +/* 图标 */ +.iconfont{ + font-family:iconfont; +} \ No newline at end of file diff --git a/l-im-app-imooc-master/l-im-app-imooc/common/icon.css b/l-im-app-imooc-master/l-im-app-imooc/common/icon.css new file mode 100644 index 0000000..3c3cbd8 --- /dev/null +++ b/l-im-app-imooc-master/l-im-app-imooc/common/icon.css @@ -0,0 +1,11 @@ +@font-face {font-family: "iconfont"; + src:url('data:application/octet-stream;base64,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Hx8HpwsfH17MXiIcCw8KH24BFGUeCnINISU1RDYoHhwMIkejQRUFkycqHgQTMjobBQAAAAALAAD/XwQMA30AEwAlADEAPQBJAFUAYQBtAHkAhQCKAAABDgEHDgEUFhcWBDc+AScuAScuARcWEgcOAScuAScuATc+ATc2FgEGFjcWNic2JgcmBhcGFjcWNic2JgcmBhcGFjcWNic2JgcmBhcGFjcWNic2JgcmBgUGFjcWNic2JgcmBhcGFjcWNic2JgcmBhcGFjcWNic2JgcmBhcGFjcWNic2JgcmBgUVITUhAZh1uDccEhIcgQHnyl9HHiK2dTyW9J14PDPlmYHEOiIFHSCETVLR/ngBESIhEQEBESEiEY4CEignEwICEycoEpwCEycoEgICEignE5wBEicoEgEBEignEv5AAREiIREBAREhIhGOAhIoJxMCAhMnKBKcAhMnKBICAhIoJxOcARInKBIBARIoJxL+vwEm/toDchqVdTlQilA5+Fu7YPaCgskmEQhrUf7Dq4WQBgd/dEnGVE+IHx8H/uYhEQEBESEiEQICESIiEAEBECIjEAICECMiEAEBECIjEAICECMiEAEBECIjEAICEL0hEQEBESEhEQEBESEiEAEBECIiEAEBECIiEAEBECIiEAEBECIiEAEBECIiEAEBEO05cQAAABIA3gABAAAAAAAAABUAAAABAAAAAAABAAgAFQABAAAAAAACAAcAHQABAAAAAAADAAgAJAABAAAAAAAEAAgALAABAAAAAAAFAAsANAABAAAAAAAGAAgAPwABAAAAAAAKACsARwABAAAAAAALABMAcgADAAEECQAAACoAhQADAAEECQABABAArwADAAEECQACAA4AvwADAAEECQADABAAzQADAAEECQAEABAA3QADAAEECQAFABYA7QADAAEECQAGABABAwADAAEECQAKAFYBEwADAAEECQALACYBaQpDcmVhdGVkIGJ5IGljb25mb250Cmljb25mb250UmVndWxhcmljb25mb250aWNvbmZvbnRWZXJzaW9uIDEuMGljb25mb250R2VuZXJhdGVkIGJ5IHN2ZzJ0dGYgZnJvbSBGb250ZWxsbyBwcm9qZWN0Lmh0dHA6Ly9mb250ZWxsby5jb20ACgBDAHIAZQBhAHQAZQBkACAAYgB5ACAAaQBjAG8AbgBmAG8AbgB0AAoAaQBjAG8AbgBmAG8AbgB0AFIAZQBnAHUAbABhAHIAaQBjAG8AbgBmAG8AbgB0AGkAYwBvAG4AZgBvAG4AdABWAGUAcgBzAGkAbwBuACAAMQAuADAAaQBjAG8AbgBmAG8AbgB0AEcAZQBuAGUAcgBhAHQAZQBkACAAYgB5ACAAcwB2AGcAMgB0AHQAZgAgAGYAcgBvAG0AIABGAG8AbgB0AGUAbABsAG8AIABwAHIAbwBqAGUAYwB0AC4AaAB0AHQAcAA6AC8ALwBmAG8AbgB0AGUAbABsAG8ALgBjAG8AbQAAAAACAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADoBAgEDAQQBBQEGAQcBCAEJAQoBCwEMAQ0BDgEPARABEQESARMBFAEVARYBFwEYARkBGgEbARwBHQEeAR8BIAEhASIBIwEkASUBJgEnASgBKQEqASsBLAEtAS4BLwEwATEBMgEzATQBNQE2ATcBOAE5AToBOwAIc2hvdWNhbmcEaW5mbw9pY29uZm9udHNoYW5jaHUJZmVueGlhbmcxCzA1cXVuenVmaWxsCmZ1amluZGVyZW4Gc2VhcmNoCXlhb3lpeWFvMQRhaTYxBHNjYW4IeW91ZmFueWUFdG91c3UEbWFpbBBpY29uZm9udHhpbmd4aW5nB2xvYWRpbmcKaGVpbWluZ2RhbgZ6aXl1YW4Ja2VodXF1bnp1A3NldAl4aW56ZW5na2UGZ3VhbmJpBWdvdXd1A3p1bwt0aXNoaWppbnpoaQdwYWl6aGFvCHNoZW5neWluCGZlbnhpYW5nA2ljbwhrYW55aWthbghzb3V5aXNvdQdwaW5nbHVuB2dlbmdkdW8Ic2FveWlzYW8FamlucnUGZmFuaHVpA2FkZAVsdXlpbgZib2ZhbmcIZ2VuZ2R1bzEFeW91eGkGdHVjZW5nAm15C2Z1emhpdHVjZW5nBXF1bnp1CXNhb3lpc2FvMQZ0dXBpYW4EZmluZAV6aGlmdQtwZW5neW91cXVhbgh0YWctZmlsbAl1c2VybmV3MDQGZmFuZ2RhBmx1eWluMQhxdW5saWFvXwlxdW5saWFvXzEJcXVubGlhb18yEXF1bmxpYW8tYmlhb3FpbmdfAAAAAAA=') format('woff2') +} + +.iconfont { + font-family: "iconfont" !important; + font-size: 16px; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} \ No newline at end of file diff --git a/l-im-app-imooc-master/l-im-app-imooc/common/imSdk/lim-sdk.js b/l-im-app-imooc-master/l-im-app-imooc/common/imSdk/lim-sdk.js new file mode 100644 index 0000000..527d316 --- /dev/null +++ b/l-im-app-imooc-master/l-im-app-imooc/common/imSdk/lim-sdk.js @@ -0,0 +1,2 @@ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.imsdk=e():t.imsdk=e()}(window,(function(){return function(t){var e={};function n(r){if(e[r])return e[r].exports;var i=e[r]={i:r,l:!1,exports:{}};return t[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:r})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var i in t)n.d(r,i,function(e){return t[e]}.bind(null,i));return r},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=5)}([function(t,e,n){"use strict";var r=this&&this.__spreadArrays||function(){for(var t=0,e=0,n=arguments.length;e0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]=1e4){a.default.info(">>> send ping ;"),r=Date.now();var s=e.imClient.buildMessagePack(y.SystemCommand.PING,{});t.send(s.pack(!1))}setTimeout(i,500)}else a.default.error("heartbeatLoop exited")};setTimeout(i,500)},t.prototype.createP2PTextMessage=function(t,e){var n=new g.MessagePack(this.appId);return n.buildTxtMessagePack(this.userId,t,e),n},t.prototype.sendP2PMessage=function(t){var n=e.imClient.buildMessagePack(y.MessageCommand.MSG_P2P,t);this.conn&&this.conn.send(n.pack(!1))},t.prototype.getUserId=function(){return this.userId},t}();e.ImClient=E,e.limLogin=function(t,e,n){return r(void 0,void 0,void 0,(function(){return i(this,(function(r){return[2,new Promise((function(r,i){var o=new c.w3cwebsocket(t);o.binaryType="arraybuffer",a.default.info("limLogin");var s=setTimeout((function(){clearTimeout(s),r({success:!1,err:new Error("timeout"),conn:o})}),1e4);o.onopen=function(){if(o.readyState==c.w3cwebsocket.OPEN){"function"==typeof n.listeners.onSocketConnectEvent&&n.listeners.onSocketConnectEvent(t,e),a.default.info("开启连接");var r={userId:e.userId},i=n.buildMessagePack(9e3,r);o.send(i.pack(!1))}},o.onerror=function(t){clearTimeout(s),a.default.error(t),r({success:!1,err:t,conn:o})},o.onmessage=function(t){if("string"!=typeof t.data){clearTimeout(s);var e=new u.default(t.data).int32().int32().unpack(),n=e[0];e[1];9001==n&&r({success:!0,conn:o})}else a.default.info("Received: '"+t.data+"'")}}))]}))}))},e.getLen=function(t){for(var e=0,n=0;n=1&&r<=126||65376<=r&&r<=65439?e++:e+=3}return e},e.imClient=new E},function(t,e,n){"use strict";(function(t){e.__esModule=!0;var r=function(){function e(){}return e.getFetchToolkit=function(){var e;if(void 0!==t.fetch&&"function"==typeof t.fetch)e=t.fetch;else if("function"==typeof fetch)e=fetch;else{e=n(9).fetch}return e},e}();e.default=r}).call(this,n(2))},function(t,e,n){"use strict";(function(t){e.__esModule=!0,e.im=void 0;var r=n(3);e.im=r.imClient,"undefined"!=typeof window&&console.log("window"),void 0!==t&&console.log("global"),"undefined"!=typeof uni&&(uni.im=r.imClient)}).call(this,n(2))},function(t,e,n){"use strict";e.__esModule=!0;var r=function(){function t(t,e){this.Type_Byte=1,this.Type_Short=2,this.Type_UShort=3,this.Type_Int32=4,this.Type_UInt32=5,this.Type_String=6,this.Type_VString=7,this.Type_Int64=8,this.Type_Float=9,this.Type_Double=10,this.Type_ByteArray=11,this._offset=0,this._list=[],this._littleEndian=!1,this._org_buf=t?t.constructor==DataView?t:t.constructor==Uint8Array?new DataView(t.buffer,e):new DataView(t,e):new DataView(new Uint8Array([]).buffer),this.arrayBuf=t,this.offset=e}return t.prototype.bigEndian=function(){return this._littleEndian=!1,this},t.prototype.littleEndianfunction=function(){return this._littleEndian=!0,this},t.prototype.utf8Write=function(t,e,n){for(var r=0,i=0,o=n.length;i>6),t.setUint8(e++,128|63&r)):r<55296||r>=57344?(t.setUint8(e++,224|r>>12),t.setUint8(e++,128|r>>6&63),t.setUint8(e++,128|63&r)):(i++,r=65536+((1023&r)<<10|1023&n.charCodeAt(i)),t.setUint8(e++,240|r>>18),t.setUint8(e++,128|r>>12&63),t.setUint8(e++,128|r>>6&63),t.setUint8(e++,128|63&r))},t.prototype.int32=function(t,e){return 0==arguments.length?(this._list.push(this._org_buf.getInt32(this._offset,this._littleEndian)),this._offset+=4):(this._list.splice(null!=e?e:this._list.length,0,{t:this.Type_Int32,d:t,l:4}),this._offset+=4),this},t.prototype.uint32=function(t,e){return 0==arguments.length?(this._list.push(this._org_buf.getUint32(this._offset,this._littleEndian)),this._offset+=4):(this._list.splice(null!=e?e:this._list.length,0,{t:this.Type_UInt32,d:t,l:4}),this._offset+=4),this},t.prototype.blength=function(){return this._offset},t.prototype.string=function(t,e){if(0==arguments.length){var n=this._org_buf.getInt32(this._offset,this._littleEndian);this._offset+=4,this._list.push(this.utf8Read(this._org_buf,this._offset,n)),this._offset+=n}else{n=0;t&&(n=this.utf8Length(t)),this._list.splice(null!=e?e:this._list.length,0,{t:this.Type_String,d:t,l:n}),this._offset+=n+4}return this},t.prototype.utf8Length=function(t){for(var e=0,n=0,r=0,i=t.length;r=57344?n+=3:(r++,n+=4);return n},t.prototype.utf8Read=function(t,e,n){for(var r="",i=0,o=e,s=e+n;o=65536?(i-=65536,r+=String.fromCharCode(55296+(i>>>10),56320+(1023&i))):r+=String.fromCharCode(i)}else r+=String.fromCharCode((15&a)<<12|(63&t.getUint8(++o))<<6|(63&t.getUint8(++o))<<0);else r+=String.fromCharCode((15&a)<<6|63&t.getUint8(++o));else r+=String.fromCharCode(a)}return r},t.prototype.vstring=function(t,e,n){if(!e)throw new Error("vstring must got len argument");if(null==t||null==t){for(var r=0,i=this._offset;i0&&r++;this._list.push(this.utf8Read(this._org_buf,this._offset,r)),this._offset+=e}else this._list.splice(null!=n?n:this._list.length,0,{t:this.Type_VString,d:t,l:e}),this._offset+=e;return this},t.prototype.int64=function(t,e){return 0==arguments.length?(this._list.push(this._org_buf.getFloat64(this._offset,this._littleEndian)),this._offset+=8):(this._list.splice(null!=e?e:this._list.length,0,{t:this.Type_Int64,d:t,l:8}),this._offset+=8),this},t.prototype.float=function(t,e){return 0==arguments.length?(this._list.push(this._org_buf.getFloat32(this._offset,this._littleEndian)),this._offset+=4):(this._list.splice(null!=e?e:this._list.length,0,{t:this.Type_Float,d:t,l:4}),this._offset+=4),this},t.prototype.double=function(t,e){return 0==arguments.length?(this._list.push(this._org_buf.getFloat64(this._offset,this._littleEndian)),this._offset+=8):(this._list.splice(null!=e?e:this._list.length,0,{t:this.Type_Double,d:t,l:8}),this._offset+=8),this},t.prototype.byteArray=function(t,e,n){if(!e)throw new Error("byteArray must got len argument");if(null==t||null==t){var r=new Uint8Array(this._org_buf.buffer.slice(this._offset,this._offset+e));this._list.push(r),this._offset+=e}else this._list.splice(null!=n?n:this._list.length,0,{t:this.Type_ByteArray,d:t,l:e}),this._offset+=e;return this},t.prototype.unpack=function(){return this._list},t.prototype.packWithHead=function(){return this.pack(!0)},t.prototype.pack=function(t){this._org_buf=new DataView(new ArrayBuffer(t?this._offset+4:this._offset));var e=0;t&&(this._org_buf.setUint32(e,this._offset,this._littleEndian),e+=4);for(var n=0;n>2,o=(3&e)<<4|(n=t.charCodeAt(f++))>>4,s=(15&n)<<2|(r=t.charCodeAt(f++))>>6,a=63&r,isNaN(n)?s=a=64:isNaN(r)&&(a=64),u=u+this._keyStr.charAt(i)+this._keyStr.charAt(o)+this._keyStr.charAt(s)+this._keyStr.charAt(a);return u},decode:function(t){var e,n,r,i,o,s,a="",u=0;for(t=t.replace(/[^A-Za-z0-9+/=]/g,"");u>4,n=(15&i)<<4|(o=this._keyStr.indexOf(t.charAt(u++)))>>2,r=(3&o)<<6|(s=this._keyStr.indexOf(t.charAt(u++))),a+=String.fromCharCode(e),64!=o&&(a+=String.fromCharCode(n)),64!=s&&(a+=String.fromCharCode(r));return a=Base64._utf8_decode(a)},_utf8_encode:function(t){t=t.replace(/rn/g,"n");for(var e="",n=0;n127&&r<2048?(e+=String.fromCharCode(r>>6|192),e+=String.fromCharCode(63&r|128)):(e+=String.fromCharCode(r>>12|224),e+=String.fromCharCode(r>>6&63|128),e+=String.fromCharCode(63&r|128))}return e},_utf8_decode:function(t){for(var e="",n=0,r=0,i=0;n191&&r<224)i=t.charCodeAt(n+1),e+=String.fromCharCode((31&r)<<6|63&i),n+=2;else{i=t.charCodeAt(n+1);var o=t.charCodeAt(n+2);e+=String.fromCharCode((15&r)<<12|(63&i)<<6|63&o),n+=3}return e}},WebToolkit=function(){function WebToolkit(){}return WebToolkit.getBrowserInfo=function(){var t=navigator.userAgent.toLowerCase(),e=/edge\/[\d.]+/gi,n=/trident\/[\d.]+/gi,r=/msie\s[\d.]+/gi,i=/firefox\/[\d.]+/gi,o=/chrome\/[\d.]+/gi,s=/safari\/[\d.]+/gi,a=/opr\/[\d.]+/gi,u={code:0,system:t.split(" ")[1].split(" ")[0].split("(")[1],browser:"",browserVersion:""};return t.indexOf("trident")>0?(u.browser=t.match(n)[0].split("/")[0],u.browserVersion=t.match(n)[0].split("/")[1],u):t.indexOf("msie")>0?(u.browser=t.match(r)[0].split(" ")[0],u.browserVersion=t.match(r)[0].split(" ")[1],u):t.indexOf("edge")>0?(u.browser=t.match(e)[0].split("/")[0],u.browserVersion=t.match(e)[0].split("/")[1],u):t.indexOf("firefox")>0?(u.browser=t.match(i)[0].split("/")[0],u.browserVersion=t.match(i)[0].split("/")[1],u):t.indexOf("opr")>0?(u.browser=t.match(a)[0].split("/")[0],u.browserVersion=t.match(a)[0].split("/")[1],u):t.indexOf("safari")>0&&t.indexOf("chrome")<0?(u.browser=t.match(s)[0].split("/")[0],u.browserVersion=t.match(s)[0].split("/")[1],u):t.indexOf("chrome")>0?(u.browser=t.match(o)[0].split("/")[0],u.browserVersion=t.match(o)[0].split("/")[1],u):(u.code=-1,u)},WebToolkit.getWxappInfo=function(){return{system:"WXAPP",browser:"WXAPP",browserVersion:"1.0"}},WebToolkit.getReactNativeInfo=function(){return{system:"RNNative",browser:"RNNative",browserVersion:"1.0"}},WebToolkit.getUniAppInfo=function(){return{system:"UNIAPP",browser:"UNIAPP",browserVersion:"1.0"}},WebToolkit.loadJS=function(t,e){var n=document.createElement("script"),r=e||function(){};n.type="text/javascript";var i=!1;for(var o in document.getElementsByTagName("head")[0].children){var s=document.getElementsByTagName("head")[0].children[o];void 0!==s.outerHTML&&s.outerHTML.indexOf(t)>=0&&(i=!0)}i?r():(n.readyState?n.onreadystatechange=function(){"loaded"!=n.readyState&&"complete"!=n.readyState||(n.onreadystatechange=null,r())}:n.onload=function(){r()},n.src=t,document.getElementsByTagName("head")[0].appendChild(n))},WebToolkit.getIpInfoByFetch=function(callback){var url="http://pv.sohu.com/cityjson?ie=utf-8",fetch=Fetch_1.default.getFetchToolkit(),request={method:"GET",mode:"cors",headers:{"Content-Type":"application/json"}};return fetch(url,request).then((function(t){return t.text()})).then((function(res){if("function"==typeof callback){var currentCity=eval("_current_city="+res.replace("var returnCitySN = ",""));callback(currentCity)}})).catch((function(t){Logger_1.default.trace(t)}))},WebToolkit.getIpInfoByInsertScript=function(t){WebToolkit.loadJS("http://pv.sohu.com/cityjson?ie=utf-8",(function(){t(window.returnCitySN)}))},WebToolkit.getIpInfo=function(t){WebToolkit.getIpInfoByFetch(t)},WebToolkit.getDeviceInfo=function(){return WebToolkit.getUniAppInfo()},WebToolkit.base64Encode=function(t){return Base64.encode(t)},WebToolkit.base64Decode=function(t){return Base64.decode(t)},WebToolkit}();exports.default=WebToolkit},function(t,e,n){"use strict";n.r(e),n.d(e,"Headers",(function(){return p})),n.d(e,"Request",(function(){return v})),n.d(e,"Response",(function(){return w})),n.d(e,"DOMException",(function(){return I})),n.d(e,"fetch",(function(){return O}));var r="undefined"!=typeof globalThis&&globalThis||"undefined"!=typeof self&&self||void 0!==r&&r,i="URLSearchParams"in r,o="Symbol"in r&&"iterator"in Symbol,s="FileReader"in r&&"Blob"in r&&function(){try{return new Blob,!0}catch(t){return!1}}(),a="FormData"in r,u="ArrayBuffer"in r;if(u)var f=["[object Int8Array]","[object Uint8Array]","[object Uint8ClampedArray]","[object Int16Array]","[object Uint16Array]","[object Int32Array]","[object Uint32Array]","[object Float32Array]","[object Float64Array]"],l=ArrayBuffer.isView||function(t){return t&&f.indexOf(Object.prototype.toString.call(t))>-1};function c(t){if("string"!=typeof t&&(t=String(t)),/[^a-z0-9\-#$%&'*+.^_`|~!]/i.test(t)||""===t)throw new TypeError('Invalid character in header field name: "'+t+'"');return t}function h(t){return"string"!=typeof t&&(t=String(t)),t}function d(t){var e={next:function(){var e=t.shift();return{done:void 0===e,value:e}}};return o&&(e[Symbol.iterator]=function(){return e}),e}function p(t){this.map={},t instanceof p?t.forEach((function(t,e){this.append(e,t)}),this):Array.isArray(t)?t.forEach((function(t){this.append(t[0],t[1])}),this):t&&Object.getOwnPropertyNames(t).forEach((function(e){this.append(e,t[e])}),this)}function _(t){if(t.bodyUsed)return Promise.reject(new TypeError("Already read"));t.bodyUsed=!0}function y(t){return new Promise((function(e,n){t.onload=function(){e(t.result)},t.onerror=function(){n(t.error)}}))}function g(t){var e=new FileReader,n=y(e);return e.readAsArrayBuffer(t),n}function b(t){if(t.slice)return t.slice(0);var e=new Uint8Array(t.byteLength);return e.set(new Uint8Array(t)),e.buffer}function E(){return this.bodyUsed=!1,this._initBody=function(t){var e;this.bodyUsed=this.bodyUsed,this._bodyInit=t,t?"string"==typeof t?this._bodyText=t:s&&Blob.prototype.isPrototypeOf(t)?this._bodyBlob=t:a&&FormData.prototype.isPrototypeOf(t)?this._bodyFormData=t:i&&URLSearchParams.prototype.isPrototypeOf(t)?this._bodyText=t.toString():u&&s&&((e=t)&&DataView.prototype.isPrototypeOf(e))?(this._bodyArrayBuffer=b(t.buffer),this._bodyInit=new Blob([this._bodyArrayBuffer])):u&&(ArrayBuffer.prototype.isPrototypeOf(t)||l(t))?this._bodyArrayBuffer=b(t):this._bodyText=t=Object.prototype.toString.call(t):this._bodyText="",this.headers.get("Content-Type")||("string"==typeof t?this.headers.set("Content-Type","text/plain;charset=UTF-8"):this._bodyBlob&&this._bodyBlob.type?this.headers.set("Content-Type",this._bodyBlob.type):i&&URLSearchParams.prototype.isPrototypeOf(t)&&this.headers.set("Content-Type","application/x-www-form-urlencoded;charset=UTF-8"))},s&&(this.blob=function(){var t=_(this);if(t)return t;if(this._bodyBlob)return Promise.resolve(this._bodyBlob);if(this._bodyArrayBuffer)return Promise.resolve(new Blob([this._bodyArrayBuffer]));if(this._bodyFormData)throw new Error("could not read FormData body as blob");return Promise.resolve(new Blob([this._bodyText]))},this.arrayBuffer=function(){if(this._bodyArrayBuffer){var t=_(this);return t||(ArrayBuffer.isView(this._bodyArrayBuffer)?Promise.resolve(this._bodyArrayBuffer.buffer.slice(this._bodyArrayBuffer.byteOffset,this._bodyArrayBuffer.byteOffset+this._bodyArrayBuffer.byteLength)):Promise.resolve(this._bodyArrayBuffer))}return this.blob().then(g)}),this.text=function(){var t,e,n,r=_(this);if(r)return r;if(this._bodyBlob)return t=this._bodyBlob,e=new FileReader,n=y(e),e.readAsText(t),n;if(this._bodyArrayBuffer)return Promise.resolve(function(t){for(var e=new Uint8Array(t),n=new Array(e.length),r=0;r-1?r:n),this.mode=e.mode||this.mode||null,this.signal=e.signal||this.signal,this.referrer=null,("GET"===this.method||"HEAD"===this.method)&&i)throw new TypeError("Body not allowed for GET or HEAD requests");if(this._initBody(i),!("GET"!==this.method&&"HEAD"!==this.method||"no-store"!==e.cache&&"no-cache"!==e.cache)){var o=/([?&])_=[^&]*/;if(o.test(this.url))this.url=this.url.replace(o,"$1_="+(new Date).getTime());else{this.url+=(/\?/.test(this.url)?"&":"?")+"_="+(new Date).getTime()}}}function S(t){var e=new FormData;return t.trim().split("&").forEach((function(t){if(t){var n=t.split("="),r=n.shift().replace(/\+/g," "),i=n.join("=").replace(/\+/g," ");e.append(decodeURIComponent(r),decodeURIComponent(i))}})),e}function T(t){var e=new p;for(var n in t)e.append(n,t[n]);return e}function w(t,e){if(!(this instanceof w))throw new TypeError('Please use the "new" operator, this DOM object constructor cannot be called as a function.');e||(e={}),this.type="default",this.status=void 0===e.status?200:e.status,this.ok=this.status>=200&&this.status<300,this.statusText=void 0===e.statusText?"":""+e.statusText,this.headers=new p(e.headers),this.url=e.url||"",this._initBody(t)}v.prototype.clone=function(){return new v(this,{body:this._bodyInit})},E.call(v.prototype),E.call(w.prototype),w.prototype.clone=function(){return new w(this._bodyInit,{status:this.status,statusText:this.statusText,headers:new p(this.headers),url:this.url})},w.error=function(){var t=new w(null,{status:0,statusText:""});return t.type="error",t};var C=[301,302,303,307,308];w.redirect=function(t,e){if(-1===C.indexOf(e))throw new RangeError("Invalid status code");return new w(null,{status:e,headers:{location:t}})};var I=r.DOMException;try{new I}catch(t){(I=function(t,e){this.message=t,this.name=e;var n=Error(t);this.stack=n.stack}).prototype=Object.create(Error.prototype),I.prototype.constructor=I}function O(t,e){return new Promise((function(n,i){var o=new v(t,e);if(o.signal&&o.signal.aborted)return i(new I("Aborted","AbortError"));function s(t){try{if("object"==typeof t)return JSON.stringify(t);if("string"==typeof t)return t}catch(t){}return t.toString()}let a=void 0===o._bodyInit?null:o._bodyInit;o.headers.hasOwnProperty("Content-Type")&&o.headers["Content-Type"].indexOf("application/json")>=0&&"POST"===o.method.toUpperCase()&&(a=JSON.parse(a));const u=uni.request({url:function(t){try{return""===t&&r.location.href?r.location.href:t}catch(e){return t}}(o.url),method:o.method,data:a,header:o.headers.map,complete:t=>{if(o.signal&&o.signal.removeEventListener("abort",f),t.errMsg.indexOf("fail")>=0)setTimeout((function(){i(new TypeError("Network request failed"))}),0);else{var e={status:t.statusCode,statusText:t.data?s(t.data):"",headers:T(t.header||{})};e.url=e.headers.get("X-Request-URL");var r=e.statusText;setTimeout((function(){n(new w(r,e))}),0)}}});function f(){u.abort()}o.signal&&o.signal.addEventListener("abort",f)}))}O.polyfill=!0,r.fetch||(r.fetch=O,r.Headers=p,r.Request=v,r.Response=w)},function(t,e,n){var r;if("object"==typeof globalThis)r=globalThis;else try{r=n(11)}catch(t){}finally{if(r||"undefined"==typeof window||(r=window),!r)throw new Error("Could not determine global this")}var i=r.WebSocket||r.MozWebSocket,o=n(12);function s(t,e){return e?new i(t,e):new i(t)}i&&["CONNECTING","OPEN","CLOSING","CLOSED"].forEach((function(t){Object.defineProperty(s,t,{get:function(){return i[t]}})})),t.exports={w3cwebsocket:i?s:null,version:o}},function(t,e){var n=function(){if("object"==typeof self&&self)return self;if("object"==typeof window&&window)return window;throw new Error("Unable to resolve global `this`")};t.exports=function(){if(this)return this;if("object"==typeof globalThis&&globalThis)return globalThis;try{Object.defineProperty(Object.prototype,"__global__",{get:function(){return this},configurable:!0})}catch(t){return n()}try{return __global__||n()}finally{delete Object.prototype.__global__}}()},function(t,e,n){t.exports=n(13).version},function(t){t.exports=JSON.parse('{"name":"websocket","description":"Websocket Client & Server Library implementing the WebSocket protocol as specified in RFC 6455.","keywords":["websocket","websockets","socket","networking","comet","push","RFC-6455","realtime","server","client"],"author":"Brian McKelvey (https://github.com/theturtle32)","contributors":["Iñaki Baz Castillo (http://dev.sipdoc.net)"],"version":"1.0.34","repository":{"type":"git","url":"https://github.com/theturtle32/WebSocket-Node.git"},"homepage":"https://github.com/theturtle32/WebSocket-Node","engines":{"node":">=4.0.0"},"dependencies":{"bufferutil":"^4.0.1","debug":"^2.2.0","es5-ext":"^0.10.50","typedarray-to-buffer":"^3.1.5","utf-8-validate":"^5.0.2","yaeti":"^0.0.6"},"devDependencies":{"buffer-equal":"^1.0.0","gulp":"^4.0.2","gulp-jshint":"^2.0.4","jshint-stylish":"^2.2.1","jshint":"^2.0.0","tape":"^4.9.1"},"config":{"verbose":false},"scripts":{"test":"tape test/unit/*.js","gulp":"gulp"},"main":"index","directories":{"lib":"./lib"},"browser":"lib/browser.js","license":"Apache-2.0"}')},function(t,e,n){"use strict";e.__esModule=!0,e.RequestBase=void 0;var r=function(t,e,n){this.appId=t,this.clientType=e,this.imei=n};e.RequestBase=r},function(t,e,n){"use strict";e.__esModule=!0,e.RequestParams=void 0;var r=function(t,e,n){this.appId=t,this.identifier=e,this.userSign=n};e.RequestParams=r},function(t,e,n){"use strict";e.__esModule=!0;var r=n(0),i=n(3),o=n(17),s=n(1),a=n(4),u=function(){function t(t){this.url="",this.url=t}return t.prototype.call=function(t,e,n){var o=i.imClient.userId;r.default.info(o);var a=this.url+t;if(null!=e){var u=this.setQueryConfig(e);console.log(u),a+=u}var f={method:"POST",headers:{"Content-Type":"application/json"},mode:"cors",body:s.default.json(n)};return this.httpFetch(a,f)},t.prototype.setQueryConfig=function(t){var e="?";for(var n in t)e+=n+"="+t[n]+"&";return e=e.substring(0,e.length-1)},t.prototype.httpFetch=function(t,e){var n=this;return console.log("httpFetch"),a.default.getFetchToolkit()(t,e).then((function(t){return console.log(t),t.json()})).then((function(i){r.default.info("==> ["+e.method+"] "+t+" back:"+s.default.json(i));var o=n.response2ApiResponse(i);return o.isFailed()?Promise.reject(o):Promise.resolve(o)}))},t.prototype.response2ApiResponse=function(t){var e=new o.default(!0);return e.data=t.data,e.msg=t.msg,e.code=t.code,e},t}();e.default=u},function(t,e,n){"use strict";e.__esModule=!0;var r=function(){function t(t){void 0===t&&(t=!1),this.msg="",this.data=null,t&&(this.code=200)}return t.prototype.isSucceed=function(){return 200===this.code},t.prototype.isFailed=function(){return!this.isSucceed()},t}();e.default=r},function(t,e,n){"use strict";var r,i,o,s,a,u;e.__esModule=!0,e.ConversationEventCommand=e.UserEventCommand=e.SystemCommand=e.GroupCommand=e.FriendShipCommand=e.MessageCommand=void 0,function(t){t[t.MSG_P2P=1103]="MSG_P2P",t[t.MSG_P2P_SYNC=1108]="MSG_P2P_SYNC",t[t.MSG_READED=1106]="MSG_READED",t[t.MSG_RECIVE_ACK=1107]="MSG_RECIVE_ACK",t[t.MSG_ACK=1046]="MSG_ACK",t[t.MSG_RECALL=1050]="MSG_RECALL",t[t.MSG_RECALL_NOTIFY=1052]="MSG_RECALL_NOTIFY",t[t.MSG_RECALL_ACK=1051]="MSG_RECALL_ACK",t[t.MSG_READED_NOTIFY=1053]="MSG_READED_NOTIFY"}(r||(r={})),e.MessageCommand=r,function(t){t[t.FRIEND_ADD=3e3]="FRIEND_ADD",t[t.FRIEND_UPDATE=3001]="FRIEND_UPDATE",t[t.FRIEND_DELETE=3002]="FRIEND_DELETE",t[t.FRIEND_REQUEST=3003]="FRIEND_REQUEST",t[t.FRIEND_REQUEST_READ=3004]="FRIEND_REQUEST_READ",t[t.FRIEND_REQUEST_APPROVER=3005]="FRIEND_REQUEST_APPROVER",t[t.FRIEND_BLACK_ADD=3010]="FRIEND_BLACK_ADD",t[t.FRIEND_BLACK_DELETE=3011]="FRIEND_BLACK_DELETE",t[t.FRIEND_GROUP_ADD=3012]="FRIEND_GROUP_ADD",t[t.FRIEND_GROUP_DELETE=3013]="FRIEND_GROUP_DELETE",t[t.FRIEND_GROUP_MEMBER_ADD=3014]="FRIEND_GROUP_MEMBER_ADD",t[t.FRIEND_GROUP_MEMBER_DELETE=3015]="FRIEND_GROUP_MEMBER_DELETE"}(i||(i={})),e.FriendShipCommand=i,function(t){t[t.JOIN_GROUP=2e3]="JOIN_GROUP",t[t.ADDED_MEMBER=2001]="ADDED_MEMBER",t[t.CREATED_GROUP=2002]="CREATED_GROUP",t[t.UPDATED_GROUP=2003]="UPDATED_GROUP",t[t.EXIT_GROUP=2004]="EXIT_GROUP",t[t.UPDATED_MEMBER=2005]="UPDATED_MEMBER",t[t.DELETED_MEMBER=2006]="DELETED_MEMBER",t[t.DESTROY_GROUP=2007]="DESTROY_GROUP",t[t.TRANSFER_GROUP=2008]="TRANSFER_GROUP",t[t.MUTE_GROUP=2009]="MUTE_GROUP",t[t.SPEAK_GOUP_MEMBER=2010]="SPEAK_GOUP_MEMBER",t[t.MSG_GROUP=2104]="MSG_GROUP",t[t.MSG_GROUP_SYNC=2105]="MSG_GROUP_SYNC",t[t.GROUP_MSG_ACK=2047]="GROUP_MSG_ACK"}(o||(o={})),e.GroupCommand=o,function(t){t[t.PING=9999]="PING",t[t.LOGIN=9e3]="LOGIN",t[t.LOGINACK=9001]="LOGINACK",t[t.MUTUALLOGIN=9002]="MUTUALLOGIN",t[t.LOGOUT=9003]="LOGOUT"}(s||(s={})),e.SystemCommand=s,function(t){t[t.USER_MODIFY=4e3]="USER_MODIFY",t[t.USER_ONLINE_STATUS_CHANGE=4001]="USER_ONLINE_STATUS_CHANGE",t[t.USER_ONLINE_STATUS_SUBSCRIBE=4002]="USER_ONLINE_STATUS_SUBSCRIBE",t[t.PULL_USER_ONLINE_STATUS=4003]="PULL_USER_ONLINE_STATUS",t[t.USER_ONLINE_STATUS_CHANGE_NOTIFY=4004]="USER_ONLINE_STATUS_CHANGE_NOTIFY"}(a||(a={})),e.UserEventCommand=a,function(t){t[t.CONVERSATION_DELETE=5e3]="CONVERSATION_DELETE",t[t.CONVERSATION_UPDATE=5001]="CONVERSATION_UPDATE"}(u||(u={})),e.ConversationEventCommand=u},function(t,e,n){"use strict";e.__esModule=!0,e.MessagePack=void 0;var r=n(1),i=function(){function t(t){this.messageId=r.default.uuid(),this.appId=t,this.messageRandom=this.RangeInteger(0,1e4),this.messageTime=Date.parse((new Date).toString())}return t.prototype.RangeInteger=function(t,e){var n=e-t;return Math.floor(Math.random()*n)+t},t.prototype.buildTxtMessagePack=function(t,e,n){this.fromId=t,this.toId=e;var i={type:1,content:n};this.messageBody=r.default.json(i)},t}();e.MessagePack=i}])})); +//# sourceMappingURL=lim-sdk.js.map \ No newline at end of file diff --git a/l-im-app-imooc-master/l-im-app-imooc/common/imSdk/lim-sdk.js.map b/l-im-app-imooc-master/l-im-app-imooc/common/imSdk/lim-sdk.js.map new file mode 100644 index 0000000..09cf8d6 --- /dev/null +++ b/l-im-app-imooc-master/l-im-app-imooc/common/imSdk/lim-sdk.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack://imsdk/webpack/universalModuleDefinition","webpack://imsdk/webpack/bootstrap","webpack://imsdk/./src/lim/log/Logger.ts","webpack://imsdk/./src/lim/common/utils.ts","webpack://imsdk/(webpack)/buildin/global.js","webpack://imsdk/./src/lim/core/ImClient.ts","webpack://imsdk/./src/lim/common/Fetch.ts","webpack://imsdk/./src/lim.ts","webpack://imsdk/./src/lim/codec/ByteBuffer.ts","webpack://imsdk/./src/lim/pack/LoginPack.ts","webpack://imsdk/./src/lim/common/WebToolkit.ts","webpack://imsdk/./src/lim/uniapp/http/uni-fetch.js","webpack://imsdk/./node_modules/websocket/lib/browser.js","webpack://imsdk/./node_modules/es5-ext/global.js","webpack://imsdk/./node_modules/websocket/lib/version.js","webpack://imsdk/./src/lim/model/RequestBase.ts","webpack://imsdk/./src/lim/model/RequestParams.ts","webpack://imsdk/./src/lim/core/HttpApi.ts","webpack://imsdk/./src/lim/model/ApiResponse.ts","webpack://imsdk/./src/lim/common/Command.ts","webpack://imsdk/./src/lim/pack/MessagePack.ts"],"names":["root","factory","exports","module","define","amd","window","installedModules","__webpack_require__","moduleId","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","__spreadArrays","this","il","arguments","length","Array","k","a","j","jl","Logger","info","message","optionalParams","_i","debug","console","apply","Date","toISOString","infoTag","tag","error","errorTag","trace","e","Error","undefined","stack","Beans","to","target","JSON","parse","stringify","bean","json","copy","replace","replaceJSON","v","toMapByKey","arrs","result","forEach","strEmpty","strNotEmpty","isEmpty","str","uuid","Math","random","toString","slice","getTime","g","Function","__awaiter","thisArg","_arguments","P","generator","Promise","resolve","reject","fulfilled","step","next","rejected","done","then","__generator","body","f","y","_","label","sent","trys","ops","verb","iterator","op","TypeError","pop","push","imClient","getLen","limLogin","ImClient","sleep","State","TimeUnit","Logger_1","ByteBuffer_1","LoginPack_1","WebToolkit_1","websocket_1","RequestBase_1","RequestParams_1","HttpApi_1","utils_1","Command_1","MessagePack_1","firstMonitorSocket","second","Unit","Second","_a","setTimeout","url","version","clientType","listeners","state","INIT","lastOfflineMessageSequence","offlineMessageList","httpUrl","getRequestBase","RequestBase","appId","imei","isInit","CONNECTED","getRequestParams","RequestParams","userId","userSign","init","callback","self","resp","ip","port","req","success","err","conn","_this","_b","getDeviceInfo","system","imeiLength","log","isFailed","data","LoginPack","onerror","onSocketErrorEvent","errorHandler","onclose","CLOSEING","onSocketCloseEvent","reason","onmessage","evt","bytebuf","byteBuffer","int32","unpack","command","bodyLen","msgBody","vstring","MessageCommand","MSG_P2P","onP2PMessage","onTestMessage","heartbeatLoop","onLogin","buildMessagePack","messagePack","jsonData","pack","index","error_1","CLOSED","RECONNECTING","onSocketReConnectEvent","onSocketReConnectSuccessEvent","getSingleUserInfo","uid","syncGetUserInfo","api","userIds","getUserInfo","getAllFriend","fromId","start","now","loop","pingPack","SystemCommand","PING","send","createP2PTextMessage","text","MessagePack","buildTxtMessagePack","sendP2PMessage","p2pPack","getUserId","w3cwebsocket","binaryType","tr","clearTimeout","onopen","readyState","OPEN","onSocketConnectEvent","loginPack","len","charCodeAt","Fetch","getFetchToolkit","httpFetch","global","fetch","im","ImClient_1","uni","ByteBuffer","arrayBuf","offset","Type_Byte","Type_Short","Type_UShort","Type_Int32","Type_UInt32","Type_String","Type_VString","Type_Int64","Type_Float","Type_Double","Type_ByteArray","_offset","_list","_littleEndian","_org_buf","constructor","DataView","Uint8Array","buffer","bigEndian","littleEndianfunction","utf8Write","view","setUint8","val","getInt32","splice","uint32","getUint32","blength","string","utf8Read","utf8Length","chr","end","byte","getUint8","String","fromCharCode","vlen","int64","getFloat64","float","getFloat32","double","byteArray","arr","packWithHead","ifHead","ArrayBuffer","setUint32","setInt8","setInt16","setUint16","setInt32","setFloat64","setFloat32","indx","getAvailable","byteLength","Fetch_1","Base64","_keyStr","encode","u","_utf8_encode","isNaN","charAt","decode","indexOf","_utf8_decode","c2","c3","WebToolkit","getBrowserInfo","agent","navigator","userAgent","toLowerCase","REGSTR_EDGE","REGSTR_IE","OLD_IE","REGSTR_FF","REGSTR_CHROME","REGSTR_SAF","REGSTR_OPERA","code","split","browser","browserVersion","match","getWxappInfo","getReactNativeInfo","getUniAppInfo","loadJS","script","document","createElement","fn","type","exist","getElementsByTagName","children","dom","outerHTML","onreadystatechange","onload","src","appendChild","getIpInfoByFetch","request","method","headers","response","res","currentCity","eval","getIpInfoByInsertScript","getIpInfo","base64Encode","base64Decode","globalThis","support","Blob","viewClasses","isArrayBufferView","isView","obj","normalizeName","test","normalizeValue","iteratorFor","items","shift","Headers","map","append","isArray","header","getOwnPropertyNames","consumed","bodyUsed","fileReaderReady","reader","readBlobAsArrayBuffer","blob","FileReader","promise","readAsArrayBuffer","bufferClone","buf","set","Body","_initBody","_bodyInit","_bodyText","isPrototypeOf","_bodyBlob","FormData","_bodyFormData","URLSearchParams","_bodyArrayBuffer","arrayBuffer","isConsumed","byteOffset","readAsText","chars","join","readArrayBufferAsText","formData","oldValue","has","keys","values","entries","methods","Request","input","options","upcased","credentials","signal","toUpperCase","referrer","cache","reParamSearch","form","trim","bytes","decodeURIComponent","parseUniappHeaders","rawHeaders","Response","bodyInit","status","ok","statusText","clone","redirectStatuses","redirect","RangeError","location","DOMException","aborted","toStr","rawBody","requestTask","href","fixUrl","complete","removeEventListener","abortXhr","errMsg","statusCode","abort","addEventListener","polyfill","_globalThis","NativeWebSocket","WebSocket","MozWebSocket","websocket_version","W3CWebSocket","uri","protocols","prop","naiveFallback","configurable","__global__","identifier","ApiResponse_1","HttpApi","params","reqUrl","paramStr","setQueryConfig","_str","substring","rnfetch1","response2ApiResponse","apiResponse","msg","ApiResponse","succeed","isSucceed","FriendShipCommand","GroupCommand","UserEventCommand","ConversationEventCommand","messageId","messageRandom","RangeInteger","messageTime","min","max","range","floor","toId","content","messageBody"],"mappings":"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","file":"lim-sdk.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"imsdk\"] = factory();\n\telse\n\t\troot[\"imsdk\"] = factory();\n})(window, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 5);\n","\"use strict\";\r\nvar __spreadArrays = (this && this.__spreadArrays) || function () {\r\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\r\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\r\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\r\n r[k] = a[j];\r\n return r;\r\n};\r\nexports.__esModule = true;\r\nvar Logger = /** @class */ (function () {\r\n function Logger() {\r\n }\r\n Logger.info = function (message) {\r\n var optionalParams = [];\r\n for (var _i = 1; _i < arguments.length; _i++) {\r\n optionalParams[_i - 1] = arguments[_i];\r\n }\r\n if (Logger.debug) {\r\n console.info.apply(console, __spreadArrays([new Date().toISOString() + \" : \" + message], optionalParams));\r\n }\r\n };\r\n Logger.infoTag = function (tag, message) {\r\n var optionalParams = [];\r\n for (var _i = 2; _i < arguments.length; _i++) {\r\n optionalParams[_i - 2] = arguments[_i];\r\n }\r\n if (Logger.debug) {\r\n console.info.apply(console, __spreadArrays([new Date().toISOString() + \" \" + tag + \" : \" + message], optionalParams));\r\n }\r\n };\r\n Logger.error = function (message) {\r\n var optionalParams = [];\r\n for (var _i = 1; _i < arguments.length; _i++) {\r\n optionalParams[_i - 1] = arguments[_i];\r\n }\r\n if (Logger.debug) {\r\n console.error.apply(console, __spreadArrays([new Date().toISOString() + \" : \" + message], optionalParams));\r\n }\r\n };\r\n Logger.errorTag = function (tag, message) {\r\n var optionalParams = [];\r\n for (var _i = 2; _i < arguments.length; _i++) {\r\n optionalParams[_i - 2] = arguments[_i];\r\n }\r\n if (Logger.debug) {\r\n console.error.apply(console, __spreadArrays([new Date().toISOString() + \" \" + tag + \" : \" + message], optionalParams));\r\n }\r\n };\r\n Logger.trace = function (e) {\r\n if (Logger.debug) {\r\n if (e instanceof Error) {\r\n console.error(e.message + \" \\n \" + (e.stack !== undefined ? e.stack : ''));\r\n }\r\n else {\r\n console.error(e);\r\n }\r\n }\r\n };\r\n Logger.debug = true;\r\n return Logger;\r\n}());\r\nexports[\"default\"] = Logger;\r\n","\"use strict\";\r\nexports.__esModule = true;\r\nvar Beans = /** @class */ (function () {\r\n function Beans() {\r\n }\r\n Beans.to = function (target) {\r\n return JSON.parse(JSON.stringify(target));\r\n };\r\n Beans.bean = function (json) {\r\n return JSON.parse(json);\r\n };\r\n Beans.copy = function (target) {\r\n return Beans.to(target);\r\n };\r\n Beans.replace = function (target, replaceJSON) {\r\n var r = Beans.to(target);\r\n for (var v in replaceJSON) {\r\n r[v] = replaceJSON[v];\r\n }\r\n return r;\r\n };\r\n Beans.toMapByKey = function (arrs, key) {\r\n var result = {};\r\n arrs.forEach(function (v) {\r\n if (v.hasOwnProperty(key)) {\r\n result[key] = v;\r\n }\r\n });\r\n return result;\r\n };\r\n Beans.json = function (target) {\r\n return JSON.stringify(target);\r\n };\r\n Beans.strEmpty = function (s) {\r\n return !!s;\r\n };\r\n Beans.strNotEmpty = function (s) {\r\n return !s;\r\n };\r\n Beans.isEmpty = function (str) {\r\n if (str === null ||\r\n str === '' ||\r\n str === undefined ||\r\n str.length === 0) {\r\n return true;\r\n }\r\n else {\r\n return false;\r\n }\r\n };\r\n Beans.uuid = function () {\r\n return (Math.random() * 36).toString(36).slice(2) + new Date().getTime().toString();\r\n };\r\n return Beans;\r\n}());\r\nexports[\"default\"] = Beans;\r\n","var g;\n\n// This works in non-strict mode\ng = (function() {\n\treturn this;\n})();\n\ntry {\n\t// This works if eval is allowed (see CSP)\n\tg = g || new Function(\"return this\")();\n} catch (e) {\n\t// This works if the window reference is available\n\tif (typeof window === \"object\") g = window;\n}\n\n// g can still be undefined, but nothing to do about it...\n// We return undefined, instead of nothing here, so it's\n// easier to handle this case. if(!global) { ...}\n\nmodule.exports = g;\n","\"use strict\";\r\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n};\r\nvar __generator = (this && this.__generator) || function (thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n};\r\nexports.__esModule = true;\r\nexports.imClient = exports.getLen = exports.limLogin = exports.ImClient = exports.sleep = exports.State = void 0;\r\nvar Logger_1 = require(\"../log/Logger\");\r\nvar ByteBuffer_1 = require(\"../codec/ByteBuffer\");\r\nvar LoginPack_1 = require(\"../pack/LoginPack\");\r\nvar WebToolkit_1 = require(\"../common/WebToolkit\");\r\nvar websocket_1 = require(\"websocket\");\r\nvar RequestBase_1 = require(\"../model/RequestBase\");\r\nvar RequestParams_1 = require(\"../model/RequestParams\");\r\nvar HttpApi_1 = require(\"./HttpApi\");\r\nvar utils_1 = require(\"../common/utils\");\r\nvar Command_1 = require(\"../common/Command\");\r\nvar MessagePack_1 = require(\"../pack/MessagePack\");\r\nvar loginTimeout = 10 * 1000; // 10 seconds\r\nvar heartbeatInterval = 10 * 1000; // seconds\r\nvar firstMonitorSocket = false; // 第一次监听socket\r\nvar State;\r\n(function (State) {\r\n State[State[\"INIT\"] = 0] = \"INIT\";\r\n State[State[\"CONNECTING\"] = 1] = \"CONNECTING\";\r\n State[State[\"CONNECTED\"] = 2] = \"CONNECTED\";\r\n State[State[\"RECONNECTING\"] = 3] = \"RECONNECTING\";\r\n State[State[\"CLOSEING\"] = 4] = \"CLOSEING\";\r\n State[State[\"CLOSED\"] = 5] = \"CLOSED\";\r\n})(State = exports.State || (exports.State = {}));\r\nvar TimeUnit;\r\n(function (TimeUnit) {\r\n TimeUnit[TimeUnit[\"Second\"] = 1000] = \"Second\";\r\n TimeUnit[TimeUnit[\"Millisecond\"] = 1] = \"Millisecond\";\r\n})(TimeUnit || (TimeUnit = {}));\r\nexports.sleep = function (second, Unit) {\r\n if (Unit === void 0) { Unit = TimeUnit.Second; }\r\n return __awaiter(void 0, void 0, void 0, function () {\r\n return __generator(this, function (_a) {\r\n return [2 /*return*/, new Promise(function (resolve, _) {\r\n setTimeout(function () {\r\n resolve();\r\n }, second * Unit);\r\n })];\r\n });\r\n });\r\n};\r\nvar ImClient = /** @class */ (function () {\r\n function ImClient() {\r\n this.url = \"\";\r\n this.version = 1;\r\n this.clientType = 1;\r\n this.listeners = null;\r\n this.state = State.INIT;\r\n this.lastOfflineMessageSequence = 0;\r\n this.offlineMessageList = new Array();\r\n this.httpUrl = \"\"; //http://127.0.0.1:8000/v1\r\n }\r\n ImClient.prototype.getRequestBase = function () {\r\n return new RequestBase_1.RequestBase(this.appId, this.clientType, this.imei);\r\n };\r\n ImClient.prototype.isInit = function () {\r\n return this.state == State.CONNECTED;\r\n };\r\n ImClient.prototype.getRequestParams = function () {\r\n return new RequestParams_1.RequestParams(this.appId, this.userId, this.userSign);\r\n };\r\n ImClient.prototype.init = function (httpUrl, appId, userId, userSign, listeners, callback) {\r\n return __awaiter(this, void 0, void 0, function () {\r\n var self, api, resp, ip, port, req, _a, success, err, conn;\r\n var _this = this;\r\n return __generator(this, function (_b) {\r\n switch (_b.label) {\r\n case 0:\r\n self = this;\r\n self.httpUrl = httpUrl;\r\n self.appId = appId;\r\n self.listeners = listeners;\r\n self.imei = WebToolkit_1[\"default\"].getDeviceInfo().system;\r\n self.imeiLength = exports.getLen(self.imei);\r\n self.userId = userId;\r\n this.userSign = userSign;\r\n this.imeiLength = self.imeiLength;\r\n if (!utils_1[\"default\"].isEmpty(this.url)) return [3 /*break*/, 2];\r\n Logger_1[\"default\"].info(\"获取im地址\");\r\n api = new HttpApi_1[\"default\"](this.httpUrl);\r\n return [4 /*yield*/, api.call(\"/user/login\", {}, { clientType: this.clientType, appId: this.appId, userId: this.userId })];\r\n case 1:\r\n resp = _b.sent();\r\n console.log(resp);\r\n if (resp.isFailed()) {\r\n Logger_1[\"default\"].info(\"登录失败:获取im地址失败\");\r\n return [2 /*return*/];\r\n }\r\n ip = resp.data.ip;\r\n port = resp.data.port;\r\n this.url = \"ws://\" + ip + \":\" + port + \"/ws\";\r\n _b.label = 2;\r\n case 2:\r\n req = new LoginPack_1.LoginPack(self.appId, self.userId, 1);\r\n return [4 /*yield*/, exports.limLogin(self.url, req, self)];\r\n case 3:\r\n _a = _b.sent(), success = _a.success, err = _a.err, conn = _a.conn;\r\n if (success) {\r\n if (!firstMonitorSocket) {\r\n firstMonitorSocket = true;\r\n }\r\n //登录成功以后操作\r\n conn.onerror = function (error) {\r\n Logger_1[\"default\"].info(\"websocket error: \", error);\r\n // 加入socket 连接事件\r\n if (typeof exports.imClient.listeners.onSocketErrorEvent === 'function') {\r\n exports.imClient.listeners.onSocketErrorEvent(error);\r\n }\r\n _this.errorHandler(error, req);\r\n };\r\n conn.onclose = function (e) {\r\n Logger_1[\"default\"].info(\"event[onclose] fired\");\r\n if (self.state == State.CLOSEING) {\r\n _this.onclose(\"logout\");\r\n return;\r\n }\r\n // 加入socket 连接事件\r\n if (typeof exports.imClient.listeners.onSocketErrorEvent === 'function') {\r\n exports.imClient.listeners.onSocketCloseEvent();\r\n }\r\n _this.errorHandler(new Error(e.reason), req);\r\n };\r\n conn.onmessage = function (evt) {\r\n var bytebuf = new ByteBuffer_1[\"default\"](evt.data);\r\n var byteBuffer = bytebuf.int32().int32().unpack();\r\n var command = byteBuffer[0]; //解析command\r\n var bodyLen = byteBuffer[1]; //解析bodylen\r\n var unpack = bytebuf.vstring(null, bodyLen).unpack(); //解析出字符串\r\n var msgBody = unpack[2];\r\n console.log(\"sdk收到服务端数据: \" + msgBody);\r\n if (command === Command_1.MessageCommand.MSG_P2P) {\r\n //单聊消息收发\r\n if (typeof exports.imClient.listeners.onP2PMessage === 'function') {\r\n exports.imClient.listeners.onP2PMessage(msgBody);\r\n }\r\n }\r\n else {\r\n if (typeof exports.imClient.listeners.onTestMessage === 'function') {\r\n exports.imClient.listeners.onTestMessage(msgBody);\r\n }\r\n }\r\n };\r\n this.conn = conn;\r\n this.state = State.CONNECTED;\r\n //拉取离线消息\r\n // this.loadOfflineMessage();\r\n //心跳包\r\n this.heartbeatLoop(this.conn);\r\n if (typeof exports.imClient.listeners.onLogin === 'function') {\r\n exports.imClient.listeners.onLogin(this.userId);\r\n }\r\n callback(self);\r\n }\r\n else {\r\n Logger_1[\"default\"].error(err === null || err === void 0 ? void 0 : err.message);\r\n }\r\n return [2 /*return*/];\r\n }\r\n });\r\n });\r\n };\r\n ImClient.prototype.buildMessagePack = function (command, messagePack) {\r\n var jsonData = JSON.stringify(messagePack);\r\n var bodyLen = exports.getLen(jsonData);\r\n var pack = new ByteBuffer_1[\"default\"](null, 0);\r\n pack.int32(command).int32(this.version).int32(this.clientType)\r\n .int32(0x0)\r\n .int32(this.appId)\r\n .int32(this.imeiLength)\r\n .int32(bodyLen)\r\n .vstring(this.imei, this.imeiLength)\r\n .vstring(jsonData, bodyLen);\r\n return pack;\r\n };\r\n // 4. 自动重连\r\n ImClient.prototype.errorHandler = function (error, req) {\r\n return __awaiter(this, void 0, void 0, function () {\r\n var index, _a, success, err, conn, error_1;\r\n return __generator(this, function (_b) {\r\n switch (_b.label) {\r\n case 0:\r\n // 如果是主动断开连接,就没有必要自动重连\r\n // 比如收到被踢,或者主动调用logout()方法\r\n if (this.state == State.CLOSED || this.state == State.CLOSEING) {\r\n return [2 /*return*/];\r\n }\r\n this.state = State.RECONNECTING;\r\n if (typeof exports.imClient.listeners.onSocketReConnectEvent === 'function') {\r\n exports.imClient.listeners.onSocketReConnectEvent();\r\n }\r\n index = 0;\r\n _b.label = 1;\r\n case 1:\r\n if (!(index < 10)) return [3 /*break*/, 7];\r\n return [4 /*yield*/, exports.sleep(3)];\r\n case 2:\r\n _b.sent();\r\n _b.label = 3;\r\n case 3:\r\n _b.trys.push([3, 5, , 6]);\r\n Logger_1[\"default\"].info(\"try to relogin\");\r\n return [4 /*yield*/, exports.limLogin(this.url, req, this)];\r\n case 4:\r\n _a = _b.sent(), success = _a.success, err = _a.err, conn = _a.conn;\r\n if (success) {\r\n if (typeof exports.imClient.listeners.onSocketReConnectSuccessEvent === 'function') {\r\n exports.imClient.listeners.onSocketReConnectSuccessEvent();\r\n }\r\n return [2 /*return*/];\r\n }\r\n Logger_1[\"default\"].info(err);\r\n return [3 /*break*/, 6];\r\n case 5:\r\n error_1 = _b.sent();\r\n Logger_1[\"default\"].info(error_1);\r\n return [3 /*break*/, 6];\r\n case 6:\r\n index++;\r\n return [3 /*break*/, 1];\r\n case 7:\r\n this.onclose(\"reconnect timeout\");\r\n return [2 /*return*/];\r\n }\r\n });\r\n });\r\n };\r\n // 表示连接中止\r\n ImClient.prototype.onclose = function (reason) {\r\n if (this.state == State.CLOSED) {\r\n return;\r\n }\r\n this.state = State.CLOSED;\r\n Logger_1[\"default\"].info(\"connection closed due to \" + reason);\r\n this.conn = undefined;\r\n this.userId = \"\";\r\n // 加入socket 关闭事件\r\n if (typeof exports.imClient.listeners.onSocketErrorEvent === 'function') {\r\n exports.imClient.listeners.onSocketCloseEvent();\r\n }\r\n };\r\n ImClient.prototype.getSingleUserInfo = function (uid) {\r\n var _this = this;\r\n return new Promise(function (resolve, _) {\r\n var api = new HttpApi_1[\"default\"](_this.httpUrl);\r\n var resp = api.call(\"/user/data/getSingleUserInfo\", _this.getRequestParams(), { userId: uid });\r\n resolve(resp);\r\n });\r\n };\r\n ImClient.prototype.syncGetUserInfo = function (userId) {\r\n return __awaiter(this, void 0, void 0, function () {\r\n var api, resp;\r\n return __generator(this, function (_a) {\r\n api = new HttpApi_1[\"default\"](this.httpUrl);\r\n resp = api.call(\"/user/data/getUserInfo\", this.getRequestParams(), { userIds: userId });\r\n return [2 /*return*/, resp];\r\n });\r\n });\r\n };\r\n ImClient.prototype.getUserInfo = function (userId) {\r\n var _this = this;\r\n return new Promise(function (resolve, _) {\r\n var api = new HttpApi_1[\"default\"](_this.httpUrl);\r\n var resp = api.call(\"/user/data/getUserInfo\", _this.getRequestParams(), { userIds: userId });\r\n resolve(resp);\r\n });\r\n };\r\n ImClient.prototype.getAllFriend = function () {\r\n var _this = this;\r\n return new Promise(function (resolve, _) {\r\n var api = new HttpApi_1[\"default\"](_this.httpUrl);\r\n var resp = api.call(\"/friendship/getAllFriendShip\", _this.getRequestParams(), { fromId: _this.userId });\r\n resolve(resp);\r\n });\r\n };\r\n // 2、心跳\r\n ImClient.prototype.heartbeatLoop = function (conn) {\r\n var _this = this;\r\n var start = Date.now();\r\n var loop = function () {\r\n if (_this.state != State.CONNECTED) {\r\n Logger_1[\"default\"].error(\"heartbeatLoop exited\");\r\n return;\r\n }\r\n if (Date.now() - start >= heartbeatInterval) {\r\n Logger_1[\"default\"].info(\">>> send ping ;\");\r\n start = Date.now();\r\n var pingPack = exports.imClient.buildMessagePack(Command_1.SystemCommand.PING, {});\r\n conn.send(pingPack.pack(false));\r\n }\r\n setTimeout(loop, 500);\r\n };\r\n setTimeout(loop, 500);\r\n };\r\n //构建单聊消息对象\r\n ImClient.prototype.createP2PTextMessage = function (to, text) {\r\n var messagePack = new MessagePack_1.MessagePack(this.appId);\r\n messagePack.buildTxtMessagePack(this.userId, to, text);\r\n return messagePack;\r\n };\r\n ImClient.prototype.sendP2PMessage = function (pack) {\r\n var p2pPack = exports.imClient.buildMessagePack(Command_1.MessageCommand.MSG_P2P, pack);\r\n if (this.conn) {\r\n this.conn.send(p2pPack.pack(false));\r\n }\r\n };\r\n ImClient.prototype.getUserId = function () {\r\n return this.userId;\r\n };\r\n return ImClient;\r\n}());\r\nexports.ImClient = ImClient;\r\nexports.limLogin = function (url, req, imClient) { return __awaiter(void 0, void 0, void 0, function () {\r\n return __generator(this, function (_a) {\r\n return [2 /*return*/, new Promise(function (resolve, _) {\r\n var conn = new websocket_1.w3cwebsocket(url);\r\n conn.binaryType = \"arraybuffer\";\r\n Logger_1[\"default\"].info(\"limLogin\");\r\n // 设置一个登陆超时器\r\n var tr = setTimeout(function () {\r\n clearTimeout(tr);\r\n resolve({ success: false, err: new Error(\"timeout\"), conn: conn });\r\n }, loginTimeout);\r\n conn.onopen = function () {\r\n if (conn.readyState == websocket_1.w3cwebsocket.OPEN) {\r\n // 加入socket 连接事件\r\n if (typeof imClient.listeners.onSocketConnectEvent === 'function') {\r\n imClient.listeners.onSocketConnectEvent(url, req);\r\n }\r\n Logger_1[\"default\"].info(\"\\u5F00\\u542F\\u8FDE\\u63A5\");\r\n //登录数据包\r\n var data = {\r\n \"userId\": req.userId\r\n };\r\n var loginPack = imClient.buildMessagePack(0x2328, data);\r\n conn.send(loginPack.pack(false));\r\n }\r\n };\r\n conn.onerror = function (error) {\r\n clearTimeout(tr);\r\n Logger_1[\"default\"].error(error);\r\n resolve({ success: false, err: error, conn: conn });\r\n };\r\n conn.onmessage = function (evt) {\r\n if (typeof evt.data === 'string') {\r\n Logger_1[\"default\"].info(\"Received: '\" + evt.data + \"'\");\r\n return;\r\n }\r\n clearTimeout(tr);\r\n var bytebuf = new ByteBuffer_1[\"default\"](evt.data);\r\n var byteBuffer = bytebuf.int32().int32().unpack();\r\n var command = byteBuffer[0];\r\n var bodyLen = byteBuffer[1];\r\n if (command == 0x2329) {\r\n resolve({ success: true, conn: conn });\r\n }\r\n };\r\n })];\r\n });\r\n}); };\r\nexports.getLen = function (str) {\r\n var len = 0;\r\n for (var i = 0; i < str.length; i++) {\r\n var c = str.charCodeAt(i);\r\n //单字节加1\r\n if ((c >= 0x0001 && c <= 0x007e) || (0xff60 <= c && c <= 0xff9f)) {\r\n len++;\r\n }\r\n else {\r\n len += 3;\r\n }\r\n }\r\n return len;\r\n};\r\nexports.imClient = new ImClient();\r\n","\"use strict\";\r\nexports.__esModule = true;\r\n/**\r\n * 返回平台所用的 fetch 工具\r\n * */\r\nvar Fetch = /** @class */ (function () {\r\n function Fetch() {\r\n }\r\n Fetch.getFetchToolkit = function () {\r\n var httpFetch;\r\n // @ts-ignore\r\n if (typeof global.fetch !== 'undefined' && typeof global.fetch === 'function') {\r\n // @ts-ignore\r\n httpFetch = global.fetch;\r\n }\r\n else if (typeof fetch === 'function') {\r\n httpFetch = fetch; // RN FETCH\r\n }\r\n else {\r\n var uniFetch = require(\"../uniapp/http/uni-fetch\");\r\n httpFetch = uniFetch.fetch;\r\n }\r\n return httpFetch;\r\n };\r\n return Fetch;\r\n}());\r\nexports[\"default\"] = Fetch;\r\n","\"use strict\";\r\nexports.__esModule = true;\r\nexports.im = void 0;\r\nvar ImClient_1 = require(\"./lim/core/ImClient\");\r\nexports.im = ImClient_1.imClient;\r\nif (typeof window !== 'undefined') {\r\n console.log(\"window\");\r\n}\r\nif (typeof global !== 'undefined') {\r\n console.log(\"global\");\r\n}\r\n// @ts-ignore\r\nif (typeof uni !== 'undefined') {\r\n // console.log(\"uni\");\r\n // @ts-ignore\r\n uni['im'] = ImClient_1.imClient;\r\n // @ts-ignore\r\n // uni['im_webtoolkit'] = WebToolkit;\r\n}\r\n","\"use strict\";\r\nexports.__esModule = true;\r\nvar ByteBuffer = /** @class */ (function () {\r\n function ByteBuffer(arrayBuf, offset) {\r\n this.Type_Byte = 1;\r\n this.Type_Short = 2;\r\n this.Type_UShort = 3;\r\n this.Type_Int32 = 4;\r\n this.Type_UInt32 = 5;\r\n this.Type_String = 6; //变长字符串,前两个字节表示长度\r\n this.Type_VString = 7; //定长字符串\r\n this.Type_Int64 = 8;\r\n this.Type_Float = 9;\r\n this.Type_Double = 10;\r\n this.Type_ByteArray = 11;\r\n this._offset = 0;\r\n this._list = [];\r\n this._littleEndian = false;\r\n this._org_buf = arrayBuf ? (arrayBuf.constructor == DataView ? arrayBuf\r\n : (arrayBuf.constructor == Uint8Array ? new DataView(arrayBuf.buffer, offset) : new DataView(arrayBuf, offset))) : new DataView(new Uint8Array([]).buffer);\r\n this.arrayBuf = arrayBuf;\r\n this.offset = offset;\r\n // if (!ArrayBuffer.prototype.slice) {\r\n // ArrayBuffer.prototype.slice = function (start, end) {\r\n // var that = new Uint8Array(this);\r\n // if (end == undefined) end = that.length;\r\n // var result = new ArrayBuffer(end - start);\r\n // var resultArray = new Uint8Array(result);\r\n // for (var i = 0; i < resultArray.length; i++)\r\n // resultArray[i] = that[i + start];\r\n // return result;\r\n // }\r\n // }\r\n }\r\n //指定字节序 为BigEndian\r\n ByteBuffer.prototype.bigEndian = function () {\r\n this._littleEndian = false;\r\n return this;\r\n };\r\n ;\r\n //指定字节序 为LittleEndian\r\n ByteBuffer.prototype.littleEndianfunction = function () {\r\n this._littleEndian = true;\r\n return this;\r\n };\r\n ;\r\n ByteBuffer.prototype.utf8Write = function (view, offset, str) {\r\n var c = 0;\r\n for (var i = 0, l = str.length; i < l; i++) {\r\n c = str.charCodeAt(i);\r\n if (c < 0x80) {\r\n view.setUint8(offset++, c);\r\n }\r\n else if (c < 0x800) {\r\n view.setUint8(offset++, 0xc0 | (c >> 6));\r\n view.setUint8(offset++, 0x80 | (c & 0x3f));\r\n }\r\n else if (c < 0xd800 || c >= 0xe000) {\r\n view.setUint8(offset++, 0xe0 | (c >> 12));\r\n view.setUint8(offset++, 0x80 | (c >> 6) & 0x3f);\r\n view.setUint8(offset++, 0x80 | (c & 0x3f));\r\n }\r\n else {\r\n i++;\r\n c = 0x10000 + (((c & 0x3ff) << 10) | (str.charCodeAt(i) & 0x3ff));\r\n view.setUint8(offset++, 0xf0 | (c >> 18));\r\n view.setUint8(offset++, 0x80 | (c >> 12) & 0x3f);\r\n view.setUint8(offset++, 0x80 | (c >> 6) & 0x3f);\r\n view.setUint8(offset++, 0x80 | (c & 0x3f));\r\n }\r\n }\r\n };\r\n // byte (val, index) {\r\n // if (arguments.length == 0) {\r\n // this._list.push(this._org_buf.getUint8(this._offset, this._littleEndian));\r\n // this._offset += 1;\r\n // } else {\r\n // this._list.splice(index != undefined ? index : this._list.length, 0);\r\n // this._offset += 1;\r\n // }\r\n // return this;\r\n // };\r\n // short(val:number, index:number) {\r\n // if (arguments.length == 0) {\r\n // this._list.push(this._org_buf.getInt16(this._offset, this._littleEndian));\r\n // this._offset += 2;\r\n // } else {\r\n // this._list.splice(index != undefined ? index : this._list.length, 0, this.Type_Short);\r\n // this._offset += 2;\r\n // }\r\n // return this;\r\n // };\r\n // ushort(val, index) {\r\n // if (arguments.length == 0) {\r\n // this._list.push(this._org_buf.getUint16(this._offset, this._littleEndian));\r\n // this._offset += 2;\r\n // } else {\r\n // // , {t: this.Type_UShort, d: val, l: 2}\r\n // this._list.splice(index != undefined ? index : this._list.length, 0);\r\n // this._offset += 2;\r\n // }\r\n // return this;\r\n // };\r\n ByteBuffer.prototype.int32 = function (val, index) {\r\n if (arguments.length == 0) {\r\n this._list.push(this._org_buf.getInt32(this._offset, this._littleEndian));\r\n this._offset += 4;\r\n }\r\n else {\r\n this._list.splice(index != undefined ? index : this._list.length, 0, { t: this.Type_Int32, d: val, l: 4 });\r\n this._offset += 4;\r\n }\r\n return this;\r\n };\r\n ;\r\n ByteBuffer.prototype.uint32 = function (val, index) {\r\n if (arguments.length == 0) {\r\n this._list.push(this._org_buf.getUint32(this._offset, this._littleEndian));\r\n this._offset += 4;\r\n }\r\n else {\r\n this._list.splice(index != undefined ? index : this._list.length, 0, { t: this.Type_UInt32, d: val, l: 4 });\r\n this._offset += 4;\r\n }\r\n return this;\r\n };\r\n ;\r\n /**\r\n * 新加的方法,获取bytebuffer的长度\r\n */\r\n ByteBuffer.prototype.blength = function () {\r\n return this._offset;\r\n };\r\n ;\r\n /**\r\n * 变长字符串 前4个字节表示字符串长度\r\n **/\r\n ByteBuffer.prototype.string = function (val, index) {\r\n if (arguments.length == 0) {\r\n var len = this._org_buf.getInt32(this._offset, this._littleEndian);\r\n this._offset += 4;\r\n this._list.push(this.utf8Read(this._org_buf, this._offset, len));\r\n this._offset += len;\r\n }\r\n else {\r\n var len = 0;\r\n if (val) {\r\n len = this.utf8Length(val);\r\n }\r\n this._list.splice(index != undefined ? index : this._list.length, 0, { t: this.Type_String, d: val, l: len });\r\n this._offset += len + 4;\r\n }\r\n return this;\r\n };\r\n ;\r\n ByteBuffer.prototype.utf8Length = function (str) {\r\n var c = 0, length = 0;\r\n for (var i = 0, l = str.length; i < l; i++) {\r\n c = str.charCodeAt(i);\r\n if (c < 0x80) {\r\n length += 1;\r\n }\r\n else if (c < 0x800) {\r\n length += 2;\r\n }\r\n else if (c < 0xd800 || c >= 0xe000) {\r\n length += 3;\r\n }\r\n else {\r\n i++;\r\n length += 4;\r\n }\r\n }\r\n return length;\r\n };\r\n ByteBuffer.prototype.utf8Read = function (view, offset, length) {\r\n var string = '', chr = 0;\r\n for (var i = offset, end = offset + length; i < end; i++) {\r\n var byte = view.getUint8(i);\r\n if ((byte & 0x80) === 0x00) {\r\n string += String.fromCharCode(byte);\r\n continue;\r\n }\r\n if ((byte & 0xe0) === 0xc0) {\r\n string += String.fromCharCode(((byte & 0x0f) << 6) |\r\n (view.getUint8(++i) & 0x3f));\r\n continue;\r\n }\r\n if ((byte & 0xf0) === 0xe0) {\r\n string += String.fromCharCode(((byte & 0x0f) << 12) |\r\n ((view.getUint8(++i) & 0x3f) << 6) |\r\n ((view.getUint8(++i) & 0x3f) << 0));\r\n continue;\r\n }\r\n if ((byte & 0xf8) === 0xf0) {\r\n chr = ((byte & 0x07) << 18) |\r\n ((view.getUint8(++i) & 0x3f) << 12) |\r\n ((view.getUint8(++i) & 0x3f) << 6) |\r\n ((view.getUint8(++i) & 0x3f) << 0);\r\n if (chr >= 0x010000) { // surrogate pair\r\n chr -= 0x010000;\r\n string += String.fromCharCode((chr >>> 10) + 0xD800, (chr & 0x3FF) + 0xDC00);\r\n }\r\n else {\r\n string += String.fromCharCode(chr);\r\n }\r\n continue;\r\n }\r\n throw new Error('Invalid byte ' + byte.toString(16));\r\n }\r\n return string;\r\n };\r\n /**\r\n * 定长字符串 val为null时,读取定长字符串(需指定长度len)\r\n **/\r\n ByteBuffer.prototype.vstring = function (val, len, index) {\r\n if (!len) {\r\n throw new Error('vstring must got len argument');\r\n return this;\r\n }\r\n if (val == undefined || val == null) {\r\n var vlen = 0; //实际长度\r\n for (var i = this._offset; i < this._offset + len; i++) {\r\n if (this._org_buf.getUint8(i) > 0)\r\n vlen++;\r\n }\r\n this._list.push(this.utf8Read(this._org_buf, this._offset, vlen));\r\n this._offset += len;\r\n }\r\n else {\r\n this._list.splice(index != undefined ? index : this._list.length, 0, { t: this.Type_VString, d: val, l: len });\r\n this._offset += len;\r\n }\r\n return this;\r\n };\r\n ;\r\n ByteBuffer.prototype.int64 = function (val, index) {\r\n if (arguments.length == 0) {\r\n this._list.push(this._org_buf.getFloat64(this._offset, this._littleEndian));\r\n this._offset += 8;\r\n }\r\n else {\r\n this._list.splice(index != undefined ? index : this._list.length, 0, { t: this.Type_Int64, d: val, l: 8 });\r\n this._offset += 8;\r\n }\r\n return this;\r\n };\r\n ;\r\n ByteBuffer.prototype.float = function (val, index) {\r\n if (arguments.length == 0) {\r\n this._list.push(this._org_buf.getFloat32(this._offset, this._littleEndian));\r\n this._offset += 4;\r\n }\r\n else {\r\n this._list.splice(index != undefined ? index : this._list.length, 0, { t: this.Type_Float, d: val, l: 4 });\r\n this._offset += 4;\r\n }\r\n return this;\r\n };\r\n ;\r\n ByteBuffer.prototype.double = function (val, index) {\r\n if (arguments.length == 0) {\r\n this._list.push(this._org_buf.getFloat64(this._offset, this._littleEndian));\r\n this._offset += 8;\r\n }\r\n else {\r\n this._list.splice(index != undefined ? index : this._list.length, 0, { t: this.Type_Double, d: val, l: 8 });\r\n this._offset += 8;\r\n }\r\n return this;\r\n };\r\n ;\r\n /**\r\n * 写入或读取一段字节数组\r\n **/\r\n ByteBuffer.prototype.byteArray = function (val, len, index) {\r\n if (!len) {\r\n throw new Error('byteArray must got len argument');\r\n return this;\r\n }\r\n if (val == undefined || val == null) {\r\n var arr = new Uint8Array(this._org_buf.buffer.slice(this._offset, this._offset + len));\r\n this._list.push(arr);\r\n this._offset += len;\r\n }\r\n else {\r\n this._list.splice(index != undefined ? index : this._list.length, 0, { t: this.Type_ByteArray, d: val, l: len });\r\n this._offset += len;\r\n }\r\n return this;\r\n };\r\n ;\r\n /**\r\n * 解包成数据数组\r\n **/\r\n ByteBuffer.prototype.unpack = function () {\r\n return this._list;\r\n };\r\n ;\r\n /**\r\n * 打包成二进制,在前面加上4个字节表示包长\r\n **/\r\n ByteBuffer.prototype.packWithHead = function () {\r\n return this.pack(true);\r\n };\r\n ;\r\n /**\r\n * 打包成二进制\r\n * @param ifHead 是否在前面加上4个字节表示包长\r\n **/\r\n ByteBuffer.prototype.pack = function (ifHead) {\r\n this._org_buf = new DataView(new ArrayBuffer((ifHead) ? this._offset + 4 : this._offset));\r\n var offset = 0;\r\n if (ifHead) {\r\n this._org_buf.setUint32(offset, this._offset, this._littleEndian);\r\n offset += 4;\r\n }\r\n for (var i = 0; i < this._list.length; i++) {\r\n switch (this._list[i].t) {\r\n case this.Type_Byte:\r\n this._org_buf.setInt8(offset, this._list[i].d);\r\n offset += this._list[i].l;\r\n break;\r\n case this.Type_Short:\r\n this._org_buf.setInt16(offset, this._list[i].d, this._littleEndian);\r\n offset += this._list[i].l;\r\n break;\r\n case this.Type_UShort:\r\n this._org_buf.setUint16(offset, this._list[i].d, this._littleEndian);\r\n offset += this._list[i].l;\r\n break;\r\n case this.Type_Int32:\r\n this._org_buf.setInt32(offset, this._list[i].d, this._littleEndian);\r\n offset += this._list[i].l;\r\n break;\r\n case this.Type_UInt32:\r\n this._org_buf.setUint32(offset, this._list[i].d, this._littleEndian);\r\n offset += this._list[i].l;\r\n break;\r\n case this.Type_String:\r\n //前4个字节表示字符串长度\r\n this._org_buf.setUint32(offset, this._list[i].l, this._littleEndian);\r\n offset += 4;\r\n this.utf8Write(this._org_buf, offset, this._list[i].d);\r\n offset += this._list[i].l;\r\n break;\r\n case this.Type_VString:\r\n this.utf8Write(this._org_buf, offset, this._list[i].d);\r\n var vlen = this.utf8Length(this._list[i].d); //字符串实际长度\r\n //补齐\\0\r\n for (var j = offset + vlen; j < offset + this._list[i].l; j++) {\r\n this._org_buf.setUint8(j, 0);\r\n }\r\n offset += this._list[i].l;\r\n break;\r\n case this.Type_Int64:\r\n this._org_buf.setFloat64(offset, this._list[i].d, this._littleEndian);\r\n offset += this._list[i].l;\r\n break;\r\n case this.Type_Float:\r\n this._org_buf.setFloat32(offset, this._list[i].d, this._littleEndian);\r\n offset += this._list[i].l;\r\n break;\r\n case this.Type_Double:\r\n this._org_buf.setFloat64(offset, this._list[i].d, this._littleEndian);\r\n offset += this._list[i].l;\r\n break;\r\n case this.Type_ByteArray:\r\n var indx = 0;\r\n for (var j = offset; j < offset + this._list[i].l; j++) {\r\n if (indx < this._list[i].d.length) {\r\n this._org_buf.setUint8(j, this._list[i].d[indx]);\r\n }\r\n else { //不够的话,后面补齐0x00\r\n this._org_buf.setUint8(j, 0);\r\n }\r\n indx++;\r\n }\r\n offset += this._list[i].l;\r\n break;\r\n }\r\n }\r\n return this._org_buf.buffer;\r\n };\r\n ;\r\n /**\r\n * 未读数据长度\r\n **/\r\n ByteBuffer.prototype.getAvailable = function () {\r\n if (!this._org_buf)\r\n return this._offset;\r\n return this._org_buf.buffer.byteLength - this._offset;\r\n };\r\n ;\r\n return ByteBuffer;\r\n}());\r\nexports[\"default\"] = ByteBuffer;\r\n","\"use strict\";\r\nexports.__esModule = true;\r\nexports.LoginPack = void 0;\r\nvar LoginPack = /** @class */ (function () {\r\n function LoginPack(appId, userId, clientType) {\r\n this.userId = userId;\r\n this.clientType = clientType;\r\n this.appId = appId;\r\n }\r\n return LoginPack;\r\n}());\r\nexports.LoginPack = LoginPack;\r\n","\"use strict\";\r\nexports.__esModule = true;\r\nvar Fetch_1 = require(\"../common/Fetch\");\r\nvar Logger_1 = require(\"../log/Logger\");\r\nvar Base64 = {\r\n _keyStr: \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\",\r\n encode: function (e) {\r\n var t = \"\";\r\n var n, r, i, s, o, u, a;\r\n var f = 0;\r\n e = Base64._utf8_encode(e);\r\n while (f < e.length) {\r\n n = e.charCodeAt(f++);\r\n r = e.charCodeAt(f++);\r\n i = e.charCodeAt(f++);\r\n s = n >> 2;\r\n o = (n & 3) << 4 | r >> 4;\r\n u = (r & 15) << 2 | i >> 6;\r\n a = i & 63;\r\n if (isNaN(r)) {\r\n u = a = 64;\r\n }\r\n else if (isNaN(i)) {\r\n a = 64;\r\n }\r\n t = t + this._keyStr.charAt(s) + this._keyStr.charAt(o) + this._keyStr.charAt(u) + this._keyStr.charAt(a);\r\n }\r\n return t;\r\n },\r\n decode: function (e) {\r\n var t = \"\";\r\n var n, r, i;\r\n var s, o, u, a;\r\n var f = 0;\r\n e = e.replace(/[^A-Za-z0-9+/=]/g, \"\");\r\n while (f < e.length) {\r\n s = this._keyStr.indexOf(e.charAt(f++));\r\n o = this._keyStr.indexOf(e.charAt(f++));\r\n u = this._keyStr.indexOf(e.charAt(f++));\r\n a = this._keyStr.indexOf(e.charAt(f++));\r\n n = s << 2 | o >> 4;\r\n r = (o & 15) << 4 | u >> 2;\r\n i = (u & 3) << 6 | a;\r\n t = t + String.fromCharCode(n);\r\n if (u != 64) {\r\n t = t + String.fromCharCode(r);\r\n }\r\n if (a != 64) {\r\n t = t + String.fromCharCode(i);\r\n }\r\n }\r\n t = Base64._utf8_decode(t);\r\n return t;\r\n },\r\n _utf8_encode: function (e) {\r\n e = e.replace(/rn/g, \"n\");\r\n var t = \"\";\r\n for (var n = 0; n < e.length; n++) {\r\n var r = e.charCodeAt(n);\r\n if (r < 128) {\r\n t += String.fromCharCode(r);\r\n }\r\n else if (r > 127 && r < 2048) {\r\n t += String.fromCharCode(r >> 6 | 192);\r\n t += String.fromCharCode(r & 63 | 128);\r\n }\r\n else {\r\n t += String.fromCharCode(r >> 12 | 224);\r\n t += String.fromCharCode(r >> 6 & 63 | 128);\r\n t += String.fromCharCode(r & 63 | 128);\r\n }\r\n }\r\n return t;\r\n },\r\n _utf8_decode: function (e) {\r\n var t = \"\";\r\n var n = 0;\r\n var r = 0;\r\n var c1 = 0;\r\n var c2 = 0;\r\n while (n < e.length) {\r\n r = e.charCodeAt(n);\r\n if (r < 128) {\r\n t += String.fromCharCode(r);\r\n n++;\r\n }\r\n else if (r > 191 && r < 224) {\r\n c2 = e.charCodeAt(n + 1);\r\n t += String.fromCharCode((r & 31) << 6 | c2 & 63);\r\n n += 2;\r\n }\r\n else {\r\n c2 = e.charCodeAt(n + 1);\r\n var c3 = e.charCodeAt(n + 2);\r\n t += String.fromCharCode((r & 15) << 12 | (c2 & 63) << 6 | c3 & 63);\r\n n += 3;\r\n }\r\n }\r\n return t;\r\n }\r\n};\r\nvar WebToolkit = /** @class */ (function () {\r\n function WebToolkit() {\r\n }\r\n // 获取浏览器信息\r\n WebToolkit.getBrowserInfo = function () {\r\n var agent = navigator.userAgent.toLowerCase();\r\n var system = agent.split(\" \")[1].split(\" \")[0].split(\"(\")[1];\r\n var REGSTR_EDGE = /edge\\/[\\d.]+/gi;\r\n var REGSTR_IE = /trident\\/[\\d.]+/gi;\r\n var OLD_IE = /msie\\s[\\d.]+/gi;\r\n var REGSTR_FF = /firefox\\/[\\d.]+/gi;\r\n var REGSTR_CHROME = /chrome\\/[\\d.]+/gi;\r\n var REGSTR_SAF = /safari\\/[\\d.]+/gi;\r\n var REGSTR_OPERA = /opr\\/[\\d.]+/gi;\r\n var info = {\r\n code: 0,\r\n system: system,\r\n browser: \"\",\r\n browserVersion: \"\"\r\n };\r\n // IE\r\n if (agent.indexOf(\"trident\") > 0) {\r\n info.browser = agent.match(REGSTR_IE)[0].split(\"/\")[0];\r\n info.browserVersion = agent.match(REGSTR_IE)[0].split(\"/\")[1];\r\n return info;\r\n }\r\n // OLD_IE\r\n if (agent.indexOf(\"msie\") > 0) {\r\n info.browser = agent.match(OLD_IE)[0].split(\" \")[0];\r\n info.browserVersion = agent.match(OLD_IE)[0].split(\" \")[1];\r\n return info;\r\n }\r\n // Edge\r\n if (agent.indexOf(\"edge\") > 0) {\r\n info.browser = agent.match(REGSTR_EDGE)[0].split(\"/\")[0];\r\n info.browserVersion = agent.match(REGSTR_EDGE)[0].split(\"/\")[1];\r\n return info;\r\n }\r\n // firefox\r\n if (agent.indexOf(\"firefox\") > 0) {\r\n info.browser = agent.match(REGSTR_FF)[0].split(\"/\")[0];\r\n info.browserVersion = agent.match(REGSTR_FF)[0].split(\"/\")[1];\r\n return info;\r\n }\r\n // Opera\r\n if (agent.indexOf(\"opr\") > 0) {\r\n info.browser = agent.match(REGSTR_OPERA)[0].split(\"/\")[0];\r\n info.browserVersion = agent.match(REGSTR_OPERA)[0].split(\"/\")[1];\r\n return info;\r\n }\r\n // Safari\r\n if (agent.indexOf(\"safari\") > 0 && agent.indexOf(\"chrome\") < 0) {\r\n info.browser = agent.match(REGSTR_SAF)[0].split(\"/\")[0];\r\n info.browserVersion = agent.match(REGSTR_SAF)[0].split(\"/\")[1];\r\n return info;\r\n }\r\n // Chrome\r\n if (agent.indexOf(\"chrome\") > 0) {\r\n info.browser = agent.match(REGSTR_CHROME)[0].split(\"/\")[0];\r\n info.browserVersion = agent.match(REGSTR_CHROME)[0].split(\"/\")[1];\r\n return info;\r\n }\r\n else {\r\n info.code = -1;\r\n return info;\r\n }\r\n };\r\n // TODO: 获取小程序设备信息\r\n WebToolkit.getWxappInfo = function () {\r\n return {\r\n system: 'WXAPP',\r\n browser: 'WXAPP',\r\n browserVersion: '1.0'\r\n };\r\n };\r\n // TODO: 获取ReactNative设备信息\r\n WebToolkit.getReactNativeInfo = function () {\r\n return {\r\n system: 'RNNative',\r\n browser: 'RNNative',\r\n browserVersion: '1.0'\r\n };\r\n };\r\n // TODO: 获取UniApp设备信息\r\n WebToolkit.getUniAppInfo = function () {\r\n return {\r\n system: 'UNIAPP',\r\n browser: 'UNIAPP',\r\n browserVersion: '1.0'\r\n };\r\n };\r\n // 动态加入script 到head 标签处\r\n WebToolkit.loadJS = function (url, callback) {\r\n var script = document.createElement('script'), fn = callback || function () { };\r\n script.type = 'text/javascript';\r\n // document.getElementsByTagName('head')[0].children[16].outerHTML.indexOf('http://pv.sohu.com/cityjson?ie=utf-8')\r\n var exist = false;\r\n for (var v in document.getElementsByTagName('head')[0].children) {\r\n var dom = document.getElementsByTagName('head')[0].children[v];\r\n if (dom.outerHTML !== undefined && dom.outerHTML.indexOf(url) >= 0) {\r\n exist = true;\r\n }\r\n }\r\n if (exist) {\r\n fn();\r\n return;\r\n }\r\n //IE\r\n if (script.readyState) {\r\n script.onreadystatechange = function () {\r\n if (script.readyState == 'loaded' || script.readyState == 'complete') {\r\n script.onreadystatechange = null;\r\n fn();\r\n }\r\n };\r\n }\r\n else {\r\n //其他浏览器\r\n script.onload = function () {\r\n fn();\r\n };\r\n }\r\n script.src = url;\r\n document.getElementsByTagName('head')[0].appendChild(script);\r\n };\r\n // 获取当前ip信息(fetch方式)\r\n WebToolkit.getIpInfoByFetch = function (callback) {\r\n var url = 'http://pv.sohu.com/cityjson?ie=utf-8';\r\n var fetch = Fetch_1[\"default\"].getFetchToolkit();\r\n var request = { method: \"GET\", mode: \"cors\", headers: { \"Content-Type\": \"application/json\" } };\r\n return fetch(url, request).then(function (response) {\r\n return response.text();\r\n }).then(function (res) {\r\n if (typeof callback === 'function') {\r\n var currentCity = eval('_current_city=' + res.replace('var returnCitySN = ', ''));\r\n callback(currentCity);\r\n }\r\n })[\"catch\"](function (e) {\r\n Logger_1[\"default\"].trace(e);\r\n });\r\n };\r\n // 获取当前ip信息(动态插入script脚本方式)\r\n WebToolkit.getIpInfoByInsertScript = function (callback) {\r\n var url = 'http://pv.sohu.com/cityjson?ie=utf-8';\r\n WebToolkit.loadJS(url, function () {\r\n callback(window['returnCitySN']);\r\n });\r\n };\r\n WebToolkit.getIpInfo = function (callback) {\r\n // 小程序的情况需要把pv.sohu.com域名加入白名单中\r\n WebToolkit.getIpInfoByFetch(callback);\r\n };\r\n // 获取客户端设备信息\r\n WebToolkit.getDeviceInfo = function () {\r\n var deviceInfo = WebToolkit.getUniAppInfo();\r\n return deviceInfo;\r\n };\r\n WebToolkit.base64Encode = function (str) {\r\n return Base64.encode(str);\r\n };\r\n WebToolkit.base64Decode = function (str) {\r\n return Base64.decode(str);\r\n };\r\n return WebToolkit;\r\n}());\r\nexports[\"default\"] = WebToolkit;\r\n","var global =\r\n (typeof globalThis !== 'undefined' && globalThis) ||\r\n (typeof self !== 'undefined' && self) ||\r\n (typeof global !== 'undefined' && global)\r\n\r\nvar support = {\r\n searchParams: 'URLSearchParams' in global,\r\n iterable: 'Symbol' in global && 'iterator' in Symbol,\r\n blob:\r\n 'FileReader' in global &&\r\n 'Blob' in global &&\r\n (function() {\r\n try {\r\n new Blob()\r\n return true\r\n } catch (e) {\r\n return false\r\n }\r\n })(),\r\n formData: 'FormData' in global,\r\n arrayBuffer: 'ArrayBuffer' in global\r\n}\r\n\r\nfunction isDataView(obj) {\r\n return obj && DataView.prototype.isPrototypeOf(obj)\r\n}\r\n\r\nif (support.arrayBuffer) {\r\n var viewClasses = [\r\n '[object Int8Array]',\r\n '[object Uint8Array]',\r\n '[object Uint8ClampedArray]',\r\n '[object Int16Array]',\r\n '[object Uint16Array]',\r\n '[object Int32Array]',\r\n '[object Uint32Array]',\r\n '[object Float32Array]',\r\n '[object Float64Array]'\r\n ]\r\n\r\n var isArrayBufferView =\r\n ArrayBuffer.isView ||\r\n function(obj) {\r\n return obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1\r\n }\r\n}\r\n\r\nfunction normalizeName(name) {\r\n if (typeof name !== 'string') {\r\n name = String(name)\r\n }\r\n if (/[^a-z0-9\\-#$%&'*+.^_`|~!]/i.test(name) || name === '') {\r\n throw new TypeError('Invalid character in header field name: \"' + name + '\"')\r\n }\r\n // return name.toLowerCase()\r\n return name;\r\n}\r\n\r\nfunction normalizeValue(value) {\r\n if (typeof value !== 'string') {\r\n value = String(value)\r\n }\r\n return value\r\n}\r\n\r\n// Build a destructive iterator for the value list\r\nfunction iteratorFor(items) {\r\n var iterator = {\r\n next: function() {\r\n var value = items.shift()\r\n return {done: value === undefined, value: value}\r\n }\r\n }\r\n\r\n if (support.iterable) {\r\n iterator[Symbol.iterator] = function() {\r\n return iterator\r\n }\r\n }\r\n\r\n return iterator\r\n}\r\n\r\nexport function Headers(headers) {\r\n this.map = {}\r\n\r\n if (headers instanceof Headers) {\r\n headers.forEach(function(value, name) {\r\n this.append(name, value)\r\n }, this)\r\n } else if (Array.isArray(headers)) {\r\n headers.forEach(function(header) {\r\n this.append(header[0], header[1])\r\n }, this)\r\n } else if (headers) {\r\n Object.getOwnPropertyNames(headers).forEach(function(name) {\r\n this.append(name, headers[name])\r\n }, this)\r\n }\r\n}\r\n\r\nHeaders.prototype.append = function(name, value) {\r\n name = normalizeName(name)\r\n value = normalizeValue(value)\r\n var oldValue = this.map[name]\r\n this.map[name] = oldValue ? oldValue + ', ' + value : value\r\n}\r\n\r\nHeaders.prototype['delete'] = function(name) {\r\n delete this.map[normalizeName(name)]\r\n}\r\n\r\nHeaders.prototype.get = function(name) {\r\n name = normalizeName(name)\r\n return this.has(name) ? this.map[name] : null\r\n}\r\n\r\nHeaders.prototype.has = function(name) {\r\n return this.map.hasOwnProperty(normalizeName(name))\r\n}\r\n\r\nHeaders.prototype.set = function(name, value) {\r\n this.map[normalizeName(name)] = normalizeValue(value)\r\n}\r\n\r\nHeaders.prototype.forEach = function(callback, thisArg) {\r\n for (var name in this.map) {\r\n if (this.map.hasOwnProperty(name)) {\r\n callback.call(thisArg, this.map[name], name, this)\r\n }\r\n }\r\n}\r\n\r\nHeaders.prototype.keys = function() {\r\n var items = []\r\n this.forEach(function(value, name) {\r\n items.push(name)\r\n })\r\n return iteratorFor(items)\r\n}\r\n\r\nHeaders.prototype.values = function() {\r\n var items = []\r\n this.forEach(function(value) {\r\n items.push(value)\r\n })\r\n return iteratorFor(items)\r\n}\r\n\r\nHeaders.prototype.entries = function() {\r\n var items = []\r\n this.forEach(function(value, name) {\r\n items.push([name, value])\r\n })\r\n return iteratorFor(items)\r\n}\r\n\r\nif (support.iterable) {\r\n Headers.prototype[Symbol.iterator] = Headers.prototype.entries\r\n}\r\n\r\nfunction consumed(body) {\r\n if (body.bodyUsed) {\r\n return Promise.reject(new TypeError('Already read'))\r\n }\r\n body.bodyUsed = true\r\n}\r\n\r\nfunction fileReaderReady(reader) {\r\n return new Promise(function(resolve, reject) {\r\n reader.onload = function() {\r\n resolve(reader.result)\r\n }\r\n reader.onerror = function() {\r\n reject(reader.error)\r\n }\r\n })\r\n}\r\n\r\nfunction readBlobAsArrayBuffer(blob) {\r\n var reader = new FileReader()\r\n var promise = fileReaderReady(reader)\r\n reader.readAsArrayBuffer(blob)\r\n return promise\r\n}\r\n\r\nfunction readBlobAsText(blob) {\r\n var reader = new FileReader()\r\n var promise = fileReaderReady(reader)\r\n reader.readAsText(blob)\r\n return promise\r\n}\r\n\r\nfunction readArrayBufferAsText(buf) {\r\n var view = new Uint8Array(buf)\r\n var chars = new Array(view.length)\r\n\r\n for (var i = 0; i < view.length; i++) {\r\n chars[i] = String.fromCharCode(view[i])\r\n }\r\n return chars.join('')\r\n}\r\n\r\nfunction bufferClone(buf) {\r\n if (buf.slice) {\r\n return buf.slice(0)\r\n } else {\r\n var view = new Uint8Array(buf.byteLength)\r\n view.set(new Uint8Array(buf))\r\n return view.buffer\r\n }\r\n}\r\n\r\nfunction Body() {\r\n this.bodyUsed = false\r\n\r\n this._initBody = function(body) {\r\n /*\r\n fetch-mock wraps the Response object in an ES6 Proxy to\r\n provide useful test harness features such as flush. However, on\r\n ES5 browsers without fetch or Proxy support pollyfills must be used;\r\n the proxy-pollyfill is unable to proxy an attribute unless it exists\r\n on the object before the Proxy is created. This change ensures\r\n Response.bodyUsed exists on the instance, while maintaining the\r\n semantic of setting Request.bodyUsed in the constructor before\r\n _initBody is called.\r\n */\r\n this.bodyUsed = this.bodyUsed\r\n this._bodyInit = body\r\n if (!body) {\r\n this._bodyText = ''\r\n } else if (typeof body === 'string') {\r\n this._bodyText = body\r\n } else if (support.blob && Blob.prototype.isPrototypeOf(body)) {\r\n this._bodyBlob = body\r\n } else if (support.formData && FormData.prototype.isPrototypeOf(body)) {\r\n this._bodyFormData = body\r\n } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {\r\n this._bodyText = body.toString()\r\n } else if (support.arrayBuffer && support.blob && isDataView(body)) {\r\n this._bodyArrayBuffer = bufferClone(body.buffer)\r\n // IE 10-11 can't handle a DataView body.\r\n this._bodyInit = new Blob([this._bodyArrayBuffer])\r\n } else if (support.arrayBuffer && (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body))) {\r\n this._bodyArrayBuffer = bufferClone(body)\r\n } else {\r\n this._bodyText = body = Object.prototype.toString.call(body)\r\n }\r\n\r\n if (!this.headers.get('Content-Type')) {\r\n if (typeof body === 'string') {\r\n this.headers.set('Content-Type', 'text/plain;charset=UTF-8')\r\n } else if (this._bodyBlob && this._bodyBlob.type) {\r\n this.headers.set('Content-Type', this._bodyBlob.type)\r\n } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {\r\n this.headers.set('Content-Type', 'application/x-www-form-urlencoded;charset=UTF-8')\r\n }\r\n }\r\n }\r\n\r\n if (support.blob) {\r\n this.blob = function() {\r\n var rejected = consumed(this)\r\n if (rejected) {\r\n return rejected\r\n }\r\n\r\n if (this._bodyBlob) {\r\n return Promise.resolve(this._bodyBlob)\r\n } else if (this._bodyArrayBuffer) {\r\n return Promise.resolve(new Blob([this._bodyArrayBuffer]))\r\n } else if (this._bodyFormData) {\r\n throw new Error('could not read FormData body as blob')\r\n } else {\r\n return Promise.resolve(new Blob([this._bodyText]))\r\n }\r\n }\r\n\r\n this.arrayBuffer = function() {\r\n if (this._bodyArrayBuffer) {\r\n var isConsumed = consumed(this)\r\n if (isConsumed) {\r\n return isConsumed\r\n }\r\n if (ArrayBuffer.isView(this._bodyArrayBuffer)) {\r\n return Promise.resolve(\r\n this._bodyArrayBuffer.buffer.slice(\r\n this._bodyArrayBuffer.byteOffset,\r\n this._bodyArrayBuffer.byteOffset + this._bodyArrayBuffer.byteLength\r\n )\r\n )\r\n } else {\r\n return Promise.resolve(this._bodyArrayBuffer)\r\n }\r\n } else {\r\n return this.blob().then(readBlobAsArrayBuffer)\r\n }\r\n }\r\n }\r\n\r\n this.text = function() {\r\n var rejected = consumed(this)\r\n if (rejected) {\r\n return rejected\r\n }\r\n\r\n if (this._bodyBlob) {\r\n return readBlobAsText(this._bodyBlob)\r\n } else if (this._bodyArrayBuffer) {\r\n return Promise.resolve(readArrayBufferAsText(this._bodyArrayBuffer))\r\n } else if (this._bodyFormData) {\r\n throw new Error('could not read FormData body as text')\r\n } else {\r\n return Promise.resolve(this._bodyText)\r\n }\r\n }\r\n\r\n if (support.formData) {\r\n this.formData = function() {\r\n return this.text().then(decode)\r\n }\r\n }\r\n\r\n this.json = function() {\r\n return this.text().then(JSON.parse)\r\n }\r\n\r\n return this\r\n}\r\n\r\n// HTTP methods whose capitalization should be normalized\r\nvar methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT']\r\n\r\nfunction normalizeMethod(method) {\r\n var upcased = method.toUpperCase()\r\n return methods.indexOf(upcased) > -1 ? upcased : method\r\n}\r\n\r\nexport function Request(input, options) {\r\n if (!(this instanceof Request)) {\r\n throw new TypeError('Please use the \"new\" operator, this DOM object constructor cannot be called as a function.')\r\n }\r\n\r\n options = options || {}\r\n var body = options.body\r\n\r\n if (input instanceof Request) {\r\n if (input.bodyUsed) {\r\n throw new TypeError('Already read')\r\n }\r\n this.url = input.url\r\n this.credentials = input.credentials\r\n if (!options.headers) {\r\n this.headers = new Headers(input.headers)\r\n }\r\n this.method = input.method\r\n this.mode = input.mode\r\n this.signal = input.signal\r\n if (!body && input._bodyInit != null) {\r\n body = input._bodyInit\r\n input.bodyUsed = true\r\n }\r\n } else {\r\n this.url = String(input)\r\n }\r\n\r\n this.credentials = options.credentials || this.credentials || 'same-origin'\r\n if (options.headers || !this.headers) {\r\n this.headers = new Headers(options.headers)\r\n }\r\n this.method = normalizeMethod(options.method || this.method || 'GET')\r\n this.mode = options.mode || this.mode || null\r\n this.signal = options.signal || this.signal\r\n this.referrer = null\r\n\r\n if ((this.method === 'GET' || this.method === 'HEAD') && body) {\r\n throw new TypeError('Body not allowed for GET or HEAD requests')\r\n }\r\n this._initBody(body)\r\n\r\n if (this.method === 'GET' || this.method === 'HEAD') {\r\n if (options.cache === 'no-store' || options.cache === 'no-cache') {\r\n // Search for a '_' parameter in the query string\r\n var reParamSearch = /([?&])_=[^&]*/\r\n if (reParamSearch.test(this.url)) {\r\n // If it already exists then set the value with the current time\r\n this.url = this.url.replace(reParamSearch, '$1_=' + new Date().getTime())\r\n } else {\r\n // Otherwise add a new '_' parameter to the end with the current time\r\n var reQueryString = /\\?/\r\n this.url += (reQueryString.test(this.url) ? '&' : '?') + '_=' + new Date().getTime()\r\n }\r\n }\r\n }\r\n}\r\n\r\nRequest.prototype.clone = function() {\r\n return new Request(this, {body: this._bodyInit})\r\n}\r\n\r\nfunction decode(body) {\r\n var form = new FormData()\r\n body\r\n .trim()\r\n .split('&')\r\n .forEach(function(bytes) {\r\n if (bytes) {\r\n var split = bytes.split('=')\r\n var name = split.shift().replace(/\\+/g, ' ')\r\n var value = split.join('=').replace(/\\+/g, ' ')\r\n form.append(decodeURIComponent(name), decodeURIComponent(value))\r\n }\r\n })\r\n return form\r\n}\r\n\r\nfunction parseHeaders(rawHeaders) {\r\n var headers = new Headers()\r\n // Replace instances of \\r\\n and \\n followed by at least one space or horizontal tab with a space\r\n // https://tools.ietf.org/html/rfc7230#section-3.2\r\n var preProcessedHeaders = rawHeaders.replace(/\\r?\\n[\\t ]+/g, ' ')\r\n // Avoiding split via regex to work around a common IE11 bug with the core-js 3.6.0 regex polyfill\r\n // https://github.com/github/fetch/issues/748\r\n // https://github.com/zloirock/core-js/issues/751\r\n preProcessedHeaders\r\n .split('\\r')\r\n .map(function(header) {\r\n return header.indexOf('\\n') === 0 ? header.substr(1, header.length) : header\r\n })\r\n .forEach(function(line) {\r\n var parts = line.split(':')\r\n var key = parts.shift().trim()\r\n if (key) {\r\n var value = parts.join(':').trim()\r\n headers.append(key, value)\r\n }\r\n })\r\n return headers\r\n}\r\n\r\nfunction parseUniappHeaders(rawHeaders) {\r\n var headers = new Headers()\r\n for(var key in rawHeaders){\r\n headers.append(key, rawHeaders[key])\r\n }\r\n return headers\r\n}\r\n\r\n\r\nBody.call(Request.prototype)\r\n\r\nexport function Response(bodyInit, options) {\r\n if (!(this instanceof Response)) {\r\n throw new TypeError('Please use the \"new\" operator, this DOM object constructor cannot be called as a function.')\r\n }\r\n if (!options) {\r\n options = {}\r\n }\r\n\r\n this.type = 'default'\r\n this.status = options.status === undefined ? 200 : options.status\r\n this.ok = this.status >= 200 && this.status < 300\r\n this.statusText = options.statusText === undefined ? '' : '' + options.statusText\r\n this.headers = new Headers(options.headers)\r\n this.url = options.url || ''\r\n this._initBody(bodyInit)\r\n}\r\n\r\nBody.call(Response.prototype)\r\n\r\nResponse.prototype.clone = function() {\r\n return new Response(this._bodyInit, {\r\n status: this.status,\r\n statusText: this.statusText,\r\n headers: new Headers(this.headers),\r\n url: this.url\r\n })\r\n}\r\n\r\nResponse.error = function() {\r\n var response = new Response(null, {status: 0, statusText: ''})\r\n response.type = 'error'\r\n return response\r\n}\r\n\r\nvar redirectStatuses = [301, 302, 303, 307, 308]\r\n\r\nResponse.redirect = function(url, status) {\r\n if (redirectStatuses.indexOf(status) === -1) {\r\n throw new RangeError('Invalid status code')\r\n }\r\n\r\n return new Response(null, {status: status, headers: {location: url}})\r\n}\r\n\r\nexport var DOMException = global.DOMException\r\ntry {\r\n new DOMException()\r\n} catch (err) {\r\n DOMException = function(message, name) {\r\n this.message = message\r\n this.name = name\r\n var error = Error(message)\r\n this.stack = error.stack\r\n }\r\n DOMException.prototype = Object.create(Error.prototype)\r\n DOMException.prototype.constructor = DOMException\r\n}\r\n\r\n// 从 whatwg-fetch 项目改写\r\nexport function fetch(input, init) {\r\n return new Promise(function(resolve, reject) {\r\n var request = new Request(input, init)\r\n\r\n if (request.signal && request.signal.aborted) {\r\n return reject(new DOMException('Aborted', 'AbortError'))\r\n }\r\n\r\n function fixUrl(url) {\r\n try {\r\n return url === '' && global.location.href ? global.location.href : url\r\n } catch (e) {\r\n return url\r\n }\r\n }\r\n function isJson(json) {\r\n try {\r\n if (typeof json == \"object\") {\r\n return true;\r\n }\r\n if (typeof json == \"string\") {\r\n if (typeof JSON.parse(str) == \"object\") {\r\n return true;\r\n }\r\n }\r\n } catch(e) {\r\n }\r\n return false;\r\n }\r\n function toStr(json) {\r\n try {\r\n if (typeof json == \"object\") {\r\n return JSON.stringify(json);\r\n }\r\n if (typeof json == \"string\") {\r\n return json;\r\n }\r\n } catch(e) {\r\n }\r\n return json.toString();\r\n }\r\n\r\n\r\n let rawBody = typeof request._bodyInit === 'undefined' ? null : request._bodyInit;\r\n if(request.headers.hasOwnProperty('Content-Type') && request.headers['Content-Type'].indexOf('application/json') >= 0){\r\n if(request.method.toUpperCase() === 'POST'){\r\n rawBody = JSON.parse(rawBody); // uniapp框架遇到 method = 'POST' 且 Content-Type = 'application/json' 会自动序列化\r\n }\r\n }\r\n const requestTask = uni.request({\r\n url: fixUrl(request.url),\r\n method: request.method,\r\n data: rawBody,\r\n header: request.headers.map,\r\n complete: (resp)=> {\r\n // Logger.info(resp);\r\n if (request.signal) {\r\n request.signal.removeEventListener('abort', abortXhr);\r\n }\r\n if(resp.errMsg.indexOf('fail') >= 0){\r\n setTimeout(function() {\r\n reject(new TypeError('Network request failed'))\r\n }, 0);\r\n return;\r\n }\r\n // if(resp.statusCode !== 200){\r\n // setTimeout(function() {\r\n // reject(new TypeError('Network request failed, statusCode:' + resp.statusCode + \" full text:\" + JSON.stringify(resp.data)))\r\n // }, 0)\r\n // return;\r\n // }\r\n var options = {\r\n status: resp.statusCode,\r\n statusText: resp.data ? toStr(resp.data) : '',\r\n headers: parseUniappHeaders(resp.header || {})\r\n };\r\n options.url = options.headers.get('X-Request-URL')\r\n var body = options.statusText;\r\n setTimeout(function() {\r\n resolve(new Response(body, options))\r\n }, 0)\r\n\r\n }\r\n });\r\n function abortXhr() {\r\n requestTask.abort()\r\n }\r\n if (request.signal) {\r\n request.signal.addEventListener('abort', abortXhr)\r\n }\r\n\r\n })\r\n}\r\n\r\nfetch.polyfill = true\r\n\r\nif (!global.fetch) {\r\n global.fetch = fetch\r\n global.Headers = Headers\r\n global.Request = Request\r\n global.Response = Response\r\n}\r\n","var _globalThis;\nif (typeof globalThis === 'object') {\n\t_globalThis = globalThis;\n} else {\n\ttry {\n\t\t_globalThis = require('es5-ext/global');\n\t} catch (error) {\n\t} finally {\n\t\tif (!_globalThis && typeof window !== 'undefined') { _globalThis = window; }\n\t\tif (!_globalThis) { throw new Error('Could not determine global this'); }\n\t}\n}\n\nvar NativeWebSocket = _globalThis.WebSocket || _globalThis.MozWebSocket;\nvar websocket_version = require('./version');\n\n\n/**\n * Expose a W3C WebSocket class with just one or two arguments.\n */\nfunction W3CWebSocket(uri, protocols) {\n\tvar native_instance;\n\n\tif (protocols) {\n\t\tnative_instance = new NativeWebSocket(uri, protocols);\n\t}\n\telse {\n\t\tnative_instance = new NativeWebSocket(uri);\n\t}\n\n\t/**\n\t * 'native_instance' is an instance of nativeWebSocket (the browser's WebSocket\n\t * class). Since it is an Object it will be returned as it is when creating an\n\t * instance of W3CWebSocket via 'new W3CWebSocket()'.\n\t *\n\t * ECMAScript 5: http://bclary.com/2004/11/07/#a-13.2.2\n\t */\n\treturn native_instance;\n}\nif (NativeWebSocket) {\n\t['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED'].forEach(function(prop) {\n\t\tObject.defineProperty(W3CWebSocket, prop, {\n\t\t\tget: function() { return NativeWebSocket[prop]; }\n\t\t});\n\t});\n}\n\n/**\n * Module exports.\n */\nmodule.exports = {\n 'w3cwebsocket' : NativeWebSocket ? W3CWebSocket : null,\n 'version' : websocket_version\n};\n","var naiveFallback = function () {\n\tif (typeof self === \"object\" && self) return self;\n\tif (typeof window === \"object\" && window) return window;\n\tthrow new Error(\"Unable to resolve global `this`\");\n};\n\nmodule.exports = (function () {\n\tif (this) return this;\n\n\t// Unexpected strict mode (may happen if e.g. bundled into ESM module)\n\n\t// Fallback to standard globalThis if available\n\tif (typeof globalThis === \"object\" && globalThis) return globalThis;\n\n\t// Thanks @mathiasbynens -> https://mathiasbynens.be/notes/globalthis\n\t// In all ES5+ engines global object inherits from Object.prototype\n\t// (if you approached one that doesn't please report)\n\ttry {\n\t\tObject.defineProperty(Object.prototype, \"__global__\", {\n\t\t\tget: function () { return this; },\n\t\t\tconfigurable: true\n\t\t});\n\t} catch (error) {\n\t\t// Unfortunate case of updates to Object.prototype being restricted\n\t\t// via preventExtensions, seal or freeze\n\t\treturn naiveFallback();\n\t}\n\ttry {\n\t\t// Safari case (window.__global__ works, but __global__ does not)\n\t\tif (!__global__) return naiveFallback();\n\t\treturn __global__;\n\t} finally {\n\t\tdelete Object.prototype.__global__;\n\t}\n})();\n","module.exports = require('../package.json').version;\n","\"use strict\";\r\nexports.__esModule = true;\r\nexports.RequestBase = void 0;\r\nvar RequestBase = /** @class */ (function () {\r\n function RequestBase(appId, clientType, imei) {\r\n this.appId = appId;\r\n this.clientType = clientType;\r\n this.imei = imei;\r\n }\r\n return RequestBase;\r\n}());\r\nexports.RequestBase = RequestBase;\r\n","\"use strict\";\r\nexports.__esModule = true;\r\nexports.RequestParams = void 0;\r\nvar RequestParams = /** @class */ (function () {\r\n function RequestParams(appId, identifier, userSign) {\r\n this.appId = appId;\r\n this.identifier = identifier;\r\n this.userSign = userSign;\r\n }\r\n return RequestParams;\r\n}());\r\nexports.RequestParams = RequestParams;\r\n","\"use strict\";\r\nexports.__esModule = true;\r\nvar Logger_1 = require(\"../log/Logger\");\r\nvar ImClient_1 = require(\"./ImClient\");\r\nvar ApiResponse_1 = require(\"../model/ApiResponse\");\r\nvar utils_1 = require(\"../common/utils\");\r\nvar Fetch_1 = require(\"../common/Fetch\");\r\nvar HttpApi = /** @class */ (function () {\r\n function HttpApi(url) {\r\n this.url = \"\"; //http://127.0.0.1:8000/v1\r\n this.url = url;\r\n }\r\n HttpApi.prototype.call = function (url, params, body) {\r\n var userId = ImClient_1.imClient.userId;\r\n Logger_1[\"default\"].info(userId);\r\n var reqUrl = this.url + url;\r\n if (params != null) {\r\n var paramStr = this.setQueryConfig(params);\r\n console.log(paramStr);\r\n reqUrl += paramStr;\r\n }\r\n var requestMethod = \"POST\";\r\n var headers = {\r\n 'Content-Type': 'application/json',\r\n };\r\n var request = { method: requestMethod, headers: headers, mode: 'cors', body: utils_1[\"default\"].json(body) };\r\n return this.httpFetch(reqUrl, request);\r\n };\r\n HttpApi.prototype.setQueryConfig = function (params) {\r\n var _str = \"?\";\r\n for (var o in params) {\r\n _str += o + \"=\" + params[o] + \"&\";\r\n }\r\n var _str = _str.substring(0, _str.length - 1); //末尾是&\r\n return _str;\r\n };\r\n HttpApi.prototype.httpFetch = function (url, request) {\r\n var _this = this;\r\n console.log(\"httpFetch\");\r\n var rnfetch1 = Fetch_1[\"default\"].getFetchToolkit();\r\n return rnfetch1(url, request).then(function (response) {\r\n console.log(response);\r\n return response.json();\r\n }).then(function (res) {\r\n Logger_1[\"default\"].info(\"==> [\" + request.method + \"] \" + url + \" back:\" + utils_1[\"default\"].json(res));\r\n var resp = _this.response2ApiResponse(res);\r\n if (resp.isFailed()) {\r\n return Promise.reject(resp);\r\n }\r\n // return Promise.resolve(this.response2ApiResponse(res));\r\n return Promise.resolve(resp);\r\n });\r\n };\r\n HttpApi.prototype.response2ApiResponse = function (response) {\r\n var apiResponse = new ApiResponse_1[\"default\"](true);\r\n apiResponse.data = response.data;\r\n apiResponse.msg = response.msg;\r\n apiResponse.code = response.code;\r\n return apiResponse;\r\n };\r\n return HttpApi;\r\n}());\r\nexports[\"default\"] = HttpApi;\r\n// export const httpApi = new HttpApi();\r\n","\"use strict\";\r\nexports.__esModule = true;\r\nvar ApiResponse = /** @class */ (function () {\r\n function ApiResponse(succeed) {\r\n if (succeed === void 0) { succeed = false; }\r\n this.msg = '';\r\n this.data = null;\r\n if (succeed) {\r\n this.code = 200;\r\n }\r\n }\r\n ApiResponse.prototype.isSucceed = function () {\r\n return this.code === 200;\r\n };\r\n ApiResponse.prototype.isFailed = function () {\r\n return !this.isSucceed();\r\n };\r\n return ApiResponse;\r\n}());\r\nexports[\"default\"] = ApiResponse;\r\n","\"use strict\";\r\nexports.__esModule = true;\r\nexports.ConversationEventCommand = exports.UserEventCommand = exports.SystemCommand = exports.GroupCommand = exports.FriendShipCommand = exports.MessageCommand = void 0;\r\nvar MessageCommand;\r\n(function (MessageCommand) {\r\n MessageCommand[MessageCommand[\"MSG_P2P\"] = 1103] = \"MSG_P2P\";\r\n MessageCommand[MessageCommand[\"MSG_P2P_SYNC\"] = 1108] = \"MSG_P2P_SYNC\";\r\n //发送消息已读 1106\r\n MessageCommand[MessageCommand[\"MSG_READED\"] = 1106] = \"MSG_READED\";\r\n //消息接收ack\r\n MessageCommand[MessageCommand[\"MSG_RECIVE_ACK\"] = 1107] = \"MSG_RECIVE_ACK\";\r\n //单聊消息ACK 1046\r\n MessageCommand[MessageCommand[\"MSG_ACK\"] = 1046] = \"MSG_ACK\";\r\n // 消息撤回 1050\r\n MessageCommand[MessageCommand[\"MSG_RECALL\"] = 1050] = \"MSG_RECALL\";\r\n // //消息撤回通知 1052\r\n MessageCommand[MessageCommand[\"MSG_RECALL_NOTIFY\"] = 1052] = \"MSG_RECALL_NOTIFY\";\r\n // 消息撤回回包 1051\r\n MessageCommand[MessageCommand[\"MSG_RECALL_ACK\"] = 1051] = \"MSG_RECALL_ACK\";\r\n // //消息已读通知 1053\r\n MessageCommand[MessageCommand[\"MSG_READED_NOTIFY\"] = 1053] = \"MSG_READED_NOTIFY\";\r\n})(MessageCommand || (MessageCommand = {}));\r\nexports.MessageCommand = MessageCommand;\r\nvar FriendShipCommand;\r\n(function (FriendShipCommand) {\r\n //添加好友 3000\r\n FriendShipCommand[FriendShipCommand[\"FRIEND_ADD\"] = 3000] = \"FRIEND_ADD\";\r\n //更新好友 3001\r\n FriendShipCommand[FriendShipCommand[\"FRIEND_UPDATE\"] = 3001] = \"FRIEND_UPDATE\";\r\n //删除好友 3002\r\n FriendShipCommand[FriendShipCommand[\"FRIEND_DELETE\"] = 3002] = \"FRIEND_DELETE\";\r\n //好友申请 3003\r\n FriendShipCommand[FriendShipCommand[\"FRIEND_REQUEST\"] = 3003] = \"FRIEND_REQUEST\";\r\n //好友申请已读 3004\r\n FriendShipCommand[FriendShipCommand[\"FRIEND_REQUEST_READ\"] = 3004] = \"FRIEND_REQUEST_READ\";\r\n //好友申请审批 3005\r\n FriendShipCommand[FriendShipCommand[\"FRIEND_REQUEST_APPROVER\"] = 3005] = \"FRIEND_REQUEST_APPROVER\";\r\n //添加黑名单 3010\r\n FriendShipCommand[FriendShipCommand[\"FRIEND_BLACK_ADD\"] = 3010] = \"FRIEND_BLACK_ADD\";\r\n //移除黑名单 3011\r\n FriendShipCommand[FriendShipCommand[\"FRIEND_BLACK_DELETE\"] = 3011] = \"FRIEND_BLACK_DELETE\";\r\n //新建好友分组 3012\r\n FriendShipCommand[FriendShipCommand[\"FRIEND_GROUP_ADD\"] = 3012] = \"FRIEND_GROUP_ADD\";\r\n //删除好友分组 3013\r\n FriendShipCommand[FriendShipCommand[\"FRIEND_GROUP_DELETE\"] = 3013] = \"FRIEND_GROUP_DELETE\";\r\n //好友分组添加成员 3014\r\n FriendShipCommand[FriendShipCommand[\"FRIEND_GROUP_MEMBER_ADD\"] = 3014] = \"FRIEND_GROUP_MEMBER_ADD\";\r\n //好友分组移除成员 3015\r\n FriendShipCommand[FriendShipCommand[\"FRIEND_GROUP_MEMBER_DELETE\"] = 3015] = \"FRIEND_GROUP_MEMBER_DELETE\";\r\n})(FriendShipCommand || (FriendShipCommand = {}));\r\nexports.FriendShipCommand = FriendShipCommand;\r\nvar GroupCommand;\r\n(function (GroupCommand) {\r\n /**\r\n * 推送申请入群通知 2000\r\n */\r\n GroupCommand[GroupCommand[\"JOIN_GROUP\"] = 2000] = \"JOIN_GROUP\";\r\n /**\r\n * 推送添加群成员 2001,通知给所有管理员和本人\r\n */\r\n GroupCommand[GroupCommand[\"ADDED_MEMBER\"] = 2001] = \"ADDED_MEMBER\";\r\n /**\r\n * 推送创建群组通知 2002,通知给所有人\r\n */\r\n GroupCommand[GroupCommand[\"CREATED_GROUP\"] = 2002] = \"CREATED_GROUP\";\r\n /**\r\n * 推送更新群组通知 2003,通知给所有人\r\n */\r\n GroupCommand[GroupCommand[\"UPDATED_GROUP\"] = 2003] = \"UPDATED_GROUP\";\r\n /**\r\n * 推送退出群组通知 2004,通知给管理员和操作人\r\n */\r\n GroupCommand[GroupCommand[\"EXIT_GROUP\"] = 2004] = \"EXIT_GROUP\";\r\n /**\r\n * 推送修改群成员通知 2005,通知给管理员和被操作人\r\n */\r\n GroupCommand[GroupCommand[\"UPDATED_MEMBER\"] = 2005] = \"UPDATED_MEMBER\";\r\n /**\r\n * 推送删除群成员通知 2006,通知给所有群成员和被踢人\r\n */\r\n GroupCommand[GroupCommand[\"DELETED_MEMBER\"] = 2006] = \"DELETED_MEMBER\";\r\n /**\r\n * 推送解散群通知 2007,通知所有人\r\n */\r\n GroupCommand[GroupCommand[\"DESTROY_GROUP\"] = 2007] = \"DESTROY_GROUP\";\r\n /**\r\n * 推送转让群主 2008,通知所有人\r\n */\r\n GroupCommand[GroupCommand[\"TRANSFER_GROUP\"] = 2008] = \"TRANSFER_GROUP\";\r\n /**\r\n * 禁言群 2009,通知所有人\r\n */\r\n GroupCommand[GroupCommand[\"MUTE_GROUP\"] = 2009] = \"MUTE_GROUP\";\r\n /**\r\n * 禁言/解禁 群成员 2010,通知管理员和被操作人\r\n */\r\n GroupCommand[GroupCommand[\"SPEAK_GOUP_MEMBER\"] = 2010] = \"SPEAK_GOUP_MEMBER\";\r\n //群聊消息收发 2104\r\n GroupCommand[GroupCommand[\"MSG_GROUP\"] = 2104] = \"MSG_GROUP\";\r\n //群聊消息收发同步消息 2105\r\n GroupCommand[GroupCommand[\"MSG_GROUP_SYNC\"] = 2105] = \"MSG_GROUP_SYNC\";\r\n //群聊消息ACK 2047\r\n GroupCommand[GroupCommand[\"GROUP_MSG_ACK\"] = 2047] = \"GROUP_MSG_ACK\";\r\n})(GroupCommand || (GroupCommand = {}));\r\nexports.GroupCommand = GroupCommand;\r\nvar SystemCommand;\r\n(function (SystemCommand) {\r\n //心跳 9999\r\n SystemCommand[SystemCommand[\"PING\"] = 9999] = \"PING\";\r\n //登陸 9000\r\n SystemCommand[SystemCommand[\"LOGIN\"] = 9000] = \"LOGIN\";\r\n //登录ack 9001\r\n SystemCommand[SystemCommand[\"LOGINACK\"] = 9001] = \"LOGINACK\";\r\n //下线通知 用于多端互斥 9002\r\n SystemCommand[SystemCommand[\"MUTUALLOGIN\"] = 9002] = \"MUTUALLOGIN\";\r\n //登出 9003\r\n SystemCommand[SystemCommand[\"LOGOUT\"] = 9003] = \"LOGOUT\";\r\n})(SystemCommand || (SystemCommand = {}));\r\nexports.SystemCommand = SystemCommand;\r\nvar UserEventCommand;\r\n(function (UserEventCommand) {\r\n //4000\r\n UserEventCommand[UserEventCommand[\"USER_MODIFY\"] = 4000] = \"USER_MODIFY\";\r\n //4001\r\n UserEventCommand[UserEventCommand[\"USER_ONLINE_STATUS_CHANGE\"] = 4001] = \"USER_ONLINE_STATUS_CHANGE\";\r\n //4002 在线状态订阅\r\n UserEventCommand[UserEventCommand[\"USER_ONLINE_STATUS_SUBSCRIBE\"] = 4002] = \"USER_ONLINE_STATUS_SUBSCRIBE\";\r\n //4003 拉取订阅的在线状态好友,只发送给请求端\r\n UserEventCommand[UserEventCommand[\"PULL_USER_ONLINE_STATUS\"] = 4003] = \"PULL_USER_ONLINE_STATUS\";\r\n //4004 用户在线状态通知报文\r\n UserEventCommand[UserEventCommand[\"USER_ONLINE_STATUS_CHANGE_NOTIFY\"] = 4004] = \"USER_ONLINE_STATUS_CHANGE_NOTIFY\";\r\n})(UserEventCommand || (UserEventCommand = {}));\r\nexports.UserEventCommand = UserEventCommand;\r\nvar ConversationEventCommand;\r\n(function (ConversationEventCommand) {\r\n //5000 会话删除\r\n ConversationEventCommand[ConversationEventCommand[\"CONVERSATION_DELETE\"] = 5000] = \"CONVERSATION_DELETE\";\r\n //5001 会话修改\r\n ConversationEventCommand[ConversationEventCommand[\"CONVERSATION_UPDATE\"] = 5001] = \"CONVERSATION_UPDATE\";\r\n})(ConversationEventCommand || (ConversationEventCommand = {}));\r\nexports.ConversationEventCommand = ConversationEventCommand;\r\n","\"use strict\";\r\nexports.__esModule = true;\r\nexports.MessagePack = void 0;\r\nvar utils_1 = require(\"../common/utils\");\r\nvar MessagePack = /** @class */ (function () {\r\n function MessagePack(appId) {\r\n this.messageId = utils_1[\"default\"].uuid();\r\n this.appId = appId;\r\n this.messageRandom = this.RangeInteger(0, 10000);\r\n this.messageTime = Date.parse(new Date().toString());\r\n }\r\n MessagePack.prototype.RangeInteger = function (min, max) {\r\n var range = max - min;\r\n var value = Math.floor(Math.random() * range) + min;\r\n return value;\r\n };\r\n MessagePack.prototype.buildTxtMessagePack = function (fromId, toId, text) {\r\n this.fromId = fromId;\r\n this.toId = toId;\r\n var body = { type: 1, content: text };\r\n this.messageBody = utils_1[\"default\"].json(body);\r\n };\r\n return MessagePack;\r\n}());\r\nexports.MessagePack = MessagePack;\r\n"],"sourceRoot":""} \ No newline at end of file diff --git a/l-im-app-imooc-master/l-im-app-imooc/common/imSdk/sdk-bridge.js b/l-im-app-imooc-master/l-im-app-imooc/common/imSdk/sdk-bridge.js new file mode 100644 index 0000000..ad533ea --- /dev/null +++ b/l-im-app-imooc-master/l-im-app-imooc/common/imSdk/sdk-bridge.js @@ -0,0 +1,15 @@ + +function getIM(){ + // UNIAPP 环境 + if(typeof uni !== 'undefined'){ + return {im:uni['im'], im_webtoolkit:uni['im_webtoolkit']}; + } + throw Error(" Couldn't not fetch lim."); +} + + +const lim = { + im: getIM().im, +}; + +module.exports = lim; diff --git a/l-im-app-imooc-master/l-im-app-imooc/common/lib/config.js b/l-im-app-imooc-master/l-im-app-imooc/common/lib/config.js new file mode 100644 index 0000000..86761f5 --- /dev/null +++ b/l-im-app-imooc-master/l-im-app-imooc/common/lib/config.js @@ -0,0 +1,6 @@ +export default { + + baseUrl:"http://127.0.0.1:8989", + version: "/v1", + +} \ No newline at end of file diff --git a/l-im-app-imooc-master/l-im-app-imooc/common/lib/request.js b/l-im-app-imooc-master/l-im-app-imooc/common/lib/request.js new file mode 100644 index 0000000..5d25dcb --- /dev/null +++ b/l-im-app-imooc-master/l-im-app-imooc/common/lib/request.js @@ -0,0 +1,91 @@ +import $C from './config.js'; +import $store from '@/store/index.js'; +export default { + // 全局配置 + common: { + baseUrl: $C.baseUrl + $C.version, + header: { + 'Content-Type': 'application/json;charset=UTF-8', + }, + data: {}, + method: 'GET', + dataType: 'json', + token: true, + }, + + // get请求 + get(url, data = {}, options = {}) { + options.url = url + options.data = data + options.method = 'GET' + return this.request(options) + }, + // post请求 + post(url, data = {}, options = {}) { + options.url = url + options.data = data + options.method = 'POST' + return this.request(options) + }, + // delete请求 + del(url, data = {}, options = {}) { + options.url = url + options.data = data + options.method = 'DELETE' + return this.request(options) + }, + + // 请求 返回promise + request(options = {}) { + // 组织参数 + options.url = this.common.baseUrl + options.url + options.header = options.header || this.common.header + options.data = options.data || this.common.data + options.method = options.method || this.common.method + options.dataType = options.dataType || this.common.dataType + options.token = options.token === false ? false : this.common.token + + // 请求 + return new Promise((res, rej) => { + // 请求中... + uni.request({ + ...options, + success: (result) => { + // 返回原始数据 + if (options.native) { + return res(result) + } + // 服务端失败 + if (result.statusCode !== 200) { + if (options.toast !== false) { + uni.showToast({ + title: result.data.data || '服务器失败', + icon: 'none' + }); + } + // token不合法,直接退出登录 + if (result.data.code === 401) { + return uni.reLaunch({ + url: '/pages/common/login/login', + }) + } + return rej(result.data) + } + // 成功 + let data = result.data + + res(data) + }, + fail: (error) => { + uni.showToast({ + title: '请求失败', + icon: 'none' + }); + return rej(error) + } + }); + }) + } + + +} diff --git a/l-im-app-imooc-master/l-im-app-imooc/common/lib/time.js b/l-im-app-imooc-master/l-im-app-imooc/common/lib/time.js new file mode 100644 index 0000000..0542b6b --- /dev/null +++ b/l-im-app-imooc-master/l-im-app-imooc/common/lib/time.js @@ -0,0 +1,65 @@ +export default{ + + // 获取聊天时间(相差300s内的信息不会显示时间) + getChatTime(v1,v2){ + v1=v1.toString().length<13 ? v1*1000 : v1; + v2=v2.toString().length<13 ? v2*1000 : v2; + if(((parseInt(v1)-parseInt(v2))/1000) > 300){ + return this.gettime(v1); + } + }, + // 人性化时间格式 + gettime(shorttime){ + shorttime=shorttime.toString().length<13 ? shorttime*1000 : shorttime; + let now = (new Date()).getTime(); + let cha = (now-parseInt(shorttime))/1000; + + if (cha < 43200) { + // 当天 + return this.dateFormat(new Date(shorttime),"{A} {t}:{ii}"); + } else if(cha < 518400){ + // 隔天 显示日期+时间 + return this.dateFormat(new Date(shorttime),"{Mon}月{DD}日 {A} {t}:{ii}"); + } else { + // 隔年 显示完整日期+时间 + return this.dateFormat(new Date(shorttime),"{Y}-{MM}-{DD} {A} {t}:{ii}"); + } + }, + + parseNumber(num) { + return num < 10 ? "0" + num : num; + }, + + dateFormat(date, formatStr) { + let dateObj = {}, + rStr = /\{([^}]+)\}/, + mons = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12']; + + dateObj["Y"] = date.getFullYear(); + dateObj["M"] = date.getMonth() + 1; + dateObj["MM"] = this.parseNumber(dateObj["M"]); + dateObj["Mon"] = mons[dateObj['M'] - 1]; + dateObj["D"] = date.getDate(); + dateObj["DD"] = this.parseNumber(dateObj["D"]); + dateObj["h"] = date.getHours(); + dateObj["hh"] = this.parseNumber(dateObj["h"]); + dateObj["t"] = dateObj["h"] > 12 ? dateObj["h"] - 12 : dateObj["h"]; + dateObj["tt"] = this.parseNumber(dateObj["t"]); + dateObj["A"] = dateObj["h"] > 12 ? '下午' : '上午'; + dateObj["i"] = date.getMinutes(); + dateObj["ii"] = this.parseNumber(dateObj["i"]); + dateObj["s"] = date.getSeconds(); + dateObj["ss"] = this.parseNumber(dateObj["s"]); + + while(rStr.test(formatStr)) { + formatStr = formatStr.replace(rStr, dateObj[RegExp.$1]); + } + return formatStr; + }, + // 获取年龄 + getAgeByBirthday(data){ + let birthday=new Date(data.replace(/-/g, "\/")); + let d=new Date(); + return d.getFullYear()-birthday.getFullYear()-((d.getMonth() + + + + + + diff --git a/l-im-app-imooc-master/l-im-app-imooc/components/ui/badge.vue b/l-im-app-imooc-master/l-im-app-imooc/components/ui/badge.vue new file mode 100644 index 0000000..b7cdb43 --- /dev/null +++ b/l-im-app-imooc-master/l-im-app-imooc/components/ui/badge.vue @@ -0,0 +1,28 @@ + + + + + diff --git a/l-im-app-imooc-master/l-im-app-imooc/components/ui/chat-item.vue b/l-im-app-imooc-master/l-im-app-imooc/components/ui/chat-item.vue new file mode 100644 index 0000000..deacbf0 --- /dev/null +++ b/l-im-app-imooc-master/l-im-app-imooc/components/ui/chat-item.vue @@ -0,0 +1,159 @@ + + + + + diff --git a/l-im-app-imooc-master/l-im-app-imooc/components/ui/confirm.vue b/l-im-app-imooc-master/l-im-app-imooc/components/ui/confirm.vue new file mode 100644 index 0000000..f76cb28 --- /dev/null +++ b/l-im-app-imooc-master/l-im-app-imooc/components/ui/confirm.vue @@ -0,0 +1,62 @@ + + + + + diff --git a/l-im-app-imooc-master/l-im-app-imooc/components/ui/divider.vue b/l-im-app-imooc-master/l-im-app-imooc/components/ui/divider.vue new file mode 100644 index 0000000..c1b853a --- /dev/null +++ b/l-im-app-imooc-master/l-im-app-imooc/components/ui/divider.vue @@ -0,0 +1,26 @@ + + + + + + diff --git a/l-im-app-imooc-master/l-im-app-imooc/components/ui/fImage.vue b/l-im-app-imooc-master/l-im-app-imooc/components/ui/fImage.vue new file mode 100644 index 0000000..6177400 --- /dev/null +++ b/l-im-app-imooc-master/l-im-app-imooc/components/ui/fImage.vue @@ -0,0 +1,69 @@ + + + + + diff --git a/l-im-app-imooc-master/l-im-app-imooc/components/ui/icon-button.vue b/l-im-app-imooc-master/l-im-app-imooc/components/ui/icon-button.vue new file mode 100644 index 0000000..0c3d772 --- /dev/null +++ b/l-im-app-imooc-master/l-im-app-imooc/components/ui/icon-button.vue @@ -0,0 +1,21 @@ + + + + + diff --git a/l-im-app-imooc-master/l-im-app-imooc/components/ui/list-item.vue b/l-im-app-imooc-master/l-im-app-imooc/components/ui/list-item.vue new file mode 100644 index 0000000..e381380 --- /dev/null +++ b/l-im-app-imooc-master/l-im-app-imooc/components/ui/list-item.vue @@ -0,0 +1,71 @@ + + + + + diff --git a/l-im-app-imooc-master/l-im-app-imooc/components/ui/main-button.vue b/l-im-app-imooc-master/l-im-app-imooc/components/ui/main-button.vue new file mode 100644 index 0000000..e9e8b62 --- /dev/null +++ b/l-im-app-imooc-master/l-im-app-imooc/components/ui/main-button.vue @@ -0,0 +1,34 @@ + + + + + diff --git a/l-im-app-imooc-master/l-im-app-imooc/components/ui/media-list.vue b/l-im-app-imooc-master/l-im-app-imooc/components/ui/media-list.vue new file mode 100644 index 0000000..5625e9b --- /dev/null +++ b/l-im-app-imooc-master/l-im-app-imooc/components/ui/media-list.vue @@ -0,0 +1,76 @@ + + + + + diff --git a/l-im-app-imooc-master/l-im-app-imooc/components/ui/nav-bar.vue b/l-im-app-imooc-master/l-im-app-imooc/components/ui/nav-bar.vue new file mode 100644 index 0000000..b836019 --- /dev/null +++ b/l-im-app-imooc-master/l-im-app-imooc/components/ui/nav-bar.vue @@ -0,0 +1,182 @@ + + + + + diff --git a/l-im-app-imooc-master/l-im-app-imooc/components/ui/popup.vue b/l-im-app-imooc-master/l-im-app-imooc/components/ui/popup.vue new file mode 100644 index 0000000..26eb39d --- /dev/null +++ b/l-im-app-imooc-master/l-im-app-imooc/components/ui/popup.vue @@ -0,0 +1,157 @@ + + + + + diff --git a/l-im-app-imooc-master/l-im-app-imooc/index.html b/l-im-app-imooc-master/l-im-app-imooc/index.html new file mode 100644 index 0000000..c3ff205 --- /dev/null +++ b/l-im-app-imooc-master/l-im-app-imooc/index.html @@ -0,0 +1,20 @@ + + + + + + + + + + +
+ + + diff --git a/l-im-app-imooc-master/l-im-app-imooc/main.js b/l-im-app-imooc-master/l-im-app-imooc/main.js new file mode 100644 index 0000000..5efc038 --- /dev/null +++ b/l-im-app-imooc-master/l-im-app-imooc/main.js @@ -0,0 +1,21 @@ +import Vue from 'vue' +import App from './App' +import store from './store'; + +Vue.prototype.$store = store +Vue.config.productionTip = false + +const sdk = require("@/common/imSdk/lim-sdk.js"); +const lim = require("@/common/imSdk/sdk-bridge.js"); + +uni.lim = lim; +App.mpType = 'app' + +Vue.prototype.imsdk = lim + + +const app = new Vue({ + store, + ...App +}) +app.$mount() diff --git a/l-im-app-imooc-master/l-im-app-imooc/manifest.json b/l-im-app-imooc-master/l-im-app-imooc/manifest.json new file mode 100644 index 0000000..a9df793 --- /dev/null +++ b/l-im-app-imooc-master/l-im-app-imooc/manifest.json @@ -0,0 +1,100 @@ +{ + "name" : "l-im-app", + "appid" : "__UNI__621989A", + "description" : "l-im-app", + "versionName" : "1.0.0", + "versionCode" : "100", + "transformPx" : false, + /* 5+App特有相关 */ + "app-plus" : { + "nvueCompiler" : "uni-app", + "usingComponents" : true, + "splashscreen" : { + "alwaysShowBeforeRender" : true, + "waiting" : true, + "autoclose" : true, + "delay" : 0 + }, + /* 模块配置 */ + "modules" : { + "VideoPlayer" : {} + }, + /* 应用发布信息 */ + "distribute" : { + /* android打包配置 */ + "android" : { + "permissions" : [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ] + }, + /* ios打包配置 */ + "ios" : { + "UIBackgroundModes" : "audio", + "idfa" : false + }, + /* SDK配置 */ + "sdkConfigs" : {} + }, + "compilerVersion" : 3 + }, + /* 快应用特有相关 */ + "quickapp" : {}, + /* 小程序特有相关 */ + "mp-weixin" : { + "appid" : "", + "setting" : { + "urlCheck" : false + }, + "usingComponents" : true + }, + "mp-alipay" : { + "usingComponents" : true + }, + "mp-baidu" : { + "usingComponents" : true + }, + "mp-toutiao" : { + "usingComponents" : true + }, + "uniStatistics" : { + "enable" : false + }, + "vueVersion" : "2" + , + "h5": { + "devServer": { + "https": false, + "proxy": { + "/v1": { + "target": "http://127.0.0.1:8000/", + "changeOrigin": true, + "ws": true, + "pathRewrite": { + "^/v1": "" + } + } + } + } + } +} diff --git a/l-im-app-imooc-master/l-im-app-imooc/package-lock.json b/l-im-app-imooc-master/l-im-app-imooc/package-lock.json new file mode 100644 index 0000000..48e341a --- /dev/null +++ b/l-im-app-imooc-master/l-im-app-imooc/package-lock.json @@ -0,0 +1,3 @@ +{ + "lockfileVersion": 1 +} diff --git a/l-im-app-imooc-master/l-im-app-imooc/pages.json b/l-im-app-imooc-master/l-im-app-imooc/pages.json new file mode 100644 index 0000000..316cccd --- /dev/null +++ b/l-im-app-imooc-master/l-im-app-imooc/pages.json @@ -0,0 +1,85 @@ +{ + "pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages + { + "path": "pages/common/login/login", + "style": {} + }, { + "path": "pages/tabbar/index/index", + "style": { + "navigationBarTitleText": "uni-app" + } + }, { + "path": "pages/tabbar/mail/mail", + "style": { + "navigationBarTitleText": "", + "enablePullDownRefresh": false + } + + }, { + "path": "pages/chat/chat/chat", + "style": {} + }, { + "path": "pages/tabbar/find/find", + "style": { + "navigationBarTitleText": "", + "enablePullDownRefresh": false + } + + }, { + "path": "pages/tabbar/my/my", + "style": { + "navigationBarTitleText": "", + "enablePullDownRefresh": false + } + + }, { + "path": "pages/my/userinfo/userinfo", + "style": {} + }, { + "path": "pages/my/setting/setting", + "style": {} + } + ], + "globalStyle": { + "navigationBarTextStyle": "black", + "navigationBarTitleText": "l-im-app", + "navigationBarBackgroundColor": "#F8F8F8", + "backgroundColor": "#F8F8F8", + "app-plus": { + "titleNView": false, + "scrollIndicator": "none" + } + }, + "tabBar": { + "color": "#000000", + "selectedColor": "#06a1c0", + "borderStyle": "black", + "backgroundColor": "#F7F7F7", + "list": [{ + "iconPath": "static/tabbar/index.png", + "selectedIconPath": "static/tabbar/index-select.png", + "pagePath": "pages/tabbar/index/index", + "text": "首页" + }, + { + "iconPath": "static/tabbar/mail.png", + "selectedIconPath": "static/tabbar/mail-select.png", + "pagePath": "pages/tabbar/mail/mail", + "text": "通讯录" + }, + { + "iconPath": "static/tabbar/find.png", + "selectedIconPath": "static/tabbar/find-select.png", + "pagePath": "pages/tabbar/find/find", + "text": "发现" + }, + { + "iconPath": "static/tabbar/my.png", + "selectedIconPath": "static/tabbar/my-select.png", + "pagePath": "pages/tabbar/my/my", + "text": "我的" + } + ] + }, + "uniIdRouter": {} +} diff --git a/l-im-app-imooc-master/l-im-app-imooc/pages/chat/chat/chat.vue b/l-im-app-imooc-master/l-im-app-imooc/pages/chat/chat/chat.vue new file mode 100644 index 0000000..b761fe1 --- /dev/null +++ b/l-im-app-imooc-master/l-im-app-imooc/pages/chat/chat/chat.vue @@ -0,0 +1,433 @@ +