初始化代码

This commit is contained in:
zhouwentao 2024-01-31 11:24:29 +08:00
parent ac4b051ba0
commit 6650a522cb
803 changed files with 107736 additions and 10 deletions

8
.gitignore vendored
View File

@ -1,4 +1,3 @@
# ---> JetBrains
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
@ -9,9 +8,6 @@
.idea/**/dictionaries
.idea/**/shelf
# AWS User-specific
.idea/**/aws.xml
# Generated files
.idea/**/contentModel.xml
@ -62,9 +58,6 @@ atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# SonarLint plugin
.idea/sonarlint/
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
@ -76,4 +69,3 @@ fabric.properties
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser

135
App.vue Normal file
View File

@ -0,0 +1,135 @@
<script>
import {
mapMutations
} from 'vuex'
import {
version
} from './package.json'
import checkUpdate from '@/uni_modules/uni-upgrade-center-app/utils/check-update';
export default {
onLaunch: function() {
// #ifdef H5
console.log(
`%c hello uniapp %c v${version} `,
'background:#35495e ; padding: 1px; border-radius: 3px 0 0 3px; color: #fff',
'background:#007aff ;padding: 1px; border-radius: 0 3px 3px 0; color: #fff; font-weight: bold;'
)
// #endif
// 线使
// console.log('%c uni-appuni-app & uniCloud hr2013@dcloud.io', 'color: red');
console.log('App Launch');
// #ifdef APP-PLUS
// AppuniCloudhttps://ext.dcloud.net.cn/plugin?id=4542
if (plus.runtime.appid !== 'HBuilder') { // appid'HBuilder'appid
checkUpdate()
}
//
uni.preLogin({
provider: 'univerify',
success: (res) => {
//
this.setUniverifyErrorMsg();
console.log("preLogin success: ", res);
},
fail: (res) => {
this.setUniverifyLogin(false);
this.setUniverifyErrorMsg(res.errMsg);
//
console.log("preLogin fail res: ", res);
}
})
// #endif
},
onShow: function() {
console.log('App Show')
},
onHide: function() {
console.log('App Hide')
},
globalData: {
test: ''
},
methods: {
...mapMutations(['setUniverifyErrorMsg', 'setUniverifyLogin'])
}
}
</script>
<style lang="scss">
@import '@/uni_modules/uni-scss/index.scss';
/* #ifndef APP-PLUS-NVUE */
/* uni.css - 通用组件、模板样式库可以当作一套ui库应用 */
@import './common/uni.css';
@import '@/static/customicons.css';
/* H5 兼容 pc 所需 */
/* #ifdef H5 */
@media screen and (min-width: 768px) {
body {
overflow-y: scroll;
}
}
/* 顶栏通栏样式 */
/* .uni-top-window {
left: 0;
right: 0;
} */
uni-page-body {
background-color: #F5F5F5 !important;
min-height: 100% !important;
height: auto !important;
}
.uni-top-window uni-tabbar .uni-tabbar {
background-color: #fff !important;
}
.uni-app--showleftwindow .hideOnPc {
display: none !important;
}
/* #endif */
/* 以下样式用于 hello uni-app 演示所需 */
page {
background-color: #efeff4;
height: 100%;
font-size: 28rpx;
/* line-height: 1.8; */
}
.fix-pc-padding {
padding: 0 50px;
}
.uni-header-logo {
padding: 30rpx;
flex-direction: column;
justify-content: center;
align-items: center;
margin-top: 10rpx;
}
.uni-header-image {
width: 100px;
height: 100px;
}
.uni-hello-text {
color: #7A7E83;
}
.uni-hello-addfile {
text-align: center;
line-height: 300rpx;
background: #FFF;
padding: 50rpx;
margin-top: 10px;
font-size: 38rpx;
color: #808080;
}
/* #endif*/
</style>

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 DCloud
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,3 +1,39 @@
# yitisheng-mini-app
# zyb-mini-app
艺体生 微信小程序 前端代码
#### 介绍
{**以下是 Gitee 平台说明,您可以替换此简介**
Gitee 是 OSCHINA 推出的基于 Git 的代码托管平台(同时支持 SVN。专为开发者提供稳定、高效、安全的云端软件开发协作平台
无论是个人、团队、或是企业,都能够用 Gitee 实现代码托管、项目管理、协作开发。企业项目请看 [https://gitee.com/enterprises](https://gitee.com/enterprises)}
#### 软件架构
软件架构说明
#### 安装教程
1. xxxx
2. xxxx
3. xxxx
#### 使用说明
1. xxxx
2. xxxx
3. xxxx
#### 参与贡献
1. Fork 本仓库
2. 新建 Feat_xxx 分支
3. 提交代码
4. 新建 Pull Request
#### 特技
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)

173
changelog.md Normal file
View File

@ -0,0 +1,173 @@
## 3.4.52024-01-11
- 新增 uni-calendar显示
## 3.4.42024-01-11
- 新增 同步 uni-ui@1.4.20
- uni-forms 【重要】组件逻辑重构,部分用法旧版本不兼容,请注意兼容问题
- uni-section 新增组件
## 3.4.32022-07-14
- 修复 HBuilderX 拉取 hello uni-app 项目直接运行提示无服务空间关联的bug
## 3.4.22022-07-06
- 新增 同步 uni-ui@1.4.18
- uni-forms 【重要】组件逻辑重构,部分用法旧版本不兼容,请注意兼容问题
- uni-forms 【重要】组件使用 Provide/Inject 方式注入依赖,提供了自定义表单组件调用 uni-forms 校验表单的能力
- uni-forms 新增 更多表单示例
- uni-forms 新增 model 属性,等同于原 value/modelValue 属性,旧属性即将废弃
- uni-forms 新增 validateTrigger 属性的 blur 值,仅 uni-easyinput 生效
- uni-forms 新增 onFieldChange 方法可以对子表单进行校验可替代binddata方法
- uni-forms 新增 子表单的 setRules 方法,配合自定义校验函数使用
- uni-forms 新增 uni-forms-item 的 setRules 方法,配置动态表单使用可动态更新校验规则
- uni-forms 修复 由 1.4.0 引发的 label 插槽不生效的bug
- uni-forms 修复 子组件找不到 setValue 报错的bug
- uni-forms 修复 uni-data-picker 在 uni-forms-item 中报错的bug
- uni-forms 修复 uni-data-picker 在 uni-forms-item 中宽度不正确的bug
- uni-forms 修复 表单校验顺序无序问题
- uni-forms 优化 子表单组件uni-datetime-picker、uni-data-select、uni-data-picker的显示样式
- uni-forms 优化 动态表单校验方式废弃拼接name的方式
- uni-breadcrumb 修复 微信小程序 separator 不显示问题
- uni-data-checkbox 优化 在 uni-forms 中的依赖注入方式
- uni-data-picker 修复 uni-data-picker 在 uni-forms-item 中宽度不正确的bug
- uni-data-picker 优化 显示样式
- uni-data-select 优化 显示样式
- uni-datetime-picker 修复 日历顶部年月及底部确认未国际化 bug
- uni-datetime-picker 优化 组件样式调整了组件图标大小、高度、颜色等与uni-ui风格保持一致
- uni-easyinput 新增 在 uni-forms 1.4.0 中使用可以在 blur 时校验内容
- uni-easyinput 新增 clear 事件,点击右侧叉号图标触发
- uni-easyinput 新增 change 事件 ,仅在输入框失去焦点或用户按下回车时触发
- uni-easyinput 优化 组件样式,组件获取焦点时高亮显示,图标颜色调整等
- uni-easyinput 优化 clearable 显示策略
- uni-file-picker 修复 在uni-forms下样式不生效的bug
- uni-nav-bar 修复 组件示例中插槽用法无法显示内容的bug
- uni-swipe-action 修复 vue3 下使用组件不能正常运行的Bug
- uni-swipe-action 修复 h5端点击click触发两次的Bug
- uni-table 修复 微信小程序存在无使用组件的问题
## 3.4.12022-06-30
- 新增 支持 ios 安全区
## 3.3.82022-05-08
- 新增 同步 uni-ui@1.4.15
- uni-data-picker 修复 字节小程序 本地数据无法选择下一级的Bug
- uni-data-select 新增 记住上次的选项(仅 collection 存在时有效)
- uni-search-bar 修复 vue3 input 事件不生效的bug
- uni-search-bar 修复 多余代码导致的bug
- uni-tooltip 更新 text 属性变更为 content
- uni-tooltip 更新 移除 width 属性
- uni-tooltip 修复 组件根 text 嵌套组件 warning
## 3.3.72022-04-06
- 新增 更新扩展组件 uni-nav-bar、uni-list 的展示页面
## 3.3.62022-03-31
- 更新 uni-ui 组件及示例
## 3.3.52022-03-30
- 修复 插槽兼容 vue3 slot -> v-slot
- 新增 更新 uni-ui
## 3.3.42022-02-25
- 修复 编译到 App 平台的控制台报错
## 3.3.32022-02-23
- 修复 模板城市选择 vue3 报错的bug
- 修复 删除 map.nvue 中多余的 enableOverlooking 变量
- 修复 swipe-dot.nvue 中条件编译媒体查询
## 3.3.22022-01-26
- 修复 默认运行到 vue2
## 3.3.12022-01-26
- 新增 同步 uni-ui@1.4.11
- uni-collapse 修复 微信小程序resize后组件收起的bug
- uni-countdown 修复 在微信小程序中样式不生效的bug
- uni-countdown 新增 update 方法 ,在动态更新时间后,刷新组件
- uni-load-more 新增 showText属性 ,是否显示文本
- uni-load-more 修复 nvue 平台下不显示文本的bug
- uni-load-more 修复 微信小程序平台样式选择器报警告的问题
- uni-nav-bar 修复 在vue下标题不垂直居中的bug
- uni-nav-bar 修复 height 属性类型错误
- uni-nav-bar 新增 height 属性,可修改组件高度
- uni-nav-bar 新增 dark 属性可可开启暗黑模式
- uni-nav-bar 优化 标题字数过多显示省略号
- uni-nav-bar 优化 插槽,插入内容可完全覆盖
- uni-popup 修复 isMaskClick 失效的bug
- uni-popup 新增 cancelText \ confirmText 属性 ,可自定义文本
- uni-popup 新增 maskBackgroundColor 属性 ,可以修改蒙版颜色
- uni-popup 优化 maskClick属性 更新为 isMaskClick ,解决微信小程序警告的问题
## 3.3.02022-01-04
- 修复 开发时在 vue3 下由 pc 端切换到手机端,不能返回上一级页面的 bug
- 优化 去掉 pc 端 topwindow 右上角用于演示的 url 导航
## 3.2.122021-12-20
- 新增 适配京东小程序
## 3.2.112021-12-07
- 修复 uni-ui 在 hello-uniapp 中丢失图标、ui 受到公共样式影响等问题
- 修复 微信登录取值报错的问题
## 3.2.102021-11-30
- 修复 map 组件示例不显示的 bug
## 3.2.92021-11-19
- 新增 uni-ui 以 uni_modules 方式引入,方便开发者从 hello-uniapp 中 copy 组件及示例
- 优化 uni-ui 示例页面,完善组件示例
## 3.2.82021-11-10
- 新增 适配飞书平台lark
## 3.2.72021-10-26
- 修复 uni-popup 示例的 button 文字在 iPhone 5 上换行的 bug
- 修复 uni-table 示例,页面顶部距离不对的 bug
- 修复 GlobalData示例在vue3是无效的 bug
- 优化 删除无用的 project.swan.json 文件
## 3.2.62021-10-08
- 由于体验问题,暂时撤销 uni-ui 以 uni_modules 方式引入的修改
## 3.2.42021-09-07
- 修复 vue3 在 H5 编译报错的 bug
- 新增 同步 uni-ui
- 新增 uni-ui 组件支持国际化 i18n
- uni-data-checkbox 修复 在uni-forms中 modelValue 中不存在当前字段,当前字段必填写也不参与校验的问题
- uni-datetime-picker 优化 取消选中时(范围选)直接开始下一次选择, 避免多点一次
- uni-datetime-picker 优化 移动端支持清除按钮,同时支持通过 ref 调用组件的 clear 方法
- uni-datetime-picker 优化 调整字号大小,美化日历界面
- uni-datetime-picker 修复 因国际化导致的 placeholder 失效的 bug
- uni-file-picker 修复 return-type="object" 时且存在v-model时无法删除文件的Bug
- uni-file-picker 新增 参数中返回 fileID 字段
- uni-file-picker 修复 腾讯云传入fileID 不能回显的bug
- uni-file-picker 修复 选择图片后,不能放大的问题
- uni-link 修复 在 nvue 下不显示的 bug
- uni-list 修复 在vue3中to属性在发行应用的时候报错的bug
- uni-search-bar 修复 value 属性与 modelValue 属性不兼容的Bug
- uni-swipe-action 优化 close-all 方法
- uni-collapse 优化 show-arrow 属性默认为true
- uni-collapse 新增 show-arrow 属性,控制是否显示右侧箭头
- uni-data-checkbox 修复 单选 list 模式下 icon 为 left 时,选中图标不显示的问题
- uni-easyinput 修复 在 uni-forms 的动态表单中默认值校验不通过的 bug
- uni-file-picker 修复 由于 0.2.11 版本引起的不能回显图片的Bug
- uni-file-picker 新增 clearFiles(index) 方法,可以手动删除指定文件
- uni-file-picker 修复 v-model 值设为 null 报错的Bug
- uni-swipe-action 新增 close-all 方法,关闭所有已打开的组件
- uni-swipe-action 新增 resize() 方法在非微信小程序、h5、app-vue端出现不能滑动的问题的时候重置组件
- uni-swipe-action 修复 app 端偶尔出现类似 Page[x][-x,xx;-x,xx,x,x-x] 的问题
- uni-swipe-action 优化 微信小程序、h5、app-vue 滑动逻辑,避免出现动态新增组件后不能滑动的问题
## 3.2.32021-08-27
- 优化 tabbar 页面移除 vuex 相关代码
- 新增 适配 vue3 (app)
## 3.2.22021-08-10
- 新增 适配快手小程序
- 新增 同步 uni-ui
- uni-datetime-picker 新增 return-type 属性支持返回 date 日期对象
- uni-file-picker 修复 fileExtname属性不指定值报错的Bug
- uni-file-picker 修复 在某种场景下图片不回显的Bug
- uni-link 支持自定义插槽
- uni-calendar 修复 弹出层被 tabbar 遮盖 bug
- uni-dateformat 调整 默认时间不再是当前时间,而是显示'-'字符
- uni-datetime-picker 新增 适配 vue3
- uni-datetime-picker 新增 支持作为 uni-forms 子组件相关功能
- uni-datetime-picker 修复 在 uni-forms 中使用时,选择时间报 NAN 错误的 bug
- uni-datetime-picker 修复 type 属性动态赋值无效的 bug
- uni-datetime-picker 修复 ‘确认’按钮被 tabbar 遮盖 bug
- uni-datetime-picker 修复 组件未赋值时范围选左、右日历相同的 bug
- uni-datetime-picker 修复 范围选未正确显示当前值的 bug
- uni-datetime-picker 修复 h5 平台(移动端)报错 'cale' of undefined 的 bug
- uni-file-picker 修复 auto-upload 属性失效的Bug
## 3.2.12021-07-31
- 新增 同步 uni-ui@1.3.8
## 3.2.02021-07-30
- 新增 同时兼容 vue2 & vue3
## 3.1.202021-07-30
- 新增 同时兼容 vue2 & vue3
## 3.1.172021-05-26
- 修复 3.1.16 依赖 sass 的问题
- 条件编译 nuve 不支持 css 属性
## 3.1.162021-05-26
- 修复 uni-data-checkbox 不关联服务空间的情况下组件报错的 Bug
## 3.1.122021-05-07
- hello-uniapp 发布插件市场

45
common/ApiConstant.js Normal file
View File

@ -0,0 +1,45 @@
export default {
Major: {
recommendMajorPage: '/art/recommendMajor/page',//获取推荐专业列表
recommendMajorList: '/art/recommendMajor/list',//获取学校的其他专业
schoolMajorDtoPage: '/yx/yxSchoolMajor/dtoPage',//获取学校开设专业分页数据
schoolHistoryMajorEnrollList: '/yx/yxHistoryMajorEnroll/list',//获取学校的分数计划
schoolMajorList: '/yx/yxSchoolMajor/list',//获取school_major 数据
majorList: '/yx/yxMajor/list',//获取专业信息表-分页列表查询
majorInfo: '/art/major/majorInfo',//获取专业详情
},
//用户类
User: {
exchangeVipCard: '/yx/yxVipCard/exchange',//兑换vip卡
},
System: {
findPassWord: '/sys/findPassWord',//找回密码
register: '/sys/register',//注册
},
//高考分数类
Score: {
scoreSave: "/yx/yxScore/save",//保存用户专业得分
getScore: "/yx/yxScore/getUserScoreInfo",//获取当前用户的高考分数信息
conversionScoreBatch: "/yx/yxHistoryScoreBatch/conversionScoreBatch",//获取分数批次段
historyScoreControlLineList: '/yx/yxHistoryScoreControlLine/list',//省控线分页列表
},
//学校类
School: {
searchSchoolList: "/art/school/search",//搜索 学校列表
schoolInfo: "/art/school/schoolInfo",//学校介绍详情
hotSchoolList: '/art/school/hotList',//热门院校 列表
},
//志愿
Volunteer: {
volunteerSave: "/art/volunteer/save",//保存用户的志愿
//volunteerList:'/art/volunteer/list',
volunteerInfo: '/art/volunteer/info',//当前使用中志愿单详情
volunteerPage: '/art/volunteer/page',//志愿单列表
volunteerDelete:'/art/volunteer/delete',//志愿单删除
artVolunteerDetail:'/art/volunteer/artVolunteerDetail',//根据id获取志愿单详情
volunteerRecordDel: '/art/volunteer/recordDel',//删除志愿明细(失效了)
volunteerRecordDelete:'/art/volunteer/volunteerRecordDelete',//删除志愿明细
volunteerRecordReplace: '/art/volunteer/replaceVolunteer',//替换志愿明细
}
}

1304
common/StaticConstant.js Normal file

File diff suppressed because it is too large Load Diff

262
common/airport.js Normal file
View File

@ -0,0 +1,262 @@
export default {
"list": [{
"letter": "A",
"data": [
"阿克苏机场",
"阿拉山口机场",
"阿勒泰机场",
"阿里昆莎机场",
"安庆天柱山机场",
"澳门国际机场"
]
}, {
"letter": "B",
"data": [
"保山机场",
"包头机场",
"北海福成机场",
"北京南苑机场",
"北京首都国际机场"
]
}, {
"letter": "C",
"data": [
"长白山机场",
"长春龙嘉国际机场",
"常德桃花源机场",
"昌都邦达机场",
"长沙黄花国际机场",
"长治王村机场",
"常州奔牛机场",
"成都双流国际机场",
"赤峰机场"
]
}, {
"letter": "D",
"data": [
"大理机场",
"大连周水子国际机场",
"大庆萨尔图机场",
"大同东王庄机场",
"达州河市机场",
"丹东浪头机场",
"德宏芒市机场",
"迪庆香格里拉机场",
"东营机场",
"敦煌机场"
]
}, {
"letter": "E",
"data": [
"鄂尔多斯机场",
"恩施许家坪机场",
"二连浩特赛乌苏国际机场"
]
}, {
"letter": "F",
"data": [
"阜阳西关机场",
"福州长乐国际机场"
]
}, {
"letter": "G",
"data": [
"赣州黄金机场",
"格尔木机场",
"固原六盘山机场",
"广元盘龙机场",
"广州白云国际机场",
"桂林两江国际机场",
"贵阳龙洞堡国际机场"
]
}, {
"letter": "H",
"data": [
"哈尔滨太平国际机场",
"哈密机场",
"海口美兰国际机场",
"海拉尔东山国际机场",
"邯郸机场",
"汉中机场",
"杭州萧山国际机场",
"合肥骆岗国际机场",
"和田机场",
"黑河机场",
"呼和浩特白塔国际机场",
"淮安涟水机场",
"黄山屯溪国际机场"
]
}, {
"letter": "I",
"data": []
}, {
"letter": "J",
"data": [
"济南遥墙国际机场",
"济宁曲阜机场",
"鸡西兴凯湖机场",
"佳木斯东郊机场",
"嘉峪关机场",
"锦州小岭子机场",
"景德镇机场",
"井冈山机场",
"九江庐山机场",
"九寨黄龙机场"
]
}, {
"letter": "K",
"data": [
"喀什机场",
"克拉玛依机场",
"库车龟兹机场",
"库尔勒机场",
"昆明巫家坝国际机场"
]
}, {
"letter": "L",
"data": [
"拉萨贡嘎机场",
"兰州中川机场",
"丽江三义机场",
"黎平机场",
"连云港白塔埠机场",
"临沧机场",
"临沂机场",
"林芝米林机场",
"柳州白莲机场",
"龙岩冠豸山机场",
"泸州蓝田机场",
"洛阳北郊机场"
]
}, {
"letter": "M",
"data": [
"满洲里西郊机场",
"绵阳南郊机场",
"漠河古莲机场",
"牡丹江海浪机场"
]
}, {
"letter": "N",
"data": [
"南昌昌北国际机场",
"南充高坪机场",
"南京禄口国际机场",
"南宁吴圩机场",
"南通兴东机场",
"南阳姜营机场",
"宁波栎社国际机场"
]
}, {
"letter": "O",
"data": []
}, {
"letter": "P",
"data": [
"普洱思茅机场"
]
}, {
"letter": "Q",
"data": [
"齐齐哈尔三家子机场",
"秦皇岛山海关机场",
"青岛流亭国际机场",
"衢州机场",
"泉州晋江机场"
]
}, {
"letter": "R",
"data": [
"日喀则和平机场"
]
}, {
"letter": "S",
"data": [
"三亚凤凰国际机场",
"汕头外砂机场",
"上海虹桥国际机场",
"上海浦东国际机场",
"深圳宝安国际机场",
"沈阳桃仙国际机场",
"石家庄正定国际机场",
"苏南硕放国际机场"
]
}, {
"letter": "T",
"data": [
"塔城机场",
"太原武宿国际机场",
"台州路桥机场 (黄岩机场)",
"唐山三女河机场",
"腾冲驼峰机场",
"天津滨海国际机场",
"通辽机场",
"铜仁凤凰机场"
]
}, {
"letter": "U",
"data": []
}, {
"letter": "V",
"data": []
}, {
"letter": "W",
"data": [
"万州五桥机场",
"潍坊机场",
"威海大水泊机场",
"文山普者黑机场",
"温州永强国际机场",
"乌海机场",
"武汉天河国际机场",
"乌兰浩特机场",
"乌鲁木齐地窝堡国际机场",
"武夷山机场",
"梧州长洲岛机场"
]
}, {
"letter": "X",
"data": [
"西安咸阳国际机场",
"西昌青山机场",
"锡林浩特机场",
"西宁曹家堡机场",
"西双版纳嘎洒机场",
"厦门高崎国际机场",
"香港国际机场",
"襄阳刘集机场",
"兴义机场",
"徐州观音机场"
]
}, {
"letter": "Y",
"data": [
"延安二十里堡机场",
"盐城机场",
"延吉朝阳川机场",
"烟台莱山国际机场",
"宜宾菜坝机场",
"宜昌三峡机场",
"伊春林都机场",
"伊宁机场",
"义乌机场",
"银川河东机场",
"永州零陵机场",
"榆林榆阳机场",
"玉树巴塘机场",
"运城张孝机场"
]
}, {
"letter": "Z",
"data": [
"湛江机场",
"昭通机场",
"郑州新郑国际机场",
"芷江机场",
"重庆江北国际机场",
"中卫香山机场",
"舟山朱家尖机场",
"珠海三灶机场"
]
}]
}

97
common/graceChecker.js Normal file
View File

@ -0,0 +1,97 @@
/**
数据验证表单验证
来自 grace.hcoder.net
作者 hcoder 深海
*/
export default {
error:'',
check : function (data, rule){
for(var i = 0; i < rule.length; i++){
if (!rule[i].checkType){return true;}
if (!rule[i].name) {return true;}
if (!rule[i].errorMsg) {return true;}
if (!data[rule[i].name]) {this.error = rule[i].errorMsg; return false;}
switch (rule[i].checkType){
case 'string':
var reg = new RegExp('^.{' + rule[i].checkRule + '}$');
if(!reg.test(data[rule[i].name])) {this.error = rule[i].errorMsg; return false;}
break;
case 'int':
var reg = new RegExp('^(-[1-9]|[1-9])[0-9]{' + rule[i].checkRule + '}$');
if(!reg.test(data[rule[i].name])) {this.error = rule[i].errorMsg; return false;}
break;
break;
case 'between':
if (!this.isNumber(data[rule[i].name])){
this.error = rule[i].errorMsg;
return false;
}
var minMax = rule[i].checkRule.split(',');
minMax[0] = Number(minMax[0]);
minMax[1] = Number(minMax[1]);
if (data[rule[i].name] > minMax[1] || data[rule[i].name] < minMax[0]) {
this.error = rule[i].errorMsg;
return false;
}
break;
case 'betweenD':
var reg = /^-?[1-9][0-9]?$/;
if (!reg.test(data[rule[i].name])) { this.error = rule[i].errorMsg; return false; }
var minMax = rule[i].checkRule.split(',');
minMax[0] = Number(minMax[0]);
minMax[1] = Number(minMax[1]);
if (data[rule[i].name] > minMax[1] || data[rule[i].name] < minMax[0]) {
this.error = rule[i].errorMsg;
return false;
}
break;
case 'betweenF':
var reg = /^-?[0-9][0-9]?.+[0-9]+$/;
if (!reg.test(data[rule[i].name])){this.error = rule[i].errorMsg; return false;}
var minMax = rule[i].checkRule.split(',');
minMax[0] = Number(minMax[0]);
minMax[1] = Number(minMax[1]);
if (data[rule[i].name] > minMax[1] || data[rule[i].name] < minMax[0]) {
this.error = rule[i].errorMsg;
return false;
}
break;
case 'same':
if (data[rule[i].name] != rule[i].checkRule) { this.error = rule[i].errorMsg; return false;}
break;
case 'notsame':
if (data[rule[i].name] == rule[i].checkRule) { this.error = rule[i].errorMsg; return false; }
break;
case 'email':
var reg = /^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
if (!reg.test(data[rule[i].name])) { this.error = rule[i].errorMsg; return false; }
break;
case 'phoneno':
var reg = /^1[0-9]{10,10}$/;
if (!reg.test(data[rule[i].name])) { this.error = rule[i].errorMsg; return false; }
break;
case 'zipcode':
var reg = /^[0-9]{6}$/;
if (!reg.test(data[rule[i].name])) { this.error = rule[i].errorMsg; return false; }
break;
case 'reg':
var reg = new RegExp(rule[i].checkRule);
if (!reg.test(data[rule[i].name])) { this.error = rule[i].errorMsg; return false; }
break;
case 'in':
if(rule[i].checkRule.indexOf(data[rule[i].name]) == -1){
this.error = rule[i].errorMsg; return false;
}
break;
case 'notnull':
if(data[rule[i].name] == null || data[rule[i].name].length < 1){this.error = rule[i].errorMsg; return false;}
break;
}
}
return true;
},
isNumber : function (checkVal){
var reg = /^-?[1-9][0-9]?.?[0-9]*$/;
return reg.test(checkVal);
}
}

352
common/html-parser.js Normal file
View File

@ -0,0 +1,352 @@
/*
* HTML5 Parser By Sam Blowes
*
* Designed for HTML5 documents
*
* Original code by John Resig (ejohn.org)
* http://ejohn.org/blog/pure-javascript-html-parser/
* Original code by Erik Arvidsson, Mozilla Public License
* http://erik.eae.net/simplehtmlparser/simplehtmlparser.js
*
* ----------------------------------------------------------------------------
* License
* ----------------------------------------------------------------------------
*
* This code is triple licensed using Apache Software License 2.0,
* Mozilla Public License or GNU Public License
*
* ////////////////////////////////////////////////////////////////////////////
*
* 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
*
* ////////////////////////////////////////////////////////////////////////////
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Simple HTML Parser.
*
* The Initial Developer of the Original Code is Erik Arvidsson.
* Portions created by Erik Arvidssson are Copyright (C) 2004. All Rights
* Reserved.
*
* ////////////////////////////////////////////////////////////////////////////
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* ----------------------------------------------------------------------------
* Usage
* ----------------------------------------------------------------------------
*
* // Use like so:
* HTMLParser(htmlString, {
* start: function(tag, attrs, unary) {},
* end: function(tag) {},
* chars: function(text) {},
* comment: function(text) {}
* });
*
* // or to get an XML string:
* HTMLtoXML(htmlString);
*
* // or to get an XML DOM Document
* HTMLtoDOM(htmlString);
*
* // or to inject into an existing document/DOM node
* HTMLtoDOM(htmlString, document);
* HTMLtoDOM(htmlString, document.body);
*
*/
// Regular Expressions for parsing tags and attributes
var startTag = /^<([-A-Za-z0-9_]+)((?:\s+[a-zA-Z_:][-a-zA-Z0-9_:.]*(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/;
var endTag = /^<\/([-A-Za-z0-9_]+)[^>]*>/;
var attr = /([a-zA-Z_:][-a-zA-Z0-9_:.]*)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/g; // Empty Elements - HTML 5
var empty = makeMap('area,base,basefont,br,col,frame,hr,img,input,link,meta,param,embed,command,keygen,source,track,wbr'); // Block Elements - HTML 5
// fixed by xxx 将 ins 标签从块级名单中移除
var block = makeMap('a,address,article,applet,aside,audio,blockquote,button,canvas,center,dd,del,dir,div,dl,dt,fieldset,figcaption,figure,footer,form,frameset,h1,h2,h3,h4,h5,h6,header,hgroup,hr,iframe,isindex,li,map,menu,noframes,noscript,object,ol,output,p,pre,section,script,table,tbody,td,tfoot,th,thead,tr,ul,video'); // Inline Elements - HTML 5
var inline = makeMap('abbr,acronym,applet,b,basefont,bdo,big,br,button,cite,code,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,textarea,tt,u,var'); // Elements that you can, intentionally, leave open
// (and which close themselves)
var closeSelf = makeMap('colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr'); // Attributes that have their values filled in disabled="disabled"
var fillAttrs = makeMap('checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected'); // Special Elements (can contain anything)
var special = makeMap('script,style');
function HTMLParser(html, handler) {
var index;
var chars;
var match;
var stack = [];
var last = html;
stack.last = function () {
return this[this.length - 1];
};
while (html) {
chars = true; // Make sure we're not in a script or style element
if (!stack.last() || !special[stack.last()]) {
// Comment
if (html.indexOf('<!--') == 0) {
index = html.indexOf('-->');
if (index >= 0) {
if (handler.comment) {
handler.comment(html.substring(4, index));
}
html = html.substring(index + 3);
chars = false;
} // end tag
} else if (html.indexOf('</') == 0) {
match = html.match(endTag);
if (match) {
html = html.substring(match[0].length);
match[0].replace(endTag, parseEndTag);
chars = false;
} // start tag
} else if (html.indexOf('<') == 0) {
match = html.match(startTag);
if (match) {
html = html.substring(match[0].length);
match[0].replace(startTag, parseStartTag);
chars = false;
}
}
if (chars) {
index = html.indexOf('<');
var text = index < 0 ? html : html.substring(0, index);
html = index < 0 ? '' : html.substring(index);
if (handler.chars) {
handler.chars(text);
}
}
} else {
html = html.replace(new RegExp('([\\s\\S]*?)<\/' + stack.last() + '[^>]*>'), function (all, text) {
text = text.replace(/<!--([\s\S]*?)-->|<!\[CDATA\[([\s\S]*?)]]>/g, '$1$2');
if (handler.chars) {
handler.chars(text);
}
return '';
});
parseEndTag('', stack.last());
}
if (html == last) {
throw 'Parse Error: ' + html;
}
last = html;
} // Clean up any remaining tags
parseEndTag();
function parseStartTag(tag, tagName, rest, unary) {
tagName = tagName.toLowerCase();
if (block[tagName]) {
while (stack.last() && inline[stack.last()]) {
parseEndTag('', stack.last());
}
}
if (closeSelf[tagName] && stack.last() == tagName) {
parseEndTag('', tagName);
}
unary = empty[tagName] || !!unary;
if (!unary) {
stack.push(tagName);
}
if (handler.start) {
var attrs = [];
rest.replace(attr, function (match, name) {
var value = arguments[2] ? arguments[2] : arguments[3] ? arguments[3] : arguments[4] ? arguments[4] : fillAttrs[name] ? name : '';
attrs.push({
name: name,
value: value,
escaped: value.replace(/(^|[^\\])"/g, '$1\\\"') // "
});
});
if (handler.start) {
handler.start(tagName, attrs, unary);
}
}
}
function parseEndTag(tag, tagName) {
// If no tag name is provided, clean shop
if (!tagName) {
var pos = 0;
} // Find the closest opened tag of the same type
else {
for (var pos = stack.length - 1; pos >= 0; pos--) {
if (stack[pos] == tagName) {
break;
}
}
}
if (pos >= 0) {
// Close all the open elements, up the stack
for (var i = stack.length - 1; i >= pos; i--) {
if (handler.end) {
handler.end(stack[i]);
}
} // Remove the open elements from the stack
stack.length = pos;
}
}
}
function makeMap(str) {
var obj = {};
var items = str.split(',');
for (var i = 0; i < items.length; i++) {
obj[items[i]] = true;
}
return obj;
}
function removeDOCTYPE(html) {
return html.replace(/<\?xml.*\?>\n/, '').replace(/<!doctype.*>\n/, '').replace(/<!DOCTYPE.*>\n/, '');
}
function parseAttrs(attrs) {
return attrs.reduce(function (pre, attr) {
var value = attr.value;
var name = attr.name;
if (pre[name]) {
pre[name] = pre[name] + " " + value;
} else {
pre[name] = value;
}
return pre;
}, {});
}
function parseHtml(html) {
html = removeDOCTYPE(html);
var stacks = [];
var results = {
node: 'root',
children: []
};
HTMLParser(html, {
start: function start(tag, attrs, unary) {
var node = {
name: tag
};
if (attrs.length !== 0) {
node.attrs = parseAttrs(attrs);
}
if (unary) {
var parent = stacks[0] || results;
if (!parent.children) {
parent.children = [];
}
parent.children.push(node);
} else {
stacks.unshift(node);
}
},
end: function end(tag) {
var node = stacks.shift();
if (node.name !== tag) console.error('invalid state: mismatch end tag');
if (stacks.length === 0) {
results.children.push(node);
} else {
var parent = stacks[0];
if (!parent.children) {
parent.children = [];
}
parent.children.push(node);
}
},
chars: function chars(text) {
var node = {
type: 'text',
text: text
};
if (stacks.length === 0) {
results.children.push(node);
} else {
var parent = stacks[0];
if (!parent.children) {
parent.children = [];
}
parent.children.push(node);
}
},
comment: function comment(text) {
var node = {
node: 'comment',
text: text
};
var parent = stacks[0];
if (!parent.children) {
parent.children = [];
}
parent.children.push(node);
}
});
return results.children;
}
export default parseHtml;

17
common/operate.js Normal file
View File

@ -0,0 +1,17 @@
export default {
//接口
api: "http://127.0.0.1:8080/jeecg-boot/",
/*api: function () {
let version = wx.getAccountInfoSync().miniProgram.envVersion;
switch (version) {
case "dev": //开发预览版
return "http://127.0.0.1:8080/jeecg-boot/"
break;
case 'prod': //正式版
return "http://127.0.0.1:8080/jeecg-boot/"
break;
default: //未知,默认调用正式版
return "http://127.0.0.1:8080/jeecg-boot/"
}
}*/
}

245
common/permission.js Normal file
View File

@ -0,0 +1,245 @@
/// null = 未请求1 = 已允许0 = 拒绝|受限, 2 = 系统未开启
var isIOS
function album() {
var result = 0;
var PHPhotoLibrary = plus.ios.import("PHPhotoLibrary");
var authStatus = PHPhotoLibrary.authorizationStatus();
if (authStatus === 0) {
result = null;
} else if (authStatus == 3) {
result = 1;
} else {
result = 0;
}
plus.ios.deleteObject(PHPhotoLibrary);
return result;
}
function camera() {
var result = 0;
var AVCaptureDevice = plus.ios.import("AVCaptureDevice");
var authStatus = AVCaptureDevice.authorizationStatusForMediaType('vide');
if (authStatus === 0) {
result = null;
} else if (authStatus == 3) {
result = 1;
} else {
result = 0;
}
plus.ios.deleteObject(AVCaptureDevice);
return result;
}
function location() {
var result = 0;
var cllocationManger = plus.ios.import("CLLocationManager");
var enable = cllocationManger.locationServicesEnabled();
var status = cllocationManger.authorizationStatus();
if (!enable) {
result = 2;
} else if (status === 0) {
result = null;
} else if (status === 3 || status === 4) {
result = 1;
} else {
result = 0;
}
plus.ios.deleteObject(cllocationManger);
return result;
}
function push() {
var result = 0;
var UIApplication = plus.ios.import("UIApplication");
var app = UIApplication.sharedApplication();
var enabledTypes = 0;
if (app.currentUserNotificationSettings) {
var settings = app.currentUserNotificationSettings();
enabledTypes = settings.plusGetAttribute("types");
if (enabledTypes == 0) {
result = 0;
console.log("推送权限没有开启");
} else {
result = 1;
console.log("已经开启推送功能!")
}
plus.ios.deleteObject(settings);
} else {
enabledTypes = app.enabledRemoteNotificationTypes();
if (enabledTypes == 0) {
result = 3;
console.log("推送权限没有开启!");
} else {
result = 4;
console.log("已经开启推送功能!")
}
}
plus.ios.deleteObject(app);
plus.ios.deleteObject(UIApplication);
return result;
}
function contact() {
var result = 0;
var CNContactStore = plus.ios.import("CNContactStore");
var cnAuthStatus = CNContactStore.authorizationStatusForEntityType(0);
if (cnAuthStatus === 0) {
result = null;
} else if (cnAuthStatus == 3) {
result = 1;
} else {
result = 0;
}
plus.ios.deleteObject(CNContactStore);
return result;
}
function record() {
var result = null;
var avaudiosession = plus.ios.import("AVAudioSession");
var avaudio = avaudiosession.sharedInstance();
var status = avaudio.recordPermission();
console.log("permissionStatus:" + status);
if (status === 1970168948) {
result = null;
} else if (status === 1735552628) {
result = 1;
} else {
result = 0;
}
plus.ios.deleteObject(avaudiosession);
return result;
}
function calendar() {
var result = null;
var EKEventStore = plus.ios.import("EKEventStore");
var ekAuthStatus = EKEventStore.authorizationStatusForEntityType(0);
if (ekAuthStatus == 3) {
result = 1;
console.log("日历权限已经开启");
} else {
console.log("日历权限没有开启");
}
plus.ios.deleteObject(EKEventStore);
return result;
}
function memo() {
var result = null;
var EKEventStore = plus.ios.import("EKEventStore");
var ekAuthStatus = EKEventStore.authorizationStatusForEntityType(1);
if (ekAuthStatus == 3) {
result = 1;
console.log("备忘录权限已经开启");
} else {
console.log("备忘录权限没有开启");
}
plus.ios.deleteObject(EKEventStore);
return result;
}
function requestIOS(permissionID) {
return new Promise((resolve, reject) => {
switch (permissionID) {
case "push":
resolve(push());
break;
case "location":
resolve(location());
break;
case "record":
resolve(record());
break;
case "camera":
resolve(camera());
break;
case "album":
resolve(album());
break;
case "contact":
resolve(contact());
break;
case "calendar":
resolve(calendar());
break;
case "memo":
resolve(memo());
break;
default:
resolve(0);
break;
}
});
}
function requestAndroid(permissionID) {
return new Promise((resolve, reject) => {
plus.android.requestPermissions(
[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);
},
function(error) {
console.log('result error: ' + error.message)
resolve({
code: error.code,
message: error.message
});
}
);
});
}
function gotoAppPermissionSetting() {
if (permission.isIOS) {
var UIApplication = plus.ios.import("UIApplication");
var application2 = UIApplication.sharedApplication();
var NSURL2 = plus.ios.import("NSURL");
var setting2 = NSURL2.URLWithString("app-settings:");
application2.openURL(setting2);
plus.ios.deleteObject(setting2);
plus.ios.deleteObject(NSURL2);
plus.ios.deleteObject(application2);
} else {
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);
}
}
const permission = {
get isIOS(){
return typeof isIOS === 'boolean' ? isIOS : (isIOS = uni.getSystemInfoSync().platform === 'ios')
},
requestIOS: requestIOS,
requestAndroid: requestAndroid,
gotoAppSetting: gotoAppPermissionSetting
}
export default permission

124
common/request.js Normal file
View File

@ -0,0 +1,124 @@
/*网络请求*/
import operate from '@/common/operate'
// vuex 的使用 详情参考官网 https://uniapp.dcloud.io/vue-vuex
import store from '../store/index.js'
let token= uni.getStorageSync('token')
token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MDU4ODQ5MDYsInVzZXJuYW1lIjoid2FuZ3hpYW9taW5nIn0.jRSoihlbs08ONDIsrk2U3l3pw8ZQK2Z1Oc2-mQaf7pw'
export default class Request {
http(param) {
// 请求参数
var url = param.url,
method = param.method,
header = {
'X-Access-Token':param.token || "",
},
data = param.data || {},
hideLoading = param.hideLoading || false;
/*token = param.token || "",*/
//拼接完整请求地址
var requestUrl = operate.api + url;
console.log(requestUrl)
//拼接完整请求地址(根据环境切换)
// var requestUrl = operate.api() + url;
//请求方式:GET或POST(POST需配置
// header: {'content-type' : "application/x-www-form-urlencoded"},)
if (method) {
method = method.toUpperCase(); //小写改为大写
if (method === "POST") {
header = {"content-type":'application/json',...header}
} else {
header = {"content-type":'application/x-www-form-urlencoded',...header}
}
}
//加载圈
if (!hideLoading) {
uni.showLoading({
title: '加载中...'
});
}
// 返回promise
return new Promise((resolve, reject) => {
// 请求
uni.request({
url: requestUrl,
data: data,
method: method,
header: header,
success: (res) => {
console.log('执行http请求')
// 判断 请求api 格式是否正确
/*if (res.statusCode && res.statusCode != 200) {
uni.showToast({
title: "api错误" + res.errMsg,
icon: 'none'
});
return;
}*/
// 将结果抛出
resolve(res.data)
},
//请求失败
fail: (e) => {
uni.showToast({
title: "" + e.data.msg,
icon: 'none'
});
resolve(e.data);
},
//请求完成
complete() {
//隐藏加载
if (!hideLoading) {
uni.hideLoading();
}
resolve();
return;
}
})
})
}
get(url,data,options={}){
options.method='get';
options.data=data;
options.url=url;
options.token=token;
return this.http(options);
}
get(url,data,headers={},options={}){
options.method='get';
options.data=data;
options.url=url;
options.token=token;
return this.http(options);
}
post(url,data,options={}){
options.method='post';
options.data=data;
options.url=url;
options.token=token;
return this.http(options);
}
post(url,data,headers={},options={}){
options.method='post';
options.data=data;
options.url=url;
options.token=token;
return this.http(options);
}
delete(url,data,options={}){
options.method='delete';
options.data=data;
options.url=url;
options.token=token;
return this.http(options);
}
}

136
common/uni-nvue.css Normal file
View File

@ -0,0 +1,136 @@
/* #ifndef APP-PLUS-NVUE */
page {
min-height: 100%;
height: auto;
}
/* #endif */
/* 解决头条小程序字体图标不显示问题因为头条运行时自动插入了span标签且有全局字体 */
/* #ifdef MP-TOUTIAO */
/* text :not(view) {
font-family: uniicons;
} */
/* #endif */
.uni-icon {
font-family: uniicons;
font-weight: normal;
}
.uni-container {
padding: 15px;
background-color: #f8f8f8;
}
.uni-header-logo {
/* #ifdef H5 */
display: flex;
/* #endif */
padding: 15px 15px;
flex-direction: column;
justify-content: center;
align-items: center;
margin-top: 10rpx;
}
.uni-header-image {
width: 80px;
height: 80px;
}
.uni-hello-text {
margin-bottom: 20px;
}
.hello-text {
color: #7A7E83;
font-size: 14px;
line-height: 20px;
}
.hello-link {
color: #7A7E83;
font-size: 14px;
line-height: 20px;
}
.uni-panel {
margin-bottom: 12px;
}
.uni-panel-h {
/* #ifdef H5 */
display: flex;
/* #endif */
background-color: #ffffff;
flex-direction: row !important;
/* justify-content: space-between !important; */
align-items: center !important;
padding: 12px;
/* #ifdef H5 */
cursor: pointer;
/* #endif */
}
/*
.uni-panel-h:active {
background-color: #f8f8f8;
}
*/
.uni-panel-h-on {
background-color: #f0f0f0;
}
.uni-panel-text {
flex: 1;
color: #000000;
font-size: 14px;
font-weight: normal;
}
.uni-panel-icon {
margin-left: 15px;
color: #999999;
font-size: 14px;
font-weight: normal;
transform: rotate(0deg);
transition-duration: 0s;
transition-property: transform;
}
.uni-panel-icon-on {
transform: rotate(180deg);
}
.uni-navigate-item {
/* #ifdef H5 */
display: flex;
/* #endif */
flex-direction: row;
align-items: center;
background-color: #FFFFFF;
border-top-style: solid;
border-top-color: #f0f0f0;
border-top-width: 1px;
padding: 12px;
/* #ifdef H5 */
cursor: pointer;
/* #endif */
}
.uni-navigate-item:active {
background-color: #f8f8f8;
}
.uni-navigate-text {
flex: 1;
color: #000000;
font-size: 14px;
font-weight: normal;
}
.uni-navigate-icon {
margin-left: 15px;
color: #999999;
font-size: 14px;
font-weight: normal;
}

1509
common/uni.css Normal file

File diff suppressed because it is too large Load Diff

73
common/util.js Normal file
View File

@ -0,0 +1,73 @@
function formatTime(time) {
if (typeof time !== 'number' || time < 0) {
return time
}
var hour = parseInt(time / 3600)
time = time % 3600
var minute = parseInt(time / 60)
time = time % 60
var second = time
return ([hour, minute, second]).map(function(n) {
n = n.toString()
return n[1] ? n : '0' + n
}).join(':')
}
function formatLocation(longitude, latitude) {
if (typeof longitude === 'string' && typeof latitude === 'string') {
longitude = parseFloat(longitude)
latitude = parseFloat(latitude)
}
longitude = longitude.toFixed(2)
latitude = latitude.toFixed(2)
return {
longitude: longitude.toString().split('.'),
latitude: latitude.toString().split('.')
}
}
var dateUtils = {
UNITS: {
'年': 31557600000,
'月': 2629800000,
'天': 86400000,
'小时': 3600000,
'分钟': 60000,
'秒': 1000
},
humanize: function(milliseconds) {
var humanize = '';
for (var key in this.UNITS) {
if (milliseconds >= this.UNITS[key]) {
humanize = Math.floor(milliseconds / this.UNITS[key]) + key + '前';
break;
}
}
return humanize || '刚刚';
},
format: function(dateStr) {
var date = this.parse(dateStr)
var diff = Date.now() - date.getTime();
if (diff < this.UNITS['天']) {
return this.humanize(diff);
}
var _format = function(number) {
return (number < 10 ? ('0' + number) : number);
};
return date.getFullYear() + '/' + _format(date.getMonth() + 1) + '/' + _format(date.getDate()) + '-' +
_format(date.getHours()) + ':' + _format(date.getMinutes());
},
parse: function(str) { //将"yyyy-mm-dd HH:MM:ss"格式的字符串转化为一个Date对象
var a = str.split(/[^0-9]/);
return new Date(a[0], a[1] - 1, a[2], a[3], a[4], a[5]);
}
};
export {
formatTime,
formatLocation,
dateUtils
}

View File

@ -0,0 +1,181 @@
import amap from '@/components/amap-wx/lib/amap-wx.js';
// 地铁颜色图
const line = {
'1号线': '#C43B33',
'2号线': '#016299',
'4号线/大兴线': '#008E9C',
'5号线': '#A42380',
'6号线': '#D09900',
'7号线': '#F2C172',
'8号线': '#009D6A',
'9号线': '#8FC41E',
'10号线': '#009DBE',
'13号线': '#F9E701',
'14号线东段': '#D4A7A2',
'14号线西段': '#D4A7A2',
'15号线': '#5D2D69',
'八通线': '#C33A32',
'昌平线': '#DE82B1',
'亦庄线': '#E40177',
'房山线': '#E66021',
'机场线': '#A29BBC',
}
// 150500:地铁站 ,150700:公交站 , 190700:地名地址
const typecode = [{
id: '150500',
icon: 'icon-ditie'
}, {
id: '150700',
icon: 'icon-gongjiao'
}, {
id: '190700',
icon: 'icon-gonglu'
}];
const util = {
key:'b526b09b86cd2996e7732be8ab8c4430',
/**
* 初始化高德地图api
*/
mapInit() {
return new amap.AMapWX({
key: this.key
});
},
// 服务状态吗
typecode,
/**
* 获取地图颜色
*/
lineColor(name) {
if (line[name]) {
return line[name];
} else {
return '#ccc';
}
},
/**
* 关键字颜色变化
*/
serachNmme(val, name) {
let namestr = new RegExp(val);
let nameresult =
`<div style="font-size: 14px;color: #333;line-height: 1.5;">
${name.replace(namestr, "<span style='color:#66ccff;'>" + val + '</span>')}
</div>`
.trim();
return nameresult;
},
/**
* 地址转地铁线路
*/
addressToLine(address, type) {
let addr = address.split(';');
let dt = '';
addr.forEach(elm => {
let color = '#cccccc';
if (type === typecode[0].id) {
color = this.lineColor(elm)
} else if (type === typecode[1].id) {
color = '#4075cb'
}
let style = 'margin:5px 0;margin-right:5px;padding:0 5px;background:' + color +
';font-size:12px;color:#fff;border-radius:3px;';
dt += `<div style=\'${style}\'>${elm}</div>`;
});
return `<div style="display:flex;flex-wrap: wrap;">${dt}</div>`;
},
/**
* 数据处理
*/
dataHandle(item, val) {
// 改变字体颜色
if (val) {
item.nameNodes = util.serachNmme(val, item.name);
} else {
item.nameNodes = `<div style="font-size: 14px;color: #333;line-height: 1.5;">${item.name}</div>`;
}
// 地址解析 地铁
if (
item.typecode === util.typecode[0].id ||
item.typecode === util.typecode[1].id
) {
item.addressNodes = util.addressToLine(item.address, item.typecode);
if (item.typecode === util.typecode[0].id) {
item.icon = util.typecode[0].icon;
} else if (item.typecode === util.typecode[1].id) {
item.icon = util.typecode[1].icon;
}
} else {
item.addressNodes = `<span>${item.district}${
item.address.length > 0 ? '·' + item.address : ''
}</span>`.trim();
item.icon = 'icon-weizhi';
}
if (item.location && item.location.length === 0) {
item.icon = 'icon-sousuo';
}
return item;
},
/**
* 存储历史数据
* val [string | object]需要存储的内容
*/
setHistory(val) {
let searchHistory = uni.getStorageSync('search:history');
if (!searchHistory) searchHistory = [];
let serachData = {};
if (typeof(val) === 'string') {
serachData = {
adcode: [],
address: [],
city: [],
district: [],
id: [],
location: [],
name: val,
typecode: []
};
} else {
serachData = val
}
// 判断数组是否存在,如果存在,那么将放到最前面
for (var i = 0; i < searchHistory.length; i++) {
if (searchHistory[i].name === serachData.name) {
searchHistory.splice(i, 1);
break;
}
}
searchHistory.unshift(util.dataHandle(serachData));
uni.setStorage({
key: 'search:history',
data: searchHistory,
success: function() {
// console.log('success');
}
});
},
getHistory() {
},
removeHistory() {
uni.removeStorage({
key: 'search:history',
success: function(res) {
console.log('success');
}
});
return []
}
}
export default util;

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,156 @@
<template>
<view class="uni-padding-wrap">
<page-head :title="title"></page-head>
<button class="button" @click="setTabBarBadge">{{ !hasSetTabBarBadge ? '设置tab徽标' : '移除tab徽标' }}</button>
<button class="button" @click="showTabBarRedDot">{{ !hasShownTabBarRedDot ? '显示红点' : '移除红点'}}</button>
<button class="button" @click="customStyle">{{ !hasCustomedStyle ? '自定义Tab样式' : '移除自定义样式'}}</button>
<button class="button" @click="customItem">{{ !hasCustomedItem ? '自定义Tab信息' : '移除自定义信息' }}</button>
<button class="button" @click="hideTabBar">{{ !hasHiddenTabBar ? '隐藏TabBar' : '显示TabBar' }}</button>
<view class="btn-area">
<button class="button" type="primary" @click="navigateBack">返回上一级</button>
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'tababr',
hasSetTabBarBadge: false,
hasShownTabBarRedDot: false,
hasCustomedStyle: false,
hasCustomedItem: false,
hasHiddenTabBar: false
}
},
destroyed() {
if (this.hasSetTabBarBadge) {
uni.removeTabBarBadge({
index: 1
})
}
if (this.hasShownTabBarRedDot) {
uni.hideTabBarRedDot({
index: 1
})
}
if (this.hasHiddenTabBar) {
uni.showTabBar()
}
if (this.hasCustomedStyle) {
uni.setTabBarStyle({
color: '#7A7E83',
selectedColor: '#007AFF',
backgroundColor: '#F8F8F8',
borderStyle: 'black'
})
}
if (this.hasCustomedItem) {
let tabBarOptions = {
index: 1,
text: '接口',
iconPath: '/static/api.png',
selectedIconPath: '/static/apiHL.png'
}
uni.setTabBarItem(tabBarOptions)
}
},
methods: {
navigateBack() {
this.$emit('unmount')
},
setTabBarBadge() {
if(this.hasShownTabBarRedDot){
uni.hideTabBarRedDot({
index: 1
})
this.hasShownTabBarRedDot = !this.hasShownTabBarRedDot
}
if (!this.hasSetTabBarBadge) {
uni.setTabBarBadge({
index: 1,
text: '1'
})
} else {
uni.removeTabBarBadge({
index: 1
})
}
this.hasSetTabBarBadge = !this.hasSetTabBarBadge
},
showTabBarRedDot() {
if(this.hasSetTabBarBadge) {
uni.removeTabBarBadge({
index: 1
})
this.hasSetTabBarBadge = !this.hasSetTabBarBadge
}
if (!this.hasShownTabBarRedDot) {
uni.showTabBarRedDot({
index: 1
})
} else {
uni.hideTabBarRedDot({
index: 1
})
}
this.hasShownTabBarRedDot = !this.hasShownTabBarRedDot
},
hideTabBar() {
if (!this.hasHiddenTabBar) {
uni.hideTabBar()
} else {
uni.showTabBar()
}
this.hasHiddenTabBar = !this.hasHiddenTabBar
},
customStyle() {
if (this.hasCustomedStyle) {
uni.setTabBarStyle({
color: '#7A7E83',
selectedColor: '#007AFF',
backgroundColor: '#F8F8F8',
borderStyle: 'black'
})
} else {
uni.setTabBarStyle({
color: '#FFF',
selectedColor: '#007AFF',
backgroundColor: '#000000',
borderStyle: 'black'
})
}
this.hasCustomedStyle = !this.hasCustomedStyle
},
customItem() {
let tabBarOptions = {
index: 1,
text: '接口',
iconPath: '/static/api.png',
selectedIconPath: '/static/apiHL.png'
}
if (this.hasCustomedItem) {
uni.setTabBarItem(tabBarOptions)
} else {
tabBarOptions.text = 'API'
uni.setTabBarItem(tabBarOptions)
}
this.hasCustomedItem = !this.hasCustomedItem
}
}
}
</script>
<style>
.button {
margin-top: 30rpx;
margin-left: 0;
margin-right: 0;
}
.btn-area {
padding-top: 30rpx;
}
</style>

View File

@ -0,0 +1 @@
export default './lib/marked'

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,139 @@
/* eslint-disable */
var provinceData = [{
"label": "北京市",
"value": "11"
},
{
"label": "天津市",
"value": "12"
},
{
"label": "河北省",
"value": "13"
},
{
"label": "山西省",
"value": "14"
},
{
"label": "内蒙古自治区",
"value": "15"
},
{
"label": "辽宁省",
"value": "21"
},
{
"label": "吉林省",
"value": "22"
},
{
"label": "黑龙江省",
"value": "23"
},
{
"label": "上海市",
"value": "31"
},
{
"label": "江苏省",
"value": "32"
},
{
"label": "浙江省",
"value": "33"
},
{
"label": "安徽省",
"value": "34"
},
{
"label": "福建省",
"value": "35"
},
{
"label": "江西省",
"value": "36"
},
{
"label": "山东省",
"value": "37"
},
{
"label": "河南省",
"value": "41"
},
{
"label": "湖北省",
"value": "42"
},
{
"label": "湖南省",
"value": "43"
},
{
"label": "广东省",
"value": "44"
},
{
"label": "广西壮族自治区",
"value": "45"
},
{
"label": "海南省",
"value": "46"
},
{
"label": "重庆市",
"value": "50"
},
{
"label": "四川省",
"value": "51"
},
{
"label": "贵州省",
"value": "52"
},
{
"label": "云南省",
"value": "53"
},
{
"label": "西藏自治区",
"value": "54"
},
{
"label": "陕西省",
"value": "61"
},
{
"label": "甘肃省",
"value": "62"
},
{
"label": "青海省",
"value": "63"
},
{
"label": "宁夏回族自治区",
"value": "64"
},
{
"label": "新疆维吾尔自治区",
"value": "65"
},
{
"label": "台湾",
"value": "66"
},
{
"label": "香港",
"value": "67"
},
{
"label": "澳门",
"value": "68"
}
]
export default provinceData;

View File

@ -0,0 +1,230 @@
<template>
<div class="mpvue-picker">
<div :class="{'pickerMask':showPicker}" @click="maskClick" catchtouchmove="true"></div>
<div class="mpvue-picker-content " :class="{'mpvue-picker-view-show':showPicker}">
<div class="mpvue-picker__hd" catchtouchmove="true">
<div class="mpvue-picker__action" @click="pickerCancel">取消</div>
<div class="mpvue-picker__action" :style="{color:themeColor}" @click="pickerConfirm">确定</div>
</div>
<picker-view indicator-style="height: 40px;" class="mpvue-picker-view" :value="pickerValue" @change="pickerChange">
<block>
<picker-view-column>
<div class="picker-item" v-for="(item,index) in provinceDataList" :key="index">{{item.label}}</div>
</picker-view-column>
<picker-view-column>
<div class="picker-item" v-for="(item,index) in cityDataList" :key="index">{{item.label}}</div>
</picker-view-column>
<picker-view-column>
<div class="picker-item" v-for="(item,index) in areaDataList" :key="index">{{item.label}}</div>
</picker-view-column>
</block>
</picker-view>
</div>
</div>
</template>
<script>
import provinceData from './city-data/province.js';
import cityData from './city-data/city.js';
import areaData from './city-data/area.js';
export default {
data() {
return {
pickerValue: [0, 0, 0],
provinceDataList: provinceData,
cityDataList: cityData[0],
areaDataList: areaData[0][0],
/* 是否显示控件 */
showPicker: false,
};
},
created() {
this.init()
},
props: {
/* 默认值 */
pickerValueDefault: {
type: Array,
default () {
return [0, 0, 0]
}
},
/* 主题色 */
themeColor: String
},
watch: {
pickerValueDefault() {
this.init();
}
},
methods: {
init() {
this.handPickValueDefault(); // pickerValueDefault
const pickerValueDefault = this.pickerValueDefault
this.cityDataList = cityData[pickerValueDefault[0]];
this.areaDataList = areaData[pickerValueDefault[0]][pickerValueDefault[1]];
this.pickerValue = pickerValueDefault;
},
show() {
setTimeout(() => {
this.showPicker = true;
}, 0);
},
maskClick() {
this.pickerCancel();
},
pickerCancel() {
this.showPicker = false;
this._$emit('onCancel');
},
pickerConfirm(e) {
this.showPicker = false;
this._$emit('onConfirm');
},
showPickerView() {
this.showPicker = true;
},
handPickValueDefault() {
const pickerValueDefault = this.pickerValueDefault
let provinceIndex = pickerValueDefault[0]
let cityIndex = pickerValueDefault[1]
const areaIndex = pickerValueDefault[2]
if (
provinceIndex !== 0 ||
cityIndex !== 0 ||
areaIndex !== 0
) {
if (provinceIndex > provinceData.length - 1) {
this.pickerValueDefault[0] = provinceIndex = provinceData.length - 1;
}
if (cityIndex > cityData[provinceIndex].length - 1) {
this.pickerValueDefault[1] = cityIndex = cityData[provinceIndex].length - 1;
}
if (areaIndex > areaData[provinceIndex][cityIndex].length - 1) {
this.pickerValueDefault[2] = areaData[provinceIndex][cityIndex].length - 1;
}
}
},
pickerChange(e) {
let changePickerValue = e.mp.detail.value;
if (this.pickerValue[0] !== changePickerValue[0]) {
//
this.cityDataList = cityData[changePickerValue[0]];
this.areaDataList = areaData[changePickerValue[0]][0];
changePickerValue[1] = 0;
changePickerValue[2] = 0;
} else if (this.pickerValue[1] !== changePickerValue[1]) {
//
this.areaDataList =
areaData[changePickerValue[0]][changePickerValue[1]];
changePickerValue[2] = 0;
}
this.pickerValue = changePickerValue;
this._$emit('onChange');
},
_$emit(emitName) {
let pickObj = {
label: this._getLabel(),
value: this.pickerValue,
cityCode: this._getCityCode()
};
this.$emit(emitName, pickObj);
},
_getLabel() {
let pcikerLabel =
this.provinceDataList[this.pickerValue[0]].label +
'-' +
this.cityDataList[this.pickerValue[1]].label +
'-' +
this.areaDataList[this.pickerValue[2]].label;
return pcikerLabel;
},
_getCityCode() {
return this.areaDataList[this.pickerValue[2]].value;
}
}
};
</script>
<style>
.pickerMask {
position: fixed;
z-index: 1000;
top: 0;
right: 0;
left: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.6);
}
.mpvue-picker-content {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
transition: all 0.3s ease;
transform: translateY(100%);
z-index: 3000;
}
.mpvue-picker-view-show {
transform: translateY(0);
}
.mpvue-picker__hd {
display: flex;
padding: 9px 15px;
background-color: #fff;
position: relative;
text-align: center;
font-size: 17px;
}
.mpvue-picker__hd:after {
content: ' ';
position: absolute;
left: 0;
bottom: 0;
right: 0;
height: 1px;
border-bottom: 1px solid #e5e5e5;
color: #e5e5e5;
transform-origin: 0 100%;
transform: scaleY(0.5);
}
.mpvue-picker__action {
display: block;
flex: 1;
color: #1aad19;
}
.mpvue-picker__action:first-child {
text-align: left;
color: #888;
}
.mpvue-picker__action:last-child {
text-align: right;
}
.picker-item {
text-align: center;
line-height: 40px;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 16px;
}
.mpvue-picker-view {
position: relative;
bottom: 0;
left: 0;
width: 100%;
height: 238px;
background-color: rgba(255, 255, 255, 1);
}
</style>

