diff --git a/liics b/liics new file mode 160000 index 0000000..e9d7f5b --- /dev/null +++ b/liics @@ -0,0 +1 @@ +Subproject commit e9d7f5bf799bf2d3d3df068f35290eba414237ad diff --git a/src/components/chat-new.vue b/src/components/chat-new.vue index df0452c..ffedc39 100644 --- a/src/components/chat-new.vue +++ b/src/components/chat-new.vue @@ -2,11 +2,15 @@ import { ref, computed, inject, watch, nextTick, onMounted } from 'vue' import { showToast } from 'vant' import _ from 'lodash' +import { showImagePreview } from 'vant' +import xss from 'xss' import footerBarInput from '@/components/footer-bar-input.vue' import hotQuestionNew from '@/components/hot-question-new.vue' import welcomes from '@/components/welcomes.vue' import abstract from '@/components/abstract.vue' import chatContent from '@/components/chat-content.vue' +import DynamicImage from '@/components/common/DynamicImage.vue' +import imageService from '@/utils/imageService' import { messageSend } from '@/utils/api' import { Post } from '@/utils/https' import { SJHLCmdList } from '@/utils/constant' @@ -28,9 +32,85 @@ const pageNum = ref(1) const pageSize = ref(10) const nolist = ref(false) const nolistTxt = ref('没有更多数据了') +function getMessageOptions(item) { + return item?.message?.[0]?.options || {} +} + +function isImageMessage(item) { + const raw = item?.raw || item || {} + const options = getMessageOptions(item) + const reqAndResType = String(raw.reqAndResType || '') + const msgType = String(raw.msgType || '') + const fromFlag = String(raw.fromFlag || '') + const isProtocolImage = + (reqAndResType === '2' && fromFlag === '1' && msgType !== '01') || + (reqAndResType === '08' && msgType === '02') + const isTextAnswer = Boolean(raw.msgText) && (msgType === '01' || fromFlag !== '1') && !isProtocolImage + + return !isTextAnswer && ( + item?.message?.[0]?.type === 'image' || + isProtocolImage || + Boolean((item?.imageUrl || item?.imageKey || options.imageUrl || options.imageKey || raw.imgUrl || raw.imgKey || raw.fileKey) && !raw.msgText) + ) +} + +function getItemImage(item) { + const raw = item?.raw || item || {} + const options = getMessageOptions(item) + const reqAndResType = String(raw.reqAndResType || '') + const msgType = String(raw.msgType || '') + const fromFlag = String(raw.fromFlag || '') + const imageMessage = + (reqAndResType === '2' && fromFlag === '1' && msgType !== '01') || + (reqAndResType === '08' && msgType === '02') + const directImage = [item?.imageUrl, options.imageUrl, raw.imgUrl] + .map((value) => String(value || '')) + .find((value) => /^(data:|blob:|https?:\/\/)/i.test(value)) + + return String( + directImage || + item?.imageKey || + options.imageKey || + raw.imgKey || + raw.fileKey || + item?.imageUrl || + options.imageUrl || + raw.imgUrl || + (imageMessage ? raw.msgText : '') || + '', + ) +} function getItemText(item) { - return item?.message?.[0]?.options?.label || '' + if (isImageMessage(item)) return '' + return String(getMessageOptions(item).label || '').replace(/\\n/g, '\n') +} + +function isImageUploading(item) { + return isImageMessage(item) && item?.uploadStatus === 'uploading' +} + +function isImageFailed(item) { + return isImageMessage(item) && item?.uploadStatus === 'failed' +} + +function getItemHtml(item) { + const content = getItemText(item) + if (!content) return '' + + // liics renders msgText as sanitized HTML and converts escaped newlines to + // line breaks. Keep the same behavior for msgType=01 and rich msgType=02. + return xss(content.replace(/\\"/g, '"').replace(/\n/g, '
')) +} + +async function previewImage(item) { + if (isImageUploading(item) || isImageFailed(item)) return + + const imageKey = getItemImage(item) + if (!imageKey) return + + const imageUrl = await imageService.getImageByKey(imageKey) + if (typeof imageUrl === 'string' && imageUrl) showImagePreview([imageUrl]) } const showTyping = computed( @@ -208,6 +288,16 @@ onMounted(async () => { getHeaderUrl() getChatHistory() }) +watch( + chatArr, + () => { + nextTick(() => { + const container = mainContainerRef.value + if (container) container.scrollTop = container.scrollHeight + }) + }, + { deep: true }, +)