|
|
@@ -0,0 +1,829 @@
|
|
|
+import CommonEventManager from '@ohos.commonEventManager'
|
|
|
+import uploadInstance from '../../common/util/UploadUtil';
|
|
|
+import { DrawingInfo, DrawingPage } from '../../viewmodel/DrawingInfo';
|
|
|
+import CommonConstants from '../../common/constants/CommonConstants';
|
|
|
+import ProcessRequest from '../../common/util/request/ProcessRequest';
|
|
|
+import RequestParamModel from '../../viewmodel/RequestParamModel';
|
|
|
+import { ConfirmDialogParams } from '../../viewmodel/ConfirmDialogParam';
|
|
|
+import { ConfirmDialog } from '../ConfirmDialog';
|
|
|
+import promptAction from '@ohos.promptAction';
|
|
|
+import ProcessInfo from '../../viewmodel/process/ProcessInfo';
|
|
|
+import { PreviewManager } from '../../common/util/PreviewManager';
|
|
|
+
|
|
|
+const TAG = "sony camera upload"
|
|
|
+
|
|
|
+// 多媒体采集工序
|
|
|
+@Component
|
|
|
+export struct MultiMediaCollect {
|
|
|
+ private scrollerPhoto: Scroller = new Scroller()
|
|
|
+ //
|
|
|
+ @State isExpanded: boolean = false
|
|
|
+ //闪光模式 0:自动 1:开启 2:关闭
|
|
|
+ @State selectedFlashMode:number = 0
|
|
|
+ //选择的照片索引
|
|
|
+ @State selectedPhotoIndex:number = -1
|
|
|
+ //拍照按键缩放
|
|
|
+ @State shootButtonClick:number =1
|
|
|
+ // 旋转角度
|
|
|
+ @State rotateAngle: number = 0
|
|
|
+ // 照片缩放比例
|
|
|
+ @State scaleValue: number = 1
|
|
|
+ // 照片X轴偏移
|
|
|
+ @State offsetX: number = 0
|
|
|
+ // 照片Y轴偏移
|
|
|
+ @State offsetY: number = 0
|
|
|
+ // 照片上次缩放值
|
|
|
+ @State lastScale: number = 1
|
|
|
+ // 照片上次X偏移
|
|
|
+ @State lastOffsetX: number = 0
|
|
|
+ // 照片上次Y偏移
|
|
|
+ @State lastOffsetY: number = 0
|
|
|
+ // 正在上传
|
|
|
+ @State isUploading: boolean = false
|
|
|
+ // 照片列表
|
|
|
+ @State photoList:DrawingInfo[]=[]
|
|
|
+ //双指缩放的中心点X
|
|
|
+ @State pinchCenterX: number = 0;
|
|
|
+ //双指缩放的中心点Y
|
|
|
+ @State pinchCenterY: number = 0;
|
|
|
+ // 获取本地live照片
|
|
|
+ @State commodityPixelMap: PixelMap | null = null;
|
|
|
+ // 拍照动作是否完成
|
|
|
+ @State isCapturing: boolean = false;
|
|
|
+ // 是否停止预览
|
|
|
+ @State isStopView: boolean = false;
|
|
|
+ // 控制帧率
|
|
|
+ @State readTimer:number = 0
|
|
|
+ // 预览操作
|
|
|
+ private previewManager: PreviewManager | null = null;
|
|
|
+
|
|
|
+ // 当前流转卡号
|
|
|
+ @Link seqNo: string
|
|
|
+ // 选中工序id
|
|
|
+ @Link selectOperationId: string
|
|
|
+ // 扫码开工后的生产过程信息
|
|
|
+ @Link process: ProcessInfo
|
|
|
+
|
|
|
+ //创建订阅者
|
|
|
+ subscriber: CommonEventManager.CommonEventSubscriber | null = null;
|
|
|
+ //订阅相机回调
|
|
|
+ subscribeInfo: CommonEventManager.CommonEventSubscribeInfo = { events: ["sonycamera_callback"] };
|
|
|
+
|
|
|
+ //提示确认弹窗
|
|
|
+ commonDialogController: CustomDialogController | null = null;
|
|
|
+ private showConfirmDialog(params: ConfirmDialogParams) {
|
|
|
+ if (this.commonDialogController) {
|
|
|
+ this.commonDialogController.close()
|
|
|
+ }
|
|
|
+
|
|
|
+ this.commonDialogController = new CustomDialogController({
|
|
|
+ builder: ConfirmDialog({
|
|
|
+ title: params.title || '提示',
|
|
|
+ message: params.message,
|
|
|
+ onConfirm: params.onConfirm
|
|
|
+ }),
|
|
|
+ cancel: () => console.log('用户取消操作'),
|
|
|
+ customStyle: true,
|
|
|
+ autoCancel:false,
|
|
|
+ maskColor: 'rgba(0,0,0,0.6)'
|
|
|
+ });
|
|
|
+
|
|
|
+ this.commonDialogController.open();
|
|
|
+ }
|
|
|
+
|
|
|
+ //订阅回调(code=3代表连接成功,code=2代表拍照成功)
|
|
|
+ createSubscriber = async () => {
|
|
|
+ this.subscriber = await CommonEventManager.createSubscriber(this.subscribeInfo);
|
|
|
+ if (this.subscriber) {
|
|
|
+ console.info(TAG, "创建订阅回调成功");
|
|
|
+ CommonEventManager.subscribe(this.subscriber, (err, data) => {
|
|
|
+ if (err?.code) {
|
|
|
+ console.error(TAG, "SubscribeCallBack err=" + JSON.stringify(err));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ console.info(TAG, "SubscribeCallBack data=" + JSON.stringify(data));
|
|
|
+ if (data?.code !== undefined) {
|
|
|
+ switch (data.code) {
|
|
|
+ case 2:
|
|
|
+ this.isCapturing = false
|
|
|
+ this.uploadPhoto(); // 拍照成功
|
|
|
+ break;
|
|
|
+ case 3:
|
|
|
+ console.info(TAG, "开始预览");
|
|
|
+ this.startView(); // 连接成功
|
|
|
+ break;
|
|
|
+ case -1:
|
|
|
+ console.info(TAG,'连接故障')
|
|
|
+ promptAction.showToast({
|
|
|
+ message: '相机连接失败,请检查usb',
|
|
|
+ duration: 3000,
|
|
|
+ })
|
|
|
+ break;
|
|
|
+ case 5:
|
|
|
+ console.info(TAG,'暂停预览')
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //0001:自动闪光 0002:关闭闪光 0003:开启闪光
|
|
|
+ if (data?.parameters?.flash_mode) {
|
|
|
+ const flashMode:string = data.parameters.flash_mode
|
|
|
+ console.info(TAG, `收到闪光模式: ${flashMode}`);
|
|
|
+ switch (flashMode) {
|
|
|
+ case '0001':
|
|
|
+ this.selectedFlashMode = 0
|
|
|
+ break;
|
|
|
+ case '0002':
|
|
|
+ this.selectedFlashMode = 2
|
|
|
+ break;
|
|
|
+ case '0003':
|
|
|
+ this.selectedFlashMode = 1
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ console.warn(TAG, `未知闪光模式: ${flashMode}`);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ //加载照片
|
|
|
+ loadPhotos=async()=>{
|
|
|
+ let res = await ProcessRequest.post('/api/v1/process/media/page', {
|
|
|
+ seqNo:this.seqNo,
|
|
|
+ operationId: this.selectOperationId,
|
|
|
+ processId: this.process.id,
|
|
|
+ pageNo: 1,
|
|
|
+ pageSize: 999999
|
|
|
+ } as RequestParamModel) as DrawingPage;
|
|
|
+ this.photoList=res.records??[]
|
|
|
+ }
|
|
|
+
|
|
|
+ //删除照片
|
|
|
+ deletePhoto=async(photoId:string)=>{
|
|
|
+ let res = await ProcessRequest.post('/api/v1/process/media/del', {
|
|
|
+ id: photoId
|
|
|
+ } as RequestParamModel) as DrawingPage;
|
|
|
+ this.loadPhotos()
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ //旋转照片
|
|
|
+ private rotateImage(angle: number) {
|
|
|
+ this.offsetX = 0;
|
|
|
+ this.offsetY = 0;
|
|
|
+ this.rotateAngle += angle
|
|
|
+ if (this.rotateAngle >= 360) {
|
|
|
+ this.rotateAngle -= 360
|
|
|
+ } else if (this.rotateAngle < 0) {
|
|
|
+ this.rotateAngle += 360
|
|
|
+ }
|
|
|
+ if(this.rotateAngle==90||this.rotateAngle==270)
|
|
|
+ {
|
|
|
+ this.scaleValue=0.63
|
|
|
+ }else {
|
|
|
+ this.scaleValue=1
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 重置图片变换
|
|
|
+ private resetImageTransform() {
|
|
|
+ this.rotateAngle = 0
|
|
|
+ this.scaleValue = 1
|
|
|
+ this.offsetX = 0
|
|
|
+ this.offsetY = 0
|
|
|
+ this.lastScale = 1
|
|
|
+ this.lastOffsetX = 0
|
|
|
+ this.lastOffsetY = 0
|
|
|
+ }
|
|
|
+
|
|
|
+ //连接相机
|
|
|
+ connectCamera = async () => {
|
|
|
+ CommonEventManager.publish("opensession", (err) => {
|
|
|
+ if (err?.code) {
|
|
|
+ console.info(TAG,"Publish openSession err=" + JSON.stringify(err))
|
|
|
+ } else {
|
|
|
+ console.info(TAG,"Publish openSession succeed ")
|
|
|
+ this.queryFlashMode();
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ //查询闪光模式
|
|
|
+ queryFlashMode = async () => {
|
|
|
+ CommonEventManager.publish("queryflashmode", (err) => {
|
|
|
+ if (err?.code) {
|
|
|
+ console.info(TAG,"Publish queryFlashMode err=" + JSON.stringify(err))
|
|
|
+ } else {
|
|
|
+ console.info(TAG,"Publish queryFlashMode succeed ")
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ //开始预览
|
|
|
+ startView=()=>{
|
|
|
+ CommonEventManager.publish("startview", (err) => {
|
|
|
+ if (err?.code) {
|
|
|
+ console.error(TAG, JSON.stringify(err));
|
|
|
+ } else {
|
|
|
+ console.info(TAG, "Publish startView succeed");
|
|
|
+ this.isStopView =false;
|
|
|
+ this.liveShow();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ //停止预览
|
|
|
+ stopView=async()=>{
|
|
|
+ CommonEventManager.publish("stopview", (err) => {
|
|
|
+ if (err?.code) {
|
|
|
+ console.error(TAG, JSON.stringify(err));
|
|
|
+ } else {
|
|
|
+ this.isStopView =true;
|
|
|
+ console.info(TAG, 'publish stopview succeed');
|
|
|
+ if (this.previewManager) {
|
|
|
+ this.previewManager.release();
|
|
|
+ }
|
|
|
+ if (this.readTimer) {
|
|
|
+ clearInterval(this.readTimer);
|
|
|
+ this.readTimer = 0 ;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ //重连相机
|
|
|
+ reconnectCamera=async()=>{
|
|
|
+ this.showConfirmDialog({
|
|
|
+ title: '重连USB',
|
|
|
+ message: `请重连USB后点击确定!`,
|
|
|
+ onConfirm: async()=> {
|
|
|
+ await new Promise<void>((resolve, reject) => {
|
|
|
+ CommonEventManager.publish("stopview", (err) => {
|
|
|
+ if (err) return reject(err);
|
|
|
+ CommonEventManager.publish("closesession", (err) => {
|
|
|
+ err ? reject(err) : resolve();
|
|
|
+ });
|
|
|
+ });
|
|
|
+ });
|
|
|
+ await new Promise<void>((resolve, reject) => {
|
|
|
+ CommonEventManager.publish("reconnect", (err) => {
|
|
|
+ if (err) return reject(err);
|
|
|
+ resolve();
|
|
|
+ });
|
|
|
+ });
|
|
|
+ promptAction.showToast({
|
|
|
+ message: '相机正在重连中...',
|
|
|
+ duration: 3000,
|
|
|
+ });
|
|
|
+ await sleep(3000);
|
|
|
+ await this.connectCamera()
|
|
|
+ //await this.liveShow()
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ liveShow = async () => {
|
|
|
+ let index = 0;
|
|
|
+ let retryCount = 0;
|
|
|
+ const MAX_RETRIES = 1000; // 最大重试次数
|
|
|
+
|
|
|
+ const previewLoop = async () => {
|
|
|
+ if (!this.isStopView && !this.isCapturing) {
|
|
|
+ try {
|
|
|
+ const success = await this.previewManager!.processFrame(index);
|
|
|
+ if (success) {
|
|
|
+ this.commodityPixelMap = await this.previewManager!.getActiveBuffer();
|
|
|
+ retryCount = 0;
|
|
|
+ } else {
|
|
|
+ retryCount++;
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ retryCount++;
|
|
|
+ console.warn(TAG, "预览更新失败:", error);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (retryCount === MAX_RETRIES) {
|
|
|
+ clearInterval(this.readTimer)
|
|
|
+ this.readTimer = 0;
|
|
|
+ console.info(TAG,"GG")
|
|
|
+ return;
|
|
|
+ //this.reconnectCamera();
|
|
|
+ }
|
|
|
+ if (this.readTimer !== 0) { // 检查是否应该继续循环
|
|
|
+ this.readTimer = setTimeout(previewLoop, 50);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ this.readTimer = setTimeout(previewLoop, 50);
|
|
|
+ };
|
|
|
+
|
|
|
+ //断开相机(停止预览->关闭连接)
|
|
|
+ disconnectCamera = async () => {
|
|
|
+ if(!this.isStopView)
|
|
|
+ {
|
|
|
+ await this.stopView()
|
|
|
+ }
|
|
|
+ CommonEventManager.publish("closesession", (err) => {
|
|
|
+ if (err?.code) {
|
|
|
+ console.info(TAG,"Publish closesession err=" + JSON.stringify(err))
|
|
|
+ } else {
|
|
|
+ console.info(TAG,"Publish closesession succeed ")
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ //拍照(停止预览->拍照->开始预览)
|
|
|
+ takePhoto = async () => {
|
|
|
+ this.isStopView = true;
|
|
|
+ this.isCapturing = true;
|
|
|
+ CommonEventManager.publish("stopview", (err) => {
|
|
|
+ if (err?.code) {
|
|
|
+ console.info(TAG,"Publish stopview err=" + JSON.stringify(err));
|
|
|
+ } else {
|
|
|
+ console.info(TAG,"Publish Publish stopview succeed");
|
|
|
+ CommonEventManager.publish("shoot", (err) => {
|
|
|
+ if (err?.code) {
|
|
|
+ console.info(TAG,"Publish shoot error=" + JSON.stringify(err));
|
|
|
+ } else {
|
|
|
+ console.info(TAG,"Publish Publish shoot succeed");
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ //设置闪光模式
|
|
|
+ setFlashMode = (mode: 'openflash' | 'closeflash' | 'autoflash') => {
|
|
|
+ this.isStopView = true;
|
|
|
+ CommonEventManager.publish("stopview", (err) => {
|
|
|
+ if (err?.code) {
|
|
|
+ console.info(TAG,"Publish stopview err=" + JSON.stringify(err));
|
|
|
+ } else {
|
|
|
+ console.info(TAG,"Publish Publish stopview succeed");
|
|
|
+ CommonEventManager.publish(mode, (err) => {
|
|
|
+ if (err?.code) {
|
|
|
+ console.info(TAG,"Publish"+mode+" error=" + JSON.stringify(err));
|
|
|
+ } else {
|
|
|
+ console.info(TAG,"Publish "+mode+" succeed");
|
|
|
+ CommonEventManager.publish("startview", (err) => {
|
|
|
+ this.isStopView = false;
|
|
|
+ if (err?.code) {
|
|
|
+ console.info(TAG,"Publish startview error=" + JSON.stringify(err));
|
|
|
+ }else{
|
|
|
+ console.info(TAG,"Publish Publish startview succeed");
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ //上传照片
|
|
|
+ uploadPhoto=()=>{
|
|
|
+ console.info(TAG,"start upload:");
|
|
|
+ let imageUri: string = "/data/storage/el2/base/haps/entry/files/image_base64.txt"
|
|
|
+ try {
|
|
|
+ uploadInstance.startUploadBase64(imageUri, () => {
|
|
|
+ this.loadPhotos()
|
|
|
+ this.isUploading = false
|
|
|
+ this.startView();//上传完恢复预览
|
|
|
+ })
|
|
|
+ } catch (error) {
|
|
|
+ console.error(TAG,"upload failed:", error.code);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private adjustOffsetWithAnimation() {
|
|
|
+ const isRotated = (this.rotateAngle === 90 || this.rotateAngle === 270);
|
|
|
+ let moveScaleY = (this.scaleValue - (isRotated ? 0.667 : 1)) / 2;
|
|
|
+ let moveScaleX = (this.scaleValue - (isRotated ? 1.50 : 1)) / 2;
|
|
|
+ let maxOffsetX = (this.scaleValue<1.5&&isRotated) ?this.offsetX: (isRotated ? 520 : 820) * moveScaleX;
|
|
|
+ let maxOffsetY = (isRotated ? 820 : 520) * moveScaleY;
|
|
|
+ // let maxOffsetX = (this.scaleValue<1.5&&isRotated) ?this.offsetX: (isRotated ? 1038 : 1635) * moveScaleX;
|
|
|
+ // let maxOffsetY = (isRotated ? 1635 : 1038) * moveScaleY;
|
|
|
+ const clampedX = Math.max(-maxOffsetX, Math.min(maxOffsetX, this.offsetX));
|
|
|
+ const clampedY = Math.max(-maxOffsetY, Math.min(maxOffsetY, this.offsetY));
|
|
|
+ if (this.offsetX !== clampedX || this.offsetY !== clampedY) {
|
|
|
+ animateTo({
|
|
|
+ duration: 100,
|
|
|
+ curve: Curve.EaseOut
|
|
|
+ }, () => {
|
|
|
+ this.offsetX = clampedX;
|
|
|
+ this.offsetY = clampedY;
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ async aboutToAppear() {
|
|
|
+ this.previewManager = new PreviewManager(getContext(this));
|
|
|
+ this.loadPhotos();
|
|
|
+ await this.createSubscriber();
|
|
|
+ await sleep(50)
|
|
|
+ await this.connectCamera();
|
|
|
+ uploadInstance.uploadParams = {
|
|
|
+ token: "your_token_here", // 替换为实际 token
|
|
|
+ operationMediaId: this.selectOperationId, // 默认值
|
|
|
+ processId:this.process.id, // 根据需求设置
|
|
|
+ seqNo:this.seqNo, // 根据需求设置
|
|
|
+ methodName: "", // 根据需求设置
|
|
|
+ apiUrlPath: "/api/v1/process/media/add", // 默认上传接口
|
|
|
+ method: "post", // 默认方法
|
|
|
+ stationIP: "", // 根据需求设置
|
|
|
+ messageKey: "" // 根据需求设置
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ aboutToDisappear(): void {
|
|
|
+ this.disconnectCamera()
|
|
|
+ if (this.subscriber) {
|
|
|
+ CommonEventManager.unsubscribe(this.subscriber);
|
|
|
+ }
|
|
|
+ if (this.commodityPixelMap) {
|
|
|
+ this.commodityPixelMap.release();
|
|
|
+ this.commodityPixelMap = null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ build() {
|
|
|
+ Row() {
|
|
|
+ Stack(){
|
|
|
+ if (this.commodityPixelMap) {
|
|
|
+ if (this.selectedPhotoIndex === -1) {
|
|
|
+ Image(this.commodityPixelMap)
|
|
|
+ .width('100%')
|
|
|
+ .height('100%')
|
|
|
+ .objectFit(ImageFit.Fill)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(this.isUploading){
|
|
|
+ Column() {
|
|
|
+ Text('正在上传中...')
|
|
|
+ .fontSize($r('app.float.fontSize_30'))
|
|
|
+ .margin({bottom:'10%'})
|
|
|
+ LoadingProgress()
|
|
|
+ .color(Color.Blue)
|
|
|
+ .width('25%')
|
|
|
+ .width('25%')
|
|
|
+ }
|
|
|
+ .height('30%')
|
|
|
+ .width('25%')
|
|
|
+ .backgroundColor(Color.White)
|
|
|
+ .borderRadius($r('app.float.virtualSize_16'))
|
|
|
+ .justifyContent(FlexAlign.Center)
|
|
|
+ }
|
|
|
+ if(this.selectedPhotoIndex === -1){
|
|
|
+ Row() {
|
|
|
+ Image(
|
|
|
+ this.selectedFlashMode === 0 ? $r('app.media.process_flash_auto') :
|
|
|
+ this.selectedFlashMode === 1 ? $r('app.media.process_flash_open') :
|
|
|
+ $r('app.media.process_flash_close')
|
|
|
+ )
|
|
|
+ .width($r('app.float.virtualSize_48'))
|
|
|
+ .height($r('app.float.virtualSize_48'))
|
|
|
+ .enabled(!this.isUploading)
|
|
|
+ .onClick(() => {
|
|
|
+ this.isExpanded = !this.isExpanded
|
|
|
+ })
|
|
|
+ .margin({right:'5%'})
|
|
|
+ if (this.isExpanded) {
|
|
|
+ Row() {
|
|
|
+ Row(){
|
|
|
+ Text('自动')
|
|
|
+ .fontSize($r('app.float.fontSize_24'))
|
|
|
+ .fontColor(this.selectedFlashMode===0?$r('app.color.FFFFFF'):$r('app.color.60FFFFFF'))
|
|
|
+ }
|
|
|
+ .width('33.3%')
|
|
|
+ .height('100%')
|
|
|
+ .justifyContent(FlexAlign.Center)
|
|
|
+ .borderRadius($r('app.float.virtualSize_16'))
|
|
|
+ .backgroundColor(this.selectedFlashMode===0?$r('app.color.0A84FF'):$r('app.color.60000000'))
|
|
|
+ .onClick(() => {
|
|
|
+ this.setFlashMode('autoflash')
|
|
|
+ this.isExpanded = false
|
|
|
+ this.selectedFlashMode = 0
|
|
|
+ })
|
|
|
+ Row(){
|
|
|
+ Text('开启')
|
|
|
+ .fontSize($r('app.float.fontSize_24'))
|
|
|
+ .fontColor(this.selectedFlashMode===1?$r('app.color.FFFFFF'):$r('app.color.60FFFFFF'))
|
|
|
+ }
|
|
|
+ .width('33.3%')
|
|
|
+ .height('100%')
|
|
|
+ .justifyContent(FlexAlign.Center)
|
|
|
+ .borderRadius($r('app.float.virtualSize_16'))
|
|
|
+ .backgroundColor(this.selectedFlashMode===1?$r('app.color.0A84FF'):$r('app.color.60000000'))
|
|
|
+ .onClick(() => {
|
|
|
+ this.setFlashMode('openflash')
|
|
|
+ this.isExpanded = false
|
|
|
+ this.selectedFlashMode = 1
|
|
|
+ })
|
|
|
+
|
|
|
+ Row(){
|
|
|
+ Text('关闭')
|
|
|
+ .fontSize($r('app.float.fontSize_24'))
|
|
|
+ .fontColor(this.selectedFlashMode===2?$r('app.color.FFFFFF'):$r('app.color.60FFFFFF'))
|
|
|
+ }
|
|
|
+ .width('33.3%')
|
|
|
+ .height('100%')
|
|
|
+ .justifyContent(FlexAlign.Center)
|
|
|
+ .borderRadius($r('app.float.virtualSize_16'))
|
|
|
+ .backgroundColor(this.selectedFlashMode===2?$r('app.color.0A84FF'):$r('app.color.60000000'))
|
|
|
+ .onClick(() => {
|
|
|
+ this.setFlashMode('closeflash')
|
|
|
+ this.isExpanded = false
|
|
|
+ this.selectedFlashMode = 2
|
|
|
+ })
|
|
|
+ }
|
|
|
+ .animation({ duration: 300, curve: Curve.EaseOut }) // 展开动画
|
|
|
+ .backgroundColor($r('app.color.60000000'))
|
|
|
+ .borderRadius($r('app.float.virtualSize_16'))
|
|
|
+ .width('85%')
|
|
|
+ .height('100%')
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .justifyContent(FlexAlign.Start)
|
|
|
+ .alignItems(VerticalAlign.Bottom)
|
|
|
+ .position({ x: '2%', y: '92%' })
|
|
|
+ .height('5%')
|
|
|
+ .width('24%')
|
|
|
+ Image(this.shootButtonClick===1?$r('app.media.process_no_shoot'):$r('app.media.process_shoot'))
|
|
|
+ .width($r('app.float.virtualSize_88'))
|
|
|
+ .height($r('app.float.virtualSize_88'))
|
|
|
+ .scale({ x: this.shootButtonClick, y: this.shootButtonClick })
|
|
|
+ .borderRadius($r('app.float.fontSize_16'))
|
|
|
+ .enabled(!this.isUploading)
|
|
|
+ .animation({
|
|
|
+ duration: 200,
|
|
|
+ curve: Curve.Linear
|
|
|
+ })
|
|
|
+ .onClick(() => {
|
|
|
+ this.shootButtonClick = 0.9;
|
|
|
+ setTimeout(() => {
|
|
|
+ this.shootButtonClick = 1;
|
|
|
+ }, 200);
|
|
|
+ if(this.isUploading){
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.isUploading = true
|
|
|
+ this.takePhoto();
|
|
|
+ })
|
|
|
+ .position({ x: '48%', y: '90%' })
|
|
|
+ Row(){
|
|
|
+ Text("重连相机")
|
|
|
+ .fontColor($r('app.color.FFFFFF'))
|
|
|
+ .fontSize($r('app.float.fontSize_24'))
|
|
|
+ }
|
|
|
+ .width('10%')
|
|
|
+ .height('6%')
|
|
|
+ .backgroundColor($r('app.color.60000000'))
|
|
|
+ .position({ x: '88%', y: '91%' })
|
|
|
+ .borderRadius($r('app.float.virtualSize_16'))
|
|
|
+ .justifyContent(FlexAlign.Center)
|
|
|
+ .onClick(()=>{
|
|
|
+ this.reconnectCamera()
|
|
|
+ })
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ Stack() {
|
|
|
+ Image(CommonConstants.PICTURE_URL_PREFIX + this.photoList[this.selectedPhotoIndex].filePath)
|
|
|
+ .width('100%')
|
|
|
+ .height('100%')
|
|
|
+ // .onComplete((event) => {
|
|
|
+ // console.info(TAG,"width:"+event!.componentWidth +"height:"+ event!.componentHeight)
|
|
|
+ // }) // 获取Image组件的长宽(除以1.5获取vp)
|
|
|
+ .objectFit(ImageFit.Fill)
|
|
|
+ .rotate({ angle: this.rotateAngle })
|
|
|
+ .scale({ x: this.scaleValue, y: this.scaleValue })
|
|
|
+ .borderRadius($r('app.float.virtualSize_16'))
|
|
|
+ .translate({ x: this.offsetX, y: this.offsetY })
|
|
|
+ .gesture(
|
|
|
+ GestureGroup(GestureMode.Exclusive,
|
|
|
+ // 替换原有的 PinchGesture 部分代码
|
|
|
+ PinchGesture()
|
|
|
+ .onActionStart((event: GestureEvent) => {
|
|
|
+ this.lastScale = this.scaleValue;
|
|
|
+ this.lastOffsetX = this.offsetX;
|
|
|
+ this.lastOffsetY = this.offsetY;
|
|
|
+ // 记录双指中心点(相对于图片中心)
|
|
|
+ this.pinchCenterX = event.pinchCenterX - 285 - 820 / 2; //rk3588
|
|
|
+ this.pinchCenterY = event.pinchCenterY - 121 - 520 / 2; //rk3588
|
|
|
+ // this.pinchCenterX = event.pinchCenterX - 1090 / 2; //rk3568
|
|
|
+ // this.pinchCenterY = event.pinchCenterY - 692 / 2; //rk3568
|
|
|
+ // console.info(TAG,event.pinchCenterX,TAG,event.pinchCenterY)
|
|
|
+ // console.info(TAG,this.pinchCenterX,TAG,this.pinchCenterY)
|
|
|
+ })
|
|
|
+ .onActionUpdate((event: GestureEvent) => {
|
|
|
+ const newScale = this.lastScale * event.scale;
|
|
|
+ //保持双指中心点不变
|
|
|
+ const scaleRatio = newScale / this.lastScale;
|
|
|
+ const newOffsetX = this.lastOffsetX + (1 - scaleRatio) * this.pinchCenterX;
|
|
|
+ const newOffsetY = this.lastOffsetY + (1 - scaleRatio) * this.pinchCenterY;
|
|
|
+
|
|
|
+ this.offsetX = newOffsetX;
|
|
|
+ this.offsetY = newOffsetY;
|
|
|
+ this.scaleValue = newScale;
|
|
|
+ })
|
|
|
+ .onActionEnd(() => {
|
|
|
+ // 缩放最小比例为1
|
|
|
+ if (this.scaleValue < 1) {
|
|
|
+ // 旋转90°或者270°的最小缩小比例为0.667
|
|
|
+ if(this.rotateAngle==90||this.rotateAngle==270) {
|
|
|
+ if(this.scaleValue<0.667){
|
|
|
+ this.scaleValue = 0.667
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ this.scaleValue = 1
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 缩放最大比例为3
|
|
|
+ if (this.scaleValue > 3) this.scaleValue = 3
|
|
|
+ this.adjustOffsetWithAnimation()
|
|
|
+ }),
|
|
|
+
|
|
|
+ // 单指滑动手势
|
|
|
+ PanGesture()
|
|
|
+ .onActionStart(() => {
|
|
|
+ if(this.rotateAngle === 90 || this.rotateAngle === 270)
|
|
|
+ {
|
|
|
+ if (this.scaleValue <= 0.667)
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ if (this.scaleValue <= 1) return;
|
|
|
+ }
|
|
|
+ this.lastOffsetX = this.offsetX;
|
|
|
+ this.lastOffsetY = this.offsetY;
|
|
|
+ })
|
|
|
+ .onActionUpdate((event: GestureEvent) => {
|
|
|
+ if(this.rotateAngle === 90 || this.rotateAngle === 270)
|
|
|
+ {
|
|
|
+ if (this.scaleValue <= 0.667)
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ if (this.scaleValue <= 1) return;
|
|
|
+ }
|
|
|
+ let dx = event.offsetX;
|
|
|
+ let dy = event.offsetY;
|
|
|
+ const sensitivity = 0.5 * this.scaleValue;
|
|
|
+ // 临时计算新位置
|
|
|
+ let newOffsetX = this.lastOffsetX;
|
|
|
+ let newOffsetY = this.lastOffsetY;
|
|
|
+ newOffsetX += dx * sensitivity;
|
|
|
+ newOffsetY += dy * sensitivity;
|
|
|
+ this.offsetX = newOffsetX;
|
|
|
+ this.offsetY = newOffsetY;
|
|
|
+ //console.info(TAG,this.offsetX,TAG,this.offsetY)
|
|
|
+ })
|
|
|
+ .onActionEnd(() => {
|
|
|
+ const isRotated = (this.rotateAngle === 90 || this.rotateAngle === 270);
|
|
|
+ if(isRotated)
|
|
|
+ {
|
|
|
+ if(this.scaleValue<=1.5)
|
|
|
+ {
|
|
|
+ this.offsetX = 0
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ if (this.scaleValue <= 1) {
|
|
|
+ // 如果缩放比例<=1,直接重置位置
|
|
|
+ this.offsetX = 0;
|
|
|
+ this.offsetY = 0;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.adjustOffsetWithAnimation()
|
|
|
+ })
|
|
|
+ )
|
|
|
+ )
|
|
|
+ }
|
|
|
+ .width('100%')
|
|
|
+ .height('100%')
|
|
|
+ .borderRadius($r('app.float.virtualSize_16'))
|
|
|
+ .clip(true)
|
|
|
+ Row()
|
|
|
+ {
|
|
|
+ Row(){
|
|
|
+ Image($r('app.media.process_back_camera'))
|
|
|
+ .width($r('app.float.virtualSize_80'))
|
|
|
+ .height($r('app.float.virtualSize_80'))
|
|
|
+ .onClick(()=>{
|
|
|
+ this.selectedPhotoIndex=-1
|
|
|
+ this.startView()
|
|
|
+ })
|
|
|
+ }
|
|
|
+ .width('10%')
|
|
|
+ .justifyContent(FlexAlign.Start)
|
|
|
+ Row({space:20}){
|
|
|
+ Image($r("app.media.process_photo_reset"))
|
|
|
+ .width($r('app.float.virtualSize_80'))
|
|
|
+ .height($r('app.float.virtualSize_80'))
|
|
|
+ .onClick(()=>{
|
|
|
+ this.resetImageTransform()
|
|
|
+ })
|
|
|
+ Image($r('app.media.process_photo_turn_left'))
|
|
|
+ .width($r('app.float.virtualSize_80'))
|
|
|
+ .height($r('app.float.virtualSize_80'))
|
|
|
+ .onClick(()=>{
|
|
|
+ this.rotateImage(-90)
|
|
|
+ })
|
|
|
+ Image($r('app.media.process_photo_turn_right'))
|
|
|
+ .width($r('app.float.virtualSize_80'))
|
|
|
+ .height($r('app.float.virtualSize_80'))
|
|
|
+ .onClick(()=>{
|
|
|
+ this.rotateImage(90)
|
|
|
+ })
|
|
|
+ Image($r('app.media.process_photo_delete'))
|
|
|
+ .width($r('app.float.virtualSize_80'))
|
|
|
+ .height($r('app.float.virtualSize_80'))
|
|
|
+ .onClick(()=>{
|
|
|
+ this.showConfirmDialog({
|
|
|
+ title: '删除照片',
|
|
|
+ message: `确定要删除照片吗?`,
|
|
|
+ onConfirm: ()=> {
|
|
|
+ const photosNum = this.photoList.length
|
|
|
+ const photoId=this.photoList[this.selectedPhotoIndex].id
|
|
|
+ //如果是图册最后一张照片,显示前一张照片,没有照片则返回拍照页面
|
|
|
+ if(this.selectedPhotoIndex===photosNum-1)
|
|
|
+ {
|
|
|
+ this.selectedPhotoIndex--
|
|
|
+ }
|
|
|
+ this.deletePhoto(photoId)
|
|
|
+ if(this.selectedPhotoIndex==-1)
|
|
|
+ {
|
|
|
+ this.startView()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ })
|
|
|
+ }.width('88%')
|
|
|
+ .justifyContent(FlexAlign.End)
|
|
|
+ .margin({right :'2%'})
|
|
|
+ }.width('98%')
|
|
|
+ .height('10%')
|
|
|
+ .position({x:'2%',y:'90%'})
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .width('86%')
|
|
|
+ .height('100%')
|
|
|
+ .backgroundColor($r('app.color.000000'))
|
|
|
+ .border({width:2})
|
|
|
+ Column(){
|
|
|
+ List({ space: 8,scroller:this.scrollerPhoto }) {
|
|
|
+ ForEach(this.photoList, (item: DrawingInfo, index) => {
|
|
|
+ ListItem() {
|
|
|
+ Column({space:4}){
|
|
|
+ Column(){
|
|
|
+ Image(CommonConstants.PICTURE_URL_PREFIX+item.filePath)
|
|
|
+ .objectFit(ImageFit.Fill)
|
|
|
+ .borderRadius($r('app.float.virtualSize_16'))
|
|
|
+ .height('97%')
|
|
|
+ .width('98%')
|
|
|
+ .opacity(index === this.selectedPhotoIndex ? 0.8 : 1) // 20% 透明度
|
|
|
+ }
|
|
|
+ .backgroundColor(index === this.selectedPhotoIndex ? $r('app.color.30D158') : '')
|
|
|
+ .width('90%')
|
|
|
+ .justifyContent(FlexAlign.Center)
|
|
|
+ .alignItems(HorizontalAlign.Center)
|
|
|
+ .borderRadius($r('app.float.virtualSize_16'))
|
|
|
+ .height('85%')
|
|
|
+ Text(`${item.updated}`)
|
|
|
+ .fontSize($r('app.float.fontSize_12'))
|
|
|
+ .fontColor($r('app.color.FFFFFF'))
|
|
|
+ .width('90%')
|
|
|
+ .textAlign(TextAlign.Start)
|
|
|
+ }
|
|
|
+ .width('100%')
|
|
|
+ .height('100%')
|
|
|
+ .justifyContent(FlexAlign.Start)
|
|
|
+ .alignItems(HorizontalAlign.Center)
|
|
|
+ .enabled(!this.isUploading)
|
|
|
+ .onClick(()=>{
|
|
|
+ this.selectedPhotoIndex = index;
|
|
|
+ this.resetImageTransform()
|
|
|
+ this.stopView();
|
|
|
+
|
|
|
+ })
|
|
|
+ }.height('19%')
|
|
|
+ .margin({bottom:'2%'})
|
|
|
+ })
|
|
|
+ }
|
|
|
+ .width('100%')
|
|
|
+ .margin({top:'2%',bottom:'2%'})
|
|
|
+ .height('96%')
|
|
|
+ }
|
|
|
+ .width('14%')
|
|
|
+ .height('100%')
|
|
|
+ }
|
|
|
+ .width('100%')
|
|
|
+ .height('100%')
|
|
|
+ //.backgroundColor($r('app.color.10FFFFFF'))
|
|
|
+ .borderRadius($r('app.float.virtualSize_16'))
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function sleep(ms: number): Promise<void> {
|
|
|
+ return new Promise((resolve) => setTimeout(resolve, ms));
|
|
|
+}
|
|
|
+
|