import React, { useState, useEffect, useRef } from 'react'; import PreviewItem from './preview-item'; import UploadButton from './upload-button'; import OPPreviewImage from '../op-preview-image'; import { ImageUploaderProps } from 'src/types/op-image-uploader'; import './index.scss'; import Viewer from 'viewerjs'; import 'viewerjs/dist/viewer.css'; const classPrefix = 'image-uploader'; const ImageUploader: React.FC = (props) => { const { value = [], maxCount = 1, deletable = false, box = 104, loading = false, capture = 'camera', selectMode = false, uploadMode = 'takePhoto', compressSize = 200, beforeUpload, onBeforeUpload, onDelete, onError, } = props; const [images, setImages] = useState([]); const [uploadingIndex, setUploadingIndex] = useState(null); const [previewImages, setPreviewImages] = useState([]); const viewerRef = useRef(null); const previewContainerRef = useRef(null); useEffect(() => { setImages(value); setPreviewImages(value?.map((item) => item.url) || []); }, [value]); // 初始化图片预�? useEffect(() => { if (previewContainerRef.current && previewImages.length > 0) { viewerRef.current = new Viewer(previewContainerRef.current, { hidden: () => { // 预览关闭时的回调 }, url: 'src', toolbar: { zoomIn: true, zoomOut: true, oneToOne: true, reset: true, prev: true, play: false, next: true, rotateLeft: true, rotateRight: true, flipHorizontal: true, flipVertical: true, }, }); } return () => { if (viewerRef.current) { viewerRef.current.destroy(); viewerRef.current = null; } }; }, [previewImages]); const onViewImage = (index: number) => { // 使用 viewer.js 打开预览 if (viewerRef.current) { viewerRef.current.view(index); } }; // 点击操作 const onClickAdd = () => { const isCameraMode = capture && capture === 'camera'; const params = { type: '0', mode: isCameraMode ? 'camera' : 'photo', }; const deviceAgent = navigator.userAgent.toLowerCase(); const agentFlag = deviceAgent.match(/android/); if (agentFlag) { if (selectMode) { // Android 设备且需要选择模式,显示选择对话�? // 这里简化处理,直接调用浏览器上�? handlerUploadNavigator(); } else { // Android 设备,直接调用相�? handlerUpload(params); } } else { // �?Android 设备,使用浏览器上传 handlerUploadNavigator(); } }; // 浏览器上�? const handlerUploadNavigator = () => { const dom = document.querySelector('#inputFile') as HTMLInputElement; if (dom) { dom.value = ''; dom.click(); dom.onchange = (e) => { const target = e.target as HTMLInputElement; const fileData = target.files?.[0]; if (!fileData) return; const reader = new FileReader(); reader.readAsDataURL(fileData); reader.onload = (event) => { const base64 = event.target?.result as string; beforeUpload && beforeUpload({ data: base64, base64, }); onBeforeUpload && onBeforeUpload({ data: base64, base64, }); const windowURL = window.URL || window.webkitURL; const imgSrc = windowURL.createObjectURL(fileData); const uid = (Math.random() * 10000).toFixed(0); setImages([...(images || []), { id: uid, url: imgSrc }]); }; }; } }; // 上传(PDA 模式�? const handlerUpload = (params: any) => { const isCameraMode = capture && capture === 'camera'; // 检查是否在 PDA 环境 if (typeof window !== 'undefined' && (window as any).WindVane) { const uploadPromise = uploadMode === 'takePhoto' ? wvCameraTakePhoto(isCameraMode) : takePhotoMethod2(compressSize); uploadPromise .then((ret) => { onBeforeUpload && onBeforeUpload(ret); beforeUpload && beforeUpload(ret); }) .catch((error) => { onError && onError(error); console.log(error); }); } else { // �?PDA 环境,降级到浏览器上�? console.warn('WindVane not available, falling back to browser upload'); handlerUploadNavigator(); } }; const onDeleteItem = (item: any, index: number) => { const newImages = images.filter((_, i) => i !== index); setImages(newImages); setPreviewImages(newImages.map((img) => img.url)); onDelete && onDelete(item, index); }; return ( <>
{images && images.map((item, index) => { return ( onDeleteItem(item, index)} onView={() => onViewImage(index)} /> ); })} {!images || images.length < maxCount ? ( ) : null}
{/* loading */} {loading ? (
) : null} {/* 隐藏的预览容器,用于 viewer.js */}
{previewImages.map((url, index) => ( {`preview-${index}`} ))}
); }; // PDA 相机拍照 function wvCameraTakePhoto(isCameraMode: boolean): Promise { return new Promise(function (resolve, reject) { if (typeof window === 'undefined' || !(window as any).WindVane) { reject(new Error('WindVane not available')); return; } const params = { type: '0', mode: isCameraMode ? 'camera' : 'photo', }; (window as any).WindVane.call( 'WVCamera', 'takePhoto', params, function (e: any) { const plugin = { domain: 'camera', method: 'getBase64', params: { filePath: e.localPath, }, }; (window as any).WindVane.call( 'WindvanePlugin', 'invoke', JSON.stringify(plugin), function (res: any) { resolve(res.data); }, function (err: any) { reject(err); console.log('failure ' + JSON.stringify(err)); }, ); }, function (err: any) { reject(err); console.log('takePhoto failure: ' + JSON.stringify(err)); }, ); }); } // PDA 拍照方法2 function takePhotoMethod2(compressSize = 200): Promise { return new Promise(function (resolve, reject) { if (typeof window === 'undefined' || !(window as any).WindVane) { reject(new Error('WindVane not available')); return; } const params = { domain: 'camera', method: 'takePhotoMethod2', params: { compressSize }, }; (window as any).WindVane.call( 'WindvanePlugin', 'invoke', JSON.stringify(params), function (e: any) { const base64 = e.data.imageBase64; resolve({ base64, data: base64 }); }, reject, ); }); } export default ImageUploader;