| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 |
- <template>
- <div
- class="dialog-item"
- :class="env?.isH5 ? 'dialog-item-h5' : 'dialog-item-web'"
- >
- <MessageEmojiReact
- v-if="env?.isH5 && needEmojiReact"
- :message="message"
- type="dropdown"
- @handleCollapse="handleCollapse"
- />
- <ul
- class="dialog-item-list"
- :class="env?.isH5 ? 'dialog-item-list-h5' : 'dialog-item-list-web'"
- v-show="showToolList"
- >
- <li
- v-if="
- (message.type === types.MSG_FILE ||
- message.type === types.MSG_VIDEO ||
- message.type === types.MSG_IMAGE) &&
- !env.isH5
- "
- @click="openMessage(message)"
- >
- <i class="icon icon-msg-copy"></i>
- <span>{{ $t('TUIChat.打开') }}</span>
- </li>
- <li
- v-if="message.type === types.MSG_TEXT"
- @click="handleMessage(message, constant.handleMessage.copy)"
- >
- <i class="icon icon-msg-copy"></i>
- <span>{{ $t('TUIChat.复制') }}</span>
- </li>
- <li
- v-if="message.status === 'success'"
- @click="handleMessage(message, constant.handleMessage.forward)"
- >
- <i class="icon icon-msg-forward"></i>
- <span>{{ $t('TUIChat.转发') }}</span>
- </li>
- <li
- v-if="message.status === 'success'"
- @click="handleMessage(message, constant.handleMessage.reference)"
- >
- <i class="icon icon-msg-quote"></i>
- <span>{{ $t('TUIChat.引用') }}</span>
- </li>
- <li
- v-if="message.status === 'success'"
- @click="handleMessage(message, constant.handleMessage.reply)"
- >
- <i class="icon icon-msg-reply"></i>
- <span>{{ $t('TUIChat.回复') }}</span>
- </li>
- <li
- v-if="
- message.flow === 'out' &&
- message.status === 'success' &&
- message.type !== types.MSG_CUSTOM
- "
- @click="handleMessage(message, constant.handleMessage.revoke)"
- >
- <i class="icon icon-msg-revoke"></i>
- <span>{{ $t('TUIChat.撤回') }}</span>
- </li>
- <li
- v-if="message.status === 'success'"
- @click="handleMessage(message, constant.handleMessage.delete)"
- >
- <i class="icon icon-msg-del"></i>
- <span>{{ $t('TUIChat.删除') }}</span>
- </li>
- </ul>
- </div>
- </template>
- <script lang="ts">
- import {
- defineComponent,
- watch,
- reactive,
- toRefs,
- ref,
- watchEffect
- } from 'vue';
- import { Message } from '../interface';
- import TIM from '../../../../TUICore/tim';
- import { handleErrorPrompts } from '../../utils';
- import constant from '../../constant';
- import useClipboard from 'vue-clipboard3';
- import { useStore } from 'vuex';
- import MessageEmojiReact from './message-emoji-react.vue';
- export default defineComponent({
- props: {
- message: {
- type: Object,
- default: () => ({})
- },
- needEmojiReact: {
- type: Boolean,
- default: false
- }
- },
- components: {
- MessageEmojiReact
- },
- setup(props: any, ctx: any) {
- const TUIServer = (window as any)?.TUIKitTUICore?.TUIServer?.TUIChat;
- const VuexStore =
- ((window as any)?.TUIKitTUICore?.isOfficial && useStore && useStore()) ||
- {};
- const data = reactive({
- message: {} as Message,
- show: false,
- types: TIM.TYPES,
- env: TUIServer.TUICore.TUIEnv,
- showToolList: true,
- needEmojiReact: false
- });
- watchEffect(() => {
- data.needEmojiReact = props.needEmojiReact;
- });
- watch(
- () => props.message,
- () => {
- data.message = props.message;
- },
- { deep: true, immediate: true }
- );
- const openMessage = (item: any) => {
- let url = '';
- switch (item.type) {
- case data.types.MSG_FILE:
- url = item.payload.fileUrl;
- break;
- case data.types.MSG_VIDEO:
- url = item.payload.remoteVideoUrl;
- break;
- case data.types.MSG_IMAGE:
- url = item.payload.imageInfoArray[0].url;
- break;
- }
- window.open(url, '_blank');
- };
- const handleMessage = async (message: Message, type: string) => {
- switch (type) {
- case constant.handleMessage.revoke:
- try {
- await TUIServer.revokeMessage(message);
- (window as any)?.TUIKitTUICore?.isOfficial &&
- VuexStore?.commit &&
- VuexStore?.commit('handleTask', 1);
- } catch (error) {
- handleErrorPrompts(error, data.env);
- }
- break;
- case constant.handleMessage.copy:
- try {
- if (
- message?.type === data.types.MSG_TEXT &&
- message?.payload?.text
- ) {
- const { toClipboard } = useClipboard();
- await toClipboard(message?.payload?.text);
- }
- } catch (error) {
- handleErrorPrompts(error, data.env);
- }
- break;
- case constant.handleMessage.delete:
- await TUIServer.deleteMessage([message]);
- break;
- case constant.handleMessage.forward:
- ctx.emit('handleMessage', message, constant.handleMessage.forward);
- break;
- case constant.handleMessage.reference:
- ctx.emit('handleMessage', message, constant.handleMessage.reference);
- break;
- case constant.handleMessage.reply:
- ctx.emit('handleMessage', message, constant.handleMessage.reply);
- break;
- }
- };
- const handleCollapse = (isCollapse: boolean) => {
- if (!data?.env?.isH5) return;
- data.showToolList = isCollapse;
- };
- return {
- ...toRefs(data),
- openMessage,
- handleMessage,
- constant,
- handleCollapse
- };
- }
- });
- </script>
- <style lang="scss" scoped>
- @import url('../../../styles/common.scss');
- @import url('../../../styles/icon.scss');
- .dialog-item {
- background: #ffffff;
- min-width: min-content;
- max-width: 220Px;
- width: 72Px;
- height: fit-content;
- word-break: keep-all;
- top: 30Px;
- border-radius: 8Px;
- display: flex;
- flex-wrap: wrap;
- align-items: baseline;
- white-space: nowrap;
- border: 1Px solid #e0e0e0;
- &-web {
- padding: 12Px 0;
- }
- &-list {
- display: flex;
- flex-wrap: wrap;
- align-items: baseline;
- white-space: nowrap;
- justify-content: space-around;
- width: 100%;
- &-h5 {
- flex-wrap: nowrap;
- margin: 10Px;
- li {
- padding: 0 5Px;
- display: flex;
- flex-direction: column;
- align-items: center;
- font-size: 8Px;
- color: #4f4f4f;
- }
- }
- &-web {
- li:first-child {
- margin-top: 0;
- }
- li {
- padding: 4Px 12Px;
- font-size: 12Px;
- line-height: 17Px;
- display: flex;
- flex-direction: row;
- align-items: center;
- span {
- padding-left: 4Px;
- }
- }
- }
- }
- }
- </style>
|