添加聊天

This commit is contained in:
bobobobo
2025-12-30 23:28:59 +08:00
parent d0cf491201
commit 2294b3b76e
450 changed files with 37066 additions and 96 deletions

View File

@@ -0,0 +1,135 @@
import imageIconLight from '../../../../assets/icon/image-light.svg';
import imageIconDark from '../../../../assets/icon/image-dark.svg';
import imageUniIcon from '../../../../assets/icon/image-uni.png';
import cameraUniIcon from '../../../../assets/icon/camera-uni.png';
import videoIconLight from '../../../../assets/icon/video-light.svg';
import videoIconDark from '../../../../assets/icon/video-dark.svg';
import videoUniIcon from '../../../../assets/icon/video-uni.png';
import fileIconLight from '../../../../assets/icon/file-light.svg';
import fileIconDark from '../../../../assets/icon/file-dark.svg';
export const ICON_SIZE_CONFIG = {
WEB: {
WIDTH: '20px',
HEIGHT: '18px',
},
UNI: {
WIDTH: '32px',
HEIGHT: '25px',
},
};
export const TOOLBAR_ICON_MAP = {
IMAGE_WEB_LIGHT: imageIconLight,
IMAGE_WEB_DARK: imageIconDark,
IMAGE_UNI: imageUniIcon,
CAMERA_UNI: cameraUniIcon,
VIDEO_WEB_LIGHT: videoIconLight,
VIDEO_WEB_DARK: videoIconDark,
VIDEO_UNI: videoUniIcon,
FILE_WEB_LIGHT: fileIconLight,
FILE_WEB_DARK: fileIconDark,
};
export enum UploadType {
IMAGE = 'IMAGE',
VIDEO = 'VIDEO',
FILE = 'FILE',
ALBUM = 'ALBUM',
CAMERA = 'CAMERA',
}
export enum SourceType {
ALBUM = 'album',
CAMERA = 'camera',
}
export enum PlatformType {
WEB = 'WEB',
UNI = 'UNI',
}
export enum ThemeType {
LIGHT = 'light',
DARK = 'dark',
}
export enum MediaType {
IMAGE = 'image',
VIDEO = 'video',
FILE = 'file',
}
export enum ToolbarTitle {
IMAGE = '图片',
PHOTO = '照片',
VIDEO = '视频',
FILE = '文件',
CAMERA = '拍照',
RECORD = '录制',
SHOOT = '拍摄',
}
export const TOOLBAR_DISPLAY_CONFIG = {
[UploadType.IMAGE]: {
[PlatformType.WEB]: {
title: ToolbarTitle.IMAGE,
getIcon: (theme: string) => theme === ThemeType.DARK ? TOOLBAR_ICON_MAP.IMAGE_WEB_DARK : TOOLBAR_ICON_MAP.IMAGE_WEB_LIGHT,
},
[PlatformType.UNI]: {
title: ToolbarTitle.PHOTO,
icon: TOOLBAR_ICON_MAP.IMAGE_UNI,
},
},
[UploadType.VIDEO]: {
[PlatformType.WEB]: {
title: ToolbarTitle.VIDEO,
getIcon: (theme: string) => theme === ThemeType.DARK ? TOOLBAR_ICON_MAP.VIDEO_WEB_DARK : TOOLBAR_ICON_MAP.VIDEO_WEB_LIGHT,
},
[PlatformType.UNI]: {
title: ToolbarTitle.VIDEO,
icon: TOOLBAR_ICON_MAP.VIDEO_UNI,
},
},
[UploadType.FILE]: {
[PlatformType.WEB]: {
title: ToolbarTitle.FILE,
getIcon: (theme: string) => theme === ThemeType.DARK ? TOOLBAR_ICON_MAP.FILE_WEB_DARK : TOOLBAR_ICON_MAP.FILE_WEB_LIGHT,
},
},
[UploadType.ALBUM]: {
[PlatformType.UNI]: {
title: ToolbarTitle.PHOTO,
icon: TOOLBAR_ICON_MAP.IMAGE_UNI,
},
},
[UploadType.CAMERA]: {
[PlatformType.UNI]: {
title: ToolbarTitle.SHOOT,
icon: TOOLBAR_ICON_MAP.CAMERA_UNI,
},
},
} as const;
export const MEDIA_CHOOSE_CONFIG = {
IMAGE: {
COUNT: 1,
MEDIA_TYPE: [MediaType.IMAGE],
SIZE_TYPE: ['original', 'compressed'],
},
VIDEO: {
COUNT: 1,
MEDIA_TYPE: [MediaType.VIDEO],
MAX_DURATION: 60,
COMPRESSED: false,
},
MIXED: {
COUNT: 1,
MEDIA_TYPE: [MediaType.IMAGE, MediaType.VIDEO],
SIZE_TYPE: ['original', 'compressed'],
},
};

