UNPKG

chatarea

Version:

纯JS封装的聊天框,交互功能对标豆包、钉钉、微信聊天框,适用于JQuery/React/Vue等各大框架,兼容PC与H5的使用

436 lines (336 loc) 12.7 kB
/** * 详细使用配置请访问文档地址: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