committed by
Gitee
54 changed files with 1403 additions and 630 deletions
@ -0,0 +1,175 @@ |
|||||
|
<template> |
||||
|
<el-scrollbar v-show="show" ref="scrollBox" class="group-member-choose" |
||||
|
:style="{'left':pos.x+'px','top':pos.y-300+'px'}"> |
||||
|
<div v-for="(member,idx) in showMembers" :key="member.id"> |
||||
|
<div class="member-item" :class="idx==activeIdx?'active':''" @click="onSelectMember(member)"> |
||||
|
<div class="member-avatar"> |
||||
|
<head-image :size="25" :name="member.aliasName" :url="member.headImage"> </head-image> |
||||
|
</div> |
||||
|
<div class="member-name"> |
||||
|
<div>{{member.aliasName}}</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</el-scrollbar> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import HeadImage from '../common/HeadImage.vue'; |
||||
|
|
||||
|
export default { |
||||
|
name: "chatAtBox", |
||||
|
components: { |
||||
|
HeadImage |
||||
|
}, |
||||
|
props: { |
||||
|
searchText: { |
||||
|
type: String, |
||||
|
default: "" |
||||
|
}, |
||||
|
ownerId: { |
||||
|
type: Number, |
||||
|
}, |
||||
|
members: { |
||||
|
type: Array |
||||
|
} |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
show: false, |
||||
|
pos: { |
||||
|
x: 0, |
||||
|
y: 0 |
||||
|
}, |
||||
|
activeIdx: 0, |
||||
|
showMembers: [] |
||||
|
}; |
||||
|
}, |
||||
|
methods: { |
||||
|
init() { |
||||
|
this.$refs.scrollBox.wrap.scrollTop = 0; |
||||
|
this.showMembers = []; |
||||
|
let userId = this.$store.state.userStore.userInfo.id; |
||||
|
let name = "全体成员"; |
||||
|
if (this.ownerId == userId && name.startsWith(this.searchText)) { |
||||
|
this.showMembers.push({ |
||||
|
userId: -1, |
||||
|
aliasName: name |
||||
|
}) |
||||
|
} |
||||
|
this.members.forEach((m) => { |
||||
|
if (m.userId != userId && m.aliasName.startsWith(this.searchText)) { |
||||
|
this.showMembers.push(m); |
||||
|
} |
||||
|
}) |
||||
|
this.activeIdx = this.showMembers.length > 0 ? 0: -1; |
||||
|
}, |
||||
|
open(pos) { |
||||
|
this.show = true; |
||||
|
this.pos = pos; |
||||
|
this.init(); |
||||
|
}, |
||||
|
close() { |
||||
|
this.show = false; |
||||
|
}, |
||||
|
moveUp() { |
||||
|
if (this.activeIdx > 0) { |
||||
|
this.activeIdx--; |
||||
|
this.scrollToActive() |
||||
|
} |
||||
|
}, |
||||
|
moveDown() { |
||||
|
if (this.activeIdx < this.showMembers.length - 1) { |
||||
|
this.activeIdx++; |
||||
|
this.scrollToActive() |
||||
|
} |
||||
|
}, |
||||
|
select() { |
||||
|
if (this.activeIdx >= 0) { |
||||
|
this.onSelectMember(this.showMembers[this.activeIdx]) |
||||
|
} |
||||
|
this.close(); |
||||
|
}, |
||||
|
scrollToActive() { |
||||
|
if (this.activeIdx * 35 - this.$refs.scrollBox.wrap.clientHeight > this.$refs.scrollBox.wrap.scrollTop) { |
||||
|
this.$refs.scrollBox.wrap.scrollTop += 140; |
||||
|
if (this.$refs.scrollBox.wrap.scrollTop > this.$refs.scrollBox.wrap.scrollHeight) { |
||||
|
this.$refs.scrollBox.wrap.scrollTop = this.$refs.scrollBox.wrap.scrollHeight |
||||
|
} |
||||
|
} |
||||
|
if (this.activeIdx * 35 < this.$refs.scrollBox.wrap.scrollTop) { |
||||
|
this.$refs.scrollBox.wrap.scrollTop -= 140; |
||||
|
if (this.$refs.scrollBox.wrap.scrollTop < 0) { |
||||
|
this.$refs.scrollBox.wrap.scrollTop = 0; |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
onSelectMember(member) { |
||||
|
this.$emit("select", member); |
||||
|
this.show = false; |
||||
|
} |
||||
|
}, |
||||
|
computed: { |
||||
|
isOwner() { |
||||
|
return this.$store.state.userStore.userInfo.id == this.ownerId; |
||||
|
} |
||||
|
}, |
||||
|
watch: { |
||||
|
searchText: { |
||||
|
handler(newText, oldText) { |
||||
|
this.init(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style scoped lang="scss"> |
||||
|
.group-member-choose { |
||||
|
position: fixed; |
||||
|
width: 200px; |
||||
|
height: 300px; |
||||
|
border: 1px solid #b4b4b4; |
||||
|
border-radius: 5px; |
||||
|
background-color: #f5f5f5; |
||||
|
box-shadow: 0px 0px 10px #ccc; |
||||
|
|
||||
|
.member-item { |
||||
|
display: flex; |
||||
|
height: 35px; |
||||
|
margin-bottom: 1px; |
||||
|
position: relative; |
||||
|
padding: 0 5px; |
||||
|
align-items: center; |
||||
|
background-color: #fafafa; |
||||
|
white-space: nowrap; |
||||
|
box-sizing: border-box; |
||||
|
|
||||
|
&:hover { |
||||
|
background-color: #eeeeee; |
||||
|
} |
||||
|
|
||||
|
&.active { |
||||
|
background-color: #eeeeee; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
.member-avatar { |
||||
|
width: 25px; |
||||
|
height: 25px; |
||||
|
} |
||||
|
|
||||
|
.member-name { |
||||
|
padding-left: 10px; |
||||
|
height: 100%; |
||||
|
text-align: left; |
||||
|
line-height: 40px; |
||||
|
white-space: nowrap; |
||||
|
overflow: hidden; |
||||
|
font-size: 14px; |
||||
|
font-weight: 600; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,176 @@ |
|||||
|
<template> |
||||
|
<uni-popup ref="popup" type="bottom" @change="onChange"> |
||||
|
<view class="chat-at-box"> |
||||
|
<view class="chat-at-top"> |
||||
|
<view class="chat-at-tip"> 选择要提醒的人</view> |
||||
|
<button class="chat-at-btn" type="warn" size="mini" @click="onClean()">清空 </button> |
||||
|
<button class="chat-at-btn" type="primary" size="mini" @click="onOk()">确定({{atUserIds.length}}) |
||||
|
</button> |
||||
|
</view> |
||||
|
<scroll-view v-show="atUserIds.length>0" scroll-x="true" scroll-left="120"> |
||||
|
<view class="at-user-items"> |
||||
|
<view v-for="m in showMembers" v-show="m.checked" class="at-user-item"> |
||||
|
<head-image :name="m.aliasName" :url="m.headImage" :size="60"></head-image> |
||||
|
</view> |
||||
|
</view> |
||||
|
</scroll-view> |
||||
|
<view class="search-bar"> |
||||
|
<uni-search-bar v-model="searchText" cancelButton="none" placeholder="搜索"></uni-search-bar> |
||||
|
</view> |
||||
|
<view class="member-items"> |
||||
|
<scroll-view class="scroll-bar" scroll-with-animation="true" scroll-y="true"> |
||||
|
<view v-for="m in showMembers" v-show="m.aliasName.startsWith(searchText)" |
||||
|
:key="m.userId"> |
||||
|
<view class="member-item" @click="onSwitchChecked(m)"> |
||||
|
<head-image :name="m.aliasName" :online="m.online" :url="m.headImage" |
||||
|
:size="90"></head-image> |
||||
|
<view class="member-name">{{ m.aliasName}}</view> |
||||
|
<view class="member-checked"> |
||||
|
<radio :checked="m.checked" @click.stop="onSwitchChecked(m)" /> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</scroll-view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</uni-popup> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
export default { |
||||
|
name: "chat-at-box", |
||||
|
props: { |
||||
|
ownerId: { |
||||
|
type: Number, |
||||
|
}, |
||||
|
members: { |
||||
|
type: Array |
||||
|
} |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
searchText: "", |
||||
|
showMembers:[] |
||||
|
}; |
||||
|
}, |
||||
|
methods: { |
||||
|
init(atUserIds) { |
||||
|
this.showMembers = []; |
||||
|
let userId = this.$store.state.userStore.userInfo.id; |
||||
|
if(this.ownerId == userId){ |
||||
|
this.showMembers.push({ |
||||
|
userId:-1, |
||||
|
aliasName: "全体成员" |
||||
|
}) |
||||
|
} |
||||
|
this.members.forEach((m) => { |
||||
|
if(m.userId != userId){ |
||||
|
m.checked = atUserIds.indexOf(m.userId) >= 0; |
||||
|
this.showMembers.push(m); |
||||
|
} |
||||
|
}); |
||||
|
}, |
||||
|
open() { |
||||
|
this.$refs.popup.open(); |
||||
|
}, |
||||
|
onSwitchChecked(member) { |
||||
|
member.checked = !member.checked; |
||||
|
}, |
||||
|
onClean() { |
||||
|
this.showMembers.forEach((m) => { |
||||
|
m.checked = false; |
||||
|
}) |
||||
|
}, |
||||
|
onOk() { |
||||
|
this.$refs.popup.close(); |
||||
|
}, |
||||
|
onChange(e) { |
||||
|
if (!e.show) { |
||||
|
this.$emit("complete", this.atUserIds) |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
computed: { |
||||
|
atUserIds() { |
||||
|
let ids = []; |
||||
|
this.showMembers.forEach((m) => { |
||||
|
if (m.checked) { |
||||
|
ids.push(m.userId); |
||||
|
} |
||||
|
}) |
||||
|
return ids; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
|
||||
|
<style lang="scss" scoped> |
||||
|
.chat-at-box { |
||||
|
position: relative; |
||||
|
border: #dddddd solid 1rpx; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
background-color: white; |
||||
|
padding: 10rpx; |
||||
|
border-radius: 15rpx; |
||||
|
|
||||
|
.chat-at-top { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
height: 70rpx; |
||||
|
padding: 10rpx; |
||||
|
|
||||
|
.chat-at-tip { |
||||
|
flex: 1; |
||||
|
} |
||||
|
|
||||
|
.chat-at-btn { |
||||
|
margin-left: 10rpx; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
.at-user-items { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
height: 90rpx; |
||||
|
|
||||
|
.at-user-item { |
||||
|
padding: 3rpx; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
.member-items { |
||||
|
position: relative; |
||||
|
flex: 1; |
||||
|
overflow: hidden; |
||||
|
|
||||
|
.member-item { |
||||
|
height: 120rpx; |
||||
|
display: flex; |
||||
|
position: relative; |
||||
|
padding: 0 30rpx; |
||||
|
align-items: center; |
||||
|
background-color: white; |
||||
|
white-space: nowrap; |
||||
|
|
||||
|
.member-name { |
||||
|
flex: 1; |
||||
|
padding-left: 20rpx; |
||||
|
font-size: 30rpx; |
||||
|
font-weight: 600; |
||||
|
line-height: 60rpx; |
||||
|
white-space: nowrap; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.scroll-bar { |
||||
|
height: 800rpx; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</style> |
||||
Binary file not shown.
Loading…
Reference in new issue