Browse Source

fix: 退出登录

test2
xuesinan 4 years ago
parent
commit
6922f24084
  1. 81
      App.vue
  2. 1
      CHANGELOG.md
  3. 5
      components/Render/Render.vue
  4. 4
      manifest.json
  5. 42
      pages.json
  6. 32
      pages/index/index.vue
  7. 6
      store/user/mutations.js
  8. 4
      uni_modules/uni-config-center/changelog.md
  9. 80
      uni_modules/uni-config-center/package.json
  10. 93
      uni_modules/uni-config-center/readme.md
  11. 1
      uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/index.js
  12. 9
      uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/package.json
  13. 72
      uni_modules/uni-id/changelog.md
  14. 84
      uni_modules/uni-id/package.json
  15. 33
      uni_modules/uni-id/readme.md
  16. 201
      uni_modules/uni-id/uniCloud/cloudfunctions/common/uni-id/LICENSE.md
  17. 1
      uni_modules/uni-id/uniCloud/cloudfunctions/common/uni-id/index.js
  18. 16
      uni_modules/uni-id/uniCloud/cloudfunctions/common/uni-id/package.json
  19. 53
      uni_modules/uni-upgrade-center-app/changelog.md
  20. BIN
      uni_modules/uni-upgrade-center-app/images/app_update_close.png
  21. BIN
      uni_modules/uni-upgrade-center-app/images/bg_top.png
  22. 83
      uni_modules/uni-upgrade-center-app/package.json
  23. 500
      uni_modules/uni-upgrade-center-app/pages/upgrade-popup.vue
  24. 18
      uni_modules/uni-upgrade-center-app/pages_init.json
  25. 121
      uni_modules/uni-upgrade-center-app/readme.md
  26. 9
      uni_modules/uni-upgrade-center-app/uniCloud/cloudfunctions/check-version/check-version.param.json
  27. 167
      uni_modules/uni-upgrade-center-app/uniCloud/cloudfunctions/check-version/index.js
  28. 29
      uni_modules/uni-upgrade-center-app/utils/call-check-version.js
  29. 155
      uni_modules/uni-upgrade-center-app/utils/check-update.js

81
App.vue

@ -238,4 +238,85 @@ page {
position: absolute; position: absolute;
} }
} }
/* #ifdef H5 */
.uni-modal {
position: fixed;
z-index: 999;
width: 80%;
max-width: 300px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: #ffffff;
text-align: center;
border-radius: 3px;
overflow: hidden;
}
.uni-modal__bd {
padding: 1.3em 1.6em 1.3em;
min-height: 40px;
font-size: 15px;
line-height: 1.4;
word-wrap: break-word;
word-break: break-all;
white-space: pre-wrap;
color: #999999;
max-height: 400px;
overflow-x: hidden;
overflow-y: auto;
}
.uni-modal__ft {
position: relative;
line-height: 48px;
font-size: 18px;
display: flex;
}
.uni-modal__btn {
display: block;
flex: 1;
color: #3cc51f;
text-decoration: none;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
position: relative;
cursor: pointer;
}
.uni-modal__ft:after {
content: ' ';
position: absolute;
left: 0;
top: 0;
right: 0;
height: 1px;
border-top: 1px solid #d5d5d6;
color: #d5d5d6;
transform-origin: 0 0;
transform: scaleY(0.5);
}
.uni-modal__btn:after {
content: ' ';
position: absolute;
left: 0;
top: 0;
width: 1px;
bottom: 0;
border-left: 1px solid #d5d5d6;
color: #d5d5d6;
transform-origin: 0 0;
transform: scaleX(0.5);
}
.uni-modal__btn_default {
color: #353535;
}
.uni-modal__btn_primary {
color: #007aff;
}
/* #endif */
</style> </style>

1
CHANGELOG.md