View File

@ -0,0 +1,123 @@
<template>
<canvas v-if="canvasId" class="ec-canvas" :id="canvasId" :canvasId="canvasId" @touchstart="touchStart" @touchmove="touchMove" @touchend="touchEnd" @error="error"></canvas>
</template>
<script>
import WxCanvas from './wx-canvas';
export default {
props: {
canvasId: {
type: String,
default: 'ec-canvas'
},
lazyLoad: {
type: Boolean,
default: false
},
disableTouch: {
type: Boolean,
default: false
},
throttleTouch: {
type: Boolean,
default: false
}
},
// #ifdef H5
mounted() {
if (!this.lazyLoad) this.init();
},
// #endif
// #ifndef H5
onReady() {
if (!this.lazyLoad) this.init();
},
// #endif
methods: {
setChart(chart){
this.chart = chart
},
init() {
const { canvasId } = this;
this.ctx = wx.createCanvasContext(canvasId, this);
this.canvas = new WxCanvas(this.ctx, canvasId);
const query = wx.createSelectorQuery().in(this);
query
.select(`#${canvasId}`)
.boundingClientRect(res => {
if (!res) {
setTimeout(() => this.init(), 50);
return;
}
this.$emit('onInit', {
width: res.width,
height: res.height
});
})
.exec();
},
canvasToTempFilePath(opt) {
const { canvasId } = this;
this.ctx.draw(true, () => {
wx.canvasToTempFilePath({
canvasId,
...opt
});
});
},
touchStart(e) {
const { disableTouch, chart } = this;
if (disableTouch || !chart || !e.mp.touches.length) return;
const touch = e.mp.touches[0];
chart._zr.handler.dispatch('mousedown', {
zrX: touch.x,
zrY: touch.y
});
chart._zr.handler.dispatch('mousemove', {
zrX: touch.x,
zrY: touch.y
});
},
touchMove(e) {
const { disableTouch, throttleTouch, chart, lastMoveTime } = this;
if (disableTouch || !chart || !e.mp.touches.length) return;
if (throttleTouch) {
const currMoveTime = Date.now();
if (currMoveTime - lastMoveTime < 240) return;
this.lastMoveTime = currMoveTime;
}
const touch = e.mp.touches[0];
chart._zr.handler.dispatch('mousemove', {
zrX: touch.x,
zrY: touch.y
});
},
touchEnd(e) {
const { disableTouch, chart } = this;
if (disableTouch || !chart) return;
const touch = e.mp.changedTouches ? e.mp.changedTouches[0] : {};
chart._zr.handler.dispatch('mouseup', {
zrX: touch.x,
zrY: touch.y
});
chart._zr.handler.dispatch('click', {
zrX: touch.x,
zrY: touch.y
});
}
}
};
</script>
<style scoped>
.ec-canvas {
width: 100%;
height: 100%;
flex: 1;
}
</style>

View File

@ -0,0 +1,73 @@
export default class WxCanvas {
constructor(ctx, canvasId) {
this.ctx = ctx;
this.canvasId = canvasId;
this.chart = null;
WxCanvas.initStyle(ctx);
this.initEvent();
}
getContext(contextType) {
return contextType === '2d' ? this.ctx : null;
}
setChart(chart) {
this.chart = chart;
}
attachEvent() {
// noop
}
detachEvent() {
// noop
}
static initStyle(ctx) {
const styles = ['fillStyle', 'strokeStyle', 'globalAlpha',
'textAlign', 'textBaseAlign', 'shadow', 'lineWidth',
'lineCap', 'lineJoin', 'lineDash', 'miterLimit', 'fontSize'];
styles.forEach((style) => {
Object.defineProperty(ctx, style, {
set: (value) => {
if ((style !== 'fillStyle' && style !== 'strokeStyle')
|| (value !== 'none' && value !== null)
) {
ctx[`set${style.charAt(0).toUpperCase()}${style.slice(1)}`](value);
}
},
});
});
ctx.createRadialGradient = () => ctx.createCircularGradient(arguments);
}
initEvent() {
this.event = {};
const eventNames = [{
wxName: 'touchStart',
ecName: 'mousedown',
}, {
wxName: 'touchMove',
ecName: 'mousemove',
}, {
wxName: 'touchEnd',
ecName: 'mouseup',
}, {
wxName: 'touchEnd',
ecName: 'click',
}];
eventNames.forEach((name) => {
this.event[name.wxName] = (e) => {
const touch = e.mp.touches[0];
this.chart._zr.handler.dispatch(name.ecName, {
zrX: name.wxName === 'tap' ? touch.clientX : touch.x,
zrY: name.wxName === 'tap' ? touch.clientY : touch.y,
});
};
});
}
}

View File

