
HBuilderX与Vue3:开启Uniapp开发的新纪元
随着技术的不断发展,使用最新版本的Vue3语法在HBuilderX中进行Uniapp开发已经成为了一种趋势。在这篇文章中,我们将为您详细介绍如何使用HBuilderX和Vue3来提高您的Uniapp开发效率。
一、HBuilderX与Vue3的完美结合
HBuilderX是一款强大的集成开发环境(IDE),它为Vue3开发者提供了一站式的解决方案。通过使用HBuilderX,您可以轻松地创建Vue3项目、编写代码、调试应用程序,以及预览和发布您的项目。此外,HBuilderX还支持多种浏览器和移动设备模拟器,让您可以在开发过程中实时查看应用程序的效果。
二、使用Vue3语法开发Uniapp的优势
使用Vue3语法开发Uniapp具有以下优势:
- 更好的性能:Vue3相比Vue2在性能上有了显著的提升,而Uniapp则可以在多个平台上运行,因此使用Vue3可以大大提高Uniapp的性能。
- 更简单的语法:Vue3的语法更加简洁、易读,使得开发者可以更快速地编写代码,同时减少了出错的可能性。
- 更好的组件化:Vue3引入了Composition API,使得组件的开发更加灵活和可维护。在Uniapp中,您可以利用Vue3的组件化特性,提高代码的可重用性和可维护性。
三、课程优势
1.一站式学习:本课程将为您详细介绍如何使用HBuilderX和Vue3进行Uniapp开发的全过程,让您从零开始,逐步掌握核心技能。
- 实战案例:我们为您准备了多个实战案例,让您在实际操作中深入理解知识点的运用,达到融会贯通的效果。
- 高效学习:课程采用线上回答+录播的形式,让您随时随地学习,高效利用时间。同时,我们还将为您提供丰富的课后资料,助您巩固知识,拓展视野。
- 课程目录:大于180课时从基础组件开始,每日更新。
5.社群交流:加入我们的学习社群,与志同道合的朋友一起交流心得,互相学习,共同进步。同时,我们还将定期进行更多实战项目和源码线上分享,让您收获更多干货。
四、课程特色
1.学员们可以免费使用讲师开发的Uniapp插件市场内的全部插件。
地址:https://ext.dcloud.net.cn/publisher?id=1116157
2.后期讲师开发的项目模板全套免费使用。
3.学员实际项目开发中,答疑遇到的问题。
4.后期录制的其他方面的课程可享受折扣。
8.HBuilderX支持实时预览功能,可以实时查看应用在真机和模拟器上的运行效果,方便开发者进行调试和优化。
9.代码提示和自动补全:HBuilderX提供了智能代码提示和自动补全功能,可以帮助开发者快速编写代码,减少出错率。
10.集成调试器:HBuilderX集成了调试器,可以帮助开发者进行代码调试,快速定位和解决问题。
五、课程收获
- 掌握HBuilderX的使用技巧和Vue3的最新语法,提升您的开发效率。
- 学会如何利用Vue3的组件化特性来提高代码的可重用性和可维护性。
- 掌握如何调试和优化Uniapp应用程序的性能,使其在多个平台上达到最佳运行效果。
- 通过实战案例的练习,让您具备独立开发高质量Uniapp应用程序的能力。
- 学会前后端全端开发,一技在手全栈拿手。
还在等什么?快来加入我们的课程吧!让我们一起开启HBuilderX与Vue3的Uniapp开发之旅,共创美好未来!
六、如何参与学习
想要参与学习,您可以按照以下步骤操作:
1.访问我们的课程网站。
https://www.w3cschool.cn/minicourse/play/tcvue
2.在课程页面中,您会看到课程介绍、课程大纲、课程费用等相关信息。请仔细阅读,了解课程的基本情况。
(每日更新)
- 在课程期间,我们将为您提供必要的学习资料和指导,帮助您更好地掌握知识和技能。请积极参与课堂讨论和实操练习,与同学们互相学习、共同进步。
七、结语
通过我们的HBuilderX与Vue3教学课程,您将掌握最新的Uniapp开发技能,为未来的职业发展打下坚实基础。我们期待您的加入,与我们一起开启全新的技术之旅!
八、附加价值
除了核心的知识和技能,我们的课程还为您提供了以下附加价值: - 案例分享:我们会定期邀请成功的开发者进行案例分享,让您了解最新的开发趋势和实践经验,拓宽您的视野。
- 职业规划建议:我们提供个性化的职业规划建议,帮助您更好地规划未来的职业发展路径,提升职业竞争力。
九、总结
通过我们的HBuilderX与Vue3教学课程,您将获得最新的Uniapp开发技能、实战经验和附加价值。我们的导师团队将为您提供全方位的学习支持,帮助您在短时间内快速提升开发能力。加入我们的课程,开启全新的技术之旅,为未来的职业发展打下坚实基础!
现在就来报名参加我们的课程吧!让我们一起学习、成长和进步!
随着技术的不断发展,使用最新版本的Vue3语法在HBuilderX中进行Uniapp开发已经成为了一种趋势。在这篇文章中,我们将为您详细介绍如何使用HBuilderX和Vue3来提高您的Uniapp开发效率。
一、HBuilderX与Vue3的完美结合
HBuilderX是一款强大的集成开发环境(IDE),它为Vue3开发者提供了一站式的解决方案。通过使用HBuilderX,您可以轻松地创建Vue3项目、编写代码、调试应用程序,以及预览和发布您的项目。此外,HBuilderX还支持多种浏览器和移动设备模拟器,让您可以在开发过程中实时查看应用程序的效果。
二、使用Vue3语法开发Uniapp的优势
使用Vue3语法开发Uniapp具有以下优势:
- 更好的性能:Vue3相比Vue2在性能上有了显著的提升,而Uniapp则可以在多个平台上运行,因此使用Vue3可以大大提高Uniapp的性能。
- 更简单的语法:Vue3的语法更加简洁、易读,使得开发者可以更快速地编写代码,同时减少了出错的可能性。
- 更好的组件化:Vue3引入了Composition API,使得组件的开发更加灵活和可维护。在Uniapp中,您可以利用Vue3的组件化特性,提高代码的可重用性和可维护性。
三、课程优势
1.一站式学习:本课程将为您详细介绍如何使用HBuilderX和Vue3进行Uniapp开发的全过程,让您从零开始,逐步掌握核心技能。
- 实战案例:我们为您准备了多个实战案例,让您在实际操作中深入理解知识点的运用,达到融会贯通的效果。
- 高效学习:课程采用线上回答+录播的形式,让您随时随地学习,高效利用时间。同时,我们还将为您提供丰富的课后资料,助您巩固知识,拓展视野。
- 课程目录:大于180课时从基础组件开始,每日更新。
5.社群交流:加入我们的学习社群,与志同道合的朋友一起交流心得,互相学习,共同进步。同时,我们还将定期进行更多实战项目和源码线上分享,让您收获更多干货。
四、课程特色
1.学员们可以免费使用讲师开发的Uniapp插件市场内的全部插件。
地址:https://ext.dcloud.net.cn/publisher?id=1116157
2.后期讲师开发的项目模板全套免费使用。
3.学员实际项目开发中,答疑遇到的问题。
4.后期录制的其他方面的课程可享受折扣。
8.HBuilderX支持实时预览功能,可以实时查看应用在真机和模拟器上的运行效果,方便开发者进行调试和优化。
9.代码提示和自动补全:HBuilderX提供了智能代码提示和自动补全功能,可以帮助开发者快速编写代码,减少出错率。
10.集成调试器:HBuilderX集成了调试器,可以帮助开发者进行代码调试,快速定位和解决问题。
五、课程收获
- 掌握HBuilderX的使用技巧和Vue3的最新语法,提升您的开发效率。
- 学会如何利用Vue3的组件化特性来提高代码的可重用性和可维护性。
- 掌握如何调试和优化Uniapp应用程序的性能,使其在多个平台上达到最佳运行效果。
- 通过实战案例的练习,让您具备独立开发高质量Uniapp应用程序的能力。
- 学会前后端全端开发,一技在手全栈拿手。
还在等什么?快来加入我们的课程吧!让我们一起开启HBuilderX与Vue3的Uniapp开发之旅,共创美好未来!
六、如何参与学习
想要参与学习,您可以按照以下步骤操作:
1.访问我们的课程网站。
https://www.w3cschool.cn/minicourse/play/tcvue
2.在课程页面中,您会看到课程介绍、课程大纲、课程费用等相关信息。请仔细阅读,了解课程的基本情况。
(每日更新)
- 在课程期间,我们将为您提供必要的学习资料和指导,帮助您更好地掌握知识和技能。请积极参与课堂讨论和实操练习,与同学们互相学习、共同进步。
七、结语
通过我们的HBuilderX与Vue3教学课程,您将掌握最新的Uniapp开发技能,为未来的职业发展打下坚实基础。我们期待您的加入,与我们一起开启全新的技术之旅!
八、附加价值
除了核心的知识和技能,我们的课程还为您提供了以下附加价值: - 案例分享:我们会定期邀请成功的开发者进行案例分享,让您了解最新的开发趋势和实践经验,拓宽您的视野。
- 职业规划建议:我们提供个性化的职业规划建议,帮助您更好地规划未来的职业发展路径,提升职业竞争力。
九、总结
通过我们的HBuilderX与Vue3教学课程,您将获得最新的Uniapp开发技能、实战经验和附加价值。我们的导师团队将为您提供全方位的学习支持,帮助您在短时间内快速提升开发能力。加入我们的课程,开启全新的技术之旅,为未来的职业发展打下坚实基础!
现在就来报名参加我们的课程吧!让我们一起学习、成长和进步!