@ -39,6 +39,7 @@
- | 时间轴调整 | [81d2500](https://101.201.226.163:50022/TALL/TALL-MUI-4/commits/81d2500) - | 时间轴调整 | [81d2500](https://101.201.226.163:50022/TALL/TALL-MUI-4/commits/81d2500)
- | 时间轴接口 | [a95d005](https://101.201.226.163:50022/TALL/TALL-MUI-4/commits/a95d005) - | 时间轴接口 | [a95d005](https://101.201.226.163:50022/TALL/TALL-MUI-4/commits/a95d005)
- | 时间轴页面 | [e926b75](https://101.201.226.163:50022/TALL/TALL-MUI-4/commits/e926b75) - | 时间轴页面 | [e926b75](https://101.201.226.163:50022/TALL/TALL-MUI-4/commits/e926b75)
- | 时间轴优化 | [77a137e](https://101.201.226.163:50022/TALL/TALL-MUI-4/commits/77a137e)
- | 时间轴展示 | [8b1b380](https://101.201.226.163:50022/TALL/TALL-MUI-4/commits/8b1b380) - | 时间轴展示 | [8b1b380](https://101.201.226.163:50022/TALL/TALL-MUI-4/commits/8b1b380)
- | 使用uview完成api请求 | [1b3efd8](https://101.201.226.163:50022/TALL/TALL-MUI-4/commits/1b3efd8) - | 使用uview完成api请求 | [1b3efd8](https://101.201.226.163:50022/TALL/TALL-MUI-4/commits/1b3efd8)
- | 手机号登录 | [a198527](https://101.201.226.163:50022/TALL/TALL-MUI-4/commits/a198527) - | 手机号登录 | [a198527](https://101.201.226.163:50022/TALL/TALL-MUI-4/commits/a198527)

5
components/Render/Render.vue

@ -85,7 +85,9 @@ export default {
methods: { methods: {
// //
async getPlugin() { async getPlugin() {
if (this.allPlugin) {
this.pluginLists = JSON.parse(this.allPlugin); this.pluginLists = JSON.parse(this.allPlugin);
this.pluginLists.forEach(item => { this.pluginLists.forEach(item => {
if (this.pluginId === item.id) { if (this.pluginId === item.id) {
this.flag = true; this.flag = true;
@ -93,6 +95,9 @@ export default {
this.show = true; this.show = true;
} }
}); });
} else {
console.log(this.pluginLists);
}
if (this.flag) { if (this.flag) {
this.$nextTick(() => { this.$nextTick(() => {

4
manifest.json

@ -1,8 +1,8 @@
{ {
"name" : "时物链条", "name" : "时物链条",
"appid" : "__UNI__6207504", "appid" : "__UNI__3CBCFFF",
"description" : "", "description" : "",
"versionName" : "1.0.0", "versionName" : "1.0.3",
"versionCode" : "100", "versionCode" : "100",
"transformPx" : false, "transformPx" : false,
/* 5+App */ /* 5+App */

42
pages.json

@ -1,6 +1,5 @@
{ {
"pages": [ "pages": [{
{
"path": "pages/index/index", "path": "pages/index/index",
"style": { "style": {
"navigationBarText": "TALL", "navigationBarText": "TALL",
@ -73,42 +72,49 @@
"style": { "style": {
"navigationBarTitleText": "404" "navigationBarTitleText": "404"
} }
} }, {
,{
"path": "pages/audit/audit", "path": "pages/audit/audit",
"style" : "style": {
{
"navigationBarTitleText": "个人管理", "navigationBarTitleText": "个人管理",
"enablePullDownRefresh": false "enablePullDownRefresh": false
} }
} }, {
,{
"path": "pages/uidispose/uidispose", "path": "pages/uidispose/uidispose",
"style" : "style": {
{
"navigationBarTitleText": "ui配置", "navigationBarTitleText": "ui配置",
"enablePullDownRefresh": false "enablePullDownRefresh": false
} }
} }, {
,{
"path": "pages/exarresources/exarresources", "path": "pages/exarresources/exarresources",
"style" : "style": {
{
"navigationBarTitleText": "域资源管理", "navigationBarTitleText": "域资源管理",
"enablePullDownRefresh": false "enablePullDownRefresh": false
} }
} }, {
,{
"path": "pages/projectVersion/projectVersion", "path": "pages/projectVersion/projectVersion",
"style" : "style": {
{
"navigationBarTitleText": "项目版本管理", "navigationBarTitleText": "项目版本管理",
"enablePullDownRefresh": false "enablePullDownRefresh": false
} }
},
{
"path": "uni_modules/uni-upgrade-center-app/pages/upgrade-popup",
"style": {
"disableScroll": true,
"app-plus": {
"backgroundColorTop": "transparent",
"background": "transparent",
"titleNView": false,
"scrollIndicator": false,
"popGesture": "none",
"animationType": "fade-in",
"animationDuration": 200
}
}
} }
], ],
"globalStyle": { "globalStyle": {

32
pages/index/index.vue

@ -30,7 +30,7 @@
</view> </view>
<view class="login-box absolute" @click="toLogin"> <view class="login-box absolute" @click="toLogin">
<text v-if="!userInfo">游客</text> <text v-if="!userInfo || !userInfo.id">游客</text>
<image v-else src="../../static/headimg4.png" mode=""></image> <image v-else src="../../static/headimg4.png" mode=""></image>
</view> </view>
<!-- <u-button class="mt-4" @click="toLogin">登录</u-button> --> <!-- <u-button class="mt-4" @click="toLogin">登录</u-button> -->
@ -47,6 +47,9 @@
import { reactive, computed, watchEffect, ref } from 'vue'; import { reactive, computed, watchEffect, ref } from 'vue';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import upApp from '../../uni_modules/uni-upgrade-center-app/utils/check-update.js';
upApp();
const store = useStore(); const store = useStore();
const token = computed(() => store.state.user.token); const token = computed(() => store.state.user.token);
@ -60,15 +63,16 @@
// days: [], // days: [],
}); });
const user = uni.$storage.getStorageSync('user');
if (!userInfo.value && user) {
store.commit('user/setUser', JSON.parse(user));
}
getProjects(); getProjects();
// handleFindPoint(); // handleFindPoint();
// token // token
watchEffect(() => { watchEffect(() => {
const user = uni.$storage.getStorageSync('user');
if (!userInfo.value && user) {
store.commit('user/setUser', JSON.parse(user));
}
// if (!token.value) return; // if (!token.value) return;
// if (token.value) { // if (token.value) {
// getProjects(); // getProjects();
@ -145,35 +149,29 @@
// data.calendar.initDate(); // data.calendar.initDate();
// } // }
function toLogin() { async function toLogin() {
if (!userInfo.value) { if (!userInfo.value) {
uni.navigateTo({ uni.navigateTo({
url: '/pages/user/login' url: '/pages/user/login'
}); });
} else { } else {
uni.showModal({ try{
content: '是否退出登录', await uni.$ui.showModal('', '是否退出登录', true)
success: ({ confirm }) => {
if (confirm) {
signout(); signout();
} catch(e) {
console.log(e);
} }
} }
})
}
} }
/** /**
* 退出登录 * 退出登录
*/ */
function signout() { function signout() {
try {
store.commit('user/setToken', ''); store.commit('user/setToken', '');
store.commit('user/setUser', ''); store.commit('user/setUser', null);
uni.$storage.setStorageSync('anyringToken', ''); uni.$storage.setStorageSync('anyringToken', '');
uni.$storage.setStorageSync('user', ''); uni.$storage.setStorageSync('user', '');
} catch (e) {
//TODO handle the exception
}
} }
</script> </script>

6
store/user/mutations.js

@ -14,10 +14,8 @@ const mutations = {
* @param {object} user * @param {object} user
*/ */
setUser(state, user) { setUser(state, user) {
if (!user) return; // if (!user) return;
state.user = { state.user = user;
...user,
};
}, },
/** /**

4
uni_modules/uni-config-center/changelog.md

@ -0,0 +1,4 @@
## 0.0.2(2021-04-16)
- 修改插件package信息
## 0.0.1(2021-03-15)
- 初始化项目

80
uni_modules/uni-config-center/package.json

@ -0,0 +1,80 @@
{
"id": "uni-config-center",
"displayName": "uni-config-center",
"version": "0.0.2",
"description": "uniCloud 配置中心",
"keywords": [
"配置",
"配置中心"
],
"repository": "",
"engines": {
"HBuilderX": "^3.1.0"
},
"dcloudext": {
"category": [
"uniCloud",
"云函数模板"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": ""
},
"directories": {
"example": "../../../scripts/dist"
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "u",
"app-nvue": "u"
},
"H5-mobile": {
"Safari": "u",
"Android Browser": "u",
"微信浏览器(Android)": "u",
"QQ浏览器(Android)": "u"
},
"H5-pc": {
"Chrome": "u",
"IE": "u",
"Edge": "u",
"Firefox": "u",
"Safari": "u"
},
"小程序": {
"微信": "u",
"阿里": "u",
"百度": "u",
"字节跳动": "u",
"QQ": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}

93
uni_modules/uni-config-center/readme.md

@ -0,0 +1,93 @@
# 为什么使用uni-config-center
实际开发中很多插件需要配置文件才可以正常运行,如果每个插件都单独进行配置的话就会产生下面这样的目录结构
```bash
cloudfunctions
└─────common 公共模块
├─plugin-a // 插件A对应的目录
│ ├─index.js
│ ├─config.json // plugin-a对应的配置文件
│ └─other-file.cert // plugin-a依赖的其他文件
└─plugin-b // plugin-b对应的目录
├─index.js
└─config.json // plugin-b对应的配置文件
```
假设插件作者要发布一个项目模板,里面使用了很多需要配置的插件,无论是作者发布还是用户使用都是一个大麻烦。
uni-config-center就是用了统一管理这些配置文件的,使用uni-config-center后的目录结构如下
```bash
cloudfunctions
└─────common 公共模块
├─plugin-a // 插件A对应的目录
│ └─index.js
├─plugin-b // plugin-b对应的目录
│ └─index.js
└─uni-config-center
├─index.js // config-center入口文件
├─plugin-a
│ ├─config.json // plugin-a对应的配置文件
│ └─other-file.cert // plugin-a依赖的其他文件
└─plugin-b
└─config.json // plugin-b对应的配置文件
```
使用uni-config-center后的优势
- 配置文件统一管理,分离插件主体和配置信息,更新插件更方便
- 支持对config.json设置schema,插件使用者在HBuilderX内编写config.json文件时会有更好的提示(后续HBuilderX会提供支持)
# 用法
在要使用uni-config-center的公共模块或云函数内引入uni-config-center依赖,请参考:[使用公共模块](https://uniapp.dcloud.net.cn/uniCloud/cf-common)
```js
const createConfig = require('uni-config-center')
const uniIdConfig = createConfig({
pluginId: 'uni-id', // 插件id
defaultConfig: { // 默认配置
tokenExpiresIn: 7200,
tokenExpiresThreshold: 600,
},
customMerge: function(defaultConfig, userConfig) { // 自定义默认配置和用户配置的合并规则,不设置的情况侠会对默认配置和用户配置进行深度合并
// defaudltConfig 默认配置
// userConfig 用户配置
return Object.assign(defaultConfig, userConfig)
}
})
// 以如下配置为例
// {
// "tokenExpiresIn": 7200,
// "passwordErrorLimit": 6,
// "bindTokenToDevice": false,
// "passwordErrorRetryTime": 3600,
// "app-plus": {
// "tokenExpiresIn": 2592000
// },
// "service": {
// "sms": {
// "codeExpiresIn": 300
// }
// }
// }
// 获取配置
uniIdConfig.config() // 获取全部配置,注意:uni-config-center内不存在对应插件目录时会返回空对象
uniIdConfig.config('tokenExpiresIn') // 指定键值获取配置,返回:7200
uniIdConfig.config('service.sms.codeExpiresIn') // 指定键值获取配置,返回:300
uniIdConfig.config('tokenExpiresThreshold', 600) // 指定键值获取配置,如果不存在则取传入的默认值,返回:600
// 获取文件绝对路径
uniIdConfig.resolve('custom-token.js') // 获取uni-config-center/uni-id/custom-token.js文件的路径
// 引用文件(require)
uniIDConfig.requireFile('custom-token.js') // 使用require方式引用uni-config-center/uni-id/custom-token.js文件。文件不存在时返回undefined,文件内有其他错误导致require失败时会抛出错误。
// 判断是否包含某文件
uniIDConfig.hasFile('custom-token.js') // 配置目录是否包含某文件,true: 文件存在,false: 文件不存在
```

1
uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/index.js

File diff suppressed because one or more lines are too long

9
uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/package.json

@ -0,0 +1,9 @@
{
"name": "uni-config-center",
"version": "0.0.2",
"description": "配置中心",
"main": "index.js",
"keywords": [],
"author": "DCloud",
"license": "Apache-2.0"
}

72
uni_modules/uni-id/changelog.md

@ -0,0 +1,72 @@
## 3.3.12(2022-01-15)
- 新增 preferedAppPlatform 配置用于解决uni-app vue2版本vue3版本获取platform不一致的问题 [详情](https://uniapp.dcloud.net.cn/uniCloud/uni-id?id=prefered-app-platform)
- 修复 checkToken 未返回自定义token内容的Bug
## 3.3.11(2022-01-11)
- 修复用户名密码登录时多个应用出现重复用户名登录报错的Bug
## 3.3.10(2022-01-07)
- 新增 自定义国际化语言支持 [详情](https://uniapp.dcloud.net.cn/uniCloud/uni-id?id=custom-i8n)
- 修复 一键登录时未校验重复手机号是否已验证的Bug
- 修复 Apple登录时用户邮箱为空时报错的Bug
- 修复 登录接口未传username时错误提示不正确的Bug
## 3.3.9(2021-11-09)
- 去除重复的context.xxx未找到的提示语
## 3.3.8(2021-10-28)
- 新增 用户账户封禁接口 [详情](https://uniapp.dcloud.net.cn/uniCloud/uni-id?id=ban-account)
- 新增 用户账户注销接口 [详情](https://uniapp.dcloud.net.cn/uniCloud/uni-id?id=close-account)
- 修复 未传appid时用户重复注册的Bug
## 3.3.7(2021-10-08)
- 移除部分接口的废弃提示
## 3.3.6(2021-09-08)
- 修复 邀请码可能重复的Bug
## 3.3.5(2021-08-10)
- 修复版本号错误
## 3.3.4(2021-08-10)
- 微信、QQ、支付宝登录新增type参数用于指定当前是登录还是注册
## 3.3.3(2021-08-04)
- 修复使用数组形式的配置文件报错的Bug
## 3.3.2(2021-08-03)
- 修复上3.3.0版本引出的createInstance接口传入配置不生效的Bug 感谢[hmh](https://gitee.com/hmh)
## 3.3.1(2021-07-30)
- 修复 将设置用户允许登录的应用列表时传入空数组报错的Bug
## 3.3.0(2021-07-30)
- 新增 不同端应用配置隔离 [详情](https://uniapp.dcloud.net.cn/uniCloud/uni-id?id=isolate-config)
- 新增 不同端用户隔离 [详情](https://uniapp.dcloud.net.cn/uniCloud/uni-id?id=isolate-user)
+ 此版本升级需要开发者处理一下用户数据,请参考 [补齐用户dcloud_appid字段](https://uniapp.dcloud.net.cn/uniCloud/uni-id?id=makeup-dcloud-appid)
- 新增 QQ登录、注册相关功能 [详情](https://uniapp.dcloud.net.cn/uniCloud/uni-id?id=qq)
- 调整 不再支持绑定手机、邮箱时不填验证码直接绑定
## 3.2.1(2021-07-09)
- 撤销3.2.0版本所做的调整
## 3.2.0(2021-07-09)
- 【重要】支持不同端(管理端、用户端等)用户隔离 [详情](https://uniapp.dcloud.net.cn/uniCloud/uni-id?id=isolate-user)
- 支持不同端(管理端、用户端等)配置文件隔离 [详情](https://uniapp.dcloud.net.cn/uniCloud/uni-id?id=isolate-config)
## 3.1.3(2021-07-08)
- 移除插件内误传的node_modules
## 3.1.2(2021-07-08)
- 修复 微信小程序绑定微信账号时报错的Bug
## 3.1.1(2021-07-01)
- 使用新的错误码规范,兼容旧版 [详情](https://uniapp.dcloud.net.cn/uniCloud/uni-id?id=errcode)
- 修复微信登录、绑定时未返回用户accessToken的Bug
## 3.1.0(2021-04-19)
- 增加对用户名、邮箱、密码字段的两端去空格
- 默认忽略用户名、邮箱的大小写 [详情](https://uniapp.dcloud.net.cn/uniCloud/uni-id?id=case-sensitive)
- 修复 customToken导出async方法报错的Bug
## 3.0.12(2021-04-13)
- 调整bindTokenToDevice默认值为false
## 3.0.11(2021-04-12)
- 修复3.0.7版本引出的多个用户访问时可能出现30201报错的Bug
## 3.0.10(2021-04-08)
- 优化错误提示
## 3.0.9(2021-04-08)
- bindMobile接口支持通过一键登录的方式绑定
- 优化错误提示
## 3.0.8(2021-03-19)
- 修复 3.0.7版本某些情况下生成token报错的Bug
## 3.0.7(2021-03-19)
- 新增 支持uni-config-center,更新uni-id无须再担心配置被覆盖 [详情](https://uniapp.dcloud.io/uniCloud/uni-id?id=uni-config-center)
- 新增 自定义token内容,可以缓存角色权限之外的更多信息到客户端 [详情](https://uniapp.dcloud.io/uniCloud/uni-id?id=custom-token)
- 新增 支持传入context获取uni-id实例,防止单实例多并发时全局context混乱 [详情](https://uniapp.dcloud.io/uniCloud/uni-id?id=create-instance)
## 3.0.6(2021-03-05)
- 新增[uniID.wxBizDataCrypt](https://uniapp.dcloud.io/uniCloud/uni-id?id=%e5%be%ae%e4%bf%a1%e6%95%b0%e6%8d%ae%e8%a7%a3%e5%af%86)方法
- 优化loginByApple方法,提高接口响应速度
## 3.0.5(2021-02-03)
- 调整为uni_modules目录规范

84
uni_modules/uni-id/package.json

@ -0,0 +1,84 @@
{
"id": "uni-id",
"displayName": "uni-id",
"version": "3.3.12",
"description": "简单、统一、可扩展的用户中心",
"keywords": [
"uniid",
"uni-id",
"用户管理",
"用户中心",
"短信验证码"
],
"repository": "https://gitee.com/dcloud/uni-id.git",
"engines": {
"HBuilderX": "^3.1.0"
},
"dcloudext": {
"category": [
"uniCloud",
"云函数模板"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": ""
},
"uni_modules": {
"dependencies": ["uni-config-center"],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "u",
"app-nvue": "u"
},
"H5-mobile": {
"Safari": "u",
"Android Browser": "u",
"微信浏览器(Android)": "u",
"QQ浏览器(Android)": "u"
},
"H5-pc": {
"Chrome": "u",
"IE": "u",
"Edge": "u",
"Firefox": "u",
"Safari": "u"
},
"小程序": {
"微信": "u",
"阿里": "u",
"百度": "u",
"字节跳动": "u",
"QQ": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
},
"Vue": {
"vue2": "y",
"vue3": "u"
}
}
}
}
}

33
uni_modules/uni-id/readme.md

@ -0,0 +1,33 @@
**文档已移至[uni-id文档](https://uniapp.dcloud.net.cn/uniCloud/uni-id)**
> 一般uni-id升级大版本时为不兼容更新,从低版本迁移到高版本请参考:[uni-id迁移指南](https://uniapp.dcloud.net.cn/uniCloud/uni-id?id=migration)
## 重要升级说明
**uni-id 3.x版本,搭配的uniCloud admin版本需大于1.2.10。**
### 缓存角色权限
自`uni-id 3.0.0`起,支持在token内缓存用户的角色权限,默认开启此功能,各登录接口的needPermission参数不再生效。如需关闭请在config内配置`"removePermissionAndRoleFromToken": true`。
为什么要缓存角色权限?要知道云数据库是按照读写次数来收取费用的,并且读写数据库会拖慢接口响应速度。未配置`"removePermissionAndRoleFromToken": true`的情况下,可以在调用checkToken接口时不查询数据库获取用户角色权限。
详细checkToken流程如下:
![](https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/ed45d350-5a4d-11eb-b997-9918a5dda011.jpg)
可以看出,旧版token(removePermissionAndRoleFromToken为true时生成的)在checkToken时如需返回权限需要进行两次数据库查询。新版token不需要查库即可返回权限信息。
**注意**
- 由于角色权限缓存在token内,可能会存在权限已经更新但是用户token未过期之前依然是旧版角色权限的情况。可以调短一些token过期时间来减少这种情况的影响。
- admin角色token内不包含permission,如需自行判断用户是否有某个权限,要注意admin角色需要额外判断一下,写法如下
```js
const {
role,
permission
} = await uniID.checkToken(event.uniIdToken)
if(role.includes('admin') || permission.includes('your permission id')) {
// 当前角色拥有'your permission id'对应的权限
}
```

201
uni_modules/uni-id/uniCloud/cloudfunctions/common/uni-id/LICENSE.md

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

1
uni_modules/uni-id/uniCloud/cloudfunctions/common/uni-id/index.js

File diff suppressed because one or more lines are too long

16
uni_modules/uni-id/uniCloud/cloudfunctions/common/uni-id/package.json

@ -0,0 +1,16 @@
{
"name": "uni-id",
"version": "3.3.12",
"description": "uni-id for uniCloud",
"main": "index.js",
"homepage": "https://uniapp.dcloud.io/uniCloud/uni-id",
"repository": {
"type": "git",
"url": "git+https://gitee.com/dcloud/uni-id.git"
},
"author": "",
"license": "Apache-2.0",
"dependencies": {
"uni-config-center": "file:../../../../../uni-config-center/uniCloud/cloudfunctions/common/uni-config-center"
}
}

53
uni_modules/uni-upgrade-center-app/changelog.md

@ -0,0 +1,53 @@
## 0.3.2(2022-01-12)
- 优化显示逻辑
## 0.3.1(2021-11-24)
- 修复 vue3 上图片不显示的Bug
## 0.3.0(2021-11-18)
- 移除 wgt 安装成功后提示,防止重启过快弹框不消失
## 0.2.2(2021-08-25)
- 兼容vue3.0
## 0.2.1(2021-07-26)
- 修复 使用腾讯云并手动填写地址时,导致下载链接失效的bug
## 0.2.0(2021-07-13)
- 更新文档 关于报错local_storage_key 为空,请不要将页面路径设置为pages.json中第一项
## 0.1.9(2021-06-28)
- 更新文档
- 修复 wgt安装失败时,按钮状态不对
## 0.1.8(2021-06-16)
- 修复 跳转安装时,导致上次下载的apk还没安装就被删掉的bug
## 0.1.7(2021-06-03)
- 修改 移除static中的图片
## 0.1.6(2021-06-03)
- 修改 下载更新按钮使用CSS渐变色
## 0.1.5(2021-04-22)
- 更新check-update函数。现在返回一个Promise,有更新时成功回调,其他情况错误回调
## 0.1.4(2021-04-13)
- 更新文档。明确云函数调用结果
## 0.1.3(2021-04-13)
- 解耦云函数与弹框处理。utils中新增 call-check-version.js,可用于单独检测是否有更新
## 0.1.2(2021-04-07)
- 更新版本对比函数 compare
## 0.1.1(2021-04-07)
- 修复 腾讯云空间下载链接不能下载问题
## 0.1.0(2021-04-07)
- 新增使用uni.showModal提示升级示例
- 修改iOS升级提示方式
## 0.0.7(2021-04-02)
- 修复在iOS上打开弹框报错
## 0.0.6(2021-04-01)
- 兼容旧版本安卓
## 0.0.5(2021-04-01)
- 修复低版本安卓上进度条错位
## 0.0.4(2021-04-01)
- 更新readme
- 修复check-update语法错误
## 0.0.3(2021-04-01)
- 新增前台更新弹框,详见readme
- 更新前台检查更新方法
## 0.0.2(2021-03-29)
- 更新文档
- 移除 dependencies
## 0.0.1(2021-03-25)
- 升级中心前台检查更新

BIN
uni_modules/uni-upgrade-center-app/images/app_update_close.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

BIN
uni_modules/uni-upgrade-center-app/images/bg_top.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

83
uni_modules/uni-upgrade-center-app/package.json

@ -0,0 +1,83 @@
{
"id": "uni-upgrade-center-app",
"displayName": "升级中心 uni-upgrade-center - App",
"version": "0.3.2",
"description": "uni升级中心 - 客户端检查更新",
"keywords": [
"uniCloud",
"update",
"升级",
"wgt"
],
"repository": "https://gitee.com/dcloud/uni-upgrade-center/tree/master/uni_modules/uni-upgrade-center-app",
"engines": {
"HBuilderX": "^3.1.0"
},
"dcloudext": {
"category": [
"uniCloud",
"云端一体页面模板"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "插件不采集任何数据",
"permissions": "无"
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "u"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "u",
"阿里": "u",
"百度": "u",
"字节跳动": "u",
"QQ": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
},
"Vue": {
"vue2": "y",
"vue3": "y"
}
}
}
}
}

500
uni_modules/uni-upgrade-center-app/pages/upgrade-popup.vue

@ -0,0 +1,500 @@
<template>
<view class="mask flex-center">
<view class="content botton-radius">
<view class="content-top">
<text class="content-top-text">{{title}}</text>
<image class="content-top" style="top: 0;" width="100%" height="100%" src="../images/bg_top.png">
</image>
</view>
<view class="content-header"></view>
<view class="content-body">
<view class="title">
<text>{{subTitle}}</text>
<!-- <text style="padding-left:20rpx;font-size: 0.5em;color: #666;">v.{{version}}</text> -->
</view>
<view class="body">
<scroll-view class="box-des-scroll" scroll-y="true">
<text class="box-des">
{{contents}}
</text>
</scroll-view>
</view>
<view class="footer flex-center">
<template v-if="isiOS">
<button class="content-button" style="border: none;color: #fff;" plain @click="jumpToAppStore">
{{downLoadBtnTextiOS}}
</button>
</template>
<template v-else>
<template v-if="!downloadSuccess">
<view class="progress-box flex-column" v-if="downloading">
<progress class="progress" border-radius="35" :percent="downLoadPercent"
activeColor="#3DA7FF" show-info stroke-width="10" />
<view style="width:100%;font-size: 28rpx;display: flex;justify-content: space-around;">
<text>{{downLoadingText}}</text>
<text>({{downloadedSize}}/{{packageFileSize}}M)</text>
</view>
</view>
<button v-else class="content-button" style="border: none;color: #fff;" plain
@click="downloadPackage">
{{downLoadBtnText}}
</button>
</template>
<button v-else-if="downloadSuccess && !installed" class="content-button"
style="border: none;color: #fff;" plain :loading="installing" :disabled="installing"
@click="installPackage">
{{installing ? '正在安装……' : '下载完成,立即安装'}}
</button>
<button v-if="installed && isWGT" class="content-button" style="border: none;color: #fff;" plain
@click="restart">
安装完毕点击重启
</button>
</template>
</view>
</view>
<image v-if="!is_mandatory" class="close-img" src="../images/app_update_close.png"
@click.stop="closeUpdate"></image>
</view>
</view>
</template>
<script>
const localFilePathKey = '__localFilePath__'
const platform_iOS = 'iOS';
let downloadTask = null;
/**
* 对比版本号如需要请自行修改判断规则
* 支持比对 ("3.0.0.0.0.1.0.1", "3.0.0.0.0.1") ("3.0.0.1", "3.0") ("3.1.1", "3.1.1.1") 之类的
* @param {Object} v1
* @param {Object} v2
* v1 > v2 return 1
* v1 < v2 return -1
* v1 == v2 return 0
*/
function compare(v1 = '0', v2 = '0') {
v1 = String(v1).split('.')
v2 = String(v2).split('.')
const minVersionLens = Math.min(v1.length, v2.length);
let result = 0;
for (let i = 0; i < minVersionLens; i++) {
const curV1 = Number(v1[i])
const curV2 = Number(v2[i])
if (curV1 > curV2) {
result = 1
break;
} else if(curV1 < curV2) {
result = -1
break;
}
}
if (result === 0 && (v1.length !== v2.length)) {
const v1BiggerThenv2 = v1.length > v2.length;
const maxLensVersion = v1BiggerThenv2 ? v1 : v2;
for (let i = minVersionLens; i < maxLensVersion.length; i++) {
const curVersion = Number(maxLensVersion[i])
if (curVersion > 0) {
v1BiggerThenv2 ? result = 1 : result = -1
break;
}
}
}
return result;
}
export default {
data() {
return {
//
installForBeforeFilePath: '',
//
installed: false,
installing: false,
//
downloadSuccess: false,
downloading: false,
downLoadPercent: 0,
downloadedSize: 0,
packageFileSize: 0,
tempFilePath: '', //
//
title: '更新日志',
contents: '',
is_mandatory: false,
//
subTitle: '发现新版本',
downLoadBtnTextiOS: '立即跳转更新',
downLoadBtnText: '立即下载更新',
downLoadingText: '安装包下载中,请稍后'
}
},
onLoad({
local_storage_key
}) {
if (!local_storage_key) {
console.error('local_storage_key为空,请检查后重试')
uni.navigateBack()
return;
};
const localPackageInfo = uni.getStorageSync(local_storage_key);
if (!localPackageInfo) {
console.error('安装包信息为空,请检查后重试')
uni.navigateBack()
return;
};
const requiredKey = ['version', 'url', 'type']
for (let key in localPackageInfo) {
if (requiredKey.indexOf(key) !== -1 && !localPackageInfo[key]) {
console.error(`参数 ${key} 必填,请检查后重试`)
uni.navigateBack()
return;
}
}
Object.assign(this, localPackageInfo)
this.checkLocalStoragePackage()
},
onBackPress() {
//
if (this.is_mandatory) {
return true
}
downloadTask && downloadTask.abort()
},
computed: {
isWGT() {
return this.type === 'wgt'
},
isiOS() {
return !this.isWGT ? this.platform.includes(platform_iOS) : false;
}
},
methods: {
checkLocalStoragePackage() {
//
const localFilePathRecord = uni.getStorageSync(localFilePathKey)
if (localFilePathRecord) {
const {
version,
savedFilePath,
installed
} = localFilePathRecord
//
if (!installed && compare(version, this.version) === 0) {
this.downloadSuccess = true;
this.installForBeforeFilePath = savedFilePath;
this.tempFilePath = savedFilePath
} else {
//
this.deleteSavedFile(savedFilePath)
}
}
},
async closeUpdate() {
if (this.downloading) {
if (this.is_mandatory) {
return uni.showToast({
title: '下载中,请稍后……',
icon: 'none',
duration: 500
})
}
uni.showModal({
title: '是否取消下载?',
cancelText: '否',
confirmText: '是',
success: res => {
if (res.confirm) {
downloadTask && downloadTask.abort()
uni.navigateBack()
}
}
});
return;
}
if (this.downloadSuccess && this.tempFilePath) {
//
await this.saveFile(this.tempFilePath, this.version)
uni.navigateBack()
return;
}
uni.navigateBack()
},
downloadPackage() {
this.downloading = true;
//
downloadTask = uni.downloadFile({
url: this.url,
success: res => {
if (res.statusCode == 200) {
this.downloadSuccess = true;
this.tempFilePath = res.tempFilePath
//
if (this.is_mandatory) {
this.installPackage();
}
}
},
complete: () => {
this.downloading = false;
this.downLoadPercent = 0
this.downloadedSize = 0
this.packageFileSize = 0
downloadTask = null;
}
});
downloadTask.onProgressUpdate(res => {
this.downLoadPercent = res.progress;
this.downloadedSize = (res.totalBytesWritten / Math.pow(1024, 2)).toFixed(2);
this.packageFileSize = (res.totalBytesExpectedToWrite / Math.pow(1024, 2)).toFixed(2);
});
},
installPackage() {
// #ifdef APP-PLUS
// wgt
if (this.isWGT) {
this.installing = true;
}
plus.runtime.install(this.tempFilePath, {
force: false
}, async res => {
this.installing = false;
this.installed = true;
// wgt
if (this.isWGT) {
//
if (this.is_mandatory) {
uni.showLoading({
icon: 'none',
title: '安装成功,正在重启……'
})
setTimeout(() => {
uni.hideLoading()
this.restart();
}, 1000)
}
} else {
const localFilePathRecord = uni.getStorageSync(localFilePathKey)
uni.setStorageSync(localFilePathKey, {
...localFilePathRecord,
installed: true
})
}
}, async err => {
//
if (this.installForBeforeFilePath) {
await this.deleteSavedFile(this.installForBeforeFilePath)
this.installForBeforeFilePath = '';
}
//
this.installing = false;
this.installed = false;
uni.showModal({
title: `更新失败${this.isWGT ? '' : ',APK文件不存在'},请重新下载`,
content: err.message,
showCancel: false
});
});
// wgt
if (!this.isWGT) {
uni.navigateBack()
}
// #endif
},
restart() {
this.installed = false;
// #ifdef APP-PLUS
//app
plus.runtime.restart();
// #endif
},
async saveFile(tempFilePath, version) {
const [err, res] = await uni.saveFile({
tempFilePath
})
if (err) {
return;
}
uni.setStorageSync(localFilePathKey, {
version,
savedFilePath: res.savedFilePath
})
},
deleteSavedFile(filePath) {
uni.removeStorageSync(localFilePathKey)
return uni.removeSavedFile({
filePath
})
},
jumpToAppStore() {
plus.runtime.openURL(this.url);
}
}
}
</script>
<style>
page {
background: transparent;
}
.flex-center {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
justify-content: center;
align-items: center;
}
.mask {
position: fixed;
left: 0;
top: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, .65);
}
.botton-radius {
border-bottom-left-radius: 30rpx;
border-bottom-right-radius: 30rpx;
}
.content {
position: relative;
top: 0;
width: 600rpx;
background-color: #fff;
box-sizing: border-box;
padding: 0 50rpx;
font-family: Source Han Sans CN;
}
.text {
/* #ifndef APP-NVUE */
display: block;
/* #endif */
line-height: 200px;
text-align: center;
color: #FFFFFF;
}
.content-top {
position: absolute;
top: -195rpx;
left: 0;
width: 600rpx;
height: 270rpx;
}
.content-top-text {
font-size: 45rpx;
font-weight: bold;
color: #F8F8FA;
position: absolute;
top: 120rpx;
left: 50rpx;
z-index: 1;
}
.content-header {
height: 70rpx;
}
.title {
font-size: 33rpx;
font-weight: bold;
color: #3DA7FF;
line-height: 38px;
}
.footer {
height: 150rpx;
display: flex;
align-items: center;
justify-content: space-around;
}
.box-des-scroll {
box-sizing: border-box;
padding: 0 40rpx;
height: 200rpx;
text-align: left;
}
.box-des {
font-size: 26rpx;
color: #000000;
line-height: 50rpx;
}
.progress-box {
width: 100%;
}
.progress {
width: 90%;
height: 40rpx;
border-radius: 35px;
}
.close-img {
width: 70rpx;
height: 70rpx;
z-index: 1000;
position: absolute;
bottom: -120rpx;
left: calc(50% - 70rpx / 2);
}
.content-button {
text-align: center;
flex: 1;
font-size: 30rpx;
font-weight: 400;
color: #FFFFFF;
border-radius: 40rpx;
margin: 0 18rpx;
height: 80rpx;
line-height: 80rpx;
background: linear-gradient(to right, #1785ff, #3DA7FF);
}
.flex-column {
display: flex;
flex-direction: column;
align-items: center;
}
</style>

18
uni_modules/uni-upgrade-center-app/pages_init.json

@ -0,0 +1,18 @@
{
"pages": [{
"path": "uni_modules/uni-upgrade-center-app/pages/upgrade-popup",
"style": {
"disableScroll": true,
"app-plus": {
"backgroundColorTop": "transparent",
"background": "transparent",
"titleNView": false,
"scrollIndicator": false,
"popGesture": "none",
"animationType": "fade-in",
"animationDuration": 200
}
}
}]
}

121
uni_modules/uni-upgrade-center-app/readme.md

@ -0,0 +1,121 @@
# uni-upgrade-center - App
### 概述
> 统一管理App及App在`Android`、`iOS`平台上`App安装包`和`wgt资源包`的发布升级
> 本插件为uni升级中心客户端检查更新,后台管理系统请点击查看 [uni-upgrade-center - Admin](https://ext.dcloud.net.cn/plugin?id=4470)
### uni升级中心 - 客户端检查更新插件
- 一键式检查更新,同时支持整包升级与wgt资源包更新
- 好看、实用、可自定义的客户端提示框
## 安装指引
1. 依赖数据库`opendb-app-versions`,如果没有此库,请在云服务空间中创建。
2. 使用`HBuilderX 3.1.0+`,因为要使用到`uni_modules`
3. 在插件市场打开本插件页面,在右侧点击`使用 HBuilderX 导入插件`,选择要导入的项目点击确定
4. 绑定一个服务空间
5. 找到`/uni_modules/uni-upgrade-center-app/uniCloud/cloudfunctions/check-version`,右键上传部署
6. 在`pages.json`中添加页面路径。**注:请不要设置为pages.json中第一项**
```json
"pages": [
// ……其他页面配置
{
"path": "uni_modules/uni-upgrade-center-app/pages/upgrade-popup",
"style": {
"disableScroll": true,
"app-plus": {
"backgroundColorTop": "transparent",
"background": "transparent",
"titleNView": false,
"scrollIndicator": false,
"popGesture": "none",
"animationType": "fade-in",
"animationDuration": 200
}
}
}
]
```
7. 将`@/uni_modules/uni-upgrade-center-app/utils/check-update`import到需要用到的地方,调用一下即可
8. 升级弹框可自行编写,也可以使用`uni.showModal`,或使用现有的升级弹框样式,如果不满足UI需求请自行替换资源文件。在`utils/check-update.js`中都有实例。
9. wgt更新时,打包前请务必将manifest.json中的版本修改为更高版本。
### 更新下载安装`check-update.js`
*该函数在utils目录下*
1. 如果是静默更新,则不会打开更新弹框,会在后台下载后安装,下次启动应用生效
2. 如果是 iOS,则会直接打开AppStore的链接
3. 其他情况,会将`check-version`返回的结果保存在localStorage中,并跳转进入`upgrade-popup.vue`打开更新弹框
### 检查更新函数`check-version`
*该函数在uniCloud/cloudfunctions目录下*
1. 使用检查更新需要传递三个参数 `appid`、`appVersion`、`wgtVersion`
2. `appid` 使用 plus.runtime.appid 获取,*注:真机运行时为固定值HBuilder,在调试的时候请使用本地调试云函数*
3. `appVersion` 使用 plus.runtime.version 获取
4. `wgtVersion` 使用 plus.runtime.getProperty(plus.runtime.appid,(wgtInfo) => { wgtInfo.version }) 获取
5. `check-version`云函数内部会自动获取 App 平台
**Tips**
1. `check-version`云函数内部有版本对比函数(compare)。
- 使用多段式版本格式(如:"3.0.0.0.0.1.0.1", "3.0.0.0.0.1")。如果不满足对比规则,请自行修改。
- 如果修改,请将*pages/upgrade-popup.vue*中*compare*函数一并修改
## 项目代码说明
### 更新弹框
- `upgrade-popup.vue` - 更新应用:
- 如果云函数`check-version`返回的参数表明需要更新,则将参数保存在localStorage中,带着键值跳转该页面
- 进入时会先从localStorage中尝试取出之前存的安装包路径(此包不会是强制安装类型的包)
- 如果有已经保存的包,则和传进来的 `version` 进行比较,如果相等则安装。大于和小于都不进行安装,因为admin端可能会调整包的版本。不符合更新会将此包删除
- 如果本地没有包或者包不符合安装条件,则进行下载安装包
- 点击下载会有进度条、已下载大小和下载包的大小
- 下载完成会提示安装:
- 如果是 wgt 包,安装时则会提示 正在安装…… 和 安装完成。安装完成会提示是否重启
- 如果是 原生安装包,则直接跳出去覆盖安装
- 下载过程中,如果退出会提示是否取消下载。如果是强制更新,则只会提示正在下载请稍后,此时不可退出
- 如果是下载完成了没有安装就退出,则会将下载完成的包保存在本地。将包的本地路径和包version保存在localStorage中
### 工具类 utils
- `call-check-version`
- 请求云函数`check-version`拿取版本检测结果
- `check-update`
- 调用`call-check-version`并根据结果判断是否显示更新弹框
### 云函数
- `check-version` - 检查应用更新:
- 根据传参,先检测传参是否完整,appid appVersion wgtVersion 必传
- 先从数据库取出所有该平台(会从上下文读取平台信息)的所有线上发行更新
- 再从所有线上发行更新中取出版本最大的一版。如果可以,尽量先检测wgt的线上发行版更新
- 使用上一步取出的版本包的版本号 和传参 appVersion、wgtVersion 来检测是否有更新。必须同时大于这两项,因为上一次可能是wgt热更新,否则返回暂无更新
- 如果库中 wgt包 版本大于传参 appVersion,但是不满足 min_uni_version < appVersion则不会使用wgt更新会接着判断库中 app包version 是否大于 appVersion
- 返回结果:
|code|message|
|:-:|:-:|
|0|当前版本已经是最新的,不需要更新|
|101|wgt更新|
|102|整包更新|
|-101|暂无更新或检查appid是否填写正确|
|-102|请检查传参是否填写正确|

9
uni_modules/uni-upgrade-center-app/uniCloud/cloudfunctions/check-version/check-version.param.json

@ -0,0 +1,9 @@
// json
// https://uniapp.dcloud.net.cn/uniCloud/quickstart?id=runparam
{
"appid": "__YOUR_APPID__",
"appVersion": "2.2.0",
"wgtVersion": "2.2.2"
}

167
uni_modules/uni-upgrade-center-app/uniCloud/cloudfunctions/check-version/index.js

@ -0,0 +1,167 @@
'use strict';
exports.main = async (event, context) => {
/**
* 检测升级 使用说明
* 上传包
* 1. 根据传参先检测传参是否完整appid appVersion wgtVersion 必传
* 2. 先从数据库取出所有该平台从上下文读取平台信息默认 Andriod的所有线上发行更新
* 3. 再从所有线上发行更新中取出版本最大的一版如果可以尽量先检测wgt的线上发行版更新
* 4. 使用上步取出的版本包的版本号 和传参 appVersionwgtVersion 来检测是否有更新必须同时大于这两项否则返回暂无更新
* 5. 如果库中 wgt包 版本大于传参 appVersion但是不满足 min_uni_version < appVersion则不会使用wgt更新会接着判断库中 app包version 是否大于 appVersion
*/
let {
appid,
appVersion,
wgtVersion,
} = event;
const platform_Android = 'Android';
const platform_iOS = 'iOS';
const package_app = 'native_app';
const package_wgt = 'wgt';
const app_version_db_name = 'opendb-app-versions'
let platform = platform_Android;
// 云函数URL化请求
if (event.headers) {
let body;
try {
if (event.httpMethod.toLocaleLowerCase() === 'get') {
body = event.queryStringParameters;
} else {
body = JSON.parse(event.body);
}
} catch (e) {
return {
code: 500,
msg: '请求错误'
};
}
appid = body.appid;
appVersion = body.appVersion;
wgtVersion = body.wgtVersion;
platform = /iPhone|iPad/.test(event.headers) ? platform_iOS : platform_Android;
} else if (context.OS) {
platform = context.OS === 'android'
? platform_Android
: context.OS === 'ios'
? platform_iOS
: platform_Android;
}
if (appid && appVersion && wgtVersion && platform) {
const collection = uniCloud.database().collection(app_version_db_name);
const record = await collection.where({
appid,
platform,
stable_publish: true
})
.orderBy('create_date', 'desc')
.get();
if (record && record.data && record.data.length > 0) {
const appVersionInDb = record.data.find(item => item.type === package_app) || {};
const wgtVersionInDb = record.data.find(item => item.type === package_wgt) || {};
const hasAppPackage = !!Object.keys(appVersionInDb).length;
const hasWgtPackage = !!Object.keys(wgtVersionInDb).length;
// 取两个版本中版本号最大的包,版本一样,使用wgt包
let stablePublishDb = hasAppPackage
? hasWgtPackage
? compare(wgtVersionInDb.version, appVersionInDb.version) >= 0
? wgtVersionInDb
: appVersionInDb
: appVersionInDb
: wgtVersionInDb;
const {
version,
min_uni_version
} = stablePublishDb;
// 库中的version必须满足同时大于appVersion和wgtVersion才行,因为上次更新可能是wgt更新
const appUpdate = compare(version, appVersion) === 1; // app包可用更新
const wgtUpdate = compare(version, wgtVersion) === 1; // wgt包可用更新
if (Object.keys(stablePublishDb).length && appUpdate && wgtUpdate) {
// 判断是否可用wgt更新
if (min_uni_version && compare(min_uni_version, appVersion) < 1) {
return {
code: 101,
message: 'wgt更新',
...stablePublishDb
};
} else if (hasAppPackage && compare(appVersionInDb.version, appVersion) === 1) {
return {
code: 102,
message: '整包更新',
...appVersionInDb
};
}
}
return {
code: 0,
message: '当前版本已经是最新的,不需要更新'
};
}
return {
code: -101,
message: '暂无更新或检查appid是否填写正确'
};
}
return {
code: -102,
message: '请检查传参是否填写正确'
};
};
/**
* 对比版本号如需要请自行修改判断规则
* 支持比对 ("3.0.0.0.0.1.0.1", "3.0.0.0.0.1") ("3.0.0.1", "3.0") ("3.1.1", "3.1.1.1") 之类的
* @param {Object} v1
* @param {Object} v2
* v1 > v2 return 1
* v1 < v2 return -1
* v1 == v2 return 0
*/
function compare(v1 = '0', v2 = '0') {
v1 = String(v1).split('.')
v2 = String(v2).split('.')
const minVersionLens = Math.min(v1.length, v2.length);
let result = 0;
for (let i = 0; i < minVersionLens; i++) {
const curV1 = Number(v1[i])
const curV2 = Number(v2[i])
if (curV1 > curV2) {
result = 1
break;
} else if(curV1 < curV2) {
result = -1
break;
}
}
if (result === 0 && (v1.length !== v2.length)) {
const v1BiggerThenv2 = v1.length > v2.length;
const maxLensVersion = v1BiggerThenv2 ? v1 : v2;
for (let i = minVersionLens; i < maxLensVersion.length; i++) {
const curVersion = Number(maxLensVersion[i])
if (curVersion > 0) {
v1BiggerThenv2 ? result = 1 : result = -1
break;
}
}
}
return result;
}

29
uni_modules/uni-upgrade-center-app/utils/call-check-version.js

@ -0,0 +1,29 @@
export default function() {
// #ifdef APP-PLUS
return new Promise((resolve, reject) => {
plus.runtime.getProperty(plus.runtime.appid, function(widgetInfo) {
uniCloud.callFunction({
name: 'check-version',
data: {
appid: plus.runtime.appid,
appVersion: plus.runtime.version,
wgtVersion: widgetInfo.version
},
success: (e) => {
resolve(e)
},
fail: (error) => {
reject(error)
}
})
})
})
// #endif
// #ifndef APP-PLUS
return new Promise((resolve, reject) => {
reject({
message: '请在App中使用'
})
})
// #endif
}

155
uni_modules/uni-upgrade-center-app/utils/check-update.js

@ -0,0 +1,155 @@
import callCheckVersion from './call-check-version'
// 推荐再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)
}
})
} else if (code < 0) {
// TODO 云函数报错处理
console.error(message)
reject(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
});
});
}
});
}
});
}
Loading…
Cancel
Save