Kaynağa Gözat

解决app端弹框被文件预览弹框遮挡问题

liurongli 1 ay önce
ebeveyn
işleme
f4af1592c3

+ 3 - 2
components/customPopupDialog.vue

@@ -1,6 +1,6 @@
 <template>
 	<!-- 自定义弹框组件 -->
-	<uni-popup ref="popupDialog" :is-mask-click="isMaskClick" style="z-index: 99;">
+	<uni-popup ref="popupDialog" :is-mask-click="isMaskClick" style="z-index: 99999;">
 		<view :class="['dialog_wrap',popupType]" :style="{ width: popupType=='center'?`${dialogWidth}rpx`:'100%' }">
 			<view class="dialog_title" v-if="showTitle">
 				<view class="dialog_title_lt">
@@ -57,7 +57,7 @@
 			default: true
 		}
 	})
-	const emit = defineEmits(['DialogConfirm']);
+	const emit = defineEmits(['DialogConfirm','DialogClose']);
 	const popupDialog = ref(null);
 	const popupType = ref('center');//弹出方式 默认中间显示
 
@@ -69,6 +69,7 @@
 	//关闭弹窗
 	const CloseDialog = () => {
 		popupDialog.value.close();
+		emit('DialogClose')
 	}
 
 	// 点击确定,只通知父组件,子组件不主动关闭!

+ 15 - 4
pages/workspace/index.vue

@@ -9,17 +9,16 @@
 					<view class="system_grid_with_large">
 						<view class="large_card" @click="handleSystemClick(largeCard)">
 							<view class="card_dot" >
-								<img :src="getModulePermission(largeCard.id) == 1 ? './static/image/workspace/throughIcon.png' : '/static/image/workspace/authorityIcon.png'" class="dot_img" alt="">
+								<img :src="getModulePermission(largeCard.id) == 1 ? './static/image/workspace/throughIcon.png' : './static/image/workspace/authorityIcon.png'" class="dot_img" alt="">
 							</view>
 							<image :src="largeCard.image" class="large_icon" mode="aspectFit"></image>
 							<text class="large_name">{{ largeCard.name }}</text>
 						</view>
-
 						<view class="right_top_grid">
 							<view v-for="(item, index) in rightTopCards" :key="index" class="small_item"
 								@click="handleSystemClick(item)">
 								<view class="card_dot" >
-									<img :src="getModulePermission(item.id) == 1 ? './static/image/workspace/throughIcon.png' : '/static/image/workspace/authorityIcon.png'" class="dot_img" alt="">
+									<img :src="getModulePermission(item.id) == 1 ? './static/image/workspace/throughIcon.png' : './static/image/workspace/authorityIcon.png'" class="dot_img" alt="">
 								</view>
 								<image :src="item.image" class="small_icon" mode="aspectFit"></image>
 								<text class="small_name">{{ item.name }}</text>
@@ -31,7 +30,7 @@
 						<view v-for="(item, index) in bottomCards" :key="index" class="small_item"
 							@click="handleSystemClick(item)">
 							<view class="card_dot" >
-								<img :src="getModulePermission(item.id) == 1 ? './static/image/workspace/throughIcon.png' : '/static/image/workspace/authorityIcon.png'" class="dot_img" alt="">
+								<img :src="getModulePermission(item.id) == 1 ? './static/image/workspace/throughIcon.png' : './static/image/workspace/authorityIcon.png'" class="dot_img" alt="">
 							</view>
 							<image :src="item.image" class="small_icon" mode="aspectFit"></image>
 							<text class="small_name">{{ item.name }}</text>
@@ -617,6 +616,10 @@ $shadow-sm: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
 					width: 32rpx;
 					height: 32rpx;
 					z-index: 100;
