<script setup lang="tsx">
import { ref, onMounted, inject, onActivated } from 'vue'
import { ElMessage } from 'element-plus'
import { uploadFile } from '@/api/materials'
import { ContentWrap } from '@/components/ContentWrap'
import { uploadReportFile } from '@/api/report'
const updateImgList = inject('updateImgList') as (() => void) | undefined
const setIsVideo = inject('setIsVideo') as ((yesno: boolean) => void) | undefined
const props = defineProps({
edittype: {
type: String,
default: ''
},
reportinfo: {
type: Object,
default: () => ({})
},
patientInfo: {
type: Object,
default: () => ({})
}
})
const video = ref<HTMLVideoElement | null>(null)
const canvasVideo = ref<HTMLCanvasElement | null>(null)
const context = ref<CanvasRenderingContext2D | null>(null)
let vstream: MediaStream | null = null
let deviceVideos: string[] = []
let deviceVideosIndex = 0
let chunks: Blob[] = []
let recording = false
let mediaRecorder: MediaRecorder | null = null
let recordedVideoUrl: string | null = null
const getUserMedia = async (constraints: MediaStreamConstraints): Promise<MediaStream> => {
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
return await navigator.mediaDevices.getUserMedia(constraints)
} else {
throw new Error('不支持访问用户媒体')
}
}
const closeCamera = () => {
return new Promise((resolve, reject) => {
if (video.value && video.value.srcObject) {
try {
const tracks = (video.value.srcObject as MediaStream).getTracks()
console.log(tracks)
tracks.forEach((track) => {
track.stop()
})
video.value.srcObject = null
} catch (e) {
console.error(e)
}
} else {
resolve('ok')
}
})
}
const openCamera = async () => {
await start()
try {
await closeCamera()
if (deviceVideos.length === 0) {
ElMessage.error('没有找到摄像头设备')
return
}
console.log(deviceVideos)
console.log('摄像头数量:' + deviceVideos.length)
const stream = await getUserMedia({
video: {
width: 1920,
height: 1080,
deviceId: deviceVideos[deviceVideosIndex++ % deviceVideos.length]
},
audio: true
})
vstream = stream
if (video.value) {
video.value.srcObject = stream
video.value.play()
}
setIsVideo?.(true)
} catch (e) {
console.log(e)
ElMessage.error(e + '!')
}
}
const keyDown = (event: KeyboardEvent) => {
console.log('ssss')
if (event.key === 'Enter') {
console.log('xxxx')
}
}
const captureSavePhoto = (event: KeyboardEvent) => {
capturePhoto()
savePhotox()
}
const capturePhoto = () => {
if (context.value && video.value) {
context.value.drawImage(video.value, 0, 0, 1920, 1080, 0, 0, 800, 600)
}
}
const saveAs = (data: string, filename: string) => {
const link = document.createElement('a')
link.href = data
link.download = filename
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
}
const saveAsx = (data: string, filename: string) => {
const link = document.createElement('a')
link.href = data
link.download = filename
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
}
const savePhotox = async () => {
const canvas1 = document.createElement('canvas')
if (video.value) {
canvas1.width = video.value.videoWidth
canvas1.height = video.value.videoHeight
const context1 = canvas1.getContext('2d')
if (context1) {
context1.drawImage(video.value, 0, 0, 1920, 1080)
const fd = new FormData()
fd.append('file', blobtoFile(base64toBlob(canvas1.toDataURL()), 'xxx.png'))
console.log('xxxxxx')
if (props.edittype === 'reg') {
console.log('取材在操作SetImage')
fd.append('RegID', props.patientInfo.RegID)
const res = await uploadFile(fd)
if (res) {
ElMessage.success('保存成功')
updateImgList()
} else {
ElMessage.error('保存失败')
}
}
if (props.edittype === 'report') {
fd.append('RegID', props.reportinfo.RegID)
const res = await uploadReportFile(fd)
if (res) {
ElMessage.success('保存成功')
updateImgList()
} else {
ElMessage.error('保存失败')
}
}
}
}
}
const blobtoFile = (blob, fileName) => {
const file = new File([blob], fileName, { type: blob.type })
return file
}
const base64toBlob = (dataurl) => {
let arr = dataurl.split(',')
let mime = arr[0].match(/:(.*?);/)[1]
let bstr = atob(arr[1])
let n = bstr.length
let u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new Blob([u8arr], { type: mime })
}
const savePhoto = () => {
const canvas1 = document.createElement('canvas')
if (video.value) {
canvas1.width = video.value.videoWidth
canvas1.height = video.value.videoHeight
const context1 = canvas1.getContext('2d')
if (context1) {
context1.drawImage(video.value, 0, 0, 1920, 1080)
saveAs(canvas1.toDataURL(), 'photo.jpg')
}
}
}
const startRecording = () => {
if (vstream && MediaRecorder.isTypeSupported('video/webm')) {
chunks = []
mediaRecorder = new MediaRecorder(vstream, { mimeType: 'video/webm' })
mediaRecorder.ondataavailable = (e) => {
if (e.data && e.data.size > 0) {
chunks.push(e.data)
}
}
mediaRecorder.onstop = () => {
const recordedBlob = new Blob(chunks, { type: 'video/webm' })
chunks = []
recordedVideoUrl = URL.createObjectURL(recordedBlob)
console.log('录像文件路径1:' + recordedVideoUrl)
}
mediaRecorder.start()
recording = true
} else {
console.error('不支持录制视频')
}
}
const stopRecording = () => {
if (recording && mediaRecorder) {
mediaRecorder.stop()
mediaRecorder = null
recording = false
}
}
const saveRecording = () => {
console.log('录像文件路径2:' + recordedVideoUrl)
if (recordedVideoUrl) {
const a = document.createElement('a')
a.href = recordedVideoUrl
a.download = '录像.webm'
a.click()
}
}
const start = () => {
if (canvasVideo.value) {
context.value = canvasVideo.value.getContext('2d')
}
console.log('onMounted')
console.log(navigator.mediaDevices)
if (navigator.mediaDevices) {
navigator.mediaDevices
.enumerateDevices()
.then((devices) => {
devices.forEach((device) => {
if (device.kind.startsWith('video')) {
deviceVideos.push(device.deviceId)
}
})
})
.catch((error) => {
console.error('Failed to enumerate devices:', error)
})
}
}
onMounted(async () => {
await start()
})
onActivated(async () => {
await start()
})
defineExpose({
openCamera,
closeCamera,
capturePhoto,
savePhoto,
startRecording,
stopRecording,
saveRecording,
captureSavePhoto
})
</script>
<template>
<ContentWrap style="border: 0px; position: relative">
<div class="flex justify-center mb-10px">
<BaseButton size="large" @keydown="keyDown" @click="captureSavePhoto">拍照并保存</BaseButton>
<!--
<BaseButton @click="openCamera">打开摄像头</BaseButton>
<BaseButton @click="closeCamera">关闭摄像头</BaseButton>
<BaseButton @click="capturePhoto">拍照</BaseButton>
<BaseButton @click="savePhoto">拍照另存为</BaseButton>
<BaseButton @click="startRecording">开始录像</BaseButton>
<BaseButton @click="stopRecording">停止录像</BaseButton>
<BaseButton @click="saveRecording">录像另存为</BaseButton>
-->
</div>
<div class="flex justify-center">
<video ref="video" width="80%" height="80%" controls></video>
</div>
<canvas id="canvasVideo" ref="canvasVideo" width="400" height="300"></canvas>
</ContentWrap>
</template>
<style scoped lang="less">
#canvasVideo {
background-color: #1c2518;
position: absolute;
bottom: 0px;
left: 0px;
display: none;
}
</style>