View File

@@ -0,0 +1,11 @@
export { useUpload, genSourceType } from './useUpload';
export {
UploadType,
SourceType,
PlatformType,
ThemeType,
MediaType,
ToolbarTitle,
} from './constants';
export * from './constants';
export * from './utils';

View File

@@ -0,0 +1,183 @@
import { ref, computed } from '../../../../adapter-vue';
import { TUIStore, StoreName, IConversationModel } from '@tencentcloud/chat-uikit-engine-lite';
import { TUIGlobal } from '@tencentcloud/universal-api';
import { isPC, isUniFrameWork } from '../../../../utils/env';
import TUIChatConfig from '../../config';
import {
TOOLBAR_DISPLAY_CONFIG,
ICON_SIZE_CONFIG,
MEDIA_CHOOSE_CONFIG,
UploadType,
SourceType,
PlatformType,
} from './constants';
import {
sendImageMessage,
sendVideoMessage,
sendFileMessage,
handleWebFileSelect,
} from './utils';
export function genSourceType(uploadType: UploadType): SourceType {
if (uploadType === UploadType.CAMERA) {
return SourceType.CAMERA;
}
return SourceType.ALBUM;
}
export function useUpload(uploadType: UploadType) {
const inputRef = ref();
const currentConversation = ref<IConversationModel>();
const theme = TUIChatConfig.getTheme();
TUIStore.watch(StoreName.CONV, {
currentConversation: (conversation: IConversationModel) => {
currentConversation.value = conversation;
},
});
const sourceType = genSourceType(uploadType);
const toolbarConfig = computed(() => {
const config = TOOLBAR_DISPLAY_CONFIG[uploadType];
if (isUniFrameWork) {
const displayConfig = (config as any)[PlatformType.UNI];
return {
icon: displayConfig.icon,
title: displayConfig.title,
iconWidth: ICON_SIZE_CONFIG.UNI.WIDTH,
iconHeight: ICON_SIZE_CONFIG.UNI.HEIGHT,
};
} else {
const displayConfig = (config as any)[PlatformType.WEB];
return {
icon: displayConfig.getIcon ? displayConfig.getIcon(theme) : displayConfig.icon,
title: displayConfig.title,
iconWidth: ICON_SIZE_CONFIG.WEB.WIDTH,
iconHeight: ICON_SIZE_CONFIG.WEB.HEIGHT,
};
}
});
const handleIconClick = () => {
if (isUniFrameWork) {
handleUniAppClick();
} else {
handleWebClick();
}
};
const handleUniAppClick = () => {
switch (uploadType) {
case UploadType.IMAGE:
chooseImageInUniApp();
break;
case UploadType.VIDEO:
chooseVideoInUniApp();
break;
case UploadType.ALBUM:
chooseMediaInUniApp();
break;
case UploadType.CAMERA:
chooseCameraInUniApp();
break;
default:
break;
}
};
const handleWebClick = () => {
if (inputRef.value?.click) {
inputRef.value.click();
}
};
const chooseImageInUniApp = () => {
TUIGlobal?.chooseImage({
count: MEDIA_CHOOSE_CONFIG.IMAGE.COUNT,
sourceType: [sourceType],
success: function (res: Record<string, any>) {
if (currentConversation.value) {
sendImageMessage(currentConversation.value, res);
}
},
});
};
const chooseVideoInUniApp = () => {
TUIGlobal?.chooseVideo({
count: MEDIA_CHOOSE_CONFIG.VIDEO.COUNT,
sourceType: [sourceType],
compressed: MEDIA_CHOOSE_CONFIG.VIDEO.COMPRESSED,
success: function (res: Record<string, any>) {
if (currentConversation.value) {
sendVideoMessage(currentConversation.value, res);
}
},
});
};
const chooseMediaInUniApp = () => {
TUIGlobal?.chooseImage({
count: MEDIA_CHOOSE_CONFIG.IMAGE.COUNT,
sourceType: [SourceType.ALBUM, SourceType.CAMERA],
success: function (res: Record<string, any>) {
if (currentConversation.value) {
sendImageMessage(currentConversation.value, res);
}
},
});
};
const chooseCameraInUniApp = () => {
TUIGlobal?.chooseVideo({
count: MEDIA_CHOOSE_CONFIG.VIDEO.COUNT,
sourceType: [SourceType.ALBUM, SourceType.CAMERA],
compressed: MEDIA_CHOOSE_CONFIG.VIDEO.COMPRESSED,
success: function (res: Record<string, any>) {
if (currentConversation.value) {
sendVideoMessage(currentConversation.value, res);
}
},
});
};
const handleWebFileChange = (event: Event) => {
switch (uploadType) {
case UploadType.IMAGE:
handleWebFileSelect(event, (file) => {
if (currentConversation.value) {
sendImageMessage(currentConversation.value, file);
}
});
break;
case UploadType.VIDEO:
handleWebFileSelect(event, (file) => {
if (currentConversation.value) {
sendVideoMessage(currentConversation.value, file);
}
});
break;
case UploadType.FILE:
handleWebFileSelect(event, (file) => {
if (currentConversation.value) {
sendFileMessage(currentConversation.value, file);
}
});
break;
}
};
return {
inputRef,
currentConversation,
toolbarConfig,
isPC,
isUniFrameWork,
handleIconClick,
handleWebFileChange,
};
}