+					img{
+						width: 32rpx;
+						height: 32rpx;
+					}
 				}
 
 				.dot-green {
@@ -664,6 +667,10 @@ $shadow-sm: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
 				width: 32rpx;
 				height: 32rpx;
 				z-index: 100;
+				img{
+					width: 32rpx;
+					height: 32rpx;
+				}
 			}
 
 			.dot-green {
@@ -710,6 +717,10 @@ $shadow-sm: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
 				width: 12rpx;
 				height: 12rpx;
 				border-radius: 50%;
+				img{
+					width: 12rpx;
+					height: 12rpx;
+				}
 			}
 
 			.dot-green {

BIN
static/image/workspace/authorityIcon.png


BIN
static/image/workspace/throughIcon.png


+ 275 - 0
uni_modules/cjx-previewOffice/components/cjx-previewOffice/cjx-previewOffice(源码).vue

@@ -0,0 +1,275 @@
+<template>
+	<view :class="['container',{'noPpopup':!props.showCloseBtn}]">
+		<view class="file_content" @click="open">
+			<slot></slot>
+		</view>
+		
+		<view class="cjx-previewOffice-container" :style="{ height: pagesHeight }">
+			<template v-if="props.showHeader">
+				<view class="cjx-previewOffice-header" v-if="!$slots.header">
+					<view class="icon" ></view>
+					<view class="name">
+						{{ name }}
+					</view>
+					<uni-icons class="icon" @click="close" type="close" size="40" style="color: #999999;font-size: 40rpx;"></uni-icons>
+					<!-- <icon class="icon" @click="close" type="cancel"></icon> -->
+				</view>
+				
+				<view class="cjx-previewOffice-header" v-else>
+					<slot name="header"></slot>
+				</view>
+			</template>
+			
+			<view class="webview">
+				<!-- #ifdef H5 -->
+					<iframe
+						class="cjx-previewOffice-iframe"
+						:webview-styles="webviewStyles"
+						:src="`${typeMapSrc[type]}${encodeURIComponent(props.value)}&safeBottom=${safeBottom}`"
+					/>
+				<!-- #endif -->
+				
+			</view>
+		</view>
+		
+		<view class="cjx-previewOffice-mask"
+			:style="{
+				zIndex: pagesHeight !== '0' ? zIndex : '-1',
+				opacity: pagesHeight !== '0' ? 1 : 0,
+			}"
+			@click="closeOnClickModalChange"
+			>
+			
+		</view>
+	</view>
+	
+</template>
+
+
+<script lang="ts" setup>
+import uniIcons from '@/uni_modules/uni-icons/components/uni-icons/uni-icons.vue';
+import { onMounted, ref } from 'vue'
+import type { CSSProperties } from 'vue'
+import { previewOfficeProps, FileType } from './interface'
+// <!-- #ifdef H5 -->
+// <!-- #endif -->
+const props = defineProps(previewOfficeProps())
+
+const showWebviewArr: FileType[] = ['excel', 'pdf', 'word', 'txt']
+
+ 
+ const webviewStyles = ref<CSSProperties>({
+	 zIndex: '9999',
+ })
+ 
+const typeMapSrc = {
+	word: 'uni_modules/cjx-previewOffice/static/hybrid/word.html?file=',
+	pdf: 'uni_modules/cjx-previewOffice/static/hybrid/pdf/web/viewer.html?file=',
+	excel: 'uni_modules/cjx-previewOffice/static/hybrid/excel.html?file=',
+	txt: 'uni_modules/cjx-previewOffice/static/hybrid/txt.html?file=',
+}
+	
+const pagesHeight = ref<string>('0')
+
+
+const safeBottom = ref<number>(0)
+let webview: any = null
+
+
+const open = () => {
+	if (pagesHeight.value === '85vh') {
+		return
+	}
+	
+	// #ifdef H5
+	setTimeout(() => {
+		pagesHeight.value = '85vh'
+	})
+	// #endif
+	
+	// #ifdef APP-PLUS
+	// console.log(11, uni.getSystemInfoSync())
+	const { statusBarHeight, windowHeight, screenHeight } = uni.getSystemInfoSync()
+	pagesHeight.value = Number(windowHeight) - Number(statusBarHeight) + 'px'
+	let headerFootHeight = 44;
+	if(!props.showCloseBtn){
+		headerFootHeight = rpxToPx(220) + rpxToPx(170)
+	}
+	
+	webview = plus.webview.create(
+		`${typeMapSrc[props.type]}${encodeURIComponent(props.value)}&safeBottom=${safeBottom.value}`,
+		'id', 
+		{ 
+			bottom: !props.showCloseBtn?rpxToPx(170):0,
+			height: windowHeight - statusBarHeight - headerFootHeight,
+		},
+
+	); 
+	const pages = getCurrentPages();
+	const page: any = pages[pages.length - 1];
+	const currentWebview = page.$getAppWebview();
+	
+	currentWebview.append(webview);
+	webview.show('id', 'slide-in-bottom')
+	// #endif
+}
+const rpxToPx = (rpx)=> {
+	const sys = uni.getSystemInfoSync()
+	return rpx * sys.screenWidth / 750
+}
+const close = () => {
+	
+	pagesHeight.value = '0'
+
+	// #ifdef APP-PLUS
+	webview.setStyle({
+		height: 0,
+	})
+	webview.close('slide-in-bottom')
+	// #endif
+}
+
+
+const closeOnClickModalChange = () => {
+	if (props.closeOnClickModal) {
+		pagesHeight.value = '0'
+		// #ifdef APP-PLUS
+		webview.setStyle({
+			height: 0,
+		})
+		webview.close('slide-in-bottom')
+		// #endif
+	}
+}
+
+defineExpose({
+	open,
+	close
+})
+
+onMounted(() => {
+	safeBottom.value = 0
+	// #ifdef H5
+	
+	// #endif
+	
+	// #ifdef APP-PLUS
+	uni.getSystemInfo({
+	  success: function (res) {
+	    console.log(res.safeArea); // 输出安全区域信息
+			safeBottom.value = res.screenHeight - res.safeArea.bottom; // 计算底部安全区域高度
+	    console.log('底部安全区域高度:', safeBottom.value);
+	  }
+	});
+	// #endif
+	// if (props.type === 'image') {
+	// 	uni.previewImage({
+	// 		urls: ['https://img2.baidu.com/it/u=412966049,488862975&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=800'],
+	// 	})
+	// }
+	
+})
+
+</script>
+
+<style lang="scss" >
+	iframe {
+		// position: absolute;
+	  // top: 44px !important;
+	  // height: calc(100vh - 44px) !important;
+		// position: absolute;
+		z-index: 9999 !important;
+		border:0;
+		top: calc(15vh + 44px) !important;
+		// height: calc(100% - 70rpx) !important;
+	}
+	.container{
+		display: flex;
+		width: 100%;
+		&.noPpopup{
+			height: 100%;
+			.file_content{
+				display: none;
+			}
+			.cjx-previewOffice-container{
+				position: static;
+				height: 100% !important;
+			}
+			.webview{
+				height: 100% !important;
+			}
+			.cjx-previewOffice-iframe{
+				top:0 !important;
+				height: 100% !important;
+			}
+			.cjx-previewOffice-mask{
+				display: none;
+			}
+		}
+	}
+	.file_content{
+		display: flex;
+		width: 100%;
+	}
+	.cjx-previewOffice-iframe {
+		// z-index: 9999 !important;
+		width: 100vw;
+		top: 44px !important;
+		height: calc(100% - 12px) !important;
+	}
+	.cjx-previewOffice-container {
+		position: fixed;
+		left: 0px;
+		overflow: hidden;
+		z-index: 998;
+		// height: 100vh;
+		width: 100vw;
+		bottom: 0;
+		transition: all ease 0.2s;
+		background-color: #fff;
+		// position: relative;
+		.cjx-previewOffice-header {
+			background-color: #fff;
+			// position: fixed;
+			// top: 0;
+			height: 44px;
+			z-index: 9999;
+			display: flex;
+			align-items: center;
+			width: 100%;
+			padding: 0 16rpx;
+			box-sizing: border-box;
+			.name {
+				width: calc(100% - 80rpx);
+				text-align: center;
+				overflow: hidden;
+				text-overflow: ellipsis;
+				white-space: nowrap;
+				padding-right: 10rpx;
+				box-sizing: border-box;
+				
+			}
+			.icon {
+				width: 40rpx;
+				color:#333;
+			}
+		}
+	}
+	
+	.webview {
+		// height: calc(100vh - 44px) !important;
+		height: calc(100% - 70rpx) !important;
+	}
+	
+	.cjx-previewOffice-mask {
+		position: fixed;
+		z-index: 990;
+		background-color: rgba(0, 0, 0, 0.4);
+		top: 0;
+		left: 0;
+		width: 100vw;
+		height: 100vh;
+		opacity: 0;
+		transition: all ease 0.2s;
+	}
+</style>

