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,350 @@
/**
* 统一的自定义操作服务
* 管理所有自定义元素的交互事件:打开预览、远程桌面、刷新文件树、打开页面等
*
* 设计参考 PC端: src/models/conversationInfo.ts
* - openPreviewView: 打开预览视图设置viewMode为'preview',显示文件树,刷新文件列表
* - openDesktopView: 打开远程桌面视图设置viewMode为'desktop',启动容器,启动保活
* - handleRefreshFileList: 刷新文件列表调用apiGetStaticFileList
*
* 详细接入文档请参考: integration_guide.md
*/
import { API_BASE_URL } from '@/constants/config'
/**
* 事件类型枚举对应PC端 EVENT_TYPE
*/
export enum CustomEventType {
/** 刷新文件列表 */
REFRESH_FILE_LIST = 'custom_action_refresh_file_list',
/** 打开预览视图 */
OPEN_PREVIEW = 'custom_action_open_preview',
/** 打开远程桌面 */
OPEN_DESKTOP = 'custom_action_open_desktop',
/** 打开扩展页面 */
OPEN_PAGE = 'custom_action_open_page',
/** 打开外部链接 */
OPEN_LINK = 'custom_action_open_link',
}
/**
* 视图模式枚举对应PC端 viewMode
*/
export enum ViewModeEnum {
/** 预览模式 */
PREVIEW = 'preview',
/** 远程桌面模式 */
DESKTOP = 'desktop',
}
/**
* 操作类型枚举
*/
export enum CustomActionType {
/** 打开预览视图(文件预览模式) */
OPEN_PREVIEW = 'OPEN_PREVIEW',
/** 打开远程桌面视图 */
OPEN_DESKTOP = 'OPEN_DESKTOP',
/** 刷新文件树 */
REFRESH_FILE_LIST = 'REFRESH_FILE_LIST',
/** 打开扩展页面iframe/webview */
OPEN_PAGE = 'OPEN_PAGE',
/** 打开外部链接 */
OPEN_LINK = 'OPEN_LINK',
}
/**
* 操作参数接口
*/
export interface CustomActionParams {
type: CustomActionType
conversationId?: string
uri?: string
params?: Record<string, any>
method?: string
dataType?: string
requestId?: string
}
/**
* 页面预览选项
*/
export interface OpenPageOptions {
uri: string
params?: Record<string, any>
method?: string
dataType?: string
requestId?: string
}
/**
* 打开预览事件数据对应PC端 openPreviewView 逻辑)
*/
export interface OpenPreviewEventData {
conversationId: string
viewMode: ViewModeEnum
}
/**
* 打开远程桌面事件数据对应PC端 openDesktopView 逻辑)
*/
export interface OpenDesktopEventData {
conversationId: string
viewMode: ViewModeEnum
}
/**
* 刷新文件列表事件数据对应PC端 handleRefreshFileList 逻辑)
*/
export interface RefreshFileListEventData {
conversationId: string
}
/**
* 打开页面事件数据
*/
export interface OpenPageEventData {
uri: string
method: string
dataType: string
requestId: string
}
/**
* 统一的自定义操作服务类
*
* 使用示例:
* - CustomActionService.openPreviewView(conversationId) // 打开预览视图
* - CustomActionService.openDesktopView(conversationId) // 打开远程桌面
* - CustomActionService.refreshFileList(conversationId) // 刷新文件树
* - CustomActionService.openPage({ uri: '/page/index', params: { id: 1 } }) // 打开扩展页面
* - CustomActionService.openLink('https://example.com') // 打开外部链接
*
* 事件监听示例:
* uni.$on(CustomEventType.OPEN_PREVIEW, (data: OpenPreviewEventData) => { ... })
* uni.$on(CustomEventType.REFRESH_FILE_LIST, (data: RefreshFileListEventData) => { ... })
*/
export class CustomActionService {
/**
* 打开预览视图
* 对应PC端 openPreviewView 方法
* 切换到文件预览模式并刷新文件列表
* @param conversationId 会话ID
*/
static openPreviewView(conversationId: string): void {
if (!conversationId) {
console.warn('[CustomActionService] openPreviewView: conversationId is required')
return
}
// 移除 chat- 前缀
const idStr = String(conversationId)
const cid = idStr.startsWith('chat-') ? idStr.replace('chat-', '') : idStr
// console.log('[CustomActionService] openPreviewView:', cid)
// 发送打开预览视图事件对应PC端 setViewMode('preview') + setIsFileTreeVisible(true)
const eventData: OpenPreviewEventData = {
conversationId: cid,
viewMode: ViewModeEnum.PREVIEW
}
// console.log('[CustomActionService] Action: OPEN_PREVIEW, Params:', { conversationId })
uni.$emit(CustomEventType.OPEN_PREVIEW, eventData)
// 触发文件列表刷新对应PC端 eventBus.emit(EVENT_TYPE.RefreshFileList, cId)
this.refreshFileList(conversationId)
}
/**
* 打开远程桌面视图
* 对应PC端 openDesktopView 方法
* 切换到远程桌面模式并启动VNC连接
* @param conversationId 会话ID
*/
static openDesktopView(conversationId: string): void {
if (!conversationId) {
console.warn('[CustomActionService] openDesktopView: conversationId is required')
return
}
// 移除 chat- 前缀
const idStr = String(conversationId)
const cid = idStr.startsWith('chat-') ? idStr.replace('chat-', '') : idStr
// console.log('[CustomActionService] openDesktopView:', cid)
// 发送打开远程桌面事件对应PC端 setViewMode('desktop') + setIsFileTreeVisible(true) + apiEnsurePod
const eventData: OpenDesktopEventData = {
conversationId: cid,
viewMode: ViewModeEnum.DESKTOP
}
// console.log('[CustomActionService] Action: OPEN_DESKTOP, Params:', { conversationId })
uni.$emit(CustomEventType.OPEN_DESKTOP, eventData)
}
/**
* 刷新文件树
* 对应PC端 handleRefreshFileList 方法
* 重新获取会话相关的文件列表
* @param conversationId 会话ID
*/
static refreshFileList(conversationId: string): void {
if (!conversationId) {
console.warn('[CustomActionService] refreshFileList: conversationId is required')
return
}
// 移除 chat- 前缀
const idStr = String(conversationId)
const cid = idStr.startsWith('chat-') ? idStr.replace('chat-', '') : idStr
// console.log('[CustomActionService] refreshFileList:', cid)
// 发送刷新文件列表事件对应PC端 runGetStaticFileList(targetId)
const eventData: RefreshFileListEventData = {
conversationId: cid
}
// console.log('[CustomActionService] Emitting REFRESH_FILE_LIST event:', eventData)
// uni.$emit(CustomEventType.REFRESH_FILE_LIST, eventData)
uni.$emit('refreshFileList', cid)
}
/**
* 打开扩展页面
* 在iframe或webview中打开指定页面
* @param options 页面选项
*/
static openPage(options: OpenPageOptions): void {
if (!options.uri) {
console.warn('[CustomActionService] openPage: uri is required')
return
}
// console.log('[CustomActionService] openPage:', options)
// 构建完整的URL
let fullUri = options.uri
if (options.params && Object.keys(options.params).length > 0) {
const queryString = Object.entries(options.params)
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)
.join('&')
fullUri = `${fullUri}${fullUri.includes('?') ? '&' : '?'}${queryString}`
}
// 发送打开页面事件
const eventData: OpenPageEventData = {
uri: fullUri,
method: options.method || 'browser_open_page',
dataType: options.dataType || 'html',
requestId: options.requestId || ''
}
// console.log('[CustomActionService] Action: OPEN_PAGE, Params:', { uri: fullUri, method: eventData.method })
uni.$emit(CustomEventType.OPEN_PAGE, eventData)
}
/**
* 打开外部链接
* 在新窗口或跳转页面打开链接
* @param uri 链接地址
* @param params 查询参数
*/
static openLink(uri: string, params?: Record<string, any>): void {
if (!uri) {
console.warn('[CustomActionService] openLink: uri is required')
return
}
// console.log('[CustomActionService] openLink:', uri, params)
// 构建完整的URL
let fullUri = uri
if (params && Object.keys(params).length > 0) {
const queryString = Object.entries(params)
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)
.join('&')
fullUri = `${fullUri}${fullUri.includes('?') ? '&' : '?'}${queryString}`
}
// #ifdef H5 || WEB
window.open(fullUri, '_blank')
// #endif
// #ifdef MP-WEIXIN
// 小程序环境下使用webview打开
uni.navigateTo({
url: `/subpackages/pages/common/webview/webview?url=${encodeURIComponent(fullUri)}`
})
// #endif
// 同时发送事件,允许页面自定义处理
// console.log('[CustomActionService] Action: OPEN_LINK, Params:', { uri: fullUri })
uni.$emit(CustomEventType.OPEN_LINK, { uri: fullUri })
}
/**
* 统一的动作分发器
* 根据动作类型调用相应的处理方法
* @param action 动作参数
*/
static dispatch(action: CustomActionParams): void {
if (!action || !action.type) {
console.warn('[CustomActionService] dispatch: action type is required')
return
}
// console.log('[CustomActionService] dispatch:', action.type, action)
switch (action.type) {
case CustomActionType.OPEN_PREVIEW:
if (action.conversationId) {
this.openPreviewView(action.conversationId)
}
break
case CustomActionType.OPEN_DESKTOP:
if (action.conversationId) {
this.openDesktopView(action.conversationId)
}
break
case CustomActionType.REFRESH_FILE_LIST:
if (action.conversationId) {
this.refreshFileList(action.conversationId)
}
break
case CustomActionType.OPEN_PAGE:
if (action.uri) {
this.openPage({
uri: action.uri,
params: action.params,
method: action.method,
dataType: action.dataType,
requestId: action.requestId
})
}
break
case CustomActionType.OPEN_LINK:
if (action.uri) {
this.openLink(action.uri, action.params)
}
break
default:
console.warn('[CustomActionService] dispatch: unknown action type:', action.type)
}
}
}
// 导出事件类型,方便外部监听
export { CustomEventType as EVENT_TYPE }
// 导出默认实例方法,方便使用
export const openPreviewView = CustomActionService.openPreviewView.bind(CustomActionService)
export const openDesktopView = CustomActionService.openDesktopView.bind(CustomActionService)
export const refreshFileList = CustomActionService.refreshFileList.bind(CustomActionService)
export const openPage = CustomActionService.openPage.bind(CustomActionService)
export const openLink = CustomActionService.openLink.bind(CustomActionService)
export const dispatchAction = CustomActionService.dispatch.bind(CustomActionService)