365 lines
8.4 KiB
JavaScript
365 lines
8.4 KiB
JavaScript
// utils/record.js
|
|
|
|
// 录屏工具类
|
|
class ScreenRecorder {
|
|
constructor() {
|
|
this.recordModule = null
|
|
this.eventModule = null
|
|
this.isRecording = false
|
|
this.recordTime = 0
|
|
this.recordTimer = null
|
|
this.eventListeners = new Map()
|
|
|
|
this.init()
|
|
}
|
|
|
|
// 初始化
|
|
init() {
|
|
try {
|
|
// 获取原生模块
|
|
this.recordModule = uni.requireNativePlugin('Record-Module')
|
|
this.eventModule = uni.requireNativePlugin('RecordEvent-Module')
|
|
|
|
console.log('录屏模块初始化成功')
|
|
} catch (error) {
|
|
console.error('录屏模块初始化失败:', error)
|
|
}
|
|
}
|
|
|
|
// 开始录屏
|
|
start(options = {}) {
|
|
return new Promise((resolve, reject) => {
|
|
if (!this.recordModule) {
|
|
reject(new Error('录屏模块未初始化'))
|
|
return
|
|
}
|
|
|
|
if (this.isRecording) {
|
|
reject(new Error('已经在录制中'))
|
|
return
|
|
}
|
|
|
|
const defaultOptions = {
|
|
width: 720, // 宽度
|
|
height: 1280, // 高度
|
|
bitRate: 4000000, // 比特率 4Mbps
|
|
fileName: null, // 自定义文件名
|
|
recordAudio: true // 是否录制音频
|
|
}
|
|
|
|
const recordOptions = { ...defaultOptions, ...options }
|
|
|
|
console.log('开始录屏,参数:', recordOptions)
|
|
|
|
this.recordModule.startRecording(recordOptions, (result) => {
|
|
console.log('开始录屏结果:', result)
|
|
|
|
if (result.code === 0 && result.success) {
|
|
this.isRecording = true
|
|
this.startTimer()
|
|
|
|
// 触发开始事件
|
|
this.emit('start', { options: recordOptions })
|
|
|
|
resolve({
|
|
success: true,
|
|
message: '开始录屏成功',
|
|
data: result
|
|
})
|
|
} else {
|
|
reject(new Error(result.message || '开始录屏失败'))
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
// 停止录屏
|
|
stop() {
|
|
return new Promise((resolve, reject) => {
|
|
if (!this.recordModule) {
|
|
reject(new Error('录屏模块未初始化'))
|
|
return
|
|
}
|
|
|
|
if (!this.isRecording) {
|
|
resolve({
|
|
success: true,
|
|
message: '当前没有在录制'
|
|
})
|
|
return
|
|
}
|
|
|
|
console.log('停止录屏')
|
|
|
|
this.recordModule.stopRecording((result) => {
|
|
console.log('停止录屏结果:', result)
|
|
|
|
this.isRecording = false
|
|
this.stopTimer()
|
|
|
|
if (result.code === 0 && result.success) {
|
|
// 触发停止事件
|
|
this.emit('stop', {})
|
|
|
|
resolve({
|
|
success: true,
|
|
message: '停止录屏成功',
|
|
data: result
|
|
})
|
|
} else {
|
|
reject(new Error(result.message || '停止录屏失败'))
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
// 获取录屏状态
|
|
getStatus() {
|
|
return new Promise((resolve, reject) => {
|
|
if (!this.recordModule) {
|
|
reject(new Error('录屏模块未初始化'))
|
|
return
|
|
}
|
|
|
|
this.recordModule.getRecordingStatus((result) => {
|
|
this.isRecording = result.isRecording
|
|
|
|
resolve({
|
|
isRecording: result.isRecording,
|
|
duration: result.duration,
|
|
filePath: result.filePath,
|
|
...result
|
|
})
|
|
})
|
|
})
|
|
}
|
|
|
|
// 获取录屏文件列表
|
|
getFileList() {
|
|
return new Promise((resolve, reject) => {
|
|
if (!this.recordModule) {
|
|
reject(new Error('录屏模块未初始化'))
|
|
return
|
|
}
|
|
|
|
this.recordModule.getRecordFiles((result) => {
|
|
if (result.code === 0) {
|
|
resolve({
|
|
success: true,
|
|
files: result.files,
|
|
count: result.count
|
|
})
|
|
} else {
|
|
reject(new Error(result.message || '获取文件列表失败'))
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
// 删除录屏文件
|
|
deleteFile(filePath) {
|
|
return new Promise((resolve, reject) => {
|
|
if (!this.recordModule) {
|
|
reject(new Error('录屏模块未初始化'))
|
|
return
|
|
}
|
|
|
|
this.recordModule.deleteRecordFile(filePath, (result) => {
|
|
if (result.code === 0 && result.success) {
|
|
resolve({
|
|
success: true,
|
|
message: '删除成功'
|
|
})
|
|
} else {
|
|
reject(new Error(result.message || '删除失败'))
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
// 检查录屏权限
|
|
checkPermission() {
|
|
return new Promise((resolve, reject) => {
|
|
if (!this.recordModule) {
|
|
reject(new Error('录屏模块未初始化'))
|
|
return
|
|
}
|
|
|
|
this.recordModule.checkPermission((result) => {
|
|
resolve({
|
|
hasPermission: result.hasPermission,
|
|
message: result.message,
|
|
...result
|
|
})
|
|
})
|
|
})
|
|
}
|
|
|
|
// 开始事件监听
|
|
startListen() {
|
|
return new Promise((resolve, reject) => {
|
|
if (!this.eventModule) {
|
|
reject(new Error('事件模块未初始化'))
|
|
return
|
|
}
|
|
|
|
this.eventModule.startListen((result) => {
|
|
if (result.code === 0 && result.success) {
|
|
// 监听全局事件
|
|
uni.$on('recordEvent', this.handleRecordEvent.bind(this))
|
|
|
|
resolve({
|
|
success: true,
|
|
message: '开始监听成功'
|
|
})
|
|
} else {
|
|
reject(new Error(result.message || '开始监听失败'))
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
// 停止事件监听
|
|
stopListen() {
|
|
return new Promise((resolve, reject) => {
|
|
if (!this.eventModule) {
|
|
reject(new Error('事件模块未初始化'))
|
|
return
|
|
}
|
|
|
|
this.eventModule.stopListen((result) => {
|
|
if (result.code === 0 && result.success) {
|
|
// 移除全局事件监听
|
|
uni.$off('recordEvent', this.handleRecordEvent.bind(this))
|
|
|
|
resolve({
|
|
success: true,
|
|
message: '停止监听成功'
|
|
})
|
|
} else {
|
|
reject(new Error(result.message || '停止监听失败'))
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
// 处理录屏事件
|
|
handleRecordEvent(event) {
|
|
console.log('收到录屏事件:', event)
|
|
|
|
const { type, data } = event
|
|
|
|
switch (type) {
|
|
case 'onRecordEvent':
|
|
this.handleNativeEvent(data)
|
|
break
|
|
}
|
|
}
|
|
|
|
// 处理原生事件
|
|
handleNativeEvent(data) {
|
|
const { event, filePath } = data
|
|
|
|
switch (event) {
|
|
case 'start':
|
|
console.log('录屏开始,文件路径:', filePath)
|
|
this.emit('started', { filePath })
|
|
break
|
|
|
|
case 'stop':
|
|
console.log('录屏停止,文件路径:', filePath)
|
|
this.emit('stopped', { filePath })
|
|
break
|
|
}
|
|
}
|
|
|
|
// 开始计时器
|
|
startTimer() {
|
|
this.recordTime = 0
|
|
this.recordTimer = setInterval(() => {
|
|
this.recordTime++
|
|
|
|
// 触发计时事件
|
|
this.emit('timeupdate', {
|
|
currentTime: this.recordTime
|
|
})
|
|
|
|
}, 1000)
|
|
}
|
|
|
|
// 停止计时器
|
|
stopTimer() {
|
|
if (this.recordTimer) {
|
|
clearInterval(this.recordTimer)
|
|
this.recordTimer = null
|
|
this.recordTime = 0
|
|
}
|
|
}
|
|
|
|
// 格式化时间
|
|
formatTime(seconds) {
|
|
const hours = Math.floor(seconds / 3600)
|
|
const minutes = Math.floor((seconds % 3600) / 60)
|
|
const secs = seconds % 60
|
|
|
|
if (hours > 0) {
|
|
return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`
|
|
} else {
|
|
return `${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`
|
|
}
|
|
}
|
|
|
|
// 事件监听
|
|
on(event, callback) {
|
|
if (!this.eventListeners.has(event)) {
|
|
this.eventListeners.set(event, [])
|
|
}
|
|
this.eventListeners.get(event).push(callback)
|
|
}
|
|
|
|
// 取消事件监听
|
|
off(event, callback) {
|
|
if (this.eventListeners.has(event)) {
|
|
const listeners = this.eventListeners.get(event)
|
|
const index = listeners.indexOf(callback)
|
|
if (index > -1) {
|
|
listeners.splice(index, 1)
|
|
}
|
|
}
|
|
}
|
|
|
|
// 触发事件
|
|
emit(event, data) {
|
|
if (this.eventListeners.has(event)) {
|
|
this.eventListeners.get(event).forEach(callback => {
|
|
try {
|
|
callback(data)
|
|
} catch (error) {
|
|
console.error(`执行事件 ${event} 的回调失败:`, error)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// 销毁
|
|
destroy() {
|
|
this.stop()
|
|
this.stopListen()
|
|
this.eventListeners.clear()
|
|
|
|
this.recordModule = null
|
|
this.eventModule = null
|
|
}
|
|
}
|
|
|
|
// 创建单例
|
|
let recorderInstance = null
|
|
|
|
export function getScreenRecorder() {
|
|
if (!recorderInstance) {
|
|
recorderInstance = new ScreenRecorder()
|
|
}
|
|
return recorderInstance
|
|
}
|
|
|
|
export default getScreenRecorder |