chatarea
Version:
纯JS封装的聊天框,交互功能对标豆包、钉钉、微信聊天框,适用于JQuery/React/Vue等各大框架,兼容PC与H5的使用
436 lines (336 loc) • 12.7 kB
TypeScript
/**
* 详细使用配置请访问文档地址:https://jianfv.top/ChatAreaDoc/
* */
export interface DeviceInfo {
isTablet: boolean;
isPhone: boolean;
isAndroid: boolean;
isIOS: boolean;
isPc: boolean;
isIPhone: boolean;
isIPad: boolean;
isWindows: boolean;
isMacOS: boolean;
isLinux: boolean;
isWechat: boolean;
isMobile: boolean;
}
export interface UserInfo {
id: string;
name: string;
avatar?: string | URL;
pinyin?: string;
}
export interface UserProps {
id?: string;
name?: string;
avatar?: string;
pinyin?: string;
}
export interface TagInfo {
id: string;
name: string;
pinyin?: string;
}
export interface SelectItem {
id: string;
name: string;
preview?: string | URL;
}
export interface UploadImage {
(file: File): Promise<string | URL>
}
export interface CustomTag {
dialogTitle: string;
prefix: string;
keyMap?: string[];
tagList: TagInfo[];
}
export interface SelectTag {
dialogTitle: string;
key: string;
options: SelectItem[];
}
export interface UpdateOption<T> {
userList?: T[];
placeholder?: string;
customTrigger?: CustomTag[];
selectList?: SelectTag[];
maxLength?: number;
copyType?: CopyType[];
uploadImage?: UploadImage;
needCallEvery?: boolean;
needCallSpace?: boolean;
userProps?: UserProps;
wrapKeyFun?: { (event: KeyboardEvent): boolean };
sendKeyFun?: { (event: KeyboardEvent): boolean };
}
export interface Options<T> extends UpdateOption<T> {
elm: HTMLElement;
device?: Device; // default auto
autoFocus?: boolean; // default true
needDialog?: boolean; // default true
needDebounce?: boolean; // default true
asyncMatch?: boolean; // default false
dialogLabels?: {
pcPointDialog?: PCPointDialogLabel;
pcPCheckDialog?: PCPCheckDialogLabel;
h5Dialog?: H5DialogLabel;
}
}
export interface PCPointDialogLabel {
title?: string;
callEveryLabel?: string;
checkLabel?: string;
emptyLabel?: string;
}
export interface PCPCheckDialogLabel {
title?: string;
searchPlaceholder?: string;
searchEmptyLabel?: string;
userTagTitle?: string;
checkAllLabel?: string;
checkEmptyLabel?: string;
confirmLabel?: string;
cancelLabel?: string;
}
export interface H5DialogLabel {
title?: string;
callEveryLabel?: string;
searchPlaceholder?: string;
searchEmptyLabel?: string;
confirmLabel?: string;
cancelLabel?: string;
}
export interface ReduceNodeConfig {
saveTagData?: boolean;
needUserId?: boolean;
needTagId?: boolean;
needSelectId?: boolean;
needTipKey?: boolean;
wrapClassName?: string;
rowClassName?: string;
imgToText?: boolean;
identifyLink?: boolean;
}
export interface TipOptions {
tagLabel?: string;
popoverLabel?: string;
codeLabel?: string;
}
export type ChatEventName =
'enterSend'
| 'operate'
| 'defaultAction'
| 'atMatch'
| 'atCheck'
| 'tagCheck'
| 'selectCheck'
| 'afterAtCheck'
| 'afterTagCheck'
| 'afterSelectCheck'
| 'showAtDialog'
| 'showTagDialog'
| 'showSelectDialog'
| 'elementClicked'
| 'tipTagState'
export type CopyType = 'text' | 'image'
export type Device = 'pc' | 'h5' | 'auto'
declare class ChatArea<T = UserInfo> {
static version: string; // 版本信息
readonly richText: HTMLElement; // 文本输入元素
readonly textLength: number; // 当设置配置项maxLength读取到的文本框字符长度
readonly deviceInfo: Readonly<DeviceInfo>; // 当前设备类型信息
readonly options: Readonly<Options<T>>; // 实例配置项
chatElement: Record<string, any>; // 私有实体类,内部方法不推荐直接使用故ts类型暂未提供定义
chatEvent: Record<string, any>; // 私有实体类,内部方法不推荐直接使用故tts类型暂未提供定义
chatInput: Record<string, any>; // 私有实体类,内部方法不推荐直接使用故tts类型暂未提供定义
constructor(options: Options<T>)
// 修改多个配置项
updateConfig(updateOption: UpdateOption<T>): void
// 修改人员列表
updateUserList(userList: T[]): void
// 搜索人员列表
searchUserList(value: string): T[]
// 获取精简后的文本框dom
getReduceNode(config?: ReduceNodeConfig): HTMLElement
// 获取发送文本
getText(config?: ReduceNodeConfig): string
// 获取发送的html内容
getHtml(config?: ReduceNodeConfig): string
// 逆向解析
reverseAnalysis(html: string, needConnect?: boolean): Promise<void>
// 光标处插入html代码
insertHtml(html: string): Promise<HTMLElement>
// 插入自定义文本
insertText(text: string): Promise<void>
// 获取@人员列表
getCallUserList(): T[]
// 获取@人员标签列表
getCallUserTagList(): T[]
// 获取自定义触发符元素已选择的数据列表
getCustomTagList(): Record<string, TagInfo[]>
// 获取标签选择元素已选择的数据列表
getSelectTagList(): Record<string, SelectTag[]>
// 获取输入元素的输入内容
getInputTagList(): Record<string, (string | null)[]>
// 置空输入框
clear(defaultText?: string): Promise<void>
// 在当前光标处进行换行操作
lineBreak(): void
// 文本框是否为空
isEmpty(unSpace: boolean): boolean
// 卸载元素,并释放实例
dispose(): void
// 在光标处插入传入的@人员
setUserTag(user: T): Promise<void>
// 在光标处插入自定义标签元素
setCustomTag(tag: TagInfo, prefix: string): Promise<void>
// 在光标出插入选择标签元素
setSelectTag(tag: SelectItem, key: string): Promise<void>
// 在光标处插入输入标签元素
setInputTag(key: string, placeholder: string, value?: string): Promise<void>
// 唤起PC人员光标选择弹窗
showPCPointDialog(): void
// 唤起PC人员多选弹窗
showPCCheckDialog(): void
// 唤起PC自定义触发符选择弹窗
showPCCustomTagDialog(prefix: string): void
// 唤起H5@人员弹窗
showH5Dialog(): void
// 唤起PC选择标签弹窗
showPCSelectDialog(key: string, elm?: HTMLElement): void
// 私有api-匹配光标选择弹窗内容插入@标签
matchSetTag(user: T): Promise<void>
// 私有api-单向插入
onceSetTag(user: T): Promise<void>
// 私有api-多项插入
batchSetTag(users: T[]): Promise<void>
// 私有api-单向插入自定义标签
onceSetCustomTag(tag: TagInfo): Promise<void>
// 私有api-匹配光标选择弹窗内容插入自定义标签
matchSetCustomTag(tag: TagInfo): Promise<void>
// 删除聊天框内的@人员标签
delUserTags(ids?: string[] | number[]): Promise<void>
// 删除聊天框内的自定义标签
delCustomTags(prefix: string, ids?: string[] | number[]): Promise<void>
// 删除聊天框内选择标签
delSelectTags(key: string, ids?: string[] | number): Promise<void>
// 删除聊天框内输入标签
delInputTags(keys?: string[]): Promise<void>
// 禁止聊天框编辑
disabled(): void
// 允许聊天框编辑
enable(): void
// 撤销
undo(): Promise<void>
// 恢复
redo(): Promise<void>
// 清空撤销重做栈
clearHistory(): void
// 光标移动
cursorMove(count: number)
// 光标删除
cursorDel(count: number): Promise<void>
// 将光标定位到最后一次记录的位置
cursorToLastRecord()
// 打开前置提示标签
openTipTag(options: TipOptions)
// 打开自定义前置标签元素
openCustomTipTag(html: string): HTMLElement
// 关闭前置提示标签
closeTipTag(): Promise<void>
// 修改PC光标选择弹窗默认文案
revisePCPointDialogLabel(config: PCPointDialogLabel): void
// 修改PC多选选择弹窗默认文案
revisePCCheckDialogLabel(config: PCPCheckDialogLabel): void
// 修改H5选择弹窗默认文案
reviseH5DialogLabel(config: H5DialogLabel): void
// 添加事件订阅
addEventListener(eventName: ChatEventName, callBack: Function): void
// 移除事件订阅
removeEventListener(eventName: ChatEventName, callBack: Function): void
// 创建OperateNode实例
createOperateNode(): ChatOperateNode
// 创建ChatComponent实例
createChatComponent(): ChatComponent
}
export type ChatNodeType = 'gridBox' | 'gridInput' | 'userTag' | 'customTag' | 'selectTag' | 'inputTag' | 'htmlTag'
export type DatasetByType = {
userTag: { id?: string, name?: string, [keyName: string]: string }; // 用户标签数据集
customTag: { id: string, name: string, prefix: string }; // 自定义标签数据集
selectTag: { id: string, name: string, key: string }; // 选择标签数据集
inputTag: { key: string, placeholder: string, value?: string }; // 输入标签数据集
gridBox: undefined; // 网格框数据集
gridInput: undefined; // 网格输入框数据集
htmlTag: undefined; // html标签数据集
}
export interface ChatNode<T extends ChatNodeType> {
type: T; // 节点类型
rank?: string; // rank码
text?: string; // 文本内容
html?: string; // html内容
dataset?: DatasetByType[ChatNodeType[T]]; // 数据集
children?: ChatNode<T>[]; // 子节点
}
export class ChatOperateNode {
target: ChatArea; // 聊天框实例
rankLen: number; // rank长度
// 获取当前聊天框内容的Node结构集合
getCurrentNodes(): ChatNode<ChatNodeType>[]
// 获取rank码
getRank(index: number): string
// 根据rank获取对应的Node
getNodeByRank(rank: string): ChatNode<ChatNodeType> | null
// 根据rank获取对应的DOM元素
getElmByRank(rank: string): HTMLElement | null
// 根据聊天框元素获取对应的rank值
getRankByElm(elm: HTMLElement): string
// 修改单个Node数据
updateNode(node: ChatNode<ChatNodeType>): Promise<void>
// 插入单个Node数据
insertNode(node: ChatNode<ChatNodeType>): Promise<void>
// 根据rank移除对应的Node
delNodeByRank(rank: string): Promise<void>
// 覆盖聊天框内的Node结构
coverNodes(nodes: ChatNode<ChatNodeType>[]): Promise<void>
// 将光标移动到当前Node
setCursorNode(node: ChatNode<ChatNodeType>, offset?: number)
// 选中目标节点
setSelectNodes(startNode: ChatNode<ChatNodeType>, endNode: ChatNode<ChatNodeType>, startOffset?: number, endOffset?: number)
// 获取当前光标所处Node
getCursorNode(): { node: ChatNode<ChatNodeType>, offset: number }
// 渲染更新下次执行方法
nextTick(callback: Function): Promise<void>
// 获取光标对象方法
getSelection(): Selection | null
}
export interface ChatComponentEvent {
componentElm: HTMLElement; // 组件元素
targetElm: HTMLElement; // 目标元素
data: TagComponent['props']; // 组件数据
eventType: string; // 事件类型
eventName: string; // 事件名称
stopPropagation: () => void; // 阻止事件冒泡
}
export interface TagComponent {
name: string; // 组件名称
props: Record<string, string>; // 组件属性
methods: Record<string, (chatEvent: ChatComponentEvent, protoEvent: Event) => void>; // 组件方法
template: string; // 组件模板
}
export class ChatComponent {
target: ChatArea; // 聊天框实例
components: Record<string, TagComponent> = {}; // 组件集合
// 注册组件
useComponent(component: TagComponent)
// 在聊天框光标区域插入组件
insertComponent(name: string, props: TagComponent['props']): Promise<HTMLElement | void>
// 删除目标组件已渲染的元素
removeComponentElm (htmlTag: HTMLElement): Promise<void>
// 更新目标组件已渲染的props内容
updateComponentElm (htmlTag: HTMLElement, props: TagComponent['props']): Promise<void>
// 获取目标组件已经在聊天框渲染的元素集合
getComponentElms (componentName: string): HTMLElement[]
}
export default ChatArea