@ -0,0 +1,484 @@
<template>
<view class="mpvue-picker">
<view :class="{'pickerMask':showPicker}" @click="maskClick" catchtouchmove="true"></view>
<view class="mpvue-picker-content " :class="{'mpvue-picker-view-show':showPicker}">
<view class="mpvue-picker__hd" catchtouchmove="true">
<view class="mpvue-picker__action" @click="pickerCancel">取消</view>
<view class="mpvue-picker__action" :style="{color:themeColor}" @click="pickerConfirm">确定</view>
</view>
<!-- 单列 -->
<picker-view indicator-style="height: 40px;" class="mpvue-picker-view" :value="pickerValue"
@change="pickerChange" v-if="mode==='selector' && pickerValueSingleArray.length > 0">
<picker-view-column>
<view class="picker-item" v-for="(item,index) in pickerValueSingleArray" :key="index">{{item.label}}
</view>
</picker-view-column>
</picker-view>
<!-- 时间选择器 -->
<picker-view indicator-style="height: 40px;" class="mpvue-picker-view" :value="pickerValue"
@change="pickerChange" v-if="mode==='timeSelector'">
<picker-view-column>
<view class="picker-item" v-for="(item,index) in pickerValueHour" :key="index">{{item.label}}</view>
</picker-view-column>
<picker-view-column>
<view class="picker-item" v-for="(item,index) in pickerValueMinute" :key="index">{{item.label}}
</view>
</picker-view-column>
</picker-view>
<!-- 多列选择 -->
<picker-view indicator-style="height: 40px;" class="mpvue-picker-view" :value="pickerValue"
@change="pickerChange" v-if="mode==='multiSelector'">
<!-- #ifdef VUE3 -->
<template v-for="(n,index) in pickerValueMulArray.length" :key="index">
<picker-view-column>
<view class="picker-item" v-for="(item,index1) in pickerValueMulArray[n]" :key="index1">
{{item.label}}
</view>
</picker-view-column>
</template>
<!-- #endif -->
<!-- #ifndef VUE3 -->
<block v-for="(n,index) in pickerValueMulArray.length" :key="index">
<picker-view-column>
<view class="picker-item" v-for="(item,index1) in pickerValueMulArray[n]" :key="index1">
{{item.label}}
</view>
</picker-view-column>
</block>
<!-- #endif -->
</picker-view>
<!-- 二级联动 -->
<picker-view indicator-style="height: 40px;" class="mpvue-picker-view" :value="pickerValue"
@change="pickerChangeMul" v-if="mode==='multiLinkageSelector' && deepLength===2">
<picker-view-column>
<view class="picker-item" v-for="(item,index) in pickerValueMulTwoOne" :key="index">{{item.label}}
</view>
</picker-view-column>
<picker-view-column>
<view class="picker-item" v-for="(item,index) in pickerValueMulTwoTwo" :key="index">{{item.label}}
</view>
</picker-view-column>
</picker-view>
<!-- 三级联动 -->
<picker-view indicator-style="height: 40px;" class="mpvue-picker-view" :value="pickerValue"
@change="pickerChangeMul" v-if="mode==='multiLinkageSelector' && deepLength===3">
<picker-view-column>
<view class="picker-item" v-for="(item,index) in pickerValueMulThreeOne" :key="index">{{item.label}}
</view>
</picker-view-column>
<picker-view-column>
<view class="picker-item" v-for="(item,index) in pickerValueMulThreeTwo" :key="index">{{item.label}}
</view>
</picker-view-column>
<picker-view-column>
<view class="picker-item" v-for="(item,index) in pickerValueMulThreeThree" :key="index">
{{item.label}}
</view>
</picker-view-column>
</picker-view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
pickerChangeValue: [],
pickerValue: [],
pickerValueArrayChange: true,
modeChange: false,
pickerValueSingleArray: [],
pickerValueHour: [],
pickerValueMinute: [],
pickerValueMulArray: [],
pickerValueMulTwoOne: [],
pickerValueMulTwoTwo: [],
pickerValueMulThreeOne: [],
pickerValueMulThreeTwo: [],
pickerValueMulThreeThree: [],
/* 是否显示控件 */
showPicker: false,
};
},
props: {
/* mode */
mode: {
type: String,
default: 'selector'
},
/* picker 数值 */
pickerValueArray: {
type: Array,
default () {
return []
}
},
/* 默认值 */
pickerValueDefault: {
type: Array,
default () {
return []
}
},
/* 几级联动 */
deepLength: {
type: Number,
default: 2
},
/* 主题色 */
themeColor: String
},
watch: {
pickerValueArray(oldVal, newVal) {
this.pickerValueArrayChange = true;
},
mode(oldVal, newVal) {
this.modeChange = true;
},
pickerValueArray(val) {
this.initPicker(val);
}
},
methods: {
initPicker(valueArray) {
let pickerValueArray = valueArray;
this.pickerValue = this.pickerValueDefault;
//
if (this.mode === 'selector') {
this.pickerValueSingleArray = valueArray;
} else if (this.mode === 'timeSelector') {
this.modeChange = false;
let hourArray = [];
let minuteArray = [];
for (let i = 0; i < 24; i++) {
hourArray.push({
value: i,
label: i > 9 ? `${i}` : `0${i}`
});
}
for (let i = 0; i < 60; i++) {
minuteArray.push({
value: i,
label: i > 9 ? `${i}` : `0${i}`
});
}
this.pickerValueHour = hourArray;
this.pickerValueMinute = minuteArray;
} else if (this.mode === 'multiSelector') {
this.pickerValueMulArray = valueArray;
} else if (this.mode === 'multiLinkageSelector' && this.deepLength === 2) {
//
let pickerValueMulTwoOne = [];
let pickerValueMulTwoTwo = [];
//
for (let i = 0, length = pickerValueArray.length; i < length; i++) {
pickerValueMulTwoOne.push(pickerValueArray[i]);
}
//
//
if (this.pickerValueDefault.length === 2) {
let num = this.pickerValueDefault[0];
for (
let i = 0, length = pickerValueArray[num].children.length; i < length; i++
) {
pickerValueMulTwoTwo.push(pickerValueArray[num].children[i]);
}
} else {
for (
let i = 0, length = pickerValueArray[0].children.length; i < length; i++
) {
pickerValueMulTwoTwo.push(pickerValueArray[0].children[i]);
}
}
this.pickerValueMulTwoOne = pickerValueMulTwoOne;
this.pickerValueMulTwoTwo = pickerValueMulTwoTwo;
} else if (
this.mode === 'multiLinkageSelector' &&
this.deepLength === 3
) {
let pickerValueMulThreeOne = [];
let pickerValueMulThreeTwo = [];
let pickerValueMulThreeThree = [];
//
for (let i = 0, length = pickerValueArray.length; i < length; i++) {
pickerValueMulThreeOne.push(pickerValueArray[i]);
}
//
this.pickerValueDefault =
this.pickerValueDefault.length === 3 ?
this.pickerValueDefault : [0, 0, 0];
if (this.pickerValueDefault.length === 3) {
let num = this.pickerValueDefault[0];
for (
let i = 0, length = pickerValueArray[num].children.length; i < length; i++
) {
pickerValueMulThreeTwo.push(pickerValueArray[num].children[i]);
}
//
let numSecond = this.pickerValueDefault[1];
for (let i = 0, length = pickerValueArray[num].children[numSecond].children.length; i <
length; i++) {
pickerValueMulThreeThree.push(
pickerValueArray[num].children[numSecond].children[i]
);
}
}
this.pickerValueMulThreeOne = pickerValueMulThreeOne;
this.pickerValueMulThreeTwo = pickerValueMulThreeTwo;
this.pickerValueMulThreeThree = pickerValueMulThreeThree;
}
},
show() {
setTimeout(() => {
if (this.pickerValueArrayChange || this.modeChange) {
this.initPicker(this.pickerValueArray);
this.showPicker = true;
this.pickerValueArrayChange = false;
this.modeChange = false;
} else {
this.showPicker = true;
}
}, 0);
},
maskClick() {
this.pickerCancel();
},
pickerCancel() {
this.showPicker = false;
this._initPickerVale();
let pickObj = {
index: this.pickerValue,
value: this._getPickerLabelAndValue(this.pickerValue, this.mode).value,
label: this._getPickerLabelAndValue(this.pickerValue, this.mode).label
};
this.$emit('onCancel', pickObj);
},
pickerConfirm(e) {
this.showPicker = false;
this._initPickerVale();
let pickObj = {
index: this.pickerValue,
value: this._getPickerLabelAndValue(this.pickerValue, this.mode).value,
label: this._getPickerLabelAndValue(this.pickerValue, this.mode).label
};
this.$emit('onConfirm', pickObj);
},
showPickerView() {
this.showPicker = true;
},
pickerChange(e) {
console.log(11111111, e);
this.pickerValue = e.detail.value;
let pickObj = {
index: this.pickerValue,
value: this._getPickerLabelAndValue(this.pickerValue, this.mode).value,
label: this._getPickerLabelAndValue(this.pickerValue, this.mode).label
};
this.$emit('onChange', pickObj);
},
pickerChangeMul(e) {
if (this.deepLength === 2) {
let pickerValueArray = this.pickerValueArray;
let changeValue = e.detail.value;
//
if (changeValue[0] !== this.pickerValue[0]) {
let pickerValueMulTwoTwo = [];
//
for (let i = 0, length = pickerValueArray[changeValue[0]].children.length; i < length; i++) {
pickerValueMulTwoTwo.push(pickerValueArray[changeValue[0]].children[i]);
}
this.pickerValueMulTwoTwo = pickerValueMulTwoTwo;
// 0
changeValue[1] = 0;
}
this.pickerValue = changeValue;
} else if (this.deepLength === 3) {
let pickerValueArray = this.pickerValueArray;
let changeValue = e.detail.value;
let pickerValueMulThreeTwo = [];
let pickerValueMulThreeThree = [];
//
//
if (changeValue[0] !== this.pickerValue[0]) {
this.pickerValueMulThreeTwo = [];
for (let i = 0, length = pickerValueArray[changeValue[0]].children.length; i < length; i++) {
pickerValueMulThreeTwo.push(pickerValueArray[changeValue[0]].children[i]);
}
//
for (let i = 0, length = pickerValueArray[changeValue[0]].children[0].children.length; i <
length; i++) {
pickerValueMulThreeThree.push(pickerValueArray[changeValue[0]].children[0].children[i]);
}
changeValue[1] = 0;
changeValue[2] = 0;
this.pickerValueMulThreeTwo = pickerValueMulThreeTwo;
this.pickerValueMulThreeThree = pickerValueMulThreeThree;
} else if (changeValue[1] !== this.pickerValue[1]) {
//
//
this.pickerValueMulThreeThree = [];
pickerValueMulThreeTwo = this.pickerValueMulThreeTwo;
for (let i = 0, length = pickerValueArray[changeValue[0]].children[changeValue[1]].children
.length; i <
length; i++) {
pickerValueMulThreeThree.push(pickerValueArray[changeValue[0]].children[changeValue[1]]
.children[
i]);
}
changeValue[2] = 0;
this.pickerValueMulThreeThree = pickerValueMulThreeThree;
}
this.pickerValue = changeValue;
}
let pickObj = {
index: this.pickerValue,
value: this._getPickerLabelAndValue(this.pickerValue, this.mode).value,
label: this._getPickerLabelAndValue(this.pickerValue, this.mode).label
};
this.$emit('onChange', pickObj);
},
// pxikerLabel
_getPickerLabelAndValue(value, mode) {
let pickerLable;
let pickerGetValue = [];
// selector
if (mode === 'selector') {
pickerLable = this.pickerValueSingleArray[value].label;
pickerGetValue.push(this.pickerValueSingleArray[value].value);
} else if (mode === 'timeSelector') {
pickerLable = `${this.pickerValueHour[value[0]].label}-${this.pickerValueMinute[value[1]].label}`;
pickerGetValue.push(this.pickerValueHour[value[0]].value);
pickerGetValue.push(this.pickerValueHour[value[1]].value);
} else if (mode === 'multiSelector') {
for (let i = 0; i < value.length; i++) {
if (i > 0) {
pickerLable += this.pickerValueMulArray[i][value[i]].label + (i === value.length - 1 ? '' :
'-');
} else {
pickerLable = this.pickerValueMulArray[i][value[i]].label + '-';
}
pickerGetValue.push(this.pickerValueMulArray[i][value[i]].value);
}
} else if (mode === 'multiLinkageSelector') {
/* eslint-disable indent */
pickerLable =
this.deepLength === 2 ?
`${this.pickerValueMulTwoOne[value[0]].label}-${this.pickerValueMulTwoTwo[value[1]].label}` :
`${this.pickerValueMulThreeOne[value[0]].label}-${this.pickerValueMulThreeTwo[value[1]].label}-${this.pickerValueMulThreeThree[value[2]].label}`;
if (this.deepLength === 2) {
pickerGetValue.push(this.pickerValueMulTwoOne[value[0]].value);
pickerGetValue.push(this.pickerValueMulTwoTwo[value[1]].value);
} else {
pickerGetValue.push(this.pickerValueMulThreeOne[value[0]].value);
pickerGetValue.push(this.pickerValueMulThreeTwo[value[1]].value);
pickerGetValue.push(this.pickerValueMulThreeThree[value[2]].value);
}
/* eslint-enable indent */
}
return {
label: pickerLable,
value: pickerGetValue
};
},
// pickerValue
_initPickerVale() {
if (this.pickerValue.length === 0) {
if (this.mode === 'selector') {
this.pickerValue = [0];
} else if (this.mode === 'multiSelector') {
this.pickerValue = new Int8Array(this.pickerValueArray.length);
} else if (
this.mode === 'multiLinkageSelector' &&
this.deepLength === 2
) {
this.pickerValue = [0, 0];
} else if (
this.mode === 'multiLinkageSelector' &&
this.deepLength === 3
) {
this.pickerValue = [0, 0, 0];
}
}
}
}
};
</script>
<style>
.pickerMask {
position: fixed;
z-index: 1000;
top: 0;
right: 0;
left: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.6);
}
.mpvue-picker-content {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
transition: all 0.3s ease;
transform: translateY(100%);
z-index: 3000;
}
.mpvue-picker-view-show {
transform: translateY(0);
}
.mpvue-picker__hd {
display: flex;
padding: 9px 15px;
background-color: #fff;
position: relative;
text-align: center;
font-size: 17px;
}
.mpvue-picker__hd:after {
content: ' ';
position: absolute;
left: 0;
bottom: 0;
right: 0;
height: 1px;
border-bottom: 1px solid #e5e5e5;
color: #e5e5e5;
transform-origin: 0 100%;
transform: scaleY(0.5);
}
.mpvue-picker__action {
display: block;
flex: 1;
color: #1aad19;
}
.mpvue-picker__action:first-child {
text-align: left;
color: #888;
}
.mpvue-picker__action:last-child {
text-align: right;
}
.picker-item {
text-align: center;
line-height: 40px;
font-size: 16px;
}
.mpvue-picker-view {
position: relative;
bottom: 0;
left: 0;
width: 100%;
height: 238px;
background-color: rgba(255, 255, 255, 1);
}
</style>

View File

@ -0,0 +1,175 @@
class GestureLock {
constructor(containerWidth, cycleRadius) {
this.containerWidth = containerWidth; // 容器宽度
this.cycleRadius = cycleRadius; // 圆的半径
this.circleArray = []; // 全部圆的对象数组
this.checkPoints = []; // 选中的圆的对象数组
this.lineArray = []; // 已激活锁之间的线段数组
this.lastCheckPoint = 0; // 最后一个激活的锁
this.offsetX = 0; // 容器的 X 偏移
this.offsetY = 0; // 容器的 Y 偏移
this.activeLine = {}; // 最后一个激活的锁与当前位置之间的线段
this.windowWidth = wx.getSystemInfoSync().windowWidth; // 窗口大小(用于rpx 和 px 转换)
this.initCircleArray();
}
// 初始化 画布上的 9个圆
initCircleArray() {
const cycleMargin = (this.containerWidth - 6 * this.cycleRadius) / 6;
let count = 0;
for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
count++;
this.circleArray.push({
count: count,
x: this.rpxTopx((cycleMargin + this.cycleRadius) * (j * 2 + 1)),
y: this.rpxTopx((cycleMargin + this.cycleRadius) * (i * 2 + 1)),
radius: this.rpxTopx(this.cycleRadius),
check: false,
style: {
left: (cycleMargin + this.cycleRadius) * (j * 2 + 1) - this.cycleRadius + 'rpx',
top: (cycleMargin + this.cycleRadius) * (i * 2 + 1) - this.cycleRadius + 'rpx',
width: this.cycleRadius * 2 + 'rpx',
}
});
}
}
}
onTouchStart(e) {
this.setOffset(e);
this.checkTouch({
x: e.touches[0].pageX - this.offsetX,
y: e.touches[0].pageY - this.offsetY
});
}
onTouchMove(e) {
this.moveDraw(e)
}
onTouchEnd(e) {
const checkPoints = this.checkPoints;
this.reset();
return checkPoints;
}
// 初始化 偏移量
setOffset(e) {
this.offsetX = e.currentTarget.offsetLeft;
this.offsetY = e.currentTarget.offsetTop;
}
// 检测当时 触摸位置是否位于 锁上
checkTouch({
x,
y
}) {
for (let i = 0; i < this.circleArray.length; i++) {
let point = this.circleArray[i];
if (this.isPointInCycle(x, y, point.x, point.y, point.radius)) {
if (!point.check) {
this.checkPoints.push(point.count);
if (this.lastCheckPoint != 0) {
// 已激活锁之间的线段
const line = this.drawLine(this.lastCheckPoint, point);
this.lineArray.push(line);
}
this.lastCheckPoint = point;
}
point.check = true;
return;
}
}
}
// 画线 - 返回 样式 对象
drawLine(start, end) {
const width = this.getPointDis(start.x, start.y, end.x, end.y);
const rotate = this.getAngle(start, end);
return {
activeLeft: start.x + 'px',
activeTop: start.y + 'px',
activeWidth: width + 'px',
activeRotate: rotate + 'deg'
}
}
// 获取 画线的 角度
getAngle(start, end) {
var diff_x = end.x - start.x,
diff_y = end.y - start.y;
if (diff_x >= 0) {
return 360 * Math.atan(diff_y / diff_x) / (2 * Math.PI);
} else {
return 180 + 360 * Math.atan(diff_y / diff_x) / (2 * Math.PI);
}
}
// 判断 当前点是否位于 锁内
isPointInCycle(x, y, circleX, circleY, radius) {
return (this.getPointDis(x, y, circleX, circleY) < radius) ? true : false;
}
// 获取两点之间距离
getPointDis(ax, ay, bx, by) {
return Math.sqrt(Math.pow(ax - bx, 2) + Math.pow(ay - by, 2));
}
// 移动 绘制
moveDraw(e) {
// 画经过的圆
const x = e.touches[0].pageX - this.offsetX;
const y = e.touches[0].pageY - this.offsetY;
this.checkTouch({
x,
y
});
// 画 最后一个激活的锁与当前位置之间的线段
this.activeLine = this.drawLine(this.lastCheckPoint, {
x,
y
});
}
// 使 画布 恢复初始状态
reset() {
this.circleArray.forEach((item) => {
item.check = false;
});
this.checkPoints = [];
this.lineArray = [];
this.activeLine = {};
this.lastCheckPoint = 0;
}
// 获取 最后一个激活的锁与当前位置之间的线段
getActiveLine() {
return this.activeLine;
}
// 获取 圆对象数组
getCycleArray() {
return this.circleArray;
}
// 获取 已激活锁之间的线段
getLineArray() {
return this.lineArray;
}
// 将 RPX 转换成 PX
rpxTopx(rpx) {
return rpx / 750 * this.windowWidth;
}
}
export default GestureLock;

View File

@ -0,0 +1,138 @@
<template>
<view class="gesture-lock" :class="{error:error}" :style="{width: containerWidth +'rpx', height:containerWidth +'rpx'}"
@touchstart.stop="onTouchStart" @touchmove.stop="onTouchMove" @touchend.stop="onTouchEnd">
<!-- 同级 v-for key 重复会有问题需要套一层 -->
<!-- 9 个圆 -->
<view>
<view v-for="(item,i) in circleArray" :key="i" class="cycle" :class="{check:item.check}" :style="{left:item.style.left,top:item.style.top,width:item.style.width,height:item.style.width}">
</view>
</view>
<view>
<!-- 已激活锁之间的线段 -->
<view v-for="(item,i) in lineArray" :key="i" class="line" :style="{left:item.activeLeft,top:item.activeTop,width:item.activeWidth,'-webkit-transform':'rotate('+item.activeRotate+')',transform:'rotate('+item.activeRotate+')'}">
</view>
</view>
<!-- 最后一个激活的锁与当前位置之间的线段 -->
<view class="line" :style="{left:activeLine.activeLeft,top:activeLine.activeTop,width:activeLine.activeWidth,'-webkit-transform':'rotate('+activeLine.activeRotate+')',transform:'rotate('+activeLine.activeRotate+')'}">
</view>
</view>
</template>
<script>
import GestureLock from './gestureLock';
export default {
name: 'index',
props: {
/**
* 容器宽度
*/
containerWidth: {
type: [Number, String],
default: 0
},
/**
* 圆的半径
*/
cycleRadius: {
type: [Number, String],
default: 0
},
/**
* 已设定的密码
*/
password: {
type: Array,
default () {
return []
}
},
},
data() {
return {
gestureLock: {}, //
circleArray: [], //
lineArray: [], // 线
activeLine: {}, // 线
error: false
}
},
methods: {
onTouchStart(e) {
this.gestureLock.onTouchStart(e);
this.refesh();
},
onTouchMove(e) {
this.gestureLock.onTouchMove(e);
this.refesh();
},
onTouchEnd(e) {
const checkPoints = this.gestureLock.onTouchEnd(e);
if (!this.password.length || checkPoints.join('') == this.password.join('')) {
this.refesh();
this.$emit('end', checkPoints);
} else {
this.error = true;
setTimeout(() => {
this.refesh();
this.$emit('end', checkPoints);
}, 800);
}
},
refesh() {
this.error = false;
this.circleArray = this.gestureLock.getCycleArray();
this.lineArray = this.gestureLock.getLineArray();
this.activeLine = this.gestureLock.getActiveLine();
}
},
mounted() {
this.gestureLock = new GestureLock(this.containerWidth, this.cycleRadius);
this.refesh();
}
}
</script>
<style scoped>
.gesture-lock {
margin: 0 auto;
position: relative;
box-sizing: border-box;
overflow: auto;
}
.gesture-lock .cycle {
box-sizing: border-box;
position: absolute;
border: 2px solid #66aaff;
border-radius: 50%;
}
.gesture-lock .cycle.check:after {
content: "";
display: block;
position: absolute;
width: 32%;
height: 32%;
border: 2px solid #66aaff;
border-radius: 50%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.gesture-lock .line {
height: 0;
border-top: 2px solid #66aaff;
position: absolute;
transform-origin: left center;
}
.gesture-lock.error .cycle.check,
.gesture-lock.error .cycle.check:after,
.gesture-lock.error .line {
border-color: #ffa197;
}
</style>

View File

@ -0,0 +1,38 @@
<template name="page-foot">
<view class="page-share-title">
<text>感谢{{name}}提供本示例</text>
<text class="submit" @click="submit">我也提交</text>
</view>
</template>
<script>
export default {
name: "page-foot",
props: {
name: {
type: String,
default: ""
}
},
methods: {
submit() {
uni.showModal({
content:"hello uni-app开源地址为https://github.com/dcloudio/uni-app/tree/master/examples请在这个开源项目上贡献你的代码",
showCancel:false
})
}
}
}
</script>
<style>
.page-share-title {
text-align: center;
font-size: 30rpx;
color: #BEBEBE;
padding: 20rpx 0;
}
.submit {
border-bottom: 1rpx solid #BEBEBE;
}
</style>

View File

@ -0,0 +1,16 @@
<template name="page-head">
<view class="common-page-head">
<view class="common-page-head-title">{{title}}</view>
</view>
</template>
<script>
export default {
name: "page-head",
props: {
title: {
type: String,
default: ""
}
}
}
</script>

66
components/product.vue Normal file
View File

@ -0,0 +1,66 @@
<template>
<view class="product">
<image class="product-image" :src="image ? image : 'https://via.placeholder.com/150x200'"></image>
<view class="product-title">{{title}}</view>
<view class="product-price">
<text class="product-price-favour">{{originalPrice}}</text>
<text class="product-price-original">{{favourPrice}}</text>
<text class="product-tip">{{tip}}</text>
</view>
</view>
</template>
<script>
export default {
name: 'product',
props: ['image', 'title', 'originalPrice', 'favourPrice', 'tip']
}
</script>
<style>
.product {
padding: 10rpx 20rpx;
display: flex;
flex-direction: column;
}
.product-image {
height: 330rpx;
width: 330rpx;
}
.product-title {
width: 300rpx;
font-size: 32rpx;
word-break: break-all;
display: -webkit-box;
overflow: hidden;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
.product-price {
font-size: 28rpx;
position: relative;
}
.product-price-original {
color: #E80080;
}
.product-price-favour {
color: #888888;
text-decoration: line-through;
margin-left: 10rpx;
}
.product-tip {
position: absolute;
right: 10rpx;
background-color: #FF3333;
color: #FFFFFF;
padding: 0 10rpx;
border-radius: 5rpx;
}
</style>

View File

@ -0,0 +1,175 @@
<template>
<view class="view">
<view class="list-cell view" hover-class="uni-list-cell-hover" @click="bindClick">
<view class="media-list view" v-if="options.title">
<view class="view" :class="{'media-image-right': options.article_type === 2, 'media-image-left': options.article_type === 1}">
<text class="media-title" :class="{'media-title2': options.article_type === 1 || options.article_type === 2}">{{options.title}}</text>
<view v-if="options.image_list || options.image_url" class="image-section view" :class="{'image-section-right': options.article_type === 2, 'image-section-left': options.article_type === 1}">
<image class="image-list1" :class="{'image-list2': options.article_type === 1 || options.article_type === 2}"
v-if="options.image_url" :src="options.image_url"></image>
<image class="image-list3" v-if="options.image_list" :src="source.url" v-for="(source, i) in options.image_list"
:key="i" />
</view>
</view>
<view class="media-foot view">
<view class="media-info view">
<text class="info-text">{{options.source}}</text>
<text class="info-text">{{options.comment_count}}条评论</text>
<text class="info-text">{{options.datetime}}</text>
</view>
<view class="max-close-view view" @click.stop="close">
<view class="close-view view"><text class="close">×</text></view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
options: {
type: Object,
default: function(e) {
return {}
}
}
},
methods: {
close(e) {
this.$emit('close');
},
bindClick() {
this.$emit('click');
}
}
}
</script>
<style>
.view {
display: flex;
flex-direction: column;
box-sizing: border-box;
}
.list-cell {
width: 750rpx;
padding: 0 30rpx;
}
.uni-list-cell-hover {
background-color: #eeeeee;
}
.media-list {
flex: 1;
flex-direction: column;
border-bottom-width: 1rpx;
border-bottom-style: solid;
border-bottom-color: #c8c7cc;
padding: 20rpx 0;
}
.media-image-right {
flex-direction: row;
}
.media-image-left {
flex-direction: row-reverse;
}
.media-title {
flex: 1;
}
.media-title {
lines: 3;
text-overflow: ellipsis;
font-size: 32rpx;
color: #555555;
}
.media-title2 {
flex: 1;
margin-top: 6rpx;
line-height: 40rpx;
}
.image-section {
margin-top: 20rpx;
flex-direction: row;
justify-content: space-between;
}
.image-section-right {
margin-top: 0rpx;
margin-left: 10rpx;
width: 225rpx;
height: 146rpx;
}
.image-section-left {
margin-top: 0rpx;
margin-right: 10rpx;
width: 225rpx;
height: 146rpx;
}
.image-list1 {
width: 690rpx;
height: 481rpx;
}
.image-list2 {
width: 225rpx;
height: 146rpx;
}
.image-list3 {
width: 225rpx;
height: 146rpx;
}
.media-info {
flex-direction: row;
}
.info-text {
margin-right: 20rpx;
color: #999999;
font-size: 24rpx;
}
.media-foot {
margin-top: 20rpx;
flex-direction: row;
justify-content: space-between;
}
.max-close-view {
align-items: center;
justify-content: flex-end;
flex-direction: row;
height: 40rpx;
width: 80rpx;
}
.close-view {
border-style: solid;
border-width: 1px;
border-color: #999999;
border-radius: 10rpx;
justify-content: center;
height: 30rpx;
width: 40rpx;
line-height: 30rpx;
}
.close {
text-align: center;
color: #999999;
font-size: 28rpx;
}
</style>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,59 @@
<template>
<text style="text-decoration:underline" :href="href" @click="openURL" :inWhiteList="inWhiteList">{{text}}</text>
</template>
<script>
/**
* @description u-link是一个外部网页超链接组件在小程序内打开内部web-view组件或复制url在app内打开外部浏览器在h5端打开新网页
* @property {String} href 点击后打开的外部网页url小程序中必须以https://
* @property {String} text 显示的文字
* @property {Boolean} inWhiteList 是否在小程序白名单中如果在的话在小程序端会直接打开内置web-view否则会只会复制url提示在外部打开
* @example * <u-link href="https://ext.dcloud.net.cn" text="https://ext.dcloud.net.cn" :inWhiteList="true"></u-link>
*/
export default {
name: 'u-link',
props: {
href: {
type: String,
default: ''
},
text: {
type: String,
default: ''
},
inWhiteList: {
type: Boolean,
default: false
}
},
methods: {
openURL() {
// #ifdef APP-PLUS
plus.runtime.openURL(this.href) //使web-view
// #endif
// #ifdef H5
window.open(this.href)
// #endif
// #ifdef MP
if (this.inWhiteList) { //webview
uni.navigateTo({
url: '/pages/component/web-view/web-view?url=' + this.href
});
} else {
uni.setClipboardData({
data: this.href
});
uni.showModal({
content: '本网址无法直接在小程序内打开。已自动复制网址,请在手机浏览器里粘贴该网址',
showCancel: false
});
}
// #endif
}
}
}
</script>
<style>
</style>

88
hybrid/html/local.html Normal file
View File

@ -0,0 +1,88 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>本地网页</title>
<style type="text/css">
.btn {
display: block;
margin: 20px auto;
padding: 5px;
background-color: #007aff;
border: 0;
color: #ffffff;
height: 40px;
width: 200px;
}
.btn-red {
background-color: #dd524d;
}
.btn-yellow {
background-color: #f0ad4e;
}
.desc {
padding: 10px;
color: #999999;
}
</style>
</head>
<body>
<p class="desc">web-view 组件加载本地 html 示例,仅在 App 环境下生效。点击下列按钮,跳转至其它页面。</p>
<div class="btn-list">
<button class="btn" type="button" data-action="navigateTo">navigateTo</button>
<button class="btn" type="button" data-action="redirectTo">redirectTo</button>
<button class="btn" type="button" data-action="navigateBack">navigateBack</button>
<button class="btn" type="button" data-action="reLaunch">reLaunch</button>
<button class="btn" type="button" data-action="switchTab">switchTab</button>
</div>
<p class="desc">网页向应用发送消息。注意:小程序端应用会在此页面后退时接收到消息。</p>
<div class="btn-list">
<button class="btn btn-red" type="button" id="postMessage">postMessage</button>
</div>
<!-- uni 的 SDK -->
<script type="text/javascript" src="https://unpkg.com/@dcloudio/uni-webview-js@0.0.1/index.js"></script>
<script type="text/javascript">
document.addEventListener('UniAppJSBridgeReady', function() {
document.querySelector('.btn-list').addEventListener('click', function(evt) {
var target = evt.target;
if (target.tagName === 'BUTTON') {
var action = target.getAttribute('data-action');
switch (action) {
case 'switchTab':
uni.switchTab({
url: '/pages/tabBar/API/API'
});
break;
case 'reLaunch':
uni.reLaunch({
url: '/pages/tabBar/API/API'
});
break;
case 'navigateBack':
uni.navigateBack({
delta: 1
});
break;
default:
uni[action]({
url: '/pages/component/button/button'
});
break;
}
}
});
document.querySelector("#postMessage").addEventListener('click', function() {
uni.postMessage({
data: {
action: 'message'
}
});
})
});
</script>
</body>
</html>

20
index.html Normal file
View File

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<script>
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
CSS.supports('top: constant(a)'))
document.write(
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
</script>
<title></title>
<!--preload-links-->
<!--app-context-->
</head>
<body>
<div id="app"><!--app-html--></div>
<script type="module" src="/main.js"></script>
</body>
</html>

39
main.js Normal file
View File

@ -0,0 +1,39 @@
import App from './App'
import store from './store'
// #ifndef VUE3
import Vue from 'vue'
Vue.config.productionTip = false
Vue.prototype.$store = store
Vue.prototype.$adpid = "1111111111"
Vue.prototype.$backgroundAudioData = {
playing: false,
playTime: 0,
formatedPlayTime: '00:00:00'
}
App.mpType = 'app'
const app = new Vue({
store,
...App
})
app.$mount()
// #endif
// #ifdef VUE3
import {
createSSRApp
} from 'vue'
export function createApp() {
const app = createSSRApp(App)
app.use(store)
app.config.globalProperties.$adpid = "1111111111"
app.config.globalProperties.$backgroundAudioData = {
playing: false,
playTime: 0,
formatedPlayTime: '00:00:00'
}
return {
app
}
}
// #endif

192
manifest.json Normal file
View File

@ -0,0 +1,192 @@
{
"name" : "mini-test",
"appid" : "__UNI__7850BDB",
"description" : "uni-app 框架示例一套代码同时发行到iOS、Android、H5、小程序等多个平台请使用手机扫码快速体验 uni-app 的强大功能",
"versionName" : "1.0.0",
"versionCode" : "100",
"transformPx" : false,
"app-plus" : {
"usingComponents" : true,
"nvueCompiler" : "uni-app",
"nvueStyleCompiler" : "uni-app",
"compilerVersion" : 3,
"nvueLaunchMode" : "fast",
"splashscreen" : {
"alwaysShowBeforeRender" : true,
"waiting" : true,
"autoclose" : true,
"delay" : 0
},
"modules" : {
"OAuth" : {},
"Payment" : {},
"Push" : {},
"Share" : {},
"Speech" : {},
"VideoPlayer" : {}
},
"distribute" : {
"android" : {
"permissions" : [
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_MOCK_LOCATION\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.CALL_PHONE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.GET_TASKS\"/>",
"<uses-permission android:name=\"android.permission.INTERNET\"/>",
"<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.READ_CONTACTS\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.READ_SMS\"/>",
"<uses-permission android:name=\"android.permission.RECEIVE_BOOT_COMPLETED\"/>",
"<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",
"<uses-permission android:name=\"android.permission.SEND_SMS\"/>",
"<uses-permission android:name=\"android.permission.SYSTEM_ALERT_WINDOW\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.WRITE_CONTACTS\"/>",
"<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SMS\"/>",
"<uses-permission android:name=\"android.permission.RECEIVE_USER_PRESENT\"/>"
]
},
"ios" : {
"UIBackgroundModes" : [ "audio" ],
"urlschemewhitelist" : [ "baidumap", "iosamap" ]
},
"sdkConfigs" : {
"speech" : {
"ifly" : {}
}
},
"orientation" : [ "portrait-primary" ]
},
"uniStatistics" : {
"enable" : true
}
},
"quickapp" : {},
"quickapp-native" : {
"icon" : "/static/logo.png",
"package" : "com.example.demo",
"features" : [
{
"name" : "system.clipboard"
}
]
},
"quickapp-webview" : {
"icon" : "/static/logo.png",
"package" : "com.example.demo",
"minPlatformVersion" : 1070,
"versionName" : "1.0.0",
"versionCode" : 100
},
"mp-weixin" : {
"appid" : "wxdaa0c852bdfa9d24",
"setting" : {
"urlCheck" : false
},
"usingComponents" : true,
"permission" : {
"scope.userLocation" : {
"desc" : "演示定位能力"
}
},
"uniStatistics" : {
"enable" : true
}
},
"mp-alipay" : {
"usingComponents" : true,
"uniStatistics" : {
"enable" : true
}
},
"mp-baidu" : {
"usingComponents" : true,
"uniStatistics" : {
"enable" : true
},
"dynamicLib" : {
"editorLib" : {
"provider" : "swan-editor"
}
}
},
"mp-toutiao" : {
"usingComponents" : true,
"uniStatistics" : {
"enable" : true
}
},
"mp-jd" : {
"usingComponents" : true,
"uniStatistics" : {
"enable" : true
}
},
"h5" : {
"template" : "template.h5.html",
"router" : {
"mode" : "history",
"base" : ""
},
"sdkConfigs" : {
"maps" : {
"qqmap" : {
"key" : "TKUBZ-D24AF-GJ4JY-JDVM2-IBYKK-KEBCU"
}
}
},
"async" : {
"timeout" : 20000
},
"uniStatistics" : {
"enable" : true
}
},
"vueVersion" : "3",
"mp-kuaishou" : {
"uniStatistics" : {
"enable" : true
}
},
"mp-lark" : {
"uniStatistics" : {
"enable" : true
}
},
"mp-qq" : {
"uniStatistics" : {
"enable" : true
}
},
"quickapp-webview-huawei" : {
"uniStatistics" : {
"enable" : true
}
},
"quickapp-webview-union" : {
"uniStatistics" : {
"enable" : true
}
},
"uniStatistics" : {
"version" : "2",
"enable" : true
}
}

115
package.json Normal file
View File

@ -0,0 +1,115 @@
{
"id": "hello-uniapp",
"name": "hello-uniapp",
"displayName": "hello-uniapp 示例工程",
"version": "3.4.5",
"description": "uni-app 框架示例一套代码同时发行到iOS、Android、H5、小程序等多个平台请使用手机扫码快速体验 uni-app 的强大功能",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": "https://github.com/dcloudio/hello-uniapp.git",
"keywords": [
"hello-uniapp",
"uni-app",
"uni-ui",
"示例工程"
],
"author": "",
"license": "MIT",
"bugs": {
"url": "https://github.com/dcloudio/hello-uniapp/issues"
},
"homepage": "https://github.com/dcloudio/hello-uniapp#readme",
"dependencies": {},
"dcloudext": {
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": "",
"type": "uniapp-template-project"
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "y"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y",
"京东": "y",
"钉钉": "y",
"快手": "y",
"飞书": "y"
},
"快应用": {
"华为": "y",
"联盟": "y"
},
"Vue": {
"vue2": "y",
"vue3": "y"
}
}
}
},
"uni-app": {
"scripts": {
"mp-dingtalk": {
"title": "钉钉小程序",
"env": {
"UNI_PLATFORM": "mp-alipay"
},
"define": {
"MP-DINGTALK": true
}
},
"hello-uniapp-demo": {
"title": "hello-uniapp 演示网站",
"env": {
"UNI_PLATFORM": "h5"
},
"define": {
"H5-DEMO": true
}
}
}
}
}

1510
pages.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,60 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap">
<view class="uni-btn-v">
<button class="target" type="default" @tap="actionSheetTap">弹出action sheet</button>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'action-sheet',
buttonRect: {}
}
},
// #ifdef H5
onReady() {
this.getNodeInfo()
window.addEventListener('resize', this.getNodeInfo)
},
beforeDestroy() {
window.removeEventListener('resize', this.getNodeInfo)
},
// #endif
methods: {
actionSheetTap() {
const that = this
uni.showActionSheet({
title: '标题',
itemList: ['item1', 'item2', 'item3', 'item4'],
popover: {
// 104: navbar + topwindow fix createSelectorQuery pc top bug
top: that.buttonRect.top + 104 + that.buttonRect.height,
left: that.buttonRect.left + that.buttonRect.width / 2
},
success: (e) => {
console.log(e.tapIndex);
uni.showToast({
title: "点击了第" + e.tapIndex + "个选项",
icon: "none"
})
}
})
},
// #ifdef H5
getNodeInfo() {
uni.createSelectorQuery().select('.target').boundingClientRect().exec((ret) => {
const rect = ret[0]
if (rect) {
this.buttonRect = rect
}
});
}
// #endif
}
}
</script>

