| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296 | <template>  <view class="chat-box">    <!--  消息渲染  -->    <view class="message-item ss-flex-col scroll-item">      <view class="ss-flex ss-row-center ss-col-center">        <!-- 日期 -->        <view v-if="message.contentType !== KeFuMessageContentTypeEnum.SYSTEM && showTime(message, messageIndex)"              class="date-message">          {{ formatDate(message.createTime) }}        </view>        <!-- 系统消息 -->        <view v-if="message.contentType === KeFuMessageContentTypeEnum.SYSTEM" class="system-message">          {{ message.content }}        </view>      </view>      <!-- 消息体渲染管理员消息和用户消息并左右展示  -->      <view        v-if="message.contentType !== KeFuMessageContentTypeEnum.SYSTEM"        class="ss-flex ss-col-top"        :class="[              message.senderType === UserTypeEnum.ADMIN                ? `ss-row-left`                : message.senderType === UserTypeEnum.MEMBER                ? `ss-row-right`                : '',            ]"      >        <!-- 客服头像 -->        <image          v-show="message.senderType === UserTypeEnum.ADMIN"          class="chat-avatar ss-m-r-24"          :src="                sheep.$url.cdn(message.senderAvatar) ||                sheep.$url.static('/static/img/shop/chat/default.png')              "          mode="aspectFill"        ></image>        <!-- 内容 -->        <template v-if="message.contentType === KeFuMessageContentTypeEnum.TEXT">          <view class="message-box" :class="{'admin': message.senderType === UserTypeEnum.ADMIN}">            <mp-html :content="replaceEmoji(message.content)" />          </view>        </template>        <template v-if="message.contentType === KeFuMessageContentTypeEnum.IMAGE">          <view class="message-box" :class="{'admin': message.senderType === UserTypeEnum.ADMIN}"                :style="{ width: '200rpx' }">            <su-image              class="message-img"              isPreview              :previewList="[sheep.$url.cdn(message.content)]"              :current="0"              :src="sheep.$url.cdn(message.content)"              :height="200"              :width="200"              mode="aspectFill"            ></su-image>          </view>        </template>        <template v-if="message.contentType === KeFuMessageContentTypeEnum.PRODUCT">          <GoodsItem            :goodsData="getMessageContent(message)"            @tap="                    sheep.$router.go('/pages/goods/index', {                      id: getMessageContent(message).id,                    })                  "          />        </template>        <template v-if="message.contentType === KeFuMessageContentTypeEnum.ORDER">          <OrderItem            :orderData="getMessageContent(message)"            @tap="                  sheep.$router.go('/pages/order/detail', {                    id: getMessageContent(message).id,                  })                "          />        </template>        <!-- user头像 -->        <image          v-if="message.senderType === UserTypeEnum.MEMBER"          class="chat-avatar ss-m-l-24"          :src="sheep.$url.cdn(message.senderAvatar) ||                sheep.$url.static('/static/img/shop/chat/default.png')"          mode="aspectFill"        >        </image>      </view>    </view>  </view></template><script setup>  import { computed, unref } from 'vue';  import dayjs from 'dayjs';  import { KeFuMessageContentTypeEnum, UserTypeEnum } from '@/pages/chat/util/constants';  import { emojiList } from '@/pages/chat/util/emoji';  import sheep from '@/sheep';  import { formatDate } from '@/sheep/util';  import GoodsItem from '@/pages/chat/components/goods.vue';  import OrderItem from '@/pages/chat/components/order.vue';  const props = defineProps({    // 消息    message: {      type: Object,      default: ()=>({}),    },    // 消息索引    messageIndex: {      type: Number,      default: 0,    },    // 消息列表    messageList:{      type: Array,      default: () => [],    }  });  const getMessageContent = computed(() => (item) => JSON.parse(item.content)); // 解析消息内容  //======================= 工具 =======================  const showTime = computed(() => (item, index) => {    if (unref(props.messageList)[index + 1]) {      let dateString = dayjs(unref(props.messageList)[index + 1].createTime).fromNow();      return dateString !== dayjs(unref(item).createTime).fromNow();    }    return false;  });  // 处理表情  function replaceEmoji(data) {    let newData = data;    if (typeof newData !== 'object') {      let reg = /\[(.+?)]/g; // [] 中括号      let zhEmojiName = newData.match(reg);      if (zhEmojiName) {        zhEmojiName.forEach((item) => {          let emojiFile = selEmojiFile(item);          newData = newData.replace(            item,            `<img class="chat-img" style="width: 24px;height: 24px;margin: 0 3px;" src="${sheep.$url.cdn(              '/static/img/chat/emoji/' + emojiFile,            )}"/>`,          );        });      }    }    return newData;  }  function selEmojiFile(name) {    for (let index in emojiList) {      if (emojiList[index].name === name) {        return emojiList[index].file;      }    }    return false;  }</script><style scoped lang="scss">  .message-item {    margin-bottom: 33rpx;  }  .date-message,  .system-message {    width: fit-content;    border-radius: 12rpx;    padding: 8rpx 16rpx;    margin-bottom: 16rpx;    background-color: var(--ui-BG-3);    color: #999;    font-size: 24rpx;  }  .chat-avatar {    width: 70rpx;    height: 70rpx;    border-radius: 50%;  }  .send-status {    color: #333;    height: 80rpx;    margin-right: 8rpx;    display: flex;    align-items: center;    .loading {      width: 32rpx;      height: 32rpx;      -webkit-animation: rotating 2s linear infinite;      animation: rotating 2s linear infinite;      @-webkit-keyframes rotating {        0% {          transform: rotateZ(0);        }        100% {          transform: rotateZ(360deg);        }      }      @keyframes rotating {        0% {          transform: rotateZ(0);        }        100% {          transform: rotateZ(360deg);        }      }    }    .warning {      width: 32rpx;      height: 32rpx;      color: #ff3000;    }  }  .message-box {    max-width: 50%;    font-size: 16px;    line-height: 20px;    white-space: normal;    word-break: break-all;    word-wrap: break-word;    padding: 20rpx;    border-radius: 10rpx;    color: #fff;    background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));    &.admin {      background: #fff;      color: #333;    }    :deep() {      .imgred {        width: 100%;      }      .imgred,      img {        width: 100%;      }    }  }  :deep() {    .goods,    .order {      max-width: 500rpx;    }  }  .message-img {    width: 100px;    height: 100px;    border-radius: 6rpx;  }  .template-wrap {    // width: 100%;    padding: 20rpx 24rpx;    background: #fff;    border-radius: 10rpx;    .title {      font-size: 26rpx;      font-weight: 500;      color: #333;      margin-bottom: 29rpx;    }    .item {      font-size: 24rpx;      color: var(--ui-BG-Main);      margin-bottom: 16rpx;      &:last-of-type {        margin-bottom: 0;      }    }  }  .error-img {    width: 400rpx;    height: 400rpx;  }</style>
 |