first commit
4
l-im-app-imooc-master/l-im-app-imooc/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
/unpackage
|
||||
/.hbuilderx
|
||||
/node_modules
|
||||
|
||||
43
l-im-app-imooc-master/l-im-app-imooc/App.vue
Normal file
0
l-im-app-imooc-master/l-im-app-imooc/README.md
Normal file
33
l-im-app-imooc-master/l-im-app-imooc/common/common.css
Normal file
@@ -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;
|
||||
}
|
||||
394
l-im-app-imooc-master/l-im-app-imooc/common/css.css
Normal file
@@ -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;
|
||||
}
|
||||
11
l-im-app-imooc-master/l-im-app-imooc/common/icon.css
Normal file
@@ -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;
|
||||
@@ -0,0 +1,6 @@
|
||||
export default {
|
||||
|
||||
baseUrl:"http://127.0.0.1:8989",
|
||||
version: "/v1",
|
||||
|
||||
}
|
||||
91
l-im-app-imooc-master/l-im-app-imooc/common/lib/request.js
Normal file
@@ -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)
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
65
l-im-app-imooc-master/l-im-app-imooc/common/lib/time.js
Normal file
@@ -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()<birthday.getMonth()|| d.getMonth()==birthday.getMonth() && d.getDate()<birthday.getDate())?1:0);
|
||||
}
|
||||
}
|
||||
30
l-im-app-imooc-master/l-im-app-imooc/common/mixin/auth.js
Normal file
@@ -0,0 +1,30 @@
|
||||
|
||||
export default {
|
||||
onShow() {
|
||||
var lim = this.imsdk
|
||||
var sdk = lim.im;
|
||||
let uid = sdk.getUserId();
|
||||
if(uid == '' || uid == undefined){
|
||||
uni.navigateTo({
|
||||
url: '/pages/common/login/login'
|
||||
});
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
navigate(path){
|
||||
uni.navigateTo({
|
||||
url: '/pages/'+path,
|
||||
});
|
||||
},
|
||||
// 返回并提示
|
||||
backToast(msg = '非法参数'){
|
||||
uni.showToast({
|
||||
title: msg,
|
||||
icon:"none"
|
||||
});
|
||||
uni.navigateBack({
|
||||
delta: 1,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import $Time from "@/common/lib/time.js"
|
||||
export default {
|
||||
filters: {
|
||||
formatTime(value) {
|
||||
return $Time.gettime(value);
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<template>
|
||||
<image :src="src ? src : '/static/images/userpic.png'" mode="widthFix" :style="getStyle" :class="type" @click="clickEvent"></image>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
size:{
|
||||
type:[String,Number],
|
||||
default:90
|
||||
},
|
||||
src: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
type:{
|
||||
type:String,
|
||||
default:"rounded"
|
||||
},
|
||||
clickType:{
|
||||
type:String,
|
||||
default:"none"
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
getStyle() {
|
||||
return `width: ${this.size}rpx;height: ${this.size}rpx;`
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
clickEvent() {
|
||||
|
||||
switch (this.clickType){
|
||||
case 'navigate':
|
||||
// console.log(this.clickType)
|
||||
uni.navigateTo({
|
||||
url: '/pages/mail/user-base/user-base'
|
||||
});
|
||||
break;
|
||||
default:
|
||||
this.$emit('click')
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
28
l-im-app-imooc-master/l-im-app-imooc/components/ui/badge.vue
Normal file
@@ -0,0 +1,28 @@
|
||||
<template>
|
||||
<text class="badge bg-danger text-white rounded-circle font-sm" :class="badgeClass" :style="badgeStyle">{{value}}</text>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
badgeClass: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
badgeStyle:{
|
||||
type:String,
|
||||
default:""
|
||||
},
|
||||
value:{
|
||||
type:[Number,String],
|
||||
default:""
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.badge{
|
||||
padding-left: 14rpx;padding-right: 14rpx;padding-bottom: 3rpx;padding-top: 3rpx;
|
||||
}
|
||||
</style>
|
||||
159
l-im-app-imooc-master/l-im-app-imooc/components/ui/chat-item.vue
Normal file
@@ -0,0 +1,159 @@
|
||||
<template>
|
||||
<div class="" @longpress="long">
|
||||
<view v-if="showTime" class="flex align-center justify-center pb-4 pt-2">
|
||||
<text class="font-sm text-light-muted">{{showTime}}</text>
|
||||
</view>
|
||||
|
||||
<view v-if="item.isRemove" ref="isRemove" class="flex align-center justify-center pb-4 pt-1 chat-animate">
|
||||
<text class="font-sm text-light-muted">你撤回了一条消息</text>
|
||||
</view>
|
||||
|
||||
<!-- 气泡 -->
|
||||
<view v-else class="flex align-start position-relative mb-3"
|
||||
:class="!isself ? 'justify-start' : 'justify-end'">
|
||||
<!-- 好友 -->
|
||||
<template v-if="!isself">
|
||||
<avater size="70" :src="item.avatar" clickType="navigate"></avater>
|
||||
<text v-if="hasLabelClass" class="iconfont text-white font-md position-absolute chat-left-icon"
|
||||
style=""></text>
|
||||
</template>
|
||||
|
||||
<div style="max-width: 500rpx;" class="p-2 rounded " :class="labelClass" :style="labelStyle">
|
||||
<!-- 文字 -->
|
||||
<text v-if="item.type === 'text'" class="font-md ">{{item.data}}</text>
|
||||
</div>
|
||||
|
||||
<!-- 本人 -->
|
||||
<template v-if="isself">
|
||||
<text v-if="hasLabelClass" class="iconfont text-chat-item font-md position-absolute chat-right-icon"
|
||||
style=""></text>
|
||||
<avater size="70" :src="item.avatar" clickType="navigate"></avater>
|
||||
</template>
|
||||
</view>
|
||||
</div>
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import avater from "@/components/ui/avater.vue"
|
||||
import fImage from "@/components/ui/fImage.vue"
|
||||
import $T from "@/common/lib/time.js"
|
||||
import {
|
||||
mapState,
|
||||
mapActions
|
||||
} from 'vuex'
|
||||
|
||||
// #ifdef APP-PLUS-NVUE
|
||||
const animation = weex.requireModule('animation')
|
||||
// #endif
|
||||
|
||||
export default {
|
||||
components: {
|
||||
avater,
|
||||
fImage
|
||||
},
|
||||
props: {
|
||||
item: Object,
|
||||
index: Number,
|
||||
pretime: [Number, String]
|
||||
},
|
||||
computed: {
|
||||
// 是否为本人
|
||||
isself() {
|
||||
var lim = this.imsdk
|
||||
var sdk = lim.im;
|
||||
let uid = sdk.getUserId();
|
||||
// console.log(uid)
|
||||
return this.item.userId === uid;
|
||||
},
|
||||
// 显示的时间
|
||||
showTime() {
|
||||
return $T.getChatTime(this.item.createTime, this.pretime)
|
||||
},
|
||||
// 是否需要气泡样式
|
||||
hasLabelClass() {
|
||||
return this.item.type === 'text'
|
||||
},
|
||||
// 气泡的样式
|
||||
labelClass() {
|
||||
let label = this.hasLabelClass ? 'bg-chat-item mr-3' : 'mr-3'
|
||||
return this.isself ? label : 'bg-white ml-3'
|
||||
},
|
||||
labelStyle(){
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
long(e) {
|
||||
let x = 0
|
||||
let y = 0
|
||||
// #ifdef APP-PLUS-NVUE
|
||||
if (Array.isArray(e.changedTouches) && e.changedTouches.length > 0) {
|
||||
x = e.changedTouches[0].screenX
|
||||
y = e.changedTouches[0].screenY
|
||||
}
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
x = e.changedTouches[0].pageX
|
||||
y = e.changedTouches[0].pageY
|
||||
// #endif
|
||||
// #ifdef MP
|
||||
x = e.detail.x
|
||||
y = e.detail.y
|
||||
// #endif
|
||||
this.$emit('long', {
|
||||
x,
|
||||
y,
|
||||
index: this.index
|
||||
})
|
||||
},
|
||||
preview(url) {
|
||||
this.$emit("preview", url)
|
||||
},
|
||||
loadImage(e) {
|
||||
let w = e.detail.width
|
||||
let h = e.detail.height
|
||||
// 按照宽度来
|
||||
let maxW = uni.upx2px(500)
|
||||
|
||||
//按照高度来
|
||||
let maxH = uni.upx2px(350)
|
||||
if (h <= maxH) {
|
||||
this.w = w <= maxW ? w : maxW;
|
||||
this.h = h;
|
||||
return;
|
||||
}
|
||||
this.h = maxH
|
||||
let w2 = maxH * (w / h)
|
||||
this.w = w2 <= maxW ? w2 : maxW
|
||||
}
|
||||
},
|
||||
destroyed() {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
w: 100,
|
||||
h: 100
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// 注册全局事件
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.chat-left-icon {
|
||||
left: 80rpx;
|
||||
}
|
||||
|
||||
.chat-right-icon {
|
||||
right: 80rpx;
|
||||
}
|
||||
|
||||
.chat-animate {
|
||||
/* #ifndef APP-PLUS-NVUE */
|
||||
opacity: 0;
|
||||
/* #endif */
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,62 @@
|
||||
<template>
|
||||
<popup ref="confirm" center maskColor transformOrigin="center center">
|
||||
<view class="bg-white rounded" style="width: 600rpx;">
|
||||
<view class="p-4 flex flex-column">
|
||||
<text class="font-md font-weight-bold mb-3">{{title}}</text>
|
||||
<slot></slot>
|
||||
</view>
|
||||
<!-- 底部 -->
|
||||
<view style="height: 100rpx;" class="border-top flex align-stretch">
|
||||
<view class="flex-1 border-right flex align-center justify-center" @click="cancel">
|
||||
<text class="font-md text-muted">取消</text>
|
||||
</view>
|
||||
<view class="flex-1 flex align-center justify-center"
|
||||
@click="confirm">
|
||||
<text class="font-md main-text-color">确定</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</popup>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import popup from '@/components/ui/popup.vue';
|
||||
export default {
|
||||
components: {
|
||||
popup
|
||||
},
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: "提示"
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
callback: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 显示
|
||||
show(callback = false){
|
||||
this.callback = callback
|
||||
this.$refs.confirm.show()
|
||||
},
|
||||
// 取消
|
||||
cancel() {
|
||||
this.$refs.confirm.hide()
|
||||
},
|
||||
// 确定
|
||||
confirm(){
|
||||
if(typeof this.callback === 'function'){
|
||||
this.callback(()=>{
|
||||
this.cancel()
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
@@ -0,0 +1,26 @@
|
||||
<template>
|
||||
<view :style="getStyle"></view>
|
||||
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
color:{
|
||||
type:String,
|
||||
default:"#EFEDE9"
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
getStyle(){
|
||||
return `height: 18rpx;background-color: ${this.color}rpx`
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
@@ -0,0 +1,69 @@
|
||||
<template>
|
||||
<image :src="src" lazy-load :style="imageStyle" :class="imageClass" @tap="$emit('click')"
|
||||
@longpress="$emit('longpress')" @load="loadImage" class="bg-hover-light"></image>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
src: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
imageClass: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
maxWidth: {
|
||||
type: Number,
|
||||
default: 500 // rpx
|
||||
},
|
||||
maxHeight: {
|
||||
type: Number,
|
||||
default: 350 // rpx
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
h: 100,
|
||||
w: 100
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
imageStyle() {
|
||||
return `width:${this.w}px;height:${this.h}px;`
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 加载图片
|
||||
loadImage(e) {
|
||||
let w = e.detail.width
|
||||
let h = e.detail.height
|
||||
// // 最大宽度 px
|
||||
let maxW = uni.upx2px(this.maxWidth)
|
||||
// 最大高度
|
||||
let maxH = uni.upx2px(this.maxHeight)
|
||||
if (h <= maxH) {
|
||||
// 用原来的宽高
|
||||
this.w = w <= maxW ? w : maxW
|
||||
this.h = h
|
||||
this.$emit('load', {
|
||||
w: this.w,
|
||||
h: this.h
|
||||
})
|
||||
return;
|
||||
}
|
||||
this.h = maxH
|
||||
let w2 = maxH * (w / h)
|
||||
this.w = w2 <= maxW ? w2 : maxW
|
||||
this.$emit('load', {
|
||||
w: this.w,
|
||||
h: this.h
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
@@ -0,0 +1,21 @@
|
||||
<template>
|
||||
<view class="flex align-center justify-center"
|
||||
hover-class="bg-hover-light" @click="$emit('click')"
|
||||
style="height: 90rpx;width: 90rpx;">
|
||||
<text class="iconfont font-md">{{icon}}</text>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
icon: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
@@ -0,0 +1,71 @@
|
||||
<template>
|
||||
<view class="bg-white flex align-stretch" hover-class="bg-light"
|
||||
@click="$emit('click')">
|
||||
<view class="flex align-center justify-center py-2 pl-3"
|
||||
v-if="showLeftIcon">
|
||||
<slot name="icon"></slot>
|
||||
<image :src="cover" v-if="cover"
|
||||
mode="widthFix" :style="coverStyle"></image>
|
||||
</view>
|
||||
<view class="flex-1 flex align-center justify-between pr-3 py-3 pl-3" :class="border ? 'border-bottom' : ''">
|
||||
<slot>
|
||||
<text class="font-md text-dark">{{title}}</text>
|
||||
</slot>
|
||||
<view class="flex align-center" v-if="showRight">
|
||||
<slot name="right"></slot>
|
||||
<!-- 右箭头 -->
|
||||
<text v-if="showRightIcon" class="iconfont text-light-muted font-md"></text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
// 是否开启下边线
|
||||
border:{
|
||||
type:Boolean,
|
||||
default:true
|
||||
},
|
||||
// 封面
|
||||
cover: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
// 封面大小
|
||||
coverSize:{
|
||||
type: [String,Number],
|
||||
default:75
|
||||
},
|
||||
// 标题
|
||||
title:{
|
||||
type:String,
|
||||
default:""
|
||||
},
|
||||
// 显示右边
|
||||
showRight:{
|
||||
type:Boolean,
|
||||
default:false
|
||||
},
|
||||
// 显示左边图标
|
||||
showLeftIcon:{
|
||||
type:Boolean,
|
||||
default:true
|
||||
},
|
||||
// 是否显示箭头
|
||||
showRightIcon:{
|
||||
type:Boolean,
|
||||
default:true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
coverStyle() {
|
||||
return `width: ${this.coverSize}rpx;height: ${this.coverSize}rpx;`
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
@@ -0,0 +1,34 @@
|
||||
<template>
|
||||
<view class="rounded mr-2 px-2 py-1"
|
||||
@click="clickEvent"
|
||||
:class="disabled ? 'bg-light border' : 'main-bg-color'">
|
||||
<text class="font"
|
||||
:class="disabled ? 'text-light-muted':'text-white'">{{name}}</text>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
name: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
disabled:{
|
||||
type:Boolean,
|
||||
default:false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
clickEvent() {
|
||||
console.log("clickEvent")
|
||||
if(!this.disabled){
|
||||
this.$emit('click')
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
@@ -0,0 +1,76 @@
|
||||
<template>
|
||||
|
||||
<view :class="item.istop ? 'bg-light' : 'bg-white'" hover-class="bg-hover-light">
|
||||
<div class="flex align-stretch" @click="onClick" @longpress="long">
|
||||
|
||||
<view class="flex align-center justify-center position-relative" style="width: 145rpx;">
|
||||
<avater :src="item.avatar" size="92"></avater>
|
||||
<badge badgeClass="position-absolute" badgeStyle="top:15rpx;right:15rpx" v-if="item.noreadnum"
|
||||
:value="item.noreadnum"></badge>
|
||||
</view>
|
||||
|
||||
<view class="flex flex-column border-bottom flex-1 py-3 pr-3 border-light-secondary">
|
||||
<view class="flex align-center justify-between mb-1">
|
||||
<text class="font-md">{{item.nickname}}</text>
|
||||
<text class="font-sm text-light-muted">{{item.updateTime|formatTime}}</text>
|
||||
</view>
|
||||
<text class="font-sm text-ellipsis text-light-muted">{{item.data}}</text>
|
||||
</view>
|
||||
|
||||
</div>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import base from "@/common/mixin/base.js"
|
||||
import avater from "@/components/ui/avater.vue"
|
||||
import badge from "@/components/ui/badge.vue"
|
||||
|
||||
export default {
|
||||
mixins:[base],
|
||||
components: {
|
||||
avater,
|
||||
badge
|
||||
},
|
||||
props: {
|
||||
item: Object,
|
||||
index:Number
|
||||
},
|
||||
methods:{
|
||||
onClick(){
|
||||
uni.navigateTo({
|
||||
url: '/pages/chat/chat/chat?params='+encodeURIComponent(JSON.stringify({
|
||||
id:this.item.id
|
||||
}))
|
||||
});
|
||||
},
|
||||
long(e){
|
||||
let x = 0
|
||||
let y = 0
|
||||
// #ifdef APP-PLUS-NVUE
|
||||
if (Array.isArray(e.changedTouches) && e.changedTouches.length > 0) {
|
||||
x = e.changedTouches[0].screenX
|
||||
y = e.changedTouches[0].screenY
|
||||
}
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
x = e.changedTouches[0].pageX
|
||||
y = e.changedTouches[0].pageY
|
||||
// #endif
|
||||
// #ifdef MP
|
||||
x = e.detail.x
|
||||
y = e.detail.y
|
||||
// #endif
|
||||
console.log(this.index)
|
||||
this.$emit('long',{
|
||||
x,
|
||||
y,
|
||||
index:this.index
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
182
l-im-app-imooc-master/l-im-app-imooc/components/ui/nav-bar.vue
Normal file
@@ -0,0 +1,182 @@
|
||||
<template>
|
||||
<view>
|
||||
<view :class="getClass">
|
||||
<!-- 状态栏 -->
|
||||
<view :style="'height:'+statusBarHeight+'px'"></view>
|
||||
<!-- 导航 -->
|
||||
<view class="w-100 flex align-center justify-between" style="height: 90rpx;">
|
||||
<!-- 左边 -->
|
||||
<view class="flex align-center">
|
||||
<!-- 返回按钮 -->
|
||||
<!-- #ifndef MP -->
|
||||
<icon-button v-if="showBack" @click="back"
|
||||
:icon="'\ue60d'"></icon-button>
|
||||
<!-- #endif -->
|
||||
<!-- 标题 -->
|
||||
<slot>
|
||||
<text v-if="title" class="font-md ml-3">{{getTitle}}</text>
|
||||
</slot>
|
||||
</view>
|
||||
<!-- 右边 -->
|
||||
<view class="flex align-center" v-if="showRight">
|
||||
<slot name="right">
|
||||
<icon-button @click="search" :icon="'\ue6e3'"></icon-button>
|
||||
<icon-button @click="openExtend" :icon="'\ue682'"></icon-button>
|
||||
</slot>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 占位 -->
|
||||
<view v-if="fixed" :style="fixedStyle"></view>
|
||||
|
||||
<!-- 扩展菜单 -->
|
||||
<popup v-if="showRight" ref="extend" :bodyWidth="320" :bodyHeight="525"
|
||||
bodyBgColor="bg-dark" transformOrigin="right top">
|
||||
<view class="flex flex-column"
|
||||
style="width: 320rpx;height: 525rpx;">
|
||||
<view class="flex-1 flex align-center"
|
||||
hover-class="bg-hover-dark"
|
||||
v-for="(item,index) in menus"
|
||||
:key="index"
|
||||
@click="clickEvent(item)">
|
||||
<text class="iconfont pl-3 pr-2 font-md text-white">{{item.icon}}</text>
|
||||
<text class="font-md text-white">{{item.name}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</popup>
|
||||
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import iconButton from "./icon-button.vue"
|
||||
import popup from "./popup.vue"
|
||||
import $H from '@/common/lib/request.js';
|
||||
export default {
|
||||
props: {
|
||||
showBack:{
|
||||
type:Boolean,
|
||||
default:false
|
||||
},
|
||||
backEvent:{
|
||||
type:Boolean,
|
||||
default:true
|
||||
},
|
||||
title: {
|
||||
type: [String,Boolean],
|
||||
default:false
|
||||
},
|
||||
fixed:{
|
||||
type:Boolean,
|
||||
default:true
|
||||
},
|
||||
noreadnum:{
|
||||
type:[Number,String],
|
||||
default:0
|
||||
},
|
||||
bgColor:{
|
||||
type:String,
|
||||
default:"bg-light"
|
||||
},
|
||||
showRight:{
|
||||
type:Boolean,
|
||||
default:true
|
||||
}
|
||||
},
|
||||
components:{
|
||||
iconButton,
|
||||
popup
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
statusBarHeight:0,
|
||||
navBarHeight:0,
|
||||
menus:[
|
||||
{
|
||||
name:"发起群聊",
|
||||
event:"navigateTo",
|
||||
path:'',
|
||||
icon:"\ue633"
|
||||
},
|
||||
{
|
||||
name:"添加好友",
|
||||
event:"navigateTo",
|
||||
path:'',
|
||||
icon:"\ue65d"
|
||||
},
|
||||
{
|
||||
name:"扫一扫",
|
||||
event:"scan",
|
||||
icon:"\ue614"
|
||||
},
|
||||
{
|
||||
name:"收付款",
|
||||
event:"",
|
||||
icon:"\ue66c"
|
||||
},
|
||||
{
|
||||
name:"帮助与反馈",
|
||||
event:"",
|
||||
icon:"\ue66c"
|
||||
}
|
||||
],
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// #ifdef APP-PLUS-NVUE
|
||||
this.statusBarHeight = plus.navigator.getStatusbarHeight()
|
||||
// #endif
|
||||
this.navBarHeight = this.statusBarHeight + uni.upx2px(90)
|
||||
},
|
||||
computed: {
|
||||
fixedStyle() {
|
||||
return `height:${this.navBarHeight}px`
|
||||
},
|
||||
getTitle(){
|
||||
let noreadnum = this.noreadnum > 0 ? '('+this.noreadnum+')' : ''
|
||||
return this.title + noreadnum
|
||||
},
|
||||
getClass(){
|
||||
let fixed = this.fixed?'fixed-top':''
|
||||
return `${fixed} ${this.bgColor}`
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
openExtend() {
|
||||
this.$refs.extend.show(uni.upx2px(415),uni.upx2px(150))
|
||||
},
|
||||
// 返回
|
||||
back(){
|
||||
if(this.backEvent){
|
||||
return uni.navigateBack({
|
||||
delta: 1
|
||||
});
|
||||
}
|
||||
this.$emit('back')
|
||||
},
|
||||
search(){
|
||||
console.log("search")
|
||||
},
|
||||
clickEvent(e){
|
||||
this.$refs.extend.hide()
|
||||
switch (e.event){
|
||||
case 'navigateTo':
|
||||
uni.navigateTo({
|
||||
url: e.path,
|
||||
});
|
||||
break;
|
||||
default:
|
||||
uni.showToast({
|
||||
title: '自己发挥',
|
||||
icon: 'none'
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
157
l-im-app-imooc-master/l-im-app-imooc/components/ui/popup.vue
Normal file
@@ -0,0 +1,157 @@
|
||||
<template>
|
||||
<div style="z-index:9999;overflow:hidden;" v-if="status">
|
||||
<!-- 蒙版 -->
|
||||
<view v-if="mask" class="position-fixed top-0 left-0 right-0 bottom-0 z-index" :style="getMaskColor" @click="hide"></view>
|
||||
<!-- 弹出框内容 -->
|
||||
<div ref="popup" class="position-fixed animated z-index" :class="getBodyClass" :style="getBodyStyle">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// #ifdef APP-PLUS-NVUE
|
||||
const animation = weex.requireModule('animation')
|
||||
// #endif
|
||||
export default {
|
||||
props: {
|
||||
// 是否开启蒙版颜色
|
||||
maskColor: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 是否开启蒙版
|
||||
mask:{
|
||||
type:Boolean,
|
||||
default:true
|
||||
},
|
||||
// 是否居中
|
||||
center:{
|
||||
type:Boolean,
|
||||
default:false
|
||||
},
|
||||
// 是否处于底部
|
||||
bottom:{
|
||||
type:Boolean,
|
||||
default:false
|
||||
},
|
||||
// 弹出层内容宽度
|
||||
bodyWidth:{
|
||||
type:Number,
|
||||
default:0
|
||||
},
|
||||
// 弹出层内容高度
|
||||
bodyHeight:{
|
||||
type:Number,
|
||||
default:0
|
||||
},
|
||||
bodyBgColor:{
|
||||
type:String,
|
||||
default:"bg-white"
|
||||
},
|
||||
transformOrigin:{
|
||||
type:String,
|
||||
default:"left top"
|
||||
},
|
||||
// tabbar高度
|
||||
tabbarHeight:{
|
||||
type:Number,
|
||||
default:0
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
status: false,
|
||||
x:-1,
|
||||
y:1,
|
||||
maxX:0,
|
||||
maxY:0
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
try {
|
||||
const res = uni.getSystemInfoSync();
|
||||
this.maxX = res.windowWidth - uni.upx2px(this.bodyWidth)
|
||||
this.maxY = res.windowHeight - uni.upx2px(this.bodyHeight) - uni.upx2px(this.tabbarHeight)
|
||||
} catch (e) {
|
||||
// error
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
getMaskColor() {
|
||||
let i = this.maskColor ? 0.5 : 0
|
||||
return `background-color: rgba(0,0,0,${i});`
|
||||
},
|
||||
getBodyClass(){
|
||||
if(this.center){
|
||||
return 'left-0 right-0 bottom-0 top-0 flex align-center justify-center'
|
||||
}
|
||||
let bottom = this.bottom ? 'left-0 right-0 bottom-0' : 'rounded border'
|
||||
return `${this.bodyBgColor} ${bottom}`
|
||||
},
|
||||
getBodyStyle(){
|
||||
let left = this.x > -1 ? `left:${this.x}px;` : ''
|
||||
let top = this.y > -1 ? `top:${this.y}px;` : ''
|
||||
return left + top
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
show(x = -1 ,y = -1){
|
||||
if (this.status) {
|
||||
return;
|
||||
}
|
||||
this.x = (x > this.maxX) ? this.maxX : x
|
||||
this.y = (y > this.maxY) ? this.maxY : y
|
||||
this.status = true
|
||||
// #ifdef APP-PLUS-NVUE
|
||||
this.$nextTick(()=>{
|
||||
animation.transition(this.$refs.popup, {
|
||||
styles: {
|
||||
transform: 'scale(1,1)',
|
||||
transformOrigin:this.transformOrigin,
|
||||
opacity:1
|
||||
},
|
||||
duration: 100, //ms
|
||||
timingFunction: 'ease',
|
||||
}, function () {
|
||||
// console.log('动画执行结束');
|
||||
})
|
||||
})
|
||||
// #endif
|
||||
|
||||
},
|
||||
hide(){
|
||||
this.$emit('hide')
|
||||
// #ifdef APP-PLUS-NVUE
|
||||
animation.transition(this.$refs.popup, {
|
||||
styles: {
|
||||
transform: 'scale(0,0)',
|
||||
transformOrigin:this.transformOrigin,
|
||||
opacity:0
|
||||
},
|
||||
duration: 100, //ms
|
||||
timingFunction: 'ease',
|
||||
}, ()=> {
|
||||
this.status = false
|
||||
// console.log('动画执行结束');
|
||||
})
|
||||
// #endif
|
||||
this.status = false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.animated{
|
||||
/* #ifdef APP-PLUS-NVUE */
|
||||
/* transform: scale(0,0);
|
||||
opacity: 0; */
|
||||
/* #endif */
|
||||
}
|
||||
.z-index{
|
||||
/* #ifndef APP-NVUE */
|
||||
z-index: 9999;
|
||||
/* #endif */
|
||||
}
|
||||
</style>
|
||||
20
l-im-app-imooc-master/l-im-app-imooc/index.html
Normal file
@@ -0,0 +1,20 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<script>
|
||||
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
|
||||
CSS.supports('top: constant(a)'))
|
||||
document.write(
|
||||
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
|
||||
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
|
||||
</script>
|
||||
<title></title>
|
||||
<!--preload-links-->
|
||||
<!--app-context-->
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"><!--app-html--></div>
|
||||
<script type="module" src="/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
21
l-im-app-imooc-master/l-im-app-imooc/main.js
Normal file
@@ -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()
|
||||
100
l-im-app-imooc-master/l-im-app-imooc/manifest.json
Normal file
@@ -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" : [
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_CONTACTS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
|
||||
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WRITE_CONTACTS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
|
||||
"<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",
|
||||
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CALL_PHONE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>",
|
||||
"<uses-feature android:name=\"android.hardware.camera\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
|
||||
]
|
||||
},
|
||||
/* 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": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3
l-im-app-imooc-master/l-im-app-imooc/package-lock.json
generated
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"lockfileVersion": 1
|
||||
}
|
||||
85
l-im-app-imooc-master/l-im-app-imooc/pages.json
Normal file
@@ -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": {}
|
||||
}
|
||||
433
l-im-app-imooc-master/l-im-app-imooc/pages/chat/chat/chat.vue
Normal file
@@ -0,0 +1,433 @@
|
||||
<template>
|
||||
<view>
|
||||
|
||||
<!-- 导航栏 -->
|
||||
<nav-bar :title="detail.name" :noreadnum="999" showBack>
|
||||
<icon-button slot="right" :icon="'\ue6fd'" ></icon-button>
|
||||
</nav-bar>
|
||||
|
||||
<!-- 聊天内容区域 -->
|
||||
<scroll-view scroll-y class="bg-light position-fixed left-0 right-0 px-3"
|
||||
style="bottom: 105rpx;box-sizing: border-box;" :style="chatBodyBottom" :show-scrollbar="false"
|
||||
:scroll-into-view="scrollIntoView" :scroll-with-animation="true" @click="clickPage">
|
||||
|
||||
<!-- 聊天信息列表组件 -->
|
||||
<view v-for="(item,index) in list" :key="index" :id="'chatItem_'+index">
|
||||
<chat-item :item="item" :index="index" ref="chatItem"
|
||||
:pretime=" index > 0 ? list[index-1].createTime : 0" @long="long"
|
||||
:shownickname="currentChatItem.shownickname"></chat-item>
|
||||
</view>
|
||||
|
||||
</scroll-view>
|
||||
|
||||
<!-- #ifdef APP-PLUS-NVUE -->
|
||||
<div v-if="mode === 'action' || mode === 'emoticon'" class="position-fixed top-0 right-0 left-0"
|
||||
:style="'bottom:'+maskBottom+'px;'" @click="clickPage"></div>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- 底部输入框 -->
|
||||
<view class="position-fixed left-0 right-0 border-top flex align-center"
|
||||
style="background-color: #F7F7F6;height: 105rpx;" :style="'bottom:'+KeyboardHeight+'px;'">
|
||||
<icon-button :icon="'\ue606'" @click="changeVoiceOrText"></icon-button>
|
||||
<view class="flex-1">
|
||||
<textarea fixed class="bg-white rounded p-2 font-md" style="height: 50rpx;max-width: 450rpx;"
|
||||
:adjust-position="false" v-model="text" @focus="mode = 'text'" />
|
||||
</view>
|
||||
<!-- 表情 -->
|
||||
<!-- <icon-button :icon="'\ue605'"></icon-button> -->
|
||||
<template v-if="text.length === 0">
|
||||
<!-- 扩展菜单 -->
|
||||
<icon-button :icon="'\ue603'" @click="openActionOrEmoticon('action')"></icon-button>
|
||||
</template>
|
||||
<view v-else class="flex-shrink">
|
||||
<!-- 发送按钮 -->
|
||||
<main-button name="发送" @click="send('text')"></main-button>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 扩展菜单 -->
|
||||
<popup ref="action" bottom transformOrigin="center bottom" @hide="KeyboardHeight = 0" :mask="false">
|
||||
<view style="height: 580rpx;" class="border-top border-light-secondary bg-light">
|
||||
<swiper :indicator-dots="actionLists.length > 1" style="height: 510rpx;">
|
||||
<swiper-item class="row pl-5" v-for="(item,index) in actionLists" :key="index">
|
||||
<view class="col-3 flex flex-column align-center justify-center" style="height: 255rpx;"
|
||||
v-for="(item2,index2) in item" :key="index2" @click="actionEvent(item2)">
|
||||
<image :src="item2.icon" mode="widthFix" style="width: 100rpx;height: 100rpx;"></image>
|
||||
<text class="font-sm text-muted mt-2">{{item2.name}}</text>
|
||||
</view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</view>
|
||||
</popup>
|
||||
|
||||
|
||||
<!-- 弹出层 -->
|
||||
<popup ref="extend" :bodyWidth="240" :bodyHeight="450" :tabbarHeight="105">
|
||||
<view class="flex flex-column" style="width: 240rpx;" :style="getMenusStyle">
|
||||
<view class="flex-1 flex align-center" hover-class="bg-light" v-for="(item,index) in menusList"
|
||||
:key="index" @click="clickEvent(item.event)">
|
||||
<text class="font-md pl-3">{{item.name}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</popup>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// #ifdef APP-PLUS-NVUE
|
||||
const dom = weex.requireModule('dom')
|
||||
// #endif
|
||||
|
||||
const sdk = uni.lim.im;
|
||||
|
||||
import navBar from "@/components/ui/nav-bar.vue"
|
||||
import iconButton from "@/components/ui/icon-button.vue"
|
||||
import chatItem from '@/components/ui/chat-item.vue';
|
||||
import popup from "@/components/ui/popup.vue"
|
||||
import mainButton from '@/components/ui/main-button.vue';
|
||||
|
||||
|
||||
import {
|
||||
mapState,
|
||||
mapMutations
|
||||
} from 'vuex'
|
||||
|
||||
import auth from '@/common/mixin/auth.js';
|
||||
import $H from '@/common/lib/request.js';
|
||||
import $C from '@/common/lib/config.js';
|
||||
|
||||
export default {
|
||||
mixins: [auth],
|
||||
components: {
|
||||
navBar,
|
||||
iconButton,
|
||||
chatItem,
|
||||
popup,
|
||||
mainButton
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
scrollIntoView: "",
|
||||
toId: "",
|
||||
// 模式 text输入文字,emoticon表情,action操作,audio音频
|
||||
mode: "text",
|
||||
// 扩展菜单列表
|
||||
actionList: [
|
||||
[{
|
||||
name: "相册",
|
||||
icon: "/static/images/extends/pic.png",
|
||||
event: "uploadImage"
|
||||
}, {
|
||||
name: "拍摄",
|
||||
icon: "/static/images/extends/video.png",
|
||||
event: "uploadVideo"
|
||||
}, {
|
||||
name: "收藏",
|
||||
icon: "/static/images/extends/shoucan.png",
|
||||
event: "openFava"
|
||||
}, {
|
||||
name: "名片",
|
||||
icon: "/static/images/extends/man.png",
|
||||
event: "sendCard"
|
||||
}, {
|
||||
name: "语音通话",
|
||||
icon: "/static/images/extends/phone.png",
|
||||
event: ""
|
||||
}, {
|
||||
name: "位置",
|
||||
icon: "/static/images/extends/path.png",
|
||||
event: ""
|
||||
}]
|
||||
],
|
||||
emoticonList: [],
|
||||
// 键盘高度
|
||||
KeyboardHeight: 0,
|
||||
menusList: [],
|
||||
navBarHeight: 0,
|
||||
list: [{
|
||||
userId: 'lld',
|
||||
avatar: "/static/images/userpic.png",
|
||||
data: "你好啊你好啊你好啊你好啊你好啊你好啊你好啊",
|
||||
nickname: "lld",
|
||||
type: "text",
|
||||
createTime: 1657465771,
|
||||
isRemove: false
|
||||
}, {
|
||||
userId: 'lld2',
|
||||
avatar: "/static/images/userpic.png",
|
||||
data: "1234567890",
|
||||
nickname: "lld2",
|
||||
type: "text",
|
||||
createTime: 1658329771,
|
||||
isRemove: false
|
||||
}, {
|
||||
userId: 'lld',
|
||||
avatar: "/static/images/userpic.png",
|
||||
data: "你好啊你好啊你好啊你好啊你好啊你好啊你好啊",
|
||||
nickname: "lld",
|
||||
type: "text",
|
||||
createTime: 1657465771,
|
||||
isRemove: false
|
||||
}, {
|
||||
userId: 'lld2',
|
||||
avatar: "/static/images/userpic.png",
|
||||
data: "1234567890",
|
||||
nickname: "lld2",
|
||||
type: "text",
|
||||
createTime: 1658329771,
|
||||
isRemove: false
|
||||
}],
|
||||
// 当前操作的气泡索引
|
||||
propIndex: -1,
|
||||
// 输入文字
|
||||
text: "",
|
||||
|
||||
detail: {
|
||||
id: 0,
|
||||
name: "",
|
||||
avatar: "",
|
||||
chat_type: "user"
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
var statusBarHeight = 0
|
||||
// #ifdef APP-PLUS-NVUE
|
||||
statusBarHeight = plus.navigator.getStatusbarHeight()
|
||||
// #endif
|
||||
this.navBarHeight = statusBarHeight + uni.upx2px(90)
|
||||
|
||||
// 监听键盘高度变化
|
||||
uni.onKeyboardHeightChange(res => {
|
||||
if (this.mode !== 'action' && this.mode !== 'emoticon') {
|
||||
this.KeyboardHeight = res.height
|
||||
}
|
||||
if (this.KeyboardHeight > 0) {
|
||||
this.pageToBottom()
|
||||
}
|
||||
})
|
||||
|
||||
this.pageToBottom()
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
}),
|
||||
// 当前会话配置信息
|
||||
currentChatItem() {
|
||||
return {}
|
||||
},
|
||||
// 获取蒙版的位置
|
||||
maskBottom() {
|
||||
return this.KeyboardHeight + uni.upx2px(105)
|
||||
},
|
||||
// 动态获取菜单高度
|
||||
getMenusHeight() {
|
||||
let H = 100
|
||||
return this.menusList.length * H
|
||||
},
|
||||
// 获取菜单的样式
|
||||
getMenusStyle() {
|
||||
return `height: ${this.getMenusHeight}rpx;`
|
||||
},
|
||||
// 判断是否操作本人信息
|
||||
isdoSelf() {
|
||||
// 获取本人id(假设拿到了)
|
||||
let id = 1
|
||||
let user_id = this.propIndex > -1 ? this.list[this.propIndex].user_id : 0
|
||||
return user_id === id
|
||||
},
|
||||
// 聊天区域bottom
|
||||
chatBodyBottom() {
|
||||
return `bottom:${uni.upx2px(105) + this.KeyboardHeight}px;top:${this.navBarHeight}px;`
|
||||
},
|
||||
// 获取操作或者表情列表
|
||||
actionLists() {
|
||||
return (this.mode === 'emoticon' || this.mode === 'action') ? this[this.mode + 'List'] : []
|
||||
},
|
||||
// 所有信息的图片地址
|
||||
imageList() {
|
||||
let arr = []
|
||||
this.list.forEach((item) => {
|
||||
if (item.type === 'emoticon' || item.type === 'image') {
|
||||
arr.push(item.data)
|
||||
}
|
||||
})
|
||||
return arr
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
mode(newValue, oldValue) {
|
||||
if (newValue !== 'action' && newValue !== 'emoticon') {
|
||||
this.$refs.action.hide()
|
||||
}
|
||||
if (newValue !== 'text') {
|
||||
uni.hideKeyboard()
|
||||
}
|
||||
}
|
||||
},
|
||||
onLoad(e) {
|
||||
var toIdObj = JSON.parse(decodeURIComponent(e.params))
|
||||
this.toId = toIdObj.id;
|
||||
// // 监听接收聊天信息
|
||||
uni.$on('P2PMessage', this.onMessage)
|
||||
},
|
||||
destroyed() {
|
||||
// // 销毁监听接收聊天消息
|
||||
uni.$off('P2PMessage',this.onMessage)
|
||||
},
|
||||
methods: {
|
||||
onMessage(message) {
|
||||
if(message.fromId != this.toId){
|
||||
return;
|
||||
}
|
||||
console.log('[聊天页] 监听接收聊天信息', message);
|
||||
var messageBody = JSON.parse(message.messageBody);
|
||||
if(messageBody.type == 1){
|
||||
let msg = {
|
||||
userId:message.fromId,
|
||||
avatar: "/static/images/userpic.png",
|
||||
data: messageBody.content == '' ? '空消息' : messageBody.content,
|
||||
nickname:message.fromId,
|
||||
type: "text",
|
||||
createTime: message.messageTime / 1000,
|
||||
isRemove: false
|
||||
}
|
||||
this.list.push(msg)
|
||||
}
|
||||
this.pageToBottom()
|
||||
},
|
||||
__init() {},
|
||||
// 打开扩展菜单或者表情包
|
||||
openActionOrEmoticon(mode = 'action') {
|
||||
this.mode = mode
|
||||
this.$refs.action.show()
|
||||
|
||||
uni.hideKeyboard()
|
||||
this.KeyboardHeight = uni.upx2px(580)
|
||||
},
|
||||
// 发送
|
||||
send(type, data = '', options = {}) {
|
||||
// 组织数据格式
|
||||
if (type == 'text') {
|
||||
sdk.sendP2PMessage(sdk.createP2PTextMessage(this.toId, this.text))
|
||||
let uid = sdk.getUserId();
|
||||
let msg = {
|
||||
userId:uid,
|
||||
avatar: "/static/images/userpic.png",
|
||||
data: this.text,
|
||||
nickname:uid,
|
||||
type: "text",
|
||||
createTime: Date.parse(new Date()) / 1000,
|
||||
isRemove: false
|
||||
}
|
||||
this.list.push(msg)
|
||||
}
|
||||
// 发送文字成功,清空输入框
|
||||
if (type === 'text') {
|
||||
this.text = ''
|
||||
}
|
||||
// 置于底部
|
||||
this.pageToBottom()
|
||||
},
|
||||
// 回到底部
|
||||
pageToBottom() {
|
||||
// #ifdef APP-PLUS-NVUE
|
||||
let chatItem = this.$refs.chatItem
|
||||
let lastIndex = chatItem.length > 0 ? chatItem.length - 1 : 0
|
||||
if (chatItem[lastIndex]) {
|
||||
dom.scrollToElement(chatItem[lastIndex], {})
|
||||
}
|
||||
// #endif
|
||||
// #ifndef APP-NVUE
|
||||
setTimeout(() => {
|
||||
let lastIndex = this.list.length - 1
|
||||
this.scrollIntoView = 'chatItem_' + lastIndex
|
||||
}, 300)
|
||||
// #endif
|
||||
},
|
||||
// 长按消息气泡
|
||||
long({
|
||||
x,
|
||||
y,
|
||||
index
|
||||
}) {
|
||||
// 初始化 索引
|
||||
this.propIndex = index
|
||||
// 组装菜单
|
||||
let menus = [{
|
||||
name: "发送给朋友",
|
||||
event: 'sendToChatItem'
|
||||
}, {
|
||||
name: "收藏",
|
||||
event: 'fava'
|
||||
}, {
|
||||
name: "删除",
|
||||
event: 'delete'
|
||||
}]
|
||||
let item = this.list[this.propIndex]
|
||||
menus.push({
|
||||
name: "撤回",
|
||||
event: 'removeChatItem'
|
||||
})
|
||||
// #ifndef H5
|
||||
if (item.type === 'text') {
|
||||
menus.unshift({
|
||||
name: "复制",
|
||||
event: 'copy',
|
||||
})
|
||||
}
|
||||
// #endif
|
||||
this.menusList = menus
|
||||
// 显示扩展菜单
|
||||
this.$refs.extend.show(x, y)
|
||||
},
|
||||
// 操作菜单方法分发
|
||||
clickEvent(event) {
|
||||
// 关闭菜单
|
||||
this.$refs.extend.hide()
|
||||
},
|
||||
// 扩展菜单
|
||||
actionEvent(e) {
|
||||
switch (e.event) {
|
||||
case 'uploadImage': // 选择相册
|
||||
uni.chooseImage({
|
||||
count: 9,
|
||||
success: (res) => {
|
||||
// 发送到服务器
|
||||
// 渲染到页面
|
||||
res.tempFilePaths.forEach((item) => {
|
||||
this.send('image', item)
|
||||
})
|
||||
}
|
||||
})
|
||||
break;
|
||||
case 'uploadVideo': // 发送短视频
|
||||
uni.chooseVideo({
|
||||
maxDuration: 10,
|
||||
success: (res) => {
|
||||
this.send('video', res.tempFilePath)
|
||||
// 渲染页面
|
||||
// 发送到服务端(获取视频封面,返回url)
|
||||
// 修改本地的发送状态
|
||||
}
|
||||
})
|
||||
break;
|
||||
}
|
||||
},
|
||||
// 点击页面
|
||||
clickPage() {
|
||||
this.mode = ''
|
||||
},
|
||||
// 切换音频录制和文本输入
|
||||
changeVoiceOrText() {
|
||||
this.mode = this.mode !== 'audio' ? 'audio' : 'text'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,144 @@
|
||||
<template>
|
||||
<view>
|
||||
<view>
|
||||
<view class="flex align-center justify-center"
|
||||
style="height: 350rpx;">
|
||||
<text style="font-size: 50rpx;">LOGO</text>
|
||||
</view>
|
||||
<view class="px-3">
|
||||
<input type="text" class="bg-light px-3 mb-3 font" :placeholder=getUserNameText style="height: 100rpx;" v-model="form.userName"/>
|
||||
<input type="text" class="bg-light px-3 mb-3 font" placeholder="请输入密码" style="height: 100rpx;" v-model="form.password"/>
|
||||
<input v-if="type === 'reg'" type="text" class="bg-light px-3 mb-3 font" placeholder="请输入确认密码" style="height: 100rpx;" v-model="form.repassword"/>
|
||||
</view>
|
||||
<view class="p-3 flex align-center justify-center">
|
||||
<view class="main-bg-color rounded p-3 flex align-center justify-center flex-1"
|
||||
hover-class="main-bg-hover-color" @click="submit">
|
||||
<text class="text-white font-md">{{type === 'login' ? '登 录' : '注 册'}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="flex align-center justify-center">
|
||||
<text class="text-light-muted font p-2" @click="changeType">{{type === 'login' ? '注册账号' : '马上登录'}}</text>
|
||||
<text class="text-light-muted font">|</text>
|
||||
<text class="text-light-muted font p-2">忘记密码</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import $H from '@/common/lib/request.js';
|
||||
import Vue from 'vue'
|
||||
|
||||
const ListenerMap = {
|
||||
onSocketConnectEvent: (option, status, data) => {
|
||||
console.log("已建立连接:" + JSON.stringify(status));
|
||||
},
|
||||
onSocketErrorEvent: (error) => {
|
||||
console.log("连接出现错误:" + userId);
|
||||
},
|
||||
onSocketReConnectEvent: () => {
|
||||
console.log("正在重连:" );
|
||||
},
|
||||
onSocketCloseEvent: () => {
|
||||
console.log("连接关闭:" );
|
||||
},onSocketReConnectSuccessEvent: () => {
|
||||
console.log("重连成功" );
|
||||
},
|
||||
onTestMessage: (e) => {
|
||||
console.log("onTestMessage :" + e );
|
||||
},
|
||||
onP2PMessage: (e) => {
|
||||
console.log("onP2PMessage :" + e );
|
||||
e = JSON.parse(e)
|
||||
uni.$emit('P2PMessage', e.data);
|
||||
},
|
||||
onLogin: (uid) => {
|
||||
console.log("用户"+uid+"登陆sdk成功" );
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
type:"login",
|
||||
form: {
|
||||
userName:"lld",
|
||||
password:"lld",
|
||||
repassword:"",
|
||||
loginType:1
|
||||
},
|
||||
show:true
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
},
|
||||
methods: {
|
||||
changeType(){
|
||||
// this.type = this.type === 'login' ? 'reg' : 'login'
|
||||
// this.form = {
|
||||
// username:"",
|
||||
// password:"",
|
||||
// repassword:""
|
||||
// }
|
||||
},
|
||||
submit() {
|
||||
if(this.type === 'login'){
|
||||
$H.post('/login',this.form,{
|
||||
token:false
|
||||
}).then(res=>{
|
||||
console.log(res)
|
||||
if(res.code !== 200){
|
||||
uni.showToast({
|
||||
title: res.msg,
|
||||
icon: 'none'
|
||||
});
|
||||
}else{
|
||||
//app服务登录成功,去登录im
|
||||
const lim = this.imsdk
|
||||
const sdk = lim.im;
|
||||
|
||||
var userId = this.form.userName;
|
||||
var listeners = {};
|
||||
for (const v in ListenerMap) {
|
||||
listeners[v] = ListenerMap[v];
|
||||
}
|
||||
|
||||
sdk.init("http://127.0.0.1:8000/v1",res.data.appId,res.data.userId,res.data.imUserSign,listeners,function (sdk) {
|
||||
if(sdk){
|
||||
console.log('sdk 成功连接的回调, 可以使用 sdk 请求数据了.');
|
||||
return uni.switchTab({
|
||||
url:"/pages/tabbar/index/index"
|
||||
})
|
||||
}
|
||||
else {
|
||||
console.log('sdk 初始化失败.');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
getUserNameText(){
|
||||
if(this.type === 'login'){
|
||||
return "请输入用户名";
|
||||
}
|
||||
else if(this.type === 'reg'){
|
||||
return "请输入手机号";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,40 @@
|
||||
<template>
|
||||
<view class="page">
|
||||
<!-- 导航栏 -->
|
||||
<nav-bar title="我的设置" showBack :showRight="false"></nav-bar>
|
||||
<!-- 退出登录 -->
|
||||
<divider></divider>
|
||||
<view class="py-3 flex align-center justify-center bg-white" hover-class="bg-light" @click="logout">
|
||||
<text class="font-md text-primary">退出登录</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import navBar from "@/components/ui/nav-bar.vue"
|
||||
import divider from "@/components/ui/divider.vue"
|
||||
import $H from '@/common/lib/request.js';
|
||||
export default {
|
||||
components: {
|
||||
navBar,
|
||||
divider
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
logout() {
|
||||
// 跳转到登录页
|
||||
uni.reLaunch({
|
||||
url: "/pages/common/login/login"
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,63 @@
|
||||
<template>
|
||||
<view class="page">
|
||||
<!-- 导航栏 -->
|
||||
<nav-bar title="个人资料" showBack :showRight="false"></nav-bar>
|
||||
<list-item title="头像" showRight :showLeftIcon="false">
|
||||
<avater slot="right" :src="user.avatar"></avater>
|
||||
</list-item>
|
||||
<list-item title="昵称" showRight :showLeftIcon="false">
|
||||
<text slot="right" class="font text-muted">{{user.nickname}}</text>
|
||||
</list-item>
|
||||
<list-item title="账号" showRight :showLeftIcon="false">
|
||||
<text slot="right" class="font text-muted">{{user.username}}</text>
|
||||
</list-item>
|
||||
|
||||
<confirm ref="confirm" :title="confirmTitle">
|
||||
<input type="text" v-model="confirmText" :placeholder="placeholder" class="border-bottom font-md"/>
|
||||
</confirm>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import navBar from "@/components/ui/nav-bar.vue"
|
||||
import avater from '@/components/ui/avater.vue';
|
||||
import listItem from "@/components/ui/list-item.vue"
|
||||
import confirm from '@/components/ui/confirm.vue';
|
||||
|
||||
import $H from '@/common/lib/request.js';
|
||||
export default {
|
||||
components: {
|
||||
navBar,
|
||||
avater,
|
||||
listItem,
|
||||
confirm
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
confirmText:"",
|
||||
confirmType:"",
|
||||
user:{
|
||||
avatar:"",
|
||||
nickname:"lld",
|
||||
username:"lld"
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
confirmTitle() {
|
||||
return this.confirmType == 'username' ? '修改账号' :'修改昵称'
|
||||
},
|
||||
placeholder(){
|
||||
return this.confirmType == 'username' ? '输入账号' :'输入昵称'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,71 @@
|
||||
<template>
|
||||
<view class="page">
|
||||
<!-- 导航栏 -->
|
||||
<nav-bar title="发现"></nav-bar>
|
||||
|
||||
<!-- 通讯录列表 -->
|
||||
<list-item title="朋友圈" showRight>
|
||||
<text slot="icon" class="iconfont font-lg py-1"></text>
|
||||
<view slot="right" class="p-1">
|
||||
<view class="position-relative" v-if="!notice.num">
|
||||
<text class="rounded-circle bg-danger position-absolute" style="width: 20rpx;height: 20rpx;top: 0;right: 0;"></text>
|
||||
</view>
|
||||
<badge v-if="notice.num" :value="notice.num"></badge>
|
||||
</view>
|
||||
</list-item>
|
||||
<divider></divider>
|
||||
<list-item title="扫一扫" showRight>
|
||||
<text slot="icon" class="iconfont font-lg py-1"></text>
|
||||
</list-item>
|
||||
<list-item title="摇一摇" showRight>
|
||||
<text slot="icon" class="iconfont font-lg py-1"></text>
|
||||
</list-item>
|
||||
<divider></divider>
|
||||
<list-item title="看一看" showRight>
|
||||
<text slot="icon" class="iconfont font-lg py-1"></text>
|
||||
</list-item>
|
||||
<list-item title="搜一搜" showRight>
|
||||
<text slot="icon" class="iconfont font-lg py-1"></text>
|
||||
</list-item>
|
||||
<divider></divider>
|
||||
<list-item title="购物" showRight>
|
||||
<text slot="icon" class="iconfont font-lg py-1"></text>
|
||||
</list-item>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import navBar from "@/components/ui/nav-bar.vue"
|
||||
import listItem from "@/components/ui/list-item.vue"
|
||||
import divider from "@/components/ui/divider.vue"
|
||||
import badge from "@/components/ui/badge.vue"
|
||||
import auth from '@/common/mixin/auth.js'
|
||||
|
||||
export default {
|
||||
mixins:[auth],
|
||||
components: {
|
||||
navBar,
|
||||
listItem,
|
||||
divider,
|
||||
badge
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
notice:{
|
||||
num: 1,
|
||||
userId:"lld",
|
||||
avatar:"/static/images/userpic.png"
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,151 @@
|
||||
<template>
|
||||
|
||||
<view>
|
||||
<!-- 导航栏 -->
|
||||
<nav-bar title="微信(10)">
|
||||
</nav-bar>
|
||||
|
||||
<!-- 置顶列表 -->
|
||||
<block v-for="(item,index) in list" :key="index">
|
||||
<media-list v-if="item.istop" :item="item" :index="index" @long="long"></media-list>
|
||||
</block>
|
||||
|
||||
<!-- 非置顶列表 -->
|
||||
<block v-for="(item,index) in list" :key="index">
|
||||
<media-list v-if="!item.istop" :item="item" :index="index" @long="long"></media-list>
|
||||
</block>
|
||||
|
||||
<!-- 弹出层 -->
|
||||
<popup ref="extend" :bodyWidth="240" :bodyHeight="getMenusHeight">
|
||||
<view class="flex flex-column" style="width: 240rpx;" :style="getMenusStyle">
|
||||
<view class="flex-1 flex align-center" hover-class="bg-light" v-for="(item,index) in menus" :key="index"
|
||||
@click="clickEvent(item.event)">
|
||||
<text class="font-md pl-3">{{item.name}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</popup>
|
||||
</view>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import navBar from "@/components/ui/nav-bar.vue"
|
||||
import mediaList from "@/components/ui/media-list.vue"
|
||||
import popup from "@/components/ui/popup.vue"
|
||||
import auth from '@/common/mixin/auth.js'
|
||||
|
||||
export default {
|
||||
mixins:[auth],
|
||||
components: {
|
||||
navBar,
|
||||
mediaList,
|
||||
popup
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
propIndex: -1,
|
||||
list: [{
|
||||
avatar: "/static/images/userpic.png",
|
||||
nickname: "lld",
|
||||
id: "lld",
|
||||
updateTime: 1657554934224,
|
||||
data: "我是lld",
|
||||
istop: true,
|
||||
noreadnum: 1
|
||||
},
|
||||
{
|
||||
avatar: "/static/images/userpic.png",
|
||||
nickname: "lld2",
|
||||
id: "lld2",
|
||||
updateTime: 1654962934000,
|
||||
data: "我是lld2",
|
||||
istop: false,
|
||||
noreadnum: 0
|
||||
},
|
||||
{
|
||||
avatar: "../../../static/images/userpic.png",
|
||||
nickname: "lld3",
|
||||
id: "lld3",
|
||||
updateTime: 1626018934000,
|
||||
data: "我是lld3",
|
||||
istop: true,
|
||||
noreadnum: 1
|
||||
}
|
||||
],
|
||||
|
||||
menus: [{
|
||||
name: "设为置顶",
|
||||
event: "setTop"
|
||||
},
|
||||
{
|
||||
name: "删除该聊天",
|
||||
event: "delChat"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
|
||||
},
|
||||
onShow() {
|
||||
|
||||
},
|
||||
computed:{
|
||||
// 动态获取菜单高度
|
||||
getMenusHeight(){
|
||||
let H = 100
|
||||
return this.menus.length * H
|
||||
},
|
||||
// 获取菜单的样式
|
||||
getMenusStyle(){
|
||||
return `height: ${this.getMenusHeight}rpx;`
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
openExtend() {
|
||||
this.$refs.extend.show();
|
||||
},
|
||||
long({
|
||||
x,
|
||||
y,
|
||||
index
|
||||
}) {
|
||||
// 初始化 索引
|
||||
this.propIndex = index
|
||||
// 拿到当前对象
|
||||
let item = this.list[index]
|
||||
// 判断之前是否处于置顶状态
|
||||
this.menus[0].name = item.istop ? '取消置顶' : '设为置顶'
|
||||
this.$refs.extend.show(x, y)
|
||||
},
|
||||
// 分发菜单事件
|
||||
clickEvent(event){
|
||||
switch (event){
|
||||
case "setTop": // 置顶/取消置顶会话
|
||||
this.setTop()
|
||||
break;
|
||||
case "delChat": // 删除当前会话
|
||||
this.delChat()
|
||||
break;
|
||||
}
|
||||
this.$refs.extend.hide()
|
||||
},
|
||||
// 置顶/取消置顶会话
|
||||
setTop(){
|
||||
let item = this.list[this.propIndex]
|
||||
item.istop = !item.istop
|
||||
},
|
||||
// 删除当前会话
|
||||
delChat(){
|
||||
this.list.splice(this.propIndex,1);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
|
||||
</style>
|
||||
166
l-im-app-imooc-master/l-im-app-imooc/pages/tabbar/mail/mail.vue
Normal file
@@ -0,0 +1,166 @@
|
||||
<template>
|
||||
<view>
|
||||
<!-- 导航栏 -->
|
||||
<nav-bar title="通讯录" :showBack="false" :showRight="false">
|
||||
|
||||
</nav-bar>
|
||||
|
||||
<scroll-view scroll-y="true" :style="'height:'+scrollHeight+'px;'" :scroll-into-view="scrollInto">
|
||||
<!-- 通讯录列表 :showRight="item.id === 'friend' && applyCount > 0" -->
|
||||
<list-item v-for="(item,index) in topList" :title="item.title" :key="item.id" :cover="item.cover">
|
||||
</list-item>
|
||||
</scroll-view>
|
||||
|
||||
|
||||
<!-- 侧边导航条 -->
|
||||
<view class="position-fixed right-0 bottom-0 bg-light flex flex-column" :style="'top:' +top+ 'px'"
|
||||
style="width: 50rpx;">
|
||||
</view>
|
||||
|
||||
<!-- 侧边导航条 -->
|
||||
<!-- <view class="position-fixed right-0 bottom-0 bg-light flex flex-column" :style="'top:'+top+'px;'"
|
||||
style="width: 50rpx;" @touchstart="touchstart" @touchmove="touchmove" @touchend="touchend">
|
||||
<view class="flex-1 flex align-center justify-center" v-for="(item,index) in list.keys()" :key="index">
|
||||
<text class="font-sm text-muted">{{item}}</text>
|
||||
</view>
|
||||
</view> -->
|
||||
|
||||
<!-- <view class="position-fixed rounded-circle bg-light border flex align-center justify-center" v-if="current"
|
||||
style="width: 150rpx;height: 150rpx;left: 300rpx;"
|
||||
:style="'top:'+modalTop+'px;'">
|
||||
<text class="font-lg">{{current}}</text>
|
||||
</view> -->
|
||||
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import navBar from "@/components/ui/nav-bar.vue"
|
||||
import listItem from "@/components/ui/list-item.vue"
|
||||
import auth from '@/common/mixin/auth.js'
|
||||
import badge from "@/components/ui/badge.vue"
|
||||
|
||||
export default {
|
||||
mixins:[auth],
|
||||
components: {
|
||||
navBar,
|
||||
listItem,
|
||||
badge
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
top: 0,
|
||||
friendRequestNum: 0,
|
||||
topList: [{
|
||||
id: "friend",
|
||||
title: "新的朋友",
|
||||
cover: "/static/images/mail/friend.png",
|
||||
path: "mail/apply-list/apply-list"
|
||||
},
|
||||
{
|
||||
id: "group",
|
||||
title: "群聊",
|
||||
cover: "/static/images/mail/group.png",
|
||||
path: "mail/group-list/group-list"
|
||||
},
|
||||
{
|
||||
id: "tag",
|
||||
title: "标签",
|
||||
cover: "/static/images/mail/tag.png",
|
||||
path: "mail/tag-list/tag-list"
|
||||
}
|
||||
],
|
||||
// list: new Map(),
|
||||
list:
|
||||
[{
|
||||
"letter": "A",
|
||||
"data": [
|
||||
"AAAAA微商",
|
||||
"a ",
|
||||
"澳门风云"
|
||||
]
|
||||
},
|
||||
{
|
||||
"letter": "B",
|
||||
"data": [
|
||||
"宝贝",
|
||||
]
|
||||
},
|
||||
{
|
||||
"letter": "C",
|
||||
"data": [
|
||||
"草原",
|
||||
]
|
||||
},
|
||||
{
|
||||
"letter": "D",
|
||||
"data": []
|
||||
},
|
||||
{
|
||||
"letter": "E",
|
||||
"data": []
|
||||
},
|
||||
{
|
||||
"letter": "F",
|
||||
"data": []
|
||||
},
|
||||
{
|
||||
"letter": "G",
|
||||
"data": []
|
||||
},
|
||||
{
|
||||
"letter": "H",
|
||||
"data": [
|
||||
"黄飞鸿",
|
||||
"黄继光"
|
||||
]
|
||||
},
|
||||
{
|
||||
"letter": "I",
|
||||
"data": [
|
||||
"ICON",
|
||||
"icc",
|
||||
"icc",
|
||||
"icc",
|
||||
"icc"
|
||||
]
|
||||
}
|
||||
]
|
||||
,
|
||||
|
||||
top: 0,
|
||||
scrollHeight: 0,
|
||||
scrollInto: '',
|
||||
current: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
},
|
||||
onLoad() {
|
||||
let res = uni.getSystemInfoSync()
|
||||
this.top = res.statusBarHeight + uni.upx2px(90)
|
||||
this.scrollHeight = res.windowHeight - this.top
|
||||
},
|
||||
onShow() {
|
||||
},
|
||||
computed: {
|
||||
// 每个索引的高度
|
||||
itemHeight() {
|
||||
let count = this.list.size
|
||||
// debugger;
|
||||
if (count < 1) {
|
||||
return 0
|
||||
}
|
||||
return this.scrollHeight / count
|
||||
},
|
||||
modalTop(){
|
||||
return (this.scrollHeight - uni.upx2px(150)) / 2
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
77
l-im-app-imooc-master/l-im-app-imooc/pages/tabbar/my/my.vue
Normal file
@@ -0,0 +1,77 @@
|
||||
<template>
|
||||
<view class="page">
|
||||
<!-- 导航栏 -->
|
||||
<nav-bar bgColor="bg-white">
|
||||
<icon-button slot="right" :icon="'\ue6ed'"></icon-button>
|
||||
</nav-bar>
|
||||
|
||||
<list-item :cover="user.photo ? user.photo : '/static/images/userpic.jpg'"
|
||||
coverSize="120" :title="user.nickName" showRight @click="open('my/userinfo/userinfo')">
|
||||
<view class="flex flex-column">
|
||||
<text class="text-dark font-lg font-weight-bold">{{user.nickName}}</text>
|
||||
<text class="text-light-muted font mt-2">仿微信号:{{user.nickName}}</text>
|
||||
</view>
|
||||
<view slot="right">
|
||||
<text class="iconfont font-md text-light-muted"></text>
|
||||
</view>
|
||||
</list-item>
|
||||
|
||||
<divider></divider>
|
||||
|
||||
<list-item title="支付" showRight>
|
||||
<text slot="icon" class="iconfont font-lg py-1"></text>
|
||||
</list-item>
|
||||
|
||||
<divider></divider>
|
||||
|
||||
<list-item title="相册" showRight
|
||||
@click="open()">
|
||||
<text slot="icon" class="iconfont font-lg py-1"></text>
|
||||
</list-item>
|
||||
|
||||
<divider></divider>
|
||||
|
||||
<list-item title="设置" showRight @click="open('my/setting/setting')">
|
||||
<text slot="icon" class="iconfont font-lg py-1"></text>
|
||||
</list-item>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import navBar from "@/components/ui/nav-bar.vue"
|
||||
import iconButton from "@/components/ui/icon-button.vue"
|
||||
import listItem from "@/components/ui/list-item.vue"
|
||||
import divider from "@/components/ui/divider.vue"
|
||||
import auth from '@/common/mixin/auth.js'
|
||||
import { mapState } from 'vuex'
|
||||
|
||||
export default {
|
||||
components:{
|
||||
navBar,
|
||||
listItem,
|
||||
iconButton,
|
||||
divider
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
user:{
|
||||
nickName:"lld"
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
open(path){
|
||||
uni.navigateTo({
|
||||
url: '/pages/'+path
|
||||
});
|
||||
},
|
||||
},
|
||||
computed:{
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
BIN
l-im-app-imooc-master/l-im-app-imooc/static/images/mail/tag.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
l-im-app-imooc-master/l-im-app-imooc/static/images/userpic.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
BIN
l-im-app-imooc-master/l-im-app-imooc/static/tabbar/find.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
BIN
l-im-app-imooc-master/l-im-app-imooc/static/tabbar/index.png
Normal file
|
After Width: | Height: | Size: 964 B |
|
After Width: | Height: | Size: 1.4 KiB |
BIN
l-im-app-imooc-master/l-im-app-imooc/static/tabbar/mail.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
l-im-app-imooc-master/l-im-app-imooc/static/tabbar/my-select.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
l-im-app-imooc-master/l-im-app-imooc/static/tabbar/my.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
12
l-im-app-imooc-master/l-im-app-imooc/store/index.js
Normal file
@@ -0,0 +1,12 @@
|
||||
import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
|
||||
Vue.use(Vuex)
|
||||
|
||||
import common from '@/store/modules/common.js';
|
||||
|
||||
export default new Vuex.Store({
|
||||
modules:{
|
||||
common
|
||||
}
|
||||
})
|
||||
10
l-im-app-imooc-master/l-im-app-imooc/store/modules/common.js
Normal file
@@ -0,0 +1,10 @@
|
||||
export default {
|
||||
state:{
|
||||
keyboardHeight:0
|
||||
},
|
||||
mutations:{
|
||||
changeKeyboardHeight(state,h){
|
||||
state.keyboardHeight = h
|
||||
}
|
||||
}
|
||||
}
|
||||
76
l-im-app-imooc-master/l-im-app-imooc/uni.scss
Normal file
@@ -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;
|
||||