View File

@ -0,0 +1,102 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-common-mt">
<view class="uni-list">
<view class="uni-list-cell">
<view class="uni-list-cell-left">
<view class="uni-label">名称</view>
</view>
<view class="uni-list-cell-db">
<input class="uni-input" type="text" placeholder="请输入联系人名称" name="name" :value="name" @input="nameChange"/>
</view>
</view>
<view class="uni-list-cell">
<view class="uni-list-cell-left">
<view class="uni-label">手机号</view>
</view>
<view class="uni-list-cell-db">
<input class="uni-input" type="text" placeholder="请输入联系人手机号" name="phone" :value="phone" @input="phoneChange"/>
</view>
</view>
</view>
<view class="uni-padding-wrap">
<view class="uni-btn-v">
<button type="primary" class="btn-setstorage" @tap="add">添加联系人</button>
</view>
</view>
</view>
</view>
</template>
<script>
// #ifdef APP-PLUS
import permision from "@/common/permission.js"
// #endif
export default {
data() {
return {
title: 'addPhoneContact',
name: '',
phone: ''
}
},
methods: {
nameChange: function(e) {
this.name = e.detail.value
},
phoneChange: function(e) {
this.phone = e.detail.value
},
async add() {
// #ifdef APP-PLUS
let status = await this.checkPermission();
if (status !== 1) {
return;
}
// #endif
uni.addPhoneContact({
firstName: this.name,
mobilePhoneNumber: this.phone,
success: function() {
uni.showModal({
content: '已成功添加联系人!',
showCancel: false
})
},
fail: function() {
uni.showModal({
content: '添加联系人失败!',
showCancel: false
})
}
});
}
// #ifdef APP-PLUS
,
async checkPermission() {
let status = permision.isIOS ? await permision.requestIOS('contact') :
await permision.requestAndroid('android.permission.WRITE_CONTACTS');
if (status === null || status === 1) {
status = 1;
} else {
uni.showModal({
content: "需要联系人权限",
confirmText: "设置",
success: function(res) {
if (res.confirm) {
permision.gotoAppSetting();
}
}
})
}
return status;
}
// #endif
}
}
</script>
<style>
</style>

View File

@ -0,0 +1,125 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap uni-common-mt">
<view class="animation-element-wrapper">
<view class="animation-element" :animation="animationData"></view>
</view>
<scroll-view class="animation-buttons" scroll-y="true">
<button class="animation-button" @tap="rotate">旋转</button>
<button class="animation-button" @tap="scale">缩放</button>
<button class="animation-button" @tap="translate">移动</button>
<button class="animation-button" @tap="skew">倾斜</button>
<button class="animation-button" @tap="rotateAndScale">旋转并缩放</button>
<button class="animation-button" @tap="rotateThenScale">旋转后缩放</button>
<button class="animation-button" @tap="all">同时展示全部</button>
<button class="animation-button" @tap="allInQueue">顺序展示全部</button>
<button class="animation-button animation-button-reset" @tap="reset">还原</button>
</scroll-view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'createAnimation',
animationData: ''
}
},
onUnload(){
this.animationData = ''
},
onLoad() {
this.animation = uni.createAnimation()
},
methods: {
rotate: function () {
this.animation.rotate(Math.random() * 720 - 360).step()
this.animationData = this.animation.export()
},
scale: function () {
this.animation.scale(Math.random() * 2).step()
this.animationData = this.animation.export()
},
translate: function () {
this.animation.translate(Math.random() * 100 - 50, Math.random() * 100 - 50).step()
this.animationData = this.animation.export()
},
skew: function () {
this.animation.skew(Math.random() * 90, Math.random() * 90).step()
this.animationData = this.animation.export()
},
rotateAndScale: function () {
this.animation.rotate(Math.random() * 720 - 360)
.scale(Math.random() * 2)
.step()
this.animationData = this.animation.export()
},
rotateThenScale: function () {
this.animation.rotate(Math.random() * 720 - 360).step()
.scale(Math.random() * 2).step()
this.animationData = this.animation.export()
},
all: function () {
this.animation.rotate(Math.random() * 720 - 360)
.scale(Math.random() * 2)
.translate(Math.random() * 100 - 50, Math.random() * 100 - 50)
.skew(Math.random() * 90, Math.random() * 90)
.step()
this.animationData = this.animation.export()
},
allInQueue: function () {
this.animation.rotate(Math.random() * 720 - 360).step()
.scale(Math.random() * 2).step()
.translate(Math.random() * 100 - 50, Math.random() * 100 - 50).step()
.skew(Math.random() * 90, Math.random() * 90).step()
this.animationData = this.animation.export()
},
reset: function () {
this.animation.rotate(0, 0)
.scale(1)
.translate(0, 0)
.skew(0, 0)
.step({
duration: 0
})
this.animationData = this.animation.export()
}
}
}
</script>
<style>
.animation-element-wrapper {
display: flex;
width: 100%;
padding-top: 150rpx;
padding-bottom: 150rpx;
justify-content: center;
overflow: hidden;
background-color: #ffffff;
}
.animation-element {
width: 200rpx;
height: 200rpx;
background-color: #1AAD19;
}
.animation-buttons {
padding:30rpx 0;
width: 100%;
/* height: 360rpx; */
}
.animation-button {
float: left;
width: 44%;
margin: 15rpx 3%;
}
.animation-button-reset {
width: 94%;
}
</style>

View File

@ -0,0 +1,163 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap">
<view class="uni-center">
<text class="time-big">{{formatedPlayTime}}</text>
</view>
<view class="uni-common-mt">
<slider class="slider" min="0" max="21" step="1" :value="playTime" @change="seek"></slider>
</view>
<view class="play-time">
<text>00:00</text>
<text>00:21</text>
</view>
<view class="uni-hello-text">注意离开当前页面后背景音乐将保持播放但退出uni-app将停止</view>
<view class="page-body-buttons">
<block v-if="playing">
<view class="page-body-button" @tap="stop">
<image src="/static/stop.png"></image>
</view>
<view class="page-body-button" @tap="pause">
<image src="/static/pause.png"></image>
</view>
</block>
<block v-if="!playing">
<view class="page-body-button"></view>
<view class="page-body-button" @tap="play">
<image src="/static/play.png"></image>
</view>
</block>
<view class="page-body-button"></view>
</view>
</view>
</view>
</template>
<script>
import * as util from '../../../common/util.js';
export default {
data() {
return {
title: 'backgroundAudio',
bgAudioMannager: null,
dataUrl: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-hello-uniapp/2cc220e0-c27a-11ea-9dfb-6da8e309e0d8.mp3',
playing: false,
playTime: 0,
formatedPlayTime: '00:00:00'
}
},
onLoad: function () {
this.playing = this.$backgroundAudioData.playing;
this.playTime = this.$backgroundAudioData.playTime;
this.formatedPlayTime = this.$backgroundAudioData.formatedPlayTime;
let bgAudioMannager = uni.getBackgroundAudioManager();
if(!bgAudioMannager.title){
bgAudioMannager.title = '致爱丽丝';
}
if(!bgAudioMannager.singer) {
bgAudioMannager.singer = '暂无';
}
if(!bgAudioMannager.coverImgUrl){
bgAudioMannager.coverImgUrl = 'https://web-assets.dcloud.net.cn/unidoc/zh/Alice.jpeg';
}
bgAudioMannager.onPlay(() => {
console.log("开始播放");
this.$backgroundAudioData.playing = this.playing = true;
})
bgAudioMannager.onPause(() => {
console.log("暂停播放");
this.$backgroundAudioData.playing = this.playing = false;
})
bgAudioMannager.onEnded(() => {
this.playing = false;
this.$backgroundAudioData.playing = false;
this.$backgroundAudioData.playTime = this.playTime = 0;
this.$backgroundAudioData.formatedPlayTime = this.formatedPlayTime = util.formatTime(0);
})
bgAudioMannager.onTimeUpdate((e) => {
if (Math.floor(bgAudioMannager.currentTime) > Math.floor(this.playTime)) {
this.$backgroundAudioData.formatedPlayTime = this.formatedPlayTime = util.formatTime(Math.floor(bgAudioMannager.currentTime));
}
this.$backgroundAudioData.playTime = this.playTime = bgAudioMannager.currentTime;
})
this.bgAudioMannager = bgAudioMannager;
},
methods: {
play: function (res) {
if (!this.bgAudioMannager.src) {
this.bgAudioMannager.startTime = this.playTime;
this.bgAudioMannager.src = this.dataUrl;
} else {
this.bgAudioMannager.seek(this.playTime);
this.bgAudioMannager.play();
}
},
seek: function (e) {
this.bgAudioMannager.seek(e.detail.value);
},
pause: function () {
this.bgAudioMannager.pause();
},
stop: function () {
this.bgAudioMannager.stop();
this.$backgroundAudioData.playing = this.playing = false;
this.$backgroundAudioData.playTime = this.playTime = 0;
this.$backgroundAudioData.formatedPlayTime = this.formatedPlayTime = util.formatTime(0);
}
}
}
</script>
<style>
image {
width: 150rpx;
height: 150rpx;
}
.page-body-text {
padding: 0 30rpx;
}
.page-body-wrapper {
margin-top: 0;
}
.page-body-info {
padding-bottom: 50rpx;
}
.time-big {
font-size: 60rpx;
margin: 20rpx;
}
.slider {
width:630rpx;
}
.play-time {
font-size: 28rpx;
width:100%;
padding: 20rpx 0;
display: flex;
justify-content: space-between;
box-sizing: border-box;
}
.page-body-buttons {
display: flex;
justify-content: space-around;
margin-top: 100rpx;
}
.page-body-button {
width: 250rpx;
text-align: center;
}
</style>

View File

@ -0,0 +1,723 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap uni-common-mt">
<view>
本蓝牙协议只支持低功耗蓝牙协议ble如果想连接非ble蓝牙设备请在社区搜索 Native.js 蓝牙
</view>
<view class="uni-btn-v">
<button type="primary" :disabled="disabled[0]" @click="openBluetoothAdapter">
初始化蓝牙模块
</button>
<view v-if="!adapterState.available">
{{ '蓝牙适配器不可用,请初始化蓝牙模块' }}
</view>
<button
type="primary"
:loading="searchLoad"
:disabled="disabled[1]"
@click="startBluetoothDevicesDiscovery"
>
开始搜索蓝牙设备
</button>
<button
type="primary"
:disabled="disabled[2]"
@click="stopBluetoothDevicesDiscovery(false)"
>
停止搜索蓝牙设备
</button>
<button
type="primary"
:loading="newDeviceLoad"
:disabled="disabled[3]"
@click="queryDevices"
>
选择设备
</button>
<view v-if="equipment.length > 0">
{{
(connected ? '已连接设备' : '已选择设备') +
' : ' +
equipment[0].name +
' (' +
equipment[0].deviceId +
')'
}}
</view>
<button type="primary" :disabled="disabled[4]" @click="createBLEConnection">
连接蓝牙设备
</button>
<button type="primary" :disabled="disabled[5]" @click="getBLEDeviceServices">
选择设备服务
</button>
<view v-if="servicesData.length > 0">已选服务uuid{{ servicesData[0].uuid }}</view>
<button type="primary" :disabled="disabled[6]" @click="getBLEDeviceCharacteristics">
获取服务的特征值
</button>
<view v-if="characteristicsData.length > 0">
<view class="uni-list_name">uuid:{{ characteristicsData[0].uuid }}</view>
<view class="uni-list_item">
是否支持 read 操作:{{ characteristicsData[0].properties.read }}
</view>
<view class="uni-list_item">
是否支持 write 操作:{{ characteristicsData[0].properties.write }}
</view>
<view class="uni-list_item">
是否支持 notify 操作:{{ characteristicsData[0].properties.notify }}
</view>
<view class="uni-list_item">
是否支持 indicate 操作:{{ characteristicsData[0].properties.indicate }}
</view>
</view>
<!-- <button type="primary" :disabled="disabled[7]" @click="readBLECharacteristicValue">
读取特征值数据
</button>
<view v-if="valueChangeData.serviceId">
<view class="list-name">
特征值最新的值:{{ valueChangeData.value || '还没有最新值' }}
</view>
</view> -->
<!-- <button type="primary" :disabled="disabled[8]" @click="w">写入特征值数据</button> -->
<button type="primary" :disabled="disabled[9]" @click="closeBLEConnection">
断开蓝牙设备
</button>
<button type="primary" :disabled="disabled[10]" @click="closeBluetoothAdapter">
关闭蓝牙模块
</button>
</view>
</view>
<!-- 遮罩 -->
<view v-if="maskShow" class="uni-mask" @touchmove.stop.prevent="moveHandle" @click="maskclose">
<scroll-view class="uni-scroll_box" scroll-y @touchmove.stop.prevent="moveHandle" @click.stop="moveHandle">
<view class="uni-title">
已经发现{{ list.length }}{{ showMaskType === 'device' ? '台设备' : '个服务' }}:
</view>
<view
class="uni-list-box"
v-for="(item, index) in list"
:key="index"
@click="tapQuery(item)"
>
<view v-if="showMaskType === 'device'">
<view class="uni-list_name">{{ item.name || item.localName }}</view>
<view class="uni-list_item">信号强度:{{ item.RSSI }}dBm</view>
<view class="uni-list_item">UUID:{{ item.deviceId }}</view>
<!-- <view class="list-item" v-if="showMaskType === 'device'">
Service数量:{{ item.advertisServiceUUIDs.length }}
</view> -->
</view>
<view v-if="showMaskType === 'service'">
<view class="uni-list_item" style="line-height:2.2;">
UUID: {{ item.uuid }}
<text v-if="showMaskType === 'service'">
{{ item.isPrimary ? '(主服务)' : '' }}
</text>
</view>
</view>
<view v-if="showMaskType === 'characteristics'">
<view class="uni-list_name">uuid:{{ item.uuid }}</view>
<view class="uni-list_item">是否支持 read 操作:{{ item.properties.read }}</view>
<view class="uni-list_item">
是否支持 write 操作:{{ item.properties.write }}
</view>
<view class="uni-list_item">
是否支持 notify 操作:{{ item.properties.notify }}
</view>
<view class="uni-list_item">
是否支持 indicate 操作:{{ item.properties.indicate }}
</view>
</view>
</view>
</scroll-view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'bluetooth',
disabled: [false, true, true, true, true, true, true, true, true, true, true],
newDeviceLoad: false,
searchLoad: false,
maskShow: false,
equipment: [],
adapterState: {
discovering: false,
available: false
},
connected: false,
showMaskType: 'device',
servicesData: [],
characteristicsData: [],
valueChangeData: {},
isStop:true ,
list: []
};
},
onLoad() {
this.onBLEConnectionStateChange();
},
methods: {
moveHandle() {},
/**
* 关闭遮罩
*/
maskclose(){
this.maskShow = false;
},
/**
* 选择设备
*/
queryDevices() {
// this.newDeviceLoad = true;
this.showMaskType = 'device';
this.maskShow = true;
},
tapQuery(item) {
if (this.showMaskType === 'device') {
this.$set(this.disabled, 4, false);
if (this.equipment.length > 0) {
this.equipment[0] = item;
} else {
this.equipment.push(item);
}
this.newDeviceLoad = false;
}
if (this.showMaskType === 'service') {
this.$set(this.disabled, 6, false);
if (this.servicesData.length > 0) {
this.servicesData[0] = item;
} else {
this.servicesData.push(item);
}
}
if (this.showMaskType === 'characteristics') {
this.$set(this.disabled, 7, false);
if (this.characteristicsData.length > 0) {
this.characteristicsData[0] = item;
} else {
this.characteristicsData.push(item);
}
}
this.maskShow = false;
},
/**
* 初始化蓝牙设备
*/
openBluetoothAdapter() {
uni.openBluetoothAdapter({
success: e => {
console.log('初始化蓝牙成功:' + e.errMsg);
console.log(JSON.stringify(e));
this.isStop = false ;
this.$set(this.disabled, 0, true);
this.$set(this.disabled, 1, false);
this.$set(this.disabled, 10, false);
this.getBluetoothAdapterState();
},
fail: e => {
console.log(e)
console.log('初始化蓝牙失败,错误码:' + (e.errCode || e.errMsg));
if (e.errCode !== 0) {
initTypes(e.errCode,e.errMsg);
}
}
});
},
/**
* 开始搜索蓝牙设备
*/
startBluetoothDevicesDiscovery() {
uni.startBluetoothDevicesDiscovery({
success: e => {
console.log('开始搜索蓝牙设备:' + e.errMsg);
this.searchLoad = true;
this.$set(this.disabled, 1, true);
this.$set(this.disabled, 2, false);
this.$set(this.disabled, 3, false);
this.onBluetoothDeviceFound();
},
fail: e => {
console.log('搜索蓝牙设备失败,错误码:' + e.errCode);
if (e.errCode !== 0) {
initTypes(e.errCode);
}
}
});
},
/**
* 停止搜索蓝牙设备
*/
stopBluetoothDevicesDiscovery(types) {
uni.stopBluetoothDevicesDiscovery({
success: e => {
console.log('停止搜索蓝牙设备:' + e.errMsg);
if (types) {
this.$set(this.disabled, 1, true);
} else {
this.$set(this.disabled, 1, false);
}
this.$set(this.disabled, 2, true);
// this.$set(this.disabled, 3, true);
this.searchLoad = false;
},
fail: e => {
console.log('停止搜索蓝牙设备失败,错误码:' + e.errCode);
if (e.errCode !== 0) {
initTypes(e.errCode);
}
}
});
},
/**
* 发现外围设备
*/
onBluetoothDeviceFound() {
uni.onBluetoothDeviceFound(devices => {
console.log('开始监听寻找到新设备的事件');
// this.$set(this.disabled, 3, false);
this.getBluetoothDevices();
});
},
/**
* 获取在蓝牙模块生效期间所有已发现的蓝牙设备包括已经和本机处于连接状态的设备
*/
getBluetoothDevices() {
uni.getBluetoothDevices({
success: res => {
this.newDeviceLoad = false;
console.log('获取蓝牙设备成功:' + res.errMsg);
// console.log(JSON.stringify(res))
this.list = res.devices;
},
fail: e => {
console.log('获取蓝牙设备错误,错误码:' + e.errCode);
if (e.errCode !== 0) {
initTypes(e.errCode);
}
}
});
},
/**
* 获取本机蓝牙适配器状态
*/
getBluetoothAdapterState() {
console.log('--->');
uni.getBluetoothAdapterState({
success: res => {
console.log(JSON.stringify(res));
this.adapterState = res;
},
fail: e => {
console.log('获取本机蓝牙适配器状态失败,错误码:' + e.errCode);
if (e.errCode !== 0) {
initTypes(e.errCode);
}
}
});
},
/**
* 连接低功耗蓝牙
*/
createBLEConnection() {
let deviceId = this.equipment[0].deviceId;
uni.showToast({
title: '连接蓝牙...',
icon: 'loading',
duration: 99999
});
uni.createBLEConnection({
// deviceId createBLEConnection
deviceId,
success: res => {
console.log(res);
console.log('连接蓝牙成功:' + res.errMsg);
//
this.stopBluetoothDevicesDiscovery(true);
uni.hideToast();
uni.showToast({
title: '连接成功',
icon: 'success',
duration: 2000
});
this.$set(this.disabled, 3, true);
this.$set(this.disabled, 4, true);
this.$set(this.disabled, 5, false);
this.$set(this.disabled, 9, false);
this.connected = true;
},
fail: e => {
console.log('连接低功耗蓝牙失败,错误码:' + e.errCode);
if (e.errCode !== 0) {
initTypes(e.errCode);
}
}
});
},
/**
* 断开与低功耗蓝牙设备的连接
*/
closeBLEConnection() {
let deviceId = this.equipment[0].deviceId;
uni.closeBLEConnection({
deviceId,
success: res => {
console.log(res);
console.log('断开低功耗蓝牙成功:' + res.errMsg);
this.$set(this.disabled, 1, false);
this.$set(this.disabled, 3, true);
this.$set(this.disabled, 4, true);
this.$set(this.disabled, 5, true);
this.$set(this.disabled, 6, true);
this.$set(this.disabled, 7, true);
this.$set(this.disabled, 8, true);
this.$set(this.disabled, 9, true);
this.equipment = [];
this.servicesData = [];
this.characteristicsData = [];
},
fail: e => {
console.log('断开低功耗蓝牙成功,错误码:' + e.errCode);
if (e.errCode !== 0) {
initTypes(e.errCode);
}
}
});
},
/**
* 获取所有服务
*/
getBLEDeviceServices() {
let deviceId = this.equipment[0].deviceId;
console.log('获取所有服务的 uuid:' + deviceId);
uni.getBLEDeviceServices({
// deviceId createBLEConnection
deviceId,
success: res => {
console.log(JSON.stringify(res.services));
console.log('获取设备服务成功:' + res.errMsg);
this.$set(this.disabled, 7, true);
this.$set(this.disabled, 8, true);
this.showMaskType = 'service';
this.list = res.services;
this.characteristicsData = [];
if (this.list.length <= 0) {
toast('获取服务失败,请重试!');
return;
}
this.maskShow = true;
},
fail: e => {
console.log('获取设备服务失败,错误码:' + e.errCode);
if (e.errCode !== 0) {
initTypes(e.errCode);
}
}
});
},
/**
* 获取某个服务下的所有特征值
*/
getBLEDeviceCharacteristics() {
let deviceId = this.equipment[0].deviceId;
let serviceId = this.servicesData[0].uuid;
console.log(deviceId);
console.log(serviceId);
uni.getBLEDeviceCharacteristics({
// deviceId createBLEConnection
deviceId,
// serviceId getBLEDeviceServices
serviceId,
success: res => {
console.log(JSON.stringify(res));
console.log('获取特征值成功:' + res.errMsg);
this.$set(this.disabled, 7, true);
this.valueChangeData = {};
this.showMaskType = 'characteristics';
this.list = res.characteristics;
if (this.list.length <= 0) {
toast('获取特征值失败,请重试!');
return;
}
this.maskShow = true;
},
fail: e => {
console.log('获取特征值失败,错误码:' + e.errCode);
if (e.errCode !== 0) {
initTypes(e.errCode);
}
}
});
},
/**
* 监听低功耗蓝牙连接状态的改变事件包括开发者主动连接或断开连接设备丢失连接异常断开等等
*/
onBLEConnectionStateChange() {
uni.onBLEConnectionStateChange(res => {
//
console.log(`蓝牙连接状态 -------------------------->`);
console.log(JSON.stringify(res));
if (!res.connected) {
if(this.isStop) return ;
console.log('断开低功耗蓝牙成功:');
this.$set(this.disabled, 1, false);
this.$set(this.disabled, 3, true);
this.$set(this.disabled, 4, true);
this.$set(this.disabled, 5, true);
this.$set(this.disabled, 6, true);
this.$set(this.disabled, 7, true);
this.$set(this.disabled, 8, true);
this.$set(this.disabled, 9, true);
this.searchLoad = false;
this.equipment = [];
this.servicesData = [];
this.characteristicsData = [];
this.valueChangeData = {};
toast('已经断开当前蓝牙连接');
}
});
},
/**
* 读取低功耗蓝牙设备的特征值的二进制数据值注意必须设备的特征值支持 read 才可以成功调用
*/
readBLECharacteristicValue() {
let deviceId = this.equipment[0].deviceId;
let serviceId = this.servicesData[0].uuid;
let characteristicId = this.characteristicsData[0].uuid;
console.log(deviceId);
console.log(serviceId);
console.log(characteristicId);
uni.readBLECharacteristicValue({
// deviceId createBLEConnection
deviceId,
// serviceId getBLEDeviceServices
serviceId,
// characteristicId getBLEDeviceCharacteristics
characteristicId,
success: res => {
console.log('读取设备数据值成功');
console.log(JSON.stringify(res));
this.notifyBLECharacteristicValueChange();
},
fail(e) {
console.log('读取设备数据值失败,错误码:' + e.errCode);
if (e.errCode !== 0) {
initTypes(e.errCode);
}
}
});
this.onBLECharacteristicValueChange();
},
/**
* 监听低功耗蓝牙设备的特征值变化事件必须先启用 notifyBLECharacteristicValueChange 接口才能接收到设备推送的 notification
*/
onBLECharacteristicValueChange() {
//
uni.onBLECharacteristicValueChange(characteristic => {
console.log('监听低功耗蓝牙设备的特征值变化事件成功');
console.log(JSON.stringify(characteristic));
this.valueChangeData = characteristic;
});
},
/**
* 订阅操作成功后需要设备主动更新特征值的 value才会触发 uni.onBLECharacteristicValueChange 回调
*/
notifyBLECharacteristicValueChange() {
let deviceId = this.equipment[0].deviceId;
let serviceId = this.servicesData[0].uuid;
let characteristicId = this.characteristicsData[0].uuid;
let notify = this.characteristicsData[0].properties.notify;
console.log(deviceId);
console.log(serviceId);
console.log(characteristicId);
console.log(notify);
uni.notifyBLECharacteristicValueChange({
state: true, // notify
// deviceId createBLEConnection
deviceId,
// serviceId getBLEDeviceServices
serviceId,
// characteristicId getBLEDeviceCharacteristics
characteristicId,
success(res) {
console.log('notifyBLECharacteristicValueChange success:' + res.errMsg);
console.log(JSON.stringify(res));
}
});
},
/**
* 断开蓝牙模块
*/
closeBluetoothAdapter(OBJECT) {
uni.closeBluetoothAdapter({
success: res => {
console.log('断开蓝牙模块成功');
this.isStop = true ;
this.$set(this.disabled, 0, false);
this.$set(this.disabled, 1, true);
this.$set(this.disabled, 2, true);
this.$set(this.disabled, 3, true);
this.$set(this.disabled, 4, true);
this.$set(this.disabled, 5, true);
this.$set(this.disabled, 6, true);
this.$set(this.disabled, 7, true);
this.$set(this.disabled, 8, true);
this.$set(this.disabled, 9, true);
this.$set(this.disabled, 10, true);
this.equipment = [];
this.servicesData = [];
this.characteristicsData = [];
this.valueChangeData = {};
this.adapterState = [];
this.searchLoad =false;
toast('断开蓝牙模块');
}
});
}
}
};
/**
* 判断初始化蓝牙状态
*/
function initTypes(code, errMsg) {
switch (code) {
case 10000:
toast('未初始化蓝牙适配器');
break;
case 10001:
toast('未检测到蓝牙,请打开蓝牙重试!');
break;
case 10002:
toast('没有找到指定设备');
break;
case 10003:
toast('连接失败');
break;
case 10004:
toast('没有找到指定服务');
break;
case 10005:
toast('没有找到指定特征值');
break;
case 10006:
toast('当前连接已断开');
break;
case 10007:
toast('当前特征值不支持此操作');
break;
case 10008:
toast('其余所有系统上报的异常');
break;
case 10009:
toast('Android 系统特有,系统版本低于 4.3 不支持 BLE');
break;
default:
toast(errMsg);
}
}
/**
* 弹出框封装
*/
function toast(content, showCancel = false) {
uni.showModal({
title: '提示',
content,
showCancel
});
}
</script>
<style>
.uni-title {
/* width: 100%; */
/* height: 80rpx; */
text-align: center;
}
.uni-mask {
position: fixed;
top: 0;
left: 0;
bottom: 0;
display: flex;
align-items: center;
width: 100%;
background: rgba(0, 0, 0, 0.6);
padding: 0 30rpx;
box-sizing: border-box;
}
.uni-scroll_box {
height: 70%;
background: #fff;
border-radius: 20rpx;
}
.uni-list-box {
margin: 0 20rpx;
padding: 15rpx 0;
border-bottom: 1px #f5f5f5 solid;
box-sizing: border-box;
}
.uni-list:last-child {
border: none;
}
.uni-list_name {
font-size: 30rpx;
color: #333;
}
.uni-list_item {
font-size: 24rpx;
color: #555;
line-height: 1.5;
}
.uni-success_box {
position: absolute;
left: 0;
bottom: 0;
min-height: 100rpx;
width: 100%;
background: #fff;
box-sizing: border-box;
border-top: 1px #eee solid;
}
.uni-success_sub {
/* width: 100%%; */
height: 100rpx;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 30rpx;
}
.uni-close_button {
padding: 0 20rpx;
height: 60rpx;
line-height: 60rpx;
background: #ce3c39;
color: #ffffff;
border-radius: 10rpx;
}
.uni-success_content {
height: 600rpx;
margin: 30rpx;
margin-top: 0;
border: 1px #eee solid;
padding: 30rpx;
}
.uni-content_list {
padding-bottom: 10rpx;
border-bottom: 1px #f5f5f5 solid;
}
.uni-tips {
text-align: center;
font-size: 24rpx;
color: #666;
}
</style>

View File

@ -0,0 +1,86 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap uni-common-mt">
<!-- #ifndef MP-TOUTIAO -->
<view class="text-box">亮度 : {{ screen }}</view>
<view class="uni-slider"><slider :value="screen" @changing="sliderChange" step="1" /></view>
<!-- #endif -->
<button type="primary" @click="keep">
{{ keepScreenOn ? '保持常亮状态' : '关闭常亮状态' }}
</button>
<view class="tips">
保持常亮时屏幕不会熄灭仅在当前应用生效离开应用后设置失效
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'brightness',
screen: 0,
keepScreenOn: true
};
},
onLoad() {
uni.getScreenBrightness({
success: res => {
this.screen = (res.value * 100).toFixed();
},
fail(e) {
console.log(e);
}
});
},
methods: {
sliderChange(e) {
let screen = e.detail.value;
//
if (this.screen !== screen) {
console.log('当前数值:' + e.detail.value);
uni.setScreenBrightness({
value: screen / 100,
success: function() {
},
fail(e) {
console.log(e);
}
});
this.screen = screen;
}
},
keep() {
uni.setKeepScreenOn({
keepScreenOn: this.keepScreenOn
});
this.keepScreenOn = !this.keepScreenOn;
}
}
};
</script>
<style>
.text-box {
margin-bottom: 40rpx;
display: flex;
justify-content: center;
align-items: center;
height: 300rpx;
background-color: #ffffff;
font-size: 32rpx;
color: #353535;
}
.uni-slider {
margin: 100rpx 0;
}
.tips {
font-size: 26rpx;
text-align: center;
margin-top: 20rpx;
color: #999;
}
</style>

366
pages/API/canvas/canvas.vue Normal file
View File

@ -0,0 +1,366 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-common-mt">
<canvas class="canvas-element" canvas-id="canvas" id="canvas"></canvas>
<scroll-view class="canvas-buttons" scroll-y="true">
<block v-for="(name, index) in names" :key="index">
<button class="canvas-button" @click="handleCanvasButton(name)">{{name}}</button>
</block>
<button class="canvas-button" @click="toTempFilePath" type="primary">toTempFilePath</button>
</scroll-view>
</view>
</view>
</template>
<script>
var context = null;
export default {
data() {
return {
title: 'createContext',
names: ["rotate", "scale", "reset", "translate", "save", "restore", "drawImage", "fillText", "fill",
"stroke", "clearRect", "beginPath", "closePath", "moveTo", "lineTo", "rect", "arc",
"quadraticCurveTo", "bezierCurveTo", "setFillStyle", "setStrokeStyle", "setGlobalAlpha",
"setShadow", "setFontSize", "setLineCap", "setLineJoin", "setLineWidth", "setMiterLimit"
]
}
},
onReady: function() {
context = uni.createCanvasContext('canvas',this)
},
methods: {
toTempFilePath: function() {
uni.canvasToTempFilePath({
canvasId: 'canvas',
success: function(res) {
console.log(res.tempFilePath)
},
fail: function(err) {
console.error(JSON.stringify(err))
}
})
},
handleCanvasButton: function(name) {
this[name] && this[name]();
},
rotate: function() {
context.beginPath()
context.rotate(10 * Math.PI / 180)
context.rect(225, 75, 20, 10)
context.fill()
context.draw()
},
scale: function() {
context.beginPath()
context.rect(25, 25, 50, 50)
context.stroke()
context.scale(2, 2)
context.beginPath()
context.rect(25, 25, 50, 50)
context.stroke()
context.draw()
},
reset: function() {
context.beginPath()
context.setFillStyle('#000000')
context.setStrokeStyle('#000000')
context.setFontSize(10)
context.setGlobalAlpha(1)
context.setShadow(0, 0, 0, 'rgba(0, 0, 0, 0)')
context.setLineCap('butt')
context.setLineJoin('miter')
context.setLineWidth(1)
context.setMiterLimit(10)
context.draw()
},
translate: function() {
context.beginPath()
context.rect(10, 10, 100, 50)
context.fill()
context.translate(70, 70)
context.beginPath()
context.fill()
context.draw()
},
save: function() {
context.beginPath()
context.setStrokeStyle('#00ff00')
context.save()
context.scale(2, 2)
context.setStrokeStyle('#ff0000')
context.rect(0, 0, 100, 100)
context.stroke()
context.restore()
context.rect(0, 0, 50, 50)
context.stroke()
context.draw()
},
restore: function() {
[3, 2, 1].forEach(function(item) {
context.beginPath()
context.save()
context.scale(item, item)
context.rect(10, 10, 100, 100)
context.stroke()
context.restore()
});
context.draw()
},
drawImage: function() {
// #ifdef APP-PLUS
context.drawImage('../../../static/app-plus/uni@2x.png', 0, 0)
// #endif
// #ifndef APP-PLUS
context.drawImage('../../../static/uni.png', 0, 0)
// #endif
context.draw()
},
fillText: function() {
context.setStrokeStyle('#ff0000')
context.beginPath()
context.moveTo(0, 10)
context.lineTo(300, 10)
context.stroke()
// context.save()
// context.scale(1.5, 1.5)
// context.translate(20, 20)
context.setFontSize(10)
context.fillText('Hello World', 0, 30)
context.setFontSize(20)
context.fillText('Hello World', 100, 30)
// context.restore()
context.beginPath()
context.moveTo(0, 30)
context.lineTo(300, 30)
context.stroke()
context.draw()
},
fill: function() {
context.beginPath()
context.rect(20, 20, 150, 100)
context.setStrokeStyle('#00ff00')
context.fill()
context.draw()
},
stroke: function() {
context.beginPath()
context.moveTo(20, 20)
context.lineTo(20, 100)
context.lineTo(70, 100)
context.setStrokeStyle('#00ff00')
context.stroke()
context.draw()
},
clearRect: function() {
context.setFillStyle('#ff0000')
context.beginPath()
context.rect(0, 0, 300, 150)
context.fill()
context.clearRect(20, 20, 100, 50)
context.draw()
},
beginPath: function() {
context.beginPath()
context.setLineWidth(5)
context.setStrokeStyle('#ff0000')
context.moveTo(0, 75)
context.lineTo(250, 75)
context.stroke()
context.beginPath()
context.setStrokeStyle('#0000ff')
context.moveTo(50, 0)
context.lineTo(150, 130)
context.stroke()
context.draw()
},
closePath: function() {
context.beginPath()
context.setLineWidth(1)
context.moveTo(20, 20)
context.lineTo(20, 100)
context.lineTo(70, 100)
context.closePath()
context.stroke()
context.draw()
},
moveTo: function() {
context.beginPath()
context.moveTo(0, 0)
context.lineTo(300, 150)
context.stroke()
context.draw()
},
lineTo: function() {
context.beginPath()
context.moveTo(20, 20)
context.lineTo(20, 100)
context.lineTo(70, 100)
context.stroke()
context.draw()
},
rect: function() {
context.beginPath()
context.rect(20, 20, 150, 100)
context.stroke()
context.draw()
},
arc: function() {
context.beginPath()
context.setLineWidth(2)
context.arc(75, 75, 50, 0, Math.PI * 2, true)
context.moveTo(110, 75)
context.arc(75, 75, 35, 0, Math.PI, false)
context.moveTo(65, 65)
context.arc(60, 65, 5, 0, Math.PI * 2, true)
context.moveTo(95, 65)
context.arc(90, 65, 5, 0, Math.PI * 2, true)
context.stroke()
context.draw()
},
quadraticCurveTo: function() {
context.beginPath()
context.moveTo(20, 20)
context.quadraticCurveTo(20, 100, 200, 20)
context.stroke()
context.draw()
},
bezierCurveTo: function() {
context.beginPath()
context.moveTo(20, 20)
context.bezierCurveTo(20, 100, 200, 100, 200, 20)
context.stroke()
context.draw()
},
setFillStyle: function() {
['#fef957', 'rgb(242,159,63)', 'rgb(242,117,63)', '#e87e51'].forEach(function(item, index) {
context.setFillStyle(item)
context.beginPath()
context.rect(0 + 75 * index, 0, 50, 50)
context.fill()
})
context.draw()
},
setStrokeStyle: function() {
['#fef957', 'rgb(242,159,63)', 'rgb(242,117,63)', '#e87e51'].forEach(function(item, index) {
context.setStrokeStyle(item)
context.beginPath()
context.rect(0 + 75 * index, 0, 50, 50)
context.stroke()
})
context.draw()
},
setGlobalAlpha: function() {
context.setFillStyle('#000000');
[1, 0.5, 0.1].forEach(function(item, index) {
context.setGlobalAlpha(item)
context.beginPath()
context.rect(0 + 75 * index, 0, 50, 50)
context.fill()
})
context.draw()
context.setGlobalAlpha(1)
},
setShadow: function() {
context.beginPath()
context.setShadow(10, 10, 10, 'rgba(0, 0, 0, 199)')
context.rect(10, 10, 100, 100)
context.fill()
context.draw()
},
setFontSize: function() {
[10, 20, 30, 40].forEach(function(item, index) {
context.setFontSize(item)
context.fillText('Hello, world', 20, 20 + 40 * index)
})
context.draw()
},
setLineCap: function() {
context.setLineWidth(10);
['butt', 'round', 'square'].forEach(function(item, index) {
context.beginPath()
context.setLineCap(item)
context.moveTo(20, 20 + 20 * index)
context.lineTo(100, 20 + 20 * index)
context.stroke()
})
context.draw()
},
setLineJoin: function() {
context.setLineWidth(10);
['bevel', 'round', 'miter'].forEach(function(item, index) {
context.beginPath()
context.setLineJoin(item)
context.moveTo(20 + 80 * index, 20)
context.lineTo(100 + 80 * index, 50)
context.lineTo(20 + 80 * index, 100)
context.stroke()
})
context.draw()
},
setLineWidth: function() {
[2, 4, 6, 8, 10].forEach(function(item, index) {
context.beginPath()
context.setLineWidth(item)
context.moveTo(20, 20 + 20 * index)
context.lineTo(100, 20 + 20 * index)
context.stroke()
})
context.draw()
},
setMiterLimit: function() {
context.setLineWidth(4);
[2, 4, 6, 8, 10].forEach(function(item, index) {
context.beginPath()
context.setMiterLimit(item)
context.moveTo(20 + 80 * index, 20)
context.lineTo(100 + 80 * index, 50)
context.lineTo(20 + 80 * index, 100)
context.stroke()
})
context.draw()
}
}
}
</script>
<style>
.canvas-element-wrapper {
display: block;
margin-bottom: 100rpx;
}
.canvas-element {
width: 100%;
height: 500rpx;
background-color: #ffffff;
}
.canvas-buttons {
padding: 30rpx 50rpx 10rpx;
width: 100%;
height: 360rpx;
box-sizing: border-box;
}
.canvas-button {
float: left;
display: inline-flex;
align-items: center;
justify-content: center;
height: 40px;
line-height: 1;
width: 300rpx;
margin: 15rpx 12rpx;
}
</style>

