提交 434c65f8 编写于 作者: DCloud-yyl's avatar DCloud-yyl

Merge branch 'alpha'

# Conflicts:
#	package.json
{ {
"id": "hello-uniapp-x", "id": "hello-uniapp-x",
"displayName": "hello-uniapp-x", "name": "hello-uniapp-x",
"description": "演示 uni-app x 框架的组件、接口、模板", "displayName": "hello-uniapp-x",
"keywords": [ "version": "1.0.8",
"uni-app-x", "description": "演示 uni-app x 框架的组件、接口、模板",
"uni-app2.0", "repository": "https://gitcode.net/dcloud/hello-uni-app-x",
"示例工程" "keywords": [
], "uni-app-x",
"version": "1.0.6" "uni-app2.0",
} "示例工程"
],
"author": "",
"license": "MIT",
"dependencies": {},
"engines": {
"HBuilderX": "^3.98"
},
"dcloudext": {
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "不采集任何数据",
"permissions": "- android.permission.INTERNET \n- android.permission.READ_EXTERNAL_STORAGE \n- android.permission.WRITE_EXTERNAL_STORAGE \n- android.permission.ACCESS_FINE_LOCATION \n- android.permission.ACCESS_COARSE_LOCATION \n- android.permission.ACCESS_NETWORK_STATE \n- android.permission.READ_MEDIA_IMAGES \n- android.permission.READ_MEDIA_VIDEO \n- android.permission.READ_MEDIA_VISUAL_USER_SELECTED \n- android.permission.CAMERA \n- android.permission.READ_PHONE_STATE \n- android.permission.REQUEST_INSTALL_PACKAGES"
},
"npmurl": "",
"type": "uniapp-template-project"
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "n",
"app-nvue": "n",
"app-uvue": "y"
},
"H5-mobile": {
"Safari": "n",
"Android Browser": "n",
"微信浏览器(Android)": "n",
"QQ浏览器(Android)": "n"
},
"H5-pc": {
"Chrome": "n",
"IE": "n",
"Edge": "n",
"Firefox": "n",
"Safari": "n"
},
"小程序": {
"微信": "n",
"阿里": "n",
"百度": "n",
"字节跳动": "n",
"QQ": "n",
"京东": "n",
"钉钉": "n",
"快手": "n",
"飞书": "n"
},
"快应用": {
"华为": "n",
"联盟": "n"
},
"Vue": {
"vue2": "n",
"vue3": "y"
}
}
}
}
}
...@@ -154,14 +154,13 @@ export default { ...@@ -154,14 +154,13 @@ export default {
open: false, open: false,
pages: [] as Page[], pages: [] as Page[],
}, },
// { {
// id: 'half-screen', id: 'half-screen',
// url: 'half-screen', url: 'half-screen',
// name: '半屏弹窗', name: '半屏弹窗',
// open: false, open: false,
// enable: false, pages: [] as Page[],
// pages: [] as Page[], },
// },
{ {
id: 'drop-card', id: 'drop-card',
url: 'drop-card', url: 'drop-card',
......
<template> <template>
<view class="page"> <view id="page" class="page">
<text>TouchEvent还有细节需要优化,需支持拦截事件分发逻辑解决拖拽半屏窗口引起内容滚动的问题</text> <text
<button class="bottomButton" @click="switchHalfScreen(true)">打开弹窗</button> style="margin: 10px">半屏弹窗,演示了弹出层内scroll-view滚动到顶时由滚变拖。本效果是通过监听TouchEvent实现,当半屏窗口移动时禁用scroll-view的滚动,避免两者的冲突。</text>
<view ref="halfScreen" class="halfScreen" @touchstart="onHalfTouchStart" @touchmove="onHalfTouchMove" @touchend="onHalfTouchEnd"> <button class="bottomButton" @click="switchHalfScreen(true)">打开弹窗</button>
<view class="halfTitle" >半屏弹窗标题</view> <view id="halfScreen" class="halfScreen" @touchstart="onHalfTouchStart" @touchmove="onHalfTouchMove"
<scroll-view ref="halfScroll" class="halfScroll" @scroll="onScroll" bounce="true"> @touchend="onHalfTouchEnd">
<view v-for="(item,index) in list" :key="index" class="item"> <view class="halfTitle">半屏弹窗标题</view>
half screen content-{{item}} <scroll-view id="halfScroll" class="halfScroll" rebound="true">
</view> <view v-for="(item,index) in list" :key="index" class="item">
</scroll-view> half screen content-{{item}}
</view> </view>
</view> </scroll-view>
</template> </view>
</view>
<script> </template>
export default {
data() { <script>
return { export default {
list: ['1','2','3','4','5','6','7','8','9','10','11','12','13','14','15'], data() {
totalHeight: 0, //总高度 return {
halfMove: false, //是否Move,响应TouchMove list: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15'],
halfScreenY: 0, //响应TouchMove的起始点Y坐标 totalHeight: 0, //总高度
halfOffset: 0, //偏移的位置,translateY halfMove: false, //是否Move,响应TouchMove
halfHeight: 0, //高度 halfScreenY: 0, //响应TouchMove的起始点Y坐标
lastY: 0, //上次 halfOffset: 0, //偏移的位置,translateY
lastY2: 0, // halfHeight: 0, //高度
bAnimation: false, //是否动画 lastY: 0, //上次
halfNode: null as Element | null, lastY2: 0, //
scrollNode: null as Element | null bAnimation: false, //是否动画
} halfNode: null as Element | null,
}, scrollNode: null as Element | null
methods: { }
onHalfTouchStart(_:TouchEvent) { },
this.halfNode?.style?.setProperty('transitionDuration', 0); methods: {
//console.log('Title TouchStart: ', e); onHalfTouchStart(_ : TouchEvent) {
}, this.halfNode?.style?.setProperty('transitionDuration', 0);
onHalfTouchMove(e:TouchEvent) { },
if(this.bAnimation){//容错处理 onHalfTouchMove(e : TouchEvent) {
return; if (this.bAnimation) {//容错处理
} return;
let top:number = this.scrollNode?.getAttribute('scrollTop') as number }
let p = e.touches[0]; let top : number = this.scrollNode?.scrollTop ?? 0;
this.lastY2 = this.lastY; let p = e.touches[0];
this.lastY = p.screenY; this.lastY2 = this.lastY;
if(top <= 0.01 || this.halfMove){ this.lastY = p.screenY;
if(this.halfScreenY == 0){ if (top <= 0.01 || this.halfMove) {
this.halfScreenY = p.screenY; if (this.halfScreenY == 0) {
} this.halfScreenY = p.screenY;
let offset = p.screenY-this.halfScreenY; }
if(offset > 0){ let offset = p.screenY - this.halfScreenY;
this.halfMove = true; if (offset > 0) {//向下滚动
this.halfNode?.style?.setProperty('transform','translateY('+offset+'px)'); this.halfMove = true;
this.halfOffset = offset; this.scrollNode?.setAttribute('scroll-y', 'false');
}else if(this.lastY2>this.lastY && this.halfOffset>0){//容错触发向下滚动的误差 this.halfNode?.style?.setProperty('transform', 'translateY(' + offset.toFixed(2) + 'px)');
offset = this.halfScreenY-p.screenY; this.halfOffset = offset;
if(offset>this.halfOffset){ } else if (this.halfOffset > 0) {//向上滚动
offset = this.halfOffset; offset = this.halfScreenY - p.screenY;
} if (offset > this.halfOffset) {
this.halfNode?.style?.setProperty('transform','translateY('+offset+'px)'); offset = 0;
this.halfOffset = offset; this.halfMove = false;
} this.scrollNode?.setAttribute('scroll-y', 'true');
} }
//console.log('TouchMove', e.target); this.halfNode?.style?.setProperty('transform', 'translateY(' + offset.toFixed(2) + 'px)');
}, this.halfOffset = offset;
onHalfTouchEnd(_:TouchEvent) { }
if(this.bAnimation){//容错处理 }
return; },
} onHalfTouchEnd(_ : TouchEvent) {
let top:number = this.scrollNode?.getAttribute('scrollTop') as number this.halfScreenY = 0;
let bHide = (this.halfHeight-this.halfOffset)<this.halfHeight/4; if (this.bAnimation) {//容错处理
if(bHide){ return;
bHide = this.lastY2>0&&this.lastY2<=this.lastY; }
}else if(top <= 0.01){ let top : number = this.scrollNode?.scrollTop ?? 0;
bHide = (this.lastY-this.lastY2)>3; //向下滑动计算加速度判断是否关闭,简单处理未考虑时间 let bHide = (this.halfHeight - this.halfOffset) < this.halfHeight / 4;
} if (bHide) {
if(bHide){ bHide = this.lastY2 > 0 && this.lastY2 <= this.lastY;
this.switchHalfScreen(false); } else if (top <= 0.01) {
}else{ bHide = (this.lastY - this.lastY2) > 3; //向下滑动计算加速度判断是否关闭,简单处理未考虑时间
this.resumeHalfScreen(); }
} if (bHide) {
}, this.switchHalfScreen(false);
onScroll(_: ScrollEvent) { } else if (this.halfOffset > 0) {
//console.log('onScroll: ', e); this.resumeHalfScreen();
}, }
switchHalfScreen(show:boolean) { },
if(show&&('visible'==this.halfNode?.style?.getPropertyValue('visibility'))){//容错处理 switchHalfScreen(show : boolean) {
console.log('qucik click button!!!'); if (show && ('visible' == this.halfNode?.style?.getPropertyValue('visibility'))) {//容错处理
return; console.log('qucik click button!!!');
} return;
this.halfMove = false; }
this.halfScreenY = 0; this.halfMove = false;
this.halfOffset = 0; this.scrollNode?.setAttribute('scroll-y', 'true');
let top = this.totalHeight; this.halfScreenY = 0;
let time = 300; this.halfOffset = 0;
if(show){ let top = this.totalHeight;
top = this.totalHeight*30/100; //计算显示的位置 let time = 300;
this.halfNode?.style?.setProperty('visibility','visible'); if (show) {
this.halfNode?.style?.setProperty('transitionTimingFunction','ease-in-out'); top = this.totalHeight * 30 / 100; //计算显示的位置
}else{ this.halfNode?.style?.setProperty('visibility', 'visible');
this.halfNode?.style?.setProperty('transitionTimingFunction','linear'); this.halfNode?.style?.setProperty('transitionTimingFunction', 'ease-in-out');
time *= (this.halfHeight/this.totalHeight); //计算关闭动画时间 } else {
} this.halfNode?.style?.setProperty('transitionTimingFunction', 'linear');
this.halfNode?.style?.setProperty('transitionDuration', time.toFixed(0)); time *= (this.halfHeight / this.totalHeight); //计算关闭动画时间
this.halfNode?.style?.setProperty('transitionProperty','top'); }
this.halfNode?.style?.setProperty('top', top.toFixed(0)); this.halfNode?.style?.setProperty('transitionDuration', time.toFixed(0));
setTimeout(()=>{ this.halfNode?.style?.setProperty('transitionProperty', 'top');
if(!show){ this.halfNode?.style?.setProperty('top', top.toFixed(2));
this.halfNode?.style?.setProperty('visibility','hidden'); setTimeout(() => {
this.halfNode?.style?.setProperty('transitionDuration', 0); if (!show) {
this.halfNode?.style?.setProperty('transform',''); this.halfNode?.style?.setProperty('visibility', 'hidden');
} this.halfNode?.style?.setProperty('transitionDuration', 0);
this.halfNode?.style?.setProperty('transitionProperty',''); this.halfNode?.style?.setProperty('transform', '');
this.bAnimation = false; }
}, time) this.halfNode?.style?.setProperty('transitionProperty', '');
this.bAnimation = true; this.bAnimation = false;
}, }, time)
resumeHalfScreen() { this.bAnimation = true;
let time = 300;//(500*this.halfOffset/this.halfHeight).toFixed(0); //回弹动画时间 },
this.halfNode?.style?.setProperty('transitionDuration',time.toFixed(0)); resumeHalfScreen() {
this.halfNode?.style?.setProperty('transitionTimingFunction','ease-in-out'); let time = 300;//(500*this.halfOffset/this.halfHeight).toFixed(0); //回弹动画时间
this.halfNode?.style?.setProperty('transitionProperty','transform'); this.halfNode?.style?.setProperty('transitionDuration', time.toFixed(0));
this.halfNode?.style?.setProperty('transform','translateY(0px)'); this.halfNode?.style?.setProperty('transitionTimingFunction', 'ease-in-out');
this.halfMove = false; this.halfNode?.style?.setProperty('transitionProperty', 'transform');
this.halfScreenY = 0; this.halfNode?.style?.setProperty('transform', 'translateY(0px)');
this.halfOffset = 0; this.halfMove = false;
setTimeout(()=>{ this.scrollNode?.setAttribute('scroll-y', 'true');
this.bAnimation = false; this.halfScreenY = 0;
}, time) this.halfOffset = 0;
this.bAnimation = true; setTimeout(() => {
} this.bAnimation = false;
}, this.halfNode?.style?.setProperty('transitionProperty', '');
onReady() { }, time)
this.halfNode = this.$refs['halfScreen'] as Element; this.bAnimation = true;
this.halfHeight = this.halfNode!.getBoundingClientRect().height; }
this.scrollNode = this.$refs['halfScroll'] as Element; },
onReady() {
this.totalHeight = uni.getWindowInfo().windowHeight; this.halfNode = uni.getElementById('halfScreen');
this.halfNode?.style?.setProperty('top', this.totalHeight.toString()); this.scrollNode = uni.getElementById('halfScroll');
},
// onResize() { this.halfHeight = this.halfNode!.getBoundingClientRect().height;
// this.halfHeight = this.halfNode!.getBoundingClientRect().height; this.totalHeight = uni.getElementById('page')?.getBoundingClientRect()?.height ?? 0;//uni.getWindowInfo().windowHeight
// this.totalHeight = uni.getWindowInfo().windowHeight; this.halfNode?.style?.setProperty('top', this.totalHeight.toFixed(2));
// } },
} onResize() {
</script> this.halfHeight = this.halfNode?.getBoundingClientRect()?.height ?? 0;
this.totalHeight = uni.getWindowInfo().windowHeight;
<style> this.halfNode?.style?.setProperty('top', this.totalHeight.toFixed(2));
.page { this.halfNode?.style?.setProperty('visibility', 'hidden');
flex: 1; }
background-color: darkgrey; }
} </script>
.bottomButton {
position: absolute; <style>
width: 100%; .page {
bottom: 0px; flex: 1;
} background-color: darkgrey;
.halfScreen { }
position: absolute;
top: 100%; .bottomButton {
width: 100%; position: absolute;
height: 70%; width: 100%;
transition-timing-function: ease-in-out; /*ease ease-in ease-out ease-in-out linear step-start step-end*/ bottom: 0px;
transition-property: top; }
transition-duration: 0;
visibility: hidden; .halfScreen {
} position: absolute;
.halfTitle { top: 100%;
align-items: center; width: 100%;
justify-content: center; height: 70%;
height: 48px; transition-timing-function: ease-in-out;
background-color: cornflowerblue; /*ease ease-in ease-out ease-in-out linear step-start step-end*/
border-radius: 10px 10px 0 0; transition-property: top;
} transition-duration: 0;
.halfScroll { visibility: hidden;
background-color: ghostwhite; }
}
.item { .halfTitle {
height: 100px; align-items: center;
} justify-content: center;
height: 48px;
background-color: ghostwhite;
border-radius: 10px 10px 0 0;
}
.halfScroll {
background-color: white;
}
.item {
height: 100px;
}
</style> </style>
## 0.7.4(2023-11-29)
- 修复 uni-app-x 项目中由上版引发的无法升级的Bug
## 0.7.3(2023-11-27)
- 修复 在 uni-app x 中无更新时报错的Bug
## 0.7.2(2023-11-20)
- 新增 插件根目录 utils 文件夹中新增 check-update-nvue.js 文件(vue2 的 nvue 页面请引用该文件)
## 0.7.1(2023-11-17) ## 0.7.1(2023-11-17)
- 修复 运行至浏览器 ts 语法报错 - 修复 运行至浏览器 ts 语法报错
## 0.7.0(2023-11-10) ## 0.7.0(2023-11-10)
......
{ {
"id": "uni-upgrade-center-app", "id": "uni-upgrade-center-app",
"displayName": "升级中心 uni-upgrade-center - App", "displayName": "升级中心 uni-upgrade-center - App",
"version": "0.7.1", "version": "0.7.4",
"description": "uni升级中心 - 客户端检查更新", "description": "uni升级中心 - 客户端检查更新",
"keywords": [ "keywords": [
"uniCloud", "uniCloud",
......
...@@ -78,14 +78,22 @@ export default function () : Promise<UniUpgradeCenterResult> { ...@@ -78,14 +78,22 @@ export default function () : Promise<UniUpgradeCenterResult> {
data: data data: data
}).then(res => { }).then(res => {
const code = res.result['code'] const code = res.result['code']
if (['Int', 'Long', 'number'].includes(typeof code) && (code as number) < 0) { const codeIsNumber = ['Int', 'Long', 'number'].includes(typeof code)
reject({ if (codeIsNumber) {
code: res.result['code'], if ((code as number) == 0) {
message: res.result['message'] reject({
}) code: res.result['code'],
} else { message: res.result['message']
const result = JSON.parse<UniUpgradeCenterResult>(JSON.stringify(res.result)) as UniUpgradeCenterResult })
resolve(result) } else if (code < 0) {
reject({
code: res.result['code'],
message: res.result['message']
})
} else {
const result = JSON.parse<UniUpgradeCenterResult>(JSON.stringify(res.result)) as UniUpgradeCenterResult
resolve(result)
}
} }
}).catch<void>((err : any | null) => { }).catch<void>((err : any | null) => {
const error = err as UniCloudError const error = err as UniCloudError
......
function callCheckVersion() {
// #ifdef APP-PLUS
return new Promise((resolve, reject) => {
plus.runtime.getProperty(plus.runtime.appid, function(widgetInfo) {
let data = {
action: 'checkVersion',
appid: plus.runtime.appid,
appVersion: plus.runtime.version,
wgtVersion: widgetInfo.version
}
uniCloud.callFunction({
name: 'uni-upgrade-center',
data,
success: (e) => {
resolve(e)
},
fail: (error) => {
reject(error)
}
})
})
})
// #endif
// #ifndef APP-PLUS
return new Promise((resolve, reject) => {})
// #endif
}
// 推荐再App.vue中使用
const PACKAGE_INFO_KEY = '__package_info__'
export default function() {
// #ifdef APP-PLUS
return new Promise((resolve, reject) => {
callCheckVersion().then(async (e) => {
if (!e.result) return;
const {
code,
message,
is_silently, // 是否静默更新
url, // 安装包下载地址
platform, // 安装包平台
type // 安装包类型
} = e.result;
// 此处逻辑仅为实例,可自行编写
if (code > 0) {
// 腾讯云和阿里云下载链接不同,需要处理一下,阿里云会原样返回
const {
fileList
} = await uniCloud.getTempFileURL({
fileList: [url]
});
if (fileList[0].tempFileURL)
e.result.url = fileList[0].tempFileURL;
resolve(e)
// 静默更新,只有wgt有
if (is_silently) {
uni.downloadFile({
url: e.result.url,
success: res => {
if (res.statusCode == 200) {
// 下载好直接安装,下次启动生效
plus.runtime.install(res.tempFilePath, {
force: false
});
}
}
});
return;
}
/**
* 提示升级一
* 使用 uni.showModal
*/
// return updateUseModal(e.result)
/**
* 提示升级二
* 官方适配的升级弹窗,可自行替换资源适配UI风格
*/
uni.setStorageSync(PACKAGE_INFO_KEY, e.result)
uni.navigateTo({
url: `/uni_modules/uni-upgrade-center-app/pages/upgrade-popup?local_storage_key=${PACKAGE_INFO_KEY}`,
fail: (err) => {
console.error('更新弹框跳转失败', err)
uni.removeStorageSync(PACKAGE_INFO_KEY)
}
})
return
} else if (code < 0) {
// TODO 云函数报错处理
console.error(message)
return reject(e)
}
return resolve(e)
}).catch(err => {
// TODO 云函数报错处理
console.error(err.message)
reject(err)
})
});
// #endif
}
/**
* 使用 uni.showModal 升级
*/
function updateUseModal(packageInfo) {
const {
title, // 标题
contents, // 升级内容
is_mandatory, // 是否强制更新
url, // 安装包下载地址
platform, // 安装包平台
type // 安装包类型
} = packageInfo;
let isWGT = type === 'wgt'
let isiOS = !isWGT ? platform.includes('iOS') : false;
let confirmText = isiOS ? '立即跳转更新' : '立即下载更新'
return uni.showModal({
title,
content: contents,
showCancel: !is_mandatory,
confirmText,
success: res => {
if (res.cancel) return;
// 安装包下载
if (isiOS) {
plus.runtime.openURL(url);
return;
}
uni.showToast({
title: '后台下载中……',
duration: 1000
});
// wgt 和 安卓下载更新
downloadTask = uni.downloadFile({
url,
success: res => {
if (res.statusCode !== 200) {
console.error('下载安装包失败', err);
return;
}
// 下载好直接安装,下次启动生效
plus.runtime.install(res.tempFilePath, {
force: false
}, () => {
if (is_mandatory) {
//更新完重启app
plus.runtime.restart();
return;
}
uni.showModal({
title: '安装成功是否重启?',
success: res => {
if (res.confirm) {
//更新完重启app
plus.runtime.restart();
}
}
});
}, err => {
uni.showModal({
title: '更新失败',
content: err
.message,
showCancel: false
});
});
}
});
}
});
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册