View File

@@ -0,0 +1,116 @@
import TUIChatEngine, {
TUIChatService,
IConversationModel,
SendMessageParams,
SendMessageOptions,
} from '@tencentcloud/chat-uikit-engine-lite';
import { isEnabledMessageReadReceiptGlobal } from '../../utils/utils';
import OfflinePushInfoManager, { IOfflinePushInfoCreateParams } from '../../offlinePushInfoManager/index';
export function createSendMessageOptions(
currentConversation: IConversationModel | undefined,
file: any,
): SendMessageParams {
return {
to:
currentConversation?.groupProfile?.groupID
|| currentConversation?.userProfile?.userID,
conversationType: currentConversation?.type,
payload: {
file,
},
needReadReceipt: isEnabledMessageReadReceiptGlobal(),
} as SendMessageParams;
}
export function genOfflinePushInfo(
currentConversation: IConversationModel,
payload: any,
messageType: any,
): SendMessageOptions {
const offlinePushInfoCreateParams: IOfflinePushInfoCreateParams = {
conversation: currentConversation,
payload,
messageType,
};
return {
offlinePushInfo: OfflinePushInfoManager.create(offlinePushInfoCreateParams),
};
}
export function sendImageMessage(
currentConversation: IConversationModel,
files: any,
): void {
if (!files) {
return;
}
const options = createSendMessageOptions(currentConversation, files);
const sendMessageOptions = genOfflinePushInfo(
currentConversation,
options.payload,
TUIChatEngine.TYPES.MSG_IMAGE,
);
TUIChatService.sendImageMessage(options, sendMessageOptions);
}
export function sendVideoMessage(
currentConversation: IConversationModel,
file: any,
): void {
if (!file) {
return;
}
const options = createSendMessageOptions(currentConversation, file);
const sendMessageOptions = genOfflinePushInfo(
currentConversation,
options.payload,
TUIChatEngine.TYPES.MSG_VIDEO,
);
TUIChatService.sendVideoMessage(options, sendMessageOptions);
}
export function sendFileMessage(
currentConversation: IConversationModel,
file: any,
): void {
if (!file) {
return;
}
const options = createSendMessageOptions(currentConversation, file);
const sendMessageOptions = genOfflinePushInfo(
currentConversation,
options.payload,
TUIChatEngine.TYPES.MSG_FILE,
);
TUIChatService.sendFileMessage(options, sendMessageOptions);
}
export function handleWebFileSelect(
event: any,
sendCallback: (file: any) => void,
): void {
if (event?.target?.files?.length <= 0) {
return;
}
sendCallback(event.target);
event.target.value = '';
}
export function isValidFile(file: any): boolean {
return !!file;
}
export function clearFileInput(inputRef: any): void {
if (inputRef.value) {
inputRef.value.value = '';
}
}