View File

@ -0,0 +1,62 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap">
<view style="background:#FFFFFF; padding:40rpx;">
<view class="uni-hello-text uni-center">当前位置信息</view>
<block v-if="hasLocation === false">
<view class="uni-h2 uni-center uni-common-mt">未选择位置</view>
</block>
<block v-if="hasLocation === true">
<view class="uni-hello-text uni-center" style="margin-top:10px;">
{{locationAddress}}
</view>
<view class="uni-h2 uni-center uni-common-mt">
<text>E: {{location.longitude[0]}}°{{location.longitude[1]}}</text>
<text>\nN: {{location.latitude[0]}}°{{location.latitude[1]}}</text>
</view>
</block>
</view>
<view class="uni-btn-v">
<button type="primary" @tap="chooseLocation">选择位置</button>
<button @tap="clear">清空</button>
</view>
</view>
</view>
</template>
<script>
import * as util from '../../../common/util.js'
var formatLocation = util.formatLocation;
export default {
data() {
return {
title: 'chooseLocation',
hasLocation: false,
location: {},
locationAddress: ''
}
},
methods: {
chooseLocation: function () {
uni.chooseLocation({
success: (res) => {
this.hasLocation = true,
this.location = formatLocation(res.longitude, res.latitude),
this.locationAddress = res.address
}
})
},
clear: function () {
this.hasLocation = false
}
}
}
</script>
<style>
.page-body-info {
padding-bottom: 0;
height: 440rpx;
}
</style>

View File

@ -0,0 +1,91 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap">
<view class="uni-title">请输入剪贴板内容</view>
<view class="uni-list">
<view class="uni-list-cell">
<input class="uni-input" type="text" placeholder="请输入剪贴板内容" :value="data" @input="dataChange"/>
</view>
</view>
<view class="uni-btn-v">
<button type="primary" @click="setClipboard">存储数据</button>
<button @tap="getClipboard">读取数据</button>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'get/setClipboardData',
data: ''
}
},
methods: {
dataChange: function (e) {
this.data = e.detail.value
},
getClipboard: function () {
uni.getClipboardData({
success: (res) => {
console.log(res.data);
const content = res.data ? '剪贴板内容为:' + res.data : '剪贴板暂无内容';
uni.showModal({
content,
title: '读取剪贴板',
showCancel: false
})
},
fail: () => {
uni.showModal({
content: '读取剪贴板失败!',
showCancel: false
})
}
});
},
setClipboard: function () {
var data = this.data;
if (data.length === 0) {
uni.showModal({
title: '设置剪贴板失败',
content: '内容不能为空',
showCancel: false
})
} else {
uni.setClipboardData({
data: data,
success: () => {
//
// #ifdef MP-ALIPAY || MP-BAIDU || MP-TOUTIAO
uni.showToast({
title: '设置剪贴板成功',
icon: "success",
mask: !1
})
// #endif
},
fail: () => {
//
// #ifdef MP-ALIPAY || MP-BAIDU || MP-TOUTIAO
uni.showToast({
title: '储存数据失败!',
icon: "none",
mask: !1
})
// #endif
}
});
}
}
}
}
</script>
<style>
</style>

View File

@ -0,0 +1,63 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap uni-common-mt">
<view v-if="imageSrc" class="image-container">
<image class="img" :src="imageSrc" mode="center" />
</view>
<block v-else style="margin-top: 50px;">
<view class="uni-hello-text">
点击按钮下载服务端示例图片下载网络文件到本地临时目录
</view>
<view class="uni-btn-v">
<button type="primary" @tap="downloadImage">下载</button>
</view>
</block>
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'downloadFile',
imageSrc: ''
}
},
onUnload() {
this.imageSrc = '';
},
methods: {
downloadImage: function () {
uni.showLoading({
title:'下载中'
})
var self = this
uni.downloadFile({
url: "https://web-assets.dcloud.net.cn/unidoc/zh/uni-app.png",
success: (res) => {
console.log('downloadFile success, res is', res)
self.imageSrc = res.tempFilePath;
uni.hideLoading();
},
fail: (err) => {
console.log('downloadFile fail, err is:', err)
}
})
}
}
}
</script>
<style>
.img {
width: 500rpx;
height: 500rpx;
margin: 0 auto;
}
.image-container {
display: flex;
justify-content: center;
align-items: center;
}
</style>

129
pages/API/file/file.vue Normal file
View File

@ -0,0 +1,129 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap uni-common-mt">
<block v-if="tempFilePath">
<image :src="tempFilePath" class="image" mode="aspectFit"></image>
</block>
<block v-if="!tempFilePath && savedFilePath">
<image :src="savedFilePath" class="image" mode="aspectFit"></image>
</block>
<block v-if="!tempFilePath && !savedFilePath">
<view class="uni-hello-addfile" @click="chooseImage">+ 请选择文件</view>
</block>
<view class="uni-btn-v">
<button class="btn-savefile" @click="saveFile">保存文件</button>
<button @click="clear">删除文件</button>
</view>
<!-- #ifndef MP-ALIPAY || MP-TOUTIAO -->
<view class="btn-area">
<button @click="openDocument">打开pdf文件</button>
</view>
<!-- #endif -->
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'saveFile',
tempFilePath: '',
savedFilePath: ''
}
},
onLoad() {
this.savedFilePath = uni.getStorageSync('savedFilePath');
},
methods: {
chooseImage() {
uni.chooseImage({
count: 1,
success: (res) => {
this.tempFilePath = res.tempFilePaths[0];
},
fail: (err) => {
// #ifdef MP
uni.getSetting({
success: (res) => {
let authStatus = res.authSetting['scope.album'] && res.authSetting['scope.camera'];
if (!authStatus) {
uni.showModal({
title: '授权失败',
content: 'Hello uni-app需要从您的相机或相册获取图片请在设置界面打开相关权限',
success: (res) => {
if (res.confirm) {
uni.openSetting()
}
}
})
}
}
})
// #endif
}
});
},
saveFile() {
if (this.tempFilePath.length > 0) {
uni.saveFile({
tempFilePath: this.tempFilePath,
success: (res) => {
this.savedFilePath = res.savedFilePath;
uni.setStorageSync('savedFilePath', res.savedFilePath);
uni.showModal({
title: '保存成功',
content: '下次进入页面时,此文件仍可用',
showCancel: false
});
},
fail: (res) => {
uni.showModal({
title: '保存失败',
content: '失败原因: ' + JSON.stringify(res),
showCancel: false
});
}
})
} else {
uni.showModal({
content: '请选择文件',
showCancel: false
});
}
},
clear() {
uni.setStorageSync('savedFilePath', '');
this.tempFilePath = '';
this.savedFilePath = '';
},
// #ifndef MP-ALIPAY || MP-TOUTIAO
openDocument() {
uni.downloadFile({
url: 'https://web-assets.dcloud.net.cn/unidoc/zh/helloworld.pdf',
success: (res) => {
uni.openDocument({
filePath: res.tempFilePath,
success: () => {
console.log('打开文档成功');
}
});
}
});
},
// #endif
}
}
</script>
<style>
.image {
width: 100%;
height: 360rpx;
}
.btn-savefile {
background-color: #007aff;
color: #ffffff;
}
</style>

View File

@ -0,0 +1,84 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap uni-common-mt">
<button :loading="loading" :disabled="loading" type="primary" class="btn" @click="showAd">显示广告</button>
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: '全屏视频广告',
loading: false,
loadError: false
}
},
onReady() {
// #ifdef APP-PLUS
this.adOption = {
adpid: '1507000611'
};
// #endif
this.createAd();
},
methods: {
createAd() {
var _ad = this._ad = uni.createFullScreenVideoAd(this.adOption);
_ad.onLoad(() => {
this.loading = false;
this.loadError = false;
_ad.show();
console.log('onLoad event')
});
_ad.onClose((res) => {
// 广
if (res && res.isEnded) {
//
console.log("onClose " + res.isEnded);
} else {
// 退
console.log("onClose " + res.isEnded);
}
setTimeout(() => {
uni.showToast({
title: "全屏视频" + (res.isEnded ? "成功" : "未") + "播放完毕",
duration: 10000,
position: 'bottom'
})
}, 500)
});
_ad.onError((err) => {
this.loading = false;
if (err.code) {
this.loadError = true;
}
console.log('onError event', err)
uni.showToast({
title: err.errMsg,
position: 'bottom'
})
});
},
showAd() {
this.loading = true;
this._ad.load();
}
}
}
</script>
<style>
.btn {
margin-bottom: 20px;
}
.ad-tips {
color: #999;
padding: 30px 0;
text-align: center;
}
</style>

View File

@ -0,0 +1,186 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap">
<view style="background:#FFFFFF; padding:40rpx;">
<view class="uni-hello-text uni-center">当前位置经纬度</view>
<block v-if="hasLocation === false">
<view class="uni-h2 uni-center uni-common-mt">未获取</view>
</block>
<block v-if="hasLocation === true">
<view class="uni-h2 uni-center uni-common-mt">
<text>E: {{location.longitude[0]}}°{{location.longitude[1]}}</text>
<text>\nN: {{location.latitude[0]}}°{{location.latitude[1]}}</text>
</view>
</block>
</view>
<view class="uni-btn-v">
<button type="primary" @tap="getLocation">获取位置</button>
<button @tap="clear">清空</button>
</view>
</view>
<uni-popup :show="type === 'showpopup'" mode="fixed" @hidePopup="togglePopup('')">
<view class="popup-view">
<text class="popup-title">需要用户授权位置权限</text>
<view class="uni-flex popup-buttons">
<button class="uni-flex-item" type="primary" open-type="openSetting" @tap="openSetting">设置</button>
<button class="uni-flex-item" @tap="togglePopup('')">取消</button>
</view>
</view>
</uni-popup>
</view>
</template>
<script>
import * as util from '../../../common/util.js'
var formatLocation = util.formatLocation;
// #ifdef APP-PLUS
import permision from "@/common/permission.js"
// #endif
export default {
data() {
return {
title: 'getLocation',
hasLocation: false,
location: {},
type: ''
}
},
methods: {
togglePopup(type) {
this.type = type;
},
showConfirm() {
this.type = 'showpopup';
},
hideConfirm() {
this.type = '';
},
async getLocation() {
// #ifdef APP-PLUS
let status = await this.checkPermission();
if (status !== 1) {
return;
}
// #endif
// #ifdef MP-WEIXIN || MP-TOUTIAO || MP-QQ
let status = await this.getSetting();
if (status === 2) {
this.showConfirm();
return;
}
// #endif
this.doGetLocation();
},
doGetLocation() {
uni.getLocation({
success: (res) => {
this.hasLocation = true;
this.location = formatLocation(res.longitude, res.latitude);
},
fail: (err) => {
// #ifdef MP-BAIDU
if (err.errCode === 202 || err.errCode === 10003) { // 202 10003 user deny
this.showConfirm();
}
// #endif
// #ifndef MP-BAIDU
if (err.errMsg.indexOf("auth deny") >= 0) {
uni.showToast({
title: "访问位置被拒绝"
})
} else {
uni.showToast({
title: err.errMsg
})
}
// #endif
}
})
},
getSetting: function() {
return new Promise((resolve, reject) => {
uni.getSetting({
success: (res) => {
if (res.authSetting['scope.userLocation'] === undefined) {
resolve(0);
return;
}
if (res.authSetting['scope.userLocation']) {
resolve(1);
} else {
resolve(2);
}
}
});
});
},
openSetting: function() {
this.hideConfirm();
uni.openSetting({
success: (res) => {
if (res.authSetting && res.authSetting['scope.userLocation']) {
this.doGetLocation();
}
},
fail: (err) => {}
})
},
async checkPermission() {
let status = permision.isIOS ? await permision.requestIOS('location') :
await permision.requestAndroid('android.permission.ACCESS_FINE_LOCATION');
if (status === null || status === 1) {
status = 1;
} else if (status === 2) {
uni.showModal({
content: "系统定位已关闭",
confirmText: "确定",
showCancel: false,
success: function(res) {
}
})
} else if (status.code) {
uni.showModal({
content: status.message
})
} else {
uni.showModal({
content: "需要定位权限",
confirmText: "设置",
success: function(res) {
if (res.confirm) {
permision.gotoAppSetting();
}
}
})
}
return status;
},
clear: function() {
this.hasLocation = false
}
}
}
</script>
<style>
.popup-view {
width: 500rpx;
}
.popup-title {
display: block;
font-size: 16px;
line-height: 3;
margin-bottom: 10px;
text-align: center;
}
.popup-buttons button {
margin-left: 4px;
margin-right: 4px;
}
</style>

View File

@ -0,0 +1,86 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap uni-common-mt">
<view style="background:#FFFFFF; padding:40rpx;">
<view class="uni-hello-text uni-center">网络状态</view>
<block v-if="hasNetworkType === false">
<view class="uni-h2 uni-center uni-common-mt">未获取</view>
<view class="uni-hello-text uni-center uni-common-mt">请点击下面按钮获取网络状态</view>
</block>
<block v-if="hasNetworkType === true">
<view class="uni-h2 uni-center uni-common-mt">{{networkType}}</view>
</block>
<view v-if="hasNetworkType === true && networkType === 'wifi'" class="uni-textarea uni-common-mt">
<textarea :value="connectedWifi"></textarea>
</view>
</view>
<view class="uni-btn-v uni-common-mt">
<button type="primary" @tap="getNetworkType">获取设备网络状态</button>
<!-- #ifdef MP-WEIXIN || MP-JD-->
<button v-if="hasNetworkType === true && networkType === 'wifi'" class="uni-common-mt" type="primary" @tap="getConnectedWifi">获取 wifi 信息</button>
<!-- #endif -->
<button class="uni-common-mt" @tap="clear">清空</button>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'getNetworkType',
hasNetworkType: false,
networkType: '',
connectedWifi: ''
}
},
onUnload:function(){
this.networkType = '',this.hasNetworkType = false;
},
methods: {
getNetworkType: function () {
uni.getNetworkType({
success: (res) => {
console.log(res)
this.hasNetworkType = true, this.networkType = res.subtype || res.networkType
},
fail: () => {
uni.showModal({
content:'获取失败!',
showCancel:false
})
}
})
},
clear: function () {
this.hasNetworkType = false,
this.networkType = '',
this.connectedWifi = ''
},
// #ifdef MP-WEIXIN || MP-JD
getConnectedWifi() {
const that = this
uni.startWifi({
success: function() {
uni.getConnectedWifi({
success: function(res) {
const { wifi } = res
that.connectedWifi = JSON.stringify(wifi)
},
fail: function(res) {
}
})
},
fail: function(res) {
}
})
}
// #endif
}
}
</script>
<style>
</style>

View File

@ -0,0 +1,117 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap uni-common-mt">
<view class="movable block">
<!-- #ifndef MP-TOUTIAO -->
<movable-area>
<movable-view class="target" direction="all" @change="getNodeInfo">Drag</movable-view>
</movable-area>
<!-- #endif -->
<!-- #ifdef MP-TOUTIAO -->
<view class="target" @click="setPosition" :style="{top:top,left:left}">Click</view>
<!-- #endif -->
</view>
<view class="movable">
<view class="info">
<view v-for="(item,index) in info" :key="index">
<text class="b">{{item.key}}</text>
<text class="span">{{item.val}}</text>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'createSelectorQuery',
top: 0,
left: '0px',
info: []
}
},
onReady() {
this.getNodeInfo()
},
methods: {
setPosition() {
this.left = Math.random() * uni.upx2px(320) + 'px'
this.top = Math.random() * uni.upx2px(320) + 'px'
this.getNodeInfo()
},
getNodeInfo() {
uni.createSelectorQuery().select('.target').boundingClientRect().exec((ret) => {
const rect = ret[0]
if (rect) {
const sort = ['left','right','top','bottom','width','height']
const info = []
for (let i in sort) {
let key = sort[i]
info.push({
'key': key,
'val': rect[key]
})
}
this.info = info
}
});
}
},
}
</script>
<style>
.movable {
display: flex;
justify-content: center;
}
.block {
height: 400rpx;
width: 400rpx;
background-color: #FFFFFF;
border: 1px solid #ccc;
position: relative;
margin: 0 auto;
margin-bottom: 30rpx;
}
movable-area {
height: 400rpx;
width: 400rpx;
position: relative;
}
.target {
height: 80rpx;
width: 80rpx;
line-height: 80rpx;
text-align: center;
color: #FFFFFF;
background-color: #4cd964;
font-size: 28rpx;
position: absolute;
}
.info {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.b {
font-weight: bold;
width: 150rpx;
display: inline-block;
}
.span {
width: 100rpx;
display: inline-block;
}
</style>

View File

@ -0,0 +1,148 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-common-mt">
<view class="uni-list">
<view class="uni-list-cell">
<view class="uni-pd">
<view class="uni-label" style="width:180px;">设备型号</view>
</view>
<view class="uni-list-cell-db">
<input class="uni-input" type="text" :disabled="true" placeholder="未获取" :value="systemInfo.model"/>
</view>
</view>
<view class="uni-list-cell">
<view class="uni-pd">
<view class="uni-label" style="width:180px;">客户端平台</view>
</view>
<view class="uni-list-cell-db">
<input class="uni-input" type="text" :disabled="true" placeholder="未获取" :value="systemInfo.platform"/>
</view>
</view>
<view class="uni-list-cell">
<view class="uni-pd">
<view class="uni-label" style="width:180px;">操作系统版本</view>
</view>
<view class="uni-list-cell-db">
<input class="uni-input" type="text" :disabled="true" placeholder="未获取" :value="systemInfo.system"/>
</view>
</view>
<view class="uni-list-cell">
<view class="uni-pd">
<view class="uni-label" style="width:180px;">语言</view>
</view>
<view class="uni-list-cell-db">
<input class="uni-input" type="text" :disabled="true" placeholder="未获取" :value="systemInfo.language"/>
</view>
</view>
<view class="uni-list-cell">
<view class="uni-pd">
<view class="uni-label" style="width:180px;">版本</view>
</view>
<view class="uni-list-cell-db">
<input class="uni-input" type="text" :disabled="true" placeholder="未获取" :value="systemInfo.version"/>
</view>
</view>
<view class="uni-list-cell">
<view class="uni-pd">
<view class="uni-label" style="width:180px;">屏幕宽度</view>
</view>
<view class="uni-list-cell-db">
<input class="uni-input" type="text" :disabled="true" placeholder="未获取" :value="systemInfo.screenWidth"/>
</view>
</view>
<view class="uni-list-cell">
<view class="uni-pd">
<view class="uni-label" style="width:180px;">屏幕高度</view>
</view>
<view class="uni-list-cell-db">
<input class="uni-input" type="text" :disabled="true" placeholder="未获取" :value="systemInfo.screenHeight"/>
</view>
</view>
<view class="uni-list-cell">
<view class="uni-pd">
<view class="uni-label" style="width:180px;">可使用窗口高度</view>
</view>
<view class="uni-list-cell-db">
<input class="uni-input" type="text" :disabled="true" placeholder="未获取" :value="systemInfo.windowHeight"/>
</view>
</view>
<view class="uni-list-cell">
<view class="uni-pd">
<view class="uni-label" style="width:180px;">可使用窗口的顶部位置</view>
</view>
<view class="uni-list-cell-db">
<input class="uni-input" type="text" :disabled="true" placeholder="未获取" :value="systemInfo.windowTop"/>
</view>
</view>
<view class="uni-list-cell">
<view class="uni-pd">
<view class="uni-label" style="width:180px;">可使用窗口的底部位置</view>
</view>
<view class="uni-list-cell-db">
<input class="uni-input" type="text" :disabled="true" placeholder="未获取" :value="systemInfo.windowBottom"/>
</view>
</view>
<view class="uni-list-cell">
<view class="uni-pd">
<view class="uni-label" style="width:180px;">状态栏的高度</view>
</view>
<view class="uni-list-cell-db">
<input class="uni-input" type="text" :disabled="true" placeholder="未获取" :value="systemInfo.statusBarHeight"/>
</view>
</view>
<view class="uni-list-cell">
<view class="uni-pd">
<view class="uni-label" style="width:180px;">DPI</view>
</view>
<view class="uni-list-cell-db">
<input class="uni-input" type="text" :disabled="true" placeholder="未获取" :value="systemInfo.pixelRatio"/>
</view>
</view>
<!-- #ifdef MP -->
<view class="uni-list-cell">
<view class="uni-pd">
<view class="uni-label" style="width:180px;">基础库版本</view>
</view>
<view class="uni-list-cell-db">
<input class="uni-input" type="text" :disabled="true" placeholder="未获取" :value="systemInfo.SDKVersion"/>
</view>
</view>
<!-- #endif -->
</view>
<view class="uni-padding-wrap">
<view class="uni-btn-v">
<button type="primary" @tap="getSystemInfo">获取设备系统信息</button>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'getSystemInfo',
systemInfo: {}
}
},
onUnload:function(){
this.systemInfo = {};
},
methods: {
getSystemInfo: function () {
uni.getSystemInfo({
success: (res) => {
this.systemInfo = res
}
})
}
}
}
</script>
<style>
.uni-pd {
padding-left: 30rpx;
}
</style>

View File

@ -0,0 +1,165 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap">
<view style="background:#FFF; padding:40rpx;">
<block v-if="hasUserInfo === false">
<view class="uni-hello-text uni-center">
<text>请点击下方按钮获取用户头像及昵称或手机号</text>
</view>
</block>
<block v-if="hasUserInfo === true">
<view class="uni-h4 uni-center uni-common-mt">{{userInfo.nickName || userInfo.nickname || userInfo.gender || userInfo.email || userInfo.phoneNumber}}</view>
<view v-if="userInfo.avatarUrl || userInfo.avatar_url " style="padding:30rpx 0; text-align:center;">
<image class="userinfo-avatar" :src="userInfo.avatarUrl||userInfo.avatar_url"></image>
</view>
</block>
</view>
<view class="uni-btn-v">
<!-- #ifdef APP-PLUS || MP-ALIPAY || MP-TOUTIAO -->
<button type="primary" :loading="btnLoading" @click="getUserInfo">获取用户信息</button>
<!-- #endif -->
<!-- #ifdef MP-WEIXIN || MP-BAIDU || MP-QQ || MP-JD -->
<button type="primary" open-type="getUserInfo" @getuserinfo="mpGetUserInfo">获取用户信息</button>
<!-- #endif -->
<button @click="clear">清空</button>
</view>
</view>
</view>
</template>
<script>
import {
mapState,
mapMutations,
mapActions
} from 'vuex'
export default {
data() {
return {
title: 'getUserInfo',
hasUserInfo: false,
userInfo: {},
btnLoading: false
}
},
computed: {
...mapState([
'loginProvider',
'isUniverifyLogin'
])
},
methods: {
...mapActions(['getPhoneNumber']),
// API 使 5+App
getUserInfo() {
this.btnLoading = true;
if (this.isUniverifyLogin) {
//
this.getPhoneNumber(uni.getStorageSync('univerifyInfo')).then(phoneNumber => {
this.hasUserInfo = true;
this.userInfo = {
phoneNumber
};
}).catch(err => {
console.error('getUserInfo fail:', err);
this.hasUserInfo = false;
}).finally(() => {
this.btnLoading = false;
})
return;
}
if(this.loginProvider === 'apple'){
const nickname = uni.getStorageSync('apple_nickname')
if(nickname){
this.hasUserInfo = true;
this.userInfo = { nickName:nickname }
this.btnLoading = false;
return;
}
}
uni.getUserInfo({
provider: this.loginProvider,
success: (result) => {
this.hasUserInfo = true;
this.userInfo = result.userInfo;
},
fail: (error) => {
console.log('getUserInfo fail', error);
let content = error.errMsg;
if (~content.indexOf('uni.login')) {
content = '请在登录页面完成登录操作';
}
// #ifndef APP-PLUS
uni.getSetting({
success: (res) => {
let authStatus = res.authSetting['scope.userInfo'];
if (!authStatus) {
uni.showModal({
title: '授权失败',
content: 'Hello uni-app需要获取您的用户信息请在设置界面打开相关权限',
success: (res) => {
if (res.confirm) {
uni.openSetting()
}
}
})
} else {
uni.showModal({
title: '获取用户信息失败',
content: '错误原因' + content,
showCancel: false
});
}
}
})
// #endif
// #ifdef APP-PLUS
uni.showModal({
title: '获取用户信息失败',
content: '错误原因' + content,
showCancel: false
});
// #endif
},
complete: () => {
this.btnLoading = false;
}
});
},
mpGetUserInfo(result) {
console.log('mpGetUserInfo', result);
if (result.detail.errMsg !== 'getUserInfo:ok') {
uni.showModal({
title: '获取用户信息失败',
content: '错误原因' + result.detail.errMsg,
showCancel: false
});
return;
}
this.hasUserInfo = true;
if(result.detail && result.detail.userInfo){
this.userInfo = result.detail.userInfo;
}else{
// #ifdef MP-JD
this.userInfo = result.detail.user_info;
// #endif
}
},
clear() {
this.hasUserInfo = false;
this.userInfo = {};
}
}
}
</script>
<style>
.userinfo-avatar {
border-radius: 128rpx;
width: 128rpx;
height: 128rpx;
}
</style>

View File

@ -0,0 +1,300 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap uni-common-mt">
<view class="uni-btn-v">
<button type="primary" :disabled="isOpen" @click="openBluetoothAdapter">打开蓝牙模块</button>
<button type="primary" :disabled="!isOpen" @click="closeBluetoothAdapter">关闭蓝牙模块</button>
<button type="primary" :disabled="!isOpen || isStarted" :loading="isStarted" @click="startBeaconDiscovery">开始搜索附近的iBeacon设备</button>
<button type="primary" :disabled="!isStarted" @click="stopBeaconDiscovery">停止搜索附近的iBeacon设备</button>
</view>
</view>
<scroll-view class="uni-scroll_box">
<view class="uni-title" v-if="isStarted || deviceList.length > 0">已经发现 {{ deviceList.length }} 台设备:</view>
<view class="uni-list-box" v-for="(item, index) in deviceList" :key="item.uuid">
<view>
<view class="uni-list_name">UUID: {{ item.uuid }}</view>
<view class="uni-list_item">major: {{ item.major }}</view>
<view class="uni-list_item">minor: {{ item.minor }}</view>
<view class="uni-list_item">rssi: {{ item.rssi }} dBm</view>
<view class="uni-list_item">accuracy: {{ item.accuracy }}</view>
<view class="uni-list_item">heading: {{ item.heading }}</view>
</view>
</view>
</scroll-view>
</view>
</template>
<script>
const DEVICE_UUID_WEICHAT = 'FDA50693-A4E2-4FB1-AFCF-C6EB07647825';
export default {
data() {
return {
title: 'iBeacon',
isOpen: false,
isStarted: false,
deviceList: [],
isPageOpened: false
};
},
onLoad() {
this.onBeaconUpdate();
},
onShow() {
this.isPageOpened = true;
},
methods: {
maskclose() {
this.maskShow = false;
},
openBluetoothAdapter() {
uni.openBluetoothAdapter({
success: (res) => {
console.log('初始化蓝牙成功:' + res.errMsg);
console.log(res);
this.isOpen = true;
this.deviceList = [];
},
fail: (err) => {
console.log('初始化蓝牙失败,错误码:' + (err.errCode || err.errMsg));
if (err.errCode !== 0) {
initTypes(err.errCode, err.errMsg);
}
}
});
},
closeBluetoothAdapter(OBJECT) {
this.stopBeaconDiscovery();
wx.closeBluetoothAdapter({
success: (res) => {
this.isOpen = false;
console.log('断开蓝牙模块成功');
}
});
},
onBeaconUpdate() {
uni.onBeaconUpdate(res => {
if (!this.isPageOpened || !this.isOpen || !this.isStarted) {
return;
}
console.log(res);
// if (res.code !== 0) {
// return;
// }
if (res.beacons && res.beacons.length > 0) {
this.getBeacons();
} else if (!res.connected) {
this.deviceList = [];
}
});
},
startBeaconDiscovery() {
uni.startBeaconDiscovery({
uuids: this.getUUIDList(),
success: (res) => {
this.isStarted = true;
console.log(res);
},
fail: (err) => {
console.error(err);
}
});
},
stopBeaconDiscovery(types) {
if(this.isStarted) {
uni.stopBeaconDiscovery({
success: (res) => {
this.isStarted = false;
},
fail: (err) => {
console.error(err);
}
});
}
},
getBeacons() {
uni.getBeacons({
success: (res) => {
if (res.beacons && res.beacons.length > 0) {
console.log(res.beacons);
this.deviceList = res.beacons;
}
},
fail: (err) => {
console.log('获取设备服务失败,错误码:' + err.errCode);
if (errCode.errCode !== 0) {
initTypes(errCode.errCode);
}
}
});
},
getUUIDList() {
// #ifdef APP-PLUS
const sysInfo = uni.getSystemInfoSync();
if (!sysInfo) {
return [];
}
let isIOS = sysInfo.platform ? (sysInfo.platform.toLowerCase() === "ios") : false;
if (isIOS) {
return [DEVICE_UUID_WEICHAT];
}
return [];
// #endif
// #ifndef APP-PLUS
return [DEVICE_UUID_WEICHAT];
// #endif
}
},
onUnload() {
this.isPageOpened = false;
}
};
/**
* 判断初始化蓝牙状态
*/
function initTypes(code, errMsg) {
switch (code) {
case 10000:
toast('未初始化蓝牙适配器');
break;
case 10001:
toast('未检测到蓝牙,请打开蓝牙重试!');
break;
case 10002:
toast('没有找到指定设备');
break;
case 10003:
toast('连接失败');
break;
case 10004:
toast('没有找到指定服务');
break;
case 10005:
toast('没有找到指定特征值');
break;
case 10006:
toast('当前连接已断开');
break;
case 10007:
toast('当前特征值不支持此操作');
break;
case 10008:
toast('其余所有系统上报的异常');
break;
case 10009:
toast('Android 系统特有,系统版本低于 4.3 不支持 BLE');
break;
default:
toast(errMsg);
}
}
/**
* 弹出框封装
*/
function toast(content, showCancel = false) {
uni.showModal({
title: '提示',
content,
showCancel
});
}
</script>
<style>
.uni-title {
/* width: 100%; */
/* height: 80rpx; */
text-align: center;
}
.uni-mask {
position: fixed;
top: 0;
left: 0;
bottom: 0;
display: flex;
align-items: center;
width: 100%;
background: rgba(0, 0, 0, 0.6);
padding: 0 30rpx;
box-sizing: border-box;
}
.uni-scroll_box {
height: 70%;
background: #fff;
border-radius: 20rpx;
}
.uni-list-box {
margin: 0 20rpx;
padding: 15rpx 0;
border-bottom: 1px #f5f5f5 solid;
box-sizing: border-box;
}
.uni-list:last-child {
border: none;
}
.uni-list_name {
font-size: 30rpx;
color: #333;
}
.uni-list_item {
font-size: 24rpx;
color: #555;
line-height: 1.5;
}
.uni-success_box {
position: absolute;
left: 0;
bottom: 0;
min-height: 100rpx;
width: 100%;
background: #fff;
box-sizing: border-box;
border-top: 1px #eee solid;
}
.uni-success_sub {
/* width: 100%%; */
height: 100rpx;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 30rpx;
}
.uni-close_button {
padding: 0 20rpx;
height: 60rpx;
line-height: 60rpx;
background: #ce3c39;
color: #ffffff;
border-radius: 10rpx;
}
.uni-success_content {
height: 600rpx;
margin: 30rpx;
margin-top: 0;
border: 1px #eee solid;
padding: 30rpx;
}
.uni-content_list {
padding-bottom: 10rpx;
border-bottom: 1px #f5f5f5 solid;
}
.uni-tips {
text-align: center;
font-size: 24rpx;
color: #666;
}
</style>

239
pages/API/image/image.vue Normal file
View File

