|
@@ -109,30 +109,145 @@ const uploading = ref(false)
|
|
|
const uploaderRef = ref(null)
|
|
const uploaderRef = ref(null)
|
|
|
|
|
|
|
|
// 打开相机
|
|
// 打开相机
|
|
|
-const openCamera = () => {
|
|
|
|
|
- // 创建隐藏的input元素来触发相机
|
|
|
|
|
- const input = document.createElement('input')
|
|
|
|
|
- input.type = 'file'
|
|
|
|
|
- input.accept = 'image/*'
|
|
|
|
|
- input.capture = 'camera'
|
|
|
|
|
-
|
|
|
|
|
- input.onchange = (e) => {
|
|
|
|
|
- const file = e.target.files[0]
|
|
|
|
|
- if (file) {
|
|
|
|
|
- // 模拟van-uploader的文件对象结构
|
|
|
|
|
|
|
+const openCamera = async () => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 检查浏览器是否支持getUserMedia
|
|
|
|
|
+ if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
|
|
|
|
|
+ showFailToast('您的浏览器不支持相机功能')
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 请求相机权限
|
|
|
|
|
+ const stream = await navigator.mediaDevices.getUserMedia({
|
|
|
|
|
+ video: {
|
|
|
|
|
+ facingMode: 'environment' // 使用后置摄像头
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ // 创建相机预览界面
|
|
|
|
|
+ showCameraPreview(stream)
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error('打开相机失败:', error)
|
|
|
|
|
+ if (error.name === 'NotAllowedError') {
|
|
|
|
|
+ showFailToast('相机权限被拒绝,请在浏览器设置中允许相机访问')
|
|
|
|
|
+ } else if (error.name === 'NotFoundError') {
|
|
|
|
|
+ showFailToast('未找到可用的相机设备')
|
|
|
|
|
+ } else {
|
|
|
|
|
+ showFailToast('打开相机失败: ' + error.message)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 显示相机预览界面
|
|
|
|
|
+const showCameraPreview = (stream) => {
|
|
|
|
|
+ // 创建预览弹窗
|
|
|
|
|
+ const previewDiv = document.createElement('div')
|
|
|
|
|
+ previewDiv.style.cssText = `
|
|
|
|
|
+ position: fixed;
|
|
|
|
|
+ top: 0;
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+ background: black;
|
|
|
|
|
+ z-index: 9999;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ `
|
|
|
|
|
+
|
|
|
|
|
+ // 创建视频元素
|
|
|
|
|
+ const video = document.createElement('video')
|
|
|
|
|
+ video.style.cssText = `
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ height: 80%;
|
|
|
|
|
+ object-fit: cover;
|
|
|
|
|
+ `
|
|
|
|
|
+ video.srcObject = stream
|
|
|
|
|
+ video.autoplay = true
|
|
|
|
|
+ video.playsInline = true
|
|
|
|
|
+
|
|
|
|
|
+ // 创建拍照按钮
|
|
|
|
|
+ const captureBtn = document.createElement('button')
|
|
|
|
|
+ captureBtn.style.cssText = `
|
|
|
|
|
+ width: 80px;
|
|
|
|
|
+ height: 80px;
|
|
|
|
|
+ border-radius: 50%;
|
|
|
|
|
+ background: #fff;
|
|
|
|
|
+ border: 4px solid #1989fa;
|
|
|
|
|
+ margin-top: 20px;
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+ font-size: 16px;
|
|
|
|
|
+ color: #1989fa;
|
|
|
|
|
+ `
|
|
|
|
|
+ captureBtn.textContent = '拍照'
|
|
|
|
|
+
|
|
|
|
|
+ // 创建关闭按钮
|
|
|
|
|
+ const closeBtn = document.createElement('button')
|
|
|
|
|
+ closeBtn.style.cssText = `
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ top: 20px;
|
|
|
|
|
+ right: 20px;
|
|
|
|
|
+ background: rgba(255,255,255,0.3);
|
|
|
|
|
+ border: none;
|
|
|
|
|
+ color: white;
|
|
|
|
|
+ font-size: 24px;
|
|
|
|
|
+ width: 40px;
|
|
|
|
|
+ height: 40px;
|
|
|
|
|
+ border-radius: 50%;
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+ `
|
|
|
|
|
+ closeBtn.textContent = '×'
|
|
|
|
|
+
|
|
|
|
|
+ // 拍照功能
|
|
|
|
|
+ captureBtn.onclick = () => {
|
|
|
|
|
+ // 创建canvas来捕获照片
|
|
|
|
|
+ const canvas = document.createElement('canvas')
|
|
|
|
|
+ const context = canvas.getContext('2d')
|
|
|
|
|
+ canvas.width = video.videoWidth
|
|
|
|
|
+ canvas.height = video.videoHeight
|
|
|
|
|
+ context.drawImage(video, 0, 0)
|
|
|
|
|
+
|
|
|
|
|
+ // 将canvas转换为blob
|
|
|
|
|
+ canvas.toBlob(async (blob) => {
|
|
|
|
|
+ // 停止相机流
|
|
|
|
|
+ stream.getTracks().forEach(track => track.stop())
|
|
|
|
|
+
|
|
|
|
|
+ // 移除预览界面
|
|
|
|
|
+ document.body.removeChild(previewDiv)
|
|
|
|
|
+
|
|
|
|
|
+ // 创建文件对象
|
|
|
|
|
+ const file = new File([blob], 'camera-photo.jpg', { type: 'image/jpeg' })
|
|
|
|
|
+
|
|
|
|
|
+ // 创建文件项
|
|
|
const fileItem = {
|
|
const fileItem = {
|
|
|
file: file,
|
|
file: file,
|
|
|
- content: URL.createObjectURL(file),
|
|
|
|
|
|
|
+ content: URL.createObjectURL(blob),
|
|
|
status: 'uploading'
|
|
status: 'uploading'
|
|
|
}
|
|
}
|
|
|
uploadImages.value = [fileItem]
|
|
uploadImages.value = [fileItem]
|
|
|
|
|
|
|
|
// 触发图片处理
|
|
// 触发图片处理
|
|
|
- afterReadImage(fileItem)
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ await afterReadImage(fileItem)
|
|
|
|
|
+ }, 'image/jpeg', 0.9)
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- input.click()
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // 关闭功能
|
|
|
|
|
+ closeBtn.onclick = () => {
|
|
|
|
|
+ // 停止相机流
|
|
|
|
|
+ stream.getTracks().forEach(track => track.stop())
|
|
|
|
|
+ // 移除预览界面
|
|
|
|
|
+ document.body.removeChild(previewDiv)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 添加到界面
|
|
|
|
|
+ previewDiv.appendChild(video)
|
|
|
|
|
+ previewDiv.appendChild(captureBtn)
|
|
|
|
|
+ previewDiv.appendChild(closeBtn)
|
|
|
|
|
+ document.body.appendChild(previewDiv)
|
|
|
|
|
+
|
|
|
|
|
+ // 播放视频
|
|
|
|
|
+ video.play()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 移除图片
|
|
// 移除图片
|