+ 28 - 28
uni_modules/cjx-previewOffice/components/cjx-previewOffice/cjx-previewOffice.vue

@@ -21,13 +21,15 @@
 			</template>
 			
 			<view class="webview">
-				<!-- #ifdef H5 -->
+				<!-- APP‑PLUS 和 H5共用iframe,v‑if销毁节点解决安卓点击穿透 -->
+				<!-- 删除 #ifdef H5 -->
 					<iframe
+						v-if="pagesHeight != '0'"
 						class="cjx-previewOffice-iframe"
 						:webview-styles="webviewStyles"
 						:src="`${typeMapSrc[type]}${encodeURIComponent(props.value)}&safeBottom=${safeBottom}`"
 					/>
-				<!-- #endif -->
+				<!-- 删除 #endif -->
 				
 			</view>
 		</view>
@@ -59,7 +61,7 @@ const showWebviewArr: FileType[] = ['excel', 'pdf', 'word', 'txt']
 
  
  const webviewStyles = ref<CSSProperties>({
-	 zIndex: '9999',
+	 zIndex: '999',
  })
  
 const typeMapSrc = {
@@ -77,41 +79,39 @@ let webview: any = null
 
 
 const open = () => {
+	
 	if (pagesHeight.value === '85vh') {
 		return
 	}
-	
-	// #ifdef H5
 	setTimeout(() => {
 		pagesHeight.value = '85vh'
 	})
-	// #endif
 	
-	// #ifdef APP-PLUS
-	// console.log(11, uni.getSystemInfoSync())
-	const { statusBarHeight, windowHeight, screenHeight } = uni.getSystemInfoSync()
-	pagesHeight.value = Number(windowHeight) - Number(statusBarHeight) + 'px'
-	let headerFootHeight = 44;
-	if(!props.showCloseBtn){
-		headerFootHeight = rpxToPx(220) + rpxToPx(170)
-	}
+	// // #ifdef APP-PLUS
+	// // console.log(11, uni.getSystemInfoSync())
+	// const { statusBarHeight, windowHeight, screenHeight } = uni.getSystemInfoSync()
+	// pagesHeight.value = Number(windowHeight) - Number(statusBarHeight) + 'px'
+	// let headerFootHeight = 44;
+	// if(!props.showCloseBtn){
+	// 	headerFootHeight = rpxToPx(220) + rpxToPx(170)
+	// }
 	
-	webview = plus.webview.create(
-		`${typeMapSrc[props.type]}${encodeURIComponent(props.value)}&safeBottom=${safeBottom.value}`,
-		'id', 
-		{ 
-			bottom: !props.showCloseBtn?rpxToPx(170):0,
-			height: windowHeight - statusBarHeight - headerFootHeight,
-		},
+	// webview = plus.webview.create(
+	// 	`${typeMapSrc[props.type]}${encodeURIComponent(props.value)}&safeBottom=${safeBottom.value}`,
+	// 	'id', 
+	// 	{ 
+	// 		bottom: !props.showCloseBtn?rpxToPx(170):0,
+	// 		height: windowHeight - statusBarHeight - headerFootHeight
+	// 	},
 
-	); 
-	const pages = getCurrentPages();
-	const page: any = pages[pages.length - 1];
-	const currentWebview = page.$getAppWebview();
+	// ); 
+	// const pages = getCurrentPages();
+	// const page: any = pages[pages.length - 1];
+	// const currentWebview = page.$getAppWebview();
 	
-	currentWebview.append(webview);
-	webview.show('id', 'slide-in-bottom')
-	// #endif
+	// currentWebview.append(webview);
+	// webview.show('id', 'slide-in-bottom')
+	// // #endif
 }
 const rpxToPx = (rpx)=> {
 	const sys = uni.getSystemInfoSync()