"use strict"; const common_vendor = require("../../common/vendor.js"); const common_config = require("../../common/config.js"); const _sfc_main = { data() { return { currentStep: 0, photos: [null, null, null, null, null, null], // 存储6张照片:左手正面、左手反面、左手握拳、右手正面、右手反面、右手握拳 instructions: [ "请将左手掌正面朝上,保持手指自然伸展,确保整个手掌清晰可见", "请将左手掌反面朝上,保持手指自然伸展,确保整个手背清晰可见", "请握紧左手拳头,使拳面朝向相机,确保整个拳头清晰可见", "请将右手掌正面朝上,保持手指自然伸展,确保整个手掌清晰可见", "请将右手掌反面朝上,保持手指自然伸展,确保整个手背清晰可见", "请握紧右手拳头,使拳面朝向相机,确保整个拳头清晰可见" ], previewTexts: [ "左手掌正面照片预览区", "左手掌反面照片预览区", "左手握拳照片预览区", "右手掌正面照片预览区", "右手掌反面照片预览区", "右手握拳照片预览区" ], photoTypes: ["left_palm", "left_back", "left_fist", "right_palm", "right_back", "right_fist"], // 照片类型标识 isH5: false, showCamera: false, mediaStream: null, cameraContext: null, cameraMode: "normal", // 添加相机模式 cameraInitRetries: 0, // 添加重试计数器 gestureOverlays: [ "http://121.36.251.245:9000/minlong/%E5%B7%A6%E6%89%8B%E6%89%8B%E6%8E%8C.png", "http://121.36.251.245:9000/minlong/%E5%B7%A6%E6%89%8B%E6%89%8B%E8%83%8C.png", "http://121.36.251.245:9000/minlong/%E5%B7%A6%E6%89%8B%E6%8F%A1%E6%8B%B3.png", "http://121.36.251.245:9000/minlong/%E5%8F%B3%E6%89%8B%E6%89%8B%E6%8E%8C.png", "http://121.36.251.245:9000/minlong/%E5%8F%B3%E6%89%8B%E6%89%8B%E8%83%8C.png", "http://121.36.251.245:9000/minlong/%E5%8F%B3%E6%89%8B%E6%8F%A1%E6%8B%B3.png" /* '/static/images/palm_overlay.png', // 手掌正面引导图 '/static/images/back_overlay.png', // 手掌反面引导图 '/static/images/fist_overlay.png' // 握拳引导图 */ ], gestureHints: [ "请将左手掌对准轮廓线", "请将左手背对准轮廓线", "请将左手拳头对准轮廓线", "请将右手掌对准轮廓线", "请将右手背对准轮廓线", "请将右手拳头对准轮廓线" ], photoLinks: [null, null, null, null, null, null], // 存储上传后的图片链接 cameraPosition: "front", // 修改默认为前置摄像头 guideIcon: [ "http://121.36.251.245:9000/minlong/%E5%B7%A6%E6%89%8B%E6%89%8B%E6%8E%8C.jpg", "http://121.36.251.245:9000/minlong/%E5%B7%A6%E6%89%8B%E6%89%8B%E8%83%8C.jpg", "http://121.36.251.245:9000/minlong/%E5%B7%A6%E6%89%8B%E5%8D%A7%E6%8B%B3.jpg", "http://121.36.251.245:9000/minlong/%E5%8F%B3%E6%89%8B%E6%89%8B%E6%8E%8C.jpg", "http://121.36.251.245:9000/minlong/%E5%8F%B3%E6%89%8B%E6%89%8B%E8%83%8C.jpg", "http://121.36.251.245:9000/minlong/%E5%8F%B3%E6%89%8B%E5%8D%A7%E6%8B%B3.jpg" ] }; }, computed: { canGoNext() { return this.photos[this.currentStep] !== null; } }, onLoad() { common_vendor.index.authorize({ scope: "scope.camera", success: () => { console.log("相机权限已授权"); }, fail: () => { common_vendor.index.showModal({ title: "提示", content: "请授权相机权限以完成手部照片采集", success: (res) => { if (res.confirm) { common_vendor.index.openSetting(); } } }); } }); }, beforeDestroy() { this.stopMediaStream(); }, methods: { takePhoto() { if (this.isH5) { this.startCamera(); } else { this.showCamera = true; this.cameraInitRetries = 0; this.$nextTick(() => { try { this.cameraContext = common_vendor.index.createCameraContext(); console.log("相机上下文创建成功"); } catch (err) { console.error("创建相机上下文失败:", err); this.handleCameraInitError(); } }); } }, uploadPhoto(filePathOrData, type) { console.log(`准备上传${type}类型的手部照片`); common_vendor.index.showLoading({ title: "上传中..." }); const userInfo = common_vendor.index.getStorageSync("userInfo"); userInfo ? JSON.parse(userInfo).openid || "" : ""; const tenant_id = common_vendor.index.getStorageSync("tenant_id") || "1"; if (!tenant_id) { common_vendor.index.hideLoading(); common_vendor.index.showToast({ title: "用户信息不完整,请重新登录", icon: "none" }); return; } if (this.isH5 && filePathOrData.startsWith("data:image")) { const base64Data = filePathOrData.split(",")[1]; const blob = this.base64ToBlob(base64Data, "image/jpeg"); const formData = new FormData(); formData.append("photo_file", blob, `${type}.jpg`); formData.append("application_id", common_vendor.index.getStorageSync("appId")); formData.append("tenant_id", tenant_id); formData.append("description", `手部照片-${type}`); console.log("H5上传参数:", { application_id: common_vendor.index.getStorageSync("appId"), tenant_id, description: `手部照片-${type}` }); fetch(`${common_config.apiBaseUrl}/job/upload_posture_photo`, { method: "POST", body: formData }).then((response) => response.json()).then((result) => { console.log("照片上传成功:", result); const index = this.photoTypes.indexOf(type); if (index !== -1 && result.data && result.data.url) { this.$set(this.photoLinks, index, result.data.url); console.log(`已保存${type}类型照片链接:`, result.data.url); } common_vendor.index.hideLoading(); common_vendor.index.showToast({ title: "照片上传成功", icon: "success" }); }).catch((error) => { console.error("照片上传失败:", error); common_vendor.index.hideLoading(); common_vendor.index.showToast({ title: "照片上传失败,请重试", icon: "none" }); }); } else { console.log(`小程序环境上传文件路径:`, filePathOrData); console.log("小程序上传参数:", { application_id: common_vendor.index.getStorageSync("appId"), tenant_id, description: `手部照片-${type}` }); common_vendor.index.uploadFile({ url: `${common_config.apiBaseUrl}/job/upload_posture_photo`, filePath: filePathOrData, name: "photo_file", // 确保文件参数名称正确 formData: { // 使用formData替代data以确保参数正确传递 "application_id": common_vendor.index.getStorageSync("appId"), "tenant_id": tenant_id, "description": `手部照片-${type}` }, success: (uploadRes) => { console.log("照片上传成功:", uploadRes); let result; try { if (typeof uploadRes.data === "string") { result = JSON.parse(uploadRes.data); } else { result = uploadRes.data; } console.log("解析后的上传结果:", result); const index = this.photoTypes.indexOf(type); if (index !== -1 && result.data && result.data.url) { this.$set(this.photoLinks, index, result.data.url); console.log(`已保存${type}类型照片链接:`, result.data.url); } } catch (e) { console.error("解析上传结果失败:", e); } common_vendor.index.hideLoading(); common_vendor.index.showToast({ title: "照片上传成功", icon: "success" }); }, fail: (err) => { console.error("照片上传失败:", err); common_vendor.index.hideLoading(); common_vendor.index.showToast({ title: "照片上传失败,请重试", icon: "none" }); }, complete: () => { common_vendor.index.hideLoading(); } }); } }, prevStep() { if (this.currentStep > 0) { this.currentStep--; } }, nextStep() { if (this.currentStep < 5) { this.currentStep++; } else if (this.currentStep === 5 && this.photos[5]) { this.submitAllPhotos(); } }, previewPhoto(index) { if (this.photos[index]) { common_vendor.index.previewImage({ urls: [this.photos[index]], current: this.photos[index] }); } }, submitAllPhotos() { if (this.photos.every((photo) => photo !== null)) { common_vendor.index.showLoading({ title: "处理中..." }); setTimeout(() => { common_vendor.index.hideLoading(); common_vendor.index.showToast({ title: "手部照片采集完成", icon: "success", duration: 2e3, success: () => { setTimeout(() => { common_vendor.index.navigateTo({ url: "/pages/success/success" }); }, 2e3); } }); }, 500); } else { common_vendor.index.showToast({ title: "请完成所有照片拍摄", icon: "none" }); } }, // H5环境下启动摄像头 startCamera() { this.showCamera = true; if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { const facingMode = this.cameraPosition === "front" ? "user" : "environment"; navigator.mediaDevices.getUserMedia({ video: { facingMode } }).then((stream) => { this.mediaStream = stream; this.$nextTick(() => { const videoElement = this.$refs.videoElement; if (videoElement) { videoElement.srcObject = stream; } }); }).catch((error) => { console.error("获取摄像头失败:", error); common_vendor.index.showToast({ title: "无法访问摄像头,请检查权限设置", icon: "none" }); this.showCamera = false; }); } else { common_vendor.index.showToast({ title: "您的浏览器不支持摄像头功能", icon: "none" }); this.showCamera = false; } }, // H5环境下拍照 capturePhoto() { console.log("执行H5拍照方法"); const videoElement = this.$refs.videoElement; const canvasElement = this.$refs.canvasElement; if (videoElement && canvasElement) { try { const context = canvasElement.getContext("2d"); canvasElement.width = videoElement.videoWidth; canvasElement.height = videoElement.videoHeight; context.drawImage(videoElement, 0, 0, canvasElement.width, canvasElement.height); const photoData = canvasElement.toDataURL("image/jpeg"); this.$set(this.photos, this.currentStep, photoData); this.uploadPhoto(photoData, this.photoTypes[this.currentStep]); this.stopMediaStream(); this.showCamera = false; } catch (err) { console.error("H5拍照失败:", err); common_vendor.index.showToast({ title: "拍照失败,请重试", icon: "none" }); } } }, // 小程序环境下拍照 capturePhotoMP() { console.log("执行小程序拍照方法"); if (!this.cameraContext) { console.error("相机上下文不存在"); this.handleCameraInitError(); return; } try { common_vendor.index.showLoading({ title: "拍照中...", mask: true }); this.cameraContext.takePhoto({ quality: "high", success: (res) => { console.log("拍照成功:", res); common_vendor.index.hideLoading(); this.$set(this.photos, this.currentStep, res.tempImagePath); this.uploadPhoto(res.tempImagePath, this.photoTypes[this.currentStep]); this.showCamera = false; }, fail: (err) => { common_vendor.index.hideLoading(); console.error("拍照失败:", err); common_vendor.index.showToast({ title: "拍照失败,请重试", icon: "none" }); this.fallbackToChooseImage(); } }); } catch (err) { common_vendor.index.hideLoading(); console.error("takePhoto方法执行失败:", err); this.fallbackToChooseImage(); } }, // 添加相机初始化错误处理 handleCameraInitError() { if (this.cameraInitRetries < 3) { this.cameraInitRetries++; common_vendor.index.showToast({ title: `相机初始化失败,正在重试(${this.cameraInitRetries}/3)`, icon: "none" }); setTimeout(() => { this.showCamera = false; setTimeout(() => { this.takePhoto(); }, 500); }, 1e3); } else { common_vendor.index.showToast({ title: "相机初始化失败,将使用系统相机", icon: "none" }); this.fallbackToChooseImage(); } }, // 添加备用的系统相机方法 fallbackToChooseImage() { this.showCamera = false; common_vendor.index.chooseImage({ count: 1, sourceType: ["camera"], success: (res) => { this.$set(this.photos, this.currentStep, res.tempFilePaths[0]); this.uploadPhoto(res.tempFilePaths[0], this.photoTypes[this.currentStep]); }, fail: (err) => { console.error("选择图片失败:", err); common_vendor.index.showToast({ title: "拍照失败,请重试", icon: "none" }); } }); }, // 修改相机错误处理方法 handleCameraError(e) { console.error("相机错误:", e.detail); const errorInfo = JSON.stringify(e.detail); console.log("详细错误信息:", errorInfo); common_vendor.index.showToast({ title: "相机启动失败,将使用系统相机", icon: "none" }); this.fallbackToChooseImage(); }, // 取消拍照 - 更新为同时支持H5和小程序 cancelCamera() { if (this.isH5) { this.stopMediaStream(); } this.showCamera = false; }, // 停止摄像头流 stopMediaStream() { if (this.mediaStream) { this.mediaStream.getTracks().forEach((track) => { track.stop(); }); this.mediaStream = null; } }, // base64转blob工具方法 base64ToBlob(base64, mimeType) { const byteCharacters = atob(base64); const byteArrays = []; for (let offset = 0; offset < byteCharacters.length; offset += 512) { const slice = byteCharacters.slice(offset, offset + 512); const byteNumbers = new Array(slice.length); for (let i = 0; i < slice.length; i++) { byteNumbers[i] = slice.charCodeAt(i); } const byteArray = new Uint8Array(byteNumbers); byteArrays.push(byteArray); } return new Blob(byteArrays, { type: mimeType }); }, retryCamera() { this.showCamera = false; setTimeout(() => { this.takePhoto(); }, 500); }, // 可以添加一个方法来切换蒙层显示 toggleGestureOverlay() { }, // 切换摄像头 switchCamera() { this.cameraPosition = this.cameraPosition === "front" ? "back" : "front"; if (this.isH5 && this.showCamera) { this.stopMediaStream(); this.startCamera(); } } } }; function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) { return common_vendor.e({ a: common_vendor.t($data.instructions[$data.currentStep]), b: $data.photos[$data.currentStep] }, $data.photos[$data.currentStep] ? { c: $data.photos[$data.currentStep] } : { d: common_vendor.t($data.previewTexts[$data.currentStep]) }, { e: common_vendor.f($data.photos, (photo, index, i0) => { return common_vendor.e({ a: photo }, photo ? { b: photo, c: common_vendor.o(($event) => $options.previewPhoto(index), index) } : { d: common_vendor.t(index + 1) }, { e: index, f: $data.currentStep === index ? 1 : "", g: photo ? 1 : "" }); }), f: common_vendor.t($data.photos[$data.currentStep] ? "重新拍摄" : "拍摄照片"), g: common_vendor.o((...args) => $options.takePhoto && $options.takePhoto(...args)), h: $data.currentStep === 0, i: common_vendor.o((...args) => $options.prevStep && $options.prevStep(...args)), j: common_vendor.t($data.currentStep === 5 && $data.photos[5] ? "完成" : "下一步"), k: !$options.canGoNext, l: common_vendor.o((...args) => $options.nextStep && $options.nextStep(...args)), m: !$data.isH5 && $data.showCamera }, !$data.isH5 && $data.showCamera ? { n: common_vendor.t($data.gestureHints[$data.currentStep]), o: $data.cameraPosition, p: common_vendor.o((...args) => $options.handleCameraError && $options.handleCameraError(...args)), q: $data.cameraMode, r: $data.guideIcon[$data.currentStep], s: common_vendor.s($data.currentStep >= 3 ? "left:30rpx" : "right:30rpx"), t: $data.gestureOverlays[$data.currentStep], v: common_vendor.o((...args) => $options.capturePhotoMP && $options.capturePhotoMP(...args)), w: common_vendor.o((...args) => $options.cancelCamera && $options.cancelCamera(...args)) } : {}, { x: $data.isH5 }, $data.isH5 ? { y: $data.guideIcon[$data.currentStep], z: common_vendor.s($data.currentStep >= 3 ? "left:30rpx" : "right:30rpx"), A: $data.gestureOverlays[$data.currentStep], B: common_vendor.t($data.gestureHints[$data.currentStep]), C: common_vendor.o((...args) => $options.capturePhoto && $options.capturePhoto(...args)), D: common_vendor.o((...args) => $options.switchCamera && $options.switchCamera(...args)), E: common_vendor.o((...args) => $options.cancelCamera && $options.cancelCamera(...args)), F: $data.showCamera } : {}); } const MiniProgramPage = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render]]); wx.createPage(MiniProgramPage);