@ -0,0 +1,239 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-common-mt">
<form>
<view class="uni-list">
<view class="uni-list-cell">
<view class="uni-list-cell-left">
<view class="uni-label">图片来源</view>
</view>
<view class="uni-list-cell-right">
<picker :range="sourceType" @change="sourceTypeChange" :value="sourceTypeIndex" mode="selector">
<view class="uni-input">{{sourceType[sourceTypeIndex]}}</view>
</picker>
</view>
</view>
<view class="uni-list-cell">
<view class="uni-list-cell-left">
<view class="uni-label">图片质量</view>
</view>
<view class="uni-list-cell-right">
<picker :range="sizeType" @change="sizeTypeChange" :value="sizeTypeIndex" mode="selector">
<view class="uni-input">{{sizeType[sizeTypeIndex]}}</view>
</picker>
</view>
</view>
<view class="uni-list-cell">
<view class="uni-list-cell-left">
<view class="uni-label">数量限制</view>
</view>
<view class="uni-list-cell-right">
<picker :range="count" @change="countChange" mode="selector">
<view class="uni-input">{{count[countIndex]}}</view>
</picker>
</view>
</view>
</view>
<view class="uni-list list-pd">
<view class="uni-list-cell cell-pd">
<view class="uni-uploader">
<view class="uni-uploader-head">
<view class="uni-uploader-title">点击可预览选好的图片</view>
<view class="uni-uploader-info">{{imageList.length}}/9</view>
</view>
<view class="uni-uploader-body">
<view class="uni-uploader__files">
<block v-for="(image,index) in imageList" :key="index">
<view class="uni-uploader__file">
<image class="uni-uploader__img" :src="image" :data-src="image" @tap="previewImage"></image>
</view>
</block>
<view class="uni-uploader__input-box">
<view class="uni-uploader__input" @tap="chooseImage"></view>
</view>
</view>
</view>
</view>
</view>
</view>
</form>
</view>
</view>
</template>
<script>
import permision from "@/common/permission.js"
var sourceType = [
['camera'],
['album'],
['camera', 'album']
]
var sizeType = [
['compressed'],
['original'],
['compressed', 'original']
]
export default {
data() {
return {
title: 'choose/previewImage',
imageList: [],
sourceTypeIndex: 2,
sourceType: ['拍照', '相册', '拍照或相册'],
sizeTypeIndex: 2,
sizeType: ['压缩', '原图', '压缩或原图'],
countIndex: 8,
count: [1, 2, 3, 4, 5, 6, 7, 8, 9]
}
},
onUnload() {
this.imageList = [],
this.sourceTypeIndex = 2,
this.sourceType = ['拍照', '相册', '拍照或相册'],
this.sizeTypeIndex = 2,
this.sizeType = ['压缩', '原图', '压缩或原图'],
this.countIndex = 8;
},
methods: {
sourceTypeChange: function(e) {
this.sourceTypeIndex = parseInt(e.detail.value)
},
sizeTypeChange: function(e) {
this.sizeTypeIndex = parseInt(e.detail.value)
},
countChange: function(e) {
this.countIndex = e.detail.value;
},
chooseImage: async function() {
// #ifdef APP-PLUS
// TODO actionsheet
if (this.sourceTypeIndex !== 2) {
let status = await this.checkPermission();
if (status !== 1) {
return;
}
}
// #endif
if (this.imageList.length === 9) {
let isContinue = await this.isFullImg();
console.log("是否继续?", isContinue);
if (!isContinue) {
return;
}
}
uni.chooseImage({
sourceType: sourceType[this.sourceTypeIndex],
sizeType: sizeType[this.sizeTypeIndex],
count: this.imageList.length + this.count[this.countIndex] > 9 ? 9 - this.imageList.length : this.count[this.countIndex],
success: (res) => {
this.imageList = this.imageList.concat(res.tempFilePaths);
},
fail: (err) => {
console.log("err: ",err);
// #ifdef APP-PLUS
if (err['code'] && err.code !== 0 && this.sourceTypeIndex === 2) {
this.checkPermission(err.code);
}
// #endif
// #ifdef MP
if(err.errMsg.indexOf('cancel') !== '-1'){
return;
}
uni.getSetting({
success: (res) => {
let authStatus = false;
switch (this.sourceTypeIndex) {
case 0:
authStatus = res.authSetting['scope.camera'];
break;
case 1:
authStatus = res.authSetting['scope.album'];
break;
case 2:
authStatus = res.authSetting['scope.album'] && res.authSetting['scope.camera'];
break;
default:
break;
}
if (!authStatus) {
uni.showModal({
title: '授权失败',
content: 'Hello uni-app需要从您的相机或相册获取图片请在设置界面打开相关权限',
success: (res) => {
if (res.confirm) {
uni.openSetting()
}
}
})
}
}
})
// #endif
}
})
},
isFullImg: function() {
return new Promise((res) => {
uni.showModal({
content: "已经有9张图片了,是否清空现有图片?",
success: (e) => {
if (e.confirm) {
this.imageList = [];
res(true);
} else {
res(false)
}
},
fail: () => {
res(false)
}
})
})
},
previewImage: function(e) {
var current = e.target.dataset.src
uni.previewImage({
current: current,
urls: this.imageList
})
},
async checkPermission(code) {
let type = code ? code - 1 : this.sourceTypeIndex;
let status = permision.isIOS ? await permision.requestIOS(sourceType[type][0]) :
await permision.requestAndroid(type === 0 ? 'android.permission.CAMERA' :
'android.permission.READ_EXTERNAL_STORAGE');
if (status === null || status === 1) {
status = 1;
} else {
uni.showModal({
content: "没有开启权限",
confirmText: "设置",
success: function(res) {
if (res.confirm) {
permision.gotoAppSetting();
}
}
})
}
return status;
}
}
}
</script>
<style>
.cell-pd {
padding: 22rpx 30rpx;
}
.list-pd {
margin-top: 50rpx;
}
</style>

View File

@ -0,0 +1,124 @@
<template>
<view class="uni-padding-wrap">
<page-head title="audio"></page-head>
<view class="uni-common-mt">
<slider :value="position" :min="0" :max="duration" @changing="onchanging" @change="onchange"></slider>
</view>
<!-- <view class="uni-common-mt play-time-area">
<text class="current-time">{{currentTime}}</text>
<text class="duration">{{duration}}</text>
</view> -->
<view class="play-button-area">
<image class="icon-play" :src="playImage" @click="play"></image>
</view>
</view>
</template>
<script>
const audioUrl = 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-hello-uniapp/2cc220e0-c27a-11ea-9dfb-6da8e309e0d8.mp3'
export default {
data() {
return {
title: "innerAudioContext",
isPlaying: false,
isPlayEnd: false,
currentTime: 0,
duration: 100
}
},
computed: {
position() {
return this.isPlayEnd ? 0 : this.currentTime;
},
playImage() {
return this.isPlaying ? "/static/pause.png" : "/static/play.png"
}
},
onLoad() {
this._isChanging = false;
this._audioContext = null;
this.createAudio();
},
onUnload() {
if (this._audioContext != null && this.isPlaying) {
this.stop();
}
},
methods: {
createAudio() {
var innerAudioContext = this._audioContext = uni.createInnerAudioContext();
innerAudioContext.autoplay = false;
innerAudioContext.src = audioUrl;
innerAudioContext.onPlay(() => {
console.log('开始播放');
});
innerAudioContext.onTimeUpdate((e) => {
if (this._isChanging === true) {
return;
}
this.currentTime = innerAudioContext.currentTime || 0;
this.duration = innerAudioContext.duration || 0;
});
innerAudioContext.onEnded(() => {
this.currentTime = 0;
this.isPlaying = false;
this.isPlayEnd = true;
});
innerAudioContext.onError((res) => {
this.isPlaying = false;
console.log(res.errMsg);
console.log(res.errCode);
});
return innerAudioContext;
},
onchanging() {
this._isChanging = true;
},
onchange(e) {
console.log(e.detail.value);
console.log(typeof e.detail.value);
this._audioContext.seek(e.detail.value);
this._isChanging = false;
},
play() {
if (this.isPlaying) {
this.pause();
return;
}
this.isPlaying = true;
this._audioContext.play();
this.isPlayEnd = false;
},
pause() {
this._audioContext.pause();
this.isPlaying = false;
},
stop() {
this._audioContext.stop();
this.isPlaying = false;
}
}
}
</script>
<style>
.play-time-area {
display: flex;
flex-direction: row;
margin-top: 20px;
}
.duration {
margin-left: auto;
}
.play-button-area {
display: flex;
flex-direction: row;
justify-content: center;
margin-top: 50px;
}
.icon-play {
width: 60px;
height: 60px;
}
</style>

View File

@ -0,0 +1,69 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap uni-common-mt">
<view class="uni-title uni-common-mt">
{{appear ? '小球出现' : '小球消失'}}
</view>
<scroll-view class="scroll-view" scroll-y>
<view class="scroll-area">
<text class="notice">向下滚动让小球出现</text>
<view class="ball"></view>
</view>
</scroll-view>
</view>
</view>
</template>
<script>
let observer = null;
export default {
data() {
return {
appear: false,
title:'intersectionObserver'
}
},
onReady() {
observer = uni.createIntersectionObserver(this);
observer.relativeTo('.scroll-view').observe('.ball', (res) => {
if (res.intersectionRatio > 0 && !this.appear) {
this.appear = true;
} else if (!res.intersectionRatio > 0 && this.appear) {
this.appear = false;
}
})
},
onUnload() {
if (observer) {
observer.disconnect()
}
}
}
</script>
<style>
.scroll-view {
height: 400rpx;
background: #fff;
border: 1px solid #ccc;
box-sizing: border-box;
}
.scroll-area {
height: 1300rpx;
display: flex;
flex-direction: column;
align-items: center;
}
.notice {
margin-top: 150rpx;
margin: 150rpx 0 400rpx 0;
}
.ball {
width: 200rpx;
height: 200rpx;
background: #4cd964;
border-radius: 50%;
}
</style>

322
pages/API/login/login.vue Normal file
View File

@ -0,0 +1,322 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap">
<view style="background:#FFF; padding:40rpx;">
<block v-if="hasLogin === true">
<view class="uni-h3 uni-center uni-common-mt">已登录
<text v-if="isUniverifyLogin" style="font-size: 0.8em;">
<i v-if="!phoneNumber.length" class="uni-icon_toast uni-loading"></i>
<i v-else>{{phoneNumber}}</i>
</text>
</view>
<view class="uni-hello-text uni-center">
<text>每个账号仅需登录 1 \n后续每次进入页面即可自动拉取用户信息</text>
</view>
</block>
<block v-if="hasLogin === false">
<view class="uni-h3 uni-center uni-common-mt">未登录</view>
<view class="uni-hello-text uni-center">
请点击按钮登录
</view>
</block>
</view>
<view class="uni-btn-v uni- uni-common-mt">
<!-- #ifdef MP-TOUTIAO -->
<button type="primary" class="page-body-button" v-for="(value,key) in providerList" @click="tologin(value)" :key="key">
登录
</button>
<!-- #endif -->
<!-- #ifndef MP-TOUTIAO -->
<button type="primary" class="page-body-button" v-for="(value,key) in providerList" @click="tologin(value)"
:loading="value.id === 'univerify' ? univerifyBtnLoading : false" :key="key">{{value.name}}</button>
<!-- #endif -->
</view>
</view>
</view>
</template>
<script>
import {
mapState,
mapMutations,
mapActions
} from 'vuex'
const univerifyInfoKey = 'univerifyInfo';
export default {
data() {
return {
title: 'login',
providerList: [],
phoneNumber: '',
univerifyBtnLoading: false
}
},
computed: {
...mapState(['hasLogin', 'isUniverifyLogin', 'univerifyErrorMsg'])
},
onLoad() {
uni.getProvider({
service: 'oauth',
success: (result) => {
this.providerList = result.provider.map((value) => {
let providerName = '';
switch (value) {
case 'weixin':
providerName = '微信登录'
break;
case 'qq':
providerName = 'QQ登录'
break;
case 'sinaweibo':
providerName = '新浪微博登录'
break;
case 'xiaomi':
providerName = '小米登录'
break;
case 'alipay':
providerName = '支付宝登录'
break;
case 'baidu':
providerName = '百度登录'
break;
case 'jd':
providerName = '京东登录'
break;
case 'toutiao':
providerName = '头条登录'
break;
case 'apple':
providerName = '苹果登录'
break;
case 'univerify':
providerName = '一键登录'
break;
}
return {
name: providerName,
id: value
}
});
},
fail: (error) => {
console.log('获取登录通道失败', error);
}
});
if (this.hasLogin && this.isUniverifyLogin) {
this.getPhoneNumber(uni.getStorageSync(univerifyInfoKey)).then((phoneNumber) => {
this.phoneNumber = phoneNumber
})
}
},
methods: {
...mapMutations(['login', 'setUniverifyLogin']),
...mapActions(['getPhoneNumber']),
Toast(data, duration = 1000) {
uni.showToast(Object.assign({}, data, {
duration
}))
},
tologin(provider) {
if (provider.id === 'univerify') {
this.univerifyBtnLoading = true;
}
// APP onLaunch
uni.login({
provider: provider.id,
// #ifdef MP-ALIPAY
scopes: 'auth_user', //
// #endif
success: async (res) => {
console.log('login success:', res);
this.Toast({
title: '登录成功'
})
// store
this.login(provider.id);
// #ifdef APP-PLUS
this.setUniverifyLogin(provider.id === 'univerify')
switch (provider.id) {
case 'univerify':
this.loginByUniverify(provider.id, res)
break;
case 'apple':
this.loginByApple(provider.id, res)
break;
}
// #endif
// #ifdef MP-WEIXIN
console.warn('如需获取openid请参考uni-id: https://uniapp.dcloud.net.cn/uniCloud/uni-id')
uni.request({
url: 'https://97fca9f2-41f6-449f-a35e-3f135d4c3875.bspapp.com/http/user-center',
method: 'POST',
data: {
action: 'loginByWeixin',
params: {
code: res.code,
platform: 'mp-weixin'
}
},
success(res) {
console.log(res);
if (res.data.code !== 0) {
console.log('获取openid失败', res.data.errMsg);
return
}
uni.setStorageSync('openid', res.data.openid)
},
fail(err) {
console.log('获取openid失败', err);
}
})
// #endif
},
fail: (err) => {
console.log('login fail:', err);
//
if (err.code == '30002') {
uni.closeAuthView();
this.Toast({
title: '其他登录方式'
})
return;
}
//
if (err.code == 1000) {
uni.showModal({
title: '登录失败',
content: `${err.errMsg}\n错误码${err.code}`,
confirmText: '开通指南',
cancelText: '确定',
success: (res) => {
if (res.confirm) {
setTimeout(() => {
plus.runtime.openWeb('https://ask.dcloud.net.cn/article/37965')
}, 500)
}
}
});
return;
}
//
if (err.code == '30005') {
uni.showModal({
showCancel: false,
title: '预登录失败',
content: this.univerifyErrorMsg || err.errMsg
});
return;
}
//
if (err.code != '30003') {
uni.showModal({
showCancel: false,
title: '登录失败',
content: JSON.stringify(err)
});
}
},
complete: () => {
this.univerifyBtnLoading = false;
}
});
},
loginByUniverify(provider, res) {
this.setUniverifyLogin(true);
uni.closeAuthView();
const univerifyInfo = {
provider,
...res.authResult,
}
this.getPhoneNumber(univerifyInfo).then((phoneNumber) => {
this.phoneNumber = phoneNumber;
uni.setStorageSync(univerifyInfoKey, univerifyInfo)
}).catch(err => {
uni.showModal({
showCancel: false,
title: '手机号获取失败',
content: `${err.errMsg}\n错误码${err.code}`
})
console.error(res);
})
},
async loginByApple(provider, res) {
//
let getUserInfoErr, result
// #ifndef VUE3
[getUserInfoErr, result] = await uni.getUserInfo({
provider
});
// #endif
// #ifdef VUE3
try {
result = await uni.getUserInfo({
provider
});
} catch(e) {
getUserInfoErr = e
}
// #endif
if (getUserInfoErr) {
let content = getUserInfoErr.errMsg;
if (~content.indexOf('uni.login')) {
content = '请在登录页面完成登录操作';
}
uni.showModal({
title: '获取用户信息失败',
content: '错误原因' + content,
showCancel: false
});
}
// uni-id
console.warn('此处使用uni-id处理苹果登录详情参考: https://uniapp.dcloud.net.cn/uniCloud/uni-id')
uni.request({
url: 'https://97fca9f2-41f6-449f-a35e-3f135d4c3875.bspapp.com/http/user-center',
method: 'POST',
data: {
action: 'loginByApple',
params: result.userInfo
},
success: (res) => {
console.log('uniId login success', res);
if(res.data.code !== 0){
uni.showModal({
showCancel: false,
content: `苹果登录失败: ${JSON.stringify(res.data.msg)}`,
})
} else {
uni.setStorageSync('openid', res.data.openid)
uni.setStorageSync('apple_nickname', res.data.userInfo.nickname)
}
},
fail: (e) => {
uni.showModal({
content: `苹果登录失败: ${JSON.stringify(e)}`,
showCancel: false
})
}
})
}
}
}
</script>
<style>
button {
background-color: #007aff;
color: #ffffff;
}
</style>

View File

@ -0,0 +1,50 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap uni-common-mt">
<view class="uni-hello-text uni-center">请在下方输入电话号码</view>
<input class="input uni-common-mt" type="number" name="input" @input="bindInput" />
<view class="uni-btn-v uni-common-mt">
<button @tap="makePhoneCall" type="primary" :disabled="disabled">拨打</button>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'makePhoneCall',
disabled: true
}
},
methods: {
bindInput: function (e) {
this.inputValue = e.detail.value
if (this.inputValue.length > 0) {
this.disabled = false
} else {
this.disabled = true
}
},
makePhoneCall: function () {
uni.makePhoneCall({
phoneNumber: this.inputValue,
success: () => {
console.log("成功拨打电话")
}
})
}
}
}
</script>
<style>
.input {
height: 119rpx;
line-height: 119rpx;
font-size: 78rpx;
border-bottom: 1rpx solid #E2E2E2;
text-align:center;
}
</style>

View File

@ -0,0 +1,102 @@
<template>
<view class="content">
<map class="map" ref="dcmap" :markers="markers" @tap="selectPoint"></map>
<scroll-view class="scrollview" scroll-y="true">
<button class="button" @click="reverseGeocode">reverseGeocode</button>
<button class="button" @click="poiSearchNearBy">poiSearchNearBy</button>
</scroll-view>
</view>
</template>
<script>
// 116.397477,39.908692
let mapSearch = weex.requireModule('mapSearch')
export default {
data() {
return {
markers: [{
id: '1',
latitude: 39.9086920000,
longitude: 116.3974770000,
title: '天安门',
zIndex: '1',
iconPath: '/static/gps.png',
width: 20,
height: 20,
anchor: {
x: 0.5,
y: 1
},
callout: {
content: '首都北京\n天安门',
color: '#00BFFF',
fontSize: 12,
borderRadius: 2,
borderWidth: 0,
borderColor: '#333300',
bgColor: '#CCFF11',
padding: '1',
display: 'ALWAYS'
}
}]
}
},
methods: {
selectPoint(e) {
console.log(e);
},
reverseGeocode() {
var point = this.markers[0]
mapSearch.reverseGeocode({
point: {
latitude: point.latitude,
longitude: point.longitude
}
}, ret => {
console.log(JSON.stringify(ret));
uni.showModal({
content: JSON.stringify(ret)
})
})
},
poiSearchNearBy() {
var point = this.markers[0]
mapSearch.poiSearchNearBy({
point: {
latitude: point.latitude,
longitude: point.longitude
},
key: '停车场',
radius: 1000
}, ret => {
console.log(ret);
uni.showModal({
content: JSON.stringify(ret)
})
})
}
}
}
</script>
<style>
.content {
flex: 1;
}
.map {
width: 750rpx;
height: 500rpx;
background-color: black;
}
.scrollview {
flex: 1;
}
.button {
margin-top: 30rpx;
margin-bottom: 20rpx;
}
</style>

447
pages/API/map/map.nvue Normal file
View File

@ -0,0 +1,447 @@
<template>
<view class="content">
<map class="map" id="map1" ref="map1" :controls="controls" :scale="scale" :longitude="location.longitude"
:latitude="location.latitude" :show-location="showLocation" :enable-3D="enable3D" :rotate="rotate" :skew="skew"
:show-compass="showCompass" :enable-overlooking="enableOverlooking" :enable-zoom="enableZoom"
:enable-scroll="enableScroll" :enable-rotate="enableRotate" :enable-satellite="enableSatellite"
:enable-traffic="enableTraffic" :markers="markers" :polyline="polyline" :circles="circles" :polygons="polygons"
:include-points="includePoints" @tap="maptap" @controltap="oncontroltap" @markertap="onmarkertap"
@callouttap="oncallouttap" @poitap="onpoitap" @updated="onupdated" @regionchange="onregionchange"></map>
<scroll-view class="scrollview" scroll-y="true">
<!-- <view class="list-item">
<text class="list-text">显示3D楼块</text>
<switch :checked="enable3D" @change="enableThreeD" />
</view>
<view class="list-item">
<text class="list-text">显示指南针</text>
<switch :checked="showCompass" @change="changeShowCompass" />
</view>
<view class="list-item">
<text class="list-text">开启俯视</text>
<switch :checked="enableOverlooking" @change="changeEnableOverlooking" />
</view>
<view class="list-item">
<text class="list-text">是否支持缩放</text>
<switch :checked="enableZoom" @change="changeEnableZoom" />
</view>
<view class="list-item">
<text class="list-text">是否支持拖动</text>
<switch :checked="enableScroll" @change="changeEnableScroll" />
</view>
<view class="list-item">
<text class="list-text">是否支持旋转</text>
<switch :checked="enableRotate" @change="changeEnableRotate" />
</view>
<view class="list-item">
<text class="list-text">是否开启卫星图</text>
<switch :checked="enableSatellite" @change="changeEnableSatellite" />
</view>
<view class="list-item">
<text class="list-text">是否开启实时路况</text>
<switch :checked="enableTraffic" @change="changeEnableTraffic" />
</view> -->
<!-- #ifndef MP-JD -->
<button class="button" @click="changeScale">changeScale</button>
<button class="button" @click="changeRotate">changeRotate</button>
<button class="button" @click="changeSkew">skew</button>
<!-- #endif -->
<button class="button" @click="addMarkers">addMarkers</button>
<button class="button" @click="addPolyline">addPolyline</button>
<!-- #ifndef MP-JD -->
<button class="button" @click="addPolygons">addPolygons</button>
<!-- #endif -->
<button class="button" @click="addCircles">addCircles</button>
<button class="button" @click="includePoint">includePoints</button>
<button class="button" @click="handleGetCenterLocation">getCenterLocation</button>
<button class="button" @click="handleGetRegion">getRegion</button>
<!-- #ifndef MP-JD -->
<button class="button" @click="handleTranslateMarker">translateMarker</button>
<!-- #endif -->
</scroll-view>
</view>
</template>
<script>
const testMarkers = [{
id: 0,
latitude: 39.989631,
longitude: 116.481018,
title: '方恒国际 阜通东大街6号',
zIndex: '1',
rotate: 0,
width: 20,
height: 20,
anchor: {
x: 0.5,
y: 1
},
callout: {
content: '方恒国际 阜通东大街6号',
color: '#00BFFF',
fontSize: 10,
borderRadius: 4,
borderWidth: 1,
borderColor: '#333300',
bgColor: '#CCFF99',
padding: '5',
display: 'ALWAYS'
}
},
{
id: 1,
latitude: 39.9086920000,
longitude: 116.3974770000,
title: '天安门',
zIndex: '1',
iconPath: '/static/location.png',
width: 40,
height: 40,
anchor: {
x: 0.5,
y: 1
},
callout: {
content: '首都北京\n天安门',
color: '#00BFFF',
fontSize: 12,
borderRadius: 2,
borderWidth: 0,
borderColor: '#333300',
bgColor: '#CCFF11',
padding: '1',
display: 'ALWAYS'
}
}
];
const testPolyline = [{
points: [{
latitude: 39.925539,
longitude: 116.279037
},
{
latitude: 39.925539,
longitude: 116.520285
}
],
color: '#FFCCFF',
width: 7,
dottedLine: true,
arrowLine: true,
borderColor: '#000000',
borderWidth: 2
},
{
points: [{
latitude: 39.938698,
longitude: 116.275177
},
{
latitude: 39.966069,
longitude: 116.289253
},
{
latitude: 39.944226,
longitude: 116.306076
},
{
latitude: 39.966069,
longitude: 116.322899
},
{
latitude: 39.938698,
longitude: 116.336975
}
],
color: '#CCFFFF',
width: 5,
dottedLine: true,
arrowLine: true,
borderColor: '#CC0000',
borderWidth: 3
}
];
const testPolygons = [{
points: [{
latitude: 39.781892,
longitude: 116.293413
},
{
latitude: 39.787600,
longitude: 116.391842
},
{
latitude: 39.733187,
longitude: 116.417932
},
{
latitude: 39.704653,
longitude: 116.338255
}
],
fillColor: '#FFCCFF',
strokeWidth: 3,
strokeColor: '#CC99CC',
zIndex: 11
},
{
points: [{
latitude: 39.887600,
longitude: 116.518932
},
{
latitude: 39.781892,
longitude: 116.518932
},
{
latitude: 39.781892,
longitude: 116.428932
},
{
latitude: 39.887600,
longitude: 116.428932
}
],
fillColor: '#CCFFFF',
strokeWidth: 5,
strokeColor: '#CC0000',
zIndex: 3
}
];
const testCircles = [{
latitude: 39.996441,
longitude: 116.411146,
radius: 15000,
strokeWidth: 5,
color: '#CCFFFF',
fillColor: '#CC0000'
},
{
latitude: 40.096441,
longitude: 116.511146,
radius: 12000,
strokeWidth: 3,
color: '#CCFFFF',
fillColor: '#FFCCFF'
},
{
latitude: 39.896441,
longitude: 116.311146,
radius: 9000,
strokeWidth: 1,
color: '#CCFFFF',
fillColor: '#CC0000'
}
];
const testIncludePoints = [{
latitude: 39.989631,
longitude: 116.481018,
},
{
latitude: 39.9086920000,
longitude: 116.3974770000,
}
];
export default {
data() {
return {
location: {
longitude: 116.3974770000,
latitude: 39.9086920000
},
controls: [{
id: 1,
position: {
left: 5,
top: 180,
width: 30,
height: 30
},
iconPath: '/static/logo.png',
clickable: true
}],
showLocation: false,
scale: 13,
showCompass: true,
enable3D: true,
enableOverlooking: true,
enableZoom: true,
enableScroll: true,
enableRotate: true,
enableSatellite: false,
enableTraffic: false,
polyline: [],
markers: [],
polygons: [],
circles: [],
includePoints: [],
rotate: 0,
skew: 0
}
},
onLoad() {},
onReady() {
this.map = uni.createMapContext("map1", this);
},
methods: {
// #ifndef MP-JD
changeScale() {
this.scale = this.scale == 9 ? 15 : 9;
},
changeRotate() {
this.rotate = this.rotate == 90 ? 0 : 90;
},
changeSkew() {
this.skew = this.skew == 30 ? 0 : 30;
},
// #endif
enableThreeD(e) {
this.enable3D = e.detail.value;
},
changeShowCompass(e) {
this.showCompass = e.detail.value;
},
changeEnableOverlooking(e) {
this.enableOverlooking = e.detail.value;
},
changeEnableZoom(e) {
this.enableZoom = e.detail.value;
},
changeEnableScroll(e) {
this.enableScroll = e.detail.value;
},
changeEnableRotate(e) {
this.enableRotate = e.detail.value;
},
changeEnableSatellite(e) {
this.enableSatellite = e.detail.value;
},
changeEnableTraffic(e) {
this.enableTraffic = e.detail.value;
},
addMarkers() {
this.markers = testMarkers;
},
addPolyline() {
this.polyline = testPolyline;
},
// #ifndef MP-JD
addPolygons() {
this.polygons = testPolygons;
},
// #endif
addCircles() {
this.circles = testCircles;
},
includePoint() {
this.includePoints = testIncludePoints;
},
handleGetCenterLocation() {
this.map.getCenterLocation({
success: ret => {
console.log(JSON.stringify(ret));
uni.showModal({
content: JSON.stringify(ret)
})
}
})
},
handleGetRegion() {
this.map.getRegion({
success: ret => {
console.log(JSON.stringify(ret));
uni.showModal({
content: JSON.stringify(ret)
})
}
})
},
// #ifndef MP-JD
handleTranslateMarker() {
this.map.translateMarker({
markerId: 1,
destination: {
latitude: 39.989631,
longitude: 116.481018
},
duration: 2000
}, ret => {
console.log(JSON.stringify(ret));
uni.showModal({
content: JSON.stringify(ret)
})
});
},
// #endif
maptap(e) {
uni.showModal({
content: JSON.stringify(e)
})
},
onmarkertap(e) {
uni.showModal({
content: JSON.stringify(e)
})
},
oncontroltap(e) {
uni.showModal({
content: JSON.stringify(e)
})
},
oncallouttap(e) {
uni.showModal({
content: JSON.stringify(e)
})
},
onupdated(e) {
console.log(JSON.stringify(e))
},
onregionchange(e) {
console.log(JSON.stringify(e));
},
onpoitap(e) {
uni.showModal({
content: JSON.stringify(e)
})
}
}
}
</script>
<style>
.content {
flex: 1;
}
.map {
width: 750rpx;
/* #ifdef H5 */
width: 100%;
/* #endif */
height: 250px;
background-color: #f0f0f0;
}
.scrollview {
/* #ifdef H5 */
margin-top: 240px;
/* #endif */
flex: 1;
padding: 10px;
}
.list-item {
flex-direction: row;
flex-wrap: nowrap;
align-items: center;
padding: 5px 0px;
}
.list-text {
flex: 1;
}
.button {
margin-top: 5px;
margin-bottom: 5px;
}
</style>

40
pages/API/modal/modal.vue Normal file
View File

@ -0,0 +1,40 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap uni-common-mt">
<view class="uni-btn-v">
<button type="default" @tap="modalTap">有标题的modal</button>
<button type="default" @tap="noTitlemodalTap">无标题的modal</button>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'modal',
modalHidden: true,
modalHidden2: true
}
},
methods: {
modalTap: function (e) {
uni.showModal({
title: "弹窗标题",
content: "弹窗内容,告知当前状态、信息和解决方法,描述文字尽量控制在三行内",
showCancel: false,
confirmText: "确定"
})
},
noTitlemodalTap: function (e) {
uni.showModal({
content: "弹窗内容,告知当前状态、信息和解决方法,描述文字尽量控制在三行内",
confirmText: "确定",
cancelText: "取消"
})
}
}
}
</script>

View File

@ -0,0 +1,105 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap uni-common-mt">
<view class="uni-btn-v">
<button @tap="navigateTo">跳转新页面并传递数据</button>
<button @tap="navigateBack">返回上一页</button>
<button @tap="redirectTo">在当前页面打开</button>
<button @tap="switchTab">切换到模板选项卡</button>
<button v-if="!hasLeftWin" @tap="reLaunch">关闭所有页面打开首页</button>
<!-- #ifdef APP-PLUS -->
<button @tap="customAnimation">使用自定义动画打开页面</button>
<!-- #endif -->
<!-- #ifdef APP-PLUS || H5 -->
<button @tap="preloadPage">预载复杂页面</button>
<!-- #endif -->
<!-- #ifdef APP-PLUS -->
<button @tap="unPreloadPage">取消页面预载</button>
<!-- #endif -->
<!-- #ifdef APP-PLUS || H5 -->
<button @tap="navigateToPreloadPage">打开复杂页面</button>
<!-- #endif -->
</view>
</view>
</view>
</template>
<script>
const preloadPageUrl = '/pages/extUI/calendar/calendar'
import { mapState } from 'vuex'
export default {
data() {
return {
title: 'navigate'
}
},
computed: {
...mapState({
hasLeftWin: state => !state.noMatchLeftWindow
})
},
methods: {
navigateTo() {
uni.navigateTo({
url: 'new-page/new-vue-page-1?data=Hello'
})
},
navigateBack() {
uni.navigateBack();
},
redirectTo() {
uni.redirectTo({
url: 'new-page/new-vue-page-1'
});
},
switchTab() {
uni.switchTab({
url: '/pages/tabBar/template/template'
});
},
reLaunch() {
if (this.hasLeftWin) {
uni.reLaunch({
url: '/pages/component/view/view'
});
return;
}
uni.reLaunch({
url: '/pages/tabBar/component/component'
});
},
customAnimation(){
uni.navigateTo({
url: 'new-page/new-vue-page-1?data=使用自定义动画打开页面',
animationType: 'slide-in-bottom',
animationDuration: 200
})
},
preloadPage(){
uni.preloadPage({
url: preloadPageUrl,
success(){
uni.showToast({
title:'页面预载成功'
})
},
fail(){
uni.showToast({
title:'页面预载失败'
})
}
})
},
unPreloadPage(){
uni.unPreloadPage({
url: preloadPageUrl
})
},
navigateToPreloadPage(){
uni.navigateTo({
url: preloadPageUrl
})
}
}
}
</script>

View File

@ -0,0 +1,83 @@
<template>
<view class="root">
<view class="page-body">
<view class="new-page__color" @click="setColorIndex(colorIndex>1?0:colorIndex+1)" :style="{backgroundColor:currentColor}">
<text class="new-page__color-text">点击改变颜色</text>
</view>
<view class="new-page__text-box">
<text class="new-page__text">点击上方色块使用vuex在页面之间进行通讯</text>
</view>
<view class="new-page__button">
<button class="new-page__button-item" @click="navToNvue">跳转NVUE页面</button>
<button class="new-page__button-item" @click="navToVue">跳转VUE页面</button>
</view>
</view>
</view>
</template>
<script>
import {mapState,mapGetters,mapMutations} from 'vuex'
export default {
data() {
return {
}
},
computed:{
...mapState(['colorIndex','colorList']),
...mapGetters(['currentColor'])
},
methods:{
...mapMutations(['setColorIndex']),
navToNvue(){
uni.navigateTo({
url:'new-nvue-page-2'
})
},
navToVue(){
uni.navigateTo({
url:'new-vue-page-2'
})
}
}
}
</script>
<style>
.new-page__text {
font-size: 14px;
color: #666666;
}
.root{
flex-direction: column;
}
.page-body{
flex: 1;
flex-direction: column;
justify-content: flex-start;
align-items: center;
padding-top: 50px;
}
.new-page__text-box{
padding: 20px;
}
.new-page__color{
width: 200px;
height: 100px;
justify-content: center;
align-items: center;
}
.new-page__color-text{
font-size: 14px;
color: #FFFFFF;
line-height: 30px;
text-align: center;
}
.new-page__button-item{
margin-top: 15px;
width: 300px;
}
</style>

View File

@ -0,0 +1,69 @@
<template>
<view class="root">
<view class="page-body">
<view class="new-page__color" @click="setColorIndex(colorIndex>1?0:colorIndex+1)" :style="{backgroundColor:currentColor}">
<text class="new-page__color-text">点击改变颜色</text>
</view>
<view class="new-page__text-box">
<text class="new-page__text">点击上方色块使用vuex在页面之间进行通讯</text>
</view>
</view>
</view>
</template>
<script>
import {mapState,mapGetters,mapMutations} from 'vuex'
export default {
data() {
return {
}
},
computed:{
...mapState(['colorIndex','colorList']),
...mapGetters(['currentColor'])
},
methods:{
...mapMutations(['setColorIndex'])
}
}
</script>
<style>
.new-page__text {
font-size: 14px;
color: #666666;
}
.root{
flex-direction: column;
}
.page-body{
flex: 1;
flex-direction: column;
justify-content: flex-start;
align-items: center;
padding-top: 50px;
}
.new-page__text-box{
padding: 20px;
}
.new-page__color{
width: 200px;
height: 100px;
justify-content: center;
align-items: center;
}
.new-page__color-text{
font-size: 14px;
color: #FFFFFF;
line-height: 30px;
text-align: center;
}
.new-page__button-item{
margin-top: 15px;
width: 300px;
}
</style>

View File