【解决】canvasToTempFilePath:fail fail canvas is empty
uni.canvasToTempFilePath({}, this);加个this
uni.canvasToTempFilePath({
canvasId: "canvas",
success: (res) => {
console.log('canvas转成图片成功:', res);
},
fail: (err) => {
console.log('canvas转成图片失败:', err)
}
}, this)
↓↓↓ 各位大佬点点赞
uni.canvasToTempFilePath({}, this);加个this
uni.canvasToTempFilePath({
canvasId: "canvas",
success: (res) => {
console.log('canvas转成图片成功:', res);
},
fail: (err) => {
console.log('canvas转成图片失败:', err)
}
}, this)
↓↓↓ 各位大佬点点赞
收起阅读 »
在 H5 中使用了uni-app 的 editor 组件异常的解决方案
首发自 ask 社区
如果问题没有解决,请参考这篇文章进行修改。https://ask.dcloud.net.cn/article/40900
如何判断你是否收到影响?
如果你同时符合下面两种情况,你需要仔细阅读:
- 你使用
uni-app
构建 web 端,也称H5
端 - 在编辑器中搜索
uni-editor
或者uniEditor
发现有引用
如果你符合上述两条要求,请继续阅读。
问题现象
近期很多用户反馈 <uni-editor />
组件在 H5 端不能正常使用,表现为组件点击无反应、赋值不生效、控制台有提示资源获取超时等,但之前是好的,近期突然不正常了。
经过 uni-app 团队排查,发现是在 H5 环境下,激活编辑器 editor
组件时候,如果当前环境没有相关依赖,会从 unpkg
上下载资源。
近期部分地区无法正常访问 unpkg
导致组件资源获取不到,最终导致 editor
组件不能正常运行。
我该如何解决?
editor
组件官方文档一直有相关提示,点击这里: https://uniapp.dcloud.net.cn/component/editor.html 在注意事项部分有相关提示。
但很多用户没注意看,这里做个详细的指导,后续会进一步优化相关提示。
这里提供两个方案,供不同用户使用。
方案一:自己管理 CDN 资源 推荐
阅读官方文档,可以看到,有两个 js 需要加载,这里可以下载两个 js 到 static
目录,并在 index.html
(Vue 3),或者 public/index.html
(Vue2) 中在 head
之间添加 js
vue2 配合 hbuiderx 使用 editor ,demo 地址 https://gitee.com/xiaoxfa/vue2-hbuilderx-playground/tree/q%2Feditor/
<head>
<script src="/static/quill-1.3.7.min.js"></script>
<script src="/static/image-resize-3.0.1.min.js"></script>
</head>
这样 editor 就可以正常使用了,代码逻辑中检测到有相关 window.Quill
变量,就不会从远程获取资源。
这种方案比较省事。如果你熟悉 npm
生态,熟悉构建流程的用户,推荐方案二。
方案二:使用 npm 相关依赖
方案一的解决思路是在 window
上进行挂载,同样,我们可以在项目入口 main.js
或者 App.vue
中引用相关依赖即可。
基础代码附上,你可以按照这个基础 demo 里的代码进行测试。
https://gitcode.net/xiurensha5731/uni-app-questions/-/tree/q/editor
整体来说,在项目中添加相关依赖:
# 经过测试最新版本 1.3.7 可以运行
npm i quill@1.3.7
npm i quill-image-resize-mp
在 vue3+ts
的代码中这样引用:
<script setup lang="ts">
declare global {
interface Window {
Quill: any;
}
}
// h5 依赖 quill 依赖,这里引入依赖,挂在全局避免去远程引入
// #ifdef H5
import ImageResize from "quill-image-resize-mp";
import Quill from "quill";
window.Quill = Quill;
window.ImageResize = { default: ImageResize };
// #endif
</script>
这样做的好处是依赖清晰,引用透明。
问题总结
项目中谨慎使用远程 CDN,无论是国外的还是国内的,鼓励使用托管资源,使用 npm 进行管理,保证依赖清晰,引用透明,方便项目长期维护。
首发自 ask 社区
如果问题没有解决,请参考这篇文章进行修改。https://ask.dcloud.net.cn/article/40900
如何判断你是否收到影响?
如果你同时符合下面两种情况,你需要仔细阅读:
- 你使用
uni-app
构建 web 端,也称H5
端 - 在编辑器中搜索
uni-editor
或者uniEditor
发现有引用
如果你符合上述两条要求,请继续阅读。
问题现象
近期很多用户反馈 <uni-editor />
组件在 H5 端不能正常使用,表现为组件点击无反应、赋值不生效、控制台有提示资源获取超时等,但之前是好的,近期突然不正常了。
经过 uni-app 团队排查,发现是在 H5 环境下,激活编辑器 editor
组件时候,如果当前环境没有相关依赖,会从 unpkg
上下载资源。
近期部分地区无法正常访问 unpkg
导致组件资源获取不到,最终导致 editor
组件不能正常运行。
我该如何解决?
editor
组件官方文档一直有相关提示,点击这里: https://uniapp.dcloud.net.cn/component/editor.html 在注意事项部分有相关提示。
但很多用户没注意看,这里做个详细的指导,后续会进一步优化相关提示。
这里提供两个方案,供不同用户使用。
方案一:自己管理 CDN 资源 推荐
阅读官方文档,可以看到,有两个 js 需要加载,这里可以下载两个 js 到 static
目录,并在 index.html
(Vue 3),或者 public/index.html
(Vue2) 中在 head
之间添加 js
vue2 配合 hbuiderx 使用 editor ,demo 地址 https://gitee.com/xiaoxfa/vue2-hbuilderx-playground/tree/q%2Feditor/
<head>
<script src="/static/quill-1.3.7.min.js"></script>
<script src="/static/image-resize-3.0.1.min.js"></script>
</head>
这样 editor 就可以正常使用了,代码逻辑中检测到有相关 window.Quill
变量,就不会从远程获取资源。
这种方案比较省事。如果你熟悉 npm
生态,熟悉构建流程的用户,推荐方案二。
方案二:使用 npm 相关依赖
方案一的解决思路是在 window
上进行挂载,同样,我们可以在项目入口 main.js
或者 App.vue
中引用相关依赖即可。
基础代码附上,你可以按照这个基础 demo 里的代码进行测试。
https://gitcode.net/xiurensha5731/uni-app-questions/-/tree/q/editor
整体来说,在项目中添加相关依赖:
# 经过测试最新版本 1.3.7 可以运行
npm i quill@1.3.7
npm i quill-image-resize-mp
在 vue3+ts
的代码中这样引用:
<script setup lang="ts">
declare global {
interface Window {
Quill: any;
}
}
// h5 依赖 quill 依赖,这里引入依赖,挂在全局避免去远程引入
// #ifdef H5
import ImageResize from "quill-image-resize-mp";
import Quill from "quill";
window.Quill = Quill;
window.ImageResize = { default: ImageResize };
// #endif
</script>
这样做的好处是依赖清晰,引用透明。
问题总结
项目中谨慎使用远程 CDN,无论是国外的还是国内的,鼓励使用托管资源,使用 npm 进行管理,保证依赖清晰,引用透明,方便项目长期维护。
收起阅读 »
小程序快速开发模板
uni-app小程序快速开发模板,基于uni+uviewui进行开发。已封装api请求、版本更新提示、分包加载等完善基础功能,是uni-app快速开发小程序的一套基础模板!
插件地址:小程序快速开发模板
小程序分包加载,避免体积超限
"optimization" : {
"subPackages" : true
}
关于接口请求
小程序新版本更新
其他
获取手机号登录;快速填充微信头像和昵称;打开微信自带的隐私政策;支持配置微信聊天素材更多打开方式;评价发布组件,可自定义邀请小程序用户评价;
uni-app小程序快速开发模板,基于uni+uviewui进行开发。已封装api请求、版本更新提示、分包加载等完善基础功能,是uni-app快速开发小程序的一套基础模板!
插件地址:小程序快速开发模板
小程序分包加载,避免体积超限
"optimization" : {
"subPackages" : true
}
关于接口请求
小程序新版本更新
其他
获取手机号登录;快速填充微信头像和昵称;打开微信自带的隐私政策;支持配置微信聊天素材更多打开方式;评价发布组件,可自定义邀请小程序用户评价;
https://ext.dcloud.net.cn/plugin?id=15514
收起阅读 »
uni爬虫抓取小说保存到数据库例子

