| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425 |
- <template>
- <view :style="popupStyle" class="message_menu_container" :class="{ message_menu_container_bottom: is_bottom }">
- <view class="message_menu_item" v-for="item in menuList" @click="menuClick(item)" :key="item.idx">
- <image :src="item.icon" class="message_menu_icon" />
- <text class="message_menu_text">{{ item.title }}</text>
- </view>
- </view>
- </template>
- <script>
- import { mapGetters, mapActions } from 'vuex';
- import { MessageMenuTypes, ContactChooseTypes, PageEvents } from '../../../../../constant';
- import IMSDK, { GroupMemberRole, MessageType, SessionType } from 'openim-uniapp-polyfill';
- import { parseAt } from '../../../../../util/imCommon';
- import copy from '../../../../../static/images/chating_message_copy.png';
- import forward from '../../../../../static/images/chating_message_forward.png';
- import reply from '../../../../../static/images/chating_message_reply.png';
- import revoke from '../../../../../static/images/chating_message_revoke.png';
- import multiple from '../../../../../static/images/chating_message_multiple.png';
- import del from '../../../../../static/images/chating_message_del.png';
- const canCopyTypes = [MessageType.TextMessage, MessageType.AtTextMessage, MessageType.QuoteMessage, MessageType.GroupAnnouncementUpdated];
- export default {
- components: {},
- props: {
- message: Object,
- isSender: {
- type: Boolean,
- default: false
- },
- paterWidth: {
- type: [Number, String],
- default: 0
- },
- is_bottom: {
- type: Boolean,
- default: false
- },
- rect: {
- type: Object,
- default: () => ({})
- }
- },
- data() {
- return {
- contentType: null
- };
- },
- computed: {
- ...mapGetters(['storeCurrentMemberInGroup', 'storeCurrentUserID',"storeCurrentConversation"]),
- getLeft() {
- // 145 + 145*0.2
- if (this.isSender && this.paterWidth < 174) {
- return 'auto';
- }
- if (!this.isSender && this.paterWidth < 174) {
- return '0';
- }
- return '20%';
- },
- getRight() {
- if (this.isSender && this.paterWidth < 174) {
- return '0';
- }
- return 'auto';
- },
- popupStyle() {
- // 如果有 rect 参数,说明是全局定位
- if (this.rect && this.rect.top !== undefined) {
- const style = {};
- // 假设屏幕高度大概是 750px (rpx) 或者根据实际像素
- // nvue 中单位默认是 px
- // 简单的判断:如果 top < 200,向下弹;否则向上弹
- const isTop = this.rect.top < 200;
-
- if (isTop) {
- style.top = (this.rect.top + this.rect.height + 10) + 'px';
- } else {
- // 向上弹,需要知道 menu 高度。这里无法预知,只能 bottom 定位?
- // 但是 bottom 是相对于屏幕底部的。
- // 我们可以用 top: rect.top - menuHeight
- // 还是 bottom 比较稳妥
- // style.bottom = (windowHeight - this.rect.top + 10) + 'px';
- // nvue 没有 windowHeight 直接可用,需要 uni.getSystemInfoSync
- // 为了简单,我们尽量用 top
-
- // 临时方案:始终向下弹?不行,底部消息会被遮挡。
- // 我们还是用 fixed bottom 吧,但是需要知道屏幕高度。
- const sys = uni.getSystemInfoSync();
- style.bottom = (sys.windowHeight - this.rect.top + 10) + 'px';
- }
- // 水平定位
- // 居中于消息气泡,或者左对齐
- // style.left = this.rect.left + 'px';
- // 为了不超出屏幕,可能需要 clamp
- let left = this.rect.left;
- // 简单的防止右溢出
- const sys = uni.getSystemInfoSync();
- if (left + 200 > sys.windowWidth) { // 假设菜单宽 200
- left = sys.windowWidth - 220;
- }
- style.left = left + 'px';
-
- return style;
- }
- // 原有的相对定位逻辑(保留以兼容 vue 页面或非全局模式)
- let style = {
- left: this.getLeft,
- right: this.getRight
- };
- if (this.is_bottom) {
- style.top = '100%';
- style.marginTop = '10px';
- } else {
- style.bottom = '100%';
- style.marginBottom = '12px';
- }
- return style;
- },
- canRevoke() {
- const interval = this.message.sendTime < Date.now() - 5 * 60 * 1000;
- if (interval) {
- return false;
- }
- if (this.message.sessionType !== SessionType.Single && this.storeCurrentMemberInGroup.roleLevel !== GroupMemberRole.Nomal) {
- return true;
- }
- return this.isSender;
- },
- isGroupAnnouncement() {
- return this.message.contentType === MessageType.GroupAnnouncementUpdated;
- },
- menuList() {
- console.log("qxj MessageMenu menuList compute start");
- console.log("qxj message:", this.message);
- console.log("qxj contentType:", this.message.contentType);
- console.log("qxj canCopyTypes:", canCopyTypes);
- // 公共基础菜单(非医生也能看到的项)
- const baseMenus = [
- {
- idx: 0,
- type: MessageMenuTypes.Copy,
- title: "复制",
- icon: copy,
- visible: canCopyTypes.includes(this.message.contentType),
- },
- { idx: 1,
- type: MessageMenuTypes.Del,
- title: "删除",
- icon: del,
- visible: true ,
- },
-
- {
- idx: 3,
- type: MessageMenuTypes.Reply,
- title: "回复",
- icon: reply,
- visible: !this.isGroupAnnouncement
- },
- {
- idx: 4,
- type: MessageMenuTypes.Revoke,
- title: "撤回",
- icon: revoke,
- visible: this.canRevoke && !this.isGroupAnnouncement
- }
- ];
- const menus1 = [
- {
- idx: 2,
- type: MessageMenuTypes.Forward,
- title: "转发",
- icon: forward,
- visible: !this.isGroupAnnouncement && this.message.contentType==MessageType.VoiceMessage
- },
- {
- idx: 5,
- type: MessageMenuTypes.Multiple,
- title: "多选",
- icon: multiple,
- visible: !this.isGroupAnnouncement && this.message.contentType==MessageType.VoiceMessage
- }
- ];
- let tempMenuArrs=this.isDoctorAction(this.storeCurrentConversation.userID) ? baseMenus: [...baseMenus, ...menus1];
- let menuList=[];
- tempMenuArrs.forEach((item) => {
- if(item.visible){
- menuList.push(item);
- }
- });
-
- return menuList;
- }
- },
- mounted() {
- this.contentType = this.message.contentType;
-
- },
- methods: {
- ...mapActions('message', ['deleteMessages', 'updateOneMessage', 'updateQuoteMessageRevoke']),
- ...mapActions('conversation', ['addRevokedMessage']),
-
- async menuClick({ type }) {
- switch (type) {
- case MessageMenuTypes.Copy:
- uni.setClipboardData({
- data: this.getCopyText(),
- success: () => {
- uni.hideToast();
- this.$nextTick(() => {
- uni.$u.toast('复制成功');
- });
- }
- });
- break;
- case MessageMenuTypes.Del:
- try {
- await IMSDK.asyncApi(IMSDK.IMMethods.DeleteMessage, IMSDK.uuid(), {
- conversationID: this.$store.getters.storeCurrentConversation.conversationID,
- clientMsgID: this.message.clientMsgID
- });
- this.deleteMessages([this.message]);
- uni.$u.toast('删除成功');
- } catch (error) {
- try {
- await IMSDK.asyncApi(IMSDK.IMMethods.DeleteMessageFromLocalStorage, IMSDK.uuid(), {
- conversationID: this.$store.getters.storeCurrentConversation.conversationID,
- clientMsgID: this.message.clientMsgID
- });
- this.deleteMessages([this.message]);
- uni.$u.toast('删除成功');
- } catch (error) {
- uni.$u.toast('删除失败');
- }
- }
- break;
- case MessageMenuTypes.Forward:
- this.$emit('enterSubPage');
- uni.navigateTo({
- url: `/pages_im/pages/common/contactChoose/index?type=${ContactChooseTypes.ForWard}&forwardMessage=${encodeURIComponent(JSON.stringify(this.message))}`
- });
- break;
- case MessageMenuTypes.Multiple:
- uni.$emit(PageEvents.MutipleCheckUpdate, {
- flag: true,
- message: this.message
- });
- break;
- case MessageMenuTypes.Reply:
- this.$store.commit('message/SET_QUOTE_MESSAGE', this.message);
- break;
- case MessageMenuTypes.Revoke:
- const _IMSDK = getIMSDK();
- _IMSDK.asyncApi(_IMSDK.IMMethods.RevokeMessage, _IMSDK.uuid(), {
- conversationID: this.$store.getters.storeCurrentConversation.conversationID,
- clientMsgID: this.message.clientMsgID
- })
- .then(() => {
- if (canCopyTypes.includes(this.contentType) && this.message.sendID === this.storeCurrentUserID) {
- this.addRevokedMessage(this.message);
- }
- this.updateOneMessage({
- message: {
- ...this.message,
- contentType: MessageType.RevokeMessage,
- notificationElem: {
- detail: JSON.stringify({
- clientMsgID: this.message.clientMsgID,
- revokeTime: Date.now(),
- revokerID: this.storeCurrentUserID,
- revokerNickname: '你',
- revokerRole: 0,
- seq: this.message.seq,
- sessionType: this.message.sessionType,
- sourceMessageSendID: this.message.sendID,
- sourceMessageSendTime: this.message.sendTime,
- sourceMessageSenderNickname: this.message.senderNickname
- })
- }
- }
- });
- this.updateQuoteMessageRevoke({
- clientMsgID: this.message.clientMsgID
- });
- })
- .catch(() => uni.$u.toast('撤回失败'));
- break;
- default:
- break;
- }
- this.$emit('close');
- },
- getMenuList(){
- // 公共基础菜单(非医生也能看到的项)
- let baseMenus = [
- {
- idx: 0,
- type: MessageMenuTypes.Copy,
- title: "复制",
- icon: copy,
- visible: canCopyTypes.includes(this.message.contentType),
- },
- { idx: 1,
- type: MessageMenuTypes.Del,
- title: "删除",
- icon: del,
- visible: true ,
- },
- {
- idx: 3,
- type: MessageMenuTypes.Reply,
- title: "回复",
- icon: reply,
- visible: true
- },
- {
- idx: 4,
- type: MessageMenuTypes.Revoke,
- title: "撤回",
- icon: revoke,
- visible: this.canRevoke && !this.isGroupAnnouncement
- }
- ];
- let menus1 = [
- {
- idx: 2,
- type: MessageMenuTypes.Forward,
- title: "转发",
- icon: forward,
- visible: !this.isGroupAnnouncement && this.message.contentType==MessageType.VoiceMessage
- },
- {
- idx: 5,
- type: MessageMenuTypes.Multiple,
- title: "多选",
- icon: multiple,
- visible: !this.isGroupAnnouncement && this.message.contentType==MessageType.VoiceMessage
- }
- ];
- let tempMenuArrs=isDoctorAction(this.storeCurrentConversation.userID) ? baseMenus: [...baseMenus, ...menus1];
- let menuList=[];
- for(let i=0;i<tempMenuArrs.length;i++){
- let item=tempMenuArrs[i];
- if(item.visible){
- menuList.push(item);
- }
- }
- console.log("qxj menuList:");
- console.log(menuList);
- return menuList;
- },
- getCopyText() {
- if (this.isGroupAnnouncement) {
- let detail = {};
- try {
- detail = JSON.parse(this.message.notificationElem.detail);
- } catch (e) {}
- return detail.group?.notification ?? '';
- }
- if (this.message.contentType === MessageType.AtTextMessage) {
- return parseAt(this.message.atTextElem, true);
- }
- if (this.message.contentType === MessageType.QuoteMessage) {
- return this.message.quoteElem.text;
- }
- return this.message.textElem.content;
- },
- isDoctorAction(userId){
- let isDoctorAct=false;
- if(userId!=undefined && (userId!="" || userId.length>0)){
- if(userId.indexOf('D')!==-1){
- isDoctorAct=true;
- }
- if(userId.indexOf('C')!==-1){
-
- }
- }
- return isDoctorAct;
- }
- }
- };
- </script>
- <style scoped lang="scss">
- .message_menu_container {
- display: flex;
- flex-direction: row;
- background-color: #5b5b5b;
- padding: 8rpx 0;
- border-radius: 16rpx;
- position: fixed;
- /* z-index: 999; */
- }
- .message_menu_container_bottom {
- /* top: unset; */
- /* bottom: 0; */
- }
- .message_menu_item {
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- font-size: 12px;
- color: #fff;
- padding: 16rpx 24rpx;
- }
- .message_menu_icon {
- width: 17px;
- height: 19px;
- margin-bottom: 4px;
- }
- .message_menu_text {
- /* min-width: max-content; nvue not support */
- color: #fff;
- font-size: 12px;
- lines: 1;
- }
- </style>
|