@ -0,0 +1,108 @@
<template>
<view class="root">
<page-head :title="title"></page-head>
<view class="page-body">
<view class="new-page__text-box">
<text class="new-page__text">从上个页面接收到参数{{data}}</text>
</view>
<view class="new-page__color" @click="setColorIndex(colorIndex>1?0:colorIndex+1)" :style="{backgroundColor:currentColor}">
<text class="new-page__color-text">点击改变颜色</text>
</view>
<view class="new-page__text-box">
<text class="new-page__text">点击上方色块使用vuex在页面之间进行通讯</text>
</view>
<view class="new-page__button">
<!-- #ifndef VUE3-->
<button class="new-page__button-item" @click="navToNvue">跳转NVUE页面</button>
<!-- #endif -->
<button class="new-page__button-item" @click="navToVue">跳转VUE页面</button>
</view>
</view>
</view>
</template>
<script>
import {mapState,mapGetters,mapMutations} from 'vuex'
export default {
data() {
return {
title: '新页面',
data:""
}
},
computed:{
...mapState(['colorIndex','colorList']),
...mapGetters(['currentColor'])
},
onLoad(e){
if(e.data){
this.data = e.data;
}
uni.$on('postMsg',(res)=>{
uni.showModal({
content: `收到uni.$emit消息:${res.msg}`,
showCancel: false
})
})
},
onUnload() {
uni.$off('postMsg')
},
methods:{
...mapMutations(['setColorIndex']),
navToNvue(){
uni.navigateTo({
url:'new-nvue-page-1'
})
},
navToVue(){
uni.navigateTo({
url:'new-vue-page-2'
})
}
}
}
</script>
<style>
.new-page__text {
font-size: 14px;
color: #666666;
}
.root{
display: flex;
flex: 1;
flex-direction: column;
}
.page-body{
/* flex: 1; */
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
}
.new-page__text-box{
padding: 20px;
}
.new-page__color{
display: flex;
width: 200px;
height: 100px;
justify-content: center;
align-items: center;
}
.new-page__color-text{
font-size: 14px;
color: #FFFFFF;
line-height: 30px;
text-align: center;
}
.new-page__button-item{
margin-top: 15px;
width: 300px;
}
</style>

View File

@ -0,0 +1,84 @@
<template>
<view class="root">
<view class="page-body">
<view class="new-page__color" @click="setColorIndex(colorIndex>1?0:colorIndex+1)" :style="{backgroundColor:currentColor}">
<text class="new-page__color-text">点击改变颜色</text>
</view>
<view class="new-page__text-box">
<text class="new-page__text">点击上方色块使用vuex在页面之间进行通讯</text>
</view>
<view class="new-page__button">
<button class="new-page__button-item" @click="emitMsg">向上一页面传递数据</button>
</view>
</view>
</view>
</template>
<script>
import {
mapState,
mapGetters,
mapMutations
} from 'vuex'
export default {
data() {
return {}
},
computed: {
...mapState(['colorIndex', 'colorList']),
...mapGetters(['currentColor'])
},
methods: {
...mapMutations(['setColorIndex']),
emitMsg() {
uni.$emit('postMsg', {
msg: 'From: Vue Page'
})
}
}
}
</script>
<style>
.new-page__text {
font-size: 14px;
color: #666666;
}
.root {
display: flex;
flex: 1;
flex-direction: column;
}
.page-body {
flex: 1;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
padding-top: 50px;
}
.new-page__text-box {
padding: 20px;
}
.new-page__color {
display: flex;
width: 200px;
height: 100px;
justify-content: center;
align-items: center;
}
.new-page__color-text {
font-size: 14px;
color: #FFFFFF;
line-height: 30px;
text-align: center;
}
.new-page__button-item {
margin-top: 15px;
width: 300px;
}
</style>

View File

@ -0,0 +1,62 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap uni-common-mt">
<!-- #ifdef APP-PLUS -->
<view class="uni-btn-v">
<button class="shake" @tap="shake">摇一摇</button>
</view>
<!-- #endif -->
<view class="uni-btn-v">
<button type="primary" @tap="watchAcce">监听设备的加速度变化</button>
<button type="primary" @tap="stopAcce">停止监听设备的加速度变化</button>
</view>
<view class="uni-textarea uni-common-mt">
<textarea class="acc-show" :value="value" />
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'onAccelerometerChange',
value: ''
}
},
onUnload() {
uni.stopAccelerometer();
},
methods: {
//#ifdef APP-PLUS
shake() {
uni.navigateTo({
url: '/platforms/app-plus/shake/shake'
})
},
//#endif
watchAcce() {
uni.onAccelerometerChange((res) => {
this.value = "监听设备的加速度变化:\n" + "X轴" + res.x.toFixed(2) + "\nY轴" + res.y.toFixed(2) +
"\nZ轴" + res.z.toFixed(2);
})
},
stopAcce() {
uni.stopAccelerometer()
}
}
}
</script>
<style>
.shake {
background-color: #FFCC33;
color: #ffffff;
margin-bottom: 50rpx;
}
.uni-textarea .acc-show{
height: 240rpx;
}
</style>

View File

@ -0,0 +1,91 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap">
<view class="uni-hello-text uni-center" style="padding-bottom:50rpx;">
旋转手机即可获取方位信息
</view>
<view class="direction">
<view class="bg-compass-line"></view>
<image class="bg-compass" src="../../../static/compass.png" :style="'transform: rotate('+direction+'deg)'"></image>
<view class="direction-value">
<text>{{direction}}</text>
<text class="direction-degree">o</text>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'onCompassChange',
direction: 0
}
},
onReady: function () {
uni.onCompassChange((res) => {
this.direction = parseInt(res.direction)
})
},
onUnload() {
// #ifndef MP-ALIPAY
uni.stopCompass();
this.direction = 0;
// #endif
// #ifdef MP-ALIPAY
uni.offCompassChange();
// #endif
}
}
</script>
<style>
.direction {
position: relative;
margin-top: 70rpx;
display: flex;
width: 540rpx;
height: 540rpx;
align-items: center;
justify-content: center;
margin:0 auto;
}
.direction-value {
position: relative;
font-size: 200rpx;
color: #353535;
line-height: 1;
z-index: 1;
}
.direction-degree {
position: absolute;
top: 0;
right: -40rpx;
font-size: 60rpx;
}
.bg-compass {
position: absolute;
top: 0;
left: 0;
width: 540rpx;
height: 540rpx;
transition: .1s;
}
.bg-compass-line {
position: absolute;
left: 267rpx;
top: -10rpx;
width: 6rpx;
height: 56rpx;
background-color: #1AAD19;
border-radius: 999rpx;
z-index: 1;
}
</style>

View File

@ -0,0 +1,75 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-common-mt">
<form @submit="openLocation">
<view class="uni-list">
<view class="uni-list-cell">
<view class="uni-list-cell-left">
<view class="uni-label">经度</view>
</view>
<view class="uni-list-cell-db">
<input class="uni-input" type="text" :disabled="true" value="116.39747" name="longitude"/>
</view>
</view>
<view class="uni-list-cell">
<view class="uni-list-cell-left">
<view class="uni-label">纬度</view>
</view>
<view class="uni-list-cell-db">
<input class="uni-input" type="text" :disabled="true" value="39.9085" name="latitude"/>
</view>
</view>
<view class="uni-list-cell">
<view class="uni-list-cell-left">
<view class="uni-label">位置名称</view>
</view>
<view class="uni-list-cell-db">
<input class="uni-input" type="text" :disabled="true" value="天安门" name="name"/>
</view>
</view>
<view class="uni-list-cell">
<view class="uni-list-cell-left">
<view class="uni-label">详细位置</view>
</view>
<view class="uni-list-cell-db">
<input class="uni-input" type="text" :disabled="true" value="北京市东城区东长安街" name="address"/>
</view>
</view>
</view>
<view class="uni-padding-wrap">
<view class="uni-btn-v uni-common-mt">
<button type="primary" formType="submit">查看位置</button>
</view>
</view>
</form>
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'openLocation'
}
},
methods: {
openLocation: function (e) {
console.log(e)
var value = e.detail.value
uni.openLocation({
longitude: Number(value.longitude),
latitude: Number(value.latitude),
name: value.name,
address: value.address
})
}
}
}
</script>
<style>
.uni-list-cell-left {
padding: 0 30rpx;
}
</style>

View File

@ -0,0 +1,83 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap uni-common-mt">
<view style="font-size: 12px; color: #666;">PC 不支持下拉刷新</view>
<view class="text" v-for="(num,index) in data" :key="index">list - {{num}}</view>
<view class="uni-loadmore" v-if="showLoadMore">{{loadMoreText}}</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: '下拉刷新 + 加载更多',
data: [],
loadMoreText: "加载中...",
showLoadMore: false,
max: 0
}
},
onLoad() {
this.initData();
},
onUnload() {
this.max = 0,
this.data = [],
this.loadMoreText = "加载更多",
this.showLoadMore = false;
},
onReachBottom() {
console.log("onReachBottom");
if (this.max > 40) {
this.loadMoreText = "没有更多数据了!"
return;
}
this.showLoadMore = true;
setTimeout(() => {
this.setListData();
}, 300);
},
onPullDownRefresh() {
console.log('onPullDownRefresh');
this.initData();
},
methods: {
initData(){
setTimeout(() => {
this.max = 0;
this.data = [];
let data = [];
this.max += 20;
for (var i = this.max - 19; i < this.max + 1; i++) {
data.push(i)
}
this.data = this.data.concat(data);
uni.stopPullDownRefresh();
}, 300);
},
setListData() {
let data = [];
this.max += 10;
for (var i = this.max - 9; i < this.max + 1; i++) {
data.push(i)
}
this.data = this.data.concat(data);
}
}
}
</script>
<style>
.text {
margin: 16rpx 0;
width:100%;
background-color: #fff;
height: 120rpx;
line-height: 120rpx;
text-align: center;
color: #555;
border-radius: 8rpx;
}
</style>

View File

@ -0,0 +1,256 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap">
<view style="background:#FFF; padding:50rpx 0;">
<view class="uni-hello-text uni-center"><text>支付金额</text></view>
<view class="uni-h1 uni-center uni-common-mt">
<text class="rmbLogo"></text>
<input class="price" type="digit" :value="price" maxlength="4" @input="priceChange" />
</view>
</view>
<view class="uni-btn-v uni-common-mt">
<!-- #ifdef MP-WEIXIN -->
<button type="primary" @click="weixinPay" :loading="loading">微信支付</button>
<!-- #endif -->
<!-- #ifdef APP-PLUS -->
<template v-if="providerList.length > 0">
<button v-for="(item,index) in providerList" :key="index" @click="requestPayment(item,index)" :loading="item.loading">{{item.name}}支付</button>
</template>
<!-- #endif -->
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'request-payment',
loading: false,
price: 1,
providerList: []
}
},
onLoad: function() {
// #ifdef APP-PLUS
uni.getProvider({
service: "payment",
success: (e) => {
console.log("payment success:" + JSON.stringify(e));
let providerList = [];
e.provider.map((value) => {
switch (value) {
case 'alipay':
providerList.push({
name: '支付宝',
id: value,
loading: false
});
break;
case 'wxpay':
providerList.push({
name: '微信',
id: value,
loading: false
});
break;
default:
break;
}
})
this.providerList = providerList;
},
fail: (e) => {
console.log("获取支付通道失败:", e);
}
});
// #endif
},
methods: {
loginMpWeixin() {
return new Promise((resolve, reject) => {
uni.login({
provider: 'weixin',
success(res) {
console.warn('此处使用uni-id处理微信小程序登录详情参考: https://uniapp.dcloud.net.cn/uniCloud/uni-id')
uni.request({
url: 'https://97fca9f2-41f6-449f-a35e-3f135d4c3875.bspapp.com/http/user-center',
method: 'POST',
data: {
action: 'loginByWeixin',
params: {
code: res.code,
platform: 'mp-weixin'
}
},
success(res) {
if (res.data.code !== 0) {
reject(new Error('获取openid失败', res.result.msg))
return
}
uni.setStorageSync('openid', res.data.openid)
resolve(res.data.openid)
},
fail(err) {
reject(new Error('获取openid失败' + err))
}
})
},
fail(err) {
reject(err)
}
})
})
},
async weixinPay() {
let openid = uni.getStorageSync('openid')
console.log("发起支付");
this.loading = true;
if (!openid) {
try {
openid = await this.loginMpWeixin()
} catch (e) {
console.error(e)
}
if (!openid) {
uni.showModal({
content: '获取openid失败',
showCancel: false
})
this.loading = false
return
}
}
this.openid = openid
let orderInfo = await this.getOrderInfo('wxpay')
if (!orderInfo) {
uni.showModal({
content: '获取支付信息失败',
showCancel: false
})
return
}
uni.requestPayment({
...orderInfo,
success: (res) => {
uni.showToast({
title: "感谢您的赞助!"
})
},
fail: (res) => {
uni.showModal({
content: "支付失败,原因为: " + res
.errMsg,
showCancel: false
})
},
complete: () => {
this.loading = false;
}
})
},
async requestPayment(e, index) {
this.providerList[index].loading = true;
const provider = e.id
let orderInfo = await this.getOrderInfo(provider);
if (!orderInfo) {
uni.showModal({
content: '获取支付信息失败',
showCancel: false
})
return
}
console.log('--------orderInfo--------')
console.log(orderInfo);
uni.requestPayment({
provider,
orderInfo: orderInfo,
success: (e) => {
console.log("success", e);
uni.showToast({
title: "感谢您的赞助!"
})
},
fail: (e) => {
console.log("fail", e);
uni.showModal({
content: "支付失败,原因为: " + e.errMsg,
showCancel: false
})
},
complete: () => {
this.providerList[index].loading = false;
}
})
},
getOrderInfo(provider) {
return new Promise((resolve, reject) => {
if (!this.price) {
reject(new Error('请输入金额'))
}
console.warn('此处使用uni-pay处理支付详情参考: https://uniapp.dcloud.io/uniCloud/unipay')
uni.request({
method: 'POST',
url: 'https://97fca9f2-41f6-449f-a35e-3f135d4c3875.bspapp.com/http/pay',
data: {
provider,
openid: this.openid,
totalFee: Number(this.price) * 100, //
// #ifdef APP-PLUS
platform: 'app-plus',
// #endif
// #ifdef MP-WEIXIN
platform: 'mp-weixin',
// #endif
},
success(res) {
if (res.data.code === 0) {
resolve(res.data.orderInfo)
} else {
reject(new Error('获取支付信息失败' + res.data.msg))
}
},
fail(err) {
reject(new Error('请求支付接口失败' + err))
}
})
})
},
priceChange(e) {
console.log(e.detail.value)
this.price = e.detail.value;
}
}
}
</script>
<style>
.rmbLogo {
font-size: 40rpx;
}
button {
background-color: #007aff;
color: #ffffff;
}
.uni-h1.uni-center {
display: flex;
flex-direction: row;
justify-content: center;
align-items: flex-end;
}
.price {
border-bottom: 1px solid #eee;
width: 200rpx;
height: 80rpx;
padding-bottom: 4rpx;
}
.ipaPayBtn {
margin-top: 30rpx;
}
</style>

View File

@ -0,0 +1,176 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap uni-common-mt">
<view class="uni-hello-text">
请点击按钮向服务器发起请求
</view>
<view class="uni-textarea uni-common-mt">
<textarea :value="res"></textarea>
</view>
<view class="uni-btn-v uni-common-mt">
<button type="primary" @click="sendRequest" :loading="loading">发起请求Callback</button>
<button type="primary" @click="sendRequest('promise')" :loading="loading">发起请求Promise</button>
<button type="primary" @click="sendRequest('await')" :loading="loading">发起请求Async/Await</button>
</view>
</view>
</view>
</template>
<script>
const requestUrl = 'https://unidemo.dcloud.net.cn/ajax/echo/text?name=uni-app'
const duration = 2000
export default {
data() {
return {
title: 'request',
loading: false,
res: ''
}
},
methods: {
sendRequest(mode) {
this.loading = true;
switch (mode) {
case 'promise':
this._requestPromise();
break;
case 'await':
this._requestAwait();
break;
default:
this._request();
break;
}
},
_request() {
uni.request({
url: requestUrl,
dataType: 'text',
data: {
noncestr: Date.now()
},
success: (res) => {
console.log('request success', res)
uni.showToast({
title: '请求成功',
icon: 'success',
mask: true,
duration: duration
});
this.res = '请求结果 : ' + JSON.stringify(res);
},
fail: (err) => {
console.log('request fail', err);
uni.showModal({
content: err.errMsg,
showCancel: false
});
},
complete: () => {
this.loading = false;
}
});
},
_requestPromise() {
// #ifndef VUE3
uni.request({
url: requestUrl,
dataType: 'text',
data: {
noncestr: Date.now()
}
}).then(res => {
console.log('request success', res[1]);
uni.showToast({
title: '请求成功',
icon: 'success',
mask: true,
duration: duration
});
this.res = '请求结果 : ' + JSON.stringify(res[1]);
this.loading = false;
}).catch(err => {
console.log('request fail', err);
uni.showModal({
content: err.errMsg,
showCancel: false
});
this.loading = false;
});
// #endif
// #ifdef VUE3
uni.request({
url: requestUrl,
dataType: 'text',
data: {
noncestr: Date.now()
}
}).then(res => {
console.log('request success', res);
uni.showToast({
title: '请求成功',
icon: 'success',
mask: true,
duration: duration
});
this.res = '请求结果 : ' + JSON.stringify(res);
this.loading = false;
}).catch(err => {
console.log('request fail', err);
uni.showModal({
content: err.errMsg,
showCancel: false
});
this.loading = false;
});
// #endif
},
async _requestAwait() {
let res, err
// #ifndef VUE3
[err, res] = await uni.request({
url: requestUrl,
dataType: 'text',
data: {
noncestr: Date.now()
}
});
// #endif
// #ifdef VUE3
try {
res = await uni.request({
url: requestUrl,
dataType: 'text',
data: {
noncestr: Date.now()
}
});
} catch(e){
err=e
}
// #endif
if (err) {
console.log('request fail', err);
uni.showModal({
content: err.errMsg,
showCancel: false
});
} else {
console.log('request success', res)
uni.showToast({
title: '请求成功',
icon: 'success',
mask: true,
duration: duration
});
this.res = '请求结果 : ' + JSON.stringify(res);
}
this.loading = false;
}
}
}
</script>

View File

@ -0,0 +1,109 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap uni-common-mt">
<button v-if="!loadError" :loading="loading" :disabled="loading" type="primary" class="btn" @click="show">显示广告</button>
<button v-if="loadError" :loading="loading" :disabled="loading" type="primary" class="btn" @click="reloadAd">重新加载广告</button>
</view>
<!-- #ifndef APP-PLUS -->
<view class="ad-tips">
<text>小程序端的广告ID由小程序平台提供</text>
</view>
<!-- #endif -->
</view>
</template>
<script>
const ERROR_CODE = [-5001, -5002, -5003, -5004, -5005, -5006];
export default {
data() {
return {
title: '激励视频广告',
loading: false,
loadError: false
}
},
onReady() {
// #ifdef APP-PLUS
this.adOption = {
adpid: '1507000689'
};
// #endif
// #ifdef MP-WEIXIN
this.adOption = {
adUnitId: ''
};
// #endif
this.createAd();
},
methods: {
createAd() {
var rewardedVideoAd = this.rewardedVideoAd = uni.createRewardedVideoAd(this.adOption);
rewardedVideoAd.onLoad(() => {
this.loading = false;
this.loadError = false;
console.log('onLoad event')
});
rewardedVideoAd.onClose((res) => {
this.loading = true;
// 广
if (res && res.isEnded) {
//
console.log("onClose " + res.isEnded);
} else {
// 退
console.log("onClose " + res.isEnded);
}
setTimeout(() => {
uni.showToast({
title: "激励视频" + (res.isEnded ? "成功" : "未") + "播放完毕",
duration: 10000,
position: 'bottom'
})
}, 500)
});
rewardedVideoAd.onError((err) => {
this.loading = false;
if (err.code && ERROR_CODE.indexOf(err.code) !== -1) {
this.loadError = true;
}
console.log('onError event', err)
});
this.loading = true;
},
show() {
const rewardedVideoAd = this.rewardedVideoAd;
rewardedVideoAd.show().catch(() => {
rewardedVideoAd.load()
.then(() => rewardedVideoAd.show())
.catch(err => {
console.log('激励视频 广告显示失败', err)
uni.showToast({
title: err.errMsg || err.message,
duration: 5000,
position: 'bottom'
})
})
})
},
reloadAd() {
this.loading = true;
this.rewardedVideoAd.load();
}
}
}
</script>
<style>
.btn {
margin-bottom: 20px;
}
.ad-tips {
color: #999;
padding: 30px 0;
text-align: center;
}
</style>

View File

@ -0,0 +1,158 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap">
<view v-if="imagePath !== ''" class="media-box image">
<image class="image" mode="widthFix" :src="imagePath" />
</view>
<button type="primary" class="uni-button" @click="saveImage">拍摄图片并保存到本地</button>
<view v-if="videoPath !== ''" class="media-box">
<video
id="myVideo"
:src="videoPath"
@error="videoErrorCallback"
enable-danmu
danmu-btn
controls
></video>
</view>
<button type="primary" class="uni-button" @click="saveVideo">录制视频并保存到本地</button>
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'saveImage/saveVideo',
imagePath: '',
videoPath: ''
};
},
onLoad() {},
methods: {
videoErrorCallback: function() {
uni.showModal({
content: '视频加载失败',
showCancel: false
});
},
saveImage() {
uni.chooseImage({
count: 1,
sourceType: ['camera'],
success: res => {
this.imagePath = res.tempFilePaths[0];
this.getTempFilePath(res.tempFilePaths[0], 'imageTempPath');
},
fail: (err) => {
// #ifdef MP
uni.getSetting({
success: (res) => {
let authStatus = res.authSetting['scope.camera'];
if (!authStatus) {
uni.showModal({
title: '授权失败',
content: 'Hello uni-app需要从您的相机获取图片请在设置界面打开相关权限',
success: (res) => {
if (res.confirm) {
uni.openSetting()
}
}
})
}
}
})
// #endif
}
});
},
saveVideo() {
let _this = this;
uni.chooseVideo({
count: 1,
sourceType: ['camera'],
success: res => {
console.log(res.tempFilePath)
this.videoPath = res.tempFilePath;
this.getTempFilePath(res.tempFilePath, 'videoTempPath');
},
fail: (err) => {
// #ifdef MP
uni.getSetting({
success: (res) => {
let authStatus = res.authSetting['scope.camera'];
if (!authStatus) {
uni.showModal({
title: '授权失败',
content: 'Hello uni-app需要从您的相机获取视频请在设置界面打开相关权限',
success: (res) => {
if (res.confirm) {
uni.openSetting()
}
}
})
}
}
})
// #endif
}
});
},
getTempFilePath(url, types) {
//
let obj = {
filePath: url,
success: () => {
console.log('save success');
uni.showModal({
content: '保存成功',
showCancel: false
});
uni.hideLoading();
},
fail: e => {
uni.hideLoading();
uni.showModal({
content: '保存失败',
showCancel: false
});
}
};
uni.showLoading({
title: '保存中...'
});
if (types === 'videoTempPath') {
uni.saveVideoToPhotosAlbum(obj);
} else {
uni.saveImageToPhotosAlbum(obj);
}
}
}
};
</script>
<style>
.media-box {
display: flex;
justify-content: center;
align-items: center;
margin: 30rpx 0;
width: 100%;
}
.image {
height: 400rpx;
overflow: hidden;
}
.image image {
width: 100%;
height: 100%;
}
video {
width: 100%;
}
.uni-button {
margin: 30rpx 0;
}
</style>

View File

@ -0,0 +1,76 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap uni-common-mt">
<view class="uni-title">扫码结果</view>
<view class="uni-list" v-if="result">
<view class="uni-cell">
<view class="scan-result">
{{result}}
</view>
</view>
</view>
<view class="uni-btn-v">
<button type="primary" @click="scan">扫一扫</button>
</view>
</view>
</view>
</template>
<script>
import permision from "@/common/permission.js"
export default {
data() {
return {
title: 'scanCode',
result: ''
}
},
methods: {
async scan() {
// #ifdef APP-PLUS
let status = await this.checkPermission();
if (status !== 1) {
return;
}
// #endif
uni.scanCode({
success: (res) => {
this.result = res.result
},
fail: (err) => {
//
}
});
}
// #ifdef APP-PLUS
,
async checkPermission(code) {
let status = permision.isIOS ? await permision.requestIOS('camera') :
await permision.requestAndroid('android.permission.CAMERA');
if (status === null || status === 1) {
status = 1;
} else {
uni.showModal({
content: "需要相机权限",
confirmText: "设置",
success: function(res) {
if (res.confirm) {
permision.gotoAppSetting();
}
}
})
}
return status;
}
// #endif
}
}
</script>
<style>
.scan-result {
min-height: 50rpx;
line-height: 50rpx;
}
</style>

View File

@ -0,0 +1,22 @@
describe('pages/API/set-navigation-bar-title/set-navigation-bar-title.vue', () => {
let page
beforeAll(async () => {
// 重新reLaunch至首页并获取首页page对象其中 program 是uni-automator自动注入的全局对象
page = await program.reLaunch('/pages/API/set-navigation-bar-title/set-navigation-bar-title')
if (process.env.UNI_PLATFORM === "mp-weixin") {
await page.waitFor(10000)
} else {
await page.waitFor(5000)
}
page = await program.currentPage()
})
it('set-navigation-bar-title 组件标题', async () => {
let view = await page.$('.common-page-head-title')
expect(await view.text()).toBe('nav-default')
})
})

View File

@ -0,0 +1,44 @@
<template>
<view class="page">
<page-head :title="title"></page-head>
<view class="uni-padding-wrap">
<view class="uni-helllo-text">
本页标题栏是uni-app的默认配置开发者可在pages.json里配置文字内容及标题颜色也可通过api接口将其改变
</view>
<view class="uni-btn-v">
<button type="default" @click="setText">改变标题栏文字</button>
<button type="primary" @click="setBg">改变标题栏颜色</button>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'nav-default',
hasSetText:false,
hasSetBg:false
}
},
methods: {
setText() {
this.hasSetText = !this.hasSetText;
uni.setNavigationBarTitle({
title: this.hasSetText ? "Hello uni-app" : "默认导航栏"
})
},
setBg() {
this.hasSetBg = !this.hasSetBg;
uni.setNavigationBarColor({
frontColor: this.hasSetBg ? "#000000" : "#ffffff",
backgroundColor: this.hasSetBg ? "#F8F8F8" : "#007AFF"
})
}
}
}
</script>
<style>
</style>

293
pages/API/share/share.vue Normal file
View File

@ -0,0 +1,293 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap">
<view class="uni-title">分享内容</view>
<view class="uni-textarea">
<textarea class="textarea" v-model="shareText" />
</view>
<view class="uni-title">分享图片</view>
<view class="uni-uploader" style="padding:15rpx; background:#FFF;">
<view class="uni-uploader__input-box" v-if="!image" @tap="chooseImage"></view>
<image class="uni-uploader__img" v-if="image" :src="image"></image>
</view>
<!-- #ifdef APP-PLUS -->
<view class="uni-title">分享类型</view>
<view>
<radio-group @change="radioChange">
<label class="radio">
<radio value="1" checked="true"/>文字
</label>
<label class="radio">
<radio value="2" />图片
</label>
<label class="radio">
<radio value="0" />图文
</label>
<label class="radio">
<radio value="5" />小程序
</label>
</radio-group>
</view>
<view class="uni-btn-v uni-common-mt" v-if="providerList.length > 0">
<block v-for="(value,index) in providerList" :key="index">
<button type="primary" v-if="value" :disabled="isDisableButton(value)" @tap="share(value)">{{value.name}}</button>
</block>
</view>
<!-- #endif -->
<!-- #ifdef MP || QUICKAPP-WEBVIEW -->
<view class="uni-btn-v uni-common-mt">
<button type="primary" open-type="share">分享</button>
</view>
<!-- #endif -->
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'share',
shareText: 'uni-app可以同时发布成原生App、小程序、H5邀请你一起体验',
href:"https://uniapp.dcloud.io",
image: '',
shareType:1,
providerList: []
}
},
computed:{
isDisableButton() {
return function(item) {
if(this.shareType === 0 && item.id === 'qq'){
return true;
}
if(this.shareType === 5 && item.name !== '分享到微信好友'){
return true;
}
return false;
}
}
},
onShareAppMessage() {
return {
title: this.shareText ? this.shareText : "欢迎体验uni-app",
path: '/pages/tabBar/component/component',
imageUrl:this.image ? this.image : 'https://web-assets.dcloud.net.cn/unidoc/zh/share-logo@3.png'
}
},
onUnload:function(){
this.shareText='uni-app可以同时发布成原生App、小程序、H5邀请你一起体验',
this.href = 'https://uniapp.dcloud.io',
this.image='';
},
onLoad: function () {
uni.getProvider({
service: 'share',
success: (e) => {
console.log('success', e);
let data = []
for (let i = 0; i < e.provider.length; i++) {
switch (e.provider[i]) {
case 'weixin':
data.push({
name: '分享到微信好友',
id: 'weixin',
sort:0
})
data.push({
name: '分享到微信朋友圈',
id: 'weixin',
type:'WXSenceTimeline',
sort:1
})
break;
case 'sinaweibo':
data.push({
name: '分享到新浪微博',
id: 'sinaweibo',
sort:2
})
break;
case 'qq':
data.push({
name: '分享到QQ',
id: 'qq',
sort:3
})
break;
default:
break;
}
}
this.providerList = data.sort((x,y) => {
return x.sort - y.sort
});
},
fail: (e) => {
console.log('获取分享通道失败', e);
uni.showModal({
content:'获取分享通道失败',
showCancel:false
})
}
});
},
methods: {
async share(e) {
console.log('分享通道:'+ e.id +' 分享类型:' + this.shareType);
if(!this.shareText && (this.shareType === 1 || this.shareType === 0)){
uni.showModal({
content:'分享内容不能为空',
showCancel:false
})
return;
}
if(!this.image && (this.shareType === 2 || this.shareType === 0)){
uni.showModal({
content:'分享图片不能为空',
showCancel:false
})
return;
}
let shareOPtions = {
provider: e.id,
scene: e.type && e.type === 'WXSceneTimeline' ? 'WXSceneTimeline' : 'WXSceneSession', //WXSceneSessionWXSceneTimelineWXSceneFavorite
type: this.shareType,
success: (e) => {
console.log('success', e);
uni.showModal({
content: '已分享',
showCancel:false
})
},
fail: (e) => {
console.log('fail', e)
uni.showModal({
content: e.errMsg,
showCancel:false
})
},
complete:function(){
console.log('分享操作结束!')
}
}
switch (this.shareType){
case 0:
shareOPtions.summary = this.shareText;
shareOPtions.imageUrl = this.image;
shareOPtions.title = '欢迎体验uniapp';
shareOPtions.href = 'https://uniapp.dcloud.io';
break;
case 1:
shareOPtions.summary = this.shareText;
break;
case 2:
shareOPtions.imageUrl = this.image;
break;
case 5:
shareOPtions.imageUrl = this.image ? this.image : 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/b6304f00-5168-11eb-bd01-97bc1429a9ff.png'
shareOPtions.title = '欢迎体验uniapp';
shareOPtions.miniProgram = {
id:'gh_33446d7f7a26',
path:'/pages/tabBar/component/component',
webUrl:'https://uniapp.dcloud.io',
type:0
};
break;
default:
break;
}
if(shareOPtions.type === 0 && plus.os.name === 'iOS'){//ios
shareOPtions.imageUrl = await this.compress();
}
if(shareOPtions.type === 1 && shareOPtions.provider === 'qq'){//qqhreftitle
shareOPtions.href = 'https://uniapp.dcloud.io';
shareOPtions.title = '欢迎体验uniapp';
}
uni.share(shareOPtions);
},
radioChange(e){
console.log('type:' + e.detail.value);
this.shareType = parseInt(e.detail.value);
},
chooseImage() {
uni.chooseImage({
count: 1,
sourceType: ['album', 'camera'],
sizeType: ['compressed', 'original'],
success: (res) => {
this.image = res.tempFilePaths[0];
},
fail: (err) => {
// #ifdef MP
uni.getSetting({
success: (res) => {
let authStatus = res.authSetting['scope.album'] && res.authSetting['scope.camera'];
if (!authStatus) {
uni.showModal({
title: '授权失败',
content: 'Hello uni-app需要从您的相机或相册获取图片请在设置界面打开相关权限',
success: (res) => {
if (res.confirm) {
uni.openSetting()
}
}
})
}
}
})
// #endif
}
})
},
compress(){// 20Kb
console.log('开始压缩');
let img = this.image;
return new Promise((res) => {
var localPath = plus.io.convertAbsoluteFileSystem(img.replace('file://', ''));
console.log('after' + localPath);
// size
plus.io.resolveLocalFileSystemURL(localPath, (entry) => {
entry.file((file) => {// entry
console.log('getFile:' + JSON.stringify(file));
if(file.size > 20480) {// size 20Kb
plus.zip.compressImage({
src: img,
dst: img.replace('.jpg', '2222.jpg').replace('.JPG', '2222.JPG'),
width: '10%',
height: '10%',
quality: 1,
overwrite: true
}, (event) => {
console.log('success zip****' + event.size);
let newImg = img.replace('.jpg', '2222.jpg').replace('.JPG', '2222.JPG');
res(newImg);
}, function(error) {
uni.showModal({
content:'分享图片太大,需要请重新选择图片!',
showCancel:false
})
});
}
});
}, (e) => {
console.log('Resolve file URL failed: ' + e.message);
uni.showModal({
content:'分享图片太大,需要请重新选择图片!',
showCancel:false
})
});
})
}
}
}
</script>
<style>
</style>

View File

@ -0,0 +1,49 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap">
<view class="uni-btn-v">
<button class="btn-load" type="primary" @click="showLoading">显示 loading 提示框</button>
<!-- #ifndef MP-ALIPAY -->
<button @click="hideLoading">隐藏 loading 提示框</button>
<!-- #endif -->
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'loading'
}
},
methods: {
showLoading: function() {
uni.showLoading({
title: 'loading'
});
// #ifdef MP-ALIPAY
this._showTimer && clearTimeout(this._showTimer);
this._showTimer = setTimeout(() => {
this.hideLoading();
}, 3000)
// #endif
},
hideLoading: function() {
uni.hideLoading();
}
}
// #ifdef MP-ALIPAY
,
onUnload() {
this._showTimer && clearTimeout(this._showTimer);
}
// #endif
}
</script>
<style>
</style>

141
pages/API/soter/soter.vue Normal file
View File

@ -0,0 +1,141 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap uni-common-mt">
<view class="uni-btn-v">
<button type="primary" @click="checkIsSupportSoterAuthentication">检查支持的认证方式</button>
<button type="primary" @click="checkIsSoterEnrolledInDeviceFingerPrint">检查是否录入指纹</button>
<button type="primary" @click="checkIsSoterEnrolledInDeviceFaceID">检查是否录入FaceID</button>
<button type="primary" @click="startSoterAuthenticationFingerPrint">开始指纹认证</button>
<button type="primary" @click="startSoterAuthenticationFaceID">开始FaceID认证</button>
</view>
<view style="width: 100%;text-align: center;">{{ result }}</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: '生物认证',
result: ''
};
},
onLoad() {
},
methods: {
checkIsSupportSoterAuthentication() {
uni.checkIsSupportSoterAuthentication({
success(res) {
uni.showModal({
content: '支持的认证方式:' + res.supportMode,
showCancel: false
})
console.log(res);
},
fail(err) {
console.log(err);
}
})
},
checkIsSoterEnrolledInDeviceFingerPrint() {
uni.checkIsSoterEnrolledInDevice({
checkAuthMode: 'fingerPrint',
success(res) {
if(res.isEnrolled) {
uni.showToast({
icon: 'none',
title: '已录入指纹'
})
}else {
uni.showModal({
content: '未录入指纹',
showCancel: false
})
}
console.log(res);
},
fail(err) {
uni.showModal({
content: '未录入指纹',
showCancel: false
})
console.log(err);
}
})
},
checkIsSoterEnrolledInDeviceFaceID() {
uni.checkIsSoterEnrolledInDevice({
checkAuthMode: 'facial',
success(res) {
if(res.isEnrolled) {
uni.showToast({
icon: 'none',
title: '已录入FaceID'
})
}else {
uni.showModal({
content: '未录入FaceID',
showCancel: false
})
}
console.log(res);
},
fail(err) {
uni.showModal({
content: '未录入FaceID',
showCancel: false
})
console.log(err);
}
})
},
startSoterAuthenticationFingerPrint() {
uni.startSoterAuthentication({
requestAuthModes: ['fingerPrint'],
challenge: '123456',
authContent: '请用指纹解锁',
success(res) {
uni.showToast({
icon: 'none',
title: '指纹验证成功'
})
console.log(res);
},
fail(err) {
uni.showModal({
content: '指纹验证失败errCode' + err.errCode,
showCancel: false
})
console.log(err);
}
})
},
startSoterAuthenticationFaceID() {
uni.startSoterAuthentication({
requestAuthModes: ['facial'],
challenge: '123456',
authContent: '请用FaceID解锁',
success(res) {
uni.showToast({
icon: 'none',
title: 'FaceID验证成功'
})
console.log(res);
},
fail(err) {
uni.showModal({
content: 'FaceID验证失败errCode' + err.errCode,
showCancel: false
})
console.log(err);
}
})
}
}
};
</script>
<style></style>