//抓取网络小说保存到芒果db实例 nodejs 21.14 MongoDB2.11 2023-12-18
//引入第三方库
let axios = require('axios');
let cheerio = require('cheerio');
const {
MongoClient
} = require('mongodb');
const url = 'mongodb://localhost:27017'; // 请根据实际情况修改MongoDB的URL
const dbName = 'xiaoshuo'; // 请替换为你的数据库名称
const client = new MongoClient(url, {
useNewUrlParser: true,
useUnifiedTopology: true
});
//要抓取的小说id
const shuidlist = {
'0': 54255,
'1': 80304,
'2': 54254,
'3': 80292,
'4':20032,
'5':12891,
'6':66513,
'7':104404,
'8':104454,
'9':20312
};
//设置insertOne插入数据函数 insertOne(要插入的数据, 数据库表名)
async function insertOne(data, dbm) {
try {
await client.connect();
const db = client.db(dbName);
const collection = db.collection(dbm);
const result = await collection.insertOne(data);
console.log('插入第' + data.id + '条数据ID为:', result.insertedId);
} catch (err) {
console.error('连接失败或插入数据失败:', err);
} finally {
await client.close();
}
}
//抓取小说封面,return小说章节链接,保存到芒果db
async function getlist(shuid) {
const url = 'https://www.paomov.com/txt' + shuid + '.shtml'; // 替换为你要抓取的小说网页地址
const chapterList = [];
const chapterContents = {};
await axios.get(url).then(res => {
const html = res.data;
const ok = cheerio.load(html);
const fenlei = ok('meta[property="og:novel:category"]').attr('content'); //分类
const biaoti = ok('meta[property="og:novel:book_name"]').attr('content'); //标题
const zuozhe = ok('meta[property="og:novel:author"]').attr('content'); //作者
const tupian = 'https://www.paomov.com' + ok('meta[property="og:image"]').attr('content'); //图片
const shijian = ok('meta[property="og:novel:update_time"]').attr('content'); //时间
const jianjie = ok('meta[property="og:description"]').attr('content'); //简介
const data = {
'feileiid': 1,
'fenlei': fenlei,
'id': shuid 1,
'biaoti': biaoti,
'zuozhe': zuozhe,
'tupian': tupian,
'shijian': shijian,
'jianjie': jianjie
};
insertOne(data, 'aaaa'); //保存封面信息到数据库
ok('div.box_con > div#list a').each((index, element) => {
const chapterTitle = ok(element).text();
const chapterUrl = ok(element).attr('href').replace('//www', 'https://www');
chapterList.push(chapterTitle);
chapterContents[index] = chapterUrl;
});
}).catch(error => {
console.error('抓取封面失败:', error);
process.exit()
})
return chapterContents;
}
//抓取小说章节标题和内容保存到芒果db
async function getcontent(chapterList, i, shuid) {
await axios.get(chapterList).then(res => {
const html = res.data;
const ok = cheerio.load(html);
const biaoti = ok('h1').text(); //章节标题
const neirong = ok('div#content').text().replace(/\s/g, ''); //章节内容
const data = {
'shuhao': shuid 1,
'id': i 1 + 1 * 1,
'biaoti': biaoti,
'neirong': neirong
};
insertOne(data, 'bbbb'); //保存章节内容到数据库
}).catch(error => {
console.error('抓取内容失败:', error);
process.exit();
})
}
//主函数抓取小说保存到数据库
async function run() {
const moshi = 0; //循环抓取模式,1为测试用
for (var key in shuidlist) {
const list = await getlist(shuidlist[key]);
if (moshi == 0) {
var shuid = shuidlist[key];
for (var i in list) {
//抓取全部
await getcontent(list[i], i, shuidlist[key]);
}
} else {
var shuid = shuidlist[key];
// console.log('小说抓取成功');
// console.log(shuid);
// console.log(list);
// return'1';
//抓取指定,测试用
for (var i = 0; i < 3; i++) {
await getcontent(list[i], i, shuid);
}
}
setTimeout(() => {
console.log('小说抓取成功');
}, 500)
}
setTimeout(() => {
console.log('全部小说抓取成功');
}, 1000)
}
run() //运行主函数
//抓取网络小说保存到芒果db实例 nodejs 21.14 MongoDB2.11 2023-12-18
//引入第三方库
let axios = require('axios');
let cheerio = require('cheerio');
const {
MongoClient
} = require('mongodb');
const url = 'mongodb://localhost:27017'; // 请根据实际情况修改MongoDB的URL
const dbName = 'xiaoshuo'; // 请替换为你的数据库名称
const client = new MongoClient(url, {
useNewUrlParser: true,
useUnifiedTopology: true
});
//要抓取的小说id
const shuidlist = {
'0': 54255,
'1': 80304,
'2': 54254,
'3': 80292,
'4':20032,
'5':12891,
'6':66513,
'7':104404,
'8':104454,
'9':20312
};
//设置insertOne插入数据函数 insertOne(要插入的数据, 数据库表名)
async function insertOne(data, dbm) {
try {
await client.connect();
const db = client.db(dbName);
const collection = db.collection(dbm);
const result = await collection.insertOne(data);
console.log('插入第' + data.id + '条数据ID为:', result.insertedId);
} catch (err) {
console.error('连接失败或插入数据失败:', err);
} finally {
await client.close();
}
}
//抓取小说封面,return小说章节链接,保存到芒果db
async function getlist(shuid) {
const url = 'https://www.paomov.com/txt' + shuid + '.shtml'; // 替换为你要抓取的小说网页地址
const chapterList = [];
const chapterContents = {};
await axios.get(url).then(res => {
const html = res.data;
const ok = cheerio.load(html);
const fenlei = ok('meta[property="og:novel:category"]').attr('content'); //分类
const biaoti = ok('meta[property="og:novel:book_name"]').attr('content'); //标题
const zuozhe = ok('meta[property="og:novel:author"]').attr('content'); //作者
const tupian = 'https://www.paomov.com' + ok('meta[property="og:image"]').attr('content'); //图片
const shijian = ok('meta[property="og:novel:update_time"]').attr('content'); //时间
const jianjie = ok('meta[property="og:description"]').attr('content'); //简介
const data = {
'feileiid': 1,
'fenlei': fenlei,
'id': shuid 1,
'biaoti': biaoti,
'zuozhe': zuozhe,
'tupian': tupian,
'shijian': shijian,
'jianjie': jianjie
};
insertOne(data, 'aaaa'); //保存封面信息到数据库
ok('div.box_con > div#list a').each((index, element) => {
const chapterTitle = ok(element).text();
const chapterUrl = ok(element).attr('href').replace('//www', 'https://www');
chapterList.push(chapterTitle);
chapterContents[index] = chapterUrl;
});
}).catch(error => {
console.error('抓取封面失败:', error);
process.exit()
})
return chapterContents;
}
//抓取小说章节标题和内容保存到芒果db
async function getcontent(chapterList, i, shuid) {
await axios.get(chapterList).then(res => {
const html = res.data;
const ok = cheerio.load(html);
const biaoti = ok('h1').text(); //章节标题
const neirong = ok('div#content').text().replace(/\s/g, ''); //章节内容
const data = {
'shuhao': shuid 1,
'id': i 1 + 1 * 1,
'biaoti': biaoti,
'neirong': neirong
};
insertOne(data, 'bbbb'); //保存章节内容到数据库
}).catch(error => {
console.error('抓取内容失败:', error);
process.exit();
})
}
//主函数抓取小说保存到数据库
async function run() {
const moshi = 0; //循环抓取模式,1为测试用
for (var key in shuidlist) {
const list = await getlist(shuidlist[key]);
if (moshi == 0) {
var shuid = shuidlist[key];
for (var i in list) {
//抓取全部
await getcontent(list[i], i, shuidlist[key]);
}
} else {
var shuid = shuidlist[key];
// console.log('小说抓取成功');
// console.log(shuid);
// console.log(list);
// return'1';
//抓取指定,测试用
for (var i = 0; i < 3; i++) {
await getcontent(list[i], i, shuid);
}
}
setTimeout(() => {
console.log('小说抓取成功');
}, 500)
}
setTimeout(() => {
console.log('全部小说抓取成功');
}, 1000)
}
run() //运行主函数

