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,262 @@
/**
* 权限处理工具类
* 用于处理H5端的各种权限请求和状态检测
*/
import { t } from "@/utils/i18n";
// 权限状态类型
export type PermissionState = 'granted' | 'denied' | 'prompt' | 'unknown'
// 权限类型
export type PermissionType = 'microphone' | 'camera' | 'geolocation' | 'notifications'
/**
* 权限管理器类
*/
export class PermissionManager {
private static instance: PermissionManager | null = null
private constructor() {}
/**
* 获取单例实例
*/
static getInstance(): PermissionManager {
if (!PermissionManager.instance) {
PermissionManager.instance = new PermissionManager()
}
return PermissionManager.instance
}
/**
* 检查权限状态
* @param permissionType 权限类型
* @returns 权限状态
*/
async checkPermission(permissionType: PermissionType): Promise<PermissionState> {
// #ifdef H5
try {
if (navigator.permissions && navigator.permissions.query) {
const permission = await navigator.permissions.query({ name: permissionType as PermissionName })
return permission.state
} else {
// 如果不支持 permissions API尝试获取权限来检测状态
return await this.checkPermissionByRequest(permissionType)
}
} catch (error) {
console.error(`检查${permissionType}权限失败:`, error)
return 'unknown'
}
// #endif
// #ifndef H5
return 'granted' // 非H5平台默认有权限
// #endif
}
/**
* 通过请求权限来检测权限状态
* @param permissionType 权限类型
* @returns 权限状态
*/
private async checkPermissionByRequest(permissionType: PermissionType): Promise<PermissionState> {
// #ifdef H5
try {
switch (permissionType) {
case 'microphone': // 麦克风
const stream = await navigator.mediaDevices.getUserMedia({ audio: true })
stream.getTracks().forEach(track => track.stop())
return 'granted' // 允许
case 'camera': // 摄像头
const videoStream = await navigator.mediaDevices.getUserMedia({ video: true })
videoStream.getTracks().forEach(track => track.stop())
return 'granted' // 允许
default: // 其他
return 'unknown' // 未知
}
} catch (error: any) {
if (error.name === 'NotAllowedError') {
return 'denied' // 拒绝
} else {
return 'prompt' // 提示
}
}
// #endif
// #ifndef H5
return 'granted'
// #endif
}
/**
* 请求权限
* @param permissionType 权限类型
* @returns 是否成功获取权限
*/
async requestPermission(permissionType: PermissionType): Promise<boolean> {
// #ifdef H5
try {
switch (permissionType) {
case 'microphone': // 麦克风
const stream = await navigator.mediaDevices.getUserMedia({ audio: true })
stream.getTracks().forEach(track => track.stop())
return true
case 'camera': // 摄像头
const videoStream = await navigator.mediaDevices.getUserMedia({ video: true })
videoStream.getTracks().forEach(track => track.stop())
return true
default: // 其他
return false // 失败
}
} catch (error: any) {
console.error(`请求${permissionType}权限失败:`, error)
return false
}
// #endif
// #ifndef H5
return true
// #endif
}
/**
* 监听权限状态变化
* @param permissionType 权限类型
* @param callback 回调函数
*/
async watchPermission(permissionType: PermissionType, callback: (state: PermissionState) => void): Promise<void> {
// #ifdef H5
try {
if (navigator.permissions && navigator.permissions.query) {
const permission = await navigator.permissions.query({ name: permissionType as PermissionName })
permission.onchange = () => {
callback(permission.state)
}
}
} catch (error) {
console.error(`监听${permissionType}权限变化失败:`, error)
}
// #endif
}
/**
* 显示权限引导弹窗
* @param permissionType 权限类型
*/
showPermissionGuide(permissionType: PermissionType): void {
const guides = {
microphone: {
title: t("Mobile.Permission.microphoneTitle"),
description: t("Mobile.Permission.microphoneDescription"),
steps: [
t("Mobile.Permission.stepClickLock"),
t("Mobile.Permission.stepAllowMicrophone"),
t("Mobile.Permission.stepRefreshRetryRecord")
]
},
camera: {
title: t("Mobile.Permission.cameraTitle"),
description: t("Mobile.Permission.cameraDescription"),
steps: [
t("Mobile.Permission.stepClickLock"),
t("Mobile.Permission.stepAllowCamera"),
t("Mobile.Permission.stepRefreshRetryPhoto")
]
}
}
const guide = guides[permissionType]
if (guide) {
uni.showModal({
title: guide.title,
content: t("Mobile.Permission.guideContent", {
description: guide.description,
steps: guide.steps.map((step, index) => `${index + 1}. ${step}`).join('\n'),
}),
showCancel: true,
cancelText: t("Mobile.Common.cancel"),
confirmText: t("Mobile.Permission.gotIt"),
success: (res) => {
if (res.confirm) {
console.log('用户确认了权限引导')
}
}
})
}
}
/**
* 检查是否支持权限API
* @returns 是否支持
*/
isPermissionAPISupported(): boolean {
// #ifdef H5
return !!(navigator.permissions && navigator.permissions.query)
// #endif
// #ifndef H5
return false
// #endif
}
}
/**
* 麦克风权限专用工具函数
*/
export class MicrophonePermissionHelper {
private static manager = PermissionManager.getInstance()
/**
* 检查麦克风权限状态
*/
static async check(): Promise<PermissionState> {
return await this.manager.checkPermission('microphone')
}
/**
* 请求麦克风权限
*/
static async request(): Promise<boolean> {
return await this.manager.requestPermission('microphone')
}
/**
* 监听麦克风权限变化
*/
static async watch(callback: (state: PermissionState) => void): Promise<void> {
return await this.manager.watchPermission('microphone', callback)
}
/**
* 显示麦克风权限引导
*/
static showGuide(): void {
this.manager.showPermissionGuide('microphone')
}
/**
* 确保麦克风权限可用
* @param showGuide 是否显示权限引导
* @returns 是否成功获取权限
*/
static async ensure(showGuide: boolean = true): Promise<boolean> {
// Always attempt to request permission first
const success = await this.request()
if (success) {
return true
}
// If request fails, check the current state
const state = await this.check()
// Show guide if denied and showGuide is true
if (showGuide && state === 'denied') {
this.showGuide()
}
return false
}
}
// 导出默认实例
export default PermissionManager.getInstance()