120
pages/API/sqlite/sqlite.vue Normal file
View File

@ -0,0 +1,120 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap uni-common-mt">
<view class="uni-btn-v"><button type="primary" @click="openDB">打开数据库test.db</button></view>
<view class="uni-btn-v"><button type="primary" @click="executeSQL">创建表database及插入数据</button></view>
<view class="uni-btn-v"><button type="primary" @click="selectSQL">查询表database的数据</button></view>
<view class="uni-btn-v"><button type="primary" @click="droptable">删除表database</button></view>
<view class="uni-btn-v"><button type="primary" @click="closeDB">关闭数据库test.db</button></view>
<view class="uni-btn-v"><button type="primary" @click="isOpenDB">查询是否打开数据库</button></view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'SQLite'
};
},
methods: {
openDB: function() {
plus.sqlite.openDatabase({
name: 'first',
path: '_doc/test.db',
success: function(e) {
plus.nativeUI.alert('打开数据库test.db成功 ');
},
fail: function(e) {
plus.nativeUI.alert('打开数据库test.db失败: ' + JSON.stringify(e));
}
});
},
// SQL
executeSQL: function() {
plus.sqlite.executeSql({
name: 'first',
sql: 'create table if not exists database("name" CHAR(110),"sex" CHAR(10),"age" INT(11))',
success: function(e) {
plus.sqlite.executeSql({
name: 'first',
sql: "insert into database values('彦','女','7000')",
success: function(e) {
plus.nativeUI.alert('创建表table和插入数据成功');
},
fail: function(e) {
plus.nativeUI.alert('创建表table成功但插入数据失败: ' + JSON.stringify(e));
}
});
},
fail: function(e) {
plus.nativeUI.alert('创建表table失败: ' + JSON.stringify(e));
}
});
},
// SQL
selectSQL: function() {
plus.sqlite.selectSql({
name: 'first',
sql: 'select * from database',
success: function(e) {
plus.nativeUI.alert('查询SQL语句成功: ' + JSON.stringify(e));
},
fail: function(e) {
plus.nativeUI.alert('查询SQL语句失败: ' + JSON.stringify(e));
}
});
},
//
droptable: function() {
plus.sqlite.executeSql({
name: 'first',
sql: 'drop table database',
success: function(e) {
plus.nativeUI.alert('删除表database成功');
},
fail: function(e) {
plus.nativeUI.alert('删除表database失败: ' + JSON.stringify(e));
}
});
},
//
closeDB: function() {
plus.sqlite.closeDatabase({
name: 'first',
success: function(e) {
plus.nativeUI.alert('关闭数据库成功');
},
fail: function(e) {
plus.nativeUI.alert('关闭数据库失败: ' + JSON.stringify(e));
}
});
},
isOpenDB: function() {
if (
plus.sqlite.isOpenDatabase({
name: 'first',
path: '_doc/test.db'
})
) {
plus.nativeUI.alert('Opened!');
} else {
plus.nativeUI.alert('Unopened!');
}
}
}
};
</script>
<style>
.uni-btn-v {
margin: 20rpx 0;
padding: 0;
}
</style>

View File

@ -0,0 +1,131 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-common-mt">
<view class="uni-list">
<view class="uni-list-cell">
<view class="uni-list-cell-left">
<view class="uni-label">key</view>
</view>
<view class="uni-list-cell-db">
<input class="uni-input" type="text" placeholder="请输入key" name="key" :value="key" @input="keyChange"/>
</view>
</view>
<view class="uni-list-cell">
<view class="uni-list-cell-left">
<view class="uni-label">value</view>
</view>
<view class="uni-list-cell-db">
<input class="uni-input" type="text" placeholder="请输入value" name="data" :value="data" @input="dataChange"/>
</view>
</view>
</view>
<view class="uni-padding-wrap">
<view class="uni-btn-v">
<button type="primary" class="btn-setstorage" @tap="setStorage">存储数据</button>
<button @tap="getStorage">读取数据</button>
<button @tap="clearStorage">清理数据</button>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'get/set/clearStorage',
key: '',
data: ''
}
},
methods: {
keyChange: function (e) {
this.key = e.detail.value
},
dataChange: function (e) {
this.data = e.detail.value
},
getStorage: function () {
var key = this.key,
data = this.data;
if (key.length === 0) {
uni.showModal({
title: '读取数据失败',
content: "key 不能为空",
showCancel:false
})
} else {
uni.getStorage({
key: key,
success: (res) => {
uni.showModal({
title: '读取数据成功',
content: "data: '" + res.data + "'",
showCancel:false
})
},
fail: () => {
uni.showModal({
title: '读取数据失败',
content: "找不到 key 对应的数据",
showCancel:false
})
}
})
}
},
setStorage: function () {
var key = this.key
var data = this.data
if (key.length === 0) {
uni.showModal({
title: '保存数据失败',
content: 'key 不能为空',
showCancel:false
})
} else {
uni.setStorage({
key: key,
data: data,
success: (res) => {
uni.showModal({
title: '存储数据成功',
// #ifndef MP-ALIPAY
content: JSON.stringify(res.errMsg),
// #endif
// #ifdef MP-ALIPAY
content: data,
// #endif
showCancel:false
})
},
fail: () => {
uni.showModal({
title: '储存数据失败!',
showCancel:false
})
}
})
}
},
clearStorage: function () {
uni.clearStorageSync()
this.key = '',
this.data = ''
uni.showModal({
title: '清除数据成功',
content: ' ',
showCancel:false
})
}
}
}
</script>
<style>
.btn-setstorage {
background-color: #007aff;
color: #ffffff;
}
</style>

View File

@ -0,0 +1,137 @@
<template>
<view class="content">
<page-head :title="title"></page-head>
<view class="example">
<view class="example-title">从左侧滑出</view>
<button @click="showDrawer">显示抽屉</button>
</view>
<view class="example">
<view class="example-title">从上侧竖向滑出</view>
<button @click="showPopup">显示 弹出层</button>
</view>
<view style="width: 100%;">
<video v-if="showVideo" id="video"
@play="playVideo"
@pause="closeMask"
:controls="false"
src="https://img.cdn.aliyun.dcloud.net.cn/guide/uniapp/%E7%AC%AC1%E8%AE%B2%EF%BC%88uni-app%E4%BA%A7%E5%93%81%E4%BB%8B%E7%BB%8D%EF%BC%89-%20DCloud%E5%AE%98%E6%96%B9%E8%A7%86%E9%A2%91%E6%95%99%E7%A8%8B@20181126-lite.m4v"
@error="videoErrorCallback" poster="https://web-assets.dcloud.net.cn/unidoc/zh/poster.png"></video>
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'SubNvue',
showVideo: false
};
},
onLoad() {
this.closeMask();
// popup
uni.$on('popup-page', (data) => {
switch(data.type){
case 'interactive':
uni.showModal({
title: '来自Popup的消息',
content: data.info
})
break;
default:
uni.showToast({
title: data.title,
})
break;
}
})
// drawer
uni.$on('drawer-page', (data) => {
uni.showToast({
title: '点击了第' + data + '项',
icon:"none"
});
})
},
onUnload() {
uni.$off('popup-page')
uni.$off('drawer-page')
},
onReady() {
this.showVideo = true
},
methods: {
showDrawer() {
uni.getSubNVueById('drawer').show('slide-in-left', 200);
},
showPopup() {
// popup
uni.$emit('page-popup', {
title: '请阅读软件内容',
content: 'uni-app 是一个使用 Vue.js 开发跨平台应用的前端框架开发者编写一套代码可编译到iOS、Android、H5、小程序等多个平台。'
});
const subNVue = uni.getSubNVueById('popup')
subNVue.show('slide-in-top', 250)
},
videoErrorCallback: function() {
uni.showModal({
content: '视频加载失败',
showCancel: false
})
},
playVideo() {
let subNVue = uni.getSubNVueById('video_mask')
subNVue.show('fade-in', 200, () => {
uni.$emit('play-video', {
status: 'open',
})
})
},
closeMask() {
let subNVue = uni.getSubNVueById('video_mask')
uni.$emit('close-video', {
status: 'close',
})
subNVue.hide('fade-out', 200)
},
}
}
</script>
<style>
.content {
align-content: center;
height: 100%;
background-color: #F4F5F6;
}
.example {
padding: 0 10px 10px
}
.example-title {
font-size: 14px;
line-height: 14px;
color: #777;
margin: 40px 2rpx;
position: relative
}
video {
position: absolute;
bottom: 30px;
left: 0;
width: 100%;
height: 200px;
}
.example .example-title {
margin: 40rpx 0
}
button {
background-color: #f8f8f8;
}
.title {
font-size: 20px;
text-align: center;
color: #8f8f94;
}
</style>

View File

@ -0,0 +1,103 @@
<template>
<div class="wrapper">
<text class="nav-text">左侧列表</text>
<list class="list-wrapper">
<cell v-for="item in lists" :key="item.id">
<div class="text-wrapper" @click="clickitem(item.id)">
<text style="font-size: 30rpx; ">{{item.name}}</text>
<text class="icon">&#xe583;</text>
</div>
</cell>
</list>
<div style="flex: 1; text-align: center;">
<div class="close-drawer" @click="hideDrawer">
<text style="font-size: 34rpx; text-align: center;">关闭抽屉</text>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
lists: [],
}
},
beforeCreate() {
const domModule = weex.requireModule('dom')
domModule.addRule('fontFace', {
fontFamily: "unibtn",
'src': "url('../../../../static/uni.ttf')"
});
},
created() {
for(let i = 0; i < 5; i++){
this.lists.push({
id: i,
name: 'Item' + i,
});
}
},
methods: {
hideDrawer() {
uni.getCurrentSubNVue().hide('auto')
},
clickitem(e) {
uni.$emit('drawer-page', e);
}
}
}
</script>
<style>
.wrapper {
flex-direction: column;
flex: 1;
text-align: center;
padding: 60rpx 0rpx 0rpx 20rpx;
background-color: #F4F5F6;
}
.nav-text {
color: #8f8f94;
/* #ifndef APP-PLUS-NVUE */
margin-bottom: 40px;
/* #endif */
/* #ifdef APP-PLUS-NVUE */
margin-bottom: 40rpx;
/* #endif */
}
.list-wrapper {
/* #ifdef APP-PLUS-NVUE */
height: 450rpx;
/* #endif */
/* #ifndef APP-PLUS-NVUE */
height: 450px;
/* #endif */
}
.text-wrapper {
justify-content: center;
border-bottom-style: solid;
border-bottom-width: 1rpx;
border-bottom-color: rgba(0,0,0,.2);
margin-bottom: 35rpx;
padding-bottom: 15rpx;
}
.close-drawer {
background-color: #f8f8f8;
width: 300rpx;
padding: 15rpx;
border-radius: 20rpx;
border-style: solid;
border-width: 1rpx;
border-color: rgba(0,0,0,.2);
}
.icon {
position: absolute;
right: 10rpx;
color: #000000;
font-family: unibtn;
font-size: 30rpx;
font-weight: 400;
}
</style>

View File

@ -0,0 +1,121 @@
<template>
<div class="wrapper">
<text class="title">{{title}}</text>
<scroller class="scroller">
<div>
<text class="content">{{content}}</text>
</div>
<div>
<text style="color: red; font-size: 30rpx;">以下为 Popup 内部滚动示例:</text>
</div>
<div class="cell" v-for="(item, index) in lists" @click="handle(item)" :key="index">
<text class="text">{{item}}</text>
</div>
</scroller>
<div class="message-wrapper">
<text class="send-message" @click="sendMessage">向页面发送消息</text>
</div>
</div>
</template>
<script>
export default {
data() {
return {
title: '',
content: '',
lists: [],
}
},
created() {
const vm = this;
for (let i = 1; i < 20; i++) {
this.lists.push('item' + i);
}
uni.$on('page-popup', (data) => {
vm.title = data.title;
vm.content = data.content;
})
},
beforeDestroy() {
uni.$off('drawer-page')
},
methods: {
sendMessage() {
const subNVue = uni.getCurrentSubNVue()
uni.$emit('popup-page', {
title: '已读完!',
})
},
handle(item, index) {
const subNVue = uni.getCurrentSubNVue()
uni.$emit('popup-page', {
type: 'interactive',
info: item + ' 该元素被点击了!',
})
}
}
}
</script>
<style>
.wrapper {
flex-direction: column;
justify-content: space-between;
padding: 10rpx 15rpx;
background-color: #F4F5F6;
border-radius: 4rpx;
}
.title {
height: 100rpx;
line-height: 100rpx;
border-bottom-style: solid;
border-bottom-width: 1rpx;
border-bottom-color: #CBCBCB;
flex: 0;
font-size: 30rpx;
}
.scroller {
height: 400rpx;
padding: 8rpx 15rpx;
}
.content {
color: #555555;
font-size: 32rpx;
}
.message-wrapper {
flex: 0;
border-top-style: solid;
border-top-width: 1rpx;
border-top-color: #CBCBCB;
height: 80rpx;
align-items: flex-end;
}
.send-message {
font-size: 30rpx;
line-height: 80rpx;
color: #00CE47;
margin-left: 20rpx;
}
.cell {
margin: 10rpx;
padding: 20rpx 0;
top: 10rpx;
align-items: center;
justify-content: center;
border-radius: 10rpx;
background-color: #5989B9;
}
.text {
font-size: 30rpx;
text-align: center;
color: white;
}
</style>

View File

@ -0,0 +1,114 @@
<template>
<div class="wrapper">
<list class="list">
<cell v-for="(item, index) in lists" :key="index" :ref="'item' + index" class="cell">
<text class="name">{{item.name}}:</text>
<text class="content">{{item.content}}</text>
</cell>
</list>
</div>
</template>
<script>
export default {
data() {
return {
lists: [],
interval: null,
yourTexts: [
{
name: '学员A',
content: '老师讲的真好',
}, {
name: '学员B',
content: 'uni-app值得学习',
}, {
name: '学员C',
content: '老师,还有实战例子吗?',
}, {
name: '学员D',
content: '老师请问是不是要先学会vue才能学uni-app',
}, {
name: '学员E',
content: '受教了uni-app太牛了',
}
],
}
},
created() {
const vm = this;
uni.$on('play-video', (data) => {
if(data.status === 'open'){
this.addItem();
}else{
this.closeItem();
}
})
},
beforeDestroy(){
uni.$off('play-video')
this.closeItem()
},
methods: {
addItem() {
const vm = this;
vm.lists = [{
name: '学员E',
content: '受教了uni-app太牛了',
}];
const dom = weex.requireModule('dom')
vm.interval = setInterval(() => {
if(vm.lists.length > 15) {
vm.lists.unshift();
}
vm.lists.push({
name: vm.yourTexts[vm.lists.length%4].name,
content: vm.yourTexts[vm.lists.length%4].content
});
if(vm.lists.length > 5) {
vm.$nextTick(() => {
if(vm.$refs['item' + (vm.lists.length - 1)]){
dom.scrollToElement(vm.$refs['item' + (vm.lists.length - 1)][0]);
}
});
}
}, 3500);
},
closeItem() {
if(this.interval) clearInterval(this.interval);
}
}
}
</script>
<style>
.wrapper {
position: relative;
flex: 1;
background-color: transparent;
}
.list {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.7);
}
.cell {
padding: 10rpx 0;
flex-direction: row;
flex-wrap: nowrap;
}
.name {
flex: 0;
font-size: 20rpx;
margin-right: 20rpx;
color: #FF5A5F;
}
.content {
flex: 1;
font-size: 20rpx;
color: #F4F5F6;
}
</style>

79
pages/API/toast/toast.vue Normal file
View File

@ -0,0 +1,79 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap">
<view class="uni-btn-v">
<button type="default" @tap="toast1Tap">点击弹出默认toast</button>
<button type="default" @tap="toast2Tap">点击弹出设置duration的toast</button>
<button type="default" @tap="toast3Tap">点击弹出显示loading的toast</button>
<!-- #ifndef MP-ALIPAY -->
<button type="default" @tap="toast4Tap">点击弹出显示自定义图片的toast</button>
<!-- #endif -->
<!-- #ifdef APP-PLUS -->
<button type="default" @tap="toast5Tap">点击显示无图标的居底toast</button>
<!-- #endif -->
<button type="default" @tap="hideToast">点击隐藏toast</button>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'toast'
}
},
// #ifdef MP-ALIPAY
onUnload() {
this._showTimer && clearTimeout(this._showTimer);
},
// #endif
methods: {
toast1Tap: function () {
uni.showToast({
title: "默认"
})
},
toast2Tap: function () {
uni.showToast({
title: "duration 3000",
duration: 3000
})
},
toast3Tap: function () {
uni.showToast({
title: "loading",
icon: "loading",
duration: 5000
})
// #ifdef MP-ALIPAY
this._showTimer = setTimeout(() => {
// icon loading showToast showLoading
my.hideLoading()
//
clearTimeout(this._showTimer);
}, 3000)
// #endif
},
toast4Tap: function () {
uni.showToast({
title: "logo",
image: "../../../static/uni.png"
})
},
// #ifdef APP-PLUS
toast5Tap: function () {
uni.showToast({
title: "显示一段轻提示",
position:'bottom'
})
},
// #endif
hideToast: function () {
uni.hideToast()
}
}
}
</script>

View File

@ -0,0 +1,95 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap uni-common-mt">
<view class="demo">
<block v-if="imageSrc">
<image :src="imageSrc" class="image" mode="widthFix"></image>
</block>
<block v-else>
<view class="uni-hello-addfile" @click="chooseImage">+ 选择图片</view>
</block>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'uploadFile',
imageSrc: ''
}
},
onUnload() {
this.imageSrc = '';
},
methods: {
chooseImage: function() {
uni.chooseImage({
count: 1,
sizeType: ['compressed'],
sourceType: ['album'],
success: (res) => {
console.log('chooseImage success, temp path is', res.tempFilePaths[0])
var imageSrc = res.tempFilePaths[0]
uni.uploadFile({
url: 'https://unidemo.dcloud.net.cn/upload',
filePath: imageSrc,
fileType: 'image',
name: 'data',
success: (res) => {
console.log('uploadImage success, res is:', res)
uni.showToast({
title: '上传成功',
icon: 'success',
duration: 1000
})
this.imageSrc = imageSrc
},
fail: (err) => {
console.log('uploadImage fail', err);
uni.showModal({
content: err.errMsg,
showCancel: false
});
}
});
},
fail: (err) => {
console.log('chooseImage fail', err)
// #ifdef MP
uni.getSetting({
success: (res) => {
let authStatus = res.authSetting['scope.album'];
if (!authStatus) {
uni.showModal({
title: '授权失败',
content: 'Hello uni-app需要从您的相册获取图片请在设置界面打开相关权限',
success: (res) => {
if (res.confirm) {
uni.openSetting()
}
}
})
}
}
})
// #endif
}
})
}
}
}
</script>
<style>
.image {
width: 100%;
}
.demo {
background: #FFF;
padding: 50rpx;
}
</style>

View File

@ -0,0 +1,59 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap">
<button class="uni-button" type="primary" @click="longshock">长震动</button>
<button class="uni-button" @click="shortshock">短震动</button>
<view class="uni-tips">
<view>Tips</view>
<view class="uni-tips-text">iOS上只有长震动没有短震动</view>
<view class="uni-tips-text">iOS上需要手机设置打开响铃时震动静音时震动否则无法震动</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'vibrateLong/vibrateShort'
};
},
onLoad() {},
methods: {
longshock() {
uni.vibrateLong({
success: function() {
console.log('success');
}
});
},
shortshock() {
uni.vibrateShort({
success: function() {
console.log('success');
}
});
}
}
};
</script>
<style>
.uni-padding-wrap {
margin-top: 50rpx 0;
}
.uni-button {
margin: 30rpx 0;
}
.uni-tips {
color: #666;
font-size: 30rpx;
}
.uni-tips-text {
margin-top: 15rpx;
line-height: 1.2;
font-size: 24rpx;
}
</style>

134
pages/API/video/video.vue Normal file
View File

@ -0,0 +1,134 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-common-mt">
<view class="uni-list">
<view class="uni-list-cell">
<view class="uni-list-cell-left">
<view class="uni-label">视频来源</view>
</view>
<view class="uni-list-cell-right">
<picker :range="sourceType" @change="sourceTypeChange" :value="sourceTypeIndex">
<view class="uni-input">{{sourceType[sourceTypeIndex]}}</view>
</picker>
</view>
</view>
</view>
</view>
<!-- #ifdef APP-PLUS || MP-WEIXIN -->
<view class="uni-title uni-common-mt uni-common-pl">摄像头位置</view>
<view class="uni-hello-text camera-tips">注意部分 Android 手机下由于系统 ROM 不支持无法生效打开拍摄界面后可操作切换</view>
<view class="uni-list">
<radio-group @change="radioChange">
<label class="uni-list-cell uni-list-cell-pd" v-for="(item, index) in cameraList" :key="item.value">
<radio :value="item.value" :checked="index === cameraIndex">{{item.name}}</radio>
</label>
</radio-group>
</view>
<!-- #endif -->
<template v-if="!src">
<view class="uni-hello-addfile" @tap="chooseVideo">+ 添加视频</view>
</template>
<template v-else>
<video :src="src" class="video"></video>
</template>
</view>
</template>
<script>
var sourceType = [
['camera'],
['album'],
['camera', 'album']
]
export default {
data() {
return {
title: 'chooseVideo',
sourceTypeIndex: 2,
sourceType: ['拍摄', '相册', '拍摄或相册'],
src: '',
cameraList: [{
value: 'back',
name: '后置摄像头',
checked: 'true'
},
{
value: 'front',
name: '前置摄像头'
},
],
cameraIndex: 0
}
},
onUnload() {
this.src = '',
this.sourceTypeIndex = 2,
this.sourceType = ['拍摄', '相册', '拍摄或相册'];
},
methods: {
radioChange(evt) {
for (let i = 0; i < this.cameraList.length; i++) {
if (this.cameraList[i].value === evt.detail.value) {
this.cameraIndex = i;
break;
}
}
},
sourceTypeChange: function(e) {
this.sourceTypeIndex = parseInt(e.detail.value)
},
chooseVideo: function() {
uni.chooseVideo({
camera: this.cameraList[this.cameraIndex].value,
sourceType: sourceType[this.sourceTypeIndex],
success: (res) => {
this.src = res.tempFilePath
},
fail: (err) => {
// #ifdef MP
uni.getSetting({
success: (res) => {
let authStatus = false;
switch (this.sourceTypeIndex) {
case 0:
authStatus = res.authSetting['scope.camera'];
break;
case 1:
authStatus = res.authSetting['scope.album'];
break;
case 2:
authStatus = res.authSetting['scope.album'] && res.authSetting['scope.camera'];
break;
default:
break;
}
if (!authStatus) {
uni.showModal({
title: '授权失败',
content: 'Hello uni-app需要从您的相机或相册获取视频请在设置界面打开相关权限',
success: (res) => {
if (res.confirm) {
uni.openSetting()
}
}
})
}
}
})
// #endif
}
})
}
}
}
</script>
<style>
.video {
width: 100%;
}
.camera-tips {
padding: 10rpx 30rpx;
}
</style>

243
pages/API/voice/voice.vue Normal file
View File

@ -0,0 +1,243 @@
<template>
<view>
<page-head :title="title"></page-head>
<view class="uni-padding-wrap">
<block v-if="!recording && !playing && !hasRecord">
<view class="page-body-time">
<text class="time-big">{{formatedRecordTime}}</text>
</view>
<view class="page-body-buttons">
<view class="page-body-button"></view>
<view class="page-body-button" @click="startRecord">
<image src="../../../static/record.png"></image>
</view>
<view class="page-body-button"></view>
</view>
</block>
<block v-if="recording === true">
<view class="page-body-time">
<text class="time-big">{{formatedRecordTime}}</text>
</view>
<view class="page-body-buttons">
<view class="page-body-button"></view>
<view class="page-body-button" @click="stopRecord">
<view class="button-stop-record"></view>
</view>
<view class="page-body-button"></view>
</view>
</block>
<block v-if="hasRecord === true && playing === false">
<view class="page-body-time">
<text class="time-big">{{formatedPlayTime}}</text>
<text class="time-small">{{formatedRecordTime}}</text>
</view>
<view class="page-body-buttons">
<view class="page-body-button" @click="playVoice">
<image src="../../../static/play.png"></image>
</view>
<view class="page-body-button" @click="clear">
<image src="../../../static/trash.png"></image>
</view>
</view>
</block>
<block v-if="hasRecord === true && playing === true">
<view class="page-body-time">
<text class="time-big">{{formatedPlayTime}}</text>
<text class="time-small">{{formatedRecordTime}}</text>
</view>
<view class="page-body-buttons">
<view class="page-body-button" @click="stopVoice">
<image src="../../../static/stop.png"></image>
</view>
<view class="page-body-button" @click="clear">
<image src="../../../static/trash.png"></image>
</view>
</view>
</block>
</view>
</view>
</template>
<script>
// #ifdef APP-PLUS
import permision from "@/common/permission.js"
// #endif
import * as util from '../../../common/util.js'
var playTimeInterval = null;
var recordTimeInterval = null;
var recorderManager = null;
var music = null;
export default {
data() {
return {
title: 'start/stopRecord、play/stopVoice',
recording: false, //
playing: false, //
hasRecord: false, //
tempFilePath: '',
recordTime: 0,
playTime: 0,
formatedRecordTime: '00:00:00', //
formatedPlayTime: '00:00:00' //
}
},
onUnload: function() {
this.end();
},
onLoad: function() {
music = uni.createInnerAudioContext();
music.onEnded(() => {
clearInterval(playTimeInterval)
var playTime = 0
console.log('play voice finished')
this.playing = false;
this.formatedPlayTime = util.formatTime(playTime);
this.playTime = playTime;
});
recorderManager = uni.getRecorderManager();
recorderManager.onStart(() => {
console.log('recorder start');
this.recording = true;
recordTimeInterval = setInterval(() => {
this.recordTime += 1;
this.formatedRecordTime = util.formatTime(this.recordTime);
}, 1000)
});
recorderManager.onStop((res) => {
console.log('on stop');
music.src = res.tempFilePath;
this.hasRecord = true;
this.recording = false;
});
recorderManager.onError(() => {
console.log('recorder onError');
});
},
methods: {
async startRecord() { //
// #ifdef APP-PLUS
let status = await this.checkPermission();
if (status !== 1) {
return;
}
// #endif
// TODO ios
recorderManager.start({
format: 'mp3'
});
},
stopRecord() { //
recorderManager.stop();
clearInterval(recordTimeInterval);
},
playVoice() {
console.log('play voice');
this.playing = true;
playTimeInterval = setInterval(() => {
this.playTime += 1;
this.formatedPlayTime = util.formatTime(this.playTime);
}, 1000)
music.play();
},
stopVoice() {
clearInterval(playTimeInterval)
this.playing = false;
this.formatedPlayTime = util.formatTime(0);
this.playTime = 0;
music.stop();
},
end() {
music.stop();
recorderManager.stop();
clearInterval(recordTimeInterval)
clearInterval(playTimeInterval);
this.recording = false, this.playing = false, this.hasRecord = false;
this.playTime = 0, this.recordTime = 0;
this.formatedRecordTime = "00:00:00", this.formatedRecordTime = "00:00:00";
},
clear() {
this.end();
}
// #ifdef APP-PLUS
,
async checkPermission() {
let status = permision.isIOS ? await permision.requestIOS('record') :
await permision.requestAndroid('android.permission.RECORD_AUDIO');
if (status === null || status === 1) {
status = 1;
} else if (status === 2) {
uni.showModal({
content: "系统麦克风已关闭",
confirmText: "确定",
showCancel: false,
success: function(res) {
}
})
} else {
uni.showModal({
content: "需要麦克风权限",
confirmText: "设置",
success: function(res) {
if (res.confirm) {
permision.gotoAppSetting();
}
}
})
}
return status;
}
// #endif
}
}
</script>
<style>
image {
width: 150rpx;
height: 150rpx;
}
.page-body-wrapper {
justify-content: space-between;
flex-grow: 1;
margin-bottom: 300rpx;
}
.page-body-time {
display: flex;
flex-direction: column;
align-items: center;
}
.time-big {
font-size: 60rpx;
margin: 20rpx;
}
.time-small {
font-size: 30rpx;
}
.page-body-buttons {
margin-top: 60rpx;
display: flex;
justify-content: space-around;
}
.page-body-button {
width: 250rpx;
text-align: center;
}
.button-stop-record {
width: 110rpx;
height: 110rpx;
border: 20rpx solid #fff;
background-color: #f55c23;
border-radius: 130rpx;
margin: 0 auto;
}
</style>

View File

@ -0,0 +1,160 @@
<template>
<view>
<page-head title="websocket通讯示例"></page-head>
<view class="uni-padding-wrap">
<view class="uni-btn-v">
<view class="websocket-msg">{{showMsg}}</view>
<button type="primary" @click="connect">连接websocket服务</button>
<button v-show="connected" type="primary" @click="send">发送一条消息</button>
<button type="primary" @click="close">断开websocket服务</button>
<view class="websocket-tips">发送消息后会收到一条服务器返回的消息与发送的消息内容一致</view>
</view>
</view>
</view>
</template>
<script>
let platform = uni.getSystemInfoSync().platform
export default {
data() {
return {
connected: false,
connecting: false,
msg: false,
roomId: ''
}
},
computed: {
showMsg() {
if (this.connected) {
if (this.msg) {
return '收到消息:' + this.msg
} else {
return '等待接收消息'
}
} else {
return '尚未连接'
}
}
},
onUnload() {
uni.closeSocket()
uni.hideLoading()
},
methods: {
connect() {
if (this.connected || this.connecting) {
uni.showModal({
content: '正在连接或者已经连接,请勿重复连接',
showCancel: false
})
return false
}
this.connecting = true
uni.showLoading({
title: '连接中...'
})
uni.connectSocket({
url: 'wss://echo.websocket.org',
data() {
return {
msg: 'Hello'
}
},
// #ifdef MP
header: {
'content-type': 'application/json'
},
// #endif
// #ifdef MP-WEIXIN
method: 'GET',
// #endif
success(res) {
//
},
fail(err) {
//
}
})
uni.onSocketOpen((res) => {
this.connecting = false
this.connected = true
uni.hideLoading()
uni.showToast({
icon: 'none',
title: '连接成功'
})
console.log('onOpen', res);
})
uni.onSocketError((err) => {
this.connecting = false
this.connected = false
uni.hideLoading()
uni.showModal({
content: '连接失败可能是websocket服务不可用请稍后再试',
showCancel: false
})
console.log('onError', err);
})
uni.onSocketMessage((res) => {
this.msg = res.data
console.log('onMessage', res)
})
uni.onSocketClose((res) => {
this.connected = false
this.startRecive = false
this.msg = false
console.log('onClose', res)
})
},
send() {
uni.sendSocketMessage({
data: 'from ' + platform + ' : ' + parseInt(Math.random() * 10000).toString(),
success(res) {
console.log(res);
},
fail(err) {
console.log(err);
}
})
},
close() {
uni.closeSocket()
}
}
}
</script>
<style>
.uni-btn-v {
padding: 10rpx 0;
}
.uni-btn-v button {
margin: 20rpx 0;
}
.websocket-room {
height: 40px;
line-height: 40px;
text-align: center;
border-bottom: solid 1px #DDDDDD;
margin-bottom: 20px;
}
.websocket-msg {
padding: 40px 0px;
text-align: center;
font-size: 14px;
line-height: 40px;
color: #666666;
}
.websocket-tips{
padding: 40px 0px;
text-align: center;
font-size: 14px;
line-height: 24px;
color: #666666;
}
</style>

View File

@ -0,0 +1,160 @@
<template>
<view>
<page-head title="websocket通讯示例"></page-head>
<view class="uni-padding-wrap">
<view class="uni-btn-v">
<view class="websocket-msg">{{showMsg}}</view>
<button type="primary" @click="connect">连接websocket服务</button>
<button v-show="connected" type="primary" @click="send">发送一条消息</button>
<button type="primary" @click="close">断开websocket服务</button>
<view class="websocket-tips">发送消息后会收到一条服务器返回的消息与发送的消息内容一致</view>
</view>
</view>
</view>
</template>
<script>
let platform = uni.getSystemInfoSync().platform
export default {
data() {
return {
connected: false,
connecting: false,
socketTask: false,
msg: false,
}
},
computed: {
showMsg() {
if (this.connected) {
if (this.msg) {
return '收到消息:' + this.msg
} else {
return '等待接收消息'
}
} else {
return '尚未连接'
}
}
},
onUnload() {
uni.hideLoading()
if (this.socketTask && this.socketTask.close) {
this.socketTask.close()
}
},
methods: {
connect() {
if (this.connected || this.connecting) {
uni.showModal({
content: '正在连接或者已经连接,请勿重复连接',
showCancel: false
})
return false
}
this.connecting = true
uni.showLoading({
title: '连接中...'
})
this.socketTask = uni.connectSocket({
url: 'wss://echo.websocket.org',
data() {
return {
msg: 'Hello'
}
},
// #ifdef MP
header: {
'content-type': 'application/json'
},
// #endif
// #ifdef MP-WEIXIN
method: 'GET',
// #endif
success(res) {
//
},
fail(err) {
//
}
})
console.log(this.socketTask);
this.socketTask.onOpen((res) => {
this.connecting = false
this.connected = true
uni.hideLoading()
uni.showToast({
icon: 'none',
title: '连接成功'
})
console.log('onOpen', res);
})
this.socketTask.onError((err) => {
this.connecting = false
this.connected = false
uni.hideLoading()
uni.showModal({
content: '连接失败可能是websocket服务不可用请稍后再试',
showCancel: false
})
console.log('onError', err);
})
this.socketTask.onMessage((res) => {
this.msg = res.data
console.log('onMessage', res)
})
this.socketTask.onClose((res) => {
this.connected = false
this.startRecive = false
this.socketTask = false
this.msg = false
console.log('onClose', res)
})
console.log('task', this.socketTask)
},
send() {
this.socketTask.send({
data: 'from ' + platform + ' : ' + parseInt(Math.random() * 10000).toString(),
success(res) {
console.log(res);
},
fail(err) {
console.log(err);
}
})
},
close() {
if (this.socketTask && this.socketTask.close) {
this.socketTask.close()
}
}
}
}
</script>
<style>
.uni-btn-v {
padding: 10rpx 0;
}
.uni-btn-v button {
margin: 20rpx 0;
}
.websocket-msg {
padding: 40px 0px;
text-align: center;
font-size: 14px;
line-height: 40px;
color: #666666;
}
.websocket-tips{
padding: 40px 0px;
text-align: center;
font-size: 14px;
line-height: 24px;
color: #666666;
}
</style>

Some files were not shown because too many files have changed in this diff Show More