云打包失败,可以试试离线打包。离线打包没那么难,7分钟即可掌握
七分钟掌握离线打包视频演示:
https://www.bilibili.com/video/BV1Xc411o7tk/
安装 uapp 开源工具:
npm install -g uapp
操作教程,可查看文档:
七分钟掌握离线打包视频演示:
https://www.bilibili.com/video/BV1Xc411o7tk/
安装 uapp 开源工具:
npm install -g uapp
操作教程,可查看文档:
https://github.com/uappkit/uapp
收起阅读 »
关于DCloud周日晚切换服务器引发问题的公告和总结
故障描述
DCloud服务器在做跨云切换,这是DCloud第一次做这类事情,经验不足,轻视了风险,以为可以无缝切换,所以未提前发公告。
但从12月17日周日晚10点半起,还是造成了部分业务中断或缓慢,尤其是登陆鉴权服务的中断,给当时仍在使用的开发者带来了很大麻烦。
- 开发者无法登陆HBuilder,鉴权失效,进而造成了无法打包等一系列故障。
- uniCloud控制台无法登陆,无法更新云函数。
本次切换是提前在新云部署好后再切换的,但还是有2个故障点:
故障时间 | 故障范围 | 故障现象 | 故障原因 | |
---|---|---|---|---|
故障1 | 22点半到23点半 | 所有开发者 | 无法登陆HX和uniCloud控制台 | 流量较大,切换不及时 |
故障2 | 23点半到1点10分 | token失效的HX开发者 | 点击登陆按钮没有反应 | HX连接服务器的备份域名未及时切换,HX主备切换相关代码不完善,备份域名切换后需要重启HX才能恢复登陆 |
往上追一层的原因分析:
- 故障1属于跨云切换经验不足。
- 故障2暴露了相关代码不健壮,后续会升级HX和服务器交互代码来彻底解决主备切换的不完善。
再次说明:DCloud服务器故障不影响开发者的线上业务运行。
包括uniCloud虽然无法登陆管理,但云函数和数据库是在阿里云、腾讯云、支付宝小程序云上的,线上云函数连接不经过DCloud服务器,所以这块不会被影响。
后续改进
开发者肯定会追问,如何避免DCloud服务器以后再次异常导致自己的开发工作受影响?
- DCloud会努力保证服务器的正常,跨云切换是非常低频的事件,日常维护方面DCloud从域名到服务器均有主备策略,我们会加大对主备切换相关代码逻辑的完善。
- DCloud计划后续更新HX,确保DCloud服务器异常时不影响开发者打包Web和Wgt。
HX发行时会校验开发者账户和AppId的匹配关系,这是防止黑产盗用正常用户的AppID。而AppId对应着DCloud的很多服务,付费插件、uniCloud、安全网络、加固...
(当然仅凭这个校验无法防护所有黑产,DCloud还有其他措施配套。) - DCloud一直以来都提供离线打包,App有离线打包,导出Wgt也将确保不因DCloud服务器异常而受影响。uni-app的cli也一直都可以离线发行Web和小程序。
我们无法保证DCloud的服务器一直不出问题,但我们可以保证:
- 相关人员吸取了教训,变得更有经验
- 相关代码会被仔细review,变得更健壮
- 相关制度会更加完善和细化,进一步降低问题出现的概率和破坏性
DCloud是一个负责任的公司,有自己的行为准则,无论您后续是否继续使用DCloud的工具和服务,无论您是否为DCloud支付费用,
这些不影响DCloud将严格要求自身,按照更高质量要求的标准提供服务。
更新:
18日上午及中午,随着开发者流量增加,一批与存储相关的业务并发性能受到影响。
该问题是因为存储文件体积较大,部分文件还未迁移到新云,老云的文件通过外网流量访问,而外网流量带宽不足导致。
随着各处的带宽配置增加,该问题已解决。
由于积压了较多打包排队请求,DCloud已经扩容了打包机,目前打包拥堵已恢复正常。
故障描述
DCloud服务器在做跨云切换,这是DCloud第一次做这类事情,经验不足,轻视了风险,以为可以无缝切换,所以未提前发公告。
但从12月17日周日晚10点半起,还是造成了部分业务中断或缓慢,尤其是登陆鉴权服务的中断,给当时仍在使用的开发者带来了很大麻烦。
- 开发者无法登陆HBuilder,鉴权失效,进而造成了无法打包等一系列故障。
- uniCloud控制台无法登陆,无法更新云函数。
本次切换是提前在新云部署好后再切换的,但还是有2个故障点:
故障时间 | 故障范围 | 故障现象 | 故障原因 | |
---|---|---|---|---|
故障1 | 22点半到23点半 | 所有开发者 | 无法登陆HX和uniCloud控制台 | 流量较大,切换不及时 |
故障2 | 23点半到1点10分 | token失效的HX开发者 | 点击登陆按钮没有反应 | HX连接服务器的备份域名未及时切换,HX主备切换相关代码不完善,备份域名切换后需要重启HX才能恢复登陆 |
往上追一层的原因分析:
- 故障1属于跨云切换经验不足。
- 故障2暴露了相关代码不健壮,后续会升级HX和服务器交互代码来彻底解决主备切换的不完善。
再次说明:DCloud服务器故障不影响开发者的线上业务运行。
包括uniCloud虽然无法登陆管理,但云函数和数据库是在阿里云、腾讯云、支付宝小程序云上的,线上云函数连接不经过DCloud服务器,所以这块不会被影响。
后续改进
开发者肯定会追问,如何避免DCloud服务器以后再次异常导致自己的开发工作受影响?
- DCloud会努力保证服务器的正常,跨云切换是非常低频的事件,日常维护方面DCloud从域名到服务器均有主备策略,我们会加大对主备切换相关代码逻辑的完善。
- DCloud计划后续更新HX,确保DCloud服务器异常时不影响开发者打包Web和Wgt。
HX发行时会校验开发者账户和AppId的匹配关系,这是防止黑产盗用正常用户的AppID。而AppId对应着DCloud的很多服务,付费插件、uniCloud、安全网络、加固...
(当然仅凭这个校验无法防护所有黑产,DCloud还有其他措施配套。) - DCloud一直以来都提供离线打包,App有离线打包,导出Wgt也将确保不因DCloud服务器异常而受影响。uni-app的cli也一直都可以离线发行Web和小程序。
我们无法保证DCloud的服务器一直不出问题,但我们可以保证:
- 相关人员吸取了教训,变得更有经验
- 相关代码会被仔细review,变得更健壮
- 相关制度会更加完善和细化,进一步降低问题出现的概率和破坏性
DCloud是一个负责任的公司,有自己的行为准则,无论您后续是否继续使用DCloud的工具和服务,无论您是否为DCloud支付费用,
这些不影响DCloud将严格要求自身,按照更高质量要求的标准提供服务。
更新:
18日上午及中午,随着开发者流量增加,一批与存储相关的业务并发性能受到影响。
该问题是因为存储文件体积较大,部分文件还未迁移到新云,老云的文件通过外网流量访问,而外网流量带宽不足导致。
随着各处的带宽配置增加,该问题已解决。
由于积压了较多打包排队请求,DCloud已经扩容了打包机,目前打包拥堵已恢复正常。

