chore: initialize qiming workspace repository

This commit is contained in:
Codex
2026-05-29 14:22:48 +08:00
commit bfd67a0f2c
10750 changed files with 1885711 additions and 0 deletions

View File

@@ -0,0 +1,203 @@
import { ref, onMounted, onUnmounted, Ref } from 'vue'
import { EventBindResponseActionEnum } from '@/types/enums/agent'
import { checkPathParams, fillPathParams, objectToQueryString } from '@/utils/common.uts'
import { EventBindConfig, ShowPagePreviewOptions } from '@/types/interfaces/agent'
import { API_BASE_URL } from '@/constants/config'
import { handleExternalLink } from '@/utils/system.uts'
import { t } from '@/utils/i18n'
// ============ 工具方法 ============
const showError = (msg: string): void => {
uni.showToast({
title: msg,
icon: 'none'
})
}
// ============ 防重复触发管理器 ============
/**
* 事件防重复触发管理器
* 用于防止短时间内重复触发相同的事件
*/
export class EventDedupManager {
private handledEvents: Set<string> = new Set()
private timeout: number = 1000
constructor(timeout?: number) {
if (timeout !== undefined) {
this.timeout = timeout
}
}
/**
* 检查事件是否已经被处理
* @param eventKey 事件键
* @returns 是否已处理true 表示已处理,应该跳过)
*/
isDuplicate(eventKey: string): boolean {
if (this.handledEvents.has(eventKey)) {
return true
}
this.handledEvents.add(eventKey)
setTimeout(() => {
this.handledEvents.delete(eventKey)
}, this.timeout)
return false
}
/**
* 清除所有记录
*/
clear(): void {
this.handledEvents.clear()
}
}
// ============ 导出的事件处理函数 ============
/**
* 处理消息事件点击
* 可以在任何地方独立调用此函数来处理事件
*
* @param eventType 事件类型标识
* @param dataStr 事件数据JSON 字符串)
* @param eventBindConfig 事件绑定配置
* @param showPagePreview 页面预览回调函数
* @param dedupManager 防重复触发管理器(可选)
*/
export const handleMessageEventClick = (
eventType: string,
dataStr: string,
eventBindConfig: EventBindConfig | undefined,
showPagePreview?: (opts: ShowPagePreviewOptions) => void,
dedupManager?: EventDedupManager
): void => {
const eventKey = `${eventType}-${dataStr}`
// 防重复触发
if (dedupManager && dedupManager.isDuplicate(eventKey)) {
return
}
// 解析数据
let parsedData: Record<string, any> = {}
try {
parsedData = JSON.parse(dataStr)
} catch (err) {
console.error('[Event Handler] 数据解析失败:', err)
return
}
// 查找事件配置
const eventConfig = eventBindConfig?.eventConfigs?.find(
(cfg) => cfg.identification === eventType
)
if (!eventConfig) {
console.warn(`[Event Handler] 未找到事件配置: ${eventType}`)
return
}
// === 根据类型执行 ===
switch (eventConfig.type) {
case EventBindResponseActionEnum.Page: {
if (!eventConfig.pageUrl) {
showError(t("Mobile.ButtonWrapper.pagePathConfigError"))
return
}
const pathParams: Record<string, any> = {}
const params: Record<string, any> = {}
eventConfig.args?.forEach((arg) => {
if (arg.inputType === 'Path' && arg.name)
pathParams[arg.name] = parsedData[arg.name] ?? arg.bindValue
if (arg.inputType === 'Query' && arg.name)
params[arg.name] = parsedData[arg.name] ?? arg.bindValue
})
if (checkPathParams(eventConfig.pageUrl, pathParams)) {
const pageUrl = fillPathParams(eventConfig.pageUrl, pathParams)
const fullUri = eventConfig.basePath? `${eventConfig.basePath}${pageUrl}`: pageUrl
// 构建查询字符串
const queryString = objectToQueryString(params)
showPagePreview?.({
uri: queryString ? `${fullUri}?${queryString}` : fullUri,
})
} else {
showError(t("Mobile.ButtonWrapper.pagePathParamConfigError"))
}
break
}
case EventBindResponseActionEnum.Link: {
handleExternalLink(eventConfig.url)
break
}
default:
console.warn(`[Event Handler] 未知的事件类型: ${eventConfig.type}`)
}
}
// ============ 主 Hook ============
export const useMessageEventDelegate = (
containerRef: Ref<HTMLElement | null>,
eventBindConfig?: EventBindConfig,
showPagePreview?: (opts: ShowPagePreviewOptions) => void
) => {
// 创建防重复触发管理器
const dedupManager = new EventDedupManager(1000)
// 👉 点击事件处理(内部封装)
const handleEventClick = (eventType: string, dataStr: string): void => {
handleMessageEventClick(
eventType,
dataStr,
eventBindConfig.value,
showPagePreview,
dedupManager
)
}
// 👉 监听容器点击事件仅H5平台
// #ifdef H5 || WEB
const handleClick = (e: MouseEvent): void => {
const target = e.target as HTMLElement
const eventElement = target.closest('.event') as HTMLElement | null
if (eventElement) {
e.preventDefault()
e.stopPropagation()
const eventType = eventElement.getAttribute('event-type')
const dataStr = eventElement.getAttribute('data')
if (eventType && dataStr) {
handleEventClick(eventType, dataStr)
} else {
console.warn('[Event Delegate] 缺少必要属性', { eventType, dataStr })
}
}
}
// 👉 生命周期挂载与清理
onMounted(() => {
const container = containerRef.value
if (container) {
container.addEventListener('click', handleClick)
}
})
onUnmounted(() => {
const container = containerRef.value
if (container) {
container.removeEventListener('click', handleClick)
}
})
// #endif
}