【跳转到App Store】ios更新,跳转到app store更新
你的AppleID:Apple Developer(发布ios app的地方)--->App信息--->综合信息里面
const url = `itms-apps://itunes.apple.com/cn/app/id${你的AppleID}?mt=8`
plus.runtime.openURL(url);
↓↓↓ 各位大佬点点赞
你的AppleID:Apple Developer(发布ios app的地方)--->App信息--->综合信息里面
const url = `itms-apps://itunes.apple.com/cn/app/id${你的AppleID}?mt=8`
plus.runtime.openURL(url);
↓↓↓ 各位大佬点点赞
收起阅读 »
关于华为应用市场上架,申请权限未告知目的被驳回问题的简单处理方式(修改篇)
该文章是在https://ask.dcloud.net.cn/article/40875上的补充
var isIos
// #ifdef APP-PLUS
isIos = (plus.os.name == "iOS")
// #endif
var viewShow = true;
// 判断推送权限是否开启
function judgeIosPermissionPush() {
var result = false;
var UIApplication = plus.ios.import("UIApplication");
var app = UIApplication.sharedApplication();
var enabledTypes = 0;
if (app.currentUserNotificationSettings) {
var settings = app.currentUserNotificationSettings();
enabledTypes = settings.plusGetAttribute("types");
console.log("enabledTypes1:" + enabledTypes);
if (enabledTypes == 0) {
console.log("推送权限没有开启");
} else {
result = true;
console.log("已经开启推送功能!")
}
plus.ios.deleteObject(settings);
} else {
enabledTypes = app.enabledRemoteNotificationTypes();
if (enabledTypes == 0) {
console.log("推送权限没有开启!");
} else {
result = true;
console.log("已经开启推送功能!")
}
console.log("enabledTypes2:" + enabledTypes);
}
plus.ios.deleteObject(app);
plus.ios.deleteObject(UIApplication);
return result;
}
// 判断定位权限是否开启
function judgeIosPermissionLocation() {
var result = false;
var cllocationManger = plus.ios.import("CLLocationManager");
var status = cllocationManger.authorizationStatus();
result = (status != 2)
console.log("定位权限开启:" + result);
// 以下代码判断了手机设备的定位是否关闭,推荐另行使用方法 checkSystemEnableLocation
/* var enable = cllocationManger.locationServicesEnabled();
var status = cllocationManger.authorizationStatus();
console.log("enable:" + enable);
console.log("status:" + status);
if (enable && status != 2) {
result = true;
console.log("手机定位服务已开启且已授予定位权限");
} else {
console.log("手机系统的定位没有打开或未给予定位权限");
} */
plus.ios.deleteObject(cllocationManger);
return result;
}
// 判断麦克风权限是否开启
function judgeIosPermissionRecord() {
var result = false;
var avaudiosession = plus.ios.import("AVAudioSession");
var avaudio = avaudiosession.sharedInstance();
var permissionStatus = avaudio.recordPermission();
console.log("permissionStatus:" + permissionStatus);
if (permissionStatus == 1684369017 || permissionStatus == 1970168948) {
console.log("麦克风权限没有开启");
} else {
result = true;
console.log("麦克风权限已经开启");
}
plus.ios.deleteObject(avaudiosession);
return result;
}
// 判断相机权限是否开启
function judgeIosPermissionCamera() {
var result = false;
var AVCaptureDevice = plus.ios.import("AVCaptureDevice");
var authStatus = AVCaptureDevice.authorizationStatusForMediaType('vide');
console.log("authStatus:" + authStatus);
if (authStatus == 3) {
result = true;
console.log("相机权限已经开启");
} else {
console.log("相机权限没有开启");
}
plus.ios.deleteObject(AVCaptureDevice);
return result;
}
// 判断相册权限是否开启
function judgeIosPermissionPhotoLibrary() {
var result = false;
var PHPhotoLibrary = plus.ios.import("PHPhotoLibrary");
var authStatus = PHPhotoLibrary.authorizationStatus();
console.log("authStatus:" + authStatus);
if (authStatus == 3) {
result = true;
console.log("相册权限已经开启");
} else {
console.log("相册权限没有开启");
}
plus.ios.deleteObject(PHPhotoLibrary);
return result;
}
// 判断通讯录权限是否开启
function judgeIosPermissionContact() {
var result = false;
var CNContactStore = plus.ios.import("CNContactStore");
var cnAuthStatus = CNContactStore.authorizationStatusForEntityType(0);
if (cnAuthStatus == 3) {
result = true;
console.log("通讯录权限已经开启");
} else {
console.log("通讯录权限没有开启");
}
plus.ios.deleteObject(CNContactStore);
return result;
}
// 判断日历权限是否开启
function judgeIosPermissionCalendar() {
var result = false;
var EKEventStore = plus.ios.import("EKEventStore");
var ekAuthStatus = EKEventStore.authorizationStatusForEntityType(0);
if (ekAuthStatus == 3) {
result = true;
console.log("日历权限已经开启");
} else {
console.log("日历权限没有开启");
}
plus.ios.deleteObject(EKEventStore);
return result;
}
// 判断备忘录权限是否开启
function judgeIosPermissionMemo() {
var result = false;
var EKEventStore = plus.ios.import("EKEventStore");
var ekAuthStatus = EKEventStore.authorizationStatusForEntityType(1);
if (ekAuthStatus == 3) {
result = true;
console.log("备忘录权限已经开启");
} else {
console.log("备忘录权限没有开启");
}
plus.ios.deleteObject(EKEventStore);
return result;
}
// Android权限查询
function requestAndroidPermission(permissionID) {
return new Promise((resolve, reject) => {
plus.android.requestPermissions(
permissionID.split(","),
// [permissionID], // 理论上支持多个权限同时查询,但实际上本函数封装只处理了一个权限的情况。有需要的可自行扩展封装
function(resultObj) {
var result = 0;
for (var i = 0; i < resultObj.granted.length; i++) {
var grantedPermission = resultObj.granted[i];
console.log('已获取的权限:' + grantedPermission);
result = 1
}
for (var i = 0; i < resultObj.deniedPresent.length; i++) {
var deniedPresentPermission = resultObj.deniedPresent[i];
console.log('拒绝本次申请的权限:' + deniedPresentPermission);
result = 0
}
for (var i = 0; i < resultObj.deniedAlways.length; i++) {
var deniedAlwaysPermission = resultObj.deniedAlways[i];
console.log('永久拒绝申请的权限:' + deniedAlwaysPermission);
result = -1
}
resolve(result);
// 若所需权限被拒绝,则打开APP设置界面,可以在APP设置界面打开相应权限
// if (result != 1) {
// gotoAppPermissionSetting()
// }
},
function(error) {
console.log('申请权限错误:' + error.code + " = " + error.message);
resolve({
code: error.code,
message: error.message
});
}
);
});
}
// 使用一个方法,根据参数判断权限
function judgeIosPermission(permissionID) {
if (permissionID == "location") {
return judgeIosPermissionLocation()
} else if (permissionID == "camera") {
return judgeIosPermissionCamera()
} else if (permissionID == "photoLibrary") {
return judgeIosPermissionPhotoLibrary()
} else if (permissionID == "record") {
return judgeIosPermissionRecord()
} else if (permissionID == "push") {
return judgeIosPermissionPush()
} else if (permissionID == "contact") {
return judgeIosPermissionContact()
} else if (permissionID == "calendar") {
return judgeIosPermissionCalendar()
} else if (permissionID == "memo") {
return judgeIosPermissionMemo()
}
return false;
}
// 跳转到**应用**的权限页面
function gotoAppPermissionSetting() {
if (isIos) {
var UIApplication = plus.ios.import("UIApplication");
var application2 = UIApplication.sharedApplication();
var NSURL2 = plus.ios.import("NSURL");
// var setting2 = NSURL2.URLWithString("prefs:root=LOCATION_SERVICES");
var setting2 = NSURL2.URLWithString("app-settings:");
application2.openURL(setting2);
plus.ios.deleteObject(setting2);
plus.ios.deleteObject(NSURL2);
plus.ios.deleteObject(application2);
} else {
// console.log(plus.device.vendor);
var Intent = plus.android.importClass("android.content.Intent");
var Settings = plus.android.importClass("android.provider.Settings");
var Uri = plus.android.importClass("android.net.Uri");
var mainActivity = plus.android.runtimeMainActivity();
var intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
var uri = Uri.fromParts("package", mainActivity.getPackageName(), null);
intent.setData(uri);
mainActivity.startActivity(intent);
}
}
// 检查系统的设备服务是否开启
// var checkSystemEnableLocation = async function () {
function checkSystemEnableLocation() {
if (isIos) {
var result = false;
var cllocationManger = plus.ios.import("CLLocationManager");
var result = cllocationManger.locationServicesEnabled();
console.log("系统定位开启:" + result);
plus.ios.deleteObject(cllocationManger);
return result;
} else {
var context = plus.android.importClass("android.content.Context");
var locationManager = plus.android.importClass("android.location.LocationManager");
var main = plus.android.runtimeMainActivity();
var mainSvr = main.getSystemService(context.LOCATION_SERVICE);
var result = mainSvr.isProviderEnabled(locationManager.GPS_PROVIDER);
console.log("系统定位开启:" + result);
return result
}
}
let permissionMap = {
"android": {
"CAMERA_EXTERNAL_STORAGE": {
"name": "android.permission.READ_EXTERNAL_STORAGE,android.permission.WRITE_EXTERNAL_STORAGE,android.permission.CAMERA",
"title": "相机/相册权限说明",
"content": "便于您使用该功能上传您的照片/图片/视频及用于更换头像、意见反馈上传图片、与客服沟通等场景中读取和写入相册和文件内容"
},
"CAMERA": {
"name": "android.permission.CAMERA",
"title": "相机权限说明",
"content": "便于您使用该功能拍照更换头像、意见反馈上传图片、与客服沟通等场景中发送拍摄图片"
},
"EXTERNAL_STORAGE": {
"name": "android.permission.READ_EXTERNAL_STORAGE,android.permission.WRITE_EXTERNAL_STORAGE",
"title": "相册权限说明",
"content": "便于您使用该功能上传您的照片/图片/视频及用于更换头像、意见反馈上传图片、与客服沟通等场景中读取和写入相册和文件内容"
}
},
"ios": {}
}
let view = null;
function showViewDesc(permission) {
let plat = isIos ? "ios" : "android";
view = new plus.nativeObj.View('per-modal', {
top: '0px',
left: '0px',
width: '100%',
backgroundColor: 'rgba(0,0,0,0.2)',
//opacity: '.9'
})
view.drawRect({
color: '#fff',
radius: '5px'
}, {
top: '30px',
left: '5%',
width: '90%',
height: "100px",
})
view.drawText(permissionMap[plat][permission]["title"], {
top: '40px',
left: "8%",
height: "30px"
}, {
align: "left",
color: "#000",
}, {
onClick: function(e) {
console.log(e);
}
})
view.drawText(permissionMap[plat][permission]["content"], {
top: '65px',
height: "60px",
left: "8%",
width: "84%"
}, {
whiteSpace: 'normal',
size: "14px",
align: "left",
color: "#656563"
})
setTimeout(()=>{
if(viewShow) view.show()
},200)
}
function premissionCheck(permission) {
return new Promise(async (resolve, reject) => {
let plat = isIos ? "ios" : "android";
if (isIos) { // ios
// const camera = permission.judgeIosPermission("camera");//判断ios是否给予摄像头权限
// //ios相册没权限,系统会自动弹出授权框
// //let photoLibrary = permission.judgeIosPermission("photoLibrary");//判断ios是否给予相册权限
// if(camera){
// resolve();
// }else{
// reject('需要开启相机使用权限');
// }
resolve(1)
} else { // android
let permission_arr = permissionMap[plat][permission]["name"].split(",");
let flag = true;
for(let i = 0;i<permission_arr.length;i++) {
let status = plus.navigator.checkPermission(permission_arr[i]);
if(status == "undetermined") {
flag = false;
}
}
if (flag == false) { // 未完全授权
showViewDesc(permission);
requestAndroidPermission(permissionMap[plat][permission]["name"]).then((res) => {
viewShow = false;
setTimeout(()=>{
viewShow = true;
},120)
view.close();
if (res == -1) {
uni.showModal({
title: '提示',
content: '操作权限已被拒绝,请手动前往设置',
confirmText: "立即设置",
success: (res) => {
if (res.confirm) {
gotoAppPermissionSetting()
}
}
})
}
resolve(res)
})
} else {
resolve(1)
}
}
})
}
module.exports = {
judgeIosPermission: judgeIosPermission,
requestAndroidPermission: requestAndroidPermission,
checkSystemEnableLocation: checkSystemEnableLocation,
gotoAppPermissionSetting: gotoAppPermissionSetting,
premissionCheck: premissionCheck
}
该文章是在https://ask.dcloud.net.cn/article/40875上的补充
var isIos
// #ifdef APP-PLUS
isIos = (plus.os.name == "iOS")
// #endif
var viewShow = true;
// 判断推送权限是否开启
function judgeIosPermissionPush() {
var result = false;
var UIApplication = plus.ios.import("UIApplication");
var app = UIApplication.sharedApplication();
var enabledTypes = 0;
if (app.currentUserNotificationSettings) {
var settings = app.currentUserNotificationSettings();
enabledTypes = settings.plusGetAttribute("types");
console.log("enabledTypes1:" + enabledTypes);
if (enabledTypes == 0) {
console.log("推送权限没有开启");
} else {
result = true;
console.log("已经开启推送功能!")
}
plus.ios.deleteObject(settings);
} else {
enabledTypes = app.enabledRemoteNotificationTypes();
if (enabledTypes == 0) {
console.log("推送权限没有开启!");
} else {
result = true;
console.log("已经开启推送功能!")
}
console.log("enabledTypes2:" + enabledTypes);
}
plus.ios.deleteObject(app);
plus.ios.deleteObject(UIApplication);
return result;
}
// 判断定位权限是否开启
function judgeIosPermissionLocation() {
var result = false;
var cllocationManger = plus.ios.import("CLLocationManager");
var status = cllocationManger.authorizationStatus();
result = (status != 2)
console.log("定位权限开启:" + result);
// 以下代码判断了手机设备的定位是否关闭,推荐另行使用方法 checkSystemEnableLocation
/* var enable = cllocationManger.locationServicesEnabled();
var status = cllocationManger.authorizationStatus();
console.log("enable:" + enable);
console.log("status:" + status);
if (enable && status != 2) {
result = true;
console.log("手机定位服务已开启且已授予定位权限");
} else {
console.log("手机系统的定位没有打开或未给予定位权限");
} */
plus.ios.deleteObject(cllocationManger);
return result;
}
// 判断麦克风权限是否开启
function judgeIosPermissionRecord() {
var result = false;
var avaudiosession = plus.ios.import("AVAudioSession");
var avaudio = avaudiosession.sharedInstance();
var permissionStatus = avaudio.recordPermission();
console.log("permissionStatus:" + permissionStatus);
if (permissionStatus == 1684369017 || permissionStatus == 1970168948) {
console.log("麦克风权限没有开启");
} else {
result = true;
console.log("麦克风权限已经开启");
}
plus.ios.deleteObject(avaudiosession);
return result;
}
// 判断相机权限是否开启
function judgeIosPermissionCamera() {
var result = false;
var AVCaptureDevice = plus.ios.import("AVCaptureDevice");
var authStatus = AVCaptureDevice.authorizationStatusForMediaType('vide');
console.log("authStatus:" + authStatus);
if (authStatus == 3) {
result = true;
console.log("相机权限已经开启");
} else {
console.log("相机权限没有开启");
}
plus.ios.deleteObject(AVCaptureDevice);
return result;
}
// 判断相册权限是否开启
function judgeIosPermissionPhotoLibrary() {
var result = false;
var PHPhotoLibrary = plus.ios.import("PHPhotoLibrary");
var authStatus = PHPhotoLibrary.authorizationStatus();
console.log("authStatus:" + authStatus);
if (authStatus == 3) {
result = true;
console.log("相册权限已经开启");
} else {
console.log("相册权限没有开启");
}
plus.ios.deleteObject(PHPhotoLibrary);
return result;
}
// 判断通讯录权限是否开启
function judgeIosPermissionContact() {
var result = false;
var CNContactStore = plus.ios.import("CNContactStore");
var cnAuthStatus = CNContactStore.authorizationStatusForEntityType(0);
if (cnAuthStatus == 3) {
result = true;
console.log("通讯录权限已经开启");
} else {
console.log("通讯录权限没有开启");
}
plus.ios.deleteObject(CNContactStore);
return result;
}
// 判断日历权限是否开启
function judgeIosPermissionCalendar() {
var result = false;
var EKEventStore = plus.ios.import("EKEventStore");
var ekAuthStatus = EKEventStore.authorizationStatusForEntityType(0);
if (ekAuthStatus == 3) {
result = true;
console.log("日历权限已经开启");
} else {
console.log("日历权限没有开启");
}
plus.ios.deleteObject(EKEventStore);
return result;
}
// 判断备忘录权限是否开启
function judgeIosPermissionMemo() {
var result = false;
var EKEventStore = plus.ios.import("EKEventStore");
var ekAuthStatus = EKEventStore.authorizationStatusForEntityType(1);
if (ekAuthStatus == 3) {
result = true;
console.log("备忘录权限已经开启");
} else {
console.log("备忘录权限没有开启");
}
plus.ios.deleteObject(EKEventStore);
return result;
}
// Android权限查询
function requestAndroidPermission(permissionID) {
return new Promise((resolve, reject) => {
plus.android.requestPermissions(
permissionID.split(","),
// [permissionID], // 理论上支持多个权限同时查询,但实际上本函数封装只处理了一个权限的情况。有需要的可自行扩展封装
function(resultObj) {
var result = 0;
for (var i = 0; i < resultObj.granted.length; i++) {
var grantedPermission = resultObj.granted[i];
console.log('已获取的权限:' + grantedPermission);
result = 1
}
for (var i = 0; i < resultObj.deniedPresent.length; i++) {
var deniedPresentPermission = resultObj.deniedPresent[i];
console.log('拒绝本次申请的权限:' + deniedPresentPermission);
result = 0
}
for (var i = 0; i < resultObj.deniedAlways.length; i++) {
var deniedAlwaysPermission = resultObj.deniedAlways[i];
console.log('永久拒绝申请的权限:' + deniedAlwaysPermission);
result = -1
}
resolve(result);
// 若所需权限被拒绝,则打开APP设置界面,可以在APP设置界面打开相应权限
// if (result != 1) {
// gotoAppPermissionSetting()
// }
},
function(error) {
console.log('申请权限错误:' + error.code + " = " + error.message);
resolve({
code: error.code,
message: error.message
});
}
);
});
}
// 使用一个方法,根据参数判断权限
function judgeIosPermission(permissionID) {
if (permissionID == "location") {
return judgeIosPermissionLocation()
} else if (permissionID == "camera") {
return judgeIosPermissionCamera()
} else if (permissionID == "photoLibrary") {
return judgeIosPermissionPhotoLibrary()
} else if (permissionID == "record") {
return judgeIosPermissionRecord()
} else if (permissionID == "push") {
return judgeIosPermissionPush()
} else if (permissionID == "contact") {
return judgeIosPermissionContact()
} else if (permissionID == "calendar") {
return judgeIosPermissionCalendar()
} else if (permissionID == "memo") {
return judgeIosPermissionMemo()
}
return false;
}
// 跳转到**应用**的权限页面
function gotoAppPermissionSetting() {
if (isIos) {
var UIApplication = plus.ios.import("UIApplication");
var application2 = UIApplication.sharedApplication();
var NSURL2 = plus.ios.import("NSURL");
// var setting2 = NSURL2.URLWithString("prefs:root=LOCATION_SERVICES");
var setting2 = NSURL2.URLWithString("app-settings:");
application2.openURL(setting2);
plus.ios.deleteObject(setting2);
plus.ios.deleteObject(NSURL2);
plus.ios.deleteObject(application2);
} else {
// console.log(plus.device.vendor);
var Intent = plus.android.importClass("android.content.Intent");
var Settings = plus.android.importClass("android.provider.Settings");
var Uri = plus.android.importClass("android.net.Uri");
var mainActivity = plus.android.runtimeMainActivity();
var intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
var uri = Uri.fromParts("package", mainActivity.getPackageName(), null);
intent.setData(uri);
mainActivity.startActivity(intent);
}
}
// 检查系统的设备服务是否开启
// var checkSystemEnableLocation = async function () {
function checkSystemEnableLocation() {
if (isIos) {
var result = false;
var cllocationManger = plus.ios.import("CLLocationManager");
var result = cllocationManger.locationServicesEnabled();
console.log("系统定位开启:" + result);
plus.ios.deleteObject(cllocationManger);
return result;
} else {
var context = plus.android.importClass("android.content.Context");
var locationManager = plus.android.importClass("android.location.LocationManager");
var main = plus.android.runtimeMainActivity();
var mainSvr = main.getSystemService(context.LOCATION_SERVICE);
var result = mainSvr.isProviderEnabled(locationManager.GPS_PROVIDER);
console.log("系统定位开启:" + result);
return result
}
}
let permissionMap = {
"android": {
"CAMERA_EXTERNAL_STORAGE": {
"name": "android.permission.READ_EXTERNAL_STORAGE,android.permission.WRITE_EXTERNAL_STORAGE,android.permission.CAMERA",
"title": "相机/相册权限说明",
"content": "便于您使用该功能上传您的照片/图片/视频及用于更换头像、意见反馈上传图片、与客服沟通等场景中读取和写入相册和文件内容"
},
"CAMERA": {
"name": "android.permission.CAMERA",
"title": "相机权限说明",
"content": "便于您使用该功能拍照更换头像、意见反馈上传图片、与客服沟通等场景中发送拍摄图片"
},
"EXTERNAL_STORAGE": {
"name": "android.permission.READ_EXTERNAL_STORAGE,android.permission.WRITE_EXTERNAL_STORAGE",
"title": "相册权限说明",
"content": "便于您使用该功能上传您的照片/图片/视频及用于更换头像、意见反馈上传图片、与客服沟通等场景中读取和写入相册和文件内容"
}
},
"ios": {}
}
let view = null;
function showViewDesc(permission) {
let plat = isIos ? "ios" : "android";
view = new plus.nativeObj.View('per-modal', {
top: '0px',
left: '0px',
width: '100%',
backgroundColor: 'rgba(0,0,0,0.2)',
//opacity: '.9'
})
view.drawRect({
color: '#fff',
radius: '5px'
}, {
top: '30px',
left: '5%',
width: '90%',
height: "100px",
})
view.drawText(permissionMap[plat][permission]["title"], {
top: '40px',
left: "8%",
height: "30px"
}, {
align: "left",
color: "#000",
}, {
onClick: function(e) {
console.log(e);
}
})
view.drawText(permissionMap[plat][permission]["content"], {
top: '65px',
height: "60px",
left: "8%",
width: "84%"
}, {
whiteSpace: 'normal',
size: "14px",
align: "left",
color: "#656563"
})
setTimeout(()=>{
if(viewShow) view.show()
},200)
}
function premissionCheck(permission) {
return new Promise(async (resolve, reject) => {
let plat = isIos ? "ios" : "android";
if (isIos) { // ios
// const camera = permission.judgeIosPermission("camera");//判断ios是否给予摄像头权限
// //ios相册没权限,系统会自动弹出授权框
// //let photoLibrary = permission.judgeIosPermission("photoLibrary");//判断ios是否给予相册权限
// if(camera){
// resolve();
// }else{
// reject('需要开启相机使用权限');
// }
resolve(1)
} else { // android
let permission_arr = permissionMap[plat][permission]["name"].split(",");
let flag = true;
for(let i = 0;i<permission_arr.length;i++) {
let status = plus.navigator.checkPermission(permission_arr[i]);
if(status == "undetermined") {
flag = false;
}
}
if (flag == false) { // 未完全授权
showViewDesc(permission);
requestAndroidPermission(permissionMap[plat][permission]["name"]).then((res) => {
viewShow = false;
setTimeout(()=>{
viewShow = true;
},120)
view.close();
if (res == -1) {
uni.showModal({
title: '提示',
content: '操作权限已被拒绝,请手动前往设置',
confirmText: "立即设置",
success: (res) => {
if (res.confirm) {
gotoAppPermissionSetting()
}
}
})
}
resolve(res)
})
} else {
resolve(1)
}
}
})
}
module.exports = {
judgeIosPermission: judgeIosPermission,
requestAndroidPermission: requestAndroidPermission,
checkSystemEnableLocation: checkSystemEnableLocation,
gotoAppPermissionSetting: gotoAppPermissionSetting,
premissionCheck: premissionCheck
}
收起阅读 »

uniapp video H5页面设置srcObject分享
需要先获取到组件video,直接获取绑定的id在uniapp中获取到的是uni-video标签,真正的标签是uni-video内包裹的video标签,要给内层的标签进行设置
代码如下:
<video id="video-dom"></video>
const vidoDom = document.querySelector('#video-dom video')
vidoDom.srcObject = stream
vidoDom.play();
珍惜成果,热心分享,给个
需要先获取到组件video,直接获取绑定的id在uniapp中获取到的是uni-video标签,真正的标签是uni-video内包裹的video标签,要给内层的标签进行设置
代码如下:
<video id="video-dom"></video>
const vidoDom = document.querySelector('#video-dom video')
vidoDom.srcObject = stream
vidoDom.play();
珍惜成果,热心分享,给个
收起阅读 »
全局搜索了个uni.requireNativePlugin,直接吧Hbuilder卡死,重启电脑再次打开依然卡死。
全局搜索了个uni.requireNativePlugin,直接吧Hbuilder卡死,重启电脑再次打开依然卡死。
写代码写上一会就特别卡。
全局搜索了个uni.requireNativePlugin,直接吧Hbuilder卡死,重启电脑再次打开依然卡死。
写代码写上一会就特别卡。